[PATCH] 2.4.4 PCI FBB
Hi Ivan, Jeff, Appended is the 2.4.4 patch for PCI Fast Back-Back (FBB) support. Could you please review/comment on it? Some caveats/notes: o Since I'm on the road (visiting relatives in Germany mostly, currently in Zurich), I'm only able to verify it boots on my Omnibook 800. PA-RISC port is still based on 2.4.0 so I can't test there. My lxr8000 (in Cupertino) doesn't reboot remotely reliably. Consider this a first cut. o I've added logic to pull the secondary PCI bus out of reset properly in case the PCI-PCI bridge not been initialized by BIOS. This was implicitly happening before in pci_setup_bridge(). The OB800 has a *broken* VLSI PCI-PCI bridge onboard with respect to the BUS_RESET bit - see the "KLUGE ALERT". o "lspci" segfaults on the OB800. I don't know why. I don't think it's related to any changes I've made. I'm running debian "unstable" and haven't been able to update in several weeks. If it persists after an update, then I'll chase it. o Ivan proposed pcibios_set_bridge_ctl(); I used "pcibios_init_bus()". The calling location in pci_do_scan_bus() seemed like a per-bus initialization point rather than a narrow/specific task. I'd like to make use of pcibios_init_bus() in the parisc port. I've only modified arch/i386 to provide pcibios_init_bus(). o For each secondary bus, pci_setup_bridge() gets called before pcibios_init_bus(). The former handles generic PCI-PCI bridge and the later deals with arch specific (eg Host-PCI bridge) stuff. However the difference is on the primary bus - only pcibios_init_bus() is called. FWIW, PA-RISC host-PCI bridges support FBB and I would like to add support to enable FBB on the primary busses (yes - plural!). o I intentionally put all FBB support in pci_setup_bridge() (arch common). FBB could also live in the arch specific location (pcibios_init_bus()) but then that gets replicated for each arch. Not sure if that's a problem or not. The trade off is how arch code interacts with common code for FBB support on the primary bus(ses). thanks! grant --- 2.4.4-orig/arch/i386/kernel/pci-i386.c Mon Aug 7 14:31:40 2000 +++ 2.4.4/arch/i386/kernel/pci-i386.c Sun Jun 17 02:30:29 2001 @@ -324,6 +324,11 @@ int pcibios_enable_resources(struct pci_ } if (dev->resource[PCI_ROM_RESOURCE].start) cmd |= PCI_COMMAND_MEMORY; + + /* If bridge/bus controller has FBB enabled, child must too. */ + if (dev->bus->bridge_ctl & PCI_BRIDGE_CTL_FAST_BACK) + cmd |= PCI_COMMAND_FAST_BACK; + if (cmd != old_cmd) { printk("PCI: Enabling device %s (%04x -> %04x)\n", dev->slot_name, old_cmd, cmd); pci_write_config_word(dev, PCI_COMMAND, cmd); --- 2.4.4-orig/arch/i386/kernel/pci-pc.cThu Apr 19 22:57:06 2001 +++ 2.4.4/arch/i386/kernel/pci-pc.c Sun Jun 17 02:46:26 2001 @@ -11,6 +11,7 @@ #include #include #include +#include #include #include @@ -1015,6 +1016,29 @@ struct pci_fixup pcibios_fixups[] = { }; /* + * Called before each bus is probed. Allows us to tweak struct pci_bus *. + */ +void __init pcibios_init_bus(struct pci_bus *b) +{ + struct pci_dev *dev = b->self; + + /* If host PCI bridge supports FBB, could add support here and + ** in pcibios_fixup_bus(). For the moment, hope the BIOS is + ** smart enough to take advantage of FBB. + */ + + /* don't forward all "ISA" IO addresses */ + if (dev && (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) + && ((dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) + && !(b->bridge_ctl | PCI_BRIDGE_CTL_NO_ISA) ) + { + b->bridge_ctl |= PCI_BRIDGE_CTL_NO_ISA; + pci_write_config_word(dev, PCI_BRIDGE_CONTROL, b->bridge_ctl); + } +} + + +/* * Called after each bus is probed, but before its children * are examined. */ @@ -1023,6 +1047,11 @@ void __init pcibios_fixup_bus(struct pci { pcibios_fixup_ghosts(b); pci_read_bridge_bases(b); + + /* if any i386 PCI host bus adapters support FBB, test FBB bit + ** in b->bridge_ctl (dis-) enable FBB in the host bus adapter. + ** Also look at comments in pcibios_init_bus(). + */ } /* --- 2.4.4-orig/drivers/pci/pci.cThu Apr 19 08:38:48 2001 +++ 2.4.4/drivers/pci/pci.c Sun Jun 17 03:06:58 2001 @@ -36,6 +36,7 @@ LIST_HEAD(pci_root_buses); LIST_HEAD(pci_devices); +unsigned int pci_post_reset_delay = 50;/* spec says 1sec but this works */ /** * pci_find_slot - locate PCI device from a given PCI slot @@ -978,9 +979,17 @@ static int __init pci_scan_bridge(struct } } else { /* -* We need to assign a number to this bus which we always -* do in the second pass. We also keep all address decoders -* on the bridge disabled during scanning. FIXME: Why? +* Assign a number to this
Re: [PATCH] 2.4.4 PCI FBB
On Sat, Jun 23, 2001 at 02:33:54PM -0600, Grant Grundler wrote: > Ivan, > I just got back to reading my mailoffline for three days > in switzerland. I've been offline for last few days, too... > > I also have some PCI fixes/cleanups for your review)... > > ok. I look forward to them...they are probably deeper in my mail queue. No, sorry. I would like to integrate your FBB stuff, but had no time yet... Anyway, here is a patch (not for inclusion! :-). It applies cleanly to 2.4.6-pre5 (or to 2.4.5 with offsets) and was reasonably well tested on my alphas. Changes: - bus resources were not added to the resource tree properly. This bug is harmless in most configurations, but could be triggered by some driver requesting resources in the run-time. - as you proposed a while back, code from arch-specific pcibios_fixup_bus() is now moved to generic pbus_assign_resources(). Hopefully this makes PPB code a bit cleaner. - on the contrary, code disabling pci devices before reallocation is now arch-specific, as various platforms may have different console devices. pdev_enable_device() killed thus. On alpha I renamed it to pcibios_postalloc_fixup(). - pcibios_set_bridge_ctl() introduced, but this likely has to be changed/renamed for FBB support. These changes currently are only for alpha and would break ARM... Some thoughts of your patch: - I'm not sure that we need a new field in the struct pci_bus -- we have plenty of room in the bridge/bus->resource[N]->flags (I used it for IORESOURCE_BUS_HAS_VGA, same could be done for, say, IORESOURCE_BUS_FBB etc.)? - it seems that pcibios_init_bus() will be actually called *before* pci_setup_bridge(), at least on alpha. So initializing the FBB bit should be done in pcibios_init_bus(). Ivan. --- 2.4.6/include/linux/pci.h Thu Jun 14 14:10:34 2001 +++ linux/include/linux/pci.h Thu Jun 14 14:12:12 2001 @@ -501,6 +501,7 @@ void pcibios_update_resource(struct pci_ struct resource *, int); void pcibios_update_irq(struct pci_dev *, int irq); void pcibios_fixup_pbus_ranges(struct pci_bus *, struct pbus_set_ranges_data *); +void pcibios_set_bridge_ctl(struct pci_dev *); /* Backward compatibility, don't use in new code! */ @@ -571,9 +572,7 @@ int pci_enable_wake(struct pci_dev *dev, int pci_claim_resource(struct pci_dev *, int); void pci_assign_unassigned_resources(void); -void pdev_enable_device(struct pci_dev *); void pdev_sort_resources(struct pci_dev *, struct resource_list *, u32); -unsigned long pci_bridge_check_io(struct pci_dev *); void pci_fixup_irqs(u8 (*)(struct pci_dev *, u8 *), int (*)(struct pci_dev *, u8, u8)); #define HAVE_PCI_REQ_REGIONS --- 2.4.6/drivers/pci/setup-bus.c Sun May 20 04:43:06 2001 +++ linux/drivers/pci/setup-bus.c Thu Jun 14 14:12:12 2001 @@ -12,6 +12,12 @@ /* * Nov 2000, Ivan Kokshaysky <[EMAIL PROTECTED]> * PCI-PCI bridges cleanup, sorted resource allocation + * + * NOTE: during reallocation we may have temporarily overlapping + * IO or MEM ranges, so the arch code (pcibios_fixup_bus()) is + * responsible for disabling all devices, probably except console + * (VGA, serial etc.) and bridges the console device might be + * behind -- typically AGP or PCI-(E)ISA bridges. */ #include @@ -23,7 +29,7 @@ #include -#define DEBUG_CONFIG 1 +#define DEBUG_CONFIG 0 #if DEBUG_CONFIG # define DBGC(args) printk args #else @@ -46,23 +52,10 @@ pbus_assign_resources_sorted(struct pci_ for (ln=bus->devices.next; ln != &bus->devices; ln=ln->next) { struct pci_dev *dev = pci_dev_b(ln); u16 class = dev->class >> 8; - u16 cmd; - /* First, disable the device to avoid side - effects of possibly overlapping I/O and - memory ranges. - Leave VGA enabled - for obvious reason. :-) - Same with all sorts of bridges - they may - have VGA behind them. */ if (class == PCI_CLASS_DISPLAY_VGA || class == PCI_CLASS_NOT_DEFINED_VGA) found_vga = 1; - else if (class >> 8 != PCI_BASE_CLASS_BRIDGE) { - pci_read_config_word(dev, PCI_COMMAND, &cmd); - cmd &= ~(PCI_COMMAND_IO | PCI_COMMAND_MEMORY - | PCI_COMMAND_MASTER); - pci_write_config_word(dev, PCI_COMMAND, cmd); - } /* Reserve some resources for CardBus. Are these values reasonable? */ @@ -160,15 +153,31 @@ pci_setup_bridge(struct pci_bus *bus) l |= ranges.mem_end & 0xfff0; pci_write_config_dword(bridge, PCI_MEMORY_BASE, l); - /* Set up PREF base/limit. */ - l = (bus->resource[2]->start >> 16) & 0xfff0; - l |= bus->resource[2]->end & 0xfff0; - pci_write_conf