* [PATCH v2 1/5] ata: libata-scsi: add atapi_max_lun module parameter
2026-04-20 12:23 [PATCH v2 0/5] ata: libata-scsi: multi-LUN ATAPI device support Phil Pemberton
@ 2026-04-20 12:23 ` Phil Pemberton
2026-04-23 11:03 ` Hannes Reinecke
2026-04-20 12:23 ` [PATCH v2 2/5] ata: libata-scsi: convert dev->sdev to per-LUN array Phil Pemberton
` (4 subsequent siblings)
5 siblings, 1 reply; 13+ messages in thread
From: Phil Pemberton @ 2026-04-20 12:23 UTC (permalink / raw)
To: Damien Le Moal, Niklas Cassel
Cc: James E . J . Bottomley, Martin K . Petersen, Hannes Reinecke,
linux-ide, linux-scsi, linux-kernel, 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.
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] 13+ messages in thread* Re: [PATCH v2 1/5] ata: libata-scsi: add atapi_max_lun module parameter
2026-04-20 12:23 ` [PATCH v2 1/5] ata: libata-scsi: add atapi_max_lun module parameter Phil Pemberton
@ 2026-04-23 11:03 ` Hannes Reinecke
0 siblings, 0 replies; 13+ messages in thread
From: Hannes Reinecke @ 2026-04-23 11:03 UTC (permalink / raw)
To: Phil Pemberton, Damien Le Moal, Niklas Cassel
Cc: James E . J . Bottomley, Martin K . Petersen, linux-ide,
linux-scsi, linux-kernel
On 4/20/26 14:23, 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.
>
> 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(-)
>
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] 13+ messages in thread
* [PATCH v2 2/5] ata: libata-scsi: convert dev->sdev to per-LUN array
2026-04-20 12:23 [PATCH v2 0/5] ata: libata-scsi: multi-LUN ATAPI device support Phil Pemberton
2026-04-20 12:23 ` [PATCH v2 1/5] ata: libata-scsi: add atapi_max_lun module parameter Phil Pemberton
@ 2026-04-20 12:23 ` Phil Pemberton
2026-04-23 11:05 ` Hannes Reinecke
2026-04-20 12:23 ` [PATCH v2 3/5] ata: libata-scsi: route non-zero LUN commands for multi-LUN ATAPI Phil Pemberton
` (3 subsequent siblings)
5 siblings, 1 reply; 13+ messages in thread
From: Phil Pemberton @ 2026-04-20 12:23 UTC (permalink / raw)
To: Damien Le Moal, Niklas Cassel
Cc: James E . J . Bottomley, Martin K . Petersen, Hannes Reinecke,
linux-ide, linux-scsi, linux-kernel, 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.
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] 13+ messages in thread* Re: [PATCH v2 2/5] ata: libata-scsi: convert dev->sdev to per-LUN array
2026-04-20 12:23 ` [PATCH v2 2/5] ata: libata-scsi: convert dev->sdev to per-LUN array Phil Pemberton
@ 2026-04-23 11:05 ` Hannes Reinecke
0 siblings, 0 replies; 13+ messages in thread
From: Hannes Reinecke @ 2026-04-23 11:05 UTC (permalink / raw)
To: Phil Pemberton, Damien Le Moal, Niklas Cassel
Cc: James E . J . Bottomley, Martin K . Petersen, linux-ide,
linux-scsi, linux-kernel
On 4/20/26 14:23, 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.
>
> 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(-)
>
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] 13+ messages in thread
* [PATCH v2 3/5] ata: libata-scsi: route non-zero LUN commands for multi-LUN ATAPI
2026-04-20 12:23 [PATCH v2 0/5] ata: libata-scsi: multi-LUN ATAPI device support Phil Pemberton
2026-04-20 12:23 ` [PATCH v2 1/5] ata: libata-scsi: add atapi_max_lun module parameter Phil Pemberton
2026-04-20 12:23 ` [PATCH v2 2/5] ata: libata-scsi: convert dev->sdev to per-LUN array Phil Pemberton
@ 2026-04-20 12:23 ` Phil Pemberton
2026-04-23 11:08 ` Hannes Reinecke
2026-04-20 12:23 ` [PATCH v2 4/5] ata: libata-scsi: probe additional LUNs for multi-LUN ATAPI devices Phil Pemberton
` (2 subsequent siblings)
5 siblings, 1 reply; 13+ messages in thread
From: Phil Pemberton @ 2026-04-20 12:23 UTC (permalink / raw)
To: Damien Le Moal, Niklas Cassel
Cc: James E . J . Bottomley, Martin K . Petersen, Hannes Reinecke,
linux-ide, linux-scsi, linux-kernel, 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.
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..4e88ae7d94c3 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 */
+ if (scmd->device->lun < 8)
+ 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] 13+ messages in thread* Re: [PATCH v2 3/5] ata: libata-scsi: route non-zero LUN commands for multi-LUN ATAPI
2026-04-20 12:23 ` [PATCH v2 3/5] ata: libata-scsi: route non-zero LUN commands for multi-LUN ATAPI Phil Pemberton
@ 2026-04-23 11:08 ` Hannes Reinecke
2026-04-23 15:50 ` Phil Pemberton
0 siblings, 1 reply; 13+ messages in thread
From: Hannes Reinecke @ 2026-04-23 11:08 UTC (permalink / raw)
To: Phil Pemberton, Damien Le Moal, Niklas Cassel
Cc: James E . J . Bottomley, Martin K . Petersen, linux-ide,
linux-scsi, linux-kernel
On 4/20/26 14:23, 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.
>
> 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..4e88ae7d94c3 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 */
> + if (scmd->device->lun < 8)
> + qc->cdb[1] = (qc->cdb[1] & 0x1f) |
> + ((u8)scmd->device->lun << 5);
> +
Hmm. And what happens when scmd->device->lun is _greater_ than 7?
We surely should abort that command, shouldn't we?
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] 13+ messages in thread
* Re: [PATCH v2 3/5] ata: libata-scsi: route non-zero LUN commands for multi-LUN ATAPI
2026-04-23 11:08 ` Hannes Reinecke
@ 2026-04-23 15:50 ` Phil Pemberton
0 siblings, 0 replies; 13+ messages in thread
From: Phil Pemberton @ 2026-04-23 15:50 UTC (permalink / raw)
To: Hannes Reinecke, Damien Le Moal, Niklas Cassel
Cc: James E . J . Bottomley, Martin K . Petersen, linux-ide,
linux-scsi, linux-kernel
On 23/04/2026 12:08, Hannes Reinecke wrote:
> On 4/20/26 14:23, 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.
>>
>> 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..4e88ae7d94c3 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 */
>> + if (scmd->device->lun < 8)
>> + qc->cdb[1] = (qc->cdb[1] & 0x1f) |
>> + ((u8)scmd->device->lun << 5);
>> +
>
> Hmm. And what happens when scmd->device->lun is _greater_ than 7?
> We surely should abort that command, shouldn't we?
I was about to say "you can't have LUNs greater than seven" until I saw
it's been extended in later versions of the standard.
What's the preferred way to abort the command in this context?
--
Phil.
philpem@philpem.me.uk
https://www.philpem.me.uk/
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH v2 4/5] ata: libata-scsi: probe additional LUNs for multi-LUN ATAPI devices
2026-04-20 12:23 [PATCH v2 0/5] ata: libata-scsi: multi-LUN ATAPI device support Phil Pemberton
` (2 preceding siblings ...)
2026-04-20 12:23 ` [PATCH v2 3/5] ata: libata-scsi: route non-zero LUN commands for multi-LUN ATAPI Phil Pemberton
@ 2026-04-20 12:23 ` Phil Pemberton
2026-04-23 11:15 ` Hannes Reinecke
2026-04-20 12:23 ` [PATCH v2 5/5] scsi: scsi_devinfo: add COMPAQ PD-1 multi-LUN ATAPI device quirk Phil Pemberton
2026-04-22 0:48 ` [PATCH v2 0/5] ata: libata-scsi: multi-LUN ATAPI device support Martin K. Petersen
5 siblings, 1 reply; 13+ messages in thread
From: Phil Pemberton @ 2026-04-20 12:23 UTC (permalink / raw)
To: Damien Le Moal, Niklas Cassel
Cc: James E . J . Bottomley, Martin K . Petersen, Hannes Reinecke,
linux-ide, linux-scsi, linux-kernel, 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/5. 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.
To suppress spurious "No Device" log entries from non-responding LUNs
(e.g. LUN 2+ on a two-LUN PD/CD drive), set pdt_1f_for_no_lun on the
scsi_target during LUN 0 configuration. The Panasonic PD-1 returns
PQ=0/PDT=0x1f for unpopulated LUNs rather than the standard PQ=3;
with this flag, scsi_probe_and_add_lun() silently skips them.
If BLIST_FORCELUN is set but atapi_max_lun is still at its default of
1, an informational message points the user at the module parameter so
the knob is discoverable from dmesg.
Signed-off-by: Phil Pemberton <philpem@philpem.me.uk>
---
drivers/ata/libata-scsi.c | 53 ++++++++++++++++++++++++++++++++-------
1 file changed, 44 insertions(+), 9 deletions(-)
diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
index 4e88ae7d94c3..9d18ef2835a5 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>
@@ -1132,6 +1133,22 @@ int ata_scsi_dev_config(struct scsi_device *sdev, struct queue_limits *lim,
sdev->security_supported = 1;
dev->sdev[sdev->lun] = sdev;
+
+ /*
+ * Tell the SCSI scan layer that PDT 0x1f with PQ 0 means "no LUN
+ * present" for this target. The Panasonic PD-1 (and likely other
+ * multi-LUN ATAPI devices) returns PQ=0/PDT=0x1f for unpopulated
+ * LUNs instead of the standard PQ=3. Setting this flag lets the
+ * sequential LUN scan skip those LUNs cleanly.
+ */
+ if (dev->class == ATA_DEV_ATAPI && sdev->lun == 0) {
+ sdev->sdev_target->pdt_1f_for_no_lun = 1;
+
+ if ((sdev->sdev_bflags & BLIST_FORCELUN) && atapi_max_lun < 2)
+ ata_dev_info(dev,
+ "device has additional LUNs; set libata.atapi_max_lun=2 or higher to access them\n");
+ }
+
return 0;
}
@@ -4700,7 +4717,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 +4727,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] 13+ messages in thread* Re: [PATCH v2 4/5] ata: libata-scsi: probe additional LUNs for multi-LUN ATAPI devices
2026-04-20 12:23 ` [PATCH v2 4/5] ata: libata-scsi: probe additional LUNs for multi-LUN ATAPI devices Phil Pemberton
@ 2026-04-23 11:15 ` Hannes Reinecke
0 siblings, 0 replies; 13+ messages in thread
From: Hannes Reinecke @ 2026-04-23 11:15 UTC (permalink / raw)
To: Phil Pemberton, Damien Le Moal, Niklas Cassel
Cc: James E . J . Bottomley, Martin K . Petersen, linux-ide,
linux-scsi, linux-kernel
On 4/20/26 14:23, 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/5. 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.
>
> To suppress spurious "No Device" log entries from non-responding LUNs
> (e.g. LUN 2+ on a two-LUN PD/CD drive), set pdt_1f_for_no_lun on the
> scsi_target during LUN 0 configuration. The Panasonic PD-1 returns
> PQ=0/PDT=0x1f for unpopulated LUNs rather than the standard PQ=3;
> with this flag, scsi_probe_and_add_lun() silently skips them.
>
> If BLIST_FORCELUN is set but atapi_max_lun is still at its default of
> 1, an informational message points the user at the module parameter so
> the knob is discoverable from dmesg.
>
> Signed-off-by: Phil Pemberton <philpem@philpem.me.uk>
> ---
> drivers/ata/libata-scsi.c | 53 ++++++++++++++++++++++++++++++++-------
> 1 file changed, 44 insertions(+), 9 deletions(-)
>
> diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
> index 4e88ae7d94c3..9d18ef2835a5 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>
> @@ -1132,6 +1133,22 @@ int ata_scsi_dev_config(struct scsi_device *sdev, struct queue_limits *lim,
> sdev->security_supported = 1;
>
> dev->sdev[sdev->lun] = sdev;
> +
> + /*
> + * Tell the SCSI scan layer that PDT 0x1f with PQ 0 means "no LUN
> + * present" for this target. The Panasonic PD-1 (and likely other
> + * multi-LUN ATAPI devices) returns PQ=0/PDT=0x1f for unpopulated
> + * LUNs instead of the standard PQ=3. Setting this flag lets the
> + * sequential LUN scan skip those LUNs cleanly.
> + */
But this would hard-code device-specifics in the generic code.
> + if (dev->class == ATA_DEV_ATAPI && sdev->lun == 0) {
> + sdev->sdev_target->pdt_1f_for_no_lun = 1;
Don't. That should be done with blacklist flags for specific devices.
> +
> + if ((sdev->sdev_bflags & BLIST_FORCELUN) && atapi_max_lun < 2)
> + ata_dev_info(dev,
> + "device has additional LUNs; set libata.atapi_max_lun=2 or higher to access them\n");
Huh? How do you know? The device _might_ have additional luns, but
here we just probed for LUN 0, giving no indication whether other
LUNs are present.
And you already know which devices are affected (as the blacklist flags
should make that clear).
So I don't think we need that warning.
> + }
> +
> return 0;
> }
>
> @@ -4700,7 +4717,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 +4727,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);
> }
> }
>
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] 13+ messages in thread
* [PATCH v2 5/5] scsi: scsi_devinfo: add COMPAQ PD-1 multi-LUN ATAPI device quirk
2026-04-20 12:23 [PATCH v2 0/5] ata: libata-scsi: multi-LUN ATAPI device support Phil Pemberton
` (3 preceding siblings ...)
2026-04-20 12:23 ` [PATCH v2 4/5] ata: libata-scsi: probe additional LUNs for multi-LUN ATAPI devices Phil Pemberton
@ 2026-04-20 12:23 ` Phil Pemberton
2026-04-23 11:20 ` Hannes Reinecke
2026-04-22 0:48 ` [PATCH v2 0/5] ata: libata-scsi: multi-LUN ATAPI device support Martin K. Petersen
5 siblings, 1 reply; 13+ messages in thread
From: Phil Pemberton @ 2026-04-20 12:23 UTC (permalink / raw)
To: Damien Le Moal, Niklas Cassel
Cc: James E . J . Bottomley, Martin K . Petersen, Hannes Reinecke,
linux-ide, linux-scsi, linux-kernel, 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
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 | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/scsi/scsi_devinfo.c b/drivers/scsi/scsi_devinfo.c
index 68a992494b12..06b211b93567 100644
--- a/drivers/scsi/scsi_devinfo.c
+++ b/drivers/scsi/scsi_devinfo.c
@@ -150,6 +150,7 @@ 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},
{"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] 13+ messages in thread* Re: [PATCH v2 5/5] scsi: scsi_devinfo: add COMPAQ PD-1 multi-LUN ATAPI device quirk
2026-04-20 12:23 ` [PATCH v2 5/5] scsi: scsi_devinfo: add COMPAQ PD-1 multi-LUN ATAPI device quirk Phil Pemberton
@ 2026-04-23 11:20 ` Hannes Reinecke
0 siblings, 0 replies; 13+ messages in thread
From: Hannes Reinecke @ 2026-04-23 11:20 UTC (permalink / raw)
To: Phil Pemberton, Damien Le Moal, Niklas Cassel
Cc: James E . J . Bottomley, Martin K . Petersen, linux-ide,
linux-scsi, linux-kernel
On 4/20/26 14:23, 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
>
> 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 | 1 +
> 1 file changed, 1 insertion(+)
>
> diff --git a/drivers/scsi/scsi_devinfo.c b/drivers/scsi/scsi_devinfo.c
> index 68a992494b12..06b211b93567 100644
> --- a/drivers/scsi/scsi_devinfo.c
> +++ b/drivers/scsi/scsi_devinfo.c
> @@ -150,6 +150,7 @@ 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},
> {"DDN", "SAN DataDirector", "*", BLIST_SPARSELUN},
> {"DEC", "HSG80", NULL, BLIST_REPORTLUN2 | BLIST_NOSTARTONADD},
> {"DELL", "PV660F", NULL, BLIST_SPARSELUN},
And as indicated, we should make the 'pdt_1f_for_no_lun' flag into a
blacklist flag, and set it from here.
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] 13+ messages in thread
* Re: [PATCH v2 0/5] ata: libata-scsi: multi-LUN ATAPI device support
2026-04-20 12:23 [PATCH v2 0/5] ata: libata-scsi: multi-LUN ATAPI device support Phil Pemberton
` (4 preceding siblings ...)
2026-04-20 12:23 ` [PATCH v2 5/5] scsi: scsi_devinfo: add COMPAQ PD-1 multi-LUN ATAPI device quirk Phil Pemberton
@ 2026-04-22 0:48 ` Martin K. Petersen
5 siblings, 0 replies; 13+ messages in thread
From: Martin K. Petersen @ 2026-04-22 0:48 UTC (permalink / raw)
To: Phil Pemberton
Cc: Damien Le Moal, Niklas Cassel, James E . J . Bottomley,
Martin K . Petersen, Hannes Reinecke, linux-ide, linux-scsi,
linux-kernel
Phil,
> 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.
Looks reasonable to me.
Reviewed-by: Martin K. Petersen <martin.petersen@oracle.com>
--
Martin K. Petersen
^ permalink raw reply [flat|nested] 13+ messages in thread