From mboxrd@z Thu Jan 1 00:00:00 1970 Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.remote-ip=74.125.82.200 ARC-Seal: i=1; d=subspace.kernel.org; s=arc20261015; a=rsa-sha256; cv=none; t=1794568330; b=dHQ7YIiunosT/6uUYmbgzQrfrd4zNIFpKc89YLKwdP28lIAFPLuem/5TARHq5x/uGPSI aPLs0dJlyTtp1gpqMd8wEjVB72XDOlbiH8sfEQMV5LA8AS7vbs4ZpeyfBSJ1qHFNa3I7s ++7fRiGEpnbgof2J34/Tq8kmYnX3aoq9DydQqk+Rt4wxFn0DPhbTbN1lnyiMoSnRSAJFE WWnbLiwOcehctNrCraMth6XIvlYlL8+Mouy81HDyZkjhNpHR4/3pE6TyBX58sl3Pw1vvq YiFmK+8c/6KMuybeOySFo0dcDEjD2a7IUwANglM6Wr1i75fn/uqFKkr5a/NrYKaSVcA== ARC-Message-Signature: i=1; d=subspace.kernel.org; s=arc20261015; a=rsa-sha256; c=relaxed/relaxed; t=1794568330; h=DMARC-Filter:Received:DKIM-Signature:X-Google-DKIM-Signature: X-Forwarded-Encrypted:X-Gm-Message-State:X-Received:Date:In-Reply-To: Mime-Version:References:X-Mailer:Message-ID:Subject:From:To:Cc: Content-Type; bh=0crRzYpZW9dxW1wNlc5vxnIxQkrZjxGjYg3H3gi691g=; b=v6MkfJLKWKxEetIu8eXNh2AuPRMs3cuHQsWK6HGyrd+SsUcwZ3S4jyUafWS4jWsBC/ZN 6Zr/WlBo4RWcQ5H0nXt+qenTV6e6AUq5/OYRBeXjVlQOxB8cQoY6UxBEz5WX5mS2M81N5 TI4daD2HoqB5ooebFlpHZE7EfeFhJJYD/wNq48nd9f1RtRMsDQTU+zAQPxP7w4omxvvBa Ek4E+7bGCLYHB2ISWK8LM8ilAU9czJf06Gn/A3RPURQWFvASw2DNnyLlWrXaz8IRulAp2 //38D4Gcdl12+rVdDWEKOme3iO669LXBON3WBBb4IVtra15v+JrucgIDEBtMFH5EQWg== ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass header.from=google.com; spf=pass smtp.mailfrom=flex--stanleyjhu.bounces.google.com; dkim=pass header.d=google.com header.i=@google.com header.a=rsa-sha256 header.s=20260707 header.b=lt7uHD8l; arc=none smtp.remote-ip=74.125.82.200 Received: from mail-dy1-f200.google.com (mail-dy1-f200.google.com [74.125.82.200]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits) key-exchange X25519 server-signature ECDSA (prime256v1) server-digest SHA256) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 9295A606A32D for ; Fri, 13 Nov 2026 11:12:09 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.2 smtp.subspace.kernel.org 9295A606A32D Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--stanleyjhu.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.a=rsa-sha256 header.s=20260707 header.b=lt7uHD8l Received: by mail-dy1-f200.google.com with SMTP id 5a478bee46e88-33c35f5ca6cso1307734eec.1 for ; Fri, 13 Nov 2026 03:12:09 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20260707; t=1794568329; x=1795173129; darn=vger.kernel.org; h=content-type:cc:to:from:subject:message-id:references:mime-version :in-reply-to:date:from:to:cc:subject:date:message-id:reply-to :content-type; bh=0crRzYpZW9dxW1wNlc5vxnIxQkrZjxGjYg3H3gi691g=; b=lt7uHD8l1toqas3ElXYiSGHB+RSr1qoum94HaRnGkl7zHQQ+rmAqvYjFlQ5WJ0ye4L HRdZjC8VkeJqUE+aHiBXrn3fhjwx9lPbN4+9iqrFU4m3xRvWksL2C6Rm9Iqq48bC0dJn V8XpHYLbWRZF+U3u8V9cx5vp9kSkjCTDnXg1RsqOu0SUEzgKKBSdwZfhnU/oB3KtKFHL Ti1htwVV1oLdCkXYAkQbzvCmzIZrkLALlgsOHqf6I1JwCXV3njJUTIIvwIPQXJHl/k7w 2OIO3KpxSxhtPALsglrF1QZnqgp9YywSNzxCxAHieFwET8P8OxPcLHM0SxLLhh7ZU5+F /TzQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1794568329; x=1795173129; h=content-type:cc:to:from:subject:message-id:references:mime-version :in-reply-to:date:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to:content-type; bh=0crRzYpZW9dxW1wNlc5vxnIxQkrZjxGjYg3H3gi691g=; b=p/jD4cSfSDeOQgxvR6qfinJ909zxt0tRdVBVBV42aYM3g8NbaVdni3E5KVf5U4iGXC 2fSI8JQW8/bhS7c0X3HnHV4i+CwUG5fNK6t7WktM3K6mtUWbsL4Wk74dFJ4Yve3u3ykh 0Jx8YMeOdTLomwqiAE2xdrCkt+nS6FRaoAdEqiT0BGmukxMlJS1fbBV1KPawJxxZ0XE3 8deh0eY0cwndOgknDxWI5IKBUvrlgiF2GQZ1saQFzifnsZ3Y/3TiY2THecW1GcX8xa04 beOZV8MkrLdndw4Uu/JWW5Tlvg49eWr1y48K7DEbs0NIvbX2vimrGWkS/Xh7Wy7ZH/WW 5Z6w== X-Forwarded-Encrypted: i=1; AL+hErHAXnveWtXuD7tpxTZQ5scxfRFDB0JSmjrAEXwWRtPRRSSYEPoyCwJrzfbM076hc3lYioXaBtwfA8SnUOY=@vger.kernel.org X-Gm-Message-State: APuU4Z9DXVIRdsGMFtfKU1HcEqrsoDJSJ0zX5+TmKFe25JNFAdAgjrbd JqWvMTu3XeaNshHIJ4Wvcxm/3k6ajE/HdQ05x+0kh6nF9cUr4h0qk0RY10V0hn40IqUaL2wT5PW jPiUeU4qz679Vhmqd90YVvg== X-Received: from dybhh46.prod.google.com ([2002:a05:7301:292e:b0:376:93cf:d6ce]) (user=stanleyjhu job=prod-delivery.src-stubby-dispatcher) by 2002:a05:7301:d189:b0:36e:e349:f2cb with SMTP id 5a478bee46e88-3796628e28amr1996025eec.19.1794568328133; Fri, 13 Nov 2026 03:12:08 -0800 (PST) Date: Fri, 13 Nov 2026 19:12:01 +0800 In-Reply-To: <20261113111202.3551341-1-stanleyjhu@google.com> X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Post: List-Help: List-Subscribe: List-Unsubscribe: List-Owner: Precedence: list Mime-Version: 1.0 References: <20261113111202.3551341-1-stanleyjhu@google.com> X-Mailer: git-send-email 2.56.0.611.g1030f0b940-goog Message-ID: <20261113111202.3551341-2-stanleyjhu@google.com> Subject: [PATCH v2 1/2] scsi: ufs: core: Recover link in ufshcd_set_dev_pwr_mode() on timeout From: Stanley Jhu To: linux-scsi@vger.kernel.org, "Martin K. Petersen" Cc: "James E.J. Bottomley" , Bart Van Assche , Alim Akhtar , Bean Huo , Peter Wang , Brian Kao , Can Guo , "Bao D. Nguyen" , Hongjie Fang , Praveen Talari , Hoyoung Seo , John Garry , Hyeoncheol Jeong , Jens Axboe , "Rafael J. Wysocki" , Stanley Jhu , linux-block@vger.kernel.org, linux-kernel@vger.kernel.org Content-Type: text/plain; charset="UTF-8" ufshcd_eh_timed_out() calls ufshcd_link_recovery() when a command times out during a power management operation. Link recovery sends a NOP OUT, which needs hba->dev_cmd.lock and the only reserved tag. 1. Runtime resume sends a query with the reserved tag while it holds hba->dev_cmd.lock. 2. The device does not answer and the query times out. 3. ufshcd_eh_timed_out() calls ufshcd_link_recovery(). 4. In MCQ mode ufshcd_verify_dev_init() waits for hba->dev_cmd.lock while __ufshcd_wl_resume() waits for the query. Resume hangs. 5. In legacy mode the query completes but the timeout handler still holds the reserved tag. The NOP OUT fails with -ENOMEM and the host enters UFSHCD_STATE_ERROR. Stop the host controller in ufshcd_eh_timed_out() and recover the link in ufshcd_set_dev_pwr_mode(), which issues START STOP UNIT without hba->dev_cmd.lock or the reserved tag. For modes other than active, ufshcd_set_dev_pwr_mode() then fails and the caller aborts the power transition. Recovering the link there needs four more changes. First, START STOP UNIT is completed with DID_TRANSPORT_FAILFAST and is not retried. ufshcd_set_dev_pwr_mode() also recovers the link if START STOP UNIT succeeds but the controller is disabled. Hosts with UFSHCI_QUIRK_BROKEN_HCE do not use the HCE bit, so ufshcd_set_dev_pwr_mode() checks only the timeout result on them. Second, in MCQ mode ufshcd_eh_timed_out() reaps the completion queue before it completes the command, so a late completion cannot complete the tag twice. Third, a timed-out reserved request forces ufshcd_err_handler(), because no power management caller recovers after it. Fourth, in MCQ mode ufshcd_err_handler() does not poll the completion queues while the controller is disabled. Fixes: 01d5e237b339 ("scsi: ufs: core: Handle PM commands timeout before SCSI EH") Cc: stable@vger.kernel.org # 7.2.x Suggested-by: Bart Van Assche Signed-off-by: Stanley Jhu --- drivers/ufs/core/ufshcd.c | 43 ++++++++++++++++++++++++++++----------- 1 file changed, 31 insertions(+), 12 deletions(-) diff --git a/drivers/ufs/core/ufshcd.c b/drivers/ufs/core/ufshcd.c index ddc953b45ce9..0f5365bd90f0 100644 --- a/drivers/ufs/core/ufshcd.c +++ b/drivers/ufs/core/ufshcd.c @@ -7108,8 +7108,12 @@ static void ufshcd_err_handler(struct work_struct *work) ufshcd_set_eh_in_progress(hba); spin_unlock_irqrestore(&hba->host->host_lock, flags); - /* Complete requests that have door-bell cleared by h/w */ - ufshcd_complete_requests(hba, false); + /* + * Complete requests that have door-bell cleared by h/w. + * CQTPy must not be read while the controller is disabled. + */ + if (!hba->mcq_enabled || ufshcd_is_hba_active(hba)) + ufshcd_complete_requests(hba, false); spin_lock_irqsave(&hba->host->host_lock, flags); again: needs_restore = false; @@ -9660,17 +9664,20 @@ static enum scsi_timeout_action ufshcd_eh_timed_out(struct scsi_cmnd *scmd) } /* - * Handle the timeout directly to prevent a deadlock between - * ufshcd_set_dev_pwr_mode() and ufshcd_err_handler(). + * Stop the host controller so that @scmd can be completed here. + * ufshcd_set_dev_pwr_mode() recovers the link for START STOP + * UNIT. ufshcd_err_handler() recovers it for other commands. */ - ufshcd_link_recovery(hba); - dev_info(hba->dev, "%s() finished; outstanding_tasks = %#lx.\n", - __func__, hba->outstanding_tasks); + ufshcd_hba_stop(hba); + if (!ufshcd_is_scsi_cmd(scmd)) + ufshcd_force_error_recovery(hba); + if (hba->mcq_enabled) { + struct ufs_hw_queue *hwq = + ufshcd_mcq_req_to_hwq(hba, scsi_cmd_to_rq(scmd)); + + ufshcd_mcq_compl_all_cqes_lock(hba, hwq); + } - /* - * ufshcd_link_recovery() may already have completed @scmd, e.g. via - * the existing MCQ force-completion path. - */ if (!test_bit(SCMD_STATE_COMPLETE, &scmd->state)) { if (!hba->mcq_enabled) { struct request *rq = scsi_cmd_to_rq(scmd); @@ -9680,7 +9687,7 @@ static enum scsi_timeout_action ufshcd_eh_timed_out(struct scsi_cmnd *scmd) } if (ufshcd_is_scsi_cmd(scmd)) { - set_host_byte(scmd, DID_REQUEUE); + set_host_byte(scmd, DID_TRANSPORT_FAILFAST); ufshcd_release_scsi_cmd(hba, scmd); } else { set_host_byte(scmd, DID_TIME_OUT); @@ -10137,6 +10144,9 @@ static int ufshcd_execute_start_stop(struct scsi_device *sdev, { const unsigned char cdb[6] = { START_STOP, 0, 0, 0, pwr_mode << 4, 0 }; struct scsi_failure failure_defs[] = { + { + .result = DID_TRANSPORT_FAILFAST << 16, + }, { .allowed = 2, .result = SCMD_FAILURE_RESULT_ANY, @@ -10172,6 +10182,7 @@ static int ufshcd_set_dev_pwr_mode(struct ufs_hba *hba, struct scsi_sense_hdr sshdr; struct scsi_device *sdp; unsigned long flags; + bool fenced; int ret; spin_lock_irqsave(&hba->host->host_lock, flags); @@ -10199,6 +10210,7 @@ static int ufshcd_set_dev_pwr_mode(struct ufs_hba *hba, * already suspended childs. */ ret = ufshcd_execute_start_stop(sdp, pwr_mode, &sshdr); + fenced = ret > 0 && host_byte(ret) == DID_TRANSPORT_FAILFAST; if (ret) { sdev_printk(KERN_WARNING, sdp, "START_STOP failed for power mode: %d, result %x\n", @@ -10212,6 +10224,13 @@ static int ufshcd_set_dev_pwr_mode(struct ufs_hba *hba, hba->curr_dev_pwr_mode = pwr_mode; } + if (fenced || (!(hba->quirks & UFSHCI_QUIRK_BROKEN_HCE) && + !ufshcd_is_hba_active(hba))) { + ret = ufshcd_link_recovery(hba); + if (!ret && hba->curr_dev_pwr_mode != pwr_mode) + ret = -EIO; + } + scsi_device_put(sdp); WRITE_ONCE(hba->host->eh_noresume, 0); return ret; -- 2.56.0.611.g1030f0b940-goog