summaryrefslogtreecommitdiff
path: root/usr/src
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src')
-rw-r--r--usr/src/uts/common/io/pciex/pcie.c73
1 files changed, 65 insertions, 8 deletions
diff --git a/usr/src/uts/common/io/pciex/pcie.c b/usr/src/uts/common/io/pciex/pcie.c
index 347f4699a3..95eaa5837f 100644
--- a/usr/src/uts/common/io/pciex/pcie.c
+++ b/usr/src/uts/common/io/pciex/pcie.c
@@ -21,6 +21,7 @@
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, Joyent, Inc.
*/
#include <sys/sysmacros.h>
@@ -466,6 +467,52 @@ pcie_fini_cfghdl(dev_info_t *cdip)
pci_config_teardown(&bus_p->bus_cfg_hdl);
}
+void
+pcie_determine_serial(dev_info_t *dip)
+{
+ pcie_bus_t *bus_p = PCIE_DIP2BUS(dip);
+ ddi_acc_handle_t h;
+ uint16_t cap;
+ uchar_t serial[8];
+ uint32_t low, high;
+
+ if (!PCIE_IS_PCIE(bus_p))
+ return;
+
+ h = bus_p->bus_cfg_hdl;
+
+ if ((PCI_CAP_LOCATE(h, PCI_CAP_XCFG_SPC(PCIE_EXT_CAP_ID_SER), &cap)) ==
+ DDI_FAILURE)
+ return;
+
+ high = PCI_XCAP_GET32(h, 0, cap, PCIE_SER_SID_UPPER_DW);
+ low = PCI_XCAP_GET32(h, 0, cap, PCIE_SER_SID_LOWER_DW);
+
+ /*
+ * Here, we're trying to figure out if we had an invalid PCIe read. From
+ * looking at the contents of the value, it can be hard to tell the
+ * difference between a value that has all 1s correctly versus if we had
+ * an error. In this case, we only assume it's invalid if both register
+ * reads are invalid. We also only use 32-bit reads as we're not sure if
+ * all devices will support these as 64-bit reads, while we know that
+ * they'll support these as 32-bit reads.
+ */
+ if (high == PCI_EINVAL32 && low == PCI_EINVAL32)
+ return;
+
+ serial[0] = low & 0xff;
+ serial[1] = (low >> 8) & 0xff;
+ serial[2] = (low >> 16) & 0xff;
+ serial[3] = (low >> 24) & 0xff;
+ serial[4] = high & 0xff;
+ serial[5] = (high >> 8) & 0xff;
+ serial[6] = (high >> 16) & 0xff;
+ serial[7] = (high >> 24) & 0xff;
+
+ (void) ndi_prop_update_byte_array(DDI_DEV_T_NONE, dip, "pcie-serial",
+ serial, sizeof (serial));
+}
+
/*
* PCI-Express child device initialization.
* This function enables generic pci-express interrupts and error
@@ -608,6 +655,8 @@ pcie_initchild(dev_info_t *cdip)
/* Enable PCIe errors */
pcie_enable_errors(cdip);
+
+ pcie_determine_serial(cdip);
}
bus_p->bus_ari = B_FALSE;
@@ -1659,24 +1708,29 @@ pcie_get_bdf_for_dma_xfer(dev_info_t *dip, dev_info_t *rdip)
}
uint32_t
-pcie_get_aer_uce_mask() {
+pcie_get_aer_uce_mask()
+{
return (pcie_aer_uce_mask);
}
uint32_t
-pcie_get_aer_ce_mask() {
+pcie_get_aer_ce_mask()
+{
return (pcie_aer_ce_mask);
}
uint32_t
-pcie_get_aer_suce_mask() {
+pcie_get_aer_suce_mask()
+{
return (pcie_aer_suce_mask);
}
uint32_t
-pcie_get_serr_mask() {
+pcie_get_serr_mask()
+{
return (pcie_serr_disable_flag);
}
void
-pcie_set_aer_uce_mask(uint32_t mask) {
+pcie_set_aer_uce_mask(uint32_t mask)
+{
pcie_aer_uce_mask = mask;
if (mask & PCIE_AER_UCE_UR)
pcie_base_err_default &= ~PCIE_DEVCTL_UR_REPORTING_EN;
@@ -1688,15 +1742,18 @@ pcie_set_aer_uce_mask(uint32_t mask) {
}
void
-pcie_set_aer_ce_mask(uint32_t mask) {
+pcie_set_aer_ce_mask(uint32_t mask)
+{
pcie_aer_ce_mask = mask;
}
void
-pcie_set_aer_suce_mask(uint32_t mask) {
+pcie_set_aer_suce_mask(uint32_t mask)
+{
pcie_aer_suce_mask = mask;
}
void
-pcie_set_serr_mask(uint32_t mask) {
+pcie_set_serr_mask(uint32_t mask)
+{
pcie_serr_disable_flag = mask;
}