Skip to content

Commit 744c2fe

Browse files
arndbgroeck
authored andcommitted
hwmon: (occ) Rework attribute registration for stack usage
clang produces an output with excessive stack usage when building the occ_setup_sensor_attrs() function, apparently the result of having a lot of struct literals and building with the -fno-strict-overflow option that leads clang to skip some optimization in case the 'attr' pointer overruns: drivers/hwmon/occ/common.c:775:12: error: stack frame size (1392) exceeds limit (1280) in 'occ_setup_sensor_attrs' [-Werror,-Wframe-larger-than] Replace the custom macros for initializing the attributes with a simpler function call that does not run into this corner case. Link: https://godbolt.org/z/Wf1Yx76a5 Fixes: 54076cb ("hwmon (occ): Add sensor attributes and register hwmon device") Signed-off-by: Arnd Bergmann <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Guenter Roeck <[email protected]>
1 parent 14c9ede commit 744c2fe

File tree

1 file changed

+85
-127
lines changed

1 file changed

+85
-127
lines changed

drivers/hwmon/occ/common.c

Lines changed: 85 additions & 127 deletions
Original file line numberDiff line numberDiff line change
@@ -747,29 +747,30 @@ static ssize_t occ_show_extended(struct device *dev,
747747
}
748748

749749
/*
750-
* Some helper macros to make it easier to define an occ_attribute. Since these
751-
* are dynamically allocated, we shouldn't use the existing kernel macros which
750+
* A helper to make it easier to define an occ_attribute. Since these
751+
* are dynamically allocated, we cannot use the existing kernel macros which
752752
* stringify the name argument.
753753
*/
754-
#define ATTR_OCC(_name, _mode, _show, _store) { \
755-
.attr = { \
756-
.name = _name, \
757-
.mode = VERIFY_OCTAL_PERMISSIONS(_mode), \
758-
}, \
759-
.show = _show, \
760-
.store = _store, \
761-
}
762-
763-
#define SENSOR_ATTR_OCC(_name, _mode, _show, _store, _nr, _index) { \
764-
.dev_attr = ATTR_OCC(_name, _mode, _show, _store), \
765-
.index = _index, \
766-
.nr = _nr, \
754+
static void occ_init_attribute(struct occ_attribute *attr, int mode,
755+
ssize_t (*show)(struct device *dev, struct device_attribute *attr, char *buf),
756+
ssize_t (*store)(struct device *dev, struct device_attribute *attr,
757+
const char *buf, size_t count),
758+
int nr, int index, const char *fmt, ...)
759+
{
760+
va_list args;
761+
762+
va_start(args, fmt);
763+
vsnprintf(attr->name, sizeof(attr->name), fmt, args);
764+
va_end(args);
765+
766+
attr->sensor.dev_attr.attr.name = attr->name;
767+
attr->sensor.dev_attr.attr.mode = mode;
768+
attr->sensor.dev_attr.show = show;
769+
attr->sensor.dev_attr.store = store;
770+
attr->sensor.index = index;
771+
attr->sensor.nr = nr;
767772
}
768773

769-
#define OCC_INIT_ATTR(_name, _mode, _show, _store, _nr, _index) \
770-
((struct sensor_device_attribute_2) \
771-
SENSOR_ATTR_OCC(_name, _mode, _show, _store, _nr, _index))
772-
773774
/*
774775
* Allocate and instatiate sensor_device_attribute_2s. It's most efficient to
775776
* use our own instead of the built-in hwmon attribute types.
@@ -855,14 +856,15 @@ static int occ_setup_sensor_attrs(struct occ *occ)
855856
sensors->extended.num_sensors = 0;
856857
}
857858

858-
occ->attrs = devm_kzalloc(dev, sizeof(*occ->attrs) * num_attrs,
859+
occ->attrs = devm_kcalloc(dev, num_attrs, sizeof(*occ->attrs),
859860
GFP_KERNEL);
860861
if (!occ->attrs)
861862
return -ENOMEM;
862863

863864
/* null-terminated list */
864-
occ->group.attrs = devm_kzalloc(dev, sizeof(*occ->group.attrs) *
865-
num_attrs + 1, GFP_KERNEL);
865+
occ->group.attrs = devm_kcalloc(dev, num_attrs + 1,
866+
sizeof(*occ->group.attrs),
867+
GFP_KERNEL);
866868
if (!occ->group.attrs)
867869
return -ENOMEM;
868870

@@ -872,43 +874,33 @@ static int occ_setup_sensor_attrs(struct occ *occ)
872874
s = i + 1;
873875
temp = ((struct temp_sensor_2 *)sensors->temp.data) + i;
874876

875-
snprintf(attr->name, sizeof(attr->name), "temp%d_label", s);
876-
attr->sensor = OCC_INIT_ATTR(attr->name, 0444, show_temp, NULL,
877-
0, i);
877+
occ_init_attribute(attr, 0444, show_temp, NULL,
878+
0, i, "temp%d_label", s);
878879
attr++;
879880

880881
if (sensors->temp.version == 2 &&
881882
temp->fru_type == OCC_FRU_TYPE_VRM) {
882-
snprintf(attr->name, sizeof(attr->name),
883-
"temp%d_alarm", s);
883+
occ_init_attribute(attr, 0444, show_temp, NULL,
884+
1, i, "temp%d_alarm", s);
884885
} else {
885-
snprintf(attr->name, sizeof(attr->name),
886-
"temp%d_input", s);
886+
occ_init_attribute(attr, 0444, show_temp, NULL,
887+
1, i, "temp%d_input", s);
887888
}
888889

889-
attr->sensor = OCC_INIT_ATTR(attr->name, 0444, show_temp, NULL,
890-
1, i);
891890
attr++;
892891

893892
if (sensors->temp.version > 1) {
894-
snprintf(attr->name, sizeof(attr->name),
895-
"temp%d_fru_type", s);
896-
attr->sensor = OCC_INIT_ATTR(attr->name, 0444,
897-
show_temp, NULL, 2, i);
893+
occ_init_attribute(attr, 0444, show_temp, NULL,
894+
2, i, "temp%d_fru_type", s);
898895
attr++;
899896

900-
snprintf(attr->name, sizeof(attr->name),
901-
"temp%d_fault", s);
902-
attr->sensor = OCC_INIT_ATTR(attr->name, 0444,
903-
show_temp, NULL, 3, i);
897+
occ_init_attribute(attr, 0444, show_temp, NULL,
898+
3, i, "temp%d_fault", s);
904899
attr++;
905900

906901
if (sensors->temp.version == 0x10) {
907-
snprintf(attr->name, sizeof(attr->name),
908-
"temp%d_max", s);
909-
attr->sensor = OCC_INIT_ATTR(attr->name, 0444,
910-
show_temp, NULL,
911-
4, i);
902+
occ_init_attribute(attr, 0444, show_temp, NULL,
903+
4, i, "temp%d_max", s);
912904
attr++;
913905
}
914906
}
@@ -917,14 +909,12 @@ static int occ_setup_sensor_attrs(struct occ *occ)
917909
for (i = 0; i < sensors->freq.num_sensors; ++i) {
918910
s = i + 1;
919911

920-
snprintf(attr->name, sizeof(attr->name), "freq%d_label", s);
921-
attr->sensor = OCC_INIT_ATTR(attr->name, 0444, show_freq, NULL,
922-
0, i);
912+
occ_init_attribute(attr, 0444, show_freq, NULL,
913+
0, i, "freq%d_label", s);
923914
attr++;
924915

925-
snprintf(attr->name, sizeof(attr->name), "freq%d_input", s);
926-
attr->sensor = OCC_INIT_ATTR(attr->name, 0444, show_freq, NULL,
927-
1, i);
916+
occ_init_attribute(attr, 0444, show_freq, NULL,
917+
1, i, "freq%d_input", s);
928918
attr++;
929919
}
930920

@@ -940,32 +930,24 @@ static int occ_setup_sensor_attrs(struct occ *occ)
940930
s = (i * 4) + 1;
941931

942932
for (j = 0; j < 4; ++j) {
943-
snprintf(attr->name, sizeof(attr->name),
944-
"power%d_label", s);
945-
attr->sensor = OCC_INIT_ATTR(attr->name, 0444,
946-
show_power, NULL,
947-
nr++, i);
933+
occ_init_attribute(attr, 0444, show_power,
934+
NULL, nr++, i,
935+
"power%d_label", s);
948936
attr++;
949937

950-
snprintf(attr->name, sizeof(attr->name),
951-
"power%d_average", s);
952-
attr->sensor = OCC_INIT_ATTR(attr->name, 0444,
953-
show_power, NULL,
954-
nr++, i);
938+
occ_init_attribute(attr, 0444, show_power,
939+
NULL, nr++, i,
940+
"power%d_average", s);
955941
attr++;
956942

957-
snprintf(attr->name, sizeof(attr->name),
958-
"power%d_average_interval", s);
959-
attr->sensor = OCC_INIT_ATTR(attr->name, 0444,
960-
show_power, NULL,
961-
nr++, i);
943+
occ_init_attribute(attr, 0444, show_power,
944+
NULL, nr++, i,
945+
"power%d_average_interval", s);
962946
attr++;
963947

964-
snprintf(attr->name, sizeof(attr->name),
965-
"power%d_input", s);
966-
attr->sensor = OCC_INIT_ATTR(attr->name, 0444,
967-
show_power, NULL,
968-
nr++, i);
948+
occ_init_attribute(attr, 0444, show_power,
949+
NULL, nr++, i,
950+
"power%d_input", s);
969951
attr++;
970952

971953
s++;
@@ -977,85 +959,64 @@ static int occ_setup_sensor_attrs(struct occ *occ)
977959
for (i = 0; i < sensors->power.num_sensors; ++i) {
978960
s = i + 1;
979961

980-
snprintf(attr->name, sizeof(attr->name),
981-
"power%d_label", s);
982-
attr->sensor = OCC_INIT_ATTR(attr->name, 0444,
983-
show_power, NULL, 0, i);
962+
occ_init_attribute(attr, 0444, show_power, NULL,
963+
0, i, "power%d_label", s);
984964
attr++;
985965

986-
snprintf(attr->name, sizeof(attr->name),
987-
"power%d_average", s);
988-
attr->sensor = OCC_INIT_ATTR(attr->name, 0444,
989-
show_power, NULL, 1, i);
966+
occ_init_attribute(attr, 0444, show_power, NULL,
967+
1, i, "power%d_average", s);
990968
attr++;
991969

992-
snprintf(attr->name, sizeof(attr->name),
993-
"power%d_average_interval", s);
994-
attr->sensor = OCC_INIT_ATTR(attr->name, 0444,
995-
show_power, NULL, 2, i);
970+
occ_init_attribute(attr, 0444, show_power, NULL,
971+
2, i, "power%d_average_interval", s);
996972
attr++;
997973

998-
snprintf(attr->name, sizeof(attr->name),
999-
"power%d_input", s);
1000-
attr->sensor = OCC_INIT_ATTR(attr->name, 0444,
1001-
show_power, NULL, 3, i);
974+
occ_init_attribute(attr, 0444, show_power, NULL,
975+
3, i, "power%d_input", s);
1002976
attr++;
1003977
}
1004978

1005979
s = sensors->power.num_sensors + 1;
1006980
}
1007981

1008982
if (sensors->caps.num_sensors >= 1) {
1009-
snprintf(attr->name, sizeof(attr->name), "power%d_label", s);
1010-
attr->sensor = OCC_INIT_ATTR(attr->name, 0444, show_caps, NULL,
1011-
0, 0);
983+
occ_init_attribute(attr, 0444, show_caps, NULL,
984+
0, 0, "power%d_label", s);
1012985
attr++;
1013986

1014-
snprintf(attr->name, sizeof(attr->name), "power%d_cap", s);
1015-
attr->sensor = OCC_INIT_ATTR(attr->name, 0444, show_caps, NULL,
1016-
1, 0);
987+
occ_init_attribute(attr, 0444, show_caps, NULL,
988+
1, 0, "power%d_cap", s);
1017989
attr++;
1018990

1019-
snprintf(attr->name, sizeof(attr->name), "power%d_input", s);
1020-
attr->sensor = OCC_INIT_ATTR(attr->name, 0444, show_caps, NULL,
1021-
2, 0);
991+
occ_init_attribute(attr, 0444, show_caps, NULL,
992+
2, 0, "power%d_input", s);
1022993
attr++;
1023994

1024-
snprintf(attr->name, sizeof(attr->name),
1025-
"power%d_cap_not_redundant", s);
1026-
attr->sensor = OCC_INIT_ATTR(attr->name, 0444, show_caps, NULL,
1027-
3, 0);
995+
occ_init_attribute(attr, 0444, show_caps, NULL,
996+
3, 0, "power%d_cap_not_redundant", s);
1028997
attr++;
1029998

1030-
snprintf(attr->name, sizeof(attr->name), "power%d_cap_max", s);
1031-
attr->sensor = OCC_INIT_ATTR(attr->name, 0444, show_caps, NULL,
1032-
4, 0);
999+
occ_init_attribute(attr, 0444, show_caps, NULL,
1000+
4, 0, "power%d_cap_max", s);
10331001
attr++;
10341002

1035-
snprintf(attr->name, sizeof(attr->name), "power%d_cap_min", s);
1036-
attr->sensor = OCC_INIT_ATTR(attr->name, 0444, show_caps, NULL,
1037-
5, 0);
1003+
occ_init_attribute(attr, 0444, show_caps, NULL,
1004+
5, 0, "power%d_cap_min", s);
10381005
attr++;
10391006

1040-
snprintf(attr->name, sizeof(attr->name), "power%d_cap_user",
1041-
s);
1042-
attr->sensor = OCC_INIT_ATTR(attr->name, 0644, show_caps,
1043-
occ_store_caps_user, 6, 0);
1007+
occ_init_attribute(attr, 0644, show_caps, occ_store_caps_user,
1008+
6, 0, "power%d_cap_user", s);
10441009
attr++;
10451010

10461011
if (sensors->caps.version > 1) {
1047-
snprintf(attr->name, sizeof(attr->name),
1048-
"power%d_cap_user_source", s);
1049-
attr->sensor = OCC_INIT_ATTR(attr->name, 0444,
1050-
show_caps, NULL, 7, 0);
1012+
occ_init_attribute(attr, 0444, show_caps, NULL,
1013+
7, 0, "power%d_cap_user_source", s);
10511014
attr++;
10521015

10531016
if (sensors->caps.version > 2) {
1054-
snprintf(attr->name, sizeof(attr->name),
1055-
"power%d_cap_min_soft", s);
1056-
attr->sensor = OCC_INIT_ATTR(attr->name, 0444,
1057-
show_caps, NULL,
1058-
8, 0);
1017+
occ_init_attribute(attr, 0444, show_caps, NULL,
1018+
8, 0,
1019+
"power%d_cap_min_soft", s);
10591020
attr++;
10601021
}
10611022
}
@@ -1064,19 +1025,16 @@ static int occ_setup_sensor_attrs(struct occ *occ)
10641025
for (i = 0; i < sensors->extended.num_sensors; ++i) {
10651026
s = i + 1;
10661027

1067-
snprintf(attr->name, sizeof(attr->name), "extn%d_label", s);
1068-
attr->sensor = OCC_INIT_ATTR(attr->name, 0444,
1069-
occ_show_extended, NULL, 0, i);
1028+
occ_init_attribute(attr, 0444, occ_show_extended, NULL,
1029+
0, i, "extn%d_label", s);
10701030
attr++;
10711031

1072-
snprintf(attr->name, sizeof(attr->name), "extn%d_flags", s);
1073-
attr->sensor = OCC_INIT_ATTR(attr->name, 0444,
1074-
occ_show_extended, NULL, 1, i);
1032+
occ_init_attribute(attr, 0444, occ_show_extended, NULL,
1033+
1, i, "extn%d_flags", s);
10751034
attr++;
10761035

1077-
snprintf(attr->name, sizeof(attr->name), "extn%d_input", s);
1078-
attr->sensor = OCC_INIT_ATTR(attr->name, 0444,
1079-
occ_show_extended, NULL, 2, i);
1036+
occ_init_attribute(attr, 0444, occ_show_extended, NULL,
1037+
2, i, "extn%d_input", s);
10801038
attr++;
10811039
}
10821040

0 commit comments

Comments
 (0)