diff options
Diffstat (limited to 'drivers/net/typhoon.c')
-rw-r--r-- | drivers/net/typhoon.c | 47 |
1 files changed, 19 insertions, 28 deletions
diff --git a/drivers/net/typhoon.c b/drivers/net/typhoon.c index 03587205546e..0377b8b64c78 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 | ||
1761 | static int | 1762 | static int |
1762 | typhoon_poll(struct net_device *dev, int *total_budget) | 1763 | typhoon_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 | ||
1817 | static irqreturn_t | 1804 | static 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; |