aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexander Duyck <alexander.h.duyck@intel.com>2012-09-25 01:14:55 -0400
committerJeff Kirsher <jeffrey.t.kirsher@intel.com>2012-10-19 07:25:10 -0400
commitb534550a17cda69a1d62acc18fff33370b5eee5b (patch)
treed37ae776186a270a791bbad843123c10659e8589
parentea5ceeabf5621ed36d24e6741b45cfd1e1fce11b (diff)
igb: Split Rx timestamping into two separate functions
In order to support page based receive we will need to split up the two different types of timestamping into two separate functions. The first one will handle legacy timestamps with the value in the register, and the new one will handle timestamps in the Rx buffer itself. Signed-off-by: Alexander Duyck <alexander.h.duyck@intel.com> Acked-by: Matthew Vick <matthew.vick@intel.com> Tested-by: Aaron Brown <aaron.f.brown@intel.com> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
-rw-r--r--drivers/net/ethernet/intel/igb/igb.h17
-rw-r--r--drivers/net/ethernet/intel/igb/igb_ptp.c55
2 files changed, 53 insertions, 19 deletions
diff --git a/drivers/net/ethernet/intel/igb/igb.h b/drivers/net/ethernet/intel/igb/igb.h
index 8aad230c0592..f6a1cd9d72a6 100644
--- a/drivers/net/ethernet/intel/igb/igb.h
+++ b/drivers/net/ethernet/intel/igb/igb.h
@@ -442,9 +442,22 @@ extern void igb_ptp_stop(struct igb_adapter *adapter);
442extern void igb_ptp_reset(struct igb_adapter *adapter); 442extern void igb_ptp_reset(struct igb_adapter *adapter);
443extern void igb_ptp_tx_work(struct work_struct *work); 443extern void igb_ptp_tx_work(struct work_struct *work);
444extern void igb_ptp_tx_hwtstamp(struct igb_adapter *adapter); 444extern void igb_ptp_tx_hwtstamp(struct igb_adapter *adapter);
445extern void igb_ptp_rx_hwtstamp(struct igb_q_vector *q_vector, 445extern void igb_ptp_rx_rgtstamp(struct igb_q_vector *q_vector,
446 union e1000_adv_rx_desc *rx_desc,
447 struct sk_buff *skb); 446 struct sk_buff *skb);
447extern void igb_ptp_rx_pktstamp(struct igb_q_vector *q_vector,
448 unsigned char *va,
449 struct sk_buff *skb);
450static inline void igb_ptp_rx_hwtstamp(struct igb_q_vector *q_vector,
451 union e1000_adv_rx_desc *rx_desc,
452 struct sk_buff *skb)
453{
454 if (igb_test_staterr(rx_desc, E1000_RXDADV_STAT_TSIP)) {
455 igb_ptp_rx_pktstamp(q_vector, skb->data, skb);
456 skb_pull(skb, IGB_TS_HDR_LEN);
457 } else if (igb_test_staterr(rx_desc, E1000_RXDADV_STAT_TS)) {
458 igb_ptp_rx_rgtstamp(q_vector, skb);
459 }
460}
448extern int igb_ptp_hwtstamp_ioctl(struct net_device *netdev, 461extern int igb_ptp_hwtstamp_ioctl(struct net_device *netdev,
449 struct ifreq *ifr, int cmd); 462 struct ifreq *ifr, int cmd);
450#endif /* CONFIG_IGB_PTP */ 463#endif /* CONFIG_IGB_PTP */
diff --git a/drivers/net/ethernet/intel/igb/igb_ptp.c b/drivers/net/ethernet/intel/igb/igb_ptp.c
index ee21445157a3..a7db4cec7a1c 100644
--- a/drivers/net/ethernet/intel/igb/igb_ptp.c
+++ b/drivers/net/ethernet/intel/igb/igb_ptp.c
@@ -441,18 +441,46 @@ void igb_ptp_tx_hwtstamp(struct igb_adapter *adapter)
441 adapter->ptp_tx_skb = NULL; 441 adapter->ptp_tx_skb = NULL;
442} 442}
443 443
444void igb_ptp_rx_hwtstamp(struct igb_q_vector *q_vector, 444/**
445 union e1000_adv_rx_desc *rx_desc, 445 * igb_ptp_rx_pktstamp - retrieve Rx per packet timestamp
446 * @q_vector: Pointer to interrupt specific structure
447 * @va: Pointer to address containing Rx buffer
448 * @skb: Buffer containing timestamp and packet
449 *
450 * This function is meant to retrieve a timestamp from the first buffer of an
451 * incoming frame. The value is stored in little endian format starting on
452 * byte 8.
453 */
454void igb_ptp_rx_pktstamp(struct igb_q_vector *q_vector,
455 unsigned char *va,
456 struct sk_buff *skb)
457{
458 u64 *regval = (u64 *)va;
459
460 /*
461 * The timestamp is recorded in little endian format.
462 * DWORD: 0 1 2 3
463 * Field: Reserved Reserved SYSTIML SYSTIMH
464 */
465 igb_ptp_systim_to_hwtstamp(q_vector->adapter, skb_hwtstamps(skb),
466 le64_to_cpu(regval[1]));
467}
468
469/**
470 * igb_ptp_rx_rgtstamp - retrieve Rx timestamp stored in register
471 * @q_vector: Pointer to interrupt specific structure
472 * @skb: Buffer containing timestamp and packet
473 *
474 * This function is meant to retrieve a timestamp from the internal registers
475 * of the adapter and store it in the skb.
476 */
477void igb_ptp_rx_rgtstamp(struct igb_q_vector *q_vector,
446 struct sk_buff *skb) 478 struct sk_buff *skb)
447{ 479{
448 struct igb_adapter *adapter = q_vector->adapter; 480 struct igb_adapter *adapter = q_vector->adapter;
449 struct e1000_hw *hw = &adapter->hw; 481 struct e1000_hw *hw = &adapter->hw;
450 u64 regval; 482 u64 regval;
451 483
452 if (!igb_test_staterr(rx_desc, E1000_RXDADV_STAT_TSIP |
453 E1000_RXDADV_STAT_TS))
454 return;
455
456 /* 484 /*
457 * If this bit is set, then the RX registers contain the time stamp. No 485 * If this bit is set, then the RX registers contain the time stamp. No
458 * other packet will be time stamped until we read these registers, so 486 * other packet will be time stamped until we read these registers, so
@@ -464,18 +492,11 @@ void igb_ptp_rx_hwtstamp(struct igb_q_vector *q_vector,
464 * If nothing went wrong, then it should have a shared tx_flags that we 492 * If nothing went wrong, then it should have a shared tx_flags that we
465 * can turn into a skb_shared_hwtstamps. 493 * can turn into a skb_shared_hwtstamps.
466 */ 494 */
467 if (igb_test_staterr(rx_desc, E1000_RXDADV_STAT_TSIP)) { 495 if (!(rd32(E1000_TSYNCRXCTL) & E1000_TSYNCRXCTL_VALID))
468 u32 *stamp = (u32 *)skb->data; 496 return;
469 regval = le32_to_cpu(*(stamp + 2));
470 regval |= (u64)le32_to_cpu(*(stamp + 3)) << 32;
471 skb_pull(skb, IGB_TS_HDR_LEN);
472 } else {
473 if (!(rd32(E1000_TSYNCRXCTL) & E1000_TSYNCRXCTL_VALID))
474 return;
475 497
476 regval = rd32(E1000_RXSTMPL); 498 regval = rd32(E1000_RXSTMPL);
477 regval |= (u64)rd32(E1000_RXSTMPH) << 32; 499 regval |= (u64)rd32(E1000_RXSTMPH) << 32;
478 }
479 500
480 igb_ptp_systim_to_hwtstamp(adapter, skb_hwtstamps(skb), regval); 501 igb_ptp_systim_to_hwtstamp(adapter, skb_hwtstamps(skb), regval);
481} 502}