nvme-hwmon: rework to avoid devm allocation
authorHannes Reinecke <hare@suse.de>
Tue, 19 Jan 2021 06:43:18 +0000 (07:43 +0100)
committerChristoph Hellwig <hch@lst.de>
Wed, 10 Feb 2021 15:38:06 +0000 (16:38 +0100)
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>
drivers/nvme/host/core.c
drivers/nvme/host/hwmon.c
drivers/nvme/host/nvme.h

index 02579f4f776c7d2fccbb7c4d2b32192bdfc4adfa..d77f3f26d8d387d4aeae051d0ddd84534c200bf4 100644 (file)
@@ -4471,6 +4471,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 5819f0381041491807b05362d9b5cf074897de50..2efb87642d180f4ca7970ae04d8f4ed276776429 100644 (file)
@@ -246,6 +246,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;
@@ -812,11 +815,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,