drivers/gpio/gpio-virtuser.c

Source file repositories/reference/linux-study-clean/drivers/gpio/gpio-virtuser.c

File Facts

System
Linux kernel
Corpus path
drivers/gpio/gpio-virtuser.c
Extension
.c
Size
44599 bytes
Lines
1813
Domain
Driver Families
Bucket
drivers/gpio
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

const struct file_operations *fops;
};

struct gpio_virtuser_irq_work_context {
	struct irq_work work;
	struct completion work_completion;
	union {
		struct {
			struct gpio_desc *desc;
			int dir;
			int val;
			int ret;
		};
		struct {
			struct gpio_descs *descs;
			unsigned long *values;
		};
	};
};

static struct gpio_virtuser_irq_work_context *
to_gpio_virtuser_irq_work_context(struct irq_work *work)
{
	return container_of(work, struct gpio_virtuser_irq_work_context, work);
}

static void
gpio_virtuser_init_irq_work_context(struct gpio_virtuser_irq_work_context *ctx)
{
	memset(ctx, 0, sizeof(*ctx));
	init_completion(&ctx->work_completion);
}

static void
gpio_virtuser_irq_work_queue_sync(struct gpio_virtuser_irq_work_context *ctx)
{
	irq_work_queue(&ctx->work);
	wait_for_completion(&ctx->work_completion);
}

static void gpio_virtuser_dbgfs_emit_value_array(char *buf,
						 unsigned long *values,
						 size_t num_values)
{
	size_t i;

	for (i = 0; i < num_values; i++)
		buf[i] = test_bit(i, values) ? '1' : '0';

	buf[i++] = '\n';
}

static void gpio_virtuser_get_value_array_atomic(struct irq_work *work)
{
	struct gpio_virtuser_irq_work_context *ctx =
				to_gpio_virtuser_irq_work_context(work);
	struct gpio_descs *descs = ctx->descs;

	ctx->ret = gpiod_get_array_value(descs->ndescs, descs->desc,
					 descs->info, ctx->values);
	complete(&ctx->work_completion);
}

static int gpio_virtuser_get_array_value(struct gpio_descs *descs,
					 unsigned long *values, bool atomic)
{
	struct gpio_virtuser_irq_work_context ctx;

	if (!atomic)
		return gpiod_get_array_value_cansleep(descs->ndescs,
						      descs->desc,
						      descs->info, values);

	gpio_virtuser_init_irq_work_context(&ctx);
	ctx.work = IRQ_WORK_INIT_HARD(gpio_virtuser_get_value_array_atomic);
	ctx.descs = descs;
	ctx.values = values;

	gpio_virtuser_irq_work_queue_sync(&ctx);

	return ctx.ret;
}

static ssize_t gpio_virtuser_value_array_do_read(struct file *file,
						 char __user *user_buf,
						 size_t size, loff_t *ppos,
						 bool atomic)
{
	struct gpio_virtuser_line_data *data = file->private_data;
	struct gpio_descs *descs = data->ad.descs;

Annotation

Implementation Notes