drivers/dma/idxd/init.c

Source file repositories/reference/linux-study-clean/drivers/dma/idxd/init.c

File Facts

System
Linux kernel
Corpus path
drivers/dma/idxd/init.c
Extension
.c
Size
35515 bytes
Lines
1395
Domain
Driver Families
Bucket
drivers/dma
Inferred role
Driver Families: operation-table or driver-model contract
Status
pattern 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

static int idxd_bind(struct device_driver *drv, const char *buf)
{
	const struct bus_type *bus = drv->bus;
	struct device *dev;
	int err = -ENODEV;

	dev = bus_find_device_by_name(bus, NULL, buf);
	if (dev)
		err = device_driver_attach(drv, dev);

	put_device(dev);

	return err;
}

/*
 * Detach IDXD device from driver.
 */
static void idxd_unbind(struct device_driver *drv, const char *buf)
{
	const struct bus_type *bus = drv->bus;
	struct device *dev;

	dev = bus_find_device_by_name(bus, NULL, buf);
	if (dev && dev->driver == drv)
		device_release_driver(dev);

	put_device(dev);
}

#define idxd_free_saved_configs(saved_configs, count)	\
	do {						\
		int i;					\
							\
		for (i = 0; i < (count); i++)		\
			kfree(saved_configs[i]);	\
	} while (0)

static void idxd_free_saved(struct idxd_group **saved_groups,
			    struct idxd_engine **saved_engines,
			    struct idxd_wq **saved_wqs,
			    struct idxd_device *idxd)
{
	if (saved_groups)
		idxd_free_saved_configs(saved_groups, idxd->max_groups);
	if (saved_engines)
		idxd_free_saved_configs(saved_engines, idxd->max_engines);
	if (saved_wqs)
		idxd_free_saved_configs(saved_wqs, idxd->max_wqs);
}

/*
 * Save IDXD device configurations including engines, groups, wqs etc.
 * The saved configurations can be restored when needed.
 */
static int idxd_device_config_save(struct idxd_device *idxd,
				   struct idxd_saved_states *idxd_saved)
{
	struct device *dev = &idxd->pdev->dev;
	int i;

	memcpy(&idxd_saved->saved_idxd, idxd, sizeof(*idxd));

	if (idxd->evl) {
		memcpy(&idxd_saved->saved_evl, idxd->evl,
		       sizeof(struct idxd_evl));
	}

	struct idxd_group **saved_groups __free(kfree) =
			kcalloc_node(idxd->max_groups,
				     sizeof(struct idxd_group *),
				     GFP_KERNEL, dev_to_node(dev));
	if (!saved_groups)
		return -ENOMEM;

	for (i = 0; i < idxd->max_groups; i++) {
		struct idxd_group *saved_group __free(kfree) =
			kzalloc_node(sizeof(*saved_group), GFP_KERNEL,
				     dev_to_node(dev));

		if (!saved_group) {
			/* Free saved groups */
			idxd_free_saved(saved_groups, NULL, NULL, idxd);

			return -ENOMEM;
		}

		memcpy(saved_group, idxd->groups[i], sizeof(*saved_group));
		saved_groups[i] = no_free_ptr(saved_group);
	}

Annotation

Implementation Notes