mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2025-01-08 14:13:53 +00:00
ibft: Fix finding IBFT ACPI table on UEFI
Found one system with UEFI/iBFT, kernel does not detect the iBFT during iscsi_ibft module loading. Root cause: on x86 (UEFI), we are calling of find_ibft_region() much earlier - specifically in setup_arch() before ACPI is enabled. Try to split acpi checking code out and call that later At that time ACPI iBFT already get permanent mapped with ioremap. So isa_virt_to_bus() will get wrong phys from right virt address. We could just skip that phys address printing. For legacy one, print the found address early. -v2: update comments and description according to Konrad. -v3: fix problem about module use case that is found by Konrad. -v4: use acpi_get_table() instead of acpi_table_parse() to handle module use case that is found by Konrad again.. Signed-off-by: Yinghai Lu <yinghai@kernel.org> Signed-off-by: Konrad Rzeszutek Wilk <konrad@kernel.org>
This commit is contained in:
parent
5611cc4572
commit
935a9fee51
@ -746,6 +746,37 @@ static void __exit ibft_exit(void)
|
|||||||
ibft_cleanup();
|
ibft_cleanup();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_ACPI
|
||||||
|
static const struct {
|
||||||
|
char *sign;
|
||||||
|
} ibft_signs[] = {
|
||||||
|
/*
|
||||||
|
* One spec says "IBFT", the other says "iBFT". We have to check
|
||||||
|
* for both.
|
||||||
|
*/
|
||||||
|
{ ACPI_SIG_IBFT },
|
||||||
|
{ "iBFT" },
|
||||||
|
};
|
||||||
|
|
||||||
|
static void __init acpi_find_ibft_region(void)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
struct acpi_table_header *table = NULL;
|
||||||
|
|
||||||
|
if (acpi_disabled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (i = 0; i < ARRAY_SIZE(ibft_signs) && !ibft_addr; i++) {
|
||||||
|
acpi_get_table(ibft_signs[i].sign, 0, &table);
|
||||||
|
ibft_addr = (struct acpi_table_ibft *)table;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
static void __init acpi_find_ibft_region(void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ibft_init() - creates sysfs tree entries for the iBFT data.
|
* ibft_init() - creates sysfs tree entries for the iBFT data.
|
||||||
*/
|
*/
|
||||||
@ -753,9 +784,16 @@ static int __init ibft_init(void)
|
|||||||
{
|
{
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
As on UEFI systems the setup_arch()/find_ibft_region()
|
||||||
|
is called before ACPI tables are parsed and it only does
|
||||||
|
legacy finding.
|
||||||
|
*/
|
||||||
|
if (!ibft_addr)
|
||||||
|
acpi_find_ibft_region();
|
||||||
|
|
||||||
if (ibft_addr) {
|
if (ibft_addr) {
|
||||||
printk(KERN_INFO "iBFT detected at 0x%llx.\n",
|
pr_info("iBFT detected.\n");
|
||||||
(u64)isa_virt_to_bus(ibft_addr));
|
|
||||||
|
|
||||||
rc = ibft_check_device();
|
rc = ibft_check_device();
|
||||||
if (rc)
|
if (rc)
|
||||||
|
@ -45,13 +45,6 @@ EXPORT_SYMBOL_GPL(ibft_addr);
|
|||||||
static const struct {
|
static const struct {
|
||||||
char *sign;
|
char *sign;
|
||||||
} ibft_signs[] = {
|
} ibft_signs[] = {
|
||||||
#ifdef CONFIG_ACPI
|
|
||||||
/*
|
|
||||||
* One spec says "IBFT", the other says "iBFT". We have to check
|
|
||||||
* for both.
|
|
||||||
*/
|
|
||||||
{ ACPI_SIG_IBFT },
|
|
||||||
#endif
|
|
||||||
{ "iBFT" },
|
{ "iBFT" },
|
||||||
{ "BIFT" }, /* Broadcom iSCSI Offload */
|
{ "BIFT" }, /* Broadcom iSCSI Offload */
|
||||||
};
|
};
|
||||||
@ -62,14 +55,6 @@ static const struct {
|
|||||||
#define VGA_MEM 0xA0000 /* VGA buffer */
|
#define VGA_MEM 0xA0000 /* VGA buffer */
|
||||||
#define VGA_SIZE 0x20000 /* 128kB */
|
#define VGA_SIZE 0x20000 /* 128kB */
|
||||||
|
|
||||||
#ifdef CONFIG_ACPI
|
|
||||||
static int __init acpi_find_ibft(struct acpi_table_header *header)
|
|
||||||
{
|
|
||||||
ibft_addr = (struct acpi_table_ibft *)header;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
#endif /* CONFIG_ACPI */
|
|
||||||
|
|
||||||
static int __init find_ibft_in_mem(void)
|
static int __init find_ibft_in_mem(void)
|
||||||
{
|
{
|
||||||
unsigned long pos;
|
unsigned long pos;
|
||||||
@ -94,6 +79,7 @@ static int __init find_ibft_in_mem(void)
|
|||||||
* the table cannot be valid. */
|
* the table cannot be valid. */
|
||||||
if (pos + len <= (IBFT_END-1)) {
|
if (pos + len <= (IBFT_END-1)) {
|
||||||
ibft_addr = (struct acpi_table_ibft *)virt;
|
ibft_addr = (struct acpi_table_ibft *)virt;
|
||||||
|
pr_info("iBFT found at 0x%lx.\n", pos);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -108,20 +94,12 @@ static int __init find_ibft_in_mem(void)
|
|||||||
*/
|
*/
|
||||||
unsigned long __init find_ibft_region(unsigned long *sizep)
|
unsigned long __init find_ibft_region(unsigned long *sizep)
|
||||||
{
|
{
|
||||||
#ifdef CONFIG_ACPI
|
|
||||||
int i;
|
|
||||||
#endif
|
|
||||||
ibft_addr = NULL;
|
ibft_addr = NULL;
|
||||||
|
|
||||||
#ifdef CONFIG_ACPI
|
|
||||||
for (i = 0; i < ARRAY_SIZE(ibft_signs) && !ibft_addr; i++)
|
|
||||||
acpi_table_parse(ibft_signs[i].sign, acpi_find_ibft);
|
|
||||||
#endif /* CONFIG_ACPI */
|
|
||||||
|
|
||||||
/* iBFT 1.03 section 1.4.3.1 mandates that UEFI machines will
|
/* iBFT 1.03 section 1.4.3.1 mandates that UEFI machines will
|
||||||
* only use ACPI for this */
|
* only use ACPI for this */
|
||||||
|
|
||||||
if (!ibft_addr && !efi_enabled)
|
if (!efi_enabled)
|
||||||
find_ibft_in_mem();
|
find_ibft_in_mem();
|
||||||
|
|
||||||
if (ibft_addr) {
|
if (ibft_addr) {
|
||||||
|
Loading…
Reference in New Issue
Block a user