[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: Stephen Hemminger <shemminger@linux-foundation.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Stephen Hemminger
2007-10-03 16:41:36 -07:00
committed by David S. Miller
parent dde4e47e8f
commit bea3348eef
91 changed files with 1765 additions and 2382 deletions
+9 -3
View File
@@ -240,17 +240,23 @@ X!Ilib/string.c
<sect1><title>Driver Support</title>
!Enet/core/dev.c
!Enet/ethernet/eth.c
!Enet/sched/sch_generic.c
!Iinclude/linux/etherdevice.h
!Iinclude/linux/netdevice.h
</sect1>
<sect1><title>PHY Support</title>
!Edrivers/net/phy/phy.c
!Idrivers/net/phy/phy.c
!Edrivers/net/phy/phy_device.c
!Idrivers/net/phy/phy_device.c
!Edrivers/net/phy/mdio_bus.c
!Idrivers/net/phy/mdio_bus.c
<!-- FIXME: Removed for now since no structured comments in source
X!Enet/core/wireless.c
-->
</sect1>
<!-- FIXME: Removed for now since no structured comments in source
<sect1><title>Wireless</title>
X!Enet/core/wireless.c
</sect1>
-->
<sect1><title>Synchronous PPP</title>
!Edrivers/net/wan/syncppp.c
</sect1>
File diff suppressed because it is too large Load Diff
+8 -4
View File
@@ -95,9 +95,13 @@ dev->set_multicast_list:
Synchronization: netif_tx_lock spinlock.
Context: BHs disabled
dev->poll:
Synchronization: __LINK_STATE_RX_SCHED bit in dev->state. See
dev_close code and comments in net/core/dev.c for more info.
struct napi_struct synchronization rules
========================================
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
will be called with interrupts disabled by netconsole.
+3 -1
View File
@@ -228,6 +228,8 @@ struct ipoib_dev_priv {
struct net_device *dev;
struct napi_struct napi;
unsigned long flags;
struct mutex mcast_mutex;
@@ -351,7 +353,7 @@ extern struct workqueue_struct *ipoib_workqueue;
/* 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);
struct ipoib_ah *ipoib_create_ah(struct net_device *dev,
+18 -25
View File
@@ -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);
}
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);
int max = min(*budget, dev->quota);
struct ipoib_dev_priv *priv = container_of(napi, struct ipoib_dev_priv, napi);
struct net_device *dev = priv->dev;
int done;
int t;
int empty;
int n, i;
done = 0;
empty = 0;
while (max) {
poll_more:
while (done < budget) {
int max = (budget - done);
t = min(IPOIB_NUM_WC, max);
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;
if (wc->wr_id & IPOIB_CM_OP_SRQ) {
++done;
--max;
ipoib_cm_handle_rx_wc(dev, wc);
} else if (wc->wr_id & IPOIB_OP_RECV) {
++done;
--max;
ipoib_ib_handle_rx_wc(dev, wc);
} else
ipoib_ib_handle_tx_wc(dev, wc);
}
if (n != t) {
empty = 1;
if (n != t)
break;
}
}
dev->quota -= done;
*budget -= done;
if (empty) {
netif_rx_complete(dev);
if (done < budget) {
netif_rx_complete(dev, napi);
if (unlikely(ib_req_notify_cq(priv->cq,
IB_CQ_NEXT_COMP |
IB_CQ_REPORT_MISSED_EVENTS)) &&
netif_rx_reschedule(dev, 0))
return 1;
return 0;
netif_rx_reschedule(dev, napi))
goto poll_more;
}
return 1;
return done;
}
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,
@@ -577,7 +572,6 @@ int ipoib_ib_dev_stop(struct net_device *dev, int flush)
int i;
clear_bit(IPOIB_FLAG_INITIALIZED, &priv->flags);
netif_poll_disable(dev);
ipoib_cm_dev_stop(dev);
@@ -660,7 +654,6 @@ timeout:
msleep(1);
}
netif_poll_enable(dev);
ib_req_notify_cq(priv->cq, IB_CQ_NEXT_COMP);
return 0;
+8 -3
View File
@@ -98,16 +98,20 @@ int ipoib_open(struct net_device *dev)
ipoib_dbg(priv, "bringing up interface\n");
napi_enable(&priv->napi);
set_bit(IPOIB_FLAG_ADMIN_UP, &priv->flags);
if (ipoib_pkey_dev_delay_open(dev))
return 0;
if (ipoib_ib_dev_open(dev))
if (ipoib_ib_dev_open(dev)) {
napi_disable(&priv->napi);
return -EINVAL;
}
if (ipoib_ib_dev_up(dev)) {
ipoib_ib_dev_stop(dev, 1);
napi_disable(&priv->napi);
return -EINVAL;
}
@@ -140,6 +144,7 @@ static int ipoib_stop(struct net_device *dev)
ipoib_dbg(priv, "stopping interface\n");
clear_bit(IPOIB_FLAG_ADMIN_UP, &priv->flags);
napi_disable(&priv->napi);
netif_stop_queue(dev);
@@ -948,8 +953,8 @@ static void ipoib_setup(struct net_device *dev)
dev->hard_header = ipoib_hard_header;
dev->set_multicast_list = ipoib_set_mcast_list;
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;
+21 -20
View File
@@ -334,6 +334,8 @@ struct cp_private {
spinlock_t lock;
u32 msg_enable;
struct napi_struct napi;
struct pci_dev *pdev;
u32 rx_config;
u16 cpcmd;
@@ -501,12 +503,12 @@ static inline unsigned int cp_rx_csum_ok (u32 status)
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);
unsigned rx_tail = cp->rx_tail;
unsigned rx_work = dev->quota;
unsigned rx;
struct cp_private *cp = container_of(napi, struct cp_private, napi);
struct net_device *dev = cp->dev;
unsigned int rx_tail = cp->rx_tail;
int rx;
rx_status_loop:
rx = 0;
@@ -588,33 +590,28 @@ rx_next:
desc->opts1 = cpu_to_le32(DescOwn | cp->rx_buf_sz);
rx_tail = NEXT_RX(rx_tail);
if (!rx_work--)
if (rx >= budget)
break;
}
cp->rx_tail = rx_tail;
dev->quota -= rx;
*budget -= rx;
/* if we did not reach work limit, then we're done with
* this round of polling
*/
if (rx_work) {
if (rx < budget) {
unsigned long flags;
if (cpr16(IntrStatus) & cp_rx_intr_mask)
goto rx_status_loop;
local_irq_save(flags);
spin_lock_irqsave(&cp->lock, flags);
cpw16_f(IntrMask, cp_intr_mask);
__netif_rx_complete(dev);
local_irq_restore(flags);
return 0; /* done */
__netif_rx_complete(dev, napi);
spin_unlock_irqrestore(&cp->lock, flags);
}
return 1; /* not done */
return rx;
}
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 (netif_rx_schedule_prep(dev)) {
if (netif_rx_schedule_prep(dev, &cp->napi)) {
cpw16_f(IntrMask, cp_norx_intr_mask);
__netif_rx_schedule(dev);
__netif_rx_schedule(dev, &cp->napi);
}
if (status & (TxOK | TxErr | TxEmpty | SWInt))
@@ -1175,6 +1172,8 @@ static int cp_open (struct net_device *dev)
if (rc)
return rc;
napi_enable(&cp->napi);
cp_init_hw(cp);
rc = request_irq(dev->irq, cp_interrupt, IRQF_SHARED, dev->name, dev);
@@ -1188,6 +1187,7 @@ static int cp_open (struct net_device *dev)
return 0;
err_out_hw:
napi_disable(&cp->napi);
cp_stop_hw(cp);
cp_free_rings(cp);
return rc;
@@ -1198,6 +1198,8 @@ static int cp_close (struct net_device *dev)
struct cp_private *cp = netdev_priv(dev);
unsigned long flags;
napi_disable(&cp->napi);
if (netif_msg_ifdown(cp))
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)
dev->hard_start_xmit = cp_start_xmit;
dev->get_stats = cp_get_stats;
dev->do_ioctl = cp_ioctl;
dev->poll = cp_rx_poll;
#ifdef CONFIG_NET_POLL_CONTROLLER
dev->poll_controller = cp_poll_controller;
#endif
dev->weight = 16; /* arbitrary? from NAPI_HOWTO.txt. */
netif_napi_add(dev, &cp->napi, cp_rx_poll, 16);
#ifdef BROKEN
dev->change_mtu = cp_change_mtu;
#endif
+23 -25
View File
@@ -573,6 +573,8 @@ struct rtl8139_private {
int drv_flags;
struct pci_dev *pci_dev;
u32 msg_enable;
struct napi_struct napi;
struct net_device *dev;
struct net_device_stats stats;
unsigned char *rx_ring;
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);
static void rtl8139_init_ring (struct net_device *dev);
static int rtl8139_start_xmit (struct sk_buff *skb,
struct net_device *dev);
static int rtl8139_poll(struct net_device *dev, int *budget);
#ifdef CONFIG_NET_POLL_CONTROLLER
static void rtl8139_poll_controller(struct net_device *dev);
#endif
static int rtl8139_poll(struct napi_struct *napi, int budget);
static irqreturn_t rtl8139_interrupt (int irq, void *dev_instance);
static int rtl8139_close (struct net_device *dev);
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,
assert (dev != NULL);
tp = netdev_priv(dev);
tp->dev = dev;
ioaddr = tp->mmio_addr;
assert (ioaddr != NULL);
@@ -976,8 +979,7 @@ static int __devinit rtl8139_init_one (struct pci_dev *pdev,
/* The Rtl8139-specific entries in the device structure. */
dev->open = rtl8139_open;
dev->hard_start_xmit = rtl8139_start_xmit;
dev->poll = rtl8139_poll;
dev->weight = 64;
netif_napi_add(dev, &tp->napi, rtl8139_poll, 64);
dev->stop = rtl8139_close;
dev->get_stats = rtl8139_get_stats;
dev->set_multicast_list = rtl8139_set_rx_mode;
@@ -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->tx_flag = (TX_FIFO_THRESH << 11) & 0x003f0000;
@@ -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;
int orig_budget = min(*budget, dev->quota);
int done = 1;
int work_done;
spin_lock(&tp->rx_lock);
if (likely(RTL_R16(IntrStatus) & RxAckBits)) {
int work_done;
work_done = 0;
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;
/*
* Order is important since data can get interrupted
* again when we think we are done.
*/
local_irq_save(flags);
spin_lock_irqsave(&tp->lock, flags);
RTL_W16_F(IntrMask, rtl8139_intr_mask);
__netif_rx_complete(dev);
local_irq_restore(flags);
__netif_rx_complete(dev, napi);
spin_unlock_irqrestore(&tp->lock, flags);
}
spin_unlock(&tp->rx_lock);
return !done;
return work_done;
}
/* 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)
/* Receive packets are processed by poll routine.
If not running start it now. */
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);
__netif_rx_schedule (dev);
__netif_rx_schedule(dev, &tp->napi);
}
}
@@ -2223,7 +2220,8 @@ static int rtl8139_close (struct net_device *dev)
void __iomem *ioaddr = tp->mmio_addr;
unsigned long flags;
netif_stop_queue (dev);
netif_stop_queue(dev);
napi_disable(&tp->napi);
if (netif_msg_ifdown(tp))
printk(KERN_DEBUG "%s: Shutting down ethercard, status was 0x%4.4x.\n",
+14 -16
View File
@@ -723,9 +723,10 @@ static int amd8111e_tx(struct net_device *dev)
#ifdef CONFIG_AMD8111E_NAPI
/* 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;
void __iomem *mmio = lp->mmio;
struct sk_buff *skb,*new_skb;
@@ -737,7 +738,7 @@ static int amd8111e_rx_poll(struct net_device *dev, int * budget)
#if AMD8111E_VLAN_TAG_USED
short vtag;
#endif
int rx_pkt_limit = dev->quota;
int rx_pkt_limit = budget;
unsigned long flags;
do{
@@ -838,21 +839,14 @@ static int amd8111e_rx_poll(struct net_device *dev, int * budget)
} while(intr0 & RINT0);
/* Receive descriptor is empty now */
dev->quota -= num_rx_pkt;
*budget -= num_rx_pkt;
spin_lock_irqsave(&lp->lock, flags);
netif_rx_complete(dev);
__netif_rx_complete(dev, napi);
writel(VAL0|RINTEN0, mmio + INTEN0);
writel(VAL2 | RDMD0, mmio + CMD0);
spin_unlock_irqrestore(&lp->lock, flags);
return 0;
rx_not_empty:
/* Do not call a netif_rx_complete */
dev->quota -= num_rx_pkt;
*budget -= num_rx_pkt;
return 1;
return num_rx_pkt;
}
#else
@@ -1287,11 +1281,11 @@ static irqreturn_t amd8111e_interrupt(int irq, void *dev_id)
/* Check if Receive Interrupt has occurred. */
#ifdef CONFIG_AMD8111E_NAPI
if(intr0 & RINT0){
if(netif_rx_schedule_prep(dev)){
if(netif_rx_schedule_prep(dev, &lp->napi)){
/* Disable receive interupts */
writel(RINTEN0, mmio + INTEN0);
/* Schedule a polling routine */
__netif_rx_schedule(dev);
__netif_rx_schedule(dev, &lp->napi);
}
else if (intren0 & RINTEN0) {
printk("************Driver bug! \
@@ -1345,6 +1339,8 @@ static int amd8111e_close(struct net_device * dev)
struct amd8111e_priv *lp = netdev_priv(dev);
netif_stop_queue(dev);
napi_disable(&lp->napi);
spin_lock_irq(&lp->lock);
amd8111e_disable_interrupt(lp);
@@ -1375,12 +1371,15 @@ static int amd8111e_open(struct net_device * dev )
dev->name, dev))
return -EAGAIN;
napi_enable(&lp->napi);
spin_lock_irq(&lp->lock);
amd8111e_init_hw_default(lp);
if(amd8111e_restart(dev)){
spin_unlock_irq(&lp->lock);
napi_disable(&lp->napi);
if (dev->irq)
free_irq(dev->irq, dev);
return -ENOMEM;
@@ -2031,8 +2030,7 @@ static int __devinit amd8111e_probe_one(struct pci_dev *pdev,
dev->tx_timeout = amd8111e_tx_timeout;
dev->watchdog_timeo = AMD8111E_TX_TIMEOUT;
#ifdef CONFIG_AMD8111E_NAPI
dev->poll = amd8111e_rx_poll;
dev->weight = 32;
netif_napi_add(dev, &lp->napi, amd8111e_rx_poll, 32);
#endif
#ifdef CONFIG_NET_POLL_CONTROLLER
dev->poll_controller = amd8111e_poll;
+2
View File
@@ -763,6 +763,8 @@ struct amd8111e_priv{
/* Reg memory mapped address */
void __iomem *mmio;
struct napi_struct napi;
spinlock_t lock; /* Guard lock */
unsigned long rx_idx, tx_idx; /* The next free ring entry */
unsigned long tx_complete_idx;
+33 -37
View File
@@ -169,6 +169,9 @@ struct ep93xx_priv
spinlock_t tx_pending_lock;
unsigned int tx_pending;
struct net_device *dev;
struct napi_struct napi;
struct net_device_stats stats;
struct mii_if_info mii;
@@ -190,15 +193,11 @@ static struct net_device_stats *ep93xx_get_stats(struct net_device *dev)
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);
int rx_done;
int processed;
rx_done = 0;
processed = 0;
while (*budget > 0) {
while (processed < budget) {
int entry;
struct ep93xx_rstat *rstat;
u32 rstat0;
@@ -211,10 +210,8 @@ static int ep93xx_rx(struct net_device *dev, int *budget)
rstat0 = rstat->rstat0;
rstat1 = rstat->rstat1;
if (!(rstat0 & RSTAT0_RFP) || !(rstat1 & RSTAT1_RFP)) {
rx_done = 1;
if (!(rstat0 & RSTAT0_RFP) || !(rstat1 & RSTAT1_RFP))
break;
}
rstat->rstat0 = 0;
rstat->rstat1 = 0;
@@ -275,8 +272,6 @@ static int ep93xx_rx(struct net_device *dev, int *budget)
err:
ep->rx_pointer = (entry + 1) & (RX_QUEUE_ENTRIES - 1);
processed++;
dev->quota--;
(*budget)--;
}
if (processed) {
@@ -284,7 +279,7 @@ err:
wrw(ep, REG_RXSTSENQ, processed);
}
return !rx_done;
return processed;
}
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));
}
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);
/*
* @@@ Have to stop polling if device is downed while we
* are polling.
*/
struct ep93xx_priv *ep = container_of(napi, struct ep93xx_priv, napi);
struct net_device *dev = ep->dev;
int rx = 0;
poll_some_more:
if (ep93xx_rx(dev, budget))
return 1;
rx = ep93xx_rx(dev, rx, budget);
if (rx < budget) {
int more = 0;
netif_rx_complete(dev);
spin_lock_irq(&ep->rx_lock);
wrl(ep, REG_INTEN, REG_INTEN_TX | REG_INTEN_RX);
if (ep93xx_have_more_rx(ep)) {
wrl(ep, REG_INTEN, REG_INTEN_TX);
wrl(ep, REG_INTSTSP, REG_INTSTS_RX);
spin_lock_irq(&ep->rx_lock);
__netif_rx_complete(dev, napi);
wrl(ep, REG_INTEN, REG_INTEN_TX | REG_INTEN_RX);
if (ep93xx_have_more_rx(ep)) {
wrl(ep, REG_INTEN, REG_INTEN_TX);
wrl(ep, REG_INTSTSP, REG_INTSTS_RX);
more = 1;
}
spin_unlock_irq(&ep->rx_lock);
if (netif_rx_reschedule(dev, 0))
if (more && netif_rx_reschedule(dev, napi))
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)
@@ -426,9 +417,9 @@ static irqreturn_t ep93xx_irq(int irq, void *dev_id)
if (status & REG_INTSTS_RX) {
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);
__netif_rx_schedule(dev);
__netif_rx_schedule(dev, &ep->napi);
}
spin_unlock(&ep->rx_lock);
}
@@ -648,7 +639,10 @@ static int ep93xx_open(struct net_device *dev)
dev->dev_addr[4], dev->dev_addr[5]);
}
napi_enable(&ep->napi);
if (ep93xx_start_hw(dev)) {
napi_disable(&ep->napi);
ep93xx_free_buffers(ep);
return -EIO;
}
@@ -662,6 +656,7 @@ static int ep93xx_open(struct net_device *dev)
err = request_irq(ep->irq, ep93xx_irq, IRQF_SHARED, dev->name, dev);
if (err) {
napi_disable(&ep->napi);
ep93xx_stop_hw(dev);
ep93xx_free_buffers(ep);
return err;
@@ -678,6 +673,7 @@ static int ep93xx_close(struct net_device *dev)
{
struct ep93xx_priv *ep = netdev_priv(dev);
napi_disable(&ep->napi);
netif_stop_queue(dev);
wrl(ep, REG_GIINTMSK, 0);
@@ -788,14 +784,12 @@ struct net_device *ep93xx_dev_alloc(struct ep93xx_eth_data *data)
dev->get_stats = ep93xx_get_stats;
dev->ethtool_ops = &ep93xx_ethtool_ops;
dev->poll = ep93xx_poll;
dev->hard_start_xmit = ep93xx_xmit;
dev->open = ep93xx_open;
dev->stop = ep93xx_close;
dev->do_ioctl = ep93xx_ioctl;
dev->features |= NETIF_F_SG | NETIF_F_HW_CSUM;
dev->weight = 64;
return dev;
}
@@ -847,6 +841,8 @@ static int ep93xx_eth_probe(struct platform_device *pdev)
goto err_out;
}
ep = netdev_priv(dev);
ep->dev = dev;
netif_napi_add(dev, &ep->napi, ep93xx_poll, 64);
platform_set_drvdata(pdev, dev);
+18 -30
View File
@@ -848,10 +848,11 @@ static int b44_rx(struct b44 *bp, int budget)
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);
int done;
struct b44 *bp = container_of(napi, struct b44, napi);
struct net_device *netdev = bp->dev;
int work_done;
spin_lock_irq(&bp->lock);
@@ -862,22 +863,9 @@ static int b44_poll(struct net_device *netdev, int *budget)
}
spin_unlock_irq(&bp->lock);
done = 1;
if (bp->istat & ISTAT_RX) {
int orig_budget = *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;
}
work_done = 0;
if (bp->istat & ISTAT_RX)
work_done += b44_rx(bp, budget);
if (bp->istat & ISTAT_ERRORS) {
unsigned long flags;
@@ -888,15 +876,15 @@ static int b44_poll(struct net_device *netdev, int *budget)
b44_init_hw(bp, B44_FULL_RESET_SKIP_PHY);
netif_wake_queue(bp->dev);
spin_unlock_irqrestore(&bp->lock, flags);
done = 1;
work_done = 0;
}
if (done) {
netif_rx_complete(netdev);
if (work_done < budget) {
netif_rx_complete(netdev, napi);
b44_enable_ints(bp);
}
return (done ? 0 : 1);
return work_done;
}
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;
}
if (netif_rx_schedule_prep(dev)) {
if (netif_rx_schedule_prep(dev, &bp->napi)) {
/* NOTE: These writes are posted by the readback of
* the ISTAT register below.
*/
bp->istat = istat;
__b44_disable_ints(bp);
__netif_rx_schedule(dev);
__netif_rx_schedule(dev, &bp->napi);
} else {
printk(KERN_ERR PFX "%s: Error, poll already scheduled\n",
dev->name);
@@ -1420,6 +1408,8 @@ static int b44_open(struct net_device *dev)
if (err)
goto out;
napi_enable(&bp->napi);
b44_init_rings(bp);
b44_init_hw(bp, B44_FULL_RESET);
@@ -1427,6 +1417,7 @@ static int b44_open(struct net_device *dev)
err = request_irq(dev->irq, b44_interrupt, IRQF_SHARED, dev->name, dev);
if (unlikely(err < 0)) {
napi_disable(&bp->napi);
b44_chip_reset(bp);
b44_free_rings(bp);
b44_free_consistent(bp);
@@ -1609,7 +1600,7 @@ static int b44_close(struct net_device *dev)
netif_stop_queue(dev);
netif_poll_disable(dev);
napi_disable(&bp->napi);
del_timer_sync(&bp->timer);
@@ -1626,8 +1617,6 @@ static int b44_close(struct net_device *dev)
free_irq(dev->irq, dev);
netif_poll_enable(dev);
if (bp->flags & B44_FLAG_WOL_ENABLE) {
b44_init_hw(bp, B44_PARTIAL_RESET);
b44_setup_wol(bp);
@@ -2194,8 +2183,7 @@ static int __devinit b44_init_one(struct pci_dev *pdev,
dev->set_mac_address = b44_set_mac_addr;
dev->do_ioctl = b44_ioctl;
dev->tx_timeout = b44_tx_timeout;
dev->poll = b44_poll;
dev->weight = 64;
netif_napi_add(dev, &bp->napi, b44_poll, 64);
dev->watchdog_timeo = B44_TX_TIMEOUT;
#ifdef CONFIG_NET_POLL_CONTROLLER
dev->poll_controller = b44_poll_controller;
+2
View File
@@ -423,6 +423,8 @@ struct b44 {
struct ring_info *rx_buffers;
struct ring_info *tx_buffers;
struct napi_struct napi;
u32 dma_offset;
u32 flags;
#define B44_FLAG_B0_ANDLATER 0x00000001
+22 -25
View File
@@ -428,7 +428,7 @@ bnx2_netif_stop(struct bnx2 *bp)
{
bnx2_disable_int_sync(bp);
if (netif_running(bp->dev)) {
netif_poll_disable(bp->dev);
napi_disable(&bp->napi);
netif_tx_disable(bp->dev);
bp->dev->trans_start = jiffies; /* prevent tx timeout */
}
@@ -440,7 +440,7 @@ bnx2_netif_start(struct bnx2 *bp)
if (atomic_dec_and_test(&bp->intr_sem)) {
if (netif_running(bp->dev)) {
netif_wake_queue(bp->dev);
netif_poll_enable(bp->dev);
napi_enable(&bp->napi);
bnx2_enable_int(bp);
}
}
@@ -2551,7 +2551,7 @@ bnx2_msi(int irq, void *dev_instance)
if (unlikely(atomic_read(&bp->intr_sem) != 0))
return IRQ_HANDLED;
netif_rx_schedule(dev);
netif_rx_schedule(dev, &bp->napi);
return IRQ_HANDLED;
}
@@ -2568,7 +2568,7 @@ bnx2_msi_1shot(int irq, void *dev_instance)
if (unlikely(atomic_read(&bp->intr_sem) != 0))
return IRQ_HANDLED;
netif_rx_schedule(dev);
netif_rx_schedule(dev, &bp->napi);
return IRQ_HANDLED;
}
@@ -2604,9 +2604,9 @@ bnx2_interrupt(int irq, void *dev_instance)
if (unlikely(atomic_read(&bp->intr_sem) != 0))
return IRQ_HANDLED;
if (netif_rx_schedule_prep(dev)) {
if (netif_rx_schedule_prep(dev, &bp->napi)) {
bp->last_status_idx = sblk->status_idx;
__netif_rx_schedule(dev);
__netif_rx_schedule(dev, &bp->napi);
}
return IRQ_HANDLED;
@@ -2632,12 +2632,14 @@ bnx2_has_work(struct bnx2 *bp)
}
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;
u32 status_attn_bits = sblk->status_attn_bits;
u32 status_attn_bits_ack = sblk->status_attn_bits_ack;
int work_done = 0;
if ((status_attn_bits & STATUS_ATTN_EVENTS) !=
(status_attn_bits_ack & STATUS_ATTN_EVENTS)) {
@@ -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)
bnx2_tx_int(bp);
if (bp->status_blk->status_rx_quick_consumer_index0 != bp->hw_rx_cons) {
int orig_budget = *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;
}
if (bp->status_blk->status_rx_quick_consumer_index0 != bp->hw_rx_cons)
work_done = bnx2_rx_int(bp, budget);
bp->last_status_idx = bp->status_blk->status_idx;
rmb();
if (!bnx2_has_work(bp)) {
netif_rx_complete(dev);
netif_rx_complete(dev, napi);
if (likely(bp->flags & USING_MSI_FLAG)) {
REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD,
BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID |
@@ -2686,10 +2679,9 @@ bnx2_poll(struct net_device *dev, int *budget)
REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD,
BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID |
bp->last_status_idx);
return 0;
}
return 1;
return work_done;
}
/* Called with rtnl_lock from vlan functions and also netif_tx_lock
@@ -5039,6 +5031,8 @@ bnx2_open(struct net_device *dev)
if (rc)
return rc;
napi_enable(&bp->napi);
if ((bp->flags & MSI_CAP_FLAG) && !disable_msi) {
if (pci_enable_msi(bp->pdev) == 0) {
bp->flags |= USING_MSI_FLAG;
@@ -5049,6 +5043,7 @@ bnx2_open(struct net_device *dev)
rc = bnx2_request_irq(bp);
if (rc) {
napi_disable(&bp->napi);
bnx2_free_mem(bp);
return rc;
}
@@ -5056,6 +5051,7 @@ bnx2_open(struct net_device *dev)
rc = bnx2_init_nic(bp);
if (rc) {
napi_disable(&bp->napi);
bnx2_free_irq(bp);
bnx2_free_skbs(bp);
bnx2_free_mem(bp);
@@ -5088,6 +5084,7 @@ bnx2_open(struct net_device *dev)
rc = bnx2_request_irq(bp);
if (rc) {
napi_disable(&bp->napi);
bnx2_free_skbs(bp);
bnx2_free_mem(bp);
del_timer_sync(&bp->timer);
@@ -5301,7 +5298,8 @@ bnx2_close(struct net_device *dev)
while (bp->in_reset_task)
msleep(1);
bnx2_netif_stop(bp);
bnx2_disable_int_sync(bp);
napi_disable(&bp->napi);
del_timer_sync(&bp->timer);
if (bp->flags & NO_WOL_FLAG)
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)
#ifdef BCM_VLAN
dev->vlan_rx_register = bnx2_vlan_rx_register;
#endif
dev->poll = bnx2_poll;
dev->ethtool_ops = &bnx2_ethtool_ops;
dev->weight = 64;
bp = netdev_priv(dev);
netif_napi_add(dev, &bp->napi, bnx2_poll, 64);
#if defined(HAVE_POLL_CONTROLLER) || defined(CONFIG_NET_POLL_CONTROLLER)
dev->poll_controller = poll_bnx2;
+2
View File
@@ -6473,6 +6473,8 @@ struct bnx2 {
struct net_device *dev;
struct pci_dev *pdev;
struct napi_struct napi;
atomic_t intr_sem;
struct status_block *status_blk;
+20 -20
View File
@@ -2485,7 +2485,7 @@ static irqreturn_t cas_interruptN(int irq, void *dev_id)
if (status & INTR_RX_DONE_ALT) { /* handle rx separately */
#ifdef USE_NAPI
cas_mask_intr(cp);
netif_rx_schedule(dev);
netif_rx_schedule(dev, &cp->napi);
#else
cas_rx_ringN(cp, ring, 0);
#endif
@@ -2536,7 +2536,7 @@ static irqreturn_t cas_interrupt1(int irq, void *dev_id)
if (status & INTR_RX_DONE_ALT) { /* handle rx separately */
#ifdef USE_NAPI
cas_mask_intr(cp);
netif_rx_schedule(dev);
netif_rx_schedule(dev, &cp->napi);
#else
cas_rx_ringN(cp, 1, 0);
#endif
@@ -2592,7 +2592,7 @@ static irqreturn_t cas_interrupt(int irq, void *dev_id)
if (status & INTR_RX_DONE) {
#ifdef USE_NAPI
cas_mask_intr(cp);
netif_rx_schedule(dev);
netif_rx_schedule(dev, &cp->napi);
#else
cas_rx_ringN(cp, 0, 0);
#endif
@@ -2607,9 +2607,10 @@ static irqreturn_t cas_interrupt(int irq, void *dev_id)
#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;
u32 status = readl(cp->regs + REG_INTR_STATUS);
unsigned long flags;
@@ -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
* 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
* todo / N_RX_COMP_RINGS
* budget / N_RX_COMP_RINGS
*/
enable_intr = 1;
credits = 0;
for (i = 0; i < N_RX_COMP_RINGS; i++) {
int j;
for (j = 0; j < N_RX_COMP_RINGS; j++) {
credits += cas_rx_ringN(cp, j, todo / N_RX_COMP_RINGS);
if (credits >= todo) {
credits += cas_rx_ringN(cp, j, budget / N_RX_COMP_RINGS);
if (credits >= budget) {
enable_intr = 0;
goto rx_comp;
}
@@ -2641,9 +2640,6 @@ static int cas_poll(struct net_device *dev, int *budget)
}
rx_comp:
*budget -= credits;
dev->quota -= credits;
/* final rx completion */
spin_lock_irqsave(&cp->lock, flags);
if (status)
@@ -2674,11 +2670,10 @@ rx_comp:
#endif
spin_unlock_irqrestore(&cp->lock, flags);
if (enable_intr) {
netif_rx_complete(dev);
netif_rx_complete(dev, napi);
cas_unmask_intr(cp);
return 0;
}
return 1;
return credits;
}
#endif
@@ -4351,6 +4346,9 @@ static int cas_open(struct net_device *dev)
goto err_spare;
}
#ifdef USE_NAPI
napi_enable(&cp->napi);
#endif
/* init hw */
cas_lock_all_save(cp, flags);
cas_clean_rings(cp);
@@ -4376,6 +4374,9 @@ static int cas_close(struct net_device *dev)
unsigned long flags;
struct cas *cp = netdev_priv(dev);
#ifdef USE_NAPI
napi_enable(&cp->napi);
#endif
/* Make sure we don't get distracted by suspend/resume */
mutex_lock(&cp->pm_mutex);
@@ -5062,8 +5063,7 @@ static int __devinit cas_init_one(struct pci_dev *pdev,
dev->watchdog_timeo = CAS_TX_TIMEOUT;
dev->change_mtu = cas_change_mtu;
#ifdef USE_NAPI
dev->poll = cas_poll;
dev->weight = 64;
netif_napi_add(dev, &cp->napi, cas_poll, 64);
#endif
#ifdef CONFIG_NET_POLL_CONTROLLER
dev->poll_controller = cas_netpoll;
+2
View File
@@ -4280,6 +4280,8 @@ struct cas {
int rx_cur[N_RX_COMP_RINGS], rx_new[N_RX_COMP_RINGS];
int rx_last[N_RX_DESC_RINGS];
struct napi_struct napi;
/* Set when chip is actually in operational state
* (ie. not power managed) */
int hw_running;
+1
View File
@@ -278,6 +278,7 @@ struct adapter {
struct peespi *espi;
struct petp *tp;
struct napi_struct napi;
struct port_info port[MAX_NPORTS];
struct delayed_work stats_update_task;
struct timer_list stats_update_timer;
+6 -3
View File
@@ -255,8 +255,11 @@ static int cxgb_open(struct net_device *dev)
struct adapter *adapter = dev->priv;
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;
}
__set_bit(dev->if_port, &adapter->open_device_map);
link_start(&adapter->port[dev->if_port]);
@@ -274,6 +277,7 @@ static int cxgb_close(struct net_device *dev)
struct cmac *mac = p->mac;
netif_stop_queue(dev);
napi_disable(&adapter->napi);
mac->ops->disable(mac, MAC_DIRECTION_TX | MAC_DIRECTION_RX);
netif_carrier_off(dev);
@@ -1113,8 +1117,7 @@ static int __devinit init_one(struct pci_dev *pdev,
netdev->poll_controller = t1_netpoll;
#endif
#ifdef CONFIG_CHELSIO_T1_NAPI
netdev->weight = 64;
netdev->poll = t1_poll;
netif_napi_add(netdev, &adapter->napi, t1_poll, 64);
#endif
SET_ETHTOOL_OPS(netdev, &t1_ethtool_ops);
+13 -16
View File
@@ -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
* 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;
work_done = process_responses(adapter, min(*budget, dev->quota));
*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;
work_done = process_responses(adapter, budget);
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)
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))
__netif_rx_schedule(dev);
__netif_rx_schedule(dev, &adapter->napi);
else {
/* no data, no NAPI needed */
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;

Some files were not shown because too many files have changed in this diff Show More