diff options
Diffstat (limited to 'drivers/net/tulip/interrupt.c')
-rw-r--r-- | drivers/net/tulip/interrupt.c | 54 |
1 files changed, 23 insertions, 31 deletions
diff --git a/drivers/net/tulip/interrupt.c b/drivers/net/tulip/interrupt.c index 53efd6694e75..365331446387 100644 --- a/drivers/net/tulip/interrupt.c +++ b/drivers/net/tulip/interrupt.c | |||
@@ -103,28 +103,29 @@ int tulip_refill_rx(struct net_device *dev) | |||
103 | void oom_timer(unsigned long data) | 103 | void oom_timer(unsigned long data) |
104 | { | 104 | { |
105 | struct net_device *dev = (struct net_device *)data; | 105 | struct net_device *dev = (struct net_device *)data; |
106 | netif_rx_schedule(dev); | 106 | struct tulip_private *tp = netdev_priv(dev); |
107 | netif_rx_schedule(dev, &tp->napi); | ||
107 | } | 108 | } |
108 | 109 | ||
109 | int tulip_poll(struct net_device *dev, int *budget) | 110 | int tulip_poll(struct napi_struct *napi, int budget) |
110 | { | 111 | { |
111 | struct tulip_private *tp = netdev_priv(dev); | 112 | struct tulip_private *tp = container_of(napi, struct tulip_private, napi); |
113 | struct net_device *dev = tp->dev; | ||
112 | int entry = tp->cur_rx % RX_RING_SIZE; | 114 | int entry = tp->cur_rx % RX_RING_SIZE; |
113 | int rx_work_limit = *budget; | 115 | int work_done = 0; |
116 | #ifdef CONFIG_TULIP_NAPI_HW_MITIGATION | ||
114 | int received = 0; | 117 | int received = 0; |
118 | #endif | ||
115 | 119 | ||
116 | if (!netif_running(dev)) | 120 | if (!netif_running(dev)) |
117 | goto done; | 121 | goto done; |
118 | 122 | ||
119 | if (rx_work_limit > dev->quota) | ||
120 | rx_work_limit = dev->quota; | ||
121 | |||
122 | #ifdef CONFIG_TULIP_NAPI_HW_MITIGATION | 123 | #ifdef CONFIG_TULIP_NAPI_HW_MITIGATION |
123 | 124 | ||
124 | /* that one buffer is needed for mit activation; or might be a | 125 | /* that one buffer is needed for mit activation; or might be a |
125 | bug in the ring buffer code; check later -- JHS*/ | 126 | bug in the ring buffer code; check later -- JHS*/ |
126 | 127 | ||
127 | if (rx_work_limit >=RX_RING_SIZE) rx_work_limit--; | 128 | if (budget >=RX_RING_SIZE) budget--; |
128 | #endif | 129 | #endif |
129 | 130 | ||
130 | if (tulip_debug > 4) | 131 | if (tulip_debug > 4) |
@@ -144,14 +145,13 @@ int tulip_poll(struct net_device *dev, int *budget) | |||
144 | while ( ! (tp->rx_ring[entry].status & cpu_to_le32(DescOwned))) { | 145 | while ( ! (tp->rx_ring[entry].status & cpu_to_le32(DescOwned))) { |
145 | s32 status = le32_to_cpu(tp->rx_ring[entry].status); | 146 | s32 status = le32_to_cpu(tp->rx_ring[entry].status); |
146 | 147 | ||
147 | |||
148 | if (tp->dirty_rx + RX_RING_SIZE == tp->cur_rx) | 148 | if (tp->dirty_rx + RX_RING_SIZE == tp->cur_rx) |
149 | break; | 149 | break; |
150 | 150 | ||
151 | if (tulip_debug > 5) | 151 | if (tulip_debug > 5) |
152 | printk(KERN_DEBUG "%s: In tulip_rx(), entry %d %8.8x.\n", | 152 | printk(KERN_DEBUG "%s: In tulip_rx(), entry %d %8.8x.\n", |
153 | dev->name, entry, status); | 153 | dev->name, entry, status); |
154 | if (--rx_work_limit < 0) | 154 | if (work_done++ >= budget) |
155 | goto not_done; | 155 | goto not_done; |
156 | 156 | ||
157 | if ((status & 0x38008300) != 0x0300) { | 157 | if ((status & 0x38008300) != 0x0300) { |
@@ -238,7 +238,9 @@ int tulip_poll(struct net_device *dev, int *budget) | |||
238 | tp->stats.rx_packets++; | 238 | tp->stats.rx_packets++; |
239 | tp->stats.rx_bytes += pkt_len; | 239 | tp->stats.rx_bytes += pkt_len; |
240 | } | 240 | } |
241 | received++; | 241 | #ifdef CONFIG_TULIP_NAPI_HW_MITIGATION |
242 | received++; | ||
243 | #endif | ||
242 | 244 | ||
243 | entry = (++tp->cur_rx) % RX_RING_SIZE; | 245 | entry = (++tp->cur_rx) % RX_RING_SIZE; |
244 | if (tp->cur_rx - tp->dirty_rx > RX_RING_SIZE/4) | 246 | if (tp->cur_rx - tp->dirty_rx > RX_RING_SIZE/4) |
@@ -296,17 +298,15 @@ done: | |||
296 | 298 | ||
297 | #endif /* CONFIG_TULIP_NAPI_HW_MITIGATION */ | 299 | #endif /* CONFIG_TULIP_NAPI_HW_MITIGATION */ |
298 | 300 | ||
299 | dev->quota -= received; | ||
300 | *budget -= received; | ||
301 | |||
302 | tulip_refill_rx(dev); | 301 | tulip_refill_rx(dev); |
303 | 302 | ||
304 | /* If RX ring is not full we are out of memory. */ | 303 | /* If RX ring is not full we are out of memory. */ |
305 | if (tp->rx_buffers[tp->dirty_rx % RX_RING_SIZE].skb == NULL) goto oom; | 304 | if (tp->rx_buffers[tp->dirty_rx % RX_RING_SIZE].skb == NULL) |
305 | goto oom; | ||
306 | 306 | ||
307 | /* Remove us from polling list and enable RX intr. */ | 307 | /* Remove us from polling list and enable RX intr. */ |
308 | 308 | ||
309 | netif_rx_complete(dev); | 309 | netif_rx_complete(dev, napi); |
310 | iowrite32(tulip_tbl[tp->chip_id].valid_intrs, tp->base_addr+CSR7); | 310 | iowrite32(tulip_tbl[tp->chip_id].valid_intrs, tp->base_addr+CSR7); |
311 | 311 | ||
312 | /* The last op happens after poll completion. Which means the following: | 312 | /* The last op happens after poll completion. Which means the following: |
@@ -320,28 +320,20 @@ done: | |||
320 | * processed irqs. But it must not result in losing events. | 320 | * processed irqs. But it must not result in losing events. |
321 | */ | 321 | */ |
322 | 322 | ||
323 | return 0; | 323 | return work_done; |
324 | 324 | ||
325 | not_done: | 325 | not_done: |
326 | if (!received) { | ||
327 | |||
328 | received = dev->quota; /* Not to happen */ | ||
329 | } | ||
330 | dev->quota -= received; | ||
331 | *budget -= received; | ||
332 | |||
333 | if (tp->cur_rx - tp->dirty_rx > RX_RING_SIZE/2 || | 326 | if (tp->cur_rx - tp->dirty_rx > RX_RING_SIZE/2 || |
334 | tp->rx_buffers[tp->dirty_rx % RX_RING_SIZE].skb == NULL) | 327 | tp->rx_buffers[tp->dirty_rx % RX_RING_SIZE].skb == NULL) |
335 | tulip_refill_rx(dev); | 328 | tulip_refill_rx(dev); |
336 | 329 | ||
337 | if (tp->rx_buffers[tp->dirty_rx % RX_RING_SIZE].skb == NULL) goto oom; | 330 | if (tp->rx_buffers[tp->dirty_rx % RX_RING_SIZE].skb == NULL) |
338 | 331 | goto oom; | |
339 | return 1; | ||
340 | 332 | ||
333 | return work_done; | ||
341 | 334 | ||
342 | oom: /* Executed with RX ints disabled */ | 335 | oom: /* Executed with RX ints disabled */ |
343 | 336 | ||
344 | |||
345 | /* Start timer, stop polling, but do not enable rx interrupts. */ | 337 | /* Start timer, stop polling, but do not enable rx interrupts. */ |
346 | mod_timer(&tp->oom_timer, jiffies+1); | 338 | mod_timer(&tp->oom_timer, jiffies+1); |
347 | 339 | ||
@@ -350,9 +342,9 @@ done: | |||
350 | * before we did netif_rx_complete(). See? We would lose it. */ | 342 | * before we did netif_rx_complete(). See? We would lose it. */ |
351 | 343 | ||
352 | /* remove ourselves from the polling list */ | 344 | /* remove ourselves from the polling list */ |
353 | netif_rx_complete(dev); | 345 | netif_rx_complete(dev, napi); |
354 | 346 | ||
355 | return 0; | 347 | return work_done; |
356 | } | 348 | } |
357 | 349 | ||
358 | #else /* CONFIG_TULIP_NAPI */ | 350 | #else /* CONFIG_TULIP_NAPI */ |
@@ -534,7 +526,7 @@ irqreturn_t tulip_interrupt(int irq, void *dev_instance) | |||
534 | rxd++; | 526 | rxd++; |
535 | /* Mask RX intrs and add the device to poll list. */ | 527 | /* Mask RX intrs and add the device to poll list. */ |
536 | iowrite32(tulip_tbl[tp->chip_id].valid_intrs&~RxPollInt, ioaddr + CSR7); | 528 | iowrite32(tulip_tbl[tp->chip_id].valid_intrs&~RxPollInt, ioaddr + CSR7); |
537 | netif_rx_schedule(dev); | 529 | netif_rx_schedule(dev, &tp->napi); |
538 | 530 | ||
539 | if (!(csr5&~(AbnormalIntr|NormalIntr|RxPollInt|TPLnkPass))) | 531 | if (!(csr5&~(AbnormalIntr|NormalIntr|RxPollInt|TPLnkPass))) |
540 | break; | 532 | break; |