drivers/infiniband/core/cma.c

Source file repositories/reference/linux-study-clean/drivers/infiniband/core/cma.c

File Facts

System
Linux kernel
Corpus path
drivers/infiniband/core/cma.c
Extension
.c
Size
151564 bytes
Lines
5676
Domain
Driver Families
Bucket
drivers/infiniband
Inferred role
Driver Families: exported/initcall integration point
Status
integration 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

module_init(cma_init);
module_exit(cma_cleanup);

static void cma_query_ib_service_handler(int status,
					 struct sa_service_rec *recs,
					 unsigned int num_recs, void *context)
{
	struct cma_work *work = context;
	struct rdma_id_private *id_priv = work->id;
	struct sockaddr_ib *addr;

	if (status)
		goto fail;

	if (!num_recs) {
		status = -ENOENT;
		goto fail;
	}

	if (id_priv->id.route.service_recs) {
		status = -EALREADY;
		goto fail;
	}

	id_priv->id.route.service_recs =
		kmalloc_objs(*recs, num_recs);
	if (!id_priv->id.route.service_recs) {
		status = -ENOMEM;
		goto fail;
	}

	id_priv->id.route.num_service_recs = num_recs;
	memcpy(id_priv->id.route.service_recs, recs, sizeof(*recs) * num_recs);

	addr = (struct sockaddr_ib *)&id_priv->id.route.addr.dst_addr;
	addr->sib_family = AF_IB;
	addr->sib_addr = *(struct ib_addr *)&recs->gid;
	addr->sib_pkey = recs->pkey;
	addr->sib_sid = recs->id;
	rdma_addr_set_dgid(&id_priv->id.route.addr.dev_addr,
			   (union ib_gid *)&addr->sib_addr);
	ib_addr_set_pkey(&id_priv->id.route.addr.dev_addr,
			 ntohs(addr->sib_pkey));

	queue_work(cma_wq, &work->work);
	return;

fail:
	work->old_state = RDMA_CM_ADDRINFO_QUERY;
	work->new_state = RDMA_CM_ADDR_BOUND;
	work->event.event = RDMA_CM_EVENT_ADDRINFO_ERROR;
	work->event.status = status;
	pr_debug_ratelimited(
		"RDMA CM: SERVICE_ERROR: failed to query service record. status %d\n",
		status);
	queue_work(cma_wq, &work->work);
}

static int cma_resolve_ib_service(struct rdma_id_private *id_priv,
				  struct rdma_ucm_ib_service *ibs)
{
	struct sa_service_rec sr = {};
	ib_sa_comp_mask mask = 0;
	struct cma_work *work;

	work = kzalloc_obj(*work);
	if (!work)
		return -ENOMEM;

	cma_id_get(id_priv);

	work->id = id_priv;
	INIT_WORK(&work->work, cma_work_handler);
	work->old_state = RDMA_CM_ADDRINFO_QUERY;
	work->new_state = RDMA_CM_ADDRINFO_RESOLVED;
	work->event.event = RDMA_CM_EVENT_ADDRINFO_RESOLVED;

	if (ibs->flags & RDMA_USER_CM_IB_SERVICE_FLAG_ID) {
		sr.id = cpu_to_be64(ibs->service_id);
		mask |= IB_SA_SERVICE_REC_SERVICE_ID;
	}
	if (ibs->flags & RDMA_USER_CM_IB_SERVICE_FLAG_NAME) {
		strscpy(sr.name, ibs->service_name, sizeof(sr.name));
		mask |= IB_SA_SERVICE_REC_SERVICE_NAME;
	}

	id_priv->query_id = ib_sa_service_rec_get(&sa_client,
						  id_priv->id.device,
						  id_priv->id.port_num,
						  &sr, mask,

Annotation

Implementation Notes