diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/scsi/pmcraid.c | 886 | ||||
-rw-r--r-- | drivers/scsi/pmcraid.h | 305 |
2 files changed, 843 insertions, 348 deletions
diff --git a/drivers/scsi/pmcraid.c b/drivers/scsi/pmcraid.c index c44e4ab4e938..9ebcea3643b2 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 | ||
@@ -3465,6 +3740,7 @@ static long pmcraid_ioctl_passthrough( | |||
3465 | unsigned long request_buffer; | 3740 | unsigned long request_buffer; |
3466 | unsigned long request_offset; | 3741 | unsigned long request_offset; |
3467 | unsigned long lock_flags; | 3742 | unsigned long lock_flags; |
3743 | u32 ioasc; | ||
3468 | int request_size; | 3744 | int request_size; |
3469 | int buffer_size; | 3745 | int buffer_size; |
3470 | u8 access, direction; | 3746 | u8 access, direction; |
@@ -3566,6 +3842,14 @@ static long pmcraid_ioctl_passthrough( | |||
3566 | buffer->ioarcb.add_cmd_param_length); | 3842 | buffer->ioarcb.add_cmd_param_length); |
3567 | } | 3843 | } |
3568 | 3844 | ||
3845 | /* set hrrq number where the IOA should respond to. Note that all cmds | ||
3846 | * generated internally uses hrrq_id 0, exception to this is the cmd | ||
3847 | * block of scsi_cmd which is re-used (e.g. cancel/abort), which uses | ||
3848 | * hrrq_id assigned here in queuecommand | ||
3849 | */ | ||
3850 | ioarcb->hrrq_id = atomic_add_return(1, &(pinstance->last_message_id)) % | ||
3851 | pinstance->num_hrrq; | ||
3852 | |||
3569 | if (request_size) { | 3853 | if (request_size) { |
3570 | rc = pmcraid_build_passthrough_ioadls(cmd, | 3854 | rc = pmcraid_build_passthrough_ioadls(cmd, |
3571 | request_size, | 3855 | request_size, |
@@ -3606,6 +3890,14 @@ static long pmcraid_ioctl_passthrough( | |||
3606 | _pmcraid_fire_command(cmd); | 3890 | _pmcraid_fire_command(cmd); |
3607 | spin_unlock_irqrestore(pinstance->host->host_lock, lock_flags); | 3891 | spin_unlock_irqrestore(pinstance->host->host_lock, lock_flags); |
3608 | 3892 | ||
3893 | /* NOTE ! Remove the below line once abort_task is implemented | ||
3894 | * in firmware. This line disables ioctl command timeout handling logic | ||
3895 | * similar to IO command timeout handling, making ioctl commands to wait | ||
3896 | * until the command completion regardless of timeout value specified in | ||
3897 | * ioarcb | ||
3898 | */ | ||
3899 | buffer->ioarcb.cmd_timeout = 0; | ||
3900 | |||
3609 | /* If command timeout is specified put caller to wait till that time, | 3901 | /* 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 | 3902 | * otherwise it would be blocking wait. If command gets timed out, it |
3611 | * will be aborted. | 3903 | * will be aborted. |
@@ -3620,25 +3912,47 @@ static long pmcraid_ioctl_passthrough( | |||
3620 | le32_to_cpu(cmd->ioa_cb->ioarcb.response_handle >> 2), | 3912 | le32_to_cpu(cmd->ioa_cb->ioarcb.response_handle >> 2), |
3621 | cmd->ioa_cb->ioarcb.cdb[0]); | 3913 | cmd->ioa_cb->ioarcb.cdb[0]); |
3622 | 3914 | ||
3623 | rc = -ETIMEDOUT; | ||
3624 | spin_lock_irqsave(pinstance->host->host_lock, lock_flags); | 3915 | spin_lock_irqsave(pinstance->host->host_lock, lock_flags); |
3625 | cancel_cmd = pmcraid_abort_cmd(cmd); | 3916 | cancel_cmd = pmcraid_abort_cmd(cmd); |
3626 | spin_unlock_irqrestore(pinstance->host->host_lock, lock_flags); | 3917 | spin_unlock_irqrestore(pinstance->host->host_lock, lock_flags); |
3627 | 3918 | ||
3628 | if (cancel_cmd) { | 3919 | if (cancel_cmd) { |
3629 | wait_for_completion(&cancel_cmd->wait_for_completion); | 3920 | wait_for_completion(&cancel_cmd->wait_for_completion); |
3921 | ioasc = cancel_cmd->ioa_cb->ioasa.ioasc; | ||
3630 | pmcraid_return_cmd(cancel_cmd); | 3922 | pmcraid_return_cmd(cancel_cmd); |
3923 | |||
3924 | /* if abort task couldn't find the command i.e it got | ||
3925 | * completed prior to aborting, return good completion. | ||
3926 | * if command got aborted succesfully or there was IOA | ||
3927 | * reset due to abort task itself getting timedout then | ||
3928 | * return -ETIMEDOUT | ||
3929 | */ | ||
3930 | if (ioasc == PMCRAID_IOASC_IOA_WAS_RESET || | ||
3931 | PMCRAID_IOASC_SENSE_KEY(ioasc) == 0x00) { | ||
3932 | if (ioasc != PMCRAID_IOASC_GC_IOARCB_NOTFOUND) | ||
3933 | rc = -ETIMEDOUT; | ||
3934 | goto out_handle_response; | ||
3935 | } | ||
3631 | } | 3936 | } |
3632 | 3937 | ||
3633 | goto out_free_sglist; | 3938 | /* no command block for abort task or abort task failed to abort |
3939 | * the IOARCB, then wait for 150 more seconds and initiate reset | ||
3940 | * sequence after timeout | ||
3941 | */ | ||
3942 | if (!wait_for_completion_timeout( | ||
3943 | &cmd->wait_for_completion, | ||
3944 | msecs_to_jiffies(150 * 1000))) { | ||
3945 | pmcraid_reset_bringup(cmd->drv_inst); | ||
3946 | rc = -ETIMEDOUT; | ||
3947 | } | ||
3634 | } | 3948 | } |
3635 | 3949 | ||
3950 | out_handle_response: | ||
3636 | /* If the command failed for any reason, copy entire IOASA buffer and | 3951 | /* If the command failed for any reason, copy entire IOASA buffer and |
3637 | * return IOCTL success. If copying IOASA to user-buffer fails, return | 3952 | * return IOCTL success. If copying IOASA to user-buffer fails, return |
3638 | * EFAULT | 3953 | * EFAULT |
3639 | */ | 3954 | */ |
3640 | if (le32_to_cpu(cmd->ioa_cb->ioasa.ioasc)) { | 3955 | if (PMCRAID_IOASC_SENSE_KEY(le32_to_cpu(cmd->ioa_cb->ioasa.ioasc))) { |
3641 | |||
3642 | void *ioasa = | 3956 | void *ioasa = |
3643 | (void *)(arg + | 3957 | (void *)(arg + |
3644 | offsetof(struct pmcraid_passthrough_ioctl_buffer, ioasa)); | 3958 | offsetof(struct pmcraid_passthrough_ioctl_buffer, ioasa)); |
@@ -3651,6 +3965,7 @@ static long pmcraid_ioctl_passthrough( | |||
3651 | rc = -EFAULT; | 3965 | rc = -EFAULT; |
3652 | } | 3966 | } |
3653 | } | 3967 | } |
3968 | |||
3654 | /* If the data transfer was from device, copy the data onto user | 3969 | /* If the data transfer was from device, copy the data onto user |
3655 | * buffers | 3970 | * buffers |
3656 | */ | 3971 | */ |
@@ -3699,7 +4014,7 @@ static long pmcraid_ioctl_driver( | |||
3699 | int rc = -ENOSYS; | 4014 | int rc = -ENOSYS; |
3700 | 4015 | ||
3701 | if (!access_ok(VERIFY_READ, user_buffer, _IOC_SIZE(cmd))) { | 4016 | if (!access_ok(VERIFY_READ, user_buffer, _IOC_SIZE(cmd))) { |
3702 | pmcraid_err("ioctl_driver: access fault in request buffer \n"); | 4017 | pmcraid_err("ioctl_driver: access fault in request buffer\n"); |
3703 | return -EFAULT; | 4018 | return -EFAULT; |
3704 | } | 4019 | } |
3705 | 4020 | ||
@@ -4011,36 +4326,77 @@ static struct scsi_host_template pmcraid_host_template = { | |||
4011 | .proc_name = PMCRAID_DRIVER_NAME | 4326 | .proc_name = PMCRAID_DRIVER_NAME |
4012 | }; | 4327 | }; |
4013 | 4328 | ||
4014 | /** | 4329 | /* |
4015 | * pmcraid_isr_common - Common interrupt handler routine | 4330 | * pmcraid_isr_msix - implements MSI-X interrupt handling routine |
4016 | * | 4331 | * @irq: interrupt vector number |
4017 | * @pinstance: pointer to adapter instance | 4332 | * @dev_id: pointer hrrq_vector |
4018 | * @intrs: active interrupts (contents of ioa_host_interrupt register) | ||
4019 | * @hrrq_id: Host RRQ index | ||
4020 | * | 4333 | * |
4021 | * Return Value | 4334 | * Return Value |
4022 | * none | 4335 | * IRQ_HANDLED if interrupt is handled or IRQ_NONE if ignored |
4023 | */ | 4336 | */ |
4024 | static void pmcraid_isr_common( | 4337 | |
4025 | struct pmcraid_instance *pinstance, | 4338 | static irqreturn_t pmcraid_isr_msix(int irq, void *dev_id) |
4026 | u32 intrs, | ||
4027 | int hrrq_id | ||
4028 | ) | ||
4029 | { | 4339 | { |
4030 | u32 intrs_clear = | 4340 | struct pmcraid_isr_param *hrrq_vector; |
4031 | (intrs & INTRS_CRITICAL_OP_IN_PROGRESS) ? intrs | 4341 | struct pmcraid_instance *pinstance; |
4032 | : INTRS_HRRQ_VALID; | 4342 | unsigned long lock_flags; |
4033 | iowrite32(intrs_clear, | 4343 | u32 intrs_val; |
4034 | pinstance->int_regs.ioa_host_interrupt_clr_reg); | 4344 | int hrrq_id; |
4035 | intrs = ioread32(pinstance->int_regs.ioa_host_interrupt_reg); | 4345 | |
4346 | hrrq_vector = (struct pmcraid_isr_param *)dev_id; | ||
4347 | hrrq_id = hrrq_vector->hrrq_id; | ||
4348 | pinstance = hrrq_vector->drv_inst; | ||
4349 | |||
4350 | if (!hrrq_id) { | ||
4351 | /* Read the interrupt */ | ||
4352 | intrs_val = pmcraid_read_interrupts(pinstance); | ||
4353 | if (intrs_val && | ||
4354 | ((ioread32(pinstance->int_regs.host_ioa_interrupt_reg) | ||
4355 | & DOORBELL_INTR_MSIX_CLR) == 0)) { | ||
4356 | /* Any error interrupts including unit_check, | ||
4357 | * initiate IOA reset.In case of unit check indicate | ||
4358 | * to reset_sequence that IOA unit checked and prepare | ||
4359 | * for a dump during reset sequence | ||
4360 | */ | ||
4361 | if (intrs_val & PMCRAID_ERROR_INTERRUPTS) { | ||
4362 | if (intrs_val & INTRS_IOA_UNIT_CHECK) | ||
4363 | pinstance->ioa_unit_check = 1; | ||
4364 | |||
4365 | pmcraid_err("ISR: error interrupts: %x \ | ||
4366 | initiating reset\n", intrs_val); | ||
4367 | spin_lock_irqsave(pinstance->host->host_lock, | ||
4368 | lock_flags); | ||
4369 | pmcraid_initiate_reset(pinstance); | ||
4370 | spin_unlock_irqrestore( | ||
4371 | pinstance->host->host_lock, | ||
4372 | lock_flags); | ||
4373 | } | ||
4374 | /* If interrupt was as part of the ioa initialization, | ||
4375 | * clear it. Delete the timer and wakeup the | ||
4376 | * reset engine to proceed with reset sequence | ||
4377 | */ | ||
4378 | if (intrs_val & INTRS_TRANSITION_TO_OPERATIONAL) | ||
4379 | pmcraid_clr_trans_op(pinstance); | ||
4380 | |||
4381 | /* Clear the interrupt register by writing | ||
4382 | * to host to ioa doorbell. Once done | ||
4383 | * FW will clear the interrupt. | ||
4384 | */ | ||
4385 | iowrite32(DOORBELL_INTR_MSIX_CLR, | ||
4386 | pinstance->int_regs.host_ioa_interrupt_reg); | ||
4387 | ioread32(pinstance->int_regs.host_ioa_interrupt_reg); | ||
4388 | |||
4036 | 4389 | ||
4037 | /* hrrq valid bit was set, schedule tasklet to handle the response */ | 4390 | } |
4038 | if (intrs_clear == INTRS_HRRQ_VALID) | 4391 | } |
4039 | tasklet_schedule(&(pinstance->isr_tasklet[hrrq_id])); | 4392 | |
4393 | tasklet_schedule(&(pinstance->isr_tasklet[hrrq_id])); | ||
4394 | |||
4395 | return IRQ_HANDLED; | ||
4040 | } | 4396 | } |
4041 | 4397 | ||
4042 | /** | 4398 | /** |
4043 | * pmcraid_isr - implements interrupt handling routine | 4399 | * pmcraid_isr - implements legacy interrupt handling routine |
4044 | * | 4400 | * |
4045 | * @irq: interrupt vector number | 4401 | * @irq: interrupt vector number |
4046 | * @dev_id: pointer hrrq_vector | 4402 | * @dev_id: pointer hrrq_vector |
@@ -4052,8 +4408,9 @@ static irqreturn_t pmcraid_isr(int irq, void *dev_id) | |||
4052 | { | 4408 | { |
4053 | struct pmcraid_isr_param *hrrq_vector; | 4409 | struct pmcraid_isr_param *hrrq_vector; |
4054 | struct pmcraid_instance *pinstance; | 4410 | struct pmcraid_instance *pinstance; |
4055 | unsigned long lock_flags; | ||
4056 | u32 intrs; | 4411 | u32 intrs; |
4412 | unsigned long lock_flags; | ||
4413 | int hrrq_id = 0; | ||
4057 | 4414 | ||
4058 | /* In case of legacy interrupt mode where interrupts are shared across | 4415 | /* 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 | 4416 | * isrs, it may be possible that the current interrupt is not from IOA |
@@ -4062,21 +4419,13 @@ static irqreturn_t pmcraid_isr(int irq, void *dev_id) | |||
4062 | printk(KERN_INFO "%s(): NULL host pointer\n", __func__); | 4419 | printk(KERN_INFO "%s(): NULL host pointer\n", __func__); |
4063 | return IRQ_NONE; | 4420 | return IRQ_NONE; |
4064 | } | 4421 | } |
4065 | |||
4066 | hrrq_vector = (struct pmcraid_isr_param *)dev_id; | 4422 | hrrq_vector = (struct pmcraid_isr_param *)dev_id; |
4067 | pinstance = hrrq_vector->drv_inst; | 4423 | pinstance = hrrq_vector->drv_inst; |
4068 | 4424 | ||
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); | 4425 | intrs = pmcraid_read_interrupts(pinstance); |
4075 | 4426 | ||
4076 | if (unlikely((intrs & PMCRAID_PCI_INTERRUPTS) == 0)) { | 4427 | if (unlikely((intrs & PMCRAID_PCI_INTERRUPTS) == 0)) |
4077 | spin_unlock_irqrestore(pinstance->host->host_lock, lock_flags); | ||
4078 | return IRQ_NONE; | 4428 | return IRQ_NONE; |
4079 | } | ||
4080 | 4429 | ||
4081 | /* Any error interrupts including unit_check, initiate IOA reset. | 4430 | /* Any error interrupts including unit_check, initiate IOA reset. |
4082 | * In case of unit check indicate to reset_sequence that IOA unit | 4431 | * In case of unit check indicate to reset_sequence that IOA unit |
@@ -4091,13 +4440,28 @@ static irqreturn_t pmcraid_isr(int irq, void *dev_id) | |||
4091 | pinstance->int_regs.ioa_host_interrupt_clr_reg); | 4440 | pinstance->int_regs.ioa_host_interrupt_clr_reg); |
4092 | pmcraid_err("ISR: error interrupts: %x initiating reset\n", | 4441 | pmcraid_err("ISR: error interrupts: %x initiating reset\n", |
4093 | intrs); | 4442 | intrs); |
4094 | intrs = ioread32(pinstance->int_regs.ioa_host_interrupt_reg); | 4443 | intrs = ioread32( |
4444 | pinstance->int_regs.ioa_host_interrupt_clr_reg); | ||
4445 | spin_lock_irqsave(pinstance->host->host_lock, lock_flags); | ||
4095 | pmcraid_initiate_reset(pinstance); | 4446 | pmcraid_initiate_reset(pinstance); |
4447 | spin_unlock_irqrestore(pinstance->host->host_lock, lock_flags); | ||
4096 | } else { | 4448 | } else { |
4097 | pmcraid_isr_common(pinstance, intrs, hrrq_vector->hrrq_id); | 4449 | /* If interrupt was as part of the ioa initialization, |
4098 | } | 4450 | * clear. Delete the timer and wakeup the |
4451 | * reset engine to proceed with reset sequence | ||
4452 | */ | ||
4453 | if (intrs & INTRS_TRANSITION_TO_OPERATIONAL) { | ||
4454 | pmcraid_clr_trans_op(pinstance); | ||
4455 | } else { | ||
4456 | iowrite32(intrs, | ||
4457 | pinstance->int_regs.ioa_host_interrupt_clr_reg); | ||
4458 | ioread32( | ||
4459 | pinstance->int_regs.ioa_host_interrupt_clr_reg); | ||
4099 | 4460 | ||
4100 | spin_unlock_irqrestore(pinstance->host->host_lock, lock_flags); | 4461 | tasklet_schedule( |
4462 | &(pinstance->isr_tasklet[hrrq_id])); | ||
4463 | } | ||
4464 | } | ||
4101 | 4465 | ||
4102 | return IRQ_HANDLED; | 4466 | return IRQ_HANDLED; |
4103 | } | 4467 | } |
@@ -4120,6 +4484,7 @@ static void pmcraid_worker_function(struct work_struct *workp) | |||
4120 | struct scsi_device *sdev; | 4484 | struct scsi_device *sdev; |
4121 | unsigned long lock_flags; | 4485 | unsigned long lock_flags; |
4122 | unsigned long host_lock_flags; | 4486 | unsigned long host_lock_flags; |
4487 | u16 fw_version; | ||
4123 | u8 bus, target, lun; | 4488 | u8 bus, target, lun; |
4124 | 4489 | ||
4125 | pinstance = container_of(workp, struct pmcraid_instance, worker_q); | 4490 | pinstance = container_of(workp, struct pmcraid_instance, worker_q); |
@@ -4127,6 +4492,8 @@ static void pmcraid_worker_function(struct work_struct *workp) | |||
4127 | if (!atomic_read(&pinstance->expose_resources)) | 4492 | if (!atomic_read(&pinstance->expose_resources)) |
4128 | return; | 4493 | return; |
4129 | 4494 | ||
4495 | fw_version = be16_to_cpu(pinstance->inq_data->fw_version); | ||
4496 | |||
4130 | spin_lock_irqsave(&pinstance->resource_lock, lock_flags); | 4497 | spin_lock_irqsave(&pinstance->resource_lock, lock_flags); |
4131 | list_for_each_entry_safe(res, temp, &pinstance->used_res_q, queue) { | 4498 | list_for_each_entry_safe(res, temp, &pinstance->used_res_q, queue) { |
4132 | 4499 | ||
@@ -4166,12 +4533,16 @@ static void pmcraid_worker_function(struct work_struct *workp) | |||
4166 | 4533 | ||
4167 | if (res->change_detected == RES_CHANGE_ADD) { | 4534 | if (res->change_detected == RES_CHANGE_ADD) { |
4168 | 4535 | ||
4169 | if (!pmcraid_expose_resource(&res->cfg_entry)) | 4536 | if (!pmcraid_expose_resource(fw_version, |
4537 | &res->cfg_entry)) | ||
4170 | continue; | 4538 | continue; |
4171 | 4539 | ||
4172 | if (RES_IS_VSET(res->cfg_entry)) { | 4540 | if (RES_IS_VSET(res->cfg_entry)) { |
4173 | bus = PMCRAID_VSET_BUS_ID; | 4541 | bus = PMCRAID_VSET_BUS_ID; |
4174 | target = res->cfg_entry.unique_flags1; | 4542 | if (fw_version <= PMCRAID_FW_VERSION_1) |
4543 | target = res->cfg_entry.unique_flags1; | ||
4544 | else | ||
4545 | target = res->cfg_entry.array_id & 0xFF; | ||
4175 | lun = PMCRAID_VSET_LUN_ID; | 4546 | lun = PMCRAID_VSET_LUN_ID; |
4176 | } else { | 4547 | } else { |
4177 | bus = PMCRAID_PHYS_BUS_ID; | 4548 | bus = PMCRAID_PHYS_BUS_ID; |
@@ -4201,7 +4572,7 @@ static void pmcraid_worker_function(struct work_struct *workp) | |||
4201 | * Return Value | 4572 | * Return Value |
4202 | * None | 4573 | * None |
4203 | */ | 4574 | */ |
4204 | void pmcraid_tasklet_function(unsigned long instance) | 4575 | static void pmcraid_tasklet_function(unsigned long instance) |
4205 | { | 4576 | { |
4206 | struct pmcraid_isr_param *hrrq_vector; | 4577 | struct pmcraid_isr_param *hrrq_vector; |
4207 | struct pmcraid_instance *pinstance; | 4578 | struct pmcraid_instance *pinstance; |
@@ -4210,35 +4581,12 @@ void pmcraid_tasklet_function(unsigned long instance) | |||
4210 | unsigned long host_lock_flags; | 4581 | unsigned long host_lock_flags; |
4211 | spinlock_t *lockp; /* hrrq buffer lock */ | 4582 | spinlock_t *lockp; /* hrrq buffer lock */ |
4212 | int id; | 4583 | int id; |
4213 | u32 intrs; | ||
4214 | __le32 resp; | 4584 | __le32 resp; |
4215 | 4585 | ||
4216 | hrrq_vector = (struct pmcraid_isr_param *)instance; | 4586 | hrrq_vector = (struct pmcraid_isr_param *)instance; |
4217 | pinstance = hrrq_vector->drv_inst; | 4587 | pinstance = hrrq_vector->drv_inst; |
4218 | id = hrrq_vector->hrrq_id; | 4588 | id = hrrq_vector->hrrq_id; |
4219 | lockp = &(pinstance->hrrq_lock[id]); | 4589 | 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 | 4590 | ||
4243 | /* loop through each of the commands responded by IOA. Each HRRQ buf is | 4591 | /* 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 | 4592 | * protected by its own lock. Traversals must be done within this lock |
@@ -4256,27 +4604,6 @@ void pmcraid_tasklet_function(unsigned long instance) | |||
4256 | int cmd_index = resp >> 2; | 4604 | int cmd_index = resp >> 2; |
4257 | struct pmcraid_cmd *cmd = NULL; | 4605 | struct pmcraid_cmd *cmd = NULL; |
4258 | 4606 | ||
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]) { | 4607 | if (pinstance->hrrq_curr[id] < pinstance->hrrq_end[id]) { |
4281 | pinstance->hrrq_curr[id]++; | 4608 | pinstance->hrrq_curr[id]++; |
4282 | } else { | 4609 | } else { |
@@ -4284,6 +4611,14 @@ void pmcraid_tasklet_function(unsigned long instance) | |||
4284 | pinstance->host_toggle_bit[id] ^= 1u; | 4611 | pinstance->host_toggle_bit[id] ^= 1u; |
4285 | } | 4612 | } |
4286 | 4613 | ||
4614 | if (cmd_index >= PMCRAID_MAX_CMD) { | ||
4615 | /* In case of invalid response handle, log message */ | ||
4616 | pmcraid_err("Invalid response handle %d\n", cmd_index); | ||
4617 | resp = le32_to_cpu(*(pinstance->hrrq_curr[id])); | ||
4618 | continue; | ||
4619 | } | ||
4620 | |||
4621 | cmd = pinstance->cmd_list[cmd_index]; | ||
4287 | spin_unlock_irqrestore(lockp, hrrq_lock_flags); | 4622 | spin_unlock_irqrestore(lockp, hrrq_lock_flags); |
4288 | 4623 | ||
4289 | spin_lock_irqsave(&pinstance->pending_pool_lock, | 4624 | spin_lock_irqsave(&pinstance->pending_pool_lock, |
@@ -4324,7 +4659,16 @@ void pmcraid_tasklet_function(unsigned long instance) | |||
4324 | static | 4659 | static |
4325 | void pmcraid_unregister_interrupt_handler(struct pmcraid_instance *pinstance) | 4660 | void pmcraid_unregister_interrupt_handler(struct pmcraid_instance *pinstance) |
4326 | { | 4661 | { |
4327 | free_irq(pinstance->pdev->irq, &(pinstance->hrrq_vector[0])); | 4662 | int i; |
4663 | |||
4664 | for (i = 0; i < pinstance->num_hrrq; i++) | ||
4665 | free_irq(pinstance->hrrq_vector[i].vector, | ||
4666 | &(pinstance->hrrq_vector[i])); | ||
4667 | |||
4668 | if (pinstance->interrupt_mode) { | ||
4669 | pci_disable_msix(pinstance->pdev); | ||
4670 | pinstance->interrupt_mode = 0; | ||
4671 | } | ||
4328 | } | 4672 | } |
4329 | 4673 | ||
4330 | /** | 4674 | /** |
@@ -4337,14 +4681,70 @@ void pmcraid_unregister_interrupt_handler(struct pmcraid_instance *pinstance) | |||
4337 | static int | 4681 | static int |
4338 | pmcraid_register_interrupt_handler(struct pmcraid_instance *pinstance) | 4682 | pmcraid_register_interrupt_handler(struct pmcraid_instance *pinstance) |
4339 | { | 4683 | { |
4684 | int rc; | ||
4340 | struct pci_dev *pdev = pinstance->pdev; | 4685 | struct pci_dev *pdev = pinstance->pdev; |
4341 | 4686 | ||
4687 | if (pci_find_capability(pdev, PCI_CAP_ID_MSIX)) { | ||
4688 | int num_hrrq = PMCRAID_NUM_MSIX_VECTORS; | ||
4689 | struct msix_entry entries[PMCRAID_NUM_MSIX_VECTORS]; | ||
4690 | int i; | ||
4691 | for (i = 0; i < PMCRAID_NUM_MSIX_VECTORS; i++) | ||
4692 | entries[i].entry = i; | ||
4693 | |||
4694 | rc = pci_enable_msix(pdev, entries, num_hrrq); | ||
4695 | if (rc < 0) | ||
4696 | goto pmcraid_isr_legacy; | ||
4697 | |||
4698 | /* Check how many MSIX vectors are allocated and register | ||
4699 | * msi-x handlers for each of them giving appropriate buffer | ||
4700 | */ | ||
4701 | if (rc > 0) { | ||
4702 | num_hrrq = rc; | ||
4703 | if (pci_enable_msix(pdev, entries, num_hrrq)) | ||
4704 | goto pmcraid_isr_legacy; | ||
4705 | } | ||
4706 | |||
4707 | for (i = 0; i < num_hrrq; i++) { | ||
4708 | pinstance->hrrq_vector[i].hrrq_id = i; | ||
4709 | pinstance->hrrq_vector[i].drv_inst = pinstance; | ||
4710 | pinstance->hrrq_vector[i].vector = entries[i].vector; | ||
4711 | rc = request_irq(pinstance->hrrq_vector[i].vector, | ||
4712 | pmcraid_isr_msix, 0, | ||
4713 | PMCRAID_DRIVER_NAME, | ||
4714 | &(pinstance->hrrq_vector[i])); | ||
4715 | |||
4716 | if (rc) { | ||
4717 | int j; | ||
4718 | for (j = 0; j < i; j++) | ||
4719 | free_irq(entries[j].vector, | ||
4720 | &(pinstance->hrrq_vector[j])); | ||
4721 | pci_disable_msix(pdev); | ||
4722 | goto pmcraid_isr_legacy; | ||
4723 | } | ||
4724 | } | ||
4725 | |||
4726 | pinstance->num_hrrq = num_hrrq; | ||
4727 | pinstance->interrupt_mode = 1; | ||
4728 | iowrite32(DOORBELL_INTR_MODE_MSIX, | ||
4729 | pinstance->int_regs.host_ioa_interrupt_reg); | ||
4730 | ioread32(pinstance->int_regs.host_ioa_interrupt_reg); | ||
4731 | goto pmcraid_isr_out; | ||
4732 | } | ||
4733 | |||
4734 | pmcraid_isr_legacy: | ||
4735 | /* If MSI-X registration failed fallback to legacy mode, where | ||
4736 | * only one hrrq entry will be used | ||
4737 | */ | ||
4342 | pinstance->hrrq_vector[0].hrrq_id = 0; | 4738 | pinstance->hrrq_vector[0].hrrq_id = 0; |
4343 | pinstance->hrrq_vector[0].drv_inst = pinstance; | 4739 | pinstance->hrrq_vector[0].drv_inst = pinstance; |
4344 | pinstance->hrrq_vector[0].vector = 0; | 4740 | pinstance->hrrq_vector[0].vector = pdev->irq; |
4345 | pinstance->num_hrrq = 1; | 4741 | pinstance->num_hrrq = 1; |
4346 | return request_irq(pdev->irq, pmcraid_isr, IRQF_SHARED, | 4742 | rc = 0; |
4347 | PMCRAID_DRIVER_NAME, &pinstance->hrrq_vector[0]); | 4743 | |
4744 | rc = request_irq(pdev->irq, pmcraid_isr, IRQF_SHARED, | ||
4745 | PMCRAID_DRIVER_NAME, &pinstance->hrrq_vector[0]); | ||
4746 | pmcraid_isr_out: | ||
4747 | return rc; | ||
4348 | } | 4748 | } |
4349 | 4749 | ||
4350 | /** | 4750 | /** |
@@ -4516,12 +4916,11 @@ pmcraid_release_host_rrqs(struct pmcraid_instance *pinstance, int maxindex) | |||
4516 | static int __devinit | 4916 | static int __devinit |
4517 | pmcraid_allocate_host_rrqs(struct pmcraid_instance *pinstance) | 4917 | pmcraid_allocate_host_rrqs(struct pmcraid_instance *pinstance) |
4518 | { | 4918 | { |
4519 | int i; | 4919 | int i, buffer_size; |
4520 | int buf_count = PMCRAID_MAX_CMD / pinstance->num_hrrq; | ||
4521 | 4920 | ||
4522 | for (i = 0; i < pinstance->num_hrrq; i++) { | 4921 | buffer_size = HRRQ_ENTRY_SIZE * PMCRAID_MAX_CMD; |
4523 | int buffer_size = HRRQ_ENTRY_SIZE * buf_count; | ||
4524 | 4922 | ||
4923 | for (i = 0; i < pinstance->num_hrrq; i++) { | ||
4525 | pinstance->hrrq_start[i] = | 4924 | pinstance->hrrq_start[i] = |
4526 | pci_alloc_consistent( | 4925 | pci_alloc_consistent( |
4527 | pinstance->pdev, | 4926 | pinstance->pdev, |
@@ -4529,7 +4928,8 @@ pmcraid_allocate_host_rrqs(struct pmcraid_instance *pinstance) | |||
4529 | &(pinstance->hrrq_start_bus_addr[i])); | 4928 | &(pinstance->hrrq_start_bus_addr[i])); |
4530 | 4929 | ||
4531 | if (pinstance->hrrq_start[i] == 0) { | 4930 | if (pinstance->hrrq_start[i] == 0) { |
4532 | pmcraid_err("could not allocate host rrq: %d\n", i); | 4931 | pmcraid_err("pci_alloc failed for hrrq vector : %d\n", |
4932 | i); | ||
4533 | pmcraid_release_host_rrqs(pinstance, i); | 4933 | pmcraid_release_host_rrqs(pinstance, i); |
4534 | return -ENOMEM; | 4934 | return -ENOMEM; |
4535 | } | 4935 | } |
@@ -4537,7 +4937,7 @@ pmcraid_allocate_host_rrqs(struct pmcraid_instance *pinstance) | |||
4537 | memset(pinstance->hrrq_start[i], 0, buffer_size); | 4937 | memset(pinstance->hrrq_start[i], 0, buffer_size); |
4538 | pinstance->hrrq_curr[i] = pinstance->hrrq_start[i]; | 4938 | pinstance->hrrq_curr[i] = pinstance->hrrq_start[i]; |
4539 | pinstance->hrrq_end[i] = | 4939 | pinstance->hrrq_end[i] = |
4540 | pinstance->hrrq_start[i] + buf_count - 1; | 4940 | pinstance->hrrq_start[i] + PMCRAID_MAX_CMD - 1; |
4541 | pinstance->host_toggle_bit[i] = 1; | 4941 | pinstance->host_toggle_bit[i] = 1; |
4542 | spin_lock_init(&pinstance->hrrq_lock[i]); | 4942 | spin_lock_init(&pinstance->hrrq_lock[i]); |
4543 | } | 4943 | } |
@@ -4557,7 +4957,7 @@ static void pmcraid_release_hcams(struct pmcraid_instance *pinstance) | |||
4557 | if (pinstance->ccn.msg != NULL) { | 4957 | if (pinstance->ccn.msg != NULL) { |
4558 | pci_free_consistent(pinstance->pdev, | 4958 | pci_free_consistent(pinstance->pdev, |
4559 | PMCRAID_AEN_HDR_SIZE + | 4959 | PMCRAID_AEN_HDR_SIZE + |
4560 | sizeof(struct pmcraid_hcam_ccn), | 4960 | sizeof(struct pmcraid_hcam_ccn_ext), |
4561 | pinstance->ccn.msg, | 4961 | pinstance->ccn.msg, |
4562 | pinstance->ccn.baddr); | 4962 | pinstance->ccn.baddr); |
4563 | 4963 | ||
@@ -4591,7 +4991,7 @@ static int pmcraid_allocate_hcams(struct pmcraid_instance *pinstance) | |||
4591 | pinstance->ccn.msg = pci_alloc_consistent( | 4991 | pinstance->ccn.msg = pci_alloc_consistent( |
4592 | pinstance->pdev, | 4992 | pinstance->pdev, |
4593 | PMCRAID_AEN_HDR_SIZE + | 4993 | PMCRAID_AEN_HDR_SIZE + |
4594 | sizeof(struct pmcraid_hcam_ccn), | 4994 | sizeof(struct pmcraid_hcam_ccn_ext), |
4595 | &(pinstance->ccn.baddr)); | 4995 | &(pinstance->ccn.baddr)); |
4596 | 4996 | ||
4597 | pinstance->ldn.msg = pci_alloc_consistent( | 4997 | pinstance->ldn.msg = pci_alloc_consistent( |
@@ -4724,6 +5124,32 @@ static void pmcraid_kill_tasklets(struct pmcraid_instance *pinstance) | |||
4724 | } | 5124 | } |
4725 | 5125 | ||
4726 | /** | 5126 | /** |
5127 | * pmcraid_release_buffers - release per-adapter buffers allocated | ||
5128 | * | ||
5129 | * @pinstance: pointer to adapter soft state | ||
5130 | * | ||
5131 | * Return Value | ||
5132 | * none | ||
5133 | */ | ||
5134 | static void pmcraid_release_buffers(struct pmcraid_instance *pinstance) | ||
5135 | { | ||
5136 | pmcraid_release_config_buffers(pinstance); | ||
5137 | pmcraid_release_control_blocks(pinstance, PMCRAID_MAX_CMD); | ||
5138 | pmcraid_release_cmd_blocks(pinstance, PMCRAID_MAX_CMD); | ||
5139 | pmcraid_release_host_rrqs(pinstance, pinstance->num_hrrq); | ||
5140 | |||
5141 | if (pinstance->inq_data != NULL) { | ||
5142 | pci_free_consistent(pinstance->pdev, | ||
5143 | sizeof(struct pmcraid_inquiry_data), | ||
5144 | pinstance->inq_data, | ||
5145 | pinstance->inq_data_baddr); | ||
5146 | |||
5147 | pinstance->inq_data = NULL; | ||
5148 | pinstance->inq_data_baddr = 0; | ||
5149 | } | ||
5150 | } | ||
5151 | |||
5152 | /** | ||
4727 | * pmcraid_init_buffers - allocates memory and initializes various structures | 5153 | * pmcraid_init_buffers - allocates memory and initializes various structures |
4728 | * @pinstance: pointer to per adapter instance structure | 5154 | * @pinstance: pointer to per adapter instance structure |
4729 | * | 5155 | * |
@@ -4753,20 +5179,32 @@ static int __devinit pmcraid_init_buffers(struct pmcraid_instance *pinstance) | |||
4753 | } | 5179 | } |
4754 | 5180 | ||
4755 | if (pmcraid_allocate_cmd_blocks(pinstance)) { | 5181 | if (pmcraid_allocate_cmd_blocks(pinstance)) { |
4756 | pmcraid_err("couldn't allocate memory for cmd blocks \n"); | 5182 | pmcraid_err("couldn't allocate memory for cmd blocks\n"); |
4757 | pmcraid_release_config_buffers(pinstance); | 5183 | pmcraid_release_config_buffers(pinstance); |
4758 | pmcraid_release_host_rrqs(pinstance, pinstance->num_hrrq); | 5184 | pmcraid_release_host_rrqs(pinstance, pinstance->num_hrrq); |
4759 | return -ENOMEM; | 5185 | return -ENOMEM; |
4760 | } | 5186 | } |
4761 | 5187 | ||
4762 | if (pmcraid_allocate_control_blocks(pinstance)) { | 5188 | if (pmcraid_allocate_control_blocks(pinstance)) { |
4763 | pmcraid_err("couldn't allocate memory control blocks \n"); | 5189 | pmcraid_err("couldn't allocate memory control blocks\n"); |
4764 | pmcraid_release_config_buffers(pinstance); | 5190 | pmcraid_release_config_buffers(pinstance); |
4765 | pmcraid_release_cmd_blocks(pinstance, PMCRAID_MAX_CMD); | 5191 | pmcraid_release_cmd_blocks(pinstance, PMCRAID_MAX_CMD); |
4766 | pmcraid_release_host_rrqs(pinstance, pinstance->num_hrrq); | 5192 | pmcraid_release_host_rrqs(pinstance, pinstance->num_hrrq); |
4767 | return -ENOMEM; | 5193 | return -ENOMEM; |
4768 | } | 5194 | } |
4769 | 5195 | ||
5196 | /* allocate DMAable memory for page D0 INQUIRY buffer */ | ||
5197 | pinstance->inq_data = pci_alloc_consistent( | ||
5198 | pinstance->pdev, | ||
5199 | sizeof(struct pmcraid_inquiry_data), | ||
5200 | &pinstance->inq_data_baddr); | ||
5201 | |||
5202 | if (pinstance->inq_data == NULL) { | ||
5203 | pmcraid_err("couldn't allocate DMA memory for INQUIRY\n"); | ||
5204 | pmcraid_release_buffers(pinstance); | ||
5205 | return -ENOMEM; | ||
5206 | } | ||
5207 | |||
4770 | /* Initialize all the command blocks and add them to free pool. No | 5208 | /* 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 | 5209 | * need to lock (free_pool_lock) as this is done in initialization |
4772 | * itself | 5210 | * itself |
@@ -4785,7 +5223,7 @@ static int __devinit pmcraid_init_buffers(struct pmcraid_instance *pinstance) | |||
4785 | * pmcraid_reinit_buffers - resets various buffer pointers | 5223 | * pmcraid_reinit_buffers - resets various buffer pointers |
4786 | * @pinstance: pointer to adapter instance | 5224 | * @pinstance: pointer to adapter instance |
4787 | * Return value | 5225 | * Return value |
4788 | * none | 5226 | * none |
4789 | */ | 5227 | */ |
4790 | static void pmcraid_reinit_buffers(struct pmcraid_instance *pinstance) | 5228 | static void pmcraid_reinit_buffers(struct pmcraid_instance *pinstance) |
4791 | { | 5229 | { |
@@ -4836,6 +5274,8 @@ static int __devinit pmcraid_init_instance( | |||
4836 | mapped_pci_addr + chip_cfg->ioa_host_intr; | 5274 | mapped_pci_addr + chip_cfg->ioa_host_intr; |
4837 | pint_regs->ioa_host_interrupt_clr_reg = | 5275 | pint_regs->ioa_host_interrupt_clr_reg = |
4838 | mapped_pci_addr + chip_cfg->ioa_host_intr_clr; | 5276 | mapped_pci_addr + chip_cfg->ioa_host_intr_clr; |
5277 | pint_regs->ioa_host_msix_interrupt_reg = | ||
5278 | mapped_pci_addr + chip_cfg->ioa_host_msix_intr; | ||
4839 | pint_regs->host_ioa_interrupt_reg = | 5279 | pint_regs->host_ioa_interrupt_reg = |
4840 | mapped_pci_addr + chip_cfg->host_ioa_intr; | 5280 | mapped_pci_addr + chip_cfg->host_ioa_intr; |
4841 | pint_regs->host_ioa_interrupt_clr_reg = | 5281 | pint_regs->host_ioa_interrupt_clr_reg = |
@@ -4858,6 +5298,7 @@ static int __devinit pmcraid_init_instance( | |||
4858 | init_waitqueue_head(&pinstance->reset_wait_q); | 5298 | init_waitqueue_head(&pinstance->reset_wait_q); |
4859 | 5299 | ||
4860 | atomic_set(&pinstance->outstanding_cmds, 0); | 5300 | atomic_set(&pinstance->outstanding_cmds, 0); |
5301 | atomic_set(&pinstance->last_message_id, 0); | ||
4861 | atomic_set(&pinstance->expose_resources, 0); | 5302 | atomic_set(&pinstance->expose_resources, 0); |
4862 | 5303 | ||
4863 | INIT_LIST_HEAD(&pinstance->free_res_q); | 5304 | INIT_LIST_HEAD(&pinstance->free_res_q); |
@@ -4883,23 +5324,6 @@ static int __devinit pmcraid_init_instance( | |||
4883 | } | 5324 | } |
4884 | 5325 | ||
4885 | /** | 5326 | /** |
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. | 5327 | * pmcraid_shutdown - shutdown adapter controller. |
4904 | * @pdev: pci device struct | 5328 | * @pdev: pci device struct |
4905 | * | 5329 | * |
@@ -4958,7 +5382,7 @@ static int pmcraid_setup_chrdev(struct pmcraid_instance *pinstance) | |||
4958 | pmcraid_release_minor(minor); | 5382 | pmcraid_release_minor(minor); |
4959 | else | 5383 | else |
4960 | device_create(pmcraid_class, NULL, MKDEV(pmcraid_major, minor), | 5384 | device_create(pmcraid_class, NULL, MKDEV(pmcraid_major, minor), |
4961 | NULL, "pmcsas%u", minor); | 5385 | NULL, "%s%u", PMCRAID_DEVFILE, minor); |
4962 | return error; | 5386 | return error; |
4963 | } | 5387 | } |
4964 | 5388 | ||
@@ -5050,7 +5474,6 @@ static int pmcraid_resume(struct pci_dev *pdev) | |||
5050 | struct pmcraid_instance *pinstance = pci_get_drvdata(pdev); | 5474 | struct pmcraid_instance *pinstance = pci_get_drvdata(pdev); |
5051 | struct Scsi_Host *host = pinstance->host; | 5475 | struct Scsi_Host *host = pinstance->host; |
5052 | int rc; | 5476 | int rc; |
5053 | int hrrqs; | ||
5054 | 5477 | ||
5055 | pci_set_power_state(pdev, PCI_D0); | 5478 | pci_set_power_state(pdev, PCI_D0); |
5056 | pci_enable_wake(pdev, PCI_D0, 0); | 5479 | pci_enable_wake(pdev, PCI_D0, 0); |
@@ -5077,8 +5500,8 @@ static int pmcraid_resume(struct pci_dev *pdev) | |||
5077 | goto disable_device; | 5500 | goto disable_device; |
5078 | } | 5501 | } |
5079 | 5502 | ||
5503 | pmcraid_disable_interrupts(pinstance, ~0); | ||
5080 | atomic_set(&pinstance->outstanding_cmds, 0); | 5504 | atomic_set(&pinstance->outstanding_cmds, 0); |
5081 | hrrqs = pinstance->num_hrrq; | ||
5082 | rc = pmcraid_register_interrupt_handler(pinstance); | 5505 | rc = pmcraid_register_interrupt_handler(pinstance); |
5083 | 5506 | ||
5084 | if (rc) { | 5507 | if (rc) { |
@@ -5100,7 +5523,7 @@ static int pmcraid_resume(struct pci_dev *pdev) | |||
5100 | * state. | 5523 | * state. |
5101 | */ | 5524 | */ |
5102 | if (pmcraid_reset_bringup(pinstance)) { | 5525 | if (pmcraid_reset_bringup(pinstance)) { |
5103 | dev_err(&pdev->dev, "couldn't initialize IOA \n"); | 5526 | dev_err(&pdev->dev, "couldn't initialize IOA\n"); |
5104 | rc = -ENODEV; | 5527 | rc = -ENODEV; |
5105 | goto release_tasklets; | 5528 | goto release_tasklets; |
5106 | } | 5529 | } |
@@ -5108,6 +5531,7 @@ static int pmcraid_resume(struct pci_dev *pdev) | |||
5108 | return 0; | 5531 | return 0; |
5109 | 5532 | ||
5110 | release_tasklets: | 5533 | release_tasklets: |
5534 | pmcraid_disable_interrupts(pinstance, ~0); | ||
5111 | pmcraid_kill_tasklets(pinstance); | 5535 | pmcraid_kill_tasklets(pinstance); |
5112 | pmcraid_unregister_interrupt_handler(pinstance); | 5536 | pmcraid_unregister_interrupt_handler(pinstance); |
5113 | 5537 | ||
@@ -5129,7 +5553,7 @@ disable_device: | |||
5129 | 5553 | ||
5130 | /** | 5554 | /** |
5131 | * pmcraid_complete_ioa_reset - Called by either timer or tasklet during | 5555 | * pmcraid_complete_ioa_reset - Called by either timer or tasklet during |
5132 | * completion of the ioa reset | 5556 | * completion of the ioa reset |
5133 | * @cmd: pointer to reset command block | 5557 | * @cmd: pointer to reset command block |
5134 | */ | 5558 | */ |
5135 | static void pmcraid_complete_ioa_reset(struct pmcraid_cmd *cmd) | 5559 | static void pmcraid_complete_ioa_reset(struct pmcraid_cmd *cmd) |
@@ -5204,11 +5628,14 @@ static void pmcraid_init_res_table(struct pmcraid_cmd *cmd) | |||
5204 | struct pmcraid_config_table_entry *cfgte; | 5628 | struct pmcraid_config_table_entry *cfgte; |
5205 | unsigned long lock_flags; | 5629 | unsigned long lock_flags; |
5206 | int found, rc, i; | 5630 | int found, rc, i; |
5631 | u16 fw_version; | ||
5207 | LIST_HEAD(old_res); | 5632 | LIST_HEAD(old_res); |
5208 | 5633 | ||
5209 | if (pinstance->cfg_table->flags & MICROCODE_UPDATE_REQUIRED) | 5634 | if (pinstance->cfg_table->flags & MICROCODE_UPDATE_REQUIRED) |
5210 | pmcraid_err("IOA requires microcode download\n"); | 5635 | pmcraid_err("IOA requires microcode download\n"); |
5211 | 5636 | ||
5637 | fw_version = be16_to_cpu(pinstance->inq_data->fw_version); | ||
5638 | |||
5212 | /* resource list is protected by pinstance->resource_lock. | 5639 | /* resource list is protected by pinstance->resource_lock. |
5213 | * init_res_table can be called from probe (user-thread) or runtime | 5640 | * init_res_table can be called from probe (user-thread) or runtime |
5214 | * reset (timer/tasklet) | 5641 | * reset (timer/tasklet) |
@@ -5219,9 +5646,14 @@ static void pmcraid_init_res_table(struct pmcraid_cmd *cmd) | |||
5219 | list_move_tail(&res->queue, &old_res); | 5646 | list_move_tail(&res->queue, &old_res); |
5220 | 5647 | ||
5221 | for (i = 0; i < pinstance->cfg_table->num_entries; i++) { | 5648 | for (i = 0; i < pinstance->cfg_table->num_entries; i++) { |
5222 | cfgte = &pinstance->cfg_table->entries[i]; | 5649 | if (be16_to_cpu(pinstance->inq_data->fw_version) <= |
5650 | PMCRAID_FW_VERSION_1) | ||
5651 | cfgte = &pinstance->cfg_table->entries[i]; | ||
5652 | else | ||
5653 | cfgte = (struct pmcraid_config_table_entry *) | ||
5654 | &pinstance->cfg_table->entries_ext[i]; | ||
5223 | 5655 | ||
5224 | if (!pmcraid_expose_resource(cfgte)) | 5656 | if (!pmcraid_expose_resource(fw_version, cfgte)) |
5225 | continue; | 5657 | continue; |
5226 | 5658 | ||
5227 | found = 0; | 5659 | found = 0; |
@@ -5263,10 +5695,12 @@ static void pmcraid_init_res_table(struct pmcraid_cmd *cmd) | |||
5263 | */ | 5695 | */ |
5264 | if (found) { | 5696 | if (found) { |
5265 | memcpy(&res->cfg_entry, cfgte, | 5697 | memcpy(&res->cfg_entry, cfgte, |
5266 | sizeof(struct pmcraid_config_table_entry)); | 5698 | pinstance->config_table_entry_size); |
5267 | pmcraid_info("New res type:%x, vset:%x, addr:%x:\n", | 5699 | pmcraid_info("New res type:%x, vset:%x, addr:%x:\n", |
5268 | res->cfg_entry.resource_type, | 5700 | res->cfg_entry.resource_type, |
5269 | res->cfg_entry.unique_flags1, | 5701 | (fw_version <= PMCRAID_FW_VERSION_1 ? |
5702 | res->cfg_entry.unique_flags1 : | ||
5703 | res->cfg_entry.array_id & 0xFF), | ||
5270 | le32_to_cpu(res->cfg_entry.resource_address)); | 5704 | le32_to_cpu(res->cfg_entry.resource_address)); |
5271 | } | 5705 | } |
5272 | } | 5706 | } |
@@ -5306,6 +5740,14 @@ static void pmcraid_querycfg(struct pmcraid_cmd *cmd) | |||
5306 | struct pmcraid_instance *pinstance = cmd->drv_inst; | 5740 | struct pmcraid_instance *pinstance = cmd->drv_inst; |
5307 | int cfg_table_size = cpu_to_be32(sizeof(struct pmcraid_config_table)); | 5741 | int cfg_table_size = cpu_to_be32(sizeof(struct pmcraid_config_table)); |
5308 | 5742 | ||
5743 | if (be16_to_cpu(pinstance->inq_data->fw_version) <= | ||
5744 | PMCRAID_FW_VERSION_1) | ||
5745 | pinstance->config_table_entry_size = | ||
5746 | sizeof(struct pmcraid_config_table_entry); | ||
5747 | else | ||
5748 | pinstance->config_table_entry_size = | ||
5749 | sizeof(struct pmcraid_config_table_entry_ext); | ||
5750 | |||
5309 | ioarcb->request_type = REQ_TYPE_IOACMD; | 5751 | ioarcb->request_type = REQ_TYPE_IOACMD; |
5310 | ioarcb->resource_handle = cpu_to_le32(PMCRAID_IOA_RES_HANDLE); | 5752 | ioarcb->resource_handle = cpu_to_le32(PMCRAID_IOA_RES_HANDLE); |
5311 | 5753 | ||
@@ -5338,7 +5780,7 @@ static void pmcraid_querycfg(struct pmcraid_cmd *cmd) | |||
5338 | 5780 | ||
5339 | 5781 | ||
5340 | /** | 5782 | /** |
5341 | * pmcraid_probe - PCI probe entry pointer for PMC MaxRaid controller driver | 5783 | * pmcraid_probe - PCI probe entry pointer for PMC MaxRAID controller driver |
5342 | * @pdev: pointer to pci device structure | 5784 | * @pdev: pointer to pci device structure |
5343 | * @dev_id: pointer to device ids structure | 5785 | * @dev_id: pointer to device ids structure |
5344 | * | 5786 | * |
@@ -5485,7 +5927,7 @@ static int __devinit pmcraid_probe( | |||
5485 | */ | 5927 | */ |
5486 | pmcraid_info("starting IOA initialization sequence\n"); | 5928 | pmcraid_info("starting IOA initialization sequence\n"); |
5487 | if (pmcraid_reset_bringup(pinstance)) { | 5929 | if (pmcraid_reset_bringup(pinstance)) { |
5488 | dev_err(&pdev->dev, "couldn't initialize IOA \n"); | 5930 | dev_err(&pdev->dev, "couldn't initialize IOA\n"); |
5489 | rc = 1; | 5931 | rc = 1; |
5490 | goto out_release_bufs; | 5932 | goto out_release_bufs; |
5491 | } | 5933 | } |
diff --git a/drivers/scsi/pmcraid.h b/drivers/scsi/pmcraid.h index b8ad07c3449e..6cfa0145a1d7 100644 --- a/drivers/scsi/pmcraid.h +++ b/drivers/scsi/pmcraid.h | |||
@@ -40,10 +40,12 @@ | |||
40 | * Driver version: version string in major_version.minor_version.patch format | 40 | * Driver version: version string in major_version.minor_version.patch format |
41 | * Driver date : date information in "Mon dd yyyy" format | 41 | * Driver date : date information in "Mon dd yyyy" format |
42 | */ | 42 | */ |
43 | #define PMCRAID_DRIVER_NAME "PMC MaxRAID" | 43 | #define PMCRAID_DRIVER_NAME "PMC MaxRAID" |
44 | #define PMCRAID_DEVFILE "pmcsas" | 44 | #define PMCRAID_DEVFILE "pmcsas" |
45 | #define PMCRAID_DRIVER_VERSION "1.0.2" | 45 | #define PMCRAID_DRIVER_VERSION "2.0.2" |
46 | #define PMCRAID_DRIVER_DATE __DATE__ | 46 | #define PMCRAID_DRIVER_DATE __DATE__ |
47 | |||
48 | #define PMCRAID_FW_VERSION_1 0x002 | ||
47 | 49 | ||
48 | /* Maximum number of adapters supported by current version of the driver */ | 50 | /* Maximum number of adapters supported by current version of the driver */ |
49 | #define PMCRAID_MAX_ADAPTERS 1024 | 51 | #define PMCRAID_MAX_ADAPTERS 1024 |
@@ -85,17 +87,17 @@ | |||
85 | #define PMCRAID_IOARCB_ALIGNMENT 32 | 87 | #define PMCRAID_IOARCB_ALIGNMENT 32 |
86 | #define PMCRAID_IOADL_ALIGNMENT 16 | 88 | #define PMCRAID_IOADL_ALIGNMENT 16 |
87 | #define PMCRAID_IOASA_ALIGNMENT 4 | 89 | #define PMCRAID_IOASA_ALIGNMENT 4 |
88 | #define PMCRAID_NUM_MSIX_VECTORS 1 | 90 | #define PMCRAID_NUM_MSIX_VECTORS 16 |
89 | 91 | ||
90 | /* various other limits */ | 92 | /* various other limits */ |
91 | #define PMCRAID_VENDOR_ID_LEN 8 | 93 | #define PMCRAID_VENDOR_ID_LEN 8 |
92 | #define PMCRAID_PRODUCT_ID_LEN 16 | 94 | #define PMCRAID_PRODUCT_ID_LEN 16 |
93 | #define PMCRAID_SERIAL_NUM_LEN 8 | 95 | #define PMCRAID_SERIAL_NUM_LEN 8 |
94 | #define PMCRAID_LUN_LEN 8 | 96 | #define PMCRAID_LUN_LEN 8 |
95 | #define PMCRAID_MAX_CDB_LEN 16 | 97 | #define PMCRAID_MAX_CDB_LEN 16 |
96 | #define PMCRAID_DEVICE_ID_LEN 8 | 98 | #define PMCRAID_DEVICE_ID_LEN 8 |
97 | #define PMCRAID_SENSE_DATA_LEN 256 | 99 | #define PMCRAID_SENSE_DATA_LEN 256 |
98 | #define PMCRAID_ADD_CMD_PARAM_LEN 48 | 100 | #define PMCRAID_ADD_CMD_PARAM_LEN 48 |
99 | 101 | ||
100 | #define PMCRAID_MAX_BUS_TO_SCAN 1 | 102 | #define PMCRAID_MAX_BUS_TO_SCAN 1 |
101 | #define PMCRAID_MAX_NUM_TARGETS_PER_BUS 256 | 103 | #define PMCRAID_MAX_NUM_TARGETS_PER_BUS 256 |
@@ -116,17 +118,10 @@ | |||
116 | #define PMCRAID_VSET_MAX_SECTORS 512 | 118 | #define PMCRAID_VSET_MAX_SECTORS 512 |
117 | #define PMCRAID_MAX_CMD_PER_LUN 254 | 119 | #define PMCRAID_MAX_CMD_PER_LUN 254 |
118 | 120 | ||
119 | /* Number of configuration table entries (resources) */ | 121 | /* Number of configuration table entries (resources), includes 1 FP, |
120 | #define PMCRAID_MAX_NUM_OF_VSETS 240 | 122 | * 1 Enclosure device |
121 | 123 | */ | |
122 | /* Todo : Check max limit for Phase 1 */ | 124 | #define PMCRAID_MAX_RESOURCES 256 |
123 | #define PMCRAID_MAX_NUM_OF_PHY_DEVS 256 | ||
124 | |||
125 | /* MAX_NUM_OF_DEVS includes 1 FP, 1 Dummy Enclosure device */ | ||
126 | #define PMCRAID_MAX_NUM_OF_DEVS \ | ||
127 | (PMCRAID_MAX_NUM_OF_VSETS + PMCRAID_MAX_NUM_OF_PHY_DEVS + 2) | ||
128 | |||
129 | #define PMCRAID_MAX_RESOURCES PMCRAID_MAX_NUM_OF_DEVS | ||
130 | 125 | ||
131 | /* Adapter Commands used by driver */ | 126 | /* Adapter Commands used by driver */ |
132 | #define PMCRAID_QUERY_RESOURCE_STATE 0xC2 | 127 | #define PMCRAID_QUERY_RESOURCE_STATE 0xC2 |
@@ -177,6 +172,7 @@ | |||
177 | #define PMCRAID_IOASC_SENSE_STATUS(ioasc) ((ioasc) & 0x000000ff) | 172 | #define PMCRAID_IOASC_SENSE_STATUS(ioasc) ((ioasc) & 0x000000ff) |
178 | 173 | ||
179 | #define PMCRAID_IOASC_GOOD_COMPLETION 0x00000000 | 174 | #define PMCRAID_IOASC_GOOD_COMPLETION 0x00000000 |
175 | #define PMCRAID_IOASC_GC_IOARCB_NOTFOUND 0x005A0000 | ||
180 | #define PMCRAID_IOASC_NR_INIT_CMD_REQUIRED 0x02040200 | 176 | #define PMCRAID_IOASC_NR_INIT_CMD_REQUIRED 0x02040200 |
181 | #define PMCRAID_IOASC_NR_IOA_RESET_REQUIRED 0x02048000 | 177 | #define PMCRAID_IOASC_NR_IOA_RESET_REQUIRED 0x02048000 |
182 | #define PMCRAID_IOASC_NR_SYNC_REQUIRED 0x023F0000 | 178 | #define PMCRAID_IOASC_NR_SYNC_REQUIRED 0x023F0000 |
@@ -187,12 +183,12 @@ | |||
187 | #define PMCRAID_IOASC_HW_IOA_RESET_REQUIRED 0x04448600 | 183 | #define PMCRAID_IOASC_HW_IOA_RESET_REQUIRED 0x04448600 |
188 | #define PMCRAID_IOASC_IR_INVALID_RESOURCE_HANDLE 0x05250000 | 184 | #define PMCRAID_IOASC_IR_INVALID_RESOURCE_HANDLE 0x05250000 |
189 | #define PMCRAID_IOASC_AC_TERMINATED_BY_HOST 0x0B5A0000 | 185 | #define PMCRAID_IOASC_AC_TERMINATED_BY_HOST 0x0B5A0000 |
190 | #define PMCRAID_IOASC_UA_BUS_WAS_RESET 0x06290000 | 186 | #define PMCRAID_IOASC_UA_BUS_WAS_RESET 0x06290000 |
191 | #define PMCRAID_IOASC_UA_BUS_WAS_RESET_BY_OTHER 0x06298000 | 187 | #define PMCRAID_IOASC_UA_BUS_WAS_RESET_BY_OTHER 0x06298000 |
192 | 188 | ||
193 | /* Driver defined IOASCs */ | 189 | /* Driver defined IOASCs */ |
194 | #define PMCRAID_IOASC_IOA_WAS_RESET 0x10000001 | 190 | #define PMCRAID_IOASC_IOA_WAS_RESET 0x10000001 |
195 | #define PMCRAID_IOASC_PCI_ACCESS_ERROR 0x10000002 | 191 | #define PMCRAID_IOASC_PCI_ACCESS_ERROR 0x10000002 |
196 | 192 | ||
197 | /* Various timeout values (in milliseconds) used. If any of these are chip | 193 | /* Various timeout values (in milliseconds) used. If any of these are chip |
198 | * specific, move them to pmcraid_chip_details structure. | 194 | * specific, move them to pmcraid_chip_details structure. |
@@ -336,6 +332,13 @@ struct pmcraid_config_table_entry { | |||
336 | __u8 lun[PMCRAID_LUN_LEN]; | 332 | __u8 lun[PMCRAID_LUN_LEN]; |
337 | } __attribute__((packed, aligned(4))); | 333 | } __attribute__((packed, aligned(4))); |
338 | 334 | ||
335 | /* extended configuration table sizes are of 64 bytes in size */ | ||
336 | #define PMCRAID_CFGTE_EXT_SIZE 32 | ||
337 | struct pmcraid_config_table_entry_ext { | ||
338 | struct pmcraid_config_table_entry cfgte; | ||
339 | __u8 cfgte_ext[PMCRAID_CFGTE_EXT_SIZE]; | ||
340 | }; | ||
341 | |||
339 | /* resource types (config_table_entry.resource_type values) */ | 342 | /* resource types (config_table_entry.resource_type values) */ |
340 | #define RES_TYPE_AF_DASD 0x00 | 343 | #define RES_TYPE_AF_DASD 0x00 |
341 | #define RES_TYPE_GSCSI 0x01 | 344 | #define RES_TYPE_GSCSI 0x01 |
@@ -376,7 +379,12 @@ struct pmcraid_config_table { | |||
376 | __u8 reserved1; | 379 | __u8 reserved1; |
377 | __u8 flags; | 380 | __u8 flags; |
378 | __u8 reserved2[11]; | 381 | __u8 reserved2[11]; |
379 | struct pmcraid_config_table_entry entries[PMCRAID_MAX_RESOURCES]; | 382 | union { |
383 | struct pmcraid_config_table_entry | ||
384 | entries[PMCRAID_MAX_RESOURCES]; | ||
385 | struct pmcraid_config_table_entry_ext | ||
386 | entries_ext[PMCRAID_MAX_RESOURCES]; | ||
387 | }; | ||
380 | } __attribute__((packed, aligned(4))); | 388 | } __attribute__((packed, aligned(4))); |
381 | 389 | ||
382 | /* config_table.flags value */ | 390 | /* config_table.flags value */ |
@@ -385,7 +393,7 @@ struct pmcraid_config_table { | |||
385 | /* | 393 | /* |
386 | * HCAM format | 394 | * HCAM format |
387 | */ | 395 | */ |
388 | #define PMCRAID_HOSTRCB_LDNSIZE 4056 | 396 | #define PMCRAID_HOSTRCB_LDNSIZE 4056 |
389 | 397 | ||
390 | /* Error log notification format */ | 398 | /* Error log notification format */ |
391 | struct pmcraid_hostrcb_error { | 399 | struct pmcraid_hostrcb_error { |
@@ -416,6 +424,15 @@ struct pmcraid_hcam_hdr { | |||
416 | struct pmcraid_hcam_ccn { | 424 | struct pmcraid_hcam_ccn { |
417 | struct pmcraid_hcam_hdr header; | 425 | struct pmcraid_hcam_hdr header; |
418 | struct pmcraid_config_table_entry cfg_entry; | 426 | struct pmcraid_config_table_entry cfg_entry; |
427 | struct pmcraid_config_table_entry cfg_entry_old; | ||
428 | } __attribute__((packed, aligned(4))); | ||
429 | |||
430 | #define PMCRAID_CCN_EXT_SIZE 3944 | ||
431 | struct pmcraid_hcam_ccn_ext { | ||
432 | struct pmcraid_hcam_hdr header; | ||
433 | struct pmcraid_config_table_entry_ext cfg_entry; | ||
434 | struct pmcraid_config_table_entry_ext cfg_entry_old; | ||
435 | __u8 reserved[PMCRAID_CCN_EXT_SIZE]; | ||
419 | } __attribute__((packed, aligned(4))); | 436 | } __attribute__((packed, aligned(4))); |
420 | 437 | ||
421 | struct pmcraid_hcam_ldn { | 438 | struct pmcraid_hcam_ldn { |
@@ -431,6 +448,8 @@ struct pmcraid_hcam_ldn { | |||
431 | #define NOTIFICATION_TYPE_ENTRY_CHANGED 0x0 | 448 | #define NOTIFICATION_TYPE_ENTRY_CHANGED 0x0 |
432 | #define NOTIFICATION_TYPE_ENTRY_NEW 0x1 | 449 | #define NOTIFICATION_TYPE_ENTRY_NEW 0x1 |
433 | #define NOTIFICATION_TYPE_ENTRY_DELETED 0x2 | 450 | #define NOTIFICATION_TYPE_ENTRY_DELETED 0x2 |
451 | #define NOTIFICATION_TYPE_STATE_CHANGE 0x3 | ||
452 | #define NOTIFICATION_TYPE_ENTRY_STATECHANGED 0x4 | ||
434 | #define NOTIFICATION_TYPE_ERROR_LOG 0x10 | 453 | #define NOTIFICATION_TYPE_ERROR_LOG 0x10 |
435 | #define NOTIFICATION_TYPE_INFORMATION_LOG 0x11 | 454 | #define NOTIFICATION_TYPE_INFORMATION_LOG 0x11 |
436 | 455 | ||
@@ -460,6 +479,7 @@ struct pmcraid_chip_details { | |||
460 | unsigned long mailbox; | 479 | unsigned long mailbox; |
461 | unsigned long global_intr_mask; | 480 | unsigned long global_intr_mask; |
462 | unsigned long ioa_host_intr; | 481 | unsigned long ioa_host_intr; |
482 | unsigned long ioa_host_msix_intr; | ||
463 | unsigned long ioa_host_intr_clr; | 483 | unsigned long ioa_host_intr_clr; |
464 | unsigned long ioa_host_mask; | 484 | unsigned long ioa_host_mask; |
465 | unsigned long ioa_host_mask_clr; | 485 | unsigned long ioa_host_mask_clr; |
@@ -482,6 +502,7 @@ struct pmcraid_chip_details { | |||
482 | #define INTRS_IOA_PROCESSOR_ERROR PMC_BIT32(29) | 502 | #define INTRS_IOA_PROCESSOR_ERROR PMC_BIT32(29) |
483 | #define INTRS_HRRQ_VALID PMC_BIT32(30) | 503 | #define INTRS_HRRQ_VALID PMC_BIT32(30) |
484 | #define INTRS_OPERATIONAL_STATUS PMC_BIT32(0) | 504 | #define INTRS_OPERATIONAL_STATUS PMC_BIT32(0) |
505 | #define INTRS_ALLOW_MSIX_VECTOR0 PMC_BIT32(31) | ||
485 | 506 | ||
486 | /* Host to IOA Doorbells */ | 507 | /* Host to IOA Doorbells */ |
487 | #define DOORBELL_RUNTIME_RESET PMC_BIT32(1) | 508 | #define DOORBELL_RUNTIME_RESET PMC_BIT32(1) |
@@ -489,10 +510,12 @@ struct pmcraid_chip_details { | |||
489 | #define DOORBELL_IOA_DEBUG_ALERT PMC_BIT32(9) | 510 | #define DOORBELL_IOA_DEBUG_ALERT PMC_BIT32(9) |
490 | #define DOORBELL_ENABLE_DESTRUCTIVE_DIAGS PMC_BIT32(8) | 511 | #define DOORBELL_ENABLE_DESTRUCTIVE_DIAGS PMC_BIT32(8) |
491 | #define DOORBELL_IOA_START_BIST PMC_BIT32(23) | 512 | #define DOORBELL_IOA_START_BIST PMC_BIT32(23) |
513 | #define DOORBELL_INTR_MODE_MSIX PMC_BIT32(25) | ||
514 | #define DOORBELL_INTR_MSIX_CLR PMC_BIT32(26) | ||
492 | #define DOORBELL_RESET_IOA PMC_BIT32(31) | 515 | #define DOORBELL_RESET_IOA PMC_BIT32(31) |
493 | 516 | ||
494 | /* Global interrupt mask register value */ | 517 | /* Global interrupt mask register value */ |
495 | #define GLOBAL_INTERRUPT_MASK 0x4ULL | 518 | #define GLOBAL_INTERRUPT_MASK 0x5ULL |
496 | 519 | ||
497 | #define PMCRAID_ERROR_INTERRUPTS (INTRS_IOARCB_TRANSFER_FAILED | \ | 520 | #define PMCRAID_ERROR_INTERRUPTS (INTRS_IOARCB_TRANSFER_FAILED | \ |
498 | INTRS_IOA_UNIT_CHECK | \ | 521 | INTRS_IOA_UNIT_CHECK | \ |
@@ -503,8 +526,8 @@ struct pmcraid_chip_details { | |||
503 | 526 | ||
504 | #define PMCRAID_PCI_INTERRUPTS (PMCRAID_ERROR_INTERRUPTS | \ | 527 | #define PMCRAID_PCI_INTERRUPTS (PMCRAID_ERROR_INTERRUPTS | \ |
505 | INTRS_HRRQ_VALID | \ | 528 | INTRS_HRRQ_VALID | \ |
506 | INTRS_CRITICAL_OP_IN_PROGRESS |\ | 529 | INTRS_TRANSITION_TO_OPERATIONAL |\ |
507 | INTRS_TRANSITION_TO_OPERATIONAL) | 530 | INTRS_ALLOW_MSIX_VECTOR0) |
508 | 531 | ||
509 | /* control_block, associated with each of the commands contains IOARCB, IOADLs | 532 | /* control_block, associated with each of the commands contains IOARCB, IOADLs |
510 | * memory for IOASA. Additional 3 * 16 bytes are allocated in order to support | 533 | * memory for IOASA. Additional 3 * 16 bytes are allocated in order to support |
@@ -526,17 +549,24 @@ struct pmcraid_sglist { | |||
526 | struct scatterlist scatterlist[1]; | 549 | struct scatterlist scatterlist[1]; |
527 | }; | 550 | }; |
528 | 551 | ||
552 | /* page D0 inquiry data of focal point resource */ | ||
553 | struct pmcraid_inquiry_data { | ||
554 | __u8 ph_dev_type; | ||
555 | __u8 page_code; | ||
556 | __u8 reserved1; | ||
557 | __u8 add_page_len; | ||
558 | __u8 length; | ||
559 | __u8 reserved2; | ||
560 | __le16 fw_version; | ||
561 | __u8 reserved3[16]; | ||
562 | }; | ||
563 | |||
529 | /* pmcraid_cmd - LLD representation of SCSI command */ | 564 | /* pmcraid_cmd - LLD representation of SCSI command */ |
530 | struct pmcraid_cmd { | 565 | struct pmcraid_cmd { |
531 | 566 | ||
532 | /* Ptr and bus address of DMA.able control block for this command */ | 567 | /* Ptr and bus address of DMA.able control block for this command */ |
533 | struct pmcraid_control_block *ioa_cb; | 568 | struct pmcraid_control_block *ioa_cb; |
534 | dma_addr_t ioa_cb_bus_addr; | 569 | dma_addr_t ioa_cb_bus_addr; |
535 | |||
536 | /* sense buffer for REQUEST SENSE command if firmware is not sending | ||
537 | * auto sense data | ||
538 | */ | ||
539 | dma_addr_t sense_buffer_dma; | ||
540 | dma_addr_t dma_handle; | 570 | dma_addr_t dma_handle; |
541 | u8 *sense_buffer; | 571 | u8 *sense_buffer; |
542 | 572 | ||
@@ -556,11 +586,22 @@ struct pmcraid_cmd { | |||
556 | 586 | ||
557 | struct pmcraid_sglist *sglist; /* used for passthrough IOCTLs */ | 587 | struct pmcraid_sglist *sglist; /* used for passthrough IOCTLs */ |
558 | 588 | ||
559 | /* scratch used during reset sequence */ | 589 | /* scratch used */ |
560 | union { | 590 | union { |
591 | /* during reset sequence */ | ||
561 | unsigned long time_left; | 592 | unsigned long time_left; |
562 | struct pmcraid_resource_entry *res; | 593 | struct pmcraid_resource_entry *res; |
563 | } u; | 594 | int hrrq_index; |
595 | |||
596 | /* used during IO command error handling. Sense buffer | ||
597 | * for REQUEST SENSE command if firmware is not sending | ||
598 | * auto sense data | ||
599 | */ | ||
600 | struct { | ||
601 | u8 *sense_buffer; | ||
602 | dma_addr_t sense_buffer_dma; | ||
603 | }; | ||
604 | }; | ||
564 | }; | 605 | }; |
565 | 606 | ||
566 | /* | 607 | /* |
@@ -568,6 +609,7 @@ struct pmcraid_cmd { | |||
568 | */ | 609 | */ |
569 | struct pmcraid_interrupts { | 610 | struct pmcraid_interrupts { |
570 | void __iomem *ioa_host_interrupt_reg; | 611 | void __iomem *ioa_host_interrupt_reg; |
612 | void __iomem *ioa_host_msix_interrupt_reg; | ||
571 | void __iomem *ioa_host_interrupt_clr_reg; | 613 | void __iomem *ioa_host_interrupt_clr_reg; |
572 | void __iomem *ioa_host_interrupt_mask_reg; | 614 | void __iomem *ioa_host_interrupt_mask_reg; |
573 | void __iomem *ioa_host_interrupt_mask_clr_reg; | 615 | void __iomem *ioa_host_interrupt_mask_clr_reg; |
@@ -578,11 +620,12 @@ struct pmcraid_interrupts { | |||
578 | 620 | ||
579 | /* ISR parameters LLD allocates (one for each MSI-X if enabled) vectors */ | 621 | /* ISR parameters LLD allocates (one for each MSI-X if enabled) vectors */ |
580 | struct pmcraid_isr_param { | 622 | struct pmcraid_isr_param { |
581 | u8 hrrq_id; /* hrrq entry index */ | ||
582 | u16 vector; /* allocated msi-x vector */ | ||
583 | struct pmcraid_instance *drv_inst; | 623 | struct pmcraid_instance *drv_inst; |
624 | u16 vector; /* allocated msi-x vector */ | ||
625 | u8 hrrq_id; /* hrrq entry index */ | ||
584 | }; | 626 | }; |
585 | 627 | ||
628 | |||
586 | /* AEN message header sent as part of event data to applications */ | 629 | /* AEN message header sent as part of event data to applications */ |
587 | struct pmcraid_aen_msg { | 630 | struct pmcraid_aen_msg { |
588 | u32 hostno; | 631 | u32 hostno; |
@@ -591,6 +634,19 @@ struct pmcraid_aen_msg { | |||
591 | u8 data[0]; | 634 | u8 data[0]; |
592 | }; | 635 | }; |
593 | 636 | ||
637 | /* Controller state event message type */ | ||
638 | struct pmcraid_state_msg { | ||
639 | struct pmcraid_aen_msg msg; | ||
640 | u32 ioa_state; | ||
641 | }; | ||
642 | |||
643 | #define PMC_DEVICE_EVENT_RESET_START 0x11000000 | ||
644 | #define PMC_DEVICE_EVENT_RESET_SUCCESS 0x11000001 | ||
645 | #define PMC_DEVICE_EVENT_RESET_FAILED 0x11000002 | ||
646 | #define PMC_DEVICE_EVENT_SHUTDOWN_START 0x11000003 | ||
647 | #define PMC_DEVICE_EVENT_SHUTDOWN_SUCCESS 0x11000004 | ||
648 | #define PMC_DEVICE_EVENT_SHUTDOWN_FAILED 0x11000005 | ||
649 | |||
594 | struct pmcraid_hostrcb { | 650 | struct pmcraid_hostrcb { |
595 | struct pmcraid_instance *drv_inst; | 651 | struct pmcraid_instance *drv_inst; |
596 | struct pmcraid_aen_msg *msg; | 652 | struct pmcraid_aen_msg *msg; |
@@ -628,6 +684,7 @@ struct pmcraid_instance { | |||
628 | /* HostRCBs needed for HCAM */ | 684 | /* HostRCBs needed for HCAM */ |
629 | struct pmcraid_hostrcb ldn; | 685 | struct pmcraid_hostrcb ldn; |
630 | struct pmcraid_hostrcb ccn; | 686 | struct pmcraid_hostrcb ccn; |
687 | struct pmcraid_state_msg scn; /* controller state change msg */ | ||
631 | 688 | ||
632 | 689 | ||
633 | /* Bus address of start of HRRQ */ | 690 | /* Bus address of start of HRRQ */ |
@@ -645,12 +702,15 @@ struct pmcraid_instance { | |||
645 | /* Lock for HRRQ access */ | 702 | /* Lock for HRRQ access */ |
646 | spinlock_t hrrq_lock[PMCRAID_NUM_MSIX_VECTORS]; | 703 | spinlock_t hrrq_lock[PMCRAID_NUM_MSIX_VECTORS]; |
647 | 704 | ||
705 | struct pmcraid_inquiry_data *inq_data; | ||
706 | dma_addr_t inq_data_baddr; | ||
707 | |||
708 | /* size of configuration table entry, varies based on the firmware */ | ||
709 | u32 config_table_entry_size; | ||
710 | |||
648 | /* Expected toggle bit at host */ | 711 | /* Expected toggle bit at host */ |
649 | u8 host_toggle_bit[PMCRAID_NUM_MSIX_VECTORS]; | 712 | u8 host_toggle_bit[PMCRAID_NUM_MSIX_VECTORS]; |
650 | 713 | ||
651 | /* No of Reset IOA retries . IOA marked dead if threshold exceeds */ | ||
652 | u8 ioa_reset_attempts; | ||
653 | #define PMCRAID_RESET_ATTEMPTS 3 | ||
654 | 714 | ||
655 | /* Wait Q for threads to wait for Reset IOA completion */ | 715 | /* Wait Q for threads to wait for Reset IOA completion */ |
656 | wait_queue_head_t reset_wait_q; | 716 | wait_queue_head_t reset_wait_q; |
@@ -664,14 +724,22 @@ struct pmcraid_instance { | |||
664 | struct Scsi_Host *host; /* mid layer interface structure handle */ | 724 | struct Scsi_Host *host; /* mid layer interface structure handle */ |
665 | struct pci_dev *pdev; /* PCI device structure handle */ | 725 | struct pci_dev *pdev; /* PCI device structure handle */ |
666 | 726 | ||
727 | /* No of Reset IOA retries . IOA marked dead if threshold exceeds */ | ||
728 | u8 ioa_reset_attempts; | ||
729 | #define PMCRAID_RESET_ATTEMPTS 3 | ||
730 | |||
667 | u8 current_log_level; /* default level for logging IOASC errors */ | 731 | u8 current_log_level; /* default level for logging IOASC errors */ |
668 | 732 | ||
669 | u8 num_hrrq; /* Number of interrupt vectors allocated */ | 733 | u8 num_hrrq; /* Number of interrupt vectors allocated */ |
734 | u8 interrupt_mode; /* current interrupt mode legacy or msix */ | ||
670 | dev_t dev; /* Major-Minor numbers for Char device */ | 735 | dev_t dev; /* Major-Minor numbers for Char device */ |
671 | 736 | ||
672 | /* Used as ISR handler argument */ | 737 | /* Used as ISR handler argument */ |
673 | struct pmcraid_isr_param hrrq_vector[PMCRAID_NUM_MSIX_VECTORS]; | 738 | struct pmcraid_isr_param hrrq_vector[PMCRAID_NUM_MSIX_VECTORS]; |
674 | 739 | ||
740 | /* Message id as filled in last fired IOARCB, used to identify HRRQ */ | ||
741 | atomic_t last_message_id; | ||
742 | |||
675 | /* configuration table */ | 743 | /* configuration table */ |
676 | struct pmcraid_config_table *cfg_table; | 744 | struct pmcraid_config_table *cfg_table; |
677 | dma_addr_t cfg_table_bus_addr; | 745 | dma_addr_t cfg_table_bus_addr; |
@@ -686,8 +754,14 @@ struct pmcraid_instance { | |||
686 | 754 | ||
687 | struct list_head free_cmd_pool; | 755 | struct list_head free_cmd_pool; |
688 | struct list_head pending_cmd_pool; | 756 | struct list_head pending_cmd_pool; |
689 | spinlock_t free_pool_lock; /* free pool lock */ | 757 | spinlock_t free_pool_lock; /* free pool lock */ |
690 | spinlock_t pending_pool_lock; /* pending pool lock */ | 758 | spinlock_t pending_pool_lock; /* pending pool lock */ |
759 | |||
760 | /* Tasklet to handle deferred processing */ | ||
761 | struct tasklet_struct isr_tasklet[PMCRAID_NUM_MSIX_VECTORS]; | ||
762 | |||
763 | /* Work-queue (Shared) for deferred reset processing */ | ||
764 | struct work_struct worker_q; | ||
691 | 765 | ||
692 | /* No of IO commands pending with FW */ | 766 | /* No of IO commands pending with FW */ |
693 | atomic_t outstanding_cmds; | 767 | atomic_t outstanding_cmds; |
@@ -695,11 +769,6 @@ struct pmcraid_instance { | |||
695 | /* should add/delete resources to mid-layer now ?*/ | 769 | /* should add/delete resources to mid-layer now ?*/ |
696 | atomic_t expose_resources; | 770 | atomic_t expose_resources; |
697 | 771 | ||
698 | /* Tasklet to handle deferred processing */ | ||
699 | struct tasklet_struct isr_tasklet[PMCRAID_NUM_MSIX_VECTORS]; | ||
700 | |||
701 | /* Work-queue (Shared) for deferred reset processing */ | ||
702 | struct work_struct worker_q; | ||
703 | 772 | ||
704 | 773 | ||
705 | u32 ioa_state:4; /* For IOA Reset sequence FSM */ | 774 | u32 ioa_state:4; /* For IOA Reset sequence FSM */ |
@@ -728,7 +797,10 @@ struct pmcraid_instance { | |||
728 | /* LLD maintained resource entry structure */ | 797 | /* LLD maintained resource entry structure */ |
729 | struct pmcraid_resource_entry { | 798 | struct pmcraid_resource_entry { |
730 | struct list_head queue; /* link to "to be exposed" resources */ | 799 | struct list_head queue; /* link to "to be exposed" resources */ |
731 | struct pmcraid_config_table_entry cfg_entry; | 800 | union { |
801 | struct pmcraid_config_table_entry cfg_entry; | ||
802 | struct pmcraid_config_table_entry_ext cfg_entry_ext; | ||
803 | }; | ||
732 | struct scsi_device *scsi_dev; /* Link scsi_device structure */ | 804 | struct scsi_device *scsi_dev; /* Link scsi_device structure */ |
733 | atomic_t read_failures; /* count of failed READ commands */ | 805 | atomic_t read_failures; /* count of failed READ commands */ |
734 | atomic_t write_failures; /* count of failed WRITE commands */ | 806 | atomic_t write_failures; /* count of failed WRITE commands */ |
@@ -771,73 +843,75 @@ struct pmcraid_ioasc_error { | |||
771 | * statically. | 843 | * statically. |
772 | */ | 844 | */ |
773 | static struct pmcraid_ioasc_error pmcraid_ioasc_error_table[] = { | 845 | static struct pmcraid_ioasc_error pmcraid_ioasc_error_table[] = { |
774 | {0x01180600, IOASC_LOG_LEVEL_MUST, | 846 | {0x01180600, IOASC_LOG_LEVEL_HARD, |
775 | "Recovered Error, soft media error, sector reassignment suggested"}, | 847 | "Recovered Error, soft media error, sector reassignment suggested"}, |
776 | {0x015D0000, IOASC_LOG_LEVEL_MUST, | 848 | {0x015D0000, IOASC_LOG_LEVEL_HARD, |
777 | "Recovered Error, failure prediction threshold exceeded"}, | 849 | "Recovered Error, failure prediction thresold exceeded"}, |
778 | {0x015D9200, IOASC_LOG_LEVEL_MUST, | 850 | {0x015D9200, IOASC_LOG_LEVEL_HARD, |
779 | "Recovered Error, soft Cache Card Battery error threshold"}, | 851 | "Recovered Error, soft Cache Card Battery error thresold"}, |
780 | {0x015D9200, IOASC_LOG_LEVEL_MUST, | 852 | {0x015D9200, IOASC_LOG_LEVEL_HARD, |
781 | "Recovered Error, soft Cache Card Battery error threshold"}, | 853 | "Recovered Error, soft Cache Card Battery error thresold"}, |
782 | {0x02048000, IOASC_LOG_LEVEL_MUST, | 854 | {0x02048000, IOASC_LOG_LEVEL_HARD, |
783 | "Not Ready, IOA Reset Required"}, | 855 | "Not Ready, IOA Reset Required"}, |
784 | {0x02408500, IOASC_LOG_LEVEL_MUST, | 856 | {0x02408500, IOASC_LOG_LEVEL_HARD, |
785 | "Not Ready, IOA microcode download required"}, | 857 | "Not Ready, IOA microcode download required"}, |
786 | {0x03110B00, IOASC_LOG_LEVEL_MUST, | 858 | {0x03110B00, IOASC_LOG_LEVEL_HARD, |
787 | "Medium Error, data unreadable, reassignment suggested"}, | 859 | "Medium Error, data unreadable, reassignment suggested"}, |
788 | {0x03110C00, IOASC_LOG_LEVEL_MUST, | 860 | {0x03110C00, IOASC_LOG_LEVEL_MUST, |
789 | "Medium Error, data unreadable do not reassign"}, | 861 | "Medium Error, data unreadable do not reassign"}, |
790 | {0x03310000, IOASC_LOG_LEVEL_MUST, | 862 | {0x03310000, IOASC_LOG_LEVEL_HARD, |
791 | "Medium Error, media corrupted"}, | 863 | "Medium Error, media corrupted"}, |
792 | {0x04050000, IOASC_LOG_LEVEL_MUST, | 864 | {0x04050000, IOASC_LOG_LEVEL_HARD, |
793 | "Hardware Error, IOA can't communicate with device"}, | 865 | "Hardware Error, IOA can't communicate with device"}, |
794 | {0x04080000, IOASC_LOG_LEVEL_MUST, | 866 | {0x04080000, IOASC_LOG_LEVEL_MUST, |
795 | "Hardware Error, device bus error"}, | 867 | "Hardware Error, device bus error"}, |
796 | {0x04080000, IOASC_LOG_LEVEL_MUST, | 868 | {0x04088000, IOASC_LOG_LEVEL_MUST, |
797 | "Hardware Error, device bus is not functioning"}, | 869 | "Hardware Error, device bus is not functioning"}, |
798 | {0x04118000, IOASC_LOG_LEVEL_MUST, | 870 | {0x04118000, IOASC_LOG_LEVEL_HARD, |
799 | "Hardware Error, IOA reserved area data check"}, | 871 | "Hardware Error, IOA reserved area data check"}, |
800 | {0x04118100, IOASC_LOG_LEVEL_MUST, | 872 | {0x04118100, IOASC_LOG_LEVEL_HARD, |
801 | "Hardware Error, IOA reserved area invalid data pattern"}, | 873 | "Hardware Error, IOA reserved area invalid data pattern"}, |
802 | {0x04118200, IOASC_LOG_LEVEL_MUST, | 874 | {0x04118200, IOASC_LOG_LEVEL_HARD, |
803 | "Hardware Error, IOA reserved area LRC error"}, | 875 | "Hardware Error, IOA reserved area LRC error"}, |
804 | {0x04320000, IOASC_LOG_LEVEL_MUST, | 876 | {0x04320000, IOASC_LOG_LEVEL_HARD, |
805 | "Hardware Error, reassignment space exhausted"}, | 877 | "Hardware Error, reassignment space exhausted"}, |
806 | {0x04330000, IOASC_LOG_LEVEL_MUST, | 878 | {0x04330000, IOASC_LOG_LEVEL_HARD, |
807 | "Hardware Error, data transfer underlength error"}, | 879 | "Hardware Error, data transfer underlength error"}, |
808 | {0x04330000, IOASC_LOG_LEVEL_MUST, | 880 | {0x04330000, IOASC_LOG_LEVEL_HARD, |
809 | "Hardware Error, data transfer overlength error"}, | 881 | "Hardware Error, data transfer overlength error"}, |
810 | {0x04418000, IOASC_LOG_LEVEL_MUST, | 882 | {0x04418000, IOASC_LOG_LEVEL_MUST, |
811 | "Hardware Error, PCI bus error"}, | 883 | "Hardware Error, PCI bus error"}, |
812 | {0x04440000, IOASC_LOG_LEVEL_MUST, | 884 | {0x04440000, IOASC_LOG_LEVEL_HARD, |
813 | "Hardware Error, device error"}, | 885 | "Hardware Error, device error"}, |
814 | {0x04448300, IOASC_LOG_LEVEL_MUST, | 886 | {0x04448200, IOASC_LOG_LEVEL_MUST, |
887 | "Hardware Error, IOA error"}, | ||
888 | {0x04448300, IOASC_LOG_LEVEL_HARD, | ||
815 | "Hardware Error, undefined device response"}, | 889 | "Hardware Error, undefined device response"}, |
816 | {0x04448400, IOASC_LOG_LEVEL_MUST, | 890 | {0x04448400, IOASC_LOG_LEVEL_HARD, |
817 | "Hardware Error, IOA microcode error"}, | 891 | "Hardware Error, IOA microcode error"}, |
818 | {0x04448600, IOASC_LOG_LEVEL_MUST, | 892 | {0x04448600, IOASC_LOG_LEVEL_HARD, |
819 | "Hardware Error, IOA reset required"}, | 893 | "Hardware Error, IOA reset required"}, |
820 | {0x04449200, IOASC_LOG_LEVEL_MUST, | 894 | {0x04449200, IOASC_LOG_LEVEL_HARD, |
821 | "Hardware Error, hard Cache Fearuee Card Battery error"}, | 895 | "Hardware Error, hard Cache Fearuee Card Battery error"}, |
822 | {0x0444A000, IOASC_LOG_LEVEL_MUST, | 896 | {0x0444A000, IOASC_LOG_LEVEL_HARD, |
823 | "Hardware Error, failed device altered"}, | 897 | "Hardware Error, failed device altered"}, |
824 | {0x0444A200, IOASC_LOG_LEVEL_MUST, | 898 | {0x0444A200, IOASC_LOG_LEVEL_HARD, |
825 | "Hardware Error, data check after reassignment"}, | 899 | "Hardware Error, data check after reassignment"}, |
826 | {0x0444A300, IOASC_LOG_LEVEL_MUST, | 900 | {0x0444A300, IOASC_LOG_LEVEL_HARD, |
827 | "Hardware Error, LRC error after reassignment"}, | 901 | "Hardware Error, LRC error after reassignment"}, |
828 | {0x044A0000, IOASC_LOG_LEVEL_MUST, | 902 | {0x044A0000, IOASC_LOG_LEVEL_HARD, |
829 | "Hardware Error, device bus error (msg/cmd phase)"}, | 903 | "Hardware Error, device bus error (msg/cmd phase)"}, |
830 | {0x04670400, IOASC_LOG_LEVEL_MUST, | 904 | {0x04670400, IOASC_LOG_LEVEL_HARD, |
831 | "Hardware Error, new device can't be used"}, | 905 | "Hardware Error, new device can't be used"}, |
832 | {0x04678000, IOASC_LOG_LEVEL_MUST, | 906 | {0x04678000, IOASC_LOG_LEVEL_HARD, |
833 | "Hardware Error, invalid multiadapter configuration"}, | 907 | "Hardware Error, invalid multiadapter configuration"}, |
834 | {0x04678100, IOASC_LOG_LEVEL_MUST, | 908 | {0x04678100, IOASC_LOG_LEVEL_HARD, |
835 | "Hardware Error, incorrect connection between enclosures"}, | 909 | "Hardware Error, incorrect connection between enclosures"}, |
836 | {0x04678200, IOASC_LOG_LEVEL_MUST, | 910 | {0x04678200, IOASC_LOG_LEVEL_HARD, |
837 | "Hardware Error, connections exceed IOA design limits"}, | 911 | "Hardware Error, connections exceed IOA design limits"}, |
838 | {0x04678300, IOASC_LOG_LEVEL_MUST, | 912 | {0x04678300, IOASC_LOG_LEVEL_HARD, |
839 | "Hardware Error, incorrect multipath connection"}, | 913 | "Hardware Error, incorrect multipath connection"}, |
840 | {0x04679000, IOASC_LOG_LEVEL_MUST, | 914 | {0x04679000, IOASC_LOG_LEVEL_HARD, |
841 | "Hardware Error, command to LUN failed"}, | 915 | "Hardware Error, command to LUN failed"}, |
842 | {0x064C8000, IOASC_LOG_LEVEL_HARD, | 916 | {0x064C8000, IOASC_LOG_LEVEL_HARD, |
843 | "Unit Attention, cache exists for missing/failed device"}, | 917 | "Unit Attention, cache exists for missing/failed device"}, |
@@ -845,15 +919,15 @@ static struct pmcraid_ioasc_error pmcraid_ioasc_error_table[] = { | |||
845 | "Unit Attention, incompatible exposed mode device"}, | 919 | "Unit Attention, incompatible exposed mode device"}, |
846 | {0x06670600, IOASC_LOG_LEVEL_HARD, | 920 | {0x06670600, IOASC_LOG_LEVEL_HARD, |
847 | "Unit Attention, attachment of logical unit failed"}, | 921 | "Unit Attention, attachment of logical unit failed"}, |
848 | {0x06678000, IOASC_LOG_LEVEL_MUST, | 922 | {0x06678000, IOASC_LOG_LEVEL_HARD, |
849 | "Unit Attention, cables exceed connective design limit"}, | 923 | "Unit Attention, cables exceed connective design limit"}, |
850 | {0x06678300, IOASC_LOG_LEVEL_MUST, | 924 | {0x06678300, IOASC_LOG_LEVEL_HARD, |
851 | "Unit Attention, incomplete multipath connection between" \ | 925 | "Unit Attention, incomplete multipath connection between" \ |
852 | "IOA and enclosure"}, | 926 | "IOA and enclosure"}, |
853 | {0x06678400, IOASC_LOG_LEVEL_MUST, | 927 | {0x06678400, IOASC_LOG_LEVEL_HARD, |
854 | "Unit Attention, incomplete multipath connection between" \ | 928 | "Unit Attention, incomplete multipath connection between" \ |
855 | "device and enclosure"}, | 929 | "device and enclosure"}, |
856 | {0x06678500, IOASC_LOG_LEVEL_MUST, | 930 | {0x06678500, IOASC_LOG_LEVEL_HARD, |
857 | "Unit Attention, incomplete multipath connection between" \ | 931 | "Unit Attention, incomplete multipath connection between" \ |
858 | "IOA and remote IOA"}, | 932 | "IOA and remote IOA"}, |
859 | {0x06678600, IOASC_LOG_LEVEL_HARD, | 933 | {0x06678600, IOASC_LOG_LEVEL_HARD, |
@@ -863,11 +937,11 @@ static struct pmcraid_ioasc_error pmcraid_ioasc_error_table[] = { | |||
863 | "function"}, | 937 | "function"}, |
864 | {0x06698200, IOASC_LOG_LEVEL_HARD, | 938 | {0x06698200, IOASC_LOG_LEVEL_HARD, |
865 | "Unit Attention, corrupt array parity detected on device"}, | 939 | "Unit Attention, corrupt array parity detected on device"}, |
866 | {0x066B0200, IOASC_LOG_LEVEL_MUST, | 940 | {0x066B0200, IOASC_LOG_LEVEL_HARD, |
867 | "Unit Attention, array exposed"}, | 941 | "Unit Attention, array exposed"}, |
868 | {0x066B8200, IOASC_LOG_LEVEL_HARD, | 942 | {0x066B8200, IOASC_LOG_LEVEL_HARD, |
869 | "Unit Attention, exposed array is still protected"}, | 943 | "Unit Attention, exposed array is still protected"}, |
870 | {0x066B9200, IOASC_LOG_LEVEL_MUST, | 944 | {0x066B9200, IOASC_LOG_LEVEL_HARD, |
871 | "Unit Attention, Multipath redundancy level got worse"}, | 945 | "Unit Attention, Multipath redundancy level got worse"}, |
872 | {0x07270000, IOASC_LOG_LEVEL_HARD, | 946 | {0x07270000, IOASC_LOG_LEVEL_HARD, |
873 | "Data Protect, device is read/write protected by IOA"}, | 947 | "Data Protect, device is read/write protected by IOA"}, |
@@ -875,37 +949,37 @@ static struct pmcraid_ioasc_error pmcraid_ioasc_error_table[] = { | |||
875 | "Data Protect, IOA doesn't support device attribute"}, | 949 | "Data Protect, IOA doesn't support device attribute"}, |
876 | {0x07278100, IOASC_LOG_LEVEL_HARD, | 950 | {0x07278100, IOASC_LOG_LEVEL_HARD, |
877 | "Data Protect, NVRAM mirroring prohibited"}, | 951 | "Data Protect, NVRAM mirroring prohibited"}, |
878 | {0x07278400, IOASC_LOG_LEVEL_MUST, | 952 | {0x07278400, IOASC_LOG_LEVEL_HARD, |
879 | "Data Protect, array is short 2 or more devices"}, | 953 | "Data Protect, array is short 2 or more devices"}, |
880 | {0x07278600, IOASC_LOG_LEVEL_MUST, | 954 | {0x07278600, IOASC_LOG_LEVEL_HARD, |
881 | "Data Protect, exposed array is short a required device"}, | 955 | "Data Protect, exposed array is short a required device"}, |
882 | {0x07278700, IOASC_LOG_LEVEL_MUST, | 956 | {0x07278700, IOASC_LOG_LEVEL_HARD, |
883 | "Data Protect, array members not at required addresses"}, | 957 | "Data Protect, array members not at required addresses"}, |
884 | {0x07278800, IOASC_LOG_LEVEL_MUST, | 958 | {0x07278800, IOASC_LOG_LEVEL_HARD, |
885 | "Data Protect, exposed mode device resource address conflict"}, | 959 | "Data Protect, exposed mode device resource address conflict"}, |
886 | {0x07278900, IOASC_LOG_LEVEL_MUST, | 960 | {0x07278900, IOASC_LOG_LEVEL_HARD, |
887 | "Data Protect, incorrect resource address of exposed mode device"}, | 961 | "Data Protect, incorrect resource address of exposed mode device"}, |
888 | {0x07278A00, IOASC_LOG_LEVEL_MUST, | 962 | {0x07278A00, IOASC_LOG_LEVEL_HARD, |
889 | "Data Protect, Array is missing a device and parity is out of sync"}, | 963 | "Data Protect, Array is missing a device and parity is out of sync"}, |
890 | {0x07278B00, IOASC_LOG_LEVEL_MUST, | 964 | {0x07278B00, IOASC_LOG_LEVEL_HARD, |
891 | "Data Protect, maximum number of arrays already exist"}, | 965 | "Data Protect, maximum number of arrays already exist"}, |
892 | {0x07278C00, IOASC_LOG_LEVEL_HARD, | 966 | {0x07278C00, IOASC_LOG_LEVEL_HARD, |
893 | "Data Protect, cannot locate cache data for device"}, | 967 | "Data Protect, cannot locate cache data for device"}, |
894 | {0x07278D00, IOASC_LOG_LEVEL_HARD, | 968 | {0x07278D00, IOASC_LOG_LEVEL_HARD, |
895 | "Data Protect, cache data exits for a changed device"}, | 969 | "Data Protect, cache data exits for a changed device"}, |
896 | {0x07279100, IOASC_LOG_LEVEL_MUST, | 970 | {0x07279100, IOASC_LOG_LEVEL_HARD, |
897 | "Data Protect, detection of a device requiring format"}, | 971 | "Data Protect, detection of a device requiring format"}, |
898 | {0x07279200, IOASC_LOG_LEVEL_MUST, | 972 | {0x07279200, IOASC_LOG_LEVEL_HARD, |
899 | "Data Protect, IOA exceeds maximum number of devices"}, | 973 | "Data Protect, IOA exceeds maximum number of devices"}, |
900 | {0x07279600, IOASC_LOG_LEVEL_MUST, | 974 | {0x07279600, IOASC_LOG_LEVEL_HARD, |
901 | "Data Protect, missing array, volume set is not functional"}, | 975 | "Data Protect, missing array, volume set is not functional"}, |
902 | {0x07279700, IOASC_LOG_LEVEL_MUST, | 976 | {0x07279700, IOASC_LOG_LEVEL_HARD, |
903 | "Data Protect, single device for a volume set"}, | 977 | "Data Protect, single device for a volume set"}, |
904 | {0x07279800, IOASC_LOG_LEVEL_MUST, | 978 | {0x07279800, IOASC_LOG_LEVEL_HARD, |
905 | "Data Protect, missing multiple devices for a volume set"}, | 979 | "Data Protect, missing multiple devices for a volume set"}, |
906 | {0x07279900, IOASC_LOG_LEVEL_HARD, | 980 | {0x07279900, IOASC_LOG_LEVEL_HARD, |
907 | "Data Protect, maximum number of volument sets already exists"}, | 981 | "Data Protect, maximum number of volument sets already exists"}, |
908 | {0x07279A00, IOASC_LOG_LEVEL_MUST, | 982 | {0x07279A00, IOASC_LOG_LEVEL_HARD, |
909 | "Data Protect, other volume set problem"}, | 983 | "Data Protect, other volume set problem"}, |
910 | }; | 984 | }; |
911 | 985 | ||
@@ -952,27 +1026,6 @@ struct pmcraid_ioctl_header { | |||
952 | 1026 | ||
953 | #define PMCRAID_IOCTL_SIGNATURE "PMCRAID" | 1027 | #define PMCRAID_IOCTL_SIGNATURE "PMCRAID" |
954 | 1028 | ||
955 | |||
956 | /* | ||
957 | * pmcraid_event_details - defines AEN details that apps can retrieve from LLD | ||
958 | * | ||
959 | * .rcb_ccn - complete RCB of CCN | ||
960 | * .rcb_ldn - complete RCB of CCN | ||
961 | */ | ||
962 | struct pmcraid_event_details { | ||
963 | struct pmcraid_hcam_ccn rcb_ccn; | ||
964 | struct pmcraid_hcam_ldn rcb_ldn; | ||
965 | }; | ||
966 | |||
967 | /* | ||
968 | * pmcraid_driver_ioctl_buffer - structure passed as argument to most of the | ||
969 | * PMC driver handled ioctls. | ||
970 | */ | ||
971 | struct pmcraid_driver_ioctl_buffer { | ||
972 | struct pmcraid_ioctl_header ioctl_header; | ||
973 | struct pmcraid_event_details event_details; | ||
974 | }; | ||
975 | |||
976 | /* | 1029 | /* |
977 | * pmcraid_passthrough_ioctl_buffer - structure given as argument to | 1030 | * pmcraid_passthrough_ioctl_buffer - structure given as argument to |
978 | * passthrough(or firmware handled) IOCTL commands. Note that ioarcb requires | 1031 | * passthrough(or firmware handled) IOCTL commands. Note that ioarcb requires |