greybus: define operation_cancel()

Define a new function operation_cancel() that cancels an
outstanding operation.  Use it to clear out any operations that
might be pending at the time a connection is torn down.

Note:  This code isn't really functional yet, partially because
greybus_kill_gbuf() is not implemented.

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-10-22 02:04:29 -05:00 committed by Greg Kroah-Hartman
parent e816e37419
commit e1158df063
3 changed files with 27 additions and 0 deletions

View File

@ -162,12 +162,19 @@ struct gb_connection *gb_connection_create(struct gb_interface *interface,
*/ */
void gb_connection_destroy(struct gb_connection *connection) void gb_connection_destroy(struct gb_connection *connection)
{ {
struct gb_operation *operation;
struct gb_operation *next;
if (WARN_ON(!connection)) if (WARN_ON(!connection))
return; return;
/* XXX Need to wait for any outstanding requests to complete */ /* XXX Need to wait for any outstanding requests to complete */
WARN_ON(!list_empty(&connection->operations)); WARN_ON(!list_empty(&connection->operations));
list_for_each_entry_safe(operation, next, &connection->operations,
links) {
gb_operation_cancel(operation);
}
spin_lock_irq(&gb_connections_lock); spin_lock_irq(&gb_connections_lock);
list_del(&connection->interface_links); list_del(&connection->interface_links);
_gb_hd_connection_remove(connection); _gb_hd_connection_remove(connection);

View File

@ -501,6 +501,24 @@ void gb_connection_operation_recv(struct gb_connection *connection,
queue_work(gb_operation_recv_workqueue, &operation->recv_work); queue_work(gb_operation_recv_workqueue, &operation->recv_work);
} }
/*
* Cancel an operation.
*/
void gb_operation_cancel(struct gb_operation *operation)
{
int ret;
operation->canceled = true;
ret = greybus_kill_gbuf(operation->request);
if (ret)
pr_warn("error %d killing request gbuf\n", ret);
if (operation->response) {
ret = greybus_kill_gbuf(operation->response);
if (ret)
pr_warn("error %d killing response gbuf\n", ret);
}
}
int gb_operation_init(void) int gb_operation_init(void)
{ {
gb_operation_cache = kmem_cache_create("gb_operation_cache", gb_operation_cache = kmem_cache_create("gb_operation_cache",

View File

@ -55,6 +55,7 @@ struct gb_operation {
struct gbuf *request; struct gbuf *request;
struct gbuf *response; struct gbuf *response;
u16 id; u16 id;
bool canceled;
u8 result; u8 result;
struct work_struct recv_work; struct work_struct recv_work;
@ -81,6 +82,7 @@ int gb_operation_request_send(struct gb_operation *operation,
gb_operation_callback callback); gb_operation_callback callback);
int gb_operation_response_send(struct gb_operation *operation); int gb_operation_response_send(struct gb_operation *operation);
void gb_operation_cancel(struct gb_operation *operation);
int gb_operation_wait(struct gb_operation *operation); int gb_operation_wait(struct gb_operation *operation);
void gb_operation_complete(struct gb_operation *operation); void gb_operation_complete(struct gb_operation *operation);