From nobody Wed Sep 10 01:42:33 2025 Received: from mail.cybernetics.com (mail.cybernetics.com [173.71.130.66]) (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 4B1132E8DEF for ; Mon, 8 Sep 2025 18:58:37 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=173.71.130.66 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757357918; cv=none; b=HHaQkGoSvYo8Q3TPiaBYGNYtIRkWAVoY+H8dBQ46BwA31xsk+q5TThdcASNAVEHx6XV9uT4PBj9FWttORpB1wvu5LRtBnJS0elqyKiZFIyAer86FLZ9leooVKlhpPk2eFeN12MQTeWSPLvK+pXfRapmoGH4GRN79tkk53KPs3II= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757357918; c=relaxed/simple; bh=46R/IQuWGmERh2+CdWK6Zeur1EvRtscnhwT+dIaPju8=; h=Message-ID:Date:MIME-Version:Subject:From:To:Cc:References: In-Reply-To:Content-Type; b=aaqkhGrqM172ZE7lnLs+WTdKtiL9HO6ahp8Xz6iCNvfX0d5j7AvLxOWfBARSelLa+olBTp3yONWQkfrEue/uaXiwq2ya5wD8CVK5Fr0QbnX3Mi6znj2PICuzS3pVPg0bl+5s1DzAGAnaFCYQAtS2KL1ZrVxBDsKxIYaiC2dcEhI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=cybernetics.com; spf=pass smtp.mailfrom=cybernetics.com; dkim=pass (1024-bit key) header.d=cybernetics.com header.i=@cybernetics.com header.b=Obyt44Jy; arc=none smtp.client-ip=173.71.130.66 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=cybernetics.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=cybernetics.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=cybernetics.com header.i=@cybernetics.com header.b="Obyt44Jy" Received: from cybernetics.com ([10.10.4.126]) by mail.cybernetics.com with ESMTP id NaYb9LDwxfya61rc; Mon, 08 Sep 2025 14:47:12 -0400 (EDT) X-Barracuda-Envelope-From: tonyb@cybernetics.com X-Barracuda-RBL-Trusted-Forwarder: 10.10.4.126 X-ASG-Whitelist: Client DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=cybernetics.com; s=mail; bh=xPZleJbj/kmNxairhwj8W6cES/D138ycLpyxK9yxPVw=; h=Content-Transfer-Encoding:Content-Type:In-Reply-To:References:Cc:To:From: Content-Language:Subject:MIME-Version:Date:Message-ID; b=Obyt44Jy0+j86u+0oxFh TBXAM/vAm1RSY4gGZtc3p18hLus/6BuviTXTIsQpwmJaNkbV14VB/LwBjSHyW5V4p0KBTyjigJ82u 7j04BCp5ITdLLVItXo7Fg5gqChXdWlEqrRpu4sSSJ3+3OudtilFDF2rEo4/NeSutOgyW0X2QiU= Received: from [10.157.2.224] (HELO [192.168.200.1]) by cybernetics.com (CommuniGate SPEC SMTP 8.0.5) with ESMTPS id 14189111; Mon, 08 Sep 2025 14:47:12 -0400 Message-ID: <7458d784-8135-4f90-bc72-644abd5368f3@cybernetics.com> X-Barracuda-RBL-Trusted-Forwarder: 10.157.2.224 Date: Mon, 8 Sep 2025 14:47:12 -0400 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 User-Agent: Mozilla Thunderbird Subject: [PATCH 01/15] Revert "scsi: qla2xxx: Perform lockless command completion in abort path" Content-Language: en-US X-ASG-Orig-Subj: [PATCH 01/15] Revert "scsi: qla2xxx: Perform lockless command completion in abort path" From: Tony Battersby To: Nilesh Javali , GR-QLogic-Storage-Upstream@marvell.com, "James E.J. Bottomley" , "Martin K. Petersen" Cc: linux-scsi , target-devel@vger.kernel.org, scst-devel@lists.sourceforge.net, "linux-kernel@vger.kernel.org" References: In-Reply-To: Content-Transfer-Encoding: quoted-printable X-Barracuda-Connect: UNKNOWN[10.10.4.126] X-Barracuda-Start-Time: 1757357232 X-Barracuda-URL: https://10.10.4.122:443/cgi-mod/mark.cgi X-Barracuda-BRTS-Status: 1 X-Virus-Scanned: by bsmtpd at cybernetics.com X-Barracuda-Scan-Msg-Size: 3563 X-ASG-Debug-ID: 1757357232-1cf43947df30c260001-xx1T2L Content-Type: text/plain; charset="utf-8" This reverts commit 0367076b0817d5c75dfb83001ce7ce5c64d803a9. The commit being reverted added code to __qla2x00_abort_all_cmds() to call sp->done() without holding a spinlock. But unlike the older code below it, this new code failed to check sp->cmd_type and just assumed TYPE_SRB, which results in a jump to an invalid pointer in target-mode with TYPE_TGT_CMD: qla2xxx [0000:65:00.0]-d034:8: qla24xx_do_nack_work create sess success 0000000009f7a79b qla2xxx [0000:65:00.0]-5003:8: ISP System Error - mbx1=3D1ff5h mbx2=3D10h mbx3=3D0h mbx4=3D0h mbx5=3D191h mbx6=3D0h mbx7=3D0h. qla2xxx [0000:65:00.0]-d01e:8: -> fwdump no buffer qla2xxx [0000:65:00.0]-f03a:8: qla_target(0): System error async event 0x8002 occurred qla2xxx [0000:65:00.0]-00af:8: Performing ISP error recovery - ha=3D0000000058183fda. BUG: kernel NULL pointer dereference, address: 0000000000000000 PF: supervisor instruction fetch in kernel mode PF: error_code(0x0010) - not-present page PGD 0 P4D 0 Oops: 0010 [#1] SMP CPU: 2 PID: 9446 Comm: qla2xxx_8_dpc Tainted: G O 6.1.133 #1 Hardware name: Supermicro Super Server/X11SPL-F, BIOS 4.2 12/15/2023 RIP: 0010:0x0 Code: Unable to access opcode bytes at 0xffffffffffffffd6. RSP: 0018:ffffc90001f93dc8 EFLAGS: 00010206 RAX: 0000000000000282 RBX: 0000000000000355 RCX: ffff88810d16a000 RDX: ffff88810dbadaa8 RSI: 0000000000080000 RDI: ffff888169dc38c0 RBP: ffff888169dc38c0 R08: 0000000000000001 R09: 0000000000000045 R10: ffffffffa034bdf0 R11: 0000000000000000 R12: ffff88810800bb40 R13: 0000000000001aa8 R14: ffff888100136610 R15: ffff8881070f7400 FS: 0000000000000000(0000) GS:ffff88bf80080000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: ffffffffffffffd6 CR3: 000000010c8ff006 CR4: 00000000003706e0 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 Call Trace: ? __die+0x4d/0x8b ? page_fault_oops+0x91/0x180 ? trace_buffer_unlock_commit_regs+0x38/0x1a0 ? exc_page_fault+0x391/0x5e0 ? asm_exc_page_fault+0x22/0x30 __qla2x00_abort_all_cmds+0xcb/0x3e0 [qla2xxx_scst] qla2x00_abort_all_cmds+0x50/0x70 [qla2xxx_scst] qla2x00_abort_isp_cleanup+0x3b7/0x4b0 [qla2xxx_scst] qla2x00_abort_isp+0xfd/0x860 [qla2xxx_scst] qla2x00_do_dpc+0x581/0xa40 [qla2xxx_scst] kthread+0xa8/0xd0 Then commit 4475afa2646d ("scsi: qla2xxx: Complete command early within lock") added the spinlock back, because not having the lock caused a race and a crash. But qla2x00_abort_srb() in the switch below already checks for qla2x00_chip_is_down() and handles it the same way, so the code above the switch is now redundant and still buggy in target-mode. Remove it. Cc: stable@vger.kernel.org Signed-off-by: Tony Battersby --- drivers/scsi/qla2xxx/qla_os.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index d4b484c0fd9d..a52293972e10 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -1862,12 +1862,6 @@ __qla2x00_abort_all_cmds(struct qla_qpair *qp, int r= es) for (cnt =3D 1; cnt < req->num_outstanding_cmds; cnt++) { sp =3D req->outstanding_cmds[cnt]; if (sp) { - if (qla2x00_chip_is_down(vha)) { - req->outstanding_cmds[cnt] =3D NULL; - sp->done(sp, res); - continue; - } - switch (sp->cmd_type) { case TYPE_SRB: qla2x00_abort_srb(qp, sp, res, &flags); --=20 2.43.0 From nobody Wed Sep 10 01:42:33 2025 Received: from mail.cybernetics.com (mail.cybernetics.com [72.215.153.18]) (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 0290C31AF27 for ; Mon, 8 Sep 2025 18:48:24 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=72.215.153.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757357306; cv=none; b=dOb9dR3ybVr+E2LJoYdzaLGoFmlOrS/8lYRITxrMACGwmuoLZ3IrNTj5/I+KrbmABadvao7mtuM4DkGy7CrrYotQGCysy1tcZpz5bhFJ3Wz3zos+ggeB7lGBkH1+BHW8Snmjkz1kdCj3G9ZrCVV5Jt1n5KhkH6YPdpD4x74zR8s= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757357306; c=relaxed/simple; bh=tZxYb0uG1pVYCFAlE2Xx8jInj2yfc8dt9AvIkZMhXeg=; h=Message-ID:Date:MIME-Version:Subject:From:To:Cc:References: In-Reply-To:Content-Type; b=gpUtwzuUK/jlKnUOicGjbsrvEhYNMovQKExMJsnlr0w1c5OX/Pp6plWz+XpgUy8O2aTuBiOswpmLE1YcRwouSzedi+keUeonzUkV4QLrucyz4oX+yU92N/lJU4AZTuU1IDaXR5HqgZK5R48Uw81nojmeRqSumON2CdObtcbSANI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=cybernetics.com; spf=pass smtp.mailfrom=cybernetics.com; dkim=pass (1024-bit key) header.d=cybernetics.com header.i=@cybernetics.com header.b=bXN/CCZ9; arc=none smtp.client-ip=72.215.153.18 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=cybernetics.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=cybernetics.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=cybernetics.com header.i=@cybernetics.com header.b="bXN/CCZ9" Received: from cybernetics.com ([10.10.4.126]) by mail.cybernetics.com with ESMTP id XKvqW97nBl2Yag9r; Mon, 08 Sep 2025 14:48:23 -0400 (EDT) X-Barracuda-Envelope-From: tonyb@cybernetics.com X-Barracuda-RBL-Trusted-Forwarder: 10.10.4.126 X-ASG-Whitelist: Client DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=cybernetics.com; s=mail; bh=2mEIfVXrub6Npv/Fr/lvqsQ058qpuI+GzoBKWdxKTCQ=; h=Content-Transfer-Encoding:Content-Type:In-Reply-To:References:Cc:To:From: Content-Language:Subject:MIME-Version:Date:Message-ID; b=bXN/CCZ9ug/1i2Xynx5i P+so3tNX06MTAK83yy0HtQW9vYTDK3ERTQZ9qaYkJWhYOjSBVyDILI39U5nG2PRahT12LMcFU6yIe xLKKpB+DrdlysR8n3TTkdQ/qnTZbGnNTSFimntGOYKuLvVj6jsyG21kqDg2AdjCj3ucBrs9LTY= Received: from [10.157.2.224] (HELO [192.168.200.1]) by cybernetics.com (CommuniGate SPEC SMTP 8.0.5) with ESMTPS id 14189115; Mon, 08 Sep 2025 14:48:23 -0400 Message-ID: <88982e77-f758-470b-92ea-6c18ef433e0f@cybernetics.com> X-Barracuda-RBL-Trusted-Forwarder: 10.157.2.224 Date: Mon, 8 Sep 2025 14:48:23 -0400 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 User-Agent: Mozilla Thunderbird Subject: [PATCH 02/15] scsi: qla2xxx: fix initiator mode with qlini_mode=exclusive Content-Language: en-US X-ASG-Orig-Subj: [PATCH 02/15] scsi: qla2xxx: fix initiator mode with qlini_mode=exclusive From: Tony Battersby To: Nilesh Javali , GR-QLogic-Storage-Upstream@marvell.com, "James E.J. Bottomley" , "Martin K. Petersen" Cc: linux-scsi , target-devel@vger.kernel.org, scst-devel@lists.sourceforge.net, "linux-kernel@vger.kernel.org" References: In-Reply-To: Content-Transfer-Encoding: quoted-printable X-Barracuda-Connect: UNKNOWN[10.10.4.126] X-Barracuda-Start-Time: 1757357303 X-Barracuda-URL: https://10.10.4.122:443/cgi-mod/mark.cgi X-Barracuda-BRTS-Status: 1 X-Virus-Scanned: by bsmtpd at cybernetics.com X-Barracuda-Scan-Msg-Size: 1148 X-ASG-Debug-ID: 1757357303-1cf43947df30c290001-xx1T2L Content-Type: text/plain; charset="utf-8" When given the module parameter qlini_mode=3Dexclusive, qla2xxx in initiator mode is initially unable to successfully send SCSI commands to devices it finds while scanning, resulting in an escalating series of resets until an adapter reset clears the issue. Fix by checking the active mode instead of the module parameter. Signed-off-by: Tony Battersby --- drivers/scsi/qla2xxx/qla_os.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index a52293972e10..f0b77f13628d 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -3438,13 +3438,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct= pci_device_id *id) ha->mqenable =3D 0; =20 if (ha->mqenable) { - bool startit =3D false; - - if (QLA_TGT_MODE_ENABLED()) - startit =3D false; - - if (ql2x_ini_mode =3D=3D QLA2XXX_INI_MODE_ENABLED) - startit =3D true; + bool startit =3D !!(host->active_mode & MODE_INITIATOR); =20 /* Create start of day qpairs for Block MQ */ for (i =3D 0; i < ha->max_qpairs; i++) --=20 2.43.0 From nobody Wed Sep 10 01:42:33 2025 Received: from mail.cybernetics.com (mail.cybernetics.com [173.71.130.66]) (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 C791A31D732 for ; Mon, 8 Sep 2025 18:50:15 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=173.71.130.66 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757357418; cv=none; b=JdV5BL67QXZE0qUsSjnFqzA9+hGApuJFkGVfPhIiXTrJVxRXRbYQDTr3c3IWLa8rAhFgYIXXwdYWsJ+F/07SrtxXfWuftFnQRwAmJJHfIstTBJaNQ5r5/GVdVevzpoyFi/YNtche3j9pB1ROHyrmD6WEO6CHzBCo67DkMlGOLJ4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757357418; c=relaxed/simple; bh=ARRb9M+RsIZoRhRWZz6vGb0OTx21D88cMuGN9IS0+y0=; h=Message-ID:Date:MIME-Version:Subject:From:To:Cc:References: In-Reply-To:Content-Type; b=N1+OFBzZ8RHzH+61iIVdPwm9tIxBrlxWcaVZwS7sFx/hBxsm1b1P9hUoP50Rl4RpKN2XtCN+G01sfjvoQ1IICyUrHWqDzxLAoLi0q5RlMsQL3I3Q4QrimQ88EJmiDW/1tQ7KBxIZD2xm/nTeplcxhXDdfXZZlHOV+A5vDSvxve8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=cybernetics.com; spf=pass smtp.mailfrom=cybernetics.com; dkim=pass (1024-bit key) header.d=cybernetics.com header.i=@cybernetics.com header.b=khk1d1Xm; arc=none smtp.client-ip=173.71.130.66 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=cybernetics.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=cybernetics.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=cybernetics.com header.i=@cybernetics.com header.b="khk1d1Xm" Received: from cybernetics.com ([10.10.4.126]) by mail.cybernetics.com with ESMTP id nXuyO1kWQa3juZlS; Mon, 08 Sep 2025 14:50:14 -0400 (EDT) X-Barracuda-Envelope-From: tonyb@cybernetics.com X-Barracuda-RBL-Trusted-Forwarder: 10.10.4.126 X-ASG-Whitelist: Client DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=cybernetics.com; s=mail; bh=hktFZ1r224ixi9BOVjvIwDq8eEQbEpqyMKaK9gIPYTQ=; h=Content-Transfer-Encoding:Content-Type:In-Reply-To:References:Cc:To:From: Content-Language:Subject:MIME-Version:Date:Message-ID; b=khk1d1XmHWywqTzcJY7T gsKTntK+D6hIBgBy5AVVIWC8vdQCh13g09lOeQ7ibUaC40YM9w7mdXu1eJtlTScK2GoLAlWjKNU+k 6XNp6q4ERHPk52inQ/3a3b+j5vosRNnIe7eQqupyOUXXKqwCpk0Il6Gk6+YnI/eomnrRYrm4j4= Received: from [10.157.2.224] (HELO [192.168.200.1]) by cybernetics.com (CommuniGate SPEC SMTP 8.0.5) with ESMTPS id 14189123; Mon, 08 Sep 2025 14:50:14 -0400 Message-ID: <3572eea7-a6ef-46b4-8bdc-d0da72fd4b3c@cybernetics.com> X-Barracuda-RBL-Trusted-Forwarder: 10.157.2.224 Date: Mon, 8 Sep 2025 14:50:14 -0400 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 User-Agent: Mozilla Thunderbird Subject: [PATCH 03/15] scsi: qla2xxx: fix lost interrupts with qlini_mode=disabled Content-Language: en-US X-ASG-Orig-Subj: [PATCH 03/15] scsi: qla2xxx: fix lost interrupts with qlini_mode=disabled From: Tony Battersby To: Nilesh Javali , GR-QLogic-Storage-Upstream@marvell.com, "James E.J. Bottomley" , "Martin K. Petersen" Cc: linux-scsi , target-devel@vger.kernel.org, scst-devel@lists.sourceforge.net, "linux-kernel@vger.kernel.org" References: In-Reply-To: Content-Transfer-Encoding: quoted-printable X-Barracuda-Connect: UNKNOWN[10.10.4.126] X-Barracuda-Start-Time: 1757357414 X-Barracuda-URL: https://10.10.4.122:443/cgi-mod/mark.cgi X-Barracuda-BRTS-Status: 0 X-Virus-Scanned: by bsmtpd at cybernetics.com X-Barracuda-Scan-Msg-Size: 7250 X-ASG-Debug-ID: 1757357414-1cf43947df30c2d0001-xx1T2L Content-Type: text/plain; charset="utf-8" (target mode) When qla2xxx is loaded with qlini_mode=3Ddisabled, ha->flags.disable_msix_handshake is used before it is set, resulting in the wrong interrupt handler being used on certain HBAs (qla2xxx_msix_rsp_q_hs() is used when qla2xxx_msix_rsp_q() should be used). The only difference between these two interrupt handlers is that the _hs() version writes to a register to clear the "RISC" interrupt, whereas the other version does not. So this bug results in the RISC interrupt being cleared when it should not be. This occasionally causes a different interrupt handler qla24xx_msix_default() for a different vector to see ((stat & HSRX_RISC_INT) =3D=3D 0) and ignore its interrupt, which then causes problems like: qla2xxx [0000:02:00.0]-d04c:6: MBX Command timeout for cmd 20, iocontrol=3D8 jiffies=3D1090c0300 mb[0-3]=3D[0x4000 0x0 0x40 0xda] mb7 0x= 500 host_status 0x40000010 hccr 0x3f00 qla2xxx [0000:02:00.0]-101e:6: Mailbox cmd timeout occurred, cmd=3D0x20, mb[0]=3D0x20. Scheduling ISP abort (the cmd varies; sometimes it is 0x20, 0x22, 0x54, 0x5a, 0x5d, or 0x6a) This problem can be reproduced with a 16 or 32 Gbps HBA by loading qla2xxx with qlini_mode=3Ddisabled and running a high IOPS test while triggering frequent RSCN database change events. While analyzing the problem I discovered that even with disable_msix_handshake forced to 0, it is not necessary to clear the RISC interrupt from qla2xxx_msix_rsp_q_hs() (more below). So just completely remove qla2xxx_msix_rsp_q_hs() and the logic for selecting it, which also fixes the bug with qlini_mode=3Ddisabled. The test below describes the justification for not needing qla2xxx_msix_rsp_q_hs(): Force disable_msix_handshake to 0: qla24xx_config_rings(): if (0 && (ha->fw_attributes & BIT_6) && (IS_MSIX_NACK_CAPABLE(ha)) && (ha->flags.msix_enabled)) { In qla24xx_msix_rsp_q() and qla2xxx_msix_rsp_q_hs(), check: (rd_reg_dword(®->host_status) & HSRX_RISC_INT) Count the number of calls to each function with HSRX_RISC_INT set and the number with HSRX_RISC_INT not set while performing some I/O. If qla2xxx_msix_rsp_q_hs() clears the RISC interrupt (original code): qla24xx_msix_rsp_q: 50% of calls have HSRX_RISC_INT set qla2xxx_msix_rsp_q_hs: 5% of calls have HSRX_RISC_INT set (# of qla2xxx_msix_rsp_q_hs interrupts) =3D (# of qla24xx_msix_rsp_q interrupts) * 3 If qla2xxx_msix_rsp_q_hs() does not clear the RISC interrupt (patched code): qla24xx_msix_rsp_q: 100% of calls have HSRX_RISC_INT set qla2xxx_msix_rsp_q_hs: 9% of calls have HSRX_RISC_INT set (# of qla2xxx_msix_rsp_q_hs interrupts) =3D (# of qla24xx_msix_rsp_q interrupts) * 3 In the case of the original code, qla24xx_msix_rsp_q() was seeing HSRX_RISC_INT set only 50% of the time because qla2xxx_msix_rsp_q_hs() was clearing it when it shouldn't have been. In the patched code, qla24xx_msix_rsp_q() sees HSRX_RISC_INT set 100% of the time, which makes sense if that interrupt handler needs to clear the RISC interrupt (which it does). qla2xxx_msix_rsp_q_hs() sees HSRX_RISC_INT only 9% of the time, which is just overlap from the other interrupt during the high IOPS test. Tested with SCST on: QLE2742 FW:v9.08.02 (32 Gbps 2-port) QLE2694L FW:v9.10.11 (16 Gbps 4-port) QLE2694L FW:v9.08.02 (16 Gbps 4-port) QLE2672 FW:v8.07.12 (16 Gbps 2-port) both initiator and target mode Signed-off-by: Tony Battersby --- drivers/scsi/qla2xxx/qla_def.h | 1 - drivers/scsi/qla2xxx/qla_gbl.h | 2 +- drivers/scsi/qla2xxx/qla_isr.c | 32 +++----------------------------- drivers/scsi/qla2xxx/qla_mid.c | 4 +--- 4 files changed, 5 insertions(+), 34 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index cb95b7b12051..b3265952c4be 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h @@ -3503,7 +3503,6 @@ struct isp_operations { #define QLA_MSIX_RSP_Q 0x01 #define QLA_ATIO_VECTOR 0x02 #define QLA_MSIX_QPAIR_MULTIQ_RSP_Q 0x03 -#define QLA_MSIX_QPAIR_MULTIQ_RSP_Q_HS 0x04 =20 #define QLA_MIDX_DEFAULT 0 #define QLA_MIDX_RSP_Q 1 diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h index 145defc420f2..55d531c19e6b 100644 --- a/drivers/scsi/qla2xxx/qla_gbl.h +++ b/drivers/scsi/qla2xxx/qla_gbl.h @@ -766,7 +766,7 @@ extern int qla2x00_dfs_remove(scsi_qla_host_t *); =20 /* Globa function prototypes for multi-q */ extern int qla25xx_request_irq(struct qla_hw_data *, struct qla_qpair *, - struct qla_msix_entry *, int); + struct qla_msix_entry *); extern int qla25xx_init_req_que(struct scsi_qla_host *, struct req_que *); extern int qla25xx_init_rsp_que(struct scsi_qla_host *, struct rsp_que *); extern int qla25xx_create_req_que(struct qla_hw_data *, uint16_t, uint8_t, diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index c4c6b5c6658c..a3971afc2dd1 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c @@ -4467,32 +4467,6 @@ qla2xxx_msix_rsp_q(int irq, void *dev_id) return IRQ_HANDLED; } =20 -irqreturn_t -qla2xxx_msix_rsp_q_hs(int irq, void *dev_id) -{ - struct qla_hw_data *ha; - struct qla_qpair *qpair; - struct device_reg_24xx __iomem *reg; - unsigned long flags; - - qpair =3D dev_id; - if (!qpair) { - ql_log(ql_log_info, NULL, 0x505b, - "%s: NULL response queue pointer.\n", __func__); - return IRQ_NONE; - } - ha =3D qpair->hw; - - reg =3D &ha->iobase->isp24; - spin_lock_irqsave(&ha->hardware_lock, flags); - wrt_reg_dword(®->hccr, HCCRX_CLR_RISC_INT); - spin_unlock_irqrestore(&ha->hardware_lock, flags); - - queue_work(ha->wq, &qpair->q_work); - - return IRQ_HANDLED; -} - /* Interrupt handling helpers. */ =20 struct qla_init_msix_entry { @@ -4505,7 +4479,6 @@ static const struct qla_init_msix_entry msix_entries[= ] =3D { { "rsp_q", qla24xx_msix_rsp_q }, { "atio_q", qla83xx_msix_atio_q }, { "qpair_multiq", qla2xxx_msix_rsp_q }, - { "qpair_multiq_hs", qla2xxx_msix_rsp_q_hs }, }; =20 static const struct qla_init_msix_entry qla82xx_msix_entries[] =3D { @@ -4792,9 +4765,10 @@ qla2x00_free_irqs(scsi_qla_host_t *vha) } =20 int qla25xx_request_irq(struct qla_hw_data *ha, struct qla_qpair *qpair, - struct qla_msix_entry *msix, int vector_type) + struct qla_msix_entry *msix) { - const struct qla_init_msix_entry *intr =3D &msix_entries[vector_type]; + const struct qla_init_msix_entry *intr =3D + &msix_entries[QLA_MSIX_QPAIR_MULTIQ_RSP_Q]; scsi_qla_host_t *vha =3D pci_get_drvdata(ha->pdev); int ret; =20 diff --git a/drivers/scsi/qla2xxx/qla_mid.c b/drivers/scsi/qla2xxx/qla_mid.c index 8b71ac0b1d99..0abc47e72e0b 100644 --- a/drivers/scsi/qla2xxx/qla_mid.c +++ b/drivers/scsi/qla2xxx/qla_mid.c @@ -899,9 +899,7 @@ qla25xx_create_rsp_que(struct qla_hw_data *ha, uint16_t= options, rsp->options, rsp->id, rsp->rsp_q_in, rsp->rsp_q_out); =20 - ret =3D qla25xx_request_irq(ha, qpair, qpair->msix, - ha->flags.disable_msix_handshake ? - QLA_MSIX_QPAIR_MULTIQ_RSP_Q : QLA_MSIX_QPAIR_MULTIQ_RSP_Q_HS); + ret =3D qla25xx_request_irq(ha, qpair, qpair->msix); if (ret) goto que_failed; =20 --=20 2.43.0 From nobody Wed Sep 10 01:42:33 2025 Received: from mail.cybernetics.com (mail.cybernetics.com [72.215.153.18]) (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 3920631C58A for ; Mon, 8 Sep 2025 18:51:30 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=72.215.153.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757357491; cv=none; b=htpFkGHoxxAIsqgWGYKcgYiRdfnAA5ynzi6PZGDcEXr4ZTijGdbkrXyW5O1WTeWd2m2CxXDG9mePCVwxdIkmLOg/axomoItTWF887Mc5Eg9V2JOMwusoA0vC5LtU6/Jrqn7wPmuc5aOC7DVlA4g6/4cbg3IdihARoS5GHI3t/uQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757357491; c=relaxed/simple; bh=3B57ATz3UdD42KSx68Sb8PP+iMlVGiDpmiGvWhdCGyo=; h=Message-ID:Date:MIME-Version:Subject:From:To:Cc:References: In-Reply-To:Content-Type; b=NaZWnFknwrMbv1T3Pn8D09XM3IXpViQRd6KMeA1Xegov7pbT/V4O8LBoEHXzFKVlMJIfsvxwLVrfX5BYEfKrCLtrsubow2YK3dT7iAggd8uIP5jESdhFDhsAUwJwdviuX3N+Txopnd6G64ICVd05kN+IZlzk+aCZSHtSxp6WSyY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=cybernetics.com; spf=pass smtp.mailfrom=cybernetics.com; dkim=pass (1024-bit key) header.d=cybernetics.com header.i=@cybernetics.com header.b=QQ20AbfK; arc=none smtp.client-ip=72.215.153.18 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=cybernetics.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=cybernetics.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=cybernetics.com header.i=@cybernetics.com header.b="QQ20AbfK" Received: from cybernetics.com ([10.10.4.126]) by mail.cybernetics.com with ESMTP id qfCNNj5fplSnWsK8; Mon, 08 Sep 2025 14:51:28 -0400 (EDT) X-Barracuda-Envelope-From: tonyb@cybernetics.com X-Barracuda-RBL-Trusted-Forwarder: 10.10.4.126 X-ASG-Whitelist: Client DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=cybernetics.com; s=mail; bh=kI5kvHmGz7C9TMJF6aaUpsjVqkrCWX3ZpUSR28Va5/M=; h=Content-Transfer-Encoding:Content-Type:In-Reply-To:References:Cc:To:From: Content-Language:Subject:MIME-Version:Date:Message-ID; b=QQ20AbfK//ewd35yg0N8 cdf6UgI3TAWZE3af9P+mUcbEWj74kAxaNGQDGiJe6JuKQKDGV6QTVs9GdNxL5Rdr7ll4Vqfu6IXdA aEHvdQ/ccQz0JgmRdA5bD0l6CO3NSp8+p4meOoL2XyCKbV12/fp8cutM/bc2qE2nqvrfDBDZbQ= Received: from [10.157.2.224] (HELO [192.168.200.1]) by cybernetics.com (CommuniGate SPEC SMTP 8.0.5) with ESMTPS id 14189039; Mon, 08 Sep 2025 14:51:28 -0400 Message-ID: <389db3ff-16e4-430f-a69d-dd41d83d83aa@cybernetics.com> X-Barracuda-RBL-Trusted-Forwarder: 10.157.2.224 Date: Mon, 8 Sep 2025 14:51:28 -0400 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 User-Agent: Mozilla Thunderbird Subject: [PATCH 04/15] scsi: qla2xxx: use reinit_completion on mbx_intr_comp Content-Language: en-US X-ASG-Orig-Subj: [PATCH 04/15] scsi: qla2xxx: use reinit_completion on mbx_intr_comp From: Tony Battersby To: Nilesh Javali , GR-QLogic-Storage-Upstream@marvell.com, "James E.J. Bottomley" , "Martin K. Petersen" Cc: linux-scsi , target-devel@vger.kernel.org, scst-devel@lists.sourceforge.net, "linux-kernel@vger.kernel.org" References: In-Reply-To: Content-Transfer-Encoding: quoted-printable X-Barracuda-Connect: UNKNOWN[10.10.4.126] X-Barracuda-Start-Time: 1757357488 X-Barracuda-URL: https://10.10.4.122:443/cgi-mod/mark.cgi X-Barracuda-BRTS-Status: 0 X-Virus-Scanned: by bsmtpd at cybernetics.com X-Barracuda-Scan-Msg-Size: 1335 X-ASG-Debug-ID: 1757357488-1cf43947df30c2f0001-xx1T2L Content-Type: text/plain; charset="utf-8" If a mailbox command completes immediately after wait_for_completion_timeout() times out, ha->mbx_intr_comp could be left in an inconsistent state, causing the next mailbox command not to wait for the hardware. Fix by reinitializing the completion before use. Signed-off-by: Tony Battersby --- drivers/scsi/qla2xxx/qla_mbx.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c index 32eb0ce8b170..1f01576f044b 100644 --- a/drivers/scsi/qla2xxx/qla_mbx.c +++ b/drivers/scsi/qla2xxx/qla_mbx.c @@ -253,6 +253,7 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t= *mcp) /* Issue set host interrupt command to send cmd out. */ ha->flags.mbox_int =3D 0; clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags); + reinit_completion(&ha->mbx_intr_comp); =20 /* Unlock mbx registers and wait for interrupt */ ql_dbg(ql_dbg_mbx, vha, 0x100f, @@ -279,6 +280,7 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t= *mcp) "cmd=3D%x Timeout.\n", command); spin_lock_irqsave(&ha->hardware_lock, flags); clear_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags); + reinit_completion(&ha->mbx_intr_comp); spin_unlock_irqrestore(&ha->hardware_lock, flags); =20 if (chip_reset !=3D ha->chip_reset) { --=20 2.43.0 From nobody Wed Sep 10 01:42:33 2025 Received: from mail.cybernetics.com (mail.cybernetics.com [72.215.153.18]) (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 810E71799F for ; Mon, 8 Sep 2025 18:53:01 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=72.215.153.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757357583; cv=none; b=QpeVeHIzwSWaLAsEg1aFUqRX0l6B0R3TJkgZSen0XOvUSwb/9Zzh6ZYXVtUg5htGmkEeM07Alom/R5Ts3cAkurSHGknIy/tuB8XhXNh2Wa2JduB9NgFiErMEYcLa2CjHuq6zIg90QMTO0d3GCLNUXZyarQ4DCeu7ocaFu4Mqc0A= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757357583; c=relaxed/simple; bh=OPynoWlf+TtliqB9Jn+lbK/6f+T6n+fWvl2d8xr8jvo=; h=Message-ID:Date:MIME-Version:Subject:From:To:Cc:References: In-Reply-To:Content-Type; b=oj5EUJkmcDKwDdj83u4VqaiOIqSQhDdGxjsfgdulSjhLT0nB0SA4LBDG16DaZef+roKq0SYEu9VKIaHNyFBADhF9IIMW5Iv9oYqb6HvoxaG5F+MjQzOPX4MiO+Jzskkpb7sMOmGm5ZHnkv82Ci9XVB0eAE/aV1Yf+IsAtyf4DzQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=cybernetics.com; spf=pass smtp.mailfrom=cybernetics.com; dkim=pass (1024-bit key) header.d=cybernetics.com header.i=@cybernetics.com header.b=UMc0baAQ; arc=none smtp.client-ip=72.215.153.18 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=cybernetics.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=cybernetics.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=cybernetics.com header.i=@cybernetics.com header.b="UMc0baAQ" Received: from cybernetics.com ([10.10.4.126]) by mail.cybernetics.com with ESMTP id yDLdLq42OM4eha9T; Mon, 08 Sep 2025 14:53:00 -0400 (EDT) X-Barracuda-Envelope-From: tonyb@cybernetics.com X-Barracuda-RBL-Trusted-Forwarder: 10.10.4.126 X-ASG-Whitelist: Client DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=cybernetics.com; s=mail; bh=YvO2yZSm6FDx3HPo7HFr8bH+Vs2f6ZhSFZIHMDWyqIc=; h=Content-Transfer-Encoding:Content-Type:In-Reply-To:References:Cc:To:From: Content-Language:Subject:MIME-Version:Date:Message-ID; b=UMc0baAQkmeGnLm4bPtI Kr3pzj/nYs2+vPWPFP5g5spLfhKQpyygA6c9PFDz2Pdl1P2OOj8f2aZaSdKQ01pQ/VLbaAd5ElC0Y BdqXhf8tHzz8dqZHs8lBW9T6fKPYGyTw4FUbmDSWkdBcp9I32M641G28kuLs3U2luH8SQmgNmY= Received: from [10.157.2.224] (HELO [192.168.200.1]) by cybernetics.com (CommuniGate SPEC SMTP 8.0.5) with ESMTPS id 14189085; Mon, 08 Sep 2025 14:53:00 -0400 Message-ID: <05e68829-aee4-49cf-902b-fd0c2b6d2d13@cybernetics.com> X-Barracuda-RBL-Trusted-Forwarder: 10.157.2.224 Date: Mon, 8 Sep 2025 14:53:00 -0400 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 User-Agent: Mozilla Thunderbird Subject: [PATCH 05/15] scsi: qla2xxx: remove code for unsupported hardware Content-Language: en-US X-ASG-Orig-Subj: [PATCH 05/15] scsi: qla2xxx: remove code for unsupported hardware From: Tony Battersby To: Nilesh Javali , GR-QLogic-Storage-Upstream@marvell.com, "James E.J. Bottomley" , "Martin K. Petersen" Cc: linux-scsi , target-devel@vger.kernel.org, scst-devel@lists.sourceforge.net, "linux-kernel@vger.kernel.org" References: In-Reply-To: Content-Transfer-Encoding: quoted-printable X-Barracuda-Connect: UNKNOWN[10.10.4.126] X-Barracuda-Start-Time: 1757357580 X-Barracuda-URL: https://10.10.4.122:443/cgi-mod/mark.cgi X-Barracuda-BRTS-Status: 0 X-Virus-Scanned: by bsmtpd at cybernetics.com X-Barracuda-Scan-Msg-Size: 2693 X-ASG-Debug-ID: 1757357580-1cf43947df30c330001-xx1T2L Content-Type: text/plain; charset="utf-8" (target mode) As far as I can tell, CONTINUE_TGT_IO_TYPE and CTIO_A64_TYPE are message types from non-FWI2 boards (older than ISP24xx), which are not supported by qla_target.c. Removing them makes it possible to turn a void * into the real type and avoid some typecasts. Signed-off-by: Tony Battersby --- drivers/scsi/qla2xxx/qla_target.c | 32 +++++-------------------------- 1 file changed, 5 insertions(+), 27 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_t= arget.c index 1e81582085e3..df5c9aac5617 100644 --- a/drivers/scsi/qla2xxx/qla_target.c +++ b/drivers/scsi/qla2xxx/qla_target.c @@ -3913,7 +3913,8 @@ static void *qlt_ctio_to_cmd(struct scsi_qla_host *vh= a, * ha->hardware_lock supposed to be held on entry. Might drop it, then rea= quire */ static void qlt_do_ctio_completion(struct scsi_qla_host *vha, - struct rsp_que *rsp, uint32_t handle, uint32_t status, void *ctio) + struct rsp_que *rsp, uint32_t handle, uint32_t status, + struct ctio7_from_24xx *ctio) { struct qla_hw_data *ha =3D vha->hw; struct se_cmd *se_cmd; @@ -3934,11 +3935,8 @@ static void qlt_do_ctio_completion(struct scsi_qla_h= ost *vha, if (cmd =3D=3D NULL) return; =20 - if ((le16_to_cpu(((struct ctio7_from_24xx *)ctio)->flags) & CTIO7_FLAGS_D= ATA_OUT) && - cmd->sess) { - qlt_chk_edif_rx_sa_delete_pending(vha, cmd->sess, - (struct ctio7_from_24xx *)ctio); - } + if ((le16_to_cpu(ctio->flags) & CTIO7_FLAGS_DATA_OUT) && cmd->sess) + qlt_chk_edif_rx_sa_delete_pending(vha, cmd->sess, ctio); =20 se_cmd =3D &cmd->se_cmd; cmd->cmd_sent_to_fw =3D 0; @@ -4007,7 +4005,7 @@ static void qlt_do_ctio_completion(struct scsi_qla_ho= st *vha, *((u64 *)&crc->actual_dif[0]), *((u64 *)&crc->expected_dif[0])); =20 - qlt_handle_dif_error(qpair, cmd, ctio); + qlt_handle_dif_error(qpair, cmd, crc); return; } =20 @@ -5816,26 +5814,6 @@ static void qlt_response_pkt(struct scsi_qla_host *v= ha, } break; =20 - case CONTINUE_TGT_IO_TYPE: - { - struct ctio_to_2xxx *entry =3D (struct ctio_to_2xxx *)pkt; - - qlt_do_ctio_completion(vha, rsp, entry->handle, - le16_to_cpu(entry->status)|(pkt->entry_status << 16), - entry); - break; - } - - case CTIO_A64_TYPE: - { - struct ctio_to_2xxx *entry =3D (struct ctio_to_2xxx *)pkt; - - qlt_do_ctio_completion(vha, rsp, entry->handle, - le16_to_cpu(entry->status)|(pkt->entry_status << 16), - entry); - break; - } - case IMMED_NOTIFY_TYPE: ql_dbg(ql_dbg_tgt, vha, 0xe035, "%s", "IMMED_NOTIFY\n"); qlt_handle_imm_notify(vha, (struct imm_ntfy_from_isp *)pkt); --=20 2.43.0 From nobody Wed Sep 10 01:42:33 2025 Received: from mail.cybernetics.com (mail.cybernetics.com [72.215.153.18]) (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 4EA9831C593 for ; Mon, 8 Sep 2025 18:54:32 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=72.215.153.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757357674; cv=none; b=YNfBDpxXYxMru1HHWMwHOP/HlHcULzia9GXF+ru94/8umlA5U5+HCIzoVyMom9pWpizUKT1satGc62YJWbM7GQu19pzPCzKQdw5N6Mh/p6M8Lu3lQkvdRidQcyj57swCTyNoWBEdP1k0hqovpCBsQFaBVAQweEd+2lL4KxbEMDg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757357674; c=relaxed/simple; bh=Qi2dqJfmYSOmbZYLHMvWimQauBJ3vI5VS+QWF9NvffQ=; h=Message-ID:Date:MIME-Version:Subject:From:To:Cc:References: In-Reply-To:Content-Type; b=ZPNnEwrXU0E6vQu0fCNOQjNrxVQAjz71cqUlavggwFh0OgydgugTwMyf2XIJNJQhfYeR6GZHn6kzXiDhxDLYQOz32MqYou07nGOzqLOV4VWeb8xzqVK3i/tNc72BcQrl1YODQdr0Fmo269aBJgRFBdMZWhpkCBgKjEbIrfhIzts= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=cybernetics.com; spf=pass smtp.mailfrom=cybernetics.com; dkim=pass (1024-bit key) header.d=cybernetics.com header.i=@cybernetics.com header.b=rFHPih/o; arc=none smtp.client-ip=72.215.153.18 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=cybernetics.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=cybernetics.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=cybernetics.com header.i=@cybernetics.com header.b="rFHPih/o" Received: from cybernetics.com ([10.10.4.126]) by mail.cybernetics.com with ESMTP id mpDVR1UXCN7uMWWZ; Mon, 08 Sep 2025 14:54:30 -0400 (EDT) X-Barracuda-Envelope-From: tonyb@cybernetics.com X-Barracuda-RBL-Trusted-Forwarder: 10.10.4.126 X-ASG-Whitelist: Client DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=cybernetics.com; s=mail; bh=Mz8YTERAqbp0grI55dYC/MIZz0p5iQa4faEztRyPnm0=; h=Content-Transfer-Encoding:Content-Type:In-Reply-To:References:Cc:To:From: Content-Language:Subject:MIME-Version:Date:Message-ID; b=rFHPih/oy0OQvJ/mdz+E kxoCuEn49I9y5P+8Z6+YwUE/thyVvH74HjobnsnvsT5a7fumOXZfHGiqBkWiTdGZXWTTEPCH7cirh 4sysQOQ0r8hykiM19IIeyv1SxcQu1pqaLd+u952NxPIJGl70Yn4Qm924p3guct0QBOWW2F9PCw= Received: from [10.157.2.224] (HELO [192.168.200.1]) by cybernetics.com (CommuniGate SPEC SMTP 8.0.5) with ESMTPS id 14189133; Mon, 08 Sep 2025 14:54:30 -0400 Message-ID: X-Barracuda-RBL-Trusted-Forwarder: 10.157.2.224 Date: Mon, 8 Sep 2025 14:54:30 -0400 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 User-Agent: Mozilla Thunderbird Subject: [PATCH 06/15] scsi: qla2xxx: improve debug output for term exchange Content-Language: en-US X-ASG-Orig-Subj: [PATCH 06/15] scsi: qla2xxx: improve debug output for term exchange From: Tony Battersby To: Nilesh Javali , GR-QLogic-Storage-Upstream@marvell.com, "James E.J. Bottomley" , "Martin K. Petersen" Cc: linux-scsi , target-devel@vger.kernel.org, scst-devel@lists.sourceforge.net, "linux-kernel@vger.kernel.org" References: In-Reply-To: Content-Transfer-Encoding: quoted-printable X-Barracuda-Connect: UNKNOWN[10.10.4.126] X-Barracuda-Start-Time: 1757357670 X-Barracuda-URL: https://10.10.4.122:443/cgi-mod/mark.cgi X-Barracuda-BRTS-Status: 1 X-Virus-Scanned: by bsmtpd at cybernetics.com X-Barracuda-Scan-Msg-Size: 4014 X-ASG-Debug-ID: 1757357670-1cf43947df30c380001-xx1T2L Content-Type: text/plain; charset="utf-8" (target mode) Print better debug info when terminating a command, and print the response status from the hardware. Signed-off-by: Tony Battersby --- drivers/scsi/qla2xxx/qla_dbg.c | 2 +- drivers/scsi/qla2xxx/qla_target.c | 40 +++++++++++++++++++++++++++---- 2 files changed, 36 insertions(+), 6 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_dbg.c b/drivers/scsi/qla2xxx/qla_dbg.c index 5136549005e7..ff4124eccc9c 100644 --- a/drivers/scsi/qla2xxx/qla_dbg.c +++ b/drivers/scsi/qla2xxx/qla_dbg.c @@ -54,7 +54,7 @@ * | Misc | 0xd303 | 0xd031-0xd0ff | * | | | 0xd101-0xd1fe | * | | | 0xd214-0xd2fe | - * | Target Mode | 0xe081 | | + * | Target Mode | 0xe084 | | * | Target Mode Management | 0xf09b | 0xf002 | * | | | 0xf046-0xf049 | * | Target Mode Task Management | 0x1000d | | diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_t= arget.c index df5c9aac5617..72c74f8f5375 100644 --- a/drivers/scsi/qla2xxx/qla_target.c +++ b/drivers/scsi/qla2xxx/qla_target.c @@ -1909,6 +1909,10 @@ static void qlt_24xx_retry_term_exchange(struct scsi= _qla_host *vha, * ABTS response. So, in it ID fields are reversed. */ =20 + ql_dbg(ql_dbg_tgt_mgt, vha, 0xe082, + "qla_target(%d): tag %u: Sending TERM EXCH CTIO for ABTS\n", + vha->vp_idx, le32_to_cpu(entry->exchange_addr_to_abort)); + ctio->entry_type =3D CTIO_TYPE7; ctio->entry_count =3D 1; ctio->nport_handle =3D entry->nport_handle; @@ -3620,16 +3624,24 @@ static int __qlt_send_term_exchange(struct qla_qpai= r *qpair, { struct scsi_qla_host *vha =3D qpair->vha; struct ctio7_to_24xx *ctio24; - struct qla_hw_data *ha =3D vha->hw; request_t *pkt; int ret =3D 0; uint16_t temp; =20 - ql_dbg(ql_dbg_tgt, vha, 0xe009, "Sending TERM EXCH CTIO (ha=3D%p)\n", ha); - if (cmd) vha =3D cmd->vha; =20 + if (cmd) { + ql_dbg(ql_dbg_tgt_mgt, vha, 0xe009, + "qla_target(%d): tag %lld: Sending TERM EXCH CTIO state %d cmd_sent_= to_fw %u\n", + vha->vp_idx, cmd->se_cmd.tag, cmd->state, + cmd->cmd_sent_to_fw); + } else { + ql_dbg(ql_dbg_tgt_mgt, vha, 0xe009, + "qla_target(%d): tag %u: Sending TERM EXCH CTIO (no cmd)\n", + vha->vp_idx, le32_to_cpu(atio->u.isp24.exchange_addr)); + } + pkt =3D (request_t *)qla2x00_alloc_iocbs_ready(qpair, NULL); if (pkt =3D=3D NULL) { ql_dbg(ql_dbg_tgt, vha, 0xe050, @@ -3920,6 +3932,7 @@ static void qlt_do_ctio_completion(struct scsi_qla_ho= st *vha, struct se_cmd *se_cmd; struct qla_tgt_cmd *cmd; struct qla_qpair *qpair =3D rsp->qpair; + uint16_t ctio_flags; =20 if (handle & CTIO_INTERMEDIATE_HANDLE_MARK) { /* That could happen only in case of an error/reset/abort */ @@ -3931,11 +3944,28 @@ static void qlt_do_ctio_completion(struct scsi_qla_= host *vha, return; } =20 + ctio_flags =3D le16_to_cpu(ctio->flags); + cmd =3D qlt_ctio_to_cmd(vha, rsp, handle, ctio); - if (cmd =3D=3D NULL) + if (unlikely(cmd =3D=3D NULL)) { + if ((handle & ~QLA_TGT_HANDLE_MASK) =3D=3D QLA_TGT_SKIP_HANDLE && + (ctio_flags & 0xe1ff) =3D=3D (CTIO7_FLAGS_STATUS_MODE_1 | + CTIO7_FLAGS_TERMINATE)) { + u32 tag =3D le32_to_cpu(ctio->exchange_address); + + if (status =3D=3D CTIO_SUCCESS) + ql_dbg(ql_dbg_tgt_mgt, vha, 0xe083, + "qla_target(%d): tag %u: term exchange successful\n", + vha->vp_idx, tag); + else + ql_dbg(ql_dbg_tgt_mgt, vha, 0xe084, + "qla_target(%d): tag %u: term exchange failed; status =3D 0x%x\n", + vha->vp_idx, tag, status); + } return; + } =20 - if ((le16_to_cpu(ctio->flags) & CTIO7_FLAGS_DATA_OUT) && cmd->sess) + if ((ctio_flags & CTIO7_FLAGS_DATA_OUT) && cmd->sess) qlt_chk_edif_rx_sa_delete_pending(vha, cmd->sess, ctio); =20 se_cmd =3D &cmd->se_cmd; --=20 2.43.0 From nobody Wed Sep 10 01:42:33 2025 Received: from mail.cybernetics.com (mail.cybernetics.com [72.215.153.18]) (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 B8D2031158A for ; Mon, 8 Sep 2025 18:56:12 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=72.215.153.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757357774; cv=none; b=PWVzDnw7dEmtFj8QyrxCnvNAduKvikJeaLzWZEyNexe7mnK0vMCeZvuNJrUu6CFOxwrcUAy5SHTtXPap0mhhqSHtognA6G8WH1cFlWLOH2RODb4hALl7KGJ7M4rnQn26wew28XITgv3JiJISH25PZiHv9C7Uwt5AHunmuvNTnpk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757357774; c=relaxed/simple; bh=jKoqQAc1VFhM4L0DcJWxLfr8M9tdHv3HkePDz6djPJ4=; h=Message-ID:Date:MIME-Version:Subject:From:To:Cc:References: In-Reply-To:Content-Type; b=tyTerkNe2kCfbp89ts4KEL58GmtAq6WhHkwRj/Hhu362uXpWlv9/IYm50S5dmJgrzcFnx1CN5fA9aQQSkTPF04cJQ7qVIbMEAnxYiXLuWV5wFM7qySIMAixGcjmjOLvz7nIdEA8pN4I5XwF54D3duXh+7o2X3ao7Rohj6WPqOHQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=cybernetics.com; spf=pass smtp.mailfrom=cybernetics.com; dkim=pass (1024-bit key) header.d=cybernetics.com header.i=@cybernetics.com header.b=akzBGShJ; arc=none smtp.client-ip=72.215.153.18 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=cybernetics.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=cybernetics.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=cybernetics.com header.i=@cybernetics.com header.b="akzBGShJ" Received: from cybernetics.com ([10.10.4.126]) by mail.cybernetics.com with ESMTP id m2DjCuTlLeepoyQC; Mon, 08 Sep 2025 14:56:11 -0400 (EDT) X-Barracuda-Envelope-From: tonyb@cybernetics.com X-Barracuda-RBL-Trusted-Forwarder: 10.10.4.126 X-ASG-Whitelist: Client DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=cybernetics.com; s=mail; bh=NY/Q+BaQ/oifWT98guFvS/KoXG9Li4hZdsQ88vbBeT8=; h=Content-Transfer-Encoding:Content-Type:In-Reply-To:References:Cc:To:From: Content-Language:Subject:MIME-Version:Date:Message-ID; b=akzBGShJlx1/YgkyRBe+ s4IL9CZza7DOaXDEFCRi+A2IhK4u1FiAVrxiyHXMojMD8kXP67XSAIBRhXli8iEsEPAq2YWxzB6h2 b6dfb+NDDNKVLHDtAh54o2V5Jm+Gd1njMj478hobSLGvvE/g7ysAH6EcOOmB3eGS7bipTHoFKA= Received: from [10.157.2.224] (HELO [192.168.200.1]) by cybernetics.com (CommuniGate SPEC SMTP 8.0.5) with ESMTPS id 14189095; Mon, 08 Sep 2025 14:56:11 -0400 Message-ID: X-Barracuda-RBL-Trusted-Forwarder: 10.157.2.224 Date: Mon, 8 Sep 2025 14:56:11 -0400 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 User-Agent: Mozilla Thunderbird Subject: [PATCH 07/15] scsi: qla2xxx: fix term exchange when cmd_sent_to_fw == 1 Content-Language: en-US X-ASG-Orig-Subj: [PATCH 07/15] scsi: qla2xxx: fix term exchange when cmd_sent_to_fw == 1 From: Tony Battersby To: Nilesh Javali , GR-QLogic-Storage-Upstream@marvell.com, "James E.J. Bottomley" , "Martin K. Petersen" Cc: linux-scsi , target-devel@vger.kernel.org, scst-devel@lists.sourceforge.net, "linux-kernel@vger.kernel.org" References: In-Reply-To: Content-Transfer-Encoding: quoted-printable X-Barracuda-Connect: UNKNOWN[10.10.4.126] X-Barracuda-Start-Time: 1757357771 X-Barracuda-URL: https://10.10.4.122:443/cgi-mod/mark.cgi X-Barracuda-BRTS-Status: 0 X-Virus-Scanned: by bsmtpd at cybernetics.com X-Barracuda-Scan-Msg-Size: 3572 X-ASG-Debug-ID: 1757357771-1cf43947df30c3d0001-xx1T2L Content-Type: text/plain; charset="utf-8" (target mode) Properly set the nport_handle field of the terminate exchange message. Previously when this field was not set properly, the term exchange would fail when cmd_sent_to_fw =3D=3D 1 but work when cmd_sent_to_fw =3D=3D 0 (i.= e. it would fail when the HW was actively transferring data or status for the cmd but work when the HW was idle). With this change, term exchange works in any cmd state, which now makes it possible to abort a command that is locked up in the HW. Signed-off-by: Tony Battersby --- drivers/scsi/qla2xxx/qla_target.c | 52 ++++++++++++++++++------------- 1 file changed, 31 insertions(+), 21 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_t= arget.c index 72c74f8f5375..b700bfc642b3 100644 --- a/drivers/scsi/qla2xxx/qla_target.c +++ b/drivers/scsi/qla2xxx/qla_target.c @@ -3622,14 +3622,35 @@ static int __qlt_send_term_exchange(struct qla_qpai= r *qpair, struct qla_tgt_cmd *cmd, struct atio_from_isp *atio) { - struct scsi_qla_host *vha =3D qpair->vha; struct ctio7_to_24xx *ctio24; - request_t *pkt; - int ret =3D 0; + struct scsi_qla_host *vha; + uint16_t loop_id; uint16_t temp; =20 - if (cmd) + if (cmd) { vha =3D cmd->vha; + loop_id =3D cmd->loop_id; + } else { + port_id_t id =3D be_to_port_id(atio->u.isp24.fcp_hdr.s_id); + struct qla_hw_data *ha; + struct fc_port *sess; + unsigned long flags; + + vha =3D qpair->vha; + ha =3D vha->hw; + + /* + * CTIO7_NHANDLE_UNRECOGNIZED works when aborting an idle + * command but not when aborting a command with an active CTIO + * exchange. + */ + loop_id =3D CTIO7_NHANDLE_UNRECOGNIZED; + spin_lock_irqsave(&ha->tgt.sess_lock, flags); + sess =3D qla2x00_find_fcport_by_nportid(vha, &id, 1); + if (sess) + loop_id =3D sess->loop_id; + spin_unlock_irqrestore(&ha->tgt.sess_lock, flags); + } =20 if (cmd) { ql_dbg(ql_dbg_tgt_mgt, vha, 0xe009, @@ -3642,31 +3663,20 @@ static int __qlt_send_term_exchange(struct qla_qpai= r *qpair, vha->vp_idx, le32_to_cpu(atio->u.isp24.exchange_addr)); } =20 - pkt =3D (request_t *)qla2x00_alloc_iocbs_ready(qpair, NULL); - if (pkt =3D=3D NULL) { + ctio24 =3D qla2x00_alloc_iocbs_ready(qpair, NULL); + if (!ctio24) { ql_dbg(ql_dbg_tgt, vha, 0xe050, "qla_target(%d): %s failed: unable to allocate " "request packet\n", vha->vp_idx, __func__); return -ENOMEM; } =20 - if (cmd !=3D NULL) { - if (cmd->state < QLA_TGT_STATE_PROCESSED) { - ql_dbg(ql_dbg_tgt, vha, 0xe051, - "qla_target(%d): Terminating cmd %p with " - "incorrect state %d\n", vha->vp_idx, cmd, - cmd->state); - } else - ret =3D 1; - } - qpair->tgt_counters.num_term_xchg_sent++; - pkt->entry_count =3D 1; - pkt->handle =3D QLA_TGT_SKIP_HANDLE | CTIO_COMPLETION_HANDLE_MARK; =20 - ctio24 =3D (struct ctio7_to_24xx *)pkt; ctio24->entry_type =3D CTIO_TYPE7; - ctio24->nport_handle =3D cpu_to_le16(CTIO7_NHANDLE_UNRECOGNIZED); + ctio24->entry_count =3D 1; + ctio24->handle =3D QLA_TGT_SKIP_HANDLE | CTIO_COMPLETION_HANDLE_MARK; + ctio24->nport_handle =3D cpu_to_le16(loop_id); ctio24->timeout =3D cpu_to_le16(QLA_TGT_TIMEOUT); ctio24->vp_index =3D vha->vp_idx; ctio24->initiator_id =3D be_id_to_le(atio->u.isp24.fcp_hdr.s_id); @@ -3683,7 +3693,7 @@ static int __qlt_send_term_exchange(struct qla_qpair = *qpair, qpair->reqq_start_iocbs(qpair); else qla2x00_start_iocbs(vha, qpair->req); - return ret; + return 0; } =20 static void qlt_send_term_exchange(struct qla_qpair *qpair, --=20 2.43.0 From nobody Wed Sep 10 01:42:33 2025 Received: from mail.cybernetics.com (mail.cybernetics.com [173.71.130.66]) (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 4DFD42E8DEF for ; Mon, 8 Sep 2025 18:58:07 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=173.71.130.66 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757357889; cv=none; b=J3HMteh4adsKSr+iIGD7cKTXzstN5LRm4xd09YwS23GOuM3qJd7cvqbVjU6vLiigTIFF+xyA8fA+VOeIKg/dmePTXsa4fgZiQ1jLiIPcvIJn3smtJo0gpEtIEFnnxXBKTrKhJqIzp5giXhE0SCaqaD6HOgxYDF+VvmPsdc0WpK8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757357889; c=relaxed/simple; bh=z6xiguFRwEVZUVci1ubFJKPnmonNX61NJNbu9I5BV5s=; h=Message-ID:Date:MIME-Version:Subject:From:To:Cc:References: In-Reply-To:Content-Type; b=ETOCYgy/dBm1NUz9iePmMd/WSGO9Eoo/G3Mdi0UK09RrIlBgNtUEr/hX5LA7C7qPB/SlOwP1UJirBPMa3+WGtFTk5gtB7l6H5ZwA3nY8bLGhs4bBE0q9ZN4rHt+GAu706biMVYiGkrtm12OHbXhOOsVf7g3bIjX6AyUtYlEKTlM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=cybernetics.com; spf=pass smtp.mailfrom=cybernetics.com; dkim=pass (1024-bit key) header.d=cybernetics.com header.i=@cybernetics.com header.b=Lln3G0Dr; arc=none smtp.client-ip=173.71.130.66 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=cybernetics.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=cybernetics.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=cybernetics.com header.i=@cybernetics.com header.b="Lln3G0Dr" Received: from cybernetics.com ([10.10.4.126]) by mail.cybernetics.com with ESMTP id LZ0tN8LV2zDlO3DC; Mon, 08 Sep 2025 14:58:06 -0400 (EDT) X-Barracuda-Envelope-From: tonyb@cybernetics.com X-Barracuda-RBL-Trusted-Forwarder: 10.10.4.126 X-ASG-Whitelist: Client DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=cybernetics.com; s=mail; bh=DUwVIZt9/nOUQijIXMuXJwo53fSVFD7gpbSIsIywAHc=; h=Content-Transfer-Encoding:Content-Type:In-Reply-To:References:Cc:To:From: Content-Language:Subject:MIME-Version:Date:Message-ID; b=Lln3G0DrYU6CsWVTFtVJ iX7wA8dfm/ke5BiItobprtlUyhjwfhg/VEP7DtW8tIgm3Pi9kXjOn8V3zl0aw1UE78gCqc1D1T0Qo wnSqj7xCFTxGrwljfl3VmHzHoyI76CzGaumaiIz3z2WokCrKaYgAzx2SsQo1rVb0Y41iQsmP1g= Received: from [10.157.2.224] (HELO [192.168.200.1]) by cybernetics.com (CommuniGate SPEC SMTP 8.0.5) with ESMTPS id 14189143; Mon, 08 Sep 2025 14:58:06 -0400 Message-ID: <80974286-f8ac-4eff-9439-c05fe38716b1@cybernetics.com> X-Barracuda-RBL-Trusted-Forwarder: 10.157.2.224 Date: Mon, 8 Sep 2025 14:58:06 -0400 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 User-Agent: Mozilla Thunderbird Subject: [PATCH 08/15] scsi: qla2xxx: fix oops during cmd abort Content-Language: en-US X-ASG-Orig-Subj: [PATCH 08/15] scsi: qla2xxx: fix oops during cmd abort From: Tony Battersby To: Nilesh Javali , GR-QLogic-Storage-Upstream@marvell.com, "James E.J. Bottomley" , "Martin K. Petersen" Cc: linux-scsi , target-devel@vger.kernel.org, scst-devel@lists.sourceforge.net, "linux-kernel@vger.kernel.org" References: In-Reply-To: Content-Transfer-Encoding: quoted-printable X-Barracuda-Connect: UNKNOWN[10.10.4.126] X-Barracuda-Start-Time: 1757357886 X-Barracuda-URL: https://10.10.4.122:443/cgi-mod/mark.cgi X-Barracuda-BRTS-Status: 0 X-Virus-Scanned: by bsmtpd at cybernetics.com X-Barracuda-Scan-Msg-Size: 19423 X-ASG-Debug-ID: 1757357886-1cf43947df30c450001-xx1T2L Content-Type: text/plain; charset="utf-8" (target mode) There is a race between the following: CPU 1: scst_hw_pending_work_fn() -> sqa_on_hw_pending_cmd_timeout() -> qlt_abort_cmd() -> qlt_unmap_sg() CPU 2: qla_do_work() -> qla24xx_process_response_queue() -> qlt_do_ctio_completion() -> qlt_unmap_sg() Two CPUs calling qlt_unmap_sg() on the same cmd at the same time results in an oops: dma_unmap_sg_attrs() BUG_ON(!valid_dma_direction(dir)); This race is more likely to happen because qlt_abort_cmd() may cause the hardware to send a CTIO. The solution is to lock cmd->qpair->qp_lock_ptr when aborting a command. This makes it possible to check the cmd state and make decisions about what to do without racing with the CTIO handler and other code. - Lock cmd->qpair->qp_lock_ptr when aborting a cmd. - Eliminate cmd->cmd_lock and change cmd->aborted back to a bitfield since it is now protected by qp_lock_ptr just like all the other flags. - Add another command state QLA_TGT_STATE_DONE to avoid any possible races between qlt_abort_cmd() and tgt_ops->free_cmd(). - Add the cmd->sent_term_exchg flag to indicate if qlt_send_term_exchange() has already been called. - For SCST (scst_hw_pending_work_fn()), export qlt_send_term_exchange() and qlt_unmap_sg() so that they can be called directly instead of trying to make qlt_abort_cmd() work for both HW timeout and TMR abort. - Add TRC_CTIO_IGNORED for scst_hw_pending_work_fn(). Fixes: 26f9ce53817a ("scsi: qla2xxx: Fix missed DMA unmap for aborted comma= nds") Signed-off-by: Tony Battersby --- drivers/scsi/qla2xxx/qla_target.c | 204 +++++++++++++---------------- drivers/scsi/qla2xxx/qla_target.h | 19 ++- drivers/scsi/qla2xxx/tcm_qla2xxx.c | 2 + 3 files changed, 105 insertions(+), 120 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_t= arget.c index b700bfc642b3..1160ca4c118f 100644 --- a/drivers/scsi/qla2xxx/qla_target.c +++ b/drivers/scsi/qla2xxx/qla_target.c @@ -104,8 +104,6 @@ static void qlt_response_pkt(struct scsi_qla_host *ha, = struct rsp_que *rsp, response_t *pkt); static int qlt_issue_task_mgmt(struct fc_port *sess, u64 lun, int fn, void *iocb, int flags); -static void qlt_send_term_exchange(struct qla_qpair *, struct qla_tgt_cmd - *cmd, struct atio_from_isp *atio, int ha_locked, int ul_abort); static void qlt_alloc_qfull_cmd(struct scsi_qla_host *vha, struct atio_from_isp *atio, uint16_t status, int qfull); static void qlt_disable_vha(struct scsi_qla_host *vha); @@ -136,20 +134,6 @@ static struct workqueue_struct *qla_tgt_wq; static DEFINE_MUTEX(qla_tgt_mutex); static LIST_HEAD(qla_tgt_glist); =20 -static const char *prot_op_str(u32 prot_op) -{ - switch (prot_op) { - case TARGET_PROT_NORMAL: return "NORMAL"; - case TARGET_PROT_DIN_INSERT: return "DIN_INSERT"; - case TARGET_PROT_DOUT_INSERT: return "DOUT_INSERT"; - case TARGET_PROT_DIN_STRIP: return "DIN_STRIP"; - case TARGET_PROT_DOUT_STRIP: return "DOUT_STRIP"; - case TARGET_PROT_DIN_PASS: return "DIN_PASS"; - case TARGET_PROT_DOUT_PASS: return "DOUT_PASS"; - default: return "UNKNOWN"; - } -} - /* This API intentionally takes dest as a parameter, rather than returning * int value to avoid caller forgetting to issue wmb() after the store */ void qlt_do_generation_tick(struct scsi_qla_host *vha, int *dest) @@ -252,7 +236,7 @@ static void qlt_queue_unknown_atio(scsi_qla_host_t *vha, return; =20 out_term: - qlt_send_term_exchange(vha->hw->base_qpair, NULL, atio, ha_locked, 0); + qlt_send_term_exchange(vha->hw->base_qpair, NULL, atio, ha_locked); goto out; } =20 @@ -271,7 +255,7 @@ static void qlt_try_to_dequeue_unknown_atios(struct scs= i_qla_host *vha, "Freeing unknown %s %p, because of Abort\n", "ATIO_TYPE7", u); qlt_send_term_exchange(vha->hw->base_qpair, NULL, - &u->atio, ha_locked, 0); + &u->atio, ha_locked); goto abort; } =20 @@ -285,7 +269,7 @@ static void qlt_try_to_dequeue_unknown_atios(struct scs= i_qla_host *vha, "Freeing unknown %s %p, because tgt is being stopped\n", "ATIO_TYPE7", u); qlt_send_term_exchange(vha->hw->base_qpair, NULL, - &u->atio, ha_locked, 0); + &u->atio, ha_locked); } else { ql_dbg(ql_dbg_async + ql_dbg_verbose, vha, 0x503d, "Reschedule u %p, vha %p, host %p\n", u, vha, host); @@ -2447,7 +2431,7 @@ static int qlt_pci_map_calc_cnt(struct qla_tgt_prm *p= rm) return -1; } =20 -static void qlt_unmap_sg(struct scsi_qla_host *vha, struct qla_tgt_cmd *cm= d) +void qlt_unmap_sg(struct scsi_qla_host *vha, struct qla_tgt_cmd *cmd) { struct qla_hw_data *ha; struct qla_qpair *qpair; @@ -2473,6 +2457,7 @@ static void qlt_unmap_sg(struct scsi_qla_host *vha, s= truct qla_tgt_cmd *cmd) =20 dma_pool_free(ha->dl_dma_pool, cmd->ctx, cmd->ctx->crc_ctx_dma); } +EXPORT_SYMBOL(qlt_unmap_sg); =20 static int qlt_check_reserve_free_req(struct qla_qpair *qpair, uint32_t req_cnt) @@ -3461,7 +3446,6 @@ qlt_handle_dif_error(struct qla_qpair *qpair, struct = qla_tgt_cmd *cmd, uint8_t *ep =3D &sts->expected_dif[0]; uint64_t lba =3D cmd->se_cmd.t_task_lba; uint8_t scsi_status, sense_key, asc, ascq; - unsigned long flags; struct scsi_qla_host *vha =3D cmd->vha; =20 cmd->trc_flags |=3D TRC_DIF_ERR; @@ -3535,13 +3519,10 @@ qlt_handle_dif_error(struct qla_qpair *qpair, struc= t qla_tgt_cmd *cmd, vha->hw->tgt.tgt_ops->handle_data(cmd); break; default: - spin_lock_irqsave(&cmd->cmd_lock, flags); - if (cmd->aborted) { - spin_unlock_irqrestore(&cmd->cmd_lock, flags); + if (cmd->sent_term_exchg) { vha->hw->tgt.tgt_ops->free_cmd(cmd); break; } - spin_unlock_irqrestore(&cmd->cmd_lock, flags); =20 qlt_send_resp_ctio(qpair, cmd, scsi_status, sense_key, asc, ascq); @@ -3696,9 +3677,22 @@ static int __qlt_send_term_exchange(struct qla_qpair= *qpair, return 0; } =20 -static void qlt_send_term_exchange(struct qla_qpair *qpair, - struct qla_tgt_cmd *cmd, struct atio_from_isp *atio, int ha_locked, - int ul_abort) +/* + * Aborting a command that is active in the FW (i.e. cmd->cmd_sent_to_fw = =3D=3D 1) + * will usually trigger the FW to send a completion CTIO with error status, + * and the driver will then call the ->handle_data() or ->free_cmd() callb= acks. + * This can be used to clear a command that is locked up in the FW unless = there + * is something more seriously wrong. + * + * Aborting a command that is not active in the FW (i.e. + * cmd->cmd_sent_to_fw =3D=3D 0) will not directly trigger any callbacks. = Instead, + * when the target mode midlevel calls qlt_rdy_to_xfer() or + * qlt_xmit_response(), the driver will see that the cmd has been aborted = and + * call the appropriate callback immediately without performing the reques= ted + * operation. + */ +void qlt_send_term_exchange(struct qla_qpair *qpair, + struct qla_tgt_cmd *cmd, struct atio_from_isp *atio, int ha_locked) { struct scsi_qla_host *vha; unsigned long flags =3D 0; @@ -3722,10 +3716,14 @@ static void qlt_send_term_exchange(struct qla_qpair= *qpair, qlt_alloc_qfull_cmd(vha, atio, 0, 0); =20 done: - if (cmd && !ul_abort && !cmd->aborted) { - if (cmd->sg_mapped) - qlt_unmap_sg(vha, cmd); - vha->hw->tgt.tgt_ops->free_cmd(cmd); + if (cmd) { + /* + * Set this even if -ENOMEM above, since term exchange will be + * sent eventually... + */ + cmd->sent_term_exchg =3D 1; + cmd->aborted =3D 1; + cmd->jiffies_at_term_exchg =3D jiffies; } =20 if (!ha_locked) @@ -3733,6 +3731,7 @@ static void qlt_send_term_exchange(struct qla_qpair *= qpair, =20 return; } +EXPORT_SYMBOL(qlt_send_term_exchange); =20 static void qlt_init_term_exchange(struct scsi_qla_host *vha) { @@ -3783,38 +3782,35 @@ static void qlt_chk_exch_leak_thresh_hold(struct sc= si_qla_host *vha) =20 int qlt_abort_cmd(struct qla_tgt_cmd *cmd) { - struct qla_tgt *tgt =3D cmd->tgt; - struct scsi_qla_host *vha =3D tgt->vha; - struct se_cmd *se_cmd =3D &cmd->se_cmd; + struct scsi_qla_host *vha =3D cmd->vha; + struct qla_qpair *qpair =3D cmd->qpair; unsigned long flags; =20 - ql_dbg(ql_dbg_tgt_mgt, vha, 0xf014, - "qla_target(%d): terminating exchange for aborted cmd=3D%p " - "(se_cmd=3D%p, tag=3D%llu)", vha->vp_idx, cmd, &cmd->se_cmd, - se_cmd->tag); - - spin_lock_irqsave(&cmd->cmd_lock, flags); - if (cmd->aborted) { - if (cmd->sg_mapped) - qlt_unmap_sg(vha, cmd); + spin_lock_irqsave(qpair->qp_lock_ptr, flags); =20 - spin_unlock_irqrestore(&cmd->cmd_lock, flags); - /* - * It's normal to see 2 calls in this path: - * 1) XFER Rdy completion + CMD_T_ABORT - * 2) TCM TMR - drain_state_list - */ - ql_dbg(ql_dbg_tgt_mgt, vha, 0xf016, - "multiple abort. %p transport_state %x, t_state %x, " - "se_cmd_flags %x\n", cmd, cmd->se_cmd.transport_state, - cmd->se_cmd.t_state, cmd->se_cmd.se_cmd_flags); - return -EIO; + ql_dbg(ql_dbg_tgt_mgt, vha, 0xf014, + "qla_target(%d): tag %lld: cmd being aborted (state %d) %s; %s\n", + vha->vp_idx, cmd->se_cmd.tag, cmd->state, + cmd->cmd_sent_to_fw ? "sent to fw" : "not sent to fw", + cmd->aborted ? "aborted" : "not aborted"); + + if (cmd->state !=3D QLA_TGT_STATE_DONE && !cmd->sent_term_exchg) { + if (!qpair->fw_started || + cmd->reset_count !=3D qpair->chip_reset) { + /* + * Chip was reset; just pretend that we sent the term + * exchange. + */ + cmd->sent_term_exchg =3D 1; + cmd->aborted =3D 1; + cmd->jiffies_at_term_exchg =3D jiffies; + } else { + qlt_send_term_exchange(qpair, cmd, &cmd->atio, 1); + } } - cmd->aborted =3D 1; - cmd->trc_flags |=3D TRC_ABORT; - spin_unlock_irqrestore(&cmd->cmd_lock, flags); =20 - qlt_send_term_exchange(cmd->qpair, cmd, &cmd->atio, 0, 1); + spin_unlock_irqrestore(qpair->qp_lock_ptr, flags); + return 0; } EXPORT_SYMBOL(qlt_abort_cmd); @@ -3845,40 +3841,6 @@ void qlt_free_cmd(struct qla_tgt_cmd *cmd) } EXPORT_SYMBOL(qlt_free_cmd); =20 -/* - * ha->hardware_lock supposed to be held on entry. Might drop it, then rea= quire - */ -static int qlt_term_ctio_exchange(struct qla_qpair *qpair, void *ctio, - struct qla_tgt_cmd *cmd, uint32_t status) -{ - int term =3D 0; - struct scsi_qla_host *vha =3D qpair->vha; - - if (cmd->se_cmd.prot_op) - ql_dbg(ql_dbg_tgt_dif, vha, 0xe013, - "Term DIF cmd: lba[0x%llx|%lld] len[0x%x] " - "se_cmd=3D%p tag[%x] op %#x/%s", - cmd->lba, cmd->lba, - cmd->num_blks, &cmd->se_cmd, - cmd->atio.u.isp24.exchange_addr, - cmd->se_cmd.prot_op, - prot_op_str(cmd->se_cmd.prot_op)); - - if (ctio !=3D NULL) { - struct ctio7_from_24xx *c =3D (struct ctio7_from_24xx *)ctio; - - term =3D !(c->flags & - cpu_to_le16(OF_TERM_EXCH)); - } else - term =3D 1; - - if (term) - qlt_send_term_exchange(qpair, cmd, &cmd->atio, 1, 0); - - return term; -} - - /* ha->hardware_lock supposed to be held on entry */ static void *qlt_ctio_to_cmd(struct scsi_qla_host *vha, struct rsp_que *rsp, uint32_t handle, void *ctio) @@ -3984,22 +3946,35 @@ static void qlt_do_ctio_completion(struct scsi_qla_= host *vha, qlt_unmap_sg(vha, cmd); =20 if (unlikely(status !=3D CTIO_SUCCESS)) { + bool term_exchg =3D false; + + /* + * If the hardware terminated the exchange, then we don't need + * to send an explicit term exchange message. + */ + if (ctio_flags & OF_TERM_EXCH) { + cmd->sent_term_exchg =3D 1; + cmd->aborted =3D 1; + cmd->jiffies_at_term_exchg =3D jiffies; + } + switch (status & 0xFFFF) { case CTIO_INVALID_RX_ID: + term_exchg =3D true; if (printk_ratelimit()) dev_info(&vha->hw->pdev->dev, "qla_target(%d): CTIO with INVALID_RX_ID ATIO attr %x CTIO Flags %= x|%x\n", vha->vp_idx, cmd->atio.u.isp24.attr, ((cmd->ctio_flags >> 9) & 0xf), cmd->ctio_flags); - break; + case CTIO_LIP_RESET: case CTIO_TARGET_RESET: case CTIO_ABORTED: - /* driver request abort via Terminate exchange */ + term_exchg =3D true; + fallthrough; case CTIO_TIMEOUT: - /* They are OK */ ql_dbg(ql_dbg_tgt_mgt, vha, 0xf058, "qla_target(%d): CTIO with " "status %#x received, state %x, se_cmd %p, " @@ -4020,6 +3995,7 @@ static void qlt_do_ctio_completion(struct scsi_qla_ho= st *vha, logged_out ? "PORT LOGGED OUT" : "PORT UNAVAILABLE", status, cmd->state, se_cmd); =20 + term_exchg =3D true; if (logged_out && cmd->sess) { /* * Session is already logged out, but we need @@ -4065,19 +4041,21 @@ static void qlt_do_ctio_completion(struct scsi_qla_= host *vha, break; } =20 + cmd->trc_flags |=3D TRC_CTIO_ERR; =20 - /* "cmd->aborted" means - * cmd is already aborted/terminated, we don't - * need to terminate again. The exchange is already - * cleaned up/freed at FW level. Just cleanup at driver - * level. + /* + * In state QLA_TGT_STATE_NEED_DATA the failed CTIO was for + * Data-Out, so either abort the exchange or try sending check + * condition with sense data depending on the severity of + * the error. In state QLA_TGT_STATE_PROCESSED the failed CTIO + * was for status (and possibly Data-In), so don't try sending + * an error status again in that case (if the error was for + * Data-In with status, we could try sending status without + * Data-In, but we don't do that currently). */ - if ((cmd->state !=3D QLA_TGT_STATE_NEED_DATA) && - (!cmd->aborted)) { - cmd->trc_flags |=3D TRC_CTIO_ERR; - if (qlt_term_ctio_exchange(qpair, ctio, cmd, status)) - return; - } + if (!cmd->sent_term_exchg && + (term_exchg || cmd->state !=3D QLA_TGT_STATE_NEED_DATA)) + qlt_send_term_exchange(qpair, cmd, &cmd->atio, 1); } =20 if (cmd->state =3D=3D QLA_TGT_STATE_PROCESSED) { @@ -4167,7 +4145,6 @@ static void __qlt_do_work(struct qla_tgt_cmd *cmd) goto out_term; } =20 - spin_lock_init(&cmd->cmd_lock); cdb =3D &atio->u.isp24.fcp_cmnd.cdb[0]; cmd->se_cmd.tag =3D le32_to_cpu(atio->u.isp24.exchange_addr); =20 @@ -4204,7 +4181,7 @@ static void __qlt_do_work(struct qla_tgt_cmd *cmd) */ cmd->trc_flags |=3D TRC_DO_WORK_ERR; spin_lock_irqsave(qpair->qp_lock_ptr, flags); - qlt_send_term_exchange(qpair, NULL, &cmd->atio, 1, 0); + qlt_send_term_exchange(qpair, NULL, &cmd->atio, 1); =20 qlt_decr_num_pend_cmds(vha); cmd->vha->hw->tgt.tgt_ops->rel_cmd(cmd); @@ -5363,6 +5340,7 @@ static void qlt_handle_imm_notify(struct scsi_qla_hos= t *vha, if (qlt_24xx_handle_els(vha, iocb) =3D=3D 0) send_notify_ack =3D 0; break; + default: ql_dbg(ql_dbg_tgt_mgt, vha, 0xf06d, "qla_target(%d): Received unknown immediate " @@ -5397,7 +5375,7 @@ static int __qlt_send_busy(struct qla_qpair *qpair, sess =3D qla2x00_find_fcport_by_nportid(vha, &id, 1); spin_unlock_irqrestore(&ha->tgt.sess_lock, flags); if (!sess) { - qlt_send_term_exchange(qpair, NULL, atio, 1, 0); + qlt_send_term_exchange(qpair, NULL, atio, 1); return 0; } /* Sending marker isn't necessary, since we called from ISR */ @@ -5626,7 +5604,7 @@ static void qlt_24xx_atio_pkt(struct scsi_qla_host *v= ha, ql_dbg(ql_dbg_tgt, vha, 0xe05f, "qla_target: Unable to send command to target, sending TERM EXCHAN= GE for rsp\n"); qlt_send_term_exchange(ha->base_qpair, NULL, - atio, 1, 0); + atio, 1); break; case -EBUSY: ql_dbg(ql_dbg_tgt, vha, 0xe060, @@ -5833,7 +5811,7 @@ static void qlt_response_pkt(struct scsi_qla_host *vh= a, ql_dbg(ql_dbg_tgt, vha, 0xe05f, "qla_target: Unable to send command to target, sending TERM EXCHAN= GE for rsp\n"); qlt_send_term_exchange(rsp->qpair, NULL, - atio, 1, 0); + atio, 1); break; case -EBUSY: ql_dbg(ql_dbg_tgt, vha, 0xe060, @@ -6723,7 +6701,7 @@ qlt_24xx_process_atio_queue(struct scsi_qla_host *vha= , uint8_t ha_locked) =20 adjust_corrupted_atio(pkt); qlt_send_term_exchange(ha->base_qpair, NULL, pkt, - ha_locked, 0); + ha_locked); } else { qlt_24xx_atio_pkt_all_vps(vha, (struct atio_from_isp *)pkt, ha_locked); diff --git a/drivers/scsi/qla2xxx/qla_target.h b/drivers/scsi/qla2xxx/qla_t= arget.h index 15a59c125c53..adbc2a05b159 100644 --- a/drivers/scsi/qla2xxx/qla_target.h +++ b/drivers/scsi/qla2xxx/qla_target.h @@ -754,6 +754,7 @@ int qla2x00_wait_for_hba_online(struct scsi_qla_host *); #define QLA_TGT_STATE_NEED_DATA 1 /* target needs data to continue */ #define QLA_TGT_STATE_DATA_IN 2 /* Data arrived + target processing */ #define QLA_TGT_STATE_PROCESSED 3 /* target done processing */ +#define QLA_TGT_STATE_DONE 4 /* cmd being freed */ =20 /* ATIO task_codes field */ #define ATIO_SIMPLE_QUEUE 0 @@ -858,6 +859,7 @@ enum trace_flags { TRC_DATA_IN =3D BIT_18, TRC_ABORT =3D BIT_19, TRC_DIF_ERR =3D BIT_20, + TRC_CTIO_IGNORED =3D BIT_21, }; =20 struct qla_tgt_cmd { @@ -876,8 +878,6 @@ struct qla_tgt_cmd { /* Sense buffer that will be mapped into outgoing status */ unsigned char sense_buffer[TRANSPORT_SENSE_BUFFER]; =20 - spinlock_t cmd_lock; - /* to save extra sess dereferences */ unsigned int conf_compl_supported:1; unsigned int sg_mapped:1; unsigned int write_data_transferred:1; @@ -887,13 +887,14 @@ struct qla_tgt_cmd { unsigned int cmd_in_wq:1; unsigned int edif:1; =20 + /* Set if the exchange has been terminated. */ + unsigned int sent_term_exchg:1; + /* - * This variable may be set from outside the LIO and I/O completion - * callback functions. Do not declare this member variable as a - * bitfield to avoid a read-modify-write operation when this variable - * is set. + * Set if sent_term_exchg is set, or if the cmd was aborted by a TMR, + * or if some other error prevents normal processing of the command. */ - unsigned int aborted; + unsigned int aborted:1; =20 struct scatterlist *sg; /* cmd data buffer SG vector */ int sg_cnt; /* SG segments count */ @@ -932,6 +933,7 @@ struct qla_tgt_cmd { #define DIF_BUNDL_DMA_VALID 1 uint16_t prot_flags; =20 + unsigned long jiffies_at_term_exchg; uint64_t jiffies_at_alloc; uint64_t jiffies_at_free; =20 @@ -1055,6 +1057,9 @@ extern void qlt_response_pkt_all_vps(struct scsi_qla_= host *, struct rsp_que *, extern int qlt_rdy_to_xfer(struct qla_tgt_cmd *); extern int qlt_xmit_response(struct qla_tgt_cmd *, int, uint8_t); extern int qlt_abort_cmd(struct qla_tgt_cmd *); +void qlt_send_term_exchange(struct qla_qpair *qpair, + struct qla_tgt_cmd *cmd, struct atio_from_isp *atio, int ha_locked); +void qlt_unmap_sg(struct scsi_qla_host *vha, struct qla_tgt_cmd *cmd); extern void qlt_xmit_tm_rsp(struct qla_tgt_mgmt_cmd *); extern void qlt_free_mcmd(struct qla_tgt_mgmt_cmd *); extern void qlt_free_cmd(struct qla_tgt_cmd *cmd); diff --git a/drivers/scsi/qla2xxx/tcm_qla2xxx.c b/drivers/scsi/qla2xxx/tcm_= qla2xxx.c index ceaf1c7b1d17..169219fe47a2 100644 --- a/drivers/scsi/qla2xxx/tcm_qla2xxx.c +++ b/drivers/scsi/qla2xxx/tcm_qla2xxx.c @@ -303,6 +303,8 @@ static void tcm_qla2xxx_rel_cmd(struct qla_tgt_cmd *cmd) */ static void tcm_qla2xxx_free_cmd(struct qla_tgt_cmd *cmd) { + cmd->state =3D QLA_TGT_STATE_DONE; + cmd->qpair->tgt_counters.core_qla_free_cmd++; cmd->cmd_in_wq =3D 1; =20 --=20 2.43.0 From nobody Wed Sep 10 01:42:33 2025 Received: from mail.cybernetics.com (mail.cybernetics.com [72.215.153.18]) (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 5EF3F80B for ; Mon, 8 Sep 2025 19:01:06 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=72.215.153.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757358067; cv=none; b=MC8Qj/gYQZdauzp0iKTa+ouoOkfP2v1sN3xscVPl4jhWpMf9BTPbw16lzySf67KKWulPUE1gjzaR3NQ2owKTr38cYg7WYPJ1lH+vLcQ+nJpbk5I+WfxRdNHBVflPnllX9sGr27Bnsbnt+BsyeT5JRtbmY/8BLt47SgD5LcYrbHo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757358067; c=relaxed/simple; bh=v5605DrgHXYgGUTIdSKUVT8UPJmtSDjfC6fjfhBimzU=; h=Message-ID:Date:MIME-Version:Subject:From:To:Cc:References: In-Reply-To:Content-Type; b=DUAKXQP/LvTnDE7EwC0p9cR73GDYncXMu2hZVFHhEJd+OERLKRc/zojPa04r0gwXv+1OE3yubfp1asotcF1FTXaLi9hzzr9CE307e6dHRpT93wJo2HLF6OR/b1mScxJiTgRNIx9xg6rhKYK3d+ojyUQxzmSI1HyQ8b0Fg4J8PHM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=cybernetics.com; spf=pass smtp.mailfrom=cybernetics.com; dkim=pass (1024-bit key) header.d=cybernetics.com header.i=@cybernetics.com header.b=lURwNsVG; arc=none smtp.client-ip=72.215.153.18 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=cybernetics.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=cybernetics.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=cybernetics.com header.i=@cybernetics.com header.b="lURwNsVG" Received: from cybernetics.com ([10.10.4.126]) by mail.cybernetics.com with ESMTP id flbENCVvvM0ThneH; Mon, 08 Sep 2025 15:01:05 -0400 (EDT) X-Barracuda-Envelope-From: tonyb@cybernetics.com X-Barracuda-RBL-Trusted-Forwarder: 10.10.4.126 X-ASG-Whitelist: Client DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=cybernetics.com; s=mail; bh=wLZyR4Gp4v+ggLzVtImTsVNMAUlLsEeuvD/tSV7JM4o=; h=Content-Transfer-Encoding:Content-Type:In-Reply-To:References:Cc:To:From: Content-Language:Subject:MIME-Version:Date:Message-ID; b=lURwNsVGJlJe2GnSrppf i916qNPwKA0hiy0xmZM+MaCOtQbIWBAqvGdjD4NFwqOdx2z/9dK5SXGPUY7kC0FfUBfnPZaL1jvGi b+KNJtolcbX27K1SagA9yu/PykUfYVbX1bbW7bn177KAm3hcp4SAKY7KED33WWmm7ZYnXDPQnY= Received: from [10.157.2.224] (HELO [192.168.200.1]) by cybernetics.com (CommuniGate SPEC SMTP 8.0.5) with ESMTPS id 14189145; Mon, 08 Sep 2025 15:01:05 -0400 Message-ID: <1d78cff6-d94d-43b9-a15c-6de3889d6066@cybernetics.com> X-Barracuda-RBL-Trusted-Forwarder: 10.157.2.224 Date: Mon, 8 Sep 2025 15:01:04 -0400 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 User-Agent: Mozilla Thunderbird Subject: [PATCH 09/15] scsi: qla2xxx: improve checks in qlt_xmit_response / qlt_rdy_to_xfer Content-Language: en-US X-ASG-Orig-Subj: [PATCH 09/15] scsi: qla2xxx: improve checks in qlt_xmit_response / qlt_rdy_to_xfer From: Tony Battersby To: Nilesh Javali , GR-QLogic-Storage-Upstream@marvell.com, "James E.J. Bottomley" , "Martin K. Petersen" Cc: linux-scsi , target-devel@vger.kernel.org, scst-devel@lists.sourceforge.net, "linux-kernel@vger.kernel.org" References: In-Reply-To: Content-Transfer-Encoding: quoted-printable X-Barracuda-Connect: UNKNOWN[10.10.4.126] X-Barracuda-Start-Time: 1757358065 X-Barracuda-URL: https://10.10.4.122:443/cgi-mod/mark.cgi X-Barracuda-BRTS-Status: 1 X-Virus-Scanned: by bsmtpd at cybernetics.com X-Barracuda-Scan-Msg-Size: 5659 X-ASG-Debug-ID: 1757358065-1cf43947df30c540001-xx1T2L Content-Type: text/plain; charset="utf-8" (target mode) Similar fixes to both functions: qlt_xmit_response: - If the cmd cannot be processed, remember to call ->free_cmd() to prevent the target-mode midlevel from seeing a cmd lockup. - Do not try to send the response if the exchange has been terminated. - Check for chip reset once after lock instead of both before and after lock. - Give errors from qlt_pre_xmit_response() a lower priority to compensate for removing the first check for chip reset. qlt_rdy_to_xfer: - Check for chip reset after lock instead of before lock to avoid races. - Do not try to receive data if the exchange has been terminated. - Give errors from qlt_pci_map_calc_cnt() a lower priority to compensate for moving the check for chip reset. Signed-off-by: Tony Battersby --- drivers/scsi/qla2xxx/qla_target.c | 86 +++++++++++++++++-------------- 1 file changed, 48 insertions(+), 38 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_t= arget.c index 1160ca4c118f..da010de9ba8a 100644 --- a/drivers/scsi/qla2xxx/qla_target.c +++ b/drivers/scsi/qla2xxx/qla_target.c @@ -3207,12 +3207,7 @@ int qlt_xmit_response(struct qla_tgt_cmd *cmd, int x= mit_type, uint32_t full_req_cnt =3D 0; unsigned long flags =3D 0; int res; - - if (!qpair->fw_started || (cmd->reset_count !=3D qpair->chip_reset) || - (cmd->sess && cmd->sess->deleted)) { - cmd->state =3D QLA_TGT_STATE_PROCESSED; - return 0; - } + int pre_xmit_res; =20 ql_dbg_qp(ql_dbg_tgt, qpair, 0xe018, "is_send_status=3D%d, cmd->bufflen=3D%d, cmd->sg_cnt=3D%d, cmd->dma_d= ata_direction=3D%d se_cmd[%p] qp %d\n", @@ -3220,33 +3215,39 @@ int qlt_xmit_response(struct qla_tgt_cmd *cmd, int = xmit_type, 1 : 0, cmd->bufflen, cmd->sg_cnt, cmd->dma_data_direction, &cmd->se_cmd, qpair->id); =20 - res =3D qlt_pre_xmit_response(cmd, &prm, xmit_type, scsi_status, + pre_xmit_res =3D qlt_pre_xmit_response(cmd, &prm, xmit_type, scsi_status, &full_req_cnt); - if (unlikely(res !=3D 0)) { - return res; - } + /* + * Check pre_xmit_res later because we want to check other errors + * first. + */ =20 spin_lock_irqsave(qpair->qp_lock_ptr, flags); =20 + if (unlikely(cmd->sent_term_exchg || + cmd->sess->deleted || + !qpair->fw_started || + cmd->reset_count !=3D qpair->chip_reset)) { + ql_dbg(ql_dbg_tgt_mgt, vha, 0xe101, + "qla_target(%d): tag %lld: skipping send response for aborted cmd\n", + vha->vp_idx, cmd->se_cmd.tag); + qlt_unmap_sg(vha, cmd); + cmd->state =3D QLA_TGT_STATE_PROCESSED; + vha->hw->tgt.tgt_ops->free_cmd(cmd); + spin_unlock_irqrestore(qpair->qp_lock_ptr, flags); + return 0; + } + + /* Check for errors from qlt_pre_xmit_response(). */ + res =3D pre_xmit_res; + if (unlikely(res)) + goto out_unmap_unlock; + if (xmit_type =3D=3D QLA_TGT_XMIT_STATUS) qpair->tgt_counters.core_qla_snd_status++; else qpair->tgt_counters.core_qla_que_buf++; =20 - if (!qpair->fw_started || cmd->reset_count !=3D qpair->chip_reset) { - /* - * Either the port is not online or this request was from - * previous life, just abort the processing. - */ - cmd->state =3D QLA_TGT_STATE_PROCESSED; - ql_dbg_qp(ql_dbg_async, qpair, 0xe101, - "RESET-RSP online/active/old-count/new-count =3D %d/%d/%d/%d.\n", - vha->flags.online, qla2x00_reset_active(vha), - cmd->reset_count, qpair->chip_reset); - res =3D 0; - goto out_unmap_unlock; - } - /* Does F/W have an IOCBs for this request */ res =3D qlt_check_reserve_free_req(qpair, full_req_cnt); if (unlikely(res)) @@ -3361,6 +3362,7 @@ int qlt_rdy_to_xfer(struct qla_tgt_cmd *cmd) struct qla_tgt_prm prm; unsigned long flags =3D 0; int res =3D 0; + int pci_map_res; struct qla_qpair *qpair =3D cmd->qpair; =20 memset(&prm, 0, sizeof(prm)); @@ -3369,28 +3371,36 @@ int qlt_rdy_to_xfer(struct qla_tgt_cmd *cmd) prm.sg =3D NULL; prm.req_cnt =3D 1; =20 - if (!qpair->fw_started || (cmd->reset_count !=3D qpair->chip_reset) || - (cmd->sess && cmd->sess->deleted)) { - /* - * Either the port is not online or this request was from - * previous life, just abort the processing. - */ + /* Calculate number of entries and segments required */ + pci_map_res =3D qlt_pci_map_calc_cnt(&prm); + /* + * Check pci_map_res later because we want to check other errors first. + */ + + spin_lock_irqsave(qpair->qp_lock_ptr, flags); + + if (unlikely(cmd->sent_term_exchg || + cmd->sess->deleted || + !qpair->fw_started || + cmd->reset_count !=3D qpair->chip_reset)) { + ql_dbg(ql_dbg_tgt_mgt, vha, 0xe102, + "qla_target(%d): tag %lld: skipping data-out for aborted cmd\n", + vha->vp_idx, cmd->se_cmd.tag); + qlt_unmap_sg(vha, cmd); cmd->aborted =3D 1; cmd->write_data_transferred =3D 0; cmd->state =3D QLA_TGT_STATE_DATA_IN; vha->hw->tgt.tgt_ops->handle_data(cmd); - ql_dbg_qp(ql_dbg_async, qpair, 0xe102, - "RESET-XFR online/active/old-count/new-count =3D %d/%d/%d/%d.\n", - vha->flags.online, qla2x00_reset_active(vha), - cmd->reset_count, qpair->chip_reset); + spin_unlock_irqrestore(qpair->qp_lock_ptr, flags); return 0; } =20 - /* Calculate number of entries and segments required */ - if (qlt_pci_map_calc_cnt(&prm) !=3D 0) - return -EAGAIN; + /* Check for errors from qlt_pci_map_calc_cnt(). */ + if (unlikely(pci_map_res !=3D 0)) { + res =3D -EAGAIN; + goto out_unlock_free_unmap; + } =20 - spin_lock_irqsave(qpair->qp_lock_ptr, flags); /* Does F/W have an IOCBs for this request */ res =3D qlt_check_reserve_free_req(qpair, prm.req_cnt); if (res !=3D 0) --=20 2.43.0 From nobody Wed Sep 10 01:42:33 2025 Received: from mail.cybernetics.com (mail.cybernetics.com [72.215.153.18]) (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 1F0241F09B6 for ; Mon, 8 Sep 2025 19:02:50 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=72.215.153.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757358172; cv=none; b=H9oWfGZ+NBOOvvO0UGDa6zmYzR2pXRKLT0SG3g068arIjnukigRH+AL5M6vzmxzCYtRCxr1wk2+yTdjcekBBXuo2McUXJelAxryjIRNQ6aXxiQ00HX+2vlfeRm/DhNfN+BvoIe0cISy27wbhyqmRwN109amaUAlQFFXLWUuuEwc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757358172; c=relaxed/simple; bh=RFHo8YfgvHGQHVv4bNsSc49nUKjMyszsYY0LnWJshlg=; h=Message-ID:Date:MIME-Version:Subject:From:To:Cc:References: In-Reply-To:Content-Type; b=SuQkU9ehiUt0EK/vEHwMXyqobqQGKUfM210QxBeRUWv6WOV4owzFHaveh0cGsg4ubva4U2lZMd7iT58Q5CW8Q9xB6YMplZDHLlkaM7IkPZRkvH8Pm+6FVqFsaXFAbDwCFdrxJFrtJnNfHcKoHkEOMsJ4S+mBddQx94WiWZhwgNQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=cybernetics.com; spf=pass smtp.mailfrom=cybernetics.com; dkim=pass (1024-bit key) header.d=cybernetics.com header.i=@cybernetics.com header.b=LmH6QYGZ; arc=none smtp.client-ip=72.215.153.18 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=cybernetics.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=cybernetics.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=cybernetics.com header.i=@cybernetics.com header.b="LmH6QYGZ" Received: from cybernetics.com ([10.10.4.126]) by mail.cybernetics.com with ESMTP id A7D5S2UZxmI9pypi; Mon, 08 Sep 2025 15:02:49 -0400 (EDT) X-Barracuda-Envelope-From: tonyb@cybernetics.com X-Barracuda-RBL-Trusted-Forwarder: 10.10.4.126 X-ASG-Whitelist: Client DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=cybernetics.com; s=mail; bh=dXHWfaQY+7UKSGl6VoUqEdWo4sqvq0kQ+TbdxxZkXwE=; h=Content-Transfer-Encoding:Content-Type:In-Reply-To:References:Cc:To:From: Content-Language:Subject:MIME-Version:Date:Message-ID; b=LmH6QYGZ4whez3nIyE/z RCDHlmC/J7qkVc5cAJERTv30VZC2/BYmiuXI7FATQqm1WI6NrQWG7b2xd/H/SFEwF7LSrZ3hFyRv/ v0BGEBnLsJIiUV7WRUjl7MKGQSOh+IKQpJDjhThJ4ijLLwusGCAxHU+pSvkL9DxZJzdFODBGLc= Received: from [10.157.2.224] (HELO [192.168.200.1]) by cybernetics.com (CommuniGate SPEC SMTP 8.0.5) with ESMTPS id 14189092; Mon, 08 Sep 2025 15:02:49 -0400 Message-ID: X-Barracuda-RBL-Trusted-Forwarder: 10.157.2.224 Date: Mon, 8 Sep 2025 15:02:49 -0400 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 User-Agent: Mozilla Thunderbird Subject: [PATCH 10/15] scsi: qla2xxx: fix TMR failure handling Content-Language: en-US X-ASG-Orig-Subj: [PATCH 10/15] scsi: qla2xxx: fix TMR failure handling From: Tony Battersby To: Nilesh Javali , GR-QLogic-Storage-Upstream@marvell.com, "James E.J. Bottomley" , "Martin K. Petersen" Cc: linux-scsi , target-devel@vger.kernel.org, scst-devel@lists.sourceforge.net, "linux-kernel@vger.kernel.org" References: In-Reply-To: Content-Transfer-Encoding: quoted-printable X-Barracuda-Connect: UNKNOWN[10.10.4.126] X-Barracuda-Start-Time: 1757358169 X-Barracuda-URL: https://10.10.4.122:443/cgi-mod/mark.cgi X-Barracuda-BRTS-Status: 0 X-Virus-Scanned: by bsmtpd at cybernetics.com X-Barracuda-Scan-Msg-Size: 2397 X-ASG-Debug-ID: 1757358169-1cf43947df30c5a0001-xx1T2L Content-Type: text/plain; charset="utf-8" (target mode) If handle_tmr() fails (e.g. -ENOMEM): - qlt_send_busy() makes no sense because it sends a SCSI command response instead of a TMR response. - Calling mempool_free() directly can lead to memory-use-after-free. Instead just reject the TMR and send the TMR response since that code path is well-tested. But be sure to set SCF_SCSI_TMR_CDB in case core_tmr_alloc_req() returns -ENOMEM; otherwise the wrong function will be called to free the mcmd. Signed-off-by: Tony Battersby --- drivers/scsi/qla2xxx/qla_target.c | 33 +++++++------------------------ 1 file changed, 7 insertions(+), 26 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_t= arget.c index da010de9ba8a..7c278f92ff3b 100644 --- a/drivers/scsi/qla2xxx/qla_target.c +++ b/drivers/scsi/qla2xxx/qla_target.c @@ -2005,7 +2005,6 @@ static void qlt_do_tmr_work(struct work_struct *work) struct qla_hw_data *ha =3D mcmd->vha->hw; int rc; uint32_t tag; - unsigned long flags; =20 switch (mcmd->tmr_func) { case QLA_TGT_ABTS: @@ -2020,34 +2019,16 @@ static void qlt_do_tmr_work(struct work_struct *wor= k) mcmd->tmr_func, tag); =20 if (rc !=3D 0) { - spin_lock_irqsave(mcmd->qpair->qp_lock_ptr, flags); - switch (mcmd->tmr_func) { - case QLA_TGT_ABTS: - mcmd->fc_tm_rsp =3D FCP_TMF_REJECTED; - qlt_build_abts_resp_iocb(mcmd); - break; - case QLA_TGT_LUN_RESET: - case QLA_TGT_CLEAR_TS: - case QLA_TGT_ABORT_TS: - case QLA_TGT_CLEAR_ACA: - case QLA_TGT_TARGET_RESET: - qlt_send_busy(mcmd->qpair, &mcmd->orig_iocb.atio, - qla_sam_status); - break; - - case QLA_TGT_ABORT_ALL: - case QLA_TGT_NEXUS_LOSS_SESS: - case QLA_TGT_NEXUS_LOSS: - qlt_send_notify_ack(mcmd->qpair, - &mcmd->orig_iocb.imm_ntfy, 0, 0, 0, 0, 0, 0); - break; - } - spin_unlock_irqrestore(mcmd->qpair->qp_lock_ptr, flags); - ql_dbg(ql_dbg_tgt_mgt, mcmd->vha, 0xf052, "qla_target(%d): tgt_ops->handle_tmr() failed: %d\n", mcmd->vha->vp_idx, rc); - mempool_free(mcmd, qla_tgt_mgmt_cmd_mempool); + /* + * SCF_SCSI_TMR_CDB might not have been set on error, but it + * must be set for the mcmd to be freed properly. + */ + mcmd->se_cmd.se_cmd_flags |=3D SCF_SCSI_TMR_CDB; + mcmd->fc_tm_rsp =3D FCP_TMF_REJECTED; + qlt_xmit_tm_rsp(mcmd); } } =20 --=20 2.43.0 From nobody Wed Sep 10 01:42:33 2025 Received: from mail.cybernetics.com (mail.cybernetics.com [72.215.153.18]) (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 0C821222564 for ; Mon, 8 Sep 2025 19:04:04 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=72.215.153.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757358246; cv=none; b=rFFY/yAnnXtNZxqRmV3CmubN/JhXLhUIO12+GaDphqWn6jBW0z2L6UKD41/NPDXOrTZ94cKw8zaTBAGvAJvcxHwX04tVz+KdBG2bp6DYx1565a3cNfVneWxgVkeb63Kmf+8sheKd/EK172qvyxROI2bJTvMlloMqdgCv3x6afRQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757358246; c=relaxed/simple; bh=ge0Dr8Vv3VuMyZwC7e7MV/EHgIRUnl8fWHu2+hxm8dE=; h=Message-ID:Date:MIME-Version:Subject:From:To:Cc:References: In-Reply-To:Content-Type; b=GT3ymugtUUCS6eiD6gOsUISTGvEBinSoWOOttd7qwPWlZNP+fjXXruDSpULlb6cLoLujfgao/XJQMajfJ5SKmFHZSc0jbtGpWWikrO9zBKtqk+p6tXvkjVFfchHG/rnsgDauTvogUOmkio2qVHBFHnfu8qPmTkUzx4uwyn69p2U= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=cybernetics.com; spf=pass smtp.mailfrom=cybernetics.com; dkim=pass (1024-bit key) header.d=cybernetics.com header.i=@cybernetics.com header.b=VjlKLKmH; arc=none smtp.client-ip=72.215.153.18 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=cybernetics.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=cybernetics.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=cybernetics.com header.i=@cybernetics.com header.b="VjlKLKmH" Received: from cybernetics.com ([10.10.4.126]) by mail.cybernetics.com with ESMTP id QLtGwePAKzvVz5qG; Mon, 08 Sep 2025 15:04:03 -0400 (EDT) X-Barracuda-Envelope-From: tonyb@cybernetics.com X-Barracuda-RBL-Trusted-Forwarder: 10.10.4.126 X-ASG-Whitelist: Client DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=cybernetics.com; s=mail; bh=tpjd0/5mjdIKBECuGqfcV3qmhJ1Rp+gMG+nCDMp/1jU=; h=Content-Transfer-Encoding:Content-Type:In-Reply-To:References:Cc:To:From: Content-Language:Subject:MIME-Version:Date:Message-ID; b=VjlKLKmH33f+SvqIxrxE ks442S0bkf2vetq2sKCNtOtQtnfO6HZh1digNovc8L0ZPAqxKz3KrRONE/oJlBD9+FownxQahr/s2 QKhx4b8MRK66nEKULVGi4huPtJV7zU73cRR7O/HBzg9N78JRctZoNAvhHgfZgwQqFSuKleBMzM= Received: from [10.157.2.224] (HELO [192.168.200.1]) by cybernetics.com (CommuniGate SPEC SMTP 8.0.5) with ESMTPS id 14189165; Mon, 08 Sep 2025 15:04:03 -0400 Message-ID: <93f444c0-bd88-4adc-9e97-bd15edf2a0bf@cybernetics.com> X-Barracuda-RBL-Trusted-Forwarder: 10.157.2.224 Date: Mon, 8 Sep 2025 15:04:03 -0400 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 User-Agent: Mozilla Thunderbird Subject: [PATCH 11/15] scsi: qla2xxx: fix invalid memory access with big CDBs Content-Language: en-US X-ASG-Orig-Subj: [PATCH 11/15] scsi: qla2xxx: fix invalid memory access with big CDBs From: Tony Battersby To: Nilesh Javali , GR-QLogic-Storage-Upstream@marvell.com, "James E.J. Bottomley" , "Martin K. Petersen" Cc: linux-scsi , target-devel@vger.kernel.org, scst-devel@lists.sourceforge.net, "linux-kernel@vger.kernel.org" References: In-Reply-To: Content-Transfer-Encoding: quoted-printable X-Barracuda-Connect: UNKNOWN[10.10.4.126] X-Barracuda-Start-Time: 1757358243 X-Barracuda-URL: https://10.10.4.122:443/cgi-mod/mark.cgi X-Barracuda-BRTS-Status: 0 X-Virus-Scanned: by bsmtpd at cybernetics.com X-Barracuda-Scan-Msg-Size: 7442 X-ASG-Debug-ID: 1757358243-1cf43947df30c5e0001-xx1T2L Content-Type: text/plain; charset="utf-8" (target mode) struct atio7_fcp_cmnd is a variable-length data structure because of add_cdb_len, but it is embedded in struct atio_from_isp and copied around like a fixed-length data structure. For big CDBs > 16 bytes, get_datalen_for_atio() called on a fixed-length copy of the atio will access invalid memory. In some cases this can be fixed by moving the atio to the end of the data structure and using a variable-length allocation. In other cases such as allocating struct qla_tgt_cmd, the fixed-length data structures are preallocated for speed, so in the case that add_cdb_len !=3D 0, allocate a separate buffer for the CDB. Also add memcpy_atio() as a safeguard against invalid memory accesses. Signed-off-by: Tony Battersby --- drivers/scsi/qla2xxx/qla_target.c | 83 ++++++++++++++++++++++++++++--- drivers/scsi/qla2xxx/qla_target.h | 7 ++- 2 files changed, 81 insertions(+), 9 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_t= arget.c index 7c278f92ff3b..eabb891a5528 100644 --- a/drivers/scsi/qla2xxx/qla_target.c +++ b/drivers/scsi/qla2xxx/qla_target.c @@ -210,6 +210,10 @@ static void qlt_queue_unknown_atio(scsi_qla_host_t *vh= a, struct qla_tgt_sess_op *u; struct qla_tgt *tgt =3D vha->vha_tgt.qla_tgt; unsigned long flags; + unsigned int add_cdb_len =3D 0; + + /* atio must be the last member of qla_tgt_sess_op for add_cdb_len */ + BUILD_BUG_ON(offsetof(struct qla_tgt_sess_op, atio) + sizeof(u->atio) != =3D sizeof(*u)); =20 if (tgt->tgt_stop) { ql_dbg(ql_dbg_async, vha, 0x502c, @@ -218,12 +222,17 @@ static void qlt_queue_unknown_atio(scsi_qla_host_t *v= ha, goto out_term; } =20 - u =3D kzalloc(sizeof(*u), GFP_ATOMIC); + if (atio->u.raw.entry_type =3D=3D ATIO_TYPE7 && + atio->u.isp24.fcp_cmnd.task_mgmt_flags =3D=3D 0) + add_cdb_len =3D + ((unsigned int) atio->u.isp24.fcp_cmnd.add_cdb_len) * 4; + + u =3D kzalloc(sizeof(*u) + add_cdb_len, GFP_ATOMIC); if (u =3D=3D NULL) goto out_term; =20 u->vha =3D vha; - memcpy(&u->atio, atio, sizeof(*atio)); + memcpy(&u->atio, atio, sizeof(*atio) + add_cdb_len); INIT_LIST_HEAD(&u->cmd_list); =20 spin_lock_irqsave(&vha->cmd_list_lock, flags); @@ -3821,6 +3830,13 @@ void qlt_free_cmd(struct qla_tgt_cmd *cmd) qlt_decr_num_pend_cmds(cmd->vha); =20 BUG_ON(cmd->sg_mapped); + + if (unlikely(cmd->cdb !=3D &cmd->atio.u.isp24.fcp_cmnd.cdb[0])) { + kfree(cmd->cdb); + cmd->cdb =3D &cmd->atio.u.isp24.fcp_cmnd.cdb[0]; + cmd->cdb_len =3D 16; + } + cmd->jiffies_at_free =3D get_jiffies_64(); =20 if (!sess || !sess->se_sess) { @@ -4120,7 +4136,6 @@ static void __qlt_do_work(struct qla_tgt_cmd *cmd) struct qla_hw_data *ha =3D vha->hw; struct fc_port *sess =3D cmd->sess; struct atio_from_isp *atio =3D &cmd->atio; - unsigned char *cdb; unsigned long flags; uint32_t data_length; int ret, fcp_task_attr, data_dir, bidi =3D 0; @@ -4136,7 +4151,6 @@ static void __qlt_do_work(struct qla_tgt_cmd *cmd) goto out_term; } =20 - cdb =3D &atio->u.isp24.fcp_cmnd.cdb[0]; cmd->se_cmd.tag =3D le32_to_cpu(atio->u.isp24.exchange_addr); =20 if (atio->u.isp24.fcp_cmnd.rddata && @@ -4154,7 +4168,7 @@ static void __qlt_do_work(struct qla_tgt_cmd *cmd) atio->u.isp24.fcp_cmnd.task_attr); data_length =3D get_datalen_for_atio(atio); =20 - ret =3D ha->tgt.tgt_ops->handle_cmd(vha, cmd, cdb, data_length, + ret =3D ha->tgt.tgt_ops->handle_cmd(vha, cmd, cmd->cdb, data_length, fcp_task_attr, data_dir, bidi); if (ret !=3D 0) goto out_term; @@ -4175,6 +4189,11 @@ static void __qlt_do_work(struct qla_tgt_cmd *cmd) qlt_send_term_exchange(qpair, NULL, &cmd->atio, 1); =20 qlt_decr_num_pend_cmds(vha); + if (unlikely(cmd->cdb !=3D &cmd->atio.u.isp24.fcp_cmnd.cdb[0])) { + kfree(cmd->cdb); + cmd->cdb =3D &cmd->atio.u.isp24.fcp_cmnd.cdb[0]; + cmd->cdb_len =3D 16; + } cmd->vha->hw->tgt.tgt_ops->rel_cmd(cmd); spin_unlock_irqrestore(qpair->qp_lock_ptr, flags); =20 @@ -4298,18 +4317,43 @@ static void qlt_assign_qpair(struct scsi_qla_host *= vha, cmd->se_cmd.cpuid =3D h->cpuid; } =20 +/* + * Safely make a fixed-length copy of a variable-length atio by truncating= the + * CDB if necessary. + */ +static void memcpy_atio(struct atio_from_isp *dst, + const struct atio_from_isp *src) +{ + int len; + + memcpy(dst, src, sizeof(*dst)); + + /* + * If the CDB was truncated, prevent get_datalen_for_atio() from + * accessing invalid memory. + */ + len =3D src->u.isp24.fcp_cmnd.add_cdb_len; + if (unlikely(len !=3D 0)) { + dst->u.isp24.fcp_cmnd.add_cdb_len =3D 0; + memcpy(&dst->u.isp24.fcp_cmnd.add_cdb[0], + &src->u.isp24.fcp_cmnd.add_cdb[len * 4], + 4); + } +} + static struct qla_tgt_cmd *qlt_get_tag(scsi_qla_host_t *vha, struct fc_port *sess, struct atio_from_isp *atio) { struct qla_tgt_cmd *cmd; + int add_cdb_len; =20 cmd =3D vha->hw->tgt.tgt_ops->get_cmd(sess); if (!cmd) return NULL; =20 cmd->cmd_type =3D TYPE_TGT_CMD; - memcpy(&cmd->atio, atio, sizeof(*atio)); + memcpy_atio(&cmd->atio, atio); INIT_LIST_HEAD(&cmd->sess_cmd_list); cmd->state =3D QLA_TGT_STATE_NEW; cmd->tgt =3D vha->vha_tgt.qla_tgt; @@ -4329,6 +4373,29 @@ static struct qla_tgt_cmd *qlt_get_tag(scsi_qla_host= _t *vha, cmd->vp_idx =3D vha->vp_idx; cmd->edif =3D sess->edif.enable; =20 + cmd->cdb =3D &cmd->atio.u.isp24.fcp_cmnd.cdb[0]; + cmd->cdb_len =3D 16; + + /* + * NOTE: memcpy_atio() set cmd->atio.u.isp24.fcp_cmnd.add_cdb_len to 0, + * so use the original value here. + */ + add_cdb_len =3D atio->u.isp24.fcp_cmnd.add_cdb_len; + if (unlikely(add_cdb_len !=3D 0)) { + int cdb_len =3D 16 + add_cdb_len * 4; + u8 *cdb; + + cdb =3D kmalloc(cdb_len, GFP_ATOMIC); + if (unlikely(!cdb)) { + vha->hw->tgt.tgt_ops->free_cmd(cmd); + return NULL; + } + /* CAUTION: copy CDB from atio not cmd->atio */ + memcpy(cdb, atio->u.isp24.fcp_cmnd.cdb, cdb_len); + cmd->cdb =3D cdb; + cmd->cdb_len =3D cdb_len; + } + return cmd; } =20 @@ -5476,13 +5543,15 @@ qlt_alloc_qfull_cmd(struct scsi_qla_host *vha, =20 qlt_incr_num_pend_cmds(vha); INIT_LIST_HEAD(&cmd->cmd_list); - memcpy(&cmd->atio, atio, sizeof(*atio)); + memcpy_atio(&cmd->atio, atio); =20 cmd->tgt =3D vha->vha_tgt.qla_tgt; cmd->vha =3D vha; cmd->reset_count =3D ha->base_qpair->chip_reset; cmd->q_full =3D 1; cmd->qpair =3D ha->base_qpair; + cmd->cdb =3D &cmd->atio.u.isp24.fcp_cmnd.cdb[0]; + cmd->cdb_len =3D 16; =20 if (qfull) { cmd->q_full =3D 1; diff --git a/drivers/scsi/qla2xxx/qla_target.h b/drivers/scsi/qla2xxx/qla_t= arget.h index adbc2a05b159..1931e1dade7a 100644 --- a/drivers/scsi/qla2xxx/qla_target.h +++ b/drivers/scsi/qla2xxx/qla_target.h @@ -830,11 +830,13 @@ struct qla_tgt { struct qla_tgt_sess_op { struct scsi_qla_host *vha; uint32_t chip_reset; - struct atio_from_isp atio; struct work_struct work; struct list_head cmd_list; bool aborted; struct rsp_que *rsp; + + struct atio_from_isp atio; + /* DO NOT ADD ANYTHING ELSE HERE - atio must be last member */ }; =20 enum trace_flags { @@ -926,8 +928,9 @@ struct qla_tgt_cmd { uint8_t scsi_status, sense_key, asc, ascq; =20 struct crc_context *ctx; - const uint8_t *cdb; + uint8_t *cdb; uint64_t lba; + int cdb_len; uint16_t a_guard, e_guard, a_app_tag, e_app_tag; uint32_t a_ref_tag, e_ref_tag; #define DIF_BUNDL_DMA_VALID 1 --=20 2.43.0 From nobody Wed Sep 10 01:42:33 2025 Received: from mail.cybernetics.com (mail.cybernetics.com [72.215.153.18]) (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 B6C09227BB5 for ; Mon, 8 Sep 2025 19:07:05 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=72.215.153.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757358427; cv=none; b=o1Xss0LkiKECdMG0v1ULvJ6iGlMTgPzZK5UU6IxdVJu0ABTeqHBT8ro5ByiD7eN0VXi5Mf2A5A5puLIr3jU4P/Fd2ZPM5uHHLwyX+2jnIusP/9bN+V3uCsk3sw+sfhuoGc57DCurUMibNcCVVYXcQUahA/4CboMeqxsWwFNMIbs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757358427; c=relaxed/simple; bh=D4ILVASdY2T/H0ahHTsH3j+adyT2xwErWJjBmNUuFBQ=; h=Message-ID:Date:MIME-Version:Subject:From:To:Cc:References: In-Reply-To:Content-Type; b=bu6hFl5QhZIfNo4XcgQDZ1WRmbV+3AN29HZQZaxTMRCHazyVqBW8Ozjb3UdBYbC94vx44vYX0iEYqru6ULWFibNxciA3/hJWa969gL9cPjolLtiNhWb+UwYlioCOuZQ8cGrK4iM3jeUxRHpuHmgj0l47KzCYhj/Dg1lgubZVBc0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=cybernetics.com; spf=pass smtp.mailfrom=cybernetics.com; dkim=pass (1024-bit key) header.d=cybernetics.com header.i=@cybernetics.com header.b=mYx+5oL/; arc=none smtp.client-ip=72.215.153.18 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=cybernetics.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=cybernetics.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=cybernetics.com header.i=@cybernetics.com header.b="mYx+5oL/" Received: from cybernetics.com ([10.10.4.126]) by mail.cybernetics.com with ESMTP id ssI5BDUJu7CMuLEf; Mon, 08 Sep 2025 15:07:04 -0400 (EDT) X-Barracuda-Envelope-From: tonyb@cybernetics.com X-Barracuda-RBL-Trusted-Forwarder: 10.10.4.126 X-ASG-Whitelist: Client DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=cybernetics.com; s=mail; bh=nnqvvPSsS49UlswJpZjg2l08e48fPD5LMiFVq7yBblc=; h=Content-Transfer-Encoding:Content-Type:In-Reply-To:References:Cc:To:From: Content-Language:Subject:MIME-Version:Date:Message-ID; b=mYx+5oL/FlTSrMGuvx/h 76HNU+vRxsyJmuEkxAbDOOR/PKyaki4EAenXPI0C94CHkDI1M491gxewL8HRjKMQr+GCICy2M3786 wse5WjLXgH/qIb97H38LdbjFLsZZHR8Bo/WSpMKIFapo8Sm4W9anL+11jc/izhZLzkHX40C+DQ= Received: from [10.157.2.224] (HELO [192.168.200.1]) by cybernetics.com (CommuniGate SPEC SMTP 8.0.5) with ESMTPS id 14188080; Mon, 08 Sep 2025 15:07:04 -0400 Message-ID: <366f8fb5-376d-4426-9f27-6bef23a624b2@cybernetics.com> X-Barracuda-RBL-Trusted-Forwarder: 10.157.2.224 Date: Mon, 8 Sep 2025 15:07:04 -0400 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 User-Agent: Mozilla Thunderbird Subject: [PATCH 12/15] scsi: qla2xxx: add cmd->rsp_sent Content-Language: en-US X-ASG-Orig-Subj: [PATCH 12/15] scsi: qla2xxx: add cmd->rsp_sent From: Tony Battersby To: Nilesh Javali , GR-QLogic-Storage-Upstream@marvell.com, "James E.J. Bottomley" , "Martin K. Petersen" Cc: linux-scsi , target-devel@vger.kernel.org, scst-devel@lists.sourceforge.net, "linux-kernel@vger.kernel.org" References: In-Reply-To: Content-Transfer-Encoding: quoted-printable X-Barracuda-Connect: UNKNOWN[10.10.4.126] X-Barracuda-Start-Time: 1757358424 X-Barracuda-URL: https://10.10.4.122:443/cgi-mod/mark.cgi X-Barracuda-BRTS-Status: 0 X-Virus-Scanned: by bsmtpd at cybernetics.com X-Barracuda-Scan-Msg-Size: 1501 X-ASG-Debug-ID: 1757358424-1cf43947df30c690001-xx1T2L Content-Type: text/plain; charset="utf-8" (target mode) Add cmd->rsp_sent to indicate that the SCSI status has been sent successfully, so that SCST can be informed of any transport errors. This will also be used for logging in later patches. Signed-off-by: Tony Battersby --- drivers/scsi/qla2xxx/qla_target.c | 4 ++++ drivers/scsi/qla2xxx/qla_target.h | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_t= arget.c index eabb891a5528..0ddbf02ebe79 100644 --- a/drivers/scsi/qla2xxx/qla_target.c +++ b/drivers/scsi/qla2xxx/qla_target.c @@ -4067,6 +4067,10 @@ static void qlt_do_ctio_completion(struct scsi_qla_h= ost *vha, =20 if (cmd->state =3D=3D QLA_TGT_STATE_PROCESSED) { cmd->trc_flags |=3D TRC_CTIO_DONE; + + if (likely(status =3D=3D CTIO_SUCCESS)) + cmd->rsp_sent =3D 1; + } else if (cmd->state =3D=3D QLA_TGT_STATE_NEED_DATA) { cmd->state =3D QLA_TGT_STATE_DATA_IN; =20 diff --git a/drivers/scsi/qla2xxx/qla_target.h b/drivers/scsi/qla2xxx/qla_t= arget.h index 1931e1dade7a..972a7af1c81c 100644 --- a/drivers/scsi/qla2xxx/qla_target.h +++ b/drivers/scsi/qla2xxx/qla_target.h @@ -883,6 +883,10 @@ struct qla_tgt_cmd { unsigned int conf_compl_supported:1; unsigned int sg_mapped:1; unsigned int write_data_transferred:1; + + /* Set if the SCSI status was sent successfully. */ + unsigned int rsp_sent:1; + unsigned int q_full:1; unsigned int term_exchg:1; unsigned int cmd_sent_to_fw:1; --=20 2.43.0 From nobody Wed Sep 10 01:42:33 2025 Received: from mail.cybernetics.com (mail.cybernetics.com [72.215.153.18]) (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 8E2A71E8324 for ; Mon, 8 Sep 2025 19:09:29 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=72.215.153.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757358571; cv=none; b=ULaxoCiqyfs/r0+D5YbrKZ9zxSHKQ8zqHItDpsz5dI0Cy9b9QSVg4N/HFOKcZd15mRpgd3m2+BJosT1cJz6zJCvyhglpD2v2jedCYH1U8ACO6FtYNZGFJ6BHCXgibOWSsGr0XiotfzCySxhXPneHGhrFkctGj8/pOe+RJXf+pac= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757358571; c=relaxed/simple; bh=7AeQ9u1HgLJvM5SuitqxpTrimWcGTWENDlCZ/5zVOYY=; h=Message-ID:Date:MIME-Version:Subject:From:To:Cc:References: In-Reply-To:Content-Type; b=iDy1IeXbu55cFFjhGHJE5P9wwMVe+2mb8QnTvKuocXuJQ8UlL1Ivx3J0lgmPgSefqUpMwf6QLekwJeR6diKYboRks5JQhaadpA/Rz+B8cLs5AuZxwdFUw0Pslahm33KGBUNNKk8VVscTy+/P8iPDint4anuaNU2g7JFLTXHJ7po= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=cybernetics.com; spf=pass smtp.mailfrom=cybernetics.com; dkim=pass (1024-bit key) header.d=cybernetics.com header.i=@cybernetics.com header.b=WuUJBY6h; arc=none smtp.client-ip=72.215.153.18 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=cybernetics.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=cybernetics.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=cybernetics.com header.i=@cybernetics.com header.b="WuUJBY6h" Received: from cybernetics.com ([10.10.4.126]) by mail.cybernetics.com with ESMTP id S3GSX9zBvRyfSBat; Mon, 08 Sep 2025 15:09:28 -0400 (EDT) X-Barracuda-Envelope-From: tonyb@cybernetics.com X-Barracuda-RBL-Trusted-Forwarder: 10.10.4.126 X-ASG-Whitelist: Client DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=cybernetics.com; s=mail; bh=HuCpFf9K+JsAPM4tutKOqxZ6vTqQCUKFzCy/o/Cd6nI=; h=Content-Transfer-Encoding:Content-Type:In-Reply-To:References:Cc:To:From: Content-Language:Subject:MIME-Version:Date:Message-ID; b=WuUJBY6hZTClc0B603wT aTAZOiZDL5GV1n2lh1GwQxSwSE3iPnHc8ZMskz2Iea6gn4cbn9tcIw/k+MVrK9bpbOotZBwVKZ+49 eQMgWtugVuHIwCiX8i+PSaRfSohVpFrHmBGmn/6wrQtR37l94b6Xsk4sdFl4/kI8Xh7PDI4mWs= Received: from [10.157.2.224] (HELO [192.168.200.1]) by cybernetics.com (CommuniGate SPEC SMTP 8.0.5) with ESMTPS id 14188950; Mon, 08 Sep 2025 15:09:28 -0400 Message-ID: <7c22ef18-5b35-4590-adf4-b5722d2ccc3e@cybernetics.com> X-Barracuda-RBL-Trusted-Forwarder: 10.157.2.224 Date: Mon, 8 Sep 2025 15:09:28 -0400 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 User-Agent: Mozilla Thunderbird Subject: [PATCH 13/15] scsi: qla2xxx: improve cmd logging Content-Language: en-US X-ASG-Orig-Subj: [PATCH 13/15] scsi: qla2xxx: improve cmd logging From: Tony Battersby To: Nilesh Javali , GR-QLogic-Storage-Upstream@marvell.com, "James E.J. Bottomley" , "Martin K. Petersen" Cc: linux-scsi , target-devel@vger.kernel.org, scst-devel@lists.sourceforge.net, "linux-kernel@vger.kernel.org" References: In-Reply-To: Content-Transfer-Encoding: quoted-printable X-Barracuda-Connect: UNKNOWN[10.10.4.126] X-Barracuda-Start-Time: 1757358568 X-Barracuda-URL: https://10.10.4.122:443/cgi-mod/mark.cgi X-Barracuda-BRTS-Status: 1 X-Virus-Scanned: by bsmtpd at cybernetics.com X-Barracuda-Scan-Msg-Size: 8956 X-ASG-Debug-ID: 1757358568-1cf43947df30c730001-xx1T2L Content-Type: text/plain; charset="utf-8" (target mode) - Add the command tag to various messages so that different messages about the same command can be correlated. - For CTIO errors (i.e. when the HW reports an error about a cmd), print the cmd tag, opcode, state, initiator WWPN, and LUN. This info helps an administrator determine what is going wrong. - When a command experiences a transport error, log a message when it is freed. This makes debugging exceptions easier. Signed-off-by: Tony Battersby --- drivers/scsi/qla2xxx/qla_dbg.c | 2 +- drivers/scsi/qla2xxx/qla_target.c | 89 ++++++++++++++++++++++--------- 2 files changed, 65 insertions(+), 26 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_dbg.c b/drivers/scsi/qla2xxx/qla_dbg.c index ff4124eccc9c..a19471d51ea5 100644 --- a/drivers/scsi/qla2xxx/qla_dbg.c +++ b/drivers/scsi/qla2xxx/qla_dbg.c @@ -54,7 +54,7 @@ * | Misc | 0xd303 | 0xd031-0xd0ff | * | | | 0xd101-0xd1fe | * | | | 0xd214-0xd2fe | - * | Target Mode | 0xe084 | | + * | Target Mode | 0xe086 | | * | Target Mode Management | 0xf09b | 0xf002 | * | | | 0xf046-0xf049 | * | Target Mode Task Management | 0x1000d | | diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_t= arget.c index 0ddbf02ebe79..028cb41f78be 100644 --- a/drivers/scsi/qla2xxx/qla_target.c +++ b/drivers/scsi/qla2xxx/qla_target.c @@ -1984,8 +1984,12 @@ static void abort_cmds_for_lun(struct scsi_qla_host = *vha, u64 lun, be_id_t s_id) cmd_key =3D sid_to_key(cmd->atio.u.isp24.fcp_hdr.s_id); cmd_lun =3D scsilun_to_int( (struct scsi_lun *)&cmd->atio.u.isp24.fcp_cmnd.lun); - if (cmd_key =3D=3D key && cmd_lun =3D=3D lun) + if (cmd_key =3D=3D key && cmd_lun =3D=3D lun) { + ql_dbg(ql_dbg_tgt_mgt, vha, 0xe085, + "qla_target(%d): tag %lld: aborted by TMR\n", + vha->vp_idx, cmd->se_cmd.tag); cmd->aborted =3D 1; + } } spin_unlock_irqrestore(&vha->cmd_list_lock, flags); } @@ -3831,6 +3835,16 @@ void qlt_free_cmd(struct qla_tgt_cmd *cmd) =20 BUG_ON(cmd->sg_mapped); =20 + if (unlikely(cmd->aborted || + (cmd->trc_flags & (TRC_CTIO_IGNORED | TRC_CTIO_STRANGE | + TRC_CTIO_ERR)))) { + ql_dbg(ql_dbg_tgt_mgt, cmd->vha, 0xe086, + "qla_target(%d): tag %lld: free cmd (trc_flags %x, aborted %u, sent_= term_exchg %u, rsp_sent %u)\n", + cmd->vha->vp_idx, cmd->se_cmd.tag, + cmd->trc_flags, cmd->aborted, cmd->sent_term_exchg, + cmd->rsp_sent); + } + if (unlikely(cmd->cdb !=3D &cmd->atio.u.isp24.fcp_cmnd.cdb[0])) { kfree(cmd->cdb); cmd->cdb =3D &cmd->atio.u.isp24.fcp_cmnd.cdb[0]; @@ -3843,7 +3857,6 @@ void qlt_free_cmd(struct qla_tgt_cmd *cmd) WARN_ON(1); return; } - cmd->jiffies_at_free =3D get_jiffies_64(); cmd->vha->hw->tgt.tgt_ops->rel_cmd(cmd); } EXPORT_SYMBOL(qlt_free_cmd); @@ -3908,7 +3921,6 @@ static void qlt_do_ctio_completion(struct scsi_qla_ho= st *vha, struct ctio7_from_24xx *ctio) { struct qla_hw_data *ha =3D vha->hw; - struct se_cmd *se_cmd; struct qla_tgt_cmd *cmd; struct qla_qpair *qpair =3D rsp->qpair; uint16_t ctio_flags; @@ -3947,12 +3959,12 @@ static void qlt_do_ctio_completion(struct scsi_qla_= host *vha, if ((ctio_flags & CTIO7_FLAGS_DATA_OUT) && cmd->sess) qlt_chk_edif_rx_sa_delete_pending(vha, cmd->sess, ctio); =20 - se_cmd =3D &cmd->se_cmd; cmd->cmd_sent_to_fw =3D 0; =20 qlt_unmap_sg(vha, cmd); =20 if (unlikely(status !=3D CTIO_SUCCESS)) { + u8 op =3D cmd->cdb ? cmd->cdb[0] : 0; bool term_exchg =3D false; =20 /* @@ -3970,8 +3982,10 @@ static void qlt_do_ctio_completion(struct scsi_qla_h= ost *vha, term_exchg =3D true; if (printk_ratelimit()) dev_info(&vha->hw->pdev->dev, - "qla_target(%d): CTIO with INVALID_RX_ID ATIO attr %x CTIO Flags %= x|%x\n", - vha->vp_idx, cmd->atio.u.isp24.attr, + "qla_target(%d): tag %lld, op %x: CTIO with INVALID_RX_ID status 0= x%x received (state %d, port %8phC, LUN %lld, ATIO attr %x, CTIO Flags %x|%= x)\n", + vha->vp_idx, cmd->se_cmd.tag, op, + status, cmd->state, cmd->sess->port_name, + cmd->unpacked_lun, cmd->atio.u.isp24.attr, ((cmd->ctio_flags >> 9) & 0xf), cmd->ctio_flags); break; @@ -3982,13 +3996,31 @@ static void qlt_do_ctio_completion(struct scsi_qla_= host *vha, term_exchg =3D true; fallthrough; case CTIO_TIMEOUT: + { + const char *status_str; + + switch (status & 0xFFFF) { + case CTIO_LIP_RESET: + status_str =3D "LIP_RESET"; + break; + case CTIO_TARGET_RESET: + status_str =3D "TARGET_RESET"; + break; + case CTIO_ABORTED: + status_str =3D "ABORTED"; + break; + case CTIO_TIMEOUT: + default: + status_str =3D "TIMEOUT"; + break; + } ql_dbg(ql_dbg_tgt_mgt, vha, 0xf058, - "qla_target(%d): CTIO with " - "status %#x received, state %x, se_cmd %p, " - "(LIP_RESET=3De, ABORTED=3D2, TARGET_RESET=3D17, " - "TIMEOUT=3Db, INVALID_RX_ID=3D8)\n", vha->vp_idx, - status, cmd->state, se_cmd); + "qla_target(%d): tag %lld, op %x: CTIO with %s status 0x%x received= (state %d, port %8phC, LUN %lld)\n", + vha->vp_idx, cmd->se_cmd.tag, op, + status_str, status, cmd->state, + cmd->sess->port_name, cmd->unpacked_lun); break; + } =20 case CTIO_PORT_LOGGED_OUT: case CTIO_PORT_UNAVAILABLE: @@ -3997,10 +4029,11 @@ static void qlt_do_ctio_completion(struct scsi_qla_= host *vha, (status & 0xFFFF) =3D=3D CTIO_PORT_LOGGED_OUT; =20 ql_dbg(ql_dbg_tgt_mgt, vha, 0xf059, - "qla_target(%d): CTIO with %s status %x " - "received (state %x, se_cmd %p)\n", vha->vp_idx, + "qla_target(%d): tag %lld, op %x: CTIO with %s status 0x%x received= (state %d, port %8phC, LUN %lld)\n", + vha->vp_idx, cmd->se_cmd.tag, op, logged_out ? "PORT LOGGED OUT" : "PORT UNAVAILABLE", - status, cmd->state, se_cmd); + status, cmd->state, cmd->sess->port_name, + cmd->unpacked_lun); =20 term_exchg =3D true; if (logged_out && cmd->sess) { @@ -4017,14 +4050,15 @@ static void qlt_do_ctio_completion(struct scsi_qla_= host *vha, } break; } + case CTIO_DIF_ERROR: { struct ctio_crc_from_fw *crc =3D (struct ctio_crc_from_fw *)ctio; ql_dbg(ql_dbg_tgt_mgt, vha, 0xf073, - "qla_target(%d): CTIO with DIF_ERROR status %x " - "received (state %x, ulp_cmd %p) actual_dif[0x%llx] " - "expect_dif[0x%llx]\n", - vha->vp_idx, status, cmd->state, se_cmd, + "qla_target(%d): tag %lld, op %x: CTIO with DIF_ERROR status 0x%x r= eceived (state %d, port %8phC, LUN %lld, actual_dif[0x%llx] expect_dif[0x%l= lx])\n", + vha->vp_idx, cmd->se_cmd.tag, op, status, + cmd->state, cmd->sess->port_name, + cmd->unpacked_lun, *((u64 *)&crc->actual_dif[0]), *((u64 *)&crc->expected_dif[0])); =20 @@ -4037,14 +4071,18 @@ static void qlt_do_ctio_completion(struct scsi_qla_= host *vha, case CTIO_FAST_INVALID_REQ: case CTIO_FAST_SPI_ERR: ql_dbg(ql_dbg_tgt_mgt, vha, 0xf05b, - "qla_target(%d): CTIO with EDIF error status 0x%x received (state %= x, se_cmd %p\n", - vha->vp_idx, status, cmd->state, se_cmd); + "qla_target(%d): tag %lld, op %x: CTIO with EDIF error status 0x%x = received (state %d, port %8phC, LUN %lld)\n", + vha->vp_idx, cmd->se_cmd.tag, op, status, + cmd->state, cmd->sess->port_name, + cmd->unpacked_lun); break; =20 default: ql_dbg(ql_dbg_tgt_mgt, vha, 0xf05b, - "qla_target(%d): CTIO with error status 0x%x received (state %x, se= _cmd %p\n", - vha->vp_idx, status, cmd->state, se_cmd); + "qla_target(%d): tag %lld, op %x: CTIO with error status 0x%x recei= ved (state %d, port %8phC, LUN %lld)\n", + vha->vp_idx, cmd->se_cmd.tag, op, status, + cmd->state, cmd->sess->port_name, + cmd->unpacked_lun); break; } =20 @@ -4082,12 +4120,13 @@ static void qlt_do_ctio_completion(struct scsi_qla_= host *vha, } else if (cmd->aborted) { cmd->trc_flags |=3D TRC_CTIO_ABORTED; ql_dbg(ql_dbg_tgt_mgt, vha, 0xf01e, - "Aborted command %p (tag %lld) finished\n", cmd, se_cmd->tag); + "qla_target(%d): tag %lld: Aborted command finished\n", + vha->vp_idx, cmd->se_cmd.tag); } else { cmd->trc_flags |=3D TRC_CTIO_STRANGE; ql_dbg(ql_dbg_tgt_mgt, vha, 0xf05c, - "qla_target(%d): A command in state (%d) should " - "not return a CTIO complete\n", vha->vp_idx, cmd->state); + "qla_target(%d): tag %lld: A command in state (%d) should not return= a CTIO complete\n", + vha->vp_idx, cmd->se_cmd.tag, cmd->state); } =20 if (unlikely(status !=3D CTIO_SUCCESS) && --=20 2.43.0 From nobody Wed Sep 10 01:42:33 2025 Received: from mail.cybernetics.com (mail.cybernetics.com [173.71.130.66]) (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 44E0B238C07 for ; Mon, 8 Sep 2025 19:10:55 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=173.71.130.66 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757358658; cv=none; b=A7mTY1A8nhgH5QHZK1Pn5sC5eu+/09e56Z+mUFXwC1GL6HjS2tNlId8AyrN/tMHWASZjPJE8sG24tTLWhB7LzQftpvu3ytNwhsgS3jCQuatrRAqf2D5abCtPy/kI7VLLImt2lgoG/p4gseh1y82gFQD0GOlAXcwlyh+ZvEPxrKQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757358658; c=relaxed/simple; bh=ZgtQZz5BU8ZeKWA5ZOYnMaUawJhI9KuzPVXy345n708=; h=Message-ID:Date:MIME-Version:Subject:From:To:Cc:References: In-Reply-To:Content-Type; b=YTWIb2IZ0jPvBTTXExBqi472TOrnkgK0PgD43MzFuB9D02IgN4HJEdVNgeZsnir6FU7pMP8LeYfqLmMYChxTc4bhiQMGVmwkpeKnDMh+yaHC81XxsZh4VNoEE/yRzUKrK6XvXqY7sm+LX2rvTf2NInXcj8TArLu+Hdp16SunLHE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=cybernetics.com; spf=pass smtp.mailfrom=cybernetics.com; dkim=pass (1024-bit key) header.d=cybernetics.com header.i=@cybernetics.com header.b=Z2UhyR5N; arc=none smtp.client-ip=173.71.130.66 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=cybernetics.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=cybernetics.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=cybernetics.com header.i=@cybernetics.com header.b="Z2UhyR5N" Received: from cybernetics.com ([10.10.4.126]) by mail.cybernetics.com with ESMTP id AxxV8hzFU0ZO3xxD; Mon, 08 Sep 2025 15:10:53 -0400 (EDT) X-Barracuda-Envelope-From: tonyb@cybernetics.com X-Barracuda-RBL-Trusted-Forwarder: 10.10.4.126 X-ASG-Whitelist: Client DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=cybernetics.com; s=mail; bh=Z/HJt+0VSk2I/X4rIDyFFvOtQLndsiBcAg+g2BQr5ns=; h=Content-Transfer-Encoding:Content-Type:In-Reply-To:References:Cc:To:From: Content-Language:Subject:MIME-Version:Date:Message-ID; b=Z2UhyR5NAY7Pnu98YqbM Pw/0aqxmo6xz8xXRZprAqhBF9P9fGVzBU5/sjMifg/K4Q3MNKrfeGAO5T+AAhBduNmAqI7Z4CQytf Bm20BnZ43yAOPIRvUMvSxCBmCHmhEngIUCjzonT8qYWZfwhd/IOWospEEih+MgQJCzHs2bnLzI= Received: from [10.157.2.224] (HELO [192.168.200.1]) by cybernetics.com (CommuniGate SPEC SMTP 8.0.5) with ESMTPS id 14189167; Mon, 08 Sep 2025 15:10:53 -0400 Message-ID: <2cc10189-6953-428e-b34e-b1c714fc0eae@cybernetics.com> X-Barracuda-RBL-Trusted-Forwarder: 10.157.2.224 Date: Mon, 8 Sep 2025 15:10:53 -0400 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 User-Agent: Mozilla Thunderbird Subject: [PATCH 14/15] scsi: qla2xxx: add back SRR support Content-Language: en-US X-ASG-Orig-Subj: [PATCH 14/15] scsi: qla2xxx: add back SRR support From: Tony Battersby To: Nilesh Javali , GR-QLogic-Storage-Upstream@marvell.com, "James E.J. Bottomley" , "Martin K. Petersen" Cc: linux-scsi , target-devel@vger.kernel.org, scst-devel@lists.sourceforge.net, "linux-kernel@vger.kernel.org" References: In-Reply-To: Content-Transfer-Encoding: quoted-printable X-Barracuda-Connect: UNKNOWN[10.10.4.126] X-Barracuda-Start-Time: 1757358653 X-Barracuda-URL: https://10.10.4.122:443/cgi-mod/mark.cgi X-Barracuda-BRTS-Status: 1 X-Virus-Scanned: by bsmtpd at cybernetics.com X-Barracuda-Scan-Msg-Size: 48289 X-ASG-Debug-ID: 1757358653-1cf43947df30c7a0002-xx1T2L Content-Type: text/plain; charset="utf-8" (target mode) Background: loading qla2xxx with "ql2xtgt_tape_enable=3D1" enables Sequence Level Error Recovery (SLER), which is most commonly used for tape drives. With SLER enabled, if there is a recoverable I/O error during a SCSI command, a Sequence Retransmission Request (SRR) will be used to retry the I/O at a low-level completely within the driver without propagating the error to the upper levels of the SCSI stack. SRR support was removed in 2017 by commit 2c39b5ca2a8c ("qla2xxx: Remove SRR code"). But I need it, so add it back, new and improved. The old removed SRR code used sequence numbers to correlate the SRR CTIOs with SRR immediate notify messages. I don't see how that would work reliably with MSI-X interrupts and multiple queues. So instead use the exchange address to find the command associated with the immediate notify (qlt_srr_to_cmd). The old removed SRR code had a function qlt_check_srr_debug() to simulate a SRR, but it didn't work for me. Instead I just used fiber optic attenuators attached to the FC cable to reduce the strength of the signal and induce errors. Unfortunately this only worked for inducing SRRs on Data-Out (write) commands, so that is all I was able to test. The code to build a new scatterlist for a SRR with nonzero offset has been improved to reduce memory requirements and has been well-tested. However it does not support protection information. When a single cmd gets multiple SRRs, the old removed SRR code would restore the data buffer from the values in cmd->se_cmd before processing the new SRR. That might be needed if the offset for the new SRR was lower than the offset for the previous SRR, but I am not sure if that can happen. In my testing, when a single cmd gets multiple SRRs, the SRR offset always increases or stays the same. But in case it can decrease, I added the function qlt_restore_orig_sg(). If this is not supposed to happen then qlt_restore_orig_sg() can be removed to simplify the code. I ran into some HBA firmware bugs with QLE2694L firmware 9.06.02 - 9.08.02 where a SRR would cause the HBA to misbehave badly. Since SRRs are rare and therefore difficult to test, I figured it would be worth checking for the buggy firmware and disabling SLER with a warning instead of letting others run into the same problem on the rare occasion that they get a SRR. This turned out to be difficult because the firmware version isn't known in the normal NVRAM config routine, so I added a second NVRAM config routine that is called after the firmware version is known. It may be necessary to add checks for additional buggy firmware versions or additional chips that I was not able to test. Signed-off-by: Tony Battersby --- drivers/scsi/qla2xxx/qla_dbg.c | 1 + drivers/scsi/qla2xxx/qla_init.c | 1 + drivers/scsi/qla2xxx/qla_target.c | 1030 ++++++++++++++++++++++++++++ drivers/scsi/qla2xxx/qla_target.h | 81 +++ drivers/scsi/qla2xxx/tcm_qla2xxx.c | 15 + 5 files changed, 1128 insertions(+) diff --git a/drivers/scsi/qla2xxx/qla_dbg.c b/drivers/scsi/qla2xxx/qla_dbg.c index a19471d51ea5..9f56bec26231 100644 --- a/drivers/scsi/qla2xxx/qla_dbg.c +++ b/drivers/scsi/qla2xxx/qla_dbg.c @@ -58,6 +58,7 @@ * | Target Mode Management | 0xf09b | 0xf002 | * | | | 0xf046-0xf049 | * | Target Mode Task Management | 0x1000d | | + * | Target Mode SRR | 0x11038 | | * ---------------------------------------------------------------------- */ =20 diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_ini= t.c index be211ff22acb..25c1760eac45 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -4369,6 +4369,7 @@ qla2x00_setup_chip(scsi_qla_host_t *vha) ha->max_npiv_vports =3D MIN_MULTI_ID_FABRIC - 1; } + qlt_config_nvram_with_fw_version(vha); qla2x00_get_resource_cnts(vha); qla_init_iocb_limit(vha); =20 diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_t= arget.c index 028cb41f78be..70e1810d4996 100644 --- a/drivers/scsi/qla2xxx/qla_target.c +++ b/drivers/scsi/qla2xxx/qla_target.c @@ -3216,6 +3216,10 @@ int qlt_xmit_response(struct qla_tgt_cmd *cmd, int x= mit_type, * first. */ =20 + /* Begin timer on the first call, not on SRR retry. */ + if (likely(cmd->jiffies_at_hw_st_entry =3D=3D 0)) + cmd->jiffies_at_hw_st_entry =3D get_jiffies_64(); + spin_lock_irqsave(qpair->qp_lock_ptr, flags); =20 if (unlikely(cmd->sent_term_exchg || @@ -3359,6 +3363,10 @@ int qlt_rdy_to_xfer(struct qla_tgt_cmd *cmd) int pci_map_res; struct qla_qpair *qpair =3D cmd->qpair; =20 + /* Begin timer on the first call, not on SRR retry. */ + if (likely(cmd->jiffies_at_hw_st_entry =3D=3D 0)) + cmd->jiffies_at_hw_st_entry =3D get_jiffies_64(); + memset(&prm, 0, sizeof(prm)); prm.cmd =3D cmd; prm.tgt =3D tgt; @@ -3384,6 +3392,7 @@ int qlt_rdy_to_xfer(struct qla_tgt_cmd *cmd) cmd->aborted =3D 1; cmd->write_data_transferred =3D 0; cmd->state =3D QLA_TGT_STATE_DATA_IN; + cmd->jiffies_at_hw_st_entry =3D 0; vha->hw->tgt.tgt_ops->handle_data(cmd); spin_unlock_irqrestore(qpair->qp_lock_ptr, flags); return 0; @@ -3431,6 +3440,7 @@ int qlt_rdy_to_xfer(struct qla_tgt_cmd *cmd) return res; =20 out_unlock_free_unmap: + cmd->jiffies_at_hw_st_entry =3D 0; qlt_unmap_sg(vha, cmd); spin_unlock_irqrestore(qpair->qp_lock_ptr, flags); =20 @@ -3520,6 +3530,7 @@ qlt_handle_dif_error(struct qla_qpair *qpair, struct = qla_tgt_cmd *cmd, case QLA_TGT_STATE_NEED_DATA: /* handle_data will load DIF error code */ cmd->state =3D QLA_TGT_STATE_DATA_IN; + cmd->jiffies_at_hw_st_entry =3D 0; vha->hw->tgt.tgt_ops->handle_data(cmd); break; default: @@ -3599,6 +3610,62 @@ static void qlt_send_term_imm_notif(struct scsi_qla_= host *vha, pr_debug("rc =3D %d\n", rc); } =20 +/* + * Handle a SRR that had been previously associated with a command when the + * command has been aborted or otherwise cannot process the SRR. + * + * If reject is true, then attempt to reject the SRR. Otherwise abort the + * immediate notify exchange. + */ +void qlt_srr_abort(struct qla_tgt_cmd *cmd, bool reject) +{ + struct scsi_qla_host *vha =3D cmd->vha; + struct qla_tgt_srr *srr =3D cmd->srr; + + if (srr->imm_ntfy_recvd) { + if (reject) + srr->reject =3D true; + else + srr->aborted =3D true; + + if (srr->ctio_recvd) { + /* + * The SRR should already be scheduled for processing, + * and the SRR processing code should see that the cmd + * has been aborted and take appropriate action. In + * addition, the cmd refcount should have been + * incremented, preventing the cmd from being freed + * until SRR processing is done. + */ + ql_dbg(ql_dbg_tgt_mgt, vha, 0x1102e, + "qla_target(%d): tag %lld: %s: SRR already scheduled\n", + vha->vp_idx, cmd->se_cmd.tag, __func__); + } else { + struct qla_tgt *tgt =3D vha->vha_tgt.qla_tgt; + unsigned long flags; + + /* Shedule processing for the SRR immediate notify. */ + ql_dbg(ql_dbg_tgt_mgt, vha, 0x1102f, + "qla_target(%d): tag %lld: %s: schedule SRR %s\n", + vha->vp_idx, cmd->se_cmd.tag, __func__, + reject ? "reject" : "abort"); + cmd->srr =3D NULL; + srr->cmd =3D NULL; + spin_lock_irqsave(&tgt->srr_lock, flags); + list_add_tail(&srr->srr_list_entry, &tgt->srr_list); + queue_work(qla_tgt_wq, &tgt->srr_work); + spin_unlock_irqrestore(&tgt->srr_lock, flags); + } + } else { + ql_dbg(ql_dbg_tgt_mgt, vha, 0x11030, + "qla_target(%d): tag %lld: %s: no IMM SRR; free SRR\n", + vha->vp_idx, cmd->se_cmd.tag, __func__); + cmd->srr =3D NULL; + kfree(srr); + } +} +EXPORT_SYMBOL(qlt_srr_abort); + /* * If hardware_lock held on entry, might drop it, then reaquire * This function sends the appropriate CTIO to ISP 2xxx or 24xx @@ -3834,9 +3901,16 @@ void qlt_free_cmd(struct qla_tgt_cmd *cmd) qlt_decr_num_pend_cmds(cmd->vha); =20 BUG_ON(cmd->sg_mapped); + if (unlikely(cmd->free_sg)) { + cmd->free_sg =3D 0; + qlt_free_sg(cmd); + } + if (unlikely(cmd->srr)) + qlt_srr_abort(cmd, false); =20 if (unlikely(cmd->aborted || (cmd->trc_flags & (TRC_CTIO_IGNORED | TRC_CTIO_STRANGE | + TRC_SRR_CTIO | TRC_SRR_IMM | TRC_CTIO_ERR)))) { ql_dbg(ql_dbg_tgt_mgt, cmd->vha, 0xe086, "qla_target(%d): tag %lld: free cmd (trc_flags %x, aborted %u, sent_= term_exchg %u, rsp_sent %u)\n", @@ -3861,6 +3935,62 @@ void qlt_free_cmd(struct qla_tgt_cmd *cmd) } EXPORT_SYMBOL(qlt_free_cmd); =20 +/* + * Process a CTIO response for a SCSI command that failed due to SRR. + * + * qpair->qp_lock_ptr supposed to be held on entry + */ +static int qlt_prepare_srr_ctio(struct qla_qpair *qpair, + struct qla_tgt_cmd *cmd) +{ + struct scsi_qla_host *vha =3D cmd->vha; + struct qla_tgt *tgt =3D vha->vha_tgt.qla_tgt; + struct qla_tgt_srr *srr; + + cmd->trc_flags |=3D TRC_SRR_CTIO; + + srr =3D cmd->srr; + if (srr !=3D NULL) { + /* qlt_prepare_srr_imm() was called first. */ + + WARN_ON(srr->ctio_recvd); + WARN_ON(!srr->imm_ntfy_recvd); + + if (vha->hw->tgt.tgt_ops->get_cmd_ref(cmd)) { + ql_dbg(ql_dbg_tgt_mgt, vha, 0x11037, + "qla_target(%d): tag %lld: unable to get cmd ref for SRR processing= \n", + vha->vp_idx, cmd->se_cmd.tag); + qlt_srr_abort(cmd, true); + return -ESHUTDOWN; + } + + srr->ctio_recvd =3D true; + + ql_dbg(ql_dbg_tgt_mgt, vha, 0x1100f, + "qla_target(%d): tag %lld: Scheduling SRR work\n", + vha->vp_idx, cmd->se_cmd.tag); + + /* Schedule the srr for processing in qlt_handle_srr(). */ + /* IRQ is already OFF */ + spin_lock(&tgt->srr_lock); + list_add_tail(&srr->srr_list_entry, &tgt->srr_list); + queue_work_on(cmd->se_cmd.cpuid, qla_tgt_wq, &tgt->srr_work); + spin_unlock(&tgt->srr_lock); + return 0; + } + + srr =3D kzalloc(sizeof(*srr), GFP_ATOMIC); + if (!srr) + return -ENOMEM; + + /* Expect qlt_prepare_srr_imm() to be called. */ + srr->ctio_recvd =3D true; + srr->cmd =3D cmd; + srr->reset_count =3D cmd->reset_count; + cmd->srr =3D srr; + return 0; +} + /* ha->hardware_lock supposed to be held on entry */ static void *qlt_ctio_to_cmd(struct scsi_qla_host *vha, struct rsp_que *rsp, uint32_t handle, void *ctio) @@ -4051,6 +4181,17 @@ static void qlt_do_ctio_completion(struct scsi_qla_h= ost *vha, break; } =20 + case CTIO_SRR_RECEIVED: + ql_dbg(ql_dbg_tgt_mgt, vha, 0x1100e, + "qla_target(%d): tag %lld, op %x: CTIO with SRR status 0x%x receive= d (state %d, port %8phC, LUN %lld, bufflen %d)\n", + vha->vp_idx, cmd->se_cmd.tag, op, status, + cmd->state, cmd->sess->port_name, + cmd->unpacked_lun, cmd->bufflen); + + if (qlt_prepare_srr_ctio(qpair, cmd) =3D=3D 0) + return; + break; + case CTIO_DIF_ERROR: { struct ctio_crc_from_fw *crc =3D (struct ctio_crc_from_fw *)ctio; @@ -4103,6 +4244,15 @@ static void qlt_do_ctio_completion(struct scsi_qla_h= ost *vha, qlt_send_term_exchange(qpair, cmd, &cmd->atio, 1); } =20 + if (unlikely(cmd->srr !=3D NULL)) { + ql_dbg(ql_dbg_tgt_mgt, vha, 0x11031, + "qla_target(%d): tag %lld, op %x: expected CTIO with SRR status; got= status 0x%x: state %d, bufflen %d\n", + vha->vp_idx, cmd->se_cmd.tag, + cmd->cdb ? cmd->cdb[0] : 0, status, cmd->state, + cmd->bufflen); + qlt_srr_abort(cmd, true); + } + if (cmd->state =3D=3D QLA_TGT_STATE_PROCESSED) { cmd->trc_flags |=3D TRC_CTIO_DONE; =20 @@ -4115,6 +4265,7 @@ static void qlt_do_ctio_completion(struct scsi_qla_ho= st *vha, if (status =3D=3D CTIO_SUCCESS) cmd->write_data_transferred =3D 1; =20 + cmd->jiffies_at_hw_st_entry =3D 0; ha->tgt.tgt_ops->handle_data(cmd); return; } else if (cmd->aborted) { @@ -5015,6 +5166,851 @@ static int qlt_handle_login(struct scsi_qla_host *v= ha, return res; } =20 +/* + * Return true if the HBA firmware version is known to have bugs that + * prevent Sequence Level Error Recovery (SLER) / Sequence Retransmission + * Request (SRR) from working. + */ +static bool qlt_has_sler_fw_bug(struct qla_hw_data *ha) +{ + bool has_sler_fw_bug =3D false; + + if (IS_QLA2071(ha)) { + /* + * QLE2694L known bad firmware: + * 9.06.02 + * 9.07.00 + * 9.08.02 + * SRRs trigger hundreds of bogus entries in the response + * queue and various other problems. + * + * QLE2694L known good firmware: + * 8.08.05 + * 9.09.00 + * + * QLE2694L unknown firmware: + * 9.00.00 - 9.05.xx + */ + if (ha->fw_major_version =3D=3D 9 && + ha->fw_minor_version >=3D 6 && + ha->fw_minor_version <=3D 8) + has_sler_fw_bug =3D true; + } + + return has_sler_fw_bug; +} + +/* + * Return true and print a message if the HA has been reset since the SRR + * immediate notify was received; else return false. + */ +static bool qlt_srr_is_chip_reset(struct scsi_qla_host *vha, + struct qla_qpair *qpair, struct qla_tgt_srr *srr) +{ + if (!vha->flags.online || + !qpair->fw_started || + srr->reset_count !=3D qpair->chip_reset) { + ql_dbg(ql_dbg_tgt_mgt, vha, 0x1100d, + "qla_target(%d): chip reset; discarding IMM SRR\n", + vha->vp_idx); + return true; + } + return false; +} + +/* Find and return the command associated with a SRR immediate notify. */ +static struct qla_tgt_cmd *qlt_srr_to_cmd(struct scsi_qla_host *vha, + const struct imm_ntfy_from_isp *iocb) +{ + struct qla_hw_data *ha =3D vha->hw; + struct fc_port *sess; + struct qla_tgt_cmd *cmd; + uint32_t tag =3D le32_to_cpu(iocb->u.isp24.exchange_address); + uint16_t loop_id; + be_id_t s_id; + unsigned long flags; + + if (tag =3D=3D ATIO_EXCHANGE_ADDRESS_UNKNOWN) { + ql_dbg(ql_dbg_tgt_mgt, vha, 0x11009, + "qla_target(%d): IMM SRR with unknown exchange address; reject SRR\n= ", + vha->vp_idx); + return NULL; + } + + loop_id =3D le16_to_cpu(iocb->u.isp24.nport_handle); + + s_id.domain =3D iocb->u.isp24.port_id[2]; + s_id.area =3D iocb->u.isp24.port_id[1]; + s_id.al_pa =3D iocb->u.isp24.port_id[0]; + + spin_lock_irqsave(&ha->tgt.sess_lock, flags); + sess =3D ha->tgt.tgt_ops->find_sess_by_s_id(vha, s_id); + if (!sess) + sess =3D ha->tgt.tgt_ops->find_sess_by_loop_id(vha, loop_id); + if (!sess || sess->deleted) { + ql_dbg(ql_dbg_tgt_mgt, vha, 0x1100a, + "qla_target(%d): could not find session for IMM SRR; reject SRR\n", + vha->vp_idx); + spin_unlock_irqrestore(&ha->tgt.sess_lock, flags); + return NULL; + } + spin_unlock_irqrestore(&ha->tgt.sess_lock, flags); + + cmd =3D ha->tgt.tgt_ops->find_cmd_by_tag(sess, tag); + if (!cmd) { + ql_dbg(ql_dbg_tgt_mgt, vha, 0x1100b, + "qla_target(%d): could not find cmd for IMM SRR; reject SRR\n", + vha->vp_idx); + } else { + u16 srr_ox_id =3D le16_to_cpu(iocb->u.isp24.srr_ox_id); + u16 cmd_ox_id =3D be16_to_cpu(cmd->atio.u.isp24.fcp_hdr.ox_id); + + if (srr_ox_id !=3D cmd_ox_id) { + ql_dbg(ql_dbg_tgt_mgt, vha, 0x1100c, + "qla_target(%d): tag %lld: IMM SRR: srr_ox_id[%04x] !=3D cmd_ox_id[= %04x]; reject SRR\n", + vha->vp_idx, cmd->se_cmd.tag, + srr_ox_id, cmd_ox_id); + cmd =3D NULL; + } + } + + return cmd; +} + +/* + * Handle an immediate notify SRR (Sequence Retransmission Request) messag= e from + * the hardware. The hardware will also send a CTIO with CTIO_SRR_RECEIVE= D status + * for the affected command. + * + * This may be called a second time for the same immediate notify SRR if + * CTIO_SRR_RECEIVED is never received and qlt_srr_abort() is called. + * + * Process context, no locks + */ +static void qlt_handle_srr_imm(struct scsi_qla_host *vha, + struct qla_tgt_srr *srr) +{ + struct qla_tgt *tgt =3D vha->vha_tgt.qla_tgt; + struct qla_hw_data *ha =3D vha->hw; + struct qla_qpair *qpair; + struct qla_tgt_cmd *cmd; + uint8_t srr_explain =3D NOTIFY_ACK_SRR_FLAGS_REJECT_EXPL_NO_EXPL; + + /* handle qlt_srr_abort() */ + if (srr->aborted) { + ql_dbg(ql_dbg_tgt_mgt, vha, 0x11004, + "qla_target(%d): IMM SRR: terminating SRR for aborted cmd\n", + vha->vp_idx); + spin_lock_irq(&ha->hardware_lock); + if (!qlt_srr_is_chip_reset(vha, ha->base_qpair, srr)) + qlt_send_term_imm_notif(vha, &srr->imm_ntfy, 1); + spin_unlock_irq(&ha->hardware_lock); + kfree(srr); + return; + } + if (srr->reject) { + ql_dbg(ql_dbg_tgt_mgt, vha, 0x11005, + "qla_target(%d): IMM SRR: rejecting SRR for unknown cmd\n", + vha->vp_idx); + goto out_reject; + } + + /* Find the command associated with the SRR. */ + cmd =3D qlt_srr_to_cmd(vha, &srr->imm_ntfy); + if (cmd =3D=3D NULL) { + ql_dbg(ql_dbg_tgt_mgt, vha, 0x11005, + "qla_target(%d): IMM SRR: rejecting SRR for unknown cmd\n", + vha->vp_idx); + srr_explain =3D NOTIFY_ACK_SRR_FLAGS_REJECT_EXPL_INVALID_OX_ID_RX_ID; + goto out_reject; + } + + if (ha->tgt.tgt_ops->get_cmd_ref(cmd)) { + ql_dbg(ql_dbg_tgt_mgt, vha, 0x11038, + "qla_target(%d): IMM SRR: unable to get cmd ref; rejecting SRR\n", + vha->vp_idx); + cmd =3D NULL; + goto out_reject; + } + + qpair =3D cmd->qpair; + + spin_lock_irq(qpair->qp_lock_ptr); + + if (cmd->reset_count !=3D srr->reset_count) { + /* force a miscompare */ + srr->reset_count =3D qpair->chip_reset ^ 1; + } + if (qlt_srr_is_chip_reset(vha, qpair, srr)) { + spin_unlock_irq(qpair->qp_lock_ptr); + ha->tgt.tgt_ops->put_cmd_ref(cmd); + kfree(srr); + return; + } + + ql_dbg(ql_dbg_tgt_mgt, vha, 0x11001, + "qla_target(%d): tag %lld, op %x: received IMM SRR\n", + vha->vp_idx, cmd->se_cmd.tag, cmd->cdb ? cmd->cdb[0] : 0); + + cmd->trc_flags |=3D TRC_SRR_IMM; + + if (cmd->srr !=3D NULL) { + if (cmd->srr->imm_ntfy_recvd) { + /* + * Received another immediate notify SRR message for + * this command before the previous one could be processed + * (not expected to happen). + */ + ql_dbg(ql_dbg_tgt_mgt, vha, 0x11006, + "qla_target(%d): tag %lld: received multiple IMM SRR; reject SRR\n", + vha->vp_idx, cmd->se_cmd.tag); + spin_unlock_irq(qpair->qp_lock_ptr); + ha->tgt.tgt_ops->put_cmd_ref(cmd); + goto out_reject; + } + + /* qlt_prepare_srr_ctio() was called first. */ + WARN_ON(!cmd->srr->ctio_recvd); + + /* + * The immediate notify and CTIO handlers both allocated + * separate srr structs; combine them. + */ + memcpy(&cmd->srr->imm_ntfy, &srr->imm_ntfy, + sizeof(srr->imm_ntfy)); + kfree(srr); + srr =3D cmd->srr; + srr->imm_ntfy_recvd =3D true; + + ql_dbg(ql_dbg_tgt_mgt, vha, 0x11002, + "qla_target(%d): tag %lld: schedule SRR work\n", + vha->vp_idx, cmd->se_cmd.tag); + + /* Schedule the srr for processing in qlt_handle_srr(). */ + spin_lock(&tgt->srr_lock); + list_add_tail(&srr->srr_list_entry, &tgt->srr_list); + /* + * Already running the work function; no need to schedule + * tgt->srr_work. + */ + spin_unlock(&tgt->srr_lock); + spin_unlock_irq(qpair->qp_lock_ptr); + /* return with cmd refcount incremented */ + return; + } + + /* The CTIO SRR for this command has not yet been received. */ + + if (cmd->sent_term_exchg) { + ql_dbg(ql_dbg_tgt_mgt, vha, 0x11007, + "qla_target(%d): tag %lld: IMM SRR: cmd already aborted\n", + vha->vp_idx, cmd->se_cmd.tag); + spin_unlock_irq(qpair->qp_lock_ptr); + spin_lock_irq(&ha->hardware_lock); + if (!qlt_srr_is_chip_reset(vha, ha->base_qpair, srr)) + qlt_send_term_imm_notif(vha, &srr->imm_ntfy, 1); + spin_unlock_irq(&ha->hardware_lock); + kfree(srr); + ha->tgt.tgt_ops->put_cmd_ref(cmd); + return; + } + + /* If not expecting a CTIO, then reject IMM SRR. */ + if (!cmd->cmd_sent_to_fw) { + ql_dbg(ql_dbg_tgt_mgt, vha, 0x11008, + "qla_target(%d): tag %lld: IMM SRR but !cmd_sent_to_fw (state %d); r= eject SRR\n", + vha->vp_idx, cmd->se_cmd.tag, cmd->state); + spin_unlock_irq(qpair->qp_lock_ptr); + ha->tgt.tgt_ops->put_cmd_ref(cmd); + goto out_reject; + } + + /* Expect qlt_prepare_srr_ctio() to be called. */ + ql_dbg(ql_dbg_tgt_mgt, vha, 0x11003, + "qla_target(%d): tag %lld: wait for CTIO SRR (state %d)\n", + vha->vp_idx, cmd->se_cmd.tag, cmd->state); + srr->cmd =3D cmd; + cmd->srr =3D srr; + + spin_unlock_irq(qpair->qp_lock_ptr); + + ha->tgt.tgt_ops->put_cmd_ref(cmd); + return; + +out_reject: + qpair =3D vha->hw->base_qpair; + spin_lock_irq(qpair->qp_lock_ptr); + if (!qlt_srr_is_chip_reset(vha, qpair, srr)) + qlt_send_notify_ack(qpair, &srr->imm_ntfy, 0, 0, 0, + NOTIFY_ACK_SRR_FLAGS_REJECT, + NOTIFY_ACK_SRR_REJECT_REASON_UNABLE_TO_PERFORM, + srr_explain); + spin_unlock_irq(qpair->qp_lock_ptr); + kfree(srr); +} + +/* + * Handle an immediate notify SRR (Sequence Retransmission Request) messag= e from + * the hardware. The hardware will also send a CTIO with CTIO_SRR_RECEIVE= D status + * for the affected command. + * + * ha->hardware_lock supposed to be held on entry + */ +static void qlt_prepare_srr_imm(struct scsi_qla_host *vha, + struct imm_ntfy_from_isp *iocb) +{ + struct qla_tgt *tgt =3D vha->vha_tgt.qla_tgt; + struct qla_tgt_srr *srr; + + ql_log(ql_log_warn, vha, 0x11000, "qla_target(%d): received IMM SRR\n", + vha->vp_idx); + + /* + * Need cmd->qpair->qp_lock_ptr, but have ha->hardware_lock. Defer + * processing to a workqueue so that the right lock can be acquired + * safely. + */ + + srr =3D kzalloc(sizeof(*srr), GFP_ATOMIC); + if (!srr) + goto out_reject; + + memcpy(&srr->imm_ntfy, iocb, sizeof(srr->imm_ntfy)); + srr->imm_ntfy_recvd =3D true; + srr->reset_count =3D vha->hw->base_qpair->chip_reset; + spin_lock(&tgt->srr_lock); + list_add_tail(&srr->srr_list_entry, &tgt->srr_list); + queue_work(qla_tgt_wq, &tgt->srr_work); + spin_unlock(&tgt->srr_lock); + /* resume processing in qlt_handle_srr_imm() */ + return; + +out_reject: + qlt_send_notify_ack(vha->hw->base_qpair, iocb, 0, 0, 0, + NOTIFY_ACK_SRR_FLAGS_REJECT, + NOTIFY_ACK_SRR_REJECT_REASON_UNABLE_TO_PERFORM, + NOTIFY_ACK_SRR_FLAGS_REJECT_EXPL_NO_EXPL); +} + +/* + * If possible, undo the effect of qlt_set_data_offset() and restore the c= md + * data buffer back to its full size. + */ +static int qlt_restore_orig_sg(struct qla_tgt_cmd *cmd) +{ + struct scsi_qla_host *vha =3D cmd->vha; + struct se_cmd *se_cmd =3D &cmd->se_cmd; + + WARN_ON(cmd->sg_mapped); + + if (cmd->offset =3D=3D 0) { + /* qlt_set_data_offset() has not been called. */ + return 0; + } + + if (se_cmd->t_data_sg =3D=3D NULL || + se_cmd->t_data_nents =3D=3D 0 || + se_cmd->data_length =3D=3D 0) { + /* The original scatterlist is not available. */ + ql_dbg(ql_dbg_tgt_mgt, vha, 0x1102c, + "qla_target(%d): tag %lld: cannot restore original cmd buffer; keep = modified buffer at offset %d\n", + vha->vp_idx, cmd->se_cmd.tag, cmd->offset); + return -ENOENT; + } + + /* Restore the original scatterlist. */ + ql_dbg(ql_dbg_tgt_mgt, vha, 0x1102d, + "qla_target(%d): tag %lld: restore original cmd buffer: offset %d -> = 0\n", + vha->vp_idx, cmd->se_cmd.tag, cmd->offset); + if (cmd->free_sg) { + cmd->free_sg =3D 0; + qlt_free_sg(cmd); + } + cmd->offset =3D 0; + cmd->sg =3D se_cmd->t_data_sg; + cmd->sg_cnt =3D se_cmd->t_data_nents; + cmd->bufflen =3D se_cmd->data_length; + return 0; +} + +/* + * Adjust the data buffer of the given command to skip over offset bytes f= rom + * the beginning while also reducing the length by offset bytes. + * + * This may be called multiple times for a single command if there are mul= tiple + * SRRs, which each call reducing the buffer size further relative to the + * previous call. Note that the buffer may be reset back to its original = size + * by calling qlt_restore_orig_sg(). + */ +static int qlt_set_data_offset(struct qla_tgt_cmd *cmd, uint32_t offset) +{ + struct scsi_qla_host *vha =3D cmd->vha; + struct scatterlist *sg_srr_start =3D NULL, *sg; + uint32_t first_offset =3D offset; + int sg_srr_cnt, i; + int bufflen =3D 0; + + WARN_ON(cmd->sg_mapped); + + ql_dbg(ql_dbg_tgt, vha, 0x11020, + "qla_target(%d): tag %lld: %s: sg %p sg_cnt %d dir %d cmd->offset %d = cmd->bufflen %d add offset %u\n", + vha->vp_idx, cmd->se_cmd.tag, __func__, cmd->sg, + cmd->sg_cnt, cmd->dma_data_direction, cmd->offset, cmd->bufflen, + offset); + + if (cmd->se_cmd.prot_op !=3D TARGET_PROT_NORMAL) { + ql_dbg(ql_dbg_tgt_mgt, vha, 0x11021, + "qla_target(%d): tag %lld: %s: SRR with protection information at no= nzero offset not implemented\n", + vha->vp_idx, cmd->se_cmd.tag, __func__); + return -EINVAL; + } + + if (!cmd->sg || !cmd->sg_cnt) { + ql_dbg(ql_dbg_tgt_mgt, vha, 0x11022, + "qla_target(%d): tag %lld: %s: Missing cmd->sg or zero cmd->sg_cnt\n= ", + vha->vp_idx, cmd->se_cmd.tag, __func__); + return -EINVAL; + } + + /* + * Walk the current cmd->sg list until we locate the new sg_srr_start + */ + for_each_sg(cmd->sg, sg, cmd->sg_cnt, i) { + ql_dbg(ql_dbg_tgt, vha, 0x11023, + "sg[%d]: %p page: %p, length: %d, offset: %d\n", + i, sg, sg_page(sg), sg->length, sg->offset); + + if (first_offset < sg->length) { + sg_srr_start =3D sg; + break; + } + first_offset -=3D sg->length; + } + + if (!sg_srr_start) { + ql_dbg(ql_dbg_tgt_mgt, vha, 0x11024, + "qla_target(%d): tag %lld: Unable to locate sg_srr_start for offset:= %u\n", + vha->vp_idx, cmd->se_cmd.tag, offset); + return -EINVAL; + } + + ql_dbg(ql_dbg_tgt_mgt, vha, 0x11025, + "qla_target(%d): tag %lld: prepare SRR sgl at sg index %d of %d byte = offset %u of %u\n", + vha->vp_idx, cmd->se_cmd.tag, i, cmd->sg_cnt, + first_offset, sg_srr_start->length); + + sg_srr_cnt =3D cmd->sg_cnt - i; + + if (first_offset =3D=3D 0 && !cmd->free_sg) { + /* + * The offset points to the beginning of a scatterlist element. + * In this case there is no need to modify the first scatterlist + * element, so we can just point directly inside the original + * unmodified scatterlist. + */ + ql_dbg(ql_dbg_tgt, vha, 0x11026, "point directly to old sgl\n"); + cmd->sg =3D sg_srr_start; + } else { + /* + * Allocate at most 2 new scatterlist elements to reduce memory + * requirements. + */ + int n_alloc_sg =3D min(sg_srr_cnt, 2); + struct scatterlist *sg_srr =3D + kmalloc_array(n_alloc_sg, sizeof(*sg_srr), GFP_ATOMIC); + if (!sg_srr) { + ql_dbg(ql_dbg_tgt_mgt, vha, 0x11027, + "qla_target(%d): tag %lld: Unable to allocate SRR scatterlist\n", + vha->vp_idx, cmd->se_cmd.tag); + return -ENOMEM; + } + sg_init_table(sg_srr, n_alloc_sg); + + /* Init the first sg element to skip over the unneeded data. */ + sg_set_page(&sg_srr[0], sg_page(sg_srr_start), + sg_srr_start->length - first_offset, + sg_srr_start->offset + first_offset); + if (sg_srr_cnt =3D=3D 1) { + ql_dbg(ql_dbg_tgt, vha, 0x11028, + "single-element array\n"); + } else if (sg_srr_cnt =3D=3D 2) { + /* Only two elements; copy the last element. */ + ql_dbg(ql_dbg_tgt, vha, 0x11029, + "complete two-element array\n"); + sg =3D sg_next(sg_srr_start); + sg_set_page(&sg_srr[1], sg_page(sg), sg->length, + sg->offset); + } else { + /* + * Three or more elements; chain our newly-allocated + * 2-entry array to the rest of the original + * scatterlist at the splice point. + */ + ql_dbg(ql_dbg_tgt, vha, 0x1102a, + "chain to original scatterlist\n"); + sg =3D sg_next(sg_srr_start); + sg_chain(sg_srr, 2, sg); + } + + /* + * If the previous scatterlist was allocated here on a previous + * call, then it should be safe to free now. + */ + if (cmd->free_sg) + qlt_free_sg(cmd); + cmd->sg =3D sg_srr; + cmd->free_sg =3D 1; + } + + /* Note that sg_cnt doesn't include any extra chain elements. */ + cmd->sg_cnt =3D sg_srr_cnt; + cmd->offset +=3D offset; + cmd->bufflen -=3D offset; + + /* Check the scatterlist length for consistency. */ + for_each_sg(cmd->sg, sg, cmd->sg_cnt, i) { + bufflen +=3D sg->length; + } + if (bufflen !=3D cmd->bufflen) { + ql_dbg(ql_dbg_tgt_mgt, vha, 0x1102b, + "qla_target(%d): tag %lld: %s: bad sgl length: expected %d got %d\n", + vha->vp_idx, cmd->se_cmd.tag, __func__, cmd->bufflen, bufflen); + return -EINVAL; + } + + return 0; +} + +/* + * Given the "SRR relative offset" (offset of data to retry), determine wh= at + * needs to be retransmitted (data and/or status) and return the mask in + * xmit_type. If retrying data, adjust the command buffer to point to onl= y the + * data that need to be retried, skipping over the data that don't need to= be + * retried. + * + * Returns 0 for success or a negative error number. + */ +static inline int qlt_srr_adjust_data(struct qla_tgt_cmd *cmd, + uint32_t srr_rel_offs, int *xmit_type) +{ + struct scsi_qla_host *vha =3D cmd->vha; + int res =3D 0, rel_offs; + + if (srr_rel_offs < cmd->offset || + srr_rel_offs > cmd->offset + cmd->bufflen) { + *xmit_type =3D 0; + ql_dbg(ql_dbg_tgt_mgt, vha, 0x1101e, + "qla_target(%d): tag %lld: srr_rel_offs %u outside accepted range %u= - %u\n", + vha->vp_idx, cmd->se_cmd.tag, srr_rel_offs, + cmd->offset, cmd->offset + cmd->bufflen); + return -EINVAL; + } + + /* + * srr_rel_offs is the offset of the data we need from the beginning of + * the *original* buffer. + * + * cmd->offset is the offset of the current cmd scatterlist from the + * beginning of the *original* buffer, which might be nonzero if there + * was a previous SRR and the buffer could not be reset back to its + * original size. + * + * rel_offs is the offset of the data we need from the beginning of the + * current cmd scatterlist. + */ + rel_offs =3D srr_rel_offs - cmd->offset; + + ql_dbg(ql_dbg_tgt_mgt, vha, 0x1101f, + "qla_target(%d): tag %lld: current buffer [%u - %u); srr_rel_offs=3D%= d, rel_offs=3D%d\n", + vha->vp_idx, cmd->se_cmd.tag, cmd->offset, + cmd->offset + cmd->bufflen, srr_rel_offs, rel_offs); + + *xmit_type =3D QLA_TGT_XMIT_ALL; + + if (rel_offs =3D=3D cmd->bufflen) + *xmit_type =3D QLA_TGT_XMIT_STATUS; + else if (rel_offs > 0) + res =3D qlt_set_data_offset(cmd, rel_offs); + + return res; +} + +/* + * Process a SRR (Sequence Retransmission Request) for a SCSI command once= both + * the immediate notify SRR and CTIO SRR have been received from the hw. + * + * Process context, no locks + */ +static void qlt_handle_srr(struct scsi_qla_host *vha, struct qla_tgt_srr *= srr) +{ + struct qla_tgt_cmd *cmd =3D srr->cmd; + struct se_cmd *se_cmd =3D &cmd->se_cmd; + struct qla_qpair *qpair =3D cmd->qpair; + struct qla_hw_data *ha =3D vha->hw; + uint8_t op =3D cmd->cdb ? cmd->cdb[0] : 0; + uint32_t srr_rel_offs =3D le32_to_cpu(srr->imm_ntfy.u.isp24.srr_rel_offs); + uint16_t srr_ui =3D le16_to_cpu(srr->imm_ntfy.u.isp24.srr_ui); + int xmit_type =3D 0; + bool xmit_response =3D false; + bool rdy_to_xfer =3D false; + bool did_timeout; + bool send_term_exch =3D false; + + spin_lock_irq(qpair->qp_lock_ptr); + + WARN_ON(cmd->cmd_sent_to_fw); + + cmd->srr =3D NULL; + + if (qlt_srr_is_chip_reset(vha, qpair, srr)) + goto out_advance_cmd; + + if (cmd->sent_term_exchg || cmd->sess->deleted || srr->aborted) { + ql_dbg(ql_dbg_tgt_mgt, vha, 0x11010, + "qla_target(%d): tag %lld: IMM SRR: cmd already aborted\n", + vha->vp_idx, cmd->se_cmd.tag); + + spin_unlock_irq(qpair->qp_lock_ptr); + + spin_lock_irq(&ha->hardware_lock); + if (!qlt_srr_is_chip_reset(vha, ha->base_qpair, srr)) + qlt_send_term_imm_notif(vha, &srr->imm_ntfy, 1); + spin_unlock_irq(&ha->hardware_lock); + + send_term_exch =3D true; + + spin_lock_irq(qpair->qp_lock_ptr); + goto out_advance_cmd; + } + + if (srr->reject) + goto out_reject; + + /* + * If we receive multiple SRRs for the same command, place a time limit + * on how long we are willing to retry. This timeout should be less + * than SQA_MAX_HW_PENDING_TIME in scst_qla2xxx.c. + */ + did_timeout =3D time_is_before_jiffies64((cmd->jiffies_at_hw_st_entry ? : + cmd->jiffies_at_alloc) + 30 * HZ); + + qlt_restore_orig_sg(cmd); + + switch (srr_ui) { + case SRR_IU_STATUS: + if (cmd->state !=3D QLA_TGT_STATE_PROCESSED) { + ql_dbg(ql_dbg_tgt_mgt, vha, 0x11011, + "qla_target(%d): tag %lld, op %x: reject SRR_IU_STATUS due to unexp= ected state %d\n", + vha->vp_idx, se_cmd->tag, op, + cmd->state); + goto out_reject; + } + + if (did_timeout) { + ql_dbg(ql_dbg_tgt_mgt, vha, 0x11033, + "qla_target(%d): tag %lld, op %x: reject SRR_IU_STATUS due to timeo= ut\n", + vha->vp_idx, se_cmd->tag, op); + goto out_reject; + } + + ql_dbg(ql_dbg_tgt_mgt, vha, 0x11012, + "qla_target(%d): tag %lld, op %x: accept SRR_IU_STATUS and retransmi= t scsi_status=3D%x\n", + vha->vp_idx, se_cmd->tag, op, + se_cmd->scsi_status); + xmit_type =3D QLA_TGT_XMIT_STATUS; + xmit_response =3D true; + cmd->trc_flags |=3D TRC_SRR_RSP; + break; + + case SRR_IU_DATA_IN: + ql_dbg(ql_dbg_tgt_mgt, vha, 0x11013, + "qla_target(%d): tag %lld, op %x: process SRR_IU_DATA_IN: bufflen=3D= %d, sg_cnt=3D%d, offset=3D%d, srr_offset=3D%d, scsi_status=3D%x\n", + vha->vp_idx, se_cmd->tag, op, cmd->bufflen, + cmd->sg_cnt, cmd->offset, srr_rel_offs, + se_cmd->scsi_status); + + if (cmd->state !=3D QLA_TGT_STATE_PROCESSED) { + ql_dbg(ql_dbg_tgt_mgt, vha, 0x11014, + "qla_target(%d): tag %lld: reject SRR_IU_DATA_IN due to unexpected = state %d\n", + vha->vp_idx, se_cmd->tag, cmd->state); + goto out_reject; + } + + /* + * QLA_TGT_STATE_PROCESSED does not necessarily imply data-in + */ + if (!qlt_has_data(cmd)) { + ql_dbg(ql_dbg_tgt_mgt, vha, 0x11015, + "qla_target(%d): tag %lld: reject SRR_IU_DATA_IN because cmd has no= data to send\n", + vha->vp_idx, se_cmd->tag); + goto out_reject; + } + + if (!cmd->sg || !cmd->sg_cnt) { + ql_dbg(ql_dbg_tgt_mgt, vha, 0x11016, + "qla_target(%d): tag %lld: reject SRR_IU_DATA_IN because buffer is = missing\n", + vha->vp_idx, se_cmd->tag); + goto out_reject; + } + + if (did_timeout) { + ql_dbg(ql_dbg_tgt_mgt, vha, 0x11034, + "qla_target(%d): tag %lld, op %x: reject SRR_IU_DATA_IN due to time= out\n", + vha->vp_idx, se_cmd->tag, op); + goto out_reject; + } + + if (qlt_srr_adjust_data(cmd, srr_rel_offs, &xmit_type) !=3D 0) + goto out_reject; + + ql_dbg(ql_dbg_tgt_mgt, vha, 0x11017, + "qla_target(%d): tag %lld: accept SRR_IU_DATA_IN and retransmit data= : bufflen=3D%d, offset=3D%d\n", + vha->vp_idx, se_cmd->tag, cmd->bufflen, + cmd->offset); + xmit_response =3D true; + cmd->trc_flags |=3D TRC_SRR_RSP; + break; + + case SRR_IU_DATA_OUT: + ql_dbg(ql_dbg_tgt_mgt, vha, 0x11018, + "qla_target(%d): tag %lld, op %x: process SRR_IU_DATA_OUT: bufflen= =3D%d, sg_cnt=3D%d, offset=3D%d, srr_offset=3D%d\n", + vha->vp_idx, se_cmd->tag, op, cmd->bufflen, + cmd->sg_cnt, cmd->offset, srr_rel_offs); + + if (cmd->state !=3D QLA_TGT_STATE_NEED_DATA) { + ql_dbg(ql_dbg_tgt_mgt, vha, 0x11019, + "qla_target(%d): tag %lld: reject SRR_IU_DATA_OUT due to unexpected= state %d\n", + vha->vp_idx, se_cmd->tag, cmd->state); + goto out_reject; + } + + /* + * QLA_TGT_STATE_NEED_DATA implies there should be data-out + */ + if (!qlt_has_data(cmd) || !cmd->sg || !cmd->sg_cnt) { + ql_dbg(ql_dbg_tgt_mgt, vha, 0x1101a, + "qla_target(%d): tag %lld: reject SRR_IU_DATA_OUT because buffer is= missing\n", + vha->vp_idx, se_cmd->tag); + goto out_reject; + } + + if (did_timeout) { + ql_dbg(ql_dbg_tgt_mgt, vha, 0x11035, + "qla_target(%d): tag %lld, op %x: reject SRR_IU_DATA_OUT due to tim= eout\n", + vha->vp_idx, se_cmd->tag, op); + goto out_reject; + } + + if (qlt_srr_adjust_data(cmd, srr_rel_offs, &xmit_type) !=3D 0) + goto out_reject; + + if (!(xmit_type & QLA_TGT_XMIT_DATA)) { + ql_dbg(ql_dbg_tgt_mgt, vha, 0x1101b, + "qla_target(%d): tag %lld: reject SRR_IU_DATA_OUT: bad offset\n", + vha->vp_idx, se_cmd->tag); + goto out_reject; + } + + ql_dbg(ql_dbg_tgt_mgt, vha, 0x1101c, + "qla_target(%d): tag %lld: accept SRR_IU_DATA_OUT and receive data a= gain: bufflen=3D%d, offset=3D%d\n", + vha->vp_idx, se_cmd->tag, cmd->bufflen, + cmd->offset); + cmd->trc_flags |=3D TRC_SRR_XRDY; + rdy_to_xfer =3D true; + break; + + default: + ql_dbg(ql_dbg_tgt_mgt, vha, 0x1101d, + "qla_target(%d): tag %lld, op %x: reject unknown srr_ui value 0x%x: = state=3D%d, bufflen=3D%d, offset=3D%d, srr_offset=3D%d\n", + vha->vp_idx, se_cmd->tag, op, srr_ui, cmd->state, + cmd->bufflen, cmd->offset, srr_rel_offs); + goto out_reject; + } + + qlt_send_notify_ack(qpair, &srr->imm_ntfy, 0, 0, 0, + NOTIFY_ACK_SRR_FLAGS_ACCEPT, 0, 0); + + spin_unlock_irq(qpair->qp_lock_ptr); + + if (xmit_response) { + /* For status and data-in, retransmit the response. */ + if (qlt_xmit_response(cmd, xmit_type, se_cmd->scsi_status)) { + send_term_exch =3D true; + spin_lock_irq(qpair->qp_lock_ptr); + goto out_advance_cmd; + } + } else if (rdy_to_xfer) { + /* For data-out, receive data again. */ + if (qlt_rdy_to_xfer(cmd)) { + send_term_exch =3D true; + spin_lock_irq(qpair->qp_lock_ptr); + goto out_advance_cmd; + } + } + + return; + +out_reject: + qlt_send_notify_ack(qpair, &srr->imm_ntfy, 0, 0, 0, + NOTIFY_ACK_SRR_FLAGS_REJECT, + NOTIFY_ACK_SRR_REJECT_REASON_UNABLE_TO_PERFORM, + NOTIFY_ACK_SRR_FLAGS_REJECT_EXPL_NO_EXPL); + +out_advance_cmd: + if (!cmd->sent_term_exchg && + (send_term_exch || cmd->state !=3D QLA_TGT_STATE_NEED_DATA) && + !qlt_srr_is_chip_reset(vha, qpair, srr)) { + cmd->trc_flags |=3D TRC_SRR_TERM; + qlt_send_term_exchange(qpair, cmd, &cmd->atio, 1); + } + if (cmd->state =3D=3D QLA_TGT_STATE_NEED_DATA) { + /* + * The initiator should abort the command, but if not, try to + * return an error. + */ + cmd->srr_failed =3D 1; + cmd->write_data_transferred =3D 0; + cmd->state =3D QLA_TGT_STATE_DATA_IN; + cmd->jiffies_at_hw_st_entry =3D 0; + vha->hw->tgt.tgt_ops->handle_data(cmd); + } else { + vha->hw->tgt.tgt_ops->free_cmd(cmd); + } + spin_unlock_irq(qpair->qp_lock_ptr); +} + +/* Workqueue function for processing SRR work in process context. */ +static void qlt_handle_srr_work(struct work_struct *work) +{ + struct qla_tgt *tgt =3D container_of(work, struct qla_tgt, srr_work); + struct scsi_qla_host *vha =3D tgt->vha; + + ql_dbg(ql_dbg_tgt_mgt, vha, 0x11032, + "qla_target(%d): Entering SRR work\n", vha->vp_idx); + + for (;;) { + struct qla_tgt_srr *srr; + + spin_lock_irq(&tgt->srr_lock); + srr =3D list_first_entry_or_null(&tgt->srr_list, typeof(*srr), + srr_list_entry); + if (!srr) { + spin_unlock_irq(&tgt->srr_lock); + break; + } + list_del(&srr->srr_list_entry); + spin_unlock_irq(&tgt->srr_lock); + + if (!srr->cmd) { + qlt_handle_srr_imm(vha, srr); + } else { + qlt_handle_srr(vha, srr); + vha->hw->tgt.tgt_ops->put_cmd_ref(srr->cmd); + kfree(srr); + } + } +} + /* * ha->hardware_lock supposed to be held on entry. Might drop it, then rea= quire */ @@ -5442,6 +6438,11 @@ static void qlt_handle_imm_notify(struct scsi_qla_ho= st *vha, send_notify_ack =3D 0; break; =20 + case IMM_NTFY_SRR: + qlt_prepare_srr_imm(vha, iocb); + send_notify_ack =3D 0; + break; + default: ql_dbg(ql_dbg_tgt_mgt, vha, 0xf06d, "qla_target(%d): Received unknown immediate " @@ -6422,6 +7423,9 @@ int qlt_add_target(struct qla_hw_data *ha, struct scs= i_qla_host *base_vha) spin_lock_init(&tgt->sess_work_lock); INIT_WORK(&tgt->sess_work, qlt_sess_work_fn); INIT_LIST_HEAD(&tgt->sess_works_list); + spin_lock_init(&tgt->srr_lock); + INIT_LIST_HEAD(&tgt->srr_list); + INIT_WORK(&tgt->srr_work, qlt_handle_srr_work); atomic_set(&tgt->tgt_global_resets_count, 0); =20 base_vha->vha_tgt.qla_tgt =3D tgt; @@ -7070,6 +8074,32 @@ qlt_81xx_config_nvram_stage2(struct scsi_qla_host *v= ha, } } =20 +/* Update any settings that depend on ha->fw_*_version. */ +void +qlt_config_nvram_with_fw_version(struct scsi_qla_host *vha) +{ + struct qla_hw_data *ha =3D vha->hw; + + if (!QLA_TGT_MODE_ENABLED()) + return; + + if (ql2xtgt_tape_enable && qlt_has_sler_fw_bug(ha)) { + ql_log(ql_log_warn, vha, 0x11036, + "WARNING: ignoring ql2xtgt_tape_enable due to buggy HBA firmware; pl= ease upgrade FW\n"); + + /* Disable FC Tape support */ + if (ha->isp_ops->nvram_config =3D=3D qla81xx_nvram_config) { + struct init_cb_81xx *icb =3D + (struct init_cb_81xx *)ha->init_cb; + icb->firmware_options_2 &=3D cpu_to_le32(~BIT_12); + } else { + struct init_cb_24xx *icb =3D + (struct init_cb_24xx *)ha->init_cb; + icb->firmware_options_2 &=3D cpu_to_le32(~BIT_12); + } + } +} + void qlt_modify_vp_config(struct scsi_qla_host *vha, struct vp_config_entry_24xx *vpmod) diff --git a/drivers/scsi/qla2xxx/qla_target.h b/drivers/scsi/qla2xxx/qla_t= arget.h index 972a7af1c81c..1351bd3fb55c 100644 --- a/drivers/scsi/qla2xxx/qla_target.h +++ b/drivers/scsi/qla2xxx/qla_target.h @@ -184,6 +184,7 @@ struct nack_to_isp { #define NOTIFY_ACK_SRR_REJECT_REASON_UNABLE_TO_PERFORM 0x9 =20 #define NOTIFY_ACK_SRR_FLAGS_REJECT_EXPL_NO_EXPL 0 +#define NOTIFY_ACK_SRR_FLAGS_REJECT_EXPL_INVALID_OX_ID_RX_ID 0x17 #define NOTIFY_ACK_SRR_FLAGS_REJECT_EXPL_UNABLE_TO_SUPPLY_DATA 0x2a =20 #define NOTIFY_ACK_SUCCESS 0x01 @@ -686,6 +687,8 @@ struct qla_tgt_func_tmpl { int (*handle_tmr)(struct qla_tgt_mgmt_cmd *, u64, uint16_t, uint32_t); struct qla_tgt_cmd *(*get_cmd)(struct fc_port *); + int (*get_cmd_ref)(struct qla_tgt_cmd *cmd); + void (*put_cmd_ref)(struct qla_tgt_cmd *cmd); void (*rel_cmd)(struct qla_tgt_cmd *); void (*free_cmd)(struct qla_tgt_cmd *); void (*free_mcmd)(struct qla_tgt_mgmt_cmd *); @@ -823,7 +826,13 @@ struct qla_tgt { int notify_ack_expected; int abts_resp_expected; int modify_lun_expected; + + spinlock_t srr_lock; + struct list_head srr_list; + struct work_struct srr_work; + atomic_t tgt_global_resets_count; + struct list_head tgt_list_entry; }; =20 @@ -862,6 +871,7 @@ enum trace_flags { TRC_ABORT =3D BIT_19, TRC_DIF_ERR =3D BIT_20, TRC_CTIO_IGNORED =3D BIT_21, + TRC_SRR_IMM =3D BIT_22, }; =20 struct qla_tgt_cmd { @@ -882,6 +892,10 @@ struct qla_tgt_cmd { =20 unsigned int conf_compl_supported:1; unsigned int sg_mapped:1; + + /* Call qlt_free_sg() if set. */ + unsigned int free_sg:1; + unsigned int write_data_transferred:1; =20 /* Set if the SCSI status was sent successfully. */ @@ -893,6 +907,9 @@ struct qla_tgt_cmd { unsigned int cmd_in_wq:1; unsigned int edif:1; =20 + /* Set if a SRR was rejected. */ + unsigned int srr_failed:1; + /* Set if the exchange has been terminated. */ unsigned int sent_term_exchg:1; =20 @@ -902,6 +919,7 @@ struct qla_tgt_cmd { */ unsigned int aborted:1; =20 + struct qla_tgt_srr *srr; struct scatterlist *sg; /* cmd data buffer SG vector */ int sg_cnt; /* SG segments count */ int bufflen; /* cmd buffer length */ @@ -941,6 +959,14 @@ struct qla_tgt_cmd { uint16_t prot_flags; =20 unsigned long jiffies_at_term_exchg; + + /* + * jiffies64 when qlt_rdy_to_xfer() or qlt_xmit_response() first + * called, or 0 when not in those states. Used to limit the number of + * SRR retries. + */ + uint64_t jiffies_at_hw_st_entry; + uint64_t jiffies_at_alloc; uint64_t jiffies_at_free; =20 @@ -1002,6 +1028,45 @@ struct qla_tgt_prm { uint16_t tot_dsds; }; =20 +/* + * SRR (Sequence Retransmission Request) - resend or re-receive some or all + * data or status to recover from a transient I/O error. + */ +struct qla_tgt_srr { + /* + * Copy of immediate notify SRR message received from hw; valid only if + * imm_ntfy_recvd is true. + */ + struct imm_ntfy_from_isp imm_ntfy; + + struct list_head srr_list_entry; + + /* The command affected by this SRR, or NULL if not yet determined. */ + struct qla_tgt_cmd *cmd; + + /* Used to detect if the HBA has been reset since receiving the SRR. */ + uint32_t reset_count; + + /* + * The hardware sends two messages for each SRR - an immediate notify + * and a CTIO with CTIO_SRR_RECEIVED status. These keep track of which + * messages have been received. The SRR can be processed once both of + * these are true. + */ + bool imm_ntfy_recvd; + bool ctio_recvd; + + /* + * This is set to true if the affected command was aborted (cmd may be + * set to NULL), in which case the immediate notify exchange also needs + * to be aborted. + */ + bool aborted; + + /* This is set to true to force the SRR to be rejected. */ + bool reject; +}; + /* Check for Switch reserved address */ #define IS_SW_RESV_ADDR(_s_id) \ ((_s_id.b.domain =3D=3D 0xff) && ((_s_id.b.area & 0xf0) =3D=3D 0xf0)) @@ -1056,6 +1121,20 @@ static inline uint32_t sid_to_key(const be_id_t s_id) s_id.al_pa; } =20 +/* + * Free the scatterlist allocated by qlt_set_data_offset(). Call this onl= y if + * cmd->free_sg is set. + */ +static inline void qlt_free_sg(struct qla_tgt_cmd *cmd) +{ + /* + * The scatterlist may be chained to the original scatterlist, but we + * only need to free the first segment here since that is the only part + * allocated by qlt_set_data_offset(). + */ + kfree(cmd->sg); +} + /* * Exported symbols from qla_target.c LLD logic used by qla2xxx code.. */ @@ -1064,6 +1143,7 @@ extern void qlt_response_pkt_all_vps(struct scsi_qla_= host *, struct rsp_que *, extern int qlt_rdy_to_xfer(struct qla_tgt_cmd *); extern int qlt_xmit_response(struct qla_tgt_cmd *, int, uint8_t); extern int qlt_abort_cmd(struct qla_tgt_cmd *); +void qlt_srr_abort(struct qla_tgt_cmd *cmd, bool reject); void qlt_send_term_exchange(struct qla_qpair *qpair, struct qla_tgt_cmd *cmd, struct atio_from_isp *atio, int ha_locked); void qlt_unmap_sg(struct scsi_qla_host *vha, struct qla_tgt_cmd *cmd); @@ -1085,6 +1165,7 @@ extern void qlt_81xx_config_nvram_stage2(struct scsi_= qla_host *, struct init_cb_81xx *); extern void qlt_81xx_config_nvram_stage1(struct scsi_qla_host *, struct nvram_81xx *); +void qlt_config_nvram_with_fw_version(struct scsi_qla_host *vha); extern void qlt_modify_vp_config(struct scsi_qla_host *, struct vp_config_entry_24xx *); extern void qlt_probe_one_stage1(struct scsi_qla_host *, struct qla_hw_dat= a *); diff --git a/drivers/scsi/qla2xxx/tcm_qla2xxx.c b/drivers/scsi/qla2xxx/tcm_= qla2xxx.c index 169219fe47a2..2fff68935338 100644 --- a/drivers/scsi/qla2xxx/tcm_qla2xxx.c +++ b/drivers/scsi/qla2xxx/tcm_qla2xxx.c @@ -291,6 +291,16 @@ static struct qla_tgt_cmd *tcm_qla2xxx_get_cmd(struct = fc_port *sess) return cmd; } =20 +static int tcm_qla2xxx_get_cmd_ref(struct qla_tgt_cmd *cmd) +{ + return target_get_sess_cmd(&cmd->se_cmd, true); +} + +static void tcm_qla2xxx_put_cmd_ref(struct qla_tgt_cmd *cmd) +{ + target_put_sess_cmd(&cmd->se_cmd); +} + static void tcm_qla2xxx_rel_cmd(struct qla_tgt_cmd *cmd) { target_free_tag(cmd->sess->se_sess, &cmd->se_cmd); @@ -531,6 +541,9 @@ static void tcm_qla2xxx_handle_data_work(struct work_st= ruct *work) if (cmd->se_cmd.pi_err) transport_generic_request_failure(&cmd->se_cmd, cmd->se_cmd.pi_err); + else if (cmd->srr_failed) + transport_generic_request_failure(&cmd->se_cmd, + TCM_SNACK_REJECTED); else transport_generic_request_failure(&cmd->se_cmd, TCM_CHECK_CONDITION_ABORT_CMD); @@ -1526,6 +1539,8 @@ static const struct qla_tgt_func_tmpl tcm_qla2xxx_tem= plate =3D { .handle_data =3D tcm_qla2xxx_handle_data, .handle_tmr =3D tcm_qla2xxx_handle_tmr, .get_cmd =3D tcm_qla2xxx_get_cmd, + .get_cmd_ref =3D tcm_qla2xxx_get_cmd_ref, + .put_cmd_ref =3D tcm_qla2xxx_put_cmd_ref, .rel_cmd =3D tcm_qla2xxx_rel_cmd, .free_cmd =3D tcm_qla2xxx_free_cmd, .free_mcmd =3D tcm_qla2xxx_free_mcmd, --=20 2.43.0 From nobody Wed Sep 10 01:42:33 2025 Received: from mail.cybernetics.com (mail.cybernetics.com [72.215.153.18]) (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 30BF42367CD for ; Mon, 8 Sep 2025 19:13:25 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=72.215.153.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757358807; cv=none; b=WvERFI45/DO22VV89FxVyYdtjUpiP7L0ilO34yHO5KRDj44MjLA+EOD+HlyctlAvxt26aSbn3Lzz7xxguuKOjVIFDpO8ry0dNKp8BTlu7j6IkiSOenyUzBmLu15g84aIjcF8q+eNoK23E3RAydCztuch1HvVu4QrIAJ5NjPyDDE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757358807; c=relaxed/simple; bh=//1icLJ4ufJR4zCDs7H+TQmn4zGQ4AglrZhJLSCiZ6U=; h=Message-ID:Date:MIME-Version:Subject:From:To:Cc:References: In-Reply-To:Content-Type; b=kj7qFqKhbvVwAJclOc4lFQ0rJ2vDijx9A1Sb/aPTv6+B/FQaOXGKrSOFhh3p5X351qsCWIAqHxqIXJUbgXC402ZwYjQwxay8ncpmm+bxloaWdLoKCH9zgxgzttNOAWrpp9H1EDlYM096gjr+uy+t4VX5nL8tQhX9hrAzgGd7wEU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=cybernetics.com; spf=pass smtp.mailfrom=cybernetics.com; dkim=pass (1024-bit key) header.d=cybernetics.com header.i=@cybernetics.com header.b=Fx4j3R0K; arc=none smtp.client-ip=72.215.153.18 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=cybernetics.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=cybernetics.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=cybernetics.com header.i=@cybernetics.com header.b="Fx4j3R0K" Received: from cybernetics.com ([10.10.4.126]) by mail.cybernetics.com with ESMTP id wjE6MEAjW9ovgQN8; Mon, 08 Sep 2025 15:13:24 -0400 (EDT) X-Barracuda-Envelope-From: tonyb@cybernetics.com X-Barracuda-RBL-Trusted-Forwarder: 10.10.4.126 X-ASG-Whitelist: Client DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=cybernetics.com; s=mail; bh=d1Ngc6m13lU4oNOnZg0ml+HN5EGsBnGsre7eO+PZdUA=; h=Content-Transfer-Encoding:Content-Type:In-Reply-To:References:Cc:To:From: Content-Language:Subject:MIME-Version:Date:Message-ID; b=Fx4j3R0K7rvWQLh0usy3 /GD0tF4nXWVDOvGmlIijSEeNtd0Xuq8/mJLamG2ktQXJASGxBzUTFNkT6O9VYViVqlWOZnzTTcRhH AoSOaTdi+p+9/a1MHM4c9lgGmW19RBIaq+/5ITrPLzDeUHhAOeGiWScIjxGnGmnucKGomaOGE4= Received: from [10.157.2.224] (HELO [192.168.200.1]) by cybernetics.com (CommuniGate SPEC SMTP 8.0.5) with ESMTPS id 14188817; Mon, 08 Sep 2025 15:13:24 -0400 Message-ID: <7f80b39f-1237-49a2-8161-8e2c43826d03@cybernetics.com> X-Barracuda-RBL-Trusted-Forwarder: 10.157.2.224 Date: Mon, 8 Sep 2025 15:13:24 -0400 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 User-Agent: Mozilla Thunderbird Subject: [PATCH 15/15] scsi: qla2xxx: improve safety of cmd lookup by handle Content-Language: en-US X-ASG-Orig-Subj: [PATCH 15/15] scsi: qla2xxx: improve safety of cmd lookup by handle From: Tony Battersby To: Nilesh Javali , GR-QLogic-Storage-Upstream@marvell.com, "James E.J. Bottomley" , "Martin K. Petersen" Cc: linux-scsi , target-devel@vger.kernel.org, scst-devel@lists.sourceforge.net, "linux-kernel@vger.kernel.org" References: In-Reply-To: Content-Transfer-Encoding: quoted-printable X-Barracuda-Connect: UNKNOWN[10.10.4.126] X-Barracuda-Start-Time: 1757358804 X-Barracuda-URL: https://10.10.4.122:443/cgi-mod/mark.cgi X-Barracuda-BRTS-Status: 1 X-Virus-Scanned: by bsmtpd at cybernetics.com X-Barracuda-Scan-Msg-Size: 7494 X-ASG-Debug-ID: 1757358804-1cf43947df30c830001-xx1T2L Content-Type: text/plain; charset="utf-8" (target mode) The driver associates two different structs with numeric handles and passes the handles to the hardware. When the hardware passes the handle back to the driver, the driver consults a table of void * to convert the handle back to the struct without checking the type of struct. This can lead to treating one type of struct as a different type if the HBA firmware misbehaves (and some firmware versions do). So verify the type of struct is what is expected before using it. But we can also do better than that. Also verify that the exchange address of the message sent from the hardware matches the exchange address of the command being returned. This adds an extra guard against buggy HBA firmware that returns duplicate messages multiple times (which has also been seen) in case the driver has reused the handle for a different command of the same type. These problems were seen on a QLE2694L with firmware 9.08.02 when testing SLER / SRR support. The SRR caused the HBA to flood the response queue with hundreds of bogus entries. Signed-off-by: Tony Battersby --- drivers/scsi/qla2xxx/qla_dbg.c | 2 +- drivers/scsi/qla2xxx/qla_target.c | 115 ++++++++++++++++++++++++------ 2 files changed, 96 insertions(+), 21 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_dbg.c b/drivers/scsi/qla2xxx/qla_dbg.c index 9f56bec26231..a7e3ec9bba47 100644 --- a/drivers/scsi/qla2xxx/qla_dbg.c +++ b/drivers/scsi/qla2xxx/qla_dbg.c @@ -54,7 +54,7 @@ * | Misc | 0xd303 | 0xd031-0xd0ff | * | | | 0xd101-0xd1fe | * | | | 0xd214-0xd2fe | - * | Target Mode | 0xe086 | | + * | Target Mode | 0xe089 | | * | Target Mode Management | 0xf09b | 0xf002 | * | | | 0xf046-0xf049 | * | Target Mode Task Management | 0x1000d | | diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_t= arget.c index 70e1810d4996..a2f880ceb8d6 100644 --- a/drivers/scsi/qla2xxx/qla_target.c +++ b/drivers/scsi/qla2xxx/qla_target.c @@ -3993,7 +3993,8 @@ static int qlt_prepare_srr_ctio(struct qla_qpair *qpa= ir, =20 /* ha->hardware_lock supposed to be held on entry */ static void *qlt_ctio_to_cmd(struct scsi_qla_host *vha, - struct rsp_que *rsp, uint32_t handle, void *ctio) + struct rsp_que *rsp, uint32_t handle, uint8_t cmd_type, + const void *ctio) { void *cmd =3D NULL; struct req_que *req; @@ -4016,29 +4017,103 @@ static void *qlt_ctio_to_cmd(struct scsi_qla_host = *vha, =20 h &=3D QLA_CMD_HANDLE_MASK; =20 - if (h !=3D QLA_TGT_NULL_HANDLE) { - if (unlikely(h >=3D req->num_outstanding_cmds)) { - ql_dbg(ql_dbg_tgt, vha, 0xe052, - "qla_target(%d): Wrong handle %x received\n", - vha->vp_idx, handle); - return NULL; - } - - cmd =3D req->outstanding_cmds[h]; - if (unlikely(cmd =3D=3D NULL)) { - ql_dbg(ql_dbg_async, vha, 0xe053, - "qla_target(%d): Suspicious: unable to find the command with handle= %x req->id %d rsp->id %d\n", - vha->vp_idx, handle, req->id, rsp->id); - return NULL; - } - req->outstanding_cmds[h] =3D NULL; - } else if (ctio !=3D NULL) { + if (h =3D=3D QLA_TGT_NULL_HANDLE) { /* We can't get loop ID from CTIO7 */ ql_dbg(ql_dbg_tgt, vha, 0xe054, "qla_target(%d): Wrong CTIO received: QLA24xx doesn't " "support NULL handles\n", vha->vp_idx); return NULL; } + if (unlikely(h >=3D req->num_outstanding_cmds)) { + ql_dbg(ql_dbg_tgt, vha, 0xe052, + "qla_target(%d): Wrong handle %x received\n", + vha->vp_idx, handle); + return NULL; + } + + cmd =3D req->outstanding_cmds[h]; + + /* + * Some places in the code set outstanding_cmds[h] to NULL and force + * the command to complete early without waiting for the CTIO. In that + * case we would get cmd =3D=3D NULL. But in the rare case that the + * detached handle is reused for a different command before we get the + * CTIO for the detached cmd, we might find the wrong command here + * instead. So compare the cmd_type and exchange_address to make sure + * that the cmd matches the CTIO. If they don't match, return NULL and + * ignore the CTIO. + * + * This also guards against buggy HBA firmware that returns the same + * CTIO multiple times. + */ + + if (unlikely(cmd =3D=3D NULL)) { + if (cmd_type =3D=3D TYPE_TGT_CMD) { + __le32 ctio_exchange_addr =3D + ((const struct ctio7_from_24xx *)ctio)-> + exchange_address; + + ql_dbg(ql_dbg_tgt_mgt, vha, 0xe053, + "qla_target(%d): tag %u: handle %x: cmd detached; ignoring CTIO (ha= ndle %x req->id %d rsp->id %d)\n", + vha->vp_idx, le32_to_cpu(ctio_exchange_addr), h, + handle, req->id, rsp->id); + } else { + ql_dbg(ql_dbg_tgt_mgt, vha, 0xe053, + "qla_target(%d): cmd detached; ignoring CTIO (handle %x req->id %d = rsp->id %d)\n", + vha->vp_idx, handle, req->id, rsp->id); + } + return NULL; + } + + if (unlikely(((srb_t *)cmd)->cmd_type !=3D cmd_type)) { + ql_dbg(ql_dbg_tgt_mgt, vha, 0xe087, + "qla_target(%d): handle %x: cmd detached; ignoring CTIO (cmd_type mi= smatch)\n", + vha->vp_idx, h); + return NULL; + } + + switch (cmd_type) { + case TYPE_TGT_CMD: { + __le32 ctio_exchange_addr =3D + ((const struct ctio7_from_24xx *)ctio)-> + exchange_address; + __le32 cmd_exchange_addr =3D + ((struct qla_tgt_cmd *)cmd)-> + atio.u.isp24.exchange_addr; + + BUILD_BUG_ON(offsetof(struct ctio7_from_24xx, + exchange_address) !=3D + offsetof(struct ctio_crc_from_fw, + exchange_address)); + + if (unlikely(ctio_exchange_addr !=3D cmd_exchange_addr)) { + ql_dbg(ql_dbg_tgt_mgt, vha, 0xe088, + "qla_target(%d): tag %u: handle %x: cmd detached; ignoring CTIO (ex= change address mismatch)\n", + vha->vp_idx, le32_to_cpu(ctio_exchange_addr), h); + return NULL; + } + break; + } + + case TYPE_TGT_TMCMD: { + __le32 ctio_exchange_addr =3D + ((const struct abts_resp_from_24xx_fw *)ctio)-> + exchange_address; + __le32 cmd_exchange_addr =3D + ((struct qla_tgt_mgmt_cmd *)cmd)-> + orig_iocb.abts.exchange_address; + + if (unlikely(ctio_exchange_addr !=3D cmd_exchange_addr)) { + ql_dbg(ql_dbg_tgt_mgt, vha, 0xe089, + "qla_target(%d): ABTS: handle %x: cmd detached; ignoring CTIO (exch= ange address mismatch)\n", + vha->vp_idx, h); + return NULL; + } + break; + } + } + + req->outstanding_cmds[h] =3D NULL; =20 return cmd; } @@ -4067,7 +4142,7 @@ static void qlt_do_ctio_completion(struct scsi_qla_ho= st *vha, =20 ctio_flags =3D le16_to_cpu(ctio->flags); =20 - cmd =3D qlt_ctio_to_cmd(vha, rsp, handle, ctio); + cmd =3D qlt_ctio_to_cmd(vha, rsp, handle, TYPE_TGT_CMD, ctio); if (unlikely(cmd =3D=3D NULL)) { if ((handle & ~QLA_TGT_HANDLE_MASK) =3D=3D QLA_TGT_SKIP_HANDLE && (ctio_flags & 0xe1ff) =3D=3D (CTIO7_FLAGS_STATUS_MODE_1 | @@ -6817,7 +6892,7 @@ static void qlt_handle_abts_completion(struct scsi_ql= a_host *vha, struct qla_tgt_mgmt_cmd *mcmd; struct qla_hw_data *ha =3D vha->hw; =20 - mcmd =3D qlt_ctio_to_cmd(vha, rsp, pkt->handle, pkt); + mcmd =3D qlt_ctio_to_cmd(vha, rsp, pkt->handle, TYPE_TGT_TMCMD, pkt); if (mcmd =3D=3D NULL && h !=3D QLA_TGT_SKIP_HANDLE) { ql_dbg(ql_dbg_async, vha, 0xe064, "qla_target(%d): ABTS Comp without mcmd\n", --=20 2.43.0 From nobody Wed Sep 10 01:42:33 2025 Received: from mail.cybernetics.com (mail.cybernetics.com [72.215.153.18]) (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 BA33C2367CD for ; Mon, 8 Sep 2025 19:14:33 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=72.215.153.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757358875; cv=none; b=bcaek3vfQJOivqnu+O+VnyETAfJ1vL+qk+OjDdw1MNiUvHSKwSAsIVC0RTjZIf1TiDIWPtuzjcA7CF2om0GX9H+AoQHYEDqcRZJllZPS3sArFD2uylBS008ofAfkCEZwWToqdbo7AtJAM3XdMoWMWYOKVsEwA+d1YU2rc5xyx9I= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757358875; c=relaxed/simple; bh=m9Tmo1alBNSq12nOWoyg4oli2lSpZELuM72iGV8P75o=; h=Message-ID:Date:MIME-Version:Subject:From:To:Cc:References: In-Reply-To:Content-Type; b=o/7ajADI9mv8MIJ2zj+ArrKr8bt3UJy2roSicLdKlXGOhFLb6zjFfjD4m9GFAXAt6JAIlLbRBYf/iRF/0dME/IAvun5tLU+ub6LcLU04WLfeR9T3e0/lBWsWPvR3Br10eeYg1SBsvW6rf1Vgr0Oc/NNa0LJYl+V5w6WEMvhCukc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=cybernetics.com; spf=pass smtp.mailfrom=cybernetics.com; dkim=pass (1024-bit key) header.d=cybernetics.com header.i=@cybernetics.com header.b=YBaX1QVL; arc=none smtp.client-ip=72.215.153.18 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=cybernetics.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=cybernetics.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=cybernetics.com header.i=@cybernetics.com header.b="YBaX1QVL" Received: from cybernetics.com ([10.10.4.126]) by mail.cybernetics.com with ESMTP id 6Sup7jlleNCiPoZE; Mon, 08 Sep 2025 15:14:32 -0400 (EDT) X-Barracuda-Envelope-From: tonyb@cybernetics.com X-Barracuda-RBL-Trusted-Forwarder: 10.10.4.126 X-ASG-Whitelist: Client DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=cybernetics.com; s=mail; bh=o845yKcCavjgQhO4zXmQrIY6so63ORQ6IIblbQOdUtQ=; h=Content-Transfer-Encoding:Content-Type:In-Reply-To:References:Cc:To:From: Content-Language:Subject:MIME-Version:Date:Message-ID; b=YBaX1QVLxN20MCbXptE5 qoKifjyTmqhTgzkx+ykU/97O5gJWSvUL9mEaZqKWU/r8EDGQ7fKyz7MR/Rebkh3x6CLkJdYDoJLb1 PZ5dO61lLvCfQJWrCk6XZlfqCVI5WimxgrSPPABoOSoiaZOBoTwugoeyX3xLCqzU0aoZHXGDBo= Received: from [10.157.2.224] (HELO [192.168.200.1]) by cybernetics.com (CommuniGate SPEC SMTP 8.0.5) with ESMTPS id 14189178; Mon, 08 Sep 2025 15:14:32 -0400 Message-ID: <919c102c-db75-40c3-b571-ffd3b8180d7f@cybernetics.com> X-Barracuda-RBL-Trusted-Forwarder: 10.157.2.224 Date: Mon, 8 Sep 2025 15:14:32 -0400 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 User-Agent: Mozilla Thunderbird Subject: [SCST PATCH] qla2x00t-32gbit: add on_abort_cmd callback Content-Language: en-US X-ASG-Orig-Subj: [SCST PATCH] qla2x00t-32gbit: add on_abort_cmd callback From: Tony Battersby To: Nilesh Javali , GR-QLogic-Storage-Upstream@marvell.com, "James E.J. Bottomley" , "Martin K. Petersen" Cc: linux-scsi , target-devel@vger.kernel.org, scst-devel@lists.sourceforge.net, "linux-kernel@vger.kernel.org" References: In-Reply-To: Content-Transfer-Encoding: quoted-printable X-Barracuda-Connect: UNKNOWN[10.10.4.126] X-Barracuda-Start-Time: 1757358872 X-Barracuda-URL: https://10.10.4.122:443/cgi-mod/mark.cgi X-Barracuda-BRTS-Status: 0 X-Virus-Scanned: by bsmtpd at cybernetics.com X-Barracuda-Scan-Msg-Size: 2830 X-ASG-Debug-ID: 1757358872-1cf43947df30c860001-xx1T2L Content-Type: text/plain; charset="utf-8" This enables the initiator to abort commands that are stuck pending in the HW without waiting for a timeout. Signed-off-by: Tony Battersby --- This patch applies to the out-of-tree SCST project, not to the Linux kernel. Apply after all the other qla2xxx patches. qla2x00t-32gbit/qla2x00-target/scst_qla2xxx.c | 42 +++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/qla2x00t-32gbit/qla2x00-target/scst_qla2xxx.c b/qla2x00t-32gbi= t/qla2x00-target/scst_qla2xxx.c index 9371dad06..76d3685a4 100644 --- a/qla2x00t-32gbit/qla2x00-target/scst_qla2xxx.c +++ b/qla2x00t-32gbit/qla2x00-target/scst_qla2xxx.c @@ -81,6 +81,7 @@ static int sqa_xmit_response(struct scst_cmd *scst_cmd); static int sqa_rdy_to_xfer(struct scst_cmd *scst_cmd); static void sqa_on_free_cmd(struct scst_cmd *scst_cmd); static void sqa_task_mgmt_fn_done(struct scst_mgmt_cmd *mcmd); +static void sqa_on_abort_cmd(struct scst_cmd *scst_cmd); static int sqa_get_initiator_port_transport_id(struct scst_tgt *tgt, struct scst_session *scst_sess, uint8_t **transport_id); @@ -1255,6 +1256,7 @@ static struct scst_tgt_template sqa_scst_template =3D= { =20 .on_free_cmd =3D sqa_on_free_cmd, .task_mgmt_fn_done =3D sqa_task_mgmt_fn_done, + .on_abort_cmd =3D sqa_on_abort_cmd, .close_session =3D sqa_close_session, =20 .get_initiator_port_transport_id =3D sqa_get_initiator_port_transport_id, @@ -1982,6 +1984,46 @@ out_unlock: TRACE_EXIT(); } =20 +struct sqa_abort_work { + struct scst_cmd *scst_cmd; + struct work_struct abort_work; +}; + +static void sqa_on_abort_cmd_work(struct work_struct *work) +{ + struct sqa_abort_work *abort_work =3D + container_of(work, struct sqa_abort_work, abort_work); + struct scst_cmd *scst_cmd =3D abort_work->scst_cmd; + struct qla_tgt_cmd *cmd =3D scst_cmd_get_tgt_priv(scst_cmd); + + TRACE_ENTRY(); + + kfree(abort_work); + qlt_abort_cmd(cmd); + scst_cmd_put(scst_cmd); + + TRACE_EXIT(); +} + +static void sqa_on_abort_cmd(struct scst_cmd *scst_cmd) +{ + struct sqa_abort_work *abort_work; + + /* + * The caller holds sess->sess_list_lock, but qlt_abort_cmd() needs to + * acquire qpair->qp_lock_ptr (ha->hardware_lock); these locks are + * acquired in the reverse order elsewhere. Use a workqueue to avoid + * acquiring the locks in the wrong order here. + */ + abort_work =3D kmalloc(sizeof(*abort_work), GFP_ATOMIC); + if (!abort_work) + return; + scst_cmd_get(scst_cmd); + abort_work->scst_cmd =3D scst_cmd; + INIT_WORK(&abort_work->abort_work, sqa_on_abort_cmd_work); + schedule_work(&abort_work->abort_work); +} + /* * The following structure defines the callbacks which will be executed * from functions in the qla_target.c file back to this interface --=20 2.43.0