From nobody Mon Oct 6 08:30:17 2025 Received: from lelvem-ot02.ext.ti.com (lelvem-ot02.ext.ti.com [198.47.23.235]) (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 11DE5281369; Wed, 23 Jul 2025 08:04:18 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.47.23.235 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1753257862; cv=none; b=QVJm9vZgSb0wrdDBjvLTnF09CWKuozGcPxl92MX0KkhTU9IB0KwPeyW9jWgZrQciHiXINlNrG9Itg0Ehfbx+miicZAFlvMjYIj8os9fMmoRq1MSHeFabgyAhqPFSGZ6QWP444E3x9AlAueb2pQP/XilG3qCjrghZ13L0Jr1VKvo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1753257862; c=relaxed/simple; bh=AqpMlJ1BSP9Swinfd7sXPYHR1l9IrdpRfu4SEx/a8zA=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=ntaEgjJjwgkdne7JrNUK2GiZEGPoDl+osKLLKtn89qKFplBWwMqRSqLo/7aZ8qnM0rG1IZ6yDBB68qwz3oWY7VivvinfHNcnfQAOLzW0pmRStCymZidRQy82WBFhp0jUm0Vv3zJjwOKrRZKA8WWw+qQkJdbJTdnp9UxV8Y+JGOA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=ti.com; spf=pass smtp.mailfrom=ti.com; dkim=pass (1024-bit key) header.d=ti.com header.i=@ti.com header.b=H2rIgjCu; arc=none smtp.client-ip=198.47.23.235 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=ti.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=ti.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=ti.com header.i=@ti.com header.b="H2rIgjCu" Received: from fllvem-sh03.itg.ti.com ([10.64.41.86]) by lelvem-ot02.ext.ti.com (8.15.2/8.15.2) with ESMTP id 56N83UVw1695117; Wed, 23 Jul 2025 03:03:30 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ti.com; s=ti-com-17Q1; t=1753257810; bh=mvDX6DOV8YuWwDnj84Y8gAsL48e8sIoeavomIPEepuU=; h=From:To:CC:Subject:Date:In-Reply-To:References; b=H2rIgjCuKKEd2RvAaxowWfB93X8BVVvA8DPvfobv9K5UrrMFS/xHmdQyPWeRH/KRx cotXgRavjssU8daP6yi1fTmgiOWgVXN0lUbHAQOwdfvQmJ2wyyQDFhzhMKL/ltO2nC jJllTdaGUpPoyOYZmEWe8MrD+SooqiRMdv7J/AwM= Received: from DFLE105.ent.ti.com (dfle105.ent.ti.com [10.64.6.26]) by fllvem-sh03.itg.ti.com (8.18.1/8.18.1) with ESMTPS id 56N83Uxn1619069 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-SHA256 bits=128 verify=FAIL); Wed, 23 Jul 2025 03:03:30 -0500 Received: from DFLE114.ent.ti.com (10.64.6.35) by DFLE105.ent.ti.com (10.64.6.26) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.2507.55; Wed, 23 Jul 2025 03:03:29 -0500 Received: from fllvem-mr07.itg.ti.com (10.64.41.89) by DFLE114.ent.ti.com (10.64.6.35) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.2507.55 via Frontend Transport; Wed, 23 Jul 2025 03:03:29 -0500 Received: from fllv0122.itg.ti.com (fllv0122.itg.ti.com [10.247.120.72]) by fllvem-mr07.itg.ti.com (8.18.1/8.18.1) with ESMTP id 56N83TDU160345; Wed, 23 Jul 2025 03:03:29 -0500 Received: from localhost (danish-tpc.dhcp.ti.com [10.24.69.25]) by fllv0122.itg.ti.com (8.14.7/8.14.7) with ESMTP id 56N83S7V015945; Wed, 23 Jul 2025 03:03:29 -0500 From: MD Danish Anwar To: "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Simon Horman , Jonathan Corbet , Andrew Lunn , Mengyuan Lou , MD Danish Anwar , Michael Ellerman , Madhavan Srinivasan , Fan Gong , Lee Trager , Lorenzo Bianconi , Geert Uytterhoeven , Lukas Bulwahn , Parthiban Veerasooran CC: , , Subject: [PATCH net-next 1/5] net: rpmsg-eth: Add Documentation for RPMSG-ETH Driver Date: Wed, 23 Jul 2025 13:33:18 +0530 Message-ID: <20250723080322.3047826-2-danishanwar@ti.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20250723080322.3047826-1-danishanwar@ti.com> References: <20250723080322.3047826-1-danishanwar@ti.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-C2ProcessedOrg: 333ef613-75bf-4e12-a4b1-8e3623f5dcea Content-Type: text/plain; charset="utf-8" Add documentation for the RPMSG Based Virtual Ethernet Driver (rpmsg-eth). The documentation describes the driver's architecture, shared memory layout, RPMSG communication protocol, and requirements for vendor firmware to interoperate with the driver. It details the use of a magic number for shared memory validation, outlines the information exchanged between the host and remote processor, and provides a how-to guide for vendors to implement compatible firmware. Signed-off-by: MD Danish Anwar --- .../device_drivers/ethernet/index.rst | 1 + .../device_drivers/ethernet/rpmsg_eth.rst | 339 ++++++++++++++++++ 2 files changed, 340 insertions(+) create mode 100644 Documentation/networking/device_drivers/ethernet/rpmsg_= eth.rst diff --git a/Documentation/networking/device_drivers/ethernet/index.rst b/D= ocumentation/networking/device_drivers/ethernet/index.rst index 40ac552641a3..941f60585ee4 100644 --- a/Documentation/networking/device_drivers/ethernet/index.rst +++ b/Documentation/networking/device_drivers/ethernet/index.rst @@ -61,6 +61,7 @@ Contents: wangxun/txgbevf wangxun/ngbe wangxun/ngbevf + rpmsg_eth =20 .. only:: subproject and html =20 diff --git a/Documentation/networking/device_drivers/ethernet/rpmsg_eth.rst= b/Documentation/networking/device_drivers/ethernet/rpmsg_eth.rst new file mode 100644 index 000000000000..70c13deb31ea --- /dev/null +++ b/Documentation/networking/device_drivers/ethernet/rpmsg_eth.rst @@ -0,0 +1,339 @@ +.. SPDX-License-Identifier: GPL-2.0 + +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D +RPMSG Based Virtual Ethernet Driver +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D + +Overview +=3D=3D=3D=3D=3D=3D=3D=3D + +The RPMSG Based Virtual Ethernet Driver provides a virtual Ethernet interf= ace for +communication between a host processor and a remote processor using the RP= MSG +framework. This driver enables Ethernet-like packet transmission and recep= tion +over shared memory, facilitating inter-core communication in systems with +heterogeneous processors. + +The driver is designed to work with the RPMSG framework, which is part of = the +Linux Remote Processor (remoteproc) subsystem. It uses shared memory for d= ata +exchange and supports features like multicast address management, dynamic = MAC +address assignment, and efficient packet processing using NAPI. + +This driver is generic and can be used by any vendor. Vendors can develop = their +own firmware for the remote processor to make it compatible with this driv= er. +The firmware must adhere to the shared memory layout, RPMSG communication +protocol, and data exchange requirements described in this documentation. + +Key Features +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D + +- Virtual Ethernet interface using RPMSG. +- Shared memory-based packet transmission and reception. +- Support for multicast address management. +- Dynamic MAC address assignment. +- NAPI (New API) support for efficient packet processing. +- State machine for managing interface states. +- Workqueue-based asynchronous operations. +- Support for notifications and responses from the remote processor. + +Magic Number +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D + +A **magic number** is used in the shared memory layout to validate that the +memory region is correctly initialized and accessible by both the host and= the +remote processor. This value is a unique constant (for example, +``0xABCDABCD``) that is written to specific locations (such as the head and +tail structures) in the shared memory by the firmware and checked by the L= inux +driver during the handshake process. + +Purpose of the Magic Number +--------------------------- + +- **Validation:** Ensures that the shared memory region has been properly = set up + and is not corrupted or uninitialized. +- **Synchronization:** Both the host and remote processor must agree on the + magic number value, which helps detect mismatches in memory layout or pr= otocol + version. +- **Error Detection:** If the driver detects an incorrect magic number dur= ing + initialization or runtime, it can abort the handshake and report an erro= r, + preventing undefined behavior. + +Implementation Details +---------------------- + +- The magic number is defined as a macro in the driver source (e.g., + ``#define RPMSG_ETH_SHM_MAGIC_NUM 0xABCDABCD``). +- The firmware must write this value to the ``magic_num`` field of the hea= d and + tail structures in the shared memory region. +- During the handshake, the Linux driver reads these fields and compares t= hem to + the expected value. If any mismatch is detected, the driver will log an = error + and refuse to proceed. + +Example Usage in Shared Memory +------------------------------ + +.. code-block:: text + + Shared Memory Layout: + --------------------------- + | MAGIC_NUM (0xABCDABCD) | <-- rpmsg_eth_shm_head + | HEAD | + --------------------------- + | MAGIC_NUM (0xABCDABCD) | <-- rpmsg_eth_shm_tail + | TAIL | + --------------------------- + +The magic number must be present in both the head and tail structures for = the +handshake to succeed. + +Firmware developers must ensure that the correct magic number is written t= o the +appropriate locations in shared memory before the Linux driver attempts to +initialize the interface. + +Shared Memory Layout +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D + +The RPMSG Based Virtual Ethernet Driver uses a shared memory region to exc= hange +data between the host and the remote processor. The shared memory is divid= ed +into transmit and receive regions, each with its own `head` and `tail` poi= nters +to track the buffer state. + +Shared Memory Parameters +------------------------ + +The following parameters are exchanged between the host and the firmware to +configure the shared memory layout: + +1. **num_pkt_bufs**: + + - The total number of packet buffers available in the shared memory. + - This determines the maximum number of packets that can be stored in t= he + shared memory at any given time. + +2. **buff_slot_size**: + + - The size of each buffer slot in the shared memory. + - This includes space for the packet length, metadata, and the actual p= acket + data. + +3. **base_addr**: + + - The base address of the shared memory region. + - This is the starting point for accessing the shared memory. + +4. **tx_offset**: + + - The offset from the `base_addr` where the transmit buffers begin. + - This is used by the host to write packets for transmission. + +5. **rx_offset**: + + - The offset from the `base_addr` where the receive buffers begin. + - This is used by the host to read packets received from the remote + processor. + +Shared Memory Structure +----------------------- + +The shared memory layout is as follows: + +.. code-block:: text + + Shared Memory Layout: + --------------------------- + | MAGIC_NUM | rpmsg_eth_shm_head + | HEAD | + --------------------------- + | MAGIC_NUM | + | PKT_1_LEN | + | PKT_1 | + --------------------------- + | ... | + --------------------------- + | MAGIC_NUM | + | TAIL | rpmsg_eth_shm_tail + --------------------------- + +1. **MAGIC_NUM**: + + - A unique identifier used to validate the shared memory region. + - Ensures that the memory region is correctly initialized and accessibl= e. + +2. **HEAD Pointer**: + + - Tracks the start of the buffer for packet transmission or reception. + - Updated by the producer (host or remote processor) after writing a pa= cket. + +3. **TAIL Pointer**: + + - Tracks the end of the buffer for packet transmission or reception. + - Updated by the consumer (host or remote processor) after reading a pa= cket. + +4. **Packet Buffers**: + + - Each packet buffer contains: + + - **Packet Length**: A 4-byte field indicating the size of the packe= t. + - **Packet Data**: The actual Ethernet frame data. + +5. **Buffer Size**: + + - Each buffer has a fixed size defined by `RPMSG_ETH_BUFFER_SIZE`, which + includes space for the packet length and data. + +Buffer Management +----------------- + +- The host and remote processor use a circular buffer mechanism to manage = the shared memory. +- The `head` and `tail` pointers are used to determine the number of packe= ts available for processing: + + .. code-block:: c + + num_pkts =3D head - tail; + num_pkts =3D num_pkts >=3D 0 ? num_pkts : (num_pkts + max_buffers= ); + +- The producer writes packets to the buffer and increments the `head` poin= ter. +- The consumer reads packets from the buffer and increments the `tail` poi= nter. + +RPMSG Communication +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D + +The driver uses RPMSG channels to exchange control messages between the ho= st and +the remote processor. These messages are used to manage the state of the +Ethernet interface, configure settings, notify events, and exchange runtime +information. + +Information Exchanged Between RPMSG Channels +-------------------------------------------- + +1. **Requests from Host to Remote Processor**: + + - `RPMSG_ETH_REQ_SHM_INFO`: Request shared memory information, such as + ``num_pkt_bufs``, ``buff_slot_size``, ``base_addr``, ``tx_offset``, a= nd + ``rx_offset``. + - `RPMSG_ETH_REQ_SET_MAC_ADDR`: Set the MAC address of the Ethernet + interface. + - `RPMSG_ETH_REQ_ADD_MC_ADDR`: Add a multicast address to the remote + processor's filter list. + - `RPMSG_ETH_REQ_DEL_MC_ADDR`: Remove a multicast address from the remo= te + processor's filter list. + +2. **Responses from Remote Processor to Host**: + + - `RPMSG_ETH_RESP_SET_MAC_ADDR`: Acknowledge the MAC address configurat= ion. + - `RPMSG_ETH_RESP_ADD_MC_ADDR`: Acknowledge the addition of a multicast + address. + - `RPMSG_ETH_RESP_DEL_MC_ADDR`: Acknowledge the removal of a multicast + address. + - `RPMSG_ETH_RESP_SHM_INFO`: Respond with shared memory information suc= h as + ``num_pkt_bufs``, ``buff_slot_size``, ``base_addr``, ``tx_offset``, a= nd + ``rx_offset``. + +3. **Notifications from Remote Processor to Host**: + + - `RPMSG_ETH_NOTIFY_PORT_UP`: Notify that the Ethernet port is up and r= eady + for communication. + - `RPMSG_ETH_NOTIFY_PORT_DOWN`: Notify that the Ethernet port is down. + - `RPMSG_ETH_NOTIFY_PORT_READY`: Notify that the Ethernet port is ready= for + configuration. + - `RPMSG_ETH_NOTIFY_REMOTE_READY`: Notify that the remote processor is = ready + for communication. + +4. **Runtime Information Exchanged**: + + - **Link State**: Notifications about link state changes (e.g., link up= or + link down). + - **Statistics**: Runtime statistics such as transmitted/received packe= ts, + errors, and dropped packets. + - **Error Notifications**: Notifications about errors like buffer overf= lows + or invalid packets. + - **Configuration Updates**: Notifications about changes in configurati= on, + such as updated MTU or VLAN settings. + +How-To Guide for Vendors +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D + +This section provides a guide for vendors to develop firmware for the remo= te +processor that is compatible with the RPMSG Based Virtual Ethernet Driver. + +1. **Implement Shared Memory Layout**: + + - Allocate a shared memory region for packet transmission and reception. + - Initialize the `MAGIC_NUM`, `num_pkt_bufs`, `buff_slot_size`, `base_a= ddr`, + `tx_offset`, and `rx_offset`. + +2. **Magic Number Requirements** + + - The firmware must write a unique magic number (for example, ``0xABCDA= BCD``) + to the `magic_num` field of both the head and tail structures in the = shared + memory region. + - This magic number is used by the Linux driver to validate that the sh= ared + memory region is correctly initialized and accessible. + - If the driver detects an incorrect magic number during the handshake,= it + will abort initialization and report an error. + - Vendors must ensure the magic number matches the value expected by the + Linux driver (see the `RPMSG_ETH_SHM_MAGIC_NUM` macro in the driver + source). + +3. **Handle RPMSG Requests**: + + - Implement handlers for the following RPMSG requests: + + - `RPMSG_ETH_REQ_SHM_INFO` + - `RPMSG_ETH_REQ_SET_MAC_ADDR` + - `RPMSG_ETH_REQ_ADD_MC_ADDR` + - `RPMSG_ETH_REQ_DEL_MC_ADDR` + +4. **Send RPMSG Notifications**: + + - Notify the host about the state of the Ethernet interface using the + notifications described above. + +5. **Send Runtime Information**: + + - Implement mechanisms to send runtime information such as link state + changes, statistics, and error notifications. + +6. **Implement Packet Processing**: + + - Process packets in the shared memory transmit and receive buffers. + +7. **Test the Firmware**: + + - Use the RPMSG Based Virtual Ethernet Driver on the host to test packet + transmission and reception. + +Configuration +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D + +The driver relies on the device tree for configuration. The shared memory = region +is specified using the `virtual-eth-shm` node in the device tree. + +Example Device Tree Node +------------------------ + +.. code-block:: dts + + virtual-eth-shm { + compatible =3D "rpmsg,virtual-eth-shm"; + reg =3D <0x80000000 0x10000>; /* Base address and size of share= d memory */ + }; + +Limitations +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D + +- The driver assumes a specific shared memory layout and may not work with= other + configurations. +- Multicast address filtering is limited to the capabilities of the underl= ying + RPMSG framework. +- The driver currently supports only one transmit and one receive queue. + +References +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D + +- RPMSG Framework Documentation: https://www.kernel.org/doc/html/latest/rp= msg.html +- Linux Networking Documentation: https://www.kernel.org/doc/html/latest/n= etworking/index.html + +Authors +=3D=3D=3D=3D=3D=3D=3D + +- MD Danish Anwar --=20 2.34.1 From nobody Mon Oct 6 08:30:17 2025 Received: from lelvem-ot01.ext.ti.com (lelvem-ot01.ext.ti.com [198.47.23.234]) (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 24C7A28136E; Wed, 23 Jul 2025 08:04:15 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.47.23.234 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1753257862; cv=none; b=BEQ11vvxbX7ej0Zzy9FfkxDtQ7ASkGQO/Fny7jVpjEQQK8nC8T8xDZusRWmx8fHI5dO/18WdWBh5Hv+qhXiKNm0XTSv8uhky2WyCgxkzDLd362TnNJoKksOp7uu4OY+67AskpGLQx4sr74N9F6vjy7FUIK4EU3QwhZqbu0D0Wl8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1753257862; c=relaxed/simple; bh=xGTQ2WxSwNbRChqdoLcpbr1XSoWncCwPF77/rQ5wj+8=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=txhA7urblbD5qm9wqc+v10Pf5PtZAUvPp/Y+mt8fpXCHHsIRPhuEvWtpArNrRIHppPRK4Thv/ofEnM5H26/GyY3O8JvzopYDmCJdbgt57dVvybaPSSRwY3BDrXLHaMLoqToCjhmI1GUrOro3XHKOFsYge+ERNxNdoXZkr0Xy63Y= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=ti.com; spf=pass smtp.mailfrom=ti.com; dkim=pass (1024-bit key) header.d=ti.com header.i=@ti.com header.b=zFch3yMt; arc=none smtp.client-ip=198.47.23.234 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=ti.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=ti.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=ti.com header.i=@ti.com header.b="zFch3yMt" Received: from fllvem-sh03.itg.ti.com ([10.64.41.86]) by lelvem-ot01.ext.ti.com (8.15.2/8.15.2) with ESMTP id 56N83Xpw1231534; Wed, 23 Jul 2025 03:03:33 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ti.com; s=ti-com-17Q1; t=1753257813; bh=HKrrFVQiYMI4gsrlFoRJ16NAJ6J7Bacvcx8aV6fKN6I=; h=From:To:CC:Subject:Date:In-Reply-To:References; b=zFch3yMtIBW2qOCqN/reQ+EXjwibCOyMFU7eYuoVfcGpyX4PBugmQiSw5nQaPmF3B 7Il96yp/zZ+v2nu2cd51Y79jIFqU7IumvQc2Ej1/8yGUpvR+AIjaLgMOKSFbX17FAP qBZGzHZFtyPv8MJPY+lKGXFGxKXqcBOU6KuSWgr0= Received: from DLEE102.ent.ti.com (dlee102.ent.ti.com [157.170.170.32]) by fllvem-sh03.itg.ti.com (8.18.1/8.18.1) with ESMTPS id 56N83Wvg1619119 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-SHA256 bits=128 verify=FAIL); Wed, 23 Jul 2025 03:03:32 -0500 Received: from DLEE114.ent.ti.com (157.170.170.25) by DLEE102.ent.ti.com (157.170.170.32) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.2507.55; Wed, 23 Jul 2025 03:03:32 -0500 Received: from fllvem-mr08.itg.ti.com (10.64.41.88) by DLEE114.ent.ti.com (157.170.170.25) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.2507.55 via Frontend Transport; Wed, 23 Jul 2025 03:03:32 -0500 Received: from fllv0122.itg.ti.com (fllv0122.itg.ti.com [10.247.120.72]) by fllvem-mr08.itg.ti.com (8.18.1/8.18.1) with ESMTP id 56N83WDN072253; Wed, 23 Jul 2025 03:03:32 -0500 Received: from localhost (danish-tpc.dhcp.ti.com [10.24.69.25]) by fllv0122.itg.ti.com (8.14.7/8.14.7) with ESMTP id 56N83VQZ015951; Wed, 23 Jul 2025 03:03:31 -0500 From: MD Danish Anwar To: "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Simon Horman , Jonathan Corbet , Andrew Lunn , Mengyuan Lou , MD Danish Anwar , Michael Ellerman , Madhavan Srinivasan , Fan Gong , Lee Trager , Lorenzo Bianconi , Geert Uytterhoeven , Lukas Bulwahn , Parthiban Veerasooran CC: , , Subject: [PATCH net-next 2/5] net: rpmsg-eth: Add basic rpmsg skeleton Date: Wed, 23 Jul 2025 13:33:19 +0530 Message-ID: <20250723080322.3047826-3-danishanwar@ti.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20250723080322.3047826-1-danishanwar@ti.com> References: <20250723080322.3047826-1-danishanwar@ti.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-C2ProcessedOrg: 333ef613-75bf-4e12-a4b1-8e3623f5dcea Content-Type: text/plain; charset="utf-8" This patch introduces a basic RPMSG Ethernet driver skeleton. It adds support for creating virtual Ethernet devices over RPMSG channels, allowing user-space programs to send and receive messages using a standard Ethernet protocol. The driver includes message handling, probe, and remove functions, along with necessary data structures. Signed-off-by: MD Danish Anwar --- drivers/net/ethernet/Kconfig | 10 +++ drivers/net/ethernet/Makefile | 1 + drivers/net/ethernet/rpmsg_eth.c | 128 +++++++++++++++++++++++++++++++ drivers/net/ethernet/rpmsg_eth.h | 75 ++++++++++++++++++ 4 files changed, 214 insertions(+) create mode 100644 drivers/net/ethernet/rpmsg_eth.c create mode 100644 drivers/net/ethernet/rpmsg_eth.h diff --git a/drivers/net/ethernet/Kconfig b/drivers/net/ethernet/Kconfig index f86d4557d8d7..a73a45a9ef3d 100644 --- a/drivers/net/ethernet/Kconfig +++ b/drivers/net/ethernet/Kconfig @@ -170,6 +170,16 @@ config OA_TC6 To know the implementation details, refer documentation in . =20 +config RPMSG_ETH + tristate "RPMsg Based Virtual Ethernet driver" + depends on RPMSG + help + This makes it possible for user-space programs to send and receive + rpmsg messages as a standard eth protocol. + + To compile this driver as a module, choose M here: the module will be + called rpmsg_eth. + source "drivers/net/ethernet/packetengines/Kconfig" source "drivers/net/ethernet/pasemi/Kconfig" source "drivers/net/ethernet/pensando/Kconfig" diff --git a/drivers/net/ethernet/Makefile b/drivers/net/ethernet/Makefile index 67182339469a..aebd15993e3c 100644 --- a/drivers/net/ethernet/Makefile +++ b/drivers/net/ethernet/Makefile @@ -107,3 +107,4 @@ obj-$(CONFIG_NET_VENDOR_XIRCOM) +=3D xircom/ obj-$(CONFIG_NET_VENDOR_SYNOPSYS) +=3D synopsys/ obj-$(CONFIG_NET_VENDOR_PENSANDO) +=3D pensando/ obj-$(CONFIG_OA_TC6) +=3D oa_tc6.o +obj-$(CONFIG_RPMSG_ETH) +=3D rpmsg_eth.o diff --git a/drivers/net/ethernet/rpmsg_eth.c b/drivers/net/ethernet/rpmsg_= eth.c new file mode 100644 index 000000000000..9a51619f9313 --- /dev/null +++ b/drivers/net/ethernet/rpmsg_eth.c @@ -0,0 +1,128 @@ +// SPDX-License-Identifier: GPL-2.0 +/* RPMsg Based Virtual Ethernet Driver + * + * Copyright (C) 2024 Texas Instruments Incorporated - https://www.ti.com/ + */ + +#include +#include "rpmsg_eth.h" + +static int rpmsg_eth_rpmsg_cb(struct rpmsg_device *rpdev, void *data, int = len, + void *priv, u32 src) +{ + struct rpmsg_eth_common *common =3D dev_get_drvdata(&rpdev->dev); + struct message *msg =3D (struct message *)data; + u32 msg_type =3D msg->msg_hdr.msg_type; + int ret =3D 0; + + switch (msg_type) { + case RPMSG_ETH_REQUEST_MSG: + case RPMSG_ETH_RESPONSE_MSG: + case RPMSG_ETH_NOTIFY_MSG: + dev_dbg(common->dev, "Msg type =3D %d, Src Id =3D %d\n", + msg_type, msg->msg_hdr.src_id); + break; + default: + dev_err(common->dev, "Invalid msg type\n"); + ret =3D -EINVAL; + break; + } + return ret; +} + +/** + * rpmsg_eth_get_shm_info - Get shared memory info from device tree + * @common: Pointer to rpmsg_eth_common structure + * + * Return: 0 on success, negative error code on failure + */ +static int rpmsg_eth_get_shm_info(struct rpmsg_eth_common *common) +{ + struct device_node *peer; + const __be32 *reg; + u64 start_address; + int prop_size; + int reg_len; + u64 size; + + peer =3D of_find_node_by_name(NULL, "virtual-eth-shm"); + if (!peer) { + dev_err(common->dev, "Couldn't get shared mem node"); + return -ENODEV; + } + + reg =3D of_get_property(peer, "reg", &prop_size); + if (!reg) { + dev_err(common->dev, "Couldn't get reg property"); + return -ENODEV; + } + + reg_len =3D prop_size / sizeof(u32); + + if (reg_len =3D=3D 2) { + /* 32-bit address space */ + start_address =3D be32_to_cpu(reg[0]); + size =3D be32_to_cpu(reg[1]); + } else if (reg_len =3D=3D 4) { + /* 64-bit address space */ + start_address =3D ((u64)be32_to_cpu(reg[0]) << 32) | + be32_to_cpu(reg[1]); + size =3D ((u64)be32_to_cpu(reg[2]) << 32) | + be32_to_cpu(reg[3]); + } else { + dev_err(common->dev, "Invalid reg_len: %d\n", reg_len); + return -EINVAL; + } + + common->port->buf_start_addr =3D start_address; + common->port->buf_size =3D size; + + return 0; +} + +static int rpmsg_eth_probe(struct rpmsg_device *rpdev) +{ + struct device *dev =3D &rpdev->dev; + struct rpmsg_eth_common *common; + int ret =3D 0; + + common =3D devm_kzalloc(&rpdev->dev, sizeof(*common), GFP_KERNEL); + if (!common) + return -ENOMEM; + + dev_set_drvdata(dev, common); + + common->port =3D devm_kzalloc(dev, sizeof(*common->port), GFP_KERNEL); + common->dev =3D dev; + common->rpdev =3D rpdev; + + ret =3D rpmsg_eth_get_shm_info(common); + if (ret) + return ret; + + return 0; +} + +static void rpmsg_eth_rpmsg_remove(struct rpmsg_device *rpdev) +{ + dev_dbg(&rpdev->dev, "rpmsg-eth client driver is removed\n"); +} + +static struct rpmsg_device_id rpmsg_eth_rpmsg_id_table[] =3D { + { .name =3D "shm-eth" }, + {}, +}; +MODULE_DEVICE_TABLE(rpmsg, rpmsg_eth_rpmsg_id_table); + +static struct rpmsg_driver rpmsg_eth_rpmsg_client =3D { + .drv.name =3D KBUILD_MODNAME, + .id_table =3D rpmsg_eth_rpmsg_id_table, + .probe =3D rpmsg_eth_probe, + .callback =3D rpmsg_eth_rpmsg_cb, + .remove =3D rpmsg_eth_rpmsg_remove, +}; +module_rpmsg_driver(rpmsg_eth_rpmsg_client); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("MD Danish Anwar "); +MODULE_DESCRIPTION("RPMsg Based Virtual Ethernet driver"); diff --git a/drivers/net/ethernet/rpmsg_eth.h b/drivers/net/ethernet/rpmsg_= eth.h new file mode 100644 index 000000000000..56dabd139643 --- /dev/null +++ b/drivers/net/ethernet/rpmsg_eth.h @@ -0,0 +1,75 @@ +/* SPDX-License-Identifier: GPL-2.0 + * Texas Instruments K3 Inter Core Virtual Ethernet Driver common header + * + * Copyright (C) 2024 Texas Instruments Incorporated - https://www.ti.com/ + */ + +#ifndef __RPMSG_ETH_H__ +#define __RPMSG_ETH_H__ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define RPMSG_ETH_SHM_MAGIC_NUM 0xABCDABCD + +enum rpmsg_eth_msg_type { + RPMSG_ETH_REQUEST_MSG =3D 0, + RPMSG_ETH_RESPONSE_MSG, + RPMSG_ETH_NOTIFY_MSG, +}; + +/** + * struct message_header - message header structure for RPMSG Ethernet + * @src_id: Source endpoint ID + * @msg_type: Message type + */ +struct message_header { + u32 src_id; + u32 msg_type; +} __packed; + +/** + * struct message - RPMSG Ethernet message structure + * + * @msg_hdr: Message header contains source and destination endpoint and + * the type of message + * + * This structure is used to send and receive messages between the RPMSG + * Ethernet ports. + */ +struct message { + struct message_header msg_hdr; +} __packed; + +/** + * struct rpmsg_eth_common - common structure for RPMSG Ethernet + * @rpdev: RPMSG device + * @port: Ethernet port + * @dev: Device + */ +struct rpmsg_eth_common { + struct rpmsg_device *rpdev; + struct rpmsg_eth_port *port; + struct device *dev; +}; + +/** + * struct rpmsg_eth_port - Ethernet port structure for RPMSG Ethernet + * @common: Pointer to the common RPMSG Ethernet structure + * @buf_start_addr: Start address of the shared memory buffer for this port + * @buf_size: Size (in bytes) of the shared memory buffer for this port + */ +struct rpmsg_eth_port { + struct rpmsg_eth_common *common; + u32 buf_start_addr; + u32 buf_size; +}; + +#endif /* __RPMSG_ETH_H__ */ --=20 2.34.1 From nobody Mon Oct 6 08:30:17 2025 Received: from fllvem-ot04.ext.ti.com (fllvem-ot04.ext.ti.com [198.47.19.246]) (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 6A55727A135; Wed, 23 Jul 2025 08:04:14 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.47.19.246 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1753257856; cv=none; b=OnE/1zJS7vY30Nu/kLK0CQflFz1TpJS4fZXUB7uuuAU8oiehDF6znUpDpZzDbTj00C1/RNOItCs8BjrcGefcfdyrupdwVFUUPfA0PmXK6g0GaCtfgYGhY+FZVhyLx4UDbHDkTVeotd0M7ZAR3DJwvYVVtBL/JEql64+hBY/FIYk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1753257856; c=relaxed/simple; bh=mu9vJrbVW6pLW0y6TlYod3MetdqgGWeuGGWBxEjrAzs=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=hhcG7noYZcSX8xLTueACyHdk8udTVOAX4rz2jZKYwHzVSyShkMH47PglgwNDWgtVePWxB4KVOovKN4etkqkvaODrchf+m7E3E7yDQX6S4mT/StiIqbJVOB1I7i4zufH8PFMODlIg4uS/ZINIb1LNeJ8ZZ1xCeH1WucmI2rKU86M= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=ti.com; spf=pass smtp.mailfrom=ti.com; dkim=pass (1024-bit key) header.d=ti.com header.i=@ti.com header.b=jNmNN4aJ; arc=none smtp.client-ip=198.47.19.246 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=ti.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=ti.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=ti.com header.i=@ti.com header.b="jNmNN4aJ" Received: from fllvem-sh03.itg.ti.com ([10.64.41.86]) by fllvem-ot04.ext.ti.com (8.15.2/8.15.2) with ESMTP id 56N83Znu1676451; Wed, 23 Jul 2025 03:03:35 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ti.com; s=ti-com-17Q1; t=1753257815; bh=J7Pw2c7pQUrc6QTEN0gXmSfzT3FzaWnjufqPB8NQJlA=; h=From:To:CC:Subject:Date:In-Reply-To:References; b=jNmNN4aJQ297TJ5n3CaM2RGk0QEpBzKCmfkES3RxJ8tUO1xpoMwcDABsDwEIx9Iv2 zsos9QA0bo63VM4c05sohC7rSeZIXuUAf01ewZmZ21uaUhZZZlmo2ZY8hQ30eZhDrr +fhWUu2BikAXcffj5BARhvrcNedYOATjcEQAAB8U= Received: from DFLE102.ent.ti.com (dfle102.ent.ti.com [10.64.6.23]) by fllvem-sh03.itg.ti.com (8.18.1/8.18.1) with ESMTPS id 56N83ZTn1619141 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-SHA256 bits=128 verify=FAIL); Wed, 23 Jul 2025 03:03:35 -0500 Received: from DFLE114.ent.ti.com (10.64.6.35) by DFLE102.ent.ti.com (10.64.6.23) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.2507.55; Wed, 23 Jul 2025 03:03:34 -0500 Received: from lelvem-mr06.itg.ti.com (10.180.75.8) by DFLE114.ent.ti.com (10.64.6.35) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.2507.55 via Frontend Transport; Wed, 23 Jul 2025 03:03:34 -0500 Received: from fllv0122.itg.ti.com (fllv0122.itg.ti.com [10.247.120.72]) by lelvem-mr06.itg.ti.com (8.18.1/8.18.1) with ESMTP id 56N83YPv2365941; Wed, 23 Jul 2025 03:03:34 -0500 Received: from localhost (danish-tpc.dhcp.ti.com [10.24.69.25]) by fllv0122.itg.ti.com (8.14.7/8.14.7) with ESMTP id 56N83XNa015985; Wed, 23 Jul 2025 03:03:34 -0500 From: MD Danish Anwar To: "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Simon Horman , Jonathan Corbet , Andrew Lunn , Mengyuan Lou , MD Danish Anwar , Michael Ellerman , Madhavan Srinivasan , Fan Gong , Lee Trager , Lorenzo Bianconi , Geert Uytterhoeven , Lukas Bulwahn , Parthiban Veerasooran CC: , , Subject: [PATCH net-next 3/5] net: rpmsg-eth: Register device as netdev Date: Wed, 23 Jul 2025 13:33:20 +0530 Message-ID: <20250723080322.3047826-4-danishanwar@ti.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20250723080322.3047826-1-danishanwar@ti.com> References: <20250723080322.3047826-1-danishanwar@ti.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-C2ProcessedOrg: 333ef613-75bf-4e12-a4b1-8e3623f5dcea Content-Type: text/plain; charset="utf-8" Register the rpmsg-eth device as a netdev and enhance the rpmsg callback function to handle shared memory for tx and rx buffers. Introduce structures for shared memory layout, including head, buffer, and tail indices. Add initialization for the netdev, including setting up MAC address, MTU, and netdev operations. Allocate memory for tx and rx buffers and map shared memory regions. Update the probe function to initialize the netdev and set the device state. Add necessary headers, constants, and enums for shared memory and state management. Define shared memory layout and buffer structures for efficient data handling. Implement helper macros for accessing private data and shared memory buffers. Ensure proper error handling during memory allocation and device registration. Signed-off-by: MD Danish Anwar --- drivers/net/ethernet/rpmsg_eth.c | 239 ++++++++++++++++++++++++++++++- drivers/net/ethernet/rpmsg_eth.h | 216 ++++++++++++++++++++++++++++ 2 files changed, 452 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/rpmsg_eth.c b/drivers/net/ethernet/rpmsg_= eth.c index 9a51619f9313..26f9eee6aeec 100644 --- a/drivers/net/ethernet/rpmsg_eth.c +++ b/drivers/net/ethernet/rpmsg_eth.c @@ -7,20 +7,173 @@ #include #include "rpmsg_eth.h" =20 +/** + * rpmsg_eth_validate_handshake - Validate handshake parameters from remote + * @port: Pointer to rpmsg_eth_port structure + * @shm_info: Pointer to shared memory info received from remote + * + * Checks the magic numbers, base address, and TX/RX offsets in the handsh= ake + * response to ensure they match expected values and are within valid rang= es. + * + * Return: 0 on success, -EINVAL on validation failure. + */ +static int rpmsg_eth_validate_handshake(struct rpmsg_eth_port *port, + struct rpmsg_eth_shm *shm_info) +{ + if (port->tx_buffer->head->magic_num !=3D RPMSG_ETH_SHM_MAGIC_NUM || + port->tx_buffer->tail->magic_num !=3D RPMSG_ETH_SHM_MAGIC_NUM || + port->rx_buffer->head->magic_num !=3D RPMSG_ETH_SHM_MAGIC_NUM || + port->rx_buffer->tail->magic_num !=3D RPMSG_ETH_SHM_MAGIC_NUM) { + dev_err(port->common->dev, "Magic number mismatch in handshake: tx_head= =3D0x%x, tx_tail=3D0x%x, rx_head=3D0x%x, rx_tail=3D0x%x\n", + port->tx_buffer->head->magic_num, + port->tx_buffer->tail->magic_num, + port->rx_buffer->head->magic_num, + port->rx_buffer->tail->magic_num); + return -EINVAL; + } + + if (shm_info->base_addr !=3D port->buf_start_addr) { + dev_err(port->common->dev, "Base address mismatch in handshake: expected= =3D0x%x, received=3D0x%x\n", + port->buf_start_addr, + shm_info->base_addr); + return -EINVAL; + } + + if (shm_info->tx_offset >=3D port->buf_size || + shm_info->rx_offset >=3D port->buf_size) { + dev_err(port->common->dev, "TX/RX offset out of range in handshake: tx_o= ffset=3D0x%x, rx_offset=3D0x%x, size=3D0x%x\n", + shm_info->tx_offset, + shm_info->rx_offset, + port->buf_size); + return -EINVAL; + } + + return 0; +} + +static void rpmsg_eth_map_buffers(struct rpmsg_eth_port *port, + struct message *msg) +{ + port->tx_buffer->head =3D + (struct rpmsg_eth_shm_index __force *) + (ioremap(msg->resp_msg.shm_info.base_addr + + msg->resp_msg.shm_info.tx_offset, + sizeof(*port->tx_buffer->head))); + + port->tx_buffer->buf->base_addr =3D + ioremap((msg->resp_msg.shm_info.base_addr + + msg->resp_msg.shm_info.tx_offset + + sizeof(*port->tx_buffer->head)), + (msg->resp_msg.shm_info.num_pkt_bufs * + msg->resp_msg.shm_info.buff_slot_size)); + + port->tx_buffer->tail =3D + (struct rpmsg_eth_shm_index __force *) + (ioremap(msg->resp_msg.shm_info.base_addr + + msg->resp_msg.shm_info.tx_offset + + sizeof(*port->tx_buffer->head) + + (msg->resp_msg.shm_info.num_pkt_bufs * + msg->resp_msg.shm_info.buff_slot_size), + sizeof(*port->tx_buffer->tail))); + + port->rx_buffer->head =3D + (struct rpmsg_eth_shm_index __force *) + (ioremap(msg->resp_msg.shm_info.base_addr + + msg->resp_msg.shm_info.rx_offset, + sizeof(*port->rx_buffer->head))); + + port->rx_buffer->buf->base_addr =3D + ioremap(msg->resp_msg.shm_info.base_addr + + msg->resp_msg.shm_info.rx_offset + + sizeof(*port->rx_buffer->head), + (msg->resp_msg.shm_info.num_pkt_bufs * + msg->resp_msg.shm_info.buff_slot_size)); + + port->rx_buffer->tail =3D + (struct rpmsg_eth_shm_index __force *) + (ioremap(msg->resp_msg.shm_info.base_addr + + msg->resp_msg.shm_info.rx_offset + + sizeof(*port->rx_buffer->head) + + (msg->resp_msg.shm_info.num_pkt_bufs * + msg->resp_msg.shm_info.buff_slot_size), + sizeof(*port->rx_buffer->tail))); +} + +static void rpmsg_eth_unmap_buffers(struct rpmsg_eth_port *port) +{ + if (port->tx_buffer && port->tx_buffer->head) { + iounmap((void __iomem *)port->tx_buffer->head); + port->tx_buffer->head =3D NULL; + } + if (port->tx_buffer && port->tx_buffer->buf && + port->tx_buffer->buf->base_addr) { + iounmap((void __iomem *)port->tx_buffer->buf->base_addr); + port->tx_buffer->buf->base_addr =3D NULL; + } + if (port->tx_buffer && port->tx_buffer->tail) { + iounmap((void __iomem *)port->tx_buffer->tail); + port->tx_buffer->tail =3D NULL; + } + + if (port->rx_buffer && port->rx_buffer->head) { + iounmap((void __iomem *)port->rx_buffer->head); + port->rx_buffer->head =3D NULL; + } + if (port->rx_buffer && port->rx_buffer->buf && + port->rx_buffer->buf->base_addr) { + iounmap((void __iomem *)port->rx_buffer->buf->base_addr); + port->rx_buffer->buf->base_addr =3D NULL; + } + if (port->rx_buffer && port->rx_buffer->tail) { + iounmap((void __iomem *)port->rx_buffer->tail); + port->rx_buffer->tail =3D NULL; + } +} + static int rpmsg_eth_rpmsg_cb(struct rpmsg_device *rpdev, void *data, int = len, void *priv, u32 src) { struct rpmsg_eth_common *common =3D dev_get_drvdata(&rpdev->dev); struct message *msg =3D (struct message *)data; + struct rpmsg_eth_port *port =3D common->port; u32 msg_type =3D msg->msg_hdr.msg_type; + u32 rpmsg_type; int ret =3D 0; =20 switch (msg_type) { case RPMSG_ETH_REQUEST_MSG: + rpmsg_type =3D msg->req_msg.type; + dev_dbg(common->dev, "Msg type =3D %d, RPMsg type =3D %d, Src Id =3D %d,= Msg Id =3D %d\n", + msg_type, rpmsg_type, msg->msg_hdr.src_id, msg->req_msg.id); + break; case RPMSG_ETH_RESPONSE_MSG: + rpmsg_type =3D msg->resp_msg.type; + dev_dbg(common->dev, "Msg type =3D %d, RPMsg type =3D %d, Src Id =3D %d,= Msg Id =3D %d\n", + msg_type, rpmsg_type, msg->msg_hdr.src_id, msg->resp_msg.id); + switch (rpmsg_type) { + case RPMSG_ETH_RESP_SHM_INFO: + /* Retrieve Tx and Rx shared memory info from msg */ + rpmsg_eth_map_buffers(port, msg); + + port->rpmsg_eth_tx_max_buffers =3D + msg->resp_msg.shm_info.num_pkt_bufs; + port->rpmsg_eth_rx_max_buffers =3D + msg->resp_msg.shm_info.num_pkt_bufs; + + /* Handshake validation */ + ret =3D rpmsg_eth_validate_handshake(port, &msg->resp_msg.shm_info); + if (ret) { + dev_err(common->dev, "RPMSG handshake failed %d\n", ret); + rpmsg_eth_unmap_buffers(port); + return ret; + } + break; + } + break; case RPMSG_ETH_NOTIFY_MSG: - dev_dbg(common->dev, "Msg type =3D %d, Src Id =3D %d\n", - msg_type, msg->msg_hdr.src_id); + rpmsg_type =3D msg->notify_msg.type; + dev_dbg(common->dev, "Msg type =3D %d, RPMsg type =3D %d, Src Id =3D %d,= Msg Id =3D %d\n", + msg_type, rpmsg_type, msg->msg_hdr.src_id, msg->notify_msg.id); break; default: dev_err(common->dev, "Invalid msg type\n"); @@ -80,6 +233,76 @@ static int rpmsg_eth_get_shm_info(struct rpmsg_eth_comm= on *common) return 0; } =20 +static int rpmsg_eth_init_ndev(struct rpmsg_eth_common *common) +{ + struct device *dev =3D &common->rpdev->dev; + struct rpmsg_eth_ndev_priv *ndev_priv; + struct rpmsg_eth_port *port; + static u32 port_id; + int err; + + port =3D common->port; + port->common =3D common; + port->port_id =3D port_id++; + + port->ndev =3D devm_alloc_etherdev_mqs(common->dev, sizeof(*ndev_priv), + RPMSG_ETH_MAX_TX_QUEUES, + RPMSG_ETH_MAX_RX_QUEUES); + + if (!port->ndev) { + dev_err(dev, "error allocating net_device\n"); + return -ENOMEM; + } + + ndev_priv =3D netdev_priv(port->ndev); + ndev_priv->port =3D port; + SET_NETDEV_DEV(port->ndev, dev); + + port->ndev->min_mtu =3D RPMSG_ETH_MIN_PACKET_SIZE; + port->ndev->max_mtu =3D MAX_MTU; + + if (!is_valid_ether_addr(port->ndev->dev_addr)) { + eth_hw_addr_random(port->ndev); + dev_dbg(dev, "Using random MAC address %pM\n", port->ndev->dev_addr); + } + + /* Allocate memory to test without actual RPMsg handshaking */ + port->tx_buffer =3D + devm_kzalloc(dev, sizeof(*port->tx_buffer), GFP_KERNEL); + if (!port->tx_buffer) { + dev_err(dev, "Memory not available\n"); + return -ENOMEM; + } + + port->tx_buffer->buf =3D + devm_kzalloc(dev, sizeof(*port->tx_buffer->buf), GFP_KERNEL); + if (!port->tx_buffer->buf) { + dev_err(dev, "Memory not available\n"); + return -ENOMEM; + } + + port->rx_buffer =3D + devm_kzalloc(dev, sizeof(*port->rx_buffer), GFP_KERNEL); + if (!port->rx_buffer) { + dev_err(dev, "Memory not available\n"); + return -ENOMEM; + } + + port->rx_buffer->buf =3D + devm_kzalloc(dev, sizeof(*port->rx_buffer->buf), GFP_KERNEL); + if (!port->rx_buffer->buf) { + dev_err(dev, "Memory not available\n"); + return -ENOMEM; + } + netif_carrier_off(port->ndev); + + err =3D register_netdev(port->ndev); + + if (err) + dev_err(dev, "error registering rpmsg_eth net device %d\n", err); + return 0; +} + static int rpmsg_eth_probe(struct rpmsg_device *rpdev) { struct device *dev =3D &rpdev->dev; @@ -95,17 +318,27 @@ static int rpmsg_eth_probe(struct rpmsg_device *rpdev) common->port =3D devm_kzalloc(dev, sizeof(*common->port), GFP_KERNEL); common->dev =3D dev; common->rpdev =3D rpdev; + common->state =3D RPMSG_ETH_STATE_PROBE; =20 ret =3D rpmsg_eth_get_shm_info(common); if (ret) return ret; =20 + /* Register the network device */ + ret =3D rpmsg_eth_init_ndev(common); + if (ret) + return ret; + return 0; } =20 static void rpmsg_eth_rpmsg_remove(struct rpmsg_device *rpdev) { - dev_dbg(&rpdev->dev, "rpmsg-eth client driver is removed\n"); + struct rpmsg_eth_common *common =3D dev_get_drvdata(&rpdev->dev); + struct rpmsg_eth_port *port =3D common->port; + + /* Unmap ioremap'd regions */ + rpmsg_eth_unmap_buffers(port); } =20 static struct rpmsg_device_id rpmsg_eth_rpmsg_id_table[] =3D { diff --git a/drivers/net/ethernet/rpmsg_eth.h b/drivers/net/ethernet/rpmsg_= eth.h index 56dabd139643..aa43030f3d72 100644 --- a/drivers/net/ethernet/rpmsg_eth.h +++ b/drivers/net/ethernet/rpmsg_eth.h @@ -18,6 +18,27 @@ #include =20 #define RPMSG_ETH_SHM_MAGIC_NUM 0xABCDABCD +#define RPMSG_ETH_MIN_PACKET_SIZE ETH_ZLEN +#define RPMSG_ETH_PACKET_BUFFER_SIZE 1540 +#define MAX_MTU (RPMSG_ETH_PACKET_BUFFER_SIZE - (ETH_HLEN + ETH_FCS_LEN = + VLAN_HLEN)) + +#define RPMSG_ETH_MAX_TX_QUEUES 1 +#define RPMSG_ETH_MAX_RX_QUEUES 1 +#define PKT_LEN_SIZE_TYPE sizeof(u32) +#define MAGIC_NUM_SIZE_TYPE sizeof(u32) + +/* 4 bytes to hold packet length and RPMSG_ETH_PACKET_BUFFER_SIZE to hold = packet */ +#define RPMSG_ETH_BUFFER_SIZE \ + (RPMSG_ETH_PACKET_BUFFER_SIZE + PKT_LEN_SIZE_TYPE + MAGIC_NUM_SIZE_TYPE) + +#define RX_POLL_TIMEOUT_JIFFIES usecs_to_jiffies(1000) +#define RX_POLL_JIFFIES (jiffies + RX_POLL_TIMEOUT_JIFFIES) +#define STATE_MACHINE_TIME_JIFFIES msecs_to_jiffies(100) +#define RPMSG_ETH_REQ_TIMEOUT_JIFFIES msecs_to_jiffies(100) + +#define rpmsg_eth_ndev_to_priv(ndev) ((struct rpmsg_eth_ndev_priv *)netdev= _priv(ndev)) +#define rpmsg_eth_ndev_to_port(ndev) (rpmsg_eth_ndev_to_priv(ndev)->port) +#define rpmsg_eth_ndev_to_common(ndev) (rpmsg_eth_ndev_to_port(ndev)->comm= on) =20 enum rpmsg_eth_msg_type { RPMSG_ETH_REQUEST_MSG =3D 0, @@ -25,6 +46,89 @@ enum rpmsg_eth_msg_type { RPMSG_ETH_NOTIFY_MSG, }; =20 +enum rpmsg_eth_rpmsg_type { + /* Request types */ + RPMSG_ETH_REQ_SHM_INFO =3D 0, + RPMSG_ETH_REQ_SET_MAC_ADDR, + + /* Response types */ + RPMSG_ETH_RESP_SHM_INFO, + RPMSG_ETH_RESP_SET_MAC_ADDR, + + /* Notification types */ + RPMSG_ETH_NOTIFY_PORT_UP, + RPMSG_ETH_NOTIFY_PORT_DOWN, + RPMSG_ETH_NOTIFY_PORT_READY, + RPMSG_ETH_NOTIFY_REMOTE_READY, +}; + +/** + * struct rpmsg_eth_shm - Shared memory layout for RPMsg Ethernet + * @num_pkt_bufs: Number of packet buffers available in the shared memory + * @buff_slot_size: Size of each buffer slot in bytes + * @base_addr: Base address of the shared memory region + * @tx_offset: Offset for the transmit buffer region within the shared mem= ory + * @rx_offset: Offset for the receive buffer region within the shared memo= ry + * + * This structure defines the layout of the shared memory used for + * communication between the host and the remote processor in an RPMsg + * Ethernet driver. It specifies the configuration and memory offsets + * required for transmitting and receiving Ethernet packets. + */ +struct rpmsg_eth_shm { + u32 num_pkt_bufs; + u32 buff_slot_size; + u32 base_addr; + u32 tx_offset; + u32 rx_offset; +} __packed; + +/** + * struct rpmsg_eth_mac_addr - MAC address information for RPMSG Ethernet + * @addr: MAC address + */ +struct rpmsg_eth_mac_addr { + char addr[ETH_ALEN]; +} __packed; + +/** + * struct request_message - request message structure for RPMSG Ethernet + * @type: Request Type + * @id: Request ID + * @mac_addr: MAC address (if request type is MAC address related) + */ +struct request_message { + u32 type; + u32 id; + union { + struct rpmsg_eth_mac_addr mac_addr; + }; +} __packed; + +/** + * struct response_message - response message structure for RPMSG Ethernet + * @type: Response Type + * @id: Response ID + * @shm_info: rpmsg shared memory info + */ +struct response_message { + u32 type; + u32 id; + union { + struct rpmsg_eth_shm shm_info; + }; +} __packed; + +/** + * struct notify_message - notification message structure for RPMSG Ethern= et + * @type: Notify Type + * @id: Notify ID + */ +struct notify_message { + u32 type; + u32 id; +} __packed; + /** * struct message_header - message header structure for RPMSG Ethernet * @src_id: Source endpoint ID @@ -40,22 +144,116 @@ struct message_header { * * @msg_hdr: Message header contains source and destination endpoint and * the type of message + * @req_msg: Request message structure contains the request type and ID + * @resp_msg: Response message structure contains the response type and ID + * @notify_msg: Notification message structure contains the notify type an= d ID * * This structure is used to send and receive messages between the RPMSG * Ethernet ports. */ struct message { struct message_header msg_hdr; + union { + struct request_message req_msg; + struct response_message resp_msg; + struct notify_message notify_msg; + }; +} __packed; + +/* Shared Memory Layout + * + * --------------------------- ***************** + * | MAGIC_NUM | rpmsg_eth_shm_head + * | HEAD | + * --------------------------- ***************** + * | MAGIC_NUM | + * | PKT_1_LEN | + * | PKT_1 | + * --------------------------- + * | MAGIC_NUM | + * | PKT_2_LEN | rpmsg_eth_shm_buf + * | PKT_2 | + * --------------------------- + * | . | + * | . | + * --------------------------- + * | MAGIC_NUM | + * | PKT_N_LEN | + * | PKT_N | + * --------------------------- **************** + * | MAGIC_NUM | rpmsg_eth_shm_tail + * | TAIL | + * --------------------------- **************** + */ + +struct rpmsg_eth_shm_index { + u32 magic_num; + u32 index; +} __packed; + +/** + * struct rpmsg_eth_shm_buf - shared memory buffer structure for RPMSG Eth= ernet + * @base_addr: Base address of the buffer + * @magic_num: Magic number for buffer validation + */ +struct rpmsg_eth_shm_buf { + void __iomem *base_addr; + u32 magic_num; +} __packed; + +/** + * struct rpmsg_eth_shared_mem - shared memory structure for RPMSG Ethernet + * @head: Head of the shared memory + * @buf: Buffer of the shared memory + * @tail: Tail of the shared memory + */ +struct rpmsg_eth_shared_mem { + struct rpmsg_eth_shm_index *head; + struct rpmsg_eth_shm_buf *buf; + struct rpmsg_eth_shm_index *tail; } __packed; =20 +enum rpmsg_eth_state { + RPMSG_ETH_STATE_PROBE, + RPMSG_ETH_STATE_OPEN, + RPMSG_ETH_STATE_CLOSE, + RPMSG_ETH_STATE_READY, + RPMSG_ETH_STATE_RUNNING, + +}; + /** * struct rpmsg_eth_common - common structure for RPMSG Ethernet * @rpdev: RPMSG device + * @send_msg: Send message + * @recv_msg: Receive message * @port: Ethernet port * @dev: Device + * @state: Interface state + * @state_work: Delayed work for state machine */ struct rpmsg_eth_common { struct rpmsg_device *rpdev; + /** @send_msg_lock: Lock for sending RPMSG */ + spinlock_t send_msg_lock; + /** @recv_msg_lock: Lock for receiving RPMSG */ + spinlock_t recv_msg_lock; + struct message send_msg; + struct message recv_msg; + struct rpmsg_eth_port *port; + struct device *dev; + enum rpmsg_eth_state state; + /** @state_lock: Lock for changing interface state */ + struct mutex state_lock; + struct delayed_work state_work; +}; + +/** + * struct rpmsg_eth_ndev_priv - private structure for RPMSG Ethernet net d= evice + * @port: Ethernet port + * @dev: Device + */ +struct rpmsg_eth_ndev_priv { struct rpmsg_eth_port *port; struct device *dev; }; @@ -65,11 +263,29 @@ struct rpmsg_eth_common { * @common: Pointer to the common RPMSG Ethernet structure * @buf_start_addr: Start address of the shared memory buffer for this port * @buf_size: Size (in bytes) of the shared memory buffer for this port + * @tx_buffer: Write buffer for data to be consumed by remote side + * @rx_buffer: Read buffer for data to be consumed by this driver + * @rx_timer: Timer for rx polling + * @rx_napi: NAPI structure for rx polling + * @local_mac_addr: Local MAC address + * @ndev: Network device + * @rpmsg_eth_tx_max_buffers: Maximum number of tx buffers + * @rpmsg_eth_rx_max_buffers: Maximum number of rx buffers + * @port_id: Port ID */ struct rpmsg_eth_port { struct rpmsg_eth_common *common; u32 buf_start_addr; u32 buf_size; + struct rpmsg_eth_shared_mem *tx_buffer; + struct rpmsg_eth_shared_mem *rx_buffer; + struct timer_list rx_timer; + struct napi_struct rx_napi; + u8 local_mac_addr[ETH_ALEN]; + struct net_device *ndev; + u32 rpmsg_eth_tx_max_buffers; + u32 rpmsg_eth_rx_max_buffers; + u32 port_id; }; =20 #endif /* __RPMSG_ETH_H__ */ --=20 2.34.1 From nobody Mon Oct 6 08:30:17 2025 Received: from fllvem-ot03.ext.ti.com (fllvem-ot03.ext.ti.com [198.47.19.245]) (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 2C4E927A12C; Wed, 23 Jul 2025 08:04:13 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.47.19.245 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1753257856; cv=none; b=Ho8WUZPIlyk2QQtFo9WoWVemRK5bQ+SphJszijtFdX6szLS5WY4Zoj8mi/22qjya1jMcJAYe87Z4ksawaiM0uaDKxsDFALSwjf5bh0UHcOD6cXWhjQoaNClLTVEw4ZDXK5J5ng/MqrvAMP78Av5Rgjyysoh+E1Lr4hwb2xm0Th0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1753257856; c=relaxed/simple; bh=Byab61WjMDYnAwBBhTk8h7ZIULStJN65B+0eQwvduFA=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=NupgAFVwiejGiYDSLFYMMcvokhYh8w8r+LEvk4SXzji2wLYq2+1hyBBNxX15kCVEhaOqp1r9DwIWDvO8QEaz6sVg5WgX2ZgCNRdcjons5pc3EUrAf3oWotfhVmifLiccIus1Y5jBzKMc5eKSmLRzfr51jCSCBe2Gts1EB/55RuI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=ti.com; spf=pass smtp.mailfrom=ti.com; dkim=pass (1024-bit key) header.d=ti.com header.i=@ti.com header.b=vTzo1LiX; arc=none smtp.client-ip=198.47.19.245 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=ti.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=ti.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=ti.com header.i=@ti.com header.b="vTzo1LiX" Received: from lelvem-sh01.itg.ti.com ([10.180.77.71]) by fllvem-ot03.ext.ti.com (8.15.2/8.15.2) with ESMTP id 56N83b4f1223412; Wed, 23 Jul 2025 03:03:37 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ti.com; s=ti-com-17Q1; t=1753257817; bh=NanDPG3eGNw9XC4l/hPEFH2QVadmc7khxeTagmYKGvg=; h=From:To:CC:Subject:Date:In-Reply-To:References; b=vTzo1LiX04NauhzWdJVl8cWqeDByuGbQxw5DuELtvToKTW5UhbZlLow7/5f6pjU6b ZaiNS5DUhG2tiCMtJWjtZUR+iVk47z6Rr2+2u9EKPvtz1lKNMqOqcKPlN0bIvnKkks ueDzwGGHrlzQ2t41toock1ex14RjB//QSswcw5eA= Received: from DFLE105.ent.ti.com (dfle105.ent.ti.com [10.64.6.26]) by lelvem-sh01.itg.ti.com (8.18.1/8.18.1) with ESMTPS id 56N83bws553849 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-SHA256 bits=128 verify=FAIL); Wed, 23 Jul 2025 03:03:37 -0500 Received: from DFLE114.ent.ti.com (10.64.6.35) by DFLE105.ent.ti.com (10.64.6.26) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.2507.55; Wed, 23 Jul 2025 03:03:36 -0500 Received: from lelvem-mr06.itg.ti.com (10.180.75.8) by DFLE114.ent.ti.com (10.64.6.35) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.2507.55 via Frontend Transport; Wed, 23 Jul 2025 03:03:37 -0500 Received: from fllv0122.itg.ti.com (fllv0122.itg.ti.com [10.247.120.72]) by lelvem-mr06.itg.ti.com (8.18.1/8.18.1) with ESMTP id 56N83bVd2366006; Wed, 23 Jul 2025 03:03:37 -0500 Received: from localhost (danish-tpc.dhcp.ti.com [10.24.69.25]) by fllv0122.itg.ti.com (8.14.7/8.14.7) with ESMTP id 56N83ZRo015995; Wed, 23 Jul 2025 03:03:36 -0500 From: MD Danish Anwar To: "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Simon Horman , Jonathan Corbet , Andrew Lunn , Mengyuan Lou , MD Danish Anwar , Michael Ellerman , Madhavan Srinivasan , Fan Gong , Lee Trager , Lorenzo Bianconi , Geert Uytterhoeven , Lukas Bulwahn , Parthiban Veerasooran CC: , , Subject: [PATCH net-next 4/5] net: rpmsg-eth: Add netdev ops Date: Wed, 23 Jul 2025 13:33:21 +0530 Message-ID: <20250723080322.3047826-5-danishanwar@ti.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20250723080322.3047826-1-danishanwar@ti.com> References: <20250723080322.3047826-1-danishanwar@ti.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-C2ProcessedOrg: 333ef613-75bf-4e12-a4b1-8e3623f5dcea Content-Type: text/plain; charset="utf-8" Add netdev ops for rpmsg-eth driver. This patch introduces the netdev operations for the rpmsg-eth driver, enabling the driver to interact with the Linux networking stack. The following functionalities are implemented: 1. `ndo_open` and `ndo_stop`: - Handles the initialization and cleanup of the network device during open and stop operations. - Manages the state transitions of the rpmsg-eth driver. 2. `ndo_start_xmit`: - Implements the transmit functionality by copying data from the skb to the shared memory buffer and updating the head index. 3. `ndo_set_mac_address`: - Allows setting the MAC address of the network device and sends the updated MAC address to the remote processor. 4. RX Path: - Adds a timer-based mechanism to poll for received packets in shared memory. - Implements NAPI-based packet processing to handle received packets efficiently. 5. State Machine: - Introduces a state machine to manage the driver's state transitions, such as PROBE, OPEN, READY, and RUNNING. 6. Initialization: - Adds necessary initialization for locks, timers, and work structures. - Registers the network device and sets up NAPI and RX timer. 7. Cleanup: - Ensures proper cleanup of resources during driver removal, including NAPI and timers. This patch enhances the rpmsg-eth driver to function as a fully operational network device in the Linux kernel. Signed-off-by: MD Danish Anwar --- drivers/net/ethernet/rpmsg_eth.c | 319 +++++++++++++++++++++++++++++++ drivers/net/ethernet/rpmsg_eth.h | 2 + 2 files changed, 321 insertions(+) diff --git a/drivers/net/ethernet/rpmsg_eth.c b/drivers/net/ethernet/rpmsg_= eth.c index 26f9eee6aeec..4efa9b634f8b 100644 --- a/drivers/net/ethernet/rpmsg_eth.c +++ b/drivers/net/ethernet/rpmsg_eth.c @@ -130,6 +130,109 @@ static void rpmsg_eth_unmap_buffers(struct rpmsg_eth_= port *port) } } =20 +static int create_request(struct rpmsg_eth_common *common, + enum rpmsg_eth_rpmsg_type rpmsg_type) +{ + struct message *msg =3D &common->send_msg; + int ret =3D 0; + + msg->msg_hdr.src_id =3D common->port->port_id; + msg->req_msg.type =3D rpmsg_type; + + switch (rpmsg_type) { + case RPMSG_ETH_REQ_SHM_INFO: + msg->msg_hdr.msg_type =3D RPMSG_ETH_REQUEST_MSG; + break; + case RPMSG_ETH_REQ_SET_MAC_ADDR: + msg->msg_hdr.msg_type =3D RPMSG_ETH_REQUEST_MSG; + ether_addr_copy(msg->req_msg.mac_addr.addr, + common->port->ndev->dev_addr); + break; + case RPMSG_ETH_NOTIFY_PORT_UP: + case RPMSG_ETH_NOTIFY_PORT_DOWN: + msg->msg_hdr.msg_type =3D RPMSG_ETH_NOTIFY_MSG; + break; + default: + ret =3D -EINVAL; + dev_err(common->dev, "Invalid RPMSG request\n"); + } + return ret; +} + +static int rpmsg_eth_create_send_request(struct rpmsg_eth_common *common, + enum rpmsg_eth_rpmsg_type rpmsg_type, + bool wait) +{ + unsigned long flags; + int ret =3D 0; + + if (wait) + reinit_completion(&common->sync_msg); + + spin_lock_irqsave(&common->send_msg_lock, flags); + ret =3D create_request(common, rpmsg_type); + if (ret) + goto release_lock; + + ret =3D rpmsg_send(common->rpdev->ept, (void *)(&common->send_msg), + sizeof(common->send_msg)); + if (ret) { + dev_err(common->dev, "Failed to send RPMSG message\n"); + goto release_lock; + } + + spin_unlock_irqrestore(&common->send_msg_lock, flags); + if (wait) { + ret =3D wait_for_completion_timeout(&common->sync_msg, + RPMSG_ETH_REQ_TIMEOUT_JIFFIES); + + if (!ret) { + dev_err(common->dev, "Failed to receive response within %ld jiffies\n", + RPMSG_ETH_REQ_TIMEOUT_JIFFIES); + return -ETIMEDOUT; + } + ret =3D 0; + } + return ret; +release_lock: + spin_unlock_irqrestore(&common->send_msg_lock, flags); + return ret; +} + +static void rpmsg_eth_state_machine(struct work_struct *work) +{ + struct delayed_work *dwork =3D to_delayed_work(work); + struct rpmsg_eth_common *common; + struct rpmsg_eth_port *port; + int ret; + + common =3D container_of(dwork, struct rpmsg_eth_common, state_work); + port =3D common->port; + + mutex_lock(&common->state_lock); + + switch (common->state) { + case RPMSG_ETH_STATE_PROBE: + break; + case RPMSG_ETH_STATE_OPEN: + rpmsg_eth_create_send_request(common, RPMSG_ETH_REQ_SHM_INFO, false); + break; + case RPMSG_ETH_STATE_CLOSE: + break; + case RPMSG_ETH_STATE_READY: + ret =3D rpmsg_eth_create_send_request(common, RPMSG_ETH_REQ_SET_MAC_ADDR= , false); + if (!ret) { + napi_enable(&port->rx_napi); + netif_carrier_on(port->ndev); + mod_timer(&port->rx_timer, RX_POLL_TIMEOUT_JIFFIES); + } + break; + case RPMSG_ETH_STATE_RUNNING: + break; + } + mutex_unlock(&common->state_lock); +} + static int rpmsg_eth_rpmsg_cb(struct rpmsg_device *rpdev, void *data, int = len, void *priv, u32 src) { @@ -167,6 +270,17 @@ static int rpmsg_eth_rpmsg_cb(struct rpmsg_device *rpd= ev, void *data, int len, rpmsg_eth_unmap_buffers(port); return ret; } + + mutex_lock(&common->state_lock); + common->state =3D RPMSG_ETH_STATE_READY; + mutex_unlock(&common->state_lock); + + mod_delayed_work(system_wq, + &common->state_work, + STATE_MACHINE_TIME_JIFFIES); + + break; + case RPMSG_ETH_RESP_SET_MAC_ADDR: break; } break; @@ -174,6 +288,20 @@ static int rpmsg_eth_rpmsg_cb(struct rpmsg_device *rpd= ev, void *data, int len, rpmsg_type =3D msg->notify_msg.type; dev_dbg(common->dev, "Msg type =3D %d, RPMsg type =3D %d, Src Id =3D %d,= Msg Id =3D %d\n", msg_type, rpmsg_type, msg->msg_hdr.src_id, msg->notify_msg.id); + switch (rpmsg_type) { + case RPMSG_ETH_NOTIFY_REMOTE_READY: + mutex_lock(&common->state_lock); + common->state =3D RPMSG_ETH_STATE_RUNNING; + mutex_unlock(&common->state_lock); + + mod_delayed_work(system_wq, + &common->state_work, + STATE_MACHINE_TIME_JIFFIES); + break; + case RPMSG_ETH_NOTIFY_PORT_UP: + case RPMSG_ETH_NOTIFY_PORT_DOWN: + break; + } break; default: dev_err(common->dev, "Invalid msg type\n"); @@ -233,6 +361,185 @@ static int rpmsg_eth_get_shm_info(struct rpmsg_eth_co= mmon *common) return 0; } =20 +static void rpmsg_eth_rx_timer(struct timer_list *timer) +{ + struct rpmsg_eth_port *port =3D timer_container_of(port, timer, rx_timer); + struct napi_struct *napi; + int num_pkts =3D 0; + u32 head, tail; + + head =3D port->rx_buffer->head->index; + tail =3D port->rx_buffer->tail->index; + + num_pkts =3D tail - head; + num_pkts =3D num_pkts >=3D 0 ? num_pkts : + (num_pkts + port->rpmsg_eth_rx_max_buffers); + + napi =3D &port->rx_napi; + if (num_pkts && likely(napi_schedule_prep(napi))) + __napi_schedule(napi); + else + mod_timer(&port->rx_timer, RX_POLL_JIFFIES); +} + +static int rpmsg_eth_rx_packets(struct napi_struct *napi, int budget) +{ + struct rpmsg_eth_port *port =3D container_of(napi, struct rpmsg_eth_port,= rx_napi); + u32 count, process_pkts; + struct sk_buff *skb; + u32 head, tail; + int num_pkts; + u32 pkt_len; + + head =3D port->rx_buffer->head->index; + tail =3D port->rx_buffer->tail->index; + + num_pkts =3D head - tail; + + num_pkts =3D num_pkts >=3D 0 ? num_pkts : + (num_pkts + port->rpmsg_eth_rx_max_buffers); + process_pkts =3D min(num_pkts, budget); + count =3D 0; + while (count < process_pkts) { + memcpy_fromio((void *)&pkt_len, + (void __iomem *)(port->rx_buffer->buf->base_addr + + MAGIC_NUM_SIZE_TYPE + + (((tail + count) % port->rpmsg_eth_rx_max_buffers) * + RPMSG_ETH_BUFFER_SIZE)), + PKT_LEN_SIZE_TYPE); + /* Start building the skb */ + skb =3D napi_alloc_skb(napi, pkt_len); + if (!skb) { + port->ndev->stats.rx_dropped++; + goto rx_dropped; + } + + skb->dev =3D port->ndev; + skb_put(skb, pkt_len); + memcpy_fromio((void *)skb->data, + (void __iomem *)(port->rx_buffer->buf->base_addr + + PKT_LEN_SIZE_TYPE + MAGIC_NUM_SIZE_TYPE + + (((tail + count) % port->rpmsg_eth_rx_max_buffers) * + RPMSG_ETH_BUFFER_SIZE)), + pkt_len); + + skb->protocol =3D eth_type_trans(skb, port->ndev); + + /* Push skb into network stack */ + napi_gro_receive(napi, skb); + + count++; + port->ndev->stats.rx_packets++; + port->ndev->stats.rx_bytes +=3D skb->len; + } + +rx_dropped: + + if (num_pkts) { + port->rx_buffer->tail->index =3D + (port->rx_buffer->tail->index + count) % + port->rpmsg_eth_rx_max_buffers; + + if (num_pkts < budget && napi_complete_done(napi, count)) + mod_timer(&port->rx_timer, RX_POLL_TIMEOUT_JIFFIES); + } + + return count; +} + +static int rpmsg_eth_ndo_open(struct net_device *ndev) +{ + struct rpmsg_eth_common *common =3D rpmsg_eth_ndev_to_common(ndev); + + mutex_lock(&common->state_lock); + common->state =3D RPMSG_ETH_STATE_OPEN; + mutex_unlock(&common->state_lock); + mod_delayed_work(system_wq, &common->state_work, msecs_to_jiffies(100)); + + return 0; +} + +static int rpmsg_eth_ndo_stop(struct net_device *ndev) +{ + struct rpmsg_eth_common *common =3D rpmsg_eth_ndev_to_common(ndev); + struct rpmsg_eth_port *port =3D rpmsg_eth_ndev_to_port(ndev); + + mutex_lock(&common->state_lock); + common->state =3D RPMSG_ETH_STATE_CLOSE; + mutex_unlock(&common->state_lock); + + netif_carrier_off(port->ndev); + + cancel_delayed_work_sync(&common->state_work); + timer_delete_sync(&port->rx_timer); + napi_disable(&port->rx_napi); + + return 0; +} + +static netdev_tx_t rpmsg_eth_start_xmit(struct sk_buff *skb, struct net_de= vice *ndev) +{ + struct rpmsg_eth_port *port =3D rpmsg_eth_ndev_to_port(ndev); + u32 head, tail; + int num_pkts; + u32 len; + + len =3D skb_headlen(skb); + head =3D port->tx_buffer->head->index; + tail =3D port->tx_buffer->tail->index; + + /* If the buffer queue is full, then drop packet */ + num_pkts =3D head - tail; + num_pkts =3D num_pkts >=3D 0 ? num_pkts : + (num_pkts + port->rpmsg_eth_tx_max_buffers); + + if ((num_pkts + 1) =3D=3D port->rpmsg_eth_tx_max_buffers) { + netdev_warn(ndev, "Tx buffer full %d\n", num_pkts); + goto ring_full; + } + /* Copy length */ + memcpy_toio((void __iomem *)port->tx_buffer->buf->base_addr + + MAGIC_NUM_SIZE_TYPE + + (port->tx_buffer->head->index * RPMSG_ETH_BUFFER_SIZE), + (void *)&len, PKT_LEN_SIZE_TYPE); + /* Copy data to shared mem */ + memcpy_toio((void __iomem *)(port->tx_buffer->buf->base_addr + + MAGIC_NUM_SIZE_TYPE + PKT_LEN_SIZE_TYPE + + (port->tx_buffer->head->index * RPMSG_ETH_BUFFER_SIZE)), + (void *)skb->data, len); + port->tx_buffer->head->index =3D + (port->tx_buffer->head->index + 1) % port->rpmsg_eth_tx_max_buffers; + + ndev->stats.tx_packets++; + ndev->stats.tx_bytes +=3D skb->len; + + dev_consume_skb_any(skb); + return NETDEV_TX_OK; + +ring_full: + return NETDEV_TX_BUSY; +} + +static int rpmsg_eth_set_mac_address(struct net_device *ndev, void *addr) +{ + struct rpmsg_eth_common *common =3D rpmsg_eth_ndev_to_common(ndev); + int ret; + + ret =3D eth_mac_addr(ndev, addr); + + if (ret < 0) + return ret; + ret =3D rpmsg_eth_create_send_request(common, RPMSG_ETH_REQ_SET_MAC_ADDR,= false); + return ret; +} + +static const struct net_device_ops rpmsg_eth_netdev_ops =3D { + .ndo_open =3D rpmsg_eth_ndo_open, + .ndo_stop =3D rpmsg_eth_ndo_stop, + .ndo_start_xmit =3D rpmsg_eth_start_xmit, + .ndo_set_mac_address =3D rpmsg_eth_set_mac_address, +}; + static int rpmsg_eth_init_ndev(struct rpmsg_eth_common *common) { struct device *dev =3D &common->rpdev->dev; @@ -256,6 +563,7 @@ static int rpmsg_eth_init_ndev(struct rpmsg_eth_common = *common) =20 ndev_priv =3D netdev_priv(port->ndev); ndev_priv->port =3D port; + port->ndev->netdev_ops =3D &rpmsg_eth_netdev_ops; SET_NETDEV_DEV(port->ndev, dev); =20 port->ndev->min_mtu =3D RPMSG_ETH_MIN_PACKET_SIZE; @@ -296,6 +604,8 @@ static int rpmsg_eth_init_ndev(struct rpmsg_eth_common = *common) } netif_carrier_off(port->ndev); =20 + netif_napi_add(port->ndev, &port->rx_napi, rpmsg_eth_rx_packets); + timer_setup(&port->rx_timer, rpmsg_eth_rx_timer, 0); err =3D register_netdev(port->ndev); =20 if (err) @@ -324,6 +634,12 @@ static int rpmsg_eth_probe(struct rpmsg_device *rpdev) if (ret) return ret; =20 + spin_lock_init(&common->send_msg_lock); + spin_lock_init(&common->recv_msg_lock); + mutex_init(&common->state_lock); + INIT_DELAYED_WORK(&common->state_work, rpmsg_eth_state_machine); + init_completion(&common->sync_msg); + /* Register the network device */ ret =3D rpmsg_eth_init_ndev(common); if (ret) @@ -339,6 +655,9 @@ static void rpmsg_eth_rpmsg_remove(struct rpmsg_device = *rpdev) =20 /* Unmap ioremap'd regions */ rpmsg_eth_unmap_buffers(port); + + netif_napi_del(&port->rx_napi); + timer_delete_sync(&port->rx_timer); } =20 static struct rpmsg_device_id rpmsg_eth_rpmsg_id_table[] =3D { diff --git a/drivers/net/ethernet/rpmsg_eth.h b/drivers/net/ethernet/rpmsg_= eth.h index aa43030f3d72..d7e4d53c8de4 100644 --- a/drivers/net/ethernet/rpmsg_eth.h +++ b/drivers/net/ethernet/rpmsg_eth.h @@ -231,6 +231,7 @@ enum rpmsg_eth_state { * @dev: Device * @state: Interface state * @state_work: Delayed work for state machine + * @sync_msg: Completion for synchronous message */ struct rpmsg_eth_common { struct rpmsg_device *rpdev; @@ -246,6 +247,7 @@ struct rpmsg_eth_common { /** @state_lock: Lock for changing interface state */ struct mutex state_lock; struct delayed_work state_work; + struct completion sync_msg; }; =20 /** --=20 2.34.1 From nobody Mon Oct 6 08:30:17 2025 Received: from fllvem-ot03.ext.ti.com (fllvem-ot03.ext.ti.com [198.47.19.245]) (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 DF871279795; Wed, 23 Jul 2025 08:04:15 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.47.19.245 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1753257857; cv=none; b=ge51aatmMX5v9X2WHx2BVpQtpCIVOI3zQQUWCfO26VZPZxEIiaz0kYTg4UVc6vqTWmEHmt4jysqLyNpHKQZFXn79KFchWnohzKSVrQmWSIsiY37OrNqLEVPKy2R2GfzyyqgILaCczlFGlCE/c8BubVB6OnayJ42M1CweYb+eq3I= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1753257857; c=relaxed/simple; bh=Rq8CWf3AxoYslKrBl8R2+0dVi1ZfoIP+gkHNSZ+MeKc=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=CTo402KVuDvq4GQBYzUhOlSTF/JtgTXfZ/I/mIvrxJxolqV8MINMLdlOgp5EhyeBC5BzJaOnXRYkSF3G5pA/bOB+RBVjKORf//vVqUD1Hs/0JymAXbyMyaOekgzPqH02wfitTKoKX1wUSTL/1a+40YrMrgKPQMj8+hIdPrbbK8g= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=ti.com; spf=pass smtp.mailfrom=ti.com; dkim=pass (1024-bit key) header.d=ti.com header.i=@ti.com header.b=YWz1RfaZ; arc=none smtp.client-ip=198.47.19.245 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=ti.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=ti.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=ti.com header.i=@ti.com header.b="YWz1RfaZ" Received: from fllvem-sh04.itg.ti.com ([10.64.41.54]) by fllvem-ot03.ext.ti.com (8.15.2/8.15.2) with ESMTP id 56N83ej81223420; Wed, 23 Jul 2025 03:03:40 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ti.com; s=ti-com-17Q1; t=1753257820; bh=exLzVkguk6cycSbD88736Px3AndF6YoZ9kK3pIxDvEY=; h=From:To:CC:Subject:Date:In-Reply-To:References; b=YWz1RfaZ6hic28j0p0ng4q1xYW01IvB+9VtkBqQGoCrsuehNm8jFuMBKysFlhNeV3 5u0yDufKNwOzWvb9vezThO1LGXYQ/hnbYtF/K5ijn27S/3DXgpGbPgkDCAca12r+s+ f2LN3UmF0Gl7YJH8raZOgHPLqxG+xOkZfWNdsFTk= Received: from DFLE101.ent.ti.com (dfle101.ent.ti.com [10.64.6.22]) by fllvem-sh04.itg.ti.com (8.18.1/8.18.1) with ESMTPS id 56N83e9N2219311 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-SHA256 bits=128 verify=FAIL); Wed, 23 Jul 2025 03:03:40 -0500 Received: from DFLE109.ent.ti.com (10.64.6.30) by DFLE101.ent.ti.com (10.64.6.22) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.2507.55; Wed, 23 Jul 2025 03:03:39 -0500 Received: from lelvem-mr06.itg.ti.com (10.180.75.8) by DFLE109.ent.ti.com (10.64.6.30) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.2507.55 via Frontend Transport; Wed, 23 Jul 2025 03:03:39 -0500 Received: from fllv0122.itg.ti.com (fllv0122.itg.ti.com [10.247.120.72]) by lelvem-mr06.itg.ti.com (8.18.1/8.18.1) with ESMTP id 56N83dgO2366059; Wed, 23 Jul 2025 03:03:39 -0500 Received: from localhost (danish-tpc.dhcp.ti.com [10.24.69.25]) by fllv0122.itg.ti.com (8.14.7/8.14.7) with ESMTP id 56N83cwT016007; Wed, 23 Jul 2025 03:03:38 -0500 From: MD Danish Anwar To: "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Simon Horman , Jonathan Corbet , Andrew Lunn , Mengyuan Lou , MD Danish Anwar , Michael Ellerman , Madhavan Srinivasan , Fan Gong , Lee Trager , Lorenzo Bianconi , Geert Uytterhoeven , Lukas Bulwahn , Parthiban Veerasooran CC: , , Subject: [PATCH net-next 5/5] net: rpmsg-eth: Add support for multicast filtering Date: Wed, 23 Jul 2025 13:33:22 +0530 Message-ID: <20250723080322.3047826-6-danishanwar@ti.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20250723080322.3047826-1-danishanwar@ti.com> References: <20250723080322.3047826-1-danishanwar@ti.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-C2ProcessedOrg: 333ef613-75bf-4e12-a4b1-8e3623f5dcea Content-Type: text/plain; charset="utf-8" Add support for multicast filtering for ICVE driver. Implement the ndo_set_rx_mode callback as icve_set_rx_mode() API. rx_mode_workqueue is initialized in icve_rpmsg_probe() and queued in icve_set_rx_mode(). Signed-off-by: MD Danish Anwar --- drivers/net/ethernet/rpmsg_eth.c | 63 ++++++++++++++++++++++++++++++++ drivers/net/ethernet/rpmsg_eth.h | 12 ++++++ 2 files changed, 75 insertions(+) diff --git a/drivers/net/ethernet/rpmsg_eth.c b/drivers/net/ethernet/rpmsg_= eth.c index 4efa9b634f8b..a77fc4f3f769 100644 --- a/drivers/net/ethernet/rpmsg_eth.c +++ b/drivers/net/ethernet/rpmsg_eth.c @@ -148,6 +148,11 @@ static int create_request(struct rpmsg_eth_common *com= mon, ether_addr_copy(msg->req_msg.mac_addr.addr, common->port->ndev->dev_addr); break; + case RPMSG_ETH_REQ_ADD_MC_ADDR: + case RPMSG_ETH_REQ_DEL_MC_ADDR: + ether_addr_copy(msg->req_msg.mac_addr.addr, + common->mcast_addr); + break; case RPMSG_ETH_NOTIFY_PORT_UP: case RPMSG_ETH_NOTIFY_PORT_DOWN: msg->msg_hdr.msg_type =3D RPMSG_ETH_NOTIFY_MSG; @@ -199,6 +204,22 @@ static int rpmsg_eth_create_send_request(struct rpmsg_= eth_common *common, return ret; } =20 +static int rpmsg_eth_add_mc_addr(struct net_device *ndev, const u8 *addr) +{ + struct rpmsg_eth_common *common =3D rpmsg_eth_ndev_to_common(ndev); + + ether_addr_copy(common->mcast_addr, addr); + return rpmsg_eth_create_send_request(common, RPMSG_ETH_REQ_ADD_MC_ADDR, t= rue); +} + +static int rpmsg_eth_del_mc_addr(struct net_device *ndev, const u8 *addr) +{ + struct rpmsg_eth_common *common =3D rpmsg_eth_ndev_to_common(ndev); + + ether_addr_copy(common->mcast_addr, addr); + return rpmsg_eth_create_send_request(common, RPMSG_ETH_REQ_DEL_MC_ADDR, t= rue); +} + static void rpmsg_eth_state_machine(struct work_struct *work) { struct delayed_work *dwork =3D to_delayed_work(work); @@ -282,6 +303,10 @@ static int rpmsg_eth_rpmsg_cb(struct rpmsg_device *rpd= ev, void *data, int len, break; case RPMSG_ETH_RESP_SET_MAC_ADDR: break; + case RPMSG_ETH_RESP_ADD_MC_ADDR: + case RPMSG_ETH_RESP_DEL_MC_ADDR: + complete(&common->sync_msg); + break; } break; case RPMSG_ETH_NOTIFY_MSG: @@ -470,10 +495,15 @@ static int rpmsg_eth_ndo_stop(struct net_device *ndev) =20 netif_carrier_off(port->ndev); =20 + __dev_mc_unsync(ndev, rpmsg_eth_del_mc_addr); + __hw_addr_init(&common->mc_list); + cancel_delayed_work_sync(&common->state_work); timer_delete_sync(&port->rx_timer); napi_disable(&port->rx_napi); =20 + cancel_work_sync(&common->rx_mode_work); + return 0; } =20 @@ -533,10 +563,35 @@ static int rpmsg_eth_set_mac_address(struct net_devic= e *ndev, void *addr) return ret; } =20 +static void rpmsg_eth_ndo_set_rx_mode_work(struct work_struct *work) +{ + struct rpmsg_eth_common *common; + struct net_device *ndev; + + common =3D container_of(work, struct rpmsg_eth_common, rx_mode_work); + ndev =3D common->port->ndev; + + /* make a mc list copy */ + netif_addr_lock_bh(ndev); + __hw_addr_sync(&common->mc_list, &ndev->mc, ndev->addr_len); + netif_addr_unlock_bh(ndev); + + __hw_addr_sync_dev(&common->mc_list, ndev, rpmsg_eth_add_mc_addr, + rpmsg_eth_del_mc_addr); +} + +static void rpmsg_eth_set_rx_mode(struct net_device *ndev) +{ + struct rpmsg_eth_common *common =3D rpmsg_eth_ndev_to_common(ndev); + + queue_work(common->cmd_wq, &common->rx_mode_work); +} + static const struct net_device_ops rpmsg_eth_netdev_ops =3D { .ndo_open =3D rpmsg_eth_ndo_open, .ndo_stop =3D rpmsg_eth_ndo_stop, .ndo_start_xmit =3D rpmsg_eth_start_xmit, + .ndo_set_rx_mode =3D rpmsg_eth_set_rx_mode, .ndo_set_mac_address =3D rpmsg_eth_set_mac_address, }; =20 @@ -640,6 +695,13 @@ static int rpmsg_eth_probe(struct rpmsg_device *rpdev) INIT_DELAYED_WORK(&common->state_work, rpmsg_eth_state_machine); init_completion(&common->sync_msg); =20 + __hw_addr_init(&common->mc_list); + INIT_WORK(&common->rx_mode_work, rpmsg_eth_ndo_set_rx_mode_work); + common->cmd_wq =3D create_singlethread_workqueue("rpmsg_eth_rx_work"); + if (!common->cmd_wq) { + dev_err(dev, "Failure requesting workqueue\n"); + return -ENOMEM; + } /* Register the network device */ ret =3D rpmsg_eth_init_ndev(common); if (ret) @@ -658,6 +720,7 @@ static void rpmsg_eth_rpmsg_remove(struct rpmsg_device = *rpdev) =20 netif_napi_del(&port->rx_napi); timer_delete_sync(&port->rx_timer); + destroy_workqueue(common->cmd_wq); } =20 static struct rpmsg_device_id rpmsg_eth_rpmsg_id_table[] =3D { diff --git a/drivers/net/ethernet/rpmsg_eth.h b/drivers/net/ethernet/rpmsg_= eth.h index d7e4d53c8de4..5ff1a0e57c37 100644 --- a/drivers/net/ethernet/rpmsg_eth.h +++ b/drivers/net/ethernet/rpmsg_eth.h @@ -50,10 +50,14 @@ enum rpmsg_eth_rpmsg_type { /* Request types */ RPMSG_ETH_REQ_SHM_INFO =3D 0, RPMSG_ETH_REQ_SET_MAC_ADDR, + RPMSG_ETH_REQ_ADD_MC_ADDR, + RPMSG_ETH_REQ_DEL_MC_ADDR, =20 /* Response types */ RPMSG_ETH_RESP_SHM_INFO, RPMSG_ETH_RESP_SET_MAC_ADDR, + RPMSG_ETH_RESP_ADD_MC_ADDR, + RPMSG_ETH_RESP_DEL_MC_ADDR, =20 /* Notification types */ RPMSG_ETH_NOTIFY_PORT_UP, @@ -232,6 +236,10 @@ enum rpmsg_eth_state { * @state: Interface state * @state_work: Delayed work for state machine * @sync_msg: Completion for synchronous message + * @rx_mode_work: Work structure for rx mode + * @cmd_wq: Workqueue for commands + * @mc_list: List of multicast addresses + * @mcast_addr: Multicast address filter */ struct rpmsg_eth_common { struct rpmsg_device *rpdev; @@ -248,6 +256,10 @@ struct rpmsg_eth_common { struct mutex state_lock; struct delayed_work state_work; struct completion sync_msg; + struct work_struct rx_mode_work; + struct workqueue_struct *cmd_wq; + struct netdev_hw_addr_list mc_list; + u8 mcast_addr[ETH_ALEN]; }; =20 /** --=20 2.34.1