diff options
Diffstat (limited to 'drivers/net/8139cp.c')
-rw-r--r-- | drivers/net/8139cp.c | 41 |
1 files changed, 21 insertions, 20 deletions
diff --git a/drivers/net/8139cp.c b/drivers/net/8139cp.c index a79f28c7a100..7f18ca23d9f8 100644 --- a/drivers/net/8139cp.c +++ b/drivers/net/8139cp.c | |||
@@ -334,6 +334,8 @@ struct cp_private { | |||
334 | spinlock_t lock; | 334 | spinlock_t lock; |
335 | u32 msg_enable; | 335 | u32 msg_enable; |
336 | 336 | ||
337 | struct napi_struct napi; | ||
338 | |||
337 | struct pci_dev *pdev; | 339 | struct pci_dev *pdev; |
338 | u32 rx_config; | 340 | u32 rx_config; |
339 | u16 cpcmd; | 341 | u16 cpcmd; |
@@ -501,12 +503,12 @@ static inline unsigned int cp_rx_csum_ok (u32 status) | |||
501 | return 0; | 503 | return 0; |
502 | } | 504 | } |
503 | 505 | ||
504 | static int cp_rx_poll (struct net_device *dev, int *budget) | 506 | static int cp_rx_poll(struct napi_struct *napi, int budget) |
505 | { | 507 | { |
506 | struct cp_private *cp = netdev_priv(dev); | 508 | struct cp_private *cp = container_of(napi, struct cp_private, napi); |
507 | unsigned rx_tail = cp->rx_tail; | 509 | struct net_device *dev = cp->dev; |
508 | unsigned rx_work = dev->quota; | 510 | unsigned int rx_tail = cp->rx_tail; |
509 | unsigned rx; | 511 | int rx; |
510 | 512 | ||
511 | rx_status_loop: | 513 | rx_status_loop: |
512 | rx = 0; | 514 | rx = 0; |
@@ -588,33 +590,28 @@ rx_next: | |||
588 | desc->opts1 = cpu_to_le32(DescOwn | cp->rx_buf_sz); | 590 | desc->opts1 = cpu_to_le32(DescOwn | cp->rx_buf_sz); |
589 | rx_tail = NEXT_RX(rx_tail); | 591 | rx_tail = NEXT_RX(rx_tail); |
590 | 592 | ||
591 | if (!rx_work--) | 593 | if (rx >= budget) |
592 | break; | 594 | break; |
593 | } | 595 | } |
594 | 596 | ||
595 | cp->rx_tail = rx_tail; | 597 | cp->rx_tail = rx_tail; |
596 | 598 | ||
597 | dev->quota -= rx; | ||
598 | *budget -= rx; | ||
599 | |||
600 | /* if we did not reach work limit, then we're done with | 599 | /* if we did not reach work limit, then we're done with |
601 | * this round of polling | 600 | * this round of polling |
602 | */ | 601 | */ |
603 | if (rx_work) { | 602 | if (rx < budget) { |
604 | unsigned long flags; | 603 | unsigned long flags; |
605 | 604 | ||
606 | if (cpr16(IntrStatus) & cp_rx_intr_mask) | 605 | if (cpr16(IntrStatus) & cp_rx_intr_mask) |
607 | goto rx_status_loop; | 606 | goto rx_status_loop; |
608 | 607 | ||
609 | local_irq_save(flags); | 608 | spin_lock_irqsave(&cp->lock, flags); |
610 | cpw16_f(IntrMask, cp_intr_mask); | 609 | cpw16_f(IntrMask, cp_intr_mask); |
611 | __netif_rx_complete(dev); | 610 | __netif_rx_complete(dev, napi); |
612 | local_irq_restore(flags); | 611 | spin_unlock_irqrestore(&cp->lock, flags); |
613 | |||
614 | return 0; /* done */ | ||
615 | } | 612 | } |
616 | 613 | ||
617 | return 1; /* not done */ | 614 | return rx; |
618 | } | 615 | } |
619 | 616 | ||
620 | static irqreturn_t cp_interrupt (int irq, void *dev_instance) | 617 | static irqreturn_t cp_interrupt (int irq, void *dev_instance) |
@@ -647,9 +644,9 @@ static irqreturn_t cp_interrupt (int irq, void *dev_instance) | |||
647 | } | 644 | } |
648 | 645 | ||
649 | if (status & (RxOK | RxErr | RxEmpty | RxFIFOOvr)) | 646 | if (status & (RxOK | RxErr | RxEmpty | RxFIFOOvr)) |
650 | if (netif_rx_schedule_prep(dev)) { | 647 | if (netif_rx_schedule_prep(dev, &cp->napi)) { |
651 | cpw16_f(IntrMask, cp_norx_intr_mask); | 648 | cpw16_f(IntrMask, cp_norx_intr_mask); |
652 | __netif_rx_schedule(dev); | 649 | __netif_rx_schedule(dev, &cp->napi); |
653 | } | 650 | } |
654 | 651 | ||
655 | if (status & (TxOK | TxErr | TxEmpty | SWInt)) | 652 | if (status & (TxOK | TxErr | TxEmpty | SWInt)) |
@@ -1175,6 +1172,8 @@ static int cp_open (struct net_device *dev) | |||
1175 | if (rc) | 1172 | if (rc) |
1176 | return rc; | 1173 | return rc; |
1177 | 1174 | ||
1175 | napi_enable(&cp->napi); | ||
1176 | |||
1178 | cp_init_hw(cp); | 1177 | cp_init_hw(cp); |
1179 | 1178 | ||
1180 | rc = request_irq(dev->irq, cp_interrupt, IRQF_SHARED, dev->name, dev); | 1179 | rc = request_irq(dev->irq, cp_interrupt, IRQF_SHARED, dev->name, dev); |
@@ -1188,6 +1187,7 @@ static int cp_open (struct net_device *dev) | |||
1188 | return 0; | 1187 | return 0; |
1189 | 1188 | ||
1190 | err_out_hw: | 1189 | err_out_hw: |
1190 | napi_disable(&cp->napi); | ||
1191 | cp_stop_hw(cp); | 1191 | cp_stop_hw(cp); |
1192 | cp_free_rings(cp); | 1192 | cp_free_rings(cp); |
1193 | return rc; | 1193 | return rc; |
@@ -1198,6 +1198,8 @@ static int cp_close (struct net_device *dev) | |||
1198 | struct cp_private *cp = netdev_priv(dev); | 1198 | struct cp_private *cp = netdev_priv(dev); |
1199 | unsigned long flags; | 1199 | unsigned long flags; |
1200 | 1200 | ||
1201 | napi_disable(&cp->napi); | ||
1202 | |||
1201 | if (netif_msg_ifdown(cp)) | 1203 | if (netif_msg_ifdown(cp)) |
1202 | printk(KERN_DEBUG "%s: disabling interface\n", dev->name); | 1204 | printk(KERN_DEBUG "%s: disabling interface\n", dev->name); |
1203 | 1205 | ||
@@ -1933,11 +1935,10 @@ static int cp_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) | |||
1933 | dev->hard_start_xmit = cp_start_xmit; | 1935 | dev->hard_start_xmit = cp_start_xmit; |
1934 | dev->get_stats = cp_get_stats; | 1936 | dev->get_stats = cp_get_stats; |
1935 | dev->do_ioctl = cp_ioctl; | 1937 | dev->do_ioctl = cp_ioctl; |
1936 | dev->poll = cp_rx_poll; | ||
1937 | #ifdef CONFIG_NET_POLL_CONTROLLER | 1938 | #ifdef CONFIG_NET_POLL_CONTROLLER |
1938 | dev->poll_controller = cp_poll_controller; | 1939 | dev->poll_controller = cp_poll_controller; |
1939 | #endif | 1940 | #endif |
1940 | dev->weight = 16; /* arbitrary? from NAPI_HOWTO.txt. */ | 1941 | netif_napi_add(dev, &cp->napi, cp_rx_poll, 16); |
1941 | #ifdef BROKEN | 1942 | #ifdef BROKEN |
1942 | dev->change_mtu = cp_change_mtu; | 1943 | dev->change_mtu = cp_change_mtu; |
1943 | #endif | 1944 | #endif |