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> 5114c85021SArnaldo Carvalho de Melo 524b48680bSYan Burman #define DRV_VERSION "1.0.0" 534b48680bSYan Burman 544b48680bSYan Burman const char ipoib_driver_version[] = DRV_VERSION; 554b48680bSYan Burman 561da177e4SLinus Torvalds MODULE_AUTHOR("Roland Dreier"); 571da177e4SLinus Torvalds MODULE_DESCRIPTION("IP-over-InfiniBand net driver"); 581da177e4SLinus Torvalds MODULE_LICENSE("Dual BSD/GPL"); 594b48680bSYan Burman MODULE_VERSION(DRV_VERSION); 601da177e4SLinus Torvalds 610f485251SShirley Ma int ipoib_sendq_size __read_mostly = IPOIB_TX_RING_SIZE; 620f485251SShirley Ma int ipoib_recvq_size __read_mostly = IPOIB_RX_RING_SIZE; 630f485251SShirley Ma 640f485251SShirley Ma module_param_named(send_queue_size, ipoib_sendq_size, int, 0444); 650f485251SShirley Ma MODULE_PARM_DESC(send_queue_size, "Number of descriptors in send queue"); 660f485251SShirley Ma module_param_named(recv_queue_size, ipoib_recvq_size, int, 0444); 670f485251SShirley Ma MODULE_PARM_DESC(recv_queue_size, "Number of descriptors in receive queue"); 680f485251SShirley Ma 691da177e4SLinus Torvalds #ifdef CONFIG_INFINIBAND_IPOIB_DEBUG 701da177e4SLinus Torvalds int ipoib_debug_level; 711da177e4SLinus Torvalds 721da177e4SLinus Torvalds module_param_named(debug_level, ipoib_debug_level, int, 0644); 731da177e4SLinus Torvalds MODULE_PARM_DESC(debug_level, "Enable debug tracing if > 0"); 741da177e4SLinus Torvalds #endif 751da177e4SLinus Torvalds 761732b0efSRoland Dreier struct ipoib_path_iter { 771732b0efSRoland Dreier struct net_device *dev; 781732b0efSRoland Dreier struct ipoib_path path; 791732b0efSRoland Dreier }; 801732b0efSRoland Dreier 811da177e4SLinus Torvalds static const u8 ipv4_bcast_addr[] = { 821da177e4SLinus Torvalds 0x00, 0xff, 0xff, 0xff, 831da177e4SLinus Torvalds 0xff, 0x12, 0x40, 0x1b, 0x00, 0x00, 0x00, 0x00, 841da177e4SLinus Torvalds 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff 851da177e4SLinus Torvalds }; 861da177e4SLinus Torvalds 871da177e4SLinus Torvalds struct workqueue_struct *ipoib_workqueue; 881da177e4SLinus Torvalds 89c1a0b23bSMichael S. Tsirkin struct ib_sa_client ipoib_sa_client; 90c1a0b23bSMichael S. Tsirkin 911da177e4SLinus Torvalds static void ipoib_add_one(struct ib_device *device); 921da177e4SLinus Torvalds static void ipoib_remove_one(struct ib_device *device); 93b63b70d8SShlomo Pongratz static void ipoib_neigh_reclaim(struct rcu_head *rp); 941da177e4SLinus Torvalds 951da177e4SLinus Torvalds static struct ib_client ipoib_client = { 961da177e4SLinus Torvalds .name = "ipoib", 971da177e4SLinus Torvalds .add = ipoib_add_one, 981da177e4SLinus Torvalds .remove = ipoib_remove_one 991da177e4SLinus Torvalds }; 1001da177e4SLinus Torvalds 1011da177e4SLinus Torvalds int ipoib_open(struct net_device *dev) 1021da177e4SLinus Torvalds { 1031da177e4SLinus Torvalds struct ipoib_dev_priv *priv = netdev_priv(dev); 1041da177e4SLinus Torvalds 1051da177e4SLinus Torvalds ipoib_dbg(priv, "bringing up interface\n"); 1061da177e4SLinus Torvalds 107437708c4SMichal Schmidt netif_carrier_off(dev); 108437708c4SMichal Schmidt 109e028cc55SYossi Etigin set_bit(IPOIB_FLAG_ADMIN_UP, &priv->flags); 1101da177e4SLinus Torvalds 111efc82eeeSDoug Ledford if (ipoib_ib_dev_open(dev)) { 112db84f880SErez Shitrit if (!test_bit(IPOIB_PKEY_ASSIGNED, &priv->flags)) 1131da177e4SLinus Torvalds return 0; 114b8a1b1ceSRoland Dreier goto err_disable; 115dd57c930SAlex Estrin } 116fe25c561SYossi Etigin 117b8a1b1ceSRoland Dreier if (ipoib_ib_dev_up(dev)) 118b8a1b1ceSRoland Dreier goto err_stop; 1191da177e4SLinus Torvalds 1201da177e4SLinus Torvalds if (!test_bit(IPOIB_FLAG_SUBINTERFACE, &priv->flags)) { 1211da177e4SLinus Torvalds struct ipoib_dev_priv *cpriv; 1221da177e4SLinus Torvalds 1231da177e4SLinus Torvalds /* Bring up any child interfaces too */ 124f47944ccSErez Shitrit down_read(&priv->vlan_rwsem); 1251da177e4SLinus Torvalds list_for_each_entry(cpriv, &priv->child_intfs, list) { 1261da177e4SLinus Torvalds int flags; 1271da177e4SLinus Torvalds 1281da177e4SLinus Torvalds flags = cpriv->dev->flags; 1291da177e4SLinus Torvalds if (flags & IFF_UP) 1301da177e4SLinus Torvalds continue; 1311da177e4SLinus Torvalds 1321da177e4SLinus Torvalds dev_change_flags(cpriv->dev, flags | IFF_UP); 1331da177e4SLinus Torvalds } 134f47944ccSErez Shitrit up_read(&priv->vlan_rwsem); 1351da177e4SLinus Torvalds } 1361da177e4SLinus Torvalds 1371da177e4SLinus Torvalds netif_start_queue(dev); 1381da177e4SLinus Torvalds 1391da177e4SLinus Torvalds return 0; 140b8a1b1ceSRoland Dreier 141b8a1b1ceSRoland Dreier err_stop: 142efc82eeeSDoug Ledford ipoib_ib_dev_stop(dev); 143b8a1b1ceSRoland Dreier 144b8a1b1ceSRoland Dreier err_disable: 145b8a1b1ceSRoland Dreier clear_bit(IPOIB_FLAG_ADMIN_UP, &priv->flags); 146b8a1b1ceSRoland Dreier 147b8a1b1ceSRoland Dreier return -EINVAL; 1481da177e4SLinus Torvalds } 1491da177e4SLinus Torvalds 1501da177e4SLinus Torvalds static int ipoib_stop(struct net_device *dev) 1511da177e4SLinus Torvalds { 1521da177e4SLinus Torvalds struct ipoib_dev_priv *priv = netdev_priv(dev); 1531da177e4SLinus Torvalds 1541da177e4SLinus Torvalds ipoib_dbg(priv, "stopping interface\n"); 1551da177e4SLinus Torvalds 1561da177e4SLinus Torvalds clear_bit(IPOIB_FLAG_ADMIN_UP, &priv->flags); 1571da177e4SLinus Torvalds 1581da177e4SLinus Torvalds netif_stop_queue(dev); 1591da177e4SLinus Torvalds 160efc82eeeSDoug Ledford ipoib_ib_dev_down(dev); 161efc82eeeSDoug Ledford ipoib_ib_dev_stop(dev); 1621da177e4SLinus Torvalds 1631da177e4SLinus Torvalds if (!test_bit(IPOIB_FLAG_SUBINTERFACE, &priv->flags)) { 1641da177e4SLinus Torvalds struct ipoib_dev_priv *cpriv; 1651da177e4SLinus Torvalds 1661da177e4SLinus Torvalds /* Bring down any child interfaces too */ 167f47944ccSErez Shitrit down_read(&priv->vlan_rwsem); 1681da177e4SLinus Torvalds list_for_each_entry(cpriv, &priv->child_intfs, list) { 1691da177e4SLinus Torvalds int flags; 1701da177e4SLinus Torvalds 1711da177e4SLinus Torvalds flags = cpriv->dev->flags; 1721da177e4SLinus Torvalds if (!(flags & IFF_UP)) 1731da177e4SLinus Torvalds continue; 1741da177e4SLinus Torvalds 1751da177e4SLinus Torvalds dev_change_flags(cpriv->dev, flags & ~IFF_UP); 1761da177e4SLinus Torvalds } 177f47944ccSErez Shitrit up_read(&priv->vlan_rwsem); 1781da177e4SLinus Torvalds } 1791da177e4SLinus Torvalds 1801da177e4SLinus Torvalds return 0; 1811da177e4SLinus Torvalds } 1821da177e4SLinus Torvalds 1839baa0b03SOr Gerlitz static void ipoib_uninit(struct net_device *dev) 1849baa0b03SOr Gerlitz { 1859baa0b03SOr Gerlitz ipoib_dev_cleanup(dev); 1869baa0b03SOr Gerlitz } 1879baa0b03SOr Gerlitz 1889ca36f7dSDavid S. Miller static netdev_features_t ipoib_fix_features(struct net_device *dev, netdev_features_t features) 1893d96c74dSMichał Mirosław { 1903d96c74dSMichał Mirosław struct ipoib_dev_priv *priv = netdev_priv(dev); 1913d96c74dSMichał Mirosław 1923d96c74dSMichał Mirosław if (test_bit(IPOIB_FLAG_ADMIN_CM, &priv->flags)) 1933d96c74dSMichał Mirosław features &= ~(NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO); 1943d96c74dSMichał Mirosław 1953d96c74dSMichał Mirosław return features; 1963d96c74dSMichał Mirosław } 1973d96c74dSMichał Mirosław 1981da177e4SLinus Torvalds static int ipoib_change_mtu(struct net_device *dev, int new_mtu) 1991da177e4SLinus Torvalds { 2001da177e4SLinus Torvalds struct ipoib_dev_priv *priv = netdev_priv(dev); 2011da177e4SLinus Torvalds 202839fcabaSMichael S. Tsirkin /* dev->mtu > 2K ==> connected mode */ 203586a6934SPradeep Satyanarayana if (ipoib_cm_admin_enabled(dev)) { 204586a6934SPradeep Satyanarayana if (new_mtu > ipoib_cm_max_mtu(dev)) 205586a6934SPradeep Satyanarayana return -EINVAL; 206586a6934SPradeep Satyanarayana 207839fcabaSMichael S. Tsirkin if (new_mtu > priv->mcast_mtu) 208839fcabaSMichael S. Tsirkin ipoib_warn(priv, "mtu > %d will cause multicast packet drops.\n", 209839fcabaSMichael S. Tsirkin priv->mcast_mtu); 210586a6934SPradeep Satyanarayana 211839fcabaSMichael S. Tsirkin dev->mtu = new_mtu; 212839fcabaSMichael S. Tsirkin return 0; 213839fcabaSMichael S. Tsirkin } 214839fcabaSMichael S. Tsirkin 215bc7b3a36SShirley Ma if (new_mtu > IPOIB_UD_MTU(priv->max_ib_mtu)) 2161da177e4SLinus Torvalds return -EINVAL; 2171da177e4SLinus Torvalds 2181da177e4SLinus Torvalds priv->admin_mtu = new_mtu; 2191da177e4SLinus Torvalds 2201da177e4SLinus Torvalds dev->mtu = min(priv->mcast_mtu, priv->admin_mtu); 2211da177e4SLinus Torvalds 2221da177e4SLinus Torvalds return 0; 2231da177e4SLinus Torvalds } 2241da177e4SLinus Torvalds 22571d9c5f9SRoland Dreier int ipoib_set_mode(struct net_device *dev, const char *buf) 22671d9c5f9SRoland Dreier { 22771d9c5f9SRoland Dreier struct ipoib_dev_priv *priv = netdev_priv(dev); 22871d9c5f9SRoland Dreier 22971d9c5f9SRoland Dreier /* flush paths if we switch modes so that connections are restarted */ 23071d9c5f9SRoland Dreier if (IPOIB_CM_SUPPORTED(dev->dev_addr) && !strcmp(buf, "connected\n")) { 23171d9c5f9SRoland Dreier set_bit(IPOIB_FLAG_ADMIN_CM, &priv->flags); 23271d9c5f9SRoland Dreier ipoib_warn(priv, "enabling connected mode " 23371d9c5f9SRoland Dreier "will cause multicast packet drops\n"); 23471d9c5f9SRoland Dreier netdev_update_features(dev); 23571d9c5f9SRoland Dreier rtnl_unlock(); 23671d9c5f9SRoland Dreier priv->tx_wr.send_flags &= ~IB_SEND_IP_CSUM; 23771d9c5f9SRoland Dreier 23871d9c5f9SRoland Dreier ipoib_flush_paths(dev); 23971d9c5f9SRoland Dreier rtnl_lock(); 24071d9c5f9SRoland Dreier return 0; 24171d9c5f9SRoland Dreier } 24271d9c5f9SRoland Dreier 24371d9c5f9SRoland Dreier if (!strcmp(buf, "datagram\n")) { 24471d9c5f9SRoland Dreier clear_bit(IPOIB_FLAG_ADMIN_CM, &priv->flags); 24571d9c5f9SRoland Dreier netdev_update_features(dev); 24671d9c5f9SRoland Dreier dev_set_mtu(dev, min(priv->mcast_mtu, dev->mtu)); 24771d9c5f9SRoland Dreier rtnl_unlock(); 24871d9c5f9SRoland Dreier ipoib_flush_paths(dev); 24971d9c5f9SRoland Dreier rtnl_lock(); 25071d9c5f9SRoland Dreier return 0; 25171d9c5f9SRoland Dreier } 25271d9c5f9SRoland Dreier 25371d9c5f9SRoland Dreier return -EINVAL; 25471d9c5f9SRoland Dreier } 25571d9c5f9SRoland Dreier 25637c22a77SJack Morgenstein static struct ipoib_path *__path_find(struct net_device *dev, void *gid) 2571da177e4SLinus Torvalds { 2581da177e4SLinus Torvalds struct ipoib_dev_priv *priv = netdev_priv(dev); 2591da177e4SLinus Torvalds struct rb_node *n = priv->path_tree.rb_node; 2601da177e4SLinus Torvalds struct ipoib_path *path; 2611da177e4SLinus Torvalds int ret; 2621da177e4SLinus Torvalds 2631da177e4SLinus Torvalds while (n) { 2641da177e4SLinus Torvalds path = rb_entry(n, struct ipoib_path, rb_node); 2651da177e4SLinus Torvalds 26637c22a77SJack Morgenstein ret = memcmp(gid, path->pathrec.dgid.raw, 2671da177e4SLinus Torvalds sizeof (union ib_gid)); 2681da177e4SLinus Torvalds 2691da177e4SLinus Torvalds if (ret < 0) 2701da177e4SLinus Torvalds n = n->rb_left; 2711da177e4SLinus Torvalds else if (ret > 0) 2721da177e4SLinus Torvalds n = n->rb_right; 2731da177e4SLinus Torvalds else 2741da177e4SLinus Torvalds return path; 2751da177e4SLinus Torvalds } 2761da177e4SLinus Torvalds 2771da177e4SLinus Torvalds return NULL; 2781da177e4SLinus Torvalds } 2791da177e4SLinus Torvalds 2801da177e4SLinus Torvalds static int __path_add(struct net_device *dev, struct ipoib_path *path) 2811da177e4SLinus Torvalds { 2821da177e4SLinus Torvalds struct ipoib_dev_priv *priv = netdev_priv(dev); 2831da177e4SLinus Torvalds struct rb_node **n = &priv->path_tree.rb_node; 2841da177e4SLinus Torvalds struct rb_node *pn = NULL; 2851da177e4SLinus Torvalds struct ipoib_path *tpath; 2861da177e4SLinus Torvalds int ret; 2871da177e4SLinus Torvalds 2881da177e4SLinus Torvalds while (*n) { 2891da177e4SLinus Torvalds pn = *n; 2901da177e4SLinus Torvalds tpath = rb_entry(pn, struct ipoib_path, rb_node); 2911da177e4SLinus Torvalds 2921da177e4SLinus Torvalds ret = memcmp(path->pathrec.dgid.raw, tpath->pathrec.dgid.raw, 2931da177e4SLinus Torvalds sizeof (union ib_gid)); 2941da177e4SLinus Torvalds if (ret < 0) 2951da177e4SLinus Torvalds n = &pn->rb_left; 2961da177e4SLinus Torvalds else if (ret > 0) 2971da177e4SLinus Torvalds n = &pn->rb_right; 2981da177e4SLinus Torvalds else 2991da177e4SLinus Torvalds return -EEXIST; 3001da177e4SLinus Torvalds } 3011da177e4SLinus Torvalds 3021da177e4SLinus Torvalds rb_link_node(&path->rb_node, pn, n); 3031da177e4SLinus Torvalds rb_insert_color(&path->rb_node, &priv->path_tree); 3041da177e4SLinus Torvalds 3051da177e4SLinus Torvalds list_add_tail(&path->list, &priv->path_list); 3061da177e4SLinus Torvalds 3071da177e4SLinus Torvalds return 0; 3081da177e4SLinus Torvalds } 3091da177e4SLinus Torvalds 3101da177e4SLinus Torvalds static void path_free(struct net_device *dev, struct ipoib_path *path) 3111da177e4SLinus Torvalds { 3121da177e4SLinus Torvalds struct sk_buff *skb; 3131da177e4SLinus Torvalds 3141da177e4SLinus Torvalds while ((skb = __skb_dequeue(&path->queue))) 3151da177e4SLinus Torvalds dev_kfree_skb_irq(skb); 3161da177e4SLinus Torvalds 317b63b70d8SShlomo Pongratz ipoib_dbg(netdev_priv(dev), "path_free\n"); 3181da177e4SLinus Torvalds 319b63b70d8SShlomo Pongratz /* remove all neigh connected to this path */ 320b63b70d8SShlomo Pongratz ipoib_del_neighs_by_gid(dev, path->pathrec.dgid.raw); 3211da177e4SLinus Torvalds 3221da177e4SLinus Torvalds if (path->ah) 3231da177e4SLinus Torvalds ipoib_put_ah(path->ah); 3241da177e4SLinus Torvalds 3251da177e4SLinus Torvalds kfree(path); 3261da177e4SLinus Torvalds } 3271da177e4SLinus Torvalds 3281732b0efSRoland Dreier #ifdef CONFIG_INFINIBAND_IPOIB_DEBUG 3291732b0efSRoland Dreier 3301732b0efSRoland Dreier struct ipoib_path_iter *ipoib_path_iter_init(struct net_device *dev) 3311732b0efSRoland Dreier { 3321732b0efSRoland Dreier struct ipoib_path_iter *iter; 3331732b0efSRoland Dreier 3341732b0efSRoland Dreier iter = kmalloc(sizeof *iter, GFP_KERNEL); 3351732b0efSRoland Dreier if (!iter) 3361732b0efSRoland Dreier return NULL; 3371732b0efSRoland Dreier 3381732b0efSRoland Dreier iter->dev = dev; 3391732b0efSRoland Dreier memset(iter->path.pathrec.dgid.raw, 0, 16); 3401732b0efSRoland Dreier 3411732b0efSRoland Dreier if (ipoib_path_iter_next(iter)) { 3421732b0efSRoland Dreier kfree(iter); 3431732b0efSRoland Dreier return NULL; 3441732b0efSRoland Dreier } 3451732b0efSRoland Dreier 3461732b0efSRoland Dreier return iter; 3471732b0efSRoland Dreier } 3481732b0efSRoland Dreier 3491732b0efSRoland Dreier int ipoib_path_iter_next(struct ipoib_path_iter *iter) 3501732b0efSRoland Dreier { 3511732b0efSRoland Dreier struct ipoib_dev_priv *priv = netdev_priv(iter->dev); 3521732b0efSRoland Dreier struct rb_node *n; 3531732b0efSRoland Dreier struct ipoib_path *path; 3541732b0efSRoland Dreier int ret = 1; 3551732b0efSRoland Dreier 3561732b0efSRoland Dreier spin_lock_irq(&priv->lock); 3571732b0efSRoland Dreier 3581732b0efSRoland Dreier n = rb_first(&priv->path_tree); 3591732b0efSRoland Dreier 3601732b0efSRoland Dreier while (n) { 3611732b0efSRoland Dreier path = rb_entry(n, struct ipoib_path, rb_node); 3621732b0efSRoland Dreier 3631732b0efSRoland Dreier if (memcmp(iter->path.pathrec.dgid.raw, path->pathrec.dgid.raw, 3641732b0efSRoland Dreier sizeof (union ib_gid)) < 0) { 3651732b0efSRoland Dreier iter->path = *path; 3661732b0efSRoland Dreier ret = 0; 3671732b0efSRoland Dreier break; 3681732b0efSRoland Dreier } 3691732b0efSRoland Dreier 3701732b0efSRoland Dreier n = rb_next(n); 3711732b0efSRoland Dreier } 3721732b0efSRoland Dreier 3731732b0efSRoland Dreier spin_unlock_irq(&priv->lock); 3741732b0efSRoland Dreier 3751732b0efSRoland Dreier return ret; 3761732b0efSRoland Dreier } 3771732b0efSRoland Dreier 3781732b0efSRoland Dreier void ipoib_path_iter_read(struct ipoib_path_iter *iter, 3791732b0efSRoland Dreier struct ipoib_path *path) 3801732b0efSRoland Dreier { 3811732b0efSRoland Dreier *path = iter->path; 3821732b0efSRoland Dreier } 3831732b0efSRoland Dreier 3841732b0efSRoland Dreier #endif /* CONFIG_INFINIBAND_IPOIB_DEBUG */ 3851732b0efSRoland Dreier 386ee1e2c82SMoni Shoua void ipoib_mark_paths_invalid(struct net_device *dev) 387ee1e2c82SMoni Shoua { 388ee1e2c82SMoni Shoua struct ipoib_dev_priv *priv = netdev_priv(dev); 389ee1e2c82SMoni Shoua struct ipoib_path *path, *tp; 390ee1e2c82SMoni Shoua 391ee1e2c82SMoni Shoua spin_lock_irq(&priv->lock); 392ee1e2c82SMoni Shoua 393ee1e2c82SMoni Shoua list_for_each_entry_safe(path, tp, &priv->path_list, list) { 3945b095d98SHarvey Harrison ipoib_dbg(priv, "mark path LID 0x%04x GID %pI6 invalid\n", 395ee1e2c82SMoni Shoua be16_to_cpu(path->pathrec.dlid), 396fcace2feSHarvey Harrison path->pathrec.dgid.raw); 397ee1e2c82SMoni Shoua path->valid = 0; 398ee1e2c82SMoni Shoua } 399ee1e2c82SMoni Shoua 400ee1e2c82SMoni Shoua spin_unlock_irq(&priv->lock); 401ee1e2c82SMoni Shoua } 402ee1e2c82SMoni Shoua 4031da177e4SLinus Torvalds void ipoib_flush_paths(struct net_device *dev) 4041da177e4SLinus Torvalds { 4051da177e4SLinus Torvalds struct ipoib_dev_priv *priv = netdev_priv(dev); 4061da177e4SLinus Torvalds struct ipoib_path *path, *tp; 4071da177e4SLinus Torvalds LIST_HEAD(remove_list); 408943c246eSRoland Dreier unsigned long flags; 4091da177e4SLinus Torvalds 410943c246eSRoland Dreier netif_tx_lock_bh(dev); 411943c246eSRoland Dreier spin_lock_irqsave(&priv->lock, flags); 4121da177e4SLinus Torvalds 413157de229SRobert P. J. Day list_splice_init(&priv->path_list, &remove_list); 4141da177e4SLinus Torvalds 4151da177e4SLinus Torvalds list_for_each_entry(path, &remove_list, list) 4161da177e4SLinus Torvalds rb_erase(&path->rb_node, &priv->path_tree); 4171da177e4SLinus Torvalds 4181da177e4SLinus Torvalds list_for_each_entry_safe(path, tp, &remove_list, list) { 4191da177e4SLinus Torvalds if (path->query) 4201da177e4SLinus Torvalds ib_sa_cancel_query(path->query_id, path->query); 421943c246eSRoland Dreier spin_unlock_irqrestore(&priv->lock, flags); 422943c246eSRoland Dreier netif_tx_unlock_bh(dev); 4231da177e4SLinus Torvalds wait_for_completion(&path->done); 4241da177e4SLinus Torvalds path_free(dev, path); 425943c246eSRoland Dreier netif_tx_lock_bh(dev); 426943c246eSRoland Dreier spin_lock_irqsave(&priv->lock, flags); 4271da177e4SLinus Torvalds } 428943c246eSRoland Dreier 429943c246eSRoland Dreier spin_unlock_irqrestore(&priv->lock, flags); 430943c246eSRoland Dreier netif_tx_unlock_bh(dev); 4311da177e4SLinus Torvalds } 4321da177e4SLinus Torvalds 4331da177e4SLinus Torvalds static void path_rec_completion(int status, 4341da177e4SLinus Torvalds struct ib_sa_path_rec *pathrec, 4351da177e4SLinus Torvalds void *path_ptr) 4361da177e4SLinus Torvalds { 4371da177e4SLinus Torvalds struct ipoib_path *path = path_ptr; 4381da177e4SLinus Torvalds struct net_device *dev = path->dev; 4391da177e4SLinus Torvalds struct ipoib_dev_priv *priv = netdev_priv(dev); 4401da177e4SLinus Torvalds struct ipoib_ah *ah = NULL; 441c9da4badSRoland Dreier struct ipoib_ah *old_ah = NULL; 442d04d01b1SMichael S. Tsirkin struct ipoib_neigh *neigh, *tn; 4431da177e4SLinus Torvalds struct sk_buff_head skqueue; 4441da177e4SLinus Torvalds struct sk_buff *skb; 4451da177e4SLinus Torvalds unsigned long flags; 4461da177e4SLinus Torvalds 447843613b0SRoland Dreier if (!status) 4485b095d98SHarvey Harrison ipoib_dbg(priv, "PathRec LID 0x%04x for GID %pI6\n", 449fcace2feSHarvey Harrison be16_to_cpu(pathrec->dlid), pathrec->dgid.raw); 4501da177e4SLinus Torvalds else 4515b095d98SHarvey Harrison ipoib_dbg(priv, "PathRec status %d for GID %pI6\n", 452fcace2feSHarvey Harrison status, path->pathrec.dgid.raw); 4531da177e4SLinus Torvalds 4541da177e4SLinus Torvalds skb_queue_head_init(&skqueue); 4551da177e4SLinus Torvalds 4561da177e4SLinus Torvalds if (!status) { 45746f1b3d7SSean Hefty struct ib_ah_attr av; 4581da177e4SLinus Torvalds 45946f1b3d7SSean Hefty if (!ib_init_ah_from_path(priv->ca, priv->port, pathrec, &av)) 4601da177e4SLinus Torvalds ah = ipoib_create_ah(dev, priv->pd, &av); 4611da177e4SLinus Torvalds } 4621da177e4SLinus Torvalds 4631da177e4SLinus Torvalds spin_lock_irqsave(&priv->lock, flags); 4641da177e4SLinus Torvalds 4653874397cSMike Marciniszyn if (!IS_ERR_OR_NULL(ah)) { 4661da177e4SLinus Torvalds path->pathrec = *pathrec; 4671da177e4SLinus Torvalds 468c9da4badSRoland Dreier old_ah = path->ah; 469c9da4badSRoland Dreier path->ah = ah; 470c9da4badSRoland Dreier 4711da177e4SLinus Torvalds ipoib_dbg(priv, "created address handle %p for LID 0x%04x, SL %d\n", 4721da177e4SLinus Torvalds ah, be16_to_cpu(pathrec->dlid), pathrec->sl); 4731da177e4SLinus Torvalds 4741da177e4SLinus Torvalds while ((skb = __skb_dequeue(&path->queue))) 4751da177e4SLinus Torvalds __skb_queue_tail(&skqueue, skb); 4761da177e4SLinus Torvalds 477d04d01b1SMichael S. Tsirkin list_for_each_entry_safe(neigh, tn, &path->neigh_list, list) { 478ee1e2c82SMoni Shoua if (neigh->ah) { 479ee1e2c82SMoni Shoua WARN_ON(neigh->ah != old_ah); 480ee1e2c82SMoni Shoua /* 481ee1e2c82SMoni Shoua * Dropping the ah reference inside 482ee1e2c82SMoni Shoua * priv->lock is safe here, because we 483ee1e2c82SMoni Shoua * will hold one more reference from 484ee1e2c82SMoni Shoua * the original value of path->ah (ie 485ee1e2c82SMoni Shoua * old_ah). 486ee1e2c82SMoni Shoua */ 487ee1e2c82SMoni Shoua ipoib_put_ah(neigh->ah); 488ee1e2c82SMoni Shoua } 4891da177e4SLinus Torvalds kref_get(&path->ah->ref); 4901da177e4SLinus Torvalds neigh->ah = path->ah; 4911da177e4SLinus Torvalds 492b63b70d8SShlomo Pongratz if (ipoib_cm_enabled(dev, neigh->daddr)) { 493839fcabaSMichael S. Tsirkin if (!ipoib_cm_get(neigh)) 494839fcabaSMichael S. Tsirkin ipoib_cm_set(neigh, ipoib_cm_create_tx(dev, 495839fcabaSMichael S. Tsirkin path, 496839fcabaSMichael S. Tsirkin neigh)); 497839fcabaSMichael S. Tsirkin if (!ipoib_cm_get(neigh)) { 498b63b70d8SShlomo Pongratz ipoib_neigh_free(neigh); 499839fcabaSMichael S. Tsirkin continue; 500839fcabaSMichael S. Tsirkin } 501839fcabaSMichael S. Tsirkin } 502839fcabaSMichael S. Tsirkin 5031da177e4SLinus Torvalds while ((skb = __skb_dequeue(&neigh->queue))) 5041da177e4SLinus Torvalds __skb_queue_tail(&skqueue, skb); 5051da177e4SLinus Torvalds } 506ee1e2c82SMoni Shoua path->valid = 1; 5075872a9fcSRoland Dreier } 5081da177e4SLinus Torvalds 5095872a9fcSRoland Dreier path->query = NULL; 5101da177e4SLinus Torvalds complete(&path->done); 5111da177e4SLinus Torvalds 5121da177e4SLinus Torvalds spin_unlock_irqrestore(&priv->lock, flags); 5131da177e4SLinus Torvalds 514f72dd566SRoland Dreier if (IS_ERR_OR_NULL(ah)) 515f72dd566SRoland Dreier ipoib_del_neighs_by_gid(dev, path->pathrec.dgid.raw); 516f72dd566SRoland Dreier 517ee1e2c82SMoni Shoua if (old_ah) 518ee1e2c82SMoni Shoua ipoib_put_ah(old_ah); 519ee1e2c82SMoni Shoua 5201da177e4SLinus Torvalds while ((skb = __skb_dequeue(&skqueue))) { 5211da177e4SLinus Torvalds skb->dev = dev; 5221da177e4SLinus Torvalds if (dev_queue_xmit(skb)) 5231da177e4SLinus Torvalds ipoib_warn(priv, "dev_queue_xmit failed " 5241da177e4SLinus Torvalds "to requeue packet\n"); 5251da177e4SLinus Torvalds } 5261da177e4SLinus Torvalds } 5271da177e4SLinus Torvalds 52837c22a77SJack Morgenstein static struct ipoib_path *path_rec_create(struct net_device *dev, void *gid) 5291da177e4SLinus Torvalds { 5301da177e4SLinus Torvalds struct ipoib_dev_priv *priv = netdev_priv(dev); 5311da177e4SLinus Torvalds struct ipoib_path *path; 5321da177e4SLinus Torvalds 5331401b53aSJack Morgenstein if (!priv->broadcast) 5341401b53aSJack Morgenstein return NULL; 5351401b53aSJack Morgenstein 53621a38489SRoland Dreier path = kzalloc(sizeof *path, GFP_ATOMIC); 5371da177e4SLinus Torvalds if (!path) 5381da177e4SLinus Torvalds return NULL; 5391da177e4SLinus Torvalds 5401da177e4SLinus Torvalds path->dev = dev; 5411da177e4SLinus Torvalds 5421da177e4SLinus Torvalds skb_queue_head_init(&path->queue); 5431da177e4SLinus Torvalds 5441da177e4SLinus Torvalds INIT_LIST_HEAD(&path->neigh_list); 5451da177e4SLinus Torvalds 54637c22a77SJack Morgenstein memcpy(path->pathrec.dgid.raw, gid, sizeof (union ib_gid)); 5471da177e4SLinus Torvalds path->pathrec.sgid = priv->local_gid; 5481da177e4SLinus Torvalds path->pathrec.pkey = cpu_to_be16(priv->pkey); 5491da177e4SLinus Torvalds path->pathrec.numb_path = 1; 55081668838SSean Hefty path->pathrec.traffic_class = priv->broadcast->mcmember.traffic_class; 5511da177e4SLinus Torvalds 5521da177e4SLinus Torvalds return path; 5531da177e4SLinus Torvalds } 5541da177e4SLinus Torvalds 5551da177e4SLinus Torvalds static int path_rec_start(struct net_device *dev, 5561da177e4SLinus Torvalds struct ipoib_path *path) 5571da177e4SLinus Torvalds { 5581da177e4SLinus Torvalds struct ipoib_dev_priv *priv = netdev_priv(dev); 5591da177e4SLinus Torvalds 5605b095d98SHarvey Harrison ipoib_dbg(priv, "Start path record lookup for %pI6\n", 561fcace2feSHarvey Harrison path->pathrec.dgid.raw); 5621da177e4SLinus Torvalds 56365c7eddaSRoland Dreier init_completion(&path->done); 56465c7eddaSRoland Dreier 5651da177e4SLinus Torvalds path->query_id = 566c1a0b23bSMichael S. Tsirkin ib_sa_path_rec_get(&ipoib_sa_client, priv->ca, priv->port, 5671da177e4SLinus Torvalds &path->pathrec, 5681da177e4SLinus Torvalds IB_SA_PATH_REC_DGID | 5691da177e4SLinus Torvalds IB_SA_PATH_REC_SGID | 5701da177e4SLinus Torvalds IB_SA_PATH_REC_NUMB_PATH | 57181668838SSean Hefty IB_SA_PATH_REC_TRAFFIC_CLASS | 5721da177e4SLinus Torvalds IB_SA_PATH_REC_PKEY, 5731da177e4SLinus Torvalds 1000, GFP_ATOMIC, 5741da177e4SLinus Torvalds path_rec_completion, 5751da177e4SLinus Torvalds path, &path->query); 5761da177e4SLinus Torvalds if (path->query_id < 0) { 57701b3fc8bSOr Gerlitz ipoib_warn(priv, "ib_sa_path_rec_get failed: %d\n", path->query_id); 5781da177e4SLinus Torvalds path->query = NULL; 57993a3ab93SYossi Etigin complete(&path->done); 5801da177e4SLinus Torvalds return path->query_id; 5811da177e4SLinus Torvalds } 5821da177e4SLinus Torvalds 5831da177e4SLinus Torvalds return 0; 5841da177e4SLinus Torvalds } 5851da177e4SLinus Torvalds 586b63b70d8SShlomo Pongratz static void neigh_add_path(struct sk_buff *skb, u8 *daddr, 587b63b70d8SShlomo Pongratz struct net_device *dev) 5881da177e4SLinus Torvalds { 5891da177e4SLinus Torvalds struct ipoib_dev_priv *priv = netdev_priv(dev); 5901da177e4SLinus Torvalds struct ipoib_path *path; 5911da177e4SLinus Torvalds struct ipoib_neigh *neigh; 592943c246eSRoland Dreier unsigned long flags; 5931da177e4SLinus Torvalds 594b5120a6eSShlomo Pongratz spin_lock_irqsave(&priv->lock, flags); 595b63b70d8SShlomo Pongratz neigh = ipoib_neigh_alloc(daddr, dev); 5961da177e4SLinus Torvalds if (!neigh) { 597b5120a6eSShlomo Pongratz spin_unlock_irqrestore(&priv->lock, flags); 598de903512SRoland Dreier ++dev->stats.tx_dropped; 5991da177e4SLinus Torvalds dev_kfree_skb_any(skb); 6001da177e4SLinus Torvalds return; 6011da177e4SLinus Torvalds } 6021da177e4SLinus Torvalds 603b63b70d8SShlomo Pongratz path = __path_find(dev, daddr + 4); 6041da177e4SLinus Torvalds if (!path) { 605b63b70d8SShlomo Pongratz path = path_rec_create(dev, daddr + 4); 6061da177e4SLinus Torvalds if (!path) 607d2e0655eSMichael S. Tsirkin goto err_path; 6081da177e4SLinus Torvalds 6091da177e4SLinus Torvalds __path_add(dev, path); 6101da177e4SLinus Torvalds } 6111da177e4SLinus Torvalds 6121da177e4SLinus Torvalds list_add_tail(&neigh->list, &path->neigh_list); 6131da177e4SLinus Torvalds 61447f7a071SMichael S. Tsirkin if (path->ah) { 6151da177e4SLinus Torvalds kref_get(&path->ah->ref); 6161da177e4SLinus Torvalds neigh->ah = path->ah; 6171da177e4SLinus Torvalds 618b63b70d8SShlomo Pongratz if (ipoib_cm_enabled(dev, neigh->daddr)) { 619839fcabaSMichael S. Tsirkin if (!ipoib_cm_get(neigh)) 620839fcabaSMichael S. Tsirkin ipoib_cm_set(neigh, ipoib_cm_create_tx(dev, path, neigh)); 621839fcabaSMichael S. Tsirkin if (!ipoib_cm_get(neigh)) { 622b63b70d8SShlomo Pongratz ipoib_neigh_free(neigh); 623839fcabaSMichael S. Tsirkin goto err_drop; 624839fcabaSMichael S. Tsirkin } 625839fcabaSMichael S. Tsirkin if (skb_queue_len(&neigh->queue) < IPOIB_MAX_PATH_REC_QUEUE) 626839fcabaSMichael S. Tsirkin __skb_queue_tail(&neigh->queue, skb); 627839fcabaSMichael S. Tsirkin else { 628839fcabaSMichael S. Tsirkin ipoib_warn(priv, "queue length limit %d. Packet drop.\n", 629839fcabaSMichael S. Tsirkin skb_queue_len(&neigh->queue)); 630839fcabaSMichael S. Tsirkin goto err_drop; 631839fcabaSMichael S. Tsirkin } 632721d67cdSRoland Dreier } else { 633721d67cdSRoland Dreier spin_unlock_irqrestore(&priv->lock, flags); 634b63b70d8SShlomo Pongratz ipoib_send(dev, skb, path->ah, IPOIB_QPN(daddr)); 635b63b70d8SShlomo Pongratz ipoib_neigh_put(neigh); 636721d67cdSRoland Dreier return; 637721d67cdSRoland Dreier } 6381da177e4SLinus Torvalds } else { 6391da177e4SLinus Torvalds neigh->ah = NULL; 6401da177e4SLinus Torvalds 6411da177e4SLinus Torvalds if (!path->query && path_rec_start(dev, path)) 64249b8e744SJim Foraker goto err_path; 6431e85b806SErez Shitrit if (skb_queue_len(&neigh->queue) < IPOIB_MAX_PATH_REC_QUEUE) 6442745b5b7SMichael S. Tsirkin __skb_queue_tail(&neigh->queue, skb); 6451e85b806SErez Shitrit else 6461e85b806SErez Shitrit goto err_drop; 6471da177e4SLinus Torvalds } 6481da177e4SLinus Torvalds 649943c246eSRoland Dreier spin_unlock_irqrestore(&priv->lock, flags); 650b63b70d8SShlomo Pongratz ipoib_neigh_put(neigh); 6511da177e4SLinus Torvalds return; 6521da177e4SLinus Torvalds 653d2e0655eSMichael S. Tsirkin err_path: 654b63b70d8SShlomo Pongratz ipoib_neigh_free(neigh); 655839fcabaSMichael S. Tsirkin err_drop: 656de903512SRoland Dreier ++dev->stats.tx_dropped; 6571da177e4SLinus Torvalds dev_kfree_skb_any(skb); 6581da177e4SLinus Torvalds 659943c246eSRoland Dreier spin_unlock_irqrestore(&priv->lock, flags); 660b63b70d8SShlomo Pongratz ipoib_neigh_put(neigh); 6611da177e4SLinus Torvalds } 6621da177e4SLinus Torvalds 6631da177e4SLinus Torvalds static void unicast_arp_send(struct sk_buff *skb, struct net_device *dev, 664936d7de3SRoland Dreier struct ipoib_cb *cb) 6651da177e4SLinus Torvalds { 6661da177e4SLinus Torvalds struct ipoib_dev_priv *priv = netdev_priv(dev); 6671da177e4SLinus Torvalds struct ipoib_path *path; 668943c246eSRoland Dreier unsigned long flags; 6691da177e4SLinus Torvalds 670943c246eSRoland Dreier spin_lock_irqsave(&priv->lock, flags); 6711da177e4SLinus Torvalds 672936d7de3SRoland Dreier path = __path_find(dev, cb->hwaddr + 4); 673ee1e2c82SMoni Shoua if (!path || !path->valid) { 67471d98b46SJack Morgenstein int new_path = 0; 67571d98b46SJack Morgenstein 67671d98b46SJack Morgenstein if (!path) { 677936d7de3SRoland Dreier path = path_rec_create(dev, cb->hwaddr + 4); 67871d98b46SJack Morgenstein new_path = 1; 67971d98b46SJack Morgenstein } 6801da177e4SLinus Torvalds if (path) { 6811e85b806SErez Shitrit if (skb_queue_len(&path->queue) < IPOIB_MAX_PATH_REC_QUEUE) { 6821da177e4SLinus Torvalds __skb_queue_tail(&path->queue, skb); 6831e85b806SErez Shitrit } else { 6841e85b806SErez Shitrit ++dev->stats.tx_dropped; 6851e85b806SErez Shitrit dev_kfree_skb_any(skb); 6861e85b806SErez Shitrit } 6871da177e4SLinus Torvalds 688ff79ae80SYossi Etigin if (!path->query && path_rec_start(dev, path)) { 689943c246eSRoland Dreier spin_unlock_irqrestore(&priv->lock, flags); 69071d98b46SJack Morgenstein if (new_path) 6911da177e4SLinus Torvalds path_free(dev, path); 6921da177e4SLinus Torvalds return; 6931da177e4SLinus Torvalds } else 6941da177e4SLinus Torvalds __path_add(dev, path); 6951da177e4SLinus Torvalds } else { 696de903512SRoland Dreier ++dev->stats.tx_dropped; 6971da177e4SLinus Torvalds dev_kfree_skb_any(skb); 6981da177e4SLinus Torvalds } 6991da177e4SLinus Torvalds 700943c246eSRoland Dreier spin_unlock_irqrestore(&priv->lock, flags); 7011da177e4SLinus Torvalds return; 7021da177e4SLinus Torvalds } 7031da177e4SLinus Torvalds 70447f7a071SMichael S. Tsirkin if (path->ah) { 7051da177e4SLinus Torvalds ipoib_dbg(priv, "Send unicast ARP to %04x\n", 7061da177e4SLinus Torvalds be16_to_cpu(path->pathrec.dlid)); 7071da177e4SLinus Torvalds 708721d67cdSRoland Dreier spin_unlock_irqrestore(&priv->lock, flags); 709936d7de3SRoland Dreier ipoib_send(dev, skb, path->ah, IPOIB_QPN(cb->hwaddr)); 710721d67cdSRoland Dreier return; 7111da177e4SLinus Torvalds } else if ((path->query || !path_rec_start(dev, path)) && 7121da177e4SLinus Torvalds skb_queue_len(&path->queue) < IPOIB_MAX_PATH_REC_QUEUE) { 7131da177e4SLinus Torvalds __skb_queue_tail(&path->queue, skb); 7141da177e4SLinus Torvalds } else { 715de903512SRoland Dreier ++dev->stats.tx_dropped; 7161da177e4SLinus Torvalds dev_kfree_skb_any(skb); 7171da177e4SLinus Torvalds } 7181da177e4SLinus Torvalds 719943c246eSRoland Dreier spin_unlock_irqrestore(&priv->lock, flags); 7201da177e4SLinus Torvalds } 7211da177e4SLinus Torvalds 7221da177e4SLinus Torvalds static int ipoib_start_xmit(struct sk_buff *skb, struct net_device *dev) 7231da177e4SLinus Torvalds { 7241da177e4SLinus Torvalds struct ipoib_dev_priv *priv = netdev_priv(dev); 7251da177e4SLinus Torvalds struct ipoib_neigh *neigh; 726b49fe362SEric Dumazet struct ipoib_cb *cb = ipoib_skb_cb(skb); 727b63b70d8SShlomo Pongratz struct ipoib_header *header; 7281da177e4SLinus Torvalds unsigned long flags; 7291da177e4SLinus Torvalds 730b63b70d8SShlomo Pongratz header = (struct ipoib_header *) skb->data; 731b63b70d8SShlomo Pongratz 732b63b70d8SShlomo Pongratz if (unlikely(cb->hwaddr[4] == 0xff)) { 733b63b70d8SShlomo Pongratz /* multicast, arrange "if" according to probability */ 734b63b70d8SShlomo Pongratz if ((header->proto != htons(ETH_P_IP)) && 735b63b70d8SShlomo Pongratz (header->proto != htons(ETH_P_IPV6)) && 736b63b70d8SShlomo Pongratz (header->proto != htons(ETH_P_ARP)) && 737dc850b0eSPatrick McHardy (header->proto != htons(ETH_P_RARP)) && 738dc850b0eSPatrick McHardy (header->proto != htons(ETH_P_TIPC))) { 739b63b70d8SShlomo Pongratz /* ethertype not supported by IPoIB */ 74017e6abeeSDavid Miller ++dev->stats.tx_dropped; 74117e6abeeSDavid Miller dev_kfree_skb_any(skb); 742b63b70d8SShlomo Pongratz return NETDEV_TX_OK; 74317e6abeeSDavid Miller } 744b63b70d8SShlomo Pongratz /* Add in the P_Key for multicast*/ 745b63b70d8SShlomo Pongratz cb->hwaddr[8] = (priv->pkey >> 8) & 0xff; 746b63b70d8SShlomo Pongratz cb->hwaddr[9] = priv->pkey & 0xff; 747b63b70d8SShlomo Pongratz 748b63b70d8SShlomo Pongratz neigh = ipoib_neigh_get(dev, cb->hwaddr); 749b63b70d8SShlomo Pongratz if (likely(neigh)) 750b63b70d8SShlomo Pongratz goto send_using_neigh; 751b63b70d8SShlomo Pongratz ipoib_mcast_send(dev, cb->hwaddr, skb); 752b63b70d8SShlomo Pongratz return NETDEV_TX_OK; 7531da177e4SLinus Torvalds } 7541da177e4SLinus Torvalds 755b63b70d8SShlomo Pongratz /* unicast, arrange "switch" according to probability */ 756b63b70d8SShlomo Pongratz switch (header->proto) { 757b63b70d8SShlomo Pongratz case htons(ETH_P_IP): 758b63b70d8SShlomo Pongratz case htons(ETH_P_IPV6): 759dc850b0eSPatrick McHardy case htons(ETH_P_TIPC): 760b63b70d8SShlomo Pongratz neigh = ipoib_neigh_get(dev, cb->hwaddr); 761b63b70d8SShlomo Pongratz if (unlikely(!neigh)) { 762b63b70d8SShlomo Pongratz neigh_add_path(skb, cb->hwaddr, dev); 763b63b70d8SShlomo Pongratz return NETDEV_TX_OK; 764b63b70d8SShlomo Pongratz } 765b63b70d8SShlomo Pongratz break; 766b63b70d8SShlomo Pongratz case htons(ETH_P_ARP): 767b63b70d8SShlomo Pongratz case htons(ETH_P_RARP): 768b63b70d8SShlomo Pongratz /* for unicast ARP and RARP should always perform path find */ 769b63b70d8SShlomo Pongratz unicast_arp_send(skb, dev, cb); 770b63b70d8SShlomo Pongratz return NETDEV_TX_OK; 771b63b70d8SShlomo Pongratz default: 772b63b70d8SShlomo Pongratz /* ethertype not supported by IPoIB */ 773b63b70d8SShlomo Pongratz ++dev->stats.tx_dropped; 774b63b70d8SShlomo Pongratz dev_kfree_skb_any(skb); 775b63b70d8SShlomo Pongratz return NETDEV_TX_OK; 7768a7f7521SMichael S. Tsirkin } 7778a7f7521SMichael S. Tsirkin 778b63b70d8SShlomo Pongratz send_using_neigh: 779b63b70d8SShlomo Pongratz /* note we now hold a ref to neigh */ 780bafff974SOr Gerlitz if (ipoib_cm_get(neigh)) { 781bafff974SOr Gerlitz if (ipoib_cm_up(neigh)) { 782bafff974SOr Gerlitz ipoib_cm_send(dev, skb, ipoib_cm_get(neigh)); 783b63b70d8SShlomo Pongratz goto unref; 784bafff974SOr Gerlitz } 785bafff974SOr Gerlitz } else if (neigh->ah) { 786b63b70d8SShlomo Pongratz ipoib_send(dev, skb, neigh->ah, IPOIB_QPN(cb->hwaddr)); 787b63b70d8SShlomo Pongratz goto unref; 7881da177e4SLinus Torvalds } 7891da177e4SLinus Torvalds 7901da177e4SLinus Torvalds if (skb_queue_len(&neigh->queue) < IPOIB_MAX_PATH_REC_QUEUE) { 791943c246eSRoland Dreier spin_lock_irqsave(&priv->lock, flags); 7921da177e4SLinus Torvalds __skb_queue_tail(&neigh->queue, skb); 793943c246eSRoland Dreier spin_unlock_irqrestore(&priv->lock, flags); 7941da177e4SLinus Torvalds } else { 795de903512SRoland Dreier ++dev->stats.tx_dropped; 7961da177e4SLinus Torvalds dev_kfree_skb_any(skb); 7971da177e4SLinus Torvalds } 7981da177e4SLinus Torvalds 799b63b70d8SShlomo Pongratz unref: 800b63b70d8SShlomo Pongratz ipoib_neigh_put(neigh); 8011da177e4SLinus Torvalds 8021da177e4SLinus Torvalds return NETDEV_TX_OK; 8031da177e4SLinus Torvalds } 8041da177e4SLinus Torvalds 8051da177e4SLinus Torvalds static void ipoib_timeout(struct net_device *dev) 8061da177e4SLinus Torvalds { 8071da177e4SLinus Torvalds struct ipoib_dev_priv *priv = netdev_priv(dev); 8081da177e4SLinus Torvalds 8094b2d319bSRoland Dreier ipoib_warn(priv, "transmit timeout: latency %d msecs\n", 8104b2d319bSRoland Dreier jiffies_to_msecs(jiffies - dev->trans_start)); 8114b2d319bSRoland Dreier ipoib_warn(priv, "queue stopped %d, tx_head %u, tx_tail %u\n", 8124b2d319bSRoland Dreier netif_queue_stopped(dev), 8134b2d319bSRoland Dreier priv->tx_head, priv->tx_tail); 8141da177e4SLinus Torvalds /* XXX reset QP, etc. */ 8151da177e4SLinus Torvalds } 8161da177e4SLinus Torvalds 8171da177e4SLinus Torvalds static int ipoib_hard_header(struct sk_buff *skb, 8181da177e4SLinus Torvalds struct net_device *dev, 8191da177e4SLinus Torvalds unsigned short type, 8203b04dddeSStephen Hemminger const void *daddr, const void *saddr, unsigned len) 8211da177e4SLinus Torvalds { 8221da177e4SLinus Torvalds struct ipoib_header *header; 823b49fe362SEric Dumazet struct ipoib_cb *cb = ipoib_skb_cb(skb); 8241da177e4SLinus Torvalds 8251da177e4SLinus Torvalds header = (struct ipoib_header *) skb_push(skb, sizeof *header); 8261da177e4SLinus Torvalds 8271da177e4SLinus Torvalds header->proto = htons(type); 8281da177e4SLinus Torvalds header->reserved = 0; 8291da177e4SLinus Torvalds 8301da177e4SLinus Torvalds /* 831b63b70d8SShlomo Pongratz * we don't rely on dst_entry structure, always stuff the 832936d7de3SRoland Dreier * destination address into skb->cb so we can figure out where 833936d7de3SRoland Dreier * to send the packet later. 8341da177e4SLinus Torvalds */ 835936d7de3SRoland Dreier memcpy(cb->hwaddr, daddr, INFINIBAND_ALEN); 8361da177e4SLinus Torvalds 83783bdd3b9SDoug Ledford return sizeof *header; 8381da177e4SLinus Torvalds } 8391da177e4SLinus Torvalds 8401da177e4SLinus Torvalds static void ipoib_set_mcast_list(struct net_device *dev) 8411da177e4SLinus Torvalds { 8421da177e4SLinus Torvalds struct ipoib_dev_priv *priv = netdev_priv(dev); 8431da177e4SLinus Torvalds 8447a343d4cSLeonid Arsh if (!test_bit(IPOIB_FLAG_OPER_UP, &priv->flags)) { 8457a343d4cSLeonid Arsh ipoib_dbg(priv, "IPOIB_FLAG_OPER_UP not set"); 8467a343d4cSLeonid Arsh return; 8477a343d4cSLeonid Arsh } 8487a343d4cSLeonid Arsh 8490b39578bSDoug Ledford queue_work(priv->wq, &priv->restart_task); 8501da177e4SLinus Torvalds } 8511da177e4SLinus Torvalds 8525aa7add8SNicolas Dichtel static int ipoib_get_iflink(const struct net_device *dev) 8535aa7add8SNicolas Dichtel { 8545aa7add8SNicolas Dichtel struct ipoib_dev_priv *priv = netdev_priv(dev); 8555aa7add8SNicolas Dichtel 8562c153959SErez Shitrit /* parent interface */ 8572c153959SErez Shitrit if (!test_bit(IPOIB_FLAG_SUBINTERFACE, &priv->flags)) 8582c153959SErez Shitrit return dev->ifindex; 8592c153959SErez Shitrit 8602c153959SErez Shitrit /* child/vlan interface */ 8615aa7add8SNicolas Dichtel return priv->parent->ifindex; 8625aa7add8SNicolas Dichtel } 8635aa7add8SNicolas Dichtel 864b63b70d8SShlomo Pongratz static u32 ipoib_addr_hash(struct ipoib_neigh_hash *htbl, u8 *daddr) 8651da177e4SLinus Torvalds { 866b63b70d8SShlomo Pongratz /* 867b63b70d8SShlomo Pongratz * Use only the address parts that contributes to spreading 868b63b70d8SShlomo Pongratz * The subnet prefix is not used as one can not connect to 869b63b70d8SShlomo Pongratz * same remote port (GUID) using the same remote QPN via two 870b63b70d8SShlomo Pongratz * different subnets. 871b63b70d8SShlomo Pongratz */ 872b63b70d8SShlomo Pongratz /* qpn octets[1:4) & port GUID octets[12:20) */ 8739d1ad66eSShlomo Pongratz u32 *d32 = (u32 *) daddr; 874b63b70d8SShlomo Pongratz u32 hv; 8751da177e4SLinus Torvalds 8769d1ad66eSShlomo Pongratz hv = jhash_3words(d32[3], d32[4], IPOIB_QPN_MASK & d32[0], 0); 877b63b70d8SShlomo Pongratz return hv & htbl->mask; 8781da177e4SLinus Torvalds } 8791da177e4SLinus Torvalds 880b63b70d8SShlomo Pongratz struct ipoib_neigh *ipoib_neigh_get(struct net_device *dev, u8 *daddr) 881b63b70d8SShlomo Pongratz { 882b63b70d8SShlomo Pongratz struct ipoib_dev_priv *priv = netdev_priv(dev); 883b63b70d8SShlomo Pongratz struct ipoib_neigh_table *ntbl = &priv->ntbl; 884b63b70d8SShlomo Pongratz struct ipoib_neigh_hash *htbl; 885b63b70d8SShlomo Pongratz struct ipoib_neigh *neigh = NULL; 886b63b70d8SShlomo Pongratz u32 hash_val; 887b63b70d8SShlomo Pongratz 888b63b70d8SShlomo Pongratz rcu_read_lock_bh(); 889b63b70d8SShlomo Pongratz 890b63b70d8SShlomo Pongratz htbl = rcu_dereference_bh(ntbl->htbl); 891b63b70d8SShlomo Pongratz 892b63b70d8SShlomo Pongratz if (!htbl) 893b63b70d8SShlomo Pongratz goto out_unlock; 894b63b70d8SShlomo Pongratz 895b63b70d8SShlomo Pongratz hash_val = ipoib_addr_hash(htbl, daddr); 896b63b70d8SShlomo Pongratz for (neigh = rcu_dereference_bh(htbl->buckets[hash_val]); 897b63b70d8SShlomo Pongratz neigh != NULL; 898b63b70d8SShlomo Pongratz neigh = rcu_dereference_bh(neigh->hnext)) { 899b63b70d8SShlomo Pongratz if (memcmp(daddr, neigh->daddr, INFINIBAND_ALEN) == 0) { 900b63b70d8SShlomo Pongratz /* found, take one ref on behalf of the caller */ 901b63b70d8SShlomo Pongratz if (!atomic_inc_not_zero(&neigh->refcnt)) { 902b63b70d8SShlomo Pongratz /* deleted */ 903b63b70d8SShlomo Pongratz neigh = NULL; 904b63b70d8SShlomo Pongratz goto out_unlock; 905b63b70d8SShlomo Pongratz } 906b63b70d8SShlomo Pongratz neigh->alive = jiffies; 907b63b70d8SShlomo Pongratz goto out_unlock; 908b63b70d8SShlomo Pongratz } 909b63b70d8SShlomo Pongratz } 910b63b70d8SShlomo Pongratz 911b63b70d8SShlomo Pongratz out_unlock: 912b63b70d8SShlomo Pongratz rcu_read_unlock_bh(); 913b63b70d8SShlomo Pongratz return neigh; 914b63b70d8SShlomo Pongratz } 915b63b70d8SShlomo Pongratz 916b63b70d8SShlomo Pongratz static void __ipoib_reap_neigh(struct ipoib_dev_priv *priv) 917b63b70d8SShlomo Pongratz { 918b63b70d8SShlomo Pongratz struct ipoib_neigh_table *ntbl = &priv->ntbl; 919b63b70d8SShlomo Pongratz struct ipoib_neigh_hash *htbl; 920b63b70d8SShlomo Pongratz unsigned long neigh_obsolete; 921b63b70d8SShlomo Pongratz unsigned long dt; 922b63b70d8SShlomo Pongratz unsigned long flags; 923b63b70d8SShlomo Pongratz int i; 924b63b70d8SShlomo Pongratz 925b63b70d8SShlomo Pongratz if (test_bit(IPOIB_STOP_NEIGH_GC, &priv->flags)) 926b63b70d8SShlomo Pongratz return; 927b63b70d8SShlomo Pongratz 928b5120a6eSShlomo Pongratz spin_lock_irqsave(&priv->lock, flags); 929b63b70d8SShlomo Pongratz 930b63b70d8SShlomo Pongratz htbl = rcu_dereference_protected(ntbl->htbl, 931b5120a6eSShlomo Pongratz lockdep_is_held(&priv->lock)); 932b63b70d8SShlomo Pongratz 933b63b70d8SShlomo Pongratz if (!htbl) 934b63b70d8SShlomo Pongratz goto out_unlock; 935b63b70d8SShlomo Pongratz 936b63b70d8SShlomo Pongratz /* neigh is obsolete if it was idle for two GC periods */ 937b63b70d8SShlomo Pongratz dt = 2 * arp_tbl.gc_interval; 938b63b70d8SShlomo Pongratz neigh_obsolete = jiffies - dt; 939b63b70d8SShlomo Pongratz /* handle possible race condition */ 940b63b70d8SShlomo Pongratz if (test_bit(IPOIB_STOP_NEIGH_GC, &priv->flags)) 941b63b70d8SShlomo Pongratz goto out_unlock; 942b63b70d8SShlomo Pongratz 943b63b70d8SShlomo Pongratz for (i = 0; i < htbl->size; i++) { 944b63b70d8SShlomo Pongratz struct ipoib_neigh *neigh; 945b63b70d8SShlomo Pongratz struct ipoib_neigh __rcu **np = &htbl->buckets[i]; 946b63b70d8SShlomo Pongratz 947b63b70d8SShlomo Pongratz while ((neigh = rcu_dereference_protected(*np, 948b5120a6eSShlomo Pongratz lockdep_is_held(&priv->lock))) != NULL) { 949b63b70d8SShlomo Pongratz /* was the neigh idle for two GC periods */ 950b63b70d8SShlomo Pongratz if (time_after(neigh_obsolete, neigh->alive)) { 951b63b70d8SShlomo Pongratz rcu_assign_pointer(*np, 952b63b70d8SShlomo Pongratz rcu_dereference_protected(neigh->hnext, 953b5120a6eSShlomo Pongratz lockdep_is_held(&priv->lock))); 954b63b70d8SShlomo Pongratz /* remove from path/mc list */ 955b63b70d8SShlomo Pongratz list_del(&neigh->list); 956b63b70d8SShlomo Pongratz call_rcu(&neigh->rcu, ipoib_neigh_reclaim); 957b63b70d8SShlomo Pongratz } else { 958b63b70d8SShlomo Pongratz np = &neigh->hnext; 959b63b70d8SShlomo Pongratz } 960b63b70d8SShlomo Pongratz 961b63b70d8SShlomo Pongratz } 962b63b70d8SShlomo Pongratz } 963b63b70d8SShlomo Pongratz 964b63b70d8SShlomo Pongratz out_unlock: 965b5120a6eSShlomo Pongratz spin_unlock_irqrestore(&priv->lock, flags); 966b63b70d8SShlomo Pongratz } 967b63b70d8SShlomo Pongratz 968b63b70d8SShlomo Pongratz static void ipoib_reap_neigh(struct work_struct *work) 969b63b70d8SShlomo Pongratz { 970b63b70d8SShlomo Pongratz struct ipoib_dev_priv *priv = 971b63b70d8SShlomo Pongratz container_of(work, struct ipoib_dev_priv, neigh_reap_task.work); 972b63b70d8SShlomo Pongratz 973b63b70d8SShlomo Pongratz __ipoib_reap_neigh(priv); 974b63b70d8SShlomo Pongratz 975b63b70d8SShlomo Pongratz if (!test_bit(IPOIB_STOP_NEIGH_GC, &priv->flags)) 9760b39578bSDoug Ledford queue_delayed_work(priv->wq, &priv->neigh_reap_task, 977b63b70d8SShlomo Pongratz arp_tbl.gc_interval); 978b63b70d8SShlomo Pongratz } 979b63b70d8SShlomo Pongratz 980b63b70d8SShlomo Pongratz 981b63b70d8SShlomo Pongratz static struct ipoib_neigh *ipoib_neigh_ctor(u8 *daddr, 982732a2170SMoni Shoua struct net_device *dev) 983d2e0655eSMichael S. Tsirkin { 984d2e0655eSMichael S. Tsirkin struct ipoib_neigh *neigh; 985d2e0655eSMichael S. Tsirkin 986b63b70d8SShlomo Pongratz neigh = kzalloc(sizeof *neigh, GFP_ATOMIC); 987d2e0655eSMichael S. Tsirkin if (!neigh) 988d2e0655eSMichael S. Tsirkin return NULL; 989d2e0655eSMichael S. Tsirkin 990732a2170SMoni Shoua neigh->dev = dev; 991b63b70d8SShlomo Pongratz memcpy(&neigh->daddr, daddr, sizeof(neigh->daddr)); 99282b39913SRoland Dreier skb_queue_head_init(&neigh->queue); 993b63b70d8SShlomo Pongratz INIT_LIST_HEAD(&neigh->list); 994839fcabaSMichael S. Tsirkin ipoib_cm_set(neigh, NULL); 995b63b70d8SShlomo Pongratz /* one ref on behalf of the caller */ 996b63b70d8SShlomo Pongratz atomic_set(&neigh->refcnt, 1); 997d2e0655eSMichael S. Tsirkin 998d2e0655eSMichael S. Tsirkin return neigh; 999d2e0655eSMichael S. Tsirkin } 1000d2e0655eSMichael S. Tsirkin 1001b63b70d8SShlomo Pongratz struct ipoib_neigh *ipoib_neigh_alloc(u8 *daddr, 1002b63b70d8SShlomo Pongratz struct net_device *dev) 1003d2e0655eSMichael S. Tsirkin { 1004b63b70d8SShlomo Pongratz struct ipoib_dev_priv *priv = netdev_priv(dev); 1005b63b70d8SShlomo Pongratz struct ipoib_neigh_table *ntbl = &priv->ntbl; 1006b63b70d8SShlomo Pongratz struct ipoib_neigh_hash *htbl; 1007b63b70d8SShlomo Pongratz struct ipoib_neigh *neigh; 1008b63b70d8SShlomo Pongratz u32 hash_val; 1009b63b70d8SShlomo Pongratz 1010b63b70d8SShlomo Pongratz htbl = rcu_dereference_protected(ntbl->htbl, 1011b5120a6eSShlomo Pongratz lockdep_is_held(&priv->lock)); 1012b63b70d8SShlomo Pongratz if (!htbl) { 1013b63b70d8SShlomo Pongratz neigh = NULL; 1014b63b70d8SShlomo Pongratz goto out_unlock; 1015b63b70d8SShlomo Pongratz } 1016b63b70d8SShlomo Pongratz 1017b63b70d8SShlomo Pongratz /* need to add a new neigh, but maybe some other thread succeeded? 1018b63b70d8SShlomo Pongratz * recalc hash, maybe hash resize took place so we do a search 1019b63b70d8SShlomo Pongratz */ 1020b63b70d8SShlomo Pongratz hash_val = ipoib_addr_hash(htbl, daddr); 1021b63b70d8SShlomo Pongratz for (neigh = rcu_dereference_protected(htbl->buckets[hash_val], 1022b5120a6eSShlomo Pongratz lockdep_is_held(&priv->lock)); 1023b63b70d8SShlomo Pongratz neigh != NULL; 1024b63b70d8SShlomo Pongratz neigh = rcu_dereference_protected(neigh->hnext, 1025b5120a6eSShlomo Pongratz lockdep_is_held(&priv->lock))) { 1026b63b70d8SShlomo Pongratz if (memcmp(daddr, neigh->daddr, INFINIBAND_ALEN) == 0) { 1027b63b70d8SShlomo Pongratz /* found, take one ref on behalf of the caller */ 1028b63b70d8SShlomo Pongratz if (!atomic_inc_not_zero(&neigh->refcnt)) { 1029b63b70d8SShlomo Pongratz /* deleted */ 1030b63b70d8SShlomo Pongratz neigh = NULL; 1031b63b70d8SShlomo Pongratz break; 1032b63b70d8SShlomo Pongratz } 1033b63b70d8SShlomo Pongratz neigh->alive = jiffies; 1034b63b70d8SShlomo Pongratz goto out_unlock; 1035b63b70d8SShlomo Pongratz } 1036b63b70d8SShlomo Pongratz } 1037b63b70d8SShlomo Pongratz 1038b63b70d8SShlomo Pongratz neigh = ipoib_neigh_ctor(daddr, dev); 1039b63b70d8SShlomo Pongratz if (!neigh) 1040b63b70d8SShlomo Pongratz goto out_unlock; 1041b63b70d8SShlomo Pongratz 1042b63b70d8SShlomo Pongratz /* one ref on behalf of the hash table */ 1043b63b70d8SShlomo Pongratz atomic_inc(&neigh->refcnt); 1044b63b70d8SShlomo Pongratz neigh->alive = jiffies; 1045b63b70d8SShlomo Pongratz /* put in hash */ 1046b63b70d8SShlomo Pongratz rcu_assign_pointer(neigh->hnext, 1047b63b70d8SShlomo Pongratz rcu_dereference_protected(htbl->buckets[hash_val], 1048b5120a6eSShlomo Pongratz lockdep_is_held(&priv->lock))); 1049b63b70d8SShlomo Pongratz rcu_assign_pointer(htbl->buckets[hash_val], neigh); 1050b63b70d8SShlomo Pongratz atomic_inc(&ntbl->entries); 1051b63b70d8SShlomo Pongratz 1052b63b70d8SShlomo Pongratz out_unlock: 1053b63b70d8SShlomo Pongratz 1054b63b70d8SShlomo Pongratz return neigh; 1055b63b70d8SShlomo Pongratz } 1056b63b70d8SShlomo Pongratz 1057b63b70d8SShlomo Pongratz void ipoib_neigh_dtor(struct ipoib_neigh *neigh) 1058b63b70d8SShlomo Pongratz { 1059b63b70d8SShlomo Pongratz /* neigh reference count was dropprd to zero */ 1060b63b70d8SShlomo Pongratz struct net_device *dev = neigh->dev; 1061b63b70d8SShlomo Pongratz struct ipoib_dev_priv *priv = netdev_priv(dev); 10622745b5b7SMichael S. Tsirkin struct sk_buff *skb; 1063b63b70d8SShlomo Pongratz if (neigh->ah) 1064b63b70d8SShlomo Pongratz ipoib_put_ah(neigh->ah); 10652745b5b7SMichael S. Tsirkin while ((skb = __skb_dequeue(&neigh->queue))) { 1066de903512SRoland Dreier ++dev->stats.tx_dropped; 10672745b5b7SMichael S. Tsirkin dev_kfree_skb_any(skb); 10682745b5b7SMichael S. Tsirkin } 1069839fcabaSMichael S. Tsirkin if (ipoib_cm_get(neigh)) 1070839fcabaSMichael S. Tsirkin ipoib_cm_destroy_tx(ipoib_cm_get(neigh)); 1071b63b70d8SShlomo Pongratz ipoib_dbg(netdev_priv(dev), 1072b63b70d8SShlomo Pongratz "neigh free for %06x %pI6\n", 1073b63b70d8SShlomo Pongratz IPOIB_QPN(neigh->daddr), 1074b63b70d8SShlomo Pongratz neigh->daddr + 4); 1075d2e0655eSMichael S. Tsirkin kfree(neigh); 1076b63b70d8SShlomo Pongratz if (atomic_dec_and_test(&priv->ntbl.entries)) { 1077b63b70d8SShlomo Pongratz if (test_bit(IPOIB_NEIGH_TBL_FLUSH, &priv->flags)) 1078b63b70d8SShlomo Pongratz complete(&priv->ntbl.flushed); 1079b63b70d8SShlomo Pongratz } 1080d2e0655eSMichael S. Tsirkin } 1081d2e0655eSMichael S. Tsirkin 1082b63b70d8SShlomo Pongratz static void ipoib_neigh_reclaim(struct rcu_head *rp) 10831da177e4SLinus Torvalds { 1084b63b70d8SShlomo Pongratz /* Called as a result of removal from hash table */ 1085b63b70d8SShlomo Pongratz struct ipoib_neigh *neigh = container_of(rp, struct ipoib_neigh, rcu); 1086b63b70d8SShlomo Pongratz /* note TX context may hold another ref */ 1087b63b70d8SShlomo Pongratz ipoib_neigh_put(neigh); 1088b63b70d8SShlomo Pongratz } 1089b63b70d8SShlomo Pongratz 1090b63b70d8SShlomo Pongratz void ipoib_neigh_free(struct ipoib_neigh *neigh) 1091b63b70d8SShlomo Pongratz { 1092b63b70d8SShlomo Pongratz struct net_device *dev = neigh->dev; 1093b63b70d8SShlomo Pongratz struct ipoib_dev_priv *priv = netdev_priv(dev); 1094b63b70d8SShlomo Pongratz struct ipoib_neigh_table *ntbl = &priv->ntbl; 1095b63b70d8SShlomo Pongratz struct ipoib_neigh_hash *htbl; 1096b63b70d8SShlomo Pongratz struct ipoib_neigh __rcu **np; 1097b63b70d8SShlomo Pongratz struct ipoib_neigh *n; 1098b63b70d8SShlomo Pongratz u32 hash_val; 1099b63b70d8SShlomo Pongratz 1100b63b70d8SShlomo Pongratz htbl = rcu_dereference_protected(ntbl->htbl, 1101b5120a6eSShlomo Pongratz lockdep_is_held(&priv->lock)); 1102b63b70d8SShlomo Pongratz if (!htbl) 1103b5120a6eSShlomo Pongratz return; 1104b63b70d8SShlomo Pongratz 1105b63b70d8SShlomo Pongratz hash_val = ipoib_addr_hash(htbl, neigh->daddr); 1106b63b70d8SShlomo Pongratz np = &htbl->buckets[hash_val]; 1107b63b70d8SShlomo Pongratz for (n = rcu_dereference_protected(*np, 1108b5120a6eSShlomo Pongratz lockdep_is_held(&priv->lock)); 1109b63b70d8SShlomo Pongratz n != NULL; 11106c723a68SShlomo Pongratz n = rcu_dereference_protected(*np, 1111b5120a6eSShlomo Pongratz lockdep_is_held(&priv->lock))) { 1112b63b70d8SShlomo Pongratz if (n == neigh) { 1113b63b70d8SShlomo Pongratz /* found */ 1114b63b70d8SShlomo Pongratz rcu_assign_pointer(*np, 1115b63b70d8SShlomo Pongratz rcu_dereference_protected(neigh->hnext, 1116b5120a6eSShlomo Pongratz lockdep_is_held(&priv->lock))); 111749b8e744SJim Foraker /* remove from parent list */ 111849b8e744SJim Foraker list_del(&neigh->list); 1119b63b70d8SShlomo Pongratz call_rcu(&neigh->rcu, ipoib_neigh_reclaim); 1120b5120a6eSShlomo Pongratz return; 1121b63b70d8SShlomo Pongratz } else { 1122b63b70d8SShlomo Pongratz np = &n->hnext; 1123b63b70d8SShlomo Pongratz } 1124b63b70d8SShlomo Pongratz } 1125b63b70d8SShlomo Pongratz } 1126b63b70d8SShlomo Pongratz 1127b63b70d8SShlomo Pongratz static int ipoib_neigh_hash_init(struct ipoib_dev_priv *priv) 1128b63b70d8SShlomo Pongratz { 1129b63b70d8SShlomo Pongratz struct ipoib_neigh_table *ntbl = &priv->ntbl; 1130b63b70d8SShlomo Pongratz struct ipoib_neigh_hash *htbl; 113152374967SBart Van Assche struct ipoib_neigh __rcu **buckets; 1132b63b70d8SShlomo Pongratz u32 size; 1133b63b70d8SShlomo Pongratz 1134b63b70d8SShlomo Pongratz clear_bit(IPOIB_NEIGH_TBL_FLUSH, &priv->flags); 1135b63b70d8SShlomo Pongratz ntbl->htbl = NULL; 1136b63b70d8SShlomo Pongratz htbl = kzalloc(sizeof(*htbl), GFP_KERNEL); 1137b63b70d8SShlomo Pongratz if (!htbl) 1138b63b70d8SShlomo Pongratz return -ENOMEM; 1139b63b70d8SShlomo Pongratz set_bit(IPOIB_STOP_NEIGH_GC, &priv->flags); 1140b63b70d8SShlomo Pongratz size = roundup_pow_of_two(arp_tbl.gc_thresh3); 1141b63b70d8SShlomo Pongratz buckets = kzalloc(size * sizeof(*buckets), GFP_KERNEL); 1142b63b70d8SShlomo Pongratz if (!buckets) { 1143b63b70d8SShlomo Pongratz kfree(htbl); 1144b63b70d8SShlomo Pongratz return -ENOMEM; 1145b63b70d8SShlomo Pongratz } 1146b63b70d8SShlomo Pongratz htbl->size = size; 1147b63b70d8SShlomo Pongratz htbl->mask = (size - 1); 1148b63b70d8SShlomo Pongratz htbl->buckets = buckets; 114952374967SBart Van Assche RCU_INIT_POINTER(ntbl->htbl, htbl); 115066172c09SShlomo Pongratz htbl->ntbl = ntbl; 1151b63b70d8SShlomo Pongratz atomic_set(&ntbl->entries, 0); 1152b63b70d8SShlomo Pongratz 1153b63b70d8SShlomo Pongratz /* start garbage collection */ 1154b63b70d8SShlomo Pongratz clear_bit(IPOIB_STOP_NEIGH_GC, &priv->flags); 11550b39578bSDoug Ledford queue_delayed_work(priv->wq, &priv->neigh_reap_task, 1156b63b70d8SShlomo Pongratz arp_tbl.gc_interval); 11571da177e4SLinus Torvalds 11581da177e4SLinus Torvalds return 0; 11591da177e4SLinus Torvalds } 11601da177e4SLinus Torvalds 1161b63b70d8SShlomo Pongratz static void neigh_hash_free_rcu(struct rcu_head *head) 1162b63b70d8SShlomo Pongratz { 1163b63b70d8SShlomo Pongratz struct ipoib_neigh_hash *htbl = container_of(head, 1164b63b70d8SShlomo Pongratz struct ipoib_neigh_hash, 1165b63b70d8SShlomo Pongratz rcu); 1166b63b70d8SShlomo Pongratz struct ipoib_neigh __rcu **buckets = htbl->buckets; 116766172c09SShlomo Pongratz struct ipoib_neigh_table *ntbl = htbl->ntbl; 1168b63b70d8SShlomo Pongratz 1169b63b70d8SShlomo Pongratz kfree(buckets); 1170b63b70d8SShlomo Pongratz kfree(htbl); 117166172c09SShlomo Pongratz complete(&ntbl->deleted); 1172b63b70d8SShlomo Pongratz } 1173b63b70d8SShlomo Pongratz 1174b63b70d8SShlomo Pongratz void ipoib_del_neighs_by_gid(struct net_device *dev, u8 *gid) 1175b63b70d8SShlomo Pongratz { 1176b63b70d8SShlomo Pongratz struct ipoib_dev_priv *priv = netdev_priv(dev); 1177b63b70d8SShlomo Pongratz struct ipoib_neigh_table *ntbl = &priv->ntbl; 1178b63b70d8SShlomo Pongratz struct ipoib_neigh_hash *htbl; 1179b63b70d8SShlomo Pongratz unsigned long flags; 1180b63b70d8SShlomo Pongratz int i; 1181b63b70d8SShlomo Pongratz 1182b63b70d8SShlomo Pongratz /* remove all neigh connected to a given path or mcast */ 1183b5120a6eSShlomo Pongratz spin_lock_irqsave(&priv->lock, flags); 1184b63b70d8SShlomo Pongratz 1185b63b70d8SShlomo Pongratz htbl = rcu_dereference_protected(ntbl->htbl, 1186b5120a6eSShlomo Pongratz lockdep_is_held(&priv->lock)); 1187b63b70d8SShlomo Pongratz 1188b63b70d8SShlomo Pongratz if (!htbl) 1189b63b70d8SShlomo Pongratz goto out_unlock; 1190b63b70d8SShlomo Pongratz 1191b63b70d8SShlomo Pongratz for (i = 0; i < htbl->size; i++) { 1192b63b70d8SShlomo Pongratz struct ipoib_neigh *neigh; 1193b63b70d8SShlomo Pongratz struct ipoib_neigh __rcu **np = &htbl->buckets[i]; 1194b63b70d8SShlomo Pongratz 1195b63b70d8SShlomo Pongratz while ((neigh = rcu_dereference_protected(*np, 1196b5120a6eSShlomo Pongratz lockdep_is_held(&priv->lock))) != NULL) { 1197b63b70d8SShlomo Pongratz /* delete neighs belong to this parent */ 1198b63b70d8SShlomo Pongratz if (!memcmp(gid, neigh->daddr + 4, sizeof (union ib_gid))) { 1199b63b70d8SShlomo Pongratz rcu_assign_pointer(*np, 1200b63b70d8SShlomo Pongratz rcu_dereference_protected(neigh->hnext, 1201b5120a6eSShlomo Pongratz lockdep_is_held(&priv->lock))); 1202b63b70d8SShlomo Pongratz /* remove from parent list */ 1203b63b70d8SShlomo Pongratz list_del(&neigh->list); 1204b63b70d8SShlomo Pongratz call_rcu(&neigh->rcu, ipoib_neigh_reclaim); 1205b63b70d8SShlomo Pongratz } else { 1206b63b70d8SShlomo Pongratz np = &neigh->hnext; 1207b63b70d8SShlomo Pongratz } 1208b63b70d8SShlomo Pongratz 1209b63b70d8SShlomo Pongratz } 1210b63b70d8SShlomo Pongratz } 1211b63b70d8SShlomo Pongratz out_unlock: 1212b5120a6eSShlomo Pongratz spin_unlock_irqrestore(&priv->lock, flags); 1213b63b70d8SShlomo Pongratz } 1214b63b70d8SShlomo Pongratz 1215b63b70d8SShlomo Pongratz static void ipoib_flush_neighs(struct ipoib_dev_priv *priv) 1216b63b70d8SShlomo Pongratz { 1217b63b70d8SShlomo Pongratz struct ipoib_neigh_table *ntbl = &priv->ntbl; 1218b63b70d8SShlomo Pongratz struct ipoib_neigh_hash *htbl; 1219b63b70d8SShlomo Pongratz unsigned long flags; 122066172c09SShlomo Pongratz int i, wait_flushed = 0; 1221b63b70d8SShlomo Pongratz 122266172c09SShlomo Pongratz init_completion(&priv->ntbl.flushed); 1223b63b70d8SShlomo Pongratz 1224b5120a6eSShlomo Pongratz spin_lock_irqsave(&priv->lock, flags); 1225b63b70d8SShlomo Pongratz 1226b63b70d8SShlomo Pongratz htbl = rcu_dereference_protected(ntbl->htbl, 1227b5120a6eSShlomo Pongratz lockdep_is_held(&priv->lock)); 1228b63b70d8SShlomo Pongratz if (!htbl) 1229b63b70d8SShlomo Pongratz goto out_unlock; 1230b63b70d8SShlomo Pongratz 123166172c09SShlomo Pongratz wait_flushed = atomic_read(&priv->ntbl.entries); 123266172c09SShlomo Pongratz if (!wait_flushed) 123366172c09SShlomo Pongratz goto free_htbl; 123466172c09SShlomo Pongratz 1235b63b70d8SShlomo Pongratz for (i = 0; i < htbl->size; i++) { 1236b63b70d8SShlomo Pongratz struct ipoib_neigh *neigh; 1237b63b70d8SShlomo Pongratz struct ipoib_neigh __rcu **np = &htbl->buckets[i]; 1238b63b70d8SShlomo Pongratz 1239b63b70d8SShlomo Pongratz while ((neigh = rcu_dereference_protected(*np, 1240b5120a6eSShlomo Pongratz lockdep_is_held(&priv->lock))) != NULL) { 1241b63b70d8SShlomo Pongratz rcu_assign_pointer(*np, 1242b63b70d8SShlomo Pongratz rcu_dereference_protected(neigh->hnext, 1243b5120a6eSShlomo Pongratz lockdep_is_held(&priv->lock))); 1244b63b70d8SShlomo Pongratz /* remove from path/mc list */ 1245b63b70d8SShlomo Pongratz list_del(&neigh->list); 1246b63b70d8SShlomo Pongratz call_rcu(&neigh->rcu, ipoib_neigh_reclaim); 1247b63b70d8SShlomo Pongratz } 1248b63b70d8SShlomo Pongratz } 1249b63b70d8SShlomo Pongratz 125066172c09SShlomo Pongratz free_htbl: 1251b63b70d8SShlomo Pongratz rcu_assign_pointer(ntbl->htbl, NULL); 1252b63b70d8SShlomo Pongratz call_rcu(&htbl->rcu, neigh_hash_free_rcu); 1253b63b70d8SShlomo Pongratz 1254b63b70d8SShlomo Pongratz out_unlock: 1255b5120a6eSShlomo Pongratz spin_unlock_irqrestore(&priv->lock, flags); 125666172c09SShlomo Pongratz if (wait_flushed) 125766172c09SShlomo Pongratz wait_for_completion(&priv->ntbl.flushed); 1258b63b70d8SShlomo Pongratz } 1259b63b70d8SShlomo Pongratz 1260b63b70d8SShlomo Pongratz static void ipoib_neigh_hash_uninit(struct net_device *dev) 1261b63b70d8SShlomo Pongratz { 1262b63b70d8SShlomo Pongratz struct ipoib_dev_priv *priv = netdev_priv(dev); 1263b63b70d8SShlomo Pongratz int stopped; 1264b63b70d8SShlomo Pongratz 1265b63b70d8SShlomo Pongratz ipoib_dbg(priv, "ipoib_neigh_hash_uninit\n"); 126666172c09SShlomo Pongratz init_completion(&priv->ntbl.deleted); 1267b63b70d8SShlomo Pongratz set_bit(IPOIB_NEIGH_TBL_FLUSH, &priv->flags); 1268b63b70d8SShlomo Pongratz 1269b63b70d8SShlomo Pongratz /* Stop GC if called at init fail need to cancel work */ 1270b63b70d8SShlomo Pongratz stopped = test_and_set_bit(IPOIB_STOP_NEIGH_GC, &priv->flags); 1271b63b70d8SShlomo Pongratz if (!stopped) 1272b63b70d8SShlomo Pongratz cancel_delayed_work(&priv->neigh_reap_task); 1273b63b70d8SShlomo Pongratz 1274b63b70d8SShlomo Pongratz ipoib_flush_neighs(priv); 127566172c09SShlomo Pongratz 127666172c09SShlomo Pongratz wait_for_completion(&priv->ntbl.deleted); 1277b63b70d8SShlomo Pongratz } 1278b63b70d8SShlomo Pongratz 1279b63b70d8SShlomo Pongratz 12801da177e4SLinus Torvalds int ipoib_dev_init(struct net_device *dev, struct ib_device *ca, int port) 12811da177e4SLinus Torvalds { 12821da177e4SLinus Torvalds struct ipoib_dev_priv *priv = netdev_priv(dev); 12831da177e4SLinus Torvalds 12841da177e4SLinus Torvalds /* Allocate RX/TX "rings" to hold queued skbs */ 12850f485251SShirley Ma priv->rx_ring = kzalloc(ipoib_recvq_size * sizeof *priv->rx_ring, 12861da177e4SLinus Torvalds GFP_KERNEL); 12871da177e4SLinus Torvalds if (!priv->rx_ring) { 12881da177e4SLinus Torvalds printk(KERN_WARNING "%s: failed to allocate RX ring (%d entries)\n", 12890f485251SShirley Ma ca->name, ipoib_recvq_size); 1290be7aa663SDoug Ledford goto out; 12911da177e4SLinus Torvalds } 12921da177e4SLinus Torvalds 1293948579cdSJoe Perches priv->tx_ring = vzalloc(ipoib_sendq_size * sizeof *priv->tx_ring); 12941da177e4SLinus Torvalds if (!priv->tx_ring) { 12951da177e4SLinus Torvalds printk(KERN_WARNING "%s: failed to allocate TX ring (%d entries)\n", 12960f485251SShirley Ma ca->name, ipoib_sendq_size); 12971da177e4SLinus Torvalds goto out_rx_ring_cleanup; 12981da177e4SLinus Torvalds } 12991da177e4SLinus Torvalds 13001b524963SMichael S. Tsirkin /* priv->tx_head, tx_tail & tx_outstanding are already 0 */ 13011da177e4SLinus Torvalds 13021da177e4SLinus Torvalds if (ipoib_ib_dev_init(dev, ca, port)) 13031da177e4SLinus Torvalds goto out_tx_ring_cleanup; 13041da177e4SLinus Torvalds 1305be7aa663SDoug Ledford /* 1306be7aa663SDoug Ledford * Must be after ipoib_ib_dev_init so we can allocate a per 1307be7aa663SDoug Ledford * device wq there and use it here 1308be7aa663SDoug Ledford */ 1309be7aa663SDoug Ledford if (ipoib_neigh_hash_init(priv) < 0) 1310be7aa663SDoug Ledford goto out_dev_uninit; 1311be7aa663SDoug Ledford 13121da177e4SLinus Torvalds return 0; 13131da177e4SLinus Torvalds 1314be7aa663SDoug Ledford out_dev_uninit: 1315be7aa663SDoug Ledford ipoib_ib_dev_cleanup(dev); 1316be7aa663SDoug Ledford 13171da177e4SLinus Torvalds out_tx_ring_cleanup: 131810313cbbSRoland Dreier vfree(priv->tx_ring); 13191da177e4SLinus Torvalds 13201da177e4SLinus Torvalds out_rx_ring_cleanup: 13211da177e4SLinus Torvalds kfree(priv->rx_ring); 13221da177e4SLinus Torvalds 13231da177e4SLinus Torvalds out: 13241da177e4SLinus Torvalds return -ENOMEM; 13251da177e4SLinus Torvalds } 13261da177e4SLinus Torvalds 13271da177e4SLinus Torvalds void ipoib_dev_cleanup(struct net_device *dev) 13281da177e4SLinus Torvalds { 13291da177e4SLinus Torvalds struct ipoib_dev_priv *priv = netdev_priv(dev), *cpriv, *tcpriv; 13309baa0b03SOr Gerlitz LIST_HEAD(head); 13319baa0b03SOr Gerlitz 13329baa0b03SOr Gerlitz ASSERT_RTNL(); 13331da177e4SLinus Torvalds 13341732b0efSRoland Dreier ipoib_delete_debug_files(dev); 13351da177e4SLinus Torvalds 13361da177e4SLinus Torvalds /* Delete any child interfaces first */ 13371da177e4SLinus Torvalds list_for_each_entry_safe(cpriv, tcpriv, &priv->child_intfs, list) { 1338b63b70d8SShlomo Pongratz /* Stop GC on child */ 1339b63b70d8SShlomo Pongratz set_bit(IPOIB_STOP_NEIGH_GC, &cpriv->flags); 1340b63b70d8SShlomo Pongratz cancel_delayed_work(&cpriv->neigh_reap_task); 13419baa0b03SOr Gerlitz unregister_netdevice_queue(cpriv->dev, &head); 13421da177e4SLinus Torvalds } 13439baa0b03SOr Gerlitz unregister_netdevice_many(&head); 13441da177e4SLinus Torvalds 1345be7aa663SDoug Ledford /* 1346be7aa663SDoug Ledford * Must be before ipoib_ib_dev_cleanup or we delete an in use 1347be7aa663SDoug Ledford * work queue 1348be7aa663SDoug Ledford */ 1349be7aa663SDoug Ledford ipoib_neigh_hash_uninit(dev); 1350be7aa663SDoug Ledford 13511da177e4SLinus Torvalds ipoib_ib_dev_cleanup(dev); 13521da177e4SLinus Torvalds 13531da177e4SLinus Torvalds kfree(priv->rx_ring); 135410313cbbSRoland Dreier vfree(priv->tx_ring); 135592a6b34bSHal Rosenstock 135692a6b34bSHal Rosenstock priv->rx_ring = NULL; 13571da177e4SLinus Torvalds priv->tx_ring = NULL; 13581da177e4SLinus Torvalds } 13591da177e4SLinus Torvalds 13603b04dddeSStephen Hemminger static const struct header_ops ipoib_header_ops = { 13613b04dddeSStephen Hemminger .create = ipoib_hard_header, 13623b04dddeSStephen Hemminger }; 13633b04dddeSStephen Hemminger 1364fe8114e8SStephen Hemminger static const struct net_device_ops ipoib_netdev_ops = { 13659baa0b03SOr Gerlitz .ndo_uninit = ipoib_uninit, 1366fe8114e8SStephen Hemminger .ndo_open = ipoib_open, 1367fe8114e8SStephen Hemminger .ndo_stop = ipoib_stop, 1368fe8114e8SStephen Hemminger .ndo_change_mtu = ipoib_change_mtu, 13693d96c74dSMichał Mirosław .ndo_fix_features = ipoib_fix_features, 1370fe8114e8SStephen Hemminger .ndo_start_xmit = ipoib_start_xmit, 1371fe8114e8SStephen Hemminger .ndo_tx_timeout = ipoib_timeout, 1372afc4b13dSJiri Pirko .ndo_set_rx_mode = ipoib_set_mcast_list, 13735aa7add8SNicolas Dichtel .ndo_get_iflink = ipoib_get_iflink, 1374fe8114e8SStephen Hemminger }; 1375fe8114e8SStephen Hemminger 13769baa0b03SOr Gerlitz void ipoib_setup(struct net_device *dev) 13771da177e4SLinus Torvalds { 13781da177e4SLinus Torvalds struct ipoib_dev_priv *priv = netdev_priv(dev); 13791da177e4SLinus Torvalds 1380fe8114e8SStephen Hemminger dev->netdev_ops = &ipoib_netdev_ops; 13813b04dddeSStephen Hemminger dev->header_ops = &ipoib_header_ops; 1382bea3348eSStephen Hemminger 138382c24c18SEli Cohen ipoib_set_ethtool_ops(dev); 138482c24c18SEli Cohen 13857f1a3867SMichal Schmidt netif_napi_add(dev, &priv->napi, ipoib_poll, NAPI_POLL_WEIGHT); 13861da177e4SLinus Torvalds 13871da177e4SLinus Torvalds dev->watchdog_timeo = HZ; 13881da177e4SLinus Torvalds 13891da177e4SLinus Torvalds dev->flags |= IFF_BROADCAST | IFF_MULTICAST; 13901da177e4SLinus Torvalds 1391936d7de3SRoland Dreier dev->hard_header_len = IPOIB_ENCAP_LEN; 13921da177e4SLinus Torvalds dev->addr_len = INFINIBAND_ALEN; 13931da177e4SLinus Torvalds dev->type = ARPHRD_INFINIBAND; 13940f485251SShirley Ma dev->tx_queue_len = ipoib_sendq_size * 2; 1395eb14032fSEli Cohen dev->features = (NETIF_F_VLAN_CHALLENGED | 1396eb14032fSEli Cohen NETIF_F_HIGHDMA); 139702875878SEric Dumazet netif_keep_dst(dev); 13981da177e4SLinus Torvalds 13991da177e4SLinus Torvalds memcpy(dev->broadcast, ipv4_bcast_addr, INFINIBAND_ALEN); 14001da177e4SLinus Torvalds 14011da177e4SLinus Torvalds priv->dev = dev; 14021da177e4SLinus Torvalds 14031da177e4SLinus Torvalds spin_lock_init(&priv->lock); 14041da177e4SLinus Torvalds 1405f47944ccSErez Shitrit init_rwsem(&priv->vlan_rwsem); 14061da177e4SLinus Torvalds 14071da177e4SLinus Torvalds INIT_LIST_HEAD(&priv->path_list); 14081da177e4SLinus Torvalds INIT_LIST_HEAD(&priv->child_intfs); 14091da177e4SLinus Torvalds INIT_LIST_HEAD(&priv->dead_ahs); 14101da177e4SLinus Torvalds INIT_LIST_HEAD(&priv->multicast_list); 14111da177e4SLinus Torvalds 1412c4028958SDavid Howells INIT_DELAYED_WORK(&priv->mcast_task, ipoib_mcast_join_task); 1413e8224e4bSYossi Etigin INIT_WORK(&priv->carrier_on_task, ipoib_mcast_carrier_on_task); 1414ee1e2c82SMoni Shoua INIT_WORK(&priv->flush_light, ipoib_ib_dev_flush_light); 1415ee1e2c82SMoni Shoua INIT_WORK(&priv->flush_normal, ipoib_ib_dev_flush_normal); 1416ee1e2c82SMoni Shoua INIT_WORK(&priv->flush_heavy, ipoib_ib_dev_flush_heavy); 1417c4028958SDavid Howells INIT_WORK(&priv->restart_task, ipoib_mcast_restart_task); 1418c4028958SDavid Howells INIT_DELAYED_WORK(&priv->ah_reap_task, ipoib_reap_ah); 1419b63b70d8SShlomo Pongratz INIT_DELAYED_WORK(&priv->neigh_reap_task, ipoib_reap_neigh); 14201da177e4SLinus Torvalds } 14211da177e4SLinus Torvalds 14221da177e4SLinus Torvalds struct ipoib_dev_priv *ipoib_intf_alloc(const char *name) 14231da177e4SLinus Torvalds { 14241da177e4SLinus Torvalds struct net_device *dev; 14251da177e4SLinus Torvalds 14261da177e4SLinus Torvalds dev = alloc_netdev((int)sizeof(struct ipoib_dev_priv), name, 1427c835a677STom Gundersen NET_NAME_UNKNOWN, ipoib_setup); 14281da177e4SLinus Torvalds if (!dev) 14291da177e4SLinus Torvalds return NULL; 14301da177e4SLinus Torvalds 14311da177e4SLinus Torvalds return netdev_priv(dev); 14321da177e4SLinus Torvalds } 14331da177e4SLinus Torvalds 143443cb76d9SGreg Kroah-Hartman static ssize_t show_pkey(struct device *dev, 143543cb76d9SGreg Kroah-Hartman struct device_attribute *attr, char *buf) 14361da177e4SLinus Torvalds { 143743cb76d9SGreg Kroah-Hartman struct ipoib_dev_priv *priv = netdev_priv(to_net_dev(dev)); 14381da177e4SLinus Torvalds 14391da177e4SLinus Torvalds return sprintf(buf, "0x%04x\n", priv->pkey); 14401da177e4SLinus Torvalds } 144143cb76d9SGreg Kroah-Hartman static DEVICE_ATTR(pkey, S_IRUGO, show_pkey, NULL); 14421da177e4SLinus Torvalds 1443335a64a5SOr Gerlitz static ssize_t show_umcast(struct device *dev, 1444335a64a5SOr Gerlitz struct device_attribute *attr, char *buf) 1445335a64a5SOr Gerlitz { 1446335a64a5SOr Gerlitz struct ipoib_dev_priv *priv = netdev_priv(to_net_dev(dev)); 1447335a64a5SOr Gerlitz 1448335a64a5SOr Gerlitz return sprintf(buf, "%d\n", test_bit(IPOIB_FLAG_UMCAST, &priv->flags)); 1449335a64a5SOr Gerlitz } 1450335a64a5SOr Gerlitz 1451862096a8SOr Gerlitz void ipoib_set_umcast(struct net_device *ndev, int umcast_val) 1452335a64a5SOr Gerlitz { 1453862096a8SOr Gerlitz struct ipoib_dev_priv *priv = netdev_priv(ndev); 1454335a64a5SOr Gerlitz 1455335a64a5SOr Gerlitz if (umcast_val > 0) { 1456335a64a5SOr Gerlitz set_bit(IPOIB_FLAG_UMCAST, &priv->flags); 1457335a64a5SOr Gerlitz ipoib_warn(priv, "ignoring multicast groups joined directly " 1458335a64a5SOr Gerlitz "by userspace\n"); 1459335a64a5SOr Gerlitz } else 1460335a64a5SOr Gerlitz clear_bit(IPOIB_FLAG_UMCAST, &priv->flags); 1461862096a8SOr Gerlitz } 1462862096a8SOr Gerlitz 1463862096a8SOr Gerlitz static ssize_t set_umcast(struct device *dev, 1464862096a8SOr Gerlitz struct device_attribute *attr, 1465862096a8SOr Gerlitz const char *buf, size_t count) 1466862096a8SOr Gerlitz { 1467862096a8SOr Gerlitz unsigned long umcast_val = simple_strtoul(buf, NULL, 0); 1468862096a8SOr Gerlitz 1469862096a8SOr Gerlitz ipoib_set_umcast(to_net_dev(dev), umcast_val); 1470335a64a5SOr Gerlitz 1471335a64a5SOr Gerlitz return count; 1472335a64a5SOr Gerlitz } 1473335a64a5SOr Gerlitz static DEVICE_ATTR(umcast, S_IWUSR | S_IRUGO, show_umcast, set_umcast); 1474335a64a5SOr Gerlitz 1475335a64a5SOr Gerlitz int ipoib_add_umcast_attr(struct net_device *dev) 1476335a64a5SOr Gerlitz { 1477335a64a5SOr Gerlitz return device_create_file(&dev->dev, &dev_attr_umcast); 1478335a64a5SOr Gerlitz } 1479335a64a5SOr Gerlitz 148043cb76d9SGreg Kroah-Hartman static ssize_t create_child(struct device *dev, 148143cb76d9SGreg Kroah-Hartman struct device_attribute *attr, 14821da177e4SLinus Torvalds const char *buf, size_t count) 14831da177e4SLinus Torvalds { 14841da177e4SLinus Torvalds int pkey; 14851da177e4SLinus Torvalds int ret; 14861da177e4SLinus Torvalds 14871da177e4SLinus Torvalds if (sscanf(buf, "%i", &pkey) != 1) 14881da177e4SLinus Torvalds return -EINVAL; 14891da177e4SLinus Torvalds 14903d790a4cSOr Gerlitz if (pkey <= 0 || pkey > 0xffff || pkey == 0x8000) 14911da177e4SLinus Torvalds return -EINVAL; 14921da177e4SLinus Torvalds 14934ce05937SRoland Dreier /* 14944ce05937SRoland Dreier * Set the full membership bit, so that we join the right 14954ce05937SRoland Dreier * broadcast group, etc. 14964ce05937SRoland Dreier */ 14974ce05937SRoland Dreier pkey |= 0x8000; 14984ce05937SRoland Dreier 149943cb76d9SGreg Kroah-Hartman ret = ipoib_vlan_add(to_net_dev(dev), pkey); 15001da177e4SLinus Torvalds 15011da177e4SLinus Torvalds return ret ? ret : count; 15021da177e4SLinus Torvalds } 15037a52b34bSOr Gerlitz static DEVICE_ATTR(create_child, S_IWUSR, NULL, create_child); 15041da177e4SLinus Torvalds 150543cb76d9SGreg Kroah-Hartman static ssize_t delete_child(struct device *dev, 150643cb76d9SGreg Kroah-Hartman struct device_attribute *attr, 15071da177e4SLinus Torvalds const char *buf, size_t count) 15081da177e4SLinus Torvalds { 15091da177e4SLinus Torvalds int pkey; 15101da177e4SLinus Torvalds int ret; 15111da177e4SLinus Torvalds 15121da177e4SLinus Torvalds if (sscanf(buf, "%i", &pkey) != 1) 15131da177e4SLinus Torvalds return -EINVAL; 15141da177e4SLinus Torvalds 15151da177e4SLinus Torvalds if (pkey < 0 || pkey > 0xffff) 15161da177e4SLinus Torvalds return -EINVAL; 15171da177e4SLinus Torvalds 151843cb76d9SGreg Kroah-Hartman ret = ipoib_vlan_delete(to_net_dev(dev), pkey); 15191da177e4SLinus Torvalds 15201da177e4SLinus Torvalds return ret ? ret : count; 15211da177e4SLinus Torvalds 15221da177e4SLinus Torvalds } 15237a52b34bSOr Gerlitz static DEVICE_ATTR(delete_child, S_IWUSR, NULL, delete_child); 15241da177e4SLinus Torvalds 15251da177e4SLinus Torvalds int ipoib_add_pkey_attr(struct net_device *dev) 15261da177e4SLinus Torvalds { 152743cb76d9SGreg Kroah-Hartman return device_create_file(&dev->dev, &dev_attr_pkey); 15281da177e4SLinus Torvalds } 15291da177e4SLinus Torvalds 153083bb63f6SOr Gerlitz int ipoib_set_dev_features(struct ipoib_dev_priv *priv, struct ib_device *hca) 153183bb63f6SOr Gerlitz { 153283bb63f6SOr Gerlitz struct ib_device_attr *device_attr; 153383bb63f6SOr Gerlitz int result = -ENOMEM; 153483bb63f6SOr Gerlitz 153583bb63f6SOr Gerlitz device_attr = kmalloc(sizeof *device_attr, GFP_KERNEL); 153683bb63f6SOr Gerlitz if (!device_attr) { 153783bb63f6SOr Gerlitz printk(KERN_WARNING "%s: allocation of %zu bytes failed\n", 153883bb63f6SOr Gerlitz hca->name, sizeof *device_attr); 153983bb63f6SOr Gerlitz return result; 154083bb63f6SOr Gerlitz } 154183bb63f6SOr Gerlitz 154283bb63f6SOr Gerlitz result = ib_query_device(hca, device_attr); 154383bb63f6SOr Gerlitz if (result) { 154483bb63f6SOr Gerlitz printk(KERN_WARNING "%s: ib_query_device failed (ret = %d)\n", 154583bb63f6SOr Gerlitz hca->name, result); 154683bb63f6SOr Gerlitz kfree(device_attr); 154783bb63f6SOr Gerlitz return result; 154883bb63f6SOr Gerlitz } 154983bb63f6SOr Gerlitz priv->hca_caps = device_attr->device_cap_flags; 155083bb63f6SOr Gerlitz 155183bb63f6SOr Gerlitz kfree(device_attr); 155283bb63f6SOr Gerlitz 155383bb63f6SOr Gerlitz if (priv->hca_caps & IB_DEVICE_UD_IP_CSUM) { 15543d96c74dSMichał Mirosław priv->dev->hw_features = NETIF_F_SG | 15553d96c74dSMichał Mirosław NETIF_F_IP_CSUM | NETIF_F_RXCSUM; 15563d96c74dSMichał Mirosław 15573d96c74dSMichał Mirosław if (priv->hca_caps & IB_DEVICE_UD_TSO) 15583d96c74dSMichał Mirosław priv->dev->hw_features |= NETIF_F_TSO; 15593d96c74dSMichał Mirosław 15603d96c74dSMichał Mirosław priv->dev->features |= priv->dev->hw_features; 156183bb63f6SOr Gerlitz } 156283bb63f6SOr Gerlitz 156383bb63f6SOr Gerlitz return 0; 156483bb63f6SOr Gerlitz } 156583bb63f6SOr Gerlitz 15661da177e4SLinus Torvalds static struct net_device *ipoib_add_port(const char *format, 15671da177e4SLinus Torvalds struct ib_device *hca, u8 port) 15681da177e4SLinus Torvalds { 15691da177e4SLinus Torvalds struct ipoib_dev_priv *priv; 1570bc7b3a36SShirley Ma struct ib_port_attr attr; 15711da177e4SLinus Torvalds int result = -ENOMEM; 15721da177e4SLinus Torvalds 15731da177e4SLinus Torvalds priv = ipoib_intf_alloc(format); 15741da177e4SLinus Torvalds if (!priv) 15751da177e4SLinus Torvalds goto alloc_mem_failed; 15761da177e4SLinus Torvalds 15771da177e4SLinus Torvalds SET_NETDEV_DEV(priv->dev, hca->dma_device); 1578c3aa9b18SEli Cohen priv->dev->dev_id = port - 1; 15791da177e4SLinus Torvalds 158058e9cc90SAmir Vadai result = ib_query_port(hca, port, &attr); 158158e9cc90SAmir Vadai if (!result) 1582bc7b3a36SShirley Ma priv->max_ib_mtu = ib_mtu_enum_to_int(attr.max_mtu); 1583bc7b3a36SShirley Ma else { 1584bc7b3a36SShirley Ma printk(KERN_WARNING "%s: ib_query_port %d failed\n", 1585bc7b3a36SShirley Ma hca->name, port); 1586bc7b3a36SShirley Ma goto device_init_failed; 1587bc7b3a36SShirley Ma } 1588bc7b3a36SShirley Ma 1589bc7b3a36SShirley Ma /* MTU will be reset when mcast join happens */ 1590bc7b3a36SShirley Ma priv->dev->mtu = IPOIB_UD_MTU(priv->max_ib_mtu); 1591bc7b3a36SShirley Ma priv->mcast_mtu = priv->admin_mtu = priv->dev->mtu; 1592bc7b3a36SShirley Ma 1593596b9b68SDavid Miller priv->dev->neigh_priv_len = sizeof(struct ipoib_neigh); 1594596b9b68SDavid Miller 15951da177e4SLinus Torvalds result = ib_query_pkey(hca, port, 0, &priv->pkey); 15961da177e4SLinus Torvalds if (result) { 15971da177e4SLinus Torvalds printk(KERN_WARNING "%s: ib_query_pkey port %d failed (ret = %d)\n", 15981da177e4SLinus Torvalds hca->name, port, result); 1599ca6de177SEli Cohen goto device_init_failed; 16001da177e4SLinus Torvalds } 16011da177e4SLinus Torvalds 160258e9cc90SAmir Vadai result = ipoib_set_dev_features(priv, hca); 160358e9cc90SAmir Vadai if (result) 16046046136cSEli Cohen goto device_init_failed; 1605af40da89SVladimir Sokolovsky 16064ce05937SRoland Dreier /* 16074ce05937SRoland Dreier * Set the full membership bit, so that we join the right 16084ce05937SRoland Dreier * broadcast group, etc. 16094ce05937SRoland Dreier */ 16104ce05937SRoland Dreier priv->pkey |= 0x8000; 16114ce05937SRoland Dreier 16121da177e4SLinus Torvalds priv->dev->broadcast[8] = priv->pkey >> 8; 16131da177e4SLinus Torvalds priv->dev->broadcast[9] = priv->pkey & 0xff; 16141da177e4SLinus Torvalds 16151da177e4SLinus Torvalds result = ib_query_gid(hca, port, 0, &priv->local_gid); 16161da177e4SLinus Torvalds if (result) { 16171da177e4SLinus Torvalds printk(KERN_WARNING "%s: ib_query_gid port %d failed (ret = %d)\n", 16181da177e4SLinus Torvalds hca->name, port, result); 1619ca6de177SEli Cohen goto device_init_failed; 16201da177e4SLinus Torvalds } else 16211da177e4SLinus Torvalds memcpy(priv->dev->dev_addr + 4, priv->local_gid.raw, sizeof (union ib_gid)); 16221da177e4SLinus Torvalds 16231da177e4SLinus Torvalds result = ipoib_dev_init(priv->dev, hca, port); 16241da177e4SLinus Torvalds if (result < 0) { 16251da177e4SLinus Torvalds printk(KERN_WARNING "%s: failed to initialize port %d (ret = %d)\n", 16261da177e4SLinus Torvalds hca->name, port, result); 16271da177e4SLinus Torvalds goto device_init_failed; 16281da177e4SLinus Torvalds } 16291da177e4SLinus Torvalds 16301da177e4SLinus Torvalds INIT_IB_EVENT_HANDLER(&priv->event_handler, 16311da177e4SLinus Torvalds priv->ca, ipoib_event); 16321da177e4SLinus Torvalds result = ib_register_event_handler(&priv->event_handler); 16331da177e4SLinus Torvalds if (result < 0) { 16341da177e4SLinus Torvalds printk(KERN_WARNING "%s: ib_register_event_handler failed for " 16351da177e4SLinus Torvalds "port %d (ret = %d)\n", 16361da177e4SLinus Torvalds hca->name, port, result); 16371da177e4SLinus Torvalds goto event_failed; 16381da177e4SLinus Torvalds } 16391da177e4SLinus Torvalds 16401da177e4SLinus Torvalds result = register_netdev(priv->dev); 16411da177e4SLinus Torvalds if (result) { 16421da177e4SLinus Torvalds printk(KERN_WARNING "%s: couldn't register ipoib port %d; error %d\n", 16431da177e4SLinus Torvalds hca->name, port, result); 16441da177e4SLinus Torvalds goto register_failed; 16451da177e4SLinus Torvalds } 16461da177e4SLinus Torvalds 16471732b0efSRoland Dreier ipoib_create_debug_files(priv->dev); 16481da177e4SLinus Torvalds 1649839fcabaSMichael S. Tsirkin if (ipoib_cm_add_mode_attr(priv->dev)) 1650839fcabaSMichael S. Tsirkin goto sysfs_failed; 16511da177e4SLinus Torvalds if (ipoib_add_pkey_attr(priv->dev)) 16521da177e4SLinus Torvalds goto sysfs_failed; 1653335a64a5SOr Gerlitz if (ipoib_add_umcast_attr(priv->dev)) 1654335a64a5SOr Gerlitz goto sysfs_failed; 165543cb76d9SGreg Kroah-Hartman if (device_create_file(&priv->dev->dev, &dev_attr_create_child)) 16561da177e4SLinus Torvalds goto sysfs_failed; 165743cb76d9SGreg Kroah-Hartman if (device_create_file(&priv->dev->dev, &dev_attr_delete_child)) 16581da177e4SLinus Torvalds goto sysfs_failed; 16591da177e4SLinus Torvalds 16601da177e4SLinus Torvalds return priv->dev; 16611da177e4SLinus Torvalds 16621da177e4SLinus Torvalds sysfs_failed: 16631732b0efSRoland Dreier ipoib_delete_debug_files(priv->dev); 16641da177e4SLinus Torvalds unregister_netdev(priv->dev); 16651da177e4SLinus Torvalds 16661da177e4SLinus Torvalds register_failed: 16671da177e4SLinus Torvalds ib_unregister_event_handler(&priv->event_handler); 16680b39578bSDoug Ledford flush_workqueue(ipoib_workqueue); 1669b63b70d8SShlomo Pongratz /* Stop GC if started before flush */ 1670b63b70d8SShlomo Pongratz set_bit(IPOIB_STOP_NEIGH_GC, &priv->flags); 1671b63b70d8SShlomo Pongratz cancel_delayed_work(&priv->neigh_reap_task); 16720b39578bSDoug Ledford flush_workqueue(priv->wq); 16731da177e4SLinus Torvalds 16741da177e4SLinus Torvalds event_failed: 16751da177e4SLinus Torvalds ipoib_dev_cleanup(priv->dev); 16761da177e4SLinus Torvalds 16771da177e4SLinus Torvalds device_init_failed: 16781da177e4SLinus Torvalds free_netdev(priv->dev); 16791da177e4SLinus Torvalds 16801da177e4SLinus Torvalds alloc_mem_failed: 16811da177e4SLinus Torvalds return ERR_PTR(result); 16821da177e4SLinus Torvalds } 16831da177e4SLinus Torvalds 16841da177e4SLinus Torvalds static void ipoib_add_one(struct ib_device *device) 16851da177e4SLinus Torvalds { 16861da177e4SLinus Torvalds struct list_head *dev_list; 16871da177e4SLinus Torvalds struct net_device *dev; 16881da177e4SLinus Torvalds struct ipoib_dev_priv *priv; 16894139032bSHal Rosenstock int p; 16908e37ab68SMichael Wang int count = 0; 169107ebafbaSTom Tucker 16921da177e4SLinus Torvalds dev_list = kmalloc(sizeof *dev_list, GFP_KERNEL); 16931da177e4SLinus Torvalds if (!dev_list) 16941da177e4SLinus Torvalds return; 16951da177e4SLinus Torvalds 16961da177e4SLinus Torvalds INIT_LIST_HEAD(dev_list); 16971da177e4SLinus Torvalds 16984139032bSHal Rosenstock for (p = rdma_start_port(device); p <= rdma_end_port(device); ++p) { 16998e37ab68SMichael Wang if (!rdma_protocol_ib(device, p)) 17007b4c8769SEli Cohen continue; 17011da177e4SLinus Torvalds dev = ipoib_add_port("ib%d", device, p); 17021da177e4SLinus Torvalds if (!IS_ERR(dev)) { 17031da177e4SLinus Torvalds priv = netdev_priv(dev); 17041da177e4SLinus Torvalds list_add_tail(&priv->list, dev_list); 17058e37ab68SMichael Wang count++; 17061da177e4SLinus Torvalds } 17071da177e4SLinus Torvalds } 17081da177e4SLinus Torvalds 17098e37ab68SMichael Wang if (!count) { 17108e37ab68SMichael Wang kfree(dev_list); 17118e37ab68SMichael Wang return; 17128e37ab68SMichael Wang } 17138e37ab68SMichael Wang 17141da177e4SLinus Torvalds ib_set_client_data(device, &ipoib_client, dev_list); 17151da177e4SLinus Torvalds } 17161da177e4SLinus Torvalds 17171da177e4SLinus Torvalds static void ipoib_remove_one(struct ib_device *device) 17181da177e4SLinus Torvalds { 17191da177e4SLinus Torvalds struct ipoib_dev_priv *priv, *tmp; 17201da177e4SLinus Torvalds struct list_head *dev_list; 17211da177e4SLinus Torvalds 17221da177e4SLinus Torvalds dev_list = ib_get_client_data(device, &ipoib_client); 17235a2815f0SItai Garbi if (!dev_list) 17245a2815f0SItai Garbi return; 17251da177e4SLinus Torvalds 17261da177e4SLinus Torvalds list_for_each_entry_safe(priv, tmp, dev_list, list) { 17271da177e4SLinus Torvalds ib_unregister_event_handler(&priv->event_handler); 17280b39578bSDoug Ledford flush_workqueue(ipoib_workqueue); 1729a77a57a1SRoland Dreier 1730a77a57a1SRoland Dreier rtnl_lock(); 1731a77a57a1SRoland Dreier dev_change_flags(priv->dev, priv->dev->flags & ~IFF_UP); 1732a77a57a1SRoland Dreier rtnl_unlock(); 1733a77a57a1SRoland Dreier 1734b63b70d8SShlomo Pongratz /* Stop GC */ 1735b63b70d8SShlomo Pongratz set_bit(IPOIB_STOP_NEIGH_GC, &priv->flags); 1736b63b70d8SShlomo Pongratz cancel_delayed_work(&priv->neigh_reap_task); 17370b39578bSDoug Ledford flush_workqueue(priv->wq); 17381da177e4SLinus Torvalds 17391da177e4SLinus Torvalds unregister_netdev(priv->dev); 17401da177e4SLinus Torvalds free_netdev(priv->dev); 17411da177e4SLinus Torvalds } 174206c56e44SMichael S. Tsirkin 174306c56e44SMichael S. Tsirkin kfree(dev_list); 17441da177e4SLinus Torvalds } 17451da177e4SLinus Torvalds 17461da177e4SLinus Torvalds static int __init ipoib_init_module(void) 17471da177e4SLinus Torvalds { 17481da177e4SLinus Torvalds int ret; 17491da177e4SLinus Torvalds 17500f485251SShirley Ma ipoib_recvq_size = roundup_pow_of_two(ipoib_recvq_size); 17510f485251SShirley Ma ipoib_recvq_size = min(ipoib_recvq_size, IPOIB_MAX_QUEUE_SIZE); 17520f485251SShirley Ma ipoib_recvq_size = max(ipoib_recvq_size, IPOIB_MIN_QUEUE_SIZE); 17530f485251SShirley Ma 17540f485251SShirley Ma ipoib_sendq_size = roundup_pow_of_two(ipoib_sendq_size); 17550f485251SShirley Ma ipoib_sendq_size = min(ipoib_sendq_size, IPOIB_MAX_QUEUE_SIZE); 1756732eacc0SHagen Paul Pfeifer ipoib_sendq_size = max3(ipoib_sendq_size, 2 * MAX_SEND_CQE, IPOIB_MIN_QUEUE_SIZE); 175768e995a2SPradeep Satyanarayana #ifdef CONFIG_INFINIBAND_IPOIB_CM 175868e995a2SPradeep Satyanarayana ipoib_max_conn_qp = min(ipoib_max_conn_qp, IPOIB_CM_MAX_CONN_QP); 175968e995a2SPradeep Satyanarayana #endif 17600f485251SShirley Ma 1761f89271daSEli Cohen /* 1762f89271daSEli Cohen * When copying small received packets, we only copy from the 1763f89271daSEli Cohen * linear data part of the SKB, so we rely on this condition. 1764f89271daSEli Cohen */ 1765f89271daSEli Cohen BUILD_BUG_ON(IPOIB_CM_COPYBREAK > IPOIB_CM_HEAD_SIZE); 1766f89271daSEli Cohen 17671da177e4SLinus Torvalds ret = ipoib_register_debugfs(); 17681da177e4SLinus Torvalds if (ret) 17691da177e4SLinus Torvalds return ret; 17701da177e4SLinus Torvalds 17711da177e4SLinus Torvalds /* 17720b39578bSDoug Ledford * We create a global workqueue here that is used for all flush 17730b39578bSDoug Ledford * operations. However, if you attempt to flush a workqueue 17740b39578bSDoug Ledford * from a task on that same workqueue, it deadlocks the system. 17750b39578bSDoug Ledford * We want to be able to flush the tasks associated with a 17760b39578bSDoug Ledford * specific net device, so we also create a workqueue for each 17770b39578bSDoug Ledford * netdevice. We queue up the tasks for that device only on 17780b39578bSDoug Ledford * its private workqueue, and we only queue up flush events 17790b39578bSDoug Ledford * on our global flush workqueue. This avoids the deadlocks. 17801da177e4SLinus Torvalds */ 17810b39578bSDoug Ledford ipoib_workqueue = create_singlethread_workqueue("ipoib_flush"); 17821da177e4SLinus Torvalds if (!ipoib_workqueue) { 17831da177e4SLinus Torvalds ret = -ENOMEM; 17841da177e4SLinus Torvalds goto err_fs; 17851da177e4SLinus Torvalds } 17861da177e4SLinus Torvalds 1787c1a0b23bSMichael S. Tsirkin ib_sa_register_client(&ipoib_sa_client); 1788c1a0b23bSMichael S. Tsirkin 17891da177e4SLinus Torvalds ret = ib_register_client(&ipoib_client); 17901da177e4SLinus Torvalds if (ret) 1791c1a0b23bSMichael S. Tsirkin goto err_sa; 17921da177e4SLinus Torvalds 17939baa0b03SOr Gerlitz ret = ipoib_netlink_init(); 17949baa0b03SOr Gerlitz if (ret) 17959baa0b03SOr Gerlitz goto err_client; 17969baa0b03SOr Gerlitz 17971da177e4SLinus Torvalds return 0; 17981da177e4SLinus Torvalds 17999baa0b03SOr Gerlitz err_client: 18009baa0b03SOr Gerlitz ib_unregister_client(&ipoib_client); 18019baa0b03SOr Gerlitz 1802c1a0b23bSMichael S. Tsirkin err_sa: 1803c1a0b23bSMichael S. Tsirkin ib_sa_unregister_client(&ipoib_sa_client); 18041da177e4SLinus Torvalds destroy_workqueue(ipoib_workqueue); 18051da177e4SLinus Torvalds 18069adec1a8SRoland Dreier err_fs: 18079adec1a8SRoland Dreier ipoib_unregister_debugfs(); 18089adec1a8SRoland Dreier 18091da177e4SLinus Torvalds return ret; 18101da177e4SLinus Torvalds } 18111da177e4SLinus Torvalds 18121da177e4SLinus Torvalds static void __exit ipoib_cleanup_module(void) 18131da177e4SLinus Torvalds { 18149baa0b03SOr Gerlitz ipoib_netlink_fini(); 18151da177e4SLinus Torvalds ib_unregister_client(&ipoib_client); 1816c1a0b23bSMichael S. Tsirkin ib_sa_unregister_client(&ipoib_sa_client); 18179adec1a8SRoland Dreier ipoib_unregister_debugfs(); 18181da177e4SLinus Torvalds destroy_workqueue(ipoib_workqueue); 18191da177e4SLinus Torvalds } 18201da177e4SLinus Torvalds 18211da177e4SLinus Torvalds module_init(ipoib_init_module); 18221da177e4SLinus Torvalds module_exit(ipoib_cleanup_module); 1823