aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sh/drivers/pci/pci.c
diff options
context:
space:
mode:
authorPaul Mundt <lethal@linux-sh.org>2010-02-03 02:46:20 -0500
committerPaul Mundt <lethal@linux-sh.org>2010-02-03 02:46:20 -0500
commit9ad62ec4f752c82b39aa5927f23d894b46ae10b9 (patch)
tree546f4572329478e849408fe129e44625881f9992 /arch/sh/drivers/pci/pci.c
parent37feecb0ae8c29b713b957c053b05ad10c42c73b (diff)
sh: Fix up early PCI PERR/SERR IRQ handling.
This adds support for handling early PERR/SERR triggering in between controller registration and the initial bus scan. Buggy cards end up asserting these as soon as the M66EN scan is undertaken, resulting in an early crash. Signed-off-by: Paul Mundt <lethal@linux-sh.org>
Diffstat (limited to 'arch/sh/drivers/pci/pci.c')
-rw-r--r--arch/sh/drivers/pci/pci.c51
1 files changed, 42 insertions, 9 deletions
diff --git a/arch/sh/drivers/pci/pci.c b/arch/sh/drivers/pci/pci.c
index f4a69833fce2..41d8f014f1df 100644
--- a/arch/sh/drivers/pci/pci.c
+++ b/arch/sh/drivers/pci/pci.c
@@ -204,7 +204,7 @@ void pcibios_align_resource(void *data, struct resource *res,
204} 204}
205 205
206void pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region, 206void pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
207 struct resource *res) 207 struct resource *res)
208{ 208{
209 struct pci_channel *hose = dev->sysdata; 209 struct pci_channel *hose = dev->sysdata;
210 unsigned long offset = 0; 210 unsigned long offset = 0;
@@ -218,9 +218,8 @@ void pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
218 region->end = res->end - offset; 218 region->end = res->end - offset;
219} 219}
220 220
221void __devinit 221void pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res,
222pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res, 222 struct pci_bus_region *region)
223 struct pci_bus_region *region)
224{ 223{
225 struct pci_channel *hose = dev->sysdata; 224 struct pci_channel *hose = dev->sysdata;
226 unsigned long offset = 0; 225 unsigned long offset = 0;
@@ -303,12 +302,41 @@ char * __devinit pcibios_setup(char *str)
303 return str; 302 return str;
304} 303}
305 304
305static void __init
306pcibios_bus_report_status_early(struct pci_channel *hose,
307 int top_bus, int current_bus,
308 unsigned int status_mask, int warn)
309{
310 unsigned int pci_devfn;
311 u16 status;
312 int ret;
313
314 for (pci_devfn = 0; pci_devfn < 0xff; pci_devfn++) {
315 if (PCI_FUNC(pci_devfn))
316 continue;
317 ret = early_read_config_word(hose, top_bus, current_bus,
318 pci_devfn, PCI_STATUS, &status);
319 if (ret != PCIBIOS_SUCCESSFUL)
320 continue;
321 if (status == 0xffff)
322 continue;
323
324 early_write_config_word(hose, top_bus, current_bus,
325 pci_devfn, PCI_STATUS,
326 status & status_mask);
327 if (warn)
328 printk("(%02x:%02x: %04X) ", current_bus,
329 pci_devfn, status);
330 }
331}
332
306/* 333/*
307 * We can't use pci_find_device() here since we are 334 * We can't use pci_find_device() here since we are
308 * called from interrupt context. 335 * called from interrupt context.
309 */ 336 */
310static void pcibios_bus_report_status(struct pci_bus *bus, 337static void __init_refok
311 unsigned int status_mask, int warn) 338pcibios_bus_report_status(struct pci_bus *bus, unsigned int status_mask,
339 int warn)
312{ 340{
313 struct pci_dev *dev; 341 struct pci_dev *dev;
314 342
@@ -341,12 +369,17 @@ static void pcibios_bus_report_status(struct pci_bus *bus,
341 pcibios_bus_report_status(dev->subordinate, status_mask, warn); 369 pcibios_bus_report_status(dev->subordinate, status_mask, warn);
342} 370}
343 371
344void pcibios_report_status(unsigned int status_mask, int warn) 372void __init_refok pcibios_report_status(unsigned int status_mask, int warn)
345{ 373{
346 struct pci_channel *hose; 374 struct pci_channel *hose;
347 375
348 for (hose = hose_head; hose; hose = hose->next) 376 for (hose = hose_head; hose; hose = hose->next) {
349 pcibios_bus_report_status(hose->bus, status_mask, warn); 377 if (unlikely(!hose->bus))
378 pcibios_bus_report_status_early(hose, hose_head->index,
379 hose->index, status_mask, warn);
380 else
381 pcibios_bus_report_status(hose->bus, status_mask, warn);
382 }
350} 383}
351 384
352int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma, 385int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,