Commit 3b076cfe authored by David S. Miller's avatar David S. Miller
Browse files


Jeff Kirsher says:

====================
Intel Wired LAN Driver Fixes 2018-12-12

This series contains fixes to i40e and ixgbe.

Stefan Assmann fixes an issue created by a previous fix, where
ether_addr_copy() was moved to avoid a race but did not take into
account that it alters the MAC address being handed to
i40e_del_mac_filter().

Michał Mirosław provides 2 fixes for i40e, first resolves issues in the
hardware VLAN offload where VLAN.TCI equal to 0 was being dropped and a
race between disabling VLAN receive feature in hardware and processing
the receive queue, where packets could have their VLAN information
dropped.

Ross Lagerwall fixes a racy condition during a ixgbe VF reset, where
writing the register to issue a reset and sending the reset message via
the mailbox API could result of the mailbox memory getting cleared
during the reset before the message gets successfully sent which results
in a VF driver malfunction.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 18330c58 96d1a731
Loading
Loading
Loading
Loading
+7 −7
Original line number Diff line number Diff line
@@ -1543,17 +1543,17 @@ static int i40e_set_mac(struct net_device *netdev, void *p)
		netdev_info(netdev, "set new mac address %pM\n", addr->sa_data);

	/* Copy the address first, so that we avoid a possible race with
	 * .set_rx_mode(). If we copy after changing the address in the filter
	 * list, we might open ourselves to a narrow race window where
	 * .set_rx_mode could delete our dev_addr filter and prevent traffic
	 * from passing.
	 * .set_rx_mode().
	 * - Remove old address from MAC filter
	 * - Copy new address
	 * - Add new address to MAC filter
	 */
	ether_addr_copy(netdev->dev_addr, addr->sa_data);

	spin_lock_bh(&vsi->mac_filter_hash_lock);
	i40e_del_mac_filter(vsi, netdev->dev_addr);
	i40e_add_mac_filter(vsi, addr->sa_data);
	ether_addr_copy(netdev->dev_addr, addr->sa_data);
	i40e_add_mac_filter(vsi, netdev->dev_addr);
	spin_unlock_bh(&vsi->mac_filter_hash_lock);

	if (vsi->type == I40E_VSI_MAIN) {
		i40e_status ret;

+12 −31
Original line number Diff line number Diff line
@@ -1558,24 +1558,6 @@ static bool i40e_alloc_mapped_page(struct i40e_ring *rx_ring,
	return true;
}

/**
 * i40e_receive_skb - Send a completed packet up the stack
 * @rx_ring:  rx ring in play
 * @skb: packet to send up
 * @vlan_tag: vlan tag for packet
 **/
void i40e_receive_skb(struct i40e_ring *rx_ring,
		      struct sk_buff *skb, u16 vlan_tag)
{
	struct i40e_q_vector *q_vector = rx_ring->q_vector;

	if ((rx_ring->netdev->features & NETIF_F_HW_VLAN_CTAG_RX) &&
	    (vlan_tag & VLAN_VID_MASK))
		__vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), vlan_tag);

	napi_gro_receive(&q_vector->napi, skb);
}

/**
 * i40e_alloc_rx_buffers - Replace used receive buffers
 * @rx_ring: ring to place buffers on
@@ -1793,8 +1775,7 @@ static inline void i40e_rx_hash(struct i40e_ring *ring,
 * other fields within the skb.
 **/
void i40e_process_skb_fields(struct i40e_ring *rx_ring,
			     union i40e_rx_desc *rx_desc, struct sk_buff *skb,
			     u8 rx_ptype)
			     union i40e_rx_desc *rx_desc, struct sk_buff *skb)
{
	u64 qword = le64_to_cpu(rx_desc->wb.qword1.status_error_len);
	u32 rx_status = (qword & I40E_RXD_QW1_STATUS_MASK) >>
@@ -1802,6 +1783,8 @@ void i40e_process_skb_fields(struct i40e_ring *rx_ring,
	u32 tsynvalid = rx_status & I40E_RXD_QW1_STATUS_TSYNVALID_MASK;
	u32 tsyn = (rx_status & I40E_RXD_QW1_STATUS_TSYNINDX_MASK) >>
		   I40E_RXD_QW1_STATUS_TSYNINDX_SHIFT;
	u8 rx_ptype = (qword & I40E_RXD_QW1_PTYPE_MASK) >>
		      I40E_RXD_QW1_PTYPE_SHIFT;

	if (unlikely(tsynvalid))
		i40e_ptp_rx_hwtstamp(rx_ring->vsi->back, skb, tsyn);
@@ -1812,6 +1795,13 @@ void i40e_process_skb_fields(struct i40e_ring *rx_ring,

	skb_record_rx_queue(skb, rx_ring->queue_index);

	if (qword & BIT(I40E_RX_DESC_STATUS_L2TAG1P_SHIFT)) {
		u16 vlan_tag = rx_desc->wb.qword0.lo_dword.l2tag1;

		__vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q),
				       le16_to_cpu(vlan_tag));
	}

	/* modifies the skb - consumes the enet header */
	skb->protocol = eth_type_trans(skb, rx_ring->netdev);
}
@@ -2350,8 +2340,6 @@ static int i40e_clean_rx_irq(struct i40e_ring *rx_ring, int budget)
		struct i40e_rx_buffer *rx_buffer;
		union i40e_rx_desc *rx_desc;
		unsigned int size;
		u16 vlan_tag;
		u8 rx_ptype;
		u64 qword;

		/* return some buffers to hardware, one at a time is too slow */
@@ -2444,18 +2432,11 @@ static int i40e_clean_rx_irq(struct i40e_ring *rx_ring, int budget)
		/* probably a little skewed due to removing CRC */
		total_rx_bytes += skb->len;

		qword = le64_to_cpu(rx_desc->wb.qword1.status_error_len);
		rx_ptype = (qword & I40E_RXD_QW1_PTYPE_MASK) >>
			   I40E_RXD_QW1_PTYPE_SHIFT;

		/* populate checksum, VLAN, and protocol */
		i40e_process_skb_fields(rx_ring, rx_desc, skb, rx_ptype);

		vlan_tag = (qword & BIT(I40E_RX_DESC_STATUS_L2TAG1P_SHIFT)) ?
			   le16_to_cpu(rx_desc->wb.qword0.lo_dword.l2tag1) : 0;
		i40e_process_skb_fields(rx_ring, rx_desc, skb);

		i40e_trace(clean_rx_irq_rx, rx_ring, rx_desc, skb);
		i40e_receive_skb(rx_ring, skb, vlan_tag);
		napi_gro_receive(&rx_ring->q_vector->napi, skb);
		skb = NULL;

		/* update budget accounting */
+1 −4
Original line number Diff line number Diff line
@@ -12,10 +12,7 @@ struct i40e_rx_buffer *i40e_clean_programming_status(
	union i40e_rx_desc *rx_desc,
	u64 qw);
void i40e_process_skb_fields(struct i40e_ring *rx_ring,
			     union i40e_rx_desc *rx_desc, struct sk_buff *skb,
			     u8 rx_ptype);
void i40e_receive_skb(struct i40e_ring *rx_ring,
		      struct sk_buff *skb, u16 vlan_tag);
			     union i40e_rx_desc *rx_desc, struct sk_buff *skb);
void i40e_xdp_ring_update_tail(struct i40e_ring *xdp_ring);
void i40e_update_rx_stats(struct i40e_ring *rx_ring,
			  unsigned int total_rx_bytes,
+2 −10
Original line number Diff line number Diff line
@@ -634,8 +634,6 @@ int i40e_clean_rx_irq_zc(struct i40e_ring *rx_ring, int budget)
		struct i40e_rx_buffer *bi;
		union i40e_rx_desc *rx_desc;
		unsigned int size;
		u16 vlan_tag;
		u8 rx_ptype;
		u64 qword;

		if (cleaned_count >= I40E_RX_BUFFER_WRITE) {
@@ -713,14 +711,8 @@ int i40e_clean_rx_irq_zc(struct i40e_ring *rx_ring, int budget)
		total_rx_bytes += skb->len;
		total_rx_packets++;

		qword = le64_to_cpu(rx_desc->wb.qword1.status_error_len);
		rx_ptype = (qword & I40E_RXD_QW1_PTYPE_MASK) >>
			   I40E_RXD_QW1_PTYPE_SHIFT;
		i40e_process_skb_fields(rx_ring, rx_desc, skb, rx_ptype);

		vlan_tag = (qword & BIT(I40E_RX_DESC_STATUS_L2TAG1P_SHIFT)) ?
			   le16_to_cpu(rx_desc->wb.qword0.lo_dword.l2tag1) : 0;
		i40e_receive_skb(rx_ring, skb, vlan_tag);
		i40e_process_skb_fields(rx_ring, rx_desc, skb);
		napi_gro_receive(&rx_ring->q_vector->napi, skb);
	}

	i40e_finalize_xdp_rx(rx_ring, xdp_xmit);
+10 −1
Original line number Diff line number Diff line
@@ -700,7 +700,6 @@ static inline void ixgbe_vf_reset_event(struct ixgbe_adapter *adapter, u32 vf)
	u8 num_tcs = adapter->hw_tcs;
	u32 reg_val;
	u32 queue;
	u32 word;

	/* remove VLAN filters beloning to this VF */
	ixgbe_clear_vf_vlans(adapter, vf);
@@ -758,6 +757,14 @@ static inline void ixgbe_vf_reset_event(struct ixgbe_adapter *adapter, u32 vf)
		}
	}

	IXGBE_WRITE_FLUSH(hw);
}

static void ixgbe_vf_clear_mbx(struct ixgbe_adapter *adapter, u32 vf)
{
	struct ixgbe_hw *hw = &adapter->hw;
	u32 word;

	/* Clear VF's mailbox memory */
	for (word = 0; word < IXGBE_VFMAILBOX_SIZE; word++)
		IXGBE_WRITE_REG_ARRAY(hw, IXGBE_PFMBMEM(vf), word, 0);
@@ -831,6 +838,8 @@ static int ixgbe_vf_reset_msg(struct ixgbe_adapter *adapter, u32 vf)
	/* reset the filters for the device */
	ixgbe_vf_reset_event(adapter, vf);

	ixgbe_vf_clear_mbx(adapter, vf);

	/* set vf mac address */
	if (!is_zero_ether_addr(vf_mac))
		ixgbe_set_vf_mac(adapter, vf, vf_mac);