hwmon: (pmbus) Simplify memory allocation for sensor attributes
authorGuenter Roeck <linux@roeck-us.net>
Sun, 20 Jan 2013 20:01:41 +0000 (12:01 -0800)
committerGuenter Roeck <linux@roeck-us.net>
Wed, 6 Feb 2013 17:58:02 +0000 (09:58 -0800)
Since memory is now allocated with dev_ functions, we no longer need to keep
track of allocated memory. Sensor memory allocation can therefore be
simplified significantly.

Signed-off-by: Guenter Roeck <linux@roeck-us.net>
drivers/hwmon/pmbus/pmbus_core.c

index d1792d7..3782fda 100644 (file)
@@ -85,8 +85,9 @@
 #define PMBUS_NAME_SIZE                24
 
 struct pmbus_sensor {
+       struct pmbus_sensor *next;
        char name[PMBUS_NAME_SIZE];     /* sysfs sensor name */
-       struct sensor_device_attribute attribute;
+       struct device_attribute attribute;
        u8 page;                /* page number */
        u16 reg;                /* register */
        enum pmbus_sensor_classes class;        /* sensor class */
@@ -94,6 +95,8 @@ struct pmbus_sensor {
        int data;               /* Sensor data.
                                   Negative if there was a read error */
 };
+#define to_pmbus_sensor(_attr) \
+       container_of(_attr, struct pmbus_sensor, attribute)
 
 struct pmbus_boolean {
        char name[PMBUS_NAME_SIZE];     /* sysfs boolean name */
@@ -127,11 +130,6 @@ struct pmbus_data {
        struct attribute **attributes;
        struct attribute_group group;
 
-       /*
-        * Sensors cover both sensor and limit registers.
-        */
-       int max_sensors;
-       int num_sensors;
        struct pmbus_sensor *sensors;
 
        struct mutex update_lock;
@@ -361,6 +359,7 @@ static struct pmbus_data *pmbus_update_device(struct device *dev)
        struct i2c_client *client = to_i2c_client(dev);
        struct pmbus_data *data = i2c_get_clientdata(client);
        const struct pmbus_driver_info *info = data->info;
+       struct pmbus_sensor *sensor;
 
        mutex_lock(&data->update_lock);
        if (time_after(jiffies, data->last_updated + HZ) || !data->valid) {
@@ -410,9 +409,7 @@ static struct pmbus_data *pmbus_update_device(struct device *dev)
                          = _pmbus_read_byte_data(client, 0,
                                                  PMBUS_STATUS_INPUT);
 
-               for (i = 0; i < data->num_sensors; i++) {
-                       struct pmbus_sensor *sensor = &data->sensors[i];
-
+               for (sensor = data->sensors; sensor; sensor = sensor->next) {
                        if (!data->valid || sensor->update)
                                sensor->data
                                    = _pmbus_read_word_data(client,
@@ -748,13 +745,11 @@ static ssize_t pmbus_show_boolean(struct device *dev,
 }
 
 static ssize_t pmbus_show_sensor(struct device *dev,
-                                struct device_attribute *da, char *buf)
+                                struct device_attribute *devattr, char *buf)
 {
-       struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
        struct pmbus_data *data = pmbus_update_device(dev);
-       struct pmbus_sensor *sensor;
+       struct pmbus_sensor *sensor = to_pmbus_sensor(devattr);
 
-       sensor = &data->sensors[attr->index];
        if (sensor->data < 0)
                return sensor->data;
 
@@ -765,10 +760,9 @@ static ssize_t pmbus_set_sensor(struct device *dev,
                                struct device_attribute *devattr,
                                const char *buf, size_t count)
 {
-       struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
        struct i2c_client *client = to_i2c_client(dev);
        struct pmbus_data *data = i2c_get_clientdata(client);
-       struct pmbus_sensor *sensor = &data->sensors[attr->index];
+       struct pmbus_sensor *sensor = to_pmbus_sensor(devattr);
        ssize_t rv = count;
        long val = 0;
        int ret;
@@ -783,7 +777,7 @@ static ssize_t pmbus_set_sensor(struct device *dev,
        if (ret < 0)
                rv = ret;
        else
-               data->sensors[attr->index].data = regval;
+               sensor->data = regval;
        mutex_unlock(&data->update_lock);
        return rv;
 }
@@ -863,12 +857,13 @@ static struct pmbus_sensor *pmbus_add_sensor(struct pmbus_data *data,
                                             bool update, bool readonly)
 {
        struct pmbus_sensor *sensor;
-       struct sensor_device_attribute *a;
+       struct device_attribute *a;
 
-       BUG_ON(data->num_sensors >= data->max_sensors ||
-              data->num_attributes >= data->max_attributes);
+       BUG_ON(data->num_attributes >= data->max_attributes);
 
-       sensor = &data->sensors[data->num_sensors];
+       sensor = devm_kzalloc(data->dev, sizeof(*sensor), GFP_KERNEL);
+       if (!sensor)
+               return NULL;
        a = &sensor->attribute;
 
        snprintf(sensor->name, sizeof(sensor->name), "%s%d_%s",
@@ -877,12 +872,13 @@ static struct pmbus_sensor *pmbus_add_sensor(struct pmbus_data *data,
        sensor->reg = reg;
        sensor->class = class;
        sensor->update = update;
-       pmbus_attr_init(a, sensor->name,
-                       readonly ? S_IRUGO : S_IRUGO | S_IWUSR,
-                       pmbus_show_sensor, pmbus_set_sensor, data->num_sensors);
+       pmbus_dev_attr_init(a, sensor->name,
+                           readonly ? S_IRUGO : S_IRUGO | S_IWUSR,
+                           pmbus_show_sensor, pmbus_set_sensor);
 
-       data->attributes[data->num_attributes++] = &a->dev_attr.attr;
-       data->num_sensors++;
+       data->attributes[data->num_attributes++] = &a->attr;
+       sensor->next = data->sensors;
+       data->sensors = sensor;
 
        return sensor;
 }
@@ -965,7 +961,6 @@ static void pmbus_find_max_attr(struct i2c_client *client,
                        max_booleans += PMBUS_MAX_BOOLEANS_PER_TEMP;
                }
        }
-       data->max_sensors = max_sensors;
        data->max_attributes = max_sensors + max_booleans + max_labels;
 }
 
@@ -1031,6 +1026,8 @@ static int pmbus_add_limit_attrs(struct i2c_client *client,
                                                page, l->reg, attr->class,
                                                attr->update || l->update,
                                                false);
+                       if (!curr)
+                               return -ENOMEM;
                        if (l->sbit && (info->func[page] & attr->sfunc)) {
                                ret = pmbus_add_boolean(data, name,
                                        l->alarm, index,
@@ -1067,6 +1064,8 @@ static int pmbus_add_sensor_attrs_one(struct i2c_client *client,
        }
        base = pmbus_add_sensor(data, name, "input", index, page, attr->reg,
                                attr->class, true, true);
+       if (!base)
+               return -ENOMEM;
        if (attr->sfunc) {
                ret = pmbus_add_limit_attrs(client, data, info, name,
                                            index, page, base, attr);
@@ -1605,9 +1604,10 @@ static int pmbus_add_fan_attributes(struct i2c_client *client,
                            (!(regval & (PB_FAN_1_INSTALLED >> ((f & 1) * 4)))))
                                continue;
 
-                       pmbus_add_sensor(data, "fan", "input", index, page,
-                                        pmbus_fan_registers[f], PSC_FAN, true,
-                                        true);
+                       if (pmbus_add_sensor(data, "fan", "input", index,
+                                            page, pmbus_fan_registers[f],
+                                            PSC_FAN, true, true) == NULL)
+                               return -ENOMEM;
 
                        /*
                         * Each fan status register covers multiple fans,
@@ -1770,11 +1770,6 @@ int pmbus_do_probe(struct i2c_client *client, const struct i2c_device_id *id,
                return ret;
        }
 
-       data->sensors = devm_kzalloc(dev, sizeof(struct pmbus_sensor)
-                                    * data->max_sensors, GFP_KERNEL);
-       if (!data->sensors)
-               return -ENOMEM;
-
        data->attributes = devm_kzalloc(dev, sizeof(struct attribute *)
                                        * data->max_attributes, GFP_KERNEL);
        if (!data->attributes)