提交 4711ba10 编写于 作者: D Dan Williams

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: NDave Jiang <dave.jiang@intel.com>
Signed-off-by: NDan Williams <dan.j.williams@intel.com>
上级 2e8320f7
...@@ -289,8 +289,6 @@ static inline void sci_base_controller_construct( ...@@ -289,8 +289,6 @@ static inline void sci_base_controller_construct(
u32 mde_count, u32 mde_count,
struct sci_base_memory_descriptor_list *next_mdl) struct sci_base_memory_descriptor_list *next_mdl)
{ {
scic_base->parent.private = NULL;
sci_base_state_machine_construct( sci_base_state_machine_construct(
&scic_base->state_machine, &scic_base->state_machine,
&scic_base->parent, &scic_base->parent,
......
...@@ -595,6 +595,7 @@ void scic_sds_controller_enable_port_task_scheduler( ...@@ -595,6 +595,7 @@ void scic_sds_controller_enable_port_task_scheduler(
*/ */
void scic_sds_controller_afe_initialization(struct scic_sds_controller *scic) 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 afe_status;
u32 phy_id; u32 phy_id;
...@@ -632,6 +633,8 @@ void scic_sds_controller_afe_initialization(struct scic_sds_controller *scic) ...@@ -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++) { 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()) { if (is_b0()) {
/* Configure transmitter SSC parameters */ /* Configure transmitter SSC parameters */
scu_afe_txreg_write(scic, phy_id, afe_tx_ssc_control, 0x00030000); 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) ...@@ -691,16 +694,16 @@ void scic_sds_controller_afe_initialization(struct scic_sds_controller *scic)
} }
udelay(AFE_REGISTER_WRITE_DELAY); 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); 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); 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); 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); udelay(AFE_REGISTER_WRITE_DELAY);
} }
...@@ -2027,6 +2030,7 @@ void scic_sds_controller_release_frame( ...@@ -2027,6 +2030,7 @@ void scic_sds_controller_release_frame(
*/ */
static void scic_sds_controller_set_default_config_parameters(struct scic_sds_controller *scic) 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; u16 index;
/* Default to APC mode. */ /* Default to APC mode. */
...@@ -2058,7 +2062,7 @@ static void scic_sds_controller_set_default_config_parameters(struct scic_sds_co ...@@ -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 * is worked around by having the upper 32-bits of SAS address
* with a value greater then the Vitesse company identifier. * with a value greater then the Vitesse company identifier.
* Hence, usage of 0x5FCFFFFF. */ * 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; scic->oem_parameters.sds1.phys[index].sas_address.high = 0x5FCFFFFF;
} }
...@@ -2604,14 +2608,11 @@ enum sci_status scic_oem_parameters_set( ...@@ -2604,14 +2608,11 @@ enum sci_status scic_oem_parameters_set(
struct scic_sds_controller *scic, struct scic_sds_controller *scic,
union scic_oem_parameters *scic_parms) union scic_oem_parameters *scic_parms)
{ {
if ( u32 state = scic->parent.state_machine.current_state_id;
(scic->parent.state_machine.current_state_id
== SCI_BASE_CONTROLLER_STATE_RESET) if (state == SCI_BASE_CONTROLLER_STATE_RESET ||
|| (scic->parent.state_machine.current_state_id state == SCI_BASE_CONTROLLER_STATE_INITIALIZING ||
== SCI_BASE_CONTROLLER_STATE_INITIALIZING) state == SCI_BASE_CONTROLLER_STATE_INITIALIZED) {
|| (scic->parent.state_machine.current_state_id
== SCI_BASE_CONTROLLER_STATE_INITIALIZED)
) {
u16 index; u16 index;
u8 combined_phy_mask = 0; u8 combined_phy_mask = 0;
...@@ -2651,7 +2652,8 @@ enum sci_status scic_oem_parameters_set( ...@@ -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) if (scic_parms->sds1.controller.max_concurrent_dev_spin_up > MAX_CONCURRENT_DEVICE_SPIN_UP_COUNT)
return SCI_FAILURE_INVALID_PARAMETER_VALUE; 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; return SCI_SUCCESS;
} }
......
...@@ -44,7 +44,7 @@ void set_binary_values(struct isci_orom *isci_orom) ...@@ -44,7 +44,7 @@ void set_binary_values(struct isci_orom *isci_orom)
/* setting OROM signature */ /* setting OROM signature */
strncpy(isci_orom->hdr.signature, sig, strlen(sig)); 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.total_block_length = sizeof(struct isci_orom);
isci_orom->hdr.hdr_length = sizeof(struct sci_bios_oem_param_block_hdr); isci_orom->hdr.hdr_length = sizeof(struct sci_bios_oem_param_block_hdr);
isci_orom->hdr.num_elements = num_elements; isci_orom->hdr.num_elements = num_elements;
...@@ -65,6 +65,15 @@ void set_binary_values(struct isci_orom *isci_orom) ...@@ -65,6 +65,15 @@ void set_binary_values(struct isci_orom *isci_orom)
(__u32)(sas_addr[ctrl_idx][phy_idx] >> 32); (__u32)(sas_addr[ctrl_idx][phy_idx] >> 32);
isci_orom->ctrl[ctrl_idx].phys[phy_idx].sas_address.low = isci_orom->ctrl[ctrl_idx].phys[phy_idx].sas_address.low =
(__u32)(sas_addr[ctrl_idx][phy_idx]); (__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;
} }
} }
} }
......
...@@ -25,14 +25,37 @@ static const int num_elements = 2; ...@@ -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 * 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). * values, use the value assigned to UNINIT_PARAM (255).
*/ */
/* discovery mode type (port auto config mode by default ) */ /* 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 #ifdef MPC
static const int mode_type = SCIC_PORT_MANUAL_CONFIGURATION_MODE; static const int mode_type = SCIC_PORT_MANUAL_CONFIGURATION_MODE;
static const __u8 phy_mask[2][4] = { {1, 2, 4, 8}, static const __u8 phy_mask[2][4] = { {1, 2, 4, 8},
{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) */ #else /* APC (default) */
static const int mode_type = SCIC_PORT_AUTOMATIC_CONFIGURATION_MODE; static const int mode_type = SCIC_PORT_AUTOMATIC_CONFIGURATION_MODE;
static const __u8 phy_mask[2][4]; 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 #endif
/* Maximum number of concurrent device spin up */ /* Maximum number of concurrent device spin up */
...@@ -47,22 +70,8 @@ static const unsigned int afe_tx_amp_control1 = 0x000e7c03; ...@@ -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_control2 = 0x000e7c03;
static const unsigned int afe_tx_amp_control3 = 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 blob_name[] = "isci_firmware.bin";
static const char sig[] = "ISCUOEMB"; static const char sig[] = "ISCUOEMB";
static const unsigned char version = 1; static const unsigned char version = 0x10;
#endif #endif
...@@ -418,7 +418,7 @@ int isci_host_init(struct isci_host *isci_host) ...@@ -418,7 +418,7 @@ int isci_host_init(struct isci_host *isci_host)
int err = 0, i; int err = 0, i;
enum sci_status status; enum sci_status status;
struct scic_sds_controller *controller; struct scic_sds_controller *controller;
union scic_oem_parameters scic_oem_params; union scic_oem_parameters oem;
union scic_user_parameters scic_user_params; union scic_user_parameters scic_user_params;
struct isci_pci_info *pci_info = to_pci_info(isci_host->pdev); 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) ...@@ -435,6 +435,7 @@ int isci_host_init(struct isci_host *isci_host)
} }
isci_host->core_controller = controller; 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->state_lock);
spin_lock_init(&isci_host->scic_lock); spin_lock_init(&isci_host->scic_lock);
spin_lock_init(&isci_host->queue_lock); spin_lock_init(&isci_host->queue_lock);
...@@ -457,12 +458,6 @@ int isci_host_init(struct isci_host *isci_host) ...@@ -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.dev = &isci_host->pdev->dev;
isci_host->sas_ha.lldd_ha = isci_host; 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 * grab initial values stored in the controller object for OEM and USER
* parameters * parameters
...@@ -477,11 +472,11 @@ int isci_host_init(struct isci_host *isci_host) ...@@ -477,11 +472,11 @@ int isci_host_init(struct isci_host *isci_host)
return -ENODEV; return -ENODEV;
} }
scic_oem_parameters_get(controller, &scic_oem_params); scic_oem_parameters_get(controller, &oem);
/* grab any OEM parameters specified in orom */ /* grab any OEM parameters specified in orom */
if (pci_info->orom) { if (pci_info->orom) {
status = isci_parse_oem_parameters(&scic_oem_params, status = isci_parse_oem_parameters(&oem,
pci_info->orom, pci_info->orom,
isci_host->id); isci_host->id);
if (status != SCI_SUCCESS) { if (status != SCI_SUCCESS) {
...@@ -489,16 +484,15 @@ int isci_host_init(struct isci_host *isci_host) ...@@ -489,16 +484,15 @@ int isci_host_init(struct isci_host *isci_host)
"parsing firmware oem parameters failed\n"); "parsing firmware oem parameters failed\n");
return -EINVAL; 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) { if (status != SCI_SUCCESS) {
dev_warn(&isci_host->pdev->dev, dev_warn(&isci_host->pdev->dev,
"%s: scic_oem_parameters_set failed\n", "%s: scic_oem_parameters_set failed\n",
__func__); __func__);
return -ENODEV; return -ENODEV;
} }
}
tasklet_init(&isci_host->completion_tasklet, tasklet_init(&isci_host->completion_tasklet,
isci_host_completion_routine, (unsigned long)isci_host); isci_host_completion_routine, (unsigned long)isci_host);
......
...@@ -466,6 +466,7 @@ static int __devinit isci_pci_probe(struct pci_dev *pdev, const struct pci_devic ...@@ -466,6 +466,7 @@ static int __devinit isci_pci_probe(struct pci_dev *pdev, const struct pci_devic
struct isci_host *isci_host; struct isci_host *isci_host;
const struct firmware *fw = NULL; const struct firmware *fw = NULL;
struct isci_orom *orom; struct isci_orom *orom;
char *source = "(platform)";
check_si_rev(pdev); check_si_rev(pdev);
...@@ -480,6 +481,7 @@ static int __devinit isci_pci_probe(struct pci_dev *pdev, const struct pci_devic ...@@ -480,6 +481,7 @@ static int __devinit isci_pci_probe(struct pci_dev *pdev, const struct pci_devic
orom = isci_request_oprom(pdev); orom = isci_request_oprom(pdev);
if (!orom) { if (!orom) {
source = "(firmware)";
orom = isci_request_firmware(pdev, fw); orom = isci_request_firmware(pdev, fw);
if (!orom) { if (!orom) {
/* TODO convert this to WARN_TAINT_ONCE once the /* 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 ...@@ -496,9 +498,9 @@ static int __devinit isci_pci_probe(struct pci_dev *pdev, const struct pci_devic
if (orom) if (orom)
dev_info(&pdev->dev, 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 & 0xf0) >> 4,
(orom->hdr.version & 0xf)); (orom->hdr.version & 0xf), source);
pci_info->orom = orom; pci_info->orom = orom;
......
...@@ -138,10 +138,7 @@ enum sci_status isci_parse_oem_parameters(union scic_oem_parameters *oem_params, ...@@ -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) scu_index > orom->hdr.num_elements || !oem_params)
return -EINVAL; return -EINVAL;
memcpy(oem_params, oem_params->sds1 = orom->ctrl[scu_index];
&orom->ctrl[scu_index],
sizeof(struct scic_sds_oem_params));
return 0; return 0;
} }
......
...@@ -96,6 +96,10 @@ struct isci_oem_hdr { ...@@ -96,6 +96,10 @@ struct isci_oem_hdr {
#define ISCI_ROM_SIG "ISCUOEMB" #define ISCI_ROM_SIG "ISCUOEMB"
#define ISCI_ROM_SIG_SIZE 8 #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 \ #define ISCI_EFI_VENDOR_GUID \
EFI_GUID(0x193dfefa, 0xa445, 0x4302, 0x99, 0xd8, 0xef, 0x3a, 0xad, \ EFI_GUID(0x193dfefa, 0xa445, 0x4302, 0x99, 0xd8, 0xef, 0x3a, 0xad, \
0x1a, 0x04, 0xc6) 0x1a, 0x04, 0xc6)
...@@ -112,8 +116,8 @@ struct isci_oem_hdr { ...@@ -112,8 +116,8 @@ struct isci_oem_hdr {
* being assigned is sufficient to declare manual PORT configuration. * being assigned is sufficient to declare manual PORT configuration.
*/ */
enum SCIC_PORT_CONFIGURATION_MODE { enum SCIC_PORT_CONFIGURATION_MODE {
SCIC_PORT_MANUAL_CONFIGURATION_MODE = 0, SCIC_PORT_AUTOMATIC_CONFIGURATION_MODE = 0,
SCIC_PORT_AUTOMATIC_CONFIGURATION_MODE = 1 SCIC_PORT_MANUAL_CONFIGURATION_MODE = 1
}; };
struct sci_bios_oem_param_block_hdr { struct sci_bios_oem_param_block_hdr {
......
:10000000495343554F454D42E70017100002000089 :10000000495343554F454D42E70017100002000089
:10001000000000000000000101000000000000FFDF :10001000000000000000000001000000000000FFE0
:10002000FFCF5F000000F0000000000000000000B3 :10002000FFCF5F01000000037C0E00037C0E000385
:1000300000000000000000FFFFCF5F000000F100A3 :100030007C0E00037C0E00FFFFCF5F010000000379
:10004000000000000000000000000000000000FFB1 :100040007C0E00037C0E00037C0E00037C0E00FF80
:10005000FFCF5F000000F200000000000000000081 :10005000FFCF5F01000000037C0E00037C0E000355
:1000600000000000000000FFFFCF5F000000F30071 :100060007C0E00037C0E00FFFFCF5F010000000349
:10007000000000000000000000000000000000017F :100070007C0E00037C0E00037C0E00037C0E00004F
:1000800001000000000000FFFFCF5F000000F4004F :1000800001000000000000FFFFCF5F02000000033E
:10009000000000000000000000000000000000FF61 :100090007C0E00037C0E00037C0E00037C0E00FF30
:1000A000FFCF5F000000F50000000000000000002E :1000A000FFCF5F02000000037C0E00037C0E000304
:1000B00000000000000000FFFFCF5F000000F6001E :1000B0007C0E00037C0E00FFFFCF5F0200000003F8
:1000C000000000000000000000000000000000FF31 :1000C0007C0E00037C0E00037C0E00037C0E00FF00
:1000D000FFCF5F000000F7000000000000000000FC :1000D000FFCF5F02000000037C0E00037C0E0003D4
:0700E0000000000000000019 :0700E0007C0E00037C0E0002
:00000001FF :00000001FF
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册