PCI patch for 2.3.99pre7-pre1

From: Martin Mares (mj@suse.cz)
Date: Sat Apr 29 2000 - 10:03:31 EST


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