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

Commit 41015e89 authored by David S. Miller's avatar David S. Miller
Browse files


Jeff Kirsher says:

====================
Intel Wired LAN Driver Updates 2016-04-13

This series contains updates to i40e, i40evf and fm10k.

Alex fixes a bug introduced earlier based on his interpretation of the
XL710 datasheet.  The actual limit for fragments with TSO and a skbuff
that has payload data in the header portion of the buffer is actually
only 7 fragments and the skb-data portion counts as 2 buffers, one for
the TSO header, and the one for a segment payload buffer.

Jacob fixes a bug where in a previous refactor of the code broke
multi-bit updates for VFs.  The problem occurs because a multi-bit
request has a non-zero length, and the PF would simply drop any
request with the upper 16 bits set.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents d6d5e999 f808c5db
Loading
Loading
Loading
Loading
+22 −8
Original line number Original line Diff line number Diff line
@@ -1223,18 +1223,32 @@ s32 fm10k_iov_msg_mac_vlan_pf(struct fm10k_hw *hw, u32 **results,
		if (err)
		if (err)
			return err;
			return err;


		/* verify upper 16 bits are zero */
		if (vid >> 16)
			return FM10K_ERR_PARAM;

		set = !(vid & FM10K_VLAN_CLEAR);
		set = !(vid & FM10K_VLAN_CLEAR);
		vid &= ~FM10K_VLAN_CLEAR;
		vid &= ~FM10K_VLAN_CLEAR;


		/* if the length field has been set, this is a multi-bit
		 * update request. For multi-bit requests, simply disallow
		 * them when the pf_vid has been set. In this case, the PF
		 * should have already cleared the VLAN_TABLE, and if we
		 * allowed them, it could allow a rogue VF to receive traffic
		 * on a VLAN it was not assigned. In the single-bit case, we
		 * need to modify requests for VLAN 0 to use the default PF or
		 * SW vid when assigned.
		 */

		if (vid >> 16) {
			/* prevent multi-bit requests when PF has
			 * administratively set the VLAN for this VF
			 */
			if (vf_info->pf_vid)
				return FM10K_ERR_PARAM;
		} else {
			err = fm10k_iov_select_vid(vf_info, (u16)vid);
			err = fm10k_iov_select_vid(vf_info, (u16)vid);
			if (err < 0)
			if (err < 0)
				return err;
				return err;


			vid = err;
			vid = err;
		}


		/* update VSI info for VF in regards to VLAN table */
		/* update VSI info for VF in regards to VLAN table */
		err = hw->mac.ops.update_vlan(hw, vid, vf_info->vsi, set);
		err = hw->mac.ops.update_vlan(hw, vid, vf_info->vsi, set);
+24 −25
Original line number Original line Diff line number Diff line
@@ -2594,35 +2594,34 @@ int __i40e_maybe_stop_tx(struct i40e_ring *tx_ring, int size)
}
}


/**
/**
 * __i40e_chk_linearize - Check if there are more than 8 fragments per packet
 * __i40e_chk_linearize - Check if there are more than 8 buffers per packet
 * @skb:      send buffer
 * @skb:      send buffer
 *
 *
 * Note: Our HW can't scatter-gather more than 8 fragments to build
 * Note: Our HW can't DMA more than 8 buffers to build a packet on the wire
 * a packet on the wire and so we need to figure out the cases where we
 * and so we need to figure out the cases where we need to linearize the skb.
 * need to linearize the skb.
 *
 * For TSO we need to count the TSO header and segment payload separately.
 * As such we need to check cases where we have 7 fragments or more as we
 * can potentially require 9 DMA transactions, 1 for the TSO header, 1 for
 * the segment payload in the first descriptor, and another 7 for the
 * fragments.
 **/
 **/
bool __i40e_chk_linearize(struct sk_buff *skb)
bool __i40e_chk_linearize(struct sk_buff *skb)
{
{
	const struct skb_frag_struct *frag, *stale;
	const struct skb_frag_struct *frag, *stale;
	int gso_size, nr_frags, sum;
	int nr_frags, sum;

	/* check to see if TSO is enabled, if so we may get a repreive */
	gso_size = skb_shinfo(skb)->gso_size;
	if (unlikely(!gso_size))
		return true;


	/* no need to check if number of frags is less than 8 */
	/* no need to check if number of frags is less than 7 */
	nr_frags = skb_shinfo(skb)->nr_frags;
	nr_frags = skb_shinfo(skb)->nr_frags;
	if (nr_frags < I40E_MAX_BUFFER_TXD)
	if (nr_frags < (I40E_MAX_BUFFER_TXD - 1))
		return false;
		return false;


	/* We need to walk through the list and validate that each group
	/* We need to walk through the list and validate that each group
	 * of 6 fragments totals at least gso_size.  However we don't need
	 * of 6 fragments totals at least gso_size.  However we don't need
	 * to perform such validation on the first or last 6 since the first
	 * to perform such validation on the last 6 since the last 6 cannot
	 * 6 cannot inherit any data from a descriptor before them, and the
	 * inherit any data from a descriptor after them.
	 * last 6 cannot inherit any data from a descriptor after them.
	 */
	 */
	nr_frags -= I40E_MAX_BUFFER_TXD - 1;
	nr_frags -= I40E_MAX_BUFFER_TXD - 2;
	frag = &skb_shinfo(skb)->frags[0];
	frag = &skb_shinfo(skb)->frags[0];


	/* Initialize size to the negative value of gso_size minus 1.  We
	/* Initialize size to the negative value of gso_size minus 1.  We
@@ -2631,21 +2630,21 @@ bool __i40e_chk_linearize(struct sk_buff *skb)
	 * descriptors for a single transmit as the header and previous
	 * descriptors for a single transmit as the header and previous
	 * fragment are already consuming 2 descriptors.
	 * fragment are already consuming 2 descriptors.
	 */
	 */
	sum = 1 - gso_size;
	sum = 1 - skb_shinfo(skb)->gso_size;


	/* Add size of frags 1 through 5 to create our initial sum */
	/* Add size of frags 0 through 4 to create our initial sum */
	sum += skb_frag_size(++frag);
	sum += skb_frag_size(frag++);
	sum += skb_frag_size(++frag);
	sum += skb_frag_size(frag++);
	sum += skb_frag_size(++frag);
	sum += skb_frag_size(frag++);
	sum += skb_frag_size(++frag);
	sum += skb_frag_size(frag++);
	sum += skb_frag_size(++frag);
	sum += skb_frag_size(frag++);


	/* Walk through fragments adding latest fragment, testing it, and
	/* Walk through fragments adding latest fragment, testing it, and
	 * then removing stale fragments from the sum.
	 * then removing stale fragments from the sum.
	 */
	 */
	stale = &skb_shinfo(skb)->frags[0];
	stale = &skb_shinfo(skb)->frags[0];
	for (;;) {
	for (;;) {
		sum += skb_frag_size(++frag);
		sum += skb_frag_size(frag++);


		/* if sum is negative we failed to make sufficient progress */
		/* if sum is negative we failed to make sufficient progress */
		if (sum < 0)
		if (sum < 0)
@@ -2655,7 +2654,7 @@ bool __i40e_chk_linearize(struct sk_buff *skb)
		if (!--nr_frags)
		if (!--nr_frags)
			break;
			break;


		sum -= skb_frag_size(++stale);
		sum -= skb_frag_size(stale++);
	}
	}


	return false;
	return false;
+7 −3
Original line number Original line Diff line number Diff line
@@ -413,10 +413,14 @@ static inline int i40e_maybe_stop_tx(struct i40e_ring *tx_ring, int size)
 **/
 **/
static inline bool i40e_chk_linearize(struct sk_buff *skb, int count)
static inline bool i40e_chk_linearize(struct sk_buff *skb, int count)
{
{
	/* we can only support up to 8 data buffers for a single send */
	/* Both TSO and single send will work if count is less than 8 */
	if (likely(count <= I40E_MAX_BUFFER_TXD))
	if (likely(count < I40E_MAX_BUFFER_TXD))
		return false;
		return false;


	if (skb_is_gso(skb))
		return __i40e_chk_linearize(skb);
		return __i40e_chk_linearize(skb);

	/* we can support up to 8 data buffers for a single send */
	return count != I40E_MAX_BUFFER_TXD;
}
}
#endif /* _I40E_TXRX_H_ */
#endif /* _I40E_TXRX_H_ */
+24 −25
Original line number Original line Diff line number Diff line
@@ -1796,35 +1796,34 @@ static void i40e_create_tx_ctx(struct i40e_ring *tx_ring,
}
}


/**
/**
 * __i40evf_chk_linearize - Check if there are more than 8 fragments per packet
 * __i40evf_chk_linearize - Check if there are more than 8 buffers per packet
 * @skb:      send buffer
 * @skb:      send buffer
 *
 *
 * Note: Our HW can't scatter-gather more than 8 fragments to build
 * Note: Our HW can't DMA more than 8 buffers to build a packet on the wire
 * a packet on the wire and so we need to figure out the cases where we
 * and so we need to figure out the cases where we need to linearize the skb.
 * need to linearize the skb.
 *
 * For TSO we need to count the TSO header and segment payload separately.
 * As such we need to check cases where we have 7 fragments or more as we
 * can potentially require 9 DMA transactions, 1 for the TSO header, 1 for
 * the segment payload in the first descriptor, and another 7 for the
 * fragments.
 **/
 **/
bool __i40evf_chk_linearize(struct sk_buff *skb)
bool __i40evf_chk_linearize(struct sk_buff *skb)
{
{
	const struct skb_frag_struct *frag, *stale;
	const struct skb_frag_struct *frag, *stale;
	int gso_size, nr_frags, sum;
	int nr_frags, sum;

	/* check to see if TSO is enabled, if so we may get a repreive */
	gso_size = skb_shinfo(skb)->gso_size;
	if (unlikely(!gso_size))
		return true;


	/* no need to check if number of frags is less than 8 */
	/* no need to check if number of frags is less than 7 */
	nr_frags = skb_shinfo(skb)->nr_frags;
	nr_frags = skb_shinfo(skb)->nr_frags;
	if (nr_frags < I40E_MAX_BUFFER_TXD)
	if (nr_frags < (I40E_MAX_BUFFER_TXD - 1))
		return false;
		return false;


	/* We need to walk through the list and validate that each group
	/* We need to walk through the list and validate that each group
	 * of 6 fragments totals at least gso_size.  However we don't need
	 * of 6 fragments totals at least gso_size.  However we don't need
	 * to perform such validation on the first or last 6 since the first
	 * to perform such validation on the last 6 since the last 6 cannot
	 * 6 cannot inherit any data from a descriptor before them, and the
	 * inherit any data from a descriptor after them.
	 * last 6 cannot inherit any data from a descriptor after them.
	 */
	 */
	nr_frags -= I40E_MAX_BUFFER_TXD - 1;
	nr_frags -= I40E_MAX_BUFFER_TXD - 2;
	frag = &skb_shinfo(skb)->frags[0];
	frag = &skb_shinfo(skb)->frags[0];


	/* Initialize size to the negative value of gso_size minus 1.  We
	/* Initialize size to the negative value of gso_size minus 1.  We
@@ -1833,21 +1832,21 @@ bool __i40evf_chk_linearize(struct sk_buff *skb)
	 * descriptors for a single transmit as the header and previous
	 * descriptors for a single transmit as the header and previous
	 * fragment are already consuming 2 descriptors.
	 * fragment are already consuming 2 descriptors.
	 */
	 */
	sum = 1 - gso_size;
	sum = 1 - skb_shinfo(skb)->gso_size;


	/* Add size of frags 1 through 5 to create our initial sum */
	/* Add size of frags 0 through 4 to create our initial sum */
	sum += skb_frag_size(++frag);
	sum += skb_frag_size(frag++);
	sum += skb_frag_size(++frag);
	sum += skb_frag_size(frag++);
	sum += skb_frag_size(++frag);
	sum += skb_frag_size(frag++);
	sum += skb_frag_size(++frag);
	sum += skb_frag_size(frag++);
	sum += skb_frag_size(++frag);
	sum += skb_frag_size(frag++);


	/* Walk through fragments adding latest fragment, testing it, and
	/* Walk through fragments adding latest fragment, testing it, and
	 * then removing stale fragments from the sum.
	 * then removing stale fragments from the sum.
	 */
	 */
	stale = &skb_shinfo(skb)->frags[0];
	stale = &skb_shinfo(skb)->frags[0];
	for (;;) {
	for (;;) {
		sum += skb_frag_size(++frag);
		sum += skb_frag_size(frag++);


		/* if sum is negative we failed to make sufficient progress */
		/* if sum is negative we failed to make sufficient progress */
		if (sum < 0)
		if (sum < 0)
@@ -1857,7 +1856,7 @@ bool __i40evf_chk_linearize(struct sk_buff *skb)
		if (!--nr_frags)
		if (!--nr_frags)
			break;
			break;


		sum -= skb_frag_size(++stale);
		sum -= skb_frag_size(stale++);
	}
	}


	return false;
	return false;
+7 −3
Original line number Original line Diff line number Diff line
@@ -395,10 +395,14 @@ static inline int i40e_maybe_stop_tx(struct i40e_ring *tx_ring, int size)
 **/
 **/
static inline bool i40e_chk_linearize(struct sk_buff *skb, int count)
static inline bool i40e_chk_linearize(struct sk_buff *skb, int count)
{
{
	/* we can only support up to 8 data buffers for a single send */
	/* Both TSO and single send will work if count is less than 8 */
	if (likely(count <= I40E_MAX_BUFFER_TXD))
	if (likely(count < I40E_MAX_BUFFER_TXD))
		return false;
		return false;


	if (skb_is_gso(skb))
		return __i40evf_chk_linearize(skb);
		return __i40evf_chk_linearize(skb);

	/* we can support up to 8 data buffers for a single send */
	return count != I40E_MAX_BUFFER_TXD;
}
}
#endif /* _I40E_TXRX_H_ */
#endif /* _I40E_TXRX_H_ */