diff options
Diffstat (limited to 'drivers/iommu/amd/init.c')
| -rw-r--r-- | drivers/iommu/amd/init.c | 86 | 
1 files changed, 61 insertions, 25 deletions
diff --git a/drivers/iommu/amd/init.c b/drivers/iommu/amd/init.c index 1a2d425bf568..467b194975b3 100644 --- a/drivers/iommu/amd/init.c +++ b/drivers/iommu/amd/init.c @@ -85,7 +85,7 @@  #define LOOP_TIMEOUT	2000000 -#define IVRS_GET_SBDF_ID(seg, bus, dev, fd)	(((seg & 0xffff) << 16) | ((bus & 0xff) << 8) \ +#define IVRS_GET_SBDF_ID(seg, bus, dev, fn)	(((seg & 0xffff) << 16) | ((bus & 0xff) << 8) \  						 | ((dev & 0x1f) << 3) | (fn & 0x7))  /* @@ -3402,18 +3402,24 @@ static int __init parse_amd_iommu_options(char *str)  static int __init parse_ivrs_ioapic(char *str)  {  	u32 seg = 0, bus, dev, fn; -	int ret, id, i; +	int id, i;  	u32 devid; -	ret = sscanf(str, "[%d]=%x:%x.%x", &id, &bus, &dev, &fn); -	if (ret != 4) { -		ret = sscanf(str, "[%d]=%x:%x:%x.%x", &id, &seg, &bus, &dev, &fn); -		if (ret != 5) { -			pr_err("Invalid command line: ivrs_ioapic%s\n", str); -			return 1; -		} +	if (sscanf(str, "=%d@%x:%x.%x", &id, &bus, &dev, &fn) == 4 || +	    sscanf(str, "=%d@%x:%x:%x.%x", &id, &seg, &bus, &dev, &fn) == 5) +		goto found; + +	if (sscanf(str, "[%d]=%x:%x.%x", &id, &bus, &dev, &fn) == 4 || +	    sscanf(str, "[%d]=%x:%x:%x.%x", &id, &seg, &bus, &dev, &fn) == 5) { +		pr_warn("ivrs_ioapic%s option format deprecated; use ivrs_ioapic=%d@%04x:%02x:%02x.%d instead\n", +			str, id, seg, bus, dev, fn); +		goto found;  	} +	pr_err("Invalid command line: ivrs_ioapic%s\n", str); +	return 1; + +found:  	if (early_ioapic_map_size == EARLY_MAP_SIZE) {  		pr_err("Early IOAPIC map overflow - ignoring ivrs_ioapic%s\n",  			str); @@ -3434,18 +3440,24 @@ static int __init parse_ivrs_ioapic(char *str)  static int __init parse_ivrs_hpet(char *str)  {  	u32 seg = 0, bus, dev, fn; -	int ret, id, i; +	int id, i;  	u32 devid; -	ret = sscanf(str, "[%d]=%x:%x.%x", &id, &bus, &dev, &fn); -	if (ret != 4) { -		ret = sscanf(str, "[%d]=%x:%x:%x.%x", &id, &seg, &bus, &dev, &fn); -		if (ret != 5) { -			pr_err("Invalid command line: ivrs_hpet%s\n", str); -			return 1; -		} +	if (sscanf(str, "=%d@%x:%x.%x", &id, &bus, &dev, &fn) == 4 || +	    sscanf(str, "=%d@%x:%x:%x.%x", &id, &seg, &bus, &dev, &fn) == 5) +		goto found; + +	if (sscanf(str, "[%d]=%x:%x.%x", &id, &bus, &dev, &fn) == 4 || +	    sscanf(str, "[%d]=%x:%x:%x.%x", &id, &seg, &bus, &dev, &fn) == 5) { +		pr_warn("ivrs_hpet%s option format deprecated; use ivrs_hpet=%d@%04x:%02x:%02x.%d instead\n", +			str, id, seg, bus, dev, fn); +		goto found;  	} +	pr_err("Invalid command line: ivrs_hpet%s\n", str); +	return 1; + +found:  	if (early_hpet_map_size == EARLY_MAP_SIZE) {  		pr_err("Early HPET map overflow - ignoring ivrs_hpet%s\n",  			str); @@ -3466,19 +3478,36 @@ static int __init parse_ivrs_hpet(char *str)  static int __init parse_ivrs_acpihid(char *str)  {  	u32 seg = 0, bus, dev, fn; -	char *hid, *uid, *p; +	char *hid, *uid, *p, *addr;  	char acpiid[ACPIHID_UID_LEN + ACPIHID_HID_LEN] = {0}; -	int ret, i; +	int i; -	ret = sscanf(str, "[%x:%x.%x]=%s", &bus, &dev, &fn, acpiid); -	if (ret != 4) { -		ret = sscanf(str, "[%x:%x:%x.%x]=%s", &seg, &bus, &dev, &fn, acpiid); -		if (ret != 5) { -			pr_err("Invalid command line: ivrs_acpihid(%s)\n", str); -			return 1; +	addr = strchr(str, '@'); +	if (!addr) { +		if (sscanf(str, "[%x:%x.%x]=%s", &bus, &dev, &fn, acpiid) == 4 || +		    sscanf(str, "[%x:%x:%x.%x]=%s", &seg, &bus, &dev, &fn, acpiid) == 5) { +			pr_warn("ivrs_acpihid%s option format deprecated; use ivrs_acpihid=%s@%04x:%02x:%02x.%d instead\n", +				str, acpiid, seg, bus, dev, fn); +			goto found;  		} +		goto not_found;  	} +	/* We have the '@', make it the terminator to get just the acpiid */ +	*addr++ = 0; + +	if (sscanf(str, "=%s", acpiid) != 1) +		goto not_found; + +	if (sscanf(addr, "%x:%x.%x", &bus, &dev, &fn) == 3 || +	    sscanf(addr, "%x:%x:%x.%x", &seg, &bus, &dev, &fn) == 4) +		goto found; + +not_found: +	pr_err("Invalid command line: ivrs_acpihid%s\n", str); +	return 1; + +found:  	p = acpiid;  	hid = strsep(&p, ":");  	uid = p; @@ -3488,6 +3517,13 @@ static int __init parse_ivrs_acpihid(char *str)  		return 1;  	} +	/* +	 * Ignore leading zeroes after ':', so e.g., AMDI0095:00 +	 * will match AMDI0095:0 in the second strcmp in acpi_dev_hid_uid_match +	 */ +	while (*uid == '0' && *(uid + 1)) +		uid++; +  	i = early_acpihid_map_size++;  	memcpy(early_acpihid_map[i].hid, hid, strlen(hid));  	memcpy(early_acpihid_map[i].uid, uid, strlen(uid));  | 
