drivers/greybus/operation.c

Source file repositories/reference/linux-study-clean/drivers/greybus/operation.c

File Facts

System
Linux kernel
Corpus path
drivers/greybus/operation.c
Extension
.c
Size
35835 bytes
Lines
1266
Domain
Driver Families
Bucket
drivers/greybus
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 (!ret) {
			/* Cancel request message if scheduled by timeout. */
			if (gb_operation_result(operation) == -ETIMEDOUT)
				gb_message_cancel(operation->request);
		}

		operation->callback(operation);
	}

	gb_operation_put_active(operation);
	gb_operation_put(operation);
}

static void gb_operation_timeout(struct timer_list *t)
{
	struct gb_operation *operation = timer_container_of(operation, t,
							    timer);

	if (gb_operation_result_set(operation, -ETIMEDOUT)) {
		/*
		 * A stuck request message will be cancelled from the
		 * workqueue.
		 */
		queue_work(gb_operation_completion_wq, &operation->work);
	}
}

static void gb_operation_message_init(struct gb_host_device *hd,
				      struct gb_message *message,
				      u16 operation_id,
				      size_t payload_size, u8 type)
{
	struct gb_operation_msg_hdr *header;

	header = message->buffer;

	message->header = header;
	message->payload = payload_size ? header + 1 : NULL;
	message->payload_size = payload_size;

	/*
	 * The type supplied for incoming message buffers will be
	 * GB_REQUEST_TYPE_INVALID. Such buffers will be overwritten by
	 * arriving data so there's no need to initialize the message header.
	 */
	if (type != GB_REQUEST_TYPE_INVALID) {
		u16 message_size = (u16)(sizeof(*header) + payload_size);

		/*
		 * For a request, the operation id gets filled in
		 * when the message is sent.  For a response, it
		 * will be copied from the request by the caller.
		 *
		 * The result field in a request message must be
		 * zero.  It will be set just prior to sending for
		 * a response.
		 */
		header->size = cpu_to_le16(message_size);
		header->operation_id = 0;
		header->type = type;
		header->result = 0;
	}
}

/*
 * Allocate a message to be used for an operation request or response.
 * Both types of message contain a common header.  The request message
 * for an outgoing operation is outbound, as is the response message
 * for an incoming operation.  The message header for an outbound
 * message is partially initialized here.
 *
 * The headers for inbound messages don't need to be initialized;
 * they'll be filled in by arriving data.
 *
 * Our message buffers have the following layout:
 *	message header  \_ these combined are
 *	message payload /  the message size
 */
static struct gb_message *
gb_operation_message_alloc(struct gb_host_device *hd, u8 type,
			   size_t payload_size, gfp_t gfp_flags)
{
	struct gb_message *message;
	struct gb_operation_msg_hdr *header;
	size_t message_size = payload_size + sizeof(*header);

	if (message_size > hd->buffer_size_max) {
		dev_warn(&hd->dev, "requested message size too big (%zu > %zu)\n",
			 message_size, hd->buffer_size_max);
		return NULL;

Annotation

Implementation Notes