mirror of https://gitee.com/openkylin/linux.git
intel-iommu: Check for 'DMAR at zero' BIOS error earlier.
Chris Wright has some patches which let us fall back to swiotlb nicely if IOMMU initialisation fails. But those are a bit much for 2.6.32. Instead, let's shift the check for the biggest problem, the HP and Acer BIOS bug which reports a DMAR at physical address zero. That one can actually be checked much earlier -- before we even admit to having detected an IOMMU in the first place. So the swiotlb init goes ahead as we want. Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
This commit is contained in:
parent
799dd75b1a
commit
86cf898e1d
|
@ -175,15 +175,6 @@ dmar_parse_one_drhd(struct acpi_dmar_header *header)
|
|||
int ret = 0;
|
||||
|
||||
drhd = (struct acpi_dmar_hardware_unit *)header;
|
||||
if (!drhd->address) {
|
||||
/* Promote an attitude of violence to a BIOS engineer today */
|
||||
WARN(1, "Your BIOS is broken; DMAR reported at address zero!\n"
|
||||
"BIOS vendor: %s; Ver: %s; Product Version: %s\n",
|
||||
dmi_get_system_info(DMI_BIOS_VENDOR),
|
||||
dmi_get_system_info(DMI_BIOS_VERSION),
|
||||
dmi_get_system_info(DMI_PRODUCT_VERSION));
|
||||
return -ENODEV;
|
||||
}
|
||||
dmaru = kzalloc(sizeof(*dmaru), GFP_KERNEL);
|
||||
if (!dmaru)
|
||||
return -ENOMEM;
|
||||
|
@ -591,12 +582,50 @@ int __init dmar_table_init(void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int __init check_zero_address(void)
|
||||
{
|
||||
struct acpi_table_dmar *dmar;
|
||||
struct acpi_dmar_header *entry_header;
|
||||
struct acpi_dmar_hardware_unit *drhd;
|
||||
|
||||
dmar = (struct acpi_table_dmar *)dmar_tbl;
|
||||
entry_header = (struct acpi_dmar_header *)(dmar + 1);
|
||||
|
||||
while (((unsigned long)entry_header) <
|
||||
(((unsigned long)dmar) + dmar_tbl->length)) {
|
||||
/* Avoid looping forever on bad ACPI tables */
|
||||
if (entry_header->length == 0) {
|
||||
printk(KERN_WARNING PREFIX
|
||||
"Invalid 0-length structure\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (entry_header->type == ACPI_DMAR_TYPE_HARDWARE_UNIT) {
|
||||
drhd = (void *)entry_header;
|
||||
if (!drhd->address) {
|
||||
/* Promote an attitude of violence to a BIOS engineer today */
|
||||
WARN(1, "Your BIOS is broken; DMAR reported at address zero!\n"
|
||||
"BIOS vendor: %s; Ver: %s; Product Version: %s\n",
|
||||
dmi_get_system_info(DMI_BIOS_VENDOR),
|
||||
dmi_get_system_info(DMI_BIOS_VERSION),
|
||||
dmi_get_system_info(DMI_PRODUCT_VERSION));
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
entry_header = ((void *)entry_header + entry_header->length);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
void __init detect_intel_iommu(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = dmar_table_detect();
|
||||
|
||||
if (ret)
|
||||
ret = check_zero_address();
|
||||
{
|
||||
#ifdef CONFIG_INTR_REMAP
|
||||
struct acpi_table_dmar *dmar;
|
||||
|
|
Loading…
Reference in New Issue