diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c index 072e7c5a72e6..44226c4c48ec 100644 --- a/drivers/staging/greybus/interface.c +++ b/drivers/staging/greybus/interface.c @@ -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); +} diff --git a/drivers/staging/greybus/interface.h b/drivers/staging/greybus/interface.h index 4b69e9ee9070..d4c55abae258 100644 --- a/drivers/staging/greybus/interface.h +++ b/drivers/staging/greybus/interface.h @@ -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); diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index 631a76965b53..480a0712018d 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -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)