aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/arm/ep93xx_eth.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/arm/ep93xx_eth.c')
-rw-r--r--drivers/net/arm/ep93xx_eth.c72
1 files changed, 34 insertions, 38 deletions
diff --git a/drivers/net/arm/ep93xx_eth.c b/drivers/net/arm/ep93xx_eth.c
index f6ece1d43f6e..7f016f3d5bf0 100644
--- a/drivers/net/arm/ep93xx_eth.c
+++ b/drivers/net/arm/ep93xx_eth.c
@@ -169,6 +169,9 @@ struct ep93xx_priv
169 spinlock_t tx_pending_lock; 169 spinlock_t tx_pending_lock;
170 unsigned int tx_pending; 170 unsigned int tx_pending;
171 171
172 struct net_device *dev;
173 struct napi_struct napi;
174
172 struct net_device_stats stats; 175 struct net_device_stats stats;
173 176
174 struct mii_if_info mii; 177 struct mii_if_info mii;
@@ -190,15 +193,11 @@ static struct net_device_stats *ep93xx_get_stats(struct net_device *dev)
190 return &(ep->stats); 193 return &(ep->stats);
191} 194}
192 195
193static int ep93xx_rx(struct net_device *dev, int *budget) 196static int ep93xx_rx(struct net_device *dev, int processed, int budget)
194{ 197{
195 struct ep93xx_priv *ep = netdev_priv(dev); 198 struct ep93xx_priv *ep = netdev_priv(dev);
196 int rx_done;
197 int processed;
198 199
199 rx_done = 0; 200 while (processed < budget) {
200 processed = 0;
201 while (*budget > 0) {
202 int entry; 201 int entry;
203 struct ep93xx_rstat *rstat; 202 struct ep93xx_rstat *rstat;
204 u32 rstat0; 203 u32 rstat0;
@@ -211,10 +210,8 @@ static int ep93xx_rx(struct net_device *dev, int *budget)
211 210
212 rstat0 = rstat->rstat0; 211 rstat0 = rstat->rstat0;
213 rstat1 = rstat->rstat1; 212 rstat1 = rstat->rstat1;
214 if (!(rstat0 & RSTAT0_RFP) || !(rstat1 & RSTAT1_RFP)) { 213 if (!(rstat0 & RSTAT0_RFP) || !(rstat1 & RSTAT1_RFP))
215 rx_done = 1;
216 break; 214 break;
217 }
218 215
219 rstat->rstat0 = 0; 216 rstat->rstat0 = 0;
220 rstat->rstat1 = 0; 217 rstat->rstat1 = 0;
@@ -275,8 +272,6 @@ static int ep93xx_rx(struct net_device *dev, int *budget)
275err: 272err:
276 ep->rx_pointer = (entry + 1) & (RX_QUEUE_ENTRIES - 1); 273 ep->rx_pointer = (entry + 1) & (RX_QUEUE_ENTRIES - 1);
277 processed++; 274 processed++;
278 dev->quota--;
279 (*budget)--;
280 } 275 }
281 276
282 if (processed) { 277 if (processed) {
@@ -284,7 +279,7 @@ err:
284 wrw(ep, REG_RXSTSENQ, processed); 279 wrw(ep, REG_RXSTSENQ, processed);
285 } 280 }
286 281
287 return !rx_done; 282 return processed;
288} 283}
289 284
290static int ep93xx_have_more_rx(struct ep93xx_priv *ep) 285static int ep93xx_have_more_rx(struct ep93xx_priv *ep)
@@ -293,36 +288,32 @@ static int ep93xx_have_more_rx(struct ep93xx_priv *ep)
293 return !!((rstat->rstat0 & RSTAT0_RFP) && (rstat->rstat1 & RSTAT1_RFP)); 288 return !!((rstat->rstat0 & RSTAT0_RFP) && (rstat->rstat1 & RSTAT1_RFP));
294} 289}
295 290
296static int ep93xx_poll(struct net_device *dev, int *budget) 291static int ep93xx_poll(struct napi_struct *napi, int budget)
297{ 292{
298 struct ep93xx_priv *ep = netdev_priv(dev); 293 struct ep93xx_priv *ep = container_of(napi, struct ep93xx_priv, napi);
299 294 struct net_device *dev = ep->dev;
300 /* 295 int rx = 0;
301 * @@@ Have to stop polling if device is downed while we
302 * are polling.
303 */
304 296
305poll_some_more: 297poll_some_more:
306 if (ep93xx_rx(dev, budget)) 298 rx = ep93xx_rx(dev, rx, budget);
307 return 1; 299 if (rx < budget) {
308 300 int more = 0;
309 netif_rx_complete(dev); 301
310 302 spin_lock_irq(&ep->rx_lock);
311 spin_lock_irq(&ep->rx_lock); 303 __netif_rx_complete(dev, napi);
312 wrl(ep, REG_INTEN, REG_INTEN_TX | REG_INTEN_RX); 304 wrl(ep, REG_INTEN, REG_INTEN_TX | REG_INTEN_RX);
313 if (ep93xx_have_more_rx(ep)) { 305 if (ep93xx_have_more_rx(ep)) {
314 wrl(ep, REG_INTEN, REG_INTEN_TX); 306 wrl(ep, REG_INTEN, REG_INTEN_TX);
315 wrl(ep, REG_INTSTSP, REG_INTSTS_RX); 307 wrl(ep, REG_INTSTSP, REG_INTSTS_RX);
308 more = 1;
309 }
316 spin_unlock_irq(&ep->rx_lock); 310 spin_unlock_irq(&ep->rx_lock);
317 311
318 if (netif_rx_reschedule(dev, 0)) 312 if (more && netif_rx_reschedule(dev, napi))
319 goto poll_some_more; 313 goto poll_some_more;
320
321 return 0;
322 } 314 }
323 spin_unlock_irq(&ep->rx_lock);
324 315
325 return 0; 316 return rx;
326} 317}
327 318
328static int ep93xx_xmit(struct sk_buff *skb, struct net_device *dev) 319static int ep93xx_xmit(struct sk_buff *skb, struct net_device *dev)
@@ -426,9 +417,9 @@ static irqreturn_t ep93xx_irq(int irq, void *dev_id)
426 417
427 if (status & REG_INTSTS_RX) { 418 if (status & REG_INTSTS_RX) {
428 spin_lock(&ep->rx_lock); 419 spin_lock(&ep->rx_lock);
429 if (likely(__netif_rx_schedule_prep(dev))) { 420 if (likely(__netif_rx_schedule_prep(dev, &ep->napi))) {
430 wrl(ep, REG_INTEN, REG_INTEN_TX); 421 wrl(ep, REG_INTEN, REG_INTEN_TX);
431 __netif_rx_schedule(dev); 422 __netif_rx_schedule(dev, &ep->napi);
432 } 423 }
433 spin_unlock(&ep->rx_lock); 424 spin_unlock(&ep->rx_lock);
434 } 425 }
@@ -648,7 +639,10 @@ static int ep93xx_open(struct net_device *dev)
648 dev->dev_addr[4], dev->dev_addr[5]); 639 dev->dev_addr[4], dev->dev_addr[5]);
649 } 640 }
650 641
642 napi_enable(&ep->napi);
643
651 if (ep93xx_start_hw(dev)) { 644 if (ep93xx_start_hw(dev)) {
645 napi_disable(&ep->napi);
652 ep93xx_free_buffers(ep); 646 ep93xx_free_buffers(ep);
653 return -EIO; 647 return -EIO;
654 } 648 }
@@ -662,6 +656,7 @@ static int ep93xx_open(struct net_device *dev)
662 656
663 err = request_irq(ep->irq, ep93xx_irq, IRQF_SHARED, dev->name, dev); 657 err = request_irq(ep->irq, ep93xx_irq, IRQF_SHARED, dev->name, dev);
664 if (err) { 658 if (err) {
659 napi_disable(&ep->napi);
665 ep93xx_stop_hw(dev); 660 ep93xx_stop_hw(dev);
666 ep93xx_free_buffers(ep); 661 ep93xx_free_buffers(ep);
667 return err; 662 return err;
@@ -678,6 +673,7 @@ static int ep93xx_close(struct net_device *dev)
678{ 673{
679 struct ep93xx_priv *ep = netdev_priv(dev); 674 struct ep93xx_priv *ep = netdev_priv(dev);
680 675
676 napi_disable(&ep->napi);
681 netif_stop_queue(dev); 677 netif_stop_queue(dev);
682 678
683 wrl(ep, REG_GIINTMSK, 0); 679 wrl(ep, REG_GIINTMSK, 0);
@@ -788,14 +784,12 @@ struct net_device *ep93xx_dev_alloc(struct ep93xx_eth_data *data)
788 784
789 dev->get_stats = ep93xx_get_stats; 785 dev->get_stats = ep93xx_get_stats;
790 dev->ethtool_ops = &ep93xx_ethtool_ops; 786 dev->ethtool_ops = &ep93xx_ethtool_ops;
791 dev->poll = ep93xx_poll;
792 dev->hard_start_xmit = ep93xx_xmit; 787 dev->hard_start_xmit = ep93xx_xmit;
793 dev->open = ep93xx_open; 788 dev->open = ep93xx_open;
794 dev->stop = ep93xx_close; 789 dev->stop = ep93xx_close;
795 dev->do_ioctl = ep93xx_ioctl; 790 dev->do_ioctl = ep93xx_ioctl;
796 791
797 dev->features |= NETIF_F_SG | NETIF_F_HW_CSUM; 792 dev->features |= NETIF_F_SG | NETIF_F_HW_CSUM;
798 dev->weight = 64;
799 793
800 return dev; 794 return dev;
801} 795}
@@ -847,6 +841,8 @@ static int ep93xx_eth_probe(struct platform_device *pdev)
847 goto err_out; 841 goto err_out;
848 } 842 }
849 ep = netdev_priv(dev); 843 ep = netdev_priv(dev);
844 ep->dev = dev;
845 netif_napi_add(dev, &ep->napi, ep93xx_poll, 64);
850 846
851 platform_set_drvdata(pdev, dev); 847 platform_set_drvdata(pdev, dev);
852 848