}
/*
- * Enable an interface by enabling its control connection and fetching the
- * manifest and other information over it.
+ * Enable an interface by enabling its control connection, fetching the
+ * manifest and other information over it, and finally registering its child
+ * devices.
*/
int gb_interface_enable(struct gb_interface *intf)
{
if (ret)
goto err_destroy_bundles;
+ /* Register the control device and any bundles */
+ ret = gb_control_add(intf->control);
+ if (ret)
+ goto err_destroy_bundles;
+
+ list_for_each_entry_safe_reverse(bundle, tmp, &intf->bundles, links) {
+ ret = gb_bundle_add(bundle);
+ if (ret) {
+ gb_bundle_destroy(bundle);
+ continue;
+ }
+ }
+
kfree(manifest);
intf->enabled = true;
intf->enabled = false;
}
-/* Register an interface and its bundles. */
+/* Register an interface. */
int gb_interface_add(struct gb_interface *intf)
{
- struct gb_bundle *bundle, *tmp;
int ret;
ret = device_add(&intf->dev);
dev_info(&intf->dev, "DDBL1 Manufacturer=0x%08x, Product=0x%08x\n",
intf->ddbl1_manufacturer_id, intf->ddbl1_product_id);
- /* NOTE: ignoring errors for now */
- gb_control_add(intf->control);
-
- list_for_each_entry_safe_reverse(bundle, tmp, &intf->bundles, links) {
- ret = gb_bundle_add(bundle);
- if (ret) {
- gb_bundle_destroy(bundle);
- continue;
- }
- }
-
return 0;
}
struct gb_host_device *hd = connection->hd;
struct gb_interface *intf;
u8 intf_id;
- u32 vendor_id = 0;
- u32 product_id = 0;
int ret;
/* The request message size has already been verified. */
intf = gb_interface_find(hd, intf_id);
if (intf) {
- /* HACK: Save Ara VID/PID for ES2 hack below */
- vendor_id = intf->vendor_id;
- product_id = intf->product_id;
-
- /*
- * We have received a hotplug request for an interface that
- * already exists.
- *
- * This can happen in cases like:
- * - bootrom loading the firmware image and booting into that,
- * which only generates a hotplug event. i.e. no hot-unplug
- * event.
- * - Or the firmware on the module crashed and sent hotplug
- * request again to the SVC, which got propagated to AP.
- *
- * Remove the interface and add it again, and let user know
- * about this with a print message.
- */
- dev_info(&svc->dev, "removing interface %u to add it again\n",
+ dev_info(&svc->dev, "mode switch detected on interface %u\n",
intf_id);
- gb_svc_intf_remove(svc, intf);
+
+ /* Mark as disconnected to prevent I/O during disable. */
+ intf->disconnected = true;
+ gb_interface_disable(intf);
+ intf->disconnected = false;
+
+ goto enable_interface;
}
intf = gb_interface_create(hd, intf_id);
if (ret) {
dev_err(&svc->dev, "failed to activate interface %u: %d\n",
intf_id, ret);
- goto err_interface_add;
+ gb_interface_add(intf);
+ return;
}
- /*
- * HACK: Use Ara VID/PID from earlier boot stage.
- *
- * FIXME: remove quirk with ES2 support
- */
- if (intf->quirks & GB_INTERFACE_QUIRK_NO_ARA_IDS) {
- intf->vendor_id = vendor_id;
- intf->product_id = product_id;
- }
+ ret = gb_interface_add(intf);
+ if (ret)
+ goto err_interface_deactivate;
+enable_interface:
ret = gb_interface_enable(intf);
if (ret) {
dev_err(&svc->dev, "failed to enable interface %u: %d\n",
goto err_interface_deactivate;
}
- ret = gb_interface_add(intf);
- if (ret) {
- gb_interface_disable(intf);
- gb_interface_deactivate(intf);
- return;
- }
-
return;
err_interface_deactivate:
gb_interface_deactivate(intf);
-err_interface_add:
- gb_interface_add(intf);
}
static void gb_svc_process_intf_hot_unplug(struct gb_operation *operation)