> +}
> +
> +static DEVICE_ATTR(online, S_IWUSR | S_IRUGO, show_occ_online,
> + store_occ_online);
> +
> +struct occ_sysfs *occ_sysfs_start(struct device *dev, struct occ *occ,
> + struct occ_sysfs_config *config)
> +{
> + struct occ_sysfs *hwmon = devm_kzalloc(dev, sizeof(struct occ_sysfs),
> + GFP_KERNEL);
> + int rc;
> +
> + if (!hwmon)
> + return ERR_PTR(-ENOMEM);
> +
> + hwmon->occ = occ;
> + hwmon->num_caps_fields = config->num_caps_fields;
> + hwmon->caps_names = config->caps_names;
> +
> + dev_set_drvdata(dev, hwmon);
> +
> + rc = device_create_file(dev, &dev_attr_online);
> + if (rc)
> + return ERR_PTR(rc);
> +
> + return hwmon;
> +}
> +EXPORT_SYMBOL(occ_sysfs_start);
> +
> +int occ_sysfs_stop(struct device *dev, struct occ_sysfs *driver)
> +{
> + if (driver->dev) {
> + occ_remove_hwmon_attrs(driver);
> + hwmon_device_unregister(driver->dev);
> + }
> +
> + device_remove_file(driver->dev, &dev_attr_online);
> +
> + devm_kfree(dev, driver);
Thw point of using devm_ functions is not to require remove/free functions.
Something is completely wrong here if you need that call.
Overall, this is architectually completely wrong. One does not register
or instantiate drivers based on writing into sysfs attributes. Please
reconsider your approach.
We had some trouble designing this driver because the BMC only has
access to the OCC once the processor is powered on. This will happen
sometime after the BMC boots (this driver runs only on the BMC). With
no access to the OCC, we don't know what sensors are present on the
system without a large static enumeration. Also any sysfs files created
before we have OCC access won't be able to return any data.
Instead of the "online" attribute, what do you think about using the
"bind"/"unbind" API to probe the device from user space once the system
is powered on? All the hwmon registration would take place in the probe
function, it would just occur some time after boot.