4 * Copyright 2014 Google Inc.
6 * Released under the GPLv2 only.
9 #include <linux/kernel.h>
10 #include <linux/slab.h>
11 #include <linux/module.h>
12 #include <linux/workqueue.h>
17 * All operation messages (both requests and responses) begin with
18 * a common header that encodes the size of the data (header
19 * included). This header also contains a unique identifier, which
20 * is used to keep track of in-flight operations. Finally, the
21 * header contains a operation type field, whose interpretation is
22 * dependent on what type of device lies on the other end of the
23 * connection. Response messages are distinguished from request
24 * messages by setting the high bit (0x80) in the operation type
27 * The wire format for all numeric fields in the header is little
28 * endian. Any operation-specific data begins immediately after the
29 * header, and is 64-bit aligned.
31 struct gb_operation_msg_hdr {
32 __le16 size; /* Size in bytes of header + payload */
33 __le16 id; /* Operation unique id */
34 __u8 type; /* E.g GB_I2C_TYPE_* or GB_GPIO_TYPE_* */
35 /* 3 bytes pad, must be zero (ignore when read) */
36 } __aligned(sizeof(u64));
38 /* XXX Could be per-host device, per-module, or even per-connection */
39 static DEFINE_SPINLOCK(gb_operations_lock);
42 * An operations's response message has arrived. If no callback was
43 * supplied it was submitted for asynchronous completion, so we notify
44 * any waiters. Otherwise we assume calling the completion is enough
45 * and nobody else will be waiting.
47 void gb_operation_complete(struct gb_operation *operation)
49 if (operation->callback)
50 operation->callback(operation);
52 complete_all(&operation->completion);
56 * Wait for a submitted operatnoi to complete */
57 int gb_operation_wait(struct gb_operation *operation)
61 ret = wait_for_completion_interruptible(&operation->completion);
62 /* If interrupted, cancel the in-flight buffer */
64 ret = greybus_kill_gbuf(operation->gbuf);
70 * Submit an outbound operation. The caller has filled in any
71 * payload so the request message is ready to go. If non-null,
72 * the callback function supplied will be called when the response
73 * message has arrived indicating the operation is complete. A null
74 * callback function is used for a synchronous request; return from
75 * this function won't occur until the operation is complete (or an
78 int gb_operation_submit(struct gb_operation *operation,
79 gb_operation_callback callback)
84 * gfp is probably GFP_ATOMIC but really I think
85 * the gfp mask should go away.
87 operation->callback = callback;
88 ret = greybus_submit_gbuf(operation->gbuf, GFP_KERNEL);
92 ret = gb_operation_wait(operation);
98 * Called when a greybus request message has actually been sent.
100 static void gbuf_out_callback(struct gbuf *gbuf)
102 /* Record it's been submitted; need response now */
106 * Create a Greybus operation having a buffer big enough for an
107 * outgoing payload of the given size to be sent over the given
110 * Returns a pointer to the new operation or a null pointer if a
111 * failure occurs due to memory exhaustion.
113 struct gb_operation *gb_operation_create(struct gb_connection *connection,
114 size_t size, u8 type)
116 struct gb_operation *operation;
117 struct gb_operation_msg_hdr *header;
120 /* XXX Use a slab cache */
121 operation = kzalloc(sizeof(*operation), GFP_KERNEL);
125 /* Our buffer holds a header in addition to the requested payload */
126 size += sizeof(*header);
127 gbuf = greybus_alloc_gbuf(connection->interface->gmod,
128 connection->hd_cport_id,
129 gbuf_out_callback, size,
130 GFP_KERNEL, operation);
135 gbuf->actual_length = size; /* Record what we'll use */
137 operation->connection = connection; /* XXX refcount? */
139 /* Fill in the header structure and payload pointer */
140 operation->gbuf = gbuf;
141 header = (struct gb_operation_msg_hdr *)&gbuf->transfer_buffer;
142 header->size = cpu_to_le16(size);
143 header->id = 0; /* Filled in when submitted */
145 operation->payload = (char *)header + sizeof(*header);
147 operation->callback = NULL; /* set at submit time */
148 init_completion(&operation->completion);
150 spin_lock_irq(&gb_operations_lock);
151 list_add_tail(&operation->links, &connection->operations);
152 spin_unlock_irq(&gb_operations_lock);
158 * Destroy a previously created operation.
160 void gb_operation_destroy(struct gb_operation *operation)
162 if (WARN_ON(!operation))
165 /* XXX Make sure it's not in flight */
166 spin_lock_irq(&gb_operations_lock);
167 list_del(&operation->links);
168 spin_unlock_irq(&gb_operations_lock);
170 greybus_free_gbuf(operation->gbuf);