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:
parent
dbb8894e0c
commit
19d03decd3
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
/* ... */
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue