scsi: mpt3sas: Limit NVMe request size to 2 MiB

The HBA firmware reports NVMe MDTS values based on the underlying drive
capability. However, because the driver allocates a fixed 4K buffer for
the PRP list, accommodating at most 512 entries, the driver supports a
maximum I/O transfer size of 2 MiB.

Limit max_hw_sectors to the smaller of the reported MDTS and the 2 MiB
driver limit to prevent issuing oversized I/O that may lead to a kernel
oops.

Cc: stable@vger.kernel.org
Fixes: 9b8b84879d ("block: Increase BLK_DEF_MAX_SECTORS_CAP")
Reported-by: Mira Limbeck <m.limbeck@proxmox.com>
Closes: https://lore.kernel.org/r/291f78bf-4b4a-40dd-867d-053b36c564b3@proxmox.com
Link: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=9b8b84879d4a
Suggested-by: Keith Busch <kbusch@kernel.org>
Signed-off-by: Ranjan Kumar <ranjan.kumar@broadcom.com>
Tested-by: Mira Limbeck <m.limbeck@proxmox.com>
Link: https://patch.msgid.link/20260414110811.85156-1-ranjan.kumar@broadcom.com
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
master
Ranjan Kumar 2026-04-14 16:38:11 +05:30 committed by Martin K. Petersen
parent 7b03c93d2b
commit 04631f55af
1 changed files with 13 additions and 1 deletions

View File

@ -2738,8 +2738,20 @@ scsih_sdev_configure(struct scsi_device *sdev, struct queue_limits *lim)
pcie_device->enclosure_level,
pcie_device->connector_name);
/*
* The HBA firmware passes the NVMe drive's MDTS
* (Maximum Data Transfer Size) up to the driver. However,
* the driver hardcodes a 4K buffer size for the PRP list,
* accommodating at most 512 entries. This strictly limits
* the maximum supported NVMe I/O transfer to 2 MiB.
*
* Cap max_hw_sectors to the smaller of the drive's reported
* MDTS or the 2 MiB driver limit to prevent kernel oopses.
*/
lim->max_hw_sectors = SZ_2M >> SECTOR_SHIFT;
if (pcie_device->nvme_mdts)
lim->max_hw_sectors = pcie_device->nvme_mdts / 512;
lim->max_hw_sectors = min(lim->max_hw_sectors,
pcie_device->nvme_mdts >> SECTOR_SHIFT);
pcie_device_put(pcie_device);
spin_unlock_irqrestore(&ioc->pcie_device_lock, flags);