Path: blob/main/sys/ofed/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
39566 views
/*-1* SPDX-License-Identifier: BSD-2-Clause OR GPL-2.02*3* Copyright (c) 2004, 2005 Topspin Communications. All rights reserved.4* Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.5* Copyright (c) 2004 Voltaire, Inc. All rights reserved.6*7* This software is available to you under a choice of one of two8* licenses. You may choose to be licensed under the terms of the GNU9* General Public License (GPL) Version 2, available from the file10* COPYING in the main directory of this source tree, or the11* OpenIB.org BSD license below:12*13* Redistribution and use in source and binary forms, with or14* without modification, are permitted provided that the following15* conditions are met:16*17* - Redistributions of source code must retain the above18* copyright notice, this list of conditions and the following19* disclaimer.20*21* - Redistributions in binary form must reproduce the above22* copyright notice, this list of conditions and the following23* disclaimer in the documentation and/or other materials24* provided with the distribution.25*26* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,27* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF28* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND29* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS30* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN31* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN32* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE33* SOFTWARE.34*/3536#include <sys/cdefs.h>37#include "ipoib.h"3839#include <linux/delay.h>40#include <linux/completion.h>4142#ifdef CONFIG_INFINIBAND_IPOIB_DEBUG43static int mcast_debug_level = 1;4445module_param(mcast_debug_level, int, 0644);46MODULE_PARM_DESC(mcast_debug_level,47"Enable multicast debug tracing if > 0");48#endif4950static DEFINE_MUTEX(mcast_mutex);5152struct ipoib_mcast_iter {53struct ipoib_dev_priv *priv;54union ib_gid mgid;55unsigned long created;56unsigned int queuelen;57unsigned int complete;58unsigned int send_only;59};6061static void ipoib_mcast_free(struct ipoib_mcast *mcast)62{63if_t dev = mcast->priv->dev;64int tx_dropped = 0;6566ipoib_dbg_mcast(mcast->priv, "deleting multicast group %16D\n",67mcast->mcmember.mgid.raw, ":");6869if (mcast->ah)70ipoib_put_ah(mcast->ah);7172tx_dropped = mcast->pkt_queue.ifq_len;73_IF_DRAIN(&mcast->pkt_queue); /* XXX Locking. */7475if_inc_counter(dev, IFCOUNTER_OERRORS, tx_dropped);7677kfree(mcast);78}7980static struct ipoib_mcast *ipoib_mcast_alloc(struct ipoib_dev_priv *priv,81int can_sleep)82{83struct ipoib_mcast *mcast;8485mcast = kzalloc(sizeof *mcast, can_sleep ? GFP_KERNEL : GFP_ATOMIC);86if (!mcast)87return NULL;8889mcast->priv = priv;90mcast->created = jiffies;91mcast->backoff = 1;9293INIT_LIST_HEAD(&mcast->list);94bzero(&mcast->pkt_queue, sizeof(mcast->pkt_queue));9596return mcast;97}9899static struct ipoib_mcast *__ipoib_mcast_find(struct ipoib_dev_priv *priv,100void *mgid)101{102struct rb_node *n = priv->multicast_tree.rb_node;103104while (n) {105struct ipoib_mcast *mcast;106int ret;107108mcast = rb_entry(n, struct ipoib_mcast, rb_node);109110ret = memcmp(mgid, mcast->mcmember.mgid.raw,111sizeof (union ib_gid));112if (ret < 0)113n = n->rb_left;114else if (ret > 0)115n = n->rb_right;116else117return mcast;118}119120return NULL;121}122123static int __ipoib_mcast_add(struct ipoib_dev_priv *priv,124struct ipoib_mcast *mcast)125{126struct rb_node **n = &priv->multicast_tree.rb_node, *pn = NULL;127128while (*n) {129struct ipoib_mcast *tmcast;130int ret;131132pn = *n;133tmcast = rb_entry(pn, struct ipoib_mcast, rb_node);134135ret = memcmp(mcast->mcmember.mgid.raw, tmcast->mcmember.mgid.raw,136sizeof (union ib_gid));137if (ret < 0)138n = &pn->rb_left;139else if (ret > 0)140n = &pn->rb_right;141else142return -EEXIST;143}144145rb_link_node(&mcast->rb_node, pn, n);146rb_insert_color(&mcast->rb_node, &priv->multicast_tree);147148return 0;149}150151static int ipoib_mcast_join_finish(struct ipoib_mcast *mcast,152struct ib_sa_mcmember_rec *mcmember)153{154struct ipoib_dev_priv *priv = mcast->priv;155if_t dev = priv->dev;156struct ipoib_ah *ah;157struct epoch_tracker et;158int ret;159int set_qkey = 0;160161mcast->mcmember = *mcmember;162163/* Set the cached Q_Key before we attach if it's the broadcast group */164if (!memcmp(mcast->mcmember.mgid.raw, if_getbroadcastaddr(dev) + 4,165sizeof (union ib_gid))) {166spin_lock_irq(&priv->lock);167if (!priv->broadcast) {168spin_unlock_irq(&priv->lock);169return -EAGAIN;170}171priv->qkey = be32_to_cpu(priv->broadcast->mcmember.qkey);172spin_unlock_irq(&priv->lock);173priv->tx_wr.remote_qkey = priv->qkey;174set_qkey = 1;175}176177if (!test_bit(IPOIB_MCAST_FLAG_SENDONLY, &mcast->flags)) {178if (test_and_set_bit(IPOIB_MCAST_FLAG_ATTACHED, &mcast->flags)) {179ipoib_warn(priv, "multicast group %16D already attached\n",180mcast->mcmember.mgid.raw, ":");181182return 0;183}184185ret = ipoib_mcast_attach(priv, be16_to_cpu(mcast->mcmember.mlid),186&mcast->mcmember.mgid, set_qkey);187if (ret < 0) {188ipoib_warn(priv, "couldn't attach QP to multicast group %16D\n",189mcast->mcmember.mgid.raw, ":");190191clear_bit(IPOIB_MCAST_FLAG_ATTACHED, &mcast->flags);192return ret;193}194}195196{197struct ib_ah_attr av = {198.dlid = be16_to_cpu(mcast->mcmember.mlid),199.port_num = priv->port,200.sl = mcast->mcmember.sl,201.ah_flags = IB_AH_GRH,202.static_rate = mcast->mcmember.rate,203.grh = {204.flow_label = be32_to_cpu(mcast->mcmember.flow_label),205.hop_limit = mcast->mcmember.hop_limit,206.sgid_index = 0,207.traffic_class = mcast->mcmember.traffic_class208}209};210av.grh.dgid = mcast->mcmember.mgid;211212ah = ipoib_create_ah(priv, priv->pd, &av);213if (!ah) {214ipoib_warn(priv, "ib_address_create failed\n");215} else {216spin_lock_irq(&priv->lock);217mcast->ah = ah;218spin_unlock_irq(&priv->lock);219220ipoib_dbg_mcast(priv, "MGID %16D AV %p, LID 0x%04x, SL %d\n",221mcast->mcmember.mgid.raw, ":",222mcast->ah->ah,223be16_to_cpu(mcast->mcmember.mlid),224mcast->mcmember.sl);225}226}227228NET_EPOCH_ENTER(et);229230/* actually send any queued packets */231while (mcast->pkt_queue.ifq_len) {232struct mbuf *mb;233_IF_DEQUEUE(&mcast->pkt_queue, mb);234mb->m_pkthdr.rcvif = dev;235236if (if_transmit(dev, mb))237ipoib_warn(priv, "dev_queue_xmit failed to requeue packet\n");238}239240NET_EPOCH_EXIT(et);241return 0;242}243244static int245ipoib_mcast_sendonly_join_complete(int status,246struct ib_sa_multicast *multicast)247{248struct ipoib_mcast *mcast = multicast->context;249struct ipoib_dev_priv *priv = mcast->priv;250251/* We trap for port events ourselves. */252if (status == -ENETRESET)253return 0;254255if (!status)256status = ipoib_mcast_join_finish(mcast, &multicast->rec);257258if (status) {259if (mcast->logcount++ < 20)260ipoib_dbg_mcast(priv, "multicast join failed for %16D, status %d\n",261mcast->mcmember.mgid.raw, ":", status);262263/* Flush out any queued packets */264if_inc_counter(priv->dev, IFCOUNTER_OERRORS, mcast->pkt_queue.ifq_len);265_IF_DRAIN(&mcast->pkt_queue);266267/* Clear the busy flag so we try again */268status = test_and_clear_bit(IPOIB_MCAST_FLAG_BUSY,269&mcast->flags);270}271return status;272}273274static int ipoib_mcast_sendonly_join(struct ipoib_mcast *mcast)275{276struct ipoib_dev_priv *priv = mcast->priv;277struct ib_sa_mcmember_rec rec = {278#if 0 /* Some SMs don't support send-only yet */279.join_state = 4280#else281.join_state = 1282#endif283};284int ret = 0;285286if (!test_bit(IPOIB_FLAG_OPER_UP, &priv->flags)) {287ipoib_dbg_mcast(priv, "device shutting down, no multicast joins\n");288return -ENODEV;289}290291if (test_and_set_bit(IPOIB_MCAST_FLAG_BUSY, &mcast->flags)) {292ipoib_dbg_mcast(priv, "multicast entry busy, skipping\n");293return -EBUSY;294}295296rec.mgid = mcast->mcmember.mgid;297rec.port_gid = priv->local_gid;298rec.pkey = cpu_to_be16(priv->pkey);299300mcast->mc = ib_sa_join_multicast(&ipoib_sa_client, priv->ca,301priv->port, &rec,302IB_SA_MCMEMBER_REC_MGID |303IB_SA_MCMEMBER_REC_PORT_GID |304IB_SA_MCMEMBER_REC_PKEY |305IB_SA_MCMEMBER_REC_JOIN_STATE,306GFP_ATOMIC,307ipoib_mcast_sendonly_join_complete,308mcast);309if (IS_ERR(mcast->mc)) {310ret = PTR_ERR(mcast->mc);311clear_bit(IPOIB_MCAST_FLAG_BUSY, &mcast->flags);312ipoib_warn(priv, "ib_sa_join_multicast failed (ret = %d)\n",313ret);314} else {315ipoib_dbg_mcast(priv, "no multicast record for %16D, starting join\n",316mcast->mcmember.mgid.raw, ":");317}318319return ret;320}321322void ipoib_mcast_carrier_on_task(struct work_struct *work)323{324struct ipoib_dev_priv *priv = container_of(work, struct ipoib_dev_priv,325carrier_on_task);326struct ib_port_attr attr;327328/*329* Take rtnl_lock to avoid racing with ipoib_stop() and330* turning the carrier back on while a device is being331* removed.332*/333if (ib_query_port(priv->ca, priv->port, &attr) ||334attr.state != IB_PORT_ACTIVE) {335ipoib_dbg(priv, "Keeping carrier off until IB port is active\n");336return;337}338if_link_state_change(priv->dev, LINK_STATE_UP);339}340341static int ipoib_mcast_join_complete(int status,342struct ib_sa_multicast *multicast)343{344struct ipoib_mcast *mcast = multicast->context;345struct ipoib_dev_priv *priv = mcast->priv;346347ipoib_dbg_mcast(priv, "join completion for %16D (status %d)\n",348mcast->mcmember.mgid.raw, ":", status);349350/* We trap for port events ourselves. */351if (status == -ENETRESET)352return 0;353354if (!status)355status = ipoib_mcast_join_finish(mcast, &multicast->rec);356357if (!status) {358mcast->backoff = 1;359mutex_lock(&mcast_mutex);360if (test_bit(IPOIB_MCAST_RUN, &priv->flags))361queue_delayed_work(ipoib_workqueue,362&priv->mcast_task, 0);363mutex_unlock(&mcast_mutex);364365/*366* Defer carrier on work to ipoib_workqueue to avoid a367* deadlock on rtnl_lock here.368*/369if (mcast == priv->broadcast)370queue_work(ipoib_workqueue, &priv->carrier_on_task);371372return 0;373}374375if (mcast->logcount++ < 20) {376if (status == -ETIMEDOUT || status == -EAGAIN) {377ipoib_dbg_mcast(priv, "multicast join failed for %16D, status %d\n",378mcast->mcmember.mgid.raw, ":", status);379} else {380ipoib_warn(priv, "multicast join failed for %16D, status %d\n",381mcast->mcmember.mgid.raw, ":", status);382}383}384385mcast->backoff *= 2;386if (mcast->backoff > IPOIB_MAX_BACKOFF_SECONDS)387mcast->backoff = IPOIB_MAX_BACKOFF_SECONDS;388389/* Clear the busy flag so we try again */390status = test_and_clear_bit(IPOIB_MCAST_FLAG_BUSY, &mcast->flags);391392mutex_lock(&mcast_mutex);393spin_lock_irq(&priv->lock);394if (test_bit(IPOIB_MCAST_RUN, &priv->flags))395queue_delayed_work(ipoib_workqueue, &priv->mcast_task,396mcast->backoff * HZ);397spin_unlock_irq(&priv->lock);398mutex_unlock(&mcast_mutex);399400return status;401}402403static void ipoib_mcast_join(struct ipoib_dev_priv *priv,404struct ipoib_mcast *mcast, int create)405{406struct ib_sa_mcmember_rec rec = {407.join_state = 1408};409ib_sa_comp_mask comp_mask;410int ret = 0;411412ipoib_dbg_mcast(priv, "joining MGID %16D\n",413mcast->mcmember.mgid.raw, ":");414415rec.mgid = mcast->mcmember.mgid;416rec.port_gid = priv->local_gid;417rec.pkey = cpu_to_be16(priv->pkey);418419comp_mask =420IB_SA_MCMEMBER_REC_MGID |421IB_SA_MCMEMBER_REC_PORT_GID |422IB_SA_MCMEMBER_REC_PKEY |423IB_SA_MCMEMBER_REC_JOIN_STATE;424425if (create) {426comp_mask |=427IB_SA_MCMEMBER_REC_QKEY |428IB_SA_MCMEMBER_REC_MTU_SELECTOR |429IB_SA_MCMEMBER_REC_MTU |430IB_SA_MCMEMBER_REC_TRAFFIC_CLASS |431IB_SA_MCMEMBER_REC_RATE_SELECTOR |432IB_SA_MCMEMBER_REC_RATE |433IB_SA_MCMEMBER_REC_SL |434IB_SA_MCMEMBER_REC_FLOW_LABEL |435IB_SA_MCMEMBER_REC_HOP_LIMIT;436437rec.qkey = priv->broadcast->mcmember.qkey;438rec.mtu_selector = IB_SA_EQ;439rec.mtu = priv->broadcast->mcmember.mtu;440rec.traffic_class = priv->broadcast->mcmember.traffic_class;441rec.rate_selector = IB_SA_EQ;442rec.rate = priv->broadcast->mcmember.rate;443rec.sl = priv->broadcast->mcmember.sl;444rec.flow_label = priv->broadcast->mcmember.flow_label;445rec.hop_limit = priv->broadcast->mcmember.hop_limit;446}447448set_bit(IPOIB_MCAST_FLAG_BUSY, &mcast->flags);449mcast->mc = ib_sa_join_multicast(&ipoib_sa_client, priv->ca, priv->port,450&rec, comp_mask, GFP_KERNEL,451ipoib_mcast_join_complete, mcast);452if (IS_ERR(mcast->mc)) {453clear_bit(IPOIB_MCAST_FLAG_BUSY, &mcast->flags);454ret = PTR_ERR(mcast->mc);455ipoib_warn(priv, "ib_sa_join_multicast failed, status %d\n", ret);456457mcast->backoff *= 2;458if (mcast->backoff > IPOIB_MAX_BACKOFF_SECONDS)459mcast->backoff = IPOIB_MAX_BACKOFF_SECONDS;460461mutex_lock(&mcast_mutex);462if (test_bit(IPOIB_MCAST_RUN, &priv->flags))463queue_delayed_work(ipoib_workqueue,464&priv->mcast_task,465mcast->backoff * HZ);466mutex_unlock(&mcast_mutex);467}468}469470void ipoib_mcast_join_task(struct work_struct *work)471{472struct ipoib_dev_priv *priv =473container_of(work, struct ipoib_dev_priv, mcast_task.work);474if_t dev = priv->dev;475struct ib_port_attr attr;476477ipoib_dbg_mcast(priv, "Running join task. flags 0x%lX\n", priv->flags);478479if (!test_bit(IPOIB_MCAST_RUN, &priv->flags))480return;481482if (ib_query_port(priv->ca, priv->port, &attr) ||483attr.state != IB_PORT_ACTIVE) {484ipoib_dbg(priv, "%s: port state is not ACTIVE (state = %d) suspend task.\n",485__func__, attr.state);486return;487}488489if (ib_query_gid(priv->ca, priv->port, 0, &priv->local_gid, NULL))490ipoib_warn(priv, "ib_query_gid() failed\n");491else492memcpy(if_getlladdr(dev) + 4, priv->local_gid.raw, sizeof (union ib_gid));493494{495struct ib_port_attr attr;496497if (!ib_query_port(priv->ca, priv->port, &attr))498priv->local_lid = attr.lid;499else500ipoib_warn(priv, "ib_query_port failed\n");501}502503if (!priv->broadcast) {504struct ipoib_mcast *broadcast;505506if (!test_bit(IPOIB_FLAG_ADMIN_UP, &priv->flags))507return;508509broadcast = ipoib_mcast_alloc(priv, 1);510if (!broadcast) {511ipoib_warn(priv, "failed to allocate broadcast group\n");512mutex_lock(&mcast_mutex);513if (test_bit(IPOIB_MCAST_RUN, &priv->flags))514queue_delayed_work(ipoib_workqueue,515&priv->mcast_task, HZ);516mutex_unlock(&mcast_mutex);517return;518}519520spin_lock_irq(&priv->lock);521memcpy(broadcast->mcmember.mgid.raw, if_getbroadcastaddr(dev) + 4,522sizeof (union ib_gid));523priv->broadcast = broadcast;524525__ipoib_mcast_add(priv, priv->broadcast);526spin_unlock_irq(&priv->lock);527}528529if (priv->broadcast &&530!test_bit(IPOIB_MCAST_FLAG_ATTACHED, &priv->broadcast->flags)) {531if (priv->broadcast &&532!test_bit(IPOIB_MCAST_FLAG_BUSY, &priv->broadcast->flags))533ipoib_mcast_join(priv, priv->broadcast, 0);534return;535}536537while (1) {538struct ipoib_mcast *mcast = NULL;539540spin_lock_irq(&priv->lock);541list_for_each_entry(mcast, &priv->multicast_list, list) {542if (!test_bit(IPOIB_MCAST_FLAG_SENDONLY, &mcast->flags)543&& !test_bit(IPOIB_MCAST_FLAG_BUSY, &mcast->flags)544&& !test_bit(IPOIB_MCAST_FLAG_ATTACHED, &mcast->flags)) {545/* Found the next unjoined group */546break;547}548}549spin_unlock_irq(&priv->lock);550551if (&mcast->list == &priv->multicast_list) {552/* All done */553break;554}555556ipoib_mcast_join(priv, mcast, 1);557return;558}559560spin_lock_irq(&priv->lock);561if (priv->broadcast)562priv->mcast_mtu = IPOIB_UD_MTU(ib_mtu_enum_to_int(priv->broadcast->mcmember.mtu));563else564priv->mcast_mtu = priv->admin_mtu;565spin_unlock_irq(&priv->lock);566567if (!ipoib_cm_admin_enabled(priv))568ipoib_change_mtu(priv, min(priv->mcast_mtu, priv->admin_mtu),569true);570571ipoib_dbg_mcast(priv, "successfully joined all multicast groups\n");572573clear_bit(IPOIB_MCAST_RUN, &priv->flags);574}575576int ipoib_mcast_start_thread(struct ipoib_dev_priv *priv)577{578ipoib_dbg_mcast(priv, "starting multicast thread flags 0x%lX\n",579priv->flags);580581mutex_lock(&mcast_mutex);582if (!test_and_set_bit(IPOIB_MCAST_RUN, &priv->flags))583queue_delayed_work(ipoib_workqueue, &priv->mcast_task, 0);584mutex_unlock(&mcast_mutex);585586return 0;587}588589int ipoib_mcast_stop_thread(struct ipoib_dev_priv *priv, int flush)590{591592ipoib_dbg_mcast(priv, "stopping multicast thread\n");593594mutex_lock(&mcast_mutex);595clear_bit(IPOIB_MCAST_RUN, &priv->flags);596cancel_delayed_work(&priv->mcast_task);597mutex_unlock(&mcast_mutex);598599if (flush)600flush_workqueue(ipoib_workqueue);601602return 0;603}604605static int ipoib_mcast_leave(struct ipoib_dev_priv *priv, struct ipoib_mcast *mcast)606{607int ret = 0;608609if (test_and_clear_bit(IPOIB_MCAST_FLAG_BUSY, &mcast->flags))610ib_sa_free_multicast(mcast->mc);611612if (test_and_clear_bit(IPOIB_MCAST_FLAG_ATTACHED, &mcast->flags)) {613ipoib_dbg_mcast(priv, "leaving MGID %16D\n",614mcast->mcmember.mgid.raw, ":");615616/* Remove ourselves from the multicast group */617ret = ib_detach_mcast(priv->qp, &mcast->mcmember.mgid,618be16_to_cpu(mcast->mcmember.mlid));619if (ret)620ipoib_warn(priv, "ib_detach_mcast failed (result = %d)\n", ret);621}622623return 0;624}625626void627ipoib_mcast_send(struct ipoib_dev_priv *priv, void *mgid, struct mbuf *mb)628{629if_t dev = priv->dev;630struct ipoib_mcast *mcast;631632if (!test_bit(IPOIB_FLAG_OPER_UP, &priv->flags) ||633!priv->broadcast ||634!test_bit(IPOIB_MCAST_FLAG_ATTACHED, &priv->broadcast->flags)) {635if_inc_counter(dev, IFCOUNTER_OERRORS, 1);636m_freem(mb);637return;638}639640mcast = __ipoib_mcast_find(priv, mgid);641if (!mcast) {642/* Let's create a new send only group now */643ipoib_dbg_mcast(priv, "setting up send only multicast group for %16D\n",644mgid, ":");645646mcast = ipoib_mcast_alloc(priv, 0);647if (!mcast) {648ipoib_warn(priv, "unable to allocate memory for "649"multicast structure\n");650if_inc_counter(dev, IFCOUNTER_OERRORS, 1);651m_freem(mb);652goto out;653}654655set_bit(IPOIB_MCAST_FLAG_SENDONLY, &mcast->flags);656memcpy(mcast->mcmember.mgid.raw, mgid, sizeof (union ib_gid));657__ipoib_mcast_add(priv, mcast);658list_add_tail(&mcast->list, &priv->multicast_list);659}660661if (!mcast->ah) {662if (mcast->pkt_queue.ifq_len < IPOIB_MAX_MCAST_QUEUE) {663_IF_ENQUEUE(&mcast->pkt_queue, mb);664} else {665if_inc_counter(dev, IFCOUNTER_OERRORS, 1);666m_freem(mb);667}668669if (test_bit(IPOIB_MCAST_FLAG_BUSY, &mcast->flags))670ipoib_dbg_mcast(priv, "no address vector, "671"but multicast join already started\n");672else if (test_bit(IPOIB_MCAST_FLAG_SENDONLY, &mcast->flags))673ipoib_mcast_sendonly_join(mcast);674675/*676* If lookup completes between here and out:, don't677* want to send packet twice.678*/679mcast = NULL;680}681682out:683if (mcast && mcast->ah)684ipoib_send(priv, mb, mcast->ah, IB_MULTICAST_QPN);685}686687void ipoib_mcast_dev_flush(struct ipoib_dev_priv *priv)688{689LIST_HEAD(remove_list);690struct ipoib_mcast *mcast, *tmcast;691unsigned long flags;692693ipoib_dbg_mcast(priv, "flushing multicast list\n");694695spin_lock_irqsave(&priv->lock, flags);696697list_for_each_entry_safe(mcast, tmcast, &priv->multicast_list, list) {698list_del(&mcast->list);699rb_erase(&mcast->rb_node, &priv->multicast_tree);700list_add_tail(&mcast->list, &remove_list);701}702703if (priv->broadcast) {704rb_erase(&priv->broadcast->rb_node, &priv->multicast_tree);705list_add_tail(&priv->broadcast->list, &remove_list);706priv->broadcast = NULL;707}708709spin_unlock_irqrestore(&priv->lock, flags);710711list_for_each_entry_safe(mcast, tmcast, &remove_list, list) {712ipoib_mcast_leave(priv, mcast);713ipoib_mcast_free(mcast);714}715}716717static int ipoib_mcast_addr_is_valid(const u8 *addr, unsigned int addrlen,718const u8 *broadcast)719{720if (addrlen != INFINIBAND_ALEN)721return 0;722/* reserved QPN, prefix, scope */723if (memcmp(addr, broadcast, 6))724return 0;725/* signature lower, pkey */726if (memcmp(addr + 7, broadcast + 7, 3))727return 0;728return 1;729}730731void ipoib_mcast_restart_task(struct work_struct *work)732{733struct ipoib_dev_priv *priv =734container_of(work, struct ipoib_dev_priv, restart_task);735ipoib_mcast_restart(priv);736}737738struct ipoib_mcast_ctx {739struct ipoib_dev_priv *priv;740struct list_head remove_list;741};742743static u_int744ipoib_process_maddr(void *arg, struct sockaddr_dl *sdl, u_int cnt)745{746struct ipoib_mcast_ctx *ctx = arg;747struct ipoib_dev_priv *priv = ctx->priv;748struct ipoib_mcast *mcast;749struct ib_sa_mcmember_rec rec;750union ib_gid mgid;751uint8_t *addr;752int addrlen;753754addr = LLADDR(sdl);755addrlen = sdl->sdl_alen;756if (!ipoib_mcast_addr_is_valid(addr, addrlen,757if_getbroadcastaddr(priv->dev)))758return (0);759760memcpy(mgid.raw, addr + 4, sizeof mgid);761762mcast = __ipoib_mcast_find(priv, &mgid);763if (!mcast || test_bit(IPOIB_MCAST_FLAG_SENDONLY, &mcast->flags)) {764struct ipoib_mcast *nmcast;765766/* ignore group which is directly joined by userspace */767if (test_bit(IPOIB_FLAG_UMCAST, &priv->flags) &&768!ib_sa_get_mcmember_rec(priv->ca, priv->port, &mgid, &rec)) {769ipoib_dbg_mcast(priv, "ignoring multicast entry for mgid %16D\n",770mgid.raw, ":");771return (0);772}773774/* Not found or send-only group, let's add a new entry */775ipoib_dbg_mcast(priv, "adding multicast entry for mgid %16D\n",776mgid.raw, ":");777778nmcast = ipoib_mcast_alloc(priv, 0);779if (!nmcast) {780ipoib_warn(priv, "unable to allocate memory for multicast structure\n");781return (0);782}783784set_bit(IPOIB_MCAST_FLAG_FOUND, &nmcast->flags);785786nmcast->mcmember.mgid = mgid;787788if (mcast) {789/* Destroy the send only entry */790list_move_tail(&mcast->list, &ctx->remove_list);791792rb_replace_node(&mcast->rb_node,793&nmcast->rb_node,794&priv->multicast_tree);795} else796__ipoib_mcast_add(priv, nmcast);797798list_add_tail(&nmcast->list, &priv->multicast_list);799}800801if (mcast)802set_bit(IPOIB_MCAST_FLAG_FOUND, &mcast->flags);803804return (1);805}806807void ipoib_mcast_restart(struct ipoib_dev_priv *priv)808{809struct ipoib_mcast_ctx ctx = { priv,810{ &ctx.remove_list, &ctx.remove_list }};811if_t dev = priv->dev;812struct ipoib_mcast *mcast, *tmcast;813814ipoib_dbg_mcast(priv, "restarting multicast task flags 0x%lX\n",815priv->flags);816817ipoib_mcast_stop_thread(priv, 0);818819spin_lock(&priv->lock);820821/*822* Unfortunately, the networking core only gives us a list of all of823* the multicast hardware addresses. We need to figure out which ones824* are new and which ones have been removed825*/826827/* Clear out the found flag */828list_for_each_entry(mcast, &priv->multicast_list, list)829clear_bit(IPOIB_MCAST_FLAG_FOUND, &mcast->flags);830831/* Mark all of the entries that are found or don't exist */832ctx.priv = priv;833if_foreach_llmaddr(dev, ipoib_process_maddr, &ctx);834835/* Remove all of the entries don't exist anymore */836list_for_each_entry_safe(mcast, tmcast, &priv->multicast_list, list) {837if (!test_bit(IPOIB_MCAST_FLAG_FOUND, &mcast->flags) &&838!test_bit(IPOIB_MCAST_FLAG_SENDONLY, &mcast->flags)) {839ipoib_dbg_mcast(priv, "deleting multicast group %16D\n",840mcast->mcmember.mgid.raw, ":");841842rb_erase(&mcast->rb_node, &priv->multicast_tree);843844/* Move to the remove list */845list_move_tail(&mcast->list, &ctx.remove_list);846}847}848849spin_unlock(&priv->lock);850851/* We have to cancel outside of the spinlock */852list_for_each_entry_safe(mcast, tmcast, &ctx.remove_list, list) {853ipoib_mcast_leave(mcast->priv, mcast);854ipoib_mcast_free(mcast);855}856857if (test_bit(IPOIB_FLAG_ADMIN_UP, &priv->flags))858ipoib_mcast_start_thread(priv);859}860861#ifdef CONFIG_INFINIBAND_IPOIB_DEBUG862863struct ipoib_mcast_iter *ipoib_mcast_iter_init(struct ipoib_dev_priv *priv)864{865struct ipoib_mcast_iter *iter;866867iter = kmalloc(sizeof *iter, GFP_KERNEL);868if (!iter)869return NULL;870871iter->priv = priv;872memset(iter->mgid.raw, 0, 16);873874if (ipoib_mcast_iter_next(iter)) {875kfree(iter);876return NULL;877}878879return iter;880}881882int ipoib_mcast_iter_next(struct ipoib_mcast_iter *iter)883{884struct ipoib_dev_priv *priv = iter->priv;885struct rb_node *n;886struct ipoib_mcast *mcast;887int ret = 1;888889spin_lock_irq(&priv->lock);890891n = rb_first(&priv->multicast_tree);892893while (n) {894mcast = rb_entry(n, struct ipoib_mcast, rb_node);895896if (memcmp(iter->mgid.raw, mcast->mcmember.mgid.raw,897sizeof (union ib_gid)) < 0) {898iter->mgid = mcast->mcmember.mgid;899iter->created = mcast->created;900iter->queuelen = mcast->pkt_queue.ifq_len;901iter->complete = !!mcast->ah;902iter->send_only = !!(mcast->flags & (1 << IPOIB_MCAST_FLAG_SENDONLY));903904ret = 0;905906break;907}908909n = rb_next(n);910}911912spin_unlock_irq(&priv->lock);913914return ret;915}916917void ipoib_mcast_iter_read(struct ipoib_mcast_iter *iter,918union ib_gid *mgid,919unsigned long *created,920unsigned int *queuelen,921unsigned int *complete,922unsigned int *send_only)923{924*mgid = iter->mgid;925*created = iter->created;926*queuelen = iter->queuelen;927*complete = iter->complete;928*send_only = iter->send_only;929}930931#endif /* CONFIG_INFINIBAND_IPOIB_DEBUG */932933934