From nobody Fri Oct 2 12:21:54 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 26191330652; Fri, 31 Jul 2026 21:52:38 +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=1785534761; cv=none; b=U12NBNtUgLiN7hkWcRoOlaEsL98hBM5a28A98oCuoe03/XRrAD7x8z4ZNOYY+cGXF4VktvqYytXewnZ+Wwxl0GO07027w8sW/S7NBdZ0qrXyg7hY9E8xr9PLJq+2TN+zr8iv4YqQt3N1HiAfAHxTL77l+0SLu5g0SOmco1OifLw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785534761; c=relaxed/simple; bh=KmYDoaG4A48TfWLPr9n3qq3A7tpoeNcbyOaCXiKLn20=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=KtHrYQxkyBh0shZGxldGj6/eci73mR6fIuwkh7LtfW+V84jMDH/94gIGNDU20ZwVTfRsb2FoQf9jX2DFVSqtnJk9PzEv5gTiW5X+c+pvy1oEfDfCx54bqZwIpC5Ntcakfs+b4azv/B/SSzSiplrXbKXAN+RKIlU865f1JKHkm5s= 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=Vm1lg9Mk; 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="Vm1lg9Mk" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=philpem.me.uk; s=mail; t=1785533714; bh=KmYDoaG4A48TfWLPr9n3qq3A7tpoeNcbyOaCXiKLn20=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Vm1lg9Mk2gWjfHXA6TdM9KqldSsQahQ6dA3KCd8/gcnBd25tgsCSAIE3F+XpwL2yy QP5WLb1vHm/F/ni5+2Pkg6+3mfB5eiXcsUTOZUuGyy5ck0HnBax+C5BEdMIBnEH8u8 HI7fC6e1SKd7nz7kbb711azQ8AYD6FpWFauelXrQ= 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 9FC2EBD752; Fri, 31 Jul 2026 21:35:14 +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 5FB905FBAF; Fri, 31 Jul 2026 22:35:14 +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 v8 1/6] ata: libata-scsi: add atapi_max_lun module parameter Date: Fri, 31 Jul 2026 22:34:58 +0100 Message-ID: <20260731213503.2379771-2-philpem@philpem.me.uk> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260731213503.2379771-1-philpem@philpem.me.uk> References: <20260731213503.2379771-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, covering LUN values 0..7). 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 Reviewed-by: Damien Le Moal 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 d893c916df0b..15ee44cf5bf2 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, + "Number of LUNs to scan on ATAPI devices flagged BLIST_FORCELUN (1 [defau= lt] =3D LUN 0 only, 8 =3D all SCSI-2 LUNs 0..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 1d225ee9eb86..04c96f3fd865 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -5154,7 +5154,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 39494ab206a2..7ee3bf1a4789 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 18edb36c29fc..25e4b671adfb 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -180,6 +180,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 Oct 2 12:21:54 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 1B62023909C; Fri, 31 Jul 2026 21:52:37 +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=1785534760; cv=none; b=rbcMAHLQCo9mtu3sqKUHbJIKwbRpv+5xY0WaPvuW8Xbc+4+lcLDoYXPg89AHzSHkzZ6MjRAyE/PlcFny8QXjoDFd6n3shEWsDUv7juAbuGSIorBm2xLlTHr/sdaQs/lDbUGKTsckoVRdTOYuNFC75ETS9YpYDzlLOTjADKpWAEQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785534760; c=relaxed/simple; bh=1qXhhcSBbR6q3oRuRSC8m6v2yz99JU7pcv2nUTDFztY=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=rHu+nbbPDTxg+tD9tSsa5l8LiKZJthnNJy8D5m0iB8iJxeJzTx0WYRX0mld7Cr0o1KBNa6Qk0zczISAdAu/Gkdv8kIVoidTJw8kdD0cBVVsG7Qa+Ig8aEja7eWICl/RUO1up4XtFV9CdnuB6ufxXuTH4jonDGBVl7yaFy/M7m3U= 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=b7dDmzcN; 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="b7dDmzcN" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=philpem.me.uk; s=mail; t=1785533714; bh=1qXhhcSBbR6q3oRuRSC8m6v2yz99JU7pcv2nUTDFztY=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=b7dDmzcNWtSb6v+YQ004g2uKS2jHQRpGT+YpHuwwjhsrkLvWRM2mOEoSa0XqANhcg vSQJgzmU6zvYHXYlt4hsHLu+ylH4EseN75xdlNBGrfaR+aMYiMtfah+FW40748+owZ EZinD31iaAYjc80mDEHouEWJvbvlHKipdbVN4nT0= 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 AF712BE527; Fri, 31 Jul 2026 21:35:14 +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 6FA1C5FC31; Fri, 31 Jul 2026 22:35:14 +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 , Hannes Reinecke Subject: [PATCH v8 2/6] ata: libata-scsi: convert dev->sdev to per-LUN array Date: Fri, 31 Jul 2026 22:34:59 +0100 Message-ID: <20260731213503.2379771-3-philpem@philpem.me.uk> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260731213503.2379771-1-philpem@philpem.me.uk> References: <20260731213503.2379771-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). All callers are updated to iterate the full array and skip NULL slots; only populated LUN slots are ever non-NULL so single-LUN devices (the vast majority) see no change in behaviour. Add an inline helper ata_dev_scsi_device(dev, lun) that returns dev->sdev[lun] guarded by a WARN_ON_ONCE(lun >=3D ATAPI_MAX_LUN) bounds check. Use it for the hardcoded LUN-0 references in libata-acpi (uevent kobj), libata-zpodd (disk events, wake notify for all LUNs), and the door-lock and OF-node paths in libata-scsi. Key changes per call site: - ata_scsi_dev_config: bounds-check lun, assign sdev to dev->sdev[sdev= ->lun] - ata_scsi_sdev_destroy: clear per-LUN slot; trigger ATA detach only when the last populated LUN is destroyed - ata_port_detach: iterate all ATAPI_MAX_LUN slots descending; clear dev->sdev[lun] before unlock to close the UAF window (Hannes Reinecke) - ata_scsi_offline_dev: iterate all slots - ata_scsi_remove_dev: snapshot all LUN slots then remove outside lock - ata_scsi_media_change_notify: send event to all populated LUNs - ata_scsi_dev_rescan: snapshot all LUNs under lock, then resume and rescan each; release remaining refs on early ex= it - ACPI, ZPODD, door-lock: use ata_dev_scsi_device(dev, 0) - ZPODD disk-events: iterate all LUNs for enable/disable and wake Reviewed-by: Hannes Reinecke Signed-off-by: Phil Pemberton --- drivers/ata/libata-acpi.c | 9 +- drivers/ata/libata-core.c | 11 ++- drivers/ata/libata-scsi.c | 164 +++++++++++++++++++++---------------- drivers/ata/libata-zpodd.c | 27 ++++-- include/linux/libata.h | 10 ++- 5 files changed, 138 insertions(+), 83 deletions(-) diff --git a/drivers/ata/libata-acpi.c b/drivers/ata/libata-acpi.c index 4433f626246b..2d1662f6f064 100644 --- a/drivers/ata/libata-acpi.c +++ b/drivers/ata/libata-acpi.c @@ -153,10 +153,13 @@ static void ata_acpi_uevent(struct ata_port *ap, stru= ct ata_device *dev, char *envp[] =3D { event_string, NULL }; =20 if (dev) { - if (dev->sdev) - kobj =3D &dev->sdev->sdev_gendev.kobj; - } else + 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 if (kobj) { snprintf(event_string, 20, "BAY_EVENT=3D%d", event); diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 15ee44cf5bf2..43d5221dc347 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -6381,11 +6381,16 @@ 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 ATAPI_MAX_LUN - 1; lun >=3D 0; lun--) { + struct scsi_device *sdev =3D dev->sdev[lun]; + if (!sdev) + continue; + dev->sdev[lun] =3D NULL; spin_unlock_irqrestore(ap->lock, flags); - scsi_remove_device(dev->sdev); + scsi_remove_device(sdev); spin_lock_irqsave(ap->lock, flags); - dev->sdev =3D NULL; } } } diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index 04c96f3fd865..808368b952b5 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -1129,7 +1129,9 @@ 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; + if (WARN_ON_ONCE(sdev->lun >=3D ATAPI_MAX_LUN)) + return -EINVAL; + dev->sdev[sdev->lun] =3D sdev; return 0; } =20 @@ -1200,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. @@ -1218,11 +1220,23 @@ 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 && !WARN_ON_ONCE(sdev->lun >=3D ATAPI_MAX_LUN) && + dev->sdev[sdev->lun] =3D=3D sdev) { + int lun; + bool last; + + dev->sdev[sdev->lun] =3D NULL; + last =3D true; + for (lun =3D 0; lun < ATAPI_MAX_LUN; lun++) { + if (dev->sdev[lun]) { + last =3D false; + break; + } + } + if (last) { + dev->flags |=3D ATA_DFLAG_DETACH; + ata_port_schedule_eh(ap); + } } spin_unlock_irqrestore(ap->lock, flags); =20 @@ -2963,12 +2977,9 @@ static void atapi_qc_complete(struct ata_queued_cmd = *qc) * * If door lock fails, always clear sdev->locked to * avoid this infinite loop. - * - * This may happen before SCSI scan is complete. Make - * sure qc->dev->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) + qc->scsicmd->device->locked =3D 0; =20 ata_scsi_qc_done(qc, true, SAM_STAT_CHECK_CONDITION); return; @@ -5185,7 +5196,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; @@ -5223,7 +5234,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)) @@ -5234,11 +5245,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; } } } @@ -5249,7 +5260,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; } } @@ -5290,7 +5301,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) @@ -5300,11 +5311,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 ATAPI_MAX_LUN - 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 /** @@ -5320,49 +5336,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 ATAPI_MAX_LUN - 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 ATAPI_MAX_LUN - 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 @@ -5399,9 +5404,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 < ATAPI_MAX_LUN; lun++) + if (dev->sdev[lun]) + sdev_evt_send_simple(dev->sdev[lun], + SDEV_EVT_MEDIA_CHANGE, GFP_ATOMIC); } =20 /** @@ -5534,7 +5542,8 @@ 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; + struct scsi_device *sdevs[ATAPI_MAX_LUN] =3D {}; + int lun; =20 /* * If the port was suspended before this was scheduled, @@ -5543,28 +5552,43 @@ void ata_scsi_dev_rescan(struct work_struct *work) if (ap->pflags & ATA_PFLAG_SUSPENDED) goto unlock_ap; =20 - if (!sdev) - continue; - if (scsi_device_get(sdev)) - continue; + for (lun =3D 0; lun < ATAPI_MAX_LUN; lun++) { + if (dev->sdev[lun] && + !scsi_device_get(dev->sdev[lun])) + sdevs[lun] =3D dev->sdev[lun]; + } =20 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 < ATAPI_MAX_LUN; lun++) { + if (!sdevs[lun]) + continue; + + spin_unlock_irqrestore(ap->lock, flags); + if (do_resume) { + ret =3D scsi_resume_device(sdevs[lun]); + if (ret =3D=3D -EWOULDBLOCK) { + scsi_device_put(sdevs[lun]); + while (++lun < ATAPI_MAX_LUN) + if (sdevs[lun]) + scsi_device_put(sdevs[lun]); + goto unlock_scan; + } + } + ret =3D scsi_rescan_device(sdevs[lun]); + scsi_device_put(sdevs[lun]); + spin_lock_irqsave(ap->lock, flags); + + if (ret) { + while (++lun < ATAPI_MAX_LUN) + if (sdevs[lun]) + scsi_device_put(sdevs[lun]); + goto unlock_ap; } - dev->flags &=3D ~ATA_DFLAG_RESUMING; } - 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..151ae5726aca 100644 --- a/drivers/ata/libata-zpodd.c +++ b/drivers/ata/libata-zpodd.c @@ -184,8 +184,13 @@ bool zpodd_zpready(struct ata_device *dev) void zpodd_enable_run_wake(struct ata_device *dev) { struct zpodd *zpodd =3D dev->zpodd; + int lun; =20 - sdev_disable_disk_events(dev->sdev); + for (lun =3D 0; lun < ATAPI_MAX_LUN; lun++) { + struct scsi_device *sdev =3D dev->sdev[lun]; + if (sdev) + sdev_disable_disk_events(sdev); + } =20 zpodd->powered_off =3D true; acpi_pm_set_device_wakeup(&dev->tdev, true); @@ -218,6 +223,7 @@ void zpodd_disable_run_wake(struct ata_device *dev) void zpodd_post_poweron(struct ata_device *dev) { struct zpodd *zpodd =3D dev->zpodd; + int lun; =20 if (!zpodd->powered_off) return; @@ -233,18 +239,27 @@ 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); + for (lun =3D 0; lun < ATAPI_MAX_LUN; lun++) { + struct scsi_device *sdev =3D dev->sdev[lun]; + if (sdev) + sdev_enable_disk_events(sdev); + } } =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; + int lun; =20 - if (event =3D=3D ACPI_NOTIFY_DEVICE_WAKE && pm_runtime_suspended(dev)) { - zpodd->from_notify =3D true; - pm_runtime_resume(dev); + if (event !=3D ACPI_NOTIFY_DEVICE_WAKE) + return; + for (lun =3D 0; lun < ATAPI_MAX_LUN; lun++) { + struct scsi_device *sdev =3D ata_dev->sdev[lun]; + if (sdev && pm_runtime_suspended(&sdev->sdev_gendev)) { + zpodd->from_notify =3D true; + pm_runtime_resume(&sdev->sdev_gendev); + } } } =20 diff --git a/include/linux/libata.h b/include/linux/libata.h index 25e4b671adfb..3b9207a9f334 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -733,7 +733,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; @@ -1726,6 +1726,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 ATAPI_MAX_LUN)) + return NULL; + return dev->sdev[lun]; +} + /* * link helpers */ --=20 2.43.0 From nobody Fri Oct 2 12:21:54 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 1B7A4330307; Fri, 31 Jul 2026 21:52:38 +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=1785534760; cv=none; b=VR+UH+0S0ABHhi9cz5kxBq5s030POomHRjY5JWDTS4EVxd29+T4KPs3RlG8pxGHEiJFFjS2iA+1yyl/S381C92UEqSF70Se8L4UYQc0qgSIu5Mcoulvq5klHvonX3yWf0Vj6QKc/bekqghJ9L1vDJFO00Qh+/oGWaaAZDkwFdwg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785534760; c=relaxed/simple; bh=MnZ1hre2Kf21Dyn7ZNb8A7WsTa84hKx8Xk3evhQYboQ=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Ox70q+Vim8nKFnBrtQkVS9U4P3BUh4HVZYIGJXZ4c/3qMEE/x4NQV1lCO/MSzTnOydUCWhV1OmQ0/OfIOaM9jHefzM017ODIZDih6FdmU0b9lRIvF6c8O+qem4db72dFS5HztNe9s9iNrA/PAuoAJwEiM72GeTLDuDWfh1QRzVU= 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=XoeDqw39; 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="XoeDqw39" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=philpem.me.uk; s=mail; t=1785533714; bh=MnZ1hre2Kf21Dyn7ZNb8A7WsTa84hKx8Xk3evhQYboQ=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=XoeDqw399ztBF14+LuigMKXg9ZYz0IdslGqEU4DCHZeAmDGv0z9uKu6WTwjkVeJOz lY8S1pAI3QPqa7zv5ygPX8Mh8I6WfYs4gpHMAwttnUqkIEjl2VlbIrniTk5Ianjm5F nNF9pHs/AVLcAUeiVNFoZds4LUkAAHvmqncRzB7M= 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 BA77CBE539; Fri, 31 Jul 2026 21:35:14 +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 840585FC3D; Fri, 31 Jul 2026 22:35:14 +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 , Hannes Reinecke Subject: [PATCH v8 3/6] ata: libata-scsi: route non-zero LUN commands for multi-LUN ATAPI Date: Fri, 31 Jul 2026 22:35:00 +0100 Message-ID: <20260731213503.2379771-4-philpem@philpem.me.uk> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260731213503.2379771-1-philpem@philpem.me.uk> References: <20260731213503.2379771-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. Always clear those bits first, then encode scmd->device->lun into them for non-zero LUNs. This is required by both the Panasonic PD/CD combos and Nakamichi CD changers. Guard with WARN_ON_ONCE() and fail the command (setting scmd->result to DID_ERROR) if the LUN is out of range, since the 3-bit CDB field cannot represent it. Reviewed-by: Hannes Reinecke Signed-off-by: Phil Pemberton --- drivers/ata/libata-scsi.c | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index 808368b952b5..0b1e4842860c 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -3012,6 +3012,20 @@ 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). + * Always clear those bits; only set them for non-zero LUNs. + */ + qc->cdb[1] =3D qc->cdb[1] & 0x1f; + if (unlikely(scmd->device->lun)) { + if (WARN_ON_ONCE(scmd->device->host->max_lun > ATAPI_MAX_LUN || + scmd->device->lun >=3D scmd->device->host->max_lun)) { + scmd->result =3D DID_ERROR << 16; + return 1; + } + qc->cdb[1] |=3D (u8)scmd->device->lun << 5; + } + qc->complete_fn =3D atapi_qc_complete; =20 qc->tf.flags |=3D ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE; @@ -3122,6 +3136,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 Oct 2 12:21:54 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 4BEA4331EB1; Fri, 31 Jul 2026 21:35:24 +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=1785533725; cv=none; b=hUljsbTIXuALaoPH/SOvT3mA2iyKYdCoclciZpL8qS7Y1JeHt9FoyqD9kkXhnTBWEUXuvOxo5TQRdMTL3S1swbpM8Oe2MgApUluCI/NVrNtQKWMCvk3q8e6ZVHjYSqdG73s8Ii4ZWKbioBeO1nXv5lUWBruVra6SkBaeM2ZwvTM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785533725; c=relaxed/simple; bh=ESXYlLL9LSnVpycKDLNE3K5jRm2q+89vmOuxy2cnQ5o=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=cw6hQyGOCY7t8PHHKCOs554fJFclRfI4xR1t5ZuNiKdPge92bI1iP4DOGhRWu1TSdrfQV6SR2zt6nNDF1sHzmIrf81Ki4WyPOXnN+2Kr2Zxn6jGGipg7/und8PkNZNw9Z58ORsWSN9pPAvk/9uV4qm420bDkYKE/piob2jliiGw= 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=UeptepJl; 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="UeptepJl" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=philpem.me.uk; s=mail; t=1785533714; bh=ESXYlLL9LSnVpycKDLNE3K5jRm2q+89vmOuxy2cnQ5o=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=UeptepJl1VYjFHitdgexZeJ7MennuagPuT6npa4MetAfcXG7wPaMNZiwdjYtKf8OZ KtEkE7pjbOk9I5uB4Xa80d0lFie/eIz8ZsgA2WxZzs3O4vwNoJoF42V+bt/j1UYdVM ewpaI9fDKCQwqiufeSbsYXbQQob/AGoL8kmoffkM= 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 E7040BE58D; Fri, 31 Jul 2026 21:35:14 +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 93B215FC3E; Fri, 31 Jul 2026 22:35:14 +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 , Hannes Reinecke Subject: [PATCH v8 4/6] scsi: add BLIST_NO_LUN_1F blacklist flag Date: Fri, 31 Jul 2026 22:35:01 +0100 Message-ID: <20260731213503.2379771-5-philpem@philpem.me.uk> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260731213503.2379771-1-philpem@philpem.me.uk> References: <20260731213503.2379771-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_probe_and_add_lun() to set starget->pdt_1f_for_no_lun from the blacklist flags. This is placed immediately before the PDT=3D0x1f check so it takes effect for all LUNs, including LUN 0, without waiting for scsi_add_lun() to run. Reviewed-by: Hannes Reinecke Reviewed-by: Martin K. Petersen Signed-off-by: Phil Pemberton --- 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 e27da038603a..98bd4d49fd62 100644 --- a/drivers/scsi/scsi_scan.c +++ b/drivers/scsi/scsi_scan.c @@ -1296,6 +1296,9 @@ static int scsi_probe_and_add_lun(struct scsi_target = *starget, * PDT=3D00h Direct-access device (floppy) * PDT=3D1Fh none (no FDD connected to the requested logical unit) */ + if (bflags & BLIST_NO_LUN_1F) + starget->pdt_1f_for_no_lun =3D 1; + if (((result[0] >> 5) =3D=3D 1 || starget->pdt_1f_for_no_lun) && (result[0] & 0x1f) =3D=3D 0x1f && !scsi_is_wlun(lun)) { 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 Oct 2 12:21:54 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 1B6A72E03EA; Fri, 31 Jul 2026 21:52:38 +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=1785534759; cv=none; b=AbPIPkMZxEPltZTT+u5fNdudqB//5PRW1w6DAGSEqcZ/TeKuRsEecfEZGFzWtQRJNpR2KoxDoL6rDL/2AG+hLMfzBgcBwm7YYbNKovW6OM9/c9pIRtbeOEBKg78HethJZ8HwehdhbTTlgPFW5KtEVMfDhvtNbR8PzJhjpyEwNR8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785534759; c=relaxed/simple; bh=qUboVyGXEhsRGVvQleQs1ZKSf621X3Pwym0vMk4PeKI=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=SO/xVPXN05oiLOfsUpXUHsgIwiqUJBSH0jkD8ySGkZJU3DBAB/lmQU3nIs1JHD67Ha3gL8ggaZ3ye3cYZhCD/NYQ93Hno9ivF0BX3t3dEx3NiwBtke5vK8L81YuoorClFZ4/xCjzbGdH1RCR/VC2dZJKE+TWPHZjbFsRuGxlxeg= 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=YtRYepYT; 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="YtRYepYT" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=philpem.me.uk; s=mail; t=1785533714; bh=qUboVyGXEhsRGVvQleQs1ZKSf621X3Pwym0vMk4PeKI=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=YtRYepYTJO4/LvcgS5dan5LjgqNmRl0Xj8fEb/HMLL7art1W8MizHCmVCOWvmyZod rG4IXMyPWHHBCH6e370lkczpeXaFZYBQqxYfE1+GNWJpG85J+s01GUTom1/ZU6nYL9 fo6+meiS+krFKSrMUtvK5mYEojP/Hgd913H1NjFQ= 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 E1501BE53E; Fri, 31 Jul 2026 21:35:14 +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 A64875F888; Fri, 31 Jul 2026 22:35:14 +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 , Hannes Reinecke Subject: [PATCH v8 5/6] ata: libata-scsi: probe additional LUNs for multi-LUN ATAPI devices Date: Fri, 31 Jul 2026 22:35:02 +0100 Message-ID: <20260731213503.2379771-6-philpem@philpem.me.uk> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260731213503.2379771-1-philpem@philpem.me.uk> References: <20260731213503.2379771-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, 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. Also fix a TOCTOU window: call ata_scsi_assign_ofnode() before scsi_device_put() so the reference to dev->sdev[0] is held while the OF node is assigned. Reviewed-by: Hannes Reinecke Signed-off-by: Phil Pemberton --- drivers/ata/libata-scsi.c | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index 0b1e4842860c..5bbb3169bea7 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -5281,13 +5282,27 @@ void ata_scsi_scan_host(struct ata_port *ap, int sy= nc) =20 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); - scsi_device_put(sdev); - } else { + if (IS_ERR(sdev)) { dev->sdev[0] =3D NULL; + continue; } + + /* + * For multi-LUN ATAPI (BLIST_FORCELUN), trigger a + * sequential scan for this target. pdt_1f_for_no_lun, + * set during LUN 0 configure, ensures non-responding + * LUNs are silently skipped; dev->sdev[] is populated + * by ata_scsi_dev_config() during the scan. + */ + if (dev->class =3D=3D ATA_DEV_ATAPI && + sdev->sdev_bflags & BLIST_FORCELUN && + !WARN_ON_ONCE(ap->scsi_host->max_lun > ATAPI_MAX_LUN)) + scsi_scan_target(&ap->scsi_host->shost_gendev, + channel, id, SCAN_WILD_CARD, + SCSI_SCAN_RESCAN); + if (dev->sdev[0]) + ata_scsi_assign_ofnode(dev, ap); + scsi_device_put(sdev); } } =20 --=20 2.43.0 From nobody Fri Oct 2 12:21:54 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 4BF3A3368A3; Fri, 31 Jul 2026 21:35:24 +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=1785533726; cv=none; b=U9+7xGH5gAcYd0t4s7oM7L94tL2StjkspaVyNxzOMYSG1UiL0NrTNbFMyHx7sXW4YkP/GbALYy3IaD8ZTXAuxzpW//gLP0RV9bhi/l8k2eokqNSJIGG4efw0jkRScBgpBYI2MO5O1IIS9OJGo+F6BZTx29/Dnlkt92O7zu7Vl34= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785533726; c=relaxed/simple; bh=G5gXHTPV/LDQm7nqGoIIvqdpYM58KIM9+EuE1LnwEeg=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=I+Hps3KiHMKowkPnVJH8/oNNo4KQFEzY2jKrVpQReuRpnDpInKbQee6iqpafW7u0pzMM+rj59TZ10KrcdcoCApQZWAdHeTpUXPhGHDFurupCvMz8sYKb1aNM+0vuGICfb/+pYwp3l6LrBSQiafGQm0gDF0mjODmxO717LX2BIZ4= 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=oNP2V9NG; 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="oNP2V9NG" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=philpem.me.uk; s=mail; t=1785533715; bh=G5gXHTPV/LDQm7nqGoIIvqdpYM58KIM9+EuE1LnwEeg=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=oNP2V9NGJ2DO6yl0tjm0yC+aOR+nc/02yKtw2O+T3rYWuZEo0Scx0Kx9EA+IC2alk GQTcoAQUgt/2S2Jh4KDwkA9+UWbv2TZVIKYXeBWCxJuISh68r/miV9YZwkCSlVnRq/ j6fwMyWOZME2QgvSEckRvUMMT2NEWcqrtUaNlIbk= 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 01B78BE595; Fri, 31 Jul 2026 21:35:14 +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 B28DD5FC4B; Fri, 31 Jul 2026 22:35:14 +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 , Hannes Reinecke Subject: [PATCH v8 6/6] scsi: scsi_devinfo: add COMPAQ PD-1 multi-LUN ATAPI device quirk Date: Fri, 31 Jul 2026 22:35:03 +0100 Message-ID: <20260731213503.2379771-7-philpem@philpem.me.uk> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260731213503.2379771-1-philpem@philpem.me.uk> References: <20260731213503.2379771-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 (and equivalent Panasonic LF-1195C) is a combination PD/CD-ROM drive that exposes two LUNs: LUN 0 is the CD-ROM and LUN 1 is the PD (Phase-change rewritable) drive. Add a scsi_devinfo entry with BLIST_FORCELUN to enable multi-LUN scanning, BLIST_SINGLELUN to prevent issuing LUN-aware commands simultaneously, and BLIST_NO_LUN_1F to suppress spurious "No Device" entries for unpopulated LUNs (which respond with PQ=3D0/PDT=3D0x1f). Reviewed-by: Damien Le Moal Reviewed-by: Hannes Reinecke Reviewed-by: Martin K. Petersen 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 15ffbe93ac72..b3fbfcd5dd93 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