Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 629c0d00 authored by Johan Hovold's avatar Johan Hovold Committed by Greg Kroah-Hartman
Browse files

greybus: interface: separate disabling from removal



Separate interface disable from interface removal.

Disabling an interface means tearing down its control connection and
destroying (i.e. deregistering and releasing) its bundles, while
removing it means deregistering and releasing the interface itself.

This is needed to implement controlled module removal, where the module
interfaces are disabled before being physically ejected.

Signed-off-by: default avatarJohan Hovold <johan@hovoldconsulting.com>
Reviewed-by: default avatarJeffrey Carlyle <jcarlyle@google.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@google.com>
parent 35580af0
Loading
Loading
Loading
Loading
+32 −30
Original line number Diff line number Diff line
@@ -137,36 +137,6 @@ struct gb_interface *gb_interface_create(struct gb_host_device *hd,
	return intf;
}

/*
 * Tear down a previously set up interface.
 */
void gb_interface_remove(struct gb_interface *intf)
{
	struct gb_bundle *bundle;
	struct gb_bundle *next;

	/*
	 * Disable the control-connection early to avoid operation timeouts
	 * when the interface is already gone.
	 */
	if (intf->disconnected)
		gb_control_disable(intf->control);

	list_for_each_entry_safe(bundle, next, &intf->bundles, links)
		gb_bundle_destroy(bundle);

	if (device_is_registered(&intf->dev)) {
		device_del(&intf->dev);
		dev_info(&intf->dev, "Interface removed\n");
	}

	gb_control_disable(intf->control);

	list_del(&intf->links);

	put_device(&intf->dev);
}

/*
 * Enable an interface by enabling its control connection and fetching the
 * manifest and other information over it.
@@ -241,6 +211,25 @@ int gb_interface_enable(struct gb_interface *intf)
	return ret;
}

/* Disable an interface and destroy its bundles. */
void gb_interface_disable(struct gb_interface *intf)
{
	struct gb_bundle *bundle;
	struct gb_bundle *next;

	/*
	 * Disable the control-connection early to avoid operation timeouts
	 * when the interface is already gone.
	 */
	if (intf->disconnected)
		gb_control_disable(intf->control);

	list_for_each_entry_safe(bundle, next, &intf->bundles, links)
		gb_bundle_destroy(bundle);

	gb_control_disable(intf->control);
}

/* Register an interface and its bundles. */
int gb_interface_add(struct gb_interface *intf)
{
@@ -268,3 +257,16 @@ int gb_interface_add(struct gb_interface *intf)

	return 0;
}

/* Deregister an interface and drop its reference. */
void gb_interface_remove(struct gb_interface *intf)
{
	if (device_is_registered(&intf->dev)) {
		device_del(&intf->dev);
		dev_info(&intf->dev, "Interface removed\n");
	}

	list_del(&intf->links);

	put_device(&intf->dev);
}
+1 −0
Original line number Diff line number Diff line
@@ -48,6 +48,7 @@ struct gb_interface *gb_interface_find(struct gb_host_device *hd,
struct gb_interface *gb_interface_create(struct gb_host_device *hd,
					 u8 interface_id);
int gb_interface_enable(struct gb_interface *intf);
void gb_interface_disable(struct gb_interface *intf);
int gb_interface_add(struct gb_interface *intf);
void gb_interface_remove(struct gb_interface *intf);

+5 −6
Original line number Diff line number Diff line
@@ -533,12 +533,9 @@ static void gb_svc_intf_remove(struct gb_svc *svc, struct gb_interface *intf)
{
	intf->disconnected = true;

	get_device(&intf->dev);

	gb_interface_remove(intf);
	gb_interface_disable(intf);
	gb_svc_interface_route_destroy(svc, intf);

	put_device(&intf->dev);
	gb_interface_remove(intf);
}

static void gb_svc_process_intf_hotplug(struct gb_operation *operation)
@@ -1001,9 +998,11 @@ static void gb_svc_remove_interfaces(struct gb_svc *svc)
{
	struct gb_interface *intf, *tmp;

	list_for_each_entry_safe(intf, tmp, &svc->hd->interfaces, links)
	list_for_each_entry_safe(intf, tmp, &svc->hd->interfaces, links) {
		gb_interface_disable(intf);
		gb_interface_remove(intf);
	}
}

void gb_svc_del(struct gb_svc *svc)
{