net/ncsi/ncsi-aen.c

Source file repositories/reference/linux-study-clean/net/ncsi/ncsi-aen.c

File Facts

System
Linux kernel
Corpus path
net/ncsi/ncsi-aen.c
Extension
.c
Size
6315 bytes
Lines
248
Domain
Networking Core
Bucket
Sockets, Protocols, Packet Path, And Network Policy
Inferred role
Networking Core: implementation source
Status
source implementation candidate

Why This File Exists

Networking stack implementation surface: socket APIs, protocol dispatch, packet flow, routing, filtering, and network namespaces.

Dependency Surface

Detected Declarations

Annotated Snippet

if (had_link) {
			ndp->flags |= NCSI_DEV_RESHUFFLE;
			ncsi_stop_channel_monitor(nc);
			spin_lock_irqsave(&ndp->lock, flags);
			list_add_tail_rcu(&nc->link, &ndp->channel_queue);
			spin_unlock_irqrestore(&ndp->lock, flags);
			return ncsi_process_next_channel(ndp);
		}
		/* Configured channel came up */
		return 0;
	}

	if (had_link) {
		ncm = &nc->modes[NCSI_MODE_TX_ENABLE];
		if (ncsi_channel_is_last(ndp, nc)) {
			/* No channels left, reconfigure */
			return ncsi_reset_dev(&ndp->ndev);
		} else if (ncm->enable) {
			/* Need to failover Tx channel */
			ncsi_update_tx_channel(ndp, nc->package, nc, NULL);
		}
	} else if (has_link && nc->package->preferred_channel == nc) {
		/* Return Tx to preferred channel */
		ncsi_update_tx_channel(ndp, nc->package, NULL, nc);
	} else if (has_link) {
		NCSI_FOR_EACH_PACKAGE(ndp, np) {
			NCSI_FOR_EACH_CHANNEL(np, tmp) {
				/* Enable Tx on this channel if the current Tx
				 * channel is down.
				 */
				ncm = &tmp->modes[NCSI_MODE_TX_ENABLE];
				if (ncm->enable &&
				    !ncsi_channel_has_link(tmp)) {
					ncsi_update_tx_channel(ndp, nc->package,
							       tmp, nc);
					break;
				}
			}
		}
	}

	/* Leave configured channels active in a multi-channel scenario so
	 * AEN events are still received.
	 */
	return 0;
}

static int ncsi_aen_handler_cr(struct ncsi_dev_priv *ndp,
			       struct ncsi_aen_pkt_hdr *h)
{
	struct ncsi_channel *nc;
	unsigned long flags;

	/* Find the NCSI channel */
	ncsi_find_package_and_channel(ndp, h->common.channel, NULL, &nc);
	if (!nc)
		return -ENODEV;

	spin_lock_irqsave(&nc->lock, flags);
	if (!list_empty(&nc->link) ||
	    nc->state != NCSI_CHANNEL_ACTIVE) {
		spin_unlock_irqrestore(&nc->lock, flags);
		return 0;
	}
	spin_unlock_irqrestore(&nc->lock, flags);

	ncsi_stop_channel_monitor(nc);
	spin_lock_irqsave(&nc->lock, flags);
	nc->state = NCSI_CHANNEL_INVISIBLE;
	spin_unlock_irqrestore(&nc->lock, flags);

	spin_lock_irqsave(&ndp->lock, flags);
	nc->state = NCSI_CHANNEL_INACTIVE;
	list_add_tail_rcu(&nc->link, &ndp->channel_queue);
	spin_unlock_irqrestore(&ndp->lock, flags);
	nc->modes[NCSI_MODE_TX_ENABLE].enable = 0;

	return ncsi_process_next_channel(ndp);
}

static int ncsi_aen_handler_hncdsc(struct ncsi_dev_priv *ndp,
				   struct ncsi_aen_pkt_hdr *h)
{
	struct ncsi_channel *nc;
	struct ncsi_channel_mode *ncm;
	struct ncsi_aen_hncdsc_pkt *hncdsc;
	unsigned long flags;

	/* Find the NCSI channel */
	ncsi_find_package_and_channel(ndp, h->common.channel, NULL, &nc);

Annotation

Implementation Notes