drivers/infiniband/ulp/ipoib/ipoib_multicast.c

Source file repositories/reference/linux-study-clean/drivers/infiniband/ulp/ipoib/ipoib_multicast.c

File Facts

System
Linux kernel
Corpus path
drivers/infiniband/ulp/ipoib/ipoib_multicast.c
Extension
.c
Size
29606 bytes
Lines
1048
Domain
Driver Families
Bucket
drivers/infiniband
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

struct ipoib_mcast_iter {
	struct net_device *dev;
	union ib_gid       mgid;
	unsigned long      created;
	unsigned int       queuelen;
	unsigned int       complete;
	unsigned int       send_only;
};

/* join state that allows creating mcg with sendonly member request */
#define SENDONLY_FULLMEMBER_JOIN	8

/*
 * This should be called with the priv->lock held
 */
static void __ipoib_mcast_schedule_join_thread(struct ipoib_dev_priv *priv,
					       struct ipoib_mcast *mcast,
					       bool delay)
{
	if (!test_bit(IPOIB_FLAG_OPER_UP, &priv->flags))
		return;

	/*
	 * We will be scheduling *something*, so cancel whatever is
	 * currently scheduled first
	 */
	cancel_delayed_work(&priv->mcast_task);
	if (mcast && delay) {
		/*
		 * We had a failure and want to schedule a retry later
		 */
		mcast->backoff *= 2;
		if (mcast->backoff > IPOIB_MAX_BACKOFF_SECONDS)
			mcast->backoff = IPOIB_MAX_BACKOFF_SECONDS;
		mcast->delay_until = jiffies + (mcast->backoff * HZ);
		/*
		 * Mark this mcast for its delay, but restart the
		 * task immediately.  The join task will make sure to
		 * clear out all entries without delays, and then
		 * schedule itself to run again when the earliest
		 * delay expires
		 */
		queue_delayed_work(priv->wq, &priv->mcast_task, 0);
	} else if (delay) {
		/*
		 * Special case of retrying after a failure to
		 * allocate the broadcast multicast group, wait
		 * 1 second and try again
		 */
		queue_delayed_work(priv->wq, &priv->mcast_task, HZ);
	} else
		queue_delayed_work(priv->wq, &priv->mcast_task, 0);
}

static void ipoib_mcast_free(struct ipoib_mcast *mcast)
{
	struct net_device *dev = mcast->dev;
	int tx_dropped = 0;

	ipoib_dbg_mcast(ipoib_priv(dev), "deleting multicast group %pI6\n",
			mcast->mcmember.mgid.raw);

	/* remove all neigh connected to this mcast */
	ipoib_del_neighs_by_gid(dev, mcast->mcmember.mgid.raw);

	if (mcast->ah)
		ipoib_put_ah(mcast->ah);

	while (!skb_queue_empty(&mcast->pkt_queue)) {
		++tx_dropped;
		dev_kfree_skb_any(skb_dequeue(&mcast->pkt_queue));
	}

	netif_tx_lock_bh(dev);
	dev->stats.tx_dropped += tx_dropped;
	netif_tx_unlock_bh(dev);

	kfree(mcast);
}

static struct ipoib_mcast *ipoib_mcast_alloc(struct net_device *dev)
{
	struct ipoib_mcast *mcast;

	mcast = kzalloc_obj(*mcast, GFP_ATOMIC);
	if (!mcast)
		return NULL;

	mcast->dev = dev;
	mcast->created = jiffies;

Annotation

Implementation Notes