aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ixp2000/ixpdev.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/ixp2000/ixpdev.c')
-rw-r--r--drivers/net/ixp2000/ixpdev.c39
1 files changed, 25 insertions, 14 deletions
diff --git a/drivers/net/ixp2000/ixpdev.c b/drivers/net/ixp2000/ixpdev.c
index d9ce1aef148a..6c0dd49149d0 100644
--- a/drivers/net/ixp2000/ixpdev.c
+++ b/drivers/net/ixp2000/ixpdev.c
@@ -74,9 +74,9 @@ static int ixpdev_xmit(struct sk_buff *skb, struct net_device *dev)
74} 74}
75 75
76 76
77static int ixpdev_rx(struct net_device *dev, int *budget) 77static int ixpdev_rx(struct net_device *dev, int processed, int budget)
78{ 78{
79 while (*budget > 0) { 79 while (processed < budget) {
80 struct ixpdev_rx_desc *desc; 80 struct ixpdev_rx_desc *desc;
81 struct sk_buff *skb; 81 struct sk_buff *skb;
82 void *buf; 82 void *buf;
@@ -122,29 +122,34 @@ static int ixpdev_rx(struct net_device *dev, int *budget)
122 122
123err: 123err:
124 ixp2000_reg_write(RING_RX_PENDING, _desc); 124 ixp2000_reg_write(RING_RX_PENDING, _desc);
125 dev->quota--; 125 processed++;
126 (*budget)--;
127 } 126 }
128 127
129 return 1; 128 return processed;
130} 129}
131 130
132/* dev always points to nds[0]. */ 131/* dev always points to nds[0]. */
133static int ixpdev_poll(struct net_device *dev, int *budget) 132static int ixpdev_poll(struct napi_struct *napi, int budget)
134{ 133{
134 struct ixpdev_priv *ip = container_of(napi, struct ixpdev_priv, napi);
135 struct net_device *dev = ip->dev;
136 int rx;
137
135 /* @@@ Have to stop polling when nds[0] is administratively 138 /* @@@ Have to stop polling when nds[0] is administratively
136 * downed while we are polling. */ 139 * downed while we are polling. */
140 rx = 0;
137 do { 141 do {
138 ixp2000_reg_write(IXP2000_IRQ_THD_RAW_STATUS_A_0, 0x00ff); 142 ixp2000_reg_write(IXP2000_IRQ_THD_RAW_STATUS_A_0, 0x00ff);
139 143
140 if (ixpdev_rx(dev, budget)) 144 rx = ixpdev_rx(dev, rx, budget);
141 return 1; 145 if (rx >= budget)
146 break;
142 } while (ixp2000_reg_read(IXP2000_IRQ_THD_RAW_STATUS_A_0) & 0x00ff); 147 } while (ixp2000_reg_read(IXP2000_IRQ_THD_RAW_STATUS_A_0) & 0x00ff);
143 148
144 netif_rx_complete(dev); 149 netif_rx_complete(dev, napi);
145 ixp2000_reg_write(IXP2000_IRQ_THD_ENABLE_SET_A_0, 0x00ff); 150 ixp2000_reg_write(IXP2000_IRQ_THD_ENABLE_SET_A_0, 0x00ff);
146 151
147 return 0; 152 return rx;
148} 153}
149 154
150static void ixpdev_tx_complete(void) 155static void ixpdev_tx_complete(void)
@@ -199,9 +204,12 @@ static irqreturn_t ixpdev_interrupt(int irq, void *dev_id)
199 * Any of the eight receive units signaled RX? 204 * Any of the eight receive units signaled RX?
200 */ 205 */
201 if (status & 0x00ff) { 206 if (status & 0x00ff) {
207 struct net_device *dev = nds[0];
208 struct ixpdev_priv *ip = netdev_priv(dev);
209
202 ixp2000_reg_wrb(IXP2000_IRQ_THD_ENABLE_CLEAR_A_0, 0x00ff); 210 ixp2000_reg_wrb(IXP2000_IRQ_THD_ENABLE_CLEAR_A_0, 0x00ff);
203 if (likely(__netif_rx_schedule_prep(nds[0]))) { 211 if (likely(napi_schedule_prep(&ip->napi))) {
204 __netif_rx_schedule(nds[0]); 212 __netif_rx_schedule(dev, &ip->napi);
205 } else { 213 } else {
206 printk(KERN_CRIT "ixp2000: irq while polling!!\n"); 214 printk(KERN_CRIT "ixp2000: irq while polling!!\n");
207 } 215 }
@@ -232,11 +240,13 @@ static int ixpdev_open(struct net_device *dev)
232 struct ixpdev_priv *ip = netdev_priv(dev); 240 struct ixpdev_priv *ip = netdev_priv(dev);
233 int err; 241 int err;
234 242
243 napi_enable(&ip->napi);
235 if (!nds_open++) { 244 if (!nds_open++) {
236 err = request_irq(IRQ_IXP2000_THDA0, ixpdev_interrupt, 245 err = request_irq(IRQ_IXP2000_THDA0, ixpdev_interrupt,
237 IRQF_SHARED, "ixp2000_eth", nds); 246 IRQF_SHARED, "ixp2000_eth", nds);
238 if (err) { 247 if (err) {
239 nds_open--; 248 nds_open--;
249 napi_disable(&ip->napi);
240 return err; 250 return err;
241 } 251 }
242 252
@@ -254,6 +264,7 @@ static int ixpdev_close(struct net_device *dev)
254 struct ixpdev_priv *ip = netdev_priv(dev); 264 struct ixpdev_priv *ip = netdev_priv(dev);
255 265
256 netif_stop_queue(dev); 266 netif_stop_queue(dev);
267 napi_disable(&ip->napi);
257 set_port_admin_status(ip->channel, 0); 268 set_port_admin_status(ip->channel, 0);
258 269
259 if (!--nds_open) { 270 if (!--nds_open) {
@@ -274,7 +285,6 @@ struct net_device *ixpdev_alloc(int channel, int sizeof_priv)
274 return NULL; 285 return NULL;
275 286
276 dev->hard_start_xmit = ixpdev_xmit; 287 dev->hard_start_xmit = ixpdev_xmit;
277 dev->poll = ixpdev_poll;
278 dev->open = ixpdev_open; 288 dev->open = ixpdev_open;
279 dev->stop = ixpdev_close; 289 dev->stop = ixpdev_close;
280#ifdef CONFIG_NET_POLL_CONTROLLER 290#ifdef CONFIG_NET_POLL_CONTROLLER
@@ -282,9 +292,10 @@ struct net_device *ixpdev_alloc(int channel, int sizeof_priv)
282#endif 292#endif
283 293
284 dev->features |= NETIF_F_SG | NETIF_F_HW_CSUM; 294 dev->features |= NETIF_F_SG | NETIF_F_HW_CSUM;
285 dev->weight = 64;
286 295
287 ip = netdev_priv(dev); 296 ip = netdev_priv(dev);
297 ip->dev = dev;
298 netif_napi_add(dev, &ip->napi, ixpdev_poll, 64);
288 ip->channel = channel; 299 ip->channel = channel;
289 ip->tx_queue_entries = 0; 300 ip->tx_queue_entries = 0;
290 301