diff options
| author | Jeff Garzik <jeff@garzik.org> | 2006-04-26 06:21:31 -0400 |
|---|---|---|
| committer | Jeff Garzik <jeff@garzik.org> | 2006-04-26 06:21:31 -0400 |
| commit | 9f1da23b631f92393f58f664348ffc5faeaddeb3 (patch) | |
| tree | 68c7bf9c0f4b11117cf6b3cde5fa5c4f2929088a | |
| parent | 00355cd938bac2a6006efa140352958784431f1f (diff) | |
| parent | 86a0f04387bfa814618bf0c2c8b203899c4fa5d2 (diff) | |
Merge branch 'upstream-fixes' into upstream
| -rw-r--r-- | drivers/net/forcedeth.c | 79 | ||||
| -rw-r--r-- | drivers/net/sky2.c | 52 | ||||
| -rw-r--r-- | drivers/net/sky2.h | 2 | ||||
| -rw-r--r-- | include/linux/netdevice.h | 18 |
4 files changed, 120 insertions, 31 deletions
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/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/include/linux/netdevice.h b/include/linux/netdevice.h index 40ccf8cc4239..01db7b88a2b1 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h | |||
| @@ -829,19 +829,21 @@ static inline void netif_rx_schedule(struct net_device *dev) | |||
| 829 | __netif_rx_schedule(dev); | 829 | __netif_rx_schedule(dev); |
| 830 | } | 830 | } |
| 831 | 831 | ||
| 832 | /* Try to reschedule poll. Called by dev->poll() after netif_rx_complete(). | 832 | |
| 833 | * Do not inline this? | 833 | static inline void __netif_rx_reschedule(struct net_device *dev, int undo) |
| 834 | */ | 834 | { |
| 835 | dev->quota += undo; | ||
| 836 | list_add_tail(&dev->poll_list, &__get_cpu_var(softnet_data).poll_list); | ||
| 837 | __raise_softirq_irqoff(NET_RX_SOFTIRQ); | ||
| 838 | } | ||
| 839 | |||
| 840 | /* Try to reschedule poll. Called by dev->poll() after netif_rx_complete(). */ | ||
| 835 | static inline int netif_rx_reschedule(struct net_device *dev, int undo) | 841 | static inline int netif_rx_reschedule(struct net_device *dev, int undo) |
| 836 | { | 842 | { |
| 837 | if (netif_rx_schedule_prep(dev)) { | 843 | if (netif_rx_schedule_prep(dev)) { |
| 838 | unsigned long flags; | 844 | unsigned long flags; |
| 839 | |||
| 840 | dev->quota += undo; | ||
| 841 | |||
| 842 | local_irq_save(flags); | 845 | local_irq_save(flags); |
| 843 | list_add_tail(&dev->poll_list, &__get_cpu_var(softnet_data).poll_list); | 846 | __netif_rx_reschedule(dev, undo); |
| 844 | __raise_softirq_irqoff(NET_RX_SOFTIRQ); | ||
| 845 | local_irq_restore(flags); | 847 | local_irq_restore(flags); |
| 846 | return 1; | 848 | return 1; |
| 847 | } | 849 | } |
