Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7aefe791 authored by Johan Hovold's avatar Johan Hovold Committed by Greg Kroah-Hartman
Browse files

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: default avatarViresh Kumar <viresh.kumar@linaro.org>
Signed-off-by: default avatarJohan Hovold <johan@hovoldconsulting.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@google.com>
parent 898d75f4
Loading
Loading
Loading
Loading
+21 −0
Original line number Diff line number Diff line
@@ -654,6 +654,27 @@ void gb_connection_disable(struct gb_connection *connection)
}
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)
{
+1 −0
Original line number Diff line number Diff line
@@ -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);
+4 −1
Original line number Diff line number Diff line
@@ -316,6 +316,9 @@ void gb_control_disable(struct gb_control *control)
{
	dev_dbg(&control->connection->intf->dev, "%s\n", __func__);

	if (control->intf->disconnected)
		gb_connection_disable_forced(control->connection);
	else
		gb_connection_disable(control->connection);
}

+1 −1
Original line number Diff line number Diff line
@@ -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);
	}
+0 −7
Original line number Diff line number Diff line
@@ -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);