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

Commit 820d1d5e authored by David S. Miller's avatar David S. Miller
Browse files


Jeff Kirsher says:

====================
Intel Wired LAN Driver Updates 2018-01-03

This series contains fixes for i40e and i40evf.

Amritha removes the UDP support for big buffer cloud filters since it is
not supported and having UDP enabled is a bug.

Alex fixes a bug in the __i40e_chk_linearize() which did not take into
account large (16K or larger) fragments that are split over 2 descriptors,
which could result in a transmit hang.

Jake fixes an issue where a devices own MAC address could be removed from
the unicast address list, so force a check on every address sync to ensure
removal does not happen.

Jiri Pirko fixes the return value when a filter configuration is not
supported, do not return "invalid" but return "not supported" so that
the core can react correctly.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents ee4aa8df bc4244c6
Loading
Loading
Loading
Loading
+26 −11
Original line number Original line Diff line number Diff line
@@ -1573,11 +1573,18 @@ static int i40e_set_mac(struct net_device *netdev, void *p)
	else
	else
		netdev_info(netdev, "set new mac address %pM\n", addr->sa_data);
		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.
	 */
	ether_addr_copy(netdev->dev_addr, addr->sa_data);

	spin_lock_bh(&vsi->mac_filter_hash_lock);
	spin_lock_bh(&vsi->mac_filter_hash_lock);
	i40e_del_mac_filter(vsi, netdev->dev_addr);
	i40e_del_mac_filter(vsi, netdev->dev_addr);
	i40e_add_mac_filter(vsi, addr->sa_data);
	i40e_add_mac_filter(vsi, addr->sa_data);
	spin_unlock_bh(&vsi->mac_filter_hash_lock);
	spin_unlock_bh(&vsi->mac_filter_hash_lock);
	ether_addr_copy(netdev->dev_addr, addr->sa_data);
	if (vsi->type == I40E_VSI_MAIN) {
	if (vsi->type == I40E_VSI_MAIN) {
		i40e_status ret;
		i40e_status ret;


@@ -1923,6 +1930,14 @@ static int i40e_addr_unsync(struct net_device *netdev, const u8 *addr)
	struct i40e_netdev_priv *np = netdev_priv(netdev);
	struct i40e_netdev_priv *np = netdev_priv(netdev);
	struct i40e_vsi *vsi = np->vsi;
	struct i40e_vsi *vsi = np->vsi;


	/* Under some circumstances, we might receive a request to delete
	 * our own device address from our uc list. Because we store the
	 * device address in the VSI's MAC/VLAN filter list, we need to ignore
	 * such requests and not delete our device address from this list.
	 */
	if (ether_addr_equal(addr, netdev->dev_addr))
		return 0;

	i40e_del_mac_filter(vsi, addr);
	i40e_del_mac_filter(vsi, addr);


	return 0;
	return 0;
@@ -6038,8 +6053,8 @@ static int i40e_validate_and_set_switch_mode(struct i40e_vsi *vsi)
	/* Set Bit 7 to be valid */
	/* Set Bit 7 to be valid */
	mode = I40E_AQ_SET_SWITCH_BIT7_VALID;
	mode = I40E_AQ_SET_SWITCH_BIT7_VALID;


	/* Set L4type to both TCP and UDP support */
	/* Set L4type for TCP support */
	mode |= I40E_AQ_SET_SWITCH_L4_TYPE_BOTH;
	mode |= I40E_AQ_SET_SWITCH_L4_TYPE_TCP;


	/* Set cloud filter mode */
	/* Set cloud filter mode */
	mode |= I40E_AQ_SET_SWITCH_MODE_NON_TUNNEL;
	mode |= I40E_AQ_SET_SWITCH_MODE_NON_TUNNEL;
@@ -6969,18 +6984,18 @@ static int i40e_add_del_cloud_filter_big_buf(struct i40e_vsi *vsi,
	     is_valid_ether_addr(filter->src_mac)) ||
	     is_valid_ether_addr(filter->src_mac)) ||
	    (is_multicast_ether_addr(filter->dst_mac) &&
	    (is_multicast_ether_addr(filter->dst_mac) &&
	     is_multicast_ether_addr(filter->src_mac)))
	     is_multicast_ether_addr(filter->src_mac)))
		return -EINVAL;
		return -EOPNOTSUPP;


	/* Make sure port is specified, otherwise bail out, for channel
	/* Big buffer cloud filter needs 'L4 port' to be non-zero. Also, UDP
	 * specific cloud filter needs 'L4 port' to be non-zero
	 * ports are not supported via big buffer now.
	 */
	 */
	if (!filter->dst_port)
	if (!filter->dst_port || filter->ip_proto == IPPROTO_UDP)
		return -EINVAL;
		return -EOPNOTSUPP;


	/* adding filter using src_port/src_ip is not supported at this stage */
	/* adding filter using src_port/src_ip is not supported at this stage */
	if (filter->src_port || filter->src_ipv4 ||
	if (filter->src_port || filter->src_ipv4 ||
	    !ipv6_addr_any(&filter->ip.v6.src_ip6))
	    !ipv6_addr_any(&filter->ip.v6.src_ip6))
		return -EINVAL;
		return -EOPNOTSUPP;


	/* copy element needed to add cloud filter from filter */
	/* copy element needed to add cloud filter from filter */
	i40e_set_cld_element(filter, &cld_filter.element);
	i40e_set_cld_element(filter, &cld_filter.element);
@@ -6991,7 +7006,7 @@ static int i40e_add_del_cloud_filter_big_buf(struct i40e_vsi *vsi,
	    is_multicast_ether_addr(filter->src_mac)) {
	    is_multicast_ether_addr(filter->src_mac)) {
		/* MAC + IP : unsupported mode */
		/* MAC + IP : unsupported mode */
		if (filter->dst_ipv4)
		if (filter->dst_ipv4)
			return -EINVAL;
			return -EOPNOTSUPP;


		/* since we validated that L4 port must be valid before
		/* since we validated that L4 port must be valid before
		 * we get here, start with respective "flags" value
		 * we get here, start with respective "flags" value
@@ -7356,7 +7371,7 @@ static int i40e_configure_clsflower(struct i40e_vsi *vsi,


	if (tc < 0) {
	if (tc < 0) {
		dev_err(&vsi->back->pdev->dev, "Invalid traffic class\n");
		dev_err(&vsi->back->pdev->dev, "Invalid traffic class\n");
		return -EINVAL;
		return -EOPNOTSUPP;
	}
	}


	if (test_bit(__I40E_RESET_RECOVERY_PENDING, pf->state) ||
	if (test_bit(__I40E_RESET_RECOVERY_PENDING, pf->state) ||
+23 −3
Original line number Original line Diff line number Diff line
@@ -3047,10 +3047,30 @@ bool __i40e_chk_linearize(struct sk_buff *skb)
	/* 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];
	for (stale = &skb_shinfo(skb)->frags[0];; stale++) {
	for (;;) {
		int stale_size = skb_frag_size(stale);

		sum += skb_frag_size(frag++);
		sum += skb_frag_size(frag++);


		/* The stale fragment may present us with a smaller
		 * descriptor than the actual fragment size. To account
		 * for that we need to remove all the data on the front and
		 * figure out what the remainder would be in the last
		 * descriptor associated with the fragment.
		 */
		if (stale_size > I40E_MAX_DATA_PER_TXD) {
			int align_pad = -(stale->page_offset) &
					(I40E_MAX_READ_REQ_SIZE - 1);

			sum -= align_pad;
			stale_size -= align_pad;

			do {
				sum -= I40E_MAX_DATA_PER_TXD_ALIGNED;
				stale_size -= I40E_MAX_DATA_PER_TXD_ALIGNED;
			} while (stale_size > I40E_MAX_DATA_PER_TXD);
		}

		/* 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)
			return true;
			return true;
@@ -3058,7 +3078,7 @@ bool __i40e_chk_linearize(struct sk_buff *skb)
		if (!nr_frags--)
		if (!nr_frags--)
			break;
			break;


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


	return false;
	return false;
+23 −3
Original line number Original line Diff line number Diff line
@@ -2012,10 +2012,30 @@ bool __i40evf_chk_linearize(struct sk_buff *skb)
	/* 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];
	for (stale = &skb_shinfo(skb)->frags[0];; stale++) {
	for (;;) {
		int stale_size = skb_frag_size(stale);

		sum += skb_frag_size(frag++);
		sum += skb_frag_size(frag++);


		/* The stale fragment may present us with a smaller
		 * descriptor than the actual fragment size. To account
		 * for that we need to remove all the data on the front and
		 * figure out what the remainder would be in the last
		 * descriptor associated with the fragment.
		 */
		if (stale_size > I40E_MAX_DATA_PER_TXD) {
			int align_pad = -(stale->page_offset) &
					(I40E_MAX_READ_REQ_SIZE - 1);

			sum -= align_pad;
			stale_size -= align_pad;

			do {
				sum -= I40E_MAX_DATA_PER_TXD_ALIGNED;
				stale_size -= I40E_MAX_DATA_PER_TXD_ALIGNED;
			} while (stale_size > I40E_MAX_DATA_PER_TXD);
		}

		/* 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)
			return true;
			return true;
@@ -2023,7 +2043,7 @@ bool __i40evf_chk_linearize(struct sk_buff *skb)
		if (!nr_frags--)
		if (!nr_frags--)
			break;
			break;


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


	return false;
	return false;