diff options
Diffstat (limited to 'drivers/scsi/mpt2sas/mpt2sas_base.c')
-rw-r--r-- | drivers/scsi/mpt2sas/mpt2sas_base.c | 96 |
1 files changed, 44 insertions, 52 deletions
diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.c b/drivers/scsi/mpt2sas/mpt2sas_base.c index 35a13867495e..d95d2f274cb3 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_base.c +++ b/drivers/scsi/mpt2sas/mpt2sas_base.c | |||
@@ -94,7 +94,7 @@ _base_fault_reset_work(struct work_struct *work) | |||
94 | int rc; | 94 | int rc; |
95 | 95 | ||
96 | spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags); | 96 | spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags); |
97 | if (ioc->ioc_reset_in_progress) | 97 | if (ioc->shost_recovery) |
98 | goto rearm_timer; | 98 | goto rearm_timer; |
99 | spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags); | 99 | spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags); |
100 | 100 | ||
@@ -687,6 +687,14 @@ _base_unmask_interrupts(struct MPT2SAS_ADAPTER *ioc) | |||
687 | ioc->mask_interrupts = 0; | 687 | ioc->mask_interrupts = 0; |
688 | } | 688 | } |
689 | 689 | ||
690 | union reply_descriptor { | ||
691 | u64 word; | ||
692 | struct { | ||
693 | u32 low; | ||
694 | u32 high; | ||
695 | } u; | ||
696 | }; | ||
697 | |||
690 | /** | 698 | /** |
691 | * _base_interrupt - MPT adapter (IOC) specific interrupt handler. | 699 | * _base_interrupt - MPT adapter (IOC) specific interrupt handler. |
692 | * @irq: irq number (not used) | 700 | * @irq: irq number (not used) |
@@ -698,47 +706,38 @@ _base_unmask_interrupts(struct MPT2SAS_ADAPTER *ioc) | |||
698 | static irqreturn_t | 706 | static irqreturn_t |
699 | _base_interrupt(int irq, void *bus_id) | 707 | _base_interrupt(int irq, void *bus_id) |
700 | { | 708 | { |
701 | union reply_descriptor { | ||
702 | u64 word; | ||
703 | struct { | ||
704 | u32 low; | ||
705 | u32 high; | ||
706 | } u; | ||
707 | }; | ||
708 | union reply_descriptor rd; | 709 | union reply_descriptor rd; |
709 | u32 post_index, post_index_next, completed_cmds; | 710 | u32 completed_cmds; |
710 | u8 request_desript_type; | 711 | u8 request_desript_type; |
711 | u16 smid; | 712 | u16 smid; |
712 | u8 cb_idx; | 713 | u8 cb_idx; |
713 | u32 reply; | 714 | u32 reply; |
714 | u8 VF_ID; | 715 | u8 VF_ID; |
715 | int i; | ||
716 | struct MPT2SAS_ADAPTER *ioc = bus_id; | 716 | struct MPT2SAS_ADAPTER *ioc = bus_id; |
717 | Mpi2ReplyDescriptorsUnion_t *rpf; | ||
717 | 718 | ||
718 | if (ioc->mask_interrupts) | 719 | if (ioc->mask_interrupts) |
719 | return IRQ_NONE; | 720 | return IRQ_NONE; |
720 | 721 | ||
721 | post_index = ioc->reply_post_host_index; | 722 | rpf = &ioc->reply_post_free[ioc->reply_post_host_index]; |
722 | request_desript_type = ioc->reply_post_free[post_index]. | 723 | request_desript_type = rpf->Default.ReplyFlags |
723 | Default.ReplyFlags & MPI2_RPY_DESCRIPT_FLAGS_TYPE_MASK; | 724 | & MPI2_RPY_DESCRIPT_FLAGS_TYPE_MASK; |
724 | if (request_desript_type == MPI2_RPY_DESCRIPT_FLAGS_UNUSED) | 725 | if (request_desript_type == MPI2_RPY_DESCRIPT_FLAGS_UNUSED) |
725 | return IRQ_NONE; | 726 | return IRQ_NONE; |
726 | 727 | ||
727 | completed_cmds = 0; | 728 | completed_cmds = 0; |
728 | do { | 729 | do { |
729 | rd.word = ioc->reply_post_free[post_index].Words; | 730 | rd.word = rpf->Words; |
730 | if (rd.u.low == UINT_MAX || rd.u.high == UINT_MAX) | 731 | if (rd.u.low == UINT_MAX || rd.u.high == UINT_MAX) |
731 | goto out; | 732 | goto out; |
732 | reply = 0; | 733 | reply = 0; |
733 | cb_idx = 0xFF; | 734 | cb_idx = 0xFF; |
734 | smid = le16_to_cpu(ioc->reply_post_free[post_index]. | 735 | smid = le16_to_cpu(rpf->Default.DescriptorTypeDependent1); |
735 | Default.DescriptorTypeDependent1); | 736 | VF_ID = rpf->Default.VF_ID; |
736 | VF_ID = ioc->reply_post_free[post_index]. | ||
737 | Default.VF_ID; | ||
738 | if (request_desript_type == | 737 | if (request_desript_type == |
739 | MPI2_RPY_DESCRIPT_FLAGS_ADDRESS_REPLY) { | 738 | MPI2_RPY_DESCRIPT_FLAGS_ADDRESS_REPLY) { |
740 | reply = le32_to_cpu(ioc->reply_post_free[post_index]. | 739 | reply = le32_to_cpu |
741 | AddressReply.ReplyFrameAddress); | 740 | (rpf->AddressReply.ReplyFrameAddress); |
742 | } else if (request_desript_type == | 741 | } else if (request_desript_type == |
743 | MPI2_RPY_DESCRIPT_FLAGS_TARGET_COMMAND_BUFFER) | 742 | MPI2_RPY_DESCRIPT_FLAGS_TARGET_COMMAND_BUFFER) |
744 | goto next; | 743 | goto next; |
@@ -765,21 +764,27 @@ _base_interrupt(int irq, void *bus_id) | |||
765 | 0 : ioc->reply_free_host_index + 1; | 764 | 0 : ioc->reply_free_host_index + 1; |
766 | ioc->reply_free[ioc->reply_free_host_index] = | 765 | ioc->reply_free[ioc->reply_free_host_index] = |
767 | cpu_to_le32(reply); | 766 | cpu_to_le32(reply); |
767 | wmb(); | ||
768 | writel(ioc->reply_free_host_index, | 768 | writel(ioc->reply_free_host_index, |
769 | &ioc->chip->ReplyFreeHostIndex); | 769 | &ioc->chip->ReplyFreeHostIndex); |
770 | wmb(); | ||
771 | } | 770 | } |
772 | 771 | ||
773 | next: | 772 | next: |
774 | post_index_next = (post_index == (ioc->reply_post_queue_depth - | 773 | |
775 | 1)) ? 0 : post_index + 1; | 774 | rpf->Words = ULLONG_MAX; |
775 | ioc->reply_post_host_index = (ioc->reply_post_host_index == | ||
776 | (ioc->reply_post_queue_depth - 1)) ? 0 : | ||
777 | ioc->reply_post_host_index + 1; | ||
776 | request_desript_type = | 778 | request_desript_type = |
777 | ioc->reply_post_free[post_index_next].Default.ReplyFlags | 779 | ioc->reply_post_free[ioc->reply_post_host_index].Default. |
778 | & MPI2_RPY_DESCRIPT_FLAGS_TYPE_MASK; | 780 | ReplyFlags & MPI2_RPY_DESCRIPT_FLAGS_TYPE_MASK; |
779 | completed_cmds++; | 781 | completed_cmds++; |
780 | if (request_desript_type == MPI2_RPY_DESCRIPT_FLAGS_UNUSED) | 782 | if (request_desript_type == MPI2_RPY_DESCRIPT_FLAGS_UNUSED) |
781 | goto out; | 783 | goto out; |
782 | post_index = post_index_next; | 784 | if (!ioc->reply_post_host_index) |
785 | rpf = ioc->reply_post_free; | ||
786 | else | ||
787 | rpf++; | ||
783 | } while (1); | 788 | } while (1); |
784 | 789 | ||
785 | out: | 790 | out: |
@@ -787,19 +792,8 @@ _base_interrupt(int irq, void *bus_id) | |||
787 | if (!completed_cmds) | 792 | if (!completed_cmds) |
788 | return IRQ_NONE; | 793 | return IRQ_NONE; |
789 | 794 | ||
790 | /* reply post descriptor handling */ | ||
791 | post_index_next = ioc->reply_post_host_index; | ||
792 | for (i = 0 ; i < completed_cmds; i++) { | ||
793 | post_index = post_index_next; | ||
794 | /* poison the reply post descriptor */ | ||
795 | ioc->reply_post_free[post_index_next].Words = ULLONG_MAX; | ||
796 | post_index_next = (post_index == | ||
797 | (ioc->reply_post_queue_depth - 1)) | ||
798 | ? 0 : post_index + 1; | ||
799 | } | ||
800 | ioc->reply_post_host_index = post_index_next; | ||
801 | writel(post_index_next, &ioc->chip->ReplyPostHostIndex); | ||
802 | wmb(); | 795 | wmb(); |
796 | writel(ioc->reply_post_host_index, &ioc->chip->ReplyPostHostIndex); | ||
803 | return IRQ_HANDLED; | 797 | return IRQ_HANDLED; |
804 | } | 798 | } |
805 | 799 | ||
@@ -1542,6 +1536,8 @@ _base_display_ioc_capabilities(struct MPT2SAS_ADAPTER *ioc) | |||
1542 | (ioc->bios_pg3.BiosVersion & 0x0000FF00) >> 8, | 1536 | (ioc->bios_pg3.BiosVersion & 0x0000FF00) >> 8, |
1543 | ioc->bios_pg3.BiosVersion & 0x000000FF); | 1537 | ioc->bios_pg3.BiosVersion & 0x000000FF); |
1544 | 1538 | ||
1539 | _base_display_dell_branding(ioc); | ||
1540 | |||
1545 | printk(MPT2SAS_INFO_FMT "Protocol=(", ioc->name); | 1541 | printk(MPT2SAS_INFO_FMT "Protocol=(", ioc->name); |
1546 | 1542 | ||
1547 | if (ioc->facts.ProtocolFlags & MPI2_IOCFACTS_PROTOCOL_SCSI_INITIATOR) { | 1543 | if (ioc->facts.ProtocolFlags & MPI2_IOCFACTS_PROTOCOL_SCSI_INITIATOR) { |
@@ -1554,8 +1550,6 @@ _base_display_ioc_capabilities(struct MPT2SAS_ADAPTER *ioc) | |||
1554 | i++; | 1550 | i++; |
1555 | } | 1551 | } |
1556 | 1552 | ||
1557 | _base_display_dell_branding(ioc); | ||
1558 | |||
1559 | i = 0; | 1553 | i = 0; |
1560 | printk("), "); | 1554 | printk("), "); |
1561 | printk("Capabilities=("); | 1555 | printk("Capabilities=("); |
@@ -1627,6 +1621,9 @@ _base_static_config_pages(struct MPT2SAS_ADAPTER *ioc) | |||
1627 | u32 iounit_pg1_flags; | 1621 | u32 iounit_pg1_flags; |
1628 | 1622 | ||
1629 | mpt2sas_config_get_manufacturing_pg0(ioc, &mpi_reply, &ioc->manu_pg0); | 1623 | mpt2sas_config_get_manufacturing_pg0(ioc, &mpi_reply, &ioc->manu_pg0); |
1624 | if (ioc->ir_firmware) | ||
1625 | mpt2sas_config_get_manufacturing_pg10(ioc, &mpi_reply, | ||
1626 | &ioc->manu_pg10); | ||
1630 | mpt2sas_config_get_bios_pg2(ioc, &mpi_reply, &ioc->bios_pg2); | 1627 | mpt2sas_config_get_bios_pg2(ioc, &mpi_reply, &ioc->bios_pg2); |
1631 | mpt2sas_config_get_bios_pg3(ioc, &mpi_reply, &ioc->bios_pg3); | 1628 | mpt2sas_config_get_bios_pg3(ioc, &mpi_reply, &ioc->bios_pg3); |
1632 | mpt2sas_config_get_ioc_pg8(ioc, &mpi_reply, &ioc->ioc_pg8); | 1629 | mpt2sas_config_get_ioc_pg8(ioc, &mpi_reply, &ioc->ioc_pg8); |
@@ -1647,7 +1644,7 @@ _base_static_config_pages(struct MPT2SAS_ADAPTER *ioc) | |||
1647 | iounit_pg1_flags |= | 1644 | iounit_pg1_flags |= |
1648 | MPI2_IOUNITPAGE1_DISABLE_TASK_SET_FULL_HANDLING; | 1645 | MPI2_IOUNITPAGE1_DISABLE_TASK_SET_FULL_HANDLING; |
1649 | ioc->iounit_pg1.Flags = cpu_to_le32(iounit_pg1_flags); | 1646 | ioc->iounit_pg1.Flags = cpu_to_le32(iounit_pg1_flags); |
1650 | mpt2sas_config_set_iounit_pg1(ioc, &mpi_reply, ioc->iounit_pg1); | 1647 | mpt2sas_config_set_iounit_pg1(ioc, &mpi_reply, &ioc->iounit_pg1); |
1651 | } | 1648 | } |
1652 | 1649 | ||
1653 | /** | 1650 | /** |
@@ -3303,13 +3300,11 @@ mpt2sas_base_attach(struct MPT2SAS_ADAPTER *ioc) | |||
3303 | ioc->tm_cmds.reply = kzalloc(ioc->reply_sz, GFP_KERNEL); | 3300 | ioc->tm_cmds.reply = kzalloc(ioc->reply_sz, GFP_KERNEL); |
3304 | ioc->tm_cmds.status = MPT2_CMD_NOT_USED; | 3301 | ioc->tm_cmds.status = MPT2_CMD_NOT_USED; |
3305 | mutex_init(&ioc->tm_cmds.mutex); | 3302 | mutex_init(&ioc->tm_cmds.mutex); |
3306 | init_completion(&ioc->tm_cmds.done); | ||
3307 | 3303 | ||
3308 | /* config page internal command bits */ | 3304 | /* config page internal command bits */ |
3309 | ioc->config_cmds.reply = kzalloc(ioc->reply_sz, GFP_KERNEL); | 3305 | ioc->config_cmds.reply = kzalloc(ioc->reply_sz, GFP_KERNEL); |
3310 | ioc->config_cmds.status = MPT2_CMD_NOT_USED; | 3306 | ioc->config_cmds.status = MPT2_CMD_NOT_USED; |
3311 | mutex_init(&ioc->config_cmds.mutex); | 3307 | mutex_init(&ioc->config_cmds.mutex); |
3312 | init_completion(&ioc->config_cmds.done); | ||
3313 | 3308 | ||
3314 | /* ctl module internal command bits */ | 3309 | /* ctl module internal command bits */ |
3315 | ioc->ctl_cmds.reply = kzalloc(ioc->reply_sz, GFP_KERNEL); | 3310 | ioc->ctl_cmds.reply = kzalloc(ioc->reply_sz, GFP_KERNEL); |
@@ -3433,6 +3428,7 @@ _base_reset_handler(struct MPT2SAS_ADAPTER *ioc, int reset_phase) | |||
3433 | if (ioc->config_cmds.status & MPT2_CMD_PENDING) { | 3428 | if (ioc->config_cmds.status & MPT2_CMD_PENDING) { |
3434 | ioc->config_cmds.status |= MPT2_CMD_RESET; | 3429 | ioc->config_cmds.status |= MPT2_CMD_RESET; |
3435 | mpt2sas_base_free_smid(ioc, ioc->config_cmds.smid); | 3430 | mpt2sas_base_free_smid(ioc, ioc->config_cmds.smid); |
3431 | ioc->config_cmds.smid = USHORT_MAX; | ||
3436 | complete(&ioc->config_cmds.done); | 3432 | complete(&ioc->config_cmds.done); |
3437 | } | 3433 | } |
3438 | break; | 3434 | break; |
@@ -3501,20 +3497,13 @@ mpt2sas_base_hard_reset_handler(struct MPT2SAS_ADAPTER *ioc, int sleep_flag, | |||
3501 | __func__)); | 3497 | __func__)); |
3502 | 3498 | ||
3503 | spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags); | 3499 | spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags); |
3504 | if (ioc->ioc_reset_in_progress) { | 3500 | if (ioc->shost_recovery) { |
3505 | spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags); | 3501 | spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags); |
3506 | printk(MPT2SAS_ERR_FMT "%s: busy\n", | 3502 | printk(MPT2SAS_ERR_FMT "%s: busy\n", |
3507 | ioc->name, __func__); | 3503 | ioc->name, __func__); |
3508 | return -EBUSY; | 3504 | return -EBUSY; |
3509 | } | 3505 | } |
3510 | ioc->ioc_reset_in_progress = 1; | ||
3511 | ioc->shost_recovery = 1; | 3506 | ioc->shost_recovery = 1; |
3512 | if (ioc->shost->shost_state == SHOST_RUNNING) { | ||
3513 | /* set back to SHOST_RUNNING in mpt2sas_scsih.c */ | ||
3514 | scsi_host_set_state(ioc->shost, SHOST_RECOVERY); | ||
3515 | printk(MPT2SAS_INFO_FMT "putting controller into " | ||
3516 | "SHOST_RECOVERY\n", ioc->name); | ||
3517 | } | ||
3518 | spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags); | 3507 | spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags); |
3519 | 3508 | ||
3520 | _base_reset_handler(ioc, MPT2_IOC_PRE_RESET); | 3509 | _base_reset_handler(ioc, MPT2_IOC_PRE_RESET); |
@@ -3534,7 +3523,10 @@ mpt2sas_base_hard_reset_handler(struct MPT2SAS_ADAPTER *ioc, int sleep_flag, | |||
3534 | ioc->name, __func__, ((r == 0) ? "SUCCESS" : "FAILED"))); | 3523 | ioc->name, __func__, ((r == 0) ? "SUCCESS" : "FAILED"))); |
3535 | 3524 | ||
3536 | spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags); | 3525 | spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags); |
3537 | ioc->ioc_reset_in_progress = 0; | 3526 | ioc->shost_recovery = 0; |
3538 | spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags); | 3527 | spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags); |
3528 | |||
3529 | if (!r) | ||
3530 | _base_reset_handler(ioc, MPT2_IOC_RUNNING); | ||
3539 | return r; | 3531 | return r; |
3540 | } | 3532 | } |