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 4914c85021SArnaldo Carvalho de Melo #include <net/dst.h> 5014c85021SArnaldo Carvalho de Melo 511da177e4SLinus Torvalds MODULE_AUTHOR("Roland Dreier"); 521da177e4SLinus Torvalds MODULE_DESCRIPTION("IP-over-InfiniBand net driver"); 531da177e4SLinus Torvalds MODULE_LICENSE("Dual BSD/GPL"); 541da177e4SLinus Torvalds 550f485251SShirley Ma int ipoib_sendq_size __read_mostly = IPOIB_TX_RING_SIZE; 560f485251SShirley Ma int ipoib_recvq_size __read_mostly = IPOIB_RX_RING_SIZE; 570f485251SShirley Ma 580f485251SShirley Ma module_param_named(send_queue_size, ipoib_sendq_size, int, 0444); 590f485251SShirley Ma MODULE_PARM_DESC(send_queue_size, "Number of descriptors in send queue"); 600f485251SShirley Ma module_param_named(recv_queue_size, ipoib_recvq_size, int, 0444); 610f485251SShirley Ma MODULE_PARM_DESC(recv_queue_size, "Number of descriptors in receive queue"); 620f485251SShirley Ma 63af40da89SVladimir Sokolovsky static int lro; 64af40da89SVladimir Sokolovsky module_param(lro, bool, 0444); 65af40da89SVladimir Sokolovsky MODULE_PARM_DESC(lro, "Enable LRO (Large Receive Offload)"); 66af40da89SVladimir Sokolovsky 67af40da89SVladimir Sokolovsky static int lro_max_aggr = IPOIB_LRO_MAX_AGGR; 68af40da89SVladimir Sokolovsky module_param(lro_max_aggr, int, 0644); 69af40da89SVladimir Sokolovsky MODULE_PARM_DESC(lro_max_aggr, "LRO: Max packets to be aggregated " 70af40da89SVladimir Sokolovsky "(default = 64)"); 71af40da89SVladimir Sokolovsky 721da177e4SLinus Torvalds #ifdef CONFIG_INFINIBAND_IPOIB_DEBUG 731da177e4SLinus Torvalds int ipoib_debug_level; 741da177e4SLinus Torvalds 751da177e4SLinus Torvalds module_param_named(debug_level, ipoib_debug_level, int, 0644); 761da177e4SLinus Torvalds MODULE_PARM_DESC(debug_level, "Enable debug tracing if > 0"); 771da177e4SLinus Torvalds #endif 781da177e4SLinus Torvalds 791732b0efSRoland Dreier struct ipoib_path_iter { 801732b0efSRoland Dreier struct net_device *dev; 811732b0efSRoland Dreier struct ipoib_path path; 821732b0efSRoland Dreier }; 831732b0efSRoland Dreier 841da177e4SLinus Torvalds static const u8 ipv4_bcast_addr[] = { 851da177e4SLinus Torvalds 0x00, 0xff, 0xff, 0xff, 861da177e4SLinus Torvalds 0xff, 0x12, 0x40, 0x1b, 0x00, 0x00, 0x00, 0x00, 871da177e4SLinus Torvalds 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff 881da177e4SLinus Torvalds }; 891da177e4SLinus Torvalds 901da177e4SLinus Torvalds struct workqueue_struct *ipoib_workqueue; 911da177e4SLinus Torvalds 92c1a0b23bSMichael S. Tsirkin struct ib_sa_client ipoib_sa_client; 93c1a0b23bSMichael S. Tsirkin 941da177e4SLinus Torvalds static void ipoib_add_one(struct ib_device *device); 951da177e4SLinus Torvalds static void ipoib_remove_one(struct ib_device *device); 961da177e4SLinus Torvalds 971da177e4SLinus Torvalds static struct ib_client ipoib_client = { 981da177e4SLinus Torvalds .name = "ipoib", 991da177e4SLinus Torvalds .add = ipoib_add_one, 1001da177e4SLinus Torvalds .remove = ipoib_remove_one 1011da177e4SLinus Torvalds }; 1021da177e4SLinus Torvalds 1031da177e4SLinus Torvalds int ipoib_open(struct net_device *dev) 1041da177e4SLinus Torvalds { 1051da177e4SLinus Torvalds struct ipoib_dev_priv *priv = netdev_priv(dev); 1061da177e4SLinus Torvalds 1071da177e4SLinus Torvalds ipoib_dbg(priv, "bringing up interface\n"); 1081da177e4SLinus Torvalds 109e028cc55SYossi Etigin set_bit(IPOIB_FLAG_ADMIN_UP, &priv->flags); 1101da177e4SLinus Torvalds 1111da177e4SLinus Torvalds if (ipoib_pkey_dev_delay_open(dev)) 1121da177e4SLinus Torvalds return 0; 1131da177e4SLinus Torvalds 114b8a1b1ceSRoland Dreier if (ipoib_ib_dev_open(dev)) 115b8a1b1ceSRoland Dreier goto err_disable; 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 */ 12495ed644fSIngo Molnar mutex_lock(&priv->vlan_mutex); 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 } 13495ed644fSIngo Molnar mutex_unlock(&priv->vlan_mutex); 1351da177e4SLinus Torvalds } 1361da177e4SLinus Torvalds 1371da177e4SLinus Torvalds netif_start_queue(dev); 1381da177e4SLinus Torvalds 1391da177e4SLinus Torvalds return 0; 140b8a1b1ceSRoland Dreier 141b8a1b1ceSRoland Dreier err_stop: 142b8a1b1ceSRoland Dreier ipoib_ib_dev_stop(dev, 1); 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 160a77a57a1SRoland Dreier ipoib_ib_dev_down(dev, 0); 161a77a57a1SRoland Dreier ipoib_ib_dev_stop(dev, 0); 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 */ 16795ed644fSIngo Molnar mutex_lock(&priv->vlan_mutex); 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 } 17795ed644fSIngo Molnar mutex_unlock(&priv->vlan_mutex); 1781da177e4SLinus Torvalds } 1791da177e4SLinus Torvalds 1801da177e4SLinus Torvalds return 0; 1811da177e4SLinus Torvalds } 1821da177e4SLinus Torvalds 1831da177e4SLinus Torvalds static int ipoib_change_mtu(struct net_device *dev, int new_mtu) 1841da177e4SLinus Torvalds { 1851da177e4SLinus Torvalds struct ipoib_dev_priv *priv = netdev_priv(dev); 1861da177e4SLinus Torvalds 187839fcabaSMichael S. Tsirkin /* dev->mtu > 2K ==> connected mode */ 188586a6934SPradeep Satyanarayana if (ipoib_cm_admin_enabled(dev)) { 189586a6934SPradeep Satyanarayana if (new_mtu > ipoib_cm_max_mtu(dev)) 190586a6934SPradeep Satyanarayana return -EINVAL; 191586a6934SPradeep Satyanarayana 192839fcabaSMichael S. Tsirkin if (new_mtu > priv->mcast_mtu) 193839fcabaSMichael S. Tsirkin ipoib_warn(priv, "mtu > %d will cause multicast packet drops.\n", 194839fcabaSMichael S. Tsirkin priv->mcast_mtu); 195586a6934SPradeep Satyanarayana 196839fcabaSMichael S. Tsirkin dev->mtu = new_mtu; 197839fcabaSMichael S. Tsirkin return 0; 198839fcabaSMichael S. Tsirkin } 199839fcabaSMichael S. Tsirkin 200bc7b3a36SShirley Ma if (new_mtu > IPOIB_UD_MTU(priv->max_ib_mtu)) 2011da177e4SLinus Torvalds return -EINVAL; 2021da177e4SLinus Torvalds 2031da177e4SLinus Torvalds priv->admin_mtu = new_mtu; 2041da177e4SLinus Torvalds 2051da177e4SLinus Torvalds dev->mtu = min(priv->mcast_mtu, priv->admin_mtu); 2061da177e4SLinus Torvalds 2071da177e4SLinus Torvalds return 0; 2081da177e4SLinus Torvalds } 2091da177e4SLinus Torvalds 21037c22a77SJack Morgenstein static struct ipoib_path *__path_find(struct net_device *dev, void *gid) 2111da177e4SLinus Torvalds { 2121da177e4SLinus Torvalds struct ipoib_dev_priv *priv = netdev_priv(dev); 2131da177e4SLinus Torvalds struct rb_node *n = priv->path_tree.rb_node; 2141da177e4SLinus Torvalds struct ipoib_path *path; 2151da177e4SLinus Torvalds int ret; 2161da177e4SLinus Torvalds 2171da177e4SLinus Torvalds while (n) { 2181da177e4SLinus Torvalds path = rb_entry(n, struct ipoib_path, rb_node); 2191da177e4SLinus Torvalds 22037c22a77SJack Morgenstein ret = memcmp(gid, path->pathrec.dgid.raw, 2211da177e4SLinus Torvalds sizeof (union ib_gid)); 2221da177e4SLinus Torvalds 2231da177e4SLinus Torvalds if (ret < 0) 2241da177e4SLinus Torvalds n = n->rb_left; 2251da177e4SLinus Torvalds else if (ret > 0) 2261da177e4SLinus Torvalds n = n->rb_right; 2271da177e4SLinus Torvalds else 2281da177e4SLinus Torvalds return path; 2291da177e4SLinus Torvalds } 2301da177e4SLinus Torvalds 2311da177e4SLinus Torvalds return NULL; 2321da177e4SLinus Torvalds } 2331da177e4SLinus Torvalds 2341da177e4SLinus Torvalds static int __path_add(struct net_device *dev, struct ipoib_path *path) 2351da177e4SLinus Torvalds { 2361da177e4SLinus Torvalds struct ipoib_dev_priv *priv = netdev_priv(dev); 2371da177e4SLinus Torvalds struct rb_node **n = &priv->path_tree.rb_node; 2381da177e4SLinus Torvalds struct rb_node *pn = NULL; 2391da177e4SLinus Torvalds struct ipoib_path *tpath; 2401da177e4SLinus Torvalds int ret; 2411da177e4SLinus Torvalds 2421da177e4SLinus Torvalds while (*n) { 2431da177e4SLinus Torvalds pn = *n; 2441da177e4SLinus Torvalds tpath = rb_entry(pn, struct ipoib_path, rb_node); 2451da177e4SLinus Torvalds 2461da177e4SLinus Torvalds ret = memcmp(path->pathrec.dgid.raw, tpath->pathrec.dgid.raw, 2471da177e4SLinus Torvalds sizeof (union ib_gid)); 2481da177e4SLinus Torvalds if (ret < 0) 2491da177e4SLinus Torvalds n = &pn->rb_left; 2501da177e4SLinus Torvalds else if (ret > 0) 2511da177e4SLinus Torvalds n = &pn->rb_right; 2521da177e4SLinus Torvalds else 2531da177e4SLinus Torvalds return -EEXIST; 2541da177e4SLinus Torvalds } 2551da177e4SLinus Torvalds 2561da177e4SLinus Torvalds rb_link_node(&path->rb_node, pn, n); 2571da177e4SLinus Torvalds rb_insert_color(&path->rb_node, &priv->path_tree); 2581da177e4SLinus Torvalds 2591da177e4SLinus Torvalds list_add_tail(&path->list, &priv->path_list); 2601da177e4SLinus Torvalds 2611da177e4SLinus Torvalds return 0; 2621da177e4SLinus Torvalds } 2631da177e4SLinus Torvalds 2641da177e4SLinus Torvalds static void path_free(struct net_device *dev, struct ipoib_path *path) 2651da177e4SLinus Torvalds { 2661da177e4SLinus Torvalds struct ipoib_dev_priv *priv = netdev_priv(dev); 2671da177e4SLinus Torvalds struct ipoib_neigh *neigh, *tn; 2681da177e4SLinus Torvalds struct sk_buff *skb; 2691da177e4SLinus Torvalds unsigned long flags; 2701da177e4SLinus Torvalds 2711da177e4SLinus Torvalds while ((skb = __skb_dequeue(&path->queue))) 2721da177e4SLinus Torvalds dev_kfree_skb_irq(skb); 2731da177e4SLinus Torvalds 2741da177e4SLinus Torvalds spin_lock_irqsave(&priv->lock, flags); 2751da177e4SLinus Torvalds 2761da177e4SLinus Torvalds list_for_each_entry_safe(neigh, tn, &path->neigh_list, list) { 2771da177e4SLinus Torvalds /* 2781da177e4SLinus Torvalds * It's safe to call ipoib_put_ah() inside priv->lock 2791da177e4SLinus Torvalds * here, because we know that path->ah will always 2801da177e4SLinus Torvalds * hold one more reference, so ipoib_put_ah() will 2811da177e4SLinus Torvalds * never do more than decrement the ref count. 2821da177e4SLinus Torvalds */ 2831da177e4SLinus Torvalds if (neigh->ah) 2841da177e4SLinus Torvalds ipoib_put_ah(neigh->ah); 285d2e0655eSMichael S. Tsirkin 2862745b5b7SMichael S. Tsirkin ipoib_neigh_free(dev, neigh); 2871da177e4SLinus Torvalds } 2881da177e4SLinus Torvalds 2891da177e4SLinus Torvalds spin_unlock_irqrestore(&priv->lock, flags); 2901da177e4SLinus Torvalds 2911da177e4SLinus Torvalds if (path->ah) 2921da177e4SLinus Torvalds ipoib_put_ah(path->ah); 2931da177e4SLinus Torvalds 2941da177e4SLinus Torvalds kfree(path); 2951da177e4SLinus Torvalds } 2961da177e4SLinus Torvalds 2971732b0efSRoland Dreier #ifdef CONFIG_INFINIBAND_IPOIB_DEBUG 2981732b0efSRoland Dreier 2991732b0efSRoland Dreier struct ipoib_path_iter *ipoib_path_iter_init(struct net_device *dev) 3001732b0efSRoland Dreier { 3011732b0efSRoland Dreier struct ipoib_path_iter *iter; 3021732b0efSRoland Dreier 3031732b0efSRoland Dreier iter = kmalloc(sizeof *iter, GFP_KERNEL); 3041732b0efSRoland Dreier if (!iter) 3051732b0efSRoland Dreier return NULL; 3061732b0efSRoland Dreier 3071732b0efSRoland Dreier iter->dev = dev; 3081732b0efSRoland Dreier memset(iter->path.pathrec.dgid.raw, 0, 16); 3091732b0efSRoland Dreier 3101732b0efSRoland Dreier if (ipoib_path_iter_next(iter)) { 3111732b0efSRoland Dreier kfree(iter); 3121732b0efSRoland Dreier return NULL; 3131732b0efSRoland Dreier } 3141732b0efSRoland Dreier 3151732b0efSRoland Dreier return iter; 3161732b0efSRoland Dreier } 3171732b0efSRoland Dreier 3181732b0efSRoland Dreier int ipoib_path_iter_next(struct ipoib_path_iter *iter) 3191732b0efSRoland Dreier { 3201732b0efSRoland Dreier struct ipoib_dev_priv *priv = netdev_priv(iter->dev); 3211732b0efSRoland Dreier struct rb_node *n; 3221732b0efSRoland Dreier struct ipoib_path *path; 3231732b0efSRoland Dreier int ret = 1; 3241732b0efSRoland Dreier 3251732b0efSRoland Dreier spin_lock_irq(&priv->lock); 3261732b0efSRoland Dreier 3271732b0efSRoland Dreier n = rb_first(&priv->path_tree); 3281732b0efSRoland Dreier 3291732b0efSRoland Dreier while (n) { 3301732b0efSRoland Dreier path = rb_entry(n, struct ipoib_path, rb_node); 3311732b0efSRoland Dreier 3321732b0efSRoland Dreier if (memcmp(iter->path.pathrec.dgid.raw, path->pathrec.dgid.raw, 3331732b0efSRoland Dreier sizeof (union ib_gid)) < 0) { 3341732b0efSRoland Dreier iter->path = *path; 3351732b0efSRoland Dreier ret = 0; 3361732b0efSRoland Dreier break; 3371732b0efSRoland Dreier } 3381732b0efSRoland Dreier 3391732b0efSRoland Dreier n = rb_next(n); 3401732b0efSRoland Dreier } 3411732b0efSRoland Dreier 3421732b0efSRoland Dreier spin_unlock_irq(&priv->lock); 3431732b0efSRoland Dreier 3441732b0efSRoland Dreier return ret; 3451732b0efSRoland Dreier } 3461732b0efSRoland Dreier 3471732b0efSRoland Dreier void ipoib_path_iter_read(struct ipoib_path_iter *iter, 3481732b0efSRoland Dreier struct ipoib_path *path) 3491732b0efSRoland Dreier { 3501732b0efSRoland Dreier *path = iter->path; 3511732b0efSRoland Dreier } 3521732b0efSRoland Dreier 3531732b0efSRoland Dreier #endif /* CONFIG_INFINIBAND_IPOIB_DEBUG */ 3541732b0efSRoland Dreier 355ee1e2c82SMoni Shoua void ipoib_mark_paths_invalid(struct net_device *dev) 356ee1e2c82SMoni Shoua { 357ee1e2c82SMoni Shoua struct ipoib_dev_priv *priv = netdev_priv(dev); 358ee1e2c82SMoni Shoua struct ipoib_path *path, *tp; 359ee1e2c82SMoni Shoua 360ee1e2c82SMoni Shoua spin_lock_irq(&priv->lock); 361ee1e2c82SMoni Shoua 362ee1e2c82SMoni Shoua list_for_each_entry_safe(path, tp, &priv->path_list, list) { 3635b095d98SHarvey Harrison ipoib_dbg(priv, "mark path LID 0x%04x GID %pI6 invalid\n", 364ee1e2c82SMoni Shoua be16_to_cpu(path->pathrec.dlid), 365fcace2feSHarvey Harrison path->pathrec.dgid.raw); 366ee1e2c82SMoni Shoua path->valid = 0; 367ee1e2c82SMoni Shoua } 368ee1e2c82SMoni Shoua 369ee1e2c82SMoni Shoua spin_unlock_irq(&priv->lock); 370ee1e2c82SMoni Shoua } 371ee1e2c82SMoni Shoua 3721da177e4SLinus Torvalds void ipoib_flush_paths(struct net_device *dev) 3731da177e4SLinus Torvalds { 3741da177e4SLinus Torvalds struct ipoib_dev_priv *priv = netdev_priv(dev); 3751da177e4SLinus Torvalds struct ipoib_path *path, *tp; 3761da177e4SLinus Torvalds LIST_HEAD(remove_list); 377943c246eSRoland Dreier unsigned long flags; 3781da177e4SLinus Torvalds 379943c246eSRoland Dreier netif_tx_lock_bh(dev); 380943c246eSRoland Dreier spin_lock_irqsave(&priv->lock, flags); 3811da177e4SLinus Torvalds 382157de229SRobert P. J. Day list_splice_init(&priv->path_list, &remove_list); 3831da177e4SLinus Torvalds 3841da177e4SLinus Torvalds list_for_each_entry(path, &remove_list, list) 3851da177e4SLinus Torvalds rb_erase(&path->rb_node, &priv->path_tree); 3861da177e4SLinus Torvalds 3871da177e4SLinus Torvalds list_for_each_entry_safe(path, tp, &remove_list, list) { 3881da177e4SLinus Torvalds if (path->query) 3891da177e4SLinus Torvalds ib_sa_cancel_query(path->query_id, path->query); 390943c246eSRoland Dreier spin_unlock_irqrestore(&priv->lock, flags); 391943c246eSRoland Dreier netif_tx_unlock_bh(dev); 3921da177e4SLinus Torvalds wait_for_completion(&path->done); 3931da177e4SLinus Torvalds path_free(dev, path); 394943c246eSRoland Dreier netif_tx_lock_bh(dev); 395943c246eSRoland Dreier spin_lock_irqsave(&priv->lock, flags); 3961da177e4SLinus Torvalds } 397943c246eSRoland Dreier 398943c246eSRoland Dreier spin_unlock_irqrestore(&priv->lock, flags); 399943c246eSRoland Dreier netif_tx_unlock_bh(dev); 4001da177e4SLinus Torvalds } 4011da177e4SLinus Torvalds 4021da177e4SLinus Torvalds static void path_rec_completion(int status, 4031da177e4SLinus Torvalds struct ib_sa_path_rec *pathrec, 4041da177e4SLinus Torvalds void *path_ptr) 4051da177e4SLinus Torvalds { 4061da177e4SLinus Torvalds struct ipoib_path *path = path_ptr; 4071da177e4SLinus Torvalds struct net_device *dev = path->dev; 4081da177e4SLinus Torvalds struct ipoib_dev_priv *priv = netdev_priv(dev); 4091da177e4SLinus Torvalds struct ipoib_ah *ah = NULL; 410c9da4badSRoland Dreier struct ipoib_ah *old_ah = NULL; 411d04d01b1SMichael S. Tsirkin struct ipoib_neigh *neigh, *tn; 4121da177e4SLinus Torvalds struct sk_buff_head skqueue; 4131da177e4SLinus Torvalds struct sk_buff *skb; 4141da177e4SLinus Torvalds unsigned long flags; 4151da177e4SLinus Torvalds 416843613b0SRoland Dreier if (!status) 4175b095d98SHarvey Harrison ipoib_dbg(priv, "PathRec LID 0x%04x for GID %pI6\n", 418fcace2feSHarvey Harrison be16_to_cpu(pathrec->dlid), pathrec->dgid.raw); 4191da177e4SLinus Torvalds else 4205b095d98SHarvey Harrison ipoib_dbg(priv, "PathRec status %d for GID %pI6\n", 421fcace2feSHarvey Harrison status, path->pathrec.dgid.raw); 4221da177e4SLinus Torvalds 4231da177e4SLinus Torvalds skb_queue_head_init(&skqueue); 4241da177e4SLinus Torvalds 4251da177e4SLinus Torvalds if (!status) { 42646f1b3d7SSean Hefty struct ib_ah_attr av; 4271da177e4SLinus Torvalds 42846f1b3d7SSean Hefty if (!ib_init_ah_from_path(priv->ca, priv->port, pathrec, &av)) 4291da177e4SLinus Torvalds ah = ipoib_create_ah(dev, priv->pd, &av); 4301da177e4SLinus Torvalds } 4311da177e4SLinus Torvalds 4321da177e4SLinus Torvalds spin_lock_irqsave(&priv->lock, flags); 4331da177e4SLinus Torvalds 4341da177e4SLinus Torvalds if (ah) { 4351da177e4SLinus Torvalds path->pathrec = *pathrec; 4361da177e4SLinus Torvalds 437c9da4badSRoland Dreier old_ah = path->ah; 438c9da4badSRoland Dreier path->ah = ah; 439c9da4badSRoland Dreier 4401da177e4SLinus Torvalds ipoib_dbg(priv, "created address handle %p for LID 0x%04x, SL %d\n", 4411da177e4SLinus Torvalds ah, be16_to_cpu(pathrec->dlid), pathrec->sl); 4421da177e4SLinus Torvalds 4431da177e4SLinus Torvalds while ((skb = __skb_dequeue(&path->queue))) 4441da177e4SLinus Torvalds __skb_queue_tail(&skqueue, skb); 4451da177e4SLinus Torvalds 446d04d01b1SMichael S. Tsirkin list_for_each_entry_safe(neigh, tn, &path->neigh_list, list) { 447ee1e2c82SMoni Shoua if (neigh->ah) { 448ee1e2c82SMoni Shoua WARN_ON(neigh->ah != old_ah); 449ee1e2c82SMoni Shoua /* 450ee1e2c82SMoni Shoua * Dropping the ah reference inside 451ee1e2c82SMoni Shoua * priv->lock is safe here, because we 452ee1e2c82SMoni Shoua * will hold one more reference from 453ee1e2c82SMoni Shoua * the original value of path->ah (ie 454ee1e2c82SMoni Shoua * old_ah). 455ee1e2c82SMoni Shoua */ 456ee1e2c82SMoni Shoua ipoib_put_ah(neigh->ah); 457ee1e2c82SMoni Shoua } 4581da177e4SLinus Torvalds kref_get(&path->ah->ref); 4591da177e4SLinus Torvalds neigh->ah = path->ah; 4608a7f7521SMichael S. Tsirkin memcpy(&neigh->dgid.raw, &path->pathrec.dgid.raw, 4618a7f7521SMichael S. Tsirkin sizeof(union ib_gid)); 4621da177e4SLinus Torvalds 463839fcabaSMichael S. Tsirkin if (ipoib_cm_enabled(dev, neigh->neighbour)) { 464839fcabaSMichael S. Tsirkin if (!ipoib_cm_get(neigh)) 465839fcabaSMichael S. Tsirkin ipoib_cm_set(neigh, ipoib_cm_create_tx(dev, 466839fcabaSMichael S. Tsirkin path, 467839fcabaSMichael S. Tsirkin neigh)); 468839fcabaSMichael S. Tsirkin if (!ipoib_cm_get(neigh)) { 469839fcabaSMichael S. Tsirkin list_del(&neigh->list); 470839fcabaSMichael S. Tsirkin if (neigh->ah) 471839fcabaSMichael S. Tsirkin ipoib_put_ah(neigh->ah); 472839fcabaSMichael S. Tsirkin ipoib_neigh_free(dev, neigh); 473839fcabaSMichael S. Tsirkin continue; 474839fcabaSMichael S. Tsirkin } 475839fcabaSMichael S. Tsirkin } 476839fcabaSMichael S. Tsirkin 4771da177e4SLinus Torvalds while ((skb = __skb_dequeue(&neigh->queue))) 4781da177e4SLinus Torvalds __skb_queue_tail(&skqueue, skb); 4791da177e4SLinus Torvalds } 480ee1e2c82SMoni Shoua path->valid = 1; 4815872a9fcSRoland Dreier } 4821da177e4SLinus Torvalds 4835872a9fcSRoland Dreier path->query = NULL; 4841da177e4SLinus Torvalds complete(&path->done); 4851da177e4SLinus Torvalds 4861da177e4SLinus Torvalds spin_unlock_irqrestore(&priv->lock, flags); 4871da177e4SLinus Torvalds 488ee1e2c82SMoni Shoua if (old_ah) 489ee1e2c82SMoni Shoua ipoib_put_ah(old_ah); 490ee1e2c82SMoni Shoua 4911da177e4SLinus Torvalds while ((skb = __skb_dequeue(&skqueue))) { 4921da177e4SLinus Torvalds skb->dev = dev; 4931da177e4SLinus Torvalds if (dev_queue_xmit(skb)) 4941da177e4SLinus Torvalds ipoib_warn(priv, "dev_queue_xmit failed " 4951da177e4SLinus Torvalds "to requeue packet\n"); 4961da177e4SLinus Torvalds } 4971da177e4SLinus Torvalds } 4981da177e4SLinus Torvalds 49937c22a77SJack Morgenstein static struct ipoib_path *path_rec_create(struct net_device *dev, void *gid) 5001da177e4SLinus Torvalds { 5011da177e4SLinus Torvalds struct ipoib_dev_priv *priv = netdev_priv(dev); 5021da177e4SLinus Torvalds struct ipoib_path *path; 5031da177e4SLinus Torvalds 5041401b53aSJack Morgenstein if (!priv->broadcast) 5051401b53aSJack Morgenstein return NULL; 5061401b53aSJack Morgenstein 50721a38489SRoland Dreier path = kzalloc(sizeof *path, GFP_ATOMIC); 5081da177e4SLinus Torvalds if (!path) 5091da177e4SLinus Torvalds return NULL; 5101da177e4SLinus Torvalds 5111da177e4SLinus Torvalds path->dev = dev; 5121da177e4SLinus Torvalds 5131da177e4SLinus Torvalds skb_queue_head_init(&path->queue); 5141da177e4SLinus Torvalds 5151da177e4SLinus Torvalds INIT_LIST_HEAD(&path->neigh_list); 5161da177e4SLinus Torvalds 51737c22a77SJack Morgenstein memcpy(path->pathrec.dgid.raw, gid, sizeof (union ib_gid)); 5181da177e4SLinus Torvalds path->pathrec.sgid = priv->local_gid; 5191da177e4SLinus Torvalds path->pathrec.pkey = cpu_to_be16(priv->pkey); 5201da177e4SLinus Torvalds path->pathrec.numb_path = 1; 52181668838SSean Hefty path->pathrec.traffic_class = priv->broadcast->mcmember.traffic_class; 5221da177e4SLinus Torvalds 5231da177e4SLinus Torvalds return path; 5241da177e4SLinus Torvalds } 5251da177e4SLinus Torvalds 5261da177e4SLinus Torvalds static int path_rec_start(struct net_device *dev, 5271da177e4SLinus Torvalds struct ipoib_path *path) 5281da177e4SLinus Torvalds { 5291da177e4SLinus Torvalds struct ipoib_dev_priv *priv = netdev_priv(dev); 5301da177e4SLinus Torvalds 5315b095d98SHarvey Harrison ipoib_dbg(priv, "Start path record lookup for %pI6\n", 532fcace2feSHarvey Harrison path->pathrec.dgid.raw); 5331da177e4SLinus Torvalds 53465c7eddaSRoland Dreier init_completion(&path->done); 53565c7eddaSRoland Dreier 5361da177e4SLinus Torvalds path->query_id = 537c1a0b23bSMichael S. Tsirkin ib_sa_path_rec_get(&ipoib_sa_client, priv->ca, priv->port, 5381da177e4SLinus Torvalds &path->pathrec, 5391da177e4SLinus Torvalds IB_SA_PATH_REC_DGID | 5401da177e4SLinus Torvalds IB_SA_PATH_REC_SGID | 5411da177e4SLinus Torvalds IB_SA_PATH_REC_NUMB_PATH | 54281668838SSean Hefty IB_SA_PATH_REC_TRAFFIC_CLASS | 5431da177e4SLinus Torvalds IB_SA_PATH_REC_PKEY, 5441da177e4SLinus Torvalds 1000, GFP_ATOMIC, 5451da177e4SLinus Torvalds path_rec_completion, 5461da177e4SLinus Torvalds path, &path->query); 5471da177e4SLinus Torvalds if (path->query_id < 0) { 54801b3fc8bSOr Gerlitz ipoib_warn(priv, "ib_sa_path_rec_get failed: %d\n", path->query_id); 5491da177e4SLinus Torvalds path->query = NULL; 55093a3ab93SYossi Etigin complete(&path->done); 5511da177e4SLinus Torvalds return path->query_id; 5521da177e4SLinus Torvalds } 5531da177e4SLinus Torvalds 5541da177e4SLinus Torvalds return 0; 5551da177e4SLinus Torvalds } 5561da177e4SLinus Torvalds 5571da177e4SLinus Torvalds static void neigh_add_path(struct sk_buff *skb, struct net_device *dev) 5581da177e4SLinus Torvalds { 5591da177e4SLinus Torvalds struct ipoib_dev_priv *priv = netdev_priv(dev); 5601da177e4SLinus Torvalds struct ipoib_path *path; 5611da177e4SLinus Torvalds struct ipoib_neigh *neigh; 562943c246eSRoland Dreier unsigned long flags; 5631da177e4SLinus Torvalds 564adf30907SEric Dumazet neigh = ipoib_neigh_alloc(skb_dst(skb)->neighbour, skb->dev); 5651da177e4SLinus Torvalds if (!neigh) { 566de903512SRoland Dreier ++dev->stats.tx_dropped; 5671da177e4SLinus Torvalds dev_kfree_skb_any(skb); 5681da177e4SLinus Torvalds return; 5691da177e4SLinus Torvalds } 5701da177e4SLinus Torvalds 571943c246eSRoland Dreier spin_lock_irqsave(&priv->lock, flags); 5721da177e4SLinus Torvalds 573adf30907SEric Dumazet path = __path_find(dev, skb_dst(skb)->neighbour->ha + 4); 5741da177e4SLinus Torvalds if (!path) { 575adf30907SEric Dumazet path = path_rec_create(dev, skb_dst(skb)->neighbour->ha + 4); 5761da177e4SLinus Torvalds if (!path) 577d2e0655eSMichael S. Tsirkin goto err_path; 5781da177e4SLinus Torvalds 5791da177e4SLinus Torvalds __path_add(dev, path); 5801da177e4SLinus Torvalds } 5811da177e4SLinus Torvalds 5821da177e4SLinus Torvalds list_add_tail(&neigh->list, &path->neigh_list); 5831da177e4SLinus Torvalds 58447f7a071SMichael S. Tsirkin if (path->ah) { 5851da177e4SLinus Torvalds kref_get(&path->ah->ref); 5861da177e4SLinus Torvalds neigh->ah = path->ah; 5878a7f7521SMichael S. Tsirkin memcpy(&neigh->dgid.raw, &path->pathrec.dgid.raw, 5888a7f7521SMichael S. Tsirkin sizeof(union ib_gid)); 5891da177e4SLinus Torvalds 590839fcabaSMichael S. Tsirkin if (ipoib_cm_enabled(dev, neigh->neighbour)) { 591839fcabaSMichael S. Tsirkin if (!ipoib_cm_get(neigh)) 592839fcabaSMichael S. Tsirkin ipoib_cm_set(neigh, ipoib_cm_create_tx(dev, path, neigh)); 593839fcabaSMichael S. Tsirkin if (!ipoib_cm_get(neigh)) { 594839fcabaSMichael S. Tsirkin list_del(&neigh->list); 595839fcabaSMichael S. Tsirkin if (neigh->ah) 596839fcabaSMichael S. Tsirkin ipoib_put_ah(neigh->ah); 597839fcabaSMichael S. Tsirkin ipoib_neigh_free(dev, neigh); 598839fcabaSMichael S. Tsirkin goto err_drop; 599839fcabaSMichael S. Tsirkin } 600839fcabaSMichael S. Tsirkin if (skb_queue_len(&neigh->queue) < IPOIB_MAX_PATH_REC_QUEUE) 601839fcabaSMichael S. Tsirkin __skb_queue_tail(&neigh->queue, skb); 602839fcabaSMichael S. Tsirkin else { 603839fcabaSMichael S. Tsirkin ipoib_warn(priv, "queue length limit %d. Packet drop.\n", 604839fcabaSMichael S. Tsirkin skb_queue_len(&neigh->queue)); 605839fcabaSMichael S. Tsirkin goto err_drop; 606839fcabaSMichael S. Tsirkin } 607721d67cdSRoland Dreier } else { 608721d67cdSRoland Dreier spin_unlock_irqrestore(&priv->lock, flags); 609adf30907SEric Dumazet ipoib_send(dev, skb, path->ah, IPOIB_QPN(skb_dst(skb)->neighbour->ha)); 610721d67cdSRoland Dreier return; 611721d67cdSRoland Dreier } 6121da177e4SLinus Torvalds } else { 6131da177e4SLinus Torvalds neigh->ah = NULL; 6141da177e4SLinus Torvalds 6151da177e4SLinus Torvalds if (!path->query && path_rec_start(dev, path)) 616d2e0655eSMichael S. Tsirkin goto err_list; 6172745b5b7SMichael S. Tsirkin 6182745b5b7SMichael S. Tsirkin __skb_queue_tail(&neigh->queue, skb); 6191da177e4SLinus Torvalds } 6201da177e4SLinus Torvalds 621943c246eSRoland Dreier spin_unlock_irqrestore(&priv->lock, flags); 6221da177e4SLinus Torvalds return; 6231da177e4SLinus Torvalds 624d2e0655eSMichael S. Tsirkin err_list: 6251da177e4SLinus Torvalds list_del(&neigh->list); 6261da177e4SLinus Torvalds 627d2e0655eSMichael S. Tsirkin err_path: 6282745b5b7SMichael S. Tsirkin ipoib_neigh_free(dev, neigh); 629839fcabaSMichael S. Tsirkin err_drop: 630de903512SRoland Dreier ++dev->stats.tx_dropped; 6311da177e4SLinus Torvalds dev_kfree_skb_any(skb); 6321da177e4SLinus Torvalds 633943c246eSRoland Dreier spin_unlock_irqrestore(&priv->lock, flags); 6341da177e4SLinus Torvalds } 6351da177e4SLinus Torvalds 636d70ed607SRoland Dreier static void ipoib_path_lookup(struct sk_buff *skb, struct net_device *dev) 6371da177e4SLinus Torvalds { 6381da177e4SLinus Torvalds struct ipoib_dev_priv *priv = netdev_priv(skb->dev); 6391da177e4SLinus Torvalds 6401da177e4SLinus Torvalds /* Look up path record for unicasts */ 641adf30907SEric Dumazet if (skb_dst(skb)->neighbour->ha[4] != 0xff) { 6421da177e4SLinus Torvalds neigh_add_path(skb, dev); 6431da177e4SLinus Torvalds return; 6441da177e4SLinus Torvalds } 6451da177e4SLinus Torvalds 6461da177e4SLinus Torvalds /* Add in the P_Key for multicasts */ 647adf30907SEric Dumazet skb_dst(skb)->neighbour->ha[8] = (priv->pkey >> 8) & 0xff; 648adf30907SEric Dumazet skb_dst(skb)->neighbour->ha[9] = priv->pkey & 0xff; 649adf30907SEric Dumazet ipoib_mcast_send(dev, skb_dst(skb)->neighbour->ha + 4, skb); 6501da177e4SLinus Torvalds } 6511da177e4SLinus Torvalds 6521da177e4SLinus Torvalds static void unicast_arp_send(struct sk_buff *skb, struct net_device *dev, 6531da177e4SLinus Torvalds struct ipoib_pseudoheader *phdr) 6541da177e4SLinus Torvalds { 6551da177e4SLinus Torvalds struct ipoib_dev_priv *priv = netdev_priv(dev); 6561da177e4SLinus Torvalds struct ipoib_path *path; 657943c246eSRoland Dreier unsigned long flags; 6581da177e4SLinus Torvalds 659943c246eSRoland Dreier spin_lock_irqsave(&priv->lock, flags); 6601da177e4SLinus Torvalds 66137c22a77SJack Morgenstein path = __path_find(dev, phdr->hwaddr + 4); 662ee1e2c82SMoni Shoua if (!path || !path->valid) { 66371d98b46SJack Morgenstein int new_path = 0; 66471d98b46SJack Morgenstein 66571d98b46SJack Morgenstein if (!path) { 66637c22a77SJack Morgenstein path = path_rec_create(dev, phdr->hwaddr + 4); 66771d98b46SJack Morgenstein new_path = 1; 66871d98b46SJack Morgenstein } 6691da177e4SLinus Torvalds if (path) { 6701da177e4SLinus Torvalds /* put pseudoheader back on for next time */ 6711da177e4SLinus Torvalds skb_push(skb, sizeof *phdr); 6721da177e4SLinus Torvalds __skb_queue_tail(&path->queue, skb); 6731da177e4SLinus Torvalds 674ff79ae80SYossi Etigin if (!path->query && path_rec_start(dev, path)) { 675943c246eSRoland Dreier spin_unlock_irqrestore(&priv->lock, flags); 67671d98b46SJack Morgenstein if (new_path) 6771da177e4SLinus Torvalds path_free(dev, path); 6781da177e4SLinus Torvalds return; 6791da177e4SLinus Torvalds } else 6801da177e4SLinus Torvalds __path_add(dev, path); 6811da177e4SLinus Torvalds } else { 682de903512SRoland Dreier ++dev->stats.tx_dropped; 6831da177e4SLinus Torvalds dev_kfree_skb_any(skb); 6841da177e4SLinus Torvalds } 6851da177e4SLinus Torvalds 686943c246eSRoland Dreier spin_unlock_irqrestore(&priv->lock, flags); 6871da177e4SLinus Torvalds return; 6881da177e4SLinus Torvalds } 6891da177e4SLinus Torvalds 69047f7a071SMichael S. Tsirkin if (path->ah) { 6911da177e4SLinus Torvalds ipoib_dbg(priv, "Send unicast ARP to %04x\n", 6921da177e4SLinus Torvalds be16_to_cpu(path->pathrec.dlid)); 6931da177e4SLinus Torvalds 694721d67cdSRoland Dreier spin_unlock_irqrestore(&priv->lock, flags); 695073ae841SMichael S. Tsirkin ipoib_send(dev, skb, path->ah, IPOIB_QPN(phdr->hwaddr)); 696721d67cdSRoland Dreier return; 6971da177e4SLinus Torvalds } else if ((path->query || !path_rec_start(dev, path)) && 6981da177e4SLinus Torvalds skb_queue_len(&path->queue) < IPOIB_MAX_PATH_REC_QUEUE) { 6991da177e4SLinus Torvalds /* put pseudoheader back on for next time */ 7001da177e4SLinus Torvalds skb_push(skb, sizeof *phdr); 7011da177e4SLinus Torvalds __skb_queue_tail(&path->queue, skb); 7021da177e4SLinus Torvalds } else { 703de903512SRoland Dreier ++dev->stats.tx_dropped; 7041da177e4SLinus Torvalds dev_kfree_skb_any(skb); 7051da177e4SLinus Torvalds } 7061da177e4SLinus Torvalds 707943c246eSRoland Dreier spin_unlock_irqrestore(&priv->lock, flags); 7081da177e4SLinus Torvalds } 7091da177e4SLinus Torvalds 7101da177e4SLinus Torvalds static int ipoib_start_xmit(struct sk_buff *skb, struct net_device *dev) 7111da177e4SLinus Torvalds { 7121da177e4SLinus Torvalds struct ipoib_dev_priv *priv = netdev_priv(dev); 7131da177e4SLinus Torvalds struct ipoib_neigh *neigh; 7141da177e4SLinus Torvalds unsigned long flags; 7151da177e4SLinus Torvalds 716adf30907SEric Dumazet if (likely(skb_dst(skb) && skb_dst(skb)->neighbour)) { 717adf30907SEric Dumazet if (unlikely(!*to_ipoib_neigh(skb_dst(skb)->neighbour))) { 718d70ed607SRoland Dreier ipoib_path_lookup(skb, dev); 719943c246eSRoland Dreier return NETDEV_TX_OK; 7201da177e4SLinus Torvalds } 7211da177e4SLinus Torvalds 722adf30907SEric Dumazet neigh = *to_ipoib_neigh(skb_dst(skb)->neighbour); 7231da177e4SLinus Torvalds 724200d1713SMoni Shoua if (unlikely((memcmp(&neigh->dgid.raw, 725adf30907SEric Dumazet skb_dst(skb)->neighbour->ha + 4, 726200d1713SMoni Shoua sizeof(union ib_gid))) || 727200d1713SMoni Shoua (neigh->dev != dev))) { 728943c246eSRoland Dreier spin_lock_irqsave(&priv->lock, flags); 7298a7f7521SMichael S. Tsirkin /* 7308a7f7521SMichael S. Tsirkin * It's safe to call ipoib_put_ah() inside 7318a7f7521SMichael S. Tsirkin * priv->lock here, because we know that 7328a7f7521SMichael S. Tsirkin * path->ah will always hold one more reference, 7338a7f7521SMichael S. Tsirkin * so ipoib_put_ah() will never do more than 7348a7f7521SMichael S. Tsirkin * decrement the ref count. 7358a7f7521SMichael S. Tsirkin */ 736a50df398SYossi Etigin if (neigh->ah) 7378a7f7521SMichael S. Tsirkin ipoib_put_ah(neigh->ah); 7388a7f7521SMichael S. Tsirkin list_del(&neigh->list); 7392745b5b7SMichael S. Tsirkin ipoib_neigh_free(dev, neigh); 740943c246eSRoland Dreier spin_unlock_irqrestore(&priv->lock, flags); 7418a7f7521SMichael S. Tsirkin ipoib_path_lookup(skb, dev); 742943c246eSRoland Dreier return NETDEV_TX_OK; 7438a7f7521SMichael S. Tsirkin } 7448a7f7521SMichael S. Tsirkin 745bafff974SOr Gerlitz if (ipoib_cm_get(neigh)) { 746bafff974SOr Gerlitz if (ipoib_cm_up(neigh)) { 747bafff974SOr Gerlitz ipoib_cm_send(dev, skb, ipoib_cm_get(neigh)); 748943c246eSRoland Dreier return NETDEV_TX_OK; 749bafff974SOr Gerlitz } 750bafff974SOr Gerlitz } else if (neigh->ah) { 751adf30907SEric Dumazet ipoib_send(dev, skb, neigh->ah, IPOIB_QPN(skb_dst(skb)->neighbour->ha)); 752943c246eSRoland Dreier return NETDEV_TX_OK; 7531da177e4SLinus Torvalds } 7541da177e4SLinus Torvalds 7551da177e4SLinus Torvalds if (skb_queue_len(&neigh->queue) < IPOIB_MAX_PATH_REC_QUEUE) { 756943c246eSRoland Dreier spin_lock_irqsave(&priv->lock, flags); 7571da177e4SLinus Torvalds __skb_queue_tail(&neigh->queue, skb); 758943c246eSRoland Dreier spin_unlock_irqrestore(&priv->lock, flags); 7591da177e4SLinus Torvalds } else { 760de903512SRoland Dreier ++dev->stats.tx_dropped; 7611da177e4SLinus Torvalds dev_kfree_skb_any(skb); 7621da177e4SLinus Torvalds } 7631da177e4SLinus Torvalds } else { 7641da177e4SLinus Torvalds struct ipoib_pseudoheader *phdr = 7651da177e4SLinus Torvalds (struct ipoib_pseudoheader *) skb->data; 7661da177e4SLinus Torvalds skb_pull(skb, sizeof *phdr); 7671da177e4SLinus Torvalds 7681da177e4SLinus Torvalds if (phdr->hwaddr[4] == 0xff) { 7691da177e4SLinus Torvalds /* Add in the P_Key for multicast*/ 7701da177e4SLinus Torvalds phdr->hwaddr[8] = (priv->pkey >> 8) & 0xff; 7711da177e4SLinus Torvalds phdr->hwaddr[9] = priv->pkey & 0xff; 7721da177e4SLinus Torvalds 77337c22a77SJack Morgenstein ipoib_mcast_send(dev, phdr->hwaddr + 4, skb); 7741da177e4SLinus Torvalds } else { 7750dca0f7bSHal Rosenstock /* unicast GID -- should be ARP or RARP reply */ 7761da177e4SLinus Torvalds 7770dca0f7bSHal Rosenstock if ((be16_to_cpup((__be16 *) skb->data) != ETH_P_ARP) && 7780dca0f7bSHal Rosenstock (be16_to_cpup((__be16 *) skb->data) != ETH_P_RARP)) { 7795b095d98SHarvey Harrison ipoib_warn(priv, "Unicast, no %s: type %04x, QPN %06x %pI6\n", 780adf30907SEric Dumazet skb_dst(skb) ? "neigh" : "dst", 78197f52eb4SSean Hefty be16_to_cpup((__be16 *) skb->data), 782073ae841SMichael S. Tsirkin IPOIB_QPN(phdr->hwaddr), 783fcace2feSHarvey Harrison phdr->hwaddr + 4); 7841da177e4SLinus Torvalds dev_kfree_skb_any(skb); 785de903512SRoland Dreier ++dev->stats.tx_dropped; 786943c246eSRoland Dreier return NETDEV_TX_OK; 7871da177e4SLinus Torvalds } 7881da177e4SLinus Torvalds 7891da177e4SLinus Torvalds unicast_arp_send(skb, dev, phdr); 7901da177e4SLinus Torvalds } 7911da177e4SLinus Torvalds } 7921da177e4SLinus Torvalds 7931da177e4SLinus Torvalds return NETDEV_TX_OK; 7941da177e4SLinus Torvalds } 7951da177e4SLinus Torvalds 7961da177e4SLinus Torvalds static void ipoib_timeout(struct net_device *dev) 7971da177e4SLinus Torvalds { 7981da177e4SLinus Torvalds struct ipoib_dev_priv *priv = netdev_priv(dev); 7991da177e4SLinus Torvalds 8004b2d319bSRoland Dreier ipoib_warn(priv, "transmit timeout: latency %d msecs\n", 8014b2d319bSRoland Dreier jiffies_to_msecs(jiffies - dev->trans_start)); 8024b2d319bSRoland Dreier ipoib_warn(priv, "queue stopped %d, tx_head %u, tx_tail %u\n", 8034b2d319bSRoland Dreier netif_queue_stopped(dev), 8044b2d319bSRoland Dreier priv->tx_head, priv->tx_tail); 8051da177e4SLinus Torvalds /* XXX reset QP, etc. */ 8061da177e4SLinus Torvalds } 8071da177e4SLinus Torvalds 8081da177e4SLinus Torvalds static int ipoib_hard_header(struct sk_buff *skb, 8091da177e4SLinus Torvalds struct net_device *dev, 8101da177e4SLinus Torvalds unsigned short type, 8113b04dddeSStephen Hemminger const void *daddr, const void *saddr, unsigned len) 8121da177e4SLinus Torvalds { 8131da177e4SLinus Torvalds struct ipoib_header *header; 8141da177e4SLinus Torvalds 8151da177e4SLinus Torvalds header = (struct ipoib_header *) skb_push(skb, sizeof *header); 8161da177e4SLinus Torvalds 8171da177e4SLinus Torvalds header->proto = htons(type); 8181da177e4SLinus Torvalds header->reserved = 0; 8191da177e4SLinus Torvalds 8201da177e4SLinus Torvalds /* 8211da177e4SLinus Torvalds * If we don't have a neighbour structure, stuff the 8221da177e4SLinus Torvalds * destination address onto the front of the skb so we can 8231da177e4SLinus Torvalds * figure out where to send the packet later. 8241da177e4SLinus Torvalds */ 825adf30907SEric Dumazet if ((!skb_dst(skb) || !skb_dst(skb)->neighbour) && daddr) { 8261da177e4SLinus Torvalds struct ipoib_pseudoheader *phdr = 8271da177e4SLinus Torvalds (struct ipoib_pseudoheader *) skb_push(skb, sizeof *phdr); 8281da177e4SLinus Torvalds memcpy(phdr->hwaddr, daddr, INFINIBAND_ALEN); 8291da177e4SLinus Torvalds } 8301da177e4SLinus Torvalds 8311da177e4SLinus Torvalds return 0; 8321da177e4SLinus Torvalds } 8331da177e4SLinus Torvalds 8341da177e4SLinus Torvalds static void ipoib_set_mcast_list(struct net_device *dev) 8351da177e4SLinus Torvalds { 8361da177e4SLinus Torvalds struct ipoib_dev_priv *priv = netdev_priv(dev); 8371da177e4SLinus Torvalds 8387a343d4cSLeonid Arsh if (!test_bit(IPOIB_FLAG_OPER_UP, &priv->flags)) { 8397a343d4cSLeonid Arsh ipoib_dbg(priv, "IPOIB_FLAG_OPER_UP not set"); 8407a343d4cSLeonid Arsh return; 8417a343d4cSLeonid Arsh } 8427a343d4cSLeonid Arsh 8431ad62a19SMichael S. Tsirkin queue_work(ipoib_workqueue, &priv->restart_task); 8441da177e4SLinus Torvalds } 8451da177e4SLinus Torvalds 846ecbb4169SAlexey Kuznetsov static void ipoib_neigh_cleanup(struct neighbour *n) 8471da177e4SLinus Torvalds { 8481da177e4SLinus Torvalds struct ipoib_neigh *neigh; 8491da177e4SLinus Torvalds struct ipoib_dev_priv *priv = netdev_priv(n->dev); 8501da177e4SLinus Torvalds unsigned long flags; 8511da177e4SLinus Torvalds struct ipoib_ah *ah = NULL; 8521da177e4SLinus Torvalds 853732a2170SMoni Shoua neigh = *to_ipoib_neigh(n); 8547bc531ddSOr Gerlitz if (neigh) 855732a2170SMoni Shoua priv = netdev_priv(neigh->dev); 8567bc531ddSOr Gerlitz else 857732a2170SMoni Shoua return; 8581da177e4SLinus Torvalds ipoib_dbg(priv, 8595b095d98SHarvey Harrison "neigh_cleanup for %06x %pI6\n", 860073ae841SMichael S. Tsirkin IPOIB_QPN(n->ha), 861fcace2feSHarvey Harrison n->ha + 4); 8621da177e4SLinus Torvalds 8631da177e4SLinus Torvalds spin_lock_irqsave(&priv->lock, flags); 8641da177e4SLinus Torvalds 8651da177e4SLinus Torvalds if (neigh->ah) 8661da177e4SLinus Torvalds ah = neigh->ah; 8671da177e4SLinus Torvalds list_del(&neigh->list); 8682745b5b7SMichael S. Tsirkin ipoib_neigh_free(n->dev, neigh); 8691da177e4SLinus Torvalds 8701da177e4SLinus Torvalds spin_unlock_irqrestore(&priv->lock, flags); 8711da177e4SLinus Torvalds 8721da177e4SLinus Torvalds if (ah) 8731da177e4SLinus Torvalds ipoib_put_ah(ah); 8741da177e4SLinus Torvalds } 8751da177e4SLinus Torvalds 876732a2170SMoni Shoua struct ipoib_neigh *ipoib_neigh_alloc(struct neighbour *neighbour, 877732a2170SMoni Shoua struct net_device *dev) 878d2e0655eSMichael S. Tsirkin { 879d2e0655eSMichael S. Tsirkin struct ipoib_neigh *neigh; 880d2e0655eSMichael S. Tsirkin 881d2e0655eSMichael S. Tsirkin neigh = kmalloc(sizeof *neigh, GFP_ATOMIC); 882d2e0655eSMichael S. Tsirkin if (!neigh) 883d2e0655eSMichael S. Tsirkin return NULL; 884d2e0655eSMichael S. Tsirkin 885d2e0655eSMichael S. Tsirkin neigh->neighbour = neighbour; 886732a2170SMoni Shoua neigh->dev = dev; 8870cd4d0fdSDavid J. Wilder memset(&neigh->dgid.raw, 0, sizeof (union ib_gid)); 888d2e0655eSMichael S. Tsirkin *to_ipoib_neigh(neighbour) = neigh; 88982b39913SRoland Dreier skb_queue_head_init(&neigh->queue); 890839fcabaSMichael S. Tsirkin ipoib_cm_set(neigh, NULL); 891d2e0655eSMichael S. Tsirkin 892d2e0655eSMichael S. Tsirkin return neigh; 893d2e0655eSMichael S. Tsirkin } 894d2e0655eSMichael S. Tsirkin 8952745b5b7SMichael S. Tsirkin void ipoib_neigh_free(struct net_device *dev, struct ipoib_neigh *neigh) 896d2e0655eSMichael S. Tsirkin { 8972745b5b7SMichael S. Tsirkin struct sk_buff *skb; 898d2e0655eSMichael S. Tsirkin *to_ipoib_neigh(neigh->neighbour) = NULL; 8992745b5b7SMichael S. Tsirkin while ((skb = __skb_dequeue(&neigh->queue))) { 900de903512SRoland Dreier ++dev->stats.tx_dropped; 9012745b5b7SMichael S. Tsirkin dev_kfree_skb_any(skb); 9022745b5b7SMichael S. Tsirkin } 903839fcabaSMichael S. Tsirkin if (ipoib_cm_get(neigh)) 904839fcabaSMichael S. Tsirkin ipoib_cm_destroy_tx(ipoib_cm_get(neigh)); 905d2e0655eSMichael S. Tsirkin kfree(neigh); 906d2e0655eSMichael S. Tsirkin } 907d2e0655eSMichael S. Tsirkin 9081da177e4SLinus Torvalds static int ipoib_neigh_setup_dev(struct net_device *dev, struct neigh_parms *parms) 9091da177e4SLinus Torvalds { 910ecbb4169SAlexey Kuznetsov parms->neigh_cleanup = ipoib_neigh_cleanup; 9111da177e4SLinus Torvalds 9121da177e4SLinus Torvalds return 0; 9131da177e4SLinus Torvalds } 9141da177e4SLinus Torvalds 9151da177e4SLinus Torvalds int ipoib_dev_init(struct net_device *dev, struct ib_device *ca, int port) 9161da177e4SLinus Torvalds { 9171da177e4SLinus Torvalds struct ipoib_dev_priv *priv = netdev_priv(dev); 9181da177e4SLinus Torvalds 9191da177e4SLinus Torvalds /* Allocate RX/TX "rings" to hold queued skbs */ 9200f485251SShirley Ma priv->rx_ring = kzalloc(ipoib_recvq_size * sizeof *priv->rx_ring, 9211da177e4SLinus Torvalds GFP_KERNEL); 9221da177e4SLinus Torvalds if (!priv->rx_ring) { 9231da177e4SLinus Torvalds printk(KERN_WARNING "%s: failed to allocate RX ring (%d entries)\n", 9240f485251SShirley Ma ca->name, ipoib_recvq_size); 9251da177e4SLinus Torvalds goto out; 9261da177e4SLinus Torvalds } 9271da177e4SLinus Torvalds 92810313cbbSRoland Dreier priv->tx_ring = vmalloc(ipoib_sendq_size * sizeof *priv->tx_ring); 9291da177e4SLinus Torvalds if (!priv->tx_ring) { 9301da177e4SLinus Torvalds printk(KERN_WARNING "%s: failed to allocate TX ring (%d entries)\n", 9310f485251SShirley Ma ca->name, ipoib_sendq_size); 9321da177e4SLinus Torvalds goto out_rx_ring_cleanup; 9331da177e4SLinus Torvalds } 93410313cbbSRoland Dreier memset(priv->tx_ring, 0, ipoib_sendq_size * sizeof *priv->tx_ring); 9351da177e4SLinus Torvalds 9361b524963SMichael S. Tsirkin /* priv->tx_head, tx_tail & tx_outstanding are already 0 */ 9371da177e4SLinus Torvalds 9381da177e4SLinus Torvalds if (ipoib_ib_dev_init(dev, ca, port)) 9391da177e4SLinus Torvalds goto out_tx_ring_cleanup; 9401da177e4SLinus Torvalds 9411da177e4SLinus Torvalds return 0; 9421da177e4SLinus Torvalds 9431da177e4SLinus Torvalds out_tx_ring_cleanup: 94410313cbbSRoland Dreier vfree(priv->tx_ring); 9451da177e4SLinus Torvalds 9461da177e4SLinus Torvalds out_rx_ring_cleanup: 9471da177e4SLinus Torvalds kfree(priv->rx_ring); 9481da177e4SLinus Torvalds 9491da177e4SLinus Torvalds out: 9501da177e4SLinus Torvalds return -ENOMEM; 9511da177e4SLinus Torvalds } 9521da177e4SLinus Torvalds 9531da177e4SLinus Torvalds void ipoib_dev_cleanup(struct net_device *dev) 9541da177e4SLinus Torvalds { 9551da177e4SLinus Torvalds struct ipoib_dev_priv *priv = netdev_priv(dev), *cpriv, *tcpriv; 9561da177e4SLinus Torvalds 9571732b0efSRoland Dreier ipoib_delete_debug_files(dev); 9581da177e4SLinus Torvalds 9591da177e4SLinus Torvalds /* Delete any child interfaces first */ 9601da177e4SLinus Torvalds list_for_each_entry_safe(cpriv, tcpriv, &priv->child_intfs, list) { 9611da177e4SLinus Torvalds unregister_netdev(cpriv->dev); 9621da177e4SLinus Torvalds ipoib_dev_cleanup(cpriv->dev); 9631da177e4SLinus Torvalds free_netdev(cpriv->dev); 9641da177e4SLinus Torvalds } 9651da177e4SLinus Torvalds 9661da177e4SLinus Torvalds ipoib_ib_dev_cleanup(dev); 9671da177e4SLinus Torvalds 9681da177e4SLinus Torvalds kfree(priv->rx_ring); 96910313cbbSRoland Dreier vfree(priv->tx_ring); 97092a6b34bSHal Rosenstock 97192a6b34bSHal Rosenstock priv->rx_ring = NULL; 9721da177e4SLinus Torvalds priv->tx_ring = NULL; 9731da177e4SLinus Torvalds } 9741da177e4SLinus Torvalds 9753b04dddeSStephen Hemminger static const struct header_ops ipoib_header_ops = { 9763b04dddeSStephen Hemminger .create = ipoib_hard_header, 9773b04dddeSStephen Hemminger }; 9783b04dddeSStephen Hemminger 979af40da89SVladimir Sokolovsky static int get_skb_hdr(struct sk_buff *skb, void **iphdr, 980af40da89SVladimir Sokolovsky void **tcph, u64 *hdr_flags, void *priv) 981af40da89SVladimir Sokolovsky { 982af40da89SVladimir Sokolovsky unsigned int ip_len; 983af40da89SVladimir Sokolovsky struct iphdr *iph; 984af40da89SVladimir Sokolovsky 985af40da89SVladimir Sokolovsky if (unlikely(skb->protocol != htons(ETH_P_IP))) 986af40da89SVladimir Sokolovsky return -1; 987af40da89SVladimir Sokolovsky 988af40da89SVladimir Sokolovsky /* 989af40da89SVladimir Sokolovsky * In the future we may add an else clause that verifies the 990af40da89SVladimir Sokolovsky * checksum and allows devices which do not calculate checksum 991af40da89SVladimir Sokolovsky * to use LRO. 992af40da89SVladimir Sokolovsky */ 993af40da89SVladimir Sokolovsky if (unlikely(skb->ip_summed != CHECKSUM_UNNECESSARY)) 994af40da89SVladimir Sokolovsky return -1; 995af40da89SVladimir Sokolovsky 996af40da89SVladimir Sokolovsky /* Check for non-TCP packet */ 997af40da89SVladimir Sokolovsky skb_reset_network_header(skb); 998af40da89SVladimir Sokolovsky iph = ip_hdr(skb); 999af40da89SVladimir Sokolovsky if (iph->protocol != IPPROTO_TCP) 1000af40da89SVladimir Sokolovsky return -1; 1001af40da89SVladimir Sokolovsky 1002af40da89SVladimir Sokolovsky ip_len = ip_hdrlen(skb); 1003af40da89SVladimir Sokolovsky skb_set_transport_header(skb, ip_len); 1004af40da89SVladimir Sokolovsky *tcph = tcp_hdr(skb); 1005af40da89SVladimir Sokolovsky 1006af40da89SVladimir Sokolovsky /* check if IP header and TCP header are complete */ 1007af40da89SVladimir Sokolovsky if (ntohs(iph->tot_len) < ip_len + tcp_hdrlen(skb)) 1008af40da89SVladimir Sokolovsky return -1; 1009af40da89SVladimir Sokolovsky 1010af40da89SVladimir Sokolovsky *hdr_flags = LRO_IPV4 | LRO_TCP; 1011af40da89SVladimir Sokolovsky *iphdr = iph; 1012af40da89SVladimir Sokolovsky 1013af40da89SVladimir Sokolovsky return 0; 1014af40da89SVladimir Sokolovsky } 1015af40da89SVladimir Sokolovsky 1016af40da89SVladimir Sokolovsky static void ipoib_lro_setup(struct ipoib_dev_priv *priv) 1017af40da89SVladimir Sokolovsky { 1018af40da89SVladimir Sokolovsky priv->lro.lro_mgr.max_aggr = lro_max_aggr; 1019af40da89SVladimir Sokolovsky priv->lro.lro_mgr.max_desc = IPOIB_MAX_LRO_DESCRIPTORS; 1020af40da89SVladimir Sokolovsky priv->lro.lro_mgr.lro_arr = priv->lro.lro_desc; 1021af40da89SVladimir Sokolovsky priv->lro.lro_mgr.get_skb_header = get_skb_hdr; 1022af40da89SVladimir Sokolovsky priv->lro.lro_mgr.features = LRO_F_NAPI; 1023af40da89SVladimir Sokolovsky priv->lro.lro_mgr.dev = priv->dev; 1024af40da89SVladimir Sokolovsky priv->lro.lro_mgr.ip_summed_aggr = CHECKSUM_UNNECESSARY; 1025af40da89SVladimir Sokolovsky } 1026af40da89SVladimir Sokolovsky 1027fe8114e8SStephen Hemminger static const struct net_device_ops ipoib_netdev_ops = { 1028fe8114e8SStephen Hemminger .ndo_open = ipoib_open, 1029fe8114e8SStephen Hemminger .ndo_stop = ipoib_stop, 1030fe8114e8SStephen Hemminger .ndo_change_mtu = ipoib_change_mtu, 1031fe8114e8SStephen Hemminger .ndo_start_xmit = ipoib_start_xmit, 1032fe8114e8SStephen Hemminger .ndo_tx_timeout = ipoib_timeout, 1033fe8114e8SStephen Hemminger .ndo_set_multicast_list = ipoib_set_mcast_list, 1034fe8114e8SStephen Hemminger .ndo_neigh_setup = ipoib_neigh_setup_dev, 1035fe8114e8SStephen Hemminger }; 1036fe8114e8SStephen Hemminger 10371da177e4SLinus Torvalds static void ipoib_setup(struct net_device *dev) 10381da177e4SLinus Torvalds { 10391da177e4SLinus Torvalds struct ipoib_dev_priv *priv = netdev_priv(dev); 10401da177e4SLinus Torvalds 1041fe8114e8SStephen Hemminger dev->netdev_ops = &ipoib_netdev_ops; 10423b04dddeSStephen Hemminger dev->header_ops = &ipoib_header_ops; 1043bea3348eSStephen Hemminger 104482c24c18SEli Cohen ipoib_set_ethtool_ops(dev); 104582c24c18SEli Cohen 1046bea3348eSStephen Hemminger netif_napi_add(dev, &priv->napi, ipoib_poll, 100); 10471da177e4SLinus Torvalds 10481da177e4SLinus Torvalds dev->watchdog_timeo = HZ; 10491da177e4SLinus Torvalds 10501da177e4SLinus Torvalds dev->flags |= IFF_BROADCAST | IFF_MULTICAST; 10511da177e4SLinus Torvalds 10521da177e4SLinus Torvalds /* 10531da177e4SLinus Torvalds * We add in INFINIBAND_ALEN to allow for the destination 10541da177e4SLinus Torvalds * address "pseudoheader" for skbs without neighbour struct. 10551da177e4SLinus Torvalds */ 10561da177e4SLinus Torvalds dev->hard_header_len = IPOIB_ENCAP_LEN + INFINIBAND_ALEN; 10571da177e4SLinus Torvalds dev->addr_len = INFINIBAND_ALEN; 10581da177e4SLinus Torvalds dev->type = ARPHRD_INFINIBAND; 10590f485251SShirley Ma dev->tx_queue_len = ipoib_sendq_size * 2; 1060eb14032fSEli Cohen dev->features = (NETIF_F_VLAN_CHALLENGED | 1061eb14032fSEli Cohen NETIF_F_HIGHDMA); 106286d15cd8SEric Dumazet dev->priv_flags &= ~IFF_XMIT_DST_RELEASE; 10631da177e4SLinus Torvalds 10641da177e4SLinus Torvalds memcpy(dev->broadcast, ipv4_bcast_addr, INFINIBAND_ALEN); 10651da177e4SLinus Torvalds 10661da177e4SLinus Torvalds netif_carrier_off(dev); 10671da177e4SLinus Torvalds 10681da177e4SLinus Torvalds priv->dev = dev; 10691da177e4SLinus Torvalds 1070af40da89SVladimir Sokolovsky ipoib_lro_setup(priv); 1071af40da89SVladimir Sokolovsky 10721da177e4SLinus Torvalds spin_lock_init(&priv->lock); 10731da177e4SLinus Torvalds 107495ed644fSIngo Molnar mutex_init(&priv->vlan_mutex); 10751da177e4SLinus Torvalds 10761da177e4SLinus Torvalds INIT_LIST_HEAD(&priv->path_list); 10771da177e4SLinus Torvalds INIT_LIST_HEAD(&priv->child_intfs); 10781da177e4SLinus Torvalds INIT_LIST_HEAD(&priv->dead_ahs); 10791da177e4SLinus Torvalds INIT_LIST_HEAD(&priv->multicast_list); 10801da177e4SLinus Torvalds 108126bbf13cSYosef Etigin INIT_DELAYED_WORK(&priv->pkey_poll_task, ipoib_pkey_poll); 1082c4028958SDavid Howells INIT_DELAYED_WORK(&priv->mcast_task, ipoib_mcast_join_task); 1083e8224e4bSYossi Etigin INIT_WORK(&priv->carrier_on_task, ipoib_mcast_carrier_on_task); 1084ee1e2c82SMoni Shoua INIT_WORK(&priv->flush_light, ipoib_ib_dev_flush_light); 1085ee1e2c82SMoni Shoua INIT_WORK(&priv->flush_normal, ipoib_ib_dev_flush_normal); 1086ee1e2c82SMoni Shoua INIT_WORK(&priv->flush_heavy, ipoib_ib_dev_flush_heavy); 1087c4028958SDavid Howells INIT_WORK(&priv->restart_task, ipoib_mcast_restart_task); 1088c4028958SDavid Howells INIT_DELAYED_WORK(&priv->ah_reap_task, ipoib_reap_ah); 10891da177e4SLinus Torvalds } 10901da177e4SLinus Torvalds 10911da177e4SLinus Torvalds struct ipoib_dev_priv *ipoib_intf_alloc(const char *name) 10921da177e4SLinus Torvalds { 10931da177e4SLinus Torvalds struct net_device *dev; 10941da177e4SLinus Torvalds 10951da177e4SLinus Torvalds dev = alloc_netdev((int) sizeof (struct ipoib_dev_priv), name, 10961da177e4SLinus Torvalds ipoib_setup); 10971da177e4SLinus Torvalds if (!dev) 10981da177e4SLinus Torvalds return NULL; 10991da177e4SLinus Torvalds 11001da177e4SLinus Torvalds return netdev_priv(dev); 11011da177e4SLinus Torvalds } 11021da177e4SLinus Torvalds 110343cb76d9SGreg Kroah-Hartman static ssize_t show_pkey(struct device *dev, 110443cb76d9SGreg Kroah-Hartman struct device_attribute *attr, char *buf) 11051da177e4SLinus Torvalds { 110643cb76d9SGreg Kroah-Hartman struct ipoib_dev_priv *priv = netdev_priv(to_net_dev(dev)); 11071da177e4SLinus Torvalds 11081da177e4SLinus Torvalds return sprintf(buf, "0x%04x\n", priv->pkey); 11091da177e4SLinus Torvalds } 111043cb76d9SGreg Kroah-Hartman static DEVICE_ATTR(pkey, S_IRUGO, show_pkey, NULL); 11111da177e4SLinus Torvalds 1112335a64a5SOr Gerlitz static ssize_t show_umcast(struct device *dev, 1113335a64a5SOr Gerlitz struct device_attribute *attr, char *buf) 1114335a64a5SOr Gerlitz { 1115335a64a5SOr Gerlitz struct ipoib_dev_priv *priv = netdev_priv(to_net_dev(dev)); 1116335a64a5SOr Gerlitz 1117335a64a5SOr Gerlitz return sprintf(buf, "%d\n", test_bit(IPOIB_FLAG_UMCAST, &priv->flags)); 1118335a64a5SOr Gerlitz } 1119335a64a5SOr Gerlitz 1120335a64a5SOr Gerlitz static ssize_t set_umcast(struct device *dev, 1121335a64a5SOr Gerlitz struct device_attribute *attr, 1122335a64a5SOr Gerlitz const char *buf, size_t count) 1123335a64a5SOr Gerlitz { 1124335a64a5SOr Gerlitz struct ipoib_dev_priv *priv = netdev_priv(to_net_dev(dev)); 1125335a64a5SOr Gerlitz unsigned long umcast_val = simple_strtoul(buf, NULL, 0); 1126335a64a5SOr Gerlitz 1127335a64a5SOr Gerlitz if (umcast_val > 0) { 1128335a64a5SOr Gerlitz set_bit(IPOIB_FLAG_UMCAST, &priv->flags); 1129335a64a5SOr Gerlitz ipoib_warn(priv, "ignoring multicast groups joined directly " 1130335a64a5SOr Gerlitz "by userspace\n"); 1131335a64a5SOr Gerlitz } else 1132335a64a5SOr Gerlitz clear_bit(IPOIB_FLAG_UMCAST, &priv->flags); 1133335a64a5SOr Gerlitz 1134335a64a5SOr Gerlitz return count; 1135335a64a5SOr Gerlitz } 1136335a64a5SOr Gerlitz static DEVICE_ATTR(umcast, S_IWUSR | S_IRUGO, show_umcast, set_umcast); 1137335a64a5SOr Gerlitz 1138335a64a5SOr Gerlitz int ipoib_add_umcast_attr(struct net_device *dev) 1139335a64a5SOr Gerlitz { 1140335a64a5SOr Gerlitz return device_create_file(&dev->dev, &dev_attr_umcast); 1141335a64a5SOr Gerlitz } 1142335a64a5SOr Gerlitz 114343cb76d9SGreg Kroah-Hartman static ssize_t create_child(struct device *dev, 114443cb76d9SGreg Kroah-Hartman struct device_attribute *attr, 11451da177e4SLinus Torvalds const char *buf, size_t count) 11461da177e4SLinus Torvalds { 11471da177e4SLinus Torvalds int pkey; 11481da177e4SLinus Torvalds int ret; 11491da177e4SLinus Torvalds 11501da177e4SLinus Torvalds if (sscanf(buf, "%i", &pkey) != 1) 11511da177e4SLinus Torvalds return -EINVAL; 11521da177e4SLinus Torvalds 11531da177e4SLinus Torvalds if (pkey < 0 || pkey > 0xffff) 11541da177e4SLinus Torvalds return -EINVAL; 11551da177e4SLinus Torvalds 11564ce05937SRoland Dreier /* 11574ce05937SRoland Dreier * Set the full membership bit, so that we join the right 11584ce05937SRoland Dreier * broadcast group, etc. 11594ce05937SRoland Dreier */ 11604ce05937SRoland Dreier pkey |= 0x8000; 11614ce05937SRoland Dreier 116243cb76d9SGreg Kroah-Hartman ret = ipoib_vlan_add(to_net_dev(dev), pkey); 11631da177e4SLinus Torvalds 11641da177e4SLinus Torvalds return ret ? ret : count; 11651da177e4SLinus Torvalds } 11667a52b34bSOr Gerlitz static DEVICE_ATTR(create_child, S_IWUSR, NULL, create_child); 11671da177e4SLinus Torvalds 116843cb76d9SGreg Kroah-Hartman static ssize_t delete_child(struct device *dev, 116943cb76d9SGreg Kroah-Hartman struct device_attribute *attr, 11701da177e4SLinus Torvalds const char *buf, size_t count) 11711da177e4SLinus Torvalds { 11721da177e4SLinus Torvalds int pkey; 11731da177e4SLinus Torvalds int ret; 11741da177e4SLinus Torvalds 11751da177e4SLinus Torvalds if (sscanf(buf, "%i", &pkey) != 1) 11761da177e4SLinus Torvalds return -EINVAL; 11771da177e4SLinus Torvalds 11781da177e4SLinus Torvalds if (pkey < 0 || pkey > 0xffff) 11791da177e4SLinus Torvalds return -EINVAL; 11801da177e4SLinus Torvalds 118143cb76d9SGreg Kroah-Hartman ret = ipoib_vlan_delete(to_net_dev(dev), pkey); 11821da177e4SLinus Torvalds 11831da177e4SLinus Torvalds return ret ? ret : count; 11841da177e4SLinus Torvalds 11851da177e4SLinus Torvalds } 11867a52b34bSOr Gerlitz static DEVICE_ATTR(delete_child, S_IWUSR, NULL, delete_child); 11871da177e4SLinus Torvalds 11881da177e4SLinus Torvalds int ipoib_add_pkey_attr(struct net_device *dev) 11891da177e4SLinus Torvalds { 119043cb76d9SGreg Kroah-Hartman return device_create_file(&dev->dev, &dev_attr_pkey); 11911da177e4SLinus Torvalds } 11921da177e4SLinus Torvalds 119383bb63f6SOr Gerlitz int ipoib_set_dev_features(struct ipoib_dev_priv *priv, struct ib_device *hca) 119483bb63f6SOr Gerlitz { 119583bb63f6SOr Gerlitz struct ib_device_attr *device_attr; 119683bb63f6SOr Gerlitz int result = -ENOMEM; 119783bb63f6SOr Gerlitz 119883bb63f6SOr Gerlitz device_attr = kmalloc(sizeof *device_attr, GFP_KERNEL); 119983bb63f6SOr Gerlitz if (!device_attr) { 120083bb63f6SOr Gerlitz printk(KERN_WARNING "%s: allocation of %zu bytes failed\n", 120183bb63f6SOr Gerlitz hca->name, sizeof *device_attr); 120283bb63f6SOr Gerlitz return result; 120383bb63f6SOr Gerlitz } 120483bb63f6SOr Gerlitz 120583bb63f6SOr Gerlitz result = ib_query_device(hca, device_attr); 120683bb63f6SOr Gerlitz if (result) { 120783bb63f6SOr Gerlitz printk(KERN_WARNING "%s: ib_query_device failed (ret = %d)\n", 120883bb63f6SOr Gerlitz hca->name, result); 120983bb63f6SOr Gerlitz kfree(device_attr); 121083bb63f6SOr Gerlitz return result; 121183bb63f6SOr Gerlitz } 121283bb63f6SOr Gerlitz priv->hca_caps = device_attr->device_cap_flags; 121383bb63f6SOr Gerlitz 121483bb63f6SOr Gerlitz kfree(device_attr); 121583bb63f6SOr Gerlitz 121683bb63f6SOr Gerlitz if (priv->hca_caps & IB_DEVICE_UD_IP_CSUM) { 121783bb63f6SOr Gerlitz set_bit(IPOIB_FLAG_CSUM, &priv->flags); 121883bb63f6SOr Gerlitz priv->dev->features |= NETIF_F_SG | NETIF_F_IP_CSUM; 121983bb63f6SOr Gerlitz } 122083bb63f6SOr Gerlitz 122183bb63f6SOr Gerlitz if (lro) 122283bb63f6SOr Gerlitz priv->dev->features |= NETIF_F_LRO; 122383bb63f6SOr Gerlitz 122483bb63f6SOr Gerlitz if (priv->dev->features & NETIF_F_SG && priv->hca_caps & IB_DEVICE_UD_TSO) 122583bb63f6SOr Gerlitz priv->dev->features |= NETIF_F_TSO; 122683bb63f6SOr Gerlitz 122783bb63f6SOr Gerlitz return 0; 122883bb63f6SOr Gerlitz } 122983bb63f6SOr Gerlitz 123083bb63f6SOr Gerlitz 12311da177e4SLinus Torvalds static struct net_device *ipoib_add_port(const char *format, 12321da177e4SLinus Torvalds struct ib_device *hca, u8 port) 12331da177e4SLinus Torvalds { 12341da177e4SLinus Torvalds struct ipoib_dev_priv *priv; 1235bc7b3a36SShirley Ma struct ib_port_attr attr; 12361da177e4SLinus Torvalds int result = -ENOMEM; 12371da177e4SLinus Torvalds 12381da177e4SLinus Torvalds priv = ipoib_intf_alloc(format); 12391da177e4SLinus Torvalds if (!priv) 12401da177e4SLinus Torvalds goto alloc_mem_failed; 12411da177e4SLinus Torvalds 12421da177e4SLinus Torvalds SET_NETDEV_DEV(priv->dev, hca->dma_device); 1243c3aa9b18SEli Cohen priv->dev->dev_id = port - 1; 12441da177e4SLinus Torvalds 1245bc7b3a36SShirley Ma if (!ib_query_port(hca, port, &attr)) 1246bc7b3a36SShirley Ma priv->max_ib_mtu = ib_mtu_enum_to_int(attr.max_mtu); 1247bc7b3a36SShirley Ma else { 1248bc7b3a36SShirley Ma printk(KERN_WARNING "%s: ib_query_port %d failed\n", 1249bc7b3a36SShirley Ma hca->name, port); 1250bc7b3a36SShirley Ma goto device_init_failed; 1251bc7b3a36SShirley Ma } 1252bc7b3a36SShirley Ma 1253bc7b3a36SShirley Ma /* MTU will be reset when mcast join happens */ 1254bc7b3a36SShirley Ma priv->dev->mtu = IPOIB_UD_MTU(priv->max_ib_mtu); 1255bc7b3a36SShirley Ma priv->mcast_mtu = priv->admin_mtu = priv->dev->mtu; 1256bc7b3a36SShirley Ma 12571da177e4SLinus Torvalds result = ib_query_pkey(hca, port, 0, &priv->pkey); 12581da177e4SLinus Torvalds if (result) { 12591da177e4SLinus Torvalds printk(KERN_WARNING "%s: ib_query_pkey port %d failed (ret = %d)\n", 12601da177e4SLinus Torvalds hca->name, port, result); 1261ca6de177SEli Cohen goto device_init_failed; 12621da177e4SLinus Torvalds } 12631da177e4SLinus Torvalds 126483bb63f6SOr Gerlitz if (ipoib_set_dev_features(priv, hca)) 12656046136cSEli Cohen goto device_init_failed; 1266af40da89SVladimir Sokolovsky 12674ce05937SRoland Dreier /* 12684ce05937SRoland Dreier * Set the full membership bit, so that we join the right 12694ce05937SRoland Dreier * broadcast group, etc. 12704ce05937SRoland Dreier */ 12714ce05937SRoland Dreier priv->pkey |= 0x8000; 12724ce05937SRoland Dreier 12731da177e4SLinus Torvalds priv->dev->broadcast[8] = priv->pkey >> 8; 12741da177e4SLinus Torvalds priv->dev->broadcast[9] = priv->pkey & 0xff; 12751da177e4SLinus Torvalds 12761da177e4SLinus Torvalds result = ib_query_gid(hca, port, 0, &priv->local_gid); 12771da177e4SLinus Torvalds if (result) { 12781da177e4SLinus Torvalds printk(KERN_WARNING "%s: ib_query_gid port %d failed (ret = %d)\n", 12791da177e4SLinus Torvalds hca->name, port, result); 1280ca6de177SEli Cohen goto device_init_failed; 12811da177e4SLinus Torvalds } else 12821da177e4SLinus Torvalds memcpy(priv->dev->dev_addr + 4, priv->local_gid.raw, sizeof (union ib_gid)); 12831da177e4SLinus Torvalds 12841da177e4SLinus Torvalds result = ipoib_dev_init(priv->dev, hca, port); 12851da177e4SLinus Torvalds if (result < 0) { 12861da177e4SLinus Torvalds printk(KERN_WARNING "%s: failed to initialize port %d (ret = %d)\n", 12871da177e4SLinus Torvalds hca->name, port, result); 12881da177e4SLinus Torvalds goto device_init_failed; 12891da177e4SLinus Torvalds } 12901da177e4SLinus Torvalds 12911da177e4SLinus Torvalds INIT_IB_EVENT_HANDLER(&priv->event_handler, 12921da177e4SLinus Torvalds priv->ca, ipoib_event); 12931da177e4SLinus Torvalds result = ib_register_event_handler(&priv->event_handler); 12941da177e4SLinus Torvalds if (result < 0) { 12951da177e4SLinus Torvalds printk(KERN_WARNING "%s: ib_register_event_handler failed for " 12961da177e4SLinus Torvalds "port %d (ret = %d)\n", 12971da177e4SLinus Torvalds hca->name, port, result); 12981da177e4SLinus Torvalds goto event_failed; 12991da177e4SLinus Torvalds } 13001da177e4SLinus Torvalds 13011da177e4SLinus Torvalds result = register_netdev(priv->dev); 13021da177e4SLinus Torvalds if (result) { 13031da177e4SLinus Torvalds printk(KERN_WARNING "%s: couldn't register ipoib port %d; error %d\n", 13041da177e4SLinus Torvalds hca->name, port, result); 13051da177e4SLinus Torvalds goto register_failed; 13061da177e4SLinus Torvalds } 13071da177e4SLinus Torvalds 13081732b0efSRoland Dreier ipoib_create_debug_files(priv->dev); 13091da177e4SLinus Torvalds 1310839fcabaSMichael S. Tsirkin if (ipoib_cm_add_mode_attr(priv->dev)) 1311839fcabaSMichael S. Tsirkin goto sysfs_failed; 13121da177e4SLinus Torvalds if (ipoib_add_pkey_attr(priv->dev)) 13131da177e4SLinus Torvalds goto sysfs_failed; 1314335a64a5SOr Gerlitz if (ipoib_add_umcast_attr(priv->dev)) 1315335a64a5SOr Gerlitz goto sysfs_failed; 131643cb76d9SGreg Kroah-Hartman if (device_create_file(&priv->dev->dev, &dev_attr_create_child)) 13171da177e4SLinus Torvalds goto sysfs_failed; 131843cb76d9SGreg Kroah-Hartman if (device_create_file(&priv->dev->dev, &dev_attr_delete_child)) 13191da177e4SLinus Torvalds goto sysfs_failed; 13201da177e4SLinus Torvalds 13211da177e4SLinus Torvalds return priv->dev; 13221da177e4SLinus Torvalds 13231da177e4SLinus Torvalds sysfs_failed: 13241732b0efSRoland Dreier ipoib_delete_debug_files(priv->dev); 13251da177e4SLinus Torvalds unregister_netdev(priv->dev); 13261da177e4SLinus Torvalds 13271da177e4SLinus Torvalds register_failed: 13281da177e4SLinus Torvalds ib_unregister_event_handler(&priv->event_handler); 1329a77a57a1SRoland Dreier flush_workqueue(ipoib_workqueue); 13301da177e4SLinus Torvalds 13311da177e4SLinus Torvalds event_failed: 13321da177e4SLinus Torvalds ipoib_dev_cleanup(priv->dev); 13331da177e4SLinus Torvalds 13341da177e4SLinus Torvalds device_init_failed: 13351da177e4SLinus Torvalds free_netdev(priv->dev); 13361da177e4SLinus Torvalds 13371da177e4SLinus Torvalds alloc_mem_failed: 13381da177e4SLinus Torvalds return ERR_PTR(result); 13391da177e4SLinus Torvalds } 13401da177e4SLinus Torvalds 13411da177e4SLinus Torvalds static void ipoib_add_one(struct ib_device *device) 13421da177e4SLinus Torvalds { 13431da177e4SLinus Torvalds struct list_head *dev_list; 13441da177e4SLinus Torvalds struct net_device *dev; 13451da177e4SLinus Torvalds struct ipoib_dev_priv *priv; 13461da177e4SLinus Torvalds int s, e, p; 13471da177e4SLinus Torvalds 134807ebafbaSTom Tucker if (rdma_node_get_transport(device->node_type) != RDMA_TRANSPORT_IB) 134907ebafbaSTom Tucker return; 135007ebafbaSTom Tucker 13511da177e4SLinus Torvalds dev_list = kmalloc(sizeof *dev_list, GFP_KERNEL); 13521da177e4SLinus Torvalds if (!dev_list) 13531da177e4SLinus Torvalds return; 13541da177e4SLinus Torvalds 13551da177e4SLinus Torvalds INIT_LIST_HEAD(dev_list); 13561da177e4SLinus Torvalds 135707ebafbaSTom Tucker if (device->node_type == RDMA_NODE_IB_SWITCH) { 13581da177e4SLinus Torvalds s = 0; 13591da177e4SLinus Torvalds e = 0; 13601da177e4SLinus Torvalds } else { 13611da177e4SLinus Torvalds s = 1; 13621da177e4SLinus Torvalds e = device->phys_port_cnt; 13631da177e4SLinus Torvalds } 13641da177e4SLinus Torvalds 13651da177e4SLinus Torvalds for (p = s; p <= e; ++p) { 13661da177e4SLinus Torvalds dev = ipoib_add_port("ib%d", device, p); 13671da177e4SLinus Torvalds if (!IS_ERR(dev)) { 13681da177e4SLinus Torvalds priv = netdev_priv(dev); 13691da177e4SLinus Torvalds list_add_tail(&priv->list, dev_list); 13701da177e4SLinus Torvalds } 13711da177e4SLinus Torvalds } 13721da177e4SLinus Torvalds 13731da177e4SLinus Torvalds ib_set_client_data(device, &ipoib_client, dev_list); 13741da177e4SLinus Torvalds } 13751da177e4SLinus Torvalds 13761da177e4SLinus Torvalds static void ipoib_remove_one(struct ib_device *device) 13771da177e4SLinus Torvalds { 13781da177e4SLinus Torvalds struct ipoib_dev_priv *priv, *tmp; 13791da177e4SLinus Torvalds struct list_head *dev_list; 13801da177e4SLinus Torvalds 138107ebafbaSTom Tucker if (rdma_node_get_transport(device->node_type) != RDMA_TRANSPORT_IB) 138207ebafbaSTom Tucker return; 138307ebafbaSTom Tucker 13841da177e4SLinus Torvalds dev_list = ib_get_client_data(device, &ipoib_client); 13851da177e4SLinus Torvalds 13861da177e4SLinus Torvalds list_for_each_entry_safe(priv, tmp, dev_list, list) { 13871da177e4SLinus Torvalds ib_unregister_event_handler(&priv->event_handler); 1388a77a57a1SRoland Dreier 1389a77a57a1SRoland Dreier rtnl_lock(); 1390a77a57a1SRoland Dreier dev_change_flags(priv->dev, priv->dev->flags & ~IFF_UP); 1391a77a57a1SRoland Dreier rtnl_unlock(); 1392a77a57a1SRoland Dreier 1393a77a57a1SRoland Dreier flush_workqueue(ipoib_workqueue); 13941da177e4SLinus Torvalds 13951da177e4SLinus Torvalds unregister_netdev(priv->dev); 13961da177e4SLinus Torvalds ipoib_dev_cleanup(priv->dev); 13971da177e4SLinus Torvalds free_netdev(priv->dev); 13981da177e4SLinus Torvalds } 139906c56e44SMichael S. Tsirkin 140006c56e44SMichael S. Tsirkin kfree(dev_list); 14011da177e4SLinus Torvalds } 14021da177e4SLinus Torvalds 14031da177e4SLinus Torvalds static int __init ipoib_init_module(void) 14041da177e4SLinus Torvalds { 14051da177e4SLinus Torvalds int ret; 14061da177e4SLinus Torvalds 14070f485251SShirley Ma ipoib_recvq_size = roundup_pow_of_two(ipoib_recvq_size); 14080f485251SShirley Ma ipoib_recvq_size = min(ipoib_recvq_size, IPOIB_MAX_QUEUE_SIZE); 14090f485251SShirley Ma ipoib_recvq_size = max(ipoib_recvq_size, IPOIB_MIN_QUEUE_SIZE); 14100f485251SShirley Ma 14110f485251SShirley Ma ipoib_sendq_size = roundup_pow_of_two(ipoib_sendq_size); 14120f485251SShirley Ma ipoib_sendq_size = min(ipoib_sendq_size, IPOIB_MAX_QUEUE_SIZE); 1413f56bcd80SEli Cohen ipoib_sendq_size = max(ipoib_sendq_size, max(2 * MAX_SEND_CQE, 1414f56bcd80SEli Cohen IPOIB_MIN_QUEUE_SIZE)); 141568e995a2SPradeep Satyanarayana #ifdef CONFIG_INFINIBAND_IPOIB_CM 141668e995a2SPradeep Satyanarayana ipoib_max_conn_qp = min(ipoib_max_conn_qp, IPOIB_CM_MAX_CONN_QP); 141768e995a2SPradeep Satyanarayana #endif 14180f485251SShirley Ma 1419f89271daSEli Cohen /* 1420f89271daSEli Cohen * When copying small received packets, we only copy from the 1421f89271daSEli Cohen * linear data part of the SKB, so we rely on this condition. 1422f89271daSEli Cohen */ 1423f89271daSEli Cohen BUILD_BUG_ON(IPOIB_CM_COPYBREAK > IPOIB_CM_HEAD_SIZE); 1424f89271daSEli Cohen 14251da177e4SLinus Torvalds ret = ipoib_register_debugfs(); 14261da177e4SLinus Torvalds if (ret) 14271da177e4SLinus Torvalds return ret; 14281da177e4SLinus Torvalds 14291da177e4SLinus Torvalds /* 14301da177e4SLinus Torvalds * We create our own workqueue mainly because we want to be 14311da177e4SLinus Torvalds * able to flush it when devices are being removed. We can't 14321da177e4SLinus Torvalds * use schedule_work()/flush_scheduled_work() because both 14331da177e4SLinus Torvalds * unregister_netdev() and linkwatch_event take the rtnl lock, 14341da177e4SLinus Torvalds * so flush_scheduled_work() can deadlock during device 14351da177e4SLinus Torvalds * removal. 14361da177e4SLinus Torvalds */ 14371da177e4SLinus Torvalds ipoib_workqueue = create_singlethread_workqueue("ipoib"); 14381da177e4SLinus Torvalds if (!ipoib_workqueue) { 14391da177e4SLinus Torvalds ret = -ENOMEM; 14401da177e4SLinus Torvalds goto err_fs; 14411da177e4SLinus Torvalds } 14421da177e4SLinus Torvalds 1443c1a0b23bSMichael S. Tsirkin ib_sa_register_client(&ipoib_sa_client); 1444c1a0b23bSMichael S. Tsirkin 14451da177e4SLinus Torvalds ret = ib_register_client(&ipoib_client); 14461da177e4SLinus Torvalds if (ret) 1447c1a0b23bSMichael S. Tsirkin goto err_sa; 14481da177e4SLinus Torvalds 14491da177e4SLinus Torvalds return 0; 14501da177e4SLinus Torvalds 1451c1a0b23bSMichael S. Tsirkin err_sa: 1452c1a0b23bSMichael S. Tsirkin ib_sa_unregister_client(&ipoib_sa_client); 14531da177e4SLinus Torvalds destroy_workqueue(ipoib_workqueue); 14541da177e4SLinus Torvalds 14559adec1a8SRoland Dreier err_fs: 14569adec1a8SRoland Dreier ipoib_unregister_debugfs(); 14579adec1a8SRoland Dreier 14581da177e4SLinus Torvalds return ret; 14591da177e4SLinus Torvalds } 14601da177e4SLinus Torvalds 14611da177e4SLinus Torvalds static void __exit ipoib_cleanup_module(void) 14621da177e4SLinus Torvalds { 14631da177e4SLinus Torvalds ib_unregister_client(&ipoib_client); 1464c1a0b23bSMichael S. Tsirkin ib_sa_unregister_client(&ipoib_sa_client); 14659adec1a8SRoland Dreier ipoib_unregister_debugfs(); 14661da177e4SLinus Torvalds destroy_workqueue(ipoib_workqueue); 14671da177e4SLinus Torvalds } 14681da177e4SLinus Torvalds 14691da177e4SLinus Torvalds module_init(ipoib_init_module); 14701da177e4SLinus Torvalds module_exit(ipoib_cleanup_module); 1471