提交 bea3348e 编写于 作者: S Stephen Hemminger 提交者: David S. Miller

[NET]: Make NAPI polling independent of struct net_device objects.

Several devices have multiple independant RX queues per net
device, and some have a single interrupt doorbell for several
queues.

In either case, it's easier to support layouts like that if the
structure representing the poll is independant from the net
device itself.

The signature of the ->poll() call back goes from:

	int foo_poll(struct net_device *dev, int *budget)

to

	int foo_poll(struct napi_struct *napi, int budget)

The caller is returned the number of RX packets processed (or
the number of "NAPI credits" consumed if you want to get
abstract).  The callee no longer messes around bumping
dev->quota, *budget, etc. because that is all handled in the
caller upon return.

The napi_struct is to be embedded in the device driver private data
structures.

Furthermore, it is the driver's responsibility to disable all NAPI
instances in it's ->stop() device close handler.  Since the
napi_struct is privatized into the driver's private data structures,
only the driver knows how to get at all of the napi_struct instances
it may have per-device.

With lots of help and suggestions from Rusty Russell, Roland Dreier,
Michael Chan, Jeff Garzik, and Jamal Hadi Salim.

Bug fixes from Thomas Graf, Roland Dreier, Peter Zijlstra,
Joseph Fannin, Scott Wood, Hans J. Koch, and Michael Chan.

[ Ported to current tree and all drivers converted.  Integrated
  Stephen's follow-on kerneldoc additions, and restored poll_list
  handling to the old style to fix mutual exclusion issues.  -DaveM ]
Signed-off-by: NStephen Hemminger <shemminger@linux-foundation.org>
Signed-off-by: NDavid S. Miller <davem@davemloft.net>
上级 dde4e47e
...@@ -240,17 +240,23 @@ X!Ilib/string.c ...@@ -240,17 +240,23 @@ X!Ilib/string.c
<sect1><title>Driver Support</title> <sect1><title>Driver Support</title>
!Enet/core/dev.c !Enet/core/dev.c
!Enet/ethernet/eth.c !Enet/ethernet/eth.c
!Enet/sched/sch_generic.c
!Iinclude/linux/etherdevice.h !Iinclude/linux/etherdevice.h
!Iinclude/linux/netdevice.h
</sect1>
<sect1><title>PHY Support</title>
!Edrivers/net/phy/phy.c !Edrivers/net/phy/phy.c
!Idrivers/net/phy/phy.c !Idrivers/net/phy/phy.c
!Edrivers/net/phy/phy_device.c !Edrivers/net/phy/phy_device.c
!Idrivers/net/phy/phy_device.c !Idrivers/net/phy/phy_device.c
!Edrivers/net/phy/mdio_bus.c !Edrivers/net/phy/mdio_bus.c
!Idrivers/net/phy/mdio_bus.c !Idrivers/net/phy/mdio_bus.c
</sect1>
<!-- FIXME: Removed for now since no structured comments in source <!-- FIXME: Removed for now since no structured comments in source
<sect1><title>Wireless</title>
X!Enet/core/wireless.c X!Enet/core/wireless.c
-->
</sect1> </sect1>
-->
<sect1><title>Synchronous PPP</title> <sect1><title>Synchronous PPP</title>
!Edrivers/net/wan/syncppp.c !Edrivers/net/wan/syncppp.c
</sect1> </sect1>
......
此差异已折叠。
...@@ -95,9 +95,13 @@ dev->set_multicast_list: ...@@ -95,9 +95,13 @@ dev->set_multicast_list:
Synchronization: netif_tx_lock spinlock. Synchronization: netif_tx_lock spinlock.
Context: BHs disabled Context: BHs disabled
dev->poll: struct napi_struct synchronization rules
Synchronization: __LINK_STATE_RX_SCHED bit in dev->state. See ========================================
dev_close code and comments in net/core/dev.c for more info. napi->poll:
Synchronization: NAPI_STATE_SCHED bit in napi->state. Device
driver's dev->close method will invoke napi_disable() on
all NAPI instances which will do a sleeping poll on the
NAPI_STATE_SCHED napi->state bit, waiting for all pending
NAPI activity to cease.
Context: softirq Context: softirq
will be called with interrupts disabled by netconsole. will be called with interrupts disabled by netconsole.
...@@ -228,6 +228,8 @@ struct ipoib_dev_priv { ...@@ -228,6 +228,8 @@ struct ipoib_dev_priv {
struct net_device *dev; struct net_device *dev;
struct napi_struct napi;
unsigned long flags; unsigned long flags;
struct mutex mcast_mutex; struct mutex mcast_mutex;
...@@ -351,7 +353,7 @@ extern struct workqueue_struct *ipoib_workqueue; ...@@ -351,7 +353,7 @@ extern struct workqueue_struct *ipoib_workqueue;
/* functions */ /* functions */
int ipoib_poll(struct net_device *dev, int *budget); int ipoib_poll(struct napi_struct *napi, int budget);
void ipoib_ib_completion(struct ib_cq *cq, void *dev_ptr); void ipoib_ib_completion(struct ib_cq *cq, void *dev_ptr);
struct ipoib_ah *ipoib_create_ah(struct net_device *dev, struct ipoib_ah *ipoib_create_ah(struct net_device *dev,
......
...@@ -281,63 +281,58 @@ static void ipoib_ib_handle_tx_wc(struct net_device *dev, struct ib_wc *wc) ...@@ -281,63 +281,58 @@ static void ipoib_ib_handle_tx_wc(struct net_device *dev, struct ib_wc *wc)
wc->status, wr_id, wc->vendor_err); wc->status, wr_id, wc->vendor_err);
} }
int ipoib_poll(struct net_device *dev, int *budget) int ipoib_poll(struct napi_struct *napi, int budget)
{ {
struct ipoib_dev_priv *priv = netdev_priv(dev); struct ipoib_dev_priv *priv = container_of(napi, struct ipoib_dev_priv, napi);
int max = min(*budget, dev->quota); struct net_device *dev = priv->dev;
int done; int done;
int t; int t;
int empty;
int n, i; int n, i;
done = 0; done = 0;
empty = 0;
while (max) { poll_more:
while (done < budget) {
int max = (budget - done);
t = min(IPOIB_NUM_WC, max); t = min(IPOIB_NUM_WC, max);
n = ib_poll_cq(priv->cq, t, priv->ibwc); n = ib_poll_cq(priv->cq, t, priv->ibwc);
for (i = 0; i < n; ++i) { for (i = 0; i < n; i++) {
struct ib_wc *wc = priv->ibwc + i; struct ib_wc *wc = priv->ibwc + i;
if (wc->wr_id & IPOIB_CM_OP_SRQ) { if (wc->wr_id & IPOIB_CM_OP_SRQ) {
++done; ++done;
--max;
ipoib_cm_handle_rx_wc(dev, wc); ipoib_cm_handle_rx_wc(dev, wc);
} else if (wc->wr_id & IPOIB_OP_RECV) { } else if (wc->wr_id & IPOIB_OP_RECV) {
++done; ++done;
--max;
ipoib_ib_handle_rx_wc(dev, wc); ipoib_ib_handle_rx_wc(dev, wc);
} else } else
ipoib_ib_handle_tx_wc(dev, wc); ipoib_ib_handle_tx_wc(dev, wc);
} }
if (n != t) { if (n != t)
empty = 1;
break; break;
}
} }
dev->quota -= done; if (done < budget) {
*budget -= done; netif_rx_complete(dev, napi);
if (empty) {
netif_rx_complete(dev);
if (unlikely(ib_req_notify_cq(priv->cq, if (unlikely(ib_req_notify_cq(priv->cq,
IB_CQ_NEXT_COMP | IB_CQ_NEXT_COMP |
IB_CQ_REPORT_MISSED_EVENTS)) && IB_CQ_REPORT_MISSED_EVENTS)) &&
netif_rx_reschedule(dev, 0)) netif_rx_reschedule(dev, napi))
return 1; goto poll_more;
return 0;
} }
return 1; return done;
} }
void ipoib_ib_completion(struct ib_cq *cq, void *dev_ptr) void ipoib_ib_completion(struct ib_cq *cq, void *dev_ptr)
{ {
netif_rx_schedule(dev_ptr); struct net_device *dev = dev_ptr;
struct ipoib_dev_priv *priv = netdev_priv(dev);
netif_rx_schedule(dev, &priv->napi);
} }
static inline int post_send(struct ipoib_dev_priv *priv, static inline int post_send(struct ipoib_dev_priv *priv,
...@@ -577,7 +572,6 @@ int ipoib_ib_dev_stop(struct net_device *dev, int flush) ...@@ -577,7 +572,6 @@ int ipoib_ib_dev_stop(struct net_device *dev, int flush)
int i; int i;
clear_bit(IPOIB_FLAG_INITIALIZED, &priv->flags); clear_bit(IPOIB_FLAG_INITIALIZED, &priv->flags);
netif_poll_disable(dev);
ipoib_cm_dev_stop(dev); ipoib_cm_dev_stop(dev);
...@@ -660,7 +654,6 @@ int ipoib_ib_dev_stop(struct net_device *dev, int flush) ...@@ -660,7 +654,6 @@ int ipoib_ib_dev_stop(struct net_device *dev, int flush)
msleep(1); msleep(1);
} }
netif_poll_enable(dev);
ib_req_notify_cq(priv->cq, IB_CQ_NEXT_COMP); ib_req_notify_cq(priv->cq, IB_CQ_NEXT_COMP);
return 0; return 0;
......
...@@ -98,16 +98,20 @@ int ipoib_open(struct net_device *dev) ...@@ -98,16 +98,20 @@ int ipoib_open(struct net_device *dev)
ipoib_dbg(priv, "bringing up interface\n"); ipoib_dbg(priv, "bringing up interface\n");
napi_enable(&priv->napi);
set_bit(IPOIB_FLAG_ADMIN_UP, &priv->flags); set_bit(IPOIB_FLAG_ADMIN_UP, &priv->flags);
if (ipoib_pkey_dev_delay_open(dev)) if (ipoib_pkey_dev_delay_open(dev))
return 0; return 0;
if (ipoib_ib_dev_open(dev)) if (ipoib_ib_dev_open(dev)) {
napi_disable(&priv->napi);
return -EINVAL; return -EINVAL;
}
if (ipoib_ib_dev_up(dev)) { if (ipoib_ib_dev_up(dev)) {
ipoib_ib_dev_stop(dev, 1); ipoib_ib_dev_stop(dev, 1);
napi_disable(&priv->napi);
return -EINVAL; return -EINVAL;
} }
...@@ -140,6 +144,7 @@ static int ipoib_stop(struct net_device *dev) ...@@ -140,6 +144,7 @@ static int ipoib_stop(struct net_device *dev)
ipoib_dbg(priv, "stopping interface\n"); ipoib_dbg(priv, "stopping interface\n");
clear_bit(IPOIB_FLAG_ADMIN_UP, &priv->flags); clear_bit(IPOIB_FLAG_ADMIN_UP, &priv->flags);
napi_disable(&priv->napi);
netif_stop_queue(dev); netif_stop_queue(dev);
...@@ -948,8 +953,8 @@ static void ipoib_setup(struct net_device *dev) ...@@ -948,8 +953,8 @@ static void ipoib_setup(struct net_device *dev)
dev->hard_header = ipoib_hard_header; dev->hard_header = ipoib_hard_header;
dev->set_multicast_list = ipoib_set_mcast_list; dev->set_multicast_list = ipoib_set_mcast_list;
dev->neigh_setup = ipoib_neigh_setup_dev; dev->neigh_setup = ipoib_neigh_setup_dev;
dev->poll = ipoib_poll;
dev->weight = 100; netif_napi_add(dev, &priv->napi, ipoib_poll, 100);
dev->watchdog_timeo = HZ; dev->watchdog_timeo = HZ;
......
...@@ -334,6 +334,8 @@ struct cp_private { ...@@ -334,6 +334,8 @@ struct cp_private {
spinlock_t lock; spinlock_t lock;
u32 msg_enable; u32 msg_enable;
struct napi_struct napi;
struct pci_dev *pdev; struct pci_dev *pdev;
u32 rx_config; u32 rx_config;
u16 cpcmd; u16 cpcmd;
...@@ -501,12 +503,12 @@ static inline unsigned int cp_rx_csum_ok (u32 status) ...@@ -501,12 +503,12 @@ static inline unsigned int cp_rx_csum_ok (u32 status)
return 0; return 0;
} }
static int cp_rx_poll (struct net_device *dev, int *budget) static int cp_rx_poll(struct napi_struct *napi, int budget)
{ {
struct cp_private *cp = netdev_priv(dev); struct cp_private *cp = container_of(napi, struct cp_private, napi);
unsigned rx_tail = cp->rx_tail; struct net_device *dev = cp->dev;
unsigned rx_work = dev->quota; unsigned int rx_tail = cp->rx_tail;
unsigned rx; int rx;
rx_status_loop: rx_status_loop:
rx = 0; rx = 0;
...@@ -588,33 +590,28 @@ static int cp_rx_poll (struct net_device *dev, int *budget) ...@@ -588,33 +590,28 @@ static int cp_rx_poll (struct net_device *dev, int *budget)
desc->opts1 = cpu_to_le32(DescOwn | cp->rx_buf_sz); desc->opts1 = cpu_to_le32(DescOwn | cp->rx_buf_sz);
rx_tail = NEXT_RX(rx_tail); rx_tail = NEXT_RX(rx_tail);
if (!rx_work--) if (rx >= budget)
break; break;
} }
cp->rx_tail = rx_tail; cp->rx_tail = rx_tail;
dev->quota -= rx;
*budget -= rx;
/* if we did not reach work limit, then we're done with /* if we did not reach work limit, then we're done with
* this round of polling * this round of polling
*/ */
if (rx_work) { if (rx < budget) {
unsigned long flags; unsigned long flags;
if (cpr16(IntrStatus) & cp_rx_intr_mask) if (cpr16(IntrStatus) & cp_rx_intr_mask)
goto rx_status_loop; goto rx_status_loop;
local_irq_save(flags); spin_lock_irqsave(&cp->lock, flags);
cpw16_f(IntrMask, cp_intr_mask); cpw16_f(IntrMask, cp_intr_mask);
__netif_rx_complete(dev); __netif_rx_complete(dev, napi);
local_irq_restore(flags); spin_unlock_irqrestore(&cp->lock, flags);
return 0; /* done */
} }
return 1; /* not done */ return rx;
} }
static irqreturn_t cp_interrupt (int irq, void *dev_instance) static irqreturn_t cp_interrupt (int irq, void *dev_instance)
...@@ -647,9 +644,9 @@ static irqreturn_t cp_interrupt (int irq, void *dev_instance) ...@@ -647,9 +644,9 @@ static irqreturn_t cp_interrupt (int irq, void *dev_instance)
} }
if (status & (RxOK | RxErr | RxEmpty | RxFIFOOvr)) if (status & (RxOK | RxErr | RxEmpty | RxFIFOOvr))
if (netif_rx_schedule_prep(dev)) { if (netif_rx_schedule_prep(dev, &cp->napi)) {
cpw16_f(IntrMask, cp_norx_intr_mask); cpw16_f(IntrMask, cp_norx_intr_mask);
__netif_rx_schedule(dev); __netif_rx_schedule(dev, &cp->napi);
} }
if (status & (TxOK | TxErr | TxEmpty | SWInt)) if (status & (TxOK | TxErr | TxEmpty | SWInt))
...@@ -1175,6 +1172,8 @@ static int cp_open (struct net_device *dev) ...@@ -1175,6 +1172,8 @@ static int cp_open (struct net_device *dev)
if (rc) if (rc)
return rc; return rc;
napi_enable(&cp->napi);
cp_init_hw(cp); cp_init_hw(cp);
rc = request_irq(dev->irq, cp_interrupt, IRQF_SHARED, dev->name, dev); rc = request_irq(dev->irq, cp_interrupt, IRQF_SHARED, dev->name, dev);
...@@ -1188,6 +1187,7 @@ static int cp_open (struct net_device *dev) ...@@ -1188,6 +1187,7 @@ static int cp_open (struct net_device *dev)
return 0; return 0;
err_out_hw: err_out_hw:
napi_disable(&cp->napi);
cp_stop_hw(cp); cp_stop_hw(cp);
cp_free_rings(cp); cp_free_rings(cp);
return rc; return rc;
...@@ -1198,6 +1198,8 @@ static int cp_close (struct net_device *dev) ...@@ -1198,6 +1198,8 @@ static int cp_close (struct net_device *dev)
struct cp_private *cp = netdev_priv(dev); struct cp_private *cp = netdev_priv(dev);
unsigned long flags; unsigned long flags;
napi_disable(&cp->napi);
if (netif_msg_ifdown(cp)) if (netif_msg_ifdown(cp))
printk(KERN_DEBUG "%s: disabling interface\n", dev->name); printk(KERN_DEBUG "%s: disabling interface\n", dev->name);
...@@ -1933,11 +1935,10 @@ static int cp_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -1933,11 +1935,10 @@ static int cp_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
dev->hard_start_xmit = cp_start_xmit; dev->hard_start_xmit = cp_start_xmit;
dev->get_stats = cp_get_stats; dev->get_stats = cp_get_stats;
dev->do_ioctl = cp_ioctl; dev->do_ioctl = cp_ioctl;
dev->poll = cp_rx_poll;
#ifdef CONFIG_NET_POLL_CONTROLLER #ifdef CONFIG_NET_POLL_CONTROLLER
dev->poll_controller = cp_poll_controller; dev->poll_controller = cp_poll_controller;
#endif #endif
dev->weight = 16; /* arbitrary? from NAPI_HOWTO.txt. */ netif_napi_add(dev, &cp->napi, cp_rx_poll, 16);
#ifdef BROKEN #ifdef BROKEN
dev->change_mtu = cp_change_mtu; dev->change_mtu = cp_change_mtu;
#endif #endif
......
...@@ -573,6 +573,8 @@ struct rtl8139_private { ...@@ -573,6 +573,8 @@ struct rtl8139_private {
int drv_flags; int drv_flags;
struct pci_dev *pci_dev; struct pci_dev *pci_dev;
u32 msg_enable; u32 msg_enable;
struct napi_struct napi;
struct net_device *dev;
struct net_device_stats stats; struct net_device_stats stats;
unsigned char *rx_ring; unsigned char *rx_ring;
unsigned int cur_rx; /* Index into the Rx buffer of next Rx pkt. */ unsigned int cur_rx; /* Index into the Rx buffer of next Rx pkt. */
...@@ -625,10 +627,10 @@ static void rtl8139_tx_timeout (struct net_device *dev); ...@@ -625,10 +627,10 @@ static void rtl8139_tx_timeout (struct net_device *dev);
static void rtl8139_init_ring (struct net_device *dev); static void rtl8139_init_ring (struct net_device *dev);
static int rtl8139_start_xmit (struct sk_buff *skb, static int rtl8139_start_xmit (struct sk_buff *skb,
struct net_device *dev); struct net_device *dev);
static int rtl8139_poll(struct net_device *dev, int *budget);
#ifdef CONFIG_NET_POLL_CONTROLLER #ifdef CONFIG_NET_POLL_CONTROLLER
static void rtl8139_poll_controller(struct net_device *dev); static void rtl8139_poll_controller(struct net_device *dev);
#endif #endif
static int rtl8139_poll(struct napi_struct *napi, int budget);
static irqreturn_t rtl8139_interrupt (int irq, void *dev_instance); static irqreturn_t rtl8139_interrupt (int irq, void *dev_instance);
static int rtl8139_close (struct net_device *dev); static int rtl8139_close (struct net_device *dev);
static int netdev_ioctl (struct net_device *dev, struct ifreq *rq, int cmd); static int netdev_ioctl (struct net_device *dev, struct ifreq *rq, int cmd);
...@@ -963,6 +965,7 @@ static int __devinit rtl8139_init_one (struct pci_dev *pdev, ...@@ -963,6 +965,7 @@ static int __devinit rtl8139_init_one (struct pci_dev *pdev,
assert (dev != NULL); assert (dev != NULL);
tp = netdev_priv(dev); tp = netdev_priv(dev);
tp->dev = dev;
ioaddr = tp->mmio_addr; ioaddr = tp->mmio_addr;
assert (ioaddr != NULL); assert (ioaddr != NULL);
...@@ -976,8 +979,7 @@ static int __devinit rtl8139_init_one (struct pci_dev *pdev, ...@@ -976,8 +979,7 @@ static int __devinit rtl8139_init_one (struct pci_dev *pdev,
/* The Rtl8139-specific entries in the device structure. */ /* The Rtl8139-specific entries in the device structure. */
dev->open = rtl8139_open; dev->open = rtl8139_open;
dev->hard_start_xmit = rtl8139_start_xmit; dev->hard_start_xmit = rtl8139_start_xmit;
dev->poll = rtl8139_poll; netif_napi_add(dev, &tp->napi, rtl8139_poll, 64);
dev->weight = 64;
dev->stop = rtl8139_close; dev->stop = rtl8139_close;
dev->get_stats = rtl8139_get_stats; dev->get_stats = rtl8139_get_stats;
dev->set_multicast_list = rtl8139_set_rx_mode; dev->set_multicast_list = rtl8139_set_rx_mode;
...@@ -1332,6 +1334,8 @@ static int rtl8139_open (struct net_device *dev) ...@@ -1332,6 +1334,8 @@ static int rtl8139_open (struct net_device *dev)
} }
napi_enable(&tp->napi);
tp->mii.full_duplex = tp->mii.force_media; tp->mii.full_duplex = tp->mii.force_media;
tp->tx_flag = (TX_FIFO_THRESH << 11) & 0x003f0000; tp->tx_flag = (TX_FIFO_THRESH << 11) & 0x003f0000;
...@@ -2103,39 +2107,32 @@ static void rtl8139_weird_interrupt (struct net_device *dev, ...@@ -2103,39 +2107,32 @@ static void rtl8139_weird_interrupt (struct net_device *dev,
} }
} }
static int rtl8139_poll(struct net_device *dev, int *budget) static int rtl8139_poll(struct napi_struct *napi, int budget)
{ {
struct rtl8139_private *tp = netdev_priv(dev); struct rtl8139_private *tp = container_of(napi, struct rtl8139_private, napi);
struct net_device *dev = tp->dev;
void __iomem *ioaddr = tp->mmio_addr; void __iomem *ioaddr = tp->mmio_addr;
int orig_budget = min(*budget, dev->quota); int work_done;
int done = 1;
spin_lock(&tp->rx_lock); spin_lock(&tp->rx_lock);
if (likely(RTL_R16(IntrStatus) & RxAckBits)) { work_done = 0;
int work_done; if (likely(RTL_R16(IntrStatus) & RxAckBits))
work_done += rtl8139_rx(dev, tp, budget);
work_done = rtl8139_rx(dev, tp, orig_budget);
if (likely(work_done > 0)) {
*budget -= work_done;
dev->quota -= work_done;
done = (work_done < orig_budget);
}
}
if (done) { if (work_done < budget) {
unsigned long flags; unsigned long flags;
/* /*
* Order is important since data can get interrupted * Order is important since data can get interrupted
* again when we think we are done. * again when we think we are done.
*/ */
local_irq_save(flags); spin_lock_irqsave(&tp->lock, flags);
RTL_W16_F(IntrMask, rtl8139_intr_mask); RTL_W16_F(IntrMask, rtl8139_intr_mask);
__netif_rx_complete(dev); __netif_rx_complete(dev, napi);
local_irq_restore(flags); spin_unlock_irqrestore(&tp->lock, flags);
} }
spin_unlock(&tp->rx_lock); spin_unlock(&tp->rx_lock);
return !done; return work_done;
} }
/* The interrupt handler does all of the Rx thread work and cleans up /* The interrupt handler does all of the Rx thread work and cleans up
...@@ -2180,9 +2177,9 @@ static irqreturn_t rtl8139_interrupt (int irq, void *dev_instance) ...@@ -2180,9 +2177,9 @@ static irqreturn_t rtl8139_interrupt (int irq, void *dev_instance)
/* Receive packets are processed by poll routine. /* Receive packets are processed by poll routine.
If not running start it now. */ If not running start it now. */
if (status & RxAckBits){ if (status & RxAckBits){
if (netif_rx_schedule_prep(dev)) { if (netif_rx_schedule_prep(dev, &tp->napi)) {
RTL_W16_F (IntrMask, rtl8139_norx_intr_mask); RTL_W16_F (IntrMask, rtl8139_norx_intr_mask);
__netif_rx_schedule (dev); __netif_rx_schedule(dev, &tp->napi);
} }
} }
...@@ -2223,7 +2220,8 @@ static int rtl8139_close (struct net_device *dev) ...@@ -2223,7 +2220,8 @@ static int rtl8139_close (struct net_device *dev)
void __iomem *ioaddr = tp->mmio_addr; void __iomem *ioaddr = tp->mmio_addr;
unsigned long flags; unsigned long flags;
netif_stop_queue (dev); netif_stop_queue(dev);
napi_disable(&tp->napi);
if (netif_msg_ifdown(tp)) if (netif_msg_ifdown(tp))
printk(KERN_DEBUG "%s: Shutting down ethercard, status was 0x%4.4x.\n", printk(KERN_DEBUG "%s: Shutting down ethercard, status was 0x%4.4x.\n",
......
...@@ -723,9 +723,10 @@ static int amd8111e_tx(struct net_device *dev) ...@@ -723,9 +723,10 @@ static int amd8111e_tx(struct net_device *dev)
#ifdef CONFIG_AMD8111E_NAPI #ifdef CONFIG_AMD8111E_NAPI
/* This function handles the driver receive operation in polling mode */ /* This function handles the driver receive operation in polling mode */
static int amd8111e_rx_poll(struct net_device *dev, int * budget) static int amd8111e_rx_poll(struct napi_struct *napi, int budget)
{ {
struct amd8111e_priv *lp = netdev_priv(dev); struct amd8111e_priv *lp = container_of(napi, struct amd8111e_priv, napi);
struct net_device *dev = lp->amd8111e_net_dev;
int rx_index = lp->rx_idx & RX_RING_DR_MOD_MASK; int rx_index = lp->rx_idx & RX_RING_DR_MOD_MASK;
void __iomem *mmio = lp->mmio; void __iomem *mmio = lp->mmio;
struct sk_buff *skb,*new_skb; struct sk_buff *skb,*new_skb;
...@@ -737,7 +738,7 @@ static int amd8111e_rx_poll(struct net_device *dev, int * budget) ...@@ -737,7 +738,7 @@ static int amd8111e_rx_poll(struct net_device *dev, int * budget)
#if AMD8111E_VLAN_TAG_USED #if AMD8111E_VLAN_TAG_USED
short vtag; short vtag;
#endif #endif
int rx_pkt_limit = dev->quota; int rx_pkt_limit = budget;
unsigned long flags; unsigned long flags;
do{ do{
...@@ -838,21 +839,14 @@ static int amd8111e_rx_poll(struct net_device *dev, int * budget) ...@@ -838,21 +839,14 @@ static int amd8111e_rx_poll(struct net_device *dev, int * budget)
} while(intr0 & RINT0); } while(intr0 & RINT0);
/* Receive descriptor is empty now */ /* Receive descriptor is empty now */
dev->quota -= num_rx_pkt;
*budget -= num_rx_pkt;
spin_lock_irqsave(&lp->lock, flags); spin_lock_irqsave(&lp->lock, flags);
netif_rx_complete(dev); __netif_rx_complete(dev, napi);
writel(VAL0|RINTEN0, mmio + INTEN0); writel(VAL0|RINTEN0, mmio + INTEN0);
writel(VAL2 | RDMD0, mmio + CMD0); writel(VAL2 | RDMD0, mmio + CMD0);
spin_unlock_irqrestore(&lp->lock, flags); spin_unlock_irqrestore(&lp->lock, flags);
return 0;
rx_not_empty: rx_not_empty:
/* Do not call a netif_rx_complete */ return num_rx_pkt;
dev->quota -= num_rx_pkt;
*budget -= num_rx_pkt;
return 1;
} }
#else #else
...@@ -1287,11 +1281,11 @@ static irqreturn_t amd8111e_interrupt(int irq, void *dev_id) ...@@ -1287,11 +1281,11 @@ static irqreturn_t amd8111e_interrupt(int irq, void *dev_id)
/* Check if Receive Interrupt has occurred. */ /* Check if Receive Interrupt has occurred. */
#ifdef CONFIG_AMD8111E_NAPI #ifdef CONFIG_AMD8111E_NAPI
if(intr0 & RINT0){ if(intr0 & RINT0){
if(netif_rx_schedule_prep(dev)){ if(netif_rx_schedule_prep(dev, &lp->napi)){
/* Disable receive interupts */ /* Disable receive interupts */
writel(RINTEN0, mmio + INTEN0); writel(RINTEN0, mmio + INTEN0);
/* Schedule a polling routine */ /* Schedule a polling routine */
__netif_rx_schedule(dev); __netif_rx_schedule(dev, &lp->napi);
} }
else if (intren0 & RINTEN0) { else if (intren0 & RINTEN0) {
printk("************Driver bug! \ printk("************Driver bug! \
...@@ -1345,6 +1339,8 @@ static int amd8111e_close(struct net_device * dev) ...@@ -1345,6 +1339,8 @@ static int amd8111e_close(struct net_device * dev)
struct amd8111e_priv *lp = netdev_priv(dev); struct amd8111e_priv *lp = netdev_priv(dev);
netif_stop_queue(dev); netif_stop_queue(dev);
napi_disable(&lp->napi);
spin_lock_irq(&lp->lock); spin_lock_irq(&lp->lock);
amd8111e_disable_interrupt(lp); amd8111e_disable_interrupt(lp);
...@@ -1375,12 +1371,15 @@ static int amd8111e_open(struct net_device * dev ) ...@@ -1375,12 +1371,15 @@ static int amd8111e_open(struct net_device * dev )
dev->name, dev)) dev->name, dev))
return -EAGAIN; return -EAGAIN;
napi_enable(&lp->napi);
spin_lock_irq(&lp->lock); spin_lock_irq(&lp->lock);
amd8111e_init_hw_default(lp); amd8111e_init_hw_default(lp);
if(amd8111e_restart(dev)){ if(amd8111e_restart(dev)){
spin_unlock_irq(&lp->lock); spin_unlock_irq(&lp->lock);
napi_disable(&lp->napi);
if (dev->irq) if (dev->irq)
free_irq(dev->irq, dev); free_irq(dev->irq, dev);
return -ENOMEM; return -ENOMEM;
...@@ -2031,8 +2030,7 @@ static int __devinit amd8111e_probe_one(struct pci_dev *pdev, ...@@ -2031,8 +2030,7 @@ static int __devinit amd8111e_probe_one(struct pci_dev *pdev,
dev->tx_timeout = amd8111e_tx_timeout; dev->tx_timeout = amd8111e_tx_timeout;
dev->watchdog_timeo = AMD8111E_TX_TIMEOUT; dev->watchdog_timeo = AMD8111E_TX_TIMEOUT;
#ifdef CONFIG_AMD8111E_NAPI #ifdef CONFIG_AMD8111E_NAPI
dev->poll = amd8111e_rx_poll; netif_napi_add(dev, &lp->napi, amd8111e_rx_poll, 32);
dev->weight = 32;
#endif #endif
#ifdef CONFIG_NET_POLL_CONTROLLER #ifdef CONFIG_NET_POLL_CONTROLLER
dev->poll_controller = amd8111e_poll; dev->poll_controller = amd8111e_poll;
......
...@@ -763,6 +763,8 @@ struct amd8111e_priv{ ...@@ -763,6 +763,8 @@ struct amd8111e_priv{
/* Reg memory mapped address */ /* Reg memory mapped address */
void __iomem *mmio; void __iomem *mmio;
struct napi_struct napi;
spinlock_t lock; /* Guard lock */ spinlock_t lock; /* Guard lock */
unsigned long rx_idx, tx_idx; /* The next free ring entry */ unsigned long rx_idx, tx_idx; /* The next free ring entry */
unsigned long tx_complete_idx; unsigned long tx_complete_idx;
......
...@@ -169,6 +169,9 @@ struct ep93xx_priv ...@@ -169,6 +169,9 @@ struct ep93xx_priv
spinlock_t tx_pending_lock; spinlock_t tx_pending_lock;
unsigned int tx_pending; unsigned int tx_pending;
struct net_device *dev;
struct napi_struct napi;
struct net_device_stats stats; struct net_device_stats stats;
struct mii_if_info mii; struct mii_if_info mii;
...@@ -190,15 +193,11 @@ static struct net_device_stats *ep93xx_get_stats(struct net_device *dev) ...@@ -190,15 +193,11 @@ static struct net_device_stats *ep93xx_get_stats(struct net_device *dev)
return &(ep->stats); return &(ep->stats);
} }
static int ep93xx_rx(struct net_device *dev, int *budget) static int ep93xx_rx(struct net_device *dev, int processed, int budget)
{ {
struct ep93xx_priv *ep = netdev_priv(dev); struct ep93xx_priv *ep = netdev_priv(dev);
int rx_done;
int processed;
rx_done = 0; while (processed < budget) {
processed = 0;
while (*budget > 0) {
int entry; int entry;
struct ep93xx_rstat *rstat; struct ep93xx_rstat *rstat;
u32 rstat0; u32 rstat0;
...@@ -211,10 +210,8 @@ static int ep93xx_rx(struct net_device *dev, int *budget) ...@@ -211,10 +210,8 @@ static int ep93xx_rx(struct net_device *dev, int *budget)
rstat0 = rstat->rstat0; rstat0 = rstat->rstat0;
rstat1 = rstat->rstat1; rstat1 = rstat->rstat1;
if (!(rstat0 & RSTAT0_RFP) || !(rstat1 & RSTAT1_RFP)) { if (!(rstat0 & RSTAT0_RFP) || !(rstat1 & RSTAT1_RFP))
rx_done = 1;
break; break;
}
rstat->rstat0 = 0; rstat->rstat0 = 0;
rstat->rstat1 = 0; rstat->rstat1 = 0;
...@@ -275,8 +272,6 @@ static int ep93xx_rx(struct net_device *dev, int *budget) ...@@ -275,8 +272,6 @@ static int ep93xx_rx(struct net_device *dev, int *budget)
err: err:
ep->rx_pointer = (entry + 1) & (RX_QUEUE_ENTRIES - 1); ep->rx_pointer = (entry + 1) & (RX_QUEUE_ENTRIES - 1);
processed++; processed++;
dev->quota--;
(*budget)--;
} }
if (processed) { if (processed) {
...@@ -284,7 +279,7 @@ static int ep93xx_rx(struct net_device *dev, int *budget) ...@@ -284,7 +279,7 @@ static int ep93xx_rx(struct net_device *dev, int *budget)
wrw(ep, REG_RXSTSENQ, processed); wrw(ep, REG_RXSTSENQ, processed);
} }
return !rx_done; return processed;
} }
static int ep93xx_have_more_rx(struct ep93xx_priv *ep) static int ep93xx_have_more_rx(struct ep93xx_priv *ep)
...@@ -293,36 +288,32 @@ static int ep93xx_have_more_rx(struct ep93xx_priv *ep) ...@@ -293,36 +288,32 @@ static int ep93xx_have_more_rx(struct ep93xx_priv *ep)
return !!((rstat->rstat0 & RSTAT0_RFP) && (rstat->rstat1 & RSTAT1_RFP)); return !!((rstat->rstat0 & RSTAT0_RFP) && (rstat->rstat1 & RSTAT1_RFP));
} }
static int ep93xx_poll(struct net_device *dev, int *budget) static int ep93xx_poll(struct napi_struct *napi, int budget)
{ {
struct ep93xx_priv *ep = netdev_priv(dev); struct ep93xx_priv *ep = container_of(napi, struct ep93xx_priv, napi);
struct net_device *dev = ep->dev;
/* int rx = 0;
* @@@ Have to stop polling if device is downed while we
* are polling.
*/
poll_some_more: poll_some_more:
if (ep93xx_rx(dev, budget)) rx = ep93xx_rx(dev, rx, budget);
return 1; if (rx < budget) {
int more = 0;
netif_rx_complete(dev);
spin_lock_irq(&ep->rx_lock);
spin_lock_irq(&ep->rx_lock); __netif_rx_complete(dev, napi);
wrl(ep, REG_INTEN, REG_INTEN_TX | REG_INTEN_RX); wrl(ep, REG_INTEN, REG_INTEN_TX | REG_INTEN_RX);
if (ep93xx_have_more_rx(ep)) { if (ep93xx_have_more_rx(ep)) {
wrl(ep, REG_INTEN, REG_INTEN_TX); wrl(ep, REG_INTEN, REG_INTEN_TX);
wrl(ep, REG_INTSTSP, REG_INTSTS_RX); wrl(ep, REG_INTSTSP, REG_INTSTS_RX);
more = 1;
}
spin_unlock_irq(&ep->rx_lock); spin_unlock_irq(&ep->rx_lock);
if (netif_rx_reschedule(dev, 0)) if (more && netif_rx_reschedule(dev, napi))
goto poll_some_more; goto poll_some_more;
return 0;
} }
spin_unlock_irq(&ep->rx_lock);
return 0; return rx;
} }
static int ep93xx_xmit(struct sk_buff *skb, struct net_device *dev) static 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,9 +417,9 @@ static irqreturn_t ep93xx_irq(int irq, void *dev_id)
if (status & REG_INTSTS_RX) { if (status & REG_INTSTS_RX) {
spin_lock(&ep->rx_lock); spin_lock(&ep->rx_lock);
if (likely(__netif_rx_schedule_prep(dev))) { if (likely(__netif_rx_schedule_prep(dev, &ep->napi))) {
wrl(ep, REG_INTEN, REG_INTEN_TX); wrl(ep, REG_INTEN, REG_INTEN_TX);
__netif_rx_schedule(dev); __netif_rx_schedule(dev, &ep->napi);
} }
spin_unlock(&ep->rx_lock); spin_unlock(&ep->rx_lock);
} }
...@@ -648,7 +639,10 @@ static int ep93xx_open(struct net_device *dev) ...@@ -648,7 +639,10 @@ static int ep93xx_open(struct net_device *dev)
dev->dev_addr[4], dev->dev_addr[5]); dev->dev_addr[4], dev->dev_addr[5]);
} }
napi_enable(&ep->napi);
if (ep93xx_start_hw(dev)) { if (ep93xx_start_hw(dev)) {
napi_disable(&ep->napi);
ep93xx_free_buffers(ep); ep93xx_free_buffers(ep);
return -EIO; return -EIO;
} }
...@@ -662,6 +656,7 @@ static int ep93xx_open(struct net_device *dev) ...@@ -662,6 +656,7 @@ static int ep93xx_open(struct net_device *dev)
err = request_irq(ep->irq, ep93xx_irq, IRQF_SHARED, dev->name, dev); err = request_irq(ep->irq, ep93xx_irq, IRQF_SHARED, dev->name, dev);
if (err) { if (err) {
napi_disable(&ep->napi);
ep93xx_stop_hw(dev); ep93xx_stop_hw(dev);
ep93xx_free_buffers(ep); ep93xx_free_buffers(ep);
return err; return err;
...@@ -678,6 +673,7 @@ static int ep93xx_close(struct net_device *dev) ...@@ -678,6 +673,7 @@ static int ep93xx_close(struct net_device *dev)
{ {
struct ep93xx_priv *ep = netdev_priv(dev); struct ep93xx_priv *ep = netdev_priv(dev);
napi_disable(&ep->napi);
netif_stop_queue(dev); netif_stop_queue(dev);
wrl(ep, REG_GIINTMSK, 0); wrl(ep, REG_GIINTMSK, 0);
...@@ -788,14 +784,12 @@ struct net_device *ep93xx_dev_alloc(struct ep93xx_eth_data *data) ...@@ -788,14 +784,12 @@ struct net_device *ep93xx_dev_alloc(struct ep93xx_eth_data *data)
dev->get_stats = ep93xx_get_stats; dev->get_stats = ep93xx_get_stats;
dev->ethtool_ops = &ep93xx_ethtool_ops; dev->ethtool_ops = &ep93xx_ethtool_ops;
dev->poll = ep93xx_poll;
dev->hard_start_xmit = ep93xx_xmit; dev->hard_start_xmit = ep93xx_xmit;
dev->open = ep93xx_open; dev->open = ep93xx_open;
dev->stop = ep93xx_close; dev->stop = ep93xx_close;
dev->do_ioctl = ep93xx_ioctl; dev->do_ioctl = ep93xx_ioctl;
dev->features |= NETIF_F_SG | NETIF_F_HW_CSUM; dev->features |= NETIF_F_SG | NETIF_F_HW_CSUM;
dev->weight = 64;
return dev; return dev;
} }
...@@ -847,6 +841,8 @@ static int ep93xx_eth_probe(struct platform_device *pdev) ...@@ -847,6 +841,8 @@ static int ep93xx_eth_probe(struct platform_device *pdev)
goto err_out; goto err_out;
} }
ep = netdev_priv(dev); ep = netdev_priv(dev);
ep->dev = dev;
netif_napi_add(dev, &ep->napi, ep93xx_poll, 64);
platform_set_drvdata(pdev, dev); platform_set_drvdata(pdev, dev);
......
...@@ -848,10 +848,11 @@ static int b44_rx(struct b44 *bp, int budget) ...@@ -848,10 +848,11 @@ static int b44_rx(struct b44 *bp, int budget)
return received; return received;
} }
static int b44_poll(struct net_device *netdev, int *budget) static int b44_poll(struct napi_struct *napi, int budget)
{ {
struct b44 *bp = netdev_priv(netdev); struct b44 *bp = container_of(napi, struct b44, napi);
int done; struct net_device *netdev = bp->dev;
int work_done;
spin_lock_irq(&bp->lock); spin_lock_irq(&bp->lock);
...@@ -862,22 +863,9 @@ static int b44_poll(struct net_device *netdev, int *budget) ...@@ -862,22 +863,9 @@ static int b44_poll(struct net_device *netdev, int *budget)
} }
spin_unlock_irq(&bp->lock); spin_unlock_irq(&bp->lock);
done = 1; work_done = 0;
if (bp->istat & ISTAT_RX) { if (bp->istat & ISTAT_RX)
int orig_budget = *budget; work_done += b44_rx(bp, budget);
int work_done;
if (orig_budget > netdev->quota)
orig_budget = netdev->quota;
work_done = b44_rx(bp, orig_budget);
*budget -= work_done;
netdev->quota -= work_done;
if (work_done >= orig_budget)
done = 0;
}
if (bp->istat & ISTAT_ERRORS) { if (bp->istat & ISTAT_ERRORS) {
unsigned long flags; unsigned long flags;
...@@ -888,15 +876,15 @@ static int b44_poll(struct net_device *netdev, int *budget) ...@@ -888,15 +876,15 @@ static int b44_poll(struct net_device *netdev, int *budget)
b44_init_hw(bp, B44_FULL_RESET_SKIP_PHY); b44_init_hw(bp, B44_FULL_RESET_SKIP_PHY);
netif_wake_queue(bp->dev); netif_wake_queue(bp->dev);
spin_unlock_irqrestore(&bp->lock, flags); spin_unlock_irqrestore(&bp->lock, flags);
done = 1; work_done = 0;
} }
if (done) { if (work_done < budget) {
netif_rx_complete(netdev); netif_rx_complete(netdev, napi);
b44_enable_ints(bp); b44_enable_ints(bp);
} }
return (done ? 0 : 1); return work_done;
} }
static irqreturn_t b44_interrupt(int irq, void *dev_id) static irqreturn_t b44_interrupt(int irq, void *dev_id)
...@@ -924,13 +912,13 @@ static irqreturn_t b44_interrupt(int irq, void *dev_id) ...@@ -924,13 +912,13 @@ static irqreturn_t b44_interrupt(int irq, void *dev_id)
goto irq_ack; goto irq_ack;
} }
if (netif_rx_schedule_prep(dev)) { if (netif_rx_schedule_prep(dev, &bp->napi)) {
/* NOTE: These writes are posted by the readback of /* NOTE: These writes are posted by the readback of
* the ISTAT register below. * the ISTAT register below.
*/ */
bp->istat = istat; bp->istat = istat;
__b44_disable_ints(bp); __b44_disable_ints(bp);
__netif_rx_schedule(dev); __netif_rx_schedule(dev, &bp->napi);
} else { } else {
printk(KERN_ERR PFX "%s: Error, poll already scheduled\n", printk(KERN_ERR PFX "%s: Error, poll already scheduled\n",
dev->name); dev->name);
...@@ -1420,6 +1408,8 @@ static int b44_open(struct net_device *dev) ...@@ -1420,6 +1408,8 @@ static int b44_open(struct net_device *dev)
if (err) if (err)
goto out; goto out;
napi_enable(&bp->napi);
b44_init_rings(bp); b44_init_rings(bp);
b44_init_hw(bp, B44_FULL_RESET); b44_init_hw(bp, B44_FULL_RESET);
...@@ -1427,6 +1417,7 @@ static int b44_open(struct net_device *dev) ...@@ -1427,6 +1417,7 @@ static int b44_open(struct net_device *dev)
err = request_irq(dev->irq, b44_interrupt, IRQF_SHARED, dev->name, dev); err = request_irq(dev->irq, b44_interrupt, IRQF_SHARED, dev->name, dev);
if (unlikely(err < 0)) { if (unlikely(err < 0)) {
napi_disable(&bp->napi);
b44_chip_reset(bp); b44_chip_reset(bp);
b44_free_rings(bp); b44_free_rings(bp);
b44_free_consistent(bp); b44_free_consistent(bp);
...@@ -1609,7 +1600,7 @@ static int b44_close(struct net_device *dev) ...@@ -1609,7 +1600,7 @@ static int b44_close(struct net_device *dev)
netif_stop_queue(dev); netif_stop_queue(dev);
netif_poll_disable(dev); napi_disable(&bp->napi);
del_timer_sync(&bp->timer); del_timer_sync(&bp->timer);
...@@ -1626,8 +1617,6 @@ static int b44_close(struct net_device *dev) ...@@ -1626,8 +1617,6 @@ static int b44_close(struct net_device *dev)
free_irq(dev->irq, dev); free_irq(dev->irq, dev);
netif_poll_enable(dev);
if (bp->flags & B44_FLAG_WOL_ENABLE) { if (bp->flags & B44_FLAG_WOL_ENABLE) {
b44_init_hw(bp, B44_PARTIAL_RESET); b44_init_hw(bp, B44_PARTIAL_RESET);
b44_setup_wol(bp); b44_setup_wol(bp);
...@@ -2194,8 +2183,7 @@ static int __devinit b44_init_one(struct pci_dev *pdev, ...@@ -2194,8 +2183,7 @@ static int __devinit b44_init_one(struct pci_dev *pdev,
dev->set_mac_address = b44_set_mac_addr; dev->set_mac_address = b44_set_mac_addr;
dev->do_ioctl = b44_ioctl; dev->do_ioctl = b44_ioctl;
dev->tx_timeout = b44_tx_timeout; dev->tx_timeout = b44_tx_timeout;
dev->poll = b44_poll; netif_napi_add(dev, &bp->napi, b44_poll, 64);
dev->weight = 64;
dev->watchdog_timeo = B44_TX_TIMEOUT; dev->watchdog_timeo = B44_TX_TIMEOUT;
#ifdef CONFIG_NET_POLL_CONTROLLER #ifdef CONFIG_NET_POLL_CONTROLLER
dev->poll_controller = b44_poll_controller; dev->poll_controller = b44_poll_controller;
......
...@@ -423,6 +423,8 @@ struct b44 { ...@@ -423,6 +423,8 @@ struct b44 {
struct ring_info *rx_buffers; struct ring_info *rx_buffers;
struct ring_info *tx_buffers; struct ring_info *tx_buffers;
struct napi_struct napi;
u32 dma_offset; u32 dma_offset;
u32 flags; u32 flags;
#define B44_FLAG_B0_ANDLATER 0x00000001 #define B44_FLAG_B0_ANDLATER 0x00000001
......
...@@ -428,7 +428,7 @@ bnx2_netif_stop(struct bnx2 *bp) ...@@ -428,7 +428,7 @@ bnx2_netif_stop(struct bnx2 *bp)
{ {
bnx2_disable_int_sync(bp); bnx2_disable_int_sync(bp);
if (netif_running(bp->dev)) { if (netif_running(bp->dev)) {
netif_poll_disable(bp->dev); napi_disable(&bp->napi);
netif_tx_disable(bp->dev); netif_tx_disable(bp->dev);
bp->dev->trans_start = jiffies; /* prevent tx timeout */ bp->dev->trans_start = jiffies; /* prevent tx timeout */
} }
...@@ -440,7 +440,7 @@ bnx2_netif_start(struct bnx2 *bp) ...@@ -440,7 +440,7 @@ bnx2_netif_start(struct bnx2 *bp)
if (atomic_dec_and_test(&bp->intr_sem)) { if (atomic_dec_and_test(&bp->intr_sem)) {
if (netif_running(bp->dev)) { if (netif_running(bp->dev)) {
netif_wake_queue(bp->dev); netif_wake_queue(bp->dev);
netif_poll_enable(bp->dev); napi_enable(&bp->napi);
bnx2_enable_int(bp); bnx2_enable_int(bp);
} }
} }
...@@ -2551,7 +2551,7 @@ bnx2_msi(int irq, void *dev_instance) ...@@ -2551,7 +2551,7 @@ bnx2_msi(int irq, void *dev_instance)
if (unlikely(atomic_read(&bp->intr_sem) != 0)) if (unlikely(atomic_read(&bp->intr_sem) != 0))
return IRQ_HANDLED; return IRQ_HANDLED;
netif_rx_schedule(dev); netif_rx_schedule(dev, &bp->napi);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
...@@ -2568,7 +2568,7 @@ bnx2_msi_1shot(int irq, void *dev_instance) ...@@ -2568,7 +2568,7 @@ bnx2_msi_1shot(int irq, void *dev_instance)
if (unlikely(atomic_read(&bp->intr_sem) != 0)) if (unlikely(atomic_read(&bp->intr_sem) != 0))
return IRQ_HANDLED; return IRQ_HANDLED;
netif_rx_schedule(dev); netif_rx_schedule(dev, &bp->napi);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
...@@ -2604,9 +2604,9 @@ bnx2_interrupt(int irq, void *dev_instance) ...@@ -2604,9 +2604,9 @@ bnx2_interrupt(int irq, void *dev_instance)
if (unlikely(atomic_read(&bp->intr_sem) != 0)) if (unlikely(atomic_read(&bp->intr_sem) != 0))
return IRQ_HANDLED; return IRQ_HANDLED;
if (netif_rx_schedule_prep(dev)) { if (netif_rx_schedule_prep(dev, &bp->napi)) {
bp->last_status_idx = sblk->status_idx; bp->last_status_idx = sblk->status_idx;
__netif_rx_schedule(dev); __netif_rx_schedule(dev, &bp->napi);
} }
return IRQ_HANDLED; return IRQ_HANDLED;
...@@ -2632,12 +2632,14 @@ bnx2_has_work(struct bnx2 *bp) ...@@ -2632,12 +2632,14 @@ bnx2_has_work(struct bnx2 *bp)
} }
static int static int
bnx2_poll(struct net_device *dev, int *budget) bnx2_poll(struct napi_struct *napi, int budget)
{ {
struct bnx2 *bp = netdev_priv(dev); struct bnx2 *bp = container_of(napi, struct bnx2, napi);
struct net_device *dev = bp->dev;
struct status_block *sblk = bp->status_blk; struct status_block *sblk = bp->status_blk;
u32 status_attn_bits = sblk->status_attn_bits; u32 status_attn_bits = sblk->status_attn_bits;
u32 status_attn_bits_ack = sblk->status_attn_bits_ack; u32 status_attn_bits_ack = sblk->status_attn_bits_ack;
int work_done = 0;
if ((status_attn_bits & STATUS_ATTN_EVENTS) != if ((status_attn_bits & STATUS_ATTN_EVENTS) !=
(status_attn_bits_ack & STATUS_ATTN_EVENTS)) { (status_attn_bits_ack & STATUS_ATTN_EVENTS)) {
...@@ -2655,23 +2657,14 @@ bnx2_poll(struct net_device *dev, int *budget) ...@@ -2655,23 +2657,14 @@ bnx2_poll(struct net_device *dev, int *budget)
if (bp->status_blk->status_tx_quick_consumer_index0 != bp->hw_tx_cons) if (bp->status_blk->status_tx_quick_consumer_index0 != bp->hw_tx_cons)
bnx2_tx_int(bp); bnx2_tx_int(bp);
if (bp->status_blk->status_rx_quick_consumer_index0 != bp->hw_rx_cons) { if (bp->status_blk->status_rx_quick_consumer_index0 != bp->hw_rx_cons)
int orig_budget = *budget; work_done = bnx2_rx_int(bp, budget);
int work_done;
if (orig_budget > dev->quota)
orig_budget = dev->quota;
work_done = bnx2_rx_int(bp, orig_budget);
*budget -= work_done;
dev->quota -= work_done;
}
bp->last_status_idx = bp->status_blk->status_idx; bp->last_status_idx = bp->status_blk->status_idx;
rmb(); rmb();
if (!bnx2_has_work(bp)) { if (!bnx2_has_work(bp)) {
netif_rx_complete(dev); netif_rx_complete(dev, napi);
if (likely(bp->flags & USING_MSI_FLAG)) { if (likely(bp->flags & USING_MSI_FLAG)) {
REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD, REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD,
BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID | BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID |
...@@ -2686,10 +2679,9 @@ bnx2_poll(struct net_device *dev, int *budget) ...@@ -2686,10 +2679,9 @@ bnx2_poll(struct net_device *dev, int *budget)
REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD, REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD,
BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID | BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID |
bp->last_status_idx); bp->last_status_idx);
return 0;
} }
return 1; return work_done;
} }
/* Called with rtnl_lock from vlan functions and also netif_tx_lock /* Called with rtnl_lock from vlan functions and also netif_tx_lock
...@@ -5039,6 +5031,8 @@ bnx2_open(struct net_device *dev) ...@@ -5039,6 +5031,8 @@ bnx2_open(struct net_device *dev)
if (rc) if (rc)
return rc; return rc;
napi_enable(&bp->napi);
if ((bp->flags & MSI_CAP_FLAG) && !disable_msi) { if ((bp->flags & MSI_CAP_FLAG) && !disable_msi) {
if (pci_enable_msi(bp->pdev) == 0) { if (pci_enable_msi(bp->pdev) == 0) {
bp->flags |= USING_MSI_FLAG; bp->flags |= USING_MSI_FLAG;
...@@ -5049,6 +5043,7 @@ bnx2_open(struct net_device *dev) ...@@ -5049,6 +5043,7 @@ bnx2_open(struct net_device *dev)
rc = bnx2_request_irq(bp); rc = bnx2_request_irq(bp);
if (rc) { if (rc) {
napi_disable(&bp->napi);
bnx2_free_mem(bp); bnx2_free_mem(bp);
return rc; return rc;
} }
...@@ -5056,6 +5051,7 @@ bnx2_open(struct net_device *dev) ...@@ -5056,6 +5051,7 @@ bnx2_open(struct net_device *dev)
rc = bnx2_init_nic(bp); rc = bnx2_init_nic(bp);
if (rc) { if (rc) {
napi_disable(&bp->napi);
bnx2_free_irq(bp); bnx2_free_irq(bp);
bnx2_free_skbs(bp); bnx2_free_skbs(bp);
bnx2_free_mem(bp); bnx2_free_mem(bp);
...@@ -5088,6 +5084,7 @@ bnx2_open(struct net_device *dev) ...@@ -5088,6 +5084,7 @@ bnx2_open(struct net_device *dev)
rc = bnx2_request_irq(bp); rc = bnx2_request_irq(bp);
if (rc) { if (rc) {
napi_disable(&bp->napi);
bnx2_free_skbs(bp); bnx2_free_skbs(bp);
bnx2_free_mem(bp); bnx2_free_mem(bp);
del_timer_sync(&bp->timer); del_timer_sync(&bp->timer);
...@@ -5301,7 +5298,8 @@ bnx2_close(struct net_device *dev) ...@@ -5301,7 +5298,8 @@ bnx2_close(struct net_device *dev)
while (bp->in_reset_task) while (bp->in_reset_task)
msleep(1); msleep(1);
bnx2_netif_stop(bp); bnx2_disable_int_sync(bp);
napi_disable(&bp->napi);
del_timer_sync(&bp->timer); del_timer_sync(&bp->timer);
if (bp->flags & NO_WOL_FLAG) if (bp->flags & NO_WOL_FLAG)
reset_code = BNX2_DRV_MSG_CODE_UNLOAD_LNK_DN; reset_code = BNX2_DRV_MSG_CODE_UNLOAD_LNK_DN;
...@@ -6858,11 +6856,10 @@ bnx2_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -6858,11 +6856,10 @@ bnx2_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
#ifdef BCM_VLAN #ifdef BCM_VLAN
dev->vlan_rx_register = bnx2_vlan_rx_register; dev->vlan_rx_register = bnx2_vlan_rx_register;
#endif #endif
dev->poll = bnx2_poll;
dev->ethtool_ops = &bnx2_ethtool_ops; dev->ethtool_ops = &bnx2_ethtool_ops;
dev->weight = 64;
bp = netdev_priv(dev); bp = netdev_priv(dev);
netif_napi_add(dev, &bp->napi, bnx2_poll, 64);
#if defined(HAVE_POLL_CONTROLLER) || defined(CONFIG_NET_POLL_CONTROLLER) #if defined(HAVE_POLL_CONTROLLER) || defined(CONFIG_NET_POLL_CONTROLLER)
dev->poll_controller = poll_bnx2; dev->poll_controller = poll_bnx2;
......
...@@ -6473,6 +6473,8 @@ struct bnx2 { ...@@ -6473,6 +6473,8 @@ struct bnx2 {
struct net_device *dev; struct net_device *dev;
struct pci_dev *pdev; struct pci_dev *pdev;
struct napi_struct napi;
atomic_t intr_sem; atomic_t intr_sem;
struct status_block *status_blk; struct status_block *status_blk;
......
...@@ -2485,7 +2485,7 @@ static irqreturn_t cas_interruptN(int irq, void *dev_id) ...@@ -2485,7 +2485,7 @@ static irqreturn_t cas_interruptN(int irq, void *dev_id)
if (status & INTR_RX_DONE_ALT) { /* handle rx separately */ if (status & INTR_RX_DONE_ALT) { /* handle rx separately */
#ifdef USE_NAPI #ifdef USE_NAPI
cas_mask_intr(cp); cas_mask_intr(cp);
netif_rx_schedule(dev); netif_rx_schedule(dev, &cp->napi);
#else #else
cas_rx_ringN(cp, ring, 0); cas_rx_ringN(cp, ring, 0);
#endif #endif
...@@ -2536,7 +2536,7 @@ static irqreturn_t cas_interrupt1(int irq, void *dev_id) ...@@ -2536,7 +2536,7 @@ static irqreturn_t cas_interrupt1(int irq, void *dev_id)
if (status & INTR_RX_DONE_ALT) { /* handle rx separately */ if (status & INTR_RX_DONE_ALT) { /* handle rx separately */
#ifdef USE_NAPI #ifdef USE_NAPI
cas_mask_intr(cp); cas_mask_intr(cp);
netif_rx_schedule(dev); netif_rx_schedule(dev, &cp->napi);
#else #else
cas_rx_ringN(cp, 1, 0); cas_rx_ringN(cp, 1, 0);
#endif #endif
...@@ -2592,7 +2592,7 @@ static irqreturn_t cas_interrupt(int irq, void *dev_id) ...@@ -2592,7 +2592,7 @@ static irqreturn_t cas_interrupt(int irq, void *dev_id)
if (status & INTR_RX_DONE) { if (status & INTR_RX_DONE) {
#ifdef USE_NAPI #ifdef USE_NAPI
cas_mask_intr(cp); cas_mask_intr(cp);
netif_rx_schedule(dev); netif_rx_schedule(dev, &cp->napi);
#else #else
cas_rx_ringN(cp, 0, 0); cas_rx_ringN(cp, 0, 0);
#endif #endif
...@@ -2607,9 +2607,10 @@ static irqreturn_t cas_interrupt(int irq, void *dev_id) ...@@ -2607,9 +2607,10 @@ static irqreturn_t cas_interrupt(int irq, void *dev_id)
#ifdef USE_NAPI #ifdef USE_NAPI
static int cas_poll(struct net_device *dev, int *budget) static int cas_poll(struct napi_struct *napi, int budget)
{ {
struct cas *cp = netdev_priv(dev); struct cas *cp = container_of(napi, struct cas, napi);
struct net_device *dev = cp->dev;
int i, enable_intr, todo, credits; int i, enable_intr, todo, credits;
u32 status = readl(cp->regs + REG_INTR_STATUS); u32 status = readl(cp->regs + REG_INTR_STATUS);
unsigned long flags; unsigned long flags;
...@@ -2620,20 +2621,18 @@ static int cas_poll(struct net_device *dev, int *budget) ...@@ -2620,20 +2621,18 @@ static int cas_poll(struct net_device *dev, int *budget)
/* NAPI rx packets. we spread the credits across all of the /* NAPI rx packets. we spread the credits across all of the
* rxc rings * rxc rings
*/ *
todo = min(*budget, dev->quota); * to make sure we're fair with the work we loop through each
/* to make sure we're fair with the work we loop through each
* ring N_RX_COMP_RING times with a request of * ring N_RX_COMP_RING times with a request of
* todo / N_RX_COMP_RINGS * budget / N_RX_COMP_RINGS
*/ */
enable_intr = 1; enable_intr = 1;
credits = 0; credits = 0;
for (i = 0; i < N_RX_COMP_RINGS; i++) { for (i = 0; i < N_RX_COMP_RINGS; i++) {
int j; int j;
for (j = 0; j < N_RX_COMP_RINGS; j++) { for (j = 0; j < N_RX_COMP_RINGS; j++) {
credits += cas_rx_ringN(cp, j, todo / N_RX_COMP_RINGS); credits += cas_rx_ringN(cp, j, budget / N_RX_COMP_RINGS);
if (credits >= todo) { if (credits >= budget) {
enable_intr = 0; enable_intr = 0;
goto rx_comp; goto rx_comp;
} }
...@@ -2641,9 +2640,6 @@ static int cas_poll(struct net_device *dev, int *budget) ...@@ -2641,9 +2640,6 @@ static int cas_poll(struct net_device *dev, int *budget)
} }
rx_comp: rx_comp:
*budget -= credits;
dev->quota -= credits;
/* final rx completion */ /* final rx completion */
spin_lock_irqsave(&cp->lock, flags); spin_lock_irqsave(&cp->lock, flags);
if (status) if (status)
...@@ -2674,11 +2670,10 @@ static int cas_poll(struct net_device *dev, int *budget) ...@@ -2674,11 +2670,10 @@ static int cas_poll(struct net_device *dev, int *budget)
#endif #endif
spin_unlock_irqrestore(&cp->lock, flags); spin_unlock_irqrestore(&cp->lock, flags);
if (enable_intr) { if (enable_intr) {
netif_rx_complete(dev); netif_rx_complete(dev, napi);
cas_unmask_intr(cp); cas_unmask_intr(cp);
return 0;
} }
return 1; return credits;
} }
#endif #endif
...@@ -4351,6 +4346,9 @@ static int cas_open(struct net_device *dev) ...@@ -4351,6 +4346,9 @@ static int cas_open(struct net_device *dev)
goto err_spare; goto err_spare;
} }
#ifdef USE_NAPI
napi_enable(&cp->napi);
#endif
/* init hw */ /* init hw */
cas_lock_all_save(cp, flags); cas_lock_all_save(cp, flags);
cas_clean_rings(cp); cas_clean_rings(cp);
...@@ -4376,6 +4374,9 @@ static int cas_close(struct net_device *dev) ...@@ -4376,6 +4374,9 @@ static int cas_close(struct net_device *dev)
unsigned long flags; unsigned long flags;
struct cas *cp = netdev_priv(dev); struct cas *cp = netdev_priv(dev);
#ifdef USE_NAPI
napi_enable(&cp->napi);
#endif
/* Make sure we don't get distracted by suspend/resume */ /* Make sure we don't get distracted by suspend/resume */
mutex_lock(&cp->pm_mutex); mutex_lock(&cp->pm_mutex);
...@@ -5062,8 +5063,7 @@ static int __devinit cas_init_one(struct pci_dev *pdev, ...@@ -5062,8 +5063,7 @@ static int __devinit cas_init_one(struct pci_dev *pdev,
dev->watchdog_timeo = CAS_TX_TIMEOUT; dev->watchdog_timeo = CAS_TX_TIMEOUT;
dev->change_mtu = cas_change_mtu; dev->change_mtu = cas_change_mtu;
#ifdef USE_NAPI #ifdef USE_NAPI
dev->poll = cas_poll; netif_napi_add(dev, &cp->napi, cas_poll, 64);
dev->weight = 64;
#endif #endif
#ifdef CONFIG_NET_POLL_CONTROLLER #ifdef CONFIG_NET_POLL_CONTROLLER
dev->poll_controller = cas_netpoll; dev->poll_controller = cas_netpoll;
......
...@@ -4280,6 +4280,8 @@ struct cas { ...@@ -4280,6 +4280,8 @@ struct cas {
int rx_cur[N_RX_COMP_RINGS], rx_new[N_RX_COMP_RINGS]; int rx_cur[N_RX_COMP_RINGS], rx_new[N_RX_COMP_RINGS];
int rx_last[N_RX_DESC_RINGS]; int rx_last[N_RX_DESC_RINGS];
struct napi_struct napi;
/* Set when chip is actually in operational state /* Set when chip is actually in operational state
* (ie. not power managed) */ * (ie. not power managed) */
int hw_running; int hw_running;
......
...@@ -278,6 +278,7 @@ struct adapter { ...@@ -278,6 +278,7 @@ struct adapter {
struct peespi *espi; struct peespi *espi;
struct petp *tp; struct petp *tp;
struct napi_struct napi;
struct port_info port[MAX_NPORTS]; struct port_info port[MAX_NPORTS];
struct delayed_work stats_update_task; struct delayed_work stats_update_task;
struct timer_list stats_update_timer; struct timer_list stats_update_timer;
......
...@@ -255,8 +255,11 @@ static int cxgb_open(struct net_device *dev) ...@@ -255,8 +255,11 @@ static int cxgb_open(struct net_device *dev)
struct adapter *adapter = dev->priv; struct adapter *adapter = dev->priv;
int other_ports = adapter->open_device_map & PORT_MASK; int other_ports = adapter->open_device_map & PORT_MASK;
if (!adapter->open_device_map && (err = cxgb_up(adapter)) < 0) napi_enable(&adapter->napi);
if (!adapter->open_device_map && (err = cxgb_up(adapter)) < 0) {
napi_disable(&adapter->napi);
return err; return err;
}
__set_bit(dev->if_port, &adapter->open_device_map); __set_bit(dev->if_port, &adapter->open_device_map);
link_start(&adapter->port[dev->if_port]); link_start(&adapter->port[dev->if_port]);
...@@ -274,6 +277,7 @@ static int cxgb_close(struct net_device *dev) ...@@ -274,6 +277,7 @@ static int cxgb_close(struct net_device *dev)
struct cmac *mac = p->mac; struct cmac *mac = p->mac;
netif_stop_queue(dev); netif_stop_queue(dev);
napi_disable(&adapter->napi);
mac->ops->disable(mac, MAC_DIRECTION_TX | MAC_DIRECTION_RX); mac->ops->disable(mac, MAC_DIRECTION_TX | MAC_DIRECTION_RX);
netif_carrier_off(dev); netif_carrier_off(dev);
...@@ -1113,8 +1117,7 @@ static int __devinit init_one(struct pci_dev *pdev, ...@@ -1113,8 +1117,7 @@ static int __devinit init_one(struct pci_dev *pdev,
netdev->poll_controller = t1_netpoll; netdev->poll_controller = t1_netpoll;
#endif #endif
#ifdef CONFIG_CHELSIO_T1_NAPI #ifdef CONFIG_CHELSIO_T1_NAPI
netdev->weight = 64; netif_napi_add(netdev, &adapter->napi, t1_poll, 64);
netdev->poll = t1_poll;
#endif #endif
SET_ETHTOOL_OPS(netdev, &t1_ethtool_ops); SET_ETHTOOL_OPS(netdev, &t1_ethtool_ops);
......
...@@ -1620,23 +1620,20 @@ static int process_pure_responses(struct adapter *adapter) ...@@ -1620,23 +1620,20 @@ static int process_pure_responses(struct adapter *adapter)
* or protection from interrupts as data interrupts are off at this point and * or protection from interrupts as data interrupts are off at this point and
* other adapter interrupts do not interfere. * other adapter interrupts do not interfere.
*/ */
int t1_poll(struct net_device *dev, int *budget) int t1_poll(struct napi_struct *napi, int budget)
{ {
struct adapter *adapter = dev->priv; struct adapter *adapter = container_of(napi, struct adapter, napi);
struct net_device *dev = adapter->port[0].dev;
int work_done; int work_done;
work_done = process_responses(adapter, min(*budget, dev->quota)); work_done = process_responses(adapter, budget);
*budget -= work_done;
dev->quota -= work_done;
if (unlikely(responses_pending(adapter)))
return 1;
netif_rx_complete(dev);
writel(adapter->sge->respQ.cidx, adapter->regs + A_SG_SLEEPING);
return 0;
if (likely(!responses_pending(adapter))) {
netif_rx_complete(dev, napi);
writel(adapter->sge->respQ.cidx,
adapter->regs + A_SG_SLEEPING);
}
return work_done;
} }
/* /*
...@@ -1653,13 +1650,13 @@ irqreturn_t t1_interrupt(int irq, void *data) ...@@ -1653,13 +1650,13 @@ irqreturn_t t1_interrupt(int irq, void *data)
writel(F_PL_INTR_SGE_DATA, adapter->regs + A_PL_CAUSE); writel(F_PL_INTR_SGE_DATA, adapter->regs + A_PL_CAUSE);
if (__netif_rx_schedule_prep(dev)) { if (napi_schedule_prep(&adapter->napi)) {
if (process_pure_responses(adapter)) if (process_pure_responses(adapter))
__netif_rx_schedule(dev); __netif_rx_schedule(dev, &adapter->napi);
else { else {
/* no data, no NAPI needed */ /* no data, no NAPI needed */
writel(sge->respQ.cidx, adapter->regs + A_SG_SLEEPING); writel(sge->respQ.cidx, adapter->regs + A_SG_SLEEPING);
netif_poll_enable(dev); /* undo schedule_prep */ napi_enable(&adapter->napi); /* undo schedule_prep */
} }
} }
return IRQ_HANDLED; return IRQ_HANDLED;
......
...@@ -77,7 +77,7 @@ int t1_sge_configure(struct sge *, struct sge_params *); ...@@ -77,7 +77,7 @@ int t1_sge_configure(struct sge *, struct sge_params *);
int t1_sge_set_coalesce_params(struct sge *, struct sge_params *); int t1_sge_set_coalesce_params(struct sge *, struct sge_params *);
void t1_sge_destroy(struct sge *); void t1_sge_destroy(struct sge *);
irqreturn_t t1_interrupt(int irq, void *cookie); irqreturn_t t1_interrupt(int irq, void *cookie);
int t1_poll(struct net_device *, int *); int t1_poll(struct napi_struct *, int);
int t1_start_xmit(struct sk_buff *skb, struct net_device *dev); int t1_start_xmit(struct sk_buff *skb, struct net_device *dev);
void t1_set_vlan_accel(struct adapter *adapter, int on_off); void t1_set_vlan_accel(struct adapter *adapter, int on_off);
......
...@@ -49,11 +49,13 @@ ...@@ -49,11 +49,13 @@
typedef irqreturn_t(*intr_handler_t) (int, void *); typedef irqreturn_t(*intr_handler_t) (int, void *);
struct vlan_group; struct vlan_group;
struct adapter; struct adapter;
struct sge_qset;
struct port_info { struct port_info {
struct adapter *adapter; struct adapter *adapter;
struct vlan_group *vlan_grp; struct vlan_group *vlan_grp;
struct sge_qset *qs;
const struct port_type_info *port_type; const struct port_type_info *port_type;
u8 port_id; u8 port_id;
u8 rx_csum_offload; u8 rx_csum_offload;
...@@ -173,10 +175,12 @@ enum { /* per port SGE statistics */ ...@@ -173,10 +175,12 @@ enum { /* per port SGE statistics */
}; };
struct sge_qset { /* an SGE queue set */ struct sge_qset { /* an SGE queue set */
struct adapter *adap;
struct napi_struct napi;
struct sge_rspq rspq; struct sge_rspq rspq;
struct sge_fl fl[SGE_RXQ_PER_SET]; struct sge_fl fl[SGE_RXQ_PER_SET];
struct sge_txq txq[SGE_TXQ_PER_SET]; struct sge_txq txq[SGE_TXQ_PER_SET];
struct net_device *netdev; /* associated net device */ struct net_device *netdev;
unsigned long txq_stopped; /* which Tx queues are stopped */ unsigned long txq_stopped; /* which Tx queues are stopped */
struct timer_list tx_reclaim_timer; /* reclaims TX buffers */ struct timer_list tx_reclaim_timer; /* reclaims TX buffers */
unsigned long port_stats[SGE_PSTAT_MAX]; unsigned long port_stats[SGE_PSTAT_MAX];
...@@ -221,12 +225,6 @@ struct adapter { ...@@ -221,12 +225,6 @@ struct adapter {
struct delayed_work adap_check_task; struct delayed_work adap_check_task;
struct work_struct ext_intr_handler_task; struct work_struct ext_intr_handler_task;
/*
* Dummy netdevices are needed when using multiple receive queues with
* NAPI as each netdevice can service only one queue.
*/
struct net_device *dummy_netdev[SGE_QSETS - 1];
struct dentry *debugfs_root; struct dentry *debugfs_root;
struct mutex mdio_lock; struct mutex mdio_lock;
...@@ -253,12 +251,6 @@ static inline struct port_info *adap2pinfo(struct adapter *adap, int idx) ...@@ -253,12 +251,6 @@ static inline struct port_info *adap2pinfo(struct adapter *adap, int idx)
return netdev_priv(adap->port[idx]); return netdev_priv(adap->port[idx]);
} }
/*
* We use the spare atalk_ptr to map a net device to its SGE queue set.
* This is a macro so it can be used as l-value.
*/
#define dev2qset(netdev) ((netdev)->atalk_ptr)
#define OFFLOAD_DEVMAP_BIT 15 #define OFFLOAD_DEVMAP_BIT 15
#define tdev2adap(d) container_of(d, struct adapter, tdev) #define tdev2adap(d) container_of(d, struct adapter, tdev)
...@@ -284,7 +276,7 @@ int t3_mgmt_tx(struct adapter *adap, struct sk_buff *skb); ...@@ -284,7 +276,7 @@ int t3_mgmt_tx(struct adapter *adap, struct sk_buff *skb);
void t3_update_qset_coalesce(struct sge_qset *qs, const struct qset_params *p); void t3_update_qset_coalesce(struct sge_qset *qs, const struct qset_params *p);
int t3_sge_alloc_qset(struct adapter *adapter, unsigned int id, int nports, int t3_sge_alloc_qset(struct adapter *adapter, unsigned int id, int nports,
int irq_vec_idx, const struct qset_params *p, int irq_vec_idx, const struct qset_params *p,
int ntxq, struct net_device *netdev); int ntxq, struct net_device *dev);
int t3_get_desc(const struct sge_qset *qs, unsigned int qnum, unsigned int idx, int t3_get_desc(const struct sge_qset *qs, unsigned int qnum, unsigned int idx,
unsigned char *data); unsigned char *data);
irqreturn_t t3_sge_intr_msix(int irq, void *cookie); irqreturn_t t3_sge_intr_msix(int irq, void *cookie);
......
...@@ -339,49 +339,17 @@ static void setup_rss(struct adapter *adap) ...@@ -339,49 +339,17 @@ static void setup_rss(struct adapter *adap)
V_RRCPLCPUSIZE(6), cpus, rspq_map); V_RRCPLCPUSIZE(6), cpus, rspq_map);
} }
/* static void init_napi(struct adapter *adap)
* If we have multiple receive queues per port serviced by NAPI we need one
* netdevice per queue as NAPI operates on netdevices. We already have one
* netdevice, namely the one associated with the interface, so we use dummy
* ones for any additional queues. Note that these netdevices exist purely
* so that NAPI has something to work with, they do not represent network
* ports and are not registered.
*/
static int init_dummy_netdevs(struct adapter *adap)
{ {
int i, j, dummy_idx = 0; int i;
struct net_device *nd;
for_each_port(adap, i) {
struct net_device *dev = adap->port[i];
const struct port_info *pi = netdev_priv(dev);
for (j = 0; j < pi->nqsets - 1; j++) {
if (!adap->dummy_netdev[dummy_idx]) {
struct port_info *p;
nd = alloc_netdev(sizeof(*p), "", ether_setup);
if (!nd)
goto free_all;
p = netdev_priv(nd); for (i = 0; i < SGE_QSETS; i++) {
p->adapter = adap; struct sge_qset *qs = &adap->sge.qs[i];
nd->weight = 64;
set_bit(__LINK_STATE_START, &nd->state);
adap->dummy_netdev[dummy_idx] = nd;
}
strcpy(adap->dummy_netdev[dummy_idx]->name, dev->name);
dummy_idx++;
}
}
return 0;
free_all: if (qs->adap)
while (--dummy_idx >= 0) { netif_napi_add(qs->netdev, &qs->napi, qs->napi.poll,
free_netdev(adap->dummy_netdev[dummy_idx]); 64);
adap->dummy_netdev[dummy_idx] = NULL;
} }
return -ENOMEM;
} }
/* /*
...@@ -392,20 +360,18 @@ static int init_dummy_netdevs(struct adapter *adap) ...@@ -392,20 +360,18 @@ static int init_dummy_netdevs(struct adapter *adap)
static void quiesce_rx(struct adapter *adap) static void quiesce_rx(struct adapter *adap)
{ {
int i; int i;
struct net_device *dev;
for_each_port(adap, i) { for (i = 0; i < SGE_QSETS; i++)
dev = adap->port[i]; if (adap->sge.qs[i].adap)
while (test_bit(__LINK_STATE_RX_SCHED, &dev->state)) napi_disable(&adap->sge.qs[i].napi);
msleep(1); }
}
for (i = 0; i < ARRAY_SIZE(adap->dummy_netdev); i++) { static void enable_all_napi(struct adapter *adap)
dev = adap->dummy_netdev[i]; {
if (dev) int i;
while (test_bit(__LINK_STATE_RX_SCHED, &dev->state)) for (i = 0; i < SGE_QSETS; i++)
msleep(1); if (adap->sge.qs[i].adap)
} napi_enable(&adap->sge.qs[i].napi);
} }
/** /**
...@@ -418,7 +384,7 @@ static void quiesce_rx(struct adapter *adap) ...@@ -418,7 +384,7 @@ static void quiesce_rx(struct adapter *adap)
*/ */
static int setup_sge_qsets(struct adapter *adap) static int setup_sge_qsets(struct adapter *adap)
{ {
int i, j, err, irq_idx = 0, qset_idx = 0, dummy_dev_idx = 0; int i, j, err, irq_idx = 0, qset_idx = 0;
unsigned int ntxq = SGE_TXQ_PER_SET; unsigned int ntxq = SGE_TXQ_PER_SET;
if (adap->params.rev > 0 && !(adap->flags & USING_MSI)) if (adap->params.rev > 0 && !(adap->flags & USING_MSI))
...@@ -426,15 +392,14 @@ static int setup_sge_qsets(struct adapter *adap) ...@@ -426,15 +392,14 @@ static int setup_sge_qsets(struct adapter *adap)
for_each_port(adap, i) { for_each_port(adap, i) {
struct net_device *dev = adap->port[i]; struct net_device *dev = adap->port[i];
const struct port_info *pi = netdev_priv(dev); struct port_info *pi = netdev_priv(dev);
pi->qs = &adap->sge.qs[pi->first_qset];
for (j = 0; j < pi->nqsets; ++j, ++qset_idx) { for (j = 0; j < pi->nqsets; ++j, ++qset_idx) {
err = t3_sge_alloc_qset(adap, qset_idx, 1, err = t3_sge_alloc_qset(adap, qset_idx, 1,
(adap->flags & USING_MSIX) ? qset_idx + 1 : (adap->flags & USING_MSIX) ? qset_idx + 1 :
irq_idx, irq_idx,
&adap->params.sge.qset[qset_idx], ntxq, &adap->params.sge.qset[qset_idx], ntxq, dev);
j == 0 ? dev :
adap-> dummy_netdev[dummy_dev_idx++]);
if (err) { if (err) {
t3_free_sge_resources(adap); t3_free_sge_resources(adap);
return err; return err;
...@@ -845,21 +810,18 @@ static int cxgb_up(struct adapter *adap) ...@@ -845,21 +810,18 @@ static int cxgb_up(struct adapter *adap)
goto out; goto out;
} }
err = init_dummy_netdevs(adap);
if (err)
goto out;
err = t3_init_hw(adap, 0); err = t3_init_hw(adap, 0);
if (err) if (err)
goto out; goto out;
t3_write_reg(adap, A_ULPRX_TDDP_PSZ, V_HPZ0(PAGE_SHIFT - 12)); t3_write_reg(adap, A_ULPRX_TDDP_PSZ, V_HPZ0(PAGE_SHIFT - 12));
err = setup_sge_qsets(adap); err = setup_sge_qsets(adap);
if (err) if (err)
goto out; goto out;
setup_rss(adap); setup_rss(adap);
init_napi(adap);
adap->flags |= FULL_INIT_DONE; adap->flags |= FULL_INIT_DONE;
} }
...@@ -886,6 +848,7 @@ static int cxgb_up(struct adapter *adap) ...@@ -886,6 +848,7 @@ static int cxgb_up(struct adapter *adap)
adap->name, adap))) adap->name, adap)))
goto irq_err; goto irq_err;
enable_all_napi(adap);
t3_sge_start(adap); t3_sge_start(adap);
t3_intr_enable(adap); t3_intr_enable(adap);
...@@ -1012,8 +975,10 @@ static int cxgb_open(struct net_device *dev) ...@@ -1012,8 +975,10 @@ static int cxgb_open(struct net_device *dev)
int other_ports = adapter->open_device_map & PORT_MASK; int other_ports = adapter->open_device_map & PORT_MASK;
int err; int err;
if (!adapter->open_device_map && (err = cxgb_up(adapter)) < 0) if (!adapter->open_device_map && (err = cxgb_up(adapter)) < 0) {
quiesce_rx(adapter);
return err; return err;
}
set_bit(pi->port_id, &adapter->open_device_map); set_bit(pi->port_id, &adapter->open_device_map);
if (is_offload(adapter) && !ofld_disable) { if (is_offload(adapter) && !ofld_disable) {
...@@ -2524,7 +2489,6 @@ static int __devinit init_one(struct pci_dev *pdev, ...@@ -2524,7 +2489,6 @@ static int __devinit init_one(struct pci_dev *pdev,
#ifdef CONFIG_NET_POLL_CONTROLLER #ifdef CONFIG_NET_POLL_CONTROLLER
netdev->poll_controller = cxgb_netpoll; netdev->poll_controller = cxgb_netpoll;
#endif #endif
netdev->weight = 64;
SET_ETHTOOL_OPS(netdev, &cxgb_ethtool_ops); SET_ETHTOOL_OPS(netdev, &cxgb_ethtool_ops);
} }
...@@ -2625,12 +2589,6 @@ static void __devexit remove_one(struct pci_dev *pdev) ...@@ -2625,12 +2589,6 @@ static void __devexit remove_one(struct pci_dev *pdev)
t3_free_sge_resources(adapter); t3_free_sge_resources(adapter);
cxgb_disable_msi(adapter); cxgb_disable_msi(adapter);
for (i = 0; i < ARRAY_SIZE(adapter->dummy_netdev); i++)
if (adapter->dummy_netdev[i]) {
free_netdev(adapter->dummy_netdev[i]);
adapter->dummy_netdev[i] = NULL;
}
for_each_port(adapter, i) for_each_port(adapter, i)
if (adapter->port[i]) if (adapter->port[i])
free_netdev(adapter->port[i]); free_netdev(adapter->port[i]);
......
...@@ -591,9 +591,6 @@ void t3_free_qset(struct adapter *adapter, struct sge_qset *q) ...@@ -591,9 +591,6 @@ void t3_free_qset(struct adapter *adapter, struct sge_qset *q)
q->rspq.desc, q->rspq.phys_addr); q->rspq.desc, q->rspq.phys_addr);
} }
if (q->netdev)
q->netdev->atalk_ptr = NULL;
memset(q, 0, sizeof(*q)); memset(q, 0, sizeof(*q));
} }
...@@ -1074,7 +1071,7 @@ int t3_eth_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -1074,7 +1071,7 @@ int t3_eth_xmit(struct sk_buff *skb, struct net_device *dev)
unsigned int ndesc, pidx, credits, gen, compl; unsigned int ndesc, pidx, credits, gen, compl;
const struct port_info *pi = netdev_priv(dev); const struct port_info *pi = netdev_priv(dev);
struct adapter *adap = pi->adapter; struct adapter *adap = pi->adapter;
struct sge_qset *qs = dev2qset(dev); struct sge_qset *qs = pi->qs;
struct sge_txq *q = &qs->txq[TXQ_ETH]; struct sge_txq *q = &qs->txq[TXQ_ETH];
/* /*
...@@ -1326,13 +1323,12 @@ static void restart_ctrlq(unsigned long data) ...@@ -1326,13 +1323,12 @@ static void restart_ctrlq(unsigned long data)
struct sk_buff *skb; struct sk_buff *skb;
struct sge_qset *qs = (struct sge_qset *)data; struct sge_qset *qs = (struct sge_qset *)data;
struct sge_txq *q = &qs->txq[TXQ_CTRL]; struct sge_txq *q = &qs->txq[TXQ_CTRL];
const struct port_info *pi = netdev_priv(qs->netdev);
struct adapter *adap = pi->adapter;
spin_lock(&q->lock); spin_lock(&q->lock);
again:reclaim_completed_tx_imm(q); again:reclaim_completed_tx_imm(q);
while (q->in_use < q->size && (skb = __skb_dequeue(&q->sendq)) != NULL) { while (q->in_use < q->size &&
(skb = __skb_dequeue(&q->sendq)) != NULL) {
write_imm(&q->desc[q->pidx], skb, skb->len, q->gen); write_imm(&q->desc[q->pidx], skb, skb->len, q->gen);
...@@ -1354,7 +1350,7 @@ static void restart_ctrlq(unsigned long data) ...@@ -1354,7 +1350,7 @@ static void restart_ctrlq(unsigned long data)
} }
spin_unlock(&q->lock); spin_unlock(&q->lock);
t3_write_reg(adap, A_SG_KDOORBELL, t3_write_reg(qs->adap, A_SG_KDOORBELL,
F_SELEGRCNTX | V_EGRCNTX(q->cntxt_id)); F_SELEGRCNTX | V_EGRCNTX(q->cntxt_id));
} }
...@@ -1638,8 +1634,7 @@ static inline void offload_enqueue(struct sge_rspq *q, struct sk_buff *skb) ...@@ -1638,8 +1634,7 @@ static inline void offload_enqueue(struct sge_rspq *q, struct sk_buff *skb)
else { else {
struct sge_qset *qs = rspq_to_qset(q); struct sge_qset *qs = rspq_to_qset(q);
if (__netif_rx_schedule_prep(qs->netdev)) napi_schedule(&qs->napi);
__netif_rx_schedule(qs->netdev);
q->rx_head = skb; q->rx_head = skb;
} }
q->rx_tail = skb; q->rx_tail = skb;
...@@ -1675,34 +1670,30 @@ static inline void deliver_partial_bundle(struct t3cdev *tdev, ...@@ -1675,34 +1670,30 @@ static inline void deliver_partial_bundle(struct t3cdev *tdev,
* receive handler. Batches need to be of modest size as we do prefetches * receive handler. Batches need to be of modest size as we do prefetches
* on the packets in each. * on the packets in each.
*/ */
static int ofld_poll(struct net_device *dev, int *budget) static int ofld_poll(struct napi_struct *napi, int budget)
{ {
const struct port_info *pi = netdev_priv(dev); struct sge_qset *qs = container_of(napi, struct sge_qset, napi);
struct adapter *adapter = pi->adapter;
struct sge_qset *qs = dev2qset(dev);
struct sge_rspq *q = &qs->rspq; struct sge_rspq *q = &qs->rspq;
int work_done, limit = min(*budget, dev->quota), avail = limit; struct adapter *adapter = qs->adap;
int work_done = 0;
while (avail) { while (work_done < budget) {
struct sk_buff *head, *tail, *skbs[RX_BUNDLE_SIZE]; struct sk_buff *head, *tail, *skbs[RX_BUNDLE_SIZE];
int ngathered; int ngathered;
spin_lock_irq(&q->lock); spin_lock_irq(&q->lock);
head = q->rx_head; head = q->rx_head;
if (!head) { if (!head) {
work_done = limit - avail; napi_complete(napi);
*budget -= work_done;
dev->quota -= work_done;
__netif_rx_complete(dev);
spin_unlock_irq(&q->lock); spin_unlock_irq(&q->lock);
return 0; return work_done;
} }
tail = q->rx_tail; tail = q->rx_tail;
q->rx_head = q->rx_tail = NULL; q->rx_head = q->rx_tail = NULL;
spin_unlock_irq(&q->lock); spin_unlock_irq(&q->lock);
for (ngathered = 0; avail && head; avail--) { for (ngathered = 0; work_done < budget && head; work_done++) {
prefetch(head->data); prefetch(head->data);
skbs[ngathered] = head; skbs[ngathered] = head;
head = head->next; head = head->next;
...@@ -1724,10 +1715,8 @@ static int ofld_poll(struct net_device *dev, int *budget) ...@@ -1724,10 +1715,8 @@ static int ofld_poll(struct net_device *dev, int *budget)
} }
deliver_partial_bundle(&adapter->tdev, q, skbs, ngathered); deliver_partial_bundle(&adapter->tdev, q, skbs, ngathered);
} }
work_done = limit - avail;
*budget -= work_done; return work_done;
dev->quota -= work_done;
return 1;
} }
/** /**
...@@ -2071,50 +2060,47 @@ static inline int is_pure_response(const struct rsp_desc *r) ...@@ -2071,50 +2060,47 @@ static inline int is_pure_response(const struct rsp_desc *r)
/** /**
* napi_rx_handler - the NAPI handler for Rx processing * napi_rx_handler - the NAPI handler for Rx processing
* @dev: the net device * @napi: the napi instance
* @budget: how many packets we can process in this round * @budget: how many packets we can process in this round
* *
* Handler for new data events when using NAPI. * Handler for new data events when using NAPI.
*/ */
static int napi_rx_handler(struct net_device *dev, int *budget) static int napi_rx_handler(struct napi_struct *napi, int budget)
{ {
const struct port_info *pi = netdev_priv(dev); struct sge_qset *qs = container_of(napi, struct sge_qset, napi);
struct adapter *adap = pi->adapter; struct adapter *adap = qs->adap;
struct sge_qset *qs = dev2qset(dev); int work_done = process_responses(adap, qs, budget);
int effective_budget = min(*budget, dev->quota);
int work_done = process_responses(adap, qs, effective_budget);
*budget -= work_done;
dev->quota -= work_done;
if (work_done >= effective_budget) if (likely(work_done < budget)) {
return 1; napi_complete(napi);
netif_rx_complete(dev);
/* /*
* Because we don't atomically flush the following write it is * Because we don't atomically flush the following
* possible that in very rare cases it can reach the device in a way * write it is possible that in very rare cases it can
* that races with a new response being written plus an error interrupt * reach the device in a way that races with a new
* causing the NAPI interrupt handler below to return unhandled status * response being written plus an error interrupt
* to the OS. To protect against this would require flushing the write * causing the NAPI interrupt handler below to return
* and doing both the write and the flush with interrupts off. Way too * unhandled status to the OS. To protect against
* expensive and unjustifiable given the rarity of the race. * this would require flushing the write and doing
* * both the write and the flush with interrupts off.
* The race cannot happen at all with MSI-X. * Way too expensive and unjustifiable given the
*/ * rarity of the race.
t3_write_reg(adap, A_SG_GTS, V_RSPQ(qs->rspq.cntxt_id) | *
V_NEWTIMER(qs->rspq.next_holdoff) | * The race cannot happen at all with MSI-X.
V_NEWINDEX(qs->rspq.cidx)); */
return 0; t3_write_reg(adap, A_SG_GTS, V_RSPQ(qs->rspq.cntxt_id) |
V_NEWTIMER(qs->rspq.next_holdoff) |
V_NEWINDEX(qs->rspq.cidx));
}
return work_done;
} }
/* /*
* Returns true if the device is already scheduled for polling. * Returns true if the device is already scheduled for polling.
*/ */
static inline int napi_is_scheduled(struct net_device *dev) static inline int napi_is_scheduled(struct napi_struct *napi)
{ {
return test_bit(__LINK_STATE_RX_SCHED, &dev->state); return test_bit(NAPI_STATE_SCHED, &napi->state);
} }
/** /**
...@@ -2197,8 +2183,7 @@ static inline int handle_responses(struct adapter *adap, struct sge_rspq *q) ...@@ -2197,8 +2183,7 @@ static inline int handle_responses(struct adapter *adap, struct sge_rspq *q)
V_NEWTIMER(q->holdoff_tmr) | V_NEWINDEX(q->cidx)); V_NEWTIMER(q->holdoff_tmr) | V_NEWINDEX(q->cidx));
return 0; return 0;
} }
if (likely(__netif_rx_schedule_prep(qs->netdev))) napi_schedule(&qs->napi);
__netif_rx_schedule(qs->netdev);
return 1; return 1;
} }
...@@ -2209,8 +2194,7 @@ static inline int handle_responses(struct adapter *adap, struct sge_rspq *q) ...@@ -2209,8 +2194,7 @@ static inline int handle_responses(struct adapter *adap, struct sge_rspq *q)
irqreturn_t t3_sge_intr_msix(int irq, void *cookie) irqreturn_t t3_sge_intr_msix(int irq, void *cookie)
{ {
struct sge_qset *qs = cookie; struct sge_qset *qs = cookie;
const struct port_info *pi = netdev_priv(qs->netdev); struct adapter *adap = qs->adap;
struct adapter *adap = pi->adapter;
struct sge_rspq *q = &qs->rspq; struct sge_rspq *q = &qs->rspq;
spin_lock(&q->lock); spin_lock(&q->lock);
...@@ -2229,13 +2213,11 @@ irqreturn_t t3_sge_intr_msix(int irq, void *cookie) ...@@ -2229,13 +2213,11 @@ irqreturn_t t3_sge_intr_msix(int irq, void *cookie)
irqreturn_t t3_sge_intr_msix_napi(int irq, void *cookie) irqreturn_t t3_sge_intr_msix_napi(int irq, void *cookie)
{ {
struct sge_qset *qs = cookie; struct sge_qset *qs = cookie;
const struct port_info *pi = netdev_priv(qs->netdev);
struct adapter *adap = pi->adapter;
struct sge_rspq *q = &qs->rspq; struct sge_rspq *q = &qs->rspq;
spin_lock(&q->lock); spin_lock(&q->lock);
if (handle_responses(adap, q) < 0) if (handle_responses(qs->adap, q) < 0)
q->unhandled_irqs++; q->unhandled_irqs++;
spin_unlock(&q->lock); spin_unlock(&q->lock);
return IRQ_HANDLED; return IRQ_HANDLED;
...@@ -2278,11 +2260,13 @@ static irqreturn_t t3_intr_msi(int irq, void *cookie) ...@@ -2278,11 +2260,13 @@ static irqreturn_t t3_intr_msi(int irq, void *cookie)
return IRQ_HANDLED; return IRQ_HANDLED;
} }
static int rspq_check_napi(struct net_device *dev, struct sge_rspq *q) static int rspq_check_napi(struct sge_qset *qs)
{ {
if (!napi_is_scheduled(dev) && is_new_response(&q->desc[q->cidx], q)) { struct sge_rspq *q = &qs->rspq;
if (likely(__netif_rx_schedule_prep(dev)))
__netif_rx_schedule(dev); if (!napi_is_scheduled(&qs->napi) &&
is_new_response(&q->desc[q->cidx], q)) {
napi_schedule(&qs->napi);
return 1; return 1;
} }
return 0; return 0;
...@@ -2303,10 +2287,9 @@ irqreturn_t t3_intr_msi_napi(int irq, void *cookie) ...@@ -2303,10 +2287,9 @@ irqreturn_t t3_intr_msi_napi(int irq, void *cookie)
spin_lock(&q->lock); spin_lock(&q->lock);
new_packets = rspq_check_napi(adap->sge.qs[0].netdev, q); new_packets = rspq_check_napi(&adap->sge.qs[0]);
if (adap->params.nports == 2) if (adap->params.nports == 2)
new_packets += rspq_check_napi(adap->sge.qs[1].netdev, new_packets += rspq_check_napi(&adap->sge.qs[1]);
&adap->sge.qs[1].rspq);
if (!new_packets && t3_slow_intr_handler(adap) == 0) if (!new_packets && t3_slow_intr_handler(adap) == 0)
q->unhandled_irqs++; q->unhandled_irqs++;
...@@ -2409,9 +2392,9 @@ static irqreturn_t t3b_intr(int irq, void *cookie) ...@@ -2409,9 +2392,9 @@ static irqreturn_t t3b_intr(int irq, void *cookie)
static irqreturn_t t3b_intr_napi(int irq, void *cookie) static irqreturn_t t3b_intr_napi(int irq, void *cookie)
{ {
u32 map; u32 map;
struct net_device *dev;
struct adapter *adap = cookie; struct adapter *adap = cookie;
struct sge_rspq *q0 = &adap->sge.qs[0].rspq; struct sge_qset *qs0 = &adap->sge.qs[0];
struct sge_rspq *q0 = &qs0->rspq;
t3_write_reg(adap, A_PL_CLI, 0); t3_write_reg(adap, A_PL_CLI, 0);
map = t3_read_reg(adap, A_SG_DATA_INTR); map = t3_read_reg(adap, A_SG_DATA_INTR);
...@@ -2424,18 +2407,11 @@ static irqreturn_t t3b_intr_napi(int irq, void *cookie) ...@@ -2424,18 +2407,11 @@ static irqreturn_t t3b_intr_napi(int irq, void *cookie)
if (unlikely(map & F_ERRINTR)) if (unlikely(map & F_ERRINTR))
t3_slow_intr_handler(adap); t3_slow_intr_handler(adap);
if (likely(map & 1)) { if (likely(map & 1))
dev = adap->sge.qs[0].netdev; napi_schedule(&qs0->napi);
if (likely(__netif_rx_schedule_prep(dev)))
__netif_rx_schedule(dev);
}
if (map & 2) {
dev = adap->sge.qs[1].netdev;
if (likely(__netif_rx_schedule_prep(dev))) if (map & 2)
__netif_rx_schedule(dev); napi_schedule(&adap->sge.qs[1].napi);
}
spin_unlock(&q0->lock); spin_unlock(&q0->lock);
return IRQ_HANDLED; return IRQ_HANDLED;
...@@ -2514,8 +2490,7 @@ static void sge_timer_cb(unsigned long data) ...@@ -2514,8 +2490,7 @@ static void sge_timer_cb(unsigned long data)
{ {
spinlock_t *lock; spinlock_t *lock;
struct sge_qset *qs = (struct sge_qset *)data; struct sge_qset *qs = (struct sge_qset *)data;
const struct port_info *pi = netdev_priv(qs->netdev); struct adapter *adap = qs->adap;
struct adapter *adap = pi->adapter;
if (spin_trylock(&qs->txq[TXQ_ETH].lock)) { if (spin_trylock(&qs->txq[TXQ_ETH].lock)) {
reclaim_completed_tx(adap, &qs->txq[TXQ_ETH]); reclaim_completed_tx(adap, &qs->txq[TXQ_ETH]);
...@@ -2526,9 +2501,9 @@ static void sge_timer_cb(unsigned long data) ...@@ -2526,9 +2501,9 @@ static void sge_timer_cb(unsigned long data)
spin_unlock(&qs->txq[TXQ_OFLD].lock); spin_unlock(&qs->txq[TXQ_OFLD].lock);
} }
lock = (adap->flags & USING_MSIX) ? &qs->rspq.lock : lock = (adap->flags & USING_MSIX) ? &qs->rspq.lock :
&adap->sge.qs[0].rspq.lock; &adap->sge.qs[0].rspq.lock;
if (spin_trylock_irq(lock)) { if (spin_trylock_irq(lock)) {
if (!napi_is_scheduled(qs->netdev)) { if (!napi_is_scheduled(&qs->napi)) {
u32 status = t3_read_reg(adap, A_SG_RSPQ_FL_STATUS); u32 status = t3_read_reg(adap, A_SG_RSPQ_FL_STATUS);
if (qs->fl[0].credits < qs->fl[0].size) if (qs->fl[0].credits < qs->fl[0].size)
...@@ -2562,12 +2537,9 @@ static void sge_timer_cb(unsigned long data) ...@@ -2562,12 +2537,9 @@ static void sge_timer_cb(unsigned long data)
*/ */
void t3_update_qset_coalesce(struct sge_qset *qs, const struct qset_params *p) void t3_update_qset_coalesce(struct sge_qset *qs, const struct qset_params *p)
{ {
if (!qs->netdev)
return;
qs->rspq.holdoff_tmr = max(p->coalesce_usecs * 10, 1U);/* can't be 0 */ qs->rspq.holdoff_tmr = max(p->coalesce_usecs * 10, 1U);/* can't be 0 */
qs->rspq.polling = p->polling; qs->rspq.polling = p->polling;
qs->netdev->poll = p->polling ? napi_rx_handler : ofld_poll; qs->napi.poll = p->polling ? napi_rx_handler : ofld_poll;
} }
/** /**
...@@ -2587,7 +2559,7 @@ void t3_update_qset_coalesce(struct sge_qset *qs, const struct qset_params *p) ...@@ -2587,7 +2559,7 @@ void t3_update_qset_coalesce(struct sge_qset *qs, const struct qset_params *p)
*/ */
int t3_sge_alloc_qset(struct adapter *adapter, unsigned int id, int nports, int t3_sge_alloc_qset(struct adapter *adapter, unsigned int id, int nports,
int irq_vec_idx, const struct qset_params *p, int irq_vec_idx, const struct qset_params *p,
int ntxq, struct net_device *netdev) int ntxq, struct net_device *dev)
{ {
int i, ret = -ENOMEM; int i, ret = -ENOMEM;
struct sge_qset *q = &adapter->sge.qs[id]; struct sge_qset *q = &adapter->sge.qs[id];
...@@ -2708,16 +2680,10 @@ int t3_sge_alloc_qset(struct adapter *adapter, unsigned int id, int nports, ...@@ -2708,16 +2680,10 @@ int t3_sge_alloc_qset(struct adapter *adapter, unsigned int id, int nports,
} }
spin_unlock(&adapter->sge.reg_lock); spin_unlock(&adapter->sge.reg_lock);
q->netdev = netdev;
t3_update_qset_coalesce(q, p);
/* q->adap = adapter;
* We use atalk_ptr as a backpointer to a qset. In case a device is q->netdev = dev;
* associated with multiple queue sets only the first one sets t3_update_qset_coalesce(q, p);
* atalk_ptr.
*/
if (netdev->atalk_ptr == NULL)
netdev->atalk_ptr = q;
refill_fl(adapter, &q->fl[0], q->fl[0].size, GFP_KERNEL); refill_fl(adapter, &q->fl[0], q->fl[0].size, GFP_KERNEL);
refill_fl(adapter, &q->fl[1], q->fl[1].size, GFP_KERNEL); refill_fl(adapter, &q->fl[1], q->fl[1].size, GFP_KERNEL);
......
...@@ -539,6 +539,7 @@ struct nic { ...@@ -539,6 +539,7 @@ struct nic {
struct csr __iomem *csr; struct csr __iomem *csr;
enum scb_cmd_lo cuc_cmd; enum scb_cmd_lo cuc_cmd;
unsigned int cbs_avail; unsigned int cbs_avail;
struct napi_struct napi;
struct cb *cbs; struct cb *cbs;
struct cb *cb_to_use; struct cb *cb_to_use;
struct cb *cb_to_send; struct cb *cb_to_send;
...@@ -1974,35 +1975,31 @@ static irqreturn_t e100_intr(int irq, void *dev_id) ...@@ -1974,35 +1975,31 @@ static irqreturn_t e100_intr(int irq, void *dev_id)
if(stat_ack & stat_ack_rnr) if(stat_ack & stat_ack_rnr)
nic->ru_running = RU_SUSPENDED; nic->ru_running = RU_SUSPENDED;
if(likely(netif_rx_schedule_prep(netdev))) { if(likely(netif_rx_schedule_prep(netdev, &nic->napi))) {
e100_disable_irq(nic); e100_disable_irq(nic);
__netif_rx_schedule(netdev); __netif_rx_schedule(netdev, &nic->napi);
} }
return IRQ_HANDLED; return IRQ_HANDLED;
} }
static int e100_poll(struct net_device *netdev, int *budget) static int e100_poll(struct napi_struct *napi, int budget)
{ {
struct nic *nic = netdev_priv(netdev); struct nic *nic = container_of(napi, struct nic, napi);
unsigned int work_to_do = min(netdev->quota, *budget); struct net_device *netdev = nic->netdev;
unsigned int work_done = 0; int work_done = 0;
int tx_cleaned; int tx_cleaned;
e100_rx_clean(nic, &work_done, work_to_do); e100_rx_clean(nic, &work_done, budget);
tx_cleaned = e100_tx_clean(nic); tx_cleaned = e100_tx_clean(nic);
/* If no Rx and Tx cleanup work was done, exit polling mode. */ /* If no Rx and Tx cleanup work was done, exit polling mode. */
if((!tx_cleaned && (work_done == 0)) || !netif_running(netdev)) { if((!tx_cleaned && (work_done == 0)) || !netif_running(netdev)) {
netif_rx_complete(netdev); netif_rx_complete(netdev, napi);
e100_enable_irq(nic); e100_enable_irq(nic);
return 0;
} }
*budget -= work_done; return work_done;
netdev->quota -= work_done;
return 1;
} }
#ifdef CONFIG_NET_POLL_CONTROLLER #ifdef CONFIG_NET_POLL_CONTROLLER
...@@ -2071,7 +2068,7 @@ static int e100_up(struct nic *nic) ...@@ -2071,7 +2068,7 @@ static int e100_up(struct nic *nic)
nic->netdev->name, nic->netdev))) nic->netdev->name, nic->netdev)))
goto err_no_irq; goto err_no_irq;
netif_wake_queue(nic->netdev); netif_wake_queue(nic->netdev);
netif_poll_enable(nic->netdev); napi_enable(&nic->napi);
/* enable ints _after_ enabling poll, preventing a race between /* enable ints _after_ enabling poll, preventing a race between
* disable ints+schedule */ * disable ints+schedule */
e100_enable_irq(nic); e100_enable_irq(nic);
...@@ -2089,7 +2086,7 @@ static int e100_up(struct nic *nic) ...@@ -2089,7 +2086,7 @@ static int e100_up(struct nic *nic)
static void e100_down(struct nic *nic) static void e100_down(struct nic *nic)
{ {
/* wait here for poll to complete */ /* wait here for poll to complete */
netif_poll_disable(nic->netdev); napi_disable(&nic->napi);
netif_stop_queue(nic->netdev); netif_stop_queue(nic->netdev);
e100_hw_reset(nic); e100_hw_reset(nic);
free_irq(nic->pdev->irq, nic->netdev); free_irq(nic->pdev->irq, nic->netdev);
...@@ -2572,14 +2569,13 @@ static int __devinit e100_probe(struct pci_dev *pdev, ...@@ -2572,14 +2569,13 @@ static int __devinit e100_probe(struct pci_dev *pdev,
SET_ETHTOOL_OPS(netdev, &e100_ethtool_ops); SET_ETHTOOL_OPS(netdev, &e100_ethtool_ops);
netdev->tx_timeout = e100_tx_timeout; netdev->tx_timeout = e100_tx_timeout;
netdev->watchdog_timeo = E100_WATCHDOG_PERIOD; netdev->watchdog_timeo = E100_WATCHDOG_PERIOD;
netdev->poll = e100_poll;
netdev->weight = E100_NAPI_WEIGHT;
#ifdef CONFIG_NET_POLL_CONTROLLER #ifdef CONFIG_NET_POLL_CONTROLLER
netdev->poll_controller = e100_netpoll; netdev->poll_controller = e100_netpoll;
#endif #endif
strncpy(netdev->name, pci_name(pdev), sizeof(netdev->name) - 1); strncpy(netdev->name, pci_name(pdev), sizeof(netdev->name) - 1);
nic = netdev_priv(netdev); nic = netdev_priv(netdev);
netif_napi_add(netdev, &nic->napi, e100_poll, E100_NAPI_WEIGHT);
nic->netdev = netdev; nic->netdev = netdev;
nic->pdev = pdev; nic->pdev = pdev;
nic->msg_enable = (1 << debug) - 1; nic->msg_enable = (1 << debug) - 1;
...@@ -2733,7 +2729,7 @@ static int e100_suspend(struct pci_dev *pdev, pm_message_t state) ...@@ -2733,7 +2729,7 @@ static int e100_suspend(struct pci_dev *pdev, pm_message_t state)
struct nic *nic = netdev_priv(netdev); struct nic *nic = netdev_priv(netdev);
if (netif_running(netdev)) if (netif_running(netdev))
netif_poll_disable(nic->netdev); napi_disable(&nic->napi);
del_timer_sync(&nic->watchdog); del_timer_sync(&nic->watchdog);
netif_carrier_off(nic->netdev); netif_carrier_off(nic->netdev);
netif_device_detach(netdev); netif_device_detach(netdev);
...@@ -2779,7 +2775,7 @@ static void e100_shutdown(struct pci_dev *pdev) ...@@ -2779,7 +2775,7 @@ static void e100_shutdown(struct pci_dev *pdev)
struct nic *nic = netdev_priv(netdev); struct nic *nic = netdev_priv(netdev);
if (netif_running(netdev)) if (netif_running(netdev))
netif_poll_disable(nic->netdev); napi_disable(&nic->napi);
del_timer_sync(&nic->watchdog); del_timer_sync(&nic->watchdog);
netif_carrier_off(nic->netdev); netif_carrier_off(nic->netdev);
...@@ -2804,12 +2800,13 @@ static void e100_shutdown(struct pci_dev *pdev) ...@@ -2804,12 +2800,13 @@ static void e100_shutdown(struct pci_dev *pdev)
static pci_ers_result_t e100_io_error_detected(struct pci_dev *pdev, pci_channel_state_t state) static pci_ers_result_t e100_io_error_detected(struct pci_dev *pdev, pci_channel_state_t state)
{ {
struct net_device *netdev = pci_get_drvdata(pdev); struct net_device *netdev = pci_get_drvdata(pdev);
struct nic *nic = netdev_priv(netdev);
/* Similar to calling e100_down(), but avoids adpater I/O. */ /* Similar to calling e100_down(), but avoids adpater I/O. */
netdev->stop(netdev); netdev->stop(netdev);
/* Detach; put netif into state similar to hotplug unplug. */ /* Detach; put netif into state similar to hotplug unplug. */
netif_poll_enable(netdev); napi_enable(&nic->napi);
netif_device_detach(netdev); netif_device_detach(netdev);
pci_disable_device(pdev); pci_disable_device(pdev);
......
...@@ -300,6 +300,7 @@ struct e1000_adapter { ...@@ -300,6 +300,7 @@ struct e1000_adapter {
int cleaned_count); int cleaned_count);
struct e1000_rx_ring *rx_ring; /* One per active queue */ struct e1000_rx_ring *rx_ring; /* One per active queue */
#ifdef CONFIG_E1000_NAPI #ifdef CONFIG_E1000_NAPI
struct napi_struct napi;
struct net_device *polling_netdev; /* One per active queue */ struct net_device *polling_netdev; /* One per active queue */
#endif #endif
int num_tx_queues; int num_tx_queues;
......
...@@ -166,7 +166,7 @@ static irqreturn_t e1000_intr_msi(int irq, void *data); ...@@ -166,7 +166,7 @@ static irqreturn_t e1000_intr_msi(int irq, void *data);
static boolean_t e1000_clean_tx_irq(struct e1000_adapter *adapter, static boolean_t e1000_clean_tx_irq(struct e1000_adapter *adapter,
struct e1000_tx_ring *tx_ring); struct e1000_tx_ring *tx_ring);
#ifdef CONFIG_E1000_NAPI #ifdef CONFIG_E1000_NAPI
static int e1000_clean(struct net_device *poll_dev, int *budget); static int e1000_clean(struct napi_struct *napi, int budget);
static boolean_t e1000_clean_rx_irq(struct e1000_adapter *adapter, static boolean_t e1000_clean_rx_irq(struct e1000_adapter *adapter,
struct e1000_rx_ring *rx_ring, struct e1000_rx_ring *rx_ring,
int *work_done, int work_to_do); int *work_done, int work_to_do);
...@@ -545,7 +545,7 @@ int e1000_up(struct e1000_adapter *adapter) ...@@ -545,7 +545,7 @@ int e1000_up(struct e1000_adapter *adapter)
clear_bit(__E1000_DOWN, &adapter->flags); clear_bit(__E1000_DOWN, &adapter->flags);
#ifdef CONFIG_E1000_NAPI #ifdef CONFIG_E1000_NAPI
netif_poll_enable(adapter->netdev); napi_enable(&adapter->napi);
#endif #endif
e1000_irq_enable(adapter); e1000_irq_enable(adapter);
...@@ -634,7 +634,7 @@ e1000_down(struct e1000_adapter *adapter) ...@@ -634,7 +634,7 @@ e1000_down(struct e1000_adapter *adapter)
set_bit(__E1000_DOWN, &adapter->flags); set_bit(__E1000_DOWN, &adapter->flags);
#ifdef CONFIG_E1000_NAPI #ifdef CONFIG_E1000_NAPI
netif_poll_disable(netdev); napi_disable(&adapter->napi);
#endif #endif
e1000_irq_disable(adapter); e1000_irq_disable(adapter);
...@@ -936,8 +936,7 @@ e1000_probe(struct pci_dev *pdev, ...@@ -936,8 +936,7 @@ e1000_probe(struct pci_dev *pdev,
netdev->tx_timeout = &e1000_tx_timeout; netdev->tx_timeout = &e1000_tx_timeout;
netdev->watchdog_timeo = 5 * HZ; netdev->watchdog_timeo = 5 * HZ;
#ifdef CONFIG_E1000_NAPI #ifdef CONFIG_E1000_NAPI
netdev->poll = &e1000_clean; netif_napi_add(netdev, &adapter->napi, e1000_clean, 64);
netdev->weight = 64;
#endif #endif
netdev->vlan_rx_register = e1000_vlan_rx_register; netdev->vlan_rx_register = e1000_vlan_rx_register;
netdev->vlan_rx_add_vid = e1000_vlan_rx_add_vid; netdev->vlan_rx_add_vid = e1000_vlan_rx_add_vid;
...@@ -1151,9 +1150,6 @@ e1000_probe(struct pci_dev *pdev, ...@@ -1151,9 +1150,6 @@ e1000_probe(struct pci_dev *pdev,
/* tell the stack to leave us alone until e1000_open() is called */ /* tell the stack to leave us alone until e1000_open() is called */
netif_carrier_off(netdev); netif_carrier_off(netdev);
netif_stop_queue(netdev); netif_stop_queue(netdev);
#ifdef CONFIG_E1000_NAPI
netif_poll_disable(netdev);
#endif
strcpy(netdev->name, "eth%d"); strcpy(netdev->name, "eth%d");
if ((err = register_netdev(netdev))) if ((err = register_netdev(netdev)))
...@@ -1222,12 +1218,13 @@ e1000_remove(struct pci_dev *pdev) ...@@ -1222,12 +1218,13 @@ e1000_remove(struct pci_dev *pdev)
* would have already happened in close and is redundant. */ * would have already happened in close and is redundant. */
e1000_release_hw_control(adapter); e1000_release_hw_control(adapter);
unregister_netdev(netdev);
#ifdef CONFIG_E1000_NAPI #ifdef CONFIG_E1000_NAPI
for (i = 0; i < adapter->num_rx_queues; i++) for (i = 0; i < adapter->num_rx_queues; i++)
dev_put(&adapter->polling_netdev[i]); dev_put(&adapter->polling_netdev[i]);
#endif #endif
unregister_netdev(netdev);
if (!e1000_check_phy_reset_block(&adapter->hw)) if (!e1000_check_phy_reset_block(&adapter->hw))
e1000_phy_hw_reset(&adapter->hw); e1000_phy_hw_reset(&adapter->hw);
...@@ -1325,8 +1322,6 @@ e1000_sw_init(struct e1000_adapter *adapter) ...@@ -1325,8 +1322,6 @@ e1000_sw_init(struct e1000_adapter *adapter)
#ifdef CONFIG_E1000_NAPI #ifdef CONFIG_E1000_NAPI
for (i = 0; i < adapter->num_rx_queues; i++) { for (i = 0; i < adapter->num_rx_queues; i++) {
adapter->polling_netdev[i].priv = adapter; adapter->polling_netdev[i].priv = adapter;
adapter->polling_netdev[i].poll = &e1000_clean;
adapter->polling_netdev[i].weight = 64;
dev_hold(&adapter->polling_netdev[i]); dev_hold(&adapter->polling_netdev[i]);
set_bit(__LINK_STATE_START, &adapter->polling_netdev[i].state); set_bit(__LINK_STATE_START, &adapter->polling_netdev[i].state);
} }
...@@ -1443,7 +1438,7 @@ e1000_open(struct net_device *netdev) ...@@ -1443,7 +1438,7 @@ e1000_open(struct net_device *netdev)
clear_bit(__E1000_DOWN, &adapter->flags); clear_bit(__E1000_DOWN, &adapter->flags);
#ifdef CONFIG_E1000_NAPI #ifdef CONFIG_E1000_NAPI
netif_poll_enable(netdev); napi_enable(&adapter->napi);
#endif #endif
e1000_irq_enable(adapter); e1000_irq_enable(adapter);
...@@ -3786,12 +3781,12 @@ e1000_intr_msi(int irq, void *data) ...@@ -3786,12 +3781,12 @@ e1000_intr_msi(int irq, void *data)
} }
#ifdef CONFIG_E1000_NAPI #ifdef CONFIG_E1000_NAPI
if (likely(netif_rx_schedule_prep(netdev))) { if (likely(netif_rx_schedule_prep(netdev, &adapter->napi))) {
adapter->total_tx_bytes = 0; adapter->total_tx_bytes = 0;
adapter->total_tx_packets = 0; adapter->total_tx_packets = 0;
adapter->total_rx_bytes = 0; adapter->total_rx_bytes = 0;
adapter->total_rx_packets = 0; adapter->total_rx_packets = 0;
__netif_rx_schedule(netdev); __netif_rx_schedule(netdev, &adapter->napi);
} else } else
e1000_irq_enable(adapter); e1000_irq_enable(adapter);
#else #else
...@@ -3871,12 +3866,12 @@ e1000_intr(int irq, void *data) ...@@ -3871,12 +3866,12 @@ e1000_intr(int irq, void *data)
E1000_WRITE_REG(hw, IMC, ~0); E1000_WRITE_REG(hw, IMC, ~0);
E1000_WRITE_FLUSH(hw); E1000_WRITE_FLUSH(hw);
} }
if (likely(netif_rx_schedule_prep(netdev))) { if (likely(netif_rx_schedule_prep(netdev, &adapter->napi))) {
adapter->total_tx_bytes = 0; adapter->total_tx_bytes = 0;
adapter->total_tx_packets = 0; adapter->total_tx_packets = 0;
adapter->total_rx_bytes = 0; adapter->total_rx_bytes = 0;
adapter->total_rx_packets = 0; adapter->total_rx_packets = 0;
__netif_rx_schedule(netdev); __netif_rx_schedule(netdev, &adapter->napi);
} else } else
/* this really should not happen! if it does it is basically a /* this really should not happen! if it does it is basically a
* bug, but not a hard error, so enable ints and continue */ * bug, but not a hard error, so enable ints and continue */
...@@ -3924,10 +3919,10 @@ e1000_intr(int irq, void *data) ...@@ -3924,10 +3919,10 @@ e1000_intr(int irq, void *data)
**/ **/
static int static int
e1000_clean(struct net_device *poll_dev, int *budget) e1000_clean(struct napi_struct *napi, int budget)
{ {
struct e1000_adapter *adapter; struct e1000_adapter *adapter = container_of(napi, struct e1000_adapter, napi);
int work_to_do = min(*budget, poll_dev->quota); struct net_device *poll_dev = adapter->netdev;
int tx_cleaned = 0, work_done = 0; int tx_cleaned = 0, work_done = 0;
/* Must NOT use netdev_priv macro here. */ /* Must NOT use netdev_priv macro here. */
...@@ -3948,23 +3943,19 @@ e1000_clean(struct net_device *poll_dev, int *budget) ...@@ -3948,23 +3943,19 @@ e1000_clean(struct net_device *poll_dev, int *budget)
} }
adapter->clean_rx(adapter, &adapter->rx_ring[0], adapter->clean_rx(adapter, &adapter->rx_ring[0],
&work_done, work_to_do); &work_done, budget);
*budget -= work_done;
poll_dev->quota -= work_done;
/* If no Tx and not enough Rx work done, exit the polling mode */ /* If no Tx and not enough Rx work done, exit the polling mode */
if ((!tx_cleaned && (work_done == 0)) || if ((!tx_cleaned && (work_done < budget)) ||
!netif_running(poll_dev)) { !netif_running(poll_dev)) {
quit_polling: quit_polling:
if (likely(adapter->itr_setting & 3)) if (likely(adapter->itr_setting & 3))
e1000_set_itr(adapter); e1000_set_itr(adapter);
netif_rx_complete(poll_dev); netif_rx_complete(poll_dev, napi);
e1000_irq_enable(adapter); e1000_irq_enable(adapter);
return 0;
} }
return 1; return work_done;
} }
#endif #endif
......
...@@ -351,6 +351,7 @@ struct ehea_q_skb_arr { ...@@ -351,6 +351,7 @@ struct ehea_q_skb_arr {
* Port resources * Port resources
*/ */
struct ehea_port_res { struct ehea_port_res {
struct napi_struct napi;
struct port_stats p_stats; struct port_stats p_stats;
struct ehea_mr send_mr; /* send memory region */ struct ehea_mr send_mr; /* send memory region */
struct ehea_mr recv_mr; /* receive memory region */ struct ehea_mr recv_mr; /* receive memory region */
...@@ -362,7 +363,6 @@ struct ehea_port_res { ...@@ -362,7 +363,6 @@ struct ehea_port_res {
struct ehea_cq *send_cq; struct ehea_cq *send_cq;
struct ehea_cq *recv_cq; struct ehea_cq *recv_cq;
struct ehea_eq *eq; struct ehea_eq *eq;
struct net_device *d_netdev;
struct ehea_q_skb_arr rq1_skba; struct ehea_q_skb_arr rq1_skba;
struct ehea_q_skb_arr rq2_skba; struct ehea_q_skb_arr rq2_skba;
struct ehea_q_skb_arr rq3_skba; struct ehea_q_skb_arr rq3_skba;
......
...@@ -393,9 +393,9 @@ static int ehea_treat_poll_error(struct ehea_port_res *pr, int rq, ...@@ -393,9 +393,9 @@ static int ehea_treat_poll_error(struct ehea_port_res *pr, int rq,
return 0; return 0;
} }
static struct ehea_cqe *ehea_proc_rwqes(struct net_device *dev, static int ehea_proc_rwqes(struct net_device *dev,
struct ehea_port_res *pr, struct ehea_port_res *pr,
int *budget) int budget)
{ {
struct ehea_port *port = pr->port; struct ehea_port *port = pr->port;
struct ehea_qp *qp = pr->qp; struct ehea_qp *qp = pr->qp;
...@@ -408,18 +408,16 @@ static struct ehea_cqe *ehea_proc_rwqes(struct net_device *dev, ...@@ -408,18 +408,16 @@ static struct ehea_cqe *ehea_proc_rwqes(struct net_device *dev,
int skb_arr_rq2_len = pr->rq2_skba.len; int skb_arr_rq2_len = pr->rq2_skba.len;
int skb_arr_rq3_len = pr->rq3_skba.len; int skb_arr_rq3_len = pr->rq3_skba.len;
int processed, processed_rq1, processed_rq2, processed_rq3; int processed, processed_rq1, processed_rq2, processed_rq3;
int wqe_index, last_wqe_index, rq, my_quota, port_reset; int wqe_index, last_wqe_index, rq, port_reset;
processed = processed_rq1 = processed_rq2 = processed_rq3 = 0; processed = processed_rq1 = processed_rq2 = processed_rq3 = 0;
last_wqe_index = 0; last_wqe_index = 0;
my_quota = min(*budget, dev->quota);
cqe = ehea_poll_rq1(qp, &wqe_index); cqe = ehea_poll_rq1(qp, &wqe_index);
while ((my_quota > 0) && cqe) { while ((processed < budget) && cqe) {
ehea_inc_rq1(qp); ehea_inc_rq1(qp);
processed_rq1++; processed_rq1++;
processed++; processed++;
my_quota--;
if (netif_msg_rx_status(port)) if (netif_msg_rx_status(port))
ehea_dump(cqe, sizeof(*cqe), "CQE"); ehea_dump(cqe, sizeof(*cqe), "CQE");
...@@ -434,14 +432,14 @@ static struct ehea_cqe *ehea_proc_rwqes(struct net_device *dev, ...@@ -434,14 +432,14 @@ static struct ehea_cqe *ehea_proc_rwqes(struct net_device *dev,
if (netif_msg_rx_err(port)) if (netif_msg_rx_err(port))
ehea_error("LL rq1: skb=NULL"); ehea_error("LL rq1: skb=NULL");
skb = netdev_alloc_skb(port->netdev, skb = netdev_alloc_skb(dev,
EHEA_L_PKT_SIZE); EHEA_L_PKT_SIZE);
if (!skb) if (!skb)
break; break;
} }
skb_copy_to_linear_data(skb, ((char*)cqe) + 64, skb_copy_to_linear_data(skb, ((char*)cqe) + 64,
cqe->num_bytes_transfered - 4); cqe->num_bytes_transfered - 4);
ehea_fill_skb(port->netdev, skb, cqe); ehea_fill_skb(dev, skb, cqe);
} else if (rq == 2) { /* RQ2 */ } else if (rq == 2) { /* RQ2 */
skb = get_skb_by_index(skb_arr_rq2, skb = get_skb_by_index(skb_arr_rq2,
skb_arr_rq2_len, cqe); skb_arr_rq2_len, cqe);
...@@ -450,7 +448,7 @@ static struct ehea_cqe *ehea_proc_rwqes(struct net_device *dev, ...@@ -450,7 +448,7 @@ static struct ehea_cqe *ehea_proc_rwqes(struct net_device *dev,
ehea_error("rq2: skb=NULL"); ehea_error("rq2: skb=NULL");
break; break;
} }
ehea_fill_skb(port->netdev, skb, cqe); ehea_fill_skb(dev, skb, cqe);
processed_rq2++; processed_rq2++;
} else { /* RQ3 */ } else { /* RQ3 */
skb = get_skb_by_index(skb_arr_rq3, skb = get_skb_by_index(skb_arr_rq3,
...@@ -460,7 +458,7 @@ static struct ehea_cqe *ehea_proc_rwqes(struct net_device *dev, ...@@ -460,7 +458,7 @@ static struct ehea_cqe *ehea_proc_rwqes(struct net_device *dev,
ehea_error("rq3: skb=NULL"); ehea_error("rq3: skb=NULL");
break; break;
} }
ehea_fill_skb(port->netdev, skb, cqe); ehea_fill_skb(dev, skb, cqe);
processed_rq3++; processed_rq3++;
} }
...@@ -471,7 +469,7 @@ static struct ehea_cqe *ehea_proc_rwqes(struct net_device *dev, ...@@ -471,7 +469,7 @@ static struct ehea_cqe *ehea_proc_rwqes(struct net_device *dev,
else else
netif_receive_skb(skb); netif_receive_skb(skb);
port->netdev->last_rx = jiffies; dev->last_rx = jiffies;
} else { } else {
pr->p_stats.poll_receive_errors++; pr->p_stats.poll_receive_errors++;
port_reset = ehea_treat_poll_error(pr, rq, cqe, port_reset = ehea_treat_poll_error(pr, rq, cqe,
...@@ -484,14 +482,12 @@ static struct ehea_cqe *ehea_proc_rwqes(struct net_device *dev, ...@@ -484,14 +482,12 @@ static struct ehea_cqe *ehea_proc_rwqes(struct net_device *dev,
} }
pr->rx_packets += processed; pr->rx_packets += processed;
*budget -= processed;
ehea_refill_rq1(pr, last_wqe_index, processed_rq1); ehea_refill_rq1(pr, last_wqe_index, processed_rq1);
ehea_refill_rq2(pr, processed_rq2); ehea_refill_rq2(pr, processed_rq2);
ehea_refill_rq3(pr, processed_rq3); ehea_refill_rq3(pr, processed_rq3);
cqe = ehea_poll_rq1(qp, &wqe_index); return processed;
return cqe;
} }
static struct ehea_cqe *ehea_proc_cqes(struct ehea_port_res *pr, int my_quota) static struct ehea_cqe *ehea_proc_cqes(struct ehea_port_res *pr, int my_quota)
...@@ -554,22 +550,27 @@ static struct ehea_cqe *ehea_proc_cqes(struct ehea_port_res *pr, int my_quota) ...@@ -554,22 +550,27 @@ static struct ehea_cqe *ehea_proc_cqes(struct ehea_port_res *pr, int my_quota)
} }
#define EHEA_NAPI_POLL_NUM_BEFORE_IRQ 16 #define EHEA_NAPI_POLL_NUM_BEFORE_IRQ 16
#define EHEA_POLL_MAX_CQES 65535
static int ehea_poll(struct net_device *dev, int *budget) static int ehea_poll(struct napi_struct *napi, int budget)
{ {
struct ehea_port_res *pr = dev->priv; struct ehea_port_res *pr = container_of(napi, struct ehea_port_res, napi);
struct net_device *dev = pr->port->netdev;
struct ehea_cqe *cqe; struct ehea_cqe *cqe;
struct ehea_cqe *cqe_skb = NULL; struct ehea_cqe *cqe_skb = NULL;
int force_irq, wqe_index; int force_irq, wqe_index;
int rx = 0;
cqe = ehea_poll_rq1(pr->qp, &wqe_index);
cqe_skb = ehea_poll_cq(pr->send_cq);
force_irq = (pr->poll_counter > EHEA_NAPI_POLL_NUM_BEFORE_IRQ); force_irq = (pr->poll_counter > EHEA_NAPI_POLL_NUM_BEFORE_IRQ);
cqe_skb = ehea_proc_cqes(pr, EHEA_POLL_MAX_CQES);
if (!force_irq)
rx += ehea_proc_rwqes(dev, pr, budget - rx);
if ((!cqe && !cqe_skb) || force_irq) { while ((rx != budget) || force_irq) {
pr->poll_counter = 0; pr->poll_counter = 0;
netif_rx_complete(dev); force_irq = 0;
netif_rx_complete(dev, napi);
ehea_reset_cq_ep(pr->recv_cq); ehea_reset_cq_ep(pr->recv_cq);
ehea_reset_cq_ep(pr->send_cq); ehea_reset_cq_ep(pr->send_cq);
ehea_reset_cq_n1(pr->recv_cq); ehea_reset_cq_n1(pr->recv_cq);
...@@ -578,43 +579,35 @@ static int ehea_poll(struct net_device *dev, int *budget) ...@@ -578,43 +579,35 @@ static int ehea_poll(struct net_device *dev, int *budget)
cqe_skb = ehea_poll_cq(pr->send_cq); cqe_skb = ehea_poll_cq(pr->send_cq);
if (!cqe && !cqe_skb) if (!cqe && !cqe_skb)
return 0; return rx;
if (!netif_rx_reschedule(dev, dev->quota)) if (!netif_rx_reschedule(dev, napi))
return 0; return rx;
}
cqe = ehea_proc_rwqes(dev, pr, budget);
cqe_skb = ehea_proc_cqes(pr, 300);
if (cqe || cqe_skb) cqe_skb = ehea_proc_cqes(pr, EHEA_POLL_MAX_CQES);
pr->poll_counter++; rx += ehea_proc_rwqes(dev, pr, budget - rx);
}
return 1; pr->poll_counter++;
return rx;
} }
#ifdef CONFIG_NET_POLL_CONTROLLER #ifdef CONFIG_NET_POLL_CONTROLLER
static void ehea_netpoll(struct net_device *dev) static void ehea_netpoll(struct net_device *dev)
{ {
struct ehea_port *port = netdev_priv(dev); struct ehea_port *port = netdev_priv(dev);
int i;
netif_rx_schedule(port->port_res[0].d_netdev); for (i = 0; i < port->num_def_qps; i++)
netif_rx_schedule(dev, &port->port_res[i].napi);
} }
#endif #endif
static int ehea_poll_firstqueue(struct net_device *dev, int *budget)
{
struct ehea_port *port = netdev_priv(dev);
struct net_device *d_dev = port->port_res[0].d_netdev;
return ehea_poll(d_dev, budget);
}
static irqreturn_t ehea_recv_irq_handler(int irq, void *param) static irqreturn_t ehea_recv_irq_handler(int irq, void *param)
{ {
struct ehea_port_res *pr = param; struct ehea_port_res *pr = param;
netif_rx_schedule(pr->d_netdev); netif_rx_schedule(pr->port->netdev, &pr->napi);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
...@@ -1236,14 +1229,7 @@ static int ehea_init_port_res(struct ehea_port *port, struct ehea_port_res *pr, ...@@ -1236,14 +1229,7 @@ static int ehea_init_port_res(struct ehea_port *port, struct ehea_port_res *pr,
kfree(init_attr); kfree(init_attr);
pr->d_netdev = alloc_netdev(0, "", ether_setup); netif_napi_add(pr->port->netdev, &pr->napi, ehea_poll, 64);
if (!pr->d_netdev)
goto out_free;
pr->d_netdev->priv = pr;
pr->d_netdev->weight = 64;
pr->d_netdev->poll = ehea_poll;
set_bit(__LINK_STATE_START, &pr->d_netdev->state);
strcpy(pr->d_netdev->name, port->netdev->name);
ret = 0; ret = 0;
goto out; goto out;
...@@ -1266,8 +1252,6 @@ static int ehea_clean_portres(struct ehea_port *port, struct ehea_port_res *pr) ...@@ -1266,8 +1252,6 @@ static int ehea_clean_portres(struct ehea_port *port, struct ehea_port_res *pr)
{ {
int ret, i; int ret, i;
free_netdev(pr->d_netdev);
ret = ehea_destroy_qp(pr->qp); ret = ehea_destroy_qp(pr->qp);
if (!ret) { if (!ret) {
...@@ -2248,6 +2232,22 @@ static int ehea_up(struct net_device *dev) ...@@ -2248,6 +2232,22 @@ static int ehea_up(struct net_device *dev)
return ret; return ret;
} }
static void port_napi_disable(struct ehea_port *port)
{
int i;
for (i = 0; i < port->num_def_qps; i++)
napi_disable(&port->port_res[i].napi);
}
static void port_napi_enable(struct ehea_port *port)
{
int i;
for (i = 0; i < port->num_def_qps; i++)
napi_enable(&port->port_res[i].napi);
}
static int ehea_open(struct net_device *dev) static int ehea_open(struct net_device *dev)
{ {
int ret; int ret;
...@@ -2259,8 +2259,10 @@ static int ehea_open(struct net_device *dev) ...@@ -2259,8 +2259,10 @@ static int ehea_open(struct net_device *dev)
ehea_info("enabling port %s", dev->name); ehea_info("enabling port %s", dev->name);
ret = ehea_up(dev); ret = ehea_up(dev);
if (!ret) if (!ret) {
port_napi_enable(port);
netif_start_queue(dev); netif_start_queue(dev);
}
up(&port->port_lock); up(&port->port_lock);
...@@ -2269,7 +2271,7 @@ static int ehea_open(struct net_device *dev) ...@@ -2269,7 +2271,7 @@ static int ehea_open(struct net_device *dev)
static int ehea_down(struct net_device *dev) static int ehea_down(struct net_device *dev)
{ {
int ret, i; int ret;
struct ehea_port *port = netdev_priv(dev); struct ehea_port *port = netdev_priv(dev);
if (port->state == EHEA_PORT_DOWN) if (port->state == EHEA_PORT_DOWN)
...@@ -2278,10 +2280,7 @@ static int ehea_down(struct net_device *dev) ...@@ -2278,10 +2280,7 @@ static int ehea_down(struct net_device *dev)
ehea_drop_multicast_list(dev); ehea_drop_multicast_list(dev);
ehea_free_interrupts(dev); ehea_free_interrupts(dev);
for (i = 0; i < port->num_def_qps; i++) port_napi_disable(port);
while (test_bit(__LINK_STATE_RX_SCHED,
&port->port_res[i].d_netdev->state))
msleep(1);
port->state = EHEA_PORT_DOWN; port->state = EHEA_PORT_DOWN;
...@@ -2319,7 +2318,8 @@ static void ehea_reset_port(struct work_struct *work) ...@@ -2319,7 +2318,8 @@ static void ehea_reset_port(struct work_struct *work)
port->resets++; port->resets++;
down(&port->port_lock); down(&port->port_lock);
netif_stop_queue(dev); netif_stop_queue(dev);
netif_poll_disable(dev);
port_napi_disable(port);
ehea_down(dev); ehea_down(dev);
...@@ -2330,7 +2330,8 @@ static void ehea_reset_port(struct work_struct *work) ...@@ -2330,7 +2330,8 @@ static void ehea_reset_port(struct work_struct *work)
if (netif_msg_timer(port)) if (netif_msg_timer(port))
ehea_info("Device %s resetted successfully", dev->name); ehea_info("Device %s resetted successfully", dev->name);
netif_poll_enable(dev); port_napi_enable(port);
netif_wake_queue(dev); netif_wake_queue(dev);
out: out:
up(&port->port_lock); up(&port->port_lock);
...@@ -2358,7 +2359,9 @@ static void ehea_rereg_mrs(struct work_struct *work) ...@@ -2358,7 +2359,9 @@ static void ehea_rereg_mrs(struct work_struct *work)
dev->name); dev->name);
down(&port->port_lock); down(&port->port_lock);
netif_stop_queue(dev); netif_stop_queue(dev);
netif_poll_disable(dev);
port_napi_disable(port);
ehea_down(dev); ehea_down(dev);
up(&port->port_lock); up(&port->port_lock);
} }
...@@ -2406,7 +2409,7 @@ static void ehea_rereg_mrs(struct work_struct *work) ...@@ -2406,7 +2409,7 @@ static void ehea_rereg_mrs(struct work_struct *work)
ret = ehea_up(dev); ret = ehea_up(dev);
if (!ret) { if (!ret) {
netif_poll_enable(dev); port_napi_enable(port);
netif_wake_queue(dev); netif_wake_queue(dev);
} }
...@@ -2644,11 +2647,9 @@ struct ehea_port *ehea_setup_single_port(struct ehea_adapter *adapter, ...@@ -2644,11 +2647,9 @@ struct ehea_port *ehea_setup_single_port(struct ehea_adapter *adapter,
memcpy(dev->dev_addr, &port->mac_addr, ETH_ALEN); memcpy(dev->dev_addr, &port->mac_addr, ETH_ALEN);
dev->open = ehea_open; dev->open = ehea_open;
dev->poll = ehea_poll_firstqueue;
#ifdef CONFIG_NET_POLL_CONTROLLER #ifdef CONFIG_NET_POLL_CONTROLLER
dev->poll_controller = ehea_netpoll; dev->poll_controller = ehea_netpoll;
#endif #endif
dev->weight = 64;
dev->stop = ehea_stop; dev->stop = ehea_stop;
dev->hard_start_xmit = ehea_start_xmit; dev->hard_start_xmit = ehea_start_xmit;
dev->get_stats = ehea_get_stats; dev->get_stats = ehea_get_stats;
......
...@@ -262,6 +262,7 @@ struct epic_private { ...@@ -262,6 +262,7 @@ struct epic_private {
/* Ring pointers. */ /* Ring pointers. */
spinlock_t lock; /* Group with Tx control cache line. */ spinlock_t lock; /* Group with Tx control cache line. */
spinlock_t napi_lock; spinlock_t napi_lock;
struct napi_struct napi;
unsigned int reschedule_in_poll; unsigned int reschedule_in_poll;
unsigned int cur_tx, dirty_tx; unsigned int cur_tx, dirty_tx;
...@@ -294,7 +295,7 @@ static void epic_tx_timeout(struct net_device *dev); ...@@ -294,7 +295,7 @@ static void epic_tx_timeout(struct net_device *dev);
static void epic_init_ring(struct net_device *dev); static void epic_init_ring(struct net_device *dev);
static int epic_start_xmit(struct sk_buff *skb, struct net_device *dev); static int epic_start_xmit(struct sk_buff *skb, struct net_device *dev);
static int epic_rx(struct net_device *dev, int budget); static int epic_rx(struct net_device *dev, int budget);
static int epic_poll(struct net_device *dev, int *budget); static int epic_poll(struct napi_struct *napi, int budget);
static irqreturn_t epic_interrupt(int irq, void *dev_instance); static irqreturn_t epic_interrupt(int irq, void *dev_instance);
static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
static const struct ethtool_ops netdev_ethtool_ops; static const struct ethtool_ops netdev_ethtool_ops;
...@@ -487,8 +488,7 @@ static int __devinit epic_init_one (struct pci_dev *pdev, ...@@ -487,8 +488,7 @@ static int __devinit epic_init_one (struct pci_dev *pdev,
dev->ethtool_ops = &netdev_ethtool_ops; dev->ethtool_ops = &netdev_ethtool_ops;
dev->watchdog_timeo = TX_TIMEOUT; dev->watchdog_timeo = TX_TIMEOUT;
dev->tx_timeout = &epic_tx_timeout; dev->tx_timeout = &epic_tx_timeout;
dev->poll = epic_poll; netif_napi_add(dev, &ep->napi, epic_poll, 64);
dev->weight = 64;
ret = register_netdev(dev); ret = register_netdev(dev);
if (ret < 0) if (ret < 0)
...@@ -660,8 +660,11 @@ static int epic_open(struct net_device *dev) ...@@ -660,8 +660,11 @@ static int epic_open(struct net_device *dev)
/* Soft reset the chip. */ /* Soft reset the chip. */
outl(0x4001, ioaddr + GENCTL); outl(0x4001, ioaddr + GENCTL);
if ((retval = request_irq(dev->irq, &epic_interrupt, IRQF_SHARED, dev->name, dev))) napi_enable(&ep->napi);
if ((retval = request_irq(dev->irq, &epic_interrupt, IRQF_SHARED, dev->name, dev))) {
napi_disable(&ep->napi);
return retval; return retval;
}
epic_init_ring(dev); epic_init_ring(dev);
...@@ -1103,9 +1106,9 @@ static irqreturn_t epic_interrupt(int irq, void *dev_instance) ...@@ -1103,9 +1106,9 @@ static irqreturn_t epic_interrupt(int irq, void *dev_instance)
if ((status & EpicNapiEvent) && !ep->reschedule_in_poll) { if ((status & EpicNapiEvent) && !ep->reschedule_in_poll) {
spin_lock(&ep->napi_lock); spin_lock(&ep->napi_lock);
if (netif_rx_schedule_prep(dev)) { if (netif_rx_schedule_prep(dev, &ep->napi)) {
epic_napi_irq_off(dev, ep); epic_napi_irq_off(dev, ep);
__netif_rx_schedule(dev); __netif_rx_schedule(dev, &ep->napi);
} else } else
ep->reschedule_in_poll++; ep->reschedule_in_poll++;
spin_unlock(&ep->napi_lock); spin_unlock(&ep->napi_lock);
...@@ -1257,26 +1260,22 @@ static void epic_rx_err(struct net_device *dev, struct epic_private *ep) ...@@ -1257,26 +1260,22 @@ static void epic_rx_err(struct net_device *dev, struct epic_private *ep)
outw(RxQueued, ioaddr + COMMAND); outw(RxQueued, ioaddr + COMMAND);
} }
static int epic_poll(struct net_device *dev, int *budget) static int epic_poll(struct napi_struct *napi, int budget)
{ {
struct epic_private *ep = dev->priv; struct epic_private *ep = container_of(napi, struct epic_private, napi);
int work_done = 0, orig_budget; struct net_device *dev = ep->mii.dev;
int work_done = 0;
long ioaddr = dev->base_addr; long ioaddr = dev->base_addr;
orig_budget = (*budget > dev->quota) ? dev->quota : *budget;
rx_action: rx_action:
epic_tx(dev, ep); epic_tx(dev, ep);
work_done += epic_rx(dev, *budget); work_done += epic_rx(dev, budget);
epic_rx_err(dev, ep); epic_rx_err(dev, ep);
*budget -= work_done; if (netif_running(dev) && (work_done < budget)) {
dev->quota -= work_done;
if (netif_running(dev) && (work_done < orig_budget)) {
unsigned long flags; unsigned long flags;
int more; int more;
...@@ -1286,7 +1285,7 @@ static int epic_poll(struct net_device *dev, int *budget) ...@@ -1286,7 +1285,7 @@ static int epic_poll(struct net_device *dev, int *budget)
more = ep->reschedule_in_poll; more = ep->reschedule_in_poll;
if (!more) { if (!more) {
__netif_rx_complete(dev); __netif_rx_complete(dev, napi);
outl(EpicNapiEvent, ioaddr + INTSTAT); outl(EpicNapiEvent, ioaddr + INTSTAT);
epic_napi_irq_on(dev, ep); epic_napi_irq_on(dev, ep);
} else } else
...@@ -1298,7 +1297,7 @@ static int epic_poll(struct net_device *dev, int *budget) ...@@ -1298,7 +1297,7 @@ static int epic_poll(struct net_device *dev, int *budget)
goto rx_action; goto rx_action;
} }
return (work_done >= orig_budget); return work_done;
} }
static int epic_close(struct net_device *dev) static int epic_close(struct net_device *dev)
...@@ -1309,6 +1308,7 @@ static int epic_close(struct net_device *dev) ...@@ -1309,6 +1308,7 @@ static int epic_close(struct net_device *dev)
int i; int i;
netif_stop_queue(dev); netif_stop_queue(dev);
napi_disable(&ep->napi);
if (debug > 1) if (debug > 1)
printk(KERN_DEBUG "%s: Shutting down ethercard, status was %2.2x.\n", printk(KERN_DEBUG "%s: Shutting down ethercard, status was %2.2x.\n",
......
...@@ -105,6 +105,8 @@ struct fec; ...@@ -105,6 +105,8 @@ struct fec;
struct fec_enet_private { struct fec_enet_private {
spinlock_t lock; /* during all ops except TX pckt processing */ spinlock_t lock; /* during all ops except TX pckt processing */
spinlock_t tx_lock; /* during fec_start_xmit and fec_tx */ spinlock_t tx_lock; /* during fec_start_xmit and fec_tx */
struct net_device *dev;
struct napi_struct napi;
int fecno; int fecno;
struct fec *fecp; struct fec *fecp;
const struct fec_platform_info *fpi; const struct fec_platform_info *fpi;
......
...@@ -465,9 +465,9 @@ void fec_stop(struct net_device *dev) ...@@ -465,9 +465,9 @@ void fec_stop(struct net_device *dev)
} }
/* common receive function */ /* common receive function */
static int fec_enet_rx_common(struct net_device *dev, int *budget) static int fec_enet_rx_common(struct fec_enet_private *ep,
struct net_device *dev, int budget)
{ {
struct fec_enet_private *fep = netdev_priv(dev);
fec_t *fecp = fep->fecp; fec_t *fecp = fep->fecp;
const struct fec_platform_info *fpi = fep->fpi; const struct fec_platform_info *fpi = fep->fpi;
cbd_t *bdp; cbd_t *bdp;
...@@ -475,11 +475,8 @@ static int fec_enet_rx_common(struct net_device *dev, int *budget) ...@@ -475,11 +475,8 @@ static int fec_enet_rx_common(struct net_device *dev, int *budget)
int received = 0; int received = 0;
__u16 pkt_len, sc; __u16 pkt_len, sc;
int curidx; int curidx;
int rx_work_limit;
if (fpi->use_napi) { if (fpi->use_napi) {
rx_work_limit = min(dev->quota, *budget);
if (!netif_running(dev)) if (!netif_running(dev))
return 0; return 0;
} }
...@@ -530,11 +527,6 @@ static int fec_enet_rx_common(struct net_device *dev, int *budget) ...@@ -530,11 +527,6 @@ static int fec_enet_rx_common(struct net_device *dev, int *budget)
BUG_ON(skbn == NULL); BUG_ON(skbn == NULL);
} else { } else {
/* napi, got packet but no quota */
if (fpi->use_napi && --rx_work_limit < 0)
break;
skb = fep->rx_skbuff[curidx]; skb = fep->rx_skbuff[curidx];
BUG_ON(skb == NULL); BUG_ON(skb == NULL);
...@@ -599,25 +591,24 @@ static int fec_enet_rx_common(struct net_device *dev, int *budget) ...@@ -599,25 +591,24 @@ static int fec_enet_rx_common(struct net_device *dev, int *budget)
* able to keep up at the expense of system resources. * able to keep up at the expense of system resources.
*/ */
FW(fecp, r_des_active, 0x01000000); FW(fecp, r_des_active, 0x01000000);
if (received >= budget)
break;
} }
fep->cur_rx = bdp; fep->cur_rx = bdp;
if (fpi->use_napi) { if (fpi->use_napi) {
dev->quota -= received; if (received < budget) {
*budget -= received; netif_rx_complete(dev, &fep->napi);
if (rx_work_limit < 0)
return 1; /* not done */
/* done */ /* enable RX interrupt bits */
netif_rx_complete(dev); FS(fecp, imask, FEC_ENET_RXF | FEC_ENET_RXB);
}
/* enable RX interrupt bits */
FS(fecp, imask, FEC_ENET_RXF | FEC_ENET_RXB);
} }
return 0; return received;
} }
static void fec_enet_tx(struct net_device *dev) static void fec_enet_tx(struct net_device *dev)
...@@ -743,12 +734,12 @@ fec_enet_interrupt(int irq, void *dev_id) ...@@ -743,12 +734,12 @@ fec_enet_interrupt(int irq, void *dev_id)
if ((int_events & FEC_ENET_RXF) != 0) { if ((int_events & FEC_ENET_RXF) != 0) {
if (!fpi->use_napi) if (!fpi->use_napi)
fec_enet_rx_common(dev, NULL); fec_enet_rx_common(fep, dev, ~0);
else { else {
if (netif_rx_schedule_prep(dev)) { if (netif_rx_schedule_prep(dev, &fep->napi)) {
/* disable rx interrupts */ /* disable rx interrupts */
FC(fecp, imask, FEC_ENET_RXF | FEC_ENET_RXB); FC(fecp, imask, FEC_ENET_RXF | FEC_ENET_RXB);
__netif_rx_schedule(dev); __netif_rx_schedule(dev, &fep->napi);
} else { } else {
printk(KERN_ERR DRV_MODULE_NAME printk(KERN_ERR DRV_MODULE_NAME
": %s driver bug! interrupt while in poll!\n", ": %s driver bug! interrupt while in poll!\n",
...@@ -893,10 +884,13 @@ static int fec_enet_open(struct net_device *dev) ...@@ -893,10 +884,13 @@ static int fec_enet_open(struct net_device *dev)
const struct fec_platform_info *fpi = fep->fpi; const struct fec_platform_info *fpi = fep->fpi;
unsigned long flags; unsigned long flags;
napi_enable(&fep->napi);
/* Install our interrupt handler. */ /* Install our interrupt handler. */
if (request_irq(fpi->fec_irq, fec_enet_interrupt, 0, "fec", dev) != 0) { if (request_irq(fpi->fec_irq, fec_enet_interrupt, 0, "fec", dev) != 0) {
printk(KERN_ERR DRV_MODULE_NAME printk(KERN_ERR DRV_MODULE_NAME
": %s Could not allocate FEC IRQ!", dev->name); ": %s Could not allocate FEC IRQ!", dev->name);
napi_disable(&fep->napi);
return -EINVAL; return -EINVAL;
} }
...@@ -907,6 +901,7 @@ static int fec_enet_open(struct net_device *dev) ...@@ -907,6 +901,7 @@ static int fec_enet_open(struct net_device *dev)
printk(KERN_ERR DRV_MODULE_NAME printk(KERN_ERR DRV_MODULE_NAME
": %s Could not allocate PHY IRQ!", dev->name); ": %s Could not allocate PHY IRQ!", dev->name);
free_irq(fpi->fec_irq, dev); free_irq(fpi->fec_irq, dev);
napi_disable(&fep->napi);
return -EINVAL; return -EINVAL;
} }
...@@ -932,6 +927,7 @@ static int fec_enet_close(struct net_device *dev) ...@@ -932,6 +927,7 @@ static int fec_enet_close(struct net_device *dev)
unsigned long flags; unsigned long flags;
netif_stop_queue(dev); netif_stop_queue(dev);
napi_disable(&fep->napi);
netif_carrier_off(dev); netif_carrier_off(dev);
if (fpi->use_mdio) if (fpi->use_mdio)
...@@ -955,9 +951,12 @@ static struct net_device_stats *fec_enet_get_stats(struct net_device *dev) ...@@ -955,9 +951,12 @@ static struct net_device_stats *fec_enet_get_stats(struct net_device *dev)
return &fep->stats; return &fep->stats;
} }
static int fec_enet_poll(struct net_device *dev, int *budget) static int fec_enet_poll(struct napi_struct *napi, int budget)
{ {
return fec_enet_rx_common(dev, budget); struct fec_enet_private *fep = container_of(napi, struct fec_enet_private, napi);
struct net_device *dev = fep->dev;
return fec_enet_rx_common(fep, dev, budget);
} }
/*************************************************************************/ /*************************************************************************/
...@@ -1107,6 +1106,7 @@ int fec_8xx_init_one(const struct fec_platform_info *fpi, ...@@ -1107,6 +1106,7 @@ int fec_8xx_init_one(const struct fec_platform_info *fpi,
SET_MODULE_OWNER(dev); SET_MODULE_OWNER(dev);
fep = netdev_priv(dev); fep = netdev_priv(dev);
fep->dev = dev;
/* partial reset of FEC */ /* partial reset of FEC */
fec_whack_reset(fecp); fec_whack_reset(fecp);
...@@ -1172,10 +1172,9 @@ int fec_8xx_init_one(const struct fec_platform_info *fpi, ...@@ -1172,10 +1172,9 @@ int fec_8xx_init_one(const struct fec_platform_info *fpi,
dev->get_stats = fec_enet_get_stats; dev->get_stats = fec_enet_get_stats;
dev->set_multicast_list = fec_set_multicast_list; dev->set_multicast_list = fec_set_multicast_list;
dev->set_mac_address = fec_set_mac_address; dev->set_mac_address = fec_set_mac_address;
if (fpi->use_napi) { netif_napi_add(dev, &fec->napi,
dev->poll = fec_enet_poll; fec_enet_poll, fpi->napi_weight);
dev->weight = fpi->napi_weight;
}
dev->ethtool_ops = &fec_ethtool_ops; dev->ethtool_ops = &fec_ethtool_ops;
dev->do_ioctl = fec_ioctl; dev->do_ioctl = fec_ioctl;
......
...@@ -159,6 +159,8 @@ ...@@ -159,6 +159,8 @@
#define dprintk(x...) do { } while (0) #define dprintk(x...) do { } while (0)
#endif #endif
#define TX_WORK_PER_LOOP 64
#define RX_WORK_PER_LOOP 64
/* /*
* Hardware access: * Hardware access:
...@@ -745,6 +747,9 @@ struct nv_skb_map { ...@@ -745,6 +747,9 @@ struct nv_skb_map {
struct fe_priv { struct fe_priv {
spinlock_t lock; spinlock_t lock;
struct net_device *dev;
struct napi_struct napi;
/* General data: /* General data:
* Locking: spin_lock(&np->lock); */ * Locking: spin_lock(&np->lock); */
struct net_device_stats stats; struct net_device_stats stats;
...@@ -1586,9 +1591,10 @@ static int nv_alloc_rx_optimized(struct net_device *dev) ...@@ -1586,9 +1591,10 @@ static int nv_alloc_rx_optimized(struct net_device *dev)
static void nv_do_rx_refill(unsigned long data) static void nv_do_rx_refill(unsigned long data)
{ {
struct net_device *dev = (struct net_device *) data; struct net_device *dev = (struct net_device *) data;
struct fe_priv *np = netdev_priv(dev);
/* Just reschedule NAPI rx processing */ /* Just reschedule NAPI rx processing */
netif_rx_schedule(dev); netif_rx_schedule(dev, &np->napi);
} }
#else #else
static void nv_do_rx_refill(unsigned long data) static void nv_do_rx_refill(unsigned long data)
...@@ -2997,7 +3003,7 @@ static irqreturn_t nv_nic_irq(int foo, void *data) ...@@ -2997,7 +3003,7 @@ static irqreturn_t nv_nic_irq(int foo, void *data)
#ifdef CONFIG_FORCEDETH_NAPI #ifdef CONFIG_FORCEDETH_NAPI
if (events & NVREG_IRQ_RX_ALL) { if (events & NVREG_IRQ_RX_ALL) {
netif_rx_schedule(dev); netif_rx_schedule(dev, &np->napi);
/* Disable furthur receive irq's */ /* Disable furthur receive irq's */
spin_lock(&np->lock); spin_lock(&np->lock);
...@@ -3010,7 +3016,7 @@ static irqreturn_t nv_nic_irq(int foo, void *data) ...@@ -3010,7 +3016,7 @@ static irqreturn_t nv_nic_irq(int foo, void *data)
spin_unlock(&np->lock); spin_unlock(&np->lock);
} }
#else #else
if (nv_rx_process(dev, dev->weight)) { if (nv_rx_process(dev, RX_WORK_PER_LOOP)) {
if (unlikely(nv_alloc_rx(dev))) { if (unlikely(nv_alloc_rx(dev))) {
spin_lock(&np->lock); spin_lock(&np->lock);
if (!np->in_shutdown) if (!np->in_shutdown)
...@@ -3079,8 +3085,6 @@ static irqreturn_t nv_nic_irq(int foo, void *data) ...@@ -3079,8 +3085,6 @@ static irqreturn_t nv_nic_irq(int foo, void *data)
return IRQ_RETVAL(i); return IRQ_RETVAL(i);
} }
#define TX_WORK_PER_LOOP 64
#define RX_WORK_PER_LOOP 64
/** /**
* All _optimized functions are used to help increase performance * All _optimized functions are used to help increase performance
* (reduce CPU and increase throughput). They use descripter version 3, * (reduce CPU and increase throughput). They use descripter version 3,
...@@ -3114,7 +3118,7 @@ static irqreturn_t nv_nic_irq_optimized(int foo, void *data) ...@@ -3114,7 +3118,7 @@ static irqreturn_t nv_nic_irq_optimized(int foo, void *data)
#ifdef CONFIG_FORCEDETH_NAPI #ifdef CONFIG_FORCEDETH_NAPI
if (events & NVREG_IRQ_RX_ALL) { if (events & NVREG_IRQ_RX_ALL) {
netif_rx_schedule(dev); netif_rx_schedule(dev, &np->napi);
/* Disable furthur receive irq's */ /* Disable furthur receive irq's */
spin_lock(&np->lock); spin_lock(&np->lock);
...@@ -3127,7 +3131,7 @@ static irqreturn_t nv_nic_irq_optimized(int foo, void *data) ...@@ -3127,7 +3131,7 @@ static irqreturn_t nv_nic_irq_optimized(int foo, void *data)
spin_unlock(&np->lock); spin_unlock(&np->lock);
} }
#else #else
if (nv_rx_process_optimized(dev, dev->weight)) { if (nv_rx_process_optimized(dev, RX_WORK_PER_LOOP)) {
if (unlikely(nv_alloc_rx_optimized(dev))) { if (unlikely(nv_alloc_rx_optimized(dev))) {
spin_lock(&np->lock); spin_lock(&np->lock);
if (!np->in_shutdown) if (!np->in_shutdown)
...@@ -3245,19 +3249,19 @@ static irqreturn_t nv_nic_irq_tx(int foo, void *data) ...@@ -3245,19 +3249,19 @@ static irqreturn_t nv_nic_irq_tx(int foo, void *data)
} }
#ifdef CONFIG_FORCEDETH_NAPI #ifdef CONFIG_FORCEDETH_NAPI
static int nv_napi_poll(struct net_device *dev, int *budget) static int nv_napi_poll(struct napi_struct *napi, int budget)
{ {
int pkts, limit = min(*budget, dev->quota); struct fe_priv *np = container_of(napi, struct fe_priv, napi);
struct fe_priv *np = netdev_priv(dev); struct net_device *dev = np->dev;
u8 __iomem *base = get_hwbase(dev); u8 __iomem *base = get_hwbase(dev);
unsigned long flags; unsigned long flags;
int retcode; int pkts, retcode;
if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) { if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) {
pkts = nv_rx_process(dev, limit); pkts = nv_rx_process(dev, budget);
retcode = nv_alloc_rx(dev); retcode = nv_alloc_rx(dev);
} else { } else {
pkts = nv_rx_process_optimized(dev, limit); pkts = nv_rx_process_optimized(dev, budget);
retcode = nv_alloc_rx_optimized(dev); retcode = nv_alloc_rx_optimized(dev);
} }
...@@ -3268,13 +3272,12 @@ static int nv_napi_poll(struct net_device *dev, int *budget) ...@@ -3268,13 +3272,12 @@ static int nv_napi_poll(struct net_device *dev, int *budget)
spin_unlock_irqrestore(&np->lock, flags); spin_unlock_irqrestore(&np->lock, flags);
} }
if (pkts < limit) { if (pkts < budget) {
/* all done, no more packets present */
netif_rx_complete(dev);
/* re-enable receive interrupts */ /* re-enable receive interrupts */
spin_lock_irqsave(&np->lock, flags); spin_lock_irqsave(&np->lock, flags);
__netif_rx_complete(dev, napi);
np->irqmask |= NVREG_IRQ_RX_ALL; np->irqmask |= NVREG_IRQ_RX_ALL;
if (np->msi_flags & NV_MSI_X_ENABLED) if (np->msi_flags & NV_MSI_X_ENABLED)
writel(NVREG_IRQ_RX_ALL, base + NvRegIrqMask); writel(NVREG_IRQ_RX_ALL, base + NvRegIrqMask);
...@@ -3282,13 +3285,8 @@ static int nv_napi_poll(struct net_device *dev, int *budget) ...@@ -3282,13 +3285,8 @@ static int nv_napi_poll(struct net_device *dev, int *budget)
writel(np->irqmask, base + NvRegIrqMask); writel(np->irqmask, base + NvRegIrqMask);
spin_unlock_irqrestore(&np->lock, flags); spin_unlock_irqrestore(&np->lock, flags);
return 0;
} else {
/* used up our quantum, so reschedule */
dev->quota -= pkts;
*budget -= pkts;
return 1;
} }
return pkts;
} }
#endif #endif
...@@ -3296,6 +3294,7 @@ static int nv_napi_poll(struct net_device *dev, int *budget) ...@@ -3296,6 +3294,7 @@ static int nv_napi_poll(struct net_device *dev, int *budget)
static irqreturn_t nv_nic_irq_rx(int foo, void *data) static irqreturn_t nv_nic_irq_rx(int foo, void *data)
{ {
struct net_device *dev = (struct net_device *) data; struct net_device *dev = (struct net_device *) data;
struct fe_priv *np = netdev_priv(dev);
u8 __iomem *base = get_hwbase(dev); u8 __iomem *base = get_hwbase(dev);
u32 events; u32 events;
...@@ -3303,7 +3302,7 @@ static irqreturn_t nv_nic_irq_rx(int foo, void *data) ...@@ -3303,7 +3302,7 @@ static irqreturn_t nv_nic_irq_rx(int foo, void *data)
writel(NVREG_IRQ_RX_ALL, base + NvRegMSIXIrqStatus); writel(NVREG_IRQ_RX_ALL, base + NvRegMSIXIrqStatus);
if (events) { if (events) {
netif_rx_schedule(dev); netif_rx_schedule(dev, &np->napi);
/* disable receive interrupts on the nic */ /* disable receive interrupts on the nic */
writel(NVREG_IRQ_RX_ALL, base + NvRegIrqMask); writel(NVREG_IRQ_RX_ALL, base + NvRegIrqMask);
pci_push(base); pci_push(base);
...@@ -3329,7 +3328,7 @@ static irqreturn_t nv_nic_irq_rx(int foo, void *data) ...@@ -3329,7 +3328,7 @@ static irqreturn_t nv_nic_irq_rx(int foo, void *data)
if (!(events & np->irqmask)) if (!(events & np->irqmask))
break; break;
if (nv_rx_process_optimized(dev, dev->weight)) { if (nv_rx_process_optimized(dev, RX_WORK_PER_LOOP)) {
if (unlikely(nv_alloc_rx_optimized(dev))) { if (unlikely(nv_alloc_rx_optimized(dev))) {
spin_lock_irqsave(&np->lock, flags); spin_lock_irqsave(&np->lock, flags);
if (!np->in_shutdown) if (!np->in_shutdown)
...@@ -4620,7 +4619,9 @@ static void nv_self_test(struct net_device *dev, struct ethtool_test *test, u64 ...@@ -4620,7 +4619,9 @@ static void nv_self_test(struct net_device *dev, struct ethtool_test *test, u64
if (test->flags & ETH_TEST_FL_OFFLINE) { if (test->flags & ETH_TEST_FL_OFFLINE) {
if (netif_running(dev)) { if (netif_running(dev)) {
netif_stop_queue(dev); netif_stop_queue(dev);
netif_poll_disable(dev); #ifdef CONFIG_FORCEDETH_NAPI
napi_disable(&np->napi);
#endif
netif_tx_lock_bh(dev); netif_tx_lock_bh(dev);
spin_lock_irq(&np->lock); spin_lock_irq(&np->lock);
nv_disable_hw_interrupts(dev, np->irqmask); nv_disable_hw_interrupts(dev, np->irqmask);
...@@ -4679,7 +4680,9 @@ static void nv_self_test(struct net_device *dev, struct ethtool_test *test, u64 ...@@ -4679,7 +4680,9 @@ static void nv_self_test(struct net_device *dev, struct ethtool_test *test, u64
nv_start_rx(dev); nv_start_rx(dev);
nv_start_tx(dev); nv_start_tx(dev);
netif_start_queue(dev); netif_start_queue(dev);
netif_poll_enable(dev); #ifdef CONFIG_FORCEDETH_NAPI
napi_enable(&np->napi);
#endif
nv_enable_hw_interrupts(dev, np->irqmask); nv_enable_hw_interrupts(dev, np->irqmask);
} }
} }
...@@ -4911,7 +4914,9 @@ static int nv_open(struct net_device *dev) ...@@ -4911,7 +4914,9 @@ static int nv_open(struct net_device *dev)
nv_start_rx(dev); nv_start_rx(dev);
nv_start_tx(dev); nv_start_tx(dev);
netif_start_queue(dev); netif_start_queue(dev);
netif_poll_enable(dev); #ifdef CONFIG_FORCEDETH_NAPI
napi_enable(&np->napi);
#endif
if (ret) { if (ret) {
netif_carrier_on(dev); netif_carrier_on(dev);
...@@ -4942,7 +4947,9 @@ static int nv_close(struct net_device *dev) ...@@ -4942,7 +4947,9 @@ static int nv_close(struct net_device *dev)
spin_lock_irq(&np->lock); spin_lock_irq(&np->lock);
np->in_shutdown = 1; np->in_shutdown = 1;
spin_unlock_irq(&np->lock); spin_unlock_irq(&np->lock);
netif_poll_disable(dev); #ifdef CONFIG_FORCEDETH_NAPI
napi_disable(&np->napi);
#endif
synchronize_irq(dev->irq); synchronize_irq(dev->irq);
del_timer_sync(&np->oom_kick); del_timer_sync(&np->oom_kick);
...@@ -4994,6 +5001,7 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i ...@@ -4994,6 +5001,7 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i
goto out; goto out;
np = netdev_priv(dev); np = netdev_priv(dev);
np->dev = dev;
np->pci_dev = pci_dev; np->pci_dev = pci_dev;
spin_lock_init(&np->lock); spin_lock_init(&np->lock);
SET_MODULE_OWNER(dev); SET_MODULE_OWNER(dev);
...@@ -5155,9 +5163,8 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i ...@@ -5155,9 +5163,8 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i
#ifdef CONFIG_NET_POLL_CONTROLLER #ifdef CONFIG_NET_POLL_CONTROLLER
dev->poll_controller = nv_poll_controller; dev->poll_controller = nv_poll_controller;
#endif #endif
dev->weight = RX_WORK_PER_LOOP;
#ifdef CONFIG_FORCEDETH_NAPI #ifdef CONFIG_FORCEDETH_NAPI
dev->poll = nv_napi_poll; netif_napi_add(dev, &np->napi, nv_napi_poll, RX_WORK_PER_LOOP);
#endif #endif
SET_ETHTOOL_OPS(dev, &ops); SET_ETHTOOL_OPS(dev, &ops);
dev->tx_timeout = nv_tx_timeout; dev->tx_timeout = nv_tx_timeout;
......
...@@ -70,18 +70,16 @@ static void fs_set_multicast_list(struct net_device *dev) ...@@ -70,18 +70,16 @@ static void fs_set_multicast_list(struct net_device *dev)
} }
/* NAPI receive function */ /* NAPI receive function */
static int fs_enet_rx_napi(struct net_device *dev, int *budget) static int fs_enet_rx_napi(struct napi_struct *napi, int budget)
{ {
struct fs_enet_private *fep = netdev_priv(dev); struct fs_enet_private *fep = container_of(napi, struct fs_enet_private, napi);
struct net_device *dev = to_net_dev(fep->dev);
const struct fs_platform_info *fpi = fep->fpi; const struct fs_platform_info *fpi = fep->fpi;
cbd_t *bdp; cbd_t *bdp;
struct sk_buff *skb, *skbn, *skbt; struct sk_buff *skb, *skbn, *skbt;
int received = 0; int received = 0;
u16 pkt_len, sc; u16 pkt_len, sc;
int curidx; int curidx;
int rx_work_limit = 0; /* pacify gcc */
rx_work_limit = min(dev->quota, *budget);
if (!netif_running(dev)) if (!netif_running(dev))
return 0; return 0;
...@@ -96,7 +94,6 @@ static int fs_enet_rx_napi(struct net_device *dev, int *budget) ...@@ -96,7 +94,6 @@ static int fs_enet_rx_napi(struct net_device *dev, int *budget)
(*fep->ops->napi_clear_rx_event)(dev); (*fep->ops->napi_clear_rx_event)(dev);
while (((sc = CBDR_SC(bdp)) & BD_ENET_RX_EMPTY) == 0) { while (((sc = CBDR_SC(bdp)) & BD_ENET_RX_EMPTY) == 0) {
curidx = bdp - fep->rx_bd_base; curidx = bdp - fep->rx_bd_base;
/* /*
...@@ -136,11 +133,6 @@ static int fs_enet_rx_napi(struct net_device *dev, int *budget) ...@@ -136,11 +133,6 @@ static int fs_enet_rx_napi(struct net_device *dev, int *budget)
skbn = skb; skbn = skb;
} else { } else {
/* napi, got packet but no quota */
if (--rx_work_limit < 0)
break;
skb = fep->rx_skbuff[curidx]; skb = fep->rx_skbuff[curidx];
dma_unmap_single(fep->dev, CBDR_BUFADDR(bdp), dma_unmap_single(fep->dev, CBDR_BUFADDR(bdp),
...@@ -199,22 +191,19 @@ static int fs_enet_rx_napi(struct net_device *dev, int *budget) ...@@ -199,22 +191,19 @@ static int fs_enet_rx_napi(struct net_device *dev, int *budget)
bdp = fep->rx_bd_base; bdp = fep->rx_bd_base;
(*fep->ops->rx_bd_done)(dev); (*fep->ops->rx_bd_done)(dev);
if (received >= budget)
break;
} }
fep->cur_rx = bdp; fep->cur_rx = bdp;
dev->quota -= received; if (received >= budget) {
*budget -= received; /* done */
netif_rx_complete(dev, napi);
if (rx_work_limit < 0) (*fep->ops->napi_enable_rx)(dev);
return 1; /* not done */ }
return received;
/* done */
netif_rx_complete(dev);
(*fep->ops->napi_enable_rx)(dev);
return 0;
} }
/* non NAPI receive function */ /* non NAPI receive function */
...@@ -470,7 +459,7 @@ fs_enet_interrupt(int irq, void *dev_id) ...@@ -470,7 +459,7 @@ fs_enet_interrupt(int irq, void *dev_id)
if (!fpi->use_napi) if (!fpi->use_napi)
fs_enet_rx_non_napi(dev); fs_enet_rx_non_napi(dev);
else { else {
napi_ok = netif_rx_schedule_prep(dev); napi_ok = napi_schedule_prep(&fep->napi);
(*fep->ops->napi_disable_rx)(dev); (*fep->ops->napi_disable_rx)(dev);
(*fep->ops->clear_int_events)(dev, fep->ev_napi_rx); (*fep->ops->clear_int_events)(dev, fep->ev_napi_rx);
...@@ -478,7 +467,7 @@ fs_enet_interrupt(int irq, void *dev_id) ...@@ -478,7 +467,7 @@ fs_enet_interrupt(int irq, void *dev_id)
/* NOTE: it is possible for FCCs in NAPI mode */ /* NOTE: it is possible for FCCs in NAPI mode */
/* to submit a spurious interrupt while in poll */ /* to submit a spurious interrupt while in poll */
if (napi_ok) if (napi_ok)
__netif_rx_schedule(dev); __netif_rx_schedule(dev, &fep->napi);
} }
} }
...@@ -799,18 +788,22 @@ static int fs_enet_open(struct net_device *dev) ...@@ -799,18 +788,22 @@ static int fs_enet_open(struct net_device *dev)
int r; int r;
int err; int err;
napi_enable(&fep->napi);
/* Install our interrupt handler. */ /* Install our interrupt handler. */
r = fs_request_irq(dev, fep->interrupt, "fs_enet-mac", fs_enet_interrupt); r = fs_request_irq(dev, fep->interrupt, "fs_enet-mac", fs_enet_interrupt);
if (r != 0) { if (r != 0) {
printk(KERN_ERR DRV_MODULE_NAME printk(KERN_ERR DRV_MODULE_NAME
": %s Could not allocate FS_ENET IRQ!", dev->name); ": %s Could not allocate FS_ENET IRQ!", dev->name);
napi_disable(&fep->napi);
return -EINVAL; return -EINVAL;
} }
err = fs_init_phy(dev); err = fs_init_phy(dev);
if(err) if(err) {
napi_disable(&fep->napi);
return err; return err;
}
phy_start(fep->phydev); phy_start(fep->phydev);
return 0; return 0;
...@@ -823,6 +816,7 @@ static int fs_enet_close(struct net_device *dev) ...@@ -823,6 +816,7 @@ static int fs_enet_close(struct net_device *dev)
netif_stop_queue(dev); netif_stop_queue(dev);
netif_carrier_off(dev); netif_carrier_off(dev);
napi_disable(&fep->napi);
phy_stop(fep->phydev); phy_stop(fep->phydev);
spin_lock_irqsave(&fep->lock, flags); spin_lock_irqsave(&fep->lock, flags);
...@@ -1047,10 +1041,9 @@ static struct net_device *fs_init_instance(struct device *dev, ...@@ -1047,10 +1041,9 @@ static struct net_device *fs_init_instance(struct device *dev,
ndev->stop = fs_enet_close; ndev->stop = fs_enet_close;
ndev->get_stats = fs_enet_get_stats; ndev->get_stats = fs_enet_get_stats;
ndev->set_multicast_list = fs_set_multicast_list; ndev->set_multicast_list = fs_set_multicast_list;
if (fpi->use_napi) { netif_napi_add(ndev, &fep->napi,
ndev->poll = fs_enet_rx_napi; fs_enet_rx_napi, fpi->napi_weight);
ndev->weight = fpi->napi_weight;
}
ndev->ethtool_ops = &fs_ethtool_ops; ndev->ethtool_ops = &fs_ethtool_ops;
ndev->do_ioctl = fs_ioctl; ndev->do_ioctl = fs_ioctl;
......
...@@ -121,6 +121,7 @@ struct fs_enet_mii_bus { ...@@ -121,6 +121,7 @@ struct fs_enet_mii_bus {
}; };
struct fs_enet_private { struct fs_enet_private {
struct napi_struct napi;
struct device *dev; /* pointer back to the device (must be initialized first) */ struct device *dev; /* pointer back to the device (must be initialized first) */
spinlock_t lock; /* during all ops except TX pckt processing */ spinlock_t lock; /* during all ops except TX pckt processing */
spinlock_t tx_lock; /* during fs_start_xmit and fs_tx */ spinlock_t tx_lock; /* during fs_start_xmit and fs_tx */
......
...@@ -134,7 +134,7 @@ static void gfar_configure_serdes(struct net_device *dev); ...@@ -134,7 +134,7 @@ static void gfar_configure_serdes(struct net_device *dev);
extern int gfar_local_mdio_write(struct gfar_mii *regs, int mii_id, int regnum, u16 value); extern int gfar_local_mdio_write(struct gfar_mii *regs, int mii_id, int regnum, u16 value);
extern int gfar_local_mdio_read(struct gfar_mii *regs, int mii_id, int regnum); extern int gfar_local_mdio_read(struct gfar_mii *regs, int mii_id, int regnum);
#ifdef CONFIG_GFAR_NAPI #ifdef CONFIG_GFAR_NAPI
static int gfar_poll(struct net_device *dev, int *budget); static int gfar_poll(struct napi_struct *napi, int budget);
#endif #endif
#ifdef CONFIG_NET_POLL_CONTROLLER #ifdef CONFIG_NET_POLL_CONTROLLER
static void gfar_netpoll(struct net_device *dev); static void gfar_netpoll(struct net_device *dev);
...@@ -188,6 +188,7 @@ static int gfar_probe(struct platform_device *pdev) ...@@ -188,6 +188,7 @@ static int gfar_probe(struct platform_device *pdev)
return -ENOMEM; return -ENOMEM;
priv = netdev_priv(dev); priv = netdev_priv(dev);
priv->dev = dev;
/* Set the info in the priv to the current info */ /* Set the info in the priv to the current info */
priv->einfo = einfo; priv->einfo = einfo;
...@@ -261,10 +262,7 @@ static int gfar_probe(struct platform_device *pdev) ...@@ -261,10 +262,7 @@ static int gfar_probe(struct platform_device *pdev)
dev->hard_start_xmit = gfar_start_xmit; dev->hard_start_xmit = gfar_start_xmit;
dev->tx_timeout = gfar_timeout; dev->tx_timeout = gfar_timeout;
dev->watchdog_timeo = TX_TIMEOUT; dev->watchdog_timeo = TX_TIMEOUT;
#ifdef CONFIG_GFAR_NAPI netif_napi_add(dev, &priv->napi, gfar_poll, GFAR_DEV_WEIGHT);
dev->poll = gfar_poll;
dev->weight = GFAR_DEV_WEIGHT;
#endif
#ifdef CONFIG_NET_POLL_CONTROLLER #ifdef CONFIG_NET_POLL_CONTROLLER
dev->poll_controller = gfar_netpoll; dev->poll_controller = gfar_netpoll;
#endif #endif
...@@ -939,6 +937,8 @@ static int gfar_enet_open(struct net_device *dev) ...@@ -939,6 +937,8 @@ static int gfar_enet_open(struct net_device *dev)
{ {
int err; int err;
napi_enable(&priv->napi);
/* Initialize a bunch of registers */ /* Initialize a bunch of registers */
init_registers(dev); init_registers(dev);
...@@ -946,10 +946,14 @@ static int gfar_enet_open(struct net_device *dev) ...@@ -946,10 +946,14 @@ static int gfar_enet_open(struct net_device *dev)
err = init_phy(dev); err = init_phy(dev);
if(err) if(err) {
napi_disable(&priv->napi);
return err; return err;
}
err = startup_gfar(dev); err = startup_gfar(dev);
if (err)
napi_disable(&priv->napi);
netif_start_queue(dev); netif_start_queue(dev);
...@@ -1102,6 +1106,9 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -1102,6 +1106,9 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev)
static int gfar_close(struct net_device *dev) static int gfar_close(struct net_device *dev)
{ {
struct gfar_private *priv = netdev_priv(dev); struct gfar_private *priv = netdev_priv(dev);
napi_disable(&priv->napi);
stop_gfar(dev); stop_gfar(dev);
/* Disconnect from the PHY */ /* Disconnect from the PHY */
...@@ -1318,7 +1325,7 @@ struct sk_buff * gfar_new_skb(struct net_device *dev, struct rxbd8 *bdp) ...@@ -1318,7 +1325,7 @@ struct sk_buff * gfar_new_skb(struct net_device *dev, struct rxbd8 *bdp)
return NULL; return NULL;
alignamount = RXBUF_ALIGNMENT - alignamount = RXBUF_ALIGNMENT -
(((unsigned) skb->data) & (RXBUF_ALIGNMENT - 1)); (((unsigned long) skb->data) & (RXBUF_ALIGNMENT - 1));
/* We need the data buffer to be aligned properly. We will reserve /* We need the data buffer to be aligned properly. We will reserve
* as many bytes as needed to align the data properly * as many bytes as needed to align the data properly
...@@ -1390,12 +1397,12 @@ irqreturn_t gfar_receive(int irq, void *dev_id) ...@@ -1390,12 +1397,12 @@ irqreturn_t gfar_receive(int irq, void *dev_id)
/* support NAPI */ /* support NAPI */
#ifdef CONFIG_GFAR_NAPI #ifdef CONFIG_GFAR_NAPI
if (netif_rx_schedule_prep(dev)) { if (netif_rx_schedule_prep(dev, &priv->napi)) {
tempval = gfar_read(&priv->regs->imask); tempval = gfar_read(&priv->regs->imask);
tempval &= IMASK_RX_DISABLED; tempval &= IMASK_RX_DISABLED;
gfar_write(&priv->regs->imask, tempval); gfar_write(&priv->regs->imask, tempval);
__netif_rx_schedule(dev); __netif_rx_schedule(dev, &priv->napi);
} else { } else {
if (netif_msg_rx_err(priv)) if (netif_msg_rx_err(priv))
printk(KERN_DEBUG "%s: receive called twice (%x)[%x]\n", printk(KERN_DEBUG "%s: receive called twice (%x)[%x]\n",
...@@ -1569,23 +1576,16 @@ int gfar_clean_rx_ring(struct net_device *dev, int rx_work_limit) ...@@ -1569,23 +1576,16 @@ int gfar_clean_rx_ring(struct net_device *dev, int rx_work_limit)
} }
#ifdef CONFIG_GFAR_NAPI #ifdef CONFIG_GFAR_NAPI
static int gfar_poll(struct net_device *dev, int *budget) static int gfar_poll(struct napi_struct *napi, int budget)
{ {
struct gfar_private *priv = container_of(napi, struct gfar_private, napi);
struct net_device *dev = priv->dev;
int howmany; int howmany;
struct gfar_private *priv = netdev_priv(dev);
int rx_work_limit = *budget;
if (rx_work_limit > dev->quota)
rx_work_limit = dev->quota;
howmany = gfar_clean_rx_ring(dev, rx_work_limit); howmany = gfar_clean_rx_ring(dev, budget);
dev->quota -= howmany; if (howmany < budget) {
rx_work_limit -= howmany; netif_rx_complete(dev, napi);
*budget -= howmany;
if (rx_work_limit > 0) {
netif_rx_complete(dev);
/* Clear the halt bit in RSTAT */ /* Clear the halt bit in RSTAT */
gfar_write(&priv->regs->rstat, RSTAT_CLEAR_RHALT); gfar_write(&priv->regs->rstat, RSTAT_CLEAR_RHALT);
...@@ -1601,8 +1601,7 @@ static int gfar_poll(struct net_device *dev, int *budget) ...@@ -1601,8 +1601,7 @@ static int gfar_poll(struct net_device *dev, int *budget)
gfar_write(&priv->regs->rxic, 0); gfar_write(&priv->regs->rxic, 0);
} }
/* Return 1 if there's more work to do */ return howmany;
return (rx_work_limit > 0) ? 0 : 1;
} }
#endif #endif
......
...@@ -691,6 +691,9 @@ struct gfar_private { ...@@ -691,6 +691,9 @@ struct gfar_private {
/* RX Locked fields */ /* RX Locked fields */
spinlock_t rxlock; spinlock_t rxlock;
struct net_device *dev;
struct napi_struct napi;
/* skb array and index */ /* skb array and index */
struct sk_buff ** rx_skbuff; struct sk_buff ** rx_skbuff;
u16 skb_currx; u16 skb_currx;
......
...@@ -83,7 +83,7 @@ ...@@ -83,7 +83,7 @@
static int ibmveth_open(struct net_device *dev); static int ibmveth_open(struct net_device *dev);
static int ibmveth_close(struct net_device *dev); static int ibmveth_close(struct net_device *dev);
static int ibmveth_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd); static int ibmveth_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd);
static int ibmveth_poll(struct net_device *dev, int *budget); static int ibmveth_poll(struct napi_struct *napi, int budget);
static int ibmveth_start_xmit(struct sk_buff *skb, struct net_device *dev); static int ibmveth_start_xmit(struct sk_buff *skb, struct net_device *dev);
static struct net_device_stats *ibmveth_get_stats(struct net_device *dev); static struct net_device_stats *ibmveth_get_stats(struct net_device *dev);
static void ibmveth_set_multicast_list(struct net_device *dev); static void ibmveth_set_multicast_list(struct net_device *dev);
...@@ -480,6 +480,8 @@ static int ibmveth_open(struct net_device *netdev) ...@@ -480,6 +480,8 @@ static int ibmveth_open(struct net_device *netdev)
ibmveth_debug_printk("open starting\n"); ibmveth_debug_printk("open starting\n");
napi_enable(&adapter->napi);
for(i = 0; i<IbmVethNumBufferPools; i++) for(i = 0; i<IbmVethNumBufferPools; i++)
rxq_entries += adapter->rx_buff_pool[i].size; rxq_entries += adapter->rx_buff_pool[i].size;
...@@ -489,6 +491,7 @@ static int ibmveth_open(struct net_device *netdev) ...@@ -489,6 +491,7 @@ static int ibmveth_open(struct net_device *netdev)
if(!adapter->buffer_list_addr || !adapter->filter_list_addr) { if(!adapter->buffer_list_addr || !adapter->filter_list_addr) {
ibmveth_error_printk("unable to allocate filter or buffer list pages\n"); ibmveth_error_printk("unable to allocate filter or buffer list pages\n");
ibmveth_cleanup(adapter); ibmveth_cleanup(adapter);
napi_disable(&adapter->napi);
return -ENOMEM; return -ENOMEM;
} }
...@@ -498,6 +501,7 @@ static int ibmveth_open(struct net_device *netdev) ...@@ -498,6 +501,7 @@ static int ibmveth_open(struct net_device *netdev)
if(!adapter->rx_queue.queue_addr) { if(!adapter->rx_queue.queue_addr) {
ibmveth_error_printk("unable to allocate rx queue pages\n"); ibmveth_error_printk("unable to allocate rx queue pages\n");
ibmveth_cleanup(adapter); ibmveth_cleanup(adapter);
napi_disable(&adapter->napi);
return -ENOMEM; return -ENOMEM;
} }
...@@ -514,6 +518,7 @@ static int ibmveth_open(struct net_device *netdev) ...@@ -514,6 +518,7 @@ static int ibmveth_open(struct net_device *netdev)
(dma_mapping_error(adapter->rx_queue.queue_dma))) { (dma_mapping_error(adapter->rx_queue.queue_dma))) {
ibmveth_error_printk("unable to map filter or buffer list pages\n"); ibmveth_error_printk("unable to map filter or buffer list pages\n");
ibmveth_cleanup(adapter); ibmveth_cleanup(adapter);
napi_disable(&adapter->napi);
return -ENOMEM; return -ENOMEM;
} }
...@@ -545,6 +550,7 @@ static int ibmveth_open(struct net_device *netdev) ...@@ -545,6 +550,7 @@ static int ibmveth_open(struct net_device *netdev)
rxq_desc.desc, rxq_desc.desc,
mac_address); mac_address);
ibmveth_cleanup(adapter); ibmveth_cleanup(adapter);
napi_disable(&adapter->napi);
return -ENONET; return -ENONET;
} }
...@@ -555,6 +561,7 @@ static int ibmveth_open(struct net_device *netdev) ...@@ -555,6 +561,7 @@ static int ibmveth_open(struct net_device *netdev)
ibmveth_error_printk("unable to alloc pool\n"); ibmveth_error_printk("unable to alloc pool\n");
adapter->rx_buff_pool[i].active = 0; adapter->rx_buff_pool[i].active = 0;
ibmveth_cleanup(adapter); ibmveth_cleanup(adapter);
napi_disable(&adapter->napi);
return -ENOMEM ; return -ENOMEM ;
} }
} }
...@@ -567,6 +574,7 @@ static int ibmveth_open(struct net_device *netdev) ...@@ -567,6 +574,7 @@ static int ibmveth_open(struct net_device *netdev)
} while (H_IS_LONG_BUSY(rc) || (rc == H_BUSY)); } while (H_IS_LONG_BUSY(rc) || (rc == H_BUSY));
ibmveth_cleanup(adapter); ibmveth_cleanup(adapter);
napi_disable(&adapter->napi);
return rc; return rc;
} }
...@@ -587,6 +595,8 @@ static int ibmveth_close(struct net_device *netdev) ...@@ -587,6 +595,8 @@ static int ibmveth_close(struct net_device *netdev)
ibmveth_debug_printk("close starting\n"); ibmveth_debug_printk("close starting\n");
napi_disable(&adapter->napi);
if (!adapter->pool_config) if (!adapter->pool_config)
netif_stop_queue(netdev); netif_stop_queue(netdev);
...@@ -767,80 +777,68 @@ out: spin_lock_irqsave(&adapter->stats_lock, flags); ...@@ -767,80 +777,68 @@ out: spin_lock_irqsave(&adapter->stats_lock, flags);
return 0; return 0;
} }
static int ibmveth_poll(struct net_device *netdev, int *budget) static int ibmveth_poll(struct napi_struct *napi, int budget)
{ {
struct ibmveth_adapter *adapter = netdev->priv; struct ibmveth_adapter *adapter = container_of(napi, struct ibmveth_adapter, napi);
int max_frames_to_process = netdev->quota; struct net_device *netdev = adapter->netdev;
int frames_processed = 0; int frames_processed = 0;
int more_work = 1;
unsigned long lpar_rc; unsigned long lpar_rc;
restart_poll: restart_poll:
do { do {
struct net_device *netdev = adapter->netdev; struct sk_buff *skb;
if(ibmveth_rxq_pending_buffer(adapter)) {
struct sk_buff *skb;
rmb(); if (!ibmveth_rxq_pending_buffer(adapter))
break;
if(!ibmveth_rxq_buffer_valid(adapter)) { rmb();
wmb(); /* suggested by larson1 */ if (!ibmveth_rxq_buffer_valid(adapter)) {
adapter->rx_invalid_buffer++; wmb(); /* suggested by larson1 */
ibmveth_debug_printk("recycling invalid buffer\n"); adapter->rx_invalid_buffer++;
ibmveth_rxq_recycle_buffer(adapter); ibmveth_debug_printk("recycling invalid buffer\n");
} else { ibmveth_rxq_recycle_buffer(adapter);
int length = ibmveth_rxq_frame_length(adapter); } else {
int offset = ibmveth_rxq_frame_offset(adapter); int length = ibmveth_rxq_frame_length(adapter);
skb = ibmveth_rxq_get_buffer(adapter); int offset = ibmveth_rxq_frame_offset(adapter);
skb = ibmveth_rxq_get_buffer(adapter);
ibmveth_rxq_harvest_buffer(adapter); ibmveth_rxq_harvest_buffer(adapter);
skb_reserve(skb, offset); skb_reserve(skb, offset);
skb_put(skb, length); skb_put(skb, length);
skb->protocol = eth_type_trans(skb, netdev); skb->protocol = eth_type_trans(skb, netdev);
netif_receive_skb(skb); /* send it up */ netif_receive_skb(skb); /* send it up */
adapter->stats.rx_packets++; adapter->stats.rx_packets++;
adapter->stats.rx_bytes += length; adapter->stats.rx_bytes += length;
frames_processed++; frames_processed++;
netdev->last_rx = jiffies; netdev->last_rx = jiffies;
}
} else {
more_work = 0;
} }
} while(more_work && (frames_processed < max_frames_to_process)); } while (frames_processed < budget);
ibmveth_replenish_task(adapter); ibmveth_replenish_task(adapter);
if(more_work) { if (frames_processed < budget) {
/* more work to do - return that we are not done yet */ /* We think we are done - reenable interrupts,
netdev->quota -= frames_processed; * then check once more to make sure we are done.
*budget -= frames_processed; */
return 1; lpar_rc = h_vio_signal(adapter->vdev->unit_address,
} VIO_IRQ_ENABLE);
/* we think we are done - reenable interrupts, then check once more to make sure we are done */
lpar_rc = h_vio_signal(adapter->vdev->unit_address, VIO_IRQ_ENABLE);
ibmveth_assert(lpar_rc == H_SUCCESS); ibmveth_assert(lpar_rc == H_SUCCESS);
netif_rx_complete(netdev); netif_rx_complete(netdev, napi);
if(ibmveth_rxq_pending_buffer(adapter) && netif_rx_reschedule(netdev, frames_processed)) if (ibmveth_rxq_pending_buffer(adapter) &&
{ netif_rx_reschedule(netdev, napi)) {
lpar_rc = h_vio_signal(adapter->vdev->unit_address, VIO_IRQ_DISABLE); lpar_rc = h_vio_signal(adapter->vdev->unit_address,
ibmveth_assert(lpar_rc == H_SUCCESS); VIO_IRQ_DISABLE);
more_work = 1; goto restart_poll;
goto restart_poll; }
} }
netdev->quota -= frames_processed; return frames_processed;
*budget -= frames_processed;
/* we really are done */
return 0;
} }
static irqreturn_t ibmveth_interrupt(int irq, void *dev_instance) static irqreturn_t ibmveth_interrupt(int irq, void *dev_instance)
...@@ -849,10 +847,11 @@ static irqreturn_t ibmveth_interrupt(int irq, void *dev_instance) ...@@ -849,10 +847,11 @@ static irqreturn_t ibmveth_interrupt(int irq, void *dev_instance)
struct ibmveth_adapter *adapter = netdev->priv; struct ibmveth_adapter *adapter = netdev->priv;
unsigned long lpar_rc; unsigned long lpar_rc;
if(netif_rx_schedule_prep(netdev)) { if (netif_rx_schedule_prep(netdev, &adapter->napi)) {
lpar_rc = h_vio_signal(adapter->vdev->unit_address, VIO_IRQ_DISABLE); lpar_rc = h_vio_signal(adapter->vdev->unit_address,
VIO_IRQ_DISABLE);
ibmveth_assert(lpar_rc == H_SUCCESS); ibmveth_assert(lpar_rc == H_SUCCESS);
__netif_rx_schedule(netdev); __netif_rx_schedule(netdev, &adapter->napi);
} }
return IRQ_HANDLED; return IRQ_HANDLED;
} }
...@@ -1004,6 +1003,8 @@ static int __devinit ibmveth_probe(struct vio_dev *dev, const struct vio_device_ ...@@ -1004,6 +1003,8 @@ static int __devinit ibmveth_probe(struct vio_dev *dev, const struct vio_device_
adapter->mcastFilterSize= *mcastFilterSize_p; adapter->mcastFilterSize= *mcastFilterSize_p;
adapter->pool_config = 0; adapter->pool_config = 0;
netif_napi_add(netdev, &adapter->napi, ibmveth_poll, 16);
/* Some older boxes running PHYP non-natively have an OF that /* Some older boxes running PHYP non-natively have an OF that
returns a 8-byte local-mac-address field (and the first returns a 8-byte local-mac-address field (and the first
2 bytes have to be ignored) while newer boxes' OF return 2 bytes have to be ignored) while newer boxes' OF return
...@@ -1020,8 +1021,6 @@ static int __devinit ibmveth_probe(struct vio_dev *dev, const struct vio_device_ ...@@ -1020,8 +1021,6 @@ static int __devinit ibmveth_probe(struct vio_dev *dev, const struct vio_device_
netdev->irq = dev->irq; netdev->irq = dev->irq;
netdev->open = ibmveth_open; netdev->open = ibmveth_open;
netdev->poll = ibmveth_poll;
netdev->weight = 16;
netdev->stop = ibmveth_close; netdev->stop = ibmveth_close;
netdev->hard_start_xmit = ibmveth_start_xmit; netdev->hard_start_xmit = ibmveth_start_xmit;
netdev->get_stats = ibmveth_get_stats; netdev->get_stats = ibmveth_get_stats;
......
...@@ -112,6 +112,7 @@ struct ibmveth_rx_q { ...@@ -112,6 +112,7 @@ struct ibmveth_rx_q {
struct ibmveth_adapter { struct ibmveth_adapter {
struct vio_dev *vdev; struct vio_dev *vdev;
struct net_device *netdev; struct net_device *netdev;
struct napi_struct napi;
struct net_device_stats stats; struct net_device_stats stats;
unsigned int mcastFilterSize; unsigned int mcastFilterSize;
unsigned long mac_addr; unsigned long mac_addr;
......
...@@ -184,6 +184,7 @@ struct ixgb_adapter { ...@@ -184,6 +184,7 @@ struct ixgb_adapter {
boolean_t rx_csum; boolean_t rx_csum;
/* OS defined structs */ /* OS defined structs */
struct napi_struct napi;
struct net_device *netdev; struct net_device *netdev;
struct pci_dev *pdev; struct pci_dev *pdev;
struct net_device_stats net_stats; struct net_device_stats net_stats;
......
...@@ -97,7 +97,7 @@ static irqreturn_t ixgb_intr(int irq, void *data); ...@@ -97,7 +97,7 @@ static irqreturn_t ixgb_intr(int irq, void *data);
static boolean_t ixgb_clean_tx_irq(struct ixgb_adapter *adapter); static boolean_t ixgb_clean_tx_irq(struct ixgb_adapter *adapter);
#ifdef CONFIG_IXGB_NAPI #ifdef CONFIG_IXGB_NAPI
static int ixgb_clean(struct net_device *netdev, int *budget); static int ixgb_clean(struct napi_struct *napi, int budget);
static boolean_t ixgb_clean_rx_irq(struct ixgb_adapter *adapter, static boolean_t ixgb_clean_rx_irq(struct ixgb_adapter *adapter,
int *work_done, int work_to_do); int *work_done, int work_to_do);
#else #else
...@@ -288,7 +288,7 @@ ixgb_up(struct ixgb_adapter *adapter) ...@@ -288,7 +288,7 @@ ixgb_up(struct ixgb_adapter *adapter)
mod_timer(&adapter->watchdog_timer, jiffies); mod_timer(&adapter->watchdog_timer, jiffies);
#ifdef CONFIG_IXGB_NAPI #ifdef CONFIG_IXGB_NAPI
netif_poll_enable(netdev); napi_enable(&adapter->napi);
#endif #endif
ixgb_irq_enable(adapter); ixgb_irq_enable(adapter);
...@@ -309,7 +309,7 @@ ixgb_down(struct ixgb_adapter *adapter, boolean_t kill_watchdog) ...@@ -309,7 +309,7 @@ ixgb_down(struct ixgb_adapter *adapter, boolean_t kill_watchdog)
if(kill_watchdog) if(kill_watchdog)
del_timer_sync(&adapter->watchdog_timer); del_timer_sync(&adapter->watchdog_timer);
#ifdef CONFIG_IXGB_NAPI #ifdef CONFIG_IXGB_NAPI
netif_poll_disable(netdev); napi_disable(&adapter->napi);
#endif #endif
adapter->link_speed = 0; adapter->link_speed = 0;
adapter->link_duplex = 0; adapter->link_duplex = 0;
...@@ -421,8 +421,7 @@ ixgb_probe(struct pci_dev *pdev, ...@@ -421,8 +421,7 @@ ixgb_probe(struct pci_dev *pdev,
netdev->tx_timeout = &ixgb_tx_timeout; netdev->tx_timeout = &ixgb_tx_timeout;
netdev->watchdog_timeo = 5 * HZ; netdev->watchdog_timeo = 5 * HZ;
#ifdef CONFIG_IXGB_NAPI #ifdef CONFIG_IXGB_NAPI
netdev->poll = &ixgb_clean; netif_napi_add(netdev, &adapter->napi, ixgb_clean, 64);
netdev->weight = 64;
#endif #endif
netdev->vlan_rx_register = ixgb_vlan_rx_register; netdev->vlan_rx_register = ixgb_vlan_rx_register;
netdev->vlan_rx_add_vid = ixgb_vlan_rx_add_vid; netdev->vlan_rx_add_vid = ixgb_vlan_rx_add_vid;
...@@ -1746,7 +1745,7 @@ ixgb_intr(int irq, void *data) ...@@ -1746,7 +1745,7 @@ ixgb_intr(int irq, void *data)
} }
#ifdef CONFIG_IXGB_NAPI #ifdef CONFIG_IXGB_NAPI
if(netif_rx_schedule_prep(netdev)) { if (netif_rx_schedule_prep(netdev, &adapter->napi)) {
/* Disable interrupts and register for poll. The flush /* Disable interrupts and register for poll. The flush
of the posted write is intentionally left out. of the posted write is intentionally left out.
...@@ -1754,7 +1753,7 @@ ixgb_intr(int irq, void *data) ...@@ -1754,7 +1753,7 @@ ixgb_intr(int irq, void *data)
atomic_inc(&adapter->irq_sem); atomic_inc(&adapter->irq_sem);
IXGB_WRITE_REG(&adapter->hw, IMC, ~0); IXGB_WRITE_REG(&adapter->hw, IMC, ~0);
__netif_rx_schedule(netdev); __netif_rx_schedule(netdev, &adapter->napi);
} }
#else #else
/* yes, that is actually a & and it is meant to make sure that /* yes, that is actually a & and it is meant to make sure that
...@@ -1776,27 +1775,23 @@ ixgb_intr(int irq, void *data) ...@@ -1776,27 +1775,23 @@ ixgb_intr(int irq, void *data)
**/ **/
static int static int
ixgb_clean(struct net_device *netdev, int *budget) ixgb_clean(struct napi_struct *napi, int budget)
{ {
struct ixgb_adapter *adapter = netdev_priv(netdev); struct ixgb_adapter *adapter = container_of(napi, struct ixgb_adapter, napi);
int work_to_do = min(*budget, netdev->quota); struct net_device *netdev = adapter->netdev;
int tx_cleaned; int tx_cleaned;
int work_done = 0; int work_done = 0;
tx_cleaned = ixgb_clean_tx_irq(adapter); tx_cleaned = ixgb_clean_tx_irq(adapter);
ixgb_clean_rx_irq(adapter, &work_done, work_to_do); ixgb_clean_rx_irq(adapter, &work_done, budget);
*budget -= work_done;
netdev->quota -= work_done;
/* if no Tx and not enough Rx work done, exit the polling mode */ /* if no Tx and not enough Rx work done, exit the polling mode */
if((!tx_cleaned && (work_done == 0)) || !netif_running(netdev)) { if((!tx_cleaned && (work_done == 0)) || !netif_running(netdev)) {
netif_rx_complete(netdev); netif_rx_complete(netdev, napi);
ixgb_irq_enable(adapter); ixgb_irq_enable(adapter);
return 0;
} }
return 1; return work_done;
} }
#endif #endif
......
...@@ -74,9 +74,9 @@ static int ixpdev_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -74,9 +74,9 @@ static int ixpdev_xmit(struct sk_buff *skb, struct net_device *dev)
} }
static int ixpdev_rx(struct net_device *dev, int *budget) static int ixpdev_rx(struct net_device *dev, int processed, int budget)
{ {
while (*budget > 0) { while (processed < budget) {
struct ixpdev_rx_desc *desc; struct ixpdev_rx_desc *desc;
struct sk_buff *skb; struct sk_buff *skb;
void *buf; void *buf;
...@@ -122,29 +122,34 @@ static int ixpdev_rx(struct net_device *dev, int *budget) ...@@ -122,29 +122,34 @@ static int ixpdev_rx(struct net_device *dev, int *budget)
err: err:
ixp2000_reg_write(RING_RX_PENDING, _desc); ixp2000_reg_write(RING_RX_PENDING, _desc);
dev->quota--; processed++;
(*budget)--;
} }
return 1; return processed;
} }
/* dev always points to nds[0]. */ /* dev always points to nds[0]. */
static int ixpdev_poll(struct net_device *dev, int *budget) static int ixpdev_poll(struct napi_struct *napi, int budget)
{ {
struct ixpdev_priv *ip = container_of(napi, struct ixpdev_priv, napi);
struct net_device *dev = ip->dev;
int rx;
/* @@@ Have to stop polling when nds[0] is administratively /* @@@ Have to stop polling when nds[0] is administratively
* downed while we are polling. */ * downed while we are polling. */
rx = 0;
do { do {
ixp2000_reg_write(IXP2000_IRQ_THD_RAW_STATUS_A_0, 0x00ff); ixp2000_reg_write(IXP2000_IRQ_THD_RAW_STATUS_A_0, 0x00ff);
if (ixpdev_rx(dev, budget)) rx = ixpdev_rx(dev, rx, budget);
return 1; if (rx >= budget)
break;
} while (ixp2000_reg_read(IXP2000_IRQ_THD_RAW_STATUS_A_0) & 0x00ff); } while (ixp2000_reg_read(IXP2000_IRQ_THD_RAW_STATUS_A_0) & 0x00ff);
netif_rx_complete(dev); netif_rx_complete(dev, napi);
ixp2000_reg_write(IXP2000_IRQ_THD_ENABLE_SET_A_0, 0x00ff); ixp2000_reg_write(IXP2000_IRQ_THD_ENABLE_SET_A_0, 0x00ff);
return 0; return rx;
} }
static void ixpdev_tx_complete(void) static void ixpdev_tx_complete(void)
...@@ -199,9 +204,12 @@ static irqreturn_t ixpdev_interrupt(int irq, void *dev_id) ...@@ -199,9 +204,12 @@ static irqreturn_t ixpdev_interrupt(int irq, void *dev_id)
* Any of the eight receive units signaled RX? * Any of the eight receive units signaled RX?
*/ */
if (status & 0x00ff) { if (status & 0x00ff) {
struct net_device *dev = nds[0];
struct ixpdev_priv *ip = netdev_priv(dev);
ixp2000_reg_wrb(IXP2000_IRQ_THD_ENABLE_CLEAR_A_0, 0x00ff); ixp2000_reg_wrb(IXP2000_IRQ_THD_ENABLE_CLEAR_A_0, 0x00ff);
if (likely(__netif_rx_schedule_prep(nds[0]))) { if (likely(napi_schedule_prep(&ip->napi))) {
__netif_rx_schedule(nds[0]); __netif_rx_schedule(dev, &ip->napi);
} else { } else {
printk(KERN_CRIT "ixp2000: irq while polling!!\n"); printk(KERN_CRIT "ixp2000: irq while polling!!\n");
} }
...@@ -232,11 +240,13 @@ static int ixpdev_open(struct net_device *dev) ...@@ -232,11 +240,13 @@ static int ixpdev_open(struct net_device *dev)
struct ixpdev_priv *ip = netdev_priv(dev); struct ixpdev_priv *ip = netdev_priv(dev);
int err; int err;
napi_enable(&ip->napi);
if (!nds_open++) { if (!nds_open++) {
err = request_irq(IRQ_IXP2000_THDA0, ixpdev_interrupt, err = request_irq(IRQ_IXP2000_THDA0, ixpdev_interrupt,
IRQF_SHARED, "ixp2000_eth", nds); IRQF_SHARED, "ixp2000_eth", nds);
if (err) { if (err) {
nds_open--; nds_open--;
napi_disable(&ip->napi);
return err; return err;
} }
...@@ -254,6 +264,7 @@ static int ixpdev_close(struct net_device *dev) ...@@ -254,6 +264,7 @@ static int ixpdev_close(struct net_device *dev)
struct ixpdev_priv *ip = netdev_priv(dev); struct ixpdev_priv *ip = netdev_priv(dev);
netif_stop_queue(dev); netif_stop_queue(dev);
napi_disable(&ip->napi);
set_port_admin_status(ip->channel, 0); set_port_admin_status(ip->channel, 0);
if (!--nds_open) { if (!--nds_open) {
...@@ -274,7 +285,6 @@ struct net_device *ixpdev_alloc(int channel, int sizeof_priv) ...@@ -274,7 +285,6 @@ struct net_device *ixpdev_alloc(int channel, int sizeof_priv)
return NULL; return NULL;
dev->hard_start_xmit = ixpdev_xmit; dev->hard_start_xmit = ixpdev_xmit;
dev->poll = ixpdev_poll;
dev->open = ixpdev_open; dev->open = ixpdev_open;
dev->stop = ixpdev_close; dev->stop = ixpdev_close;
#ifdef CONFIG_NET_POLL_CONTROLLER #ifdef CONFIG_NET_POLL_CONTROLLER
...@@ -282,9 +292,10 @@ struct net_device *ixpdev_alloc(int channel, int sizeof_priv) ...@@ -282,9 +292,10 @@ struct net_device *ixpdev_alloc(int channel, int sizeof_priv)
#endif #endif
dev->features |= NETIF_F_SG | NETIF_F_HW_CSUM; dev->features |= NETIF_F_SG | NETIF_F_HW_CSUM;
dev->weight = 64;
ip = netdev_priv(dev); ip = netdev_priv(dev);
ip->dev = dev;
netif_napi_add(dev, &ip->napi, ixpdev_poll, 64);
ip->channel = channel; ip->channel = channel;
ip->tx_queue_entries = 0; ip->tx_queue_entries = 0;
......
...@@ -14,6 +14,8 @@ ...@@ -14,6 +14,8 @@
struct ixpdev_priv struct ixpdev_priv
{ {
struct net_device *dev;
struct napi_struct napi;
int channel; int channel;
int tx_queue_entries; int tx_queue_entries;
}; };
......
...@@ -470,47 +470,41 @@ static int macb_rx(struct macb *bp, int budget) ...@@ -470,47 +470,41 @@ static int macb_rx(struct macb *bp, int budget)
return received; return received;
} }
static int macb_poll(struct net_device *dev, int *budget) static int macb_poll(struct napi_struct *napi, int budget)
{ {
struct macb *bp = netdev_priv(dev); struct macb *bp = container_of(napi, struct macb, napi);
int orig_budget, work_done, retval = 0; struct net_device *dev = bp->dev;
int work_done;
u32 status; u32 status;
status = macb_readl(bp, RSR); status = macb_readl(bp, RSR);
macb_writel(bp, RSR, status); macb_writel(bp, RSR, status);
work_done = 0;
if (!status) { if (!status) {
/* /*
* This may happen if an interrupt was pending before * This may happen if an interrupt was pending before
* this function was called last time, and no packets * this function was called last time, and no packets
* have been received since. * have been received since.
*/ */
netif_rx_complete(dev); netif_rx_complete(dev, napi);
goto out; goto out;
} }
dev_dbg(&bp->pdev->dev, "poll: status = %08lx, budget = %d\n", dev_dbg(&bp->pdev->dev, "poll: status = %08lx, budget = %d\n",
(unsigned long)status, *budget); (unsigned long)status, budget);
if (!(status & MACB_BIT(REC))) { if (!(status & MACB_BIT(REC))) {
dev_warn(&bp->pdev->dev, dev_warn(&bp->pdev->dev,
"No RX buffers complete, status = %02lx\n", "No RX buffers complete, status = %02lx\n",
(unsigned long)status); (unsigned long)status);
netif_rx_complete(dev); netif_rx_complete(dev, napi);
goto out; goto out;
} }
orig_budget = *budget; work_done = macb_rx(bp, budget);
if (orig_budget > dev->quota) if (work_done < budget)
orig_budget = dev->quota; netif_rx_complete(dev, napi);
work_done = macb_rx(bp, orig_budget);
if (work_done < orig_budget) {
netif_rx_complete(dev);
retval = 0;
} else {
retval = 1;
}
/* /*
* We've done what we can to clean the buffers. Make sure we * We've done what we can to clean the buffers. Make sure we
...@@ -521,7 +515,7 @@ static int macb_poll(struct net_device *dev, int *budget) ...@@ -521,7 +515,7 @@ static int macb_poll(struct net_device *dev, int *budget)
/* TODO: Handle errors */ /* TODO: Handle errors */
return retval; return work_done;
} }
static irqreturn_t macb_interrupt(int irq, void *dev_id) static irqreturn_t macb_interrupt(int irq, void *dev_id)
...@@ -545,7 +539,7 @@ static irqreturn_t macb_interrupt(int irq, void *dev_id) ...@@ -545,7 +539,7 @@ static irqreturn_t macb_interrupt(int irq, void *dev_id)
} }
if (status & MACB_RX_INT_FLAGS) { if (status & MACB_RX_INT_FLAGS) {
if (netif_rx_schedule_prep(dev)) { if (netif_rx_schedule_prep(dev, &bp->napi)) {
/* /*
* There's no point taking any more interrupts * There's no point taking any more interrupts
* until we have processed the buffers * until we have processed the buffers
...@@ -553,7 +547,7 @@ static irqreturn_t macb_interrupt(int irq, void *dev_id) ...@@ -553,7 +547,7 @@ static irqreturn_t macb_interrupt(int irq, void *dev_id)
macb_writel(bp, IDR, MACB_RX_INT_FLAGS); macb_writel(bp, IDR, MACB_RX_INT_FLAGS);
dev_dbg(&bp->pdev->dev, dev_dbg(&bp->pdev->dev,
"scheduling RX softirq\n"); "scheduling RX softirq\n");
__netif_rx_schedule(dev); __netif_rx_schedule(dev, &bp->napi);
} }
} }
...@@ -937,6 +931,8 @@ static int macb_open(struct net_device *dev) ...@@ -937,6 +931,8 @@ static int macb_open(struct net_device *dev)
return err; return err;
} }
napi_enable(&bp->napi);
macb_init_rings(bp); macb_init_rings(bp);
macb_init_hw(bp); macb_init_hw(bp);
...@@ -954,6 +950,7 @@ static int macb_close(struct net_device *dev) ...@@ -954,6 +950,7 @@ static int macb_close(struct net_device *dev)
unsigned long flags; unsigned long flags;
netif_stop_queue(dev); netif_stop_queue(dev);
napi_disable(&bp->napi);
if (bp->phy_dev) if (bp->phy_dev)
phy_stop(bp->phy_dev); phy_stop(bp->phy_dev);
...@@ -1146,8 +1143,7 @@ static int __devinit macb_probe(struct platform_device *pdev) ...@@ -1146,8 +1143,7 @@ static int __devinit macb_probe(struct platform_device *pdev)
dev->get_stats = macb_get_stats; dev->get_stats = macb_get_stats;
dev->set_multicast_list = macb_set_rx_mode; dev->set_multicast_list = macb_set_rx_mode;
dev->do_ioctl = macb_ioctl; dev->do_ioctl = macb_ioctl;
dev->poll = macb_poll; netif_napi_add(dev, &bp->napi, macb_poll, 64);
dev->weight = 64;
dev->ethtool_ops = &macb_ethtool_ops; dev->ethtool_ops = &macb_ethtool_ops;
dev->base_addr = regs->start; dev->base_addr = regs->start;
......
...@@ -374,6 +374,7 @@ struct macb { ...@@ -374,6 +374,7 @@ struct macb {
struct clk *pclk; struct clk *pclk;
struct clk *hclk; struct clk *hclk;
struct net_device *dev; struct net_device *dev;
struct napi_struct napi;
struct net_device_stats stats; struct net_device_stats stats;
struct macb_stats hw_stats; struct macb_stats hw_stats;
......
...@@ -66,7 +66,7 @@ static int mv643xx_eth_change_mtu(struct net_device *, int); ...@@ -66,7 +66,7 @@ static int mv643xx_eth_change_mtu(struct net_device *, int);
static struct net_device_stats *mv643xx_eth_get_stats(struct net_device *); static struct net_device_stats *mv643xx_eth_get_stats(struct net_device *);
static void eth_port_init_mac_tables(unsigned int eth_port_num); static void eth_port_init_mac_tables(unsigned int eth_port_num);
#ifdef MV643XX_NAPI #ifdef MV643XX_NAPI
static int mv643xx_poll(struct net_device *dev, int *budget); static int mv643xx_poll(struct napi_struct *napi, int budget);
#endif #endif
static int ethernet_phy_get(unsigned int eth_port_num); static int ethernet_phy_get(unsigned int eth_port_num);
static void ethernet_phy_set(unsigned int eth_port_num, int phy_addr); static void ethernet_phy_set(unsigned int eth_port_num, int phy_addr);
...@@ -562,7 +562,7 @@ static irqreturn_t mv643xx_eth_int_handler(int irq, void *dev_id) ...@@ -562,7 +562,7 @@ static irqreturn_t mv643xx_eth_int_handler(int irq, void *dev_id)
/* wait for previous write to complete */ /* wait for previous write to complete */
mv_read(MV643XX_ETH_INTERRUPT_MASK_REG(port_num)); mv_read(MV643XX_ETH_INTERRUPT_MASK_REG(port_num));
netif_rx_schedule(dev); netif_rx_schedule(dev, &mp->napi);
} }
#else #else
if (eth_int_cause & ETH_INT_CAUSE_RX) if (eth_int_cause & ETH_INT_CAUSE_RX)
...@@ -880,6 +880,10 @@ static int mv643xx_eth_open(struct net_device *dev) ...@@ -880,6 +880,10 @@ static int mv643xx_eth_open(struct net_device *dev)
mv643xx_eth_rx_refill_descs(dev); /* Fill RX ring with skb's */ mv643xx_eth_rx_refill_descs(dev); /* Fill RX ring with skb's */
#ifdef MV643XX_NAPI
napi_enable(&mp->napi);
#endif
eth_port_start(dev); eth_port_start(dev);
/* Interrupt Coalescing */ /* Interrupt Coalescing */
...@@ -982,7 +986,7 @@ static int mv643xx_eth_stop(struct net_device *dev) ...@@ -982,7 +986,7 @@ static int mv643xx_eth_stop(struct net_device *dev)
mv_read(MV643XX_ETH_INTERRUPT_MASK_REG(port_num)); mv_read(MV643XX_ETH_INTERRUPT_MASK_REG(port_num));
#ifdef MV643XX_NAPI #ifdef MV643XX_NAPI
netif_poll_disable(dev); napi_disable(&mp->napi);
#endif #endif
netif_carrier_off(dev); netif_carrier_off(dev);
netif_stop_queue(dev); netif_stop_queue(dev);
...@@ -992,10 +996,6 @@ static int mv643xx_eth_stop(struct net_device *dev) ...@@ -992,10 +996,6 @@ static int mv643xx_eth_stop(struct net_device *dev)
mv643xx_eth_free_tx_rings(dev); mv643xx_eth_free_tx_rings(dev);
mv643xx_eth_free_rx_rings(dev); mv643xx_eth_free_rx_rings(dev);
#ifdef MV643XX_NAPI
netif_poll_enable(dev);
#endif
free_irq(dev->irq, dev); free_irq(dev->irq, dev);
return 0; return 0;
...@@ -1007,11 +1007,12 @@ static int mv643xx_eth_stop(struct net_device *dev) ...@@ -1007,11 +1007,12 @@ static int mv643xx_eth_stop(struct net_device *dev)
* *
* This function is used in case of NAPI * This function is used in case of NAPI
*/ */
static int mv643xx_poll(struct net_device *dev, int *budget) static int mv643xx_poll(struct napi_struct *napi, int budget)
{ {
struct mv643xx_private *mp = netdev_priv(dev); struct mv643xx_private *mp = container_of(napi, struct mv643xx_private, napi);
int done = 1, orig_budget, work_done; struct net_device *dev = mp->dev;
unsigned int port_num = mp->port_num; unsigned int port_num = mp->port_num;
int work_done;
#ifdef MV643XX_TX_FAST_REFILL #ifdef MV643XX_TX_FAST_REFILL
if (++mp->tx_clean_threshold > 5) { if (++mp->tx_clean_threshold > 5) {
...@@ -1020,27 +1021,20 @@ static int mv643xx_poll(struct net_device *dev, int *budget) ...@@ -1020,27 +1021,20 @@ static int mv643xx_poll(struct net_device *dev, int *budget)
} }
#endif #endif
work_done = 0;
if ((mv_read(MV643XX_ETH_RX_CURRENT_QUEUE_DESC_PTR_0(port_num))) if ((mv_read(MV643XX_ETH_RX_CURRENT_QUEUE_DESC_PTR_0(port_num)))
!= (u32) mp->rx_used_desc_q) { != (u32) mp->rx_used_desc_q)
orig_budget = *budget; work_done = mv643xx_eth_receive_queue(dev, budget);
if (orig_budget > dev->quota)
orig_budget = dev->quota;
work_done = mv643xx_eth_receive_queue(dev, orig_budget);
*budget -= work_done;
dev->quota -= work_done;
if (work_done >= orig_budget)
done = 0;
}
if (done) { if (work_done < budget) {
netif_rx_complete(dev); netif_rx_complete(dev, napi);
mv_write(MV643XX_ETH_INTERRUPT_CAUSE_REG(port_num), 0); mv_write(MV643XX_ETH_INTERRUPT_CAUSE_REG(port_num), 0);
mv_write(MV643XX_ETH_INTERRUPT_CAUSE_EXTEND_REG(port_num), 0); mv_write(MV643XX_ETH_INTERRUPT_CAUSE_EXTEND_REG(port_num), 0);
mv_write(MV643XX_ETH_INTERRUPT_MASK_REG(port_num), mv_write(MV643XX_ETH_INTERRUPT_MASK_REG(port_num),
ETH_INT_UNMASK_ALL); ETH_INT_UNMASK_ALL);
} }
return done ? 0 : 1; return work_done;
} }
#endif #endif
...@@ -1333,6 +1327,10 @@ static int mv643xx_eth_probe(struct platform_device *pdev) ...@@ -1333,6 +1327,10 @@ static int mv643xx_eth_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, dev); platform_set_drvdata(pdev, dev);
mp = netdev_priv(dev); mp = netdev_priv(dev);
mp->dev = dev;
#ifdef MV643XX_NAPI
netif_napi_add(dev, &mp->napi, mv643xx_poll, 64);
#endif
res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
BUG_ON(!res); BUG_ON(!res);
...@@ -1347,10 +1345,6 @@ static int mv643xx_eth_probe(struct platform_device *pdev) ...@@ -1347,10 +1345,6 @@ static int mv643xx_eth_probe(struct platform_device *pdev)
/* No need to Tx Timeout */ /* No need to Tx Timeout */
dev->tx_timeout = mv643xx_eth_tx_timeout; dev->tx_timeout = mv643xx_eth_tx_timeout;
#ifdef MV643XX_NAPI
dev->poll = mv643xx_poll;
dev->weight = 64;
#endif
#ifdef CONFIG_NET_POLL_CONTROLLER #ifdef CONFIG_NET_POLL_CONTROLLER
dev->poll_controller = mv643xx_netpoll; dev->poll_controller = mv643xx_netpoll;
......
...@@ -320,6 +320,8 @@ struct mv643xx_private { ...@@ -320,6 +320,8 @@ struct mv643xx_private {
struct work_struct tx_timeout_task; struct work_struct tx_timeout_task;
struct net_device *dev;
struct napi_struct napi;
struct net_device_stats stats; struct net_device_stats stats;
struct mv643xx_mib_counters mib_counters; struct mv643xx_mib_counters mib_counters;
spinlock_t lock; spinlock_t lock;
......
...@@ -163,6 +163,7 @@ struct myri10ge_priv { ...@@ -163,6 +163,7 @@ struct myri10ge_priv {
int small_bytes; int small_bytes;
int big_bytes; int big_bytes;
struct net_device *dev; struct net_device *dev;
struct napi_struct napi;
struct net_device_stats stats; struct net_device_stats stats;
u8 __iomem *sram; u8 __iomem *sram;
int sram_size; int sram_size;
...@@ -1100,7 +1101,7 @@ static inline void myri10ge_tx_done(struct myri10ge_priv *mgp, int mcp_index) ...@@ -1100,7 +1101,7 @@ static inline void myri10ge_tx_done(struct myri10ge_priv *mgp, int mcp_index)
} }
} }
static inline void myri10ge_clean_rx_done(struct myri10ge_priv *mgp, int *limit) static inline int myri10ge_clean_rx_done(struct myri10ge_priv *mgp, int budget)
{ {
struct myri10ge_rx_done *rx_done = &mgp->rx_done; struct myri10ge_rx_done *rx_done = &mgp->rx_done;
unsigned long rx_bytes = 0; unsigned long rx_bytes = 0;
...@@ -1109,10 +1110,11 @@ static inline void myri10ge_clean_rx_done(struct myri10ge_priv *mgp, int *limit) ...@@ -1109,10 +1110,11 @@ static inline void myri10ge_clean_rx_done(struct myri10ge_priv *mgp, int *limit)
int idx = rx_done->idx; int idx = rx_done->idx;
int cnt = rx_done->cnt; int cnt = rx_done->cnt;
int work_done = 0;
u16 length; u16 length;
__wsum checksum; __wsum checksum;
while (rx_done->entry[idx].length != 0 && *limit != 0) { while (rx_done->entry[idx].length != 0 && work_done++ < budget) {
length = ntohs(rx_done->entry[idx].length); length = ntohs(rx_done->entry[idx].length);
rx_done->entry[idx].length = 0; rx_done->entry[idx].length = 0;
checksum = csum_unfold(rx_done->entry[idx].checksum); checksum = csum_unfold(rx_done->entry[idx].checksum);
...@@ -1128,10 +1130,6 @@ static inline void myri10ge_clean_rx_done(struct myri10ge_priv *mgp, int *limit) ...@@ -1128,10 +1130,6 @@ static inline void myri10ge_clean_rx_done(struct myri10ge_priv *mgp, int *limit)
rx_bytes += rx_ok * (unsigned long)length; rx_bytes += rx_ok * (unsigned long)length;
cnt++; cnt++;
idx = cnt & (myri10ge_max_intr_slots - 1); idx = cnt & (myri10ge_max_intr_slots - 1);
/* limit potential for livelock by only handling a
* limited number of frames. */
(*limit)--;
} }
rx_done->idx = idx; rx_done->idx = idx;
rx_done->cnt = cnt; rx_done->cnt = cnt;
...@@ -1145,6 +1143,7 @@ static inline void myri10ge_clean_rx_done(struct myri10ge_priv *mgp, int *limit) ...@@ -1145,6 +1143,7 @@ static inline void myri10ge_clean_rx_done(struct myri10ge_priv *mgp, int *limit)
if (mgp->rx_big.fill_cnt - mgp->rx_big.cnt < myri10ge_fill_thresh) if (mgp->rx_big.fill_cnt - mgp->rx_big.cnt < myri10ge_fill_thresh)
myri10ge_alloc_rx_pages(mgp, &mgp->rx_big, mgp->big_bytes, 0); myri10ge_alloc_rx_pages(mgp, &mgp->rx_big, mgp->big_bytes, 0);
return work_done;
} }
static inline void myri10ge_check_statblock(struct myri10ge_priv *mgp) static inline void myri10ge_check_statblock(struct myri10ge_priv *mgp)
...@@ -1189,26 +1188,21 @@ static inline void myri10ge_check_statblock(struct myri10ge_priv *mgp) ...@@ -1189,26 +1188,21 @@ static inline void myri10ge_check_statblock(struct myri10ge_priv *mgp)
} }
} }
static int myri10ge_poll(struct net_device *netdev, int *budget) static int myri10ge_poll(struct napi_struct *napi, int budget)
{ {
struct myri10ge_priv *mgp = netdev_priv(netdev); struct myri10ge_priv *mgp = container_of(napi, struct myri10ge_priv, napi);
struct net_device *netdev = mgp->dev;
struct myri10ge_rx_done *rx_done = &mgp->rx_done; struct myri10ge_rx_done *rx_done = &mgp->rx_done;
int limit, orig_limit, work_done; int work_done;
/* process as many rx events as NAPI will allow */ /* process as many rx events as NAPI will allow */
limit = min(*budget, netdev->quota); work_done = myri10ge_clean_rx_done(mgp, budget);
orig_limit = limit;
myri10ge_clean_rx_done(mgp, &limit);
work_done = orig_limit - limit;
*budget -= work_done;
netdev->quota -= work_done;
if (rx_done->entry[rx_done->idx].length == 0 || !netif_running(netdev)) { if (rx_done->entry[rx_done->idx].length == 0 || !netif_running(netdev)) {
netif_rx_complete(netdev); netif_rx_complete(netdev, napi);
put_be32(htonl(3), mgp->irq_claim); put_be32(htonl(3), mgp->irq_claim);
return 0;
} }
return 1; return work_done;
} }
static irqreturn_t myri10ge_intr(int irq, void *arg) static irqreturn_t myri10ge_intr(int irq, void *arg)
...@@ -1226,7 +1220,7 @@ static irqreturn_t myri10ge_intr(int irq, void *arg) ...@@ -1226,7 +1220,7 @@ static irqreturn_t myri10ge_intr(int irq, void *arg)
/* low bit indicates receives are present, so schedule /* low bit indicates receives are present, so schedule
* napi poll handler */ * napi poll handler */
if (stats->valid & 1) if (stats->valid & 1)
netif_rx_schedule(mgp->dev); netif_rx_schedule(mgp->dev, &mgp->napi);
if (!mgp->msi_enabled) { if (!mgp->msi_enabled) {
put_be32(0, mgp->irq_deassert); put_be32(0, mgp->irq_deassert);
...@@ -1853,7 +1847,7 @@ static int myri10ge_open(struct net_device *dev) ...@@ -1853,7 +1847,7 @@ static int myri10ge_open(struct net_device *dev)
mgp->link_state = htonl(~0U); mgp->link_state = htonl(~0U);
mgp->rdma_tags_available = 15; mgp->rdma_tags_available = 15;
netif_poll_enable(mgp->dev); /* must happen prior to any irq */ napi_enable(&mgp->napi); /* must happen prior to any irq */
status = myri10ge_send_cmd(mgp, MXGEFW_CMD_ETHERNET_UP, &cmd, 0); status = myri10ge_send_cmd(mgp, MXGEFW_CMD_ETHERNET_UP, &cmd, 0);
if (status) { if (status) {
...@@ -1897,7 +1891,7 @@ static int myri10ge_close(struct net_device *dev) ...@@ -1897,7 +1891,7 @@ static int myri10ge_close(struct net_device *dev)
del_timer_sync(&mgp->watchdog_timer); del_timer_sync(&mgp->watchdog_timer);
mgp->running = MYRI10GE_ETH_STOPPING; mgp->running = MYRI10GE_ETH_STOPPING;
netif_poll_disable(mgp->dev); napi_disable(&mgp->napi);
netif_carrier_off(dev); netif_carrier_off(dev);
netif_stop_queue(dev); netif_stop_queue(dev);
old_down_cnt = mgp->down_cnt; old_down_cnt = mgp->down_cnt;
...@@ -2857,6 +2851,8 @@ static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -2857,6 +2851,8 @@ static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
mgp = netdev_priv(netdev); mgp = netdev_priv(netdev);
memset(mgp, 0, sizeof(*mgp)); memset(mgp, 0, sizeof(*mgp));
mgp->dev = netdev; mgp->dev = netdev;
netif_napi_add(netdev, &mgp->napi,
myri10ge_poll, myri10ge_napi_weight);
mgp->pdev = pdev; mgp->pdev = pdev;
mgp->csum_flag = MXGEFW_FLAGS_CKSUM; mgp->csum_flag = MXGEFW_FLAGS_CKSUM;
mgp->pause = myri10ge_flow_control; mgp->pause = myri10ge_flow_control;
...@@ -2981,8 +2977,6 @@ static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -2981,8 +2977,6 @@ static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
netdev->features = NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_TSO; netdev->features = NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_TSO;
if (dac_enabled) if (dac_enabled)
netdev->features |= NETIF_F_HIGHDMA; netdev->features |= NETIF_F_HIGHDMA;
netdev->poll = myri10ge_poll;
netdev->weight = myri10ge_napi_weight;
/* make sure we can get an irq, and that MSI can be /* make sure we can get an irq, and that MSI can be
* setup (if available). Also ensure netdev->irq * setup (if available). Also ensure netdev->irq
......
...@@ -560,6 +560,8 @@ struct netdev_private { ...@@ -560,6 +560,8 @@ struct netdev_private {
/* address of a sent-in-place packet/buffer, for later free() */ /* address of a sent-in-place packet/buffer, for later free() */
struct sk_buff *tx_skbuff[TX_RING_SIZE]; struct sk_buff *tx_skbuff[TX_RING_SIZE];
dma_addr_t tx_dma[TX_RING_SIZE]; dma_addr_t tx_dma[TX_RING_SIZE];
struct net_device *dev;
struct napi_struct napi;
struct net_device_stats stats; struct net_device_stats stats;
/* Media monitoring timer */ /* Media monitoring timer */
struct timer_list timer; struct timer_list timer;
...@@ -636,7 +638,7 @@ static void init_registers(struct net_device *dev); ...@@ -636,7 +638,7 @@ static void init_registers(struct net_device *dev);
static int start_tx(struct sk_buff *skb, struct net_device *dev); static int start_tx(struct sk_buff *skb, struct net_device *dev);
static irqreturn_t intr_handler(int irq, void *dev_instance); static irqreturn_t intr_handler(int irq, void *dev_instance);
static void netdev_error(struct net_device *dev, int intr_status); static void netdev_error(struct net_device *dev, int intr_status);
static int natsemi_poll(struct net_device *dev, int *budget); static int natsemi_poll(struct napi_struct *napi, int budget);
static void netdev_rx(struct net_device *dev, int *work_done, int work_to_do); static void netdev_rx(struct net_device *dev, int *work_done, int work_to_do);
static void netdev_tx_done(struct net_device *dev); static void netdev_tx_done(struct net_device *dev);
static int natsemi_change_mtu(struct net_device *dev, int new_mtu); static int natsemi_change_mtu(struct net_device *dev, int new_mtu);
...@@ -861,6 +863,7 @@ static int __devinit natsemi_probe1 (struct pci_dev *pdev, ...@@ -861,6 +863,7 @@ static int __devinit natsemi_probe1 (struct pci_dev *pdev,
dev->irq = irq; dev->irq = irq;
np = netdev_priv(dev); np = netdev_priv(dev);
netif_napi_add(dev, &np->napi, natsemi_poll, 64);
np->pci_dev = pdev; np->pci_dev = pdev;
pci_set_drvdata(pdev, dev); pci_set_drvdata(pdev, dev);
...@@ -931,8 +934,6 @@ static int __devinit natsemi_probe1 (struct pci_dev *pdev, ...@@ -931,8 +934,6 @@ static int __devinit natsemi_probe1 (struct pci_dev *pdev,
dev->do_ioctl = &netdev_ioctl; dev->do_ioctl = &netdev_ioctl;
dev->tx_timeout = &tx_timeout; dev->tx_timeout = &tx_timeout;
dev->watchdog_timeo = TX_TIMEOUT; dev->watchdog_timeo = TX_TIMEOUT;
dev->poll = natsemi_poll;
dev->weight = 64;
#ifdef CONFIG_NET_POLL_CONTROLLER #ifdef CONFIG_NET_POLL_CONTROLLER
dev->poll_controller = &natsemi_poll_controller; dev->poll_controller = &natsemi_poll_controller;
...@@ -1554,6 +1555,8 @@ static int netdev_open(struct net_device *dev) ...@@ -1554,6 +1555,8 @@ static int netdev_open(struct net_device *dev)
free_irq(dev->irq, dev); free_irq(dev->irq, dev);
return i; return i;
} }
napi_enable(&np->napi);
init_ring(dev); init_ring(dev);
spin_lock_irq(&np->lock); spin_lock_irq(&np->lock);
init_registers(dev); init_registers(dev);
...@@ -2200,10 +2203,10 @@ static irqreturn_t intr_handler(int irq, void *dev_instance) ...@@ -2200,10 +2203,10 @@ static irqreturn_t intr_handler(int irq, void *dev_instance)
prefetch(&np->rx_skbuff[np->cur_rx % RX_RING_SIZE]); prefetch(&np->rx_skbuff[np->cur_rx % RX_RING_SIZE]);
if (netif_rx_schedule_prep(dev)) { if (netif_rx_schedule_prep(dev, &np->napi)) {
/* Disable interrupts and register for poll */ /* Disable interrupts and register for poll */
natsemi_irq_disable(dev); natsemi_irq_disable(dev);
__netif_rx_schedule(dev); __netif_rx_schedule(dev, &np->napi);
} else } else
printk(KERN_WARNING printk(KERN_WARNING
"%s: Ignoring interrupt, status %#08x, mask %#08x.\n", "%s: Ignoring interrupt, status %#08x, mask %#08x.\n",
...@@ -2216,12 +2219,11 @@ static irqreturn_t intr_handler(int irq, void *dev_instance) ...@@ -2216,12 +2219,11 @@ static irqreturn_t intr_handler(int irq, void *dev_instance)
/* This is the NAPI poll routine. As well as the standard RX handling /* This is the NAPI poll routine. As well as the standard RX handling
* it also handles all other interrupts that the chip might raise. * it also handles all other interrupts that the chip might raise.
*/ */
static int natsemi_poll(struct net_device *dev, int *budget) static int natsemi_poll(struct napi_struct *napi, int budget)
{ {
struct netdev_private *np = netdev_priv(dev); struct netdev_private *np = container_of(napi, struct netdev_private, napi);
struct net_device *dev = np->dev;
void __iomem * ioaddr = ns_ioaddr(dev); void __iomem * ioaddr = ns_ioaddr(dev);
int work_to_do = min(*budget, dev->quota);
int work_done = 0; int work_done = 0;
do { do {
...@@ -2236,7 +2238,7 @@ static int natsemi_poll(struct net_device *dev, int *budget) ...@@ -2236,7 +2238,7 @@ static int natsemi_poll(struct net_device *dev, int *budget)
if (np->intr_status & if (np->intr_status &
(IntrRxDone | IntrRxIntr | RxStatusFIFOOver | (IntrRxDone | IntrRxIntr | RxStatusFIFOOver |
IntrRxErr | IntrRxOverrun)) { IntrRxErr | IntrRxOverrun)) {
netdev_rx(dev, &work_done, work_to_do); netdev_rx(dev, &work_done, budget);
} }
if (np->intr_status & if (np->intr_status &
...@@ -2250,16 +2252,13 @@ static int natsemi_poll(struct net_device *dev, int *budget) ...@@ -2250,16 +2252,13 @@ static int natsemi_poll(struct net_device *dev, int *budget)
if (np->intr_status & IntrAbnormalSummary) if (np->intr_status & IntrAbnormalSummary)
netdev_error(dev, np->intr_status); netdev_error(dev, np->intr_status);
*budget -= work_done; if (work_done >= budget)
dev->quota -= work_done; return work_done;
if (work_done >= work_to_do)
return 1;
np->intr_status = readl(ioaddr + IntrStatus); np->intr_status = readl(ioaddr + IntrStatus);
} while (np->intr_status); } while (np->intr_status);
netif_rx_complete(dev); netif_rx_complete(dev, napi);
/* Reenable interrupts providing nothing is trying to shut /* Reenable interrupts providing nothing is trying to shut
* the chip down. */ * the chip down. */
...@@ -2268,7 +2267,7 @@ static int natsemi_poll(struct net_device *dev, int *budget) ...@@ -2268,7 +2267,7 @@ static int natsemi_poll(struct net_device *dev, int *budget)
natsemi_irq_enable(dev); natsemi_irq_enable(dev);
spin_unlock(&np->lock); spin_unlock(&np->lock);
return 0; return work_done;
} }
/* This routine is logically part of the interrupt handler, but separated /* This routine is logically part of the interrupt handler, but separated
...@@ -3158,6 +3157,8 @@ static int netdev_close(struct net_device *dev) ...@@ -3158,6 +3157,8 @@ static int netdev_close(struct net_device *dev)
dev->name, np->cur_tx, np->dirty_tx, dev->name, np->cur_tx, np->dirty_tx,
np->cur_rx, np->dirty_rx); np->cur_rx, np->dirty_rx);
napi_disable(&np->napi);
/* /*
* FIXME: what if someone tries to close a device * FIXME: what if someone tries to close a device
* that is suspended? * that is suspended?
...@@ -3253,7 +3254,7 @@ static void __devexit natsemi_remove1 (struct pci_dev *pdev) ...@@ -3253,7 +3254,7 @@ static void __devexit natsemi_remove1 (struct pci_dev *pdev)
* disable_irq() to enforce synchronization. * disable_irq() to enforce synchronization.
* * natsemi_poll: checks before reenabling interrupts. suspend * * natsemi_poll: checks before reenabling interrupts. suspend
* sets hands_off, disables interrupts and then waits with * sets hands_off, disables interrupts and then waits with
* netif_poll_disable(). * napi_disable().
* *
* Interrupts must be disabled, otherwise hands_off can cause irq storms. * Interrupts must be disabled, otherwise hands_off can cause irq storms.
*/ */
...@@ -3279,7 +3280,7 @@ static int natsemi_suspend (struct pci_dev *pdev, pm_message_t state) ...@@ -3279,7 +3280,7 @@ static int natsemi_suspend (struct pci_dev *pdev, pm_message_t state)
spin_unlock_irq(&np->lock); spin_unlock_irq(&np->lock);
enable_irq(dev->irq); enable_irq(dev->irq);
netif_poll_disable(dev); napi_disable(&np->napi);
/* Update the error counts. */ /* Update the error counts. */
__get_stats(dev); __get_stats(dev);
...@@ -3320,6 +3321,8 @@ static int natsemi_resume (struct pci_dev *pdev) ...@@ -3320,6 +3321,8 @@ static int natsemi_resume (struct pci_dev *pdev)
pci_enable_device(pdev); pci_enable_device(pdev);
/* pci_power_on(pdev); */ /* pci_power_on(pdev); */
napi_enable(&np->napi);
natsemi_reset(dev); natsemi_reset(dev);
init_ring(dev); init_ring(dev);
disable_irq(dev->irq); disable_irq(dev->irq);
...@@ -3333,7 +3336,6 @@ static int natsemi_resume (struct pci_dev *pdev) ...@@ -3333,7 +3336,6 @@ static int natsemi_resume (struct pci_dev *pdev)
mod_timer(&np->timer, jiffies + 1*HZ); mod_timer(&np->timer, jiffies + 1*HZ);
} }
netif_device_attach(dev); netif_device_attach(dev);
netif_poll_enable(dev);
out: out:
rtnl_unlock(); rtnl_unlock();
return 0; return 0;
......
...@@ -880,6 +880,7 @@ struct netxen_adapter { ...@@ -880,6 +880,7 @@ struct netxen_adapter {
struct netxen_adapter *master; struct netxen_adapter *master;
struct net_device *netdev; struct net_device *netdev;
struct pci_dev *pdev; struct pci_dev *pdev;
struct napi_struct napi;
struct net_device_stats net_stats; struct net_device_stats net_stats;
unsigned char mac_addr[ETH_ALEN]; unsigned char mac_addr[ETH_ALEN];
int mtu; int mtu;
......
...@@ -68,7 +68,7 @@ static void netxen_tx_timeout(struct net_device *netdev); ...@@ -68,7 +68,7 @@ static void netxen_tx_timeout(struct net_device *netdev);
static void netxen_tx_timeout_task(struct work_struct *work); static void netxen_tx_timeout_task(struct work_struct *work);
static void netxen_watchdog(unsigned long); static void netxen_watchdog(unsigned long);
static int netxen_handle_int(struct netxen_adapter *, struct net_device *); static int netxen_handle_int(struct netxen_adapter *, struct net_device *);
static int netxen_nic_poll(struct net_device *dev, int *budget); static int netxen_nic_poll(struct napi_struct *napi, int budget);
#ifdef CONFIG_NET_POLL_CONTROLLER #ifdef CONFIG_NET_POLL_CONTROLLER
static void netxen_nic_poll_controller(struct net_device *netdev); static void netxen_nic_poll_controller(struct net_device *netdev);
#endif #endif
...@@ -402,6 +402,9 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -402,6 +402,9 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
adapter->netdev = netdev; adapter->netdev = netdev;
adapter->pdev = pdev; adapter->pdev = pdev;
netif_napi_add(netdev, &adapter->napi,
netxen_nic_poll, NETXEN_NETDEV_WEIGHT);
/* this will be read from FW later */ /* this will be read from FW later */
adapter->intr_scheme = -1; adapter->intr_scheme = -1;
...@@ -422,8 +425,6 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -422,8 +425,6 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
netxen_nic_change_mtu(netdev, netdev->mtu); netxen_nic_change_mtu(netdev, netdev->mtu);
SET_ETHTOOL_OPS(netdev, &netxen_nic_ethtool_ops); SET_ETHTOOL_OPS(netdev, &netxen_nic_ethtool_ops);
netdev->poll = netxen_nic_poll;
netdev->weight = NETXEN_NETDEV_WEIGHT;
#ifdef CONFIG_NET_POLL_CONTROLLER #ifdef CONFIG_NET_POLL_CONTROLLER
netdev->poll_controller = netxen_nic_poll_controller; netdev->poll_controller = netxen_nic_poll_controller;
#endif #endif
...@@ -885,6 +886,8 @@ static int netxen_nic_open(struct net_device *netdev) ...@@ -885,6 +886,8 @@ static int netxen_nic_open(struct net_device *netdev)
if (!adapter->driver_mismatch) if (!adapter->driver_mismatch)
mod_timer(&adapter->watchdog_timer, jiffies); mod_timer(&adapter->watchdog_timer, jiffies);
napi_enable(&adapter->napi);
netxen_nic_enable_int(adapter); netxen_nic_enable_int(adapter);
/* Done here again so that even if phantom sw overwrote it, /* Done here again so that even if phantom sw overwrote it,
...@@ -894,6 +897,7 @@ static int netxen_nic_open(struct net_device *netdev) ...@@ -894,6 +897,7 @@ static int netxen_nic_open(struct net_device *netdev)
del_timer_sync(&adapter->watchdog_timer); del_timer_sync(&adapter->watchdog_timer);
printk(KERN_ERR "%s: Failed to initialize port %d\n", printk(KERN_ERR "%s: Failed to initialize port %d\n",
netxen_nic_driver_name, adapter->portnum); netxen_nic_driver_name, adapter->portnum);
napi_disable(&adapter->napi);
return -EIO; return -EIO;
} }
if (adapter->macaddr_set) if (adapter->macaddr_set)
...@@ -923,6 +927,7 @@ static int netxen_nic_close(struct net_device *netdev) ...@@ -923,6 +927,7 @@ static int netxen_nic_close(struct net_device *netdev)
netif_carrier_off(netdev); netif_carrier_off(netdev);
netif_stop_queue(netdev); netif_stop_queue(netdev);
napi_disable(&adapter->napi);
netxen_nic_disable_int(adapter); netxen_nic_disable_int(adapter);
...@@ -1243,11 +1248,11 @@ netxen_handle_int(struct netxen_adapter *adapter, struct net_device *netdev) ...@@ -1243,11 +1248,11 @@ netxen_handle_int(struct netxen_adapter *adapter, struct net_device *netdev)
netxen_nic_disable_int(adapter); netxen_nic_disable_int(adapter);
if (netxen_nic_rx_has_work(adapter) || netxen_nic_tx_has_work(adapter)) { if (netxen_nic_rx_has_work(adapter) || netxen_nic_tx_has_work(adapter)) {
if (netif_rx_schedule_prep(netdev)) { if (netif_rx_schedule_prep(netdev, &adapter->napi)) {
/* /*
* Interrupts are already disabled. * Interrupts are already disabled.
*/ */
__netif_rx_schedule(netdev); __netif_rx_schedule(netdev, &adapter->napi);
} else { } else {
static unsigned int intcount = 0; static unsigned int intcount = 0;
if ((++intcount & 0xfff) == 0xfff) if ((++intcount & 0xfff) == 0xfff)
...@@ -1305,14 +1310,13 @@ irqreturn_t netxen_intr(int irq, void *data) ...@@ -1305,14 +1310,13 @@ irqreturn_t netxen_intr(int irq, void *data)
return IRQ_HANDLED; return IRQ_HANDLED;
} }
static int netxen_nic_poll(struct net_device *netdev, int *budget) static int netxen_nic_poll(struct napi_struct *napi, int budget)
{ {
struct netxen_adapter *adapter = netdev_priv(netdev); struct netxen_adapter *adapter = container_of(napi, struct netxen_adapter, napi);
int work_to_do = min(*budget, netdev->quota); struct net_device *netdev = adapter->netdev;
int done = 1; int done = 1;
int ctx; int ctx;
int this_work_done; int work_done;
int work_done = 0;
DPRINTK(INFO, "polling for %d descriptors\n", *budget); DPRINTK(INFO, "polling for %d descriptors\n", *budget);
...@@ -1330,16 +1334,11 @@ static int netxen_nic_poll(struct net_device *netdev, int *budget) ...@@ -1330,16 +1334,11 @@ static int netxen_nic_poll(struct net_device *netdev, int *budget)
* packets are on one context, it gets only half of the quota, * packets are on one context, it gets only half of the quota,
* and ends up not processing it. * and ends up not processing it.
*/ */
this_work_done = netxen_process_rcv_ring(adapter, ctx, work_done += netxen_process_rcv_ring(adapter, ctx,
work_to_do / budget / MAX_RCV_CTX);
MAX_RCV_CTX);
work_done += this_work_done;
} }
netdev->quota -= work_done; if (work_done >= budget && netxen_nic_rx_has_work(adapter) != 0)
*budget -= work_done;
if (work_done >= work_to_do && netxen_nic_rx_has_work(adapter) != 0)
done = 0; done = 0;
if (netxen_process_cmd_ring((unsigned long)adapter) == 0) if (netxen_process_cmd_ring((unsigned long)adapter) == 0)
...@@ -1348,11 +1347,11 @@ static int netxen_nic_poll(struct net_device *netdev, int *budget) ...@@ -1348,11 +1347,11 @@ static int netxen_nic_poll(struct net_device *netdev, int *budget)
DPRINTK(INFO, "new work_done: %d work_to_do: %d\n", DPRINTK(INFO, "new work_done: %d work_to_do: %d\n",
work_done, work_to_do); work_done, work_to_do);
if (done) { if (done) {
netif_rx_complete(netdev); netif_rx_complete(netdev, napi);
netxen_nic_enable_int(adapter); netxen_nic_enable_int(adapter);
} }
return !done; return work_done;
} }
#ifdef CONFIG_NET_POLL_CONTROLLER #ifdef CONFIG_NET_POLL_CONTROLLER
......
...@@ -584,7 +584,7 @@ static irqreturn_t pasemi_mac_rx_intr(int irq, void *data) ...@@ -584,7 +584,7 @@ static irqreturn_t pasemi_mac_rx_intr(int irq, void *data)
if (*mac->rx_status & PAS_STATUS_TIMER) if (*mac->rx_status & PAS_STATUS_TIMER)
reg |= PAS_IOB_DMA_RXCH_RESET_TINTC; reg |= PAS_IOB_DMA_RXCH_RESET_TINTC;
netif_rx_schedule(dev); netif_rx_schedule(dev, &mac->napi);
pci_write_config_dword(mac->iob_pdev, pci_write_config_dword(mac->iob_pdev,
PAS_IOB_DMA_RXCH_RESET(mac->dma_rxch), reg); PAS_IOB_DMA_RXCH_RESET(mac->dma_rxch), reg);
...@@ -808,7 +808,7 @@ static int pasemi_mac_open(struct net_device *dev) ...@@ -808,7 +808,7 @@ static int pasemi_mac_open(struct net_device *dev)
dev_warn(&mac->pdev->dev, "phy init failed: %d\n", ret); dev_warn(&mac->pdev->dev, "phy init failed: %d\n", ret);
netif_start_queue(dev); netif_start_queue(dev);
netif_poll_enable(dev); napi_enable(&mac->napi);
/* Interrupts are a bit different for our DMA controller: While /* Interrupts are a bit different for our DMA controller: While
* it's got one a regular PCI device header, the interrupt there * it's got one a regular PCI device header, the interrupt there
...@@ -845,7 +845,7 @@ static int pasemi_mac_open(struct net_device *dev) ...@@ -845,7 +845,7 @@ static int pasemi_mac_open(struct net_device *dev)
out_rx_int: out_rx_int:
free_irq(mac->tx_irq, dev); free_irq(mac->tx_irq, dev);
out_tx_int: out_tx_int:
netif_poll_disable(dev); napi_disable(&mac->napi);
netif_stop_queue(dev); netif_stop_queue(dev);
pasemi_mac_free_tx_resources(dev); pasemi_mac_free_tx_resources(dev);
out_tx_resources: out_tx_resources:
...@@ -869,6 +869,7 @@ static int pasemi_mac_close(struct net_device *dev) ...@@ -869,6 +869,7 @@ static int pasemi_mac_close(struct net_device *dev)
} }
netif_stop_queue(dev); netif_stop_queue(dev);
napi_disable(&mac->napi);
/* Clean out any pending buffers */ /* Clean out any pending buffers */
pasemi_mac_clean_tx(mac); pasemi_mac_clean_tx(mac);
...@@ -1047,26 +1048,20 @@ static void pasemi_mac_set_rx_mode(struct net_device *dev) ...@@ -1047,26 +1048,20 @@ static void pasemi_mac_set_rx_mode(struct net_device *dev)
} }
static int pasemi_mac_poll(struct net_device *dev, int *budget) static int pasemi_mac_poll(struct napi_struct *napi, int budget)
{ {
int pkts, limit = min(*budget, dev->quota); struct pasemi_mac *mac = container_of(napi, struct pasemi_mac, napi);
struct pasemi_mac *mac = netdev_priv(dev); struct net_device *dev = mac->netdev;
int pkts;
pkts = pasemi_mac_clean_rx(mac, limit);
dev->quota -= pkts; pkts = pasemi_mac_clean_rx(mac, budget);
*budget -= pkts; if (pkts < budget) {
if (pkts < limit) {
/* all done, no more packets present */ /* all done, no more packets present */
netif_rx_complete(dev); netif_rx_complete(dev, napi);
pasemi_mac_restart_rx_intr(mac); pasemi_mac_restart_rx_intr(mac);
return 0;
} else {
/* used up our quantum, so reschedule */
return 1;
} }
return pkts;
} }
static int __devinit static int __devinit
...@@ -1099,6 +1094,10 @@ pasemi_mac_probe(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -1099,6 +1094,10 @@ pasemi_mac_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
mac->netdev = dev; mac->netdev = dev;
mac->dma_pdev = pci_get_device(PCI_VENDOR_ID_PASEMI, 0xa007, NULL); mac->dma_pdev = pci_get_device(PCI_VENDOR_ID_PASEMI, 0xa007, NULL);
netif_napi_add(dev, &mac->napi, pasemi_mac_poll, 64);
dev->features = NETIF_F_HW_CSUM;
if (!mac->dma_pdev) { if (!mac->dma_pdev) {
dev_err(&pdev->dev, "Can't find DMA Controller\n"); dev_err(&pdev->dev, "Can't find DMA Controller\n");
err = -ENODEV; err = -ENODEV;
...@@ -1150,9 +1149,6 @@ pasemi_mac_probe(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -1150,9 +1149,6 @@ pasemi_mac_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
dev->hard_start_xmit = pasemi_mac_start_tx; dev->hard_start_xmit = pasemi_mac_start_tx;
dev->get_stats = pasemi_mac_get_stats; dev->get_stats = pasemi_mac_get_stats;
dev->set_multicast_list = pasemi_mac_set_rx_mode; dev->set_multicast_list = pasemi_mac_set_rx_mode;
dev->weight = 64;
dev->poll = pasemi_mac_poll;
dev->features = NETIF_F_HW_CSUM;
/* The dma status structure is located in the I/O bridge, and /* The dma status structure is located in the I/O bridge, and
* is cache coherent. * is cache coherent.
......
...@@ -56,6 +56,7 @@ struct pasemi_mac { ...@@ -56,6 +56,7 @@ struct pasemi_mac {
struct pci_dev *dma_pdev; struct pci_dev *dma_pdev;
struct pci_dev *iob_pdev; struct pci_dev *iob_pdev;
struct phy_device *phydev; struct phy_device *phydev;
struct napi_struct napi;
struct net_device_stats stats; struct net_device_stats stats;
/* Pointer to the cacheable per-channel status registers */ /* Pointer to the cacheable per-channel status registers */
......
此差异已折叠。
...@@ -556,6 +556,7 @@ static int gelic_net_stop(struct net_device *netdev) ...@@ -556,6 +556,7 @@ static int gelic_net_stop(struct net_device *netdev)
{ {
struct gelic_net_card *card = netdev_priv(netdev); struct gelic_net_card *card = netdev_priv(netdev);
napi_disable(&card->napi);
netif_stop_queue(netdev); netif_stop_queue(netdev);
/* turn off DMA, force end */ /* turn off DMA, force end */
...@@ -987,32 +988,24 @@ static int gelic_net_decode_one_descr(struct gelic_net_card *card) ...@@ -987,32 +988,24 @@ static int gelic_net_decode_one_descr(struct gelic_net_card *card)
* if the quota is exceeded, but the driver has still packets. * if the quota is exceeded, but the driver has still packets.
* *
*/ */
static int gelic_net_poll(struct net_device *netdev, int *budget) static int gelic_net_poll(struct napi_struct *napi, int budget)
{ {
struct gelic_net_card *card = netdev_priv(netdev); struct gelic_net_card *card = container_of(napi, struct gelic_net_card, napi);
int packets_to_do, packets_done = 0; struct net_device *netdev = card->netdev;
int no_more_packets = 0; int packets_done = 0;
packets_to_do = min(*budget, netdev->quota);
while (packets_to_do) { while (packets_done < budget) {
if (gelic_net_decode_one_descr(card)) { if (!gelic_net_decode_one_descr(card))
packets_done++;
packets_to_do--;
} else {
/* no more packets for the stack */
no_more_packets = 1;
break; break;
}
packets_done++;
} }
netdev->quota -= packets_done;
*budget -= packets_done; if (packets_done < budget) {
if (no_more_packets) { netif_rx_complete(netdev, napi);
netif_rx_complete(netdev);
gelic_net_rx_irq_on(card); gelic_net_rx_irq_on(card);
return 0; }
} else return packets_done;
return 1;
} }
/** /**
* gelic_net_change_mtu - changes the MTU of an interface * gelic_net_change_mtu - changes the MTU of an interface
...@@ -1055,7 +1048,7 @@ static irqreturn_t gelic_net_interrupt(int irq, void *ptr) ...@@ -1055,7 +1048,7 @@ static irqreturn_t gelic_net_interrupt(int irq, void *ptr)
if (status & GELIC_NET_RXINT) { if (status & GELIC_NET_RXINT) {
gelic_net_rx_irq_off(card); gelic_net_rx_irq_off(card);
netif_rx_schedule(netdev); netif_rx_schedule(netdev, &card->napi);
} }
if (status & GELIC_NET_TXINT) { if (status & GELIC_NET_TXINT) {
...@@ -1159,6 +1152,8 @@ static int gelic_net_open(struct net_device *netdev) ...@@ -1159,6 +1152,8 @@ static int gelic_net_open(struct net_device *netdev)
if (gelic_net_alloc_rx_skbs(card)) if (gelic_net_alloc_rx_skbs(card))
goto alloc_skbs_failed; goto alloc_skbs_failed;
napi_enable(&card->napi);
card->tx_dma_progress = 0; card->tx_dma_progress = 0;
card->ghiintmask = GELIC_NET_RXINT | GELIC_NET_TXINT; card->ghiintmask = GELIC_NET_RXINT | GELIC_NET_TXINT;
...@@ -1360,9 +1355,6 @@ static void gelic_net_setup_netdev_ops(struct net_device *netdev) ...@@ -1360,9 +1355,6 @@ static void gelic_net_setup_netdev_ops(struct net_device *netdev)
/* tx watchdog */ /* tx watchdog */
netdev->tx_timeout = &gelic_net_tx_timeout; netdev->tx_timeout = &gelic_net_tx_timeout;
netdev->watchdog_timeo = GELIC_NET_WATCHDOG_TIMEOUT; netdev->watchdog_timeo = GELIC_NET_WATCHDOG_TIMEOUT;
/* NAPI */
netdev->poll = &gelic_net_poll;
netdev->weight = GELIC_NET_NAPI_WEIGHT;
netdev->ethtool_ops = &gelic_net_ethtool_ops; netdev->ethtool_ops = &gelic_net_ethtool_ops;
} }
...@@ -1390,6 +1382,9 @@ static int gelic_net_setup_netdev(struct gelic_net_card *card) ...@@ -1390,6 +1382,9 @@ static int gelic_net_setup_netdev(struct gelic_net_card *card)
gelic_net_setup_netdev_ops(netdev); gelic_net_setup_netdev_ops(netdev);
netif_napi_add(netdev, &card->napi,
gelic_net_poll, GELIC_NET_NAPI_WEIGHT);
netdev->features = NETIF_F_IP_CSUM; netdev->features = NETIF_F_IP_CSUM;
status = lv1_net_control(bus_id(card), dev_id(card), status = lv1_net_control(bus_id(card), dev_id(card),
......
...@@ -194,6 +194,7 @@ struct gelic_net_descr_chain { ...@@ -194,6 +194,7 @@ struct gelic_net_descr_chain {
struct gelic_net_card { struct gelic_net_card {
struct net_device *netdev; struct net_device *netdev;
struct napi_struct napi;
/* /*
* hypervisor requires irq_status should be * hypervisor requires irq_status should be
* 8 bytes aligned, but u64 member is * 8 bytes aligned, but u64 member is
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册