aboutsummaryrefslogtreecommitdiffstats
path: root/net/core/netpoll.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/core/netpoll.c')
-rw-r--r--net/core/netpoll.c182
1 files changed, 106 insertions, 76 deletions
diff --git a/net/core/netpoll.c b/net/core/netpoll.c
index 94825b109551..537e01afd81b 100644
--- a/net/core/netpoll.c
+++ b/net/core/netpoll.c
@@ -199,11 +199,13 @@ void netpoll_poll_dev(struct net_device *dev)
199 199
200 zap_completion_queue(); 200 zap_completion_queue();
201} 201}
202EXPORT_SYMBOL(netpoll_poll_dev);
202 203
203void netpoll_poll(struct netpoll *np) 204void netpoll_poll(struct netpoll *np)
204{ 205{
205 netpoll_poll_dev(np->dev); 206 netpoll_poll_dev(np->dev);
206} 207}
208EXPORT_SYMBOL(netpoll_poll);
207 209
208static void refill_skbs(void) 210static void refill_skbs(void)
209{ 211{
@@ -292,6 +294,7 @@ void netpoll_send_skb(struct netpoll *np, struct sk_buff *skb)
292 unsigned long tries; 294 unsigned long tries;
293 struct net_device *dev = np->dev; 295 struct net_device *dev = np->dev;
294 const struct net_device_ops *ops = dev->netdev_ops; 296 const struct net_device_ops *ops = dev->netdev_ops;
297 /* It is up to the caller to keep npinfo alive. */
295 struct netpoll_info *npinfo = np->dev->npinfo; 298 struct netpoll_info *npinfo = np->dev->npinfo;
296 299
297 if (!npinfo || !netif_running(dev) || !netif_device_present(dev)) { 300 if (!npinfo || !netif_running(dev) || !netif_device_present(dev)) {
@@ -343,6 +346,7 @@ void netpoll_send_skb(struct netpoll *np, struct sk_buff *skb)
343 schedule_delayed_work(&npinfo->tx_work,0); 346 schedule_delayed_work(&npinfo->tx_work,0);
344 } 347 }
345} 348}
349EXPORT_SYMBOL(netpoll_send_skb);
346 350
347void netpoll_send_udp(struct netpoll *np, const char *msg, int len) 351void netpoll_send_udp(struct netpoll *np, const char *msg, int len)
348{ 352{
@@ -404,6 +408,7 @@ void netpoll_send_udp(struct netpoll *np, const char *msg, int len)
404 408
405 netpoll_send_skb(np, skb); 409 netpoll_send_skb(np, skb);
406} 410}
411EXPORT_SYMBOL(netpoll_send_udp);
407 412
408static void arp_reply(struct sk_buff *skb) 413static void arp_reply(struct sk_buff *skb)
409{ 414{
@@ -630,6 +635,7 @@ void netpoll_print_options(struct netpoll *np)
630 printk(KERN_INFO "%s: remote ethernet address %pM\n", 635 printk(KERN_INFO "%s: remote ethernet address %pM\n",
631 np->name, np->remote_mac); 636 np->name, np->remote_mac);
632} 637}
638EXPORT_SYMBOL(netpoll_print_options);
633 639
634int netpoll_parse_options(struct netpoll *np, char *opt) 640int netpoll_parse_options(struct netpoll *np, char *opt)
635{ 641{
@@ -722,30 +728,29 @@ int netpoll_parse_options(struct netpoll *np, char *opt)
722 np->name, cur); 728 np->name, cur);
723 return -1; 729 return -1;
724} 730}
731EXPORT_SYMBOL(netpoll_parse_options);
725 732
726int netpoll_setup(struct netpoll *np) 733int __netpoll_setup(struct netpoll *np)
727{ 734{
728 struct net_device *ndev = NULL; 735 struct net_device *ndev = np->dev;
729 struct in_device *in_dev;
730 struct netpoll_info *npinfo; 736 struct netpoll_info *npinfo;
731 struct netpoll *npe, *tmp; 737 const struct net_device_ops *ops;
732 unsigned long flags; 738 unsigned long flags;
733 int err; 739 int err;
734 740
735 if (np->dev_name) 741 if ((ndev->priv_flags & IFF_DISABLE_NETPOLL) ||
736 ndev = dev_get_by_name(&init_net, np->dev_name); 742 !ndev->netdev_ops->ndo_poll_controller) {
737 if (!ndev) { 743 printk(KERN_ERR "%s: %s doesn't support polling, aborting.\n",
738 printk(KERN_ERR "%s: %s doesn't exist, aborting.\n",
739 np->name, np->dev_name); 744 np->name, np->dev_name);
740 return -ENODEV; 745 err = -ENOTSUPP;
746 goto out;
741 } 747 }
742 748
743 np->dev = ndev;
744 if (!ndev->npinfo) { 749 if (!ndev->npinfo) {
745 npinfo = kmalloc(sizeof(*npinfo), GFP_KERNEL); 750 npinfo = kmalloc(sizeof(*npinfo), GFP_KERNEL);
746 if (!npinfo) { 751 if (!npinfo) {
747 err = -ENOMEM; 752 err = -ENOMEM;
748 goto put; 753 goto out;
749 } 754 }
750 755
751 npinfo->rx_flags = 0; 756 npinfo->rx_flags = 0;
@@ -757,6 +762,13 @@ int netpoll_setup(struct netpoll *np)
757 INIT_DELAYED_WORK(&npinfo->tx_work, queue_process); 762 INIT_DELAYED_WORK(&npinfo->tx_work, queue_process);
758 763
759 atomic_set(&npinfo->refcnt, 1); 764 atomic_set(&npinfo->refcnt, 1);
765
766 ops = np->dev->netdev_ops;
767 if (ops->ndo_netpoll_setup) {
768 err = ops->ndo_netpoll_setup(ndev, npinfo);
769 if (err)
770 goto free_npinfo;
771 }
760 } else { 772 } else {
761 npinfo = ndev->npinfo; 773 npinfo = ndev->npinfo;
762 atomic_inc(&npinfo->refcnt); 774 atomic_inc(&npinfo->refcnt);
@@ -764,12 +776,37 @@ int netpoll_setup(struct netpoll *np)
764 776
765 npinfo->netpoll = np; 777 npinfo->netpoll = np;
766 778
767 if ((ndev->priv_flags & IFF_DISABLE_NETPOLL) || 779 if (np->rx_hook) {
768 !ndev->netdev_ops->ndo_poll_controller) { 780 spin_lock_irqsave(&npinfo->rx_lock, flags);
769 printk(KERN_ERR "%s: %s doesn't support polling, aborting.\n", 781 npinfo->rx_flags |= NETPOLL_RX_ENABLED;
782 list_add_tail(&np->rx, &npinfo->rx_np);
783 spin_unlock_irqrestore(&npinfo->rx_lock, flags);
784 }
785
786 /* last thing to do is link it to the net device structure */
787 rcu_assign_pointer(ndev->npinfo, npinfo);
788
789 return 0;
790
791free_npinfo:
792 kfree(npinfo);
793out:
794 return err;
795}
796EXPORT_SYMBOL_GPL(__netpoll_setup);
797
798int netpoll_setup(struct netpoll *np)
799{
800 struct net_device *ndev = NULL;
801 struct in_device *in_dev;
802 int err;
803
804 if (np->dev_name)
805 ndev = dev_get_by_name(&init_net, np->dev_name);
806 if (!ndev) {
807 printk(KERN_ERR "%s: %s doesn't exist, aborting.\n",
770 np->name, np->dev_name); 808 np->name, np->dev_name);
771 err = -ENOTSUPP; 809 return -ENODEV;
772 goto release;
773 } 810 }
774 811
775 if (!netif_running(ndev)) { 812 if (!netif_running(ndev)) {
@@ -785,7 +822,7 @@ int netpoll_setup(struct netpoll *np)
785 if (err) { 822 if (err) {
786 printk(KERN_ERR "%s: failed to open %s\n", 823 printk(KERN_ERR "%s: failed to open %s\n",
787 np->name, ndev->name); 824 np->name, ndev->name);
788 goto release; 825 goto put;
789 } 826 }
790 827
791 atleast = jiffies + HZ/10; 828 atleast = jiffies + HZ/10;
@@ -822,7 +859,7 @@ int netpoll_setup(struct netpoll *np)
822 printk(KERN_ERR "%s: no IP address for %s, aborting\n", 859 printk(KERN_ERR "%s: no IP address for %s, aborting\n",
823 np->name, np->dev_name); 860 np->name, np->dev_name);
824 err = -EDESTADDRREQ; 861 err = -EDESTADDRREQ;
825 goto release; 862 goto put;
826 } 863 }
827 864
828 np->local_ip = in_dev->ifa_list->ifa_local; 865 np->local_ip = in_dev->ifa_list->ifa_local;
@@ -830,38 +867,25 @@ int netpoll_setup(struct netpoll *np)
830 printk(KERN_INFO "%s: local IP %pI4\n", np->name, &np->local_ip); 867 printk(KERN_INFO "%s: local IP %pI4\n", np->name, &np->local_ip);
831 } 868 }
832 869
833 if (np->rx_hook) { 870 np->dev = ndev;
834 spin_lock_irqsave(&npinfo->rx_lock, flags);
835 npinfo->rx_flags |= NETPOLL_RX_ENABLED;
836 list_add_tail(&np->rx, &npinfo->rx_np);
837 spin_unlock_irqrestore(&npinfo->rx_lock, flags);
838 }
839 871
840 /* fill up the skb queue */ 872 /* fill up the skb queue */
841 refill_skbs(); 873 refill_skbs();
842 874
843 /* last thing to do is link it to the net device structure */ 875 rtnl_lock();
844 ndev->npinfo = npinfo; 876 err = __netpoll_setup(np);
877 rtnl_unlock();
845 878
846 /* avoid racing with NAPI reading npinfo */ 879 if (err)
847 synchronize_rcu(); 880 goto put;
848 881
849 return 0; 882 return 0;
850 883
851 release:
852 if (!ndev->npinfo) {
853 spin_lock_irqsave(&npinfo->rx_lock, flags);
854 list_for_each_entry_safe(npe, tmp, &npinfo->rx_np, rx) {
855 npe->dev = NULL;
856 }
857 spin_unlock_irqrestore(&npinfo->rx_lock, flags);
858
859 kfree(npinfo);
860 }
861put: 884put:
862 dev_put(ndev); 885 dev_put(ndev);
863 return err; 886 return err;
864} 887}
888EXPORT_SYMBOL(netpoll_setup);
865 889
866static int __init netpoll_init(void) 890static int __init netpoll_init(void)
867{ 891{
@@ -870,49 +894,65 @@ static int __init netpoll_init(void)
870} 894}
871core_initcall(netpoll_init); 895core_initcall(netpoll_init);
872 896
873void netpoll_cleanup(struct netpoll *np) 897void __netpoll_cleanup(struct netpoll *np)
874{ 898{
875 struct netpoll_info *npinfo; 899 struct netpoll_info *npinfo;
876 unsigned long flags; 900 unsigned long flags;
877 901
878 if (np->dev) { 902 npinfo = np->dev->npinfo;
879 npinfo = np->dev->npinfo; 903 if (!npinfo)
880 if (npinfo) { 904 return;
881 if (!list_empty(&npinfo->rx_np)) {
882 spin_lock_irqsave(&npinfo->rx_lock, flags);
883 list_del(&np->rx);
884 if (list_empty(&npinfo->rx_np))
885 npinfo->rx_flags &= ~NETPOLL_RX_ENABLED;
886 spin_unlock_irqrestore(&npinfo->rx_lock, flags);
887 }
888 905
889 if (atomic_dec_and_test(&npinfo->refcnt)) { 906 if (!list_empty(&npinfo->rx_np)) {
890 const struct net_device_ops *ops; 907 spin_lock_irqsave(&npinfo->rx_lock, flags);
891 skb_queue_purge(&npinfo->arp_tx); 908 list_del(&np->rx);
892 skb_queue_purge(&npinfo->txq); 909 if (list_empty(&npinfo->rx_np))
893 cancel_rearming_delayed_work(&npinfo->tx_work); 910 npinfo->rx_flags &= ~NETPOLL_RX_ENABLED;
894 911 spin_unlock_irqrestore(&npinfo->rx_lock, flags);
895 /* clean after last, unfinished work */ 912 }
896 __skb_queue_purge(&npinfo->txq); 913
897 kfree(npinfo); 914 if (atomic_dec_and_test(&npinfo->refcnt)) {
898 ops = np->dev->netdev_ops; 915 const struct net_device_ops *ops;
899 if (ops->ndo_netpoll_cleanup) 916
900 ops->ndo_netpoll_cleanup(np->dev); 917 ops = np->dev->netdev_ops;
901 else 918 if (ops->ndo_netpoll_cleanup)
902 np->dev->npinfo = NULL; 919 ops->ndo_netpoll_cleanup(np->dev);
903 } 920
904 } 921 rcu_assign_pointer(np->dev->npinfo, NULL);
922
923 /* avoid racing with NAPI reading npinfo */
924 synchronize_rcu_bh();
925
926 skb_queue_purge(&npinfo->arp_tx);
927 skb_queue_purge(&npinfo->txq);
928 cancel_rearming_delayed_work(&npinfo->tx_work);
905 929
906 dev_put(np->dev); 930 /* clean after last, unfinished work */
931 __skb_queue_purge(&npinfo->txq);
932 kfree(npinfo);
907 } 933 }
934}
935EXPORT_SYMBOL_GPL(__netpoll_cleanup);
936
937void netpoll_cleanup(struct netpoll *np)
938{
939 if (!np->dev)
940 return;
908 941
942 rtnl_lock();
943 __netpoll_cleanup(np);
944 rtnl_unlock();
945
946 dev_put(np->dev);
909 np->dev = NULL; 947 np->dev = NULL;
910} 948}
949EXPORT_SYMBOL(netpoll_cleanup);
911 950
912int netpoll_trap(void) 951int netpoll_trap(void)
913{ 952{
914 return atomic_read(&trapped); 953 return atomic_read(&trapped);
915} 954}
955EXPORT_SYMBOL(netpoll_trap);
916 956
917void netpoll_set_trap(int trap) 957void netpoll_set_trap(int trap)
918{ 958{
@@ -921,14 +961,4 @@ void netpoll_set_trap(int trap)
921 else 961 else
922 atomic_dec(&trapped); 962 atomic_dec(&trapped);
923} 963}
924
925EXPORT_SYMBOL(netpoll_send_skb);
926EXPORT_SYMBOL(netpoll_set_trap); 964EXPORT_SYMBOL(netpoll_set_trap);
927EXPORT_SYMBOL(netpoll_trap);
928EXPORT_SYMBOL(netpoll_print_options);
929EXPORT_SYMBOL(netpoll_parse_options);
930EXPORT_SYMBOL(netpoll_setup);
931EXPORT_SYMBOL(netpoll_cleanup);
932EXPORT_SYMBOL(netpoll_send_udp);
933EXPORT_SYMBOL(netpoll_poll_dev);
934EXPORT_SYMBOL(netpoll_poll);