net/smc/smc_ism.c

Source file repositories/reference/linux-study-clean/net/smc/smc_ism.c

File Facts

System
Linux kernel
Corpus path
net/smc/smc_ism.c
Extension
.c
Size
16306 bytes
Lines
645
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

struct smc_ism_event_work {
	struct work_struct work;
	struct smcd_dev *smcd;
	struct dibs_event event;
};

#define ISM_EVENT_REQUEST		0x0001
#define ISM_EVENT_RESPONSE		0x0002
#define ISM_EVENT_REQUEST_IR		0x00000001
#define ISM_EVENT_CODE_SHUTDOWN		0x80
#define ISM_EVENT_CODE_TESTLINK		0x83

union smcd_sw_event_info {
	u64	info;
	struct {
		u8		uid[SMC_LGR_ID_SIZE];
		unsigned short	vlan_id;
		u16		code;
	};
};

static void smcd_handle_sw_event(struct smc_ism_event_work *wrk)
{
	struct dibs_dev *dibs = wrk->smcd->dibs;
	union smcd_sw_event_info ev_info;
	struct smcd_gid peer_gid;
	uuid_t ism_rgid;

	copy_to_smcdgid(&peer_gid, &wrk->event.gid);
	ev_info.info = wrk->event.data;
	switch (wrk->event.subtype) {
	case ISM_EVENT_CODE_SHUTDOWN:	/* Peer shut down DMBs */
		smc_smcd_terminate(wrk->smcd, &peer_gid, ev_info.vlan_id);
		break;
	case ISM_EVENT_CODE_TESTLINK:	/* Activity timer */
		if (ev_info.code == ISM_EVENT_REQUEST &&
		    dibs->ops->signal_event) {
			ev_info.code = ISM_EVENT_RESPONSE;
			copy_to_dibsgid(&ism_rgid, &peer_gid);
			dibs->ops->signal_event(dibs, &ism_rgid,
					       ISM_EVENT_REQUEST_IR,
					       ISM_EVENT_CODE_TESTLINK,
					       ev_info.info);
		}
		break;
	}
}

/* worker for SMC-D events */
static void smc_ism_event_work(struct work_struct *work)
{
	struct smc_ism_event_work *wrk =
		container_of(work, struct smc_ism_event_work, work);
	struct smcd_gid smcd_gid;

	copy_to_smcdgid(&smcd_gid, &wrk->event.gid);

	switch (wrk->event.type) {
	case DIBS_DEV_EVENT: /* GID event, token is peer GID */
		smc_smcd_terminate(wrk->smcd, &smcd_gid, VLAN_VID_MASK);
		break;
	case DIBS_BUF_EVENT:
		break;
	case DIBS_SW_EVENT: /* Software defined event */
		smcd_handle_sw_event(wrk);
		break;
	}
	kfree(wrk);
}

static struct smcd_dev *smcd_alloc_dev(const char *name, int max_dmbs)
{
	struct smcd_dev *smcd;

	smcd = kzalloc_flex(*smcd, conn, max_dmbs);
	if (!smcd)
		return NULL;

	smcd->event_wq = alloc_ordered_workqueue("ism_evt_wq-%s)",
						 WQ_MEM_RECLAIM, name);
	if (!smcd->event_wq)
		goto free_smcd;

	spin_lock_init(&smcd->lock);
	spin_lock_init(&smcd->lgr_lock);
	INIT_LIST_HEAD(&smcd->vlan);
	INIT_LIST_HEAD(&smcd->lgr_list);
	init_waitqueue_head(&smcd->lgrs_deleted);
	return smcd;

Annotation

Implementation Notes