From nobody Thu Oct 2 03:30:48 2025 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 C931330FC20 for ; Tue, 23 Sep 2025 06:37:53 +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=1758609475; cv=none; b=l14F8WUrN3rsgI1yMfN8DeLDYHv/lkbDQ72bkLDJc35+5e8Jr6w1iTtXUjNCZK8uVuNHleRRzc8JJRe52wkuKDCCwMVaiVr37VG/Ve8K78xavHQ/+qKGjVzh1UaY/IM6wKYk5LlgsAf8UsYuEfa1ElqKGT7srnj6rSW+9i3jieg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1758609475; c=relaxed/simple; bh=GyDV1zAPt6M4BAQbQYZppmlVchSBpKNe8e6ZOu3WccQ=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=hSyDjeY53ZOYNd5YvOWU5hyuRdOCLeJZ+NsNOaWg/tPvLacZTJlU9qVHomC7mxJSxpu7U/q1axHnqvVHNA+mJUUd/U/xpJCpxxI1MSJHOtsoTZAIYeQNQHC3m0sSnwV+kXraG7vcFRlImYjjCaEhE3X7Rsoqrp+9JG//QtUzGy8= 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=BcISzfLG; 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="BcISzfLG" Received: from pps.filterd (m0279865.ppops.net [127.0.0.1]) by mx0a-0031df01.pphosted.com (8.18.1.2/8.18.1.2) with ESMTP id 58N6Zl2O015787 for ; Tue, 23 Sep 2025 06:37:53 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= o115QF7cjdxwuELjPwNmUZnyAWH+5MdK8KNQcAv/DcM=; b=BcISzfLGDbLKwBU6 hH6AKDD02d5wIND0Wztt88Y8lO5R/n/JcQQsT/OiEMMRlDctejeMhL1vAX/rwsuP OlRLBopezym+btV/HSQCGTa427/wm5pZt7CxfS+ZxW+nY1JNIl+TYVzw+o3loToG bZeaK8qJfU3jijG6FqbT9HVwuHqWJLwpTeg3ltMxYV9uTR4gp4x0+JPfIjDjgckx 2T3zdQ9IvmpQx+RNc96k7lwTnF8dG9ubJ1FisR2EXNxywT99tCDmBHSGxGAww4HP CbCgBxK0O9ABZvmPPhQ9pKhbAQ+HEQLBow1My/h0vloeZ6jwyr9RBGIIyBqfkoOF jnIJjw== Received: from mail-pg1-f199.google.com (mail-pg1-f199.google.com [209.85.215.199]) by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 49bajesw28-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NOT) for ; Tue, 23 Sep 2025 06:37:52 +0000 (GMT) Received: by mail-pg1-f199.google.com with SMTP id 41be03b00d2f7-b4f87c691a7so8848147a12.3 for ; Mon, 22 Sep 2025 23:37:52 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1758609472; x=1759214272; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=o115QF7cjdxwuELjPwNmUZnyAWH+5MdK8KNQcAv/DcM=; b=UZpY6uhL/GeZuAxR7Fhr/xnpSNGPslH7U9wgFxrYjRo80fhebg6a4mZY+b1KNuJVDG 5Orjfm3mrF4QA7iKT7YRwJt0WBX+Lzmt/aXN9yvXOAN7uVIuRKayqBnC+LA2xIyFHvbD lCWf6z1/fpFPExI4Z/DdMe5qNM4YYrtTn1hk0n9NMk+1HK9+wmfsak2iAbYV0HVAf2ED e3STovJ86c/uk94tve0dbA53BLdvwO5LcDnfHB9rln0FmKefOuzEQN0Om9FBRNLUDpsx o3gS72uj+GpPOPpk1EwSDys5WLKfV2TJrpAcUi4iBdacJkvA2Bl9hOPorivATmnuPExV oxOg== X-Forwarded-Encrypted: i=1; AJvYcCUanVfnqeZRgLpK2rUWf8IT2L/7P+6GXflaXrhIAwoO2iH3oPaUL7wPxnFvBUIR5ksfgDGSEQXK4u6ZwDk=@vger.kernel.org X-Gm-Message-State: AOJu0YyhIh8Pta3kZEol4rs/v9BWIl9iNQs/5CgJ7f1B/5T6FTf7X3VR Ed/FQkZQSIkdhvWDw2htRHGfwTJg0Dmi6H/pJ+k6o62/y2l25BMByLT/qHZLKg3p70900sXu/8B DlVgGuYv4v6Yt7pNbn4sKz61oC43RI6mLD10JYVvcnI9E4v/MZbDDxNJqhc+wnc4EhvA= X-Gm-Gg: ASbGncvKO3o1duEIjcikX0FBwstOEEm3hvjA51giFcU9mYbJABc3i7o3mYFCx327d2R niOqhIa6ft4ADJ1G/WdbEDA0nE/gmMILYm5rEDvfHZ1ryCjLOc8ZAd7jXjXHFMk+q1Cnj7fe7y3 DsCYjfqSLkWbQbkh1gqiSxDt3q9gJZ8KTAlkpujgHy02/z+GWb/KA/MdY6BIAHnIXjhnGXSlbLI MOqAnW1OYakP57xMh49cRIOe1NfqpgM1Aa6VrNlDvZZyJgbWE0i4uoDEYh5//9bMGspQOvululj ZAwrSgCMk8D7Vt6ClmCZOB3WHMQhb3UND5htcid6m1UU6motIcZV7yufH/E4HOBxhA== X-Received: by 2002:a05:6a20:2447:b0:249:fd42:fa33 with SMTP id adf61e73a8af0-2cfd9803d79mr2198747637.4.1758609471613; Mon, 22 Sep 2025 23:37:51 -0700 (PDT) X-Google-Smtp-Source: AGHT+IEw9XUQ4o8BOkYVVVyLpzHXazWVe5TjkOk1T+RiSdOU2wEdtMpEJimpIfmsSeMMzuoB5pI0FA== X-Received: by 2002:a05:6a20:2447:b0:249:fd42:fa33 with SMTP id adf61e73a8af0-2cfd9803d79mr2198698637.4.1758609470707; Mon, 22 Sep 2025 23:37:50 -0700 (PDT) Received: from hu-sumk-hyd.qualcomm.com ([202.46.23.25]) by smtp.gmail.com with ESMTPSA id 41be03b00d2f7-b551905bb4csm10792840a12.29.2025.09.22.23.37.47 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 22 Sep 2025 23:37:50 -0700 (PDT) From: Sumit Kumar Date: Tue, 23 Sep 2025 12:07:41 +0530 Subject: [PATCH 1/2] bus: mhi: host: 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: <20250923-loopback_mhi-v1-1-8618f31f44aa@oss.qualcomm.com> References: <20250923-loopback_mhi-v1-0-8618f31f44aa@oss.qualcomm.com> In-Reply-To: <20250923-loopback_mhi-v1-0-8618f31f44aa@oss.qualcomm.com> To: Manivannan Sadhasivam Cc: Krishna Chaitanya Chundru , Akhil Vinod , Subramanian Ananthanarayanan , linux-kernel@vger.kernel.org, mhi@lists.linux.dev, linux-arm-msm@vger.kernel.org, quic_vpernami@quicinc.com, Sumit Kumar X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=ed25519-sha256; t=1758609464; l=12147; i=sumit.kumar@oss.qualcomm.com; s=20250409; h=from:subject:message-id; bh=GyDV1zAPt6M4BAQbQYZppmlVchSBpKNe8e6ZOu3WccQ=; b=4/nsQ00EhRFdsoJ712JR7/BOa4SEw2anAhNVxVeJZznxpGkpuXW1SEbiHCqiaExA1paAlfSzO VRsCEwmEGhZCYF23AgcpKCNUc2Gl4GmMTwtKfeR+YoOch7gFGgbxVtK X-Developer-Key: i=sumit.kumar@oss.qualcomm.com; a=ed25519; pk=3cys6srXqLACgA68n7n7KjDeM9JiMK1w6VxzMxr0dnM= X-Proofpoint-GUID: SDbOOEb4VBzjfBuZnPDQY6-B2S2y3mnT X-Authority-Analysis: v=2.4 cv=fY2ty1QF c=1 sm=1 tr=0 ts=68d24040 cx=c_pps a=Oh5Dbbf/trHjhBongsHeRQ==:117 a=ZePRamnt/+rB5gQjfz0u9A==:17 a=IkcTkHD0fZMA:10 a=yJojWOMRYYMA:10 a=EUspDBNiAAAA:8 a=bacY0d_NKaLyk7ydmrwA:9 a=QEXdDO2ut3YA:10 a=_Vgx9l1VpLgwpw_dHYaR:22 X-Proofpoint-Spam-Details-Enc: AW1haW4tMjUwOTIyMDE2OCBTYWx0ZWRfX/zSWnkx1DUFL gRnnDgobU00FNNunKuar3hVuL7eOYBm7Fv+FyvKLDRQvLVc/iMRE2fa2z6PcsTfTZIz9dXz7bUc glApQzMmgsnTbRD+mrvSC2UtYdblyAeQKnYKGiYAyf9riq8BAkH+2GPqs0TTpJdOn2rj7tIWUNY 1+MnYejCbVMsS8YmtXwywEDUEMxx+mIZmzFLsiX/mUZS5XC/guZCjiI7mRaIKl5rZztDwK/so5P va0DEDwUGC7Tye5+oObvOIqL31Kvsv31PolDaLGLyxwz9wT8FGWArwQVOarsTSlaPBu0e/iPXkD yllJTUaxwNyjIokj085k/siCdszbw7S4pF0mO/lqAJZOPLPBLTSNjurr5lpL4EZLTVzR5J1Ej6B 5sgVyNLe X-Proofpoint-ORIG-GUID: SDbOOEb4VBzjfBuZnPDQY6-B2S2y3mnT X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1117,Hydra:6.1.9,FMLib:17.12.80.40 definitions=2025-09-23_01,2025-09-22_05,2025-03-28_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 suspectscore=0 malwarescore=0 spamscore=0 adultscore=0 impostorscore=0 phishscore=0 bulkscore=0 priorityscore=1501 clxscore=1015 classifier=typeunknown authscore=0 authtc= authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.19.0-2507300000 definitions=main-2509220168 Add loopback driver for MHI host controllers that provides sysfs based testing interface for data path validation. The driver supports the "LOOPBACK" channel and offers configurable test parameters. Sysfs interface provides: - size: Configure TRE size - num_tre: Set number of TREs for chained transfers - start: Initiate loopback test - status: Read test results The driver is useful for testing TRE chaining functionality, and verifying data integrity. Co-developed-by: Krishna Chaitanya Chundru Signed-off-by: Krishna Chaitanya Chundru Signed-off-by: Sumit Kumar --- drivers/bus/mhi/host/Kconfig | 7 + drivers/bus/mhi/host/Makefile | 1 + drivers/bus/mhi/host/mhi_loopback.c | 348 ++++++++++++++++++++++++++++++++= ++++ 3 files changed, 356 insertions(+) diff --git a/drivers/bus/mhi/host/Kconfig b/drivers/bus/mhi/host/Kconfig index da5cd0c9fc620ab595e742c422f1a22a2a84c7b9..08a39ecb47f585bf39721c101ed= 5e2ff44bdd5f8 100644 --- a/drivers/bus/mhi/host/Kconfig +++ b/drivers/bus/mhi/host/Kconfig @@ -29,3 +29,10 @@ config MHI_BUS_PCI_GENERIC This driver provides MHI PCI controller driver for devices such as Qualcomm SDX55 based PCIe modems. =20 +config MHI_BUS_LOOPBACK + tristate "MHI loopback driver" + depends on MHI_BUS + help + MHI loopback driver for data path testing. This driver + provides a mechanism to test MHI data transfer functionality + by implementing an echo service between host and endpoint. diff --git a/drivers/bus/mhi/host/Makefile b/drivers/bus/mhi/host/Makefile index 859c2f38451c669b3d3014c374b2b957c99a1cfe..e5d6dccf5a976eaeb827c47924a= d0614c9958f8b 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-$(CONFIG_MHI_BUS_LOOPBACK) +=3D mhi_loopback.o diff --git a/drivers/bus/mhi/host/mhi_loopback.c b/drivers/bus/mhi/host/mhi= _loopback.c new file mode 100644 index 0000000000000000000000000000000000000000..2936fc67e6ff1788263690e2649= f2a55398f46d8 --- /dev/null +++ b/drivers/bus/mhi/host/mhi_loopback.c @@ -0,0 +1,348 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#include +#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 65536 + +struct mhi_loopback { + struct completion comp; + struct mhi_device *mdev; + struct mutex lb_mutex; + char result[32]; + u32 size; + u32 num_tre; + bool loopback_in_progress; + atomic_t num_completions_received; +}; + +static ssize_t size_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct mhi_loopback *mhi_lb =3D dev_get_drvdata(dev); + + return sysfs_emit(buf, "%u\n", mhi_lb->size); +} + +static ssize_t size_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct mhi_loopback *mhi_lb =3D dev_get_drvdata(dev); + u32 val; + + if (kstrtou32(buf, 0, &val)) { + dev_err(dev, "Invalid size value\n"); + return -EINVAL; + } + + if (val =3D=3D 0 || val > MHI_LOOPBACK_MAX_TRE_SIZE) { + dev_err(dev, "Size must be between 1 and %u bytes\n", + MHI_LOOPBACK_MAX_TRE_SIZE); + return -EINVAL; + } + + guard(mutex)(&mhi_lb->lb_mutex); + if (mhi_lb->loopback_in_progress) + return -EBUSY; + + mhi_lb->size =3D val; + return count; +} +static DEVICE_ATTR_RW(size); + +static ssize_t num_tre_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct mhi_loopback *mhi_lb =3D dev_get_drvdata(dev); + + return sysfs_emit(buf, "%u\n", mhi_lb->num_tre); +} + +static ssize_t num_tre_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct mhi_loopback *mhi_lb =3D dev_get_drvdata(dev); + u32 val; + int el_num; + + guard(mutex)(&mhi_lb->lb_mutex); + if (mhi_lb->loopback_in_progress) + return -EBUSY; + + if (kstrtou32(buf, 0, &val)) { + dev_err(dev, "Invalid num_tre value\n"); + return -EINVAL; + } + + if (val =3D=3D 0) { + dev_err(dev, "Number of TREs cannot be zero\n"); + return -EINVAL; + } + + el_num =3D mhi_get_free_desc_count(mhi_lb->mdev, DMA_TO_DEVICE); + if (val > el_num) { + dev_err(dev, "num_tre (%u) exceeds ring capacity (%d)\n", val, el_num); + return -EINVAL; + } + + mhi_lb->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 *mhi_lb =3D dev_get_drvdata(dev); + void *send_buf, *recv_buf; + u32 total_size, tre_count, tre_size; + int ret, i; + + atomic_set(&mhi_lb->num_completions_received, 0); + guard(mutex)(&mhi_lb->lb_mutex); + + if (mhi_lb->loopback_in_progress) + return -EBUSY; + + mhi_lb->loopback_in_progress =3D true; + + tre_size =3D mhi_lb->size; + tre_count =3D mhi_lb->num_tre; + + strscpy(mhi_lb->result, "Loopback started", sizeof(mhi_lb->result)); + + total_size =3D tre_count * tre_size; + + recv_buf =3D kzalloc(total_size, GFP_KERNEL); + if (!recv_buf) { + strscpy(mhi_lb->result, "Memory allocation failed", sizeof(mhi_lb->resul= t)); + ret =3D -ENOMEM; + goto unlock; + } + + send_buf =3D kzalloc(total_size, GFP_KERNEL); + if (!send_buf) { + strscpy(mhi_lb->result, "Memory allocation failed", sizeof(mhi_lb->resul= t)); + ret =3D -ENOMEM; + goto free_recv_buf; + } + + for (i =3D 0; i < tre_count; i++) { + ret =3D mhi_queue_buf(mhi_lb->mdev, DMA_FROM_DEVICE, recv_buf + (i * tre= _size), + tre_size, MHI_EOT); + if (ret) { + dev_err(dev, "Unable to queue read TRE %d: %d\n", i, ret); + strscpy(mhi_lb->result, "Queue tre failed", sizeof(mhi_lb->result)); + goto free_buf; + } + } + + get_random_bytes(send_buf, total_size); + + reinit_completion(&mhi_lb->comp); + + for (i =3D 0; i < tre_count - 1; i++) { + ret =3D mhi_queue_buf(mhi_lb->mdev, DMA_TO_DEVICE, send_buf + (i * tre_s= ize), + tre_size, MHI_CHAIN); + if (ret) { + dev_err(dev, "Unable to queue send TRE %d (chained): %d\n", i, ret); + strscpy(mhi_lb->result, "Queue send failed", sizeof(mhi_lb->result)); + goto free_buf; + } + } + + ret =3D mhi_queue_buf(mhi_lb->mdev, DMA_TO_DEVICE, send_buf + (i * tre_si= ze), + tre_size, MHI_EOT); + if (ret) { + dev_err(dev, "Unable to queue final TRE: %d\n", ret); + strscpy(mhi_lb->result, "Queue final tre failed", sizeof(mhi_lb->result)= ); + goto free_buf; + } + + if (!wait_for_completion_timeout(&mhi_lb->comp, + msecs_to_jiffies(MHI_LOOPBACK_TIMEOUT_MS))) { + strscpy(mhi_lb->result, "Loopback timeout", sizeof(mhi_lb->result)); + dev_err(dev, "Loopback test timed out\n"); + ret =3D -ETIMEDOUT; + goto free_buf; + } + + ret =3D memcmp(send_buf, recv_buf, total_size); + if (!ret) { + strscpy(mhi_lb->result, "Loopback successful", sizeof(mhi_lb->result)); + dev_info(dev, "Loopback test passed\n"); + ret =3D count; + } else { + strscpy(mhi_lb->result, "Loopback data mismatch", sizeof(mhi_lb->result)= ); + dev_err(dev, "Loopback test failed\n"); + ret =3D -EIO; + } + +free_buf: + kfree(send_buf); +free_recv_buf: + kfree(recv_buf); +unlock: + mhi_lb->loopback_in_progress =3D false; + return ret; +} + +static DEVICE_ATTR_WO(start); + +static ssize_t status_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct mhi_loopback *mhi_lb =3D dev_get_drvdata(dev); + + return sysfs_emit(buf, "%s\n", mhi_lb->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 *mhi_lb =3D dev_get_drvdata(&mhi_dev->dev); + + if (!mhi_res->transaction_status) { + if (atomic_inc_return(&mhi_lb->num_completions_received) >=3D mhi_lb->nu= m_tre) { + atomic_set(&mhi_lb->num_completions_received, 0); + complete(&mhi_lb->comp); + } + } else { + dev_err(&mhi_dev->dev, "DL callback error: status %d\n", + mhi_res->transaction_status); + atomic_set(&mhi_lb->num_completions_received, 0); + complete(&mhi_lb->comp); + } +} + +static void mhi_loopback_ul_callback(struct mhi_device *mhi_dev, + struct mhi_result *mhi_res) +{ +} + +static int mhi_loopback_probe(struct mhi_device *mhi_dev, + const struct mhi_device_id *id) +{ + struct mhi_loopback *mhi_lb; + int rc; + + mhi_lb =3D devm_kzalloc(&mhi_dev->dev, sizeof(*mhi_lb), GFP_KERNEL); + if (!mhi_lb) + return -ENOMEM; + + mhi_lb->mdev =3D mhi_dev; + + dev_set_drvdata(&mhi_dev->dev, mhi_lb); + + mhi_lb->size =3D MHI_LOOPBACK_DEFAULT_TRE_SIZE; + mhi_lb->num_tre =3D MHI_LOOPBACK_DEFAULT_NUM_TRE; + mhi_lb->loopback_in_progress =3D false; + + mutex_init(&mhi_lb->lb_mutex); + strscpy(mhi_lb->result, "Loopback not started", sizeof(mhi_lb->result)); + + rc =3D sysfs_create_file(&mhi_dev->dev.kobj, &dev_attr_size.attr); + if (rc) { + dev_err(&mhi_dev->dev, "failed to create size sysfs file\n"); + goto out; + } + + rc =3D sysfs_create_file(&mhi_dev->dev.kobj, &dev_attr_num_tre.attr); + if (rc) { + dev_err(&mhi_dev->dev, "failed to create num_tre sysfs file\n"); + goto del_size_sysfs; + } + + rc =3D sysfs_create_file(&mhi_dev->dev.kobj, &dev_attr_start.attr); + if (rc) { + dev_err(&mhi_dev->dev, "failed to create start sysfs file\n"); + goto del_num_tre_sysfs; + } + + rc =3D sysfs_create_file(&mhi_dev->dev.kobj, &dev_attr_status.attr); + if (rc) { + dev_err(&mhi_dev->dev, "failed to create status sysfs file\n"); + goto del_start_sysfs; + } + + rc =3D mhi_prepare_for_transfer(mhi_lb->mdev); + if (rc) { + dev_err(&mhi_dev->dev, "failed to prepare for transfers\n"); + goto del_status_sysfs; + } + + init_completion(&mhi_lb->comp); + + return 0; + +del_status_sysfs: + sysfs_remove_file(&mhi_dev->dev.kobj, &dev_attr_status.attr); +del_start_sysfs: + sysfs_remove_file(&mhi_dev->dev.kobj, &dev_attr_start.attr); +del_num_tre_sysfs: + sysfs_remove_file(&mhi_dev->dev.kobj, &dev_attr_num_tre.attr); +del_size_sysfs: + sysfs_remove_file(&mhi_dev->dev.kobj, &dev_attr_size.attr); +out: + return rc; +} + +static void mhi_loopback_remove(struct mhi_device *mhi_dev) +{ + struct mhi_loopback *mhi_lb =3D dev_get_drvdata(&mhi_dev->dev); + + if (mhi_lb) + complete(&mhi_lb->comp); + + sysfs_remove_file(&mhi_dev->dev.kobj, &dev_attr_status.attr); + sysfs_remove_file(&mhi_dev->dev.kobj, &dev_attr_start.attr); + sysfs_remove_file(&mhi_dev->dev.kobj, &dev_attr_num_tre.attr); + sysfs_remove_file(&mhi_dev->dev.kobj, &dev_attr_size.attr); + mhi_unprepare_from_transfer(mhi_dev); + 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 Thu Oct 2 03:30:48 2025 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 0B43830FF00 for ; Tue, 23 Sep 2025 06:37:56 +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=1758609478; cv=none; b=hhOyvz/K8XqCeeazfK3Nr0xUyGEexpk2KKDkUb17mFzn13Uy0A4a6iy3AutL1cC4nn29EEZT0Ex9tNxCM+Qt4LLetiYeFJvRWxSwg88KSKaoIUkeOuSV3B0VkkmU7NDyR1jocsbA87RkskGWkqtlo4u5+3QCafIfAbb7kU2nHQI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1758609478; c=relaxed/simple; bh=/XZjxMDsdlsb2hd1V1q563apP/LGTaw7IP8VKfFQNnM=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=uaE+ajnlGFsi/fk9l3tyot8K71Dd1j41iwU9R1AMUgOREIGDD6YoDPX9RsQkWbPzh/4rUaoBXUV6PeXXGZVCmGOZeiditoGAje6qttT76siUvvwLMJIGs4351aHPK+GnICmSpVYUQTpqRCH93D6tGvHmR814MH+4HcgYHiCRCsM= 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=b2JwHXt2; 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="b2JwHXt2" Received: from pps.filterd (m0279873.ppops.net [127.0.0.1]) by mx0a-0031df01.pphosted.com (8.18.1.2/8.18.1.2) with ESMTP id 58N6ZhLN026426 for ; Tue, 23 Sep 2025 06:37: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= /2i5gCewt8z3E3EoPGc+LEWHh1OOCMfCgomgDxGz2IM=; b=b2JwHXt2hQ1DXyan h1uTZL0FqtBJiQTpA/mZv2s8MtvjISRn3gXI8oeK9shy9r+2yiKiIOY+Z1QKGU5c QdRe+gNUZDJtQTubzho4XUP0ArR0dq12H3xJ6YYuj0KiEB7z/TXTXSpcHUSxrZMC lTWqnrRBouwA8kwzkwoGbnJ1cvlC1CC6SNtZja22IDVs6ivl221IjmUoeandSJmS ByftprOWqB6asnCHkQXdTXSUHsJmviBgQUbwGFcHEaMH+Jy77drSfz0YV4bjhq4M rO3zbK2CnacrnA4g+l9cRg/z8dW1abi+4hz+gB/whYBFmgaXtIaJsWBHvziWcFwV PjFuDA== Received: from mail-pf1-f197.google.com (mail-pf1-f197.google.com [209.85.210.197]) by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 499hmnqrff-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NOT) for ; Tue, 23 Sep 2025 06:37:55 +0000 (GMT) Received: by mail-pf1-f197.google.com with SMTP id d2e1a72fcca58-77f2eff831dso3178824b3a.0 for ; Mon, 22 Sep 2025 23:37:55 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1758609474; x=1759214274; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=/2i5gCewt8z3E3EoPGc+LEWHh1OOCMfCgomgDxGz2IM=; b=DBP1lbF4f/CCcBbVCC/zI97oFRGltqvEOsViDt+qC7JPXKDooaSo7gsPA7EKollhWl roYPVRn6Ig3thJ0t63/9ibCfQicnTbhA2wa4jqGsvrBQiZeHpOPBqkxIOYwdvmWKnCmh 3i4Kytu8Eu/5I8tUjbY2NzlUfjP3G0kxgVoXBcBcSQIIOflyiBOS70kxENbvU6DaqRNl xr6rfUPT9pDs0aoAOA37YX/9GCvex9p+JMXVBrIq0LQGqx2VRYiDeZnoTQ93kadsA+Pk ri4oOGiqRaPGDLH/wEgYbFKktwGpn8gGBYP1Zkl7ayIKTnvXnOBmUm60xG7S0bxcMU7C w2xw== X-Forwarded-Encrypted: i=1; AJvYcCW7KdIjhyhn53LaNeeiTfBYhcBX3Shb+FO13NFJq+bs9u8F5n9YRMT03Q3qe348q2Gq2B3GTwL3Yos8Bz0=@vger.kernel.org X-Gm-Message-State: AOJu0YyGpCY/P3EGFpeaT9cA8YWnR/cRcGhLNX+XsRjA7H8acfgk07qy ramR3uZDxMObm0XVOlCCp/qtA9oCnYgTHOIsfBk3m/vZ28/Au8W34m1RRLD217qv4kJQ5/tpjAU yKRkPdDBVkga2eIwwcxTIgzMfviSLYp9Ir92YPL6xaDzLd4dmb7/35ZUbLHdsvSdXUkc= X-Gm-Gg: ASbGncvV8tR+5R1/3zvPhPgMVZZ0ON4HTFlZMDakdlYrhF5Oo83rt7OMFIPp1WaoH2K ZuoHnfsv219AhPJrfSeTCPtZWupUBw4+BWNyGw2fi+AoNQm9nQUpQabFkZRfJwT5GylZ3xBwrTz TaAS484dMlap0cs3Uaa++cdT54LH1ZhAE96Pt8YxWLWp0cTE40C41P52C7jHa/nh9Wjzyxah8Ix 4kbf3cAsFjZEo6kPqK16AJRJr5bbz4Ca+CXDZ19lChXKYRGK2CPL6vjwfPAgHndfgn/3dJ4H4QG mW5OjZcIZWvZPz3/gUpWvb9WbIxp+0HmYqZk8zy0dP3K2ciWQCc50sAgCC+Rli4oug== X-Received: by 2002:a05:6a21:6d97:b0:2b5:769f:2542 with SMTP id adf61e73a8af0-2cfe8990c69mr2570923637.36.1758609474173; Mon, 22 Sep 2025 23:37:54 -0700 (PDT) X-Google-Smtp-Source: AGHT+IEcdgMOz1PL6eB9rEDeqp235HhjD28WXRHTyz1Aw/HjM+cmU/CEZqbyYKplL/kpmh4rWvdwEQ== X-Received: by 2002:a05:6a21:6d97:b0:2b5:769f:2542 with SMTP id adf61e73a8af0-2cfe8990c69mr2570886637.36.1758609473642; Mon, 22 Sep 2025 23:37:53 -0700 (PDT) Received: from hu-sumk-hyd.qualcomm.com ([202.46.23.25]) by smtp.gmail.com with ESMTPSA id 41be03b00d2f7-b551905bb4csm10792840a12.29.2025.09.22.23.37.51 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 22 Sep 2025 23:37:53 -0700 (PDT) From: Sumit Kumar Date: Tue, 23 Sep 2025 12:07:42 +0530 Subject: [PATCH 2/2] bus: mhi: ep: 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: <20250923-loopback_mhi-v1-2-8618f31f44aa@oss.qualcomm.com> References: <20250923-loopback_mhi-v1-0-8618f31f44aa@oss.qualcomm.com> In-Reply-To: <20250923-loopback_mhi-v1-0-8618f31f44aa@oss.qualcomm.com> To: Manivannan Sadhasivam Cc: Krishna Chaitanya Chundru , Akhil Vinod , Subramanian Ananthanarayanan , linux-kernel@vger.kernel.org, mhi@lists.linux.dev, linux-arm-msm@vger.kernel.org, quic_vpernami@quicinc.com, Sumit Kumar X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=ed25519-sha256; t=1758609464; l=5830; i=sumit.kumar@oss.qualcomm.com; s=20250409; h=from:subject:message-id; bh=/XZjxMDsdlsb2hd1V1q563apP/LGTaw7IP8VKfFQNnM=; b=WD/6L5VbKB2D38KzJB8gQHdyMsWs2SrkdKIoQaD+MAq6ui8rTHJuvnjhuIKISlRT070gQF1N3 pruOysrtJ/wAkO1k8tjM0ZDaLdRVlVYLCVovKtsMY741Oxd/fHtv4u/ X-Developer-Key: i=sumit.kumar@oss.qualcomm.com; a=ed25519; pk=3cys6srXqLACgA68n7n7KjDeM9JiMK1w6VxzMxr0dnM= X-Authority-Analysis: v=2.4 cv=YPqfyQGx c=1 sm=1 tr=0 ts=68d24043 cx=c_pps a=rEQLjTOiSrHUhVqRoksmgQ==:117 a=ZePRamnt/+rB5gQjfz0u9A==:17 a=IkcTkHD0fZMA:10 a=yJojWOMRYYMA:10 a=EUspDBNiAAAA:8 a=RyQsIt2LcgCPV6mEHuQA:9 a=QEXdDO2ut3YA:10 a=2VI0MkxyNR6bbpdq8BZq:22 X-Proofpoint-ORIG-GUID: rrMIOtvOJEiL7y6GenUcAo6jkqbDEo7j X-Proofpoint-Spam-Details-Enc: AW1haW4tMjUwOTIwMDAwMCBTYWx0ZWRfXzxhN2wJa/DEA fKYRDbTOvTRmIPFFli6ZMFHcIzUoqIVYquu0kVmN8DuJKs+teppSsbbkCKsFVSCSrIAkk8K98v6 Ujqcfo+wmuhTM6K4vU+ID2+aNkasz1Aq+3hKtVzdExsAGaenmAyrGuwm4RoUOmuDdits32nEKRz X3Ga26BqKTRac+YjQTYiiQ9qihYeTRtWwend60B0Z30GfxqyGmXjxl/5vHmQ28xil5utlZ24aPu IltyTCJKi73AbNl8m/EgYXycasfQQXnUBeGyhmBhPAOoY6zoZ/oFpzprjRLHbPhnO+8/Kp0p3W1 Jx+B809GECJ7tnHe3ORldlWK3GnjBlLOiNoOd+ySx4nw5Q9oQgXfwKb4X8lz0BXxsTIMe1GUif3 JeUbLuB0 X-Proofpoint-GUID: rrMIOtvOJEiL7y6GenUcAo6jkqbDEo7j X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1117,Hydra:6.1.9,FMLib:17.12.80.40 definitions=2025-09-23_01,2025-09-22_05,2025-03-28_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 suspectscore=0 bulkscore=0 priorityscore=1501 phishscore=0 adultscore=0 clxscore=1015 impostorscore=0 spamscore=0 malwarescore=0 classifier=typeunknown authscore=0 authtc= authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.19.0-2507300000 definitions=main-2509200000 Add loopback driver for MHI endpoint devices. The driver receives data on the uplink channel and echoes it back on the downlink channel using a workqueue for asynchronous processing. The driver is useful for testing MHI endpoint data path functionality and debugging communication issues. Co-developed-by: Krishna Chaitanya Chundru Signed-off-by: Krishna Chaitanya Chundru Signed-off-by: Sumit Kumar --- drivers/bus/mhi/ep/Kconfig | 8 +++ drivers/bus/mhi/ep/Makefile | 1 + drivers/bus/mhi/ep/mhi_ep_loopback.c | 132 +++++++++++++++++++++++++++++++= ++++ 3 files changed, 141 insertions(+) diff --git a/drivers/bus/mhi/ep/Kconfig b/drivers/bus/mhi/ep/Kconfig index 90ab3b040672e0f04181d4802e3062afcc7cf782..ce7b63c2da82a6ca49528517687= f4910552c35bb 100644 --- a/drivers/bus/mhi/ep/Kconfig +++ b/drivers/bus/mhi/ep/Kconfig @@ -8,3 +8,11 @@ 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. + +config MHI_BUS_EP_LOOPBACK + tristate "MHI Endpoint loopback driver" + depends on MHI_BUS_EP + help + MHI endpoint loopback driver for data path testing. + This driver receives data on the uplink channel and echoes + it back on the downlink channel for testing purposes. diff --git a/drivers/bus/mhi/ep/Makefile b/drivers/bus/mhi/ep/Makefile index aad85f180b707fb997fcb541837eda9bbbb67437..02e4700e8dc3f860d40290476b0= a852286683f8f 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-$(CONFIG_MHI_BUS_EP_LOOPBACK) +=3D mhi_ep_loopback.o diff --git a/drivers/bus/mhi/ep/mhi_ep_loopback.c b/drivers/bus/mhi/ep/mhi_= ep_loopback.c new file mode 100644 index 0000000000000000000000000000000000000000..89244aca684ffc959a38f8a0c3a= d577b2d127c48 --- /dev/null +++ b/drivers/bus/mhi/ep/mhi_ep_loopback.c @@ -0,0 +1,132 @@ +// 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; + struct sk_buff *skb; +}; + +static void mhi_ep_loopback_work_handler(struct work_struct *work) +{ + int ret; + struct mhi_ep_loopback_work *mhi_ep_lb_work =3D container_of(work, + struct mhi_ep_loopback_work, work); + + ret =3D mhi_ep_queue_skb(mhi_ep_lb_work->mdev, mhi_ep_lb_work->skb); + if (ret) { + dev_err(&mhi_ep_lb_work->mdev->dev, "Failed to send the packet\n"); + kfree_skb(mhi_ep_lb_work->skb); + } + + 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; + struct sk_buff *skb; + + if (!(mhi_res->transaction_status)) { + skb =3D alloc_skb(mhi_res->bytes_xferd, GFP_KERNEL); + if (!skb) { + dev_err(&mhi_dev->dev, "Failed to allocate skb\n"); + return; + } + + skb_put_data(skb, mhi_res->buf_addr, mhi_res->bytes_xferd); + + mhi_ep_lb_work =3D kmalloc(sizeof(*mhi_ep_lb_work), GFP_KERNEL); + if (!mhi_ep_lb_work) { + dev_err(&mhi_dev->dev, "Unable to allocate the work structure\n"); + kfree_skb(skb); + 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->skb =3D skb; + + 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) +{ + struct sk_buff *skb; + + if (mhi_res->transaction_status) + return; + + skb =3D mhi_res->buf_addr; + if (skb) + kfree_skb(skb); +} + +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(struct mhi_ep_loopback),= GFP_KERNEL); + if (!mhi_ep_lb) + return -ENOMEM; + + mhi_ep_lb->loopback_wq =3D alloc_ordered_workqueue("mhi_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", + .owner =3D THIS_MODULE, + }, +}; + +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