Skip to content

Commit 82dbb57

Browse files
damien-lemoalmartinkpetersen
authored andcommitted
scsi: mpt3sas: Avoid IOMMU page faults on REPORT ZONES
Some firmware versions of the 9600 series SAS HBA byte-swap the REPORT ZONES command reply buffer from ATA-ZAC devices by directly accessing the buffer in the host memory. This does not respect the default command DMA direction and causes IOMMU page faults on architectures with an IOMMU enforcing write-only mappings for DMA_FROM_DEVICE DMA driection (e.g. AMD hosts). scsi 18:0:0:0: Direct-Access-ZBC ATA WDC WSH722020AL W870 PQ: 0 ANSI: 6 scsi 18:0:0:0: SATA: handle(0x0027), sas_addr(0x300062b2083e7c40), phy(0), device_name(0x5000cca29dc35e11) scsi 18:0:0:0: enclosure logical id (0x300062b208097c40), slot(0) scsi 18:0:0:0: enclosure level(0x0000), connector name( C0.0) scsi 18:0:0:0: atapi(n), ncq(y), asyn_notify(n), smart(y), fua(y), sw_preserve(y) scsi 18:0:0:0: qdepth(32), tagged(1), scsi_level(7), cmd_que(1) sd 18:0:0:0: Attached scsi generic sg2 type 20 sd 18:0:0:0: [sdc] Host-managed zoned block device mpt3sas 0000:41:00.0: AMD-Vi: Event logged [IO_PAGE_FAULT domain=0x0021 address=0xfff9b200 flags=0x0050] mpt3sas 0000:41:00.0: AMD-Vi: Event logged [IO_PAGE_FAULT domain=0x0021 address=0xfff9b300 flags=0x0050] mpt3sas_cm0: mpt3sas_ctl_pre_reset_handler: Releasing the trace buffer due to adapter reset. mpt3sas_cm0 fault info from func: mpt3sas_base_make_ioc_ready mpt3sas_cm0: fault_state(0x2666)! mpt3sas_cm0: sending diag reset !! mpt3sas_cm0: diag reset: SUCCESS sd 18:0:0:0: [sdc] REPORT ZONES start lba 0 failed sd 18:0:0:0: [sdc] REPORT ZONES: Result: hostbyte=DID_RESET driverbyte=DRIVER_OK sd 18:0:0:0: [sdc] 0 4096-byte logical blocks: (0 B/0 B) Avoid such issue by always mapping the buffer of REPORT ZONES commands using DMA_BIDIRECTIONAL (read+write IOMMU mapping). This is done by introducing the helper function _base_scsi_dma_map() and using this helper in _base_build_sg_scmd() and _base_build_sg_scmd_ieee() instead of calling directly scsi_dma_map(). Fixes: 471ef9d ("mpt3sas: Build MPI SGL LIST on GEN2 HBAs and IEEE SGL LIST on GEN3 HBAs") Cc: stable@vger.kernel.org Signed-off-by: Damien Le Moal <dlemoal@kernel.org> Link: https://lore.kernel.org/r/20240719073913.179559-3-dlemoal@kernel.org Reviewed-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Johannes Thumshirn <johannes.thumshirn@wdc.com> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
1 parent 1abc900 commit 82dbb57

File tree

1 file changed

+18
-2
lines changed

1 file changed

+18
-2
lines changed

drivers/scsi/mpt3sas/mpt3sas_base.c

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2671,6 +2671,22 @@ _base_build_zero_len_sge_ieee(struct MPT3SAS_ADAPTER *ioc, void *paddr)
26712671
_base_add_sg_single_ieee(paddr, sgl_flags, 0, 0, -1);
26722672
}
26732673

2674+
static inline int _base_scsi_dma_map(struct scsi_cmnd *cmd)
2675+
{
2676+
/*
2677+
* Some firmware versions byte-swap the REPORT ZONES command reply from
2678+
* ATA-ZAC devices by directly accessing in the host buffer. This does
2679+
* not respect the default command DMA direction and causes IOMMU page
2680+
* faults on some architectures with an IOMMU enforcing write mappings
2681+
* (e.g. AMD hosts). Avoid such issue by making the report zones buffer
2682+
* mapping bi-directional.
2683+
*/
2684+
if (cmd->cmnd[0] == ZBC_IN && cmd->cmnd[1] == ZI_REPORT_ZONES)
2685+
cmd->sc_data_direction = DMA_BIDIRECTIONAL;
2686+
2687+
return scsi_dma_map(cmd);
2688+
}
2689+
26742690
/**
26752691
* _base_build_sg_scmd - main sg creation routine
26762692
* pcie_device is unused here!
@@ -2717,7 +2733,7 @@ _base_build_sg_scmd(struct MPT3SAS_ADAPTER *ioc,
27172733
sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT;
27182734

27192735
sg_scmd = scsi_sglist(scmd);
2720-
sges_left = scsi_dma_map(scmd);
2736+
sges_left = _base_scsi_dma_map(scmd);
27212737
if (sges_left < 0)
27222738
return -ENOMEM;
27232739

@@ -2861,7 +2877,7 @@ _base_build_sg_scmd_ieee(struct MPT3SAS_ADAPTER *ioc,
28612877
}
28622878

28632879
sg_scmd = scsi_sglist(scmd);
2864-
sges_left = scsi_dma_map(scmd);
2880+
sges_left = _base_scsi_dma_map(scmd);
28652881
if (sges_left < 0)
28662882
return -ENOMEM;
28672883

0 commit comments

Comments
 (0)