greybus: svc: keep interfaces registered during mode switch

Keep a detected interface registered until it is physically removed.
Specifically, do not re-register an interface that is switching mode.

Note that this also allows us to get rid of some nasty hacks from core.
The Ara VID/PID bootrom hack for ES2 will continue to work, but is now
mostly confined to the bootrom driver.

Signed-off-by: Johan Hovold <johan@hovoldconsulting.com>
Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
This commit is contained in:
Johan Hovold 2016-04-13 19:19:08 +02:00 коммит произвёл Greg Kroah-Hartman
Родитель 87a4c819a5
Коммит 96fb6c340b
2 изменённых файлов: 31 добавлений и 56 удалений

Просмотреть файл

@ -426,8 +426,9 @@ void gb_interface_deactivate(struct gb_interface *intf)
} }
/* /*
* Enable an interface by enabling its control connection and fetching the * Enable an interface by enabling its control connection, fetching the
* manifest and other information over it. * manifest and other information over it, and finally registering its child
* devices.
*/ */
int gb_interface_enable(struct gb_interface *intf) int gb_interface_enable(struct gb_interface *intf)
{ {
@ -499,6 +500,19 @@ int gb_interface_enable(struct gb_interface *intf)
if (ret) if (ret)
goto err_destroy_bundles; 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); kfree(manifest);
intf->enabled = true; intf->enabled = true;
@ -546,10 +560,9 @@ void gb_interface_disable(struct gb_interface *intf)
intf->enabled = false; intf->enabled = false;
} }
/* Register an interface and its bundles. */ /* Register an interface. */
int gb_interface_add(struct gb_interface *intf) int gb_interface_add(struct gb_interface *intf)
{ {
struct gb_bundle *bundle, *tmp;
int ret; int ret;
ret = device_add(&intf->dev); ret = device_add(&intf->dev);
@ -563,17 +576,6 @@ int gb_interface_add(struct gb_interface *intf)
dev_info(&intf->dev, "DDBL1 Manufacturer=0x%08x, Product=0x%08x\n", dev_info(&intf->dev, "DDBL1 Manufacturer=0x%08x, Product=0x%08x\n",
intf->ddbl1_manufacturer_id, intf->ddbl1_product_id); 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; return 0;
} }

Просмотреть файл

@ -452,8 +452,6 @@ static void gb_svc_process_intf_hotplug(struct gb_operation *operation)
struct gb_host_device *hd = connection->hd; struct gb_host_device *hd = connection->hd;
struct gb_interface *intf; struct gb_interface *intf;
u8 intf_id; u8 intf_id;
u32 vendor_id = 0;
u32 product_id = 0;
int ret; int ret;
/* The request message size has already been verified. */ /* The request message size has already been verified. */
@ -464,27 +462,15 @@ static void gb_svc_process_intf_hotplug(struct gb_operation *operation)
intf = gb_interface_find(hd, intf_id); intf = gb_interface_find(hd, intf_id);
if (intf) { if (intf) {
/* HACK: Save Ara VID/PID for ES2 hack below */ dev_info(&svc->dev, "mode switch detected on interface %u\n",
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",
intf_id); 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); intf = gb_interface_create(hd, intf_id);
@ -498,19 +484,15 @@ static void gb_svc_process_intf_hotplug(struct gb_operation *operation)
if (ret) { if (ret) {
dev_err(&svc->dev, "failed to activate interface %u: %d\n", dev_err(&svc->dev, "failed to activate interface %u: %d\n",
intf_id, ret); intf_id, ret);
goto err_interface_add; gb_interface_add(intf);
return;
} }
/* ret = gb_interface_add(intf);
* HACK: Use Ara VID/PID from earlier boot stage. if (ret)
* goto err_interface_deactivate;
* 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;
}
enable_interface:
ret = gb_interface_enable(intf); ret = gb_interface_enable(intf);
if (ret) { if (ret) {
dev_err(&svc->dev, "failed to enable interface %u: %d\n", dev_err(&svc->dev, "failed to enable interface %u: %d\n",
@ -518,19 +500,10 @@ static void gb_svc_process_intf_hotplug(struct gb_operation *operation)
goto err_interface_deactivate; goto err_interface_deactivate;
} }
ret = gb_interface_add(intf);
if (ret) {
gb_interface_disable(intf);
gb_interface_deactivate(intf);
return;
}
return; return;
err_interface_deactivate: err_interface_deactivate:
gb_interface_deactivate(intf); gb_interface_deactivate(intf);
err_interface_add:
gb_interface_add(intf);
} }
static void gb_svc_process_intf_hot_unplug(struct gb_operation *operation) static void gb_svc_process_intf_hot_unplug(struct gb_operation *operation)