Commit 19d03dec authored by Alex Elder's avatar Alex Elder Committed by Greg Kroah-Hartman

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: default avatarAlex Elder <elder@linaro.org>
Signed-off-by: default avatarGreg Kroah-Hartman <greg@kroah.com>
parent dbb8894e
...@@ -404,3 +404,19 @@ struct gb_connection_handler gb_battery_connection_handler = { ...@@ -404,3 +404,19 @@ struct gb_connection_handler gb_battery_connection_handler = {
.connection_init = gb_battery_connection_init, .connection_init = gb_battery_connection_init,
.connection_exit = gb_battery_connection_exit, .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) ...@@ -277,17 +277,23 @@ static int __init gb_init(void)
goto error_operation; 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: error_operation:
gb_gbuf_exit(); gb_gbuf_exit();
error_gbuf: error_gbuf:
gb_ap_exit(); gb_ap_exit();
error_ap: error_ap:
bus_unregister(&greybus_bus_type); bus_unregister(&greybus_bus_type);
error_bus: error_bus:
gb_debugfs_cleanup(); gb_debugfs_cleanup();
......
...@@ -796,3 +796,19 @@ struct gb_connection_handler gb_gpio_connection_handler = { ...@@ -796,3 +796,19 @@ struct gb_connection_handler gb_gpio_connection_handler = {
.connection_init = gb_gpio_connection_init, .connection_init = gb_gpio_connection_init,
.connection_exit = gb_gpio_connection_exit, .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 { ...@@ -30,6 +30,7 @@ enum greybus_protocol {
GREYBUS_PROTOCOL_I2C = 0x03, GREYBUS_PROTOCOL_I2C = 0x03,
GREYBUS_PROTOCOL_UART = 0x04, GREYBUS_PROTOCOL_UART = 0x04,
GREYBUS_PROTOCOL_HID = 0x05, GREYBUS_PROTOCOL_HID = 0x05,
GREYBUS_PROTOCOL_SDIO = 0x06,
GREYBUS_PROTOCOL_BATTERY = 0x08, GREYBUS_PROTOCOL_BATTERY = 0x08,
GREYBUS_PROTOCOL_LED = 0x0e, GREYBUS_PROTOCOL_LED = 0x0e,
/* ... */ /* ... */
......
...@@ -522,3 +522,19 @@ struct gb_connection_handler gb_i2c_connection_handler = { ...@@ -522,3 +522,19 @@ struct gb_connection_handler gb_i2c_connection_handler = {
.connection_init = gb_i2c_connection_init, .connection_init = gb_i2c_connection_init,
.connection_exit = gb_i2c_connection_exit, .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) ...@@ -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 */ /* 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; struct gb_protocol *existing;
u8 id = protocol->id;
/* Initialize it speculatively */ u8 major = protocol->major;
protocol = kzalloc(sizeof(*protocol), GFP_KERNEL); u8 minor = protocol->minor;
if (!protocol)
return false;
protocol->id = id;
protocol->major = major;
protocol->minor = minor;
/* /*
* The protocols list is sorted first by protocol id (low to * 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) ...@@ -79,7 +73,6 @@ bool gb_protocol_register(u8 id, u8 major, u8 minor)
/* A matching protocol has already been registered */ /* A matching protocol has already been registered */
spin_unlock_irq(&gb_protocols_lock); spin_unlock_irq(&gb_protocols_lock);
kfree(protocol);
return false; return false;
} }
...@@ -94,7 +87,17 @@ bool gb_protocol_register(u8 id, u8 major, u8 minor) ...@@ -94,7 +87,17 @@ bool gb_protocol_register(u8 id, u8 major, u8 minor)
return true; 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) bool gb_protocol_deregister(struct gb_protocol *protocol)
{ {
u8 protocol_count = 0; u8 protocol_count = 0;
...@@ -108,7 +111,6 @@ bool gb_protocol_deregister(struct gb_protocol *protocol) ...@@ -108,7 +111,6 @@ bool gb_protocol_deregister(struct gb_protocol *protocol)
list_del(&protocol->links); list_del(&protocol->links);
} }
spin_unlock_irq(&gb_protocols_lock); spin_unlock_irq(&gb_protocols_lock);
kfree(protocol);
return protocol && !protocol_count; return protocol && !protocol_count;
} }
...@@ -158,3 +160,39 @@ void gb_protocol_put(struct gb_protocol *protocol) ...@@ -158,3 +160,39 @@ void gb_protocol_put(struct gb_protocol *protocol)
pr_err("protocol id %hhu version %hhu.%hhu not found\n", pr_err("protocol id %hhu version %hhu.%hhu not found\n",
protocol->id, major, minor); 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 { ...@@ -25,10 +25,33 @@ struct gb_protocol {
struct list_head links; /* global list */ 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); bool gb_protocol_deregister(struct gb_protocol *protocol);
struct gb_protocol *gb_protocol_get(u8 id, u8 major, u8 minor); struct gb_protocol *gb_protocol_get(u8 id, u8 major, u8 minor);
void gb_protocol_put(struct gb_protocol *protocol); 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 */ #endif /* __PROTOCOL_H */
...@@ -81,3 +81,19 @@ struct gb_connection_handler gb_sdio_connection_handler = { ...@@ -81,3 +81,19 @@ struct gb_connection_handler gb_sdio_connection_handler = {
.connection_init = gb_sdio_connection_init, .connection_init = gb_sdio_connection_init,
.connection_exit = gb_sdio_connection_exit, .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 = { ...@@ -524,3 +524,19 @@ struct gb_connection_handler gb_uart_connection_handler = {
.connection_init = gb_uart_connection_init, .connection_init = gb_uart_connection_init,
.connection_exit = gb_uart_connection_exit, .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);
}
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