Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

netvsc: refactor notifier/event handling code to use the failover framework

Use the registration/notification framework supported by the generic
failover infrastructure.

Signed-off-by: Sridhar Samudrala <sridhar.samudrala@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Sridhar Samudrala and committed by
David S. Miller
1ff78076 30c8bd5a

+60 -165
+1
drivers/net/hyperv/Kconfig
··· 2 2 tristate "Microsoft Hyper-V virtual network driver" 3 3 depends on HYPERV 4 4 select UCS2_STRING 5 + select FAILOVER 5 6 help 6 7 Select this option to enable the Hyper-V virtual network driver.
+2
drivers/net/hyperv/hyperv_net.h
··· 932 932 u32 vf_alloc; 933 933 /* Serial number of the VF to team with */ 934 934 u32 vf_serial; 935 + 936 + struct failover *failover; 935 937 }; 936 938 937 939 /* Per channel data */
+57 -165
drivers/net/hyperv/netvsc_drv.c
··· 43 43 #include <net/pkt_sched.h> 44 44 #include <net/checksum.h> 45 45 #include <net/ip6_checksum.h> 46 + #include <net/failover.h> 46 47 47 48 #include "hyperv_net.h" 48 49 ··· 1780 1779 rtnl_unlock(); 1781 1780 } 1782 1781 1783 - static struct net_device *get_netvsc_bymac(const u8 *mac) 1784 - { 1785 - struct net_device *dev; 1786 - 1787 - ASSERT_RTNL(); 1788 - 1789 - for_each_netdev(&init_net, dev) { 1790 - if (dev->netdev_ops != &device_ops) 1791 - continue; /* not a netvsc device */ 1792 - 1793 - if (ether_addr_equal(mac, dev->perm_addr)) 1794 - return dev; 1795 - } 1796 - 1797 - return NULL; 1798 - } 1799 - 1800 - static struct net_device *get_netvsc_byref(struct net_device *vf_netdev) 1801 - { 1802 - struct net_device *dev; 1803 - 1804 - ASSERT_RTNL(); 1805 - 1806 - for_each_netdev(&init_net, dev) { 1807 - struct net_device_context *net_device_ctx; 1808 - 1809 - if (dev->netdev_ops != &device_ops) 1810 - continue; /* not a netvsc device */ 1811 - 1812 - net_device_ctx = netdev_priv(dev); 1813 - if (!rtnl_dereference(net_device_ctx->nvdev)) 1814 - continue; /* device is removed */ 1815 - 1816 - if (rtnl_dereference(net_device_ctx->vf_netdev) == vf_netdev) 1817 - return dev; /* a match */ 1818 - } 1819 - 1820 - return NULL; 1821 - } 1822 - 1823 1782 /* Called when VF is injecting data into network stack. 1824 1783 * Change the associated network device from VF to netvsc. 1825 1784 * note: already called with rcu_read_lock ··· 1800 1839 u64_stats_update_end(&pcpu_stats->syncp); 1801 1840 1802 1841 return RX_HANDLER_ANOTHER; 1803 - } 1804 - 1805 - static int netvsc_vf_join(struct net_device *vf_netdev, 1806 - struct net_device *ndev) 1807 - { 1808 - struct net_device_context *ndev_ctx = netdev_priv(ndev); 1809 - int ret; 1810 - 1811 - ret = netdev_rx_handler_register(vf_netdev, 1812 - netvsc_vf_handle_frame, ndev); 1813 - if (ret != 0) { 1814 - netdev_err(vf_netdev, 1815 - "can not register netvsc VF receive handler (err = %d)\n", 1816 - ret); 1817 - goto rx_handler_failed; 1818 - } 1819 - 1820 - ret = netdev_master_upper_dev_link(vf_netdev, ndev, 1821 - NULL, NULL, NULL); 1822 - if (ret != 0) { 1823 - netdev_err(vf_netdev, 1824 - "can not set master device %s (err = %d)\n", 1825 - ndev->name, ret); 1826 - goto upper_link_failed; 1827 - } 1828 - 1829 - /* set slave flag before open to prevent IPv6 addrconf */ 1830 - vf_netdev->flags |= IFF_SLAVE; 1831 - 1832 - schedule_delayed_work(&ndev_ctx->vf_takeover, VF_TAKEOVER_INT); 1833 - 1834 - call_netdevice_notifiers(NETDEV_JOIN, vf_netdev); 1835 - 1836 - netdev_info(vf_netdev, "joined to %s\n", ndev->name); 1837 - return 0; 1838 - 1839 - upper_link_failed: 1840 - netdev_rx_handler_unregister(vf_netdev); 1841 - rx_handler_failed: 1842 - return ret; 1843 1842 } 1844 1843 1845 1844 static void __netvsc_vf_setup(struct net_device *ndev, ··· 1852 1931 rtnl_unlock(); 1853 1932 } 1854 1933 1855 - static int netvsc_register_vf(struct net_device *vf_netdev) 1934 + static int netvsc_pre_register_vf(struct net_device *vf_netdev, 1935 + struct net_device *ndev) 1856 1936 { 1857 - struct net_device *ndev; 1858 1937 struct net_device_context *net_device_ctx; 1859 1938 struct netvsc_device *netvsc_dev; 1860 - 1861 - if (vf_netdev->addr_len != ETH_ALEN) 1862 - return NOTIFY_DONE; 1863 - 1864 - /* 1865 - * We will use the MAC address to locate the synthetic interface to 1866 - * associate with the VF interface. If we don't find a matching 1867 - * synthetic interface, move on. 1868 - */ 1869 - ndev = get_netvsc_bymac(vf_netdev->perm_addr); 1870 - if (!ndev) 1871 - return NOTIFY_DONE; 1872 1939 1873 1940 net_device_ctx = netdev_priv(ndev); 1874 1941 netvsc_dev = rtnl_dereference(net_device_ctx->nvdev); 1875 1942 if (!netvsc_dev || rtnl_dereference(net_device_ctx->vf_netdev)) 1876 - return NOTIFY_DONE; 1943 + return -ENODEV; 1877 1944 1878 - if (netvsc_vf_join(vf_netdev, ndev) != 0) 1879 - return NOTIFY_DONE; 1945 + return 0; 1946 + } 1880 1947 1881 - netdev_info(ndev, "VF registering: %s\n", vf_netdev->name); 1948 + static int netvsc_register_vf(struct net_device *vf_netdev, 1949 + struct net_device *ndev) 1950 + { 1951 + struct net_device_context *ndev_ctx = netdev_priv(ndev); 1952 + 1953 + /* set slave flag before open to prevent IPv6 addrconf */ 1954 + vf_netdev->flags |= IFF_SLAVE; 1955 + 1956 + schedule_delayed_work(&ndev_ctx->vf_takeover, VF_TAKEOVER_INT); 1957 + 1958 + call_netdevice_notifiers(NETDEV_JOIN, vf_netdev); 1959 + 1960 + netdev_info(vf_netdev, "joined to %s\n", ndev->name); 1882 1961 1883 1962 dev_hold(vf_netdev); 1884 - rcu_assign_pointer(net_device_ctx->vf_netdev, vf_netdev); 1885 - return NOTIFY_OK; 1963 + rcu_assign_pointer(ndev_ctx->vf_netdev, vf_netdev); 1964 + 1965 + return 0; 1886 1966 } 1887 1967 1888 1968 /* VF up/down change detected, schedule to change data path */ 1889 - static int netvsc_vf_changed(struct net_device *vf_netdev) 1969 + static int netvsc_vf_changed(struct net_device *vf_netdev, 1970 + struct net_device *ndev) 1890 1971 { 1891 1972 struct net_device_context *net_device_ctx; 1892 1973 struct netvsc_device *netvsc_dev; 1893 - struct net_device *ndev; 1894 1974 bool vf_is_up = netif_running(vf_netdev); 1895 - 1896 - ndev = get_netvsc_byref(vf_netdev); 1897 - if (!ndev) 1898 - return NOTIFY_DONE; 1899 1975 1900 1976 net_device_ctx = netdev_priv(ndev); 1901 1977 netvsc_dev = rtnl_dereference(net_device_ctx->nvdev); 1902 1978 if (!netvsc_dev) 1903 - return NOTIFY_DONE; 1979 + return -ENODEV; 1904 1980 1905 1981 netvsc_switch_datapath(ndev, vf_is_up); 1906 1982 netdev_info(ndev, "Data path switched %s VF: %s\n", 1907 1983 vf_is_up ? "to" : "from", vf_netdev->name); 1908 1984 1909 - return NOTIFY_OK; 1985 + return 0; 1910 1986 } 1911 1987 1912 - static int netvsc_unregister_vf(struct net_device *vf_netdev) 1988 + static int netvsc_pre_unregister_vf(struct net_device *vf_netdev, 1989 + struct net_device *ndev) 1913 1990 { 1914 - struct net_device *ndev; 1915 1991 struct net_device_context *net_device_ctx; 1916 - 1917 - ndev = get_netvsc_byref(vf_netdev); 1918 - if (!ndev) 1919 - return NOTIFY_DONE; 1920 1992 1921 1993 net_device_ctx = netdev_priv(ndev); 1922 1994 cancel_delayed_work_sync(&net_device_ctx->vf_takeover); 1923 1995 1996 + return 0; 1997 + } 1998 + 1999 + static int netvsc_unregister_vf(struct net_device *vf_netdev, 2000 + struct net_device *ndev) 2001 + { 2002 + struct net_device_context *net_device_ctx; 2003 + 2004 + net_device_ctx = netdev_priv(ndev); 2005 + 1924 2006 netdev_info(ndev, "VF unregistering: %s\n", vf_netdev->name); 1925 2007 1926 - netdev_rx_handler_unregister(vf_netdev); 1927 - netdev_upper_dev_unlink(vf_netdev, ndev); 1928 2008 RCU_INIT_POINTER(net_device_ctx->vf_netdev, NULL); 1929 2009 dev_put(vf_netdev); 1930 2010 1931 - return NOTIFY_OK; 2011 + return 0; 1932 2012 } 2013 + 2014 + static struct failover_ops netvsc_failover_ops = { 2015 + .slave_pre_register = netvsc_pre_register_vf, 2016 + .slave_register = netvsc_register_vf, 2017 + .slave_pre_unregister = netvsc_pre_unregister_vf, 2018 + .slave_unregister = netvsc_unregister_vf, 2019 + .slave_link_change = netvsc_vf_changed, 2020 + .slave_handle_frame = netvsc_vf_handle_frame, 2021 + }; 1933 2022 1934 2023 static int netvsc_probe(struct hv_device *dev, 1935 2024 const struct hv_vmbus_device_id *dev_id) ··· 2030 2099 goto register_failed; 2031 2100 } 2032 2101 2102 + net_device_ctx->failover = failover_register(net, &netvsc_failover_ops); 2103 + if (IS_ERR(net_device_ctx->failover)) 2104 + goto err_failover; 2105 + 2033 2106 return ret; 2034 2107 2108 + err_failover: 2109 + unregister_netdev(net); 2035 2110 register_failed: 2036 2111 rndis_filter_device_remove(dev, nvdev); 2037 2112 rndis_failed: ··· 2078 2141 rtnl_lock(); 2079 2142 vf_netdev = rtnl_dereference(ndev_ctx->vf_netdev); 2080 2143 if (vf_netdev) 2081 - netvsc_unregister_vf(vf_netdev); 2144 + failover_slave_unregister(vf_netdev); 2082 2145 2083 2146 if (nvdev) 2084 2147 rndis_filter_device_remove(dev, nvdev); 2085 2148 2086 2149 unregister_netdevice(net); 2150 + 2151 + failover_unregister(ndev_ctx->failover); 2087 2152 2088 2153 rtnl_unlock(); 2089 2154 rcu_read_unlock(); ··· 2113 2174 .remove = netvsc_remove, 2114 2175 }; 2115 2176 2116 - /* 2117 - * On Hyper-V, every VF interface is matched with a corresponding 2118 - * synthetic interface. The synthetic interface is presented first 2119 - * to the guest. When the corresponding VF instance is registered, 2120 - * we will take care of switching the data path. 2121 - */ 2122 - static int netvsc_netdev_event(struct notifier_block *this, 2123 - unsigned long event, void *ptr) 2124 - { 2125 - struct net_device *event_dev = netdev_notifier_info_to_dev(ptr); 2126 - 2127 - /* Skip our own events */ 2128 - if (event_dev->netdev_ops == &device_ops) 2129 - return NOTIFY_DONE; 2130 - 2131 - /* Avoid non-Ethernet type devices */ 2132 - if (event_dev->type != ARPHRD_ETHER) 2133 - return NOTIFY_DONE; 2134 - 2135 - /* Avoid Vlan dev with same MAC registering as VF */ 2136 - if (is_vlan_dev(event_dev)) 2137 - return NOTIFY_DONE; 2138 - 2139 - /* Avoid Bonding master dev with same MAC registering as VF */ 2140 - if ((event_dev->priv_flags & IFF_BONDING) && 2141 - (event_dev->flags & IFF_MASTER)) 2142 - return NOTIFY_DONE; 2143 - 2144 - switch (event) { 2145 - case NETDEV_REGISTER: 2146 - return netvsc_register_vf(event_dev); 2147 - case NETDEV_UNREGISTER: 2148 - return netvsc_unregister_vf(event_dev); 2149 - case NETDEV_UP: 2150 - case NETDEV_DOWN: 2151 - return netvsc_vf_changed(event_dev); 2152 - default: 2153 - return NOTIFY_DONE; 2154 - } 2155 - } 2156 - 2157 - static struct notifier_block netvsc_netdev_notifier = { 2158 - .notifier_call = netvsc_netdev_event, 2159 - }; 2160 - 2161 2177 static void __exit netvsc_drv_exit(void) 2162 2178 { 2163 - unregister_netdevice_notifier(&netvsc_netdev_notifier); 2164 2179 vmbus_driver_unregister(&netvsc_drv); 2165 2180 } 2166 2181 ··· 2134 2241 if (ret) 2135 2242 return ret; 2136 2243 2137 - register_netdevice_notifier(&netvsc_netdev_notifier); 2138 2244 return 0; 2139 2245 } 2140 2246