> Date: Mon, 15 Apr 2019 08:55:10 +0200
> From: Patrick Wildt <patr...@blueri.se>
> 
> Hi,
> 
> with kettenis' change from 2015(?) we can configure a ppb(4)'s bus
> information.  Unfortunately the hotplug fixup code runs before that
> change has a chance, and it will program a single bus (with no amount
> of children) below it.  I think that part of the hotplug fixup can go
> away.
> 
> The hotplug fixup also contains code for fixing up interrupt lines.  On
> my todays machine it uses MSIs, so a missing interrupt line does not
> hurt me.  I'm not sure if this is still needed for yesterday's machines.
> 
> Apparently that code was for some ExpressCards?

Tested this on my x220 now.  Doesn't break inserting my ExpressCard
serial card that has a PCIe-PCI bridge on it.  Seems to make things
slightly better for the freaky ExpressCard extension box that has two
PCIe slots and two PCI slots.  Hotplugging that one still doesn't
fully work, but I end up with less "not configured by firmware"
messages, so I consider that to be progress.

Commit this and keep an eye out for fallout.

ok kettenis@

> diff --git a/sys/dev/pci/ppb.c b/sys/dev/pci/ppb.c
> index a9ff32ce33c..22ff8ca2b5f 100644
> --- a/sys/dev/pci/ppb.c
> +++ b/sys/dev/pci/ppb.c
> @@ -117,9 +117,6 @@ void      ppb_alloc_resources(struct ppb_softc *, struct 
> pci_attach_args *);
>  int  ppb_intr(void *);
>  void ppb_hotplug_insert(void *);
>  void ppb_hotplug_insert_finish(void *);
> -int  ppb_hotplug_fixup(struct pci_attach_args *);
> -int  ppb_hotplug_fixup_type0(pci_chipset_tag_t, pcitag_t, pcitag_t);
> -int  ppb_hotplug_fixup_type1(pci_chipset_tag_t, pcitag_t, pcitag_t);
>  void ppb_hotplug_rescan(void *);
>  void ppb_hotplug_remove(void *);
>  int  ppbprint(void *, const char *pnp);
> @@ -776,108 +773,14 @@ ppb_hotplug_insert_finish(void *arg)
>       task_add(systq, &sc->sc_rescan_task);
>  }
>  
> -int
> -ppb_hotplug_fixup(struct pci_attach_args *pa)
> -{
> -     pcireg_t bhlcr;
> -
> -     bhlcr = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_BHLC_REG);
> -     switch (PCI_HDRTYPE_TYPE(bhlcr)) {
> -     case 0:
> -             return ppb_hotplug_fixup_type0(pa->pa_pc,
> -                 pa->pa_tag, *pa->pa_bridgetag);
> -     case 1:
> -             return ppb_hotplug_fixup_type1(pa->pa_pc,
> -                 pa->pa_tag, *pa->pa_bridgetag);
> -     default:
> -             return (0);
> -     }
> -}
> -
> -int
> -ppb_hotplug_fixup_type0(pci_chipset_tag_t pc, pcitag_t tag, pcitag_t 
> bridgetag)
> -{
> -     pcireg_t intr;
> -     int line;
> -
> -     /*
> -      * Fill in the interrupt line for platforms that need it.
> -      *
> -      * XXX We assume that the interrupt line matches the line used
> -      * by the PCI Express bridge.  This may not be true.
> -      */
> -     intr = pci_conf_read(pc, tag, PCI_INTERRUPT_REG);
> -     if (PCI_INTERRUPT_PIN(intr) != PCI_INTERRUPT_PIN_NONE &&
> -         PCI_INTERRUPT_LINE(intr) == 0) {
> -             /* Get the interrupt line from our parent. */
> -             intr = pci_conf_read(pc, bridgetag, PCI_INTERRUPT_REG);
> -             line = PCI_INTERRUPT_LINE(intr);
> -
> -             intr = pci_conf_read(pc, tag, PCI_INTERRUPT_REG);
> -             intr &= ~(PCI_INTERRUPT_LINE_MASK << PCI_INTERRUPT_LINE_SHIFT);
> -             intr |= line << PCI_INTERRUPT_LINE_SHIFT;
> -             pci_conf_write(pc, tag, PCI_INTERRUPT_REG, intr);
> -     }
> -
> -     return (0);
> -}
> -
> -int
> -ppb_hotplug_fixup_type1(pci_chipset_tag_t pc, pcitag_t tag, pcitag_t 
> bridgetag)
> -{
> -     pcireg_t bhlcr, bir, csr, val;
> -     int bus, dev, reg;
> -
> -     bir = pci_conf_read(pc, bridgetag, PPB_REG_BUSINFO);
> -     if (PPB_BUSINFO_SUBORDINATE(bir) <= PPB_BUSINFO_SECONDARY(bir))
> -             return (0);
> -
> -     bus = PPB_BUSINFO_SECONDARY(bir);
> -     bir = pci_conf_read(pc, tag, PPB_REG_BUSINFO);
> -     bir &= (0xff << 24);
> -     bir |= bus++;
> -     bir |= (bus << 8);
> -     bir |= (bus << 16);
> -     pci_conf_write(pc, tag, PPB_REG_BUSINFO, bir);
> -
> -     for (reg = PPB_REG_IOSTATUS; reg < PPB_REG_BRIDGECONTROL; reg += 4) {
> -             val = pci_conf_read(pc, bridgetag, reg);
> -             pci_conf_write(pc, tag, reg, val);
> -     }
> -
> -     csr = pci_conf_read(pc, tag, PCI_COMMAND_STATUS_REG);
> -     csr |= PCI_COMMAND_IO_ENABLE | PCI_COMMAND_MEM_ENABLE;
> -     csr |= PCI_COMMAND_MASTER_ENABLE;
> -     csr |= PCI_COMMAND_INVALIDATE_ENABLE;
> -     csr |= PCI_COMMAND_SERR_ENABLE;
> -     pci_conf_write(pc, tag, PCI_COMMAND_STATUS_REG, csr);
> -
> -     for (dev = 0; dev < pci_bus_maxdevs(pc, bus); dev++) {
> -             tag = pci_make_tag(pc, bus, dev, 0);
> -
> -             bhlcr = pci_conf_read(pc, tag, PCI_BHLC_REG);
> -             if (PCI_HDRTYPE_TYPE(bhlcr) != 0)
> -                     continue;
> -
> -             ppb_hotplug_fixup_type0(pc, tag, bridgetag);
> -     }
> -
> -     return (0);
> -}
> -
>  void
>  ppb_hotplug_rescan(void *xsc)
>  {
>       struct ppb_softc *sc = xsc;
>       struct pci_softc *psc = (struct pci_softc *)sc->sc_psc;
>  
> -     if (psc) {
> -             /* Assign resources. */
> -             pci_enumerate_bus(psc, ppb_hotplug_fixup, NULL);
> -
> -             /* Attach devices. */
> +     if (psc)
>               pci_enumerate_bus(psc, NULL, NULL);
> -     }
>  }
>  
>  void
> 
> 

Reply via email to