|
@@ -179,9 +179,8 @@ static void service_arp_queue(struct netpoll_info *npi)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-void netpoll_poll(struct netpoll *np)
|
|
|
+void netpoll_poll_dev(struct net_device *dev)
|
|
|
{
|
|
|
- struct net_device *dev = np->dev;
|
|
|
const struct net_device_ops *ops;
|
|
|
|
|
|
if (!dev || !netif_running(dev))
|
|
@@ -201,6 +200,11 @@ void netpoll_poll(struct netpoll *np)
|
|
|
zap_completion_queue();
|
|
|
}
|
|
|
|
|
|
+void netpoll_poll(struct netpoll *np)
|
|
|
+{
|
|
|
+ netpoll_poll_dev(np->dev);
|
|
|
+}
|
|
|
+
|
|
|
static void refill_skbs(void)
|
|
|
{
|
|
|
struct sk_buff *skb;
|
|
@@ -282,7 +286,7 @@ static int netpoll_owner_active(struct net_device *dev)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-static void netpoll_send_skb(struct netpoll *np, struct sk_buff *skb)
|
|
|
+void netpoll_send_skb(struct netpoll *np, struct sk_buff *skb)
|
|
|
{
|
|
|
int status = NETDEV_TX_BUSY;
|
|
|
unsigned long tries;
|
|
@@ -308,7 +312,9 @@ static void netpoll_send_skb(struct netpoll *np, struct sk_buff *skb)
|
|
|
tries > 0; --tries) {
|
|
|
if (__netif_tx_trylock(txq)) {
|
|
|
if (!netif_tx_queue_stopped(txq)) {
|
|
|
+ dev->priv_flags |= IFF_IN_NETPOLL;
|
|
|
status = ops->ndo_start_xmit(skb, dev);
|
|
|
+ dev->priv_flags &= ~IFF_IN_NETPOLL;
|
|
|
if (status == NETDEV_TX_OK)
|
|
|
txq_trans_update(txq);
|
|
|
}
|
|
@@ -756,7 +762,10 @@ int netpoll_setup(struct netpoll *np)
|
|
|
atomic_inc(&npinfo->refcnt);
|
|
|
}
|
|
|
|
|
|
- if (!ndev->netdev_ops->ndo_poll_controller) {
|
|
|
+ npinfo->netpoll = np;
|
|
|
+
|
|
|
+ if ((ndev->priv_flags & IFF_DISABLE_NETPOLL) ||
|
|
|
+ !ndev->netdev_ops->ndo_poll_controller) {
|
|
|
printk(KERN_ERR "%s: %s doesn't support polling, aborting.\n",
|
|
|
np->name, np->dev_name);
|
|
|
err = -ENOTSUPP;
|
|
@@ -878,6 +887,7 @@ void netpoll_cleanup(struct netpoll *np)
|
|
|
}
|
|
|
|
|
|
if (atomic_dec_and_test(&npinfo->refcnt)) {
|
|
|
+ const struct net_device_ops *ops;
|
|
|
skb_queue_purge(&npinfo->arp_tx);
|
|
|
skb_queue_purge(&npinfo->txq);
|
|
|
cancel_rearming_delayed_work(&npinfo->tx_work);
|
|
@@ -885,7 +895,11 @@ void netpoll_cleanup(struct netpoll *np)
|
|
|
/* clean after last, unfinished work */
|
|
|
__skb_queue_purge(&npinfo->txq);
|
|
|
kfree(npinfo);
|
|
|
- np->dev->npinfo = NULL;
|
|
|
+ ops = np->dev->netdev_ops;
|
|
|
+ if (ops->ndo_netpoll_cleanup)
|
|
|
+ ops->ndo_netpoll_cleanup(np->dev);
|
|
|
+ else
|
|
|
+ np->dev->npinfo = NULL;
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -908,6 +922,7 @@ void netpoll_set_trap(int trap)
|
|
|
atomic_dec(&trapped);
|
|
|
}
|
|
|
|
|
|
+EXPORT_SYMBOL(netpoll_send_skb);
|
|
|
EXPORT_SYMBOL(netpoll_set_trap);
|
|
|
EXPORT_SYMBOL(netpoll_trap);
|
|
|
EXPORT_SYMBOL(netpoll_print_options);
|
|
@@ -915,4 +930,5 @@ EXPORT_SYMBOL(netpoll_parse_options);
|
|
|
EXPORT_SYMBOL(netpoll_setup);
|
|
|
EXPORT_SYMBOL(netpoll_cleanup);
|
|
|
EXPORT_SYMBOL(netpoll_send_udp);
|
|
|
+EXPORT_SYMBOL(netpoll_poll_dev);
|
|
|
EXPORT_SYMBOL(netpoll_poll);
|