From nobody Sun Jun 21 21:48:28 2026 Received: from mx0b-0031df01.pphosted.com (mx0b-0031df01.pphosted.com [205.220.180.131]) (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 EEECD34389C for ; Wed, 10 Jun 2026 05:52:50 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=205.220.180.131 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1781070772; cv=none; b=qqOWWNrqltt8Jmhz7NcE0H1txuVfyiB/6WSmnhNTkV/knyRBEk2JS6goyhgL1boZm5EnKPTzp2gDdVhqH4ew/aD3yiw/davEtkn61Z5BYzWX1FYcnBB8imG3oHQtu3xxEzrjPNT2FZGzhjRFtrXlAAJQcIoHkugwX988M8xKOIg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1781070772; c=relaxed/simple; bh=QNVGduDx0nxQ0bQDSfenGVzWTDrg2845VWNRYOROTY8=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=pgREsGDazz9cVjPeo1PthKfSdZMmBsM1+Vc4OCXb3EhFvi+BtZShNVkfAZH+0uKBkWiLhC7EkvqkD2nKzJhjG9+ibJOlH6KfzmOWGVMUn0ZSdsIBszsT6JEG5mdp2nDj8iX+7ZzkWbNKdNfxKkGDZ8GtcUYIzPLrzvD5dq5rtwA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=oss.qualcomm.com; spf=pass smtp.mailfrom=oss.qualcomm.com; dkim=pass (2048-bit key) header.d=qualcomm.com header.i=@qualcomm.com header.b=iC36aIsW; dkim=pass (2048-bit key) header.d=oss.qualcomm.com header.i=@oss.qualcomm.com header.b=UMTqJs84; arc=none smtp.client-ip=205.220.180.131 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=oss.qualcomm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=oss.qualcomm.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=qualcomm.com header.i=@qualcomm.com header.b="iC36aIsW"; dkim=pass (2048-bit key) header.d=oss.qualcomm.com header.i=@oss.qualcomm.com header.b="UMTqJs84" Received: from pps.filterd (m0279868.ppops.net [127.0.0.1]) by mx0a-0031df01.pphosted.com (8.18.1.11/8.18.1.11) with ESMTP id 65A45DYI387404 for ; Wed, 10 Jun 2026 05:52:50 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=qualcomm.com; h= cc:content-transfer-encoding:content-type:date:from:in-reply-to :message-id:mime-version:references:subject:to; s=qcppdkim1; bh= VpziLNpumf5VyVaf+LUv71Prv1GwddB0rwZE31HmFFc=; b=iC36aIsWwD8i0v8g GCRa6n+Ltt8RVo70nPWCVfagPJp1SUok7Y+K9GgSe6dO6wzvoGF9K69X9Mcj2SaE vapS9AdXVAoJ72iBY48cQWV7ZKsA2d7o9bvodQ5tlJe/YPvo75/JtmFdA3fg48BT 7e5qYKQe8pjxfAi0YQ1dLcq23cs3XMre9e0JAjH2JW3XyPzzNvHfj304YpxbPQv2 YAjM2bJgw5K+WBXZ3CbfGkUlYPZn91X948ZdBVzB7Xf666kodXU/IJuk1msOq+HI rJP2cTuko0tqEg6f0JBdERkUUvCduQByyu9Fx1oweUcHJUjM1WwPDaB7LufSryGb KlG1sQ== Received: from mail-pj1-f71.google.com (mail-pj1-f71.google.com [209.85.216.71]) by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 4eq0kd8a50-1 (version=TLSv1.3 cipher=TLS_AES_128_GCM_SHA256 bits=128 verify=NOT) for ; Wed, 10 Jun 2026 05:52:49 +0000 (GMT) Received: by mail-pj1-f71.google.com with SMTP id 98e67ed59e1d1-36d97955899so6056322a91.0 for ; Tue, 09 Jun 2026 22:52:49 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=oss.qualcomm.com; s=google; t=1781070769; x=1781675569; darn=vger.kernel.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:from:to:cc:subject:date:message-id :reply-to; bh=VpziLNpumf5VyVaf+LUv71Prv1GwddB0rwZE31HmFFc=; b=UMTqJs84ZwPx1zHqt33I0EO4er14bb7s2D++Qbgk9Vxyp2P+Hj5yi4z3zqnOHdTUSn TwshNZaqQFcp4EfdBBH6tUiwHnuTBW3vq5tlcP/3ealRcQZyMca9wC6Wkdng4bJhAtII y4G2G2c+tAwqctn6tN7glgTPHgRC4QBYnqKbCk1bMaIPCz76efV0ynwravTi5F3uNhaI +o9j/U8wSh1MRQh2YxTKT3+a2eO78ymqttrZwMJR5CYrHDw19tJvW07S64YvYAO4mKdJ fksuJSh/Jud3fWDTplwm/ubX+fiLDtDxmjJrCBojrZARdlgNZzWGhPHZj2H/bqVAOONq HaDg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1781070769; x=1781675569; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:x-gm-gg:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to; bh=VpziLNpumf5VyVaf+LUv71Prv1GwddB0rwZE31HmFFc=; b=IVbY5UztUvOEVvL3XSYcLfQKhROD7xmoc2FfnicsE+FVghUUUVTyMxBwlLMiXWiEoN dnK2iqL1Gskl+c6uLoGyn6wNz/V9xRS8zhiJOO1XEQ9bRWgB1CaGK8bkPQQOxChZDncB 7YVzJPBOKWrM8b7jRmGLwj2xtOOzGIlxerfTy7sDhV5aaQMSNRdza0Tn29f9b/yGGfsK mUTCD+GwjAU8wBeZoJwLS8FalvxFVwg1cJuUXqf+hFcKBuZwJe2PxBtJmiTdoDz+3G7F 4h+6++eGSropWRlLZwfAkZlylAUtmIhxXeWoR1MjewIa+QIutRkN1wlxrUoSkpiDgExu 4cLg== X-Forwarded-Encrypted: i=1; AFNElJ8qd0jY4spuUn/QcYDiBQff8eAvm0XcuprMuhGsRUf3qUQt23gOV/SCHgf63fCysjWUtnMubxImF0xxmUs=@vger.kernel.org X-Gm-Message-State: AOJu0YwCqqEUfpql+KBSwCUkN1SjutvoGoBtzPDUY4sKgI1iTbro73vG 4XeaA7aZR+NKnwcDImCACZ0FCcS0nM0p+C62vSlqypBwN4xEO14j+t6qEiO57yvAQ1SidTNGChb fWvbFMYH9P+o79v6yB0EyyYHnHU2zVwXoL8XMUUeTvnwqxTzJ128AtOd7Seyzf7zaN90= X-Gm-Gg: Acq92OFYykjZX0Oovkm3mk7U/T6D4fIPceJZMBQzwKVmEsC8+Ek2+L8DpkpIU783RtL 8OeTPKR6S+ZAj/4TqJUszysnWvoS6/Pw9UjCL8WAw7N8dhW1mF48k1Gidl7BW4X3iTgE4jgS1fa NlJkK80SqFJ8DNsxTPsTg8B9R00c4kN70B2v9cu2bfDzamQXsgx3Er5SHcbBWNiXPGDc0JczLTS KHHnhYgAnRriWR1eOSdE3A4fTsbtIMnXp+qwWNbSvC1lIE6X1Y2Lt+/9wncOL7IFApLIcZbWt+q OQpwEpd39sJgBslCBRf+2ajyK5yjmRrEqh0h591URSF3C5FdAJlS4BfeA8myS0dLIyf1ITDChap wmzKgrYoUQMAvD2M/eps+joICdE+EgnM7P2PLo/BFoO67UQE32ifGxO8GeQ== X-Received: by 2002:a17:90b:54c3:b0:36a:d6dd:9fee with SMTP id 98e67ed59e1d1-37520dc57d2mr7068751a91.12.1781070768471; Tue, 09 Jun 2026 22:52:48 -0700 (PDT) X-Received: by 2002:a17:90b:54c3:b0:36a:d6dd:9fee with SMTP id 98e67ed59e1d1-37520dc57d2mr7068713a91.12.1781070767801; Tue, 09 Jun 2026 22:52:47 -0700 (PDT) Received: from hu-sumk-hyd.qualcomm.com ([202.46.23.25]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-2c24edc8acasm108601105ad.45.2026.06.09.22.52.45 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 09 Jun 2026 22:52:47 -0700 (PDT) From: Sumit Kumar Date: Wed, 10 Jun 2026 11:22:25 +0530 Subject: [PATCH v3 1/3] bus: mhi: host: clients: Add loopback driver with sysfs interface Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260610-loopback_mhi-v3-1-a733c0cef61a@oss.qualcomm.com> References: <20260610-loopback_mhi-v3-0-a733c0cef61a@oss.qualcomm.com> In-Reply-To: <20260610-loopback_mhi-v3-0-a733c0cef61a@oss.qualcomm.com> To: Manivannan Sadhasivam Cc: mhi@lists.linux.dev, linux-arm-msm@vger.kernel.org, linux-kernel@vger.kernel.org, Sumit Kumar , Krishna Chaitanya Chundru X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=ed25519-sha256; t=1781070762; l=15221; i=sumit.kumar@oss.qualcomm.com; s=20250409; h=from:subject:message-id; bh=QNVGduDx0nxQ0bQDSfenGVzWTDrg2845VWNRYOROTY8=; b=mdS3QPhtrDbai2LMCBAd7QP4hXjQ5XzeZeR4F1cMbpwa3vcrCqj1a/fPA6cdUbcNkQRtxw+OP LK/yrKbkC9WBLOeWVDFWrVAsgvP5A9/H3KyNpAiDu0dUDfuF3EVdbL1 X-Developer-Key: i=sumit.kumar@oss.qualcomm.com; a=ed25519; pk=3cys6srXqLACgA68n7n7KjDeM9JiMK1w6VxzMxr0dnM= X-Authority-Analysis: v=2.4 cv=TeamcxQh c=1 sm=1 tr=0 ts=6a28fbb1 cx=c_pps a=UNFcQwm+pnOIJct1K4W+Mw==:117 a=ZePRamnt/+rB5gQjfz0u9A==:17 a=IkcTkHD0fZMA:10 a=FelO9ux0wxsA:10 a=s4-Qcg_JpJYA:10 a=VkNPw1HP01LnGYTKEx00:22 a=u7WPNUs3qKkmUXheDGA7:22 a=ZpdpYltYx_vBUK5n70dp:22 a=EUspDBNiAAAA:8 a=VwQbUJbxAAAA:8 a=fr5qSj5IhElrMRFVs5kA:9 a=QEXdDO2ut3YA:10 a=uKXjsCUrEbL0IQVhDsJ9:22 X-Proofpoint-GUID: JEuc3B1q-O3XJL7HVj0bShz97u8empGU X-Proofpoint-ORIG-GUID: JEuc3B1q-O3XJL7HVj0bShz97u8empGU X-Proofpoint-Spam-Details-Enc: AW1haW4tMjYwNjEwMDA1MiBTYWx0ZWRfX5dpv9tYre02K A2jGPuuWb/SlhfSw4wsbv5n9SImBkkClXVNzg70edf0Tw3hwSFw9shVpVGRtd8C5o1PxhFt4BrH tkIsfTNln1eVafPwUCxU2g7XxZy9+XsnbSK4vOEFqzOS/GcdmUpZh+fnYVg5NTw7a4AlIklyU4Z lpTU/whw3t1kSLoi161dudOzsUKz5JQiNoe+/RYSV9N8VAOHsFUdy4MqWnmdpjRRN2tr/U4Nk9c LC2YatYInKvbiVyFwBOxCswjBX9Dt18/7qzmhtaYUMcr509c46Z5F/7ExScvIl6B/wSdWwMLpa9 WPBTKvZZuTnlYfnWEBFZPDx3tnmcoRX7ukoxNSrqUfH+qKBFNEihfLJTqc7ZZzhq90fn+RNdsay aeynDdZ/bWutWf4i6gp7UOjrVLT+hu9BrU24WiBs4kfop9tUF1YioVnG5QC6Uw7PY2mqroSQoOW OJxUQDrgCucCFnMBHPQ== X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1143,Hydra:6.1.125,FMLib:17.12.100.49 definitions=2026-06-10_01,2026-06-09_02,2025-10-01_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 lowpriorityscore=0 suspectscore=0 malwarescore=0 phishscore=0 spamscore=0 impostorscore=0 clxscore=1015 priorityscore=1501 bulkscore=0 adultscore=0 classifier=typeunknown authscore=0 authtc= authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.22.0-2605210000 definitions=main-2606100052 The MHI specification defines a LOOPBACK channel. The endpoint firmware echoes back whatever the host sends on this channel. Without a host-side driver, there is no way to exercise this channel to validate MHI data path integrity between host and endpoint. Add a host-side loopback driver that binds to the LOOPBACK channel and expose a sysfs interface for data path testing. The sysfs interface allows users to configure TRE buffer size and count, trigger a loopback test, and read the result. Co-developed-by: Krishna Chaitanya Chundru Signed-off-by: Krishna Chaitanya Chundru Signed-off-by: Sumit Kumar --- .../ABI/testing/sysfs-bus-mhi-devices-loopback | 51 ++++ MAINTAINERS | 1 + drivers/bus/mhi/host/Kconfig | 1 + drivers/bus/mhi/host/Makefile | 1 + drivers/bus/mhi/host/clients/Kconfig | 17 ++ drivers/bus/mhi/host/clients/Makefile | 2 + drivers/bus/mhi/host/clients/loopback.c | 316 +++++++++++++++++= ++++ 7 files changed, 389 insertions(+) diff --git a/Documentation/ABI/testing/sysfs-bus-mhi-devices-loopback b/Doc= umentation/ABI/testing/sysfs-bus-mhi-devices-loopback new file mode 100644 index 0000000000000000000000000000000000000000..3bd770747799a3341a23903cc1a= 108e650e915b8 --- /dev/null +++ b/Documentation/ABI/testing/sysfs-bus-mhi-devices-loopback @@ -0,0 +1,51 @@ +What: /sys/bus/mhi/devices/mhi_LOOPBACK/tre_size +Date: April 2026 +KernelVersion: 7.1 +Contact: mhi@lists.linux.dev +Description: + (RW) Size of each Transfer Ring Element (TRE) buffer in bytes + used for the loopback test. Valid range is 1 to the value + reported by max_tre_size. Default value is 32 bytes. + +What: /sys/bus/mhi/devices/mhi_LOOPBACK/max_tre_size +Date: April 2026 +KernelVersion: 7.1 +Contact: mhi@lists.linux.dev +Description: + (RO) Maximum allowed TRE size in bytes. Reading this file + returns the upper bound for the tre_size attribute. + +What: /sys/bus/mhi/devices/mhi_LOOPBACK/num_tre +Date: April 2026 +KernelVersion: 7.1 +Contact: mhi@lists.linux.dev +Description: + (RW) Number of Transfer Ring Elements (TREs) to use per + loopback test. Must be greater than zero and must not exceed + the channel ring capacity. Default value is 1. + +What: /sys/bus/mhi/devices/mhi_LOOPBACK/start +Date: April 2026 +KernelVersion: 7.1 +Contact: mhi@lists.linux.dev +Description: + (WO) Write any value to trigger a loopback test. The driver + sends random data to the endpoint using the configured tre_size + and num_tre parameters, waits for the endpoint to echo it back, + and verifies the received data matches what was sent. + + This is a blocking write that returns when the test completes + or times out after 5 seconds. + +What: /sys/bus/mhi/devices/mhi_LOOPBACK/status +Date: April 2026 +KernelVersion: 7.1 +Contact: mhi@lists.linux.dev +Description: + (RO) Result of the last loopback test. Returns one of: + "pass" - last test completed successfully + "fail" - last test failed + "not started" - no test has been run yet + + Reading this file while a test is in progress will block + until the test completes. diff --git a/MAINTAINERS b/MAINTAINERS index 6dcfbd11efef87927041f5cf58d70633dbb4b18d..ff12a6da48947ac853bc638359a= 7046fea85fc21 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -16441,6 +16441,7 @@ L: linux-arm-msm@vger.kernel.org S: Maintained T: git git://git.kernel.org/pub/scm/linux/kernel/git/mani/mhi.git F: Documentation/ABI/stable/sysfs-bus-mhi +F: Documentation/ABI/testing/sysfs-bus-mhi-devices-loopback F: Documentation/mhi/ F: drivers/bus/mhi/ F: drivers/pci/endpoint/functions/pci-epf-mhi.c diff --git a/drivers/bus/mhi/host/Kconfig b/drivers/bus/mhi/host/Kconfig index da5cd0c9fc620ab595e742c422f1a22a2a84c7b9..627c57948235aa52348179ae8b2= d0826ebaed01e 100644 --- a/drivers/bus/mhi/host/Kconfig +++ b/drivers/bus/mhi/host/Kconfig @@ -29,3 +29,4 @@ config MHI_BUS_PCI_GENERIC This driver provides MHI PCI controller driver for devices such as Qualcomm SDX55 based PCIe modems. =20 +source "drivers/bus/mhi/host/clients/Kconfig" diff --git a/drivers/bus/mhi/host/Makefile b/drivers/bus/mhi/host/Makefile index 859c2f38451c669b3d3014c374b2b957c99a1cfe..2a16008aeb38127494782bbff4e= 1656428d2b776 100644 --- a/drivers/bus/mhi/host/Makefile +++ b/drivers/bus/mhi/host/Makefile @@ -4,3 +4,4 @@ mhi-$(CONFIG_MHI_BUS_DEBUG) +=3D debugfs.o =20 obj-$(CONFIG_MHI_BUS_PCI_GENERIC) +=3D mhi_pci_generic.o mhi_pci_generic-y +=3D pci_generic.o +obj-y +=3D clients/ diff --git a/drivers/bus/mhi/host/clients/Kconfig b/drivers/bus/mhi/host/cl= ients/Kconfig new file mode 100644 index 0000000000000000000000000000000000000000..d1463c3e0df0da461c815afaec6= 23ba349b51dda --- /dev/null +++ b/drivers/bus/mhi/host/clients/Kconfig @@ -0,0 +1,17 @@ +# SPDX-License-Identifier: GPL-2.0 + +config MHI_BUS_LOOPBACK + tristate "MHI LOOPBACK client driver" + depends on MHI_BUS + help + MHI LOOPBACK client driver that binds to the MHI LOOPBACK channel + as defined in the MHI specification. The LOOPBACK channel is + implemented by MHI-based devices (modems, WLAN) in the field, where + the endpoint firmware echoes back whatever the host sends. + + This driver exposes a sysfs interface for testing MHI data path + integrity between host and endpoint. Users can configure the TRE + size and count, trigger a loopback test, and read the result. + + To compile this driver as a module, choose M here. The module + will be called mhi_loopback. diff --git a/drivers/bus/mhi/host/clients/Makefile b/drivers/bus/mhi/host/c= lients/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..3811b6928f42b38f94b1167941c= f3b0fe512d32b --- /dev/null +++ b/drivers/bus/mhi/host/clients/Makefile @@ -0,0 +1,2 @@ +obj-$(CONFIG_MHI_BUS_LOOPBACK) +=3D mhi_loopback.o +mhi_loopback-y +=3D loopback.o diff --git a/drivers/bus/mhi/host/clients/loopback.c b/drivers/bus/mhi/host= /clients/loopback.c new file mode 100644 index 0000000000000000000000000000000000000000..3ae4d94dbc6b291006bb206ec40= a634ae9561f5d --- /dev/null +++ b/drivers/bus/mhi/host/clients/loopback.c @@ -0,0 +1,316 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +/* + * The MHI LOOPBACK channel is defined in the MHI specification and is + * implemented by MHI-based devices (modems, WLAN) already deployed in the + * field. The endpoint firmware echoes back whatever the host sends on this + * channel. This driver binds to the LOOPBACK channel and exposes a sysfs + * interface for testing MHI data path integrity between host and endpoint. + * The sysfs interface is stable ABI because the wire protocol is fixed by + * the endpoint firmware and cannot be changed. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MHI_LOOPBACK_DEFAULT_TRE_SIZE 32 +#define MHI_LOOPBACK_DEFAULT_NUM_TRE 1 +#define MHI_LOOPBACK_TIMEOUT_MS 5000 +#define MHI_LOOPBACK_MAX_TRE_SIZE SZ_64K + +struct mhi_loopback { + struct mhi_device *mdev; + struct mutex lb_mutex; /* serializes concurrent test operations */ + struct completion comp; + atomic_t tres_pending; /* DL callbacks still outstanding */ + const char *result; + u32 num_tre; + u32 tre_size; +}; + +static ssize_t tre_size_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct mhi_loopback *loopback =3D dev_get_drvdata(dev); + + return sysfs_emit(buf, "%u\n", loopback->tre_size); +} + +static ssize_t tre_size_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct mhi_loopback *loopback =3D dev_get_drvdata(dev); + u32 val; + + if (kstrtou32(buf, 0, &val)) + return -EINVAL; + + if (val =3D=3D 0 || val > MHI_LOOPBACK_MAX_TRE_SIZE) + return -EINVAL; + + guard(mutex)(&loopback->lb_mutex); + loopback->tre_size =3D val; + + return count; +} +static DEVICE_ATTR_RW(tre_size); + +static ssize_t max_tre_size_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return sysfs_emit(buf, "%u\n", MHI_LOOPBACK_MAX_TRE_SIZE); +} +static DEVICE_ATTR_RO(max_tre_size); + +static ssize_t num_tre_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct mhi_loopback *loopback =3D dev_get_drvdata(dev); + + return sysfs_emit(buf, "%u\n", loopback->num_tre); +} + +static ssize_t num_tre_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct mhi_loopback *loopback =3D dev_get_drvdata(dev); + u32 val; + int el_num; + + if (kstrtou32(buf, 0, &val)) + return -EINVAL; + + if (val =3D=3D 0) + return -EINVAL; + + guard(mutex)(&loopback->lb_mutex); + + el_num =3D mhi_get_free_desc_count(loopback->mdev, DMA_TO_DEVICE); + if (val > el_num) { + dev_err(dev, "num_tre (%u) exceeds ring capacity (%d)\n", val, el_num); + return -EINVAL; + } + + loopback->num_tre =3D val; + + return count; +} +static DEVICE_ATTR_RW(num_tre); + +static ssize_t start_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct mhi_loopback *loopback =3D dev_get_drvdata(dev); + void *send_buf =3D NULL, *recv_buf =3D NULL; + u32 total_size, tre_count, tre_size; + ssize_t ret; + int i; + + guard(mutex)(&loopback->lb_mutex); + + tre_size =3D loopback->tre_size; + tre_count =3D loopback->num_tre; + total_size =3D size_mul(tre_count, tre_size); + + recv_buf =3D kzalloc(total_size, GFP_KERNEL); + if (!recv_buf) + return -ENOMEM; + + send_buf =3D kzalloc(total_size, GFP_KERNEL); + if (!send_buf) { + ret =3D -ENOMEM; + goto free_buf; + } + + ret =3D mhi_prepare_for_transfer(loopback->mdev); + if (ret) { + dev_err(dev, "failed to prepare for transfers: %zd\n", ret); + goto free_buf; + } + + get_random_bytes(send_buf, total_size); + + /* Arm completion before queuing recv TREs to avoid losing an early callb= ack */ + atomic_set(&loopback->tres_pending, tre_count); + reinit_completion(&loopback->comp); + + for (i =3D 0; i < tre_count; i++) { + ret =3D mhi_queue_buf(loopback->mdev, DMA_FROM_DEVICE, + recv_buf + (i * tre_size), tre_size, MHI_EOT); + if (ret) { + dev_err(dev, "Unable to queue read TRE %d: %zd\n", i, ret); + loopback->result =3D "fail"; + if (atomic_sub_and_test(tre_count - i, &loopback->tres_pending)) + complete(&loopback->comp); + goto out; + } + } + + for (i =3D 0; i < tre_count - 1; i++) { + ret =3D mhi_queue_buf(loopback->mdev, DMA_TO_DEVICE, + send_buf + (i * tre_size), tre_size, MHI_CHAIN); + if (ret) { + dev_err(dev, "Unable to queue send TRE %d: %zd\n", i, ret); + loopback->result =3D "fail"; + goto out; + } + } + + ret =3D mhi_queue_buf(loopback->mdev, DMA_TO_DEVICE, + send_buf + (i * tre_size), tre_size, MHI_EOT); + if (ret) { + dev_err(dev, "Unable to queue final TRE: %zd\n", ret); + loopback->result =3D "fail"; + goto out; + } + + if (!wait_for_completion_timeout(&loopback->comp, + msecs_to_jiffies(MHI_LOOPBACK_TIMEOUT_MS))) { + dev_err(dev, "Loopback test timed out\n"); + loopback->result =3D "fail"; + ret =3D -ETIMEDOUT; + goto out; + } + + if (memcmp(send_buf, recv_buf, total_size)) { + dev_err(dev, "Loopback data mismatch\n"); + loopback->result =3D "fail"; + ret =3D -EIO; + goto out; + } + + loopback->result =3D "pass"; + ret =3D count; + +out: + mhi_unprepare_from_transfer(loopback->mdev); +free_buf: + kfree(send_buf); + kfree(recv_buf); + return ret; +} +static DEVICE_ATTR_WO(start); + +static ssize_t status_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct mhi_loopback *loopback =3D dev_get_drvdata(dev); + + guard(mutex)(&loopback->lb_mutex); + + return sysfs_emit(buf, "%s\n", loopback->result); +} +static DEVICE_ATTR_RO(status); + +static void mhi_loopback_dl_callback(struct mhi_device *mhi_dev, + struct mhi_result *mhi_res) +{ + struct mhi_loopback *loopback =3D dev_get_drvdata(&mhi_dev->dev); + + if (!loopback) + return; + + if (mhi_res->transaction_status && mhi_res->transaction_status !=3D -ENOT= CONN) + dev_err(&mhi_dev->dev, "DL callback error: status %d\n", + mhi_res->transaction_status); + + if (atomic_dec_and_test(&loopback->tres_pending)) + complete(&loopback->comp); +} + +static void mhi_loopback_ul_callback(struct mhi_device *mhi_dev, + struct mhi_result *mhi_res) +{ +} + +static struct attribute *mhi_loopback_attrs[] =3D { + &dev_attr_tre_size.attr, + &dev_attr_max_tre_size.attr, + &dev_attr_num_tre.attr, + &dev_attr_start.attr, + &dev_attr_status.attr, + NULL, +}; + +static const struct attribute_group mhi_loopback_group =3D { + .attrs =3D mhi_loopback_attrs, +}; + +static int mhi_loopback_probe(struct mhi_device *mhi_dev, + const struct mhi_device_id *id) +{ + struct mhi_loopback *loopback; + int rc; + + loopback =3D devm_kzalloc(&mhi_dev->dev, sizeof(*loopback), GFP_KERNEL); + if (!loopback) + return -ENOMEM; + + loopback->mdev =3D mhi_dev; + loopback->tre_size =3D MHI_LOOPBACK_DEFAULT_TRE_SIZE; + loopback->num_tre =3D MHI_LOOPBACK_DEFAULT_NUM_TRE; + loopback->result =3D "not started"; + + mutex_init(&loopback->lb_mutex); + init_completion(&loopback->comp); + + dev_set_drvdata(&mhi_dev->dev, loopback); + + rc =3D devm_device_add_group(&mhi_dev->dev, &mhi_loopback_group); + if (rc) + dev_err(&mhi_dev->dev, "failed to create sysfs attributes\n"); + + return rc; +} + +static void mhi_loopback_remove(struct mhi_device *mhi_dev) +{ + struct mhi_loopback *loopback =3D dev_get_drvdata(&mhi_dev->dev); + + complete(&loopback->comp); + + mutex_lock(&loopback->lb_mutex); + mutex_unlock(&loopback->lb_mutex); + + dev_set_drvdata(&mhi_dev->dev, NULL); +} + +static const struct mhi_device_id mhi_loopback_id_table[] =3D { + { .chan =3D "LOOPBACK"}, + {} +}; +MODULE_DEVICE_TABLE(mhi, mhi_loopback_id_table); + +static struct mhi_driver mhi_loopback_driver =3D { + .probe =3D mhi_loopback_probe, + .remove =3D mhi_loopback_remove, + .dl_xfer_cb =3D mhi_loopback_dl_callback, + .ul_xfer_cb =3D mhi_loopback_ul_callback, + .id_table =3D mhi_loopback_id_table, + .driver =3D { + .name =3D "mhi_loopback", + }, +}; + +module_mhi_driver(mhi_loopback_driver); + +MODULE_AUTHOR("Krishna Chaitanya Chundru "); +MODULE_AUTHOR("Sumit Kumar "); +MODULE_DESCRIPTION("MHI Host Loopback Driver"); +MODULE_LICENSE("GPL"); --=20 2.34.1 From nobody Sun Jun 21 21:48:28 2026 Received: from mx0b-0031df01.pphosted.com (mx0b-0031df01.pphosted.com [205.220.180.131]) (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 1542E33ADB3 for ; Wed, 10 Jun 2026 05:52:52 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=205.220.180.131 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1781070774; cv=none; b=Z0TyHU1hPEVDOdpGMyVI6LN8nbCjlZgPQ3jfmQo+V1zK+kS+Y4tQhFATJEW7eWnyI/arPSinVeJjK6otjBlJpt4pTD3pPWqFQqfoMvSODkkZ/2V5eZi9dcUhqqBQ47wtCQ26kjTso8JfOlp4HrpGmsRUSvjXreVPOpxsPs7iQ9w= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1781070774; c=relaxed/simple; bh=kPiK4VVYK2YYSSKt+UOoRg5CfNLvCgE5KlbH1vf/nME=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=ZMys4oNfXT3UkQ+aPIBWRUIWLrvgbQgWxqFCA5+2HWIX29UpzMJaLmBfj9SQ9AZolrEDYD8uwH+xQ1uPWm117MOe9FXdTEq16WwxsdWHZcEtHDaGFvNpPD07yYIP2gsLydXW0MxJiQ9PkSwzGv5IsWPNWRMuKGeUx6Ty6P+OluY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=oss.qualcomm.com; spf=pass smtp.mailfrom=oss.qualcomm.com; dkim=pass (2048-bit key) header.d=qualcomm.com header.i=@qualcomm.com header.b=jpDXfsIT; dkim=pass (2048-bit key) header.d=oss.qualcomm.com header.i=@oss.qualcomm.com header.b=Eklz2DOQ; arc=none smtp.client-ip=205.220.180.131 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=oss.qualcomm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=oss.qualcomm.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=qualcomm.com header.i=@qualcomm.com header.b="jpDXfsIT"; dkim=pass (2048-bit key) header.d=oss.qualcomm.com header.i=@oss.qualcomm.com header.b="Eklz2DOQ" Received: from pps.filterd (m0279872.ppops.net [127.0.0.1]) by mx0a-0031df01.pphosted.com (8.18.1.11/8.18.1.11) with ESMTP id 65A2eeVI240975 for ; Wed, 10 Jun 2026 05:52:52 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=qualcomm.com; h= cc:content-transfer-encoding:content-type:date:from:in-reply-to :message-id:mime-version:references:subject:to; s=qcppdkim1; bh= avk5meTGBcIz3G48y/NS8SFzaal/HS1a4+vUZxSJN6o=; b=jpDXfsIT4AT4ka9V kFpZtT7578UkocoomF56qut2haoZtqeJoPeXeKJcyhW8LXhspVLysomeYybXw0Gt zhMYWTgeWZ3B0stIFdOtQTjA1CzFZLA0XZTnL/yMSVeQHkF8HNgO13GS/PqRsHpX dIPb33a+v3SXukEuUCjJUSWs+r1cU8cns6cvkXNm1Xz0lfiSGMy3bf0yRX2tAv33 90JglukacCflDwjlcY5GFWhRc1L6EUc2PASloykGTI8+R90DNB7g6tJFyvjk48hq UnA6wJ79hxjXcdDQEEq37cPEdBHOY9YVOLbDdY+hhnynzMS1Y20RuvemP6l8mnkI xXKKBw== Received: from mail-pl1-f199.google.com (mail-pl1-f199.google.com [209.85.214.199]) by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 4epukesev6-1 (version=TLSv1.3 cipher=TLS_AES_128_GCM_SHA256 bits=128 verify=NOT) for ; Wed, 10 Jun 2026 05:52:52 +0000 (GMT) Received: by mail-pl1-f199.google.com with SMTP id d9443c01a7336-2c0c20f7581so67690215ad.0 for ; Tue, 09 Jun 2026 22:52:51 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=oss.qualcomm.com; s=google; t=1781070771; x=1781675571; darn=vger.kernel.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:from:to:cc:subject:date:message-id :reply-to; bh=avk5meTGBcIz3G48y/NS8SFzaal/HS1a4+vUZxSJN6o=; b=Eklz2DOQ97+Yv46xlzGxrD7X0QoW+MwQ3+kjyjobDb/gzLiaFlhUJB6sGd8ulYc6/x dfBS65N3tuaNi8QSWK0vETDNZpblfPT86xyTww/eB/QvA9Hn1x5Au0nvqOsJDyIPTP/D oQUPRaBkINfWJ8po3rHMX4XwqC1IXrD23W/EwBIGxB7rrmI1Ksrp+3PxgGsv/Wbyiwzt z8g9qJNRYCYaHjbgNaSNA+/Frv0aZw4f9BsMzjDYfrLxsHIzl7feMZECtfpt8E0Zmoop lLgGC7GPqL4Zo5ocKUe82MdyJS3M3LMhPgNxrpd0GCOhwbguSmSGvczjqw9+/PDN2wkI t+gA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1781070771; x=1781675571; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:x-gm-gg:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to; bh=avk5meTGBcIz3G48y/NS8SFzaal/HS1a4+vUZxSJN6o=; b=RE0C8v1WTLTv5aGKTeSmXCogiCYYLgQsTvzlvPgYhIuj8QgnoVSUmf5UyR7Ilk9zzp LHjfe91xRxhu6VmixsTfNiENGNPecwyvEh5IVCOnTzlkkHdMCCzgQuaS3k4iGCMirBYA ZrqqiNLfUCTOITbcb6nIAH8c/dgtLhzU88Sl2G/p8t6GxX+WqypY7RcHqkHtGNDMb8K7 M1Q72i/dKVSxGBvICWOb3MuVAiflkOVKEF/uBmT/VDQWgjo9zyyBv2NobeyPX47w2mqx bvnOAu5gkwfunbYMh/VEHiTx5CwvjKnNBuMzqo6fXo/UxQumZ9Na72lbjdPwZnFGdm9i 5ITg== X-Forwarded-Encrypted: i=1; AFNElJ/XvJfQZYNArwwRSC19J4lyc/pZK5kEFssP56jUCxPqpU4v33VVvV3Vc1C7H71+W5kFMx8t7iY7jlHHOzo=@vger.kernel.org X-Gm-Message-State: AOJu0YyOiugcDmM8TxhIRtkW43IibBOM7cZOGyKn6A7bjfhJ93DEGgv/ qFJSqCVHyIQRinsUeR6jZ3QnowSPxv8BwuNsIroVl8iyfOoeBH0JhinogaeXCr3lPMKa3tP2os7 seqUzQNNi4Ri1kEBBw1XQw14waP+GGhNJ1aTl7SgcU5Al2KrXZ9RyLLhLiwEcBviKhrg= X-Gm-Gg: Acq92OFgB3lkKkA3UPFvx5DrORha8YzRvtrI4LwN9p78yLaVHAv19a9xbjqkLkqyIZv qmr6jGxtbu36eJ9zgkeP9oi4q3He+5dQzijR3TpSAomozPi0wxJZBAa0p4mpdo67gfg8VxMKdVy wLRt3lH/Zsli7/dz7rYOyPXvDiSgU9t9EkqANdGFL1fHiQZFX7pgqWAuuj3I0/7WR5jmjL+p1/x 7TtfcAYF5wACgTgKLjyjeBBOzs3V47RmovLMQD5DEuCmf+7F23l91YeRLxMm+Zem7iP3iymdNUu JvRTsQN9R9xq38swn0nyEs0Bf2tGyHTD5y1LjgpaQ0ZWqh+QYzbWf+uo2yBXxVMtQdu9ZeJmlki MPSCQt8IanzHzu5hWKlnm9s5NMxl9/+jOND2Kf36BqYdHOlEDyCruLWBaPg== X-Received: by 2002:a17:902:ffce:b0:2c0:a746:7aff with SMTP id d9443c01a7336-2c1e80ebb9amr268984255ad.24.1781070770785; Tue, 09 Jun 2026 22:52:50 -0700 (PDT) X-Received: by 2002:a17:902:ffce:b0:2c0:a746:7aff with SMTP id d9443c01a7336-2c1e80ebb9amr268983905ad.24.1781070770232; Tue, 09 Jun 2026 22:52:50 -0700 (PDT) Received: from hu-sumk-hyd.qualcomm.com ([202.46.23.25]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-2c24edc8acasm108601105ad.45.2026.06.09.22.52.48 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 09 Jun 2026 22:52:49 -0700 (PDT) From: Sumit Kumar Date: Wed, 10 Jun 2026 11:22:26 +0530 Subject: [PATCH v3 2/3] bus: mhi: ep: Add mhi_ep_queue_buf() API for raw buffer queuing Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260610-loopback_mhi-v3-2-a733c0cef61a@oss.qualcomm.com> References: <20260610-loopback_mhi-v3-0-a733c0cef61a@oss.qualcomm.com> In-Reply-To: <20260610-loopback_mhi-v3-0-a733c0cef61a@oss.qualcomm.com> To: Manivannan Sadhasivam Cc: mhi@lists.linux.dev, linux-arm-msm@vger.kernel.org, linux-kernel@vger.kernel.org, Sumit Kumar X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=ed25519-sha256; t=1781070762; l=4302; i=sumit.kumar@oss.qualcomm.com; s=20250409; h=from:subject:message-id; bh=kPiK4VVYK2YYSSKt+UOoRg5CfNLvCgE5KlbH1vf/nME=; b=q4wkcXgb9kSyURpLBh9O/mKjiY/e3Q45Mu4AC/46kfOxEMBEgeGRBEwxDgEYIfi4SctX4pwcR D7bJIgV7+RWC93s7so8eWsurMOAJUZhs1AD3sJj9oOuUYon+1d0ryER X-Developer-Key: i=sumit.kumar@oss.qualcomm.com; a=ed25519; pk=3cys6srXqLACgA68n7n7KjDeM9JiMK1w6VxzMxr0dnM= X-Proofpoint-Spam-Details-Enc: AW1haW4tMjYwNjEwMDA1MiBTYWx0ZWRfX6YEzEFeOQnd+ WvvKMxKIfCIVOqCot7waPfPMJh3KUkMZw9fVLAesXUnxWhFGARqY1ns36xYbAisM15JlRRCKYGI OKweDONxkhnhHdGV9bM0x0FkmSA0/NwBNbjEOygBcJhm9slRpO0WsJmvQLrn35cew1ejmy+9GMl yGRFxHYx28wKQAZWP92JS+GDXYSWVlbxp1nOiU54LPulu7zGHt1iCAQVzGJXgZese6WJpURACPz iXuV7nY1fwAQbSYGqTJITIdB4D1jBabPbt0hkydMl71ruWFKobCPA+2RPncmnBRIu1Ka/pRUb2O S6ngzp6/yE09iUKhr/HT7NoW5AxLrY/uCVK1Jz6Nfb4x0Mo0bpnP6sMnMWEIP3GXZW4hpkKfg6r VU8SR+Vfb5GmfWSUHUPPE0yNhWDY0um6/s8BNWyzr1MY6z1aYYO5lNsdNUzZn450TfIGlDhGbU7 P7QDj62yNOi8vYiOSJw== X-Proofpoint-ORIG-GUID: 1HHTVKvlVAaTHHZGc6eM7q5HMDQhC2aP X-Proofpoint-GUID: 1HHTVKvlVAaTHHZGc6eM7q5HMDQhC2aP X-Authority-Analysis: v=2.4 cv=DNG/JSNb c=1 sm=1 tr=0 ts=6a28fbb4 cx=c_pps a=JL+w9abYAAE89/QcEU+0QA==:117 a=ZePRamnt/+rB5gQjfz0u9A==:17 a=IkcTkHD0fZMA:10 a=FelO9ux0wxsA:10 a=s4-Qcg_JpJYA:10 a=VkNPw1HP01LnGYTKEx00:22 a=u7WPNUs3qKkmUXheDGA7:22 a=yx91gb_oNiZeI1HMLzn7:22 a=EUspDBNiAAAA:8 a=27Ti7_ZD70JoqEhemiIA:9 a=QEXdDO2ut3YA:10 a=324X-CrmTo6CU4MGRt3R:22 X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1143,Hydra:6.1.125,FMLib:17.12.100.49 definitions=2026-06-10_01,2026-06-09_02,2025-10-01_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 lowpriorityscore=0 malwarescore=0 spamscore=0 impostorscore=0 priorityscore=1501 adultscore=0 phishscore=0 clxscore=1015 suspectscore=0 bulkscore=0 classifier=typeunknown authscore=0 authtc= authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.22.0-2605210000 definitions=main-2606100052 Some MHI endpoint clients do not use socket buffers and need a way to queue raw buffers for DL transfers. Add mhi_ep_queue_buf() to support this use case. Refactor mhi_ep_queue_skb() to delegate to a new internal mhi_ep_queue() helper shared by both APIs, and rename mhi_ep_skb_completion() to mhi_ep_buf_completion() to reflect its broader use. Signed-off-by: Sumit Kumar --- drivers/bus/mhi/ep/main.c | 27 +++++++++++++++++++-------- include/linux/mhi_ep.h | 15 +++++++++++++++ 2 files changed, 34 insertions(+), 8 deletions(-) diff --git a/drivers/bus/mhi/ep/main.c b/drivers/bus/mhi/ep/main.c index b3eafcf2a2c50d95e3efd3afb27038ecf55552a5..6c4c5ca473b821f9c2abe11cfe5= 043ec4c5545f4 100644 --- a/drivers/bus/mhi/ep/main.c +++ b/drivers/bus/mhi/ep/main.c @@ -516,7 +516,7 @@ static int mhi_ep_process_ch_ring(struct mhi_ep_ring *r= ing) return 0; } =20 -static void mhi_ep_skb_completion(struct mhi_ep_buf_info *buf_info) +static void mhi_ep_buf_completion(struct mhi_ep_buf_info *buf_info) { struct mhi_ep_device *mhi_dev =3D buf_info->mhi_dev; struct mhi_ep_cntrl *mhi_cntrl =3D mhi_dev->mhi_cntrl; @@ -544,9 +544,9 @@ static void mhi_ep_skb_completion(struct mhi_ep_buf_inf= o *buf_info) =20 mhi_ep_ring_inc_index(ring); } - /* TODO: Handle partially formed TDs */ -int mhi_ep_queue_skb(struct mhi_ep_device *mhi_dev, struct sk_buff *skb) +static int mhi_ep_queue(struct mhi_ep_device *mhi_dev, void *buf, size_t l= en, + void *cb_buf) { struct mhi_ep_cntrl *mhi_cntrl =3D mhi_dev->mhi_cntrl; struct mhi_ep_chan *mhi_chan =3D mhi_dev->dl_chan; @@ -559,7 +559,7 @@ int mhi_ep_queue_skb(struct mhi_ep_device *mhi_dev, str= uct sk_buff *skb) u32 tre_len; int ret; =20 - buf_left =3D skb->len; + buf_left =3D len; ring =3D &mhi_cntrl->mhi_chan[mhi_chan->chan].ring; =20 mutex_lock(&mhi_chan->lock); @@ -582,13 +582,13 @@ int mhi_ep_queue_skb(struct mhi_ep_device *mhi_dev, s= truct sk_buff *skb) tre_len =3D MHI_TRE_DATA_GET_LEN(el); =20 tr_len =3D min(buf_left, tre_len); - read_offset =3D skb->len - buf_left; + read_offset =3D len - buf_left; =20 - buf_info.dev_addr =3D skb->data + read_offset; + buf_info.dev_addr =3D buf + read_offset; buf_info.host_addr =3D MHI_TRE_DATA_GET_PTR(el); buf_info.size =3D tr_len; - buf_info.cb =3D mhi_ep_skb_completion; - buf_info.cb_buf =3D skb; + buf_info.cb =3D mhi_ep_buf_completion; + buf_info.cb_buf =3D cb_buf; buf_info.mhi_dev =3D mhi_dev; =20 /* @@ -627,8 +627,19 @@ int mhi_ep_queue_skb(struct mhi_ep_device *mhi_dev, st= ruct sk_buff *skb) =20 return ret; } + +int mhi_ep_queue_skb(struct mhi_ep_device *mhi_dev, struct sk_buff *skb) +{ + return mhi_ep_queue(mhi_dev, skb->data, skb->len, skb); +} EXPORT_SYMBOL_GPL(mhi_ep_queue_skb); =20 +int mhi_ep_queue_buf(struct mhi_ep_device *mhi_dev, void *buf, size_t len) +{ + return mhi_ep_queue(mhi_dev, buf, len, buf); +} +EXPORT_SYMBOL_GPL(mhi_ep_queue_buf); + static int mhi_ep_cache_host_cfg(struct mhi_ep_cntrl *mhi_cntrl) { size_t cmd_ctx_host_size, ch_ctx_host_size, ev_ctx_host_size; diff --git a/include/linux/mhi_ep.h b/include/linux/mhi_ep.h index 7b40fc8cbe77ab8419d167e89264b69a817b9fb1..59f796e56207aaf8be09edc9ba4= d1f59b665581f 100644 --- a/include/linux/mhi_ep.h +++ b/include/linux/mhi_ep.h @@ -302,4 +302,19 @@ bool mhi_ep_queue_is_empty(struct mhi_ep_device *mhi_d= ev, enum dma_data_directio */ int mhi_ep_queue_skb(struct mhi_ep_device *mhi_dev, struct sk_buff *skb); =20 +/** + * mhi_ep_queue_buf - Send buffer to host over MHI Endpoint + * @mhi_dev: Device associated with the DL channel + * @buf: Buffer to be queued. On success, ownership passes to the MHI stac= k; + * the caller must not free @buf until the DL transfer callback fires + * with result->buf_addr equal to @buf. On failure, the caller retai= ns + * ownership and must free @buf. + * Note: if @len spans multiple host DL TREs, the DL transfer callba= ck + * fires once per TRE, each time with result->buf_addr equal to @buf. + * @len: Size of the buffer + * + * Return: 0 if the buffer has been sent successfully, a negative error co= de otherwise. + */ +int mhi_ep_queue_buf(struct mhi_ep_device *mhi_dev, void *buf, size_t len); + #endif --=20 2.34.1 From nobody Sun Jun 21 21:48:28 2026 Received: from mx0a-0031df01.pphosted.com (mx0a-0031df01.pphosted.com [205.220.168.131]) (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 ED7D23438A2 for ; Wed, 10 Jun 2026 05:52:55 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=205.220.168.131 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1781070777; cv=none; b=DMUBz+c7kbZDNHyfFbthI7d8Svjewrk0wcx1ht2k8QUMg4hBMW2j+nDbLOtkwKgJWOUGQ3fiB2xtOWY8Dsfgy8SsIZc5Sky4zLNGg+5VO6DgI0pFMkDwCIJN8QknoFAlKxiFxgwT3bDQc6fkWIrwboz/GXL+HonzX8VoUvradaM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1781070777; c=relaxed/simple; bh=SCb5JdpwwyhuPYxgnCpTsUjM/m5K7yjby9KZ/2wyEu4=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=YDRlMBxeJdFYDq1JPVrJQMTEUTvhS+zXvTaKdIgbit4a7Uc8ou/vKkQVoCYCnZvMwhitO9g83aaez66wnr+18UK1nkyEU/NOulq4nyaNW34dmSkJWNYwvwAOod5I6gFIKX5Plyds4ZIryY/ZvDRdYD9vF6s0JyiKTWWVYmtu9oE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=oss.qualcomm.com; spf=pass smtp.mailfrom=oss.qualcomm.com; dkim=pass (2048-bit key) header.d=qualcomm.com header.i=@qualcomm.com header.b=l9+GZBpd; dkim=pass (2048-bit key) header.d=oss.qualcomm.com header.i=@oss.qualcomm.com header.b=RzgLYtxx; arc=none smtp.client-ip=205.220.168.131 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=oss.qualcomm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=oss.qualcomm.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=qualcomm.com header.i=@qualcomm.com header.b="l9+GZBpd"; dkim=pass (2048-bit key) header.d=oss.qualcomm.com header.i=@oss.qualcomm.com header.b="RzgLYtxx" Received: from pps.filterd (m0279865.ppops.net [127.0.0.1]) by mx0a-0031df01.pphosted.com (8.18.1.11/8.18.1.11) with ESMTP id 65A2eibT2481678 for ; Wed, 10 Jun 2026 05:52:55 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=qualcomm.com; h= cc:content-transfer-encoding:content-type:date:from:in-reply-to :message-id:mime-version:references:subject:to; s=qcppdkim1; bh= 0RaNe1EFZcr7pe+M0opguIhKZAP/A4Gj9NbfkvE3bNQ=; b=l9+GZBpdx/IMyHBt oFftq8PD5DcOfIhMxdf1Z7e5J4ZlvqG4xwUB8L2eqq3G0+ecexO9MZX36G7aaXrM JZVeRc9EWCR9tIgGs3rDrpyHZAkP/ypEaclwXn+gkQIS23aFzQBMtu5tg87CTiNA aqPQgLB8wSFpbFI+XBxbXGP+e4OzE5+NhZDpkqjr1LGaGYqh0ZBkVye7RXILmd87 /ET3kQ7JoLfWhZG0IoGZbDTTmwFdY5sbO1/vA/QCN6ZAMY0NU6+U+gcH1i9SIrzy 25mJTbIspTi/UUiGI01eSSU0gQIoZSDjKzQsmBCGyO8iOl2dIvfUGYt7u7KK2kll X7lxvQ== Received: from mail-pl1-f199.google.com (mail-pl1-f199.google.com [209.85.214.199]) by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 4epwnerwvf-1 (version=TLSv1.3 cipher=TLS_AES_128_GCM_SHA256 bits=128 verify=NOT) for ; Wed, 10 Jun 2026 05:52:55 +0000 (GMT) Received: by mail-pl1-f199.google.com with SMTP id d9443c01a7336-2bf32259e0eso84177755ad.0 for ; Tue, 09 Jun 2026 22:52:55 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=oss.qualcomm.com; s=google; t=1781070774; x=1781675574; darn=vger.kernel.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:from:to:cc:subject:date:message-id :reply-to; bh=0RaNe1EFZcr7pe+M0opguIhKZAP/A4Gj9NbfkvE3bNQ=; b=RzgLYtxx0gmymb4D0hjM0poH95J8mYK0s7rxuI7YDbpQg+CSFYiM1QA19DyM96JbtN 7XTT1XV7JOhzjBCPH7d2T/tIeP4uCNEnvTi4j6Dv+FUU3yK/ez7Q0wQYWSKzyQwzg5vn JJ1/5k1vB8aplcXsVES0V5Ya4jFIDwZOoeSEqnPSrmfRqW8jR6ptdmTdbVaLAlulWLIR GPWZu3kehiiT4unBQo8o3lWh2arYpj+3lM+7U6vZWcNRuO6VCS7t2HM9EvEvBy9hiS0u aIkwcotGuCCfcj7BaxlVIcg7hk3cwzxwYqr/TSq+GYqYm2MPwwEg+vuFjT9PSg4N7tQb cT8g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1781070774; x=1781675574; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:x-gm-gg:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to; bh=0RaNe1EFZcr7pe+M0opguIhKZAP/A4Gj9NbfkvE3bNQ=; b=Os5/PZje6OM4TPYiIBmVp4TdndwMCpsefeNFalO+cM5kX/u0V63WHC+0+eHJ6EhZsD 7uI/MrV0vmEA99zLYuihNfLG+dCBJDw6ww8uyqpiopN3sfCKvdeYJHGFVm3HfBSV9O1/ kVDrM7U9xHbSBBbYDJ0dajdAleGuSKP4HJXjSoMc7CbgIbl+byoPb58Neq6hOQZ9aZmA glIUJ6HljaFOE+1BAZaSosKLLn3yRRfPb11KNte4KANpyY1KKQ2NMLrqglyMEEJu2w15 zRCIVNStpyqbwkJKwEFjpitRViNq/1CxSYmFYQN8VhthUhIw/jp4kkNSmNXxe/CxBtkN 7O7g== X-Forwarded-Encrypted: i=1; AFNElJ9PnhPb+u3TFEeh1lnJk80PWyGnPnU3bvyJCspzYuPQnKhcluMOt+BplFWKB79JxZQMgQ1Z5pl8WjpPYVc=@vger.kernel.org X-Gm-Message-State: AOJu0YygKWyZ/GJXBz1IQm1OfnC4xX0N/dc2D8zxQXBQhe7rP8/qP9/G swA2K52ytsK7JAUleAEcHwzlElNVc5a1eFC1kLPac5YClKpbHOqEo/X8S0bmVe0oAtShKZHE6xr oN4DN0XRI++3wir0JjRGbI2WjQJ7dJoix4gE7vFV6toFGr/7Ar7SYZsN9oiIyc2imTn4= X-Gm-Gg: Acq92OF0SC+rbU4vnhOA4dRZHpNBCiVJzI/Jj180n+gwMzcMXg5gxs/F9JrD66Lz9l2 S55jKhHvl38m88bXaMIFrTgsQTJ3CxYRPsPd9sR/y7bs+slUiCl6x+B8DqB257fl4dXy1AU2XNw wGOswnrxvFY44iVdM22z+3qYTvDHIEDDvTZfQFbX1qHETA6udvrHLqmuLThM0yg6XzerNSws420 45i+LmSf00PyJ8newL4Z+6IvZH32M6wKeTZYRKZykozEiH/3r/nn+0d79Xm5ylhGdQ5dtt7gYU3 X4YmIu8gk8W9RaScTWXDh4lmabkNTN9FDIrl/lSgumj/++xcfszN7bJd//cQxFzLV/AxQTQl+4r TuOq8y0dIRhK/7ocOQv7W9/PMhEF1G8S800t19G0Mpb6/wXgMZcWwzKmUdQ== X-Received: by 2002:a17:903:3c48:b0:2c0:eee2:fc40 with SMTP id d9443c01a7336-2c1e80cede0mr273611145ad.3.1781070774458; Tue, 09 Jun 2026 22:52:54 -0700 (PDT) X-Received: by 2002:a17:903:3c48:b0:2c0:eee2:fc40 with SMTP id d9443c01a7336-2c1e80cede0mr273610625ad.3.1781070773718; Tue, 09 Jun 2026 22:52:53 -0700 (PDT) Received: from hu-sumk-hyd.qualcomm.com ([202.46.23.25]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-2c24edc8acasm108601105ad.45.2026.06.09.22.52.50 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 09 Jun 2026 22:52:52 -0700 (PDT) From: Sumit Kumar Date: Wed, 10 Jun 2026 11:22:27 +0530 Subject: [PATCH v3 3/3] bus: mhi: ep: clients: Add loopback driver for data path testing Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260610-loopback_mhi-v3-3-a733c0cef61a@oss.qualcomm.com> References: <20260610-loopback_mhi-v3-0-a733c0cef61a@oss.qualcomm.com> In-Reply-To: <20260610-loopback_mhi-v3-0-a733c0cef61a@oss.qualcomm.com> To: Manivannan Sadhasivam Cc: mhi@lists.linux.dev, linux-arm-msm@vger.kernel.org, linux-kernel@vger.kernel.org, Sumit Kumar , Krishna Chaitanya Chundru X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=ed25519-sha256; t=1781070762; l=7042; i=sumit.kumar@oss.qualcomm.com; s=20250409; h=from:subject:message-id; bh=SCb5JdpwwyhuPYxgnCpTsUjM/m5K7yjby9KZ/2wyEu4=; b=uHKlPIIHk3sZ4Hmksb0hNEK7d4tgAZm1RgXWtX6c2UdT7jJUFFaUDZFI1Q2z5NWZYDHVbSfGt UtwoUNsfsgiCum+DK0gpzhlckCvp6o1CGkxhrIezi+7PqQDrZBfg7/m X-Developer-Key: i=sumit.kumar@oss.qualcomm.com; a=ed25519; pk=3cys6srXqLACgA68n7n7KjDeM9JiMK1w6VxzMxr0dnM= X-Proofpoint-GUID: Or8EC-BejvTSJDMVIy4tXuny2405o5tl X-Authority-Analysis: v=2.4 cv=ebYNubEH c=1 sm=1 tr=0 ts=6a28fbb7 cx=c_pps a=JL+w9abYAAE89/QcEU+0QA==:117 a=ZePRamnt/+rB5gQjfz0u9A==:17 a=IkcTkHD0fZMA:10 a=FelO9ux0wxsA:10 a=s4-Qcg_JpJYA:10 a=VkNPw1HP01LnGYTKEx00:22 a=u7WPNUs3qKkmUXheDGA7:22 a=Um2Pa8k9VHT-vaBCBUpS:22 a=EUspDBNiAAAA:8 a=F9PWhn0UeK7EsyOwsFYA:9 a=QEXdDO2ut3YA:10 a=324X-CrmTo6CU4MGRt3R:22 X-Proofpoint-ORIG-GUID: Or8EC-BejvTSJDMVIy4tXuny2405o5tl X-Proofpoint-Spam-Details-Enc: AW1haW4tMjYwNjEwMDA1MiBTYWx0ZWRfX72ufmbkmBDSO RdXHnHglYA6g7UvUXL/cW4ms4S/5QicD36IgyppQFBpVM+ZQeBw5qoDLJ9KsuSwv7i/G7rImWAY sUq0HEJ3GiTMV2Qf26m46QbJLkqccvC7tz0Sl3jhPG4nz2k1ZrIZNjAAbB/j2lctUekXdEhFOzD pOlQlS3pSC4rYow/JhujOYsqOuQia/fz5a4bydYTduHZJMWSf6Rru4S9qTnCi921+HHAAnmjbam 4gOHNaPNoFGQJFV0vfHXsEPITI2o1u1x1dNTUTIQhZX6E7eM14WWnkZGEeUZAhLPTMO1FIQ7czu yDLDfmB//H6/LiLSz9RJ7t3ITR6hBifngAmNk5bjcSAV98hxZKnF/0V6+J09YiAcbJ4VKHV8odx +E/DiOuaFuTwbLNvLTyu/hZAVrlhcIiSgU5eU2dba4FuID9ceiaXdM4n+J1afXX4fzXRaRn8UD6 owt4ga8tKosMznQwa9Q== X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1143,Hydra:6.1.125,FMLib:17.12.100.49 definitions=2026-06-10_01,2026-06-09_02,2025-10-01_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 malwarescore=0 impostorscore=0 spamscore=0 bulkscore=0 clxscore=1015 suspectscore=0 phishscore=0 adultscore=0 lowpriorityscore=0 priorityscore=1501 classifier=typeunknown authscore=0 authtc= authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.22.0-2605210000 definitions=main-2606100052 When an MHI endpoint device runs Linux, there is no firmware to implement the LOOPBACK channel echo that real modem firmware provides. Without an endpoint-side driver, the host loopback test has no software echo partner and cannot exercise the full end-to-end MHI data path. Add an endpoint-side loopback driver that binds to the LOOPBACK channel and echoes received data back to the host. An ordered workqueue is used for asynchronous processing to preserve packet ordering. Together with the host-side loopback driver, this enables complete MHI data path validation for Linux-based endpoint devices. Co-developed-by: Krishna Chaitanya Chundru Signed-off-by: Krishna Chaitanya Chundru Signed-off-by: Sumit Kumar --- drivers/bus/mhi/ep/Kconfig | 2 + drivers/bus/mhi/ep/Makefile | 1 + drivers/bus/mhi/ep/clients/Kconfig | 16 +++++ drivers/bus/mhi/ep/clients/Makefile | 2 + drivers/bus/mhi/ep/clients/loopback.c | 122 ++++++++++++++++++++++++++++++= ++++ 5 files changed, 143 insertions(+) diff --git a/drivers/bus/mhi/ep/Kconfig b/drivers/bus/mhi/ep/Kconfig index 90ab3b040672e0f04181d4802e3062afcc7cf782..9edb81b39890e093a51138465a4= d7705767eafa5 100644 --- a/drivers/bus/mhi/ep/Kconfig +++ b/drivers/bus/mhi/ep/Kconfig @@ -8,3 +8,5 @@ config MHI_BUS_EP =20 MHI_BUS_EP implements the MHI protocol for the endpoint devices, such as SDX55 modem connected to the host machine over PCIe. + +source "drivers/bus/mhi/ep/clients/Kconfig" diff --git a/drivers/bus/mhi/ep/Makefile b/drivers/bus/mhi/ep/Makefile index aad85f180b707fb997fcb541837eda9bbbb67437..ab36ef2a40ab8174e5ddae44a3e= 6ccb8eb31168d 100644 --- a/drivers/bus/mhi/ep/Makefile +++ b/drivers/bus/mhi/ep/Makefile @@ -1,2 +1,3 @@ obj-$(CONFIG_MHI_BUS_EP) +=3D mhi_ep.o mhi_ep-y :=3D main.o mmio.o ring.o sm.o +obj-y +=3D clients/ diff --git a/drivers/bus/mhi/ep/clients/Kconfig b/drivers/bus/mhi/ep/client= s/Kconfig new file mode 100644 index 0000000000000000000000000000000000000000..4cf27184058ca2be020885b6f57= b4cc44b5054b6 --- /dev/null +++ b/drivers/bus/mhi/ep/clients/Kconfig @@ -0,0 +1,16 @@ +# SPDX-License-Identifier: GPL-2.0 + +config MHI_BUS_EP_LOOPBACK + tristate "MHI Endpoint LOOPBACK client driver" + depends on MHI_BUS_EP + help + MHI Endpoint LOOPBACK client driver that binds to the MHI LOOPBACK + channel as defined in the MHI specification. The LOOPBACK channel is + implemented by MHI-based endpoint devices (modems, WLAN) in the field, + where the endpoint firmware echoes back whatever the host sends. + + This driver receives data on the uplink channel and echoes it back on + the downlink channel for testing the MHI endpoint data path. + + To compile this driver as a module, choose M here. The module + will be called mhi_ep_loopback. diff --git a/drivers/bus/mhi/ep/clients/Makefile b/drivers/bus/mhi/ep/clien= ts/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..71dc91cc63b02592b177cf66db6= 090748c0653a6 --- /dev/null +++ b/drivers/bus/mhi/ep/clients/Makefile @@ -0,0 +1,2 @@ +obj-$(CONFIG_MHI_BUS_EP_LOOPBACK) +=3D mhi_ep_loopback.o +mhi_ep_loopback-y +=3D loopback.o diff --git a/drivers/bus/mhi/ep/clients/loopback.c b/drivers/bus/mhi/ep/cli= ents/loopback.c new file mode 100644 index 0000000000000000000000000000000000000000..f346ad9ffca9eb957680b1d259c= 9789e55cffae9 --- /dev/null +++ b/drivers/bus/mhi/ep/clients/loopback.c @@ -0,0 +1,122 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#include +#include +#include +#include + +struct mhi_ep_loopback { + struct workqueue_struct *loopback_wq; + struct mhi_ep_device *mdev; +}; + +struct mhi_ep_loopback_work { + struct mhi_ep_device *mdev; + struct work_struct work; + void *buf; + size_t len; +}; + +static void mhi_ep_loopback_work_handler(struct work_struct *work) +{ + struct mhi_ep_loopback_work *mhi_ep_lb_work =3D container_of(work, + struct mhi_ep_loopback_work, work); + int ret; + + ret =3D mhi_ep_queue_buf(mhi_ep_lb_work->mdev, mhi_ep_lb_work->buf, + mhi_ep_lb_work->len); + if (ret) { + dev_err(&mhi_ep_lb_work->mdev->dev, "Failed to send the packet\n"); + kfree(mhi_ep_lb_work->buf); + } + + kfree(mhi_ep_lb_work); +} + +static void mhi_ep_loopback_ul_callback(struct mhi_ep_device *mhi_dev, + struct mhi_result *mhi_res) +{ + struct mhi_ep_loopback *mhi_ep_lb =3D dev_get_drvdata(&mhi_dev->dev); + struct mhi_ep_loopback_work *mhi_ep_lb_work; + void *buf; + + if (!mhi_res->transaction_status) { + buf =3D kmemdup(mhi_res->buf_addr, mhi_res->bytes_xferd, GFP_KERNEL); + if (!buf) + return; + + mhi_ep_lb_work =3D kmalloc(sizeof(*mhi_ep_lb_work), GFP_KERNEL); + if (!mhi_ep_lb_work) { + kfree(buf); + return; + } + + INIT_WORK(&mhi_ep_lb_work->work, mhi_ep_loopback_work_handler); + mhi_ep_lb_work->mdev =3D mhi_dev; + mhi_ep_lb_work->buf =3D buf; + mhi_ep_lb_work->len =3D mhi_res->bytes_xferd; + + queue_work(mhi_ep_lb->loopback_wq, &mhi_ep_lb_work->work); + } +} + +static void mhi_ep_loopback_dl_callback(struct mhi_ep_device *mhi_dev, + struct mhi_result *mhi_res) +{ + kfree(mhi_res->buf_addr); +} + +static int mhi_ep_loopback_probe(struct mhi_ep_device *mhi_dev, const stru= ct mhi_device_id *id) +{ + struct mhi_ep_loopback *mhi_ep_lb; + + mhi_ep_lb =3D devm_kzalloc(&mhi_dev->dev, sizeof(*mhi_ep_lb), GFP_KERNEL); + if (!mhi_ep_lb) + return -ENOMEM; + + mhi_ep_lb->loopback_wq =3D alloc_ordered_workqueue("mhi_ep_loopback", WQ_= MEM_RECLAIM); + if (!mhi_ep_lb->loopback_wq) { + dev_err(&mhi_dev->dev, "Failed to create workqueue.\n"); + return -ENOMEM; + } + + mhi_ep_lb->mdev =3D mhi_dev; + dev_set_drvdata(&mhi_dev->dev, mhi_ep_lb); + + return 0; +} + +static void mhi_ep_loopback_remove(struct mhi_ep_device *mhi_dev) +{ + struct mhi_ep_loopback *mhi_ep_lb =3D dev_get_drvdata(&mhi_dev->dev); + + destroy_workqueue(mhi_ep_lb->loopback_wq); + dev_set_drvdata(&mhi_dev->dev, NULL); +} + +static const struct mhi_device_id mhi_ep_loopback_id_table[] =3D { + { .chan =3D "LOOPBACK"}, + {} +}; +MODULE_DEVICE_TABLE(mhi, mhi_ep_loopback_id_table); + +static struct mhi_ep_driver mhi_ep_loopback_driver =3D { + .probe =3D mhi_ep_loopback_probe, + .remove =3D mhi_ep_loopback_remove, + .dl_xfer_cb =3D mhi_ep_loopback_dl_callback, + .ul_xfer_cb =3D mhi_ep_loopback_ul_callback, + .id_table =3D mhi_ep_loopback_id_table, + .driver =3D { + .name =3D "mhi_ep_loopback", + }, +}; + +module_mhi_ep_driver(mhi_ep_loopback_driver); + +MODULE_AUTHOR("Krishna Chaitanya Chundru "); +MODULE_AUTHOR("Sumit Kumar "); +MODULE_DESCRIPTION("MHI Endpoint Loopback driver"); +MODULE_LICENSE("GPL"); --=20 2.34.1