Commit 96fb6c34 authored by Johan Hovold's avatar Johan Hovold Committed by Greg Kroah-Hartman
Browse files

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: default avatarJohan Hovold <johan@hovoldconsulting.com>
Reviewed-by: default avatarViresh Kumar <viresh.kumar@linaro.org>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@google.com>
parent 87a4c819
Loading
Loading
Loading
Loading
+17 −15
Original line number Diff line number Diff line
@@ -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;
}

+14 −41
Original line number Diff line number Diff line
@@ -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)