diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index 032973cf27a9d84aca0ad10d8894d317b9a5f31d..180d0285622523c5bf3e254671472a276769d258 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -145,21 +145,6 @@ static void gb_message_cancel(struct gb_message *message) hd->driver->buffer_cancel(message->cookie); } -/* - * An operation's response message has arrived. If no callback was - * supplied it was submitted for asynchronous completion, so we notify - * any waiters. Otherwise we assume calling the completion is enough - * and nobody else will be waiting. - */ -static void gb_operation_complete(struct gb_operation *operation) -{ - if (operation->callback) - operation->callback(operation); - else - complete(&operation->completion); - gb_operation_put(operation); -} - #if 0 static void gb_operation_request_handle(struct gb_operation *operation) { @@ -192,7 +177,12 @@ static void gb_operation_work(struct work_struct *work) struct gb_operation *operation; operation = container_of(work, struct gb_operation, work); - gb_operation_complete(operation); + if (WARN_ON(!operation->callback)) + return; + + operation->callback(operation); + operation->callback = NULL; + gb_operation_put(operation); } /* @@ -423,14 +413,22 @@ void gb_operation_put(struct gb_operation *operation) kref_put(&operation->kref, _gb_operation_destroy); } +/* Tell the requester we're done */ +static void gb_operation_sync_callback(struct gb_operation *operation) +{ + complete(&operation->completion); +} + /* * Send an operation request message. The caller has filled in * any payload so the request message is ready to go. If non-null, * the callback function supplied will be called when the response - * message has arrived indicating the operation is complete. A null + * message has arrived indicating the operation is complete. In + * that case, the callback function is responsible for extracting + * the result of the operation from operation->errno if desired, + * and dropping the final reference to the operation. A null * callback function is used for a synchronous request; return from - * this function won't occur until the operation is complete (or an - * interrupt occurs). + * this function won't occur until the operation is complete. */ int gb_operation_request_send(struct gb_operation *operation, gb_operation_callback callback) @@ -447,7 +445,11 @@ int gb_operation_request_send(struct gb_operation *operation, */ gb_operation_get(operation); - operation->callback = callback; + /* A null callback pointer means synchronous return */ + if (callback) + operation->callback = callback; + else + operation->callback = gb_operation_sync_callback; gb_pending_operation_insert(operation); /*