greybus: interface: reduce control-device lifetime

Make the control-device lifetime coincide with when the interface is
enabled (enumerated).

This is needed to be able register a new control device after a mode
switch.

Signed-off-by: Johan Hovold <johan@hovoldconsulting.com>
Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
This commit is contained in:
Johan Hovold 2016-04-13 19:19:06 +02:00 коммит произвёл Greg Kroah-Hartman
Родитель b6147e4fb1
Коммит 49605839bc
2 изменённых файлов: 23 добавлений и 12 удалений

Просмотреть файл

@ -352,9 +352,6 @@ static void gb_interface_release(struct device *dev)
{ {
struct gb_interface *intf = to_gb_interface(dev); struct gb_interface *intf = to_gb_interface(dev);
if (intf->control)
gb_control_put(intf->control);
kfree(intf); kfree(intf);
} }
@ -381,7 +378,6 @@ struct device_type greybus_interface_type = {
struct gb_interface *gb_interface_create(struct gb_host_device *hd, struct gb_interface *gb_interface_create(struct gb_host_device *hd,
u8 interface_id) u8 interface_id)
{ {
struct gb_control *control;
struct gb_interface *intf; struct gb_interface *intf;
intf = kzalloc(sizeof(*intf), GFP_KERNEL); intf = kzalloc(sizeof(*intf), GFP_KERNEL);
@ -404,13 +400,6 @@ struct gb_interface *gb_interface_create(struct gb_host_device *hd,
device_initialize(&intf->dev); device_initialize(&intf->dev);
dev_set_name(&intf->dev, "%d-%d", hd->bus_id, interface_id); dev_set_name(&intf->dev, "%d-%d", hd->bus_id, interface_id);
control = gb_control_create(intf);
if (IS_ERR(control)) {
put_device(&intf->dev);
return NULL;
}
intf->control = control;
list_add(&intf->links, &hd->interfaces); list_add(&intf->links, &hd->interfaces);
return intf; return intf;
@ -442,6 +431,7 @@ void gb_interface_deactivate(struct gb_interface *intf)
*/ */
int gb_interface_enable(struct gb_interface *intf) int gb_interface_enable(struct gb_interface *intf)
{ {
struct gb_control *control;
struct gb_bundle *bundle, *tmp; struct gb_bundle *bundle, *tmp;
int ret, size; int ret, size;
void *manifest; void *manifest;
@ -453,9 +443,17 @@ int gb_interface_enable(struct gb_interface *intf)
} }
/* Establish control connection */ /* Establish control connection */
control = gb_control_create(intf);
if (IS_ERR(control)) {
dev_err(&intf->dev, "failed to create control device: %lu\n",
PTR_ERR(control));
return PTR_ERR(control);
}
intf->control = control;
ret = gb_control_enable(intf->control); ret = gb_control_enable(intf->control);
if (ret) if (ret)
return ret; goto err_put_control;
/* Get manifest size using control protocol on CPort */ /* Get manifest size using control protocol on CPort */
size = gb_control_get_manifest_size_operation(intf); size = gb_control_get_manifest_size_operation(intf);
@ -503,6 +501,8 @@ int gb_interface_enable(struct gb_interface *intf)
kfree(manifest); kfree(manifest);
intf->enabled = true;
return 0; return 0;
err_destroy_bundles: err_destroy_bundles:
@ -512,6 +512,9 @@ err_free_manifest:
kfree(manifest); kfree(manifest);
err_disable_control: err_disable_control:
gb_control_disable(intf->control); gb_control_disable(intf->control);
err_put_control:
gb_control_put(intf->control);
intf->control = NULL;
return ret; return ret;
} }
@ -522,6 +525,9 @@ void gb_interface_disable(struct gb_interface *intf)
struct gb_bundle *bundle; struct gb_bundle *bundle;
struct gb_bundle *next; struct gb_bundle *next;
if (!intf->enabled)
return;
/* /*
* Disable the control-connection early to avoid operation timeouts * Disable the control-connection early to avoid operation timeouts
* when the interface is already gone. * when the interface is already gone.
@ -534,6 +540,10 @@ void gb_interface_disable(struct gb_interface *intf)
gb_control_del(intf->control); gb_control_del(intf->control);
gb_control_disable(intf->control); gb_control_disable(intf->control);
gb_control_put(intf->control);
intf->control = NULL;
intf->enabled = false;
} }
/* Register an interface and its bundles. */ /* Register an interface and its bundles. */

Просмотреть файл

@ -39,6 +39,7 @@ struct gb_interface {
unsigned long quirks; unsigned long quirks;
bool disconnected; bool disconnected;
bool enabled;
}; };
#define to_gb_interface(d) container_of(d, struct gb_interface, dev) #define to_gb_interface(d) container_of(d, struct gb_interface, dev)