diff options
author | Simon Kagstrom <simon.kagstrom@netinsight.net> | 2009-11-25 17:10:26 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-11-26 18:51:15 -0500 |
commit | dfff7144b14bab3d8baaeba8926fab371fa4a01e (patch) | |
tree | d876204977e50bd7091f334614bdf0b2c2f7982b /drivers/net | |
parent | 6dfc4b95b29d89dbdb45de04b1b1ff493ec8016d (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/net')
-rw-r--r-- | drivers/net/via-velocity.c | 81 | ||||
-rw-r--r-- | drivers/net/via-velocity.h | 3 |
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 | */ |
355 | VELOCITY_PARAM(wol_opts, "Wake On Lan options"); | 355 | VELOCITY_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 | |||
361 | VELOCITY_PARAM(int_works, "Number of packets per interrupt services"); | ||
362 | |||
363 | static int rx_copybreak = 200; | 357 | static int rx_copybreak = 200; |
364 | module_param(rx_copybreak, int, 0644); | 358 | module_param(rx_copybreak, int, 0644); |
365 | MODULE_PARM_DESC(rx_copybreak, "Copy breakpoint for copy-only-tiny-frames"); | 359 | MODULE_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 | */ |
2112 | static int velocity_rx_srv(struct velocity_info *vptr, int status) | 2105 | static 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 | ||
2155 | static 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; |
2254 | out: | 2263 | out: |
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 | /** |