diff options
Diffstat (limited to 'drivers/net/natsemi.c')
| -rw-r--r-- | drivers/net/natsemi.c | 58 |
1 files changed, 31 insertions, 27 deletions
diff --git a/drivers/net/natsemi.c b/drivers/net/natsemi.c index c6172a77a6d7..349b96a3ec4c 100644 --- a/drivers/net/natsemi.c +++ b/drivers/net/natsemi.c | |||
| @@ -1712,7 +1712,7 @@ static void init_registers(struct net_device *dev) | |||
| 1712 | 1712 | ||
| 1713 | /* Enable interrupts by setting the interrupt mask. */ | 1713 | /* Enable interrupts by setting the interrupt mask. */ |
| 1714 | writel(DEFAULT_INTR, ioaddr + IntrMask); | 1714 | writel(DEFAULT_INTR, ioaddr + IntrMask); |
| 1715 | writel(1, ioaddr + IntrEnable); | 1715 | natsemi_irq_enable(dev); |
| 1716 | 1716 | ||
| 1717 | writel(RxOn | TxOn, ioaddr + ChipCmd); | 1717 | writel(RxOn | TxOn, ioaddr + ChipCmd); |
| 1718 | writel(StatsClear, ioaddr + StatsCtrl); /* Clear Stats */ | 1718 | writel(StatsClear, ioaddr + StatsCtrl); /* Clear Stats */ |
| @@ -2119,28 +2119,35 @@ static irqreturn_t intr_handler(int irq, void *dev_instance) | |||
| 2119 | struct netdev_private *np = netdev_priv(dev); | 2119 | struct netdev_private *np = netdev_priv(dev); |
| 2120 | void __iomem * ioaddr = ns_ioaddr(dev); | 2120 | void __iomem * ioaddr = ns_ioaddr(dev); |
| 2121 | 2121 | ||
| 2122 | if (np->hands_off) | 2122 | /* Reading IntrStatus automatically acknowledges so don't do |
| 2123 | * that while interrupts are disabled, (for example, while a | ||
| 2124 | * poll is scheduled). */ | ||
| 2125 | if (np->hands_off || !readl(ioaddr + IntrEnable)) | ||
| 2123 | return IRQ_NONE; | 2126 | return IRQ_NONE; |
| 2124 | 2127 | ||
| 2125 | /* Reading automatically acknowledges. */ | ||
| 2126 | np->intr_status = readl(ioaddr + IntrStatus); | 2128 | np->intr_status = readl(ioaddr + IntrStatus); |
| 2127 | 2129 | ||
| 2130 | if (!np->intr_status) | ||
| 2131 | return IRQ_NONE; | ||
| 2132 | |||
| 2128 | if (netif_msg_intr(np)) | 2133 | if (netif_msg_intr(np)) |
| 2129 | printk(KERN_DEBUG | 2134 | printk(KERN_DEBUG |
| 2130 | "%s: Interrupt, status %#08x, mask %#08x.\n", | 2135 | "%s: Interrupt, status %#08x, mask %#08x.\n", |
| 2131 | dev->name, np->intr_status, | 2136 | dev->name, np->intr_status, |
| 2132 | readl(ioaddr + IntrMask)); | 2137 | readl(ioaddr + IntrMask)); |
| 2133 | 2138 | ||
| 2134 | if (!np->intr_status) | ||
| 2135 | return IRQ_NONE; | ||
| 2136 | |||
| 2137 | prefetch(&np->rx_skbuff[np->cur_rx % RX_RING_SIZE]); | 2139 | prefetch(&np->rx_skbuff[np->cur_rx % RX_RING_SIZE]); |
| 2138 | 2140 | ||
| 2139 | if (netif_rx_schedule_prep(dev)) { | 2141 | if (netif_rx_schedule_prep(dev)) { |
| 2140 | /* Disable interrupts and register for poll */ | 2142 | /* Disable interrupts and register for poll */ |
| 2141 | natsemi_irq_disable(dev); | 2143 | natsemi_irq_disable(dev); |
| 2142 | __netif_rx_schedule(dev); | 2144 | __netif_rx_schedule(dev); |
| 2143 | } | 2145 | } else |
| 2146 | printk(KERN_WARNING | ||
| 2147 | "%s: Ignoring interrupt, status %#08x, mask %#08x.\n", | ||
| 2148 | dev->name, np->intr_status, | ||
| 2149 | readl(ioaddr + IntrMask)); | ||
| 2150 | |||
| 2144 | return IRQ_HANDLED; | 2151 | return IRQ_HANDLED; |
| 2145 | } | 2152 | } |
| 2146 | 2153 | ||
| @@ -2156,6 +2163,20 @@ static int natsemi_poll(struct net_device *dev, int *budget) | |||
| 2156 | int work_done = 0; | 2163 | int work_done = 0; |
| 2157 | 2164 | ||
| 2158 | do { | 2165 | do { |
| 2166 | if (netif_msg_intr(np)) | ||
| 2167 | printk(KERN_DEBUG | ||
| 2168 | "%s: Poll, status %#08x, mask %#08x.\n", | ||
| 2169 | dev->name, np->intr_status, | ||
| 2170 | readl(ioaddr + IntrMask)); | ||
| 2171 | |||
| 2172 | /* netdev_rx() may read IntrStatus again if the RX state | ||
| 2173 | * machine falls over so do it first. */ | ||
| 2174 | if (np->intr_status & | ||
| 2175 | (IntrRxDone | IntrRxIntr | RxStatusFIFOOver | | ||
| 2176 | IntrRxErr | IntrRxOverrun)) { | ||
| 2177 | netdev_rx(dev, &work_done, work_to_do); | ||
| 2178 | } | ||
| 2179 | |||
| 2159 | if (np->intr_status & | 2180 | if (np->intr_status & |
| 2160 | (IntrTxDone | IntrTxIntr | IntrTxIdle | IntrTxErr)) { | 2181 | (IntrTxDone | IntrTxIntr | IntrTxIdle | IntrTxErr)) { |
| 2161 | spin_lock(&np->lock); | 2182 | spin_lock(&np->lock); |
| @@ -2167,12 +2188,6 @@ static int natsemi_poll(struct net_device *dev, int *budget) | |||
| 2167 | if (np->intr_status & IntrAbnormalSummary) | 2188 | if (np->intr_status & IntrAbnormalSummary) |
| 2168 | netdev_error(dev, np->intr_status); | 2189 | netdev_error(dev, np->intr_status); |
| 2169 | 2190 | ||
| 2170 | if (np->intr_status & | ||
| 2171 | (IntrRxDone | IntrRxIntr | RxStatusFIFOOver | | ||
| 2172 | IntrRxErr | IntrRxOverrun)) { | ||
| 2173 | netdev_rx(dev, &work_done, work_to_do); | ||
| 2174 | } | ||
| 2175 | |||
| 2176 | *budget -= work_done; | 2191 | *budget -= work_done; |
| 2177 | dev->quota -= work_done; | 2192 | dev->quota -= work_done; |
| 2178 | 2193 | ||
| @@ -2399,19 +2414,8 @@ static struct net_device_stats *get_stats(struct net_device *dev) | |||
| 2399 | #ifdef CONFIG_NET_POLL_CONTROLLER | 2414 | #ifdef CONFIG_NET_POLL_CONTROLLER |
| 2400 | static void natsemi_poll_controller(struct net_device *dev) | 2415 | static void natsemi_poll_controller(struct net_device *dev) |
| 2401 | { | 2416 | { |
| 2402 | struct netdev_private *np = netdev_priv(dev); | ||
| 2403 | |||
| 2404 | disable_irq(dev->irq); | 2417 | disable_irq(dev->irq); |
| 2405 | 2418 | intr_handler(dev->irq, dev); | |
| 2406 | /* | ||
| 2407 | * A real interrupt might have already reached us at this point | ||
| 2408 | * but NAPI might still haven't called us back. As the interrupt | ||
| 2409 | * status register is cleared by reading, we should prevent an | ||
| 2410 | * interrupt loss in this case... | ||
| 2411 | */ | ||
| 2412 | if (!np->intr_status) | ||
| 2413 | intr_handler(dev->irq, dev); | ||
| 2414 | |||
| 2415 | enable_irq(dev->irq); | 2419 | enable_irq(dev->irq); |
| 2416 | } | 2420 | } |
| 2417 | #endif | 2421 | #endif |
| @@ -3071,7 +3075,7 @@ static void enable_wol_mode(struct net_device *dev, int enable_intr) | |||
| 3071 | * Could be used to send a netlink message. | 3075 | * Could be used to send a netlink message. |
| 3072 | */ | 3076 | */ |
| 3073 | writel(WOLPkt | LinkChange, ioaddr + IntrMask); | 3077 | writel(WOLPkt | LinkChange, ioaddr + IntrMask); |
| 3074 | writel(1, ioaddr + IntrEnable); | 3078 | natsemi_irq_enable(dev); |
| 3075 | } | 3079 | } |
| 3076 | } | 3080 | } |
| 3077 | 3081 | ||
| @@ -3202,7 +3206,7 @@ static int natsemi_suspend (struct pci_dev *pdev, pm_message_t state) | |||
| 3202 | disable_irq(dev->irq); | 3206 | disable_irq(dev->irq); |
| 3203 | spin_lock_irq(&np->lock); | 3207 | spin_lock_irq(&np->lock); |
| 3204 | 3208 | ||
| 3205 | writel(0, ioaddr + IntrEnable); | 3209 | natsemi_irq_disable(dev); |
| 3206 | np->hands_off = 1; | 3210 | np->hands_off = 1; |
| 3207 | natsemi_stop_rxtx(dev); | 3211 | natsemi_stop_rxtx(dev); |
| 3208 | netif_stop_queue(dev); | 3212 | netif_stop_queue(dev); |
