greybus: operation: allow atomic operation allocations

Add gfp mask argument to gb_operation_create to allow operations to be
allocated in atomic context.

Signed-off-by: Johan Hovold <johan@hovoldconsulting.com>
Reviewed-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
This commit is contained in:
Johan Hovold 2015-07-01 12:37:22 +02:00 committed by Greg Kroah-Hartman
parent 3e136cc9e0
commit e420721b47
6 changed files with 16 additions and 20 deletions

View File

@ -128,7 +128,8 @@ static int gb_hid_set_report(struct gb_hid *ghid, u8 report_type, u8 report_id,
int ret, size = sizeof(*request) + len - 1;
operation = gb_operation_create(ghid->connection,
GB_HID_TYPE_SET_REPORT, size, 0);
GB_HID_TYPE_SET_REPORT, size, 0,
GFP_KERNEL);
if (!operation)
return -ENOMEM;

View File

@ -146,7 +146,7 @@ gb_i2c_operation_create(struct gb_connection *connection,
/* Response consists only of incoming data */
operation = gb_operation_create(connection, GB_I2C_TYPE_TRANSFER,
request_size, data_in_size);
request_size, data_in_size, GFP_KERNEL);
if (!operation)
return NULL;

View File

@ -409,22 +409,13 @@ EXPORT_SYMBOL_GPL(gb_operation_response_alloc);
*/
static struct gb_operation *
gb_operation_create_common(struct gb_connection *connection, u8 type,
size_t request_size, size_t response_size)
size_t request_size, size_t response_size,
gfp_t gfp_flags)
{
struct greybus_host_device *hd = connection->hd;
struct gb_operation *operation;
unsigned long flags;
gfp_t gfp_flags;
/*
* An incoming request will pass an invalid operation type,
* because the header will get overwritten anyway. These
* occur in interrupt context, so we must use GFP_ATOMIC.
*/
if (type == GB_OPERATION_TYPE_INVALID)
gfp_flags = GFP_ATOMIC;
else
gfp_flags = GFP_KERNEL;
operation = kmem_cache_zalloc(gb_operation_cache, gfp_flags);
if (!operation)
return NULL;
@ -472,7 +463,8 @@ err_cache:
*/
struct gb_operation *gb_operation_create(struct gb_connection *connection,
u8 type, size_t request_size,
size_t response_size)
size_t response_size,
gfp_t gfp)
{
if (WARN_ON_ONCE(type == GB_OPERATION_TYPE_INVALID))
return NULL;
@ -480,7 +472,7 @@ struct gb_operation *gb_operation_create(struct gb_connection *connection,
type &= ~GB_MESSAGE_TYPE_RESPONSE;
return gb_operation_create_common(connection, type,
request_size, response_size);
request_size, response_size, gfp);
}
EXPORT_SYMBOL_GPL(gb_operation_create);
@ -504,7 +496,7 @@ gb_operation_create_incoming(struct gb_connection *connection, u16 id,
operation = gb_operation_create_common(connection,
GB_OPERATION_TYPE_INVALID,
request_size, 0);
request_size, 0, GFP_ATOMIC);
if (operation) {
operation->id = id;
operation->type = type;
@ -888,7 +880,8 @@ int gb_operation_sync(struct gb_connection *connection, int type,
return -EINVAL;
operation = gb_operation_create(connection, type,
request_size, response_size);
request_size, response_size,
GFP_KERNEL);
if (!operation)
return -ENOMEM;

View File

@ -134,7 +134,8 @@ int gb_operation_result(struct gb_operation *operation);
size_t gb_operation_get_payload_size_max(struct gb_connection *connection);
struct gb_operation *gb_operation_create(struct gb_connection *connection,
u8 type, size_t request_size,
size_t response_size);
size_t response_size,
gfp_t gfp);
void gb_operation_get(struct gb_operation *operation);
void gb_operation_put(struct gb_operation *operation);
static inline void gb_operation_destroy(struct gb_operation *operation)

View File

@ -90,7 +90,7 @@ gb_spi_operation_create(struct gb_connection *connection,
/* Response consists only of incoming data */
operation = gb_operation_create(connection, GB_SPI_TYPE_TRANSFER,
request_size, rx_size);
request_size, rx_size, GFP_KERNEL);
if (!operation)
return NULL;

View File

@ -131,7 +131,8 @@ static int urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flags)
operation = gb_operation_create(dev->connection,
GB_USB_TYPE_URB_ENQUEUE,
sizeof(*request) +
urb->transfer_buffer_length, 0);
urb->transfer_buffer_length, 0,
GFP_KERNEL);
if (!operation)
return -ENODEV;