diff options
author | Yinghai Lu <yinghai@kernel.org> | 2013-03-28 00:28:05 -0400 |
---|---|---|
committer | Bjorn Helgaas <bhelgaas@google.com> | 2013-04-01 14:02:05 -0400 |
commit | c5fb301ae83bec6892e54984e6ec765c47df8e10 (patch) | |
tree | b8b55517ba6a0ab9076cb5071fbc91becd2c61ec /drivers/eisa | |
parent | 2cfda637e29ce9e3df31b59f64516b2e571cc985 (diff) |
EISA/PCI: Init EISA early, before PNP
Matthew reported kernels fail the pci_eisa probe and are later successful
with the virtual_eisa_root_init force probe without slot0.
The reason for that is: PNP probing is before pci_eisa_init gets called
as pci_eisa_init is called via pci_driver.
pnp 00:0f has 0xc80 - 0xc84 reserved.
[ 9.700409] pnp 00:0f: [io 0x0c80-0x0c84]
so eisa_probe will fail from pci_eisa_init
==>eisa_root_register
==>eisa_probe path.
as force_probe is not set in pci_eisa_root, it will bail early when
slot0 is not probed and initialized.
Try to use subsys_initcall_sync instead, and will keep following sequence:
pci_subsys_init
pci_eisa_init_early
pnpacpi_init/isapnp_init
After this patch EISA can be initialized properly, and PNP overlapping
resource will not be reserved.
[ 10.104434] system 00:0f: [io 0x0c80-0x0c84] could not be reserved
Reported-by: Matthew Whitehead <mwhitehe@redhat.com>
Tested-by: Matthew Whitehead <mwhitehe@redhat.com>
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Cc: stable@vger.kernel.org
Diffstat (limited to 'drivers/eisa')
-rw-r--r-- | drivers/eisa/pci_eisa.c | 39 |
1 files changed, 21 insertions, 18 deletions
diff --git a/drivers/eisa/pci_eisa.c b/drivers/eisa/pci_eisa.c index ef5c3ec87432..6c3fca97d346 100644 --- a/drivers/eisa/pci_eisa.c +++ b/drivers/eisa/pci_eisa.c | |||
@@ -19,8 +19,7 @@ | |||
19 | /* There is only *one* pci_eisa device per machine, right ? */ | 19 | /* There is only *one* pci_eisa device per machine, right ? */ |
20 | static struct eisa_root_device pci_eisa_root; | 20 | static struct eisa_root_device pci_eisa_root; |
21 | 21 | ||
22 | static int __init pci_eisa_init(struct pci_dev *pdev, | 22 | static int __init pci_eisa_init(struct pci_dev *pdev) |
23 | const struct pci_device_id *ent) | ||
24 | { | 23 | { |
25 | int rc, i; | 24 | int rc, i; |
26 | struct resource *res, *bus_res = NULL; | 25 | struct resource *res, *bus_res = NULL; |
@@ -67,22 +66,26 @@ static int __init pci_eisa_init(struct pci_dev *pdev, | |||
67 | return 0; | 66 | return 0; |
68 | } | 67 | } |
69 | 68 | ||
70 | static struct pci_device_id pci_eisa_pci_tbl[] = { | 69 | /* |
71 | { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, | 70 | * We have to call pci_eisa_init_early() before pnpacpi_init()/isapnp_init(). |
72 | PCI_CLASS_BRIDGE_EISA << 8, 0xffff00, 0 }, | 71 | * Otherwise pnp resource will get enabled early and could prevent eisa |
73 | { 0, } | 72 | * to be initialized. |
74 | }; | 73 | * Also need to make sure pci_eisa_init_early() is called after |
74 | * x86/pci_subsys_init(). | ||
75 | * So need to use subsys_initcall_sync with it. | ||
76 | */ | ||
77 | static int __init pci_eisa_init_early(void) | ||
78 | { | ||
79 | struct pci_dev *dev = NULL; | ||
80 | int ret; | ||
75 | 81 | ||
76 | static struct pci_driver __refdata pci_eisa_driver = { | 82 | for_each_pci_dev(dev) |
77 | .name = "pci_eisa", | 83 | if ((dev->class >> 8) == PCI_CLASS_BRIDGE_EISA) { |
78 | .id_table = pci_eisa_pci_tbl, | 84 | ret = pci_eisa_init(dev); |
79 | .probe = pci_eisa_init, | 85 | if (ret) |
80 | }; | 86 | return ret; |
87 | } | ||
81 | 88 | ||
82 | static int __init pci_eisa_init_module (void) | 89 | return 0; |
83 | { | ||
84 | return pci_register_driver (&pci_eisa_driver); | ||
85 | } | 90 | } |
86 | 91 | subsys_initcall_sync(pci_eisa_init_early); | |
87 | device_initcall(pci_eisa_init_module); | ||
88 | MODULE_DEVICE_TABLE(pci, pci_eisa_pci_tbl); | ||