Commit 5b3db0dd authored by Alex Elder's avatar Alex Elder Committed by Greg Kroah-Hartman

greybus: create a slab cache for operations

Everything we do on greybus will involve an operation, so create a
slab cache for that frequently-allocated data structure.
Signed-off-by: default avatarAlex Elder <elder@linaro.org>
Signed-off-by: default avatarGreg Kroah-Hartman <greg@kroah.com>
parent 599dc6aa
...@@ -24,6 +24,8 @@ ...@@ -24,6 +24,8 @@
*/ */
#define GB_OPERATION_MESSAGE_SIZE_MAX 4096 #define GB_OPERATION_MESSAGE_SIZE_MAX 4096
static struct kmem_cache *gb_operation_cache;
/* Workqueue to handle Greybus operation completions. */ /* Workqueue to handle Greybus operation completions. */
static struct workqueue_struct *gb_operation_recv_workqueue; static struct workqueue_struct *gb_operation_recv_workqueue;
...@@ -307,8 +309,7 @@ struct gb_operation *gb_operation_create(struct gb_connection *connection, ...@@ -307,8 +309,7 @@ struct gb_operation *gb_operation_create(struct gb_connection *connection,
gfp_t gfp_flags = response_size ? GFP_KERNEL : GFP_ATOMIC; gfp_t gfp_flags = response_size ? GFP_KERNEL : GFP_ATOMIC;
bool outgoing = response_size != 0; bool outgoing = response_size != 0;
/* XXX Use a slab cache */ operation = kmem_cache_zalloc(gb_operation_cache, gfp_flags);
operation = kzalloc(sizeof(*operation), gfp_flags);
if (!operation) if (!operation)
return NULL; return NULL;
operation->connection = connection; /* XXX refcount? */ operation->connection = connection; /* XXX refcount? */
...@@ -316,10 +317,8 @@ struct gb_operation *gb_operation_create(struct gb_connection *connection, ...@@ -316,10 +317,8 @@ struct gb_operation *gb_operation_create(struct gb_connection *connection,
operation->request = gb_operation_gbuf_create(operation, type, operation->request = gb_operation_gbuf_create(operation, type,
request_size, request_size,
outgoing); outgoing);
if (!operation->request) { if (!operation->request)
kfree(operation); goto err_cache;
return NULL;
}
operation->request_payload = operation->request->transfer_buffer + operation->request_payload = operation->request->transfer_buffer +
sizeof(struct gb_operation_msg_hdr); sizeof(struct gb_operation_msg_hdr);
/* We always use the full request buffer */ /* We always use the full request buffer */
...@@ -330,11 +329,8 @@ struct gb_operation *gb_operation_create(struct gb_connection *connection, ...@@ -330,11 +329,8 @@ struct gb_operation *gb_operation_create(struct gb_connection *connection,
operation->response = gb_operation_gbuf_create(operation, operation->response = gb_operation_gbuf_create(operation,
type, response_size, type, response_size,
false); false);
if (!operation->response) { if (!operation->response)
greybus_free_gbuf(operation->request); goto err_request;
kfree(operation);
return NULL;
}
operation->response_payload = operation->response_payload =
operation->response->transfer_buffer + operation->response->transfer_buffer +
sizeof(struct gb_operation_msg_hdr); sizeof(struct gb_operation_msg_hdr);
...@@ -349,6 +345,13 @@ struct gb_operation *gb_operation_create(struct gb_connection *connection, ...@@ -349,6 +345,13 @@ struct gb_operation *gb_operation_create(struct gb_connection *connection,
spin_unlock_irq(&gb_operations_lock); spin_unlock_irq(&gb_operations_lock);
return operation; return operation;
err_request:
greybus_free_gbuf(operation->request);
err_cache:
kmem_cache_free(gb_operation_cache, operation);
return NULL;
} }
/* /*
...@@ -367,7 +370,7 @@ void gb_operation_destroy(struct gb_operation *operation) ...@@ -367,7 +370,7 @@ void gb_operation_destroy(struct gb_operation *operation)
greybus_free_gbuf(operation->response); greybus_free_gbuf(operation->response);
greybus_free_gbuf(operation->request); greybus_free_gbuf(operation->request);
kfree(operation); kmem_cache_free(gb_operation_cache, operation);
} }
/* /*
...@@ -470,14 +473,25 @@ void gb_connection_operation_recv(struct gb_connection *connection, ...@@ -470,14 +473,25 @@ void gb_connection_operation_recv(struct gb_connection *connection,
int gb_operation_init(void) int gb_operation_init(void)
{ {
gb_operation_cache = kmem_cache_create("gb_operation_cache",
sizeof(struct gb_operation), 0, 0, NULL);
if (!gb_operation_cache)
return -ENOMEM;
gb_operation_recv_workqueue = alloc_workqueue("greybus_recv", 0, 1); gb_operation_recv_workqueue = alloc_workqueue("greybus_recv", 0, 1);
if (!gb_operation_recv_workqueue) if (!gb_operation_recv_workqueue) {
kmem_cache_destroy(gb_operation_cache);
gb_operation_cache = NULL;
return -ENOMEM; return -ENOMEM;
}
return 0; return 0;
} }
void gb_operation_exit(void) void gb_operation_exit(void)
{ {
kmem_cache_destroy(gb_operation_cache);
gb_operation_cache = NULL;
destroy_workqueue(gb_operation_recv_workqueue); destroy_workqueue(gb_operation_recv_workqueue);
gb_operation_recv_workqueue = NULL;
} }
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