enum
{
NAPI_STATE_SCHED, /* Poll is scheduled */
+ NAPI_STATE_DISABLE, /* Disable pending */
};
extern void FASTCALL(__napi_schedule(struct napi_struct *n));
+static inline int napi_disable_pending(struct napi_struct *n)
+{
+ return test_bit(NAPI_STATE_DISABLE, &n->state);
+}
+
/**
* napi_schedule_prep - check if napi can be scheduled
* @n: napi context
*
* Test if NAPI routine is already running, and if not mark
* it as running. This is used as a condition variable
- * insure only one NAPI poll instance runs
+ * insure only one NAPI poll instance runs. We also make
+ * sure there is no pending NAPI disable.
*/
static inline int napi_schedule_prep(struct napi_struct *n)
{
- return !test_and_set_bit(NAPI_STATE_SCHED, &n->state);
+ return !napi_disable_pending(n) &&
+ !test_and_set_bit(NAPI_STATE_SCHED, &n->state);
}
/**
*/
static inline void napi_disable(struct napi_struct *n)
{
+ set_bit(NAPI_STATE_DISABLE, &n->state);
while (test_and_set_bit(NAPI_STATE_SCHED, &n->state))
- msleep_interruptible(1);
+ msleep(1);
+ clear_bit(NAPI_STATE_DISABLE, &n->state);
}
/**
#define HAVE_SET_MAC_ADDR
int (*set_mac_address)(struct net_device *dev,
void *addr);
+#define HAVE_VALIDATE_ADDR
+ int (*validate_addr)(struct net_device *dev);
#define HAVE_PRIVATE_IOCTL
int (*do_ioctl)(struct net_device *dev,
struct ifreq *ifr, int cmd);
*/
#define SET_NETDEV_DEV(net, pdev) ((net)->dev.parent = (pdev))
+/**
+ * netif_napi_add - initialize a napi context
+ * @dev: network device
+ * @napi: napi context
+ * @poll: polling function
+ * @weight: default weight
+ *
+ * netif_napi_add() must be used to initialize a napi context prior to calling
+ * *any* of the other napi related functions.
+ */
static inline void netif_napi_add(struct net_device *dev,
struct napi_struct *napi,
int (*poll)(struct napi_struct *, int),
const void *daddr, const void *saddr,
unsigned len)
{
- if (!dev->header_ops)
+ if (!dev->header_ops || !dev->header_ops->create)
return 0;
return dev->header_ops->create(skb, dev, type, daddr, saddr, len);
static inline int netif_rx_schedule_prep(struct net_device *dev,
struct napi_struct *napi)
{
- return netif_running(dev) && napi_schedule_prep(napi);
+ return napi_schedule_prep(napi);
}
/* Add interface to tail of rx poll list. This assumes that _prep has
static inline void __netif_rx_schedule(struct net_device *dev,
struct napi_struct *napi)
{
- dev_hold(dev);
__napi_schedule(napi);
}
struct napi_struct *napi)
{
__napi_complete(napi);
- dev_put(dev);
}
/* Remove interface from poll list: it must be in the poll list