diff options
Diffstat (limited to 'drivers/hwmon/occ/common.c')
-rw-r--r-- | drivers/hwmon/occ/common.c | 100 |
1 files changed, 70 insertions, 30 deletions
diff --git a/drivers/hwmon/occ/common.c b/drivers/hwmon/occ/common.c index f00cd59f1d19..d78f4bebc718 100644 --- a/drivers/hwmon/occ/common.c +++ b/drivers/hwmon/occ/common.c @@ -1149,44 +1149,75 @@ static void occ_parse_poll_response(struct occ *occ) sizeof(*header), size + sizeof(*header)); } -int occ_setup(struct occ *occ, const char *name) +int occ_active(struct occ *occ, bool active) { - int rc; - - mutex_init(&occ->lock); - occ->groups[0] = &occ->group; + int rc = mutex_lock_interruptible(&occ->lock); - /* no need to lock */ - rc = occ_poll(occ); - if (rc == -ESHUTDOWN) { - dev_info(occ->bus_dev, "host is not ready\n"); - return rc; - } else if (rc < 0) { - dev_err(occ->bus_dev, - "failed to get OCC poll response=%02x: %d\n", - occ->resp.return_status, rc); + if (rc) return rc; - } - occ->next_update = jiffies + OCC_UPDATE_FREQUENCY; - occ_parse_poll_response(occ); + if (active) { + if (occ->active) { + rc = -EALREADY; + goto unlock; + } - rc = occ_setup_sensor_attrs(occ); - if (rc) { - dev_err(occ->bus_dev, "failed to setup sensor attrs: %d\n", - rc); - return rc; - } + occ->error_count = 0; + occ->last_safe = 0; - occ->hwmon = devm_hwmon_device_register_with_groups(occ->bus_dev, name, - occ, occ->groups); - if (IS_ERR(occ->hwmon)) { - rc = PTR_ERR(occ->hwmon); - dev_err(occ->bus_dev, "failed to register hwmon device: %d\n", - rc); - return rc; + rc = occ_poll(occ); + if (rc < 0) { + dev_err(occ->bus_dev, + "failed to get OCC poll response=%02x: %d\n", + occ->resp.return_status, rc); + goto unlock; + } + + occ->active = true; + occ->next_update = jiffies + OCC_UPDATE_FREQUENCY; + occ_parse_poll_response(occ); + + rc = occ_setup_sensor_attrs(occ); + if (rc) { + dev_err(occ->bus_dev, + "failed to setup sensor attrs: %d\n", rc); + goto unlock; + } + + occ->hwmon = hwmon_device_register_with_groups(occ->bus_dev, + "occ", occ, + occ->groups); + if (IS_ERR(occ->hwmon)) { + rc = PTR_ERR(occ->hwmon); + occ->hwmon = NULL; + dev_err(occ->bus_dev, + "failed to register hwmon device: %d\n", rc); + goto unlock; + } + } else { + if (!occ->active) { + rc = -EALREADY; + goto unlock; + } + + if (occ->hwmon) + hwmon_device_unregister(occ->hwmon); + occ->active = false; + occ->hwmon = NULL; } +unlock: + mutex_unlock(&occ->lock); + return rc; +} + +int occ_setup(struct occ *occ) +{ + int rc; + + mutex_init(&occ->lock); + occ->groups[0] = &occ->group; + rc = occ_setup_sysfs(occ); if (rc) dev_err(occ->bus_dev, "failed to setup sysfs: %d\n", rc); @@ -1195,6 +1226,15 @@ int occ_setup(struct occ *occ, const char *name) } EXPORT_SYMBOL_GPL(occ_setup); +void occ_shutdown(struct occ *occ) +{ + occ_shutdown_sysfs(occ); + + if (occ->hwmon) + hwmon_device_unregister(occ->hwmon); +} +EXPORT_SYMBOL_GPL(occ_shutdown); + MODULE_AUTHOR("Eddie James <eajames@linux.ibm.com>"); MODULE_DESCRIPTION("Common OCC hwmon code"); MODULE_LICENSE("GPL"); |