From: Sasha Levin <sashal@kernel.org>
To: linux-kernel@vger.kernel.org, stable@vger.kernel.org
Cc: Even Xu <even.xu@intel.com>,
Srinivas Pandruvada <srinivas.pandruvada@intel.com>,
Jiri Kosina <jkosina@suse.cz>, Sasha Levin <sashal@kernel.org>,
srinivas.pandruvada@linux.intel.com, jikos@kernel.org,
benjamin.tissoires@redhat.com, linux-input@vger.kernel.org
Subject: [PATCH AUTOSEL 5.19 11/38] hid: intel-ish-hid: ishtp: Fix ishtp client sending disordered message
Date: Sat, 10 Sep 2022 17:15:56 -0400 [thread overview]
Message-ID: <20220910211623.69825-11-sashal@kernel.org> (raw)
In-Reply-To: <20220910211623.69825-1-sashal@kernel.org>
From: Even Xu <even.xu@intel.com>
[ Upstream commit e1fa076706209cc447d7a2abd0843a18277e5ef7 ]
There is a timing issue captured during ishtp client sending stress tests.
It was observed during stress tests that ISH firmware is getting out of
ordered messages. This is a rare scenario as the current set of ISH client
drivers don't send much data to firmware. But this may not be the case
going forward.
When message size is bigger than IPC MTU, ishtp splits the message into
fragments and uses serialized async method to send message fragments.
The call stack:
ishtp_cl_send_msg_ipc->ipc_tx_callback(first fregment)->
ishtp_send_msg(with callback)->write_ipc_to_queue->
write_ipc_from_queue->callback->ipc_tx_callback(next fregment)......
When an ipc write complete interrupt is received, driver also calls
write_ipc_from_queue->ipc_tx_callback in ISR to start sending of next fragment.
Through ipc_tx_callback uses spin_lock to protect message splitting, as the
serialized sending method will call back to ipc_tx_callback again, so it doesn't
put sending under spin_lock, it causes driver cannot guarantee all fragments
be sent in order.
Considering this scenario:
ipc_tx_callback just finished a fragment splitting, and not call ishtp_send_msg
yet, there is a write complete interrupt happens, then ISR->write_ipc_from_queue
->ipc_tx_callback->ishtp_send_msg->write_ipc_to_queue......
Because ISR has higher exec priority than normal thread, this causes the new
fragment be sent out before previous fragment. This disordered message causes
invalid message to firmware.
The solution is, to send fragments synchronously:
Use ishtp_write_message writing fragments into tx queue directly one by one,
instead of ishtp_send_msg only writing one fragment with completion callback.
As no completion callback be used, so change ipc_tx_callback to ipc_tx_send.
Signed-off-by: Even Xu <even.xu@intel.com>
Acked-by: Srinivas Pandruvada <srinivas.pandruvada@intel.com>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/hid/intel-ish-hid/ishtp/client.c | 68 ++++++++++++++----------
1 file changed, 39 insertions(+), 29 deletions(-)
diff --git a/drivers/hid/intel-ish-hid/ishtp/client.c b/drivers/hid/intel-ish-hid/ishtp/client.c
index 405e0d5212cc8..df0a825694f52 100644
--- a/drivers/hid/intel-ish-hid/ishtp/client.c
+++ b/drivers/hid/intel-ish-hid/ishtp/client.c
@@ -626,13 +626,14 @@ static void ishtp_cl_read_complete(struct ishtp_cl_rb *rb)
}
/**
- * ipc_tx_callback() - IPC tx callback function
+ * ipc_tx_send() - IPC tx send function
* @prm: Pointer to client device instance
*
- * Send message over IPC either first time or on callback on previous message
- * completion
+ * Send message over IPC. Message will be split into fragments
+ * if message size is bigger than IPC FIFO size, and all
+ * fragments will be sent one by one.
*/
-static void ipc_tx_callback(void *prm)
+static void ipc_tx_send(void *prm)
{
struct ishtp_cl *cl = prm;
struct ishtp_cl_tx_ring *cl_msg;
@@ -677,32 +678,41 @@ static void ipc_tx_callback(void *prm)
list);
rem = cl_msg->send_buf.size - cl->tx_offs;
- ishtp_hdr.host_addr = cl->host_client_id;
- ishtp_hdr.fw_addr = cl->fw_client_id;
- ishtp_hdr.reserved = 0;
- pmsg = cl_msg->send_buf.data + cl->tx_offs;
+ while (rem > 0) {
+ ishtp_hdr.host_addr = cl->host_client_id;
+ ishtp_hdr.fw_addr = cl->fw_client_id;
+ ishtp_hdr.reserved = 0;
+ pmsg = cl_msg->send_buf.data + cl->tx_offs;
+
+ if (rem <= dev->mtu) {
+ /* Last fragment or only one packet */
+ ishtp_hdr.length = rem;
+ ishtp_hdr.msg_complete = 1;
+ /* Submit to IPC queue with no callback */
+ ishtp_write_message(dev, &ishtp_hdr, pmsg);
+ cl->tx_offs = 0;
+ cl->sending = 0;
- if (rem <= dev->mtu) {
- ishtp_hdr.length = rem;
- ishtp_hdr.msg_complete = 1;
- cl->sending = 0;
- list_del_init(&cl_msg->list); /* Must be before write */
- spin_unlock_irqrestore(&cl->tx_list_spinlock, tx_flags);
- /* Submit to IPC queue with no callback */
- ishtp_write_message(dev, &ishtp_hdr, pmsg);
- spin_lock_irqsave(&cl->tx_free_list_spinlock, tx_free_flags);
- list_add_tail(&cl_msg->list, &cl->tx_free_list.list);
- ++cl->tx_ring_free_size;
- spin_unlock_irqrestore(&cl->tx_free_list_spinlock,
- tx_free_flags);
- } else {
- /* Send IPC fragment */
- spin_unlock_irqrestore(&cl->tx_list_spinlock, tx_flags);
- cl->tx_offs += dev->mtu;
- ishtp_hdr.length = dev->mtu;
- ishtp_hdr.msg_complete = 0;
- ishtp_send_msg(dev, &ishtp_hdr, pmsg, ipc_tx_callback, cl);
+ break;
+ } else {
+ /* Send ipc fragment */
+ ishtp_hdr.length = dev->mtu;
+ ishtp_hdr.msg_complete = 0;
+ /* All fregments submitted to IPC queue with no callback */
+ ishtp_write_message(dev, &ishtp_hdr, pmsg);
+ cl->tx_offs += dev->mtu;
+ rem = cl_msg->send_buf.size - cl->tx_offs;
+ }
}
+
+ list_del_init(&cl_msg->list);
+ spin_unlock_irqrestore(&cl->tx_list_spinlock, tx_flags);
+
+ spin_lock_irqsave(&cl->tx_free_list_spinlock, tx_free_flags);
+ list_add_tail(&cl_msg->list, &cl->tx_free_list.list);
+ ++cl->tx_ring_free_size;
+ spin_unlock_irqrestore(&cl->tx_free_list_spinlock,
+ tx_free_flags);
}
/**
@@ -720,7 +730,7 @@ static void ishtp_cl_send_msg_ipc(struct ishtp_device *dev,
return;
cl->tx_offs = 0;
- ipc_tx_callback(cl);
+ ipc_tx_send(cl);
++cl->send_msg_cnt_ipc;
}
--
2.35.1
next prev parent reply other threads:[~2022-09-10 21:17 UTC|newest]
Thread overview: 40+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-09-10 21:15 [PATCH AUTOSEL 5.19 01/38] Input: goodix - add support for GT1158 Sasha Levin
2022-09-10 21:15 ` [PATCH AUTOSEL 5.19 02/38] platform/surface: aggregator_registry: Add support for Surface Laptop Go 2 Sasha Levin
2022-09-10 21:15 ` [PATCH AUTOSEL 5.19 03/38] drm/msm/rd: Fix FIFO-full deadlock Sasha Levin
2022-09-10 21:15 ` [PATCH AUTOSEL 5.19 04/38] peci: cpu: Fix use-after-free in adev_release() Sasha Levin
2022-09-10 21:15 ` [PATCH AUTOSEL 5.19 05/38] hwmon: (pmbus) Use dev_err_probe() to filter -EPROBE_DEFER error messages Sasha Levin
2022-09-10 21:15 ` [PATCH AUTOSEL 5.19 06/38] kvm: x86: mmu: Always flush TLBs when enabling dirty logging Sasha Levin
2022-09-10 21:15 ` [PATCH AUTOSEL 5.19 07/38] dt-bindings: iio: gyroscope: bosch,bmg160: correct number of pins Sasha Levin
2022-09-10 21:15 ` [PATCH AUTOSEL 5.19 08/38] HID: hidraw: fix memory leak in hidraw_release() Sasha Levin
2022-09-10 21:15 ` [PATCH AUTOSEL 5.19 09/38] HID: asus: ROG NKey: Ignore portion of 0x5a report Sasha Levin
2022-09-10 21:15 ` [PATCH AUTOSEL 5.19 10/38] HID: ishtp-hid-clientHID: ishtp-hid-client: Fix comment typo Sasha Levin
2022-09-10 21:15 ` Sasha Levin [this message]
2022-09-10 21:15 ` [PATCH AUTOSEL 5.19 12/38] HID: thrustmaster: Add sparco wheel and fix array length Sasha Levin
2022-09-10 21:15 ` [PATCH AUTOSEL 5.19 13/38] HID: AMD_SFH: Add a DMI quirk entry for Chromebooks Sasha Levin
2022-09-10 21:15 ` [PATCH AUTOSEL 5.19 14/38] HID: add Lenovo Yoga C630 battery quirk Sasha Levin
2022-09-10 21:16 ` [PATCH AUTOSEL 5.19 15/38] HID: Add Apple Touchbar on T2 Macs in hid_have_special_driver list Sasha Levin
2022-09-10 21:16 ` [PATCH AUTOSEL 5.19 16/38] HID: intel-ish-hid: ipc: Add Meteor Lake PCI device ID Sasha Levin
2022-09-10 21:16 ` [PATCH AUTOSEL 5.19 17/38] HID: nintendo: fix rumble worker null pointer deref Sasha Levin
2022-09-10 21:16 ` [PATCH AUTOSEL 5.19 18/38] Bluetooth: MGMT: Fix Get Device Flags Sasha Levin
2022-09-10 21:16 ` [PATCH AUTOSEL 5.19 19/38] tg3: Disable tg3 device on system reboot to avoid triggering AER Sasha Levin
2022-09-10 21:16 ` [PATCH AUTOSEL 5.19 20/38] r8152: add PID for the Lenovo OneLink+ Dock Sasha Levin
2022-09-10 21:16 ` [PATCH AUTOSEL 5.19 21/38] gpio: mockup: remove gpio debugfs when remove device Sasha Levin
2022-09-10 21:16 ` [PATCH AUTOSEL 5.19 22/38] ieee802154: cc2520: add rc code in cc2520_tx() Sasha Levin
2022-09-10 21:16 ` [PATCH AUTOSEL 5.19 23/38] Input: iforce - add support for Boeder Force Feedback Wheel Sasha Levin
2022-09-10 21:16 ` [PATCH AUTOSEL 5.19 24/38] drm/amdgpu: disable FRU access on special SIENNA CICHLID card Sasha Levin
2022-09-10 21:16 ` [PATCH AUTOSEL 5.19 25/38] drm/amd/pm: use vbios carried pptable for all SMU13.0.7 SKUs Sasha Levin
2022-09-10 21:16 ` [PATCH AUTOSEL 5.19 26/38] nvme-pci: add NVME_QUIRK_BOGUS_NID for Lexar NM610 Sasha Levin
2022-09-10 21:16 ` [PATCH AUTOSEL 5.19 27/38] nvmet-tcp: fix unhandled tcp states in nvmet_tcp_state_change() Sasha Levin
2022-09-10 21:16 ` [PATCH AUTOSEL 5.19 28/38] drm/amd/amdgpu: skip ucode loading if ucode_size == 0 Sasha Levin
2022-09-10 21:16 ` [PATCH AUTOSEL 5.19 29/38] net: dsa: hellcreek: Print warning only once Sasha Levin
2022-09-10 21:16 ` [PATCH AUTOSEL 5.19 30/38] perf/arm_pmu_platform: fix tests for platform_get_irq() failure Sasha Levin
2022-09-10 21:16 ` [PATCH AUTOSEL 5.19 31/38] platform/x86: acer-wmi: Acer Aspire One AOD270/Packard Bell Dot keymap fixes Sasha Levin
2022-09-10 21:16 ` [PATCH AUTOSEL 5.19 32/38] usb: storage: Add ASUS <0x0b05:0x1932> to IGNORE_UAS Sasha Levin
2022-09-10 21:16 ` [PATCH AUTOSEL 5.19 33/38] misc: fastrpc: increase maximum session count Sasha Levin
2022-09-11 9:31 ` Johan Hovold
2022-09-12 8:57 ` Sasha Levin
2022-09-10 21:16 ` [PATCH AUTOSEL 5.19 34/38] platform/x86: asus-wmi: Increase FAN_CURVE_BUF_LEN to 32 Sasha Levin
2022-09-10 21:16 ` [PATCH AUTOSEL 5.19 35/38] LoongArch: Fix section mismatch due to acpi_os_ioremap() Sasha Levin
2022-09-10 21:16 ` [PATCH AUTOSEL 5.19 36/38] LoongArch: Fix arch_remove_memory() undefined build error Sasha Levin
2022-09-10 21:16 ` [PATCH AUTOSEL 5.19 37/38] gpio: 104-dio-48e: Make irq_chip immutable Sasha Levin
2022-09-10 21:16 ` [PATCH AUTOSEL 5.19 38/38] gpio: 104-idio-16: " Sasha Levin
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20220910211623.69825-11-sashal@kernel.org \
--to=sashal@kernel.org \
--cc=benjamin.tissoires@redhat.com \
--cc=even.xu@intel.com \
--cc=jikos@kernel.org \
--cc=jkosina@suse.cz \
--cc=linux-input@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=srinivas.pandruvada@intel.com \
--cc=srinivas.pandruvada@linux.intel.com \
--cc=stable@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox