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); |
