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

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
......@@ -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);
}
......@@ -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);
......
......@@ -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,8 +998,10 @@ 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)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment