changeset 3961:d0e2cb165836

6418673 pcicfg should support downstream transparent bridges 6496579 Spelling errors in pcicfg.e.c error messages
author zk194757
date Tue, 03 Apr 2007 06:46:12 -0700
parents 8ab802bbe8b2
children 85f418471203
files usr/src/uts/sun4/io/pcicfg.e.c
diffstat 1 files changed, 55 insertions(+), 11 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/uts/sun4/io/pcicfg.e.c	Tue Apr 03 03:12:32 2007 -0700
+++ b/usr/src/uts/sun4/io/pcicfg.e.c	Tue Apr 03 06:46:12 2007 -0700
@@ -288,7 +288,8 @@
 static int pcicfg_device_assign(dev_info_t *);
 static int pcicfg_bridge_assign(dev_info_t *, void *);
 static int pcicfg_free_resources(dev_info_t *);
-static void pcicfg_setup_bridge(pcicfg_phdl_t *, ddi_acc_handle_t);
+static void pcicfg_setup_bridge(pcicfg_phdl_t *, ddi_acc_handle_t,
+    dev_info_t *);
 static void pcicfg_update_bridge(pcicfg_phdl_t *, ddi_acc_handle_t);
 static void pcicfg_enable_bridge_probe_err(dev_info_t *dip,
 				ddi_acc_handle_t h, pcicfg_err_regs_t *regs);
@@ -297,7 +298,7 @@
 static int pcicfg_update_assigned_prop(dev_info_t *, pci_regspec_t *);
 static void pcicfg_device_on(ddi_acc_handle_t);
 static void pcicfg_device_off(ddi_acc_handle_t);
-static int pcicfg_set_busnode_props(dev_info_t *, uint8_t);
+static int pcicfg_set_busnode_props(dev_info_t *, uint8_t, int, int);
 static int pcicfg_free_bridge_resources(dev_info_t *);
 static int pcicfg_free_device_resources(dev_info_t *);
 static int pcicfg_teardown_device(dev_info_t *);
@@ -837,8 +838,8 @@
 	pci_config_teardown(&config_handle);
 
 	/* create Bus node properties for ntbridge. */
-	if (pcicfg_set_busnode_props(new_device, pcie_device_type) !=
-						PCICFG_SUCCESS) {
+	if (pcicfg_set_busnode_props(new_device, pcie_device_type, -1, -1) !=
+	    PCICFG_SUCCESS) {
 		DEBUG0("Failed to set busnode props\n");
 		return (rc);
 	}
@@ -882,7 +883,8 @@
 	rc = ndi_devi_online(new_device, NDI_NO_EVENT|NDI_CONFIG);
 	if (rc != NDI_SUCCESS) {
 		cmn_err(CE_WARN,
-		"pcicfg: Fail:cant load nontransparent bridgd driver..\n");
+		    "pcicfg: Fail: can\'t load non-transparent bridge \
+		    driver.\n");
 		rc = PCICFG_FAILURE;
 		return (rc);
 	}
@@ -1016,7 +1018,7 @@
 	DEBUG1("pcicfg: now unloading the ntbridge driver. rc1=%d\n", rc1);
 	if (rc1 != NDI_SUCCESS) {
 		cmn_err(CE_WARN,
-		"pcicfg: cant unload ntbridge driver..children.\n");
+		    "pcicfg: can\'t unload ntbridge driver children.\n");
 		rc = PCICFG_FAILURE;
 	}
 
@@ -1738,7 +1740,7 @@
 		bzero((caddr_t)range,
 			sizeof (pcicfg_range_t) * PCICFG_RANGE_LEN);
 
-		(void) pcicfg_setup_bridge(entry, handle);
+		(void) pcicfg_setup_bridge(entry, handle, dip);
 
 		range[0].child_hi = range[0].parent_hi |=
 			(PCI_REG_REL_M | PCI_ADDR_IO);
@@ -3191,7 +3193,8 @@
 	return (PCICFG_SUCCESS);
 }
 static int
-pcicfg_set_busnode_props(dev_info_t *dip, uint8_t pcie_device_type)
+pcicfg_set_busnode_props(dev_info_t *dip, uint8_t pcie_device_type,
+    int pbus, int sbus)
 {
 	int ret;
 	char device_type[8];
@@ -3213,6 +3216,21 @@
 				"#size-cells", 2)) != DDI_SUCCESS) {
 		return (ret);
 	}
+
+	/*
+	 * Create primary-bus and secondary-bus properties to be used
+	 * to restore bus numbers in the pcicfg_setup_bridge() routine.
+	 */
+	if (pbus != -1 && sbus != -1) {
+		if ((ret = ndi_prop_update_int(DDI_DEV_T_NONE, dip,
+		    "primary-bus", pbus)) != DDI_SUCCESS) {
+				return (ret);
+		}
+		if ((ret = ndi_prop_update_int(DDI_DEV_T_NONE, dip,
+		    "secondary-bus", sbus)) != DDI_SUCCESS) {
+				return (ret);
+		}
+	}
 	return (PCICFG_SUCCESS);
 }
 
@@ -3419,13 +3437,39 @@
  */
 static void
 pcicfg_setup_bridge(pcicfg_phdl_t *entry,
-	ddi_acc_handle_t handle)
+    ddi_acc_handle_t handle, dev_info_t *dip)
 {
+	int pbus, sbus;
+
 	/*
 	 * The highest bus seen during probing is the max-subordinate bus
 	 */
 	pci_config_put8(handle, PCI_BCNF_SUBBUS, entry->highest_bus);
 
+
+	/*
+	 * If there exists more than 1 downstream bridge, it
+	 * will be reset by the below secondary bus reset which
+	 * will clear the bus numbers assumed to be programmed in
+	 * the pcicfg_probe_children() routine.  We therefore restore
+	 * them here.
+	 */
+	if (pci_config_get8(handle, PCI_BCNF_SECBUS) == 0) {
+		pbus = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
+		    DDI_PROP_DONTPASS, "primary-bus", -1);
+		sbus = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
+		    DDI_PROP_DONTPASS, "secondary-bus", -1);
+		if (pbus != -1 && sbus != -1) {
+			pci_config_put8(handle, PCI_BCNF_PRIBUS, (uint_t)pbus);
+			pci_config_put8(handle, PCI_BCNF_SECBUS, (uint_t)sbus);
+		} else {
+			cmn_err(CE_WARN, "Invalid Bridge number detected: \
+			    %s%d: pbus = 0x%x, sbus = 0x%x",
+			    ddi_get_name(dip), ddi_get_instance(dip), pbus,
+			    sbus);
+		}
+	}
+
 	/*
 	 * Reset the secondary bus
 	 */
@@ -4534,8 +4578,8 @@
 	/*
 	 * Set bus properties
 	 */
-	if (pcicfg_set_busnode_props(new_child, pcie_device_type)
-				!= PCICFG_SUCCESS) {
+	if (pcicfg_set_busnode_props(new_child, pcie_device_type,
+	    (int)bus, (int)new_bus) != PCICFG_SUCCESS) {
 		DEBUG0("Failed to set busnode props\n");
 		return (PCICFG_FAILURE);
 	}