in interface.c [1068:1174]
int gb_interface_enable(struct gb_interface *intf)
{
struct gb_control *control;
struct gb_bundle *bundle, *tmp;
int ret, size;
void *manifest;
ret = gb_interface_read_and_clear_init_status(intf);
if (ret) {
dev_err(&intf->dev, "failed to clear init status: %d\n", ret);
return ret;
}
/* Establish control connection */
control = gb_control_create(intf);
if (IS_ERR(control)) {
dev_err(&intf->dev, "failed to create control device: %ld\n",
PTR_ERR(control));
return PTR_ERR(control);
}
intf->control = control;
ret = gb_control_enable(intf->control);
if (ret)
goto err_put_control;
/* Get manifest size using control protocol on CPort */
size = gb_control_get_manifest_size_operation(intf);
if (size <= 0) {
dev_err(&intf->dev, "failed to get manifest size: %d\n", size);
if (size)
ret = size;
else
ret = -EINVAL;
goto err_disable_control;
}
manifest = kmalloc(size, GFP_KERNEL);
if (!manifest) {
ret = -ENOMEM;
goto err_disable_control;
}
/* Get manifest using control protocol on CPort */
ret = gb_control_get_manifest_operation(intf, manifest, size);
if (ret) {
dev_err(&intf->dev, "failed to get manifest: %d\n", ret);
goto err_free_manifest;
}
/*
* Parse the manifest and build up our data structures representing
* what's in it.
*/
if (!gb_manifest_parse(intf, manifest, size)) {
dev_err(&intf->dev, "failed to parse manifest\n");
ret = -EINVAL;
goto err_destroy_bundles;
}
ret = gb_control_get_bundle_versions(intf->control);
if (ret)
goto err_destroy_bundles;
/* Register the control device and any bundles */
ret = gb_control_add(intf->control);
if (ret)
goto err_destroy_bundles;
pm_runtime_use_autosuspend(&intf->dev);
pm_runtime_get_noresume(&intf->dev);
pm_runtime_set_active(&intf->dev);
pm_runtime_enable(&intf->dev);
list_for_each_entry_safe_reverse(bundle, tmp, &intf->bundles, links) {
ret = gb_bundle_add(bundle);
if (ret) {
gb_bundle_destroy(bundle);
continue;
}
}
kfree(manifest);
intf->enabled = true;
pm_runtime_put(&intf->dev);
trace_gb_interface_enable(intf);
return 0;
err_destroy_bundles:
list_for_each_entry_safe(bundle, tmp, &intf->bundles, links)
gb_bundle_destroy(bundle);
err_free_manifest:
kfree(manifest);
err_disable_control:
gb_control_disable(intf->control);
err_put_control:
gb_control_put(intf->control);
intf->control = NULL;
return ret;
}