diff options
| -rw-r--r-- | MAINTAINERS | 8 | ||||
| -rw-r--r-- | drivers/net/e1000/e1000_main.c | 1 | ||||
| -rw-r--r-- | drivers/net/forcedeth.c | 79 | ||||
| -rw-r--r-- | drivers/net/gianfar.c | 56 | ||||
| -rw-r--r-- | drivers/net/gianfar.h | 67 | ||||
| -rw-r--r-- | drivers/net/gianfar_ethtool.c | 20 | ||||
| -rw-r--r-- | drivers/net/gianfar_sysfs.c | 24 | ||||
| -rw-r--r-- | drivers/net/sky2.c | 52 | ||||
| -rw-r--r-- | drivers/net/sky2.h | 2 | ||||
| -rw-r--r-- | drivers/net/wireless/bcm43xx/bcm43xx_dma.h | 8 | ||||
| -rw-r--r-- | drivers/net/wireless/bcm43xx/bcm43xx_pio.c | 92 | ||||
| -rw-r--r-- | drivers/net/wireless/bcm43xx/bcm43xx_pio.h | 16 | ||||
| -rw-r--r-- | drivers/net/wireless/hostap/hostap_ioctl.c | 4 | ||||
| -rw-r--r-- | include/linux/netdevice.h | 18 | ||||
| -rw-r--r-- | include/net/ieee80211softmac.h | 5 | ||||
| -rw-r--r-- | net/ieee80211/softmac/ieee80211softmac_assoc.c | 20 | ||||
| -rw-r--r-- | net/ieee80211/softmac/ieee80211softmac_module.c | 2 | ||||
| -rw-r--r-- | net/ieee80211/softmac/ieee80211softmac_wx.c | 27 |
18 files changed, 354 insertions, 147 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index 4e1e8175eb6d..d6a8e5b434ec 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
| @@ -421,6 +421,14 @@ L: linux-hams@vger.kernel.org | |||
| 421 | W: http://www.baycom.org/~tom/ham/ham.html | 421 | W: http://www.baycom.org/~tom/ham/ham.html |
| 422 | S: Maintained | 422 | S: Maintained |
| 423 | 423 | ||
| 424 | BCM43XX WIRELESS DRIVER | ||
| 425 | P: Michael Buesch | ||
| 426 | M: mb@bu3sch.de | ||
| 427 | P: Stefano Brivio | ||
| 428 | M: st3@riseup.net | ||
| 429 | W: http://bcm43xx.berlios.de/ | ||
| 430 | S: Maintained | ||
| 431 | |||
| 424 | BEFS FILE SYSTEM | 432 | BEFS FILE SYSTEM |
| 425 | P: Sergey S. Kostyliov | 433 | P: Sergey S. Kostyliov |
| 426 | M: rathamahata@php4.ru | 434 | M: rathamahata@php4.ru |
diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index add8dc4aa7b0..c99e87838f92 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c | |||
| @@ -3768,6 +3768,7 @@ e1000_clean_rx_irq_ps(struct e1000_adapter *adapter, | |||
| 3768 | ps_page->ps_page[j] = NULL; | 3768 | ps_page->ps_page[j] = NULL; |
| 3769 | skb->len += length; | 3769 | skb->len += length; |
| 3770 | skb->data_len += length; | 3770 | skb->data_len += length; |
| 3771 | skb->truesize += length; | ||
| 3771 | } | 3772 | } |
| 3772 | 3773 | ||
| 3773 | copydone: | 3774 | copydone: |
diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c index 7627a75f4f7c..9788b1ef2e7d 100644 --- a/drivers/net/forcedeth.c +++ b/drivers/net/forcedeth.c | |||
| @@ -105,6 +105,7 @@ | |||
| 105 | * 0.50: 20 Jan 2006: Add 8021pq tagging support. | 105 | * 0.50: 20 Jan 2006: Add 8021pq tagging support. |
| 106 | * 0.51: 20 Jan 2006: Add 64bit consistent memory allocation for rings. | 106 | * 0.51: 20 Jan 2006: Add 64bit consistent memory allocation for rings. |
| 107 | * 0.52: 20 Jan 2006: Add MSI/MSIX support. | 107 | * 0.52: 20 Jan 2006: Add MSI/MSIX support. |
| 108 | * 0.53: 19 Mar 2006: Fix init from low power mode and add hw reset. | ||
| 108 | * | 109 | * |
| 109 | * Known bugs: | 110 | * Known bugs: |
| 110 | * We suspect that on some hardware no TX done interrupts are generated. | 111 | * We suspect that on some hardware no TX done interrupts are generated. |
| @@ -116,7 +117,7 @@ | |||
| 116 | * DEV_NEED_TIMERIRQ will not harm you on sane hardware, only generating a few | 117 | * DEV_NEED_TIMERIRQ will not harm you on sane hardware, only generating a few |
| 117 | * superfluous timer interrupts from the nic. | 118 | * superfluous timer interrupts from the nic. |
| 118 | */ | 119 | */ |
| 119 | #define FORCEDETH_VERSION "0.52" | 120 | #define FORCEDETH_VERSION "0.53" |
| 120 | #define DRV_NAME "forcedeth" | 121 | #define DRV_NAME "forcedeth" |
| 121 | 122 | ||
| 122 | #include <linux/module.h> | 123 | #include <linux/module.h> |
| @@ -160,6 +161,7 @@ | |||
| 160 | #define DEV_HAS_VLAN 0x0020 /* device supports vlan tagging and striping */ | 161 | #define DEV_HAS_VLAN 0x0020 /* device supports vlan tagging and striping */ |
| 161 | #define DEV_HAS_MSI 0x0040 /* device supports MSI */ | 162 | #define DEV_HAS_MSI 0x0040 /* device supports MSI */ |
| 162 | #define DEV_HAS_MSI_X 0x0080 /* device supports MSI-X */ | 163 | #define DEV_HAS_MSI_X 0x0080 /* device supports MSI-X */ |
| 164 | #define DEV_HAS_POWER_CNTRL 0x0100 /* device supports power savings */ | ||
| 163 | 165 | ||
| 164 | enum { | 166 | enum { |
| 165 | NvRegIrqStatus = 0x000, | 167 | NvRegIrqStatus = 0x000, |
| @@ -203,6 +205,8 @@ enum { | |||
| 203 | #define NVREG_MISC1_HD 0x02 | 205 | #define NVREG_MISC1_HD 0x02 |
| 204 | #define NVREG_MISC1_FORCE 0x3b0f3c | 206 | #define NVREG_MISC1_FORCE 0x3b0f3c |
| 205 | 207 | ||
| 208 | NvRegMacReset = 0x3c, | ||
| 209 | #define NVREG_MAC_RESET_ASSERT 0x0F3 | ||
| 206 | NvRegTransmitterControl = 0x084, | 210 | NvRegTransmitterControl = 0x084, |
| 207 | #define NVREG_XMITCTL_START 0x01 | 211 | #define NVREG_XMITCTL_START 0x01 |
| 208 | NvRegTransmitterStatus = 0x088, | 212 | NvRegTransmitterStatus = 0x088, |
| @@ -326,6 +330,10 @@ enum { | |||
| 326 | NvRegMSIXMap0 = 0x3e0, | 330 | NvRegMSIXMap0 = 0x3e0, |
| 327 | NvRegMSIXMap1 = 0x3e4, | 331 | NvRegMSIXMap1 = 0x3e4, |
| 328 | NvRegMSIXIrqStatus = 0x3f0, | 332 | NvRegMSIXIrqStatus = 0x3f0, |
| 333 | |||
| 334 | NvRegPowerState2 = 0x600, | ||
| 335 | #define NVREG_POWERSTATE2_POWERUP_MASK 0x0F11 | ||
| 336 | #define NVREG_POWERSTATE2_POWERUP_REV_A3 0x0001 | ||
| 329 | }; | 337 | }; |
| 330 | 338 | ||
| 331 | /* Big endian: should work, but is untested */ | 339 | /* Big endian: should work, but is untested */ |
| @@ -414,7 +422,8 @@ typedef union _ring_type { | |||
| 414 | #define NV_RX3_VLAN_TAG_MASK (0x0000FFFF) | 422 | #define NV_RX3_VLAN_TAG_MASK (0x0000FFFF) |
| 415 | 423 | ||
| 416 | /* Miscelaneous hardware related defines: */ | 424 | /* Miscelaneous hardware related defines: */ |
| 417 | #define NV_PCI_REGSZ 0x270 | 425 | #define NV_PCI_REGSZ_VER1 0x270 |
| 426 | #define NV_PCI_REGSZ_VER2 0x604 | ||
| 418 | 427 | ||
| 419 | /* various timeout delays: all in usec */ | 428 | /* various timeout delays: all in usec */ |
| 420 | #define NV_TXRX_RESET_DELAY 4 | 429 | #define NV_TXRX_RESET_DELAY 4 |
| @@ -431,6 +440,7 @@ typedef union _ring_type { | |||
| 431 | #define NV_MIIBUSY_DELAY 50 | 440 | #define NV_MIIBUSY_DELAY 50 |
| 432 | #define NV_MIIPHY_DELAY 10 | 441 | #define NV_MIIPHY_DELAY 10 |
| 433 | #define NV_MIIPHY_DELAYMAX 10000 | 442 | #define NV_MIIPHY_DELAYMAX 10000 |
| 443 | #define NV_MAC_RESET_DELAY 64 | ||
| 434 | 444 | ||
| 435 | #define NV_WAKEUPPATTERNS 5 | 445 | #define NV_WAKEUPPATTERNS 5 |
| 436 | #define NV_WAKEUPMASKENTRIES 4 | 446 | #define NV_WAKEUPMASKENTRIES 4 |
| @@ -552,6 +562,8 @@ struct fe_priv { | |||
| 552 | u32 desc_ver; | 562 | u32 desc_ver; |
| 553 | u32 txrxctl_bits; | 563 | u32 txrxctl_bits; |
| 554 | u32 vlanctl_bits; | 564 | u32 vlanctl_bits; |
| 565 | u32 driver_data; | ||
| 566 | u32 register_size; | ||
| 555 | 567 | ||
| 556 | void __iomem *base; | 568 | void __iomem *base; |
| 557 | 569 | ||
| @@ -919,6 +931,24 @@ static void nv_txrx_reset(struct net_device *dev) | |||
| 919 | pci_push(base); | 931 | pci_push(base); |
| 920 | } | 932 | } |
| 921 | 933 | ||
| 934 | static void nv_mac_reset(struct net_device *dev) | ||
| 935 | { | ||
| 936 | struct fe_priv *np = netdev_priv(dev); | ||
| 937 | u8 __iomem *base = get_hwbase(dev); | ||
| 938 | |||
| 939 | dprintk(KERN_DEBUG "%s: nv_mac_reset\n", dev->name); | ||
| 940 | writel(NVREG_TXRXCTL_BIT2 | NVREG_TXRXCTL_RESET | np->txrxctl_bits, base + NvRegTxRxControl); | ||
| 941 | pci_push(base); | ||
| 942 | writel(NVREG_MAC_RESET_ASSERT, base + NvRegMacReset); | ||
| 943 | pci_push(base); | ||
| 944 | udelay(NV_MAC_RESET_DELAY); | ||
| 945 | writel(0, base + NvRegMacReset); | ||
| 946 | pci_push(base); | ||
| 947 | udelay(NV_MAC_RESET_DELAY); | ||
| 948 | writel(NVREG_TXRXCTL_BIT2 | np->txrxctl_bits, base + NvRegTxRxControl); | ||
| 949 | pci_push(base); | ||
| 950 | } | ||
| 951 | |||
| 922 | /* | 952 | /* |
| 923 | * nv_get_stats: dev->get_stats function | 953 | * nv_get_stats: dev->get_stats function |
| 924 | * Get latest stats value from the nic. | 954 | * Get latest stats value from the nic. |
| @@ -1331,7 +1361,7 @@ static void nv_tx_timeout(struct net_device *dev) | |||
| 1331 | dev->name, (unsigned long)np->ring_addr, | 1361 | dev->name, (unsigned long)np->ring_addr, |
| 1332 | np->next_tx, np->nic_tx); | 1362 | np->next_tx, np->nic_tx); |
| 1333 | printk(KERN_INFO "%s: Dumping tx registers\n", dev->name); | 1363 | printk(KERN_INFO "%s: Dumping tx registers\n", dev->name); |
| 1334 | for (i=0;i<0x400;i+= 32) { | 1364 | for (i=0;i<=np->register_size;i+= 32) { |
| 1335 | printk(KERN_INFO "%3x: %08x %08x %08x %08x %08x %08x %08x %08x\n", | 1365 | printk(KERN_INFO "%3x: %08x %08x %08x %08x %08x %08x %08x %08x\n", |
| 1336 | i, | 1366 | i, |
| 1337 | readl(base + i + 0), readl(base + i + 4), | 1367 | readl(base + i + 0), readl(base + i + 4), |
| @@ -2488,11 +2518,11 @@ static int nv_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd) | |||
| 2488 | } | 2518 | } |
| 2489 | 2519 | ||
| 2490 | #define FORCEDETH_REGS_VER 1 | 2520 | #define FORCEDETH_REGS_VER 1 |
| 2491 | #define FORCEDETH_REGS_SIZE 0x400 /* 256 32-bit registers */ | ||
| 2492 | 2521 | ||
| 2493 | static int nv_get_regs_len(struct net_device *dev) | 2522 | static int nv_get_regs_len(struct net_device *dev) |
| 2494 | { | 2523 | { |
| 2495 | return FORCEDETH_REGS_SIZE; | 2524 | struct fe_priv *np = netdev_priv(dev); |
| 2525 | return np->register_size; | ||
| 2496 | } | 2526 | } |
| 2497 | 2527 | ||
| 2498 | static void nv_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *buf) | 2528 | static void nv_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *buf) |
| @@ -2504,7 +2534,7 @@ static void nv_get_regs(struct net_device *dev, struct ethtool_regs *regs, void | |||
| 2504 | 2534 | ||
| 2505 | regs->version = FORCEDETH_REGS_VER; | 2535 | regs->version = FORCEDETH_REGS_VER; |
| 2506 | spin_lock_irq(&np->lock); | 2536 | spin_lock_irq(&np->lock); |
| 2507 | for (i=0;i<FORCEDETH_REGS_SIZE/sizeof(u32);i++) | 2537 | for (i = 0;i <= np->register_size/sizeof(u32); i++) |
| 2508 | rbuf[i] = readl(base + i*sizeof(u32)); | 2538 | rbuf[i] = readl(base + i*sizeof(u32)); |
| 2509 | spin_unlock_irq(&np->lock); | 2539 | spin_unlock_irq(&np->lock); |
| 2510 | } | 2540 | } |
| @@ -2608,6 +2638,8 @@ static int nv_open(struct net_device *dev) | |||
| 2608 | dprintk(KERN_DEBUG "nv_open: begin\n"); | 2638 | dprintk(KERN_DEBUG "nv_open: begin\n"); |
| 2609 | 2639 | ||
| 2610 | /* 1) erase previous misconfiguration */ | 2640 | /* 1) erase previous misconfiguration */ |
| 2641 | if (np->driver_data & DEV_HAS_POWER_CNTRL) | ||
| 2642 | nv_mac_reset(dev); | ||
| 2611 | /* 4.1-1: stop adapter: ignored, 4.3 seems to be overkill */ | 2643 | /* 4.1-1: stop adapter: ignored, 4.3 seems to be overkill */ |
| 2612 | writel(NVREG_MCASTADDRA_FORCE, base + NvRegMulticastAddrA); | 2644 | writel(NVREG_MCASTADDRA_FORCE, base + NvRegMulticastAddrA); |
| 2613 | writel(0, base + NvRegMulticastAddrB); | 2645 | writel(0, base + NvRegMulticastAddrB); |
| @@ -2878,6 +2910,7 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i | |||
| 2878 | unsigned long addr; | 2910 | unsigned long addr; |
| 2879 | u8 __iomem *base; | 2911 | u8 __iomem *base; |
| 2880 | int err, i; | 2912 | int err, i; |
| 2913 | u32 powerstate; | ||
| 2881 | 2914 | ||
| 2882 | dev = alloc_etherdev(sizeof(struct fe_priv)); | 2915 | dev = alloc_etherdev(sizeof(struct fe_priv)); |
| 2883 | err = -ENOMEM; | 2916 | err = -ENOMEM; |
| @@ -2910,6 +2943,11 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i | |||
| 2910 | if (err < 0) | 2943 | if (err < 0) |
| 2911 | goto out_disable; | 2944 | goto out_disable; |
| 2912 | 2945 | ||
| 2946 | if (id->driver_data & (DEV_HAS_VLAN|DEV_HAS_MSI_X|DEV_HAS_POWER_CNTRL)) | ||
| 2947 | np->register_size = NV_PCI_REGSZ_VER2; | ||
| 2948 | else | ||
| 2949 | np->register_size = NV_PCI_REGSZ_VER1; | ||
| 2950 | |||
| 2913 | err = -EINVAL; | 2951 | err = -EINVAL; |
| 2914 | addr = 0; | 2952 | addr = 0; |
| 2915 | for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) { | 2953 | for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) { |
| @@ -2918,7 +2956,7 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i | |||
| 2918 | pci_resource_len(pci_dev, i), | 2956 | pci_resource_len(pci_dev, i), |
| 2919 | pci_resource_flags(pci_dev, i)); | 2957 | pci_resource_flags(pci_dev, i)); |
| 2920 | if (pci_resource_flags(pci_dev, i) & IORESOURCE_MEM && | 2958 | if (pci_resource_flags(pci_dev, i) & IORESOURCE_MEM && |
| 2921 | pci_resource_len(pci_dev, i) >= NV_PCI_REGSZ) { | 2959 | pci_resource_len(pci_dev, i) >= np->register_size) { |
| 2922 | addr = pci_resource_start(pci_dev, i); | 2960 | addr = pci_resource_start(pci_dev, i); |
| 2923 | break; | 2961 | break; |
| 2924 | } | 2962 | } |
| @@ -2929,6 +2967,9 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i | |||
| 2929 | goto out_relreg; | 2967 | goto out_relreg; |
| 2930 | } | 2968 | } |
| 2931 | 2969 | ||
| 2970 | /* copy of driver data */ | ||
| 2971 | np->driver_data = id->driver_data; | ||
| 2972 | |||
| 2932 | /* handle different descriptor versions */ | 2973 | /* handle different descriptor versions */ |
| 2933 | if (id->driver_data & DEV_HAS_HIGH_DMA) { | 2974 | if (id->driver_data & DEV_HAS_HIGH_DMA) { |
| 2934 | /* packet format 3: supports 40-bit addressing */ | 2975 | /* packet format 3: supports 40-bit addressing */ |
| @@ -2986,7 +3027,7 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i | |||
| 2986 | } | 3027 | } |
| 2987 | 3028 | ||
| 2988 | err = -ENOMEM; | 3029 | err = -ENOMEM; |
| 2989 | np->base = ioremap(addr, NV_PCI_REGSZ); | 3030 | np->base = ioremap(addr, np->register_size); |
| 2990 | if (!np->base) | 3031 | if (!np->base) |
| 2991 | goto out_relreg; | 3032 | goto out_relreg; |
| 2992 | dev->base_addr = (unsigned long)np->base; | 3033 | dev->base_addr = (unsigned long)np->base; |
| @@ -3062,6 +3103,20 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i | |||
| 3062 | writel(0, base + NvRegWakeUpFlags); | 3103 | writel(0, base + NvRegWakeUpFlags); |
| 3063 | np->wolenabled = 0; | 3104 | np->wolenabled = 0; |
| 3064 | 3105 | ||
| 3106 | if (id->driver_data & DEV_HAS_POWER_CNTRL) { | ||
| 3107 | u8 revision_id; | ||
| 3108 | pci_read_config_byte(pci_dev, PCI_REVISION_ID, &revision_id); | ||
| 3109 | |||
| 3110 | /* take phy and nic out of low power mode */ | ||
| 3111 | powerstate = readl(base + NvRegPowerState2); | ||
| 3112 | powerstate &= ~NVREG_POWERSTATE2_POWERUP_MASK; | ||
| 3113 | if ((id->device == PCI_DEVICE_ID_NVIDIA_NVENET_12 || | ||
| 3114 | id->device == PCI_DEVICE_ID_NVIDIA_NVENET_13) && | ||
| 3115 | revision_id >= 0xA3) | ||
| 3116 | powerstate |= NVREG_POWERSTATE2_POWERUP_REV_A3; | ||
| 3117 | writel(powerstate, base + NvRegPowerState2); | ||
| 3118 | } | ||
| 3119 | |||
| 3065 | if (np->desc_ver == DESC_VER_1) { | 3120 | if (np->desc_ver == DESC_VER_1) { |
| 3066 | np->tx_flags = NV_TX_VALID; | 3121 | np->tx_flags = NV_TX_VALID; |
| 3067 | } else { | 3122 | } else { |
| @@ -3223,19 +3278,19 @@ static struct pci_device_id pci_tbl[] = { | |||
| 3223 | }, | 3278 | }, |
| 3224 | { /* MCP51 Ethernet Controller */ | 3279 | { /* MCP51 Ethernet Controller */ |
| 3225 | PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_12), | 3280 | PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_12), |
| 3226 | .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA, | 3281 | .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL, |
| 3227 | }, | 3282 | }, |
| 3228 | { /* MCP51 Ethernet Controller */ | 3283 | { /* MCP51 Ethernet Controller */ |
| 3229 | PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_13), | 3284 | PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_13), |
| 3230 | .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA, | 3285 | .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL, |
| 3231 | }, | 3286 | }, |
| 3232 | { /* MCP55 Ethernet Controller */ | 3287 | { /* MCP55 Ethernet Controller */ |
| 3233 | PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_14), | 3288 | PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_14), |
| 3234 | .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_VLAN|DEV_HAS_MSI|DEV_HAS_MSI_X, | 3289 | .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_VLAN|DEV_HAS_MSI|DEV_HAS_MSI_X|DEV_HAS_POWER_CNTRL, |
| 3235 | }, | 3290 | }, |
| 3236 | { /* MCP55 Ethernet Controller */ | 3291 | { /* MCP55 Ethernet Controller */ |
| 3237 | PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_15), | 3292 | PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_15), |
| 3238 | .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_VLAN|DEV_HAS_MSI|DEV_HAS_MSI_X, | 3293 | .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_VLAN|DEV_HAS_MSI|DEV_HAS_MSI_X|DEV_HAS_POWER_CNTRL, |
| 3239 | }, | 3294 | }, |
| 3240 | {0,}, | 3295 | {0,}, |
| 3241 | }; | 3296 | }; |
diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c index 771e25d8c417..218d31764c52 100644 --- a/drivers/net/gianfar.c +++ b/drivers/net/gianfar.c | |||
| @@ -210,7 +210,8 @@ static int gfar_probe(struct platform_device *pdev) | |||
| 210 | goto regs_fail; | 210 | goto regs_fail; |
| 211 | } | 211 | } |
| 212 | 212 | ||
| 213 | spin_lock_init(&priv->lock); | 213 | spin_lock_init(&priv->txlock); |
| 214 | spin_lock_init(&priv->rxlock); | ||
| 214 | 215 | ||
| 215 | platform_set_drvdata(pdev, dev); | 216 | platform_set_drvdata(pdev, dev); |
| 216 | 217 | ||
| @@ -515,11 +516,13 @@ void stop_gfar(struct net_device *dev) | |||
| 515 | phy_stop(priv->phydev); | 516 | phy_stop(priv->phydev); |
| 516 | 517 | ||
| 517 | /* Lock it down */ | 518 | /* Lock it down */ |
| 518 | spin_lock_irqsave(&priv->lock, flags); | 519 | spin_lock_irqsave(&priv->txlock, flags); |
| 520 | spin_lock(&priv->rxlock); | ||
| 519 | 521 | ||
| 520 | gfar_halt(dev); | 522 | gfar_halt(dev); |
| 521 | 523 | ||
| 522 | spin_unlock_irqrestore(&priv->lock, flags); | 524 | spin_unlock(&priv->rxlock); |
| 525 | spin_unlock_irqrestore(&priv->txlock, flags); | ||
| 523 | 526 | ||
| 524 | /* Free the IRQs */ | 527 | /* Free the IRQs */ |
| 525 | if (priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_MULTI_INTR) { | 528 | if (priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_MULTI_INTR) { |
| @@ -605,14 +608,15 @@ void gfar_start(struct net_device *dev) | |||
| 605 | tempval |= DMACTRL_INIT_SETTINGS; | 608 | tempval |= DMACTRL_INIT_SETTINGS; |
| 606 | gfar_write(&priv->regs->dmactrl, tempval); | 609 | gfar_write(&priv->regs->dmactrl, tempval); |
| 607 | 610 | ||
| 608 | /* Clear THLT, so that the DMA starts polling now */ | ||
| 609 | gfar_write(®s->tstat, TSTAT_CLEAR_THALT); | ||
| 610 | |||
| 611 | /* Make sure we aren't stopped */ | 611 | /* Make sure we aren't stopped */ |
| 612 | tempval = gfar_read(&priv->regs->dmactrl); | 612 | tempval = gfar_read(&priv->regs->dmactrl); |
| 613 | tempval &= ~(DMACTRL_GRS | DMACTRL_GTS); | 613 | tempval &= ~(DMACTRL_GRS | DMACTRL_GTS); |
| 614 | gfar_write(&priv->regs->dmactrl, tempval); | 614 | gfar_write(&priv->regs->dmactrl, tempval); |
| 615 | 615 | ||
| 616 | /* Clear THLT/RHLT, so that the DMA starts polling now */ | ||
| 617 | gfar_write(®s->tstat, TSTAT_CLEAR_THALT); | ||
| 618 | gfar_write(®s->rstat, RSTAT_CLEAR_RHALT); | ||
| 619 | |||
| 616 | /* Unmask the interrupts we look for */ | 620 | /* Unmask the interrupts we look for */ |
| 617 | gfar_write(®s->imask, IMASK_DEFAULT); | 621 | gfar_write(®s->imask, IMASK_DEFAULT); |
| 618 | } | 622 | } |
| @@ -928,12 +932,13 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
| 928 | struct txfcb *fcb = NULL; | 932 | struct txfcb *fcb = NULL; |
| 929 | struct txbd8 *txbdp; | 933 | struct txbd8 *txbdp; |
| 930 | u16 status; | 934 | u16 status; |
| 935 | unsigned long flags; | ||
| 931 | 936 | ||
| 932 | /* Update transmit stats */ | 937 | /* Update transmit stats */ |
| 933 | priv->stats.tx_bytes += skb->len; | 938 | priv->stats.tx_bytes += skb->len; |
| 934 | 939 | ||
| 935 | /* Lock priv now */ | 940 | /* Lock priv now */ |
| 936 | spin_lock_irq(&priv->lock); | 941 | spin_lock_irqsave(&priv->txlock, flags); |
| 937 | 942 | ||
| 938 | /* Point at the first free tx descriptor */ | 943 | /* Point at the first free tx descriptor */ |
| 939 | txbdp = priv->cur_tx; | 944 | txbdp = priv->cur_tx; |
| @@ -1004,7 +1009,7 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
| 1004 | gfar_write(&priv->regs->tstat, TSTAT_CLEAR_THALT); | 1009 | gfar_write(&priv->regs->tstat, TSTAT_CLEAR_THALT); |
| 1005 | 1010 | ||
| 1006 | /* Unlock priv */ | 1011 | /* Unlock priv */ |
| 1007 | spin_unlock_irq(&priv->lock); | 1012 | spin_unlock_irqrestore(&priv->txlock, flags); |
| 1008 | 1013 | ||
| 1009 | return 0; | 1014 | return 0; |
| 1010 | } | 1015 | } |
| @@ -1049,7 +1054,7 @@ static void gfar_vlan_rx_register(struct net_device *dev, | |||
| 1049 | unsigned long flags; | 1054 | unsigned long flags; |
| 1050 | u32 tempval; | 1055 | u32 tempval; |
| 1051 | 1056 | ||
| 1052 | spin_lock_irqsave(&priv->lock, flags); | 1057 | spin_lock_irqsave(&priv->rxlock, flags); |
| 1053 | 1058 | ||
| 1054 | priv->vlgrp = grp; | 1059 | priv->vlgrp = grp; |
| 1055 | 1060 | ||
| @@ -1076,7 +1081,7 @@ static void gfar_vlan_rx_register(struct net_device *dev, | |||
| 1076 | gfar_write(&priv->regs->rctrl, tempval); | 1081 | gfar_write(&priv->regs->rctrl, tempval); |
| 1077 | } | 1082 | } |
| 1078 | 1083 | ||
| 1079 | spin_unlock_irqrestore(&priv->lock, flags); | 1084 | spin_unlock_irqrestore(&priv->rxlock, flags); |
| 1080 | } | 1085 | } |
| 1081 | 1086 | ||
| 1082 | 1087 | ||
| @@ -1085,12 +1090,12 @@ static void gfar_vlan_rx_kill_vid(struct net_device *dev, uint16_t vid) | |||
| 1085 | struct gfar_private *priv = netdev_priv(dev); | 1090 | struct gfar_private *priv = netdev_priv(dev); |
| 1086 | unsigned long flags; | 1091 | unsigned long flags; |
| 1087 | 1092 | ||
| 1088 | spin_lock_irqsave(&priv->lock, flags); | 1093 | spin_lock_irqsave(&priv->rxlock, flags); |
| 1089 | 1094 | ||
| 1090 | if (priv->vlgrp) | 1095 | if (priv->vlgrp) |
| 1091 | priv->vlgrp->vlan_devices[vid] = NULL; | 1096 | priv->vlgrp->vlan_devices[vid] = NULL; |
| 1092 | 1097 | ||
| 1093 | spin_unlock_irqrestore(&priv->lock, flags); | 1098 | spin_unlock_irqrestore(&priv->rxlock, flags); |
| 1094 | } | 1099 | } |
| 1095 | 1100 | ||
| 1096 | 1101 | ||
| @@ -1179,7 +1184,7 @@ static irqreturn_t gfar_transmit(int irq, void *dev_id, struct pt_regs *regs) | |||
| 1179 | gfar_write(&priv->regs->ievent, IEVENT_TX_MASK); | 1184 | gfar_write(&priv->regs->ievent, IEVENT_TX_MASK); |
| 1180 | 1185 | ||
| 1181 | /* Lock priv */ | 1186 | /* Lock priv */ |
| 1182 | spin_lock(&priv->lock); | 1187 | spin_lock(&priv->txlock); |
| 1183 | bdp = priv->dirty_tx; | 1188 | bdp = priv->dirty_tx; |
| 1184 | while ((bdp->status & TXBD_READY) == 0) { | 1189 | while ((bdp->status & TXBD_READY) == 0) { |
| 1185 | /* If dirty_tx and cur_tx are the same, then either the */ | 1190 | /* If dirty_tx and cur_tx are the same, then either the */ |
| @@ -1224,7 +1229,7 @@ static irqreturn_t gfar_transmit(int irq, void *dev_id, struct pt_regs *regs) | |||
| 1224 | else | 1229 | else |
| 1225 | gfar_write(&priv->regs->txic, 0); | 1230 | gfar_write(&priv->regs->txic, 0); |
| 1226 | 1231 | ||
| 1227 | spin_unlock(&priv->lock); | 1232 | spin_unlock(&priv->txlock); |
| 1228 | 1233 | ||
| 1229 | return IRQ_HANDLED; | 1234 | return IRQ_HANDLED; |
| 1230 | } | 1235 | } |
| @@ -1305,9 +1310,10 @@ irqreturn_t gfar_receive(int irq, void *dev_id, struct pt_regs *regs) | |||
| 1305 | { | 1310 | { |
| 1306 | struct net_device *dev = (struct net_device *) dev_id; | 1311 | struct net_device *dev = (struct net_device *) dev_id; |
| 1307 | struct gfar_private *priv = netdev_priv(dev); | 1312 | struct gfar_private *priv = netdev_priv(dev); |
| 1308 | |||
| 1309 | #ifdef CONFIG_GFAR_NAPI | 1313 | #ifdef CONFIG_GFAR_NAPI |
| 1310 | u32 tempval; | 1314 | u32 tempval; |
| 1315 | #else | ||
| 1316 | unsigned long flags; | ||
| 1311 | #endif | 1317 | #endif |
| 1312 | 1318 | ||
| 1313 | /* Clear IEVENT, so rx interrupt isn't called again | 1319 | /* Clear IEVENT, so rx interrupt isn't called again |
| @@ -1330,7 +1336,7 @@ irqreturn_t gfar_receive(int irq, void *dev_id, struct pt_regs *regs) | |||
| 1330 | } | 1336 | } |
| 1331 | #else | 1337 | #else |
| 1332 | 1338 | ||
| 1333 | spin_lock(&priv->lock); | 1339 | spin_lock_irqsave(&priv->rxlock, flags); |
| 1334 | gfar_clean_rx_ring(dev, priv->rx_ring_size); | 1340 | gfar_clean_rx_ring(dev, priv->rx_ring_size); |
| 1335 | 1341 | ||
| 1336 | /* If we are coalescing interrupts, update the timer */ | 1342 | /* If we are coalescing interrupts, update the timer */ |
| @@ -1341,7 +1347,7 @@ irqreturn_t gfar_receive(int irq, void *dev_id, struct pt_regs *regs) | |||
| 1341 | else | 1347 | else |
| 1342 | gfar_write(&priv->regs->rxic, 0); | 1348 | gfar_write(&priv->regs->rxic, 0); |
| 1343 | 1349 | ||
| 1344 | spin_unlock(&priv->lock); | 1350 | spin_unlock_irqrestore(&priv->rxlock, flags); |
| 1345 | #endif | 1351 | #endif |
| 1346 | 1352 | ||
| 1347 | return IRQ_HANDLED; | 1353 | return IRQ_HANDLED; |
| @@ -1490,13 +1496,6 @@ int gfar_clean_rx_ring(struct net_device *dev, int rx_work_limit) | |||
| 1490 | /* Update the current rxbd pointer to be the next one */ | 1496 | /* Update the current rxbd pointer to be the next one */ |
| 1491 | priv->cur_rx = bdp; | 1497 | priv->cur_rx = bdp; |
| 1492 | 1498 | ||
| 1493 | /* If no packets have arrived since the | ||
| 1494 | * last one we processed, clear the IEVENT RX and | ||
| 1495 | * BSY bits so that another interrupt won't be | ||
| 1496 | * generated when we set IMASK */ | ||
| 1497 | if (bdp->status & RXBD_EMPTY) | ||
| 1498 | gfar_write(&priv->regs->ievent, IEVENT_RX_MASK); | ||
| 1499 | |||
| 1500 | return howmany; | 1499 | return howmany; |
| 1501 | } | 1500 | } |
| 1502 | 1501 | ||
| @@ -1516,7 +1515,7 @@ static int gfar_poll(struct net_device *dev, int *budget) | |||
| 1516 | rx_work_limit -= howmany; | 1515 | rx_work_limit -= howmany; |
| 1517 | *budget -= howmany; | 1516 | *budget -= howmany; |
| 1518 | 1517 | ||
| 1519 | if (rx_work_limit >= 0) { | 1518 | if (rx_work_limit > 0) { |
| 1520 | netif_rx_complete(dev); | 1519 | netif_rx_complete(dev); |
| 1521 | 1520 | ||
| 1522 | /* Clear the halt bit in RSTAT */ | 1521 | /* Clear the halt bit in RSTAT */ |
| @@ -1533,7 +1532,8 @@ static int gfar_poll(struct net_device *dev, int *budget) | |||
| 1533 | gfar_write(&priv->regs->rxic, 0); | 1532 | gfar_write(&priv->regs->rxic, 0); |
| 1534 | } | 1533 | } |
| 1535 | 1534 | ||
| 1536 | return (rx_work_limit < 0) ? 1 : 0; | 1535 | /* Return 1 if there's more work to do */ |
| 1536 | return (rx_work_limit > 0) ? 0 : 1; | ||
| 1537 | } | 1537 | } |
| 1538 | #endif | 1538 | #endif |
| 1539 | 1539 | ||
| @@ -1629,7 +1629,7 @@ static void adjust_link(struct net_device *dev) | |||
| 1629 | struct phy_device *phydev = priv->phydev; | 1629 | struct phy_device *phydev = priv->phydev; |
| 1630 | int new_state = 0; | 1630 | int new_state = 0; |
| 1631 | 1631 | ||
| 1632 | spin_lock_irqsave(&priv->lock, flags); | 1632 | spin_lock_irqsave(&priv->txlock, flags); |
| 1633 | if (phydev->link) { | 1633 | if (phydev->link) { |
| 1634 | u32 tempval = gfar_read(®s->maccfg2); | 1634 | u32 tempval = gfar_read(®s->maccfg2); |
| 1635 | u32 ecntrl = gfar_read(®s->ecntrl); | 1635 | u32 ecntrl = gfar_read(®s->ecntrl); |
| @@ -1694,7 +1694,7 @@ static void adjust_link(struct net_device *dev) | |||
| 1694 | if (new_state && netif_msg_link(priv)) | 1694 | if (new_state && netif_msg_link(priv)) |
| 1695 | phy_print_status(phydev); | 1695 | phy_print_status(phydev); |
| 1696 | 1696 | ||
| 1697 | spin_unlock_irqrestore(&priv->lock, flags); | 1697 | spin_unlock_irqrestore(&priv->txlock, flags); |
| 1698 | } | 1698 | } |
| 1699 | 1699 | ||
| 1700 | /* Update the hash table based on the current list of multicast | 1700 | /* Update the hash table based on the current list of multicast |
diff --git a/drivers/net/gianfar.h b/drivers/net/gianfar.h index d37d5401be6e..127c98cf3336 100644 --- a/drivers/net/gianfar.h +++ b/drivers/net/gianfar.h | |||
| @@ -656,43 +656,62 @@ struct gfar { | |||
| 656 | * the buffer descriptor determines the actual condition. | 656 | * the buffer descriptor determines the actual condition. |
| 657 | */ | 657 | */ |
| 658 | struct gfar_private { | 658 | struct gfar_private { |
| 659 | /* pointers to arrays of skbuffs for tx and rx */ | 659 | /* Fields controlled by TX lock */ |
| 660 | spinlock_t txlock; | ||
| 661 | |||
| 662 | /* Pointer to the array of skbuffs */ | ||
| 660 | struct sk_buff ** tx_skbuff; | 663 | struct sk_buff ** tx_skbuff; |
| 661 | struct sk_buff ** rx_skbuff; | ||
| 662 | 664 | ||
| 663 | /* indices pointing to the next free sbk in skb arrays */ | 665 | /* next free skb in the array */ |
| 664 | u16 skb_curtx; | 666 | u16 skb_curtx; |
| 665 | u16 skb_currx; | ||
| 666 | 667 | ||
| 667 | /* index of the first skb which hasn't been transmitted | 668 | /* First skb in line to be transmitted */ |
| 668 | * yet. */ | ||
| 669 | u16 skb_dirtytx; | 669 | u16 skb_dirtytx; |
| 670 | 670 | ||
| 671 | /* Configuration info for the coalescing features */ | 671 | /* Configuration info for the coalescing features */ |
| 672 | unsigned char txcoalescing; | 672 | unsigned char txcoalescing; |
| 673 | unsigned short txcount; | 673 | unsigned short txcount; |
| 674 | unsigned short txtime; | 674 | unsigned short txtime; |
| 675 | |||
| 676 | /* Buffer descriptor pointers */ | ||
| 677 | struct txbd8 *tx_bd_base; /* First tx buffer descriptor */ | ||
| 678 | struct txbd8 *cur_tx; /* Next free ring entry */ | ||
| 679 | struct txbd8 *dirty_tx; /* First buffer in line | ||
| 680 | to be transmitted */ | ||
| 681 | unsigned int tx_ring_size; | ||
| 682 | |||
| 683 | /* RX Locked fields */ | ||
| 684 | spinlock_t rxlock; | ||
| 685 | |||
| 686 | /* skb array and index */ | ||
| 687 | struct sk_buff ** rx_skbuff; | ||
| 688 | u16 skb_currx; | ||
| 689 | |||
| 690 | /* RX Coalescing values */ | ||
| 675 | unsigned char rxcoalescing; | 691 | unsigned char rxcoalescing; |
| 676 | unsigned short rxcount; | 692 | unsigned short rxcount; |
| 677 | unsigned short rxtime; | 693 | unsigned short rxtime; |
| 678 | 694 | ||
| 679 | /* GFAR addresses */ | 695 | struct rxbd8 *rx_bd_base; /* First Rx buffers */ |
| 680 | struct rxbd8 *rx_bd_base; /* Base addresses of Rx and Tx Buffers */ | ||
| 681 | struct txbd8 *tx_bd_base; | ||
| 682 | struct rxbd8 *cur_rx; /* Next free rx ring entry */ | 696 | struct rxbd8 *cur_rx; /* Next free rx ring entry */ |
| 683 | struct txbd8 *cur_tx; /* Next free ring entry */ | 697 | |
| 684 | struct txbd8 *dirty_tx; /* The Ring entry to be freed. */ | 698 | /* RX parameters */ |
| 685 | struct gfar __iomem *regs; /* Pointer to the GFAR memory mapped Registers */ | 699 | unsigned int rx_ring_size; |
| 686 | u32 __iomem *hash_regs[16]; | ||
| 687 | int hash_width; | ||
| 688 | struct net_device_stats stats; /* linux network statistics */ | ||
| 689 | struct gfar_extra_stats extra_stats; | ||
| 690 | spinlock_t lock; | ||
| 691 | unsigned int rx_buffer_size; | 700 | unsigned int rx_buffer_size; |
| 692 | unsigned int rx_stash_size; | 701 | unsigned int rx_stash_size; |
| 693 | unsigned int rx_stash_index; | 702 | unsigned int rx_stash_index; |
| 694 | unsigned int tx_ring_size; | 703 | |
| 695 | unsigned int rx_ring_size; | 704 | struct vlan_group *vlgrp; |
| 705 | |||
| 706 | /* Unprotected fields */ | ||
| 707 | /* Pointer to the GFAR memory mapped Registers */ | ||
| 708 | struct gfar __iomem *regs; | ||
| 709 | |||
| 710 | /* Hash registers and their width */ | ||
| 711 | u32 __iomem *hash_regs[16]; | ||
| 712 | int hash_width; | ||
| 713 | |||
| 714 | /* global parameters */ | ||
| 696 | unsigned int fifo_threshold; | 715 | unsigned int fifo_threshold; |
| 697 | unsigned int fifo_starve; | 716 | unsigned int fifo_starve; |
| 698 | unsigned int fifo_starve_off; | 717 | unsigned int fifo_starve_off; |
| @@ -702,13 +721,15 @@ struct gfar_private { | |||
| 702 | extended_hash:1, | 721 | extended_hash:1, |
| 703 | bd_stash_en:1; | 722 | bd_stash_en:1; |
| 704 | unsigned short padding; | 723 | unsigned short padding; |
| 705 | struct vlan_group *vlgrp; | 724 | |
| 706 | /* Info structure initialized by board setup code */ | ||
| 707 | unsigned int interruptTransmit; | 725 | unsigned int interruptTransmit; |
| 708 | unsigned int interruptReceive; | 726 | unsigned int interruptReceive; |
| 709 | unsigned int interruptError; | 727 | unsigned int interruptError; |
| 728 | |||
| 729 | /* info structure initialized by platform code */ | ||
| 710 | struct gianfar_platform_data *einfo; | 730 | struct gianfar_platform_data *einfo; |
| 711 | 731 | ||
| 732 | /* PHY stuff */ | ||
| 712 | struct phy_device *phydev; | 733 | struct phy_device *phydev; |
| 713 | struct mii_bus *mii_bus; | 734 | struct mii_bus *mii_bus; |
| 714 | int oldspeed; | 735 | int oldspeed; |
| @@ -716,6 +737,10 @@ struct gfar_private { | |||
| 716 | int oldlink; | 737 | int oldlink; |
| 717 | 738 | ||
| 718 | uint32_t msg_enable; | 739 | uint32_t msg_enable; |
| 740 | |||
| 741 | /* Network Statistics */ | ||
| 742 | struct net_device_stats stats; | ||
| 743 | struct gfar_extra_stats extra_stats; | ||
| 719 | }; | 744 | }; |
| 720 | 745 | ||
| 721 | static inline u32 gfar_read(volatile unsigned __iomem *addr) | 746 | static inline u32 gfar_read(volatile unsigned __iomem *addr) |
diff --git a/drivers/net/gianfar_ethtool.c b/drivers/net/gianfar_ethtool.c index 5de7b2e259dc..d69698c695ef 100644 --- a/drivers/net/gianfar_ethtool.c +++ b/drivers/net/gianfar_ethtool.c | |||
| @@ -455,10 +455,14 @@ static int gfar_sringparam(struct net_device *dev, struct ethtool_ringparam *rva | |||
| 455 | 455 | ||
| 456 | /* Halt TX and RX, and process the frames which | 456 | /* Halt TX and RX, and process the frames which |
| 457 | * have already been received */ | 457 | * have already been received */ |
| 458 | spin_lock_irqsave(&priv->lock, flags); | 458 | spin_lock_irqsave(&priv->txlock, flags); |
| 459 | spin_lock(&priv->rxlock); | ||
| 460 | |||
| 459 | gfar_halt(dev); | 461 | gfar_halt(dev); |
| 460 | gfar_clean_rx_ring(dev, priv->rx_ring_size); | 462 | gfar_clean_rx_ring(dev, priv->rx_ring_size); |
| 461 | spin_unlock_irqrestore(&priv->lock, flags); | 463 | |
| 464 | spin_unlock(&priv->rxlock); | ||
| 465 | spin_unlock_irqrestore(&priv->txlock, flags); | ||
| 462 | 466 | ||
| 463 | /* Now we take down the rings to rebuild them */ | 467 | /* Now we take down the rings to rebuild them */ |
| 464 | stop_gfar(dev); | 468 | stop_gfar(dev); |
| @@ -488,10 +492,14 @@ static int gfar_set_rx_csum(struct net_device *dev, uint32_t data) | |||
| 488 | 492 | ||
| 489 | /* Halt TX and RX, and process the frames which | 493 | /* Halt TX and RX, and process the frames which |
| 490 | * have already been received */ | 494 | * have already been received */ |
| 491 | spin_lock_irqsave(&priv->lock, flags); | 495 | spin_lock_irqsave(&priv->txlock, flags); |
| 496 | spin_lock(&priv->rxlock); | ||
| 497 | |||
| 492 | gfar_halt(dev); | 498 | gfar_halt(dev); |
| 493 | gfar_clean_rx_ring(dev, priv->rx_ring_size); | 499 | gfar_clean_rx_ring(dev, priv->rx_ring_size); |
| 494 | spin_unlock_irqrestore(&priv->lock, flags); | 500 | |
| 501 | spin_unlock(&priv->rxlock); | ||
| 502 | spin_unlock_irqrestore(&priv->txlock, flags); | ||
| 495 | 503 | ||
| 496 | /* Now we take down the rings to rebuild them */ | 504 | /* Now we take down the rings to rebuild them */ |
| 497 | stop_gfar(dev); | 505 | stop_gfar(dev); |
| @@ -523,7 +531,7 @@ static int gfar_set_tx_csum(struct net_device *dev, uint32_t data) | |||
| 523 | if (!(priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_CSUM)) | 531 | if (!(priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_CSUM)) |
| 524 | return -EOPNOTSUPP; | 532 | return -EOPNOTSUPP; |
| 525 | 533 | ||
| 526 | spin_lock_irqsave(&priv->lock, flags); | 534 | spin_lock_irqsave(&priv->txlock, flags); |
| 527 | gfar_halt(dev); | 535 | gfar_halt(dev); |
| 528 | 536 | ||
| 529 | if (data) | 537 | if (data) |
| @@ -532,7 +540,7 @@ static int gfar_set_tx_csum(struct net_device *dev, uint32_t data) | |||
| 532 | dev->features &= ~NETIF_F_IP_CSUM; | 540 | dev->features &= ~NETIF_F_IP_CSUM; |
| 533 | 541 | ||
| 534 | gfar_start(dev); | 542 | gfar_start(dev); |
| 535 | spin_unlock_irqrestore(&priv->lock, flags); | 543 | spin_unlock_irqrestore(&priv->txlock, flags); |
| 536 | 544 | ||
| 537 | return 0; | 545 | return 0; |
| 538 | } | 546 | } |
diff --git a/drivers/net/gianfar_sysfs.c b/drivers/net/gianfar_sysfs.c index 51ef181b1368..a6d5c43199cb 100644 --- a/drivers/net/gianfar_sysfs.c +++ b/drivers/net/gianfar_sysfs.c | |||
| @@ -82,7 +82,7 @@ static ssize_t gfar_set_bd_stash(struct class_device *cdev, | |||
| 82 | else | 82 | else |
| 83 | return count; | 83 | return count; |
| 84 | 84 | ||
| 85 | spin_lock_irqsave(&priv->lock, flags); | 85 | spin_lock_irqsave(&priv->rxlock, flags); |
| 86 | 86 | ||
| 87 | /* Set the new stashing value */ | 87 | /* Set the new stashing value */ |
| 88 | priv->bd_stash_en = new_setting; | 88 | priv->bd_stash_en = new_setting; |
| @@ -96,7 +96,7 @@ static ssize_t gfar_set_bd_stash(struct class_device *cdev, | |||
| 96 | 96 | ||
| 97 | gfar_write(&priv->regs->attr, temp); | 97 | gfar_write(&priv->regs->attr, temp); |
| 98 | 98 | ||
| 99 | spin_unlock_irqrestore(&priv->lock, flags); | 99 | spin_unlock_irqrestore(&priv->rxlock, flags); |
| 100 | 100 | ||
| 101 | return count; | 101 | return count; |
| 102 | } | 102 | } |
| @@ -118,7 +118,7 @@ static ssize_t gfar_set_rx_stash_size(struct class_device *cdev, | |||
| 118 | u32 temp; | 118 | u32 temp; |
| 119 | unsigned long flags; | 119 | unsigned long flags; |
| 120 | 120 | ||
| 121 | spin_lock_irqsave(&priv->lock, flags); | 121 | spin_lock_irqsave(&priv->rxlock, flags); |
| 122 | if (length > priv->rx_buffer_size) | 122 | if (length > priv->rx_buffer_size) |
| 123 | return count; | 123 | return count; |
| 124 | 124 | ||
| @@ -142,7 +142,7 @@ static ssize_t gfar_set_rx_stash_size(struct class_device *cdev, | |||
| 142 | 142 | ||
| 143 | gfar_write(&priv->regs->attr, temp); | 143 | gfar_write(&priv->regs->attr, temp); |
| 144 | 144 | ||
| 145 | spin_unlock_irqrestore(&priv->lock, flags); | 145 | spin_unlock_irqrestore(&priv->rxlock, flags); |
| 146 | 146 | ||
| 147 | return count; | 147 | return count; |
| 148 | } | 148 | } |
| @@ -166,7 +166,7 @@ static ssize_t gfar_set_rx_stash_index(struct class_device *cdev, | |||
| 166 | u32 temp; | 166 | u32 temp; |
| 167 | unsigned long flags; | 167 | unsigned long flags; |
| 168 | 168 | ||
| 169 | spin_lock_irqsave(&priv->lock, flags); | 169 | spin_lock_irqsave(&priv->rxlock, flags); |
| 170 | if (index > priv->rx_stash_size) | 170 | if (index > priv->rx_stash_size) |
| 171 | return count; | 171 | return count; |
| 172 | 172 | ||
| @@ -180,7 +180,7 @@ static ssize_t gfar_set_rx_stash_index(struct class_device *cdev, | |||
| 180 | temp |= ATTRELI_EI(index); | 180 | temp |= ATTRELI_EI(index); |
| 181 | gfar_write(&priv->regs->attreli, flags); | 181 | gfar_write(&priv->regs->attreli, flags); |
| 182 | 182 | ||
| 183 | spin_unlock_irqrestore(&priv->lock, flags); | 183 | spin_unlock_irqrestore(&priv->rxlock, flags); |
| 184 | 184 | ||
| 185 | return count; | 185 | return count; |
| 186 | } | 186 | } |
| @@ -205,7 +205,7 @@ static ssize_t gfar_set_fifo_threshold(struct class_device *cdev, | |||
| 205 | if (length > GFAR_MAX_FIFO_THRESHOLD) | 205 | if (length > GFAR_MAX_FIFO_THRESHOLD) |
| 206 | return count; | 206 | return count; |
| 207 | 207 | ||
| 208 | spin_lock_irqsave(&priv->lock, flags); | 208 | spin_lock_irqsave(&priv->txlock, flags); |
| 209 | 209 | ||
| 210 | priv->fifo_threshold = length; | 210 | priv->fifo_threshold = length; |
| 211 | 211 | ||
| @@ -214,7 +214,7 @@ static ssize_t gfar_set_fifo_threshold(struct class_device *cdev, | |||
| 214 | temp |= length; | 214 | temp |= length; |
| 215 | gfar_write(&priv->regs->fifo_tx_thr, temp); | 215 | gfar_write(&priv->regs->fifo_tx_thr, temp); |
| 216 | 216 | ||
| 217 | spin_unlock_irqrestore(&priv->lock, flags); | 217 | spin_unlock_irqrestore(&priv->txlock, flags); |
| 218 | 218 | ||
| 219 | return count; | 219 | return count; |
| 220 | } | 220 | } |
| @@ -240,7 +240,7 @@ static ssize_t gfar_set_fifo_starve(struct class_device *cdev, | |||
| 240 | if (num > GFAR_MAX_FIFO_STARVE) | 240 | if (num > GFAR_MAX_FIFO_STARVE) |
| 241 | return count; | 241 | return count; |
| 242 | 242 | ||
| 243 | spin_lock_irqsave(&priv->lock, flags); | 243 | spin_lock_irqsave(&priv->txlock, flags); |
| 244 | 244 | ||
| 245 | priv->fifo_starve = num; | 245 | priv->fifo_starve = num; |
| 246 | 246 | ||
| @@ -249,7 +249,7 @@ static ssize_t gfar_set_fifo_starve(struct class_device *cdev, | |||
| 249 | temp |= num; | 249 | temp |= num; |
| 250 | gfar_write(&priv->regs->fifo_tx_starve, temp); | 250 | gfar_write(&priv->regs->fifo_tx_starve, temp); |
| 251 | 251 | ||
| 252 | spin_unlock_irqrestore(&priv->lock, flags); | 252 | spin_unlock_irqrestore(&priv->txlock, flags); |
| 253 | 253 | ||
| 254 | return count; | 254 | return count; |
| 255 | } | 255 | } |
| @@ -274,7 +274,7 @@ static ssize_t gfar_set_fifo_starve_off(struct class_device *cdev, | |||
| 274 | if (num > GFAR_MAX_FIFO_STARVE_OFF) | 274 | if (num > GFAR_MAX_FIFO_STARVE_OFF) |
| 275 | return count; | 275 | return count; |
| 276 | 276 | ||
| 277 | spin_lock_irqsave(&priv->lock, flags); | 277 | spin_lock_irqsave(&priv->txlock, flags); |
| 278 | 278 | ||
| 279 | priv->fifo_starve_off = num; | 279 | priv->fifo_starve_off = num; |
| 280 | 280 | ||
| @@ -283,7 +283,7 @@ static ssize_t gfar_set_fifo_starve_off(struct class_device *cdev, | |||
| 283 | temp |= num; | 283 | temp |= num; |
| 284 | gfar_write(&priv->regs->fifo_tx_starve_shutoff, temp); | 284 | gfar_write(&priv->regs->fifo_tx_starve_shutoff, temp); |
| 285 | 285 | ||
| 286 | spin_unlock_irqrestore(&priv->lock, flags); | 286 | spin_unlock_irqrestore(&priv->txlock, flags); |
| 287 | 287 | ||
| 288 | return count; | 288 | return count; |
| 289 | } | 289 | } |
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index 67b0eab16589..227df9876a2c 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c | |||
| @@ -51,7 +51,7 @@ | |||
| 51 | #include "sky2.h" | 51 | #include "sky2.h" |
| 52 | 52 | ||
| 53 | #define DRV_NAME "sky2" | 53 | #define DRV_NAME "sky2" |
| 54 | #define DRV_VERSION "1.1" | 54 | #define DRV_VERSION "1.2" |
| 55 | #define PFX DRV_NAME " " | 55 | #define PFX DRV_NAME " " |
| 56 | 56 | ||
| 57 | /* | 57 | /* |
| @@ -925,8 +925,7 @@ static inline struct sk_buff *sky2_alloc_skb(unsigned int size, gfp_t gfp_mask) | |||
| 925 | skb = alloc_skb(size + RX_SKB_ALIGN, gfp_mask); | 925 | skb = alloc_skb(size + RX_SKB_ALIGN, gfp_mask); |
| 926 | if (likely(skb)) { | 926 | if (likely(skb)) { |
| 927 | unsigned long p = (unsigned long) skb->data; | 927 | unsigned long p = (unsigned long) skb->data; |
| 928 | skb_reserve(skb, | 928 | skb_reserve(skb, ALIGN(p, RX_SKB_ALIGN) - p); |
| 929 | ((p + RX_SKB_ALIGN - 1) & ~(RX_SKB_ALIGN - 1)) - p); | ||
| 930 | } | 929 | } |
| 931 | 930 | ||
| 932 | return skb; | 931 | return skb; |
| @@ -1686,13 +1685,12 @@ static void sky2_tx_timeout(struct net_device *dev) | |||
| 1686 | } | 1685 | } |
| 1687 | 1686 | ||
| 1688 | 1687 | ||
| 1689 | #define roundup(x, y) ((((x)+((y)-1))/(y))*(y)) | ||
| 1690 | /* Want receive buffer size to be multiple of 64 bits | 1688 | /* Want receive buffer size to be multiple of 64 bits |
| 1691 | * and incl room for vlan and truncation | 1689 | * and incl room for vlan and truncation |
| 1692 | */ | 1690 | */ |
| 1693 | static inline unsigned sky2_buf_size(int mtu) | 1691 | static inline unsigned sky2_buf_size(int mtu) |
| 1694 | { | 1692 | { |
| 1695 | return roundup(mtu + ETH_HLEN + VLAN_HLEN, 8) + 8; | 1693 | return ALIGN(mtu + ETH_HLEN + VLAN_HLEN, 8) + 8; |
| 1696 | } | 1694 | } |
| 1697 | 1695 | ||
| 1698 | static int sky2_change_mtu(struct net_device *dev, int new_mtu) | 1696 | static int sky2_change_mtu(struct net_device *dev, int new_mtu) |
| @@ -2086,6 +2084,20 @@ static void sky2_descriptor_error(struct sky2_hw *hw, unsigned port, | |||
| 2086 | } | 2084 | } |
| 2087 | } | 2085 | } |
| 2088 | 2086 | ||
| 2087 | /* If idle then force a fake soft NAPI poll once a second | ||
| 2088 | * to work around cases where sharing an edge triggered interrupt. | ||
| 2089 | */ | ||
| 2090 | static void sky2_idle(unsigned long arg) | ||
| 2091 | { | ||
| 2092 | struct net_device *dev = (struct net_device *) arg; | ||
| 2093 | |||
| 2094 | local_irq_disable(); | ||
| 2095 | if (__netif_rx_schedule_prep(dev)) | ||
| 2096 | __netif_rx_schedule(dev); | ||
| 2097 | local_irq_enable(); | ||
| 2098 | } | ||
| 2099 | |||
| 2100 | |||
| 2089 | static int sky2_poll(struct net_device *dev0, int *budget) | 2101 | static int sky2_poll(struct net_device *dev0, int *budget) |
| 2090 | { | 2102 | { |
| 2091 | struct sky2_hw *hw = ((struct sky2_port *) netdev_priv(dev0))->hw; | 2103 | struct sky2_hw *hw = ((struct sky2_port *) netdev_priv(dev0))->hw; |
| @@ -2093,6 +2105,7 @@ static int sky2_poll(struct net_device *dev0, int *budget) | |||
| 2093 | int work_done = 0; | 2105 | int work_done = 0; |
| 2094 | u32 status = sky2_read32(hw, B0_Y2_SP_EISR); | 2106 | u32 status = sky2_read32(hw, B0_Y2_SP_EISR); |
| 2095 | 2107 | ||
| 2108 | restart_poll: | ||
| 2096 | if (unlikely(status & ~Y2_IS_STAT_BMU)) { | 2109 | if (unlikely(status & ~Y2_IS_STAT_BMU)) { |
| 2097 | if (status & Y2_IS_HW_ERR) | 2110 | if (status & Y2_IS_HW_ERR) |
| 2098 | sky2_hw_intr(hw); | 2111 | sky2_hw_intr(hw); |
| @@ -2123,7 +2136,7 @@ static int sky2_poll(struct net_device *dev0, int *budget) | |||
| 2123 | } | 2136 | } |
| 2124 | 2137 | ||
| 2125 | if (status & Y2_IS_STAT_BMU) { | 2138 | if (status & Y2_IS_STAT_BMU) { |
| 2126 | work_done = sky2_status_intr(hw, work_limit); | 2139 | work_done += sky2_status_intr(hw, work_limit - work_done); |
| 2127 | *budget -= work_done; | 2140 | *budget -= work_done; |
| 2128 | dev0->quota -= work_done; | 2141 | dev0->quota -= work_done; |
| 2129 | 2142 | ||
| @@ -2133,9 +2146,24 @@ static int sky2_poll(struct net_device *dev0, int *budget) | |||
| 2133 | sky2_write32(hw, STAT_CTRL, SC_STAT_CLR_IRQ); | 2146 | sky2_write32(hw, STAT_CTRL, SC_STAT_CLR_IRQ); |
| 2134 | } | 2147 | } |
| 2135 | 2148 | ||
| 2136 | netif_rx_complete(dev0); | 2149 | mod_timer(&hw->idle_timer, jiffies + HZ); |
| 2150 | |||
| 2151 | local_irq_disable(); | ||
| 2152 | __netif_rx_complete(dev0); | ||
| 2137 | 2153 | ||
| 2138 | status = sky2_read32(hw, B0_Y2_SP_LISR); | 2154 | status = sky2_read32(hw, B0_Y2_SP_LISR); |
| 2155 | |||
| 2156 | if (unlikely(status)) { | ||
| 2157 | /* More work pending, try and keep going */ | ||
| 2158 | if (__netif_rx_schedule_prep(dev0)) { | ||
| 2159 | __netif_rx_reschedule(dev0, work_done); | ||
| 2160 | status = sky2_read32(hw, B0_Y2_SP_EISR); | ||
| 2161 | local_irq_enable(); | ||
| 2162 | goto restart_poll; | ||
| 2163 | } | ||
| 2164 | } | ||
| 2165 | |||
| 2166 | local_irq_enable(); | ||
| 2139 | return 0; | 2167 | return 0; |
| 2140 | } | 2168 | } |
| 2141 | 2169 | ||
| @@ -2153,8 +2181,6 @@ static irqreturn_t sky2_intr(int irq, void *dev_id, struct pt_regs *regs) | |||
| 2153 | prefetch(&hw->st_le[hw->st_idx]); | 2181 | prefetch(&hw->st_le[hw->st_idx]); |
| 2154 | if (likely(__netif_rx_schedule_prep(dev0))) | 2182 | if (likely(__netif_rx_schedule_prep(dev0))) |
| 2155 | __netif_rx_schedule(dev0); | 2183 | __netif_rx_schedule(dev0); |
| 2156 | else | ||
| 2157 | printk(KERN_DEBUG PFX "irq race detected\n"); | ||
| 2158 | 2184 | ||
| 2159 | return IRQ_HANDLED; | 2185 | return IRQ_HANDLED; |
| 2160 | } | 2186 | } |
| @@ -2193,7 +2219,7 @@ static inline u32 sky2_clk2us(const struct sky2_hw *hw, u32 clk) | |||
| 2193 | } | 2219 | } |
| 2194 | 2220 | ||
| 2195 | 2221 | ||
| 2196 | static int sky2_reset(struct sky2_hw *hw) | 2222 | static int __devinit sky2_reset(struct sky2_hw *hw) |
| 2197 | { | 2223 | { |
| 2198 | u16 status; | 2224 | u16 status; |
| 2199 | u8 t8, pmd_type; | 2225 | u8 t8, pmd_type; |
| @@ -3276,6 +3302,8 @@ static int __devinit sky2_probe(struct pci_dev *pdev, | |||
| 3276 | 3302 | ||
| 3277 | sky2_write32(hw, B0_IMSK, Y2_IS_BASE); | 3303 | sky2_write32(hw, B0_IMSK, Y2_IS_BASE); |
| 3278 | 3304 | ||
| 3305 | setup_timer(&hw->idle_timer, sky2_idle, (unsigned long) dev); | ||
| 3306 | |||
| 3279 | pci_set_drvdata(pdev, hw); | 3307 | pci_set_drvdata(pdev, hw); |
| 3280 | 3308 | ||
| 3281 | return 0; | 3309 | return 0; |
| @@ -3311,13 +3339,15 @@ static void __devexit sky2_remove(struct pci_dev *pdev) | |||
| 3311 | if (!hw) | 3339 | if (!hw) |
| 3312 | return; | 3340 | return; |
| 3313 | 3341 | ||
| 3342 | del_timer_sync(&hw->idle_timer); | ||
| 3343 | |||
| 3344 | sky2_write32(hw, B0_IMSK, 0); | ||
| 3314 | dev0 = hw->dev[0]; | 3345 | dev0 = hw->dev[0]; |
| 3315 | dev1 = hw->dev[1]; | 3346 | dev1 = hw->dev[1]; |
| 3316 | if (dev1) | 3347 | if (dev1) |
| 3317 | unregister_netdev(dev1); | 3348 | unregister_netdev(dev1); |
| 3318 | unregister_netdev(dev0); | 3349 | unregister_netdev(dev0); |
| 3319 | 3350 | ||
| 3320 | sky2_write32(hw, B0_IMSK, 0); | ||
| 3321 | sky2_set_power_state(hw, PCI_D3hot); | 3351 | sky2_set_power_state(hw, PCI_D3hot); |
| 3322 | sky2_write16(hw, B0_Y2LED, LED_STAT_OFF); | 3352 | sky2_write16(hw, B0_Y2LED, LED_STAT_OFF); |
| 3323 | sky2_write8(hw, B0_CTST, CS_RST_SET); | 3353 | sky2_write8(hw, B0_CTST, CS_RST_SET); |
diff --git a/drivers/net/sky2.h b/drivers/net/sky2.h index 89dd18cd12f0..b026f5653f04 100644 --- a/drivers/net/sky2.h +++ b/drivers/net/sky2.h | |||
| @@ -1880,6 +1880,8 @@ struct sky2_hw { | |||
| 1880 | struct sky2_status_le *st_le; | 1880 | struct sky2_status_le *st_le; |
| 1881 | u32 st_idx; | 1881 | u32 st_idx; |
| 1882 | dma_addr_t st_dma; | 1882 | dma_addr_t st_dma; |
| 1883 | |||
| 1884 | struct timer_list idle_timer; | ||
| 1883 | int msi_detected; | 1885 | int msi_detected; |
| 1884 | wait_queue_head_t msi_wait; | 1886 | wait_queue_head_t msi_wait; |
| 1885 | }; | 1887 | }; |
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_dma.h b/drivers/net/wireless/bcm43xx/bcm43xx_dma.h index 2d520e4b0276..b7d77638ba8c 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_dma.h +++ b/drivers/net/wireless/bcm43xx/bcm43xx_dma.h | |||
| @@ -213,6 +213,14 @@ static inline | |||
| 213 | void bcm43xx_dma_rx(struct bcm43xx_dmaring *ring) | 213 | void bcm43xx_dma_rx(struct bcm43xx_dmaring *ring) |
| 214 | { | 214 | { |
| 215 | } | 215 | } |
| 216 | static inline | ||
| 217 | void bcm43xx_dma_tx_suspend(struct bcm43xx_dmaring *ring) | ||
| 218 | { | ||
| 219 | } | ||
| 220 | static inline | ||
| 221 | void bcm43xx_dma_tx_resume(struct bcm43xx_dmaring *ring) | ||
| 222 | { | ||
| 223 | } | ||
| 216 | 224 | ||
| 217 | #endif /* CONFIG_BCM43XX_DMA */ | 225 | #endif /* CONFIG_BCM43XX_DMA */ |
| 218 | #endif /* BCM43xx_DMA_H_ */ | 226 | #endif /* BCM43xx_DMA_H_ */ |
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_pio.c b/drivers/net/wireless/bcm43xx/bcm43xx_pio.c index c59ddd40680d..0aa1bd269a25 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_pio.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_pio.c | |||
| @@ -27,6 +27,7 @@ | |||
| 27 | #include "bcm43xx_pio.h" | 27 | #include "bcm43xx_pio.h" |
| 28 | #include "bcm43xx_main.h" | 28 | #include "bcm43xx_main.h" |
| 29 | #include "bcm43xx_xmit.h" | 29 | #include "bcm43xx_xmit.h" |
| 30 | #include "bcm43xx_power.h" | ||
| 30 | 31 | ||
| 31 | #include <linux/delay.h> | 32 | #include <linux/delay.h> |
| 32 | 33 | ||
| @@ -44,10 +45,10 @@ static void tx_octet(struct bcm43xx_pioqueue *queue, | |||
| 44 | bcm43xx_pio_write(queue, BCM43xx_PIO_TXDATA, | 45 | bcm43xx_pio_write(queue, BCM43xx_PIO_TXDATA, |
| 45 | octet); | 46 | octet); |
| 46 | bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL, | 47 | bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL, |
| 47 | BCM43xx_PIO_TXCTL_WRITEHI); | 48 | BCM43xx_PIO_TXCTL_WRITELO); |
| 48 | } else { | 49 | } else { |
| 49 | bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL, | 50 | bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL, |
| 50 | BCM43xx_PIO_TXCTL_WRITEHI); | 51 | BCM43xx_PIO_TXCTL_WRITELO); |
| 51 | bcm43xx_pio_write(queue, BCM43xx_PIO_TXDATA, | 52 | bcm43xx_pio_write(queue, BCM43xx_PIO_TXDATA, |
| 52 | octet); | 53 | octet); |
| 53 | } | 54 | } |
| @@ -103,7 +104,7 @@ static void tx_complete(struct bcm43xx_pioqueue *queue, | |||
| 103 | bcm43xx_pio_write(queue, BCM43xx_PIO_TXDATA, | 104 | bcm43xx_pio_write(queue, BCM43xx_PIO_TXDATA, |
| 104 | skb->data[skb->len - 1]); | 105 | skb->data[skb->len - 1]); |
| 105 | bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL, | 106 | bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL, |
| 106 | BCM43xx_PIO_TXCTL_WRITEHI | | 107 | BCM43xx_PIO_TXCTL_WRITELO | |
| 107 | BCM43xx_PIO_TXCTL_COMPLETE); | 108 | BCM43xx_PIO_TXCTL_COMPLETE); |
| 108 | } else { | 109 | } else { |
| 109 | bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL, | 110 | bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL, |
| @@ -112,9 +113,10 @@ static void tx_complete(struct bcm43xx_pioqueue *queue, | |||
| 112 | } | 113 | } |
| 113 | 114 | ||
| 114 | static u16 generate_cookie(struct bcm43xx_pioqueue *queue, | 115 | static u16 generate_cookie(struct bcm43xx_pioqueue *queue, |
| 115 | int packetindex) | 116 | struct bcm43xx_pio_txpacket *packet) |
| 116 | { | 117 | { |
| 117 | u16 cookie = 0x0000; | 118 | u16 cookie = 0x0000; |
| 119 | int packetindex; | ||
| 118 | 120 | ||
| 119 | /* We use the upper 4 bits for the PIO | 121 | /* We use the upper 4 bits for the PIO |
| 120 | * controller ID and the lower 12 bits | 122 | * controller ID and the lower 12 bits |
| @@ -135,6 +137,7 @@ static u16 generate_cookie(struct bcm43xx_pioqueue *queue, | |||
| 135 | default: | 137 | default: |
| 136 | assert(0); | 138 | assert(0); |
| 137 | } | 139 | } |
| 140 | packetindex = pio_txpacket_getindex(packet); | ||
| 138 | assert(((u16)packetindex & 0xF000) == 0x0000); | 141 | assert(((u16)packetindex & 0xF000) == 0x0000); |
| 139 | cookie |= (u16)packetindex; | 142 | cookie |= (u16)packetindex; |
| 140 | 143 | ||
| @@ -184,7 +187,7 @@ static void pio_tx_write_fragment(struct bcm43xx_pioqueue *queue, | |||
| 184 | bcm43xx_generate_txhdr(queue->bcm, | 187 | bcm43xx_generate_txhdr(queue->bcm, |
| 185 | &txhdr, skb->data, skb->len, | 188 | &txhdr, skb->data, skb->len, |
| 186 | (packet->xmitted_frags == 0), | 189 | (packet->xmitted_frags == 0), |
| 187 | generate_cookie(queue, pio_txpacket_getindex(packet))); | 190 | generate_cookie(queue, packet)); |
| 188 | 191 | ||
| 189 | tx_start(queue); | 192 | tx_start(queue); |
| 190 | octets = skb->len + sizeof(txhdr); | 193 | octets = skb->len + sizeof(txhdr); |
| @@ -241,7 +244,7 @@ static int pio_tx_packet(struct bcm43xx_pio_txpacket *packet) | |||
| 241 | queue->tx_devq_packets++; | 244 | queue->tx_devq_packets++; |
| 242 | queue->tx_devq_used += octets; | 245 | queue->tx_devq_used += octets; |
| 243 | 246 | ||
| 244 | assert(packet->xmitted_frags <= packet->txb->nr_frags); | 247 | assert(packet->xmitted_frags < packet->txb->nr_frags); |
| 245 | packet->xmitted_frags++; | 248 | packet->xmitted_frags++; |
| 246 | packet->xmitted_octets += octets; | 249 | packet->xmitted_octets += octets; |
| 247 | } | 250 | } |
| @@ -257,8 +260,14 @@ static void tx_tasklet(unsigned long d) | |||
| 257 | unsigned long flags; | 260 | unsigned long flags; |
| 258 | struct bcm43xx_pio_txpacket *packet, *tmp_packet; | 261 | struct bcm43xx_pio_txpacket *packet, *tmp_packet; |
| 259 | int err; | 262 | int err; |
| 263 | u16 txctl; | ||
| 260 | 264 | ||
| 261 | bcm43xx_lock_mmio(bcm, flags); | 265 | bcm43xx_lock_mmio(bcm, flags); |
| 266 | |||
| 267 | txctl = bcm43xx_pio_read(queue, BCM43xx_PIO_TXCTL); | ||
| 268 | if (txctl & BCM43xx_PIO_TXCTL_SUSPEND) | ||
| 269 | goto out_unlock; | ||
| 270 | |||
| 262 | list_for_each_entry_safe(packet, tmp_packet, &queue->txqueue, list) { | 271 | list_for_each_entry_safe(packet, tmp_packet, &queue->txqueue, list) { |
| 263 | assert(packet->xmitted_frags < packet->txb->nr_frags); | 272 | assert(packet->xmitted_frags < packet->txb->nr_frags); |
| 264 | if (packet->xmitted_frags == 0) { | 273 | if (packet->xmitted_frags == 0) { |
| @@ -288,6 +297,7 @@ static void tx_tasklet(unsigned long d) | |||
| 288 | next_packet: | 297 | next_packet: |
| 289 | continue; | 298 | continue; |
| 290 | } | 299 | } |
| 300 | out_unlock: | ||
| 291 | bcm43xx_unlock_mmio(bcm, flags); | 301 | bcm43xx_unlock_mmio(bcm, flags); |
| 292 | } | 302 | } |
| 293 | 303 | ||
| @@ -330,12 +340,19 @@ struct bcm43xx_pioqueue * bcm43xx_setup_pioqueue(struct bcm43xx_private *bcm, | |||
| 330 | (unsigned long)queue); | 340 | (unsigned long)queue); |
| 331 | 341 | ||
| 332 | value = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); | 342 | value = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); |
| 333 | value |= BCM43xx_SBF_XFER_REG_BYTESWAP; | 343 | value &= ~BCM43xx_SBF_XFER_REG_BYTESWAP; |
| 334 | bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, value); | 344 | bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, value); |
| 335 | 345 | ||
| 336 | qsize = bcm43xx_read16(bcm, queue->mmio_base + BCM43xx_PIO_TXQBUFSIZE); | 346 | qsize = bcm43xx_read16(bcm, queue->mmio_base + BCM43xx_PIO_TXQBUFSIZE); |
| 347 | if (qsize == 0) { | ||
| 348 | printk(KERN_ERR PFX "ERROR: This card does not support PIO " | ||
| 349 | "operation mode. Please use DMA mode " | ||
| 350 | "(module parameter pio=0).\n"); | ||
| 351 | goto err_freequeue; | ||
| 352 | } | ||
| 337 | if (qsize <= BCM43xx_PIO_TXQADJUST) { | 353 | if (qsize <= BCM43xx_PIO_TXQADJUST) { |
| 338 | printk(KERN_ERR PFX "PIO tx device-queue too small (%u)\n", qsize); | 354 | printk(KERN_ERR PFX "PIO tx device-queue too small (%u)\n", |
| 355 | qsize); | ||
| 339 | goto err_freequeue; | 356 | goto err_freequeue; |
| 340 | } | 357 | } |
| 341 | qsize -= BCM43xx_PIO_TXQADJUST; | 358 | qsize -= BCM43xx_PIO_TXQADJUST; |
| @@ -444,15 +461,10 @@ int bcm43xx_pio_tx(struct bcm43xx_private *bcm, | |||
| 444 | { | 461 | { |
| 445 | struct bcm43xx_pioqueue *queue = bcm43xx_current_pio(bcm)->queue1; | 462 | struct bcm43xx_pioqueue *queue = bcm43xx_current_pio(bcm)->queue1; |
| 446 | struct bcm43xx_pio_txpacket *packet; | 463 | struct bcm43xx_pio_txpacket *packet; |
| 447 | u16 tmp; | ||
| 448 | 464 | ||
| 449 | assert(!queue->tx_suspended); | 465 | assert(!queue->tx_suspended); |
| 450 | assert(!list_empty(&queue->txfree)); | 466 | assert(!list_empty(&queue->txfree)); |
| 451 | 467 | ||
| 452 | tmp = bcm43xx_pio_read(queue, BCM43xx_PIO_TXCTL); | ||
| 453 | if (tmp & BCM43xx_PIO_TXCTL_SUSPEND) | ||
| 454 | return -EBUSY; | ||
| 455 | |||
| 456 | packet = list_entry(queue->txfree.next, struct bcm43xx_pio_txpacket, list); | 468 | packet = list_entry(queue->txfree.next, struct bcm43xx_pio_txpacket, list); |
| 457 | packet->txb = txb; | 469 | packet->txb = txb; |
| 458 | packet->xmitted_frags = 0; | 470 | packet->xmitted_frags = 0; |
| @@ -462,7 +474,7 @@ int bcm43xx_pio_tx(struct bcm43xx_private *bcm, | |||
| 462 | assert(queue->nr_txfree < BCM43xx_PIO_MAXTXPACKETS); | 474 | assert(queue->nr_txfree < BCM43xx_PIO_MAXTXPACKETS); |
| 463 | 475 | ||
| 464 | /* Suspend TX, if we are out of packets in the "free" queue. */ | 476 | /* Suspend TX, if we are out of packets in the "free" queue. */ |
| 465 | if (unlikely(list_empty(&queue->txfree))) { | 477 | if (list_empty(&queue->txfree)) { |
| 466 | netif_stop_queue(queue->bcm->net_dev); | 478 | netif_stop_queue(queue->bcm->net_dev); |
| 467 | queue->tx_suspended = 1; | 479 | queue->tx_suspended = 1; |
| 468 | } | 480 | } |
| @@ -480,15 +492,15 @@ void bcm43xx_pio_handle_xmitstatus(struct bcm43xx_private *bcm, | |||
| 480 | 492 | ||
| 481 | queue = parse_cookie(bcm, status->cookie, &packet); | 493 | queue = parse_cookie(bcm, status->cookie, &packet); |
| 482 | assert(queue); | 494 | assert(queue); |
| 483 | //TODO | 495 | |
| 484 | if (!queue) | ||
| 485 | return; | ||
| 486 | free_txpacket(packet, 1); | 496 | free_txpacket(packet, 1); |
| 487 | if (unlikely(queue->tx_suspended)) { | 497 | if (queue->tx_suspended) { |
| 488 | queue->tx_suspended = 0; | 498 | queue->tx_suspended = 0; |
| 489 | netif_wake_queue(queue->bcm->net_dev); | 499 | netif_wake_queue(queue->bcm->net_dev); |
| 490 | } | 500 | } |
| 491 | /* If there are packets on the txqueue, poke the tasklet. */ | 501 | /* If there are packets on the txqueue, poke the tasklet |
| 502 | * to transmit them. | ||
| 503 | */ | ||
| 492 | if (!list_empty(&queue->txqueue)) | 504 | if (!list_empty(&queue->txqueue)) |
| 493 | tasklet_schedule(&queue->txtask); | 505 | tasklet_schedule(&queue->txtask); |
| 494 | } | 506 | } |
| @@ -519,12 +531,9 @@ void bcm43xx_pio_rx(struct bcm43xx_pioqueue *queue) | |||
| 519 | int i, preamble_readwords; | 531 | int i, preamble_readwords; |
| 520 | struct sk_buff *skb; | 532 | struct sk_buff *skb; |
| 521 | 533 | ||
| 522 | return; | ||
| 523 | tmp = bcm43xx_pio_read(queue, BCM43xx_PIO_RXCTL); | 534 | tmp = bcm43xx_pio_read(queue, BCM43xx_PIO_RXCTL); |
| 524 | if (!(tmp & BCM43xx_PIO_RXCTL_DATAAVAILABLE)) { | 535 | if (!(tmp & BCM43xx_PIO_RXCTL_DATAAVAILABLE)) |
| 525 | dprintkl(KERN_ERR PFX "PIO RX: No data available\n");//TODO: remove this printk. | ||
| 526 | return; | 536 | return; |
| 527 | } | ||
| 528 | bcm43xx_pio_write(queue, BCM43xx_PIO_RXCTL, | 537 | bcm43xx_pio_write(queue, BCM43xx_PIO_RXCTL, |
| 529 | BCM43xx_PIO_RXCTL_DATAAVAILABLE); | 538 | BCM43xx_PIO_RXCTL_DATAAVAILABLE); |
| 530 | 539 | ||
| @@ -538,8 +547,7 @@ return; | |||
| 538 | return; | 547 | return; |
| 539 | data_ready: | 548 | data_ready: |
| 540 | 549 | ||
| 541 | //FIXME: endianess in this function. | 550 | len = bcm43xx_pio_read(queue, BCM43xx_PIO_RXDATA); |
| 542 | len = le16_to_cpu(bcm43xx_pio_read(queue, BCM43xx_PIO_RXDATA)); | ||
| 543 | if (unlikely(len > 0x700)) { | 551 | if (unlikely(len > 0x700)) { |
| 544 | pio_rx_error(queue, 0, "len > 0x700"); | 552 | pio_rx_error(queue, 0, "len > 0x700"); |
| 545 | return; | 553 | return; |
| @@ -555,7 +563,7 @@ data_ready: | |||
| 555 | preamble_readwords = 18 / sizeof(u16); | 563 | preamble_readwords = 18 / sizeof(u16); |
| 556 | for (i = 0; i < preamble_readwords; i++) { | 564 | for (i = 0; i < preamble_readwords; i++) { |
| 557 | tmp = bcm43xx_pio_read(queue, BCM43xx_PIO_RXDATA); | 565 | tmp = bcm43xx_pio_read(queue, BCM43xx_PIO_RXDATA); |
| 558 | preamble[i + 1] = cpu_to_be16(tmp);//FIXME? | 566 | preamble[i + 1] = cpu_to_le16(tmp); |
| 559 | } | 567 | } |
| 560 | rxhdr = (struct bcm43xx_rxhdr *)preamble; | 568 | rxhdr = (struct bcm43xx_rxhdr *)preamble; |
| 561 | rxflags2 = le16_to_cpu(rxhdr->flags2); | 569 | rxflags2 = le16_to_cpu(rxhdr->flags2); |
| @@ -591,16 +599,40 @@ data_ready: | |||
| 591 | } | 599 | } |
| 592 | skb_put(skb, len); | 600 | skb_put(skb, len); |
| 593 | for (i = 0; i < len - 1; i += 2) { | 601 | for (i = 0; i < len - 1; i += 2) { |
| 594 | tmp = cpu_to_be16(bcm43xx_pio_read(queue, BCM43xx_PIO_RXDATA)); | 602 | tmp = bcm43xx_pio_read(queue, BCM43xx_PIO_RXDATA); |
| 595 | *((u16 *)(skb->data + i)) = tmp; | 603 | *((u16 *)(skb->data + i)) = cpu_to_le16(tmp); |
| 596 | } | 604 | } |
| 597 | if (len % 2) { | 605 | if (len % 2) { |
| 598 | tmp = bcm43xx_pio_read(queue, BCM43xx_PIO_RXDATA); | 606 | tmp = bcm43xx_pio_read(queue, BCM43xx_PIO_RXDATA); |
| 599 | skb->data[len - 1] = (tmp & 0x00FF); | 607 | skb->data[len - 1] = (tmp & 0x00FF); |
| 608 | /* The specs say the following is required, but | ||
| 609 | * it is wrong and corrupts the PLCP. If we don't do | ||
| 610 | * this, the PLCP seems to be correct. So ifdef it out for now. | ||
| 611 | */ | ||
| 612 | #if 0 | ||
| 600 | if (rxflags2 & BCM43xx_RXHDR_FLAGS2_TYPE2FRAME) | 613 | if (rxflags2 & BCM43xx_RXHDR_FLAGS2_TYPE2FRAME) |
| 601 | skb->data[0x20] = (tmp & 0xFF00) >> 8; | 614 | skb->data[2] = (tmp & 0xFF00) >> 8; |
| 602 | else | 615 | else |
| 603 | skb->data[0x1E] = (tmp & 0xFF00) >> 8; | 616 | skb->data[0] = (tmp & 0xFF00) >> 8; |
| 617 | #endif | ||
| 604 | } | 618 | } |
| 619 | skb_trim(skb, len - IEEE80211_FCS_LEN); | ||
| 605 | bcm43xx_rx(queue->bcm, skb, rxhdr); | 620 | bcm43xx_rx(queue->bcm, skb, rxhdr); |
| 606 | } | 621 | } |
| 622 | |||
| 623 | void bcm43xx_pio_tx_suspend(struct bcm43xx_pioqueue *queue) | ||
| 624 | { | ||
| 625 | bcm43xx_power_saving_ctl_bits(queue->bcm, -1, 1); | ||
| 626 | bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL, | ||
| 627 | bcm43xx_pio_read(queue, BCM43xx_PIO_TXCTL) | ||
| 628 | | BCM43xx_PIO_TXCTL_SUSPEND); | ||
| 629 | } | ||
| 630 | |||
| 631 | void bcm43xx_pio_tx_resume(struct bcm43xx_pioqueue *queue) | ||
| 632 | { | ||
| 633 | bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL, | ||
| 634 | bcm43xx_pio_read(queue, BCM43xx_PIO_TXCTL) | ||
| 635 | & ~BCM43xx_PIO_TXCTL_SUSPEND); | ||
| 636 | bcm43xx_power_saving_ctl_bits(queue->bcm, -1, -1); | ||
| 637 | tasklet_schedule(&queue->txtask); | ||
| 638 | } | ||
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_pio.h b/drivers/net/wireless/bcm43xx/bcm43xx_pio.h index 970627bc1769..dfc78209e3a3 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_pio.h +++ b/drivers/net/wireless/bcm43xx/bcm43xx_pio.h | |||
| @@ -14,8 +14,8 @@ | |||
| 14 | #define BCM43xx_PIO_RXCTL 0x08 | 14 | #define BCM43xx_PIO_RXCTL 0x08 |
| 15 | #define BCM43xx_PIO_RXDATA 0x0A | 15 | #define BCM43xx_PIO_RXDATA 0x0A |
| 16 | 16 | ||
| 17 | #define BCM43xx_PIO_TXCTL_WRITEHI (1 << 0) | 17 | #define BCM43xx_PIO_TXCTL_WRITELO (1 << 0) |
| 18 | #define BCM43xx_PIO_TXCTL_WRITELO (1 << 1) | 18 | #define BCM43xx_PIO_TXCTL_WRITEHI (1 << 1) |
| 19 | #define BCM43xx_PIO_TXCTL_COMPLETE (1 << 2) | 19 | #define BCM43xx_PIO_TXCTL_COMPLETE (1 << 2) |
| 20 | #define BCM43xx_PIO_TXCTL_INIT (1 << 3) | 20 | #define BCM43xx_PIO_TXCTL_INIT (1 << 3) |
| 21 | #define BCM43xx_PIO_TXCTL_SUSPEND (1 << 7) | 21 | #define BCM43xx_PIO_TXCTL_SUSPEND (1 << 7) |
| @@ -95,6 +95,7 @@ void bcm43xx_pio_write(struct bcm43xx_pioqueue *queue, | |||
| 95 | u16 offset, u16 value) | 95 | u16 offset, u16 value) |
| 96 | { | 96 | { |
| 97 | bcm43xx_write16(queue->bcm, queue->mmio_base + offset, value); | 97 | bcm43xx_write16(queue->bcm, queue->mmio_base + offset, value); |
| 98 | mmiowb(); | ||
| 98 | } | 99 | } |
| 99 | 100 | ||
| 100 | 101 | ||
| @@ -107,6 +108,9 @@ void bcm43xx_pio_handle_xmitstatus(struct bcm43xx_private *bcm, | |||
| 107 | struct bcm43xx_xmitstatus *status); | 108 | struct bcm43xx_xmitstatus *status); |
| 108 | void bcm43xx_pio_rx(struct bcm43xx_pioqueue *queue); | 109 | void bcm43xx_pio_rx(struct bcm43xx_pioqueue *queue); |
| 109 | 110 | ||
| 111 | void bcm43xx_pio_tx_suspend(struct bcm43xx_pioqueue *queue); | ||
| 112 | void bcm43xx_pio_tx_resume(struct bcm43xx_pioqueue *queue); | ||
| 113 | |||
| 110 | #else /* CONFIG_BCM43XX_PIO */ | 114 | #else /* CONFIG_BCM43XX_PIO */ |
| 111 | 115 | ||
| 112 | static inline | 116 | static inline |
| @@ -133,6 +137,14 @@ static inline | |||
| 133 | void bcm43xx_pio_rx(struct bcm43xx_pioqueue *queue) | 137 | void bcm43xx_pio_rx(struct bcm43xx_pioqueue *queue) |
| 134 | { | 138 | { |
| 135 | } | 139 | } |
| 140 | static inline | ||
| 141 | void bcm43xx_pio_tx_suspend(struct bcm43xx_pioqueue *queue) | ||
| 142 | { | ||
| 143 | } | ||
| 144 | static inline | ||
| 145 | void bcm43xx_pio_tx_resume(struct bcm43xx_pioqueue *queue) | ||
| 146 | { | ||
| 147 | } | ||
| 136 | 148 | ||
| 137 | #endif /* CONFIG_BCM43XX_PIO */ | 149 | #endif /* CONFIG_BCM43XX_PIO */ |
| 138 | #endif /* BCM43xx_PIO_H_ */ | 150 | #endif /* BCM43xx_PIO_H_ */ |
diff --git a/drivers/net/wireless/hostap/hostap_ioctl.c b/drivers/net/wireless/hostap/hostap_ioctl.c index 8b37e824dfcb..8399de581893 100644 --- a/drivers/net/wireless/hostap/hostap_ioctl.c +++ b/drivers/net/wireless/hostap/hostap_ioctl.c | |||
| @@ -1860,7 +1860,7 @@ static char * __prism2_translate_scan(local_info_t *local, | |||
| 1860 | memset(&iwe, 0, sizeof(iwe)); | 1860 | memset(&iwe, 0, sizeof(iwe)); |
| 1861 | iwe.cmd = SIOCGIWFREQ; | 1861 | iwe.cmd = SIOCGIWFREQ; |
| 1862 | if (scan) { | 1862 | if (scan) { |
| 1863 | chan = scan->chid; | 1863 | chan = le16_to_cpu(scan->chid); |
| 1864 | } else if (bss) { | 1864 | } else if (bss) { |
| 1865 | chan = bss->chan; | 1865 | chan = bss->chan; |
| 1866 | } else { | 1866 | } else { |
| @@ -1868,7 +1868,7 @@ static char * __prism2_translate_scan(local_info_t *local, | |||
| 1868 | } | 1868 | } |
| 1869 | 1869 | ||
| 1870 | if (chan > 0) { | 1870 | if (chan > 0) { |
| 1871 | iwe.u.freq.m = freq_list[le16_to_cpu(chan - 1)] * 100000; | 1871 | iwe.u.freq.m = freq_list[chan - 1] * 100000; |
| 1872 | iwe.u.freq.e = 1; | 1872 | iwe.u.freq.e = 1; |
| 1873 | current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, | 1873 | current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, |
| 1874 | IW_EV_FREQ_LEN); | 1874 | IW_EV_FREQ_LEN); |
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 40ccf8cc4239..01db7b88a2b1 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h | |||
| @@ -829,19 +829,21 @@ static inline void netif_rx_schedule(struct net_device *dev) | |||
| 829 | __netif_rx_schedule(dev); | 829 | __netif_rx_schedule(dev); |
| 830 | } | 830 | } |
| 831 | 831 | ||
| 832 | /* Try to reschedule poll. Called by dev->poll() after netif_rx_complete(). | 832 | |
| 833 | * Do not inline this? | 833 | static inline void __netif_rx_reschedule(struct net_device *dev, int undo) |
| 834 | */ | 834 | { |
| 835 | dev->quota += undo; | ||
| 836 | list_add_tail(&dev->poll_list, &__get_cpu_var(softnet_data).poll_list); | ||
| 837 | __raise_softirq_irqoff(NET_RX_SOFTIRQ); | ||
| 838 | } | ||
| 839 | |||
| 840 | /* Try to reschedule poll. Called by dev->poll() after netif_rx_complete(). */ | ||
| 835 | static inline int netif_rx_reschedule(struct net_device *dev, int undo) | 841 | static inline int netif_rx_reschedule(struct net_device *dev, int undo) |
| 836 | { | 842 | { |
| 837 | if (netif_rx_schedule_prep(dev)) { | 843 | if (netif_rx_schedule_prep(dev)) { |
| 838 | unsigned long flags; | 844 | unsigned long flags; |
| 839 | |||
| 840 | dev->quota += undo; | ||
| 841 | |||
| 842 | local_irq_save(flags); | 845 | local_irq_save(flags); |
| 843 | list_add_tail(&dev->poll_list, &__get_cpu_var(softnet_data).poll_list); | 846 | __netif_rx_reschedule(dev, undo); |
| 844 | __raise_softirq_irqoff(NET_RX_SOFTIRQ); | ||
| 845 | local_irq_restore(flags); | 847 | local_irq_restore(flags); |
| 846 | return 1; | 848 | return 1; |
| 847 | } | 849 | } |
diff --git a/include/net/ieee80211softmac.h b/include/net/ieee80211softmac.h index 6b3693f05ca0..b1ebfbae397f 100644 --- a/include/net/ieee80211softmac.h +++ b/include/net/ieee80211softmac.h | |||
| @@ -96,10 +96,13 @@ struct ieee80211softmac_assoc_info { | |||
| 96 | * | 96 | * |
| 97 | * bssvalid is true if we found a matching network | 97 | * bssvalid is true if we found a matching network |
| 98 | * and saved it's BSSID into the bssid above. | 98 | * and saved it's BSSID into the bssid above. |
| 99 | * | ||
| 100 | * bssfixed is used for SIOCSIWAP. | ||
| 99 | */ | 101 | */ |
| 100 | u8 static_essid:1, | 102 | u8 static_essid:1, |
| 101 | associating:1, | 103 | associating:1, |
| 102 | bssvalid:1; | 104 | bssvalid:1, |
| 105 | bssfixed:1; | ||
| 103 | 106 | ||
| 104 | /* Scan retries remaining */ | 107 | /* Scan retries remaining */ |
| 105 | int scan_retry; | 108 | int scan_retry; |
diff --git a/net/ieee80211/softmac/ieee80211softmac_assoc.c b/net/ieee80211/softmac/ieee80211softmac_assoc.c index 4498023841dc..fb79ce7d6439 100644 --- a/net/ieee80211/softmac/ieee80211softmac_assoc.c +++ b/net/ieee80211/softmac/ieee80211softmac_assoc.c | |||
| @@ -144,6 +144,12 @@ network_matches_request(struct ieee80211softmac_device *mac, struct ieee80211_ne | |||
| 144 | if (!we_support_all_basic_rates(mac, net->rates_ex, net->rates_ex_len)) | 144 | if (!we_support_all_basic_rates(mac, net->rates_ex, net->rates_ex_len)) |
| 145 | return 0; | 145 | return 0; |
| 146 | 146 | ||
| 147 | /* assume that users know what they're doing ... | ||
| 148 | * (note we don't let them select a net we're incompatible with) */ | ||
| 149 | if (mac->associnfo.bssfixed) { | ||
| 150 | return !memcmp(mac->associnfo.bssid, net->bssid, ETH_ALEN); | ||
| 151 | } | ||
| 152 | |||
| 147 | /* if 'ANY' network requested, take any that doesn't have privacy enabled */ | 153 | /* if 'ANY' network requested, take any that doesn't have privacy enabled */ |
| 148 | if (mac->associnfo.req_essid.len == 0 | 154 | if (mac->associnfo.req_essid.len == 0 |
| 149 | && !(net->capability & WLAN_CAPABILITY_PRIVACY)) | 155 | && !(net->capability & WLAN_CAPABILITY_PRIVACY)) |
| @@ -176,7 +182,7 @@ ieee80211softmac_assoc_work(void *d) | |||
| 176 | ieee80211softmac_disassoc(mac, WLAN_REASON_DISASSOC_STA_HAS_LEFT); | 182 | ieee80211softmac_disassoc(mac, WLAN_REASON_DISASSOC_STA_HAS_LEFT); |
| 177 | 183 | ||
| 178 | /* try to find the requested network in our list, if we found one already */ | 184 | /* try to find the requested network in our list, if we found one already */ |
| 179 | if (mac->associnfo.bssvalid) | 185 | if (mac->associnfo.bssvalid || mac->associnfo.bssfixed) |
| 180 | found = ieee80211softmac_get_network_by_bssid(mac, mac->associnfo.bssid); | 186 | found = ieee80211softmac_get_network_by_bssid(mac, mac->associnfo.bssid); |
| 181 | 187 | ||
| 182 | /* Search the ieee80211 networks for this network if we didn't find it by bssid, | 188 | /* Search the ieee80211 networks for this network if we didn't find it by bssid, |
| @@ -241,19 +247,25 @@ ieee80211softmac_assoc_work(void *d) | |||
| 241 | if (ieee80211softmac_start_scan(mac)) | 247 | if (ieee80211softmac_start_scan(mac)) |
| 242 | dprintk(KERN_INFO PFX "Associate: failed to initiate scan. Is device up?\n"); | 248 | dprintk(KERN_INFO PFX "Associate: failed to initiate scan. Is device up?\n"); |
| 243 | return; | 249 | return; |
| 244 | } | 250 | } else { |
| 245 | else { | ||
| 246 | spin_lock_irqsave(&mac->lock, flags); | 251 | spin_lock_irqsave(&mac->lock, flags); |
| 247 | mac->associnfo.associating = 0; | 252 | mac->associnfo.associating = 0; |
| 248 | mac->associated = 0; | 253 | mac->associated = 0; |
| 249 | spin_unlock_irqrestore(&mac->lock, flags); | 254 | spin_unlock_irqrestore(&mac->lock, flags); |
| 250 | 255 | ||
| 251 | dprintk(KERN_INFO PFX "Unable to find matching network after scan!\n"); | 256 | dprintk(KERN_INFO PFX "Unable to find matching network after scan!\n"); |
| 257 | /* reset the retry counter for the next user request since we | ||
| 258 | * break out and don't reschedule ourselves after this point. */ | ||
| 259 | mac->associnfo.scan_retry = IEEE80211SOFTMAC_ASSOC_SCAN_RETRY_LIMIT; | ||
| 252 | ieee80211softmac_call_events(mac, IEEE80211SOFTMAC_EVENT_ASSOCIATE_NET_NOT_FOUND, NULL); | 260 | ieee80211softmac_call_events(mac, IEEE80211SOFTMAC_EVENT_ASSOCIATE_NET_NOT_FOUND, NULL); |
| 253 | return; | 261 | return; |
| 254 | } | 262 | } |
| 255 | } | 263 | } |
| 256 | 264 | ||
| 265 | /* reset the retry counter for the next user request since we | ||
| 266 | * now found a net and will try to associate to it, but not | ||
| 267 | * schedule this function again. */ | ||
| 268 | mac->associnfo.scan_retry = IEEE80211SOFTMAC_ASSOC_SCAN_RETRY_LIMIT; | ||
| 257 | mac->associnfo.bssvalid = 1; | 269 | mac->associnfo.bssvalid = 1; |
| 258 | memcpy(mac->associnfo.bssid, found->bssid, ETH_ALEN); | 270 | memcpy(mac->associnfo.bssid, found->bssid, ETH_ALEN); |
| 259 | /* copy the ESSID for displaying it */ | 271 | /* copy the ESSID for displaying it */ |
diff --git a/net/ieee80211/softmac/ieee80211softmac_module.c b/net/ieee80211/softmac/ieee80211softmac_module.c index 60f06a31f0d1..be83bdc1644a 100644 --- a/net/ieee80211/softmac/ieee80211softmac_module.c +++ b/net/ieee80211/softmac/ieee80211softmac_module.c | |||
| @@ -45,6 +45,8 @@ struct net_device *alloc_ieee80211softmac(int sizeof_priv) | |||
| 45 | softmac->ieee->handle_disassoc = ieee80211softmac_handle_disassoc; | 45 | softmac->ieee->handle_disassoc = ieee80211softmac_handle_disassoc; |
| 46 | softmac->scaninfo = NULL; | 46 | softmac->scaninfo = NULL; |
| 47 | 47 | ||
| 48 | softmac->associnfo.scan_retry = IEEE80211SOFTMAC_ASSOC_SCAN_RETRY_LIMIT; | ||
| 49 | |||
| 48 | /* TODO: initialise all the other callbacks in the ieee struct | 50 | /* TODO: initialise all the other callbacks in the ieee struct |
| 49 | * (once they're written) | 51 | * (once they're written) |
| 50 | */ | 52 | */ |
diff --git a/net/ieee80211/softmac/ieee80211softmac_wx.c b/net/ieee80211/softmac/ieee80211softmac_wx.c index 00f0d4f71897..27edb2b5581a 100644 --- a/net/ieee80211/softmac/ieee80211softmac_wx.c +++ b/net/ieee80211/softmac/ieee80211softmac_wx.c | |||
| @@ -27,7 +27,8 @@ | |||
| 27 | #include "ieee80211softmac_priv.h" | 27 | #include "ieee80211softmac_priv.h" |
| 28 | 28 | ||
| 29 | #include <net/iw_handler.h> | 29 | #include <net/iw_handler.h> |
| 30 | 30 | /* for is_broadcast_ether_addr and is_zero_ether_addr */ | |
| 31 | #include <linux/etherdevice.h> | ||
| 31 | 32 | ||
| 32 | int | 33 | int |
| 33 | ieee80211softmac_wx_trigger_scan(struct net_device *net_dev, | 34 | ieee80211softmac_wx_trigger_scan(struct net_device *net_dev, |
| @@ -83,7 +84,6 @@ ieee80211softmac_wx_set_essid(struct net_device *net_dev, | |||
| 83 | sm->associnfo.static_essid = 1; | 84 | sm->associnfo.static_essid = 1; |
| 84 | } | 85 | } |
| 85 | } | 86 | } |
| 86 | sm->associnfo.scan_retry = IEEE80211SOFTMAC_ASSOC_SCAN_RETRY_LIMIT; | ||
| 87 | 87 | ||
| 88 | /* set our requested ESSID length. | 88 | /* set our requested ESSID length. |
| 89 | * If applicable, we have already copied the data in */ | 89 | * If applicable, we have already copied the data in */ |
| @@ -310,8 +310,6 @@ ieee80211softmac_wx_set_wap(struct net_device *net_dev, | |||
| 310 | char *extra) | 310 | char *extra) |
| 311 | { | 311 | { |
| 312 | struct ieee80211softmac_device *mac = ieee80211_priv(net_dev); | 312 | struct ieee80211softmac_device *mac = ieee80211_priv(net_dev); |
| 313 | static const unsigned char any[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; | ||
| 314 | static const unsigned char off[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; | ||
| 315 | unsigned long flags; | 313 | unsigned long flags; |
| 316 | 314 | ||
| 317 | /* sanity check */ | 315 | /* sanity check */ |
| @@ -320,10 +318,17 @@ ieee80211softmac_wx_set_wap(struct net_device *net_dev, | |||
| 320 | } | 318 | } |
| 321 | 319 | ||
| 322 | spin_lock_irqsave(&mac->lock, flags); | 320 | spin_lock_irqsave(&mac->lock, flags); |
| 323 | if (!memcmp(any, data->ap_addr.sa_data, ETH_ALEN) || | 321 | if (is_broadcast_ether_addr(data->ap_addr.sa_data)) { |
| 324 | !memcmp(off, data->ap_addr.sa_data, ETH_ALEN)) { | 322 | /* the bssid we have is not to be fixed any longer, |
| 325 | schedule_work(&mac->associnfo.work); | 323 | * and we should reassociate to the best AP. */ |
| 326 | goto out; | 324 | mac->associnfo.bssfixed = 0; |
| 325 | /* force reassociation */ | ||
| 326 | mac->associnfo.bssvalid = 0; | ||
| 327 | if (mac->associated) | ||
| 328 | schedule_work(&mac->associnfo.work); | ||
| 329 | } else if (is_zero_ether_addr(data->ap_addr.sa_data)) { | ||
| 330 | /* the bssid we have is no longer fixed */ | ||
| 331 | mac->associnfo.bssfixed = 0; | ||
| 327 | } else { | 332 | } else { |
| 328 | if (!memcmp(mac->associnfo.bssid, data->ap_addr.sa_data, ETH_ALEN)) { | 333 | if (!memcmp(mac->associnfo.bssid, data->ap_addr.sa_data, ETH_ALEN)) { |
| 329 | if (mac->associnfo.associating || mac->associated) { | 334 | if (mac->associnfo.associating || mac->associated) { |
| @@ -333,12 +338,14 @@ ieee80211softmac_wx_set_wap(struct net_device *net_dev, | |||
| 333 | } else { | 338 | } else { |
| 334 | /* copy new value in data->ap_addr.sa_data to bssid */ | 339 | /* copy new value in data->ap_addr.sa_data to bssid */ |
| 335 | memcpy(mac->associnfo.bssid, data->ap_addr.sa_data, ETH_ALEN); | 340 | memcpy(mac->associnfo.bssid, data->ap_addr.sa_data, ETH_ALEN); |
| 336 | } | 341 | } |
| 342 | /* tell the other code that this bssid should be used no matter what */ | ||
| 343 | mac->associnfo.bssfixed = 1; | ||
| 337 | /* queue associate if new bssid or (old one again and not associated) */ | 344 | /* queue associate if new bssid or (old one again and not associated) */ |
| 338 | schedule_work(&mac->associnfo.work); | 345 | schedule_work(&mac->associnfo.work); |
| 339 | } | 346 | } |
| 340 | 347 | ||
| 341 | out: | 348 | out: |
| 342 | spin_unlock_irqrestore(&mac->lock, flags); | 349 | spin_unlock_irqrestore(&mac->lock, flags); |
| 343 | return 0; | 350 | return 0; |
| 344 | } | 351 | } |
