mirror of https://gitee.com/openkylin/linux.git
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: 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>
This commit is contained in:
parent
295a39f5a5
commit
ed7770f662
|
@ -4471,6 +4471,7 @@ EXPORT_SYMBOL_GPL(nvme_start_ctrl);
|
||||||
|
|
||||||
void nvme_uninit_ctrl(struct nvme_ctrl *ctrl)
|
void nvme_uninit_ctrl(struct nvme_ctrl *ctrl)
|
||||||
{
|
{
|
||||||
|
nvme_hwmon_exit(ctrl);
|
||||||
nvme_fault_inject_fini(&ctrl->fault_inject);
|
nvme_fault_inject_fini(&ctrl->fault_inject);
|
||||||
dev_pm_qos_hide_latency_tolerance(ctrl->device);
|
dev_pm_qos_hide_latency_tolerance(ctrl->device);
|
||||||
cdev_device_del(&ctrl->cdev, ctrl->device);
|
cdev_device_del(&ctrl->cdev, ctrl->device);
|
||||||
|
|
|
@ -223,12 +223,12 @@ static const struct hwmon_chip_info nvme_hwmon_chip_info = {
|
||||||
|
|
||||||
int nvme_hwmon_init(struct nvme_ctrl *ctrl)
|
int nvme_hwmon_init(struct nvme_ctrl *ctrl)
|
||||||
{
|
{
|
||||||
struct device *dev = ctrl->dev;
|
struct device *dev = ctrl->device;
|
||||||
struct nvme_hwmon_data *data;
|
struct nvme_hwmon_data *data;
|
||||||
struct device *hwmon;
|
struct device *hwmon;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
|
data = kzalloc(sizeof(*data), GFP_KERNEL);
|
||||||
if (!data)
|
if (!data)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
@ -237,19 +237,30 @@ int nvme_hwmon_init(struct nvme_ctrl *ctrl)
|
||||||
|
|
||||||
err = nvme_hwmon_get_smart_log(data);
|
err = nvme_hwmon_get_smart_log(data);
|
||||||
if (err) {
|
if (err) {
|
||||||
dev_warn(ctrl->device,
|
dev_warn(dev, "Failed to read smart log (error %d)\n", err);
|
||||||
"Failed to read smart log (error %d)\n", err);
|
kfree(data);
|
||||||
devm_kfree(dev, data);
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
hwmon = devm_hwmon_device_register_with_info(dev, "nvme", data,
|
hwmon = hwmon_device_register_with_info(dev, "nvme",
|
||||||
&nvme_hwmon_chip_info,
|
data, &nvme_hwmon_chip_info,
|
||||||
NULL);
|
NULL);
|
||||||
if (IS_ERR(hwmon)) {
|
if (IS_ERR(hwmon)) {
|
||||||
dev_warn(dev, "Failed to instantiate hwmon device\n");
|
dev_warn(dev, "Failed to instantiate hwmon device\n");
|
||||||
devm_kfree(dev, data);
|
kfree(data);
|
||||||
}
|
}
|
||||||
|
ctrl->hwmon_device = hwmon;
|
||||||
return 0;
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -246,6 +246,9 @@ struct nvme_ctrl {
|
||||||
struct rw_semaphore namespaces_rwsem;
|
struct rw_semaphore namespaces_rwsem;
|
||||||
struct device ctrl_device;
|
struct device ctrl_device;
|
||||||
struct device *device; /* char device */
|
struct device *device; /* char device */
|
||||||
|
#ifdef CONFIG_NVME_HWMON
|
||||||
|
struct device *hwmon_device;
|
||||||
|
#endif
|
||||||
struct cdev cdev;
|
struct cdev cdev;
|
||||||
struct work_struct reset_work;
|
struct work_struct reset_work;
|
||||||
struct work_struct delete_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
|
#ifdef CONFIG_NVME_HWMON
|
||||||
int nvme_hwmon_init(struct nvme_ctrl *ctrl);
|
int nvme_hwmon_init(struct nvme_ctrl *ctrl);
|
||||||
|
void nvme_hwmon_exit(struct nvme_ctrl *ctrl);
|
||||||
#else
|
#else
|
||||||
static inline int nvme_hwmon_init(struct nvme_ctrl *ctrl)
|
static inline int nvme_hwmon_init(struct nvme_ctrl *ctrl)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void nvme_hwmon_exit(struct nvme_ctrl *ctrl)
|
||||||
|
{
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
u32 nvme_command_effects(struct nvme_ctrl *ctrl, struct nvme_ns *ns,
|
u32 nvme_command_effects(struct nvme_ctrl *ctrl, struct nvme_ns *ns,
|
||||||
|
|
Loading…
Reference in New Issue