nvme-hwmon: rework to avoid devm allocation
authorHannes Reinecke <hare@suse.de>
Tue, 19 Jan 2021 06:43:18 +0000 (07:43 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sun, 30 Oct 2022 08:41:17 +0000 (09:41 +0100)
[ Upstream commit ed7770f6628691c13c9423bce7eee7cff2399c12 ]

The original design to use device-managed resource allocation
doesn't really work as the NVMe controller has a vastly different
lifetime than the hwmon sysfs attributes, causing warning about
duplicate sysfs entries upon reconnection.
This patch reworks the hwmon allocation to avoid device-managed
resource allocation, and uses the NVMe controller as parent for
the sysfs attributes.

Cc: Guenter Roeck <linux@roeck-us.net>
Signed-off-by: Hannes Reinecke <hare@suse.de>
Tested-by: Enzo Matsumiya <ematsumiya@suse.de>
Tested-by: Daniel Wagner <dwagner@suse.de>
Signed-off-by: Christoph Hellwig <hch@lst.de>
Stable-dep-of: c94b7f9bab22 ("nvme-hwmon: kmalloc the NVME SMART log buffer")
Signed-off-by: Sasha Levin <sashal@kernel.org>
drivers/nvme/host/core.c
drivers/nvme/host/hwmon.c
drivers/nvme/host/nvme.h

index e9c13804760e7068d77285871edfe998f4e9df8a..51e5c12988fe81a70e57b2ca1420e79b9d8de3f0 100644 (file)
@@ -4485,6 +4485,7 @@ EXPORT_SYMBOL_GPL(nvme_start_ctrl);
 
 void nvme_uninit_ctrl(struct nvme_ctrl *ctrl)
 {
+       nvme_hwmon_exit(ctrl);
        nvme_fault_inject_fini(&ctrl->fault_inject);
        dev_pm_qos_hide_latency_tolerance(ctrl->device);
        cdev_device_del(&ctrl->cdev, ctrl->device);
index 552dbc04567bcbf5a2ca26b935d0f771187e8506..8f9e96986780e6f831a90022f305a93f5d3fc9b1 100644 (file)
@@ -223,12 +223,12 @@ static const struct hwmon_chip_info nvme_hwmon_chip_info = {
 
 int nvme_hwmon_init(struct nvme_ctrl *ctrl)
 {
-       struct device *dev = ctrl->dev;
+       struct device *dev = ctrl->device;
        struct nvme_hwmon_data *data;
        struct device *hwmon;
        int err;
 
-       data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
+       data = kzalloc(sizeof(*data), GFP_KERNEL);
        if (!data)
                return 0;
 
@@ -237,19 +237,30 @@ int nvme_hwmon_init(struct nvme_ctrl *ctrl)
 
        err = nvme_hwmon_get_smart_log(data);
        if (err) {
-               dev_warn(ctrl->device,
-                       "Failed to read smart log (error %d)\n", err);
-               devm_kfree(dev, data);
+               dev_warn(dev, "Failed to read smart log (error %d)\n", err);
+               kfree(data);
                return err;
        }
 
-       hwmon = devm_hwmon_device_register_with_info(dev, "nvme", data,
-                                                    &nvme_hwmon_chip_info,
-                                                    NULL);
+       hwmon = hwmon_device_register_with_info(dev, "nvme",
+                                               data, &nvme_hwmon_chip_info,
+                                               NULL);
        if (IS_ERR(hwmon)) {
                dev_warn(dev, "Failed to instantiate hwmon device\n");
-               devm_kfree(dev, data);
+               kfree(data);
        }
-
+       ctrl->hwmon_device = hwmon;
        return 0;
 }
+
+void nvme_hwmon_exit(struct nvme_ctrl *ctrl)
+{
+       if (ctrl->hwmon_device) {
+               struct nvme_hwmon_data *data =
+                       dev_get_drvdata(ctrl->hwmon_device);
+
+               hwmon_device_unregister(ctrl->hwmon_device);
+               ctrl->hwmon_device = NULL;
+               kfree(data);
+       }
+}
index 58cf9e39d613e0a078c5add5d1c77e278d26ee32..abae7ef2ac5110e91c525e40464dffe9b318ebc5 100644 (file)
@@ -257,6 +257,9 @@ struct nvme_ctrl {
        struct rw_semaphore namespaces_rwsem;
        struct device ctrl_device;
        struct device *device;  /* char device */
+#ifdef CONFIG_NVME_HWMON
+       struct device *hwmon_device;
+#endif
        struct cdev cdev;
        struct work_struct reset_work;
        struct work_struct delete_work;
@@ -876,11 +879,16 @@ static inline struct nvme_ns *nvme_get_ns_from_dev(struct device *dev)
 
 #ifdef CONFIG_NVME_HWMON
 int nvme_hwmon_init(struct nvme_ctrl *ctrl);
+void nvme_hwmon_exit(struct nvme_ctrl *ctrl);
 #else
 static inline int nvme_hwmon_init(struct nvme_ctrl *ctrl)
 {
        return 0;
 }
+
+static inline void nvme_hwmon_exit(struct nvme_ctrl *ctrl)
+{
+}
 #endif
 
 u32 nvme_command_effects(struct nvme_ctrl *ctrl, struct nvme_ns *ns,