[PATCH 5/5] tcm_qla2xxx: Fix confusion about DMA mapping direction

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

 



From: Roland Dreier <roland@xxxxxxxxxxxxxxx>

LIO core uses data_direction in the opposite way that qla2xxx needs; for
example, to the LIO core, a READ command is getting data from the target
so it uses DMA_FROM_DEVICE; however for the HBA to be able to DMA the
data to respond to the READ command, the buffer should be mapped with
DMA_TO_DEVICE (since data is flowing from memory to the HBA).

This causes problems on systems with a real IOMMU; eg with VT-d
(intel_iommu) enabled, one sees messages like

    DMAR:[DMA Read] Request device [06:00.0] fault addr ffe4e000
    DMAR:[fault reason 06] PTE Read access is not set

and the target is not able to transfer any data.

Fix this by adding a function tcm_qla2xxx_mapping_dir() that converts
from the LIO core direction to the value that qla2xxx needs to use.

Signed-off-by: Roland Dreier <roland@xxxxxxxxxxxxxxx>
---
 drivers/target/tcm_qla2xxx/tcm_qla2xxx_fabric.c |   31 ++++++++++++++++++++--
 1 files changed, 28 insertions(+), 3 deletions(-)

diff --git a/drivers/target/tcm_qla2xxx/tcm_qla2xxx_fabric.c b/drivers/target/tcm_qla2xxx/tcm_qla2xxx_fabric.c
index c0c7d2e..305f554 100644
--- a/drivers/target/tcm_qla2xxx/tcm_qla2xxx_fabric.c
+++ b/drivers/target/tcm_qla2xxx/tcm_qla2xxx_fabric.c
@@ -513,12 +513,37 @@ u32 tcm_qla2xxx_sess_get_index(struct se_session *se_sess)
 	return 0;
 }
 
+/*
+ * The LIO target core uses DMA_TO_DEVICE to mean that data is going
+ * to the target (eg handling a WRITE) and DMA_FROM_DEVICE to mean
+ * that data is coming from the target (eg handling a READ).  However,
+ * this is just the opposite of what we have to tell the DMA mapping
+ * layer -- eg when handling a READ, the HBA will have to DMA the data
+ * out of memory so it can send it to the initiator, which means we
+ * need to use DMA_TO_DEVICE when we map the data.
+ */
+static enum dma_data_direction tcm_qla2xxx_mapping_dir(struct se_cmd *se_cmd)
+{
+	if (se_cmd->t_tasks_bidi)
+		return DMA_BIDIRECTIONAL;
+
+	switch (se_cmd->data_direction) {
+	case DMA_TO_DEVICE:
+		return DMA_FROM_DEVICE;
+	case DMA_FROM_DEVICE:
+		return DMA_TO_DEVICE;
+	case DMA_NONE:
+	default:
+		return DMA_NONE;
+	}
+}
+
 int tcm_qla2xxx_write_pending(struct se_cmd *se_cmd)
 {
 	struct qla_tgt_cmd *cmd = container_of(se_cmd, struct qla_tgt_cmd, se_cmd);
 
 	cmd->bufflen = se_cmd->data_length;
-	cmd->dma_data_direction = se_cmd->data_direction;
+	cmd->dma_data_direction = tcm_qla2xxx_mapping_dir(se_cmd);
 	/*
 	 * Setup the struct se_task->task_sg[] chained SG list
 	 */
@@ -720,7 +745,7 @@ int tcm_qla2xxx_queue_data_in(struct se_cmd *se_cmd)
 	struct qla_tgt_cmd *cmd = container_of(se_cmd, struct qla_tgt_cmd, se_cmd);
 
 	cmd->bufflen = se_cmd->data_length;
-	cmd->dma_data_direction = se_cmd->data_direction;
+	cmd->dma_data_direction = tcm_qla2xxx_mapping_dir(se_cmd);
 	cmd->aborted = atomic_read(&se_cmd->t_transport_aborted);
 	/*
 	 * Setup the struct se_task->task_sg[] chained SG list
@@ -754,7 +779,7 @@ int tcm_qla2xxx_queue_status(struct se_cmd *se_cmd)
 	cmd->sg = NULL;
 	cmd->sg_cnt = 0;
 	cmd->offset = 0;
-	cmd->dma_data_direction = se_cmd->data_direction;
+	cmd->dma_data_direction = tcm_qla2xxx_mapping_dir(se_cmd);
 	cmd->aborted = atomic_read(&se_cmd->t_transport_aborted);
 
 	if (se_cmd->data_direction == DMA_FROM_DEVICE) {
-- 
1.7.5.4

--
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