diff options
Diffstat (limited to 'drivers/net')
47 files changed, 360 insertions, 178 deletions
| diff --git a/drivers/net/ethernet/allwinner/sun4i-emac.c b/drivers/net/ethernet/allwinner/sun4i-emac.c index 1fcd5568a352..f3470d96837a 100644 --- a/drivers/net/ethernet/allwinner/sun4i-emac.c +++ b/drivers/net/ethernet/allwinner/sun4i-emac.c @@ -850,8 +850,10 @@ static int emac_probe(struct platform_device *pdev)  	}  	db->clk = devm_clk_get(&pdev->dev, NULL); -	if (IS_ERR(db->clk)) +	if (IS_ERR(db->clk)) { +		ret = PTR_ERR(db->clk);  		goto out; +	}  	clk_prepare_enable(db->clk); diff --git a/drivers/net/ethernet/altera/altera_tse_main.c b/drivers/net/ethernet/altera/altera_tse_main.c index 3498760dc22a..760c72c6e2ac 100644 --- a/drivers/net/ethernet/altera/altera_tse_main.c +++ b/drivers/net/ethernet/altera/altera_tse_main.c @@ -1170,10 +1170,6 @@ tx_request_irq_error:  init_error:  	free_skbufs(dev);  alloc_skbuf_error: -	if (priv->phydev) { -		phy_disconnect(priv->phydev); -		priv->phydev = NULL; -	}  phy_error:  	return ret;  } @@ -1186,12 +1182,9 @@ static int tse_shutdown(struct net_device *dev)  	int ret;  	unsigned long int flags; -	/* Stop and disconnect the PHY */ -	if (priv->phydev) { +	/* Stop the PHY */ +	if (priv->phydev)  		phy_stop(priv->phydev); -		phy_disconnect(priv->phydev); -		priv->phydev = NULL; -	}  	netif_stop_queue(dev);  	napi_disable(&priv->napi); @@ -1525,6 +1518,10 @@ err_free_netdev:  static int altera_tse_remove(struct platform_device *pdev)  {  	struct net_device *ndev = platform_get_drvdata(pdev); +	struct altera_tse_private *priv = netdev_priv(ndev); + +	if (priv->phydev) +		phy_disconnect(priv->phydev);  	platform_set_drvdata(pdev, NULL);  	altera_tse_mdio_destroy(ndev); diff --git a/drivers/net/ethernet/atheros/alx/main.c b/drivers/net/ethernet/atheros/alx/main.c index e398eda07298..c8af3ce3ea38 100644 --- a/drivers/net/ethernet/atheros/alx/main.c +++ b/drivers/net/ethernet/atheros/alx/main.c @@ -184,15 +184,16 @@ static void alx_schedule_reset(struct alx_priv *alx)  	schedule_work(&alx->reset_wk);  } -static bool alx_clean_rx_irq(struct alx_priv *alx, int budget) +static int alx_clean_rx_irq(struct alx_priv *alx, int budget)  {  	struct alx_rx_queue *rxq = &alx->rxq;  	struct alx_rrd *rrd;  	struct alx_buffer *rxb;  	struct sk_buff *skb;  	u16 length, rfd_cleaned = 0; +	int work = 0; -	while (budget > 0) { +	while (work < budget) {  		rrd = &rxq->rrd[rxq->rrd_read_idx];  		if (!(rrd->word3 & cpu_to_le32(1 << RRD_UPDATED_SHIFT)))  			break; @@ -203,7 +204,7 @@ static bool alx_clean_rx_irq(struct alx_priv *alx, int budget)  		    ALX_GET_FIELD(le32_to_cpu(rrd->word0),  				  RRD_NOR) != 1) {  			alx_schedule_reset(alx); -			return 0; +			return work;  		}  		rxb = &rxq->bufs[rxq->read_idx]; @@ -243,7 +244,7 @@ static bool alx_clean_rx_irq(struct alx_priv *alx, int budget)  		}  		napi_gro_receive(&alx->napi, skb); -		budget--; +		work++;  next_pkt:  		if (++rxq->read_idx == alx->rx_ringsz) @@ -258,21 +259,22 @@ next_pkt:  	if (rfd_cleaned)  		alx_refill_rx_ring(alx, GFP_ATOMIC); -	return budget > 0; +	return work;  }  static int alx_poll(struct napi_struct *napi, int budget)  {  	struct alx_priv *alx = container_of(napi, struct alx_priv, napi);  	struct alx_hw *hw = &alx->hw; -	bool complete = true;  	unsigned long flags; +	bool tx_complete; +	int work; -	complete = alx_clean_tx_irq(alx) && -		   alx_clean_rx_irq(alx, budget); +	tx_complete = alx_clean_tx_irq(alx); +	work = alx_clean_rx_irq(alx, budget); -	if (!complete) -		return 1; +	if (!tx_complete || work == budget) +		return budget;  	napi_complete(&alx->napi); @@ -284,7 +286,7 @@ static int alx_poll(struct napi_struct *napi, int budget)  	alx_post_write(hw); -	return 0; +	return work;  }  static irqreturn_t alx_intr_handle(struct alx_priv *alx, u32 intr) diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c index 553dcd8a9df2..96bf01ba32dd 100644 --- a/drivers/net/ethernet/broadcom/tg3.c +++ b/drivers/net/ethernet/broadcom/tg3.c @@ -7413,6 +7413,8 @@ static inline void tg3_netif_start(struct tg3 *tp)  }  static void tg3_irq_quiesce(struct tg3 *tp) +	__releases(tp->lock) +	__acquires(tp->lock)  {  	int i; @@ -7421,8 +7423,12 @@ static void tg3_irq_quiesce(struct tg3 *tp)  	tp->irq_sync = 1;  	smp_mb(); +	spin_unlock_bh(&tp->lock); +  	for (i = 0; i < tp->irq_cnt; i++)  		synchronize_irq(tp->napi[i].irq_vec); + +	spin_lock_bh(&tp->lock);  }  /* Fully shutdown all tg3 driver activity elsewhere in the system. @@ -9018,6 +9024,8 @@ static void tg3_restore_clk(struct tg3 *tp)  /* tp->lock is held. */  static int tg3_chip_reset(struct tg3 *tp) +	__releases(tp->lock) +	__acquires(tp->lock)  {  	u32 val;  	void (*write_op)(struct tg3 *, u32, u32); @@ -9073,9 +9081,13 @@ static int tg3_chip_reset(struct tg3 *tp)  	}  	smp_mb(); +	tg3_full_unlock(tp); +  	for (i = 0; i < tp->irq_cnt; i++)  		synchronize_irq(tp->napi[i].irq_vec); +	tg3_full_lock(tp, 0); +  	if (tg3_asic_rev(tp) == ASIC_REV_57780) {  		val = tr32(TG3_PCIE_LNKCTL) & ~TG3_PCIE_LNKCTL_L1_PLL_PD_EN;  		tw32(TG3_PCIE_LNKCTL, val | TG3_PCIE_LNKCTL_L1_PLL_PD_DIS); @@ -10903,11 +10915,13 @@ static void tg3_timer(unsigned long __opaque)  {  	struct tg3 *tp = (struct tg3 *) __opaque; -	if (tp->irq_sync || tg3_flag(tp, RESET_TASK_PENDING)) -		goto restart_timer; -  	spin_lock(&tp->lock); +	if (tp->irq_sync || tg3_flag(tp, RESET_TASK_PENDING)) { +		spin_unlock(&tp->lock); +		goto restart_timer; +	} +  	if (tg3_asic_rev(tp) == ASIC_REV_5717 ||  	    tg3_flag(tp, 57765_CLASS))  		tg3_chk_missed_msi(tp); @@ -11101,11 +11115,13 @@ static void tg3_reset_task(struct work_struct *work)  	struct tg3 *tp = container_of(work, struct tg3, reset_task);  	int err; +	rtnl_lock();  	tg3_full_lock(tp, 0);  	if (!netif_running(tp->dev)) {  		tg3_flag_clear(tp, RESET_TASK_PENDING);  		tg3_full_unlock(tp); +		rtnl_unlock();  		return;  	} @@ -11138,6 +11154,7 @@ out:  		tg3_phy_start(tp);  	tg3_flag_clear(tp, RESET_TASK_PENDING); +	rtnl_unlock();  }  static int tg3_request_irq(struct tg3 *tp, int irq_num) diff --git a/drivers/net/ethernet/cadence/at91_ether.c b/drivers/net/ethernet/cadence/at91_ether.c index 55eb7f2af2b4..7ef55f5fa664 100644 --- a/drivers/net/ethernet/cadence/at91_ether.c +++ b/drivers/net/ethernet/cadence/at91_ether.c @@ -340,7 +340,7 @@ static int __init at91ether_probe(struct platform_device *pdev)  		res = PTR_ERR(lp->pclk);  		goto err_free_dev;  	} -	clk_enable(lp->pclk); +	clk_prepare_enable(lp->pclk);  	lp->hclk = ERR_PTR(-ENOENT);  	lp->tx_clk = ERR_PTR(-ENOENT); @@ -406,7 +406,7 @@ static int __init at91ether_probe(struct platform_device *pdev)  err_out_unregister_netdev:  	unregister_netdev(dev);  err_disable_clock: -	clk_disable(lp->pclk); +	clk_disable_unprepare(lp->pclk);  err_free_dev:  	free_netdev(dev);  	return res; @@ -424,7 +424,7 @@ static int at91ether_remove(struct platform_device *pdev)  	kfree(lp->mii_bus->irq);  	mdiobus_free(lp->mii_bus);  	unregister_netdev(dev); -	clk_disable(lp->pclk); +	clk_disable_unprepare(lp->pclk);  	free_netdev(dev);  	return 0; @@ -440,7 +440,7 @@ static int at91ether_suspend(struct platform_device *pdev, pm_message_t mesg)  		netif_stop_queue(net_dev);  		netif_device_detach(net_dev); -		clk_disable(lp->pclk); +		clk_disable_unprepare(lp->pclk);  	}  	return 0;  } @@ -451,7 +451,7 @@ static int at91ether_resume(struct platform_device *pdev)  	struct macb *lp = netdev_priv(net_dev);  	if (netif_running(net_dev)) { -		clk_enable(lp->pclk); +		clk_prepare_enable(lp->pclk);  		netif_device_attach(net_dev);  		netif_start_queue(net_dev); diff --git a/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c b/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c index 2215d432a059..a936ee8958c7 100644 --- a/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c +++ b/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c @@ -2430,7 +2430,7 @@ static void cfg_queues(struct adapter *adapter)  	 */  	n10g = 0;  	for_each_port(adapter, pidx) -		n10g += is_10g_port(&adap2pinfo(adapter, pidx)->link_cfg); +		n10g += is_x_10g_port(&adap2pinfo(adapter, pidx)->link_cfg);  	/*  	 * We default to 1 queue per non-10G port and up to # of cores queues diff --git a/drivers/net/ethernet/chelsio/cxgb4vf/t4vf_hw.c b/drivers/net/ethernet/chelsio/cxgb4vf/t4vf_hw.c index 21dc9a20308c..60426cf890a7 100644 --- a/drivers/net/ethernet/chelsio/cxgb4vf/t4vf_hw.c +++ b/drivers/net/ethernet/chelsio/cxgb4vf/t4vf_hw.c @@ -323,6 +323,8 @@ int t4vf_port_init(struct adapter *adapter, int pidx)  		return v;  	v = be32_to_cpu(port_rpl.u.info.lstatus_to_modtype); +	pi->mdio_addr = (v & FW_PORT_CMD_MDIOCAP_F) ? +			FW_PORT_CMD_MDIOADDR_G(v) : -1;  	pi->port_type = FW_PORT_CMD_PTYPE_G(v);  	pi->mod_type = FW_PORT_MOD_TYPE_NA; diff --git a/drivers/net/ethernet/cisco/enic/enic_main.c b/drivers/net/ethernet/cisco/enic/enic_main.c index 705f334ebb85..b29e027c476e 100644 --- a/drivers/net/ethernet/cisco/enic/enic_main.c +++ b/drivers/net/ethernet/cisco/enic/enic_main.c @@ -1616,7 +1616,7 @@ static int enic_open(struct net_device *netdev)  		if (vnic_rq_desc_used(&enic->rq[i]) == 0) {  			netdev_err(netdev, "Unable to alloc receive buffers\n");  			err = -ENOMEM; -			goto err_out_notify_unset; +			goto err_out_free_rq;  		}  	} @@ -1649,7 +1649,9 @@ static int enic_open(struct net_device *netdev)  	return 0; -err_out_notify_unset: +err_out_free_rq: +	for (i = 0; i < enic->rq_count; i++) +		vnic_rq_clean(&enic->rq[i], enic_free_rq_buf);  	enic_dev_notify_unset(enic);  err_out_free_intr:  	enic_free_intr(enic); diff --git a/drivers/net/ethernet/dnet.c b/drivers/net/ethernet/dnet.c index a379c3e4b57f..13d00a38a5bd 100644 --- a/drivers/net/ethernet/dnet.c +++ b/drivers/net/ethernet/dnet.c @@ -398,13 +398,8 @@ static int dnet_poll(struct napi_struct *napi, int budget)  		 * break out of while loop if there are no more  		 * packets waiting  		 */ -		if (!(dnet_readl(bp, RX_FIFO_WCNT) >> 16)) { -			napi_complete(napi); -			int_enable = dnet_readl(bp, INTR_ENB); -			int_enable |= DNET_INTR_SRC_RX_CMDFIFOAF; -			dnet_writel(bp, int_enable, INTR_ENB); -			return 0; -		} +		if (!(dnet_readl(bp, RX_FIFO_WCNT) >> 16)) +			break;  		cmd_word = dnet_readl(bp, RX_LEN_FIFO);  		pkt_len = cmd_word & 0xFFFF; @@ -433,20 +428,17 @@ static int dnet_poll(struct napi_struct *napi, int budget)  			       "size %u.\n", dev->name, pkt_len);  	} -	budget -= npackets; -  	if (npackets < budget) {  		/* We processed all packets available.  Tell NAPI it can -		 * stop polling then re-enable rx interrupts */ +		 * stop polling then re-enable rx interrupts. +		 */  		napi_complete(napi);  		int_enable = dnet_readl(bp, INTR_ENB);  		int_enable |= DNET_INTR_SRC_RX_CMDFIFOAF;  		dnet_writel(bp, int_enable, INTR_ENB); -		return 0;  	} -	/* There are still packets waiting */ -	return 1; +	return npackets;  }  static irqreturn_t dnet_interrupt(int irq, void *dev_id) diff --git a/drivers/net/ethernet/freescale/fec.h b/drivers/net/ethernet/freescale/fec.h index 469691ad4a1e..40132929daf7 100644 --- a/drivers/net/ethernet/freescale/fec.h +++ b/drivers/net/ethernet/freescale/fec.h @@ -424,6 +424,8 @@ struct bufdesc_ex {   * (40ns * 6).   */  #define FEC_QUIRK_BUG_CAPTURE		(1 << 10) +/* Controller has only one MDIO bus */ +#define FEC_QUIRK_SINGLE_MDIO		(1 << 11)  struct fec_enet_priv_tx_q {  	int index; diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c index 5ebdf8dc8a31..bba87775419d 100644 --- a/drivers/net/ethernet/freescale/fec_main.c +++ b/drivers/net/ethernet/freescale/fec_main.c @@ -91,7 +91,8 @@ static struct platform_device_id fec_devtype[] = {  		.driver_data = 0,  	}, {  		.name = "imx28-fec", -		.driver_data = FEC_QUIRK_ENET_MAC | FEC_QUIRK_SWAP_FRAME, +		.driver_data = FEC_QUIRK_ENET_MAC | FEC_QUIRK_SWAP_FRAME | +				FEC_QUIRK_SINGLE_MDIO,  	}, {  		.name = "imx6q-fec",  		.driver_data = FEC_QUIRK_ENET_MAC | FEC_QUIRK_HAS_GBIT | @@ -1937,7 +1938,7 @@ static int fec_enet_mii_init(struct platform_device *pdev)  	int err = -ENXIO, i;  	/* -	 * The dual fec interfaces are not equivalent with enet-mac. +	 * The i.MX28 dual fec interfaces are not equal.  	 * Here are the differences:  	 *  	 *  - fec0 supports MII & RMII modes while fec1 only supports RMII @@ -1952,7 +1953,7 @@ static int fec_enet_mii_init(struct platform_device *pdev)  	 * mdio interface in board design, and need to be configured by  	 * fec0 mii_bus.  	 */ -	if ((fep->quirks & FEC_QUIRK_ENET_MAC) && fep->dev_id > 0) { +	if ((fep->quirks & FEC_QUIRK_SINGLE_MDIO) && fep->dev_id > 0) {  		/* fec1 uses fec0 mii_bus */  		if (mii_cnt && fec0_mii_bus) {  			fep->mii_bus = fec0_mii_bus; @@ -2015,7 +2016,7 @@ static int fec_enet_mii_init(struct platform_device *pdev)  	mii_cnt++;  	/* save fec0 mii_bus */ -	if (fep->quirks & FEC_QUIRK_ENET_MAC) +	if (fep->quirks & FEC_QUIRK_SINGLE_MDIO)  		fec0_mii_bus = fep->mii_bus;  	return 0; @@ -3129,6 +3130,7 @@ fec_probe(struct platform_device *pdev)  		pdev->id_entry = of_id->data;  	fep->quirks = pdev->id_entry->driver_data; +	fep->netdev = ndev;  	fep->num_rx_queues = num_rx_qs;  	fep->num_tx_queues = num_tx_qs; diff --git a/drivers/net/ethernet/intel/Kconfig b/drivers/net/ethernet/intel/Kconfig index 5b8300a32bf5..4d61ef50b465 100644 --- a/drivers/net/ethernet/intel/Kconfig +++ b/drivers/net/ethernet/intel/Kconfig @@ -281,6 +281,17 @@ config I40E_DCB  	  If unsure, say N. +config I40E_FCOE +	bool "Fibre Channel over Ethernet (FCoE)" +	default n +	depends on I40E && DCB && FCOE +	---help--- +	  Say Y here if you want to use Fibre Channel over Ethernet (FCoE) +	  in the driver. This will create new netdev for exclusive FCoE +	  use with XL710 FCoE offloads enabled. + +	  If unsure, say N. +  config I40EVF  	tristate "Intel(R) XL710 X710 Virtual Function Ethernet support"  	depends on PCI_MSI diff --git a/drivers/net/ethernet/intel/e100.c b/drivers/net/ethernet/intel/e100.c index 781065eb5431..e9c3a87e5b11 100644 --- a/drivers/net/ethernet/intel/e100.c +++ b/drivers/net/ethernet/intel/e100.c @@ -1543,7 +1543,7 @@ static int e100_phy_init(struct nic *nic)  		mdio_write(netdev, nic->mii.phy_id, MII_BMCR, bmcr);  	} else if ((nic->mac >= mac_82550_D102) || ((nic->flags & ich) &&  	   (mdio_read(netdev, nic->mii.phy_id, MII_TPISTATUS) & 0x8000) && -		!(nic->eeprom[eeprom_cnfg_mdix] & eeprom_mdix_enabled))) { +		(nic->eeprom[eeprom_cnfg_mdix] & eeprom_mdix_enabled))) {  		/* enable/disable MDI/MDI-X auto-switching. */  		mdio_write(netdev, nic->mii.phy_id, MII_NCONFIG,  				nic->mii.force_media ? 0 : NCONFIG_AUTO_SWITCH); diff --git a/drivers/net/ethernet/intel/i40e/Makefile b/drivers/net/ethernet/intel/i40e/Makefile index 4b94ddb29c24..c40581999121 100644 --- a/drivers/net/ethernet/intel/i40e/Makefile +++ b/drivers/net/ethernet/intel/i40e/Makefile @@ -44,4 +44,4 @@ i40e-objs := i40e_main.o \  	i40e_virtchnl_pf.o  i40e-$(CONFIG_I40E_DCB) += i40e_dcb.o i40e_dcb_nl.o -i40e-$(CONFIG_FCOE:m=y) += i40e_fcoe.o +i40e-$(CONFIG_I40E_FCOE) += i40e_fcoe.o diff --git a/drivers/net/ethernet/intel/i40e/i40e_debugfs.c b/drivers/net/ethernet/intel/i40e/i40e_debugfs.c index 433a55886ad2..cb0de455683e 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_debugfs.c +++ b/drivers/net/ethernet/intel/i40e/i40e_debugfs.c @@ -829,7 +829,7 @@ static void i40e_dbg_dump_desc(int cnt, int vsi_seid, int ring_id, int desc_n,  		if (desc_n >= ring->count || desc_n < 0) {  			dev_info(&pf->pdev->dev,  				 "descriptor %d not found\n", desc_n); -			return; +			goto out;  		}  		if (!is_rx_ring) {  			txd = I40E_TX_DESC(ring, desc_n); @@ -855,6 +855,8 @@ static void i40e_dbg_dump_desc(int cnt, int vsi_seid, int ring_id, int desc_n,  	} else {  		dev_info(&pf->pdev->dev, "dump desc rx/tx <vsi_seid> <ring_id> [<desc_n>]\n");  	} + +out:  	kfree(ring);  } diff --git a/drivers/net/ethernet/intel/i40e/i40e_osdep.h b/drivers/net/ethernet/intel/i40e/i40e_osdep.h index 045b5c4b98b3..ad802dd0f67a 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_osdep.h +++ b/drivers/net/ethernet/intel/i40e/i40e_osdep.h @@ -78,7 +78,7 @@ do {                                                            \  } while (0)  typedef enum i40e_status_code i40e_status; -#if defined(CONFIG_FCOE) || defined(CONFIG_FCOE_MODULE) +#ifdef CONFIG_I40E_FCOE  #define I40E_FCOE -#endif /* CONFIG_FCOE or CONFIG_FCOE_MODULE */ +#endif  #endif /* _I40E_OSDEP_H_ */ diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.c b/drivers/net/ethernet/intel/i40e/i40e_txrx.c index 04b441460bbd..cecb340898fe 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_txrx.c +++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.c @@ -658,6 +658,8 @@ static inline u32 i40e_get_head(struct i40e_ring *tx_ring)  	return le32_to_cpu(*(volatile __le32 *)head);  } +#define WB_STRIDE 0x3 +  /**   * i40e_clean_tx_irq - Reclaim resources after transmit completes   * @tx_ring:  tx ring to clean @@ -759,6 +761,18 @@ static bool i40e_clean_tx_irq(struct i40e_ring *tx_ring, int budget)  	tx_ring->q_vector->tx.total_bytes += total_bytes;  	tx_ring->q_vector->tx.total_packets += total_packets; +	/* check to see if there are any non-cache aligned descriptors +	 * waiting to be written back, and kick the hardware to force +	 * them to be written back in case of napi polling +	 */ +	if (budget && +	    !((i & WB_STRIDE) == WB_STRIDE) && +	    !test_bit(__I40E_DOWN, &tx_ring->vsi->state) && +	    (I40E_DESC_UNUSED(tx_ring) != tx_ring->count)) +		tx_ring->arm_wb = true; +	else +		tx_ring->arm_wb = false; +  	if (check_for_tx_hang(tx_ring) && i40e_check_tx_hang(tx_ring)) {  		/* schedule immediate reset if we believe we hung */  		dev_info(tx_ring->dev, "Detected Tx Unit Hang\n" @@ -777,13 +791,16 @@ static bool i40e_clean_tx_irq(struct i40e_ring *tx_ring, int budget)  		netif_stop_subqueue(tx_ring->netdev, tx_ring->queue_index);  		dev_info(tx_ring->dev, -			 "tx hang detected on queue %d, resetting adapter\n", +			 "tx hang detected on queue %d, reset requested\n",  			 tx_ring->queue_index); -		tx_ring->netdev->netdev_ops->ndo_tx_timeout(tx_ring->netdev); +		/* do not fire the reset immediately, wait for the stack to +		 * decide we are truly stuck, also prevents every queue from +		 * simultaneously requesting a reset +		 */ -		/* the adapter is about to reset, no point in enabling stuff */ -		return true; +		/* the adapter is about to reset, no point in enabling polling */ +		budget = 1;  	}  	netdev_tx_completed_queue(netdev_get_tx_queue(tx_ring->netdev, @@ -806,7 +823,25 @@ static bool i40e_clean_tx_irq(struct i40e_ring *tx_ring, int budget)  		}  	} -	return budget > 0; +	return !!budget; +} + +/** + * i40e_force_wb - Arm hardware to do a wb on noncache aligned descriptors + * @vsi: the VSI we care about + * @q_vector: the vector  on which to force writeback + * + **/ +static void i40e_force_wb(struct i40e_vsi *vsi, struct i40e_q_vector *q_vector) +{ +	u32 val = I40E_PFINT_DYN_CTLN_INTENA_MASK | +		  I40E_PFINT_DYN_CTLN_SWINT_TRIG_MASK | +		  I40E_PFINT_DYN_CTLN_SW_ITR_INDX_ENA_MASK +		  /* allow 00 to be written to the index */; + +	wr32(&vsi->back->hw, +	     I40E_PFINT_DYN_CTLN(q_vector->v_idx + vsi->base_vector - 1), +	     val);  }  /** @@ -1290,9 +1325,7 @@ static inline void i40e_rx_checksum(struct i40e_vsi *vsi,  	 * so the total length of IPv4 header is IHL*4 bytes  	 * The UDP_0 bit *may* bet set if the *inner* header is UDP  	 */ -	if (ipv4_tunnel && -	    (decoded.inner_prot != I40E_RX_PTYPE_INNER_PROT_UDP) && -	    !(rx_status & (1 << I40E_RX_DESC_STATUS_UDP_0_SHIFT))) { +	if (ipv4_tunnel) {  		skb->transport_header = skb->mac_header +  					sizeof(struct ethhdr) +  					(ip_hdr(skb)->ihl * 4); @@ -1302,15 +1335,19 @@ static inline void i40e_rx_checksum(struct i40e_vsi *vsi,  					  skb->protocol == htons(ETH_P_8021AD))  					  ? VLAN_HLEN : 0; -		rx_udp_csum = udp_csum(skb); -		iph = ip_hdr(skb); -		csum = csum_tcpudp_magic( -				iph->saddr, iph->daddr, -				(skb->len - skb_transport_offset(skb)), -				IPPROTO_UDP, rx_udp_csum); +		if ((ip_hdr(skb)->protocol == IPPROTO_UDP) && +		    (udp_hdr(skb)->check != 0)) { +			rx_udp_csum = udp_csum(skb); +			iph = ip_hdr(skb); +			csum = csum_tcpudp_magic( +					iph->saddr, iph->daddr, +					(skb->len - skb_transport_offset(skb)), +					IPPROTO_UDP, rx_udp_csum); -		if (udp_hdr(skb)->check != csum) -			goto checksum_fail; +			if (udp_hdr(skb)->check != csum) +				goto checksum_fail; + +		} /* else its GRE and so no outer UDP header */  	}  	skb->ip_summed = CHECKSUM_UNNECESSARY; @@ -1581,6 +1618,7 @@ int i40e_napi_poll(struct napi_struct *napi, int budget)  	struct i40e_vsi *vsi = q_vector->vsi;  	struct i40e_ring *ring;  	bool clean_complete = true; +	bool arm_wb = false;  	int budget_per_ring;  	if (test_bit(__I40E_DOWN, &vsi->state)) { @@ -1591,8 +1629,10 @@ int i40e_napi_poll(struct napi_struct *napi, int budget)  	/* Since the actual Tx work is minimal, we can give the Tx a larger  	 * budget and be more aggressive about cleaning up the Tx descriptors.  	 */ -	i40e_for_each_ring(ring, q_vector->tx) +	i40e_for_each_ring(ring, q_vector->tx) {  		clean_complete &= i40e_clean_tx_irq(ring, vsi->work_limit); +		arm_wb |= ring->arm_wb; +	}  	/* We attempt to distribute budget to each Rx queue fairly, but don't  	 * allow the budget to go below 1 because that would exit polling early. @@ -1603,8 +1643,11 @@ int i40e_napi_poll(struct napi_struct *napi, int budget)  		clean_complete &= i40e_clean_rx_irq(ring, budget_per_ring);  	/* If work not completed, return budget and polling will return */ -	if (!clean_complete) +	if (!clean_complete) { +		if (arm_wb) +			i40e_force_wb(vsi, q_vector);  		return budget; +	}  	/* Work is done so exit the polling mode and re-enable the interrupt */  	napi_complete(napi); @@ -1840,17 +1883,16 @@ static int i40e_tso(struct i40e_ring *tx_ring, struct sk_buff *skb,  	if (err < 0)  		return err; -	if (protocol == htons(ETH_P_IP)) { -		iph = skb->encapsulation ? inner_ip_hdr(skb) : ip_hdr(skb); +	iph = skb->encapsulation ? inner_ip_hdr(skb) : ip_hdr(skb); +	ipv6h = skb->encapsulation ? inner_ipv6_hdr(skb) : ipv6_hdr(skb); + +	if (iph->version == 4) {  		tcph = skb->encapsulation ? inner_tcp_hdr(skb) : tcp_hdr(skb);  		iph->tot_len = 0;  		iph->check = 0;  		tcph->check = ~csum_tcpudp_magic(iph->saddr, iph->daddr,  						 0, IPPROTO_TCP, 0); -	} else if (skb_is_gso_v6(skb)) { - -		ipv6h = skb->encapsulation ? inner_ipv6_hdr(skb) -					   : ipv6_hdr(skb); +	} else if (ipv6h->version == 6) {  		tcph = skb->encapsulation ? inner_tcp_hdr(skb) : tcp_hdr(skb);  		ipv6h->payload_len = 0;  		tcph->check = ~csum_ipv6_magic(&ipv6h->saddr, &ipv6h->daddr, @@ -1946,13 +1988,9 @@ static void i40e_tx_enable_csum(struct sk_buff *skb, u32 tx_flags,  					 I40E_TX_CTX_EXT_IP_IPV4_NO_CSUM;  			}  		} else if (tx_flags & I40E_TX_FLAGS_IPV6) { -			if (tx_flags & I40E_TX_FLAGS_TSO) { -				*cd_tunneling |= I40E_TX_CTX_EXT_IP_IPV6; +			*cd_tunneling |= I40E_TX_CTX_EXT_IP_IPV6; +			if (tx_flags & I40E_TX_FLAGS_TSO)  				ip_hdr(skb)->check = 0; -			} else { -				*cd_tunneling |= -					 I40E_TX_CTX_EXT_IP_IPV4_NO_CSUM; -			}  		}  		/* Now set the ctx descriptor fields */ @@ -1962,7 +2000,10 @@ static void i40e_tx_enable_csum(struct sk_buff *skb, u32 tx_flags,  				   ((skb_inner_network_offset(skb) -  					skb_transport_offset(skb)) >> 1) <<  				   I40E_TXD_CTX_QW0_NATLEN_SHIFT; - +		if (this_ip_hdr->version == 6) { +			tx_flags &= ~I40E_TX_FLAGS_IPV4; +			tx_flags |= I40E_TX_FLAGS_IPV6; +		}  	} else {  		network_hdr_len = skb_network_header_len(skb);  		this_ip_hdr = ip_hdr(skb); @@ -2198,7 +2239,6 @@ static void i40e_tx_map(struct i40e_ring *tx_ring, struct sk_buff *skb,  	/* Place RS bit on last descriptor of any packet that spans across the  	 * 4th descriptor (WB_STRIDE aka 0x3) in a 64B cacheline.  	 */ -#define WB_STRIDE 0x3  	if (((i & WB_STRIDE) != WB_STRIDE) &&  	    (first <= &tx_ring->tx_bi[i]) &&  	    (first >= &tx_ring->tx_bi[i & ~WB_STRIDE])) { diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.h b/drivers/net/ethernet/intel/i40e/i40e_txrx.h index e60d3accb2e2..18b00231d2f1 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_txrx.h +++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.h @@ -241,6 +241,7 @@ struct i40e_ring {  	unsigned long last_rx_timestamp;  	bool ring_active;		/* is ring online or not */ +	bool arm_wb;		/* do something to arm write back */  	/* stats structs */  	struct i40e_queue_stats	stats; diff --git a/drivers/net/ethernet/intel/igb/e1000_82575.c b/drivers/net/ethernet/intel/igb/e1000_82575.c index 051ea94bdcd3..0f69ef81751a 100644 --- a/drivers/net/ethernet/intel/igb/e1000_82575.c +++ b/drivers/net/ethernet/intel/igb/e1000_82575.c @@ -1125,7 +1125,7 @@ static s32 igb_acquire_swfw_sync_82575(struct e1000_hw *hw, u16 mask)  	u32 swmask = mask;  	u32 fwmask = mask << 16;  	s32 ret_val = 0; -	s32 i = 0, timeout = 200; /* FIXME: find real value to use here */ +	s32 i = 0, timeout = 200;  	while (i < timeout) {  		if (igb_get_hw_semaphore(hw)) { diff --git a/drivers/net/ethernet/mellanox/mlx4/main.c b/drivers/net/ethernet/mellanox/mlx4/main.c index 943cbd47d832..03e9eb0dc761 100644 --- a/drivers/net/ethernet/mellanox/mlx4/main.c +++ b/drivers/net/ethernet/mellanox/mlx4/main.c @@ -1829,7 +1829,7 @@ static int mlx4_init_hca(struct mlx4_dev *dev)  		err = mlx4_dev_cap(dev, &dev_cap);  		if (err) {  			mlx4_err(dev, "QUERY_DEV_CAP command failed, aborting\n"); -			goto err_stop_fw; +			return err;  		}  		choose_steering_mode(dev, &dev_cap); @@ -1860,7 +1860,7 @@ static int mlx4_init_hca(struct mlx4_dev *dev)  					     &init_hca);  		if ((long long) icm_size < 0) {  			err = icm_size; -			goto err_stop_fw; +			return err;  		}  		dev->caps.max_fmr_maps = (1 << (32 - ilog2(dev->caps.num_mpts))) - 1; @@ -1874,7 +1874,7 @@ static int mlx4_init_hca(struct mlx4_dev *dev)  		err = mlx4_init_icm(dev, &dev_cap, &init_hca, icm_size);  		if (err) -			goto err_stop_fw; +			return err;  		err = mlx4_INIT_HCA(dev, &init_hca);  		if (err) { @@ -1886,7 +1886,7 @@ static int mlx4_init_hca(struct mlx4_dev *dev)  			err = mlx4_query_func(dev, &dev_cap);  			if (err < 0) {  				mlx4_err(dev, "QUERY_FUNC command failed, aborting.\n"); -				goto err_stop_fw; +				goto err_close;  			} else if (err & MLX4_QUERY_FUNC_NUM_SYS_EQS) {  				dev->caps.num_eqs = dev_cap.max_eqs;  				dev->caps.reserved_eqs = dev_cap.reserved_eqs; @@ -2006,11 +2006,6 @@ err_free_icm:  	if (!mlx4_is_slave(dev))  		mlx4_free_icms(dev); -err_stop_fw: -	if (!mlx4_is_slave(dev)) { -		mlx4_UNMAP_FA(dev); -		mlx4_free_icm(dev, priv->fw.fw_icm, 0); -	}  	return err;  } diff --git a/drivers/net/ethernet/mellanox/mlx4/mr.c b/drivers/net/ethernet/mellanox/mlx4/mr.c index d6f549685c0f..7094a9c70fd5 100644 --- a/drivers/net/ethernet/mellanox/mlx4/mr.c +++ b/drivers/net/ethernet/mellanox/mlx4/mr.c @@ -584,6 +584,7 @@ EXPORT_SYMBOL_GPL(mlx4_mr_free);  void mlx4_mr_rereg_mem_cleanup(struct mlx4_dev *dev, struct mlx4_mr *mr)  {  	mlx4_mtt_cleanup(dev, &mr->mtt); +	mr->mtt.order = -1;  }  EXPORT_SYMBOL_GPL(mlx4_mr_rereg_mem_cleanup); @@ -593,14 +594,14 @@ int mlx4_mr_rereg_mem_write(struct mlx4_dev *dev, struct mlx4_mr *mr,  {  	int err; -	mpt_entry->start       = cpu_to_be64(iova); -	mpt_entry->length      = cpu_to_be64(size); -	mpt_entry->entity_size = cpu_to_be32(page_shift); -  	err = mlx4_mtt_init(dev, npages, page_shift, &mr->mtt);  	if (err)  		return err; +	mpt_entry->start       = cpu_to_be64(mr->iova); +	mpt_entry->length      = cpu_to_be64(mr->size); +	mpt_entry->entity_size = cpu_to_be32(mr->mtt.page_shift); +  	mpt_entry->pd_flags &= cpu_to_be32(MLX4_MPT_PD_MASK |  					   MLX4_MPT_PD_FLAG_EN_INV);  	mpt_entry->flags    &= cpu_to_be32(MLX4_MPT_FLAG_FREE | diff --git a/drivers/net/ethernet/myricom/myri10ge/myri10ge.c b/drivers/net/ethernet/myricom/myri10ge/myri10ge.c index af099057f0e9..71af98bb72cb 100644 --- a/drivers/net/ethernet/myricom/myri10ge/myri10ge.c +++ b/drivers/net/ethernet/myricom/myri10ge/myri10ge.c @@ -4033,8 +4033,10 @@ static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent)  	(void)pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64));  	mgp->cmd = dma_alloc_coherent(&pdev->dev, sizeof(*mgp->cmd),  				      &mgp->cmd_bus, GFP_KERNEL); -	if (mgp->cmd == NULL) +	if (!mgp->cmd) { +		status = -ENOMEM;  		goto abort_with_enabled; +	}  	mgp->board_span = pci_resource_len(pdev, 0);  	mgp->iomem_base = pci_resource_start(pdev, 0); diff --git a/drivers/net/ethernet/qlogic/qla3xxx.c b/drivers/net/ethernet/qlogic/qla3xxx.c index c2f09af5c25b..4847713211ca 100644 --- a/drivers/net/ethernet/qlogic/qla3xxx.c +++ b/drivers/net/ethernet/qlogic/qla3xxx.c @@ -146,10 +146,7 @@ static int ql_wait_for_drvr_lock(struct ql3_adapter *qdev)  {  	int i = 0; -	while (i < 10) { -		if (i) -			ssleep(1); - +	do {  		if (ql_sem_lock(qdev,  				QL_DRVR_SEM_MASK,  				(QL_RESOURCE_BITS_BASE_CODE | (qdev->mac_index) @@ -158,7 +155,8 @@ static int ql_wait_for_drvr_lock(struct ql3_adapter *qdev)  				      "driver lock acquired\n");  			return 1;  		} -	} +		ssleep(1); +	} while (++i < 10);  	netdev_err(qdev->ndev, "Timed out waiting for driver lock...\n");  	return 0; diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c index 9929b97cfb36..2528c3fb6b90 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c @@ -2605,6 +2605,7 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)  	} else {  		dev_err(&pdev->dev,  			"%s: failed. Please Reboot\n", __func__); +		err = -ENODEV;  		goto err_out_free_hw;  	} diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c index c29ba80ae02b..37583a9d8853 100644 --- a/drivers/net/ethernet/renesas/sh_eth.c +++ b/drivers/net/ethernet/renesas/sh_eth.c @@ -473,6 +473,7 @@ static struct sh_eth_cpu_data r8a777x_data = {  	.eesr_err_check	= EESR_TWB | EESR_TABT | EESR_RABT | EESR_RFE |  			  EESR_RDE | EESR_RFRMER | EESR_TFE | EESR_TDE |  			  EESR_ECI, +	.fdr_value	= 0x00000f0f,  	.apr		= 1,  	.mpr		= 1, @@ -495,6 +496,7 @@ static struct sh_eth_cpu_data r8a779x_data = {  	.eesr_err_check	= EESR_TWB | EESR_TABT | EESR_RABT | EESR_RFE |  			  EESR_RDE | EESR_RFRMER | EESR_TFE | EESR_TDE |  			  EESR_ECI, +	.fdr_value	= 0x00000f0f,  	.apr		= 1,  	.mpr		= 1, @@ -536,6 +538,8 @@ static struct sh_eth_cpu_data sh7724_data = {  			  EESR_RDE | EESR_RFRMER | EESR_TFE | EESR_TDE |  			  EESR_ECI, +	.trscer_err_mask = DESC_I_RINT8, +  	.apr		= 1,  	.mpr		= 1,  	.tpauser	= 1, @@ -856,6 +860,9 @@ static void sh_eth_set_default_cpu_data(struct sh_eth_cpu_data *cd)  	if (!cd->eesr_err_check)  		cd->eesr_err_check = DEFAULT_EESR_ERR_CHECK; + +	if (!cd->trscer_err_mask) +		cd->trscer_err_mask = DEFAULT_TRSCER_ERR_MASK;  }  static int sh_eth_check_reset(struct net_device *ndev) @@ -1294,7 +1301,7 @@ static int sh_eth_dev_init(struct net_device *ndev, bool start)  	/* Frame recv control (enable multiple-packets per rx irq) */  	sh_eth_write(ndev, RMCR_RNC, RMCR); -	sh_eth_write(ndev, DESC_I_RINT8 | DESC_I_RINT5 | DESC_I_TINT2, TRSCER); +	sh_eth_write(ndev, mdp->cd->trscer_err_mask, TRSCER);  	if (mdp->cd->bculr)  		sh_eth_write(ndev, 0x800, BCULR);	/* Burst sycle set */ diff --git a/drivers/net/ethernet/renesas/sh_eth.h b/drivers/net/ethernet/renesas/sh_eth.h index 22301bf9c21d..71f5de1171bd 100644 --- a/drivers/net/ethernet/renesas/sh_eth.h +++ b/drivers/net/ethernet/renesas/sh_eth.h @@ -369,6 +369,8 @@ enum DESC_I_BIT {  	DESC_I_RINT1 = 0x0001,  }; +#define DEFAULT_TRSCER_ERR_MASK (DESC_I_RINT8 | DESC_I_RINT5 | DESC_I_TINT2) +  /* RPADIR */  enum RPADIR_BIT {  	RPADIR_PADS1 = 0x20000, RPADIR_PADS0 = 0x10000, @@ -470,6 +472,9 @@ struct sh_eth_cpu_data {  	unsigned long tx_check;  	unsigned long eesr_err_check; +	/* Error mask */ +	unsigned long trscer_err_mask; +  	/* hardware features */  	unsigned long irq_flags; /* IRQ configuration flags */  	unsigned no_psr:1;	/* EtherC DO NOT have PSR */ diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c index c560f9aeb55d..64d1cef4cda1 100644 --- a/drivers/net/ethernet/ti/cpsw.c +++ b/drivers/net/ethernet/ti/cpsw.c @@ -610,7 +610,7 @@ static void cpsw_set_promiscious(struct net_device *ndev, bool enable)  			/* Clear all mcast from ALE */  			cpsw_ale_flush_multicast(ale, ALE_ALL_PORTS << -						 priv->host_port); +						 priv->host_port, -1);  			/* Flood All Unicast Packets to Host port */  			cpsw_ale_control_set(ale, 0, ALE_P0_UNI_FLOOD, 1); @@ -634,6 +634,12 @@ static void cpsw_set_promiscious(struct net_device *ndev, bool enable)  static void cpsw_ndo_set_rx_mode(struct net_device *ndev)  {  	struct cpsw_priv *priv = netdev_priv(ndev); +	int vid; + +	if (priv->data.dual_emac) +		vid = priv->slaves[priv->emac_port].port_vlan; +	else +		vid = priv->data.default_vlan;  	if (ndev->flags & IFF_PROMISC) {  		/* Enable promiscuous mode */ @@ -649,7 +655,8 @@ static void cpsw_ndo_set_rx_mode(struct net_device *ndev)  	cpsw_ale_set_allmulti(priv->ale, priv->ndev->flags & IFF_ALLMULTI);  	/* Clear all mcast from ALE */ -	cpsw_ale_flush_multicast(priv->ale, ALE_ALL_PORTS << priv->host_port); +	cpsw_ale_flush_multicast(priv->ale, ALE_ALL_PORTS << priv->host_port, +				 vid);  	if (!netdev_mc_empty(ndev)) {  		struct netdev_hw_addr *ha; @@ -757,6 +764,14 @@ requeue:  static irqreturn_t cpsw_interrupt(int irq, void *dev_id)  {  	struct cpsw_priv *priv = dev_id; +	int value = irq - priv->irqs_table[0]; + +	/* NOTICE: Ending IRQ here. The trick with the 'value' variable above +	 * is to make sure we will always write the correct value to the EOI +	 * register. Namely 0 for RX_THRESH Interrupt, 1 for RX Interrupt, 2 +	 * for TX Interrupt and 3 for MISC Interrupt. +	 */ +	cpdma_ctlr_eoi(priv->dma, value);  	cpsw_intr_disable(priv);  	if (priv->irq_enabled == true) { @@ -786,8 +801,6 @@ static int cpsw_poll(struct napi_struct *napi, int budget)  	int			num_tx, num_rx;  	num_tx = cpdma_chan_process(priv->txch, 128); -	if (num_tx) -		cpdma_ctlr_eoi(priv->dma, CPDMA_EOI_TX);  	num_rx = cpdma_chan_process(priv->rxch, budget);  	if (num_rx < budget) { @@ -795,7 +808,6 @@ static int cpsw_poll(struct napi_struct *napi, int budget)  		napi_complete(napi);  		cpsw_intr_enable(priv); -		cpdma_ctlr_eoi(priv->dma, CPDMA_EOI_RX);  		prim_cpsw = cpsw_get_slave_priv(priv, 0);  		if (prim_cpsw->irq_enabled == false) {  			prim_cpsw->irq_enabled = true; @@ -1310,8 +1322,6 @@ static int cpsw_ndo_open(struct net_device *ndev)  	napi_enable(&priv->napi);  	cpdma_ctlr_start(priv->dma);  	cpsw_intr_enable(priv); -	cpdma_ctlr_eoi(priv->dma, CPDMA_EOI_RX); -	cpdma_ctlr_eoi(priv->dma, CPDMA_EOI_TX);  	prim_cpsw = cpsw_get_slave_priv(priv, 0);  	if (prim_cpsw->irq_enabled == false) { @@ -1578,9 +1588,6 @@ static void cpsw_ndo_tx_timeout(struct net_device *ndev)  	cpdma_chan_start(priv->txch);  	cpdma_ctlr_int_ctrl(priv->dma, true);  	cpsw_intr_enable(priv); -	cpdma_ctlr_eoi(priv->dma, CPDMA_EOI_RX); -	cpdma_ctlr_eoi(priv->dma, CPDMA_EOI_TX); -  }  static int cpsw_ndo_set_mac_address(struct net_device *ndev, void *p) @@ -1620,9 +1627,6 @@ static void cpsw_ndo_poll_controller(struct net_device *ndev)  	cpsw_interrupt(ndev->irq, priv);  	cpdma_ctlr_int_ctrl(priv->dma, true);  	cpsw_intr_enable(priv); -	cpdma_ctlr_eoi(priv->dma, CPDMA_EOI_RX); -	cpdma_ctlr_eoi(priv->dma, CPDMA_EOI_TX); -  }  #endif diff --git a/drivers/net/ethernet/ti/cpsw_ale.c b/drivers/net/ethernet/ti/cpsw_ale.c index 097ebe7077ac..5246b3a18ff8 100644 --- a/drivers/net/ethernet/ti/cpsw_ale.c +++ b/drivers/net/ethernet/ti/cpsw_ale.c @@ -234,7 +234,7 @@ static void cpsw_ale_flush_mcast(struct cpsw_ale *ale, u32 *ale_entry,  		cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_FREE);  } -int cpsw_ale_flush_multicast(struct cpsw_ale *ale, int port_mask) +int cpsw_ale_flush_multicast(struct cpsw_ale *ale, int port_mask, int vid)  {  	u32 ale_entry[ALE_ENTRY_WORDS];  	int ret, idx; @@ -245,6 +245,14 @@ int cpsw_ale_flush_multicast(struct cpsw_ale *ale, int port_mask)  		if (ret != ALE_TYPE_ADDR && ret != ALE_TYPE_VLAN_ADDR)  			continue; +		/* if vid passed is -1 then remove all multicast entry from +		 * the table irrespective of vlan id, if a valid vlan id is +		 * passed then remove only multicast added to that vlan id. +		 * if vlan id doesn't match then move on to next entry. +		 */ +		if (vid != -1 && cpsw_ale_get_vlan_id(ale_entry) != vid) +			continue; +  		if (cpsw_ale_get_mcast(ale_entry)) {  			u8 addr[6]; diff --git a/drivers/net/ethernet/ti/cpsw_ale.h b/drivers/net/ethernet/ti/cpsw_ale.h index c0d4127aa549..af1e7ecd87c6 100644 --- a/drivers/net/ethernet/ti/cpsw_ale.h +++ b/drivers/net/ethernet/ti/cpsw_ale.h @@ -92,7 +92,7 @@ void cpsw_ale_stop(struct cpsw_ale *ale);  int cpsw_ale_set_ageout(struct cpsw_ale *ale, int ageout);  int cpsw_ale_flush(struct cpsw_ale *ale, int port_mask); -int cpsw_ale_flush_multicast(struct cpsw_ale *ale, int port_mask); +int cpsw_ale_flush_multicast(struct cpsw_ale *ale, int port_mask, int vid);  int cpsw_ale_add_ucast(struct cpsw_ale *ale, u8 *addr, int port,  		       int flags, u16 vid);  int cpsw_ale_del_ucast(struct cpsw_ale *ale, u8 *addr, int port, diff --git a/drivers/net/ethernet/xilinx/ll_temac_main.c b/drivers/net/ethernet/xilinx/ll_temac_main.c index 9c2d91ea0af4..dbcbf0c5bcfa 100644 --- a/drivers/net/ethernet/xilinx/ll_temac_main.c +++ b/drivers/net/ethernet/xilinx/ll_temac_main.c @@ -1043,6 +1043,7 @@ static int temac_of_probe(struct platform_device *op)  	lp->regs = of_iomap(op->dev.of_node, 0);  	if (!lp->regs) {  		dev_err(&op->dev, "could not map temac regs.\n"); +		rc = -ENOMEM;  		goto nodev;  	} @@ -1062,6 +1063,7 @@ static int temac_of_probe(struct platform_device *op)  	np = of_parse_phandle(op->dev.of_node, "llink-connected", 0);  	if (!np) {  		dev_err(&op->dev, "could not find DMA node\n"); +		rc = -ENODEV;  		goto err_iounmap;  	} diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c index c18a0c637c44..a6d2860b712c 100644 --- a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c +++ b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c @@ -1501,6 +1501,7 @@ static int axienet_of_probe(struct platform_device *op)  	lp->regs = of_iomap(op->dev.of_node, 0);  	if (!lp->regs) {  		dev_err(&op->dev, "could not map Axi Ethernet regs.\n"); +		ret = -ENOMEM;  		goto nodev;  	}  	/* Setup checksum offload, but default to off if not specified */ @@ -1563,6 +1564,7 @@ static int axienet_of_probe(struct platform_device *op)  	np = of_parse_phandle(op->dev.of_node, "axistream-connected", 0);  	if (!np) {  		dev_err(&op->dev, "could not find DMA node\n"); +		ret = -ENODEV;  		goto err_iounmap;  	}  	lp->dma_regs = of_iomap(np, 0); diff --git a/drivers/net/ethernet/xilinx/xilinx_emaclite.c b/drivers/net/ethernet/xilinx/xilinx_emaclite.c index 24858799c204..9d4ce388510a 100644 --- a/drivers/net/ethernet/xilinx/xilinx_emaclite.c +++ b/drivers/net/ethernet/xilinx/xilinx_emaclite.c @@ -1109,6 +1109,7 @@ static int xemaclite_of_probe(struct platform_device *ofdev)  	res = platform_get_resource(ofdev, IORESOURCE_IRQ, 0);  	if (!res) {  		dev_err(dev, "no IRQ found\n"); +		rc = -ENXIO;  		goto error;  	} diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c index 93e224217e24..f7ff493f1e73 100644 --- a/drivers/net/team/team.c +++ b/drivers/net/team/team.c @@ -629,6 +629,7 @@ static int team_change_mode(struct team *team, const char *kind)  static void team_notify_peers_work(struct work_struct *work)  {  	struct team *team; +	int val;  	team = container_of(work, struct team, notify_peers.dw.work); @@ -636,9 +637,14 @@ static void team_notify_peers_work(struct work_struct *work)  		schedule_delayed_work(&team->notify_peers.dw, 0);  		return;  	} +	val = atomic_dec_if_positive(&team->notify_peers.count_pending); +	if (val < 0) { +		rtnl_unlock(); +		return; +	}  	call_netdevice_notifiers(NETDEV_NOTIFY_PEERS, team->dev);  	rtnl_unlock(); -	if (!atomic_dec_and_test(&team->notify_peers.count_pending)) +	if (val)  		schedule_delayed_work(&team->notify_peers.dw,  				      msecs_to_jiffies(team->notify_peers.interval));  } @@ -669,6 +675,7 @@ static void team_notify_peers_fini(struct team *team)  static void team_mcast_rejoin_work(struct work_struct *work)  {  	struct team *team; +	int val;  	team = container_of(work, struct team, mcast_rejoin.dw.work); @@ -676,9 +683,14 @@ static void team_mcast_rejoin_work(struct work_struct *work)  		schedule_delayed_work(&team->mcast_rejoin.dw, 0);  		return;  	} +	val = atomic_dec_if_positive(&team->mcast_rejoin.count_pending); +	if (val < 0) { +		rtnl_unlock(); +		return; +	}  	call_netdevice_notifiers(NETDEV_RESEND_IGMP, team->dev);  	rtnl_unlock(); -	if (!atomic_dec_and_test(&team->mcast_rejoin.count_pending)) +	if (val)  		schedule_delayed_work(&team->mcast_rejoin.dw,  				      msecs_to_jiffies(team->mcast_rejoin.interval));  } diff --git a/drivers/net/usb/kaweth.c b/drivers/net/usb/kaweth.c index dcb6d33141e0..1e9cdca37014 100644 --- a/drivers/net/usb/kaweth.c +++ b/drivers/net/usb/kaweth.c @@ -1276,7 +1276,7 @@ static int usb_start_wait_urb(struct urb *urb, int timeout, int* actual_length)          awd.done = 0;          urb->context = &awd; -        status = usb_submit_urb(urb, GFP_NOIO); +        status = usb_submit_urb(urb, GFP_ATOMIC);          if (status) {                  // something went wrong                  usb_free_urb(urb); diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c index b8a82b86f909..602dc6668c3a 100644 --- a/drivers/net/usb/qmi_wwan.c +++ b/drivers/net/usb/qmi_wwan.c @@ -56,6 +56,8 @@ struct qmi_wwan_state {  /* default ethernet address used by the modem */  static const u8 default_modem_addr[ETH_ALEN] = {0x02, 0x50, 0xf3}; +static const u8 buggy_fw_addr[ETH_ALEN] = {0x00, 0xa0, 0xc6, 0x00, 0x00, 0x00}; +  /* Make up an ethernet header if the packet doesn't have one.   *   * A firmware bug common among several devices cause them to send raw @@ -332,10 +334,12 @@ next_desc:  		usb_driver_release_interface(driver, info->data);  	} -	/* Never use the same address on both ends of the link, even -	 * if the buggy firmware told us to. +	/* Never use the same address on both ends of the link, even if the +	 * buggy firmware told us to. Or, if device is assigned the well-known +	 * buggy firmware MAC address, replace it with a random address,  	 */ -	if (ether_addr_equal(dev->net->dev_addr, default_modem_addr)) +	if (ether_addr_equal(dev->net->dev_addr, default_modem_addr) || +	    ether_addr_equal(dev->net->dev_addr, buggy_fw_addr))  		eth_hw_addr_random(dev->net);  	/* make MAC addr easily distinguishable from an IP header */ diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c index 2d1c77e81836..57ec23e8ccfa 100644 --- a/drivers/net/usb/r8152.c +++ b/drivers/net/usb/r8152.c @@ -1897,6 +1897,22 @@ static void _rtl8152_set_rx_mode(struct net_device *netdev)  	netif_wake_queue(netdev);  } +static netdev_features_t +rtl8152_features_check(struct sk_buff *skb, struct net_device *dev, +		       netdev_features_t features) +{ +	u32 mss = skb_shinfo(skb)->gso_size; +	int max_offset = mss ? GTTCPHO_MAX : TCPHO_MAX; +	int offset = skb_transport_offset(skb); + +	if ((mss || skb->ip_summed == CHECKSUM_PARTIAL) && offset > max_offset) +		features &= ~(NETIF_F_ALL_CSUM | NETIF_F_GSO_MASK); +	else if ((skb->len + sizeof(struct tx_desc)) > agg_buf_sz) +		features &= ~NETIF_F_GSO_MASK; + +	return features; +} +  static netdev_tx_t rtl8152_start_xmit(struct sk_buff *skb,  				      struct net_device *netdev)  { @@ -3706,6 +3722,7 @@ static const struct net_device_ops rtl8152_netdev_ops = {  	.ndo_set_mac_address	= rtl8152_set_mac_address,  	.ndo_change_mtu		= rtl8152_change_mtu,  	.ndo_validate_addr	= eth_validate_addr, +	.ndo_features_check	= rtl8152_features_check,  };  static void r8152b_get_version(struct r8152 *tp) diff --git a/drivers/net/wireless/iwlwifi/iwl-7000.c b/drivers/net/wireless/iwlwifi/iwl-7000.c index e5be2d21868f..a5f9198d5747 100644 --- a/drivers/net/wireless/iwlwifi/iwl-7000.c +++ b/drivers/net/wireless/iwlwifi/iwl-7000.c @@ -69,8 +69,8 @@  #include "iwl-agn-hw.h"  /* Highest firmware API version supported */ -#define IWL7260_UCODE_API_MAX	10 -#define IWL3160_UCODE_API_MAX	10 +#define IWL7260_UCODE_API_MAX	12 +#define IWL3160_UCODE_API_MAX	12  /* Oldest version we won't warn about */  #define IWL7260_UCODE_API_OK	10 @@ -105,7 +105,7 @@  #define IWL7265_MODULE_FIRMWARE(api) IWL7265_FW_PRE __stringify(api) ".ucode"  #define IWL7265D_FW_PRE "iwlwifi-7265D-" -#define IWL7265D_MODULE_FIRMWARE(api) IWL7265_FW_PRE __stringify(api) ".ucode" +#define IWL7265D_MODULE_FIRMWARE(api) IWL7265D_FW_PRE __stringify(api) ".ucode"  #define NVM_HW_SECTION_NUM_FAMILY_7000		0 diff --git a/drivers/net/wireless/iwlwifi/iwl-8000.c b/drivers/net/wireless/iwlwifi/iwl-8000.c index bf0a95cb7153..3668fc57e770 100644 --- a/drivers/net/wireless/iwlwifi/iwl-8000.c +++ b/drivers/net/wireless/iwlwifi/iwl-8000.c @@ -69,7 +69,7 @@  #include "iwl-agn-hw.h"  /* Highest firmware API version supported */ -#define IWL8000_UCODE_API_MAX	10 +#define IWL8000_UCODE_API_MAX	12  /* Oldest version we won't warn about */  #define IWL8000_UCODE_API_OK	10 diff --git a/drivers/net/wireless/iwlwifi/iwl-fw-file.h b/drivers/net/wireless/iwlwifi/iwl-fw-file.h index f2a047f6bb3e..1bbe4fc47b97 100644 --- a/drivers/net/wireless/iwlwifi/iwl-fw-file.h +++ b/drivers/net/wireless/iwlwifi/iwl-fw-file.h @@ -243,6 +243,9 @@ enum iwl_ucode_tlv_flag {   * @IWL_UCODE_TLV_API_SF_NO_DUMMY_NOTIF: ucode supports disabling dummy notif.   * @IWL_UCODE_TLV_API_FRAGMENTED_SCAN: This ucode supports active dwell time   *	longer than the passive one, which is essential for fragmented scan. + * @IWL_UCODE_TLV_API_BASIC_DWELL: use only basic dwell time in scan command, + *	regardless of the band or the number of the probes. FW will calculate + *	the actual dwell time.   */  enum iwl_ucode_tlv_api {  	IWL_UCODE_TLV_API_WOWLAN_CONFIG_TID	= BIT(0), @@ -253,6 +256,7 @@ enum iwl_ucode_tlv_api {  	IWL_UCODE_TLV_API_LMAC_SCAN		= BIT(6),  	IWL_UCODE_TLV_API_SF_NO_DUMMY_NOTIF	= BIT(7),  	IWL_UCODE_TLV_API_FRAGMENTED_SCAN	= BIT(8), +	IWL_UCODE_TLV_API_BASIC_DWELL		= BIT(13),  };  /** diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h index 1f2acf47bfb2..201846de94e7 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h +++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h @@ -672,6 +672,7 @@ struct iwl_scan_channel_opt {   * @IWL_MVM_LMAC_SCAN_FLAG_FRAGMENTED: all passive scans will be fragmented   * @IWL_MVM_LMAC_SCAN_FLAGS_RRM_ENABLED: insert WFA vendor-specific TPC report   *	and DS parameter set IEs into probe requests. + * @IWL_MVM_LMAC_SCAN_FLAG_MATCH: Send match found notification on matches   */  enum iwl_mvm_lmac_scan_flags {  	IWL_MVM_LMAC_SCAN_FLAG_PASS_ALL		= BIT(0), @@ -681,6 +682,7 @@ enum iwl_mvm_lmac_scan_flags {  	IWL_MVM_LMAC_SCAN_FLAG_MULTIPLE_SSIDS	= BIT(4),  	IWL_MVM_LMAC_SCAN_FLAG_FRAGMENTED	= BIT(5),  	IWL_MVM_LMAC_SCAN_FLAGS_RRM_ENABLED	= BIT(6), +	IWL_MVM_LMAC_SCAN_FLAG_MATCH		= BIT(9),  };  enum iwl_scan_priority { diff --git a/drivers/net/wireless/iwlwifi/mvm/scan.c b/drivers/net/wireless/iwlwifi/mvm/scan.c index e5294d01181e..ec9a8e7bae1d 100644 --- a/drivers/net/wireless/iwlwifi/mvm/scan.c +++ b/drivers/net/wireless/iwlwifi/mvm/scan.c @@ -171,15 +171,21 @@ static void iwl_mvm_scan_fill_ssids(struct iwl_ssid_ie *cmd_ssid,   * already included in the probe template, so we need to set only   * req->n_ssids - 1 bits in addition to the first bit.   */ -static u16 iwl_mvm_get_active_dwell(enum ieee80211_band band, int n_ssids) +static u16 iwl_mvm_get_active_dwell(struct iwl_mvm *mvm, +				    enum ieee80211_band band, int n_ssids)  { +	if (mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_BASIC_DWELL) +		return 10;  	if (band == IEEE80211_BAND_2GHZ)  		return 20  + 3 * (n_ssids + 1);  	return 10  + 2 * (n_ssids + 1);  } -static u16 iwl_mvm_get_passive_dwell(enum ieee80211_band band) +static u16 iwl_mvm_get_passive_dwell(struct iwl_mvm *mvm, +				     enum ieee80211_band band)  { +	if (mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_BASIC_DWELL) +			return 110;  	return band == IEEE80211_BAND_2GHZ ? 100 + 20 : 100 + 10;  } @@ -331,7 +337,8 @@ static void iwl_mvm_scan_calc_params(struct iwl_mvm *mvm,  		 */  		if (vif->type == NL80211_IFTYPE_P2P_DEVICE) {  			u32 passive_dwell = -				iwl_mvm_get_passive_dwell(IEEE80211_BAND_2GHZ); +				iwl_mvm_get_passive_dwell(mvm, +							  IEEE80211_BAND_2GHZ);  			params->max_out_time = passive_dwell;  		} else {  			params->passive_fragmented = true; @@ -348,8 +355,8 @@ not_bound:  			params->dwell[band].passive = frag_passive_dwell;  		else  			params->dwell[band].passive = -				iwl_mvm_get_passive_dwell(band); -		params->dwell[band].active = iwl_mvm_get_active_dwell(band, +				iwl_mvm_get_passive_dwell(mvm, band); +		params->dwell[band].active = iwl_mvm_get_active_dwell(mvm, band,  								      n_ssids);  	}  } @@ -1448,6 +1455,8 @@ int iwl_mvm_unified_sched_scan_lmac(struct iwl_mvm *mvm,  	if (iwl_mvm_scan_pass_all(mvm, req))  		flags |= IWL_MVM_LMAC_SCAN_FLAG_PASS_ALL; +	else +		flags |= IWL_MVM_LMAC_SCAN_FLAG_MATCH;  	if (req->n_ssids == 1 && req->ssids[0].ssid_len != 0)  		flags |= IWL_MVM_LMAC_SCAN_FLAG_PRE_CONNECTION; diff --git a/drivers/net/wireless/iwlwifi/mvm/tx.c b/drivers/net/wireless/iwlwifi/mvm/tx.c index 4f15d9decc81..4333306ccdee 100644 --- a/drivers/net/wireless/iwlwifi/mvm/tx.c +++ b/drivers/net/wireless/iwlwifi/mvm/tx.c @@ -108,8 +108,12 @@ void iwl_mvm_set_tx_cmd(struct iwl_mvm *mvm, struct sk_buff *skb,  			tx_flags &= ~TX_CMD_FLG_SEQ_CTL;  	} -	/* tid_tspec will default to 0 = BE when QOS isn't enabled */ -	ac = tid_to_mac80211_ac[tx_cmd->tid_tspec]; +	/* Default to 0 (BE) when tid_spec is set to IWL_TID_NON_QOS */ +	if (tx_cmd->tid_tspec < IWL_MAX_TID_COUNT) +		ac = tid_to_mac80211_ac[tx_cmd->tid_tspec]; +	else +		ac = tid_to_mac80211_ac[0]; +  	tx_flags |= iwl_mvm_bt_coex_tx_prio(mvm, hdr, info, ac) <<  			TX_CMD_FLG_BT_PRIO_POS; diff --git a/drivers/net/wireless/iwlwifi/mvm/utils.c b/drivers/net/wireless/iwlwifi/mvm/utils.c index e56e77ef5d2e..917431e30f74 100644 --- a/drivers/net/wireless/iwlwifi/mvm/utils.c +++ b/drivers/net/wireless/iwlwifi/mvm/utils.c @@ -665,7 +665,7 @@ bool iwl_mvm_rx_diversity_allowed(struct iwl_mvm *mvm)  	if (num_of_ant(mvm->fw->valid_rx_ant) == 1)  		return false; -	if (!mvm->cfg->rx_with_siso_diversity) +	if (mvm->cfg->rx_with_siso_diversity)  		return false;  	ieee80211_iterate_active_interfaces_atomic( diff --git a/drivers/net/wireless/iwlwifi/pcie/drv.c b/drivers/net/wireless/iwlwifi/pcie/drv.c index 2f0c4b170344..d5aadb00dd9e 100644 --- a/drivers/net/wireless/iwlwifi/pcie/drv.c +++ b/drivers/net/wireless/iwlwifi/pcie/drv.c @@ -527,8 +527,10 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)  	else if (cfg == &iwl7265_n_cfg)  		cfg_7265d = &iwl7265d_n_cfg;  	if (cfg_7265d && -	    (iwl_trans->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_7265D) +	    (iwl_trans->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_7265D) {  		cfg = cfg_7265d; +		iwl_trans->cfg = cfg_7265d; +	}  #endif  	pci_set_drvdata(pdev, iwl_trans); diff --git a/drivers/net/wireless/rtlwifi/pci.c b/drivers/net/wireless/rtlwifi/pci.c index 846a2e6e34d8..c70efb9a6e78 100644 --- a/drivers/net/wireless/rtlwifi/pci.c +++ b/drivers/net/wireless/rtlwifi/pci.c @@ -666,7 +666,8 @@ tx_status_ok:  }  static int _rtl_pci_init_one_rxdesc(struct ieee80211_hw *hw, -				    u8 *entry, int rxring_idx, int desc_idx) +				    struct sk_buff *new_skb, u8 *entry, +				    int rxring_idx, int desc_idx)  {  	struct rtl_priv *rtlpriv = rtl_priv(hw);  	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); @@ -674,11 +675,15 @@ static int _rtl_pci_init_one_rxdesc(struct ieee80211_hw *hw,  	u8 tmp_one = 1;  	struct sk_buff *skb; +	if (likely(new_skb)) { +		skb = new_skb; +		goto remap; +	}  	skb = dev_alloc_skb(rtlpci->rxbuffersize);  	if (!skb)  		return 0; -	rtlpci->rx_ring[rxring_idx].rx_buf[desc_idx] = skb; +remap:  	/* just set skb->cb to mapping addr for pci_unmap_single use */  	*((dma_addr_t *)skb->cb) =  		pci_map_single(rtlpci->pdev, skb_tail_pointer(skb), @@ -686,6 +691,7 @@ static int _rtl_pci_init_one_rxdesc(struct ieee80211_hw *hw,  	bufferaddress = *((dma_addr_t *)skb->cb);  	if (pci_dma_mapping_error(rtlpci->pdev, bufferaddress))  		return 0; +	rtlpci->rx_ring[rxring_idx].rx_buf[desc_idx] = skb;  	if (rtlpriv->use_new_trx_flow) {  		rtlpriv->cfg->ops->set_desc(hw, (u8 *)entry, false,  					    HW_DESC_RX_PREPARE, @@ -781,6 +787,7 @@ static void _rtl_pci_rx_interrupt(struct ieee80211_hw *hw)  		/*rx pkt */  		struct sk_buff *skb = rtlpci->rx_ring[rxring_idx].rx_buf[  				      rtlpci->rx_ring[rxring_idx].idx]; +		struct sk_buff *new_skb;  		if (rtlpriv->use_new_trx_flow) {  			rx_remained_cnt = @@ -807,6 +814,13 @@ static void _rtl_pci_rx_interrupt(struct ieee80211_hw *hw)  		pci_unmap_single(rtlpci->pdev, *((dma_addr_t *)skb->cb),  				 rtlpci->rxbuffersize, PCI_DMA_FROMDEVICE); +		/* get a new skb - if fail, old one will be reused */ +		new_skb = dev_alloc_skb(rtlpci->rxbuffersize); +		if (unlikely(!new_skb)) { +			pr_err("Allocation of new skb failed in %s\n", +			       __func__); +			goto no_new; +		}  		if (rtlpriv->use_new_trx_flow) {  			buffer_desc =  			  &rtlpci->rx_ring[rxring_idx].buffer_desc @@ -911,14 +925,16 @@ static void _rtl_pci_rx_interrupt(struct ieee80211_hw *hw)  			schedule_work(&rtlpriv->works.lps_change_work);  		}  end: +		skb = new_skb; +no_new:  		if (rtlpriv->use_new_trx_flow) { -			_rtl_pci_init_one_rxdesc(hw, (u8 *)buffer_desc, +			_rtl_pci_init_one_rxdesc(hw, skb, (u8 *)buffer_desc,  						 rxring_idx, -					       rtlpci->rx_ring[rxring_idx].idx); +						 rtlpci->rx_ring[rxring_idx].idx);  		} else { -			_rtl_pci_init_one_rxdesc(hw, (u8 *)pdesc, rxring_idx, +			_rtl_pci_init_one_rxdesc(hw, skb, (u8 *)pdesc, +						 rxring_idx,  						 rtlpci->rx_ring[rxring_idx].idx); -  			if (rtlpci->rx_ring[rxring_idx].idx ==  			    rtlpci->rxringcount - 1)  				rtlpriv->cfg->ops->set_desc(hw, (u8 *)pdesc, @@ -1307,7 +1323,7 @@ static int _rtl_pci_init_rx_ring(struct ieee80211_hw *hw, int rxring_idx)  		rtlpci->rx_ring[rxring_idx].idx = 0;  		for (i = 0; i < rtlpci->rxringcount; i++) {  			entry = &rtlpci->rx_ring[rxring_idx].buffer_desc[i]; -			if (!_rtl_pci_init_one_rxdesc(hw, (u8 *)entry, +			if (!_rtl_pci_init_one_rxdesc(hw, NULL, (u8 *)entry,  						      rxring_idx, i))  				return -ENOMEM;  		} @@ -1332,7 +1348,7 @@ static int _rtl_pci_init_rx_ring(struct ieee80211_hw *hw, int rxring_idx)  		for (i = 0; i < rtlpci->rxringcount; i++) {  			entry = &rtlpci->rx_ring[rxring_idx].desc[i]; -			if (!_rtl_pci_init_one_rxdesc(hw, (u8 *)entry, +			if (!_rtl_pci_init_one_rxdesc(hw, NULL, (u8 *)entry,  						      rxring_idx, i))  				return -ENOMEM;  		} diff --git a/drivers/net/xen-netback/xenbus.c b/drivers/net/xen-netback/xenbus.c index efbaf2ae1999..794204e34fba 100644 --- a/drivers/net/xen-netback/xenbus.c +++ b/drivers/net/xen-netback/xenbus.c @@ -737,6 +737,7 @@ static void connect(struct backend_info *be)  		}  		queue->remaining_credit = credit_bytes; +		queue->credit_usec = credit_usec;  		err = connect_rings(be, queue);  		if (err) { diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c index 22bcb4e12e2a..d8c10764f130 100644 --- a/drivers/net/xen-netfront.c +++ b/drivers/net/xen-netfront.c @@ -88,10 +88,8 @@ struct netfront_cb {  #define IRQ_NAME_SIZE (QUEUE_NAME_SIZE + 3)  struct netfront_stats { -	u64			rx_packets; -	u64			tx_packets; -	u64			rx_bytes; -	u64			tx_bytes; +	u64			packets; +	u64			bytes;  	struct u64_stats_sync	syncp;  }; @@ -160,7 +158,8 @@ struct netfront_info {  	struct netfront_queue *queues;  	/* Statistics */ -	struct netfront_stats __percpu *stats; +	struct netfront_stats __percpu *rx_stats; +	struct netfront_stats __percpu *tx_stats;  	atomic_t rx_gso_checksum_fixup;  }; @@ -565,7 +564,7 @@ static int xennet_start_xmit(struct sk_buff *skb, struct net_device *dev)  {  	unsigned short id;  	struct netfront_info *np = netdev_priv(dev); -	struct netfront_stats *stats = this_cpu_ptr(np->stats); +	struct netfront_stats *tx_stats = this_cpu_ptr(np->tx_stats);  	struct xen_netif_tx_request *tx;  	char *data = skb->data;  	RING_IDX i; @@ -672,10 +671,10 @@ static int xennet_start_xmit(struct sk_buff *skb, struct net_device *dev)  	if (notify)  		notify_remote_via_irq(queue->tx_irq); -	u64_stats_update_begin(&stats->syncp); -	stats->tx_bytes += skb->len; -	stats->tx_packets++; -	u64_stats_update_end(&stats->syncp); +	u64_stats_update_begin(&tx_stats->syncp); +	tx_stats->bytes += skb->len; +	tx_stats->packets++; +	u64_stats_update_end(&tx_stats->syncp);  	/* Note: It is not safe to access skb after xennet_tx_buf_gc()! */  	xennet_tx_buf_gc(queue); @@ -931,7 +930,7 @@ static int checksum_setup(struct net_device *dev, struct sk_buff *skb)  static int handle_incoming_queue(struct netfront_queue *queue,  				 struct sk_buff_head *rxq)  { -	struct netfront_stats *stats = this_cpu_ptr(queue->info->stats); +	struct netfront_stats *rx_stats = this_cpu_ptr(queue->info->rx_stats);  	int packets_dropped = 0;  	struct sk_buff *skb; @@ -952,10 +951,10 @@ static int handle_incoming_queue(struct netfront_queue *queue,  			continue;  		} -		u64_stats_update_begin(&stats->syncp); -		stats->rx_packets++; -		stats->rx_bytes += skb->len; -		u64_stats_update_end(&stats->syncp); +		u64_stats_update_begin(&rx_stats->syncp); +		rx_stats->packets++; +		rx_stats->bytes += skb->len; +		u64_stats_update_end(&rx_stats->syncp);  		/* Pass it up. */  		napi_gro_receive(&queue->napi, skb); @@ -1079,18 +1078,22 @@ static struct rtnl_link_stats64 *xennet_get_stats64(struct net_device *dev,  	int cpu;  	for_each_possible_cpu(cpu) { -		struct netfront_stats *stats = per_cpu_ptr(np->stats, cpu); +		struct netfront_stats *rx_stats = per_cpu_ptr(np->rx_stats, cpu); +		struct netfront_stats *tx_stats = per_cpu_ptr(np->tx_stats, cpu);  		u64 rx_packets, rx_bytes, tx_packets, tx_bytes;  		unsigned int start;  		do { -			start = u64_stats_fetch_begin_irq(&stats->syncp); +			start = u64_stats_fetch_begin_irq(&tx_stats->syncp); +			tx_packets = tx_stats->packets; +			tx_bytes = tx_stats->bytes; +		} while (u64_stats_fetch_retry_irq(&tx_stats->syncp, start)); -			rx_packets = stats->rx_packets; -			tx_packets = stats->tx_packets; -			rx_bytes = stats->rx_bytes; -			tx_bytes = stats->tx_bytes; -		} while (u64_stats_fetch_retry_irq(&stats->syncp, start)); +		do { +			start = u64_stats_fetch_begin_irq(&rx_stats->syncp); +			rx_packets = rx_stats->packets; +			rx_bytes = rx_stats->bytes; +		} while (u64_stats_fetch_retry_irq(&rx_stats->syncp, start));  		tot->rx_packets += rx_packets;  		tot->tx_packets += tx_packets; @@ -1275,6 +1278,15 @@ static const struct net_device_ops xennet_netdev_ops = {  #endif  }; +static void xennet_free_netdev(struct net_device *netdev) +{ +	struct netfront_info *np = netdev_priv(netdev); + +	free_percpu(np->rx_stats); +	free_percpu(np->tx_stats); +	free_netdev(netdev); +} +  static struct net_device *xennet_create_dev(struct xenbus_device *dev)  {  	int err; @@ -1295,8 +1307,11 @@ static struct net_device *xennet_create_dev(struct xenbus_device *dev)  	np->queues = NULL;  	err = -ENOMEM; -	np->stats = netdev_alloc_pcpu_stats(struct netfront_stats); -	if (np->stats == NULL) +	np->rx_stats = netdev_alloc_pcpu_stats(struct netfront_stats); +	if (np->rx_stats == NULL) +		goto exit; +	np->tx_stats = netdev_alloc_pcpu_stats(struct netfront_stats); +	if (np->tx_stats == NULL)  		goto exit;  	netdev->netdev_ops	= &xennet_netdev_ops; @@ -1327,7 +1342,7 @@ static struct net_device *xennet_create_dev(struct xenbus_device *dev)  	return netdev;   exit: -	free_netdev(netdev); +	xennet_free_netdev(netdev);  	return ERR_PTR(err);  } @@ -1369,7 +1384,7 @@ static int netfront_probe(struct xenbus_device *dev,  	return 0;   fail: -	free_netdev(netdev); +	xennet_free_netdev(netdev);  	dev_set_drvdata(&dev->dev, NULL);  	return err;  } @@ -2189,9 +2204,7 @@ static int xennet_remove(struct xenbus_device *dev)  		info->queues = NULL;  	} -	free_percpu(info->stats); - -	free_netdev(info->netdev); +	xennet_free_netdev(info->netdev);  	return 0;  } | 
