diff options
-rw-r--r-- | drivers/scsi/qla2xxx/qla_bsg.c | 9 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_iocb.c | 80 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_isr.c | 83 |
3 files changed, 162 insertions, 10 deletions
diff --git a/drivers/scsi/qla2xxx/qla_bsg.c b/drivers/scsi/qla2xxx/qla_bsg.c index 518fccfbfdb2..04ead0620d5f 100644 --- a/drivers/scsi/qla2xxx/qla_bsg.c +++ b/drivers/scsi/qla2xxx/qla_bsg.c | |||
@@ -396,15 +396,6 @@ qla2x00_process_ct(struct fc_bsg_job *bsg_job) | |||
396 | char *type = "FC_BSG_HST_CT"; | 396 | char *type = "FC_BSG_HST_CT"; |
397 | struct srb_ctx *ct; | 397 | struct srb_ctx *ct; |
398 | 398 | ||
399 | /* pass through is supported only for ISP 4Gb or higher */ | ||
400 | if (!IS_FWI2_CAPABLE(ha)) { | ||
401 | DEBUG2(qla_printk(KERN_INFO, ha, | ||
402 | "scsi(%ld):Firmware is not capable to support FC " | ||
403 | "CT pass thru\n", vha->host_no)); | ||
404 | rval = -EPERM; | ||
405 | goto done; | ||
406 | } | ||
407 | |||
408 | req_sg_cnt = | 399 | req_sg_cnt = |
409 | dma_map_sg(&ha->pdev->dev, bsg_job->request_payload.sg_list, | 400 | dma_map_sg(&ha->pdev->dev, bsg_job->request_payload.sg_list, |
410 | bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE); | 401 | bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE); |
diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c index 370646f7b3ff..e27d94713bdf 100644 --- a/drivers/scsi/qla2xxx/qla_iocb.c +++ b/drivers/scsi/qla2xxx/qla_iocb.c | |||
@@ -1765,6 +1765,82 @@ qla24xx_els_iocb(srb_t *sp, struct els_entry_24xx *els_iocb) | |||
1765 | } | 1765 | } |
1766 | 1766 | ||
1767 | static void | 1767 | static void |
1768 | qla2x00_ct_iocb(srb_t *sp, ms_iocb_entry_t *ct_iocb) | ||
1769 | { | ||
1770 | uint16_t avail_dsds; | ||
1771 | uint32_t *cur_dsd; | ||
1772 | struct scatterlist *sg; | ||
1773 | int index; | ||
1774 | uint16_t tot_dsds; | ||
1775 | scsi_qla_host_t *vha = sp->fcport->vha; | ||
1776 | struct qla_hw_data *ha = vha->hw; | ||
1777 | struct fc_bsg_job *bsg_job = ((struct srb_ctx *)sp->ctx)->u.bsg_job; | ||
1778 | int loop_iterartion = 0; | ||
1779 | int cont_iocb_prsnt = 0; | ||
1780 | int entry_count = 1; | ||
1781 | |||
1782 | memset(ct_iocb, 0, sizeof(ms_iocb_entry_t)); | ||
1783 | ct_iocb->entry_type = CT_IOCB_TYPE; | ||
1784 | ct_iocb->entry_status = 0; | ||
1785 | ct_iocb->handle1 = sp->handle; | ||
1786 | SET_TARGET_ID(ha, ct_iocb->loop_id, sp->fcport->loop_id); | ||
1787 | ct_iocb->status = __constant_cpu_to_le16(0); | ||
1788 | ct_iocb->control_flags = __constant_cpu_to_le16(0); | ||
1789 | ct_iocb->timeout = 0; | ||
1790 | ct_iocb->cmd_dsd_count = | ||
1791 | __constant_cpu_to_le16(bsg_job->request_payload.sg_cnt); | ||
1792 | ct_iocb->total_dsd_count = | ||
1793 | __constant_cpu_to_le16(bsg_job->request_payload.sg_cnt + 1); | ||
1794 | ct_iocb->req_bytecount = | ||
1795 | cpu_to_le32(bsg_job->request_payload.payload_len); | ||
1796 | ct_iocb->rsp_bytecount = | ||
1797 | cpu_to_le32(bsg_job->reply_payload.payload_len); | ||
1798 | |||
1799 | ct_iocb->dseg_req_address[0] = cpu_to_le32(LSD(sg_dma_address | ||
1800 | (bsg_job->request_payload.sg_list))); | ||
1801 | ct_iocb->dseg_req_address[1] = cpu_to_le32(MSD(sg_dma_address | ||
1802 | (bsg_job->request_payload.sg_list))); | ||
1803 | ct_iocb->dseg_req_length = ct_iocb->req_bytecount; | ||
1804 | |||
1805 | ct_iocb->dseg_rsp_address[0] = cpu_to_le32(LSD(sg_dma_address | ||
1806 | (bsg_job->reply_payload.sg_list))); | ||
1807 | ct_iocb->dseg_rsp_address[1] = cpu_to_le32(MSD(sg_dma_address | ||
1808 | (bsg_job->reply_payload.sg_list))); | ||
1809 | ct_iocb->dseg_rsp_length = ct_iocb->rsp_bytecount; | ||
1810 | |||
1811 | avail_dsds = 1; | ||
1812 | cur_dsd = (uint32_t *)ct_iocb->dseg_rsp_address; | ||
1813 | index = 0; | ||
1814 | tot_dsds = bsg_job->reply_payload.sg_cnt; | ||
1815 | |||
1816 | for_each_sg(bsg_job->reply_payload.sg_list, sg, tot_dsds, index) { | ||
1817 | dma_addr_t sle_dma; | ||
1818 | cont_a64_entry_t *cont_pkt; | ||
1819 | |||
1820 | /* Allocate additional continuation packets? */ | ||
1821 | if (avail_dsds == 0) { | ||
1822 | /* | ||
1823 | * Five DSDs are available in the Cont. | ||
1824 | * Type 1 IOCB. | ||
1825 | */ | ||
1826 | cont_pkt = qla2x00_prep_cont_type1_iocb(vha); | ||
1827 | cur_dsd = (uint32_t *) cont_pkt->dseg_0_address; | ||
1828 | avail_dsds = 5; | ||
1829 | cont_iocb_prsnt = 1; | ||
1830 | entry_count++; | ||
1831 | } | ||
1832 | |||
1833 | sle_dma = sg_dma_address(sg); | ||
1834 | *cur_dsd++ = cpu_to_le32(LSD(sle_dma)); | ||
1835 | *cur_dsd++ = cpu_to_le32(MSD(sle_dma)); | ||
1836 | *cur_dsd++ = cpu_to_le32(sg_dma_len(sg)); | ||
1837 | loop_iterartion++; | ||
1838 | avail_dsds--; | ||
1839 | } | ||
1840 | ct_iocb->entry_count = entry_count; | ||
1841 | } | ||
1842 | |||
1843 | static void | ||
1768 | qla24xx_ct_iocb(srb_t *sp, struct ct_entry_24xx *ct_iocb) | 1844 | qla24xx_ct_iocb(srb_t *sp, struct ct_entry_24xx *ct_iocb) |
1769 | { | 1845 | { |
1770 | uint16_t avail_dsds; | 1846 | uint16_t avail_dsds; |
@@ -1867,7 +1943,9 @@ qla2x00_start_sp(srb_t *sp) | |||
1867 | qla24xx_els_iocb(sp, pkt); | 1943 | qla24xx_els_iocb(sp, pkt); |
1868 | break; | 1944 | break; |
1869 | case SRB_CT_CMD: | 1945 | case SRB_CT_CMD: |
1870 | qla24xx_ct_iocb(sp, pkt); | 1946 | IS_FWI2_CAPABLE(ha) ? |
1947 | qla24xx_ct_iocb(sp, pkt) : | ||
1948 | qla2x00_ct_iocb(sp, pkt); | ||
1871 | break; | 1949 | break; |
1872 | case SRB_ADISC_CMD: | 1950 | case SRB_ADISC_CMD: |
1873 | IS_FWI2_CAPABLE(ha) ? | 1951 | IS_FWI2_CAPABLE(ha) ? |
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index ffc855f7697d..518003328226 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c | |||
@@ -984,6 +984,86 @@ logio_done: | |||
984 | } | 984 | } |
985 | 985 | ||
986 | static void | 986 | static void |
987 | qla2x00_ct_entry(scsi_qla_host_t *vha, struct req_que *req, | ||
988 | sts_entry_t *pkt, int iocb_type) | ||
989 | { | ||
990 | const char func[] = "CT_IOCB"; | ||
991 | const char *type; | ||
992 | struct qla_hw_data *ha = vha->hw; | ||
993 | srb_t *sp; | ||
994 | struct srb_ctx *sp_bsg; | ||
995 | struct fc_bsg_job *bsg_job; | ||
996 | uint16_t comp_status; | ||
997 | |||
998 | sp = qla2x00_get_sp_from_handle(vha, func, req, pkt); | ||
999 | if (!sp) | ||
1000 | return; | ||
1001 | |||
1002 | sp_bsg = sp->ctx; | ||
1003 | bsg_job = sp_bsg->u.bsg_job; | ||
1004 | |||
1005 | type = NULL; | ||
1006 | switch (sp_bsg->type) { | ||
1007 | case SRB_CT_CMD: | ||
1008 | type = "ct pass-through"; | ||
1009 | break; | ||
1010 | default: | ||
1011 | qla_printk(KERN_WARNING, ha, | ||
1012 | "%s: Unrecognized SRB: (%p) type=%d.\n", func, sp, | ||
1013 | sp_bsg->type); | ||
1014 | return; | ||
1015 | } | ||
1016 | |||
1017 | comp_status = le16_to_cpu(pkt->comp_status); | ||
1018 | |||
1019 | /* return FC_CTELS_STATUS_OK and leave the decoding of the ELS/CT | ||
1020 | * fc payload to the caller | ||
1021 | */ | ||
1022 | bsg_job->reply->reply_data.ctels_reply.status = FC_CTELS_STATUS_OK; | ||
1023 | bsg_job->reply_len = sizeof(struct fc_bsg_reply); | ||
1024 | |||
1025 | if (comp_status != CS_COMPLETE) { | ||
1026 | if (comp_status == CS_DATA_UNDERRUN) { | ||
1027 | bsg_job->reply->result = DID_OK << 16; | ||
1028 | bsg_job->reply->reply_payload_rcv_len = | ||
1029 | le16_to_cpu(((sts_entry_t *)pkt)->rsp_info_len); | ||
1030 | |||
1031 | DEBUG2(qla_printk(KERN_WARNING, ha, | ||
1032 | "scsi(%ld): CT pass-through-%s error " | ||
1033 | "comp_status-status=0x%x total_byte = 0x%x.\n", | ||
1034 | vha->host_no, type, comp_status, | ||
1035 | bsg_job->reply->reply_payload_rcv_len)); | ||
1036 | } else { | ||
1037 | DEBUG2(qla_printk(KERN_WARNING, ha, | ||
1038 | "scsi(%ld): CT pass-through-%s error " | ||
1039 | "comp_status-status=0x%x.\n", | ||
1040 | vha->host_no, type, comp_status)); | ||
1041 | bsg_job->reply->result = DID_ERROR << 16; | ||
1042 | bsg_job->reply->reply_payload_rcv_len = 0; | ||
1043 | } | ||
1044 | DEBUG2(qla2x00_dump_buffer((uint8_t *)pkt, sizeof(*pkt))); | ||
1045 | } else { | ||
1046 | bsg_job->reply->result = DID_OK << 16;; | ||
1047 | bsg_job->reply->reply_payload_rcv_len = | ||
1048 | bsg_job->reply_payload.payload_len; | ||
1049 | bsg_job->reply_len = 0; | ||
1050 | } | ||
1051 | |||
1052 | dma_unmap_sg(&ha->pdev->dev, bsg_job->request_payload.sg_list, | ||
1053 | bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE); | ||
1054 | |||
1055 | dma_unmap_sg(&ha->pdev->dev, bsg_job->reply_payload.sg_list, | ||
1056 | bsg_job->reply_payload.sg_cnt, DMA_FROM_DEVICE); | ||
1057 | |||
1058 | if (sp_bsg->type == SRB_ELS_CMD_HST || sp_bsg->type == SRB_CT_CMD) | ||
1059 | kfree(sp->fcport); | ||
1060 | |||
1061 | kfree(sp->ctx); | ||
1062 | mempool_free(sp, ha->srb_mempool); | ||
1063 | bsg_job->job_done(bsg_job); | ||
1064 | } | ||
1065 | |||
1066 | static void | ||
987 | qla24xx_els_ct_entry(scsi_qla_host_t *vha, struct req_que *req, | 1067 | qla24xx_els_ct_entry(scsi_qla_host_t *vha, struct req_que *req, |
988 | struct sts_entry_24xx *pkt, int iocb_type) | 1068 | struct sts_entry_24xx *pkt, int iocb_type) |
989 | { | 1069 | { |
@@ -1303,6 +1383,9 @@ qla2x00_process_response_queue(struct rsp_que *rsp) | |||
1303 | qla2x00_mbx_iocb_entry(vha, rsp->req, | 1383 | qla2x00_mbx_iocb_entry(vha, rsp->req, |
1304 | (struct mbx_entry *)pkt); | 1384 | (struct mbx_entry *)pkt); |
1305 | break; | 1385 | break; |
1386 | case CT_IOCB_TYPE: | ||
1387 | qla2x00_ct_entry(vha, rsp->req, pkt, CT_IOCB_TYPE); | ||
1388 | break; | ||
1306 | default: | 1389 | default: |
1307 | /* Type Not Supported. */ | 1390 | /* Type Not Supported. */ |
1308 | DEBUG4(printk(KERN_WARNING | 1391 | DEBUG4(printk(KERN_WARNING |