summaryrefslogtreecommitdiff
path: root/usr/src
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src')
-rw-r--r--usr/src/uts/i86pc/io/pci/pci_common.c125
-rw-r--r--usr/src/uts/i86pc/io/pcplusmp/apic_introp.c8
-rw-r--r--usr/src/uts/intel/io/hotplug/pcicfg/pcicfg.c11
-rw-r--r--usr/src/uts/intel/io/pciex/pcie_nvidia.c12
4 files changed, 106 insertions, 50 deletions
diff --git a/usr/src/uts/i86pc/io/pci/pci_common.c b/usr/src/uts/i86pc/io/pci/pci_common.c
index f432b85130..cacc0ae123 100644
--- a/usr/src/uts/i86pc/io/pci/pci_common.c
+++ b/usr/src/uts/i86pc/io/pci/pci_common.c
@@ -52,6 +52,7 @@
#include <io/pci/pci_common.h>
#include <sys/pci_cfgspace.h>
#include <sys/pci_impl.h>
+#include <sys/pci_cap.h>
/*
* Function prototypes
@@ -199,8 +200,11 @@ pci_common_intr_ops(dev_info_t *pdip, dev_info_t *rdip, ddi_intr_op_t intr_op,
int types = 0;
int pciepci = 0;
int i, j, count;
+ int rv;
int behavior;
int cap_ptr;
+ uint16_t msi_cap_base, msix_cap_base, cap_ctrl;
+ char *prop;
ddi_intrspec_t isp;
struct intrspec *ispec;
ddi_intr_handle_impl_t tmp_hdl;
@@ -216,27 +220,86 @@ pci_common_intr_ops(dev_info_t *pdip, dev_info_t *rdip, ddi_intr_op_t intr_op,
/* Process the request */
switch (intr_op) {
case DDI_INTROP_SUPPORTED_TYPES:
+ /*
+ * First we determine the interrupt types supported by the
+ * device itself, then we filter them through what the OS
+ * and system supports. We determine system-level
+ * interrupt type support for anything other than fixed intrs
+ * through the psm_intr_ops vector
+ */
+ rv = DDI_FAILURE;
+
/* Fixed supported by default */
- *(int *)result = DDI_INTR_TYPE_FIXED;
+ types = DDI_INTR_TYPE_FIXED;
- /* Figure out if MSI or MSI-X is supported? */
- if (pci_msi_get_supported_type(rdip, &types) != DDI_SUCCESS)
+ if (psm_intr_ops == NULL) {
+ *(int *)result = types;
return (DDI_SUCCESS);
+ }
+ if (pci_config_setup(rdip, &handle) != DDI_SUCCESS)
+ return (DDI_FAILURE);
- if (psm_intr_ops != NULL) {
- /*
- * Only support MSI for now, OR it in
- */
- *(int *)result |= (types & DDI_INTR_TYPE_MSI);
+ /* Sanity test cap control values if found */
- tmp_hdl.ih_type = *(int *)result;
- (void) (*psm_intr_ops)(rdip, &tmp_hdl,
- PSM_INTR_OP_CHECK_MSI, result);
- DDI_INTR_NEXDBG((CE_CONT, "pci_common_intr_ops: "
- "rdip: 0x%p supported types: 0x%x\n", (void *)rdip,
- *(int *)result));
+ if (PCI_CAP_LOCATE(handle, PCI_CAP_ID_MSI, &msi_cap_base) ==
+ DDI_SUCCESS) {
+ cap_ctrl = PCI_CAP_GET16(handle, 0, msi_cap_base,
+ PCI_MSI_CTRL);
+ if (cap_ctrl == PCI_CAP_EINVAL16)
+ goto SUPPORTED_TYPES_OUT;
+
+ types |= DDI_INTR_TYPE_MSI;
}
- break;
+
+ if (PCI_CAP_LOCATE(handle, PCI_CAP_ID_MSI_X, &msix_cap_base) ==
+ DDI_SUCCESS) {
+ cap_ctrl = PCI_CAP_GET16(handle, 0, msix_cap_base,
+ PCI_MSIX_CTRL);
+ if (cap_ctrl == PCI_CAP_EINVAL16)
+ goto SUPPORTED_TYPES_OUT;
+
+ types |= DDI_INTR_TYPE_MSIX;
+ }
+
+ /*
+ * Filter device-level types through system-level support
+ */
+
+ /* No official MSI-X support for now */
+ types &= ~DDI_INTR_TYPE_MSIX;
+
+ tmp_hdl.ih_type = types;
+ if ((*psm_intr_ops)(rdip, &tmp_hdl, PSM_INTR_OP_CHECK_MSI,
+ &types) != PSM_SUCCESS)
+ goto SUPPORTED_TYPES_OUT;
+
+ DDI_INTR_NEXDBG((CE_CONT, "pci_common_intr_ops: "
+ "rdip: 0x%p supported types: 0x%x\n", (void *)rdip,
+ *(int *)result));
+
+ /*
+ * Export any MSI/MSI-X cap locations via properties
+ */
+ if (types & DDI_INTR_TYPE_MSI) {
+ if (ndi_prop_update_int(DDI_DEV_T_NONE, rdip,
+ "pci-msi-capid-pointer", (int)msi_cap_base) !=
+ DDI_PROP_SUCCESS)
+ goto SUPPORTED_TYPES_OUT;
+ }
+ if (types & DDI_INTR_TYPE_MSIX) {
+ if (ndi_prop_update_int(DDI_DEV_T_NONE, rdip,
+ "pci-msix-capid-pointer", (int)msix_cap_base) !=
+ DDI_PROP_SUCCESS)
+ goto SUPPORTED_TYPES_OUT;
+ }
+
+ rv = DDI_SUCCESS;
+
+SUPPORTED_TYPES_OUT:
+ *(int *)result = types;
+ pci_config_teardown(&handle);
+ return (rv);
+
case DDI_INTROP_NAVAIL:
case DDI_INTROP_NINTRS:
if (DDI_INTR_IS_MSI_OR_MSIX(hdlp->ih_type)) {
@@ -280,19 +343,33 @@ pci_common_intr_ops(dev_info_t *pdip, dev_info_t *rdip, ddi_intr_op_t intr_op,
i_ddi_set_pci_config_handle(rdip, handle);
}
- if (i_ddi_get_msi_msix_cap_ptr(rdip) == 0) {
- char *prop =
- (hdlp->ih_type == DDI_INTR_TYPE_MSI) ?
- "pci-msi-capid-pointer" :
- "pci-msix-capid-pointer";
+ prop = NULL;
+ cap_ptr = 0;
+ if (hdlp->ih_type == DDI_INTR_TYPE_MSI)
+ prop = "pci-msi-capid-pointer";
+ else if (hdlp->ih_type == DDI_INTR_TYPE_MSIX)
+ prop = "pci-msix-capid-pointer";
+ /*
+ * Enforce the calling of DDI_INTROP_SUPPORTED_TYPES
+ * for MSI(X) before allocation
+ */
+ if (prop != NULL) {
cap_ptr = ddi_prop_get_int(DDI_DEV_T_ANY, rdip,
- DDI_PROP_DONTPASS, prop,
- PCI_CAP_NEXT_PTR_NULL);
- i_ddi_set_msi_msix_cap_ptr(rdip, cap_ptr);
+ DDI_PROP_DONTPASS, prop, 0);
+ if (cap_ptr == 0) {
+ DDI_INTR_NEXDBG((CE_CONT,
+ "pci_common_intr_ops: rdip: 0x%p "
+ "attempted MSI(X) alloc without "
+ "cap property\n", (void *)rdip));
+ return (DDI_FAILURE);
+ }
}
+ i_ddi_set_msi_msix_cap_ptr(rdip, cap_ptr);
-
+ /*
+ * Allocate interrupt vectors
+ */
(void) (*psm_intr_ops)(rdip, hdlp,
PSM_INTR_OP_ALLOC_VECTORS, result);
diff --git a/usr/src/uts/i86pc/io/pcplusmp/apic_introp.c b/usr/src/uts/i86pc/io/pcplusmp/apic_introp.c
index 02617ae071..324c8cb54d 100644
--- a/usr/src/uts/i86pc/io/pcplusmp/apic_introp.c
+++ b/usr/src/uts/i86pc/io/pcplusmp/apic_introp.c
@@ -89,7 +89,7 @@ apic_pci_msi_enable_vector(dev_info_t *dip, int type, int inum, int vector,
"\tdriver = %s, inum=0x%x vector=0x%x apicid=0x%x\n", (void *)dip,
ddi_driver_name(dip), inum, vector, target_apic_id));
- if (handle == NULL)
+ if (handle == NULL || cap_ptr == 0)
return (PSM_FAILURE);
/* MSI Address */
@@ -553,7 +553,7 @@ apic_pci_msi_unconfigure(dev_info_t *rdip, int type, int inum)
int cap_ptr = i_ddi_get_msi_msix_cap_ptr(rdip);
ddi_acc_handle_t handle = i_ddi_get_pci_config_handle(rdip);
- if (handle == NULL)
+ if (handle == NULL || cap_ptr == 0)
return (PSM_FAILURE);
if (type == DDI_INTR_TYPE_MSI) {
@@ -600,7 +600,7 @@ apic_pci_msi_enable_mode(dev_info_t *rdip, int type, int inum)
int cap_ptr = i_ddi_get_msi_msix_cap_ptr(rdip);
ddi_acc_handle_t handle = i_ddi_get_pci_config_handle(rdip);
- if (handle == NULL)
+ if (handle == NULL || cap_ptr == 0)
return (PSM_FAILURE);
if (type == DDI_INTR_TYPE_MSI) {
@@ -644,7 +644,7 @@ apic_pci_msi_disable_mode(dev_info_t *rdip, int type, int inum)
int cap_ptr = i_ddi_get_msi_msix_cap_ptr(rdip);
ddi_acc_handle_t handle = i_ddi_get_pci_config_handle(rdip);
- if (handle == NULL)
+ if (handle == NULL || cap_ptr == 0)
return (PSM_FAILURE);
if (type == DDI_INTR_TYPE_MSI) {
diff --git a/usr/src/uts/intel/io/hotplug/pcicfg/pcicfg.c b/usr/src/uts/intel/io/hotplug/pcicfg/pcicfg.c
index 1ca88880c4..6081d9a8b7 100644
--- a/usr/src/uts/intel/io/hotplug/pcicfg/pcicfg.c
+++ b/usr/src/uts/intel/io/hotplug/pcicfg/pcicfg.c
@@ -2969,17 +2969,6 @@ pcicfg_set_standard_props(dev_info_t *dip, ddi_acc_handle_t config_handle,
return (ret);
}
}
- if ((cap_id_loc = pcicfg_get_cap(config_handle, PCI_CAP_ID_MSI)) > 0) {
- if ((ret = ndi_prop_update_int(DDI_DEV_T_NONE, dip,
- "pci-msi-capid-pointer", cap_id_loc)) != DDI_SUCCESS)
- return (ret);
- }
- if ((cap_id_loc = pcicfg_get_cap(config_handle, PCI_CAP_ID_MSI_X)) >
- 0) {
- if ((ret = ndi_prop_update_int(DDI_DEV_T_NONE, dip,
- "pci-msix-capid-pointer", cap_id_loc)) != DDI_SUCCESS)
- return (ret);
- }
if ((cap_id_loc = pcicfg_get_cap(config_handle, PCI_CAP_ID_PCIX)) > 0) {
/* create the pcix-capid-pointer property */
if ((ret = ndi_prop_update_int(DDI_DEV_T_NONE, dip,
diff --git a/usr/src/uts/intel/io/pciex/pcie_nvidia.c b/usr/src/uts/intel/io/pciex/pcie_nvidia.c
index aec3a31580..23f3993b9f 100644
--- a/usr/src/uts/intel/io/pciex/pcie_nvidia.c
+++ b/usr/src/uts/intel/io/pciex/pcie_nvidia.c
@@ -20,7 +20,7 @@
*/
/*
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -71,16 +71,6 @@ check_if_device_is_pciex(dev_info_t *cdip, uchar_t bus, uchar_t dev,
(void) ndi_prop_update_int(DDI_DEV_T_NONE, cdip,
"pcix-capid-pointer", capsp);
- if (cap == PCI_CAP_ID_MSI && cdip) {
- (void) ndi_prop_update_int(DDI_DEV_T_NONE, cdip,
- "pci-msi-capid-pointer", capsp);
- }
-
- if (cap == PCI_CAP_ID_MSI_X && cdip) {
- (void) ndi_prop_update_int(DDI_DEV_T_NONE, cdip,
- "pci-msix-capid-pointer", capsp);
- }
-
if (cap == PCI_CAP_ID_PCI_E) {
#ifdef DEBUG
if (pci_boot_debug)