diff options
Diffstat (limited to 'drivers/scsi/qla2xxx/qla_isr.c')
-rw-r--r-- | drivers/scsi/qla2xxx/qla_isr.c | 110 |
1 files changed, 107 insertions, 3 deletions
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index 6fc63b98818c..ab90329ff2e4 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c | |||
@@ -8,6 +8,7 @@ | |||
8 | 8 | ||
9 | #include <linux/delay.h> | 9 | #include <linux/delay.h> |
10 | #include <scsi/scsi_tcq.h> | 10 | #include <scsi/scsi_tcq.h> |
11 | #include <scsi/scsi_bsg_fc.h> | ||
11 | 12 | ||
12 | static void qla2x00_mbx_completion(scsi_qla_host_t *, uint16_t); | 13 | static void qla2x00_mbx_completion(scsi_qla_host_t *, uint16_t); |
13 | static void qla2x00_process_completed_request(struct scsi_qla_host *, | 14 | static void qla2x00_process_completed_request(struct scsi_qla_host *, |
@@ -881,7 +882,9 @@ qla2x00_get_sp_from_handle(scsi_qla_host_t *vha, const char *func, | |||
881 | index); | 882 | index); |
882 | return NULL; | 883 | return NULL; |
883 | } | 884 | } |
885 | |||
884 | req->outstanding_cmds[index] = NULL; | 886 | req->outstanding_cmds[index] = NULL; |
887 | |||
885 | done: | 888 | done: |
886 | return sp; | 889 | return sp; |
887 | } | 890 | } |
@@ -982,6 +985,100 @@ done_post_logio_done_work: | |||
982 | } | 985 | } |
983 | 986 | ||
984 | static void | 987 | static void |
988 | qla24xx_els_ct_entry(scsi_qla_host_t *vha, struct req_que *req, | ||
989 | struct sts_entry_24xx *pkt, int iocb_type) | ||
990 | { | ||
991 | const char func[] = "ELS_CT_IOCB"; | ||
992 | const char *type; | ||
993 | struct qla_hw_data *ha = vha->hw; | ||
994 | srb_t *sp; | ||
995 | struct srb_bsg *sp_bsg; | ||
996 | struct fc_bsg_job *bsg_job; | ||
997 | uint16_t comp_status; | ||
998 | uint32_t fw_status[3]; | ||
999 | uint8_t* fw_sts_ptr; | ||
1000 | |||
1001 | sp = qla2x00_get_sp_from_handle(vha, func, req, pkt); | ||
1002 | if (!sp) | ||
1003 | return; | ||
1004 | sp_bsg = (struct srb_bsg*)sp->ctx; | ||
1005 | bsg_job = sp_bsg->bsg_job; | ||
1006 | |||
1007 | type = NULL; | ||
1008 | switch (sp_bsg->ctx.type) { | ||
1009 | case SRB_ELS_CMD_RPT: | ||
1010 | case SRB_ELS_CMD_HST: | ||
1011 | type = "els"; | ||
1012 | break; | ||
1013 | case SRB_CT_CMD: | ||
1014 | type = "ct pass-through"; | ||
1015 | break; | ||
1016 | default: | ||
1017 | qla_printk(KERN_WARNING, ha, | ||
1018 | "%s: Unrecognized SRB: (%p) type=%d.\n", func, sp, | ||
1019 | sp_bsg->ctx.type); | ||
1020 | return; | ||
1021 | } | ||
1022 | |||
1023 | comp_status = fw_status[0] = le16_to_cpu(pkt->comp_status); | ||
1024 | fw_status[1] = le16_to_cpu(((struct els_sts_entry_24xx*)pkt)->error_subcode_1); | ||
1025 | fw_status[2] = le16_to_cpu(((struct els_sts_entry_24xx*)pkt)->error_subcode_2); | ||
1026 | |||
1027 | /* return FC_CTELS_STATUS_OK and leave the decoding of the ELS/CT | ||
1028 | * fc payload to the caller | ||
1029 | */ | ||
1030 | bsg_job->reply->reply_data.ctels_reply.status = FC_CTELS_STATUS_OK; | ||
1031 | bsg_job->reply_len = sizeof(struct fc_bsg_reply) + sizeof(fw_status); | ||
1032 | |||
1033 | if (comp_status != CS_COMPLETE) { | ||
1034 | if (comp_status == CS_DATA_UNDERRUN) { | ||
1035 | bsg_job->reply->result = DID_OK << 16; | ||
1036 | bsg_job->reply->reply_payload_rcv_len = | ||
1037 | le16_to_cpu(((struct els_sts_entry_24xx*)pkt)->total_byte_count); | ||
1038 | |||
1039 | DEBUG2(qla_printk(KERN_WARNING, ha, | ||
1040 | "scsi(%ld:0x%x): ELS-CT pass-through-%s error comp_status-status=0x%x " | ||
1041 | "error subcode 1=0x%x error subcode 2=0x%x total_byte = 0x%x.\n", | ||
1042 | vha->host_no, sp->handle, type, comp_status, fw_status[1], fw_status[2], | ||
1043 | le16_to_cpu(((struct els_sts_entry_24xx*)pkt)->total_byte_count))); | ||
1044 | fw_sts_ptr = ((uint8_t*)bsg_job->req->sense) + sizeof(struct fc_bsg_reply); | ||
1045 | memcpy( fw_sts_ptr, fw_status, sizeof(fw_status)); | ||
1046 | } | ||
1047 | else { | ||
1048 | DEBUG2(qla_printk(KERN_WARNING, ha, | ||
1049 | "scsi(%ld:0x%x): ELS-CT pass-through-%s error comp_status-status=0x%x " | ||
1050 | "error subcode 1=0x%x error subcode 2=0x%x.\n", | ||
1051 | vha->host_no, sp->handle, type, comp_status, | ||
1052 | le16_to_cpu(((struct els_sts_entry_24xx*)pkt)->error_subcode_1), | ||
1053 | le16_to_cpu(((struct els_sts_entry_24xx*)pkt)->error_subcode_2))); | ||
1054 | bsg_job->reply->result = DID_ERROR << 16; | ||
1055 | bsg_job->reply->reply_payload_rcv_len = 0; | ||
1056 | fw_sts_ptr = ((uint8_t*)bsg_job->req->sense) + sizeof(struct fc_bsg_reply); | ||
1057 | memcpy( fw_sts_ptr, fw_status, sizeof(fw_status)); | ||
1058 | } | ||
1059 | DEBUG2(qla2x00_dump_buffer((uint8_t *)pkt, sizeof(*pkt))); | ||
1060 | } | ||
1061 | else { | ||
1062 | bsg_job->reply->result = DID_OK << 16;; | ||
1063 | bsg_job->reply->reply_payload_rcv_len = bsg_job->reply_payload.payload_len; | ||
1064 | bsg_job->reply_len = 0; | ||
1065 | } | ||
1066 | |||
1067 | dma_unmap_sg(&ha->pdev->dev, | ||
1068 | bsg_job->request_payload.sg_list, | ||
1069 | bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE); | ||
1070 | dma_unmap_sg(&ha->pdev->dev, | ||
1071 | bsg_job->reply_payload.sg_list, | ||
1072 | bsg_job->reply_payload.sg_cnt, DMA_FROM_DEVICE); | ||
1073 | if ((sp_bsg->ctx.type == SRB_ELS_CMD_HST) || | ||
1074 | (sp_bsg->ctx.type == SRB_CT_CMD)) | ||
1075 | kfree(sp->fcport); | ||
1076 | kfree(sp->ctx); | ||
1077 | mempool_free(sp, ha->srb_mempool); | ||
1078 | bsg_job->job_done(bsg_job); | ||
1079 | } | ||
1080 | |||
1081 | static void | ||
985 | qla24xx_logio_entry(scsi_qla_host_t *vha, struct req_que *req, | 1082 | qla24xx_logio_entry(scsi_qla_host_t *vha, struct req_que *req, |
986 | struct logio_entry_24xx *logio) | 1083 | struct logio_entry_24xx *logio) |
987 | { | 1084 | { |
@@ -1749,6 +1846,13 @@ void qla24xx_process_response_queue(struct scsi_qla_host *vha, | |||
1749 | qla24xx_logio_entry(vha, rsp->req, | 1846 | qla24xx_logio_entry(vha, rsp->req, |
1750 | (struct logio_entry_24xx *)pkt); | 1847 | (struct logio_entry_24xx *)pkt); |
1751 | break; | 1848 | break; |
1849 | case CT_IOCB_TYPE: | ||
1850 | qla24xx_els_ct_entry(vha, rsp->req, pkt, CT_IOCB_TYPE); | ||
1851 | clear_bit(MBX_INTERRUPT, &vha->hw->mbx_cmd_flags); | ||
1852 | break; | ||
1853 | case ELS_IOCB_TYPE: | ||
1854 | qla24xx_els_ct_entry(vha, rsp->req, pkt, ELS_IOCB_TYPE); | ||
1855 | break; | ||
1752 | default: | 1856 | default: |
1753 | /* Type Not Supported. */ | 1857 | /* Type Not Supported. */ |
1754 | DEBUG4(printk(KERN_WARNING | 1858 | DEBUG4(printk(KERN_WARNING |
@@ -2049,7 +2153,6 @@ qla24xx_msix_default(int irq, void *dev_id) | |||
2049 | set_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags); | 2153 | set_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags); |
2050 | complete(&ha->mbx_intr_comp); | 2154 | complete(&ha->mbx_intr_comp); |
2051 | } | 2155 | } |
2052 | |||
2053 | return IRQ_HANDLED; | 2156 | return IRQ_HANDLED; |
2054 | } | 2157 | } |
2055 | 2158 | ||
@@ -2255,10 +2358,11 @@ qla2x00_free_irqs(scsi_qla_host_t *vha) | |||
2255 | 2358 | ||
2256 | if (ha->flags.msix_enabled) | 2359 | if (ha->flags.msix_enabled) |
2257 | qla24xx_disable_msix(ha); | 2360 | qla24xx_disable_msix(ha); |
2258 | else if (ha->flags.inta_enabled) { | 2361 | else if (ha->flags.msi_enabled) { |
2259 | free_irq(ha->pdev->irq, rsp); | 2362 | free_irq(ha->pdev->irq, rsp); |
2260 | pci_disable_msi(ha->pdev); | 2363 | pci_disable_msi(ha->pdev); |
2261 | } | 2364 | } else |
2365 | free_irq(ha->pdev->irq, rsp); | ||
2262 | } | 2366 | } |
2263 | 2367 | ||
2264 | 2368 | ||