}
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)
{
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);
{
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)
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);
}
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);