Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F145191426
D6136.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
21 KB
Referenced Files
None
Subscribers
None
D6136.diff
View Options
Index: head/sys/amd64/conf/GENERIC
===================================================================
--- head/sys/amd64/conf/GENERIC
+++ head/sys/amd64/conf/GENERIC
@@ -102,6 +102,7 @@
device acpi
options ACPI_DMAR
device pci
+options PCI_HP # PCI-Express native HotPlug
options PCI_IOV # PCI SR-IOV support
# Floppy drives
Index: head/sys/arm64/conf/GENERIC
===================================================================
--- head/sys/arm64/conf/GENERIC
+++ head/sys/arm64/conf/GENERIC
@@ -96,6 +96,7 @@
# Bus drivers
device pci
+options PCI_HP # PCI-Express native HotPlug
options PCI_IOV # PCI SR-IOV support
# Ethernet NICs
Index: head/sys/conf/NOTES
===================================================================
--- head/sys/conf/NOTES
+++ head/sys/conf/NOTES
@@ -1411,6 +1411,7 @@
# PCI bus & PCI options:
#
device pci
+options PCI_HP # PCI-Express native HotPlug
options PCI_IOV # PCI SR-IOV support
Index: head/sys/conf/options
===================================================================
--- head/sys/conf/options
+++ head/sys/conf/options
@@ -177,6 +177,7 @@
NSWBUF_MIN opt_swap.h
MBUF_PACKET_ZONE_DISABLE opt_global.h
PANIC_REBOOT_WAIT_TIME opt_panic.h
+PCI_HP opt_pci.h
PCI_IOV opt_global.h
PPC_DEBUG opt_ppc.h
PPC_PROBE_CHIPSET opt_ppc.h
Index: head/sys/dev/acpica/acpi_pcib_acpi.c
===================================================================
--- head/sys/dev/acpica/acpi_pcib_acpi.c
+++ head/sys/dev/acpica/acpi_pcib_acpi.c
@@ -29,6 +29,8 @@
__FBSDID("$FreeBSD$");
#include "opt_acpi.h"
+#include "opt_pci.h"
+
#include <sys/param.h>
#include <sys/bus.h>
#include <sys/kernel.h>
@@ -312,6 +314,11 @@
/* Control Field */
cap_set[2] = 0;
+#ifdef PCI_HP
+ /* Control Field: PCI Express Native Hot Plug */
+ cap_set[2] |= 0x1;
+#endif
+
status = acpi_EvaluateOSC(sc->ap_handle, pci_host_bridge_uuid, 1,
nitems(cap_set), cap_set, cap_set, false);
if (ACPI_FAILURE(status)) {
Index: head/sys/dev/pci/pci_pci.c
===================================================================
--- head/sys/dev/pci/pci_pci.c
+++ head/sys/dev/pci/pci_pci.c
@@ -35,6 +35,8 @@
* PCI:PCI bridge support.
*/
+#include "opt_pci.h"
+
#include <sys/param.h>
#include <sys/bus.h>
#include <sys/kernel.h>
@@ -43,6 +45,7 @@
#include <sys/rman.h>
#include <sys/sysctl.h>
#include <sys/systm.h>
+#include <sys/taskqueue.h>
#include <dev/pci/pcivar.h>
#include <dev/pci/pcireg.h>
@@ -67,6 +70,11 @@
static int pcib_ari_enabled(device_t pcib);
static void pcib_ari_decode_rid(device_t pcib, uint16_t rid,
int *bus, int *slot, int *func);
+#ifdef PCI_HP
+static void pcib_pcie_ab_timeout(void *arg);
+static void pcib_pcie_cc_timeout(void *arg);
+static void pcib_pcie_dll_timeout(void *arg);
+#endif
static device_method_t pcib_methods[] = {
/* Device interface */
@@ -78,6 +86,7 @@
DEVMETHOD(device_resume, pcib_resume),
/* Bus interface */
+ DEVMETHOD(bus_child_present, pcib_child_present),
DEVMETHOD(bus_read_ivar, pcib_read_ivar),
DEVMETHOD(bus_write_ivar, pcib_write_ivar),
DEVMETHOD(bus_alloc_resource, pcib_alloc_resource),
@@ -839,6 +848,466 @@
}
#endif
+#ifdef PCI_HP
+/*
+ * PCI-express HotPlug support.
+ */
+static void
+pcib_probe_hotplug(struct pcib_softc *sc)
+{
+ device_t dev;
+
+ dev = sc->dev;
+ if (pci_find_cap(dev, PCIY_EXPRESS, NULL) != 0)
+ return;
+
+ if (!(pcie_read_config(dev, PCIER_FLAGS, 2) & PCIEM_FLAGS_SLOT))
+ return;
+
+ sc->pcie_link_cap = pcie_read_config(dev, PCIER_LINK_CAP, 4);
+ sc->pcie_slot_cap = pcie_read_config(dev, PCIER_SLOT_CAP, 4);
+
+ if (sc->pcie_slot_cap & PCIEM_SLOT_CAP_HPC)
+ sc->flags |= PCIB_HOTPLUG;
+}
+
+/*
+ * Send a HotPlug command to the slot control register. If this slot
+ * uses command completion interrupts, these updates will be buffered
+ * while a previous command is completing.
+ */
+static void
+pcib_pcie_hotplug_command(struct pcib_softc *sc, uint16_t val, uint16_t mask)
+{
+ device_t dev;
+ uint16_t ctl, new;
+
+ dev = sc->dev;
+ if (sc->pcie_slot_cap & PCIEM_SLOT_CAP_NCCS) {
+ ctl = pcie_read_config(dev, PCIER_SLOT_CTL, 2);
+ new = (ctl & ~mask) | val;
+ if (new != ctl)
+ pcie_write_config(dev, PCIER_SLOT_CTL, new, 2);
+ return;
+ }
+
+ if (sc->flags & PCIB_HOTPLUG_CMD_PENDING) {
+ sc->pcie_pending_link_ctl_val &= ~mask;
+ sc->pcie_pending_link_ctl_val |= val;
+ sc->pcie_pending_link_ctl_mask |= mask;
+ } else {
+ ctl = pcie_read_config(dev, PCIER_SLOT_CTL, 2);
+ new = (ctl & ~mask) | val;
+ if (new != ctl) {
+ pcie_write_config(dev, PCIER_SLOT_CTL, ctl, 2);
+ sc->flags |= PCIB_HOTPLUG_CMD_PENDING;
+ if (!cold)
+ callout_reset(&sc->pcie_cc_timer, hz,
+ pcib_pcie_cc_timeout, sc);
+ }
+ }
+}
+
+static void
+pcib_pcie_hotplug_command_completed(struct pcib_softc *sc)
+{
+ device_t dev;
+ uint16_t ctl, new;
+
+ dev = sc->dev;
+
+ if (bootverbose)
+ device_printf(dev, "Command Completed\n");
+ if (!(sc->flags & PCIB_HOTPLUG_CMD_PENDING))
+ return;
+ if (sc->pcie_pending_link_ctl_mask != 0) {
+ ctl = pcie_read_config(dev, PCIER_SLOT_CTL, 2);
+ new = ctl & ~sc->pcie_pending_link_ctl_mask;
+ new |= sc->pcie_pending_link_ctl_val;
+ if (new != ctl) {
+ pcie_write_config(dev, PCIER_SLOT_CTL, ctl, 2);
+ if (!cold)
+ callout_reset(&sc->pcie_cc_timer, hz,
+ pcib_pcie_cc_timeout, sc);
+ } else
+ sc->flags &= ~PCIB_HOTPLUG_CMD_PENDING;
+ sc->pcie_pending_link_ctl_mask = 0;
+ sc->pcie_pending_link_ctl_val = 0;
+ } else {
+ callout_stop(&sc->pcie_cc_timer);
+ sc->flags &= ~PCIB_HOTPLUG_CMD_PENDING;
+ }
+}
+
+/*
+ * Returns true if a card is fully inserted from the user's
+ * perspective. It may not yet be ready for access, but the driver
+ * can now start enabling access if necessary.
+ */
+static bool
+pcib_hotplug_inserted(struct pcib_softc *sc)
+{
+
+ /* Pretend the card isn't present if a detach is forced. */
+ if (sc->flags & PCIB_DETACHING)
+ return (false);
+
+ /* Card must be present in the slot. */
+ if ((sc->pcie_slot_sta & PCIEM_SLOT_STA_PDS) == 0)
+ return (false);
+
+ /* A power fault implicitly turns off power to the slot. */
+ if (sc->pcie_slot_sta & PCIEM_SLOT_STA_PFD)
+ return (false);
+
+ /* If the MRL is disengaged, the slot is powered off. */
+ if (sc->pcie_slot_cap & PCIEM_SLOT_CAP_MRLSP &&
+ (sc->pcie_slot_sta & PCIEM_SLOT_STA_MRLSS) != 0)
+ return (false);
+
+ return (true);
+}
+
+/*
+ * Returns -1 if the card is fully inserted, powered, and ready for
+ * access. Otherwise, returns 0.
+ */
+static int
+pcib_hotplug_present(struct pcib_softc *sc)
+{
+ device_t dev;
+
+ dev = sc->dev;
+
+ /* Card must be inserted. */
+ if (!pcib_hotplug_inserted(sc))
+ return (0);
+
+ /*
+ * Require the Electromechanical Interlock to be engaged if
+ * present.
+ */
+ if (sc->pcie_slot_cap & PCIEM_SLOT_CAP_EIP &&
+ (sc->pcie_slot_sta & PCIEM_SLOT_STA_EIS) == 0)
+ return (0);
+
+ /* Require the Data Link Layer to be active. */
+ if (sc->pcie_link_cap & PCIEM_LINK_CAP_DL_ACTIVE) {
+ if (!(sc->pcie_link_sta & PCIEM_LINK_STA_DL_ACTIVE))
+ return (0);
+ }
+
+ return (-1);
+}
+
+static void
+pcib_pcie_hotplug_update(struct pcib_softc *sc, uint16_t val, uint16_t mask,
+ bool schedule_task)
+{
+ bool card_inserted;
+
+ /* Clear DETACHING if Present Detect has cleared. */
+ if ((sc->pcie_slot_sta & (PCIEM_SLOT_STA_PDC | PCIEM_SLOT_STA_PDS)) ==
+ PCIEM_SLOT_STA_PDC)
+ sc->flags &= ~PCIB_DETACHING;
+
+ card_inserted = pcib_hotplug_inserted(sc);
+
+ /* Turn the power indicator on if a card is inserted. */
+ if (sc->pcie_slot_cap & PCIEM_SLOT_CAP_PIP) {
+ mask |= PCIEM_SLOT_CTL_PIC;
+ if (card_inserted)
+ val |= PCIEM_SLOT_CTL_PI_ON;
+ else if (sc->flags & PCIB_DETACH_PENDING)
+ val |= PCIEM_SLOT_CTL_PI_BLINK;
+ else
+ val |= PCIEM_SLOT_CTL_PI_OFF;
+ }
+
+ /* Turn the power on via the Power Controller if a card is inserted. */
+ if (sc->pcie_slot_cap & PCIEM_SLOT_CAP_PCP) {
+ mask |= PCIEM_SLOT_CTL_PCC;
+ if (card_inserted)
+ val |= PCIEM_SLOT_CTL_PC_ON;
+ else
+ val |= PCIEM_SLOT_CTL_PC_OFF;
+ }
+
+ /*
+ * If a card is inserted, enable the Electromechanical
+ * Interlock. If a card is not inserted (or we are in the
+ * process of detaching), disable the Electromechanical
+ * Interlock.
+ */
+ if (sc->pcie_slot_cap & PCIEM_SLOT_CAP_EIP) {
+ if (card_inserted !=
+ !(sc->pcie_slot_sta & PCIEM_SLOT_STA_EIS)) {
+ mask |= PCIEM_SLOT_CTL_EIC;
+ val |= PCIEM_SLOT_CTL_EIC;
+ }
+ }
+
+ /*
+ * Start a timer to see if the Data Link Layer times out.
+ * Note that we only start the timer if Presence Detect
+ * changed on this interrupt. Stop any scheduled timer if
+ * the Data Link Layer is active.
+ */
+ if (sc->pcie_link_cap & PCIEM_LINK_CAP_DL_ACTIVE) {
+ if (card_inserted &&
+ !(sc->pcie_link_sta & PCIEM_LINK_STA_DL_ACTIVE) &&
+ sc->pcie_slot_sta & PCIEM_SLOT_STA_PDC) {
+ if (cold)
+ device_printf(sc->dev,
+ "Data Link Layer inactive\n");
+ else
+ callout_reset(&sc->pcie_dll_timer, hz,
+ pcib_pcie_dll_timeout, sc);
+ } else if (sc->pcie_link_sta & PCIEM_LINK_STA_DL_ACTIVE)
+ callout_stop(&sc->pcie_dll_timer);
+ }
+
+ pcib_pcie_hotplug_command(sc, val, mask);
+
+ /*
+ * During attach the child "pci" device is added sychronously;
+ * otherwise, the task is scheduled to manage the child
+ * device.
+ */
+ if (schedule_task &&
+ (pcib_hotplug_present(sc) != 0) != (sc->child != NULL))
+ taskqueue_enqueue(taskqueue_thread, &sc->pcie_hp_task);
+}
+
+static void
+pcib_pcie_intr(void *arg)
+{
+ struct pcib_softc *sc;
+ device_t dev;
+
+ sc = arg;
+ dev = sc->dev;
+ sc->pcie_slot_sta = pcie_read_config(dev, PCIER_SLOT_STA, 2);
+
+ /* Clear the events just reported. */
+ pcie_write_config(dev, PCIER_SLOT_STA, sc->pcie_slot_sta, 2);
+
+ if (sc->pcie_slot_sta & PCIEM_SLOT_STA_ABP) {
+ if (sc->flags & PCIB_DETACH_PENDING) {
+ device_printf(dev,
+ "Attention Button Pressed: Detach Cancelled\n");
+ sc->flags &= ~PCIB_DETACH_PENDING;
+ callout_stop(&sc->pcie_ab_timer);
+ } else {
+ device_printf(dev,
+ "Attention Button Pressed: Detaching in 5 seconds\n");
+ sc->flags |= PCIB_DETACH_PENDING;
+ callout_reset(&sc->pcie_ab_timer, 5 * hz,
+ pcib_pcie_ab_timeout, sc);
+ }
+ }
+ if (sc->pcie_slot_sta & PCIEM_SLOT_STA_PFD)
+ device_printf(dev, "Power Fault Detected\n");
+ if (sc->pcie_slot_sta & PCIEM_SLOT_STA_MRLSC)
+ device_printf(dev, "MRL Sensor Changed to %s\n",
+ sc->pcie_slot_sta & PCIEM_SLOT_STA_MRLSS ? "open" :
+ "closed");
+ if (bootverbose && sc->pcie_slot_sta & PCIEM_SLOT_STA_PDC)
+ device_printf(dev, "Present Detect Changed to %s\n",
+ sc->pcie_slot_sta & PCIEM_SLOT_STA_PDS ? "card present" :
+ "empty");
+ if (sc->pcie_slot_sta & PCIEM_SLOT_STA_CC)
+ pcib_pcie_hotplug_command_completed(sc);
+ if (sc->pcie_slot_sta & PCIEM_SLOT_STA_DLLSC) {
+ sc->pcie_link_sta = pcie_read_config(dev, PCIER_LINK_STA, 2);
+ if (bootverbose)
+ device_printf(dev,
+ "Data Link Layer State Changed to %s\n",
+ sc->pcie_link_sta & PCIEM_LINK_STA_DL_ACTIVE ?
+ "active" : "inactive");
+ }
+
+ pcib_pcie_hotplug_update(sc, 0, 0, true);
+}
+
+static void
+pcib_pcie_hotplug_task(void *context, int pending)
+{
+ struct pcib_softc *sc;
+ device_t dev;
+
+ sc = context;
+ mtx_lock(&Giant);
+ dev = sc->dev;
+ if (pcib_hotplug_present(sc) != 0) {
+ if (sc->child == NULL) {
+ sc->child = device_add_child(dev, "pci", -1);
+ bus_generic_attach(dev);
+ }
+ } else {
+ if (sc->child != NULL) {
+ if (device_delete_child(dev, sc->child) == 0)
+ sc->child = NULL;
+ }
+ }
+ mtx_unlock(&Giant);
+}
+
+static void
+pcib_pcie_ab_timeout(void *arg)
+{
+ struct pcib_softc *sc;
+ device_t dev;
+
+ sc = arg;
+ dev = sc->dev;
+ mtx_assert(&Giant, MA_OWNED);
+ if (sc->flags & PCIB_DETACH_PENDING) {
+ sc->flags |= PCIB_DETACHING;
+ sc->flags &= ~PCIB_DETACH_PENDING;
+ pcib_pcie_hotplug_update(sc, 0, 0, true);
+ }
+}
+
+static void
+pcib_pcie_cc_timeout(void *arg)
+{
+ struct pcib_softc *sc;
+ device_t dev;
+
+ sc = arg;
+ dev = sc->dev;
+ mtx_assert(&Giant, MA_OWNED);
+ if (sc->flags & PCIB_HOTPLUG_CMD_PENDING) {
+ device_printf(dev,
+ "Hotplug Command Timed Out - forcing detach\n");
+ sc->flags &= ~(PCIB_HOTPLUG_CMD_PENDING | PCIB_DETACH_PENDING);
+ sc->flags |= PCIB_DETACHING;
+ pcib_pcie_hotplug_update(sc, 0, 0, true);
+ }
+}
+
+static void
+pcib_pcie_dll_timeout(void *arg)
+{
+ struct pcib_softc *sc;
+ device_t dev;
+ uint16_t sta;
+
+ sc = arg;
+ dev = sc->dev;
+ mtx_assert(&Giant, MA_OWNED);
+ sta = pcie_read_config(dev, PCIER_LINK_STA, 2);
+ if (!(sta & PCIEM_LINK_STA_DL_ACTIVE)) {
+ device_printf(dev,
+ "Timed out waiting for Data Link Layer Active\n");
+ sc->flags |= PCIB_DETACHING;
+ pcib_pcie_hotplug_update(sc, 0, 0, true);
+ } else if (sta != sc->pcie_link_sta) {
+ device_printf(dev,
+ "Missed HotPlug interrupt waiting for DLL Active\n");
+ pcib_pcie_intr(sc);
+ }
+}
+
+static int
+pcib_alloc_pcie_irq(struct pcib_softc *sc)
+{
+ device_t dev;
+ int count, error, rid;
+
+ rid = -1;
+ dev = sc->dev;
+
+ /*
+ * For simplicity, only use MSI-X if there is a single message.
+ * To support a device with multiple messages we would have to
+ * use remap intr if the MSI number is not 0.
+ */
+ count = pci_msix_count(dev);
+ if (count == 1) {
+ error = pci_alloc_msix(dev, &count);
+ if (error == 0)
+ rid = 1;
+ }
+
+ if (rid < 0 && pci_msi_count(dev) > 0) {
+ count = 1;
+ error = pci_alloc_msi(dev, &count);
+ if (error == 0)
+ rid = 1;
+ }
+
+ if (rid < 0)
+ rid = 0;
+
+ sc->pcie_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
+ RF_ACTIVE);
+ if (sc->pcie_irq == NULL) {
+ device_printf(dev,
+ "Failed to allocate interrupt for PCI-e events\n");
+ if (rid > 0)
+ pci_release_msi(dev);
+ return (ENXIO);
+ }
+
+ error = bus_setup_intr(dev, sc->pcie_irq, INTR_TYPE_MISC,
+ NULL, pcib_pcie_intr, sc, &sc->pcie_ihand);
+ if (error) {
+ device_printf(dev, "Failed to setup PCI-e interrupt handler\n");
+ bus_release_resource(dev, SYS_RES_IRQ, rid, sc->pcie_irq);
+ if (rid > 0)
+ pci_release_msi(dev);
+ return (error);
+ }
+ return (0);
+}
+
+static void
+pcib_setup_hotplug(struct pcib_softc *sc)
+{
+ device_t dev;
+ uint16_t mask, val;
+
+ dev = sc->dev;
+ callout_init(&sc->pcie_ab_timer, 0);
+ callout_init(&sc->pcie_cc_timer, 0);
+ callout_init(&sc->pcie_dll_timer, 0);
+ TASK_INIT(&sc->pcie_hp_task, 0, pcib_pcie_hotplug_task, sc);
+
+ /* Allocate IRQ. */
+ if (pcib_alloc_pcie_irq(sc) != 0)
+ return;
+
+ sc->pcie_link_sta = pcie_read_config(dev, PCIER_LINK_STA, 2);
+ sc->pcie_slot_sta = pcie_read_config(dev, PCIER_SLOT_STA, 2);
+
+ /* Enable HotPlug events. */
+ mask = PCIEM_SLOT_CTL_DLLSCE | PCIEM_SLOT_CTL_HPIE |
+ PCIEM_SLOT_CTL_CCIE | PCIEM_SLOT_CTL_PDCE | PCIEM_SLOT_CTL_MRLSCE |
+ PCIEM_SLOT_CTL_PFDE | PCIEM_SLOT_CTL_ABPE;
+ val = PCIEM_SLOT_CTL_PDCE | PCIEM_SLOT_CTL_HPIE;
+ if (sc->pcie_slot_cap & PCIEM_SLOT_CAP_APB)
+ val |= PCIEM_SLOT_CTL_ABPE;
+ if (sc->pcie_slot_cap & PCIEM_SLOT_CAP_PCP)
+ val |= PCIEM_SLOT_CTL_PFDE;
+ if (sc->pcie_slot_cap & PCIEM_SLOT_CAP_MRLSP)
+ val |= PCIEM_SLOT_CTL_MRLSCE;
+ if (!(sc->pcie_slot_cap & PCIEM_SLOT_CAP_NCCS))
+ val |= PCIEM_SLOT_CTL_CCIE;
+ if (sc->pcie_link_cap & PCIEM_LINK_CAP_DL_ACTIVE)
+ val |= PCIEM_SLOT_CTL_DLLSCE;
+
+ /* Turn the attention indicator off. */
+ if (sc->pcie_slot_cap & PCIEM_SLOT_CAP_AIP) {
+ mask |= PCIEM_SLOT_CTL_AIC;
+ val |= PCIEM_SLOT_CTL_AI_OFF;
+ }
+
+ pcib_pcie_hotplug_update(sc, val, mask, false);
+}
+#endif
+
/*
* Get current bridge configuration.
*/
@@ -1017,12 +1486,19 @@
pci_read_config(dev, PCIR_PROGIF, 1) == PCIP_BRIDGE_PCI_SUBTRACTIVE)
sc->flags |= PCIB_SUBTRACTIVE;
+#ifdef PCI_HP
+ pcib_probe_hotplug(sc);
+#endif
#ifdef NEW_PCIB
#ifdef PCI_RES_BUS
pcib_setup_secbus(dev, &sc->bus, 1);
#endif
pcib_probe_windows(sc);
#endif
+#ifdef PCI_HP
+ if (sc->flags & PCIB_HOTPLUG)
+ pcib_setup_hotplug(sc);
+#endif
if (bootverbose) {
device_printf(dev, " domain %d\n", sc->domain);
device_printf(dev, " secondary bus %d\n", sc->bus.sec);
@@ -1074,6 +1550,17 @@
pci_enable_busmaster(dev);
}
+#ifdef PCI_HP
+static int
+pcib_present(struct pcib_softc *sc)
+{
+
+ if (sc->flags & PCIB_HOTPLUG)
+ return (pcib_hotplug_present(sc) != 0);
+ return (1);
+}
+#endif
+
int
pcib_attach_child(device_t dev)
{
@@ -1085,6 +1572,13 @@
return(0);
}
+#ifdef PCI_HP
+ if (!pcib_present(sc)) {
+ /* An empty HotPlug slot, so don't add a PCI bus yet. */
+ return (0);
+ }
+#endif
+
sc->child = device_add_child(dev, "pci", -1);
return (bus_generic_attach(dev));
}
@@ -1129,6 +1623,22 @@
}
int
+pcib_child_present(device_t dev, device_t child)
+{
+#ifdef PCI_HP
+ struct pcib_softc *sc = device_get_softc(dev);
+ int retval;
+
+ retval = bus_child_present(dev);
+ if (retval != 0 && sc->flags & PCIB_HOTPLUG)
+ retval = pcib_hotplug_present(sc);
+ return (retval);
+#else
+ return (bus_child_present(dev));
+#endif
+}
+
+int
pcib_read_ivar(device_t dev, device_t child, int which, uintptr_t *result)
{
struct pcib_softc *sc = device_get_softc(dev);
@@ -1909,7 +2419,21 @@
static uint32_t
pcib_read_config(device_t dev, u_int b, u_int s, u_int f, u_int reg, int width)
{
+#ifdef PCI_HP
+ struct pcib_softc *sc;
+ sc = device_get_softc(dev);
+ if (!pcib_present(sc)) {
+ switch (width) {
+ case 2:
+ return (0xffff);
+ case 1:
+ return (0xff);
+ default:
+ return (0xffffffff);
+ }
+ }
+#endif
pcib_xlate_ari(dev, b, &s, &f);
return(PCIB_READ_CONFIG(device_get_parent(device_get_parent(dev)), b, s,
f, reg, width));
@@ -1918,7 +2442,13 @@
static void
pcib_write_config(device_t dev, u_int b, u_int s, u_int f, u_int reg, uint32_t val, int width)
{
+#ifdef PCI_HP
+ struct pcib_softc *sc;
+ sc = device_get_softc(dev);
+ if (!pcib_present(sc))
+ return;
+#endif
pcib_xlate_ari(dev, b, &s, &f);
PCIB_WRITE_CONFIG(device_get_parent(device_get_parent(dev)), b, s, f,
reg, val, width);
Index: head/sys/dev/pci/pcib_private.h
===================================================================
--- head/sys/dev/pci/pcib_private.h
+++ head/sys/dev/pci/pcib_private.h
@@ -33,6 +33,9 @@
#ifndef __PCIB_PRIVATE_H__
#define __PCIB_PRIVATE_H__
+#include <sys/_callout.h>
+#include <sys/_task.h>
+
#ifdef NEW_PCIB
/*
* Data structure and routines that Host to PCI bridge drivers can use
@@ -107,6 +110,10 @@
#define PCIB_DISABLE_MSI 0x2
#define PCIB_DISABLE_MSIX 0x4
#define PCIB_ENABLE_ARI 0x8
+#define PCIB_HOTPLUG 0x10
+#define PCIB_HOTPLUG_CMD_PENDING 0x20
+#define PCIB_DETACH_PENDING 0x40
+#define PCIB_DETACHING 0x80
u_int domain; /* domain number */
u_int pribus; /* primary bus number */
struct pcib_secbus bus; /* secondary bus numbers */
@@ -123,6 +130,18 @@
uint32_t iolimit; /* topmost address of port window */
#endif
uint16_t bridgectl; /* bridge control register */
+ uint16_t pcie_link_sta;
+ uint16_t pcie_slot_sta;
+ uint32_t pcie_link_cap;
+ uint32_t pcie_slot_cap;
+ uint16_t pcie_pending_link_ctl_mask;
+ uint16_t pcie_pending_link_ctl_val;
+ struct resource *pcie_irq;
+ void *pcie_ihand;
+ struct task pcie_hp_task;
+ struct callout pcie_ab_timer;
+ struct callout pcie_cc_timer;
+ struct callout pcie_dll_timer;
};
#define PCIB_SUPPORTED_ARI_VER 1
@@ -151,6 +170,7 @@
#ifdef NEW_PCIB
const char *pcib_child_name(device_t child);
#endif
+int pcib_child_present(device_t dev, device_t child);
int pcib_read_ivar(device_t dev, device_t child, int which, uintptr_t *result);
int pcib_write_ivar(device_t dev, device_t child, int which, uintptr_t value);
struct resource *pcib_alloc_resource(device_t dev, device_t child, int type, int *rid,
Index: head/sys/dev/pci/pcireg.h
===================================================================
--- head/sys/dev/pci/pcireg.h
+++ head/sys/dev/pci/pcireg.h
@@ -850,8 +850,16 @@
#define PCIEM_SLOT_CTL_CCIE 0x0010
#define PCIEM_SLOT_CTL_HPIE 0x0020
#define PCIEM_SLOT_CTL_AIC 0x00c0
+#define PCIEM_SLOT_CTL_AI_ON 0x0040
+#define PCIEM_SLOT_CTL_AI_BLINK 0x0080
+#define PCIEM_SLOT_CTL_AI_OFF 0x00c0
#define PCIEM_SLOT_CTL_PIC 0x0300
+#define PCIEM_SLOT_CTL_PI_ON 0x0100
+#define PCIEM_SLOT_CTL_PI_BLINK 0x0200
+#define PCIEM_SLOT_CTL_PI_OFF 0x0300
#define PCIEM_SLOT_CTL_PCC 0x0400
+#define PCIEM_SLOT_CTL_PC_ON 0x0000
+#define PCIEM_SLOT_CTL_PC_OFF 0x0400
#define PCIEM_SLOT_CTL_EIC 0x0800
#define PCIEM_SLOT_CTL_DLLSCE 0x1000
#define PCIER_SLOT_STA 0x1a
Index: head/sys/i386/conf/GENERIC
===================================================================
--- head/sys/i386/conf/GENERIC
+++ head/sys/i386/conf/GENERIC
@@ -101,6 +101,7 @@
# Bus support.
device acpi
device pci
+options PCI_HP # PCI-Express native HotPlug
options PCI_IOV # PCI SR-IOV support
# Floppy drives
Index: head/sys/powerpc/conf/GENERIC
===================================================================
--- head/sys/powerpc/conf/GENERIC
+++ head/sys/powerpc/conf/GENERIC
@@ -102,6 +102,7 @@
# Standard busses
device pci
+options PCI_HP # PCI-Express native HotPlug
device agp
# ATA controllers
Index: head/sys/powerpc/conf/GENERIC64
===================================================================
--- head/sys/powerpc/conf/GENERIC64
+++ head/sys/powerpc/conf/GENERIC64
@@ -99,6 +99,7 @@
# Standard busses
device pci
+options PCI_HP # PCI-Express native HotPlug
device agp
# ATA controllers
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Tue, Feb 17, 10:55 PM (12 h, 44 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
28828046
Default Alt Text
D6136.diff (21 KB)
Attached To
Mode
D6136: Native PCI-express HotPlug support.
Attached
Detach File
Event Timeline
Log In to Comment