Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* Re: [PATCH] media: imx-jpeg: avoid double free on video register failure
From: Mirela Rabulea @ 2026-05-25 14:04 UTC (permalink / raw)
  To: Guangshuo Li, Mauro Carvalho Chehab, Frank Li, Sascha Hauer,
	Pengutronix Kernel Team, Fabio Estevam, Hans Verkuil, imx,
	linux-media, linux-arm-kernel, linux-kernel
In-Reply-To: <20260518130259.1001956-1-lgs201920130244@gmail.com>

> [You don't often get email from lgs201920130244@gmail.com. Learn why this is important at https://aka.ms/LearnAboutSenderIdentification ]
>
> Caution: This is an external email. Please take care when clicking links or opening attachments. When in doubt, report the message using the 'Report this email' button
>
>
> mxc_jpeg_probe() allocates a video_device with video_device_alloc() and
> releases it from the err_vdev_register error path if
> video_register_device() fails.
>
> This can double free the video_device when __video_register_device()
> reaches device_register() and that call fails:
>
>    video_register_device()
>      -> __video_register_device()
>         -> device_register() fails
>            -> put_device(&vdev->dev)
>               -> v4l2_device_release()
>                  -> vdev->release(vdev)
>                     -> video_device_release(vdev)
>
>    mxc_jpeg_probe()
>      -> err_vdev_register
>         -> video_device_release(jpeg->dec_vdev)
>
> Use video_device_release_empty() while registering the device so that
> registration failure paths do not free jpeg->dec_vdev through
> vdev->release(). mxc_jpeg_probe() then releases jpeg->dec_vdev exactly
> once from err_vdev_register. Restore video_device_release() after
> successful registration so the registered device keeps its normal lifetime
> handling.
>
> This issue was found by a static analysis tool I am developing.
>
> Fixes: 2db16c6ed72c ("media: imx-jpeg: Add V4L2 driver for i.MX8 JPEG Encoder/Decoder")
> Signed-off-by: Guangshuo Li <lgs201920130244@gmail.com>

Hi Guangshuo,

sorry for the late response, so I assume this patch will be dropped in 
favor of a fix in v4l2-core, as per discussions here?:

https://lore.kernel.org/linux-media/20260519090819.1041314-1-lgs201920130244@gmail.com/

Thanks,

Mirela

> ---
>   drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c | 4 +++-
>   1 file changed, 3 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c b/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c
> index b442dcba02e7..fe8a373576ef 100644
> --- a/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c
> +++ b/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c
> @@ -2943,7 +2943,7 @@ static int mxc_jpeg_probe(struct platform_device *pdev)
>          jpeg->dec_vdev->fops = &mxc_jpeg_fops;
>          jpeg->dec_vdev->ioctl_ops = &mxc_jpeg_ioctl_ops;
>          jpeg->dec_vdev->minor = -1;
> -       jpeg->dec_vdev->release = video_device_release;
> +       jpeg->dec_vdev->release = video_device_release_empty;
>          jpeg->dec_vdev->lock = &jpeg->lock; /* lock for ioctl serialization */
>          jpeg->dec_vdev->v4l2_dev = &jpeg->v4l2_dev;
>          jpeg->dec_vdev->vfl_dir = VFL_DIR_M2M;
> @@ -2962,6 +2962,8 @@ static int mxc_jpeg_probe(struct platform_device *pdev)
>                  dev_err(dev, "failed to register video device\n");
>                  goto err_vdev_register;
>          }
> +       jpeg->dec_vdev->release = video_device_release;
> +
>          if (mode == MXC_JPEG_ENCODE)
>                  v4l2_info(&jpeg->v4l2_dev,
>                            "encoder device registered as /dev/video%d (%d,%d)\n",
> --
> 2.43.0
>


^ permalink raw reply

* Re: [PATCH v3] Bluetooth: Add Broadcom channel priority commands
From: Joshua Peisach @ 2026-05-25 13:58 UTC (permalink / raw)
  To: Sasha Finkelstein, Sven Peter, Janne Grunau, Neal Gompa,
	Marcel Holtmann, Luiz Augusto von Dentz, David S. Miller,
	Eric Dumazet, Jakub Kicinski, Paolo Abeni, Simon Horman
  Cc: linux-kernel, asahi, linux-arm-kernel, linux-bluetooth, netdev
In-Reply-To: <20260525-brcm-prio-v3-1-6259e10233f8@chaosmail.tech>

On Mon May 25, 2026 at 8:11 AM EDT, Sasha Finkelstein wrote:
> --- /dev/null
> +++ b/net/bluetooth/brcm.c
> @@ -0,0 +1,38 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * Copyright (C) 2026 The Asahi Linux Contributors
> + */
> +
> +#include <net/bluetooth/bluetooth.h>
> +#include <net/bluetooth/hci_core.h>
> +
> +#include "brcm.h"
> +
> +struct brcm_prio_cmd {
> +	__le16 handle;
> +	u8 enable;
> +} __packed;
> +
> +int brcm_set_high_priority(struct hci_dev *hdev, struct hci_conn *conn,
> +			   bool enable)
> +{
> +	struct sk_buff *skb;
> +	struct brcm_prio_cmd cmd;
> +
> +	if (!hdev->brcm_capable)
> +		return 0;
> +
> +	if (conn->brcm_high_prio == enable)
> +		return 0;
> +
> +	cmd.handle = cpu_to_le16(conn->handle);
> +	cmd.enable = !!enable;
> +

Probably a dumb question, but worth asking - what is the purpose of the
"!!"? Wouldn't just passing "enable" be sufficient?

Also, currently, cmd.enable seems to just be set and used in the case
of boolean conditions. Would it make sense for the enable field in
brcm_prio_cmd to be a bool or does it not really matter?

> +	skb = hci_cmd_sync(hdev, 0xfc57, sizeof(cmd), &cmd, HCI_CMD_TIMEOUT);
> +	if (IS_ERR(skb))
> +		return PTR_ERR(skb);
> +
> +	conn->brcm_high_prio = enable;
> +	kfree_skb(skb);
> +	return 0;
> +}
> diff --git a/net/bluetooth/brcm.h b/net/bluetooth/brcm.h
> new file mode 100644
> index 000000000000..2290fc6cf798
> --- /dev/null
> +++ b/net/bluetooth/brcm.h
> @@ -0,0 +1,19 @@
> +/* SPDX-License-Identifier: GPL-2.0-only */
> +/*
> + * Copyright (C) 2026 The Asahi Linux Contributors
> + */
> +
> +#if IS_ENABLED(CONFIG_BT_BRCMEXT)
> +
> +int brcm_set_high_priority(struct hci_dev *hdev, struct hci_conn *conn,
> +			   bool enable);
> +
> +#else
> +
> +static inline int brcm_set_high_priority(struct hci_dev *hdev,
> +					 struct hci_conn *conn, bool enable)
> +{
> +	return 0;
> +}
> +
> +#endif
> diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
> index c46c1236ebfa..0e74bad496a2 100644
> --- a/net/bluetooth/hci_core.c
> +++ b/net/bluetooth/hci_core.c
> @@ -46,6 +46,7 @@
>  #include "msft.h"
>  #include "aosp.h"
>  #include "hci_codec.h"
> +#include "brcm.h"
>  
>  static void hci_rx_work(struct work_struct *work);
>  static void hci_cmd_work(struct work_struct *work);
> @@ -3696,6 +3697,9 @@ static void hci_sched_acl_pkt(struct hci_dev *hdev)
>  
>  			skb = skb_dequeue(&chan->data_q);
>  
> +			if (skb->priority == TC_PRIO_INTERACTIVE)
> +				brcm_set_high_priority(hdev, chan->conn, true);
> +
>  			hci_conn_enter_active_mode(chan->conn,
>  						   bt_cb(skb)->force_active);
>  
>
> ---
> base-commit: 8bc67e4db64aa72732c474b44ea8622062c903f0
> change-id: 20260407-brcm-prio-b630e6cc3834
>
> Best regards,
> --  
> Sasha Finkelstein <k@chaosmail.tech>



^ permalink raw reply

* Re: [PATCH v3] Bluetooth: Add Broadcom channel priority commands
From: Sasha Finkelstein @ 2026-05-25 14:05 UTC (permalink / raw)
  To: Joshua Peisach
  Cc: Sven Peter, Janne Grunau, Neal Gompa, Marcel Holtmann,
	Luiz Augusto von Dentz, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, Simon Horman, linux-kernel, asahi,
	linux-arm-kernel, linux-bluetooth, netdev
In-Reply-To: <DIRT7260SRQZ.1BFF8CX3FJ57G@ubuntu.com>


> On May 25, 2026, at 15:58, Joshua Peisach <jpeisach@ubuntu.com> wrote:
> 
> On Mon May 25, 2026 at 8:11 AM EDT, Sasha Finkelstein wrote:
>> 
>> + cmd.enable = !!enable;
>> +
> 
> Probably a dumb question, but worth asking - what is the purpose of the
> "!!"? Wouldn't just passing "enable" be sufficient?

This is a way to enforce that the value is exactly 0 or 1, not 0 or non-zero.

> 
> Also, currently, cmd.enable seems to just be set and used in the case
> of boolean conditions. Would it make sense for the enable field in
> brcm_prio_cmd to be a bool or does it not really matter?
> 
Opposite, actually, this struct is fed to firmware, and it needs to be
specifically a u8.



^ permalink raw reply

* Re: [PATCH v3] Bluetooth: Add Broadcom channel priority commands
From: Joshua Peisach @ 2026-05-25 14:07 UTC (permalink / raw)
  To: Sasha Finkelstein, Joshua Peisach
  Cc: Sven Peter, Janne Grunau, Neal Gompa, Marcel Holtmann,
	Luiz Augusto von Dentz, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, Simon Horman, linux-kernel, asahi,
	linux-arm-kernel, linux-bluetooth, netdev
In-Reply-To: <172D11E7-AF98-43F8-B41B-907738749EA5@chaosmail.tech>

On Mon May 25, 2026 at 10:05 AM EDT, Sasha Finkelstein wrote:
>
>> On May 25, 2026, at 15:58, Joshua Peisach <jpeisach@ubuntu.com> wrote:
>> 
>> On Mon May 25, 2026 at 8:11 AM EDT, Sasha Finkelstein wrote:
>>> 
>>> + cmd.enable = !!enable;
>>> +
>> 
>> Probably a dumb question, but worth asking - what is the purpose of the
>> "!!"? Wouldn't just passing "enable" be sufficient?
>
> This is a way to enforce that the value is exactly 0 or 1, not 0 or non-zero.
>
>> 
>> Also, currently, cmd.enable seems to just be set and used in the case
>> of boolean conditions. Would it make sense for the enable field in
>> brcm_prio_cmd to be a bool or does it not really matter?
>> 
> Opposite, actually, this struct is fed to firmware, and it needs to be
> specifically a u8.

Got it, thanks!

Reviewed-by: Joshua Peisach <jpeisach@ubuntu.com>


^ permalink raw reply

* Re: [PATCH v2 0/2] Add dynamic CSU register sysfs interface
From: Michal Simek @ 2026-05-25 14:09 UTC (permalink / raw)
  To: Ronak Jain, senthilnathan.thangaraj; +Cc: linux-kernel, linux-arm-kernel
In-Reply-To: <20260520093654.3303917-1-ronak.jain@amd.com>



On 5/20/26 11:36, Ronak Jain wrote:
> This patch series adds support for exposing CSU registers through a
> sysfs interface. The implementation uses dynamic discovery via the
> PM_QUERY_DATA firmware API to determine available registers at
> runtime, making the interface flexible and maintainable without
> requiring kernel changes when firmware capabilities evolve.
> 
> Background:
> 
> The ZynqMP platform has several CSU registers that are useful for
> system configuration and debugging. Previously, accessing these
> registers required direct memory access or custom tools. This series
> provides a standardized sysfs interface that leverages existing
> firmware APIs for secure access.
> 
> Key Features:
> 
> - Dynamic register discovery using PM_QUERY_DATA API
>    * PM_QID_GET_NODE_COUNT: Query number of available registers
>    * PM_QID_GET_NODE_NAME: Query register names by index
> - Automatic sysfs attribute creation under csu_registers/ group
> - Read operations via existing IOCTL_READ_REG firmware API
> - Write operations via existing IOCTL_MASK_WRITE_REG firmware API
> - Firmware-enforced access control for read-only registers
> 
> Currently Supported Registers:
> 
> - multiboot (CSU_MULTI_BOOT): Boot mode configuration
> - idcode (CSU_IDCODE): Device identification (read-only)
> - pcap-status (CSU_PCAP_STATUS): PCAP status (read-only)
> 
> The sysfs interface is available at:
>    /sys/devices/platform/firmware:zynqmp-firmware/csu_registers/
> 
> Usage Examples:
> 
> Reading a register:
>    # cat /sys/devices/platform/firmware:zynqmp-firmware/csu_registers/idcode
> 
> Writing a register (mask and value in hex):
>    # echo "0xFFFFFFFF 0x0" > /sys/devices/platform/firmware:zynqmp-firmware/csu_registers/multiboot
> 
> 
> Testing:
> 
> - Verified register read operations return correct values
> - Verified write operations update registers correctly
> - Verified read-only registers reject write attempts
> - Verified dynamic discovery works with different firmware versions
> 
> Changes in v2:
> Patch #1
> - Update date
> 
> Patch #2:
> - Removed unused csu_reg_count field from struct zynqmp_csu_data and
>    its kernel-doc entry.
> - Added explicit devm_kfree() on the csu_regs and attrs allocation
>    failure paths, plus on devm_device_add_group() failure — keeps the
>    footprint minimal when CSU is optional.
> - Expanded the 0644 sysfs-mode inline comment into a block comment
>    explaining the firmware-enforced access-control limitation.Also,
>    update the commit message accordingly.
> - Added zynqmp_pm_is_function_supported check for PM_QID_GET_NODE_NAME
>    ID to mirror the PM_QID_GET_NODE_COUNT verification.
> 
> Ronak Jain (2):
>    Documentation: ABI: add sysfs interface for ZynqMP CSU registers
>    firmware: zynqmp: Add dynamic CSU register discovery and sysfs
>      interface
> 
>   .../ABI/stable/sysfs-driver-firmware-zynqmp   |  33 +++
>   MAINTAINERS                                   |  10 +
>   drivers/firmware/xilinx/Makefile              |   2 +-
>   drivers/firmware/xilinx/zynqmp-csu-reg.c      | 258 ++++++++++++++++++
>   drivers/firmware/xilinx/zynqmp-csu-reg.h      |  18 ++
>   drivers/firmware/xilinx/zynqmp.c              |   6 +
>   include/linux/firmware/xlnx-zynqmp.h          |   4 +-
>   7 files changed, 329 insertions(+), 2 deletions(-)
>   create mode 100644 drivers/firmware/xilinx/zynqmp-csu-reg.c
>   create mode 100644 drivers/firmware/xilinx/zynqmp-csu-reg.h
> 

Applied with kernel version changed to 7.2.

Thanks,
Michal


^ permalink raw reply

* Re: [PATCH net-next] net: airoha: bind WLAN-bound flows on PPE driver L2 cache miss
From: Jihong Min @ 2026-05-25 14:13 UTC (permalink / raw)
  To: Lorenzo Bianconi
  Cc: netdev, Andrew Lunn, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, linux-arm-kernel, linux-mediatek,
	linux-kernel
In-Reply-To: <ahQDon-nio0STA4E@lore-desk>



On 5/25/26 17:09, Lorenzo Bianconi wrote:
>> The Linux bridge FDB can resolve a destination station to WDMA even when
>> the Airoha PPE driver's L2 offload cache has no entry for that MAC pair.
>> The normal bind path only checks the PPE driver's L2 offload cache, so an
>> unbound PPE hit for WLAN egress can stay unbound even though the bridge
>> already knows the right output path, unless a later offload event fills
>> that PPE driver cache.
>>
>> This matters for bridge-visible WLAN egress, such as wired-to-WLAN
>> forwarding or WLAN peer forwarding across another BSS, radio or MLO link.
>> Same-link or same-radio intra-BSS forwarding can stay inside the WLAN
>> datapath and is not covered.
> 
> Hi Jihong,

Hi, Lorenzo.

> 
> In order to offload L2 flows, I assume you are using the OpenWrt bridger
> package, right?

Actually, no.

I am using Fanboy's OpenWrt `test` build for the Lumen W1700K2,
together with several of my other patches. It does not include the
bridger package specifically. It now uses native nft-based offloading
with `kmod-br-netfilter`.

> IIUC the issue you want to resolve is we are not adding PPE L2 entries for
> the specified cases (same-link or same-radio intra-BSS forwarding), correct?

No. As written in the patch message, this specifically addresses
bridge-visible WLAN egress, such as:

1. wired-to-WLAN forwarding
2. WLAN peer forwarding across another BSS, radio, or MLO link

Same-link or same-radio intra-BSS forwarding can stay inside the WLAN
datapath and is not covered by this patch, although it did show poor
performance, whether that is due to shared airtime or not. That case
appears to belong to the Wi-Fi stack/driver datapath, such as the
mac80211/mt76/mt7996 path, rather than to this Airoha PPE fallback path.

> Using this approach, we are breaking the assumption PPE flow-table and hw
> flow-table are in sync. If the issue is the one described above, why not
> fixing the problem directly in the bridger package?

Again, this problem exists in an environment without bridger.

> Moreover, I see you developed the patch using Codex:gpt-5.5. Have you tested it
> on a real hw?

Yes. This has been tested on my Lumen W1700K2 with the environment
described above. MLO Wi-Fi P2P communication and some wired-to-WLAN
cases were indeed left unbound by PPE. CPU usage was high, and the
unbound throughput was close to 50% of what this patch achieves now.

> 
> Some comments inline.
> 
> Regards,
> Lorenzo
> >>
>> Before touching the PPE table, resolve the destination MAC through the
>> bridge device above the ingress netdev. If the PPE driver's L2 offload
>> cache lookup misses, bind the hardware flow to the resolved CDM4/WDMA
>> path.
>>
>> Assisted-by: Codex:gpt-5.5
>> Signed-off-by: Jihong Min <hurryman2212@gmail.com>
>> ---
>>  drivers/net/ethernet/airoha/airoha_ppe.c | 138 +++++++++++++++++++----
>>  1 file changed, 119 insertions(+), 19 deletions(-)
>>
>> diff --git a/drivers/net/ethernet/airoha/airoha_ppe.c b/drivers/net/ethernet/airoha/airoha_ppe.c
>> index 26da519236bf..ea932e6d87f6 100644
>> --- a/drivers/net/ethernet/airoha/airoha_ppe.c
>> +++ b/drivers/net/ethernet/airoha/airoha_ppe.c
>> @@ -803,65 +803,163 @@ static void airoha_ppe_foe_flow_remove_entry(struct airoha_ppe *ppe,
>>  }
>>  
>>  static int
>> -airoha_ppe_foe_commit_subflow_entry(struct airoha_ppe *ppe,
>> -				    struct airoha_flow_table_entry *e,
>> -				    u32 hash, bool rx_wlan)
>> +airoha_ppe_foe_commit_subflow(struct airoha_ppe *ppe,
>> +			      const struct airoha_foe_entry *bridge,
> 
> maybe l2_hwe instead of bridge?
> 
>> +			      u32 hash, bool rx_wlan)
>>  {
>>  	u32 mask = AIROHA_FOE_IB1_BIND_PACKET_TYPE | AIROHA_FOE_IB1_BIND_UDP;
>>  	struct airoha_foe_entry *hwe_p, hwe;
>> -	struct airoha_flow_table_entry *f;
>>  	int type;
>>  
>>  	hwe_p = airoha_ppe_foe_get_entry_locked(ppe, hash);
>>  	if (!hwe_p)
>>  		return -EINVAL;
>>  
>> -	f = kzalloc_obj(*f, GFP_ATOMIC);
>> -	if (!f)
>> -		return -ENOMEM;
>> -
>> -	hlist_add_head(&f->l2_subflow_node, &e->l2_flows);
>> -	f->type = FLOW_TYPE_L2_SUBFLOW;
>> -	f->hash = hash;
>> -
>>  	memcpy(&hwe, hwe_p, sizeof(*hwe_p));
>> -	hwe.ib1 = (hwe.ib1 & mask) | (e->data.ib1 & ~mask);
>> +	hwe.ib1 = (hwe.ib1 & mask) | (bridge->ib1 & ~mask);
>>  
>>  	type = FIELD_GET(AIROHA_FOE_IB1_BIND_PACKET_TYPE, hwe.ib1);
>>  	if (type >= PPE_PKT_TYPE_IPV6_ROUTE_3T) {
>> -		memcpy(&hwe.ipv6.l2, &e->data.bridge.l2, sizeof(hwe.ipv6.l2));
>> -		hwe.ipv6.ib2 = e->data.bridge.ib2;
>> +		memcpy(&hwe.ipv6.l2, &bridge->bridge.l2,
>> +		       sizeof(hwe.ipv6.l2));
>> +		hwe.ipv6.ib2 = bridge->bridge.ib2;
>>  		/* setting smac_id to 0xf instruct the hw to keep original
>>  		 * source mac address
>>  		 */
>>  		hwe.ipv6.l2.src_mac_hi = FIELD_PREP(AIROHA_FOE_MAC_SMAC_ID,
>>  						    0xf);
>>  	} else {
>> -		memcpy(&hwe.bridge.l2, &e->data.bridge.l2,
>> +		memcpy(&hwe.bridge.l2, &bridge->bridge.l2,
>>  		       sizeof(hwe.bridge.l2));
>> -		hwe.bridge.ib2 = e->data.bridge.ib2;
>> +		hwe.bridge.ib2 = bridge->bridge.ib2;
>>  		if (type == PPE_PKT_TYPE_IPV4_HNAPT)
>>  			memcpy(&hwe.ipv4.new_tuple, &hwe.ipv4.orig_tuple,
>>  			       sizeof(hwe.ipv4.new_tuple));
>>  	}
>>  
>> -	hwe.bridge.data = e->data.bridge.data;
>> -	airoha_ppe_foe_commit_entry(ppe, &hwe, hash, rx_wlan);
>> +	hwe.bridge.data = bridge->bridge.data;
>> +
>> +	return airoha_ppe_foe_commit_entry(ppe, &hwe, hash, rx_wlan);
>> +}
>> +
>> +static int
>> +airoha_ppe_foe_commit_subflow_entry(struct airoha_ppe *ppe,
>> +				    struct airoha_flow_table_entry *e,
>> +				    u32 hash, bool rx_wlan)
>> +{
>> +	struct airoha_flow_table_entry *f;
>> +	int err;
>> +
>> +	f = kzalloc_obj(*f, GFP_ATOMIC);
>> +	if (!f)
>> +		return -ENOMEM;
>> +
>> +	err = airoha_ppe_foe_commit_subflow(ppe, &e->data, hash, rx_wlan);
>> +	if (err) {
>> +		kfree(f);
>> +		return err;
>> +	}
>> +
>> +	hlist_add_head(&f->l2_subflow_node, &e->l2_flows);
>> +	f->type = FLOW_TYPE_L2_SUBFLOW;
>> +	f->hash = hash;
>>  
>>  	return 0;
>>  }
>>  
>> +static bool
>> +airoha_ppe_foe_prepare_wdma_subflow_dev(struct airoha_ppe *ppe,
>> +					struct net_device *dev,
>> +					struct airoha_flow_data *data,
>> +					struct airoha_foe_entry *hwe)
>> +{
>> +	u32 pse_port;
>> +	int err;
>> +
>> +	err = airoha_ppe_foe_entry_prepare(ppe->eth, hwe, dev,
>> +					   PPE_PKT_TYPE_BRIDGE, data, 0);
>> +	if (err)
>> +		return false;
>> +
>> +	pse_port = FIELD_GET(AIROHA_FOE_IB2_PSE_PORT, hwe->bridge.ib2);
>> +	if (pse_port != FE_PSE_PORT_CDM4)
>> +		return false;
>> +
>> +	return true;
> 
> 	return pse_port == FE_PSE_PORT_CDM4;
> 
>> +}
>> +
>> +static struct net_device *
>> +airoha_ppe_foe_get_bridge_master(struct net_device *dev)
>> +{
>> +	struct net_device *master = NULL;
>> +
>> +	rcu_read_lock();
>> +	master = netdev_master_upper_dev_get_rcu(dev);
>> +	if (master && netif_is_bridge_master(master))
>> +		dev_hold(master);
>> +	else
>> +		master = NULL;
>> +	rcu_read_unlock();
>> +
>> +	return master;
>> +}
>> +
>> +static bool
>> +airoha_ppe_foe_prepare_wdma_subflow(struct airoha_ppe *ppe,
>> +				    struct sk_buff *skb,
>> +				    struct airoha_foe_entry *hwe)
>> +{
>> +	struct ethhdr *eh = eth_hdr(skb);
>> +	struct airoha_flow_data data = {};
>> +	struct net_device *master;
>> +
>> +	if (!is_valid_ether_addr(eh->h_source) ||
>> +	    !is_valid_ether_addr(eh->h_dest))
>> +		return false;
>> +
>> +	ether_addr_copy(data.eth.h_dest, eh->h_dest);
>> +	ether_addr_copy(data.eth.h_source, eh->h_source);
>> +
>> +	if (!skb->dev)
>> +		return false;
>> +
>> +	/* WLAN egress unbound hits can arrive before flowtable creates the
>> +	 * L2 master flow normally used for subflow binding. Resolve only
>> +	 * through the bridge master so dev_fill_forward_path() must use the
>> +	 * bridge FDB for the destination MAC. Calling the ingress AP netdev
>> +	 * directly can describe the source station's WDMA path and would
>> +	 * corrupt Wi-Fi-to-wired flows whose real egress is not WDMA.
>> +	 */
>> +	master = airoha_ppe_foe_get_bridge_master(skb->dev);
>> +	if (!master)
>> +		return false;
>> +
>> +	if (airoha_ppe_foe_prepare_wdma_subflow_dev(ppe, master, &data,
>> +						    hwe)) {
>> +		dev_put(master);
>> +		return true;
>> +	}
>> +
>> +	dev_put(master);
>> +	return false;
> 
> maybe something like:
> 
> 	ret = airoha_ppe_foe_prepare_wdma_subflow_dev();
> 	dev_put(master);
> 
> 	return ret;
> 
>> +}
>> +
>>  static void airoha_ppe_foe_insert_entry(struct airoha_ppe *ppe,
>>  					struct sk_buff *skb,
>>  					u32 hash, bool rx_wlan)
>>  {
>> +	struct airoha_foe_entry wdma_hwe = {};
>>  	struct airoha_flow_table_entry *e;
>>  	struct airoha_foe_bridge br = {};
>>  	struct airoha_foe_entry *hwe;
>>  	bool commit_done = false;
>> +	bool wdma_ready = false;
>>  	struct hlist_node *n;
>>  	u32 index, state;
>>  
>> +	wdma_ready = airoha_ppe_foe_prepare_wdma_subflow(ppe, skb,
>> +							 &wdma_hwe);
>> +
>>  	spin_lock_bh(&ppe_lock);
>>  
>>  	hwe = airoha_ppe_foe_get_entry_locked(ppe, hash);
>> @@ -899,6 +997,8 @@ static void airoha_ppe_foe_insert_entry(struct airoha_ppe *ppe,
>>  				   airoha_l2_flow_table_params);
>>  	if (e)
>>  		airoha_ppe_foe_commit_subflow_entry(ppe, e, hash, rx_wlan);
>> +	else if (wdma_ready)
>> +		airoha_ppe_foe_commit_subflow(ppe, &wdma_hwe, hash, rx_wlan);
>>  unlock:
>>  	spin_unlock_bh(&ppe_lock);
>>  }
>> -- 
>> 2.53.0
>>

All inline code-style review comments will be addressed in the next
submission of the patch set, together with the responses to Sashiko's
review, if any.


^ permalink raw reply

* [PATCH v2 0/6] leds: is31fl319x: Fix shutdown GPIO and update DT bindings
From: Jun Yan @ 2026-05-25 14:46 UTC (permalink / raw)
  To: linusw, dmitry.baryshkov, Lee Jones, Pavel Machek, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Bjorn Andersson, Konrad Dybcio,
	Andrew Lunn, Gregory Clement, Sebastian Hesselbarth,
	Bartosz Golaszewski, Vincent Knecht, Grant Feng, Andre Przywara,
	Jisheng Zhang, Michal Simek, Florian Fainelli, Neil Armstrong,
	Robert Marko
  Cc: Jun Yan, Pavel Machek, Krzysztof Kozlowski, Geert Uytterhoeven,
	Kunihiko Hayashi, Patrice Chotard, linux-leds, devicetree,
	linux-kernel, linux-arm-msm, linux-arm-kernel, linux-gpio

This series fixes incorrect shutdown GPIO polarity and improves
shutdown-gpios description in DT bindings.

Patch 1 adds detailed shutdown-gpios description and fixes example
in DT bindings.

Patch 2 fixes shutdown GPIO initial state and removes redundant
startup toggling.

Patch 3 adds fixup to force consumer active low for legacy device 
trees in gpiolib.

Patches 4-6 correct shutdown GPIO polarity in board DTS files.

Changes in v2:
- Add comments explaining the reason for this GPIO line level.
- Add fixup to force consumer active low for legacy device trees in gpiolib.
- Link to v1: https://lore.kernel.org/all/20260508152435.21389-1-jerrysteve1101@gmail.com

Jun Yan (6):
  dt-bindings: leds: issi,is31fl319x: Update description for the
    shutdown-gpios property
  leds: is31fl319x: Fix shutdown GPIO initial state and remove redundant
    startup pulse
  gpiolib: of: add quirk for IS31FL319X shutdown line
  arm64: dts: qcom: msm8916-alcatel-idol347: Fix sn3190 shutdown GPIO
    polarity
  ARM: dts: qcom: msm8974-oneplus-bacon: Fix sn3193 shutdown GPIO
    polarity
  arm64: dts: marvell: armada-7040-mochabin: Fix is31fl3199 shutdown
    GPIO polarity

 .../devicetree/bindings/leds/issi,is31fl319x.yaml     |  9 +++++++--
 .../boot/dts/qcom/qcom-msm8974pro-oneplus-bacon.dts   |  2 +-
 arch/arm64/boot/dts/marvell/armada-7040-mochabin.dts  |  2 +-
 arch/arm64/boot/dts/qcom/msm8916-alcatel-idol347.dts  |  2 +-
 drivers/gpio/gpiolib-of.c                             | 10 ++++++++++
 drivers/leds/leds-is31fl319x.c                        | 11 ++++-------
 6 files changed, 24 insertions(+), 12 deletions(-)

-- 
2.54.0



^ permalink raw reply

* [PATCH v2 1/6] dt-bindings: leds: issi,is31fl319x: Update description for the shutdown-gpios property
From: Jun Yan @ 2026-05-25 14:46 UTC (permalink / raw)
  To: linusw, dmitry.baryshkov, Lee Jones, Pavel Machek, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Bjorn Andersson, Konrad Dybcio,
	Andrew Lunn, Gregory Clement, Sebastian Hesselbarth,
	Bartosz Golaszewski, Vincent Knecht, Grant Feng, Andre Przywara,
	Claudiu Beznea, Wei Xu, Sudeep Holla, Tony Lindgren, Robert Marko
  Cc: Jun Yan, Pavel Machek, Krzysztof Kozlowski, Patrice Chotard,
	Kunihiko Hayashi, Michal Simek, linux-leds, devicetree,
	linux-kernel, linux-arm-msm, linux-arm-kernel, linux-gpio
In-Reply-To: <20260525144629.498630-1-jerrysteve1101@gmail.com>

The IS31FL319X series features an SDB shutdown pin.
Driving it low (active low) places the chip into hardware shutdown
mode for power saving, while all register contents are preserved
and registers are not reset.

Update description for the shutdown down (SDB) pin and fix the example
device tree binding.

Fixes: dbc801b472c1 ("dt-bindings: leds: Convert is31fl319x to dtschema")
Signed-off-by: Jun Yan <jerrysteve1101@gmail.com>
Reviewed-by: Rob Herring (Arm) <robh@kernel.org>
---
 .../devicetree/bindings/leds/issi,is31fl319x.yaml        | 9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/Documentation/devicetree/bindings/leds/issi,is31fl319x.yaml b/Documentation/devicetree/bindings/leds/issi,is31fl319x.yaml
index 906735acfbaf..ebf2bed51e7f 100644
--- a/Documentation/devicetree/bindings/leds/issi,is31fl319x.yaml
+++ b/Documentation/devicetree/bindings/leds/issi,is31fl319x.yaml
@@ -39,7 +39,12 @@ properties:
 
   shutdown-gpios:
     maxItems: 1
-    description: GPIO attached to the SDB pin.
+    description: |
+      GPIO attached to the chip's SDB pin.
+      Driving this GPIO low places the chip into hardware shutdown mode
+      for power saving. All register contents are preserved and registers
+      are not reset during shutdown. The chip exits hardware shutdown mode
+      when the SDB pin is pulled high.
 
   audio-gain-db:
     default: 0
@@ -174,7 +179,7 @@ examples:
             #address-cells = <1>;
             #size-cells = <0>;
 
-            shutdown-gpios = <&gpio0 11 GPIO_ACTIVE_HIGH>;
+            shutdown-gpios = <&gpio0 11 GPIO_ACTIVE_LOW>;
 
             led@1 {
                 reg = <1>;
-- 
2.54.0



^ permalink raw reply related

* [PATCH v2 2/6] leds: is31fl319x: Fix shutdown GPIO initial state and remove redundant startup pulse
From: Jun Yan @ 2026-05-25 14:46 UTC (permalink / raw)
  To: linusw, dmitry.baryshkov, Lee Jones, Pavel Machek, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Bjorn Andersson, Konrad Dybcio,
	Andrew Lunn, Gregory Clement, Sebastian Hesselbarth,
	Bartosz Golaszewski, Vincent Knecht, Grant Feng, Andre Przywara,
	Geert Uytterhoeven, Viresh Kumar, Florian Fainelli, Robert Marko
  Cc: Jun Yan, Pavel Machek, Krzysztof Kozlowski, Shawn Guo,
	Michal Simek, Heiko Stuebner, linux-leds, devicetree,
	linux-kernel, linux-arm-msm, linux-arm-kernel, linux-gpio
In-Reply-To: <20260525144629.498630-1-jerrysteve1101@gmail.com>

1. Per IS31FL319x datasheet [1], the hardware shutdown pin (SDB) is
active-low.

Fix incorrect initial GPIO level to properly release the chip from shutdown
state.

2. According to datasheet [1] definition:
  Shutdown mode can either be used as a means of
  reducing power consumption or generating a flashing
  display (repeatedly entering and leaving shutdown
  mode). During shutdown mode all registers retain their
  data.
shutdown mode does NOT perform chip reset.A dedicated software reset is
already implemented in driver by writing 0 to reset chip.

Remove redundant unnecessary toggling of the shutdown GPIO.

[1] https://lumissil.com/assets/pdf/core/IS31FL3193_DS.pdf

Fixes: dddb4e38c6ba ("leds: is31fl319x: Add shutdown pin and generate a 5ms low pulse when startup")
Signed-off-by: Jun Yan <jerrysteve1101@gmail.com>
---
 drivers/leds/leds-is31fl319x.c | 11 ++++-------
 1 file changed, 4 insertions(+), 7 deletions(-)

diff --git a/drivers/leds/leds-is31fl319x.c b/drivers/leds/leds-is31fl319x.c
index e411cee06dab..41087ed262cb 100644
--- a/drivers/leds/leds-is31fl319x.c
+++ b/drivers/leds/leds-is31fl319x.c
@@ -396,7 +396,10 @@ static int is31fl319x_parse_fw(struct device *dev, struct is31fl319x_chip *is31)
 	int count;
 	int ret;
 
-	is31->shutdown_gpio = devm_gpiod_get_optional(dev, "shutdown", GPIOD_OUT_HIGH);
+	/* Driving this GPIO line low (in fact high) takes the chip out of shutdown,
+	 * as it is flagged as GPIO_ACTIVE_LOW in provider (such as the device tree).
+	 */
+	is31->shutdown_gpio = devm_gpiod_get_optional(dev, "shutdown", GPIOD_OUT_LOW);
 	if (IS_ERR(is31->shutdown_gpio))
 		return dev_err_probe(dev, PTR_ERR(is31->shutdown_gpio),
 				     "Failed to get shutdown gpio\n");
@@ -506,12 +509,6 @@ static int is31fl319x_probe(struct i2c_client *client)
 	if (err)
 		return err;
 
-	if (is31->shutdown_gpio) {
-		gpiod_direction_output(is31->shutdown_gpio, 0);
-		mdelay(5);
-		gpiod_direction_output(is31->shutdown_gpio, 1);
-	}
-
 	is31->client = client;
 	is31->regmap = devm_regmap_init_i2c(client, is31->cdef->is31fl319x_regmap_config);
 	if (IS_ERR(is31->regmap))
-- 
2.54.0



^ permalink raw reply related

* [PATCH v2 3/6] gpiolib: of: add quirk for IS31FL319X shutdown line
From: Jun Yan @ 2026-05-25 14:46 UTC (permalink / raw)
  To: linusw, dmitry.baryshkov, Lee Jones, Pavel Machek, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Bjorn Andersson, Konrad Dybcio,
	Andrew Lunn, Gregory Clement, Sebastian Hesselbarth,
	Bartosz Golaszewski, Vincent Knecht, Grant Feng, Andre Przywara,
	Tony Lindgren, Sudeep Holla, Romain Perier, Jesper Nilsson,
	Robert Marko
  Cc: Jun Yan, Pavel Machek, Krzysztof Kozlowski, Wei Xu,
	Geert Uytterhoeven, Peter Rosin, linux-leds, devicetree,
	linux-kernel, linux-arm-msm, linux-arm-kernel, linux-gpio
In-Reply-To: <20260525144629.498630-1-jerrysteve1101@gmail.com>

According to the IS31FL319x datasheet[1], the SDB pin is active‑low.
However, existing device tree incorrectly configure it as active‑high.

Add a fixup to force the consumer active low for legacy device trees.

[1] https://lumissil.com/assets/pdf/core/IS31FL3196_DS.pdf

Signed-off-by: Jun Yan <jerrysteve1101@gmail.com>
---
 drivers/gpio/gpiolib-of.c | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/drivers/gpio/gpiolib-of.c b/drivers/gpio/gpiolib-of.c
index ef1ac68b94b7..8a79aaadc9ea 100644
--- a/drivers/gpio/gpiolib-of.c
+++ b/drivers/gpio/gpiolib-of.c
@@ -194,6 +194,16 @@ static void of_gpio_try_fixup_polarity(const struct device_node *np,
 		{ "himax,hx8357",	"gpios-reset",	false },
 		{ "himax,hx8369",	"gpios-reset",	false },
 #endif
+#if IS_ENABLED(CONFIG_LEDS_IS31FL319X)
+		/*
+		 * According to the IS31FL319x datasheet, the SDB pin is active‑low.
+		 * However, existing device tree incorrectly configure it
+		 * as active‑high.
+		 */
+		{ "issi,is31fl3199",	"shutdown-gpios",	false },
+		{ "si-en,sn3190",	"shutdown-gpios",	false },
+		{ "si-en,sn3193",	"shutdown-gpios",	false },
+#endif
 #if IS_ENABLED(CONFIG_MTD_NAND_JZ4780)
 		/*
 		 * The rb-gpios semantics was undocumented and qi,lb60 (along with
-- 
2.54.0



^ permalink raw reply related

* [PATCH v2 4/6] arm64: dts: qcom: msm8916-alcatel-idol347: Fix sn3190 shutdown GPIO polarity
From: Jun Yan @ 2026-05-25 14:46 UTC (permalink / raw)
  To: linusw, dmitry.baryshkov, Lee Jones, Pavel Machek, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Bjorn Andersson, Konrad Dybcio,
	Andrew Lunn, Gregory Clement, Sebastian Hesselbarth,
	Bartosz Golaszewski, Vincent Knecht, Grant Feng, Andre Przywara,
	Viresh Kumar, Heiko Stuebner, Sudeep Holla, Florian Fainelli,
	Robert Marko
  Cc: Jun Yan, Konrad Dybcio, Pavel Machek, Krzysztof Kozlowski, Wei Xu,
	Romain Perier, Geert Uytterhoeven, linux-leds, devicetree,
	linux-kernel, linux-arm-msm, linux-arm-kernel, linux-gpio
In-Reply-To: <20260525144629.498630-1-jerrysteve1101@gmail.com>

The sn3190 shutdown pin is active-low [1]. Correct the GPIO flags
from GPIO_ACTIVE_HIGH to GPIO_ACTIVE_LOW to match the hardware.

[1] https://lumissil.com/assets/pdf/core/IS31FL3190_DS.pdf

Fixes: 1c8cc183d070 ("arm64: dts: qcom: msm8916-alcatel-idol347: add LED indicator")
Signed-off-by: Jun Yan <jerrysteve1101@gmail.com>
Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
---
 arch/arm64/boot/dts/qcom/msm8916-alcatel-idol347.dts | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm64/boot/dts/qcom/msm8916-alcatel-idol347.dts b/arch/arm64/boot/dts/qcom/msm8916-alcatel-idol347.dts
index 2de8b6f9531b..6d51d6efcbac 100644
--- a/arch/arm64/boot/dts/qcom/msm8916-alcatel-idol347.dts
+++ b/arch/arm64/boot/dts/qcom/msm8916-alcatel-idol347.dts
@@ -197,7 +197,7 @@ &blsp_i2c6 {
 	led-controller@68 {
 		compatible = "si-en,sn3190";
 		reg = <0x68>;
-		shutdown-gpios = <&tlmm 89 GPIO_ACTIVE_HIGH>;
+		shutdown-gpios = <&tlmm 89 GPIO_ACTIVE_LOW>;
 		pinctrl-names = "default";
 		pinctrl-0 = <&led_enable_default &led_shutdown_default>;
 		#address-cells = <1>;
-- 
2.54.0



^ permalink raw reply related

* [PATCH v2 5/6] ARM: dts: qcom: msm8974-oneplus-bacon: Fix sn3193 shutdown GPIO polarity
From: Jun Yan @ 2026-05-25 14:46 UTC (permalink / raw)
  To: linusw, dmitry.baryshkov, Lee Jones, Pavel Machek, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Bjorn Andersson, Konrad Dybcio,
	Andrew Lunn, Gregory Clement, Sebastian Hesselbarth,
	Bartosz Golaszewski, Vincent Knecht, Grant Feng, Andre Przywara,
	Alexandre TORGUE, Kunihiko Hayashi, Robert Marko
  Cc: Jun Yan, Konrad Dybcio, Pavel Machek, Krzysztof Kozlowski,
	Geert Uytterhoeven, Sudeep Holla, Baruch Siach, linux-leds,
	devicetree, linux-kernel, linux-arm-msm, linux-arm-kernel,
	linux-gpio
In-Reply-To: <20260525144629.498630-1-jerrysteve1101@gmail.com>

The sn3193 shutdown pin is active-low[1]. Correct the GPIO flags
from GPIO_ACTIVE_HIGH to GPIO_ACTIVE_LOW to match the hardware.

[1] https://lumissil.com/assets/pdf/core/IS31FL3193_DS.pdf

Fixes: 724ba6751532 ("ARM: dts: Move .dts files to vendor sub-directories")
Signed-off-by: Jun Yan <jerrysteve1101@gmail.com>
Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
---
 arch/arm/boot/dts/qcom/qcom-msm8974pro-oneplus-bacon.dts | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/boot/dts/qcom/qcom-msm8974pro-oneplus-bacon.dts b/arch/arm/boot/dts/qcom/qcom-msm8974pro-oneplus-bacon.dts
index 258bbbecd927..c528d42bade5 100644
--- a/arch/arm/boot/dts/qcom/qcom-msm8974pro-oneplus-bacon.dts
+++ b/arch/arm/boot/dts/qcom/qcom-msm8974pro-oneplus-bacon.dts
@@ -147,7 +147,7 @@ led-controller@68 {
 		compatible = "si-en,sn3193";
 		reg = <0x68>;
 
-		shutdown-gpios = <&tlmm 45 GPIO_ACTIVE_HIGH>;
+		shutdown-gpios = <&tlmm 45 GPIO_ACTIVE_LOW>;
 
 		#address-cells = <1>;
 		#size-cells = <0>;
-- 
2.54.0



^ permalink raw reply related

* [PATCH v2 6/6] arm64: dts: marvell: armada-7040-mochabin: Fix is31fl3199 shutdown GPIO polarity
From: Jun Yan @ 2026-05-25 14:46 UTC (permalink / raw)
  To: linusw, dmitry.baryshkov, Lee Jones, Pavel Machek, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Bjorn Andersson, Konrad Dybcio,
	Andrew Lunn, Gregory Clement, Sebastian Hesselbarth,
	Bartosz Golaszewski, Vincent Knecht, Grant Feng, Andre Przywara,
	Baruch Siach, Shawn Guo, Paul Barker, Robert Marko
  Cc: Jun Yan, Pavel Machek, Krzysztof Kozlowski, Wei Xu,
	Geert Uytterhoeven, Patrice Chotard, linux-leds, devicetree,
	linux-kernel, linux-arm-msm, linux-arm-kernel, linux-gpio
In-Reply-To: <20260525144629.498630-1-jerrysteve1101@gmail.com>

The is31fl3199 shutdown pin is active-low [1]. Correct the GPIO flags
from GPIO_ACTIVE_HIGH to GPIO_ACTIVE_LOW to match the hardware.

[1] https://lumissil.com/assets/pdf/core/IS31FL3199_DS.pdf

Fixes: 737929191283 ("arm64: dts: marvell: add Globalscale MOCHAbin")
Signed-off-by: Jun Yan <jerrysteve1101@gmail.com>
---
 arch/arm64/boot/dts/marvell/armada-7040-mochabin.dts | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm64/boot/dts/marvell/armada-7040-mochabin.dts b/arch/arm64/boot/dts/marvell/armada-7040-mochabin.dts
index 6bdc4f1e6939..cf690a85cc2a 100644
--- a/arch/arm64/boot/dts/marvell/armada-7040-mochabin.dts
+++ b/arch/arm64/boot/dts/marvell/armada-7040-mochabin.dts
@@ -236,7 +236,7 @@ leds@64 {
 		#size-cells = <0>;
 		pinctrl-names = "default";
 		pinctrl-0 = <&is31_sdb_pins>;
-		shutdown-gpios = <&cp0_gpio1 30 GPIO_ACTIVE_HIGH>;
+		shutdown-gpios = <&cp0_gpio1 30 GPIO_ACTIVE_LOW>;
 		reg = <0x64>;
 
 		led1_red: led@1 {
-- 
2.54.0



^ permalink raw reply related

* Re: [PATCH v5 0/2] mm: improve large folio readahead for exec memory
From: Usama Arif @ 2026-05-25 15:01 UTC (permalink / raw)
  To: Andrew Morton
  Cc: david, willy, ryan.roberts, linux-mm, r, jack, Andrew Donnellan,
	apopple, baohua, baolin.wang, brauner, catalin.marinas, dev.jain,
	kees, kevin.brodsky, lance.yang, Liam R.Howlett, linux-arm-kernel,
	linux-fsdevel, linux-kernel, ljs, mhocko, npache, pasha.tatashin,
	rmclure, rppt, surenb, vbabka, Al Viro, wilts.infradead.org, ziy,
	hannes, kas, shakeel.butt, kernel-team
In-Reply-To: <20260522122052.7b4ad7c482a0e4826296e392@linux-foundation.org>



On 22/05/2026 20:20, Andrew Morton wrote:
> On Fri, 22 May 2026 09:23:46 -0700 Usama Arif <usama.arif@linux.dev> wrote:
> 
>> Two checks in do_sync_mmap_readahead() limit large-folio readahead:
>>
>>   1. The mmap_miss heuristic is meant to throttle wasteful speculative
>>      readahead. It is currently also applied to the VM_EXEC readahead
>>      path, which is targeted rather than speculative. Once mmap_miss exceeds
>>      MMAP_LOTSAMISS, exec readahead - including the large-folio
>>      order requested by exec_folio_order() - is disabled. On
>>      configurations where the mmap_miss decrement paths are not
>>      active (see patch 1) the counter only grows, so exec readahead
>>      is permanently disabled after the first 100 faults.
>>
>>   2. The force_thp_readahead path is gated only on
>>      HPAGE_PMD_ORDER <= MAX_PAGECACHE_ORDER and always drives the
>>      readahead at HPAGE_PMD_ORDER. Configurations where
>>      HPAGE_PMD_ORDER exceeds MAX_PAGECACHE_ORDER never reach this
>>      path, even when the mapping itself supports usefully large
>>      folios well below the cap.
>>
>> Both issues are most visible on arm64 with a 64K base page size,
>> where HPAGE_PMD_ORDER is 13 (512MB) -- above MAX_PAGECACHE_ORDER
>> (11) -- and where fault_around_pages collapses to 1 disabling
>> should_fault_around() (one of the two mmap_miss decrement sites).
>> However the fixes are architecture-agnostic: patch 1 reflects the
>> nature of VM_EXEC readahead regardless of base page size, and
>> patch 2 generalises the gate so any mapping advertising a usefully
>> large maximum folio order can benefit.
>>
>> I created a benchmark that mmaps a large executable file and calls
>> RET-stub functions at PAGE_SIZE offsets across it. "Cold" measures
>> fault + readahead cost. "Random" first faults in all pages with a
>> sequential sweep (not measured), then measures time for calling random
>> offsets, isolating iTLB miss cost for scattered execution.
>>
>> The benchmark results on Neoverse V2 (Grace), arm64 with 64K base pages,
>> 512MB executable file on ext4, averaged over 3 runs:
>>
>>   Phase      | Baseline     | Patched      | Improvement
>>   -----------|--------------|--------------|------------------
>>   Cold fault | 83.4 ms      | 41.3 ms      | 50% faster
>>   Random     | 76.0 ms      | 58.3 ms      | 23% faster
> 
> Well that's nice.
> 
> AI review might have found a few things:
> 	https://sashiko.dev/#/patchset/20260522162422.3856502-1-usama.arif@linux.dev
> 

Thanks Andrew! So sashiko seems to have brought out some interesting problems,
some of which are pre-existing. For example, the decrement sites for mmap_miss
in do_async_mmap_readahead() and filemap_map_pages() dont skip for VM_SEQ_READ.

I have sent this as an independent patch in [1].

I will send the next version of this series on top of [1] in a few days
addressing the rest of the issues raised by sashiko.

[1] https://lore.kernel.org/all/20260525145751.2671248-1-usama.arif@linux.dev/




^ permalink raw reply

* Re: [PATCH net-next] net: airoha: bind WLAN-bound flows on PPE driver L2 cache miss
From: Lorenzo Bianconi @ 2026-05-25 15:19 UTC (permalink / raw)
  To: Jihong Min
  Cc: netdev, Andrew Lunn, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, linux-arm-kernel, linux-mediatek,
	linux-kernel
In-Reply-To: <a08289e7-641c-489e-8d89-6eae9f092f90@gmail.com>

[-- Attachment #1: Type: text/plain, Size: 10873 bytes --]

> 
> 
> On 5/25/26 17:09, Lorenzo Bianconi wrote:
> >> The Linux bridge FDB can resolve a destination station to WDMA even when
> >> the Airoha PPE driver's L2 offload cache has no entry for that MAC pair.
> >> The normal bind path only checks the PPE driver's L2 offload cache, so an
> >> unbound PPE hit for WLAN egress can stay unbound even though the bridge
> >> already knows the right output path, unless a later offload event fills
> >> that PPE driver cache.
> >>
> >> This matters for bridge-visible WLAN egress, such as wired-to-WLAN
> >> forwarding or WLAN peer forwarding across another BSS, radio or MLO link.
> >> Same-link or same-radio intra-BSS forwarding can stay inside the WLAN
> >> datapath and is not covered.
> > 
> > Hi Jihong,
> 
> Hi, Lorenzo.
> 
> > 
> > In order to offload L2 flows, I assume you are using the OpenWrt bridger
> > package, right?
> 
> Actually, no.
> 
> I am using Fanboy's OpenWrt `test` build for the Lumen W1700K2,
> together with several of my other patches. It does not include the
> bridger package specifically. It now uses native nft-based offloading
> with `kmod-br-netfilter`.

according to my understanding this is not merged yet, right? I guess the
patches should be based on official/accepted code.

> 
> > IIUC the issue you want to resolve is we are not adding PPE L2 entries for
> > the specified cases (same-link or same-radio intra-BSS forwarding), correct?
> 
> No. As written in the patch message, this specifically addresses
> bridge-visible WLAN egress, such as:
> 
> 1. wired-to-WLAN forwarding
> 2. WLAN peer forwarding across another BSS, radio, or MLO link
> 
> Same-link or same-radio intra-BSS forwarding can stay inside the WLAN
> datapath and is not covered by this patch, although it did show poor
> performance, whether that is due to shared airtime or not. That case
> appears to belong to the Wi-Fi stack/driver datapath, such as the
> mac80211/mt76/mt7996 path, rather than to this Airoha PPE fallback path.

according to my understanding the l2 nft-based offloading solution should
add the missing info to PPE flow-table. As I pointed out, it should be
in-sync with hw flow-table. It seems a bug in the nft code to me.

> 
> > Using this approach, we are breaking the assumption PPE flow-table and hw
> > flow-table are in sync. If the issue is the one described above, why not
> > fixing the problem directly in the bridger package?
> 
> Again, this problem exists in an environment without bridger.

In order to offload L2 traffic bridger is mandatory. Do you mean the issue
occurs even on L3 scenario?

> 
> > Moreover, I see you developed the patch using Codex:gpt-5.5. Have you tested it
> > on a real hw?
> 
> Yes. This has been tested on my Lumen W1700K2 with the environment
> described above. MLO Wi-Fi P2P communication and some wired-to-WLAN
> cases were indeed left unbound by PPE. CPU usage was high, and the
> unbound throughput was close to 50% of what this patch achieves now.

ack

Regards,
Lorenzo

> 
> > 
> > Some comments inline.
> > 
> > Regards,
> > Lorenzo
> > >>
> >> Before touching the PPE table, resolve the destination MAC through the
> >> bridge device above the ingress netdev. If the PPE driver's L2 offload
> >> cache lookup misses, bind the hardware flow to the resolved CDM4/WDMA
> >> path.
> >>
> >> Assisted-by: Codex:gpt-5.5
> >> Signed-off-by: Jihong Min <hurryman2212@gmail.com>
> >> ---
> >>  drivers/net/ethernet/airoha/airoha_ppe.c | 138 +++++++++++++++++++----
> >>  1 file changed, 119 insertions(+), 19 deletions(-)
> >>
> >> diff --git a/drivers/net/ethernet/airoha/airoha_ppe.c b/drivers/net/ethernet/airoha/airoha_ppe.c
> >> index 26da519236bf..ea932e6d87f6 100644
> >> --- a/drivers/net/ethernet/airoha/airoha_ppe.c
> >> +++ b/drivers/net/ethernet/airoha/airoha_ppe.c
> >> @@ -803,65 +803,163 @@ static void airoha_ppe_foe_flow_remove_entry(struct airoha_ppe *ppe,
> >>  }
> >>  
> >>  static int
> >> -airoha_ppe_foe_commit_subflow_entry(struct airoha_ppe *ppe,
> >> -				    struct airoha_flow_table_entry *e,
> >> -				    u32 hash, bool rx_wlan)
> >> +airoha_ppe_foe_commit_subflow(struct airoha_ppe *ppe,
> >> +			      const struct airoha_foe_entry *bridge,
> > 
> > maybe l2_hwe instead of bridge?
> > 
> >> +			      u32 hash, bool rx_wlan)
> >>  {
> >>  	u32 mask = AIROHA_FOE_IB1_BIND_PACKET_TYPE | AIROHA_FOE_IB1_BIND_UDP;
> >>  	struct airoha_foe_entry *hwe_p, hwe;
> >> -	struct airoha_flow_table_entry *f;
> >>  	int type;
> >>  
> >>  	hwe_p = airoha_ppe_foe_get_entry_locked(ppe, hash);
> >>  	if (!hwe_p)
> >>  		return -EINVAL;
> >>  
> >> -	f = kzalloc_obj(*f, GFP_ATOMIC);
> >> -	if (!f)
> >> -		return -ENOMEM;
> >> -
> >> -	hlist_add_head(&f->l2_subflow_node, &e->l2_flows);
> >> -	f->type = FLOW_TYPE_L2_SUBFLOW;
> >> -	f->hash = hash;
> >> -
> >>  	memcpy(&hwe, hwe_p, sizeof(*hwe_p));
> >> -	hwe.ib1 = (hwe.ib1 & mask) | (e->data.ib1 & ~mask);
> >> +	hwe.ib1 = (hwe.ib1 & mask) | (bridge->ib1 & ~mask);
> >>  
> >>  	type = FIELD_GET(AIROHA_FOE_IB1_BIND_PACKET_TYPE, hwe.ib1);
> >>  	if (type >= PPE_PKT_TYPE_IPV6_ROUTE_3T) {
> >> -		memcpy(&hwe.ipv6.l2, &e->data.bridge.l2, sizeof(hwe.ipv6.l2));
> >> -		hwe.ipv6.ib2 = e->data.bridge.ib2;
> >> +		memcpy(&hwe.ipv6.l2, &bridge->bridge.l2,
> >> +		       sizeof(hwe.ipv6.l2));
> >> +		hwe.ipv6.ib2 = bridge->bridge.ib2;
> >>  		/* setting smac_id to 0xf instruct the hw to keep original
> >>  		 * source mac address
> >>  		 */
> >>  		hwe.ipv6.l2.src_mac_hi = FIELD_PREP(AIROHA_FOE_MAC_SMAC_ID,
> >>  						    0xf);
> >>  	} else {
> >> -		memcpy(&hwe.bridge.l2, &e->data.bridge.l2,
> >> +		memcpy(&hwe.bridge.l2, &bridge->bridge.l2,
> >>  		       sizeof(hwe.bridge.l2));
> >> -		hwe.bridge.ib2 = e->data.bridge.ib2;
> >> +		hwe.bridge.ib2 = bridge->bridge.ib2;
> >>  		if (type == PPE_PKT_TYPE_IPV4_HNAPT)
> >>  			memcpy(&hwe.ipv4.new_tuple, &hwe.ipv4.orig_tuple,
> >>  			       sizeof(hwe.ipv4.new_tuple));
> >>  	}
> >>  
> >> -	hwe.bridge.data = e->data.bridge.data;
> >> -	airoha_ppe_foe_commit_entry(ppe, &hwe, hash, rx_wlan);
> >> +	hwe.bridge.data = bridge->bridge.data;
> >> +
> >> +	return airoha_ppe_foe_commit_entry(ppe, &hwe, hash, rx_wlan);
> >> +}
> >> +
> >> +static int
> >> +airoha_ppe_foe_commit_subflow_entry(struct airoha_ppe *ppe,
> >> +				    struct airoha_flow_table_entry *e,
> >> +				    u32 hash, bool rx_wlan)
> >> +{
> >> +	struct airoha_flow_table_entry *f;
> >> +	int err;
> >> +
> >> +	f = kzalloc_obj(*f, GFP_ATOMIC);
> >> +	if (!f)
> >> +		return -ENOMEM;
> >> +
> >> +	err = airoha_ppe_foe_commit_subflow(ppe, &e->data, hash, rx_wlan);
> >> +	if (err) {
> >> +		kfree(f);
> >> +		return err;
> >> +	}
> >> +
> >> +	hlist_add_head(&f->l2_subflow_node, &e->l2_flows);
> >> +	f->type = FLOW_TYPE_L2_SUBFLOW;
> >> +	f->hash = hash;
> >>  
> >>  	return 0;
> >>  }
> >>  
> >> +static bool
> >> +airoha_ppe_foe_prepare_wdma_subflow_dev(struct airoha_ppe *ppe,
> >> +					struct net_device *dev,
> >> +					struct airoha_flow_data *data,
> >> +					struct airoha_foe_entry *hwe)
> >> +{
> >> +	u32 pse_port;
> >> +	int err;
> >> +
> >> +	err = airoha_ppe_foe_entry_prepare(ppe->eth, hwe, dev,
> >> +					   PPE_PKT_TYPE_BRIDGE, data, 0);
> >> +	if (err)
> >> +		return false;
> >> +
> >> +	pse_port = FIELD_GET(AIROHA_FOE_IB2_PSE_PORT, hwe->bridge.ib2);
> >> +	if (pse_port != FE_PSE_PORT_CDM4)
> >> +		return false;
> >> +
> >> +	return true;
> > 
> > 	return pse_port == FE_PSE_PORT_CDM4;
> > 
> >> +}
> >> +
> >> +static struct net_device *
> >> +airoha_ppe_foe_get_bridge_master(struct net_device *dev)
> >> +{
> >> +	struct net_device *master = NULL;
> >> +
> >> +	rcu_read_lock();
> >> +	master = netdev_master_upper_dev_get_rcu(dev);
> >> +	if (master && netif_is_bridge_master(master))
> >> +		dev_hold(master);
> >> +	else
> >> +		master = NULL;
> >> +	rcu_read_unlock();
> >> +
> >> +	return master;
> >> +}
> >> +
> >> +static bool
> >> +airoha_ppe_foe_prepare_wdma_subflow(struct airoha_ppe *ppe,
> >> +				    struct sk_buff *skb,
> >> +				    struct airoha_foe_entry *hwe)
> >> +{
> >> +	struct ethhdr *eh = eth_hdr(skb);
> >> +	struct airoha_flow_data data = {};
> >> +	struct net_device *master;
> >> +
> >> +	if (!is_valid_ether_addr(eh->h_source) ||
> >> +	    !is_valid_ether_addr(eh->h_dest))
> >> +		return false;
> >> +
> >> +	ether_addr_copy(data.eth.h_dest, eh->h_dest);
> >> +	ether_addr_copy(data.eth.h_source, eh->h_source);
> >> +
> >> +	if (!skb->dev)
> >> +		return false;
> >> +
> >> +	/* WLAN egress unbound hits can arrive before flowtable creates the
> >> +	 * L2 master flow normally used for subflow binding. Resolve only
> >> +	 * through the bridge master so dev_fill_forward_path() must use the
> >> +	 * bridge FDB for the destination MAC. Calling the ingress AP netdev
> >> +	 * directly can describe the source station's WDMA path and would
> >> +	 * corrupt Wi-Fi-to-wired flows whose real egress is not WDMA.
> >> +	 */
> >> +	master = airoha_ppe_foe_get_bridge_master(skb->dev);
> >> +	if (!master)
> >> +		return false;
> >> +
> >> +	if (airoha_ppe_foe_prepare_wdma_subflow_dev(ppe, master, &data,
> >> +						    hwe)) {
> >> +		dev_put(master);
> >> +		return true;
> >> +	}
> >> +
> >> +	dev_put(master);
> >> +	return false;
> > 
> > maybe something like:
> > 
> > 	ret = airoha_ppe_foe_prepare_wdma_subflow_dev();
> > 	dev_put(master);
> > 
> > 	return ret;
> > 
> >> +}
> >> +
> >>  static void airoha_ppe_foe_insert_entry(struct airoha_ppe *ppe,
> >>  					struct sk_buff *skb,
> >>  					u32 hash, bool rx_wlan)
> >>  {
> >> +	struct airoha_foe_entry wdma_hwe = {};
> >>  	struct airoha_flow_table_entry *e;
> >>  	struct airoha_foe_bridge br = {};
> >>  	struct airoha_foe_entry *hwe;
> >>  	bool commit_done = false;
> >> +	bool wdma_ready = false;
> >>  	struct hlist_node *n;
> >>  	u32 index, state;
> >>  
> >> +	wdma_ready = airoha_ppe_foe_prepare_wdma_subflow(ppe, skb,
> >> +							 &wdma_hwe);
> >> +
> >>  	spin_lock_bh(&ppe_lock);
> >>  
> >>  	hwe = airoha_ppe_foe_get_entry_locked(ppe, hash);
> >> @@ -899,6 +997,8 @@ static void airoha_ppe_foe_insert_entry(struct airoha_ppe *ppe,
> >>  				   airoha_l2_flow_table_params);
> >>  	if (e)
> >>  		airoha_ppe_foe_commit_subflow_entry(ppe, e, hash, rx_wlan);
> >> +	else if (wdma_ready)
> >> +		airoha_ppe_foe_commit_subflow(ppe, &wdma_hwe, hash, rx_wlan);
> >>  unlock:
> >>  	spin_unlock_bh(&ppe_lock);
> >>  }
> >> -- 
> >> 2.53.0
> >>
> 
> All inline code-style review comments will be addressed in the next
> submission of the patch set, together with the responses to Sashiko's
> review, if any.

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]

^ permalink raw reply

* Re: [PATCH v2] ARM: OMAP2+: Add CFI type for omap4_finish_suspend
From: kernel test robot @ 2026-05-25 15:18 UTC (permalink / raw)
  To: Mithil Bavishi, Aaro Koskinen, Andreas Kemnade, Kevin Hilman,
	Roger Quadros, Tony Lindgren, Russell King
  Cc: oe-kbuild-all, Sami Tolvanen, Kees Cook, Nathan Chancellor,
	linux-arm-kernel, linux-omap, llvm, linux-kernel, Mithil Bavishi
In-Reply-To: <20260522233036.12277-1-bavishimithil@gmail.com>

Hi Mithil,

kernel test robot noticed the following build errors:

[auto build test ERROR on tmlind-omap/for-next]
[also build test ERROR on linus/master v7.1-rc5 next-20260522]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Mithil-Bavishi/ARM-OMAP2-Add-CFI-type-for-omap4_finish_suspend/20260523-073206
base:   https://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap.git for-next
patch link:    https://lore.kernel.org/r/20260522233036.12277-1-bavishimithil%40gmail.com
patch subject: [PATCH v2] ARM: OMAP2+: Add CFI type for omap4_finish_suspend
config: arm-allyesconfig (https://download.01.org/0day-ci/archive/20260525/202605252315.UhjCBtGA-lkp@intel.com/config)
compiler: arm-linux-gnueabi-gcc (GCC) 15.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260525/202605252315.UhjCBtGA-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202605252315.UhjCBtGA-lkp@intel.com/

All errors (new ones prefixed by >>):

   arch/arm/mach-omap2/sleep44xx.S: Assembler messages:
>> arch/arm/mach-omap2/sleep44xx.S:61: Error: bad instruction `sym_typed_func_start(omap4_finish_suspend)'
>> /tmp/ccmn2Vzn.s: Error: invalid operands (.text and *UND* sections) for `-' when setting `.L__sym_size_omap4_finish_suspend'


vim +61 arch/arm/mach-omap2/sleep44xx.S

    33	
    34	/*
    35	 * =============================
    36	 * == CPU suspend finisher ==
    37	 * =============================
    38	 *
    39	 * void omap4_finish_suspend(unsigned long cpu_state)
    40	 *
    41	 * This function code saves the CPU context and performs the CPU
    42	 * power down sequence. Calling WFI effectively changes the CPU
    43	 * power domains states to the desired target power state.
    44	 *
    45	 * @cpu_state : contains context save state (r0)
    46	 *	0 - No context lost
    47	 * 	1 - CPUx L1 and logic lost: MPUSS CSWR
    48	 * 	2 - CPUx L1 and logic lost + GIC lost: MPUSS OSWR
    49	 *	3 - CPUx L1 and logic lost + GIC + L2 lost: MPUSS OFF
    50	 * @return: This function never returns for CPU OFF and DORMANT power states.
    51	 * Post WFI, CPU transitions to DORMANT or OFF power state and on wake-up
    52	 * from this follows a full CPU reset path via ROM code to CPU restore code.
    53	 * The restore function pointer is stored at CPUx_WAKEUP_NS_PA_ADDR_OFFSET.
    54	 * It returns to the caller for CPU INACTIVE and ON power states or in case
    55	 * CPU failed to transition to targeted OFF/DORMANT state.
    56	 *
    57	 * omap4_finish_suspend() calls v7_flush_dcache_all() which doesn't save
    58	 * stack frame and it expects the caller to take care of it. Hence the entire
    59	 * stack frame is saved to avoid possible stack corruption.
    60	 */
  > 61	SYM_TYPED_FUNC_START(omap4_finish_suspend)
    62		stmfd	sp!, {r4-r12, lr}
    63		cmp	r0, #0x0
    64		beq	do_WFI				@ No lowpower state, jump to WFI
    65	
    66		/*
    67		 * Flush all data from the L1 data cache before disabling
    68		 * SCTLR.C bit.
    69		 */
    70		bl	omap4_get_sar_ram_base
    71		ldr	r9, [r0, #OMAP_TYPE_OFFSET]
    72		cmp	r9, #0x1			@ Check for HS device
    73		bne	skip_secure_l1_clean
    74		mov	r0, #SCU_PM_NORMAL
    75		mov	r1, #0xFF			@ clean seucre L1
    76		stmfd   r13!, {r4-r12, r14}
    77		ldr	r12, =OMAP4_MON_SCU_PWR_INDEX
    78		DO_SMC
    79		ldmfd   r13!, {r4-r12, r14}
    80	skip_secure_l1_clean:
    81		bl	v7_flush_dcache_all
    82	
    83		/*
    84		 * Clear the SCTLR.C bit to prevent further data cache
    85		 * allocation. Clearing SCTLR.C would make all the data accesses
    86		 * strongly ordered and would not hit the cache.
    87		 */
    88		mrc	p15, 0, r0, c1, c0, 0
    89		bic	r0, r0, #(1 << 2)		@ Disable the C bit
    90		mcr	p15, 0, r0, c1, c0, 0
    91		isb
    92	
    93		bl	v7_invalidate_l1
    94	
    95		/*
    96		 * Switch the CPU from Symmetric Multiprocessing (SMP) mode
    97		 * to AsymmetricMultiprocessing (AMP) mode by programming
    98		 * the SCU power status to DORMANT or OFF mode.
    99		 * This enables the CPU to be taken out of coherency by
   100		 * preventing the CPU from receiving cache, TLB, or BTB
   101		 * maintenance operations broadcast by other CPUs in the cluster.
   102		 */
   103		bl	omap4_get_sar_ram_base
   104		mov	r8, r0
   105		ldr	r9, [r8, #OMAP_TYPE_OFFSET]
   106		cmp	r9, #0x1			@ Check for HS device
   107		bne	scu_gp_set
   108		mrc	p15, 0, r0, c0, c0, 5		@ Read MPIDR
   109		ands	r0, r0, #0x0f
   110		ldreq	r0, [r8, #SCU_OFFSET0]
   111		ldrne	r0, [r8, #SCU_OFFSET1]
   112		mov	r1, #0x00
   113		stmfd   r13!, {r4-r12, r14}
   114		ldr	r12, =OMAP4_MON_SCU_PWR_INDEX
   115		DO_SMC
   116		ldmfd   r13!, {r4-r12, r14}
   117		b	skip_scu_gp_set
   118	scu_gp_set:
   119		mrc	p15, 0, r0, c0, c0, 5		@ Read MPIDR
   120		ands	r0, r0, #0x0f
   121		ldreq	r1, [r8, #SCU_OFFSET0]
   122		ldrne	r1, [r8, #SCU_OFFSET1]
   123		bl	omap4_get_scu_base
   124		bl	scu_power_mode
   125	skip_scu_gp_set:
   126		mrc	p15, 0, r0, c1, c1, 2		@ Read NSACR data
   127		tst	r0, #(1 << 18)
   128		mrcne	p15, 0, r0, c1, c0, 1
   129		bicne	r0, r0, #(1 << 6)		@ Disable SMP bit
   130		mcrne	p15, 0, r0, c1, c0, 1
   131		isb
   132		dsb
   133	#ifdef CONFIG_CACHE_L2X0
   134		/*
   135		 * Clean and invalidate the L2 cache.
   136		 * Common cache-l2x0.c functions can't be used here since it
   137		 * uses spinlocks. We are out of coherency here with data cache
   138		 * disabled. The spinlock implementation uses exclusive load/store
   139		 * instruction which can fail without data cache being enabled.
   140		 * OMAP4 hardware doesn't support exclusive monitor which can
   141		 * overcome exclusive access issue. Because of this, CPU can
   142		 * lead to deadlock.
   143		 */
   144		bl	omap4_get_sar_ram_base
   145		mov	r8, r0
   146		mrc	p15, 0, r5, c0, c0, 5		@ Read MPIDR
   147		ands	r5, r5, #0x0f
   148		ldreq	r0, [r8, #L2X0_SAVE_OFFSET0]	@ Retrieve L2 state from SAR
   149		ldrne	r0, [r8, #L2X0_SAVE_OFFSET1]	@ memory.
   150		cmp	r0, #3
   151		bne	do_WFI
   152	#ifdef CONFIG_PL310_ERRATA_727915
   153		mov	r0, #0x03
   154		mov	r12, #OMAP4_MON_L2X0_DBG_CTRL_INDEX
   155		DO_SMC
   156	#endif
   157		bl	omap4_get_l2cache_base
   158		mov	r2, r0
   159		ldr	r0, =0xffff
   160		str	r0, [r2, #L2X0_CLEAN_INV_WAY]
   161	wait:
   162		ldr	r0, [r2, #L2X0_CLEAN_INV_WAY]
   163		ldr	r1, =0xffff
   164		ands	r0, r0, r1
   165		bne	wait
   166	#ifdef CONFIG_PL310_ERRATA_727915
   167		mov	r0, #0x00
   168		mov	r12, #OMAP4_MON_L2X0_DBG_CTRL_INDEX
   169		DO_SMC
   170	#endif
   171	l2x_sync:
   172		bl	omap4_get_l2cache_base
   173		mov	r2, r0
   174		mov	r0, #0x0
   175		str	r0, [r2, #L2X0_CACHE_SYNC]
   176	sync:
   177		ldr	r0, [r2, #L2X0_CACHE_SYNC]
   178		ands	r0, r0, #0x1
   179		bne	sync
   180	#endif
   181	
   182	do_WFI:
   183		bl	omap_do_wfi
   184	
   185		/*
   186		 * CPU is here when it failed to enter OFF/DORMANT or
   187		 * no low power state was attempted.
   188		 */
   189		mrc	p15, 0, r0, c1, c0, 0
   190		tst	r0, #(1 << 2)			@ Check C bit enabled?
   191		orreq	r0, r0, #(1 << 2)		@ Enable the C bit
   192		mcreq	p15, 0, r0, c1, c0, 0
   193		isb
   194	
   195		/*
   196		 * Ensure the CPU power state is set to NORMAL in
   197		 * SCU power state so that CPU is back in coherency.
   198		 * In non-coherent mode CPU can lock-up and lead to
   199		 * system deadlock.
   200		 */
   201		mrc	p15, 0, r0, c1, c0, 1
   202		tst	r0, #(1 << 6)			@ Check SMP bit enabled?
   203		orreq	r0, r0, #(1 << 6)
   204		mcreq	p15, 0, r0, c1, c0, 1
   205		isb
   206		bl	omap4_get_sar_ram_base
   207		mov	r8, r0
   208		ldr	r9, [r8, #OMAP_TYPE_OFFSET]
   209		cmp	r9, #0x1			@ Check for HS device
   210		bne	scu_gp_clear
   211		mov	r0, #SCU_PM_NORMAL
   212		mov	r1, #0x00
   213		stmfd   r13!, {r4-r12, r14}
   214		ldr	r12, =OMAP4_MON_SCU_PWR_INDEX
   215		DO_SMC
   216		ldmfd   r13!, {r4-r12, r14}
   217		b	skip_scu_gp_clear
   218	scu_gp_clear:
   219		bl	omap4_get_scu_base
   220		mov	r1, #SCU_PM_NORMAL
   221		bl	scu_power_mode
   222	skip_scu_gp_clear:
   223		isb
   224		dsb
   225		ldmfd	sp!, {r4-r12, pc}
   226	SYM_FUNC_END(omap4_finish_suspend)
   227	

--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki


^ permalink raw reply

* Re: [RFC net PATCH v1] net: pcs: pcs-mtk-lynxi: fix bpi-r3 serdes configuration
From: Jakub Kicinski @ 2026-05-25 15:28 UTC (permalink / raw)
  To: Frank Wunderlich (linux)
  Cc: Vladimir Oltean, Alexander Couzens, Daniel Golle, Andrew Lunn,
	Heiner Kallweit, Russell King, David S. Miller, Eric Dumazet,
	Paolo Abeni, Matthias Brugger, AngeloGioacchino Del Regno,
	Frank Wunderlich, netdev, linux-kernel, linux-arm-kernel,
	linux-mediatek
In-Reply-To: <64b40fbee19dc108752574419a38bcfc@fw-web.de>

On Mon, 25 May 2026 12:07:33 +0200 Frank Wunderlich (linux) wrote:
> Am 2026-04-09 23:55, schrieb Vladimir Oltean:
> > On Thu, Apr 09, 2026 at 03:33:42PM +0200, Frank Wunderlich wrote:  
> >> From: Frank Wunderlich <frank-w@public-files.de>
> >> 
> >> Commit 8871389da151 introduces common pcs dts properties which writes
> >> rx=normal,tx=normal polarity to register SGMSYS_QPHY_WRAP_CTRL of 
> >> switch.
> >> This is initialized with tx-bit set and so change inverts polarity
> >> compared to before.
> >> 
> >> It looks like mt7531 has tx polarity inverted in hardware and set 
> >> tx-bit
> >> by default to restore the normal polarity.
> >> 
> >> Till this patch the register write was only called when 
> >> mediatek,pnswap
> >> property was set which cannot be done for switch because the fw-node 
> >> param
> >> was always NULL from switch driver in the mtk_pcs_lynxi_create call.
> >> 
> >> Do not configure switch side like it's done before.
> >> 
> >> Fixes: 8871389da151 ("net: pcs: pcs-mtk-lynxi: deprecate 
> >> "mediatek,pnswap"")
> >> Signed-off-by: Frank Wunderlich <frank-w@public-files.de>
> >> ---  
> > 
> > Reviewed-by: Vladimir Oltean <vladimir.oltean@nxp.com>  
> 
> just a gentle ping as i still not see this in torvalds/master.
 
You posted it as RFC, patchwork treats RFC as "no action required".
Since the posting is now >1mo old, please resend without the RFC tag?


^ permalink raw reply

* RE: [PATCH v2] iommu: Allow device driver to use its own PASID space for SVA
From: Joonwon Kang @ 2026-05-25 15:29 UTC (permalink / raw)
  To: kevin.tian
  Cc: Alexander.Grest, alexander.shishkin, amhetre, baolu.lu, bp,
	dave.hansen, easwar.hariharan, hpa, iommu, jacob.jun.pan, jgg,
	joonwonkang, joro, jpb, kas, kees, linux-arm-kernel, linux-kernel,
	mingo, nicolinc, peterz, praan, robin.murphy, ryasuoka, smostafa,
	sohil.mehta, tglx, will, x86, xin
In-Reply-To: <BL1PR11MB52710D3CCFA2F75F6B540A468C0A2@BL1PR11MB5271.namprd11.prod.outlook.com>

Hi Kevin, thanks for your review.

> > This commit resolves the issue by allowing device driver to maintain its
> > own PASID space and assign a PASID from that for the process-device bond
> > via a new API called `iommu_sva_bind_device_pasid(dev, mm, pasid)`. Doing
> > that, however, will disallow the process to execute the ENQCMD-like
> > instructions at EL0. It is because the process cannot change its PASID in
> > IA32_PASID(or ACCDATA_EL1 on ARM) for each device without the kernel's
> > intervention. For this reason, calling `iommu_sva_bind_device()` and then
> > `iommu_sva_bind_device_pasid()` for the same process will not be allowed
> > and vice versa.
> > 
> > Currently, there is a limitation that a process simultaneously doing SVA
> > with multiple devices with different PASIDs is not supported. So, calling
> > `iommu_sva_bind_device_pasid()` multiple times for the same process with
> > different devices will not be allowed for now while that for
> > `iommu_sva_bind_device()` will be.
> > 
> > Another limitation is that a process cannot do `iommu_sva_bind_device()`
> > if it has ever done `iommu_sva_bind_device_pasid()` even though it has
> > been unbound after use.
> 
> Why not making it clean in one step instead of leaving many unsupported
> cases which are likely required soon in this "1" to "many" transition?
> 

Since I did not know much about the IOMMU team's future plans on the IOMMU
core structure, I narrowed down the scope just enough to resolve our
specific problem and avoided introducing big change. But now that I have
two queries to support the 1-to-many relationships in this patchset, not
in a later one, I think it is fair enough to start working on it now. I
will try it and lift the limitations.

> for each mm:
> - one global pasid for ENQCMD or ST64BV0
> - an array of device local pasids tracked in [struct device *, pasid] tuple.
> 
> upon gp fault or equivalent, fetch the global pasid.
> 
> upon device-specific bind, match [dev, pasid].
> 
> > 
> > Suggested-by: Jason Gunthorpe <jgg@ziepe.ca>
> > Suggested-by: Kevin Tian <kevin.tian@intel.com>
> > Signed-off-by: Joonwon Kang <joonwonkang@google.com>
> > ---
> > v2: Reuse iommu_mm->pasid after SVA bound by
> > iommu_sva_bind_device_pasid()
> >     is unbound.
> 
> No idea what it talks about.
> 

There was a bug in v1 that the second call for `iommu_sva_bind_device_pasid()`
failed after the first call with a different PASID was released. Will
rephrase it in a clearer language in v3.

> btw a new kAPI always needs accompanied users to review together.

Currently, the only known expected user of the new kAPI is our team. Since
I test if the patch resolves our problem before sending it, I believe it
should be good enough. Do you mean more than our team by "accompanied
users"?

Thanks,
Joonwon Kang


^ permalink raw reply

* Re: [PATCH v4 0/3] ASoC: soc-core: Add core support for ignoring suspend on selected DAPM widgets
From: Mark Brown @ 2026-05-25 12:38 UTC (permalink / raw)
  To: lgirdwood, perex, tiwai, shengjiu.wang, Xiubo.Lee, festevam,
	nicoleotsuka, Frank.Li, s.hauer, Chancel Liu
  Cc: kernel, shumingf, pierre-louis.bossart, linux-sound, linux-kernel,
	linuxppc-dev, imx, linux-arm-kernel
In-Reply-To: <20260507013654.2945915-1-chancel.liu@nxp.com>

On Thu, 07 May 2026 10:36:51 +0900, Chancel Liu wrote:
> ASoC: soc-core: Add core support for ignoring suspend on selected DAPM widgets
> 
> Some audio systems require specific DAPM widgets to remain powered
> during system suspend. Introduce a generic and reusable mechanism in
> the ASoC core to mark selected DAPM widgets as ignore_suspend.
> 
> The unified mechanism consists of two parts:
> 1. Parse and store the name list of widgets to ignore suspend in
> struct snd_soc_card
> 
> [...]

Applied to

   https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git for-7.2

Thanks!

[1/3] ASoC: dapm: Fix widget lookup with prefixed names across DAPM contexts
      https://git.kernel.org/broonie/sound/c/8468c8aafe8b
[2/3] ASoC: soc-core: Add core support for ignoring suspend on selected DAPM widgets
      https://git.kernel.org/broonie/sound/c/51271184a06d
[3/3] ASoC: fsl: imx-rpmsg: Switch to core ignore-suspend-widgets support
      https://git.kernel.org/broonie/sound/c/68bb9a7f557a

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

Thanks,
Mark



^ permalink raw reply

* Re: [PATCH v2 0/2] ASoC: codecs: max98090: switch to standard set_jack callback
From: Mark Brown @ 2026-05-25 12:39 UTC (permalink / raw)
  To: Srinivas Kandagatla
  Cc: lgirdwood, perex, tiwai, matthias.bgg, angelogioacchino.delregno,
	sharq0406, kuninori.morimoto.gx, ckeepax, linux-sound,
	linux-kernel, linux-arm-kernel, linux-mediatek
In-Reply-To: <20260520155002.145306-1-srinivas.kandagatla@oss.qualcomm.com>

On Wed, 20 May 2026 15:50:00 +0000, Srinivas Kandagatla wrote:
> ASoC: codecs: max98090: switch to standard set_jack callback
> 
> The MAX98090 codec driver currently exposes a custom
> max98090_mic_detect() helper for machine drivers to register a headset
> jack.
> 
> This series converts the driver to use the standard component
> .set_jack callback and updates the mt8173-max98090 machine driver to use
> snd_soc_component_set_jack() instead of the codec-specific helper.
> 
> [...]

Applied to

   https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git for-7.2

Thanks!

[1/2] ASoC: mt8173-max98090: use standard callback to set jack
      https://git.kernel.org/broonie/sound/c/bad83abb5c29
[2/2] ASoC: codecs: max98090: use component set_jack callback
      https://git.kernel.org/broonie/sound/c/e2c428c3832e

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

Thanks,
Mark



^ permalink raw reply

* Re: [PATCHSET v4 sched_ext/for-7.2] bpf/arena: Direct kernel-side access
From: Alexei Starovoitov @ 2026-05-25 15:45 UTC (permalink / raw)
  To: Tejun Heo
  Cc: David Vernet, Andrea Righi, Changwoo Min, Alexei Starovoitov,
	Andrii Nakryiko, Daniel Borkmann, Martin KaFai Lau,
	Kumar Kartikeya Dwivedi, Peter Zijlstra, Catalin Marinas,
	Will Deacon, Thomas Gleixner, Ingo Molnar, Borislav Petkov,
	Dave Hansen, Andrew Morton, David Hildenbrand, Mike Rapoport,
	Emil Tsalapatis, sched-ext, bpf, X86 ML, linux-arm-kernel,
	linux-mm, LKML
In-Reply-To: <20260522172219.1423324-1-tj@kernel.org>

On Fri, May 22, 2026 at 10:22 AM Tejun Heo <tj@kernel.org> wrote:
>
> Patches 1-2 (atomic PTE install + arena scratch-page recovery)
> --------------------------------------------------------------
>
>   mm: Add ptep_try_set() for lockless empty-slot installs
>   bpf: Recover arena kernel faults with scratch page
>
> Patches 3-5 (helpers used by struct_ops registration)
> -----------------------------------------------------
>
>   bpf: Add sleepable variant of bpf_arena_alloc_pages for kernel callers
>   bpf: Add bpf_struct_ops_for_each_prog()
>   bpf/arena: Add bpf_arena_map_kern_vm_start() and bpf_prog_arena()
>
> Patches 6-8 (sched_ext: arena auto-discovery, allocator, set_cmask)
> -------------------------------------------------------------------
>
>   sched_ext: Require an arena for cid-form schedulers
>   sched_ext: Sub-allocator over kernel-claimed BPF arena pages
>   sched_ext: Convert ops.set_cmask() to arena-resident cmask
>
> Patch 6 reads each member prog's prog->aux->arena via bpf_prog_arena() and
> requires the cid-form struct_ops to reference exactly one arena. Patch 7
> builds a gen_pool sub-allocator inside that arena. Patch 8 converts
> set_cmask() to write into arena memory. BPF dereferences via __arena like
> any other arena struct, no probe-reads.
>
> Base
> ----
>
> sched_ext/for-7.2 (f31e89a8f583)
>
> Git tree: git://git.kernel.org/pub/scm/linux/kernel/git/tj/sched_ext.git arena-direct-v4

I created a stable branch bpf-next/arena_direct_access
with the first 5 patches and merged it into bpf-next/master.

Tejun,
please pull it into sched-ext tree as well.

Let's do any follow ups on top.

Thanks everyone!


^ permalink raw reply

* Re: [PATCH 1/8] mm: Add ptep_try_set() for lockless empty-slot installs
From: patchwork-bot+netdevbpf @ 2026-05-25 15:50 UTC (permalink / raw)
  To: Tejun Heo
  Cc: void, arighi, changwoo, ast, andrii, daniel, martin.lau, memxor,
	peterz, catalin.marinas, will, tglx, mingo, bp, dave.hansen, akpm,
	david, rppt, emil, sched-ext, bpf, x86, linux-arm-kernel,
	linux-mm, linux-kernel
In-Reply-To: <20260522172219.1423324-2-tj@kernel.org>

Hello:

This series was applied to bpf/bpf-next.git (master)
by Alexei Starovoitov <ast@kernel.org>:

On Fri, 22 May 2026 07:22:12 -1000 you wrote:
> Add ptep_try_set(ptep, new_pte): atomically set *ptep to new_pte iff it is
> currently pte_none(). Returns true on success, false if the slot was already
> populated or the arch has no implementation.
> 
> The intended caller is the upcoming bpf_arena kernel-side fault recovery
> path. The install runs from a page fault that can be nested under locks
> held by the faulting kernel caller (e.g. a BPF program holding
> raw_res_spin_lock_irqsave on its arena's spinlock), so trylock-and-retry
> would A-A deadlock. Lock-free cmpxchg is the only viable option, which
> constrains this helper to special kernel page tables where concurrent
> writers cooperate via atomic accessors.
> 
> [...]

Here is the summary with links:
  - [1/8] mm: Add ptep_try_set() for lockless empty-slot installs
    https://git.kernel.org/bpf/bpf-next/c/258df8fce42f
  - [2/8] bpf: Recover arena kernel faults with scratch page
    (no matching commit)
  - [3/8] bpf: Add sleepable variant of bpf_arena_alloc_pages for kernel callers
    https://git.kernel.org/bpf/bpf-next/c/f211c81ddc36
  - [4/8] bpf: Add bpf_struct_ops_for_each_prog()
    https://git.kernel.org/bpf/bpf-next/c/7c48a28c1bbe
  - [5/8] bpf/arena: Add bpf_arena_map_kern_vm_start() and bpf_prog_arena()
    https://git.kernel.org/bpf/bpf-next/c/53cc12a2dc88
  - [6/8] sched_ext: Require an arena for cid-form schedulers
    (no matching commit)
  - [7/8] sched_ext: Sub-allocator over kernel-claimed BPF arena pages
    (no matching commit)
  - [8/8] sched_ext: Convert ops.set_cmask() to arena-resident cmask
    (no matching commit)

You are awesome, thank you!
-- 
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html




^ permalink raw reply

* Re: [PATCH 1/8] mm: Add ptep_try_install() for lockless empty-slot installs
From: patchwork-bot+netdevbpf @ 2026-05-25 15:50 UTC (permalink / raw)
  To: Tejun Heo
  Cc: void, arighi, changwoo, ast, andrii, daniel, martin.lau, memxor,
	catalin.marinas, will, tglx, mingo, bp, dave.hansen, akpm, david,
	rppt, emil, sched-ext, bpf, x86, linux-arm-kernel, linux-mm,
	linux-kernel
In-Reply-To: <20260517211232.1670594-2-tj@kernel.org>

Hello:

This series was applied to bpf/bpf-next.git (master)
by Alexei Starovoitov <ast@kernel.org>:

On Sun, 17 May 2026 11:12:25 -1000 you wrote:
> Add ptep_try_install(ptep, new_pte): atomically set *ptep to new_pte
> iff it is currently pte_none(). Returns true on success, false if the
> slot was already populated or the arch has no implementation.
> 
> The intended caller is the upcoming bpf_arena kernel-side fault
> recovery path. The install runs from a page fault and may have to
> contend with locks already held by the faulting kernel caller, so
> keeping it lock-free via cmpxchg is the safe choice.
> 
> [...]

Here is the summary with links:
  - [1/8] mm: Add ptep_try_install() for lockless empty-slot installs
    (no matching commit)
  - [2/8] bpf: Recover arena kernel faults with scratch page
    (no matching commit)
  - [3/8] bpf: Add sleepable variant of bpf_arena_alloc_pages for kernel callers
    https://git.kernel.org/bpf/bpf-next/c/f211c81ddc36
  - [4/8] bpf: Add bpf_struct_ops_for_each_prog()
    https://git.kernel.org/bpf/bpf-next/c/7c48a28c1bbe
  - [5/8] bpf/arena: Add bpf_arena_map_kern_vm_start() and bpf_prog_arena()
    https://git.kernel.org/bpf/bpf-next/c/53cc12a2dc88
  - [6/8] sched_ext: Require an arena for cid-form schedulers
    (no matching commit)
  - [7/8] sched_ext: Sub-allocator over kernel-claimed BPF arena pages
    (no matching commit)
  - [8/8] sched_ext: Convert ops.set_cmask() to arena-resident cmask
    (no matching commit)

You are awesome, thank you!
-- 
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html




^ permalink raw reply

* Re: [PATCH net-next] net: airoha: bind WLAN-bound flows on PPE driver L2 cache miss
From: Jihong Min @ 2026-05-25 16:05 UTC (permalink / raw)
  To: Lorenzo Bianconi
  Cc: netdev, Andrew Lunn, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, linux-arm-kernel, linux-mediatek,
	linux-kernel
In-Reply-To: <ahRonGRDCqdFTBQm@lore-desk>



On 5/26/26 00:19, Lorenzo Bianconi wrote:
>>
>>
>> On 5/25/26 17:09, Lorenzo Bianconi wrote:
>>>> The Linux bridge FDB can resolve a destination station to WDMA even when
>>>> the Airoha PPE driver's L2 offload cache has no entry for that MAC pair.
>>>> The normal bind path only checks the PPE driver's L2 offload cache, so an
>>>> unbound PPE hit for WLAN egress can stay unbound even though the bridge
>>>> already knows the right output path, unless a later offload event fills
>>>> that PPE driver cache.
>>>>
>>>> This matters for bridge-visible WLAN egress, such as wired-to-WLAN
>>>> forwarding or WLAN peer forwarding across another BSS, radio or MLO link.
>>>> Same-link or same-radio intra-BSS forwarding can stay inside the WLAN
>>>> datapath and is not covered.
>>>
>>> Hi Jihong,
>>
>> Hi, Lorenzo.
>>
>>>
>>> In order to offload L2 flows, I assume you are using the OpenWrt bridger
>>> package, right?
>>
>> Actually, no.
>>
>> I am using Fanboy's OpenWrt `test` build for the Lumen W1700K2,
>> together with several of my other patches. It does not include the
>> bridger package specifically. It now uses native nft-based offloading
>> with `kmod-br-netfilter`.
> 
> according to my understanding this is not merged yet, right? I guess the
> patches should be based on official/accepted code.
> 

Yes, you are right. I just checked current net-next and realized that the
bridge/L2 nft_flow_offload pieces used in my test environment are not
merged upstream yet. Sorry, I should have checked this before submitting
the patch.

Since I cannot properly test the current upstream code plus bridger at the
moment, I will put this patch on hold.

I will also check whether this should instead be fixed on the
nft_flow_offload side.


Sincerely,
Jihong Min

>>
>>> IIUC the issue you want to resolve is we are not adding PPE L2 entries for
>>> the specified cases (same-link or same-radio intra-BSS forwarding), correct?
>>
>> No. As written in the patch message, this specifically addresses
>> bridge-visible WLAN egress, such as:
>>
>> 1. wired-to-WLAN forwarding
>> 2. WLAN peer forwarding across another BSS, radio, or MLO link
>>
>> Same-link or same-radio intra-BSS forwarding can stay inside the WLAN
>> datapath and is not covered by this patch, although it did show poor
>> performance, whether that is due to shared airtime or not. That case
>> appears to belong to the Wi-Fi stack/driver datapath, such as the
>> mac80211/mt76/mt7996 path, rather than to this Airoha PPE fallback path.
> 
> according to my understanding the l2 nft-based offloading solution should
> add the missing info to PPE flow-table. As I pointed out, it should be
> in-sync with hw flow-table. It seems a bug in the nft code to me.
> 
>>
>>> Using this approach, we are breaking the assumption PPE flow-table and hw
>>> flow-table are in sync. If the issue is the one described above, why not
>>> fixing the problem directly in the bridger package?
>>
>> Again, this problem exists in an environment without bridger.
> 
> In order to offload L2 traffic bridger is mandatory. Do you mean the issue
> occurs even on L3 scenario?
> 
>>
>>> Moreover, I see you developed the patch using Codex:gpt-5.5. Have you tested it
>>> on a real hw?
>>
>> Yes. This has been tested on my Lumen W1700K2 with the environment
>> described above. MLO Wi-Fi P2P communication and some wired-to-WLAN
>> cases were indeed left unbound by PPE. CPU usage was high, and the
>> unbound throughput was close to 50% of what this patch achieves now.
> 
> ack
> 
> Regards,
> Lorenzo
> 
>>
>>>
>>> Some comments inline.
>>>
>>> Regards,
>>> Lorenzo
>>>>>
>>>> Before touching the PPE table, resolve the destination MAC through the
>>>> bridge device above the ingress netdev. If the PPE driver's L2 offload
>>>> cache lookup misses, bind the hardware flow to the resolved CDM4/WDMA
>>>> path.
>>>>
>>>> Assisted-by: Codex:gpt-5.5
>>>> Signed-off-by: Jihong Min <hurryman2212@gmail.com>
>>>> ---
>>>>  drivers/net/ethernet/airoha/airoha_ppe.c | 138 +++++++++++++++++++----
>>>>  1 file changed, 119 insertions(+), 19 deletions(-)
>>>>
>>>> diff --git a/drivers/net/ethernet/airoha/airoha_ppe.c b/drivers/net/ethernet/airoha/airoha_ppe.c
>>>> index 26da519236bf..ea932e6d87f6 100644
>>>> --- a/drivers/net/ethernet/airoha/airoha_ppe.c
>>>> +++ b/drivers/net/ethernet/airoha/airoha_ppe.c
>>>> @@ -803,65 +803,163 @@ static void airoha_ppe_foe_flow_remove_entry(struct airoha_ppe *ppe,
>>>>  }
>>>>  
>>>>  static int
>>>> -airoha_ppe_foe_commit_subflow_entry(struct airoha_ppe *ppe,
>>>> -				    struct airoha_flow_table_entry *e,
>>>> -				    u32 hash, bool rx_wlan)
>>>> +airoha_ppe_foe_commit_subflow(struct airoha_ppe *ppe,
>>>> +			      const struct airoha_foe_entry *bridge,
>>>
>>> maybe l2_hwe instead of bridge?
>>>
>>>> +			      u32 hash, bool rx_wlan)
>>>>  {
>>>>  	u32 mask = AIROHA_FOE_IB1_BIND_PACKET_TYPE | AIROHA_FOE_IB1_BIND_UDP;
>>>>  	struct airoha_foe_entry *hwe_p, hwe;
>>>> -	struct airoha_flow_table_entry *f;
>>>>  	int type;
>>>>  
>>>>  	hwe_p = airoha_ppe_foe_get_entry_locked(ppe, hash);
>>>>  	if (!hwe_p)
>>>>  		return -EINVAL;
>>>>  
>>>> -	f = kzalloc_obj(*f, GFP_ATOMIC);
>>>> -	if (!f)
>>>> -		return -ENOMEM;
>>>> -
>>>> -	hlist_add_head(&f->l2_subflow_node, &e->l2_flows);
>>>> -	f->type = FLOW_TYPE_L2_SUBFLOW;
>>>> -	f->hash = hash;
>>>> -
>>>>  	memcpy(&hwe, hwe_p, sizeof(*hwe_p));
>>>> -	hwe.ib1 = (hwe.ib1 & mask) | (e->data.ib1 & ~mask);
>>>> +	hwe.ib1 = (hwe.ib1 & mask) | (bridge->ib1 & ~mask);
>>>>  
>>>>  	type = FIELD_GET(AIROHA_FOE_IB1_BIND_PACKET_TYPE, hwe.ib1);
>>>>  	if (type >= PPE_PKT_TYPE_IPV6_ROUTE_3T) {
>>>> -		memcpy(&hwe.ipv6.l2, &e->data.bridge.l2, sizeof(hwe.ipv6.l2));
>>>> -		hwe.ipv6.ib2 = e->data.bridge.ib2;
>>>> +		memcpy(&hwe.ipv6.l2, &bridge->bridge.l2,
>>>> +		       sizeof(hwe.ipv6.l2));
>>>> +		hwe.ipv6.ib2 = bridge->bridge.ib2;
>>>>  		/* setting smac_id to 0xf instruct the hw to keep original
>>>>  		 * source mac address
>>>>  		 */
>>>>  		hwe.ipv6.l2.src_mac_hi = FIELD_PREP(AIROHA_FOE_MAC_SMAC_ID,
>>>>  						    0xf);
>>>>  	} else {
>>>> -		memcpy(&hwe.bridge.l2, &e->data.bridge.l2,
>>>> +		memcpy(&hwe.bridge.l2, &bridge->bridge.l2,
>>>>  		       sizeof(hwe.bridge.l2));
>>>> -		hwe.bridge.ib2 = e->data.bridge.ib2;
>>>> +		hwe.bridge.ib2 = bridge->bridge.ib2;
>>>>  		if (type == PPE_PKT_TYPE_IPV4_HNAPT)
>>>>  			memcpy(&hwe.ipv4.new_tuple, &hwe.ipv4.orig_tuple,
>>>>  			       sizeof(hwe.ipv4.new_tuple));
>>>>  	}
>>>>  
>>>> -	hwe.bridge.data = e->data.bridge.data;
>>>> -	airoha_ppe_foe_commit_entry(ppe, &hwe, hash, rx_wlan);
>>>> +	hwe.bridge.data = bridge->bridge.data;
>>>> +
>>>> +	return airoha_ppe_foe_commit_entry(ppe, &hwe, hash, rx_wlan);
>>>> +}
>>>> +
>>>> +static int
>>>> +airoha_ppe_foe_commit_subflow_entry(struct airoha_ppe *ppe,
>>>> +				    struct airoha_flow_table_entry *e,
>>>> +				    u32 hash, bool rx_wlan)
>>>> +{
>>>> +	struct airoha_flow_table_entry *f;
>>>> +	int err;
>>>> +
>>>> +	f = kzalloc_obj(*f, GFP_ATOMIC);
>>>> +	if (!f)
>>>> +		return -ENOMEM;
>>>> +
>>>> +	err = airoha_ppe_foe_commit_subflow(ppe, &e->data, hash, rx_wlan);
>>>> +	if (err) {
>>>> +		kfree(f);
>>>> +		return err;
>>>> +	}
>>>> +
>>>> +	hlist_add_head(&f->l2_subflow_node, &e->l2_flows);
>>>> +	f->type = FLOW_TYPE_L2_SUBFLOW;
>>>> +	f->hash = hash;
>>>>  
>>>>  	return 0;
>>>>  }
>>>>  
>>>> +static bool
>>>> +airoha_ppe_foe_prepare_wdma_subflow_dev(struct airoha_ppe *ppe,
>>>> +					struct net_device *dev,
>>>> +					struct airoha_flow_data *data,
>>>> +					struct airoha_foe_entry *hwe)
>>>> +{
>>>> +	u32 pse_port;
>>>> +	int err;
>>>> +
>>>> +	err = airoha_ppe_foe_entry_prepare(ppe->eth, hwe, dev,
>>>> +					   PPE_PKT_TYPE_BRIDGE, data, 0);
>>>> +	if (err)
>>>> +		return false;
>>>> +
>>>> +	pse_port = FIELD_GET(AIROHA_FOE_IB2_PSE_PORT, hwe->bridge.ib2);
>>>> +	if (pse_port != FE_PSE_PORT_CDM4)
>>>> +		return false;
>>>> +
>>>> +	return true;
>>>
>>> 	return pse_port == FE_PSE_PORT_CDM4;
>>>
>>>> +}
>>>> +
>>>> +static struct net_device *
>>>> +airoha_ppe_foe_get_bridge_master(struct net_device *dev)
>>>> +{
>>>> +	struct net_device *master = NULL;
>>>> +
>>>> +	rcu_read_lock();
>>>> +	master = netdev_master_upper_dev_get_rcu(dev);
>>>> +	if (master && netif_is_bridge_master(master))
>>>> +		dev_hold(master);
>>>> +	else
>>>> +		master = NULL;
>>>> +	rcu_read_unlock();
>>>> +
>>>> +	return master;
>>>> +}
>>>> +
>>>> +static bool
>>>> +airoha_ppe_foe_prepare_wdma_subflow(struct airoha_ppe *ppe,
>>>> +				    struct sk_buff *skb,
>>>> +				    struct airoha_foe_entry *hwe)
>>>> +{
>>>> +	struct ethhdr *eh = eth_hdr(skb);
>>>> +	struct airoha_flow_data data = {};
>>>> +	struct net_device *master;
>>>> +
>>>> +	if (!is_valid_ether_addr(eh->h_source) ||
>>>> +	    !is_valid_ether_addr(eh->h_dest))
>>>> +		return false;
>>>> +
>>>> +	ether_addr_copy(data.eth.h_dest, eh->h_dest);
>>>> +	ether_addr_copy(data.eth.h_source, eh->h_source);
>>>> +
>>>> +	if (!skb->dev)
>>>> +		return false;
>>>> +
>>>> +	/* WLAN egress unbound hits can arrive before flowtable creates the
>>>> +	 * L2 master flow normally used for subflow binding. Resolve only
>>>> +	 * through the bridge master so dev_fill_forward_path() must use the
>>>> +	 * bridge FDB for the destination MAC. Calling the ingress AP netdev
>>>> +	 * directly can describe the source station's WDMA path and would
>>>> +	 * corrupt Wi-Fi-to-wired flows whose real egress is not WDMA.
>>>> +	 */
>>>> +	master = airoha_ppe_foe_get_bridge_master(skb->dev);
>>>> +	if (!master)
>>>> +		return false;
>>>> +
>>>> +	if (airoha_ppe_foe_prepare_wdma_subflow_dev(ppe, master, &data,
>>>> +						    hwe)) {
>>>> +		dev_put(master);
>>>> +		return true;
>>>> +	}
>>>> +
>>>> +	dev_put(master);
>>>> +	return false;
>>>
>>> maybe something like:
>>>
>>> 	ret = airoha_ppe_foe_prepare_wdma_subflow_dev();
>>> 	dev_put(master);
>>>
>>> 	return ret;
>>>
>>>> +}
>>>> +
>>>>  static void airoha_ppe_foe_insert_entry(struct airoha_ppe *ppe,
>>>>  					struct sk_buff *skb,
>>>>  					u32 hash, bool rx_wlan)
>>>>  {
>>>> +	struct airoha_foe_entry wdma_hwe = {};
>>>>  	struct airoha_flow_table_entry *e;
>>>>  	struct airoha_foe_bridge br = {};
>>>>  	struct airoha_foe_entry *hwe;
>>>>  	bool commit_done = false;
>>>> +	bool wdma_ready = false;
>>>>  	struct hlist_node *n;
>>>>  	u32 index, state;
>>>>  
>>>> +	wdma_ready = airoha_ppe_foe_prepare_wdma_subflow(ppe, skb,
>>>> +							 &wdma_hwe);
>>>> +
>>>>  	spin_lock_bh(&ppe_lock);
>>>>  
>>>>  	hwe = airoha_ppe_foe_get_entry_locked(ppe, hash);
>>>> @@ -899,6 +997,8 @@ static void airoha_ppe_foe_insert_entry(struct airoha_ppe *ppe,
>>>>  				   airoha_l2_flow_table_params);
>>>>  	if (e)
>>>>  		airoha_ppe_foe_commit_subflow_entry(ppe, e, hash, rx_wlan);
>>>> +	else if (wdma_ready)
>>>> +		airoha_ppe_foe_commit_subflow(ppe, &wdma_hwe, hash, rx_wlan);
>>>>  unlock:
>>>>  	spin_unlock_bh(&ppe_lock);
>>>>  }
>>>> -- 
>>>> 2.53.0
>>>>
>>
>> All inline code-style review comments will be addressed in the next
>> submission of the patch set, together with the responses to Sashiko's
>> review, if any.



^ permalink raw reply

* Re: [PATCH net-next] net: airoha: bind WLAN-bound flows on PPE driver L2 cache miss
From: Lorenzo Bianconi @ 2026-05-25 16:32 UTC (permalink / raw)
  To: Jihong Min
  Cc: netdev, Andrew Lunn, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, linux-arm-kernel, linux-mediatek,
	linux-kernel
In-Reply-To: <82d0e4a5-76b1-4c86-a153-2500c60e8063@gmail.com>

[-- Attachment #1: Type: text/plain, Size: 12161 bytes --]

> 
> 
> On 5/26/26 00:19, Lorenzo Bianconi wrote:
> >>
> >>
> >> On 5/25/26 17:09, Lorenzo Bianconi wrote:
> >>>> The Linux bridge FDB can resolve a destination station to WDMA even when
> >>>> the Airoha PPE driver's L2 offload cache has no entry for that MAC pair.
> >>>> The normal bind path only checks the PPE driver's L2 offload cache, so an
> >>>> unbound PPE hit for WLAN egress can stay unbound even though the bridge
> >>>> already knows the right output path, unless a later offload event fills
> >>>> that PPE driver cache.
> >>>>
> >>>> This matters for bridge-visible WLAN egress, such as wired-to-WLAN
> >>>> forwarding or WLAN peer forwarding across another BSS, radio or MLO link.
> >>>> Same-link or same-radio intra-BSS forwarding can stay inside the WLAN
> >>>> datapath and is not covered.
> >>>
> >>> Hi Jihong,
> >>
> >> Hi, Lorenzo.
> >>
> >>>
> >>> In order to offload L2 flows, I assume you are using the OpenWrt bridger
> >>> package, right?
> >>
> >> Actually, no.
> >>
> >> I am using Fanboy's OpenWrt `test` build for the Lumen W1700K2,
> >> together with several of my other patches. It does not include the
> >> bridger package specifically. It now uses native nft-based offloading
> >> with `kmod-br-netfilter`.
> > 
> > according to my understanding this is not merged yet, right? I guess the
> > patches should be based on official/accepted code.
> > 
> 
> Yes, you are right. I just checked current net-next and realized that the
> bridge/L2 nft_flow_offload pieces used in my test environment are not
> merged upstream yet. Sorry, I should have checked this before submitting
> the patch.

ack, no worries ;)

> 
> Since I cannot properly test the current upstream code plus bridger at the
> moment, I will put this patch on hold.
> 
> I will also check whether this should instead be fixed on the
> nft_flow_offload side.

ack.

Regards,
Lorenzo

> 
> 
> Sincerely,
> Jihong Min
> 
> >>
> >>> IIUC the issue you want to resolve is we are not adding PPE L2 entries for
> >>> the specified cases (same-link or same-radio intra-BSS forwarding), correct?
> >>
> >> No. As written in the patch message, this specifically addresses
> >> bridge-visible WLAN egress, such as:
> >>
> >> 1. wired-to-WLAN forwarding
> >> 2. WLAN peer forwarding across another BSS, radio, or MLO link
> >>
> >> Same-link or same-radio intra-BSS forwarding can stay inside the WLAN
> >> datapath and is not covered by this patch, although it did show poor
> >> performance, whether that is due to shared airtime or not. That case
> >> appears to belong to the Wi-Fi stack/driver datapath, such as the
> >> mac80211/mt76/mt7996 path, rather than to this Airoha PPE fallback path.
> > 
> > according to my understanding the l2 nft-based offloading solution should
> > add the missing info to PPE flow-table. As I pointed out, it should be
> > in-sync with hw flow-table. It seems a bug in the nft code to me.
> > 
> >>
> >>> Using this approach, we are breaking the assumption PPE flow-table and hw
> >>> flow-table are in sync. If the issue is the one described above, why not
> >>> fixing the problem directly in the bridger package?
> >>
> >> Again, this problem exists in an environment without bridger.
> > 
> > In order to offload L2 traffic bridger is mandatory. Do you mean the issue
> > occurs even on L3 scenario?
> > 
> >>
> >>> Moreover, I see you developed the patch using Codex:gpt-5.5. Have you tested it
> >>> on a real hw?
> >>
> >> Yes. This has been tested on my Lumen W1700K2 with the environment
> >> described above. MLO Wi-Fi P2P communication and some wired-to-WLAN
> >> cases were indeed left unbound by PPE. CPU usage was high, and the
> >> unbound throughput was close to 50% of what this patch achieves now.
> > 
> > ack
> > 
> > Regards,
> > Lorenzo
> > 
> >>
> >>>
> >>> Some comments inline.
> >>>
> >>> Regards,
> >>> Lorenzo
> >>>>>
> >>>> Before touching the PPE table, resolve the destination MAC through the
> >>>> bridge device above the ingress netdev. If the PPE driver's L2 offload
> >>>> cache lookup misses, bind the hardware flow to the resolved CDM4/WDMA
> >>>> path.
> >>>>
> >>>> Assisted-by: Codex:gpt-5.5
> >>>> Signed-off-by: Jihong Min <hurryman2212@gmail.com>
> >>>> ---
> >>>>  drivers/net/ethernet/airoha/airoha_ppe.c | 138 +++++++++++++++++++----
> >>>>  1 file changed, 119 insertions(+), 19 deletions(-)
> >>>>
> >>>> diff --git a/drivers/net/ethernet/airoha/airoha_ppe.c b/drivers/net/ethernet/airoha/airoha_ppe.c
> >>>> index 26da519236bf..ea932e6d87f6 100644
> >>>> --- a/drivers/net/ethernet/airoha/airoha_ppe.c
> >>>> +++ b/drivers/net/ethernet/airoha/airoha_ppe.c
> >>>> @@ -803,65 +803,163 @@ static void airoha_ppe_foe_flow_remove_entry(struct airoha_ppe *ppe,
> >>>>  }
> >>>>  
> >>>>  static int
> >>>> -airoha_ppe_foe_commit_subflow_entry(struct airoha_ppe *ppe,
> >>>> -				    struct airoha_flow_table_entry *e,
> >>>> -				    u32 hash, bool rx_wlan)
> >>>> +airoha_ppe_foe_commit_subflow(struct airoha_ppe *ppe,
> >>>> +			      const struct airoha_foe_entry *bridge,
> >>>
> >>> maybe l2_hwe instead of bridge?
> >>>
> >>>> +			      u32 hash, bool rx_wlan)
> >>>>  {
> >>>>  	u32 mask = AIROHA_FOE_IB1_BIND_PACKET_TYPE | AIROHA_FOE_IB1_BIND_UDP;
> >>>>  	struct airoha_foe_entry *hwe_p, hwe;
> >>>> -	struct airoha_flow_table_entry *f;
> >>>>  	int type;
> >>>>  
> >>>>  	hwe_p = airoha_ppe_foe_get_entry_locked(ppe, hash);
> >>>>  	if (!hwe_p)
> >>>>  		return -EINVAL;
> >>>>  
> >>>> -	f = kzalloc_obj(*f, GFP_ATOMIC);
> >>>> -	if (!f)
> >>>> -		return -ENOMEM;
> >>>> -
> >>>> -	hlist_add_head(&f->l2_subflow_node, &e->l2_flows);
> >>>> -	f->type = FLOW_TYPE_L2_SUBFLOW;
> >>>> -	f->hash = hash;
> >>>> -
> >>>>  	memcpy(&hwe, hwe_p, sizeof(*hwe_p));
> >>>> -	hwe.ib1 = (hwe.ib1 & mask) | (e->data.ib1 & ~mask);
> >>>> +	hwe.ib1 = (hwe.ib1 & mask) | (bridge->ib1 & ~mask);
> >>>>  
> >>>>  	type = FIELD_GET(AIROHA_FOE_IB1_BIND_PACKET_TYPE, hwe.ib1);
> >>>>  	if (type >= PPE_PKT_TYPE_IPV6_ROUTE_3T) {
> >>>> -		memcpy(&hwe.ipv6.l2, &e->data.bridge.l2, sizeof(hwe.ipv6.l2));
> >>>> -		hwe.ipv6.ib2 = e->data.bridge.ib2;
> >>>> +		memcpy(&hwe.ipv6.l2, &bridge->bridge.l2,
> >>>> +		       sizeof(hwe.ipv6.l2));
> >>>> +		hwe.ipv6.ib2 = bridge->bridge.ib2;
> >>>>  		/* setting smac_id to 0xf instruct the hw to keep original
> >>>>  		 * source mac address
> >>>>  		 */
> >>>>  		hwe.ipv6.l2.src_mac_hi = FIELD_PREP(AIROHA_FOE_MAC_SMAC_ID,
> >>>>  						    0xf);
> >>>>  	} else {
> >>>> -		memcpy(&hwe.bridge.l2, &e->data.bridge.l2,
> >>>> +		memcpy(&hwe.bridge.l2, &bridge->bridge.l2,
> >>>>  		       sizeof(hwe.bridge.l2));
> >>>> -		hwe.bridge.ib2 = e->data.bridge.ib2;
> >>>> +		hwe.bridge.ib2 = bridge->bridge.ib2;
> >>>>  		if (type == PPE_PKT_TYPE_IPV4_HNAPT)
> >>>>  			memcpy(&hwe.ipv4.new_tuple, &hwe.ipv4.orig_tuple,
> >>>>  			       sizeof(hwe.ipv4.new_tuple));
> >>>>  	}
> >>>>  
> >>>> -	hwe.bridge.data = e->data.bridge.data;
> >>>> -	airoha_ppe_foe_commit_entry(ppe, &hwe, hash, rx_wlan);
> >>>> +	hwe.bridge.data = bridge->bridge.data;
> >>>> +
> >>>> +	return airoha_ppe_foe_commit_entry(ppe, &hwe, hash, rx_wlan);
> >>>> +}
> >>>> +
> >>>> +static int
> >>>> +airoha_ppe_foe_commit_subflow_entry(struct airoha_ppe *ppe,
> >>>> +				    struct airoha_flow_table_entry *e,
> >>>> +				    u32 hash, bool rx_wlan)
> >>>> +{
> >>>> +	struct airoha_flow_table_entry *f;
> >>>> +	int err;
> >>>> +
> >>>> +	f = kzalloc_obj(*f, GFP_ATOMIC);
> >>>> +	if (!f)
> >>>> +		return -ENOMEM;
> >>>> +
> >>>> +	err = airoha_ppe_foe_commit_subflow(ppe, &e->data, hash, rx_wlan);
> >>>> +	if (err) {
> >>>> +		kfree(f);
> >>>> +		return err;
> >>>> +	}
> >>>> +
> >>>> +	hlist_add_head(&f->l2_subflow_node, &e->l2_flows);
> >>>> +	f->type = FLOW_TYPE_L2_SUBFLOW;
> >>>> +	f->hash = hash;
> >>>>  
> >>>>  	return 0;
> >>>>  }
> >>>>  
> >>>> +static bool
> >>>> +airoha_ppe_foe_prepare_wdma_subflow_dev(struct airoha_ppe *ppe,
> >>>> +					struct net_device *dev,
> >>>> +					struct airoha_flow_data *data,
> >>>> +					struct airoha_foe_entry *hwe)
> >>>> +{
> >>>> +	u32 pse_port;
> >>>> +	int err;
> >>>> +
> >>>> +	err = airoha_ppe_foe_entry_prepare(ppe->eth, hwe, dev,
> >>>> +					   PPE_PKT_TYPE_BRIDGE, data, 0);
> >>>> +	if (err)
> >>>> +		return false;
> >>>> +
> >>>> +	pse_port = FIELD_GET(AIROHA_FOE_IB2_PSE_PORT, hwe->bridge.ib2);
> >>>> +	if (pse_port != FE_PSE_PORT_CDM4)
> >>>> +		return false;
> >>>> +
> >>>> +	return true;
> >>>
> >>> 	return pse_port == FE_PSE_PORT_CDM4;
> >>>
> >>>> +}
> >>>> +
> >>>> +static struct net_device *
> >>>> +airoha_ppe_foe_get_bridge_master(struct net_device *dev)
> >>>> +{
> >>>> +	struct net_device *master = NULL;
> >>>> +
> >>>> +	rcu_read_lock();
> >>>> +	master = netdev_master_upper_dev_get_rcu(dev);
> >>>> +	if (master && netif_is_bridge_master(master))
> >>>> +		dev_hold(master);
> >>>> +	else
> >>>> +		master = NULL;
> >>>> +	rcu_read_unlock();
> >>>> +
> >>>> +	return master;
> >>>> +}
> >>>> +
> >>>> +static bool
> >>>> +airoha_ppe_foe_prepare_wdma_subflow(struct airoha_ppe *ppe,
> >>>> +				    struct sk_buff *skb,
> >>>> +				    struct airoha_foe_entry *hwe)
> >>>> +{
> >>>> +	struct ethhdr *eh = eth_hdr(skb);
> >>>> +	struct airoha_flow_data data = {};
> >>>> +	struct net_device *master;
> >>>> +
> >>>> +	if (!is_valid_ether_addr(eh->h_source) ||
> >>>> +	    !is_valid_ether_addr(eh->h_dest))
> >>>> +		return false;
> >>>> +
> >>>> +	ether_addr_copy(data.eth.h_dest, eh->h_dest);
> >>>> +	ether_addr_copy(data.eth.h_source, eh->h_source);
> >>>> +
> >>>> +	if (!skb->dev)
> >>>> +		return false;
> >>>> +
> >>>> +	/* WLAN egress unbound hits can arrive before flowtable creates the
> >>>> +	 * L2 master flow normally used for subflow binding. Resolve only
> >>>> +	 * through the bridge master so dev_fill_forward_path() must use the
> >>>> +	 * bridge FDB for the destination MAC. Calling the ingress AP netdev
> >>>> +	 * directly can describe the source station's WDMA path and would
> >>>> +	 * corrupt Wi-Fi-to-wired flows whose real egress is not WDMA.
> >>>> +	 */
> >>>> +	master = airoha_ppe_foe_get_bridge_master(skb->dev);
> >>>> +	if (!master)
> >>>> +		return false;
> >>>> +
> >>>> +	if (airoha_ppe_foe_prepare_wdma_subflow_dev(ppe, master, &data,
> >>>> +						    hwe)) {
> >>>> +		dev_put(master);
> >>>> +		return true;
> >>>> +	}
> >>>> +
> >>>> +	dev_put(master);
> >>>> +	return false;
> >>>
> >>> maybe something like:
> >>>
> >>> 	ret = airoha_ppe_foe_prepare_wdma_subflow_dev();
> >>> 	dev_put(master);
> >>>
> >>> 	return ret;
> >>>
> >>>> +}
> >>>> +
> >>>>  static void airoha_ppe_foe_insert_entry(struct airoha_ppe *ppe,
> >>>>  					struct sk_buff *skb,
> >>>>  					u32 hash, bool rx_wlan)
> >>>>  {
> >>>> +	struct airoha_foe_entry wdma_hwe = {};
> >>>>  	struct airoha_flow_table_entry *e;
> >>>>  	struct airoha_foe_bridge br = {};
> >>>>  	struct airoha_foe_entry *hwe;
> >>>>  	bool commit_done = false;
> >>>> +	bool wdma_ready = false;
> >>>>  	struct hlist_node *n;
> >>>>  	u32 index, state;
> >>>>  
> >>>> +	wdma_ready = airoha_ppe_foe_prepare_wdma_subflow(ppe, skb,
> >>>> +							 &wdma_hwe);
> >>>> +
> >>>>  	spin_lock_bh(&ppe_lock);
> >>>>  
> >>>>  	hwe = airoha_ppe_foe_get_entry_locked(ppe, hash);
> >>>> @@ -899,6 +997,8 @@ static void airoha_ppe_foe_insert_entry(struct airoha_ppe *ppe,
> >>>>  				   airoha_l2_flow_table_params);
> >>>>  	if (e)
> >>>>  		airoha_ppe_foe_commit_subflow_entry(ppe, e, hash, rx_wlan);
> >>>> +	else if (wdma_ready)
> >>>> +		airoha_ppe_foe_commit_subflow(ppe, &wdma_hwe, hash, rx_wlan);
> >>>>  unlock:
> >>>>  	spin_unlock_bh(&ppe_lock);
> >>>>  }
> >>>> -- 
> >>>> 2.53.0
> >>>>
> >>
> >> All inline code-style review comments will be addressed in the next
> >> submission of the patch set, together with the responses to Sashiko's
> >> review, if any.
> 

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox