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:
Родитель
87a4c819a5
Коммит
96fb6c340b
|
@ -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)
|
||||||
|
|
Загрузка…
Ссылка в новой задаче