diff options
author | Dan Williams <dan.j.williams@intel.com> | 2011-04-20 15:57:08 -0400 |
---|---|---|
committer | Dan Williams <dan.j.williams@intel.com> | 2011-07-03 07:00:37 -0400 |
commit | 2d70de5a0f03072289015917b059c155936c894d (patch) | |
tree | 1ccb3f5d30ac13b05c42d2fcd43c289987f590e0 /drivers | |
parent | f22be5d8386d9da67bfe02693806fbaff7b078da (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.h | 2 | ||||
-rw-r--r-- | drivers/scsi/isci/core/scic_sds_controller.c | 75 | ||||
-rw-r--r-- | drivers/scsi/isci/init.c | 10 |
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 | ||
282 | int 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 | ||
2458 | enum sci_status scic_oem_parameters_set( | 2458 | int 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 == | 2492 | enum 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); |