Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 757b77e2 authored by Nick Nunley's avatar Nick Nunley Committed by David S. Miller
Browse files

igb: add per-packet timestamping



This patch adds support for per-packet timestamping for the
82580 adapter. The rx timestamp code is also pulled out of the
inlined rx hotpath and instead moved to a seperate function.

This version adds a comment explaining the per-packet timestamping
code added to igb_hwtstamp_ioctl().

Signed-off-by: default avatarNicholas Nunley <nicholasx.d.nunley@intel.com>
Signed-off-by: default avatarJeff Kirsher <jeffrey.t.kirsher@intel.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 3365a293
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -53,6 +53,7 @@ extern void igb_rx_fifo_flush_82575(struct e1000_hw *hw);
#define E1000_SRRCTL_DESCTYPE_ADV_ONEBUF                0x02000000
#define E1000_SRRCTL_DESCTYPE_HDR_SPLIT_ALWAYS          0x0A000000
#define E1000_SRRCTL_DROP_EN                            0x80000000
#define E1000_SRRCTL_TIMESTAMP                          0x40000000

#define E1000_MRQC_ENABLE_RSS_4Q            0x00000002
#define E1000_MRQC_ENABLE_VMDQ              0x00000003
@@ -109,6 +110,7 @@ union e1000_adv_rx_desc {
#define E1000_RXDADV_HDRBUFLEN_MASK      0x7FE0
#define E1000_RXDADV_HDRBUFLEN_SHIFT     5
#define E1000_RXDADV_STAT_TS             0x10000 /* Pkt was time stamped */
#define E1000_RXDADV_STAT_TSIP           0x08000 /* timestamp in packet */

/* Transmit Descriptor - Advanced */
union e1000_adv_tx_desc {
+2 −0
Original line number Diff line number Diff line
@@ -107,6 +107,7 @@ struct vf_data_storage {
#define MAXIMUM_ETHERNET_VLAN_SIZE 1522

/* Supported Rx Buffer Sizes */
#define IGB_RXBUFFER_64    64     /* Used for packet split */
#define IGB_RXBUFFER_128   128    /* Used for packet split */
#define IGB_RXBUFFER_1024  1024
#define IGB_RXBUFFER_2048  2048
@@ -324,6 +325,7 @@ struct igb_adapter {

#define IGB_82576_TSYNC_SHIFT 19
#define IGB_82580_TSYNC_SHIFT 24
#define IGB_TS_HDR_LEN        16
enum e1000_state_t {
	__IGB_TESTING,
	__IGB_RESETTING,
+37 −8
Original line number Diff line number Diff line
@@ -2576,6 +2576,8 @@ void igb_configure_rx_ring(struct igb_adapter *adapter,
		         E1000_SRRCTL_BSIZEPKT_SHIFT;
		srrctl |= E1000_SRRCTL_DESCTYPE_ADV_ONEBUF;
	}
	if (hw->mac.type == e1000_82580)
		srrctl |= E1000_SRRCTL_TIMESTAMP;
	/* Only set Drop Enable if we are supporting multiple queues */
	if (adapter->vfs_allocated_count || adapter->num_rx_queues > 1)
		srrctl |= E1000_SRRCTL_DROP_EN;
@@ -3910,6 +3912,9 @@ static int igb_change_mtu(struct net_device *netdev, int new_mtu)
	 * i.e. RXBUFFER_2048 --> size-4096 slab
	 */

	if (adapter->hw.mac.type == e1000_82580)
		max_frame += IGB_TS_HDR_LEN;

	if (max_frame <= IGB_RXBUFFER_1024)
		rx_buffer_len = IGB_RXBUFFER_1024;
	else if (max_frame <= MAXIMUM_ETHERNET_VLAN_SIZE)
@@ -3917,6 +3922,14 @@ static int igb_change_mtu(struct net_device *netdev, int new_mtu)
	else
		rx_buffer_len = IGB_RXBUFFER_128;

	if ((max_frame == ETH_FRAME_LEN + ETH_FCS_LEN + IGB_TS_HDR_LEN) ||
	     (max_frame == MAXIMUM_ETHERNET_VLAN_SIZE + IGB_TS_HDR_LEN))
		rx_buffer_len = MAXIMUM_ETHERNET_VLAN_SIZE + IGB_TS_HDR_LEN;

	if ((adapter->hw.mac.type == e1000_82580) &&
	    (rx_buffer_len == IGB_RXBUFFER_128))
		rx_buffer_len += IGB_RXBUFFER_64;

	if (netif_running(netdev))
		igb_down(adapter);

@@ -5133,7 +5146,7 @@ static inline void igb_rx_checksum_adv(struct igb_ring *ring,
	dev_dbg(&ring->pdev->dev, "cksum success: bits %08X\n", status_err);
}

static inline void igb_rx_hwtstamp(struct igb_q_vector *q_vector, u32 staterr,
static void igb_rx_hwtstamp(struct igb_q_vector *q_vector, u32 staterr,
                                   struct sk_buff *skb)
{
	struct igb_adapter *adapter = q_vector->adapter;
@@ -5151,13 +5164,18 @@ static inline void igb_rx_hwtstamp(struct igb_q_vector *q_vector, u32 staterr,
	 * If nothing went wrong, then it should have a skb_shared_tx that we
	 * can turn into a skb_shared_hwtstamps.
	 */
	if (likely(!(staterr & E1000_RXDADV_STAT_TS)))
		return;
	if (staterr & E1000_RXDADV_STAT_TSIP) {
		u32 *stamp = (u32 *)skb->data;
		regval = le32_to_cpu(*(stamp + 2));
		regval |= (u64)le32_to_cpu(*(stamp + 3)) << 32;
		skb_pull(skb, IGB_TS_HDR_LEN);
	} else {
		if(!(rd32(E1000_TSYNCRXCTL) & E1000_TSYNCRXCTL_VALID))
			return;

		regval = rd32(E1000_RXSTMPL);
		regval |= (u64)rd32(E1000_RXSTMPH) << 32;
	}

	igb_systim_to_hwtstamp(adapter, skb_hwtstamps(skb), regval);
}
@@ -5265,6 +5283,7 @@ static bool igb_clean_rx_irq_adv(struct igb_q_vector *q_vector,
			goto next_desc;
		}

		if (staterr & (E1000_RXDADV_STAT_TSIP | E1000_RXDADV_STAT_TS))
			igb_rx_hwtstamp(q_vector, staterr, skb);
		total_bytes += skb->len;
		total_packets++;
@@ -5545,6 +5564,16 @@ static int igb_hwtstamp_ioctl(struct net_device *netdev,
		return 0;
	}

	/*
	 * Per-packet timestamping only works if all packets are
	 * timestamped, so enable timestamping in all packets as
	 * long as one rx filter was configured.
	 */
	if ((hw->mac.type == e1000_82580) && tsync_rx_ctl) {
		tsync_rx_ctl = E1000_TSYNCRXCTL_ENABLED;
		tsync_rx_ctl |= E1000_TSYNCRXCTL_TYPE_ALL;
	}

	/* enable/disable TX */
	regval = rd32(E1000_TSYNCTXCTL);
	regval &= ~E1000_TSYNCTXCTL_ENABLED;