From: Alex Elder Date: Wed, 5 Nov 2014 22:12:53 +0000 (-0600) Subject: greybus: register preallocated protocols X-Git-Url: https://git.stricted.de/?a=commitdiff_plain;h=19d03decd3415a7a0ec6c378720058f29f9568cc;p=GitHub%2FLineageOS%2Fandroid_kernel_motorola_exynos9610.git greybus: register preallocated protocols Set up protocol structures as static objects in each protocol source file. Pass the address of that in--rather than the protocol id and version information--to the protocol registration routine. Call a central routine to register all our pre-defined protocols. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman --- diff --git a/drivers/staging/greybus/battery-gb.c b/drivers/staging/greybus/battery-gb.c index 28c0d0b9aefe..457daf700543 100644 --- a/drivers/staging/greybus/battery-gb.c +++ b/drivers/staging/greybus/battery-gb.c @@ -404,3 +404,19 @@ struct gb_connection_handler gb_battery_connection_handler = { .connection_init = gb_battery_connection_init, .connection_exit = gb_battery_connection_exit, }; + +static struct gb_protocol battery_protocol = { + .id = GREYBUS_PROTOCOL_BATTERY, + .major = 0, + .minor = 1, +}; + +bool gb_battery_protocol_init(void) +{ + return gb_protocol_register(&battery_protocol); +} + +void gb_battery_protocol_exit(void) +{ + gb_protocol_deregister(&battery_protocol); +} diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index 252d131c3ae8..1d05c35a1b60 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -277,17 +277,23 @@ static int __init gb_init(void) goto error_operation; } - return 0; + if (!gb_protocol_init()) { + /* This only fails for duplicate protocol registration */ + retval = -EEXIST; + pr_err("gb_protocol_init failed\n"); + goto error_protocol; + } + return 0; /* Success */ + +error_protocol: + gb_operation_exit(); error_operation: gb_gbuf_exit(); - error_gbuf: gb_ap_exit(); - error_ap: bus_unregister(&greybus_bus_type); - error_bus: gb_debugfs_cleanup(); diff --git a/drivers/staging/greybus/gpio-gb.c b/drivers/staging/greybus/gpio-gb.c index df7dbae85d63..242b91a99d22 100644 --- a/drivers/staging/greybus/gpio-gb.c +++ b/drivers/staging/greybus/gpio-gb.c @@ -796,3 +796,19 @@ struct gb_connection_handler gb_gpio_connection_handler = { .connection_init = gb_gpio_connection_init, .connection_exit = gb_gpio_connection_exit, }; + +static struct gb_protocol gpio_protocol = { + .id = GREYBUS_PROTOCOL_GPIO, + .major = 0, + .minor = 1, +}; + +bool gb_gpio_protocol_init(void) +{ + return gb_protocol_register(&gpio_protocol); +} + +void gb_gpio_protocol_exit(void) +{ + gb_protocol_deregister(&gpio_protocol); +} diff --git a/drivers/staging/greybus/greybus_manifest.h b/drivers/staging/greybus/greybus_manifest.h index c6988ce2818a..844ab8a745b0 100644 --- a/drivers/staging/greybus/greybus_manifest.h +++ b/drivers/staging/greybus/greybus_manifest.h @@ -30,6 +30,7 @@ enum greybus_protocol { GREYBUS_PROTOCOL_I2C = 0x03, GREYBUS_PROTOCOL_UART = 0x04, GREYBUS_PROTOCOL_HID = 0x05, + GREYBUS_PROTOCOL_SDIO = 0x06, GREYBUS_PROTOCOL_BATTERY = 0x08, GREYBUS_PROTOCOL_LED = 0x0e, /* ... */ diff --git a/drivers/staging/greybus/i2c-gb.c b/drivers/staging/greybus/i2c-gb.c index b26464a14b32..c8fae17d4b77 100644 --- a/drivers/staging/greybus/i2c-gb.c +++ b/drivers/staging/greybus/i2c-gb.c @@ -522,3 +522,19 @@ struct gb_connection_handler gb_i2c_connection_handler = { .connection_init = gb_i2c_connection_init, .connection_exit = gb_i2c_connection_exit, }; + +static struct gb_protocol i2c_protocol = { + .id = GREYBUS_PROTOCOL_I2C, + .major = 0, + .minor = 1, +}; + +bool gb_i2c_protocol_init(void) +{ + return gb_protocol_register(&i2c_protocol); +} + +void gb_i2c_protocol_exit(void) +{ + gb_protocol_deregister(&i2c_protocol); +} diff --git a/drivers/staging/greybus/protocol.c b/drivers/staging/greybus/protocol.c index 6fec32eea76d..93e0af3c6b4e 100644 --- a/drivers/staging/greybus/protocol.c +++ b/drivers/staging/greybus/protocol.c @@ -39,18 +39,12 @@ static struct gb_protocol *_gb_protocol_find(u8 id, u8 major, u8 minor) } /* Returns true if protocol was succesfully registered, false otherwise */ -bool gb_protocol_register(u8 id, u8 major, u8 minor) +bool gb_protocol_register(struct gb_protocol *protocol) { - struct gb_protocol *protocol; struct gb_protocol *existing; - - /* Initialize it speculatively */ - protocol = kzalloc(sizeof(*protocol), GFP_KERNEL); - if (!protocol) - return false; - protocol->id = id; - protocol->major = major; - protocol->minor = minor; + u8 id = protocol->id; + u8 major = protocol->major; + u8 minor = protocol->minor; /* * The protocols list is sorted first by protocol id (low to @@ -79,7 +73,6 @@ bool gb_protocol_register(u8 id, u8 major, u8 minor) /* A matching protocol has already been registered */ spin_unlock_irq(&gb_protocols_lock); - kfree(protocol); return false; } @@ -94,7 +87,17 @@ bool gb_protocol_register(u8 id, u8 major, u8 minor) return true; } -/* Returns true if successful, false otherwise */ +/* + * De-register a previously registered protocol. + * + * XXX Currently this fails (and reports an error to the caller) if + * XXX the protocol is currently in use. We may want to forcefully + * XXX kill off a protocol and all its active users at some point. + * XXX But I think that's better handled by quescing modules that + * XXX have users and having those users drop their reference. + * + * Returns true if successful, false otherwise. + */ bool gb_protocol_deregister(struct gb_protocol *protocol) { u8 protocol_count = 0; @@ -108,7 +111,6 @@ bool gb_protocol_deregister(struct gb_protocol *protocol) list_del(&protocol->links); } spin_unlock_irq(&gb_protocols_lock); - kfree(protocol); return protocol && !protocol_count; } @@ -158,3 +160,39 @@ void gb_protocol_put(struct gb_protocol *protocol) pr_err("protocol id %hhu version %hhu.%hhu not found\n", protocol->id, major, minor); } + +bool gb_protocol_init(void) +{ + bool ret = true; + + if (!gb_battery_protocol_init()) { + pr_err("error initializing battery protocol\n"); + ret = false; + } + if (!gb_gpio_protocol_init()) { + pr_err("error initializing gpio protocol\n"); + ret = false; + } + if (!gb_i2c_protocol_init()) { + pr_err("error initializing i2c protocol\n"); + ret = false; + } + if (!gb_uart_protocol_init()) { + pr_err("error initializing uart protocol\n"); + ret = false; + } + if (!gb_sdio_protocol_init()) { + pr_err("error initializing sdio protocol\n"); + ret = false; + } + return ret; +} + +void gb_protocol_exit(void) +{ + gb_sdio_protocol_exit(); + gb_uart_protocol_exit(); + gb_i2c_protocol_exit(); + gb_gpio_protocol_exit(); + gb_battery_protocol_exit(); +} diff --git a/drivers/staging/greybus/protocol.h b/drivers/staging/greybus/protocol.h index aa7b5548e8a8..c2adfdca8bf7 100644 --- a/drivers/staging/greybus/protocol.h +++ b/drivers/staging/greybus/protocol.h @@ -25,10 +25,33 @@ struct gb_protocol { struct list_head links; /* global list */ }; -bool gb_protocol_register(u8 id, u8 major, u8 minor); +bool gb_protocol_register(struct gb_protocol *protocol); bool gb_protocol_deregister(struct gb_protocol *protocol); struct gb_protocol *gb_protocol_get(u8 id, u8 major, u8 minor); void gb_protocol_put(struct gb_protocol *protocol); +/* + * These are defined in their respective protocol source files. + * Declared here for now. They could be added via modules, or maybe + * just use initcalls (which level?). + */ +extern bool gb_battery_protocol_init(void); +extern void gb_battery_protocol_exit(void); + +extern bool gb_gpio_protocol_init(void); +extern void gb_gpio_protocol_exit(void); + +extern bool gb_i2c_protocol_init(void); +extern void gb_i2c_protocol_exit(void); + +extern bool gb_uart_protocol_init(void); +extern void gb_uart_protocol_exit(void); + +extern bool gb_sdio_protocol_init(void); +extern void gb_sdio_protocol_exit(void); + +bool gb_protocol_init(void); +void gb_protocol_exit(void); + #endif /* __PROTOCOL_H */ diff --git a/drivers/staging/greybus/sdio-gb.c b/drivers/staging/greybus/sdio-gb.c index 30caba8d0fa5..8fbfbca37c48 100644 --- a/drivers/staging/greybus/sdio-gb.c +++ b/drivers/staging/greybus/sdio-gb.c @@ -81,3 +81,19 @@ struct gb_connection_handler gb_sdio_connection_handler = { .connection_init = gb_sdio_connection_init, .connection_exit = gb_sdio_connection_exit, }; + +static struct gb_protocol sdio_protocol = { + .id = GREYBUS_PROTOCOL_SDIO, + .major = 0, + .minor = 1, +}; + +bool gb_sdio_protocol_init(void) +{ + return gb_protocol_register(&sdio_protocol); +} + +void gb_sdio_protocol_exit(void) +{ + gb_protocol_deregister(&sdio_protocol); +} diff --git a/drivers/staging/greybus/uart-gb.c b/drivers/staging/greybus/uart-gb.c index b52d9e11f536..5596644e952b 100644 --- a/drivers/staging/greybus/uart-gb.c +++ b/drivers/staging/greybus/uart-gb.c @@ -524,3 +524,19 @@ struct gb_connection_handler gb_uart_connection_handler = { .connection_init = gb_uart_connection_init, .connection_exit = gb_uart_connection_exit, }; + +static struct gb_protocol uart_protocol = { + .id = GREYBUS_PROTOCOL_UART, + .major = 0, + .minor = 1, +}; + +bool gb_uart_protocol_init(void) +{ + return gb_protocol_register(&uart_protocol); +} + +void gb_uart_protocol_exit(void) +{ + gb_protocol_deregister(&uart_protocol); +}