aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hwmon
diff options
context:
space:
mode:
authorGuenter Roeck <linux@roeck-us.net>2013-01-21 00:00:01 -0500
committerGuenter Roeck <linux@roeck-us.net>2013-02-06 12:58:03 -0500
commit85cfb3a83536ad7f055b45f3a9c227848fa4dc80 (patch)
tree99ecfa2660a4a8cf7c695ed93091dcba798d3411 /drivers/hwmon
parente1e081a7e3ae7c2390889688b4f8a0c7dbb6bb6b (diff)
hwmon: (pmbus) Use krealloc to allocate attribute memory
So far, attribute memory was allocated by pre-calculating the maximum possible amount of attributes. Not only does this waste memory, it is also risky because the calculation might be wrong. It also requires a lot of defines to specify the maximum number of attributes per class. Allocate attribute memory using krealloc() instead. That means we have to use kfree(), since devm_krealloc() does not exist, but that is still less costly and less risky than trying to predict the number of attributes at the beginning. Signed-off-by: Guenter Roeck <linux@roeck-us.net>
Diffstat (limited to 'drivers/hwmon')
-rw-r--r--drivers/hwmon/pmbus/pmbus_core.c140
1 files changed, 31 insertions, 109 deletions
diff --git a/drivers/hwmon/pmbus/pmbus_core.c b/drivers/hwmon/pmbus/pmbus_core.c
index 3782fda21c8b..26b699a6abb9 100644
--- a/drivers/hwmon/pmbus/pmbus_core.c
+++ b/drivers/hwmon/pmbus/pmbus_core.c
@@ -31,39 +31,10 @@
31#include "pmbus.h" 31#include "pmbus.h"
32 32
33/* 33/*
34 * Constants needed to determine number of sensors, booleans, and labels. 34 * Number of additional attribute pointers to allocate
35 * with each call to krealloc
35 */ 36 */
36#define PMBUS_MAX_INPUT_SENSORS 22 /* 10*volt, 7*curr, 5*power */ 37#define PMBUS_ATTR_ALLOC_SIZE 32
37#define PMBUS_VOUT_SENSORS_PER_PAGE 9 /* input, min, max, lcrit,
38 crit, lowest, highest, avg,
39 reset */
40#define PMBUS_IOUT_SENSORS_PER_PAGE 8 /* input, min, max, crit,
41 lowest, highest, avg,
42 reset */
43#define PMBUS_POUT_SENSORS_PER_PAGE 7 /* input, cap, max, crit,
44 * highest, avg, reset
45 */
46#define PMBUS_MAX_SENSORS_PER_FAN 1 /* input */
47#define PMBUS_MAX_SENSORS_PER_TEMP 9 /* input, min, max, lcrit,
48 * crit, lowest, highest, avg,
49 * reset
50 */
51
52#define PMBUS_MAX_INPUT_BOOLEANS 7 /* v: min_alarm, max_alarm,
53 lcrit_alarm, crit_alarm;
54 c: alarm, crit_alarm;
55 p: crit_alarm */
56#define PMBUS_VOUT_BOOLEANS_PER_PAGE 4 /* min_alarm, max_alarm,
57 lcrit_alarm, crit_alarm */
58#define PMBUS_IOUT_BOOLEANS_PER_PAGE 3 /* alarm, lcrit_alarm,
59 crit_alarm */
60#define PMBUS_POUT_BOOLEANS_PER_PAGE 3 /* cap_alarm, alarm, crit_alarm
61 */
62#define PMBUS_MAX_BOOLEANS_PER_FAN 2 /* alarm, fault */
63#define PMBUS_MAX_BOOLEANS_PER_TEMP 4 /* min_alarm, max_alarm,
64 lcrit_alarm, crit_alarm */
65
66#define PMBUS_MAX_INPUT_LABELS 4 /* vin, vcap, iin, pin */
67 38
68/* 39/*
69 * status, status_vout, status_iout, status_fans, status_fan34, and status_temp 40 * status, status_vout, status_iout, status_fans, status_fan34, and status_temp
@@ -127,7 +98,6 @@ struct pmbus_data {
127 98
128 int max_attributes; 99 int max_attributes;
129 int num_attributes; 100 int num_attributes;
130 struct attribute **attributes;
131 struct attribute_group group; 101 struct attribute_group group;
132 102
133 struct pmbus_sensor *sensors; 103 struct pmbus_sensor *sensors;
@@ -790,6 +760,22 @@ static ssize_t pmbus_show_label(struct device *dev,
790 return snprintf(buf, PAGE_SIZE, "%s\n", label->label); 760 return snprintf(buf, PAGE_SIZE, "%s\n", label->label);
791} 761}
792 762
763static int pmbus_add_attribute(struct pmbus_data *data, struct attribute *attr)
764{
765 if (data->num_attributes >= data->max_attributes - 1) {
766 data->max_attributes += PMBUS_ATTR_ALLOC_SIZE;
767 data->group.attrs = krealloc(data->group.attrs,
768 sizeof(struct attribute *) *
769 data->max_attributes, GFP_KERNEL);
770 if (data->group.attrs == NULL)
771 return -ENOMEM;
772 }
773
774 data->group.attrs[data->num_attributes++] = attr;
775 data->group.attrs[data->num_attributes] = NULL;
776 return 0;
777}
778
793static void pmbus_dev_attr_init(struct device_attribute *dev_attr, 779static void pmbus_dev_attr_init(struct device_attribute *dev_attr,
794 const char *name, 780 const char *name,
795 umode_t mode, 781 umode_t mode,
@@ -831,8 +817,6 @@ static int pmbus_add_boolean(struct pmbus_data *data,
831 struct pmbus_boolean *boolean; 817 struct pmbus_boolean *boolean;
832 struct sensor_device_attribute *a; 818 struct sensor_device_attribute *a;
833 819
834 BUG_ON(data->num_attributes >= data->max_attributes);
835
836 boolean = devm_kzalloc(data->dev, sizeof(*boolean), GFP_KERNEL); 820 boolean = devm_kzalloc(data->dev, sizeof(*boolean), GFP_KERNEL);
837 if (!boolean) 821 if (!boolean)
838 return -ENOMEM; 822 return -ENOMEM;
@@ -845,9 +829,8 @@ static int pmbus_add_boolean(struct pmbus_data *data,
845 boolean->s2 = s2; 829 boolean->s2 = s2;
846 pmbus_attr_init(a, boolean->name, S_IRUGO, pmbus_show_boolean, NULL, 830 pmbus_attr_init(a, boolean->name, S_IRUGO, pmbus_show_boolean, NULL,
847 (reg << 8) | mask); 831 (reg << 8) | mask);
848 data->attributes[data->num_attributes++] = &a->dev_attr.attr;
849 832
850 return 0; 833 return pmbus_add_attribute(data, &a->dev_attr.attr);
851} 834}
852 835
853static struct pmbus_sensor *pmbus_add_sensor(struct pmbus_data *data, 836static struct pmbus_sensor *pmbus_add_sensor(struct pmbus_data *data,
@@ -859,8 +842,6 @@ static struct pmbus_sensor *pmbus_add_sensor(struct pmbus_data *data,
859 struct pmbus_sensor *sensor; 842 struct pmbus_sensor *sensor;
860 struct device_attribute *a; 843 struct device_attribute *a;
861 844
862 BUG_ON(data->num_attributes >= data->max_attributes);
863
864 sensor = devm_kzalloc(data->dev, sizeof(*sensor), GFP_KERNEL); 845 sensor = devm_kzalloc(data->dev, sizeof(*sensor), GFP_KERNEL);
865 if (!sensor) 846 if (!sensor)
866 return NULL; 847 return NULL;
@@ -876,7 +857,9 @@ static struct pmbus_sensor *pmbus_add_sensor(struct pmbus_data *data,
876 readonly ? S_IRUGO : S_IRUGO | S_IWUSR, 857 readonly ? S_IRUGO : S_IRUGO | S_IWUSR,
877 pmbus_show_sensor, pmbus_set_sensor); 858 pmbus_show_sensor, pmbus_set_sensor);
878 859
879 data->attributes[data->num_attributes++] = &a->attr; 860 if (pmbus_add_attribute(data, &a->attr))
861 return NULL;
862
880 sensor->next = data->sensors; 863 sensor->next = data->sensors;
881 data->sensors = sensor; 864 data->sensors = sensor;
882 865
@@ -890,8 +873,6 @@ static int pmbus_add_label(struct pmbus_data *data,
890 struct pmbus_label *label; 873 struct pmbus_label *label;
891 struct device_attribute *a; 874 struct device_attribute *a;
892 875
893 BUG_ON(data->num_attributes >= data->max_attributes);
894
895 label = devm_kzalloc(data->dev, sizeof(*label), GFP_KERNEL); 876 label = devm_kzalloc(data->dev, sizeof(*label), GFP_KERNEL);
896 if (!label) 877 if (!label)
897 return -ENOMEM; 878 return -ENOMEM;
@@ -906,62 +887,7 @@ static int pmbus_add_label(struct pmbus_data *data,
906 index); 887 index);
907 888
908 pmbus_dev_attr_init(a, label->name, S_IRUGO, pmbus_show_label, NULL); 889 pmbus_dev_attr_init(a, label->name, S_IRUGO, pmbus_show_label, NULL);
909 data->attributes[data->num_attributes++] = &a->attr; 890 return pmbus_add_attribute(data, &a->attr);
910 return 0;
911}
912
913/*
914 * Determine maximum number of sensors, booleans, and labels.
915 * To keep things simple, only make a rough high estimate.
916 */
917static void pmbus_find_max_attr(struct i2c_client *client,
918 struct pmbus_data *data)
919{
920 const struct pmbus_driver_info *info = data->info;
921 int page, max_sensors, max_booleans, max_labels;
922
923 max_sensors = PMBUS_MAX_INPUT_SENSORS;
924 max_booleans = PMBUS_MAX_INPUT_BOOLEANS;
925 max_labels = PMBUS_MAX_INPUT_LABELS;
926
927 for (page = 0; page < info->pages; page++) {
928 if (info->func[page] & PMBUS_HAVE_VOUT) {
929 max_sensors += PMBUS_VOUT_SENSORS_PER_PAGE;
930 max_booleans += PMBUS_VOUT_BOOLEANS_PER_PAGE;
931 max_labels++;
932 }
933 if (info->func[page] & PMBUS_HAVE_IOUT) {
934 max_sensors += PMBUS_IOUT_SENSORS_PER_PAGE;
935 max_booleans += PMBUS_IOUT_BOOLEANS_PER_PAGE;
936 max_labels++;
937 }
938 if (info->func[page] & PMBUS_HAVE_POUT) {
939 max_sensors += PMBUS_POUT_SENSORS_PER_PAGE;
940 max_booleans += PMBUS_POUT_BOOLEANS_PER_PAGE;
941 max_labels++;
942 }
943 if (info->func[page] & PMBUS_HAVE_FAN12) {
944 max_sensors += 2 * PMBUS_MAX_SENSORS_PER_FAN;
945 max_booleans += 2 * PMBUS_MAX_BOOLEANS_PER_FAN;
946 }
947 if (info->func[page] & PMBUS_HAVE_FAN34) {
948 max_sensors += 2 * PMBUS_MAX_SENSORS_PER_FAN;
949 max_booleans += 2 * PMBUS_MAX_BOOLEANS_PER_FAN;
950 }
951 if (info->func[page] & PMBUS_HAVE_TEMP) {
952 max_sensors += PMBUS_MAX_SENSORS_PER_TEMP;
953 max_booleans += PMBUS_MAX_BOOLEANS_PER_TEMP;
954 }
955 if (info->func[page] & PMBUS_HAVE_TEMP2) {
956 max_sensors += PMBUS_MAX_SENSORS_PER_TEMP;
957 max_booleans += PMBUS_MAX_BOOLEANS_PER_TEMP;
958 }
959 if (info->func[page] & PMBUS_HAVE_TEMP3) {
960 max_sensors += PMBUS_MAX_SENSORS_PER_TEMP;
961 max_booleans += PMBUS_MAX_BOOLEANS_PER_TEMP;
962 }
963 }
964 data->max_attributes = max_sensors + max_booleans + max_labels;
965} 891}
966 892
967/* 893/*
@@ -1709,8 +1635,6 @@ static int pmbus_identify_common(struct i2c_client *client,
1709 } 1635 }
1710 } 1636 }
1711 1637
1712 /* Determine maximum number of sensors, booleans, and labels */
1713 pmbus_find_max_attr(client, data);
1714 pmbus_clear_fault_page(client, 0); 1638 pmbus_clear_fault_page(client, 0);
1715 return 0; 1639 return 0;
1716} 1640}
@@ -1770,14 +1694,9 @@ int pmbus_do_probe(struct i2c_client *client, const struct i2c_device_id *id,
1770 return ret; 1694 return ret;
1771 } 1695 }
1772 1696
1773 data->attributes = devm_kzalloc(dev, sizeof(struct attribute *)
1774 * data->max_attributes, GFP_KERNEL);
1775 if (!data->attributes)
1776 return -ENOMEM;
1777
1778 ret = pmbus_find_attributes(client, data); 1697 ret = pmbus_find_attributes(client, data);
1779 if (ret) 1698 if (ret)
1780 return ret; 1699 goto out_kfree;
1781 1700
1782 /* 1701 /*
1783 * If there are no attributes, something is wrong. 1702 * If there are no attributes, something is wrong.
@@ -1785,15 +1704,15 @@ int pmbus_do_probe(struct i2c_client *client, const struct i2c_device_id *id,
1785 */ 1704 */
1786 if (!data->num_attributes) { 1705 if (!data->num_attributes) {
1787 dev_err(dev, "No attributes found\n"); 1706 dev_err(dev, "No attributes found\n");
1788 return -ENODEV; 1707 ret = -ENODEV;
1708 goto out_kfree;
1789 } 1709 }
1790 1710
1791 /* Register sysfs hooks */ 1711 /* Register sysfs hooks */
1792 data->group.attrs = data->attributes;
1793 ret = sysfs_create_group(&dev->kobj, &data->group); 1712 ret = sysfs_create_group(&dev->kobj, &data->group);
1794 if (ret) { 1713 if (ret) {
1795 dev_err(dev, "Failed to create sysfs entries\n"); 1714 dev_err(dev, "Failed to create sysfs entries\n");
1796 return ret; 1715 goto out_kfree;
1797 } 1716 }
1798 data->hwmon_dev = hwmon_device_register(dev); 1717 data->hwmon_dev = hwmon_device_register(dev);
1799 if (IS_ERR(data->hwmon_dev)) { 1718 if (IS_ERR(data->hwmon_dev)) {
@@ -1805,6 +1724,8 @@ int pmbus_do_probe(struct i2c_client *client, const struct i2c_device_id *id,
1805 1724
1806out_hwmon_device_register: 1725out_hwmon_device_register:
1807 sysfs_remove_group(&dev->kobj, &data->group); 1726 sysfs_remove_group(&dev->kobj, &data->group);
1727out_kfree:
1728 kfree(data->group.attrs);
1808 return ret; 1729 return ret;
1809} 1730}
1810EXPORT_SYMBOL_GPL(pmbus_do_probe); 1731EXPORT_SYMBOL_GPL(pmbus_do_probe);
@@ -1814,6 +1735,7 @@ int pmbus_do_remove(struct i2c_client *client)
1814 struct pmbus_data *data = i2c_get_clientdata(client); 1735 struct pmbus_data *data = i2c_get_clientdata(client);
1815 hwmon_device_unregister(data->hwmon_dev); 1736 hwmon_device_unregister(data->hwmon_dev);
1816 sysfs_remove_group(&client->dev.kobj, &data->group); 1737 sysfs_remove_group(&client->dev.kobj, &data->group);
1738 kfree(data->group.attrs);
1817 return 0; 1739 return 0;
1818} 1740}
1819EXPORT_SYMBOL_GPL(pmbus_do_remove); 1741EXPORT_SYMBOL_GPL(pmbus_do_remove);