[PATCH v7 5/6] ata: libata-scsi: probe additional LUNs for multi-LUN ATAPI devices
From: Phil Pemberton
Date: Wed Jun 10 2026 - 22:44:36 EST
After LUN 0 is added for an ATAPI device, check its BLIST_FORCELUN
flag. If set, call scsi_scan_target() with SCAN_WILD_CARD to trigger
the SCSI layer's built-in sequential LUN scan for that target only.
This probes LUNs 1..shost->max_lun, driven by the libata atapi_max_lun
module parameter.
Devices without BLIST_FORCELUN (the vast majority of ATAPI devices)
are left with only LUN 0 -- no sequential scan is triggered, so
single-LUN devices like the iHAS124 DVD writer are completely
unaffected.
Non-responding LUNs (PQ=0/PDT=0x1f) are silently skipped by
scsi_probe_and_add_lun() when BLIST_NO_LUN_1F is set on the device
via scsi_devinfo.
Also fix a TOCTOU window: call ata_scsi_assign_ofnode() before
scsi_device_put() so the reference to dev->sdev[0] is held while
the OF node is assigned.
Reviewed-by: Hannes Reinecke <hare@xxxxxxxxxx>
Signed-off-by: Phil Pemberton <philpem@xxxxxxxxxxxxx>
---
drivers/ata/libata-scsi.c | 25 ++++++++++++++++++++-----
1 file changed, 20 insertions(+), 5 deletions(-)
diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
index 2e3b5fd41d05..64cb2860a67b 100644
--- a/drivers/ata/libata-scsi.c
+++ b/drivers/ata/libata-scsi.c
@@ -26,6 +26,7 @@
#include <scsi/scsi_device.h>
#include <scsi/scsi_tcq.h>
#include <scsi/scsi_transport.h>
+#include <scsi/scsi_devinfo.h>
#include <linux/libata.h>
#include <linux/hdreg.h>
#include <linux/uaccess.h>
@@ -4754,13 +4755,27 @@ void ata_scsi_scan_host(struct ata_port *ap, int sync)
sdev = __scsi_add_device(ap->scsi_host, channel, id, 0,
NULL);
- if (!IS_ERR(sdev)) {
- dev->sdev[0] = sdev;
- ata_scsi_assign_ofnode(dev, ap);
- scsi_device_put(sdev);
- } else {
+ if (IS_ERR(sdev)) {
dev->sdev[0] = NULL;
+ continue;
}
+
+ /*
+ * For multi-LUN ATAPI (BLIST_FORCELUN), trigger a
+ * sequential scan for this target. pdt_1f_for_no_lun,
+ * set during LUN 0 configure, ensures non-responding
+ * LUNs are silently skipped; dev->sdev[] is populated
+ * by ata_scsi_dev_config() during the scan.
+ */
+ if (dev->class == ATA_DEV_ATAPI &&
+ sdev->sdev_bflags & BLIST_FORCELUN &&
+ !WARN_ON_ONCE(ap->scsi_host->max_lun > ATAPI_MAX_LUN))
+ scsi_scan_target(&ap->scsi_host->shost_gendev,
+ channel, id, SCAN_WILD_CARD,
+ SCSI_SCAN_RESCAN);
+ if (dev->sdev[0])
+ ata_scsi_assign_ofnode(dev, ap);
+ scsi_device_put(sdev);
}
}
--
2.43.0