aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorSimon Kagstrom <simon.kagstrom@netinsight.net>2009-11-25 17:10:26 -0500
committerDavid S. Miller <davem@davemloft.net>2009-11-26 18:51:15 -0500
commitdfff7144b14bab3d8baaeba8926fab371fa4a01e (patch)
treed876204977e50bd7091f334614bdf0b2c2f7982b /drivers
parent6dfc4b95b29d89dbdb45de04b1b1ff493ec8016d (diff)
via-velocity: Implement NAPI support
This patch adds NAPI support for VIA velocity. The new velocity_poll function also pairs tx/rx handling twice which improves perforamance on some workloads (e.g., netperf UDP_STREAM) significantly (that part is from the VIA driver). Signed-off-by: Simon Kagstrom <simon.kagstrom@netinsight.net> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/via-velocity.c81
-rw-r--r--drivers/net/via-velocity.h3
2 files changed, 49 insertions, 35 deletions
diff --git a/drivers/net/via-velocity.c b/drivers/net/via-velocity.c
index 7c362b242704..47b28821589b 100644
--- a/drivers/net/via-velocity.c
+++ b/drivers/net/via-velocity.c
@@ -354,12 +354,6 @@ VELOCITY_PARAM(ValPktLen, "Receiving or Drop invalid 802.3 frame");
354*/ 354*/
355VELOCITY_PARAM(wol_opts, "Wake On Lan options"); 355VELOCITY_PARAM(wol_opts, "Wake On Lan options");
356 356
357#define INT_WORKS_DEF 20
358#define INT_WORKS_MIN 10
359#define INT_WORKS_MAX 64
360
361VELOCITY_PARAM(int_works, "Number of packets per interrupt services");
362
363static int rx_copybreak = 200; 357static int rx_copybreak = 200;
364module_param(rx_copybreak, int, 0644); 358module_param(rx_copybreak, int, 0644);
365MODULE_PARM_DESC(rx_copybreak, "Copy breakpoint for copy-only-tiny-frames"); 359MODULE_PARM_DESC(rx_copybreak, "Copy breakpoint for copy-only-tiny-frames");
@@ -503,7 +497,6 @@ static void __devinit velocity_get_options(struct velocity_opt *opts, int index,
503 velocity_set_bool_opt(&opts->flags, ValPktLen[index], VAL_PKT_LEN_DEF, VELOCITY_FLAGS_VAL_PKT_LEN, "ValPktLen", devname); 497 velocity_set_bool_opt(&opts->flags, ValPktLen[index], VAL_PKT_LEN_DEF, VELOCITY_FLAGS_VAL_PKT_LEN, "ValPktLen", devname);
504 velocity_set_int_opt((int *) &opts->spd_dpx, speed_duplex[index], MED_LNK_MIN, MED_LNK_MAX, MED_LNK_DEF, "Media link mode", devname); 498 velocity_set_int_opt((int *) &opts->spd_dpx, speed_duplex[index], MED_LNK_MIN, MED_LNK_MAX, MED_LNK_DEF, "Media link mode", devname);
505 velocity_set_int_opt((int *) &opts->wol_opts, wol_opts[index], WOL_OPT_MIN, WOL_OPT_MAX, WOL_OPT_DEF, "Wake On Lan options", devname); 499 velocity_set_int_opt((int *) &opts->wol_opts, wol_opts[index], WOL_OPT_MIN, WOL_OPT_MAX, WOL_OPT_DEF, "Wake On Lan options", devname);
506 velocity_set_int_opt((int *) &opts->int_works, int_works[index], INT_WORKS_MIN, INT_WORKS_MAX, INT_WORKS_DEF, "Interrupt service works", devname);
507 opts->numrx = (opts->numrx & ~3); 500 opts->numrx = (opts->numrx & ~3);
508} 501}
509 502
@@ -2109,13 +2102,14 @@ static int velocity_receive_frame(struct velocity_info *vptr, int idx)
2109 * any received packets from the receive queue. Hand the ring 2102 * any received packets from the receive queue. Hand the ring
2110 * slots back to the adapter for reuse. 2103 * slots back to the adapter for reuse.
2111 */ 2104 */
2112static int velocity_rx_srv(struct velocity_info *vptr, int status) 2105static int velocity_rx_srv(struct velocity_info *vptr, int status,
2106 int budget_left)
2113{ 2107{
2114 struct net_device_stats *stats = &vptr->dev->stats; 2108 struct net_device_stats *stats = &vptr->dev->stats;
2115 int rd_curr = vptr->rx.curr; 2109 int rd_curr = vptr->rx.curr;
2116 int works = 0; 2110 int works = 0;
2117 2111
2118 do { 2112 while (works < budget_left) {
2119 struct rx_desc *rd = vptr->rx.ring + rd_curr; 2113 struct rx_desc *rd = vptr->rx.ring + rd_curr;
2120 2114
2121 if (!vptr->rx.info[rd_curr].skb) 2115 if (!vptr->rx.info[rd_curr].skb)
@@ -2146,7 +2140,8 @@ static int velocity_rx_srv(struct velocity_info *vptr, int status)
2146 rd_curr++; 2140 rd_curr++;
2147 if (rd_curr >= vptr->options.numrx) 2141 if (rd_curr >= vptr->options.numrx)
2148 rd_curr = 0; 2142 rd_curr = 0;
2149 } while (++works <= 15); 2143 works++;
2144 }
2150 2145
2151 vptr->rx.curr = rd_curr; 2146 vptr->rx.curr = rd_curr;
2152 2147
@@ -2157,6 +2152,40 @@ static int velocity_rx_srv(struct velocity_info *vptr, int status)
2157 return works; 2152 return works;
2158} 2153}
2159 2154
2155static int velocity_poll(struct napi_struct *napi, int budget)
2156{
2157 struct velocity_info *vptr = container_of(napi,
2158 struct velocity_info, napi);
2159 unsigned int rx_done;
2160 u32 isr_status;
2161
2162 spin_lock(&vptr->lock);
2163 isr_status = mac_read_isr(vptr->mac_regs);
2164
2165 /* Ack the interrupt */
2166 mac_write_isr(vptr->mac_regs, isr_status);
2167 if (isr_status & (~(ISR_PRXI | ISR_PPRXI | ISR_PTXI | ISR_PPTXI)))
2168 velocity_error(vptr, isr_status);
2169
2170 /*
2171 * Do rx and tx twice for performance (taken from the VIA
2172 * out-of-tree driver).
2173 */
2174 rx_done = velocity_rx_srv(vptr, isr_status, budget / 2);
2175 velocity_tx_srv(vptr, isr_status);
2176 rx_done += velocity_rx_srv(vptr, isr_status, budget - rx_done);
2177 velocity_tx_srv(vptr, isr_status);
2178
2179 spin_unlock(&vptr->lock);
2180
2181 /* If budget not fully consumed, exit the polling mode */
2182 if (rx_done < budget) {
2183 napi_complete(napi);
2184 mac_enable_int(vptr->mac_regs);
2185 }
2186
2187 return rx_done;
2188}
2160 2189
2161/** 2190/**
2162 * velocity_intr - interrupt callback 2191 * velocity_intr - interrupt callback
@@ -2173,8 +2202,6 @@ static irqreturn_t velocity_intr(int irq, void *dev_instance)
2173 struct net_device *dev = dev_instance; 2202 struct net_device *dev = dev_instance;
2174 struct velocity_info *vptr = netdev_priv(dev); 2203 struct velocity_info *vptr = netdev_priv(dev);
2175 u32 isr_status; 2204 u32 isr_status;
2176 int max_count = 0;
2177
2178 2205
2179 spin_lock(&vptr->lock); 2206 spin_lock(&vptr->lock);
2180 isr_status = mac_read_isr(vptr->mac_regs); 2207 isr_status = mac_read_isr(vptr->mac_regs);
@@ -2185,32 +2212,13 @@ static irqreturn_t velocity_intr(int irq, void *dev_instance)
2185 return IRQ_NONE; 2212 return IRQ_NONE;
2186 } 2213 }
2187 2214
2188 mac_disable_int(vptr->mac_regs); 2215 if (likely(napi_schedule_prep(&vptr->napi))) {
2189 2216 mac_disable_int(vptr->mac_regs);
2190 /* 2217 __napi_schedule(&vptr->napi);
2191 * Keep processing the ISR until we have completed
2192 * processing and the isr_status becomes zero
2193 */
2194
2195 while (isr_status != 0) {
2196 mac_write_isr(vptr->mac_regs, isr_status);
2197 if (isr_status & (~(ISR_PRXI | ISR_PPRXI | ISR_PTXI | ISR_PPTXI)))
2198 velocity_error(vptr, isr_status);
2199 if (isr_status & (ISR_PRXI | ISR_PPRXI))
2200 max_count += velocity_rx_srv(vptr, isr_status);
2201 if (isr_status & (ISR_PTXI | ISR_PPTXI))
2202 max_count += velocity_tx_srv(vptr, isr_status);
2203 isr_status = mac_read_isr(vptr->mac_regs);
2204 if (max_count > vptr->options.int_works) {
2205 printk(KERN_WARNING "%s: excessive work at interrupt.\n",
2206 dev->name);
2207 max_count = 0;
2208 }
2209 } 2218 }
2210 spin_unlock(&vptr->lock); 2219 spin_unlock(&vptr->lock);
2211 mac_enable_int(vptr->mac_regs);
2212 return IRQ_HANDLED;
2213 2220
2221 return IRQ_HANDLED;
2214} 2222}
2215 2223
2216/** 2224/**
@@ -2250,6 +2258,7 @@ static int velocity_open(struct net_device *dev)
2250 2258
2251 mac_enable_int(vptr->mac_regs); 2259 mac_enable_int(vptr->mac_regs);
2252 netif_start_queue(dev); 2260 netif_start_queue(dev);
2261 napi_enable(&vptr->napi);
2253 vptr->flags |= VELOCITY_FLAGS_OPENED; 2262 vptr->flags |= VELOCITY_FLAGS_OPENED;
2254out: 2263out:
2255 return ret; 2264 return ret;
@@ -2485,6 +2494,7 @@ static int velocity_close(struct net_device *dev)
2485{ 2494{
2486 struct velocity_info *vptr = netdev_priv(dev); 2495 struct velocity_info *vptr = netdev_priv(dev);
2487 2496
2497 napi_disable(&vptr->napi);
2488 netif_stop_queue(dev); 2498 netif_stop_queue(dev);
2489 velocity_shutdown(vptr); 2499 velocity_shutdown(vptr);
2490 2500
@@ -2803,6 +2813,7 @@ static int __devinit velocity_found1(struct pci_dev *pdev, const struct pci_devi
2803 dev->irq = pdev->irq; 2813 dev->irq = pdev->irq;
2804 dev->netdev_ops = &velocity_netdev_ops; 2814 dev->netdev_ops = &velocity_netdev_ops;
2805 dev->ethtool_ops = &velocity_ethtool_ops; 2815 dev->ethtool_ops = &velocity_ethtool_ops;
2816 netif_napi_add(dev, &vptr->napi, velocity_poll, VELOCITY_NAPI_WEIGHT);
2806 2817
2807 dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_FILTER | 2818 dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_FILTER |
2808 NETIF_F_HW_VLAN_RX; 2819 NETIF_F_HW_VLAN_RX;
diff --git a/drivers/net/via-velocity.h b/drivers/net/via-velocity.h
index 499da64773ee..d37a30329312 100644
--- a/drivers/net/via-velocity.h
+++ b/drivers/net/via-velocity.h
@@ -32,6 +32,7 @@
32#define VELOCITY_VERSION "1.14" 32#define VELOCITY_VERSION "1.14"
33 33
34#define VELOCITY_IO_SIZE 256 34#define VELOCITY_IO_SIZE 256
35#define VELOCITY_NAPI_WEIGHT 64
35 36
36#define PKT_BUF_SZ 1540 37#define PKT_BUF_SZ 1540
37 38
@@ -1562,6 +1563,8 @@ struct velocity_info {
1562 u32 ticks; 1563 u32 ticks;
1563 1564
1564 u8 rev_id; 1565 u8 rev_id;
1566
1567 struct napi_struct napi;
1565}; 1568};
1566 1569
1567/** 1570/**