11da177e4SLinus Torvalds /* 21da177e4SLinus Torvalds * Copyright (c) 2004 Topspin Communications. All rights reserved. 32a1d9b7fSRoland Dreier * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved. 42a1d9b7fSRoland Dreier * Copyright (c) 2004 Voltaire, Inc. All rights reserved. 51da177e4SLinus Torvalds * 61da177e4SLinus Torvalds * This software is available to you under a choice of one of two 71da177e4SLinus Torvalds * licenses. You may choose to be licensed under the terms of the GNU 81da177e4SLinus Torvalds * General Public License (GPL) Version 2, available from the file 91da177e4SLinus Torvalds * COPYING in the main directory of this source tree, or the 101da177e4SLinus Torvalds * OpenIB.org BSD license below: 111da177e4SLinus Torvalds * 121da177e4SLinus Torvalds * Redistribution and use in source and binary forms, with or 131da177e4SLinus Torvalds * without modification, are permitted provided that the following 141da177e4SLinus Torvalds * conditions are met: 151da177e4SLinus Torvalds * 161da177e4SLinus Torvalds * - Redistributions of source code must retain the above 171da177e4SLinus Torvalds * copyright notice, this list of conditions and the following 181da177e4SLinus Torvalds * disclaimer. 191da177e4SLinus Torvalds * 201da177e4SLinus Torvalds * - Redistributions in binary form must reproduce the above 211da177e4SLinus Torvalds * copyright notice, this list of conditions and the following 221da177e4SLinus Torvalds * disclaimer in the documentation and/or other materials 231da177e4SLinus Torvalds * provided with the distribution. 241da177e4SLinus Torvalds * 251da177e4SLinus Torvalds * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 261da177e4SLinus Torvalds * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 271da177e4SLinus Torvalds * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 281da177e4SLinus Torvalds * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 291da177e4SLinus Torvalds * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 301da177e4SLinus Torvalds * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 311da177e4SLinus Torvalds * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 321da177e4SLinus Torvalds * SOFTWARE. 331da177e4SLinus Torvalds */ 341da177e4SLinus Torvalds 351da177e4SLinus Torvalds #include "ipoib.h" 361da177e4SLinus Torvalds 371da177e4SLinus Torvalds #include <linux/module.h> 381da177e4SLinus Torvalds 391da177e4SLinus Torvalds #include <linux/init.h> 401da177e4SLinus Torvalds #include <linux/slab.h> 410f485251SShirley Ma #include <linux/kernel.h> 4210313cbbSRoland Dreier #include <linux/vmalloc.h> 431da177e4SLinus Torvalds 441da177e4SLinus Torvalds #include <linux/if_arp.h> /* For ARPHRD_xxx */ 451da177e4SLinus Torvalds 461da177e4SLinus Torvalds #include <linux/ip.h> 471da177e4SLinus Torvalds #include <linux/in.h> 481da177e4SLinus Torvalds 49b63b70d8SShlomo Pongratz #include <linux/jhash.h> 50b63b70d8SShlomo Pongratz #include <net/arp.h> 51ddde896eSGuy Shapiro #include <net/addrconf.h> 52ddde896eSGuy Shapiro #include <linux/inetdevice.h> 53ddde896eSGuy Shapiro #include <rdma/ib_cache.h> 549c3c5f8eSEli Cohen #include <linux/pci.h> 5514c85021SArnaldo Carvalho de Melo 564b48680bSYan Burman #define DRV_VERSION "1.0.0" 574b48680bSYan Burman 584b48680bSYan Burman const char ipoib_driver_version[] = DRV_VERSION; 594b48680bSYan Burman 601da177e4SLinus Torvalds MODULE_AUTHOR("Roland Dreier"); 611da177e4SLinus Torvalds MODULE_DESCRIPTION("IP-over-InfiniBand net driver"); 621da177e4SLinus Torvalds MODULE_LICENSE("Dual BSD/GPL"); 634b48680bSYan Burman MODULE_VERSION(DRV_VERSION); 641da177e4SLinus Torvalds 650f485251SShirley Ma int ipoib_sendq_size __read_mostly = IPOIB_TX_RING_SIZE; 660f485251SShirley Ma int ipoib_recvq_size __read_mostly = IPOIB_RX_RING_SIZE; 670f485251SShirley Ma 680f485251SShirley Ma module_param_named(send_queue_size, ipoib_sendq_size, int, 0444); 690f485251SShirley Ma MODULE_PARM_DESC(send_queue_size, "Number of descriptors in send queue"); 700f485251SShirley Ma module_param_named(recv_queue_size, ipoib_recvq_size, int, 0444); 710f485251SShirley Ma MODULE_PARM_DESC(recv_queue_size, "Number of descriptors in receive queue"); 720f485251SShirley Ma 731da177e4SLinus Torvalds #ifdef CONFIG_INFINIBAND_IPOIB_DEBUG 741da177e4SLinus Torvalds int ipoib_debug_level; 751da177e4SLinus Torvalds 761da177e4SLinus Torvalds module_param_named(debug_level, ipoib_debug_level, int, 0644); 771da177e4SLinus Torvalds MODULE_PARM_DESC(debug_level, "Enable debug tracing if > 0"); 781da177e4SLinus Torvalds #endif 791da177e4SLinus Torvalds 801732b0efSRoland Dreier struct ipoib_path_iter { 811732b0efSRoland Dreier struct net_device *dev; 821732b0efSRoland Dreier struct ipoib_path path; 831732b0efSRoland Dreier }; 841732b0efSRoland Dreier 851da177e4SLinus Torvalds static const u8 ipv4_bcast_addr[] = { 861da177e4SLinus Torvalds 0x00, 0xff, 0xff, 0xff, 871da177e4SLinus Torvalds 0xff, 0x12, 0x40, 0x1b, 0x00, 0x00, 0x00, 0x00, 881da177e4SLinus Torvalds 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff 891da177e4SLinus Torvalds }; 901da177e4SLinus Torvalds 911da177e4SLinus Torvalds struct workqueue_struct *ipoib_workqueue; 921da177e4SLinus Torvalds 93c1a0b23bSMichael S. Tsirkin struct ib_sa_client ipoib_sa_client; 94c1a0b23bSMichael S. Tsirkin 951da177e4SLinus Torvalds static void ipoib_add_one(struct ib_device *device); 967c1eb45aSHaggai Eran static void ipoib_remove_one(struct ib_device *device, void *client_data); 97b63b70d8SShlomo Pongratz static void ipoib_neigh_reclaim(struct rcu_head *rp); 98ddde896eSGuy Shapiro static struct net_device *ipoib_get_net_dev_by_params( 99ddde896eSGuy Shapiro struct ib_device *dev, u8 port, u16 pkey, 100ddde896eSGuy Shapiro const union ib_gid *gid, const struct sockaddr *addr, 101ddde896eSGuy Shapiro void *client_data); 102492a7e67SMark Bloch static int ipoib_set_mac(struct net_device *dev, void *addr); 1031da177e4SLinus Torvalds 1041da177e4SLinus Torvalds static struct ib_client ipoib_client = { 1051da177e4SLinus Torvalds .name = "ipoib", 1061da177e4SLinus Torvalds .add = ipoib_add_one, 107ddde896eSGuy Shapiro .remove = ipoib_remove_one, 108ddde896eSGuy Shapiro .get_net_dev_by_params = ipoib_get_net_dev_by_params, 1091da177e4SLinus Torvalds }; 1101da177e4SLinus Torvalds 1111da177e4SLinus Torvalds int ipoib_open(struct net_device *dev) 1121da177e4SLinus Torvalds { 1131da177e4SLinus Torvalds struct ipoib_dev_priv *priv = netdev_priv(dev); 1141da177e4SLinus Torvalds 1151da177e4SLinus Torvalds ipoib_dbg(priv, "bringing up interface\n"); 1161da177e4SLinus Torvalds 117437708c4SMichal Schmidt netif_carrier_off(dev); 118437708c4SMichal Schmidt 119e028cc55SYossi Etigin set_bit(IPOIB_FLAG_ADMIN_UP, &priv->flags); 1201da177e4SLinus Torvalds 1213b561130SErez Shitrit priv->sm_fullmember_sendonly_support = false; 1223b561130SErez Shitrit 123efc82eeeSDoug Ledford if (ipoib_ib_dev_open(dev)) { 124db84f880SErez Shitrit if (!test_bit(IPOIB_PKEY_ASSIGNED, &priv->flags)) 1251da177e4SLinus Torvalds return 0; 126b8a1b1ceSRoland Dreier goto err_disable; 127dd57c930SAlex Estrin } 128fe25c561SYossi Etigin 129b8a1b1ceSRoland Dreier if (ipoib_ib_dev_up(dev)) 130b8a1b1ceSRoland Dreier goto err_stop; 1311da177e4SLinus Torvalds 1321da177e4SLinus Torvalds if (!test_bit(IPOIB_FLAG_SUBINTERFACE, &priv->flags)) { 1331da177e4SLinus Torvalds struct ipoib_dev_priv *cpriv; 1341da177e4SLinus Torvalds 1351da177e4SLinus Torvalds /* Bring up any child interfaces too */ 136f47944ccSErez Shitrit down_read(&priv->vlan_rwsem); 1371da177e4SLinus Torvalds list_for_each_entry(cpriv, &priv->child_intfs, list) { 1381da177e4SLinus Torvalds int flags; 1391da177e4SLinus Torvalds 1401da177e4SLinus Torvalds flags = cpriv->dev->flags; 1411da177e4SLinus Torvalds if (flags & IFF_UP) 1421da177e4SLinus Torvalds continue; 1431da177e4SLinus Torvalds 1441da177e4SLinus Torvalds dev_change_flags(cpriv->dev, flags | IFF_UP); 1451da177e4SLinus Torvalds } 146f47944ccSErez Shitrit up_read(&priv->vlan_rwsem); 1471da177e4SLinus Torvalds } 1481da177e4SLinus Torvalds 1491da177e4SLinus Torvalds netif_start_queue(dev); 1501da177e4SLinus Torvalds 1511da177e4SLinus Torvalds return 0; 152b8a1b1ceSRoland Dreier 153b8a1b1ceSRoland Dreier err_stop: 154efc82eeeSDoug Ledford ipoib_ib_dev_stop(dev); 155b8a1b1ceSRoland Dreier 156b8a1b1ceSRoland Dreier err_disable: 157b8a1b1ceSRoland Dreier clear_bit(IPOIB_FLAG_ADMIN_UP, &priv->flags); 158b8a1b1ceSRoland Dreier 159b8a1b1ceSRoland Dreier return -EINVAL; 1601da177e4SLinus Torvalds } 1611da177e4SLinus Torvalds 1621da177e4SLinus Torvalds static int ipoib_stop(struct net_device *dev) 1631da177e4SLinus Torvalds { 1641da177e4SLinus Torvalds struct ipoib_dev_priv *priv = netdev_priv(dev); 1651da177e4SLinus Torvalds 1661da177e4SLinus Torvalds ipoib_dbg(priv, "stopping interface\n"); 1671da177e4SLinus Torvalds 1681da177e4SLinus Torvalds clear_bit(IPOIB_FLAG_ADMIN_UP, &priv->flags); 1691da177e4SLinus Torvalds 1701da177e4SLinus Torvalds netif_stop_queue(dev); 1711da177e4SLinus Torvalds 172efc82eeeSDoug Ledford ipoib_ib_dev_down(dev); 173efc82eeeSDoug Ledford ipoib_ib_dev_stop(dev); 1741da177e4SLinus Torvalds 1751da177e4SLinus Torvalds if (!test_bit(IPOIB_FLAG_SUBINTERFACE, &priv->flags)) { 1761da177e4SLinus Torvalds struct ipoib_dev_priv *cpriv; 1771da177e4SLinus Torvalds 1781da177e4SLinus Torvalds /* Bring down any child interfaces too */ 179f47944ccSErez Shitrit down_read(&priv->vlan_rwsem); 1801da177e4SLinus Torvalds list_for_each_entry(cpriv, &priv->child_intfs, list) { 1811da177e4SLinus Torvalds int flags; 1821da177e4SLinus Torvalds 1831da177e4SLinus Torvalds flags = cpriv->dev->flags; 1841da177e4SLinus Torvalds if (!(flags & IFF_UP)) 1851da177e4SLinus Torvalds continue; 1861da177e4SLinus Torvalds 1871da177e4SLinus Torvalds dev_change_flags(cpriv->dev, flags & ~IFF_UP); 1881da177e4SLinus Torvalds } 189f47944ccSErez Shitrit up_read(&priv->vlan_rwsem); 1901da177e4SLinus Torvalds } 1911da177e4SLinus Torvalds 1921da177e4SLinus Torvalds return 0; 1931da177e4SLinus Torvalds } 1941da177e4SLinus Torvalds 1959baa0b03SOr Gerlitz static void ipoib_uninit(struct net_device *dev) 1969baa0b03SOr Gerlitz { 1979baa0b03SOr Gerlitz ipoib_dev_cleanup(dev); 1989baa0b03SOr Gerlitz } 1999baa0b03SOr Gerlitz 2009ca36f7dSDavid S. Miller static netdev_features_t ipoib_fix_features(struct net_device *dev, netdev_features_t features) 2013d96c74dSMichał Mirosław { 2023d96c74dSMichał Mirosław struct ipoib_dev_priv *priv = netdev_priv(dev); 2033d96c74dSMichał Mirosław 2043d96c74dSMichał Mirosław if (test_bit(IPOIB_FLAG_ADMIN_CM, &priv->flags)) 205c4268778SYuval Shaia features &= ~(NETIF_F_IP_CSUM | NETIF_F_TSO); 2063d96c74dSMichał Mirosław 2073d96c74dSMichał Mirosław return features; 2083d96c74dSMichał Mirosław } 2093d96c74dSMichał Mirosław 2101da177e4SLinus Torvalds static int ipoib_change_mtu(struct net_device *dev, int new_mtu) 2111da177e4SLinus Torvalds { 2121da177e4SLinus Torvalds struct ipoib_dev_priv *priv = netdev_priv(dev); 2131da177e4SLinus Torvalds 214839fcabaSMichael S. Tsirkin /* dev->mtu > 2K ==> connected mode */ 215586a6934SPradeep Satyanarayana if (ipoib_cm_admin_enabled(dev)) { 216586a6934SPradeep Satyanarayana if (new_mtu > ipoib_cm_max_mtu(dev)) 217586a6934SPradeep Satyanarayana return -EINVAL; 218586a6934SPradeep Satyanarayana 219839fcabaSMichael S. Tsirkin if (new_mtu > priv->mcast_mtu) 220839fcabaSMichael S. Tsirkin ipoib_warn(priv, "mtu > %d will cause multicast packet drops.\n", 221839fcabaSMichael S. Tsirkin priv->mcast_mtu); 222586a6934SPradeep Satyanarayana 223839fcabaSMichael S. Tsirkin dev->mtu = new_mtu; 224839fcabaSMichael S. Tsirkin return 0; 225839fcabaSMichael S. Tsirkin } 226839fcabaSMichael S. Tsirkin 227bc7b3a36SShirley Ma if (new_mtu > IPOIB_UD_MTU(priv->max_ib_mtu)) 2281da177e4SLinus Torvalds return -EINVAL; 2291da177e4SLinus Torvalds 2301da177e4SLinus Torvalds priv->admin_mtu = new_mtu; 2311da177e4SLinus Torvalds 23229da686dSFeras Daoud if (priv->mcast_mtu < priv->admin_mtu) 23329da686dSFeras Daoud ipoib_dbg(priv, "MTU must be smaller than the underlying " 23429da686dSFeras Daoud "link layer MTU - 4 (%u)\n", priv->mcast_mtu); 23529da686dSFeras Daoud 2361da177e4SLinus Torvalds dev->mtu = min(priv->mcast_mtu, priv->admin_mtu); 2371da177e4SLinus Torvalds 2381da177e4SLinus Torvalds return 0; 2391da177e4SLinus Torvalds } 2401da177e4SLinus Torvalds 241ddde896eSGuy Shapiro /* Called with an RCU read lock taken */ 242ddde896eSGuy Shapiro static bool ipoib_is_dev_match_addr_rcu(const struct sockaddr *addr, 243ddde896eSGuy Shapiro struct net_device *dev) 244ddde896eSGuy Shapiro { 245ddde896eSGuy Shapiro struct net *net = dev_net(dev); 246ddde896eSGuy Shapiro struct in_device *in_dev; 247ddde896eSGuy Shapiro struct sockaddr_in *addr_in = (struct sockaddr_in *)addr; 248ddde896eSGuy Shapiro struct sockaddr_in6 *addr_in6 = (struct sockaddr_in6 *)addr; 249ddde896eSGuy Shapiro __be32 ret_addr; 250ddde896eSGuy Shapiro 251ddde896eSGuy Shapiro switch (addr->sa_family) { 252ddde896eSGuy Shapiro case AF_INET: 253ddde896eSGuy Shapiro in_dev = in_dev_get(dev); 254ddde896eSGuy Shapiro if (!in_dev) 255ddde896eSGuy Shapiro return false; 256ddde896eSGuy Shapiro 257ddde896eSGuy Shapiro ret_addr = inet_confirm_addr(net, in_dev, 0, 258ddde896eSGuy Shapiro addr_in->sin_addr.s_addr, 259ddde896eSGuy Shapiro RT_SCOPE_HOST); 260ddde896eSGuy Shapiro in_dev_put(in_dev); 261ddde896eSGuy Shapiro if (ret_addr) 262ddde896eSGuy Shapiro return true; 263ddde896eSGuy Shapiro 264ddde896eSGuy Shapiro break; 265ddde896eSGuy Shapiro case AF_INET6: 266ddde896eSGuy Shapiro if (IS_ENABLED(CONFIG_IPV6) && 267ddde896eSGuy Shapiro ipv6_chk_addr(net, &addr_in6->sin6_addr, dev, 1)) 268ddde896eSGuy Shapiro return true; 269ddde896eSGuy Shapiro 270ddde896eSGuy Shapiro break; 271ddde896eSGuy Shapiro } 272ddde896eSGuy Shapiro return false; 273ddde896eSGuy Shapiro } 274ddde896eSGuy Shapiro 275ddde896eSGuy Shapiro /** 276ddde896eSGuy Shapiro * Find the master net_device on top of the given net_device. 277ddde896eSGuy Shapiro * @dev: base IPoIB net_device 278ddde896eSGuy Shapiro * 279ddde896eSGuy Shapiro * Returns the master net_device with a reference held, or the same net_device 280ddde896eSGuy Shapiro * if no master exists. 281ddde896eSGuy Shapiro */ 282ddde896eSGuy Shapiro static struct net_device *ipoib_get_master_net_dev(struct net_device *dev) 283ddde896eSGuy Shapiro { 284ddde896eSGuy Shapiro struct net_device *master; 285ddde896eSGuy Shapiro 286ddde896eSGuy Shapiro rcu_read_lock(); 287ddde896eSGuy Shapiro master = netdev_master_upper_dev_get_rcu(dev); 288ddde896eSGuy Shapiro if (master) 289ddde896eSGuy Shapiro dev_hold(master); 290ddde896eSGuy Shapiro rcu_read_unlock(); 291ddde896eSGuy Shapiro 292ddde896eSGuy Shapiro if (master) 293ddde896eSGuy Shapiro return master; 294ddde896eSGuy Shapiro 295ddde896eSGuy Shapiro dev_hold(dev); 296ddde896eSGuy Shapiro return dev; 297ddde896eSGuy Shapiro } 298ddde896eSGuy Shapiro 299e0e79c8eSDavid Ahern struct ipoib_walk_data { 300e0e79c8eSDavid Ahern const struct sockaddr *addr; 301e0e79c8eSDavid Ahern struct net_device *result; 302e0e79c8eSDavid Ahern }; 303e0e79c8eSDavid Ahern 304e0e79c8eSDavid Ahern static int ipoib_upper_walk(struct net_device *upper, void *_data) 305e0e79c8eSDavid Ahern { 306e0e79c8eSDavid Ahern struct ipoib_walk_data *data = _data; 307e0e79c8eSDavid Ahern int ret = 0; 308e0e79c8eSDavid Ahern 309e0e79c8eSDavid Ahern if (ipoib_is_dev_match_addr_rcu(data->addr, upper)) { 310e0e79c8eSDavid Ahern dev_hold(upper); 311e0e79c8eSDavid Ahern data->result = upper; 312e0e79c8eSDavid Ahern ret = 1; 313e0e79c8eSDavid Ahern } 314e0e79c8eSDavid Ahern 315e0e79c8eSDavid Ahern return ret; 316e0e79c8eSDavid Ahern } 317e0e79c8eSDavid Ahern 318ddde896eSGuy Shapiro /** 319ddde896eSGuy Shapiro * Find a net_device matching the given address, which is an upper device of 320ddde896eSGuy Shapiro * the given net_device. 321ddde896eSGuy Shapiro * @addr: IP address to look for. 322ddde896eSGuy Shapiro * @dev: base IPoIB net_device 323ddde896eSGuy Shapiro * 324ddde896eSGuy Shapiro * If found, returns the net_device with a reference held. Otherwise return 325ddde896eSGuy Shapiro * NULL. 326ddde896eSGuy Shapiro */ 327ddde896eSGuy Shapiro static struct net_device *ipoib_get_net_dev_match_addr( 328ddde896eSGuy Shapiro const struct sockaddr *addr, struct net_device *dev) 329ddde896eSGuy Shapiro { 330e0e79c8eSDavid Ahern struct ipoib_walk_data data = { 331e0e79c8eSDavid Ahern .addr = addr, 332e0e79c8eSDavid Ahern }; 333ddde896eSGuy Shapiro 334ddde896eSGuy Shapiro rcu_read_lock(); 335ddde896eSGuy Shapiro if (ipoib_is_dev_match_addr_rcu(addr, dev)) { 336ddde896eSGuy Shapiro dev_hold(dev); 337e0e79c8eSDavid Ahern data.result = dev; 338ddde896eSGuy Shapiro goto out; 339ddde896eSGuy Shapiro } 340ddde896eSGuy Shapiro 341e0e79c8eSDavid Ahern netdev_walk_all_upper_dev_rcu(dev, ipoib_upper_walk, &data); 342ddde896eSGuy Shapiro out: 343ddde896eSGuy Shapiro rcu_read_unlock(); 344e0e79c8eSDavid Ahern return data.result; 345ddde896eSGuy Shapiro } 346ddde896eSGuy Shapiro 347ddde896eSGuy Shapiro /* returns the number of IPoIB netdevs on top a given ipoib device matching a 348ddde896eSGuy Shapiro * pkey_index and address, if one exists. 349ddde896eSGuy Shapiro * 350ddde896eSGuy Shapiro * @found_net_dev: contains a matching net_device if the return value >= 1, 351ddde896eSGuy Shapiro * with a reference held. */ 352ddde896eSGuy Shapiro static int ipoib_match_gid_pkey_addr(struct ipoib_dev_priv *priv, 353ddde896eSGuy Shapiro const union ib_gid *gid, 354ddde896eSGuy Shapiro u16 pkey_index, 355ddde896eSGuy Shapiro const struct sockaddr *addr, 356ddde896eSGuy Shapiro int nesting, 357ddde896eSGuy Shapiro struct net_device **found_net_dev) 358ddde896eSGuy Shapiro { 359ddde896eSGuy Shapiro struct ipoib_dev_priv *child_priv; 360ddde896eSGuy Shapiro struct net_device *net_dev = NULL; 361ddde896eSGuy Shapiro int matches = 0; 362ddde896eSGuy Shapiro 363ddde896eSGuy Shapiro if (priv->pkey_index == pkey_index && 364ddde896eSGuy Shapiro (!gid || !memcmp(gid, &priv->local_gid, sizeof(*gid)))) { 365ddde896eSGuy Shapiro if (!addr) { 366ddde896eSGuy Shapiro net_dev = ipoib_get_master_net_dev(priv->dev); 367ddde896eSGuy Shapiro } else { 368ddde896eSGuy Shapiro /* Verify the net_device matches the IP address, as 369ddde896eSGuy Shapiro * IPoIB child devices currently share a GID. */ 370ddde896eSGuy Shapiro net_dev = ipoib_get_net_dev_match_addr(addr, priv->dev); 371ddde896eSGuy Shapiro } 372ddde896eSGuy Shapiro if (net_dev) { 373ddde896eSGuy Shapiro if (!*found_net_dev) 374ddde896eSGuy Shapiro *found_net_dev = net_dev; 375ddde896eSGuy Shapiro else 376ddde896eSGuy Shapiro dev_put(net_dev); 377ddde896eSGuy Shapiro ++matches; 378ddde896eSGuy Shapiro } 379ddde896eSGuy Shapiro } 380ddde896eSGuy Shapiro 381ddde896eSGuy Shapiro /* Check child interfaces */ 382ddde896eSGuy Shapiro down_read_nested(&priv->vlan_rwsem, nesting); 383ddde896eSGuy Shapiro list_for_each_entry(child_priv, &priv->child_intfs, list) { 384ddde896eSGuy Shapiro matches += ipoib_match_gid_pkey_addr(child_priv, gid, 385ddde896eSGuy Shapiro pkey_index, addr, 386ddde896eSGuy Shapiro nesting + 1, 387ddde896eSGuy Shapiro found_net_dev); 388ddde896eSGuy Shapiro if (matches > 1) 389ddde896eSGuy Shapiro break; 390ddde896eSGuy Shapiro } 391ddde896eSGuy Shapiro up_read(&priv->vlan_rwsem); 392ddde896eSGuy Shapiro 393ddde896eSGuy Shapiro return matches; 394ddde896eSGuy Shapiro } 395ddde896eSGuy Shapiro 396ddde896eSGuy Shapiro /* Returns the number of matching net_devs found (between 0 and 2). Also 397ddde896eSGuy Shapiro * return the matching net_device in the @net_dev parameter, holding a 398ddde896eSGuy Shapiro * reference to the net_device, if the number of matches >= 1 */ 399ddde896eSGuy Shapiro static int __ipoib_get_net_dev_by_params(struct list_head *dev_list, u8 port, 400ddde896eSGuy Shapiro u16 pkey_index, 401ddde896eSGuy Shapiro const union ib_gid *gid, 402ddde896eSGuy Shapiro const struct sockaddr *addr, 403ddde896eSGuy Shapiro struct net_device **net_dev) 404ddde896eSGuy Shapiro { 405ddde896eSGuy Shapiro struct ipoib_dev_priv *priv; 406ddde896eSGuy Shapiro int matches = 0; 407ddde896eSGuy Shapiro 408ddde896eSGuy Shapiro *net_dev = NULL; 409ddde896eSGuy Shapiro 410ddde896eSGuy Shapiro list_for_each_entry(priv, dev_list, list) { 411ddde896eSGuy Shapiro if (priv->port != port) 412ddde896eSGuy Shapiro continue; 413ddde896eSGuy Shapiro 414ddde896eSGuy Shapiro matches += ipoib_match_gid_pkey_addr(priv, gid, pkey_index, 415ddde896eSGuy Shapiro addr, 0, net_dev); 416ddde896eSGuy Shapiro if (matches > 1) 417ddde896eSGuy Shapiro break; 418ddde896eSGuy Shapiro } 419ddde896eSGuy Shapiro 420ddde896eSGuy Shapiro return matches; 421ddde896eSGuy Shapiro } 422ddde896eSGuy Shapiro 423ddde896eSGuy Shapiro static struct net_device *ipoib_get_net_dev_by_params( 424ddde896eSGuy Shapiro struct ib_device *dev, u8 port, u16 pkey, 425ddde896eSGuy Shapiro const union ib_gid *gid, const struct sockaddr *addr, 426ddde896eSGuy Shapiro void *client_data) 427ddde896eSGuy Shapiro { 428ddde896eSGuy Shapiro struct net_device *net_dev; 429ddde896eSGuy Shapiro struct list_head *dev_list = client_data; 430ddde896eSGuy Shapiro u16 pkey_index; 431ddde896eSGuy Shapiro int matches; 432ddde896eSGuy Shapiro int ret; 433ddde896eSGuy Shapiro 434ddde896eSGuy Shapiro if (!rdma_protocol_ib(dev, port)) 435ddde896eSGuy Shapiro return NULL; 436ddde896eSGuy Shapiro 437ddde896eSGuy Shapiro ret = ib_find_cached_pkey(dev, port, pkey, &pkey_index); 438ddde896eSGuy Shapiro if (ret) 439ddde896eSGuy Shapiro return NULL; 440ddde896eSGuy Shapiro 441ddde896eSGuy Shapiro if (!dev_list) 442ddde896eSGuy Shapiro return NULL; 443ddde896eSGuy Shapiro 444ddde896eSGuy Shapiro /* See if we can find a unique device matching the L2 parameters */ 445ddde896eSGuy Shapiro matches = __ipoib_get_net_dev_by_params(dev_list, port, pkey_index, 446ddde896eSGuy Shapiro gid, NULL, &net_dev); 447ddde896eSGuy Shapiro 448ddde896eSGuy Shapiro switch (matches) { 449ddde896eSGuy Shapiro case 0: 450ddde896eSGuy Shapiro return NULL; 451ddde896eSGuy Shapiro case 1: 452ddde896eSGuy Shapiro return net_dev; 453ddde896eSGuy Shapiro } 454ddde896eSGuy Shapiro 455ddde896eSGuy Shapiro dev_put(net_dev); 456ddde896eSGuy Shapiro 457ddde896eSGuy Shapiro /* Couldn't find a unique device with L2 parameters only. Use L3 458ddde896eSGuy Shapiro * address to uniquely match the net device */ 459ddde896eSGuy Shapiro matches = __ipoib_get_net_dev_by_params(dev_list, port, pkey_index, 460ddde896eSGuy Shapiro gid, addr, &net_dev); 461ddde896eSGuy Shapiro switch (matches) { 462ddde896eSGuy Shapiro case 0: 463ddde896eSGuy Shapiro return NULL; 464ddde896eSGuy Shapiro default: 465ddde896eSGuy Shapiro dev_warn_ratelimited(&dev->dev, 466ddde896eSGuy Shapiro "duplicate IP address detected\n"); 467ddde896eSGuy Shapiro /* Fall through */ 468ddde896eSGuy Shapiro case 1: 469ddde896eSGuy Shapiro return net_dev; 470ddde896eSGuy Shapiro } 471ddde896eSGuy Shapiro } 472ddde896eSGuy Shapiro 47371d9c5f9SRoland Dreier int ipoib_set_mode(struct net_device *dev, const char *buf) 47471d9c5f9SRoland Dreier { 47571d9c5f9SRoland Dreier struct ipoib_dev_priv *priv = netdev_priv(dev); 47671d9c5f9SRoland Dreier 47780b5b35aSFeras Daoud if ((test_bit(IPOIB_FLAG_ADMIN_CM, &priv->flags) && 47880b5b35aSFeras Daoud !strcmp(buf, "connected\n")) || 47980b5b35aSFeras Daoud (!test_bit(IPOIB_FLAG_ADMIN_CM, &priv->flags) && 48080b5b35aSFeras Daoud !strcmp(buf, "datagram\n"))) { 48180b5b35aSFeras Daoud return 0; 48280b5b35aSFeras Daoud } 48380b5b35aSFeras Daoud 48471d9c5f9SRoland Dreier /* flush paths if we switch modes so that connections are restarted */ 48571d9c5f9SRoland Dreier if (IPOIB_CM_SUPPORTED(dev->dev_addr) && !strcmp(buf, "connected\n")) { 48671d9c5f9SRoland Dreier set_bit(IPOIB_FLAG_ADMIN_CM, &priv->flags); 48771d9c5f9SRoland Dreier ipoib_warn(priv, "enabling connected mode " 48871d9c5f9SRoland Dreier "will cause multicast packet drops\n"); 48971d9c5f9SRoland Dreier netdev_update_features(dev); 490edcd2a74SErez Shitrit dev_set_mtu(dev, ipoib_cm_max_mtu(dev)); 49171d9c5f9SRoland Dreier rtnl_unlock(); 492e622f2f4SChristoph Hellwig priv->tx_wr.wr.send_flags &= ~IB_SEND_IP_CSUM; 49371d9c5f9SRoland Dreier 49471d9c5f9SRoland Dreier ipoib_flush_paths(dev); 4950a0007f2SFeras Daoud return (!rtnl_trylock()) ? -EBUSY : 0; 49671d9c5f9SRoland Dreier } 49771d9c5f9SRoland Dreier 49871d9c5f9SRoland Dreier if (!strcmp(buf, "datagram\n")) { 49971d9c5f9SRoland Dreier clear_bit(IPOIB_FLAG_ADMIN_CM, &priv->flags); 50071d9c5f9SRoland Dreier netdev_update_features(dev); 50171d9c5f9SRoland Dreier dev_set_mtu(dev, min(priv->mcast_mtu, dev->mtu)); 50271d9c5f9SRoland Dreier rtnl_unlock(); 50371d9c5f9SRoland Dreier ipoib_flush_paths(dev); 5040a0007f2SFeras Daoud return (!rtnl_trylock()) ? -EBUSY : 0; 50571d9c5f9SRoland Dreier } 50671d9c5f9SRoland Dreier 50771d9c5f9SRoland Dreier return -EINVAL; 50871d9c5f9SRoland Dreier } 50971d9c5f9SRoland Dreier 510546481c2SErez Shitrit struct ipoib_path *__path_find(struct net_device *dev, void *gid) 5111da177e4SLinus Torvalds { 5121da177e4SLinus Torvalds struct ipoib_dev_priv *priv = netdev_priv(dev); 5131da177e4SLinus Torvalds struct rb_node *n = priv->path_tree.rb_node; 5141da177e4SLinus Torvalds struct ipoib_path *path; 5151da177e4SLinus Torvalds int ret; 5161da177e4SLinus Torvalds 5171da177e4SLinus Torvalds while (n) { 5181da177e4SLinus Torvalds path = rb_entry(n, struct ipoib_path, rb_node); 5191da177e4SLinus Torvalds 52037c22a77SJack Morgenstein ret = memcmp(gid, path->pathrec.dgid.raw, 5211da177e4SLinus Torvalds sizeof (union ib_gid)); 5221da177e4SLinus Torvalds 5231da177e4SLinus Torvalds if (ret < 0) 5241da177e4SLinus Torvalds n = n->rb_left; 5251da177e4SLinus Torvalds else if (ret > 0) 5261da177e4SLinus Torvalds n = n->rb_right; 5271da177e4SLinus Torvalds else 5281da177e4SLinus Torvalds return path; 5291da177e4SLinus Torvalds } 5301da177e4SLinus Torvalds 5311da177e4SLinus Torvalds return NULL; 5321da177e4SLinus Torvalds } 5331da177e4SLinus Torvalds 5341da177e4SLinus Torvalds static int __path_add(struct net_device *dev, struct ipoib_path *path) 5351da177e4SLinus Torvalds { 5361da177e4SLinus Torvalds struct ipoib_dev_priv *priv = netdev_priv(dev); 5371da177e4SLinus Torvalds struct rb_node **n = &priv->path_tree.rb_node; 5381da177e4SLinus Torvalds struct rb_node *pn = NULL; 5391da177e4SLinus Torvalds struct ipoib_path *tpath; 5401da177e4SLinus Torvalds int ret; 5411da177e4SLinus Torvalds 5421da177e4SLinus Torvalds while (*n) { 5431da177e4SLinus Torvalds pn = *n; 5441da177e4SLinus Torvalds tpath = rb_entry(pn, struct ipoib_path, rb_node); 5451da177e4SLinus Torvalds 5461da177e4SLinus Torvalds ret = memcmp(path->pathrec.dgid.raw, tpath->pathrec.dgid.raw, 5471da177e4SLinus Torvalds sizeof (union ib_gid)); 5481da177e4SLinus Torvalds if (ret < 0) 5491da177e4SLinus Torvalds n = &pn->rb_left; 5501da177e4SLinus Torvalds else if (ret > 0) 5511da177e4SLinus Torvalds n = &pn->rb_right; 5521da177e4SLinus Torvalds else 5531da177e4SLinus Torvalds return -EEXIST; 5541da177e4SLinus Torvalds } 5551da177e4SLinus Torvalds 5561da177e4SLinus Torvalds rb_link_node(&path->rb_node, pn, n); 5571da177e4SLinus Torvalds rb_insert_color(&path->rb_node, &priv->path_tree); 5581da177e4SLinus Torvalds 5591da177e4SLinus Torvalds list_add_tail(&path->list, &priv->path_list); 5601da177e4SLinus Torvalds 5611da177e4SLinus Torvalds return 0; 5621da177e4SLinus Torvalds } 5631da177e4SLinus Torvalds 5641da177e4SLinus Torvalds static void path_free(struct net_device *dev, struct ipoib_path *path) 5651da177e4SLinus Torvalds { 5661da177e4SLinus Torvalds struct sk_buff *skb; 5671da177e4SLinus Torvalds 5681da177e4SLinus Torvalds while ((skb = __skb_dequeue(&path->queue))) 5691da177e4SLinus Torvalds dev_kfree_skb_irq(skb); 5701da177e4SLinus Torvalds 571b63b70d8SShlomo Pongratz ipoib_dbg(netdev_priv(dev), "path_free\n"); 5721da177e4SLinus Torvalds 573b63b70d8SShlomo Pongratz /* remove all neigh connected to this path */ 574b63b70d8SShlomo Pongratz ipoib_del_neighs_by_gid(dev, path->pathrec.dgid.raw); 5751da177e4SLinus Torvalds 5761da177e4SLinus Torvalds if (path->ah) 5771da177e4SLinus Torvalds ipoib_put_ah(path->ah); 5781da177e4SLinus Torvalds 5791da177e4SLinus Torvalds kfree(path); 5801da177e4SLinus Torvalds } 5811da177e4SLinus Torvalds 5821732b0efSRoland Dreier #ifdef CONFIG_INFINIBAND_IPOIB_DEBUG 5831732b0efSRoland Dreier 5841732b0efSRoland Dreier struct ipoib_path_iter *ipoib_path_iter_init(struct net_device *dev) 5851732b0efSRoland Dreier { 5861732b0efSRoland Dreier struct ipoib_path_iter *iter; 5871732b0efSRoland Dreier 5881732b0efSRoland Dreier iter = kmalloc(sizeof *iter, GFP_KERNEL); 5891732b0efSRoland Dreier if (!iter) 5901732b0efSRoland Dreier return NULL; 5911732b0efSRoland Dreier 5921732b0efSRoland Dreier iter->dev = dev; 5931732b0efSRoland Dreier memset(iter->path.pathrec.dgid.raw, 0, 16); 5941732b0efSRoland Dreier 5951732b0efSRoland Dreier if (ipoib_path_iter_next(iter)) { 5961732b0efSRoland Dreier kfree(iter); 5971732b0efSRoland Dreier return NULL; 5981732b0efSRoland Dreier } 5991732b0efSRoland Dreier 6001732b0efSRoland Dreier return iter; 6011732b0efSRoland Dreier } 6021732b0efSRoland Dreier 6031732b0efSRoland Dreier int ipoib_path_iter_next(struct ipoib_path_iter *iter) 6041732b0efSRoland Dreier { 6051732b0efSRoland Dreier struct ipoib_dev_priv *priv = netdev_priv(iter->dev); 6061732b0efSRoland Dreier struct rb_node *n; 6071732b0efSRoland Dreier struct ipoib_path *path; 6081732b0efSRoland Dreier int ret = 1; 6091732b0efSRoland Dreier 6101732b0efSRoland Dreier spin_lock_irq(&priv->lock); 6111732b0efSRoland Dreier 6121732b0efSRoland Dreier n = rb_first(&priv->path_tree); 6131732b0efSRoland Dreier 6141732b0efSRoland Dreier while (n) { 6151732b0efSRoland Dreier path = rb_entry(n, struct ipoib_path, rb_node); 6161732b0efSRoland Dreier 6171732b0efSRoland Dreier if (memcmp(iter->path.pathrec.dgid.raw, path->pathrec.dgid.raw, 6181732b0efSRoland Dreier sizeof (union ib_gid)) < 0) { 6191732b0efSRoland Dreier iter->path = *path; 6201732b0efSRoland Dreier ret = 0; 6211732b0efSRoland Dreier break; 6221732b0efSRoland Dreier } 6231732b0efSRoland Dreier 6241732b0efSRoland Dreier n = rb_next(n); 6251732b0efSRoland Dreier } 6261732b0efSRoland Dreier 6271732b0efSRoland Dreier spin_unlock_irq(&priv->lock); 6281732b0efSRoland Dreier 6291732b0efSRoland Dreier return ret; 6301732b0efSRoland Dreier } 6311732b0efSRoland Dreier 6321732b0efSRoland Dreier void ipoib_path_iter_read(struct ipoib_path_iter *iter, 6331732b0efSRoland Dreier struct ipoib_path *path) 6341732b0efSRoland Dreier { 6351732b0efSRoland Dreier *path = iter->path; 6361732b0efSRoland Dreier } 6371732b0efSRoland Dreier 6381732b0efSRoland Dreier #endif /* CONFIG_INFINIBAND_IPOIB_DEBUG */ 6391732b0efSRoland Dreier 640ee1e2c82SMoni Shoua void ipoib_mark_paths_invalid(struct net_device *dev) 641ee1e2c82SMoni Shoua { 642ee1e2c82SMoni Shoua struct ipoib_dev_priv *priv = netdev_priv(dev); 643ee1e2c82SMoni Shoua struct ipoib_path *path, *tp; 644ee1e2c82SMoni Shoua 645ee1e2c82SMoni Shoua spin_lock_irq(&priv->lock); 646ee1e2c82SMoni Shoua 647ee1e2c82SMoni Shoua list_for_each_entry_safe(path, tp, &priv->path_list, list) { 6485b095d98SHarvey Harrison ipoib_dbg(priv, "mark path LID 0x%04x GID %pI6 invalid\n", 649ee1e2c82SMoni Shoua be16_to_cpu(path->pathrec.dlid), 650fcace2feSHarvey Harrison path->pathrec.dgid.raw); 651ee1e2c82SMoni Shoua path->valid = 0; 652ee1e2c82SMoni Shoua } 653ee1e2c82SMoni Shoua 654ee1e2c82SMoni Shoua spin_unlock_irq(&priv->lock); 655ee1e2c82SMoni Shoua } 656ee1e2c82SMoni Shoua 6573b561130SErez Shitrit struct classport_info_context { 6583b561130SErez Shitrit struct ipoib_dev_priv *priv; 6593b561130SErez Shitrit struct completion done; 6603b561130SErez Shitrit struct ib_sa_query *sa_query; 6613b561130SErez Shitrit }; 6623b561130SErez Shitrit 6633b561130SErez Shitrit static void classport_info_query_cb(int status, struct ib_class_port_info *rec, 6643b561130SErez Shitrit void *context) 6653b561130SErez Shitrit { 6663b561130SErez Shitrit struct classport_info_context *cb_ctx = context; 6673b561130SErez Shitrit struct ipoib_dev_priv *priv; 6683b561130SErez Shitrit 6693b561130SErez Shitrit WARN_ON(!context); 6703b561130SErez Shitrit 6713b561130SErez Shitrit priv = cb_ctx->priv; 6723b561130SErez Shitrit 6733b561130SErez Shitrit if (status || !rec) { 6743b561130SErez Shitrit pr_debug("device: %s failed query classport_info status: %d\n", 6753b561130SErez Shitrit priv->dev->name, status); 6763b561130SErez Shitrit /* keeps the default, will try next mcast_restart */ 6773b561130SErez Shitrit priv->sm_fullmember_sendonly_support = false; 6783b561130SErez Shitrit goto out; 6793b561130SErez Shitrit } 6803b561130SErez Shitrit 6813b561130SErez Shitrit if (ib_get_cpi_capmask2(rec) & 6823b561130SErez Shitrit IB_SA_CAP_MASK2_SENDONLY_FULL_MEM_SUPPORT) { 6833b561130SErez Shitrit pr_debug("device: %s enabled fullmember-sendonly for sendonly MCG\n", 6843b561130SErez Shitrit priv->dev->name); 6853b561130SErez Shitrit priv->sm_fullmember_sendonly_support = true; 6863b561130SErez Shitrit } else { 6873b561130SErez Shitrit pr_debug("device: %s disabled fullmember-sendonly for sendonly MCG\n", 6883b561130SErez Shitrit priv->dev->name); 6893b561130SErez Shitrit priv->sm_fullmember_sendonly_support = false; 6903b561130SErez Shitrit } 6913b561130SErez Shitrit 6923b561130SErez Shitrit out: 6933b561130SErez Shitrit complete(&cb_ctx->done); 6943b561130SErez Shitrit } 6953b561130SErez Shitrit 6963b561130SErez Shitrit int ipoib_check_sm_sendonly_fullmember_support(struct ipoib_dev_priv *priv) 6973b561130SErez Shitrit { 6983b561130SErez Shitrit struct classport_info_context *callback_context; 6993b561130SErez Shitrit int ret; 7003b561130SErez Shitrit 7013b561130SErez Shitrit callback_context = kmalloc(sizeof(*callback_context), GFP_KERNEL); 7023b561130SErez Shitrit if (!callback_context) 7033b561130SErez Shitrit return -ENOMEM; 7043b561130SErez Shitrit 7053b561130SErez Shitrit callback_context->priv = priv; 7063b561130SErez Shitrit init_completion(&callback_context->done); 7073b561130SErez Shitrit 7083b561130SErez Shitrit ret = ib_sa_classport_info_rec_query(&ipoib_sa_client, 7093b561130SErez Shitrit priv->ca, priv->port, 3000, 7103b561130SErez Shitrit GFP_KERNEL, 7113b561130SErez Shitrit classport_info_query_cb, 7123b561130SErez Shitrit callback_context, 7133b561130SErez Shitrit &callback_context->sa_query); 7143b561130SErez Shitrit if (ret < 0) { 7153b561130SErez Shitrit pr_info("%s failed to send ib_sa_classport_info query, ret: %d\n", 7163b561130SErez Shitrit priv->dev->name, ret); 7173b561130SErez Shitrit kfree(callback_context); 7183b561130SErez Shitrit return ret; 7193b561130SErez Shitrit } 7203b561130SErez Shitrit 7213b561130SErez Shitrit /* waiting for the callback to finish before returnning */ 7223b561130SErez Shitrit wait_for_completion(&callback_context->done); 7233b561130SErez Shitrit kfree(callback_context); 7243b561130SErez Shitrit 7253b561130SErez Shitrit return ret; 7263b561130SErez Shitrit } 7273b561130SErez Shitrit 7281da177e4SLinus Torvalds void ipoib_flush_paths(struct net_device *dev) 7291da177e4SLinus Torvalds { 7301da177e4SLinus Torvalds struct ipoib_dev_priv *priv = netdev_priv(dev); 7311da177e4SLinus Torvalds struct ipoib_path *path, *tp; 7321da177e4SLinus Torvalds LIST_HEAD(remove_list); 733943c246eSRoland Dreier unsigned long flags; 7341da177e4SLinus Torvalds 735943c246eSRoland Dreier netif_tx_lock_bh(dev); 736943c246eSRoland Dreier spin_lock_irqsave(&priv->lock, flags); 7371da177e4SLinus Torvalds 738157de229SRobert P. J. Day list_splice_init(&priv->path_list, &remove_list); 7391da177e4SLinus Torvalds 7401da177e4SLinus Torvalds list_for_each_entry(path, &remove_list, list) 7411da177e4SLinus Torvalds rb_erase(&path->rb_node, &priv->path_tree); 7421da177e4SLinus Torvalds 7431da177e4SLinus Torvalds list_for_each_entry_safe(path, tp, &remove_list, list) { 7441da177e4SLinus Torvalds if (path->query) 7451da177e4SLinus Torvalds ib_sa_cancel_query(path->query_id, path->query); 746943c246eSRoland Dreier spin_unlock_irqrestore(&priv->lock, flags); 747943c246eSRoland Dreier netif_tx_unlock_bh(dev); 7481da177e4SLinus Torvalds wait_for_completion(&path->done); 7491da177e4SLinus Torvalds path_free(dev, path); 750943c246eSRoland Dreier netif_tx_lock_bh(dev); 751943c246eSRoland Dreier spin_lock_irqsave(&priv->lock, flags); 7521da177e4SLinus Torvalds } 753943c246eSRoland Dreier 754943c246eSRoland Dreier spin_unlock_irqrestore(&priv->lock, flags); 755943c246eSRoland Dreier netif_tx_unlock_bh(dev); 7561da177e4SLinus Torvalds } 7571da177e4SLinus Torvalds 7581da177e4SLinus Torvalds static void path_rec_completion(int status, 7591da177e4SLinus Torvalds struct ib_sa_path_rec *pathrec, 7601da177e4SLinus Torvalds void *path_ptr) 7611da177e4SLinus Torvalds { 7621da177e4SLinus Torvalds struct ipoib_path *path = path_ptr; 7631da177e4SLinus Torvalds struct net_device *dev = path->dev; 7641da177e4SLinus Torvalds struct ipoib_dev_priv *priv = netdev_priv(dev); 7651da177e4SLinus Torvalds struct ipoib_ah *ah = NULL; 766c9da4badSRoland Dreier struct ipoib_ah *old_ah = NULL; 767d04d01b1SMichael S. Tsirkin struct ipoib_neigh *neigh, *tn; 7681da177e4SLinus Torvalds struct sk_buff_head skqueue; 7691da177e4SLinus Torvalds struct sk_buff *skb; 7701da177e4SLinus Torvalds unsigned long flags; 7711da177e4SLinus Torvalds 772843613b0SRoland Dreier if (!status) 7735b095d98SHarvey Harrison ipoib_dbg(priv, "PathRec LID 0x%04x for GID %pI6\n", 774fcace2feSHarvey Harrison be16_to_cpu(pathrec->dlid), pathrec->dgid.raw); 7751da177e4SLinus Torvalds else 7765b095d98SHarvey Harrison ipoib_dbg(priv, "PathRec status %d for GID %pI6\n", 777fcace2feSHarvey Harrison status, path->pathrec.dgid.raw); 7781da177e4SLinus Torvalds 7791da177e4SLinus Torvalds skb_queue_head_init(&skqueue); 7801da177e4SLinus Torvalds 7811da177e4SLinus Torvalds if (!status) { 78246f1b3d7SSean Hefty struct ib_ah_attr av; 7831da177e4SLinus Torvalds 78446f1b3d7SSean Hefty if (!ib_init_ah_from_path(priv->ca, priv->port, pathrec, &av)) 7851da177e4SLinus Torvalds ah = ipoib_create_ah(dev, priv->pd, &av); 7861da177e4SLinus Torvalds } 7871da177e4SLinus Torvalds 7881da177e4SLinus Torvalds spin_lock_irqsave(&priv->lock, flags); 7891da177e4SLinus Torvalds 7903874397cSMike Marciniszyn if (!IS_ERR_OR_NULL(ah)) { 7911da177e4SLinus Torvalds path->pathrec = *pathrec; 7921da177e4SLinus Torvalds 793c9da4badSRoland Dreier old_ah = path->ah; 794c9da4badSRoland Dreier path->ah = ah; 795c9da4badSRoland Dreier 7961da177e4SLinus Torvalds ipoib_dbg(priv, "created address handle %p for LID 0x%04x, SL %d\n", 7971da177e4SLinus Torvalds ah, be16_to_cpu(pathrec->dlid), pathrec->sl); 7981da177e4SLinus Torvalds 7991da177e4SLinus Torvalds while ((skb = __skb_dequeue(&path->queue))) 8001da177e4SLinus Torvalds __skb_queue_tail(&skqueue, skb); 8011da177e4SLinus Torvalds 802d04d01b1SMichael S. Tsirkin list_for_each_entry_safe(neigh, tn, &path->neigh_list, list) { 803ee1e2c82SMoni Shoua if (neigh->ah) { 804ee1e2c82SMoni Shoua WARN_ON(neigh->ah != old_ah); 805ee1e2c82SMoni Shoua /* 806ee1e2c82SMoni Shoua * Dropping the ah reference inside 807ee1e2c82SMoni Shoua * priv->lock is safe here, because we 808ee1e2c82SMoni Shoua * will hold one more reference from 809ee1e2c82SMoni Shoua * the original value of path->ah (ie 810ee1e2c82SMoni Shoua * old_ah). 811ee1e2c82SMoni Shoua */ 812ee1e2c82SMoni Shoua ipoib_put_ah(neigh->ah); 813ee1e2c82SMoni Shoua } 8141da177e4SLinus Torvalds kref_get(&path->ah->ref); 8151da177e4SLinus Torvalds neigh->ah = path->ah; 8161da177e4SLinus Torvalds 817b63b70d8SShlomo Pongratz if (ipoib_cm_enabled(dev, neigh->daddr)) { 818839fcabaSMichael S. Tsirkin if (!ipoib_cm_get(neigh)) 819839fcabaSMichael S. Tsirkin ipoib_cm_set(neigh, ipoib_cm_create_tx(dev, 820839fcabaSMichael S. Tsirkin path, 821839fcabaSMichael S. Tsirkin neigh)); 822839fcabaSMichael S. Tsirkin if (!ipoib_cm_get(neigh)) { 823b63b70d8SShlomo Pongratz ipoib_neigh_free(neigh); 824839fcabaSMichael S. Tsirkin continue; 825839fcabaSMichael S. Tsirkin } 826839fcabaSMichael S. Tsirkin } 827839fcabaSMichael S. Tsirkin 8281da177e4SLinus Torvalds while ((skb = __skb_dequeue(&neigh->queue))) 8291da177e4SLinus Torvalds __skb_queue_tail(&skqueue, skb); 8301da177e4SLinus Torvalds } 831ee1e2c82SMoni Shoua path->valid = 1; 8325872a9fcSRoland Dreier } 8331da177e4SLinus Torvalds 8345872a9fcSRoland Dreier path->query = NULL; 8351da177e4SLinus Torvalds complete(&path->done); 8361da177e4SLinus Torvalds 8371da177e4SLinus Torvalds spin_unlock_irqrestore(&priv->lock, flags); 8381da177e4SLinus Torvalds 839f72dd566SRoland Dreier if (IS_ERR_OR_NULL(ah)) 840f72dd566SRoland Dreier ipoib_del_neighs_by_gid(dev, path->pathrec.dgid.raw); 841f72dd566SRoland Dreier 842ee1e2c82SMoni Shoua if (old_ah) 843ee1e2c82SMoni Shoua ipoib_put_ah(old_ah); 844ee1e2c82SMoni Shoua 8451da177e4SLinus Torvalds while ((skb = __skb_dequeue(&skqueue))) { 846d32b9a81SFeras Daoud int ret; 8471da177e4SLinus Torvalds skb->dev = dev; 848d32b9a81SFeras Daoud ret = dev_queue_xmit(skb); 849d32b9a81SFeras Daoud if (ret) 850d32b9a81SFeras Daoud ipoib_warn(priv, "%s: dev_queue_xmit failed to re-queue packet, ret:%d\n", 851d32b9a81SFeras Daoud __func__, ret); 8521da177e4SLinus Torvalds } 8531da177e4SLinus Torvalds } 8541da177e4SLinus Torvalds 85537c22a77SJack Morgenstein static struct ipoib_path *path_rec_create(struct net_device *dev, void *gid) 8561da177e4SLinus Torvalds { 8571da177e4SLinus Torvalds struct ipoib_dev_priv *priv = netdev_priv(dev); 8581da177e4SLinus Torvalds struct ipoib_path *path; 8591da177e4SLinus Torvalds 8601401b53aSJack Morgenstein if (!priv->broadcast) 8611401b53aSJack Morgenstein return NULL; 8621401b53aSJack Morgenstein 86321a38489SRoland Dreier path = kzalloc(sizeof *path, GFP_ATOMIC); 8641da177e4SLinus Torvalds if (!path) 8651da177e4SLinus Torvalds return NULL; 8661da177e4SLinus Torvalds 8671da177e4SLinus Torvalds path->dev = dev; 8681da177e4SLinus Torvalds 8691da177e4SLinus Torvalds skb_queue_head_init(&path->queue); 8701da177e4SLinus Torvalds 8711da177e4SLinus Torvalds INIT_LIST_HEAD(&path->neigh_list); 8721da177e4SLinus Torvalds 87337c22a77SJack Morgenstein memcpy(path->pathrec.dgid.raw, gid, sizeof (union ib_gid)); 8741da177e4SLinus Torvalds path->pathrec.sgid = priv->local_gid; 8751da177e4SLinus Torvalds path->pathrec.pkey = cpu_to_be16(priv->pkey); 8761da177e4SLinus Torvalds path->pathrec.numb_path = 1; 87781668838SSean Hefty path->pathrec.traffic_class = priv->broadcast->mcmember.traffic_class; 8781da177e4SLinus Torvalds 8791da177e4SLinus Torvalds return path; 8801da177e4SLinus Torvalds } 8811da177e4SLinus Torvalds 8821da177e4SLinus Torvalds static int path_rec_start(struct net_device *dev, 8831da177e4SLinus Torvalds struct ipoib_path *path) 8841da177e4SLinus Torvalds { 8851da177e4SLinus Torvalds struct ipoib_dev_priv *priv = netdev_priv(dev); 8861da177e4SLinus Torvalds 8875b095d98SHarvey Harrison ipoib_dbg(priv, "Start path record lookup for %pI6\n", 888fcace2feSHarvey Harrison path->pathrec.dgid.raw); 8891da177e4SLinus Torvalds 89065c7eddaSRoland Dreier init_completion(&path->done); 89165c7eddaSRoland Dreier 8921da177e4SLinus Torvalds path->query_id = 893c1a0b23bSMichael S. Tsirkin ib_sa_path_rec_get(&ipoib_sa_client, priv->ca, priv->port, 8941da177e4SLinus Torvalds &path->pathrec, 8951da177e4SLinus Torvalds IB_SA_PATH_REC_DGID | 8961da177e4SLinus Torvalds IB_SA_PATH_REC_SGID | 8971da177e4SLinus Torvalds IB_SA_PATH_REC_NUMB_PATH | 89881668838SSean Hefty IB_SA_PATH_REC_TRAFFIC_CLASS | 8991da177e4SLinus Torvalds IB_SA_PATH_REC_PKEY, 9001da177e4SLinus Torvalds 1000, GFP_ATOMIC, 9011da177e4SLinus Torvalds path_rec_completion, 9021da177e4SLinus Torvalds path, &path->query); 9031da177e4SLinus Torvalds if (path->query_id < 0) { 90401b3fc8bSOr Gerlitz ipoib_warn(priv, "ib_sa_path_rec_get failed: %d\n", path->query_id); 9051da177e4SLinus Torvalds path->query = NULL; 90693a3ab93SYossi Etigin complete(&path->done); 9071da177e4SLinus Torvalds return path->query_id; 9081da177e4SLinus Torvalds } 9091da177e4SLinus Torvalds 9101da177e4SLinus Torvalds return 0; 9111da177e4SLinus Torvalds } 9121da177e4SLinus Torvalds 913b63b70d8SShlomo Pongratz static void neigh_add_path(struct sk_buff *skb, u8 *daddr, 914b63b70d8SShlomo Pongratz struct net_device *dev) 9151da177e4SLinus Torvalds { 9161da177e4SLinus Torvalds struct ipoib_dev_priv *priv = netdev_priv(dev); 9171da177e4SLinus Torvalds struct ipoib_path *path; 9181da177e4SLinus Torvalds struct ipoib_neigh *neigh; 919943c246eSRoland Dreier unsigned long flags; 9201da177e4SLinus Torvalds 921b5120a6eSShlomo Pongratz spin_lock_irqsave(&priv->lock, flags); 922b63b70d8SShlomo Pongratz neigh = ipoib_neigh_alloc(daddr, dev); 9231da177e4SLinus Torvalds if (!neigh) { 924b5120a6eSShlomo Pongratz spin_unlock_irqrestore(&priv->lock, flags); 925de903512SRoland Dreier ++dev->stats.tx_dropped; 9261da177e4SLinus Torvalds dev_kfree_skb_any(skb); 9271da177e4SLinus Torvalds return; 9281da177e4SLinus Torvalds } 9291da177e4SLinus Torvalds 930b63b70d8SShlomo Pongratz path = __path_find(dev, daddr + 4); 9311da177e4SLinus Torvalds if (!path) { 932b63b70d8SShlomo Pongratz path = path_rec_create(dev, daddr + 4); 9331da177e4SLinus Torvalds if (!path) 934d2e0655eSMichael S. Tsirkin goto err_path; 9351da177e4SLinus Torvalds 9361da177e4SLinus Torvalds __path_add(dev, path); 9371da177e4SLinus Torvalds } 9381da177e4SLinus Torvalds 9391da177e4SLinus Torvalds list_add_tail(&neigh->list, &path->neigh_list); 9401da177e4SLinus Torvalds 94147f7a071SMichael S. Tsirkin if (path->ah) { 9421da177e4SLinus Torvalds kref_get(&path->ah->ref); 9431da177e4SLinus Torvalds neigh->ah = path->ah; 9441da177e4SLinus Torvalds 945b63b70d8SShlomo Pongratz if (ipoib_cm_enabled(dev, neigh->daddr)) { 946839fcabaSMichael S. Tsirkin if (!ipoib_cm_get(neigh)) 947839fcabaSMichael S. Tsirkin ipoib_cm_set(neigh, ipoib_cm_create_tx(dev, path, neigh)); 948839fcabaSMichael S. Tsirkin if (!ipoib_cm_get(neigh)) { 949b63b70d8SShlomo Pongratz ipoib_neigh_free(neigh); 950839fcabaSMichael S. Tsirkin goto err_drop; 951839fcabaSMichael S. Tsirkin } 952fc791b63SPaolo Abeni if (skb_queue_len(&neigh->queue) < 953fc791b63SPaolo Abeni IPOIB_MAX_PATH_REC_QUEUE) { 954fc791b63SPaolo Abeni /* put pseudoheader back on for next time */ 955fc791b63SPaolo Abeni skb_push(skb, IPOIB_PSEUDO_LEN); 956839fcabaSMichael S. Tsirkin __skb_queue_tail(&neigh->queue, skb); 957fc791b63SPaolo Abeni } else { 958839fcabaSMichael S. Tsirkin ipoib_warn(priv, "queue length limit %d. Packet drop.\n", 959839fcabaSMichael S. Tsirkin skb_queue_len(&neigh->queue)); 960839fcabaSMichael S. Tsirkin goto err_drop; 961839fcabaSMichael S. Tsirkin } 962721d67cdSRoland Dreier } else { 963721d67cdSRoland Dreier spin_unlock_irqrestore(&priv->lock, flags); 964b63b70d8SShlomo Pongratz ipoib_send(dev, skb, path->ah, IPOIB_QPN(daddr)); 965b63b70d8SShlomo Pongratz ipoib_neigh_put(neigh); 966721d67cdSRoland Dreier return; 967721d67cdSRoland Dreier } 9681da177e4SLinus Torvalds } else { 9691da177e4SLinus Torvalds neigh->ah = NULL; 9701da177e4SLinus Torvalds 9711da177e4SLinus Torvalds if (!path->query && path_rec_start(dev, path)) 97249b8e744SJim Foraker goto err_path; 9731e85b806SErez Shitrit if (skb_queue_len(&neigh->queue) < IPOIB_MAX_PATH_REC_QUEUE) 9742745b5b7SMichael S. Tsirkin __skb_queue_tail(&neigh->queue, skb); 9751e85b806SErez Shitrit else 9761e85b806SErez Shitrit goto err_drop; 9771da177e4SLinus Torvalds } 9781da177e4SLinus Torvalds 979943c246eSRoland Dreier spin_unlock_irqrestore(&priv->lock, flags); 980b63b70d8SShlomo Pongratz ipoib_neigh_put(neigh); 9811da177e4SLinus Torvalds return; 9821da177e4SLinus Torvalds 983d2e0655eSMichael S. Tsirkin err_path: 984b63b70d8SShlomo Pongratz ipoib_neigh_free(neigh); 985839fcabaSMichael S. Tsirkin err_drop: 986de903512SRoland Dreier ++dev->stats.tx_dropped; 9871da177e4SLinus Torvalds dev_kfree_skb_any(skb); 9881da177e4SLinus Torvalds 989943c246eSRoland Dreier spin_unlock_irqrestore(&priv->lock, flags); 990b63b70d8SShlomo Pongratz ipoib_neigh_put(neigh); 9911da177e4SLinus Torvalds } 9921da177e4SLinus Torvalds 9931da177e4SLinus Torvalds static void unicast_arp_send(struct sk_buff *skb, struct net_device *dev, 994fc791b63SPaolo Abeni struct ipoib_pseudo_header *phdr) 9951da177e4SLinus Torvalds { 9961da177e4SLinus Torvalds struct ipoib_dev_priv *priv = netdev_priv(dev); 9971da177e4SLinus Torvalds struct ipoib_path *path; 998943c246eSRoland Dreier unsigned long flags; 9991da177e4SLinus Torvalds 1000943c246eSRoland Dreier spin_lock_irqsave(&priv->lock, flags); 10011da177e4SLinus Torvalds 1002fc791b63SPaolo Abeni path = __path_find(dev, phdr->hwaddr + 4); 1003ee1e2c82SMoni Shoua if (!path || !path->valid) { 100471d98b46SJack Morgenstein int new_path = 0; 100571d98b46SJack Morgenstein 100671d98b46SJack Morgenstein if (!path) { 1007fc791b63SPaolo Abeni path = path_rec_create(dev, phdr->hwaddr + 4); 100871d98b46SJack Morgenstein new_path = 1; 100971d98b46SJack Morgenstein } 10101da177e4SLinus Torvalds if (path) { 10111e85b806SErez Shitrit if (skb_queue_len(&path->queue) < IPOIB_MAX_PATH_REC_QUEUE) { 1012fc791b63SPaolo Abeni /* put pseudoheader back on for next time */ 1013fc791b63SPaolo Abeni skb_push(skb, IPOIB_PSEUDO_LEN); 10141da177e4SLinus Torvalds __skb_queue_tail(&path->queue, skb); 10151e85b806SErez Shitrit } else { 10161e85b806SErez Shitrit ++dev->stats.tx_dropped; 10171e85b806SErez Shitrit dev_kfree_skb_any(skb); 10181e85b806SErez Shitrit } 10191da177e4SLinus Torvalds 1020ff79ae80SYossi Etigin if (!path->query && path_rec_start(dev, path)) { 1021943c246eSRoland Dreier spin_unlock_irqrestore(&priv->lock, flags); 102271d98b46SJack Morgenstein if (new_path) 10231da177e4SLinus Torvalds path_free(dev, path); 10241da177e4SLinus Torvalds return; 10251da177e4SLinus Torvalds } else 10261da177e4SLinus Torvalds __path_add(dev, path); 10271da177e4SLinus Torvalds } else { 1028de903512SRoland Dreier ++dev->stats.tx_dropped; 10291da177e4SLinus Torvalds dev_kfree_skb_any(skb); 10301da177e4SLinus Torvalds } 10311da177e4SLinus Torvalds 1032943c246eSRoland Dreier spin_unlock_irqrestore(&priv->lock, flags); 10331da177e4SLinus Torvalds return; 10341da177e4SLinus Torvalds } 10351da177e4SLinus Torvalds 103647f7a071SMichael S. Tsirkin if (path->ah) { 10371da177e4SLinus Torvalds ipoib_dbg(priv, "Send unicast ARP to %04x\n", 10381da177e4SLinus Torvalds be16_to_cpu(path->pathrec.dlid)); 10391da177e4SLinus Torvalds 1040721d67cdSRoland Dreier spin_unlock_irqrestore(&priv->lock, flags); 1041fc791b63SPaolo Abeni ipoib_send(dev, skb, path->ah, IPOIB_QPN(phdr->hwaddr)); 1042721d67cdSRoland Dreier return; 10431da177e4SLinus Torvalds } else if ((path->query || !path_rec_start(dev, path)) && 10441da177e4SLinus Torvalds skb_queue_len(&path->queue) < IPOIB_MAX_PATH_REC_QUEUE) { 1045fc791b63SPaolo Abeni /* put pseudoheader back on for next time */ 1046fc791b63SPaolo Abeni skb_push(skb, IPOIB_PSEUDO_LEN); 10471da177e4SLinus Torvalds __skb_queue_tail(&path->queue, skb); 10481da177e4SLinus Torvalds } else { 1049de903512SRoland Dreier ++dev->stats.tx_dropped; 10501da177e4SLinus Torvalds dev_kfree_skb_any(skb); 10511da177e4SLinus Torvalds } 10521da177e4SLinus Torvalds 1053943c246eSRoland Dreier spin_unlock_irqrestore(&priv->lock, flags); 10541da177e4SLinus Torvalds } 10551da177e4SLinus Torvalds 10561da177e4SLinus Torvalds static int ipoib_start_xmit(struct sk_buff *skb, struct net_device *dev) 10571da177e4SLinus Torvalds { 10581da177e4SLinus Torvalds struct ipoib_dev_priv *priv = netdev_priv(dev); 10591da177e4SLinus Torvalds struct ipoib_neigh *neigh; 1060fc791b63SPaolo Abeni struct ipoib_pseudo_header *phdr; 1061b63b70d8SShlomo Pongratz struct ipoib_header *header; 10621da177e4SLinus Torvalds unsigned long flags; 10631da177e4SLinus Torvalds 1064fc791b63SPaolo Abeni phdr = (struct ipoib_pseudo_header *) skb->data; 1065fc791b63SPaolo Abeni skb_pull(skb, sizeof(*phdr)); 1066b63b70d8SShlomo Pongratz header = (struct ipoib_header *) skb->data; 1067b63b70d8SShlomo Pongratz 1068fc791b63SPaolo Abeni if (unlikely(phdr->hwaddr[4] == 0xff)) { 1069b63b70d8SShlomo Pongratz /* multicast, arrange "if" according to probability */ 1070b63b70d8SShlomo Pongratz if ((header->proto != htons(ETH_P_IP)) && 1071b63b70d8SShlomo Pongratz (header->proto != htons(ETH_P_IPV6)) && 1072b63b70d8SShlomo Pongratz (header->proto != htons(ETH_P_ARP)) && 1073dc850b0eSPatrick McHardy (header->proto != htons(ETH_P_RARP)) && 1074dc850b0eSPatrick McHardy (header->proto != htons(ETH_P_TIPC))) { 1075b63b70d8SShlomo Pongratz /* ethertype not supported by IPoIB */ 107617e6abeeSDavid Miller ++dev->stats.tx_dropped; 107717e6abeeSDavid Miller dev_kfree_skb_any(skb); 1078b63b70d8SShlomo Pongratz return NETDEV_TX_OK; 107917e6abeeSDavid Miller } 1080b63b70d8SShlomo Pongratz /* Add in the P_Key for multicast*/ 1081fc791b63SPaolo Abeni phdr->hwaddr[8] = (priv->pkey >> 8) & 0xff; 1082fc791b63SPaolo Abeni phdr->hwaddr[9] = priv->pkey & 0xff; 1083b63b70d8SShlomo Pongratz 1084fc791b63SPaolo Abeni neigh = ipoib_neigh_get(dev, phdr->hwaddr); 1085b63b70d8SShlomo Pongratz if (likely(neigh)) 1086b63b70d8SShlomo Pongratz goto send_using_neigh; 1087fc791b63SPaolo Abeni ipoib_mcast_send(dev, phdr->hwaddr, skb); 1088b63b70d8SShlomo Pongratz return NETDEV_TX_OK; 10891da177e4SLinus Torvalds } 10901da177e4SLinus Torvalds 1091b63b70d8SShlomo Pongratz /* unicast, arrange "switch" according to probability */ 1092b63b70d8SShlomo Pongratz switch (header->proto) { 1093b63b70d8SShlomo Pongratz case htons(ETH_P_IP): 1094b63b70d8SShlomo Pongratz case htons(ETH_P_IPV6): 1095dc850b0eSPatrick McHardy case htons(ETH_P_TIPC): 1096fc791b63SPaolo Abeni neigh = ipoib_neigh_get(dev, phdr->hwaddr); 1097b63b70d8SShlomo Pongratz if (unlikely(!neigh)) { 1098fc791b63SPaolo Abeni neigh_add_path(skb, phdr->hwaddr, dev); 1099b63b70d8SShlomo Pongratz return NETDEV_TX_OK; 1100b63b70d8SShlomo Pongratz } 1101b63b70d8SShlomo Pongratz break; 1102b63b70d8SShlomo Pongratz case htons(ETH_P_ARP): 1103b63b70d8SShlomo Pongratz case htons(ETH_P_RARP): 1104b63b70d8SShlomo Pongratz /* for unicast ARP and RARP should always perform path find */ 1105fc791b63SPaolo Abeni unicast_arp_send(skb, dev, phdr); 1106b63b70d8SShlomo Pongratz return NETDEV_TX_OK; 1107b63b70d8SShlomo Pongratz default: 1108b63b70d8SShlomo Pongratz /* ethertype not supported by IPoIB */ 1109b63b70d8SShlomo Pongratz ++dev->stats.tx_dropped; 1110b63b70d8SShlomo Pongratz dev_kfree_skb_any(skb); 1111b63b70d8SShlomo Pongratz return NETDEV_TX_OK; 11128a7f7521SMichael S. Tsirkin } 11138a7f7521SMichael S. Tsirkin 1114b63b70d8SShlomo Pongratz send_using_neigh: 1115b63b70d8SShlomo Pongratz /* note we now hold a ref to neigh */ 1116bafff974SOr Gerlitz if (ipoib_cm_get(neigh)) { 1117bafff974SOr Gerlitz if (ipoib_cm_up(neigh)) { 1118bafff974SOr Gerlitz ipoib_cm_send(dev, skb, ipoib_cm_get(neigh)); 1119b63b70d8SShlomo Pongratz goto unref; 1120bafff974SOr Gerlitz } 1121bafff974SOr Gerlitz } else if (neigh->ah) { 1122fc791b63SPaolo Abeni ipoib_send(dev, skb, neigh->ah, IPOIB_QPN(phdr->hwaddr)); 1123b63b70d8SShlomo Pongratz goto unref; 11241da177e4SLinus Torvalds } 11251da177e4SLinus Torvalds 11261da177e4SLinus Torvalds if (skb_queue_len(&neigh->queue) < IPOIB_MAX_PATH_REC_QUEUE) { 1127fc791b63SPaolo Abeni /* put pseudoheader back on for next time */ 1128fc791b63SPaolo Abeni skb_push(skb, sizeof(*phdr)); 1129943c246eSRoland Dreier spin_lock_irqsave(&priv->lock, flags); 11301da177e4SLinus Torvalds __skb_queue_tail(&neigh->queue, skb); 1131943c246eSRoland Dreier spin_unlock_irqrestore(&priv->lock, flags); 11321da177e4SLinus Torvalds } else { 1133de903512SRoland Dreier ++dev->stats.tx_dropped; 11341da177e4SLinus Torvalds dev_kfree_skb_any(skb); 11351da177e4SLinus Torvalds } 11361da177e4SLinus Torvalds 1137b63b70d8SShlomo Pongratz unref: 1138b63b70d8SShlomo Pongratz ipoib_neigh_put(neigh); 11391da177e4SLinus Torvalds 11401da177e4SLinus Torvalds return NETDEV_TX_OK; 11411da177e4SLinus Torvalds } 11421da177e4SLinus Torvalds 11431da177e4SLinus Torvalds static void ipoib_timeout(struct net_device *dev) 11441da177e4SLinus Torvalds { 11451da177e4SLinus Torvalds struct ipoib_dev_priv *priv = netdev_priv(dev); 11461da177e4SLinus Torvalds 11474b2d319bSRoland Dreier ipoib_warn(priv, "transmit timeout: latency %d msecs\n", 11484d0e9657SFlorian Westphal jiffies_to_msecs(jiffies - dev_trans_start(dev))); 11494b2d319bSRoland Dreier ipoib_warn(priv, "queue stopped %d, tx_head %u, tx_tail %u\n", 11504b2d319bSRoland Dreier netif_queue_stopped(dev), 11514b2d319bSRoland Dreier priv->tx_head, priv->tx_tail); 11521da177e4SLinus Torvalds /* XXX reset QP, etc. */ 11531da177e4SLinus Torvalds } 11541da177e4SLinus Torvalds 11551da177e4SLinus Torvalds static int ipoib_hard_header(struct sk_buff *skb, 11561da177e4SLinus Torvalds struct net_device *dev, 11571da177e4SLinus Torvalds unsigned short type, 11583b04dddeSStephen Hemminger const void *daddr, const void *saddr, unsigned len) 11591da177e4SLinus Torvalds { 1160fc791b63SPaolo Abeni struct ipoib_pseudo_header *phdr; 11611da177e4SLinus Torvalds struct ipoib_header *header; 11621da177e4SLinus Torvalds 11631da177e4SLinus Torvalds header = (struct ipoib_header *) skb_push(skb, sizeof *header); 11641da177e4SLinus Torvalds 11651da177e4SLinus Torvalds header->proto = htons(type); 11661da177e4SLinus Torvalds header->reserved = 0; 11671da177e4SLinus Torvalds 11681da177e4SLinus Torvalds /* 1169b63b70d8SShlomo Pongratz * we don't rely on dst_entry structure, always stuff the 1170fc791b63SPaolo Abeni * destination address into skb hard header so we can figure out where 1171936d7de3SRoland Dreier * to send the packet later. 11721da177e4SLinus Torvalds */ 1173fc791b63SPaolo Abeni phdr = (struct ipoib_pseudo_header *) skb_push(skb, sizeof(*phdr)); 1174fc791b63SPaolo Abeni memcpy(phdr->hwaddr, daddr, INFINIBAND_ALEN); 11751da177e4SLinus Torvalds 1176fc791b63SPaolo Abeni return IPOIB_HARD_LEN; 11771da177e4SLinus Torvalds } 11781da177e4SLinus Torvalds 11791da177e4SLinus Torvalds static void ipoib_set_mcast_list(struct net_device *dev) 11801da177e4SLinus Torvalds { 11811da177e4SLinus Torvalds struct ipoib_dev_priv *priv = netdev_priv(dev); 11821da177e4SLinus Torvalds 11837a343d4cSLeonid Arsh if (!test_bit(IPOIB_FLAG_OPER_UP, &priv->flags)) { 11847a343d4cSLeonid Arsh ipoib_dbg(priv, "IPOIB_FLAG_OPER_UP not set"); 11857a343d4cSLeonid Arsh return; 11867a343d4cSLeonid Arsh } 11877a343d4cSLeonid Arsh 11880b39578bSDoug Ledford queue_work(priv->wq, &priv->restart_task); 11891da177e4SLinus Torvalds } 11901da177e4SLinus Torvalds 11915aa7add8SNicolas Dichtel static int ipoib_get_iflink(const struct net_device *dev) 11925aa7add8SNicolas Dichtel { 11935aa7add8SNicolas Dichtel struct ipoib_dev_priv *priv = netdev_priv(dev); 11945aa7add8SNicolas Dichtel 11952c153959SErez Shitrit /* parent interface */ 11962c153959SErez Shitrit if (!test_bit(IPOIB_FLAG_SUBINTERFACE, &priv->flags)) 11972c153959SErez Shitrit return dev->ifindex; 11982c153959SErez Shitrit 11992c153959SErez Shitrit /* child/vlan interface */ 12005aa7add8SNicolas Dichtel return priv->parent->ifindex; 12015aa7add8SNicolas Dichtel } 12025aa7add8SNicolas Dichtel 1203b63b70d8SShlomo Pongratz static u32 ipoib_addr_hash(struct ipoib_neigh_hash *htbl, u8 *daddr) 12041da177e4SLinus Torvalds { 1205b63b70d8SShlomo Pongratz /* 1206b63b70d8SShlomo Pongratz * Use only the address parts that contributes to spreading 1207b63b70d8SShlomo Pongratz * The subnet prefix is not used as one can not connect to 1208b63b70d8SShlomo Pongratz * same remote port (GUID) using the same remote QPN via two 1209b63b70d8SShlomo Pongratz * different subnets. 1210b63b70d8SShlomo Pongratz */ 1211b63b70d8SShlomo Pongratz /* qpn octets[1:4) & port GUID octets[12:20) */ 12129d1ad66eSShlomo Pongratz u32 *d32 = (u32 *) daddr; 1213b63b70d8SShlomo Pongratz u32 hv; 12141da177e4SLinus Torvalds 12159d1ad66eSShlomo Pongratz hv = jhash_3words(d32[3], d32[4], IPOIB_QPN_MASK & d32[0], 0); 1216b63b70d8SShlomo Pongratz return hv & htbl->mask; 12171da177e4SLinus Torvalds } 12181da177e4SLinus Torvalds 1219b63b70d8SShlomo Pongratz struct ipoib_neigh *ipoib_neigh_get(struct net_device *dev, u8 *daddr) 1220b63b70d8SShlomo Pongratz { 1221b63b70d8SShlomo Pongratz struct ipoib_dev_priv *priv = netdev_priv(dev); 1222b63b70d8SShlomo Pongratz struct ipoib_neigh_table *ntbl = &priv->ntbl; 1223b63b70d8SShlomo Pongratz struct ipoib_neigh_hash *htbl; 1224b63b70d8SShlomo Pongratz struct ipoib_neigh *neigh = NULL; 1225b63b70d8SShlomo Pongratz u32 hash_val; 1226b63b70d8SShlomo Pongratz 1227b63b70d8SShlomo Pongratz rcu_read_lock_bh(); 1228b63b70d8SShlomo Pongratz 1229b63b70d8SShlomo Pongratz htbl = rcu_dereference_bh(ntbl->htbl); 1230b63b70d8SShlomo Pongratz 1231b63b70d8SShlomo Pongratz if (!htbl) 1232b63b70d8SShlomo Pongratz goto out_unlock; 1233b63b70d8SShlomo Pongratz 1234b63b70d8SShlomo Pongratz hash_val = ipoib_addr_hash(htbl, daddr); 1235b63b70d8SShlomo Pongratz for (neigh = rcu_dereference_bh(htbl->buckets[hash_val]); 1236b63b70d8SShlomo Pongratz neigh != NULL; 1237b63b70d8SShlomo Pongratz neigh = rcu_dereference_bh(neigh->hnext)) { 1238b63b70d8SShlomo Pongratz if (memcmp(daddr, neigh->daddr, INFINIBAND_ALEN) == 0) { 1239b63b70d8SShlomo Pongratz /* found, take one ref on behalf of the caller */ 1240b63b70d8SShlomo Pongratz if (!atomic_inc_not_zero(&neigh->refcnt)) { 1241b63b70d8SShlomo Pongratz /* deleted */ 1242b63b70d8SShlomo Pongratz neigh = NULL; 1243b63b70d8SShlomo Pongratz goto out_unlock; 1244b63b70d8SShlomo Pongratz } 124561c78eeaSErez Shitrit 124661c78eeaSErez Shitrit if (likely(skb_queue_len(&neigh->queue) < IPOIB_MAX_PATH_REC_QUEUE)) 1247b63b70d8SShlomo Pongratz neigh->alive = jiffies; 1248b63b70d8SShlomo Pongratz goto out_unlock; 1249b63b70d8SShlomo Pongratz } 1250b63b70d8SShlomo Pongratz } 1251b63b70d8SShlomo Pongratz 1252b63b70d8SShlomo Pongratz out_unlock: 1253b63b70d8SShlomo Pongratz rcu_read_unlock_bh(); 1254b63b70d8SShlomo Pongratz return neigh; 1255b63b70d8SShlomo Pongratz } 1256b63b70d8SShlomo Pongratz 1257b63b70d8SShlomo Pongratz static void __ipoib_reap_neigh(struct ipoib_dev_priv *priv) 1258b63b70d8SShlomo Pongratz { 1259b63b70d8SShlomo Pongratz struct ipoib_neigh_table *ntbl = &priv->ntbl; 1260b63b70d8SShlomo Pongratz struct ipoib_neigh_hash *htbl; 1261b63b70d8SShlomo Pongratz unsigned long neigh_obsolete; 1262b63b70d8SShlomo Pongratz unsigned long dt; 1263b63b70d8SShlomo Pongratz unsigned long flags; 1264b63b70d8SShlomo Pongratz int i; 1265bd99b2e0SChristoph Lameter LIST_HEAD(remove_list); 1266b63b70d8SShlomo Pongratz 1267b63b70d8SShlomo Pongratz if (test_bit(IPOIB_STOP_NEIGH_GC, &priv->flags)) 1268b63b70d8SShlomo Pongratz return; 1269b63b70d8SShlomo Pongratz 1270b5120a6eSShlomo Pongratz spin_lock_irqsave(&priv->lock, flags); 1271b63b70d8SShlomo Pongratz 1272b63b70d8SShlomo Pongratz htbl = rcu_dereference_protected(ntbl->htbl, 1273b5120a6eSShlomo Pongratz lockdep_is_held(&priv->lock)); 1274b63b70d8SShlomo Pongratz 1275b63b70d8SShlomo Pongratz if (!htbl) 1276b63b70d8SShlomo Pongratz goto out_unlock; 1277b63b70d8SShlomo Pongratz 1278b63b70d8SShlomo Pongratz /* neigh is obsolete if it was idle for two GC periods */ 1279b63b70d8SShlomo Pongratz dt = 2 * arp_tbl.gc_interval; 1280b63b70d8SShlomo Pongratz neigh_obsolete = jiffies - dt; 1281b63b70d8SShlomo Pongratz /* handle possible race condition */ 1282b63b70d8SShlomo Pongratz if (test_bit(IPOIB_STOP_NEIGH_GC, &priv->flags)) 1283b63b70d8SShlomo Pongratz goto out_unlock; 1284b63b70d8SShlomo Pongratz 1285b63b70d8SShlomo Pongratz for (i = 0; i < htbl->size; i++) { 1286b63b70d8SShlomo Pongratz struct ipoib_neigh *neigh; 1287b63b70d8SShlomo Pongratz struct ipoib_neigh __rcu **np = &htbl->buckets[i]; 1288b63b70d8SShlomo Pongratz 1289b63b70d8SShlomo Pongratz while ((neigh = rcu_dereference_protected(*np, 1290b5120a6eSShlomo Pongratz lockdep_is_held(&priv->lock))) != NULL) { 1291b63b70d8SShlomo Pongratz /* was the neigh idle for two GC periods */ 1292b63b70d8SShlomo Pongratz if (time_after(neigh_obsolete, neigh->alive)) { 1293bd99b2e0SChristoph Lameter 1294432c55ffSChristoph Lameter ipoib_check_and_add_mcast_sendonly(priv, neigh->daddr + 4, &remove_list); 1295bd99b2e0SChristoph Lameter 1296b63b70d8SShlomo Pongratz rcu_assign_pointer(*np, 1297b63b70d8SShlomo Pongratz rcu_dereference_protected(neigh->hnext, 1298b5120a6eSShlomo Pongratz lockdep_is_held(&priv->lock))); 1299b63b70d8SShlomo Pongratz /* remove from path/mc list */ 1300c586071dSFeras Daoud list_del_init(&neigh->list); 1301b63b70d8SShlomo Pongratz call_rcu(&neigh->rcu, ipoib_neigh_reclaim); 1302b63b70d8SShlomo Pongratz } else { 1303b63b70d8SShlomo Pongratz np = &neigh->hnext; 1304b63b70d8SShlomo Pongratz } 1305b63b70d8SShlomo Pongratz 1306b63b70d8SShlomo Pongratz } 1307b63b70d8SShlomo Pongratz } 1308b63b70d8SShlomo Pongratz 1309b63b70d8SShlomo Pongratz out_unlock: 1310b5120a6eSShlomo Pongratz spin_unlock_irqrestore(&priv->lock, flags); 131150be28deSErez Shitrit ipoib_mcast_remove_list(&remove_list); 1312b63b70d8SShlomo Pongratz } 1313b63b70d8SShlomo Pongratz 1314b63b70d8SShlomo Pongratz static void ipoib_reap_neigh(struct work_struct *work) 1315b63b70d8SShlomo Pongratz { 1316b63b70d8SShlomo Pongratz struct ipoib_dev_priv *priv = 1317b63b70d8SShlomo Pongratz container_of(work, struct ipoib_dev_priv, neigh_reap_task.work); 1318b63b70d8SShlomo Pongratz 1319b63b70d8SShlomo Pongratz __ipoib_reap_neigh(priv); 1320b63b70d8SShlomo Pongratz 1321b63b70d8SShlomo Pongratz if (!test_bit(IPOIB_STOP_NEIGH_GC, &priv->flags)) 13220b39578bSDoug Ledford queue_delayed_work(priv->wq, &priv->neigh_reap_task, 1323b63b70d8SShlomo Pongratz arp_tbl.gc_interval); 1324b63b70d8SShlomo Pongratz } 1325b63b70d8SShlomo Pongratz 1326b63b70d8SShlomo Pongratz 1327b63b70d8SShlomo Pongratz static struct ipoib_neigh *ipoib_neigh_ctor(u8 *daddr, 1328732a2170SMoni Shoua struct net_device *dev) 1329d2e0655eSMichael S. Tsirkin { 1330d2e0655eSMichael S. Tsirkin struct ipoib_neigh *neigh; 1331d2e0655eSMichael S. Tsirkin 1332b63b70d8SShlomo Pongratz neigh = kzalloc(sizeof *neigh, GFP_ATOMIC); 1333d2e0655eSMichael S. Tsirkin if (!neigh) 1334d2e0655eSMichael S. Tsirkin return NULL; 1335d2e0655eSMichael S. Tsirkin 1336732a2170SMoni Shoua neigh->dev = dev; 1337b63b70d8SShlomo Pongratz memcpy(&neigh->daddr, daddr, sizeof(neigh->daddr)); 133882b39913SRoland Dreier skb_queue_head_init(&neigh->queue); 1339b63b70d8SShlomo Pongratz INIT_LIST_HEAD(&neigh->list); 1340839fcabaSMichael S. Tsirkin ipoib_cm_set(neigh, NULL); 1341b63b70d8SShlomo Pongratz /* one ref on behalf of the caller */ 1342b63b70d8SShlomo Pongratz atomic_set(&neigh->refcnt, 1); 1343d2e0655eSMichael S. Tsirkin 1344d2e0655eSMichael S. Tsirkin return neigh; 1345d2e0655eSMichael S. Tsirkin } 1346d2e0655eSMichael S. Tsirkin 1347b63b70d8SShlomo Pongratz struct ipoib_neigh *ipoib_neigh_alloc(u8 *daddr, 1348b63b70d8SShlomo Pongratz struct net_device *dev) 1349d2e0655eSMichael S. Tsirkin { 1350b63b70d8SShlomo Pongratz struct ipoib_dev_priv *priv = netdev_priv(dev); 1351b63b70d8SShlomo Pongratz struct ipoib_neigh_table *ntbl = &priv->ntbl; 1352b63b70d8SShlomo Pongratz struct ipoib_neigh_hash *htbl; 1353b63b70d8SShlomo Pongratz struct ipoib_neigh *neigh; 1354b63b70d8SShlomo Pongratz u32 hash_val; 1355b63b70d8SShlomo Pongratz 1356b63b70d8SShlomo Pongratz htbl = rcu_dereference_protected(ntbl->htbl, 1357b5120a6eSShlomo Pongratz lockdep_is_held(&priv->lock)); 1358b63b70d8SShlomo Pongratz if (!htbl) { 1359b63b70d8SShlomo Pongratz neigh = NULL; 1360b63b70d8SShlomo Pongratz goto out_unlock; 1361b63b70d8SShlomo Pongratz } 1362b63b70d8SShlomo Pongratz 1363b63b70d8SShlomo Pongratz /* need to add a new neigh, but maybe some other thread succeeded? 1364b63b70d8SShlomo Pongratz * recalc hash, maybe hash resize took place so we do a search 1365b63b70d8SShlomo Pongratz */ 1366b63b70d8SShlomo Pongratz hash_val = ipoib_addr_hash(htbl, daddr); 1367b63b70d8SShlomo Pongratz for (neigh = rcu_dereference_protected(htbl->buckets[hash_val], 1368b5120a6eSShlomo Pongratz lockdep_is_held(&priv->lock)); 1369b63b70d8SShlomo Pongratz neigh != NULL; 1370b63b70d8SShlomo Pongratz neigh = rcu_dereference_protected(neigh->hnext, 1371b5120a6eSShlomo Pongratz lockdep_is_held(&priv->lock))) { 1372b63b70d8SShlomo Pongratz if (memcmp(daddr, neigh->daddr, INFINIBAND_ALEN) == 0) { 1373b63b70d8SShlomo Pongratz /* found, take one ref on behalf of the caller */ 1374b63b70d8SShlomo Pongratz if (!atomic_inc_not_zero(&neigh->refcnt)) { 1375b63b70d8SShlomo Pongratz /* deleted */ 1376b63b70d8SShlomo Pongratz neigh = NULL; 1377b63b70d8SShlomo Pongratz break; 1378b63b70d8SShlomo Pongratz } 1379b63b70d8SShlomo Pongratz neigh->alive = jiffies; 1380b63b70d8SShlomo Pongratz goto out_unlock; 1381b63b70d8SShlomo Pongratz } 1382b63b70d8SShlomo Pongratz } 1383b63b70d8SShlomo Pongratz 1384b63b70d8SShlomo Pongratz neigh = ipoib_neigh_ctor(daddr, dev); 1385b63b70d8SShlomo Pongratz if (!neigh) 1386b63b70d8SShlomo Pongratz goto out_unlock; 1387b63b70d8SShlomo Pongratz 1388b63b70d8SShlomo Pongratz /* one ref on behalf of the hash table */ 1389b63b70d8SShlomo Pongratz atomic_inc(&neigh->refcnt); 1390b63b70d8SShlomo Pongratz neigh->alive = jiffies; 1391b63b70d8SShlomo Pongratz /* put in hash */ 1392b63b70d8SShlomo Pongratz rcu_assign_pointer(neigh->hnext, 1393b63b70d8SShlomo Pongratz rcu_dereference_protected(htbl->buckets[hash_val], 1394b5120a6eSShlomo Pongratz lockdep_is_held(&priv->lock))); 1395b63b70d8SShlomo Pongratz rcu_assign_pointer(htbl->buckets[hash_val], neigh); 1396b63b70d8SShlomo Pongratz atomic_inc(&ntbl->entries); 1397b63b70d8SShlomo Pongratz 1398b63b70d8SShlomo Pongratz out_unlock: 1399b63b70d8SShlomo Pongratz 1400b63b70d8SShlomo Pongratz return neigh; 1401b63b70d8SShlomo Pongratz } 1402b63b70d8SShlomo Pongratz 1403b63b70d8SShlomo Pongratz void ipoib_neigh_dtor(struct ipoib_neigh *neigh) 1404b63b70d8SShlomo Pongratz { 1405b63b70d8SShlomo Pongratz /* neigh reference count was dropprd to zero */ 1406b63b70d8SShlomo Pongratz struct net_device *dev = neigh->dev; 1407b63b70d8SShlomo Pongratz struct ipoib_dev_priv *priv = netdev_priv(dev); 14082745b5b7SMichael S. Tsirkin struct sk_buff *skb; 1409b63b70d8SShlomo Pongratz if (neigh->ah) 1410b63b70d8SShlomo Pongratz ipoib_put_ah(neigh->ah); 14112745b5b7SMichael S. Tsirkin while ((skb = __skb_dequeue(&neigh->queue))) { 1412de903512SRoland Dreier ++dev->stats.tx_dropped; 14132745b5b7SMichael S. Tsirkin dev_kfree_skb_any(skb); 14142745b5b7SMichael S. Tsirkin } 1415839fcabaSMichael S. Tsirkin if (ipoib_cm_get(neigh)) 1416839fcabaSMichael S. Tsirkin ipoib_cm_destroy_tx(ipoib_cm_get(neigh)); 1417b63b70d8SShlomo Pongratz ipoib_dbg(netdev_priv(dev), 1418b63b70d8SShlomo Pongratz "neigh free for %06x %pI6\n", 1419b63b70d8SShlomo Pongratz IPOIB_QPN(neigh->daddr), 1420b63b70d8SShlomo Pongratz neigh->daddr + 4); 1421d2e0655eSMichael S. Tsirkin kfree(neigh); 1422b63b70d8SShlomo Pongratz if (atomic_dec_and_test(&priv->ntbl.entries)) { 1423b63b70d8SShlomo Pongratz if (test_bit(IPOIB_NEIGH_TBL_FLUSH, &priv->flags)) 1424b63b70d8SShlomo Pongratz complete(&priv->ntbl.flushed); 1425b63b70d8SShlomo Pongratz } 1426d2e0655eSMichael S. Tsirkin } 1427d2e0655eSMichael S. Tsirkin 1428b63b70d8SShlomo Pongratz static void ipoib_neigh_reclaim(struct rcu_head *rp) 14291da177e4SLinus Torvalds { 1430b63b70d8SShlomo Pongratz /* Called as a result of removal from hash table */ 1431b63b70d8SShlomo Pongratz struct ipoib_neigh *neigh = container_of(rp, struct ipoib_neigh, rcu); 1432b63b70d8SShlomo Pongratz /* note TX context may hold another ref */ 1433b63b70d8SShlomo Pongratz ipoib_neigh_put(neigh); 1434b63b70d8SShlomo Pongratz } 1435b63b70d8SShlomo Pongratz 1436b63b70d8SShlomo Pongratz void ipoib_neigh_free(struct ipoib_neigh *neigh) 1437b63b70d8SShlomo Pongratz { 1438b63b70d8SShlomo Pongratz struct net_device *dev = neigh->dev; 1439b63b70d8SShlomo Pongratz struct ipoib_dev_priv *priv = netdev_priv(dev); 1440b63b70d8SShlomo Pongratz struct ipoib_neigh_table *ntbl = &priv->ntbl; 1441b63b70d8SShlomo Pongratz struct ipoib_neigh_hash *htbl; 1442b63b70d8SShlomo Pongratz struct ipoib_neigh __rcu **np; 1443b63b70d8SShlomo Pongratz struct ipoib_neigh *n; 1444b63b70d8SShlomo Pongratz u32 hash_val; 1445b63b70d8SShlomo Pongratz 1446b63b70d8SShlomo Pongratz htbl = rcu_dereference_protected(ntbl->htbl, 1447b5120a6eSShlomo Pongratz lockdep_is_held(&priv->lock)); 1448b63b70d8SShlomo Pongratz if (!htbl) 1449b5120a6eSShlomo Pongratz return; 1450b63b70d8SShlomo Pongratz 1451b63b70d8SShlomo Pongratz hash_val = ipoib_addr_hash(htbl, neigh->daddr); 1452b63b70d8SShlomo Pongratz np = &htbl->buckets[hash_val]; 1453b63b70d8SShlomo Pongratz for (n = rcu_dereference_protected(*np, 1454b5120a6eSShlomo Pongratz lockdep_is_held(&priv->lock)); 1455b63b70d8SShlomo Pongratz n != NULL; 14566c723a68SShlomo Pongratz n = rcu_dereference_protected(*np, 1457b5120a6eSShlomo Pongratz lockdep_is_held(&priv->lock))) { 1458b63b70d8SShlomo Pongratz if (n == neigh) { 1459b63b70d8SShlomo Pongratz /* found */ 1460b63b70d8SShlomo Pongratz rcu_assign_pointer(*np, 1461b63b70d8SShlomo Pongratz rcu_dereference_protected(neigh->hnext, 1462b5120a6eSShlomo Pongratz lockdep_is_held(&priv->lock))); 146349b8e744SJim Foraker /* remove from parent list */ 1464c586071dSFeras Daoud list_del_init(&neigh->list); 1465b63b70d8SShlomo Pongratz call_rcu(&neigh->rcu, ipoib_neigh_reclaim); 1466b5120a6eSShlomo Pongratz return; 1467b63b70d8SShlomo Pongratz } else { 1468b63b70d8SShlomo Pongratz np = &n->hnext; 1469b63b70d8SShlomo Pongratz } 1470b63b70d8SShlomo Pongratz } 1471b63b70d8SShlomo Pongratz } 1472b63b70d8SShlomo Pongratz 1473b63b70d8SShlomo Pongratz static int ipoib_neigh_hash_init(struct ipoib_dev_priv *priv) 1474b63b70d8SShlomo Pongratz { 1475b63b70d8SShlomo Pongratz struct ipoib_neigh_table *ntbl = &priv->ntbl; 1476b63b70d8SShlomo Pongratz struct ipoib_neigh_hash *htbl; 147752374967SBart Van Assche struct ipoib_neigh __rcu **buckets; 1478b63b70d8SShlomo Pongratz u32 size; 1479b63b70d8SShlomo Pongratz 1480b63b70d8SShlomo Pongratz clear_bit(IPOIB_NEIGH_TBL_FLUSH, &priv->flags); 1481b63b70d8SShlomo Pongratz ntbl->htbl = NULL; 1482b63b70d8SShlomo Pongratz htbl = kzalloc(sizeof(*htbl), GFP_KERNEL); 1483b63b70d8SShlomo Pongratz if (!htbl) 1484b63b70d8SShlomo Pongratz return -ENOMEM; 1485b63b70d8SShlomo Pongratz set_bit(IPOIB_STOP_NEIGH_GC, &priv->flags); 1486b63b70d8SShlomo Pongratz size = roundup_pow_of_two(arp_tbl.gc_thresh3); 1487b63b70d8SShlomo Pongratz buckets = kzalloc(size * sizeof(*buckets), GFP_KERNEL); 1488b63b70d8SShlomo Pongratz if (!buckets) { 1489b63b70d8SShlomo Pongratz kfree(htbl); 1490b63b70d8SShlomo Pongratz return -ENOMEM; 1491b63b70d8SShlomo Pongratz } 1492b63b70d8SShlomo Pongratz htbl->size = size; 1493b63b70d8SShlomo Pongratz htbl->mask = (size - 1); 1494b63b70d8SShlomo Pongratz htbl->buckets = buckets; 149552374967SBart Van Assche RCU_INIT_POINTER(ntbl->htbl, htbl); 149666172c09SShlomo Pongratz htbl->ntbl = ntbl; 1497b63b70d8SShlomo Pongratz atomic_set(&ntbl->entries, 0); 1498b63b70d8SShlomo Pongratz 1499b63b70d8SShlomo Pongratz /* start garbage collection */ 1500b63b70d8SShlomo Pongratz clear_bit(IPOIB_STOP_NEIGH_GC, &priv->flags); 15010b39578bSDoug Ledford queue_delayed_work(priv->wq, &priv->neigh_reap_task, 1502b63b70d8SShlomo Pongratz arp_tbl.gc_interval); 15031da177e4SLinus Torvalds 15041da177e4SLinus Torvalds return 0; 15051da177e4SLinus Torvalds } 15061da177e4SLinus Torvalds 1507b63b70d8SShlomo Pongratz static void neigh_hash_free_rcu(struct rcu_head *head) 1508b63b70d8SShlomo Pongratz { 1509b63b70d8SShlomo Pongratz struct ipoib_neigh_hash *htbl = container_of(head, 1510b63b70d8SShlomo Pongratz struct ipoib_neigh_hash, 1511b63b70d8SShlomo Pongratz rcu); 1512b63b70d8SShlomo Pongratz struct ipoib_neigh __rcu **buckets = htbl->buckets; 151366172c09SShlomo Pongratz struct ipoib_neigh_table *ntbl = htbl->ntbl; 1514b63b70d8SShlomo Pongratz 1515b63b70d8SShlomo Pongratz kfree(buckets); 1516b63b70d8SShlomo Pongratz kfree(htbl); 151766172c09SShlomo Pongratz complete(&ntbl->deleted); 1518b63b70d8SShlomo Pongratz } 1519b63b70d8SShlomo Pongratz 1520b63b70d8SShlomo Pongratz void ipoib_del_neighs_by_gid(struct net_device *dev, u8 *gid) 1521b63b70d8SShlomo Pongratz { 1522b63b70d8SShlomo Pongratz struct ipoib_dev_priv *priv = netdev_priv(dev); 1523b63b70d8SShlomo Pongratz struct ipoib_neigh_table *ntbl = &priv->ntbl; 1524b63b70d8SShlomo Pongratz struct ipoib_neigh_hash *htbl; 1525b63b70d8SShlomo Pongratz unsigned long flags; 1526b63b70d8SShlomo Pongratz int i; 1527b63b70d8SShlomo Pongratz 1528b63b70d8SShlomo Pongratz /* remove all neigh connected to a given path or mcast */ 1529b5120a6eSShlomo Pongratz spin_lock_irqsave(&priv->lock, flags); 1530b63b70d8SShlomo Pongratz 1531b63b70d8SShlomo Pongratz htbl = rcu_dereference_protected(ntbl->htbl, 1532b5120a6eSShlomo Pongratz lockdep_is_held(&priv->lock)); 1533b63b70d8SShlomo Pongratz 1534b63b70d8SShlomo Pongratz if (!htbl) 1535b63b70d8SShlomo Pongratz goto out_unlock; 1536b63b70d8SShlomo Pongratz 1537b63b70d8SShlomo Pongratz for (i = 0; i < htbl->size; i++) { 1538b63b70d8SShlomo Pongratz struct ipoib_neigh *neigh; 1539b63b70d8SShlomo Pongratz struct ipoib_neigh __rcu **np = &htbl->buckets[i]; 1540b63b70d8SShlomo Pongratz 1541b63b70d8SShlomo Pongratz while ((neigh = rcu_dereference_protected(*np, 1542b5120a6eSShlomo Pongratz lockdep_is_held(&priv->lock))) != NULL) { 1543b63b70d8SShlomo Pongratz /* delete neighs belong to this parent */ 1544b63b70d8SShlomo Pongratz if (!memcmp(gid, neigh->daddr + 4, sizeof (union ib_gid))) { 1545b63b70d8SShlomo Pongratz rcu_assign_pointer(*np, 1546b63b70d8SShlomo Pongratz rcu_dereference_protected(neigh->hnext, 1547b5120a6eSShlomo Pongratz lockdep_is_held(&priv->lock))); 1548b63b70d8SShlomo Pongratz /* remove from parent list */ 1549c586071dSFeras Daoud list_del_init(&neigh->list); 1550b63b70d8SShlomo Pongratz call_rcu(&neigh->rcu, ipoib_neigh_reclaim); 1551b63b70d8SShlomo Pongratz } else { 1552b63b70d8SShlomo Pongratz np = &neigh->hnext; 1553b63b70d8SShlomo Pongratz } 1554b63b70d8SShlomo Pongratz 1555b63b70d8SShlomo Pongratz } 1556b63b70d8SShlomo Pongratz } 1557b63b70d8SShlomo Pongratz out_unlock: 1558b5120a6eSShlomo Pongratz spin_unlock_irqrestore(&priv->lock, flags); 1559b63b70d8SShlomo Pongratz } 1560b63b70d8SShlomo Pongratz 1561b63b70d8SShlomo Pongratz static void ipoib_flush_neighs(struct ipoib_dev_priv *priv) 1562b63b70d8SShlomo Pongratz { 1563b63b70d8SShlomo Pongratz struct ipoib_neigh_table *ntbl = &priv->ntbl; 1564b63b70d8SShlomo Pongratz struct ipoib_neigh_hash *htbl; 1565b63b70d8SShlomo Pongratz unsigned long flags; 156666172c09SShlomo Pongratz int i, wait_flushed = 0; 1567b63b70d8SShlomo Pongratz 156866172c09SShlomo Pongratz init_completion(&priv->ntbl.flushed); 1569b63b70d8SShlomo Pongratz 1570b5120a6eSShlomo Pongratz spin_lock_irqsave(&priv->lock, flags); 1571b63b70d8SShlomo Pongratz 1572b63b70d8SShlomo Pongratz htbl = rcu_dereference_protected(ntbl->htbl, 1573b5120a6eSShlomo Pongratz lockdep_is_held(&priv->lock)); 1574b63b70d8SShlomo Pongratz if (!htbl) 1575b63b70d8SShlomo Pongratz goto out_unlock; 1576b63b70d8SShlomo Pongratz 157766172c09SShlomo Pongratz wait_flushed = atomic_read(&priv->ntbl.entries); 157866172c09SShlomo Pongratz if (!wait_flushed) 157966172c09SShlomo Pongratz goto free_htbl; 158066172c09SShlomo Pongratz 1581b63b70d8SShlomo Pongratz for (i = 0; i < htbl->size; i++) { 1582b63b70d8SShlomo Pongratz struct ipoib_neigh *neigh; 1583b63b70d8SShlomo Pongratz struct ipoib_neigh __rcu **np = &htbl->buckets[i]; 1584b63b70d8SShlomo Pongratz 1585b63b70d8SShlomo Pongratz while ((neigh = rcu_dereference_protected(*np, 1586b5120a6eSShlomo Pongratz lockdep_is_held(&priv->lock))) != NULL) { 1587b63b70d8SShlomo Pongratz rcu_assign_pointer(*np, 1588b63b70d8SShlomo Pongratz rcu_dereference_protected(neigh->hnext, 1589b5120a6eSShlomo Pongratz lockdep_is_held(&priv->lock))); 1590b63b70d8SShlomo Pongratz /* remove from path/mc list */ 1591c586071dSFeras Daoud list_del_init(&neigh->list); 1592b63b70d8SShlomo Pongratz call_rcu(&neigh->rcu, ipoib_neigh_reclaim); 1593b63b70d8SShlomo Pongratz } 1594b63b70d8SShlomo Pongratz } 1595b63b70d8SShlomo Pongratz 159666172c09SShlomo Pongratz free_htbl: 1597b63b70d8SShlomo Pongratz rcu_assign_pointer(ntbl->htbl, NULL); 1598b63b70d8SShlomo Pongratz call_rcu(&htbl->rcu, neigh_hash_free_rcu); 1599b63b70d8SShlomo Pongratz 1600b63b70d8SShlomo Pongratz out_unlock: 1601b5120a6eSShlomo Pongratz spin_unlock_irqrestore(&priv->lock, flags); 160266172c09SShlomo Pongratz if (wait_flushed) 160366172c09SShlomo Pongratz wait_for_completion(&priv->ntbl.flushed); 1604b63b70d8SShlomo Pongratz } 1605b63b70d8SShlomo Pongratz 1606b63b70d8SShlomo Pongratz static void ipoib_neigh_hash_uninit(struct net_device *dev) 1607b63b70d8SShlomo Pongratz { 1608b63b70d8SShlomo Pongratz struct ipoib_dev_priv *priv = netdev_priv(dev); 1609b63b70d8SShlomo Pongratz int stopped; 1610b63b70d8SShlomo Pongratz 1611b63b70d8SShlomo Pongratz ipoib_dbg(priv, "ipoib_neigh_hash_uninit\n"); 161266172c09SShlomo Pongratz init_completion(&priv->ntbl.deleted); 1613b63b70d8SShlomo Pongratz set_bit(IPOIB_NEIGH_TBL_FLUSH, &priv->flags); 1614b63b70d8SShlomo Pongratz 1615b63b70d8SShlomo Pongratz /* Stop GC if called at init fail need to cancel work */ 1616b63b70d8SShlomo Pongratz stopped = test_and_set_bit(IPOIB_STOP_NEIGH_GC, &priv->flags); 1617b63b70d8SShlomo Pongratz if (!stopped) 1618b63b70d8SShlomo Pongratz cancel_delayed_work(&priv->neigh_reap_task); 1619b63b70d8SShlomo Pongratz 1620b63b70d8SShlomo Pongratz ipoib_flush_neighs(priv); 162166172c09SShlomo Pongratz 162266172c09SShlomo Pongratz wait_for_completion(&priv->ntbl.deleted); 1623b63b70d8SShlomo Pongratz } 1624b63b70d8SShlomo Pongratz 1625b63b70d8SShlomo Pongratz 16261da177e4SLinus Torvalds int ipoib_dev_init(struct net_device *dev, struct ib_device *ca, int port) 16271da177e4SLinus Torvalds { 16281da177e4SLinus Torvalds struct ipoib_dev_priv *priv = netdev_priv(dev); 16291da177e4SLinus Torvalds 16301da177e4SLinus Torvalds /* Allocate RX/TX "rings" to hold queued skbs */ 16310f485251SShirley Ma priv->rx_ring = kzalloc(ipoib_recvq_size * sizeof *priv->rx_ring, 16321da177e4SLinus Torvalds GFP_KERNEL); 163374226649SLeon Romanovsky if (!priv->rx_ring) 1634be7aa663SDoug Ledford goto out; 16351da177e4SLinus Torvalds 1636948579cdSJoe Perches priv->tx_ring = vzalloc(ipoib_sendq_size * sizeof *priv->tx_ring); 16371da177e4SLinus Torvalds if (!priv->tx_ring) { 16381da177e4SLinus Torvalds printk(KERN_WARNING "%s: failed to allocate TX ring (%d entries)\n", 16390f485251SShirley Ma ca->name, ipoib_sendq_size); 16401da177e4SLinus Torvalds goto out_rx_ring_cleanup; 16411da177e4SLinus Torvalds } 16421da177e4SLinus Torvalds 16431b524963SMichael S. Tsirkin /* priv->tx_head, tx_tail & tx_outstanding are already 0 */ 16441da177e4SLinus Torvalds 16451da177e4SLinus Torvalds if (ipoib_ib_dev_init(dev, ca, port)) 16461da177e4SLinus Torvalds goto out_tx_ring_cleanup; 16471da177e4SLinus Torvalds 1648be7aa663SDoug Ledford /* 1649be7aa663SDoug Ledford * Must be after ipoib_ib_dev_init so we can allocate a per 1650be7aa663SDoug Ledford * device wq there and use it here 1651be7aa663SDoug Ledford */ 1652be7aa663SDoug Ledford if (ipoib_neigh_hash_init(priv) < 0) 1653be7aa663SDoug Ledford goto out_dev_uninit; 1654be7aa663SDoug Ledford 16551da177e4SLinus Torvalds return 0; 16561da177e4SLinus Torvalds 1657be7aa663SDoug Ledford out_dev_uninit: 1658be7aa663SDoug Ledford ipoib_ib_dev_cleanup(dev); 1659be7aa663SDoug Ledford 16601da177e4SLinus Torvalds out_tx_ring_cleanup: 166110313cbbSRoland Dreier vfree(priv->tx_ring); 16621da177e4SLinus Torvalds 16631da177e4SLinus Torvalds out_rx_ring_cleanup: 16641da177e4SLinus Torvalds kfree(priv->rx_ring); 16651da177e4SLinus Torvalds 16661da177e4SLinus Torvalds out: 16671da177e4SLinus Torvalds return -ENOMEM; 16681da177e4SLinus Torvalds } 16691da177e4SLinus Torvalds 16701da177e4SLinus Torvalds void ipoib_dev_cleanup(struct net_device *dev) 16711da177e4SLinus Torvalds { 16721da177e4SLinus Torvalds struct ipoib_dev_priv *priv = netdev_priv(dev), *cpriv, *tcpriv; 16739baa0b03SOr Gerlitz LIST_HEAD(head); 16749baa0b03SOr Gerlitz 16759baa0b03SOr Gerlitz ASSERT_RTNL(); 16761da177e4SLinus Torvalds 16771732b0efSRoland Dreier ipoib_delete_debug_files(dev); 16781da177e4SLinus Torvalds 16791da177e4SLinus Torvalds /* Delete any child interfaces first */ 16801da177e4SLinus Torvalds list_for_each_entry_safe(cpriv, tcpriv, &priv->child_intfs, list) { 1681b63b70d8SShlomo Pongratz /* Stop GC on child */ 1682b63b70d8SShlomo Pongratz set_bit(IPOIB_STOP_NEIGH_GC, &cpriv->flags); 1683b63b70d8SShlomo Pongratz cancel_delayed_work(&cpriv->neigh_reap_task); 16849baa0b03SOr Gerlitz unregister_netdevice_queue(cpriv->dev, &head); 16851da177e4SLinus Torvalds } 16869baa0b03SOr Gerlitz unregister_netdevice_many(&head); 16871da177e4SLinus Torvalds 1688be7aa663SDoug Ledford /* 1689be7aa663SDoug Ledford * Must be before ipoib_ib_dev_cleanup or we delete an in use 1690be7aa663SDoug Ledford * work queue 1691be7aa663SDoug Ledford */ 1692be7aa663SDoug Ledford ipoib_neigh_hash_uninit(dev); 1693be7aa663SDoug Ledford 16941da177e4SLinus Torvalds ipoib_ib_dev_cleanup(dev); 16951da177e4SLinus Torvalds 16961da177e4SLinus Torvalds kfree(priv->rx_ring); 169710313cbbSRoland Dreier vfree(priv->tx_ring); 169892a6b34bSHal Rosenstock 169992a6b34bSHal Rosenstock priv->rx_ring = NULL; 17001da177e4SLinus Torvalds priv->tx_ring = NULL; 17011da177e4SLinus Torvalds } 17021da177e4SLinus Torvalds 17039c3c5f8eSEli Cohen static int ipoib_set_vf_link_state(struct net_device *dev, int vf, int link_state) 17049c3c5f8eSEli Cohen { 17059c3c5f8eSEli Cohen struct ipoib_dev_priv *priv = netdev_priv(dev); 17069c3c5f8eSEli Cohen 17079c3c5f8eSEli Cohen return ib_set_vf_link_state(priv->ca, vf, priv->port, link_state); 17089c3c5f8eSEli Cohen } 17099c3c5f8eSEli Cohen 17109c3c5f8eSEli Cohen static int ipoib_get_vf_config(struct net_device *dev, int vf, 17119c3c5f8eSEli Cohen struct ifla_vf_info *ivf) 17129c3c5f8eSEli Cohen { 17139c3c5f8eSEli Cohen struct ipoib_dev_priv *priv = netdev_priv(dev); 17149c3c5f8eSEli Cohen int err; 17159c3c5f8eSEli Cohen 17169c3c5f8eSEli Cohen err = ib_get_vf_config(priv->ca, vf, priv->port, ivf); 17179c3c5f8eSEli Cohen if (err) 17189c3c5f8eSEli Cohen return err; 17199c3c5f8eSEli Cohen 17209c3c5f8eSEli Cohen ivf->vf = vf; 17219c3c5f8eSEli Cohen 17229c3c5f8eSEli Cohen return 0; 17239c3c5f8eSEli Cohen } 17249c3c5f8eSEli Cohen 17259c3c5f8eSEli Cohen static int ipoib_set_vf_guid(struct net_device *dev, int vf, u64 guid, int type) 17269c3c5f8eSEli Cohen { 17279c3c5f8eSEli Cohen struct ipoib_dev_priv *priv = netdev_priv(dev); 17289c3c5f8eSEli Cohen 17299c3c5f8eSEli Cohen if (type != IFLA_VF_IB_NODE_GUID && type != IFLA_VF_IB_PORT_GUID) 17309c3c5f8eSEli Cohen return -EINVAL; 17319c3c5f8eSEli Cohen 17329c3c5f8eSEli Cohen return ib_set_vf_guid(priv->ca, vf, priv->port, guid, type); 17339c3c5f8eSEli Cohen } 17349c3c5f8eSEli Cohen 17359c3c5f8eSEli Cohen static int ipoib_get_vf_stats(struct net_device *dev, int vf, 17369c3c5f8eSEli Cohen struct ifla_vf_stats *vf_stats) 17379c3c5f8eSEli Cohen { 17389c3c5f8eSEli Cohen struct ipoib_dev_priv *priv = netdev_priv(dev); 17399c3c5f8eSEli Cohen 17409c3c5f8eSEli Cohen return ib_get_vf_stats(priv->ca, vf, priv->port, vf_stats); 17419c3c5f8eSEli Cohen } 17429c3c5f8eSEli Cohen 17433b04dddeSStephen Hemminger static const struct header_ops ipoib_header_ops = { 17443b04dddeSStephen Hemminger .create = ipoib_hard_header, 17453b04dddeSStephen Hemminger }; 17463b04dddeSStephen Hemminger 17479c3c5f8eSEli Cohen static const struct net_device_ops ipoib_netdev_ops_pf = { 17489c3c5f8eSEli Cohen .ndo_uninit = ipoib_uninit, 17499c3c5f8eSEli Cohen .ndo_open = ipoib_open, 17509c3c5f8eSEli Cohen .ndo_stop = ipoib_stop, 17519c3c5f8eSEli Cohen .ndo_change_mtu = ipoib_change_mtu, 17529c3c5f8eSEli Cohen .ndo_fix_features = ipoib_fix_features, 17539c3c5f8eSEli Cohen .ndo_start_xmit = ipoib_start_xmit, 17549c3c5f8eSEli Cohen .ndo_tx_timeout = ipoib_timeout, 17559c3c5f8eSEli Cohen .ndo_set_rx_mode = ipoib_set_mcast_list, 17569c3c5f8eSEli Cohen .ndo_get_iflink = ipoib_get_iflink, 17579c3c5f8eSEli Cohen .ndo_set_vf_link_state = ipoib_set_vf_link_state, 17589c3c5f8eSEli Cohen .ndo_get_vf_config = ipoib_get_vf_config, 17599c3c5f8eSEli Cohen .ndo_get_vf_stats = ipoib_get_vf_stats, 17609c3c5f8eSEli Cohen .ndo_set_vf_guid = ipoib_set_vf_guid, 1761492a7e67SMark Bloch .ndo_set_mac_address = ipoib_set_mac, 17629c3c5f8eSEli Cohen }; 17639c3c5f8eSEli Cohen 17649c3c5f8eSEli Cohen static const struct net_device_ops ipoib_netdev_ops_vf = { 17659baa0b03SOr Gerlitz .ndo_uninit = ipoib_uninit, 1766fe8114e8SStephen Hemminger .ndo_open = ipoib_open, 1767fe8114e8SStephen Hemminger .ndo_stop = ipoib_stop, 1768fe8114e8SStephen Hemminger .ndo_change_mtu = ipoib_change_mtu, 17693d96c74dSMichał Mirosław .ndo_fix_features = ipoib_fix_features, 1770fe8114e8SStephen Hemminger .ndo_start_xmit = ipoib_start_xmit, 1771fe8114e8SStephen Hemminger .ndo_tx_timeout = ipoib_timeout, 1772afc4b13dSJiri Pirko .ndo_set_rx_mode = ipoib_set_mcast_list, 17735aa7add8SNicolas Dichtel .ndo_get_iflink = ipoib_get_iflink, 1774fe8114e8SStephen Hemminger }; 1775fe8114e8SStephen Hemminger 17769baa0b03SOr Gerlitz void ipoib_setup(struct net_device *dev) 17771da177e4SLinus Torvalds { 17781da177e4SLinus Torvalds struct ipoib_dev_priv *priv = netdev_priv(dev); 17791da177e4SLinus Torvalds 17809c3c5f8eSEli Cohen if (priv->hca_caps & IB_DEVICE_VIRTUAL_FUNCTION) 17819c3c5f8eSEli Cohen dev->netdev_ops = &ipoib_netdev_ops_vf; 17829c3c5f8eSEli Cohen else 17839c3c5f8eSEli Cohen dev->netdev_ops = &ipoib_netdev_ops_pf; 17849c3c5f8eSEli Cohen 17853b04dddeSStephen Hemminger dev->header_ops = &ipoib_header_ops; 1786bea3348eSStephen Hemminger 178782c24c18SEli Cohen ipoib_set_ethtool_ops(dev); 178882c24c18SEli Cohen 17897f1a3867SMichal Schmidt netif_napi_add(dev, &priv->napi, ipoib_poll, NAPI_POLL_WEIGHT); 17901da177e4SLinus Torvalds 17911da177e4SLinus Torvalds dev->watchdog_timeo = HZ; 17921da177e4SLinus Torvalds 17931da177e4SLinus Torvalds dev->flags |= IFF_BROADCAST | IFF_MULTICAST; 17941da177e4SLinus Torvalds 1795fc791b63SPaolo Abeni dev->hard_header_len = IPOIB_HARD_LEN; 17961da177e4SLinus Torvalds dev->addr_len = INFINIBAND_ALEN; 17971da177e4SLinus Torvalds dev->type = ARPHRD_INFINIBAND; 17980f485251SShirley Ma dev->tx_queue_len = ipoib_sendq_size * 2; 1799eb14032fSEli Cohen dev->features = (NETIF_F_VLAN_CHALLENGED | 1800eb14032fSEli Cohen NETIF_F_HIGHDMA); 180102875878SEric Dumazet netif_keep_dst(dev); 18021da177e4SLinus Torvalds 18031da177e4SLinus Torvalds memcpy(dev->broadcast, ipv4_bcast_addr, INFINIBAND_ALEN); 18041da177e4SLinus Torvalds 18051da177e4SLinus Torvalds priv->dev = dev; 18061da177e4SLinus Torvalds 18071da177e4SLinus Torvalds spin_lock_init(&priv->lock); 18081da177e4SLinus Torvalds 1809f47944ccSErez Shitrit init_rwsem(&priv->vlan_rwsem); 18101da177e4SLinus Torvalds 18111da177e4SLinus Torvalds INIT_LIST_HEAD(&priv->path_list); 18121da177e4SLinus Torvalds INIT_LIST_HEAD(&priv->child_intfs); 18131da177e4SLinus Torvalds INIT_LIST_HEAD(&priv->dead_ahs); 18141da177e4SLinus Torvalds INIT_LIST_HEAD(&priv->multicast_list); 18151da177e4SLinus Torvalds 1816c4028958SDavid Howells INIT_DELAYED_WORK(&priv->mcast_task, ipoib_mcast_join_task); 1817e8224e4bSYossi Etigin INIT_WORK(&priv->carrier_on_task, ipoib_mcast_carrier_on_task); 1818ee1e2c82SMoni Shoua INIT_WORK(&priv->flush_light, ipoib_ib_dev_flush_light); 1819ee1e2c82SMoni Shoua INIT_WORK(&priv->flush_normal, ipoib_ib_dev_flush_normal); 1820ee1e2c82SMoni Shoua INIT_WORK(&priv->flush_heavy, ipoib_ib_dev_flush_heavy); 1821c4028958SDavid Howells INIT_WORK(&priv->restart_task, ipoib_mcast_restart_task); 1822c4028958SDavid Howells INIT_DELAYED_WORK(&priv->ah_reap_task, ipoib_reap_ah); 1823b63b70d8SShlomo Pongratz INIT_DELAYED_WORK(&priv->neigh_reap_task, ipoib_reap_neigh); 18241da177e4SLinus Torvalds } 18251da177e4SLinus Torvalds 18261da177e4SLinus Torvalds struct ipoib_dev_priv *ipoib_intf_alloc(const char *name) 18271da177e4SLinus Torvalds { 18281da177e4SLinus Torvalds struct net_device *dev; 18291da177e4SLinus Torvalds 18301da177e4SLinus Torvalds dev = alloc_netdev((int)sizeof(struct ipoib_dev_priv), name, 1831c835a677STom Gundersen NET_NAME_UNKNOWN, ipoib_setup); 18321da177e4SLinus Torvalds if (!dev) 18331da177e4SLinus Torvalds return NULL; 18341da177e4SLinus Torvalds 18351da177e4SLinus Torvalds return netdev_priv(dev); 18361da177e4SLinus Torvalds } 18371da177e4SLinus Torvalds 183843cb76d9SGreg Kroah-Hartman static ssize_t show_pkey(struct device *dev, 183943cb76d9SGreg Kroah-Hartman struct device_attribute *attr, char *buf) 18401da177e4SLinus Torvalds { 184143cb76d9SGreg Kroah-Hartman struct ipoib_dev_priv *priv = netdev_priv(to_net_dev(dev)); 18421da177e4SLinus Torvalds 18431da177e4SLinus Torvalds return sprintf(buf, "0x%04x\n", priv->pkey); 18441da177e4SLinus Torvalds } 184543cb76d9SGreg Kroah-Hartman static DEVICE_ATTR(pkey, S_IRUGO, show_pkey, NULL); 18461da177e4SLinus Torvalds 1847335a64a5SOr Gerlitz static ssize_t show_umcast(struct device *dev, 1848335a64a5SOr Gerlitz struct device_attribute *attr, char *buf) 1849335a64a5SOr Gerlitz { 1850335a64a5SOr Gerlitz struct ipoib_dev_priv *priv = netdev_priv(to_net_dev(dev)); 1851335a64a5SOr Gerlitz 1852335a64a5SOr Gerlitz return sprintf(buf, "%d\n", test_bit(IPOIB_FLAG_UMCAST, &priv->flags)); 1853335a64a5SOr Gerlitz } 1854335a64a5SOr Gerlitz 1855862096a8SOr Gerlitz void ipoib_set_umcast(struct net_device *ndev, int umcast_val) 1856335a64a5SOr Gerlitz { 1857862096a8SOr Gerlitz struct ipoib_dev_priv *priv = netdev_priv(ndev); 1858335a64a5SOr Gerlitz 1859335a64a5SOr Gerlitz if (umcast_val > 0) { 1860335a64a5SOr Gerlitz set_bit(IPOIB_FLAG_UMCAST, &priv->flags); 1861335a64a5SOr Gerlitz ipoib_warn(priv, "ignoring multicast groups joined directly " 1862335a64a5SOr Gerlitz "by userspace\n"); 1863335a64a5SOr Gerlitz } else 1864335a64a5SOr Gerlitz clear_bit(IPOIB_FLAG_UMCAST, &priv->flags); 1865862096a8SOr Gerlitz } 1866862096a8SOr Gerlitz 1867862096a8SOr Gerlitz static ssize_t set_umcast(struct device *dev, 1868862096a8SOr Gerlitz struct device_attribute *attr, 1869862096a8SOr Gerlitz const char *buf, size_t count) 1870862096a8SOr Gerlitz { 1871862096a8SOr Gerlitz unsigned long umcast_val = simple_strtoul(buf, NULL, 0); 1872862096a8SOr Gerlitz 1873862096a8SOr Gerlitz ipoib_set_umcast(to_net_dev(dev), umcast_val); 1874335a64a5SOr Gerlitz 1875335a64a5SOr Gerlitz return count; 1876335a64a5SOr Gerlitz } 1877335a64a5SOr Gerlitz static DEVICE_ATTR(umcast, S_IWUSR | S_IRUGO, show_umcast, set_umcast); 1878335a64a5SOr Gerlitz 1879335a64a5SOr Gerlitz int ipoib_add_umcast_attr(struct net_device *dev) 1880335a64a5SOr Gerlitz { 1881335a64a5SOr Gerlitz return device_create_file(&dev->dev, &dev_attr_umcast); 1882335a64a5SOr Gerlitz } 1883335a64a5SOr Gerlitz 1884492a7e67SMark Bloch static void set_base_guid(struct ipoib_dev_priv *priv, union ib_gid *gid) 1885492a7e67SMark Bloch { 1886492a7e67SMark Bloch struct ipoib_dev_priv *child_priv; 1887492a7e67SMark Bloch struct net_device *netdev = priv->dev; 1888492a7e67SMark Bloch 18899b29953bSMark Bloch netif_addr_lock_bh(netdev); 1890492a7e67SMark Bloch 1891492a7e67SMark Bloch memcpy(&priv->local_gid.global.interface_id, 1892492a7e67SMark Bloch &gid->global.interface_id, 1893492a7e67SMark Bloch sizeof(gid->global.interface_id)); 1894492a7e67SMark Bloch memcpy(netdev->dev_addr + 4, &priv->local_gid, sizeof(priv->local_gid)); 1895492a7e67SMark Bloch clear_bit(IPOIB_FLAG_DEV_ADDR_SET, &priv->flags); 1896492a7e67SMark Bloch 18979b29953bSMark Bloch netif_addr_unlock_bh(netdev); 1898492a7e67SMark Bloch 1899492a7e67SMark Bloch if (!test_bit(IPOIB_FLAG_SUBINTERFACE, &priv->flags)) { 1900492a7e67SMark Bloch down_read(&priv->vlan_rwsem); 1901492a7e67SMark Bloch list_for_each_entry(child_priv, &priv->child_intfs, list) 1902492a7e67SMark Bloch set_base_guid(child_priv, gid); 1903492a7e67SMark Bloch up_read(&priv->vlan_rwsem); 1904492a7e67SMark Bloch } 1905492a7e67SMark Bloch } 1906492a7e67SMark Bloch 1907492a7e67SMark Bloch static int ipoib_check_lladdr(struct net_device *dev, 1908492a7e67SMark Bloch struct sockaddr_storage *ss) 1909492a7e67SMark Bloch { 1910492a7e67SMark Bloch union ib_gid *gid = (union ib_gid *)(ss->__data + 4); 1911492a7e67SMark Bloch int ret = 0; 1912492a7e67SMark Bloch 19139b29953bSMark Bloch netif_addr_lock_bh(dev); 1914492a7e67SMark Bloch 1915492a7e67SMark Bloch /* Make sure the QPN, reserved and subnet prefix match the current 1916492a7e67SMark Bloch * lladdr, it also makes sure the lladdr is unicast. 1917492a7e67SMark Bloch */ 1918492a7e67SMark Bloch if (memcmp(dev->dev_addr, ss->__data, 1919492a7e67SMark Bloch 4 + sizeof(gid->global.subnet_prefix)) || 1920492a7e67SMark Bloch gid->global.interface_id == 0) 1921492a7e67SMark Bloch ret = -EINVAL; 1922492a7e67SMark Bloch 19239b29953bSMark Bloch netif_addr_unlock_bh(dev); 1924492a7e67SMark Bloch 1925492a7e67SMark Bloch return ret; 1926492a7e67SMark Bloch } 1927492a7e67SMark Bloch 1928492a7e67SMark Bloch static int ipoib_set_mac(struct net_device *dev, void *addr) 1929492a7e67SMark Bloch { 1930492a7e67SMark Bloch struct ipoib_dev_priv *priv = netdev_priv(dev); 1931492a7e67SMark Bloch struct sockaddr_storage *ss = addr; 1932492a7e67SMark Bloch int ret; 1933492a7e67SMark Bloch 1934492a7e67SMark Bloch if (!(dev->priv_flags & IFF_LIVE_ADDR_CHANGE) && netif_running(dev)) 1935492a7e67SMark Bloch return -EBUSY; 1936492a7e67SMark Bloch 1937492a7e67SMark Bloch ret = ipoib_check_lladdr(dev, ss); 1938492a7e67SMark Bloch if (ret) 1939492a7e67SMark Bloch return ret; 1940492a7e67SMark Bloch 1941492a7e67SMark Bloch set_base_guid(priv, (union ib_gid *)(ss->__data + 4)); 1942492a7e67SMark Bloch 1943492a7e67SMark Bloch queue_work(ipoib_workqueue, &priv->flush_light); 1944492a7e67SMark Bloch 1945492a7e67SMark Bloch return 0; 1946492a7e67SMark Bloch } 1947492a7e67SMark Bloch 194843cb76d9SGreg Kroah-Hartman static ssize_t create_child(struct device *dev, 194943cb76d9SGreg Kroah-Hartman struct device_attribute *attr, 19501da177e4SLinus Torvalds const char *buf, size_t count) 19511da177e4SLinus Torvalds { 19521da177e4SLinus Torvalds int pkey; 19531da177e4SLinus Torvalds int ret; 19541da177e4SLinus Torvalds 19551da177e4SLinus Torvalds if (sscanf(buf, "%i", &pkey) != 1) 19561da177e4SLinus Torvalds return -EINVAL; 19571da177e4SLinus Torvalds 19583d790a4cSOr Gerlitz if (pkey <= 0 || pkey > 0xffff || pkey == 0x8000) 19591da177e4SLinus Torvalds return -EINVAL; 19601da177e4SLinus Torvalds 19614ce05937SRoland Dreier /* 19624ce05937SRoland Dreier * Set the full membership bit, so that we join the right 19634ce05937SRoland Dreier * broadcast group, etc. 19644ce05937SRoland Dreier */ 19654ce05937SRoland Dreier pkey |= 0x8000; 19664ce05937SRoland Dreier 196743cb76d9SGreg Kroah-Hartman ret = ipoib_vlan_add(to_net_dev(dev), pkey); 19681da177e4SLinus Torvalds 19691da177e4SLinus Torvalds return ret ? ret : count; 19701da177e4SLinus Torvalds } 19717a52b34bSOr Gerlitz static DEVICE_ATTR(create_child, S_IWUSR, NULL, create_child); 19721da177e4SLinus Torvalds 197343cb76d9SGreg Kroah-Hartman static ssize_t delete_child(struct device *dev, 197443cb76d9SGreg Kroah-Hartman struct device_attribute *attr, 19751da177e4SLinus Torvalds const char *buf, size_t count) 19761da177e4SLinus Torvalds { 19771da177e4SLinus Torvalds int pkey; 19781da177e4SLinus Torvalds int ret; 19791da177e4SLinus Torvalds 19801da177e4SLinus Torvalds if (sscanf(buf, "%i", &pkey) != 1) 19811da177e4SLinus Torvalds return -EINVAL; 19821da177e4SLinus Torvalds 19831da177e4SLinus Torvalds if (pkey < 0 || pkey > 0xffff) 19841da177e4SLinus Torvalds return -EINVAL; 19851da177e4SLinus Torvalds 198643cb76d9SGreg Kroah-Hartman ret = ipoib_vlan_delete(to_net_dev(dev), pkey); 19871da177e4SLinus Torvalds 19881da177e4SLinus Torvalds return ret ? ret : count; 19891da177e4SLinus Torvalds 19901da177e4SLinus Torvalds } 19917a52b34bSOr Gerlitz static DEVICE_ATTR(delete_child, S_IWUSR, NULL, delete_child); 19921da177e4SLinus Torvalds 19931da177e4SLinus Torvalds int ipoib_add_pkey_attr(struct net_device *dev) 19941da177e4SLinus Torvalds { 199543cb76d9SGreg Kroah-Hartman return device_create_file(&dev->dev, &dev_attr_pkey); 19961da177e4SLinus Torvalds } 19971da177e4SLinus Torvalds 199883bb63f6SOr Gerlitz int ipoib_set_dev_features(struct ipoib_dev_priv *priv, struct ib_device *hca) 199983bb63f6SOr Gerlitz { 20004a061b28SOr Gerlitz priv->hca_caps = hca->attrs.device_cap_flags; 200183bb63f6SOr Gerlitz 200283bb63f6SOr Gerlitz if (priv->hca_caps & IB_DEVICE_UD_IP_CSUM) { 20035faba546SYuval Shaia priv->dev->hw_features = NETIF_F_IP_CSUM | NETIF_F_RXCSUM; 20043d96c74dSMichał Mirosław 20053d96c74dSMichał Mirosław if (priv->hca_caps & IB_DEVICE_UD_TSO) 20063d96c74dSMichał Mirosław priv->dev->hw_features |= NETIF_F_TSO; 20073d96c74dSMichał Mirosław 20083d96c74dSMichał Mirosław priv->dev->features |= priv->dev->hw_features; 200983bb63f6SOr Gerlitz } 201083bb63f6SOr Gerlitz 201183bb63f6SOr Gerlitz return 0; 201283bb63f6SOr Gerlitz } 201383bb63f6SOr Gerlitz 20141da177e4SLinus Torvalds static struct net_device *ipoib_add_port(const char *format, 20151da177e4SLinus Torvalds struct ib_device *hca, u8 port) 20161da177e4SLinus Torvalds { 20171da177e4SLinus Torvalds struct ipoib_dev_priv *priv; 2018bc7b3a36SShirley Ma struct ib_port_attr attr; 20191da177e4SLinus Torvalds int result = -ENOMEM; 20201da177e4SLinus Torvalds 20211da177e4SLinus Torvalds priv = ipoib_intf_alloc(format); 20221da177e4SLinus Torvalds if (!priv) 20231da177e4SLinus Torvalds goto alloc_mem_failed; 20241da177e4SLinus Torvalds 2025db97ed0aSBart Van Assche SET_NETDEV_DEV(priv->dev, hca->dev.parent); 2026c3aa9b18SEli Cohen priv->dev->dev_id = port - 1; 20271da177e4SLinus Torvalds 202858e9cc90SAmir Vadai result = ib_query_port(hca, port, &attr); 202958e9cc90SAmir Vadai if (!result) 2030bc7b3a36SShirley Ma priv->max_ib_mtu = ib_mtu_enum_to_int(attr.max_mtu); 2031bc7b3a36SShirley Ma else { 2032bc7b3a36SShirley Ma printk(KERN_WARNING "%s: ib_query_port %d failed\n", 2033bc7b3a36SShirley Ma hca->name, port); 2034bc7b3a36SShirley Ma goto device_init_failed; 2035bc7b3a36SShirley Ma } 2036bc7b3a36SShirley Ma 2037bc7b3a36SShirley Ma /* MTU will be reset when mcast join happens */ 2038bc7b3a36SShirley Ma priv->dev->mtu = IPOIB_UD_MTU(priv->max_ib_mtu); 2039bc7b3a36SShirley Ma priv->mcast_mtu = priv->admin_mtu = priv->dev->mtu; 2040b3e3893eSJarod Wilson priv->dev->max_mtu = IPOIB_CM_MTU; 2041bc7b3a36SShirley Ma 2042596b9b68SDavid Miller priv->dev->neigh_priv_len = sizeof(struct ipoib_neigh); 2043596b9b68SDavid Miller 20441da177e4SLinus Torvalds result = ib_query_pkey(hca, port, 0, &priv->pkey); 20451da177e4SLinus Torvalds if (result) { 20461da177e4SLinus Torvalds printk(KERN_WARNING "%s: ib_query_pkey port %d failed (ret = %d)\n", 20471da177e4SLinus Torvalds hca->name, port, result); 2048ca6de177SEli Cohen goto device_init_failed; 20491da177e4SLinus Torvalds } 20501da177e4SLinus Torvalds 205158e9cc90SAmir Vadai result = ipoib_set_dev_features(priv, hca); 205258e9cc90SAmir Vadai if (result) 20536046136cSEli Cohen goto device_init_failed; 2054af40da89SVladimir Sokolovsky 20554ce05937SRoland Dreier /* 20564ce05937SRoland Dreier * Set the full membership bit, so that we join the right 20574ce05937SRoland Dreier * broadcast group, etc. 20584ce05937SRoland Dreier */ 20594ce05937SRoland Dreier priv->pkey |= 0x8000; 20604ce05937SRoland Dreier 20611da177e4SLinus Torvalds priv->dev->broadcast[8] = priv->pkey >> 8; 20621da177e4SLinus Torvalds priv->dev->broadcast[9] = priv->pkey & 0xff; 20631da177e4SLinus Torvalds 206455ee3ab2SMatan Barak result = ib_query_gid(hca, port, 0, &priv->local_gid, NULL); 20651da177e4SLinus Torvalds if (result) { 20661da177e4SLinus Torvalds printk(KERN_WARNING "%s: ib_query_gid port %d failed (ret = %d)\n", 20671da177e4SLinus Torvalds hca->name, port, result); 2068ca6de177SEli Cohen goto device_init_failed; 20691da177e4SLinus Torvalds } else 20701da177e4SLinus Torvalds memcpy(priv->dev->dev_addr + 4, priv->local_gid.raw, sizeof (union ib_gid)); 2071492a7e67SMark Bloch set_bit(IPOIB_FLAG_DEV_ADDR_SET, &priv->flags); 20721da177e4SLinus Torvalds 20731da177e4SLinus Torvalds result = ipoib_dev_init(priv->dev, hca, port); 20741da177e4SLinus Torvalds if (result < 0) { 20751da177e4SLinus Torvalds printk(KERN_WARNING "%s: failed to initialize port %d (ret = %d)\n", 20761da177e4SLinus Torvalds hca->name, port, result); 20771da177e4SLinus Torvalds goto device_init_failed; 20781da177e4SLinus Torvalds } 20791da177e4SLinus Torvalds 20801da177e4SLinus Torvalds INIT_IB_EVENT_HANDLER(&priv->event_handler, 20811da177e4SLinus Torvalds priv->ca, ipoib_event); 20821da177e4SLinus Torvalds result = ib_register_event_handler(&priv->event_handler); 20831da177e4SLinus Torvalds if (result < 0) { 20841da177e4SLinus Torvalds printk(KERN_WARNING "%s: ib_register_event_handler failed for " 20851da177e4SLinus Torvalds "port %d (ret = %d)\n", 20861da177e4SLinus Torvalds hca->name, port, result); 20871da177e4SLinus Torvalds goto event_failed; 20881da177e4SLinus Torvalds } 20891da177e4SLinus Torvalds 20901da177e4SLinus Torvalds result = register_netdev(priv->dev); 20911da177e4SLinus Torvalds if (result) { 20921da177e4SLinus Torvalds printk(KERN_WARNING "%s: couldn't register ipoib port %d; error %d\n", 20931da177e4SLinus Torvalds hca->name, port, result); 20941da177e4SLinus Torvalds goto register_failed; 20951da177e4SLinus Torvalds } 20961da177e4SLinus Torvalds 20971732b0efSRoland Dreier ipoib_create_debug_files(priv->dev); 20981da177e4SLinus Torvalds 2099839fcabaSMichael S. Tsirkin if (ipoib_cm_add_mode_attr(priv->dev)) 2100839fcabaSMichael S. Tsirkin goto sysfs_failed; 21011da177e4SLinus Torvalds if (ipoib_add_pkey_attr(priv->dev)) 21021da177e4SLinus Torvalds goto sysfs_failed; 2103335a64a5SOr Gerlitz if (ipoib_add_umcast_attr(priv->dev)) 2104335a64a5SOr Gerlitz goto sysfs_failed; 210543cb76d9SGreg Kroah-Hartman if (device_create_file(&priv->dev->dev, &dev_attr_create_child)) 21061da177e4SLinus Torvalds goto sysfs_failed; 210743cb76d9SGreg Kroah-Hartman if (device_create_file(&priv->dev->dev, &dev_attr_delete_child)) 21081da177e4SLinus Torvalds goto sysfs_failed; 21091da177e4SLinus Torvalds 21101da177e4SLinus Torvalds return priv->dev; 21111da177e4SLinus Torvalds 21121da177e4SLinus Torvalds sysfs_failed: 21131732b0efSRoland Dreier ipoib_delete_debug_files(priv->dev); 21141da177e4SLinus Torvalds unregister_netdev(priv->dev); 21151da177e4SLinus Torvalds 21161da177e4SLinus Torvalds register_failed: 21171da177e4SLinus Torvalds ib_unregister_event_handler(&priv->event_handler); 21180b39578bSDoug Ledford flush_workqueue(ipoib_workqueue); 2119b63b70d8SShlomo Pongratz /* Stop GC if started before flush */ 2120b63b70d8SShlomo Pongratz set_bit(IPOIB_STOP_NEIGH_GC, &priv->flags); 2121b63b70d8SShlomo Pongratz cancel_delayed_work(&priv->neigh_reap_task); 21220b39578bSDoug Ledford flush_workqueue(priv->wq); 21231da177e4SLinus Torvalds 21241da177e4SLinus Torvalds event_failed: 21251da177e4SLinus Torvalds ipoib_dev_cleanup(priv->dev); 21261da177e4SLinus Torvalds 21271da177e4SLinus Torvalds device_init_failed: 21281da177e4SLinus Torvalds free_netdev(priv->dev); 21291da177e4SLinus Torvalds 21301da177e4SLinus Torvalds alloc_mem_failed: 21311da177e4SLinus Torvalds return ERR_PTR(result); 21321da177e4SLinus Torvalds } 21331da177e4SLinus Torvalds 21341da177e4SLinus Torvalds static void ipoib_add_one(struct ib_device *device) 21351da177e4SLinus Torvalds { 21361da177e4SLinus Torvalds struct list_head *dev_list; 21371da177e4SLinus Torvalds struct net_device *dev; 21381da177e4SLinus Torvalds struct ipoib_dev_priv *priv; 21394139032bSHal Rosenstock int p; 21408e37ab68SMichael Wang int count = 0; 214107ebafbaSTom Tucker 21421da177e4SLinus Torvalds dev_list = kmalloc(sizeof *dev_list, GFP_KERNEL); 21431da177e4SLinus Torvalds if (!dev_list) 21441da177e4SLinus Torvalds return; 21451da177e4SLinus Torvalds 21461da177e4SLinus Torvalds INIT_LIST_HEAD(dev_list); 21471da177e4SLinus Torvalds 21484139032bSHal Rosenstock for (p = rdma_start_port(device); p <= rdma_end_port(device); ++p) { 21498e37ab68SMichael Wang if (!rdma_protocol_ib(device, p)) 21507b4c8769SEli Cohen continue; 21511da177e4SLinus Torvalds dev = ipoib_add_port("ib%d", device, p); 21521da177e4SLinus Torvalds if (!IS_ERR(dev)) { 21531da177e4SLinus Torvalds priv = netdev_priv(dev); 21541da177e4SLinus Torvalds list_add_tail(&priv->list, dev_list); 21558e37ab68SMichael Wang count++; 21561da177e4SLinus Torvalds } 21571da177e4SLinus Torvalds } 21581da177e4SLinus Torvalds 21598e37ab68SMichael Wang if (!count) { 21608e37ab68SMichael Wang kfree(dev_list); 21618e37ab68SMichael Wang return; 21628e37ab68SMichael Wang } 21638e37ab68SMichael Wang 21641da177e4SLinus Torvalds ib_set_client_data(device, &ipoib_client, dev_list); 21651da177e4SLinus Torvalds } 21661da177e4SLinus Torvalds 21677c1eb45aSHaggai Eran static void ipoib_remove_one(struct ib_device *device, void *client_data) 21681da177e4SLinus Torvalds { 21691da177e4SLinus Torvalds struct ipoib_dev_priv *priv, *tmp; 21707c1eb45aSHaggai Eran struct list_head *dev_list = client_data; 21711da177e4SLinus Torvalds 21725a2815f0SItai Garbi if (!dev_list) 21735a2815f0SItai Garbi return; 21741da177e4SLinus Torvalds 21751da177e4SLinus Torvalds list_for_each_entry_safe(priv, tmp, dev_list, list) { 21761da177e4SLinus Torvalds ib_unregister_event_handler(&priv->event_handler); 21770b39578bSDoug Ledford flush_workqueue(ipoib_workqueue); 2178a77a57a1SRoland Dreier 2179198b12f7SErez Shitrit /* mark interface in the middle of destruction */ 2180198b12f7SErez Shitrit set_bit(IPOIB_FLAG_GOING_DOWN, &priv->flags); 2181198b12f7SErez Shitrit 2182a77a57a1SRoland Dreier rtnl_lock(); 2183a77a57a1SRoland Dreier dev_change_flags(priv->dev, priv->dev->flags & ~IFF_UP); 2184a77a57a1SRoland Dreier rtnl_unlock(); 2185a77a57a1SRoland Dreier 2186b63b70d8SShlomo Pongratz /* Stop GC */ 2187b63b70d8SShlomo Pongratz set_bit(IPOIB_STOP_NEIGH_GC, &priv->flags); 2188b63b70d8SShlomo Pongratz cancel_delayed_work(&priv->neigh_reap_task); 21890b39578bSDoug Ledford flush_workqueue(priv->wq); 21901da177e4SLinus Torvalds 21911da177e4SLinus Torvalds unregister_netdev(priv->dev); 21921da177e4SLinus Torvalds free_netdev(priv->dev); 21931da177e4SLinus Torvalds } 219406c56e44SMichael S. Tsirkin 219506c56e44SMichael S. Tsirkin kfree(dev_list); 21961da177e4SLinus Torvalds } 21971da177e4SLinus Torvalds 21981da177e4SLinus Torvalds static int __init ipoib_init_module(void) 21991da177e4SLinus Torvalds { 22001da177e4SLinus Torvalds int ret; 22011da177e4SLinus Torvalds 22020f485251SShirley Ma ipoib_recvq_size = roundup_pow_of_two(ipoib_recvq_size); 22030f485251SShirley Ma ipoib_recvq_size = min(ipoib_recvq_size, IPOIB_MAX_QUEUE_SIZE); 22040f485251SShirley Ma ipoib_recvq_size = max(ipoib_recvq_size, IPOIB_MIN_QUEUE_SIZE); 22050f485251SShirley Ma 22060f485251SShirley Ma ipoib_sendq_size = roundup_pow_of_two(ipoib_sendq_size); 22070f485251SShirley Ma ipoib_sendq_size = min(ipoib_sendq_size, IPOIB_MAX_QUEUE_SIZE); 2208732eacc0SHagen Paul Pfeifer ipoib_sendq_size = max3(ipoib_sendq_size, 2 * MAX_SEND_CQE, IPOIB_MIN_QUEUE_SIZE); 220968e995a2SPradeep Satyanarayana #ifdef CONFIG_INFINIBAND_IPOIB_CM 221068e995a2SPradeep Satyanarayana ipoib_max_conn_qp = min(ipoib_max_conn_qp, IPOIB_CM_MAX_CONN_QP); 221168e995a2SPradeep Satyanarayana #endif 22120f485251SShirley Ma 2213f89271daSEli Cohen /* 2214f89271daSEli Cohen * When copying small received packets, we only copy from the 2215f89271daSEli Cohen * linear data part of the SKB, so we rely on this condition. 2216f89271daSEli Cohen */ 2217f89271daSEli Cohen BUILD_BUG_ON(IPOIB_CM_COPYBREAK > IPOIB_CM_HEAD_SIZE); 2218f89271daSEli Cohen 22191da177e4SLinus Torvalds ret = ipoib_register_debugfs(); 22201da177e4SLinus Torvalds if (ret) 22211da177e4SLinus Torvalds return ret; 22221da177e4SLinus Torvalds 22231da177e4SLinus Torvalds /* 22240b39578bSDoug Ledford * We create a global workqueue here that is used for all flush 22250b39578bSDoug Ledford * operations. However, if you attempt to flush a workqueue 22260b39578bSDoug Ledford * from a task on that same workqueue, it deadlocks the system. 22270b39578bSDoug Ledford * We want to be able to flush the tasks associated with a 22280b39578bSDoug Ledford * specific net device, so we also create a workqueue for each 22290b39578bSDoug Ledford * netdevice. We queue up the tasks for that device only on 22300b39578bSDoug Ledford * its private workqueue, and we only queue up flush events 22310b39578bSDoug Ledford * on our global flush workqueue. This avoids the deadlocks. 22321da177e4SLinus Torvalds */ 2233855cda68SBhaktipriya Shridhar ipoib_workqueue = alloc_ordered_workqueue("ipoib_flush", 2234855cda68SBhaktipriya Shridhar WQ_MEM_RECLAIM); 22351da177e4SLinus Torvalds if (!ipoib_workqueue) { 22361da177e4SLinus Torvalds ret = -ENOMEM; 22371da177e4SLinus Torvalds goto err_fs; 22381da177e4SLinus Torvalds } 22391da177e4SLinus Torvalds 2240c1a0b23bSMichael S. Tsirkin ib_sa_register_client(&ipoib_sa_client); 2241c1a0b23bSMichael S. Tsirkin 22421da177e4SLinus Torvalds ret = ib_register_client(&ipoib_client); 22431da177e4SLinus Torvalds if (ret) 2244c1a0b23bSMichael S. Tsirkin goto err_sa; 22451da177e4SLinus Torvalds 22469baa0b03SOr Gerlitz ret = ipoib_netlink_init(); 22479baa0b03SOr Gerlitz if (ret) 22489baa0b03SOr Gerlitz goto err_client; 22499baa0b03SOr Gerlitz 22501da177e4SLinus Torvalds return 0; 22511da177e4SLinus Torvalds 22529baa0b03SOr Gerlitz err_client: 22539baa0b03SOr Gerlitz ib_unregister_client(&ipoib_client); 22549baa0b03SOr Gerlitz 2255c1a0b23bSMichael S. Tsirkin err_sa: 2256c1a0b23bSMichael S. Tsirkin ib_sa_unregister_client(&ipoib_sa_client); 22571da177e4SLinus Torvalds destroy_workqueue(ipoib_workqueue); 22581da177e4SLinus Torvalds 22599adec1a8SRoland Dreier err_fs: 22609adec1a8SRoland Dreier ipoib_unregister_debugfs(); 22619adec1a8SRoland Dreier 22621da177e4SLinus Torvalds return ret; 22631da177e4SLinus Torvalds } 22641da177e4SLinus Torvalds 22651da177e4SLinus Torvalds static void __exit ipoib_cleanup_module(void) 22661da177e4SLinus Torvalds { 22679baa0b03SOr Gerlitz ipoib_netlink_fini(); 22681da177e4SLinus Torvalds ib_unregister_client(&ipoib_client); 2269c1a0b23bSMichael S. Tsirkin ib_sa_unregister_client(&ipoib_sa_client); 22709adec1a8SRoland Dreier ipoib_unregister_debugfs(); 22711da177e4SLinus Torvalds destroy_workqueue(ipoib_workqueue); 22721da177e4SLinus Torvalds } 22731da177e4SLinus Torvalds 22741da177e4SLinus Torvalds module_init(ipoib_init_module); 22751da177e4SLinus Torvalds module_exit(ipoib_cleanup_module); 2276