greybus: core: avoid I/O to disconnected interfaces
Add new helper to disable connections to interfaces that have already been disconnected (e.g. forcibly removed). The connection tear-down procedure differs enough depending on whether the interface is still present or already gone to warrant a dedicated helper. This will become more obvious with the new tear-down procedure, which involves I/O on the connection being tore down. This also simplifies handling of the legacy bootrom, which does not support the new tear-down operations. Specifically, this allows us to remove the early control-connection tear down during interface disable, and also avoids some error messages currently printed during legacy mode switch (i.e. bootrom boot-over-UniPro) and forcible removal. Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
This commit is contained in:
parent
898d75f4aa
commit
7aefe7918f
|
@ -654,6 +654,27 @@ out_unlock:
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(gb_connection_disable);
|
||||
|
||||
/* Disable a connection without communicating with the remote end. */
|
||||
void gb_connection_disable_forced(struct gb_connection *connection)
|
||||
{
|
||||
mutex_lock(&connection->mutex);
|
||||
|
||||
if (connection->state == GB_CONNECTION_STATE_DISABLED)
|
||||
goto out_unlock;
|
||||
|
||||
spin_lock_irq(&connection->lock);
|
||||
connection->state = GB_CONNECTION_STATE_DISABLED;
|
||||
gb_connection_cancel_operations(connection, -ESHUTDOWN);
|
||||
spin_unlock_irq(&connection->lock);
|
||||
|
||||
gb_connection_svc_connection_destroy(connection);
|
||||
gb_connection_hd_cport_disable(connection);
|
||||
|
||||
out_unlock:
|
||||
mutex_unlock(&connection->mutex);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(gb_connection_disable_forced);
|
||||
|
||||
/* Caller must have disabled the connection before destroying it. */
|
||||
void gb_connection_destroy(struct gb_connection *connection)
|
||||
{
|
||||
|
|
|
@ -80,6 +80,7 @@ int gb_connection_enable(struct gb_connection *connection);
|
|||
int gb_connection_enable_tx(struct gb_connection *connection);
|
||||
void gb_connection_disable_rx(struct gb_connection *connection);
|
||||
void gb_connection_disable(struct gb_connection *connection);
|
||||
void gb_connection_disable_forced(struct gb_connection *connection);
|
||||
|
||||
void greybus_data_rcvd(struct gb_host_device *hd, u16 cport_id,
|
||||
u8 *data, size_t length);
|
||||
|
|
|
@ -316,7 +316,10 @@ void gb_control_disable(struct gb_control *control)
|
|||
{
|
||||
dev_dbg(&control->connection->intf->dev, "%s\n", __func__);
|
||||
|
||||
gb_connection_disable(control->connection);
|
||||
if (control->intf->disconnected)
|
||||
gb_connection_disable_forced(control->connection);
|
||||
else
|
||||
gb_connection_disable(control->connection);
|
||||
}
|
||||
|
||||
int gb_control_add(struct gb_control *control)
|
||||
|
|
|
@ -189,7 +189,7 @@ static int greybus_remove(struct device *dev)
|
|||
|
||||
list_for_each_entry(connection, &bundle->connections, bundle_links) {
|
||||
if (bundle->intf->disconnected)
|
||||
gb_connection_disable(connection);
|
||||
gb_connection_disable_forced(connection);
|
||||
else
|
||||
gb_connection_disable_rx(connection);
|
||||
}
|
||||
|
|
|
@ -671,13 +671,6 @@ void gb_interface_disable(struct gb_interface *intf)
|
|||
|
||||
trace_gb_interface_disable(intf);
|
||||
|
||||
/*
|
||||
* Disable the control-connection early to avoid operation timeouts
|
||||
* when the interface is already gone.
|
||||
*/
|
||||
if (intf->disconnected)
|
||||
gb_control_disable(intf->control);
|
||||
|
||||
list_for_each_entry_safe(bundle, next, &intf->bundles, links)
|
||||
gb_bundle_destroy(bundle);
|
||||
|
||||
|
|
Loading…
Reference in New Issue