summaryrefslogtreecommitdiffstats
path: root/drivers/staging/greybus/operation.c
diff options
context:
space:
mode:
authorAlex Elder2014-11-22 02:29:12 +0100
committerGreg Kroah-Hartman2014-11-22 04:31:13 +0100
commit23383defa8395eb34d02dd4d4fc1d95e95c5603d (patch)
tree6455d7911736f59729ae75e5f541a8a39413bb84 /drivers/staging/greybus/operation.c
parentgreybus: Random spell fixes (diff)
downloadkernel-qcow2-linux-23383defa8395eb34d02dd4d4fc1d95e95c5603d.tar.gz
kernel-qcow2-linux-23383defa8395eb34d02dd4d4fc1d95e95c5603d.tar.xz
kernel-qcow2-linux-23383defa8395eb34d02dd4d4fc1d95e95c5603d.zip
greybus: use errno for operation result
An in-core operation structure tracks the progress of an operation. Currently it holds a result field that was intended to take the status value that arrives in an operation response message header. But operations can fail for reasons other than that, and it's inconvenient to try to represent those using the operation status codes. So change the operation->result field to be an int, and switch to storing negative errno values in it. Rename it "errno" to make it obvious how to interpret the value. This patch makes another change, which simplifies the protocol drivers a lot. It's being done as part of this patch because it affects all the same code as the above change does. If desired I can split this into two separate patches. If a caller makes a synchronous gb_operation_request_send() request (i.e., no callback function is supplied), and the operation request and response messages were transferred successfully, have gb_operation_request_send() return the result of the request (i.e., operation->errno). This allows the caller (or more generally, any caller of gb_request_wait() to avoid having to look at this field for every successful send. Any caller that does an asynchronous request will of course need to look at request->errno in the callback function to see the result of the operation. Signed-off-by: Alex Elder <elder@linaro.org> Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
Diffstat (limited to 'drivers/staging/greybus/operation.c')
-rw-r--r--drivers/staging/greybus/operation.c29
1 files changed, 15 insertions, 14 deletions
diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c
index 442046562bfb..5ab1c47f5521 100644
--- a/drivers/staging/greybus/operation.c
+++ b/drivers/staging/greybus/operation.c
@@ -159,7 +159,11 @@ static void gb_operation_complete(struct gb_operation *operation)
complete_all(&operation->completion);
}
-/* Wait for a submitted operation to complete */
+/*
+ * Wait for a submitted operation to complete. Returns -RESTARTSYS
+ * if the wait was interrupted. Otherwise returns the result of the
+ * operation.
+ */
int gb_operation_wait(struct gb_operation *operation)
{
int ret;
@@ -168,6 +172,8 @@ int gb_operation_wait(struct gb_operation *operation)
/* If interrupted, cancel the in-flight buffer */
if (ret < 0)
gb_message_cancel(operation->request);
+ else
+ ret = operation->errno;
return ret;
}
@@ -189,7 +195,7 @@ static void gb_operation_request_handle(struct gb_operation *operation)
gb_connection_err(operation->connection,
"unexpected incoming request type 0x%02hhx\n", header->type);
- operation->result = GB_OP_PROTOCOL_BAD;
+ operation->errno = -EPROTONOSUPPORT;
}
/*
@@ -224,7 +230,7 @@ static void operation_timeout(struct work_struct *work)
operation = container_of(work, struct gb_operation, timeout_work.work);
pr_debug("%s: timeout!\n", __func__);
- operation->result = GB_OP_TIMEOUT;
+ operation->errno = -ETIMEDOUT;
gb_operation_complete(operation);
}
@@ -470,13 +476,10 @@ int gb_operation_request_send(struct gb_operation *operation,
/* All set, send the request */
ret = gb_message_send(operation->request, GFP_KERNEL);
- if (ret)
+ if (ret || callback)
return ret;
- if (!callback)
- ret = gb_operation_wait(operation);
-
- return ret;
+ return gb_operation_wait(operation);
}
/*
@@ -493,8 +496,6 @@ int gb_operation_response_send(struct gb_operation *operation)
* This function is called when a buffer send request has completed.
* The "header" is the message header--the beginning of what we
* asked to have sent.
- *
- * XXX Mismatch between errno here and operation result code
*/
void
greybus_data_sent(struct greybus_host_device *hd, void *header, int status)
@@ -510,7 +511,7 @@ greybus_data_sent(struct greybus_host_device *hd, void *header, int status)
message = gb_hd_message_find(hd, header);
operation = message->operation;
gb_connection_err(operation->connection, "send error %d\n", status);
- operation->result = status; /* XXX */
+ operation->errno = status;
gb_operation_complete(operation);
}
EXPORT_SYMBOL_GPL(greybus_data_sent);
@@ -567,14 +568,14 @@ static void gb_connection_recv_response(struct gb_connection *connection,
if (size <= message->size) {
/* Transfer the operation result from the response header */
header = message->header;
- operation->result = header->result;
+ operation->errno = gb_operation_status_map(header->result);
} else {
gb_connection_err(connection, "recv buffer too small");
- operation->result = GB_OP_OVERFLOW;
+ operation->errno = -E2BIG;
}
/* We must ignore the payload if a bad status is returned */
- if (operation->result == GB_OP_SUCCESS)
+ if (!operation->errno)
memcpy(message->header, data, size);
/* The rest will be handled in work queue context */