Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

scsi: mpt3sas: Use 63-bit DMA addressing on SAS35 HBA

Although SAS3 & SAS3.5 IT HBA controllers support 64-bit DMA addressing, as
per hardware design, if DMA-able range contains all 64-bits
set (0xFFFFFFFF-FFFFFFFF) then it results in a firmware fault.

E.g. SGE's start address is 0xFFFFFFFF-FFFF000 and data length is 0x1000
bytes. when HBA tries to DMA the data at 0xFFFFFFFF-FFFFFFFF location then
HBA will fault the firmware.

Driver will set 63-bit DMA mask to ensure the above address will not be
used.

Cc: <stable@vger.kernel.org> # 5.1.20+
Signed-off-by: Suganath Prabu <suganath-prabu.subramani@broadcom.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>

authored by

Suganath Prabu and committed by
Martin K. Petersen
df9a6061 18a56d69

+7 -5
+7 -5
drivers/scsi/mpt3sas/mpt3sas_base.c
··· 2703 2703 { 2704 2704 u64 required_mask, coherent_mask; 2705 2705 struct sysinfo s; 2706 + /* Set 63 bit DMA mask for all SAS3 and SAS35 controllers */ 2707 + int dma_mask = (ioc->hba_mpi_version_belonged > MPI2_VERSION) ? 63 : 64; 2706 2708 2707 2709 if (ioc->is_mcpu_endpoint) 2708 2710 goto try_32bit; ··· 2714 2712 goto try_32bit; 2715 2713 2716 2714 if (ioc->dma_mask) 2717 - coherent_mask = DMA_BIT_MASK(64); 2715 + coherent_mask = DMA_BIT_MASK(dma_mask); 2718 2716 else 2719 2717 coherent_mask = DMA_BIT_MASK(32); 2720 2718 2721 - if (dma_set_mask(&pdev->dev, DMA_BIT_MASK(64)) || 2719 + if (dma_set_mask(&pdev->dev, DMA_BIT_MASK(dma_mask)) || 2722 2720 dma_set_coherent_mask(&pdev->dev, coherent_mask)) 2723 2721 goto try_32bit; 2724 2722 2725 2723 ioc->base_add_sg_single = &_base_add_sg_single_64; 2726 2724 ioc->sge_size = sizeof(Mpi2SGESimple64_t); 2727 - ioc->dma_mask = 64; 2725 + ioc->dma_mask = dma_mask; 2728 2726 goto out; 2729 2727 2730 2728 try_32bit: ··· 2746 2744 _base_change_consistent_dma_mask(struct MPT3SAS_ADAPTER *ioc, 2747 2745 struct pci_dev *pdev) 2748 2746 { 2749 - if (pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64))) { 2747 + if (pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(ioc->dma_mask))) { 2750 2748 if (pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32))) 2751 2749 return -ENODEV; 2752 2750 } ··· 4991 4989 total_sz += sz; 4992 4990 } while (ioc->rdpq_array_enable && (++i < ioc->reply_queue_count)); 4993 4991 4994 - if (ioc->dma_mask == 64) { 4992 + if (ioc->dma_mask > 32) { 4995 4993 if (_base_change_consistent_dma_mask(ioc, ioc->pdev) != 0) { 4996 4994 ioc_warn(ioc, "no suitable consistent DMA mask for %s\n", 4997 4995 pci_name(ioc->pdev));