From 574341c67213afdc9dcb5aefb4f6fa84644438bb Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Thu, 16 Oct 2014 06:35:35 -0500 Subject: [PATCH] greybus: add device initialization Set up the infrastructure for initializing connections based on their protocol. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman --- drivers/staging/greybus/connection.c | 24 ++++++++++++++++ drivers/staging/greybus/connection.h | 2 ++ drivers/staging/greybus/core.c | 8 ++++-- drivers/staging/greybus/greybus.h | 2 ++ drivers/staging/greybus/interface.c | 15 ++++++++++ drivers/staging/greybus/interface.h | 2 ++ drivers/staging/greybus/module.c | 41 ++++++++++++++++++---------- drivers/staging/greybus/module.h | 2 ++ 8 files changed, 79 insertions(+), 17 deletions(-) diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 740f491bf5fc..0143a4f6bd12 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -191,3 +191,27 @@ void gb_connection_err(struct gb_connection *connection, const char *fmt, ...) va_end(args); } + +/* + * XXX Protocols should have a set of function pointers: + * ->init (called here, to initialize the device) + * ->input_handler + * ->exit (reverse of init) + */ +int gb_connection_init(struct gb_connection *connection) +{ + switch (connection->protocol) { + case GREYBUS_PROTOCOL_I2C: + case GREYBUS_PROTOCOL_CONTROL: + case GREYBUS_PROTOCOL_AP: + case GREYBUS_PROTOCOL_GPIO: + case GREYBUS_PROTOCOL_UART: + case GREYBUS_PROTOCOL_HID: + case GREYBUS_PROTOCOL_VENDOR: + default: + gb_connection_err(connection, "unimplemented protocol %u", + (u32)connection->protocol); + break; + } + return -ENXIO; +} diff --git a/drivers/staging/greybus/connection.h b/drivers/staging/greybus/connection.h index 5862ce05933e..bb22c52c2f01 100644 --- a/drivers/staging/greybus/connection.h +++ b/drivers/staging/greybus/connection.h @@ -34,6 +34,8 @@ struct gb_connection *gb_connection_create(struct gb_interface *interface, u16 cport_id, enum greybus_protocol protocol); void gb_connection_destroy(struct gb_connection *connection); +int gb_connection_init(struct gb_connection *connection); + struct gb_connection *gb_hd_connection_find(struct greybus_host_device *hd, u16 cport_id); diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index b5f666a6255e..38f867db9411 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -182,8 +182,11 @@ void gb_add_module(struct greybus_host_device *hd, u8 module_id, dev_set_name(&gmod->dev, "%d", module_id); retval = device_add(&gmod->dev); - if (!retval) - return; /* Success */ + if (retval) + goto error; + + gb_module_interfaces_init(gmod); + return; error: gb_module_destroy(gmod); @@ -253,7 +256,6 @@ void greybus_remove_hd(struct greybus_host_device *hd) } EXPORT_SYMBOL_GPL(greybus_remove_hd); - static int __init gb_init(void) { int retval; diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index 1970106d70a0..d92ba5178cf1 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -265,6 +265,8 @@ void gb_deregister_cport_complete(u16 cport_id); extern const struct attribute_group *greybus_module_groups[]; +int gb_i2c_device_init(struct gb_connection *connection); + int gb_tty_init(void); void gb_tty_exit(void); diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c index b9dd93093cc6..0c2fdd3f7ea2 100644 --- a/drivers/staging/greybus/interface.c +++ b/drivers/staging/greybus/interface.c @@ -57,3 +57,18 @@ void gb_interface_destroy(struct gb_interface *interface) /* kref_put(gmod); */ kfree(interface); } + +int gb_interface_connections_init(struct gb_interface *interface) +{ + struct gb_connection *connection; + int ret = 0; + + list_for_each_entry(connection, &interface->connections, + interface_links) { + ret = gb_connection_init(connection); + if (ret) + break; + } + + return ret; +} diff --git a/drivers/staging/greybus/interface.h b/drivers/staging/greybus/interface.h index 9c9ffe7715a5..1019a981f5f6 100644 --- a/drivers/staging/greybus/interface.h +++ b/drivers/staging/greybus/interface.h @@ -22,4 +22,6 @@ struct gb_interface { struct gb_interface *gb_interface_create(struct gb_module *gmod, u8 module_id); void gb_interface_destroy(struct gb_interface *interface); +int gb_interface_connections_init(struct gb_interface *interface); + #endif /* __INTERFACE_H */ diff --git a/drivers/staging/greybus/module.c b/drivers/staging/greybus/module.c index 1970e7b01081..699cd003e367 100644 --- a/drivers/staging/greybus/module.c +++ b/drivers/staging/greybus/module.c @@ -55,39 +55,52 @@ const struct greybus_module_id *gb_module_match_id(struct gb_module *gmod, */ struct gb_module *gb_module_create(struct greybus_host_device *hd, u8 module_id) { - struct gb_module *module; + struct gb_module *gmod; - module = kzalloc(sizeof(*module), GFP_KERNEL); - if (!module) + gmod = kzalloc(sizeof(*gmod), GFP_KERNEL); + if (!gmod) return NULL; - module->hd = hd; /* XXX refcount? */ - module->module_id = module_id; - INIT_LIST_HEAD(&module->interfaces); + gmod->hd = hd; /* XXX refcount? */ + gmod->module_id = module_id; + INIT_LIST_HEAD(&gmod->interfaces); spin_lock_irq(&gb_modules_lock); - list_add_tail(&module->links, &hd->modules); + list_add_tail(&gmod->links, &hd->modules); spin_unlock_irq(&gb_modules_lock); - return module; + return gmod; } /* * Tear down a previously set up module. */ -void gb_module_destroy(struct gb_module *module) +void gb_module_destroy(struct gb_module *gmod) { - if (WARN_ON(!module)) + if (WARN_ON(!gmod)) return; - kfree(module->product_string); - kfree(module->vendor_string); + kfree(gmod->product_string); + kfree(gmod->vendor_string); spin_lock_irq(&gb_modules_lock); - list_del(&module->links); + list_del(&gmod->links); spin_unlock_irq(&gb_modules_lock); /* kref_put(module->hd); */ - kfree(module); + kfree(gmod); +} + +void gb_module_interfaces_init(struct gb_module *gmod) +{ + struct gb_interface *interface; + int ret = 0; + + list_for_each_entry(interface, &gmod->interfaces, links) { + ret = gb_interface_connections_init(interface); + if (ret) + dev_err(gmod->hd->parent, + "module interface init error %d\n", ret); + } } diff --git a/drivers/staging/greybus/module.h b/drivers/staging/greybus/module.h index 7b01950fa36e..114f15750380 100644 --- a/drivers/staging/greybus/module.h +++ b/drivers/staging/greybus/module.h @@ -62,4 +62,6 @@ struct gb_module *gb_module_create(struct greybus_host_device *hd, u8 module_id); void gb_module_destroy(struct gb_module *module); +void gb_module_interfaces_init(struct gb_module *gmod); + #endif /* __MODULE_H */ -- 2.45.2