aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/isci/init.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/isci/init.c')
-rw-r--r--drivers/scsi/isci/init.c199
1 files changed, 182 insertions, 17 deletions
diff --git a/drivers/scsi/isci/init.c b/drivers/scsi/isci/init.c
index 5137db5a5d85..eda43851cc98 100644
--- a/drivers/scsi/isci/init.c
+++ b/drivers/scsi/isci/init.c
@@ -397,38 +397,203 @@ static int isci_setup_interrupts(struct pci_dev *pdev)
397 return err; 397 return err;
398} 398}
399 399
400static void isci_user_parameters_get(struct sci_user_parameters *u)
401{
402 int i;
403
404 for (i = 0; i < SCI_MAX_PHYS; i++) {
405 struct sci_phy_user_params *u_phy = &u->phys[i];
406
407 u_phy->max_speed_generation = phy_gen;
408
409 /* we are not exporting these for now */
410 u_phy->align_insertion_frequency = 0x7f;
411 u_phy->in_connection_align_insertion_frequency = 0xff;
412 u_phy->notify_enable_spin_up_insertion_frequency = 0x33;
413 }
414
415 u->stp_inactivity_timeout = stp_inactive_to;
416 u->ssp_inactivity_timeout = ssp_inactive_to;
417 u->stp_max_occupancy_timeout = stp_max_occ_to;
418 u->ssp_max_occupancy_timeout = ssp_max_occ_to;
419 u->no_outbound_task_timeout = no_outbound_task_to;
420 u->max_concurr_spinup = max_concurr_spinup;
421}
422
423static enum sci_status sci_user_parameters_set(struct isci_host *ihost,
424 struct sci_user_parameters *sci_parms)
425{
426 u16 index;
427
428 /*
429 * Validate the user parameters. If they are not legal, then
430 * return a failure.
431 */
432 for (index = 0; index < SCI_MAX_PHYS; index++) {
433 struct sci_phy_user_params *u;
434
435 u = &sci_parms->phys[index];
436
437 if (!((u->max_speed_generation <= SCIC_SDS_PARM_MAX_SPEED) &&
438 (u->max_speed_generation > SCIC_SDS_PARM_NO_SPEED)))
439 return SCI_FAILURE_INVALID_PARAMETER_VALUE;
440
441 if (u->in_connection_align_insertion_frequency < 3)
442 return SCI_FAILURE_INVALID_PARAMETER_VALUE;
443
444 if ((u->in_connection_align_insertion_frequency < 3) ||
445 (u->align_insertion_frequency == 0) ||
446 (u->notify_enable_spin_up_insertion_frequency == 0))
447 return SCI_FAILURE_INVALID_PARAMETER_VALUE;
448 }
449
450 if ((sci_parms->stp_inactivity_timeout == 0) ||
451 (sci_parms->ssp_inactivity_timeout == 0) ||
452 (sci_parms->stp_max_occupancy_timeout == 0) ||
453 (sci_parms->ssp_max_occupancy_timeout == 0) ||
454 (sci_parms->no_outbound_task_timeout == 0))
455 return SCI_FAILURE_INVALID_PARAMETER_VALUE;
456
457 memcpy(&ihost->user_parameters, sci_parms, sizeof(*sci_parms));
458
459 return SCI_SUCCESS;
460}
461
462static void sci_oem_defaults(struct isci_host *ihost)
463{
464 /* these defaults are overridden by the platform / firmware */
465 struct sci_user_parameters *user = &ihost->user_parameters;
466 struct sci_oem_params *oem = &ihost->oem_parameters;
467 int i;
468
469 /* Default to APC mode. */
470 oem->controller.mode_type = SCIC_PORT_AUTOMATIC_CONFIGURATION_MODE;
471
472 /* Default to APC mode. */
473 oem->controller.max_concurr_spin_up = 1;
474
475 /* Default to no SSC operation. */
476 oem->controller.do_enable_ssc = false;
477
478 /* Default to short cables on all phys. */
479 oem->controller.cable_selection_mask = 0;
480
481 /* Initialize all of the port parameter information to narrow ports. */
482 for (i = 0; i < SCI_MAX_PORTS; i++)
483 oem->ports[i].phy_mask = 0;
484
485 /* Initialize all of the phy parameter information. */
486 for (i = 0; i < SCI_MAX_PHYS; i++) {
487 /* Default to 3G (i.e. Gen 2). */
488 user->phys[i].max_speed_generation = SCIC_SDS_PARM_GEN2_SPEED;
489
490 /* the frequencies cannot be 0 */
491 user->phys[i].align_insertion_frequency = 0x7f;
492 user->phys[i].in_connection_align_insertion_frequency = 0xff;
493 user->phys[i].notify_enable_spin_up_insertion_frequency = 0x33;
494
495 /* Previous Vitesse based expanders had a arbitration issue that
496 * is worked around by having the upper 32-bits of SAS address
497 * with a value greater then the Vitesse company identifier.
498 * Hence, usage of 0x5FCFFFFF.
499 */
500 oem->phys[i].sas_address.low = 0x1 + ihost->id;
501 oem->phys[i].sas_address.high = 0x5FCFFFFF;
502 }
503
504 user->stp_inactivity_timeout = 5;
505 user->ssp_inactivity_timeout = 5;
506 user->stp_max_occupancy_timeout = 5;
507 user->ssp_max_occupancy_timeout = 20;
508 user->no_outbound_task_timeout = 2;
509}
510
400static struct isci_host *isci_host_alloc(struct pci_dev *pdev, int id) 511static struct isci_host *isci_host_alloc(struct pci_dev *pdev, int id)
401{ 512{
402 struct isci_host *isci_host; 513 struct isci_orom *orom = to_pci_info(pdev)->orom;
514 struct sci_user_parameters sci_user_params;
515 u8 oem_version = ISCI_ROM_VER_1_0;
516 struct isci_host *ihost;
403 struct Scsi_Host *shost; 517 struct Scsi_Host *shost;
404 int err; 518 int err, i;
405 519
406 isci_host = devm_kzalloc(&pdev->dev, sizeof(*isci_host), GFP_KERNEL); 520 ihost = devm_kzalloc(&pdev->dev, sizeof(*ihost), GFP_KERNEL);
407 if (!isci_host) 521 if (!ihost)
522 return NULL;
523
524 ihost->pdev = pdev;
525 ihost->id = id;
526 spin_lock_init(&ihost->scic_lock);
527 init_waitqueue_head(&ihost->eventq);
528 ihost->sas_ha.dev = &ihost->pdev->dev;
529 ihost->sas_ha.lldd_ha = ihost;
530 tasklet_init(&ihost->completion_tasklet,
531 isci_host_completion_routine, (unsigned long)ihost);
532
533 /* validate module parameters */
534 /* TODO: kill struct sci_user_parameters and reference directly */
535 sci_oem_defaults(ihost);
536 isci_user_parameters_get(&sci_user_params);
537 if (sci_user_parameters_set(ihost, &sci_user_params)) {
538 dev_warn(&pdev->dev,
539 "%s: sci_user_parameters_set failed\n", __func__);
540 return NULL;
541 }
542
543 /* sanity check platform (or 'firmware') oem parameters */
544 if (orom) {
545 if (id < 0 || id >= SCI_MAX_CONTROLLERS || id > orom->hdr.num_elements) {
546 dev_warn(&pdev->dev, "parsing firmware oem parameters failed\n");
547 return NULL;
548 }
549 ihost->oem_parameters = orom->ctrl[id];
550 oem_version = orom->hdr.version;
551 }
552
553 /* validate oem parameters (platform, firmware, or built-in defaults) */
554 if (sci_oem_parameters_validate(&ihost->oem_parameters, oem_version)) {
555 dev_warn(&pdev->dev, "oem parameter validation failed\n");
408 return NULL; 556 return NULL;
557 }
558
559 INIT_LIST_HEAD(&ihost->requests_to_complete);
560 INIT_LIST_HEAD(&ihost->requests_to_errorback);
561 for (i = 0; i < SCI_MAX_PORTS; i++) {
562 struct isci_port *iport = &ihost->ports[i];
563
564 INIT_LIST_HEAD(&iport->remote_dev_list);
565 iport->isci_host = ihost;
566 }
409 567
410 isci_host->pdev = pdev; 568 for (i = 0; i < SCI_MAX_PHYS; i++)
411 isci_host->id = id; 569 isci_phy_init(&ihost->phys[i], ihost, i);
570
571 for (i = 0; i < SCI_MAX_REMOTE_DEVICES; i++) {
572 struct isci_remote_device *idev = &ihost->devices[i];
573
574 INIT_LIST_HEAD(&idev->reqs_in_process);
575 INIT_LIST_HEAD(&idev->node);
576 }
412 577
413 shost = scsi_host_alloc(&isci_sht, sizeof(void *)); 578 shost = scsi_host_alloc(&isci_sht, sizeof(void *));
414 if (!shost) 579 if (!shost)
415 return NULL; 580 return NULL;
416 isci_host->shost = shost; 581 ihost->shost = shost;
417 582
418 dev_info(&pdev->dev, "%sSCU controller %d: phy 3-0 cables: " 583 dev_info(&pdev->dev, "%sSCU controller %d: phy 3-0 cables: "
419 "{%s, %s, %s, %s}\n", 584 "{%s, %s, %s, %s}\n",
420 (is_cable_select_overridden() ? "* " : ""), isci_host->id, 585 (is_cable_select_overridden() ? "* " : ""), ihost->id,
421 lookup_cable_names(decode_cable_selection(isci_host, 3)), 586 lookup_cable_names(decode_cable_selection(ihost, 3)),
422 lookup_cable_names(decode_cable_selection(isci_host, 2)), 587 lookup_cable_names(decode_cable_selection(ihost, 2)),
423 lookup_cable_names(decode_cable_selection(isci_host, 1)), 588 lookup_cable_names(decode_cable_selection(ihost, 1)),
424 lookup_cable_names(decode_cable_selection(isci_host, 0))); 589 lookup_cable_names(decode_cable_selection(ihost, 0)));
425 590
426 err = isci_host_init(isci_host); 591 err = isci_host_init(ihost);
427 if (err) 592 if (err)
428 goto err_shost; 593 goto err_shost;
429 594
430 SHOST_TO_SAS_HA(shost) = &isci_host->sas_ha; 595 SHOST_TO_SAS_HA(shost) = &ihost->sas_ha;
431 isci_host->sas_ha.core.shost = shost; 596 ihost->sas_ha.core.shost = shost;
432 shost->transportt = isci_transport_template; 597 shost->transportt = isci_transport_template;
433 598
434 shost->max_id = ~0; 599 shost->max_id = ~0;
@@ -439,11 +604,11 @@ static struct isci_host *isci_host_alloc(struct pci_dev *pdev, int id)
439 if (err) 604 if (err)
440 goto err_shost; 605 goto err_shost;
441 606
442 err = isci_register_sas_ha(isci_host); 607 err = isci_register_sas_ha(ihost);
443 if (err) 608 if (err)
444 goto err_shost_remove; 609 goto err_shost_remove;
445 610
446 return isci_host; 611 return ihost;
447 612
448 err_shost_remove: 613 err_shost_remove:
449 scsi_remove_host(shost); 614 scsi_remove_host(shost);