public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH v3 0/7] ata: libata-scsi: multi-LUN ATAPI device support
@ 2026-04-26 19:09 Phil Pemberton
  2026-04-26 19:09 ` [PATCH v3 1/7] ata: libata-scsi: add atapi_max_lun module parameter Phil Pemberton
                   ` (6 more replies)
  0 siblings, 7 replies; 21+ messages in thread
From: Phil Pemberton @ 2026-04-26 19:09 UTC (permalink / raw)
  To: linux-ide, linux-scsi
  Cc: linux-kernel, Damien Le Moal, Niklas Cassel,
	James E . J . Bottomley, Martin K . Petersen, Hannes Reinecke,
	Phil Pemberton

Hi all,

This is v3, addressing review feedback from Hannes Reinecke on v2.

This series gives libata support for ATAPI devices with multiple LUNs,
such as the Panasonic PD-1 PD/CD combo drive. This exposes both the
CD-ROM and rewritable PD optical interfaces: CD-ROM as LUN 0 and PD
as LUN 1.

libata has never supported multi-LUN ATAPI. This series adds support
by fixing the following limitations:

  1. shost->max_lun is hardcoded to 1 in ata_scsi_add_hosts(), preventing
     the SCSI layer from probing any LUN beyond 0.

  2. __ata_scsi_find_dev() rejects all commands where scsidev->lun != 0,
     returning NULL and resulting in DID_BAD_TARGET.

  3. The SCSI-2 CDB LUN field (byte 1, bits 7:5) is never populated.
     ATAPI tunnels SCSI commands over the ATA PACKET interface, and the
     transport-layer LUN addressing used by SPC-3+ is not available.
     Older multi-LUN ATAPI devices rely on this CDB field to route
     commands to the correct LUN.

  4. ata_scsi_scan_host() only calls __scsi_add_device() for LUN 0,
     never probing additional LUNs even when the SCSI device info table
     would indicate the device supports them.

  5. dev->sdev is a single pointer, but multi-LUN ATAPI puts multiple
     sdevs behind one ata_device.  Every call to ata_scsi_dev_config()
     overwrote the pointer, and ata_scsi_sdev_destroy() tore down the
     entire ATA device whenever any sdev was destroyed -- so removing a
     spurious LUN result during scanning would kill the whole port, and
     the other users of dev->sdev (scsi_remove_device in
     ata_port_detach(), ACPI uevents, zpodd, media-change notify,
     suspend/resume rescan) could only ever see one LUN.

Changes from v2:

  - pdt_1f_for_no_lun is no longer set unconditionally for every ATAPI
    target.  Hannes suggested making this opt-in via the SCSI device
    info table, so a new BLIST_NO_LUN_1F flag has been added to
    scsi_devinfo.h, wired in scsi_scan.c, and applied to the COMPAQ
    PD-1 entry.  Targets that legitimately use PDT 0x1f / PQ 0 for
    "LUN not present" can now opt in without affecting other ATAPI
    devices.  This adds two new patches (4/7 and the updated 6/7).

  - Dropped the one-shot dmesg hint that pointed users at
    libata.atapi_max_lun when a BLIST_FORCELUN device was detected.
    Hannes felt the kernel should not be advertising its own knobs;
    the parameter is documented in the relevant patch and that's the
    expected place for users to discover it.

  - atapi_xlat() now rejects scmd->device->lun >= 8 with
    AC_ERR_INVALID instead of silently truncating.  The SCSI-2 CDB
    LUN field is only 3 bits wide, so a request to a LUN outside that
    range is unrepresentable on the wire and must fail.

  - Patches 1/7 and 2/7 carry Hannes' Reviewed-by tags from v2.

  - Added an optional 7/7 that extends BLIST_NO_LUN_1F to the MATSHITA
    and NEC OEM-branded PD-1 variants.  See note below.

The series is split as:

  1/7: libata-scsi: add libata.atapi_max_lun module parameter.

  2/7: libata-scsi: convert dev->sdev to a per-LUN array and update
       every caller.

  3/7: libata-scsi: relax __ata_scsi_find_dev() to accept non-zero LUN
       for ATAPI devices, and encode the LUN in CDB byte 1 bits 7:5.
       Reject LUN >= 8 with AC_ERR_INVALID.

  4/7: scsi: add a BLIST_NO_LUN_1F blacklist flag, which sets
       scsi_target.pdt_1f_for_no_lun for matching devices so that
       PDT 0x1f / PQ 0 INQUIRY responses are treated as "LUN not
       present" and silently skipped.

  5/7: libata-scsi: after adding LUN 0, trigger scsi_scan_target() for
       BLIST_FORCELUN ATAPI devices only.  Single-LUN devices are
       completely unaffected.

  6/7: scsi_devinfo: add the COMPAQ-branded variant of the PD-1 to the
       device info table with BLIST_FORCELUN | BLIST_SINGLELUN |
       BLIST_NO_LUN_1F.  An entry already exists for the Panasonic
       OEM-branded "MATSHITA PD-1" and the NEC "NEC PD-1 ODX654P".

  7/7: scsi_devinfo: extend BLIST_NO_LUN_1F to the MATSHITA and NEC
       PD-1 variants for completeness.  This patch is *optional* --
       it has not been tested on those OEM units (the author only has
       a COMPAQ unit), but the three variants are the same Panasonic
       LF-1095/LF-1195 mechanism with the same firmware family, so
       the quirk is expected to apply equally.  The flag is a no-op
       on devices that do not return PDT 0x1f / PQ 0 for non-existent
       LUNs, so the worst case is that it has no effect.  Drop or
       hold this patch if confirmation on real MATSHITA / NEC
       hardware is preferred first.

Tested on a Panasonic LF-1195C PD/CD (Compaq branded) attached to an
ata_piix host on i686, kernel 7.0.0-rc7+, with libata.atapi_max_lun=7.
Both LUNs enumerate correctly: the CD-ROM as sr0 and the PD as sda.
Reads from each device succeed against the appropriate media.
Non-responding LUNs are silently skipped (no spurious "No Device"
entries in dmesg).  An iHAS124 DVD writer on the same machine
(single-LUN, no BLIST_FORCELUN entry) is unaffected: only LUN 0 is
scanned.

If the iHAS124 is scanned regardless, it seems to ignore the LUN
parameter, and enumerates as eight drives. I expect most standard ATAPI
devices would behave this way, hence the BLIST_FORCELUN gate.

Two known limitations around media-change detection on multi-LUN
ATAPI devices with a shared physical media slot (e.g. PD/CD combos
flagged BLIST_SINGLELUN):

1. The block layer disables in-kernel polling by default
   (block.events_dfl_poll_msecs defaults to 0).  Without polling,
   sd_check_events never runs and media insertion on the PD LUN is
   not detected automatically.  sr_mod is unaffected because it
   re-reads the TOC on every open.

   Workaround -- either globally via kernel boot parameter:

       block.events_dfl_poll_msecs=2000

   or per-device via udev rule:

       ACTION=="add", KERNEL=="sd*", \
         ATTRS{vendor}=="COMPAQ  ", ATTRS{model}=="PD-1*", \
         ATTR{events_poll_msecs}="2000"

   Even with polling enabled the sd path does not always pick up
   fresh media; `blockdev --rereadpt /dev/sdX` reliably forces a
   revalidate and proves the libata routing itself is correct.

   A follow-up patch could add a BLIST flag (e.g. BLIST_POLL_EVENTS)
   to scsi_devinfo and have sd_probe_async() set the per-disk poll
   interval when the flag is present.  This would be a separate
   submission to the SCSI list since it touches sd.c.

2. Media-change sense is not propagated across sibling LUNs.  When
   one LUN reports UNIT ATTENTION (ASC 0x28 or 0x3A), the other LUNs
   are not notified.  With polling enabled, sd_check_events detects
   the change independently on each LUN via TUR, so this is mainly a
   latency issue rather than a functional one.  A follow-up to
   propagate media-change events to sibling LUNs in
   atapi_qc_complete is straightforward but deferred to keep this
   series focused on the LUN-scanning core.

Suspend/resume with multi-LUN ATAPI attached has not yet been tested;
this is on the list.  ata_scsi_dev_rescan iterates all populated LUN
slots, and the SCSI layer's host-level suspend tracking already
serialises port quiesce, so no additional per-LUN suspend counting is
needed in libata.

Comments and suggestions welcome.

Phil Pemberton (7):
  ata: libata-scsi: add atapi_max_lun module parameter
  ata: libata-scsi: convert dev->sdev to per-LUN array
  ata: libata-scsi: route non-zero LUN commands for multi-LUN ATAPI
  scsi: add BLIST_NO_LUN_1F blacklist flag
  ata: libata-scsi: probe additional LUNs for multi-LUN ATAPI devices
  scsi: scsi_devinfo: add COMPAQ PD-1 multi-LUN ATAPI device quirk
  scsi: scsi_devinfo: extend BLIST_NO_LUN_1F to MATSHITA and NEC PD-1
    variants

 drivers/ata/libata-acpi.c   |   4 +-
 drivers/ata/libata-core.c   |  15 ++-
 drivers/ata/libata-scsi.c   | 198 +++++++++++++++++++++---------------
 drivers/ata/libata-zpodd.c  |   6 +-
 drivers/ata/libata.h        |   1 +
 drivers/scsi/scsi_devinfo.c |   8 +-
 drivers/scsi/scsi_scan.c    |   3 +
 include/linux/libata.h      |   3 +-
 include/scsi/scsi_devinfo.h |   6 +-
 9 files changed, 147 insertions(+), 97 deletions(-)

-- 
2.43.0


^ permalink raw reply	[flat|nested] 21+ messages in thread

* [PATCH v3 1/7] ata: libata-scsi: add atapi_max_lun module parameter
  2026-04-26 19:09 [PATCH v3 0/7] ata: libata-scsi: multi-LUN ATAPI device support Phil Pemberton
@ 2026-04-26 19:09 ` Phil Pemberton
  2026-04-26 23:14   ` Damien Le Moal
  2026-04-26 19:09 ` [PATCH v3 2/7] ata: libata-scsi: convert dev->sdev to per-LUN array Phil Pemberton
                   ` (5 subsequent siblings)
  6 siblings, 1 reply; 21+ messages in thread
From: Phil Pemberton @ 2026-04-26 19:09 UTC (permalink / raw)
  To: linux-ide, linux-scsi
  Cc: linux-kernel, Damien Le Moal, Niklas Cassel,
	James E . J . Bottomley, Martin K . Petersen, Hannes Reinecke,
	Phil Pemberton

Until now libata has hard-coded shost->max_lun = 1 for every ATA host,
so the SCSI layer never scans past LUN 0.  This blocks support for
the small handful of multi-LUN ATAPI devices (Panasonic LF-1195C and
COMPAQ PD-1 PD/CD combos export CD on LUN 0 and PD on LUN 1; old
Nakamichi MJ-x.y CD changers expose one LUN per disc slot, up to 7).

Introduce a libata module parameter, atapi_max_lun, that controls the
upper bound of the per-host SCSI LUN scan.  Default is 1, preserving
current behaviour exactly: out-of-the-box only LUN 0 is scanned.
Range is clamped to 1..ATAPI_MAX_LUN (8, the SCSI-2 ceiling).

Subsequent patches gate actual LUN>0 probing on BLIST_FORCELUN, so a
device must both be on the SCSI device list (or carry the appropriate
quirk) and run on a host whose atapi_max_lun has been raised before
any extra LUNs are scanned.

Reviewed-by: Hannes Reinecke <hare@suse.de>
Signed-off-by: Phil Pemberton <philpem@philpem.me.uk>
---
 drivers/ata/libata-core.c | 5 +++++
 drivers/ata/libata-scsi.c | 2 +-
 drivers/ata/libata.h      | 1 +
 include/linux/libata.h    | 1 +
 4 files changed, 8 insertions(+), 1 deletion(-)

diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index 374993031895..8c279b6eb1fb 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -122,6 +122,11 @@ int atapi_passthru16 = 1;
 module_param(atapi_passthru16, int, 0444);
 MODULE_PARM_DESC(atapi_passthru16, "Enable ATA_16 passthru for ATAPI devices (0=off, 1=on [default])");
 
+int atapi_max_lun = 1;
+module_param(atapi_max_lun, int, 0444);
+MODULE_PARM_DESC(atapi_max_lun,
+	"Maximum LUN to scan on ATAPI devices flagged BLIST_FORCELUN (1 [default] .. 7)");
+
 int libata_fua = 0;
 module_param_named(fua, libata_fua, int, 0444);
 MODULE_PARM_DESC(fua, "FUA support (0=off [default], 1=on)");
diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
index 3b65df914ebb..d1665305b552 100644
--- a/drivers/ata/libata-scsi.c
+++ b/drivers/ata/libata-scsi.c
@@ -4620,7 +4620,7 @@ int ata_scsi_add_hosts(struct ata_host *host, const struct scsi_host_template *s
 		shost->transportt = ata_scsi_transport_template;
 		shost->unique_id = ap->print_id;
 		shost->max_id = 16;
-		shost->max_lun = 1;
+		shost->max_lun = clamp(atapi_max_lun, 1, ATAPI_MAX_LUN);
 		shost->max_channel = 1;
 		shost->max_cmd_len = 32;
 
diff --git a/drivers/ata/libata.h b/drivers/ata/libata.h
index b5423b6e97de..96d804d02b99 100644
--- a/drivers/ata/libata.h
+++ b/drivers/ata/libata.h
@@ -33,6 +33,7 @@ enum {
 #define ATA_PORT_TYPE_NAME	"ata_port"
 
 extern int atapi_passthru16;
+extern int atapi_max_lun;
 extern int libata_fua;
 extern int libata_noacpi;
 extern int libata_allow_tpm;
diff --git a/include/linux/libata.h b/include/linux/libata.h
index 00346ce3af5e..27b11577826e 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -131,6 +131,7 @@ enum {
 	ATA_SHORT_PAUSE		= 16,
 
 	ATAPI_MAX_DRAIN		= 16 << 10,
+	ATAPI_MAX_LUN		= 8,	/* SCSI-2 cap (LUN values 0..7) */
 
 	ATA_ALL_DEVICES		= (1 << ATA_MAX_DEVICES) - 1,
 
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH v3 2/7] ata: libata-scsi: convert dev->sdev to per-LUN array
  2026-04-26 19:09 [PATCH v3 0/7] ata: libata-scsi: multi-LUN ATAPI device support Phil Pemberton
  2026-04-26 19:09 ` [PATCH v3 1/7] ata: libata-scsi: add atapi_max_lun module parameter Phil Pemberton
@ 2026-04-26 19:09 ` Phil Pemberton
  2026-04-26 23:25   ` Damien Le Moal
  2026-04-26 19:09 ` [PATCH v3 3/7] ata: libata-scsi: route non-zero LUN commands for multi-LUN ATAPI Phil Pemberton
                   ` (4 subsequent siblings)
  6 siblings, 1 reply; 21+ messages in thread
From: Phil Pemberton @ 2026-04-26 19:09 UTC (permalink / raw)
  To: linux-ide, linux-scsi
  Cc: linux-kernel, Damien Le Moal, Niklas Cassel,
	James E . J . Bottomley, Martin K . Petersen, Hannes Reinecke,
	Phil Pemberton

Multi-LUN ATAPI devices (PD/CD combos, CD changers) share a single
ata_device but expose multiple scsi_devices.  The previous single
dev->sdev pointer could only track one LUN, making all other LUNs
invisible to code that operates on sdevs: port detach, suspend/resume,
ACPI uevent, ZPODD, media change notification, and EH teardown.

Replace the scalar struct scsi_device *sdev with a fixed-size array
dev->sdev[ATAPI_MAX_LUN] indexed by LUN number, where ATAPI_MAX_LUN
is 8 (the SCSI-2 ceiling, LUN values 0..7).

Key changes per call site:
  - ata_scsi_dev_config:  assign sdev to dev->sdev[sdev->lun]
  - ata_scsi_sdev_destroy: clear dev->sdev[sdev->lun]; only trigger
    ATA-level detach when LUN 0 is destroyed, since removing a higher
    LUN should not tear down the underlying ATA device
  - ata_port_detach:  iterate all LUN slots (high→low)
  - ata_scsi_offline_dev:  iterate all LUN slots
  - ata_scsi_remove_dev:  snapshot and remove all LUN slots, then
    scsi_remove_device each one outside the lock
  - ata_scsi_media_change_notify:  send event to all populated LUNs
  - ata_scsi_dev_rescan:  resume and rescan each populated LUN
  - ACPI, ZPODD, ofnode, door-lock:  use dev->sdev[0] (LUN 0 remains
    canonical for ATA-level operations)
  - ata_scsi_scan_host:  uses dev->sdev[0] for the existing LUN-0
    add/retry path

For single-LUN devices (the vast majority), only dev->sdev[0] is ever
populated and the additional slots remain NULL.

Reviewed-by: Hannes Reinecke <hare@suse.de>
Signed-off-by: Phil Pemberton <philpem@philpem.me.uk>
---
 drivers/ata/libata-acpi.c  |   4 +-
 drivers/ata/libata-core.c  |  10 ++-
 drivers/ata/libata-scsi.c  | 146 ++++++++++++++++++-------------------
 drivers/ata/libata-zpodd.c |   6 +-
 include/linux/libata.h     |   2 +-
 5 files changed, 86 insertions(+), 82 deletions(-)

diff --git a/drivers/ata/libata-acpi.c b/drivers/ata/libata-acpi.c
index 4433f626246b..d07237f66d98 100644
--- a/drivers/ata/libata-acpi.c
+++ b/drivers/ata/libata-acpi.c
@@ -153,8 +153,8 @@ static void ata_acpi_uevent(struct ata_port *ap, struct ata_device *dev,
 	char *envp[] = { event_string, NULL };
 
 	if (dev) {
-		if (dev->sdev)
-			kobj = &dev->sdev->sdev_gendev.kobj;
+		if (dev->sdev[0])
+			kobj = &dev->sdev[0]->sdev_gendev.kobj;
 	} else
 		kobj = &ap->dev->kobj;
 
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index 8c279b6eb1fb..f24d38f6ee73 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -6270,11 +6270,15 @@ static void ata_port_detach(struct ata_port *ap)
 	/* Remove scsi devices */
 	ata_for_each_link(link, ap, HOST_FIRST) {
 		ata_for_each_dev(dev, link, ALL) {
-			if (dev->sdev) {
+			int lun;
+
+			for (lun = ATAPI_MAX_LUN - 1; lun >= 0; lun--) {
+				if (!dev->sdev[lun])
+					continue;
 				spin_unlock_irqrestore(ap->lock, flags);
-				scsi_remove_device(dev->sdev);
+				scsi_remove_device(dev->sdev[lun]);
 				spin_lock_irqsave(ap->lock, flags);
-				dev->sdev = NULL;
+				dev->sdev[lun] = NULL;
 			}
 		}
 	}
diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
index d1665305b552..317883bac25f 100644
--- a/drivers/ata/libata-scsi.c
+++ b/drivers/ata/libata-scsi.c
@@ -1131,7 +1131,7 @@ int ata_scsi_dev_config(struct scsi_device *sdev, struct queue_limits *lim,
 	if (dev->flags & ATA_DFLAG_TRUSTED)
 		sdev->security_supported = 1;
 
-	dev->sdev = sdev;
+	dev->sdev[sdev->lun] = sdev;
 	return 0;
 }
 
@@ -1202,10 +1202,10 @@ EXPORT_SYMBOL_GPL(ata_scsi_sdev_configure);
  *
  *	@sdev is about to be destroyed for hot/warm unplugging.  If
  *	this unplugging was initiated by libata as indicated by NULL
- *	dev->sdev, this function doesn't have to do anything.
+ *	dev->sdev[], this function doesn't have to do anything.
  *	Otherwise, SCSI layer initiated warm-unplug is in progress.
- *	Clear dev->sdev, schedule the device for ATA detach and invoke
- *	EH.
+ *	Clear the per-LUN slot; when the last LUN (LUN 0) is destroyed,
+ *	schedule ATA-level detach via EH.
  *
  *	LOCKING:
  *	Defined by SCSI layer.  We don't really care.
@@ -1220,11 +1220,12 @@ void ata_scsi_sdev_destroy(struct scsi_device *sdev)
 
 	spin_lock_irqsave(ap->lock, flags);
 	dev = __ata_scsi_find_dev(ap, sdev);
-	if (dev && dev->sdev) {
-		/* SCSI device already in CANCEL state, no need to offline it */
-		dev->sdev = NULL;
-		dev->flags |= ATA_DFLAG_DETACH;
-		ata_port_schedule_eh(ap);
+	if (dev && dev->sdev[sdev->lun] == sdev) {
+		dev->sdev[sdev->lun] = NULL;
+		if (sdev->lun == 0) {
+			dev->flags |= ATA_DFLAG_DETACH;
+			ata_port_schedule_eh(ap);
+		}
 	}
 	spin_unlock_irqrestore(ap->lock, flags);
 
@@ -2912,10 +2913,10 @@ static void atapi_qc_complete(struct ata_queued_cmd *qc)
 		 * avoid this infinite loop.
 		 *
 		 * This may happen before SCSI scan is complete.  Make
-		 * sure qc->dev->sdev isn't NULL before dereferencing.
+		 * sure qc->dev->sdev[0] isn't NULL before dereferencing.
 		 */
-		if (qc->cdb[0] == ALLOW_MEDIUM_REMOVAL && qc->dev->sdev)
-			qc->dev->sdev->locked = 0;
+		if (qc->cdb[0] == ALLOW_MEDIUM_REMOVAL && qc->dev->sdev[0])
+			qc->dev->sdev[0]->locked = 0;
 
 		qc->scsicmd->result = SAM_STAT_CHECK_CONDITION;
 		ata_qc_done(qc);
@@ -4651,7 +4652,7 @@ int ata_scsi_add_hosts(struct ata_host *host, const struct scsi_host_template *s
 #ifdef CONFIG_OF
 static void ata_scsi_assign_ofnode(struct ata_device *dev, struct ata_port *ap)
 {
-	struct scsi_device *sdev = dev->sdev;
+	struct scsi_device *sdev = dev->sdev[0];
 	struct device *d = ap->host->dev;
 	struct device_node *np = d->of_node;
 	struct device_node *child;
@@ -4689,7 +4690,7 @@ void ata_scsi_scan_host(struct ata_port *ap, int sync)
 			struct scsi_device *sdev;
 			int channel = 0, id = 0;
 
-			if (dev->sdev)
+			if (dev->sdev[0])
 				continue;
 
 			if (ata_is_host_link(link))
@@ -4700,11 +4701,11 @@ 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 = sdev;
+				dev->sdev[0] = sdev;
 				ata_scsi_assign_ofnode(dev, ap);
 				scsi_device_put(sdev);
 			} else {
-				dev->sdev = NULL;
+				dev->sdev[0] = NULL;
 			}
 		}
 	}
@@ -4715,7 +4716,7 @@ void ata_scsi_scan_host(struct ata_port *ap, int sync)
 	 */
 	ata_for_each_link(link, ap, EDGE) {
 		ata_for_each_dev(dev, link, ENABLED) {
-			if (!dev->sdev)
+			if (!dev->sdev[0])
 				goto exit_loop;
 		}
 	}
@@ -4756,7 +4757,7 @@ void ata_scsi_scan_host(struct ata_port *ap, int sync)
  *
  *	This function is called from ata_eh_detach_dev() and is responsible for
  *	taking the SCSI device attached to @dev offline.  This function is
- *	called with host lock which protects dev->sdev against clearing.
+ *	called with host lock which protects dev->sdev[] against clearing.
  *
  *	LOCKING:
  *	spin_lock_irqsave(host lock)
@@ -4766,11 +4767,16 @@ void ata_scsi_scan_host(struct ata_port *ap, int sync)
  */
 bool ata_scsi_offline_dev(struct ata_device *dev)
 {
-	if (dev->sdev) {
-		scsi_device_set_state(dev->sdev, SDEV_OFFLINE);
-		return true;
+	bool found = false;
+	int lun;
+
+	for (lun = ATAPI_MAX_LUN - 1; lun >= 0; lun--) {
+		if (dev->sdev[lun]) {
+			scsi_device_set_state(dev->sdev[lun], SDEV_OFFLINE);
+			found = true;
+		}
 	}
-	return false;
+	return found;
 }
 
 /**
@@ -4786,49 +4792,38 @@ bool ata_scsi_offline_dev(struct ata_device *dev)
 static void ata_scsi_remove_dev(struct ata_device *dev)
 {
 	struct ata_port *ap = dev->link->ap;
-	struct scsi_device *sdev;
+	struct scsi_device *sdevs[ATAPI_MAX_LUN] = {};
 	unsigned long flags;
+	int lun;
 
-	/* Alas, we need to grab scan_mutex to ensure SCSI device
-	 * state doesn't change underneath us and thus
-	 * scsi_device_get() always succeeds.  The mutex locking can
-	 * be removed if there is __scsi_device_get() interface which
-	 * increments reference counts regardless of device state.
-	 */
 	mutex_lock(&ap->scsi_host->scan_mutex);
 	spin_lock_irqsave(ap->lock, flags);
 
-	/* clearing dev->sdev is protected by host lock */
-	sdev = dev->sdev;
-	dev->sdev = NULL;
+	for (lun = ATAPI_MAX_LUN - 1; lun >= 0; lun--) {
+		struct scsi_device *sdev = dev->sdev[lun];
+
+		dev->sdev[lun] = NULL;
+		if (!sdev)
+			continue;
 
-	if (sdev) {
-		/* If user initiated unplug races with us, sdev can go
-		 * away underneath us after the host lock and
-		 * scan_mutex are released.  Hold onto it.
-		 */
 		if (scsi_device_get(sdev) == 0) {
-			/* The following ensures the attached sdev is
-			 * offline on return from ata_scsi_offline_dev()
-			 * regardless it wins or loses the race
-			 * against this function.
-			 */
 			scsi_device_set_state(sdev, SDEV_OFFLINE);
+			sdevs[lun] = sdev;
 		} else {
 			WARN_ON(1);
-			sdev = NULL;
 		}
 	}
 
 	spin_unlock_irqrestore(ap->lock, flags);
 	mutex_unlock(&ap->scsi_host->scan_mutex);
 
-	if (sdev) {
+	for (lun = ATAPI_MAX_LUN - 1; lun >= 0; lun--) {
+		if (!sdevs[lun])
+			continue;
 		ata_dev_info(dev, "detaching (SCSI %s)\n",
-			     dev_name(&sdev->sdev_gendev));
-
-		scsi_remove_device(sdev);
-		scsi_device_put(sdev);
+			     dev_name(&sdevs[lun]->sdev_gendev));
+		scsi_remove_device(sdevs[lun]);
+		scsi_device_put(sdevs[lun]);
 	}
 }
 
@@ -4865,9 +4860,12 @@ static void ata_scsi_handle_link_detach(struct ata_link *link)
  */
 void ata_scsi_media_change_notify(struct ata_device *dev)
 {
-	if (dev->sdev)
-		sdev_evt_send_simple(dev->sdev, SDEV_EVT_MEDIA_CHANGE,
-				     GFP_ATOMIC);
+	int lun;
+
+	for (lun = 0; lun < ATAPI_MAX_LUN; lun++)
+		if (dev->sdev[lun])
+			sdev_evt_send_simple(dev->sdev[lun],
+					     SDEV_EVT_MEDIA_CHANGE, GFP_ATOMIC);
 }
 
 /**
@@ -5000,37 +4998,39 @@ void ata_scsi_dev_rescan(struct work_struct *work)
 
 	ata_for_each_link(link, ap, EDGE) {
 		ata_for_each_dev(dev, link, ENABLED) {
-			struct scsi_device *sdev = dev->sdev;
+			int lun;
 
-			/*
-			 * If the port was suspended before this was scheduled,
-			 * bail out.
-			 */
 			if (ap->pflags & ATA_PFLAG_SUSPENDED)
 				goto unlock_ap;
 
-			if (!sdev)
-				continue;
-			if (scsi_device_get(sdev))
-				continue;
-
 			do_resume = dev->flags & ATA_DFLAG_RESUMING;
 
-			spin_unlock_irqrestore(ap->lock, flags);
-			if (do_resume) {
-				ret = scsi_resume_device(sdev);
-				if (ret == -EWOULDBLOCK) {
-					scsi_device_put(sdev);
-					goto unlock_scan;
+			for (lun = 0; lun < ATAPI_MAX_LUN; lun++) {
+				struct scsi_device *sdev = dev->sdev[lun];
+
+				if (!sdev)
+					continue;
+				if (scsi_device_get(sdev))
+					continue;
+
+				spin_unlock_irqrestore(ap->lock, flags);
+				if (do_resume) {
+					ret = scsi_resume_device(sdev);
+					if (ret == -EWOULDBLOCK) {
+						scsi_device_put(sdev);
+						goto unlock_scan;
+					}
 				}
-				dev->flags &= ~ATA_DFLAG_RESUMING;
+				ret = scsi_rescan_device(sdev);
+				scsi_device_put(sdev);
+				spin_lock_irqsave(ap->lock, flags);
+
+				if (ret)
+					goto unlock_ap;
 			}
-			ret = scsi_rescan_device(sdev);
-			scsi_device_put(sdev);
-			spin_lock_irqsave(ap->lock, flags);
 
-			if (ret)
-				goto unlock_ap;
+			if (do_resume)
+				dev->flags &= ~ATA_DFLAG_RESUMING;
 		}
 	}
 
diff --git a/drivers/ata/libata-zpodd.c b/drivers/ata/libata-zpodd.c
index 414e7c63bd85..116dd42f8232 100644
--- a/drivers/ata/libata-zpodd.c
+++ b/drivers/ata/libata-zpodd.c
@@ -185,7 +185,7 @@ void zpodd_enable_run_wake(struct ata_device *dev)
 {
 	struct zpodd *zpodd = dev->zpodd;
 
-	sdev_disable_disk_events(dev->sdev);
+	sdev_disable_disk_events(dev->sdev[0]);
 
 	zpodd->powered_off = true;
 	acpi_pm_set_device_wakeup(&dev->tdev, true);
@@ -233,14 +233,14 @@ void zpodd_post_poweron(struct ata_device *dev)
 	zpodd->zp_sampled = false;
 	zpodd->zp_ready = false;
 
-	sdev_enable_disk_events(dev->sdev);
+	sdev_enable_disk_events(dev->sdev[0]);
 }
 
 static void zpodd_wake_dev(acpi_handle handle, u32 event, void *context)
 {
 	struct ata_device *ata_dev = context;
 	struct zpodd *zpodd = ata_dev->zpodd;
-	struct device *dev = &ata_dev->sdev->sdev_gendev;
+	struct device *dev = &ata_dev->sdev[0]->sdev_gendev;
 
 	if (event == ACPI_NOTIFY_DEVICE_WAKE && pm_runtime_suspended(dev)) {
 		zpodd->from_notify = true;
diff --git a/include/linux/libata.h b/include/linux/libata.h
index 27b11577826e..e2e759d492c7 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -722,7 +722,7 @@ struct ata_device {
 	unsigned int		devno;		/* 0 or 1 */
 	u64			quirks;		/* List of broken features */
 	unsigned long		flags;		/* ATA_DFLAG_xxx */
-	struct scsi_device	*sdev;		/* attached SCSI device */
+	struct scsi_device	*sdev[ATAPI_MAX_LUN];	/* per-LUN SCSI devices */
 	void			*private_data;
 #ifdef CONFIG_ATA_ACPI
 	union acpi_object	*gtf_cache;
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH v3 3/7] ata: libata-scsi: route non-zero LUN commands for multi-LUN ATAPI
  2026-04-26 19:09 [PATCH v3 0/7] ata: libata-scsi: multi-LUN ATAPI device support Phil Pemberton
  2026-04-26 19:09 ` [PATCH v3 1/7] ata: libata-scsi: add atapi_max_lun module parameter Phil Pemberton
  2026-04-26 19:09 ` [PATCH v3 2/7] ata: libata-scsi: convert dev->sdev to per-LUN array Phil Pemberton
@ 2026-04-26 19:09 ` Phil Pemberton
  2026-04-26 23:29   ` Damien Le Moal
  2026-04-27 11:53   ` Hannes Reinecke
  2026-04-26 19:09 ` [PATCH v3 4/7] scsi: add BLIST_NO_LUN_1F blacklist flag Phil Pemberton
                   ` (3 subsequent siblings)
  6 siblings, 2 replies; 21+ messages in thread
From: Phil Pemberton @ 2026-04-26 19:09 UTC (permalink / raw)
  To: linux-ide, linux-scsi
  Cc: linux-kernel, Damien Le Moal, Niklas Cassel,
	James E . J . Bottomley, Martin K . Petersen, Hannes Reinecke,
	Phil Pemberton

Two changes are required to route commands to ATAPI LUNs other than 0:

1. __ata_scsi_find_dev():  The existing code rejects any scsi_device
   with a non-zero LUN, returning NULL and dropping the command on
   the floor.  Relax both the PMP and non-PMP branches to allow
   non-zero LUNs through when the underlying ata_device is ATAPI
   class, since ATAPI devices can legitimately expose multiple LUNs.

2. atapi_xlat():  Older ATAPI devices (SCSI-2 era) expect the LUN in
   CDB byte 1 bits 7:5 rather than relying on transport-level LUN
   addressing.  Encode scmd->device->lun into those bits, preserving
   the existing command-specific bits in 4:0.  This is required by
   both the Panasonic PD/CD combos and Nakamichi CD changers.  LUNs
   beyond 7 cannot be encoded in the 3-bit CDB field; reject them
   with AC_ERR_INVALID.

Signed-off-by: Phil Pemberton <philpem@philpem.me.uk>
---
 drivers/ata/libata-scsi.c | 17 +++++++++++++++--
 1 file changed, 15 insertions(+), 2 deletions(-)

diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
index 317883bac25f..48c7d323d6f9 100644
--- a/drivers/ata/libata-scsi.c
+++ b/drivers/ata/libata-scsi.c
@@ -2951,6 +2951,11 @@ static unsigned int atapi_xlat(struct ata_queued_cmd *qc)
 	memset(qc->cdb, 0, dev->cdb_len);
 	memcpy(qc->cdb, scmd->cmnd, scmd->cmd_len);
 
+	/* SCSI-2 CDB LUN encoding: bits 7:5 of byte 1 (3-bit field) */
+	if (scmd->device->lun >= 8)
+		return AC_ERR_INVALID;
+	qc->cdb[1] = (qc->cdb[1] & 0x1f) | ((u8)scmd->device->lun << 5);
+
 	qc->complete_fn = atapi_qc_complete;
 
 	qc->tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
@@ -3059,19 +3064,27 @@ static struct ata_device *ata_find_dev(struct ata_port *ap, unsigned int devno)
 static struct ata_device *__ata_scsi_find_dev(struct ata_port *ap,
 					      const struct scsi_device *scsidev)
 {
+	struct ata_device *dev;
 	int devno;
 
 	/* skip commands not addressed to targets we simulate */
 	if (!sata_pmp_attached(ap)) {
-		if (unlikely(scsidev->channel || scsidev->lun))
+		if (unlikely(scsidev->channel))
 			return NULL;
 		devno = scsidev->id;
 	} else {
-		if (unlikely(scsidev->id || scsidev->lun))
+		if (unlikely(scsidev->id))
 			return NULL;
 		devno = scsidev->channel;
 	}
 
+	if (unlikely(scsidev->lun)) {
+		dev = ata_find_dev(ap, devno);
+		if (!dev || dev->class != ATA_DEV_ATAPI)
+			return NULL;
+		return dev;
+	}
+
 	return ata_find_dev(ap, devno);
 }
 
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH v3 4/7] scsi: add BLIST_NO_LUN_1F blacklist flag
  2026-04-26 19:09 [PATCH v3 0/7] ata: libata-scsi: multi-LUN ATAPI device support Phil Pemberton
                   ` (2 preceding siblings ...)
  2026-04-26 19:09 ` [PATCH v3 3/7] ata: libata-scsi: route non-zero LUN commands for multi-LUN ATAPI Phil Pemberton
@ 2026-04-26 19:09 ` Phil Pemberton
  2026-04-26 23:32   ` Damien Le Moal
  2026-04-27 11:54   ` Hannes Reinecke
  2026-04-26 19:09 ` [PATCH v3 5/7] ata: libata-scsi: probe additional LUNs for multi-LUN ATAPI devices Phil Pemberton
                   ` (2 subsequent siblings)
  6 siblings, 2 replies; 21+ messages in thread
From: Phil Pemberton @ 2026-04-26 19:09 UTC (permalink / raw)
  To: linux-ide, linux-scsi
  Cc: linux-kernel, Damien Le Moal, Niklas Cassel,
	James E . J . Bottomley, Martin K . Petersen, Hannes Reinecke,
	Phil Pemberton

Some multi-LUN devices respond to INQUIRY on unpopulated LUNs with
PQ=0 / PDT=0x1f instead of the standard PQ=3.  The SCSI scan layer
normally adds such devices (PQ=0 means "connected"), producing
spurious "No Device" entries.

The scsi_target field pdt_1f_for_no_lun already exists to suppress
this, but was previously only set by the USB UFI driver.

Add BLIST_NO_LUN_1F so the flag can be set per-device from
scsi_devinfo, and wire it up in scsi_add_lun() to set
starget->pdt_1f_for_no_lun from the blacklist flags.  This runs
during LUN 0 processing, before the sequential LUN scan probes
higher LUNs.

Signed-off-by: Phil Pemberton <philpem@philpem.me.uk>
---
 drivers/scsi/scsi_scan.c    | 3 +++
 include/scsi/scsi_devinfo.h | 6 +++---
 2 files changed, 6 insertions(+), 3 deletions(-)

diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
index 7b11bc7de0e3..d3f0540d79a2 100644
--- a/drivers/scsi/scsi_scan.c
+++ b/drivers/scsi/scsi_scan.c
@@ -1070,6 +1070,9 @@ static int scsi_add_lun(struct scsi_device *sdev, unsigned char *inq_result,
 
 	sdev->sdev_bflags = *bflags;
 
+	if (*bflags & BLIST_NO_LUN_1F)
+		sdev->sdev_target->pdt_1f_for_no_lun = 1;
+
 	if (scsi_device_is_pseudo_dev(sdev))
 		return SCSI_SCAN_LUN_PRESENT;
 
diff --git a/include/scsi/scsi_devinfo.h b/include/scsi/scsi_devinfo.h
index 1d79a3b536ce..6957b0705510 100644
--- a/include/scsi/scsi_devinfo.h
+++ b/include/scsi/scsi_devinfo.h
@@ -34,7 +34,8 @@
 #define BLIST_NOSTARTONADD	((__force blist_flags_t)(1ULL << 12))
 /* do not ask for VPD page size first on some broken targets */
 #define BLIST_NO_VPD_SIZE	((__force blist_flags_t)(1ULL << 13))
-#define __BLIST_UNUSED_14	((__force blist_flags_t)(1ULL << 14))
+/* PDT 0x1f with PQ 0 means no LUN present (e.g. some ATAPI multi-LUN) */
+#define BLIST_NO_LUN_1F		((__force blist_flags_t)(1ULL << 14))
 #define __BLIST_UNUSED_15	((__force blist_flags_t)(1ULL << 15))
 #define __BLIST_UNUSED_16	((__force blist_flags_t)(1ULL << 16))
 /* try REPORT_LUNS even for SCSI-2 devs (if HBA supports more than 8 LUNs) */
@@ -77,8 +78,7 @@
 #define __BLIST_HIGH_UNUSED (~(__BLIST_LAST_USED | \
 			       (__force blist_flags_t) \
 			       ((__force __u64)__BLIST_LAST_USED - 1ULL)))
-#define __BLIST_UNUSED_MASK (__BLIST_UNUSED_14 | \
-			     __BLIST_UNUSED_15 | \
+#define __BLIST_UNUSED_MASK (__BLIST_UNUSED_15 | \
 			     __BLIST_UNUSED_16 | \
 			     __BLIST_UNUSED_24 | \
 			     __BLIST_UNUSED_27 | \
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH v3 5/7] ata: libata-scsi: probe additional LUNs for multi-LUN ATAPI devices
  2026-04-26 19:09 [PATCH v3 0/7] ata: libata-scsi: multi-LUN ATAPI device support Phil Pemberton
                   ` (3 preceding siblings ...)
  2026-04-26 19:09 ` [PATCH v3 4/7] scsi: add BLIST_NO_LUN_1F blacklist flag Phil Pemberton
@ 2026-04-26 19:09 ` Phil Pemberton
  2026-04-26 23:36   ` Damien Le Moal
  2026-04-26 19:09 ` [PATCH v3 6/7] scsi: scsi_devinfo: add COMPAQ PD-1 multi-LUN ATAPI device quirk Phil Pemberton
  2026-04-26 19:09 ` [PATCH v3 7/7] scsi: scsi_devinfo: extend BLIST_NO_LUN_1F to MATSHITA and NEC PD-1 variants Phil Pemberton
  6 siblings, 1 reply; 21+ messages in thread
From: Phil Pemberton @ 2026-04-26 19:09 UTC (permalink / raw)
  To: linux-ide, linux-scsi
  Cc: linux-kernel, Damien Le Moal, Niklas Cassel,
	James E . J . Bottomley, Martin K . Petersen, Hannes Reinecke,
	Phil Pemberton

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 atapi_max_lun module
parameter from patch 1/6.  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 (see patch 4/6).

Signed-off-by: Phil Pemberton <philpem@philpem.me.uk>
---
 drivers/ata/libata-scsi.c | 37 ++++++++++++++++++++++++++++---------
 1 file changed, 28 insertions(+), 9 deletions(-)

diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
index 48c7d323d6f9..fc719e3d7d60 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>
@@ -4700,7 +4701,6 @@ void ata_scsi_scan_host(struct ata_port *ap, int sync)
  repeat:
 	ata_for_each_link(link, ap, EDGE) {
 		ata_for_each_dev(dev, link, ENABLED) {
-			struct scsi_device *sdev;
 			int channel = 0, id = 0;
 
 			if (dev->sdev[0])
@@ -4711,15 +4711,34 @@ void ata_scsi_scan_host(struct ata_port *ap, int sync)
 			else
 				channel = link->pmp;
 
-			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 {
-				dev->sdev[0] = NULL;
+			{
+				struct scsi_device *sdev;
+
+				sdev = __scsi_add_device(ap->scsi_host,
+							 channel, id, 0, NULL);
+				if (!IS_ERR(sdev)) {
+					/*
+					 * For multi-LUN ATAPI (BLIST_FORCELUN),
+					 * trigger the sequential LUN scan.
+					 * 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 callbacks.
+					 */
+					if (dev->class == ATA_DEV_ATAPI &&
+					    sdev->sdev_bflags & BLIST_FORCELUN)
+						scsi_scan_target(
+							&ap->scsi_host->shost_gendev,
+							channel, id,
+							SCAN_WILD_CARD,
+							SCSI_SCAN_RESCAN);
+					scsi_device_put(sdev);
+				}
 			}
+
+			if (dev->sdev[0])
+				ata_scsi_assign_ofnode(dev, ap);
 		}
 	}
 
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH v3 6/7] scsi: scsi_devinfo: add COMPAQ PD-1 multi-LUN ATAPI device quirk
  2026-04-26 19:09 [PATCH v3 0/7] ata: libata-scsi: multi-LUN ATAPI device support Phil Pemberton
                   ` (4 preceding siblings ...)
  2026-04-26 19:09 ` [PATCH v3 5/7] ata: libata-scsi: probe additional LUNs for multi-LUN ATAPI devices Phil Pemberton
@ 2026-04-26 19:09 ` Phil Pemberton
  2026-04-26 23:37   ` Damien Le Moal
  2026-04-27 11:55   ` Hannes Reinecke
  2026-04-26 19:09 ` [PATCH v3 7/7] scsi: scsi_devinfo: extend BLIST_NO_LUN_1F to MATSHITA and NEC PD-1 variants Phil Pemberton
  6 siblings, 2 replies; 21+ messages in thread
From: Phil Pemberton @ 2026-04-26 19:09 UTC (permalink / raw)
  To: linux-ide, linux-scsi
  Cc: linux-kernel, Damien Le Moal, Niklas Cassel,
	James E . J . Bottomley, Martin K . Petersen, Hannes Reinecke,
	Phil Pemberton

The COMPAQ PD-1 (OEM Panasonic/Matsushita LF-1195C) is a PD/CD combo
drive that exposes two ATAPI LUNs: LUN 0 is a CD-ROM (TYPE_ROM),
LUN 1 is a 650 MB PD (TYPE_DISK).

Add it to the SCSI device list with:
  - BLIST_FORCELUN: tells the SCSI layer to scan past LUN 0
  - BLIST_SINGLELUN: serialises commands across the two LUNs, since
    the drive has a single transport and cannot handle concurrent
    operations on both
  - BLIST_NO_LUN_1F: the drive returns PQ=0/PDT=0x1f for unpopulated
    LUNs instead of PQ=3; this flag tells scsi_probe_and_add_lun()
    to silently skip them

The INQUIRY strings as reported by the device are:
  Vendor:  "COMPAQ  " (T10 format, space-padded)
  Product: "PD-1"

Signed-off-by: Phil Pemberton <philpem@philpem.me.uk>
---
 drivers/scsi/scsi_devinfo.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/scsi/scsi_devinfo.c b/drivers/scsi/scsi_devinfo.c
index 68a992494b12..bfc2cbd43897 100644
--- a/drivers/scsi/scsi_devinfo.c
+++ b/drivers/scsi/scsi_devinfo.c
@@ -150,6 +150,8 @@ static struct {
 	{"COMPAQ", "MSA1000", NULL, BLIST_SPARSELUN | BLIST_NOSTARTONADD},
 	{"COMPAQ", "MSA1000 VOLUME", NULL, BLIST_SPARSELUN | BLIST_NOSTARTONADD},
 	{"COMPAQ", "HSV110", NULL, BLIST_REPORTLUN2 | BLIST_NOSTARTONADD},
+	{"COMPAQ", "PD-1", NULL, BLIST_FORCELUN | BLIST_SINGLELUN |
+				 BLIST_NO_LUN_1F},
 	{"DDN", "SAN DataDirector", "*", BLIST_SPARSELUN},
 	{"DEC", "HSG80", NULL, BLIST_REPORTLUN2 | BLIST_NOSTARTONADD},
 	{"DELL", "PV660F", NULL, BLIST_SPARSELUN},
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH v3 7/7] scsi: scsi_devinfo: extend BLIST_NO_LUN_1F to MATSHITA and NEC PD-1 variants
  2026-04-26 19:09 [PATCH v3 0/7] ata: libata-scsi: multi-LUN ATAPI device support Phil Pemberton
                   ` (5 preceding siblings ...)
  2026-04-26 19:09 ` [PATCH v3 6/7] scsi: scsi_devinfo: add COMPAQ PD-1 multi-LUN ATAPI device quirk Phil Pemberton
@ 2026-04-26 19:09 ` Phil Pemberton
  2026-04-26 23:37   ` Damien Le Moal
  2026-04-27 11:56   ` Hannes Reinecke
  6 siblings, 2 replies; 21+ messages in thread
From: Phil Pemberton @ 2026-04-26 19:09 UTC (permalink / raw)
  To: linux-ide, linux-scsi
  Cc: linux-kernel, Damien Le Moal, Niklas Cassel,
	James E . J . Bottomley, Martin K . Petersen, Hannes Reinecke,
	Phil Pemberton

The Panasonic LF-1095/LF-1195 PD/CD combo drive was sold under three
OEM identities: COMPAQ "PD-1", MATSHITA "PD-1", and NEC "PD-1 ODX654P".
All three are the same drive mechanism with the same firmware family,
so they should share the BLIST_NO_LUN_1F quirk that was applied to the
COMPAQ variant: PDT 0x1f / PQ 0 INQUIRY responses on non-existent LUNs
are treated as "LUN not present" rather than as a phantom sdev.

This patch is offered for completeness.  It has not been tested on the
MATSHITA or NEC variants -- the author only has access to the COMPAQ
unit -- but the drives are functionally identical and the flag is a
no-op on devices that do not exhibit the PDT 0x1f response.  Drop or
hold this patch if confirmation on real hardware is preferred before
extending the quirk.

Signed-off-by: Phil Pemberton <philpem@philpem.me.uk>
---
 drivers/scsi/scsi_devinfo.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/drivers/scsi/scsi_devinfo.c b/drivers/scsi/scsi_devinfo.c
index bfc2cbd43897..ab1ffa9433b7 100644
--- a/drivers/scsi/scsi_devinfo.c
+++ b/drivers/scsi/scsi_devinfo.c
@@ -201,7 +201,8 @@ static struct {
 	{"LASOUND", "CDX7405", "3.10", BLIST_MAX5LUN | BLIST_SINGLELUN},
 	{"Marvell", "Console", NULL, BLIST_SKIP_VPD_PAGES},
 	{"Marvell", "91xx Config", "1.01", BLIST_SKIP_VPD_PAGES},
-	{"MATSHITA", "PD-1", NULL, BLIST_FORCELUN | BLIST_SINGLELUN},
+	{"MATSHITA", "PD-1", NULL, BLIST_FORCELUN | BLIST_SINGLELUN |
+				   BLIST_NO_LUN_1F},
 	{"MATSHITA", "DMC-LC5", NULL, BLIST_NOT_LOCKABLE | BLIST_INQUIRY_36},
 	{"MATSHITA", "DMC-LC40", NULL, BLIST_NOT_LOCKABLE | BLIST_INQUIRY_36},
 	{"Medion", "Flash XL  MMC/SD", "2.6D", BLIST_FORCELUN},
@@ -212,7 +213,8 @@ static struct {
 	{"nCipher", "Fastness Crypto", NULL, BLIST_FORCELUN},
 	{"NAKAMICH", "MJ-4.8S", NULL, BLIST_FORCELUN | BLIST_SINGLELUN},
 	{"NAKAMICH", "MJ-5.16S", NULL, BLIST_FORCELUN | BLIST_SINGLELUN},
-	{"NEC", "PD-1 ODX654P", NULL, BLIST_FORCELUN | BLIST_SINGLELUN},
+	{"NEC", "PD-1 ODX654P", NULL, BLIST_FORCELUN | BLIST_SINGLELUN |
+				      BLIST_NO_LUN_1F},
 	{"NEC", "iStorage", NULL, BLIST_REPORTLUN2},
 	{"NRC", "MBR-7", NULL, BLIST_FORCELUN | BLIST_SINGLELUN},
 	{"NRC", "MBR-7.4", NULL, BLIST_FORCELUN | BLIST_SINGLELUN},
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* Re: [PATCH v3 1/7] ata: libata-scsi: add atapi_max_lun module parameter
  2026-04-26 19:09 ` [PATCH v3 1/7] ata: libata-scsi: add atapi_max_lun module parameter Phil Pemberton
@ 2026-04-26 23:14   ` Damien Le Moal
  0 siblings, 0 replies; 21+ messages in thread
From: Damien Le Moal @ 2026-04-26 23:14 UTC (permalink / raw)
  To: Phil Pemberton, linux-ide, linux-scsi
  Cc: linux-kernel, Niklas Cassel, James E . J . Bottomley,
	Martin K . Petersen, Hannes Reinecke

On 4/27/26 4:09 AM, Phil Pemberton wrote:
> Until now libata has hard-coded shost->max_lun = 1 for every ATA host,
> so the SCSI layer never scans past LUN 0.  This blocks support for
> the small handful of multi-LUN ATAPI devices (Panasonic LF-1195C and
> COMPAQ PD-1 PD/CD combos export CD on LUN 0 and PD on LUN 1; old
> Nakamichi MJ-x.y CD changers expose one LUN per disc slot, up to 7).
> 
> Introduce a libata module parameter, atapi_max_lun, that controls the
> upper bound of the per-host SCSI LUN scan.  Default is 1, preserving
> current behaviour exactly: out-of-the-box only LUN 0 is scanned.
> Range is clamped to 1..ATAPI_MAX_LUN (8, the SCSI-2 ceiling).
> 
> Subsequent patches gate actual LUN>0 probing on BLIST_FORCELUN, so a
> device must both be on the SCSI device list (or carry the appropriate
> quirk) and run on a host whose atapi_max_lun has been raised before
> any extra LUNs are scanned.
> 
> Reviewed-by: Hannes Reinecke <hare@suse.de>
> Signed-off-by: Phil Pemberton <philpem@philpem.me.uk>

This looks OK to me, but I would prefer renaming things a little:

atapi_max_lun -> atapi_max_nr_luns

to avoid confusion between the maximum LUN ID and the maximum number of LUNs
(yeah, they are only off by one, but better be clear to not trip on that).

One additional nit below.

With that fixed, feel free to add:

Reviewed-by: Damien Le Moal <dlemoal@kernel.org>

> ---
>  drivers/ata/libata-core.c | 5 +++++
>  drivers/ata/libata-scsi.c | 2 +-
>  drivers/ata/libata.h      | 1 +
>  include/linux/libata.h    | 1 +
>  4 files changed, 8 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
> index 374993031895..8c279b6eb1fb 100644
> --- a/drivers/ata/libata-core.c
> +++ b/drivers/ata/libata-core.c
> @@ -122,6 +122,11 @@ int atapi_passthru16 = 1;
>  module_param(atapi_passthru16, int, 0444);
>  MODULE_PARM_DESC(atapi_passthru16, "Enable ATA_16 passthru for ATAPI devices (0=off, 1=on [default])");
>  
> +int atapi_max_lun = 1;
> +module_param(atapi_max_lun, int, 0444);
> +MODULE_PARM_DESC(atapi_max_lun,
> +	"Maximum LUN to scan on ATAPI devices flagged BLIST_FORCELUN (1 [default] .. 7)");

	"Maximum number of LUNs to scan on ATAPI devices flagged "
	"with BLIST_FORCELUN (1 [default] .. 7)");

> +
>  int libata_fua = 0;
>  module_param_named(fua, libata_fua, int, 0444);
>  MODULE_PARM_DESC(fua, "FUA support (0=off [default], 1=on)");
> diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
> index 3b65df914ebb..d1665305b552 100644
> --- a/drivers/ata/libata-scsi.c
> +++ b/drivers/ata/libata-scsi.c
> @@ -4620,7 +4620,7 @@ int ata_scsi_add_hosts(struct ata_host *host, const struct scsi_host_template *s
>  		shost->transportt = ata_scsi_transport_template;
>  		shost->unique_id = ap->print_id;
>  		shost->max_id = 16;
> -		shost->max_lun = 1;
> +		shost->max_lun = clamp(atapi_max_lun, 1, ATAPI_MAX_LUN);
>  		shost->max_channel = 1;
>  		shost->max_cmd_len = 32;
>  
> diff --git a/drivers/ata/libata.h b/drivers/ata/libata.h
> index b5423b6e97de..96d804d02b99 100644
> --- a/drivers/ata/libata.h
> +++ b/drivers/ata/libata.h
> @@ -33,6 +33,7 @@ enum {
>  #define ATA_PORT_TYPE_NAME	"ata_port"
>  
>  extern int atapi_passthru16;
> +extern int atapi_max_lun;
>  extern int libata_fua;
>  extern int libata_noacpi;
>  extern int libata_allow_tpm;
> diff --git a/include/linux/libata.h b/include/linux/libata.h
> index 00346ce3af5e..27b11577826e 100644
> --- a/include/linux/libata.h
> +++ b/include/linux/libata.h
> @@ -131,6 +131,7 @@ enum {
>  	ATA_SHORT_PAUSE		= 16,
>  
>  	ATAPI_MAX_DRAIN		= 16 << 10,
> +	ATAPI_MAX_LUN		= 8,	/* SCSI-2 cap (LUN values 0..7) */
>  
>  	ATA_ALL_DEVICES		= (1 << ATA_MAX_DEVICES) - 1,
>  


-- 
Damien Le Moal
Western Digital Research

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH v3 2/7] ata: libata-scsi: convert dev->sdev to per-LUN array
  2026-04-26 19:09 ` [PATCH v3 2/7] ata: libata-scsi: convert dev->sdev to per-LUN array Phil Pemberton
@ 2026-04-26 23:25   ` Damien Le Moal
  0 siblings, 0 replies; 21+ messages in thread
From: Damien Le Moal @ 2026-04-26 23:25 UTC (permalink / raw)
  To: Phil Pemberton, linux-ide, linux-scsi
  Cc: linux-kernel, Niklas Cassel, James E . J . Bottomley,
	Martin K . Petersen, Hannes Reinecke

On 4/27/26 4:09 AM, Phil Pemberton wrote:
> Multi-LUN ATAPI devices (PD/CD combos, CD changers) share a single
> ata_device but expose multiple scsi_devices.  The previous single
> dev->sdev pointer could only track one LUN, making all other LUNs
> invisible to code that operates on sdevs: port detach, suspend/resume,
> ACPI uevent, ZPODD, media change notification, and EH teardown.
> 
> Replace the scalar struct scsi_device *sdev with a fixed-size array
> dev->sdev[ATAPI_MAX_LUN] indexed by LUN number, where ATAPI_MAX_LUN
> is 8 (the SCSI-2 ceiling, LUN values 0..7).
> 
> Key changes per call site:
>   - ata_scsi_dev_config:  assign sdev to dev->sdev[sdev->lun]
>   - ata_scsi_sdev_destroy: clear dev->sdev[sdev->lun]; only trigger
>     ATA-level detach when LUN 0 is destroyed, since removing a higher
>     LUN should not tear down the underlying ATA device
>   - ata_port_detach:  iterate all LUN slots (high→low)
>   - ata_scsi_offline_dev:  iterate all LUN slots
>   - ata_scsi_remove_dev:  snapshot and remove all LUN slots, then
>     scsi_remove_device each one outside the lock
>   - ata_scsi_media_change_notify:  send event to all populated LUNs
>   - ata_scsi_dev_rescan:  resume and rescan each populated LUN
>   - ACPI, ZPODD, ofnode, door-lock:  use dev->sdev[0] (LUN 0 remains
>     canonical for ATA-level operations)
>   - ata_scsi_scan_host:  uses dev->sdev[0] for the existing LUN-0
>     add/retry path
> 
> For single-LUN devices (the vast majority), only dev->sdev[0] is ever
> populated and the additional slots remain NULL.

Exactly, and that is why I a not a big fan of this patch as is. The main reason
is that once we probe the device, we'll know how many LUNs it has, and in the
vast majority of cases, that will be 1. So I think that instead of having all
the loops looking at all possible LUNs with ATAPI_MAX_LUN as the upper
boundary, we need to add a dev->nr_luns field indicating the number of LUNs
that are valid for the device. Again, that will be 1 most of the time, and thus
will not add unnecessary overhead for looking at LUNs that do not exist.

The direct refereincing of dev->sdev[i] is also a little ugly. Having a little
inline helper like:

static inline struct scsi_device *
ata_dev_scsi_device(struct ata_device *dev, unsigned int lun)
{
	if (WARN_ON_ONCE(lun >= dev->nr_luns))
		return NULL;
	return dev->sdev[lun];
}

would make things cleaner.

> 
> Reviewed-by: Hannes Reinecke <hare@suse.de>
> Signed-off-by: Phil Pemberton <philpem@philpem.me.uk>
> ---
>  drivers/ata/libata-acpi.c  |   4 +-
>  drivers/ata/libata-core.c  |  10 ++-
>  drivers/ata/libata-scsi.c  | 146 ++++++++++++++++++-------------------
>  drivers/ata/libata-zpodd.c |   6 +-
>  include/linux/libata.h     |   2 +-
>  5 files changed, 86 insertions(+), 82 deletions(-)
> 
> diff --git a/drivers/ata/libata-acpi.c b/drivers/ata/libata-acpi.c
> index 4433f626246b..d07237f66d98 100644
> --- a/drivers/ata/libata-acpi.c
> +++ b/drivers/ata/libata-acpi.c
> @@ -153,8 +153,8 @@ static void ata_acpi_uevent(struct ata_port *ap, struct ata_device *dev,
>  	char *envp[] = { event_string, NULL };
>  
>  	if (dev) {
> -		if (dev->sdev)
> -			kobj = &dev->sdev->sdev_gendev.kobj;
> +		if (dev->sdev[0])
> +			kobj = &dev->sdev[0]->sdev_gendev.kobj;
>  	} else
>  		kobj = &ap->dev->kobj;
>  
> diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
> index 8c279b6eb1fb..f24d38f6ee73 100644
> --- a/drivers/ata/libata-core.c
> +++ b/drivers/ata/libata-core.c
> @@ -6270,11 +6270,15 @@ static void ata_port_detach(struct ata_port *ap)
>  	/* Remove scsi devices */
>  	ata_for_each_link(link, ap, HOST_FIRST) {
>  		ata_for_each_dev(dev, link, ALL) {
> -			if (dev->sdev) {
> +			int lun;
> +
> +			for (lun = ATAPI_MAX_LUN - 1; lun >= 0; lun--) {
> +				if (!dev->sdev[lun])
> +					continue;
>  				spin_unlock_irqrestore(ap->lock, flags);
> -				scsi_remove_device(dev->sdev);
> +				scsi_remove_device(dev->sdev[lun]);
>  				spin_lock_irqsave(ap->lock, flags);
> -				dev->sdev = NULL;
> +				dev->sdev[lun] = NULL;
>  			}
>  		}
>  	}
> diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
> index d1665305b552..317883bac25f 100644
> --- a/drivers/ata/libata-scsi.c
> +++ b/drivers/ata/libata-scsi.c
> @@ -1131,7 +1131,7 @@ int ata_scsi_dev_config(struct scsi_device *sdev, struct queue_limits *lim,
>  	if (dev->flags & ATA_DFLAG_TRUSTED)
>  		sdev->security_supported = 1;
>  
> -	dev->sdev = sdev;
> +	dev->sdev[sdev->lun] = sdev;
>  	return 0;
>  }
>  
> @@ -1202,10 +1202,10 @@ EXPORT_SYMBOL_GPL(ata_scsi_sdev_configure);
>   *
>   *	@sdev is about to be destroyed for hot/warm unplugging.  If
>   *	this unplugging was initiated by libata as indicated by NULL
> - *	dev->sdev, this function doesn't have to do anything.
> + *	dev->sdev[], this function doesn't have to do anything.
>   *	Otherwise, SCSI layer initiated warm-unplug is in progress.
> - *	Clear dev->sdev, schedule the device for ATA detach and invoke
> - *	EH.
> + *	Clear the per-LUN slot; when the last LUN (LUN 0) is destroyed,
> + *	schedule ATA-level detach via EH.
>   *
>   *	LOCKING:
>   *	Defined by SCSI layer.  We don't really care.
> @@ -1220,11 +1220,12 @@ void ata_scsi_sdev_destroy(struct scsi_device *sdev)
>  
>  	spin_lock_irqsave(ap->lock, flags);
>  	dev = __ata_scsi_find_dev(ap, sdev);
> -	if (dev && dev->sdev) {
> -		/* SCSI device already in CANCEL state, no need to offline it */
> -		dev->sdev = NULL;
> -		dev->flags |= ATA_DFLAG_DETACH;
> -		ata_port_schedule_eh(ap);
> +	if (dev && dev->sdev[sdev->lun] == sdev) {
> +		dev->sdev[sdev->lun] = NULL;
> +		if (sdev->lun == 0) {
> +			dev->flags |= ATA_DFLAG_DETACH;
> +			ata_port_schedule_eh(ap);
> +		}
>  	}
>  	spin_unlock_irqrestore(ap->lock, flags);
>  
> @@ -2912,10 +2913,10 @@ static void atapi_qc_complete(struct ata_queued_cmd *qc)
>  		 * avoid this infinite loop.
>  		 *
>  		 * This may happen before SCSI scan is complete.  Make
> -		 * sure qc->dev->sdev isn't NULL before dereferencing.
> +		 * sure qc->dev->sdev[0] isn't NULL before dereferencing.
>  		 */
> -		if (qc->cdb[0] == ALLOW_MEDIUM_REMOVAL && qc->dev->sdev)
> -			qc->dev->sdev->locked = 0;
> +		if (qc->cdb[0] == ALLOW_MEDIUM_REMOVAL && qc->dev->sdev[0])
> +			qc->dev->sdev[0]->locked = 0;
>  
>  		qc->scsicmd->result = SAM_STAT_CHECK_CONDITION;
>  		ata_qc_done(qc);
> @@ -4651,7 +4652,7 @@ int ata_scsi_add_hosts(struct ata_host *host, const struct scsi_host_template *s
>  #ifdef CONFIG_OF
>  static void ata_scsi_assign_ofnode(struct ata_device *dev, struct ata_port *ap)
>  {
> -	struct scsi_device *sdev = dev->sdev;
> +	struct scsi_device *sdev = dev->sdev[0];
>  	struct device *d = ap->host->dev;
>  	struct device_node *np = d->of_node;
>  	struct device_node *child;
> @@ -4689,7 +4690,7 @@ void ata_scsi_scan_host(struct ata_port *ap, int sync)
>  			struct scsi_device *sdev;
>  			int channel = 0, id = 0;
>  
> -			if (dev->sdev)
> +			if (dev->sdev[0])
>  				continue;
>  
>  			if (ata_is_host_link(link))
> @@ -4700,11 +4701,11 @@ 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 = sdev;
> +				dev->sdev[0] = sdev;
>  				ata_scsi_assign_ofnode(dev, ap);
>  				scsi_device_put(sdev);
>  			} else {
> -				dev->sdev = NULL;
> +				dev->sdev[0] = NULL;
>  			}
>  		}
>  	}
> @@ -4715,7 +4716,7 @@ void ata_scsi_scan_host(struct ata_port *ap, int sync)
>  	 */
>  	ata_for_each_link(link, ap, EDGE) {
>  		ata_for_each_dev(dev, link, ENABLED) {
> -			if (!dev->sdev)
> +			if (!dev->sdev[0])
>  				goto exit_loop;
>  		}
>  	}
> @@ -4756,7 +4757,7 @@ void ata_scsi_scan_host(struct ata_port *ap, int sync)
>   *
>   *	This function is called from ata_eh_detach_dev() and is responsible for
>   *	taking the SCSI device attached to @dev offline.  This function is
> - *	called with host lock which protects dev->sdev against clearing.
> + *	called with host lock which protects dev->sdev[] against clearing.
>   *
>   *	LOCKING:
>   *	spin_lock_irqsave(host lock)
> @@ -4766,11 +4767,16 @@ void ata_scsi_scan_host(struct ata_port *ap, int sync)
>   */
>  bool ata_scsi_offline_dev(struct ata_device *dev)
>  {
> -	if (dev->sdev) {
> -		scsi_device_set_state(dev->sdev, SDEV_OFFLINE);
> -		return true;
> +	bool found = false;
> +	int lun;
> +
> +	for (lun = ATAPI_MAX_LUN - 1; lun >= 0; lun--) {
> +		if (dev->sdev[lun]) {
> +			scsi_device_set_state(dev->sdev[lun], SDEV_OFFLINE);
> +			found = true;
> +		}
>  	}
> -	return false;
> +	return found;
>  }
>  
>  /**
> @@ -4786,49 +4792,38 @@ bool ata_scsi_offline_dev(struct ata_device *dev)
>  static void ata_scsi_remove_dev(struct ata_device *dev)
>  {
>  	struct ata_port *ap = dev->link->ap;
> -	struct scsi_device *sdev;
> +	struct scsi_device *sdevs[ATAPI_MAX_LUN] = {};
>  	unsigned long flags;
> +	int lun;
>  
> -	/* Alas, we need to grab scan_mutex to ensure SCSI device
> -	 * state doesn't change underneath us and thus
> -	 * scsi_device_get() always succeeds.  The mutex locking can
> -	 * be removed if there is __scsi_device_get() interface which
> -	 * increments reference counts regardless of device state.
> -	 */
>  	mutex_lock(&ap->scsi_host->scan_mutex);
>  	spin_lock_irqsave(ap->lock, flags);
>  
> -	/* clearing dev->sdev is protected by host lock */
> -	sdev = dev->sdev;
> -	dev->sdev = NULL;
> +	for (lun = ATAPI_MAX_LUN - 1; lun >= 0; lun--) {
> +		struct scsi_device *sdev = dev->sdev[lun];
> +
> +		dev->sdev[lun] = NULL;
> +		if (!sdev)
> +			continue;
>  
> -	if (sdev) {
> -		/* If user initiated unplug races with us, sdev can go
> -		 * away underneath us after the host lock and
> -		 * scan_mutex are released.  Hold onto it.
> -		 */
>  		if (scsi_device_get(sdev) == 0) {
> -			/* The following ensures the attached sdev is
> -			 * offline on return from ata_scsi_offline_dev()
> -			 * regardless it wins or loses the race
> -			 * against this function.
> -			 */
>  			scsi_device_set_state(sdev, SDEV_OFFLINE);
> +			sdevs[lun] = sdev;
>  		} else {
>  			WARN_ON(1);
> -			sdev = NULL;
>  		}
>  	}
>  
>  	spin_unlock_irqrestore(ap->lock, flags);
>  	mutex_unlock(&ap->scsi_host->scan_mutex);
>  
> -	if (sdev) {
> +	for (lun = ATAPI_MAX_LUN - 1; lun >= 0; lun--) {
> +		if (!sdevs[lun])
> +			continue;
>  		ata_dev_info(dev, "detaching (SCSI %s)\n",
> -			     dev_name(&sdev->sdev_gendev));
> -
> -		scsi_remove_device(sdev);
> -		scsi_device_put(sdev);
> +			     dev_name(&sdevs[lun]->sdev_gendev));
> +		scsi_remove_device(sdevs[lun]);
> +		scsi_device_put(sdevs[lun]);
>  	}
>  }
>  
> @@ -4865,9 +4860,12 @@ static void ata_scsi_handle_link_detach(struct ata_link *link)
>   */
>  void ata_scsi_media_change_notify(struct ata_device *dev)
>  {
> -	if (dev->sdev)
> -		sdev_evt_send_simple(dev->sdev, SDEV_EVT_MEDIA_CHANGE,
> -				     GFP_ATOMIC);
> +	int lun;
> +
> +	for (lun = 0; lun < ATAPI_MAX_LUN; lun++)
> +		if (dev->sdev[lun])
> +			sdev_evt_send_simple(dev->sdev[lun],
> +					     SDEV_EVT_MEDIA_CHANGE, GFP_ATOMIC);
>  }
>  
>  /**
> @@ -5000,37 +4998,39 @@ void ata_scsi_dev_rescan(struct work_struct *work)
>  
>  	ata_for_each_link(link, ap, EDGE) {
>  		ata_for_each_dev(dev, link, ENABLED) {
> -			struct scsi_device *sdev = dev->sdev;
> +			int lun;
>  
> -			/*
> -			 * If the port was suspended before this was scheduled,
> -			 * bail out.
> -			 */
>  			if (ap->pflags & ATA_PFLAG_SUSPENDED)
>  				goto unlock_ap;
>  
> -			if (!sdev)
> -				continue;
> -			if (scsi_device_get(sdev))
> -				continue;
> -
>  			do_resume = dev->flags & ATA_DFLAG_RESUMING;
>  
> -			spin_unlock_irqrestore(ap->lock, flags);
> -			if (do_resume) {
> -				ret = scsi_resume_device(sdev);
> -				if (ret == -EWOULDBLOCK) {
> -					scsi_device_put(sdev);
> -					goto unlock_scan;
> +			for (lun = 0; lun < ATAPI_MAX_LUN; lun++) {
> +				struct scsi_device *sdev = dev->sdev[lun];
> +
> +				if (!sdev)
> +					continue;
> +				if (scsi_device_get(sdev))
> +					continue;
> +
> +				spin_unlock_irqrestore(ap->lock, flags);
> +				if (do_resume) {
> +					ret = scsi_resume_device(sdev);
> +					if (ret == -EWOULDBLOCK) {
> +						scsi_device_put(sdev);
> +						goto unlock_scan;
> +					}
>  				}
> -				dev->flags &= ~ATA_DFLAG_RESUMING;
> +				ret = scsi_rescan_device(sdev);
> +				scsi_device_put(sdev);
> +				spin_lock_irqsave(ap->lock, flags);
> +
> +				if (ret)
> +					goto unlock_ap;
>  			}
> -			ret = scsi_rescan_device(sdev);
> -			scsi_device_put(sdev);
> -			spin_lock_irqsave(ap->lock, flags);
>  
> -			if (ret)
> -				goto unlock_ap;
> +			if (do_resume)
> +				dev->flags &= ~ATA_DFLAG_RESUMING;
>  		}
>  	}
>  
> diff --git a/drivers/ata/libata-zpodd.c b/drivers/ata/libata-zpodd.c
> index 414e7c63bd85..116dd42f8232 100644
> --- a/drivers/ata/libata-zpodd.c
> +++ b/drivers/ata/libata-zpodd.c
> @@ -185,7 +185,7 @@ void zpodd_enable_run_wake(struct ata_device *dev)
>  {
>  	struct zpodd *zpodd = dev->zpodd;
>  
> -	sdev_disable_disk_events(dev->sdev);
> +	sdev_disable_disk_events(dev->sdev[0]);
>  
>  	zpodd->powered_off = true;
>  	acpi_pm_set_device_wakeup(&dev->tdev, true);
> @@ -233,14 +233,14 @@ void zpodd_post_poweron(struct ata_device *dev)
>  	zpodd->zp_sampled = false;
>  	zpodd->zp_ready = false;
>  
> -	sdev_enable_disk_events(dev->sdev);
> +	sdev_enable_disk_events(dev->sdev[0]);
>  }
>  
>  static void zpodd_wake_dev(acpi_handle handle, u32 event, void *context)
>  {
>  	struct ata_device *ata_dev = context;
>  	struct zpodd *zpodd = ata_dev->zpodd;
> -	struct device *dev = &ata_dev->sdev->sdev_gendev;
> +	struct device *dev = &ata_dev->sdev[0]->sdev_gendev;
>  
>  	if (event == ACPI_NOTIFY_DEVICE_WAKE && pm_runtime_suspended(dev)) {
>  		zpodd->from_notify = true;
> diff --git a/include/linux/libata.h b/include/linux/libata.h
> index 27b11577826e..e2e759d492c7 100644
> --- a/include/linux/libata.h
> +++ b/include/linux/libata.h
> @@ -722,7 +722,7 @@ struct ata_device {
>  	unsigned int		devno;		/* 0 or 1 */
>  	u64			quirks;		/* List of broken features */
>  	unsigned long		flags;		/* ATA_DFLAG_xxx */
> -	struct scsi_device	*sdev;		/* attached SCSI device */
> +	struct scsi_device	*sdev[ATAPI_MAX_LUN];	/* per-LUN SCSI devices */
>  	void			*private_data;
>  #ifdef CONFIG_ATA_ACPI
>  	union acpi_object	*gtf_cache;


-- 
Damien Le Moal
Western Digital Research

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH v3 3/7] ata: libata-scsi: route non-zero LUN commands for multi-LUN ATAPI
  2026-04-26 19:09 ` [PATCH v3 3/7] ata: libata-scsi: route non-zero LUN commands for multi-LUN ATAPI Phil Pemberton
@ 2026-04-26 23:29   ` Damien Le Moal
  2026-04-27 11:53   ` Hannes Reinecke
  1 sibling, 0 replies; 21+ messages in thread
From: Damien Le Moal @ 2026-04-26 23:29 UTC (permalink / raw)
  To: Phil Pemberton, linux-ide, linux-scsi
  Cc: linux-kernel, Niklas Cassel, James E . J . Bottomley,
	Martin K . Petersen, Hannes Reinecke

On 4/27/26 4:09 AM, Phil Pemberton wrote:
> Two changes are required to route commands to ATAPI LUNs other than 0:
> 
> 1. __ata_scsi_find_dev():  The existing code rejects any scsi_device
>    with a non-zero LUN, returning NULL and dropping the command on
>    the floor.  Relax both the PMP and non-PMP branches to allow
>    non-zero LUNs through when the underlying ata_device is ATAPI
>    class, since ATAPI devices can legitimately expose multiple LUNs.
> 
> 2. atapi_xlat():  Older ATAPI devices (SCSI-2 era) expect the LUN in
>    CDB byte 1 bits 7:5 rather than relying on transport-level LUN
>    addressing.  Encode scmd->device->lun into those bits, preserving
>    the existing command-specific bits in 4:0.  This is required by
>    both the Panasonic PD/CD combos and Nakamichi CD changers.  LUNs
>    beyond 7 cannot be encoded in the 3-bit CDB field; reject them
>    with AC_ERR_INVALID.
> 
> Signed-off-by: Phil Pemberton <philpem@philpem.me.uk>
> ---
>  drivers/ata/libata-scsi.c | 17 +++++++++++++++--
>  1 file changed, 15 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
> index 317883bac25f..48c7d323d6f9 100644
> --- a/drivers/ata/libata-scsi.c
> +++ b/drivers/ata/libata-scsi.c
> @@ -2951,6 +2951,11 @@ static unsigned int atapi_xlat(struct ata_queued_cmd *qc)
>  	memset(qc->cdb, 0, dev->cdb_len);
>  	memcpy(qc->cdb, scmd->cmnd, scmd->cmd_len);
>  
> +	/* SCSI-2 CDB LUN encoding: bits 7:5 of byte 1 (3-bit field) */
> +	if (scmd->device->lun >= 8)

Instead of 8, please use ATAPI_MAX_LUN.
Since this should never happen, this also warrants the use of WARN_ON_ONCE()
for the if condition.

> +		return AC_ERR_INVALID;
> +	qc->cdb[1] = (qc->cdb[1] & 0x1f) | ((u8)scmd->device->lun << 5);
> +
>  	qc->complete_fn = atapi_qc_complete;
>  
>  	qc->tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
> @@ -3059,19 +3064,27 @@ static struct ata_device *ata_find_dev(struct ata_port *ap, unsigned int devno)
>  static struct ata_device *__ata_scsi_find_dev(struct ata_port *ap,
>  					      const struct scsi_device *scsidev)
>  {
> +	struct ata_device *dev;
>  	int devno;
>  
>  	/* skip commands not addressed to targets we simulate */
>  	if (!sata_pmp_attached(ap)) {
> -		if (unlikely(scsidev->channel || scsidev->lun))
> +		if (unlikely(scsidev->channel))
>  			return NULL;
>  		devno = scsidev->id;
>  	} else {
> -		if (unlikely(scsidev->id || scsidev->lun))
> +		if (unlikely(scsidev->id))
>  			return NULL;
>  		devno = scsidev->channel;
>  	}
>  
> +	if (unlikely(scsidev->lun)) {
> +		dev = ata_find_dev(ap, devno);
> +		if (!dev || dev->class != ATA_DEV_ATAPI)
> +			return NULL;
> +		return dev;
> +	}

This really should come first in the function. Otherwise, you are radically
changing the function since you removed the scsidev->lun checks for the
preceding checks.

> +
>  	return ata_find_dev(ap, devno);
>  }
>  


-- 
Damien Le Moal
Western Digital Research

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH v3 4/7] scsi: add BLIST_NO_LUN_1F blacklist flag
  2026-04-26 19:09 ` [PATCH v3 4/7] scsi: add BLIST_NO_LUN_1F blacklist flag Phil Pemberton
@ 2026-04-26 23:32   ` Damien Le Moal
  2026-04-27 11:54   ` Hannes Reinecke
  1 sibling, 0 replies; 21+ messages in thread
From: Damien Le Moal @ 2026-04-26 23:32 UTC (permalink / raw)
  To: Phil Pemberton, linux-ide, linux-scsi
  Cc: linux-kernel, Niklas Cassel, James E . J . Bottomley,
	Martin K . Petersen, Hannes Reinecke

On 4/27/26 4:09 AM, Phil Pemberton wrote:
> Some multi-LUN devices respond to INQUIRY on unpopulated LUNs with
> PQ=0 / PDT=0x1f instead of the standard PQ=3.  The SCSI scan layer
> normally adds such devices (PQ=0 means "connected"), producing
> spurious "No Device" entries.
> 
> The scsi_target field pdt_1f_for_no_lun already exists to suppress
> this, but was previously only set by the USB UFI driver.
> 
> Add BLIST_NO_LUN_1F so the flag can be set per-device from
> scsi_devinfo, and wire it up in scsi_add_lun() to set
> starget->pdt_1f_for_no_lun from the blacklist flags.  This runs
> during LUN 0 processing, before the sequential LUN scan probes
> higher LUNs.
> 
> Signed-off-by: Phil Pemberton <philpem@philpem.me.uk>
> ---
>  drivers/scsi/scsi_scan.c    | 3 +++
>  include/scsi/scsi_devinfo.h | 6 +++---
>  2 files changed, 6 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
> index 7b11bc7de0e3..d3f0540d79a2 100644
> --- a/drivers/scsi/scsi_scan.c
> +++ b/drivers/scsi/scsi_scan.c
> @@ -1070,6 +1070,9 @@ static int scsi_add_lun(struct scsi_device *sdev, unsigned char *inq_result,
>  
>  	sdev->sdev_bflags = *bflags;
>  
> +	if (*bflags & BLIST_NO_LUN_1F)

Instead of dereferencing again bflags, maybe use sdev->sdev_bflags here ?
I would also remove the blank line before this if.

With that, looks OK to me.

Reviewed-by: Damien Le Moal <dlemoal@kernel.org>

> +		sdev->sdev_target->pdt_1f_for_no_lun = 1;
> +
>  	if (scsi_device_is_pseudo_dev(sdev))
>  		return SCSI_SCAN_LUN_PRESENT;
>  
> diff --git a/include/scsi/scsi_devinfo.h b/include/scsi/scsi_devinfo.h
> index 1d79a3b536ce..6957b0705510 100644
> --- a/include/scsi/scsi_devinfo.h
> +++ b/include/scsi/scsi_devinfo.h
> @@ -34,7 +34,8 @@
>  #define BLIST_NOSTARTONADD	((__force blist_flags_t)(1ULL << 12))
>  /* do not ask for VPD page size first on some broken targets */
>  #define BLIST_NO_VPD_SIZE	((__force blist_flags_t)(1ULL << 13))
> -#define __BLIST_UNUSED_14	((__force blist_flags_t)(1ULL << 14))
> +/* PDT 0x1f with PQ 0 means no LUN present (e.g. some ATAPI multi-LUN) */
> +#define BLIST_NO_LUN_1F		((__force blist_flags_t)(1ULL << 14))
>  #define __BLIST_UNUSED_15	((__force blist_flags_t)(1ULL << 15))
>  #define __BLIST_UNUSED_16	((__force blist_flags_t)(1ULL << 16))
>  /* try REPORT_LUNS even for SCSI-2 devs (if HBA supports more than 8 LUNs) */
> @@ -77,8 +78,7 @@
>  #define __BLIST_HIGH_UNUSED (~(__BLIST_LAST_USED | \
>  			       (__force blist_flags_t) \
>  			       ((__force __u64)__BLIST_LAST_USED - 1ULL)))
> -#define __BLIST_UNUSED_MASK (__BLIST_UNUSED_14 | \
> -			     __BLIST_UNUSED_15 | \
> +#define __BLIST_UNUSED_MASK (__BLIST_UNUSED_15 | \
>  			     __BLIST_UNUSED_16 | \
>  			     __BLIST_UNUSED_24 | \
>  			     __BLIST_UNUSED_27 | \


-- 
Damien Le Moal
Western Digital Research

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH v3 5/7] ata: libata-scsi: probe additional LUNs for multi-LUN ATAPI devices
  2026-04-26 19:09 ` [PATCH v3 5/7] ata: libata-scsi: probe additional LUNs for multi-LUN ATAPI devices Phil Pemberton
@ 2026-04-26 23:36   ` Damien Le Moal
  0 siblings, 0 replies; 21+ messages in thread
From: Damien Le Moal @ 2026-04-26 23:36 UTC (permalink / raw)
  To: Phil Pemberton, linux-ide, linux-scsi
  Cc: linux-kernel, Niklas Cassel, James E . J . Bottomley,
	Martin K . Petersen, Hannes Reinecke

On 4/27/26 4:09 AM, Phil Pemberton wrote:
> 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 atapi_max_lun module
> parameter from patch 1/6.  Devices without BLIST_FORCELUN (the vast

Please remove the mention of patch 1/6. Once the patches are applied, that will
not mean anything.

> 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 (see patch 4/6).

Same thing here.

> 
> Signed-off-by: Phil Pemberton <philpem@philpem.me.uk>
> ---
>  drivers/ata/libata-scsi.c | 37 ++++++++++++++++++++++++++++---------
>  1 file changed, 28 insertions(+), 9 deletions(-)
> 
> diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
> index 48c7d323d6f9..fc719e3d7d60 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>
> @@ -4700,7 +4701,6 @@ void ata_scsi_scan_host(struct ata_port *ap, int sync)
>   repeat:
>  	ata_for_each_link(link, ap, EDGE) {
>  		ata_for_each_dev(dev, link, ENABLED) {
> -			struct scsi_device *sdev;
>  			int channel = 0, id = 0;
>  
>  			if (dev->sdev[0])
> @@ -4711,15 +4711,34 @@ void ata_scsi_scan_host(struct ata_port *ap, int sync)
>  			else
>  				channel = link->pmp;
>  
> -			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 {
> -				dev->sdev[0] = NULL;
> +			{
> +				struct scsi_device *sdev;

This is not pretty... Please leave the declaration of sdev where it was and
remove this curly bracket. That will save one level of identation and make the
code cleaner.

> +
> +				sdev = __scsi_add_device(ap->scsi_host,
> +							 channel, id, 0, NULL);
> +				if (!IS_ERR(sdev)) {
> +					/*
> +					 * For multi-LUN ATAPI (BLIST_FORCELUN),
> +					 * trigger the sequential LUN scan.
> +					 * 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 callbacks.
> +					 */
> +					if (dev->class == ATA_DEV_ATAPI &&
> +					    sdev->sdev_bflags & BLIST_FORCELUN)
> +						scsi_scan_target(
> +							&ap->scsi_host->shost_gendev,
> +							channel, id,
> +							SCAN_WILD_CARD,
> +							SCSI_SCAN_RESCAN);
> +					scsi_device_put(sdev);
> +				}
>  			}
> +
> +			if (dev->sdev[0])
> +				ata_scsi_assign_ofnode(dev, ap);
>  		}
>  	}
>  


-- 
Damien Le Moal
Western Digital Research

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH v3 6/7] scsi: scsi_devinfo: add COMPAQ PD-1 multi-LUN ATAPI device quirk
  2026-04-26 19:09 ` [PATCH v3 6/7] scsi: scsi_devinfo: add COMPAQ PD-1 multi-LUN ATAPI device quirk Phil Pemberton
@ 2026-04-26 23:37   ` Damien Le Moal
  2026-04-27 11:55   ` Hannes Reinecke
  1 sibling, 0 replies; 21+ messages in thread
From: Damien Le Moal @ 2026-04-26 23:37 UTC (permalink / raw)
  To: Phil Pemberton, linux-ide, linux-scsi
  Cc: linux-kernel, Niklas Cassel, James E . J . Bottomley,
	Martin K . Petersen, Hannes Reinecke

On 4/27/26 4:09 AM, Phil Pemberton wrote:
> The COMPAQ PD-1 (OEM Panasonic/Matsushita LF-1195C) is a PD/CD combo
> drive that exposes two ATAPI LUNs: LUN 0 is a CD-ROM (TYPE_ROM),
> LUN 1 is a 650 MB PD (TYPE_DISK).
> 
> Add it to the SCSI device list with:
>   - BLIST_FORCELUN: tells the SCSI layer to scan past LUN 0
>   - BLIST_SINGLELUN: serialises commands across the two LUNs, since
>     the drive has a single transport and cannot handle concurrent
>     operations on both
>   - BLIST_NO_LUN_1F: the drive returns PQ=0/PDT=0x1f for unpopulated
>     LUNs instead of PQ=3; this flag tells scsi_probe_and_add_lun()
>     to silently skip them
> 
> The INQUIRY strings as reported by the device are:
>   Vendor:  "COMPAQ  " (T10 format, space-padded)
>   Product: "PD-1"
> 
> Signed-off-by: Phil Pemberton <philpem@philpem.me.uk>

Reviewed-by: Damien Le Moal <dlemoal@kernel.org>


-- 
Damien Le Moal
Western Digital Research

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH v3 7/7] scsi: scsi_devinfo: extend BLIST_NO_LUN_1F to MATSHITA and NEC PD-1 variants
  2026-04-26 19:09 ` [PATCH v3 7/7] scsi: scsi_devinfo: extend BLIST_NO_LUN_1F to MATSHITA and NEC PD-1 variants Phil Pemberton
@ 2026-04-26 23:37   ` Damien Le Moal
  2026-04-27 11:56   ` Hannes Reinecke
  1 sibling, 0 replies; 21+ messages in thread
From: Damien Le Moal @ 2026-04-26 23:37 UTC (permalink / raw)
  To: Phil Pemberton, linux-ide, linux-scsi
  Cc: linux-kernel, Niklas Cassel, James E . J . Bottomley,
	Martin K . Petersen, Hannes Reinecke

On 4/27/26 4:09 AM, Phil Pemberton wrote:
> The Panasonic LF-1095/LF-1195 PD/CD combo drive was sold under three
> OEM identities: COMPAQ "PD-1", MATSHITA "PD-1", and NEC "PD-1 ODX654P".
> All three are the same drive mechanism with the same firmware family,
> so they should share the BLIST_NO_LUN_1F quirk that was applied to the
> COMPAQ variant: PDT 0x1f / PQ 0 INQUIRY responses on non-existent LUNs
> are treated as "LUN not present" rather than as a phantom sdev.
> 
> This patch is offered for completeness.  It has not been tested on the
> MATSHITA or NEC variants -- the author only has access to the COMPAQ
> unit -- but the drives are functionally identical and the flag is a
> no-op on devices that do not exhibit the PDT 0x1f response.  Drop or
> hold this patch if confirmation on real hardware is preferred before
> extending the quirk.
> 
> Signed-off-by: Phil Pemberton <philpem@philpem.me.uk>

Reviewed-by: Damien Le Moal <dlemoal@kernel.org>


-- 
Damien Le Moal
Western Digital Research

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH v3 3/7] ata: libata-scsi: route non-zero LUN commands for multi-LUN ATAPI
  2026-04-26 19:09 ` [PATCH v3 3/7] ata: libata-scsi: route non-zero LUN commands for multi-LUN ATAPI Phil Pemberton
  2026-04-26 23:29   ` Damien Le Moal
@ 2026-04-27 11:53   ` Hannes Reinecke
  1 sibling, 0 replies; 21+ messages in thread
From: Hannes Reinecke @ 2026-04-27 11:53 UTC (permalink / raw)
  To: Phil Pemberton, linux-ide, linux-scsi
  Cc: linux-kernel, Damien Le Moal, Niklas Cassel,
	James E . J . Bottomley, Martin K . Petersen

On 4/26/26 21:09, Phil Pemberton wrote:
> Two changes are required to route commands to ATAPI LUNs other than 0:
> 
> 1. __ata_scsi_find_dev():  The existing code rejects any scsi_device
>     with a non-zero LUN, returning NULL and dropping the command on
>     the floor.  Relax both the PMP and non-PMP branches to allow
>     non-zero LUNs through when the underlying ata_device is ATAPI
>     class, since ATAPI devices can legitimately expose multiple LUNs.
> 
> 2. atapi_xlat():  Older ATAPI devices (SCSI-2 era) expect the LUN in
>     CDB byte 1 bits 7:5 rather than relying on transport-level LUN
>     addressing.  Encode scmd->device->lun into those bits, preserving
>     the existing command-specific bits in 4:0.  This is required by
>     both the Panasonic PD/CD combos and Nakamichi CD changers.  LUNs
>     beyond 7 cannot be encoded in the 3-bit CDB field; reject them
>     with AC_ERR_INVALID.
> 
> Signed-off-by: Phil Pemberton <philpem@philpem.me.uk>
> ---
>   drivers/ata/libata-scsi.c | 17 +++++++++++++++--
>   1 file changed, 15 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
> index 317883bac25f..48c7d323d6f9 100644
> --- a/drivers/ata/libata-scsi.c
> +++ b/drivers/ata/libata-scsi.c
> @@ -2951,6 +2951,11 @@ static unsigned int atapi_xlat(struct ata_queued_cmd *qc)
>   	memset(qc->cdb, 0, dev->cdb_len);
>   	memcpy(qc->cdb, scmd->cmnd, scmd->cmd_len);
>   
> +	/* SCSI-2 CDB LUN encoding: bits 7:5 of byte 1 (3-bit field) */
> +	if (scmd->device->lun >= 8)

This should be 'max_luns' of the associated scsi device, and the driver
should set the appropriate max_luns value for this specific device
(via blacklist flags etc).

Cheers,

Hannes

-- 
Dr. Hannes Reinecke                  Kernel Storage Architect
hare@suse.de                                +49 911 74053 688
SUSE Software Solutions GmbH, Frankenstr. 146, 90461 Nürnberg
HRB 36809 (AG Nürnberg), GF: I. Totev, A. McDonald, W. Knoblich

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH v3 4/7] scsi: add BLIST_NO_LUN_1F blacklist flag
  2026-04-26 19:09 ` [PATCH v3 4/7] scsi: add BLIST_NO_LUN_1F blacklist flag Phil Pemberton
  2026-04-26 23:32   ` Damien Le Moal
@ 2026-04-27 11:54   ` Hannes Reinecke
  1 sibling, 0 replies; 21+ messages in thread
From: Hannes Reinecke @ 2026-04-27 11:54 UTC (permalink / raw)
  To: Phil Pemberton, linux-ide, linux-scsi
  Cc: linux-kernel, Damien Le Moal, Niklas Cassel,
	James E . J . Bottomley, Martin K . Petersen

On 4/26/26 21:09, Phil Pemberton wrote:
> Some multi-LUN devices respond to INQUIRY on unpopulated LUNs with
> PQ=0 / PDT=0x1f instead of the standard PQ=3.  The SCSI scan layer
> normally adds such devices (PQ=0 means "connected"), producing
> spurious "No Device" entries.
> 
> The scsi_target field pdt_1f_for_no_lun already exists to suppress
> this, but was previously only set by the USB UFI driver.
> 
> Add BLIST_NO_LUN_1F so the flag can be set per-device from
> scsi_devinfo, and wire it up in scsi_add_lun() to set
> starget->pdt_1f_for_no_lun from the blacklist flags.  This runs
> during LUN 0 processing, before the sequential LUN scan probes
> higher LUNs.
> 
> Signed-off-by: Phil Pemberton <philpem@philpem.me.uk>
> ---
>   drivers/scsi/scsi_scan.c    | 3 +++
>   include/scsi/scsi_devinfo.h | 6 +++---
>   2 files changed, 6 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
> index 7b11bc7de0e3..d3f0540d79a2 100644
> --- a/drivers/scsi/scsi_scan.c
> +++ b/drivers/scsi/scsi_scan.c
> @@ -1070,6 +1070,9 @@ static int scsi_add_lun(struct scsi_device *sdev, unsigned char *inq_result,
>   
>   	sdev->sdev_bflags = *bflags;
>   
> +	if (*bflags & BLIST_NO_LUN_1F)
> +		sdev->sdev_target->pdt_1f_for_no_lun = 1;
> +
>   	if (scsi_device_is_pseudo_dev(sdev))
>   		return SCSI_SCAN_LUN_PRESENT;
>   
> diff --git a/include/scsi/scsi_devinfo.h b/include/scsi/scsi_devinfo.h
> index 1d79a3b536ce..6957b0705510 100644
> --- a/include/scsi/scsi_devinfo.h
> +++ b/include/scsi/scsi_devinfo.h
> @@ -34,7 +34,8 @@
>   #define BLIST_NOSTARTONADD	((__force blist_flags_t)(1ULL << 12))
>   /* do not ask for VPD page size first on some broken targets */
>   #define BLIST_NO_VPD_SIZE	((__force blist_flags_t)(1ULL << 13))
> -#define __BLIST_UNUSED_14	((__force blist_flags_t)(1ULL << 14))
> +/* PDT 0x1f with PQ 0 means no LUN present (e.g. some ATAPI multi-LUN) */
> +#define BLIST_NO_LUN_1F		((__force blist_flags_t)(1ULL << 14))
>   #define __BLIST_UNUSED_15	((__force blist_flags_t)(1ULL << 15))
>   #define __BLIST_UNUSED_16	((__force blist_flags_t)(1ULL << 16))
>   /* try REPORT_LUNS even for SCSI-2 devs (if HBA supports more than 8 LUNs) */
> @@ -77,8 +78,7 @@
>   #define __BLIST_HIGH_UNUSED (~(__BLIST_LAST_USED | \
>   			       (__force blist_flags_t) \
>   			       ((__force __u64)__BLIST_LAST_USED - 1ULL)))
> -#define __BLIST_UNUSED_MASK (__BLIST_UNUSED_14 | \
> -			     __BLIST_UNUSED_15 | \
> +#define __BLIST_UNUSED_MASK (__BLIST_UNUSED_15 | \
>   			     __BLIST_UNUSED_16 | \
>   			     __BLIST_UNUSED_24 | \
>   			     __BLIST_UNUSED_27 | \

Much better.

Reviewed-by: Hannes Reinecke <hare@suse.de>

Cheers,

Hannes
-- 
Dr. Hannes Reinecke                  Kernel Storage Architect
hare@suse.de                                +49 911 74053 688
SUSE Software Solutions GmbH, Frankenstr. 146, 90461 Nürnberg
HRB 36809 (AG Nürnberg), GF: I. Totev, A. McDonald, W. Knoblich

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH v3 6/7] scsi: scsi_devinfo: add COMPAQ PD-1 multi-LUN ATAPI device quirk
  2026-04-26 19:09 ` [PATCH v3 6/7] scsi: scsi_devinfo: add COMPAQ PD-1 multi-LUN ATAPI device quirk Phil Pemberton
  2026-04-26 23:37   ` Damien Le Moal
@ 2026-04-27 11:55   ` Hannes Reinecke
  1 sibling, 0 replies; 21+ messages in thread
From: Hannes Reinecke @ 2026-04-27 11:55 UTC (permalink / raw)
  To: Phil Pemberton, linux-ide, linux-scsi
  Cc: linux-kernel, Damien Le Moal, Niklas Cassel,
	James E . J . Bottomley, Martin K . Petersen

On 4/26/26 21:09, Phil Pemberton wrote:
> The COMPAQ PD-1 (OEM Panasonic/Matsushita LF-1195C) is a PD/CD combo
> drive that exposes two ATAPI LUNs: LUN 0 is a CD-ROM (TYPE_ROM),
> LUN 1 is a 650 MB PD (TYPE_DISK).
> 
> Add it to the SCSI device list with:
>    - BLIST_FORCELUN: tells the SCSI layer to scan past LUN 0
>    - BLIST_SINGLELUN: serialises commands across the two LUNs, since
>      the drive has a single transport and cannot handle concurrent
>      operations on both
>    - BLIST_NO_LUN_1F: the drive returns PQ=0/PDT=0x1f for unpopulated
>      LUNs instead of PQ=3; this flag tells scsi_probe_and_add_lun()
>      to silently skip them
> 
> The INQUIRY strings as reported by the device are:
>    Vendor:  "COMPAQ  " (T10 format, space-padded)
>    Product: "PD-1"
> 
> Signed-off-by: Phil Pemberton <philpem@philpem.me.uk>
> ---
>   drivers/scsi/scsi_devinfo.c | 2 ++
>   1 file changed, 2 insertions(+)
> 
> diff --git a/drivers/scsi/scsi_devinfo.c b/drivers/scsi/scsi_devinfo.c
> index 68a992494b12..bfc2cbd43897 100644
> --- a/drivers/scsi/scsi_devinfo.c
> +++ b/drivers/scsi/scsi_devinfo.c
> @@ -150,6 +150,8 @@ static struct {
>   	{"COMPAQ", "MSA1000", NULL, BLIST_SPARSELUN | BLIST_NOSTARTONADD},
>   	{"COMPAQ", "MSA1000 VOLUME", NULL, BLIST_SPARSELUN | BLIST_NOSTARTONADD},
>   	{"COMPAQ", "HSV110", NULL, BLIST_REPORTLUN2 | BLIST_NOSTARTONADD},
> +	{"COMPAQ", "PD-1", NULL, BLIST_FORCELUN | BLIST_SINGLELUN |
> +				 BLIST_NO_LUN_1F},
>   	{"DDN", "SAN DataDirector", "*", BLIST_SPARSELUN},
>   	{"DEC", "HSG80", NULL, BLIST_REPORTLUN2 | BLIST_NOSTARTONADD},
>   	{"DELL", "PV660F", NULL, BLIST_SPARSELUN},
Reviewed-by: Hannes Reinecke <hare@suse.de>

Cheers,

Hannes
-- 
Dr. Hannes Reinecke                  Kernel Storage Architect
hare@suse.de                                +49 911 74053 688
SUSE Software Solutions GmbH, Frankenstr. 146, 90461 Nürnberg
HRB 36809 (AG Nürnberg), GF: I. Totev, A. McDonald, W. Knoblich

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH v3 7/7] scsi: scsi_devinfo: extend BLIST_NO_LUN_1F to MATSHITA and NEC PD-1 variants
  2026-04-26 19:09 ` [PATCH v3 7/7] scsi: scsi_devinfo: extend BLIST_NO_LUN_1F to MATSHITA and NEC PD-1 variants Phil Pemberton
  2026-04-26 23:37   ` Damien Le Moal
@ 2026-04-27 11:56   ` Hannes Reinecke
  2026-04-27 12:12     ` Phil Pemberton
  2026-05-06  0:52     ` Phil Pemberton
  1 sibling, 2 replies; 21+ messages in thread
From: Hannes Reinecke @ 2026-04-27 11:56 UTC (permalink / raw)
  To: Phil Pemberton, linux-ide, linux-scsi
  Cc: linux-kernel, Damien Le Moal, Niklas Cassel,
	James E . J . Bottomley, Martin K . Petersen

On 4/26/26 21:09, Phil Pemberton wrote:
> The Panasonic LF-1095/LF-1195 PD/CD combo drive was sold under three
> OEM identities: COMPAQ "PD-1", MATSHITA "PD-1", and NEC "PD-1 ODX654P".
> All three are the same drive mechanism with the same firmware family,
> so they should share the BLIST_NO_LUN_1F quirk that was applied to the
> COMPAQ variant: PDT 0x1f / PQ 0 INQUIRY responses on non-existent LUNs
> are treated as "LUN not present" rather than as a phantom sdev.
> 
> This patch is offered for completeness.  It has not been tested on the
> MATSHITA or NEC variants -- the author only has access to the COMPAQ
> unit -- but the drives are functionally identical and the flag is a
> no-op on devices that do not exhibit the PDT 0x1f response.  Drop or
> hold this patch if confirmation on real hardware is preferred before
> extending the quirk.
> 
> Signed-off-by: Phil Pemberton <philpem@philpem.me.uk>
> ---
>   drivers/scsi/scsi_devinfo.c | 6 ++++--
>   1 file changed, 4 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/scsi/scsi_devinfo.c b/drivers/scsi/scsi_devinfo.c
> index bfc2cbd43897..ab1ffa9433b7 100644
> --- a/drivers/scsi/scsi_devinfo.c
> +++ b/drivers/scsi/scsi_devinfo.c
> @@ -201,7 +201,8 @@ static struct {
>   	{"LASOUND", "CDX7405", "3.10", BLIST_MAX5LUN | BLIST_SINGLELUN},
>   	{"Marvell", "Console", NULL, BLIST_SKIP_VPD_PAGES},
>   	{"Marvell", "91xx Config", "1.01", BLIST_SKIP_VPD_PAGES},
> -	{"MATSHITA", "PD-1", NULL, BLIST_FORCELUN | BLIST_SINGLELUN},
> +	{"MATSHITA", "PD-1", NULL, BLIST_FORCELUN | BLIST_SINGLELUN |
> +				   BLIST_NO_LUN_1F},
>   	{"MATSHITA", "DMC-LC5", NULL, BLIST_NOT_LOCKABLE | BLIST_INQUIRY_36},
>   	{"MATSHITA", "DMC-LC40", NULL, BLIST_NOT_LOCKABLE | BLIST_INQUIRY_36},
>   	{"Medion", "Flash XL  MMC/SD", "2.6D", BLIST_FORCELUN},
> @@ -212,7 +213,8 @@ static struct {
>   	{"nCipher", "Fastness Crypto", NULL, BLIST_FORCELUN},
>   	{"NAKAMICH", "MJ-4.8S", NULL, BLIST_FORCELUN | BLIST_SINGLELUN},
>   	{"NAKAMICH", "MJ-5.16S", NULL, BLIST_FORCELUN | BLIST_SINGLELUN},
> -	{"NEC", "PD-1 ODX654P", NULL, BLIST_FORCELUN | BLIST_SINGLELUN},
> +	{"NEC", "PD-1 ODX654P", NULL, BLIST_FORCELUN | BLIST_SINGLELUN |
> +				      BLIST_NO_LUN_1F},
>   	{"NEC", "iStorage", NULL, BLIST_REPORTLUN2},
>   	{"NRC", "MBR-7", NULL, BLIST_FORCELUN | BLIST_SINGLELUN},
>   	{"NRC", "MBR-7.4", NULL, BLIST_FORCELUN | BLIST_SINGLELUN},

Any specific reason why this patch is not merged with the previous one?
Otherwise:

Reviewed-by: Hannes Reinecke <hare@suse.de>

Cheers,

Hannes
-- 
Dr. Hannes Reinecke                  Kernel Storage Architect
hare@suse.de                                +49 911 74053 688
SUSE Software Solutions GmbH, Frankenstr. 146, 90461 Nürnberg
HRB 36809 (AG Nürnberg), GF: I. Totev, A. McDonald, W. Knoblich

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH v3 7/7] scsi: scsi_devinfo: extend BLIST_NO_LUN_1F to MATSHITA and NEC PD-1 variants
  2026-04-27 11:56   ` Hannes Reinecke
@ 2026-04-27 12:12     ` Phil Pemberton
  2026-05-06  0:52     ` Phil Pemberton
  1 sibling, 0 replies; 21+ messages in thread
From: Phil Pemberton @ 2026-04-27 12:12 UTC (permalink / raw)
  To: Hannes Reinecke, linux-ide, linux-scsi
  Cc: linux-kernel, Damien Le Moal, Niklas Cassel,
	James E . J . Bottomley, Martin K . Petersen

On 27/04/2026 12:56, Hannes Reinecke wrote:
> On 4/26/26 21:09, Phil Pemberton wrote:
>> The Panasonic LF-1095/LF-1195 PD/CD combo drive was sold under three
>> OEM identities: COMPAQ "PD-1", MATSHITA "PD-1", and NEC "PD-1 ODX654P".
>> All three are the same drive mechanism with the same firmware family,
>> so they should share the BLIST_NO_LUN_1F quirk that was applied to the
>> COMPAQ variant: PDT 0x1f / PQ 0 INQUIRY responses on non-existent LUNs
>> are treated as "LUN not present" rather than as a phantom sdev.
>>
>> This patch is offered for completeness.  It has not been tested on the
>> MATSHITA or NEC variants -- the author only has access to the COMPAQ
>> unit -- but the drives are functionally identical and the flag is a
>> no-op on devices that do not exhibit the PDT 0x1f response.  Drop or
>> hold this patch if confirmation on real hardware is preferred before
>> extending the quirk.
>>
>> Signed-off-by: Phil Pemberton <philpem@philpem.me.uk>
>> ---
>>   drivers/scsi/scsi_devinfo.c | 6 ++++--
>>   1 file changed, 4 insertions(+), 2 deletions(-)
>>
>> diff --git a/drivers/scsi/scsi_devinfo.c b/drivers/scsi/scsi_devinfo.c
>> index bfc2cbd43897..ab1ffa9433b7 100644
>> --- a/drivers/scsi/scsi_devinfo.c
>> +++ b/drivers/scsi/scsi_devinfo.c
>> @@ -201,7 +201,8 @@ static struct {
>>       {"LASOUND", "CDX7405", "3.10", BLIST_MAX5LUN | BLIST_SINGLELUN},
>>       {"Marvell", "Console", NULL, BLIST_SKIP_VPD_PAGES},
>>       {"Marvell", "91xx Config", "1.01", BLIST_SKIP_VPD_PAGES},
>> -    {"MATSHITA", "PD-1", NULL, BLIST_FORCELUN | BLIST_SINGLELUN},
>> +    {"MATSHITA", "PD-1", NULL, BLIST_FORCELUN | BLIST_SINGLELUN |
>> +                   BLIST_NO_LUN_1F},
>>       {"MATSHITA", "DMC-LC5", NULL, BLIST_NOT_LOCKABLE | 
>> BLIST_INQUIRY_36},
>>       {"MATSHITA", "DMC-LC40", NULL, BLIST_NOT_LOCKABLE | 
>> BLIST_INQUIRY_36},
>>       {"Medion", "Flash XL  MMC/SD", "2.6D", BLIST_FORCELUN},
>> @@ -212,7 +213,8 @@ static struct {
>>       {"nCipher", "Fastness Crypto", NULL, BLIST_FORCELUN},
>>       {"NAKAMICH", "MJ-4.8S", NULL, BLIST_FORCELUN | BLIST_SINGLELUN},
>>       {"NAKAMICH", "MJ-5.16S", NULL, BLIST_FORCELUN | BLIST_SINGLELUN},
>> -    {"NEC", "PD-1 ODX654P", NULL, BLIST_FORCELUN | BLIST_SINGLELUN},
>> +    {"NEC", "PD-1 ODX654P", NULL, BLIST_FORCELUN | BLIST_SINGLELUN |
>> +                      BLIST_NO_LUN_1F},
>>       {"NEC", "iStorage", NULL, BLIST_REPORTLUN2},
>>       {"NRC", "MBR-7", NULL, BLIST_FORCELUN | BLIST_SINGLELUN},
>>       {"NRC", "MBR-7.4", NULL, BLIST_FORCELUN | BLIST_SINGLELUN},
> 
> Any specific reason why this patch is not merged with the previous one?
> Otherwise:
> 
> Reviewed-by: Hannes Reinecke <hare@suse.de>
> 
> Cheers,
> 
> Hannes

Hi Hannes,

The short answer is because I don't have those two drives to test with. 
They're based on the same hardware platform but I'm assuming they have 
the same behaviour.

The idea of the separate patch is that if the lack of testing was an 
issue, it could be separated from the known-working parts in the first 6 
sections.

Thanks,
-- 
Phil.
philpem@philpem.me.uk
https://www.philpem.me.uk/

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH v3 7/7] scsi: scsi_devinfo: extend BLIST_NO_LUN_1F to MATSHITA and NEC PD-1 variants
  2026-04-27 11:56   ` Hannes Reinecke
  2026-04-27 12:12     ` Phil Pemberton
@ 2026-05-06  0:52     ` Phil Pemberton
  1 sibling, 0 replies; 21+ messages in thread
From: Phil Pemberton @ 2026-05-06  0:52 UTC (permalink / raw)
  To: Hannes Reinecke, linux-ide, linux-scsi
  Cc: linux-kernel, Damien Le Moal, Niklas Cassel,
	James E . J . Bottomley, Martin K . Petersen

On 27/04/2026 12:56, Hannes Reinecke wrote:
> On 4/26/26 21:09, Phil Pemberton wrote:
>> The Panasonic LF-1095/LF-1195 PD/CD combo drive was sold under three
>> OEM identities: COMPAQ "PD-1", MATSHITA "PD-1", and NEC "PD-1 ODX654P".
>> All three are the same drive mechanism with the same firmware family,
>> so they should share the BLIST_NO_LUN_1F quirk that was applied to the
>> COMPAQ variant: PDT 0x1f / PQ 0 INQUIRY responses on non-existent LUNs
>> are treated as "LUN not present" rather than as a phantom sdev.
>>
>> This patch is offered for completeness.  It has not been tested on the
>> MATSHITA or NEC variants -- the author only has access to the COMPAQ
>> unit -- but the drives are functionally identical and the flag is a
>> no-op on devices that do not exhibit the PDT 0x1f response.  Drop or
>> hold this patch if confirmation on real hardware is preferred before
>> extending the quirk.
>>
>> Signed-off-by: Phil Pemberton <philpem@philpem.me.uk>
>> ---
>>   drivers/scsi/scsi_devinfo.c | 6 ++++--
>>   1 file changed, 4 insertions(+), 2 deletions(-)
>>
>> diff --git a/drivers/scsi/scsi_devinfo.c b/drivers/scsi/scsi_devinfo.c
>> index bfc2cbd43897..ab1ffa9433b7 100644
>> --- a/drivers/scsi/scsi_devinfo.c
>> +++ b/drivers/scsi/scsi_devinfo.c
>> @@ -201,7 +201,8 @@ static struct {
>>       {"LASOUND", "CDX7405", "3.10", BLIST_MAX5LUN | BLIST_SINGLELUN},
>>       {"Marvell", "Console", NULL, BLIST_SKIP_VPD_PAGES},
>>       {"Marvell", "91xx Config", "1.01", BLIST_SKIP_VPD_PAGES},
>> -    {"MATSHITA", "PD-1", NULL, BLIST_FORCELUN | BLIST_SINGLELUN},
>> +    {"MATSHITA", "PD-1", NULL, BLIST_FORCELUN | BLIST_SINGLELUN |
>> +                   BLIST_NO_LUN_1F},
>>       {"MATSHITA", "DMC-LC5", NULL, BLIST_NOT_LOCKABLE | 
>> BLIST_INQUIRY_36},
>>       {"MATSHITA", "DMC-LC40", NULL, BLIST_NOT_LOCKABLE | 
>> BLIST_INQUIRY_36},
>>       {"Medion", "Flash XL  MMC/SD", "2.6D", BLIST_FORCELUN},
>> @@ -212,7 +213,8 @@ static struct {
>>       {"nCipher", "Fastness Crypto", NULL, BLIST_FORCELUN},
>>       {"NAKAMICH", "MJ-4.8S", NULL, BLIST_FORCELUN | BLIST_SINGLELUN},
>>       {"NAKAMICH", "MJ-5.16S", NULL, BLIST_FORCELUN | BLIST_SINGLELUN},
>> -    {"NEC", "PD-1 ODX654P", NULL, BLIST_FORCELUN | BLIST_SINGLELUN},
>> +    {"NEC", "PD-1 ODX654P", NULL, BLIST_FORCELUN | BLIST_SINGLELUN |
>> +                      BLIST_NO_LUN_1F},
>>       {"NEC", "iStorage", NULL, BLIST_REPORTLUN2},
>>       {"NRC", "MBR-7", NULL, BLIST_FORCELUN | BLIST_SINGLELUN},
>>       {"NRC", "MBR-7.4", NULL, BLIST_FORCELUN | BLIST_SINGLELUN},
> 
> Any specific reason why this patch is not merged with the previous one?
> Otherwise:
> 
> Reviewed-by: Hannes Reinecke <hare@suse.de>

Only that these are optional to the feature work and untested as I don't 
have hardware. I believe these drives use the same PD-1 mechanism and 
firmware so should behave the same, but I can't prove it.

The intent was to allow the 1-6 set to be merged (as these are tested) 
without 7/7 (which is not) to minimise the risk of regressions.

Thanks,
-- 
Phil.
philpem@philpem.me.uk
https://www.philpem.me.uk/

^ permalink raw reply	[flat|nested] 21+ messages in thread

end of thread, other threads:[~2026-05-06  1:11 UTC | newest]

Thread overview: 21+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-04-26 19:09 [PATCH v3 0/7] ata: libata-scsi: multi-LUN ATAPI device support Phil Pemberton
2026-04-26 19:09 ` [PATCH v3 1/7] ata: libata-scsi: add atapi_max_lun module parameter Phil Pemberton
2026-04-26 23:14   ` Damien Le Moal
2026-04-26 19:09 ` [PATCH v3 2/7] ata: libata-scsi: convert dev->sdev to per-LUN array Phil Pemberton
2026-04-26 23:25   ` Damien Le Moal
2026-04-26 19:09 ` [PATCH v3 3/7] ata: libata-scsi: route non-zero LUN commands for multi-LUN ATAPI Phil Pemberton
2026-04-26 23:29   ` Damien Le Moal
2026-04-27 11:53   ` Hannes Reinecke
2026-04-26 19:09 ` [PATCH v3 4/7] scsi: add BLIST_NO_LUN_1F blacklist flag Phil Pemberton
2026-04-26 23:32   ` Damien Le Moal
2026-04-27 11:54   ` Hannes Reinecke
2026-04-26 19:09 ` [PATCH v3 5/7] ata: libata-scsi: probe additional LUNs for multi-LUN ATAPI devices Phil Pemberton
2026-04-26 23:36   ` Damien Le Moal
2026-04-26 19:09 ` [PATCH v3 6/7] scsi: scsi_devinfo: add COMPAQ PD-1 multi-LUN ATAPI device quirk Phil Pemberton
2026-04-26 23:37   ` Damien Le Moal
2026-04-27 11:55   ` Hannes Reinecke
2026-04-26 19:09 ` [PATCH v3 7/7] scsi: scsi_devinfo: extend BLIST_NO_LUN_1F to MATSHITA and NEC PD-1 variants Phil Pemberton
2026-04-26 23:37   ` Damien Le Moal
2026-04-27 11:56   ` Hannes Reinecke
2026-04-27 12:12     ` Phil Pemberton
2026-05-06  0:52     ` Phil Pemberton

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox