greybus: Merge branch 'master' into driver_model_rework

This commit is contained in:
Greg Kroah-Hartman 2014-10-28 10:30:18 +08:00
commit a25f375cf7
13 changed files with 118 additions and 155 deletions

View File

@ -359,7 +359,7 @@ static enum power_supply_property battery_props[] = {
POWER_SUPPLY_PROP_VOLTAGE_NOW,
};
int gb_battery_device_init(struct gb_connection *connection)
static int gb_battery_connection_init(struct gb_connection *connection)
{
struct gb_battery *gb;
struct power_supply *b;
@ -369,7 +369,7 @@ int gb_battery_device_init(struct gb_connection *connection)
if (!gb)
return -ENOMEM;
gb->connection = connection; // FIXME refcount!
gb->connection = connection;
connection->private = gb;
/* Check the version */
@ -397,7 +397,7 @@ int gb_battery_device_init(struct gb_connection *connection)
return 0;
}
void gb_battery_device_exit(struct gb_connection *connection)
static void gb_battery_connection_exit(struct gb_connection *connection)
{
struct gb_battery *gb = connection->private;
@ -405,29 +405,7 @@ void gb_battery_device_exit(struct gb_connection *connection)
kfree(gb);
}
void gb_battery_disconnect(struct gb_module *gmod)
{
#if 0
struct gb_battery *gb;
gb = gmod->gb_battery;
if (!gb)
return;
power_supply_unregister(&gb->bat);
kfree(gb);
#endif
}
#if 0
static struct greybus_driver battery_gb_driver = {
.probe = gb_battery_probe,
.disconnect = gb_battery_disconnect,
.id_table = id_table,
struct gb_connection_handler gb_battery_connection_handler = {
.connection_init = gb_battery_connection_init,
.connection_exit = gb_battery_connection_exit,
};
module_greybus_driver(battery_gb_driver);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Greg Kroah-Hartman <gregkh@linuxfoundation.org>");
#endif

View File

@ -170,7 +170,7 @@ struct gb_connection *gb_connection_create(struct gb_interface *interface,
return NULL;
}
connection->interface = interface; /* XXX refcount? */
connection->interface = interface;
connection->interface_cport_id = cport_id;
connection->protocol = protocol;
connection->state = GB_CONNECTION_STATE_DISABLED;
@ -267,17 +267,19 @@ int gb_connection_init(struct gb_connection *connection)
connection->state = GB_CONNECTION_STATE_ENABLED;
switch (connection->protocol) {
case GREYBUS_PROTOCOL_I2C:
ret = gb_i2c_device_init(connection);
connection->handler = &gb_i2c_connection_handler;
break;
case GREYBUS_PROTOCOL_GPIO:
ret = gb_gpio_controller_init(connection);
connection->handler = &gb_gpio_connection_handler;
break;
case GREYBUS_PROTOCOL_BATTERY:
ret = gb_battery_device_init(connection);
connection->handler = &gb_battery_connection_handler;
break;
case GREYBUS_PROTOCOL_UART:
connection->handler = &gb_uart_connection_handler;
break;
case GREYBUS_PROTOCOL_CONTROL:
case GREYBUS_PROTOCOL_AP:
case GREYBUS_PROTOCOL_UART:
case GREYBUS_PROTOCOL_HID:
case GREYBUS_PROTOCOL_LED:
case GREYBUS_PROTOCOL_VENDOR:
@ -296,26 +298,10 @@ int gb_connection_init(struct gb_connection *connection)
void gb_connection_exit(struct gb_connection *connection)
{
connection->state = GB_CONNECTION_STATE_DESTROYING;
switch (connection->protocol) {
case GREYBUS_PROTOCOL_I2C:
gb_i2c_device_exit(connection);
break;
case GREYBUS_PROTOCOL_GPIO:
gb_gpio_controller_exit(connection);
break;
case GREYBUS_PROTOCOL_BATTERY:
gb_battery_device_exit(connection);
break;
case GREYBUS_PROTOCOL_CONTROL:
case GREYBUS_PROTOCOL_AP:
case GREYBUS_PROTOCOL_UART:
case GREYBUS_PROTOCOL_HID:
case GREYBUS_PROTOCOL_VENDOR:
default:
gb_connection_err(connection, "unimplemented protocol %u",
(u32)connection->protocol);
break;
if (!connection->handler) {
gb_connection_err(connection, "uninitialized connection");
return;
}
connection->state = GB_CONNECTION_STATE_DESTROYING;
connection->handler->connection_exit(connection);
}

View File

@ -21,6 +21,15 @@ enum gb_connection_state {
GB_CONNECTION_STATE_DESTROYING = 4,
};
struct gb_connection;
typedef int (*gb_connection_init_t)(struct gb_connection *);
typedef void (*gb_connection_exit_t)(struct gb_connection *);
struct gb_connection_handler {
gb_connection_init_t connection_init;
gb_connection_exit_t connection_exit;
};
struct gb_connection {
struct greybus_host_device *hd;
struct gb_interface *interface;
@ -37,6 +46,8 @@ struct gb_connection {
struct rb_root pending; /* awaiting reponse */
atomic_t op_cycle;
struct gb_connection_handler *handler;
void *private;
};
#define to_gb_connection(d) container_of(d, struct gb_connection, dev)

View File

@ -282,17 +282,8 @@ static int __init gb_init(void)
goto error_operation;
}
retval = gb_tty_init();
if (retval) {
pr_err("gb_tty_init failed\n");
goto error_tty;
}
return 0;
error_tty:
gb_operation_exit();
error_operation:
gb_gbuf_exit();
@ -310,7 +301,6 @@ error_bus:
static void __exit gb_exit(void)
{
gb_tty_exit();
gb_operation_exit();
gb_gbuf_exit();
gb_ap_exit();

View File

@ -29,7 +29,6 @@ struct gb_gpio_controller {
struct gb_gpio_line *lines;
struct gpio_chip chip;
struct gpio_chip *gpio;
};
#define gpio_chip_to_gb_gpio_controller(chip) \
container_of(chip, struct gb_gpio_controller, chip)
@ -733,7 +732,7 @@ static int gb_gpio_controller_setup(struct gb_gpio_controller *gb_gpio_controlle
return ret;
}
int gb_gpio_controller_init(struct gb_connection *connection)
static int gb_gpio_connection_init(struct gb_connection *connection)
{
struct gb_gpio_controller *gb_gpio_controller;
struct gpio_chip *gpio;
@ -781,7 +780,7 @@ out_err:
return ret;
}
void gb_gpio_controller_exit(struct gb_connection *connection)
static void gb_gpio_connection_exit(struct gb_connection *connection)
{
struct gb_gpio_controller *gb_gpio_controller = connection->private;
@ -793,6 +792,11 @@ void gb_gpio_controller_exit(struct gb_connection *connection)
kfree(gb_gpio_controller);
}
struct gb_connection_handler gb_gpio_connection_handler = {
.connection_init = gb_gpio_connection_init,
.connection_exit = gb_gpio_connection_exit,
};
#if 0
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Greybus GPIO driver");

View File

@ -151,7 +151,6 @@ struct gbuf {
struct gb_i2c_device;
struct gb_gpio_device;
struct gb_sdio_host;
struct gb_tty;
struct gb_usb_device;
struct gb_battery;
@ -266,17 +265,14 @@ void gb_deregister_cport_complete(u16 cport_id);
extern struct bus_type greybus_bus_type;
extern const struct attribute_group *greybus_module_groups[];
int gb_i2c_device_init(struct gb_connection *connection);
void gb_i2c_device_exit(struct gb_connection *connection);
extern struct gb_connection_handler gb_i2c_connection_handler;
extern struct gb_connection_handler gb_gpio_connection_handler;
extern struct gb_connection_handler gb_battery_connection_handler;
extern struct gb_connection_handler gb_uart_connection_handler;
extern struct gb_connection_handler gb_sdio_connection_handler;
int gb_battery_device_init(struct gb_connection *connection);
void gb_battery_device_exit(struct gb_connection *connection);
int gb_gpio_controller_init(struct gb_connection *connection);
void gb_gpio_controller_exit(struct gb_connection *connection);
int gb_tty_init(void);
void gb_tty_exit(void);
int gb_uart_device_init(struct gb_connection *connection);
void gb_uart_device_exit(struct gb_connection *connection);
int svc_set_route_send(struct gb_interface *interface,
struct greybus_host_device *hd);

View File

@ -22,7 +22,7 @@ struct gb_i2c_device {
u16 timeout_msec;
u8 retries;
struct i2c_adapter *adapter;
struct i2c_adapter adapter;
};
/* Version of the Greybus i2c protocol we support */
@ -466,10 +466,10 @@ static int gb_i2c_device_setup(struct gb_i2c_device *gb_i2c_dev)
return gb_i2c_timeout_operation(gb_i2c_dev, GB_I2C_TIMEOUT_DEFAULT);
}
int gb_i2c_device_init(struct gb_connection *connection)
static int gb_i2c_connection_init(struct gb_connection *connection)
{
struct gb_i2c_device *gb_i2c_dev;
struct i2c_adapter *adapter = NULL;
struct i2c_adapter *adapter;
int ret;
gb_i2c_dev = kzalloc(sizeof(*gb_i2c_dev), GFP_KERNEL);
@ -482,13 +482,8 @@ int gb_i2c_device_init(struct gb_connection *connection)
if (ret)
goto out_err;
/* Looks good; allocate and set up our i2c adapter */
adapter = kzalloc(sizeof(*adapter), GFP_KERNEL);
if (!adapter) {
ret = -ENOMEM;
goto out_err;
}
/* Looks good; up our i2c adapter */
adapter = &gb_i2c_dev->adapter;
adapter->owner = THIS_MODULE;
adapter->class = I2C_CLASS_HWMON | I2C_CLASS_SPD;
adapter->algo = &gb_i2c_algorithm;
@ -504,28 +499,30 @@ int gb_i2c_device_init(struct gb_connection *connection)
if (ret)
goto out_err;
gb_i2c_dev->adapter = adapter;
connection->private = gb_i2c_dev;
return 0;
out_err:
kfree(adapter);
/* kref_put(gb_i2c_dev->connection) */
kfree(gb_i2c_dev);
return ret;
}
void gb_i2c_device_exit(struct gb_connection *connection)
static void gb_i2c_connection_exit(struct gb_connection *connection)
{
struct gb_i2c_device *gb_i2c_dev = connection->private;
i2c_del_adapter(gb_i2c_dev->adapter);
kfree(gb_i2c_dev->adapter);
i2c_del_adapter(&gb_i2c_dev->adapter);
/* kref_put(gb_i2c_dev->connection) */
kfree(gb_i2c_dev);
}
struct gb_connection_handler gb_i2c_connection_handler = {
.connection_init = gb_i2c_connection_init,
.connection_exit = gb_i2c_connection_exit,
};
#if 0
module_greybus_driver(i2c_gb_driver);
MODULE_LICENSE("GPL");

View File

@ -61,7 +61,7 @@ gb_interface_create(struct gb_module *gmod, u8 interface_id)
if (!interface)
return NULL;
interface->gmod = gmod; /* XXX refcount? */
interface->gmod = gmod;
interface->id = interface_id;
interface->device_id = 0xff; /* Invalid device id to start with */
INIT_LIST_HEAD(&interface->connections);

View File

@ -48,4 +48,19 @@ static inline void gb_gpiochip_remove(struct gpio_chip *chip)
}
#endif
/*
* ATTRIBUTE_GROUPS showed up in 3.11-rc2, but we need to build on 3.10, so add
* it here.
*/
#if LINUX_VERSION_CODE < KERNEL_VERSION(3,11,0)
#define ATTRIBUTE_GROUPS(name) \
static const struct attribute_group name##_group = { \
.attrs = name##_attrs, \
}; \
static const struct attribute_group *name##_groups[] = { \
&name##_group, \
NULL, \
}
#endif
#endif /* __GREYBUS_KERNEL_VER_H */

View File

@ -82,7 +82,7 @@ struct gb_module *gb_module_create(struct greybus_host_device *hd, u8 module_id)
return NULL;
gmod->hd = hd; /* XXX refcount? */
gmod->module_id = module_id; /* XXX check for dups */
gmod->module_id = module_id;
INIT_LIST_HEAD(&gmod->interfaces);
spin_lock_irq(&gb_modules_lock);

View File

@ -363,7 +363,7 @@ struct gb_operation *gb_operation_create(struct gb_connection *connection,
operation = kmem_cache_zalloc(gb_operation_cache, gfp_flags);
if (!operation)
return NULL;
operation->connection = connection; /* XXX refcount? */
operation->connection = connection;
operation->request = gb_operation_gbuf_create(operation, type,
request_size,

View File

@ -13,6 +13,7 @@
#include "greybus.h"
struct gb_sdio_host {
struct gb_connection *connection;
struct mmc_host *mmc;
struct mmc_request *mrq;
// FIXME - some lock?
@ -45,13 +46,12 @@ static const struct mmc_host_ops gb_sd_ops = {
.get_ro = gb_sd_get_ro,
};
int gb_sdio_probe(struct gb_module *gmod,
const struct greybus_module_id *id)
static int gb_sdio_connection_init(struct gb_connection *connection)
{
struct mmc_host *mmc;
struct gb_sdio_host *host;
mmc = mmc_alloc_host(sizeof(struct gb_sdio_host), &gmod->dev);
mmc = mmc_alloc_host(sizeof(struct gb_sdio_host), &connection->dev);
if (!mmc)
return -ENOMEM;
@ -60,36 +60,29 @@ int gb_sdio_probe(struct gb_module *gmod,
mmc->ops = &gb_sd_ops;
// FIXME - set up size limits we can handle.
// FIXME - register the host controller.
// gmod->gb_sdio_host = host;
host->connection = connection;
connection->private = host;
return 0;
}
void gb_sdio_disconnect(struct gb_module *gmod)
static void gb_sdio_connection_exit(struct gb_connection *connection)
{
#if 0
struct mmc_host *mmc;
struct gb_sdio_host *host;
host = gmod->gb_sdio_host;
host = connection->private;
if (!host)
return;
mmc = host->mmc;
mmc_remove_host(mmc);
mmc_free_host(mmc);
#endif
connection->private = NULL;
}
#if 0
static struct greybus_driver sd_gb_driver = {
.probe = gb_sdio_probe,
.disconnect = gb_sdio_disconnect,
.id_table = id_table,
struct gb_connection_handler gb_sdio_connection_handler = {
.connection_init = gb_sdio_connection_init,
.connection_exit = gb_sdio_connection_exit,
};
module_greybus_driver(sd_gb_driver);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Greybus SD/MMC Host driver");
MODULE_AUTHOR("Greg Kroah-Hartman <gregkh@linuxfoundation.org>");
#endif

View File

@ -35,7 +35,7 @@
struct gb_tty {
struct tty_port port;
struct gb_module *gmod;
struct gb_connection *connection;
u16 cport_id;
unsigned int minor;
unsigned char clocal;
@ -59,6 +59,10 @@ static const struct greybus_module_id id_table[] = {
static struct tty_driver *gb_tty_driver;
static DEFINE_IDR(tty_minors);
static DEFINE_MUTEX(table_lock);
static atomic_t reference_count = ATOMIC_INIT(0);
static int gb_tty_init(void);
static void gb_tty_exit(void);
static struct gb_tty *get_gb_by_minor(unsigned minor)
{
@ -386,14 +390,22 @@ static const struct tty_operations gb_ops = {
};
int gb_tty_probe(struct gb_module *gmod,
const struct greybus_module_id *id)
static int gb_uart_connection_init(struct gb_connection *connection)
{
struct gb_tty *gb_tty;
struct device *tty_dev;
int retval;
int minor;
/* First time here, initialize the tty structures */
if (atomic_inc_return(&reference_count) == 1) {
retval = gb_tty_init();
if (retval) {
atomic_dec(&reference_count);
return retval;
}
}
gb_tty = kzalloc(sizeof(*gb_tty), GFP_KERNEL);
if (!gb_tty)
return -ENOMEM;
@ -401,14 +413,14 @@ int gb_tty_probe(struct gb_module *gmod,
minor = alloc_minor(gb_tty);
if (minor < 0) {
if (minor == -ENOSPC) {
dev_err(&gmod->dev, "no more free minor numbers\n");
dev_err(&connection->dev, "no more free minor numbers\n");
return -ENODEV;
}
return minor;
}
gb_tty->minor = minor;
gb_tty->gmod = gmod;
gb_tty->connection = connection;
spin_lock_init(&gb_tty->write_lock);
spin_lock_init(&gb_tty->read_lock);
init_waitqueue_head(&gb_tty->wioctl);
@ -416,10 +428,10 @@ int gb_tty_probe(struct gb_module *gmod,
/* FIXME - allocate gb buffers */
gmod->gb_tty = gb_tty;
connection->private = gb_tty;
tty_dev = tty_port_register_device(&gb_tty->port, gb_tty_driver, minor,
&gmod->dev);
&connection->dev);
if (IS_ERR(tty_dev)) {
retval = PTR_ERR(tty_dev);
goto error;
@ -427,14 +439,14 @@ int gb_tty_probe(struct gb_module *gmod,
return 0;
error:
gmod->gb_tty = NULL;
connection->private = NULL;
release_minor(gb_tty);
return retval;
}
void gb_tty_disconnect(struct gb_module *gmod)
static void gb_uart_connection_exit(struct gb_connection *connection)
{
struct gb_tty *gb_tty = gmod->gb_tty;
struct gb_tty *gb_tty = connection->private;
struct tty_struct *tty;
if (!gb_tty)
@ -444,7 +456,7 @@ void gb_tty_disconnect(struct gb_module *gmod)
gb_tty->disconnected = true;
wake_up_all(&gb_tty->wioctl);
gmod->gb_tty = NULL;
connection->private = NULL;
mutex_unlock(&gb_tty->mutex);
tty = tty_port_tty_get(&gb_tty->port);
@ -461,17 +473,13 @@ void gb_tty_disconnect(struct gb_module *gmod)
tty_port_put(&gb_tty->port);
kfree(gb_tty);
/* If last device is gone, tear down the tty structures */
if (atomic_dec_return(&reference_count) == 0)
gb_tty_exit();
}
#if 0
static struct greybus_driver tty_gb_driver = {
.probe = gb_tty_probe,
.disconnect = gb_tty_disconnect,
.id_table = id_table,
};
#endif
int __init gb_tty_init(void)
static int gb_tty_init(void)
{
int retval = 0;
@ -499,40 +507,25 @@ int __init gb_tty_init(void)
goto fail_put_gb_tty;
}
#if 0
retval = greybus_register(&tty_gb_driver);
if (retval) {
pr_err("Can not register greybus driver.\n");
goto fail_unregister_gb_tty;
}
#endif
return 0;
/* fail_unregister_gb_tty: */
tty_unregister_driver(gb_tty_driver);
fail_put_gb_tty:
put_tty_driver(gb_tty_driver);
fail_unregister_dev:
return retval;
}
void __exit gb_tty_exit(void)
static void gb_tty_exit(void)
{
int major = MAJOR(gb_tty_driver->major);
int minor = gb_tty_driver->minor_start;
#if 0
greybus_deregister(&tty_gb_driver);
#endif
tty_unregister_driver(gb_tty_driver);
put_tty_driver(gb_tty_driver);
unregister_chrdev_region(MKDEV(major, minor), GB_NUM_MINORS);
}
#if 0
module_init(gb_tty_init);
module_exit(gb_tty_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Greg Kroah-Hartman <gregkh@linuxfoundation.org>");
#endif
struct gb_connection_handler gb_uart_connection_handler = {
.connection_init = gb_uart_connection_init,
.connection_exit = gb_uart_connection_exit,
};