]> www.infradead.org Git - users/dwmw2/linux.git/commitdiff
scsi: mpt3sas: Use 63-bit DMA addressing on SAS35 HBA
authorSuganath Prabu <suganath-prabu.subramani@broadcom.com>
Tue, 30 Jul 2019 07:43:57 +0000 (03:43 -0400)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 6 Aug 2019 17:08:19 +0000 (19:08 +0200)
commit df9a606184bfdb5ae3ca9d226184e9489f5c24f7 upstream.

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>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/scsi/mpt3sas/mpt3sas_base.c

index 8aacbd1e7db2c28b601e7fbe796774601dd84d89..f2d61d023bcb997e0d517280a84b5cbc8b0084bb 100644 (file)
@@ -2683,6 +2683,8 @@ _base_config_dma_addressing(struct MPT3SAS_ADAPTER *ioc, struct pci_dev *pdev)
 {
        u64 required_mask, coherent_mask;
        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)
                goto try_32bit;
@@ -2692,17 +2694,17 @@ _base_config_dma_addressing(struct MPT3SAS_ADAPTER *ioc, struct pci_dev *pdev)
                goto try_32bit;
 
        if (ioc->dma_mask)
-               coherent_mask = DMA_BIT_MASK(64);
+               coherent_mask = DMA_BIT_MASK(dma_mask);
        else
                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))
                goto try_32bit;
 
        ioc->base_add_sg_single = &_base_add_sg_single_64;
        ioc->sge_size = sizeof(Mpi2SGESimple64_t);
-       ioc->dma_mask = 64;
+       ioc->dma_mask = dma_mask;
        goto out;
 
  try_32bit:
@@ -2724,7 +2726,7 @@ static int
 _base_change_consistent_dma_mask(struct MPT3SAS_ADAPTER *ioc,
                                      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)))
                        return -ENODEV;
        }
@@ -4631,7 +4633,7 @@ _base_allocate_memory_pools(struct MPT3SAS_ADAPTER *ioc)
                total_sz += sz;
        } 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) {
                        ioc_warn(ioc, "no suitable consistent DMA mask for %s\n",
                                 pci_name(ioc->pdev));