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 <elder@linaro.org>
Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
This commit is contained in:
Alex Elder 2014-11-05 16:12:53 -06:00 committed by Greg Kroah-Hartman
parent dbb8894e0c
commit 19d03decd3
9 changed files with 166 additions and 18 deletions

View file

@ -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);
}

View file

@ -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();

View file

@ -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);
}

View file

@ -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,
/* ... */

View file

@ -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);
}

View file

@ -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();
}

View file

@ -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 */

View file

@ -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);
}

View file

@ -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);
}