diff options
Diffstat (limited to 'drivers/scsi/qla2xxx/qla_isr.c')
-rw-r--r-- | drivers/scsi/qla2xxx/qla_isr.c | 309 |
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 | ||
923 | static srb_t * | ||
924 | qla2x00_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; | ||
953 | done: | ||
954 | return sp; | ||
955 | } | ||
956 | |||
957 | static void | ||
958 | qla2x00_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 | |||
1044 | done_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 | |||
1052 | static void | ||
1053 | qla24xx_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 | |||
1158 | done_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(®->hccr, HCCRX_CLR_RISC_INT); | 2023 | if (!ha->mqenable) { |
1727 | 2024 | WRT_REG_DWORD(®->hccr, HCCRX_CLR_RISC_INT); | |
2025 | RD_REG_DWORD_RELAXED(®->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; |