[PATCH] qla2xxx: Reenable SRR support in qla_target.c

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Nicholas Bellinger <nab@xxxxxxxxxxxxxxx>

This patch re-enables support for sequence retransmission request (SRR) in
FC target mode that uses new cmd->sg_srr_start + cmd->dma_buffers assignments
based upon a received SRR offset for individual struct qla_tgt_cmd descriptors
during qla_tgt_set_data_offset() execution.

This includes fixing qla_tgt_handle_srr_work() to reset SRR related values
from the original se_cmd scatterlists setup by tcm_qla2xxx module code via
transport_do_task_sg_chain(), and subsequent qla2*xx_handle_srr() process
context execution for >= 24xx and < 24xx codepaths.  The new cmd->sg_srr_start
SGL pointer is used by qla_tgt_pci_map_calc_cnt() + qla_tgt_unmap_sg() with
pci_map_page() + pci_unmap_page() respectively to handle SRR offsets into an
existing cmd->sg set of scatterlists.

So far this patch has been initially tested with qla25xx hardware using
se_cmds of type SCF_SCSI_DATA_SG_IO_CDB with physical link layer failure
with FCP_READ to generate SRR_IU_DATA_IN, and FCP_WRITE to generate
SRR_IU_DATA_OUT.

Reported-by: Roland Dreier <roland@xxxxxxxxxxxxxxx>
Signed-off-by: Nicholas Bellinger <nab@xxxxxxxxxxxxxxx>
---
 drivers/scsi/qla2xxx/qla_target.c |  348 +++++++++++++++++++------------------
 drivers/scsi/qla2xxx/qla_target.h |    7 +-
 2 files changed, 181 insertions(+), 174 deletions(-)

diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c
index 0d4fa3c..ade0d90 100644
--- a/drivers/scsi/qla2xxx/qla_target.c
+++ b/drivers/scsi/qla2xxx/qla_target.c
@@ -107,7 +107,7 @@ static void qla24xx_send_term_exchange(struct scsi_qla_host *ha, struct qla_tgt_
 	atio7_entry_t *atio, int ha_locked);
 static void qla_tgt_reject_free_srr_imm(struct scsi_qla_host *ha, struct srr_imm *imm,
 	int ha_lock);
-static int qla_tgt_cut_cmd_data_head(struct qla_tgt_cmd *cmd, unsigned int offset);
+static int qla_tgt_set_data_offset(struct qla_tgt_cmd *cmd, uint32_t offset);
 static void qla_tgt_clear_tgt_db(struct qla_tgt *tgt, bool local_only);
 static int qla_tgt_unreg_sess(struct qla_tgt_sess *sess);
 /*
@@ -1601,13 +1601,45 @@ EXPORT_SYMBOL(qla_tgt_xmit_tm_rsp);
 /* No locks */
 static int qla_tgt_pci_map_calc_cnt(struct qla_tgt_prm *prm)
 {
-	BUG_ON(prm->cmd->sg_cnt == 0);
+	struct qla_tgt_cmd *cmd = prm->cmd;
+	struct scatterlist *sg;
+	int initial_off = cmd->sg_srr_off, i = 0, j;
+
+	BUG_ON(cmd->sg_cnt == 0);
+
+	prm->sg = (struct scatterlist *)cmd->sg;
+	/*
+	 * Use pci_map_sg() for non SRR payloads, otherwise use pci_map_page()
+	 * from cmd->sg_srr_start with sg_srr_off -> initial_off
+	 */
+	if (!cmd->sg_srr_start) {
+		prm->seg_cnt = pci_map_sg(prm->tgt->ha->pdev, cmd->sg,
+					cmd->sg_cnt, cmd->dma_data_direction);
+		if (unlikely(prm->seg_cnt == 0))
+			goto out_err;
+	} else {
+		u64 dma_pointer;
+
+		for_each_sg(cmd->sg_srr_start, sg, cmd->sg_cnt, i) {
+			DEBUG22(qla_printk(KERN_INFO, cmd->vha->hw, "Calling pci_map_page:"
+				" sg[%d]: %p, page: %p, offset: %d , init_off: %d"
+				" length: %d\n", i, sg, sg_page(sg), sg->offset,
+				initial_off, (sg->length - initial_off)));
+
+			dma_pointer = pci_map_page(prm->tgt->ha->pdev,
+						sg_page(sg), initial_off,
+						(sg->length - initial_off),
+						prm->cmd->dma_data_direction);
+			if (unlikely(pci_dma_mapping_error(prm->tgt->ha->pdev,
+							dma_pointer)))
+				goto out_err;
+
+			cmd->srr_dma_buffer[i] = dma_pointer;
+			initial_off = 0;
+		}
 
-	prm->sg = (struct scatterlist *)prm->cmd->sg;
-	prm->seg_cnt = pci_map_sg(prm->tgt->ha->pdev, prm->cmd->sg,
-		prm->cmd->sg_cnt, prm->cmd->dma_data_direction);
-	if (unlikely(prm->seg_cnt == 0))
-		goto out_err;
+		prm->seg_cnt += i;
+	}
 
 	prm->cmd->sg_mapped = 1;
 
@@ -1629,6 +1661,19 @@ static int qla_tgt_pci_map_calc_cnt(struct qla_tgt_prm *prm)
 	return 0;
 
 out_err:
+	if (!cmd->sg_srr_start)
+		goto out;
+	j = i;
+	i = 0;
+	initial_off = cmd->sg_srr_off;
+
+	for_each_sg(cmd->sg_srr_start, sg, j, i) {
+		pci_unmap_page(prm->tgt->ha->pdev, cmd->srr_dma_buffer[i],
+				(sg->length - initial_off),
+				cmd->dma_data_direction);
+		initial_off = 0;
+	}
+out:
 	printk(KERN_ERR "qla_target(%d): PCI mapping failed: sg_cnt=%d",
 		0, prm->cmd->sg_cnt);
 	return -1;
@@ -1639,7 +1684,22 @@ static inline void qla_tgt_unmap_sg(struct scsi_qla_host *vha, struct qla_tgt_cm
 	struct qla_hw_data *ha = vha->hw;
 
 	BUG_ON(!cmd->sg_mapped);
-	pci_unmap_sg(ha->pdev, cmd->sg, cmd->sg_cnt, cmd->dma_data_direction);
+	if (!cmd->sg_srr_start)
+		pci_unmap_sg(ha->pdev, cmd->sg, cmd->sg_cnt, cmd->dma_data_direction);
+	else {
+		struct scatterlist *sg;
+		int i, initial_off = cmd->sg_srr_off;
+
+		for_each_sg(cmd->sg_srr_start, sg, cmd->sg_cnt, i) {
+			pci_unmap_page(ha->pdev, cmd->srr_dma_buffer[i],
+					(sg->length - initial_off),
+					cmd->dma_data_direction);
+			initial_off = 0;
+		}
+
+		cmd->sg_srr_start = NULL;
+		cmd->sg_srr_off = 0;
+	}
 	cmd->sg_mapped = 0;
 }
 
@@ -2264,6 +2324,12 @@ static void qla_tgt_check_srr_debug(struct qla_tgt_cmd *cmd, int *xmit_type)
 			cmd->tag));
 	}
 #endif
+	/*
+	 * It's currently not possible to simulate SRRs for FCP_WRITE without
+	 * a physical link layer failure, so don't even try here..
+	 */
+	if (cmd->dma_data_direction != DMA_FROM_DEVICE)
+		return;
 
 	if (qla_tgt_has_data(cmd) && (cmd->sg_cnt > 1) &&
 	    ((qla_tgt_srr_random() % 100) == 20)) {
@@ -2292,9 +2358,9 @@ static void qla_tgt_check_srr_debug(struct qla_tgt_cmd *cmd, int *xmit_type)
 			offset, cmd->bufflen));
 		if (offset == 0)
 			*xmit_type &= ~QLA_TGT_XMIT_DATA;
-		else if (qla_tgt_cut_cmd_data_head(cmd, offset)) {
-			DEBUG22(qla_printk(KERN_INFO, "qla_tgt_cut_cmd_data_head() failed (tag %d)",
-				cmd->tag));
+		else if (qla_tgt_set_data_offset(cmd, offset)) {
+			DEBUG22(qla_printk(KERN_INFO, cmd->vha->hw, "qla_tgt_set_data_offset()"
+				" failed (tag %d)", cmd->tag));
 		}
 	}
 }
@@ -2304,9 +2370,7 @@ static inline void qla_tgt_check_srr_debug(struct qla_tgt_cmd *cmd, int *xmit_ty
 
 int qla2xxx_xmit_response(struct qla_tgt_cmd *cmd, int xmit_type, uint8_t scsi_status)
 {
-#if 0
 	qla_tgt_check_srr_debug(cmd, &xmit_type);
-#endif
 
 	DEBUG21(qla_printk(KERN_INFO, cmd->vha->hw, "is_send_status=%d,"
 		" cmd->bufflen=%d, cmd->sg_cnt=%d, cmd->dma_data_direction=%d",
@@ -2684,8 +2748,8 @@ void qla_tgt_free_cmd(struct qla_tgt_cmd *cmd)
 {
 	BUG_ON(cmd->sg_mapped);
 
-	if (unlikely(cmd->free_sg))
-		kfree(cmd->sg);
+	if (unlikely(cmd->srr_dma_buffer))
+		kfree(cmd->srr_dma_buffer);
 	kmem_cache_free(qla_tgt_cmd_cachep, cmd);
 }
 EXPORT_SYMBOL(qla_tgt_free_cmd);
@@ -2710,8 +2774,6 @@ static int qla_tgt_prepare_srr_ctio(struct scsi_qla_host *vha, struct qla_tgt_cm
 		return EINVAL;
 	}
 
-	dump_stack();
-
 	sc = kzalloc(sizeof(*sc), GFP_ATOMIC);
 	if (sc != NULL) {
 		sc->cmd = cmd;
@@ -3458,126 +3520,77 @@ static int qla24xx_handle_els(struct scsi_qla_host *vha, notify24xx_entry_t *ioc
 	return res;
 }
 
-static int qla_tgt_cut_cmd_data_head(struct qla_tgt_cmd *cmd, unsigned int offset)
+static int qla_tgt_set_data_offset(struct qla_tgt_cmd *cmd, uint32_t offset)
 {
-	int res = 0;
-	int cnt, first_sg, first_page = 0, first_page_offs = 0, i;
-	unsigned int l;
-	int cur_dst, cur_src;
-	struct scatterlist *sg;
-	size_t bufflen = 0;
-
-	first_sg = -1;
-	cnt = 0;
-	l = 0;
-	for (i = 0; i < cmd->sg_cnt; i++) {
-		l += cmd->sg[i].length;
-		if (l > offset) {
-			int sg_offs = l - cmd->sg[i].length;
-			first_sg = i;
-			if (cmd->sg[i].offset == 0) {
-				first_page_offs = offset % PAGE_SIZE;
-				first_page = (offset - sg_offs) >> PAGE_SHIFT;
-			} else {
-				DEBUG24(qla_printk(KERN_INFO, cmd->vha->hw, "i=%d, sg[i]."
-					"offset=%d, sg_offs=%d", i, cmd->sg[i].offset,
-					sg_offs));
-				if ((cmd->sg[i].offset + sg_offs) > offset) {
-					first_page_offs = offset - sg_offs;
-					first_page = 0;
-				} else {
-					int sec_page_offs = sg_offs +
-						(PAGE_SIZE - cmd->sg[i].offset);
-					first_page_offs = sec_page_offs % PAGE_SIZE;
-					first_page = 1 +
-						((offset - sec_page_offs) >>
-							PAGE_SHIFT);
-				}
-			}
-			cnt = cmd->sg_cnt - i + (first_page_offs != 0);
-			break;
-		}
-	}
-	if (first_sg == -1) {
-		printk(KERN_ERR "qla_target(%d): Wrong offset %d, buf length %d",
-			cmd->vha->vp_idx, offset, cmd->bufflen);
-		return -EINVAL;
-	}
+	struct scatterlist *sg = NULL, *sg_srr_start = NULL;
+	size_t first_offset = 0, rem_offset = offset, tmp = 0;
+	int i;
 
-	DEBUG24(qla_printk(KERN_INFO, cmd->vha->hw, "offset=%d, first_sg=%d, first_page=%d, "
-		"first_page_offs=%d, cmd->bufflen=%d, cmd->sg_cnt=%d", offset,
-		first_sg, first_page, first_page_offs, cmd->bufflen,
-		cmd->sg_cnt));
+	DEBUG24(qla_printk(cmd->vha->hw, "Entering qla_tgt_set_data_offset:"
+		" cmd: %p, cmd->sg: %p, cmd->sg_cnt: %u, direction: %d\n",
+		cmd, cmd->sg, cmd->sg_cnt, cmd->dma_data_direction));
 
-	sg = kzalloc(cnt * sizeof(sg[0]), GFP_KERNEL);
-	if (sg == NULL) {
-		printk(KERN_ERR "qla_target(%d): Unable to allocate cut "
-			"SG (len %zd)", cmd->vha->vp_idx,
-			cnt * sizeof(sg[0]));
-		return -ENOMEM;
+	if (!cmd->sg || !cmd->sg_cnt) {
+		printk(KERN_ERR "Missing cmd->sg or zero cmd->sg_cnt in"
+				" qla_tgt_set_data_offset\n");
+		return -EINVAL;
 	}
-	sg_init_table(sg, cnt);
-
-	cur_dst = 0;
-	cur_src = first_sg;
-	if (first_page_offs != 0) {
-		int fpgs;
-		sg_set_page(&sg[cur_dst], &sg_page(&cmd->sg[cur_src])[first_page],
-			PAGE_SIZE - first_page_offs, first_page_offs);
-		bufflen += sg[cur_dst].length;
-		DEBUG24(qla_printk(KERN_INFO, cmd->vha->hw, "cur_dst=%d, cur_src=%d,"
-			" sg[].page=%p, sg[].offset=%d, sg[].length=%d, bufflen=%zu",
-			cur_dst, cur_src, sg_page(&sg[cur_dst]), sg[cur_dst].offset,
-			sg[cur_dst].length, bufflen));
-		cur_dst++;
-
-		fpgs = (cmd->sg[cur_src].length >> PAGE_SHIFT) +
-			((cmd->sg[cur_src].length & ~PAGE_MASK) != 0);
-		first_page++;
-		if (fpgs > first_page) {
-			sg_set_page(&sg[cur_dst],
-				&sg_page(&cmd->sg[cur_src])[first_page],
-				cmd->sg[cur_src].length - PAGE_SIZE*first_page,
-				0);
-			DEBUG24(qla_printk(KERN_INFO, cmd->vha->hw, "fpgs=%d, cur_dst=%d,"
-				" cur_src=%d, sg[].page=%p, sg[].length=%d, bufflen=%zu",
-				fpgs, cur_dst, cur_src, sg_page(&sg[cur_dst]),
-				sg[cur_dst].length, bufflen));
-			bufflen += sg[cur_dst].length;
-			cur_dst++;
+	/*
+	 * Walk the current cmd->sg list until we locate the new sg_srr_start
+	 */
+	for_each_sg(cmd->sg, sg, cmd->sg_cnt, i) {
+		DEBUG24(qla_printk(cmd->vha->hw, "sg[%d]: %p page: %p,"
+			" length: %d, offset: %d\n", i, sg, sg_page(sg),
+			sg->length, sg->offset));
+
+		if ((sg->length + tmp) > offset) {
+			first_offset = rem_offset;
+			sg_srr_start = sg;
+			DEBUG24(qla_printk(cmd->vha->hw, "Found matching sg[%d],"
+				" using %p as sg_srr_start, and using first_offset:"
+				" %lu\n", i, sg, first_offset));
+			break;
 		}
-		cur_src++;
+		tmp += sg->length;
+		rem_offset -= sg->length;
 	}
 
-	while (cur_src < cmd->sg_cnt) {
-		sg_set_page(&sg[cur_dst], sg_page(&cmd->sg[cur_src]),
-			cmd->sg[cur_src].length, cmd->sg[cur_src].offset);
-		DEBUG24(qla_printk(KERN_INFO, cmd->vha->hw, "cur_dst=%d, cur_src=%d, "
-			"sg[].page=%p, sg[].length=%d, sg[].offset=%d, "
-			"bufflen=%zu", cur_dst, cur_src, sg_page(&sg[cur_dst]),
-			sg[cur_dst].length, sg[cur_dst].offset, bufflen));
-		bufflen += sg[cur_dst].length;
-		cur_dst++;
-		cur_src++;
+	if (!sg_srr_start) {
+		printk(KERN_ERR "Unable to locate sg_srr_start for offset: %u\n", offset);
+		return -EINVAL;
 	}
 
-	if (cmd->free_sg)
-		kfree(cmd->sg);
+	cmd->srr_dma_buffer = kzalloc(sizeof(dma_addr_t) * cmd->tgt->sg_tablesize,
+					GFP_KERNEL);
+	if (!cmd->srr_dma_buffer)
+		return -ENOMEM;
 
-	cmd->sg = sg;
-	cmd->free_sg = 1;
-	cmd->sg_cnt = cur_dst;
-	cmd->bufflen = bufflen;
+	cmd->sg_srr_start = sg_srr_start;
+	cmd->sg_cnt -= i;
+	cmd->sg_srr_off = first_offset;
+	cmd->bufflen -= offset;
 	cmd->offset += offset;
 
-	return res;
+	DEBUG24(qla_printk(cmd->vha->hw, "New cmd->sg: %p\n", cmd->sg));
+	DEBUG24(qla_printk(cmd->vha->hw, "New cmd->sg_cnt: %u\n", cmd->sg_cnt));
+	DEBUG24(qla_printk(cmd->vha->hw, "New cmd->sg_srr_off: %u\n", cmd->sg_srr_off));
+	DEBUG24(qla_printk(cmd->vha->hw, "New cmd->bufflen: %u\n", cmd->bufflen));
+	DEBUG24(qla_printk(cmd->vha->hw, "New cmd->offset: %u\n", cmd->offset));
+
+	if (cmd->sg_cnt < 0)
+		BUG();
+
+	if (cmd->bufflen < 0)
+		BUG();
+
+	return 0;
 }
 
 static inline int qla_tgt_srr_adjust_data(struct qla_tgt_cmd *cmd,
 	uint32_t srr_rel_offs, int *xmit_type)
 {
 	int res = 0;
-	int rel_offs;
+	uint32_t rel_offs;
 
 	rel_offs = srr_rel_offs - cmd->offset;
 	DEBUG22(qla_printk(KERN_INFO, cmd->vha->hw, "srr_rel_offs=%d, rel_offs=%d",
@@ -3592,13 +3605,12 @@ static inline int qla_tgt_srr_adjust_data(struct qla_tgt_cmd *cmd,
 	} else if (rel_offs == cmd->bufflen)
 		*xmit_type = QLA_TGT_XMIT_STATUS;
 	else if (rel_offs > 0)
-		res = qla_tgt_cut_cmd_data_head(cmd, rel_offs);
+		res = qla_tgt_set_data_offset(cmd, rel_offs);
 
 	return res;
 }
 
 /* No locks, thread context */
-#warning FIXME: qla24xx_handle_srr
 static void qla24xx_handle_srr(struct scsi_qla_host *vha, struct srr_ctio *sctio,
 	struct srr_imm *imm)
 {
@@ -3620,8 +3632,8 @@ static void qla24xx_handle_srr(struct scsi_qla_host *vha, struct srr_ctio *sctio
 		__qla24xx_xmit_response(cmd, QLA_TGT_XMIT_STATUS, se_cmd->scsi_status);
 		break;
 	case SRR_IU_DATA_IN:
-#if 0
-		cmd->bufflen = 0;
+		cmd->bufflen = se_cmd->data_length;
+
 		if (qla_tgt_has_data(cmd)) {
 			uint32_t offset;
 			int xmit_type;
@@ -3640,17 +3652,16 @@ static void qla24xx_handle_srr(struct scsi_qla_host *vha, struct srr_ctio *sctio
 				cmd->se_cmd.scsi_status);
 			goto out_reject;
 		}
-#else
-		printk("q24 SRR_IU_DATA_IN, rejecting\n");
-		dump_stack();
-		goto out_reject;
-#endif
 		break;
 	case SRR_IU_DATA_OUT:
-#if 0
-		cmd->bufflen = 0;
-		cmd->sg = NULL;
-		cmd->sg_cnt = 0;
+		if (!cmd->sg || !cmd->sg_cnt) {
+			printk(KERN_ERR "Unable to process SRR_IU_DATA_OUT due to"
+				" missing cmd->sg\n");
+			dump_stack();
+			goto out_reject;
+		}
+		cmd->bufflen = se_cmd->data_length;
+
 		if (qla_tgt_has_data(cmd)) {
 			uint32_t offset;
 			int xmit_type;
@@ -3660,9 +3671,9 @@ static void qla24xx_handle_srr(struct scsi_qla_host *vha, struct srr_ctio *sctio
 			spin_lock_irqsave(&ha->hardware_lock, flags);
 			qla24xx_send_notify_ack(vha, ntfy,
 				NOTIFY_ACK_SRR_FLAGS_ACCEPT, 0, 0);
-			spin_unlock_irqrestore(&ha->hardware_lock. flags);
+			spin_unlock_irqrestore(&ha->hardware_lock, flags);
 			if (xmit_type & QLA_TGT_XMIT_DATA)
-				__qla_tgt_rdy_to_xfer(cmd);
+				qla_tgt_rdy_to_xfer(cmd);
 		} else {
 			printk(KERN_ERR "qla_target(%d): SRR for out data for cmd "
 				"without them (tag %d, SCSI status %d), "
@@ -3670,11 +3681,6 @@ static void qla24xx_handle_srr(struct scsi_qla_host *vha, struct srr_ctio *sctio
 				cmd->se_cmd.scsi_status);
 			goto out_reject;
 		}
-#else
-		printk("q24 SRR_IU_DATA_OUT, rejecting\n");
-		dump_stack();
-		goto out_reject;
-#endif
 		break;
 	default:
 		printk(KERN_ERR "qla_target(%d): Unknown srr_ui value %x",
@@ -3719,8 +3725,7 @@ static void qla2xxx_handle_srr(struct scsi_qla_host *vha, struct srr_ctio *sctio
 		__qla2xxx_xmit_response(cmd, QLA_TGT_XMIT_STATUS, se_cmd->scsi_status);
 		break;
 	case SRR_IU_DATA_IN:
-#if 0
-		cmd->bufflen = 0;
+		cmd->bufflen = se_cmd->data_length;
 		if (qla_tgt_has_data(cmd)) {
 			uint32_t offset;
 			int xmit_type;
@@ -3731,7 +3736,7 @@ static void qla2xxx_handle_srr(struct scsi_qla_host *vha, struct srr_ctio *sctio
 			qla2xxx_send_notify_ack(vha, ntfy, 0, 0, 0,
 				NOTIFY_ACK_SRR_FLAGS_ACCEPT, 0, 0);
 			spin_unlock_irqrestore(&ha->hardware_lock, flags);
-			__qla2xxx_xmit_response(cmd, xmit_type);
+			__qla2xxx_xmit_response(cmd, xmit_type, se_cmd->scsi_status);
 		} else {
 			printk(KERN_ERR "qla_target(%d): SRR for in data for cmd "
 				"without them (tag %d, SCSI status %d), "
@@ -3739,16 +3744,15 @@ static void qla2xxx_handle_srr(struct scsi_qla_host *vha, struct srr_ctio *sctio
 				cmd->se_cmd.scsi_status);
 			goto out_reject;
 		}
-#else
-		printk("q2x SRR_IU_DATA_IN:\n");
-		dump_stack();
-#endif
 		break;
 	case SRR_IU_DATA_OUT:
-#if 0
-		cmd->bufflen = 0;
-		cmd->sg = NULL;
-		cmd->sg_cnt = 0;
+		if (!cmd->sg || !cmd->sg_cnt) {
+			printk(KERN_ERR "Unable to process SRR_IU_DATA_OUT due to"
+					" missing cmd->sg\n");
+			goto out_reject;
+		}
+		cmd->bufflen = se_cmd->data_length;
+
 		if (qla_tgt_has_data(cmd)) {
 			uint32_t offset;
 			int xmit_type;
@@ -3760,7 +3764,7 @@ static void qla2xxx_handle_srr(struct scsi_qla_host *vha, struct srr_ctio *sctio
 				NOTIFY_ACK_SRR_FLAGS_ACCEPT, 0, 0);
 			spin_unlock_irqrestore(&ha->hardware_lock, flags);
 			if (xmit_type & QLA_TGT_XMIT_DATA)
-				__qla_tgt_rdy_to_xfer(cmd);
+				qla_tgt_rdy_to_xfer(cmd);
 		} else {
 			printk(KERN_ERR "qla_target(%d): SRR for out data for cmd "
 				"without them (tag %d, SCSI status %d), "
@@ -3768,10 +3772,6 @@ static void qla2xxx_handle_srr(struct scsi_qla_host *vha, struct srr_ctio *sctio
 				cmd->se_cmd.scsi_status);
 			goto out_reject;
 		}
-#else
-		printk("q2x SRR_IU_DATA_OUT:\n");
-		dump_stack();
-#endif
 		break;
 	default:
 		printk(KERN_ERR "qla_target(%d): Unknown srr_ui value %x",
@@ -3821,7 +3821,6 @@ static void qla_tgt_reject_free_srr_imm(struct scsi_qla_host *vha, struct srr_im
 	kfree(imm);
 }
 
-#warning FIXME: qla_tgt_handle_srr_work()
 static void qla_tgt_handle_srr_work(struct work_struct *work)
 {
 	struct qla_tgt *tgt = container_of(work, struct qla_tgt, srr_work);
@@ -3869,25 +3868,33 @@ restart:
 
 		cmd = sctio->cmd;
 		vha = cmd->vha;
-#if 0
-		/* Restore the originals, except bufflen */
+		/*
+		 * Reset qla_tgt_cmd SRR values and SGL pointer+count to follow
+		 * tcm_qla2xxx_write_pending() and tcm_qla2xxx_queue_data_in()
+		 * logic..
+		 */
 		cmd->offset = 0;
-		if (cmd->free_sg) {
-			kfree(cmd->sg);
-			cmd->free_sg = 0;
+		if (cmd->sg_srr_start) {
+			cmd->sg_srr_start = NULL;
+			cmd->sg_srr_off = 0;
+			kfree(cmd->srr_dma_buffer);
 		}
-		cmd->sg = NULL;
-		cmd->sg_cnt = 0;
-
 		se_cmd = &cmd->se_cmd;
 
+		if ((se_cmd->se_cmd_flags & SCF_SCSI_DATA_SG_IO_CDB) ||
+		    (se_cmd->se_cmd_flags & SCF_SCSI_CONTROL_SG_IO_CDB)) {
+			cmd->sg_cnt = se_cmd->t_tasks_sg_chained_no;
+			cmd->sg = se_cmd->t_tasks_sg_chained;
+		} else if (se_cmd->se_cmd_flags & SCF_SCSI_CONTROL_NONSG_IO_CDB) {
+			cmd->sg_cnt = 1;
+			cmd->sg = &se_cmd->t_tasks_sg_bounce;
+		}
+
 		DEBUG22(qla_printk(KERN_INFO, ha, "SRR cmd %p (se_cmd %p, tag %d, op %x), "
 			"sg_cnt=%d, offset=%d", cmd, &cmd->se_cmd,
 			cmd->tag, T_TASK(se_cmd)->t_task_cdb[0], cmd->sg_cnt,
 			cmd->offset));
-#else
-		dump_stack();
-#endif
+
 		if (IS_FWI2_CAPABLE(ha))
 			qla24xx_handle_srr(vha, sctio, imm);
 		else
@@ -4924,7 +4931,6 @@ static void qla_tgt_sess_work_fn(struct work_struct *work)
 int qla_tgt_add_target(struct qla_hw_data *ha, struct scsi_qla_host *base_vha)
 {
 	struct qla_tgt *tgt;
-	int sg_tablesize;
 
 	DEBUG21(qla_printk(KERN_INFO, ha, "Registering target for host %ld(%p)",
 			base_vha->host_no, ha));
@@ -4960,7 +4966,7 @@ int qla_tgt_add_target(struct qla_hw_data *ha, struct scsi_qla_host *base_vha)
 			   "addressing", base_vha->vp_idx);
 			tgt->tgt_enable_64bit_addr = 1;
 			/* 3 is reserved */
-			sg_tablesize =
+			tgt->sg_tablesize =
 			    QLA_MAX_SG_24XX(base_vha->req->length - 3);
 			tgt->datasegs_per_cmd = DATASEGS_PER_COMMAND_24XX;
 			tgt->datasegs_per_cont = DATASEGS_PER_CONT_24XX;
@@ -4970,14 +4976,14 @@ int qla_tgt_add_target(struct qla_hw_data *ha, struct scsi_qla_host *base_vha)
 				   "addressing enabled", base_vha->vp_idx);
 			tgt->tgt_enable_64bit_addr = 1;
 			/* 3 is reserved */
-			sg_tablesize =
+			tgt->sg_tablesize =
 				QLA_MAX_SG64(base_vha->req->length - 3);
 			tgt->datasegs_per_cmd = DATASEGS_PER_COMMAND64;
 			tgt->datasegs_per_cont = DATASEGS_PER_CONT64;
 		} else {
 			printk(KERN_INFO "qla_target(%d): Using 32 Bit "
 				   "PCI addressing", base_vha->vp_idx);
-			sg_tablesize =
+			tgt->sg_tablesize =
 				QLA_MAX_SG32(base_vha->req->length - 3);
 			tgt->datasegs_per_cmd = DATASEGS_PER_COMMAND32;
 			tgt->datasegs_per_cont = DATASEGS_PER_CONT32;
diff --git a/drivers/scsi/qla2xxx/qla_target.h b/drivers/scsi/qla2xxx/qla_target.h
index 7ee8cd1..3f9a6ed 100644
--- a/drivers/scsi/qla2xxx/qla_target.h
+++ b/drivers/scsi/qla2xxx/qla_target.h
@@ -819,7 +819,7 @@ struct qla_tgt {
 	 */
 	int irq_cmd_count;
 
-	int datasegs_per_cmd, datasegs_per_cont;
+	int datasegs_per_cmd, datasegs_per_cont, sg_tablesize;
 
 	/* Target's flags, serialized by pha->hardware_lock */
 	unsigned int tgt_enable_64bit_addr:1;	/* 64-bits PCI addressing enabled */
@@ -901,16 +901,17 @@ struct qla_tgt_cmd {
 
 	unsigned int conf_compl_supported:1;/* to save extra sess dereferences */
 	unsigned int sg_mapped:1;
-	unsigned int free_sg:1;
 	unsigned int aborted:1; /* Needed in case of SRR */
 	unsigned int write_data_transferred:1;
 
 	struct scatterlist *sg;	/* cmd data buffer SG vector */
+	struct scatterlist *sg_srr_start; /* Used for SRR data offset */
 	int sg_cnt;		/* SG segments count */
+	int sg_srr_off;		/* Used for SRR offsets into sg_srr_start */
 	int bufflen;		/* cmd buffer length */
 	int offset;
 	uint32_t tag;
-	dma_addr_t dma_handle;
+	dma_addr_t *srr_dma_buffer; /* Used for SRR offsets with pci_map_page() */
 	enum dma_data_direction dma_data_direction;
 
 	uint16_t loop_id;		    /* to save extra sess dereferences */
-- 
1.7.2.5

--
To unsubscribe from this list: send the line "unsubscribe target-devel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux SCSI]     [Kernel Newbies]     [Linux SCSI Target Infrastructure]     [Share Photos]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Linux IIO]     [Device Mapper]

  Powered by Linux