drivers/infiniband/core/ib_core_uverbs.c

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

File Facts

System
Linux kernel
Corpus path
drivers/infiniband/core/ib_core_uverbs.c
Extension
.c
Size
22354 bytes
Lines
759
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 (err == -E2BIG) {
			ibdev_dbg(
				rdma_udata_to_dev(udata),
				"System call driver input udata not zero from %zu -> %zu for ioctl %ps called by %pSR\n",
				minimum_size, udata->inlen,
				uverbs_get_handler_fn(udata),
				__builtin_return_address(0));
			return -EOPNOTSUPP;
		}
		ibdev_dbg(
			rdma_udata_to_dev(udata),
			"System call driver input udata EFAULT for ioctl %ps called by %pSR\n",
			uverbs_get_handler_fn(udata),
			__builtin_return_address(0));
		return err;
	}
	return 0;
}
EXPORT_SYMBOL(_ib_copy_validate_udata_in);

int _ib_copy_validate_udata_cm_fail(struct ib_udata *udata, u64 req_cm,
				    u64 valid_cm)
{
	ibdev_dbg(
		rdma_udata_to_dev(udata),
		"System call driver input udata has unsupported comp_mask %llx & ~%llx = %llx for ioctl %ps called by %pSR\n",
		req_cm, valid_cm, req_cm & ~valid_cm,
		uverbs_get_handler_fn(udata), __builtin_return_address(0));
	return -EOPNOTSUPP;
}
EXPORT_SYMBOL(_ib_copy_validate_udata_cm_fail);

int _ib_respond_udata(struct ib_udata *udata, const void *src, size_t len)
{
	size_t copy_len;

	/* 0 length copy_len is a NOP for copy_to_user() and doesn't fail. */
	copy_len = min(len, udata->outlen);
	if (copy_to_user(udata->outbuf, src, copy_len))
		goto err_fault;
	if (copy_len < udata->outlen) {
		if (clear_user(udata->outbuf + copy_len,
			       udata->outlen - copy_len))
			goto err_fault;
	}
	return 0;
err_fault:
	ibdev_dbg(
		rdma_udata_to_dev(udata),
		"System call driver out udata has EFAULT (%zu into %zu) for ioctl %ps called by %pSR\n",
		len, udata->outlen, uverbs_get_handler_fn(udata),
		__builtin_return_address(0));
	return -EFAULT;
}
EXPORT_SYMBOL(_ib_respond_udata);

/*
 * Must be called with the ufile->device->disassociate_srcu held, and the lock
 * must be held until use of the ucontext is finished.
 */
struct ib_ucontext *ib_uverbs_get_ucontext_file(struct ib_uverbs_file *ufile)
{
	/*
	 * We do not hold the hw_destroy_rwsem lock for this flow, instead
	 * srcu is used. It does not matter if someone races this with
	 * get_context, we get NULL or valid ucontext.
	 */
	struct ib_ucontext *ucontext = smp_load_acquire(&ufile->ucontext);

	if (!srcu_dereference(ufile->device->ib_dev,
			      &ufile->device->disassociate_srcu))
		return ERR_PTR(-EIO);

	if (!ucontext)
		return ERR_PTR(-EINVAL);

	return ucontext;
}
EXPORT_SYMBOL(ib_uverbs_get_ucontext_file);

int uverbs_destroy_def_handler(struct uverbs_attr_bundle *attrs)
{
	return 0;
}
EXPORT_SYMBOL(uverbs_destroy_def_handler);

/*
 * When calling a destroy function during an error unwind we need to pass in
 * the udata that is sanitized of all user arguments. Ie from the driver
 * perspective it looks like no udata was passed.

Annotation

Implementation Notes