aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/qla4xxx/ql4_isr.c
diff options
context:
space:
mode:
authorVikas Chaudhary <vikas.chaudhary@qlogic.com>2012-08-22 07:55:08 -0400
committerJames Bottomley <JBottomley@Parallels.com>2012-09-24 04:11:08 -0400
commit6e7b429259fc0b7f2d9b1147466656b34d114815 (patch)
treeb5bc8dc7e7e803f6589c9cdd4e71c8dc7a9932ab /drivers/scsi/qla4xxx/ql4_isr.c
parentaec07caedbb769535e78adca30c851c977fd5741 (diff)
[SCSI] qla4xxx: Added support for ISP83XX
Signed-off-by: Poornima Vonti <poornima.vonti@qlogic.com> Signed-off-by: Vikas Chaudhary <vikas.chaudhary@qlogic.com> Reviewed-by: Mike Christie <michaelc@cs.wisc.edu> Signed-off-by: James Bottomley <JBottomley@Parallels.com>
Diffstat (limited to 'drivers/scsi/qla4xxx/ql4_isr.c')
-rw-r--r--drivers/scsi/qla4xxx/ql4_isr.c202
1 files changed, 168 insertions, 34 deletions
diff --git a/drivers/scsi/qla4xxx/ql4_isr.c b/drivers/scsi/qla4xxx/ql4_isr.c
index 55d366b14a51..cb78e9c16744 100644
--- a/drivers/scsi/qla4xxx/ql4_isr.c
+++ b/drivers/scsi/qla4xxx/ql4_isr.c
@@ -126,7 +126,7 @@ static void qla4xxx_status_entry(struct scsi_qla_host *ha,
126 ql4_printk(KERN_WARNING, ha, "%s invalid status entry: " 126 ql4_printk(KERN_WARNING, ha, "%s invalid status entry: "
127 "handle=0x%0x, srb=%p\n", __func__, 127 "handle=0x%0x, srb=%p\n", __func__,
128 sts_entry->handle, srb); 128 sts_entry->handle, srb);
129 if (is_qla8022(ha)) 129 if (is_qla80XX(ha))
130 set_bit(DPC_RESET_HA_FW_CONTEXT, &ha->dpc_flags); 130 set_bit(DPC_RESET_HA_FW_CONTEXT, &ha->dpc_flags);
131 else 131 else
132 set_bit(DPC_RESET_HA, &ha->dpc_flags); 132 set_bit(DPC_RESET_HA, &ha->dpc_flags);
@@ -594,6 +594,14 @@ static void qla4xxx_isr_decode_mailbox(struct scsi_qla_host * ha,
594{ 594{
595 int i; 595 int i;
596 uint32_t mbox_sts[MBOX_AEN_REG_COUNT]; 596 uint32_t mbox_sts[MBOX_AEN_REG_COUNT];
597 __le32 __iomem *mailbox_out;
598
599 if (is_qla8032(ha))
600 mailbox_out = &ha->qla4_83xx_reg->mailbox_out[0];
601 else if (is_qla8022(ha))
602 mailbox_out = &ha->qla4_82xx_reg->mailbox_out[0];
603 else
604 mailbox_out = &ha->reg->mailbox[0];
597 605
598 if ((mbox_status == MBOX_STS_BUSY) || 606 if ((mbox_status == MBOX_STS_BUSY) ||
599 (mbox_status == MBOX_STS_INTERMEDIATE_COMPLETION) || 607 (mbox_status == MBOX_STS_INTERMEDIATE_COMPLETION) ||
@@ -606,9 +614,7 @@ static void qla4xxx_isr_decode_mailbox(struct scsi_qla_host * ha,
606 * location and set mailbox command done flag 614 * location and set mailbox command done flag
607 */ 615 */
608 for (i = 0; i < ha->mbox_status_count; i++) 616 for (i = 0; i < ha->mbox_status_count; i++)
609 ha->mbox_status[i] = is_qla8022(ha) 617 ha->mbox_status[i] = readl(&mailbox_out[i]);
610 ? readl(&ha->qla4_82xx_reg->mailbox_out[i])
611 : readl(&ha->reg->mailbox[i]);
612 618
613 set_bit(AF_MBOX_COMMAND_DONE, &ha->flags); 619 set_bit(AF_MBOX_COMMAND_DONE, &ha->flags);
614 620
@@ -617,9 +623,7 @@ static void qla4xxx_isr_decode_mailbox(struct scsi_qla_host * ha,
617 } 623 }
618 } else if (mbox_status >> 12 == MBOX_ASYNC_EVENT_STATUS) { 624 } else if (mbox_status >> 12 == MBOX_ASYNC_EVENT_STATUS) {
619 for (i = 0; i < MBOX_AEN_REG_COUNT; i++) 625 for (i = 0; i < MBOX_AEN_REG_COUNT; i++)
620 mbox_sts[i] = is_qla8022(ha) 626 mbox_sts[i] = readl(&mailbox_out[i]);
621 ? readl(&ha->qla4_82xx_reg->mailbox_out[i])
622 : readl(&ha->reg->mailbox[i]);
623 627
624 /* Immediately process the AENs that don't require much work. 628 /* Immediately process the AENs that don't require much work.
625 * Only queue the database_changed AENs */ 629 * Only queue the database_changed AENs */
@@ -635,7 +639,8 @@ static void qla4xxx_isr_decode_mailbox(struct scsi_qla_host * ha,
635 ql4_printk(KERN_INFO, ha, "%s: System Err\n", __func__); 639 ql4_printk(KERN_INFO, ha, "%s: System Err\n", __func__);
636 qla4xxx_dump_registers(ha); 640 qla4xxx_dump_registers(ha);
637 641
638 if (ql4xdontresethba) { 642 if ((is_qla8022(ha) && ql4xdontresethba) ||
643 (is_qla8032(ha) && qla4_83xx_idc_dontreset(ha))) {
639 DEBUG2(printk("scsi%ld: %s:Don't Reset HBA\n", 644 DEBUG2(printk("scsi%ld: %s:Don't Reset HBA\n",
640 ha->host_no, __func__)); 645 ha->host_no, __func__));
641 } else { 646 } else {
@@ -651,7 +656,7 @@ static void qla4xxx_isr_decode_mailbox(struct scsi_qla_host * ha,
651 case MBOX_ASTS_DHCP_LEASE_EXPIRED: 656 case MBOX_ASTS_DHCP_LEASE_EXPIRED:
652 DEBUG2(printk("scsi%ld: AEN %04x, ERROR Status, " 657 DEBUG2(printk("scsi%ld: AEN %04x, ERROR Status, "
653 "Reset HA\n", ha->host_no, mbox_status)); 658 "Reset HA\n", ha->host_no, mbox_status));
654 if (is_qla8022(ha)) 659 if (is_qla80XX(ha))
655 set_bit(DPC_RESET_HA_FW_CONTEXT, 660 set_bit(DPC_RESET_HA_FW_CONTEXT,
656 &ha->dpc_flags); 661 &ha->dpc_flags);
657 else 662 else
@@ -716,7 +721,7 @@ static void qla4xxx_isr_decode_mailbox(struct scsi_qla_host * ha,
716 set_bit(DPC_GET_DHCP_IP_ADDR, &ha->dpc_flags); 721 set_bit(DPC_GET_DHCP_IP_ADDR, &ha->dpc_flags);
717 else if ((mbox_sts[3] == ACB_STATE_ACQUIRING) && 722 else if ((mbox_sts[3] == ACB_STATE_ACQUIRING) &&
718 (mbox_sts[2] == ACB_STATE_VALID)) { 723 (mbox_sts[2] == ACB_STATE_VALID)) {
719 if (is_qla8022(ha)) 724 if (is_qla80XX(ha))
720 set_bit(DPC_RESET_HA_FW_CONTEXT, 725 set_bit(DPC_RESET_HA_FW_CONTEXT,
721 &ha->dpc_flags); 726 &ha->dpc_flags);
722 else 727 else
@@ -815,6 +820,23 @@ static void qla4xxx_isr_decode_mailbox(struct scsi_qla_host * ha,
815 } 820 }
816} 821}
817 822
823void qla4_83xx_interrupt_service_routine(struct scsi_qla_host *ha,
824 uint32_t intr_status)
825{
826 /* Process mailbox/asynch event interrupt.*/
827 if (intr_status) {
828 qla4xxx_isr_decode_mailbox(ha,
829 readl(&ha->qla4_83xx_reg->mailbox_out[0]));
830 /* clear the interrupt */
831 writel(0, &ha->qla4_83xx_reg->risc_intr);
832 } else {
833 qla4xxx_process_response_queue(ha);
834 }
835
836 /* clear the interrupt */
837 writel(0, &ha->qla4_83xx_reg->mb_int_mask);
838}
839
818/** 840/**
819 * qla4_82xx_interrupt_service_routine - isr 841 * qla4_82xx_interrupt_service_routine - isr
820 * @ha: pointer to host adapter structure. 842 * @ha: pointer to host adapter structure.
@@ -1045,6 +1067,59 @@ irqreturn_t qla4_82xx_intr_handler(int irq, void *dev_id)
1045 return IRQ_HANDLED; 1067 return IRQ_HANDLED;
1046} 1068}
1047 1069
1070#define LEG_INT_PTR_B31 (1 << 31)
1071#define LEG_INT_PTR_B30 (1 << 30)
1072#define PF_BITS_MASK (0xF << 16)
1073
1074/**
1075 * qla4_83xx_intr_handler - hardware interrupt handler.
1076 * @irq: Unused
1077 * @dev_id: Pointer to host adapter structure
1078 **/
1079irqreturn_t qla4_83xx_intr_handler(int irq, void *dev_id)
1080{
1081 struct scsi_qla_host *ha = dev_id;
1082 uint32_t leg_int_ptr = 0;
1083 unsigned long flags = 0;
1084
1085 ha->isr_count++;
1086 leg_int_ptr = readl(&ha->qla4_83xx_reg->leg_int_ptr);
1087
1088 /* Legacy interrupt is valid if bit31 of leg_int_ptr is set */
1089 if (!(leg_int_ptr & LEG_INT_PTR_B31)) {
1090 ql4_printk(KERN_ERR, ha,
1091 "%s: Legacy Interrupt Bit 31 not set, spurious interrupt!\n",
1092 __func__);
1093 return IRQ_NONE;
1094 }
1095
1096 /* Validate the PCIE function ID set in leg_int_ptr bits [19..16] */
1097 if ((leg_int_ptr & PF_BITS_MASK) != ha->pf_bit) {
1098 ql4_printk(KERN_ERR, ha,
1099 "%s: Incorrect function ID 0x%x in legacy interrupt register, ha->pf_bit = 0x%x\n",
1100 __func__, (leg_int_ptr & PF_BITS_MASK), ha->pf_bit);
1101 return IRQ_NONE;
1102 }
1103
1104 /* To de-assert legacy interrupt, write 0 to Legacy Interrupt Trigger
1105 * Control register and poll till Legacy Interrupt Pointer register
1106 * bit30 is 0.
1107 */
1108 writel(0, &ha->qla4_83xx_reg->leg_int_trig);
1109 do {
1110 leg_int_ptr = readl(&ha->qla4_83xx_reg->leg_int_ptr);
1111 if ((leg_int_ptr & PF_BITS_MASK) != ha->pf_bit)
1112 break;
1113 } while (leg_int_ptr & LEG_INT_PTR_B30);
1114
1115 spin_lock_irqsave(&ha->hardware_lock, flags);
1116 leg_int_ptr = readl(&ha->qla4_83xx_reg->risc_intr);
1117 ha->isp_ops->interrupt_service_routine(ha, leg_int_ptr);
1118 spin_unlock_irqrestore(&ha->hardware_lock, flags);
1119
1120 return IRQ_HANDLED;
1121}
1122
1048irqreturn_t 1123irqreturn_t
1049qla4_8xxx_msi_handler(int irq, void *dev_id) 1124qla4_8xxx_msi_handler(int irq, void *dev_id)
1050{ 1125{
@@ -1068,6 +1143,37 @@ qla4_8xxx_msi_handler(int irq, void *dev_id)
1068 return qla4_8xxx_default_intr_handler(irq, dev_id); 1143 return qla4_8xxx_default_intr_handler(irq, dev_id);
1069} 1144}
1070 1145
1146static irqreturn_t qla4_83xx_mailbox_intr_handler(int irq, void *dev_id)
1147{
1148 struct scsi_qla_host *ha = dev_id;
1149 unsigned long flags;
1150 uint32_t ival = 0;
1151
1152 spin_lock_irqsave(&ha->hardware_lock, flags);
1153
1154 ival = readl(&ha->qla4_83xx_reg->risc_intr);
1155 if (ival == 0) {
1156 ql4_printk(KERN_INFO, ha,
1157 "%s: It is a spurious mailbox interrupt!\n",
1158 __func__);
1159 ival = readl(&ha->qla4_83xx_reg->mb_int_mask);
1160 ival &= ~INT_MASK_FW_MB;
1161 writel(ival, &ha->qla4_83xx_reg->mb_int_mask);
1162 goto exit;
1163 }
1164
1165 qla4xxx_isr_decode_mailbox(ha,
1166 readl(&ha->qla4_83xx_reg->mailbox_out[0]));
1167 writel(0, &ha->qla4_83xx_reg->risc_intr);
1168 ival = readl(&ha->qla4_83xx_reg->mb_int_mask);
1169 ival &= ~INT_MASK_FW_MB;
1170 writel(ival, &ha->qla4_83xx_reg->mb_int_mask);
1171 ha->isr_count++;
1172exit:
1173 spin_unlock_irqrestore(&ha->hardware_lock, flags);
1174 return IRQ_HANDLED;
1175}
1176
1071/** 1177/**
1072 * qla4_8xxx_default_intr_handler - hardware interrupt handler. 1178 * qla4_8xxx_default_intr_handler - hardware interrupt handler.
1073 * @irq: Unused 1179 * @irq: Unused
@@ -1084,29 +1190,32 @@ qla4_8xxx_default_intr_handler(int irq, void *dev_id)
1084 uint32_t intr_status; 1190 uint32_t intr_status;
1085 uint8_t reqs_count = 0; 1191 uint8_t reqs_count = 0;
1086 1192
1087 spin_lock_irqsave(&ha->hardware_lock, flags); 1193 if (is_qla8032(ha)) {
1088 while (1) { 1194 qla4_83xx_mailbox_intr_handler(irq, dev_id);
1089 if (!(readl(&ha->qla4_82xx_reg->host_int) & 1195 } else {
1090 ISRX_82XX_RISC_INT)) { 1196 spin_lock_irqsave(&ha->hardware_lock, flags);
1091 qla4_82xx_spurious_interrupt(ha, reqs_count); 1197 while (1) {
1092 break; 1198 if (!(readl(&ha->qla4_82xx_reg->host_int) &
1093 } 1199 ISRX_82XX_RISC_INT)) {
1200 qla4_82xx_spurious_interrupt(ha, reqs_count);
1201 break;
1202 }
1094 1203
1095 intr_status = readl(&ha->qla4_82xx_reg->host_status); 1204 intr_status = readl(&ha->qla4_82xx_reg->host_status);
1096 if ((intr_status & 1205 if ((intr_status &
1097 (HSRX_RISC_MB_INT | HSRX_RISC_IOCB_INT)) == 0) { 1206 (HSRX_RISC_MB_INT | HSRX_RISC_IOCB_INT)) == 0) {
1098 qla4_82xx_spurious_interrupt(ha, reqs_count); 1207 qla4_82xx_spurious_interrupt(ha, reqs_count);
1099 break; 1208 break;
1100 } 1209 }
1101 1210
1102 ha->isp_ops->interrupt_service_routine(ha, intr_status); 1211 ha->isp_ops->interrupt_service_routine(ha, intr_status);
1103 1212
1104 if (++reqs_count == MAX_REQS_SERVICED_PER_INTR) 1213 if (++reqs_count == MAX_REQS_SERVICED_PER_INTR)
1105 break; 1214 break;
1215 }
1216 ha->isr_count++;
1217 spin_unlock_irqrestore(&ha->hardware_lock, flags);
1106 } 1218 }
1107
1108 ha->isr_count++;
1109 spin_unlock_irqrestore(&ha->hardware_lock, flags);
1110 return IRQ_HANDLED; 1219 return IRQ_HANDLED;
1111} 1220}
1112 1221
@@ -1115,13 +1224,25 @@ qla4_8xxx_msix_rsp_q(int irq, void *dev_id)
1115{ 1224{
1116 struct scsi_qla_host *ha = dev_id; 1225 struct scsi_qla_host *ha = dev_id;
1117 unsigned long flags; 1226 unsigned long flags;
1227 uint32_t ival = 0;
1118 1228
1119 spin_lock_irqsave(&ha->hardware_lock, flags); 1229 spin_lock_irqsave(&ha->hardware_lock, flags);
1120 qla4xxx_process_response_queue(ha); 1230 if (is_qla8032(ha)) {
1121 writel(0, &ha->qla4_82xx_reg->host_int); 1231 ival = readl(&ha->qla4_83xx_reg->iocb_int_mask);
1122 spin_unlock_irqrestore(&ha->hardware_lock, flags); 1232 if (ival == 0) {
1123 1233 ql4_printk(KERN_INFO, ha, "%s: It is a spurious iocb interrupt!\n",
1234 __func__);
1235 goto exit_msix_rsp_q;
1236 }
1237 qla4xxx_process_response_queue(ha);
1238 writel(0, &ha->qla4_83xx_reg->iocb_int_mask);
1239 } else {
1240 qla4xxx_process_response_queue(ha);
1241 writel(0, &ha->qla4_82xx_reg->host_int);
1242 }
1124 ha->isr_count++; 1243 ha->isr_count++;
1244exit_msix_rsp_q:
1245 spin_unlock_irqrestore(&ha->hardware_lock, flags);
1125 return IRQ_HANDLED; 1246 return IRQ_HANDLED;
1126} 1247}
1127 1248
@@ -1196,8 +1317,15 @@ int qla4xxx_request_irqs(struct scsi_qla_host *ha)
1196 if (is_qla40XX(ha)) 1317 if (is_qla40XX(ha))
1197 goto try_intx; 1318 goto try_intx;
1198 1319
1199 if (ql4xenablemsix == 2) 1320 if (ql4xenablemsix == 2) {
1321 /* Note: MSI Interrupts not supported for ISP8324 */
1322 if (is_qla8032(ha)) {
1323 ql4_printk(KERN_INFO, ha, "%s: MSI Interrupts not supported for ISP8324, Falling back-to INTx mode\n",
1324 __func__);
1325 goto try_intx;
1326 }
1200 goto try_msi; 1327 goto try_msi;
1328 }
1201 1329
1202 if (ql4xenablemsix == 0 || ql4xenablemsix != 1) 1330 if (ql4xenablemsix == 0 || ql4xenablemsix != 1)
1203 goto try_intx; 1331 goto try_intx;
@@ -1208,6 +1336,12 @@ int qla4xxx_request_irqs(struct scsi_qla_host *ha)
1208 DEBUG2(ql4_printk(KERN_INFO, ha, 1336 DEBUG2(ql4_printk(KERN_INFO, ha,
1209 "MSI-X: Enabled (0x%X).\n", ha->revision_id)); 1337 "MSI-X: Enabled (0x%X).\n", ha->revision_id));
1210 goto irq_attached; 1338 goto irq_attached;
1339 } else {
1340 if (is_qla8032(ha)) {
1341 ql4_printk(KERN_INFO, ha, "%s: ISP8324: MSI-X: Falling back-to INTx mode. ret = %d\n",
1342 __func__, ret);
1343 goto try_intx;
1344 }
1211 } 1345 }
1212 1346
1213 ql4_printk(KERN_WARNING, ha, 1347 ql4_printk(KERN_WARNING, ha,