drivers/infiniband/ulp/srp/ib_srp.c

Source file repositories/reference/linux-study-clean/drivers/infiniband/ulp/srp/ib_srp.c

File Facts

System
Linux kernel
Corpus path
drivers/infiniband/ulp/srp/ib_srp.c
Extension
.c
Size
112242 bytes
Lines
4240
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

if (device_add(&host->dev))
		goto put_host;

	return host;

put_host:
	put_device(&host->dev);
	return NULL;
}

static void srp_rename_dev(struct ib_device *device, void *client_data)
{
	struct srp_device *srp_dev = client_data;
	struct srp_host *host, *tmp_host;

	list_for_each_entry_safe(host, tmp_host, &srp_dev->dev_list, list) {
		char name[IB_DEVICE_NAME_MAX + 8];

		snprintf(name, sizeof(name), "srp-%s-%u",
			 dev_name(&device->dev), host->port);
		device_rename(&host->dev, name);
	}
}

static int srp_add_one(struct ib_device *device)
{
	struct srp_device *srp_dev;
	struct ib_device_attr *attr = &device->attrs;
	struct srp_host *host;
	int mr_page_shift;
	u32 p;
	u64 max_pages_per_mr;
	unsigned int flags = 0;

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

	/*
	 * Use the smallest page size supported by the HCA, down to a
	 * minimum of 4096 bytes. We're unlikely to build large sglists
	 * out of smaller entries.
	 */
	mr_page_shift		= max(12, ffs(attr->page_size_cap) - 1);
	srp_dev->mr_page_size	= 1 << mr_page_shift;
	srp_dev->mr_page_mask	= ~((u64) srp_dev->mr_page_size - 1);
	max_pages_per_mr	= attr->max_mr_size;
	do_div(max_pages_per_mr, srp_dev->mr_page_size);
	pr_debug("%s: %llu / %u = %llu <> %u\n", __func__,
		 attr->max_mr_size, srp_dev->mr_page_size,
		 max_pages_per_mr, SRP_MAX_PAGES_PER_MR);
	srp_dev->max_pages_per_mr = min_t(u64, SRP_MAX_PAGES_PER_MR,
					  max_pages_per_mr);

	srp_dev->has_fr = (attr->device_cap_flags &
			   IB_DEVICE_MEM_MGT_EXTENSIONS);
	if (!never_register && !srp_dev->has_fr)
		dev_warn(&device->dev, "FR is not supported\n");
	else if (!never_register &&
		 attr->max_mr_size >= 2 * srp_dev->mr_page_size)
		srp_dev->use_fast_reg = srp_dev->has_fr;

	if (never_register || !register_always || !srp_dev->has_fr)
		flags |= IB_PD_UNSAFE_GLOBAL_RKEY;

	if (srp_dev->use_fast_reg) {
		srp_dev->max_pages_per_mr =
			min_t(u32, srp_dev->max_pages_per_mr,
			      attr->max_fast_reg_page_list_len);
	}
	srp_dev->mr_max_size	= srp_dev->mr_page_size *
				   srp_dev->max_pages_per_mr;
	pr_debug("%s: mr_page_shift = %d, device->max_mr_size = %#llx, device->max_fast_reg_page_list_len = %u, max_pages_per_mr = %d, mr_max_size = %#x\n",
		 dev_name(&device->dev), mr_page_shift, attr->max_mr_size,
		 attr->max_fast_reg_page_list_len,
		 srp_dev->max_pages_per_mr, srp_dev->mr_max_size);

	INIT_LIST_HEAD(&srp_dev->dev_list);

	srp_dev->dev = device;
	srp_dev->pd  = ib_alloc_pd(device, flags);
	if (IS_ERR(srp_dev->pd)) {
		int ret = PTR_ERR(srp_dev->pd);

		kfree(srp_dev);
		return ret;
	}

	if (flags & IB_PD_UNSAFE_GLOBAL_RKEY) {
		srp_dev->global_rkey = srp_dev->pd->unsafe_global_rkey;

Annotation

Implementation Notes