Commit 1597cacb authored by Alan Cox's avatar Alan Cox Committed by Greg Kroah-Hartman

PCI: Fix multiple problems with VIA hardware

This patch is designed to fix:
- Disk eating corruptor on KT7 after resume from RAM
- VIA IRQ handling
- VIA fixups for bus lockups after resume from RAM

The core of this is to add a table of resume fixups run at resume time.
We need to do this for a variety of boards and features, but particularly
we need to do this to get various critical VIA fixups done on resume.

The second part of the problem is to handle VIA IRQ number rules which
are a bit odd and need special handling for PIC interrupts. Various
patches broke various boxes and while this one may not be perfect
(hopefully it is) it ensures the workaround is applied to the right
devices only.

From: Jean Delvare <khali@linux-fr.org>

Now that PCI quirks are replayed on software resume, we can safely
re-enable the Asus SMBus unhiding quirk even when software suspend support
is enabled.

[akpm@osdl.org: fix const warning]
Signed-off-by: default avatarAlan Cox <alan@redhat.com>
Cc: Jean Delvare <khali@linux-fr.org>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent beb7cc82
...@@ -115,7 +115,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_3, pci ...@@ -115,7 +115,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_3, pci
#define VIA_8363_KL133_REVISION_ID 0x81 #define VIA_8363_KL133_REVISION_ID 0x81
#define VIA_8363_KM133_REVISION_ID 0x84 #define VIA_8363_KM133_REVISION_ID 0x84
static void __devinit pci_fixup_via_northbridge_bug(struct pci_dev *d) static void pci_fixup_via_northbridge_bug(struct pci_dev *d)
{ {
u8 v; u8 v;
u8 revision; u8 revision;
...@@ -151,6 +151,10 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8363_0, pci_fixup_ ...@@ -151,6 +151,10 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8363_0, pci_fixup_
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8622, pci_fixup_via_northbridge_bug); DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8622, pci_fixup_via_northbridge_bug);
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8361, pci_fixup_via_northbridge_bug); DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8361, pci_fixup_via_northbridge_bug);
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8367_0, pci_fixup_via_northbridge_bug); DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8367_0, pci_fixup_via_northbridge_bug);
DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8363_0, pci_fixup_via_northbridge_bug);
DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8622, pci_fixup_via_northbridge_bug);
DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8361, pci_fixup_via_northbridge_bug);
DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8367_0, pci_fixup_via_northbridge_bug);
/* /*
* For some reasons Intel decided that certain parts of their * For some reasons Intel decided that certain parts of their
...@@ -181,7 +185,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_ANY_ID, pci_fixup_transparent_ ...@@ -181,7 +185,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_ANY_ID, pci_fixup_transparent_
* issue another HALT within 80 ns of the initial HALT, the failure condition * issue another HALT within 80 ns of the initial HALT, the failure condition
* is avoided. * is avoided.
*/ */
static void __init pci_fixup_nforce2(struct pci_dev *dev) static void pci_fixup_nforce2(struct pci_dev *dev)
{ {
u32 val; u32 val;
...@@ -204,6 +208,7 @@ static void __init pci_fixup_nforce2(struct pci_dev *dev) ...@@ -204,6 +208,7 @@ static void __init pci_fixup_nforce2(struct pci_dev *dev)
} }
} }
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE2, pci_fixup_nforce2); DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE2, pci_fixup_nforce2);
DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE2, pci_fixup_nforce2);
/* Max PCI Express root ports */ /* Max PCI Express root ports */
#define MAX_PCIEROOT 6 #define MAX_PCIEROOT 6
...@@ -419,7 +424,7 @@ DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_TI, 0x8032, ...@@ -419,7 +424,7 @@ DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_TI, 0x8032,
* Prevent the BIOS trapping accesses to the Cyrix CS5530A video device * Prevent the BIOS trapping accesses to the Cyrix CS5530A video device
* configuration space. * configuration space.
*/ */
static void __devinit pci_early_fixup_cyrix_5530(struct pci_dev *dev) static void pci_early_fixup_cyrix_5530(struct pci_dev *dev)
{ {
u8 r; u8 r;
/* clear 'F4 Video Configuration Trap' bit */ /* clear 'F4 Video Configuration Trap' bit */
...@@ -429,3 +434,5 @@ static void __devinit pci_early_fixup_cyrix_5530(struct pci_dev *dev) ...@@ -429,3 +434,5 @@ static void __devinit pci_early_fixup_cyrix_5530(struct pci_dev *dev)
} }
DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5530_LEGACY, DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5530_LEGACY,
pci_early_fixup_cyrix_5530); pci_early_fixup_cyrix_5530);
DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5530_LEGACY,
pci_early_fixup_cyrix_5530);
...@@ -353,6 +353,8 @@ static int pci_device_resume_early(struct device * dev) ...@@ -353,6 +353,8 @@ static int pci_device_resume_early(struct device * dev)
struct pci_dev * pci_dev = to_pci_dev(dev); struct pci_dev * pci_dev = to_pci_dev(dev);
struct pci_driver * drv = pci_dev->driver; struct pci_driver * drv = pci_dev->driver;
pci_fixup_device(pci_fixup_resume, pci_dev);
if (drv && drv->resume_early) if (drv && drv->resume_early)
error = drv->resume_early(pci_dev); error = drv->resume_early(pci_dev);
return error; return error;
......
This diff is collapsed.
...@@ -416,7 +416,7 @@ struct pci_dev *pci_get_class(unsigned int class, struct pci_dev *from) ...@@ -416,7 +416,7 @@ struct pci_dev *pci_get_class(unsigned int class, struct pci_dev *from)
const struct pci_device_id *pci_find_present(const struct pci_device_id *ids) const struct pci_device_id *pci_find_present(const struct pci_device_id *ids)
{ {
struct pci_dev *dev; struct pci_dev *dev;
struct pci_device_id * found = NULL; const struct pci_device_id *found = NULL;
WARN_ON(in_interrupt()); WARN_ON(in_interrupt());
down_read(&pci_bus_sem); down_read(&pci_bus_sem);
...@@ -442,7 +442,6 @@ const struct pci_device_id *pci_find_present(const struct pci_device_id *ids) ...@@ -442,7 +442,6 @@ const struct pci_device_id *pci_find_present(const struct pci_device_id *ids)
* find devices that are usually built into a system, or for a general hint as * find devices that are usually built into a system, or for a general hint as
* to if another device happens to be present at this specific moment in time. * to if another device happens to be present at this specific moment in time.
*/ */
int pci_dev_present(const struct pci_device_id *ids) int pci_dev_present(const struct pci_device_id *ids)
{ {
return pci_find_present(ids) == NULL ? 0 : 1; return pci_find_present(ids) == NULL ? 0 : 1;
......
...@@ -35,6 +35,9 @@ ...@@ -35,6 +35,9 @@
VMLINUX_SYMBOL(__start_pci_fixups_enable) = .; \ VMLINUX_SYMBOL(__start_pci_fixups_enable) = .; \
*(.pci_fixup_enable) \ *(.pci_fixup_enable) \
VMLINUX_SYMBOL(__end_pci_fixups_enable) = .; \ VMLINUX_SYMBOL(__end_pci_fixups_enable) = .; \
VMLINUX_SYMBOL(__start_pci_fixups_resume) = .; \
*(.pci_fixup_resume) \
VMLINUX_SYMBOL(__end_pci_fixups_resume) = .; \
} \ } \
\ \
/* RapidIO route ops */ \ /* RapidIO route ops */ \
......
...@@ -396,6 +396,21 @@ struct pci_driver { ...@@ -396,6 +396,21 @@ struct pci_driver {
*/ */
#define pci_module_init pci_register_driver #define pci_module_init pci_register_driver
/**
* PCI_VDEVICE - macro used to describe a specific pci device in short form
* @vend: the vendor name
* @dev: the 16 bit PCI Device ID
*
* This macro is used to create a struct pci_device_id that matches a
* specific PCI device. The subvendor, and subdevice fields will be set
* to PCI_ANY_ID. The macro allows the next field to follow as the device
* private data.
*/
#define PCI_VDEVICE(vendor, device) \
PCI_VENDOR_ID_##vendor, (device), \
PCI_ANY_ID, PCI_ANY_ID, 0, 0
/* these external functions are only available when PCI support is enabled */ /* these external functions are only available when PCI support is enabled */
#ifdef CONFIG_PCI #ifdef CONFIG_PCI
...@@ -787,6 +802,7 @@ enum pci_fixup_pass { ...@@ -787,6 +802,7 @@ enum pci_fixup_pass {
pci_fixup_header, /* After reading configuration header */ pci_fixup_header, /* After reading configuration header */
pci_fixup_final, /* Final phase of device fixups */ pci_fixup_final, /* Final phase of device fixups */
pci_fixup_enable, /* pci_enable_device() time */ pci_fixup_enable, /* pci_enable_device() time */
pci_fixup_resume, /* pci_enable_device() time */
}; };
/* Anonymous variables would be nice... */ /* Anonymous variables would be nice... */
...@@ -805,6 +821,9 @@ enum pci_fixup_pass { ...@@ -805,6 +821,9 @@ enum pci_fixup_pass {
#define DECLARE_PCI_FIXUP_ENABLE(vendor, device, hook) \ #define DECLARE_PCI_FIXUP_ENABLE(vendor, device, hook) \
DECLARE_PCI_FIXUP_SECTION(.pci_fixup_enable, \ DECLARE_PCI_FIXUP_SECTION(.pci_fixup_enable, \
vendor##device##hook, vendor, device, hook) vendor##device##hook, vendor, device, hook)
#define DECLARE_PCI_FIXUP_RESUME(vendor, device, hook) \
DECLARE_PCI_FIXUP_SECTION(.pci_fixup_resume, \
resume##vendor##device##hook, vendor, device, hook)
void pci_fixup_device(enum pci_fixup_pass pass, struct pci_dev *dev); void pci_fixup_device(enum pci_fixup_pass pass, struct pci_dev *dev);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment