From 96fb6c340b4abb295ae5c7e904befef33a1d0325 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 13 Apr 2016 19:19:08 +0200 Subject: [PATCH] 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 Reviewed-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman --- drivers/staging/greybus/interface.c | 32 +++++++++-------- drivers/staging/greybus/svc.c | 55 ++++++++--------------------- 2 files changed, 31 insertions(+), 56 deletions(-) diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c index 5c87fbcd8937..89fe901cb0a3 100644 --- a/drivers/staging/greybus/interface.c +++ b/drivers/staging/greybus/interface.c @@ -426,8 +426,9 @@ void gb_interface_deactivate(struct gb_interface *intf) } /* - * 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) { @@ -499,6 +500,19 @@ 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; @@ -546,10 +560,9 @@ void gb_interface_disable(struct gb_interface *intf) 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); @@ -563,17 +576,6 @@ int gb_interface_add(struct gb_interface *intf) 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; } diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index 25978e718ece..a9ef16ecd0d9 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -452,8 +452,6 @@ static void gb_svc_process_intf_hotplug(struct gb_operation *operation) 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. */ @@ -464,27 +462,15 @@ static void gb_svc_process_intf_hotplug(struct gb_operation *operation) 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); @@ -498,19 +484,15 @@ static void gb_svc_process_intf_hotplug(struct gb_operation *operation) 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", @@ -518,19 +500,10 @@ static void gb_svc_process_intf_hotplug(struct gb_operation *operation) 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)