Linux ATA/IDE development
 help / color / mirror / Atom feed
From: Niklas Cassel <cassel@kernel.org>
To: Tommy Kelly <linux@tkel.ly>, Damien Le Moal <dlemoal@kernel.org>,
	Niklas Cassel <cassel@kernel.org>,
	John Garry <john.g.garry@oracle.com>,
	"Martin K. Petersen" <martin.petersen@oracle.com>
Cc: linux-ide@vger.kernel.org
Subject: [PATCH 2/3] ata: libata-scsi: do not use the deferred QC feature on PMPs with CBS
Date: Fri,  1 May 2026 14:54:12 +0200	[thread overview]
Message-ID: <20260501125410.1204490-7-cassel@kernel.org> (raw)
In-Reply-To: <20260501125410.1204490-5-cassel@kernel.org>

When using Port Multipliers (PMPs) with Command-Based Switching (CBS), you
can only issue commands to one link at a time. For PMPs with CBS, there is
already code to handle commands being send to different links in
sata_pmp_qc_defer_cmd_switch(), which will return ATA_DEFER_PORT when
trying to send a command (NCQ or non-NCQ) to the non-active link.

After commit 0ea84089dbf6 ("ata: libata-scsi: avoid Non-NCQ command
starvation"), in addition to the existing handling PMP CBS handling, we
would also, incorrectly, save a non-NCQ command to another link in
ap->deferred_qc. The deferred qc feature was only meant to defer QCs to
the same link, not to duplicate the existing PMP CBS deferal logic when
dealing with separate links.

Note that when deferring commands to the same link (i.e. because NCQ and
non-NCQ commands are mixed), even when using a PMP with CBS, we will use
the deferred_qc feature that issues the deferred qc via a workqueue
(because sata_pmp_qc_defer_cmd_switch() in this case ATA_DEFER_LINK is
returned).

Since the deferred_qc issuing via workqueue was only meant to deal with a
single link, modify the code to feature to only set link->deferred_qc when
deferring a qc to the same link (ATA_DEFER_LINK), and not when deferring a
qc because we are not issuing a qc to the active link (ATA_DEFER_PORT).

If we want to modify the scope of the workqueue issuing to also handle the
case where we issue commands to the link that is not the active link, then
we should ensure that it can save both NCQ and non-NCQ commands, while also
removing some of the existing PMP CBS handling, such that we don't
duplicate features.

Thus, modify ata_scsi_qc_issue() to only use the deferred_qc workqueue for
ATA_DEFER_LINK and not for ATA_DEFER_PORT.

Fixes: 0ea84089dbf6 ("ata: libata-scsi: avoid Non-NCQ command starvation")
Signed-off-by: Niklas Cassel <cassel@kernel.org>
---
 drivers/ata/libata-scsi.c | 27 ++++++++++++++-------------
 1 file changed, 14 insertions(+), 13 deletions(-)

diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
index f44612e269a4..dca7ea7e6315 100644
--- a/drivers/ata/libata-scsi.c
+++ b/drivers/ata/libata-scsi.c
@@ -1785,18 +1785,6 @@ static int ata_scsi_qc_issue(struct ata_port *ap, struct ata_queued_cmd *qc)
 	case 0:
 		break;
 	case ATA_DEFER_LINK:
-		ret = SCSI_MLQUEUE_DEVICE_BUSY;
-		break;
-	case ATA_DEFER_PORT:
-		ret = SCSI_MLQUEUE_HOST_BUSY;
-		break;
-	default:
-		WARN_ON_ONCE(1);
-		ret = SCSI_MLQUEUE_HOST_BUSY;
-		break;
-	}
-
-	if (ret) {
 		/*
 		 * We must defer this qc: if this is not an NCQ command, keep
 		 * this qc as a deferred one and report to the SCSI layer that
@@ -1811,7 +1799,20 @@ static int ata_scsi_qc_issue(struct ata_port *ap, struct ata_queued_cmd *qc)
 
 		/* Force a requeue of the command to defer its execution. */
 		ata_qc_free(qc);
-		return ret;
+		return SCSI_MLQUEUE_DEVICE_BUSY;
+	case ATA_DEFER_PORT:
+		/*
+		 * ATA_DEFER_PORT is returned when the host is busy, e.g. when
+		 * using a PMP with CBS and trying to issue a qc to a link that
+		 * is not the currently active link. In this case, simply
+		 * propagate the error back to the SCSI layer.
+		 */
+		ata_qc_free(qc);
+		return SCSI_MLQUEUE_HOST_BUSY;
+	default:
+		WARN_ON_ONCE(1);
+		ata_qc_free(qc);
+		return SCSI_MLQUEUE_HOST_BUSY;
 	}
 
 issue:
-- 
2.54.0


  parent reply	other threads:[~2026-05-01 12:54 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-05-01 12:54 [PATCH 0/3] ata: fix deferred QC handling for port multipliers Niklas Cassel
2026-05-01 12:54 ` [PATCH 1/3] ata: libata-pmp: fix ata_pmp_qc_defer_cmd_switch() Niklas Cassel
2026-05-01 12:54 ` Niklas Cassel [this message]
2026-05-01 12:54 ` [PATCH 3/3] ata: libata-scsi: do not needlessly defer commands when using PMP with FBS Niklas Cassel
2026-05-01 14:19 ` [PATCH 0/3] ata: fix deferred QC handling for port multipliers John Garry
2026-05-01 18:42   ` Niklas Cassel
2026-05-04  7:27     ` John Garry
2026-05-08 19:23       ` Niklas Cassel
2026-05-03  0:59 ` Tommy Kelly
2026-05-06  0:13   ` Tommy Kelly
2026-05-06  8:45     ` Heiko Stuebner
2026-05-06 15:00     ` Niklas Cassel
2026-05-06 14:52   ` Niklas Cassel

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260501125410.1204490-7-cassel@kernel.org \
    --to=cassel@kernel.org \
    --cc=dlemoal@kernel.org \
    --cc=john.g.garry@oracle.com \
    --cc=linux-ide@vger.kernel.org \
    --cc=linux@tkel.ly \
    --cc=martin.petersen@oracle.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox