diff options
Diffstat (limited to 'drivers/net/ethernet/intel')
| -rw-r--r-- | drivers/net/ethernet/intel/e1000/e1000.h | 3 | ||||
| -rw-r--r-- | drivers/net/ethernet/intel/e1000/e1000_hw.c | 6 | ||||
| -rw-r--r-- | drivers/net/ethernet/intel/e1000/e1000_main.c | 27 | ||||
| -rw-r--r-- | drivers/net/ethernet/intel/e1000e/ich8lan.c | 11 | ||||
| -rw-r--r-- | drivers/net/ethernet/intel/e1000e/ich8lan.h | 3 | ||||
| -rw-r--r-- | drivers/net/ethernet/intel/e1000e/netdev.c | 9 | ||||
| -rw-r--r-- | drivers/net/ethernet/intel/i40e/i40e_main.c | 38 | ||||
| -rw-r--r-- | drivers/net/ethernet/intel/i40e/i40e_txrx.c | 26 | ||||
| -rw-r--r-- | drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c | 2 | ||||
| -rw-r--r-- | drivers/net/ethernet/intel/i40evf/i40e_txrx.c | 26 | 
10 files changed, 117 insertions, 34 deletions
| diff --git a/drivers/net/ethernet/intel/e1000/e1000.h b/drivers/net/ethernet/intel/e1000/e1000.h index d7bdea79e9fa..8fd2458060a0 100644 --- a/drivers/net/ethernet/intel/e1000/e1000.h +++ b/drivers/net/ethernet/intel/e1000/e1000.h @@ -331,7 +331,8 @@ struct e1000_adapter {  enum e1000_state_t {  	__E1000_TESTING,  	__E1000_RESETTING, -	__E1000_DOWN +	__E1000_DOWN, +	__E1000_DISABLED  };  #undef pr_fmt diff --git a/drivers/net/ethernet/intel/e1000/e1000_hw.c b/drivers/net/ethernet/intel/e1000/e1000_hw.c index 8172cf08cc33..3bac9df1c099 100644 --- a/drivers/net/ethernet/intel/e1000/e1000_hw.c +++ b/drivers/net/ethernet/intel/e1000/e1000_hw.c @@ -4307,8 +4307,10 @@ static void e1000_init_rx_addrs(struct e1000_hw *hw)  	rar_num = E1000_RAR_ENTRIES; -	/* Zero out the other 15 receive addresses. */ -	e_dbg("Clearing RAR[1-15]\n"); +	/* Zero out the following 14 receive addresses. RAR[15] is for +	 * manageability +	 */ +	e_dbg("Clearing RAR[1-14]\n");  	for (i = 1; i < rar_num; i++) {  		E1000_WRITE_REG_ARRAY(hw, RA, (i << 1), 0);  		E1000_WRITE_FLUSH(); diff --git a/drivers/net/ethernet/intel/e1000/e1000_main.c b/drivers/net/ethernet/intel/e1000/e1000_main.c index 1982f7917a8d..3dd4aeb2706d 100644 --- a/drivers/net/ethernet/intel/e1000/e1000_main.c +++ b/drivers/net/ethernet/intel/e1000/e1000_main.c @@ -945,7 +945,7 @@ static int e1000_init_hw_struct(struct e1000_adapter *adapter,  static int e1000_probe(struct pci_dev *pdev, const struct pci_device_id *ent)  {  	struct net_device *netdev; -	struct e1000_adapter *adapter; +	struct e1000_adapter *adapter = NULL;  	struct e1000_hw *hw;  	static int cards_found; @@ -955,6 +955,7 @@ static int e1000_probe(struct pci_dev *pdev, const struct pci_device_id *ent)  	u16 tmp = 0;  	u16 eeprom_apme_mask = E1000_EEPROM_APME;  	int bars, need_ioport; +	bool disable_dev = false;  	/* do not allocate ioport bars when not needed */  	need_ioport = e1000_is_need_ioport(pdev); @@ -1259,11 +1260,13 @@ err_mdio_ioremap:  	iounmap(hw->ce4100_gbe_mdio_base_virt);  	iounmap(hw->hw_addr);  err_ioremap: +	disable_dev = !test_and_set_bit(__E1000_DISABLED, &adapter->flags);  	free_netdev(netdev);  err_alloc_etherdev:  	pci_release_selected_regions(pdev, bars);  err_pci_reg: -	pci_disable_device(pdev); +	if (!adapter || disable_dev) +		pci_disable_device(pdev);  	return err;  } @@ -1281,6 +1284,7 @@ static void e1000_remove(struct pci_dev *pdev)  	struct net_device *netdev = pci_get_drvdata(pdev);  	struct e1000_adapter *adapter = netdev_priv(netdev);  	struct e1000_hw *hw = &adapter->hw; +	bool disable_dev;  	e1000_down_and_stop(adapter);  	e1000_release_manageability(adapter); @@ -1299,9 +1303,11 @@ static void e1000_remove(struct pci_dev *pdev)  		iounmap(hw->flash_address);  	pci_release_selected_regions(pdev, adapter->bars); +	disable_dev = !test_and_set_bit(__E1000_DISABLED, &adapter->flags);  	free_netdev(netdev); -	pci_disable_device(pdev); +	if (disable_dev) +		pci_disable_device(pdev);  }  /** @@ -5156,7 +5162,8 @@ static int __e1000_shutdown(struct pci_dev *pdev, bool *enable_wake)  	if (netif_running(netdev))  		e1000_free_irq(adapter); -	pci_disable_device(pdev); +	if (!test_and_set_bit(__E1000_DISABLED, &adapter->flags)) +		pci_disable_device(pdev);  	return 0;  } @@ -5200,6 +5207,10 @@ static int e1000_resume(struct pci_dev *pdev)  		pr_err("Cannot enable PCI device from suspend\n");  		return err;  	} + +	/* flush memory to make sure state is correct */ +	smp_mb__before_atomic(); +	clear_bit(__E1000_DISABLED, &adapter->flags);  	pci_set_master(pdev);  	pci_enable_wake(pdev, PCI_D3hot, 0); @@ -5274,7 +5285,9 @@ static pci_ers_result_t e1000_io_error_detected(struct pci_dev *pdev,  	if (netif_running(netdev))  		e1000_down(adapter); -	pci_disable_device(pdev); + +	if (!test_and_set_bit(__E1000_DISABLED, &adapter->flags)) +		pci_disable_device(pdev);  	/* Request a slot slot reset. */  	return PCI_ERS_RESULT_NEED_RESET; @@ -5302,6 +5315,10 @@ static pci_ers_result_t e1000_io_slot_reset(struct pci_dev *pdev)  		pr_err("Cannot re-enable PCI device after reset.\n");  		return PCI_ERS_RESULT_DISCONNECT;  	} + +	/* flush memory to make sure state is correct */ +	smp_mb__before_atomic(); +	clear_bit(__E1000_DISABLED, &adapter->flags);  	pci_set_master(pdev);  	pci_enable_wake(pdev, PCI_D3hot, 0); diff --git a/drivers/net/ethernet/intel/e1000e/ich8lan.c b/drivers/net/ethernet/intel/e1000e/ich8lan.c index d6d4ed7acf03..31277d3bb7dc 100644 --- a/drivers/net/ethernet/intel/e1000e/ich8lan.c +++ b/drivers/net/ethernet/intel/e1000e/ich8lan.c @@ -1367,6 +1367,9 @@ out:   *  Checks to see of the link status of the hardware has changed.  If a   *  change in link status has been detected, then we read the PHY registers   *  to get the current speed/duplex if link exists. + * + *  Returns a negative error code (-E1000_ERR_*) or 0 (link down) or 1 (link + *  up).   **/  static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw)  { @@ -1382,7 +1385,7 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw)  	 * Change or Rx Sequence Error interrupt.  	 */  	if (!mac->get_link_status) -		return 0; +		return 1;  	/* First we want to see if the MII Status Register reports  	 * link.  If so, then we want to get the current speed/duplex @@ -1613,10 +1616,12 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw)  	 * different link partner.  	 */  	ret_val = e1000e_config_fc_after_link_up(hw); -	if (ret_val) +	if (ret_val) {  		e_dbg("Error configuring flow control\n"); +		return ret_val; +	} -	return ret_val; +	return 1;  }  static s32 e1000_get_variants_ich8lan(struct e1000_adapter *adapter) diff --git a/drivers/net/ethernet/intel/e1000e/ich8lan.h b/drivers/net/ethernet/intel/e1000e/ich8lan.h index 67163ca898ba..00a36df02a3f 100644 --- a/drivers/net/ethernet/intel/e1000e/ich8lan.h +++ b/drivers/net/ethernet/intel/e1000e/ich8lan.h @@ -113,7 +113,8 @@  #define NVM_SIZE_MULTIPLIER 4096	/*multiplier for NVMS field */  #define E1000_FLASH_BASE_ADDR 0xE000	/*offset of NVM access regs */  #define E1000_CTRL_EXT_NVMVS 0x3	/*NVM valid sector */ -#define E1000_TARC0_CB_MULTIQ_3_REQ	(1 << 28 | 1 << 29) +#define E1000_TARC0_CB_MULTIQ_3_REQ	0x30000000 +#define E1000_TARC0_CB_MULTIQ_2_REQ	0x20000000  #define PCIE_ICH8_SNOOP_ALL	PCIE_NO_SNOOP_ALL  #define E1000_ICH_RAR_ENTRIES	7 diff --git a/drivers/net/ethernet/intel/e1000e/netdev.c b/drivers/net/ethernet/intel/e1000e/netdev.c index f2f49239b015..9f18d39bdc8f 100644 --- a/drivers/net/ethernet/intel/e1000e/netdev.c +++ b/drivers/net/ethernet/intel/e1000e/netdev.c @@ -3034,9 +3034,12 @@ static void e1000_configure_tx(struct e1000_adapter *adapter)  		ew32(IOSFPC, reg_val);  		reg_val = er32(TARC(0)); -		/* SPT and KBL Si errata workaround to avoid Tx hang */ -		reg_val &= ~BIT(28); -		reg_val |= BIT(29); +		/* SPT and KBL Si errata workaround to avoid Tx hang. +		 * Dropping the number of outstanding requests from +		 * 3 to 2 in order to avoid a buffer overrun. +		 */ +		reg_val &= ~E1000_TARC0_CB_MULTIQ_3_REQ; +		reg_val |= E1000_TARC0_CB_MULTIQ_2_REQ;  		ew32(TARC(0), reg_val);  	}  } diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 4c08cc86463e..42dcaefc4c19 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -1573,11 +1573,18 @@ static int i40e_set_mac(struct net_device *netdev, void *p)  	else  		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);  	i40e_del_mac_filter(vsi, netdev->dev_addr);  	i40e_add_mac_filter(vsi, addr->sa_data);  	spin_unlock_bh(&vsi->mac_filter_hash_lock); -	ether_addr_copy(netdev->dev_addr, addr->sa_data);  	if (vsi->type == I40E_VSI_MAIN) {  		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_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);  	return 0; @@ -6038,8 +6053,8 @@ static int i40e_validate_and_set_switch_mode(struct i40e_vsi *vsi)  	/* Set Bit 7 to be valid */  	mode = I40E_AQ_SET_SWITCH_BIT7_VALID; -	/* Set L4type to both TCP and UDP support */ -	mode |= I40E_AQ_SET_SWITCH_L4_TYPE_BOTH; +	/* Set L4type for TCP support */ +	mode |= I40E_AQ_SET_SWITCH_L4_TYPE_TCP;  	/* Set cloud filter mode */  	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_multicast_ether_addr(filter->dst_mac) &&  	     is_multicast_ether_addr(filter->src_mac))) -		return -EINVAL; +		return -EOPNOTSUPP; -	/* Make sure port is specified, otherwise bail out, for channel -	 * specific cloud filter needs 'L4 port' to be non-zero +	/* Big buffer cloud filter needs 'L4 port' to be non-zero. Also, UDP +	 * ports are not supported via big buffer now.  	 */ -	if (!filter->dst_port) -		return -EINVAL; +	if (!filter->dst_port || filter->ip_proto == IPPROTO_UDP) +		return -EOPNOTSUPP;  	/* adding filter using src_port/src_ip is not supported at this stage */  	if (filter->src_port || filter->src_ipv4 ||  	    !ipv6_addr_any(&filter->ip.v6.src_ip6)) -		return -EINVAL; +		return -EOPNOTSUPP;  	/* copy element needed to add cloud filter from filter */  	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)) {  		/* MAC + IP : unsupported mode */  		if (filter->dst_ipv4) -			return -EINVAL; +			return -EOPNOTSUPP;  		/* since we validated that L4 port must be valid before  		 * we get here, start with respective "flags" value @@ -7356,7 +7371,7 @@ static int i40e_configure_clsflower(struct i40e_vsi *vsi,  	if (tc < 0) {  		dev_err(&vsi->back->pdev->dev, "Invalid traffic class\n"); -		return -EINVAL; +		return -EOPNOTSUPP;  	}  	if (test_bit(__I40E_RESET_RECOVERY_PENDING, pf->state) || @@ -7401,7 +7416,6 @@ static int i40e_configure_clsflower(struct i40e_vsi *vsi,  		dev_err(&pf->pdev->dev,  			"Failed to add cloud filter, err %s\n",  			i40e_stat_str(&pf->hw, err)); -		err = i40e_aq_rc_to_posix(err, pf->hw.aq.asq_last_status);  		goto err;  	} diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.c b/drivers/net/ethernet/intel/i40e/i40e_txrx.c index 4566d66ffc7c..5bc2748ac468 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_txrx.c +++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.c @@ -3047,10 +3047,30 @@ bool __i40e_chk_linearize(struct sk_buff *skb)  	/* Walk through fragments adding latest fragment, testing it, and  	 * then removing stale fragments from the sum.  	 */ -	stale = &skb_shinfo(skb)->frags[0]; -	for (;;) { +	for (stale = &skb_shinfo(skb)->frags[0];; stale++) { +		int stale_size = skb_frag_size(stale); +  		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 < 0)  			return true; @@ -3058,7 +3078,7 @@ bool __i40e_chk_linearize(struct sk_buff *skb)  		if (!nr_frags--)  			break; -		sum -= skb_frag_size(stale++); +		sum -= stale_size;  	}  	return false; diff --git a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c index a3dc9b932946..36cb8e068e85 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c +++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c @@ -2086,7 +2086,7 @@ static int i40e_vc_request_queues_msg(struct i40e_vf *vf, u8 *msg, int msglen)  	}  	return i40e_vc_send_msg_to_vf(vf, VIRTCHNL_OP_REQUEST_QUEUES, 0, -				      (u8 *)vfres, sizeof(vfres)); +				      (u8 *)vfres, sizeof(*vfres));  }  /** diff --git a/drivers/net/ethernet/intel/i40evf/i40e_txrx.c b/drivers/net/ethernet/intel/i40evf/i40e_txrx.c index 50864f99446d..1ba29bb85b67 100644 --- a/drivers/net/ethernet/intel/i40evf/i40e_txrx.c +++ b/drivers/net/ethernet/intel/i40evf/i40e_txrx.c @@ -2012,10 +2012,30 @@ bool __i40evf_chk_linearize(struct sk_buff *skb)  	/* Walk through fragments adding latest fragment, testing it, and  	 * then removing stale fragments from the sum.  	 */ -	stale = &skb_shinfo(skb)->frags[0]; -	for (;;) { +	for (stale = &skb_shinfo(skb)->frags[0];; stale++) { +		int stale_size = skb_frag_size(stale); +  		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 < 0)  			return true; @@ -2023,7 +2043,7 @@ bool __i40evf_chk_linearize(struct sk_buff *skb)  		if (!nr_frags--)  			break; -		sum -= skb_frag_size(stale++); +		sum -= stale_size;  	}  	return false; |