diff options
Diffstat (limited to 'drivers/net')
30 files changed, 514 insertions, 289 deletions
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/ne.c b/drivers/net/ne.c index 08b218c5bfbc..93c494bcd18d 100644 --- a/drivers/net/ne.c +++ b/drivers/net/ne.c | |||
| @@ -226,7 +226,7 @@ struct net_device * __init ne_probe(int unit) | |||
| 226 | netdev_boot_setup_check(dev); | 226 | netdev_boot_setup_check(dev); |
| 227 | 227 | ||
| 228 | #ifdef CONFIG_TOSHIBA_RBTX4938 | 228 | #ifdef CONFIG_TOSHIBA_RBTX4938 |
| 229 | dev->base_addr = 0x07f20280; | 229 | dev->base_addr = RBTX4938_RTL_8019_BASE; |
| 230 | dev->irq = RBTX4938_RTL_8019_IRQ; | 230 | dev->irq = RBTX4938_RTL_8019_IRQ; |
| 231 | #endif | 231 | #endif |
| 232 | err = do_ne_probe(dev); | 232 | err = do_ne_probe(dev); |
diff --git a/drivers/net/pcmcia/pcnet_cs.c b/drivers/net/pcmcia/pcnet_cs.c index 506e777c5f06..d090df413049 100644 --- a/drivers/net/pcmcia/pcnet_cs.c +++ b/drivers/net/pcmcia/pcnet_cs.c | |||
| @@ -1639,6 +1639,7 @@ static struct pcmcia_device_id pcnet_ids[] = { | |||
| 1639 | PCMCIA_DEVICE_PROD_ID12("CONTEC", "C-NET(PC)C-10L", 0x21cab552, 0xf6f90722), | 1639 | PCMCIA_DEVICE_PROD_ID12("CONTEC", "C-NET(PC)C-10L", 0x21cab552, 0xf6f90722), |
| 1640 | PCMCIA_DEVICE_PROD_ID12("corega", "FEther PCC-TXF", 0x0a21501a, 0xa51564a2), | 1640 | PCMCIA_DEVICE_PROD_ID12("corega", "FEther PCC-TXF", 0x0a21501a, 0xa51564a2), |
| 1641 | PCMCIA_DEVICE_PROD_ID12("corega K.K.", "corega EtherII PCC-T", 0x5261440f, 0xfa9d85bd), | 1641 | PCMCIA_DEVICE_PROD_ID12("corega K.K.", "corega EtherII PCC-T", 0x5261440f, 0xfa9d85bd), |
| 1642 | PCMCIA_DEVICE_PROD_ID12("corega K.K.", "corega EtherII PCC-TD", 0x5261440f, 0xc49bd73d), | ||
| 1642 | PCMCIA_DEVICE_PROD_ID12("Corega K.K.", "corega EtherII PCC-TD", 0xd4fdcbd8, 0xc49bd73d), | 1643 | PCMCIA_DEVICE_PROD_ID12("Corega K.K.", "corega EtherII PCC-TD", 0xd4fdcbd8, 0xc49bd73d), |
| 1643 | PCMCIA_DEVICE_PROD_ID12("corega K.K.", "corega Ether PCC-T", 0x5261440f, 0x6705fcaa), | 1644 | PCMCIA_DEVICE_PROD_ID12("corega K.K.", "corega Ether PCC-T", 0x5261440f, 0x6705fcaa), |
| 1644 | PCMCIA_DEVICE_PROD_ID12("corega K.K.", "corega FastEther PCC-TX", 0x5261440f, 0x485e85d9), | 1645 | PCMCIA_DEVICE_PROD_ID12("corega K.K.", "corega FastEther PCC-TX", 0x5261440f, 0x485e85d9), |
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/sungem_phy.c b/drivers/net/sungem_phy.c index cb0aba95d4e3..046371ee5bbe 100644 --- a/drivers/net/sungem_phy.c +++ b/drivers/net/sungem_phy.c | |||
| @@ -275,7 +275,7 @@ static int bcm5411_init(struct mii_phy* phy) | |||
| 275 | return 0; | 275 | return 0; |
| 276 | } | 276 | } |
| 277 | 277 | ||
| 278 | static int bcm5411_suspend(struct mii_phy* phy) | 278 | static int generic_suspend(struct mii_phy* phy) |
| 279 | { | 279 | { |
| 280 | phy_write(phy, MII_BMCR, BMCR_PDOWN); | 280 | phy_write(phy, MII_BMCR, BMCR_PDOWN); |
| 281 | 281 | ||
| @@ -738,7 +738,7 @@ static struct mii_phy_def bcm5401_phy_def = { | |||
| 738 | /* Broadcom BCM 5411 */ | 738 | /* Broadcom BCM 5411 */ |
| 739 | static struct mii_phy_ops bcm5411_phy_ops = { | 739 | static struct mii_phy_ops bcm5411_phy_ops = { |
| 740 | .init = bcm5411_init, | 740 | .init = bcm5411_init, |
| 741 | .suspend = bcm5411_suspend, | 741 | .suspend = generic_suspend, |
| 742 | .setup_aneg = bcm54xx_setup_aneg, | 742 | .setup_aneg = bcm54xx_setup_aneg, |
| 743 | .setup_forced = bcm54xx_setup_forced, | 743 | .setup_forced = bcm54xx_setup_forced, |
| 744 | .poll_link = genmii_poll_link, | 744 | .poll_link = genmii_poll_link, |
| @@ -757,7 +757,7 @@ static struct mii_phy_def bcm5411_phy_def = { | |||
| 757 | /* Broadcom BCM 5421 */ | 757 | /* Broadcom BCM 5421 */ |
| 758 | static struct mii_phy_ops bcm5421_phy_ops = { | 758 | static struct mii_phy_ops bcm5421_phy_ops = { |
| 759 | .init = bcm5421_init, | 759 | .init = bcm5421_init, |
| 760 | .suspend = bcm5411_suspend, | 760 | .suspend = generic_suspend, |
| 761 | .setup_aneg = bcm54xx_setup_aneg, | 761 | .setup_aneg = bcm54xx_setup_aneg, |
| 762 | .setup_forced = bcm54xx_setup_forced, | 762 | .setup_forced = bcm54xx_setup_forced, |
| 763 | .poll_link = genmii_poll_link, | 763 | .poll_link = genmii_poll_link, |
| @@ -776,7 +776,7 @@ static struct mii_phy_def bcm5421_phy_def = { | |||
| 776 | /* Broadcom BCM 5421 built-in K2 */ | 776 | /* Broadcom BCM 5421 built-in K2 */ |
| 777 | static struct mii_phy_ops bcm5421k2_phy_ops = { | 777 | static struct mii_phy_ops bcm5421k2_phy_ops = { |
| 778 | .init = bcm5421_init, | 778 | .init = bcm5421_init, |
| 779 | .suspend = bcm5411_suspend, | 779 | .suspend = generic_suspend, |
| 780 | .setup_aneg = bcm54xx_setup_aneg, | 780 | .setup_aneg = bcm54xx_setup_aneg, |
| 781 | .setup_forced = bcm54xx_setup_forced, | 781 | .setup_forced = bcm54xx_setup_forced, |
| 782 | .poll_link = genmii_poll_link, | 782 | .poll_link = genmii_poll_link, |
| @@ -795,7 +795,7 @@ static struct mii_phy_def bcm5421k2_phy_def = { | |||
| 795 | /* Broadcom BCM 5462 built-in Vesta */ | 795 | /* Broadcom BCM 5462 built-in Vesta */ |
| 796 | static struct mii_phy_ops bcm5462V_phy_ops = { | 796 | static struct mii_phy_ops bcm5462V_phy_ops = { |
| 797 | .init = bcm5421_init, | 797 | .init = bcm5421_init, |
| 798 | .suspend = bcm5411_suspend, | 798 | .suspend = generic_suspend, |
| 799 | .setup_aneg = bcm54xx_setup_aneg, | 799 | .setup_aneg = bcm54xx_setup_aneg, |
| 800 | .setup_forced = bcm54xx_setup_forced, | 800 | .setup_forced = bcm54xx_setup_forced, |
| 801 | .poll_link = genmii_poll_link, | 801 | .poll_link = genmii_poll_link, |
| @@ -816,6 +816,7 @@ static struct mii_phy_def bcm5462V_phy_def = { | |||
| 816 | * would be useful here) --BenH. | 816 | * would be useful here) --BenH. |
| 817 | */ | 817 | */ |
| 818 | static struct mii_phy_ops marvell_phy_ops = { | 818 | static struct mii_phy_ops marvell_phy_ops = { |
| 819 | .suspend = generic_suspend, | ||
| 819 | .setup_aneg = marvell_setup_aneg, | 820 | .setup_aneg = marvell_setup_aneg, |
| 820 | .setup_forced = marvell_setup_forced, | 821 | .setup_forced = marvell_setup_forced, |
| 821 | .poll_link = genmii_poll_link, | 822 | .poll_link = genmii_poll_link, |
diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig index bad09ebdb50b..e0874cbfefea 100644 --- a/drivers/net/wireless/Kconfig +++ b/drivers/net/wireless/Kconfig | |||
| @@ -6,7 +6,7 @@ menu "Wireless LAN (non-hamradio)" | |||
| 6 | depends on NETDEVICES | 6 | depends on NETDEVICES |
| 7 | 7 | ||
| 8 | config NET_RADIO | 8 | config NET_RADIO |
| 9 | bool "Wireless LAN drivers (non-hamradio)" | 9 | bool "Wireless LAN drivers (non-hamradio) & Wireless Extensions" |
| 10 | select WIRELESS_EXT | 10 | select WIRELESS_EXT |
| 11 | ---help--- | 11 | ---help--- |
| 12 | Support for wireless LANs and everything having to do with radio, | 12 | Support for wireless LANs and everything having to do with radio, |
diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c index 108d9fed8f07..00764ddd74d8 100644 --- a/drivers/net/wireless/airo.c +++ b/drivers/net/wireless/airo.c | |||
| @@ -3139,6 +3139,7 @@ static irqreturn_t airo_interrupt ( int irq, void* dev_id, struct pt_regs *regs) | |||
| 3139 | } | 3139 | } |
| 3140 | if ( status & EV_LINK ) { | 3140 | if ( status & EV_LINK ) { |
| 3141 | union iwreq_data wrqu; | 3141 | union iwreq_data wrqu; |
| 3142 | int scan_forceloss = 0; | ||
| 3142 | /* The link status has changed, if you want to put a | 3143 | /* The link status has changed, if you want to put a |
| 3143 | monitor hook in, do it here. (Remember that | 3144 | monitor hook in, do it here. (Remember that |
| 3144 | interrupts are still disabled!) | 3145 | interrupts are still disabled!) |
| @@ -3157,7 +3158,8 @@ static irqreturn_t airo_interrupt ( int irq, void* dev_id, struct pt_regs *regs) | |||
| 3157 | code) */ | 3158 | code) */ |
| 3158 | #define AUTHFAIL 0x0300 /* Authentication failure (low byte is reason | 3159 | #define AUTHFAIL 0x0300 /* Authentication failure (low byte is reason |
| 3159 | code) */ | 3160 | code) */ |
| 3160 | #define ASSOCIATED 0x0400 /* Assocatied */ | 3161 | #define ASSOCIATED 0x0400 /* Associated */ |
| 3162 | #define REASSOCIATED 0x0600 /* Reassociated? Only on firmware >= 5.30.17 */ | ||
| 3161 | #define RC_RESERVED 0 /* Reserved return code */ | 3163 | #define RC_RESERVED 0 /* Reserved return code */ |
| 3162 | #define RC_NOREASON 1 /* Unspecified reason */ | 3164 | #define RC_NOREASON 1 /* Unspecified reason */ |
| 3163 | #define RC_AUTHINV 2 /* Previous authentication invalid */ | 3165 | #define RC_AUTHINV 2 /* Previous authentication invalid */ |
| @@ -3174,44 +3176,30 @@ static irqreturn_t airo_interrupt ( int irq, void* dev_id, struct pt_regs *regs) | |||
| 3174 | leaving BSS */ | 3176 | leaving BSS */ |
| 3175 | #define RC_NOAUTH 9 /* Station requesting (Re)Association is not | 3177 | #define RC_NOAUTH 9 /* Station requesting (Re)Association is not |
| 3176 | Authenticated with the responding station */ | 3178 | Authenticated with the responding station */ |
| 3177 | if (newStatus != ASSOCIATED) { | 3179 | if (newStatus == FORCELOSS && apriv->scan_timeout > 0) |
| 3178 | if (auto_wep && !apriv->expires) { | 3180 | scan_forceloss = 1; |
| 3179 | apriv->expires = RUN_AT(3*HZ); | 3181 | if(newStatus == ASSOCIATED || newStatus == REASSOCIATED) { |
| 3180 | wake_up_interruptible(&apriv->thr_wait); | ||
| 3181 | } | ||
| 3182 | } else { | ||
| 3183 | struct task_struct *task = apriv->task; | ||
| 3184 | if (auto_wep) | 3182 | if (auto_wep) |
| 3185 | apriv->expires = 0; | 3183 | apriv->expires = 0; |
| 3186 | if (task) | 3184 | if (apriv->task) |
| 3187 | wake_up_process (task); | 3185 | wake_up_process (apriv->task); |
| 3188 | set_bit(FLAG_UPDATE_UNI, &apriv->flags); | 3186 | set_bit(FLAG_UPDATE_UNI, &apriv->flags); |
| 3189 | set_bit(FLAG_UPDATE_MULTI, &apriv->flags); | 3187 | set_bit(FLAG_UPDATE_MULTI, &apriv->flags); |
| 3190 | } | 3188 | |
| 3191 | /* Question : is ASSOCIATED the only status | ||
| 3192 | * that is valid ? We want to catch handover | ||
| 3193 | * and reassociations as valid status | ||
| 3194 | * Jean II */ | ||
| 3195 | if(newStatus == ASSOCIATED) { | ||
| 3196 | #if 0 | ||
| 3197 | /* FIXME: Grabbing scan results here | ||
| 3198 | * seems to be too early??? Just wait for | ||
| 3199 | * timeout instead. */ | ||
| 3200 | if (apriv->scan_timeout > 0) { | ||
| 3201 | set_bit(JOB_SCAN_RESULTS, &apriv->flags); | ||
| 3202 | wake_up_interruptible(&apriv->thr_wait); | ||
| 3203 | } | ||
| 3204 | #endif | ||
| 3205 | if (down_trylock(&apriv->sem) != 0) { | 3189 | if (down_trylock(&apriv->sem) != 0) { |
| 3206 | set_bit(JOB_EVENT, &apriv->flags); | 3190 | set_bit(JOB_EVENT, &apriv->flags); |
| 3207 | wake_up_interruptible(&apriv->thr_wait); | 3191 | wake_up_interruptible(&apriv->thr_wait); |
| 3208 | } else | 3192 | } else |
| 3209 | airo_send_event(dev); | 3193 | airo_send_event(dev); |
| 3210 | } else { | 3194 | } else if (!scan_forceloss) { |
| 3211 | memset(wrqu.ap_addr.sa_data, '\0', ETH_ALEN); | 3195 | if (auto_wep && !apriv->expires) { |
| 3212 | wrqu.ap_addr.sa_family = ARPHRD_ETHER; | 3196 | apriv->expires = RUN_AT(3*HZ); |
| 3197 | wake_up_interruptible(&apriv->thr_wait); | ||
| 3198 | } | ||
| 3213 | 3199 | ||
| 3214 | /* Send event to user space */ | 3200 | /* Send event to user space */ |
| 3201 | memset(wrqu.ap_addr.sa_data, '\0', ETH_ALEN); | ||
| 3202 | wrqu.ap_addr.sa_family = ARPHRD_ETHER; | ||
| 3215 | wireless_send_event(dev, SIOCGIWAP, &wrqu,NULL); | 3203 | wireless_send_event(dev, SIOCGIWAP, &wrqu,NULL); |
| 3216 | } | 3204 | } |
| 3217 | } | 3205 | } |
| @@ -7136,10 +7124,10 @@ static int airo_set_scan(struct net_device *dev, | |||
| 7136 | goto out; | 7124 | goto out; |
| 7137 | 7125 | ||
| 7138 | /* Initiate a scan command */ | 7126 | /* Initiate a scan command */ |
| 7127 | ai->scan_timeout = RUN_AT(3*HZ); | ||
| 7139 | memset(&cmd, 0, sizeof(cmd)); | 7128 | memset(&cmd, 0, sizeof(cmd)); |
| 7140 | cmd.cmd=CMD_LISTBSS; | 7129 | cmd.cmd=CMD_LISTBSS; |
| 7141 | issuecommand(ai, &cmd, &rsp); | 7130 | issuecommand(ai, &cmd, &rsp); |
| 7142 | ai->scan_timeout = RUN_AT(3*HZ); | ||
| 7143 | wake = 1; | 7131 | wake = 1; |
| 7144 | 7132 | ||
| 7145 | out: | 7133 | out: |
diff --git a/drivers/net/wireless/atmel.c b/drivers/net/wireless/atmel.c index 87afa6878f26..8606c88886fc 100644 --- a/drivers/net/wireless/atmel.c +++ b/drivers/net/wireless/atmel.c | |||
| @@ -3463,6 +3463,7 @@ static void atmel_command_irq(struct atmel_private *priv) | |||
| 3463 | u8 status = atmel_rmem8(priv, atmel_co(priv, CMD_BLOCK_STATUS_OFFSET)); | 3463 | u8 status = atmel_rmem8(priv, atmel_co(priv, CMD_BLOCK_STATUS_OFFSET)); |
| 3464 | u8 command = atmel_rmem8(priv, atmel_co(priv, CMD_BLOCK_COMMAND_OFFSET)); | 3464 | u8 command = atmel_rmem8(priv, atmel_co(priv, CMD_BLOCK_COMMAND_OFFSET)); |
| 3465 | int fast_scan; | 3465 | int fast_scan; |
| 3466 | union iwreq_data wrqu; | ||
| 3466 | 3467 | ||
| 3467 | if (status == CMD_STATUS_IDLE || | 3468 | if (status == CMD_STATUS_IDLE || |
| 3468 | status == CMD_STATUS_IN_PROGRESS) | 3469 | status == CMD_STATUS_IN_PROGRESS) |
| @@ -3487,6 +3488,7 @@ static void atmel_command_irq(struct atmel_private *priv) | |||
| 3487 | atmel_scan(priv, 1); | 3488 | atmel_scan(priv, 1); |
| 3488 | } else { | 3489 | } else { |
| 3489 | int bss_index = retrieve_bss(priv); | 3490 | int bss_index = retrieve_bss(priv); |
| 3491 | int notify_scan_complete = 1; | ||
| 3490 | if (bss_index != -1) { | 3492 | if (bss_index != -1) { |
| 3491 | atmel_join_bss(priv, bss_index); | 3493 | atmel_join_bss(priv, bss_index); |
| 3492 | } else if (priv->operating_mode == IW_MODE_ADHOC && | 3494 | } else if (priv->operating_mode == IW_MODE_ADHOC && |
| @@ -3495,8 +3497,14 @@ static void atmel_command_irq(struct atmel_private *priv) | |||
| 3495 | } else { | 3497 | } else { |
| 3496 | priv->fast_scan = !fast_scan; | 3498 | priv->fast_scan = !fast_scan; |
| 3497 | atmel_scan(priv, 1); | 3499 | atmel_scan(priv, 1); |
| 3500 | notify_scan_complete = 0; | ||
| 3498 | } | 3501 | } |
| 3499 | priv->site_survey_state = SITE_SURVEY_COMPLETED; | 3502 | priv->site_survey_state = SITE_SURVEY_COMPLETED; |
| 3503 | if (notify_scan_complete) { | ||
| 3504 | wrqu.data.length = 0; | ||
| 3505 | wrqu.data.flags = 0; | ||
| 3506 | wireless_send_event(priv->dev, SIOCGIWSCAN, &wrqu, NULL); | ||
| 3507 | } | ||
| 3500 | } | 3508 | } |
| 3501 | break; | 3509 | break; |
| 3502 | 3510 | ||
| @@ -3509,6 +3517,9 @@ static void atmel_command_irq(struct atmel_private *priv) | |||
| 3509 | priv->site_survey_state = SITE_SURVEY_COMPLETED; | 3517 | priv->site_survey_state = SITE_SURVEY_COMPLETED; |
| 3510 | if (priv->station_is_associated) { | 3518 | if (priv->station_is_associated) { |
| 3511 | atmel_enter_state(priv, STATION_STATE_READY); | 3519 | atmel_enter_state(priv, STATION_STATE_READY); |
| 3520 | wrqu.data.length = 0; | ||
| 3521 | wrqu.data.flags = 0; | ||
| 3522 | wireless_send_event(priv->dev, SIOCGIWSCAN, &wrqu, NULL); | ||
| 3512 | } else { | 3523 | } else { |
| 3513 | atmel_scan(priv, 1); | 3524 | atmel_scan(priv, 1); |
| 3514 | } | 3525 | } |
diff --git a/drivers/net/wireless/bcm43xx/Kconfig b/drivers/net/wireless/bcm43xx/Kconfig index 418465600a77..25ea4748f0b9 100644 --- a/drivers/net/wireless/bcm43xx/Kconfig +++ b/drivers/net/wireless/bcm43xx/Kconfig | |||
| @@ -17,8 +17,11 @@ config BCM43XX_DEBUG | |||
| 17 | 17 | ||
| 18 | config BCM43XX_DMA | 18 | config BCM43XX_DMA |
| 19 | bool | 19 | bool |
| 20 | depends on BCM43XX | ||
| 21 | |||
| 20 | config BCM43XX_PIO | 22 | config BCM43XX_PIO |
| 21 | bool | 23 | bool |
| 24 | depends on BCM43XX | ||
| 22 | 25 | ||
| 23 | choice | 26 | choice |
| 24 | prompt "BCM43xx data transfer mode" | 27 | prompt "BCM43xx data transfer mode" |
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx.h b/drivers/net/wireless/bcm43xx/bcm43xx.h index dcadd295de4f..2e83083935e1 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx.h +++ b/drivers/net/wireless/bcm43xx/bcm43xx.h | |||
| @@ -15,7 +15,6 @@ | |||
| 15 | 15 | ||
| 16 | #include "bcm43xx_debugfs.h" | 16 | #include "bcm43xx_debugfs.h" |
| 17 | #include "bcm43xx_leds.h" | 17 | #include "bcm43xx_leds.h" |
| 18 | #include "bcm43xx_sysfs.h" | ||
| 19 | 18 | ||
| 20 | 19 | ||
| 21 | #define PFX KBUILD_MODNAME ": " | 20 | #define PFX KBUILD_MODNAME ": " |
| @@ -638,8 +637,6 @@ struct bcm43xx_key { | |||
| 638 | }; | 637 | }; |
| 639 | 638 | ||
| 640 | struct bcm43xx_private { | 639 | struct bcm43xx_private { |
| 641 | struct bcm43xx_sysfs sysfs; | ||
| 642 | |||
| 643 | struct ieee80211_device *ieee; | 640 | struct ieee80211_device *ieee; |
| 644 | struct ieee80211softmac_device *softmac; | 641 | struct ieee80211softmac_device *softmac; |
| 645 | 642 | ||
| @@ -772,6 +769,20 @@ struct bcm43xx_private * bcm43xx_priv(struct net_device *dev) | |||
| 772 | return ieee80211softmac_priv(dev); | 769 | return ieee80211softmac_priv(dev); |
| 773 | } | 770 | } |
| 774 | 771 | ||
| 772 | struct device; | ||
| 773 | |||
| 774 | static inline | ||
| 775 | struct bcm43xx_private * dev_to_bcm(struct device *dev) | ||
| 776 | { | ||
| 777 | struct net_device *net_dev; | ||
| 778 | struct bcm43xx_private *bcm; | ||
| 779 | |||
| 780 | net_dev = dev_get_drvdata(dev); | ||
| 781 | bcm = bcm43xx_priv(net_dev); | ||
| 782 | |||
| 783 | return bcm; | ||
| 784 | } | ||
| 785 | |||
| 775 | 786 | ||
| 776 | /* Helper function, which returns a boolean. | 787 | /* Helper function, which returns a boolean. |
| 777 | * TRUE, if PIO is used; FALSE, if DMA is used. | 788 | * TRUE, if PIO is used; FALSE, if DMA is used. |
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c b/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c index d2c3401e9b70..35a4fcb6d923 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c | |||
| @@ -452,12 +452,12 @@ void bcm43xx_printk_dump(const char *data, | |||
| 452 | size_t i; | 452 | size_t i; |
| 453 | char c; | 453 | char c; |
| 454 | 454 | ||
| 455 | printk(KERN_INFO PFX "Data dump (%s, %u bytes):", | 455 | printk(KERN_INFO PFX "Data dump (%s, %zd bytes):", |
| 456 | description, size); | 456 | description, size); |
| 457 | for (i = 0; i < size; i++) { | 457 | for (i = 0; i < size; i++) { |
| 458 | c = data[i]; | 458 | c = data[i]; |
| 459 | if (i % 8 == 0) | 459 | if (i % 8 == 0) |
| 460 | printk("\n" KERN_INFO PFX "0x%08x: 0x%02x, ", i, c & 0xff); | 460 | printk("\n" KERN_INFO PFX "0x%08zx: 0x%02x, ", i, c & 0xff); |
| 461 | else | 461 | else |
| 462 | printk("0x%02x, ", c & 0xff); | 462 | printk("0x%02x, ", c & 0xff); |
| 463 | } | 463 | } |
| @@ -472,12 +472,12 @@ void bcm43xx_printk_bitdump(const unsigned char *data, | |||
| 472 | int j; | 472 | int j; |
| 473 | const unsigned char *d; | 473 | const unsigned char *d; |
| 474 | 474 | ||
| 475 | printk(KERN_INFO PFX "*** Bitdump (%s, %u bytes, %s) ***", | 475 | printk(KERN_INFO PFX "*** Bitdump (%s, %zd bytes, %s) ***", |
| 476 | description, bytes, msb_to_lsb ? "MSB to LSB" : "LSB to MSB"); | 476 | description, bytes, msb_to_lsb ? "MSB to LSB" : "LSB to MSB"); |
| 477 | for (i = 0; i < bytes; i++) { | 477 | for (i = 0; i < bytes; i++) { |
| 478 | d = data + i; | 478 | d = data + i; |
| 479 | if (i % 8 == 0) | 479 | if (i % 8 == 0) |
| 480 | printk("\n" KERN_INFO PFX "0x%08x: ", i); | 480 | printk("\n" KERN_INFO PFX "0x%08zx: ", i); |
| 481 | if (msb_to_lsb) { | 481 | if (msb_to_lsb) { |
| 482 | for (j = 7; j >= 0; j--) { | 482 | for (j = 7; j >= 0; j--) { |
| 483 | if (*d & (1 << j)) | 483 | if (*d & (1 << j)) |
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_dma.c b/drivers/net/wireless/bcm43xx/bcm43xx_dma.c index c3681b8f09b4..bbecba02e697 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_dma.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_dma.c | |||
| @@ -196,8 +196,9 @@ static int alloc_ringmemory(struct bcm43xx_dmaring *ring) | |||
| 196 | } | 196 | } |
| 197 | if (ring->dmabase + BCM43xx_DMA_RINGMEMSIZE > BCM43xx_DMA_BUSADDRMAX) { | 197 | if (ring->dmabase + BCM43xx_DMA_RINGMEMSIZE > BCM43xx_DMA_BUSADDRMAX) { |
| 198 | printk(KERN_ERR PFX ">>>FATAL ERROR<<< DMA RINGMEMORY >1G " | 198 | printk(KERN_ERR PFX ">>>FATAL ERROR<<< DMA RINGMEMORY >1G " |
| 199 | "(0x%08x, len: %lu)\n", | 199 | "(0x%llx, len: %lu)\n", |
| 200 | ring->dmabase, BCM43xx_DMA_RINGMEMSIZE); | 200 | (unsigned long long)ring->dmabase, |
| 201 | BCM43xx_DMA_RINGMEMSIZE); | ||
| 201 | dma_free_coherent(dev, BCM43xx_DMA_RINGMEMSIZE, | 202 | dma_free_coherent(dev, BCM43xx_DMA_RINGMEMSIZE, |
| 202 | ring->vbase, ring->dmabase); | 203 | ring->vbase, ring->dmabase); |
| 203 | return -ENOMEM; | 204 | return -ENOMEM; |
| @@ -307,8 +308,8 @@ static int setup_rx_descbuffer(struct bcm43xx_dmaring *ring, | |||
| 307 | unmap_descbuffer(ring, dmaaddr, ring->rx_buffersize, 0); | 308 | unmap_descbuffer(ring, dmaaddr, ring->rx_buffersize, 0); |
| 308 | dev_kfree_skb_any(skb); | 309 | dev_kfree_skb_any(skb); |
| 309 | printk(KERN_ERR PFX ">>>FATAL ERROR<<< DMA RX SKB >1G " | 310 | printk(KERN_ERR PFX ">>>FATAL ERROR<<< DMA RX SKB >1G " |
| 310 | "(0x%08x, len: %u)\n", | 311 | "(0x%llx, len: %u)\n", |
| 311 | dmaaddr, ring->rx_buffersize); | 312 | (unsigned long long)dmaaddr, ring->rx_buffersize); |
| 312 | return -ENOMEM; | 313 | return -ENOMEM; |
| 313 | } | 314 | } |
| 314 | meta->skb = skb; | 315 | meta->skb = skb; |
| @@ -729,8 +730,8 @@ static int dma_tx_fragment(struct bcm43xx_dmaring *ring, | |||
| 729 | if (unlikely(meta->dmaaddr + skb->len > BCM43xx_DMA_BUSADDRMAX)) { | 730 | if (unlikely(meta->dmaaddr + skb->len > BCM43xx_DMA_BUSADDRMAX)) { |
| 730 | return_slot(ring, slot); | 731 | return_slot(ring, slot); |
| 731 | printk(KERN_ERR PFX ">>>FATAL ERROR<<< DMA TX SKB >1G " | 732 | printk(KERN_ERR PFX ">>>FATAL ERROR<<< DMA TX SKB >1G " |
| 732 | "(0x%08x, len: %u)\n", | 733 | "(0x%llx, len: %u)\n", |
| 733 | meta->dmaaddr, skb->len); | 734 | (unsigned long long)meta->dmaaddr, skb->len); |
| 734 | return -ENOMEM; | 735 | return -ENOMEM; |
| 735 | } | 736 | } |
| 736 | 737 | ||
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_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c index c37371fc9e01..9a06e61df0a2 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c | |||
| @@ -52,6 +52,7 @@ | |||
| 52 | #include "bcm43xx_wx.h" | 52 | #include "bcm43xx_wx.h" |
| 53 | #include "bcm43xx_ethtool.h" | 53 | #include "bcm43xx_ethtool.h" |
| 54 | #include "bcm43xx_xmit.h" | 54 | #include "bcm43xx_xmit.h" |
| 55 | #include "bcm43xx_sysfs.h" | ||
| 55 | 56 | ||
| 56 | 57 | ||
| 57 | MODULE_DESCRIPTION("Broadcom BCM43xx wireless driver"); | 58 | MODULE_DESCRIPTION("Broadcom BCM43xx wireless driver"); |
| @@ -3522,6 +3523,7 @@ static inline int bcm43xx_tx(struct bcm43xx_private *bcm, | |||
| 3522 | err = bcm43xx_pio_tx(bcm, txb); | 3523 | err = bcm43xx_pio_tx(bcm, txb); |
| 3523 | else | 3524 | else |
| 3524 | err = bcm43xx_dma_tx(bcm, txb); | 3525 | err = bcm43xx_dma_tx(bcm, txb); |
| 3526 | bcm->net_dev->trans_start = jiffies; | ||
| 3525 | 3527 | ||
| 3526 | return err; | 3528 | return err; |
| 3527 | } | 3529 | } |
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_phy.c b/drivers/net/wireless/bcm43xx/bcm43xx_phy.c index 0a66f43ca0c0..33137165727f 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_phy.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_phy.c | |||
| @@ -2151,6 +2151,7 @@ int bcm43xx_phy_init_tssi2dbm_table(struct bcm43xx_private *bcm) | |||
| 2151 | phy->tssi2dbm = NULL; | 2151 | phy->tssi2dbm = NULL; |
| 2152 | printk(KERN_ERR PFX "Could not generate " | 2152 | printk(KERN_ERR PFX "Could not generate " |
| 2153 | "tssi2dBm table\n"); | 2153 | "tssi2dBm table\n"); |
| 2154 | kfree(dyn_tssi2dbm); | ||
| 2154 | return -ENODEV; | 2155 | return -ENODEV; |
| 2155 | } | 2156 | } |
| 2156 | phy->tssi2dbm = dyn_tssi2dbm; | 2157 | phy->tssi2dbm = dyn_tssi2dbm; |
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/bcm43xx/bcm43xx_power.c b/drivers/net/wireless/bcm43xx/bcm43xx_power.c index 3c92b62807c5..6569da3a7a39 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_power.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_power.c | |||
| @@ -35,77 +35,101 @@ | |||
| 35 | #include "bcm43xx_main.h" | 35 | #include "bcm43xx_main.h" |
| 36 | 36 | ||
| 37 | 37 | ||
| 38 | /* Get the Slow Clock Source */ | ||
| 39 | static int bcm43xx_pctl_get_slowclksrc(struct bcm43xx_private *bcm) | ||
| 40 | { | ||
| 41 | u32 tmp; | ||
| 42 | int err; | ||
| 43 | |||
| 44 | assert(bcm->current_core == &bcm->core_chipcommon); | ||
| 45 | if (bcm->current_core->rev < 6) { | ||
| 46 | if (bcm->bustype == BCM43xx_BUSTYPE_PCMCIA || | ||
| 47 | bcm->bustype == BCM43xx_BUSTYPE_SB) | ||
| 48 | return BCM43xx_PCTL_CLKSRC_XTALOS; | ||
| 49 | if (bcm->bustype == BCM43xx_BUSTYPE_PCI) { | ||
| 50 | err = bcm43xx_pci_read_config32(bcm, BCM43xx_PCTL_OUT, &tmp); | ||
| 51 | assert(!err); | ||
| 52 | if (tmp & 0x10) | ||
| 53 | return BCM43xx_PCTL_CLKSRC_PCI; | ||
| 54 | return BCM43xx_PCTL_CLKSRC_XTALOS; | ||
| 55 | } | ||
| 56 | } | ||
| 57 | if (bcm->current_core->rev < 10) { | ||
| 58 | tmp = bcm43xx_read32(bcm, BCM43xx_CHIPCOMMON_SLOWCLKCTL); | ||
| 59 | tmp &= 0x7; | ||
| 60 | if (tmp == 0) | ||
| 61 | return BCM43xx_PCTL_CLKSRC_LOPWROS; | ||
| 62 | if (tmp == 1) | ||
| 63 | return BCM43xx_PCTL_CLKSRC_XTALOS; | ||
| 64 | if (tmp == 2) | ||
| 65 | return BCM43xx_PCTL_CLKSRC_PCI; | ||
| 66 | } | ||
| 67 | |||
| 68 | return BCM43xx_PCTL_CLKSRC_XTALOS; | ||
| 69 | } | ||
| 70 | |||
| 38 | /* Get max/min slowclock frequency | 71 | /* Get max/min slowclock frequency |
| 39 | * as described in http://bcm-specs.sipsolutions.net/PowerControl | 72 | * as described in http://bcm-specs.sipsolutions.net/PowerControl |
| 40 | */ | 73 | */ |
| 41 | static int bcm43xx_pctl_clockfreqlimit(struct bcm43xx_private *bcm, | 74 | static int bcm43xx_pctl_clockfreqlimit(struct bcm43xx_private *bcm, |
| 42 | int get_max) | 75 | int get_max) |
| 43 | { | 76 | { |
| 44 | int limit = 0; | 77 | int limit; |
| 78 | int clocksrc; | ||
| 45 | int divisor; | 79 | int divisor; |
| 46 | int selection; | ||
| 47 | int err; | ||
| 48 | u32 tmp; | 80 | u32 tmp; |
| 49 | struct bcm43xx_coreinfo *old_core; | ||
| 50 | 81 | ||
| 51 | if (!(bcm->chipcommon_capabilities & BCM43xx_CAPABILITIES_PCTL)) | 82 | assert(bcm->chipcommon_capabilities & BCM43xx_CAPABILITIES_PCTL); |
| 52 | goto out; | 83 | assert(bcm->current_core == &bcm->core_chipcommon); |
| 53 | old_core = bcm->current_core; | ||
| 54 | err = bcm43xx_switch_core(bcm, &bcm->core_chipcommon); | ||
| 55 | if (err) | ||
| 56 | goto out; | ||
| 57 | 84 | ||
| 85 | clocksrc = bcm43xx_pctl_get_slowclksrc(bcm); | ||
| 58 | if (bcm->current_core->rev < 6) { | 86 | if (bcm->current_core->rev < 6) { |
| 59 | if ((bcm->bustype == BCM43xx_BUSTYPE_PCMCIA) || | 87 | switch (clocksrc) { |
| 60 | (bcm->bustype == BCM43xx_BUSTYPE_SB)) { | 88 | case BCM43xx_PCTL_CLKSRC_PCI: |
| 61 | selection = 1; | 89 | divisor = 64; |
| 90 | break; | ||
| 91 | case BCM43xx_PCTL_CLKSRC_XTALOS: | ||
| 62 | divisor = 32; | 92 | divisor = 32; |
| 63 | } else { | 93 | break; |
| 64 | err = bcm43xx_pci_read_config32(bcm, BCM43xx_PCTL_OUT, &tmp); | 94 | default: |
| 65 | if (err) { | 95 | assert(0); |
| 66 | printk(KERN_ERR PFX "clockfreqlimit pcicfg read failure\n"); | 96 | divisor = 1; |
| 67 | goto out_switchback; | ||
| 68 | } | ||
| 69 | if (tmp & 0x10) { | ||
| 70 | /* PCI */ | ||
| 71 | selection = 2; | ||
| 72 | divisor = 64; | ||
| 73 | } else { | ||
| 74 | /* XTAL */ | ||
| 75 | selection = 1; | ||
| 76 | divisor = 32; | ||
| 77 | } | ||
| 78 | } | 97 | } |
| 79 | } else if (bcm->current_core->rev < 10) { | 98 | } else if (bcm->current_core->rev < 10) { |
| 80 | selection = (tmp & 0x07); | 99 | switch (clocksrc) { |
| 81 | if (selection) { | 100 | case BCM43xx_PCTL_CLKSRC_LOPWROS: |
| 101 | divisor = 1; | ||
| 102 | break; | ||
| 103 | case BCM43xx_PCTL_CLKSRC_XTALOS: | ||
| 104 | case BCM43xx_PCTL_CLKSRC_PCI: | ||
| 82 | tmp = bcm43xx_read32(bcm, BCM43xx_CHIPCOMMON_SLOWCLKCTL); | 105 | tmp = bcm43xx_read32(bcm, BCM43xx_CHIPCOMMON_SLOWCLKCTL); |
| 83 | divisor = 4 * (1 + ((tmp & 0xFFFF0000) >> 16)); | 106 | divisor = ((tmp & 0xFFFF0000) >> 16) + 1; |
| 84 | } else | 107 | divisor *= 4; |
| 108 | break; | ||
| 109 | default: | ||
| 110 | assert(0); | ||
| 85 | divisor = 1; | 111 | divisor = 1; |
| 112 | } | ||
| 86 | } else { | 113 | } else { |
| 87 | tmp = bcm43xx_read32(bcm, BCM43xx_CHIPCOMMON_SYSCLKCTL); | 114 | tmp = bcm43xx_read32(bcm, BCM43xx_CHIPCOMMON_SYSCLKCTL); |
| 88 | divisor = 4 * (1 + ((tmp & 0xFFFF0000) >> 16)); | 115 | divisor = ((tmp & 0xFFFF0000) >> 16) + 1; |
| 89 | selection = 1; | 116 | divisor *= 4; |
| 90 | } | 117 | } |
| 91 | 118 | ||
| 92 | switch (selection) { | 119 | switch (clocksrc) { |
| 93 | case 0: | 120 | case BCM43xx_PCTL_CLKSRC_LOPWROS: |
| 94 | /* LPO */ | ||
| 95 | if (get_max) | 121 | if (get_max) |
| 96 | limit = 43000; | 122 | limit = 43000; |
| 97 | else | 123 | else |
| 98 | limit = 25000; | 124 | limit = 25000; |
| 99 | break; | 125 | break; |
| 100 | case 1: | 126 | case BCM43xx_PCTL_CLKSRC_XTALOS: |
| 101 | /* XTAL */ | ||
| 102 | if (get_max) | 127 | if (get_max) |
| 103 | limit = 20200000; | 128 | limit = 20200000; |
| 104 | else | 129 | else |
| 105 | limit = 19800000; | 130 | limit = 19800000; |
| 106 | break; | 131 | break; |
| 107 | case 2: | 132 | case BCM43xx_PCTL_CLKSRC_PCI: |
| 108 | /* PCI */ | ||
| 109 | if (get_max) | 133 | if (get_max) |
| 110 | limit = 34000000; | 134 | limit = 34000000; |
| 111 | else | 135 | else |
| @@ -113,17 +137,14 @@ static int bcm43xx_pctl_clockfreqlimit(struct bcm43xx_private *bcm, | |||
| 113 | break; | 137 | break; |
| 114 | default: | 138 | default: |
| 115 | assert(0); | 139 | assert(0); |
| 140 | limit = 0; | ||
| 116 | } | 141 | } |
| 117 | limit /= divisor; | 142 | limit /= divisor; |
| 118 | 143 | ||
| 119 | out_switchback: | ||
| 120 | err = bcm43xx_switch_core(bcm, old_core); | ||
| 121 | assert(err == 0); | ||
| 122 | |||
| 123 | out: | ||
| 124 | return limit; | 144 | return limit; |
| 125 | } | 145 | } |
| 126 | 146 | ||
| 147 | |||
| 127 | /* init power control | 148 | /* init power control |
| 128 | * as described in http://bcm-specs.sipsolutions.net/PowerControl | 149 | * as described in http://bcm-specs.sipsolutions.net/PowerControl |
| 129 | */ | 150 | */ |
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_power.h b/drivers/net/wireless/bcm43xx/bcm43xx_power.h index 5f63640810bd..c966ab3a5a8c 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_power.h +++ b/drivers/net/wireless/bcm43xx/bcm43xx_power.h | |||
| @@ -33,6 +33,15 @@ | |||
| 33 | 33 | ||
| 34 | #include <linux/types.h> | 34 | #include <linux/types.h> |
| 35 | 35 | ||
| 36 | /* Clock sources */ | ||
| 37 | enum { | ||
| 38 | /* PCI clock */ | ||
| 39 | BCM43xx_PCTL_CLKSRC_PCI, | ||
| 40 | /* Crystal slow clock oscillator */ | ||
| 41 | BCM43xx_PCTL_CLKSRC_XTALOS, | ||
| 42 | /* Low power oscillator */ | ||
| 43 | BCM43xx_PCTL_CLKSRC_LOPWROS, | ||
| 44 | }; | ||
| 36 | 45 | ||
| 37 | struct bcm43xx_private; | 46 | struct bcm43xx_private; |
| 38 | 47 | ||
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c b/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c index c44d890b949b..b438f48e891d 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c | |||
| @@ -71,14 +71,46 @@ static int get_boolean(const char *buf, size_t count) | |||
| 71 | return -EINVAL; | 71 | return -EINVAL; |
| 72 | } | 72 | } |
| 73 | 73 | ||
| 74 | static int sprom2hex(const u16 *sprom, char *buf, size_t buf_len) | ||
| 75 | { | ||
| 76 | int i, pos = 0; | ||
| 77 | |||
| 78 | for (i = 0; i < BCM43xx_SPROM_SIZE; i++) { | ||
| 79 | pos += snprintf(buf + pos, buf_len - pos - 1, | ||
| 80 | "%04X", swab16(sprom[i]) & 0xFFFF); | ||
| 81 | } | ||
| 82 | pos += snprintf(buf + pos, buf_len - pos - 1, "\n"); | ||
| 83 | |||
| 84 | return pos + 1; | ||
| 85 | } | ||
| 86 | |||
| 87 | static int hex2sprom(u16 *sprom, const char *dump, size_t len) | ||
| 88 | { | ||
| 89 | char tmp[5] = { 0 }; | ||
| 90 | int cnt = 0; | ||
| 91 | unsigned long parsed; | ||
| 92 | |||
| 93 | if (len < BCM43xx_SPROM_SIZE * sizeof(u16) * 2) | ||
| 94 | return -EINVAL; | ||
| 95 | |||
| 96 | while (cnt < BCM43xx_SPROM_SIZE) { | ||
| 97 | memcpy(tmp, dump, 4); | ||
| 98 | dump += 4; | ||
| 99 | parsed = simple_strtoul(tmp, NULL, 16); | ||
| 100 | sprom[cnt++] = swab16((u16)parsed); | ||
| 101 | } | ||
| 102 | |||
| 103 | return 0; | ||
| 104 | } | ||
| 105 | |||
| 74 | static ssize_t bcm43xx_attr_sprom_show(struct device *dev, | 106 | static ssize_t bcm43xx_attr_sprom_show(struct device *dev, |
| 75 | struct device_attribute *attr, | 107 | struct device_attribute *attr, |
| 76 | char *buf) | 108 | char *buf) |
| 77 | { | 109 | { |
| 78 | struct bcm43xx_private *bcm = devattr_to_bcm(attr, attr_sprom); | 110 | struct bcm43xx_private *bcm = dev_to_bcm(dev); |
| 79 | u16 *sprom; | 111 | u16 *sprom; |
| 80 | unsigned long flags; | 112 | unsigned long flags; |
| 81 | int i, err; | 113 | int err; |
| 82 | 114 | ||
| 83 | if (!capable(CAP_NET_ADMIN)) | 115 | if (!capable(CAP_NET_ADMIN)) |
| 84 | return -EPERM; | 116 | return -EPERM; |
| @@ -91,55 +123,53 @@ static ssize_t bcm43xx_attr_sprom_show(struct device *dev, | |||
| 91 | bcm43xx_lock_mmio(bcm, flags); | 123 | bcm43xx_lock_mmio(bcm, flags); |
| 92 | assert(bcm->initialized); | 124 | assert(bcm->initialized); |
| 93 | err = bcm43xx_sprom_read(bcm, sprom); | 125 | err = bcm43xx_sprom_read(bcm, sprom); |
| 94 | if (!err) { | 126 | if (!err) |
| 95 | for (i = 0; i < BCM43xx_SPROM_SIZE; i++) { | 127 | err = sprom2hex(sprom, buf, PAGE_SIZE); |
| 96 | buf[i * 2] = sprom[i] & 0x00FF; | ||
| 97 | buf[i * 2 + 1] = (sprom[i] & 0xFF00) >> 8; | ||
| 98 | } | ||
| 99 | } | ||
| 100 | bcm43xx_unlock_mmio(bcm, flags); | 128 | bcm43xx_unlock_mmio(bcm, flags); |
| 101 | kfree(sprom); | 129 | kfree(sprom); |
| 102 | 130 | ||
| 103 | return err ? err : BCM43xx_SPROM_SIZE * sizeof(u16); | 131 | return err; |
| 104 | } | 132 | } |
| 105 | 133 | ||
| 106 | static ssize_t bcm43xx_attr_sprom_store(struct device *dev, | 134 | static ssize_t bcm43xx_attr_sprom_store(struct device *dev, |
| 107 | struct device_attribute *attr, | 135 | struct device_attribute *attr, |
| 108 | const char *buf, size_t count) | 136 | const char *buf, size_t count) |
| 109 | { | 137 | { |
| 110 | struct bcm43xx_private *bcm = devattr_to_bcm(attr, attr_sprom); | 138 | struct bcm43xx_private *bcm = dev_to_bcm(dev); |
| 111 | u16 *sprom; | 139 | u16 *sprom; |
| 112 | unsigned long flags; | 140 | unsigned long flags; |
| 113 | int i, err; | 141 | int err; |
| 114 | 142 | ||
| 115 | if (!capable(CAP_NET_ADMIN)) | 143 | if (!capable(CAP_NET_ADMIN)) |
| 116 | return -EPERM; | 144 | return -EPERM; |
| 117 | 145 | ||
| 118 | if (count != BCM43xx_SPROM_SIZE * sizeof(u16)) | ||
| 119 | return -EINVAL; | ||
| 120 | sprom = kmalloc(BCM43xx_SPROM_SIZE * sizeof(*sprom), | 146 | sprom = kmalloc(BCM43xx_SPROM_SIZE * sizeof(*sprom), |
| 121 | GFP_KERNEL); | 147 | GFP_KERNEL); |
| 122 | if (!sprom) | 148 | if (!sprom) |
| 123 | return -ENOMEM; | 149 | return -ENOMEM; |
| 124 | for (i = 0; i < BCM43xx_SPROM_SIZE; i++) { | 150 | err = hex2sprom(sprom, buf, count); |
| 125 | sprom[i] = buf[i * 2] & 0xFF; | 151 | if (err) |
| 126 | sprom[i] |= ((u16)(buf[i * 2 + 1] & 0xFF)) << 8; | 152 | goto out_kfree; |
| 127 | } | ||
| 128 | bcm43xx_lock_mmio(bcm, flags); | 153 | bcm43xx_lock_mmio(bcm, flags); |
| 129 | assert(bcm->initialized); | 154 | assert(bcm->initialized); |
| 130 | err = bcm43xx_sprom_write(bcm, sprom); | 155 | err = bcm43xx_sprom_write(bcm, sprom); |
| 131 | bcm43xx_unlock_mmio(bcm, flags); | 156 | bcm43xx_unlock_mmio(bcm, flags); |
| 157 | out_kfree: | ||
| 132 | kfree(sprom); | 158 | kfree(sprom); |
| 133 | 159 | ||
| 134 | return err ? err : count; | 160 | return err ? err : count; |
| 135 | 161 | ||
| 136 | } | 162 | } |
| 137 | 163 | ||
| 164 | static DEVICE_ATTR(sprom, 0600, | ||
| 165 | bcm43xx_attr_sprom_show, | ||
| 166 | bcm43xx_attr_sprom_store); | ||
| 167 | |||
| 138 | static ssize_t bcm43xx_attr_interfmode_show(struct device *dev, | 168 | static ssize_t bcm43xx_attr_interfmode_show(struct device *dev, |
| 139 | struct device_attribute *attr, | 169 | struct device_attribute *attr, |
| 140 | char *buf) | 170 | char *buf) |
| 141 | { | 171 | { |
| 142 | struct bcm43xx_private *bcm = devattr_to_bcm(attr, attr_interfmode); | 172 | struct bcm43xx_private *bcm = dev_to_bcm(dev); |
| 143 | unsigned long flags; | 173 | unsigned long flags; |
| 144 | int err; | 174 | int err; |
| 145 | ssize_t count = 0; | 175 | ssize_t count = 0; |
| @@ -175,7 +205,7 @@ static ssize_t bcm43xx_attr_interfmode_store(struct device *dev, | |||
| 175 | struct device_attribute *attr, | 205 | struct device_attribute *attr, |
| 176 | const char *buf, size_t count) | 206 | const char *buf, size_t count) |
| 177 | { | 207 | { |
| 178 | struct bcm43xx_private *bcm = devattr_to_bcm(attr, attr_interfmode); | 208 | struct bcm43xx_private *bcm = dev_to_bcm(dev); |
| 179 | unsigned long flags; | 209 | unsigned long flags; |
| 180 | int err; | 210 | int err; |
| 181 | int mode; | 211 | int mode; |
| @@ -215,11 +245,15 @@ static ssize_t bcm43xx_attr_interfmode_store(struct device *dev, | |||
| 215 | return err ? err : count; | 245 | return err ? err : count; |
| 216 | } | 246 | } |
| 217 | 247 | ||
| 248 | static DEVICE_ATTR(interference, 0644, | ||
| 249 | bcm43xx_attr_interfmode_show, | ||
| 250 | bcm43xx_attr_interfmode_store); | ||
| 251 | |||
| 218 | static ssize_t bcm43xx_attr_preamble_show(struct device *dev, | 252 | static ssize_t bcm43xx_attr_preamble_show(struct device *dev, |
| 219 | struct device_attribute *attr, | 253 | struct device_attribute *attr, |
| 220 | char *buf) | 254 | char *buf) |
| 221 | { | 255 | { |
| 222 | struct bcm43xx_private *bcm = devattr_to_bcm(attr, attr_preamble); | 256 | struct bcm43xx_private *bcm = dev_to_bcm(dev); |
| 223 | unsigned long flags; | 257 | unsigned long flags; |
| 224 | int err; | 258 | int err; |
| 225 | ssize_t count; | 259 | ssize_t count; |
| @@ -245,7 +279,7 @@ static ssize_t bcm43xx_attr_preamble_store(struct device *dev, | |||
| 245 | struct device_attribute *attr, | 279 | struct device_attribute *attr, |
| 246 | const char *buf, size_t count) | 280 | const char *buf, size_t count) |
| 247 | { | 281 | { |
| 248 | struct bcm43xx_private *bcm = devattr_to_bcm(attr, attr_preamble); | 282 | struct bcm43xx_private *bcm = dev_to_bcm(dev); |
| 249 | unsigned long flags; | 283 | unsigned long flags; |
| 250 | int err; | 284 | int err; |
| 251 | int value; | 285 | int value; |
| @@ -267,56 +301,41 @@ static ssize_t bcm43xx_attr_preamble_store(struct device *dev, | |||
| 267 | return err ? err : count; | 301 | return err ? err : count; |
| 268 | } | 302 | } |
| 269 | 303 | ||
| 304 | static DEVICE_ATTR(shortpreamble, 0644, | ||
| 305 | bcm43xx_attr_preamble_show, | ||
| 306 | bcm43xx_attr_preamble_store); | ||
| 307 | |||
| 270 | int bcm43xx_sysfs_register(struct bcm43xx_private *bcm) | 308 | int bcm43xx_sysfs_register(struct bcm43xx_private *bcm) |
| 271 | { | 309 | { |
| 272 | struct device *dev = &bcm->pci_dev->dev; | 310 | struct device *dev = &bcm->pci_dev->dev; |
| 273 | struct bcm43xx_sysfs *sysfs = &bcm->sysfs; | ||
| 274 | int err; | 311 | int err; |
| 275 | 312 | ||
| 276 | assert(bcm->initialized); | 313 | assert(bcm->initialized); |
| 277 | 314 | ||
| 278 | sysfs->attr_sprom.attr.name = "sprom"; | 315 | err = device_create_file(dev, &dev_attr_sprom); |
| 279 | sysfs->attr_sprom.attr.owner = THIS_MODULE; | ||
| 280 | sysfs->attr_sprom.attr.mode = 0600; | ||
| 281 | sysfs->attr_sprom.show = bcm43xx_attr_sprom_show; | ||
| 282 | sysfs->attr_sprom.store = bcm43xx_attr_sprom_store; | ||
| 283 | err = device_create_file(dev, &sysfs->attr_sprom); | ||
| 284 | if (err) | 316 | if (err) |
| 285 | goto out; | 317 | goto out; |
| 286 | 318 | err = device_create_file(dev, &dev_attr_interference); | |
| 287 | sysfs->attr_interfmode.attr.name = "interference"; | ||
| 288 | sysfs->attr_interfmode.attr.owner = THIS_MODULE; | ||
| 289 | sysfs->attr_interfmode.attr.mode = 0600; | ||
| 290 | sysfs->attr_interfmode.show = bcm43xx_attr_interfmode_show; | ||
| 291 | sysfs->attr_interfmode.store = bcm43xx_attr_interfmode_store; | ||
| 292 | err = device_create_file(dev, &sysfs->attr_interfmode); | ||
| 293 | if (err) | 319 | if (err) |
| 294 | goto err_remove_sprom; | 320 | goto err_remove_sprom; |
| 295 | 321 | err = device_create_file(dev, &dev_attr_shortpreamble); | |
| 296 | sysfs->attr_preamble.attr.name = "shortpreamble"; | ||
| 297 | sysfs->attr_preamble.attr.owner = THIS_MODULE; | ||
| 298 | sysfs->attr_preamble.attr.mode = 0600; | ||
| 299 | sysfs->attr_preamble.show = bcm43xx_attr_preamble_show; | ||
| 300 | sysfs->attr_preamble.store = bcm43xx_attr_preamble_store; | ||
| 301 | err = device_create_file(dev, &sysfs->attr_preamble); | ||
| 302 | if (err) | 322 | if (err) |
| 303 | goto err_remove_interfmode; | 323 | goto err_remove_interfmode; |
| 304 | 324 | ||
| 305 | out: | 325 | out: |
| 306 | return err; | 326 | return err; |
| 307 | err_remove_interfmode: | 327 | err_remove_interfmode: |
| 308 | device_remove_file(dev, &sysfs->attr_interfmode); | 328 | device_remove_file(dev, &dev_attr_interference); |
| 309 | err_remove_sprom: | 329 | err_remove_sprom: |
| 310 | device_remove_file(dev, &sysfs->attr_sprom); | 330 | device_remove_file(dev, &dev_attr_sprom); |
| 311 | goto out; | 331 | goto out; |
| 312 | } | 332 | } |
| 313 | 333 | ||
| 314 | void bcm43xx_sysfs_unregister(struct bcm43xx_private *bcm) | 334 | void bcm43xx_sysfs_unregister(struct bcm43xx_private *bcm) |
| 315 | { | 335 | { |
| 316 | struct device *dev = &bcm->pci_dev->dev; | 336 | struct device *dev = &bcm->pci_dev->dev; |
| 317 | struct bcm43xx_sysfs *sysfs = &bcm->sysfs; | ||
| 318 | 337 | ||
| 319 | device_remove_file(dev, &sysfs->attr_preamble); | 338 | device_remove_file(dev, &dev_attr_shortpreamble); |
| 320 | device_remove_file(dev, &sysfs->attr_interfmode); | 339 | device_remove_file(dev, &dev_attr_interference); |
| 321 | device_remove_file(dev, &sysfs->attr_sprom); | 340 | device_remove_file(dev, &dev_attr_sprom); |
| 322 | } | 341 | } |
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.h b/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.h index 57f14514e3e0..cc701df71e2a 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.h +++ b/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.h | |||
| @@ -1,22 +1,6 @@ | |||
| 1 | #ifndef BCM43xx_SYSFS_H_ | 1 | #ifndef BCM43xx_SYSFS_H_ |
| 2 | #define BCM43xx_SYSFS_H_ | 2 | #define BCM43xx_SYSFS_H_ |
| 3 | 3 | ||
| 4 | #include <linux/device.h> | ||
| 5 | |||
| 6 | |||
| 7 | struct bcm43xx_sysfs { | ||
| 8 | struct device_attribute attr_sprom; | ||
| 9 | struct device_attribute attr_interfmode; | ||
| 10 | struct device_attribute attr_preamble; | ||
| 11 | }; | ||
| 12 | |||
| 13 | #define devattr_to_bcm(attr, attr_name) ({ \ | ||
| 14 | struct bcm43xx_sysfs *__s; struct bcm43xx_private *__p; \ | ||
| 15 | __s = container_of((attr), struct bcm43xx_sysfs, attr_name); \ | ||
| 16 | __p = container_of(__s, struct bcm43xx_private, sysfs); \ | ||
| 17 | __p; \ | ||
| 18 | }) | ||
| 19 | |||
| 20 | struct bcm43xx_private; | 4 | struct bcm43xx_private; |
| 21 | 5 | ||
| 22 | int bcm43xx_sysfs_register(struct bcm43xx_private *bcm); | 6 | int bcm43xx_sysfs_register(struct bcm43xx_private *bcm); |
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_wx.c b/drivers/net/wireless/bcm43xx/bcm43xx_wx.c index 3daee828ef4b..3edbb481a0a0 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_wx.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_wx.c | |||
| @@ -962,22 +962,22 @@ static const struct iw_priv_args bcm43xx_priv_wx_args[] = { | |||
| 962 | { | 962 | { |
| 963 | .cmd = PRIV_WX_SET_SHORTPREAMBLE, | 963 | .cmd = PRIV_WX_SET_SHORTPREAMBLE, |
| 964 | .set_args = IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, | 964 | .set_args = IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, |
| 965 | .name = "set_shortpreambl", | 965 | .name = "set_shortpreamb", |
| 966 | }, | 966 | }, |
| 967 | { | 967 | { |
| 968 | .cmd = PRIV_WX_GET_SHORTPREAMBLE, | 968 | .cmd = PRIV_WX_GET_SHORTPREAMBLE, |
| 969 | .get_args = IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | MAX_WX_STRING, | 969 | .get_args = IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | MAX_WX_STRING, |
| 970 | .name = "get_shortpreambl", | 970 | .name = "get_shortpreamb", |
| 971 | }, | 971 | }, |
| 972 | { | 972 | { |
| 973 | .cmd = PRIV_WX_SET_SWENCRYPTION, | 973 | .cmd = PRIV_WX_SET_SWENCRYPTION, |
| 974 | .set_args = IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, | 974 | .set_args = IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, |
| 975 | .name = "set_swencryption", | 975 | .name = "set_swencrypt", |
| 976 | }, | 976 | }, |
| 977 | { | 977 | { |
| 978 | .cmd = PRIV_WX_GET_SWENCRYPTION, | 978 | .cmd = PRIV_WX_GET_SWENCRYPTION, |
| 979 | .get_args = IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | MAX_WX_STRING, | 979 | .get_args = IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | MAX_WX_STRING, |
| 980 | .name = "get_swencryption", | 980 | .name = "get_swencrypt", |
| 981 | }, | 981 | }, |
| 982 | { | 982 | { |
| 983 | .cmd = PRIV_WX_SPROM_WRITE, | 983 | .cmd = PRIV_WX_SPROM_WRITE, |
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/drivers/net/wireless/orinoco.c b/drivers/net/wireless/orinoco.c index 8dfdfbd5966c..06523e2a8471 100644 --- a/drivers/net/wireless/orinoco.c +++ b/drivers/net/wireless/orinoco.c | |||
| @@ -390,7 +390,7 @@ static struct iw_statistics *orinoco_get_wireless_stats(struct net_device *dev) | |||
| 390 | } | 390 | } |
| 391 | } else { | 391 | } else { |
| 392 | struct { | 392 | struct { |
| 393 | __le16 qual, signal, noise; | 393 | __le16 qual, signal, noise, unused; |
| 394 | } __attribute__ ((packed)) cq; | 394 | } __attribute__ ((packed)) cq; |
| 395 | 395 | ||
| 396 | err = HERMES_READ_RECORD(hw, USER_BAP, | 396 | err = HERMES_READ_RECORD(hw, USER_BAP, |
