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

Commit c5b9bd5e authored by Alexander Duyck's avatar Alexander Duyck Committed by David S. Miller
Browse files

igb: cleanup some of the code related to hw timestamping



The code for the hw timestamping is a bit bulky and making some of the
functions difficult to read.  In order to clean things up a bit I am moving
the timestamping operations into seperate functions.

Signed-off-by: default avatarAlexander Duyck <alexander.h.duyck@intel.com>
Signed-off-by: default avatarJeff Kirsher <jeffrey.t.kirsher@intel.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 4fc82adf
Loading
Loading
Loading
Loading
+14 −0
Original line number Diff line number Diff line
@@ -66,6 +66,8 @@ extern void igb_rx_fifo_flush_82575(struct e1000_hw *hw);
    E1000_EICR_RX_QUEUE3)

/* Immediate Interrupt Rx (A.K.A. Low Latency Interrupt) */
#define E1000_IMIREXT_SIZE_BP     0x00001000  /* Packet size bypass */
#define E1000_IMIREXT_CTRL_BP     0x00080000  /* Bypass check of ctrl bits */

/* Receive Descriptor - Advanced */
union e1000_adv_rx_desc {
@@ -98,6 +100,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 */

/* Transmit Descriptor - Advanced */
union e1000_adv_tx_desc {
@@ -167,6 +170,17 @@ struct e1000_adv_tx_context_desc {
#define E1000_DCA_TXCTRL_CPUID_SHIFT 24 /* Tx CPUID now in the last byte */
#define E1000_DCA_RXCTRL_CPUID_SHIFT 24 /* Rx CPUID now in the last byte */

/* ETQF register bit definitions */
#define E1000_ETQF_FILTER_ENABLE   (1 << 26)
#define E1000_ETQF_1588            (1 << 30)

/* FTQF register bit definitions */
#define E1000_FTQF_VF_BP               0x00008000
#define E1000_FTQF_1588_TIME_STAMP     0x08000000
#define E1000_FTQF_MASK                0xF0000000
#define E1000_FTQF_MASK_PROTO_BP       0x10000000
#define E1000_FTQF_MASK_SOURCE_PORT_BP 0x80000000

#define E1000_NVM_APME_82575          0x0400
#define MAX_NUM_VFS                   8

+33 −0
Original line number Diff line number Diff line
@@ -435,6 +435,39 @@
/* Flow Control */
#define E1000_FCRTL_XONE 0x80000000     /* Enable XON frame transmission */

#define E1000_TSYNCTXCTL_VALID    0x00000001 /* tx timestamp valid */
#define E1000_TSYNCTXCTL_ENABLED  0x00000010 /* enable tx timestampping */

#define E1000_TSYNCRXCTL_VALID      0x00000001 /* rx timestamp valid */
#define E1000_TSYNCRXCTL_TYPE_MASK  0x0000000E /* rx type mask */
#define E1000_TSYNCRXCTL_TYPE_L2_V2       0x00
#define E1000_TSYNCRXCTL_TYPE_L4_V1       0x02
#define E1000_TSYNCRXCTL_TYPE_L2_L4_V2    0x04
#define E1000_TSYNCRXCTL_TYPE_ALL         0x08
#define E1000_TSYNCRXCTL_TYPE_EVENT_V2    0x0A
#define E1000_TSYNCRXCTL_ENABLED    0x00000010 /* enable rx timestampping */

#define E1000_TSYNCRXCFG_PTP_V1_CTRLT_MASK   0x000000FF
#define E1000_TSYNCRXCFG_PTP_V1_SYNC_MESSAGE       0x00
#define E1000_TSYNCRXCFG_PTP_V1_DELAY_REQ_MESSAGE  0x01
#define E1000_TSYNCRXCFG_PTP_V1_FOLLOWUP_MESSAGE   0x02
#define E1000_TSYNCRXCFG_PTP_V1_DELAY_RESP_MESSAGE 0x03
#define E1000_TSYNCRXCFG_PTP_V1_MANAGEMENT_MESSAGE 0x04

#define E1000_TSYNCRXCFG_PTP_V2_MSGID_MASK               0x00000F00
#define E1000_TSYNCRXCFG_PTP_V2_SYNC_MESSAGE                 0x0000
#define E1000_TSYNCRXCFG_PTP_V2_DELAY_REQ_MESSAGE            0x0100
#define E1000_TSYNCRXCFG_PTP_V2_PATH_DELAY_REQ_MESSAGE       0x0200
#define E1000_TSYNCRXCFG_PTP_V2_PATH_DELAY_RESP_MESSAGE      0x0300
#define E1000_TSYNCRXCFG_PTP_V2_FOLLOWUP_MESSAGE             0x0800
#define E1000_TSYNCRXCFG_PTP_V2_DELAY_RESP_MESSAGE           0x0900
#define E1000_TSYNCRXCFG_PTP_V2_PATH_DELAY_FOLLOWUP_MESSAGE  0x0A00
#define E1000_TSYNCRXCFG_PTP_V2_ANNOUNCE_MESSAGE             0x0B00
#define E1000_TSYNCRXCFG_PTP_V2_SIGNALLING_MESSAGE           0x0C00
#define E1000_TSYNCRXCFG_PTP_V2_MANAGEMENT_MESSAGE           0x0D00

#define E1000_TIMINCA_16NS_SHIFT 24

/* PCI Express Control */
#define E1000_GCR_CMPL_TMOUT_MASK       0x0000F000
#define E1000_GCR_CMPL_TMOUT_10ms       0x00001000
+12 −53
Original line number Diff line number Diff line
@@ -76,59 +76,18 @@
#define E1000_FCRTV    0x02460  /* Flow Control Refresh Timer Value - RW */

/* IEEE 1588 TIMESYNCH */
#define E1000_TSYNCTXCTL 0x0B614
#define E1000_TSYNCTXCTL_VALID (1<<0)
#define E1000_TSYNCTXCTL_ENABLED (1<<4)
#define E1000_TSYNCRXCTL 0x0B620
#define E1000_TSYNCRXCTL_VALID (1<<0)
#define E1000_TSYNCRXCTL_ENABLED (1<<4)
enum {
	E1000_TSYNCRXCTL_TYPE_L2_V2 = 0,
	E1000_TSYNCRXCTL_TYPE_L4_V1 = (1<<1),
	E1000_TSYNCRXCTL_TYPE_L2_L4_V2 = (1<<2),
	E1000_TSYNCRXCTL_TYPE_ALL = (1<<3),
	E1000_TSYNCRXCTL_TYPE_EVENT_V2 = (1<<3) | (1<<1),
};
#define E1000_TSYNCRXCFG 0x05F50
enum {
	E1000_TSYNCRXCFG_PTP_V1_SYNC_MESSAGE = 0<<0,
	E1000_TSYNCRXCFG_PTP_V1_DELAY_REQ_MESSAGE = 1<<0,
	E1000_TSYNCRXCFG_PTP_V1_FOLLOWUP_MESSAGE = 2<<0,
	E1000_TSYNCRXCFG_PTP_V1_DELAY_RESP_MESSAGE = 3<<0,
	E1000_TSYNCRXCFG_PTP_V1_MANAGEMENT_MESSAGE = 4<<0,

	E1000_TSYNCRXCFG_PTP_V2_SYNC_MESSAGE = 0<<8,
	E1000_TSYNCRXCFG_PTP_V2_DELAY_REQ_MESSAGE = 1<<8,
	E1000_TSYNCRXCFG_PTP_V2_PATH_DELAY_REQ_MESSAGE = 2<<8,
	E1000_TSYNCRXCFG_PTP_V2_PATH_DELAY_RESP_MESSAGE = 3<<8,
	E1000_TSYNCRXCFG_PTP_V2_FOLLOWUP_MESSAGE = 8<<8,
	E1000_TSYNCRXCFG_PTP_V2_DELAY_RESP_MESSAGE = 9<<8,
	E1000_TSYNCRXCFG_PTP_V2_PATH_DELAY_FOLLOWUP_MESSAGE = 0xA<<8,
	E1000_TSYNCRXCFG_PTP_V2_ANNOUNCE_MESSAGE = 0xB<<8,
	E1000_TSYNCRXCFG_PTP_V2_SIGNALLING_MESSAGE = 0xC<<8,
	E1000_TSYNCRXCFG_PTP_V2_MANAGEMENT_MESSAGE = 0xD<<8,
};
#define E1000_SYSTIML 0x0B600
#define E1000_SYSTIMH 0x0B604
#define E1000_TIMINCA 0x0B608

#define E1000_RXMTRL     0x0B634
#define E1000_RXSTMPL 0x0B624
#define E1000_RXSTMPH 0x0B628
#define E1000_RXSATRL 0x0B62C
#define E1000_RXSATRH 0x0B630

#define E1000_TXSTMPL 0x0B618
#define E1000_TXSTMPH 0x0B61C

#define E1000_ETQF0   0x05CB0
#define E1000_ETQF1   0x05CB4
#define E1000_ETQF2   0x05CB8
#define E1000_ETQF3   0x05CBC
#define E1000_ETQF4   0x05CC0
#define E1000_ETQF5   0x05CC4
#define E1000_ETQF6   0x05CC8
#define E1000_ETQF7   0x05CCC
#define E1000_TSYNCRXCTL 0x0B620 /* Rx Time Sync Control register - RW */
#define E1000_TSYNCTXCTL 0x0B614 /* Tx Time Sync Control register - RW */
#define E1000_TSYNCRXCFG 0x05F50 /* Time Sync Rx Configuration - RW */
#define E1000_RXSTMPL    0x0B624 /* Rx timestamp Low - RO */
#define E1000_RXSTMPH    0x0B628 /* Rx timestamp High - RO */
#define E1000_RXSATRL    0x0B62C /* Rx timestamp attribute low - RO */
#define E1000_RXSATRH    0x0B630 /* Rx timestamp attribute high - RO */
#define E1000_TXSTMPL    0x0B618 /* Tx timestamp value Low - RO */
#define E1000_TXSTMPH    0x0B61C /* Tx timestamp value High - RO */
#define E1000_SYSTIML    0x0B600 /* System time register Low - RO */
#define E1000_SYSTIMH    0x0B604 /* System time register High - RO */
#define E1000_TIMINCA    0x0B608 /* Increment attributes register - RW */

/* Filtering Registers */
#define E1000_SAQF(_n) (0x5980 + 4 * (_n))
+1 −0
Original line number Diff line number Diff line
@@ -323,6 +323,7 @@ struct igb_adapter {
#define IGB_FLAG_QUAD_PORT_A       (1 << 2)
#define IGB_FLAG_QUEUE_PAIRS       (1 << 3)

#define IGB_82576_TSYNC_SHIFT 19
enum e1000_state_t {
	__IGB_TESTING,
	__IGB_RESETTING,
+182 −215
Original line number Diff line number Diff line
@@ -219,38 +219,6 @@ MODULE_DESCRIPTION("Intel(R) Gigabit Ethernet Network Driver");
MODULE_LICENSE("GPL");
MODULE_VERSION(DRV_VERSION);

/**
 * Scale the NIC clock cycle by a large factor so that
 * relatively small clock corrections can be added or
 * substracted at each clock tick. The drawbacks of a
 * large factor are a) that the clock register overflows
 * more quickly (not such a big deal) and b) that the
 * increment per tick has to fit into 24 bits.
 *
 * Note that
 *   TIMINCA = IGB_TSYNC_CYCLE_TIME_IN_NANOSECONDS *
 *             IGB_TSYNC_SCALE
 *   TIMINCA += TIMINCA * adjustment [ppm] / 1e9
 *
 * The base scale factor is intentionally a power of two
 * so that the division in %struct timecounter can be done with
 * a shift.
 */
#define IGB_TSYNC_SHIFT (19)
#define IGB_TSYNC_SCALE (1<<IGB_TSYNC_SHIFT)

/**
 * The duration of one clock cycle of the NIC.
 *
 * @todo This hard-coded value is part of the specification and might change
 * in future hardware revisions. Add revision check.
 */
#define IGB_TSYNC_CYCLE_TIME_IN_NANOSECONDS 16

#if (IGB_TSYNC_SCALE * IGB_TSYNC_CYCLE_TIME_IN_NANOSECONDS) >= (1<<24)
# error IGB_TSYNC_SCALE and/or IGB_TSYNC_CYCLE_TIME_IN_NANOSECONDS are too large to fit into TIMINCA
#endif

/**
 * igb_read_clock - read raw cycle counter (to be used by time counter)
 */
@@ -259,11 +227,11 @@ static cycle_t igb_read_clock(const struct cyclecounter *tc)
	struct igb_adapter *adapter =
		container_of(tc, struct igb_adapter, cycles);
	struct e1000_hw *hw = &adapter->hw;
	u64 stamp;

	stamp =  rd32(E1000_SYSTIML);
	stamp |= (u64)rd32(E1000_SYSTIMH) << 32ULL;
	u64 stamp = 0;
	int shift = 0;

	stamp |= (u64)rd32(E1000_SYSTIML) << shift;
	stamp |= (u64)rd32(E1000_SYSTIMH) << (shift + 32);
	return stamp;
}

@@ -1669,8 +1637,11 @@ static int __devinit igb_probe(struct pci_dev *pdev,
		dev_info(&pdev->dev, "DCA enabled\n");
		igb_setup_dca(adapter);
	}

#endif

	switch (hw->mac.type) {
	case e1000_82576:
		/*
		 * Initialize hardware timer: we keep it running just in case
		 * that some program needs it later on.
@@ -1679,28 +1650,28 @@ static int __devinit igb_probe(struct pci_dev *pdev,
		adapter->cycles.read = igb_read_clock;
		adapter->cycles.mask = CLOCKSOURCE_MASK(64);
		adapter->cycles.mult = 1;
	adapter->cycles.shift = IGB_TSYNC_SHIFT;
	wr32(E1000_TIMINCA,
	     (1<<24) |
	     IGB_TSYNC_CYCLE_TIME_IN_NANOSECONDS * IGB_TSYNC_SCALE);
#if 0
	/*
	 * Avoid rollover while we initialize by resetting the time counter.
	 */
	wr32(E1000_SYSTIML, 0x00000000);
	wr32(E1000_SYSTIMH, 0x00000000);
#else
	/*
	 * Set registers so that rollover occurs soon to test this.
		/**
		 * Scale the NIC clock cycle by a large factor so that
		 * relatively small clock corrections can be added or
		 * substracted at each clock tick. The drawbacks of a large
		 * factor are a) that the clock register overflows more quickly
		 * (not such a big deal) and b) that the increment per tick has
		 * to fit into 24 bits.  As a result we need to use a shift of
		 * 19 so we can fit a value of 16 into the TIMINCA register.
		 */
		adapter->cycles.shift = IGB_82576_TSYNC_SHIFT;
		wr32(E1000_TIMINCA,
		                (1 << E1000_TIMINCA_16NS_SHIFT) |
		                (16 << IGB_82576_TSYNC_SHIFT));

		/* Set registers so that rollover occurs soon to test this. */
		wr32(E1000_SYSTIML, 0x00000000);
		wr32(E1000_SYSTIMH, 0xFF800000);
#endif
		wrfl();

		timecounter_init(&adapter->clock,
				 &adapter->cycles,
				 ktime_to_ns(ktime_get_real()));

		/*
		 * Synchronize our NIC clock against system wall clock. NIC
		 * time stamp reading requires ~3us per sample, each sample
@@ -1712,16 +1683,12 @@ static int __devinit igb_probe(struct pci_dev *pdev,
		adapter->compare.target = ktime_get_real;
		adapter->compare.num_samples = 10;
		timecompare_update(&adapter->compare, 0);

#ifdef DEBUG
	{
		char buffer[160];
		printk(KERN_DEBUG
			"igb: %s: hw %p initialized timer\n",
			igb_get_time_str(adapter, buffer),
			&adapter->hw);
		break;
	case e1000_82575:
		/* 82575 does not support timesync */
	default:
		break;
	}
#endif

	dev_info(&pdev->dev, "Intel(R) Gigabit Ethernet Network Connection\n");
	/* print bus type/speed/width info */
@@ -3596,7 +3563,7 @@ netdev_tx_t igb_xmit_frame_ring_adv(struct sk_buff *skb,
	u8 hdr_len = 0;
	int count = 0;
	int tso = 0;
	union skb_shared_tx *shtx;
	union skb_shared_tx *shtx = skb_tx(skb);

	/* need: 1 descriptor per page,
	 *       + 2 desc gap to keep tail from touching head,
@@ -3608,16 +3575,6 @@ netdev_tx_t igb_xmit_frame_ring_adv(struct sk_buff *skb,
		return NETDEV_TX_BUSY;
	}

	/*
	 * TODO: check that there currently is no other packet with
	 * time stamping in the queue
	 *
	 * When doing time stamping, keep the connection to the socket
	 * a while longer: it is still needed by skb_hwtstamp_tx(),
	 * called either in igb_tx_hwtstamp() or by our caller when
	 * doing software time stamping.
	 */
	shtx = skb_tx(skb);
	if (unlikely(shtx->hardware)) {
		shtx->in_progress = 1;
		tx_flags |= IGB_TX_FLAGS_TSTAMP;
@@ -4633,38 +4590,55 @@ static int igb_poll(struct napi_struct *napi, int budget)
}

/**
 * igb_hwtstamp - utility function which checks for TX time stamp
 * igb_systim_to_hwtstamp - convert system time value to hw timestamp
 * @adapter: board private structure
 * @shhwtstamps: timestamp structure to update
 * @regval: unsigned 64bit system time value.
 *
 * We need to convert the system time value stored in the RX/TXSTMP registers
 * into a hwtstamp which can be used by the upper level timestamping functions
 */
static void igb_systim_to_hwtstamp(struct igb_adapter *adapter,
                                   struct skb_shared_hwtstamps *shhwtstamps,
                                   u64 regval)
{
	u64 ns;

	ns = timecounter_cyc2time(&adapter->clock, regval);
	timecompare_update(&adapter->compare, ns);
	memset(shhwtstamps, 0, sizeof(struct skb_shared_hwtstamps));
	shhwtstamps->hwtstamp = ns_to_ktime(ns);
	shhwtstamps->syststamp = timecompare_transform(&adapter->compare, ns);
}

/**
 * igb_tx_hwtstamp - utility function which checks for TX time stamp
 * @q_vector: pointer to q_vector containing needed info
 * @skb: packet that was just sent
 *
 * If we were asked to do hardware stamping and such a time stamp is
 * available, then it must have been for this skb here because we only
 * allow only one such packet into the queue.
 */
static void igb_tx_hwtstamp(struct igb_adapter *adapter, struct sk_buff *skb)
static void igb_tx_hwtstamp(struct igb_q_vector *q_vector, struct sk_buff *skb)
{
	struct igb_adapter *adapter = q_vector->adapter;
	union skb_shared_tx *shtx = skb_tx(skb);
	struct e1000_hw *hw = &adapter->hw;

	if (unlikely(shtx->hardware)) {
		u32 valid = rd32(E1000_TSYNCTXCTL) & E1000_TSYNCTXCTL_VALID;
		if (valid) {
			u64 regval = rd32(E1000_TXSTMPL);
			u64 ns;
	struct skb_shared_hwtstamps shhwtstamps;
	u64 regval;

			memset(&shhwtstamps, 0, sizeof(shhwtstamps));
	/* if skb does not support hw timestamp or TX stamp not valid exit */
	if (likely(!shtx->hardware) ||
	    !(rd32(E1000_TSYNCTXCTL) & E1000_TSYNCTXCTL_VALID))
		return;

	regval = rd32(E1000_TXSTMPL);
	regval |= (u64)rd32(E1000_TXSTMPH) << 32;
			ns = timecounter_cyc2time(&adapter->clock,
						  regval);
			timecompare_update(&adapter->compare, ns);
			shhwtstamps.hwtstamp = ns_to_ktime(ns);
			shhwtstamps.syststamp =
				timecompare_transform(&adapter->compare, ns);

	igb_systim_to_hwtstamp(adapter, &shhwtstamps, regval);
	skb_tstamp_tx(skb, &shhwtstamps);
}
	}
}

/**
 * igb_clean_tx_irq - Reclaim resources after transmit completes
@@ -4706,7 +4680,7 @@ static bool igb_clean_tx_irq(struct igb_q_vector *q_vector)
				total_packets += segs;
				total_bytes += bytecount;

				igb_tx_hwtstamp(adapter, skb);
				igb_tx_hwtstamp(q_vector, skb);
			}

			igb_unmap_and_free_tx_resource(tx_ring, buffer_info);
@@ -4831,6 +4805,34 @@ 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,
                                   struct sk_buff *skb)
{
	struct igb_adapter *adapter = q_vector->adapter;
	struct e1000_hw *hw = &adapter->hw;
	u64 regval;

	/*
	 * If this bit is set, then the RX registers contain the time stamp. No
	 * other packet will be time stamped until we read these registers, so
	 * read the registers to make them available again. Because only one
	 * packet can be time stamped at a time, we know that the register
	 * values must belong to this one here and therefore we don't need to
	 * compare any of the additional attributes stored for it.
	 *
	 * 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 (!(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);
}
static inline u16 igb_get_hlen(struct igb_ring *rx_ring,
                               union e1000_adv_rx_desc *rx_desc)
{
@@ -4848,10 +4850,8 @@ static inline u16 igb_get_hlen(struct igb_ring *rx_ring,
static bool igb_clean_rx_irq_adv(struct igb_q_vector *q_vector,
                                 int *work_done, int budget)
{
	struct igb_adapter *adapter = q_vector->adapter;
	struct igb_ring *rx_ring = q_vector->rx_ring;
	struct net_device *netdev = rx_ring->netdev;
	struct e1000_hw *hw = &adapter->hw;
	struct pci_dev *pdev = rx_ring->pdev;
	union e1000_adv_rx_desc *rx_desc , *next_rxd;
	struct igb_buffer *buffer_info , *next_buffer;
@@ -4930,52 +4930,12 @@ static bool igb_clean_rx_irq_adv(struct igb_q_vector *q_vector,
			goto next_desc;
		}
send_up:
		/*
		 * If this bit is set, then the RX registers contain
		 * the time stamp. No other packet will be time
		 * stamped until we read these registers, so read the
		 * registers to make them available again. Because
		 * only one packet can be time stamped at a time, we
		 * know that the register values must belong to this
		 * one here and therefore we don't need to compare
		 * any of the additional attributes stored for it.
		 *
		 * If nothing went wrong, then it should have a
		 * skb_shared_tx that we can turn into a
		 * skb_shared_hwtstamps.
		 *
		 * TODO: can time stamping be triggered (thus locking
		 * the registers) without the packet reaching this point
		 * here? In that case RX time stamping would get stuck.
		 *
		 * TODO: in "time stamp all packets" mode this bit is
		 * not set. Need a global flag for this mode and then
		 * always read the registers. Cannot be done without
		 * a race condition.
		 */
		if (unlikely(staterr & E1000_RXD_STAT_TS)) {
			u64 regval;
			u64 ns;
			struct skb_shared_hwtstamps *shhwtstamps =
				skb_hwtstamps(skb);

			WARN(!(rd32(E1000_TSYNCRXCTL) & E1000_TSYNCRXCTL_VALID),
			     "igb: no RX time stamp available for time stamped packet");
			regval = rd32(E1000_RXSTMPL);
			regval |= (u64)rd32(E1000_RXSTMPH) << 32;
			ns = timecounter_cyc2time(&adapter->clock, regval);
			timecompare_update(&adapter->compare, ns);
			memset(shhwtstamps, 0, sizeof(*shhwtstamps));
			shhwtstamps->hwtstamp = ns_to_ktime(ns);
			shhwtstamps->syststamp =
				timecompare_transform(&adapter->compare, ns);
		}

		if (staterr & E1000_RXDEXT_ERR_FRAME_ERR_MASK) {
			dev_kfree_skb_irq(skb);
			goto next_desc;
		}

		igb_rx_hwtstamp(q_vector, staterr, skb);
		total_bytes += skb->len;
		total_packets++;

@@ -5161,13 +5121,11 @@ static int igb_hwtstamp_ioctl(struct net_device *netdev,
	struct igb_adapter *adapter = netdev_priv(netdev);
	struct e1000_hw *hw = &adapter->hw;
	struct hwtstamp_config config;
	u32 tsync_tx_ctl_bit = E1000_TSYNCTXCTL_ENABLED;
	u32 tsync_rx_ctl_bit = E1000_TSYNCRXCTL_ENABLED;
	u32 tsync_rx_ctl_type = 0;
	u32 tsync_tx_ctl = E1000_TSYNCTXCTL_ENABLED;
	u32 tsync_rx_ctl = E1000_TSYNCRXCTL_ENABLED;
	u32 tsync_rx_cfg = 0;
	int is_l4 = 0;
	int is_l2 = 0;
	short port = 319; /* PTP */
	bool is_l4 = false;
	bool is_l2 = false;
	u32 regval;

	if (copy_from_user(&config, ifr->ifr_data, sizeof(config)))
@@ -5179,10 +5137,8 @@ static int igb_hwtstamp_ioctl(struct net_device *netdev,

	switch (config.tx_type) {
	case HWTSTAMP_TX_OFF:
		tsync_tx_ctl_bit = 0;
		break;
		tsync_tx_ctl = 0;
	case HWTSTAMP_TX_ON:
		tsync_tx_ctl_bit = E1000_TSYNCTXCTL_ENABLED;
		break;
	default:
		return -ERANGE;
@@ -5190,7 +5146,7 @@ static int igb_hwtstamp_ioctl(struct net_device *netdev,

	switch (config.rx_filter) {
	case HWTSTAMP_FILTER_NONE:
		tsync_rx_ctl_bit = 0;
		tsync_rx_ctl = 0;
		break;
	case HWTSTAMP_FILTER_PTP_V1_L4_EVENT:
	case HWTSTAMP_FILTER_PTP_V2_L4_EVENT:
@@ -5201,86 +5157,97 @@ static int igb_hwtstamp_ioctl(struct net_device *netdev,
		 * possible to time stamp both Sync and Delay_Req messages
		 * => fall back to time stamping all packets
		 */
		tsync_rx_ctl_type = E1000_TSYNCRXCTL_TYPE_ALL;
		tsync_rx_ctl |= E1000_TSYNCRXCTL_TYPE_ALL;
		config.rx_filter = HWTSTAMP_FILTER_ALL;
		break;
	case HWTSTAMP_FILTER_PTP_V1_L4_SYNC:
		tsync_rx_ctl_type = E1000_TSYNCRXCTL_TYPE_L4_V1;
		tsync_rx_ctl |= E1000_TSYNCRXCTL_TYPE_L4_V1;
		tsync_rx_cfg = E1000_TSYNCRXCFG_PTP_V1_SYNC_MESSAGE;
		is_l4 = 1;
		is_l4 = true;
		break;
	case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ:
		tsync_rx_ctl_type = E1000_TSYNCRXCTL_TYPE_L4_V1;
		tsync_rx_ctl |= E1000_TSYNCRXCTL_TYPE_L4_V1;
		tsync_rx_cfg = E1000_TSYNCRXCFG_PTP_V1_DELAY_REQ_MESSAGE;
		is_l4 = 1;
		is_l4 = true;
		break;
	case HWTSTAMP_FILTER_PTP_V2_L2_SYNC:
	case HWTSTAMP_FILTER_PTP_V2_L4_SYNC:
		tsync_rx_ctl_type = E1000_TSYNCRXCTL_TYPE_L2_L4_V2;
		tsync_rx_ctl |= E1000_TSYNCRXCTL_TYPE_L2_L4_V2;
		tsync_rx_cfg = E1000_TSYNCRXCFG_PTP_V2_SYNC_MESSAGE;
		is_l2 = 1;
		is_l4 = 1;
		is_l2 = true;
		is_l4 = true;
		config.rx_filter = HWTSTAMP_FILTER_SOME;
		break;
	case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ:
	case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ:
		tsync_rx_ctl_type = E1000_TSYNCRXCTL_TYPE_L2_L4_V2;
		tsync_rx_ctl |= E1000_TSYNCRXCTL_TYPE_L2_L4_V2;
		tsync_rx_cfg = E1000_TSYNCRXCFG_PTP_V2_DELAY_REQ_MESSAGE;
		is_l2 = 1;
		is_l4 = 1;
		is_l2 = true;
		is_l4 = true;
		config.rx_filter = HWTSTAMP_FILTER_SOME;
		break;
	case HWTSTAMP_FILTER_PTP_V2_EVENT:
	case HWTSTAMP_FILTER_PTP_V2_SYNC:
	case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ:
		tsync_rx_ctl_type = E1000_TSYNCRXCTL_TYPE_EVENT_V2;
		tsync_rx_ctl |= E1000_TSYNCRXCTL_TYPE_EVENT_V2;
		config.rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT;
		is_l2 = 1;
		is_l2 = true;
		break;
	default:
		return -ERANGE;
	}

	if (hw->mac.type == e1000_82575) {
		if (tsync_rx_ctl | tsync_tx_ctl)
			return -EINVAL;
		return 0;
	}

	/* enable/disable TX */
	regval = rd32(E1000_TSYNCTXCTL);
	regval = (regval & ~E1000_TSYNCTXCTL_ENABLED) | tsync_tx_ctl_bit;
	regval &= ~E1000_TSYNCTXCTL_ENABLED;
	regval |= tsync_tx_ctl;
	wr32(E1000_TSYNCTXCTL, regval);

	/* enable/disable RX, define which PTP packets are time stamped */
	/* enable/disable RX */
	regval = rd32(E1000_TSYNCRXCTL);
	regval = (regval & ~E1000_TSYNCRXCTL_ENABLED) | tsync_rx_ctl_bit;
	regval = (regval & ~0xE) | tsync_rx_ctl_type;
	regval &= ~(E1000_TSYNCRXCTL_ENABLED | E1000_TSYNCRXCTL_TYPE_MASK);
	regval |= tsync_rx_ctl;
	wr32(E1000_TSYNCRXCTL, regval);
	wr32(E1000_TSYNCRXCFG, tsync_rx_cfg);

	/*
	 * Ethertype Filter Queue Filter[0][15:0] = 0x88F7
	 *                                          (Ethertype to filter on)
	 * Ethertype Filter Queue Filter[0][26] = 0x1 (Enable filter)
	 * Ethertype Filter Queue Filter[0][30] = 0x1 (Enable Timestamping)
	 */
	wr32(E1000_ETQF0, is_l2 ? 0x440088f7 : 0);

	/* L4 Queue Filter[0]: only filter by source and destination port */
	wr32(E1000_SPQF0, htons(port));
	wr32(E1000_IMIREXT(0), is_l4 ?
	     ((1<<12) | (1<<19) /* bypass size and control flags */) : 0);
	wr32(E1000_IMIR(0), is_l4 ?
	     (htons(port)
	      | (0<<16) /* immediate interrupt disabled */
	      | 0 /* (1<<17) bit cleared: do not bypass
		     destination port check */)
		: 0);
	wr32(E1000_FTQF0, is_l4 ?
	     (0x11 /* UDP */
	      | (1<<15) /* VF not compared */
	      | (1<<27) /* Enable Timestamping */
	      | (7<<28) /* only source port filter enabled,
			   source/target address and protocol
			   masked */)
	     : ((1<<15) | (15<<28) /* all mask bits set = filter not
				      enabled */));
	/* define which PTP packets are time stamped */
	wr32(E1000_TSYNCRXCFG, tsync_rx_cfg);

	/* define ethertype filter for timestamped packets */
	if (is_l2)
		wr32(E1000_ETQF(3),
		                (E1000_ETQF_FILTER_ENABLE | /* enable filter */
		                 E1000_ETQF_1588 | /* enable timestamping */
		                 ETH_P_1588));     /* 1588 eth protocol type */
	else
		wr32(E1000_ETQF(3), 0);

#define PTP_PORT 319
	/* L4 Queue Filter[3]: filter by destination port and protocol */
	if (is_l4) {
		u32 ftqf = (IPPROTO_UDP /* UDP */
			| E1000_FTQF_VF_BP /* VF not compared */
			| E1000_FTQF_1588_TIME_STAMP /* Enable Timestamping */
			| E1000_FTQF_MASK); /* mask all inputs */
		ftqf &= ~E1000_FTQF_MASK_PROTO_BP; /* enable protocol check */

		wr32(E1000_IMIR(3), htons(PTP_PORT));
		wr32(E1000_IMIREXT(3),
		     (E1000_IMIREXT_SIZE_BP | E1000_IMIREXT_CTRL_BP));
		if (hw->mac.type == e1000_82576) {
			/* enable source port check */
			wr32(E1000_SPQF(3), htons(PTP_PORT));
			ftqf &= ~E1000_FTQF_MASK_SOURCE_PORT_BP;
		}
		wr32(E1000_FTQF(3), ftqf);
	} else {
		wr32(E1000_FTQF(3), E1000_FTQF_MASK);
	}
	wrfl();

	adapter->hwtstamp_config = config;