aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/mpt2sas/mpt2sas_base.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/mpt2sas/mpt2sas_base.c')
-rw-r--r--drivers/scsi/mpt2sas/mpt2sas_base.c96
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
690union 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)
698static irqreturn_t 706static 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}