summaryrefslogtreecommitdiffstats
path: root/freebsd/sys/dev/pci
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2018-08-21 09:39:55 +0200
committerSebastian Huber <sebastian.huber@embedded-brains.de>2018-09-21 10:29:40 +0200
commit2df56dbd60bb5d925d2ce0ddbdefdbe6107ea783 (patch)
treebd7bad558534db4a1f400bc38a2c9aa7ea4f411e /freebsd/sys/dev/pci
parentUpdate to FreeBSD head 2018-02-01 (diff)
downloadrtems-libbsd-2df56dbd60bb5d925d2ce0ddbdefdbe6107ea783.tar.bz2
Update to FreeBSD head 2018-04-01
Git mirror commit 8dfb1ccc26d1cea7e2529303003ff61f9f1784c4. Update #3472.
Diffstat (limited to 'freebsd/sys/dev/pci')
-rw-r--r--freebsd/sys/dev/pci/pci.c119
-rw-r--r--freebsd/sys/dev/pci/pci_private.h6
-rw-r--r--freebsd/sys/dev/pci/pci_user.c7
-rw-r--r--freebsd/sys/dev/pci/pcivar.h21
4 files changed, 144 insertions, 9 deletions
diff --git a/freebsd/sys/dev/pci/pci.c b/freebsd/sys/dev/pci/pci.c
index 7fbdc693..55a21320 100644
--- a/freebsd/sys/dev/pci/pci.c
+++ b/freebsd/sys/dev/pci/pci.c
@@ -185,8 +185,11 @@ static device_method_t pci_methods[] = {
DEVMETHOD(pci_set_powerstate, pci_set_powerstate_method),
DEVMETHOD(pci_assign_interrupt, pci_assign_interrupt_method),
DEVMETHOD(pci_find_cap, pci_find_cap_method),
+ DEVMETHOD(pci_find_next_cap, pci_find_next_cap_method),
DEVMETHOD(pci_find_extcap, pci_find_extcap_method),
+ DEVMETHOD(pci_find_next_extcap, pci_find_next_extcap_method),
DEVMETHOD(pci_find_htcap, pci_find_htcap_method),
+ DEVMETHOD(pci_find_next_htcap, pci_find_next_htcap_method),
DEVMETHOD(pci_alloc_msi, pci_alloc_msi_method),
DEVMETHOD(pci_alloc_msix, pci_alloc_msix_method),
DEVMETHOD(pci_enable_msi, pci_enable_msi_method),
@@ -1381,7 +1384,7 @@ pci_find_htcap_method(device_t dev, device_t child, int capability, int *capreg)
* Traverse the capabilities list checking each HT capability
* to see if it matches the requested HT capability.
*/
- while (ptr != 0) {
+ for (;;) {
val = pci_read_config(child, ptr + PCIR_HT_COMMAND, 2);
if (capability == PCIM_HTCAP_SLAVE ||
capability == PCIM_HTCAP_HOST)
@@ -1395,13 +1398,51 @@ pci_find_htcap_method(device_t dev, device_t child, int capability, int *capreg)
}
/* Skip to the next HT capability. */
- while (ptr != 0) {
- ptr = pci_read_config(child, ptr + PCICAP_NEXTPTR, 1);
- if (pci_read_config(child, ptr + PCICAP_ID, 1) ==
- PCIY_HT)
- break;
+ if (pci_find_next_cap(child, PCIY_HT, ptr, &ptr) != 0)
+ break;
+ }
+
+ return (ENOENT);
+}
+
+/*
+ * Find the next requested HyperTransport capability after start and return
+ * the offset in configuration space via the pointer provided. The function
+ * returns 0 on success and an error code otherwise.
+ */
+int
+pci_find_next_htcap_method(device_t dev, device_t child, int capability,
+ int start, int *capreg)
+{
+ int ptr;
+ uint16_t val;
+
+ KASSERT(pci_read_config(child, start + PCICAP_ID, 1) == PCIY_HT,
+ ("start capability is not HyperTransport capability"));
+ ptr = start;
+
+ /*
+ * Traverse the capabilities list checking each HT capability
+ * to see if it matches the requested HT capability.
+ */
+ for (;;) {
+ /* Skip to the next HT capability. */
+ if (pci_find_next_cap(child, PCIY_HT, ptr, &ptr) != 0)
+ break;
+
+ val = pci_read_config(child, ptr + PCIR_HT_COMMAND, 2);
+ if (capability == PCIM_HTCAP_SLAVE ||
+ capability == PCIM_HTCAP_HOST)
+ val &= 0xe000;
+ else
+ val &= PCIM_HTCMD_CAP_MASK;
+ if (val == capability) {
+ if (capreg != NULL)
+ *capreg = ptr;
+ return (0);
}
}
+
return (ENOENT);
}
@@ -1416,8 +1457,8 @@ pci_find_cap_method(device_t dev, device_t child, int capability,
{
struct pci_devinfo *dinfo = device_get_ivars(child);
pcicfgregs *cfg = &dinfo->cfg;
- u_int32_t status;
- u_int8_t ptr;
+ uint32_t status;
+ uint8_t ptr;
/*
* Check the CAP_LIST bit of the PCI status register first.
@@ -1459,6 +1500,33 @@ pci_find_cap_method(device_t dev, device_t child, int capability,
}
/*
+ * Find the next requested capability after start and return the offset in
+ * configuration space via the pointer provided. The function returns
+ * 0 on success and an error code otherwise.
+ */
+int
+pci_find_next_cap_method(device_t dev, device_t child, int capability,
+ int start, int *capreg)
+{
+ uint8_t ptr;
+
+ KASSERT(pci_read_config(child, start + PCICAP_ID, 1) == capability,
+ ("start capability is not expected capability"));
+
+ ptr = pci_read_config(child, start + PCICAP_NEXTPTR, 1);
+ while (ptr != 0) {
+ if (pci_read_config(child, ptr + PCICAP_ID, 1) == capability) {
+ if (capreg != NULL)
+ *capreg = ptr;
+ return (0);
+ }
+ ptr = pci_read_config(child, ptr + PCICAP_NEXTPTR, 1);
+ }
+
+ return (ENOENT);
+}
+
+/*
* Find the requested extended capability and return the offset in
* configuration space via the pointer provided. The function returns
* 0 on success and an error code otherwise.
@@ -1496,6 +1564,41 @@ pci_find_extcap_method(device_t dev, device_t child, int capability,
}
/*
+ * Find the next requested extended capability after start and return the
+ * offset in configuration space via the pointer provided. The function
+ * returns 0 on success and an error code otherwise.
+ */
+int
+pci_find_next_extcap_method(device_t dev, device_t child, int capability,
+ int start, int *capreg)
+{
+ struct pci_devinfo *dinfo = device_get_ivars(child);
+ pcicfgregs *cfg = &dinfo->cfg;
+ uint32_t ecap;
+ uint16_t ptr;
+
+ /* Only supported for PCI-express devices. */
+ if (cfg->pcie.pcie_location == 0)
+ return (ENXIO);
+
+ ecap = pci_read_config(child, start, 4);
+ KASSERT(PCI_EXTCAP_ID(ecap) == capability,
+ ("start extended capability is not expected capability"));
+ ptr = PCI_EXTCAP_NEXTPTR(ecap);
+ while (ptr != 0) {
+ ecap = pci_read_config(child, ptr, 4);
+ if (PCI_EXTCAP_ID(ecap) == capability) {
+ if (capreg != NULL)
+ *capreg = ptr;
+ return (0);
+ }
+ ptr = PCI_EXTCAP_NEXTPTR(ecap);
+ }
+
+ return (ENOENT);
+}
+
+/*
* Support for MSI-X message interrupts.
*/
static void
diff --git a/freebsd/sys/dev/pci/pci_private.h b/freebsd/sys/dev/pci/pci_private.h
index dd254e66..f468152b 100644
--- a/freebsd/sys/dev/pci/pci_private.h
+++ b/freebsd/sys/dev/pci/pci_private.h
@@ -90,10 +90,16 @@ int pci_enable_io_method(device_t dev, device_t child, int space);
int pci_disable_io_method(device_t dev, device_t child, int space);
int pci_find_cap_method(device_t dev, device_t child,
int capability, int *capreg);
+int pci_find_next_cap_method(device_t dev, device_t child,
+ int capability, int start, int *capreg);
int pci_find_extcap_method(device_t dev, device_t child,
int capability, int *capreg);
+int pci_find_next_extcap_method(device_t dev, device_t child,
+ int capability, int start, int *capreg);
int pci_find_htcap_method(device_t dev, device_t child,
int capability, int *capreg);
+int pci_find_next_htcap_method(device_t dev, device_t child,
+ int capability, int start, int *capreg);
int pci_alloc_msi_method(device_t dev, device_t child, int *count);
int pci_alloc_msix_method(device_t dev, device_t child, int *count);
void pci_enable_msi_method(device_t dev, device_t child,
diff --git a/freebsd/sys/dev/pci/pci_user.c b/freebsd/sys/dev/pci/pci_user.c
index 6e1cc3ef..e6297bd7 100644
--- a/freebsd/sys/dev/pci/pci_user.c
+++ b/freebsd/sys/dev/pci/pci_user.c
@@ -764,12 +764,16 @@ pci_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *t
* tell the user that there are more matches
* left.
*/
- if (cio->num_matches >= ionum)
+ if (cio->num_matches >= ionum) {
+ error = 0;
break;
+ }
#ifdef PRE7_COMPAT
#ifdef COMPAT_FREEBSD32
if (cmd == PCIOCGETCONF_OLD32) {
+ memset(&conf_old32, 0,
+ sizeof(conf_old32));
conf_old32.pc_sel.pc_bus =
dinfo->conf.pc_sel.pc_bus;
conf_old32.pc_sel.pc_dev =
@@ -803,6 +807,7 @@ pci_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *t
} else
#endif /* COMPAT_FREEBSD32 */
if (cmd == PCIOCGETCONF_OLD) {
+ memset(&conf_old, 0, sizeof(conf_old));
conf_old.pc_sel.pc_bus =
dinfo->conf.pc_sel.pc_bus;
conf_old.pc_sel.pc_dev =
diff --git a/freebsd/sys/dev/pci/pcivar.h b/freebsd/sys/dev/pci/pcivar.h
index 430e29db..492b7117 100644
--- a/freebsd/sys/dev/pci/pcivar.h
+++ b/freebsd/sys/dev/pci/pcivar.h
@@ -468,18 +468,39 @@ pci_find_cap(device_t dev, int capability, int *capreg)
}
static __inline int
+pci_find_next_cap(device_t dev, int capability, int start, int *capreg)
+{
+ return (PCI_FIND_NEXT_CAP(device_get_parent(dev), dev, capability, start,
+ capreg));
+}
+
+static __inline int
pci_find_extcap(device_t dev, int capability, int *capreg)
{
return (PCI_FIND_EXTCAP(device_get_parent(dev), dev, capability, capreg));
}
static __inline int
+pci_find_next_extcap(device_t dev, int capability, int start, int *capreg)
+{
+ return (PCI_FIND_NEXT_EXTCAP(device_get_parent(dev), dev, capability,
+ start, capreg));
+}
+
+static __inline int
pci_find_htcap(device_t dev, int capability, int *capreg)
{
return (PCI_FIND_HTCAP(device_get_parent(dev), dev, capability, capreg));
}
static __inline int
+pci_find_next_htcap(device_t dev, int capability, int start, int *capreg)
+{
+ return (PCI_FIND_NEXT_HTCAP(device_get_parent(dev), dev, capability,
+ start, capreg));
+}
+
+static __inline int
pci_alloc_msi(device_t dev, int *count)
{
return (PCI_ALLOC_MSI(device_get_parent(dev), dev, count));