Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4711ba10 authored by Dan Williams's avatar Dan Williams
Browse files

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: default avatarDave Jiang <dave.jiang@intel.com>
Signed-off-by: default avatarDan Williams <dan.j.williams@intel.com>
parent 2e8320f7
Loading
Loading
Loading
Loading
+0 −2
Original line number Diff line number Diff line
@@ -289,8 +289,6 @@ static inline void sci_base_controller_construct(
	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,
+16 −14
Original line number Diff line number Diff line
@@ -595,6 +595,7 @@ void scic_sds_controller_enable_port_task_scheduler(
 */
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 @@ void scic_sds_controller_afe_initialization(struct scic_sds_controller *scic)
	}

	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 @@ void scic_sds_controller_afe_initialization(struct scic_sds_controller *scic)
		}
		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 @@ void scic_sds_controller_release_frame(
 */
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 @@ static void scic_sds_controller_set_default_config_parameters(struct scic_sds_co
		 * 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 @@ enum sci_status scic_oem_parameters_set(
	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 @@ enum sci_status scic_oem_parameters_set(
		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;
	}

+10 −1
Original line number Diff line number Diff line
@@ -44,7 +44,7 @@ void set_binary_values(struct isci_orom *isci_orom)

	/* 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 @@ void set_binary_values(struct isci_orom *isci_orom)
				(__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;
		}
	}
}
+24 −15
Original line number Diff line number Diff line
@@ -25,14 +25,37 @@ static const int num_elements = 2;
 * 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_control1 = 0x000e7c03;
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
+12 −18
Original line number Diff line number Diff line
@@ -418,7 +418,7 @@ int isci_host_init(struct isci_host *isci_host)
	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 @@ int isci_host_init(struct isci_host *isci_host)
	}

	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 @@ int isci_host_init(struct isci_host *isci_host)
	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 @@ int isci_host_init(struct isci_host *isci_host)
		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,16 +484,15 @@ int isci_host_init(struct isci_host *isci_host)
				 "parsing firmware oem parameters failed\n");
			return -EINVAL;
		}
	} else {
		status = scic_oem_parameters_set(isci_host->core_controller,
						 &scic_oem_params);
	}

	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,
		     isci_host_completion_routine, (unsigned long)isci_host);
Loading