Commit 3eeac7e3 authored by Johan Hovold's avatar Johan Hovold Committed by Greg Kroah-Hartman

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: default avatarJohan Hovold <johan@hovoldconsulting.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@google.com>
parent 9a586bd2
...@@ -32,6 +32,18 @@ static DEFINE_SPINLOCK(gb_operations_lock); ...@@ -32,6 +32,18 @@ static DEFINE_SPINLOCK(gb_operations_lock);
static int gb_operation_response_send(struct gb_operation *operation, static int gb_operation_response_send(struct gb_operation *operation,
int errno); 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. * Set an operation's result.
* *
...@@ -204,6 +216,7 @@ static void gb_operation_work(struct work_struct *work) ...@@ -204,6 +216,7 @@ static void gb_operation_work(struct work_struct *work)
operation->callback(operation); operation->callback(operation);
gb_operation_put_active(operation);
gb_operation_put(operation); gb_operation_put(operation);
} }
...@@ -449,6 +462,7 @@ gb_operation_create_common(struct gb_connection *connection, u8 type, ...@@ -449,6 +462,7 @@ gb_operation_create_common(struct gb_connection *connection, u8 type,
INIT_WORK(&operation->work, gb_operation_work); INIT_WORK(&operation->work, gb_operation_work);
init_completion(&operation->completion); init_completion(&operation->completion);
kref_init(&operation->kref); kref_init(&operation->kref);
atomic_set(&operation->active, 0);
spin_lock_irqsave(&gb_operations_lock, flags); spin_lock_irqsave(&gb_operations_lock, flags);
list_add_tail(&operation->links, &connection->operations); list_add_tail(&operation->links, &connection->operations);
...@@ -597,6 +611,7 @@ int gb_operation_request_send(struct gb_operation *operation, ...@@ -597,6 +611,7 @@ int gb_operation_request_send(struct gb_operation *operation,
* It'll be dropped when the operation completes. * It'll be dropped when the operation completes.
*/ */
gb_operation_get(operation); gb_operation_get(operation);
gb_operation_get_active(operation);
/* /*
* Record the callback function, which is executed in * Record the callback function, which is executed in
...@@ -618,8 +633,10 @@ int gb_operation_request_send(struct gb_operation *operation, ...@@ -618,8 +633,10 @@ int gb_operation_request_send(struct gb_operation *operation,
gb_operation_result_set(operation, -EINPROGRESS); gb_operation_result_set(operation, -EINPROGRESS);
ret = gb_message_send(operation->request, gfp); ret = gb_message_send(operation->request, gfp);
if (ret) if (ret) {
gb_operation_put_active(operation);
gb_operation_put(operation); gb_operation_put(operation);
}
return ret; return ret;
} }
...@@ -688,13 +705,16 @@ static int gb_operation_response_send(struct gb_operation *operation, ...@@ -688,13 +705,16 @@ static int gb_operation_response_send(struct gb_operation *operation,
/* Reference will be dropped when message has been sent. */ /* Reference will be dropped when message has been sent. */
gb_operation_get(operation); gb_operation_get(operation);
gb_operation_get_active(operation);
/* Fill in the response header and send it */ /* Fill in the response header and send it */
operation->response->header->result = gb_operation_errno_map(errno); operation->response->header->result = gb_operation_errno_map(errno);
ret = gb_message_send(operation->response, GFP_KERNEL); ret = gb_message_send(operation->response, GFP_KERNEL);
if (ret) if (ret) {
gb_operation_put_active(operation);
gb_operation_put(operation); gb_operation_put(operation);
}
return ret; return ret;
} }
...@@ -723,6 +743,7 @@ void greybus_message_sent(struct greybus_host_device *hd, ...@@ -723,6 +743,7 @@ void greybus_message_sent(struct greybus_host_device *hd,
dev_err(&operation->connection->dev, dev_err(&operation->connection->dev,
"error sending response: %d\n", status); "error sending response: %d\n", status);
} }
gb_operation_put_active(operation);
gb_operation_put(operation); gb_operation_put(operation);
} else if (status) { } else if (status) {
if (gb_operation_result_set(operation, status)) if (gb_operation_result_set(operation, status))
...@@ -751,6 +772,8 @@ static void gb_connection_recv_request(struct gb_connection *connection, ...@@ -751,6 +772,8 @@ static void gb_connection_recv_request(struct gb_connection *connection,
return; /* XXX Respond with pre-allocated ENOMEM */ return; /* XXX Respond with pre-allocated ENOMEM */
} }
gb_operation_get_active(operation);
/* /*
* Incoming requests are handled by arranging for the * Incoming requests are handled by arranging for the
* request handler to be the operation's callback function. * request handler to be the operation's callback function.
...@@ -863,6 +886,7 @@ void gb_operation_cancel(struct gb_operation *operation, int errno) ...@@ -863,6 +886,7 @@ void gb_operation_cancel(struct gb_operation *operation, int errno)
} else { } else {
if (gb_operation_result_set(operation, errno)) { if (gb_operation_result_set(operation, errno)) {
gb_message_cancel(operation->request); gb_message_cancel(operation->request);
gb_operation_put_active(operation);
gb_operation_put(operation); gb_operation_put(operation);
} }
} }
......
...@@ -127,6 +127,8 @@ struct gb_operation { ...@@ -127,6 +127,8 @@ struct gb_operation {
struct completion completion; struct completion completion;
struct kref kref; struct kref kref;
atomic_t active;
struct list_head links; /* connection->operations */ struct list_head links; /* connection->operations */
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment