aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/scsi/qla2xxx/qla_bsg.c9
-rw-r--r--drivers/scsi/qla2xxx/qla_iocb.c80
-rw-r--r--drivers/scsi/qla2xxx/qla_isr.c83
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
1767static void 1767static void
1768qla2x00_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
1843static void
1768qla24xx_ct_iocb(srb_t *sp, struct ct_entry_24xx *ct_iocb) 1844qla24xx_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
986static void 986static void
987qla2x00_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
1066static void
987qla24xx_els_ct_entry(scsi_qla_host_t *vha, struct req_que *req, 1067qla24xx_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