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

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

 



On Tue, 2011-08-16 at 09:57 -0700, Roland Dreier wrote:
> 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.
> 

Ouch..  So it sounds like the dma-mapping.h macro usage in target core
is backwards for following the DMA_FROM_DEVICE -> SCSI READ and
DMA_TO_DEVICE -> SCSI WRITE as used by drivers/scsi/ for traditional
initiator mode / LLD operation.

Conceptually this makes things more confusing, but requiring each HW
target fabric driver to have to flip these around looks pretty ugly..

I'm happy to merge this as a workaround to address the DMAR exceptions
above, but need to think if it makes sense to do a wholesale conversion
of this for target core..


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

Mmmm, I don't think this is correct.  It's my understanding that
DMA_BIDIRECTIONAL is different from SCSI bidi operation, and that the
individual bidi payloads should be retaining their individual
DMA_FROM_DEVICE and DMA_TO_DEVICE usage..  (Boaz CC'ed)


> +	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) {

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