diff options
author | Andrew Morton <akpm@osdl.org> | 2006-05-19 05:13:21 -0400 |
---|---|---|
committer | Jeff Garzik <jeff@garzik.org> | 2006-05-20 00:13:05 -0400 |
commit | f34ba4e1edd82272dbc192e488c7dc9e56c4ec62 (patch) | |
tree | a8b593a3346954321fdadc77f0c01b02cd0025b1 | |
parent | 2f880b65fdbc2d4915bddc59d75a176329570fdd (diff) |
[PATCH] revert "forcedeth: fix multi irq issues"
Revert ebf34c9b6fcd22338ef764b039b3ac55ed0e297b. Maybe. Due to crashes
at shutdown - see http://bugzilla.kernel.org/show_bug.cgi?id=6568.
Cc: Ayaz Abdulla <aabdulla@nvidia.com>
Cc: Manfred Spraul <manfred@colorfullife.com>
Cc: Jeff Garzik <jeff@garzik.org>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Jeff Garzik <jeff@garzik.org>
-rw-r--r-- | drivers/net/forcedeth.c | 312 |
1 files changed, 84 insertions, 228 deletions
diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c index f7235c9bc421..7e078b4cca7c 100644 --- a/drivers/net/forcedeth.c +++ b/drivers/net/forcedeth.c | |||
@@ -106,7 +106,6 @@ | |||
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 | * 0.53: 19 Mar 2006: Fix init from low power mode and add hw reset. |
109 | * 0.54: 21 Mar 2006: Fix spin locks for multi irqs and cleanup. | ||
110 | * | 109 | * |
111 | * Known bugs: | 110 | * Known bugs: |
112 | * 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. |
@@ -118,7 +117,7 @@ | |||
118 | * 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 |
119 | * superfluous timer interrupts from the nic. | 118 | * superfluous timer interrupts from the nic. |
120 | */ | 119 | */ |
121 | #define FORCEDETH_VERSION "0.54" | 120 | #define FORCEDETH_VERSION "0.53" |
122 | #define DRV_NAME "forcedeth" | 121 | #define DRV_NAME "forcedeth" |
123 | 122 | ||
124 | #include <linux/module.h> | 123 | #include <linux/module.h> |
@@ -711,72 +710,6 @@ static void setup_hw_rings(struct net_device *dev, int rxtx_flags) | |||
711 | } | 710 | } |
712 | } | 711 | } |
713 | 712 | ||
714 | static int using_multi_irqs(struct net_device *dev) | ||
715 | { | ||
716 | struct fe_priv *np = get_nvpriv(dev); | ||
717 | |||
718 | if (!(np->msi_flags & NV_MSI_X_ENABLED) || | ||
719 | ((np->msi_flags & NV_MSI_X_ENABLED) && | ||
720 | ((np->msi_flags & NV_MSI_X_VECTORS_MASK) == 0x1))) | ||
721 | return 0; | ||
722 | else | ||
723 | return 1; | ||
724 | } | ||
725 | |||
726 | static void nv_enable_irq(struct net_device *dev) | ||
727 | { | ||
728 | struct fe_priv *np = get_nvpriv(dev); | ||
729 | |||
730 | if (!using_multi_irqs(dev)) { | ||
731 | if (np->msi_flags & NV_MSI_X_ENABLED) | ||
732 | enable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_ALL].vector); | ||
733 | else | ||
734 | enable_irq(dev->irq); | ||
735 | } else { | ||
736 | enable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_RX].vector); | ||
737 | enable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_TX].vector); | ||
738 | enable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_OTHER].vector); | ||
739 | } | ||
740 | } | ||
741 | |||
742 | static void nv_disable_irq(struct net_device *dev) | ||
743 | { | ||
744 | struct fe_priv *np = get_nvpriv(dev); | ||
745 | |||
746 | if (!using_multi_irqs(dev)) { | ||
747 | if (np->msi_flags & NV_MSI_X_ENABLED) | ||
748 | disable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_ALL].vector); | ||
749 | else | ||
750 | disable_irq(dev->irq); | ||
751 | } else { | ||
752 | disable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_RX].vector); | ||
753 | disable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_TX].vector); | ||
754 | disable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_OTHER].vector); | ||
755 | } | ||
756 | } | ||
757 | |||
758 | /* In MSIX mode, a write to irqmask behaves as XOR */ | ||
759 | static void nv_enable_hw_interrupts(struct net_device *dev, u32 mask) | ||
760 | { | ||
761 | u8 __iomem *base = get_hwbase(dev); | ||
762 | |||
763 | writel(mask, base + NvRegIrqMask); | ||
764 | } | ||
765 | |||
766 | static void nv_disable_hw_interrupts(struct net_device *dev, u32 mask) | ||
767 | { | ||
768 | struct fe_priv *np = get_nvpriv(dev); | ||
769 | u8 __iomem *base = get_hwbase(dev); | ||
770 | |||
771 | if (np->msi_flags & NV_MSI_X_ENABLED) { | ||
772 | writel(mask, base + NvRegIrqMask); | ||
773 | } else { | ||
774 | if (np->msi_flags & NV_MSI_ENABLED) | ||
775 | writel(0, base + NvRegMSIIrqMask); | ||
776 | writel(0, base + NvRegIrqMask); | ||
777 | } | ||
778 | } | ||
779 | |||
780 | #define MII_READ (-1) | 713 | #define MII_READ (-1) |
781 | /* mii_rw: read/write a register on the PHY. | 714 | /* mii_rw: read/write a register on the PHY. |
782 | * | 715 | * |
@@ -1086,25 +1019,24 @@ static void nv_do_rx_refill(unsigned long data) | |||
1086 | struct net_device *dev = (struct net_device *) data; | 1019 | struct net_device *dev = (struct net_device *) data; |
1087 | struct fe_priv *np = netdev_priv(dev); | 1020 | struct fe_priv *np = netdev_priv(dev); |
1088 | 1021 | ||
1089 | if (!using_multi_irqs(dev)) { | 1022 | |
1090 | if (np->msi_flags & NV_MSI_X_ENABLED) | 1023 | if (!(np->msi_flags & NV_MSI_X_ENABLED) || |
1091 | disable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_ALL].vector); | 1024 | ((np->msi_flags & NV_MSI_X_ENABLED) && |
1092 | else | 1025 | ((np->msi_flags & NV_MSI_X_VECTORS_MASK) == 0x1))) { |
1093 | disable_irq(dev->irq); | 1026 | disable_irq(dev->irq); |
1094 | } else { | 1027 | } else { |
1095 | disable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_RX].vector); | 1028 | disable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_RX].vector); |
1096 | } | 1029 | } |
1097 | if (nv_alloc_rx(dev)) { | 1030 | if (nv_alloc_rx(dev)) { |
1098 | spin_lock_irq(&np->lock); | 1031 | spin_lock(&np->lock); |
1099 | if (!np->in_shutdown) | 1032 | if (!np->in_shutdown) |
1100 | mod_timer(&np->oom_kick, jiffies + OOM_REFILL); | 1033 | mod_timer(&np->oom_kick, jiffies + OOM_REFILL); |
1101 | spin_unlock_irq(&np->lock); | 1034 | spin_unlock(&np->lock); |
1102 | } | 1035 | } |
1103 | if (!using_multi_irqs(dev)) { | 1036 | if (!(np->msi_flags & NV_MSI_X_ENABLED) || |
1104 | if (np->msi_flags & NV_MSI_X_ENABLED) | 1037 | ((np->msi_flags & NV_MSI_X_ENABLED) && |
1105 | enable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_ALL].vector); | 1038 | ((np->msi_flags & NV_MSI_X_VECTORS_MASK) == 0x1))) { |
1106 | else | 1039 | enable_irq(dev->irq); |
1107 | enable_irq(dev->irq); | ||
1108 | } else { | 1040 | } else { |
1109 | enable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_RX].vector); | 1041 | enable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_RX].vector); |
1110 | } | 1042 | } |
@@ -1736,7 +1668,15 @@ static int nv_change_mtu(struct net_device *dev, int new_mtu) | |||
1736 | * guessed, there is probably a simpler approach. | 1668 | * guessed, there is probably a simpler approach. |
1737 | * Changing the MTU is a rare event, it shouldn't matter. | 1669 | * Changing the MTU is a rare event, it shouldn't matter. |
1738 | */ | 1670 | */ |
1739 | nv_disable_irq(dev); | 1671 | if (!(np->msi_flags & NV_MSI_X_ENABLED) || |
1672 | ((np->msi_flags & NV_MSI_X_ENABLED) && | ||
1673 | ((np->msi_flags & NV_MSI_X_VECTORS_MASK) == 0x1))) { | ||
1674 | disable_irq(dev->irq); | ||
1675 | } else { | ||
1676 | disable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_RX].vector); | ||
1677 | disable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_TX].vector); | ||
1678 | disable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_OTHER].vector); | ||
1679 | } | ||
1740 | spin_lock_bh(&dev->xmit_lock); | 1680 | spin_lock_bh(&dev->xmit_lock); |
1741 | spin_lock(&np->lock); | 1681 | spin_lock(&np->lock); |
1742 | /* stop engines */ | 1682 | /* stop engines */ |
@@ -1769,7 +1709,15 @@ static int nv_change_mtu(struct net_device *dev, int new_mtu) | |||
1769 | nv_start_tx(dev); | 1709 | nv_start_tx(dev); |
1770 | spin_unlock(&np->lock); | 1710 | spin_unlock(&np->lock); |
1771 | spin_unlock_bh(&dev->xmit_lock); | 1711 | spin_unlock_bh(&dev->xmit_lock); |
1772 | nv_enable_irq(dev); | 1712 | if (!(np->msi_flags & NV_MSI_X_ENABLED) || |
1713 | ((np->msi_flags & NV_MSI_X_ENABLED) && | ||
1714 | ((np->msi_flags & NV_MSI_X_VECTORS_MASK) == 0x1))) { | ||
1715 | enable_irq(dev->irq); | ||
1716 | } else { | ||
1717 | enable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_RX].vector); | ||
1718 | enable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_TX].vector); | ||
1719 | enable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_OTHER].vector); | ||
1720 | } | ||
1773 | } | 1721 | } |
1774 | return 0; | 1722 | return 0; |
1775 | } | 1723 | } |
@@ -2160,16 +2108,16 @@ static irqreturn_t nv_nic_irq_tx(int foo, void *data, struct pt_regs *regs) | |||
2160 | if (!(events & np->irqmask)) | 2108 | if (!(events & np->irqmask)) |
2161 | break; | 2109 | break; |
2162 | 2110 | ||
2163 | spin_lock_irq(&np->lock); | 2111 | spin_lock(&np->lock); |
2164 | nv_tx_done(dev); | 2112 | nv_tx_done(dev); |
2165 | spin_unlock_irq(&np->lock); | 2113 | spin_unlock(&np->lock); |
2166 | 2114 | ||
2167 | if (events & (NVREG_IRQ_TX_ERR)) { | 2115 | if (events & (NVREG_IRQ_TX_ERR)) { |
2168 | dprintk(KERN_DEBUG "%s: received irq with events 0x%x. Probably TX fail.\n", | 2116 | dprintk(KERN_DEBUG "%s: received irq with events 0x%x. Probably TX fail.\n", |
2169 | dev->name, events); | 2117 | dev->name, events); |
2170 | } | 2118 | } |
2171 | if (i > max_interrupt_work) { | 2119 | if (i > max_interrupt_work) { |
2172 | spin_lock_irq(&np->lock); | 2120 | spin_lock(&np->lock); |
2173 | /* disable interrupts on the nic */ | 2121 | /* disable interrupts on the nic */ |
2174 | writel(NVREG_IRQ_TX_ALL, base + NvRegIrqMask); | 2122 | writel(NVREG_IRQ_TX_ALL, base + NvRegIrqMask); |
2175 | pci_push(base); | 2123 | pci_push(base); |
@@ -2179,7 +2127,7 @@ static irqreturn_t nv_nic_irq_tx(int foo, void *data, struct pt_regs *regs) | |||
2179 | mod_timer(&np->nic_poll, jiffies + POLL_WAIT); | 2127 | mod_timer(&np->nic_poll, jiffies + POLL_WAIT); |
2180 | } | 2128 | } |
2181 | printk(KERN_DEBUG "%s: too many iterations (%d) in nv_nic_irq_tx.\n", dev->name, i); | 2129 | printk(KERN_DEBUG "%s: too many iterations (%d) in nv_nic_irq_tx.\n", dev->name, i); |
2182 | spin_unlock_irq(&np->lock); | 2130 | spin_unlock(&np->lock); |
2183 | break; | 2131 | break; |
2184 | } | 2132 | } |
2185 | 2133 | ||
@@ -2209,14 +2157,14 @@ static irqreturn_t nv_nic_irq_rx(int foo, void *data, struct pt_regs *regs) | |||
2209 | 2157 | ||
2210 | nv_rx_process(dev); | 2158 | nv_rx_process(dev); |
2211 | if (nv_alloc_rx(dev)) { | 2159 | if (nv_alloc_rx(dev)) { |
2212 | spin_lock_irq(&np->lock); | 2160 | spin_lock(&np->lock); |
2213 | if (!np->in_shutdown) | 2161 | if (!np->in_shutdown) |
2214 | mod_timer(&np->oom_kick, jiffies + OOM_REFILL); | 2162 | mod_timer(&np->oom_kick, jiffies + OOM_REFILL); |
2215 | spin_unlock_irq(&np->lock); | 2163 | spin_unlock(&np->lock); |
2216 | } | 2164 | } |
2217 | 2165 | ||
2218 | if (i > max_interrupt_work) { | 2166 | if (i > max_interrupt_work) { |
2219 | spin_lock_irq(&np->lock); | 2167 | spin_lock(&np->lock); |
2220 | /* disable interrupts on the nic */ | 2168 | /* disable interrupts on the nic */ |
2221 | writel(NVREG_IRQ_RX_ALL, base + NvRegIrqMask); | 2169 | writel(NVREG_IRQ_RX_ALL, base + NvRegIrqMask); |
2222 | pci_push(base); | 2170 | pci_push(base); |
@@ -2226,7 +2174,7 @@ static irqreturn_t nv_nic_irq_rx(int foo, void *data, struct pt_regs *regs) | |||
2226 | mod_timer(&np->nic_poll, jiffies + POLL_WAIT); | 2174 | mod_timer(&np->nic_poll, jiffies + POLL_WAIT); |
2227 | } | 2175 | } |
2228 | printk(KERN_DEBUG "%s: too many iterations (%d) in nv_nic_irq_rx.\n", dev->name, i); | 2176 | printk(KERN_DEBUG "%s: too many iterations (%d) in nv_nic_irq_rx.\n", dev->name, i); |
2229 | spin_unlock_irq(&np->lock); | 2177 | spin_unlock(&np->lock); |
2230 | break; | 2178 | break; |
2231 | } | 2179 | } |
2232 | 2180 | ||
@@ -2255,14 +2203,14 @@ static irqreturn_t nv_nic_irq_other(int foo, void *data, struct pt_regs *regs) | |||
2255 | break; | 2203 | break; |
2256 | 2204 | ||
2257 | if (events & NVREG_IRQ_LINK) { | 2205 | if (events & NVREG_IRQ_LINK) { |
2258 | spin_lock_irq(&np->lock); | 2206 | spin_lock(&np->lock); |
2259 | nv_link_irq(dev); | 2207 | nv_link_irq(dev); |
2260 | spin_unlock_irq(&np->lock); | 2208 | spin_unlock(&np->lock); |
2261 | } | 2209 | } |
2262 | if (np->need_linktimer && time_after(jiffies, np->link_timeout)) { | 2210 | if (np->need_linktimer && time_after(jiffies, np->link_timeout)) { |
2263 | spin_lock_irq(&np->lock); | 2211 | spin_lock(&np->lock); |
2264 | nv_linkchange(dev); | 2212 | nv_linkchange(dev); |
2265 | spin_unlock_irq(&np->lock); | 2213 | spin_unlock(&np->lock); |
2266 | np->link_timeout = jiffies + LINK_TIMEOUT; | 2214 | np->link_timeout = jiffies + LINK_TIMEOUT; |
2267 | } | 2215 | } |
2268 | if (events & (NVREG_IRQ_UNKNOWN)) { | 2216 | if (events & (NVREG_IRQ_UNKNOWN)) { |
@@ -2270,7 +2218,7 @@ static irqreturn_t nv_nic_irq_other(int foo, void *data, struct pt_regs *regs) | |||
2270 | dev->name, events); | 2218 | dev->name, events); |
2271 | } | 2219 | } |
2272 | if (i > max_interrupt_work) { | 2220 | if (i > max_interrupt_work) { |
2273 | spin_lock_irq(&np->lock); | 2221 | spin_lock(&np->lock); |
2274 | /* disable interrupts on the nic */ | 2222 | /* disable interrupts on the nic */ |
2275 | writel(NVREG_IRQ_OTHER, base + NvRegIrqMask); | 2223 | writel(NVREG_IRQ_OTHER, base + NvRegIrqMask); |
2276 | pci_push(base); | 2224 | pci_push(base); |
@@ -2280,7 +2228,7 @@ static irqreturn_t nv_nic_irq_other(int foo, void *data, struct pt_regs *regs) | |||
2280 | mod_timer(&np->nic_poll, jiffies + POLL_WAIT); | 2228 | mod_timer(&np->nic_poll, jiffies + POLL_WAIT); |
2281 | } | 2229 | } |
2282 | printk(KERN_DEBUG "%s: too many iterations (%d) in nv_nic_irq_other.\n", dev->name, i); | 2230 | printk(KERN_DEBUG "%s: too many iterations (%d) in nv_nic_irq_other.\n", dev->name, i); |
2283 | spin_unlock_irq(&np->lock); | 2231 | spin_unlock(&np->lock); |
2284 | break; | 2232 | break; |
2285 | } | 2233 | } |
2286 | 2234 | ||
@@ -2303,11 +2251,10 @@ static void nv_do_nic_poll(unsigned long data) | |||
2303 | * nv_nic_irq because that may decide to do otherwise | 2251 | * nv_nic_irq because that may decide to do otherwise |
2304 | */ | 2252 | */ |
2305 | 2253 | ||
2306 | if (!using_multi_irqs(dev)) { | 2254 | if (!(np->msi_flags & NV_MSI_X_ENABLED) || |
2307 | if (np->msi_flags & NV_MSI_X_ENABLED) | 2255 | ((np->msi_flags & NV_MSI_X_ENABLED) && |
2308 | disable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_ALL].vector); | 2256 | ((np->msi_flags & NV_MSI_X_VECTORS_MASK) == 0x1))) { |
2309 | else | 2257 | disable_irq(dev->irq); |
2310 | disable_irq(dev->irq); | ||
2311 | mask = np->irqmask; | 2258 | mask = np->irqmask; |
2312 | } else { | 2259 | } else { |
2313 | if (np->nic_poll_irq & NVREG_IRQ_RX_ALL) { | 2260 | if (np->nic_poll_irq & NVREG_IRQ_RX_ALL) { |
@@ -2330,12 +2277,11 @@ static void nv_do_nic_poll(unsigned long data) | |||
2330 | writel(mask, base + NvRegIrqMask); | 2277 | writel(mask, base + NvRegIrqMask); |
2331 | pci_push(base); | 2278 | pci_push(base); |
2332 | 2279 | ||
2333 | if (!using_multi_irqs(dev)) { | 2280 | if (!(np->msi_flags & NV_MSI_X_ENABLED) || |
2281 | ((np->msi_flags & NV_MSI_X_ENABLED) && | ||
2282 | ((np->msi_flags & NV_MSI_X_VECTORS_MASK) == 0x1))) { | ||
2334 | nv_nic_irq((int) 0, (void *) data, (struct pt_regs *) NULL); | 2283 | nv_nic_irq((int) 0, (void *) data, (struct pt_regs *) NULL); |
2335 | if (np->msi_flags & NV_MSI_X_ENABLED) | 2284 | enable_irq(dev->irq); |
2336 | enable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_ALL].vector); | ||
2337 | else | ||
2338 | enable_irq(dev->irq); | ||
2339 | } else { | 2285 | } else { |
2340 | if (np->nic_poll_irq & NVREG_IRQ_RX_ALL) { | 2286 | if (np->nic_poll_irq & NVREG_IRQ_RX_ALL) { |
2341 | nv_nic_irq_rx((int) 0, (void *) data, (struct pt_regs *) NULL); | 2287 | nv_nic_irq_rx((int) 0, (void *) data, (struct pt_regs *) NULL); |
@@ -2682,113 +2628,6 @@ static void set_msix_vector_map(struct net_device *dev, u32 vector, u32 irqmask) | |||
2682 | writel(readl(base + NvRegMSIXMap1) | msixmap, base + NvRegMSIXMap1); | 2628 | writel(readl(base + NvRegMSIXMap1) | msixmap, base + NvRegMSIXMap1); |
2683 | } | 2629 | } |
2684 | 2630 | ||
2685 | static int nv_request_irq(struct net_device *dev) | ||
2686 | { | ||
2687 | struct fe_priv *np = get_nvpriv(dev); | ||
2688 | u8 __iomem *base = get_hwbase(dev); | ||
2689 | int ret = 1; | ||
2690 | int i; | ||
2691 | |||
2692 | if (np->msi_flags & NV_MSI_X_CAPABLE) { | ||
2693 | for (i = 0; i < (np->msi_flags & NV_MSI_X_VECTORS_MASK); i++) { | ||
2694 | np->msi_x_entry[i].entry = i; | ||
2695 | } | ||
2696 | if ((ret = pci_enable_msix(np->pci_dev, np->msi_x_entry, (np->msi_flags & NV_MSI_X_VECTORS_MASK))) == 0) { | ||
2697 | np->msi_flags |= NV_MSI_X_ENABLED; | ||
2698 | if (optimization_mode == NV_OPTIMIZATION_MODE_THROUGHPUT) { | ||
2699 | /* Request irq for rx handling */ | ||
2700 | if (request_irq(np->msi_x_entry[NV_MSI_X_VECTOR_RX].vector, &nv_nic_irq_rx, SA_SHIRQ, dev->name, dev) != 0) { | ||
2701 | printk(KERN_INFO "forcedeth: request_irq failed for rx %d\n", ret); | ||
2702 | pci_disable_msix(np->pci_dev); | ||
2703 | np->msi_flags &= ~NV_MSI_X_ENABLED; | ||
2704 | goto out_err; | ||
2705 | } | ||
2706 | /* Request irq for tx handling */ | ||
2707 | if (request_irq(np->msi_x_entry[NV_MSI_X_VECTOR_TX].vector, &nv_nic_irq_tx, SA_SHIRQ, dev->name, dev) != 0) { | ||
2708 | printk(KERN_INFO "forcedeth: request_irq failed for tx %d\n", ret); | ||
2709 | pci_disable_msix(np->pci_dev); | ||
2710 | np->msi_flags &= ~NV_MSI_X_ENABLED; | ||
2711 | goto out_free_rx; | ||
2712 | } | ||
2713 | /* Request irq for link and timer handling */ | ||
2714 | if (request_irq(np->msi_x_entry[NV_MSI_X_VECTOR_OTHER].vector, &nv_nic_irq_other, SA_SHIRQ, dev->name, dev) != 0) { | ||
2715 | printk(KERN_INFO "forcedeth: request_irq failed for link %d\n", ret); | ||
2716 | pci_disable_msix(np->pci_dev); | ||
2717 | np->msi_flags &= ~NV_MSI_X_ENABLED; | ||
2718 | goto out_free_tx; | ||
2719 | } | ||
2720 | /* map interrupts to their respective vector */ | ||
2721 | writel(0, base + NvRegMSIXMap0); | ||
2722 | writel(0, base + NvRegMSIXMap1); | ||
2723 | set_msix_vector_map(dev, NV_MSI_X_VECTOR_RX, NVREG_IRQ_RX_ALL); | ||
2724 | set_msix_vector_map(dev, NV_MSI_X_VECTOR_TX, NVREG_IRQ_TX_ALL); | ||
2725 | set_msix_vector_map(dev, NV_MSI_X_VECTOR_OTHER, NVREG_IRQ_OTHER); | ||
2726 | } else { | ||
2727 | /* Request irq for all interrupts */ | ||
2728 | if (request_irq(np->msi_x_entry[NV_MSI_X_VECTOR_ALL].vector, &nv_nic_irq, SA_SHIRQ, dev->name, dev) != 0) { | ||
2729 | printk(KERN_INFO "forcedeth: request_irq failed %d\n", ret); | ||
2730 | pci_disable_msix(np->pci_dev); | ||
2731 | np->msi_flags &= ~NV_MSI_X_ENABLED; | ||
2732 | goto out_err; | ||
2733 | } | ||
2734 | |||
2735 | /* map interrupts to vector 0 */ | ||
2736 | writel(0, base + NvRegMSIXMap0); | ||
2737 | writel(0, base + NvRegMSIXMap1); | ||
2738 | } | ||
2739 | } | ||
2740 | } | ||
2741 | if (ret != 0 && np->msi_flags & NV_MSI_CAPABLE) { | ||
2742 | if ((ret = pci_enable_msi(np->pci_dev)) == 0) { | ||
2743 | np->msi_flags |= NV_MSI_ENABLED; | ||
2744 | if (request_irq(np->pci_dev->irq, &nv_nic_irq, SA_SHIRQ, dev->name, dev) != 0) { | ||
2745 | printk(KERN_INFO "forcedeth: request_irq failed %d\n", ret); | ||
2746 | pci_disable_msi(np->pci_dev); | ||
2747 | np->msi_flags &= ~NV_MSI_ENABLED; | ||
2748 | goto out_err; | ||
2749 | } | ||
2750 | |||
2751 | /* map interrupts to vector 0 */ | ||
2752 | writel(0, base + NvRegMSIMap0); | ||
2753 | writel(0, base + NvRegMSIMap1); | ||
2754 | /* enable msi vector 0 */ | ||
2755 | writel(NVREG_MSI_VECTOR_0_ENABLED, base + NvRegMSIIrqMask); | ||
2756 | } | ||
2757 | } | ||
2758 | if (ret != 0) { | ||
2759 | if (request_irq(np->pci_dev->irq, &nv_nic_irq, SA_SHIRQ, dev->name, dev) != 0) | ||
2760 | goto out_err; | ||
2761 | } | ||
2762 | |||
2763 | return 0; | ||
2764 | out_free_tx: | ||
2765 | free_irq(np->msi_x_entry[NV_MSI_X_VECTOR_TX].vector, dev); | ||
2766 | out_free_rx: | ||
2767 | free_irq(np->msi_x_entry[NV_MSI_X_VECTOR_RX].vector, dev); | ||
2768 | out_err: | ||
2769 | return 1; | ||
2770 | } | ||
2771 | |||
2772 | static void nv_free_irq(struct net_device *dev) | ||
2773 | { | ||
2774 | struct fe_priv *np = get_nvpriv(dev); | ||
2775 | int i; | ||
2776 | |||
2777 | if (np->msi_flags & NV_MSI_X_ENABLED) { | ||
2778 | for (i = 0; i < (np->msi_flags & NV_MSI_X_VECTORS_MASK); i++) { | ||
2779 | free_irq(np->msi_x_entry[i].vector, dev); | ||
2780 | } | ||
2781 | pci_disable_msix(np->pci_dev); | ||
2782 | np->msi_flags &= ~NV_MSI_X_ENABLED; | ||
2783 | } else { | ||
2784 | free_irq(np->pci_dev->irq, dev); | ||
2785 | if (np->msi_flags & NV_MSI_ENABLED) { | ||
2786 | pci_disable_msi(np->pci_dev); | ||
2787 | np->msi_flags &= ~NV_MSI_ENABLED; | ||
2788 | } | ||
2789 | } | ||
2790 | } | ||
2791 | |||
2792 | static int nv_open(struct net_device *dev) | 2631 | static int nv_open(struct net_device *dev) |
2793 | { | 2632 | { |
2794 | struct fe_priv *np = netdev_priv(dev); | 2633 | struct fe_priv *np = netdev_priv(dev); |
@@ -2881,16 +2720,12 @@ static int nv_open(struct net_device *dev) | |||
2881 | udelay(10); | 2720 | udelay(10); |
2882 | writel(readl(base + NvRegPowerState) | NVREG_POWERSTATE_VALID, base + NvRegPowerState); | 2721 | writel(readl(base + NvRegPowerState) | NVREG_POWERSTATE_VALID, base + NvRegPowerState); |
2883 | 2722 | ||
2884 | nv_disable_hw_interrupts(dev, np->irqmask); | 2723 | writel(0, base + NvRegIrqMask); |
2885 | pci_push(base); | 2724 | pci_push(base); |
2886 | writel(NVREG_MIISTAT_MASK2, base + NvRegMIIStatus); | 2725 | writel(NVREG_MIISTAT_MASK2, base + NvRegMIIStatus); |
2887 | writel(NVREG_IRQSTAT_MASK, base + NvRegIrqStatus); | 2726 | writel(NVREG_IRQSTAT_MASK, base + NvRegIrqStatus); |
2888 | pci_push(base); | 2727 | pci_push(base); |
2889 | 2728 | ||
2890 | if (nv_request_irq(dev)) { | ||
2891 | goto out_drain; | ||
2892 | } | ||
2893 | |||
2894 | if (np->msi_flags & NV_MSI_X_CAPABLE) { | 2729 | if (np->msi_flags & NV_MSI_X_CAPABLE) { |
2895 | for (i = 0; i < (np->msi_flags & NV_MSI_X_VECTORS_MASK); i++) { | 2730 | for (i = 0; i < (np->msi_flags & NV_MSI_X_VECTORS_MASK); i++) { |
2896 | np->msi_x_entry[i].entry = i; | 2731 | np->msi_x_entry[i].entry = i; |
@@ -2964,7 +2799,7 @@ static int nv_open(struct net_device *dev) | |||
2964 | } | 2799 | } |
2965 | 2800 | ||
2966 | /* ask for interrupts */ | 2801 | /* ask for interrupts */ |
2967 | nv_enable_hw_interrupts(dev, np->irqmask); | 2802 | writel(np->irqmask, base + NvRegIrqMask); |
2968 | 2803 | ||
2969 | spin_lock_irq(&np->lock); | 2804 | spin_lock_irq(&np->lock); |
2970 | writel(NVREG_MCASTADDRA_FORCE, base + NvRegMulticastAddrA); | 2805 | writel(NVREG_MCASTADDRA_FORCE, base + NvRegMulticastAddrA); |
@@ -3008,6 +2843,7 @@ static int nv_close(struct net_device *dev) | |||
3008 | { | 2843 | { |
3009 | struct fe_priv *np = netdev_priv(dev); | 2844 | struct fe_priv *np = netdev_priv(dev); |
3010 | u8 __iomem *base; | 2845 | u8 __iomem *base; |
2846 | int i; | ||
3011 | 2847 | ||
3012 | spin_lock_irq(&np->lock); | 2848 | spin_lock_irq(&np->lock); |
3013 | np->in_shutdown = 1; | 2849 | np->in_shutdown = 1; |
@@ -3025,13 +2861,31 @@ static int nv_close(struct net_device *dev) | |||
3025 | 2861 | ||
3026 | /* disable interrupts on the nic or we will lock up */ | 2862 | /* disable interrupts on the nic or we will lock up */ |
3027 | base = get_hwbase(dev); | 2863 | base = get_hwbase(dev); |
3028 | nv_disable_hw_interrupts(dev, np->irqmask); | 2864 | if (np->msi_flags & NV_MSI_X_ENABLED) { |
2865 | writel(np->irqmask, base + NvRegIrqMask); | ||
2866 | } else { | ||
2867 | if (np->msi_flags & NV_MSI_ENABLED) | ||
2868 | writel(0, base + NvRegMSIIrqMask); | ||
2869 | writel(0, base + NvRegIrqMask); | ||
2870 | } | ||
3029 | pci_push(base); | 2871 | pci_push(base); |
3030 | dprintk(KERN_INFO "%s: Irqmask is zero again\n", dev->name); | 2872 | dprintk(KERN_INFO "%s: Irqmask is zero again\n", dev->name); |
3031 | 2873 | ||
3032 | spin_unlock_irq(&np->lock); | 2874 | spin_unlock_irq(&np->lock); |
3033 | 2875 | ||
3034 | nv_free_irq(dev); | 2876 | if (np->msi_flags & NV_MSI_X_ENABLED) { |
2877 | for (i = 0; i < (np->msi_flags & NV_MSI_X_VECTORS_MASK); i++) { | ||
2878 | free_irq(np->msi_x_entry[i].vector, dev); | ||
2879 | } | ||
2880 | pci_disable_msix(np->pci_dev); | ||
2881 | np->msi_flags &= ~NV_MSI_X_ENABLED; | ||
2882 | } else { | ||
2883 | free_irq(np->pci_dev->irq, dev); | ||
2884 | if (np->msi_flags & NV_MSI_ENABLED) { | ||
2885 | pci_disable_msi(np->pci_dev); | ||
2886 | np->msi_flags &= ~NV_MSI_ENABLED; | ||
2887 | } | ||
2888 | } | ||
3035 | 2889 | ||
3036 | drain_ring(dev); | 2890 | drain_ring(dev); |
3037 | 2891 | ||
@@ -3120,18 +2974,20 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i | |||
3120 | if (id->driver_data & DEV_HAS_HIGH_DMA) { | 2974 | if (id->driver_data & DEV_HAS_HIGH_DMA) { |
3121 | /* packet format 3: supports 40-bit addressing */ | 2975 | /* packet format 3: supports 40-bit addressing */ |
3122 | np->desc_ver = DESC_VER_3; | 2976 | np->desc_ver = DESC_VER_3; |
3123 | np->txrxctl_bits = NVREG_TXRXCTL_DESC_3; | ||
3124 | if (pci_set_dma_mask(pci_dev, DMA_39BIT_MASK)) { | 2977 | if (pci_set_dma_mask(pci_dev, DMA_39BIT_MASK)) { |
3125 | printk(KERN_INFO "forcedeth: 64-bit DMA failed, using 32-bit addressing for device %s.\n", | 2978 | printk(KERN_INFO "forcedeth: 64-bit DMA failed, using 32-bit addressing for device %s.\n", |
3126 | pci_name(pci_dev)); | 2979 | pci_name(pci_dev)); |
3127 | } else { | 2980 | } else { |
3128 | dev->features |= NETIF_F_HIGHDMA; | 2981 | if (pci_set_consistent_dma_mask(pci_dev, 0x0000007fffffffffULL)) { |
3129 | printk(KERN_INFO "forcedeth: using HIGHDMA\n"); | 2982 | printk(KERN_INFO "forcedeth: 64-bit DMA (consistent) failed for device %s.\n", |
3130 | } | 2983 | pci_name(pci_dev)); |
3131 | if (pci_set_consistent_dma_mask(pci_dev, 0x0000007fffffffffULL)) { | 2984 | goto out_relreg; |
3132 | printk(KERN_INFO "forcedeth: 64-bit DMA (consistent) failed for device %s.\n", | 2985 | } else { |
3133 | pci_name(pci_dev)); | 2986 | dev->features |= NETIF_F_HIGHDMA; |
2987 | printk(KERN_INFO "forcedeth: using HIGHDMA\n"); | ||
2988 | } | ||
3134 | } | 2989 | } |
2990 | np->txrxctl_bits = NVREG_TXRXCTL_DESC_3; | ||
3135 | } else if (id->driver_data & DEV_HAS_LARGEDESC) { | 2991 | } else if (id->driver_data & DEV_HAS_LARGEDESC) { |
3136 | /* packet format 2: supports jumbo frames */ | 2992 | /* packet format 2: supports jumbo frames */ |
3137 | np->desc_ver = DESC_VER_2; | 2993 | np->desc_ver = DESC_VER_2; |