mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-09-12 05:48:40 +00:00
greybus: get rid of pending operations list
A connection has two lists of operations, and an operation is always on one or the other of them. One of them contains the operations that are currently "in flight". We really don't expect to have very many in-flight operations on any given connection (in fact, at the moment it's always exactly one). So there's no significant performance benefit to keeping these in a separate list. An in-flight operation can also be distinguished by its errno field holding -EINPROGRESS. Get rid of the pending list, and search all operations rather than the pending list when looking up a response message's operation. Rename gb_pending_operation_find() accordingly. There's no longer any need to remove operations from the pending list, and the insertion function no longer has anything to do with a pending list. Just open code what was the insertion function (it now has only to do with assigning the operation id). Signed-off-by: Alex Elder <elder@linaro.org> Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
This commit is contained in:
parent
0ba02c4d16
commit
afb2e1342e
4 changed files with 17 additions and 39 deletions
|
@ -192,7 +192,6 @@ struct gb_connection *gb_connection_create(struct gb_interface *interface,
|
|||
spin_unlock_irq(&gb_connections_lock);
|
||||
|
||||
INIT_LIST_HEAD(&connection->operations);
|
||||
INIT_LIST_HEAD(&connection->pending);
|
||||
|
||||
return connection;
|
||||
}
|
||||
|
|
|
@ -37,7 +37,6 @@ struct gb_connection {
|
|||
|
||||
u16 op_cycle;
|
||||
struct list_head operations;
|
||||
struct list_head pending; /* awaiting response */
|
||||
|
||||
void *private;
|
||||
};
|
||||
|
|
|
@ -144,44 +144,14 @@ int gb_operation_result(struct gb_operation *operation)
|
|||
return result;
|
||||
}
|
||||
|
||||
static void gb_pending_operation_insert(struct gb_operation *operation)
|
||||
{
|
||||
struct gb_connection *connection = operation->connection;
|
||||
struct gb_operation_msg_hdr *header;
|
||||
|
||||
/*
|
||||
* Assign the operation's id and move it into its
|
||||
* connection's pending list. Zero is a reserved operation
|
||||
* id.
|
||||
*/
|
||||
spin_lock_irq(&gb_operations_lock);
|
||||
operation->id = ++connection->op_cycle % U16_MAX + 1;
|
||||
list_move_tail(&operation->links, &connection->pending);
|
||||
spin_unlock_irq(&gb_operations_lock);
|
||||
|
||||
/* Store the operation id in the request header */
|
||||
header = operation->request->header;
|
||||
header->operation_id = cpu_to_le16(operation->id);
|
||||
}
|
||||
|
||||
static void gb_pending_operation_remove(struct gb_operation *operation)
|
||||
{
|
||||
struct gb_connection *connection = operation->connection;
|
||||
|
||||
/* Take us off of the list of pending operations */
|
||||
spin_lock_irq(&gb_operations_lock);
|
||||
list_move_tail(&operation->links, &connection->operations);
|
||||
spin_unlock_irq(&gb_operations_lock);
|
||||
}
|
||||
|
||||
static struct gb_operation *
|
||||
gb_pending_operation_find(struct gb_connection *connection, u16 operation_id)
|
||||
gb_operation_find(struct gb_connection *connection, u16 operation_id)
|
||||
{
|
||||
struct gb_operation *operation;
|
||||
bool found = false;
|
||||
|
||||
spin_lock_irq(&gb_operations_lock);
|
||||
list_for_each_entry(operation, &connection->pending, links)
|
||||
list_for_each_entry(operation, &connection->operations, links)
|
||||
if (operation->id == operation_id) {
|
||||
found = true;
|
||||
break;
|
||||
|
@ -667,10 +637,12 @@ static void gb_operation_sync_callback(struct gb_operation *operation)
|
|||
int gb_operation_request_send(struct gb_operation *operation,
|
||||
gb_operation_callback callback)
|
||||
{
|
||||
struct gb_connection *connection = operation->connection;
|
||||
struct gb_operation_msg_hdr *header;
|
||||
unsigned long timeout;
|
||||
int ret;
|
||||
|
||||
if (operation->connection->state != GB_CONNECTION_STATE_ENABLED)
|
||||
if (connection->state != GB_CONNECTION_STATE_ENABLED)
|
||||
return -ENOTCONN;
|
||||
|
||||
/*
|
||||
|
@ -684,7 +656,16 @@ int gb_operation_request_send(struct gb_operation *operation,
|
|||
operation->callback = callback;
|
||||
else
|
||||
operation->callback = gb_operation_sync_callback;
|
||||
gb_pending_operation_insert(operation);
|
||||
|
||||
/*
|
||||
* Assign the operation's id, and store it in the request header.
|
||||
* Zero is a reserved operation id.
|
||||
*/
|
||||
spin_lock_irq(&gb_operations_lock);
|
||||
operation->id = ++connection->op_cycle % U16_MAX + 1;
|
||||
spin_unlock_irq(&gb_operations_lock);
|
||||
header = operation->request->header;
|
||||
header->operation_id = cpu_to_le16(operation->id);
|
||||
|
||||
/*
|
||||
* We impose a time limit for requests to complete. We need
|
||||
|
@ -826,14 +807,13 @@ static void gb_connection_recv_response(struct gb_connection *connection,
|
|||
struct gb_message *message;
|
||||
int errno = gb_operation_status_map(result);
|
||||
|
||||
operation = gb_pending_operation_find(connection, operation_id);
|
||||
operation = gb_operation_find(connection, operation_id);
|
||||
if (!operation) {
|
||||
gb_connection_err(connection, "operation not found");
|
||||
return;
|
||||
}
|
||||
|
||||
cancel_delayed_work(&operation->timeout_work);
|
||||
gb_pending_operation_remove(operation);
|
||||
|
||||
message = operation->response;
|
||||
if (!errno && size != message->size) {
|
||||
|
|
|
@ -92,7 +92,7 @@ struct gb_operation {
|
|||
struct delayed_work timeout_work;
|
||||
|
||||
struct kref kref;
|
||||
struct list_head links; /* connection->{operations,pending} */
|
||||
struct list_head links; /* connection->operations */
|
||||
};
|
||||
|
||||
void gb_connection_recv(struct gb_connection *connection,
|
||||
|
|
Loading…
Reference in a new issue