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> 5414c85021SArnaldo Carvalho de Melo 554b48680bSYan Burman #define DRV_VERSION "1.0.0" 564b48680bSYan Burman 574b48680bSYan Burman const char ipoib_driver_version[] = DRV_VERSION; 584b48680bSYan Burman 591da177e4SLinus Torvalds MODULE_AUTHOR("Roland Dreier"); 601da177e4SLinus Torvalds MODULE_DESCRIPTION("IP-over-InfiniBand net driver"); 611da177e4SLinus Torvalds MODULE_LICENSE("Dual BSD/GPL"); 624b48680bSYan Burman MODULE_VERSION(DRV_VERSION); 631da177e4SLinus Torvalds 640f485251SShirley Ma int ipoib_sendq_size __read_mostly = IPOIB_TX_RING_SIZE; 650f485251SShirley Ma int ipoib_recvq_size __read_mostly = IPOIB_RX_RING_SIZE; 660f485251SShirley Ma 670f485251SShirley Ma module_param_named(send_queue_size, ipoib_sendq_size, int, 0444); 680f485251SShirley Ma MODULE_PARM_DESC(send_queue_size, "Number of descriptors in send queue"); 690f485251SShirley Ma module_param_named(recv_queue_size, ipoib_recvq_size, int, 0444); 700f485251SShirley Ma MODULE_PARM_DESC(recv_queue_size, "Number of descriptors in receive queue"); 710f485251SShirley Ma 721da177e4SLinus Torvalds #ifdef CONFIG_INFINIBAND_IPOIB_DEBUG 731da177e4SLinus Torvalds int ipoib_debug_level; 741da177e4SLinus Torvalds 751da177e4SLinus Torvalds module_param_named(debug_level, ipoib_debug_level, int, 0644); 761da177e4SLinus Torvalds MODULE_PARM_DESC(debug_level, "Enable debug tracing if > 0"); 771da177e4SLinus Torvalds #endif 781da177e4SLinus Torvalds 791732b0efSRoland Dreier struct ipoib_path_iter { 801732b0efSRoland Dreier struct net_device *dev; 811732b0efSRoland Dreier struct ipoib_path path; 821732b0efSRoland Dreier }; 831732b0efSRoland Dreier 841da177e4SLinus Torvalds static const u8 ipv4_bcast_addr[] = { 851da177e4SLinus Torvalds 0x00, 0xff, 0xff, 0xff, 861da177e4SLinus Torvalds 0xff, 0x12, 0x40, 0x1b, 0x00, 0x00, 0x00, 0x00, 871da177e4SLinus Torvalds 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff 881da177e4SLinus Torvalds }; 891da177e4SLinus Torvalds 901da177e4SLinus Torvalds struct workqueue_struct *ipoib_workqueue; 911da177e4SLinus Torvalds 92c1a0b23bSMichael S. Tsirkin struct ib_sa_client ipoib_sa_client; 93c1a0b23bSMichael S. Tsirkin 941da177e4SLinus Torvalds static void ipoib_add_one(struct ib_device *device); 957c1eb45aSHaggai Eran static void ipoib_remove_one(struct ib_device *device, void *client_data); 96b63b70d8SShlomo Pongratz static void ipoib_neigh_reclaim(struct rcu_head *rp); 97ddde896eSGuy Shapiro static struct net_device *ipoib_get_net_dev_by_params( 98ddde896eSGuy Shapiro struct ib_device *dev, u8 port, u16 pkey, 99ddde896eSGuy Shapiro const union ib_gid *gid, const struct sockaddr *addr, 100ddde896eSGuy Shapiro void *client_data); 1011da177e4SLinus Torvalds 1021da177e4SLinus Torvalds static struct ib_client ipoib_client = { 1031da177e4SLinus Torvalds .name = "ipoib", 1041da177e4SLinus Torvalds .add = ipoib_add_one, 105ddde896eSGuy Shapiro .remove = ipoib_remove_one, 106ddde896eSGuy Shapiro .get_net_dev_by_params = ipoib_get_net_dev_by_params, 1071da177e4SLinus Torvalds }; 1081da177e4SLinus Torvalds 1091da177e4SLinus Torvalds int ipoib_open(struct net_device *dev) 1101da177e4SLinus Torvalds { 1111da177e4SLinus Torvalds struct ipoib_dev_priv *priv = netdev_priv(dev); 1121da177e4SLinus Torvalds 1131da177e4SLinus Torvalds ipoib_dbg(priv, "bringing up interface\n"); 1141da177e4SLinus Torvalds 115437708c4SMichal Schmidt netif_carrier_off(dev); 116437708c4SMichal Schmidt 117e028cc55SYossi Etigin set_bit(IPOIB_FLAG_ADMIN_UP, &priv->flags); 1181da177e4SLinus Torvalds 119efc82eeeSDoug Ledford if (ipoib_ib_dev_open(dev)) { 120db84f880SErez Shitrit if (!test_bit(IPOIB_PKEY_ASSIGNED, &priv->flags)) 1211da177e4SLinus Torvalds return 0; 122b8a1b1ceSRoland Dreier goto err_disable; 123dd57c930SAlex Estrin } 124fe25c561SYossi Etigin 125b8a1b1ceSRoland Dreier if (ipoib_ib_dev_up(dev)) 126b8a1b1ceSRoland Dreier goto err_stop; 1271da177e4SLinus Torvalds 1281da177e4SLinus Torvalds if (!test_bit(IPOIB_FLAG_SUBINTERFACE, &priv->flags)) { 1291da177e4SLinus Torvalds struct ipoib_dev_priv *cpriv; 1301da177e4SLinus Torvalds 1311da177e4SLinus Torvalds /* Bring up any child interfaces too */ 132f47944ccSErez Shitrit down_read(&priv->vlan_rwsem); 1331da177e4SLinus Torvalds list_for_each_entry(cpriv, &priv->child_intfs, list) { 1341da177e4SLinus Torvalds int flags; 1351da177e4SLinus Torvalds 1361da177e4SLinus Torvalds flags = cpriv->dev->flags; 1371da177e4SLinus Torvalds if (flags & IFF_UP) 1381da177e4SLinus Torvalds continue; 1391da177e4SLinus Torvalds 1401da177e4SLinus Torvalds dev_change_flags(cpriv->dev, flags | IFF_UP); 1411da177e4SLinus Torvalds } 142f47944ccSErez Shitrit up_read(&priv->vlan_rwsem); 1431da177e4SLinus Torvalds } 1441da177e4SLinus Torvalds 1451da177e4SLinus Torvalds netif_start_queue(dev); 1461da177e4SLinus Torvalds 1471da177e4SLinus Torvalds return 0; 148b8a1b1ceSRoland Dreier 149b8a1b1ceSRoland Dreier err_stop: 150efc82eeeSDoug Ledford ipoib_ib_dev_stop(dev); 151b8a1b1ceSRoland Dreier 152b8a1b1ceSRoland Dreier err_disable: 153b8a1b1ceSRoland Dreier clear_bit(IPOIB_FLAG_ADMIN_UP, &priv->flags); 154b8a1b1ceSRoland Dreier 155b8a1b1ceSRoland Dreier return -EINVAL; 1561da177e4SLinus Torvalds } 1571da177e4SLinus Torvalds 1581da177e4SLinus Torvalds static int ipoib_stop(struct net_device *dev) 1591da177e4SLinus Torvalds { 1601da177e4SLinus Torvalds struct ipoib_dev_priv *priv = netdev_priv(dev); 1611da177e4SLinus Torvalds 1621da177e4SLinus Torvalds ipoib_dbg(priv, "stopping interface\n"); 1631da177e4SLinus Torvalds 1641da177e4SLinus Torvalds clear_bit(IPOIB_FLAG_ADMIN_UP, &priv->flags); 1651da177e4SLinus Torvalds 1661da177e4SLinus Torvalds netif_stop_queue(dev); 1671da177e4SLinus Torvalds 168efc82eeeSDoug Ledford ipoib_ib_dev_down(dev); 169efc82eeeSDoug Ledford ipoib_ib_dev_stop(dev); 1701da177e4SLinus Torvalds 1711da177e4SLinus Torvalds if (!test_bit(IPOIB_FLAG_SUBINTERFACE, &priv->flags)) { 1721da177e4SLinus Torvalds struct ipoib_dev_priv *cpriv; 1731da177e4SLinus Torvalds 1741da177e4SLinus Torvalds /* Bring down any child interfaces too */ 175f47944ccSErez Shitrit down_read(&priv->vlan_rwsem); 1761da177e4SLinus Torvalds list_for_each_entry(cpriv, &priv->child_intfs, list) { 1771da177e4SLinus Torvalds int flags; 1781da177e4SLinus Torvalds 1791da177e4SLinus Torvalds flags = cpriv->dev->flags; 1801da177e4SLinus Torvalds if (!(flags & IFF_UP)) 1811da177e4SLinus Torvalds continue; 1821da177e4SLinus Torvalds 1831da177e4SLinus Torvalds dev_change_flags(cpriv->dev, flags & ~IFF_UP); 1841da177e4SLinus Torvalds } 185f47944ccSErez Shitrit up_read(&priv->vlan_rwsem); 1861da177e4SLinus Torvalds } 1871da177e4SLinus Torvalds 1881da177e4SLinus Torvalds return 0; 1891da177e4SLinus Torvalds } 1901da177e4SLinus Torvalds 1919baa0b03SOr Gerlitz static void ipoib_uninit(struct net_device *dev) 1929baa0b03SOr Gerlitz { 1939baa0b03SOr Gerlitz ipoib_dev_cleanup(dev); 1949baa0b03SOr Gerlitz } 1959baa0b03SOr Gerlitz 1969ca36f7dSDavid S. Miller static netdev_features_t ipoib_fix_features(struct net_device *dev, netdev_features_t features) 1973d96c74dSMichał Mirosław { 1983d96c74dSMichał Mirosław struct ipoib_dev_priv *priv = netdev_priv(dev); 1993d96c74dSMichał Mirosław 2003d96c74dSMichał Mirosław if (test_bit(IPOIB_FLAG_ADMIN_CM, &priv->flags)) 201c4268778SYuval Shaia features &= ~(NETIF_F_IP_CSUM | NETIF_F_TSO); 2023d96c74dSMichał Mirosław 2033d96c74dSMichał Mirosław return features; 2043d96c74dSMichał Mirosław } 2053d96c74dSMichał Mirosław 2061da177e4SLinus Torvalds static int ipoib_change_mtu(struct net_device *dev, int new_mtu) 2071da177e4SLinus Torvalds { 2081da177e4SLinus Torvalds struct ipoib_dev_priv *priv = netdev_priv(dev); 2091da177e4SLinus Torvalds 210839fcabaSMichael S. Tsirkin /* dev->mtu > 2K ==> connected mode */ 211586a6934SPradeep Satyanarayana if (ipoib_cm_admin_enabled(dev)) { 212586a6934SPradeep Satyanarayana if (new_mtu > ipoib_cm_max_mtu(dev)) 213586a6934SPradeep Satyanarayana return -EINVAL; 214586a6934SPradeep Satyanarayana 215839fcabaSMichael S. Tsirkin if (new_mtu > priv->mcast_mtu) 216839fcabaSMichael S. Tsirkin ipoib_warn(priv, "mtu > %d will cause multicast packet drops.\n", 217839fcabaSMichael S. Tsirkin priv->mcast_mtu); 218586a6934SPradeep Satyanarayana 219839fcabaSMichael S. Tsirkin dev->mtu = new_mtu; 220839fcabaSMichael S. Tsirkin return 0; 221839fcabaSMichael S. Tsirkin } 222839fcabaSMichael S. Tsirkin 223bc7b3a36SShirley Ma if (new_mtu > IPOIB_UD_MTU(priv->max_ib_mtu)) 2241da177e4SLinus Torvalds return -EINVAL; 2251da177e4SLinus Torvalds 2261da177e4SLinus Torvalds priv->admin_mtu = new_mtu; 2271da177e4SLinus Torvalds 2281da177e4SLinus Torvalds dev->mtu = min(priv->mcast_mtu, priv->admin_mtu); 2291da177e4SLinus Torvalds 2301da177e4SLinus Torvalds return 0; 2311da177e4SLinus Torvalds } 2321da177e4SLinus Torvalds 233ddde896eSGuy Shapiro /* Called with an RCU read lock taken */ 234ddde896eSGuy Shapiro static bool ipoib_is_dev_match_addr_rcu(const struct sockaddr *addr, 235ddde896eSGuy Shapiro struct net_device *dev) 236ddde896eSGuy Shapiro { 237ddde896eSGuy Shapiro struct net *net = dev_net(dev); 238ddde896eSGuy Shapiro struct in_device *in_dev; 239ddde896eSGuy Shapiro struct sockaddr_in *addr_in = (struct sockaddr_in *)addr; 240ddde896eSGuy Shapiro struct sockaddr_in6 *addr_in6 = (struct sockaddr_in6 *)addr; 241ddde896eSGuy Shapiro __be32 ret_addr; 242ddde896eSGuy Shapiro 243ddde896eSGuy Shapiro switch (addr->sa_family) { 244ddde896eSGuy Shapiro case AF_INET: 245ddde896eSGuy Shapiro in_dev = in_dev_get(dev); 246ddde896eSGuy Shapiro if (!in_dev) 247ddde896eSGuy Shapiro return false; 248ddde896eSGuy Shapiro 249ddde896eSGuy Shapiro ret_addr = inet_confirm_addr(net, in_dev, 0, 250ddde896eSGuy Shapiro addr_in->sin_addr.s_addr, 251ddde896eSGuy Shapiro RT_SCOPE_HOST); 252ddde896eSGuy Shapiro in_dev_put(in_dev); 253ddde896eSGuy Shapiro if (ret_addr) 254ddde896eSGuy Shapiro return true; 255ddde896eSGuy Shapiro 256ddde896eSGuy Shapiro break; 257ddde896eSGuy Shapiro case AF_INET6: 258ddde896eSGuy Shapiro if (IS_ENABLED(CONFIG_IPV6) && 259ddde896eSGuy Shapiro ipv6_chk_addr(net, &addr_in6->sin6_addr, dev, 1)) 260ddde896eSGuy Shapiro return true; 261ddde896eSGuy Shapiro 262ddde896eSGuy Shapiro break; 263ddde896eSGuy Shapiro } 264ddde896eSGuy Shapiro return false; 265ddde896eSGuy Shapiro } 266ddde896eSGuy Shapiro 267ddde896eSGuy Shapiro /** 268ddde896eSGuy Shapiro * Find the master net_device on top of the given net_device. 269ddde896eSGuy Shapiro * @dev: base IPoIB net_device 270ddde896eSGuy Shapiro * 271ddde896eSGuy Shapiro * Returns the master net_device with a reference held, or the same net_device 272ddde896eSGuy Shapiro * if no master exists. 273ddde896eSGuy Shapiro */ 274ddde896eSGuy Shapiro static struct net_device *ipoib_get_master_net_dev(struct net_device *dev) 275ddde896eSGuy Shapiro { 276ddde896eSGuy Shapiro struct net_device *master; 277ddde896eSGuy Shapiro 278ddde896eSGuy Shapiro rcu_read_lock(); 279ddde896eSGuy Shapiro master = netdev_master_upper_dev_get_rcu(dev); 280ddde896eSGuy Shapiro if (master) 281ddde896eSGuy Shapiro dev_hold(master); 282ddde896eSGuy Shapiro rcu_read_unlock(); 283ddde896eSGuy Shapiro 284ddde896eSGuy Shapiro if (master) 285ddde896eSGuy Shapiro return master; 286ddde896eSGuy Shapiro 287ddde896eSGuy Shapiro dev_hold(dev); 288ddde896eSGuy Shapiro return dev; 289ddde896eSGuy Shapiro } 290ddde896eSGuy Shapiro 291ddde896eSGuy Shapiro /** 292ddde896eSGuy Shapiro * Find a net_device matching the given address, which is an upper device of 293ddde896eSGuy Shapiro * the given net_device. 294ddde896eSGuy Shapiro * @addr: IP address to look for. 295ddde896eSGuy Shapiro * @dev: base IPoIB net_device 296ddde896eSGuy Shapiro * 297ddde896eSGuy Shapiro * If found, returns the net_device with a reference held. Otherwise return 298ddde896eSGuy Shapiro * NULL. 299ddde896eSGuy Shapiro */ 300ddde896eSGuy Shapiro static struct net_device *ipoib_get_net_dev_match_addr( 301ddde896eSGuy Shapiro const struct sockaddr *addr, struct net_device *dev) 302ddde896eSGuy Shapiro { 303ddde896eSGuy Shapiro struct net_device *upper, 304ddde896eSGuy Shapiro *result = NULL; 305ddde896eSGuy Shapiro struct list_head *iter; 306ddde896eSGuy Shapiro 307ddde896eSGuy Shapiro rcu_read_lock(); 308ddde896eSGuy Shapiro if (ipoib_is_dev_match_addr_rcu(addr, dev)) { 309ddde896eSGuy Shapiro dev_hold(dev); 310ddde896eSGuy Shapiro result = dev; 311ddde896eSGuy Shapiro goto out; 312ddde896eSGuy Shapiro } 313ddde896eSGuy Shapiro 314ddde896eSGuy Shapiro netdev_for_each_all_upper_dev_rcu(dev, upper, iter) { 315ddde896eSGuy Shapiro if (ipoib_is_dev_match_addr_rcu(addr, upper)) { 316ddde896eSGuy Shapiro dev_hold(upper); 317ddde896eSGuy Shapiro result = upper; 318ddde896eSGuy Shapiro break; 319ddde896eSGuy Shapiro } 320ddde896eSGuy Shapiro } 321ddde896eSGuy Shapiro out: 322ddde896eSGuy Shapiro rcu_read_unlock(); 323ddde896eSGuy Shapiro return result; 324ddde896eSGuy Shapiro } 325ddde896eSGuy Shapiro 326ddde896eSGuy Shapiro /* returns the number of IPoIB netdevs on top a given ipoib device matching a 327ddde896eSGuy Shapiro * pkey_index and address, if one exists. 328ddde896eSGuy Shapiro * 329ddde896eSGuy Shapiro * @found_net_dev: contains a matching net_device if the return value >= 1, 330ddde896eSGuy Shapiro * with a reference held. */ 331ddde896eSGuy Shapiro static int ipoib_match_gid_pkey_addr(struct ipoib_dev_priv *priv, 332ddde896eSGuy Shapiro const union ib_gid *gid, 333ddde896eSGuy Shapiro u16 pkey_index, 334ddde896eSGuy Shapiro const struct sockaddr *addr, 335ddde896eSGuy Shapiro int nesting, 336ddde896eSGuy Shapiro struct net_device **found_net_dev) 337ddde896eSGuy Shapiro { 338ddde896eSGuy Shapiro struct ipoib_dev_priv *child_priv; 339ddde896eSGuy Shapiro struct net_device *net_dev = NULL; 340ddde896eSGuy Shapiro int matches = 0; 341ddde896eSGuy Shapiro 342ddde896eSGuy Shapiro if (priv->pkey_index == pkey_index && 343ddde896eSGuy Shapiro (!gid || !memcmp(gid, &priv->local_gid, sizeof(*gid)))) { 344ddde896eSGuy Shapiro if (!addr) { 345ddde896eSGuy Shapiro net_dev = ipoib_get_master_net_dev(priv->dev); 346ddde896eSGuy Shapiro } else { 347ddde896eSGuy Shapiro /* Verify the net_device matches the IP address, as 348ddde896eSGuy Shapiro * IPoIB child devices currently share a GID. */ 349ddde896eSGuy Shapiro net_dev = ipoib_get_net_dev_match_addr(addr, priv->dev); 350ddde896eSGuy Shapiro } 351ddde896eSGuy Shapiro if (net_dev) { 352ddde896eSGuy Shapiro if (!*found_net_dev) 353ddde896eSGuy Shapiro *found_net_dev = net_dev; 354ddde896eSGuy Shapiro else 355ddde896eSGuy Shapiro dev_put(net_dev); 356ddde896eSGuy Shapiro ++matches; 357ddde896eSGuy Shapiro } 358ddde896eSGuy Shapiro } 359ddde896eSGuy Shapiro 360ddde896eSGuy Shapiro /* Check child interfaces */ 361ddde896eSGuy Shapiro down_read_nested(&priv->vlan_rwsem, nesting); 362ddde896eSGuy Shapiro list_for_each_entry(child_priv, &priv->child_intfs, list) { 363ddde896eSGuy Shapiro matches += ipoib_match_gid_pkey_addr(child_priv, gid, 364ddde896eSGuy Shapiro pkey_index, addr, 365ddde896eSGuy Shapiro nesting + 1, 366ddde896eSGuy Shapiro found_net_dev); 367ddde896eSGuy Shapiro if (matches > 1) 368ddde896eSGuy Shapiro break; 369ddde896eSGuy Shapiro } 370ddde896eSGuy Shapiro up_read(&priv->vlan_rwsem); 371ddde896eSGuy Shapiro 372ddde896eSGuy Shapiro return matches; 373ddde896eSGuy Shapiro } 374ddde896eSGuy Shapiro 375ddde896eSGuy Shapiro /* Returns the number of matching net_devs found (between 0 and 2). Also 376ddde896eSGuy Shapiro * return the matching net_device in the @net_dev parameter, holding a 377ddde896eSGuy Shapiro * reference to the net_device, if the number of matches >= 1 */ 378ddde896eSGuy Shapiro static int __ipoib_get_net_dev_by_params(struct list_head *dev_list, u8 port, 379ddde896eSGuy Shapiro u16 pkey_index, 380ddde896eSGuy Shapiro const union ib_gid *gid, 381ddde896eSGuy Shapiro const struct sockaddr *addr, 382ddde896eSGuy Shapiro struct net_device **net_dev) 383ddde896eSGuy Shapiro { 384ddde896eSGuy Shapiro struct ipoib_dev_priv *priv; 385ddde896eSGuy Shapiro int matches = 0; 386ddde896eSGuy Shapiro 387ddde896eSGuy Shapiro *net_dev = NULL; 388ddde896eSGuy Shapiro 389ddde896eSGuy Shapiro list_for_each_entry(priv, dev_list, list) { 390ddde896eSGuy Shapiro if (priv->port != port) 391ddde896eSGuy Shapiro continue; 392ddde896eSGuy Shapiro 393ddde896eSGuy Shapiro matches += ipoib_match_gid_pkey_addr(priv, gid, pkey_index, 394ddde896eSGuy Shapiro addr, 0, net_dev); 395ddde896eSGuy Shapiro if (matches > 1) 396ddde896eSGuy Shapiro break; 397ddde896eSGuy Shapiro } 398ddde896eSGuy Shapiro 399ddde896eSGuy Shapiro return matches; 400ddde896eSGuy Shapiro } 401ddde896eSGuy Shapiro 402ddde896eSGuy Shapiro static struct net_device *ipoib_get_net_dev_by_params( 403ddde896eSGuy Shapiro struct ib_device *dev, u8 port, u16 pkey, 404ddde896eSGuy Shapiro const union ib_gid *gid, const struct sockaddr *addr, 405ddde896eSGuy Shapiro void *client_data) 406ddde896eSGuy Shapiro { 407ddde896eSGuy Shapiro struct net_device *net_dev; 408ddde896eSGuy Shapiro struct list_head *dev_list = client_data; 409ddde896eSGuy Shapiro u16 pkey_index; 410ddde896eSGuy Shapiro int matches; 411ddde896eSGuy Shapiro int ret; 412ddde896eSGuy Shapiro 413ddde896eSGuy Shapiro if (!rdma_protocol_ib(dev, port)) 414ddde896eSGuy Shapiro return NULL; 415ddde896eSGuy Shapiro 416ddde896eSGuy Shapiro ret = ib_find_cached_pkey(dev, port, pkey, &pkey_index); 417ddde896eSGuy Shapiro if (ret) 418ddde896eSGuy Shapiro return NULL; 419ddde896eSGuy Shapiro 420ddde896eSGuy Shapiro if (!dev_list) 421ddde896eSGuy Shapiro return NULL; 422ddde896eSGuy Shapiro 423ddde896eSGuy Shapiro /* See if we can find a unique device matching the L2 parameters */ 424ddde896eSGuy Shapiro matches = __ipoib_get_net_dev_by_params(dev_list, port, pkey_index, 425ddde896eSGuy Shapiro gid, NULL, &net_dev); 426ddde896eSGuy Shapiro 427ddde896eSGuy Shapiro switch (matches) { 428ddde896eSGuy Shapiro case 0: 429ddde896eSGuy Shapiro return NULL; 430ddde896eSGuy Shapiro case 1: 431ddde896eSGuy Shapiro return net_dev; 432ddde896eSGuy Shapiro } 433ddde896eSGuy Shapiro 434ddde896eSGuy Shapiro dev_put(net_dev); 435ddde896eSGuy Shapiro 436ddde896eSGuy Shapiro /* Couldn't find a unique device with L2 parameters only. Use L3 437ddde896eSGuy Shapiro * address to uniquely match the net device */ 438ddde896eSGuy Shapiro matches = __ipoib_get_net_dev_by_params(dev_list, port, pkey_index, 439ddde896eSGuy Shapiro gid, addr, &net_dev); 440ddde896eSGuy Shapiro switch (matches) { 441ddde896eSGuy Shapiro case 0: 442ddde896eSGuy Shapiro return NULL; 443ddde896eSGuy Shapiro default: 444ddde896eSGuy Shapiro dev_warn_ratelimited(&dev->dev, 445ddde896eSGuy Shapiro "duplicate IP address detected\n"); 446ddde896eSGuy Shapiro /* Fall through */ 447ddde896eSGuy Shapiro case 1: 448ddde896eSGuy Shapiro return net_dev; 449ddde896eSGuy Shapiro } 450ddde896eSGuy Shapiro } 451ddde896eSGuy Shapiro 45271d9c5f9SRoland Dreier int ipoib_set_mode(struct net_device *dev, const char *buf) 45371d9c5f9SRoland Dreier { 45471d9c5f9SRoland Dreier struct ipoib_dev_priv *priv = netdev_priv(dev); 45571d9c5f9SRoland Dreier 45671d9c5f9SRoland Dreier /* flush paths if we switch modes so that connections are restarted */ 45771d9c5f9SRoland Dreier if (IPOIB_CM_SUPPORTED(dev->dev_addr) && !strcmp(buf, "connected\n")) { 45871d9c5f9SRoland Dreier set_bit(IPOIB_FLAG_ADMIN_CM, &priv->flags); 45971d9c5f9SRoland Dreier ipoib_warn(priv, "enabling connected mode " 46071d9c5f9SRoland Dreier "will cause multicast packet drops\n"); 46171d9c5f9SRoland Dreier netdev_update_features(dev); 462edcd2a74SErez Shitrit dev_set_mtu(dev, ipoib_cm_max_mtu(dev)); 46371d9c5f9SRoland Dreier rtnl_unlock(); 464e622f2f4SChristoph Hellwig priv->tx_wr.wr.send_flags &= ~IB_SEND_IP_CSUM; 46571d9c5f9SRoland Dreier 46671d9c5f9SRoland Dreier ipoib_flush_paths(dev); 46771d9c5f9SRoland Dreier rtnl_lock(); 46871d9c5f9SRoland Dreier return 0; 46971d9c5f9SRoland Dreier } 47071d9c5f9SRoland Dreier 47171d9c5f9SRoland Dreier if (!strcmp(buf, "datagram\n")) { 47271d9c5f9SRoland Dreier clear_bit(IPOIB_FLAG_ADMIN_CM, &priv->flags); 47371d9c5f9SRoland Dreier netdev_update_features(dev); 47471d9c5f9SRoland Dreier dev_set_mtu(dev, min(priv->mcast_mtu, dev->mtu)); 47571d9c5f9SRoland Dreier rtnl_unlock(); 47671d9c5f9SRoland Dreier ipoib_flush_paths(dev); 47771d9c5f9SRoland Dreier rtnl_lock(); 47871d9c5f9SRoland Dreier return 0; 47971d9c5f9SRoland Dreier } 48071d9c5f9SRoland Dreier 48171d9c5f9SRoland Dreier return -EINVAL; 48271d9c5f9SRoland Dreier } 48371d9c5f9SRoland Dreier 48437c22a77SJack Morgenstein static struct ipoib_path *__path_find(struct net_device *dev, void *gid) 4851da177e4SLinus Torvalds { 4861da177e4SLinus Torvalds struct ipoib_dev_priv *priv = netdev_priv(dev); 4871da177e4SLinus Torvalds struct rb_node *n = priv->path_tree.rb_node; 4881da177e4SLinus Torvalds struct ipoib_path *path; 4891da177e4SLinus Torvalds int ret; 4901da177e4SLinus Torvalds 4911da177e4SLinus Torvalds while (n) { 4921da177e4SLinus Torvalds path = rb_entry(n, struct ipoib_path, rb_node); 4931da177e4SLinus Torvalds 49437c22a77SJack Morgenstein ret = memcmp(gid, path->pathrec.dgid.raw, 4951da177e4SLinus Torvalds sizeof (union ib_gid)); 4961da177e4SLinus Torvalds 4971da177e4SLinus Torvalds if (ret < 0) 4981da177e4SLinus Torvalds n = n->rb_left; 4991da177e4SLinus Torvalds else if (ret > 0) 5001da177e4SLinus Torvalds n = n->rb_right; 5011da177e4SLinus Torvalds else 5021da177e4SLinus Torvalds return path; 5031da177e4SLinus Torvalds } 5041da177e4SLinus Torvalds 5051da177e4SLinus Torvalds return NULL; 5061da177e4SLinus Torvalds } 5071da177e4SLinus Torvalds 5081da177e4SLinus Torvalds static int __path_add(struct net_device *dev, struct ipoib_path *path) 5091da177e4SLinus Torvalds { 5101da177e4SLinus Torvalds struct ipoib_dev_priv *priv = netdev_priv(dev); 5111da177e4SLinus Torvalds struct rb_node **n = &priv->path_tree.rb_node; 5121da177e4SLinus Torvalds struct rb_node *pn = NULL; 5131da177e4SLinus Torvalds struct ipoib_path *tpath; 5141da177e4SLinus Torvalds int ret; 5151da177e4SLinus Torvalds 5161da177e4SLinus Torvalds while (*n) { 5171da177e4SLinus Torvalds pn = *n; 5181da177e4SLinus Torvalds tpath = rb_entry(pn, struct ipoib_path, rb_node); 5191da177e4SLinus Torvalds 5201da177e4SLinus Torvalds ret = memcmp(path->pathrec.dgid.raw, tpath->pathrec.dgid.raw, 5211da177e4SLinus Torvalds sizeof (union ib_gid)); 5221da177e4SLinus Torvalds if (ret < 0) 5231da177e4SLinus Torvalds n = &pn->rb_left; 5241da177e4SLinus Torvalds else if (ret > 0) 5251da177e4SLinus Torvalds n = &pn->rb_right; 5261da177e4SLinus Torvalds else 5271da177e4SLinus Torvalds return -EEXIST; 5281da177e4SLinus Torvalds } 5291da177e4SLinus Torvalds 5301da177e4SLinus Torvalds rb_link_node(&path->rb_node, pn, n); 5311da177e4SLinus Torvalds rb_insert_color(&path->rb_node, &priv->path_tree); 5321da177e4SLinus Torvalds 5331da177e4SLinus Torvalds list_add_tail(&path->list, &priv->path_list); 5341da177e4SLinus Torvalds 5351da177e4SLinus Torvalds return 0; 5361da177e4SLinus Torvalds } 5371da177e4SLinus Torvalds 5381da177e4SLinus Torvalds static void path_free(struct net_device *dev, struct ipoib_path *path) 5391da177e4SLinus Torvalds { 5401da177e4SLinus Torvalds struct sk_buff *skb; 5411da177e4SLinus Torvalds 5421da177e4SLinus Torvalds while ((skb = __skb_dequeue(&path->queue))) 5431da177e4SLinus Torvalds dev_kfree_skb_irq(skb); 5441da177e4SLinus Torvalds 545b63b70d8SShlomo Pongratz ipoib_dbg(netdev_priv(dev), "path_free\n"); 5461da177e4SLinus Torvalds 547b63b70d8SShlomo Pongratz /* remove all neigh connected to this path */ 548b63b70d8SShlomo Pongratz ipoib_del_neighs_by_gid(dev, path->pathrec.dgid.raw); 5491da177e4SLinus Torvalds 5501da177e4SLinus Torvalds if (path->ah) 5511da177e4SLinus Torvalds ipoib_put_ah(path->ah); 5521da177e4SLinus Torvalds 5531da177e4SLinus Torvalds kfree(path); 5541da177e4SLinus Torvalds } 5551da177e4SLinus Torvalds 5561732b0efSRoland Dreier #ifdef CONFIG_INFINIBAND_IPOIB_DEBUG 5571732b0efSRoland Dreier 5581732b0efSRoland Dreier struct ipoib_path_iter *ipoib_path_iter_init(struct net_device *dev) 5591732b0efSRoland Dreier { 5601732b0efSRoland Dreier struct ipoib_path_iter *iter; 5611732b0efSRoland Dreier 5621732b0efSRoland Dreier iter = kmalloc(sizeof *iter, GFP_KERNEL); 5631732b0efSRoland Dreier if (!iter) 5641732b0efSRoland Dreier return NULL; 5651732b0efSRoland Dreier 5661732b0efSRoland Dreier iter->dev = dev; 5671732b0efSRoland Dreier memset(iter->path.pathrec.dgid.raw, 0, 16); 5681732b0efSRoland Dreier 5691732b0efSRoland Dreier if (ipoib_path_iter_next(iter)) { 5701732b0efSRoland Dreier kfree(iter); 5711732b0efSRoland Dreier return NULL; 5721732b0efSRoland Dreier } 5731732b0efSRoland Dreier 5741732b0efSRoland Dreier return iter; 5751732b0efSRoland Dreier } 5761732b0efSRoland Dreier 5771732b0efSRoland Dreier int ipoib_path_iter_next(struct ipoib_path_iter *iter) 5781732b0efSRoland Dreier { 5791732b0efSRoland Dreier struct ipoib_dev_priv *priv = netdev_priv(iter->dev); 5801732b0efSRoland Dreier struct rb_node *n; 5811732b0efSRoland Dreier struct ipoib_path *path; 5821732b0efSRoland Dreier int ret = 1; 5831732b0efSRoland Dreier 5841732b0efSRoland Dreier spin_lock_irq(&priv->lock); 5851732b0efSRoland Dreier 5861732b0efSRoland Dreier n = rb_first(&priv->path_tree); 5871732b0efSRoland Dreier 5881732b0efSRoland Dreier while (n) { 5891732b0efSRoland Dreier path = rb_entry(n, struct ipoib_path, rb_node); 5901732b0efSRoland Dreier 5911732b0efSRoland Dreier if (memcmp(iter->path.pathrec.dgid.raw, path->pathrec.dgid.raw, 5921732b0efSRoland Dreier sizeof (union ib_gid)) < 0) { 5931732b0efSRoland Dreier iter->path = *path; 5941732b0efSRoland Dreier ret = 0; 5951732b0efSRoland Dreier break; 5961732b0efSRoland Dreier } 5971732b0efSRoland Dreier 5981732b0efSRoland Dreier n = rb_next(n); 5991732b0efSRoland Dreier } 6001732b0efSRoland Dreier 6011732b0efSRoland Dreier spin_unlock_irq(&priv->lock); 6021732b0efSRoland Dreier 6031732b0efSRoland Dreier return ret; 6041732b0efSRoland Dreier } 6051732b0efSRoland Dreier 6061732b0efSRoland Dreier void ipoib_path_iter_read(struct ipoib_path_iter *iter, 6071732b0efSRoland Dreier struct ipoib_path *path) 6081732b0efSRoland Dreier { 6091732b0efSRoland Dreier *path = iter->path; 6101732b0efSRoland Dreier } 6111732b0efSRoland Dreier 6121732b0efSRoland Dreier #endif /* CONFIG_INFINIBAND_IPOIB_DEBUG */ 6131732b0efSRoland Dreier 614ee1e2c82SMoni Shoua void ipoib_mark_paths_invalid(struct net_device *dev) 615ee1e2c82SMoni Shoua { 616ee1e2c82SMoni Shoua struct ipoib_dev_priv *priv = netdev_priv(dev); 617ee1e2c82SMoni Shoua struct ipoib_path *path, *tp; 618ee1e2c82SMoni Shoua 619ee1e2c82SMoni Shoua spin_lock_irq(&priv->lock); 620ee1e2c82SMoni Shoua 621ee1e2c82SMoni Shoua list_for_each_entry_safe(path, tp, &priv->path_list, list) { 6225b095d98SHarvey Harrison ipoib_dbg(priv, "mark path LID 0x%04x GID %pI6 invalid\n", 623ee1e2c82SMoni Shoua be16_to_cpu(path->pathrec.dlid), 624fcace2feSHarvey Harrison path->pathrec.dgid.raw); 625ee1e2c82SMoni Shoua path->valid = 0; 626ee1e2c82SMoni Shoua } 627ee1e2c82SMoni Shoua 628ee1e2c82SMoni Shoua spin_unlock_irq(&priv->lock); 629ee1e2c82SMoni Shoua } 630ee1e2c82SMoni Shoua 6311da177e4SLinus Torvalds void ipoib_flush_paths(struct net_device *dev) 6321da177e4SLinus Torvalds { 6331da177e4SLinus Torvalds struct ipoib_dev_priv *priv = netdev_priv(dev); 6341da177e4SLinus Torvalds struct ipoib_path *path, *tp; 6351da177e4SLinus Torvalds LIST_HEAD(remove_list); 636943c246eSRoland Dreier unsigned long flags; 6371da177e4SLinus Torvalds 638943c246eSRoland Dreier netif_tx_lock_bh(dev); 639943c246eSRoland Dreier spin_lock_irqsave(&priv->lock, flags); 6401da177e4SLinus Torvalds 641157de229SRobert P. J. Day list_splice_init(&priv->path_list, &remove_list); 6421da177e4SLinus Torvalds 6431da177e4SLinus Torvalds list_for_each_entry(path, &remove_list, list) 6441da177e4SLinus Torvalds rb_erase(&path->rb_node, &priv->path_tree); 6451da177e4SLinus Torvalds 6461da177e4SLinus Torvalds list_for_each_entry_safe(path, tp, &remove_list, list) { 6471da177e4SLinus Torvalds if (path->query) 6481da177e4SLinus Torvalds ib_sa_cancel_query(path->query_id, path->query); 649943c246eSRoland Dreier spin_unlock_irqrestore(&priv->lock, flags); 650943c246eSRoland Dreier netif_tx_unlock_bh(dev); 6511da177e4SLinus Torvalds wait_for_completion(&path->done); 6521da177e4SLinus Torvalds path_free(dev, path); 653943c246eSRoland Dreier netif_tx_lock_bh(dev); 654943c246eSRoland Dreier spin_lock_irqsave(&priv->lock, flags); 6551da177e4SLinus Torvalds } 656943c246eSRoland Dreier 657943c246eSRoland Dreier spin_unlock_irqrestore(&priv->lock, flags); 658943c246eSRoland Dreier netif_tx_unlock_bh(dev); 6591da177e4SLinus Torvalds } 6601da177e4SLinus Torvalds 6611da177e4SLinus Torvalds static void path_rec_completion(int status, 6621da177e4SLinus Torvalds struct ib_sa_path_rec *pathrec, 6631da177e4SLinus Torvalds void *path_ptr) 6641da177e4SLinus Torvalds { 6651da177e4SLinus Torvalds struct ipoib_path *path = path_ptr; 6661da177e4SLinus Torvalds struct net_device *dev = path->dev; 6671da177e4SLinus Torvalds struct ipoib_dev_priv *priv = netdev_priv(dev); 6681da177e4SLinus Torvalds struct ipoib_ah *ah = NULL; 669c9da4badSRoland Dreier struct ipoib_ah *old_ah = NULL; 670d04d01b1SMichael S. Tsirkin struct ipoib_neigh *neigh, *tn; 6711da177e4SLinus Torvalds struct sk_buff_head skqueue; 6721da177e4SLinus Torvalds struct sk_buff *skb; 6731da177e4SLinus Torvalds unsigned long flags; 6741da177e4SLinus Torvalds 675843613b0SRoland Dreier if (!status) 6765b095d98SHarvey Harrison ipoib_dbg(priv, "PathRec LID 0x%04x for GID %pI6\n", 677fcace2feSHarvey Harrison be16_to_cpu(pathrec->dlid), pathrec->dgid.raw); 6781da177e4SLinus Torvalds else 6795b095d98SHarvey Harrison ipoib_dbg(priv, "PathRec status %d for GID %pI6\n", 680fcace2feSHarvey Harrison status, path->pathrec.dgid.raw); 6811da177e4SLinus Torvalds 6821da177e4SLinus Torvalds skb_queue_head_init(&skqueue); 6831da177e4SLinus Torvalds 6841da177e4SLinus Torvalds if (!status) { 68546f1b3d7SSean Hefty struct ib_ah_attr av; 6861da177e4SLinus Torvalds 68746f1b3d7SSean Hefty if (!ib_init_ah_from_path(priv->ca, priv->port, pathrec, &av)) 6881da177e4SLinus Torvalds ah = ipoib_create_ah(dev, priv->pd, &av); 6891da177e4SLinus Torvalds } 6901da177e4SLinus Torvalds 6911da177e4SLinus Torvalds spin_lock_irqsave(&priv->lock, flags); 6921da177e4SLinus Torvalds 6933874397cSMike Marciniszyn if (!IS_ERR_OR_NULL(ah)) { 6941da177e4SLinus Torvalds path->pathrec = *pathrec; 6951da177e4SLinus Torvalds 696c9da4badSRoland Dreier old_ah = path->ah; 697c9da4badSRoland Dreier path->ah = ah; 698c9da4badSRoland Dreier 6991da177e4SLinus Torvalds ipoib_dbg(priv, "created address handle %p for LID 0x%04x, SL %d\n", 7001da177e4SLinus Torvalds ah, be16_to_cpu(pathrec->dlid), pathrec->sl); 7011da177e4SLinus Torvalds 7021da177e4SLinus Torvalds while ((skb = __skb_dequeue(&path->queue))) 7031da177e4SLinus Torvalds __skb_queue_tail(&skqueue, skb); 7041da177e4SLinus Torvalds 705d04d01b1SMichael S. Tsirkin list_for_each_entry_safe(neigh, tn, &path->neigh_list, list) { 706ee1e2c82SMoni Shoua if (neigh->ah) { 707ee1e2c82SMoni Shoua WARN_ON(neigh->ah != old_ah); 708ee1e2c82SMoni Shoua /* 709ee1e2c82SMoni Shoua * Dropping the ah reference inside 710ee1e2c82SMoni Shoua * priv->lock is safe here, because we 711ee1e2c82SMoni Shoua * will hold one more reference from 712ee1e2c82SMoni Shoua * the original value of path->ah (ie 713ee1e2c82SMoni Shoua * old_ah). 714ee1e2c82SMoni Shoua */ 715ee1e2c82SMoni Shoua ipoib_put_ah(neigh->ah); 716ee1e2c82SMoni Shoua } 7171da177e4SLinus Torvalds kref_get(&path->ah->ref); 7181da177e4SLinus Torvalds neigh->ah = path->ah; 7191da177e4SLinus Torvalds 720b63b70d8SShlomo Pongratz if (ipoib_cm_enabled(dev, neigh->daddr)) { 721839fcabaSMichael S. Tsirkin if (!ipoib_cm_get(neigh)) 722839fcabaSMichael S. Tsirkin ipoib_cm_set(neigh, ipoib_cm_create_tx(dev, 723839fcabaSMichael S. Tsirkin path, 724839fcabaSMichael S. Tsirkin neigh)); 725839fcabaSMichael S. Tsirkin if (!ipoib_cm_get(neigh)) { 726b63b70d8SShlomo Pongratz ipoib_neigh_free(neigh); 727839fcabaSMichael S. Tsirkin continue; 728839fcabaSMichael S. Tsirkin } 729839fcabaSMichael S. Tsirkin } 730839fcabaSMichael S. Tsirkin 7311da177e4SLinus Torvalds while ((skb = __skb_dequeue(&neigh->queue))) 7321da177e4SLinus Torvalds __skb_queue_tail(&skqueue, skb); 7331da177e4SLinus Torvalds } 734ee1e2c82SMoni Shoua path->valid = 1; 7355872a9fcSRoland Dreier } 7361da177e4SLinus Torvalds 7375872a9fcSRoland Dreier path->query = NULL; 7381da177e4SLinus Torvalds complete(&path->done); 7391da177e4SLinus Torvalds 7401da177e4SLinus Torvalds spin_unlock_irqrestore(&priv->lock, flags); 7411da177e4SLinus Torvalds 742f72dd566SRoland Dreier if (IS_ERR_OR_NULL(ah)) 743f72dd566SRoland Dreier ipoib_del_neighs_by_gid(dev, path->pathrec.dgid.raw); 744f72dd566SRoland Dreier 745ee1e2c82SMoni Shoua if (old_ah) 746ee1e2c82SMoni Shoua ipoib_put_ah(old_ah); 747ee1e2c82SMoni Shoua 7481da177e4SLinus Torvalds while ((skb = __skb_dequeue(&skqueue))) { 7491da177e4SLinus Torvalds skb->dev = dev; 7501da177e4SLinus Torvalds if (dev_queue_xmit(skb)) 7511da177e4SLinus Torvalds ipoib_warn(priv, "dev_queue_xmit failed " 7521da177e4SLinus Torvalds "to requeue packet\n"); 7531da177e4SLinus Torvalds } 7541da177e4SLinus Torvalds } 7551da177e4SLinus Torvalds 75637c22a77SJack Morgenstein static struct ipoib_path *path_rec_create(struct net_device *dev, void *gid) 7571da177e4SLinus Torvalds { 7581da177e4SLinus Torvalds struct ipoib_dev_priv *priv = netdev_priv(dev); 7591da177e4SLinus Torvalds struct ipoib_path *path; 7601da177e4SLinus Torvalds 7611401b53aSJack Morgenstein if (!priv->broadcast) 7621401b53aSJack Morgenstein return NULL; 7631401b53aSJack Morgenstein 76421a38489SRoland Dreier path = kzalloc(sizeof *path, GFP_ATOMIC); 7651da177e4SLinus Torvalds if (!path) 7661da177e4SLinus Torvalds return NULL; 7671da177e4SLinus Torvalds 7681da177e4SLinus Torvalds path->dev = dev; 7691da177e4SLinus Torvalds 7701da177e4SLinus Torvalds skb_queue_head_init(&path->queue); 7711da177e4SLinus Torvalds 7721da177e4SLinus Torvalds INIT_LIST_HEAD(&path->neigh_list); 7731da177e4SLinus Torvalds 77437c22a77SJack Morgenstein memcpy(path->pathrec.dgid.raw, gid, sizeof (union ib_gid)); 7751da177e4SLinus Torvalds path->pathrec.sgid = priv->local_gid; 7761da177e4SLinus Torvalds path->pathrec.pkey = cpu_to_be16(priv->pkey); 7771da177e4SLinus Torvalds path->pathrec.numb_path = 1; 77881668838SSean Hefty path->pathrec.traffic_class = priv->broadcast->mcmember.traffic_class; 7791da177e4SLinus Torvalds 7801da177e4SLinus Torvalds return path; 7811da177e4SLinus Torvalds } 7821da177e4SLinus Torvalds 7831da177e4SLinus Torvalds static int path_rec_start(struct net_device *dev, 7841da177e4SLinus Torvalds struct ipoib_path *path) 7851da177e4SLinus Torvalds { 7861da177e4SLinus Torvalds struct ipoib_dev_priv *priv = netdev_priv(dev); 7871da177e4SLinus Torvalds 7885b095d98SHarvey Harrison ipoib_dbg(priv, "Start path record lookup for %pI6\n", 789fcace2feSHarvey Harrison path->pathrec.dgid.raw); 7901da177e4SLinus Torvalds 79165c7eddaSRoland Dreier init_completion(&path->done); 79265c7eddaSRoland Dreier 7931da177e4SLinus Torvalds path->query_id = 794c1a0b23bSMichael S. Tsirkin ib_sa_path_rec_get(&ipoib_sa_client, priv->ca, priv->port, 7951da177e4SLinus Torvalds &path->pathrec, 7961da177e4SLinus Torvalds IB_SA_PATH_REC_DGID | 7971da177e4SLinus Torvalds IB_SA_PATH_REC_SGID | 7981da177e4SLinus Torvalds IB_SA_PATH_REC_NUMB_PATH | 79981668838SSean Hefty IB_SA_PATH_REC_TRAFFIC_CLASS | 8001da177e4SLinus Torvalds IB_SA_PATH_REC_PKEY, 8011da177e4SLinus Torvalds 1000, GFP_ATOMIC, 8021da177e4SLinus Torvalds path_rec_completion, 8031da177e4SLinus Torvalds path, &path->query); 8041da177e4SLinus Torvalds if (path->query_id < 0) { 80501b3fc8bSOr Gerlitz ipoib_warn(priv, "ib_sa_path_rec_get failed: %d\n", path->query_id); 8061da177e4SLinus Torvalds path->query = NULL; 80793a3ab93SYossi Etigin complete(&path->done); 8081da177e4SLinus Torvalds return path->query_id; 8091da177e4SLinus Torvalds } 8101da177e4SLinus Torvalds 8111da177e4SLinus Torvalds return 0; 8121da177e4SLinus Torvalds } 8131da177e4SLinus Torvalds 814b63b70d8SShlomo Pongratz static void neigh_add_path(struct sk_buff *skb, u8 *daddr, 815b63b70d8SShlomo Pongratz struct net_device *dev) 8161da177e4SLinus Torvalds { 8171da177e4SLinus Torvalds struct ipoib_dev_priv *priv = netdev_priv(dev); 8181da177e4SLinus Torvalds struct ipoib_path *path; 8191da177e4SLinus Torvalds struct ipoib_neigh *neigh; 820943c246eSRoland Dreier unsigned long flags; 8211da177e4SLinus Torvalds 822b5120a6eSShlomo Pongratz spin_lock_irqsave(&priv->lock, flags); 823b63b70d8SShlomo Pongratz neigh = ipoib_neigh_alloc(daddr, dev); 8241da177e4SLinus Torvalds if (!neigh) { 825b5120a6eSShlomo Pongratz spin_unlock_irqrestore(&priv->lock, flags); 826de903512SRoland Dreier ++dev->stats.tx_dropped; 8271da177e4SLinus Torvalds dev_kfree_skb_any(skb); 8281da177e4SLinus Torvalds return; 8291da177e4SLinus Torvalds } 8301da177e4SLinus Torvalds 831b63b70d8SShlomo Pongratz path = __path_find(dev, daddr + 4); 8321da177e4SLinus Torvalds if (!path) { 833b63b70d8SShlomo Pongratz path = path_rec_create(dev, daddr + 4); 8341da177e4SLinus Torvalds if (!path) 835d2e0655eSMichael S. Tsirkin goto err_path; 8361da177e4SLinus Torvalds 8371da177e4SLinus Torvalds __path_add(dev, path); 8381da177e4SLinus Torvalds } 8391da177e4SLinus Torvalds 8401da177e4SLinus Torvalds list_add_tail(&neigh->list, &path->neigh_list); 8411da177e4SLinus Torvalds 84247f7a071SMichael S. Tsirkin if (path->ah) { 8431da177e4SLinus Torvalds kref_get(&path->ah->ref); 8441da177e4SLinus Torvalds neigh->ah = path->ah; 8451da177e4SLinus Torvalds 846b63b70d8SShlomo Pongratz if (ipoib_cm_enabled(dev, neigh->daddr)) { 847839fcabaSMichael S. Tsirkin if (!ipoib_cm_get(neigh)) 848839fcabaSMichael S. Tsirkin ipoib_cm_set(neigh, ipoib_cm_create_tx(dev, path, neigh)); 849839fcabaSMichael S. Tsirkin if (!ipoib_cm_get(neigh)) { 850b63b70d8SShlomo Pongratz ipoib_neigh_free(neigh); 851839fcabaSMichael S. Tsirkin goto err_drop; 852839fcabaSMichael S. Tsirkin } 853839fcabaSMichael S. Tsirkin if (skb_queue_len(&neigh->queue) < IPOIB_MAX_PATH_REC_QUEUE) 854839fcabaSMichael S. Tsirkin __skb_queue_tail(&neigh->queue, skb); 855839fcabaSMichael S. Tsirkin else { 856839fcabaSMichael S. Tsirkin ipoib_warn(priv, "queue length limit %d. Packet drop.\n", 857839fcabaSMichael S. Tsirkin skb_queue_len(&neigh->queue)); 858839fcabaSMichael S. Tsirkin goto err_drop; 859839fcabaSMichael S. Tsirkin } 860721d67cdSRoland Dreier } else { 861721d67cdSRoland Dreier spin_unlock_irqrestore(&priv->lock, flags); 862b63b70d8SShlomo Pongratz ipoib_send(dev, skb, path->ah, IPOIB_QPN(daddr)); 863b63b70d8SShlomo Pongratz ipoib_neigh_put(neigh); 864721d67cdSRoland Dreier return; 865721d67cdSRoland Dreier } 8661da177e4SLinus Torvalds } else { 8671da177e4SLinus Torvalds neigh->ah = NULL; 8681da177e4SLinus Torvalds 8691da177e4SLinus Torvalds if (!path->query && path_rec_start(dev, path)) 87049b8e744SJim Foraker goto err_path; 8711e85b806SErez Shitrit if (skb_queue_len(&neigh->queue) < IPOIB_MAX_PATH_REC_QUEUE) 8722745b5b7SMichael S. Tsirkin __skb_queue_tail(&neigh->queue, skb); 8731e85b806SErez Shitrit else 8741e85b806SErez Shitrit goto err_drop; 8751da177e4SLinus Torvalds } 8761da177e4SLinus Torvalds 877943c246eSRoland Dreier spin_unlock_irqrestore(&priv->lock, flags); 878b63b70d8SShlomo Pongratz ipoib_neigh_put(neigh); 8791da177e4SLinus Torvalds return; 8801da177e4SLinus Torvalds 881d2e0655eSMichael S. Tsirkin err_path: 882b63b70d8SShlomo Pongratz ipoib_neigh_free(neigh); 883839fcabaSMichael S. Tsirkin err_drop: 884de903512SRoland Dreier ++dev->stats.tx_dropped; 8851da177e4SLinus Torvalds dev_kfree_skb_any(skb); 8861da177e4SLinus Torvalds 887943c246eSRoland Dreier spin_unlock_irqrestore(&priv->lock, flags); 888b63b70d8SShlomo Pongratz ipoib_neigh_put(neigh); 8891da177e4SLinus Torvalds } 8901da177e4SLinus Torvalds 8911da177e4SLinus Torvalds static void unicast_arp_send(struct sk_buff *skb, struct net_device *dev, 892936d7de3SRoland Dreier struct ipoib_cb *cb) 8931da177e4SLinus Torvalds { 8941da177e4SLinus Torvalds struct ipoib_dev_priv *priv = netdev_priv(dev); 8951da177e4SLinus Torvalds struct ipoib_path *path; 896943c246eSRoland Dreier unsigned long flags; 8971da177e4SLinus Torvalds 898943c246eSRoland Dreier spin_lock_irqsave(&priv->lock, flags); 8991da177e4SLinus Torvalds 900936d7de3SRoland Dreier path = __path_find(dev, cb->hwaddr + 4); 901ee1e2c82SMoni Shoua if (!path || !path->valid) { 90271d98b46SJack Morgenstein int new_path = 0; 90371d98b46SJack Morgenstein 90471d98b46SJack Morgenstein if (!path) { 905936d7de3SRoland Dreier path = path_rec_create(dev, cb->hwaddr + 4); 90671d98b46SJack Morgenstein new_path = 1; 90771d98b46SJack Morgenstein } 9081da177e4SLinus Torvalds if (path) { 9091e85b806SErez Shitrit if (skb_queue_len(&path->queue) < IPOIB_MAX_PATH_REC_QUEUE) { 9101da177e4SLinus Torvalds __skb_queue_tail(&path->queue, skb); 9111e85b806SErez Shitrit } else { 9121e85b806SErez Shitrit ++dev->stats.tx_dropped; 9131e85b806SErez Shitrit dev_kfree_skb_any(skb); 9141e85b806SErez Shitrit } 9151da177e4SLinus Torvalds 916ff79ae80SYossi Etigin if (!path->query && path_rec_start(dev, path)) { 917943c246eSRoland Dreier spin_unlock_irqrestore(&priv->lock, flags); 91871d98b46SJack Morgenstein if (new_path) 9191da177e4SLinus Torvalds path_free(dev, path); 9201da177e4SLinus Torvalds return; 9211da177e4SLinus Torvalds } else 9221da177e4SLinus Torvalds __path_add(dev, path); 9231da177e4SLinus Torvalds } else { 924de903512SRoland Dreier ++dev->stats.tx_dropped; 9251da177e4SLinus Torvalds dev_kfree_skb_any(skb); 9261da177e4SLinus Torvalds } 9271da177e4SLinus Torvalds 928943c246eSRoland Dreier spin_unlock_irqrestore(&priv->lock, flags); 9291da177e4SLinus Torvalds return; 9301da177e4SLinus Torvalds } 9311da177e4SLinus Torvalds 93247f7a071SMichael S. Tsirkin if (path->ah) { 9331da177e4SLinus Torvalds ipoib_dbg(priv, "Send unicast ARP to %04x\n", 9341da177e4SLinus Torvalds be16_to_cpu(path->pathrec.dlid)); 9351da177e4SLinus Torvalds 936721d67cdSRoland Dreier spin_unlock_irqrestore(&priv->lock, flags); 937936d7de3SRoland Dreier ipoib_send(dev, skb, path->ah, IPOIB_QPN(cb->hwaddr)); 938721d67cdSRoland Dreier return; 9391da177e4SLinus Torvalds } else if ((path->query || !path_rec_start(dev, path)) && 9401da177e4SLinus Torvalds skb_queue_len(&path->queue) < IPOIB_MAX_PATH_REC_QUEUE) { 9411da177e4SLinus Torvalds __skb_queue_tail(&path->queue, skb); 9421da177e4SLinus Torvalds } else { 943de903512SRoland Dreier ++dev->stats.tx_dropped; 9441da177e4SLinus Torvalds dev_kfree_skb_any(skb); 9451da177e4SLinus Torvalds } 9461da177e4SLinus Torvalds 947943c246eSRoland Dreier spin_unlock_irqrestore(&priv->lock, flags); 9481da177e4SLinus Torvalds } 9491da177e4SLinus Torvalds 9501da177e4SLinus Torvalds static int ipoib_start_xmit(struct sk_buff *skb, struct net_device *dev) 9511da177e4SLinus Torvalds { 9521da177e4SLinus Torvalds struct ipoib_dev_priv *priv = netdev_priv(dev); 9531da177e4SLinus Torvalds struct ipoib_neigh *neigh; 954b49fe362SEric Dumazet struct ipoib_cb *cb = ipoib_skb_cb(skb); 955b63b70d8SShlomo Pongratz struct ipoib_header *header; 9561da177e4SLinus Torvalds unsigned long flags; 9571da177e4SLinus Torvalds 958b63b70d8SShlomo Pongratz header = (struct ipoib_header *) skb->data; 959b63b70d8SShlomo Pongratz 960b63b70d8SShlomo Pongratz if (unlikely(cb->hwaddr[4] == 0xff)) { 961b63b70d8SShlomo Pongratz /* multicast, arrange "if" according to probability */ 962b63b70d8SShlomo Pongratz if ((header->proto != htons(ETH_P_IP)) && 963b63b70d8SShlomo Pongratz (header->proto != htons(ETH_P_IPV6)) && 964b63b70d8SShlomo Pongratz (header->proto != htons(ETH_P_ARP)) && 965dc850b0eSPatrick McHardy (header->proto != htons(ETH_P_RARP)) && 966dc850b0eSPatrick McHardy (header->proto != htons(ETH_P_TIPC))) { 967b63b70d8SShlomo Pongratz /* ethertype not supported by IPoIB */ 96817e6abeeSDavid Miller ++dev->stats.tx_dropped; 96917e6abeeSDavid Miller dev_kfree_skb_any(skb); 970b63b70d8SShlomo Pongratz return NETDEV_TX_OK; 97117e6abeeSDavid Miller } 972b63b70d8SShlomo Pongratz /* Add in the P_Key for multicast*/ 973b63b70d8SShlomo Pongratz cb->hwaddr[8] = (priv->pkey >> 8) & 0xff; 974b63b70d8SShlomo Pongratz cb->hwaddr[9] = priv->pkey & 0xff; 975b63b70d8SShlomo Pongratz 976b63b70d8SShlomo Pongratz neigh = ipoib_neigh_get(dev, cb->hwaddr); 977b63b70d8SShlomo Pongratz if (likely(neigh)) 978b63b70d8SShlomo Pongratz goto send_using_neigh; 979b63b70d8SShlomo Pongratz ipoib_mcast_send(dev, cb->hwaddr, skb); 980b63b70d8SShlomo Pongratz return NETDEV_TX_OK; 9811da177e4SLinus Torvalds } 9821da177e4SLinus Torvalds 983b63b70d8SShlomo Pongratz /* unicast, arrange "switch" according to probability */ 984b63b70d8SShlomo Pongratz switch (header->proto) { 985b63b70d8SShlomo Pongratz case htons(ETH_P_IP): 986b63b70d8SShlomo Pongratz case htons(ETH_P_IPV6): 987dc850b0eSPatrick McHardy case htons(ETH_P_TIPC): 988b63b70d8SShlomo Pongratz neigh = ipoib_neigh_get(dev, cb->hwaddr); 989b63b70d8SShlomo Pongratz if (unlikely(!neigh)) { 990b63b70d8SShlomo Pongratz neigh_add_path(skb, cb->hwaddr, dev); 991b63b70d8SShlomo Pongratz return NETDEV_TX_OK; 992b63b70d8SShlomo Pongratz } 993b63b70d8SShlomo Pongratz break; 994b63b70d8SShlomo Pongratz case htons(ETH_P_ARP): 995b63b70d8SShlomo Pongratz case htons(ETH_P_RARP): 996b63b70d8SShlomo Pongratz /* for unicast ARP and RARP should always perform path find */ 997b63b70d8SShlomo Pongratz unicast_arp_send(skb, dev, cb); 998b63b70d8SShlomo Pongratz return NETDEV_TX_OK; 999b63b70d8SShlomo Pongratz default: 1000b63b70d8SShlomo Pongratz /* ethertype not supported by IPoIB */ 1001b63b70d8SShlomo Pongratz ++dev->stats.tx_dropped; 1002b63b70d8SShlomo Pongratz dev_kfree_skb_any(skb); 1003b63b70d8SShlomo Pongratz return NETDEV_TX_OK; 10048a7f7521SMichael S. Tsirkin } 10058a7f7521SMichael S. Tsirkin 1006b63b70d8SShlomo Pongratz send_using_neigh: 1007b63b70d8SShlomo Pongratz /* note we now hold a ref to neigh */ 1008bafff974SOr Gerlitz if (ipoib_cm_get(neigh)) { 1009bafff974SOr Gerlitz if (ipoib_cm_up(neigh)) { 1010bafff974SOr Gerlitz ipoib_cm_send(dev, skb, ipoib_cm_get(neigh)); 1011b63b70d8SShlomo Pongratz goto unref; 1012bafff974SOr Gerlitz } 1013bafff974SOr Gerlitz } else if (neigh->ah) { 1014b63b70d8SShlomo Pongratz ipoib_send(dev, skb, neigh->ah, IPOIB_QPN(cb->hwaddr)); 1015b63b70d8SShlomo Pongratz goto unref; 10161da177e4SLinus Torvalds } 10171da177e4SLinus Torvalds 10181da177e4SLinus Torvalds if (skb_queue_len(&neigh->queue) < IPOIB_MAX_PATH_REC_QUEUE) { 1019943c246eSRoland Dreier spin_lock_irqsave(&priv->lock, flags); 10201da177e4SLinus Torvalds __skb_queue_tail(&neigh->queue, skb); 1021943c246eSRoland Dreier spin_unlock_irqrestore(&priv->lock, flags); 10221da177e4SLinus Torvalds } else { 1023de903512SRoland Dreier ++dev->stats.tx_dropped; 10241da177e4SLinus Torvalds dev_kfree_skb_any(skb); 10251da177e4SLinus Torvalds } 10261da177e4SLinus Torvalds 1027b63b70d8SShlomo Pongratz unref: 1028b63b70d8SShlomo Pongratz ipoib_neigh_put(neigh); 10291da177e4SLinus Torvalds 10301da177e4SLinus Torvalds return NETDEV_TX_OK; 10311da177e4SLinus Torvalds } 10321da177e4SLinus Torvalds 10331da177e4SLinus Torvalds static void ipoib_timeout(struct net_device *dev) 10341da177e4SLinus Torvalds { 10351da177e4SLinus Torvalds struct ipoib_dev_priv *priv = netdev_priv(dev); 10361da177e4SLinus Torvalds 10374b2d319bSRoland Dreier ipoib_warn(priv, "transmit timeout: latency %d msecs\n", 10384b2d319bSRoland Dreier jiffies_to_msecs(jiffies - dev->trans_start)); 10394b2d319bSRoland Dreier ipoib_warn(priv, "queue stopped %d, tx_head %u, tx_tail %u\n", 10404b2d319bSRoland Dreier netif_queue_stopped(dev), 10414b2d319bSRoland Dreier priv->tx_head, priv->tx_tail); 10421da177e4SLinus Torvalds /* XXX reset QP, etc. */ 10431da177e4SLinus Torvalds } 10441da177e4SLinus Torvalds 10451da177e4SLinus Torvalds static int ipoib_hard_header(struct sk_buff *skb, 10461da177e4SLinus Torvalds struct net_device *dev, 10471da177e4SLinus Torvalds unsigned short type, 10483b04dddeSStephen Hemminger const void *daddr, const void *saddr, unsigned len) 10491da177e4SLinus Torvalds { 10501da177e4SLinus Torvalds struct ipoib_header *header; 1051b49fe362SEric Dumazet struct ipoib_cb *cb = ipoib_skb_cb(skb); 10521da177e4SLinus Torvalds 10531da177e4SLinus Torvalds header = (struct ipoib_header *) skb_push(skb, sizeof *header); 10541da177e4SLinus Torvalds 10551da177e4SLinus Torvalds header->proto = htons(type); 10561da177e4SLinus Torvalds header->reserved = 0; 10571da177e4SLinus Torvalds 10581da177e4SLinus Torvalds /* 1059b63b70d8SShlomo Pongratz * we don't rely on dst_entry structure, always stuff the 1060936d7de3SRoland Dreier * destination address into skb->cb so we can figure out where 1061936d7de3SRoland Dreier * to send the packet later. 10621da177e4SLinus Torvalds */ 1063936d7de3SRoland Dreier memcpy(cb->hwaddr, daddr, INFINIBAND_ALEN); 10641da177e4SLinus Torvalds 106583bdd3b9SDoug Ledford return sizeof *header; 10661da177e4SLinus Torvalds } 10671da177e4SLinus Torvalds 10681da177e4SLinus Torvalds static void ipoib_set_mcast_list(struct net_device *dev) 10691da177e4SLinus Torvalds { 10701da177e4SLinus Torvalds struct ipoib_dev_priv *priv = netdev_priv(dev); 10711da177e4SLinus Torvalds 10727a343d4cSLeonid Arsh if (!test_bit(IPOIB_FLAG_OPER_UP, &priv->flags)) { 10737a343d4cSLeonid Arsh ipoib_dbg(priv, "IPOIB_FLAG_OPER_UP not set"); 10747a343d4cSLeonid Arsh return; 10757a343d4cSLeonid Arsh } 10767a343d4cSLeonid Arsh 10770b39578bSDoug Ledford queue_work(priv->wq, &priv->restart_task); 10781da177e4SLinus Torvalds } 10791da177e4SLinus Torvalds 10805aa7add8SNicolas Dichtel static int ipoib_get_iflink(const struct net_device *dev) 10815aa7add8SNicolas Dichtel { 10825aa7add8SNicolas Dichtel struct ipoib_dev_priv *priv = netdev_priv(dev); 10835aa7add8SNicolas Dichtel 10842c153959SErez Shitrit /* parent interface */ 10852c153959SErez Shitrit if (!test_bit(IPOIB_FLAG_SUBINTERFACE, &priv->flags)) 10862c153959SErez Shitrit return dev->ifindex; 10872c153959SErez Shitrit 10882c153959SErez Shitrit /* child/vlan interface */ 10895aa7add8SNicolas Dichtel return priv->parent->ifindex; 10905aa7add8SNicolas Dichtel } 10915aa7add8SNicolas Dichtel 1092b63b70d8SShlomo Pongratz static u32 ipoib_addr_hash(struct ipoib_neigh_hash *htbl, u8 *daddr) 10931da177e4SLinus Torvalds { 1094b63b70d8SShlomo Pongratz /* 1095b63b70d8SShlomo Pongratz * Use only the address parts that contributes to spreading 1096b63b70d8SShlomo Pongratz * The subnet prefix is not used as one can not connect to 1097b63b70d8SShlomo Pongratz * same remote port (GUID) using the same remote QPN via two 1098b63b70d8SShlomo Pongratz * different subnets. 1099b63b70d8SShlomo Pongratz */ 1100b63b70d8SShlomo Pongratz /* qpn octets[1:4) & port GUID octets[12:20) */ 11019d1ad66eSShlomo Pongratz u32 *d32 = (u32 *) daddr; 1102b63b70d8SShlomo Pongratz u32 hv; 11031da177e4SLinus Torvalds 11049d1ad66eSShlomo Pongratz hv = jhash_3words(d32[3], d32[4], IPOIB_QPN_MASK & d32[0], 0); 1105b63b70d8SShlomo Pongratz return hv & htbl->mask; 11061da177e4SLinus Torvalds } 11071da177e4SLinus Torvalds 1108b63b70d8SShlomo Pongratz struct ipoib_neigh *ipoib_neigh_get(struct net_device *dev, u8 *daddr) 1109b63b70d8SShlomo Pongratz { 1110b63b70d8SShlomo Pongratz struct ipoib_dev_priv *priv = netdev_priv(dev); 1111b63b70d8SShlomo Pongratz struct ipoib_neigh_table *ntbl = &priv->ntbl; 1112b63b70d8SShlomo Pongratz struct ipoib_neigh_hash *htbl; 1113b63b70d8SShlomo Pongratz struct ipoib_neigh *neigh = NULL; 1114b63b70d8SShlomo Pongratz u32 hash_val; 1115b63b70d8SShlomo Pongratz 1116b63b70d8SShlomo Pongratz rcu_read_lock_bh(); 1117b63b70d8SShlomo Pongratz 1118b63b70d8SShlomo Pongratz htbl = rcu_dereference_bh(ntbl->htbl); 1119b63b70d8SShlomo Pongratz 1120b63b70d8SShlomo Pongratz if (!htbl) 1121b63b70d8SShlomo Pongratz goto out_unlock; 1122b63b70d8SShlomo Pongratz 1123b63b70d8SShlomo Pongratz hash_val = ipoib_addr_hash(htbl, daddr); 1124b63b70d8SShlomo Pongratz for (neigh = rcu_dereference_bh(htbl->buckets[hash_val]); 1125b63b70d8SShlomo Pongratz neigh != NULL; 1126b63b70d8SShlomo Pongratz neigh = rcu_dereference_bh(neigh->hnext)) { 1127b63b70d8SShlomo Pongratz if (memcmp(daddr, neigh->daddr, INFINIBAND_ALEN) == 0) { 1128b63b70d8SShlomo Pongratz /* found, take one ref on behalf of the caller */ 1129b63b70d8SShlomo Pongratz if (!atomic_inc_not_zero(&neigh->refcnt)) { 1130b63b70d8SShlomo Pongratz /* deleted */ 1131b63b70d8SShlomo Pongratz neigh = NULL; 1132b63b70d8SShlomo Pongratz goto out_unlock; 1133b63b70d8SShlomo Pongratz } 1134b63b70d8SShlomo Pongratz neigh->alive = jiffies; 1135b63b70d8SShlomo Pongratz goto out_unlock; 1136b63b70d8SShlomo Pongratz } 1137b63b70d8SShlomo Pongratz } 1138b63b70d8SShlomo Pongratz 1139b63b70d8SShlomo Pongratz out_unlock: 1140b63b70d8SShlomo Pongratz rcu_read_unlock_bh(); 1141b63b70d8SShlomo Pongratz return neigh; 1142b63b70d8SShlomo Pongratz } 1143b63b70d8SShlomo Pongratz 1144b63b70d8SShlomo Pongratz static void __ipoib_reap_neigh(struct ipoib_dev_priv *priv) 1145b63b70d8SShlomo Pongratz { 1146b63b70d8SShlomo Pongratz struct ipoib_neigh_table *ntbl = &priv->ntbl; 1147b63b70d8SShlomo Pongratz struct ipoib_neigh_hash *htbl; 1148b63b70d8SShlomo Pongratz unsigned long neigh_obsolete; 1149b63b70d8SShlomo Pongratz unsigned long dt; 1150b63b70d8SShlomo Pongratz unsigned long flags; 1151b63b70d8SShlomo Pongratz int i; 1152bd99b2e0SChristoph Lameter LIST_HEAD(remove_list); 1153bd99b2e0SChristoph Lameter struct ipoib_mcast *mcast, *tmcast; 1154bd99b2e0SChristoph Lameter struct net_device *dev = priv->dev; 1155b63b70d8SShlomo Pongratz 1156b63b70d8SShlomo Pongratz if (test_bit(IPOIB_STOP_NEIGH_GC, &priv->flags)) 1157b63b70d8SShlomo Pongratz return; 1158b63b70d8SShlomo Pongratz 1159b5120a6eSShlomo Pongratz spin_lock_irqsave(&priv->lock, flags); 1160b63b70d8SShlomo Pongratz 1161b63b70d8SShlomo Pongratz htbl = rcu_dereference_protected(ntbl->htbl, 1162b5120a6eSShlomo Pongratz lockdep_is_held(&priv->lock)); 1163b63b70d8SShlomo Pongratz 1164b63b70d8SShlomo Pongratz if (!htbl) 1165b63b70d8SShlomo Pongratz goto out_unlock; 1166b63b70d8SShlomo Pongratz 1167b63b70d8SShlomo Pongratz /* neigh is obsolete if it was idle for two GC periods */ 1168b63b70d8SShlomo Pongratz dt = 2 * arp_tbl.gc_interval; 1169b63b70d8SShlomo Pongratz neigh_obsolete = jiffies - dt; 1170b63b70d8SShlomo Pongratz /* handle possible race condition */ 1171b63b70d8SShlomo Pongratz if (test_bit(IPOIB_STOP_NEIGH_GC, &priv->flags)) 1172b63b70d8SShlomo Pongratz goto out_unlock; 1173b63b70d8SShlomo Pongratz 1174b63b70d8SShlomo Pongratz for (i = 0; i < htbl->size; i++) { 1175b63b70d8SShlomo Pongratz struct ipoib_neigh *neigh; 1176b63b70d8SShlomo Pongratz struct ipoib_neigh __rcu **np = &htbl->buckets[i]; 1177b63b70d8SShlomo Pongratz 1178b63b70d8SShlomo Pongratz while ((neigh = rcu_dereference_protected(*np, 1179b5120a6eSShlomo Pongratz lockdep_is_held(&priv->lock))) != NULL) { 1180b63b70d8SShlomo Pongratz /* was the neigh idle for two GC periods */ 1181b63b70d8SShlomo Pongratz if (time_after(neigh_obsolete, neigh->alive)) { 1182bd99b2e0SChristoph Lameter u8 *mgid = neigh->daddr + 4; 1183bd99b2e0SChristoph Lameter 1184bd99b2e0SChristoph Lameter /* Is this multicast ? */ 1185bd99b2e0SChristoph Lameter if (*mgid == 0xff) { 1186bd99b2e0SChristoph Lameter mcast = __ipoib_mcast_find(dev, mgid); 1187bd99b2e0SChristoph Lameter 1188bd99b2e0SChristoph Lameter if (mcast && test_bit(IPOIB_MCAST_FLAG_SENDONLY, &mcast->flags)) { 1189bd99b2e0SChristoph Lameter list_del(&mcast->list); 1190bd99b2e0SChristoph Lameter rb_erase(&mcast->rb_node, &priv->multicast_tree); 1191bd99b2e0SChristoph Lameter list_add_tail(&mcast->list, &remove_list); 1192bd99b2e0SChristoph Lameter } 1193bd99b2e0SChristoph Lameter } 1194bd99b2e0SChristoph Lameter 1195b63b70d8SShlomo Pongratz rcu_assign_pointer(*np, 1196b63b70d8SShlomo Pongratz rcu_dereference_protected(neigh->hnext, 1197b5120a6eSShlomo Pongratz lockdep_is_held(&priv->lock))); 1198b63b70d8SShlomo Pongratz /* remove from path/mc list */ 1199b63b70d8SShlomo Pongratz list_del(&neigh->list); 1200b63b70d8SShlomo Pongratz call_rcu(&neigh->rcu, ipoib_neigh_reclaim); 1201b63b70d8SShlomo Pongratz } else { 1202b63b70d8SShlomo Pongratz np = &neigh->hnext; 1203b63b70d8SShlomo Pongratz } 1204b63b70d8SShlomo Pongratz 1205b63b70d8SShlomo Pongratz } 1206b63b70d8SShlomo Pongratz } 1207b63b70d8SShlomo Pongratz 1208b63b70d8SShlomo Pongratz out_unlock: 1209b5120a6eSShlomo Pongratz spin_unlock_irqrestore(&priv->lock, flags); 1210bd99b2e0SChristoph Lameter list_for_each_entry_safe(mcast, tmcast, &remove_list, list) 1211bd99b2e0SChristoph Lameter ipoib_mcast_leave(dev, mcast); 1212b63b70d8SShlomo Pongratz } 1213b63b70d8SShlomo Pongratz 1214b63b70d8SShlomo Pongratz static void ipoib_reap_neigh(struct work_struct *work) 1215b63b70d8SShlomo Pongratz { 1216b63b70d8SShlomo Pongratz struct ipoib_dev_priv *priv = 1217b63b70d8SShlomo Pongratz container_of(work, struct ipoib_dev_priv, neigh_reap_task.work); 1218b63b70d8SShlomo Pongratz 1219b63b70d8SShlomo Pongratz __ipoib_reap_neigh(priv); 1220b63b70d8SShlomo Pongratz 1221b63b70d8SShlomo Pongratz if (!test_bit(IPOIB_STOP_NEIGH_GC, &priv->flags)) 12220b39578bSDoug Ledford queue_delayed_work(priv->wq, &priv->neigh_reap_task, 1223b63b70d8SShlomo Pongratz arp_tbl.gc_interval); 1224b63b70d8SShlomo Pongratz } 1225b63b70d8SShlomo Pongratz 1226b63b70d8SShlomo Pongratz 1227b63b70d8SShlomo Pongratz static struct ipoib_neigh *ipoib_neigh_ctor(u8 *daddr, 1228732a2170SMoni Shoua struct net_device *dev) 1229d2e0655eSMichael S. Tsirkin { 1230d2e0655eSMichael S. Tsirkin struct ipoib_neigh *neigh; 1231d2e0655eSMichael S. Tsirkin 1232b63b70d8SShlomo Pongratz neigh = kzalloc(sizeof *neigh, GFP_ATOMIC); 1233d2e0655eSMichael S. Tsirkin if (!neigh) 1234d2e0655eSMichael S. Tsirkin return NULL; 1235d2e0655eSMichael S. Tsirkin 1236732a2170SMoni Shoua neigh->dev = dev; 1237b63b70d8SShlomo Pongratz memcpy(&neigh->daddr, daddr, sizeof(neigh->daddr)); 123882b39913SRoland Dreier skb_queue_head_init(&neigh->queue); 1239b63b70d8SShlomo Pongratz INIT_LIST_HEAD(&neigh->list); 1240839fcabaSMichael S. Tsirkin ipoib_cm_set(neigh, NULL); 1241b63b70d8SShlomo Pongratz /* one ref on behalf of the caller */ 1242b63b70d8SShlomo Pongratz atomic_set(&neigh->refcnt, 1); 1243d2e0655eSMichael S. Tsirkin 1244d2e0655eSMichael S. Tsirkin return neigh; 1245d2e0655eSMichael S. Tsirkin } 1246d2e0655eSMichael S. Tsirkin 1247b63b70d8SShlomo Pongratz struct ipoib_neigh *ipoib_neigh_alloc(u8 *daddr, 1248b63b70d8SShlomo Pongratz struct net_device *dev) 1249d2e0655eSMichael S. Tsirkin { 1250b63b70d8SShlomo Pongratz struct ipoib_dev_priv *priv = netdev_priv(dev); 1251b63b70d8SShlomo Pongratz struct ipoib_neigh_table *ntbl = &priv->ntbl; 1252b63b70d8SShlomo Pongratz struct ipoib_neigh_hash *htbl; 1253b63b70d8SShlomo Pongratz struct ipoib_neigh *neigh; 1254b63b70d8SShlomo Pongratz u32 hash_val; 1255b63b70d8SShlomo Pongratz 1256b63b70d8SShlomo Pongratz htbl = rcu_dereference_protected(ntbl->htbl, 1257b5120a6eSShlomo Pongratz lockdep_is_held(&priv->lock)); 1258b63b70d8SShlomo Pongratz if (!htbl) { 1259b63b70d8SShlomo Pongratz neigh = NULL; 1260b63b70d8SShlomo Pongratz goto out_unlock; 1261b63b70d8SShlomo Pongratz } 1262b63b70d8SShlomo Pongratz 1263b63b70d8SShlomo Pongratz /* need to add a new neigh, but maybe some other thread succeeded? 1264b63b70d8SShlomo Pongratz * recalc hash, maybe hash resize took place so we do a search 1265b63b70d8SShlomo Pongratz */ 1266b63b70d8SShlomo Pongratz hash_val = ipoib_addr_hash(htbl, daddr); 1267b63b70d8SShlomo Pongratz for (neigh = rcu_dereference_protected(htbl->buckets[hash_val], 1268b5120a6eSShlomo Pongratz lockdep_is_held(&priv->lock)); 1269b63b70d8SShlomo Pongratz neigh != NULL; 1270b63b70d8SShlomo Pongratz neigh = rcu_dereference_protected(neigh->hnext, 1271b5120a6eSShlomo Pongratz lockdep_is_held(&priv->lock))) { 1272b63b70d8SShlomo Pongratz if (memcmp(daddr, neigh->daddr, INFINIBAND_ALEN) == 0) { 1273b63b70d8SShlomo Pongratz /* found, take one ref on behalf of the caller */ 1274b63b70d8SShlomo Pongratz if (!atomic_inc_not_zero(&neigh->refcnt)) { 1275b63b70d8SShlomo Pongratz /* deleted */ 1276b63b70d8SShlomo Pongratz neigh = NULL; 1277b63b70d8SShlomo Pongratz break; 1278b63b70d8SShlomo Pongratz } 1279b63b70d8SShlomo Pongratz neigh->alive = jiffies; 1280b63b70d8SShlomo Pongratz goto out_unlock; 1281b63b70d8SShlomo Pongratz } 1282b63b70d8SShlomo Pongratz } 1283b63b70d8SShlomo Pongratz 1284b63b70d8SShlomo Pongratz neigh = ipoib_neigh_ctor(daddr, dev); 1285b63b70d8SShlomo Pongratz if (!neigh) 1286b63b70d8SShlomo Pongratz goto out_unlock; 1287b63b70d8SShlomo Pongratz 1288b63b70d8SShlomo Pongratz /* one ref on behalf of the hash table */ 1289b63b70d8SShlomo Pongratz atomic_inc(&neigh->refcnt); 1290b63b70d8SShlomo Pongratz neigh->alive = jiffies; 1291b63b70d8SShlomo Pongratz /* put in hash */ 1292b63b70d8SShlomo Pongratz rcu_assign_pointer(neigh->hnext, 1293b63b70d8SShlomo Pongratz rcu_dereference_protected(htbl->buckets[hash_val], 1294b5120a6eSShlomo Pongratz lockdep_is_held(&priv->lock))); 1295b63b70d8SShlomo Pongratz rcu_assign_pointer(htbl->buckets[hash_val], neigh); 1296b63b70d8SShlomo Pongratz atomic_inc(&ntbl->entries); 1297b63b70d8SShlomo Pongratz 1298b63b70d8SShlomo Pongratz out_unlock: 1299b63b70d8SShlomo Pongratz 1300b63b70d8SShlomo Pongratz return neigh; 1301b63b70d8SShlomo Pongratz } 1302b63b70d8SShlomo Pongratz 1303b63b70d8SShlomo Pongratz void ipoib_neigh_dtor(struct ipoib_neigh *neigh) 1304b63b70d8SShlomo Pongratz { 1305b63b70d8SShlomo Pongratz /* neigh reference count was dropprd to zero */ 1306b63b70d8SShlomo Pongratz struct net_device *dev = neigh->dev; 1307b63b70d8SShlomo Pongratz struct ipoib_dev_priv *priv = netdev_priv(dev); 13082745b5b7SMichael S. Tsirkin struct sk_buff *skb; 1309b63b70d8SShlomo Pongratz if (neigh->ah) 1310b63b70d8SShlomo Pongratz ipoib_put_ah(neigh->ah); 13112745b5b7SMichael S. Tsirkin while ((skb = __skb_dequeue(&neigh->queue))) { 1312de903512SRoland Dreier ++dev->stats.tx_dropped; 13132745b5b7SMichael S. Tsirkin dev_kfree_skb_any(skb); 13142745b5b7SMichael S. Tsirkin } 1315839fcabaSMichael S. Tsirkin if (ipoib_cm_get(neigh)) 1316839fcabaSMichael S. Tsirkin ipoib_cm_destroy_tx(ipoib_cm_get(neigh)); 1317b63b70d8SShlomo Pongratz ipoib_dbg(netdev_priv(dev), 1318b63b70d8SShlomo Pongratz "neigh free for %06x %pI6\n", 1319b63b70d8SShlomo Pongratz IPOIB_QPN(neigh->daddr), 1320b63b70d8SShlomo Pongratz neigh->daddr + 4); 1321d2e0655eSMichael S. Tsirkin kfree(neigh); 1322b63b70d8SShlomo Pongratz if (atomic_dec_and_test(&priv->ntbl.entries)) { 1323b63b70d8SShlomo Pongratz if (test_bit(IPOIB_NEIGH_TBL_FLUSH, &priv->flags)) 1324b63b70d8SShlomo Pongratz complete(&priv->ntbl.flushed); 1325b63b70d8SShlomo Pongratz } 1326d2e0655eSMichael S. Tsirkin } 1327d2e0655eSMichael S. Tsirkin 1328b63b70d8SShlomo Pongratz static void ipoib_neigh_reclaim(struct rcu_head *rp) 13291da177e4SLinus Torvalds { 1330b63b70d8SShlomo Pongratz /* Called as a result of removal from hash table */ 1331b63b70d8SShlomo Pongratz struct ipoib_neigh *neigh = container_of(rp, struct ipoib_neigh, rcu); 1332b63b70d8SShlomo Pongratz /* note TX context may hold another ref */ 1333b63b70d8SShlomo Pongratz ipoib_neigh_put(neigh); 1334b63b70d8SShlomo Pongratz } 1335b63b70d8SShlomo Pongratz 1336b63b70d8SShlomo Pongratz void ipoib_neigh_free(struct ipoib_neigh *neigh) 1337b63b70d8SShlomo Pongratz { 1338b63b70d8SShlomo Pongratz struct net_device *dev = neigh->dev; 1339b63b70d8SShlomo Pongratz struct ipoib_dev_priv *priv = netdev_priv(dev); 1340b63b70d8SShlomo Pongratz struct ipoib_neigh_table *ntbl = &priv->ntbl; 1341b63b70d8SShlomo Pongratz struct ipoib_neigh_hash *htbl; 1342b63b70d8SShlomo Pongratz struct ipoib_neigh __rcu **np; 1343b63b70d8SShlomo Pongratz struct ipoib_neigh *n; 1344b63b70d8SShlomo Pongratz u32 hash_val; 1345b63b70d8SShlomo Pongratz 1346b63b70d8SShlomo Pongratz htbl = rcu_dereference_protected(ntbl->htbl, 1347b5120a6eSShlomo Pongratz lockdep_is_held(&priv->lock)); 1348b63b70d8SShlomo Pongratz if (!htbl) 1349b5120a6eSShlomo Pongratz return; 1350b63b70d8SShlomo Pongratz 1351b63b70d8SShlomo Pongratz hash_val = ipoib_addr_hash(htbl, neigh->daddr); 1352b63b70d8SShlomo Pongratz np = &htbl->buckets[hash_val]; 1353b63b70d8SShlomo Pongratz for (n = rcu_dereference_protected(*np, 1354b5120a6eSShlomo Pongratz lockdep_is_held(&priv->lock)); 1355b63b70d8SShlomo Pongratz n != NULL; 13566c723a68SShlomo Pongratz n = rcu_dereference_protected(*np, 1357b5120a6eSShlomo Pongratz lockdep_is_held(&priv->lock))) { 1358b63b70d8SShlomo Pongratz if (n == neigh) { 1359b63b70d8SShlomo Pongratz /* found */ 1360b63b70d8SShlomo Pongratz rcu_assign_pointer(*np, 1361b63b70d8SShlomo Pongratz rcu_dereference_protected(neigh->hnext, 1362b5120a6eSShlomo Pongratz lockdep_is_held(&priv->lock))); 136349b8e744SJim Foraker /* remove from parent list */ 136449b8e744SJim Foraker list_del(&neigh->list); 1365b63b70d8SShlomo Pongratz call_rcu(&neigh->rcu, ipoib_neigh_reclaim); 1366b5120a6eSShlomo Pongratz return; 1367b63b70d8SShlomo Pongratz } else { 1368b63b70d8SShlomo Pongratz np = &n->hnext; 1369b63b70d8SShlomo Pongratz } 1370b63b70d8SShlomo Pongratz } 1371b63b70d8SShlomo Pongratz } 1372b63b70d8SShlomo Pongratz 1373b63b70d8SShlomo Pongratz static int ipoib_neigh_hash_init(struct ipoib_dev_priv *priv) 1374b63b70d8SShlomo Pongratz { 1375b63b70d8SShlomo Pongratz struct ipoib_neigh_table *ntbl = &priv->ntbl; 1376b63b70d8SShlomo Pongratz struct ipoib_neigh_hash *htbl; 137752374967SBart Van Assche struct ipoib_neigh __rcu **buckets; 1378b63b70d8SShlomo Pongratz u32 size; 1379b63b70d8SShlomo Pongratz 1380b63b70d8SShlomo Pongratz clear_bit(IPOIB_NEIGH_TBL_FLUSH, &priv->flags); 1381b63b70d8SShlomo Pongratz ntbl->htbl = NULL; 1382b63b70d8SShlomo Pongratz htbl = kzalloc(sizeof(*htbl), GFP_KERNEL); 1383b63b70d8SShlomo Pongratz if (!htbl) 1384b63b70d8SShlomo Pongratz return -ENOMEM; 1385b63b70d8SShlomo Pongratz set_bit(IPOIB_STOP_NEIGH_GC, &priv->flags); 1386b63b70d8SShlomo Pongratz size = roundup_pow_of_two(arp_tbl.gc_thresh3); 1387b63b70d8SShlomo Pongratz buckets = kzalloc(size * sizeof(*buckets), GFP_KERNEL); 1388b63b70d8SShlomo Pongratz if (!buckets) { 1389b63b70d8SShlomo Pongratz kfree(htbl); 1390b63b70d8SShlomo Pongratz return -ENOMEM; 1391b63b70d8SShlomo Pongratz } 1392b63b70d8SShlomo Pongratz htbl->size = size; 1393b63b70d8SShlomo Pongratz htbl->mask = (size - 1); 1394b63b70d8SShlomo Pongratz htbl->buckets = buckets; 139552374967SBart Van Assche RCU_INIT_POINTER(ntbl->htbl, htbl); 139666172c09SShlomo Pongratz htbl->ntbl = ntbl; 1397b63b70d8SShlomo Pongratz atomic_set(&ntbl->entries, 0); 1398b63b70d8SShlomo Pongratz 1399b63b70d8SShlomo Pongratz /* start garbage collection */ 1400b63b70d8SShlomo Pongratz clear_bit(IPOIB_STOP_NEIGH_GC, &priv->flags); 14010b39578bSDoug Ledford queue_delayed_work(priv->wq, &priv->neigh_reap_task, 1402b63b70d8SShlomo Pongratz arp_tbl.gc_interval); 14031da177e4SLinus Torvalds 14041da177e4SLinus Torvalds return 0; 14051da177e4SLinus Torvalds } 14061da177e4SLinus Torvalds 1407b63b70d8SShlomo Pongratz static void neigh_hash_free_rcu(struct rcu_head *head) 1408b63b70d8SShlomo Pongratz { 1409b63b70d8SShlomo Pongratz struct ipoib_neigh_hash *htbl = container_of(head, 1410b63b70d8SShlomo Pongratz struct ipoib_neigh_hash, 1411b63b70d8SShlomo Pongratz rcu); 1412b63b70d8SShlomo Pongratz struct ipoib_neigh __rcu **buckets = htbl->buckets; 141366172c09SShlomo Pongratz struct ipoib_neigh_table *ntbl = htbl->ntbl; 1414b63b70d8SShlomo Pongratz 1415b63b70d8SShlomo Pongratz kfree(buckets); 1416b63b70d8SShlomo Pongratz kfree(htbl); 141766172c09SShlomo Pongratz complete(&ntbl->deleted); 1418b63b70d8SShlomo Pongratz } 1419b63b70d8SShlomo Pongratz 1420b63b70d8SShlomo Pongratz void ipoib_del_neighs_by_gid(struct net_device *dev, u8 *gid) 1421b63b70d8SShlomo Pongratz { 1422b63b70d8SShlomo Pongratz struct ipoib_dev_priv *priv = netdev_priv(dev); 1423b63b70d8SShlomo Pongratz struct ipoib_neigh_table *ntbl = &priv->ntbl; 1424b63b70d8SShlomo Pongratz struct ipoib_neigh_hash *htbl; 1425b63b70d8SShlomo Pongratz unsigned long flags; 1426b63b70d8SShlomo Pongratz int i; 1427b63b70d8SShlomo Pongratz 1428b63b70d8SShlomo Pongratz /* remove all neigh connected to a given path or mcast */ 1429b5120a6eSShlomo Pongratz spin_lock_irqsave(&priv->lock, flags); 1430b63b70d8SShlomo Pongratz 1431b63b70d8SShlomo Pongratz htbl = rcu_dereference_protected(ntbl->htbl, 1432b5120a6eSShlomo Pongratz lockdep_is_held(&priv->lock)); 1433b63b70d8SShlomo Pongratz 1434b63b70d8SShlomo Pongratz if (!htbl) 1435b63b70d8SShlomo Pongratz goto out_unlock; 1436b63b70d8SShlomo Pongratz 1437b63b70d8SShlomo Pongratz for (i = 0; i < htbl->size; i++) { 1438b63b70d8SShlomo Pongratz struct ipoib_neigh *neigh; 1439b63b70d8SShlomo Pongratz struct ipoib_neigh __rcu **np = &htbl->buckets[i]; 1440b63b70d8SShlomo Pongratz 1441b63b70d8SShlomo Pongratz while ((neigh = rcu_dereference_protected(*np, 1442b5120a6eSShlomo Pongratz lockdep_is_held(&priv->lock))) != NULL) { 1443b63b70d8SShlomo Pongratz /* delete neighs belong to this parent */ 1444b63b70d8SShlomo Pongratz if (!memcmp(gid, neigh->daddr + 4, sizeof (union ib_gid))) { 1445b63b70d8SShlomo Pongratz rcu_assign_pointer(*np, 1446b63b70d8SShlomo Pongratz rcu_dereference_protected(neigh->hnext, 1447b5120a6eSShlomo Pongratz lockdep_is_held(&priv->lock))); 1448b63b70d8SShlomo Pongratz /* remove from parent list */ 1449b63b70d8SShlomo Pongratz list_del(&neigh->list); 1450b63b70d8SShlomo Pongratz call_rcu(&neigh->rcu, ipoib_neigh_reclaim); 1451b63b70d8SShlomo Pongratz } else { 1452b63b70d8SShlomo Pongratz np = &neigh->hnext; 1453b63b70d8SShlomo Pongratz } 1454b63b70d8SShlomo Pongratz 1455b63b70d8SShlomo Pongratz } 1456b63b70d8SShlomo Pongratz } 1457b63b70d8SShlomo Pongratz out_unlock: 1458b5120a6eSShlomo Pongratz spin_unlock_irqrestore(&priv->lock, flags); 1459b63b70d8SShlomo Pongratz } 1460b63b70d8SShlomo Pongratz 1461b63b70d8SShlomo Pongratz static void ipoib_flush_neighs(struct ipoib_dev_priv *priv) 1462b63b70d8SShlomo Pongratz { 1463b63b70d8SShlomo Pongratz struct ipoib_neigh_table *ntbl = &priv->ntbl; 1464b63b70d8SShlomo Pongratz struct ipoib_neigh_hash *htbl; 1465b63b70d8SShlomo Pongratz unsigned long flags; 146666172c09SShlomo Pongratz int i, wait_flushed = 0; 1467b63b70d8SShlomo Pongratz 146866172c09SShlomo Pongratz init_completion(&priv->ntbl.flushed); 1469b63b70d8SShlomo Pongratz 1470b5120a6eSShlomo Pongratz spin_lock_irqsave(&priv->lock, flags); 1471b63b70d8SShlomo Pongratz 1472b63b70d8SShlomo Pongratz htbl = rcu_dereference_protected(ntbl->htbl, 1473b5120a6eSShlomo Pongratz lockdep_is_held(&priv->lock)); 1474b63b70d8SShlomo Pongratz if (!htbl) 1475b63b70d8SShlomo Pongratz goto out_unlock; 1476b63b70d8SShlomo Pongratz 147766172c09SShlomo Pongratz wait_flushed = atomic_read(&priv->ntbl.entries); 147866172c09SShlomo Pongratz if (!wait_flushed) 147966172c09SShlomo Pongratz goto free_htbl; 148066172c09SShlomo Pongratz 1481b63b70d8SShlomo Pongratz for (i = 0; i < htbl->size; i++) { 1482b63b70d8SShlomo Pongratz struct ipoib_neigh *neigh; 1483b63b70d8SShlomo Pongratz struct ipoib_neigh __rcu **np = &htbl->buckets[i]; 1484b63b70d8SShlomo Pongratz 1485b63b70d8SShlomo Pongratz while ((neigh = rcu_dereference_protected(*np, 1486b5120a6eSShlomo Pongratz lockdep_is_held(&priv->lock))) != NULL) { 1487b63b70d8SShlomo Pongratz rcu_assign_pointer(*np, 1488b63b70d8SShlomo Pongratz rcu_dereference_protected(neigh->hnext, 1489b5120a6eSShlomo Pongratz lockdep_is_held(&priv->lock))); 1490b63b70d8SShlomo Pongratz /* remove from path/mc list */ 1491b63b70d8SShlomo Pongratz list_del(&neigh->list); 1492b63b70d8SShlomo Pongratz call_rcu(&neigh->rcu, ipoib_neigh_reclaim); 1493b63b70d8SShlomo Pongratz } 1494b63b70d8SShlomo Pongratz } 1495b63b70d8SShlomo Pongratz 149666172c09SShlomo Pongratz free_htbl: 1497b63b70d8SShlomo Pongratz rcu_assign_pointer(ntbl->htbl, NULL); 1498b63b70d8SShlomo Pongratz call_rcu(&htbl->rcu, neigh_hash_free_rcu); 1499b63b70d8SShlomo Pongratz 1500b63b70d8SShlomo Pongratz out_unlock: 1501b5120a6eSShlomo Pongratz spin_unlock_irqrestore(&priv->lock, flags); 150266172c09SShlomo Pongratz if (wait_flushed) 150366172c09SShlomo Pongratz wait_for_completion(&priv->ntbl.flushed); 1504b63b70d8SShlomo Pongratz } 1505b63b70d8SShlomo Pongratz 1506b63b70d8SShlomo Pongratz static void ipoib_neigh_hash_uninit(struct net_device *dev) 1507b63b70d8SShlomo Pongratz { 1508b63b70d8SShlomo Pongratz struct ipoib_dev_priv *priv = netdev_priv(dev); 1509b63b70d8SShlomo Pongratz int stopped; 1510b63b70d8SShlomo Pongratz 1511b63b70d8SShlomo Pongratz ipoib_dbg(priv, "ipoib_neigh_hash_uninit\n"); 151266172c09SShlomo Pongratz init_completion(&priv->ntbl.deleted); 1513b63b70d8SShlomo Pongratz set_bit(IPOIB_NEIGH_TBL_FLUSH, &priv->flags); 1514b63b70d8SShlomo Pongratz 1515b63b70d8SShlomo Pongratz /* Stop GC if called at init fail need to cancel work */ 1516b63b70d8SShlomo Pongratz stopped = test_and_set_bit(IPOIB_STOP_NEIGH_GC, &priv->flags); 1517b63b70d8SShlomo Pongratz if (!stopped) 1518b63b70d8SShlomo Pongratz cancel_delayed_work(&priv->neigh_reap_task); 1519b63b70d8SShlomo Pongratz 1520b63b70d8SShlomo Pongratz ipoib_flush_neighs(priv); 152166172c09SShlomo Pongratz 152266172c09SShlomo Pongratz wait_for_completion(&priv->ntbl.deleted); 1523b63b70d8SShlomo Pongratz } 1524b63b70d8SShlomo Pongratz 1525b63b70d8SShlomo Pongratz 15261da177e4SLinus Torvalds int ipoib_dev_init(struct net_device *dev, struct ib_device *ca, int port) 15271da177e4SLinus Torvalds { 15281da177e4SLinus Torvalds struct ipoib_dev_priv *priv = netdev_priv(dev); 15291da177e4SLinus Torvalds 15301da177e4SLinus Torvalds /* Allocate RX/TX "rings" to hold queued skbs */ 15310f485251SShirley Ma priv->rx_ring = kzalloc(ipoib_recvq_size * sizeof *priv->rx_ring, 15321da177e4SLinus Torvalds GFP_KERNEL); 15331da177e4SLinus Torvalds if (!priv->rx_ring) { 15341da177e4SLinus Torvalds printk(KERN_WARNING "%s: failed to allocate RX ring (%d entries)\n", 15350f485251SShirley Ma ca->name, ipoib_recvq_size); 1536be7aa663SDoug Ledford goto out; 15371da177e4SLinus Torvalds } 15381da177e4SLinus Torvalds 1539948579cdSJoe Perches priv->tx_ring = vzalloc(ipoib_sendq_size * sizeof *priv->tx_ring); 15401da177e4SLinus Torvalds if (!priv->tx_ring) { 15411da177e4SLinus Torvalds printk(KERN_WARNING "%s: failed to allocate TX ring (%d entries)\n", 15420f485251SShirley Ma ca->name, ipoib_sendq_size); 15431da177e4SLinus Torvalds goto out_rx_ring_cleanup; 15441da177e4SLinus Torvalds } 15451da177e4SLinus Torvalds 15461b524963SMichael S. Tsirkin /* priv->tx_head, tx_tail & tx_outstanding are already 0 */ 15471da177e4SLinus Torvalds 15481da177e4SLinus Torvalds if (ipoib_ib_dev_init(dev, ca, port)) 15491da177e4SLinus Torvalds goto out_tx_ring_cleanup; 15501da177e4SLinus Torvalds 1551be7aa663SDoug Ledford /* 1552be7aa663SDoug Ledford * Must be after ipoib_ib_dev_init so we can allocate a per 1553be7aa663SDoug Ledford * device wq there and use it here 1554be7aa663SDoug Ledford */ 1555be7aa663SDoug Ledford if (ipoib_neigh_hash_init(priv) < 0) 1556be7aa663SDoug Ledford goto out_dev_uninit; 1557be7aa663SDoug Ledford 15581da177e4SLinus Torvalds return 0; 15591da177e4SLinus Torvalds 1560be7aa663SDoug Ledford out_dev_uninit: 1561be7aa663SDoug Ledford ipoib_ib_dev_cleanup(dev); 1562be7aa663SDoug Ledford 15631da177e4SLinus Torvalds out_tx_ring_cleanup: 156410313cbbSRoland Dreier vfree(priv->tx_ring); 15651da177e4SLinus Torvalds 15661da177e4SLinus Torvalds out_rx_ring_cleanup: 15671da177e4SLinus Torvalds kfree(priv->rx_ring); 15681da177e4SLinus Torvalds 15691da177e4SLinus Torvalds out: 15701da177e4SLinus Torvalds return -ENOMEM; 15711da177e4SLinus Torvalds } 15721da177e4SLinus Torvalds 15731da177e4SLinus Torvalds void ipoib_dev_cleanup(struct net_device *dev) 15741da177e4SLinus Torvalds { 15751da177e4SLinus Torvalds struct ipoib_dev_priv *priv = netdev_priv(dev), *cpriv, *tcpriv; 15769baa0b03SOr Gerlitz LIST_HEAD(head); 15779baa0b03SOr Gerlitz 15789baa0b03SOr Gerlitz ASSERT_RTNL(); 15791da177e4SLinus Torvalds 15801732b0efSRoland Dreier ipoib_delete_debug_files(dev); 15811da177e4SLinus Torvalds 15821da177e4SLinus Torvalds /* Delete any child interfaces first */ 15831da177e4SLinus Torvalds list_for_each_entry_safe(cpriv, tcpriv, &priv->child_intfs, list) { 1584b63b70d8SShlomo Pongratz /* Stop GC on child */ 1585b63b70d8SShlomo Pongratz set_bit(IPOIB_STOP_NEIGH_GC, &cpriv->flags); 1586b63b70d8SShlomo Pongratz cancel_delayed_work(&cpriv->neigh_reap_task); 15879baa0b03SOr Gerlitz unregister_netdevice_queue(cpriv->dev, &head); 15881da177e4SLinus Torvalds } 15899baa0b03SOr Gerlitz unregister_netdevice_many(&head); 15901da177e4SLinus Torvalds 1591be7aa663SDoug Ledford /* 1592be7aa663SDoug Ledford * Must be before ipoib_ib_dev_cleanup or we delete an in use 1593be7aa663SDoug Ledford * work queue 1594be7aa663SDoug Ledford */ 1595be7aa663SDoug Ledford ipoib_neigh_hash_uninit(dev); 1596be7aa663SDoug Ledford 15971da177e4SLinus Torvalds ipoib_ib_dev_cleanup(dev); 15981da177e4SLinus Torvalds 15991da177e4SLinus Torvalds kfree(priv->rx_ring); 160010313cbbSRoland Dreier vfree(priv->tx_ring); 160192a6b34bSHal Rosenstock 160292a6b34bSHal Rosenstock priv->rx_ring = NULL; 16031da177e4SLinus Torvalds priv->tx_ring = NULL; 16041da177e4SLinus Torvalds } 16051da177e4SLinus Torvalds 16063b04dddeSStephen Hemminger static const struct header_ops ipoib_header_ops = { 16073b04dddeSStephen Hemminger .create = ipoib_hard_header, 16083b04dddeSStephen Hemminger }; 16093b04dddeSStephen Hemminger 1610fe8114e8SStephen Hemminger static const struct net_device_ops ipoib_netdev_ops = { 16119baa0b03SOr Gerlitz .ndo_uninit = ipoib_uninit, 1612fe8114e8SStephen Hemminger .ndo_open = ipoib_open, 1613fe8114e8SStephen Hemminger .ndo_stop = ipoib_stop, 1614fe8114e8SStephen Hemminger .ndo_change_mtu = ipoib_change_mtu, 16153d96c74dSMichał Mirosław .ndo_fix_features = ipoib_fix_features, 1616fe8114e8SStephen Hemminger .ndo_start_xmit = ipoib_start_xmit, 1617fe8114e8SStephen Hemminger .ndo_tx_timeout = ipoib_timeout, 1618afc4b13dSJiri Pirko .ndo_set_rx_mode = ipoib_set_mcast_list, 16195aa7add8SNicolas Dichtel .ndo_get_iflink = ipoib_get_iflink, 1620fe8114e8SStephen Hemminger }; 1621fe8114e8SStephen Hemminger 16229baa0b03SOr Gerlitz void ipoib_setup(struct net_device *dev) 16231da177e4SLinus Torvalds { 16241da177e4SLinus Torvalds struct ipoib_dev_priv *priv = netdev_priv(dev); 16251da177e4SLinus Torvalds 1626fe8114e8SStephen Hemminger dev->netdev_ops = &ipoib_netdev_ops; 16273b04dddeSStephen Hemminger dev->header_ops = &ipoib_header_ops; 1628bea3348eSStephen Hemminger 162982c24c18SEli Cohen ipoib_set_ethtool_ops(dev); 163082c24c18SEli Cohen 16317f1a3867SMichal Schmidt netif_napi_add(dev, &priv->napi, ipoib_poll, NAPI_POLL_WEIGHT); 16321da177e4SLinus Torvalds 16331da177e4SLinus Torvalds dev->watchdog_timeo = HZ; 16341da177e4SLinus Torvalds 16351da177e4SLinus Torvalds dev->flags |= IFF_BROADCAST | IFF_MULTICAST; 16361da177e4SLinus Torvalds 1637936d7de3SRoland Dreier dev->hard_header_len = IPOIB_ENCAP_LEN; 16381da177e4SLinus Torvalds dev->addr_len = INFINIBAND_ALEN; 16391da177e4SLinus Torvalds dev->type = ARPHRD_INFINIBAND; 16400f485251SShirley Ma dev->tx_queue_len = ipoib_sendq_size * 2; 1641eb14032fSEli Cohen dev->features = (NETIF_F_VLAN_CHALLENGED | 1642eb14032fSEli Cohen NETIF_F_HIGHDMA); 164302875878SEric Dumazet netif_keep_dst(dev); 16441da177e4SLinus Torvalds 16451da177e4SLinus Torvalds memcpy(dev->broadcast, ipv4_bcast_addr, INFINIBAND_ALEN); 16461da177e4SLinus Torvalds 16471da177e4SLinus Torvalds priv->dev = dev; 16481da177e4SLinus Torvalds 16491da177e4SLinus Torvalds spin_lock_init(&priv->lock); 16501da177e4SLinus Torvalds 1651f47944ccSErez Shitrit init_rwsem(&priv->vlan_rwsem); 16521da177e4SLinus Torvalds 16531da177e4SLinus Torvalds INIT_LIST_HEAD(&priv->path_list); 16541da177e4SLinus Torvalds INIT_LIST_HEAD(&priv->child_intfs); 16551da177e4SLinus Torvalds INIT_LIST_HEAD(&priv->dead_ahs); 16561da177e4SLinus Torvalds INIT_LIST_HEAD(&priv->multicast_list); 16571da177e4SLinus Torvalds 1658c4028958SDavid Howells INIT_DELAYED_WORK(&priv->mcast_task, ipoib_mcast_join_task); 1659e8224e4bSYossi Etigin INIT_WORK(&priv->carrier_on_task, ipoib_mcast_carrier_on_task); 1660ee1e2c82SMoni Shoua INIT_WORK(&priv->flush_light, ipoib_ib_dev_flush_light); 1661ee1e2c82SMoni Shoua INIT_WORK(&priv->flush_normal, ipoib_ib_dev_flush_normal); 1662ee1e2c82SMoni Shoua INIT_WORK(&priv->flush_heavy, ipoib_ib_dev_flush_heavy); 1663c4028958SDavid Howells INIT_WORK(&priv->restart_task, ipoib_mcast_restart_task); 1664c4028958SDavid Howells INIT_DELAYED_WORK(&priv->ah_reap_task, ipoib_reap_ah); 1665b63b70d8SShlomo Pongratz INIT_DELAYED_WORK(&priv->neigh_reap_task, ipoib_reap_neigh); 16661da177e4SLinus Torvalds } 16671da177e4SLinus Torvalds 16681da177e4SLinus Torvalds struct ipoib_dev_priv *ipoib_intf_alloc(const char *name) 16691da177e4SLinus Torvalds { 16701da177e4SLinus Torvalds struct net_device *dev; 16711da177e4SLinus Torvalds 16721da177e4SLinus Torvalds dev = alloc_netdev((int)sizeof(struct ipoib_dev_priv), name, 1673c835a677STom Gundersen NET_NAME_UNKNOWN, ipoib_setup); 16741da177e4SLinus Torvalds if (!dev) 16751da177e4SLinus Torvalds return NULL; 16761da177e4SLinus Torvalds 16771da177e4SLinus Torvalds return netdev_priv(dev); 16781da177e4SLinus Torvalds } 16791da177e4SLinus Torvalds 168043cb76d9SGreg Kroah-Hartman static ssize_t show_pkey(struct device *dev, 168143cb76d9SGreg Kroah-Hartman struct device_attribute *attr, char *buf) 16821da177e4SLinus Torvalds { 168343cb76d9SGreg Kroah-Hartman struct ipoib_dev_priv *priv = netdev_priv(to_net_dev(dev)); 16841da177e4SLinus Torvalds 16851da177e4SLinus Torvalds return sprintf(buf, "0x%04x\n", priv->pkey); 16861da177e4SLinus Torvalds } 168743cb76d9SGreg Kroah-Hartman static DEVICE_ATTR(pkey, S_IRUGO, show_pkey, NULL); 16881da177e4SLinus Torvalds 1689335a64a5SOr Gerlitz static ssize_t show_umcast(struct device *dev, 1690335a64a5SOr Gerlitz struct device_attribute *attr, char *buf) 1691335a64a5SOr Gerlitz { 1692335a64a5SOr Gerlitz struct ipoib_dev_priv *priv = netdev_priv(to_net_dev(dev)); 1693335a64a5SOr Gerlitz 1694335a64a5SOr Gerlitz return sprintf(buf, "%d\n", test_bit(IPOIB_FLAG_UMCAST, &priv->flags)); 1695335a64a5SOr Gerlitz } 1696335a64a5SOr Gerlitz 1697862096a8SOr Gerlitz void ipoib_set_umcast(struct net_device *ndev, int umcast_val) 1698335a64a5SOr Gerlitz { 1699862096a8SOr Gerlitz struct ipoib_dev_priv *priv = netdev_priv(ndev); 1700335a64a5SOr Gerlitz 1701335a64a5SOr Gerlitz if (umcast_val > 0) { 1702335a64a5SOr Gerlitz set_bit(IPOIB_FLAG_UMCAST, &priv->flags); 1703335a64a5SOr Gerlitz ipoib_warn(priv, "ignoring multicast groups joined directly " 1704335a64a5SOr Gerlitz "by userspace\n"); 1705335a64a5SOr Gerlitz } else 1706335a64a5SOr Gerlitz clear_bit(IPOIB_FLAG_UMCAST, &priv->flags); 1707862096a8SOr Gerlitz } 1708862096a8SOr Gerlitz 1709862096a8SOr Gerlitz static ssize_t set_umcast(struct device *dev, 1710862096a8SOr Gerlitz struct device_attribute *attr, 1711862096a8SOr Gerlitz const char *buf, size_t count) 1712862096a8SOr Gerlitz { 1713862096a8SOr Gerlitz unsigned long umcast_val = simple_strtoul(buf, NULL, 0); 1714862096a8SOr Gerlitz 1715862096a8SOr Gerlitz ipoib_set_umcast(to_net_dev(dev), umcast_val); 1716335a64a5SOr Gerlitz 1717335a64a5SOr Gerlitz return count; 1718335a64a5SOr Gerlitz } 1719335a64a5SOr Gerlitz static DEVICE_ATTR(umcast, S_IWUSR | S_IRUGO, show_umcast, set_umcast); 1720335a64a5SOr Gerlitz 1721335a64a5SOr Gerlitz int ipoib_add_umcast_attr(struct net_device *dev) 1722335a64a5SOr Gerlitz { 1723335a64a5SOr Gerlitz return device_create_file(&dev->dev, &dev_attr_umcast); 1724335a64a5SOr Gerlitz } 1725335a64a5SOr Gerlitz 172643cb76d9SGreg Kroah-Hartman static ssize_t create_child(struct device *dev, 172743cb76d9SGreg Kroah-Hartman struct device_attribute *attr, 17281da177e4SLinus Torvalds const char *buf, size_t count) 17291da177e4SLinus Torvalds { 17301da177e4SLinus Torvalds int pkey; 17311da177e4SLinus Torvalds int ret; 17321da177e4SLinus Torvalds 17331da177e4SLinus Torvalds if (sscanf(buf, "%i", &pkey) != 1) 17341da177e4SLinus Torvalds return -EINVAL; 17351da177e4SLinus Torvalds 17363d790a4cSOr Gerlitz if (pkey <= 0 || pkey > 0xffff || pkey == 0x8000) 17371da177e4SLinus Torvalds return -EINVAL; 17381da177e4SLinus Torvalds 17394ce05937SRoland Dreier /* 17404ce05937SRoland Dreier * Set the full membership bit, so that we join the right 17414ce05937SRoland Dreier * broadcast group, etc. 17424ce05937SRoland Dreier */ 17434ce05937SRoland Dreier pkey |= 0x8000; 17444ce05937SRoland Dreier 174543cb76d9SGreg Kroah-Hartman ret = ipoib_vlan_add(to_net_dev(dev), pkey); 17461da177e4SLinus Torvalds 17471da177e4SLinus Torvalds return ret ? ret : count; 17481da177e4SLinus Torvalds } 17497a52b34bSOr Gerlitz static DEVICE_ATTR(create_child, S_IWUSR, NULL, create_child); 17501da177e4SLinus Torvalds 175143cb76d9SGreg Kroah-Hartman static ssize_t delete_child(struct device *dev, 175243cb76d9SGreg Kroah-Hartman struct device_attribute *attr, 17531da177e4SLinus Torvalds const char *buf, size_t count) 17541da177e4SLinus Torvalds { 17551da177e4SLinus Torvalds int pkey; 17561da177e4SLinus Torvalds int ret; 17571da177e4SLinus Torvalds 17581da177e4SLinus Torvalds if (sscanf(buf, "%i", &pkey) != 1) 17591da177e4SLinus Torvalds return -EINVAL; 17601da177e4SLinus Torvalds 17611da177e4SLinus Torvalds if (pkey < 0 || pkey > 0xffff) 17621da177e4SLinus Torvalds return -EINVAL; 17631da177e4SLinus Torvalds 176443cb76d9SGreg Kroah-Hartman ret = ipoib_vlan_delete(to_net_dev(dev), pkey); 17651da177e4SLinus Torvalds 17661da177e4SLinus Torvalds return ret ? ret : count; 17671da177e4SLinus Torvalds 17681da177e4SLinus Torvalds } 17697a52b34bSOr Gerlitz static DEVICE_ATTR(delete_child, S_IWUSR, NULL, delete_child); 17701da177e4SLinus Torvalds 17711da177e4SLinus Torvalds int ipoib_add_pkey_attr(struct net_device *dev) 17721da177e4SLinus Torvalds { 177343cb76d9SGreg Kroah-Hartman return device_create_file(&dev->dev, &dev_attr_pkey); 17741da177e4SLinus Torvalds } 17751da177e4SLinus Torvalds 177683bb63f6SOr Gerlitz int ipoib_set_dev_features(struct ipoib_dev_priv *priv, struct ib_device *hca) 177783bb63f6SOr Gerlitz { 177883bb63f6SOr Gerlitz struct ib_device_attr *device_attr; 177983bb63f6SOr Gerlitz int result = -ENOMEM; 178083bb63f6SOr Gerlitz 178183bb63f6SOr Gerlitz device_attr = kmalloc(sizeof *device_attr, GFP_KERNEL); 178283bb63f6SOr Gerlitz if (!device_attr) { 178383bb63f6SOr Gerlitz printk(KERN_WARNING "%s: allocation of %zu bytes failed\n", 178483bb63f6SOr Gerlitz hca->name, sizeof *device_attr); 178583bb63f6SOr Gerlitz return result; 178683bb63f6SOr Gerlitz } 178783bb63f6SOr Gerlitz 178883bb63f6SOr Gerlitz result = ib_query_device(hca, device_attr); 178983bb63f6SOr Gerlitz if (result) { 179083bb63f6SOr Gerlitz printk(KERN_WARNING "%s: ib_query_device failed (ret = %d)\n", 179183bb63f6SOr Gerlitz hca->name, result); 179283bb63f6SOr Gerlitz kfree(device_attr); 179383bb63f6SOr Gerlitz return result; 179483bb63f6SOr Gerlitz } 179583bb63f6SOr Gerlitz priv->hca_caps = device_attr->device_cap_flags; 179683bb63f6SOr Gerlitz 179783bb63f6SOr Gerlitz kfree(device_attr); 179883bb63f6SOr Gerlitz 179983bb63f6SOr Gerlitz if (priv->hca_caps & IB_DEVICE_UD_IP_CSUM) { 18003d96c74dSMichał Mirosław priv->dev->hw_features = NETIF_F_SG | 18013d96c74dSMichał Mirosław NETIF_F_IP_CSUM | NETIF_F_RXCSUM; 18023d96c74dSMichał Mirosław 18033d96c74dSMichał Mirosław if (priv->hca_caps & IB_DEVICE_UD_TSO) 18043d96c74dSMichał Mirosław priv->dev->hw_features |= NETIF_F_TSO; 18053d96c74dSMichał Mirosław 18063d96c74dSMichał Mirosław priv->dev->features |= priv->dev->hw_features; 180783bb63f6SOr Gerlitz } 180883bb63f6SOr Gerlitz 180983bb63f6SOr Gerlitz return 0; 181083bb63f6SOr Gerlitz } 181183bb63f6SOr Gerlitz 18121da177e4SLinus Torvalds static struct net_device *ipoib_add_port(const char *format, 18131da177e4SLinus Torvalds struct ib_device *hca, u8 port) 18141da177e4SLinus Torvalds { 18151da177e4SLinus Torvalds struct ipoib_dev_priv *priv; 1816bc7b3a36SShirley Ma struct ib_port_attr attr; 18171da177e4SLinus Torvalds int result = -ENOMEM; 18181da177e4SLinus Torvalds 18191da177e4SLinus Torvalds priv = ipoib_intf_alloc(format); 18201da177e4SLinus Torvalds if (!priv) 18211da177e4SLinus Torvalds goto alloc_mem_failed; 18221da177e4SLinus Torvalds 18231da177e4SLinus Torvalds SET_NETDEV_DEV(priv->dev, hca->dma_device); 1824c3aa9b18SEli Cohen priv->dev->dev_id = port - 1; 18251da177e4SLinus Torvalds 182658e9cc90SAmir Vadai result = ib_query_port(hca, port, &attr); 182758e9cc90SAmir Vadai if (!result) 1828bc7b3a36SShirley Ma priv->max_ib_mtu = ib_mtu_enum_to_int(attr.max_mtu); 1829bc7b3a36SShirley Ma else { 1830bc7b3a36SShirley Ma printk(KERN_WARNING "%s: ib_query_port %d failed\n", 1831bc7b3a36SShirley Ma hca->name, port); 1832bc7b3a36SShirley Ma goto device_init_failed; 1833bc7b3a36SShirley Ma } 1834bc7b3a36SShirley Ma 1835bc7b3a36SShirley Ma /* MTU will be reset when mcast join happens */ 1836bc7b3a36SShirley Ma priv->dev->mtu = IPOIB_UD_MTU(priv->max_ib_mtu); 1837bc7b3a36SShirley Ma priv->mcast_mtu = priv->admin_mtu = priv->dev->mtu; 1838bc7b3a36SShirley Ma 1839596b9b68SDavid Miller priv->dev->neigh_priv_len = sizeof(struct ipoib_neigh); 1840596b9b68SDavid Miller 18411da177e4SLinus Torvalds result = ib_query_pkey(hca, port, 0, &priv->pkey); 18421da177e4SLinus Torvalds if (result) { 18431da177e4SLinus Torvalds printk(KERN_WARNING "%s: ib_query_pkey port %d failed (ret = %d)\n", 18441da177e4SLinus Torvalds hca->name, port, result); 1845ca6de177SEli Cohen goto device_init_failed; 18461da177e4SLinus Torvalds } 18471da177e4SLinus Torvalds 184858e9cc90SAmir Vadai result = ipoib_set_dev_features(priv, hca); 184958e9cc90SAmir Vadai if (result) 18506046136cSEli Cohen goto device_init_failed; 1851af40da89SVladimir Sokolovsky 18524ce05937SRoland Dreier /* 18534ce05937SRoland Dreier * Set the full membership bit, so that we join the right 18544ce05937SRoland Dreier * broadcast group, etc. 18554ce05937SRoland Dreier */ 18564ce05937SRoland Dreier priv->pkey |= 0x8000; 18574ce05937SRoland Dreier 18581da177e4SLinus Torvalds priv->dev->broadcast[8] = priv->pkey >> 8; 18591da177e4SLinus Torvalds priv->dev->broadcast[9] = priv->pkey & 0xff; 18601da177e4SLinus Torvalds 18611da177e4SLinus Torvalds result = ib_query_gid(hca, port, 0, &priv->local_gid); 18621da177e4SLinus Torvalds if (result) { 18631da177e4SLinus Torvalds printk(KERN_WARNING "%s: ib_query_gid port %d failed (ret = %d)\n", 18641da177e4SLinus Torvalds hca->name, port, result); 1865ca6de177SEli Cohen goto device_init_failed; 18661da177e4SLinus Torvalds } else 18671da177e4SLinus Torvalds memcpy(priv->dev->dev_addr + 4, priv->local_gid.raw, sizeof (union ib_gid)); 18681da177e4SLinus Torvalds 18691da177e4SLinus Torvalds result = ipoib_dev_init(priv->dev, hca, port); 18701da177e4SLinus Torvalds if (result < 0) { 18711da177e4SLinus Torvalds printk(KERN_WARNING "%s: failed to initialize port %d (ret = %d)\n", 18721da177e4SLinus Torvalds hca->name, port, result); 18731da177e4SLinus Torvalds goto device_init_failed; 18741da177e4SLinus Torvalds } 18751da177e4SLinus Torvalds 18761da177e4SLinus Torvalds INIT_IB_EVENT_HANDLER(&priv->event_handler, 18771da177e4SLinus Torvalds priv->ca, ipoib_event); 18781da177e4SLinus Torvalds result = ib_register_event_handler(&priv->event_handler); 18791da177e4SLinus Torvalds if (result < 0) { 18801da177e4SLinus Torvalds printk(KERN_WARNING "%s: ib_register_event_handler failed for " 18811da177e4SLinus Torvalds "port %d (ret = %d)\n", 18821da177e4SLinus Torvalds hca->name, port, result); 18831da177e4SLinus Torvalds goto event_failed; 18841da177e4SLinus Torvalds } 18851da177e4SLinus Torvalds 18861da177e4SLinus Torvalds result = register_netdev(priv->dev); 18871da177e4SLinus Torvalds if (result) { 18881da177e4SLinus Torvalds printk(KERN_WARNING "%s: couldn't register ipoib port %d; error %d\n", 18891da177e4SLinus Torvalds hca->name, port, result); 18901da177e4SLinus Torvalds goto register_failed; 18911da177e4SLinus Torvalds } 18921da177e4SLinus Torvalds 18931732b0efSRoland Dreier ipoib_create_debug_files(priv->dev); 18941da177e4SLinus Torvalds 1895839fcabaSMichael S. Tsirkin if (ipoib_cm_add_mode_attr(priv->dev)) 1896839fcabaSMichael S. Tsirkin goto sysfs_failed; 18971da177e4SLinus Torvalds if (ipoib_add_pkey_attr(priv->dev)) 18981da177e4SLinus Torvalds goto sysfs_failed; 1899335a64a5SOr Gerlitz if (ipoib_add_umcast_attr(priv->dev)) 1900335a64a5SOr Gerlitz goto sysfs_failed; 190143cb76d9SGreg Kroah-Hartman if (device_create_file(&priv->dev->dev, &dev_attr_create_child)) 19021da177e4SLinus Torvalds goto sysfs_failed; 190343cb76d9SGreg Kroah-Hartman if (device_create_file(&priv->dev->dev, &dev_attr_delete_child)) 19041da177e4SLinus Torvalds goto sysfs_failed; 19051da177e4SLinus Torvalds 19061da177e4SLinus Torvalds return priv->dev; 19071da177e4SLinus Torvalds 19081da177e4SLinus Torvalds sysfs_failed: 19091732b0efSRoland Dreier ipoib_delete_debug_files(priv->dev); 19101da177e4SLinus Torvalds unregister_netdev(priv->dev); 19111da177e4SLinus Torvalds 19121da177e4SLinus Torvalds register_failed: 19131da177e4SLinus Torvalds ib_unregister_event_handler(&priv->event_handler); 19140b39578bSDoug Ledford flush_workqueue(ipoib_workqueue); 1915b63b70d8SShlomo Pongratz /* Stop GC if started before flush */ 1916b63b70d8SShlomo Pongratz set_bit(IPOIB_STOP_NEIGH_GC, &priv->flags); 1917b63b70d8SShlomo Pongratz cancel_delayed_work(&priv->neigh_reap_task); 19180b39578bSDoug Ledford flush_workqueue(priv->wq); 19191da177e4SLinus Torvalds 19201da177e4SLinus Torvalds event_failed: 19211da177e4SLinus Torvalds ipoib_dev_cleanup(priv->dev); 19221da177e4SLinus Torvalds 19231da177e4SLinus Torvalds device_init_failed: 19241da177e4SLinus Torvalds free_netdev(priv->dev); 19251da177e4SLinus Torvalds 19261da177e4SLinus Torvalds alloc_mem_failed: 19271da177e4SLinus Torvalds return ERR_PTR(result); 19281da177e4SLinus Torvalds } 19291da177e4SLinus Torvalds 19301da177e4SLinus Torvalds static void ipoib_add_one(struct ib_device *device) 19311da177e4SLinus Torvalds { 19321da177e4SLinus Torvalds struct list_head *dev_list; 19331da177e4SLinus Torvalds struct net_device *dev; 19341da177e4SLinus Torvalds struct ipoib_dev_priv *priv; 19354139032bSHal Rosenstock int p; 19368e37ab68SMichael Wang int count = 0; 193707ebafbaSTom Tucker 19381da177e4SLinus Torvalds dev_list = kmalloc(sizeof *dev_list, GFP_KERNEL); 19391da177e4SLinus Torvalds if (!dev_list) 19401da177e4SLinus Torvalds return; 19411da177e4SLinus Torvalds 19421da177e4SLinus Torvalds INIT_LIST_HEAD(dev_list); 19431da177e4SLinus Torvalds 19444139032bSHal Rosenstock for (p = rdma_start_port(device); p <= rdma_end_port(device); ++p) { 19458e37ab68SMichael Wang if (!rdma_protocol_ib(device, p)) 19467b4c8769SEli Cohen continue; 19471da177e4SLinus Torvalds dev = ipoib_add_port("ib%d", device, p); 19481da177e4SLinus Torvalds if (!IS_ERR(dev)) { 19491da177e4SLinus Torvalds priv = netdev_priv(dev); 19501da177e4SLinus Torvalds list_add_tail(&priv->list, dev_list); 19518e37ab68SMichael Wang count++; 19521da177e4SLinus Torvalds } 19531da177e4SLinus Torvalds } 19541da177e4SLinus Torvalds 19558e37ab68SMichael Wang if (!count) { 19568e37ab68SMichael Wang kfree(dev_list); 19578e37ab68SMichael Wang return; 19588e37ab68SMichael Wang } 19598e37ab68SMichael Wang 19601da177e4SLinus Torvalds ib_set_client_data(device, &ipoib_client, dev_list); 19611da177e4SLinus Torvalds } 19621da177e4SLinus Torvalds 19637c1eb45aSHaggai Eran static void ipoib_remove_one(struct ib_device *device, void *client_data) 19641da177e4SLinus Torvalds { 19651da177e4SLinus Torvalds struct ipoib_dev_priv *priv, *tmp; 19667c1eb45aSHaggai Eran struct list_head *dev_list = client_data; 19671da177e4SLinus Torvalds 19685a2815f0SItai Garbi if (!dev_list) 19695a2815f0SItai Garbi return; 19701da177e4SLinus Torvalds 19711da177e4SLinus Torvalds list_for_each_entry_safe(priv, tmp, dev_list, list) { 19721da177e4SLinus Torvalds ib_unregister_event_handler(&priv->event_handler); 19730b39578bSDoug Ledford flush_workqueue(ipoib_workqueue); 1974a77a57a1SRoland Dreier 1975a77a57a1SRoland Dreier rtnl_lock(); 1976a77a57a1SRoland Dreier dev_change_flags(priv->dev, priv->dev->flags & ~IFF_UP); 1977a77a57a1SRoland Dreier rtnl_unlock(); 1978a77a57a1SRoland Dreier 1979b63b70d8SShlomo Pongratz /* Stop GC */ 1980b63b70d8SShlomo Pongratz set_bit(IPOIB_STOP_NEIGH_GC, &priv->flags); 1981b63b70d8SShlomo Pongratz cancel_delayed_work(&priv->neigh_reap_task); 19820b39578bSDoug Ledford flush_workqueue(priv->wq); 19831da177e4SLinus Torvalds 19841da177e4SLinus Torvalds unregister_netdev(priv->dev); 19851da177e4SLinus Torvalds free_netdev(priv->dev); 19861da177e4SLinus Torvalds } 198706c56e44SMichael S. Tsirkin 198806c56e44SMichael S. Tsirkin kfree(dev_list); 19891da177e4SLinus Torvalds } 19901da177e4SLinus Torvalds 19911da177e4SLinus Torvalds static int __init ipoib_init_module(void) 19921da177e4SLinus Torvalds { 19931da177e4SLinus Torvalds int ret; 19941da177e4SLinus Torvalds 19950f485251SShirley Ma ipoib_recvq_size = roundup_pow_of_two(ipoib_recvq_size); 19960f485251SShirley Ma ipoib_recvq_size = min(ipoib_recvq_size, IPOIB_MAX_QUEUE_SIZE); 19970f485251SShirley Ma ipoib_recvq_size = max(ipoib_recvq_size, IPOIB_MIN_QUEUE_SIZE); 19980f485251SShirley Ma 19990f485251SShirley Ma ipoib_sendq_size = roundup_pow_of_two(ipoib_sendq_size); 20000f485251SShirley Ma ipoib_sendq_size = min(ipoib_sendq_size, IPOIB_MAX_QUEUE_SIZE); 2001732eacc0SHagen Paul Pfeifer ipoib_sendq_size = max3(ipoib_sendq_size, 2 * MAX_SEND_CQE, IPOIB_MIN_QUEUE_SIZE); 200268e995a2SPradeep Satyanarayana #ifdef CONFIG_INFINIBAND_IPOIB_CM 200368e995a2SPradeep Satyanarayana ipoib_max_conn_qp = min(ipoib_max_conn_qp, IPOIB_CM_MAX_CONN_QP); 200468e995a2SPradeep Satyanarayana #endif 20050f485251SShirley Ma 2006f89271daSEli Cohen /* 2007f89271daSEli Cohen * When copying small received packets, we only copy from the 2008f89271daSEli Cohen * linear data part of the SKB, so we rely on this condition. 2009f89271daSEli Cohen */ 2010f89271daSEli Cohen BUILD_BUG_ON(IPOIB_CM_COPYBREAK > IPOIB_CM_HEAD_SIZE); 2011f89271daSEli Cohen 20121da177e4SLinus Torvalds ret = ipoib_register_debugfs(); 20131da177e4SLinus Torvalds if (ret) 20141da177e4SLinus Torvalds return ret; 20151da177e4SLinus Torvalds 20161da177e4SLinus Torvalds /* 20170b39578bSDoug Ledford * We create a global workqueue here that is used for all flush 20180b39578bSDoug Ledford * operations. However, if you attempt to flush a workqueue 20190b39578bSDoug Ledford * from a task on that same workqueue, it deadlocks the system. 20200b39578bSDoug Ledford * We want to be able to flush the tasks associated with a 20210b39578bSDoug Ledford * specific net device, so we also create a workqueue for each 20220b39578bSDoug Ledford * netdevice. We queue up the tasks for that device only on 20230b39578bSDoug Ledford * its private workqueue, and we only queue up flush events 20240b39578bSDoug Ledford * on our global flush workqueue. This avoids the deadlocks. 20251da177e4SLinus Torvalds */ 20260b39578bSDoug Ledford ipoib_workqueue = create_singlethread_workqueue("ipoib_flush"); 20271da177e4SLinus Torvalds if (!ipoib_workqueue) { 20281da177e4SLinus Torvalds ret = -ENOMEM; 20291da177e4SLinus Torvalds goto err_fs; 20301da177e4SLinus Torvalds } 20311da177e4SLinus Torvalds 2032c1a0b23bSMichael S. Tsirkin ib_sa_register_client(&ipoib_sa_client); 2033c1a0b23bSMichael S. Tsirkin 20341da177e4SLinus Torvalds ret = ib_register_client(&ipoib_client); 20351da177e4SLinus Torvalds if (ret) 2036c1a0b23bSMichael S. Tsirkin goto err_sa; 20371da177e4SLinus Torvalds 20389baa0b03SOr Gerlitz ret = ipoib_netlink_init(); 20399baa0b03SOr Gerlitz if (ret) 20409baa0b03SOr Gerlitz goto err_client; 20419baa0b03SOr Gerlitz 20421da177e4SLinus Torvalds return 0; 20431da177e4SLinus Torvalds 20449baa0b03SOr Gerlitz err_client: 20459baa0b03SOr Gerlitz ib_unregister_client(&ipoib_client); 20469baa0b03SOr Gerlitz 2047c1a0b23bSMichael S. Tsirkin err_sa: 2048c1a0b23bSMichael S. Tsirkin ib_sa_unregister_client(&ipoib_sa_client); 20491da177e4SLinus Torvalds destroy_workqueue(ipoib_workqueue); 20501da177e4SLinus Torvalds 20519adec1a8SRoland Dreier err_fs: 20529adec1a8SRoland Dreier ipoib_unregister_debugfs(); 20539adec1a8SRoland Dreier 20541da177e4SLinus Torvalds return ret; 20551da177e4SLinus Torvalds } 20561da177e4SLinus Torvalds 20571da177e4SLinus Torvalds static void __exit ipoib_cleanup_module(void) 20581da177e4SLinus Torvalds { 20599baa0b03SOr Gerlitz ipoib_netlink_fini(); 20601da177e4SLinus Torvalds ib_unregister_client(&ipoib_client); 2061c1a0b23bSMichael S. Tsirkin ib_sa_unregister_client(&ipoib_sa_client); 20629adec1a8SRoland Dreier ipoib_unregister_debugfs(); 20631da177e4SLinus Torvalds destroy_workqueue(ipoib_workqueue); 20641da177e4SLinus Torvalds } 20651da177e4SLinus Torvalds 20661da177e4SLinus Torvalds module_init(ipoib_init_module); 20671da177e4SLinus Torvalds module_exit(ipoib_cleanup_module); 2068