diff options
author | Johan Hovold <johan@hovoldconsulting.com> | 2015-07-14 15:43:25 +0200 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@google.com> | 2015-07-15 12:39:13 -0700 |
commit | 3eeac7e37ce9856e53693772dfe81a79b57b5a00 (patch) | |
tree | 0823f523632ace05cd73c3c04d05b6dd974196fa /drivers/staging/greybus/operation.c | |
parent | 9a586bd2bb80a268345cc8ccfa702413359ece06 (diff) |
greybus: operation: add active counter
Add active counter to track operations that are in use.
Note that the active count is always less than the reference count.
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.c | 28 |
1 files changed, 26 insertions, 2 deletions
diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index 081694c8a1c2..abe44c18fb9e 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -32,6 +32,18 @@ static DEFINE_SPINLOCK(gb_operations_lock); static int gb_operation_response_send(struct gb_operation *operation, int errno); +/* Caller holds operation reference. */ +static inline void gb_operation_get_active(struct gb_operation *operation) +{ + atomic_inc(&operation->active); +} + +/* Caller holds operation reference. */ +static inline void gb_operation_put_active(struct gb_operation *operation) +{ + atomic_dec(&operation->active); +} + /* * Set an operation's result. * @@ -204,6 +216,7 @@ static void gb_operation_work(struct work_struct *work) operation->callback(operation); + gb_operation_put_active(operation); gb_operation_put(operation); } @@ -449,6 +462,7 @@ gb_operation_create_common(struct gb_connection *connection, u8 type, INIT_WORK(&operation->work, gb_operation_work); init_completion(&operation->completion); kref_init(&operation->kref); + atomic_set(&operation->active, 0); spin_lock_irqsave(&gb_operations_lock, flags); list_add_tail(&operation->links, &connection->operations); @@ -597,6 +611,7 @@ int gb_operation_request_send(struct gb_operation *operation, * It'll be dropped when the operation completes. */ gb_operation_get(operation); + gb_operation_get_active(operation); /* * Record the callback function, which is executed in @@ -618,8 +633,10 @@ int gb_operation_request_send(struct gb_operation *operation, gb_operation_result_set(operation, -EINPROGRESS); ret = gb_message_send(operation->request, gfp); - if (ret) + if (ret) { + gb_operation_put_active(operation); gb_operation_put(operation); + } return ret; } @@ -688,13 +705,16 @@ static int gb_operation_response_send(struct gb_operation *operation, /* Reference will be dropped when message has been sent. */ gb_operation_get(operation); + gb_operation_get_active(operation); /* Fill in the response header and send it */ operation->response->header->result = gb_operation_errno_map(errno); ret = gb_message_send(operation->response, GFP_KERNEL); - if (ret) + if (ret) { + gb_operation_put_active(operation); gb_operation_put(operation); + } return ret; } @@ -723,6 +743,7 @@ void greybus_message_sent(struct greybus_host_device *hd, dev_err(&operation->connection->dev, "error sending response: %d\n", status); } + gb_operation_put_active(operation); gb_operation_put(operation); } else if (status) { if (gb_operation_result_set(operation, status)) @@ -751,6 +772,8 @@ static void gb_connection_recv_request(struct gb_connection *connection, return; /* XXX Respond with pre-allocated ENOMEM */ } + gb_operation_get_active(operation); + /* * Incoming requests are handled by arranging for the * request handler to be the operation's callback function. @@ -863,6 +886,7 @@ void gb_operation_cancel(struct gb_operation *operation, int errno) } else { if (gb_operation_result_set(operation, errno)) { gb_message_cancel(operation->request); + gb_operation_put_active(operation); gb_operation_put(operation); } } |