aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorDan Williams <dan.j.williams@intel.com>2011-04-20 15:57:08 -0400
committerDan Williams <dan.j.williams@intel.com>2011-07-03 07:00:37 -0400
commit2d70de5a0f03072289015917b059c155936c894d (patch)
tree1ccb3f5d30ac13b05c42d2fcd43c289987f590e0 /drivers
parentf22be5d8386d9da67bfe02693806fbaff7b078da (diff)
isci: validate oem parameters early, and fallback
If the platform specifies invalid parameters warn the user and fallback to internal defaults rather than fail the driver load altogether. Reported-by: Yinghai Lu <yinghai.lu@oracle.com> Signed-off-by: Dan Williams <dan.j.williams@intel.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/scsi/isci/core/scic_config_parameters.h2
-rw-r--r--drivers/scsi/isci/core/scic_sds_controller.c75
-rw-r--r--drivers/scsi/isci/init.c10
3 files changed, 49 insertions, 38 deletions
diff --git a/drivers/scsi/isci/core/scic_config_parameters.h b/drivers/scsi/isci/core/scic_config_parameters.h
index cb6abcc7e7cd..716abfcd0c23 100644
--- a/drivers/scsi/isci/core/scic_config_parameters.h
+++ b/drivers/scsi/isci/core/scic_config_parameters.h
@@ -279,6 +279,8 @@ enum sci_status scic_oem_parameters_set(
279 struct scic_sds_controller *controller, 279 struct scic_sds_controller *controller,
280 union scic_oem_parameters *oem_parameters); 280 union scic_oem_parameters *oem_parameters);
281 281
282int scic_oem_parameters_validate(struct scic_sds_oem_params *oem);
283
282/** 284/**
283 * scic_oem_parameters_get() - This method allows the user to retreive the OEM 285 * scic_oem_parameters_get() - This method allows the user to retreive the OEM
284 * parameters utilized by the controller. 286 * parameters utilized by the controller.
diff --git a/drivers/scsi/isci/core/scic_sds_controller.c b/drivers/scsi/isci/core/scic_sds_controller.c
index 8194618b76c6..9bb78a2e6ff7 100644
--- a/drivers/scsi/isci/core/scic_sds_controller.c
+++ b/drivers/scsi/isci/core/scic_sds_controller.c
@@ -2455,52 +2455,51 @@ enum sci_status scic_user_parameters_set(
2455 return SCI_FAILURE_INVALID_STATE; 2455 return SCI_FAILURE_INVALID_STATE;
2456} 2456}
2457 2457
2458enum sci_status scic_oem_parameters_set( 2458int scic_oem_parameters_validate(struct scic_sds_oem_params *oem)
2459 struct scic_sds_controller *scic,
2460 union scic_oem_parameters *scic_parms)
2461{ 2459{
2462 u32 state = scic->state_machine.current_state_id; 2460 int i;
2463 2461
2464 if (state == SCI_BASE_CONTROLLER_STATE_RESET || 2462 for (i = 0; i < SCI_MAX_PORTS; i++)
2465 state == SCI_BASE_CONTROLLER_STATE_INITIALIZING || 2463 if (oem->ports[i].phy_mask > SCIC_SDS_PARM_PHY_MASK_MAX)
2466 state == SCI_BASE_CONTROLLER_STATE_INITIALIZED) { 2464 return -EINVAL;
2467 u16 index; 2465
2468 u8 combined_phy_mask = 0; 2466 for (i = 0; i < SCI_MAX_PHYS; i++)
2467 if (oem->phys[i].sas_address.high == 0 &&
2468 oem->phys[i].sas_address.low == 0)
2469 return -EINVAL;
2470
2471 if (oem->controller.mode_type == SCIC_PORT_AUTOMATIC_CONFIGURATION_MODE) {
2472 for (i = 0; i < SCI_MAX_PHYS; i++)
2473 if (oem->ports[i].phy_mask != 0)
2474 return -EINVAL;
2475 } else if (oem->controller.mode_type == SCIC_PORT_MANUAL_CONFIGURATION_MODE) {
2476 u8 phy_mask = 0;
2477
2478 for (i = 0; i < SCI_MAX_PHYS; i++)
2479 phy_mask |= oem->ports[i].phy_mask;
2480
2481 if (phy_mask == 0)
2482 return -EINVAL;
2483 } else
2484 return -EINVAL;
2469 2485
2470 /* 2486 if (oem->controller.max_concurrent_dev_spin_up > MAX_CONCURRENT_DEVICE_SPIN_UP_COUNT)
2471 * Validate the oem parameters. If they are not legal, then 2487 return -EINVAL;
2472 * return a failure. */
2473 for (index = 0; index < SCI_MAX_PORTS; index++) {
2474 if (scic_parms->sds1.ports[index].phy_mask > SCIC_SDS_PARM_PHY_MASK_MAX)
2475 return SCI_FAILURE_INVALID_PARAMETER_VALUE;
2476 }
2477 2488
2478 for (index = 0; index < SCI_MAX_PHYS; index++) { 2489 return 0;
2479 if ((scic_parms->sds1.phys[index].sas_address.high == 0) && 2490}
2480 (scic_parms->sds1.phys[index].sas_address.low == 0))
2481 return SCI_FAILURE_INVALID_PARAMETER_VALUE;
2482 }
2483 2491
2484 if (scic_parms->sds1.controller.mode_type == 2492enum sci_status scic_oem_parameters_set(struct scic_sds_controller *scic,
2485 SCIC_PORT_AUTOMATIC_CONFIGURATION_MODE) { 2493 union scic_oem_parameters *scic_parms)
2486 for (index = 0; index < SCI_MAX_PHYS; index++) { 2494{
2487 if (scic_parms->sds1.ports[index].phy_mask != 0) 2495 u32 state = scic->state_machine.current_state_id;
2488 return SCI_FAILURE_INVALID_PARAMETER_VALUE;
2489 }
2490 } else if (scic_parms->sds1.controller.mode_type ==
2491 SCIC_PORT_MANUAL_CONFIGURATION_MODE) {
2492 for (index = 0; index < SCI_MAX_PHYS; index++)
2493 combined_phy_mask |= scic_parms->sds1.ports[index].phy_mask;
2494 2496
2495 if (combined_phy_mask == 0) 2497 if (state == SCI_BASE_CONTROLLER_STATE_RESET ||
2496 return SCI_FAILURE_INVALID_PARAMETER_VALUE; 2498 state == SCI_BASE_CONTROLLER_STATE_INITIALIZING ||
2497 } else 2499 state == SCI_BASE_CONTROLLER_STATE_INITIALIZED) {
2498 return SCI_FAILURE_INVALID_PARAMETER_VALUE;
2499 2500
2500 if (scic_parms->sds1.controller.max_concurrent_dev_spin_up > 2501 if (scic_oem_parameters_validate(&scic_parms->sds1))
2501 MAX_CONCURRENT_DEVICE_SPIN_UP_COUNT)
2502 return SCI_FAILURE_INVALID_PARAMETER_VALUE; 2502 return SCI_FAILURE_INVALID_PARAMETER_VALUE;
2503
2504 scic->oem_parameters.sds1 = scic_parms->sds1; 2503 scic->oem_parameters.sds1 = scic_parms->sds1;
2505 2504
2506 return SCI_SUCCESS; 2505 return SCI_SUCCESS;
diff --git a/drivers/scsi/isci/init.c b/drivers/scsi/isci/init.c
index 5da9a6925cd7..015ce94453bb 100644
--- a/drivers/scsi/isci/init.c
+++ b/drivers/scsi/isci/init.c
@@ -489,6 +489,16 @@ static int __devinit isci_pci_probe(struct pci_dev *pdev, const struct pci_devic
489 else 489 else
490 orom = isci_request_oprom(pdev); 490 orom = isci_request_oprom(pdev);
491 491
492 for (i = 0; orom && i < ARRAY_SIZE(orom->ctrl); i++) {
493 if (scic_oem_parameters_validate(&orom->ctrl[i])) {
494 dev_warn(&pdev->dev,
495 "[%d]: invalid oem parameters detected, falling back to firmware\n", i);
496 devm_kfree(&pdev->dev, orom);
497 orom = NULL;
498 break;
499 }
500 }
501
492 if (!orom) { 502 if (!orom) {
493 source = "(firmware)"; 503 source = "(firmware)";
494 orom = isci_request_firmware(pdev, fw); 504 orom = isci_request_firmware(pdev, fw);