Hi Linus!
This is a PCI patch for 2.3.99pre7-pre1. I haven't looked at the power management
stuff yet (hopefully I'll do so tomorrow), but there is a small bunch of useful fixes:
o /proc/pci now works even if read in small chunks.
o On ALI IRQ routers, we are also able to read current routing.
o Don't crash when the BIOS reports a non-existent IRQ router.
o Split IRQ fixup to pcibios_irq_init and pcibios_fixup_irqs. The former
needs to be called before peer bridge detection, the latter afterwards.
o request_region() PCI configuration ports.
o On SI5597/5598 chipsets, don't allow latency higher than 32
(reported by Alan to lock up the system).
Martin
--- include/linux/pci_ids.h.mj Sat Apr 29 15:00:36 2000
+++ include/linux/pci_ids.h Sat Apr 29 15:00:36 2000
@@ -332,6 +332,7 @@
#define PCI_DEVICE_ID_SI_5571 0x5571
#define PCI_DEVICE_ID_SI_5591 0x5591
#define PCI_DEVICE_ID_SI_5597 0x5597
+#define PCI_DEVICE_ID_SI_5598 0x5598
#define PCI_DEVICE_ID_SI_5600 0x5600
#define PCI_DEVICE_ID_SI_6306 0x6306
#define PCI_DEVICE_ID_SI_6326 0x6326
--- drivers/pci/proc.c.mj Sat Apr 29 14:48:42 2000
+++ drivers/pci/proc.c Sat Apr 29 14:48:42 2000
@@ -389,7 +389,7 @@
*eof = 1;
pci_for_each_dev(dev) {
- nprinted = sprint_dev_config(dev, buf + len, count - len);
+ nprinted = sprint_dev_config(dev, buf + len, PAGE_SIZE - len);
if (nprinted < 0) {
*eof = 0;
break;
--- arch/i386/kernel/pci-irq.c.mj Fri Apr 28 01:05:42 2000
+++ arch/i386/kernel/pci-irq.c Sat Apr 29 15:09:02 2000
@@ -125,11 +125,22 @@
}
}
+static int pirq_ali_get(struct pci_dev *router, struct pci_dev *dev, int pirq)
+{
+ static unsigned char irqmap[16] = { 0, 9, 3, 10, 4, 5, 7, 6, 1, 11, 0, 12, 0, 14, 0, 15 };
+ pirq--;
+ if (pirq < 8) {
+ u8 x;
+ unsigned reg = 0x48 + (pirq >> 1);
+ pci_read_config_byte(router, reg, &x);
+ return irqmap[(pirq & 1) ? (x >> 4) : (x & 0x0f)];
+ }
+ return 0;
+}
+
static int pirq_ali_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq)
{
- static unsigned char irqmap[16] = {
- 0, 8, 0, 2, 4, 5, 7, 6, 0, 1, 3, 9, 11, 0, 13, 15
- };
+ static unsigned char irqmap[16] = { 0, 8, 0, 2, 4, 5, 7, 6, 0, 1, 3, 9, 11, 0, 13, 15 };
unsigned int val = irqmap[irq];
pirq--;
if (val && pirq < 8) {
@@ -211,7 +222,7 @@
{ "PIIX", PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371FB_0, pirq_piix_get, pirq_piix_set },
{ "PIIX", PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371SB_0, pirq_piix_get, pirq_piix_set },
{ "PIIX", PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_0, pirq_piix_get, pirq_piix_set },
- { "ALI", PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, NULL, pirq_ali_set },
+ { "ALI", PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, pirq_ali_get, pirq_ali_set },
{ "VIA", PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_0, pirq_via_get, pirq_via_set },
{ "VIA", PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C596, pirq_via_get, pirq_via_set },
{ "VIA", PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686, pirq_via_get, pirq_via_set },
@@ -236,7 +247,9 @@
}
#endif
if (!(pirq_router_dev = pci_find_slot(rt->rtr_bus, rt->rtr_devfn))) {
- DBG("PCI: Interrupt router not found\n");
+ DBG("PCI: Interrupt router not found at %02x:%02x\n", rt->rtr_bus, rt->rtr_devfn);
+ /* fall back to default router */
+ pirq_router = pirq_routers + sizeof(pirq_routers) / sizeof(pirq_routers[0]) - 1;
return;
}
if (rt->rtr_vendor) {
@@ -354,12 +367,9 @@
return 1;
}
-void __init pcibios_fixup_irqs(void)
+void __init pcibios_irq_init(void)
{
- struct pci_dev *dev;
- u8 pin;
-
- DBG("PCI: IRQ fixup\n");
+ DBG("PCI: IRQ init\n");
pirq_table = pirq_find_routing_table();
#ifdef CONFIG_PCI_BIOS
if (!pirq_table && (pci_probe & PCI_BIOS_IRQ_SCAN))
@@ -369,7 +379,14 @@
pirq_peer_trick();
pirq_find_router();
}
+}
+
+void __init pcibios_fixup_irqs(void)
+{
+ struct pci_dev *dev;
+ u8 pin;
+ DBG("PCI: IRQ fixup\n");
pci_for_each_dev(dev) {
/*
* If the BIOS has set an out of range IRQ number, just ignore it.
--- arch/i386/kernel/pci-pc.c.mj Sat Apr 29 14:52:43 2000
+++ arch/i386/kernel/pci-pc.c Sat Apr 29 15:02:56 2000
@@ -10,6 +10,7 @@
#include <linux/sched.h>
#include <linux/pci.h>
#include <linux/init.h>
+#include <linux/ioport.h>
#include <asm/segment.h>
#include <asm/io.h>
@@ -208,6 +209,7 @@
outl (tmp, 0xCF8);
__restore_flags(flags);
printk("PCI: Using configuration type 1\n");
+ request_region(0xCF8, 8, "PCI conf1");
return &pci_direct_conf1;
}
outl (tmp, 0xCF8);
@@ -224,6 +226,7 @@
pci_sanity_check(&pci_direct_conf2)) {
__restore_flags(flags);
printk("PCI: Using configuration type 2\n");
+ request_region(0xCF8, 4, "PCI conf2");
return &pci_direct_conf2;
}
}
@@ -912,6 +915,16 @@
d->resource[i].start = d->resource[i].end = d->resource[i].flags = 0;
}
+static void __init pci_fixup_latency(struct pci_dev *d)
+{
+ /*
+ * SiS 5597 and 5598 chipsets require latency timer set to
+ * at most 32 to avoid lockups.
+ */
+ DBG("PCI: Setting max latency to 32\n");
+ pcibios_max_latency = 32;
+}
+
struct pci_fixup pcibios_fixups[] = {
{ PCI_FIXUP_HEADER, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82451NX, pci_fixup_i450nx },
{ PCI_FIXUP_HEADER, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82454GX, pci_fixup_i450gx },
@@ -921,6 +934,8 @@
{ PCI_FIXUP_HEADER, PCI_VENDOR_ID_UMC, PCI_DEVICE_ID_UMC_UM8886BF, pci_fixup_umc_ide },
{ PCI_FIXUP_HEADER, PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_5513, pci_fixup_ide_trash },
{ PCI_FIXUP_HEADER, PCI_ANY_ID, PCI_ANY_ID, pci_fixup_ide_bases },
+ { PCI_FIXUP_HEADER, PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_5597, pci_fixup_latency },
+ { PCI_FIXUP_HEADER, PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_5598, pci_fixup_latency },
{ 0 }
};
@@ -969,8 +984,9 @@
printk("PCI: Probing PCI hardware\n");
pci_root_bus = pci_scan_bus(0, pci_root_ops, NULL);
- pcibios_fixup_irqs();
+ pcibios_irq_init();
pcibios_fixup_peer_bridges();
+ pcibios_fixup_irqs();
pcibios_resource_survey();
#ifdef CONFIG_PCI_BIOS
--- arch/i386/kernel/pci-i386.h.mj Sat Apr 29 14:53:42 2000
+++ arch/i386/kernel/pci-i386.h Sat Apr 29 15:03:14 2000
@@ -25,6 +25,8 @@
/* pci-i386.c */
+extern unsigned int pcibios_max_latency;
+
void pcibios_resource_survey(void);
int pcibios_enable_resources(struct pci_dev *);
@@ -64,5 +66,6 @@
extern unsigned int pcibios_irq_mask;
+void pcibios_irq_init(void);
void pcibios_fixup_irqs(void);
int pcibios_lookup_irq(struct pci_dev *dev, int assign);
--- arch/i386/kernel/pci-i386.c.mj Sat Apr 29 14:57:06 2000
+++ arch/i386/kernel/pci-i386.c Sat Apr 29 14:57:06 2000
@@ -330,12 +330,18 @@
* If we set up a device for bus mastering, we need to check the latency
* timer as certain crappy BIOSes forget to set it properly.
*/
+unsigned int pcibios_max_latency = 255;
+
void pcibios_set_master(struct pci_dev *dev)
{
u8 lat;
pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lat);
- if (lat < 16) {
- printk("PCI: Increasing latency timer of device %s to 64\n", dev->slot_name);
- pci_write_config_byte(dev, PCI_LATENCY_TIMER, 64);
- }
+ if (lat < 16)
+ lat = (64 <= pcibios_max_latency) ? 64 : pcibios_max_latency;
+ else if (lat > pcibios_max_latency)
+ lat = pcibios_max_latency;
+ else
+ return;
+ printk("PCI: Setting latency timer of device %s to %d\n", dev->slot_name, lat);
+ pci_write_config_byte(dev, PCI_LATENCY_TIMER, lat);
}
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/
This archive was generated by hypermail 2b29 : Sun Apr 30 2000 - 21:00:16 EST