hc
2024-02-20 102a0743326a03cd1a1202ceda21e175b7d3575c
kernel/drivers/iommu/amd/init.c
....@@ -85,6 +85,10 @@
8585 #define ACPI_DEVFLAG_ATSDIS 0x10000000
8686
8787 #define LOOP_TIMEOUT 2000000
88
+
89
+#define IVRS_GET_SBDF_ID(seg, bus, dev, fd) (((seg & 0xffff) << 16) | ((bus & 0xff) << 8) \
90
+ | ((dev & 0x1f) << 3) | (fn & 0x7))
91
+
8892 /*
8993 * ACPI table definitions
9094 *
....@@ -3046,24 +3050,32 @@
30463050
30473051 static int __init parse_ivrs_ioapic(char *str)
30483052 {
3049
- unsigned int bus, dev, fn;
3050
- int ret, id, i;
3051
- u16 devid;
3053
+ u32 seg = 0, bus, dev, fn;
3054
+ int id, i;
3055
+ u32 devid;
30523056
3053
- ret = sscanf(str, "[%d]=%x:%x.%x", &id, &bus, &dev, &fn);
3057
+ if (sscanf(str, "=%d@%x:%x.%x", &id, &bus, &dev, &fn) == 4 ||
3058
+ sscanf(str, "=%d@%x:%x:%x.%x", &id, &seg, &bus, &dev, &fn) == 5)
3059
+ goto found;
30543060
3055
- if (ret != 4) {
3056
- pr_err("Invalid command line: ivrs_ioapic%s\n", str);
3057
- return 1;
3061
+ if (sscanf(str, "[%d]=%x:%x.%x", &id, &bus, &dev, &fn) == 4 ||
3062
+ sscanf(str, "[%d]=%x:%x:%x.%x", &id, &seg, &bus, &dev, &fn) == 5) {
3063
+ pr_warn("ivrs_ioapic%s option format deprecated; use ivrs_ioapic=%d@%04x:%02x:%02x.%d instead\n",
3064
+ str, id, seg, bus, dev, fn);
3065
+ goto found;
30583066 }
30593067
3068
+ pr_err("Invalid command line: ivrs_ioapic%s\n", str);
3069
+ return 1;
3070
+
3071
+found:
30603072 if (early_ioapic_map_size == EARLY_MAP_SIZE) {
30613073 pr_err("Early IOAPIC map overflow - ignoring ivrs_ioapic%s\n",
30623074 str);
30633075 return 1;
30643076 }
30653077
3066
- devid = ((bus & 0xff) << 8) | ((dev & 0x1f) << 3) | (fn & 0x7);
3078
+ devid = IVRS_GET_SBDF_ID(seg, bus, dev, fn);
30673079
30683080 cmdline_maps = true;
30693081 i = early_ioapic_map_size++;
....@@ -3076,24 +3088,32 @@
30763088
30773089 static int __init parse_ivrs_hpet(char *str)
30783090 {
3079
- unsigned int bus, dev, fn;
3080
- int ret, id, i;
3081
- u16 devid;
3091
+ u32 seg = 0, bus, dev, fn;
3092
+ int id, i;
3093
+ u32 devid;
30823094
3083
- ret = sscanf(str, "[%d]=%x:%x.%x", &id, &bus, &dev, &fn);
3095
+ if (sscanf(str, "=%d@%x:%x.%x", &id, &bus, &dev, &fn) == 4 ||
3096
+ sscanf(str, "=%d@%x:%x:%x.%x", &id, &seg, &bus, &dev, &fn) == 5)
3097
+ goto found;
30843098
3085
- if (ret != 4) {
3086
- pr_err("Invalid command line: ivrs_hpet%s\n", str);
3087
- return 1;
3099
+ if (sscanf(str, "[%d]=%x:%x.%x", &id, &bus, &dev, &fn) == 4 ||
3100
+ sscanf(str, "[%d]=%x:%x:%x.%x", &id, &seg, &bus, &dev, &fn) == 5) {
3101
+ pr_warn("ivrs_hpet%s option format deprecated; use ivrs_hpet=%d@%04x:%02x:%02x.%d instead\n",
3102
+ str, id, seg, bus, dev, fn);
3103
+ goto found;
30883104 }
30893105
3106
+ pr_err("Invalid command line: ivrs_hpet%s\n", str);
3107
+ return 1;
3108
+
3109
+found:
30903110 if (early_hpet_map_size == EARLY_MAP_SIZE) {
30913111 pr_err("Early HPET map overflow - ignoring ivrs_hpet%s\n",
30923112 str);
30933113 return 1;
30943114 }
30953115
3096
- devid = ((bus & 0xff) << 8) | ((dev & 0x1f) << 3) | (fn & 0x7);
3116
+ devid = IVRS_GET_SBDF_ID(seg, bus, dev, fn);
30973117
30983118 cmdline_maps = true;
30993119 i = early_hpet_map_size++;
....@@ -3104,19 +3124,53 @@
31043124 return 1;
31053125 }
31063126
3127
+#define ACPIID_LEN (ACPIHID_UID_LEN + ACPIHID_HID_LEN)
3128
+
31073129 static int __init parse_ivrs_acpihid(char *str)
31083130 {
3109
- u32 bus, dev, fn;
3110
- char *hid, *uid, *p;
3111
- char acpiid[ACPIHID_UID_LEN + ACPIHID_HID_LEN] = {0};
3112
- int ret, i;
3131
+ u32 seg = 0, bus, dev, fn;
3132
+ char *hid, *uid, *p, *addr;
3133
+ char acpiid[ACPIID_LEN] = {0};
3134
+ int i;
31133135
3114
- ret = sscanf(str, "[%x:%x.%x]=%s", &bus, &dev, &fn, acpiid);
3115
- if (ret != 4) {
3116
- pr_err("Invalid command line: ivrs_acpihid(%s)\n", str);
3117
- return 1;
3136
+ addr = strchr(str, '@');
3137
+ if (!addr) {
3138
+ addr = strchr(str, '=');
3139
+ if (!addr)
3140
+ goto not_found;
3141
+
3142
+ ++addr;
3143
+
3144
+ if (strlen(addr) > ACPIID_LEN)
3145
+ goto not_found;
3146
+
3147
+ if (sscanf(str, "[%x:%x.%x]=%s", &bus, &dev, &fn, acpiid) == 4 ||
3148
+ sscanf(str, "[%x:%x:%x.%x]=%s", &seg, &bus, &dev, &fn, acpiid) == 5) {
3149
+ pr_warn("ivrs_acpihid%s option format deprecated; use ivrs_acpihid=%s@%04x:%02x:%02x.%d instead\n",
3150
+ str, acpiid, seg, bus, dev, fn);
3151
+ goto found;
3152
+ }
3153
+ goto not_found;
31183154 }
31193155
3156
+ /* We have the '@', make it the terminator to get just the acpiid */
3157
+ *addr++ = 0;
3158
+
3159
+ if (strlen(str) > ACPIID_LEN + 1)
3160
+ goto not_found;
3161
+
3162
+ if (sscanf(str, "=%s", acpiid) != 1)
3163
+ goto not_found;
3164
+
3165
+ if (sscanf(addr, "%x:%x.%x", &bus, &dev, &fn) == 3 ||
3166
+ sscanf(addr, "%x:%x:%x.%x", &seg, &bus, &dev, &fn) == 4)
3167
+ goto found;
3168
+
3169
+not_found:
3170
+ pr_err("Invalid command line: ivrs_acpihid%s\n", str);
3171
+ return 1;
3172
+
3173
+found:
31203174 p = acpiid;
31213175 hid = strsep(&p, ":");
31223176 uid = p;
....@@ -3126,11 +3180,17 @@
31263180 return 1;
31273181 }
31283182
3183
+ /*
3184
+ * Ignore leading zeroes after ':', so e.g., AMDI0095:00
3185
+ * will match AMDI0095:0 in the second strcmp in acpi_dev_hid_uid_match
3186
+ */
3187
+ while (*uid == '0' && *(uid + 1))
3188
+ uid++;
3189
+
31293190 i = early_acpihid_map_size++;
31303191 memcpy(early_acpihid_map[i].hid, hid, strlen(hid));
31313192 memcpy(early_acpihid_map[i].uid, uid, strlen(uid));
3132
- early_acpihid_map[i].devid =
3133
- ((bus & 0xff) << 8) | ((dev & 0x1f) << 3) | (fn & 0x7);
3193
+ early_acpihid_map[i].devid = IVRS_GET_SBDF_ID(seg, bus, dev, fn);
31343194 early_acpihid_map[i].cmd_line = true;
31353195
31363196 return 1;