greybus: introduce gb_operation_request_send_sync()

Define a new function used to initiate a synchronous operation.
It sends the operation request message and doesn't return until
the response has been received and/or the operation's result
has been set.

This gets rid of the convention that a null callback pointer
signifies a synchronous operation.

Signed-off-by: Alex Elder <elder@linaro.org>
Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
This commit is contained in:
Alex Elder 2014-12-03 08:35:09 -06:00 committed by Greg Kroah-Hartman
parent 4afb7fd015
commit c25572ca94
4 changed files with 26 additions and 12 deletions

View File

@ -285,7 +285,7 @@ static int gb_i2c_transfer_operation(struct gb_i2c_device *gb_i2c_dev,
return -ENOMEM;
/* Synchronous operation--no callback */
ret = gb_operation_request_send(operation, NULL);
ret = gb_operation_request_send_sync(operation);
if (ret) {
if (ret != -EAGAIN)
pr_err("transfer operation failed (%d)\n", ret);

View File

@ -641,7 +641,6 @@ int gb_operation_request_send(struct gb_operation *operation,
struct gb_operation_msg_hdr *header;
unsigned long timeout;
unsigned int cycle;
int ret;
if (connection->state != GB_CONNECTION_STATE_ENABLED)
return -ENOTCONN;
@ -652,11 +651,12 @@ int gb_operation_request_send(struct gb_operation *operation,
*/
gb_operation_get(operation);
/* A null callback pointer means synchronous return */
if (callback)
/*
* Record the callback function, which is executed in
* non-atomic (workqueue) context when the final result
* of an operation has been set.
*/
operation->callback = callback;
else
operation->callback = gb_operation_sync_callback;
/*
* Assign the operation's id, and store it in the request header.
@ -677,8 +677,22 @@ int gb_operation_request_send(struct gb_operation *operation,
/* All set, send the request */
gb_operation_result_set(operation, -EINPROGRESS);
ret = gb_message_send(operation->request);
if (ret || callback)
return gb_message_send(operation->request);
}
/*
* Send a synchronous operation. This function is expected to
* block, returning only when the response has arrived, (or when an
* error is detected. The return value is the result of the
* operation.
*/
int gb_operation_request_send_sync(struct gb_operation *operation)
{
int ret;
ret = gb_operation_request_send(operation, gb_operation_sync_callback);
if (ret)
return ret;
/* Cancel the operation if interrupted */
@ -923,8 +937,7 @@ int gb_operation_sync(struct gb_connection *connection, int type,
if (request_size)
memcpy(operation->request->payload, request, request_size);
/* Synchronous operation--no callback */
ret = gb_operation_request_send(operation, NULL);
ret = gb_operation_request_send_sync(operation);
if (ret)
pr_err("version operation failed (%d)\n", ret);
else

View File

@ -115,6 +115,7 @@ bool gb_operation_response_alloc(struct gb_operation *operation,
int gb_operation_request_send(struct gb_operation *operation,
gb_operation_callback callback);
int gb_operation_request_send_sync(struct gb_operation *operation);
int gb_operation_response_send(struct gb_operation *operation, int errno);
void gb_operation_cancel(struct gb_operation *operation, int errno);

View File

@ -169,7 +169,7 @@ static int urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flags)
memcpy(&request->payload, urb->transfer_buffer,
urb->transfer_buffer_length);
ret = gb_operation_request_send(operation, NULL);
ret = gb_operation_request_send_sync(operation);
gb_operation_destroy(operation);
return ret;