Commit df9a6061 authored by Suganath Prabu's avatar Suganath Prabu Committed by Martin K. Petersen
Browse files

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: default avatarSuganath Prabu <suganath-prabu.subramani@broadcom.com>
Reviewed-by: default avatarChristoph Hellwig <hch@lst.de>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent 18a56d69
Loading
Loading
Loading
Loading
+7 −5
Original line number Original line Diff line number Diff line
@@ -2703,6 +2703,8 @@ _base_config_dma_addressing(struct MPT3SAS_ADAPTER *ioc, struct pci_dev *pdev)
{
{
	u64 required_mask, coherent_mask;
	u64 required_mask, coherent_mask;
	struct sysinfo s;
	struct sysinfo s;
	/* Set 63 bit DMA mask for all SAS3 and SAS35 controllers */
	int dma_mask = (ioc->hba_mpi_version_belonged > MPI2_VERSION) ? 63 : 64;


	if (ioc->is_mcpu_endpoint)
	if (ioc->is_mcpu_endpoint)
		goto try_32bit;
		goto try_32bit;
@@ -2712,17 +2714,17 @@ _base_config_dma_addressing(struct MPT3SAS_ADAPTER *ioc, struct pci_dev *pdev)
		goto try_32bit;
		goto try_32bit;


	if (ioc->dma_mask)
	if (ioc->dma_mask)
		coherent_mask = DMA_BIT_MASK(64);
		coherent_mask = DMA_BIT_MASK(dma_mask);
	else
	else
		coherent_mask = DMA_BIT_MASK(32);
		coherent_mask = DMA_BIT_MASK(32);


	if (dma_set_mask(&pdev->dev, DMA_BIT_MASK(64)) ||
	if (dma_set_mask(&pdev->dev, DMA_BIT_MASK(dma_mask)) ||
	    dma_set_coherent_mask(&pdev->dev, coherent_mask))
	    dma_set_coherent_mask(&pdev->dev, coherent_mask))
		goto try_32bit;
		goto try_32bit;


	ioc->base_add_sg_single = &_base_add_sg_single_64;
	ioc->base_add_sg_single = &_base_add_sg_single_64;
	ioc->sge_size = sizeof(Mpi2SGESimple64_t);
	ioc->sge_size = sizeof(Mpi2SGESimple64_t);
	ioc->dma_mask = 64;
	ioc->dma_mask = dma_mask;
	goto out;
	goto out;


 try_32bit:
 try_32bit:
@@ -2744,7 +2746,7 @@ static int
_base_change_consistent_dma_mask(struct MPT3SAS_ADAPTER *ioc,
_base_change_consistent_dma_mask(struct MPT3SAS_ADAPTER *ioc,
				      struct pci_dev *pdev)
				      struct pci_dev *pdev)
{
{
	if (pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64))) {
	if (pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(ioc->dma_mask))) {
		if (pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)))
		if (pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)))
			return -ENODEV;
			return -ENODEV;
	}
	}
@@ -4989,7 +4991,7 @@ _base_allocate_memory_pools(struct MPT3SAS_ADAPTER *ioc)
		total_sz += sz;
		total_sz += sz;
	} while (ioc->rdpq_array_enable && (++i < ioc->reply_queue_count));
	} while (ioc->rdpq_array_enable && (++i < ioc->reply_queue_count));


	if (ioc->dma_mask == 64) {
	if (ioc->dma_mask > 32) {
		if (_base_change_consistent_dma_mask(ioc, ioc->pdev) != 0) {
		if (_base_change_consistent_dma_mask(ioc, ioc->pdev) != 0) {
			ioc_warn(ioc, "no suitable consistent DMA mask for %s\n",
			ioc_warn(ioc, "no suitable consistent DMA mask for %s\n",
				 pci_name(ioc->pdev));
				 pci_name(ioc->pdev));