You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
[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:
committed by
David S. Miller
parent
dde4e47e8f
commit
bea3348eef
@@ -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
@@ -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.
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
@@ -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;
|
||||
|
||||
@@ -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
@@ -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;
|
||||
|
||||
@@ -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
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
@@ -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
Reference in New Issue
Block a user