summaryrefslogtreecommitdiff
path: root/drivers/staging/greybus/operation.c
diff options
context:
space:
mode:
authorJohan Hovold <johan@hovoldconsulting.com>2016-04-29 17:08:32 +0200
committerGreg Kroah-Hartman <gregkh@google.com>2016-04-29 14:27:05 -0700
commit3e2ee2c1e50541b611087be9e2e55b8f77477cf6 (patch)
tree4e6ce843e39a24a3bb3da763533d57a9be8b950d /drivers/staging/greybus/operation.c
parent613c15e86b7ac30cb3e3f16e13ee367845a941b2 (diff)
greybus: operation: add support for initiating unidirectional operations
Add support for initiating unidirectional operations, that is, sending requests that do not require responses. Note that we already handle incoming unidirectional operations. Signed-off-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
Diffstat (limited to 'drivers/staging/greybus/operation.c')
-rw-r--r--drivers/staging/greybus/operation.c38
1 files changed, 27 insertions, 11 deletions
diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c
index bb8995583f6a..9fb7993a86e8 100644
--- a/drivers/staging/greybus/operation.c
+++ b/drivers/staging/greybus/operation.c
@@ -635,9 +635,10 @@ static void gb_operation_sync_callback(struct gb_operation *operation)
*
* The caller has filled in any payload so the request message is ready to go.
* The callback function supplied will be called when the response message has
- * arrived, or the operation is cancelled, indicating that the operation is
- * complete. The callback function can fetch the result of the operation using
- * gb_operation_result() if desired.
+ * arrived, a unidirectional request has been sent, or the operation is
+ * cancelled, indicating that the operation is complete. The callback function
+ * can fetch the result of the operation using gb_operation_result() if
+ * desired.
*
* Return: 0 if the request was successfully queued in the host-driver queues,
* or a negative errno.
@@ -653,6 +654,7 @@ int gb_operation_request_send(struct gb_operation *operation,
if (!callback)
return -EINVAL;
+
/*
* Record the callback function, which is executed in
* non-atomic (workqueue) context when the final result
@@ -662,10 +664,15 @@ int gb_operation_request_send(struct gb_operation *operation,
/*
* Assign the operation's id, and store it in the request header.
- * Zero is a reserved operation id.
+ * Zero is a reserved operation id for unidirectional operations.
*/
- cycle = (unsigned int)atomic_inc_return(&connection->op_cycle);
- operation->id = (u16)(cycle % U16_MAX + 1);
+ if (gb_operation_is_unidirectional(operation)) {
+ operation->id = 0;
+ } else {
+ cycle = (unsigned int)atomic_inc_return(&connection->op_cycle);
+ operation->id = (u16)(cycle % U16_MAX + 1);
+ }
+
header = operation->request->header;
header->operation_id = cpu_to_le16(operation->id);
@@ -799,10 +806,11 @@ void greybus_message_sent(struct gb_host_device *hd,
* reference to the operation. If an error occurred, report
* it.
*
- * For requests, if there's no error, there's nothing more
- * to do until the response arrives. If an error occurred
- * attempting to send it, record that as the result of
- * the operation and schedule its completion.
+ * For requests, if there's no error and the operation in not
+ * unidirectional, there's nothing more to do until the response
+ * arrives. If an error occurred attempting to send it, or if the
+ * operation is unidrectional, record the result of the operation and
+ * schedule its completion.
*/
if (message == operation->response) {
if (status) {
@@ -810,9 +818,10 @@ void greybus_message_sent(struct gb_host_device *hd,
"%s: error sending response 0x%02x: %d\n",
connection->name, operation->type, status);
}
+
gb_operation_put_active(operation);
gb_operation_put(operation);
- } else if (status) {
+ } else if (status || gb_operation_is_unidirectional(operation)) {
if (gb_operation_result_set(operation, status)) {
queue_work(gb_operation_completion_wq,
&operation->work);
@@ -876,6 +885,13 @@ static void gb_connection_recv_response(struct gb_connection *connection,
int errno = gb_operation_status_map(result);
size_t message_size;
+ if (!operation_id) {
+ dev_err(&connection->hd->dev,
+ "%s: invalid response id 0 received\n",
+ connection->name);
+ return;
+ }
+
operation = gb_operation_find_outgoing(connection, operation_id);
if (!operation) {
dev_err(&connection->hd->dev,