From 4711ba10b13891edf228944a9d0a21dfe7fe90f0 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Fri, 11 Mar 2011 10:43:57 -0800 Subject: 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 Signed-off-by: Dan Williams --- drivers/scsi/isci/core/sci_base_controller.h | 2 -- drivers/scsi/isci/core/scic_sds_controller.c | 30 +++++++++++---------- drivers/scsi/isci/firmware/create_fw.c | 11 +++++++- drivers/scsi/isci/firmware/create_fw.h | 39 +++++++++++++++++----------- drivers/scsi/isci/host.c | 30 +++++++++------------ drivers/scsi/isci/init.c | 6 +++-- drivers/scsi/isci/probe_roms.c | 5 +--- drivers/scsi/isci/probe_roms.h | 8 ++++-- firmware/isci/isci_firmware.bin.ihex | 28 ++++++++++---------- 9 files changed, 87 insertions(+), 72 deletions(-) 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 @@ 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, 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_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; } 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 @@ 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; } } } 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 @@ 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 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 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,15 +484,14 @@ 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); - 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 @@ static int __devinit isci_pci_probe(struct pci_dev *pdev, const struct pci_devic 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 @@ static int __devinit isci_pci_probe(struct pci_dev *pdev, const struct pci_devic 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 @@ static int __devinit isci_pci_probe(struct pci_dev *pdev, const struct pci_devic 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 @@ enum sci_status isci_parse_oem_parameters(union scic_oem_parameters *oem_params, 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 @@ struct isci_oem_hdr { #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 @@ struct isci_oem_hdr { * 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 -- cgit v1.1