hc
2023-12-11 d2ccde1c8e90d38cee87a1b0309ad2827f3fd30d
kernel/drivers/platform/x86/ideapad-laptop.c
....@@ -1,23 +1,9 @@
1
+// SPDX-License-Identifier: GPL-2.0-or-later
12 /*
23 * ideapad-laptop.c - Lenovo IdeaPad ACPI Extras
34 *
45 * Copyright © 2010 Intel Corporation
56 * Copyright © 2010 David Woodhouse <dwmw2@infradead.org>
6
- *
7
- * This program is free software; you can redistribute it and/or modify
8
- * it under the terms of the GNU General Public License as published by
9
- * the Free Software Foundation; either version 2 of the License, or
10
- * (at your option) any later version.
11
- *
12
- * This program is distributed in the hope that it will be useful,
13
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
- * GNU General Public License for more details.
16
- *
17
- * You should have received a copy of the GNU General Public License
18
- * along with this program; if not, write to the Free Software
19
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
20
- * 02110-1301, USA.
217 */
228
239 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
....@@ -106,6 +92,7 @@
10692 struct dentry *debug;
10793 unsigned long cfg;
10894 bool has_hw_rfkill_switch;
95
+ bool has_touchpad_switch;
10996 const char *fnesc_guid;
11097 };
11198
....@@ -212,7 +199,7 @@
212199 return 0;
213200 }
214201 }
215
- pr_err("timeout in read_ec_cmd\n");
202
+ pr_err("timeout in %s\n", __func__);
216203 return -1;
217204 }
218205
....@@ -330,34 +317,15 @@
330317 }
331318 DEFINE_SHOW_ATTRIBUTE(debugfs_cfg);
332319
333
-static int ideapad_debugfs_init(struct ideapad_private *priv)
320
+static void ideapad_debugfs_init(struct ideapad_private *priv)
334321 {
335
- struct dentry *node;
322
+ struct dentry *dir;
336323
337
- priv->debug = debugfs_create_dir("ideapad", NULL);
338
- if (priv->debug == NULL) {
339
- pr_err("failed to create debugfs directory");
340
- goto errout;
341
- }
324
+ dir = debugfs_create_dir("ideapad", NULL);
325
+ priv->debug = dir;
342326
343
- node = debugfs_create_file("cfg", S_IRUGO, priv->debug, priv,
344
- &debugfs_cfg_fops);
345
- if (!node) {
346
- pr_err("failed to create cfg in debugfs");
347
- goto errout;
348
- }
349
-
350
- node = debugfs_create_file("status", S_IRUGO, priv->debug, priv,
351
- &debugfs_status_fops);
352
- if (!node) {
353
- pr_err("failed to create status in debugfs");
354
- goto errout;
355
- }
356
-
357
- return 0;
358
-
359
-errout:
360
- return -ENOMEM;
327
+ debugfs_create_file("cfg", S_IRUGO, dir, priv, &debugfs_cfg_fops);
328
+ debugfs_create_file("status", S_IRUGO, dir, priv, &debugfs_status_fops);
361329 }
362330
363331 static void ideapad_debugfs_exit(struct ideapad_private *priv)
....@@ -568,7 +536,9 @@
568536 } else if (attr == &dev_attr_fn_lock.attr) {
569537 supported = acpi_has_method(priv->adev->handle, "HALS") &&
570538 acpi_has_method(priv->adev->handle, "SALS");
571
- } else
539
+ } else if (attr == &dev_attr_touchpad.attr)
540
+ supported = priv->has_touchpad_switch;
541
+ else
572542 supported = true;
573543
574544 return supported ? attr->mode : 0;
....@@ -900,6 +870,9 @@
900870 {
901871 unsigned long value;
902872
873
+ if (!priv->has_touchpad_switch)
874
+ return;
875
+
903876 /* Without reading from EC touchpad LED doesn't switch state */
904877 if (!read_ec_data(priv->adev->handle, VPCCMD_R_TOUCHPAD, &value)) {
905878 /* Some IdeaPads don't really turn off touchpad - they only
....@@ -980,263 +953,21 @@
980953 #endif
981954
982955 /*
983
- * Some ideapads don't have a hardware rfkill switch, reading VPCCMD_R_RF
984
- * always results in 0 on these models, causing ideapad_laptop to wrongly
985
- * report all radios as hardware-blocked.
956
+ * Some ideapads have a hardware rfkill switch, but most do not have one.
957
+ * Reading VPCCMD_R_RF always results in 0 on models without a hardware rfkill,
958
+ * switch causing ideapad_laptop to wrongly report all radios as hw-blocked.
959
+ * There used to be a long list of DMI ids for models without a hw rfkill
960
+ * switch here, but that resulted in playing whack a mole.
961
+ * More importantly wrongly reporting the wifi radio as hw-blocked, results in
962
+ * non working wifi. Whereas not reporting it hw-blocked, when it actually is
963
+ * hw-blocked results in an empty SSID list, which is a much more benign
964
+ * failure mode.
965
+ * So the default now is the much safer option of assuming there is no
966
+ * hardware rfkill switch. This default also actually matches most hardware,
967
+ * since having a hw rfkill switch is quite rare on modern hardware, so this
968
+ * also leads to a much shorter list.
986969 */
987
-static const struct dmi_system_id no_hw_rfkill_list[] = {
988
- {
989
- .ident = "Lenovo RESCUER R720-15IKBN",
990
- .matches = {
991
- DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
992
- DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo R720-15IKBN"),
993
- },
994
- },
995
- {
996
- .ident = "Lenovo G40-30",
997
- .matches = {
998
- DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
999
- DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo G40-30"),
1000
- },
1001
- },
1002
- {
1003
- .ident = "Lenovo G50-30",
1004
- .matches = {
1005
- DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
1006
- DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo G50-30"),
1007
- },
1008
- },
1009
- {
1010
- .ident = "Lenovo V310-14IKB",
1011
- .matches = {
1012
- DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
1013
- DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo V310-14IKB"),
1014
- },
1015
- },
1016
- {
1017
- .ident = "Lenovo V310-14ISK",
1018
- .matches = {
1019
- DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
1020
- DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo V310-14ISK"),
1021
- },
1022
- },
1023
- {
1024
- .ident = "Lenovo V310-15IKB",
1025
- .matches = {
1026
- DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
1027
- DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo V310-15IKB"),
1028
- },
1029
- },
1030
- {
1031
- .ident = "Lenovo V310-15ISK",
1032
- .matches = {
1033
- DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
1034
- DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo V310-15ISK"),
1035
- },
1036
- },
1037
- {
1038
- .ident = "Lenovo V510-15IKB",
1039
- .matches = {
1040
- DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
1041
- DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo V510-15IKB"),
1042
- },
1043
- },
1044
- {
1045
- .ident = "Lenovo ideapad 300-15IBR",
1046
- .matches = {
1047
- DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
1048
- DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo ideapad 300-15IBR"),
1049
- },
1050
- },
1051
- {
1052
- .ident = "Lenovo ideapad 300-15IKB",
1053
- .matches = {
1054
- DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
1055
- DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo ideapad 300-15IKB"),
1056
- },
1057
- },
1058
- {
1059
- .ident = "Lenovo ideapad 300S-11IBR",
1060
- .matches = {
1061
- DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
1062
- DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo ideapad 300S-11BR"),
1063
- },
1064
- },
1065
- {
1066
- .ident = "Lenovo ideapad 310-15ABR",
1067
- .matches = {
1068
- DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
1069
- DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo ideapad 310-15ABR"),
1070
- },
1071
- },
1072
- {
1073
- .ident = "Lenovo ideapad 310-15IAP",
1074
- .matches = {
1075
- DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
1076
- DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo ideapad 310-15IAP"),
1077
- },
1078
- },
1079
- {
1080
- .ident = "Lenovo ideapad 310-15IKB",
1081
- .matches = {
1082
- DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
1083
- DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo ideapad 310-15IKB"),
1084
- },
1085
- },
1086
- {
1087
- .ident = "Lenovo ideapad 310-15ISK",
1088
- .matches = {
1089
- DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
1090
- DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo ideapad 310-15ISK"),
1091
- },
1092
- },
1093
- {
1094
- .ident = "Lenovo ideapad Y700-14ISK",
1095
- .matches = {
1096
- DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
1097
- DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo ideapad Y700-14ISK"),
1098
- },
1099
- },
1100
- {
1101
- .ident = "Lenovo ideapad Y700-15ACZ",
1102
- .matches = {
1103
- DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
1104
- DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo ideapad Y700-15ACZ"),
1105
- },
1106
- },
1107
- {
1108
- .ident = "Lenovo ideapad Y700-15ISK",
1109
- .matches = {
1110
- DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
1111
- DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo ideapad Y700-15ISK"),
1112
- },
1113
- },
1114
- {
1115
- .ident = "Lenovo ideapad Y700 Touch-15ISK",
1116
- .matches = {
1117
- DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
1118
- DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo ideapad Y700 Touch-15ISK"),
1119
- },
1120
- },
1121
- {
1122
- .ident = "Lenovo ideapad Y700-17ISK",
1123
- .matches = {
1124
- DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
1125
- DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo ideapad Y700-17ISK"),
1126
- },
1127
- },
1128
- {
1129
- .ident = "Lenovo ideapad MIIX 720-12IKB",
1130
- .matches = {
1131
- DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
1132
- DMI_MATCH(DMI_PRODUCT_VERSION, "MIIX 720-12IKB"),
1133
- },
1134
- },
1135
- {
1136
- .ident = "Lenovo Legion Y520-15IKB",
1137
- .matches = {
1138
- DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
1139
- DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo Y520-15IKB"),
1140
- },
1141
- },
1142
- {
1143
- .ident = "Lenovo Y520-15IKBM",
1144
- .matches = {
1145
- DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
1146
- DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo Y520-15IKBM"),
1147
- },
1148
- },
1149
- {
1150
- .ident = "Lenovo Legion Y720-15IKB",
1151
- .matches = {
1152
- DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
1153
- DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo Y720-15IKB"),
1154
- },
1155
- },
1156
- {
1157
- .ident = "Lenovo Legion Y720-15IKBN",
1158
- .matches = {
1159
- DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
1160
- DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo Y720-15IKBN"),
1161
- },
1162
- },
1163
- {
1164
- .ident = "Lenovo Y720-15IKBM",
1165
- .matches = {
1166
- DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
1167
- DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo Y720-15IKBM"),
1168
- },
1169
- },
1170
- {
1171
- .ident = "Lenovo Yoga 2 11 / 13 / Pro",
1172
- .matches = {
1173
- DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
1174
- DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo Yoga 2"),
1175
- },
1176
- },
1177
- {
1178
- .ident = "Lenovo Yoga 2 11 / 13 / Pro",
1179
- .matches = {
1180
- DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
1181
- DMI_MATCH(DMI_BOARD_NAME, "Yoga2"),
1182
- },
1183
- },
1184
- {
1185
- .ident = "Lenovo Yoga 3 1170 / 1470",
1186
- .matches = {
1187
- DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
1188
- DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo Yoga 3"),
1189
- },
1190
- },
1191
- {
1192
- .ident = "Lenovo Yoga 3 Pro 1370",
1193
- .matches = {
1194
- DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
1195
- DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo YOGA 3"),
1196
- },
1197
- },
1198
- {
1199
- .ident = "Lenovo Yoga 700",
1200
- .matches = {
1201
- DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
1202
- DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo YOGA 700"),
1203
- },
1204
- },
1205
- {
1206
- .ident = "Lenovo Yoga 900",
1207
- .matches = {
1208
- DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
1209
- DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo YOGA 900"),
1210
- },
1211
- },
1212
- {
1213
- .ident = "Lenovo Yoga 900",
1214
- .matches = {
1215
- DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
1216
- DMI_MATCH(DMI_BOARD_NAME, "VIUU4"),
1217
- },
1218
- },
1219
- {
1220
- .ident = "Lenovo YOGA 910-13IKB",
1221
- .matches = {
1222
- DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
1223
- DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo YOGA 910-13IKB"),
1224
- },
1225
- },
1226
- {
1227
- .ident = "Lenovo YOGA 920-13IKB",
1228
- .matches = {
1229
- DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
1230
- DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo YOGA 920-13IKB"),
1231
- },
1232
- },
1233
- {
1234
- .ident = "Lenovo Zhaoyang E42-80",
1235
- .matches = {
1236
- DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
1237
- DMI_MATCH(DMI_PRODUCT_VERSION, "ZHAOYANG E42-80"),
1238
- },
1239
- },
970
+static const struct dmi_system_id hw_rfkill_list[] = {
1240971 {}
1241972 };
1242973
....@@ -1262,15 +993,16 @@
1262993 priv->cfg = cfg;
1263994 priv->adev = adev;
1264995 priv->platform_device = pdev;
1265
- priv->has_hw_rfkill_switch = !dmi_check_system(no_hw_rfkill_list);
996
+ priv->has_hw_rfkill_switch = dmi_check_system(hw_rfkill_list);
997
+
998
+ /* Most ideapads with ELAN0634 touchpad don't use EC touchpad switch */
999
+ priv->has_touchpad_switch = !acpi_dev_present("ELAN0634", NULL, -1);
12661000
12671001 ret = ideapad_sysfs_init(priv);
12681002 if (ret)
12691003 return ret;
12701004
1271
- ret = ideapad_debugfs_init(priv);
1272
- if (ret)
1273
- goto debugfs_failed;
1005
+ ideapad_debugfs_init(priv);
12741006
12751007 ret = ideapad_input_init(priv);
12761008 if (ret)
....@@ -1282,6 +1014,10 @@
12821014 */
12831015 if (!priv->has_hw_rfkill_switch)
12841016 write_ec_cmd(priv->adev->handle, VPCCMD_W_RF, 1);
1017
+
1018
+ /* The same for Touchpad */
1019
+ if (!priv->has_touchpad_switch)
1020
+ write_ec_cmd(priv->adev->handle, VPCCMD_W_TOUCHPAD, 1);
12851021
12861022 for (i = 0; i < IDEAPAD_RFKILL_DEV_NUM; i++)
12871023 if (test_bit(ideapad_rfk_data[i].cfgbit, &priv->cfg))
....@@ -1327,7 +1063,6 @@
13271063 ideapad_input_exit(priv);
13281064 input_failed:
13291065 ideapad_debugfs_exit(priv);
1330
-debugfs_failed:
13311066 ideapad_sysfs_exit(priv);
13321067 return ret;
13331068 }