aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/netconsole.c15
-rw-r--r--include/linux/if.h2
-rw-r--r--include/linux/netdevice.h1
-rw-r--r--include/linux/netpoll.h5
-rw-r--r--include/linux/notifier.h1
-rw-r--r--net/core/netpoll.c26
6 files changed, 39 insertions, 11 deletions
diff --git a/drivers/net/netconsole.c b/drivers/net/netconsole.c
index a361dea35574..ca142c47b2e4 100644
--- a/drivers/net/netconsole.c
+++ b/drivers/net/netconsole.c
@@ -665,7 +665,8 @@ static int netconsole_netdev_event(struct notifier_block *this,
665 struct netconsole_target *nt; 665 struct netconsole_target *nt;
666 struct net_device *dev = ptr; 666 struct net_device *dev = ptr;
667 667
668 if (!(event == NETDEV_CHANGENAME || event == NETDEV_UNREGISTER)) 668 if (!(event == NETDEV_CHANGENAME || event == NETDEV_UNREGISTER ||
669 event == NETDEV_BONDING_DESLAVE || event == NETDEV_GOING_DOWN))
669 goto done; 670 goto done;
670 671
671 spin_lock_irqsave(&target_list_lock, flags); 672 spin_lock_irqsave(&target_list_lock, flags);
@@ -677,19 +678,21 @@ static int netconsole_netdev_event(struct notifier_block *this,
677 strlcpy(nt->np.dev_name, dev->name, IFNAMSIZ); 678 strlcpy(nt->np.dev_name, dev->name, IFNAMSIZ);
678 break; 679 break;
679 case NETDEV_UNREGISTER: 680 case NETDEV_UNREGISTER:
680 if (!nt->enabled)
681 break;
682 netpoll_cleanup(&nt->np); 681 netpoll_cleanup(&nt->np);
682 /* Fall through */
683 case NETDEV_GOING_DOWN:
684 case NETDEV_BONDING_DESLAVE:
683 nt->enabled = 0; 685 nt->enabled = 0;
684 printk(KERN_INFO "netconsole: network logging stopped"
685 ", interface %s unregistered\n",
686 dev->name);
687 break; 686 break;
688 } 687 }
689 } 688 }
690 netconsole_target_put(nt); 689 netconsole_target_put(nt);
691 } 690 }
692 spin_unlock_irqrestore(&target_list_lock, flags); 691 spin_unlock_irqrestore(&target_list_lock, flags);
692 if (event == NETDEV_UNREGISTER || event == NETDEV_BONDING_DESLAVE)
693 printk(KERN_INFO "netconsole: network logging stopped, "
694 "interface %s %s\n", dev->name,
695 event == NETDEV_UNREGISTER ? "unregistered" : "released slaves");
693 696
694done: 697done:
695 return NOTIFY_DONE; 698 return NOTIFY_DONE;
diff --git a/include/linux/if.h b/include/linux/if.h
index 3a9f410a296b..be350e62a905 100644
--- a/include/linux/if.h
+++ b/include/linux/if.h
@@ -71,6 +71,8 @@
71 * release skb->dst 71 * release skb->dst
72 */ 72 */
73#define IFF_DONT_BRIDGE 0x800 /* disallow bridging this ether dev */ 73#define IFF_DONT_BRIDGE 0x800 /* disallow bridging this ether dev */
74#define IFF_IN_NETPOLL 0x1000 /* whether we are processing netpoll */
75#define IFF_DISABLE_NETPOLL 0x2000 /* disable netpoll at run-time */
74 76
75#define IF_GET_IFACE 0x0001 /* for querying only */ 77#define IF_GET_IFACE 0x0001 /* for querying only */
76#define IF_GET_PROTO 0x0002 78#define IF_GET_PROTO 0x0002
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 98112fbddefd..69022d47d6f2 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -724,6 +724,7 @@ struct net_device_ops {
724 unsigned short vid); 724 unsigned short vid);
725#ifdef CONFIG_NET_POLL_CONTROLLER 725#ifdef CONFIG_NET_POLL_CONTROLLER
726 void (*ndo_poll_controller)(struct net_device *dev); 726 void (*ndo_poll_controller)(struct net_device *dev);
727 void (*ndo_netpoll_cleanup)(struct net_device *dev);
727#endif 728#endif
728 int (*ndo_set_vf_mac)(struct net_device *dev, 729 int (*ndo_set_vf_mac)(struct net_device *dev,
729 int queue, u8 *mac); 730 int queue, u8 *mac);
diff --git a/include/linux/netpoll.h b/include/linux/netpoll.h
index a765ea898549..017e604d05f8 100644
--- a/include/linux/netpoll.h
+++ b/include/linux/netpoll.h
@@ -14,6 +14,7 @@
14 14
15struct netpoll { 15struct netpoll {
16 struct net_device *dev; 16 struct net_device *dev;
17 struct net_device *real_dev;
17 char dev_name[IFNAMSIZ]; 18 char dev_name[IFNAMSIZ];
18 const char *name; 19 const char *name;
19 void (*rx_hook)(struct netpoll *, int, char *, int); 20 void (*rx_hook)(struct netpoll *, int, char *, int);
@@ -36,8 +37,11 @@ struct netpoll_info {
36 struct sk_buff_head txq; 37 struct sk_buff_head txq;
37 38
38 struct delayed_work tx_work; 39 struct delayed_work tx_work;
40
41 struct netpoll *netpoll;
39}; 42};
40 43
44void netpoll_poll_dev(struct net_device *dev);
41void netpoll_poll(struct netpoll *np); 45void netpoll_poll(struct netpoll *np);
42void netpoll_send_udp(struct netpoll *np, const char *msg, int len); 46void netpoll_send_udp(struct netpoll *np, const char *msg, int len);
43void netpoll_print_options(struct netpoll *np); 47void netpoll_print_options(struct netpoll *np);
@@ -47,6 +51,7 @@ int netpoll_trap(void);
47void netpoll_set_trap(int trap); 51void netpoll_set_trap(int trap);
48void netpoll_cleanup(struct netpoll *np); 52void netpoll_cleanup(struct netpoll *np);
49int __netpoll_rx(struct sk_buff *skb); 53int __netpoll_rx(struct sk_buff *skb);
54void netpoll_send_skb(struct netpoll *np, struct sk_buff *skb);
50 55
51 56
52#ifdef CONFIG_NETPOLL 57#ifdef CONFIG_NETPOLL
diff --git a/include/linux/notifier.h b/include/linux/notifier.h
index 9c5d3fad01f3..7c3609622334 100644
--- a/include/linux/notifier.h
+++ b/include/linux/notifier.h
@@ -206,6 +206,7 @@ static inline int notifier_to_errno(int ret)
206#define NETDEV_POST_TYPE_CHANGE 0x000F 206#define NETDEV_POST_TYPE_CHANGE 0x000F
207#define NETDEV_POST_INIT 0x0010 207#define NETDEV_POST_INIT 0x0010
208#define NETDEV_UNREGISTER_BATCH 0x0011 208#define NETDEV_UNREGISTER_BATCH 0x0011
209#define NETDEV_BONDING_DESLAVE 0x0012
209 210
210#define SYS_DOWN 0x0001 /* Notify of system down */ 211#define SYS_DOWN 0x0001 /* Notify of system down */
211#define SYS_RESTART SYS_DOWN 212#define SYS_RESTART SYS_DOWN
diff --git a/net/core/netpoll.c b/net/core/netpoll.c
index a58f59b97597..94825b109551 100644
--- a/net/core/netpoll.c
+++ b/net/core/netpoll.c
@@ -179,9 +179,8 @@ static void service_arp_queue(struct netpoll_info *npi)
179 } 179 }
180} 180}
181 181
182void netpoll_poll(struct netpoll *np) 182void netpoll_poll_dev(struct net_device *dev)
183{ 183{
184 struct net_device *dev = np->dev;
185 const struct net_device_ops *ops; 184 const struct net_device_ops *ops;
186 185
187 if (!dev || !netif_running(dev)) 186 if (!dev || !netif_running(dev))
@@ -201,6 +200,11 @@ void netpoll_poll(struct netpoll *np)
201 zap_completion_queue(); 200 zap_completion_queue();
202} 201}
203 202
203void netpoll_poll(struct netpoll *np)
204{
205 netpoll_poll_dev(np->dev);
206}
207
204static void refill_skbs(void) 208static void refill_skbs(void)
205{ 209{
206 struct sk_buff *skb; 210 struct sk_buff *skb;
@@ -282,7 +286,7 @@ static int netpoll_owner_active(struct net_device *dev)
282 return 0; 286 return 0;
283} 287}
284 288
285static void netpoll_send_skb(struct netpoll *np, struct sk_buff *skb) 289void netpoll_send_skb(struct netpoll *np, struct sk_buff *skb)
286{ 290{
287 int status = NETDEV_TX_BUSY; 291 int status = NETDEV_TX_BUSY;
288 unsigned long tries; 292 unsigned long tries;
@@ -308,7 +312,9 @@ static void netpoll_send_skb(struct netpoll *np, struct sk_buff *skb)
308 tries > 0; --tries) { 312 tries > 0; --tries) {
309 if (__netif_tx_trylock(txq)) { 313 if (__netif_tx_trylock(txq)) {
310 if (!netif_tx_queue_stopped(txq)) { 314 if (!netif_tx_queue_stopped(txq)) {
315 dev->priv_flags |= IFF_IN_NETPOLL;
311 status = ops->ndo_start_xmit(skb, dev); 316 status = ops->ndo_start_xmit(skb, dev);
317 dev->priv_flags &= ~IFF_IN_NETPOLL;
312 if (status == NETDEV_TX_OK) 318 if (status == NETDEV_TX_OK)
313 txq_trans_update(txq); 319 txq_trans_update(txq);
314 } 320 }
@@ -756,7 +762,10 @@ int netpoll_setup(struct netpoll *np)
756 atomic_inc(&npinfo->refcnt); 762 atomic_inc(&npinfo->refcnt);
757 } 763 }
758 764
759 if (!ndev->netdev_ops->ndo_poll_controller) { 765 npinfo->netpoll = np;
766
767 if ((ndev->priv_flags & IFF_DISABLE_NETPOLL) ||
768 !ndev->netdev_ops->ndo_poll_controller) {
760 printk(KERN_ERR "%s: %s doesn't support polling, aborting.\n", 769 printk(KERN_ERR "%s: %s doesn't support polling, aborting.\n",
761 np->name, np->dev_name); 770 np->name, np->dev_name);
762 err = -ENOTSUPP; 771 err = -ENOTSUPP;
@@ -878,6 +887,7 @@ void netpoll_cleanup(struct netpoll *np)
878 } 887 }
879 888
880 if (atomic_dec_and_test(&npinfo->refcnt)) { 889 if (atomic_dec_and_test(&npinfo->refcnt)) {
890 const struct net_device_ops *ops;
881 skb_queue_purge(&npinfo->arp_tx); 891 skb_queue_purge(&npinfo->arp_tx);
882 skb_queue_purge(&npinfo->txq); 892 skb_queue_purge(&npinfo->txq);
883 cancel_rearming_delayed_work(&npinfo->tx_work); 893 cancel_rearming_delayed_work(&npinfo->tx_work);
@@ -885,7 +895,11 @@ void netpoll_cleanup(struct netpoll *np)
885 /* clean after last, unfinished work */ 895 /* clean after last, unfinished work */
886 __skb_queue_purge(&npinfo->txq); 896 __skb_queue_purge(&npinfo->txq);
887 kfree(npinfo); 897 kfree(npinfo);
888 np->dev->npinfo = NULL; 898 ops = np->dev->netdev_ops;
899 if (ops->ndo_netpoll_cleanup)
900 ops->ndo_netpoll_cleanup(np->dev);
901 else
902 np->dev->npinfo = NULL;
889 } 903 }
890 } 904 }
891 905
@@ -908,6 +922,7 @@ void netpoll_set_trap(int trap)
908 atomic_dec(&trapped); 922 atomic_dec(&trapped);
909} 923}
910 924
925EXPORT_SYMBOL(netpoll_send_skb);
911EXPORT_SYMBOL(netpoll_set_trap); 926EXPORT_SYMBOL(netpoll_set_trap);
912EXPORT_SYMBOL(netpoll_trap); 927EXPORT_SYMBOL(netpoll_trap);
913EXPORT_SYMBOL(netpoll_print_options); 928EXPORT_SYMBOL(netpoll_print_options);
@@ -915,4 +930,5 @@ EXPORT_SYMBOL(netpoll_parse_options);
915EXPORT_SYMBOL(netpoll_setup); 930EXPORT_SYMBOL(netpoll_setup);
916EXPORT_SYMBOL(netpoll_cleanup); 931EXPORT_SYMBOL(netpoll_cleanup);
917EXPORT_SYMBOL(netpoll_send_udp); 932EXPORT_SYMBOL(netpoll_send_udp);
933EXPORT_SYMBOL(netpoll_poll_dev);
918EXPORT_SYMBOL(netpoll_poll); 934EXPORT_SYMBOL(netpoll_poll);