diff options
-rw-r--r-- | drivers/net/netconsole.c | 15 | ||||
-rw-r--r-- | include/linux/if.h | 2 | ||||
-rw-r--r-- | include/linux/netdevice.h | 1 | ||||
-rw-r--r-- | include/linux/netpoll.h | 5 | ||||
-rw-r--r-- | include/linux/notifier.h | 1 | ||||
-rw-r--r-- | net/core/netpoll.c | 26 |
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 | ||
694 | done: | 697 | done: |
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 | ||
15 | struct netpoll { | 15 | struct 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 | ||
44 | void netpoll_poll_dev(struct net_device *dev); | ||
41 | void netpoll_poll(struct netpoll *np); | 45 | void netpoll_poll(struct netpoll *np); |
42 | void netpoll_send_udp(struct netpoll *np, const char *msg, int len); | 46 | void netpoll_send_udp(struct netpoll *np, const char *msg, int len); |
43 | void netpoll_print_options(struct netpoll *np); | 47 | void netpoll_print_options(struct netpoll *np); |
@@ -47,6 +51,7 @@ int netpoll_trap(void); | |||
47 | void netpoll_set_trap(int trap); | 51 | void netpoll_set_trap(int trap); |
48 | void netpoll_cleanup(struct netpoll *np); | 52 | void netpoll_cleanup(struct netpoll *np); |
49 | int __netpoll_rx(struct sk_buff *skb); | 53 | int __netpoll_rx(struct sk_buff *skb); |
54 | void 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 | ||
182 | void netpoll_poll(struct netpoll *np) | 182 | void 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 | ||
203 | void netpoll_poll(struct netpoll *np) | ||
204 | { | ||
205 | netpoll_poll_dev(np->dev); | ||
206 | } | ||
207 | |||
204 | static void refill_skbs(void) | 208 | static 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 | ||
285 | static void netpoll_send_skb(struct netpoll *np, struct sk_buff *skb) | 289 | void 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 | ||
925 | EXPORT_SYMBOL(netpoll_send_skb); | ||
911 | EXPORT_SYMBOL(netpoll_set_trap); | 926 | EXPORT_SYMBOL(netpoll_set_trap); |
912 | EXPORT_SYMBOL(netpoll_trap); | 927 | EXPORT_SYMBOL(netpoll_trap); |
913 | EXPORT_SYMBOL(netpoll_print_options); | 928 | EXPORT_SYMBOL(netpoll_print_options); |
@@ -915,4 +930,5 @@ EXPORT_SYMBOL(netpoll_parse_options); | |||
915 | EXPORT_SYMBOL(netpoll_setup); | 930 | EXPORT_SYMBOL(netpoll_setup); |
916 | EXPORT_SYMBOL(netpoll_cleanup); | 931 | EXPORT_SYMBOL(netpoll_cleanup); |
917 | EXPORT_SYMBOL(netpoll_send_udp); | 932 | EXPORT_SYMBOL(netpoll_send_udp); |
933 | EXPORT_SYMBOL(netpoll_poll_dev); | ||
918 | EXPORT_SYMBOL(netpoll_poll); | 934 | EXPORT_SYMBOL(netpoll_poll); |