Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 351642
b: refs/heads/master
c: 891dc08
h: refs/heads/master
v: v3
  • Loading branch information
Jacob Keller authored and Jeff Kirsher committed Jan 23, 2013
1 parent 1b993db commit 8228276
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 35 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 6cb562d6681155190c52ef7603c559c284eef159
refs/heads/master: 891dc0821d2089afcb04d3cace0a3522093680e7
5 changes: 3 additions & 2 deletions trunk/drivers/net/ethernet/intel/ixgbe/ixgbe.h
Original file line number Diff line number Diff line change
Expand Up @@ -582,6 +582,9 @@ struct ixgbe_adapter {

struct ptp_clock *ptp_clock;
struct ptp_clock_info ptp_caps;
struct work_struct ptp_tx_work;
struct sk_buff *ptp_tx_skb;
unsigned long ptp_tx_start;
unsigned long last_overflow_check;
unsigned long last_rx_ptp_check;
spinlock_t tmreg_lock;
Expand Down Expand Up @@ -752,8 +755,6 @@ extern void ixgbe_ptp_init(struct ixgbe_adapter *adapter);
extern void ixgbe_ptp_stop(struct ixgbe_adapter *adapter);
extern void ixgbe_ptp_overflow_check(struct ixgbe_adapter *adapter);
extern void ixgbe_ptp_rx_hang(struct ixgbe_adapter *adapter);
extern void ixgbe_ptp_tx_hwtstamp(struct ixgbe_q_vector *q_vector,
struct sk_buff *skb);
extern void ixgbe_ptp_rx_hwtstamp(struct ixgbe_ring *rx_ring,
union ixgbe_adv_rx_desc *rx_desc,
struct sk_buff *skb);
Expand Down
16 changes: 10 additions & 6 deletions trunk/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -850,9 +850,6 @@ static bool ixgbe_clean_tx_irq(struct ixgbe_q_vector *q_vector,
total_bytes += tx_buffer->bytecount;
total_packets += tx_buffer->gso_segs;

if (unlikely(tx_buffer->tx_flags & IXGBE_TX_FLAGS_TSTAMP))
ixgbe_ptp_tx_hwtstamp(q_vector, tx_buffer->skb);

/* free the skb */
dev_kfree_skb_any(tx_buffer->skb);

Expand Down Expand Up @@ -5880,16 +5877,18 @@ static void ixgbe_service_task(struct work_struct *work)
struct ixgbe_adapter *adapter = container_of(work,
struct ixgbe_adapter,
service_task);

ixgbe_reset_subtask(adapter);
ixgbe_sfp_detection_subtask(adapter);
ixgbe_sfp_link_config_subtask(adapter);
ixgbe_check_overtemp_subtask(adapter);
ixgbe_watchdog_subtask(adapter);
ixgbe_fdir_reinit_subtask(adapter);
ixgbe_check_hang_subtask(adapter);
ixgbe_ptp_overflow_check(adapter);
ixgbe_ptp_rx_hang(adapter);

if (adapter->flags2 & IXGBE_FLAG2_PTP_ENABLED) {
ixgbe_ptp_overflow_check(adapter);
ixgbe_ptp_rx_hang(adapter);
}

ixgbe_service_event_complete(adapter);
}
Expand Down Expand Up @@ -6435,6 +6434,11 @@ netdev_tx_t ixgbe_xmit_frame_ring(struct sk_buff *skb,
if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP)) {
skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
tx_flags |= IXGBE_TX_FLAGS_TSTAMP;

/* schedule check for Tx timestamp */
adapter->ptp_tx_skb = skb_get(skb);
adapter->ptp_tx_start = jiffies;
schedule_work(&adapter->ptp_tx_work);
}

#ifdef CONFIG_PCI_IOV
Expand Down
78 changes: 52 additions & 26 deletions trunk/drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@
#define IXGBE_MAX_TIMEADJ_VALUE 0x7FFFFFFFFFFFFFFFULL

#define IXGBE_OVERFLOW_PERIOD (HZ * 30)
#define IXGBE_PTP_TX_TIMEOUT (HZ * 15)

#ifndef NSECS_PER_SEC
#define NSECS_PER_SEC 1000000000ULL
Expand Down Expand Up @@ -401,7 +402,6 @@ void ixgbe_ptp_check_pps_event(struct ixgbe_adapter *adapter, u32 eicr)
}
}


/**
* ixgbe_ptp_overflow_check - watchdog task to detect SYSTIME overflow
* @adapter: private adapter struct
Expand All @@ -416,8 +416,7 @@ void ixgbe_ptp_overflow_check(struct ixgbe_adapter *adapter)
IXGBE_OVERFLOW_PERIOD);
struct timespec ts;

if ((adapter->flags2 & IXGBE_FLAG2_PTP_ENABLED) &&
(timeout)) {
if (timeout) {
ixgbe_ptp_gettime(&adapter->ptp_caps, &ts);
adapter->last_overflow_check = jiffies;
}
Expand Down Expand Up @@ -467,48 +466,68 @@ void ixgbe_ptp_rx_hang(struct ixgbe_adapter *adapter)

/**
* ixgbe_ptp_tx_hwtstamp - utility function which checks for TX time stamp
* @q_vector: structure containing interrupt and ring information
* @skb: particular skb to send timestamp with
* @adapter: the private adapter struct
*
* if the timestamp is valid, we convert it into the timecounter ns
* value, then store that result into the shhwtstamps structure which
* is passed up the network stack
*/
void ixgbe_ptp_tx_hwtstamp(struct ixgbe_q_vector *q_vector,
struct sk_buff *skb)
static void ixgbe_ptp_tx_hwtstamp(struct ixgbe_adapter *adapter)
{
struct ixgbe_adapter *adapter;
struct ixgbe_hw *hw;
struct ixgbe_hw *hw = &adapter->hw;
struct skb_shared_hwtstamps shhwtstamps;
u64 regval = 0, ns;
u32 tsynctxctl;
unsigned long flags;

/* we cannot process timestamps on a ring without a q_vector */
if (!q_vector || !q_vector->adapter)
return;

adapter = q_vector->adapter;
hw = &adapter->hw;

tsynctxctl = IXGBE_READ_REG(hw, IXGBE_TSYNCTXCTL);
regval |= (u64)IXGBE_READ_REG(hw, IXGBE_TXSTMPL);
regval |= (u64)IXGBE_READ_REG(hw, IXGBE_TXSTMPH) << 32;

/*
* if TX timestamp is not valid, exit after clearing the
* timestamp registers
*/
if (!(tsynctxctl & IXGBE_TSYNCTXCTL_VALID))
return;

spin_lock_irqsave(&adapter->tmreg_lock, flags);
ns = timecounter_cyc2time(&adapter->tc, regval);
spin_unlock_irqrestore(&adapter->tmreg_lock, flags);

memset(&shhwtstamps, 0, sizeof(shhwtstamps));
shhwtstamps.hwtstamp = ns_to_ktime(ns);
skb_tstamp_tx(skb, &shhwtstamps);
skb_tstamp_tx(adapter->ptp_tx_skb, &shhwtstamps);

dev_kfree_skb_any(adapter->ptp_tx_skb);
adapter->ptp_tx_skb = NULL;
}

/**
* ixgbe_ptp_tx_hwtstamp_work
* @work: pointer to the work struct
*
* This work item polls TSYNCTXCTL valid bit to determine when a Tx hardware
* timestamp has been taken for the current skb. It is necesary, because the
* descriptor's "done" bit does not correlate with the timestamp event.
*/
static void ixgbe_ptp_tx_hwtstamp_work(struct work_struct *work)
{
struct ixgbe_adapter *adapter = container_of(work, struct ixgbe_adapter,
ptp_tx_work);
struct ixgbe_hw *hw = &adapter->hw;
bool timeout = time_is_before_jiffies(adapter->ptp_tx_start +
IXGBE_PTP_TX_TIMEOUT);
u32 tsynctxctl;

/* we have to have a valid skb */
if (!adapter->ptp_tx_skb)
return;

if (timeout) {
dev_kfree_skb_any(adapter->ptp_tx_skb);
adapter->ptp_tx_skb = NULL;
e_warn(drv, "clearing Tx Timestamp hang");
return;
}

tsynctxctl = IXGBE_READ_REG(hw, IXGBE_TSYNCTXCTL);
if (tsynctxctl & IXGBE_TSYNCTXCTL_VALID)
ixgbe_ptp_tx_hwtstamp(adapter);
else
/* reschedule to keep checking if it's not available yet */
schedule_work(&adapter->ptp_tx_work);
}

/**
Expand Down Expand Up @@ -865,6 +884,7 @@ void ixgbe_ptp_init(struct ixgbe_adapter *adapter)
}

spin_lock_init(&adapter->tmreg_lock);
INIT_WORK(&adapter->ptp_tx_work, ixgbe_ptp_tx_hwtstamp_work);

adapter->ptp_clock = ptp_clock_register(&adapter->ptp_caps,
&adapter->pdev->dev);
Expand Down Expand Up @@ -896,6 +916,12 @@ void ixgbe_ptp_stop(struct ixgbe_adapter *adapter)

ixgbe_ptp_setup_sdp(adapter);

cancel_work_sync(&adapter->ptp_tx_work);
if (adapter->ptp_tx_skb) {
dev_kfree_skb_any(adapter->ptp_tx_skb);
adapter->ptp_tx_skb = NULL;
}

if (adapter->ptp_clock) {
ptp_clock_unregister(adapter->ptp_clock);
adapter->ptp_clock = NULL;
Expand Down

0 comments on commit 8228276

Please sign in to comment.