Message ID | 20230802032629.24309-1-kch@nvidia.com |
---|---|
State | New |
Headers | show |
On Tue, Aug 01, 2023 at 08:26:26PM -0700, Chaitanya Kulkarni wrote: > Hi, > > Restructure nvme_init_ctrl() for better initialization flow. > > Currenlty nvme_init_ctrl() initialized nvme authentication, fault > injection, and device PM QoS after adding the controller device with > a call to cdev_device_add(). This has led to additional code complexity, > as it required handling the unwinding of these initializations if any > of them failed. The current code is in fact also broken, as after device_add (which cdev_device_add does underneath) fails we can't just cleaup, but most call put_device. I think this single patch is what we should be doing, but I don't fell fully confindent in it without some extra error injection: diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c index 47d7ba2827ff29..5da55a271a5ab0 100644 --- a/drivers/nvme/host/core.c +++ b/drivers/nvme/host/core.c @@ -4405,14 +4405,12 @@ int nvme_init_ctrl(struct nvme_ctrl *ctrl, struct device *dev, BUILD_BUG_ON(NVME_DSM_MAX_RANGES * sizeof(struct nvme_dsm_range) > PAGE_SIZE); ctrl->discard_page = alloc_page(GFP_KERNEL); - if (!ctrl->discard_page) { - ret = -ENOMEM; - goto out; - } + if (!ctrl->discard_page) + return -ENOMEM; ret = ida_alloc(&nvme_instance_ida, GFP_KERNEL); if (ret < 0) - goto out; + goto out_free_discard_page; ctrl->instance = ret; device_initialize(&ctrl->ctrl_device); @@ -4431,13 +4429,6 @@ int nvme_init_ctrl(struct nvme_ctrl *ctrl, struct device *dev, if (ret) goto out_release_instance; - nvme_get_ctrl(ctrl); - cdev_init(&ctrl->cdev, &nvme_dev_fops); - ctrl->cdev.owner = ops->module; - ret = cdev_device_add(&ctrl->cdev, ctrl->device); - if (ret) - goto out_free_name; - /* * Initialize latency tolerance controls. The sysfs files won't * be visible to userspace unless the device actually supports APST. @@ -4448,23 +4439,27 @@ int nvme_init_ctrl(struct nvme_ctrl *ctrl, struct device *dev, nvme_fault_inject_init(&ctrl->fault_inject, dev_name(ctrl->device)); nvme_mpath_init_ctrl(ctrl); + ret = nvme_auth_init_ctrl(ctrl); if (ret) - goto out_free_cdev; + goto out_fault_inject_fini; - return 0; -out_free_cdev: + nvme_get_ctrl(ctrl); + cdev_init(&ctrl->cdev, &nvme_dev_fops); + ctrl->cdev.owner = ops->module; + ret = cdev_device_add(&ctrl->cdev, ctrl->device); + if (ret) + put_device(ctrl->device); + return ret; + +out_fault_inject_fini: nvme_fault_inject_fini(&ctrl->fault_inject); dev_pm_qos_hide_latency_tolerance(ctrl->device); - cdev_device_del(&ctrl->cdev, ctrl->device); -out_free_name: - nvme_put_ctrl(ctrl); kfree_const(ctrl->device->kobj.name); out_release_instance: ida_free(&nvme_instance_ida, ctrl->instance); -out: - if (ctrl->discard_page) - __free_page(ctrl->discard_page); +out_free_discard_page: + __free_page(ctrl->discard_page); return ret; } EXPORT_SYMBOL_GPL(nvme_init_ctrl);
diff --git a/drivers/base/power/qos.c b/drivers/base/power/qos.c index 8e93167f1783..169ec6d02ffb 100644 --- a/drivers/base/power/qos.c +++ b/drivers/base/power/qos.c @@ -39,6 +39,9 @@ #include "power.h" +#undef pr_fmt +#define pr_fmt(fmt) "power/qos: " fmt + static DEFINE_MUTEX(dev_pm_qos_mtx); static DEFINE_MUTEX(dev_pm_qos_sysfs_mtx); @@ -906,11 +909,12 @@ int dev_pm_qos_update_user_latency_tolerance(struct device *dev, s32 val) int ret; mutex_lock(&dev_pm_qos_mtx); - + pr_info("%s %d\n", __func__, __LINE__); if (IS_ERR_OR_NULL(dev->power.qos) || !dev->power.qos->latency_tolerance_req) { struct dev_pm_qos_request *req; + pr_info("%s %d\n", __func__, __LINE__); if (val < 0) { if (val == PM_QOS_LATENCY_TOLERANCE_NO_CONSTRAINT) ret = 0; @@ -918,19 +922,24 @@ int dev_pm_qos_update_user_latency_tolerance(struct device *dev, s32 val) ret = -EINVAL; goto out; } + pr_info("%s %d\n", __func__, __LINE__); req = kzalloc(sizeof(*req), GFP_KERNEL); if (!req) { ret = -ENOMEM; goto out; } + pr_info("%s %d\n", __func__, __LINE__); ret = __dev_pm_qos_add_request(dev, req, DEV_PM_QOS_LATENCY_TOLERANCE, val); if (ret < 0) { kfree(req); goto out; } dev->power.qos->latency_tolerance_req = req; + pr_info("%s %d\n", __func__, __LINE__); } else { + pr_info("%s %d\n", __func__, __LINE__); if (val < 0) { + pr_info("%s %d\n", __func__, __LINE__); __dev_pm_qos_drop_user_request(dev, DEV_PM_QOS_LATENCY_TOLERANCE); ret = 0; } else {