diff --git a/drivers/soc/qcom/apr.c b/drivers/soc/qcom/apr.c index 2073edb416a4..2d5645ff9919 100644 --- a/drivers/soc/qcom/apr.c +++ b/drivers/soc/qcom/apr.c @@ -411,31 +411,35 @@ static int apr_add_device(struct device *dev, struct device_node *np, if (np) snprintf(adev->name, APR_NAME_SIZE, "%pOFn", np); - switch (apr->type) { - case PR_TYPE_APR: - dev_set_name(&adev->dev, "aprsvc:%s:%x:%x", adev->name, - domain_id, svc_id); - break; - case PR_TYPE_GPR: - dev_set_name(&adev->dev, "gprsvc:%s:%x:%x", adev->name, - domain_id, svc_id); - break; - default: - break; - } - adev->dev.bus = &aprbus; adev->dev.parent = dev; adev->dev.of_node = np; adev->dev.release = apr_dev_release; adev->dev.driver = NULL; + device_initialize(&adev->dev); + + switch (apr->type) { + case PR_TYPE_APR: + ret = dev_set_name(&adev->dev, "aprsvc:%s:%x:%x", adev->name, + domain_id, svc_id); + break; + case PR_TYPE_GPR: + ret = dev_set_name(&adev->dev, "gprsvc:%s:%x:%x", adev->name, + domain_id, svc_id); + break; + default: + ret = -EINVAL; + break; + } + if (ret) + goto out_put_device; spin_lock(&apr->svcs_lock); ret = idr_alloc(&apr->svcs_idr, svc, svc_id, svc_id + 1, GFP_ATOMIC); spin_unlock(&apr->svcs_lock); if (ret < 0) { dev_err(dev, "idr_alloc failed: %d\n", ret); - goto out; + goto out_put_device; } /* Protection domain is optional, it does not exist on older platforms */ @@ -443,18 +447,26 @@ static int apr_add_device(struct device *dev, struct device_node *np, 1, &adev->service_path); if (ret < 0 && ret != -EINVAL) { dev_err(dev, "Failed to read second value of qcom,protection-domain\n"); - goto out; + goto out_remove_idr; } dev_info(dev, "Adding APR/GPR dev: %s\n", dev_name(&adev->dev)); - ret = device_register(&adev->dev); + ret = device_add(&adev->dev); if (ret) { - dev_err(dev, "device_register failed: %d\n", ret); - put_device(&adev->dev); + dev_err(dev, "device_add failed: %d\n", ret); + goto out_remove_idr; } -out: + return 0; + +out_remove_idr: + spin_lock(&apr->svcs_lock); + idr_remove(&apr->svcs_idr, svc_id); + spin_unlock(&apr->svcs_lock); + flush_workqueue(apr->rxwq); +out_put_device: + put_device(&adev->dev); return ret; }