aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/typhoon.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/typhoon.c')
-rw-r--r--drivers/net/typhoon.c47
1 files changed, 19 insertions, 28 deletions
diff --git a/drivers/net/typhoon.c b/drivers/net/typhoon.c
index 03587205546..0377b8b64c7 100644
--- a/drivers/net/typhoon.c
+++ b/drivers/net/typhoon.c
@@ -284,6 +284,7 @@ struct typhoon {
284 struct basic_ring rxLoRing; 284 struct basic_ring rxLoRing;
285 struct pci_dev * pdev; 285 struct pci_dev * pdev;
286 struct net_device * dev; 286 struct net_device * dev;
287 struct napi_struct napi;
287 spinlock_t state_lock; 288 spinlock_t state_lock;
288 struct vlan_group * vlgrp; 289 struct vlan_group * vlgrp;
289 struct basic_ring rxHiRing; 290 struct basic_ring rxHiRing;
@@ -1759,12 +1760,12 @@ typhoon_fill_free_ring(struct typhoon *tp)
1759} 1760}
1760 1761
1761static int 1762static int
1762typhoon_poll(struct net_device *dev, int *total_budget) 1763typhoon_poll(struct napi_struct *napi, int budget)
1763{ 1764{
1764 struct typhoon *tp = netdev_priv(dev); 1765 struct typhoon *tp = container_of(napi, struct typhoon, napi);
1766 struct net_device *dev = tp->dev;
1765 struct typhoon_indexes *indexes = tp->indexes; 1767 struct typhoon_indexes *indexes = tp->indexes;
1766 int orig_budget = *total_budget; 1768 int work_done;
1767 int budget, work_done, done;
1768 1769
1769 rmb(); 1770 rmb();
1770 if(!tp->awaiting_resp && indexes->respReady != indexes->respCleared) 1771 if(!tp->awaiting_resp && indexes->respReady != indexes->respCleared)
@@ -1773,30 +1774,16 @@ typhoon_poll(struct net_device *dev, int *total_budget)
1773 if(le32_to_cpu(indexes->txLoCleared) != tp->txLoRing.lastRead) 1774 if(le32_to_cpu(indexes->txLoCleared) != tp->txLoRing.lastRead)
1774 typhoon_tx_complete(tp, &tp->txLoRing, &indexes->txLoCleared); 1775 typhoon_tx_complete(tp, &tp->txLoRing, &indexes->txLoCleared);
1775 1776
1776 if(orig_budget > dev->quota)
1777 orig_budget = dev->quota;
1778
1779 budget = orig_budget;
1780 work_done = 0; 1777 work_done = 0;
1781 done = 1;
1782 1778
1783 if(indexes->rxHiCleared != indexes->rxHiReady) { 1779 if(indexes->rxHiCleared != indexes->rxHiReady) {
1784 work_done = typhoon_rx(tp, &tp->rxHiRing, &indexes->rxHiReady, 1780 work_done += typhoon_rx(tp, &tp->rxHiRing, &indexes->rxHiReady,
1785 &indexes->rxHiCleared, budget); 1781 &indexes->rxHiCleared, budget);
1786 budget -= work_done;
1787 } 1782 }
1788 1783
1789 if(indexes->rxLoCleared != indexes->rxLoReady) { 1784 if(indexes->rxLoCleared != indexes->rxLoReady) {
1790 work_done += typhoon_rx(tp, &tp->rxLoRing, &indexes->rxLoReady, 1785 work_done += typhoon_rx(tp, &tp->rxLoRing, &indexes->rxLoReady,
1791 &indexes->rxLoCleared, budget); 1786 &indexes->rxLoCleared, budget - work_done);
1792 }
1793
1794 if(work_done) {
1795 *total_budget -= work_done;
1796 dev->quota -= work_done;
1797
1798 if(work_done >= orig_budget)
1799 done = 0;
1800 } 1787 }
1801 1788
1802 if(le32_to_cpu(indexes->rxBuffCleared) == tp->rxBuffRing.lastWrite) { 1789 if(le32_to_cpu(indexes->rxBuffCleared) == tp->rxBuffRing.lastWrite) {
@@ -1804,14 +1791,14 @@ typhoon_poll(struct net_device *dev, int *total_budget)
1804 typhoon_fill_free_ring(tp); 1791 typhoon_fill_free_ring(tp);
1805 } 1792 }
1806 1793
1807 if(done) { 1794 if (work_done < budget) {
1808 netif_rx_complete(dev); 1795 netif_rx_complete(dev, napi);
1809 iowrite32(TYPHOON_INTR_NONE, 1796 iowrite32(TYPHOON_INTR_NONE,
1810 tp->ioaddr + TYPHOON_REG_INTR_MASK); 1797 tp->ioaddr + TYPHOON_REG_INTR_MASK);
1811 typhoon_post_pci_writes(tp->ioaddr); 1798 typhoon_post_pci_writes(tp->ioaddr);
1812 } 1799 }
1813 1800
1814 return (done ? 0 : 1); 1801 return work_done;
1815} 1802}
1816 1803
1817static irqreturn_t 1804static irqreturn_t
@@ -1828,10 +1815,10 @@ typhoon_interrupt(int irq, void *dev_instance)
1828 1815
1829 iowrite32(intr_status, ioaddr + TYPHOON_REG_INTR_STATUS); 1816 iowrite32(intr_status, ioaddr + TYPHOON_REG_INTR_STATUS);
1830 1817
1831 if(netif_rx_schedule_prep(dev)) { 1818 if (netif_rx_schedule_prep(dev, &tp->napi)) {
1832 iowrite32(TYPHOON_INTR_ALL, ioaddr + TYPHOON_REG_INTR_MASK); 1819 iowrite32(TYPHOON_INTR_ALL, ioaddr + TYPHOON_REG_INTR_MASK);
1833 typhoon_post_pci_writes(ioaddr); 1820 typhoon_post_pci_writes(ioaddr);
1834 __netif_rx_schedule(dev); 1821 __netif_rx_schedule(dev, &tp->napi);
1835 } else { 1822 } else {
1836 printk(KERN_ERR "%s: Error, poll already scheduled\n", 1823 printk(KERN_ERR "%s: Error, poll already scheduled\n",
1837 dev->name); 1824 dev->name);
@@ -2119,9 +2106,13 @@ typhoon_open(struct net_device *dev)
2119 if(err < 0) 2106 if(err < 0)
2120 goto out_sleep; 2107 goto out_sleep;
2121 2108
2109 napi_enable(&tp->napi);
2110
2122 err = typhoon_start_runtime(tp); 2111 err = typhoon_start_runtime(tp);
2123 if(err < 0) 2112 if(err < 0) {
2113 napi_disable(&tp->napi);
2124 goto out_irq; 2114 goto out_irq;
2115 }
2125 2116
2126 netif_start_queue(dev); 2117 netif_start_queue(dev);
2127 return 0; 2118 return 0;
@@ -2150,6 +2141,7 @@ typhoon_close(struct net_device *dev)
2150 struct typhoon *tp = netdev_priv(dev); 2141 struct typhoon *tp = netdev_priv(dev);
2151 2142
2152 netif_stop_queue(dev); 2143 netif_stop_queue(dev);
2144 napi_disable(&tp->napi);
2153 2145
2154 if(typhoon_stop_runtime(tp, WaitSleep) < 0) 2146 if(typhoon_stop_runtime(tp, WaitSleep) < 0)
2155 printk(KERN_ERR "%s: unable to stop runtime\n", dev->name); 2147 printk(KERN_ERR "%s: unable to stop runtime\n", dev->name);
@@ -2521,8 +2513,7 @@ typhoon_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
2521 dev->stop = typhoon_close; 2513 dev->stop = typhoon_close;
2522 dev->set_multicast_list = typhoon_set_rx_mode; 2514 dev->set_multicast_list = typhoon_set_rx_mode;
2523 dev->tx_timeout = typhoon_tx_timeout; 2515 dev->tx_timeout = typhoon_tx_timeout;
2524 dev->poll = typhoon_poll; 2516 netif_napi_add(dev, &tp->napi, typhoon_poll, 16);
2525 dev->weight = 16;
2526 dev->watchdog_timeo = TX_TIMEOUT; 2517 dev->watchdog_timeo = TX_TIMEOUT;
2527 dev->get_stats = typhoon_get_stats; 2518 dev->get_stats = typhoon_get_stats;
2528 dev->set_mac_address = typhoon_set_mac_address; 2519 dev->set_mac_address = typhoon_set_mac_address;