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:
Родитель
b6147e4fb1
Коммит
49605839bc
|
@ -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)
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче