18c2ecf20Sopenharmony_ci/* 28c2ecf20Sopenharmony_ci * Copyright (c) 2004, 2005 Topspin Communications. All rights reserved. 38c2ecf20Sopenharmony_ci * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved. 48c2ecf20Sopenharmony_ci * Copyright (c) 2004 Voltaire, Inc. All rights reserved. 58c2ecf20Sopenharmony_ci * 68c2ecf20Sopenharmony_ci * This software is available to you under a choice of one of two 78c2ecf20Sopenharmony_ci * licenses. You may choose to be licensed under the terms of the GNU 88c2ecf20Sopenharmony_ci * General Public License (GPL) Version 2, available from the file 98c2ecf20Sopenharmony_ci * COPYING in the main directory of this source tree, or the 108c2ecf20Sopenharmony_ci * OpenIB.org BSD license below: 118c2ecf20Sopenharmony_ci * 128c2ecf20Sopenharmony_ci * Redistribution and use in source and binary forms, with or 138c2ecf20Sopenharmony_ci * without modification, are permitted provided that the following 148c2ecf20Sopenharmony_ci * conditions are met: 158c2ecf20Sopenharmony_ci * 168c2ecf20Sopenharmony_ci * - Redistributions of source code must retain the above 178c2ecf20Sopenharmony_ci * copyright notice, this list of conditions and the following 188c2ecf20Sopenharmony_ci * disclaimer. 198c2ecf20Sopenharmony_ci * 208c2ecf20Sopenharmony_ci * - Redistributions in binary form must reproduce the above 218c2ecf20Sopenharmony_ci * copyright notice, this list of conditions and the following 228c2ecf20Sopenharmony_ci * disclaimer in the documentation and/or other materials 238c2ecf20Sopenharmony_ci * provided with the distribution. 248c2ecf20Sopenharmony_ci * 258c2ecf20Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 268c2ecf20Sopenharmony_ci * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 278c2ecf20Sopenharmony_ci * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 288c2ecf20Sopenharmony_ci * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 298c2ecf20Sopenharmony_ci * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 308c2ecf20Sopenharmony_ci * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 318c2ecf20Sopenharmony_ci * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 328c2ecf20Sopenharmony_ci * SOFTWARE. 338c2ecf20Sopenharmony_ci */ 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_ci#include <linux/skbuff.h> 368c2ecf20Sopenharmony_ci#include <linux/rtnetlink.h> 378c2ecf20Sopenharmony_ci#include <linux/moduleparam.h> 388c2ecf20Sopenharmony_ci#include <linux/ip.h> 398c2ecf20Sopenharmony_ci#include <linux/in.h> 408c2ecf20Sopenharmony_ci#include <linux/igmp.h> 418c2ecf20Sopenharmony_ci#include <linux/inetdevice.h> 428c2ecf20Sopenharmony_ci#include <linux/delay.h> 438c2ecf20Sopenharmony_ci#include <linux/completion.h> 448c2ecf20Sopenharmony_ci#include <linux/slab.h> 458c2ecf20Sopenharmony_ci 468c2ecf20Sopenharmony_ci#include <net/dst.h> 478c2ecf20Sopenharmony_ci 488c2ecf20Sopenharmony_ci#include "ipoib.h" 498c2ecf20Sopenharmony_ci 508c2ecf20Sopenharmony_ci#ifdef CONFIG_INFINIBAND_IPOIB_DEBUG 518c2ecf20Sopenharmony_cistatic int mcast_debug_level; 528c2ecf20Sopenharmony_ci 538c2ecf20Sopenharmony_cimodule_param(mcast_debug_level, int, 0644); 548c2ecf20Sopenharmony_ciMODULE_PARM_DESC(mcast_debug_level, 558c2ecf20Sopenharmony_ci "Enable multicast debug tracing if > 0"); 568c2ecf20Sopenharmony_ci#endif 578c2ecf20Sopenharmony_ci 588c2ecf20Sopenharmony_cistruct ipoib_mcast_iter { 598c2ecf20Sopenharmony_ci struct net_device *dev; 608c2ecf20Sopenharmony_ci union ib_gid mgid; 618c2ecf20Sopenharmony_ci unsigned long created; 628c2ecf20Sopenharmony_ci unsigned int queuelen; 638c2ecf20Sopenharmony_ci unsigned int complete; 648c2ecf20Sopenharmony_ci unsigned int send_only; 658c2ecf20Sopenharmony_ci}; 668c2ecf20Sopenharmony_ci 678c2ecf20Sopenharmony_ci/* join state that allows creating mcg with sendonly member request */ 688c2ecf20Sopenharmony_ci#define SENDONLY_FULLMEMBER_JOIN 8 698c2ecf20Sopenharmony_ci 708c2ecf20Sopenharmony_ci/* 718c2ecf20Sopenharmony_ci * This should be called with the priv->lock held 728c2ecf20Sopenharmony_ci */ 738c2ecf20Sopenharmony_cistatic void __ipoib_mcast_schedule_join_thread(struct ipoib_dev_priv *priv, 748c2ecf20Sopenharmony_ci struct ipoib_mcast *mcast, 758c2ecf20Sopenharmony_ci bool delay) 768c2ecf20Sopenharmony_ci{ 778c2ecf20Sopenharmony_ci if (!test_bit(IPOIB_FLAG_OPER_UP, &priv->flags)) 788c2ecf20Sopenharmony_ci return; 798c2ecf20Sopenharmony_ci 808c2ecf20Sopenharmony_ci /* 818c2ecf20Sopenharmony_ci * We will be scheduling *something*, so cancel whatever is 828c2ecf20Sopenharmony_ci * currently scheduled first 838c2ecf20Sopenharmony_ci */ 848c2ecf20Sopenharmony_ci cancel_delayed_work(&priv->mcast_task); 858c2ecf20Sopenharmony_ci if (mcast && delay) { 868c2ecf20Sopenharmony_ci /* 878c2ecf20Sopenharmony_ci * We had a failure and want to schedule a retry later 888c2ecf20Sopenharmony_ci */ 898c2ecf20Sopenharmony_ci mcast->backoff *= 2; 908c2ecf20Sopenharmony_ci if (mcast->backoff > IPOIB_MAX_BACKOFF_SECONDS) 918c2ecf20Sopenharmony_ci mcast->backoff = IPOIB_MAX_BACKOFF_SECONDS; 928c2ecf20Sopenharmony_ci mcast->delay_until = jiffies + (mcast->backoff * HZ); 938c2ecf20Sopenharmony_ci /* 948c2ecf20Sopenharmony_ci * Mark this mcast for its delay, but restart the 958c2ecf20Sopenharmony_ci * task immediately. The join task will make sure to 968c2ecf20Sopenharmony_ci * clear out all entries without delays, and then 978c2ecf20Sopenharmony_ci * schedule itself to run again when the earliest 988c2ecf20Sopenharmony_ci * delay expires 998c2ecf20Sopenharmony_ci */ 1008c2ecf20Sopenharmony_ci queue_delayed_work(priv->wq, &priv->mcast_task, 0); 1018c2ecf20Sopenharmony_ci } else if (delay) { 1028c2ecf20Sopenharmony_ci /* 1038c2ecf20Sopenharmony_ci * Special case of retrying after a failure to 1048c2ecf20Sopenharmony_ci * allocate the broadcast multicast group, wait 1058c2ecf20Sopenharmony_ci * 1 second and try again 1068c2ecf20Sopenharmony_ci */ 1078c2ecf20Sopenharmony_ci queue_delayed_work(priv->wq, &priv->mcast_task, HZ); 1088c2ecf20Sopenharmony_ci } else 1098c2ecf20Sopenharmony_ci queue_delayed_work(priv->wq, &priv->mcast_task, 0); 1108c2ecf20Sopenharmony_ci} 1118c2ecf20Sopenharmony_ci 1128c2ecf20Sopenharmony_cistatic void ipoib_mcast_free(struct ipoib_mcast *mcast) 1138c2ecf20Sopenharmony_ci{ 1148c2ecf20Sopenharmony_ci struct net_device *dev = mcast->dev; 1158c2ecf20Sopenharmony_ci int tx_dropped = 0; 1168c2ecf20Sopenharmony_ci 1178c2ecf20Sopenharmony_ci ipoib_dbg_mcast(ipoib_priv(dev), "deleting multicast group %pI6\n", 1188c2ecf20Sopenharmony_ci mcast->mcmember.mgid.raw); 1198c2ecf20Sopenharmony_ci 1208c2ecf20Sopenharmony_ci /* remove all neigh connected to this mcast */ 1218c2ecf20Sopenharmony_ci ipoib_del_neighs_by_gid(dev, mcast->mcmember.mgid.raw); 1228c2ecf20Sopenharmony_ci 1238c2ecf20Sopenharmony_ci if (mcast->ah) 1248c2ecf20Sopenharmony_ci ipoib_put_ah(mcast->ah); 1258c2ecf20Sopenharmony_ci 1268c2ecf20Sopenharmony_ci while (!skb_queue_empty(&mcast->pkt_queue)) { 1278c2ecf20Sopenharmony_ci ++tx_dropped; 1288c2ecf20Sopenharmony_ci dev_kfree_skb_any(skb_dequeue(&mcast->pkt_queue)); 1298c2ecf20Sopenharmony_ci } 1308c2ecf20Sopenharmony_ci 1318c2ecf20Sopenharmony_ci netif_tx_lock_bh(dev); 1328c2ecf20Sopenharmony_ci dev->stats.tx_dropped += tx_dropped; 1338c2ecf20Sopenharmony_ci netif_tx_unlock_bh(dev); 1348c2ecf20Sopenharmony_ci 1358c2ecf20Sopenharmony_ci kfree(mcast); 1368c2ecf20Sopenharmony_ci} 1378c2ecf20Sopenharmony_ci 1388c2ecf20Sopenharmony_cistatic struct ipoib_mcast *ipoib_mcast_alloc(struct net_device *dev) 1398c2ecf20Sopenharmony_ci{ 1408c2ecf20Sopenharmony_ci struct ipoib_mcast *mcast; 1418c2ecf20Sopenharmony_ci 1428c2ecf20Sopenharmony_ci mcast = kzalloc(sizeof(*mcast), GFP_ATOMIC); 1438c2ecf20Sopenharmony_ci if (!mcast) 1448c2ecf20Sopenharmony_ci return NULL; 1458c2ecf20Sopenharmony_ci 1468c2ecf20Sopenharmony_ci mcast->dev = dev; 1478c2ecf20Sopenharmony_ci mcast->created = jiffies; 1488c2ecf20Sopenharmony_ci mcast->delay_until = jiffies; 1498c2ecf20Sopenharmony_ci mcast->backoff = 1; 1508c2ecf20Sopenharmony_ci 1518c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&mcast->list); 1528c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&mcast->neigh_list); 1538c2ecf20Sopenharmony_ci skb_queue_head_init(&mcast->pkt_queue); 1548c2ecf20Sopenharmony_ci 1558c2ecf20Sopenharmony_ci return mcast; 1568c2ecf20Sopenharmony_ci} 1578c2ecf20Sopenharmony_ci 1588c2ecf20Sopenharmony_cistatic struct ipoib_mcast *__ipoib_mcast_find(struct net_device *dev, void *mgid) 1598c2ecf20Sopenharmony_ci{ 1608c2ecf20Sopenharmony_ci struct ipoib_dev_priv *priv = ipoib_priv(dev); 1618c2ecf20Sopenharmony_ci struct rb_node *n = priv->multicast_tree.rb_node; 1628c2ecf20Sopenharmony_ci 1638c2ecf20Sopenharmony_ci while (n) { 1648c2ecf20Sopenharmony_ci struct ipoib_mcast *mcast; 1658c2ecf20Sopenharmony_ci int ret; 1668c2ecf20Sopenharmony_ci 1678c2ecf20Sopenharmony_ci mcast = rb_entry(n, struct ipoib_mcast, rb_node); 1688c2ecf20Sopenharmony_ci 1698c2ecf20Sopenharmony_ci ret = memcmp(mgid, mcast->mcmember.mgid.raw, 1708c2ecf20Sopenharmony_ci sizeof (union ib_gid)); 1718c2ecf20Sopenharmony_ci if (ret < 0) 1728c2ecf20Sopenharmony_ci n = n->rb_left; 1738c2ecf20Sopenharmony_ci else if (ret > 0) 1748c2ecf20Sopenharmony_ci n = n->rb_right; 1758c2ecf20Sopenharmony_ci else 1768c2ecf20Sopenharmony_ci return mcast; 1778c2ecf20Sopenharmony_ci } 1788c2ecf20Sopenharmony_ci 1798c2ecf20Sopenharmony_ci return NULL; 1808c2ecf20Sopenharmony_ci} 1818c2ecf20Sopenharmony_ci 1828c2ecf20Sopenharmony_cistatic int __ipoib_mcast_add(struct net_device *dev, struct ipoib_mcast *mcast) 1838c2ecf20Sopenharmony_ci{ 1848c2ecf20Sopenharmony_ci struct ipoib_dev_priv *priv = ipoib_priv(dev); 1858c2ecf20Sopenharmony_ci struct rb_node **n = &priv->multicast_tree.rb_node, *pn = NULL; 1868c2ecf20Sopenharmony_ci 1878c2ecf20Sopenharmony_ci while (*n) { 1888c2ecf20Sopenharmony_ci struct ipoib_mcast *tmcast; 1898c2ecf20Sopenharmony_ci int ret; 1908c2ecf20Sopenharmony_ci 1918c2ecf20Sopenharmony_ci pn = *n; 1928c2ecf20Sopenharmony_ci tmcast = rb_entry(pn, struct ipoib_mcast, rb_node); 1938c2ecf20Sopenharmony_ci 1948c2ecf20Sopenharmony_ci ret = memcmp(mcast->mcmember.mgid.raw, tmcast->mcmember.mgid.raw, 1958c2ecf20Sopenharmony_ci sizeof (union ib_gid)); 1968c2ecf20Sopenharmony_ci if (ret < 0) 1978c2ecf20Sopenharmony_ci n = &pn->rb_left; 1988c2ecf20Sopenharmony_ci else if (ret > 0) 1998c2ecf20Sopenharmony_ci n = &pn->rb_right; 2008c2ecf20Sopenharmony_ci else 2018c2ecf20Sopenharmony_ci return -EEXIST; 2028c2ecf20Sopenharmony_ci } 2038c2ecf20Sopenharmony_ci 2048c2ecf20Sopenharmony_ci rb_link_node(&mcast->rb_node, pn, n); 2058c2ecf20Sopenharmony_ci rb_insert_color(&mcast->rb_node, &priv->multicast_tree); 2068c2ecf20Sopenharmony_ci 2078c2ecf20Sopenharmony_ci return 0; 2088c2ecf20Sopenharmony_ci} 2098c2ecf20Sopenharmony_ci 2108c2ecf20Sopenharmony_cistatic int ipoib_mcast_join_finish(struct ipoib_mcast *mcast, 2118c2ecf20Sopenharmony_ci struct ib_sa_mcmember_rec *mcmember) 2128c2ecf20Sopenharmony_ci{ 2138c2ecf20Sopenharmony_ci struct net_device *dev = mcast->dev; 2148c2ecf20Sopenharmony_ci struct ipoib_dev_priv *priv = ipoib_priv(dev); 2158c2ecf20Sopenharmony_ci struct rdma_netdev *rn = netdev_priv(dev); 2168c2ecf20Sopenharmony_ci struct ipoib_ah *ah; 2178c2ecf20Sopenharmony_ci struct rdma_ah_attr av; 2188c2ecf20Sopenharmony_ci int ret; 2198c2ecf20Sopenharmony_ci int set_qkey = 0; 2208c2ecf20Sopenharmony_ci int mtu; 2218c2ecf20Sopenharmony_ci 2228c2ecf20Sopenharmony_ci mcast->mcmember = *mcmember; 2238c2ecf20Sopenharmony_ci 2248c2ecf20Sopenharmony_ci /* Set the multicast MTU and cached Q_Key before we attach if it's 2258c2ecf20Sopenharmony_ci * the broadcast group. 2268c2ecf20Sopenharmony_ci */ 2278c2ecf20Sopenharmony_ci if (!memcmp(mcast->mcmember.mgid.raw, priv->dev->broadcast + 4, 2288c2ecf20Sopenharmony_ci sizeof (union ib_gid))) { 2298c2ecf20Sopenharmony_ci spin_lock_irq(&priv->lock); 2308c2ecf20Sopenharmony_ci if (!priv->broadcast) { 2318c2ecf20Sopenharmony_ci spin_unlock_irq(&priv->lock); 2328c2ecf20Sopenharmony_ci return -EAGAIN; 2338c2ecf20Sopenharmony_ci } 2348c2ecf20Sopenharmony_ci /*update priv member according to the new mcast*/ 2358c2ecf20Sopenharmony_ci priv->broadcast->mcmember.qkey = mcmember->qkey; 2368c2ecf20Sopenharmony_ci priv->broadcast->mcmember.mtu = mcmember->mtu; 2378c2ecf20Sopenharmony_ci priv->broadcast->mcmember.traffic_class = mcmember->traffic_class; 2388c2ecf20Sopenharmony_ci priv->broadcast->mcmember.rate = mcmember->rate; 2398c2ecf20Sopenharmony_ci priv->broadcast->mcmember.sl = mcmember->sl; 2408c2ecf20Sopenharmony_ci priv->broadcast->mcmember.flow_label = mcmember->flow_label; 2418c2ecf20Sopenharmony_ci priv->broadcast->mcmember.hop_limit = mcmember->hop_limit; 2428c2ecf20Sopenharmony_ci /* assume if the admin and the mcast are the same both can be changed */ 2438c2ecf20Sopenharmony_ci mtu = rdma_mtu_enum_to_int(priv->ca, priv->port, 2448c2ecf20Sopenharmony_ci priv->broadcast->mcmember.mtu); 2458c2ecf20Sopenharmony_ci if (priv->mcast_mtu == priv->admin_mtu) 2468c2ecf20Sopenharmony_ci priv->admin_mtu = IPOIB_UD_MTU(mtu); 2478c2ecf20Sopenharmony_ci priv->mcast_mtu = IPOIB_UD_MTU(mtu); 2488c2ecf20Sopenharmony_ci rn->mtu = priv->mcast_mtu; 2498c2ecf20Sopenharmony_ci 2508c2ecf20Sopenharmony_ci priv->qkey = be32_to_cpu(priv->broadcast->mcmember.qkey); 2518c2ecf20Sopenharmony_ci spin_unlock_irq(&priv->lock); 2528c2ecf20Sopenharmony_ci priv->tx_wr.remote_qkey = priv->qkey; 2538c2ecf20Sopenharmony_ci set_qkey = 1; 2548c2ecf20Sopenharmony_ci } 2558c2ecf20Sopenharmony_ci 2568c2ecf20Sopenharmony_ci if (!test_bit(IPOIB_MCAST_FLAG_SENDONLY, &mcast->flags)) { 2578c2ecf20Sopenharmony_ci if (test_and_set_bit(IPOIB_MCAST_FLAG_ATTACHED, &mcast->flags)) { 2588c2ecf20Sopenharmony_ci ipoib_warn(priv, "multicast group %pI6 already attached\n", 2598c2ecf20Sopenharmony_ci mcast->mcmember.mgid.raw); 2608c2ecf20Sopenharmony_ci 2618c2ecf20Sopenharmony_ci return 0; 2628c2ecf20Sopenharmony_ci } 2638c2ecf20Sopenharmony_ci 2648c2ecf20Sopenharmony_ci ret = rn->attach_mcast(dev, priv->ca, &mcast->mcmember.mgid, 2658c2ecf20Sopenharmony_ci be16_to_cpu(mcast->mcmember.mlid), 2668c2ecf20Sopenharmony_ci set_qkey, priv->qkey); 2678c2ecf20Sopenharmony_ci if (ret < 0) { 2688c2ecf20Sopenharmony_ci ipoib_warn(priv, "couldn't attach QP to multicast group %pI6\n", 2698c2ecf20Sopenharmony_ci mcast->mcmember.mgid.raw); 2708c2ecf20Sopenharmony_ci 2718c2ecf20Sopenharmony_ci clear_bit(IPOIB_MCAST_FLAG_ATTACHED, &mcast->flags); 2728c2ecf20Sopenharmony_ci return ret; 2738c2ecf20Sopenharmony_ci } 2748c2ecf20Sopenharmony_ci } 2758c2ecf20Sopenharmony_ci 2768c2ecf20Sopenharmony_ci memset(&av, 0, sizeof(av)); 2778c2ecf20Sopenharmony_ci av.type = rdma_ah_find_type(priv->ca, priv->port); 2788c2ecf20Sopenharmony_ci rdma_ah_set_dlid(&av, be16_to_cpu(mcast->mcmember.mlid)), 2798c2ecf20Sopenharmony_ci rdma_ah_set_port_num(&av, priv->port); 2808c2ecf20Sopenharmony_ci rdma_ah_set_sl(&av, mcast->mcmember.sl); 2818c2ecf20Sopenharmony_ci rdma_ah_set_static_rate(&av, mcast->mcmember.rate); 2828c2ecf20Sopenharmony_ci 2838c2ecf20Sopenharmony_ci rdma_ah_set_grh(&av, &mcast->mcmember.mgid, 2848c2ecf20Sopenharmony_ci be32_to_cpu(mcast->mcmember.flow_label), 2858c2ecf20Sopenharmony_ci 0, mcast->mcmember.hop_limit, 2868c2ecf20Sopenharmony_ci mcast->mcmember.traffic_class); 2878c2ecf20Sopenharmony_ci 2888c2ecf20Sopenharmony_ci ah = ipoib_create_ah(dev, priv->pd, &av); 2898c2ecf20Sopenharmony_ci if (IS_ERR(ah)) { 2908c2ecf20Sopenharmony_ci ipoib_warn(priv, "ib_address_create failed %ld\n", 2918c2ecf20Sopenharmony_ci -PTR_ERR(ah)); 2928c2ecf20Sopenharmony_ci /* use original error */ 2938c2ecf20Sopenharmony_ci return PTR_ERR(ah); 2948c2ecf20Sopenharmony_ci } 2958c2ecf20Sopenharmony_ci spin_lock_irq(&priv->lock); 2968c2ecf20Sopenharmony_ci mcast->ah = ah; 2978c2ecf20Sopenharmony_ci spin_unlock_irq(&priv->lock); 2988c2ecf20Sopenharmony_ci 2998c2ecf20Sopenharmony_ci ipoib_dbg_mcast(priv, "MGID %pI6 AV %p, LID 0x%04x, SL %d\n", 3008c2ecf20Sopenharmony_ci mcast->mcmember.mgid.raw, 3018c2ecf20Sopenharmony_ci mcast->ah->ah, 3028c2ecf20Sopenharmony_ci be16_to_cpu(mcast->mcmember.mlid), 3038c2ecf20Sopenharmony_ci mcast->mcmember.sl); 3048c2ecf20Sopenharmony_ci 3058c2ecf20Sopenharmony_ci /* actually send any queued packets */ 3068c2ecf20Sopenharmony_ci netif_tx_lock_bh(dev); 3078c2ecf20Sopenharmony_ci while (!skb_queue_empty(&mcast->pkt_queue)) { 3088c2ecf20Sopenharmony_ci struct sk_buff *skb = skb_dequeue(&mcast->pkt_queue); 3098c2ecf20Sopenharmony_ci 3108c2ecf20Sopenharmony_ci netif_tx_unlock_bh(dev); 3118c2ecf20Sopenharmony_ci 3128c2ecf20Sopenharmony_ci skb->dev = dev; 3138c2ecf20Sopenharmony_ci 3148c2ecf20Sopenharmony_ci ret = dev_queue_xmit(skb); 3158c2ecf20Sopenharmony_ci if (ret) 3168c2ecf20Sopenharmony_ci ipoib_warn(priv, "%s:dev_queue_xmit failed to re-queue packet, ret:%d\n", 3178c2ecf20Sopenharmony_ci __func__, ret); 3188c2ecf20Sopenharmony_ci netif_tx_lock_bh(dev); 3198c2ecf20Sopenharmony_ci } 3208c2ecf20Sopenharmony_ci netif_tx_unlock_bh(dev); 3218c2ecf20Sopenharmony_ci 3228c2ecf20Sopenharmony_ci return 0; 3238c2ecf20Sopenharmony_ci} 3248c2ecf20Sopenharmony_ci 3258c2ecf20Sopenharmony_civoid ipoib_mcast_carrier_on_task(struct work_struct *work) 3268c2ecf20Sopenharmony_ci{ 3278c2ecf20Sopenharmony_ci struct ipoib_dev_priv *priv = container_of(work, struct ipoib_dev_priv, 3288c2ecf20Sopenharmony_ci carrier_on_task); 3298c2ecf20Sopenharmony_ci struct ib_port_attr attr; 3308c2ecf20Sopenharmony_ci 3318c2ecf20Sopenharmony_ci if (ib_query_port(priv->ca, priv->port, &attr) || 3328c2ecf20Sopenharmony_ci attr.state != IB_PORT_ACTIVE) { 3338c2ecf20Sopenharmony_ci ipoib_dbg(priv, "Keeping carrier off until IB port is active\n"); 3348c2ecf20Sopenharmony_ci return; 3358c2ecf20Sopenharmony_ci } 3368c2ecf20Sopenharmony_ci /* 3378c2ecf20Sopenharmony_ci * Check if can send sendonly MCG's with sendonly-fullmember join state. 3388c2ecf20Sopenharmony_ci * It done here after the successfully join to the broadcast group, 3398c2ecf20Sopenharmony_ci * because the broadcast group must always be joined first and is always 3408c2ecf20Sopenharmony_ci * re-joined if the SM changes substantially. 3418c2ecf20Sopenharmony_ci */ 3428c2ecf20Sopenharmony_ci priv->sm_fullmember_sendonly_support = 3438c2ecf20Sopenharmony_ci ib_sa_sendonly_fullmem_support(&ipoib_sa_client, 3448c2ecf20Sopenharmony_ci priv->ca, priv->port); 3458c2ecf20Sopenharmony_ci /* 3468c2ecf20Sopenharmony_ci * Take rtnl_lock to avoid racing with ipoib_stop() and 3478c2ecf20Sopenharmony_ci * turning the carrier back on while a device is being 3488c2ecf20Sopenharmony_ci * removed. However, ipoib_stop() will attempt to flush 3498c2ecf20Sopenharmony_ci * the workqueue while holding the rtnl lock, so loop 3508c2ecf20Sopenharmony_ci * on trylock until either we get the lock or we see 3518c2ecf20Sopenharmony_ci * FLAG_OPER_UP go away as that signals that we are bailing 3528c2ecf20Sopenharmony_ci * and can safely ignore the carrier on work. 3538c2ecf20Sopenharmony_ci */ 3548c2ecf20Sopenharmony_ci while (!rtnl_trylock()) { 3558c2ecf20Sopenharmony_ci if (!test_bit(IPOIB_FLAG_OPER_UP, &priv->flags)) 3568c2ecf20Sopenharmony_ci return; 3578c2ecf20Sopenharmony_ci else 3588c2ecf20Sopenharmony_ci msleep(20); 3598c2ecf20Sopenharmony_ci } 3608c2ecf20Sopenharmony_ci if (!ipoib_cm_admin_enabled(priv->dev)) 3618c2ecf20Sopenharmony_ci dev_set_mtu(priv->dev, min(priv->mcast_mtu, priv->admin_mtu)); 3628c2ecf20Sopenharmony_ci netif_carrier_on(priv->dev); 3638c2ecf20Sopenharmony_ci rtnl_unlock(); 3648c2ecf20Sopenharmony_ci} 3658c2ecf20Sopenharmony_ci 3668c2ecf20Sopenharmony_cistatic int ipoib_mcast_join_complete(int status, 3678c2ecf20Sopenharmony_ci struct ib_sa_multicast *multicast) 3688c2ecf20Sopenharmony_ci{ 3698c2ecf20Sopenharmony_ci struct ipoib_mcast *mcast = multicast->context; 3708c2ecf20Sopenharmony_ci struct net_device *dev = mcast->dev; 3718c2ecf20Sopenharmony_ci struct ipoib_dev_priv *priv = ipoib_priv(dev); 3728c2ecf20Sopenharmony_ci 3738c2ecf20Sopenharmony_ci ipoib_dbg_mcast(priv, "%sjoin completion for %pI6 (status %d)\n", 3748c2ecf20Sopenharmony_ci test_bit(IPOIB_MCAST_FLAG_SENDONLY, &mcast->flags) ? 3758c2ecf20Sopenharmony_ci "sendonly " : "", 3768c2ecf20Sopenharmony_ci mcast->mcmember.mgid.raw, status); 3778c2ecf20Sopenharmony_ci 3788c2ecf20Sopenharmony_ci /* We trap for port events ourselves. */ 3798c2ecf20Sopenharmony_ci if (status == -ENETRESET) { 3808c2ecf20Sopenharmony_ci status = 0; 3818c2ecf20Sopenharmony_ci goto out; 3828c2ecf20Sopenharmony_ci } 3838c2ecf20Sopenharmony_ci 3848c2ecf20Sopenharmony_ci if (!status) 3858c2ecf20Sopenharmony_ci status = ipoib_mcast_join_finish(mcast, &multicast->rec); 3868c2ecf20Sopenharmony_ci 3878c2ecf20Sopenharmony_ci if (!status) { 3888c2ecf20Sopenharmony_ci mcast->backoff = 1; 3898c2ecf20Sopenharmony_ci mcast->delay_until = jiffies; 3908c2ecf20Sopenharmony_ci 3918c2ecf20Sopenharmony_ci /* 3928c2ecf20Sopenharmony_ci * Defer carrier on work to priv->wq to avoid a 3938c2ecf20Sopenharmony_ci * deadlock on rtnl_lock here. Requeue our multicast 3948c2ecf20Sopenharmony_ci * work too, which will end up happening right after 3958c2ecf20Sopenharmony_ci * our carrier on task work and will allow us to 3968c2ecf20Sopenharmony_ci * send out all of the non-broadcast joins 3978c2ecf20Sopenharmony_ci */ 3988c2ecf20Sopenharmony_ci if (mcast == priv->broadcast) { 3998c2ecf20Sopenharmony_ci spin_lock_irq(&priv->lock); 4008c2ecf20Sopenharmony_ci queue_work(priv->wq, &priv->carrier_on_task); 4018c2ecf20Sopenharmony_ci __ipoib_mcast_schedule_join_thread(priv, NULL, 0); 4028c2ecf20Sopenharmony_ci goto out_locked; 4038c2ecf20Sopenharmony_ci } 4048c2ecf20Sopenharmony_ci } else { 4058c2ecf20Sopenharmony_ci bool silent_fail = 4068c2ecf20Sopenharmony_ci test_bit(IPOIB_MCAST_FLAG_SENDONLY, &mcast->flags) && 4078c2ecf20Sopenharmony_ci status == -EINVAL; 4088c2ecf20Sopenharmony_ci 4098c2ecf20Sopenharmony_ci if (mcast->logcount < 20) { 4108c2ecf20Sopenharmony_ci if (status == -ETIMEDOUT || status == -EAGAIN || 4118c2ecf20Sopenharmony_ci silent_fail) { 4128c2ecf20Sopenharmony_ci ipoib_dbg_mcast(priv, "%smulticast join failed for %pI6, status %d\n", 4138c2ecf20Sopenharmony_ci test_bit(IPOIB_MCAST_FLAG_SENDONLY, &mcast->flags) ? "sendonly " : "", 4148c2ecf20Sopenharmony_ci mcast->mcmember.mgid.raw, status); 4158c2ecf20Sopenharmony_ci } else { 4168c2ecf20Sopenharmony_ci ipoib_warn(priv, "%smulticast join failed for %pI6, status %d\n", 4178c2ecf20Sopenharmony_ci test_bit(IPOIB_MCAST_FLAG_SENDONLY, &mcast->flags) ? "sendonly " : "", 4188c2ecf20Sopenharmony_ci mcast->mcmember.mgid.raw, status); 4198c2ecf20Sopenharmony_ci } 4208c2ecf20Sopenharmony_ci 4218c2ecf20Sopenharmony_ci if (!silent_fail) 4228c2ecf20Sopenharmony_ci mcast->logcount++; 4238c2ecf20Sopenharmony_ci } 4248c2ecf20Sopenharmony_ci 4258c2ecf20Sopenharmony_ci if (test_bit(IPOIB_MCAST_FLAG_SENDONLY, &mcast->flags) && 4268c2ecf20Sopenharmony_ci mcast->backoff >= 2) { 4278c2ecf20Sopenharmony_ci /* 4288c2ecf20Sopenharmony_ci * We only retry sendonly joins once before we drop 4298c2ecf20Sopenharmony_ci * the packet and quit trying to deal with the 4308c2ecf20Sopenharmony_ci * group. However, we leave the group in the 4318c2ecf20Sopenharmony_ci * mcast list as an unjoined group. If we want to 4328c2ecf20Sopenharmony_ci * try joining again, we simply queue up a packet 4338c2ecf20Sopenharmony_ci * and restart the join thread. The empty queue 4348c2ecf20Sopenharmony_ci * is why the join thread ignores this group. 4358c2ecf20Sopenharmony_ci */ 4368c2ecf20Sopenharmony_ci mcast->backoff = 1; 4378c2ecf20Sopenharmony_ci netif_tx_lock_bh(dev); 4388c2ecf20Sopenharmony_ci while (!skb_queue_empty(&mcast->pkt_queue)) { 4398c2ecf20Sopenharmony_ci ++dev->stats.tx_dropped; 4408c2ecf20Sopenharmony_ci dev_kfree_skb_any(skb_dequeue(&mcast->pkt_queue)); 4418c2ecf20Sopenharmony_ci } 4428c2ecf20Sopenharmony_ci netif_tx_unlock_bh(dev); 4438c2ecf20Sopenharmony_ci } else { 4448c2ecf20Sopenharmony_ci spin_lock_irq(&priv->lock); 4458c2ecf20Sopenharmony_ci /* Requeue this join task with a backoff delay */ 4468c2ecf20Sopenharmony_ci __ipoib_mcast_schedule_join_thread(priv, mcast, 1); 4478c2ecf20Sopenharmony_ci goto out_locked; 4488c2ecf20Sopenharmony_ci } 4498c2ecf20Sopenharmony_ci } 4508c2ecf20Sopenharmony_ciout: 4518c2ecf20Sopenharmony_ci spin_lock_irq(&priv->lock); 4528c2ecf20Sopenharmony_ciout_locked: 4538c2ecf20Sopenharmony_ci /* 4548c2ecf20Sopenharmony_ci * Make sure to set mcast->mc before we clear the busy flag to avoid 4558c2ecf20Sopenharmony_ci * racing with code that checks for BUSY before checking mcast->mc 4568c2ecf20Sopenharmony_ci */ 4578c2ecf20Sopenharmony_ci if (status) 4588c2ecf20Sopenharmony_ci mcast->mc = NULL; 4598c2ecf20Sopenharmony_ci else 4608c2ecf20Sopenharmony_ci mcast->mc = multicast; 4618c2ecf20Sopenharmony_ci clear_bit(IPOIB_MCAST_FLAG_BUSY, &mcast->flags); 4628c2ecf20Sopenharmony_ci spin_unlock_irq(&priv->lock); 4638c2ecf20Sopenharmony_ci complete(&mcast->done); 4648c2ecf20Sopenharmony_ci 4658c2ecf20Sopenharmony_ci return status; 4668c2ecf20Sopenharmony_ci} 4678c2ecf20Sopenharmony_ci 4688c2ecf20Sopenharmony_ci/* 4698c2ecf20Sopenharmony_ci * Caller must hold 'priv->lock' 4708c2ecf20Sopenharmony_ci */ 4718c2ecf20Sopenharmony_cistatic int ipoib_mcast_join(struct net_device *dev, struct ipoib_mcast *mcast) 4728c2ecf20Sopenharmony_ci{ 4738c2ecf20Sopenharmony_ci struct ipoib_dev_priv *priv = ipoib_priv(dev); 4748c2ecf20Sopenharmony_ci struct ib_sa_multicast *multicast; 4758c2ecf20Sopenharmony_ci struct ib_sa_mcmember_rec rec = { 4768c2ecf20Sopenharmony_ci .join_state = 1 4778c2ecf20Sopenharmony_ci }; 4788c2ecf20Sopenharmony_ci ib_sa_comp_mask comp_mask; 4798c2ecf20Sopenharmony_ci int ret = 0; 4808c2ecf20Sopenharmony_ci 4818c2ecf20Sopenharmony_ci if (!priv->broadcast || 4828c2ecf20Sopenharmony_ci !test_bit(IPOIB_FLAG_OPER_UP, &priv->flags)) 4838c2ecf20Sopenharmony_ci return -EINVAL; 4848c2ecf20Sopenharmony_ci 4858c2ecf20Sopenharmony_ci init_completion(&mcast->done); 4868c2ecf20Sopenharmony_ci set_bit(IPOIB_MCAST_FLAG_BUSY, &mcast->flags); 4878c2ecf20Sopenharmony_ci 4888c2ecf20Sopenharmony_ci ipoib_dbg_mcast(priv, "joining MGID %pI6\n", mcast->mcmember.mgid.raw); 4898c2ecf20Sopenharmony_ci 4908c2ecf20Sopenharmony_ci rec.mgid = mcast->mcmember.mgid; 4918c2ecf20Sopenharmony_ci rec.port_gid = priv->local_gid; 4928c2ecf20Sopenharmony_ci rec.pkey = cpu_to_be16(priv->pkey); 4938c2ecf20Sopenharmony_ci 4948c2ecf20Sopenharmony_ci comp_mask = 4958c2ecf20Sopenharmony_ci IB_SA_MCMEMBER_REC_MGID | 4968c2ecf20Sopenharmony_ci IB_SA_MCMEMBER_REC_PORT_GID | 4978c2ecf20Sopenharmony_ci IB_SA_MCMEMBER_REC_PKEY | 4988c2ecf20Sopenharmony_ci IB_SA_MCMEMBER_REC_JOIN_STATE; 4998c2ecf20Sopenharmony_ci 5008c2ecf20Sopenharmony_ci if (mcast != priv->broadcast) { 5018c2ecf20Sopenharmony_ci /* 5028c2ecf20Sopenharmony_ci * RFC 4391: 5038c2ecf20Sopenharmony_ci * The MGID MUST use the same P_Key, Q_Key, SL, MTU, 5048c2ecf20Sopenharmony_ci * and HopLimit as those used in the broadcast-GID. The rest 5058c2ecf20Sopenharmony_ci * of attributes SHOULD follow the values used in the 5068c2ecf20Sopenharmony_ci * broadcast-GID as well. 5078c2ecf20Sopenharmony_ci */ 5088c2ecf20Sopenharmony_ci comp_mask |= 5098c2ecf20Sopenharmony_ci IB_SA_MCMEMBER_REC_QKEY | 5108c2ecf20Sopenharmony_ci IB_SA_MCMEMBER_REC_MTU_SELECTOR | 5118c2ecf20Sopenharmony_ci IB_SA_MCMEMBER_REC_MTU | 5128c2ecf20Sopenharmony_ci IB_SA_MCMEMBER_REC_TRAFFIC_CLASS | 5138c2ecf20Sopenharmony_ci IB_SA_MCMEMBER_REC_RATE_SELECTOR | 5148c2ecf20Sopenharmony_ci IB_SA_MCMEMBER_REC_RATE | 5158c2ecf20Sopenharmony_ci IB_SA_MCMEMBER_REC_SL | 5168c2ecf20Sopenharmony_ci IB_SA_MCMEMBER_REC_FLOW_LABEL | 5178c2ecf20Sopenharmony_ci IB_SA_MCMEMBER_REC_HOP_LIMIT; 5188c2ecf20Sopenharmony_ci 5198c2ecf20Sopenharmony_ci rec.qkey = priv->broadcast->mcmember.qkey; 5208c2ecf20Sopenharmony_ci rec.mtu_selector = IB_SA_EQ; 5218c2ecf20Sopenharmony_ci rec.mtu = priv->broadcast->mcmember.mtu; 5228c2ecf20Sopenharmony_ci rec.traffic_class = priv->broadcast->mcmember.traffic_class; 5238c2ecf20Sopenharmony_ci rec.rate_selector = IB_SA_EQ; 5248c2ecf20Sopenharmony_ci rec.rate = priv->broadcast->mcmember.rate; 5258c2ecf20Sopenharmony_ci rec.sl = priv->broadcast->mcmember.sl; 5268c2ecf20Sopenharmony_ci rec.flow_label = priv->broadcast->mcmember.flow_label; 5278c2ecf20Sopenharmony_ci rec.hop_limit = priv->broadcast->mcmember.hop_limit; 5288c2ecf20Sopenharmony_ci 5298c2ecf20Sopenharmony_ci /* 5308c2ecf20Sopenharmony_ci * Send-only IB Multicast joins work at the core IB layer but 5318c2ecf20Sopenharmony_ci * require specific SM support. 5328c2ecf20Sopenharmony_ci * We can use such joins here only if the current SM supports that feature. 5338c2ecf20Sopenharmony_ci * However, if not, we emulate an Ethernet multicast send, 5348c2ecf20Sopenharmony_ci * which does not require a multicast subscription and will 5358c2ecf20Sopenharmony_ci * still send properly. The most appropriate thing to 5368c2ecf20Sopenharmony_ci * do is to create the group if it doesn't exist as that 5378c2ecf20Sopenharmony_ci * most closely emulates the behavior, from a user space 5388c2ecf20Sopenharmony_ci * application perspective, of Ethernet multicast operation. 5398c2ecf20Sopenharmony_ci */ 5408c2ecf20Sopenharmony_ci if (test_bit(IPOIB_MCAST_FLAG_SENDONLY, &mcast->flags) && 5418c2ecf20Sopenharmony_ci priv->sm_fullmember_sendonly_support) 5428c2ecf20Sopenharmony_ci /* SM supports sendonly-fullmember, otherwise fallback to full-member */ 5438c2ecf20Sopenharmony_ci rec.join_state = SENDONLY_FULLMEMBER_JOIN; 5448c2ecf20Sopenharmony_ci } 5458c2ecf20Sopenharmony_ci 5468c2ecf20Sopenharmony_ci multicast = ib_sa_join_multicast(&ipoib_sa_client, priv->ca, priv->port, 5478c2ecf20Sopenharmony_ci &rec, comp_mask, GFP_ATOMIC, 5488c2ecf20Sopenharmony_ci ipoib_mcast_join_complete, mcast); 5498c2ecf20Sopenharmony_ci if (IS_ERR(multicast)) { 5508c2ecf20Sopenharmony_ci ret = PTR_ERR(multicast); 5518c2ecf20Sopenharmony_ci ipoib_warn(priv, "ib_sa_join_multicast failed, status %d\n", ret); 5528c2ecf20Sopenharmony_ci /* Requeue this join task with a backoff delay */ 5538c2ecf20Sopenharmony_ci __ipoib_mcast_schedule_join_thread(priv, mcast, 1); 5548c2ecf20Sopenharmony_ci clear_bit(IPOIB_MCAST_FLAG_BUSY, &mcast->flags); 5558c2ecf20Sopenharmony_ci complete(&mcast->done); 5568c2ecf20Sopenharmony_ci return ret; 5578c2ecf20Sopenharmony_ci } 5588c2ecf20Sopenharmony_ci return 0; 5598c2ecf20Sopenharmony_ci} 5608c2ecf20Sopenharmony_ci 5618c2ecf20Sopenharmony_civoid ipoib_mcast_join_task(struct work_struct *work) 5628c2ecf20Sopenharmony_ci{ 5638c2ecf20Sopenharmony_ci struct ipoib_dev_priv *priv = 5648c2ecf20Sopenharmony_ci container_of(work, struct ipoib_dev_priv, mcast_task.work); 5658c2ecf20Sopenharmony_ci struct net_device *dev = priv->dev; 5668c2ecf20Sopenharmony_ci struct ib_port_attr port_attr; 5678c2ecf20Sopenharmony_ci unsigned long delay_until = 0; 5688c2ecf20Sopenharmony_ci struct ipoib_mcast *mcast = NULL; 5698c2ecf20Sopenharmony_ci 5708c2ecf20Sopenharmony_ci if (!test_bit(IPOIB_FLAG_OPER_UP, &priv->flags)) 5718c2ecf20Sopenharmony_ci return; 5728c2ecf20Sopenharmony_ci 5738c2ecf20Sopenharmony_ci if (ib_query_port(priv->ca, priv->port, &port_attr)) { 5748c2ecf20Sopenharmony_ci ipoib_dbg(priv, "ib_query_port() failed\n"); 5758c2ecf20Sopenharmony_ci return; 5768c2ecf20Sopenharmony_ci } 5778c2ecf20Sopenharmony_ci if (port_attr.state != IB_PORT_ACTIVE) { 5788c2ecf20Sopenharmony_ci ipoib_dbg(priv, "port state is not ACTIVE (state = %d) suspending join task\n", 5798c2ecf20Sopenharmony_ci port_attr.state); 5808c2ecf20Sopenharmony_ci return; 5818c2ecf20Sopenharmony_ci } 5828c2ecf20Sopenharmony_ci priv->local_lid = port_attr.lid; 5838c2ecf20Sopenharmony_ci netif_addr_lock_bh(dev); 5848c2ecf20Sopenharmony_ci 5858c2ecf20Sopenharmony_ci if (!test_bit(IPOIB_FLAG_DEV_ADDR_SET, &priv->flags)) { 5868c2ecf20Sopenharmony_ci netif_addr_unlock_bh(dev); 5878c2ecf20Sopenharmony_ci return; 5888c2ecf20Sopenharmony_ci } 5898c2ecf20Sopenharmony_ci netif_addr_unlock_bh(dev); 5908c2ecf20Sopenharmony_ci 5918c2ecf20Sopenharmony_ci spin_lock_irq(&priv->lock); 5928c2ecf20Sopenharmony_ci if (!test_bit(IPOIB_FLAG_OPER_UP, &priv->flags)) 5938c2ecf20Sopenharmony_ci goto out; 5948c2ecf20Sopenharmony_ci 5958c2ecf20Sopenharmony_ci if (!priv->broadcast) { 5968c2ecf20Sopenharmony_ci struct ipoib_mcast *broadcast; 5978c2ecf20Sopenharmony_ci 5988c2ecf20Sopenharmony_ci broadcast = ipoib_mcast_alloc(dev); 5998c2ecf20Sopenharmony_ci if (!broadcast) { 6008c2ecf20Sopenharmony_ci ipoib_warn(priv, "failed to allocate broadcast group\n"); 6018c2ecf20Sopenharmony_ci /* 6028c2ecf20Sopenharmony_ci * Restart us after a 1 second delay to retry 6038c2ecf20Sopenharmony_ci * creating our broadcast group and attaching to 6048c2ecf20Sopenharmony_ci * it. Until this succeeds, this ipoib dev is 6058c2ecf20Sopenharmony_ci * completely stalled (multicast wise). 6068c2ecf20Sopenharmony_ci */ 6078c2ecf20Sopenharmony_ci __ipoib_mcast_schedule_join_thread(priv, NULL, 1); 6088c2ecf20Sopenharmony_ci goto out; 6098c2ecf20Sopenharmony_ci } 6108c2ecf20Sopenharmony_ci 6118c2ecf20Sopenharmony_ci memcpy(broadcast->mcmember.mgid.raw, priv->dev->broadcast + 4, 6128c2ecf20Sopenharmony_ci sizeof (union ib_gid)); 6138c2ecf20Sopenharmony_ci priv->broadcast = broadcast; 6148c2ecf20Sopenharmony_ci 6158c2ecf20Sopenharmony_ci __ipoib_mcast_add(dev, priv->broadcast); 6168c2ecf20Sopenharmony_ci } 6178c2ecf20Sopenharmony_ci 6188c2ecf20Sopenharmony_ci if (!test_bit(IPOIB_MCAST_FLAG_ATTACHED, &priv->broadcast->flags)) { 6198c2ecf20Sopenharmony_ci if (IS_ERR_OR_NULL(priv->broadcast->mc) && 6208c2ecf20Sopenharmony_ci !test_bit(IPOIB_MCAST_FLAG_BUSY, &priv->broadcast->flags)) { 6218c2ecf20Sopenharmony_ci mcast = priv->broadcast; 6228c2ecf20Sopenharmony_ci if (mcast->backoff > 1 && 6238c2ecf20Sopenharmony_ci time_before(jiffies, mcast->delay_until)) { 6248c2ecf20Sopenharmony_ci delay_until = mcast->delay_until; 6258c2ecf20Sopenharmony_ci mcast = NULL; 6268c2ecf20Sopenharmony_ci } 6278c2ecf20Sopenharmony_ci } 6288c2ecf20Sopenharmony_ci goto out; 6298c2ecf20Sopenharmony_ci } 6308c2ecf20Sopenharmony_ci 6318c2ecf20Sopenharmony_ci /* 6328c2ecf20Sopenharmony_ci * We'll never get here until the broadcast group is both allocated 6338c2ecf20Sopenharmony_ci * and attached 6348c2ecf20Sopenharmony_ci */ 6358c2ecf20Sopenharmony_ci list_for_each_entry(mcast, &priv->multicast_list, list) { 6368c2ecf20Sopenharmony_ci if (IS_ERR_OR_NULL(mcast->mc) && 6378c2ecf20Sopenharmony_ci !test_bit(IPOIB_MCAST_FLAG_BUSY, &mcast->flags) && 6388c2ecf20Sopenharmony_ci (!test_bit(IPOIB_MCAST_FLAG_SENDONLY, &mcast->flags) || 6398c2ecf20Sopenharmony_ci !skb_queue_empty(&mcast->pkt_queue))) { 6408c2ecf20Sopenharmony_ci if (mcast->backoff == 1 || 6418c2ecf20Sopenharmony_ci time_after_eq(jiffies, mcast->delay_until)) { 6428c2ecf20Sopenharmony_ci /* Found the next unjoined group */ 6438c2ecf20Sopenharmony_ci if (ipoib_mcast_join(dev, mcast)) { 6448c2ecf20Sopenharmony_ci spin_unlock_irq(&priv->lock); 6458c2ecf20Sopenharmony_ci return; 6468c2ecf20Sopenharmony_ci } 6478c2ecf20Sopenharmony_ci } else if (!delay_until || 6488c2ecf20Sopenharmony_ci time_before(mcast->delay_until, delay_until)) 6498c2ecf20Sopenharmony_ci delay_until = mcast->delay_until; 6508c2ecf20Sopenharmony_ci } 6518c2ecf20Sopenharmony_ci } 6528c2ecf20Sopenharmony_ci 6538c2ecf20Sopenharmony_ci mcast = NULL; 6548c2ecf20Sopenharmony_ci ipoib_dbg_mcast(priv, "successfully started all multicast joins\n"); 6558c2ecf20Sopenharmony_ci 6568c2ecf20Sopenharmony_ciout: 6578c2ecf20Sopenharmony_ci if (delay_until) { 6588c2ecf20Sopenharmony_ci cancel_delayed_work(&priv->mcast_task); 6598c2ecf20Sopenharmony_ci queue_delayed_work(priv->wq, &priv->mcast_task, 6608c2ecf20Sopenharmony_ci delay_until - jiffies); 6618c2ecf20Sopenharmony_ci } 6628c2ecf20Sopenharmony_ci if (mcast) 6638c2ecf20Sopenharmony_ci ipoib_mcast_join(dev, mcast); 6648c2ecf20Sopenharmony_ci 6658c2ecf20Sopenharmony_ci spin_unlock_irq(&priv->lock); 6668c2ecf20Sopenharmony_ci} 6678c2ecf20Sopenharmony_ci 6688c2ecf20Sopenharmony_civoid ipoib_mcast_start_thread(struct net_device *dev) 6698c2ecf20Sopenharmony_ci{ 6708c2ecf20Sopenharmony_ci struct ipoib_dev_priv *priv = ipoib_priv(dev); 6718c2ecf20Sopenharmony_ci unsigned long flags; 6728c2ecf20Sopenharmony_ci 6738c2ecf20Sopenharmony_ci ipoib_dbg_mcast(priv, "starting multicast thread\n"); 6748c2ecf20Sopenharmony_ci 6758c2ecf20Sopenharmony_ci spin_lock_irqsave(&priv->lock, flags); 6768c2ecf20Sopenharmony_ci __ipoib_mcast_schedule_join_thread(priv, NULL, 0); 6778c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&priv->lock, flags); 6788c2ecf20Sopenharmony_ci} 6798c2ecf20Sopenharmony_ci 6808c2ecf20Sopenharmony_civoid ipoib_mcast_stop_thread(struct net_device *dev) 6818c2ecf20Sopenharmony_ci{ 6828c2ecf20Sopenharmony_ci struct ipoib_dev_priv *priv = ipoib_priv(dev); 6838c2ecf20Sopenharmony_ci 6848c2ecf20Sopenharmony_ci ipoib_dbg_mcast(priv, "stopping multicast thread\n"); 6858c2ecf20Sopenharmony_ci 6868c2ecf20Sopenharmony_ci cancel_delayed_work_sync(&priv->mcast_task); 6878c2ecf20Sopenharmony_ci} 6888c2ecf20Sopenharmony_ci 6898c2ecf20Sopenharmony_cistatic int ipoib_mcast_leave(struct net_device *dev, struct ipoib_mcast *mcast) 6908c2ecf20Sopenharmony_ci{ 6918c2ecf20Sopenharmony_ci struct ipoib_dev_priv *priv = ipoib_priv(dev); 6928c2ecf20Sopenharmony_ci struct rdma_netdev *rn = netdev_priv(dev); 6938c2ecf20Sopenharmony_ci int ret = 0; 6948c2ecf20Sopenharmony_ci 6958c2ecf20Sopenharmony_ci if (test_and_clear_bit(IPOIB_MCAST_FLAG_BUSY, &mcast->flags)) 6968c2ecf20Sopenharmony_ci ipoib_warn(priv, "ipoib_mcast_leave on an in-flight join\n"); 6978c2ecf20Sopenharmony_ci 6988c2ecf20Sopenharmony_ci if (!IS_ERR_OR_NULL(mcast->mc)) 6998c2ecf20Sopenharmony_ci ib_sa_free_multicast(mcast->mc); 7008c2ecf20Sopenharmony_ci 7018c2ecf20Sopenharmony_ci if (test_and_clear_bit(IPOIB_MCAST_FLAG_ATTACHED, &mcast->flags)) { 7028c2ecf20Sopenharmony_ci ipoib_dbg_mcast(priv, "leaving MGID %pI6\n", 7038c2ecf20Sopenharmony_ci mcast->mcmember.mgid.raw); 7048c2ecf20Sopenharmony_ci 7058c2ecf20Sopenharmony_ci /* Remove ourselves from the multicast group */ 7068c2ecf20Sopenharmony_ci ret = rn->detach_mcast(dev, priv->ca, &mcast->mcmember.mgid, 7078c2ecf20Sopenharmony_ci be16_to_cpu(mcast->mcmember.mlid)); 7088c2ecf20Sopenharmony_ci if (ret) 7098c2ecf20Sopenharmony_ci ipoib_warn(priv, "ib_detach_mcast failed (result = %d)\n", ret); 7108c2ecf20Sopenharmony_ci } else if (!test_bit(IPOIB_MCAST_FLAG_SENDONLY, &mcast->flags)) 7118c2ecf20Sopenharmony_ci ipoib_dbg(priv, "leaving with no mcmember but not a " 7128c2ecf20Sopenharmony_ci "SENDONLY join\n"); 7138c2ecf20Sopenharmony_ci 7148c2ecf20Sopenharmony_ci return 0; 7158c2ecf20Sopenharmony_ci} 7168c2ecf20Sopenharmony_ci 7178c2ecf20Sopenharmony_ci/* 7188c2ecf20Sopenharmony_ci * Check if the multicast group is sendonly. If so remove it from the maps 7198c2ecf20Sopenharmony_ci * and add to the remove list 7208c2ecf20Sopenharmony_ci */ 7218c2ecf20Sopenharmony_civoid ipoib_check_and_add_mcast_sendonly(struct ipoib_dev_priv *priv, u8 *mgid, 7228c2ecf20Sopenharmony_ci struct list_head *remove_list) 7238c2ecf20Sopenharmony_ci{ 7248c2ecf20Sopenharmony_ci /* Is this multicast ? */ 7258c2ecf20Sopenharmony_ci if (*mgid == 0xff) { 7268c2ecf20Sopenharmony_ci struct ipoib_mcast *mcast = __ipoib_mcast_find(priv->dev, mgid); 7278c2ecf20Sopenharmony_ci 7288c2ecf20Sopenharmony_ci if (mcast && test_bit(IPOIB_MCAST_FLAG_SENDONLY, &mcast->flags)) { 7298c2ecf20Sopenharmony_ci list_del(&mcast->list); 7308c2ecf20Sopenharmony_ci rb_erase(&mcast->rb_node, &priv->multicast_tree); 7318c2ecf20Sopenharmony_ci list_add_tail(&mcast->list, remove_list); 7328c2ecf20Sopenharmony_ci } 7338c2ecf20Sopenharmony_ci } 7348c2ecf20Sopenharmony_ci} 7358c2ecf20Sopenharmony_ci 7368c2ecf20Sopenharmony_civoid ipoib_mcast_remove_list(struct list_head *remove_list) 7378c2ecf20Sopenharmony_ci{ 7388c2ecf20Sopenharmony_ci struct ipoib_mcast *mcast, *tmcast; 7398c2ecf20Sopenharmony_ci 7408c2ecf20Sopenharmony_ci /* 7418c2ecf20Sopenharmony_ci * make sure the in-flight joins have finished before we attempt 7428c2ecf20Sopenharmony_ci * to leave 7438c2ecf20Sopenharmony_ci */ 7448c2ecf20Sopenharmony_ci list_for_each_entry_safe(mcast, tmcast, remove_list, list) 7458c2ecf20Sopenharmony_ci if (test_bit(IPOIB_MCAST_FLAG_BUSY, &mcast->flags)) 7468c2ecf20Sopenharmony_ci wait_for_completion(&mcast->done); 7478c2ecf20Sopenharmony_ci 7488c2ecf20Sopenharmony_ci list_for_each_entry_safe(mcast, tmcast, remove_list, list) { 7498c2ecf20Sopenharmony_ci ipoib_mcast_leave(mcast->dev, mcast); 7508c2ecf20Sopenharmony_ci ipoib_mcast_free(mcast); 7518c2ecf20Sopenharmony_ci } 7528c2ecf20Sopenharmony_ci} 7538c2ecf20Sopenharmony_ci 7548c2ecf20Sopenharmony_civoid ipoib_mcast_send(struct net_device *dev, u8 *daddr, struct sk_buff *skb) 7558c2ecf20Sopenharmony_ci{ 7568c2ecf20Sopenharmony_ci struct ipoib_dev_priv *priv = ipoib_priv(dev); 7578c2ecf20Sopenharmony_ci struct rdma_netdev *rn = netdev_priv(dev); 7588c2ecf20Sopenharmony_ci struct ipoib_mcast *mcast; 7598c2ecf20Sopenharmony_ci unsigned long flags; 7608c2ecf20Sopenharmony_ci void *mgid = daddr + 4; 7618c2ecf20Sopenharmony_ci 7628c2ecf20Sopenharmony_ci spin_lock_irqsave(&priv->lock, flags); 7638c2ecf20Sopenharmony_ci 7648c2ecf20Sopenharmony_ci if (!test_bit(IPOIB_FLAG_OPER_UP, &priv->flags) || 7658c2ecf20Sopenharmony_ci !priv->broadcast || 7668c2ecf20Sopenharmony_ci !test_bit(IPOIB_MCAST_FLAG_ATTACHED, &priv->broadcast->flags)) { 7678c2ecf20Sopenharmony_ci ++dev->stats.tx_dropped; 7688c2ecf20Sopenharmony_ci dev_kfree_skb_any(skb); 7698c2ecf20Sopenharmony_ci goto unlock; 7708c2ecf20Sopenharmony_ci } 7718c2ecf20Sopenharmony_ci 7728c2ecf20Sopenharmony_ci mcast = __ipoib_mcast_find(dev, mgid); 7738c2ecf20Sopenharmony_ci if (!mcast || !mcast->ah) { 7748c2ecf20Sopenharmony_ci if (!mcast) { 7758c2ecf20Sopenharmony_ci /* Let's create a new send only group now */ 7768c2ecf20Sopenharmony_ci ipoib_dbg_mcast(priv, "setting up send only multicast group for %pI6\n", 7778c2ecf20Sopenharmony_ci mgid); 7788c2ecf20Sopenharmony_ci 7798c2ecf20Sopenharmony_ci mcast = ipoib_mcast_alloc(dev); 7808c2ecf20Sopenharmony_ci if (!mcast) { 7818c2ecf20Sopenharmony_ci ipoib_warn(priv, "unable to allocate memory " 7828c2ecf20Sopenharmony_ci "for multicast structure\n"); 7838c2ecf20Sopenharmony_ci ++dev->stats.tx_dropped; 7848c2ecf20Sopenharmony_ci dev_kfree_skb_any(skb); 7858c2ecf20Sopenharmony_ci goto unlock; 7868c2ecf20Sopenharmony_ci } 7878c2ecf20Sopenharmony_ci 7888c2ecf20Sopenharmony_ci set_bit(IPOIB_MCAST_FLAG_SENDONLY, &mcast->flags); 7898c2ecf20Sopenharmony_ci memcpy(mcast->mcmember.mgid.raw, mgid, 7908c2ecf20Sopenharmony_ci sizeof (union ib_gid)); 7918c2ecf20Sopenharmony_ci __ipoib_mcast_add(dev, mcast); 7928c2ecf20Sopenharmony_ci list_add_tail(&mcast->list, &priv->multicast_list); 7938c2ecf20Sopenharmony_ci } 7948c2ecf20Sopenharmony_ci if (skb_queue_len(&mcast->pkt_queue) < IPOIB_MAX_MCAST_QUEUE) { 7958c2ecf20Sopenharmony_ci /* put pseudoheader back on for next time */ 7968c2ecf20Sopenharmony_ci skb_push(skb, sizeof(struct ipoib_pseudo_header)); 7978c2ecf20Sopenharmony_ci skb_queue_tail(&mcast->pkt_queue, skb); 7988c2ecf20Sopenharmony_ci } else { 7998c2ecf20Sopenharmony_ci ++dev->stats.tx_dropped; 8008c2ecf20Sopenharmony_ci dev_kfree_skb_any(skb); 8018c2ecf20Sopenharmony_ci } 8028c2ecf20Sopenharmony_ci if (!test_bit(IPOIB_MCAST_FLAG_BUSY, &mcast->flags)) { 8038c2ecf20Sopenharmony_ci __ipoib_mcast_schedule_join_thread(priv, NULL, 0); 8048c2ecf20Sopenharmony_ci } 8058c2ecf20Sopenharmony_ci } else { 8068c2ecf20Sopenharmony_ci struct ipoib_neigh *neigh; 8078c2ecf20Sopenharmony_ci 8088c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&priv->lock, flags); 8098c2ecf20Sopenharmony_ci neigh = ipoib_neigh_get(dev, daddr); 8108c2ecf20Sopenharmony_ci spin_lock_irqsave(&priv->lock, flags); 8118c2ecf20Sopenharmony_ci if (!neigh) { 8128c2ecf20Sopenharmony_ci neigh = ipoib_neigh_alloc(daddr, dev); 8138c2ecf20Sopenharmony_ci /* Make sure that the neigh will be added only 8148c2ecf20Sopenharmony_ci * once to mcast list. 8158c2ecf20Sopenharmony_ci */ 8168c2ecf20Sopenharmony_ci if (neigh && list_empty(&neigh->list)) { 8178c2ecf20Sopenharmony_ci kref_get(&mcast->ah->ref); 8188c2ecf20Sopenharmony_ci neigh->ah = mcast->ah; 8198c2ecf20Sopenharmony_ci neigh->ah->valid = 1; 8208c2ecf20Sopenharmony_ci list_add_tail(&neigh->list, &mcast->neigh_list); 8218c2ecf20Sopenharmony_ci } 8228c2ecf20Sopenharmony_ci } 8238c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&priv->lock, flags); 8248c2ecf20Sopenharmony_ci mcast->ah->last_send = rn->send(dev, skb, mcast->ah->ah, 8258c2ecf20Sopenharmony_ci IB_MULTICAST_QPN); 8268c2ecf20Sopenharmony_ci if (neigh) 8278c2ecf20Sopenharmony_ci ipoib_neigh_put(neigh); 8288c2ecf20Sopenharmony_ci return; 8298c2ecf20Sopenharmony_ci } 8308c2ecf20Sopenharmony_ci 8318c2ecf20Sopenharmony_ciunlock: 8328c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&priv->lock, flags); 8338c2ecf20Sopenharmony_ci} 8348c2ecf20Sopenharmony_ci 8358c2ecf20Sopenharmony_civoid ipoib_mcast_dev_flush(struct net_device *dev) 8368c2ecf20Sopenharmony_ci{ 8378c2ecf20Sopenharmony_ci struct ipoib_dev_priv *priv = ipoib_priv(dev); 8388c2ecf20Sopenharmony_ci LIST_HEAD(remove_list); 8398c2ecf20Sopenharmony_ci struct ipoib_mcast *mcast, *tmcast; 8408c2ecf20Sopenharmony_ci unsigned long flags; 8418c2ecf20Sopenharmony_ci 8428c2ecf20Sopenharmony_ci mutex_lock(&priv->mcast_mutex); 8438c2ecf20Sopenharmony_ci ipoib_dbg_mcast(priv, "flushing multicast list\n"); 8448c2ecf20Sopenharmony_ci 8458c2ecf20Sopenharmony_ci spin_lock_irqsave(&priv->lock, flags); 8468c2ecf20Sopenharmony_ci 8478c2ecf20Sopenharmony_ci list_for_each_entry_safe(mcast, tmcast, &priv->multicast_list, list) { 8488c2ecf20Sopenharmony_ci list_del(&mcast->list); 8498c2ecf20Sopenharmony_ci rb_erase(&mcast->rb_node, &priv->multicast_tree); 8508c2ecf20Sopenharmony_ci list_add_tail(&mcast->list, &remove_list); 8518c2ecf20Sopenharmony_ci } 8528c2ecf20Sopenharmony_ci 8538c2ecf20Sopenharmony_ci if (priv->broadcast) { 8548c2ecf20Sopenharmony_ci rb_erase(&priv->broadcast->rb_node, &priv->multicast_tree); 8558c2ecf20Sopenharmony_ci list_add_tail(&priv->broadcast->list, &remove_list); 8568c2ecf20Sopenharmony_ci priv->broadcast = NULL; 8578c2ecf20Sopenharmony_ci } 8588c2ecf20Sopenharmony_ci 8598c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&priv->lock, flags); 8608c2ecf20Sopenharmony_ci 8618c2ecf20Sopenharmony_ci ipoib_mcast_remove_list(&remove_list); 8628c2ecf20Sopenharmony_ci mutex_unlock(&priv->mcast_mutex); 8638c2ecf20Sopenharmony_ci} 8648c2ecf20Sopenharmony_ci 8658c2ecf20Sopenharmony_cistatic int ipoib_mcast_addr_is_valid(const u8 *addr, const u8 *broadcast) 8668c2ecf20Sopenharmony_ci{ 8678c2ecf20Sopenharmony_ci /* reserved QPN, prefix, scope */ 8688c2ecf20Sopenharmony_ci if (memcmp(addr, broadcast, 6)) 8698c2ecf20Sopenharmony_ci return 0; 8708c2ecf20Sopenharmony_ci /* signature lower, pkey */ 8718c2ecf20Sopenharmony_ci if (memcmp(addr + 7, broadcast + 7, 3)) 8728c2ecf20Sopenharmony_ci return 0; 8738c2ecf20Sopenharmony_ci return 1; 8748c2ecf20Sopenharmony_ci} 8758c2ecf20Sopenharmony_ci 8768c2ecf20Sopenharmony_civoid ipoib_mcast_restart_task(struct work_struct *work) 8778c2ecf20Sopenharmony_ci{ 8788c2ecf20Sopenharmony_ci struct ipoib_dev_priv *priv = 8798c2ecf20Sopenharmony_ci container_of(work, struct ipoib_dev_priv, restart_task); 8808c2ecf20Sopenharmony_ci struct net_device *dev = priv->dev; 8818c2ecf20Sopenharmony_ci struct netdev_hw_addr *ha; 8828c2ecf20Sopenharmony_ci struct ipoib_mcast *mcast, *tmcast; 8838c2ecf20Sopenharmony_ci LIST_HEAD(remove_list); 8848c2ecf20Sopenharmony_ci struct ib_sa_mcmember_rec rec; 8858c2ecf20Sopenharmony_ci 8868c2ecf20Sopenharmony_ci if (!test_bit(IPOIB_FLAG_OPER_UP, &priv->flags)) 8878c2ecf20Sopenharmony_ci /* 8888c2ecf20Sopenharmony_ci * shortcut...on shutdown flush is called next, just 8898c2ecf20Sopenharmony_ci * let it do all the work 8908c2ecf20Sopenharmony_ci */ 8918c2ecf20Sopenharmony_ci return; 8928c2ecf20Sopenharmony_ci 8938c2ecf20Sopenharmony_ci ipoib_dbg_mcast(priv, "restarting multicast task\n"); 8948c2ecf20Sopenharmony_ci 8958c2ecf20Sopenharmony_ci netif_addr_lock_bh(dev); 8968c2ecf20Sopenharmony_ci spin_lock_irq(&priv->lock); 8978c2ecf20Sopenharmony_ci 8988c2ecf20Sopenharmony_ci /* 8998c2ecf20Sopenharmony_ci * Unfortunately, the networking core only gives us a list of all of 9008c2ecf20Sopenharmony_ci * the multicast hardware addresses. We need to figure out which ones 9018c2ecf20Sopenharmony_ci * are new and which ones have been removed 9028c2ecf20Sopenharmony_ci */ 9038c2ecf20Sopenharmony_ci 9048c2ecf20Sopenharmony_ci /* Clear out the found flag */ 9058c2ecf20Sopenharmony_ci list_for_each_entry(mcast, &priv->multicast_list, list) 9068c2ecf20Sopenharmony_ci clear_bit(IPOIB_MCAST_FLAG_FOUND, &mcast->flags); 9078c2ecf20Sopenharmony_ci 9088c2ecf20Sopenharmony_ci /* Mark all of the entries that are found or don't exist */ 9098c2ecf20Sopenharmony_ci netdev_for_each_mc_addr(ha, dev) { 9108c2ecf20Sopenharmony_ci union ib_gid mgid; 9118c2ecf20Sopenharmony_ci 9128c2ecf20Sopenharmony_ci if (!ipoib_mcast_addr_is_valid(ha->addr, dev->broadcast)) 9138c2ecf20Sopenharmony_ci continue; 9148c2ecf20Sopenharmony_ci 9158c2ecf20Sopenharmony_ci memcpy(mgid.raw, ha->addr + 4, sizeof(mgid)); 9168c2ecf20Sopenharmony_ci 9178c2ecf20Sopenharmony_ci mcast = __ipoib_mcast_find(dev, &mgid); 9188c2ecf20Sopenharmony_ci if (!mcast || test_bit(IPOIB_MCAST_FLAG_SENDONLY, &mcast->flags)) { 9198c2ecf20Sopenharmony_ci struct ipoib_mcast *nmcast; 9208c2ecf20Sopenharmony_ci 9218c2ecf20Sopenharmony_ci /* ignore group which is directly joined by userspace */ 9228c2ecf20Sopenharmony_ci if (test_bit(IPOIB_FLAG_UMCAST, &priv->flags) && 9238c2ecf20Sopenharmony_ci !ib_sa_get_mcmember_rec(priv->ca, priv->port, &mgid, &rec)) { 9248c2ecf20Sopenharmony_ci ipoib_dbg_mcast(priv, "ignoring multicast entry for mgid %pI6\n", 9258c2ecf20Sopenharmony_ci mgid.raw); 9268c2ecf20Sopenharmony_ci continue; 9278c2ecf20Sopenharmony_ci } 9288c2ecf20Sopenharmony_ci 9298c2ecf20Sopenharmony_ci /* Not found or send-only group, let's add a new entry */ 9308c2ecf20Sopenharmony_ci ipoib_dbg_mcast(priv, "adding multicast entry for mgid %pI6\n", 9318c2ecf20Sopenharmony_ci mgid.raw); 9328c2ecf20Sopenharmony_ci 9338c2ecf20Sopenharmony_ci nmcast = ipoib_mcast_alloc(dev); 9348c2ecf20Sopenharmony_ci if (!nmcast) { 9358c2ecf20Sopenharmony_ci ipoib_warn(priv, "unable to allocate memory for multicast structure\n"); 9368c2ecf20Sopenharmony_ci continue; 9378c2ecf20Sopenharmony_ci } 9388c2ecf20Sopenharmony_ci 9398c2ecf20Sopenharmony_ci set_bit(IPOIB_MCAST_FLAG_FOUND, &nmcast->flags); 9408c2ecf20Sopenharmony_ci 9418c2ecf20Sopenharmony_ci nmcast->mcmember.mgid = mgid; 9428c2ecf20Sopenharmony_ci 9438c2ecf20Sopenharmony_ci if (mcast) { 9448c2ecf20Sopenharmony_ci /* Destroy the send only entry */ 9458c2ecf20Sopenharmony_ci list_move_tail(&mcast->list, &remove_list); 9468c2ecf20Sopenharmony_ci 9478c2ecf20Sopenharmony_ci rb_replace_node(&mcast->rb_node, 9488c2ecf20Sopenharmony_ci &nmcast->rb_node, 9498c2ecf20Sopenharmony_ci &priv->multicast_tree); 9508c2ecf20Sopenharmony_ci } else 9518c2ecf20Sopenharmony_ci __ipoib_mcast_add(dev, nmcast); 9528c2ecf20Sopenharmony_ci 9538c2ecf20Sopenharmony_ci list_add_tail(&nmcast->list, &priv->multicast_list); 9548c2ecf20Sopenharmony_ci } 9558c2ecf20Sopenharmony_ci 9568c2ecf20Sopenharmony_ci if (mcast) 9578c2ecf20Sopenharmony_ci set_bit(IPOIB_MCAST_FLAG_FOUND, &mcast->flags); 9588c2ecf20Sopenharmony_ci } 9598c2ecf20Sopenharmony_ci 9608c2ecf20Sopenharmony_ci /* Remove all of the entries don't exist anymore */ 9618c2ecf20Sopenharmony_ci list_for_each_entry_safe(mcast, tmcast, &priv->multicast_list, list) { 9628c2ecf20Sopenharmony_ci if (!test_bit(IPOIB_MCAST_FLAG_FOUND, &mcast->flags) && 9638c2ecf20Sopenharmony_ci !test_bit(IPOIB_MCAST_FLAG_SENDONLY, &mcast->flags)) { 9648c2ecf20Sopenharmony_ci ipoib_dbg_mcast(priv, "deleting multicast group %pI6\n", 9658c2ecf20Sopenharmony_ci mcast->mcmember.mgid.raw); 9668c2ecf20Sopenharmony_ci 9678c2ecf20Sopenharmony_ci rb_erase(&mcast->rb_node, &priv->multicast_tree); 9688c2ecf20Sopenharmony_ci 9698c2ecf20Sopenharmony_ci /* Move to the remove list */ 9708c2ecf20Sopenharmony_ci list_move_tail(&mcast->list, &remove_list); 9718c2ecf20Sopenharmony_ci } 9728c2ecf20Sopenharmony_ci } 9738c2ecf20Sopenharmony_ci 9748c2ecf20Sopenharmony_ci spin_unlock_irq(&priv->lock); 9758c2ecf20Sopenharmony_ci netif_addr_unlock_bh(dev); 9768c2ecf20Sopenharmony_ci 9778c2ecf20Sopenharmony_ci ipoib_mcast_remove_list(&remove_list); 9788c2ecf20Sopenharmony_ci 9798c2ecf20Sopenharmony_ci /* 9808c2ecf20Sopenharmony_ci * Double check that we are still up 9818c2ecf20Sopenharmony_ci */ 9828c2ecf20Sopenharmony_ci if (test_bit(IPOIB_FLAG_OPER_UP, &priv->flags)) { 9838c2ecf20Sopenharmony_ci spin_lock_irq(&priv->lock); 9848c2ecf20Sopenharmony_ci __ipoib_mcast_schedule_join_thread(priv, NULL, 0); 9858c2ecf20Sopenharmony_ci spin_unlock_irq(&priv->lock); 9868c2ecf20Sopenharmony_ci } 9878c2ecf20Sopenharmony_ci} 9888c2ecf20Sopenharmony_ci 9898c2ecf20Sopenharmony_ci#ifdef CONFIG_INFINIBAND_IPOIB_DEBUG 9908c2ecf20Sopenharmony_ci 9918c2ecf20Sopenharmony_cistruct ipoib_mcast_iter *ipoib_mcast_iter_init(struct net_device *dev) 9928c2ecf20Sopenharmony_ci{ 9938c2ecf20Sopenharmony_ci struct ipoib_mcast_iter *iter; 9948c2ecf20Sopenharmony_ci 9958c2ecf20Sopenharmony_ci iter = kmalloc(sizeof(*iter), GFP_KERNEL); 9968c2ecf20Sopenharmony_ci if (!iter) 9978c2ecf20Sopenharmony_ci return NULL; 9988c2ecf20Sopenharmony_ci 9998c2ecf20Sopenharmony_ci iter->dev = dev; 10008c2ecf20Sopenharmony_ci memset(iter->mgid.raw, 0, 16); 10018c2ecf20Sopenharmony_ci 10028c2ecf20Sopenharmony_ci if (ipoib_mcast_iter_next(iter)) { 10038c2ecf20Sopenharmony_ci kfree(iter); 10048c2ecf20Sopenharmony_ci return NULL; 10058c2ecf20Sopenharmony_ci } 10068c2ecf20Sopenharmony_ci 10078c2ecf20Sopenharmony_ci return iter; 10088c2ecf20Sopenharmony_ci} 10098c2ecf20Sopenharmony_ci 10108c2ecf20Sopenharmony_ciint ipoib_mcast_iter_next(struct ipoib_mcast_iter *iter) 10118c2ecf20Sopenharmony_ci{ 10128c2ecf20Sopenharmony_ci struct ipoib_dev_priv *priv = ipoib_priv(iter->dev); 10138c2ecf20Sopenharmony_ci struct rb_node *n; 10148c2ecf20Sopenharmony_ci struct ipoib_mcast *mcast; 10158c2ecf20Sopenharmony_ci int ret = 1; 10168c2ecf20Sopenharmony_ci 10178c2ecf20Sopenharmony_ci spin_lock_irq(&priv->lock); 10188c2ecf20Sopenharmony_ci 10198c2ecf20Sopenharmony_ci n = rb_first(&priv->multicast_tree); 10208c2ecf20Sopenharmony_ci 10218c2ecf20Sopenharmony_ci while (n) { 10228c2ecf20Sopenharmony_ci mcast = rb_entry(n, struct ipoib_mcast, rb_node); 10238c2ecf20Sopenharmony_ci 10248c2ecf20Sopenharmony_ci if (memcmp(iter->mgid.raw, mcast->mcmember.mgid.raw, 10258c2ecf20Sopenharmony_ci sizeof (union ib_gid)) < 0) { 10268c2ecf20Sopenharmony_ci iter->mgid = mcast->mcmember.mgid; 10278c2ecf20Sopenharmony_ci iter->created = mcast->created; 10288c2ecf20Sopenharmony_ci iter->queuelen = skb_queue_len(&mcast->pkt_queue); 10298c2ecf20Sopenharmony_ci iter->complete = !!mcast->ah; 10308c2ecf20Sopenharmony_ci iter->send_only = !!(mcast->flags & (1 << IPOIB_MCAST_FLAG_SENDONLY)); 10318c2ecf20Sopenharmony_ci 10328c2ecf20Sopenharmony_ci ret = 0; 10338c2ecf20Sopenharmony_ci 10348c2ecf20Sopenharmony_ci break; 10358c2ecf20Sopenharmony_ci } 10368c2ecf20Sopenharmony_ci 10378c2ecf20Sopenharmony_ci n = rb_next(n); 10388c2ecf20Sopenharmony_ci } 10398c2ecf20Sopenharmony_ci 10408c2ecf20Sopenharmony_ci spin_unlock_irq(&priv->lock); 10418c2ecf20Sopenharmony_ci 10428c2ecf20Sopenharmony_ci return ret; 10438c2ecf20Sopenharmony_ci} 10448c2ecf20Sopenharmony_ci 10458c2ecf20Sopenharmony_civoid ipoib_mcast_iter_read(struct ipoib_mcast_iter *iter, 10468c2ecf20Sopenharmony_ci union ib_gid *mgid, 10478c2ecf20Sopenharmony_ci unsigned long *created, 10488c2ecf20Sopenharmony_ci unsigned int *queuelen, 10498c2ecf20Sopenharmony_ci unsigned int *complete, 10508c2ecf20Sopenharmony_ci unsigned int *send_only) 10518c2ecf20Sopenharmony_ci{ 10528c2ecf20Sopenharmony_ci *mgid = iter->mgid; 10538c2ecf20Sopenharmony_ci *created = iter->created; 10548c2ecf20Sopenharmony_ci *queuelen = iter->queuelen; 10558c2ecf20Sopenharmony_ci *complete = iter->complete; 10568c2ecf20Sopenharmony_ci *send_only = iter->send_only; 10578c2ecf20Sopenharmony_ci} 10588c2ecf20Sopenharmony_ci 10598c2ecf20Sopenharmony_ci#endif /* CONFIG_INFINIBAND_IPOIB_DEBUG */ 1060