diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 9bcda993685a..b1e933fc7044 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -143,6 +143,7 @@ struct gb_connection *gb_connection_create(struct gb_interface *interface, connection->interface = interface; /* XXX refcount? */ connection->interface_cport_id = cport_id; connection->protocol = protocol; + connection->state = GB_CONNECTION_STATE_DISABLED; spin_lock_irq(&gb_connections_lock); _gb_hd_connection_insert(hd, connection); @@ -217,13 +218,20 @@ void gb_connection_err(struct gb_connection *connection, const char *fmt, ...) */ int gb_connection_init(struct gb_connection *connection) { + int ret; + + /* Need to enable the connection to initialize it */ + connection->state = GB_CONNECTION_STATE_ENABLED; switch (connection->protocol) { case GREYBUS_PROTOCOL_I2C: - return gb_i2c_device_init(connection); + ret = gb_i2c_device_init(connection); + break; case GREYBUS_PROTOCOL_GPIO: - return gb_gpio_controller_init(connection); + ret = gb_gpio_controller_init(connection); + break; case GREYBUS_PROTOCOL_BATTERY: - return gb_battery_device_init(connection); + ret = gb_battery_device_init(connection); + break; case GREYBUS_PROTOCOL_CONTROL: case GREYBUS_PROTOCOL_AP: case GREYBUS_PROTOCOL_UART: @@ -233,13 +241,20 @@ int gb_connection_init(struct gb_connection *connection) default: gb_connection_err(connection, "unimplemented protocol %u", (u32)connection->protocol); + ret = -ENXIO; break; } - return -ENXIO; + + if (ret) + connection->state = GB_CONNECTION_STATE_ERROR; + + return ret; } 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); diff --git a/drivers/staging/greybus/connection.h b/drivers/staging/greybus/connection.h index b5901a1b1a74..a16e52a8ba18 100644 --- a/drivers/staging/greybus/connection.h +++ b/drivers/staging/greybus/connection.h @@ -13,6 +13,14 @@ #include "greybus.h" +enum gb_connection_state { + GB_CONNECTION_STATE_INVALID = 0, + GB_CONNECTION_STATE_DISABLED = 1, + GB_CONNECTION_STATE_ENABLED = 2, + GB_CONNECTION_STATE_ERROR = 3, + GB_CONNECTION_STATE_DESTROYING = 4, +}; + struct gb_connection { struct greybus_host_device *hd; struct gb_interface *interface; @@ -22,6 +30,7 @@ struct gb_connection { struct rb_node hd_node; struct list_head interface_links; enum greybus_protocol protocol; + enum gb_connection_state state; struct list_head operations; struct rb_root pending; /* awaiting reponse */ diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index afb42d5e1941..5d23d1977297 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -417,6 +417,9 @@ int gb_operation_request_send(struct gb_operation *operation, { int ret; + if (operation->connection->state != GB_CONNECTION_STATE_ENABLED) + return -ENOTCONN; + /* * XXX * I think the order of operations is going to be @@ -461,6 +464,9 @@ void gb_connection_operation_recv(struct gb_connection *connection, struct gbuf *gbuf; u16 msg_size; + if (connection->state != GB_CONNECTION_STATE_ENABLED) + return; + if (size > GB_OPERATION_MESSAGE_SIZE_MAX) { gb_connection_err(connection, "message too big"); return;