From nobody Fri Jun 12 20:24:00 2026 Received: from nick.sneptech.io (nick.sneptech.io [178.62.38.78]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 90BFF3AFD16; Mon, 8 Jun 2026 21:57:02 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=178.62.38.78 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780955824; cv=none; b=UPnjRJQWar1wQngD1+Fdxf+h8jsqbQyPehgQTpDbhtqzDqBS/kiy36VylUDQ1NQIdCtVZ3p6gr9onIfFtQhsvYWL5P1GlhHLBP5EmKE8L9xrSIt+CmZ73vGkWywt2fmhRcARiO9ithOjEWbiWP/jTmvcSSJ8OYP7kEh5gzuYrwU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780955824; c=relaxed/simple; bh=x6f8CJNbI915EJ13DABGEvOBY0TFxfB2QN6TGIZA5KE=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=VOeE1bYqqGEuVLGr5RIJyetUP6G/zUOGEeNc/6kNwcSN2xvV9KcCJPwcHKwrtJvJ4zgv0SPwVkCh5wpxc8O9xOkki/iQOBjoskyTO6jXwLYNkjYkGxtvAdS/oPB1FwUblgmv7Rb512QHfz8OU4rMqZJWEUJTJwy+qPeRtFZya54= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=philpem.me.uk; spf=pass smtp.mailfrom=philpem.me.uk; dkim=pass (1024-bit key) header.d=philpem.me.uk header.i=@philpem.me.uk header.b=JxfUmSAd; arc=none smtp.client-ip=178.62.38.78 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=philpem.me.uk Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=philpem.me.uk Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=philpem.me.uk header.i=@philpem.me.uk header.b="JxfUmSAd" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=philpem.me.uk; s=mail; t=1780954491; bh=x6f8CJNbI915EJ13DABGEvOBY0TFxfB2QN6TGIZA5KE=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=JxfUmSAdJyWchnn7m+sZfM3j1JVMxlLw+o3KSqvceKIOa34D8DNrqmELmvqKhOrgJ sbIdFYXeeXe3VB4wqH93vnKvi1hUT9DWHHU+IUNr06z2Oie8tTT9m14qZqepPqgn3n uzdJOF2fIl0Kj7cvXoO9hnYV6i9XAuQM8lIbfHPM= Received: from wolf.philpem.me.uk (81-187-163-148.ip4.reverse-dns.uk [81.187.163.148]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) (Authenticated sender: mailrelay_wolf@philpem.me.uk) by nick.sneptech.io (Postfix) with ESMTPSA id 30069BD6EE; Mon, 8 Jun 2026 21:34:51 +0000 (UTC) Received: from cheetah.homenet.philpem.me.uk (cheetah.homenet.philpem.me.uk [10.0.0.32]) by wolf.philpem.me.uk (Postfix) with ESMTPSA id D793B5FC0F; Mon, 8 Jun 2026 22:34:50 +0100 (BST) From: Phil Pemberton To: linux-ide@vger.kernel.org, linux-scsi@vger.kernel.org Cc: linux-kernel@vger.kernel.org, Damien Le Moal , Niklas Cassel , "James E . J . Bottomley" , "Martin K . Petersen" , Hannes Reinecke , Phil Pemberton Subject: [PATCH v6 1/6] ata: libata-scsi: add atapi_max_lun module parameter Date: Mon, 8 Jun 2026 22:34:38 +0100 Message-ID: <20260608213443.2296614-2-philpem@philpem.me.uk> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260608213443.2296614-1-philpem@philpem.me.uk> References: <20260608213443.2296614-1-philpem@philpem.me.uk> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Until now libata has hard-coded shost->max_lun =3D 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 Signed-off-by: Phil Pemberton --- 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 e76d15411e2a..4408b1fb48c7 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -122,6 +122,11 @@ int atapi_passthru16 =3D 1; module_param(atapi_passthru16, int, 0444); MODULE_PARM_DESC(atapi_passthru16, "Enable ATA_16 passthru for ATAPI devic= es (0=3Doff, 1=3Don [default])"); =20 +int atapi_max_lun =3D 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 =3D 0; module_param_named(fua, libata_fua, int, 0444); MODULE_PARM_DESC(fua, "FUA support (0=3Doff [default], 1=3Don)"); diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index f44612e269a4..32c6a0e497cf 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -4627,7 +4627,7 @@ int ata_scsi_add_hosts(struct ata_host *host, const s= truct scsi_host_template *s shost->transportt =3D &ata_scsi_transportt; shost->unique_id =3D ap->print_id; shost->max_id =3D 16; - shost->max_lun =3D 1; + shost->max_lun =3D clamp(atapi_max_lun, 1, ATAPI_MAX_LUN); shost->max_channel =3D 1; shost->max_cmd_len =3D 32; =20 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" =20 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 5c085ef4eda7..3e33ee30628d 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -131,6 +131,7 @@ enum { ATA_SHORT_PAUSE =3D 16, =20 ATAPI_MAX_DRAIN =3D 16 << 10, + ATAPI_MAX_LUN =3D 8, /* SCSI-2 cap (LUN values 0..7) */ =20 ATA_ALL_DEVICES =3D (1 << ATA_MAX_DEVICES) - 1, =20 --=20 2.43.0 From nobody Fri Jun 12 20:24:00 2026 Received: from nick.sneptech.io (nick.sneptech.io [178.62.38.78]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 90E263B0AC4; Mon, 8 Jun 2026 21:57:02 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=178.62.38.78 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780955825; cv=none; b=oL2U7+kYVpc6JRlZpvVE5KttrzhkpSHuwhUkeY6LrAa8AQGT7VBtJ4KA4FxMio98aYnltNNUhayU0pMr+BzMekzy5Sdkr+8KHiWS/nBAfTyuxzyDHnyGv3Yae8oKIxiU3sJ6i9+tcaGv4ITcI5HdLWSpAgb4AoN1OnhxrT2fans= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780955825; c=relaxed/simple; bh=qYv8tVeIH19cO/jH+GEV12UiE4fByjbcTz6BekvguZ4=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=HP5vPlmltO8yaqCPGS4j4FwcYEr+i9T41LfbffvoriJ2BQ0J4ryFCsJqXQjsIBjxf1lKP9hkOSSaCZQybvVKt+CjCb0uNQEt+mugqqXjgIcCoNA6LGF7MXBkfXYkM2SZ3rg+BwMuspd8b9IHv8Ti/FMynfay3WxjvGbD0hDMXFo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=philpem.me.uk; spf=pass smtp.mailfrom=philpem.me.uk; dkim=pass (1024-bit key) header.d=philpem.me.uk header.i=@philpem.me.uk header.b=w8lFnNFZ; arc=none smtp.client-ip=178.62.38.78 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=philpem.me.uk Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=philpem.me.uk Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=philpem.me.uk header.i=@philpem.me.uk header.b="w8lFnNFZ" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=philpem.me.uk; s=mail; t=1780954491; bh=qYv8tVeIH19cO/jH+GEV12UiE4fByjbcTz6BekvguZ4=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=w8lFnNFZfGkURrE4xQtrhUtgMeObVsVMRiVcmiaivIaFXFiNTpwJ5tF8IbgR8tEID Cmwz+ieeoaPFREKS4U0w/DfXXnCvJKtMmKYB0zq7U3uSLoZFMUh8MWo6KdTfouneXx mrtiOzCO5dFU7Fqg8rth6/kQPvOCJXyeqPRN2V60= Received: from wolf.philpem.me.uk (81-187-163-148.ip4.reverse-dns.uk [81.187.163.148]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) (Authenticated sender: mailrelay_wolf@philpem.me.uk) by nick.sneptech.io (Postfix) with ESMTPSA id 42D21BE6B5; Mon, 8 Jun 2026 21:34:51 +0000 (UTC) Received: from cheetah.homenet.philpem.me.uk (cheetah.homenet.philpem.me.uk [10.0.0.32]) by wolf.philpem.me.uk (Postfix) with ESMTPSA id DEAD85FC3F; Mon, 8 Jun 2026 22:34:50 +0100 (BST) From: Phil Pemberton To: linux-ide@vger.kernel.org, linux-scsi@vger.kernel.org Cc: linux-kernel@vger.kernel.org, Damien Le Moal , Niklas Cassel , "James E . J . Bottomley" , "Martin K . Petersen" , Hannes Reinecke , Phil Pemberton Subject: [PATCH v6 2/6] ata: libata-scsi: convert dev->sdev to per-LUN array Date: Mon, 8 Jun 2026 22:34:39 +0100 Message-ID: <20260608213443.2296614-3-philpem@philpem.me.uk> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260608213443.2296614-1-philpem@philpem.me.uk> References: <20260608213443.2296614-1-philpem@philpem.me.uk> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" 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). Add a companion field dev->nr_luns recording the number of valid entries -- defaults to 1 during ata_dev_init() and is bumped during multi-LUN probe -- so the common single-LUN case iterates one slot, not eight. Add an inline helper ata_dev_scsi_device(dev, lun) that returns dev->sdev[lun] guarded by a WARN_ON_ONCE(lun >=3D dev->nr_luns) bounds check. Use it for the hardcoded LUN-0 references in libata-acpi (uevent kobj), libata-zpodd (disk events, wake notify), and the door-lock and OF-node paths in libata-scsi. 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 dev->nr_luns slots (high->low) - ata_scsi_offline_dev: iterate dev->nr_luns 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 ata_dev_scsi_device(dev, 0) For single-LUN devices (the vast majority) only dev->sdev[0] is ever populated and dev->nr_luns stays at 1, so existing call paths see no change in behaviour. Signed-off-by: Phil Pemberton --- drivers/ata/libata-acpi.c | 6 +- drivers/ata/libata-core.c | 11 ++- drivers/ata/libata-scsi.c | 151 +++++++++++++++++++------------------ drivers/ata/libata-zpodd.c | 6 +- include/linux/libata.h | 11 ++- 5 files changed, 103 insertions(+), 82 deletions(-) diff --git a/drivers/ata/libata-acpi.c b/drivers/ata/libata-acpi.c index 4433f626246b..8af35d0b1053 100644 --- a/drivers/ata/libata-acpi.c +++ b/drivers/ata/libata-acpi.c @@ -153,8 +153,10 @@ static void ata_acpi_uevent(struct ata_port *ap, struc= t ata_device *dev, char *envp[] =3D { event_string, NULL }; =20 if (dev) { - if (dev->sdev) - kobj =3D &dev->sdev->sdev_gendev.kobj; + struct scsi_device *sdev =3D ata_dev_scsi_device(dev, 0); + + if (sdev) + kobj =3D &sdev->sdev_gendev.kobj; } else kobj =3D &ap->dev->kobj; =20 diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 4408b1fb48c7..1cb159d9dbc7 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -5564,6 +5564,7 @@ void ata_dev_init(struct ata_device *dev) dev->pio_mask =3D UINT_MAX; dev->mwdma_mask =3D UINT_MAX; dev->udma_mask =3D UINT_MAX; + dev->nr_luns =3D 1; } =20 /** @@ -6275,11 +6276,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 =3D dev->nr_luns - 1; lun >=3D 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 =3D NULL; + dev->sdev[lun] =3D NULL; } } } diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index 32c6a0e497cf..7c3d31dc49a1 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, str= uct queue_limits *lim, if (dev->flags & ATA_DFLAG_TRUSTED) sdev->security_supported =3D 1; =20 - dev->sdev =3D sdev; + dev->sdev[sdev->lun] =3D sdev; return 0; } =20 @@ -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) =20 spin_lock_irqsave(ap->lock, flags); dev =3D __ata_scsi_find_dev(ap, sdev); - if (dev && dev->sdev) { - /* SCSI device already in CANCEL state, no need to offline it */ - dev->sdev =3D NULL; - dev->flags |=3D ATA_DFLAG_DETACH; - ata_port_schedule_eh(ap); + if (dev && dev->sdev[sdev->lun] =3D=3D sdev) { + dev->sdev[sdev->lun] =3D NULL; + if (sdev->lun =3D=3D 0) { + dev->flags |=3D ATA_DFLAG_DETACH; + ata_port_schedule_eh(ap); + } } spin_unlock_irqrestore(ap->lock, flags); =20 @@ -2911,10 +2912,15 @@ 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 the LUN-0 sdev isn't NULL before dereferencing. */ - if (qc->cdb[0] =3D=3D ALLOW_MEDIUM_REMOVAL && qc->dev->sdev) - qc->dev->sdev->locked =3D 0; + if (qc->cdb[0] =3D=3D ALLOW_MEDIUM_REMOVAL) { + struct scsi_device *sdev =3D + ata_dev_scsi_device(qc->dev, 0); + + if (sdev) + sdev->locked =3D 0; + } =20 ata_scsi_qc_done(qc, true, SAM_STAT_CHECK_CONDITION); return; @@ -4658,7 +4664,7 @@ int ata_scsi_add_hosts(struct ata_host *host, const s= truct 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 =3D dev->sdev; + struct scsi_device *sdev =3D ata_dev_scsi_device(dev, 0); struct device *d =3D ap->host->dev; struct device_node *np =3D d->of_node; struct device_node *child; @@ -4696,7 +4702,7 @@ void ata_scsi_scan_host(struct ata_port *ap, int sync) struct scsi_device *sdev; int channel =3D 0, id =3D 0; =20 - if (dev->sdev) + if (dev->sdev[0]) continue; =20 if (ata_is_host_link(link)) @@ -4707,11 +4713,11 @@ void ata_scsi_scan_host(struct ata_port *ap, int sy= nc) sdev =3D __scsi_add_device(ap->scsi_host, channel, id, 0, NULL); if (!IS_ERR(sdev)) { - dev->sdev =3D sdev; + dev->sdev[0] =3D sdev; ata_scsi_assign_ofnode(dev, ap); scsi_device_put(sdev); } else { - dev->sdev =3D NULL; + dev->sdev[0] =3D NULL; } } } @@ -4722,7 +4728,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; } } @@ -4763,7 +4769,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) @@ -4773,11 +4779,16 @@ void ata_scsi_scan_host(struct ata_port *ap, int sy= nc) */ bool ata_scsi_offline_dev(struct ata_device *dev) { - if (dev->sdev) { - scsi_device_set_state(dev->sdev, SDEV_OFFLINE); - return true; + bool found =3D false; + int lun; + + for (lun =3D dev->nr_luns - 1; lun >=3D 0; lun--) { + if (dev->sdev[lun]) { + scsi_device_set_state(dev->sdev[lun], SDEV_OFFLINE); + found =3D true; + } } - return false; + return found; } =20 /** @@ -4793,49 +4804,38 @@ bool ata_scsi_offline_dev(struct ata_device *dev) static void ata_scsi_remove_dev(struct ata_device *dev) { struct ata_port *ap =3D dev->link->ap; - struct scsi_device *sdev; + struct scsi_device *sdevs[ATAPI_MAX_LUN] =3D {}; unsigned long flags; + int lun; =20 - /* 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); =20 - /* clearing dev->sdev is protected by host lock */ - sdev =3D dev->sdev; - dev->sdev =3D NULL; + for (lun =3D dev->nr_luns - 1; lun >=3D 0; lun--) { + struct scsi_device *sdev =3D dev->sdev[lun]; + + dev->sdev[lun] =3D NULL; + if (!sdev) + continue; =20 - 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) =3D=3D 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] =3D sdev; } else { WARN_ON(1); - sdev =3D NULL; } } =20 spin_unlock_irqrestore(ap->lock, flags); mutex_unlock(&ap->scsi_host->scan_mutex); =20 - if (sdev) { + for (lun =3D dev->nr_luns - 1; lun >=3D 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]); } } =20 @@ -4872,9 +4872,12 @@ static void ata_scsi_handle_link_detach(struct ata_l= ink *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 =3D 0; lun < dev->nr_luns; lun++) + if (dev->sdev[lun]) + sdev_evt_send_simple(dev->sdev[lun], + SDEV_EVT_MEDIA_CHANGE, GFP_ATOMIC); } =20 /** @@ -5007,37 +5010,39 @@ void ata_scsi_dev_rescan(struct work_struct *work) =20 ata_for_each_link(link, ap, EDGE) { ata_for_each_dev(dev, link, ENABLED) { - struct scsi_device *sdev =3D dev->sdev; + int lun; =20 - /* - * If the port was suspended before this was scheduled, - * bail out. - */ if (ap->pflags & ATA_PFLAG_SUSPENDED) goto unlock_ap; =20 - if (!sdev) - continue; - if (scsi_device_get(sdev)) - continue; - do_resume =3D dev->flags & ATA_DFLAG_RESUMING; =20 - spin_unlock_irqrestore(ap->lock, flags); - if (do_resume) { - ret =3D scsi_resume_device(sdev); - if (ret =3D=3D -EWOULDBLOCK) { - scsi_device_put(sdev); - goto unlock_scan; + for (lun =3D 0; lun < dev->nr_luns; lun++) { + struct scsi_device *sdev =3D dev->sdev[lun]; + + if (!sdev) + continue; + if (scsi_device_get(sdev)) + continue; + + spin_unlock_irqrestore(ap->lock, flags); + if (do_resume) { + ret =3D scsi_resume_device(sdev); + if (ret =3D=3D -EWOULDBLOCK) { + scsi_device_put(sdev); + goto unlock_scan; + } } - dev->flags &=3D ~ATA_DFLAG_RESUMING; + ret =3D scsi_rescan_device(sdev); + scsi_device_put(sdev); + spin_lock_irqsave(ap->lock, flags); + + if (ret) + goto unlock_ap; } - ret =3D scsi_rescan_device(sdev); - scsi_device_put(sdev); - spin_lock_irqsave(ap->lock, flags); =20 - if (ret) - goto unlock_ap; + if (do_resume) + dev->flags &=3D ~ATA_DFLAG_RESUMING; } } =20 diff --git a/drivers/ata/libata-zpodd.c b/drivers/ata/libata-zpodd.c index 414e7c63bd85..dca774d8ec05 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 =3D dev->zpodd; =20 - sdev_disable_disk_events(dev->sdev); + sdev_disable_disk_events(ata_dev_scsi_device(dev, 0)); =20 zpodd->powered_off =3D true; acpi_pm_set_device_wakeup(&dev->tdev, true); @@ -233,14 +233,14 @@ void zpodd_post_poweron(struct ata_device *dev) zpodd->zp_sampled =3D false; zpodd->zp_ready =3D false; =20 - sdev_enable_disk_events(dev->sdev); + sdev_enable_disk_events(ata_dev_scsi_device(dev, 0)); } =20 static void zpodd_wake_dev(acpi_handle handle, u32 event, void *context) { struct ata_device *ata_dev =3D context; struct zpodd *zpodd =3D ata_dev->zpodd; - struct device *dev =3D &ata_dev->sdev->sdev_gendev; + struct device *dev =3D &ata_dev_scsi_device(ata_dev, 0)->sdev_gendev; =20 if (event =3D=3D ACPI_NOTIFY_DEVICE_WAKE && pm_runtime_suspended(dev)) { zpodd->from_notify =3D true; diff --git a/include/linux/libata.h b/include/linux/libata.h index 3e33ee30628d..5db8a2e3f051 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -722,7 +722,8 @@ 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 */ + unsigned int nr_luns; /* valid entries in sdev[] */ void *private_data; #ifdef CONFIG_ATA_ACPI union acpi_object *gtf_cache; @@ -1715,6 +1716,14 @@ static inline unsigned int ata_dev_absent(const stru= ct ata_device *dev) return ata_class_absent(dev->class); } =20 +static inline struct scsi_device * +ata_dev_scsi_device(struct ata_device *dev, unsigned int lun) +{ + if (WARN_ON_ONCE(lun >=3D dev->nr_luns)) + return NULL; + return dev->sdev[lun]; +} + /* * link helpers */ --=20 2.43.0 From nobody Fri Jun 12 20:24:00 2026 Received: from nick.sneptech.io (nick.sneptech.io [178.62.38.78]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 7914C3AFCEA; Mon, 8 Jun 2026 21:52:02 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=178.62.38.78 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780955523; cv=none; b=Su2seWd/88EpPrAuCwDQIWrHu2aDGt06JYv8S1IH8i9f4s5TqUhvk0Jd9z94OBFJXCCYVynBT0lMuoplsSWqjzd3njybqo+AkzS7kdbq+hsdAe7bD1rjbDPSJ9+oVfVzl4jsQrRPiyqDXSvLNEIurUBS724b0tCBly2LK8PSy+E= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780955523; c=relaxed/simple; bh=TvxDQEo20GxcEfBjGwo/dMBpT4kGWwqB2G0X2IUMJE4=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=gkpgCxNRYyP3bzbvQBa7RZfflKOaJ/XTO+ZuK7d/hsK3hE0PZ3uKqfSvyCvaP8M1ZOx06DwVa/oYdP7GE2kF9EJ1NYLCaXFhTneUZk60KzzuQphK82Lb6VuWIx7OERW5Rro9SAj7uRVn1TxapCWV6vdfZGtM0NWSpb18O3jY9eM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=philpem.me.uk; spf=pass smtp.mailfrom=philpem.me.uk; dkim=pass (1024-bit key) header.d=philpem.me.uk header.i=@philpem.me.uk header.b=HGMOtsNb; arc=none smtp.client-ip=178.62.38.78 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=philpem.me.uk Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=philpem.me.uk Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=philpem.me.uk header.i=@philpem.me.uk header.b="HGMOtsNb" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=philpem.me.uk; s=mail; t=1780954491; bh=TvxDQEo20GxcEfBjGwo/dMBpT4kGWwqB2G0X2IUMJE4=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=HGMOtsNbS4j07G+N6YVpuMXnlp6DcP5TRcVltvnzamlDfh6dkxV8EE+InSL6kls8q 7NjkFAAEWFEhjln0k/+eupdG7j/MaTh13O+2gtBzNiv0XkFnfKWeGeO+1xr0dOEP6Z U+z7XkO1TVNr3GG7vIDQXuYS0TXQr6mPWFnYffVk= Received: from wolf.philpem.me.uk (81-187-163-148.ip4.reverse-dns.uk [81.187.163.148]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) (Authenticated sender: mailrelay_wolf@philpem.me.uk) by nick.sneptech.io (Postfix) with ESMTPSA id 5A25ABE6EB; Mon, 8 Jun 2026 21:34:51 +0000 (UTC) Received: from cheetah.homenet.philpem.me.uk (cheetah.homenet.philpem.me.uk [10.0.0.32]) by wolf.philpem.me.uk (Postfix) with ESMTPSA id 0266B5FC4B; Mon, 8 Jun 2026 22:34:51 +0100 (BST) From: Phil Pemberton To: linux-ide@vger.kernel.org, linux-scsi@vger.kernel.org Cc: linux-kernel@vger.kernel.org, Damien Le Moal , Niklas Cassel , "James E . J . Bottomley" , "Martin K . Petersen" , Hannes Reinecke , Phil Pemberton Subject: [PATCH v6 3/6] ata: libata-scsi: route non-zero LUN commands for multi-LUN ATAPI Date: Mon, 8 Jun 2026 22:34:40 +0100 Message-ID: <20260608213443.2296614-4-philpem@philpem.me.uk> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260608213443.2296614-1-philpem@philpem.me.uk> References: <20260608213443.2296614-1-philpem@philpem.me.uk> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" 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. Hoist a non-zero LUN early-exit ahead of the original channel/id checks: when scsidev->lun is non-zero, allow it through only if the underlying ata_device is ATAPI class. The original LUN-0 path is left structurally unchanged. 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. The SCSI layer caps the LUN at shost->max_lun, so a value beyond the device's nr_luns should never reach this point; guard with WARN_ON_ONCE() and return AC_ERR_INVALID if it does, since the 3-bit CDB field cannot represent it. Signed-off-by: Phil Pemberton Reviewed-by: Hannes Reinecke --- drivers/ata/libata-scsi.c | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index 7c3d31dc49a1..2d714efc855f 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -2953,6 +2953,15 @@ 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); =20 + /* + * SCSI-2 CDB LUN encoding: bits 7:5 of byte 1 (3-bit field). + * The SCSI layer caps the LUN at shost->max_lun (<=3D ATAPI_MAX_LUN), + * so this should never trip; warn and reject if it does. + */ + if (WARN_ON_ONCE(scmd->device->lun >=3D dev->nr_luns)) + return AC_ERR_INVALID; + qc->cdb[1] =3D (qc->cdb[1] & 0x1f) | ((u8)scmd->device->lun << 5); + qc->complete_fn =3D atapi_qc_complete; =20 qc->tf.flags |=3D ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE; @@ -3063,6 +3072,29 @@ static struct ata_device *__ata_scsi_find_dev(struct= ata_port *ap, { int devno; =20 + /* + * Non-zero LUN is only legal for ATAPI devices, since they can + * legitimately expose more than one LUN (PD/CD combos, CD changers). + * Handle that case up front so the LUN-0 path below stays unchanged. + */ + if (unlikely(scsidev->lun)) { + struct ata_device *dev; + + if (!sata_pmp_attached(ap)) { + if (unlikely(scsidev->channel)) + return NULL; + devno =3D scsidev->id; + } else { + if (unlikely(scsidev->id)) + return NULL; + devno =3D scsidev->channel; + } + dev =3D ata_find_dev(ap, devno); + if (!dev || dev->class !=3D ATA_DEV_ATAPI) + return NULL; + return dev; + } + /* skip commands not addressed to targets we simulate */ if (!sata_pmp_attached(ap)) { if (unlikely(scsidev->channel || scsidev->lun)) --=20 2.43.0 From nobody Fri Jun 12 20:24:00 2026 Received: from nick.sneptech.io (nick.sneptech.io [178.62.38.78]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 90D383AFD1F; Mon, 8 Jun 2026 21:57:02 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=178.62.38.78 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780955825; cv=none; b=X5E5IxiG9F7GbVOi6ZaXtvEVlaEhCbZOQhZcLJkwg4NHzoEOwBZaQaTwKcJT/FftlOGEuT16xC1E9HkKaRCT167u1w1spBs9PW69C6VUY3SiM+nnKG+nKuexUvBpD0Hc3j/p3NCaQfSxVMkMxyY/cegPNj0EcKWf6HVMRyKGl/U= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780955825; c=relaxed/simple; bh=Qn3vwVigO0URt2j33/EaXlxCUk+kPReoOtoKacUnLik=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=A106hDyB62SQ0Fkzh4v6hRCXpGVq2CG4mqcC2sFhYYKd8GP3xkPDjXD2IMrCeu5Q7CwjtiPFEUZ9+F89ZLbWS9gHoCsREvlihcmjLu80okBqBxgiBq8DWMIwc/C0tuiak1tkw5DIeR1ga8cc3IzQgKygP3QnY8K0sWKSB8bZlBM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=philpem.me.uk; spf=pass smtp.mailfrom=philpem.me.uk; dkim=pass (1024-bit key) header.d=philpem.me.uk header.i=@philpem.me.uk header.b=q4Qc/diM; arc=none smtp.client-ip=178.62.38.78 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=philpem.me.uk Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=philpem.me.uk Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=philpem.me.uk header.i=@philpem.me.uk header.b="q4Qc/diM" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=philpem.me.uk; s=mail; t=1780954491; bh=Qn3vwVigO0URt2j33/EaXlxCUk+kPReoOtoKacUnLik=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=q4Qc/diMJSpG2jFVEV6HaJKSwQ79jFCSBbJTIc3oEiN2UDf6UClEFQ/2bABtoDLsi e0ZkLq8DmKHFNmpNuZG7pSHENYqq9nTrDFmMjWLvsQiX3zr0VGElugJjdUIlt5QkBg NFKm1LglVBvRbzquvpVGHcm1GjfUKgZpvGydTkTs= Received: from wolf.philpem.me.uk (81-187-163-148.ip4.reverse-dns.uk [81.187.163.148]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) (Authenticated sender: mailrelay_wolf@philpem.me.uk) by nick.sneptech.io (Postfix) with ESMTPSA id 63E8BBE6EC; Mon, 8 Jun 2026 21:34:51 +0000 (UTC) Received: from cheetah.homenet.philpem.me.uk (cheetah.homenet.philpem.me.uk [10.0.0.32]) by wolf.philpem.me.uk (Postfix) with ESMTPSA id 12F7A5FC4E; Mon, 8 Jun 2026 22:34:51 +0100 (BST) From: Phil Pemberton To: linux-ide@vger.kernel.org, linux-scsi@vger.kernel.org Cc: linux-kernel@vger.kernel.org, Damien Le Moal , Niklas Cassel , "James E . J . Bottomley" , "Martin K . Petersen" , Hannes Reinecke , Phil Pemberton Subject: [PATCH v6 4/6] scsi: add BLIST_NO_LUN_1F blacklist flag Date: Mon, 8 Jun 2026 22:34:41 +0100 Message-ID: <20260608213443.2296614-5-philpem@philpem.me.uk> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260608213443.2296614-1-philpem@philpem.me.uk> References: <20260608213443.2296614-1-philpem@philpem.me.uk> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Some multi-LUN devices respond to INQUIRY on unpopulated LUNs with PQ=3D0 / PDT=3D0x1f instead of the standard PQ=3D3. The SCSI scan layer normally adds such devices (PQ=3D0 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 Reviewed-by: Hannes Reinecke --- drivers/scsi/scsi_scan.c | 2 ++ include/scsi/scsi_devinfo.h | 6 +++--- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c index ef22a4228b85..bfbbf9be05d2 100644 --- a/drivers/scsi/scsi_scan.c +++ b/drivers/scsi/scsi_scan.c @@ -1069,6 +1069,8 @@ static int scsi_add_lun(struct scsi_device *sdev, uns= igned char *inq_result, transport_configure_device(&sdev->sdev_gendev); =20 sdev->sdev_bflags =3D *bflags; + if (sdev->sdev_bflags & BLIST_NO_LUN_1F) + sdev->sdev_target->pdt_1f_for_no_lun =3D 1; =20 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 | \ --=20 2.43.0 From nobody Fri Jun 12 20:24:00 2026 Received: from nick.sneptech.io (nick.sneptech.io [178.62.38.78]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id D97072E9729; Mon, 8 Jun 2026 21:34:59 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=178.62.38.78 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780954502; cv=none; b=EObORNGKhVvmWp6THv4VizxNg6f2hlnNCK9e9bH9cyg28siFLEbaIMIfYqrryUEPKDQnR+X0EOzJCHLVKl2ePuJaPjSxsCm2Ue94DgPhmUg5FiqFrkbhXfkFOg82Zo1RjY4kPVDO3tlqGNFZkX6RFzeStKN1RDICl7buiPLMHJk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780954502; c=relaxed/simple; bh=2Zw3vbvV8x4GK8JZGJ5RHUORMcfvOnvV4537sQAvgsk=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=lUzIpDHMY9rMMmuT41946lcyG98P7RPnITNHx2h+a70ehW7M0UFwNo0nV0m0x52kKbQZEyboya/ADBfZEVralcsfuAg39dfJAy7OvischzFZMWmctH41KqWbfjuD4EJc1Ef7Pq8UlDCJigjiFIwbViXEOozHhGndkb+FuMMTHLg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=philpem.me.uk; spf=pass smtp.mailfrom=philpem.me.uk; dkim=pass (1024-bit key) header.d=philpem.me.uk header.i=@philpem.me.uk header.b=U6TBUtIB; arc=none smtp.client-ip=178.62.38.78 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=philpem.me.uk Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=philpem.me.uk Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=philpem.me.uk header.i=@philpem.me.uk header.b="U6TBUtIB" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=philpem.me.uk; s=mail; t=1780954491; bh=2Zw3vbvV8x4GK8JZGJ5RHUORMcfvOnvV4537sQAvgsk=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=U6TBUtIBmVrjngcikqOas574rgOrKoEECqKy1zZoLX3+ZtoTQtSbSFGdC9t1nIXfv r5bGWJuMC7cEqkWmrou9znw/U0tGzHI0o1u1Fyafo3YLf3xYpPhpOwSQzcO7uxwe4w 2WwI20Ir/yJfqKqSJZjO7s5VrTcoMNVfEBLbW4Oc= Received: from wolf.philpem.me.uk (81-187-163-148.ip4.reverse-dns.uk [81.187.163.148]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) (Authenticated sender: mailrelay_wolf@philpem.me.uk) by nick.sneptech.io (Postfix) with ESMTPSA id 81A10BE731; Mon, 8 Jun 2026 21:34:51 +0000 (UTC) Received: from cheetah.homenet.philpem.me.uk (cheetah.homenet.philpem.me.uk [10.0.0.32]) by wolf.philpem.me.uk (Postfix) with ESMTPSA id 1ABA65FC4F; Mon, 8 Jun 2026 22:34:51 +0100 (BST) From: Phil Pemberton To: linux-ide@vger.kernel.org, linux-scsi@vger.kernel.org Cc: linux-kernel@vger.kernel.org, Damien Le Moal , Niklas Cassel , "James E . J . Bottomley" , "Martin K . Petersen" , Hannes Reinecke , Phil Pemberton Subject: [PATCH v6 5/6] ata: libata-scsi: probe additional LUNs for multi-LUN ATAPI devices Date: Mon, 8 Jun 2026 22:34:42 +0100 Message-ID: <20260608213443.2296614-6-philpem@philpem.me.uk> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260608213443.2296614-1-philpem@philpem.me.uk> References: <20260608213443.2296614-1-philpem@philpem.me.uk> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" After LUN 0 is added for an ATAPI device, check its BLIST_FORCELUN flag. If set, bump dev->nr_luns to the host's max_lun so the LUN routing in atapi_xlat() accepts the probe INQUIRYs, then call scsi_scan_target() with SCAN_WILD_CARD to trigger the SCSI layer's built-in sequential LUN scan for that target only. This probes LUNs 1..shost->max_lun, driven by the libata atapi_max_lun module parameter. Devices without BLIST_FORCELUN (the vast majority of ATAPI devices) are left with only LUN 0 -- no sequential scan is triggered, so single-LUN devices like the iHAS124 DVD writer are completely unaffected. Non-responding LUNs (PQ=3D0/PDT=3D0x1f) are silently skipped by scsi_probe_and_add_lun() when BLIST_NO_LUN_1F is set on the device via scsi_devinfo. Signed-off-by: Phil Pemberton Reviewed-by: Hannes Reinecke --- drivers/ata/libata-scsi.c | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index 2d714efc855f..a6f5557014c7 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -4745,12 +4746,30 @@ void ata_scsi_scan_host(struct ata_port *ap, int sy= nc) sdev =3D __scsi_add_device(ap->scsi_host, channel, id, 0, NULL); if (!IS_ERR(sdev)) { - dev->sdev[0] =3D sdev; - ata_scsi_assign_ofnode(dev, ap); + /* + * For multi-LUN ATAPI (BLIST_FORCELUN), bump + * dev->nr_luns to the host max so the LUN + * routing in atapi_xlat() accepts the probe + * INQUIRYs to LUN > 0, then trigger the + * sequential 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. + */ + if (dev->class =3D=3D ATA_DEV_ATAPI && + sdev->sdev_bflags & BLIST_FORCELUN) { + dev->nr_luns =3D ap->scsi_host->max_lun; + scsi_scan_target( + &ap->scsi_host->shost_gendev, + channel, id, SCAN_WILD_CARD, + SCSI_SCAN_RESCAN); + } scsi_device_put(sdev); - } else { - dev->sdev[0] =3D NULL; } + + if (dev->sdev[0]) + ata_scsi_assign_ofnode(dev, ap); } } =20 --=20 2.43.0 From nobody Fri Jun 12 20:24:00 2026 Received: from nick.sneptech.io (nick.sneptech.io [178.62.38.78]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id D977731E85C; Mon, 8 Jun 2026 21:34:59 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=178.62.38.78 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780954501; cv=none; b=FwnGDIUs1CFJDv36GIlob1XXKQND0vcU7bdVdcHv25dwS5NUjrN9Ll7pxeoiaaA+6xgJCWqItV6UENWVJzryZ9aL+/9mStB0C1KrrtSrHXlsGIET4roe4uq0JlGA9HRpR3WzUrzfV291k0bg7KqNomtkKW6SGdDisdVxFPYOZFU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780954501; c=relaxed/simple; bh=NgI+BloTluXJ7eZWq4tfe6pWs03z++jaiAMs+De/a1I=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=l4+GloB8ZqhVm83m+ZKw1+9roacXBoE/7wFU1zGhjVOznvbK1fFdr5rv0q3AJrUj/hoTjTKWCyUQr74sOi5oa8jNCeG6RYX6eWc+hE1ppbn5ZTu/vNmLVb0xUZ3OKvWTgavquthjE1Z0orbyDiAtYIoloOgkq/mFJ0nT9XHwSQw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=philpem.me.uk; spf=pass smtp.mailfrom=philpem.me.uk; dkim=pass (1024-bit key) header.d=philpem.me.uk header.i=@philpem.me.uk header.b=ablupl2Y; arc=none smtp.client-ip=178.62.38.78 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=philpem.me.uk Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=philpem.me.uk Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=philpem.me.uk header.i=@philpem.me.uk header.b="ablupl2Y" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=philpem.me.uk; s=mail; t=1780954491; bh=NgI+BloTluXJ7eZWq4tfe6pWs03z++jaiAMs+De/a1I=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=ablupl2YeRod29tWxeh0JJwSI+GG9HxBf+sKqgKP65Gs4h3oxT6vMiJS1f2HzGThZ 9G/PVc+9bHEBzJYZjgwocPGU/054DzFaQWz6THlp8GvA/9toK6QLWhPzfaO72fnZkE NvwHZTONZ5qpmbZmdLaVqPbmx4CCfVGhLQrU3JIM= Received: from wolf.philpem.me.uk (81-187-163-148.ip4.reverse-dns.uk [81.187.163.148]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) (Authenticated sender: mailrelay_wolf@philpem.me.uk) by nick.sneptech.io (Postfix) with ESMTPSA id 86F0DBECDE; Mon, 8 Jun 2026 21:34:51 +0000 (UTC) Received: from cheetah.homenet.philpem.me.uk (cheetah.homenet.philpem.me.uk [10.0.0.32]) by wolf.philpem.me.uk (Postfix) with ESMTPSA id 2AB245FC53; Mon, 8 Jun 2026 22:34:51 +0100 (BST) From: Phil Pemberton To: linux-ide@vger.kernel.org, linux-scsi@vger.kernel.org Cc: linux-kernel@vger.kernel.org, Damien Le Moal , Niklas Cassel , "James E . J . Bottomley" , "Martin K . Petersen" , Hannes Reinecke , Phil Pemberton Subject: [PATCH v6 6/6] scsi: scsi_devinfo: add COMPAQ PD-1 multi-LUN ATAPI device quirk Date: Mon, 8 Jun 2026 22:34:43 +0100 Message-ID: <20260608213443.2296614-7-philpem@philpem.me.uk> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260608213443.2296614-1-philpem@philpem.me.uk> References: <20260608213443.2296614-1-philpem@philpem.me.uk> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" 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=3D0/PDT=3D0x1f for unpopulated LUNs instead of PQ=3D3; 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" Reviewed-by: Damien Le Moal Reviewed-by: Hannes Reinecke Signed-off-by: Phil Pemberton --- 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}, --=20 2.43.0