Commit ed7770f6 authored by Hannes Reinecke's avatar Hannes Reinecke Committed by Christoph Hellwig
Browse files

nvme-hwmon: rework to avoid devm allocation



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: default avatarHannes Reinecke <hare@suse.de>
Tested-by: default avatarEnzo Matsumiya <ematsumiya@suse.de>
Tested-by: default avatarDaniel Wagner <dwagner@suse.de>
Signed-off-by: default avatarChristoph Hellwig <hch@lst.de>
parent 295a39f5
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -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);
+21 −10
Original line number Diff line number Diff line
@@ -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,
	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);
	}
}
+8 −0
Original line number Diff line number Diff line
@@ -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,