1
0
Fork 0

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: Johan Hovold <johan@hovoldconsulting.com>
Reviewed-by: Jeffrey Carlyle <jcarlyle@google.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
hifive-unleashed-5.1
Johan Hovold 2016-03-09 12:20:43 +01:00 committed by Greg Kroah-Hartman
parent 35580af0bd
commit 629c0d007d
3 changed files with 38 additions and 36 deletions

View File

@ -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 @@ err_disable_control:
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);
}

View File

@ -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);

View File

@ -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)