diff options
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/arm/ep93xx_eth.c | 10 | ||||
-rw-r--r-- | drivers/net/e1000e/netdev.c | 3 | ||||
-rw-r--r-- | drivers/net/fec.c | 2 | ||||
-rw-r--r-- | drivers/net/gianfar.c | 2 | ||||
-rw-r--r-- | drivers/net/phy/Kconfig | 5 | ||||
-rw-r--r-- | drivers/net/phy/Makefile | 1 | ||||
-rw-r--r-- | drivers/net/phy/mdio-octeon.c | 10 | ||||
-rw-r--r-- | drivers/net/phy/micrel.c | 105 | ||||
-rw-r--r-- | drivers/net/ppp_generic.c | 34 | ||||
-rw-r--r-- | drivers/net/r8169.c | 22 | ||||
-rw-r--r-- | drivers/net/sb1250-mac.c | 67 | ||||
-rw-r--r-- | drivers/net/usb/Kconfig | 1 | ||||
-rw-r--r-- | drivers/net/usb/dm9601.c | 2 | ||||
-rw-r--r-- | drivers/net/usb/sierra_net.c | 3 | ||||
-rw-r--r-- | drivers/net/veth.c | 1 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ar9170/usb.c | 11 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ar9170/usb.h | 1 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-commands.h | 4 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-scan.c | 23 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl3945-base.c | 3 | ||||
-rw-r--r-- | drivers/net/wireless/p54/p54pci.c | 2 |
21 files changed, 243 insertions, 69 deletions
diff --git a/drivers/net/arm/ep93xx_eth.c b/drivers/net/arm/ep93xx_eth.c index 6995169..cd17d09 100644 --- a/drivers/net/arm/ep93xx_eth.c +++ b/drivers/net/arm/ep93xx_eth.c @@ -311,11 +311,6 @@ err: processed++; } - if (processed) { - wrw(ep, REG_RXDENQ, processed); - wrw(ep, REG_RXSTSENQ, processed); - } - return processed; } @@ -350,6 +345,11 @@ poll_some_more: goto poll_some_more; } + if (rx) { + wrw(ep, REG_RXDENQ, rx); + wrw(ep, REG_RXSTSENQ, rx); + } + return rx; } diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c index fb8fc7d..dbf8178 100644 --- a/drivers/net/e1000e/netdev.c +++ b/drivers/net/e1000e/netdev.c @@ -4633,6 +4633,9 @@ static void __e1000e_disable_aspm(struct pci_dev *pdev, u16 state) reg16 &= ~state; pci_write_config_word(pdev, pos + PCI_EXP_LNKCTL, reg16); + if (!pdev->bus->self) + return; + pos = pci_pcie_cap(pdev->bus->self); pci_read_config_word(pdev->bus->self, pos + PCI_EXP_LNKCTL, ®16); reg16 &= ~state; diff --git a/drivers/net/fec.c b/drivers/net/fec.c index 9f98c1c..9b4e8f7 100644 --- a/drivers/net/fec.c +++ b/drivers/net/fec.c @@ -1653,7 +1653,7 @@ fec_set_mac_address(struct net_device *dev, void *p) (dev->dev_addr[1] << 16) | (dev->dev_addr[0] << 24), fep->hwp + FEC_ADDR_LOW); writel((dev->dev_addr[5] << 16) | (dev->dev_addr[4] << 24), - fep + FEC_ADDR_HIGH); + fep->hwp + FEC_ADDR_HIGH); return 0; } diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c index 4e97ca1..5d3763f 100644 --- a/drivers/net/gianfar.c +++ b/drivers/net/gianfar.c @@ -1649,6 +1649,7 @@ static void free_skb_resources(struct gfar_private *priv) sizeof(struct rxbd8) * priv->total_rx_ring_size, priv->tx_queue[0]->tx_bd_base, priv->tx_queue[0]->tx_bd_dma_base); + skb_queue_purge(&priv->rx_recycle); } void gfar_start(struct net_device *dev) @@ -2088,7 +2089,6 @@ static int gfar_close(struct net_device *dev) disable_napi(priv); - skb_queue_purge(&priv->rx_recycle); cancel_work_sync(&priv->reset_task); stop_gfar(dev); diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig index fc5938ba..a527e37 100644 --- a/drivers/net/phy/Kconfig +++ b/drivers/net/phy/Kconfig @@ -88,6 +88,11 @@ config LSI_ET1011C_PHY ---help--- Supports the LSI ET1011C PHY. +config MICREL_PHY + tristate "Driver for Micrel PHYs" + ---help--- + Supports the KSZ9021, VSC8201, KS8001 PHYs. + config FIXED_PHY bool "Driver for MDIO Bus/PHY emulation with fixed speed/link PHYs" depends on PHYLIB=y diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile index 1342585..13bebab 100644 --- a/drivers/net/phy/Makefile +++ b/drivers/net/phy/Makefile @@ -20,4 +20,5 @@ obj-$(CONFIG_MDIO_BITBANG) += mdio-bitbang.o obj-$(CONFIG_MDIO_GPIO) += mdio-gpio.o obj-$(CONFIG_NATIONAL_PHY) += national.o obj-$(CONFIG_STE10XP) += ste10Xp.o +obj-$(CONFIG_MICREL_PHY) += micrel.o obj-$(CONFIG_MDIO_OCTEON) += mdio-octeon.o diff --git a/drivers/net/phy/mdio-octeon.c b/drivers/net/phy/mdio-octeon.c index a872aea..f443d43 100644 --- a/drivers/net/phy/mdio-octeon.c +++ b/drivers/net/phy/mdio-octeon.c @@ -88,6 +88,7 @@ static int octeon_mdiobus_write(struct mii_bus *bus, int phy_id, static int __init octeon_mdiobus_probe(struct platform_device *pdev) { struct octeon_mdiobus *bus; + union cvmx_smix_en smi_en; int i; int err = -ENOENT; @@ -103,6 +104,10 @@ static int __init octeon_mdiobus_probe(struct platform_device *pdev) if (!bus->mii_bus) goto err; + smi_en.u64 = 0; + smi_en.s.en = 1; + cvmx_write_csr(CVMX_SMIX_EN(bus->unit), smi_en.u64); + /* * Standard Octeon evaluation boards don't support phy * interrupts, we need to poll. @@ -133,17 +138,22 @@ err_register: err: devm_kfree(&pdev->dev, bus); + smi_en.u64 = 0; + cvmx_write_csr(CVMX_SMIX_EN(bus->unit), smi_en.u64); return err; } static int __exit octeon_mdiobus_remove(struct platform_device *pdev) { struct octeon_mdiobus *bus; + union cvmx_smix_en smi_en; bus = dev_get_drvdata(&pdev->dev); mdiobus_unregister(bus->mii_bus); mdiobus_free(bus->mii_bus); + smi_en.u64 = 0; + cvmx_write_csr(CVMX_SMIX_EN(bus->unit), smi_en.u64); return 0; } diff --git a/drivers/net/phy/micrel.c b/drivers/net/phy/micrel.c new file mode 100644 index 0000000..e67691d --- /dev/null +++ b/drivers/net/phy/micrel.c @@ -0,0 +1,105 @@ +/* + * drivers/net/phy/micrel.c + * + * Driver for Micrel PHYs + * + * Author: David J. Choi + * + * Copyright (c) 2010 Micrel, Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * Support : ksz9021 , vsc8201, ks8001 + */ + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/phy.h> + +#define PHY_ID_KSZ9021 0x00221611 +#define PHY_ID_VSC8201 0x000FC413 +#define PHY_ID_KS8001 0x0022161A + + +static int kszphy_config_init(struct phy_device *phydev) +{ + return 0; +} + + +static struct phy_driver ks8001_driver = { + .phy_id = PHY_ID_KS8001, + .name = "Micrel KS8001", + .phy_id_mask = 0x00fffff0, + .features = PHY_BASIC_FEATURES, + .flags = PHY_POLL, + .config_init = kszphy_config_init, + .config_aneg = genphy_config_aneg, + .read_status = genphy_read_status, + .driver = { .owner = THIS_MODULE,}, +}; + +static struct phy_driver vsc8201_driver = { + .phy_id = PHY_ID_VSC8201, + .name = "Micrel VSC8201", + .phy_id_mask = 0x00fffff0, + .features = PHY_BASIC_FEATURES, + .flags = PHY_POLL, + .config_init = kszphy_config_init, + .config_aneg = genphy_config_aneg, + .read_status = genphy_read_status, + .driver = { .owner = THIS_MODULE,}, +}; + +static struct phy_driver ksz9021_driver = { + .phy_id = PHY_ID_KSZ9021, + .phy_id_mask = 0x000fff10, + .name = "Micrel KSZ9021 Gigabit PHY", + .features = PHY_GBIT_FEATURES | SUPPORTED_Pause, + .flags = PHY_POLL, + .config_init = kszphy_config_init, + .config_aneg = genphy_config_aneg, + .read_status = genphy_read_status, + .driver = { .owner = THIS_MODULE, }, +}; + +static int __init ksphy_init(void) +{ + int ret; + + ret = phy_driver_register(&ks8001_driver); + if (ret) + goto err1; + ret = phy_driver_register(&vsc8201_driver); + if (ret) + goto err2; + + ret = phy_driver_register(&ksz9021_driver); + if (ret) + goto err3; + return 0; + +err3: + phy_driver_unregister(&vsc8201_driver); +err2: + phy_driver_unregister(&ks8001_driver); +err1: + return ret; +} + +static void __exit ksphy_exit(void) +{ + phy_driver_unregister(&ks8001_driver); + phy_driver_unregister(&vsc8201_driver); + phy_driver_unregister(&ksz9021_driver); +} + +module_init(ksphy_init); +module_exit(ksphy_exit); + +MODULE_DESCRIPTION("Micrel PHY driver"); +MODULE_AUTHOR("David J. Choi"); +MODULE_LICENSE("GPL"); diff --git a/drivers/net/ppp_generic.c b/drivers/net/ppp_generic.c index 6e281bc..8518a2e 100644 --- a/drivers/net/ppp_generic.c +++ b/drivers/net/ppp_generic.c @@ -405,6 +405,7 @@ static ssize_t ppp_read(struct file *file, char __user *buf, DECLARE_WAITQUEUE(wait, current); ssize_t ret; struct sk_buff *skb = NULL; + struct iovec iov; ret = count; @@ -448,7 +449,9 @@ static ssize_t ppp_read(struct file *file, char __user *buf, if (skb->len > count) goto outf; ret = -EFAULT; - if (copy_to_user(buf, skb->data, skb->len)) + iov.iov_base = buf; + iov.iov_len = count; + if (skb_copy_datagram_iovec(skb, 0, &iov, skb->len)) goto outf; ret = skb->len; @@ -1567,13 +1570,22 @@ ppp_input(struct ppp_channel *chan, struct sk_buff *skb) struct channel *pch = chan->ppp; int proto; - if (!pch || skb->len == 0) { + if (!pch) { kfree_skb(skb); return; } - proto = PPP_PROTO(skb); read_lock_bh(&pch->upl); + if (!pskb_may_pull(skb, 2)) { + kfree_skb(skb); + if (pch->ppp) { + ++pch->ppp->dev->stats.rx_length_errors; + ppp_receive_error(pch->ppp); + } + goto done; + } + + proto = PPP_PROTO(skb); if (!pch->ppp || proto >= 0xc000 || proto == PPP_CCPFRAG) { /* put it on the channel queue */ skb_queue_tail(&pch->file.rq, skb); @@ -1585,6 +1597,8 @@ ppp_input(struct ppp_channel *chan, struct sk_buff *skb) } else { ppp_do_recv(pch->ppp, skb, pch); } + +done: read_unlock_bh(&pch->upl); } @@ -1617,7 +1631,8 @@ ppp_input_error(struct ppp_channel *chan, int code) static void ppp_receive_frame(struct ppp *ppp, struct sk_buff *skb, struct channel *pch) { - if (pskb_may_pull(skb, 2)) { + /* note: a 0-length skb is used as an error indication */ + if (skb->len > 0) { #ifdef CONFIG_PPP_MULTILINK /* XXX do channel-level decompression here */ if (PPP_PROTO(skb) == PPP_MP) @@ -1625,15 +1640,10 @@ ppp_receive_frame(struct ppp *ppp, struct sk_buff *skb, struct channel *pch) else #endif /* CONFIG_PPP_MULTILINK */ ppp_receive_nonmp_frame(ppp, skb); - return; + } else { + kfree_skb(skb); + ppp_receive_error(ppp); } - - if (skb->len > 0) - /* note: a 0-length skb is used as an error indication */ - ++ppp->dev->stats.rx_length_errors; - - kfree_skb(skb); - ppp_receive_error(ppp); } static void diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index 4748c21..dd8106f 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c @@ -1042,14 +1042,14 @@ static void rtl8169_vlan_rx_register(struct net_device *dev, } static int rtl8169_rx_vlan_skb(struct rtl8169_private *tp, struct RxDesc *desc, - struct sk_buff *skb) + struct sk_buff *skb, int polling) { u32 opts2 = le32_to_cpu(desc->opts2); struct vlan_group *vlgrp = tp->vlgrp; int ret; if (vlgrp && (opts2 & RxVlanTag)) { - vlan_hwaccel_receive_skb(skb, vlgrp, swab16(opts2 & 0xffff)); + __vlan_hwaccel_rx(skb, vlgrp, swab16(opts2 & 0xffff), polling); ret = 0; } else ret = -1; @@ -1066,7 +1066,7 @@ static inline u32 rtl8169_tx_vlan_tag(struct rtl8169_private *tp, } static int rtl8169_rx_vlan_skb(struct rtl8169_private *tp, struct RxDesc *desc, - struct sk_buff *skb) + struct sk_buff *skb, int polling) { return -1; } @@ -4445,12 +4445,20 @@ out: return done; } +/* + * Warning : rtl8169_rx_interrupt() might be called : + * 1) from NAPI (softirq) context + * (polling = 1 : we should call netif_receive_skb()) + * 2) from process context (rtl8169_reset_task()) + * (polling = 0 : we must call netif_rx() instead) + */ static int rtl8169_rx_interrupt(struct net_device *dev, struct rtl8169_private *tp, void __iomem *ioaddr, u32 budget) { unsigned int cur_rx, rx_left; unsigned int delta, count; + int polling = (budget != ~(u32)0) ? 1 : 0; cur_rx = tp->cur_rx; rx_left = NUM_RX_DESC + tp->dirty_rx - cur_rx; @@ -4512,8 +4520,12 @@ static int rtl8169_rx_interrupt(struct net_device *dev, skb_put(skb, pkt_size); skb->protocol = eth_type_trans(skb, dev); - if (rtl8169_rx_vlan_skb(tp, desc, skb) < 0) - netif_receive_skb(skb); + if (rtl8169_rx_vlan_skb(tp, desc, skb, polling) < 0) { + if (likely(polling)) + netif_receive_skb(skb); + else + netif_rx(skb); + } dev->stats.rx_bytes += pkt_size; dev->stats.rx_packets++; diff --git a/drivers/net/sb1250-mac.c b/drivers/net/sb1250-mac.c index 9944e5d..04efc0c 100644 --- a/drivers/net/sb1250-mac.c +++ b/drivers/net/sb1250-mac.c @@ -2353,17 +2353,36 @@ static int sbmac_init(struct platform_device *pldev, long long base) sc->mii_bus = mdiobus_alloc(); if (sc->mii_bus == NULL) { - sbmac_uninitctx(sc); - return -ENOMEM; + err = -ENOMEM; + goto uninit_ctx; } + sc->mii_bus->name = sbmac_mdio_string; + snprintf(sc->mii_bus->id, MII_BUS_ID_SIZE, "%x", idx); + sc->mii_bus->priv = sc; + sc->mii_bus->read = sbmac_mii_read; + sc->mii_bus->write = sbmac_mii_write; + sc->mii_bus->irq = sc->phy_irq; + for (i = 0; i < PHY_MAX_ADDR; ++i) + sc->mii_bus->irq[i] = SBMAC_PHY_INT; + + sc->mii_bus->parent = &pldev->dev; + /* + * Probe PHY address + */ + err = mdiobus_register(sc->mii_bus); + if (err) { + printk(KERN_ERR "%s: unable to register MDIO bus\n", + dev->name); + goto free_mdio; + } + dev_set_drvdata(&pldev->dev, sc->mii_bus); + err = register_netdev(dev); if (err) { printk(KERN_ERR "%s.%d: unable to register netdev\n", sbmac_string, idx); - mdiobus_free(sc->mii_bus); - sbmac_uninitctx(sc); - return err; + goto unreg_mdio; } pr_info("%s.%d: registered as %s\n", sbmac_string, idx, dev->name); @@ -2379,19 +2398,15 @@ static int sbmac_init(struct platform_device *pldev, long long base) pr_info("%s: SiByte Ethernet at 0x%08Lx, address: %pM\n", dev->name, base, eaddr); - sc->mii_bus->name = sbmac_mdio_string; - snprintf(sc->mii_bus->id, MII_BUS_ID_SIZE, "%x", idx); - sc->mii_bus->priv = sc; - sc->mii_bus->read = sbmac_mii_read; - sc->mii_bus->write = sbmac_mii_write; - sc->mii_bus->irq = sc->phy_irq; - for (i = 0; i < PHY_MAX_ADDR; ++i) - sc->mii_bus->irq[i] = SBMAC_PHY_INT; - - sc->mii_bus->parent = &pldev->dev; - dev_set_drvdata(&pldev->dev, sc->mii_bus); - return 0; +unreg_mdio: + mdiobus_unregister(sc->mii_bus); + dev_set_drvdata(&pldev->dev, NULL); +free_mdio: + mdiobus_free(sc->mii_bus); +uninit_ctx: + sbmac_uninitctx(sc); + return err; } @@ -2417,16 +2432,6 @@ static int sbmac_open(struct net_device *dev) goto out_err; } - /* - * Probe PHY address - */ - err = mdiobus_register(sc->mii_bus); - if (err) { - printk(KERN_ERR "%s: unable to register MDIO bus\n", - dev->name); - goto out_unirq; - } - sc->sbm_speed = sbmac_speed_none; sc->sbm_duplex = sbmac_duplex_none; sc->sbm_fc = sbmac_fc_none; @@ -2457,11 +2462,7 @@ static int sbmac_open(struct net_device *dev) return 0; out_unregister: - mdiobus_unregister(sc->mii_bus); - -out_unirq: free_irq(dev->irq, dev); - out_err: return err; } @@ -2650,9 +2651,6 @@ static int sbmac_close(struct net_device *dev) phy_disconnect(sc->phy_dev); sc->phy_dev = NULL; - - mdiobus_unregister(sc->mii_bus); - free_irq(dev->irq, dev); sbdma_emptyring(&(sc->sbm_txdma)); @@ -2760,6 +2758,7 @@ static int __exit sbmac_remove(struct platform_device *pldev) unregister_netdev(dev); sbmac_uninitctx(sc); + mdiobus_unregister(sc->mii_bus); mdiobus_free(sc->mii_bus); iounmap(sc->sbm_base); free_netdev(dev); diff --git a/drivers/net/usb/Kconfig b/drivers/net/usb/Kconfig index 5d58abc..d7b7018 100644 --- a/drivers/net/usb/Kconfig +++ b/drivers/net/usb/Kconfig @@ -400,7 +400,6 @@ config USB_IPHETH config USB_SIERRA_NET tristate "USB-to-WWAN Driver for Sierra Wireless modems" depends on USB_USBNET - default y help Choose this option if you have a Sierra Wireless USB-to-WWAN device. diff --git a/drivers/net/usb/dm9601.c b/drivers/net/usb/dm9601.c index 04b2810..5dfed92 100644 --- a/drivers/net/usb/dm9601.c +++ b/drivers/net/usb/dm9601.c @@ -240,7 +240,7 @@ static int dm_write_shared_word(struct usbnet *dev, int phy, u8 reg, __le16 valu goto out; dm_write_reg(dev, DM_SHARED_ADDR, phy ? (reg | 0x40) : reg); - dm_write_reg(dev, DM_SHARED_CTRL, phy ? 0x1c : 0x14); + dm_write_reg(dev, DM_SHARED_CTRL, phy ? 0x1a : 0x12); for (i = 0; i < DM_TIMEOUT; i++) { u8 tmp; diff --git a/drivers/net/usb/sierra_net.c b/drivers/net/usb/sierra_net.c index a44f9e0..f1942d6 100644 --- a/drivers/net/usb/sierra_net.c +++ b/drivers/net/usb/sierra_net.c @@ -789,6 +789,9 @@ static int sierra_net_bind(struct usbnet *dev, struct usb_interface *intf) /* prepare sync message from template */ memcpy(priv->sync_msg, sync_tmplate, sizeof(priv->sync_msg)); + /* initiate the sync sequence */ + sierra_net_dosync(dev); + return 0; } diff --git a/drivers/net/veth.c b/drivers/net/veth.c index f9f0730..5ec542d 100644 --- a/drivers/net/veth.c +++ b/drivers/net/veth.c @@ -187,7 +187,6 @@ tx_drop: return NETDEV_TX_OK; rx_drop: - kfree_skb(skb); rcv_stats->rx_dropped++; return NETDEV_TX_OK; } diff --git a/drivers/net/wireless/ath/ar9170/usb.c b/drivers/net/wireless/ath/ar9170/usb.c index 99a6da4..e1c2fca 100644 --- a/drivers/net/wireless/ath/ar9170/usb.c +++ b/drivers/net/wireless/ath/ar9170/usb.c @@ -727,12 +727,16 @@ static void ar9170_usb_firmware_failed(struct ar9170_usb *aru) { struct device *parent = aru->udev->dev.parent; + complete(&aru->firmware_loading_complete); + /* unbind anything failed */ if (parent) down(&parent->sem); device_release_driver(&aru->udev->dev); if (parent) up(&parent->sem); + + usb_put_dev(aru->udev); } static void ar9170_usb_firmware_finish(const struct firmware *fw, void *context) @@ -761,6 +765,8 @@ static void ar9170_usb_firmware_finish(const struct firmware *fw, void *context) if (err) goto err_unrx; + complete(&aru->firmware_loading_complete); + usb_put_dev(aru->udev); return; err_unrx: @@ -858,6 +864,7 @@ static int ar9170_usb_probe(struct usb_interface *intf, init_usb_anchor(&aru->tx_pending); init_usb_anchor(&aru->tx_submitted); init_completion(&aru->cmd_wait); + init_completion(&aru->firmware_loading_complete); spin_lock_init(&aru->tx_urb_lock); aru->tx_pending_urbs = 0; @@ -877,6 +884,7 @@ static int ar9170_usb_probe(struct usb_interface *intf, if (err) goto err_freehw; + usb_get_dev(aru->udev); return request_firmware_nowait(THIS_MODULE, 1, "ar9170.fw", &aru->udev->dev, GFP_KERNEL, aru, ar9170_usb_firmware_step2); @@ -896,6 +904,9 @@ static void ar9170_usb_disconnect(struct usb_interface *intf) return; aru->common.state = AR9170_IDLE; + + wait_for_completion(&aru->firmware_loading_complete); + ar9170_unregister(&aru->common); ar9170_usb_cancel_urbs(aru); diff --git a/drivers/net/wireless/ath/ar9170/usb.h b/drivers/net/wireless/ath/ar9170/usb.h index a2ce3b1..919b060 100644 --- a/drivers/net/wireless/ath/ar9170/usb.h +++ b/drivers/net/wireless/ath/ar9170/usb.h @@ -71,6 +71,7 @@ struct ar9170_usb { unsigned int tx_pending_urbs; struct completion cmd_wait; + struct completion firmware_loading_complete; int readlen; u8 *readbuf; diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h index 6383d9f..f4e59ae 100644 --- a/drivers/net/wireless/iwlwifi/iwl-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-commands.h @@ -2621,7 +2621,9 @@ struct iwl_ssid_ie { #define PROBE_OPTION_MAX_3945 4 #define PROBE_OPTION_MAX 20 #define TX_CMD_LIFE_TIME_INFINITE cpu_to_le32(0xFFFFFFFF) -#define IWL_GOOD_CRC_TH cpu_to_le16(1) +#define IWL_GOOD_CRC_TH_DISABLED 0 +#define IWL_GOOD_CRC_TH_DEFAULT cpu_to_le16(1) +#define IWL_GOOD_CRC_TH_NEVER cpu_to_le16(0xffff) #define IWL_MAX_SCAN_SIZE 1024 #define IWL_MAX_CMD_SIZE 4096 #define IWL_MAX_PROBE_REQUEST 200 diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c index 12e455a..741e65e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-scan.c +++ b/drivers/net/wireless/iwlwifi/iwl-scan.c @@ -813,16 +813,29 @@ static void iwl_bg_request_scan(struct work_struct *data) rate = IWL_RATE_1M_PLCP; rate_flags = RATE_MCS_CCK_MSK; } - scan->good_CRC_th = 0; + scan->good_CRC_th = IWL_GOOD_CRC_TH_DISABLED; } else if (priv->scan_bands & BIT(IEEE80211_BAND_5GHZ)) { band = IEEE80211_BAND_5GHZ; rate = IWL_RATE_6M_PLCP; /* - * If active scaning is requested but a certain channel - * is marked passive, we can do active scanning if we - * detect transmissions. + * If active scanning is requested but a certain channel is + * marked passive, we can do active scanning if we detect + * transmissions. + * + * There is an issue with some firmware versions that triggers + * a sysassert on a "good CRC threshold" of zero (== disabled), + * on a radar channel even though this means that we should NOT + * send probes. + * + * The "good CRC threshold" is the number of frames that we + * need to receive during our dwell time on a channel before + * sending out probes -- setting this to a huge value will + * mean we never reach it, but at the same time work around + * the aforementioned issue. Thus use IWL_GOOD_CRC_TH_NEVER + * here instead of IWL_GOOD_CRC_TH_DISABLED. */ - scan->good_CRC_th = is_active ? IWL_GOOD_CRC_TH : 0; + scan->good_CRC_th = is_active ? IWL_GOOD_CRC_TH_DEFAULT : + IWL_GOOD_CRC_TH_NEVER; /* Force use of chains B and C (0x6) for scan Rx for 4965 * Avoid A (0x1) because of its off-channel reception on A-band. diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index b55e4f3..b74a56c 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -2967,7 +2967,8 @@ static void iwl3945_bg_request_scan(struct work_struct *data) * is marked passive, we can do active scanning if we * detect transmissions. */ - scan->good_CRC_th = is_active ? IWL_GOOD_CRC_TH : 0; + scan->good_CRC_th = is_active ? IWL_GOOD_CRC_TH_DEFAULT : + IWL_GOOD_CRC_TH_DISABLED; band = IEEE80211_BAND_5GHZ; } else { IWL_WARN(priv, "Invalid scan band count\n"); diff --git a/drivers/net/wireless/p54/p54pci.c b/drivers/net/wireless/p54/p54pci.c index 269fda3..c24067f 100644 --- a/drivers/net/wireless/p54/p54pci.c +++ b/drivers/net/wireless/p54/p54pci.c @@ -246,7 +246,7 @@ static void p54p_check_tx_ring(struct ieee80211_hw *dev, u32 *index, u32 idx, i; i = (*index) % ring_limit; - (*index) = idx = le32_to_cpu(ring_control->device_idx[1]); + (*index) = idx = le32_to_cpu(ring_control->device_idx[ring_index]); idx %= ring_limit; while (i != idx) { |