.. | .. |
---|
85 | 85 | #define ACPI_DEVFLAG_ATSDIS 0x10000000 |
---|
86 | 86 | |
---|
87 | 87 | #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 | + |
---|
88 | 92 | /* |
---|
89 | 93 | * ACPI table definitions |
---|
90 | 94 | * |
---|
.. | .. |
---|
3046 | 3050 | |
---|
3047 | 3051 | static int __init parse_ivrs_ioapic(char *str) |
---|
3048 | 3052 | { |
---|
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; |
---|
3052 | 3056 | |
---|
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; |
---|
3054 | 3060 | |
---|
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; |
---|
3058 | 3066 | } |
---|
3059 | 3067 | |
---|
| 3068 | + pr_err("Invalid command line: ivrs_ioapic%s\n", str); |
---|
| 3069 | + return 1; |
---|
| 3070 | + |
---|
| 3071 | +found: |
---|
3060 | 3072 | if (early_ioapic_map_size == EARLY_MAP_SIZE) { |
---|
3061 | 3073 | pr_err("Early IOAPIC map overflow - ignoring ivrs_ioapic%s\n", |
---|
3062 | 3074 | str); |
---|
3063 | 3075 | return 1; |
---|
3064 | 3076 | } |
---|
3065 | 3077 | |
---|
3066 | | - devid = ((bus & 0xff) << 8) | ((dev & 0x1f) << 3) | (fn & 0x7); |
---|
| 3078 | + devid = IVRS_GET_SBDF_ID(seg, bus, dev, fn); |
---|
3067 | 3079 | |
---|
3068 | 3080 | cmdline_maps = true; |
---|
3069 | 3081 | i = early_ioapic_map_size++; |
---|
.. | .. |
---|
3076 | 3088 | |
---|
3077 | 3089 | static int __init parse_ivrs_hpet(char *str) |
---|
3078 | 3090 | { |
---|
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; |
---|
3082 | 3094 | |
---|
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; |
---|
3084 | 3098 | |
---|
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; |
---|
3088 | 3104 | } |
---|
3089 | 3105 | |
---|
| 3106 | + pr_err("Invalid command line: ivrs_hpet%s\n", str); |
---|
| 3107 | + return 1; |
---|
| 3108 | + |
---|
| 3109 | +found: |
---|
3090 | 3110 | if (early_hpet_map_size == EARLY_MAP_SIZE) { |
---|
3091 | 3111 | pr_err("Early HPET map overflow - ignoring ivrs_hpet%s\n", |
---|
3092 | 3112 | str); |
---|
3093 | 3113 | return 1; |
---|
3094 | 3114 | } |
---|
3095 | 3115 | |
---|
3096 | | - devid = ((bus & 0xff) << 8) | ((dev & 0x1f) << 3) | (fn & 0x7); |
---|
| 3116 | + devid = IVRS_GET_SBDF_ID(seg, bus, dev, fn); |
---|
3097 | 3117 | |
---|
3098 | 3118 | cmdline_maps = true; |
---|
3099 | 3119 | i = early_hpet_map_size++; |
---|
.. | .. |
---|
3104 | 3124 | return 1; |
---|
3105 | 3125 | } |
---|
3106 | 3126 | |
---|
| 3127 | +#define ACPIID_LEN (ACPIHID_UID_LEN + ACPIHID_HID_LEN) |
---|
| 3128 | + |
---|
3107 | 3129 | static int __init parse_ivrs_acpihid(char *str) |
---|
3108 | 3130 | { |
---|
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; |
---|
3113 | 3135 | |
---|
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; |
---|
3118 | 3154 | } |
---|
3119 | 3155 | |
---|
| 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: |
---|
3120 | 3174 | p = acpiid; |
---|
3121 | 3175 | hid = strsep(&p, ":"); |
---|
3122 | 3176 | uid = p; |
---|
.. | .. |
---|
3126 | 3180 | return 1; |
---|
3127 | 3181 | } |
---|
3128 | 3182 | |
---|
| 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 | + |
---|
3129 | 3190 | i = early_acpihid_map_size++; |
---|
3130 | 3191 | memcpy(early_acpihid_map[i].hid, hid, strlen(hid)); |
---|
3131 | 3192 | 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); |
---|
3134 | 3194 | early_acpihid_map[i].cmd_line = true; |
---|
3135 | 3195 | |
---|
3136 | 3196 | return 1; |
---|