drivers/spi/spi-offload.c

Source file repositories/reference/linux-study-clean/drivers/spi/spi-offload.c

File Facts

System
Linux kernel
Corpus path
drivers/spi/spi-offload.c
Extension
.c
Size
12248 bytes
Lines
466
Domain
Driver Families
Bucket
drivers/spi
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

struct spi_controller_and_offload {
	struct spi_controller *controller;
	struct spi_offload *offload;
};

struct spi_offload_trigger {
	struct list_head list;
	struct kref ref;
	struct fwnode_handle *fwnode;
	/* synchronizes calling ops and driver registration */
	struct mutex lock;
	/*
	 * If the provider goes away while the consumer still has a reference,
	 * ops and priv will be set to NULL and all calls will fail with -ENODEV.
	 */
	const struct spi_offload_trigger_ops *ops;
	void *priv;
};

static LIST_HEAD(spi_offload_triggers);
static DEFINE_MUTEX(spi_offload_triggers_lock);

/**
 * devm_spi_offload_alloc() - Allocate offload instance
 * @dev: Device for devm purposes and assigned to &struct spi_offload.provider_dev
 * @priv_size: Size of private data to allocate
 *
 * Offload providers should use this to allocate offload instances.
 *
 * Return: Pointer to new offload instance or error on failure.
 */
struct spi_offload *devm_spi_offload_alloc(struct device *dev,
					   size_t priv_size)
{
	struct spi_offload *offload;
	void *priv;

	offload = devm_kzalloc(dev, sizeof(*offload), GFP_KERNEL);
	if (!offload)
		return ERR_PTR(-ENOMEM);

	priv = devm_kzalloc(dev, priv_size, GFP_KERNEL);
	if (!priv)
		return ERR_PTR(-ENOMEM);

	offload->provider_dev = dev;
	offload->priv = priv;

	return offload;
}
EXPORT_SYMBOL_GPL(devm_spi_offload_alloc);

static void spi_offload_put(void *data)
{
	struct spi_controller_and_offload *resource = data;

	resource->controller->put_offload(resource->offload);
	kfree(resource);
}

/**
 * devm_spi_offload_get() - Get an offload instance
 * @dev: Device for devm purposes
 * @spi: SPI device to use for the transfers
 * @config: Offload configuration
 *
 * Peripheral drivers call this function to get an offload instance that meets
 * the requirements specified in @config. If no suitable offload instance is
 * available, -ENODEV is returned.
 *
 * Return: Offload instance or error on failure.
 */
struct spi_offload *devm_spi_offload_get(struct device *dev,
					 struct spi_device *spi,
					 const struct spi_offload_config *config)
{
	struct spi_controller_and_offload *resource;
	struct spi_offload *offload;
	int ret;

	if (!spi || !config)
		return ERR_PTR(-EINVAL);

	if (!spi->controller->get_offload)
		return ERR_PTR(-ENODEV);

	resource = kzalloc_obj(*resource);
	if (!resource)
		return ERR_PTR(-ENOMEM);

Annotation

Implementation Notes