Changeset View
Changeset View
Standalone View
Standalone View
sys/dev/pci/pci_pci.c
Context not available. | |||||
static void pcib_ari_decode_rid(device_t pcib, uint16_t rid, | static void pcib_ari_decode_rid(device_t pcib, uint16_t rid, | ||||
int *bus, int *slot, int *func); | int *bus, int *slot, int *func); | ||||
#ifdef PCI_HP | #ifdef PCI_HP | ||||
static void pcib_pcie_new_pass(device_t dev); | |||||
static void pcib_pcie_ab_timeout(void *arg); | static void pcib_pcie_ab_timeout(void *arg); | ||||
static void pcib_pcie_cc_timeout(void *arg); | static void pcib_pcie_cc_timeout(void *arg); | ||||
static void pcib_pcie_dll_timeout(void *arg); | static void pcib_pcie_dll_timeout(void *arg); | ||||
Context not available. | |||||
DEVMETHOD(device_resume, pcib_resume), | DEVMETHOD(device_resume, pcib_resume), | ||||
/* Bus interface */ | /* Bus interface */ | ||||
#ifdef PCI_HP | |||||
DEVMETHOD(bus_new_pass, pcib_pcie_new_pass), | |||||
#endif | |||||
DEVMETHOD(bus_child_present, pcib_child_present), | DEVMETHOD(bus_child_present, pcib_child_present), | ||||
DEVMETHOD(bus_read_ivar, pcib_read_ivar), | DEVMETHOD(bus_read_ivar, pcib_read_ivar), | ||||
DEVMETHOD(bus_write_ivar, pcib_write_ivar), | DEVMETHOD(bus_write_ivar, pcib_write_ivar), | ||||
Context not available. | |||||
static devclass_t pcib_devclass; | static devclass_t pcib_devclass; | ||||
DEFINE_CLASS_0(pcib, pcib_driver, pcib_methods, sizeof(struct pcib_softc)); | DEFINE_CLASS_0(pcib, pcib_driver, pcib_methods, sizeof(struct pcib_softc)); | ||||
DRIVER_MODULE(pcib, pci, pcib_driver, pcib_devclass, NULL, NULL); | EARLY_DRIVER_MODULE(pcib, pci, pcib_driver, pcib_devclass, NULL, NULL, | ||||
BUS_PASS_BUS); | |||||
#if defined(NEW_PCIB) || defined(PCI_HP) | #if defined(NEW_PCIB) || defined(PCI_HP) | ||||
SYSCTL_DECL(_hw_pci); | SYSCTL_DECL(_hw_pci); | ||||
Context not available. | |||||
SYSCTL_INT(_hw_pci, OID_AUTO, enable_pcie_hp, CTLFLAG_RDTUN, | SYSCTL_INT(_hw_pci, OID_AUTO, enable_pcie_hp, CTLFLAG_RDTUN, | ||||
&pci_enable_pcie_hp, 0, | &pci_enable_pcie_hp, 0, | ||||
"Enable support for native PCI-express HotPlug."); | "Enable support for native PCI-express HotPlug."); | ||||
static int pcib_detach_hotplug(struct pcib_softc *sc); | |||||
static void | static void | ||||
pcib_probe_hotplug(struct pcib_softc *sc) | pcib_probe_hotplug(struct pcib_softc *sc) | ||||
Context not available. | |||||
pcib_alloc_pcie_irq(struct pcib_softc *sc) | pcib_alloc_pcie_irq(struct pcib_softc *sc) | ||||
{ | { | ||||
device_t dev; | device_t dev; | ||||
int count, error, rid; | int count, error; | ||||
rid = -1; | sc->pcie_irq_id = -1; | ||||
dev = sc->dev; | dev = sc->dev; | ||||
/* | /* | ||||
Context not available. | |||||
if (count == 1) { | if (count == 1) { | ||||
error = pci_alloc_msix(dev, &count); | error = pci_alloc_msix(dev, &count); | ||||
if (error == 0) | if (error == 0) | ||||
rid = 1; | sc->pcie_irq_id = 1; | ||||
} | } | ||||
if (rid < 0 && pci_msi_count(dev) > 0) { | if (sc->pcie_irq_id < 0 && pci_msi_count(dev) > 0) { | ||||
count = 1; | count = 1; | ||||
error = pci_alloc_msi(dev, &count); | error = pci_alloc_msi(dev, &count); | ||||
if (error == 0) | if (error == 0) | ||||
rid = 1; | sc->pcie_irq_id = 1; | ||||
} | } | ||||
if (rid < 0) | if (sc->pcie_irq_id < 0) | ||||
rid = 0; | sc->pcie_irq_id = 0; | ||||
sc->pcie_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, | sc->pcie_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, | ||||
RF_ACTIVE); | &sc->pcie_irq_id, 0 /* Inactive until after BUS_PASS_INTERRUPT */); | ||||
if (sc->pcie_irq == NULL) { | if (sc->pcie_irq == NULL) { | ||||
device_printf(dev, | device_printf(dev, | ||||
"Failed to allocate interrupt for PCI-e events\n"); | "Failed to allocate interrupt for PCI-e events\n"); | ||||
if (rid > 0) | if (sc->pcie_irq_id > 0) | ||||
pci_release_msi(dev); | pci_release_msi(dev); | ||||
return (ENXIO); | return (ENXIO); | ||||
} | } | ||||
/* Check if this attached late */ | |||||
if (bus_current_pass > BUS_PASS_INTERRUPT + BUS_PASS_ORDER_LAST) | |||||
pcib_pcie_new_pass(dev); | |||||
return (0); | |||||
} | |||||
/* | |||||
* Late attach for interrupt setup for hotplug bridges, since the interrupt | |||||
* controller may be a child of the bridge. | |||||
*/ | |||||
static void | |||||
pcib_pcie_new_pass(device_t dev) | |||||
jhb: I would perhaps call this 'pcib_pcie_alloc_irq()' and have pcib_pcie_new_pass() be something… | |||||
{ | |||||
struct pcib_softc *sc; | |||||
int error; | |||||
if (bus_current_pass <= BUS_PASS_INTERRUPT + BUS_PASS_ORDER_LAST) | |||||
goto out; | |||||
sc = device_get_softc(dev); | |||||
if (sc->pcie_irq == NULL || (rman_get_flags(sc->pcie_irq) & RF_ACTIVE)) | |||||
goto out; | |||||
bus_activate_resource(dev, SYS_RES_IRQ, sc->pcie_irq_id, sc->pcie_irq); | |||||
error = bus_setup_intr(dev, sc->pcie_irq, INTR_TYPE_MISC, | error = bus_setup_intr(dev, sc->pcie_irq, INTR_TYPE_MISC, | ||||
NULL, pcib_pcie_intr, sc, &sc->pcie_ihand); | NULL, pcib_pcie_intr, sc, &sc->pcie_ihand); | ||||
if (error) { | if (error) { | ||||
device_printf(dev, "Failed to setup PCI-e interrupt handler\n"); | device_printf(dev, "Failed to setup PCI-e interrupt handler\n"); | ||||
bus_release_resource(dev, SYS_RES_IRQ, rid, sc->pcie_irq); | bus_release_resource(dev, SYS_RES_IRQ, sc->pcie_irq_id, | ||||
if (rid > 0) | sc->pcie_irq); | ||||
pci_release_msi(dev); | pcib_detach_hotplug(sc); | ||||
return (error); | sc->flags &= ~PCIB_DETACHING; | ||||
sc->pcie_irq = NULL; | |||||
} | } | ||||
return (0); | |||||
out: | |||||
bus_generic_new_pass(dev); | |||||
} | } | ||||
static int | static int | ||||
Context not available. | |||||
int error; | int error; | ||||
dev = sc->dev; | dev = sc->dev; | ||||
error = bus_teardown_intr(dev, sc->pcie_irq, sc->pcie_ihand); | if (rman_get_flags(sc->pcie_irq) & RF_ACTIVE) { | ||||
jhbUnsubmitted Not Done Inline ActionsAh, I would actually defer all of pcib_pcie_alloc_irq() (including all the MSI song and dance) in which case you won't need this change or the explicit bus_activate_resource(). (Missed that part of the change in the comment above). That would then let you still have a "simple" bus_new_pass method that just calls pcib_pcie_alloc_irq() if need be. jhb: Ah, I would actually defer all of pcib_pcie_alloc_irq() (including all the MSI song and dance)… | |||||
if (error) | error = bus_teardown_intr(dev, sc->pcie_irq, sc->pcie_ihand); | ||||
return (error); | if (error) | ||||
return (error); | |||||
} | |||||
error = bus_free_resource(dev, SYS_RES_IRQ, sc->pcie_irq); | error = bus_free_resource(dev, SYS_RES_IRQ, sc->pcie_irq); | ||||
if (error) | if (error) | ||||
return (error); | return (error); | ||||
Context not available. |
I would perhaps call this 'pcib_pcie_alloc_irq()' and have pcib_pcie_new_pass() be something like: