changeset 3625:e65afa5b6fae

6504958 px: WARNING: px4: ino 0x15 blocked 6506837 ddi_intr_alloc() should not allow multiple allocations after max allocation is reached 6520838 Interrupts should not be registered for rev AA of PLX hardware 6522439 uninitialized field in pxtool_get_phys_addr can cause pcitool config access to fail
author egillett
date Fri, 09 Feb 2007 11:58:24 -0800
parents 63608428a281
children 8840ea2939d4
files usr/src/uts/common/os/ddi_intr.c usr/src/uts/common/sys/ddi_intr_impl.h usr/src/uts/sun4/io/px/px_pci.c usr/src/uts/sun4/io/px/px_pci.h usr/src/uts/sun4/io/px/px_tools.c
diffstat 5 files changed, 62 insertions(+), 31 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/uts/common/os/ddi_intr.c	Fri Feb 09 11:00:27 2007 -0800
+++ b/usr/src/uts/common/os/ddi_intr.c	Fri Feb 09 11:58:24 2007 -0800
@@ -19,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -47,7 +47,7 @@
  * MSI/X allocation limit.
  * This limit will change with Resource Management support.
  */
-uint_t		ddi_msix_alloc_limit = 2;
+uint_t		ddi_msix_alloc_limit = DDI_INTR_DEFAULT_ALLOC;
 
 /*
  * ddi_intr_get_supported_types:
@@ -176,7 +176,7 @@
 {
 	ddi_intr_handle_impl_t	*hdlp, tmp_hdl;
 	int			i, ret, cap = 0, intr_type, nintrs = 0;
-	uint_t			pri;
+	uint_t			pri, curr_nintrs = 0;
 
 	DDI_INTR_APIDBG((CE_CONT, "ddi_intr_alloc: name %s dip 0x%p "
 	    "type %x inum %x count %x behavior %x\n", ddi_driver_name(dip),
@@ -245,10 +245,11 @@
 		DDI_INTR_APIDBG((CE_CONT, "ddi_intr_alloc: type %x "
 		    "is already being used\n", type));
 
-		if ((count + i_ddi_intr_get_current_nintrs(dip)) > nintrs) {
+		curr_nintrs = i_ddi_intr_get_current_nintrs(dip);
+		if ((count + curr_nintrs) > nintrs) {
 			DDI_INTR_APIDBG((CE_CONT, "ddi_intr_alloc: count %d "
 			    "+ intrs in use %d exceeds supported %d intrs\n",
-			    count, i_ddi_intr_get_current_nintrs(dip), nintrs));
+			    count, curr_nintrs, nintrs));
 			return (DDI_EINVAL);
 		}
 	}
@@ -266,19 +267,27 @@
 	 * Limit max MSI/X allocation to ddi_msix_alloc_limit.
 	 * This limit will change with Resource Management support.
 	 */
-	if (DDI_INTR_IS_MSI_OR_MSIX(type) && (count > ddi_msix_alloc_limit)) {
-		DDI_INTR_APIDBG((CE_CONT, "ddi_intr_alloc: Requested MSI/Xs %d"
-		    "Max MSI/Xs limit %d\n", count, ddi_msix_alloc_limit));
-
-		if (behavior == DDI_INTR_ALLOC_STRICT) {
+	if (DDI_INTR_IS_MSI_OR_MSIX(type)) {
+		if (curr_nintrs == ddi_msix_alloc_limit) {
 			DDI_INTR_APIDBG((CE_CONT, "ddi_intr_alloc: "
-			    "DDI_INTR_ALLOC_STRICT flag is passed, "
-			    "return failure\n"));
+			    "max # of intrs %d already allocated\n",
+			    curr_nintrs));
+			return (DDI_EINVAL);
+		}
+		if ((count + curr_nintrs) > ddi_msix_alloc_limit) {
+			DDI_INTR_APIDBG((CE_CONT, "ddi_intr_alloc: Requested "
+			    "MSI/Xs %d Max MSI/Xs limit %d\n", count,
+			    ddi_msix_alloc_limit));
 
-			return (DDI_EAGAIN);
+			if (behavior == DDI_INTR_ALLOC_STRICT) {
+				DDI_INTR_APIDBG((CE_CONT, "ddi_intr_alloc: "
+				    "DDI_INTR_ALLOC_STRICT flag is passed, "
+				    "return failure\n"));
+				return (DDI_EAGAIN);
+			}
+
+			count = ddi_msix_alloc_limit - curr_nintrs;
 		}
-
-		count = ddi_msix_alloc_limit;
 	}
 
 	/* Now allocate required number of interrupts */
--- a/usr/src/uts/common/sys/ddi_intr_impl.h	Fri Feb 09 11:00:27 2007 -0800
+++ b/usr/src/uts/common/sys/ddi_intr_impl.h	Fri Feb 09 11:58:24 2007 -0800
@@ -19,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -132,6 +132,9 @@
 /* values for ih_flags */
 #define	DDI_INTR_MSIX_DUP	0x01	/* MSI-X vector which has been dupped */
 
+/* Default number of MSI/X resources to allocate */
+#define	DDI_INTR_DEFAULT_ALLOC		2
+
 struct av_softinfo;
 
 /*
@@ -313,7 +316,7 @@
  */
 typedef enum {DDI_INTR_CTLOPS_NONE} ddi_intr_ctlop_t;
 
-/* The following are the obsolete interfaces */
+/* The following are obsolete interfaces */
 ddi_intrspec_t	i_ddi_get_intrspec(dev_info_t *dip, dev_info_t *rdip,
 	    uint_t inumber);
 
--- a/usr/src/uts/sun4/io/px/px_pci.c	Fri Feb 09 11:00:27 2007 -0800
+++ b/usr/src/uts/sun4/io/px/px_pci.c	Fri Feb 09 11:58:24 2007 -0800
@@ -450,25 +450,47 @@
 	}
 
 	/*
-	 * Initialize hotplug support on this bus. At minimum
-	 * (for non hotplug bus) this would create ":devctl" minor
-	 * node to support DEVCTL_DEVICE_* and DEVCTL_BUS_* ioctls
-	 * to this bus. This all takes place if this nexus has hot-plug
+	 * Initialize hotplug support on this bus except for the PLX switch
+	 * revision AA. At a minimum (for non hotplug bus) this would create
+	 * ":devctl" minor node to support DEVCTL_DEVICE_* and DEVCTL_BUS_*
+	 * ioctls to this bus. This all takes place if this nexus has hot-plug
 	 * slots and successfully initializes Hot Plug Framework.
 	 */
 	pxb->pxb_hotplug_capable = B_FALSE;
 
+#ifdef PX_PLX
+	if (pxb->pxb_rev_id <= PXB_DEVICE_PLX_AA_REV)
+		goto hotplug_done;
+#endif /* PX_PLX */
+
 	if ((pxb->pxb_port_type == PX_CAP_REG_DEV_TYPE_DOWN) ||
 	    (pxb->pxb_port_type == PX_CAP_REG_DEV_TYPE_PCIE2PCI) ||
 	    (pxb->pxb_port_type == PX_CAP_REG_DEV_TYPE_PCI2PCIE)) {
+#ifdef PX_PLX
+		/*
+		 * Workaround for a race condition between hotplug
+		 * initialization and actual MSI interrupt registration
+		 * for hotplug functionality. The hotplug initialization
+		 * generates an INTx interrupt for hotplug events and this
+		 * INTx interrupt may interfere with shared leaf drivers
+		 * using same INTx interrupt, which may eventually block
+		 * the leaf drivers.
+		 */
+		pci_config_put16(config_handle, PCI_CONF_COMM,
+		    pci_config_get16(config_handle, PCI_CONF_COMM) |
+		    PCI_COMM_INTX_DISABLE);
+#endif /* PX_PLX */
+
 		pxb_init_hotplug(pxb);
 	}
 
-	/* attach interrupt only if hotplug functionality is required */
-	if (pxb->pxb_hotplug_capable != B_FALSE) {
+	/* Attach interrupt only if hotplug functionality is required */
+	if (pxb->pxb_hotplug_capable == B_TRUE) {
 		if (pxb_intr_attach(pxb) != DDI_SUCCESS)
 			goto fail;
 	}
+
+hotplug_done:
 #ifdef	PRINT_PLX_SEEPROM_CRC
 	/* check seeprom CRC to ensure the platform config is right */
 	(void) pxb_print_plx_seeprom_crc_data(pxb);
@@ -1022,11 +1044,6 @@
 		return (DDI_FAILURE);
 	}
 
-#ifdef PX_PLX
-	if (pxb->pxb_rev_id <= PXB_DEVICE_PLX_BAD_MSI_REV)
-		intr_types &= DDI_INTR_TYPE_FIXED;
-#endif /* PX_PLX */
-
 	if ((intr_types & DDI_INTR_TYPE_MSI) && pxb_enable_msi) {
 		if (pxb_intr_init(pxb, DDI_INTR_TYPE_MSI) == DDI_SUCCESS)
 			intr_types = DDI_INTR_TYPE_MSI;
--- a/usr/src/uts/sun4/io/px/px_pci.h	Fri Feb 09 11:00:27 2007 -0800
+++ b/usr/src/uts/sun4/io/px/px_pci.h	Fri Feb 09 11:58:24 2007 -0800
@@ -19,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -178,7 +178,8 @@
 #define	PXB_DEVICE_PLX_8532		0x8532
 #define	PXB_DEVICE_PLX_8516		0x8516
 
-#define	PXB_DEVICE_PLX_BAD_MSI_REV	0xAA	/* last known bad rev for MSI */
+/* Last known bad rev for MSI and other issues */
+#define	PXB_DEVICE_PLX_AA_REV		0xAA
 
 #define	PXB_VENDOR_SUN			0x108E
 #define	PXB_DEVICE_PLX_PCIX		0x9010
--- a/usr/src/uts/sun4/io/px/px_tools.c	Fri Feb 09 11:00:27 2007 -0800
+++ b/usr/src/uts/sun4/io/px/px_tools.c	Fri Feb 09 11:58:24 2007 -0800
@@ -19,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -370,6 +370,7 @@
 		dev_regspec.pci_phys_hi +=
 		    (offset & (PCI_REG_BDFR_M ^ PCI_REG_REG_M));
 		dev_regspec.pci_phys_low = offset & PCI_REG_REG_M;
+		dev_regspec.pci_phys_mid = 0;	/* Not used */
 	} else {
 		dev_regspec.pci_phys_mid = offset >> 32;
 		dev_regspec.pci_phys_low = offset & 0xffffffff;