diff options
| author | Harish Zunjarrao <harish.zunjarrao@qlogic.com> | 2010-07-23 06:28:32 -0400 |
|---|---|---|
| committer | James Bottomley <James.Bottomley@suse.de> | 2010-07-28 10:06:13 -0400 |
| commit | 9bc4f4fb44d22e5edc9369c87585a3b492073b8b (patch) | |
| tree | 0d2469b389af3e4b020b8e96b2d5beaeec3cb1db | |
| parent | 9a15eb4b514c526cf3181ce224967ab5d8dafe77 (diff) | |
[SCSI] qla2xxx: Add CT passthru support for ISP23xx adapters
Signed-off-by: Harish Zunjarrao <harish.zunjarrao@qlogic.com>
Signed-off-by: Giridhar Malavali <giridhar.malavali@qlogic.com>
Signed-off-by: James Bottomley <James.Bottomley@suse.de>
| -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 |
