diff options
Diffstat (limited to 'drivers/scsi/pmcraid.c')
| -rw-r--r-- | drivers/scsi/pmcraid.c | 893 |
1 files changed, 667 insertions, 226 deletions
diff --git a/drivers/scsi/pmcraid.c b/drivers/scsi/pmcraid.c index c44e4ab4e938..ecc45c8b4e6b 100644 --- a/drivers/scsi/pmcraid.c +++ b/drivers/scsi/pmcraid.c | |||
| @@ -113,6 +113,7 @@ static struct pmcraid_chip_details pmcraid_chip_cfg[] = { | |||
| 113 | .global_intr_mask = 0x00034, | 113 | .global_intr_mask = 0x00034, |
| 114 | .ioa_host_intr = 0x0009C, | 114 | .ioa_host_intr = 0x0009C, |
| 115 | .ioa_host_intr_clr = 0x000A0, | 115 | .ioa_host_intr_clr = 0x000A0, |
| 116 | .ioa_host_msix_intr = 0x7FC40, | ||
| 116 | .ioa_host_mask = 0x7FC28, | 117 | .ioa_host_mask = 0x7FC28, |
| 117 | .ioa_host_mask_clr = 0x7FC28, | 118 | .ioa_host_mask_clr = 0x7FC28, |
| 118 | .host_ioa_intr = 0x00020, | 119 | .host_ioa_intr = 0x00020, |
| @@ -154,8 +155,12 @@ static int pmcraid_slave_alloc(struct scsi_device *scsi_dev) | |||
| 154 | u8 target, bus, lun; | 155 | u8 target, bus, lun; |
| 155 | unsigned long lock_flags; | 156 | unsigned long lock_flags; |
| 156 | int rc = -ENXIO; | 157 | int rc = -ENXIO; |
| 158 | u16 fw_version; | ||
| 159 | |||
| 157 | pinstance = shost_priv(scsi_dev->host); | 160 | pinstance = shost_priv(scsi_dev->host); |
| 158 | 161 | ||
| 162 | fw_version = be16_to_cpu(pinstance->inq_data->fw_version); | ||
| 163 | |||
| 159 | /* Driver exposes VSET and GSCSI resources only; all other device types | 164 | /* Driver exposes VSET and GSCSI resources only; all other device types |
| 160 | * are not exposed. Resource list is synchronized using resource lock | 165 | * are not exposed. Resource list is synchronized using resource lock |
| 161 | * so any traversal or modifications to the list should be done inside | 166 | * so any traversal or modifications to the list should be done inside |
| @@ -166,7 +171,11 @@ static int pmcraid_slave_alloc(struct scsi_device *scsi_dev) | |||
| 166 | 171 | ||
| 167 | /* do not expose VSETs with order-ids > MAX_VSET_TARGETS */ | 172 | /* do not expose VSETs with order-ids > MAX_VSET_TARGETS */ |
| 168 | if (RES_IS_VSET(temp->cfg_entry)) { | 173 | if (RES_IS_VSET(temp->cfg_entry)) { |
| 169 | target = temp->cfg_entry.unique_flags1; | 174 | if (fw_version <= PMCRAID_FW_VERSION_1) |
| 175 | target = temp->cfg_entry.unique_flags1; | ||
| 176 | else | ||
| 177 | target = temp->cfg_entry.array_id & 0xFF; | ||
| 178 | |||
| 170 | if (target > PMCRAID_MAX_VSET_TARGETS) | 179 | if (target > PMCRAID_MAX_VSET_TARGETS) |
| 171 | continue; | 180 | continue; |
| 172 | bus = PMCRAID_VSET_BUS_ID; | 181 | bus = PMCRAID_VSET_BUS_ID; |
| @@ -283,7 +292,7 @@ static void pmcraid_slave_destroy(struct scsi_device *scsi_dev) | |||
| 283 | * @reason: calling context | 292 | * @reason: calling context |
| 284 | * | 293 | * |
| 285 | * Return value | 294 | * Return value |
| 286 | * actual depth set | 295 | * actual depth set |
| 287 | */ | 296 | */ |
| 288 | static int pmcraid_change_queue_depth(struct scsi_device *scsi_dev, int depth, | 297 | static int pmcraid_change_queue_depth(struct scsi_device *scsi_dev, int depth, |
| 289 | int reason) | 298 | int reason) |
| @@ -305,7 +314,7 @@ static int pmcraid_change_queue_depth(struct scsi_device *scsi_dev, int depth, | |||
| 305 | * @tag: type of tags to use | 314 | * @tag: type of tags to use |
| 306 | * | 315 | * |
| 307 | * Return value: | 316 | * Return value: |
| 308 | * actual queue type set | 317 | * actual queue type set |
| 309 | */ | 318 | */ |
| 310 | static int pmcraid_change_queue_type(struct scsi_device *scsi_dev, int tag) | 319 | static int pmcraid_change_queue_type(struct scsi_device *scsi_dev, int tag) |
| 311 | { | 320 | { |
| @@ -357,6 +366,7 @@ void pmcraid_init_cmdblk(struct pmcraid_cmd *cmd, int index) | |||
| 357 | * processed by IOA | 366 | * processed by IOA |
| 358 | */ | 367 | */ |
| 359 | memset(&cmd->ioa_cb->ioarcb.cdb, 0, PMCRAID_MAX_CDB_LEN); | 368 | memset(&cmd->ioa_cb->ioarcb.cdb, 0, PMCRAID_MAX_CDB_LEN); |
| 369 | ioarcb->hrrq_id = 0; | ||
| 360 | ioarcb->request_flags0 = 0; | 370 | ioarcb->request_flags0 = 0; |
| 361 | ioarcb->request_flags1 = 0; | 371 | ioarcb->request_flags1 = 0; |
| 362 | ioarcb->cmd_timeout = 0; | 372 | ioarcb->cmd_timeout = 0; |
| @@ -368,13 +378,15 @@ void pmcraid_init_cmdblk(struct pmcraid_cmd *cmd, int index) | |||
| 368 | ioarcb->add_cmd_param_offset = 0; | 378 | ioarcb->add_cmd_param_offset = 0; |
| 369 | cmd->ioa_cb->ioasa.ioasc = 0; | 379 | cmd->ioa_cb->ioasa.ioasc = 0; |
| 370 | cmd->ioa_cb->ioasa.residual_data_length = 0; | 380 | cmd->ioa_cb->ioasa.residual_data_length = 0; |
| 371 | cmd->u.time_left = 0; | 381 | cmd->time_left = 0; |
| 372 | } | 382 | } |
| 373 | 383 | ||
| 374 | cmd->cmd_done = NULL; | 384 | cmd->cmd_done = NULL; |
| 375 | cmd->scsi_cmd = NULL; | 385 | cmd->scsi_cmd = NULL; |
| 376 | cmd->release = 0; | 386 | cmd->release = 0; |
| 377 | cmd->completion_req = 0; | 387 | cmd->completion_req = 0; |
| 388 | cmd->sense_buffer = 0; | ||
| 389 | cmd->sense_buffer_dma = 0; | ||
| 378 | cmd->dma_handle = 0; | 390 | cmd->dma_handle = 0; |
| 379 | init_timer(&cmd->timer); | 391 | init_timer(&cmd->timer); |
| 380 | } | 392 | } |
| @@ -449,7 +461,9 @@ void pmcraid_return_cmd(struct pmcraid_cmd *cmd) | |||
| 449 | */ | 461 | */ |
| 450 | static u32 pmcraid_read_interrupts(struct pmcraid_instance *pinstance) | 462 | static u32 pmcraid_read_interrupts(struct pmcraid_instance *pinstance) |
| 451 | { | 463 | { |
| 452 | return ioread32(pinstance->int_regs.ioa_host_interrupt_reg); | 464 | return (pinstance->interrupt_mode) ? |
| 465 | ioread32(pinstance->int_regs.ioa_host_msix_interrupt_reg) : | ||
| 466 | ioread32(pinstance->int_regs.ioa_host_interrupt_reg); | ||
| 453 | } | 467 | } |
| 454 | 468 | ||
| 455 | /** | 469 | /** |
| @@ -469,10 +483,15 @@ static void pmcraid_disable_interrupts( | |||
| 469 | u32 gmask = ioread32(pinstance->int_regs.global_interrupt_mask_reg); | 483 | u32 gmask = ioread32(pinstance->int_regs.global_interrupt_mask_reg); |
| 470 | u32 nmask = gmask | GLOBAL_INTERRUPT_MASK; | 484 | u32 nmask = gmask | GLOBAL_INTERRUPT_MASK; |
| 471 | 485 | ||
| 472 | iowrite32(nmask, pinstance->int_regs.global_interrupt_mask_reg); | ||
| 473 | iowrite32(intrs, pinstance->int_regs.ioa_host_interrupt_clr_reg); | 486 | iowrite32(intrs, pinstance->int_regs.ioa_host_interrupt_clr_reg); |
| 474 | iowrite32(intrs, pinstance->int_regs.ioa_host_interrupt_mask_reg); | 487 | iowrite32(nmask, pinstance->int_regs.global_interrupt_mask_reg); |
| 475 | ioread32(pinstance->int_regs.ioa_host_interrupt_mask_reg); | 488 | ioread32(pinstance->int_regs.global_interrupt_mask_reg); |
| 489 | |||
| 490 | if (!pinstance->interrupt_mode) { | ||
| 491 | iowrite32(intrs, | ||
| 492 | pinstance->int_regs.ioa_host_interrupt_mask_reg); | ||
| 493 | ioread32(pinstance->int_regs.ioa_host_interrupt_mask_reg); | ||
| 494 | } | ||
| 476 | } | 495 | } |
| 477 | 496 | ||
| 478 | /** | 497 | /** |
| @@ -493,8 +512,12 @@ static void pmcraid_enable_interrupts( | |||
| 493 | u32 nmask = gmask & (~GLOBAL_INTERRUPT_MASK); | 512 | u32 nmask = gmask & (~GLOBAL_INTERRUPT_MASK); |
| 494 | 513 | ||
| 495 | iowrite32(nmask, pinstance->int_regs.global_interrupt_mask_reg); | 514 | iowrite32(nmask, pinstance->int_regs.global_interrupt_mask_reg); |
| 496 | iowrite32(~intrs, pinstance->int_regs.ioa_host_interrupt_mask_reg); | 515 | |
| 497 | ioread32(pinstance->int_regs.ioa_host_interrupt_mask_reg); | 516 | if (!pinstance->interrupt_mode) { |
| 517 | iowrite32(~intrs, | ||
| 518 | pinstance->int_regs.ioa_host_interrupt_mask_reg); | ||
| 519 | ioread32(pinstance->int_regs.ioa_host_interrupt_mask_reg); | ||
| 520 | } | ||
| 498 | 521 | ||
| 499 | pmcraid_info("enabled interrupts global mask = %x intr_mask = %x\n", | 522 | pmcraid_info("enabled interrupts global mask = %x intr_mask = %x\n", |
| 500 | ioread32(pinstance->int_regs.global_interrupt_mask_reg), | 523 | ioread32(pinstance->int_regs.global_interrupt_mask_reg), |
| @@ -502,6 +525,39 @@ static void pmcraid_enable_interrupts( | |||
| 502 | } | 525 | } |
| 503 | 526 | ||
| 504 | /** | 527 | /** |
| 528 | * pmcraid_clr_trans_op - clear trans to op interrupt | ||
| 529 | * | ||
| 530 | * @pinstance: pointer to per adapter instance structure | ||
| 531 | * | ||
| 532 | * Return Value | ||
| 533 | * None | ||
| 534 | */ | ||
| 535 | static void pmcraid_clr_trans_op( | ||
| 536 | struct pmcraid_instance *pinstance | ||
| 537 | ) | ||
| 538 | { | ||
| 539 | unsigned long lock_flags; | ||
| 540 | |||
| 541 | if (!pinstance->interrupt_mode) { | ||
| 542 | iowrite32(INTRS_TRANSITION_TO_OPERATIONAL, | ||
| 543 | pinstance->int_regs.ioa_host_interrupt_mask_reg); | ||
| 544 | ioread32(pinstance->int_regs.ioa_host_interrupt_mask_reg); | ||
| 545 | iowrite32(INTRS_TRANSITION_TO_OPERATIONAL, | ||
| 546 | pinstance->int_regs.ioa_host_interrupt_clr_reg); | ||
| 547 | ioread32(pinstance->int_regs.ioa_host_interrupt_clr_reg); | ||
| 548 | } | ||
| 549 | |||
| 550 | if (pinstance->reset_cmd != NULL) { | ||
| 551 | del_timer(&pinstance->reset_cmd->timer); | ||
| 552 | spin_lock_irqsave( | ||
| 553 | pinstance->host->host_lock, lock_flags); | ||
| 554 | pinstance->reset_cmd->cmd_done(pinstance->reset_cmd); | ||
| 555 | spin_unlock_irqrestore( | ||
| 556 | pinstance->host->host_lock, lock_flags); | ||
| 557 | } | ||
| 558 | } | ||
| 559 | |||
| 560 | /** | ||
| 505 | * pmcraid_reset_type - Determine the required reset type | 561 | * pmcraid_reset_type - Determine the required reset type |
| 506 | * @pinstance: pointer to adapter instance structure | 562 | * @pinstance: pointer to adapter instance structure |
| 507 | * | 563 | * |
| @@ -536,7 +592,7 @@ static void pmcraid_reset_type(struct pmcraid_instance *pinstance) | |||
| 536 | * pmcraid_bist_done - completion function for PCI BIST | 592 | * pmcraid_bist_done - completion function for PCI BIST |
| 537 | * @cmd: pointer to reset command | 593 | * @cmd: pointer to reset command |
| 538 | * Return Value | 594 | * Return Value |
| 539 | * none | 595 | * none |
| 540 | */ | 596 | */ |
| 541 | 597 | ||
| 542 | static void pmcraid_ioa_reset(struct pmcraid_cmd *); | 598 | static void pmcraid_ioa_reset(struct pmcraid_cmd *); |
| @@ -552,16 +608,16 @@ static void pmcraid_bist_done(struct pmcraid_cmd *cmd) | |||
| 552 | 608 | ||
| 553 | /* If PCI config space can't be accessed wait for another two secs */ | 609 | /* If PCI config space can't be accessed wait for another two secs */ |
| 554 | if ((rc != PCIBIOS_SUCCESSFUL || (!(pci_reg & PCI_COMMAND_MEMORY))) && | 610 | if ((rc != PCIBIOS_SUCCESSFUL || (!(pci_reg & PCI_COMMAND_MEMORY))) && |
| 555 | cmd->u.time_left > 0) { | 611 | cmd->time_left > 0) { |
| 556 | pmcraid_info("BIST not complete, waiting another 2 secs\n"); | 612 | pmcraid_info("BIST not complete, waiting another 2 secs\n"); |
| 557 | cmd->timer.expires = jiffies + cmd->u.time_left; | 613 | cmd->timer.expires = jiffies + cmd->time_left; |
| 558 | cmd->u.time_left = 0; | 614 | cmd->time_left = 0; |
| 559 | cmd->timer.data = (unsigned long)cmd; | 615 | cmd->timer.data = (unsigned long)cmd; |
| 560 | cmd->timer.function = | 616 | cmd->timer.function = |
| 561 | (void (*)(unsigned long))pmcraid_bist_done; | 617 | (void (*)(unsigned long))pmcraid_bist_done; |
| 562 | add_timer(&cmd->timer); | 618 | add_timer(&cmd->timer); |
| 563 | } else { | 619 | } else { |
| 564 | cmd->u.time_left = 0; | 620 | cmd->time_left = 0; |
| 565 | pmcraid_info("BIST is complete, proceeding with reset\n"); | 621 | pmcraid_info("BIST is complete, proceeding with reset\n"); |
| 566 | spin_lock_irqsave(pinstance->host->host_lock, lock_flags); | 622 | spin_lock_irqsave(pinstance->host->host_lock, lock_flags); |
| 567 | pmcraid_ioa_reset(cmd); | 623 | pmcraid_ioa_reset(cmd); |
| @@ -585,10 +641,10 @@ static void pmcraid_start_bist(struct pmcraid_cmd *cmd) | |||
| 585 | pinstance->int_regs.host_ioa_interrupt_reg); | 641 | pinstance->int_regs.host_ioa_interrupt_reg); |
| 586 | doorbells = ioread32(pinstance->int_regs.host_ioa_interrupt_reg); | 642 | doorbells = ioread32(pinstance->int_regs.host_ioa_interrupt_reg); |
| 587 | intrs = ioread32(pinstance->int_regs.ioa_host_interrupt_reg); | 643 | intrs = ioread32(pinstance->int_regs.ioa_host_interrupt_reg); |
| 588 | pmcraid_info("doorbells after start bist: %x intrs: %x \n", | 644 | pmcraid_info("doorbells after start bist: %x intrs: %x\n", |
| 589 | doorbells, intrs); | 645 | doorbells, intrs); |
| 590 | 646 | ||
| 591 | cmd->u.time_left = msecs_to_jiffies(PMCRAID_BIST_TIMEOUT); | 647 | cmd->time_left = msecs_to_jiffies(PMCRAID_BIST_TIMEOUT); |
| 592 | cmd->timer.data = (unsigned long)cmd; | 648 | cmd->timer.data = (unsigned long)cmd; |
| 593 | cmd->timer.expires = jiffies + msecs_to_jiffies(PMCRAID_BIST_TIMEOUT); | 649 | cmd->timer.expires = jiffies + msecs_to_jiffies(PMCRAID_BIST_TIMEOUT); |
| 594 | cmd->timer.function = (void (*)(unsigned long))pmcraid_bist_done; | 650 | cmd->timer.function = (void (*)(unsigned long))pmcraid_bist_done; |
| @@ -612,7 +668,7 @@ static void pmcraid_reset_alert_done(struct pmcraid_cmd *cmd) | |||
| 612 | * some more time to wait, restart the timer | 668 | * some more time to wait, restart the timer |
| 613 | */ | 669 | */ |
| 614 | if (((status & INTRS_CRITICAL_OP_IN_PROGRESS) == 0) || | 670 | if (((status & INTRS_CRITICAL_OP_IN_PROGRESS) == 0) || |
| 615 | cmd->u.time_left <= 0) { | 671 | cmd->time_left <= 0) { |
| 616 | pmcraid_info("critical op is reset proceeding with reset\n"); | 672 | pmcraid_info("critical op is reset proceeding with reset\n"); |
| 617 | spin_lock_irqsave(pinstance->host->host_lock, lock_flags); | 673 | spin_lock_irqsave(pinstance->host->host_lock, lock_flags); |
| 618 | pmcraid_ioa_reset(cmd); | 674 | pmcraid_ioa_reset(cmd); |
| @@ -620,7 +676,7 @@ static void pmcraid_reset_alert_done(struct pmcraid_cmd *cmd) | |||
| 620 | } else { | 676 | } else { |
| 621 | pmcraid_info("critical op is not yet reset waiting again\n"); | 677 | pmcraid_info("critical op is not yet reset waiting again\n"); |
| 622 | /* restart timer if some more time is available to wait */ | 678 | /* restart timer if some more time is available to wait */ |
| 623 | cmd->u.time_left -= PMCRAID_CHECK_FOR_RESET_TIMEOUT; | 679 | cmd->time_left -= PMCRAID_CHECK_FOR_RESET_TIMEOUT; |
| 624 | cmd->timer.data = (unsigned long)cmd; | 680 | cmd->timer.data = (unsigned long)cmd; |
| 625 | cmd->timer.expires = jiffies + PMCRAID_CHECK_FOR_RESET_TIMEOUT; | 681 | cmd->timer.expires = jiffies + PMCRAID_CHECK_FOR_RESET_TIMEOUT; |
| 626 | cmd->timer.function = | 682 | cmd->timer.function = |
| @@ -638,6 +694,7 @@ static void pmcraid_reset_alert_done(struct pmcraid_cmd *cmd) | |||
| 638 | * successfully written to IOA. Returns non-zero in case pci_config_space | 694 | * successfully written to IOA. Returns non-zero in case pci_config_space |
| 639 | * is not accessible | 695 | * is not accessible |
| 640 | */ | 696 | */ |
| 697 | static void pmcraid_notify_ioastate(struct pmcraid_instance *, u32); | ||
| 641 | static void pmcraid_reset_alert(struct pmcraid_cmd *cmd) | 698 | static void pmcraid_reset_alert(struct pmcraid_cmd *cmd) |
| 642 | { | 699 | { |
| 643 | struct pmcraid_instance *pinstance = cmd->drv_inst; | 700 | struct pmcraid_instance *pinstance = cmd->drv_inst; |
| @@ -658,7 +715,7 @@ static void pmcraid_reset_alert(struct pmcraid_cmd *cmd) | |||
| 658 | * OPERATION bit is reset. A timer is started to wait for this | 715 | * OPERATION bit is reset. A timer is started to wait for this |
| 659 | * bit to be reset. | 716 | * bit to be reset. |
| 660 | */ | 717 | */ |
| 661 | cmd->u.time_left = PMCRAID_RESET_TIMEOUT; | 718 | cmd->time_left = PMCRAID_RESET_TIMEOUT; |
| 662 | cmd->timer.data = (unsigned long)cmd; | 719 | cmd->timer.data = (unsigned long)cmd; |
| 663 | cmd->timer.expires = jiffies + PMCRAID_CHECK_FOR_RESET_TIMEOUT; | 720 | cmd->timer.expires = jiffies + PMCRAID_CHECK_FOR_RESET_TIMEOUT; |
| 664 | cmd->timer.function = | 721 | cmd->timer.function = |
| @@ -693,7 +750,8 @@ static void pmcraid_timeout_handler(struct pmcraid_cmd *cmd) | |||
| 693 | unsigned long lock_flags; | 750 | unsigned long lock_flags; |
| 694 | 751 | ||
| 695 | dev_info(&pinstance->pdev->dev, | 752 | dev_info(&pinstance->pdev->dev, |
| 696 | "Adapter being reset due to command timeout.\n"); | 753 | "Adapter being reset due to cmd(CDB[0] = %x) timeout\n", |
| 754 | cmd->ioa_cb->ioarcb.cdb[0]); | ||
| 697 | 755 | ||
| 698 | /* Command timeouts result in hard reset sequence. The command that got | 756 | /* Command timeouts result in hard reset sequence. The command that got |
| 699 | * timed out may be the one used as part of reset sequence. In this | 757 | * timed out may be the one used as part of reset sequence. In this |
| @@ -736,9 +794,14 @@ static void pmcraid_timeout_handler(struct pmcraid_cmd *cmd) | |||
| 736 | */ | 794 | */ |
| 737 | if (cmd == pinstance->reset_cmd) | 795 | if (cmd == pinstance->reset_cmd) |
| 738 | cmd->cmd_done = pmcraid_ioa_reset; | 796 | cmd->cmd_done = pmcraid_ioa_reset; |
| 739 | |||
| 740 | } | 797 | } |
| 741 | 798 | ||
| 799 | /* Notify apps of important IOA bringup/bringdown sequences */ | ||
| 800 | if (pinstance->scn.ioa_state != PMC_DEVICE_EVENT_RESET_START && | ||
| 801 | pinstance->scn.ioa_state != PMC_DEVICE_EVENT_SHUTDOWN_START) | ||
| 802 | pmcraid_notify_ioastate(pinstance, | ||
| 803 | PMC_DEVICE_EVENT_RESET_START); | ||
| 804 | |||
| 742 | pinstance->ioa_state = IOA_STATE_IN_RESET_ALERT; | 805 | pinstance->ioa_state = IOA_STATE_IN_RESET_ALERT; |
| 743 | scsi_block_requests(pinstance->host); | 806 | scsi_block_requests(pinstance->host); |
| 744 | pmcraid_reset_alert(cmd); | 807 | pmcraid_reset_alert(cmd); |
| @@ -866,7 +929,7 @@ static void _pmcraid_fire_command(struct pmcraid_cmd *cmd) | |||
| 866 | /* Add this command block to pending cmd pool. We do this prior to | 929 | /* Add this command block to pending cmd pool. We do this prior to |
| 867 | * writting IOARCB to ioarrin because IOA might complete the command | 930 | * writting IOARCB to ioarrin because IOA might complete the command |
| 868 | * by the time we are about to add it to the list. Response handler | 931 | * by the time we are about to add it to the list. Response handler |
| 869 | * (isr/tasklet) looks for cmb block in the pending pending list. | 932 | * (isr/tasklet) looks for cmd block in the pending pending list. |
| 870 | */ | 933 | */ |
| 871 | spin_lock_irqsave(&pinstance->pending_pool_lock, lock_flags); | 934 | spin_lock_irqsave(&pinstance->pending_pool_lock, lock_flags); |
| 872 | list_add_tail(&cmd->free_list, &pinstance->pending_cmd_pool); | 935 | list_add_tail(&cmd->free_list, &pinstance->pending_cmd_pool); |
| @@ -916,6 +979,23 @@ static void pmcraid_send_cmd( | |||
| 916 | } | 979 | } |
| 917 | 980 | ||
| 918 | /** | 981 | /** |
| 982 | * pmcraid_ioa_shutdown_done - completion function for IOA shutdown command | ||
| 983 | * @cmd: pointer to the command block used for sending IOA shutdown command | ||
| 984 | * | ||
| 985 | * Return value | ||
| 986 | * None | ||
| 987 | */ | ||
| 988 | static void pmcraid_ioa_shutdown_done(struct pmcraid_cmd *cmd) | ||
| 989 | { | ||
| 990 | struct pmcraid_instance *pinstance = cmd->drv_inst; | ||
| 991 | unsigned long lock_flags; | ||
| 992 | |||
| 993 | spin_lock_irqsave(pinstance->host->host_lock, lock_flags); | ||
| 994 | pmcraid_ioa_reset(cmd); | ||
| 995 | spin_unlock_irqrestore(pinstance->host->host_lock, lock_flags); | ||
| 996 | } | ||
| 997 | |||
| 998 | /** | ||
| 919 | * pmcraid_ioa_shutdown - sends SHUTDOWN command to ioa | 999 | * pmcraid_ioa_shutdown - sends SHUTDOWN command to ioa |
| 920 | * | 1000 | * |
| 921 | * @cmd: pointer to the command block used as part of reset sequence | 1001 | * @cmd: pointer to the command block used as part of reset sequence |
| @@ -943,30 +1023,112 @@ static void pmcraid_ioa_shutdown(struct pmcraid_cmd *cmd) | |||
| 943 | pmcraid_info("firing normal shutdown command (%d) to IOA\n", | 1023 | pmcraid_info("firing normal shutdown command (%d) to IOA\n", |
| 944 | le32_to_cpu(cmd->ioa_cb->ioarcb.response_handle)); | 1024 | le32_to_cpu(cmd->ioa_cb->ioarcb.response_handle)); |
| 945 | 1025 | ||
| 946 | pmcraid_send_cmd(cmd, pmcraid_ioa_reset, | 1026 | pmcraid_notify_ioastate(cmd->drv_inst, PMC_DEVICE_EVENT_SHUTDOWN_START); |
| 1027 | |||
| 1028 | pmcraid_send_cmd(cmd, pmcraid_ioa_shutdown_done, | ||
| 947 | PMCRAID_SHUTDOWN_TIMEOUT, | 1029 | PMCRAID_SHUTDOWN_TIMEOUT, |
| 948 | pmcraid_timeout_handler); | 1030 | pmcraid_timeout_handler); |
| 949 | } | 1031 | } |
| 950 | 1032 | ||
| 951 | /** | 1033 | /** |
| 952 | * pmcraid_identify_hrrq - registers host rrq buffers with IOA | 1034 | * pmcraid_get_fwversion_done - completion function for get_fwversion |
| 953 | * @cmd: pointer to command block to be used for identify hrrq | 1035 | * |
| 1036 | * @cmd: pointer to command block used to send INQUIRY command | ||
| 954 | * | 1037 | * |
| 955 | * Return Value | 1038 | * Return Value |
| 956 | * 0 in case of success, otherwise non-zero failure code | 1039 | * none |
| 957 | */ | 1040 | */ |
| 958 | |||
| 959 | static void pmcraid_querycfg(struct pmcraid_cmd *); | 1041 | static void pmcraid_querycfg(struct pmcraid_cmd *); |
| 960 | 1042 | ||
| 1043 | static void pmcraid_get_fwversion_done(struct pmcraid_cmd *cmd) | ||
| 1044 | { | ||
| 1045 | struct pmcraid_instance *pinstance = cmd->drv_inst; | ||
| 1046 | u32 ioasc = le32_to_cpu(cmd->ioa_cb->ioasa.ioasc); | ||
| 1047 | unsigned long lock_flags; | ||
| 1048 | |||
| 1049 | /* configuration table entry size depends on firmware version. If fw | ||
| 1050 | * version is not known, it is not possible to interpret IOA config | ||
| 1051 | * table | ||
| 1052 | */ | ||
| 1053 | if (ioasc) { | ||
| 1054 | pmcraid_err("IOA Inquiry failed with %x\n", ioasc); | ||
| 1055 | spin_lock_irqsave(pinstance->host->host_lock, lock_flags); | ||
| 1056 | pinstance->ioa_state = IOA_STATE_IN_RESET_ALERT; | ||
| 1057 | pmcraid_reset_alert(cmd); | ||
| 1058 | spin_unlock_irqrestore(pinstance->host->host_lock, lock_flags); | ||
| 1059 | } else { | ||
| 1060 | pmcraid_querycfg(cmd); | ||
| 1061 | } | ||
| 1062 | } | ||
| 1063 | |||
| 1064 | /** | ||
| 1065 | * pmcraid_get_fwversion - reads firmware version information | ||
| 1066 | * | ||
| 1067 | * @cmd: pointer to command block used to send INQUIRY command | ||
| 1068 | * | ||
| 1069 | * Return Value | ||
| 1070 | * none | ||
| 1071 | */ | ||
| 1072 | static void pmcraid_get_fwversion(struct pmcraid_cmd *cmd) | ||
| 1073 | { | ||
| 1074 | struct pmcraid_ioarcb *ioarcb = &cmd->ioa_cb->ioarcb; | ||
| 1075 | struct pmcraid_ioadl_desc *ioadl = ioarcb->add_data.u.ioadl; | ||
| 1076 | struct pmcraid_instance *pinstance = cmd->drv_inst; | ||
| 1077 | u16 data_size = sizeof(struct pmcraid_inquiry_data); | ||
| 1078 | |||
| 1079 | pmcraid_reinit_cmdblk(cmd); | ||
| 1080 | ioarcb->request_type = REQ_TYPE_SCSI; | ||
| 1081 | ioarcb->resource_handle = cpu_to_le32(PMCRAID_IOA_RES_HANDLE); | ||
| 1082 | ioarcb->cdb[0] = INQUIRY; | ||
| 1083 | ioarcb->cdb[1] = 1; | ||
| 1084 | ioarcb->cdb[2] = 0xD0; | ||
| 1085 | ioarcb->cdb[3] = (data_size >> 8) & 0xFF; | ||
| 1086 | ioarcb->cdb[4] = data_size & 0xFF; | ||
| 1087 | |||
| 1088 | /* Since entire inquiry data it can be part of IOARCB itself | ||
| 1089 | */ | ||
| 1090 | ioarcb->ioadl_bus_addr = cpu_to_le64((cmd->ioa_cb_bus_addr) + | ||
| 1091 | offsetof(struct pmcraid_ioarcb, | ||
| 1092 | add_data.u.ioadl[0])); | ||
| 1093 | ioarcb->ioadl_length = cpu_to_le32(sizeof(struct pmcraid_ioadl_desc)); | ||
| 1094 | ioarcb->ioarcb_bus_addr &= ~(0x1FULL); | ||
| 1095 | |||
| 1096 | ioarcb->request_flags0 |= NO_LINK_DESCS; | ||
| 1097 | ioarcb->data_transfer_length = cpu_to_le32(data_size); | ||
| 1098 | ioadl = &(ioarcb->add_data.u.ioadl[0]); | ||
| 1099 | ioadl->flags = IOADL_FLAGS_LAST_DESC; | ||
| 1100 | ioadl->address = cpu_to_le64(pinstance->inq_data_baddr); | ||
| 1101 | ioadl->data_len = cpu_to_le32(data_size); | ||
| 1102 | |||
| 1103 | pmcraid_send_cmd(cmd, pmcraid_get_fwversion_done, | ||
| 1104 | PMCRAID_INTERNAL_TIMEOUT, pmcraid_timeout_handler); | ||
| 1105 | } | ||
| 1106 | |||
| 1107 | /** | ||
| 1108 | * pmcraid_identify_hrrq - registers host rrq buffers with IOA | ||
| 1109 | * @cmd: pointer to command block to be used for identify hrrq | ||
| 1110 | * | ||
| 1111 | * Return Value | ||
| 1112 | * none | ||
| 1113 | */ | ||
| 961 | static void pmcraid_identify_hrrq(struct pmcraid_cmd *cmd) | 1114 | static void pmcraid_identify_hrrq(struct pmcraid_cmd *cmd) |
| 962 | { | 1115 | { |
| 963 | struct pmcraid_instance *pinstance = cmd->drv_inst; | 1116 | struct pmcraid_instance *pinstance = cmd->drv_inst; |
| 964 | struct pmcraid_ioarcb *ioarcb = &cmd->ioa_cb->ioarcb; | 1117 | struct pmcraid_ioarcb *ioarcb = &cmd->ioa_cb->ioarcb; |
| 965 | int index = 0; | 1118 | int index = cmd->hrrq_index; |
| 966 | __be64 hrrq_addr = cpu_to_be64(pinstance->hrrq_start_bus_addr[index]); | 1119 | __be64 hrrq_addr = cpu_to_be64(pinstance->hrrq_start_bus_addr[index]); |
| 967 | u32 hrrq_size = cpu_to_be32(sizeof(u32) * PMCRAID_MAX_CMD); | 1120 | u32 hrrq_size = cpu_to_be32(sizeof(u32) * PMCRAID_MAX_CMD); |
| 1121 | void (*done_function)(struct pmcraid_cmd *); | ||
| 968 | 1122 | ||
| 969 | pmcraid_reinit_cmdblk(cmd); | 1123 | pmcraid_reinit_cmdblk(cmd); |
| 1124 | cmd->hrrq_index = index + 1; | ||
| 1125 | |||
| 1126 | if (cmd->hrrq_index < pinstance->num_hrrq) { | ||
| 1127 | done_function = pmcraid_identify_hrrq; | ||
| 1128 | } else { | ||
| 1129 | cmd->hrrq_index = 0; | ||
| 1130 | done_function = pmcraid_get_fwversion; | ||
| 1131 | } | ||
| 970 | 1132 | ||
| 971 | /* Initialize ioarcb */ | 1133 | /* Initialize ioarcb */ |
| 972 | ioarcb->request_type = REQ_TYPE_IOACMD; | 1134 | ioarcb->request_type = REQ_TYPE_IOACMD; |
| @@ -980,8 +1142,8 @@ static void pmcraid_identify_hrrq(struct pmcraid_cmd *cmd) | |||
| 980 | /* IOA expects 64-bit pci address to be written in B.E format | 1142 | /* IOA expects 64-bit pci address to be written in B.E format |
| 981 | * (i.e cdb[2]=MSByte..cdb[9]=LSB. | 1143 | * (i.e cdb[2]=MSByte..cdb[9]=LSB. |
| 982 | */ | 1144 | */ |
| 983 | pmcraid_info("HRRQ_IDENTIFY with hrrq:ioarcb => %llx:%llx\n", | 1145 | pmcraid_info("HRRQ_IDENTIFY with hrrq:ioarcb:index => %llx:%llx:%x\n", |
| 984 | hrrq_addr, ioarcb->ioarcb_bus_addr); | 1146 | hrrq_addr, ioarcb->ioarcb_bus_addr, index); |
| 985 | 1147 | ||
| 986 | memcpy(&(ioarcb->cdb[2]), &hrrq_addr, sizeof(hrrq_addr)); | 1148 | memcpy(&(ioarcb->cdb[2]), &hrrq_addr, sizeof(hrrq_addr)); |
| 987 | memcpy(&(ioarcb->cdb[10]), &hrrq_size, sizeof(hrrq_size)); | 1149 | memcpy(&(ioarcb->cdb[10]), &hrrq_size, sizeof(hrrq_size)); |
| @@ -990,7 +1152,7 @@ static void pmcraid_identify_hrrq(struct pmcraid_cmd *cmd) | |||
| 990 | * Note that this gets called even during reset from SCSI mid-layer | 1152 | * Note that this gets called even during reset from SCSI mid-layer |
| 991 | * or tasklet | 1153 | * or tasklet |
| 992 | */ | 1154 | */ |
| 993 | pmcraid_send_cmd(cmd, pmcraid_querycfg, | 1155 | pmcraid_send_cmd(cmd, done_function, |
| 994 | PMCRAID_INTERNAL_TIMEOUT, | 1156 | PMCRAID_INTERNAL_TIMEOUT, |
| 995 | pmcraid_timeout_handler); | 1157 | pmcraid_timeout_handler); |
| 996 | } | 1158 | } |
| @@ -1047,7 +1209,7 @@ static struct pmcraid_cmd *pmcraid_init_hcam | |||
| 1047 | } | 1209 | } |
| 1048 | 1210 | ||
| 1049 | if (type == PMCRAID_HCAM_CODE_CONFIG_CHANGE) { | 1211 | if (type == PMCRAID_HCAM_CODE_CONFIG_CHANGE) { |
| 1050 | rcb_size = sizeof(struct pmcraid_hcam_ccn); | 1212 | rcb_size = sizeof(struct pmcraid_hcam_ccn_ext); |
| 1051 | cmd_done = pmcraid_process_ccn; | 1213 | cmd_done = pmcraid_process_ccn; |
| 1052 | dma = pinstance->ccn.baddr + PMCRAID_AEN_HDR_SIZE; | 1214 | dma = pinstance->ccn.baddr + PMCRAID_AEN_HDR_SIZE; |
| 1053 | hcam = &pinstance->ccn; | 1215 | hcam = &pinstance->ccn; |
| @@ -1094,7 +1256,7 @@ static struct pmcraid_cmd *pmcraid_init_hcam | |||
| 1094 | * This function will send a Host Controlled Async command to IOA. | 1256 | * This function will send a Host Controlled Async command to IOA. |
| 1095 | * | 1257 | * |
| 1096 | * Return value: | 1258 | * Return value: |
| 1097 | * none | 1259 | * none |
| 1098 | */ | 1260 | */ |
| 1099 | static void pmcraid_send_hcam(struct pmcraid_instance *pinstance, u8 type) | 1261 | static void pmcraid_send_hcam(struct pmcraid_instance *pinstance, u8 type) |
| 1100 | { | 1262 | { |
| @@ -1202,18 +1364,25 @@ static void pmcraid_cancel_ldn(struct pmcraid_cmd *cmd) | |||
| 1202 | /** | 1364 | /** |
| 1203 | * pmcraid_expose_resource - check if the resource can be exposed to OS | 1365 | * pmcraid_expose_resource - check if the resource can be exposed to OS |
| 1204 | * | 1366 | * |
| 1367 | * @fw_version: firmware version code | ||
| 1205 | * @cfgte: pointer to configuration table entry of the resource | 1368 | * @cfgte: pointer to configuration table entry of the resource |
| 1206 | * | 1369 | * |
| 1207 | * Return value: | 1370 | * Return value: |
| 1208 | * true if resource can be added to midlayer, false(0) otherwise | 1371 | * true if resource can be added to midlayer, false(0) otherwise |
| 1209 | */ | 1372 | */ |
| 1210 | static int pmcraid_expose_resource(struct pmcraid_config_table_entry *cfgte) | 1373 | static int pmcraid_expose_resource(u16 fw_version, |
| 1374 | struct pmcraid_config_table_entry *cfgte) | ||
| 1211 | { | 1375 | { |
| 1212 | int retval = 0; | 1376 | int retval = 0; |
| 1213 | 1377 | ||
| 1214 | if (cfgte->resource_type == RES_TYPE_VSET) | 1378 | if (cfgte->resource_type == RES_TYPE_VSET) { |
| 1215 | retval = ((cfgte->unique_flags1 & 0x80) == 0); | 1379 | if (fw_version <= PMCRAID_FW_VERSION_1) |
| 1216 | else if (cfgte->resource_type == RES_TYPE_GSCSI) | 1380 | retval = ((cfgte->unique_flags1 & 0x80) == 0); |
| 1381 | else | ||
| 1382 | retval = ((cfgte->unique_flags0 & 0x80) == 0 && | ||
| 1383 | (cfgte->unique_flags1 & 0x80) == 0); | ||
| 1384 | |||
| 1385 | } else if (cfgte->resource_type == RES_TYPE_GSCSI) | ||
| 1217 | retval = (RES_BUS(cfgte->resource_address) != | 1386 | retval = (RES_BUS(cfgte->resource_address) != |
| 1218 | PMCRAID_VIRTUAL_ENCL_BUS_ID); | 1387 | PMCRAID_VIRTUAL_ENCL_BUS_ID); |
| 1219 | return retval; | 1388 | return retval; |
| @@ -1246,8 +1415,8 @@ static struct genl_family pmcraid_event_family = { | |||
| 1246 | * pmcraid_netlink_init - registers pmcraid_event_family | 1415 | * pmcraid_netlink_init - registers pmcraid_event_family |
| 1247 | * | 1416 | * |
| 1248 | * Return value: | 1417 | * Return value: |
| 1249 | * 0 if the pmcraid_event_family is successfully registered | 1418 | * 0 if the pmcraid_event_family is successfully registered |
| 1250 | * with netlink generic, non-zero otherwise | 1419 | * with netlink generic, non-zero otherwise |
| 1251 | */ | 1420 | */ |
| 1252 | static int pmcraid_netlink_init(void) | 1421 | static int pmcraid_netlink_init(void) |
| 1253 | { | 1422 | { |
| @@ -1268,7 +1437,7 @@ static int pmcraid_netlink_init(void) | |||
| 1268 | * pmcraid_netlink_release - unregisters pmcraid_event_family | 1437 | * pmcraid_netlink_release - unregisters pmcraid_event_family |
| 1269 | * | 1438 | * |
| 1270 | * Return value: | 1439 | * Return value: |
| 1271 | * none | 1440 | * none |
| 1272 | */ | 1441 | */ |
| 1273 | static void pmcraid_netlink_release(void) | 1442 | static void pmcraid_netlink_release(void) |
| 1274 | { | 1443 | { |
| @@ -1283,31 +1452,30 @@ static void pmcraid_netlink_release(void) | |||
| 1283 | * Return value: | 1452 | * Return value: |
| 1284 | * 0 if success, error value in case of any failure. | 1453 | * 0 if success, error value in case of any failure. |
| 1285 | */ | 1454 | */ |
| 1286 | static int pmcraid_notify_aen(struct pmcraid_instance *pinstance, u8 type) | 1455 | static int pmcraid_notify_aen( |
| 1456 | struct pmcraid_instance *pinstance, | ||
| 1457 | struct pmcraid_aen_msg *aen_msg, | ||
| 1458 | u32 data_size | ||
| 1459 | ) | ||
| 1287 | { | 1460 | { |
| 1288 | struct sk_buff *skb; | 1461 | struct sk_buff *skb; |
| 1289 | struct pmcraid_aen_msg *aen_msg; | ||
| 1290 | void *msg_header; | 1462 | void *msg_header; |
| 1291 | int data_size, total_size; | 1463 | u32 total_size, nla_genl_hdr_total_size; |
| 1292 | int result; | 1464 | int result; |
| 1293 | 1465 | ||
| 1294 | |||
| 1295 | if (type == PMCRAID_HCAM_CODE_LOG_DATA) { | ||
| 1296 | aen_msg = pinstance->ldn.msg; | ||
| 1297 | data_size = pinstance->ldn.hcam->data_len; | ||
| 1298 | } else { | ||
| 1299 | aen_msg = pinstance->ccn.msg; | ||
| 1300 | data_size = pinstance->ccn.hcam->data_len; | ||
| 1301 | } | ||
| 1302 | |||
| 1303 | data_size += sizeof(struct pmcraid_hcam_hdr); | ||
| 1304 | aen_msg->hostno = (pinstance->host->unique_id << 16 | | 1466 | aen_msg->hostno = (pinstance->host->unique_id << 16 | |
| 1305 | MINOR(pinstance->cdev.dev)); | 1467 | MINOR(pinstance->cdev.dev)); |
| 1306 | aen_msg->length = data_size; | 1468 | aen_msg->length = data_size; |
| 1469 | |||
| 1307 | data_size += sizeof(*aen_msg); | 1470 | data_size += sizeof(*aen_msg); |
| 1308 | 1471 | ||
| 1309 | total_size = nla_total_size(data_size); | 1472 | total_size = nla_total_size(data_size); |
| 1310 | skb = genlmsg_new(total_size, GFP_ATOMIC); | 1473 | /* Add GENL_HDR to total_size */ |
| 1474 | nla_genl_hdr_total_size = | ||
| 1475 | (total_size + (GENL_HDRLEN + | ||
| 1476 | ((struct genl_family *)&pmcraid_event_family)->hdrsize) | ||
| 1477 | + NLMSG_HDRLEN); | ||
| 1478 | skb = genlmsg_new(nla_genl_hdr_total_size, GFP_ATOMIC); | ||
| 1311 | 1479 | ||
| 1312 | 1480 | ||
| 1313 | if (!skb) { | 1481 | if (!skb) { |
| @@ -1329,7 +1497,7 @@ static int pmcraid_notify_aen(struct pmcraid_instance *pinstance, u8 type) | |||
| 1329 | result = nla_put(skb, PMCRAID_AEN_ATTR_EVENT, data_size, aen_msg); | 1497 | result = nla_put(skb, PMCRAID_AEN_ATTR_EVENT, data_size, aen_msg); |
| 1330 | 1498 | ||
| 1331 | if (result) { | 1499 | if (result) { |
| 1332 | pmcraid_err("failed to copy AEN attribute data \n"); | 1500 | pmcraid_err("failed to copy AEN attribute data\n"); |
| 1333 | nlmsg_free(skb); | 1501 | nlmsg_free(skb); |
| 1334 | return -EINVAL; | 1502 | return -EINVAL; |
| 1335 | } | 1503 | } |
| @@ -1350,13 +1518,57 @@ static int pmcraid_notify_aen(struct pmcraid_instance *pinstance, u8 type) | |||
| 1350 | * value. | 1518 | * value. |
| 1351 | */ | 1519 | */ |
| 1352 | if (result) | 1520 | if (result) |
| 1353 | pmcraid_info("failed to send %s event message %x!\n", | 1521 | pmcraid_info("error (%x) sending aen event message\n", result); |
| 1354 | type == PMCRAID_HCAM_CODE_LOG_DATA ? "LDN" : "CCN", | ||
| 1355 | result); | ||
| 1356 | return result; | 1522 | return result; |
| 1357 | } | 1523 | } |
| 1358 | 1524 | ||
| 1359 | /** | 1525 | /** |
| 1526 | * pmcraid_notify_ccn - notifies about CCN event msg to user space | ||
| 1527 | * @pinstance: pointer adapter instance structure | ||
| 1528 | * | ||
| 1529 | * Return value: | ||
| 1530 | * 0 if success, error value in case of any failure | ||
| 1531 | */ | ||
| 1532 | static int pmcraid_notify_ccn(struct pmcraid_instance *pinstance) | ||
| 1533 | { | ||
| 1534 | return pmcraid_notify_aen(pinstance, | ||
| 1535 | pinstance->ccn.msg, | ||
| 1536 | pinstance->ccn.hcam->data_len + | ||
| 1537 | sizeof(struct pmcraid_hcam_hdr)); | ||
| 1538 | } | ||
| 1539 | |||
| 1540 | /** | ||
| 1541 | * pmcraid_notify_ldn - notifies about CCN event msg to user space | ||
| 1542 | * @pinstance: pointer adapter instance structure | ||
| 1543 | * | ||
| 1544 | * Return value: | ||
| 1545 | * 0 if success, error value in case of any failure | ||
| 1546 | */ | ||
| 1547 | static int pmcraid_notify_ldn(struct pmcraid_instance *pinstance) | ||
| 1548 | { | ||
| 1549 | return pmcraid_notify_aen(pinstance, | ||
| 1550 | pinstance->ldn.msg, | ||
| 1551 | pinstance->ldn.hcam->data_len + | ||
| 1552 | sizeof(struct pmcraid_hcam_hdr)); | ||
| 1553 | } | ||
| 1554 | |||
| 1555 | /** | ||
| 1556 | * pmcraid_notify_ioastate - sends IOA state event msg to user space | ||
| 1557 | * @pinstance: pointer adapter instance structure | ||
| 1558 | * @evt: controller state event to be sent | ||
| 1559 | * | ||
| 1560 | * Return value: | ||
| 1561 | * 0 if success, error value in case of any failure | ||
| 1562 | */ | ||
| 1563 | static void pmcraid_notify_ioastate(struct pmcraid_instance *pinstance, u32 evt) | ||
| 1564 | { | ||
| 1565 | pinstance->scn.ioa_state = evt; | ||
| 1566 | pmcraid_notify_aen(pinstance, | ||
| 1567 | &pinstance->scn.msg, | ||
| 1568 | sizeof(u32)); | ||
| 1569 | } | ||
| 1570 | |||
| 1571 | /** | ||
| 1360 | * pmcraid_handle_config_change - Handle a config change from the adapter | 1572 | * pmcraid_handle_config_change - Handle a config change from the adapter |
| 1361 | * @pinstance: pointer to per adapter instance structure | 1573 | * @pinstance: pointer to per adapter instance structure |
| 1362 | * | 1574 | * |
| @@ -1375,10 +1587,12 @@ static void pmcraid_handle_config_change(struct pmcraid_instance *pinstance) | |||
| 1375 | unsigned long host_lock_flags; | 1587 | unsigned long host_lock_flags; |
| 1376 | u32 new_entry = 1; | 1588 | u32 new_entry = 1; |
| 1377 | u32 hidden_entry = 0; | 1589 | u32 hidden_entry = 0; |
| 1590 | u16 fw_version; | ||
| 1378 | int rc; | 1591 | int rc; |
| 1379 | 1592 | ||
| 1380 | ccn_hcam = (struct pmcraid_hcam_ccn *)pinstance->ccn.hcam; | 1593 | ccn_hcam = (struct pmcraid_hcam_ccn *)pinstance->ccn.hcam; |
| 1381 | cfg_entry = &ccn_hcam->cfg_entry; | 1594 | cfg_entry = &ccn_hcam->cfg_entry; |
| 1595 | fw_version = be16_to_cpu(pinstance->inq_data->fw_version); | ||
| 1382 | 1596 | ||
| 1383 | pmcraid_info | 1597 | pmcraid_info |
| 1384 | ("CCN(%x): %x type: %x lost: %x flags: %x res: %x:%x:%x:%x\n", | 1598 | ("CCN(%x): %x type: %x lost: %x flags: %x res: %x:%x:%x:%x\n", |
| @@ -1391,7 +1605,10 @@ static void pmcraid_handle_config_change(struct pmcraid_instance *pinstance) | |||
| 1391 | RES_IS_VSET(*cfg_entry) ? PMCRAID_VSET_BUS_ID : | 1605 | RES_IS_VSET(*cfg_entry) ? PMCRAID_VSET_BUS_ID : |
| 1392 | (RES_IS_GSCSI(*cfg_entry) ? PMCRAID_PHYS_BUS_ID : | 1606 | (RES_IS_GSCSI(*cfg_entry) ? PMCRAID_PHYS_BUS_ID : |
| 1393 | RES_BUS(cfg_entry->resource_address)), | 1607 | RES_BUS(cfg_entry->resource_address)), |
| 1394 | RES_IS_VSET(*cfg_entry) ? cfg_entry->unique_flags1 : | 1608 | RES_IS_VSET(*cfg_entry) ? |
| 1609 | (fw_version <= PMCRAID_FW_VERSION_1 ? | ||
| 1610 | cfg_entry->unique_flags1 : | ||
| 1611 | cfg_entry->array_id & 0xFF) : | ||
| 1395 | RES_TARGET(cfg_entry->resource_address), | 1612 | RES_TARGET(cfg_entry->resource_address), |
| 1396 | RES_LUN(cfg_entry->resource_address)); | 1613 | RES_LUN(cfg_entry->resource_address)); |
| 1397 | 1614 | ||
| @@ -1415,11 +1632,16 @@ static void pmcraid_handle_config_change(struct pmcraid_instance *pinstance) | |||
| 1415 | */ | 1632 | */ |
| 1416 | if (pinstance->ccn.hcam->notification_type == | 1633 | if (pinstance->ccn.hcam->notification_type == |
| 1417 | NOTIFICATION_TYPE_ENTRY_CHANGED && | 1634 | NOTIFICATION_TYPE_ENTRY_CHANGED && |
| 1418 | cfg_entry->resource_type == RES_TYPE_VSET && | 1635 | cfg_entry->resource_type == RES_TYPE_VSET) { |
| 1419 | cfg_entry->unique_flags1 & 0x80) { | 1636 | |
| 1420 | hidden_entry = 1; | 1637 | if (fw_version <= PMCRAID_FW_VERSION_1) |
| 1421 | } else if (!pmcraid_expose_resource(cfg_entry)) | 1638 | hidden_entry = (cfg_entry->unique_flags1 & 0x80) != 0; |
| 1639 | else | ||
| 1640 | hidden_entry = (cfg_entry->unique_flags1 & 0x80) != 0; | ||
| 1641 | |||
| 1642 | } else if (!pmcraid_expose_resource(fw_version, cfg_entry)) { | ||
| 1422 | goto out_notify_apps; | 1643 | goto out_notify_apps; |
| 1644 | } | ||
| 1423 | 1645 | ||
| 1424 | spin_lock_irqsave(&pinstance->resource_lock, lock_flags); | 1646 | spin_lock_irqsave(&pinstance->resource_lock, lock_flags); |
| 1425 | list_for_each_entry(res, &pinstance->used_res_q, queue) { | 1647 | list_for_each_entry(res, &pinstance->used_res_q, queue) { |
| @@ -1466,13 +1688,15 @@ static void pmcraid_handle_config_change(struct pmcraid_instance *pinstance) | |||
| 1466 | list_add_tail(&res->queue, &pinstance->used_res_q); | 1688 | list_add_tail(&res->queue, &pinstance->used_res_q); |
| 1467 | } | 1689 | } |
| 1468 | 1690 | ||
| 1469 | memcpy(&res->cfg_entry, cfg_entry, | 1691 | memcpy(&res->cfg_entry, cfg_entry, pinstance->config_table_entry_size); |
| 1470 | sizeof(struct pmcraid_config_table_entry)); | ||
| 1471 | 1692 | ||
| 1472 | if (pinstance->ccn.hcam->notification_type == | 1693 | if (pinstance->ccn.hcam->notification_type == |
| 1473 | NOTIFICATION_TYPE_ENTRY_DELETED || hidden_entry) { | 1694 | NOTIFICATION_TYPE_ENTRY_DELETED || hidden_entry) { |
| 1474 | if (res->scsi_dev) { | 1695 | if (res->scsi_dev) { |
| 1475 | res->cfg_entry.unique_flags1 &= 0x7F; | 1696 | if (fw_version <= PMCRAID_FW_VERSION_1) |
| 1697 | res->cfg_entry.unique_flags1 &= 0x7F; | ||
| 1698 | else | ||
| 1699 | res->cfg_entry.array_id &= 0xFF; | ||
| 1476 | res->change_detected = RES_CHANGE_DEL; | 1700 | res->change_detected = RES_CHANGE_DEL; |
| 1477 | res->cfg_entry.resource_handle = | 1701 | res->cfg_entry.resource_handle = |
| 1478 | PMCRAID_INVALID_RES_HANDLE; | 1702 | PMCRAID_INVALID_RES_HANDLE; |
| @@ -1491,7 +1715,7 @@ out_notify_apps: | |||
| 1491 | 1715 | ||
| 1492 | /* Notify configuration changes to registered applications.*/ | 1716 | /* Notify configuration changes to registered applications.*/ |
| 1493 | if (!pmcraid_disable_aen) | 1717 | if (!pmcraid_disable_aen) |
| 1494 | pmcraid_notify_aen(pinstance, PMCRAID_HCAM_CODE_CONFIG_CHANGE); | 1718 | pmcraid_notify_ccn(pinstance); |
| 1495 | 1719 | ||
| 1496 | cmd = pmcraid_init_hcam(pinstance, PMCRAID_HCAM_CODE_CONFIG_CHANGE); | 1720 | cmd = pmcraid_init_hcam(pinstance, PMCRAID_HCAM_CODE_CONFIG_CHANGE); |
| 1497 | if (cmd) | 1721 | if (cmd) |
| @@ -1528,7 +1752,7 @@ void pmcraid_ioasc_logger(u32 ioasc, struct pmcraid_cmd *cmd) | |||
| 1528 | return; | 1752 | return; |
| 1529 | 1753 | ||
| 1530 | /* log the error string */ | 1754 | /* log the error string */ |
| 1531 | pmcraid_err("cmd [%d] for resource %x failed with %x(%s)\n", | 1755 | pmcraid_err("cmd [%x] for resource %x failed with %x(%s)\n", |
| 1532 | cmd->ioa_cb->ioarcb.cdb[0], | 1756 | cmd->ioa_cb->ioarcb.cdb[0], |
| 1533 | cmd->ioa_cb->ioarcb.resource_handle, | 1757 | cmd->ioa_cb->ioarcb.resource_handle, |
| 1534 | le32_to_cpu(ioasc), error_info->error_string); | 1758 | le32_to_cpu(ioasc), error_info->error_string); |
| @@ -1663,7 +1887,7 @@ static void pmcraid_process_ldn(struct pmcraid_cmd *cmd) | |||
| 1663 | } | 1887 | } |
| 1664 | /* send netlink message for HCAM notification if enabled */ | 1888 | /* send netlink message for HCAM notification if enabled */ |
| 1665 | if (!pmcraid_disable_aen) | 1889 | if (!pmcraid_disable_aen) |
| 1666 | pmcraid_notify_aen(pinstance, PMCRAID_HCAM_CODE_LOG_DATA); | 1890 | pmcraid_notify_ldn(pinstance); |
| 1667 | 1891 | ||
| 1668 | cmd = pmcraid_init_hcam(pinstance, PMCRAID_HCAM_CODE_LOG_DATA); | 1892 | cmd = pmcraid_init_hcam(pinstance, PMCRAID_HCAM_CODE_LOG_DATA); |
| 1669 | if (cmd) | 1893 | if (cmd) |
| @@ -1701,10 +1925,13 @@ static void pmcraid_unregister_hcams(struct pmcraid_cmd *cmd) | |||
| 1701 | atomic_set(&pinstance->ldn.ignore, 1); | 1925 | atomic_set(&pinstance->ldn.ignore, 1); |
| 1702 | 1926 | ||
| 1703 | /* If adapter reset was forced as part of runtime reset sequence, | 1927 | /* If adapter reset was forced as part of runtime reset sequence, |
| 1704 | * start the reset sequence. | 1928 | * start the reset sequence. Reset will be triggered even in case |
| 1929 | * IOA unit_check. | ||
| 1705 | */ | 1930 | */ |
| 1706 | if (pinstance->force_ioa_reset && !pinstance->ioa_bringdown) { | 1931 | if ((pinstance->force_ioa_reset && !pinstance->ioa_bringdown) || |
| 1932 | pinstance->ioa_unit_check) { | ||
| 1707 | pinstance->force_ioa_reset = 0; | 1933 | pinstance->force_ioa_reset = 0; |
| 1934 | pinstance->ioa_unit_check = 0; | ||
| 1708 | pinstance->ioa_state = IOA_STATE_IN_RESET_ALERT; | 1935 | pinstance->ioa_state = IOA_STATE_IN_RESET_ALERT; |
| 1709 | pmcraid_reset_alert(cmd); | 1936 | pmcraid_reset_alert(cmd); |
| 1710 | return; | 1937 | return; |
| @@ -1735,10 +1962,13 @@ static int pmcraid_reset_enable_ioa(struct pmcraid_instance *pinstance) | |||
| 1735 | pmcraid_enable_interrupts(pinstance, PMCRAID_PCI_INTERRUPTS); | 1962 | pmcraid_enable_interrupts(pinstance, PMCRAID_PCI_INTERRUPTS); |
| 1736 | 1963 | ||
| 1737 | if (intrs & INTRS_TRANSITION_TO_OPERATIONAL) { | 1964 | if (intrs & INTRS_TRANSITION_TO_OPERATIONAL) { |
| 1738 | iowrite32(INTRS_TRANSITION_TO_OPERATIONAL, | 1965 | if (!pinstance->interrupt_mode) { |
| 1739 | pinstance->int_regs.ioa_host_interrupt_mask_reg); | 1966 | iowrite32(INTRS_TRANSITION_TO_OPERATIONAL, |
| 1740 | iowrite32(INTRS_TRANSITION_TO_OPERATIONAL, | 1967 | pinstance->int_regs. |
| 1741 | pinstance->int_regs.ioa_host_interrupt_clr_reg); | 1968 | ioa_host_interrupt_mask_reg); |
| 1969 | iowrite32(INTRS_TRANSITION_TO_OPERATIONAL, | ||
| 1970 | pinstance->int_regs.ioa_host_interrupt_clr_reg); | ||
| 1971 | } | ||
| 1742 | return 1; | 1972 | return 1; |
| 1743 | } else { | 1973 | } else { |
| 1744 | return 0; | 1974 | return 0; |
| @@ -1777,8 +2007,19 @@ static void pmcraid_soft_reset(struct pmcraid_cmd *cmd) | |||
| 1777 | doorbell = DOORBELL_RUNTIME_RESET | | 2007 | doorbell = DOORBELL_RUNTIME_RESET | |
| 1778 | DOORBELL_ENABLE_DESTRUCTIVE_DIAGS; | 2008 | DOORBELL_ENABLE_DESTRUCTIVE_DIAGS; |
| 1779 | 2009 | ||
| 2010 | /* Since we do RESET_ALERT and Start BIST we have to again write | ||
| 2011 | * MSIX Doorbell to indicate the interrupt mode | ||
| 2012 | */ | ||
| 2013 | if (pinstance->interrupt_mode) { | ||
| 2014 | iowrite32(DOORBELL_INTR_MODE_MSIX, | ||
| 2015 | pinstance->int_regs.host_ioa_interrupt_reg); | ||
| 2016 | ioread32(pinstance->int_regs.host_ioa_interrupt_reg); | ||
| 2017 | } | ||
| 2018 | |||
| 1780 | iowrite32(doorbell, pinstance->int_regs.host_ioa_interrupt_reg); | 2019 | iowrite32(doorbell, pinstance->int_regs.host_ioa_interrupt_reg); |
| 2020 | ioread32(pinstance->int_regs.host_ioa_interrupt_reg), | ||
| 1781 | int_reg = ioread32(pinstance->int_regs.ioa_host_interrupt_reg); | 2021 | int_reg = ioread32(pinstance->int_regs.ioa_host_interrupt_reg); |
| 2022 | |||
| 1782 | pmcraid_info("Waiting for IOA to become operational %x:%x\n", | 2023 | pmcraid_info("Waiting for IOA to become operational %x:%x\n", |
| 1783 | ioread32(pinstance->int_regs.host_ioa_interrupt_reg), | 2024 | ioread32(pinstance->int_regs.host_ioa_interrupt_reg), |
| 1784 | int_reg); | 2025 | int_reg); |
| @@ -1854,7 +2095,8 @@ static void pmcraid_fail_outstanding_cmds(struct pmcraid_instance *pinstance) | |||
| 1854 | } else if (cmd->cmd_done == pmcraid_internal_done || | 2095 | } else if (cmd->cmd_done == pmcraid_internal_done || |
| 1855 | cmd->cmd_done == pmcraid_erp_done) { | 2096 | cmd->cmd_done == pmcraid_erp_done) { |
| 1856 | cmd->cmd_done(cmd); | 2097 | cmd->cmd_done(cmd); |
| 1857 | } else if (cmd->cmd_done != pmcraid_ioa_reset) { | 2098 | } else if (cmd->cmd_done != pmcraid_ioa_reset && |
| 2099 | cmd->cmd_done != pmcraid_ioa_shutdown_done) { | ||
| 1858 | pmcraid_return_cmd(cmd); | 2100 | pmcraid_return_cmd(cmd); |
| 1859 | } | 2101 | } |
| 1860 | 2102 | ||
| @@ -1964,6 +2206,13 @@ static void pmcraid_ioa_reset(struct pmcraid_cmd *cmd) | |||
| 1964 | pinstance->ioa_reset_attempts = 0; | 2206 | pinstance->ioa_reset_attempts = 0; |
| 1965 | pmcraid_err("IOA didn't respond marking it as dead\n"); | 2207 | pmcraid_err("IOA didn't respond marking it as dead\n"); |
| 1966 | pinstance->ioa_state = IOA_STATE_DEAD; | 2208 | pinstance->ioa_state = IOA_STATE_DEAD; |
| 2209 | |||
| 2210 | if (pinstance->ioa_bringdown) | ||
| 2211 | pmcraid_notify_ioastate(pinstance, | ||
| 2212 | PMC_DEVICE_EVENT_SHUTDOWN_FAILED); | ||
| 2213 | else | ||
| 2214 | pmcraid_notify_ioastate(pinstance, | ||
| 2215 | PMC_DEVICE_EVENT_RESET_FAILED); | ||
| 1967 | reset_complete = 1; | 2216 | reset_complete = 1; |
| 1968 | break; | 2217 | break; |
| 1969 | } | 2218 | } |
| @@ -1971,7 +2220,6 @@ static void pmcraid_ioa_reset(struct pmcraid_cmd *cmd) | |||
| 1971 | /* Once either bist or pci reset is done, restore PCI config | 2220 | /* Once either bist or pci reset is done, restore PCI config |
| 1972 | * space. If this fails, proceed with hard reset again | 2221 | * space. If this fails, proceed with hard reset again |
| 1973 | */ | 2222 | */ |
| 1974 | |||
| 1975 | if (pci_restore_state(pinstance->pdev)) { | 2223 | if (pci_restore_state(pinstance->pdev)) { |
| 1976 | pmcraid_info("config-space error resetting again\n"); | 2224 | pmcraid_info("config-space error resetting again\n"); |
| 1977 | pinstance->ioa_state = IOA_STATE_IN_RESET_ALERT; | 2225 | pinstance->ioa_state = IOA_STATE_IN_RESET_ALERT; |
| @@ -2002,6 +2250,8 @@ static void pmcraid_ioa_reset(struct pmcraid_cmd *cmd) | |||
| 2002 | pinstance->ioa_shutdown_type = SHUTDOWN_NONE; | 2250 | pinstance->ioa_shutdown_type = SHUTDOWN_NONE; |
| 2003 | pinstance->ioa_bringdown = 0; | 2251 | pinstance->ioa_bringdown = 0; |
| 2004 | pinstance->ioa_state = IOA_STATE_UNKNOWN; | 2252 | pinstance->ioa_state = IOA_STATE_UNKNOWN; |
| 2253 | pmcraid_notify_ioastate(pinstance, | ||
| 2254 | PMC_DEVICE_EVENT_SHUTDOWN_SUCCESS); | ||
| 2005 | reset_complete = 1; | 2255 | reset_complete = 1; |
| 2006 | } else { | 2256 | } else { |
| 2007 | /* bring-up IOA, so proceed with soft reset | 2257 | /* bring-up IOA, so proceed with soft reset |
| @@ -2051,6 +2301,8 @@ static void pmcraid_ioa_reset(struct pmcraid_cmd *cmd) | |||
| 2051 | */ | 2301 | */ |
| 2052 | if (pinstance->ioa_shutdown_type == SHUTDOWN_NONE && | 2302 | if (pinstance->ioa_shutdown_type == SHUTDOWN_NONE && |
| 2053 | pinstance->force_ioa_reset == 0) { | 2303 | pinstance->force_ioa_reset == 0) { |
| 2304 | pmcraid_notify_ioastate(pinstance, | ||
| 2305 | PMC_DEVICE_EVENT_RESET_SUCCESS); | ||
| 2054 | reset_complete = 1; | 2306 | reset_complete = 1; |
| 2055 | } else { | 2307 | } else { |
| 2056 | if (pinstance->ioa_shutdown_type != SHUTDOWN_NONE) | 2308 | if (pinstance->ioa_shutdown_type != SHUTDOWN_NONE) |
| @@ -2116,6 +2368,8 @@ static void pmcraid_initiate_reset(struct pmcraid_instance *pinstance) | |||
| 2116 | pinstance->ioa_shutdown_type = SHUTDOWN_NONE; | 2368 | pinstance->ioa_shutdown_type = SHUTDOWN_NONE; |
| 2117 | pinstance->reset_cmd = cmd; | 2369 | pinstance->reset_cmd = cmd; |
| 2118 | pinstance->force_ioa_reset = 1; | 2370 | pinstance->force_ioa_reset = 1; |
| 2371 | pmcraid_notify_ioastate(pinstance, | ||
| 2372 | PMC_DEVICE_EVENT_RESET_START); | ||
| 2119 | pmcraid_ioa_reset(cmd); | 2373 | pmcraid_ioa_reset(cmd); |
| 2120 | } | 2374 | } |
| 2121 | } | 2375 | } |
| @@ -2191,7 +2445,7 @@ static int pmcraid_reset_reload( | |||
| 2191 | wait_event(pinstance->reset_wait_q, | 2445 | wait_event(pinstance->reset_wait_q, |
| 2192 | !pinstance->ioa_reset_in_progress); | 2446 | !pinstance->ioa_reset_in_progress); |
| 2193 | 2447 | ||
| 2194 | pmcraid_info("reset_reload: reset is complete !! \n"); | 2448 | pmcraid_info("reset_reload: reset is complete !!\n"); |
| 2195 | scsi_unblock_requests(pinstance->host); | 2449 | scsi_unblock_requests(pinstance->host); |
| 2196 | if (pinstance->ioa_state == target_state) | 2450 | if (pinstance->ioa_state == target_state) |
| 2197 | reset = 0; | 2451 | reset = 0; |
| @@ -2225,6 +2479,8 @@ static int pmcraid_reset_bringdown(struct pmcraid_instance *pinstance) | |||
| 2225 | */ | 2479 | */ |
| 2226 | static int pmcraid_reset_bringup(struct pmcraid_instance *pinstance) | 2480 | static int pmcraid_reset_bringup(struct pmcraid_instance *pinstance) |
| 2227 | { | 2481 | { |
| 2482 | pmcraid_notify_ioastate(pinstance, PMC_DEVICE_EVENT_RESET_START); | ||
| 2483 | |||
| 2228 | return pmcraid_reset_reload(pinstance, | 2484 | return pmcraid_reset_reload(pinstance, |
| 2229 | SHUTDOWN_NONE, | 2485 | SHUTDOWN_NONE, |
| 2230 | IOA_STATE_OPERATIONAL); | 2486 | IOA_STATE_OPERATIONAL); |
| @@ -2704,7 +2960,7 @@ static struct pmcraid_cmd *pmcraid_abort_cmd(struct pmcraid_cmd *cmd) | |||
| 2704 | 2960 | ||
| 2705 | pmcraid_info("command (%d) CDB[0] = %x for %x\n", | 2961 | pmcraid_info("command (%d) CDB[0] = %x for %x\n", |
| 2706 | le32_to_cpu(cancel_cmd->ioa_cb->ioarcb.response_handle) >> 2, | 2962 | le32_to_cpu(cancel_cmd->ioa_cb->ioarcb.response_handle) >> 2, |
| 2707 | cmd->ioa_cb->ioarcb.cdb[0], | 2963 | cancel_cmd->ioa_cb->ioarcb.cdb[0], |
| 2708 | le32_to_cpu(cancel_cmd->ioa_cb->ioarcb.resource_handle)); | 2964 | le32_to_cpu(cancel_cmd->ioa_cb->ioarcb.resource_handle)); |
| 2709 | 2965 | ||
| 2710 | pmcraid_send_cmd(cancel_cmd, | 2966 | pmcraid_send_cmd(cancel_cmd, |
| @@ -2729,8 +2985,8 @@ static int pmcraid_abort_complete(struct pmcraid_cmd *cancel_cmd) | |||
| 2729 | u32 ioasc; | 2985 | u32 ioasc; |
| 2730 | 2986 | ||
| 2731 | wait_for_completion(&cancel_cmd->wait_for_completion); | 2987 | wait_for_completion(&cancel_cmd->wait_for_completion); |
| 2732 | res = cancel_cmd->u.res; | 2988 | res = cancel_cmd->res; |
| 2733 | cancel_cmd->u.res = NULL; | 2989 | cancel_cmd->res = NULL; |
| 2734 | ioasc = le32_to_cpu(cancel_cmd->ioa_cb->ioasa.ioasc); | 2990 | ioasc = le32_to_cpu(cancel_cmd->ioa_cb->ioasa.ioasc); |
| 2735 | 2991 | ||
| 2736 | /* If the abort task is not timed out we will get a Good completion | 2992 | /* If the abort task is not timed out we will get a Good completion |
| @@ -2823,7 +3079,7 @@ static int pmcraid_eh_abort_handler(struct scsi_cmnd *scsi_cmd) | |||
| 2823 | host_lock_flags); | 3079 | host_lock_flags); |
| 2824 | 3080 | ||
| 2825 | if (cancel_cmd) { | 3081 | if (cancel_cmd) { |
| 2826 | cancel_cmd->u.res = cmd->scsi_cmd->device->hostdata; | 3082 | cancel_cmd->res = cmd->scsi_cmd->device->hostdata; |
| 2827 | rc = pmcraid_abort_complete(cancel_cmd); | 3083 | rc = pmcraid_abort_complete(cancel_cmd); |
| 2828 | } | 3084 | } |
| 2829 | 3085 | ||
| @@ -2842,7 +3098,7 @@ static int pmcraid_eh_abort_handler(struct scsi_cmnd *scsi_cmd) | |||
| 2842 | * takes care by locking/unlocking host_lock. | 3098 | * takes care by locking/unlocking host_lock. |
| 2843 | * | 3099 | * |
| 2844 | * Return value | 3100 | * Return value |
| 2845 | * SUCCESS or FAILED | 3101 | * SUCCESS or FAILED |
| 2846 | */ | 3102 | */ |
| 2847 | static int pmcraid_eh_device_reset_handler(struct scsi_cmnd *scmd) | 3103 | static int pmcraid_eh_device_reset_handler(struct scsi_cmnd *scmd) |
| 2848 | { | 3104 | { |
| @@ -2879,7 +3135,7 @@ static int pmcraid_eh_target_reset_handler(struct scsi_cmnd *scmd) | |||
| 2879 | * Initiates adapter reset to bring it up to operational state | 3135 | * Initiates adapter reset to bring it up to operational state |
| 2880 | * | 3136 | * |
| 2881 | * Return value | 3137 | * Return value |
| 2882 | * SUCCESS or FAILED | 3138 | * SUCCESS or FAILED |
| 2883 | */ | 3139 | */ |
| 2884 | static int pmcraid_eh_host_reset_handler(struct scsi_cmnd *scmd) | 3140 | static int pmcraid_eh_host_reset_handler(struct scsi_cmnd *scmd) |
| 2885 | { | 3141 | { |
| @@ -2991,7 +3247,7 @@ pmcraid_init_ioadls(struct pmcraid_cmd *cmd, int sgcount) | |||
| 2991 | * to firmware. This builds ioadl descriptors and sets up ioarcb fields. | 3247 | * to firmware. This builds ioadl descriptors and sets up ioarcb fields. |
| 2992 | * | 3248 | * |
| 2993 | * Return value: | 3249 | * Return value: |
| 2994 | * 0 on success or -1 on failure | 3250 | * 0 on success or -1 on failure |
| 2995 | */ | 3251 | */ |
| 2996 | static int pmcraid_build_ioadl( | 3252 | static int pmcraid_build_ioadl( |
| 2997 | struct pmcraid_instance *pinstance, | 3253 | struct pmcraid_instance *pinstance, |
| @@ -3049,7 +3305,7 @@ static int pmcraid_build_ioadl( | |||
| 3049 | * Free a DMA'able memory previously allocated with pmcraid_alloc_sglist | 3305 | * Free a DMA'able memory previously allocated with pmcraid_alloc_sglist |
| 3050 | * | 3306 | * |
| 3051 | * Return value: | 3307 | * Return value: |
| 3052 | * none | 3308 | * none |
| 3053 | */ | 3309 | */ |
| 3054 | static void pmcraid_free_sglist(struct pmcraid_sglist *sglist) | 3310 | static void pmcraid_free_sglist(struct pmcraid_sglist *sglist) |
| 3055 | { | 3311 | { |
| @@ -3070,7 +3326,7 @@ static void pmcraid_free_sglist(struct pmcraid_sglist *sglist) | |||
| 3070 | * list. | 3326 | * list. |
| 3071 | * | 3327 | * |
| 3072 | * Return value | 3328 | * Return value |
| 3073 | * pointer to sglist / NULL on failure | 3329 | * pointer to sglist / NULL on failure |
| 3074 | */ | 3330 | */ |
| 3075 | static struct pmcraid_sglist *pmcraid_alloc_sglist(int buflen) | 3331 | static struct pmcraid_sglist *pmcraid_alloc_sglist(int buflen) |
| 3076 | { | 3332 | { |
| @@ -3224,11 +3480,12 @@ static int pmcraid_queuecommand( | |||
| 3224 | struct pmcraid_resource_entry *res; | 3480 | struct pmcraid_resource_entry *res; |
| 3225 | struct pmcraid_ioarcb *ioarcb; | 3481 | struct pmcraid_ioarcb *ioarcb; |
| 3226 | struct pmcraid_cmd *cmd; | 3482 | struct pmcraid_cmd *cmd; |
| 3483 | u32 fw_version; | ||
| 3227 | int rc = 0; | 3484 | int rc = 0; |
| 3228 | 3485 | ||
| 3229 | pinstance = | 3486 | pinstance = |
| 3230 | (struct pmcraid_instance *)scsi_cmd->device->host->hostdata; | 3487 | (struct pmcraid_instance *)scsi_cmd->device->host->hostdata; |
| 3231 | 3488 | fw_version = be16_to_cpu(pinstance->inq_data->fw_version); | |
| 3232 | scsi_cmd->scsi_done = done; | 3489 | scsi_cmd->scsi_done = done; |
| 3233 | res = scsi_cmd->device->hostdata; | 3490 | res = scsi_cmd->device->hostdata; |
| 3234 | scsi_cmd->result = (DID_OK << 16); | 3491 | scsi_cmd->result = (DID_OK << 16); |
| @@ -3247,6 +3504,15 @@ static int pmcraid_queuecommand( | |||
| 3247 | if (pinstance->ioa_reset_in_progress) | 3504 | if (pinstance->ioa_reset_in_progress) |
| 3248 | return SCSI_MLQUEUE_HOST_BUSY; | 3505 | return SCSI_MLQUEUE_HOST_BUSY; |
| 3249 | 3506 | ||
| 3507 | /* Firmware doesn't support SYNCHRONIZE_CACHE command (0x35), complete | ||
| 3508 | * the command here itself with success return | ||
| 3509 | */ | ||
| 3510 | if (scsi_cmd->cmnd[0] == SYNCHRONIZE_CACHE) { | ||
| 3511 | pmcraid_info("SYNC_CACHE(0x35), completing in driver itself\n"); | ||
| 3512 | scsi_cmd->scsi_done(scsi_cmd); | ||
| 3513 | return 0; | ||
| 3514 | } | ||
| 3515 | |||
| 3250 | /* initialize the command and IOARCB to be sent to IOA */ | 3516 | /* initialize the command and IOARCB to be sent to IOA */ |
| 3251 | cmd = pmcraid_get_free_cmd(pinstance); | 3517 | cmd = pmcraid_get_free_cmd(pinstance); |
| 3252 | 3518 | ||
| @@ -3261,6 +3527,13 @@ static int pmcraid_queuecommand( | |||
| 3261 | ioarcb->resource_handle = res->cfg_entry.resource_handle; | 3527 | ioarcb->resource_handle = res->cfg_entry.resource_handle; |
| 3262 | ioarcb->request_type = REQ_TYPE_SCSI; | 3528 | ioarcb->request_type = REQ_TYPE_SCSI; |
| 3263 | 3529 | ||
| 3530 | /* set hrrq number where the IOA should respond to. Note that all cmds | ||
| 3531 | * generated internally uses hrrq_id 0, exception to this is the cmd | ||
| 3532 | * block of scsi_cmd which is re-used (e.g. cancel/abort), which uses | ||
| 3533 | * hrrq_id assigned here in queuecommand | ||
| 3534 | */ | ||
| 3535 | ioarcb->hrrq_id = atomic_add_return(1, &(pinstance->last_message_id)) % | ||
| 3536 | pinstance->num_hrrq; | ||
| 3264 | cmd->cmd_done = pmcraid_io_done; | 3537 | cmd->cmd_done = pmcraid_io_done; |
| 3265 | 3538 | ||
| 3266 | if (RES_IS_GSCSI(res->cfg_entry) || RES_IS_VSET(res->cfg_entry)) { | 3539 | if (RES_IS_GSCSI(res->cfg_entry) || RES_IS_VSET(res->cfg_entry)) { |
| @@ -3287,7 +3560,9 @@ static int pmcraid_queuecommand( | |||
| 3287 | RES_IS_VSET(res->cfg_entry) ? PMCRAID_VSET_BUS_ID : | 3560 | RES_IS_VSET(res->cfg_entry) ? PMCRAID_VSET_BUS_ID : |
| 3288 | PMCRAID_PHYS_BUS_ID, | 3561 | PMCRAID_PHYS_BUS_ID, |
| 3289 | RES_IS_VSET(res->cfg_entry) ? | 3562 | RES_IS_VSET(res->cfg_entry) ? |
| 3290 | res->cfg_entry.unique_flags1 : | 3563 | (fw_version <= PMCRAID_FW_VERSION_1 ? |
| 3564 | res->cfg_entry.unique_flags1 : | ||
| 3565 | res->cfg_entry.array_id & 0xFF) : | ||
| 3291 | RES_TARGET(res->cfg_entry.resource_address), | 3566 | RES_TARGET(res->cfg_entry.resource_address), |
| 3292 | RES_LUN(res->cfg_entry.resource_address)); | 3567 | RES_LUN(res->cfg_entry.resource_address)); |
| 3293 | 3568 | ||
| @@ -3324,8 +3599,7 @@ static int pmcraid_chr_open(struct inode *inode, struct file *filep) | |||
| 3324 | */ | 3599 | */ |
| 3325 | static int pmcraid_chr_release(struct inode *inode, struct file *filep) | 3600 | static int pmcraid_chr_release(struct inode *inode, struct file *filep) |
| 3326 | { | 3601 | { |
| 3327 | struct pmcraid_instance *pinstance = | 3602 | struct pmcraid_instance *pinstance = filep->private_data; |
| 3328 | ((struct pmcraid_instance *)filep->private_data); | ||
| 3329 | 3603 | ||
| 3330 | filep->private_data = NULL; | 3604 | filep->private_data = NULL; |
| 3331 | fasync_helper(-1, filep, 0, &pinstance->aen_queue); | 3605 | fasync_helper(-1, filep, 0, &pinstance->aen_queue); |
| @@ -3344,7 +3618,7 @@ static int pmcraid_chr_fasync(int fd, struct file *filep, int mode) | |||
| 3344 | struct pmcraid_instance *pinstance; | 3618 | struct pmcraid_instance *pinstance; |
| 3345 | int rc; | 3619 | int rc; |
| 3346 | 3620 | ||
| 3347 | pinstance = (struct pmcraid_instance *)filep->private_data; | 3621 | pinstance = filep->private_data; |
| 3348 | mutex_lock(&pinstance->aen_queue_lock); | 3622 | mutex_lock(&pinstance->aen_queue_lock); |
| 3349 | rc = fasync_helper(fd, filep, mode, &pinstance->aen_queue); | 3623 | rc = fasync_helper(fd, filep, mode, &pinstance->aen_queue); |
| 3350 | mutex_unlock(&pinstance->aen_queue_lock); | 3624 | mutex_unlock(&pinstance->aen_queue_lock); |
| @@ -3465,6 +3739,7 @@ static long pmcraid_ioctl_passthrough( | |||
| 3465 | unsigned long request_buffer; | 3739 | unsigned long request_buffer; |
| 3466 | unsigned long request_offset; | 3740 | unsigned long request_offset; |
| 3467 | unsigned long lock_flags; | 3741 | unsigned long lock_flags; |
| 3742 | u32 ioasc; | ||
| 3468 | int request_size; | 3743 | int request_size; |
| 3469 | int buffer_size; | 3744 | int buffer_size; |
| 3470 | u8 access, direction; | 3745 | u8 access, direction; |
| @@ -3566,6 +3841,14 @@ static long pmcraid_ioctl_passthrough( | |||
| 3566 | buffer->ioarcb.add_cmd_param_length); | 3841 | buffer->ioarcb.add_cmd_param_length); |
| 3567 | } | 3842 | } |
| 3568 | 3843 | ||
| 3844 | /* set hrrq number where the IOA should respond to. Note that all cmds | ||
| 3845 | * generated internally uses hrrq_id 0, exception to this is the cmd | ||
| 3846 | * block of scsi_cmd which is re-used (e.g. cancel/abort), which uses | ||
| 3847 | * hrrq_id assigned here in queuecommand | ||
| 3848 | */ | ||
| 3849 | ioarcb->hrrq_id = atomic_add_return(1, &(pinstance->last_message_id)) % | ||
| 3850 | pinstance->num_hrrq; | ||
| 3851 | |||
| 3569 | if (request_size) { | 3852 | if (request_size) { |
| 3570 | rc = pmcraid_build_passthrough_ioadls(cmd, | 3853 | rc = pmcraid_build_passthrough_ioadls(cmd, |
| 3571 | request_size, | 3854 | request_size, |
| @@ -3606,6 +3889,14 @@ static long pmcraid_ioctl_passthrough( | |||
| 3606 | _pmcraid_fire_command(cmd); | 3889 | _pmcraid_fire_command(cmd); |
| 3607 | spin_unlock_irqrestore(pinstance->host->host_lock, lock_flags); | 3890 | spin_unlock_irqrestore(pinstance->host->host_lock, lock_flags); |
| 3608 | 3891 | ||
| 3892 | /* NOTE ! Remove the below line once abort_task is implemented | ||
| 3893 | * in firmware. This line disables ioctl command timeout handling logic | ||
| 3894 | * similar to IO command timeout handling, making ioctl commands to wait | ||
| 3895 | * until the command completion regardless of timeout value specified in | ||
| 3896 | * ioarcb | ||
| 3897 | */ | ||
| 3898 | buffer->ioarcb.cmd_timeout = 0; | ||
| 3899 | |||
| 3609 | /* If command timeout is specified put caller to wait till that time, | 3900 | /* If command timeout is specified put caller to wait till that time, |
| 3610 | * otherwise it would be blocking wait. If command gets timed out, it | 3901 | * otherwise it would be blocking wait. If command gets timed out, it |
| 3611 | * will be aborted. | 3902 | * will be aborted. |
| @@ -3620,25 +3911,47 @@ static long pmcraid_ioctl_passthrough( | |||
| 3620 | le32_to_cpu(cmd->ioa_cb->ioarcb.response_handle >> 2), | 3911 | le32_to_cpu(cmd->ioa_cb->ioarcb.response_handle >> 2), |
| 3621 | cmd->ioa_cb->ioarcb.cdb[0]); | 3912 | cmd->ioa_cb->ioarcb.cdb[0]); |
| 3622 | 3913 | ||
| 3623 | rc = -ETIMEDOUT; | ||
| 3624 | spin_lock_irqsave(pinstance->host->host_lock, lock_flags); | 3914 | spin_lock_irqsave(pinstance->host->host_lock, lock_flags); |
| 3625 | cancel_cmd = pmcraid_abort_cmd(cmd); | 3915 | cancel_cmd = pmcraid_abort_cmd(cmd); |
| 3626 | spin_unlock_irqrestore(pinstance->host->host_lock, lock_flags); | 3916 | spin_unlock_irqrestore(pinstance->host->host_lock, lock_flags); |
| 3627 | 3917 | ||
| 3628 | if (cancel_cmd) { | 3918 | if (cancel_cmd) { |
| 3629 | wait_for_completion(&cancel_cmd->wait_for_completion); | 3919 | wait_for_completion(&cancel_cmd->wait_for_completion); |
| 3920 | ioasc = cancel_cmd->ioa_cb->ioasa.ioasc; | ||
| 3630 | pmcraid_return_cmd(cancel_cmd); | 3921 | pmcraid_return_cmd(cancel_cmd); |
| 3922 | |||
| 3923 | /* if abort task couldn't find the command i.e it got | ||
| 3924 | * completed prior to aborting, return good completion. | ||
| 3925 | * if command got aborted succesfully or there was IOA | ||
| 3926 | * reset due to abort task itself getting timedout then | ||
| 3927 | * return -ETIMEDOUT | ||
| 3928 | */ | ||
| 3929 | if (ioasc == PMCRAID_IOASC_IOA_WAS_RESET || | ||
| 3930 | PMCRAID_IOASC_SENSE_KEY(ioasc) == 0x00) { | ||
| 3931 | if (ioasc != PMCRAID_IOASC_GC_IOARCB_NOTFOUND) | ||
| 3932 | rc = -ETIMEDOUT; | ||
| 3933 | goto out_handle_response; | ||
| 3934 | } | ||
| 3631 | } | 3935 | } |
| 3632 | 3936 | ||
| 3633 | goto out_free_sglist; | 3937 | /* no command block for abort task or abort task failed to abort |
| 3938 | * the IOARCB, then wait for 150 more seconds and initiate reset | ||
| 3939 | * sequence after timeout | ||
| 3940 | */ | ||
| 3941 | if (!wait_for_completion_timeout( | ||
| 3942 | &cmd->wait_for_completion, | ||
| 3943 | msecs_to_jiffies(150 * 1000))) { | ||
| 3944 | pmcraid_reset_bringup(cmd->drv_inst); | ||
| 3945 | rc = -ETIMEDOUT; | ||
| 3946 | } | ||
| 3634 | } | 3947 | } |
| 3635 | 3948 | ||
| 3949 | out_handle_response: | ||
| 3636 | /* If the command failed for any reason, copy entire IOASA buffer and | 3950 | /* If the command failed for any reason, copy entire IOASA buffer and |
| 3637 | * return IOCTL success. If copying IOASA to user-buffer fails, return | 3951 | * return IOCTL success. If copying IOASA to user-buffer fails, return |
| 3638 | * EFAULT | 3952 | * EFAULT |
| 3639 | */ | 3953 | */ |
| 3640 | if (le32_to_cpu(cmd->ioa_cb->ioasa.ioasc)) { | 3954 | if (PMCRAID_IOASC_SENSE_KEY(le32_to_cpu(cmd->ioa_cb->ioasa.ioasc))) { |
| 3641 | |||
| 3642 | void *ioasa = | 3955 | void *ioasa = |
| 3643 | (void *)(arg + | 3956 | (void *)(arg + |
| 3644 | offsetof(struct pmcraid_passthrough_ioctl_buffer, ioasa)); | 3957 | offsetof(struct pmcraid_passthrough_ioctl_buffer, ioasa)); |
| @@ -3651,6 +3964,7 @@ static long pmcraid_ioctl_passthrough( | |||
| 3651 | rc = -EFAULT; | 3964 | rc = -EFAULT; |
| 3652 | } | 3965 | } |
| 3653 | } | 3966 | } |
| 3967 | |||
| 3654 | /* If the data transfer was from device, copy the data onto user | 3968 | /* If the data transfer was from device, copy the data onto user |
| 3655 | * buffers | 3969 | * buffers |
| 3656 | */ | 3970 | */ |
| @@ -3699,7 +4013,7 @@ static long pmcraid_ioctl_driver( | |||
| 3699 | int rc = -ENOSYS; | 4013 | int rc = -ENOSYS; |
| 3700 | 4014 | ||
| 3701 | if (!access_ok(VERIFY_READ, user_buffer, _IOC_SIZE(cmd))) { | 4015 | if (!access_ok(VERIFY_READ, user_buffer, _IOC_SIZE(cmd))) { |
| 3702 | pmcraid_err("ioctl_driver: access fault in request buffer \n"); | 4016 | pmcraid_err("ioctl_driver: access fault in request buffer\n"); |
| 3703 | return -EFAULT; | 4017 | return -EFAULT; |
| 3704 | } | 4018 | } |
| 3705 | 4019 | ||
| @@ -3795,7 +4109,7 @@ static long pmcraid_chr_ioctl( | |||
| 3795 | return retval; | 4109 | return retval; |
| 3796 | } | 4110 | } |
| 3797 | 4111 | ||
| 3798 | pinstance = (struct pmcraid_instance *)filep->private_data; | 4112 | pinstance = filep->private_data; |
| 3799 | 4113 | ||
| 3800 | if (!pinstance) { | 4114 | if (!pinstance) { |
| 3801 | pmcraid_info("adapter instance is not found\n"); | 4115 | pmcraid_info("adapter instance is not found\n"); |
| @@ -4011,36 +4325,77 @@ static struct scsi_host_template pmcraid_host_template = { | |||
| 4011 | .proc_name = PMCRAID_DRIVER_NAME | 4325 | .proc_name = PMCRAID_DRIVER_NAME |
| 4012 | }; | 4326 | }; |
| 4013 | 4327 | ||
| 4014 | /** | 4328 | /* |
| 4015 | * pmcraid_isr_common - Common interrupt handler routine | 4329 | * pmcraid_isr_msix - implements MSI-X interrupt handling routine |
| 4016 | * | 4330 | * @irq: interrupt vector number |
| 4017 | * @pinstance: pointer to adapter instance | 4331 | * @dev_id: pointer hrrq_vector |
| 4018 | * @intrs: active interrupts (contents of ioa_host_interrupt register) | ||
| 4019 | * @hrrq_id: Host RRQ index | ||
| 4020 | * | 4332 | * |
| 4021 | * Return Value | 4333 | * Return Value |
| 4022 | * none | 4334 | * IRQ_HANDLED if interrupt is handled or IRQ_NONE if ignored |
| 4023 | */ | 4335 | */ |
| 4024 | static void pmcraid_isr_common( | 4336 | |
| 4025 | struct pmcraid_instance *pinstance, | 4337 | static irqreturn_t pmcraid_isr_msix(int irq, void *dev_id) |
| 4026 | u32 intrs, | ||
| 4027 | int hrrq_id | ||
| 4028 | ) | ||
| 4029 | { | 4338 | { |
| 4030 | u32 intrs_clear = | 4339 | struct pmcraid_isr_param *hrrq_vector; |
| 4031 | (intrs & INTRS_CRITICAL_OP_IN_PROGRESS) ? intrs | 4340 | struct pmcraid_instance *pinstance; |
| 4032 | : INTRS_HRRQ_VALID; | 4341 | unsigned long lock_flags; |
| 4033 | iowrite32(intrs_clear, | 4342 | u32 intrs_val; |
| 4034 | pinstance->int_regs.ioa_host_interrupt_clr_reg); | 4343 | int hrrq_id; |
| 4035 | intrs = ioread32(pinstance->int_regs.ioa_host_interrupt_reg); | 4344 | |
| 4345 | hrrq_vector = (struct pmcraid_isr_param *)dev_id; | ||
| 4346 | hrrq_id = hrrq_vector->hrrq_id; | ||
| 4347 | pinstance = hrrq_vector->drv_inst; | ||
| 4348 | |||
| 4349 | if (!hrrq_id) { | ||
| 4350 | /* Read the interrupt */ | ||
| 4351 | intrs_val = pmcraid_read_interrupts(pinstance); | ||
| 4352 | if (intrs_val && | ||
| 4353 | ((ioread32(pinstance->int_regs.host_ioa_interrupt_reg) | ||
| 4354 | & DOORBELL_INTR_MSIX_CLR) == 0)) { | ||
| 4355 | /* Any error interrupts including unit_check, | ||
| 4356 | * initiate IOA reset.In case of unit check indicate | ||
| 4357 | * to reset_sequence that IOA unit checked and prepare | ||
| 4358 | * for a dump during reset sequence | ||
| 4359 | */ | ||
| 4360 | if (intrs_val & PMCRAID_ERROR_INTERRUPTS) { | ||
| 4361 | if (intrs_val & INTRS_IOA_UNIT_CHECK) | ||
| 4362 | pinstance->ioa_unit_check = 1; | ||
| 4363 | |||
| 4364 | pmcraid_err("ISR: error interrupts: %x \ | ||
| 4365 | initiating reset\n", intrs_val); | ||
| 4366 | spin_lock_irqsave(pinstance->host->host_lock, | ||
| 4367 | lock_flags); | ||
| 4368 | pmcraid_initiate_reset(pinstance); | ||
| 4369 | spin_unlock_irqrestore( | ||
| 4370 | pinstance->host->host_lock, | ||
| 4371 | lock_flags); | ||
| 4372 | } | ||
| 4373 | /* If interrupt was as part of the ioa initialization, | ||
| 4374 | * clear it. Delete the timer and wakeup the | ||
| 4375 | * reset engine to proceed with reset sequence | ||
| 4376 | */ | ||
| 4377 | if (intrs_val & INTRS_TRANSITION_TO_OPERATIONAL) | ||
| 4378 | pmcraid_clr_trans_op(pinstance); | ||
| 4379 | |||
| 4380 | /* Clear the interrupt register by writing | ||
| 4381 | * to host to ioa doorbell. Once done | ||
| 4382 | * FW will clear the interrupt. | ||
| 4383 | */ | ||
| 4384 | iowrite32(DOORBELL_INTR_MSIX_CLR, | ||
| 4385 | pinstance->int_regs.host_ioa_interrupt_reg); | ||
| 4386 | ioread32(pinstance->int_regs.host_ioa_interrupt_reg); | ||
| 4387 | |||
| 4036 | 4388 | ||
| 4037 | /* hrrq valid bit was set, schedule tasklet to handle the response */ | 4389 | } |
| 4038 | if (intrs_clear == INTRS_HRRQ_VALID) | 4390 | } |
| 4039 | tasklet_schedule(&(pinstance->isr_tasklet[hrrq_id])); | 4391 | |
| 4392 | tasklet_schedule(&(pinstance->isr_tasklet[hrrq_id])); | ||
| 4393 | |||
| 4394 | return IRQ_HANDLED; | ||
| 4040 | } | 4395 | } |
| 4041 | 4396 | ||
| 4042 | /** | 4397 | /** |
| 4043 | * pmcraid_isr - implements interrupt handling routine | 4398 | * pmcraid_isr - implements legacy interrupt handling routine |
| 4044 | * | 4399 | * |
| 4045 | * @irq: interrupt vector number | 4400 | * @irq: interrupt vector number |
| 4046 | * @dev_id: pointer hrrq_vector | 4401 | * @dev_id: pointer hrrq_vector |
| @@ -4052,8 +4407,9 @@ static irqreturn_t pmcraid_isr(int irq, void *dev_id) | |||
| 4052 | { | 4407 | { |
| 4053 | struct pmcraid_isr_param *hrrq_vector; | 4408 | struct pmcraid_isr_param *hrrq_vector; |
| 4054 | struct pmcraid_instance *pinstance; | 4409 | struct pmcraid_instance *pinstance; |
| 4055 | unsigned long lock_flags; | ||
| 4056 | u32 intrs; | 4410 | u32 intrs; |
| 4411 | unsigned long lock_flags; | ||
| 4412 | int hrrq_id = 0; | ||
| 4057 | 4413 | ||
| 4058 | /* In case of legacy interrupt mode where interrupts are shared across | 4414 | /* In case of legacy interrupt mode where interrupts are shared across |
| 4059 | * isrs, it may be possible that the current interrupt is not from IOA | 4415 | * isrs, it may be possible that the current interrupt is not from IOA |
| @@ -4062,21 +4418,13 @@ static irqreturn_t pmcraid_isr(int irq, void *dev_id) | |||
| 4062 | printk(KERN_INFO "%s(): NULL host pointer\n", __func__); | 4418 | printk(KERN_INFO "%s(): NULL host pointer\n", __func__); |
| 4063 | return IRQ_NONE; | 4419 | return IRQ_NONE; |
| 4064 | } | 4420 | } |
| 4065 | |||
| 4066 | hrrq_vector = (struct pmcraid_isr_param *)dev_id; | 4421 | hrrq_vector = (struct pmcraid_isr_param *)dev_id; |
| 4067 | pinstance = hrrq_vector->drv_inst; | 4422 | pinstance = hrrq_vector->drv_inst; |
| 4068 | 4423 | ||
| 4069 | /* Acquire the lock (currently host_lock) while processing interrupts. | ||
| 4070 | * This interval is small as most of the response processing is done by | ||
| 4071 | * tasklet without the lock. | ||
| 4072 | */ | ||
| 4073 | spin_lock_irqsave(pinstance->host->host_lock, lock_flags); | ||
| 4074 | intrs = pmcraid_read_interrupts(pinstance); | 4424 | intrs = pmcraid_read_interrupts(pinstance); |
| 4075 | 4425 | ||
| 4076 | if (unlikely((intrs & PMCRAID_PCI_INTERRUPTS) == 0)) { | 4426 | if (unlikely((intrs & PMCRAID_PCI_INTERRUPTS) == 0)) |
| 4077 | spin_unlock_irqrestore(pinstance->host->host_lock, lock_flags); | ||
| 4078 | return IRQ_NONE; | 4427 | return IRQ_NONE; |
| 4079 | } | ||
| 4080 | 4428 | ||
| 4081 | /* Any error interrupts including unit_check, initiate IOA reset. | 4429 | /* Any error interrupts including unit_check, initiate IOA reset. |
| 4082 | * In case of unit check indicate to reset_sequence that IOA unit | 4430 | * In case of unit check indicate to reset_sequence that IOA unit |
| @@ -4091,13 +4439,28 @@ static irqreturn_t pmcraid_isr(int irq, void *dev_id) | |||
| 4091 | pinstance->int_regs.ioa_host_interrupt_clr_reg); | 4439 | pinstance->int_regs.ioa_host_interrupt_clr_reg); |
| 4092 | pmcraid_err("ISR: error interrupts: %x initiating reset\n", | 4440 | pmcraid_err("ISR: error interrupts: %x initiating reset\n", |
| 4093 | intrs); | 4441 | intrs); |
| 4094 | intrs = ioread32(pinstance->int_regs.ioa_host_interrupt_reg); | 4442 | intrs = ioread32( |
| 4443 | pinstance->int_regs.ioa_host_interrupt_clr_reg); | ||
| 4444 | spin_lock_irqsave(pinstance->host->host_lock, lock_flags); | ||
| 4095 | pmcraid_initiate_reset(pinstance); | 4445 | pmcraid_initiate_reset(pinstance); |
| 4446 | spin_unlock_irqrestore(pinstance->host->host_lock, lock_flags); | ||
| 4096 | } else { | 4447 | } else { |
| 4097 | pmcraid_isr_common(pinstance, intrs, hrrq_vector->hrrq_id); | 4448 | /* If interrupt was as part of the ioa initialization, |
| 4098 | } | 4449 | * clear. Delete the timer and wakeup the |
| 4450 | * reset engine to proceed with reset sequence | ||
| 4451 | */ | ||
| 4452 | if (intrs & INTRS_TRANSITION_TO_OPERATIONAL) { | ||
| 4453 | pmcraid_clr_trans_op(pinstance); | ||
| 4454 | } else { | ||
| 4455 | iowrite32(intrs, | ||
| 4456 | pinstance->int_regs.ioa_host_interrupt_clr_reg); | ||
| 4457 | ioread32( | ||
| 4458 | pinstance->int_regs.ioa_host_interrupt_clr_reg); | ||
| 4099 | 4459 | ||
| 4100 | spin_unlock_irqrestore(pinstance->host->host_lock, lock_flags); | 4460 | tasklet_schedule( |
| 4461 | &(pinstance->isr_tasklet[hrrq_id])); | ||
| 4462 | } | ||
| 4463 | } | ||
| 4101 | 4464 | ||
| 4102 | return IRQ_HANDLED; | 4465 | return IRQ_HANDLED; |
| 4103 | } | 4466 | } |
| @@ -4120,6 +4483,7 @@ static void pmcraid_worker_function(struct work_struct *workp) | |||
| 4120 | struct scsi_device *sdev; | 4483 | struct scsi_device *sdev; |
| 4121 | unsigned long lock_flags; | 4484 | unsigned long lock_flags; |
| 4122 | unsigned long host_lock_flags; | 4485 | unsigned long host_lock_flags; |
| 4486 | u16 fw_version; | ||
| 4123 | u8 bus, target, lun; | 4487 | u8 bus, target, lun; |
| 4124 | 4488 | ||
| 4125 | pinstance = container_of(workp, struct pmcraid_instance, worker_q); | 4489 | pinstance = container_of(workp, struct pmcraid_instance, worker_q); |
| @@ -4127,6 +4491,8 @@ static void pmcraid_worker_function(struct work_struct *workp) | |||
| 4127 | if (!atomic_read(&pinstance->expose_resources)) | 4491 | if (!atomic_read(&pinstance->expose_resources)) |
| 4128 | return; | 4492 | return; |
| 4129 | 4493 | ||
| 4494 | fw_version = be16_to_cpu(pinstance->inq_data->fw_version); | ||
| 4495 | |||
| 4130 | spin_lock_irqsave(&pinstance->resource_lock, lock_flags); | 4496 | spin_lock_irqsave(&pinstance->resource_lock, lock_flags); |
| 4131 | list_for_each_entry_safe(res, temp, &pinstance->used_res_q, queue) { | 4497 | list_for_each_entry_safe(res, temp, &pinstance->used_res_q, queue) { |
| 4132 | 4498 | ||
| @@ -4166,12 +4532,16 @@ static void pmcraid_worker_function(struct work_struct *workp) | |||
| 4166 | 4532 | ||
| 4167 | if (res->change_detected == RES_CHANGE_ADD) { | 4533 | if (res->change_detected == RES_CHANGE_ADD) { |
| 4168 | 4534 | ||
| 4169 | if (!pmcraid_expose_resource(&res->cfg_entry)) | 4535 | if (!pmcraid_expose_resource(fw_version, |
| 4536 | &res->cfg_entry)) | ||
| 4170 | continue; | 4537 | continue; |
| 4171 | 4538 | ||
| 4172 | if (RES_IS_VSET(res->cfg_entry)) { | 4539 | if (RES_IS_VSET(res->cfg_entry)) { |
| 4173 | bus = PMCRAID_VSET_BUS_ID; | 4540 | bus = PMCRAID_VSET_BUS_ID; |
| 4174 | target = res->cfg_entry.unique_flags1; | 4541 | if (fw_version <= PMCRAID_FW_VERSION_1) |
| 4542 | target = res->cfg_entry.unique_flags1; | ||
| 4543 | else | ||
| 4544 | target = res->cfg_entry.array_id & 0xFF; | ||
| 4175 | lun = PMCRAID_VSET_LUN_ID; | 4545 | lun = PMCRAID_VSET_LUN_ID; |
| 4176 | } else { | 4546 | } else { |
| 4177 | bus = PMCRAID_PHYS_BUS_ID; | 4547 | bus = PMCRAID_PHYS_BUS_ID; |
| @@ -4201,7 +4571,7 @@ static void pmcraid_worker_function(struct work_struct *workp) | |||
| 4201 | * Return Value | 4571 | * Return Value |
| 4202 | * None | 4572 | * None |
| 4203 | */ | 4573 | */ |
| 4204 | void pmcraid_tasklet_function(unsigned long instance) | 4574 | static void pmcraid_tasklet_function(unsigned long instance) |
| 4205 | { | 4575 | { |
| 4206 | struct pmcraid_isr_param *hrrq_vector; | 4576 | struct pmcraid_isr_param *hrrq_vector; |
| 4207 | struct pmcraid_instance *pinstance; | 4577 | struct pmcraid_instance *pinstance; |
| @@ -4210,35 +4580,12 @@ void pmcraid_tasklet_function(unsigned long instance) | |||
| 4210 | unsigned long host_lock_flags; | 4580 | unsigned long host_lock_flags; |
| 4211 | spinlock_t *lockp; /* hrrq buffer lock */ | 4581 | spinlock_t *lockp; /* hrrq buffer lock */ |
| 4212 | int id; | 4582 | int id; |
| 4213 | u32 intrs; | ||
| 4214 | __le32 resp; | 4583 | __le32 resp; |
| 4215 | 4584 | ||
| 4216 | hrrq_vector = (struct pmcraid_isr_param *)instance; | 4585 | hrrq_vector = (struct pmcraid_isr_param *)instance; |
| 4217 | pinstance = hrrq_vector->drv_inst; | 4586 | pinstance = hrrq_vector->drv_inst; |
| 4218 | id = hrrq_vector->hrrq_id; | 4587 | id = hrrq_vector->hrrq_id; |
| 4219 | lockp = &(pinstance->hrrq_lock[id]); | 4588 | lockp = &(pinstance->hrrq_lock[id]); |
| 4220 | intrs = pmcraid_read_interrupts(pinstance); | ||
| 4221 | |||
| 4222 | /* If interrupts was as part of the ioa initialization, clear and mask | ||
| 4223 | * it. Delete the timer and wakeup the reset engine to proceed with | ||
| 4224 | * reset sequence | ||
| 4225 | */ | ||
| 4226 | if (intrs & INTRS_TRANSITION_TO_OPERATIONAL) { | ||
| 4227 | iowrite32(INTRS_TRANSITION_TO_OPERATIONAL, | ||
| 4228 | pinstance->int_regs.ioa_host_interrupt_mask_reg); | ||
| 4229 | iowrite32(INTRS_TRANSITION_TO_OPERATIONAL, | ||
| 4230 | pinstance->int_regs.ioa_host_interrupt_clr_reg); | ||
| 4231 | |||
| 4232 | if (pinstance->reset_cmd != NULL) { | ||
| 4233 | del_timer(&pinstance->reset_cmd->timer); | ||
| 4234 | spin_lock_irqsave(pinstance->host->host_lock, | ||
| 4235 | host_lock_flags); | ||
| 4236 | pinstance->reset_cmd->cmd_done(pinstance->reset_cmd); | ||
| 4237 | spin_unlock_irqrestore(pinstance->host->host_lock, | ||
| 4238 | host_lock_flags); | ||
| 4239 | } | ||
| 4240 | return; | ||
| 4241 | } | ||
| 4242 | 4589 | ||
| 4243 | /* loop through each of the commands responded by IOA. Each HRRQ buf is | 4590 | /* loop through each of the commands responded by IOA. Each HRRQ buf is |
| 4244 | * protected by its own lock. Traversals must be done within this lock | 4591 | * protected by its own lock. Traversals must be done within this lock |
| @@ -4256,27 +4603,6 @@ void pmcraid_tasklet_function(unsigned long instance) | |||
| 4256 | int cmd_index = resp >> 2; | 4603 | int cmd_index = resp >> 2; |
| 4257 | struct pmcraid_cmd *cmd = NULL; | 4604 | struct pmcraid_cmd *cmd = NULL; |
| 4258 | 4605 | ||
| 4259 | if (cmd_index < PMCRAID_MAX_CMD) { | ||
| 4260 | cmd = pinstance->cmd_list[cmd_index]; | ||
| 4261 | } else { | ||
| 4262 | /* In case of invalid response handle, initiate IOA | ||
| 4263 | * reset sequence. | ||
| 4264 | */ | ||
| 4265 | spin_unlock_irqrestore(lockp, hrrq_lock_flags); | ||
| 4266 | |||
| 4267 | pmcraid_err("Invalid response %d initiating reset\n", | ||
| 4268 | cmd_index); | ||
| 4269 | |||
| 4270 | spin_lock_irqsave(pinstance->host->host_lock, | ||
| 4271 | host_lock_flags); | ||
| 4272 | pmcraid_initiate_reset(pinstance); | ||
| 4273 | spin_unlock_irqrestore(pinstance->host->host_lock, | ||
| 4274 | host_lock_flags); | ||
| 4275 | |||
| 4276 | spin_lock_irqsave(lockp, hrrq_lock_flags); | ||
| 4277 | break; | ||
| 4278 | } | ||
| 4279 | |||
| 4280 | if (pinstance->hrrq_curr[id] < pinstance->hrrq_end[id]) { | 4606 | if (pinstance->hrrq_curr[id] < pinstance->hrrq_end[id]) { |
| 4281 | pinstance->hrrq_curr[id]++; | 4607 | pinstance->hrrq_curr[id]++; |
| 4282 | } else { | 4608 | } else { |
| @@ -4284,6 +4610,14 @@ void pmcraid_tasklet_function(unsigned long instance) | |||
| 4284 | pinstance->host_toggle_bit[id] ^= 1u; | 4610 | pinstance->host_toggle_bit[id] ^= 1u; |
| 4285 | } | 4611 | } |
| 4286 | 4612 | ||
| 4613 | if (cmd_index >= PMCRAID_MAX_CMD) { | ||
| 4614 | /* In case of invalid response handle, log message */ | ||
| 4615 | pmcraid_err("Invalid response handle %d\n", cmd_index); | ||
| 4616 | resp = le32_to_cpu(*(pinstance->hrrq_curr[id])); | ||
| 4617 | continue; | ||
| 4618 | } | ||
| 4619 | |||
| 4620 | cmd = pinstance->cmd_list[cmd_index]; | ||
| 4287 | spin_unlock_irqrestore(lockp, hrrq_lock_flags); | 4621 | spin_unlock_irqrestore(lockp, hrrq_lock_flags); |
| 4288 | 4622 | ||
| 4289 | spin_lock_irqsave(&pinstance->pending_pool_lock, | 4623 | spin_lock_irqsave(&pinstance->pending_pool_lock, |
| @@ -4324,7 +4658,16 @@ void pmcraid_tasklet_function(unsigned long instance) | |||
| 4324 | static | 4658 | static |
| 4325 | void pmcraid_unregister_interrupt_handler(struct pmcraid_instance *pinstance) | 4659 | void pmcraid_unregister_interrupt_handler(struct pmcraid_instance *pinstance) |
| 4326 | { | 4660 | { |
| 4327 | free_irq(pinstance->pdev->irq, &(pinstance->hrrq_vector[0])); | 4661 | int i; |
| 4662 | |||
| 4663 | for (i = 0; i < pinstance->num_hrrq; i++) | ||
| 4664 | free_irq(pinstance->hrrq_vector[i].vector, | ||
| 4665 | &(pinstance->hrrq_vector[i])); | ||
| 4666 | |||
| 4667 | if (pinstance->interrupt_mode) { | ||
| 4668 | pci_disable_msix(pinstance->pdev); | ||
| 4669 | pinstance->interrupt_mode = 0; | ||
| 4670 | } | ||
| 4328 | } | 4671 | } |
| 4329 | 4672 | ||
| 4330 | /** | 4673 | /** |
| @@ -4337,14 +4680,70 @@ void pmcraid_unregister_interrupt_handler(struct pmcraid_instance *pinstance) | |||
| 4337 | static int | 4680 | static int |
| 4338 | pmcraid_register_interrupt_handler(struct pmcraid_instance *pinstance) | 4681 | pmcraid_register_interrupt_handler(struct pmcraid_instance *pinstance) |
| 4339 | { | 4682 | { |
| 4683 | int rc; | ||
| 4340 | struct pci_dev *pdev = pinstance->pdev; | 4684 | struct pci_dev *pdev = pinstance->pdev; |
| 4341 | 4685 | ||
| 4686 | if (pci_find_capability(pdev, PCI_CAP_ID_MSIX)) { | ||
| 4687 | int num_hrrq = PMCRAID_NUM_MSIX_VECTORS; | ||
| 4688 | struct msix_entry entries[PMCRAID_NUM_MSIX_VECTORS]; | ||
| 4689 | int i; | ||
| 4690 | for (i = 0; i < PMCRAID_NUM_MSIX_VECTORS; i++) | ||
| 4691 | entries[i].entry = i; | ||
| 4692 | |||
| 4693 | rc = pci_enable_msix(pdev, entries, num_hrrq); | ||
| 4694 | if (rc < 0) | ||
| 4695 | goto pmcraid_isr_legacy; | ||
| 4696 | |||
| 4697 | /* Check how many MSIX vectors are allocated and register | ||
| 4698 | * msi-x handlers for each of them giving appropriate buffer | ||
| 4699 | */ | ||
| 4700 | if (rc > 0) { | ||
| 4701 | num_hrrq = rc; | ||
| 4702 | if (pci_enable_msix(pdev, entries, num_hrrq)) | ||
| 4703 | goto pmcraid_isr_legacy; | ||
| 4704 | } | ||
| 4705 | |||
| 4706 | for (i = 0; i < num_hrrq; i++) { | ||
| 4707 | pinstance->hrrq_vector[i].hrrq_id = i; | ||
| 4708 | pinstance->hrrq_vector[i].drv_inst = pinstance; | ||
| 4709 | pinstance->hrrq_vector[i].vector = entries[i].vector; | ||
| 4710 | rc = request_irq(pinstance->hrrq_vector[i].vector, | ||
| 4711 | pmcraid_isr_msix, 0, | ||
| 4712 | PMCRAID_DRIVER_NAME, | ||
| 4713 | &(pinstance->hrrq_vector[i])); | ||
| 4714 | |||
| 4715 | if (rc) { | ||
| 4716 | int j; | ||
| 4717 | for (j = 0; j < i; j++) | ||
| 4718 | free_irq(entries[j].vector, | ||
| 4719 | &(pinstance->hrrq_vector[j])); | ||
| 4720 | pci_disable_msix(pdev); | ||
| 4721 | goto pmcraid_isr_legacy; | ||
| 4722 | } | ||
| 4723 | } | ||
| 4724 | |||
| 4725 | pinstance->num_hrrq = num_hrrq; | ||
| 4726 | pinstance->interrupt_mode = 1; | ||
| 4727 | iowrite32(DOORBELL_INTR_MODE_MSIX, | ||
| 4728 | pinstance->int_regs.host_ioa_interrupt_reg); | ||
| 4729 | ioread32(pinstance->int_regs.host_ioa_interrupt_reg); | ||
| 4730 | goto pmcraid_isr_out; | ||
| 4731 | } | ||
| 4732 | |||
| 4733 | pmcraid_isr_legacy: | ||
| 4734 | /* If MSI-X registration failed fallback to legacy mode, where | ||
| 4735 | * only one hrrq entry will be used | ||
| 4736 | */ | ||
| 4342 | pinstance->hrrq_vector[0].hrrq_id = 0; | 4737 | pinstance->hrrq_vector[0].hrrq_id = 0; |
| 4343 | pinstance->hrrq_vector[0].drv_inst = pinstance; | 4738 | pinstance->hrrq_vector[0].drv_inst = pinstance; |
| 4344 | pinstance->hrrq_vector[0].vector = 0; | 4739 | pinstance->hrrq_vector[0].vector = pdev->irq; |
| 4345 | pinstance->num_hrrq = 1; | 4740 | pinstance->num_hrrq = 1; |
| 4346 | return request_irq(pdev->irq, pmcraid_isr, IRQF_SHARED, | 4741 | rc = 0; |
| 4347 | PMCRAID_DRIVER_NAME, &pinstance->hrrq_vector[0]); | 4742 | |
| 4743 | rc = request_irq(pdev->irq, pmcraid_isr, IRQF_SHARED, | ||
| 4744 | PMCRAID_DRIVER_NAME, &pinstance->hrrq_vector[0]); | ||
| 4745 | pmcraid_isr_out: | ||
| 4746 | return rc; | ||
| 4348 | } | 4747 | } |
| 4349 | 4748 | ||
| 4350 | /** | 4749 | /** |
| @@ -4516,12 +4915,11 @@ pmcraid_release_host_rrqs(struct pmcraid_instance *pinstance, int maxindex) | |||
| 4516 | static int __devinit | 4915 | static int __devinit |
| 4517 | pmcraid_allocate_host_rrqs(struct pmcraid_instance *pinstance) | 4916 | pmcraid_allocate_host_rrqs(struct pmcraid_instance *pinstance) |
| 4518 | { | 4917 | { |
| 4519 | int i; | 4918 | int i, buffer_size; |
| 4520 | int buf_count = PMCRAID_MAX_CMD / pinstance->num_hrrq; | ||
| 4521 | 4919 | ||
| 4522 | for (i = 0; i < pinstance->num_hrrq; i++) { | 4920 | buffer_size = HRRQ_ENTRY_SIZE * PMCRAID_MAX_CMD; |
| 4523 | int buffer_size = HRRQ_ENTRY_SIZE * buf_count; | ||
| 4524 | 4921 | ||
| 4922 | for (i = 0; i < pinstance->num_hrrq; i++) { | ||
| 4525 | pinstance->hrrq_start[i] = | 4923 | pinstance->hrrq_start[i] = |
| 4526 | pci_alloc_consistent( | 4924 | pci_alloc_consistent( |
| 4527 | pinstance->pdev, | 4925 | pinstance->pdev, |
| @@ -4529,7 +4927,8 @@ pmcraid_allocate_host_rrqs(struct pmcraid_instance *pinstance) | |||
| 4529 | &(pinstance->hrrq_start_bus_addr[i])); | 4927 | &(pinstance->hrrq_start_bus_addr[i])); |
| 4530 | 4928 | ||
| 4531 | if (pinstance->hrrq_start[i] == 0) { | 4929 | if (pinstance->hrrq_start[i] == 0) { |
| 4532 | pmcraid_err("could not allocate host rrq: %d\n", i); | 4930 | pmcraid_err("pci_alloc failed for hrrq vector : %d\n", |
| 4931 | i); | ||
| 4533 | pmcraid_release_host_rrqs(pinstance, i); | 4932 | pmcraid_release_host_rrqs(pinstance, i); |
| 4534 | return -ENOMEM; | 4933 | return -ENOMEM; |
| 4535 | } | 4934 | } |
| @@ -4537,7 +4936,7 @@ pmcraid_allocate_host_rrqs(struct pmcraid_instance *pinstance) | |||
| 4537 | memset(pinstance->hrrq_start[i], 0, buffer_size); | 4936 | memset(pinstance->hrrq_start[i], 0, buffer_size); |
| 4538 | pinstance->hrrq_curr[i] = pinstance->hrrq_start[i]; | 4937 | pinstance->hrrq_curr[i] = pinstance->hrrq_start[i]; |
| 4539 | pinstance->hrrq_end[i] = | 4938 | pinstance->hrrq_end[i] = |
| 4540 | pinstance->hrrq_start[i] + buf_count - 1; | 4939 | pinstance->hrrq_start[i] + PMCRAID_MAX_CMD - 1; |
| 4541 | pinstance->host_toggle_bit[i] = 1; | 4940 | pinstance->host_toggle_bit[i] = 1; |
| 4542 | spin_lock_init(&pinstance->hrrq_lock[i]); | 4941 | spin_lock_init(&pinstance->hrrq_lock[i]); |
| 4543 | } | 4942 | } |
| @@ -4557,7 +4956,7 @@ static void pmcraid_release_hcams(struct pmcraid_instance *pinstance) | |||
| 4557 | if (pinstance->ccn.msg != NULL) { | 4956 | if (pinstance->ccn.msg != NULL) { |
| 4558 | pci_free_consistent(pinstance->pdev, | 4957 | pci_free_consistent(pinstance->pdev, |
| 4559 | PMCRAID_AEN_HDR_SIZE + | 4958 | PMCRAID_AEN_HDR_SIZE + |
| 4560 | sizeof(struct pmcraid_hcam_ccn), | 4959 | sizeof(struct pmcraid_hcam_ccn_ext), |
| 4561 | pinstance->ccn.msg, | 4960 | pinstance->ccn.msg, |
| 4562 | pinstance->ccn.baddr); | 4961 | pinstance->ccn.baddr); |
| 4563 | 4962 | ||
| @@ -4591,7 +4990,7 @@ static int pmcraid_allocate_hcams(struct pmcraid_instance *pinstance) | |||
| 4591 | pinstance->ccn.msg = pci_alloc_consistent( | 4990 | pinstance->ccn.msg = pci_alloc_consistent( |
| 4592 | pinstance->pdev, | 4991 | pinstance->pdev, |
| 4593 | PMCRAID_AEN_HDR_SIZE + | 4992 | PMCRAID_AEN_HDR_SIZE + |
| 4594 | sizeof(struct pmcraid_hcam_ccn), | 4993 | sizeof(struct pmcraid_hcam_ccn_ext), |
| 4595 | &(pinstance->ccn.baddr)); | 4994 | &(pinstance->ccn.baddr)); |
| 4596 | 4995 | ||
| 4597 | pinstance->ldn.msg = pci_alloc_consistent( | 4996 | pinstance->ldn.msg = pci_alloc_consistent( |
| @@ -4724,6 +5123,32 @@ static void pmcraid_kill_tasklets(struct pmcraid_instance *pinstance) | |||
| 4724 | } | 5123 | } |
| 4725 | 5124 | ||
| 4726 | /** | 5125 | /** |
| 5126 | * pmcraid_release_buffers - release per-adapter buffers allocated | ||
| 5127 | * | ||
| 5128 | * @pinstance: pointer to adapter soft state | ||
| 5129 | * | ||
| 5130 | * Return Value | ||
| 5131 | * none | ||
| 5132 | */ | ||
| 5133 | static void pmcraid_release_buffers(struct pmcraid_instance *pinstance) | ||
| 5134 | { | ||
| 5135 | pmcraid_release_config_buffers(pinstance); | ||
| 5136 | pmcraid_release_control_blocks(pinstance, PMCRAID_MAX_CMD); | ||
| 5137 | pmcraid_release_cmd_blocks(pinstance, PMCRAID_MAX_CMD); | ||
| 5138 | pmcraid_release_host_rrqs(pinstance, pinstance->num_hrrq); | ||
| 5139 | |||
| 5140 | if (pinstance->inq_data != NULL) { | ||
| 5141 | pci_free_consistent(pinstance->pdev, | ||
| 5142 | sizeof(struct pmcraid_inquiry_data), | ||
| 5143 | pinstance->inq_data, | ||
| 5144 | pinstance->inq_data_baddr); | ||
| 5145 | |||
| 5146 | pinstance->inq_data = NULL; | ||
| 5147 | pinstance->inq_data_baddr = 0; | ||
| 5148 | } | ||
| 5149 | } | ||
| 5150 | |||
| 5151 | /** | ||
| 4727 | * pmcraid_init_buffers - allocates memory and initializes various structures | 5152 | * pmcraid_init_buffers - allocates memory and initializes various structures |
| 4728 | * @pinstance: pointer to per adapter instance structure | 5153 | * @pinstance: pointer to per adapter instance structure |
| 4729 | * | 5154 | * |
| @@ -4753,20 +5178,32 @@ static int __devinit pmcraid_init_buffers(struct pmcraid_instance *pinstance) | |||
| 4753 | } | 5178 | } |
| 4754 | 5179 | ||
| 4755 | if (pmcraid_allocate_cmd_blocks(pinstance)) { | 5180 | if (pmcraid_allocate_cmd_blocks(pinstance)) { |
| 4756 | pmcraid_err("couldn't allocate memory for cmd blocks \n"); | 5181 | pmcraid_err("couldn't allocate memory for cmd blocks\n"); |
| 4757 | pmcraid_release_config_buffers(pinstance); | 5182 | pmcraid_release_config_buffers(pinstance); |
| 4758 | pmcraid_release_host_rrqs(pinstance, pinstance->num_hrrq); | 5183 | pmcraid_release_host_rrqs(pinstance, pinstance->num_hrrq); |
| 4759 | return -ENOMEM; | 5184 | return -ENOMEM; |
| 4760 | } | 5185 | } |
| 4761 | 5186 | ||
| 4762 | if (pmcraid_allocate_control_blocks(pinstance)) { | 5187 | if (pmcraid_allocate_control_blocks(pinstance)) { |
| 4763 | pmcraid_err("couldn't allocate memory control blocks \n"); | 5188 | pmcraid_err("couldn't allocate memory control blocks\n"); |
| 4764 | pmcraid_release_config_buffers(pinstance); | 5189 | pmcraid_release_config_buffers(pinstance); |
| 4765 | pmcraid_release_cmd_blocks(pinstance, PMCRAID_MAX_CMD); | 5190 | pmcraid_release_cmd_blocks(pinstance, PMCRAID_MAX_CMD); |
| 4766 | pmcraid_release_host_rrqs(pinstance, pinstance->num_hrrq); | 5191 | pmcraid_release_host_rrqs(pinstance, pinstance->num_hrrq); |
| 4767 | return -ENOMEM; | 5192 | return -ENOMEM; |
| 4768 | } | 5193 | } |
| 4769 | 5194 | ||
| 5195 | /* allocate DMAable memory for page D0 INQUIRY buffer */ | ||
| 5196 | pinstance->inq_data = pci_alloc_consistent( | ||
| 5197 | pinstance->pdev, | ||
| 5198 | sizeof(struct pmcraid_inquiry_data), | ||
| 5199 | &pinstance->inq_data_baddr); | ||
| 5200 | |||
| 5201 | if (pinstance->inq_data == NULL) { | ||
| 5202 | pmcraid_err("couldn't allocate DMA memory for INQUIRY\n"); | ||
| 5203 | pmcraid_release_buffers(pinstance); | ||
| 5204 | return -ENOMEM; | ||
| 5205 | } | ||
| 5206 | |||
| 4770 | /* Initialize all the command blocks and add them to free pool. No | 5207 | /* Initialize all the command blocks and add them to free pool. No |
| 4771 | * need to lock (free_pool_lock) as this is done in initialization | 5208 | * need to lock (free_pool_lock) as this is done in initialization |
| 4772 | * itself | 5209 | * itself |
| @@ -4785,7 +5222,7 @@ static int __devinit pmcraid_init_buffers(struct pmcraid_instance *pinstance) | |||
| 4785 | * pmcraid_reinit_buffers - resets various buffer pointers | 5222 | * pmcraid_reinit_buffers - resets various buffer pointers |
| 4786 | * @pinstance: pointer to adapter instance | 5223 | * @pinstance: pointer to adapter instance |
| 4787 | * Return value | 5224 | * Return value |
| 4788 | * none | 5225 | * none |
| 4789 | */ | 5226 | */ |
| 4790 | static void pmcraid_reinit_buffers(struct pmcraid_instance *pinstance) | 5227 | static void pmcraid_reinit_buffers(struct pmcraid_instance *pinstance) |
| 4791 | { | 5228 | { |
| @@ -4836,6 +5273,8 @@ static int __devinit pmcraid_init_instance( | |||
| 4836 | mapped_pci_addr + chip_cfg->ioa_host_intr; | 5273 | mapped_pci_addr + chip_cfg->ioa_host_intr; |
| 4837 | pint_regs->ioa_host_interrupt_clr_reg = | 5274 | pint_regs->ioa_host_interrupt_clr_reg = |
| 4838 | mapped_pci_addr + chip_cfg->ioa_host_intr_clr; | 5275 | mapped_pci_addr + chip_cfg->ioa_host_intr_clr; |
| 5276 | pint_regs->ioa_host_msix_interrupt_reg = | ||
| 5277 | mapped_pci_addr + chip_cfg->ioa_host_msix_intr; | ||
| 4839 | pint_regs->host_ioa_interrupt_reg = | 5278 | pint_regs->host_ioa_interrupt_reg = |
| 4840 | mapped_pci_addr + chip_cfg->host_ioa_intr; | 5279 | mapped_pci_addr + chip_cfg->host_ioa_intr; |
| 4841 | pint_regs->host_ioa_interrupt_clr_reg = | 5280 | pint_regs->host_ioa_interrupt_clr_reg = |
| @@ -4858,6 +5297,7 @@ static int __devinit pmcraid_init_instance( | |||
| 4858 | init_waitqueue_head(&pinstance->reset_wait_q); | 5297 | init_waitqueue_head(&pinstance->reset_wait_q); |
| 4859 | 5298 | ||
| 4860 | atomic_set(&pinstance->outstanding_cmds, 0); | 5299 | atomic_set(&pinstance->outstanding_cmds, 0); |
| 5300 | atomic_set(&pinstance->last_message_id, 0); | ||
| 4861 | atomic_set(&pinstance->expose_resources, 0); | 5301 | atomic_set(&pinstance->expose_resources, 0); |
| 4862 | 5302 | ||
| 4863 | INIT_LIST_HEAD(&pinstance->free_res_q); | 5303 | INIT_LIST_HEAD(&pinstance->free_res_q); |
| @@ -4883,23 +5323,6 @@ static int __devinit pmcraid_init_instance( | |||
| 4883 | } | 5323 | } |
| 4884 | 5324 | ||
| 4885 | /** | 5325 | /** |
| 4886 | * pmcraid_release_buffers - release per-adapter buffers allocated | ||
| 4887 | * | ||
| 4888 | * @pinstance: pointer to adapter soft state | ||
| 4889 | * | ||
| 4890 | * Return Value | ||
| 4891 | * none | ||
| 4892 | */ | ||
| 4893 | static void pmcraid_release_buffers(struct pmcraid_instance *pinstance) | ||
| 4894 | { | ||
| 4895 | pmcraid_release_config_buffers(pinstance); | ||
| 4896 | pmcraid_release_control_blocks(pinstance, PMCRAID_MAX_CMD); | ||
| 4897 | pmcraid_release_cmd_blocks(pinstance, PMCRAID_MAX_CMD); | ||
| 4898 | pmcraid_release_host_rrqs(pinstance, pinstance->num_hrrq); | ||
| 4899 | |||
| 4900 | } | ||
| 4901 | |||
| 4902 | /** | ||
| 4903 | * pmcraid_shutdown - shutdown adapter controller. | 5326 | * pmcraid_shutdown - shutdown adapter controller. |
| 4904 | * @pdev: pci device struct | 5327 | * @pdev: pci device struct |
| 4905 | * | 5328 | * |
| @@ -4958,7 +5381,7 @@ static int pmcraid_setup_chrdev(struct pmcraid_instance *pinstance) | |||
| 4958 | pmcraid_release_minor(minor); | 5381 | pmcraid_release_minor(minor); |
| 4959 | else | 5382 | else |
| 4960 | device_create(pmcraid_class, NULL, MKDEV(pmcraid_major, minor), | 5383 | device_create(pmcraid_class, NULL, MKDEV(pmcraid_major, minor), |
| 4961 | NULL, "pmcsas%u", minor); | 5384 | NULL, "%s%u", PMCRAID_DEVFILE, minor); |
| 4962 | return error; | 5385 | return error; |
| 4963 | } | 5386 | } |
| 4964 | 5387 | ||
| @@ -5050,7 +5473,6 @@ static int pmcraid_resume(struct pci_dev *pdev) | |||
| 5050 | struct pmcraid_instance *pinstance = pci_get_drvdata(pdev); | 5473 | struct pmcraid_instance *pinstance = pci_get_drvdata(pdev); |
| 5051 | struct Scsi_Host *host = pinstance->host; | 5474 | struct Scsi_Host *host = pinstance->host; |
| 5052 | int rc; | 5475 | int rc; |
| 5053 | int hrrqs; | ||
| 5054 | 5476 | ||
| 5055 | pci_set_power_state(pdev, PCI_D0); | 5477 | pci_set_power_state(pdev, PCI_D0); |
| 5056 | pci_enable_wake(pdev, PCI_D0, 0); | 5478 | pci_enable_wake(pdev, PCI_D0, 0); |
| @@ -5077,8 +5499,8 @@ static int pmcraid_resume(struct pci_dev *pdev) | |||
| 5077 | goto disable_device; | 5499 | goto disable_device; |
| 5078 | } | 5500 | } |
| 5079 | 5501 | ||
| 5502 | pmcraid_disable_interrupts(pinstance, ~0); | ||
| 5080 | atomic_set(&pinstance->outstanding_cmds, 0); | 5503 | atomic_set(&pinstance->outstanding_cmds, 0); |
| 5081 | hrrqs = pinstance->num_hrrq; | ||
| 5082 | rc = pmcraid_register_interrupt_handler(pinstance); | 5504 | rc = pmcraid_register_interrupt_handler(pinstance); |
| 5083 | 5505 | ||
| 5084 | if (rc) { | 5506 | if (rc) { |
| @@ -5100,7 +5522,7 @@ static int pmcraid_resume(struct pci_dev *pdev) | |||
| 5100 | * state. | 5522 | * state. |
| 5101 | */ | 5523 | */ |
| 5102 | if (pmcraid_reset_bringup(pinstance)) { | 5524 | if (pmcraid_reset_bringup(pinstance)) { |
| 5103 | dev_err(&pdev->dev, "couldn't initialize IOA \n"); | 5525 | dev_err(&pdev->dev, "couldn't initialize IOA\n"); |
| 5104 | rc = -ENODEV; | 5526 | rc = -ENODEV; |
| 5105 | goto release_tasklets; | 5527 | goto release_tasklets; |
| 5106 | } | 5528 | } |
| @@ -5108,6 +5530,7 @@ static int pmcraid_resume(struct pci_dev *pdev) | |||
| 5108 | return 0; | 5530 | return 0; |
| 5109 | 5531 | ||
| 5110 | release_tasklets: | 5532 | release_tasklets: |
| 5533 | pmcraid_disable_interrupts(pinstance, ~0); | ||
| 5111 | pmcraid_kill_tasklets(pinstance); | 5534 | pmcraid_kill_tasklets(pinstance); |
| 5112 | pmcraid_unregister_interrupt_handler(pinstance); | 5535 | pmcraid_unregister_interrupt_handler(pinstance); |
| 5113 | 5536 | ||
| @@ -5129,7 +5552,7 @@ disable_device: | |||
| 5129 | 5552 | ||
| 5130 | /** | 5553 | /** |
| 5131 | * pmcraid_complete_ioa_reset - Called by either timer or tasklet during | 5554 | * pmcraid_complete_ioa_reset - Called by either timer or tasklet during |
| 5132 | * completion of the ioa reset | 5555 | * completion of the ioa reset |
| 5133 | * @cmd: pointer to reset command block | 5556 | * @cmd: pointer to reset command block |
| 5134 | */ | 5557 | */ |
| 5135 | static void pmcraid_complete_ioa_reset(struct pmcraid_cmd *cmd) | 5558 | static void pmcraid_complete_ioa_reset(struct pmcraid_cmd *cmd) |
| @@ -5204,11 +5627,14 @@ static void pmcraid_init_res_table(struct pmcraid_cmd *cmd) | |||
| 5204 | struct pmcraid_config_table_entry *cfgte; | 5627 | struct pmcraid_config_table_entry *cfgte; |
| 5205 | unsigned long lock_flags; | 5628 | unsigned long lock_flags; |
| 5206 | int found, rc, i; | 5629 | int found, rc, i; |
| 5630 | u16 fw_version; | ||
| 5207 | LIST_HEAD(old_res); | 5631 | LIST_HEAD(old_res); |
| 5208 | 5632 | ||
| 5209 | if (pinstance->cfg_table->flags & MICROCODE_UPDATE_REQUIRED) | 5633 | if (pinstance->cfg_table->flags & MICROCODE_UPDATE_REQUIRED) |
| 5210 | pmcraid_err("IOA requires microcode download\n"); | 5634 | pmcraid_err("IOA requires microcode download\n"); |
| 5211 | 5635 | ||
| 5636 | fw_version = be16_to_cpu(pinstance->inq_data->fw_version); | ||
| 5637 | |||
| 5212 | /* resource list is protected by pinstance->resource_lock. | 5638 | /* resource list is protected by pinstance->resource_lock. |
| 5213 | * init_res_table can be called from probe (user-thread) or runtime | 5639 | * init_res_table can be called from probe (user-thread) or runtime |
| 5214 | * reset (timer/tasklet) | 5640 | * reset (timer/tasklet) |
| @@ -5219,9 +5645,14 @@ static void pmcraid_init_res_table(struct pmcraid_cmd *cmd) | |||
| 5219 | list_move_tail(&res->queue, &old_res); | 5645 | list_move_tail(&res->queue, &old_res); |
| 5220 | 5646 | ||
| 5221 | for (i = 0; i < pinstance->cfg_table->num_entries; i++) { | 5647 | for (i = 0; i < pinstance->cfg_table->num_entries; i++) { |
| 5222 | cfgte = &pinstance->cfg_table->entries[i]; | 5648 | if (be16_to_cpu(pinstance->inq_data->fw_version) <= |
| 5649 | PMCRAID_FW_VERSION_1) | ||
| 5650 | cfgte = &pinstance->cfg_table->entries[i]; | ||
| 5651 | else | ||
| 5652 | cfgte = (struct pmcraid_config_table_entry *) | ||
| 5653 | &pinstance->cfg_table->entries_ext[i]; | ||
| 5223 | 5654 | ||
| 5224 | if (!pmcraid_expose_resource(cfgte)) | 5655 | if (!pmcraid_expose_resource(fw_version, cfgte)) |
| 5225 | continue; | 5656 | continue; |
| 5226 | 5657 | ||
| 5227 | found = 0; | 5658 | found = 0; |
| @@ -5263,10 +5694,12 @@ static void pmcraid_init_res_table(struct pmcraid_cmd *cmd) | |||
| 5263 | */ | 5694 | */ |
| 5264 | if (found) { | 5695 | if (found) { |
| 5265 | memcpy(&res->cfg_entry, cfgte, | 5696 | memcpy(&res->cfg_entry, cfgte, |
| 5266 | sizeof(struct pmcraid_config_table_entry)); | 5697 | pinstance->config_table_entry_size); |
| 5267 | pmcraid_info("New res type:%x, vset:%x, addr:%x:\n", | 5698 | pmcraid_info("New res type:%x, vset:%x, addr:%x:\n", |
| 5268 | res->cfg_entry.resource_type, | 5699 | res->cfg_entry.resource_type, |
| 5269 | res->cfg_entry.unique_flags1, | 5700 | (fw_version <= PMCRAID_FW_VERSION_1 ? |
| 5701 | res->cfg_entry.unique_flags1 : | ||
| 5702 | res->cfg_entry.array_id & 0xFF), | ||
| 5270 | le32_to_cpu(res->cfg_entry.resource_address)); | 5703 | le32_to_cpu(res->cfg_entry.resource_address)); |
| 5271 | } | 5704 | } |
| 5272 | } | 5705 | } |
| @@ -5306,6 +5739,14 @@ static void pmcraid_querycfg(struct pmcraid_cmd *cmd) | |||
| 5306 | struct pmcraid_instance *pinstance = cmd->drv_inst; | 5739 | struct pmcraid_instance *pinstance = cmd->drv_inst; |
| 5307 | int cfg_table_size = cpu_to_be32(sizeof(struct pmcraid_config_table)); | 5740 | int cfg_table_size = cpu_to_be32(sizeof(struct pmcraid_config_table)); |
| 5308 | 5741 | ||
| 5742 | if (be16_to_cpu(pinstance->inq_data->fw_version) <= | ||
| 5743 | PMCRAID_FW_VERSION_1) | ||
| 5744 | pinstance->config_table_entry_size = | ||
| 5745 | sizeof(struct pmcraid_config_table_entry); | ||
| 5746 | else | ||
| 5747 | pinstance->config_table_entry_size = | ||
| 5748 | sizeof(struct pmcraid_config_table_entry_ext); | ||
| 5749 | |||
| 5309 | ioarcb->request_type = REQ_TYPE_IOACMD; | 5750 | ioarcb->request_type = REQ_TYPE_IOACMD; |
| 5310 | ioarcb->resource_handle = cpu_to_le32(PMCRAID_IOA_RES_HANDLE); | 5751 | ioarcb->resource_handle = cpu_to_le32(PMCRAID_IOA_RES_HANDLE); |
| 5311 | 5752 | ||
| @@ -5338,7 +5779,7 @@ static void pmcraid_querycfg(struct pmcraid_cmd *cmd) | |||
| 5338 | 5779 | ||
| 5339 | 5780 | ||
| 5340 | /** | 5781 | /** |
| 5341 | * pmcraid_probe - PCI probe entry pointer for PMC MaxRaid controller driver | 5782 | * pmcraid_probe - PCI probe entry pointer for PMC MaxRAID controller driver |
| 5342 | * @pdev: pointer to pci device structure | 5783 | * @pdev: pointer to pci device structure |
| 5343 | * @dev_id: pointer to device ids structure | 5784 | * @dev_id: pointer to device ids structure |
| 5344 | * | 5785 | * |
| @@ -5485,7 +5926,7 @@ static int __devinit pmcraid_probe( | |||
| 5485 | */ | 5926 | */ |
| 5486 | pmcraid_info("starting IOA initialization sequence\n"); | 5927 | pmcraid_info("starting IOA initialization sequence\n"); |
| 5487 | if (pmcraid_reset_bringup(pinstance)) { | 5928 | if (pmcraid_reset_bringup(pinstance)) { |
| 5488 | dev_err(&pdev->dev, "couldn't initialize IOA \n"); | 5929 | dev_err(&pdev->dev, "couldn't initialize IOA\n"); |
| 5489 | rc = 1; | 5930 | rc = 1; |
| 5490 | goto out_release_bufs; | 5931 | goto out_release_bufs; |
| 5491 | } | 5932 | } |
