aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/qla2xxx/qla_isr.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/qla2xxx/qla_isr.c')
-rw-r--r--drivers/scsi/qla2xxx/qla_isr.c309
1 files changed, 304 insertions, 5 deletions
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c
index 245e7afb4c4d..b20a7169aac2 100644
--- a/drivers/scsi/qla2xxx/qla_isr.c
+++ b/drivers/scsi/qla2xxx/qla_isr.c
@@ -598,9 +598,54 @@ skip_rio:
598 break; 598 break;
599 599
600 case MBA_PORT_UPDATE: /* Port database update */ 600 case MBA_PORT_UPDATE: /* Port database update */
601 /* Only handle SCNs for our Vport index. */ 601 /*
602 if (vha->vp_idx && vha->vp_idx != (mb[3] & 0xff)) 602 * Handle only global and vn-port update events
603 *
604 * Relevant inputs:
605 * mb[1] = N_Port handle of changed port
606 * OR 0xffff for global event
607 * mb[2] = New login state
608 * 7 = Port logged out
609 * mb[3] = LSB is vp_idx, 0xff = all vps
610 *
611 * Skip processing if:
612 * Event is global, vp_idx is NOT all vps,
613 * vp_idx does not match
614 * Event is not global, vp_idx does not match
615 */
616 if ((mb[1] == 0xffff && (mb[3] & 0xff) != 0xff)
617 || (mb[1] != 0xffff)) {
618 if (vha->vp_idx != (mb[3] & 0xff))
619 break;
620 }
621
622 /* Global event -- port logout or port unavailable. */
623 if (mb[1] == 0xffff && mb[2] == 0x7) {
624 DEBUG2(printk("scsi(%ld): Asynchronous PORT UPDATE.\n",
625 vha->host_no));
626 DEBUG(printk(KERN_INFO
627 "scsi(%ld): Port unavailable %04x %04x %04x.\n",
628 vha->host_no, mb[1], mb[2], mb[3]));
629
630 if (atomic_read(&vha->loop_state) != LOOP_DOWN) {
631 atomic_set(&vha->loop_state, LOOP_DOWN);
632 atomic_set(&vha->loop_down_timer,
633 LOOP_DOWN_TIME);
634 vha->device_flags |= DFLG_NO_CABLE;
635 qla2x00_mark_all_devices_lost(vha, 1);
636 }
637
638 if (vha->vp_idx) {
639 atomic_set(&vha->vp_state, VP_FAILED);
640 fc_vport_set_state(vha->fc_vport,
641 FC_VPORT_FAILED);
642 qla2x00_mark_all_devices_lost(vha, 1);
643 }
644
645 vha->flags.management_server_logged_in = 0;
646 ha->link_data_rate = PORT_SPEED_UNKNOWN;
603 break; 647 break;
648 }
604 649
605 /* 650 /*
606 * If PORT UPDATE is global (received LIP_OCCURRED/LIP_RESET 651 * If PORT UPDATE is global (received LIP_OCCURRED/LIP_RESET
@@ -640,8 +685,9 @@ skip_rio:
640 if (vha->vp_idx && test_bit(VP_SCR_NEEDED, &vha->vp_flags)) 685 if (vha->vp_idx && test_bit(VP_SCR_NEEDED, &vha->vp_flags))
641 break; 686 break;
642 /* Only handle SCNs for our Vport index. */ 687 /* Only handle SCNs for our Vport index. */
643 if (vha->vp_idx && vha->vp_idx != (mb[3] & 0xff)) 688 if (ha->flags.npiv_supported && vha->vp_idx != (mb[3] & 0xff))
644 break; 689 break;
690
645 DEBUG2(printk("scsi(%ld): Asynchronous RSCR UPDATE.\n", 691 DEBUG2(printk("scsi(%ld): Asynchronous RSCR UPDATE.\n",
646 vha->host_no)); 692 vha->host_no));
647 DEBUG(printk(KERN_INFO 693 DEBUG(printk(KERN_INFO
@@ -874,6 +920,249 @@ qla2x00_process_completed_request(struct scsi_qla_host *vha,
874 } 920 }
875} 921}
876 922
923static srb_t *
924qla2x00_get_sp_from_handle(scsi_qla_host_t *vha, const char *func,
925 struct req_que *req, void *iocb)
926{
927 struct qla_hw_data *ha = vha->hw;
928 sts_entry_t *pkt = iocb;
929 srb_t *sp = NULL;
930 uint16_t index;
931
932 index = LSW(pkt->handle);
933 if (index >= MAX_OUTSTANDING_COMMANDS) {
934 qla_printk(KERN_WARNING, ha,
935 "%s: Invalid completion handle (%x).\n", func, index);
936 set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
937 goto done;
938 }
939 sp = req->outstanding_cmds[index];
940 if (!sp) {
941 qla_printk(KERN_WARNING, ha,
942 "%s: Invalid completion handle (%x) -- timed-out.\n", func,
943 index);
944 return sp;
945 }
946 if (sp->handle != index) {
947 qla_printk(KERN_WARNING, ha,
948 "%s: SRB handle (%x) mismatch %x.\n", func, sp->handle,
949 index);
950 return NULL;
951 }
952 req->outstanding_cmds[index] = NULL;
953done:
954 return sp;
955}
956
957static void
958qla2x00_mbx_iocb_entry(scsi_qla_host_t *vha, struct req_que *req,
959 struct mbx_entry *mbx)
960{
961 const char func[] = "MBX-IOCB";
962 const char *type;
963 struct qla_hw_data *ha = vha->hw;
964 fc_port_t *fcport;
965 srb_t *sp;
966 struct srb_logio *lio;
967 uint16_t data[2];
968
969 sp = qla2x00_get_sp_from_handle(vha, func, req, mbx);
970 if (!sp)
971 return;
972
973 type = NULL;
974 lio = sp->ctx;
975 switch (lio->ctx.type) {
976 case SRB_LOGIN_CMD:
977 type = "login";
978 break;
979 case SRB_LOGOUT_CMD:
980 type = "logout";
981 break;
982 default:
983 qla_printk(KERN_WARNING, ha,
984 "%s: Unrecognized SRB: (%p) type=%d.\n", func, sp,
985 lio->ctx.type);
986 return;
987 }
988
989 del_timer(&lio->ctx.timer);
990 fcport = sp->fcport;
991
992 data[0] = data[1] = 0;
993 if (mbx->entry_status) {
994 DEBUG2(printk(KERN_WARNING
995 "scsi(%ld:%x): Async-%s error entry - entry-status=%x "
996 "status=%x state-flag=%x status-flags=%x.\n",
997 fcport->vha->host_no, sp->handle, type,
998 mbx->entry_status, le16_to_cpu(mbx->status),
999 le16_to_cpu(mbx->state_flags),
1000 le16_to_cpu(mbx->status_flags)));
1001 DEBUG2(qla2x00_dump_buffer((uint8_t *)mbx, sizeof(*mbx)));
1002
1003 data[0] = MBS_COMMAND_ERROR;
1004 data[1] = lio->flags & SRB_LOGIN_RETRIED ?
1005 QLA_LOGIO_LOGIN_RETRIED: 0;
1006 goto done_post_logio_done_work;
1007 }
1008
1009 if (!mbx->status && le16_to_cpu(mbx->mb0) == MBS_COMMAND_COMPLETE) {
1010 DEBUG2(printk(KERN_DEBUG
1011 "scsi(%ld:%x): Async-%s complete - mbx1=%x.\n",
1012 fcport->vha->host_no, sp->handle, type,
1013 le16_to_cpu(mbx->mb1)));
1014
1015 data[0] = MBS_COMMAND_COMPLETE;
1016 if (lio->ctx.type == SRB_LOGIN_CMD && le16_to_cpu(mbx->mb1) & BIT_1)
1017 fcport->flags |= FCF_FCP2_DEVICE;
1018
1019 goto done_post_logio_done_work;
1020 }
1021
1022 data[0] = le16_to_cpu(mbx->mb0);
1023 switch (data[0]) {
1024 case MBS_PORT_ID_USED:
1025 data[1] = le16_to_cpu(mbx->mb1);
1026 break;
1027 case MBS_LOOP_ID_USED:
1028 break;
1029 default:
1030 data[0] = MBS_COMMAND_ERROR;
1031 data[1] = lio->flags & SRB_LOGIN_RETRIED ?
1032 QLA_LOGIO_LOGIN_RETRIED: 0;
1033 break;
1034 }
1035
1036 DEBUG2(printk(KERN_WARNING
1037 "scsi(%ld:%x): Async-%s failed - status=%x mb0=%x mb1=%x mb2=%x "
1038 "mb6=%x mb7=%x.\n",
1039 fcport->vha->host_no, sp->handle, type, le16_to_cpu(mbx->status),
1040 le16_to_cpu(mbx->mb0), le16_to_cpu(mbx->mb1),
1041 le16_to_cpu(mbx->mb2), le16_to_cpu(mbx->mb6),
1042 le16_to_cpu(mbx->mb7)));
1043
1044done_post_logio_done_work:
1045 lio->ctx.type == SRB_LOGIN_CMD ?
1046 qla2x00_post_async_login_done_work(fcport->vha, fcport, data):
1047 qla2x00_post_async_logout_done_work(fcport->vha, fcport, data);
1048
1049 lio->ctx.free(sp);
1050}
1051
1052static void
1053qla24xx_logio_entry(scsi_qla_host_t *vha, struct req_que *req,
1054 struct logio_entry_24xx *logio)
1055{
1056 const char func[] = "LOGIO-IOCB";
1057 const char *type;
1058 struct qla_hw_data *ha = vha->hw;
1059 fc_port_t *fcport;
1060 srb_t *sp;
1061 struct srb_logio *lio;
1062 uint16_t data[2];
1063 uint32_t iop[2];
1064
1065 sp = qla2x00_get_sp_from_handle(vha, func, req, logio);
1066 if (!sp)
1067 return;
1068
1069 type = NULL;
1070 lio = sp->ctx;
1071 switch (lio->ctx.type) {
1072 case SRB_LOGIN_CMD:
1073 type = "login";
1074 break;
1075 case SRB_LOGOUT_CMD:
1076 type = "logout";
1077 break;
1078 default:
1079 qla_printk(KERN_WARNING, ha,
1080 "%s: Unrecognized SRB: (%p) type=%d.\n", func, sp,
1081 lio->ctx.type);
1082 return;
1083 }
1084
1085 del_timer(&lio->ctx.timer);
1086 fcport = sp->fcport;
1087
1088 data[0] = data[1] = 0;
1089 if (logio->entry_status) {
1090 DEBUG2(printk(KERN_WARNING
1091 "scsi(%ld:%x): Async-%s error entry - entry-status=%x.\n",
1092 fcport->vha->host_no, sp->handle, type,
1093 logio->entry_status));
1094 DEBUG2(qla2x00_dump_buffer((uint8_t *)logio, sizeof(*logio)));
1095
1096 data[0] = MBS_COMMAND_ERROR;
1097 data[1] = lio->flags & SRB_LOGIN_RETRIED ?
1098 QLA_LOGIO_LOGIN_RETRIED: 0;
1099 goto done_post_logio_done_work;
1100 }
1101
1102 if (le16_to_cpu(logio->comp_status) == CS_COMPLETE) {
1103 DEBUG2(printk(KERN_DEBUG
1104 "scsi(%ld:%x): Async-%s complete - iop0=%x.\n",
1105 fcport->vha->host_no, sp->handle, type,
1106 le32_to_cpu(logio->io_parameter[0])));
1107
1108 data[0] = MBS_COMMAND_COMPLETE;
1109 if (lio->ctx.type == SRB_LOGOUT_CMD)
1110 goto done_post_logio_done_work;
1111
1112 iop[0] = le32_to_cpu(logio->io_parameter[0]);
1113 if (iop[0] & BIT_4) {
1114 fcport->port_type = FCT_TARGET;
1115 if (iop[0] & BIT_8)
1116 fcport->flags |= FCF_FCP2_DEVICE;
1117 }
1118 if (iop[0] & BIT_5)
1119 fcport->port_type = FCT_INITIATOR;
1120 if (logio->io_parameter[7] || logio->io_parameter[8])
1121 fcport->supported_classes |= FC_COS_CLASS2;
1122 if (logio->io_parameter[9] || logio->io_parameter[10])
1123 fcport->supported_classes |= FC_COS_CLASS3;
1124
1125 goto done_post_logio_done_work;
1126 }
1127
1128 iop[0] = le32_to_cpu(logio->io_parameter[0]);
1129 iop[1] = le32_to_cpu(logio->io_parameter[1]);
1130 switch (iop[0]) {
1131 case LSC_SCODE_PORTID_USED:
1132 data[0] = MBS_PORT_ID_USED;
1133 data[1] = LSW(iop[1]);
1134 break;
1135 case LSC_SCODE_NPORT_USED:
1136 data[0] = MBS_LOOP_ID_USED;
1137 break;
1138 case LSC_SCODE_CMD_FAILED:
1139 if ((iop[1] & 0xff) == 0x05) {
1140 data[0] = MBS_NOT_LOGGED_IN;
1141 break;
1142 }
1143 /* Fall through. */
1144 default:
1145 data[0] = MBS_COMMAND_ERROR;
1146 data[1] = lio->flags & SRB_LOGIN_RETRIED ?
1147 QLA_LOGIO_LOGIN_RETRIED: 0;
1148 break;
1149 }
1150
1151 DEBUG2(printk(KERN_WARNING
1152 "scsi(%ld:%x): Async-%s failed - comp=%x iop0=%x iop1=%x.\n",
1153 fcport->vha->host_no, sp->handle, type,
1154 le16_to_cpu(logio->comp_status),
1155 le32_to_cpu(logio->io_parameter[0]),
1156 le32_to_cpu(logio->io_parameter[1])));
1157
1158done_post_logio_done_work:
1159 lio->ctx.type == SRB_LOGIN_CMD ?
1160 qla2x00_post_async_login_done_work(fcport->vha, fcport, data):
1161 qla2x00_post_async_logout_done_work(fcport->vha, fcport, data);
1162
1163 lio->ctx.free(sp);
1164}
1165
877/** 1166/**
878 * qla2x00_process_response_queue() - Process response queue entries. 1167 * qla2x00_process_response_queue() - Process response queue entries.
879 * @ha: SCSI driver HA context 1168 * @ha: SCSI driver HA context
@@ -935,6 +1224,9 @@ qla2x00_process_response_queue(struct rsp_que *rsp)
935 case STATUS_CONT_TYPE: 1224 case STATUS_CONT_TYPE:
936 qla2x00_status_cont_entry(rsp, (sts_cont_entry_t *)pkt); 1225 qla2x00_status_cont_entry(rsp, (sts_cont_entry_t *)pkt);
937 break; 1226 break;
1227 case MBX_IOCB_TYPE:
1228 qla2x00_mbx_iocb_entry(vha, rsp->req,
1229 (struct mbx_entry *)pkt);
938 default: 1230 default:
939 /* Type Not Supported. */ 1231 /* Type Not Supported. */
940 DEBUG4(printk(KERN_WARNING 1232 DEBUG4(printk(KERN_WARNING
@@ -1223,6 +1515,7 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt)
1223 cp->device->id, cp->device->lun, resid, 1515 cp->device->id, cp->device->lun, resid,
1224 scsi_bufflen(cp))); 1516 scsi_bufflen(cp)));
1225 1517
1518 scsi_set_resid(cp, resid);
1226 cp->result = DID_ERROR << 16; 1519 cp->result = DID_ERROR << 16;
1227 break; 1520 break;
1228 } 1521 }
@@ -1544,6 +1837,10 @@ void qla24xx_process_response_queue(struct scsi_qla_host *vha,
1544 qla24xx_report_id_acquisition(vha, 1837 qla24xx_report_id_acquisition(vha,
1545 (struct vp_rpt_id_entry_24xx *)pkt); 1838 (struct vp_rpt_id_entry_24xx *)pkt);
1546 break; 1839 break;
1840 case LOGINOUT_PORT_IOCB_TYPE:
1841 qla24xx_logio_entry(vha, rsp->req,
1842 (struct logio_entry_24xx *)pkt);
1843 break;
1547 default: 1844 default:
1548 /* Type Not Supported. */ 1845 /* Type Not Supported. */
1549 DEBUG4(printk(KERN_WARNING 1846 DEBUG4(printk(KERN_WARNING
@@ -1723,8 +2020,10 @@ qla24xx_msix_rsp_q(int irq, void *dev_id)
1723 2020
1724 vha = qla25xx_get_host(rsp); 2021 vha = qla25xx_get_host(rsp);
1725 qla24xx_process_response_queue(vha, rsp); 2022 qla24xx_process_response_queue(vha, rsp);
1726 WRT_REG_DWORD(&reg->hccr, HCCRX_CLR_RISC_INT); 2023 if (!ha->mqenable) {
1727 2024 WRT_REG_DWORD(&reg->hccr, HCCRX_CLR_RISC_INT);
2025 RD_REG_DWORD_RELAXED(&reg->hccr);
2026 }
1728 spin_unlock_irq(&ha->hardware_lock); 2027 spin_unlock_irq(&ha->hardware_lock);
1729 2028
1730 return IRQ_HANDLED; 2029 return IRQ_HANDLED;