isci: fix oem parameter initialization and mode detection

1/ Since commit 858d4aa7 "isci: Move firmware loading to per PCI device" we have
   been silently falling back to built-in defaults for the parameter settings by
   skipping the call to scic_oem_parameters_set().

2/ The afe parameters from the firmware were not being honored

3/ The latest oem parameter definition flips the mode_type values which are
   now 0: for APC 1: for MPC.  For APC we need to make sure all the phys
   default to the same address otherwise strict_wide_ports will cause duplicate
   domains.

4/ Fix up the driver announcement to indicate the source of the
   parameters.

5/ Fix up the sas addresses to be unique per controller (in the fallback case)

Signed-off-by: Dave Jiang <dave.jiang@intel.com>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
diff --git a/drivers/scsi/isci/core/sci_base_controller.h b/drivers/scsi/isci/core/sci_base_controller.h
index 36c5340..8e0c46f 100644
--- a/drivers/scsi/isci/core/sci_base_controller.h
+++ b/drivers/scsi/isci/core/sci_base_controller.h
@@ -289,8 +289,6 @@
 	u32 mde_count,
 	struct sci_base_memory_descriptor_list *next_mdl)
 {
-	scic_base->parent.private = NULL;
-
 	sci_base_state_machine_construct(
 		&scic_base->state_machine,
 		&scic_base->parent,
diff --git a/drivers/scsi/isci/core/scic_sds_controller.c b/drivers/scsi/isci/core/scic_sds_controller.c
index 12b2ad5..b0edd84 100644
--- a/drivers/scsi/isci/core/scic_sds_controller.c
+++ b/drivers/scsi/isci/core/scic_sds_controller.c
@@ -595,6 +595,7 @@
  */
 void scic_sds_controller_afe_initialization(struct scic_sds_controller *scic)
 {
+	const struct scic_sds_oem_params *oem = &scic->oem_parameters.sds1;
 	u32 afe_status;
 	u32 phy_id;
 
@@ -632,6 +633,8 @@
 	}
 
 	for (phy_id = 0; phy_id < SCI_MAX_PHYS; phy_id++) {
+		const struct sci_phy_oem_params *oem_phy = &oem->phys[phy_id];
+
 		if (is_b0()) {
 			 /* Configure transmitter SSC parameters */
 			scu_afe_txreg_write(scic, phy_id, afe_tx_ssc_control, 0x00030000);
@@ -691,16 +694,16 @@
 		}
 		udelay(AFE_REGISTER_WRITE_DELAY);
 
-		scu_afe_txreg_write(scic, phy_id, afe_tx_amp_control0, 0x000E7C03);
+		scu_afe_txreg_write(scic, phy_id, afe_tx_amp_control0, oem_phy->afe_tx_amp_control0);
 		udelay(AFE_REGISTER_WRITE_DELAY);
 
-		scu_afe_txreg_write(scic, phy_id, afe_tx_amp_control1, 0x000E7C03);
+		scu_afe_txreg_write(scic, phy_id, afe_tx_amp_control0, oem_phy->afe_tx_amp_control1);
 		udelay(AFE_REGISTER_WRITE_DELAY);
 
-		scu_afe_txreg_write(scic, phy_id, afe_tx_amp_control2, 0x000E7C03);
+		scu_afe_txreg_write(scic, phy_id, afe_tx_amp_control0, oem_phy->afe_tx_amp_control2);
 		udelay(AFE_REGISTER_WRITE_DELAY);
 
-		scu_afe_txreg_write(scic, phy_id, afe_tx_amp_control3, 0x000E7C03);
+		scu_afe_txreg_write(scic, phy_id, afe_tx_amp_control0, oem_phy->afe_tx_amp_control3);
 		udelay(AFE_REGISTER_WRITE_DELAY);
 	}
 
@@ -2027,6 +2030,7 @@
  */
 static void scic_sds_controller_set_default_config_parameters(struct scic_sds_controller *scic)
 {
+	struct isci_host *ihost = sci_object_get_association(scic);
 	u16 index;
 
 	/* Default to APC mode. */
@@ -2058,7 +2062,7 @@
 		 * is worked around by having the upper 32-bits of SAS address
 		 * with a value greater then the Vitesse company identifier.
 		 * Hence, usage of 0x5FCFFFFF. */
-		scic->oem_parameters.sds1.phys[index].sas_address.low = 0x00000001;
+		scic->oem_parameters.sds1.phys[index].sas_address.low = 0x1 + ihost->id;
 		scic->oem_parameters.sds1.phys[index].sas_address.high = 0x5FCFFFFF;
 	}
 
@@ -2604,14 +2608,11 @@
 	struct scic_sds_controller *scic,
 	union scic_oem_parameters *scic_parms)
 {
-	if (
-		(scic->parent.state_machine.current_state_id
-		 == SCI_BASE_CONTROLLER_STATE_RESET)
-		|| (scic->parent.state_machine.current_state_id
-		    == SCI_BASE_CONTROLLER_STATE_INITIALIZING)
-		|| (scic->parent.state_machine.current_state_id
-		    == SCI_BASE_CONTROLLER_STATE_INITIALIZED)
-		) {
+	u32 state = scic->parent.state_machine.current_state_id;
+
+	if (state == SCI_BASE_CONTROLLER_STATE_RESET ||
+	    state == SCI_BASE_CONTROLLER_STATE_INITIALIZING ||
+	    state == SCI_BASE_CONTROLLER_STATE_INITIALIZED) {
 		u16 index;
 		u8  combined_phy_mask = 0;
 
@@ -2651,7 +2652,8 @@
 		if (scic_parms->sds1.controller.max_concurrent_dev_spin_up > MAX_CONCURRENT_DEVICE_SPIN_UP_COUNT)
 			return SCI_FAILURE_INVALID_PARAMETER_VALUE;
 
-		memcpy(&scic->oem_parameters, scic_parms, sizeof(*scic_parms));
+		scic->oem_parameters.sds1 = scic_parms->sds1;
+
 		return SCI_SUCCESS;
 	}
 
diff --git a/drivers/scsi/isci/firmware/create_fw.c b/drivers/scsi/isci/firmware/create_fw.c
index f8f96d6..c7a2887 100644
--- a/drivers/scsi/isci/firmware/create_fw.c
+++ b/drivers/scsi/isci/firmware/create_fw.c
@@ -44,7 +44,7 @@
 
 	/* setting OROM signature */
 	strncpy(isci_orom->hdr.signature, sig, strlen(sig));
-	isci_orom->hdr.version = 0x10;
+	isci_orom->hdr.version = version;
 	isci_orom->hdr.total_block_length = sizeof(struct isci_orom);
 	isci_orom->hdr.hdr_length = sizeof(struct sci_bios_oem_param_block_hdr);
 	isci_orom->hdr.num_elements = num_elements;
@@ -65,6 +65,15 @@
 				(__u32)(sas_addr[ctrl_idx][phy_idx] >> 32);
 			isci_orom->ctrl[ctrl_idx].phys[phy_idx].sas_address.low =
 				(__u32)(sas_addr[ctrl_idx][phy_idx]);
+
+			isci_orom->ctrl[ctrl_idx].phys[phy_idx].afe_tx_amp_control0 =
+				afe_tx_amp_control0;
+			isci_orom->ctrl[ctrl_idx].phys[phy_idx].afe_tx_amp_control1 =
+				afe_tx_amp_control1;
+			isci_orom->ctrl[ctrl_idx].phys[phy_idx].afe_tx_amp_control2 =
+				afe_tx_amp_control2;
+			isci_orom->ctrl[ctrl_idx].phys[phy_idx].afe_tx_amp_control3 =
+				afe_tx_amp_control3;
 		}
 	}
 }
diff --git a/drivers/scsi/isci/firmware/create_fw.h b/drivers/scsi/isci/firmware/create_fw.h
index 788a8de..9f9afbd 100644
--- a/drivers/scsi/isci/firmware/create_fw.h
+++ b/drivers/scsi/isci/firmware/create_fw.h
@@ -25,14 +25,37 @@
  * if there is a port/phy on which you do not wish to override the default
  * values, use the value assigned to UNINIT_PARAM (255).
  */
+
 /* discovery mode type (port auto config mode by default ) */
+
+/*
+ * if there is a port/phy on which you do not wish to override the default
+ * values, use the value "0000000000000000". SAS address of zero's is
+ * considered invalid and will not be used.
+ */
 #ifdef MPC
 static const int mode_type = SCIC_PORT_MANUAL_CONFIGURATION_MODE;
 static const __u8 phy_mask[2][4] = { {1, 2, 4, 8},
 				     {1, 2, 4, 8} };
+static const unsigned long long sas_addr[2][4] = { { 0x5FCFFFFFF0000001ULL,
+						     0x5FCFFFFFF0000002ULL,
+						     0x5FCFFFFFF0000003ULL,
+						     0x5FCFFFFFF0000004ULL },
+						   { 0x5FCFFFFFF0000005ULL,
+						     0x5FCFFFFFF0000006ULL,
+						     0x5FCFFFFFF0000007ULL,
+						     0x5FCFFFFFF0000008ULL } };
 #else	/* APC (default) */
 static const int mode_type = SCIC_PORT_AUTOMATIC_CONFIGURATION_MODE;
 static const __u8 phy_mask[2][4];
+static const unsigned long long sas_addr[2][4] = { { 0x5FCFFFFF00000001ULL,
+						     0x5FCFFFFF00000001ULL,
+						     0x5FCFFFFF00000001ULL,
+						     0x5FCFFFFF00000001ULL },
+						   { 0x5FCFFFFF00000002ULL,
+						     0x5FCFFFFF00000002ULL,
+						     0x5FCFFFFF00000002ULL,
+						     0x5FCFFFFF00000002ULL } };
 #endif
 
 /* Maximum number of concurrent device spin up */
@@ -47,22 +70,8 @@
 static const unsigned int afe_tx_amp_control2 = 0x000e7c03;
 static const unsigned int afe_tx_amp_control3 = 0x000e7c03;
 
-/*
- * if there is a port/phy on which you do not wish to override the default
- * values, use the value "0000000000000000". SAS address of zero's is
- * considered invalid and will not be used.
- */
-static const unsigned long long sas_addr[2][4] = { { 0x5FCFFFFFF0000000ULL,
-						     0x5FCFFFFFF1000000ULL,
-						     0x5FCFFFFFF2000000ULL,
-						     0x5FCFFFFFF3000000ULL },
-						   { 0x5FCFFFFFF4000000ULL,
-						     0x5FCFFFFFF5000000ULL,
-						     0x5FCFFFFFF6000000ULL,
-						     0x5FCFFFFFF7000000ULL } };
-
 static const char blob_name[] = "isci_firmware.bin";
 static const char sig[] = "ISCUOEMB";
-static const unsigned char version = 1;
+static const unsigned char version = 0x10;
 
 #endif
diff --git a/drivers/scsi/isci/host.c b/drivers/scsi/isci/host.c
index bb5b54d..d6e2a73 100644
--- a/drivers/scsi/isci/host.c
+++ b/drivers/scsi/isci/host.c
@@ -418,7 +418,7 @@
 	int err = 0, i;
 	enum sci_status status;
 	struct scic_sds_controller *controller;
-	union scic_oem_parameters scic_oem_params;
+	union scic_oem_parameters oem;
 	union scic_user_parameters scic_user_params;
 	struct isci_pci_info *pci_info = to_pci_info(isci_host->pdev);
 
@@ -435,6 +435,7 @@
 	}
 
 	isci_host->core_controller = controller;
+	sci_object_set_association(isci_host->core_controller, isci_host);
 	spin_lock_init(&isci_host->state_lock);
 	spin_lock_init(&isci_host->scic_lock);
 	spin_lock_init(&isci_host->queue_lock);
@@ -457,12 +458,6 @@
 	isci_host->sas_ha.dev = &isci_host->pdev->dev;
 	isci_host->sas_ha.lldd_ha = isci_host;
 
-	/*----------- SCIC controller Initialization Stuff ------------------
-	 * set association host adapter struct in core controller.
-	 */
-	sci_object_set_association(isci_host->core_controller,
-				   (void *)isci_host);
-
 	/*
 	 * grab initial values stored in the controller object for OEM and USER
 	 * parameters
@@ -477,11 +472,11 @@
 		return -ENODEV;
 	}
 
-	scic_oem_parameters_get(controller, &scic_oem_params);
+	scic_oem_parameters_get(controller, &oem);
 
 	/* grab any OEM parameters specified in orom */
 	if (pci_info->orom) {
-		status = isci_parse_oem_parameters(&scic_oem_params,
+		status = isci_parse_oem_parameters(&oem,
 						   pci_info->orom,
 						   isci_host->id);
 		if (status != SCI_SUCCESS) {
@@ -489,15 +484,14 @@
 				 "parsing firmware oem parameters failed\n");
 			return -EINVAL;
 		}
-	} else {
-		status = scic_oem_parameters_set(isci_host->core_controller,
-						 &scic_oem_params);
-		if (status != SCI_SUCCESS) {
-			dev_warn(&isci_host->pdev->dev,
-				 "%s: scic_oem_parameters_set failed\n",
-				 __func__);
-			return -ENODEV;
-		}
+	}
+
+	status = scic_oem_parameters_set(isci_host->core_controller, &oem);
+	if (status != SCI_SUCCESS) {
+		dev_warn(&isci_host->pdev->dev,
+				"%s: scic_oem_parameters_set failed\n",
+				__func__);
+		return -ENODEV;
 	}
 
 	tasklet_init(&isci_host->completion_tasklet,
diff --git a/drivers/scsi/isci/init.c b/drivers/scsi/isci/init.c
index ef0c49a..51a7bce 100644
--- a/drivers/scsi/isci/init.c
+++ b/drivers/scsi/isci/init.c
@@ -466,6 +466,7 @@
 	struct isci_host *isci_host;
 	const struct firmware *fw = NULL;
 	struct isci_orom *orom;
+	char *source = "(platform)";
 
 	check_si_rev(pdev);
 
@@ -480,6 +481,7 @@
 		orom = isci_request_oprom(pdev);
 
 	if (!orom) {
+		source = "(firmware)";
 		orom = isci_request_firmware(pdev, fw);
 		if (!orom) {
 			/* TODO convert this to WARN_TAINT_ONCE once the
@@ -496,9 +498,9 @@
 
 	if (orom)
 		dev_info(&pdev->dev,
-			 "OEM SAS parameters (version: %u.%u) loaded\n",
+			 "OEM SAS parameters (version: %u.%u) loaded %s\n",
 			 (orom->hdr.version & 0xf0) >> 4,
-			 (orom->hdr.version & 0xf));
+			 (orom->hdr.version & 0xf), source);
 
 	pci_info->orom = orom;
 
diff --git a/drivers/scsi/isci/probe_roms.c b/drivers/scsi/isci/probe_roms.c
index 0d968d3..1697487 100644
--- a/drivers/scsi/isci/probe_roms.c
+++ b/drivers/scsi/isci/probe_roms.c
@@ -138,10 +138,7 @@
 	    scu_index > orom->hdr.num_elements || !oem_params)
 		return -EINVAL;
 
-	memcpy(oem_params,
-	       &orom->ctrl[scu_index],
-	       sizeof(struct scic_sds_oem_params));
-
+	oem_params->sds1 = orom->ctrl[scu_index];
 	return 0;
 }
 
diff --git a/drivers/scsi/isci/probe_roms.h b/drivers/scsi/isci/probe_roms.h
index c2162cf..1b44483 100644
--- a/drivers/scsi/isci/probe_roms.h
+++ b/drivers/scsi/isci/probe_roms.h
@@ -96,6 +96,10 @@
 #define ISCI_ROM_SIG		"ISCUOEMB"
 #define ISCI_ROM_SIG_SIZE	8
 
+#define ISCI_PREBOOT_SOURCE_INIT     (0x00)
+#define ISCI_PREBOOT_SOURCE_OROM     (0x80)
+#define ISCI_PREBOOT_SOURCE_EFI      (0x81)
+
 #define ISCI_EFI_VENDOR_GUID	\
 	EFI_GUID(0x193dfefa, 0xa445, 0x4302, 0x99, 0xd8, 0xef, 0x3a, 0xad, \
 			0x1a, 0x04, 0xc6)
@@ -112,8 +116,8 @@
  * being assigned is sufficient to declare manual PORT configuration.
  */
 enum SCIC_PORT_CONFIGURATION_MODE {
-	SCIC_PORT_MANUAL_CONFIGURATION_MODE = 0,
-	SCIC_PORT_AUTOMATIC_CONFIGURATION_MODE = 1
+	SCIC_PORT_AUTOMATIC_CONFIGURATION_MODE = 0,
+	SCIC_PORT_MANUAL_CONFIGURATION_MODE = 1
 };
 
 struct sci_bios_oem_param_block_hdr {
diff --git a/firmware/isci/isci_firmware.bin.ihex b/firmware/isci/isci_firmware.bin.ihex
index b1bb5cf..4f8767c 100644
--- a/firmware/isci/isci_firmware.bin.ihex
+++ b/firmware/isci/isci_firmware.bin.ihex
@@ -1,16 +1,16 @@
 :10000000495343554F454D42E70017100002000089
-:10001000000000000000000101000000000000FFDF
-:10002000FFCF5F000000F0000000000000000000B3
-:1000300000000000000000FFFFCF5F000000F100A3
-:10004000000000000000000000000000000000FFB1
-:10005000FFCF5F000000F200000000000000000081
-:1000600000000000000000FFFFCF5F000000F30071
-:10007000000000000000000000000000000000017F
-:1000800001000000000000FFFFCF5F000000F4004F
-:10009000000000000000000000000000000000FF61
-:1000A000FFCF5F000000F50000000000000000002E
-:1000B00000000000000000FFFFCF5F000000F6001E
-:1000C000000000000000000000000000000000FF31
-:1000D000FFCF5F000000F7000000000000000000FC
-:0700E0000000000000000019
+:10001000000000000000000001000000000000FFE0
+:10002000FFCF5F01000000037C0E00037C0E000385
+:100030007C0E00037C0E00FFFFCF5F010000000379
+:100040007C0E00037C0E00037C0E00037C0E00FF80
+:10005000FFCF5F01000000037C0E00037C0E000355
+:100060007C0E00037C0E00FFFFCF5F010000000349
+:100070007C0E00037C0E00037C0E00037C0E00004F
+:1000800001000000000000FFFFCF5F02000000033E
+:100090007C0E00037C0E00037C0E00037C0E00FF30
+:1000A000FFCF5F02000000037C0E00037C0E000304
+:1000B0007C0E00037C0E00FFFFCF5F0200000003F8
+:1000C0007C0E00037C0E00037C0E00037C0E00FF00
+:1000D000FFCF5F02000000037C0E00037C0E0003D4
+:0700E0007C0E00037C0E0002
 :00000001FF