diff options
Diffstat (limited to 'drivers/net')
| -rw-r--r-- | drivers/net/Kconfig | 2 | ||||
| -rw-r--r-- | drivers/net/benet/be.h | 1 | ||||
| -rw-r--r-- | drivers/net/benet/be_main.c | 60 | ||||
| -rw-r--r-- | drivers/net/bnx2.c | 12 | ||||
| -rw-r--r-- | drivers/net/bonding/bond_main.c | 25 | ||||
| -rw-r--r-- | drivers/net/dm9000.c | 6 | ||||
| -rw-r--r-- | drivers/net/dnet.c | 6 | ||||
| -rw-r--r-- | drivers/net/sh_eth.c | 20 | ||||
| -rw-r--r-- | drivers/net/sh_eth.h | 4 | ||||
| -rw-r--r-- | drivers/net/smsc911x.c | 4 | ||||
| -rw-r--r-- | drivers/net/sungem.c | 9 | ||||
| -rw-r--r-- | drivers/net/tulip/tulip_core.c | 45 | ||||
| -rw-r--r-- | drivers/net/ucc_geth.c | 34 | ||||
| -rw-r--r-- | drivers/net/ucc_geth.h | 3 | ||||
| -rw-r--r-- | drivers/net/virtio_net.c | 3 | ||||
| -rw-r--r-- | drivers/net/wireless/ath9k/ath9k.h | 4 | ||||
| -rw-r--r-- | drivers/net/wireless/ath9k/core.h | 33 | ||||
| -rw-r--r-- | drivers/net/wireless/ath9k/hw.c | 22 | ||||
| -rw-r--r-- | drivers/net/wireless/ath9k/main.c | 1 | ||||
| -rw-r--r-- | drivers/net/wireless/zd1211rw/zd_mac.c | 8 | 
20 files changed, 202 insertions, 100 deletions
| diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 435e2e3a82c..62d732a886f 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -1042,7 +1042,7 @@ config NI65  config DNET  	tristate "Dave ethernet support (DNET)" -	depends on NET_ETHERNET +	depends on NET_ETHERNET && HAS_IOMEM  	select PHYLIB  	help  	  The Dave ethernet interface (DNET) is found on Qong Board FPGA. diff --git a/drivers/net/benet/be.h b/drivers/net/benet/be.h index 63d593d5315..f327be57ca9 100644 --- a/drivers/net/benet/be.h +++ b/drivers/net/benet/be.h @@ -194,6 +194,7 @@ struct be_adapter {  	struct be_eq_obj rx_eq;  	struct be_rx_obj rx_obj;  	u32 big_page_size;	/* Compounded page size shared by rx wrbs */ +	bool rx_post_starved;	/* Zero rx frags have been posted to BE */  	struct vlan_group *vlan_grp;  	u16 num_vlans; diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c index 897a63de5bd..0ecaffb70e5 100644 --- a/drivers/net/benet/be_main.c +++ b/drivers/net/benet/be_main.c @@ -273,26 +273,6 @@ static void be_rx_eqd_update(struct be_adapter *adapter)  	rx_eq->cur_eqd = eqd;  } -static void be_worker(struct work_struct *work) -{ -	struct be_adapter *adapter = -		container_of(work, struct be_adapter, work.work); -	int status; - -	/* Check link */ -	be_link_status_update(adapter); - -	/* Get Stats */ -	status = be_cmd_get_stats(&adapter->ctrl, &adapter->stats.cmd); -	if (!status) -		netdev_stats_update(adapter); - -	/* Set EQ delay */ -	be_rx_eqd_update(adapter); - -	schedule_delayed_work(&adapter->work, msecs_to_jiffies(1000)); -} -  static struct net_device_stats *be_get_stats(struct net_device *dev)  {  	struct be_adapter *adapter = netdev_priv(dev); @@ -493,7 +473,7 @@ static int be_change_mtu(struct net_device *netdev, int new_mtu)   * program them in BE.  If more than BE_NUM_VLANS_SUPPORTED are configured,   * set the BE in promiscuous VLAN mode.   */ -static void be_vids_config(struct net_device *netdev) +static void be_vid_config(struct net_device *netdev)  {  	struct be_adapter *adapter = netdev_priv(netdev);  	u16 vtag[BE_NUM_VLANS_SUPPORTED]; @@ -536,7 +516,7 @@ static void be_vlan_add_vid(struct net_device *netdev, u16 vid)  	adapter->num_vlans++;  	adapter->vlan_tag[vid] = 1; -	be_vids_config(netdev); +	be_vid_config(netdev);  }  static void be_vlan_rem_vid(struct net_device *netdev, u16 vid) @@ -547,7 +527,7 @@ static void be_vlan_rem_vid(struct net_device *netdev, u16 vid)  	adapter->vlan_tag[vid] = 0;  	vlan_group_set_device(adapter->vlan_grp, vid, NULL); -	be_vids_config(netdev); +	be_vid_config(netdev);  }  static void be_set_multicast_filter(struct net_device *netdev) @@ -900,8 +880,11 @@ static void be_post_rx_frags(struct be_adapter *adapter)  		page_info->last_page_user = true;  	if (posted) { -		be_rxq_notify(&adapter->ctrl, rxq->id, posted);  		atomic_add(posted, &rxq->used); +		be_rxq_notify(&adapter->ctrl, rxq->id, posted); +	} else if (atomic_read(&rxq->used) == 0) { +		/* Let be_worker replenish when memory is available */ +		adapter->rx_post_starved = true;  	}  	return; @@ -1305,6 +1288,31 @@ int be_poll_tx(struct napi_struct *napi, int budget)  	return 1;  } +static void be_worker(struct work_struct *work) +{ +	struct be_adapter *adapter = +		container_of(work, struct be_adapter, work.work); +	int status; + +	/* Check link */ +	be_link_status_update(adapter); + +	/* Get Stats */ +	status = be_cmd_get_stats(&adapter->ctrl, &adapter->stats.cmd); +	if (!status) +		netdev_stats_update(adapter); + +	/* Set EQ delay */ +	be_rx_eqd_update(adapter); + +	if (adapter->rx_post_starved) { +		adapter->rx_post_starved = false; +		be_post_rx_frags(adapter); +	} + +	schedule_delayed_work(&adapter->work, msecs_to_jiffies(1000)); +} +  static void be_msix_enable(struct be_adapter *adapter)  {  	int i, status; @@ -1422,6 +1430,8 @@ static int be_open(struct net_device *netdev)  	if (status != 0)  		goto do_none; +	be_vid_config(netdev); +  	status = be_cmd_set_flow_control(ctrl, true, true);  	if (status != 0)  		goto if_destroy; @@ -1856,8 +1866,6 @@ static int be_resume(struct pci_dev *pdev)  	pci_set_power_state(pdev, 0);  	pci_restore_state(pdev); -	be_vids_config(netdev); -  	if (netif_running(netdev)) {  		rtnl_lock();  		be_open(netdev); diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c index 6500b7c4739..6b6530ffdf1 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c @@ -57,8 +57,8 @@  #define DRV_MODULE_NAME		"bnx2"  #define PFX DRV_MODULE_NAME	": " -#define DRV_MODULE_VERSION	"1.9.2" -#define DRV_MODULE_RELDATE	"Feb 11, 2009" +#define DRV_MODULE_VERSION	"1.9.3" +#define DRV_MODULE_RELDATE	"March 17, 2009"  #define RUN_AT(x) (jiffies + (x)) @@ -5843,9 +5843,6 @@ bnx2_enable_msix(struct bnx2 *bp, int msix_vecs)  	for (i = 0; i < BNX2_MAX_MSIX_VEC; i++) {  		msix_ent[i].entry = i;  		msix_ent[i].vector = 0; - -		snprintf(bp->irq_tbl[i].name, len, "%s-%d", dev->name, i); -		bp->irq_tbl[i].handler = bnx2_msi_1shot;  	}  	rc = pci_enable_msix(bp->pdev, msix_ent, BNX2_MAX_MSIX_VEC); @@ -5854,8 +5851,11 @@ bnx2_enable_msix(struct bnx2 *bp, int msix_vecs)  	bp->irq_nvecs = msix_vecs;  	bp->flags |= BNX2_FLAG_USING_MSIX | BNX2_FLAG_ONE_SHOT_MSI; -	for (i = 0; i < BNX2_MAX_MSIX_VEC; i++) +	for (i = 0; i < BNX2_MAX_MSIX_VEC; i++) {  		bp->irq_tbl[i].vector = msix_ent[i].vector; +		snprintf(bp->irq_tbl[i].name, len, "%s-%d", dev->name, i); +		bp->irq_tbl[i].handler = bnx2_msi_1shot; +	}  }  static void diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index e0578fe8c0d..3d76686dcec 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -3537,11 +3537,26 @@ static int bond_slave_netdev_event(unsigned long event, struct net_device *slave  		}  		break;  	case NETDEV_CHANGE: -		/* -		 * TODO: is this what we get if somebody -		 * sets up a hierarchical bond, then rmmod's -		 * one of the slave bonding devices? -		 */ +		if (bond->params.mode == BOND_MODE_8023AD || bond_is_lb(bond)) { +			struct slave *slave; + +			slave = bond_get_slave_by_dev(bond, slave_dev); +			if (slave) { +				u16 old_speed = slave->speed; +				u16 old_duplex = slave->duplex; + +				bond_update_speed_duplex(slave); + +				if (bond_is_lb(bond)) +					break; + +				if (old_speed != slave->speed) +					bond_3ad_adapter_speed_changed(slave); +				if (old_duplex != slave->duplex) +					bond_3ad_adapter_duplex_changed(slave); +			} +		} +  		break;  	case NETDEV_DOWN:  		/* diff --git a/drivers/net/dm9000.c b/drivers/net/dm9000.c index bcf92917bbf..254ec62b5f5 100644 --- a/drivers/net/dm9000.c +++ b/drivers/net/dm9000.c @@ -930,13 +930,15 @@ static irqreturn_t dm9000_interrupt(int irq, void *dev_id)  	struct net_device *dev = dev_id;  	board_info_t *db = netdev_priv(dev);  	int int_status; +	unsigned long flags;  	u8 reg_save;  	dm9000_dbg(db, 3, "entering %s\n", __func__);  	/* A real interrupt coming */ -	spin_lock(&db->lock); +	/* holders of db->lock must always block IRQs */ +	spin_lock_irqsave(&db->lock, flags);  	/* Save previous register address */  	reg_save = readb(db->io_addr); @@ -972,7 +974,7 @@ static irqreturn_t dm9000_interrupt(int irq, void *dev_id)  	/* Restore previous register address */  	writeb(reg_save, db->io_addr); -	spin_unlock(&db->lock); +	spin_unlock_irqrestore(&db->lock, flags);  	return IRQ_HANDLED;  } diff --git a/drivers/net/dnet.c b/drivers/net/dnet.c index 5c347f70cb6..1b4063222a8 100644 --- a/drivers/net/dnet.c +++ b/drivers/net/dnet.c @@ -280,11 +280,11 @@ static int dnet_mii_probe(struct net_device *dev)  	/* attach the mac to the phy */  	if (bp->capabilities & DNET_HAS_RMII) { -		phydev = phy_connect(dev, phydev->dev.bus_id, +		phydev = phy_connect(dev, dev_name(&phydev->dev),  				     &dnet_handle_link_change, 0,  				     PHY_INTERFACE_MODE_RMII);  	} else { -		phydev = phy_connect(dev, phydev->dev.bus_id, +		phydev = phy_connect(dev, dev_name(&phydev->dev),  				     &dnet_handle_link_change, 0,  				     PHY_INTERFACE_MODE_MII);  	} @@ -927,7 +927,7 @@ static int __devinit dnet_probe(struct platform_device *pdev)  	phydev = bp->phy_dev;  	dev_info(&pdev->dev, "attached PHY driver [%s] "  	       "(mii_bus:phy_addr=%s, irq=%d)\n", -	       phydev->drv->name, phydev->dev.bus_id, phydev->irq); +	       phydev->drv->name, dev_name(&phydev->dev), phydev->irq);  	return 0; diff --git a/drivers/net/sh_eth.c b/drivers/net/sh_eth.c index 7f8e514eb5e..7b1882765a0 100644 --- a/drivers/net/sh_eth.c +++ b/drivers/net/sh_eth.c @@ -687,6 +687,7 @@ static irqreturn_t sh_eth_interrupt(int irq, void *netdev)  {  	struct net_device *ndev = netdev;  	struct sh_eth_private *mdp = netdev_priv(ndev); +	irqreturn_t ret = IRQ_NONE;  	u32 ioaddr, boguscnt = RX_RING_SIZE;  	u32 intr_status = 0; @@ -696,7 +697,13 @@ static irqreturn_t sh_eth_interrupt(int irq, void *netdev)  	/* Get interrpt stat */  	intr_status = ctrl_inl(ioaddr + EESR);  	/* Clear interrupt */ -	ctrl_outl(intr_status, ioaddr + EESR); +	if (intr_status & (EESR_FRC | EESR_RMAF | EESR_RRF | +			EESR_RTLF | EESR_RTSF | EESR_PRE | EESR_CERF | +			TX_CHECK | EESR_ERR_CHECK)) { +		ctrl_outl(intr_status, ioaddr + EESR); +		ret = IRQ_HANDLED; +	} else +		goto other_irq;  	if (intr_status & (EESR_FRC | /* Frame recv*/  			EESR_RMAF | /* Multi cast address recv*/ @@ -723,9 +730,10 @@ static irqreturn_t sh_eth_interrupt(int irq, void *netdev)  		       ndev->name, intr_status);  	} +other_irq:  	spin_unlock(&mdp->lock); -	return IRQ_HANDLED; +	return ret;  }  static void sh_eth_timer(unsigned long data) @@ -844,7 +852,13 @@ static int sh_eth_open(struct net_device *ndev)  	int ret = 0;  	struct sh_eth_private *mdp = netdev_priv(ndev); -	ret = request_irq(ndev->irq, &sh_eth_interrupt, 0, ndev->name, ndev); +	ret = request_irq(ndev->irq, &sh_eth_interrupt, +#if defined(CONFIG_CPU_SUBTYPE_SH7763) || defined(CONFIG_CPU_SUBTYPE_SH7764) +				IRQF_SHARED, +#else +				0, +#endif +				ndev->name, ndev);  	if (ret) {  		printk(KERN_ERR "Can not assign IRQ number to %s\n", CARDNAME);  		return ret; diff --git a/drivers/net/sh_eth.h b/drivers/net/sh_eth.h index 73bc7181cc1..1537e13e623 100644 --- a/drivers/net/sh_eth.h +++ b/drivers/net/sh_eth.h @@ -43,8 +43,8 @@  #define SH7763_SKB_ALIGN 32  /* Chip Base Address */ -# define SH_TSU_ADDR  0xFFE01800 -# define ARSTR 		  0xFFE01800 +# define SH_TSU_ADDR	0xFEE01800 +# define ARSTR			SH_TSU_ADDR  /* Chip Registers */  /* E-DMAC */ diff --git a/drivers/net/smsc911x.c b/drivers/net/smsc911x.c index 9a78daec2fe..d1590ac55e4 100644 --- a/drivers/net/smsc911x.c +++ b/drivers/net/smsc911x.c @@ -1225,6 +1225,10 @@ static int smsc911x_open(struct net_device *dev)  	dev_info(&dev->dev, "SMSC911x/921x identified at %#08lx, IRQ: %d\n",  		 (unsigned long)pdata->ioaddr, dev->irq); +	/* Reset the last known duplex and carrier */ +	pdata->last_duplex = -1; +	pdata->last_carrier = -1; +  	/* Bring the PHY up */  	phy_start(pdata->phy_dev); diff --git a/drivers/net/sungem.c b/drivers/net/sungem.c index 0fcb7503363..c9c7650826c 100644 --- a/drivers/net/sungem.c +++ b/drivers/net/sungem.c @@ -2998,8 +2998,11 @@ static const struct net_device_ops gem_netdev_ops = {  	.ndo_do_ioctl		= gem_ioctl,  	.ndo_tx_timeout		= gem_tx_timeout,  	.ndo_change_mtu		= gem_change_mtu, -	.ndo_set_mac_address 	= eth_mac_addr,  	.ndo_validate_addr	= eth_validate_addr, +	.ndo_set_mac_address    = gem_set_mac_address, +#ifdef CONFIG_NET_POLL_CONTROLLER +	.ndo_poll_controller    = gem_poll_controller, +#endif  };  static int __devinit gem_init_one(struct pci_dev *pdev, @@ -3161,10 +3164,6 @@ static int __devinit gem_init_one(struct pci_dev *pdev,  	dev->watchdog_timeo = 5 * HZ;  	dev->irq = pdev->irq;  	dev->dma = 0; -	dev->set_mac_address = gem_set_mac_address; -#ifdef CONFIG_NET_POLL_CONTROLLER -	dev->poll_controller = gem_poll_controller; -#endif  	/* Set that now, in case PM kicks in now */  	pci_set_drvdata(pdev, dev); diff --git a/drivers/net/tulip/tulip_core.c b/drivers/net/tulip/tulip_core.c index bee75fa87a9..2abb5d3becc 100644 --- a/drivers/net/tulip/tulip_core.c +++ b/drivers/net/tulip/tulip_core.c @@ -255,6 +255,7 @@ const char tulip_media_cap[32] =  static void tulip_tx_timeout(struct net_device *dev);  static void tulip_init_ring(struct net_device *dev); +static void tulip_free_ring(struct net_device *dev);  static int tulip_start_xmit(struct sk_buff *skb, struct net_device *dev);  static int tulip_open(struct net_device *dev);  static int tulip_close(struct net_device *dev); @@ -502,16 +503,21 @@ tulip_open(struct net_device *dev)  {  	int retval; -	if ((retval = request_irq(dev->irq, &tulip_interrupt, IRQF_SHARED, dev->name, dev))) -		return retval; -  	tulip_init_ring (dev); +	retval = request_irq(dev->irq, &tulip_interrupt, IRQF_SHARED, dev->name, dev); +	if (retval) +		goto free_ring; +  	tulip_up (dev);  	netif_start_queue (dev);  	return 0; + +free_ring: +	tulip_free_ring (dev); +	return retval;  } @@ -768,23 +774,11 @@ static void tulip_down (struct net_device *dev)  	tulip_set_power_state (tp, 0, 1);  } - -static int tulip_close (struct net_device *dev) +static void tulip_free_ring (struct net_device *dev)  {  	struct tulip_private *tp = netdev_priv(dev); -	void __iomem *ioaddr = tp->base_addr;  	int i; -	netif_stop_queue (dev); - -	tulip_down (dev); - -	if (tulip_debug > 1) -		printk (KERN_DEBUG "%s: Shutting down ethercard, status was %2.2x.\n", -			dev->name, ioread32 (ioaddr + CSR5)); - -	free_irq (dev->irq, dev); -  	/* Free all the skbuffs in the Rx queue. */  	for (i = 0; i < RX_RING_SIZE; i++) {  		struct sk_buff *skb = tp->rx_buffers[i].skb; @@ -803,6 +797,7 @@ static int tulip_close (struct net_device *dev)  			dev_kfree_skb (skb);  		}  	} +  	for (i = 0; i < TX_RING_SIZE; i++) {  		struct sk_buff *skb = tp->tx_buffers[i].skb; @@ -814,6 +809,24 @@ static int tulip_close (struct net_device *dev)  		tp->tx_buffers[i].skb = NULL;  		tp->tx_buffers[i].mapping = 0;  	} +} + +static int tulip_close (struct net_device *dev) +{ +	struct tulip_private *tp = netdev_priv(dev); +	void __iomem *ioaddr = tp->base_addr; + +	netif_stop_queue (dev); + +	tulip_down (dev); + +	if (tulip_debug > 1) +		printk (KERN_DEBUG "%s: Shutting down ethercard, status was %2.2x.\n", +			dev->name, ioread32 (ioaddr + CSR5)); + +	free_irq (dev->irq, dev); + +	tulip_free_ring (dev);  	return 0;  } diff --git a/drivers/net/ucc_geth.c b/drivers/net/ucc_geth.c index e87986867ba..1f61e42c641 100644 --- a/drivers/net/ucc_geth.c +++ b/drivers/net/ucc_geth.c @@ -1536,32 +1536,15 @@ static void adjust_link(struct net_device *dev)  static int init_phy(struct net_device *dev)  {  	struct ucc_geth_private *priv = netdev_priv(dev); -	struct device_node *np = priv->node; -	struct device_node *phy, *mdio; -	const phandle *ph; -	char bus_name[MII_BUS_ID_SIZE]; -	const unsigned int *id; +	struct ucc_geth_info *ug_info = priv->ug_info;  	struct phy_device *phydev; -	char phy_id[BUS_ID_SIZE];  	priv->oldlink = 0;  	priv->oldspeed = 0;  	priv->oldduplex = -1; -	ph = of_get_property(np, "phy-handle", NULL); -	phy = of_find_node_by_phandle(*ph); -	mdio = of_get_parent(phy); - -	id = of_get_property(phy, "reg", NULL); - -	of_node_put(phy); -	of_node_put(mdio); - -	uec_mdio_bus_name(bus_name, mdio); -	snprintf(phy_id, sizeof(phy_id), "%s:%02x", -                                bus_name, *id); - -	phydev = phy_connect(dev, phy_id, &adjust_link, 0, priv->phy_interface); +	phydev = phy_connect(dev, ug_info->phy_bus_id, &adjust_link, 0, +			     priv->phy_interface);  	if (IS_ERR(phydev)) {  		printk("%s: Could not attach to PHY\n", dev->name); @@ -3629,10 +3612,12 @@ static int ucc_geth_probe(struct of_device* ofdev, const struct of_device_id *ma  	ug_info->uf_info.irq = irq_of_parse_and_map(np, 0);  	fixed_link = of_get_property(np, "fixed-link", NULL);  	if (fixed_link) { -		snprintf(ug_info->mdio_bus, MII_BUS_ID_SIZE, "0"); -		ug_info->phy_address = fixed_link[0]; +		snprintf(ug_info->phy_bus_id, sizeof(ug_info->phy_bus_id), +			 PHY_ID_FMT, "0", fixed_link[0]);  		phy = NULL;  	} else { +		char bus_name[MII_BUS_ID_SIZE]; +  		ph = of_get_property(np, "phy-handle", NULL);  		phy = of_find_node_by_phandle(*ph); @@ -3643,7 +3628,6 @@ static int ucc_geth_probe(struct of_device* ofdev, const struct of_device_id *ma  		prop = of_get_property(phy, "reg", NULL);  		if (prop == NULL)  			return -1; -		ug_info->phy_address = *prop;  		/* Set the bus id */  		mdio = of_get_parent(phy); @@ -3657,7 +3641,9 @@ static int ucc_geth_probe(struct of_device* ofdev, const struct of_device_id *ma  		if (err)  			return -1; -		snprintf(ug_info->mdio_bus, MII_BUS_ID_SIZE, "%x", res.start); +		uec_mdio_bus_name(bus_name, mdio); +		snprintf(ug_info->phy_bus_id, sizeof(ug_info->phy_bus_id), +			"%s:%02x", bus_name, *prop);  	}  	/* get the phy interface type, or default to MII */ diff --git a/drivers/net/ucc_geth.h b/drivers/net/ucc_geth.h index 16cbe42ba43..611bdef2402 100644 --- a/drivers/net/ucc_geth.h +++ b/drivers/net/ucc_geth.h @@ -1091,8 +1091,7 @@ struct ucc_geth_info {  	u32 eventRegMask;  	u16 pausePeriod;  	u16 extensionField; -	u8 phy_address; -	char mdio_bus[MII_BUS_ID_SIZE]; +	char phy_bus_id[BUS_ID_SIZE];  	u8 weightfactor[NUM_TX_QUEUES];  	u8 interruptcoalescingmaxvalue[NUM_RX_QUEUES];  	u8 l2qt[UCC_GETH_VLAN_PRIORITY_MAX]; diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index c68808336c8..e67d16c2e5f 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -612,6 +612,7 @@ static struct ethtool_ops virtnet_ethtool_ops = {  	.set_tx_csum = virtnet_set_tx_csum,  	.set_sg = ethtool_op_set_sg,  	.set_tso = ethtool_op_set_tso, +	.get_link = ethtool_op_get_link,  };  #define MIN_MTU 68 @@ -739,6 +740,8 @@ static int virtnet_probe(struct virtio_device *vdev)  		goto unregister;  	} +	netif_carrier_on(dev); +  	pr_debug("virtnet: registered device %s\n", dev->name);  	return 0; diff --git a/drivers/net/wireless/ath9k/ath9k.h b/drivers/net/wireless/ath9k/ath9k.h index d2781350295..6650f609ece 100644 --- a/drivers/net/wireless/ath9k/ath9k.h +++ b/drivers/net/wireless/ath9k/ath9k.h @@ -587,8 +587,8 @@ struct ath9k_country_entry {  	u8 iso[3];  }; -#define REG_WRITE(_ah, _reg, _val) iowrite32(_val, _ah->ah_sh + _reg) -#define REG_READ(_ah, _reg) ioread32(_ah->ah_sh + _reg) +#define REG_WRITE(_ah, _reg, _val) ath9k_iowrite32((_ah), (_reg), (_val)) +#define REG_READ(_ah, _reg) ath9k_ioread32((_ah), (_reg))  #define SM(_v, _f)  (((_v) << _f##_S) & _f)  #define MS(_v, _f)  (((_v) & _f) >> _f##_S) diff --git a/drivers/net/wireless/ath9k/core.h b/drivers/net/wireless/ath9k/core.h index 4ca2aed236e..139566cbbf6 100644 --- a/drivers/net/wireless/ath9k/core.h +++ b/drivers/net/wireless/ath9k/core.h @@ -701,6 +701,7 @@ struct ath_softc {  	struct ath_hal *sc_ah;  	void __iomem *mem;  	spinlock_t sc_resetlock; +	spinlock_t sc_serial_rw;  	struct mutex mutex;  	u8 sc_curbssid[ETH_ALEN]; @@ -751,4 +752,36 @@ int ath_get_hal_qnum(u16 queue, struct ath_softc *sc);  int ath_get_mac80211_qnum(u32 queue, struct ath_softc *sc);  int ath_cabq_update(struct ath_softc *); +/* + * Read and write, they both share the same lock. We do this to serialize + * reads and writes on Atheros 802.11n PCI devices only. This is required + * as the FIFO on these devices can only accept sanely 2 requests. After + * that the device goes bananas. Serializing the reads/writes prevents this + * from happening. + */ + +static inline void ath9k_iowrite32(struct ath_hal *ah, u32 reg_offset, u32 val) +{ +	if (ah->ah_config.serialize_regmode == SER_REG_MODE_ON) { +		unsigned long flags; +		spin_lock_irqsave(&ah->ah_sc->sc_serial_rw, flags); +		iowrite32(val, ah->ah_sc->mem + reg_offset); +		spin_unlock_irqrestore(&ah->ah_sc->sc_serial_rw, flags); +	} else +		iowrite32(val, ah->ah_sc->mem + reg_offset); +} + +static inline unsigned int ath9k_ioread32(struct ath_hal *ah, u32 reg_offset) +{ +	u32 val; +	if (ah->ah_config.serialize_regmode == SER_REG_MODE_ON) { +		unsigned long flags; +		spin_lock_irqsave(&ah->ah_sc->sc_serial_rw, flags); +		val = ioread32(ah->ah_sc->mem + reg_offset); +		spin_unlock_irqrestore(&ah->ah_sc->sc_serial_rw, flags); +	} else +		val = ioread32(ah->ah_sc->mem + reg_offset); +	return val; +} +  #endif /* CORE_H */ diff --git a/drivers/net/wireless/ath9k/hw.c b/drivers/net/wireless/ath9k/hw.c index 34474edefc9..c38a00bbce6 100644 --- a/drivers/net/wireless/ath9k/hw.c +++ b/drivers/net/wireless/ath9k/hw.c @@ -437,6 +437,25 @@ static void ath9k_hw_set_defaults(struct ath_hal *ah)  	}  	ah->ah_config.intr_mitigation = 1; + +	/* +	 * We need this for PCI devices only (Cardbus, PCI, miniPCI) +	 * _and_ if on non-uniprocessor systems (Multiprocessor/HT). +	 * This means we use it for all AR5416 devices, and the few +	 * minor PCI AR9280 devices out there. +	 * +	 * Serialization is required because these devices do not handle +	 * well the case of two concurrent reads/writes due to the latency +	 * involved. During one read/write another read/write can be issued +	 * on another CPU while the previous read/write may still be working +	 * on our hardware, if we hit this case the hardware poops in a loop. +	 * We prevent this by serializing reads and writes. +	 * +	 * This issue is not present on PCI-Express devices or pre-AR5416 +	 * devices (legacy, 802.11abg). +	 */ +	if (num_possible_cpus() > 1) +		ah->ah_config.serialize_regmode = SER_REG_MODE_AUTO;  }  static struct ath_hal_5416 *ath9k_hw_newstate(u16 devid, @@ -668,7 +687,8 @@ static struct ath_hal *ath9k_hw_do_attach(u16 devid, struct ath_softc *sc,  	}  	if (ah->ah_config.serialize_regmode == SER_REG_MODE_AUTO) { -		if (ah->ah_macVersion == AR_SREV_VERSION_5416_PCI) { +		if (ah->ah_macVersion == AR_SREV_VERSION_5416_PCI || +		    (AR_SREV_9280(ah) && !ah->ah_isPciExpress)) {  			ah->ah_config.serialize_regmode =  				SER_REG_MODE_ON;  		} else { diff --git a/drivers/net/wireless/ath9k/main.c b/drivers/net/wireless/ath9k/main.c index 0e80990d8e8..3c04044a60b 100644 --- a/drivers/net/wireless/ath9k/main.c +++ b/drivers/net/wireless/ath9k/main.c @@ -1336,6 +1336,7 @@ static int ath_init(u16 devid, struct ath_softc *sc)  		printk(KERN_ERR "Unable to create debugfs files\n");  	spin_lock_init(&sc->sc_resetlock); +	spin_lock_init(&sc->sc_serial_rw);  	mutex_init(&sc->mutex);  	tasklet_init(&sc->intr_tq, ath9k_tasklet, (unsigned long)sc);  	tasklet_init(&sc->bcon_tasklet, ath9k_beacon_tasklet, diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c index a611ad85798..847057d682b 100644 --- a/drivers/net/wireless/zd1211rw/zd_mac.c +++ b/drivers/net/wireless/zd1211rw/zd_mac.c @@ -575,13 +575,17 @@ static int zd_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)  	r = fill_ctrlset(mac, skb);  	if (r) -		return r; +		goto fail;  	info->rate_driver_data[0] = hw;  	r = zd_usb_tx(&mac->chip.usb, skb);  	if (r) -		return r; +		goto fail; +	return 0; + +fail: +	dev_kfree_skb(skb);  	return 0;  } | 
