Merge tag 'ext4_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso...
[pandora-kernel.git] / drivers / hwmon / pmbus / pmbus_core.c
index d89b339..be51037 100644 (file)
 #define PMBUS_IOUT_SENSORS_PER_PAGE    8       /* input, min, max, crit,
                                                   lowest, highest, avg,
                                                   reset */
-#define PMBUS_POUT_SENSORS_PER_PAGE    4       /* input, cap, max, crit */
+#define PMBUS_POUT_SENSORS_PER_PAGE    7       /* input, cap, max, crit,
+                                                * highest, avg, reset
+                                                */
 #define PMBUS_MAX_SENSORS_PER_FAN      1       /* input */
-#define PMBUS_MAX_SENSORS_PER_TEMP     8       /* input, min, max, lcrit,
-                                                  crit, lowest, highest,
-                                                  reset */
+#define PMBUS_MAX_SENSORS_PER_TEMP     9       /* input, min, max, lcrit,
+                                                * crit, lowest, highest, avg,
+                                                * reset
+                                                */
 
 #define PMBUS_MAX_INPUT_BOOLEANS       7       /* v: min_alarm, max_alarm,
                                                   lcrit_alarm, crit_alarm;
@@ -782,7 +785,7 @@ static ssize_t pmbus_set_sensor(struct device *dev,
        int ret;
        u16 regval;
 
-       if (strict_strtol(buf, 10, &val) < 0)
+       if (kstrtol(buf, 10, &val) < 0)
                return -EINVAL;
 
        mutex_lock(&data->update_lock);
@@ -1334,6 +1337,17 @@ static const struct pmbus_limit_attr pout_limit_attrs[] = {
                .attr = "crit",
                .alarm = "crit_alarm",
                .sbit = PB_POUT_OP_FAULT,
+       }, {
+               .reg = PMBUS_VIRT_READ_POUT_AVG,
+               .update = true,
+               .attr = "average",
+       }, {
+               .reg = PMBUS_VIRT_READ_POUT_MAX,
+               .update = true,
+               .attr = "input_highest",
+       }, {
+               .reg = PMBUS_VIRT_RESET_POUT_HISTORY,
+               .attr = "reset_history",
        }
 };
 
@@ -1388,6 +1402,9 @@ static const struct pmbus_limit_attr temp_limit_attrs[] = {
        }, {
                .reg = PMBUS_VIRT_READ_TEMP_MIN,
                .attr = "lowest",
+       }, {
+               .reg = PMBUS_VIRT_READ_TEMP_AVG,
+               .attr = "average",
        }, {
                .reg = PMBUS_VIRT_READ_TEMP_MAX,
                .attr = "highest",
@@ -1423,6 +1440,9 @@ static const struct pmbus_limit_attr temp_limit_attrs2[] = {
        }, {
                .reg = PMBUS_VIRT_READ_TEMP2_MIN,
                .attr = "lowest",
+       }, {
+               .reg = PMBUS_VIRT_READ_TEMP2_AVG,
+               .attr = "average",
        }, {
                .reg = PMBUS_VIRT_READ_TEMP2_MAX,
                .attr = "highest",
@@ -1676,7 +1696,7 @@ int pmbus_do_probe(struct i2c_client *client, const struct i2c_device_id *id,
                                     | I2C_FUNC_SMBUS_WORD_DATA))
                return -ENODEV;
 
-       data = kzalloc(sizeof(*data), GFP_KERNEL);
+       data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL);
        if (!data) {
                dev_err(&client->dev, "No memory to allocate driver data\n");
                return -ENOMEM;
@@ -1688,8 +1708,7 @@ int pmbus_do_probe(struct i2c_client *client, const struct i2c_device_id *id,
        /* Bail out if PMBus status register does not exist. */
        if (i2c_smbus_read_byte_data(client, PMBUS_STATUS_BYTE) < 0) {
                dev_err(&client->dev, "PMBus status register not found\n");
-               ret = -ENODEV;
-               goto out_data;
+               return -ENODEV;
        }
 
        if (pdata)
@@ -1702,50 +1721,49 @@ int pmbus_do_probe(struct i2c_client *client, const struct i2c_device_id *id,
                ret = (*info->identify)(client, info);
                if (ret < 0) {
                        dev_err(&client->dev, "Chip identification failed\n");
-                       goto out_data;
+                       return ret;
                }
        }
 
        if (info->pages <= 0 || info->pages > PMBUS_PAGES) {
                dev_err(&client->dev, "Bad number of PMBus pages: %d\n",
                        info->pages);
-               ret = -ENODEV;
-               goto out_data;
+               return -ENODEV;
        }
 
        ret = pmbus_identify_common(client, data);
        if (ret < 0) {
                dev_err(&client->dev, "Failed to identify chip capabilities\n");
-               goto out_data;
+               return ret;
        }
 
        ret = -ENOMEM;
-       data->sensors = kzalloc(sizeof(struct pmbus_sensor) * data->max_sensors,
-                               GFP_KERNEL);
+       data->sensors = devm_kzalloc(&client->dev, sizeof(struct pmbus_sensor)
+                                    * data->max_sensors, GFP_KERNEL);
        if (!data->sensors) {
                dev_err(&client->dev, "No memory to allocate sensor data\n");
-               goto out_data;
+               return -ENOMEM;
        }
 
-       data->booleans = kzalloc(sizeof(struct pmbus_boolean)
+       data->booleans = devm_kzalloc(&client->dev, sizeof(struct pmbus_boolean)
                                 * data->max_booleans, GFP_KERNEL);
        if (!data->booleans) {
                dev_err(&client->dev, "No memory to allocate boolean data\n");
-               goto out_sensors;
+               return -ENOMEM;
        }
 
-       data->labels = kzalloc(sizeof(struct pmbus_label) * data->max_labels,
-                              GFP_KERNEL);
+       data->labels = devm_kzalloc(&client->dev, sizeof(struct pmbus_label)
+                                   * data->max_labels, GFP_KERNEL);
        if (!data->labels) {
                dev_err(&client->dev, "No memory to allocate label data\n");
-               goto out_booleans;
+               return -ENOMEM;
        }
 
-       data->attributes = kzalloc(sizeof(struct attribute *)
-                                  * data->max_attributes, GFP_KERNEL);
+       data->attributes = devm_kzalloc(&client->dev, sizeof(struct attribute *)
+                                       * data->max_attributes, GFP_KERNEL);
        if (!data->attributes) {
                dev_err(&client->dev, "No memory to allocate attribute data\n");
-               goto out_labels;
+               return -ENOMEM;
        }
 
        pmbus_find_attributes(client, data);
@@ -1756,8 +1774,7 @@ int pmbus_do_probe(struct i2c_client *client, const struct i2c_device_id *id,
         */
        if (!data->num_attributes) {
                dev_err(&client->dev, "No attributes found\n");
-               ret = -ENODEV;
-               goto out_attributes;
+               return -ENODEV;
        }
 
        /* Register sysfs hooks */
@@ -1765,7 +1782,7 @@ int pmbus_do_probe(struct i2c_client *client, const struct i2c_device_id *id,
        ret = sysfs_create_group(&client->dev.kobj, &data->group);
        if (ret) {
                dev_err(&client->dev, "Failed to create sysfs entries\n");
-               goto out_attributes;
+               return ret;
        }
        data->hwmon_dev = hwmon_device_register(&client->dev);
        if (IS_ERR(data->hwmon_dev)) {
@@ -1777,30 +1794,16 @@ int pmbus_do_probe(struct i2c_client *client, const struct i2c_device_id *id,
 
 out_hwmon_device_register:
        sysfs_remove_group(&client->dev.kobj, &data->group);
-out_attributes:
-       kfree(data->attributes);
-out_labels:
-       kfree(data->labels);
-out_booleans:
-       kfree(data->booleans);
-out_sensors:
-       kfree(data->sensors);
-out_data:
-       kfree(data);
        return ret;
 }
 EXPORT_SYMBOL_GPL(pmbus_do_probe);
 
-void pmbus_do_remove(struct i2c_client *client)
+int pmbus_do_remove(struct i2c_client *client)
 {
        struct pmbus_data *data = i2c_get_clientdata(client);
        hwmon_device_unregister(data->hwmon_dev);
        sysfs_remove_group(&client->dev.kobj, &data->group);
-       kfree(data->attributes);
-       kfree(data->labels);
-       kfree(data->booleans);
-       kfree(data->sensors);
-       kfree(data);
+       return 0;
 }
 EXPORT_SYMBOL_GPL(pmbus_do_remove);