diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 56588f357b20..8ae099d20b48 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -396,6 +396,18 @@ int gb_connection_enable(struct gb_connection *connection, if (connection->state == GB_CONNECTION_STATE_ENABLED) goto out_unlock; + if (connection->state == GB_CONNECTION_STATE_ENABLED_TX) { + if (!handler) + goto out_unlock; + + spin_lock_irq(&connection->lock); + connection->handler = handler; + connection->state = GB_CONNECTION_STATE_ENABLED; + spin_unlock_irq(&connection->lock); + + goto out_unlock; + } + ret = gb_connection_hd_cport_enable(connection); if (ret) goto err_unlock; @@ -406,7 +418,10 @@ int gb_connection_enable(struct gb_connection *connection, spin_lock_irq(&connection->lock); connection->handler = handler; - connection->state = GB_CONNECTION_STATE_ENABLED; + if (handler) + connection->state = GB_CONNECTION_STATE_ENABLED; + else + connection->state = GB_CONNECTION_STATE_ENABLED_TX; spin_unlock_irq(&connection->lock); ret = gb_connection_control_connected(connection); @@ -422,6 +437,7 @@ err_svc_destroy: spin_lock_irq(&connection->lock); connection->state = GB_CONNECTION_STATE_DISABLED; gb_connection_cancel_operations(connection, -ESHUTDOWN); + connection->handler = NULL; spin_unlock_irq(&connection->lock); gb_connection_svc_connection_destroy(connection); @@ -446,6 +462,7 @@ void gb_connection_disable(struct gb_connection *connection) spin_lock_irq(&connection->lock); connection->state = GB_CONNECTION_STATE_DISABLED; gb_connection_cancel_operations(connection, -ESHUTDOWN); + connection->handler = NULL; spin_unlock_irq(&connection->lock); gb_connection_svc_connection_destroy(connection); diff --git a/drivers/staging/greybus/connection.h b/drivers/staging/greybus/connection.h index e7c6feb76e80..ab2556d81273 100644 --- a/drivers/staging/greybus/connection.h +++ b/drivers/staging/greybus/connection.h @@ -16,7 +16,8 @@ enum gb_connection_state { GB_CONNECTION_STATE_INVALID = 0, GB_CONNECTION_STATE_DISABLED = 1, - GB_CONNECTION_STATE_ENABLED = 2, + GB_CONNECTION_STATE_ENABLED_TX = 2, + GB_CONNECTION_STATE_ENABLED = 3, }; struct gb_operation; @@ -70,6 +71,10 @@ static inline bool gb_connection_is_static(struct gb_connection *connection) int gb_connection_enable(struct gb_connection *connection, gb_request_handler_t handler); +static inline int gb_connection_enable_tx(struct gb_connection *connection) +{ + return gb_connection_enable(connection, NULL); +} void gb_connection_disable(struct gb_connection *connection); int gb_connection_legacy_init(struct gb_connection *connection); diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index 4dc79cb12397..d6b3d1f22b28 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -47,7 +47,9 @@ static int gb_operation_get_active(struct gb_operation *operation) spin_lock_irqsave(&connection->lock, flags); - if (connection->state != GB_CONNECTION_STATE_ENABLED) { + if (connection->state != GB_CONNECTION_STATE_ENABLED && + connection->state != GB_CONNECTION_STATE_ENABLED_TX && + !gb_operation_is_incoming(operation)) { spin_unlock_irqrestore(&connection->lock, flags); return -ENOTCONN; } @@ -906,7 +908,8 @@ void gb_connection_recv(struct gb_connection *connection, size_t msg_size; u16 operation_id; - if (connection->state != GB_CONNECTION_STATE_ENABLED) { + if (connection->state != GB_CONNECTION_STATE_ENABLED && + connection->state != GB_CONNECTION_STATE_ENABLED_TX) { dev_warn(dev, "%s: dropping %zu received bytes\n", connection->name, size); return;