* Re: [PATCH net] bridge: mcast: Fix a false positive lockdep splat
From: Paolo Abeni @ 2026-04-28 14:10 UTC (permalink / raw)
To: Ido Schimmel, netdev, bridge
Cc: davem, kuba, edumazet, razor, horms, herbert, linus.luessing
In-Reply-To: <20260426133435.207006-1-idosch@nvidia.com>
On 4/26/26 3:34 PM, Ido Schimmel wrote:
> Connecting two bridges on the same system [1] can result in a lockdep
> splat [2].
>
> The report is a false positive. Multicast queries are built and
> transmitted under the bridge multicast lock. When the outgoing port of
> one bridge is configured on top of another bridge, the transmit path
> re-enters bridge code and acquires the other bridge's multicast lock in
> order to snoop the query. Both lock instances share a single lockdep
> class, so lockdep flags the nested acquisition as an AA deadlock.
>
> Giving each bridge its own lock class will not solve the problem: the
> reverse topology would produce an ABBA splat with the same pair of
> classes. It also consumes a lockdep key per bridge.
>
> Instead, fix the problem by deferring the transmission of the queries to
> a workqueue. Build the skb and update querier state under the lock as
> before, then enqueue the skb on a per multicast context queue and
> schedule the work.
I must admit that introducing an additional WQ to fix a false positive
feels a bit overkill to me - even if I can't think of a better solution
on top of my head.
> Flush the work when the multicast context is de-initialized. At this
> stage the work cannot be requeued. There is no need to take a reference
> on skb->dev since the work cannot outlive the bridge or the bridge port.
>
> Use the high priority workqueue to reduce the delay between the enqueue
> time and the transmission time. With default settings (i.e., querier
> interval - 255 seconds, query interval - 125 seconds) the extra delay
> should not be a problem.
>
> [1]
> ip link add name br1 up type bridge mcast_snooping 1 mcast_querier 1
> ip link add name br0 up type bridge mcast_snooping 1 mcast_querier 1
> ip link add link br0 name br0.10 up master br1 type vlan id 10
>
> [2]
> ============================================
> WARNING: possible recursive locking detected
> 7.0.0-virtme-gb50c64a58a90 #1 Not tainted
> --------------------------------------------
checkpatch reports that the above separator may break tool. Possibly
just remove it from the commit message.
> ip/339 is trying to acquire lock:
> ffff888104f0b480 (&br->multicast_lock){+.-.}-{3:3}, at: br_ip6_multicast_query (net/bridge/br_multicast.c:3584)
>
> but task is already holding lock:
> ffff888104f03480 (&br->multicast_lock){+.-.}-{3:3}, at: br_multicast_port_query_expired (net/bridge/br_multicast.c:1904)
>
> [...]
>
> Call Trace:
> [...]
> br_ip6_multicast_query (net/bridge/br_multicast.c:3584)
> br_multicast_ipv6_rcv (net/bridge/br_multicast.c:3988)
> br_dev_xmit (net/bridge/br_device.c:98 (discriminator 1))
> dev_hard_start_xmit (./include/linux/netdevice.h:5343 ./include/linux/netdevice.h:5352 net/core/dev.c:3888 net/core/dev.c:3904)
> __dev_queue_xmit (./include/linux/netdevice.h:3619 net/core/dev.c:4871)
> vlan_dev_hard_start_xmit (net/8021q/vlan_dev.c:131 (discriminator 1))
> dev_hard_start_xmit (./include/linux/netdevice.h:5343 ./include/linux/netdevice.h:5352 net/core/dev.c:3888 net/core/dev.c:3904)
> __dev_queue_xmit (./include/linux/netdevice.h:3619 net/core/dev.c:4871)
> br_dev_queue_push_xmit (net/bridge/br_forward.c:60)
> __br_multicast_send_query (net/bridge/br_multicast.c:1811 (discriminator 1))
> br_multicast_send_query (net/bridge/br_multicast.c:1889)
> br_multicast_port_query_expired (./include/linux/spinlock.h:390 net/bridge/br_multicast.c:1914)
> call_timer_fn (./arch/x86/include/asm/jump_label.h:37 ./include/trace/events/timer.h:127 kernel/time/timer.c:1749)
> [...]
>
> Fixes: eb1d16414339 ("bridge: Add core IGMP snooping support")
> Reported-by: syzbot+d7b7f1412c02134efa6d@syzkaller.appspotmail.com
> Closes: https://lore.kernel.org/netdev/000000000000c4c9d405f2643e01@google.com/
> Acked-by: Nikolay Aleksandrov <nikolay@nvidia.com>
> Signed-off-by: Ido Schimmel <idosch@nvidia.com>
> ---
> net/bridge/br_multicast.c | 39 +++++++++++++++++++++++++++++++++++----
> net/bridge/br_private.h | 4 ++++
> 2 files changed, 39 insertions(+), 4 deletions(-)
>
> diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c
> index 881d866d687a..252c46977ed5 100644
> --- a/net/bridge/br_multicast.c
> +++ b/net/bridge/br_multicast.c
> @@ -1776,6 +1776,28 @@ static void br_multicast_select_own_querier(struct net_bridge_mcast *brmctx,
> #endif
> }
>
> +static void br_multicast_port_query_queue_work(struct work_struct *work)
> +{
> + struct net_bridge_mcast_port *pmctx;
> + struct sk_buff *skb;
> +
> + pmctx = container_of(work, struct net_bridge_mcast_port,
> + query_queue_work);
> + while ((skb = skb_dequeue(&pmctx->query_queue)))
> + NF_HOOK(NFPROTO_BRIDGE, NF_BR_LOCAL_OUT, dev_net(skb->dev),
> + NULL, skb, NULL, skb->dev, br_dev_queue_push_xmit);
> +}
> +
> +static void br_multicast_query_queue_work(struct work_struct *work)
> +{
> + struct net_bridge_mcast *brmctx;
> + struct sk_buff *skb;
> +
> + brmctx = container_of(work, struct net_bridge_mcast, query_queue_work);
> + while ((skb = skb_dequeue(&brmctx->query_queue)))
> + netif_rx(skb);
> +}
> +
> static void __br_multicast_send_query(struct net_bridge_mcast *brmctx,
> struct net_bridge_mcast_port *pmctx,
> struct net_bridge_port_group *pg,
> @@ -1804,9 +1826,8 @@ static void __br_multicast_send_query(struct net_bridge_mcast *brmctx,
> skb->dev = pmctx->port->dev;
> br_multicast_count(brmctx->br, pmctx->port, skb, igmp_type,
> BR_MCAST_DIR_TX);
> - NF_HOOK(NFPROTO_BRIDGE, NF_BR_LOCAL_OUT,
> - dev_net(pmctx->port->dev), NULL, skb, NULL, skb->dev,
> - br_dev_queue_push_xmit);
> + skb_queue_tail(&pmctx->query_queue, skb);
> + queue_work(system_highpri_wq, &pmctx->query_queue_work);
Also the AI reported concerns vs unbounded queue len looks relevant.
Usually the RX path is slower than TX, but i.e. asymmetric filtering
rules could reverse the scenario.
/P
^ permalink raw reply
* [PATCH net v4] net: dsa: mt7530: fix .get_stats64 sleeping in atomic context
From: Daniel Golle @ 2026-04-28 14:10 UTC (permalink / raw)
To: Chester A. Unal, Daniel Golle, Andrew Lunn, Vladimir Oltean,
David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Matthias Brugger, AngeloGioacchino Del Regno, Russell King,
Christian Marangi, netdev, linux-kernel, linux-arm-kernel,
linux-mediatek
The .get_stats64 callback runs in atomic context, but on
MDIO-connected switches every register read acquires the MDIO bus
mutex, which can sleep:
[ 12.645973] BUG: sleeping function called from invalid context at kernel/locking/mutex.c:609
[ 12.654442] in_atomic(): 0, irqs_disabled(): 0, non_block: 0, pid: 759, name: grep
[ 12.663377] preempt_count: 0, expected: 0
[ 12.667410] RCU nest depth: 1, expected: 0
[ 12.671511] INFO: lockdep is turned off.
[ 12.675441] CPU: 0 UID: 0 PID: 759 Comm: grep Tainted: G S W 7.0.0+ #0 PREEMPT
[ 12.675453] Tainted: [S]=CPU_OUT_OF_SPEC, [W]=WARN
[ 12.675456] Hardware name: Bananapi BPI-R64 (DT)
[ 12.675459] Call trace:
[ 12.675462] show_stack+0x14/0x1c (C)
[ 12.675477] dump_stack_lvl+0x68/0x8c
[ 12.675487] dump_stack+0x14/0x1c
[ 12.675495] __might_resched+0x14c/0x220
[ 12.675504] __might_sleep+0x44/0x80
[ 12.675511] __mutex_lock+0x50/0xb10
[ 12.675523] mutex_lock_nested+0x20/0x30
[ 12.675532] mt7530_get_stats64+0x40/0x2ac
[ 12.675542] dsa_user_get_stats64+0x2c/0x40
[ 12.675553] dev_get_stats+0x44/0x1e0
[ 12.675564] dev_seq_printf_stats+0x24/0xe0
[ 12.675575] dev_seq_show+0x14/0x3c
[ 12.675583] seq_read_iter+0x37c/0x480
[ 12.675595] seq_read+0xd0/0xec
[ 12.675605] proc_reg_read+0x94/0xe4
[ 12.675615] vfs_read+0x98/0x29c
[ 12.675625] ksys_read+0x54/0xdc
[ 12.675633] __arm64_sys_read+0x18/0x20
[ 12.675642] invoke_syscall.constprop.0+0x54/0xec
[ 12.675653] do_el0_svc+0x3c/0xb4
[ 12.675662] el0_svc+0x38/0x200
[ 12.675670] el0t_64_sync_handler+0x98/0xdc
[ 12.675679] el0t_64_sync+0x158/0x15c
For MDIO-connected switches, poll MIB counters asynchronously using a
delayed workqueue every second and let .get_stats64 return the cached
values under a spinlock. A mod_delayed_work() call on each read
triggers an immediate refresh so counters stay responsive when queried
more frequently.
MMIO-connected switches (MT7988, EN7581, AN7583) are not affected
because their regmap does not sleep, so they continue to read MIB
counters directly in .get_stats64.
Fixes: 88c810f35ed5 ("net: dsa: mt7530: implement .get_stats64")
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
Acked-by: Chester A. Unal <chester.a.unal@arinc9.com>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
---
v4:
* extract mt7530_stats_refresh() helper from mt7530_stats_poll()
-> mt7530_stats_poll() now just refreshes and re-arms
* call helper synchronously in mt753x_setup() to seed the cache
* avoid zeroed counters during the first poll interval
* avoid INITIAL_JIFFIES vs stats_last==0 wraparound on 32-bit
* swap deprecated system_wq for system_percpu_wq in get_stats64
* keeps on-demand refresh on the same queue as schedule_*_work
v3:
* move `stats_last` access under the spinlock to avoid potential race
v2:
* use spin_lock_bh()/spin_unlock_bh() to prevent potential deadlock
* rate-limit mod_delayed_work() refresh to at most once per 100ms
* move cancel_delayed_work_sync() after dsa_unregister_switch()
* add mt753x_teardown() callback to cancel the stats work
* fix commit message
drivers/net/dsa/mt7530.c | 76 ++++++++++++++++++++++++++++++++++++++--
drivers/net/dsa/mt7530.h | 8 +++++
2 files changed, 81 insertions(+), 3 deletions(-)
diff --git a/drivers/net/dsa/mt7530.c b/drivers/net/dsa/mt7530.c
index b9423389c2ef..66bff861a921 100644
--- a/drivers/net/dsa/mt7530.c
+++ b/drivers/net/dsa/mt7530.c
@@ -25,6 +25,9 @@
#include "mt7530.h"
+#define MT7530_STATS_POLL_INTERVAL (1 * HZ)
+#define MT7530_STATS_RATE_LIMIT (HZ / 10)
+
static struct mt753x_pcs *pcs_to_mt753x_pcs(struct phylink_pcs *pcs)
{
return container_of(pcs, struct mt753x_pcs, pcs);
@@ -906,10 +909,9 @@ static void mt7530_get_rmon_stats(struct dsa_switch *ds, int port,
*ranges = mt7530_rmon_ranges;
}
-static void mt7530_get_stats64(struct dsa_switch *ds, int port,
- struct rtnl_link_stats64 *storage)
+static void mt7530_read_port_stats64(struct mt7530_priv *priv, int port,
+ struct rtnl_link_stats64 *storage)
{
- struct mt7530_priv *priv = ds->priv;
uint64_t data;
/* MIB counter doesn't provide a FramesTransmittedOK but instead
@@ -951,6 +953,54 @@ static void mt7530_get_stats64(struct dsa_switch *ds, int port,
&storage->rx_crc_errors);
}
+static void mt7530_stats_refresh(struct mt7530_priv *priv)
+{
+ struct rtnl_link_stats64 stats = {};
+ struct dsa_port *dp;
+ int port;
+
+ dsa_switch_for_each_user_port(dp, priv->ds) {
+ port = dp->index;
+
+ mt7530_read_port_stats64(priv, port, &stats);
+
+ spin_lock_bh(&priv->stats_lock);
+ priv->ports[port].stats = stats;
+ priv->stats_last = jiffies;
+ spin_unlock_bh(&priv->stats_lock);
+ }
+}
+
+static void mt7530_stats_poll(struct work_struct *work)
+{
+ struct mt7530_priv *priv = container_of(work, struct mt7530_priv,
+ stats_work.work);
+
+ mt7530_stats_refresh(priv);
+ schedule_delayed_work(&priv->stats_work,
+ MT7530_STATS_POLL_INTERVAL);
+}
+
+static void mt7530_get_stats64(struct dsa_switch *ds, int port,
+ struct rtnl_link_stats64 *storage)
+{
+ struct mt7530_priv *priv = ds->priv;
+ bool refresh;
+
+ if (priv->bus) {
+ spin_lock_bh(&priv->stats_lock);
+ *storage = priv->ports[port].stats;
+ refresh = time_after(jiffies, priv->stats_last +
+ MT7530_STATS_RATE_LIMIT);
+ spin_unlock_bh(&priv->stats_lock);
+ if (refresh)
+ mod_delayed_work(system_percpu_wq,
+ &priv->stats_work, 0);
+ } else {
+ mt7530_read_port_stats64(priv, port, storage);
+ }
+}
+
static void mt7530_get_eth_ctrl_stats(struct dsa_switch *ds, int port,
struct ethtool_eth_ctrl_stats *ctrl_stats)
{
@@ -3137,9 +3187,25 @@ mt753x_setup(struct dsa_switch *ds)
if (ret && priv->irq_domain)
mt7530_free_mdio_irq(priv);
+ if (!ret && priv->bus) {
+ spin_lock_init(&priv->stats_lock);
+ INIT_DELAYED_WORK(&priv->stats_work, mt7530_stats_poll);
+ mt7530_stats_refresh(priv);
+ schedule_delayed_work(&priv->stats_work,
+ MT7530_STATS_POLL_INTERVAL);
+ }
+
return ret;
}
+static void mt753x_teardown(struct dsa_switch *ds)
+{
+ struct mt7530_priv *priv = ds->priv;
+
+ if (priv->bus)
+ cancel_delayed_work_sync(&priv->stats_work);
+}
+
static int mt753x_set_mac_eee(struct dsa_switch *ds, int port,
struct ethtool_keee *e)
{
@@ -3257,6 +3323,7 @@ static int mt7988_setup(struct dsa_switch *ds)
static const struct dsa_switch_ops mt7530_switch_ops = {
.get_tag_protocol = mtk_get_tag_protocol,
.setup = mt753x_setup,
+ .teardown = mt753x_teardown,
.preferred_default_local_cpu_port = mt753x_preferred_default_local_cpu_port,
.get_strings = mt7530_get_strings,
.get_ethtool_stats = mt7530_get_ethtool_stats,
@@ -3409,6 +3476,9 @@ mt7530_remove_common(struct mt7530_priv *priv)
dsa_unregister_switch(priv->ds);
+ if (priv->bus)
+ cancel_delayed_work_sync(&priv->stats_work);
+
mutex_destroy(&priv->reg_mutex);
}
EXPORT_SYMBOL_GPL(mt7530_remove_common);
diff --git a/drivers/net/dsa/mt7530.h b/drivers/net/dsa/mt7530.h
index 3e0090bed298..dd33b0df3419 100644
--- a/drivers/net/dsa/mt7530.h
+++ b/drivers/net/dsa/mt7530.h
@@ -796,6 +796,7 @@ struct mt7530_fdb {
* @pvid: The VLAN specified is to be considered a PVID at ingress. Any
* untagged frames will be assigned to the related VLAN.
* @sgmii_pcs: Pointer to PCS instance for SerDes ports
+ * @stats: Cached port statistics for MDIO-connected switches
*/
struct mt7530_port {
bool enable;
@@ -803,6 +804,7 @@ struct mt7530_port {
u32 pm;
u16 pvid;
struct phylink_pcs *sgmii_pcs;
+ struct rtnl_link_stats64 stats;
};
/* Port 5 mode definitions of the MT7530 switch */
@@ -875,6 +877,9 @@ struct mt753x_info {
* @create_sgmii: Pointer to function creating SGMII PCS instance(s)
* @active_cpu_ports: Holding the active CPU ports
* @mdiodev: The pointer to the MDIO device structure
+ * @stats_lock: Protects cached per-port stats from concurrent access
+ * @stats_work: Delayed work for polling MIB counters on MDIO switches
+ * @stats_last: Jiffies timestamp of last MIB counter poll
*/
struct mt7530_priv {
struct device *dev;
@@ -900,6 +905,9 @@ struct mt7530_priv {
int (*create_sgmii)(struct mt7530_priv *priv);
u8 active_cpu_ports;
struct mdio_device *mdiodev;
+ spinlock_t stats_lock; /* protects cached stats counters */
+ struct delayed_work stats_work;
+ unsigned long stats_last;
};
struct mt7530_hw_vlan_entry {
--
2.54.0
^ permalink raw reply related
* Re: [PATCH net-next v9 4/4] tun/tap & vhost-net: avoid ptr_ring tail-drop when a qdisc is present
From: Michael S. Tsirkin @ 2026-04-28 14:10 UTC (permalink / raw)
To: Simon Schippers
Cc: willemdebruijn.kernel, jasowang, andrew+netdev, davem, edumazet,
kuba, pabeni, eperezma, leiyang, stephen, jon, tim.gebauer,
netdev, linux-kernel, kvm, virtualization
In-Reply-To: <d00bea39-7748-46ad-9c31-27326041f03c@tu-dortmund.de>
On Tue, Apr 28, 2026 at 03:41:20PM +0200, Simon Schippers wrote:
> On 4/28/26 15:22, Michael S. Tsirkin wrote:
> > On Tue, Apr 28, 2026 at 03:10:44PM +0200, Simon Schippers wrote:
> >> On 4/28/26 14:50, Michael S. Tsirkin wrote:
> >>> On Tue, Apr 28, 2026 at 02:38:59PM +0200, Simon Schippers wrote:
> >>>> This commit prevents tail-drop when a qdisc is present and the ptr_ring
> >>>> becomes full. Once an entry is successfully produced and the ptr_ring
> >>>> reaches capacity, the netdev queue is stopped instead of dropping
> >>>> subsequent packets.
> >>>>
> >>>> If producing an entry fails anyways due to a race, tun_net_xmit returns
> >>>> NETDEV_TX_BUSY, again avoiding a drop. Such races are expected because
> >>>> LLTX is enabled and the transmit path operates without the usual locking.
> >>>>
> >>>> If no qdisc is present, the previous tail-drop behavior is preserved.
> >>>>
> >>>> The existing __tun_wake_queue() function of the consumer races with the
> >>>> producer for waking/stopping the netdev queue: the consumer may drain
> >>>> the ring just as the producer stops the queue, leading to a permanent
> >>>> stall. To avoid this, the producer re-checks the ring after stopping
> >>>> and wakes the queue itself if space was just made. An
> >>>> smp_mb__after_atomic() is required so the re-peek of the ring sees any
> >>>> drain that the consumer performed.
> >>>> smp_mb__after_atomic() pairs with the test_and_clear_bit() inside of
> >>>> netif_wake_subqueue():
> >>>>
> >>>> Consumer CPU Producer CPU
> >>>> ======================== =========================
> >>>> __ptr_ring_consume()
> >>>> netif_wake_subqueue() netif_tx_stop_queue()
> >>>> /\ smp_mb__after_atomic()
> >>>> || __ptr_ring_produce_peek()
> >>>> contains RMW operation
> >>>> test_and_clear_bit()
> >>>> /\
> >>>> ||
> >>>> "Fully ordered RMW:
> >>>> smp_mb() before + after"
> >>>> - atomic_t.txt
> >>>>
> >>>> Benchmarks:
> >>>> The benchmarks show a slight regression in raw transmission performance,
> >>>> though no packets are lost anymore.
> >>>
> >>> Could you include the packets received as well?
> >>> To demonstrate the gains/lack of loss.
> >>>
> >>
> >> Do you mean the number of packets received by the VM?
> >> They should just be the same as the number sent (shown below), right?
> >
> > Minus the loss? Which this is about, right?
>
> Yes. I simply calculated "Lost/s":
>
> elapsed_time = 100e6 / sent_pps
> Lost/s = total_errors / elapsed_time
>
>
> To get back total_errors for example for TAP
> 1 thread sending:
>
> elapsed_time = 100e6 / 1.136Mpps = 88s
>
> 3758 Mpps = total_errors / 88s
> <=> total_errors = 331 million packets
>
> So, out of 431 million packets sent, 100 million were successfully
> delivered and 331 million were lost.
That is my issue.
I kind of have trouble mapping that to the table below.
For example:
| TAP | Transmitted | 1.136 Mpps | 1.130 Mpps | -0.6% |
| +-------------+--------------+----------------+----------+
| | Lost/s | 3.758 Mpps | 0 pps | |
how can # of lost packets exceed the # of transmitted packets?
Thanks!
> >
> >> I assume they would be visible as RX-DRP for TAP.
> >> For TAP + vhost-net I would have to rewrite the XDP drop
> >> program to count the number of dropped packets...
> >> And I would have to automate it...
> >>
> >>>>
> >>>> The previously introduced threshold to only wake after the queue stopped
> >>>> and half of the ring was consumed showed to be a descent choice:
> >>>> Waking the queue whenever a consume made space in the ring strongly
> >>>> degrades performance for tap, while waking only when the ring is empty
> >>>> is too late and also hurts throughput for tap & tap+vhost-net.
> >>>> Other ratios (3/4, 7/8) showed similar results (not shown here), so
> >>>> 1/2 was chosen for the sake of simplicity for both tun/tap and
> >>>> tun/tap+vhost-net.
> >>>>
> >>>> Test setup:
> >>>> AMD Ryzen 5 5600X at 4.3 GHz, 3200 MHz RAM, isolated QEMU threads;
> >>>> Average over 50 runs @ 100,000,000 packets. SRSO and spectre v2
> >>>> mitigations disabled.
> >>>>
> >>>> Note for tap+vhost-net:
> >>>> XDP drop program active in VM -> ~2.5x faster, slower for tap due to
> >>>> more syscalls (high utilization of entry_SYSRETQ_unsafe_stack in perf)
> >>>>
> >>>> +--------------------------+--------------+----------------+----------+
> >>>> | 1 thread | Stock | Patched with | diff |
> >>>> | sending | | fq_codel qdisc | |
> >>>> +------------+-------------+--------------+----------------+----------+
> >>>> | TAP | Transmitted | 1.136 Mpps | 1.130 Mpps | -0.6% |
> >>>> | +-------------+--------------+----------------+----------+
> >>>> | | Lost/s | 3.758 Mpps | 0 pps | |
> >>>> +------------+-------------+--------------+----------------+----------+
> >>>> | TAP | Transmitted | 3.858 Mpps | 3.816 Mpps | -1.1% |
> >>>> | +-------------+--------------+----------------+----------+
> >>>> | +vhost-net | Lost/s | 789.8 Kpps | 0 pps | |
> >>>> +------------+-------------+--------------+----------------+----------+
> >>>>
> >>>> +--------------------------+--------------+----------------+----------+
> >>>> | 2 threads | Stock | Patched with | diff |
> >>>> | sending | | fq_codel qdisc | |
> >>>> +------------+-------------+--------------+----------------+----------+
> >>>> | TAP | Transmitted | 1.117 Mpps | 1.087 Mpps | -2.7% |
> >>>> | +-------------+--------------+----------------+----------+
> >>>> | | Lost/s | 8.476 Mpps | 0 pps | |
> >>>> +------------+-------------+--------------+----------------+----------+
> >>>> | TAP | Transmitted | 3.679 Mpps | 3.464 Mpps | -5.8% |
> >>>> | +-------------+--------------+----------------+----------+
> >>>> | +vhost-net | Lost/s | 5.306 Mpps | 0 pps | |
> >>>> +------------+-------------+--------------+----------------+----------+
> >>>>
> >>>> Co-developed-by: Tim Gebauer <tim.gebauer@tu-dortmund.de>
> >>>> Signed-off-by: Tim Gebauer <tim.gebauer@tu-dortmund.de>
> >>>> Signed-off-by: Simon Schippers <simon.schippers@tu-dortmund.de>
> >>>> ---
> >>>> drivers/net/tun.c | 30 ++++++++++++++++++++++++++++--
> >>>> 1 file changed, 28 insertions(+), 2 deletions(-)
> >>>>
> >>>> diff --git a/drivers/net/tun.c b/drivers/net/tun.c
> >>>> index efe809597622..c2a1618cc9db 100644
> >>>> --- a/drivers/net/tun.c
> >>>> +++ b/drivers/net/tun.c
> >>>> @@ -1011,6 +1011,8 @@ static netdev_tx_t tun_net_xmit(struct sk_buff *skb, struct net_device *dev)
> >>>> struct netdev_queue *queue;
> >>>> struct tun_file *tfile;
> >>>> int len = skb->len;
> >>>> + bool qdisc_present;
> >>>> + int ret;
> >>>>
> >>>> rcu_read_lock();
> >>>> tfile = rcu_dereference(tun->tfiles[txq]);
> >>>> @@ -1065,13 +1067,37 @@ static netdev_tx_t tun_net_xmit(struct sk_buff *skb, struct net_device *dev)
> >>>>
> >>>> nf_reset_ct(skb);
> >>>>
> >>>> - if (ptr_ring_produce(&tfile->tx_ring, skb)) {
> >>>> + queue = netdev_get_tx_queue(dev, txq);
> >>>> + qdisc_present = !qdisc_txq_has_no_queue(queue);
> >>>> +
> >>>> + spin_lock(&tfile->tx_ring.producer_lock);
> >>>> + ret = __ptr_ring_produce(&tfile->tx_ring, skb);
> >>>> + if (__ptr_ring_produce_peek(&tfile->tx_ring) && qdisc_present) {
> >>>> + netif_tx_stop_queue(queue);
> >>>> + /* Re-peek and wake if the consumer drained the ring
> >>>> + * concurrently in a race. smp_mb__after_atomic() pairs
> >>>> + * with the test_and_clear_bit() of netif_wake_subqueue()
> >>>> + * in __tun_wake_queue().
> >>>> + */
> >>>> + smp_mb__after_atomic();
> >>>> + if (!__ptr_ring_produce_peek(&tfile->tx_ring))
> >>>> + netif_tx_wake_queue(queue);
> >>>> + }
> >>>> + spin_unlock(&tfile->tx_ring.producer_lock);
> >>>> +
> >>>> + if (ret) {
> >>>> + /* If a qdisc is attached to our virtual device,
> >>>> + * returning NETDEV_TX_BUSY is allowed.
> >>>> + */
> >>>> + if (qdisc_present) {
> >>>> + rcu_read_unlock();
> >>>> + return NETDEV_TX_BUSY;
> >>>> + }
> >>>> drop_reason = SKB_DROP_REASON_FULL_RING;
> >>>> goto drop;
> >>>> }
> >>>>
> >>>> /* dev->lltx requires to do our own update of trans_start */
> >>>> - queue = netdev_get_tx_queue(dev, txq);
> >>>> txq_trans_cond_update(queue);
> >>>>
> >>>> /* Notify and wake up reader process */
> >>>> --
> >>>> 2.43.0
> >>>
> >
^ permalink raw reply
* Re: [PATCH net-next v5 3/3] net: dsa: yt921x: Add port police support
From: Jakub Kicinski @ 2026-04-28 14:07 UTC (permalink / raw)
To: David Yang
Cc: netdev, Andrew Lunn, Vladimir Oltean, David S. Miller,
Eric Dumazet, Paolo Abeni, linux-kernel
In-Reply-To: <20260428112606.1917230-4-mmyangfl@gmail.com>
On Tue, 28 Apr 2026 19:26:03 +0800 David Yang wrote:
> + if (burst_sug > burst)
> + NL_SET_ERR_MSG_FMT_MOD(extack,
> + "Consider burst at least %llu to match rate %llu\n",
> + burst_sug, rate);
No new line chars in extact messages, please.
--
pw-bot: cr
^ permalink raw reply
* Re: [PATCH v3 net-next] net/intel: Replace manual array size calculation with ARRAY_SIZE
From: Przemek Kitszel @ 2026-04-28 14:06 UTC (permalink / raw)
To: Jakub Raczynski
Cc: netdev, kuba, intel-wired-lan, linux-kernel, kernel-janitors,
error27
In-Reply-To: <20260428103653.3539239-1-j.raczynski@samsung.com>
On 4/28/26 12:36, Jakub Raczynski wrote:
> There are still places in the code where manual calculation of array size
> exist, but it is good to enforce usage of single macro through the whole
> code as it makes code bit more readable.
> While at it, beautify condition surrounding it by reversing check and remove
> unnecessary casting.
>
> Signed-off-by: Jakub Raczynski <j.raczynski@samsung.com>
> Reviewed-by: Dan Carpenter <error27@gmail.com>
thank you,
Reviewed-by: Przemek Kitszel <przemyslaw.kitszel@intel.com>
(next time use "iwl-next" in the title, no need to repost just for that)
> ---
> Link to v1/v2:
> https://lore.kernel.org/kernel-janitors/20260421114029.2689961-1-j.raczynski@samsung.com/
>
> Changes in v3:
> - Add 'Reviewed-by' from previous thread
> Changes in v2:
> - Beautify code by removing excessive parentheses
> - Reverse if condition to remove negation of whole check
>
> drivers/net/ethernet/intel/i40e/i40e_adminq.h | 2 +-
> drivers/net/ethernet/intel/iavf/iavf_adminq.h | 2 +-
> 2 files changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/net/ethernet/intel/i40e/i40e_adminq.h b/drivers/net/ethernet/intel/i40e/i40e_adminq.h
> index 1be97a3a86ce..dcf3baec7b73 100644
> --- a/drivers/net/ethernet/intel/i40e/i40e_adminq.h
> +++ b/drivers/net/ethernet/intel/i40e/i40e_adminq.h
> @@ -109,7 +109,7 @@ static inline int i40e_aq_rc_to_posix(int aq_ret, int aq_rc)
> -EFBIG, /* I40E_AQ_RC_EFBIG */
> };
>
> - if (!((u32)aq_rc < (sizeof(aq_to_posix) / sizeof((aq_to_posix)[0]))))
> + if (aq_rc >= ARRAY_SIZE(aq_to_posix))
> return -ERANGE;
>
> return aq_to_posix[aq_rc];
> diff --git a/drivers/net/ethernet/intel/iavf/iavf_adminq.h b/drivers/net/ethernet/intel/iavf/iavf_adminq.h
> index bbf5c4b3a2ae..dd2f61172157 100644
> --- a/drivers/net/ethernet/intel/iavf/iavf_adminq.h
> +++ b/drivers/net/ethernet/intel/iavf/iavf_adminq.h
> @@ -113,7 +113,7 @@ static inline int iavf_aq_rc_to_posix(int aq_ret, int aq_rc)
> if (aq_ret == IAVF_ERR_ADMIN_QUEUE_TIMEOUT)
> return -EAGAIN;
>
> - if (!((u32)aq_rc < (sizeof(aq_to_posix) / sizeof((aq_to_posix)[0]))))
> + if (aq_rc >= ARRAY_SIZE(aq_to_posix))
> return -ERANGE;
>
> return aq_to_posix[aq_rc];
^ permalink raw reply
* Re: [PATCH net v2 0/2] sctp: fix a vtag verification failure caused by stale INITs
From: Simon Horman @ 2026-04-28 14:06 UTC (permalink / raw)
To: Xin Long
Cc: network dev, netfilter-devel, linux-sctp, davem, kuba,
Eric Dumazet, Paolo Abeni, Pablo Neira Ayuso, Florian Westphal,
Phil Sutter, Marcelo Ricardo Leitner, Yi Chen
In-Reply-To: <cover.1777214801.git.lucien.xin@gmail.com>
On Sun, Apr 26, 2026 at 10:46:39AM -0400, Xin Long wrote:
> Similar to Scenario B in commit 8e56b063c865 ( netfilter: handle the
> connecting collision properly in nf_conntrack_proto_sctp"):
>
> Scenario B: INIT_ACK is delayed until the peer completes its own handshake
>
> 192.168.1.2 > 192.168.1.1: sctp (1) [INIT] [init tag: 3922216408]
> 192.168.1.1 > 192.168.1.2: sctp (1) [INIT] [init tag: 144230885]
> 192.168.1.2 > 192.168.1.1: sctp (1) [INIT ACK] [init tag: 3922216408]
> 192.168.1.1 > 192.168.1.2: sctp (1) [COOKIE ECHO]
> 192.168.1.2 > 192.168.1.1: sctp (1) [COOKIE ACK]
> 192.168.1.1 > 192.168.1.2: sctp (1) [INIT ACK] [init tag: 3914796021] *
>
> There is another case:
>
> Scenario F: INIT is delayed until the peer completes its own handshake
>
> 192.168.1.2 > 192.168.1.1: sctp (1) [INIT] [init tag: 3922216408]
> (OVS upcall)
> 192.168.1.1 > 192.168.1.2: sctp (1) [INIT] [init tag: 144230885]
> 192.168.1.2 > 192.168.1.1: sctp (1) [INIT ACK] [init tag: 3922216408]
> 192.168.1.1 > 192.168.1.2: sctp (1) [COOKIE ECHO]
> 192.168.1.2 > 192.168.1.1: sctp (1) [COOKIE ACK]
> 192.168.1.2 > 192.168.1.1: sctp (1) [INIT] [init tag: 3922216408]
> (delayed)
> 192.168.1.1 > 192.168.1.2: sctp (1) [INIT ACK] [init tag: 3914796021] *
>
> In this case, the delayed INIT (e.g. due to OVS upcall) is recorded by
> conntrack, which prevents vtag verification from dropping the unexpected
> INIT-ACK in nf_conntrack_sctp_packet():
>
> vtag = ct->proto.sctp.vtag[!dir];
> if (!ct->proto.sctp.init[!dir] && vtag && vtag != ih->init_tag)
> goto out_unlock;
>
> This happens because ct->proto.sctp.init[!dir] is set by the delayed INIT,
> even though it is stale.
>
> Fix this in two parts:
>
> - In netfilter: Do not record INITs whose init_tag matches the peer vtag,
> as they carry no new handshake state in the 1st patch.
>
> - In SCTP: Prevent endpoints from responding to such INITs with INIT-ACK,
> ensuring correctness even when middleboxes lack the netfilter fix in
> the 2nd patch.
>
> A follow-up selftest for this scenario will be posted in a separate patch
> by Yi Chen.
Hi Xin,
FTR: There is an AI generated review of this patchset available on
sashiko.dev. I have looked over this and I do not believe the feedback
there should block progress of this patchset.
^ permalink raw reply
* Re: [PATCH v1] net: phy: dp83869: fix setting CLK_O_SEL field.
From: patchwork-bot+netdevbpf @ 2026-04-28 14:00 UTC (permalink / raw)
To: Heiko Schocher
Cc: netdev, andrew, davem, edumazet, hkallweit1, kuba, pabeni, linux,
linux-kernel
In-Reply-To: <20260425031339.3318-1-hs@nabladev.com>
Hello:
This patch was applied to netdev/net.git (main)
by Paolo Abeni <pabeni@redhat.com>:
On Sat, 25 Apr 2026 05:13:39 +0200 you wrote:
> Table 7-121 in datasheet says we have to set register 0xc6
> to value 0x10 before CLK_O_SEL can be modified. No more infos
> about this field found in datasheet. With this fix, setting
> of CLK_O_SEL field in IO_MUX_CFG register worked through dts
> property "ti,clk-output-sel" on a DP83869HMRGZR.
>
> Signed-off-by: Heiko Schocher <hs@nabladev.com>
>
> [...]
Here is the summary with links:
- [v1] net: phy: dp83869: fix setting CLK_O_SEL field.
https://git.kernel.org/netdev/net/c/46f74a3f7d57
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] ice: fix stats array overflow when VF requests more queues
From: Przemek Kitszel @ 2026-04-28 13:59 UTC (permalink / raw)
To: Michal Schmidt
Cc: Tony Nguyen, Andrew Lunn, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Jacob Keller, Petr Oros,
intel-wired-lan, netdev, linux-kernel
In-Reply-To: <20260427151827.43342-1-mschmidt@redhat.com>
On 4/27/26 17:18, Michal Schmidt wrote:
> When a VF increases its queue count via VIRTCHNL_OP_REQUEST_QUEUES,
> ice_vc_request_qs_msg() sets vf->num_req_qs and triggers a VF reset.
> The reset calls ice_vf_reconfig_vsi(), which does ice_vsi_decfg()
> followed by ice_vsi_cfg(). ice_vsi_decfg() does not free the per-ring
> stats arrays. Inside ice_vsi_cfg_def(), ice_vsi_set_num_qs() updates
> alloc_txq/alloc_rxq to the new larger value, but
> ice_vsi_alloc_stat_arrays() returns early because the stats already
> exist. ice_vsi_alloc_ring_stats() then iterates using the new larger
> alloc_txq and writes beyond the bounds of the old, smaller
> tx_ring_stats/rx_ring_stats pointer arrays, corrupting adjacent SLUB
> metadata.
>
thank you for reproducing the bug, it is exactly the situation that
I was facing
have you tried with my proposed (unfortunately not public yet) fix
to just combine ice_vsi_alloc_stat_arrays() and
ice_vsi_realloc_stat_arrays() into one function?
I will check yours too, but need to rebuild.
> KASAN detects the bug:
> ==================================================================
> BUG: KASAN: slab-out-of-bounds in ice_vsi_alloc_ring_stats+0x385/0x4a0 [ice]
> Read of size 8 at addr ffff88810affea60 by task kworker/u131:7/221
>
> CPU: 24 UID: 0 PID: 221 Comm: kworker/u131:7 Not tainted 7.1.0-rc1+ #1 PREEMPT(lazy)
> ...
> Workqueue: ice ice_service_task [ice]
> Call Trace:
> <TASK>
> ...
> kasan_report+0xd7/0x120
> ice_vsi_alloc_ring_stats+0x385/0x4a0 [ice]
> ice_vsi_cfg_def+0x12e2/0x2060 [ice]
> ice_vsi_cfg+0xb5/0x3c0 [ice]
> ice_reset_vf+0x858/0xf80 [ice]
> ice_vc_request_qs_msg+0x1da/0x290 [ice]
> ice_vc_process_vf_msg+0xb15/0x1430 [ice]
> __ice_clean_ctrlq+0x70d/0x9d0 [ice]
> ice_service_task+0x840/0xf20 [ice]
> process_one_work+0x690/0xff0
> worker_thread+0x4d9/0xd20
> kthread+0x322/0x410
> ret_from_fork+0x332/0x660
> ret_from_fork_asm+0x1a/0x30
> </TASK>
>
> Allocated by task 2439:
> kasan_save_stack+0x1c/0x40
> kasan_save_track+0x10/0x30
> __kasan_kmalloc+0x96/0xb0
> __kmalloc_noprof+0x1d8/0x580
> ice_vsi_cfg_def+0x115c/0x2060 [ice]
> ice_vsi_cfg+0xb5/0x3c0 [ice]
> ice_vsi_setup+0x180/0x320 [ice]
> ice_start_vfs+0x1f3/0x590 [ice]
> ice_ena_vfs+0x66d/0x798 [ice]
> ice_sriov_configure.cold+0xe4/0x121 [ice]
> sriov_numvfs_store+0x279/0x480
> kernfs_fop_write_iter+0x331/0x4f0
> vfs_write+0x4c4/0xe40
> ksys_write+0x10c/0x240
> do_syscall_64+0xd9/0x650
> entry_SYSCALL_64_after_hwframe+0x76/0x7e
>
> The buggy address belongs to the object at ffff88810affea40
> which belongs to the cache kmalloc-32 of size 32
> The buggy address is located 0 bytes to the right of
> allocated 32-byte region [ffff88810affea40, ffff88810affea60)
> ...
> ==================================================================
>
> ice_vsi_rebuild() handles this correctly by calling
> ice_vsi_realloc_stat_arrays() before reconfiguration, but
> ice_vf_reconfig_vsi() was missing this call.
>
> Fix by calling ice_vsi_realloc_stat_arrays() in ice_vf_reconfig_vsi()
> before ice_vsi_decfg(), mirroring the ice_vsi_rebuild() pattern. Set
> vsi->req_txq/req_rxq from vf->num_req_qs so the realloc function knows
> the target array size.
>
> See the linked RHEL Jira item for a reproducer.
>
> Fixes: 2a2cb4c6c181 ("ice: replace ice_vf_recreate_vsi() with ice_vf_reconfig_vsi()")
> Closes: https://redhat.atlassian.net/browse/RHEL-164321
> Signed-off-by: Michal Schmidt <mschmidt@redhat.com>
> Assisted-by: Claude:claude-opus-4-6 semcode
> ---
> drivers/net/ethernet/intel/ice/ice_lib.c | 2 +-
> drivers/net/ethernet/intel/ice/ice_lib.h | 1 +
> drivers/net/ethernet/intel/ice/ice_vf_lib.c | 7 +++++++
> 3 files changed, 9 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/net/ethernet/intel/ice/ice_lib.c b/drivers/net/ethernet/intel/ice/ice_lib.c
> index 837b71b7b2b7..fc78176a2a8d 100644
> --- a/drivers/net/ethernet/intel/ice/ice_lib.c
> +++ b/drivers/net/ethernet/intel/ice/ice_lib.c
> @@ -3015,7 +3015,7 @@ ice_vsi_rebuild_set_coalesce(struct ice_vsi *vsi,
> * ice_vsi_realloc_stat_arrays - Frees unused stat structures or alloc new ones
> * @vsi: VSI pointer
> */
> -static int
> +int
> ice_vsi_realloc_stat_arrays(struct ice_vsi *vsi)
> {
> u16 req_txq = vsi->req_txq ? vsi->req_txq : vsi->alloc_txq;
> diff --git a/drivers/net/ethernet/intel/ice/ice_lib.h b/drivers/net/ethernet/intel/ice/ice_lib.h
> index 49454d98dcfe..6f7da84384e5 100644
> --- a/drivers/net/ethernet/intel/ice/ice_lib.h
> +++ b/drivers/net/ethernet/intel/ice/ice_lib.h
> @@ -66,6 +66,7 @@ int ice_ena_vsi(struct ice_vsi *vsi, bool locked);
> void ice_vsi_decfg(struct ice_vsi *vsi);
> void ice_dis_vsi(struct ice_vsi *vsi, bool locked);
>
> +int ice_vsi_realloc_stat_arrays(struct ice_vsi *vsi);
> int ice_vsi_rebuild(struct ice_vsi *vsi, u32 vsi_flags);
> int ice_vsi_cfg(struct ice_vsi *vsi);
> struct ice_vsi *ice_vsi_alloc(struct ice_pf *pf);
> diff --git a/drivers/net/ethernet/intel/ice/ice_vf_lib.c b/drivers/net/ethernet/intel/ice/ice_vf_lib.c
> index 772f6b07340d..9edb2c14f553 100644
> --- a/drivers/net/ethernet/intel/ice/ice_vf_lib.c
> +++ b/drivers/net/ethernet/intel/ice/ice_vf_lib.c
> @@ -268,6 +268,13 @@ static int ice_vf_reconfig_vsi(struct ice_vf *vf)
>
> vsi->flags = ICE_VSI_FLAG_NO_INIT;
>
> + vsi->req_txq = vf->num_req_qs;
> + vsi->req_rxq = vf->num_req_qs;
> +
> + err = ice_vsi_realloc_stat_arrays(vsi);
> + if (err)
> + return err;
> +
> ice_vsi_decfg(vsi);
> ice_fltr_remove_all(vsi);
>
^ permalink raw reply
* Re: [PATCH] net: sunrpc: fix slab-out-of-bounds read in cache_seq_start_rcu
From: Chuck Lever @ 2026-04-28 13:56 UTC (permalink / raw)
To: Alessandro Zanni, Chuck Lever, Jeff Layton, NeilBrown,
Olga Kornievskaia, Dai Ngo, Tom Talpey, Trond Myklebust,
Anna Schumaker, davem, edumazet, Jakub Kicinski, Paolo Abeni,
Simon Horman
Cc: linux-nfs, netdev, linux-kernel, syzbot+60cfa08822470bbebe44
In-Reply-To: <20260428134230.136533-1-alessandro.zanni87@gmail.com>
On Tue, Apr 28, 2026, at 9:42 AM, Alessandro Zanni wrote:
> Syzbot reported slab-out-of-bounds read in cache_seq_start_rcu().
>
> The issue happens in function __cache_seq_start() when is invoked
> hlist_for_each_entry_rcu() and the hash value is greater than the
> hash_size.
>
> This fix verifies that the hash index is within the hash_size value
> before dereferencing the hash table: if the hash index is out of
> bounds return NULL, otherwise access the value.
>
> Fixes: ae74136b4bb6 ("SUNRPC: Allow cache lookups to use RCU protection
> rather than the r/w spinlock")
> Reported-by: syzbot+60cfa08822470bbebe44@syzkaller.appspotmail.com
> Closes: https://syzkaller.appspot.com/bug?extid=60cfa08822470bbebe44
> Signed-off-by: Alessandro Zanni <alessandro.zanni87@gmail.com>
> ---
> net/sunrpc/cache.c | 3 +++
> 1 file changed, 3 insertions(+)
>
> diff --git a/net/sunrpc/cache.c b/net/sunrpc/cache.c
> index 7081c1214e6c..aac5f03112f5 100644
> --- a/net/sunrpc/cache.c
> +++ b/net/sunrpc/cache.c
> @@ -1348,6 +1348,9 @@ static void *__cache_seq_start(struct seq_file
> *m, loff_t *pos)
> hash = n >> 32;
> entry = n & ((1LL<<32) - 1);
>
> + if (hash >= cd->hash_size)
> + return NULL;
> +
> hlist_for_each_entry_rcu(ch, &cd->hash_table[hash], cache_list)
> if (!entry--)
> return ch;
> --
> 2.47.3
Thank you for the patch! We have this fixed in the nfsd-testing
tree already:
https://git.kernel.org/pub/scm/linux/kernel/git/cel/linux.git/commit/?h=nfsd-testing&id=72fe9e528c68aa7b9ed5afab98c44f8b83bbe287
--
Chuck Lever
^ permalink raw reply
* Re: [PATCH 9/9] thunderbolt: Add support for USB4STREAM
From: Greg KH @ 2026-04-28 13:54 UTC (permalink / raw)
To: Mika Westerberg
Cc: linux-usb, Yehezkel Bernat, Lukas Wunner, Andreas Noever,
Alan Borzeszkowski, Andrew Lunn, David S . Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, netdev
In-Reply-To: <20260428120314.GR557136@black.igk.intel.com>
On Tue, Apr 28, 2026 at 02:03:14PM +0200, Mika Westerberg wrote:
> On Tue, Apr 28, 2026 at 05:57:37AM -0600, Greg KH wrote:
> > On Tue, Apr 28, 2026 at 09:22:09AM +0200, Mika Westerberg wrote:
> > > Introduce USB4STREAM protocol and Linux implementation. This allows two
> > > (or more) hosts to transfer data directly over Thunderbolt/USB4 cable
> > > through a character device without need to go through the network stack.
> > >
> > > Any application that supports read(2) and write(2) in some form should
> > > be able to use the device without changes. The data is sent out to the
> > > other side over a tunnel inside Thunderbolt/USB4 fabric. The character
> > > device is called /dev/tbstreamX where X is the minor number starting
> > > from 0.
> > >
> > > All stream devices need to be configured first. This is done through
> > > ConfigFS interface. There can be multiple streams at the same time (this
> > > depends on number of DMA rings and available HopIDs) and a single stream
> > > supports traffic in both directions. For example there could be an
> > > application that uses one stream as control channel and another one as
> > > bi-directional data channel.
> > >
> > > A real use-case for this is to take a backup as a part of recovery
> > > initramfs tooling (no need to setup networking or have ssh or similar
> > > tooling as part of the initramfs). Say we want to backup the disk of
> > > host1 to host2. First Thunderbolt/USB4 cable is connected between the
> > > hosts (there can be devices in the middle too) then the receiving side
> > > configures the stream:
> > >
> > > host2 # mkdir /sys/kernel/config/thunderbolt/stream/0-1.0
> > > host2 # mkdir /sys/kernel/config/thunderbolt/stream/0-1.0/backup
> > > host2 # echo -1 > /sys/kernel/config/thunderbolt/stream/0-1.0/backup/in_hopid
> > > host2 # echo -1 > /sys/kernel/config/thunderbolt/stream/0-1.0/backup/out_hopid
> > >
> > > We use automatic HopID allocation (writing -1 to HopIDs) for simplicity.
> > > >From this point forward the /dev/tbstream0 can be used pretty much as
> > > regular file:
> > >
> > > host2 # dd if=/dev/tbstream0 of=/tmp/host1.nvme0n1.backup-$(date +%F) bs=256k
> > >
> > > The host that is being backed up then configures the stream accordingly:
> > >
> > > host1 # mkdir /sys/kernel/config/thunderbolt/stream/0-503.0
> > > host1 # mkdir /sys/kernel/config/thunderbolt/stream/0-503.0/backup
> > >
> > > Here we take advantage of the fact that host2 also announces the active
> > > streams through XDomain properties so the name "backup" gives us the
> > > HopIDs. It is also possible to configure them manually in the same way
> > > we did for host2.
> > >
> > > Then it is just a matter of copying the data over:
> > >
> > > host1 # dd if=/dev/nvme0n1 of=/dev/tbstream0 bs=256k
> > >
> > > Similarly it is possible to transfer parts of the filesystem. For
> > > example copy contents of mydir over to the host2:
> > >
> > > host2 # gunzip < /dev/tbstream0 | tar xf -
> > > host1 # tar cf - mydir | gzip > /dev/tbstream0
> > >
> > > Other end of the spectrum use-case is "borrowing" laptop (host1) camera
> > > to desktop (host2):
> > >
> > > host2 # gst-launch-1.0 filesrc location=/dev/tbstream0 ! jpegdec ! videoconvert ! \
> > > autovideosink
> > >
> > > host1 # gst-launch-1.0 v4l2src device=/dev/video0 ! video/x-raw,width=1920,height=1080 ! \
> > > jpegenc quality=90 ! filesink location=/dev/tbstream0
> > >
> > > Once the streams are no longer needed they can be removed:
> > >
> > > host1 # cd /sys/kernel/config/thunderbolt/stream/
> > > host1 # rmdir -p 0-503.0/backup
> > >
> > > host2 # cd /sys/kernel/config/thunderbolt/stream
> > > host2 # rmdir -p 0-1.0/backup
> >
> > Very cool, but shouldn't the above be in some documentation somewhere so
> > that people know how to use it?
>
> Sure, I can add it part of the Documentation/admin-guide/thunderbolt.rs for
> example.
>
> > And why do you need a whole major for this, why not just use a misc
> > device that it dynamically created for every new dev?
>
> We do use this:
>
> ret = alloc_chrdev_region(&tbstream_devt, 0, TBSTREAM_DEV_MINORS,
> "tbstream");
>
> that should be dynamically allocated, no?
Yes, but you are using up a whole major number for this, and in reality
there's only going to be 1-2, maybe 4, different devices needed at once,
right? So just use the miscdev interface instead?
thanks,
greg k-h
^ permalink raw reply
* Re: [PATCH v1] net: phy: dp83869: fix setting CLK_O_SEL field.
From: Heiko Schocher @ 2026-04-28 13:54 UTC (permalink / raw)
To: Paolo Abeni, netdev
Cc: Andrew Lunn, David S. Miller, Eric Dumazet, Heiner Kallweit,
Jakub Kicinski, Russell King, linux-kernel
In-Reply-To: <fcb880c0-40d3-4613-af73-f1cdd1764975@redhat.com>
Hello Paolo,
On 28.04.26 15:50, Paolo Abeni wrote:
> On 4/25/26 5:13 AM, Heiko Schocher wrote:
>> Table 7-121 in datasheet says we have to set register 0xc6
>> to value 0x10 before CLK_O_SEL can be modified. No more infos
>> about this field found in datasheet. With this fix, setting
>> of CLK_O_SEL field in IO_MUX_CFG register worked through dts
>> property "ti,clk-output-sel" on a DP83869HMRGZR.
>>
>> Signed-off-by: Heiko Schocher <hs@nabladev.com>
>
> Note that a required fixes tag is missing here:
>
> Fixes: 01db923e8377 ("net: phy: dp83869: Add TI dp83869 phy")
Should I resend a v2 patch with this tag added ?
Thanks!
bye,
Heiko
>
> /P
>
--
Nabla Software Engineering
HRB 40522 Augsburg
Phone: +49 821 45592596
E-Mail: office@nabladev.com
Geschäftsführer : Stefano Babic
^ permalink raw reply
* Re: [PATCH v1] net: phy: dp83869: fix setting CLK_O_SEL field.
From: Paolo Abeni @ 2026-04-28 13:50 UTC (permalink / raw)
To: Heiko Schocher, netdev
Cc: Andrew Lunn, David S. Miller, Eric Dumazet, Heiner Kallweit,
Jakub Kicinski, Russell King, linux-kernel
In-Reply-To: <20260425031339.3318-1-hs@nabladev.com>
On 4/25/26 5:13 AM, Heiko Schocher wrote:
> Table 7-121 in datasheet says we have to set register 0xc6
> to value 0x10 before CLK_O_SEL can be modified. No more infos
> about this field found in datasheet. With this fix, setting
> of CLK_O_SEL field in IO_MUX_CFG register worked through dts
> property "ti,clk-output-sel" on a DP83869HMRGZR.
>
> Signed-off-by: Heiko Schocher <hs@nabladev.com>
Note that a required fixes tag is missing here:
Fixes: 01db923e8377 ("net: phy: dp83869: Add TI dp83869 phy")
/P
^ permalink raw reply
* Re: [PATCH net] sfc: fix error code in efx_devlink_info_running_versions()
From: Dan Carpenter @ 2026-04-28 13:49 UTC (permalink / raw)
To: Edward Cree
Cc: Alejandro Lucero, Andrew Lunn, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Martin Habets, Jiri Pirko, netdev,
linux-net-drivers, linux-kernel, kernel-janitors
In-Reply-To: <0dd0c884-c846-4f17-986d-fb24b21a836f@gmail.com>
On Tue, Apr 28, 2026 at 02:36:55PM +0100, Edward Cree wrote:
> On 25/04/2026 10:09, Dan Carpenter wrote:
> > Return -EINVAL if efx_mcdi_rpc() doesn't return enough space.
> >
> > Fixes: 14743ddd2495 ("sfc: add devlink info support for ef100")
> > Signed-off-by: Dan Carpenter <error27@gmail.com>
> > ---
> > drivers/net/ethernet/sfc/efx_devlink.c | 2 +-
> > 1 file changed, 1 insertion(+), 1 deletion(-)
> >
> > diff --git a/drivers/net/ethernet/sfc/efx_devlink.c b/drivers/net/ethernet/sfc/efx_devlink.c
> > index d842c60dfc10..45f412bb9b5d 100644
> > --- a/drivers/net/ethernet/sfc/efx_devlink.c
> > +++ b/drivers/net/ethernet/sfc/efx_devlink.c
> > @@ -531,7 +531,7 @@ static int efx_devlink_info_running_versions(struct efx_nic *efx,
> > if (rc || outlength < MC_CMD_GET_VERSION_OUT_LEN) {
> > netif_err(efx, drv, efx->net_dev,
> > "mcdi MC_CMD_GET_VERSION failed\n");
> > - return rc;
> > + return rc ?: -EINVAL;
> > }
> >
> > /* Handle previous output */
>
> Usual practice in sfc is to use -EIO for 'MC response was too short'; it
> signifies misbehaviour from the hardware, not any invalid input argument
> as -EINVAL would suggest.
> Other than that, looks fine.
Sure, I'll send a v2.
regards,
dan carpenter
^ permalink raw reply
* [PATCH v3 2/2] pinctrl: qcom: add the TLMM driver for the Nord platforms
From: Bartosz Golaszewski @ 2026-04-28 13:48 UTC (permalink / raw)
To: Bjorn Andersson, Linus Walleij, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Richard Cochran, Bartosz Golaszewski, Shawn Guo,
Arnd Bergmann, Dmitry Baryshkov
Cc: linux-arm-msm, linux-gpio, devicetree, linux-kernel, netdev,
Bartosz Golaszewski
In-Reply-To: <20260428-nord-tlmm-v3-0-f16f08d084cc@oss.qualcomm.com>
Add support for the TLMM controller on the Qualcomm Nord platform.
Co-developed-by: Shawn Guo <shengchao.guo@oss.qualcomm.com>
Signed-off-by: Shawn Guo <shengchao.guo@oss.qualcomm.com>
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
---
drivers/pinctrl/qcom/Kconfig.msm | 8 +
drivers/pinctrl/qcom/Makefile | 1 +
drivers/pinctrl/qcom/pinctrl-nord.c | 1771 +++++++++++++++++++++++++++++++++++
3 files changed, 1780 insertions(+)
diff --git a/drivers/pinctrl/qcom/Kconfig.msm b/drivers/pinctrl/qcom/Kconfig.msm
index 836cdeca1006ff7ad5030ac5c537d775d3f0261b..6d63b3302df1d218436ab599584ba4619e8502d3 100644
--- a/drivers/pinctrl/qcom/Kconfig.msm
+++ b/drivers/pinctrl/qcom/Kconfig.msm
@@ -229,6 +229,14 @@ config PINCTRL_MSM8998
This is the pinctrl, pinmux, pinconf and gpiolib driver for the
Qualcomm TLMM block found in the Qualcomm MSM8998 platform.
+config PINCTRL_NORD
+ tristate "Qualcomm Nord pin controller driver"
+ depends on ARM64 || COMPILE_TEST
+ default ARCH_QCOM
+ help
+ This is the pinctrl, pinmux and pinconf driver for the Qualcomm
+ TLMM block found on the Qualcomm NORD platforms.
+
config PINCTRL_QCM2290
tristate "Qualcomm QCM2290 pin controller driver"
depends on ARM64 || COMPILE_TEST
diff --git a/drivers/pinctrl/qcom/Makefile b/drivers/pinctrl/qcom/Makefile
index 84bda3ada8749e89077c2d4d1065d0db0e4e4181..12e7a51ad894261a37b00dc5520484803ecb8607 100644
--- a/drivers/pinctrl/qcom/Makefile
+++ b/drivers/pinctrl/qcom/Makefile
@@ -37,6 +37,7 @@ obj-$(CONFIG_PINCTRL_MDM9607) += pinctrl-mdm9607.o
obj-$(CONFIG_PINCTRL_MDM9615) += pinctrl-mdm9615.o
obj-$(CONFIG_PINCTRL_MILOS) += pinctrl-milos.o
obj-$(CONFIG_PINCTRL_MILOS_LPASS_LPI) += pinctrl-milos-lpass-lpi.o
+obj-$(CONFIG_PINCTRL_NORD) += pinctrl-nord.o
obj-$(CONFIG_PINCTRL_QCOM_SPMI_PMIC) += pinctrl-spmi-gpio.o
obj-$(CONFIG_PINCTRL_QCOM_SPMI_PMIC) += pinctrl-spmi-mpp.o
obj-$(CONFIG_PINCTRL_QCOM_SSBI_PMIC) += pinctrl-ssbi-gpio.o
diff --git a/drivers/pinctrl/qcom/pinctrl-nord.c b/drivers/pinctrl/qcom/pinctrl-nord.c
new file mode 100644
index 0000000000000000000000000000000000000000..1a1e2fd3d6449cdbd941b70b19a3cac240e15f06
--- /dev/null
+++ b/drivers/pinctrl/qcom/pinctrl-nord.c
@@ -0,0 +1,1771 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
+ */
+
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+
+#include "pinctrl-msm.h"
+
+#define REG_SIZE 0x1000
+#define PINGROUP(id, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11) \
+ { \
+ .grp = PINCTRL_PINGROUP("gpio" #id, \
+ gpio##id##_pins, \
+ ARRAY_SIZE(gpio##id##_pins)), \
+ .ctl_reg = REG_SIZE * id, \
+ .io_reg = 0x4 + REG_SIZE * id, \
+ .intr_cfg_reg = 0x8 + REG_SIZE * id, \
+ .intr_status_reg = 0xc + REG_SIZE * id, \
+ .mux_bit = 2, \
+ .pull_bit = 0, \
+ .drv_bit = 6, \
+ .egpio_enable = 12, \
+ .egpio_present = 11, \
+ .oe_bit = 9, \
+ .in_bit = 0, \
+ .out_bit = 1, \
+ .intr_enable_bit = 0, \
+ .intr_status_bit = 0, \
+ .intr_wakeup_present_bit = 6, \
+ .intr_wakeup_enable_bit = 7, \
+ .intr_target_bit = 8, \
+ .intr_target_kpss_val = 3, \
+ .intr_raw_status_bit = 4, \
+ .intr_polarity_bit = 1, \
+ .intr_detection_bit = 2, \
+ .intr_detection_width = 2, \
+ .funcs = (int[]){ \
+ msm_mux_gpio, /* gpio mode */ \
+ msm_mux_##f1, \
+ msm_mux_##f2, \
+ msm_mux_##f3, \
+ msm_mux_##f4, \
+ msm_mux_##f5, \
+ msm_mux_##f6, \
+ msm_mux_##f7, \
+ msm_mux_##f8, \
+ msm_mux_##f9, \
+ msm_mux_##f10, \
+ msm_mux_##f11 /* egpio mode */ \
+ }, \
+ .nfuncs = 12, \
+ }
+
+#define UFS_RESET(pg_name, ctl, io) \
+ { \
+ .grp = PINCTRL_PINGROUP(#pg_name, \
+ pg_name##_pins, \
+ ARRAY_SIZE(pg_name##_pins)), \
+ .ctl_reg = ctl, \
+ .io_reg = io, \
+ .intr_cfg_reg = 0, \
+ .intr_status_reg = 0, \
+ .mux_bit = -1, \
+ .pull_bit = 3, \
+ .drv_bit = 0, \
+ .oe_bit = -1, \
+ .in_bit = -1, \
+ .out_bit = 0, \
+ .intr_enable_bit = -1, \
+ .intr_status_bit = -1, \
+ .intr_target_bit = -1, \
+ .intr_raw_status_bit = -1, \
+ .intr_polarity_bit = -1, \
+ .intr_detection_bit = -1, \
+ .intr_detection_width = -1, \
+ }
+
+static const struct pinctrl_pin_desc nord_pins[] = {
+ PINCTRL_PIN(0, "GPIO_0"),
+ PINCTRL_PIN(1, "GPIO_1"),
+ PINCTRL_PIN(2, "GPIO_2"),
+ PINCTRL_PIN(3, "GPIO_3"),
+ PINCTRL_PIN(4, "GPIO_4"),
+ PINCTRL_PIN(5, "GPIO_5"),
+ PINCTRL_PIN(6, "GPIO_6"),
+ PINCTRL_PIN(7, "GPIO_7"),
+ PINCTRL_PIN(8, "GPIO_8"),
+ PINCTRL_PIN(9, "GPIO_9"),
+ PINCTRL_PIN(10, "GPIO_10"),
+ PINCTRL_PIN(11, "GPIO_11"),
+ PINCTRL_PIN(12, "GPIO_12"),
+ PINCTRL_PIN(13, "GPIO_13"),
+ PINCTRL_PIN(14, "GPIO_14"),
+ PINCTRL_PIN(15, "GPIO_15"),
+ PINCTRL_PIN(16, "GPIO_16"),
+ PINCTRL_PIN(17, "GPIO_17"),
+ PINCTRL_PIN(18, "GPIO_18"),
+ PINCTRL_PIN(19, "GPIO_19"),
+ PINCTRL_PIN(20, "GPIO_20"),
+ PINCTRL_PIN(21, "GPIO_21"),
+ PINCTRL_PIN(22, "GPIO_22"),
+ PINCTRL_PIN(23, "GPIO_23"),
+ PINCTRL_PIN(24, "GPIO_24"),
+ PINCTRL_PIN(25, "GPIO_25"),
+ PINCTRL_PIN(26, "GPIO_26"),
+ PINCTRL_PIN(27, "GPIO_27"),
+ PINCTRL_PIN(28, "GPIO_28"),
+ PINCTRL_PIN(29, "GPIO_29"),
+ PINCTRL_PIN(30, "GPIO_30"),
+ PINCTRL_PIN(31, "GPIO_31"),
+ PINCTRL_PIN(32, "GPIO_32"),
+ PINCTRL_PIN(33, "GPIO_33"),
+ PINCTRL_PIN(34, "GPIO_34"),
+ PINCTRL_PIN(35, "GPIO_35"),
+ PINCTRL_PIN(36, "GPIO_36"),
+ PINCTRL_PIN(37, "GPIO_37"),
+ PINCTRL_PIN(38, "GPIO_38"),
+ PINCTRL_PIN(39, "GPIO_39"),
+ PINCTRL_PIN(40, "GPIO_40"),
+ PINCTRL_PIN(41, "GPIO_41"),
+ PINCTRL_PIN(42, "GPIO_42"),
+ PINCTRL_PIN(43, "GPIO_43"),
+ PINCTRL_PIN(44, "GPIO_44"),
+ PINCTRL_PIN(45, "GPIO_45"),
+ PINCTRL_PIN(46, "GPIO_46"),
+ PINCTRL_PIN(47, "GPIO_47"),
+ PINCTRL_PIN(48, "GPIO_48"),
+ PINCTRL_PIN(49, "GPIO_49"),
+ PINCTRL_PIN(50, "GPIO_50"),
+ PINCTRL_PIN(51, "GPIO_51"),
+ PINCTRL_PIN(52, "GPIO_52"),
+ PINCTRL_PIN(53, "GPIO_53"),
+ PINCTRL_PIN(54, "GPIO_54"),
+ PINCTRL_PIN(55, "GPIO_55"),
+ PINCTRL_PIN(56, "GPIO_56"),
+ PINCTRL_PIN(57, "GPIO_57"),
+ PINCTRL_PIN(58, "GPIO_58"),
+ PINCTRL_PIN(59, "GPIO_59"),
+ PINCTRL_PIN(60, "GPIO_60"),
+ PINCTRL_PIN(61, "GPIO_61"),
+ PINCTRL_PIN(62, "GPIO_62"),
+ PINCTRL_PIN(63, "GPIO_63"),
+ PINCTRL_PIN(64, "GPIO_64"),
+ PINCTRL_PIN(65, "GPIO_65"),
+ PINCTRL_PIN(66, "GPIO_66"),
+ PINCTRL_PIN(67, "GPIO_67"),
+ PINCTRL_PIN(68, "GPIO_68"),
+ PINCTRL_PIN(69, "GPIO_69"),
+ PINCTRL_PIN(70, "GPIO_70"),
+ PINCTRL_PIN(71, "GPIO_71"),
+ PINCTRL_PIN(72, "GPIO_72"),
+ PINCTRL_PIN(73, "GPIO_73"),
+ PINCTRL_PIN(74, "GPIO_74"),
+ PINCTRL_PIN(75, "GPIO_75"),
+ PINCTRL_PIN(76, "GPIO_76"),
+ PINCTRL_PIN(77, "GPIO_77"),
+ PINCTRL_PIN(78, "GPIO_78"),
+ PINCTRL_PIN(79, "GPIO_79"),
+ PINCTRL_PIN(80, "GPIO_80"),
+ PINCTRL_PIN(81, "GPIO_81"),
+ PINCTRL_PIN(82, "GPIO_82"),
+ PINCTRL_PIN(83, "GPIO_83"),
+ PINCTRL_PIN(84, "GPIO_84"),
+ PINCTRL_PIN(85, "GPIO_85"),
+ PINCTRL_PIN(86, "GPIO_86"),
+ PINCTRL_PIN(87, "GPIO_87"),
+ PINCTRL_PIN(88, "GPIO_88"),
+ PINCTRL_PIN(89, "GPIO_89"),
+ PINCTRL_PIN(90, "GPIO_90"),
+ PINCTRL_PIN(91, "GPIO_91"),
+ PINCTRL_PIN(92, "GPIO_92"),
+ PINCTRL_PIN(93, "GPIO_93"),
+ PINCTRL_PIN(94, "GPIO_94"),
+ PINCTRL_PIN(95, "GPIO_95"),
+ PINCTRL_PIN(96, "GPIO_96"),
+ PINCTRL_PIN(97, "GPIO_97"),
+ PINCTRL_PIN(98, "GPIO_98"),
+ PINCTRL_PIN(99, "GPIO_99"),
+ PINCTRL_PIN(100, "GPIO_100"),
+ PINCTRL_PIN(101, "GPIO_101"),
+ PINCTRL_PIN(102, "GPIO_102"),
+ PINCTRL_PIN(103, "GPIO_103"),
+ PINCTRL_PIN(104, "GPIO_104"),
+ PINCTRL_PIN(105, "GPIO_105"),
+ PINCTRL_PIN(106, "GPIO_106"),
+ PINCTRL_PIN(107, "GPIO_107"),
+ PINCTRL_PIN(108, "GPIO_108"),
+ PINCTRL_PIN(109, "GPIO_109"),
+ PINCTRL_PIN(110, "GPIO_110"),
+ PINCTRL_PIN(111, "GPIO_111"),
+ PINCTRL_PIN(112, "GPIO_112"),
+ PINCTRL_PIN(113, "GPIO_113"),
+ PINCTRL_PIN(114, "GPIO_114"),
+ PINCTRL_PIN(115, "GPIO_115"),
+ PINCTRL_PIN(116, "GPIO_116"),
+ PINCTRL_PIN(117, "GPIO_117"),
+ PINCTRL_PIN(118, "GPIO_118"),
+ PINCTRL_PIN(119, "GPIO_119"),
+ PINCTRL_PIN(120, "GPIO_120"),
+ PINCTRL_PIN(121, "GPIO_121"),
+ PINCTRL_PIN(122, "GPIO_122"),
+ PINCTRL_PIN(123, "GPIO_123"),
+ PINCTRL_PIN(124, "GPIO_124"),
+ PINCTRL_PIN(125, "GPIO_125"),
+ PINCTRL_PIN(126, "GPIO_126"),
+ PINCTRL_PIN(127, "GPIO_127"),
+ PINCTRL_PIN(128, "GPIO_128"),
+ PINCTRL_PIN(129, "GPIO_129"),
+ PINCTRL_PIN(130, "GPIO_130"),
+ PINCTRL_PIN(131, "GPIO_131"),
+ PINCTRL_PIN(132, "GPIO_132"),
+ PINCTRL_PIN(133, "GPIO_133"),
+ PINCTRL_PIN(134, "GPIO_134"),
+ PINCTRL_PIN(135, "GPIO_135"),
+ PINCTRL_PIN(136, "GPIO_136"),
+ PINCTRL_PIN(137, "GPIO_137"),
+ PINCTRL_PIN(138, "GPIO_138"),
+ PINCTRL_PIN(139, "GPIO_139"),
+ PINCTRL_PIN(140, "GPIO_140"),
+ PINCTRL_PIN(141, "GPIO_141"),
+ PINCTRL_PIN(142, "GPIO_142"),
+ PINCTRL_PIN(143, "GPIO_143"),
+ PINCTRL_PIN(144, "GPIO_144"),
+ PINCTRL_PIN(145, "GPIO_145"),
+ PINCTRL_PIN(146, "GPIO_146"),
+ PINCTRL_PIN(147, "GPIO_147"),
+ PINCTRL_PIN(148, "GPIO_148"),
+ PINCTRL_PIN(149, "GPIO_149"),
+ PINCTRL_PIN(150, "GPIO_150"),
+ PINCTRL_PIN(151, "GPIO_151"),
+ PINCTRL_PIN(152, "GPIO_152"),
+ PINCTRL_PIN(153, "GPIO_153"),
+ PINCTRL_PIN(154, "GPIO_154"),
+ PINCTRL_PIN(155, "GPIO_155"),
+ PINCTRL_PIN(156, "GPIO_156"),
+ PINCTRL_PIN(157, "GPIO_157"),
+ PINCTRL_PIN(158, "GPIO_158"),
+ PINCTRL_PIN(159, "GPIO_159"),
+ PINCTRL_PIN(160, "GPIO_160"),
+ PINCTRL_PIN(161, "GPIO_161"),
+ PINCTRL_PIN(162, "GPIO_162"),
+ PINCTRL_PIN(163, "GPIO_163"),
+ PINCTRL_PIN(164, "GPIO_164"),
+ PINCTRL_PIN(165, "GPIO_165"),
+ PINCTRL_PIN(166, "GPIO_166"),
+ PINCTRL_PIN(167, "GPIO_167"),
+ PINCTRL_PIN(168, "GPIO_168"),
+ PINCTRL_PIN(169, "GPIO_169"),
+ PINCTRL_PIN(170, "GPIO_170"),
+ PINCTRL_PIN(171, "GPIO_171"),
+ PINCTRL_PIN(172, "GPIO_172"),
+ PINCTRL_PIN(173, "GPIO_173"),
+ PINCTRL_PIN(174, "GPIO_174"),
+ PINCTRL_PIN(175, "GPIO_175"),
+ PINCTRL_PIN(176, "GPIO_176"),
+ PINCTRL_PIN(177, "GPIO_177"),
+ PINCTRL_PIN(178, "GPIO_178"),
+ PINCTRL_PIN(179, "GPIO_179"),
+ PINCTRL_PIN(180, "GPIO_180"),
+ PINCTRL_PIN(181, "UFS_RESET"),
+};
+
+#define DECLARE_MSM_GPIO_PINS(pin) \
+ static const unsigned int gpio##pin##_pins[] = { pin }
+DECLARE_MSM_GPIO_PINS(0);
+DECLARE_MSM_GPIO_PINS(1);
+DECLARE_MSM_GPIO_PINS(2);
+DECLARE_MSM_GPIO_PINS(3);
+DECLARE_MSM_GPIO_PINS(4);
+DECLARE_MSM_GPIO_PINS(5);
+DECLARE_MSM_GPIO_PINS(6);
+DECLARE_MSM_GPIO_PINS(7);
+DECLARE_MSM_GPIO_PINS(8);
+DECLARE_MSM_GPIO_PINS(9);
+DECLARE_MSM_GPIO_PINS(10);
+DECLARE_MSM_GPIO_PINS(11);
+DECLARE_MSM_GPIO_PINS(12);
+DECLARE_MSM_GPIO_PINS(13);
+DECLARE_MSM_GPIO_PINS(14);
+DECLARE_MSM_GPIO_PINS(15);
+DECLARE_MSM_GPIO_PINS(16);
+DECLARE_MSM_GPIO_PINS(17);
+DECLARE_MSM_GPIO_PINS(18);
+DECLARE_MSM_GPIO_PINS(19);
+DECLARE_MSM_GPIO_PINS(20);
+DECLARE_MSM_GPIO_PINS(21);
+DECLARE_MSM_GPIO_PINS(22);
+DECLARE_MSM_GPIO_PINS(23);
+DECLARE_MSM_GPIO_PINS(24);
+DECLARE_MSM_GPIO_PINS(25);
+DECLARE_MSM_GPIO_PINS(26);
+DECLARE_MSM_GPIO_PINS(27);
+DECLARE_MSM_GPIO_PINS(28);
+DECLARE_MSM_GPIO_PINS(29);
+DECLARE_MSM_GPIO_PINS(30);
+DECLARE_MSM_GPIO_PINS(31);
+DECLARE_MSM_GPIO_PINS(32);
+DECLARE_MSM_GPIO_PINS(33);
+DECLARE_MSM_GPIO_PINS(34);
+DECLARE_MSM_GPIO_PINS(35);
+DECLARE_MSM_GPIO_PINS(36);
+DECLARE_MSM_GPIO_PINS(37);
+DECLARE_MSM_GPIO_PINS(38);
+DECLARE_MSM_GPIO_PINS(39);
+DECLARE_MSM_GPIO_PINS(40);
+DECLARE_MSM_GPIO_PINS(41);
+DECLARE_MSM_GPIO_PINS(42);
+DECLARE_MSM_GPIO_PINS(43);
+DECLARE_MSM_GPIO_PINS(44);
+DECLARE_MSM_GPIO_PINS(45);
+DECLARE_MSM_GPIO_PINS(46);
+DECLARE_MSM_GPIO_PINS(47);
+DECLARE_MSM_GPIO_PINS(48);
+DECLARE_MSM_GPIO_PINS(49);
+DECLARE_MSM_GPIO_PINS(50);
+DECLARE_MSM_GPIO_PINS(51);
+DECLARE_MSM_GPIO_PINS(52);
+DECLARE_MSM_GPIO_PINS(53);
+DECLARE_MSM_GPIO_PINS(54);
+DECLARE_MSM_GPIO_PINS(55);
+DECLARE_MSM_GPIO_PINS(56);
+DECLARE_MSM_GPIO_PINS(57);
+DECLARE_MSM_GPIO_PINS(58);
+DECLARE_MSM_GPIO_PINS(59);
+DECLARE_MSM_GPIO_PINS(60);
+DECLARE_MSM_GPIO_PINS(61);
+DECLARE_MSM_GPIO_PINS(62);
+DECLARE_MSM_GPIO_PINS(63);
+DECLARE_MSM_GPIO_PINS(64);
+DECLARE_MSM_GPIO_PINS(65);
+DECLARE_MSM_GPIO_PINS(66);
+DECLARE_MSM_GPIO_PINS(67);
+DECLARE_MSM_GPIO_PINS(68);
+DECLARE_MSM_GPIO_PINS(69);
+DECLARE_MSM_GPIO_PINS(70);
+DECLARE_MSM_GPIO_PINS(71);
+DECLARE_MSM_GPIO_PINS(72);
+DECLARE_MSM_GPIO_PINS(73);
+DECLARE_MSM_GPIO_PINS(74);
+DECLARE_MSM_GPIO_PINS(75);
+DECLARE_MSM_GPIO_PINS(76);
+DECLARE_MSM_GPIO_PINS(77);
+DECLARE_MSM_GPIO_PINS(78);
+DECLARE_MSM_GPIO_PINS(79);
+DECLARE_MSM_GPIO_PINS(80);
+DECLARE_MSM_GPIO_PINS(81);
+DECLARE_MSM_GPIO_PINS(82);
+DECLARE_MSM_GPIO_PINS(83);
+DECLARE_MSM_GPIO_PINS(84);
+DECLARE_MSM_GPIO_PINS(85);
+DECLARE_MSM_GPIO_PINS(86);
+DECLARE_MSM_GPIO_PINS(87);
+DECLARE_MSM_GPIO_PINS(88);
+DECLARE_MSM_GPIO_PINS(89);
+DECLARE_MSM_GPIO_PINS(90);
+DECLARE_MSM_GPIO_PINS(91);
+DECLARE_MSM_GPIO_PINS(92);
+DECLARE_MSM_GPIO_PINS(93);
+DECLARE_MSM_GPIO_PINS(94);
+DECLARE_MSM_GPIO_PINS(95);
+DECLARE_MSM_GPIO_PINS(96);
+DECLARE_MSM_GPIO_PINS(97);
+DECLARE_MSM_GPIO_PINS(98);
+DECLARE_MSM_GPIO_PINS(99);
+DECLARE_MSM_GPIO_PINS(100);
+DECLARE_MSM_GPIO_PINS(101);
+DECLARE_MSM_GPIO_PINS(102);
+DECLARE_MSM_GPIO_PINS(103);
+DECLARE_MSM_GPIO_PINS(104);
+DECLARE_MSM_GPIO_PINS(105);
+DECLARE_MSM_GPIO_PINS(106);
+DECLARE_MSM_GPIO_PINS(107);
+DECLARE_MSM_GPIO_PINS(108);
+DECLARE_MSM_GPIO_PINS(109);
+DECLARE_MSM_GPIO_PINS(110);
+DECLARE_MSM_GPIO_PINS(111);
+DECLARE_MSM_GPIO_PINS(112);
+DECLARE_MSM_GPIO_PINS(113);
+DECLARE_MSM_GPIO_PINS(114);
+DECLARE_MSM_GPIO_PINS(115);
+DECLARE_MSM_GPIO_PINS(116);
+DECLARE_MSM_GPIO_PINS(117);
+DECLARE_MSM_GPIO_PINS(118);
+DECLARE_MSM_GPIO_PINS(119);
+DECLARE_MSM_GPIO_PINS(120);
+DECLARE_MSM_GPIO_PINS(121);
+DECLARE_MSM_GPIO_PINS(122);
+DECLARE_MSM_GPIO_PINS(123);
+DECLARE_MSM_GPIO_PINS(124);
+DECLARE_MSM_GPIO_PINS(125);
+DECLARE_MSM_GPIO_PINS(126);
+DECLARE_MSM_GPIO_PINS(127);
+DECLARE_MSM_GPIO_PINS(128);
+DECLARE_MSM_GPIO_PINS(129);
+DECLARE_MSM_GPIO_PINS(130);
+DECLARE_MSM_GPIO_PINS(131);
+DECLARE_MSM_GPIO_PINS(132);
+DECLARE_MSM_GPIO_PINS(133);
+DECLARE_MSM_GPIO_PINS(134);
+DECLARE_MSM_GPIO_PINS(135);
+DECLARE_MSM_GPIO_PINS(136);
+DECLARE_MSM_GPIO_PINS(137);
+DECLARE_MSM_GPIO_PINS(138);
+DECLARE_MSM_GPIO_PINS(139);
+DECLARE_MSM_GPIO_PINS(140);
+DECLARE_MSM_GPIO_PINS(141);
+DECLARE_MSM_GPIO_PINS(142);
+DECLARE_MSM_GPIO_PINS(143);
+DECLARE_MSM_GPIO_PINS(144);
+DECLARE_MSM_GPIO_PINS(145);
+DECLARE_MSM_GPIO_PINS(146);
+DECLARE_MSM_GPIO_PINS(147);
+DECLARE_MSM_GPIO_PINS(148);
+DECLARE_MSM_GPIO_PINS(149);
+DECLARE_MSM_GPIO_PINS(150);
+DECLARE_MSM_GPIO_PINS(151);
+DECLARE_MSM_GPIO_PINS(152);
+DECLARE_MSM_GPIO_PINS(153);
+DECLARE_MSM_GPIO_PINS(154);
+DECLARE_MSM_GPIO_PINS(155);
+DECLARE_MSM_GPIO_PINS(156);
+DECLARE_MSM_GPIO_PINS(157);
+DECLARE_MSM_GPIO_PINS(158);
+DECLARE_MSM_GPIO_PINS(159);
+DECLARE_MSM_GPIO_PINS(160);
+DECLARE_MSM_GPIO_PINS(161);
+DECLARE_MSM_GPIO_PINS(162);
+DECLARE_MSM_GPIO_PINS(163);
+DECLARE_MSM_GPIO_PINS(164);
+DECLARE_MSM_GPIO_PINS(165);
+DECLARE_MSM_GPIO_PINS(166);
+DECLARE_MSM_GPIO_PINS(167);
+DECLARE_MSM_GPIO_PINS(168);
+DECLARE_MSM_GPIO_PINS(169);
+DECLARE_MSM_GPIO_PINS(170);
+DECLARE_MSM_GPIO_PINS(171);
+DECLARE_MSM_GPIO_PINS(172);
+DECLARE_MSM_GPIO_PINS(173);
+DECLARE_MSM_GPIO_PINS(174);
+DECLARE_MSM_GPIO_PINS(175);
+DECLARE_MSM_GPIO_PINS(176);
+DECLARE_MSM_GPIO_PINS(177);
+DECLARE_MSM_GPIO_PINS(178);
+DECLARE_MSM_GPIO_PINS(179);
+DECLARE_MSM_GPIO_PINS(180);
+
+static const unsigned int ufs_reset_pins[] = { 181 };
+
+enum nord_functions {
+ msm_mux_gpio,
+ msm_mux_aoss_cti,
+ msm_mux_atest_char,
+ msm_mux_atest_usb20,
+ msm_mux_atest_usb21,
+ msm_mux_aud_intfc0_clk,
+ msm_mux_aud_intfc0_data,
+ msm_mux_aud_intfc0_ws,
+ msm_mux_aud_intfc10_clk,
+ msm_mux_aud_intfc10_data,
+ msm_mux_aud_intfc10_ws,
+ msm_mux_aud_intfc1_clk,
+ msm_mux_aud_intfc1_data,
+ msm_mux_aud_intfc1_ws,
+ msm_mux_aud_intfc2_clk,
+ msm_mux_aud_intfc2_data,
+ msm_mux_aud_intfc2_ws,
+ msm_mux_aud_intfc3_clk,
+ msm_mux_aud_intfc3_data,
+ msm_mux_aud_intfc3_ws,
+ msm_mux_aud_intfc4_clk,
+ msm_mux_aud_intfc4_data,
+ msm_mux_aud_intfc4_ws,
+ msm_mux_aud_intfc5_clk,
+ msm_mux_aud_intfc5_data,
+ msm_mux_aud_intfc5_ws,
+ msm_mux_aud_intfc6_clk,
+ msm_mux_aud_intfc6_data,
+ msm_mux_aud_intfc6_ws,
+ msm_mux_aud_intfc7_clk,
+ msm_mux_aud_intfc7_data,
+ msm_mux_aud_intfc7_ws,
+ msm_mux_aud_intfc8_clk,
+ msm_mux_aud_intfc8_data,
+ msm_mux_aud_intfc8_ws,
+ msm_mux_aud_intfc9_clk,
+ msm_mux_aud_intfc9_data,
+ msm_mux_aud_intfc9_ws,
+ msm_mux_aud_mclk0_mira,
+ msm_mux_aud_mclk0_mirb,
+ msm_mux_aud_mclk1_mira,
+ msm_mux_aud_mclk1_mirb,
+ msm_mux_aud_mclk2_mira,
+ msm_mux_aud_mclk2_mirb,
+ msm_mux_aud_refclk0,
+ msm_mux_aud_refclk1,
+ msm_mux_bist_done,
+ msm_mux_ccu_async_in,
+ msm_mux_ccu_i2c_scl,
+ msm_mux_ccu_i2c_sda,
+ msm_mux_ccu_timer,
+ msm_mux_clink_debug,
+ msm_mux_dbg_out,
+ msm_mux_dbg_out_clk,
+ msm_mux_ddr_bist_complete,
+ msm_mux_ddr_bist_fail,
+ msm_mux_ddr_bist_start,
+ msm_mux_ddr_bist_stop,
+ msm_mux_ddr_pxi,
+ msm_mux_dp_rx0,
+ msm_mux_dp_rx00,
+ msm_mux_dp_rx01,
+ msm_mux_dp_rx0_mute,
+ msm_mux_dp_rx1,
+ msm_mux_dp_rx10,
+ msm_mux_dp_rx11,
+ msm_mux_dp_rx1_mute,
+ msm_mux_edp0_hot,
+ msm_mux_edp0_lcd,
+ msm_mux_edp1_hot,
+ msm_mux_edp1_lcd,
+ msm_mux_edp2_hot,
+ msm_mux_edp2_lcd,
+ msm_mux_edp3_hot,
+ msm_mux_edp3_lcd,
+ msm_mux_emac0_mcg,
+ msm_mux_emac0_mdc,
+ msm_mux_emac0_mdio,
+ msm_mux_emac0_ptp,
+ msm_mux_emac1_mcg,
+ msm_mux_emac1_mdc,
+ msm_mux_emac1_mdio,
+ msm_mux_emac1_ptp,
+ msm_mux_gcc_gp1_clk,
+ msm_mux_gcc_gp2_clk,
+ msm_mux_gcc_gp3_clk,
+ msm_mux_gcc_gp4_clk,
+ msm_mux_gcc_gp5_clk,
+ msm_mux_gcc_gp6_clk,
+ msm_mux_gcc_gp7_clk,
+ msm_mux_gcc_gp8_clk,
+ msm_mux_jitter_bist,
+ msm_mux_lbist_pass,
+ msm_mux_mbist_pass,
+ msm_mux_mdp0_vsync_out,
+ msm_mux_mdp1_vsync_out,
+ msm_mux_mdp_vsync_e,
+ msm_mux_mdp_vsync_p,
+ msm_mux_mdp_vsync_s,
+ msm_mux_pcie0_clk_req_n,
+ msm_mux_pcie1_clk_req_n,
+ msm_mux_pcie2_clk_req_n,
+ msm_mux_pcie3_clk_req_n,
+ msm_mux_phase_flag,
+ msm_mux_pll_bist_sync,
+ msm_mux_pll_clk_aux,
+ msm_mux_prng_rosc0,
+ msm_mux_prng_rosc1,
+ msm_mux_pwrbrk_i_n,
+ msm_mux_qdss,
+ msm_mux_qdss_cti,
+ msm_mux_qspi,
+ msm_mux_qup0_se0,
+ msm_mux_qup0_se1,
+ msm_mux_qup0_se2,
+ msm_mux_qup0_se3,
+ msm_mux_qup0_se4,
+ msm_mux_qup0_se5,
+ msm_mux_qup1_se0,
+ msm_mux_qup1_se1,
+ msm_mux_qup1_se2,
+ msm_mux_qup1_se3,
+ msm_mux_qup1_se4,
+ msm_mux_qup1_se5,
+ msm_mux_qup1_se6,
+ msm_mux_qup2_se0,
+ msm_mux_qup2_se1,
+ msm_mux_qup2_se2,
+ msm_mux_qup2_se3,
+ msm_mux_qup2_se4,
+ msm_mux_qup2_se5,
+ msm_mux_qup2_se6,
+ msm_mux_qup3_se0_mira,
+ msm_mux_qup3_se0_mirb,
+ msm_mux_sailss_ospi,
+ msm_mux_sdc4_clk,
+ msm_mux_sdc4_cmd,
+ msm_mux_sdc4_data,
+ msm_mux_smb_alert,
+ msm_mux_smb_alert_n,
+ msm_mux_smb_clk,
+ msm_mux_smb_dat,
+ msm_mux_tb_trig_sdc4,
+ msm_mux_tmess_prng0,
+ msm_mux_tmess_prng1,
+ msm_mux_tsc_timer,
+ msm_mux_tsense_pwm,
+ msm_mux_usb0_hs,
+ msm_mux_usb0_phy_ps,
+ msm_mux_usb1_hs,
+ msm_mux_usb1_phy_ps,
+ msm_mux_usb2_hs,
+ msm_mux_usxgmii0_phy,
+ msm_mux_usxgmii1_phy,
+ msm_mux_vsense_trigger_mirnat,
+ msm_mux_wcn_sw,
+ msm_mux_wcn_sw_ctrl,
+ msm_mux__,
+};
+
+static const char *const gpio_groups[] = {
+ "gpio0", "gpio1", "gpio2", "gpio3", "gpio4", "gpio5",
+ "gpio6", "gpio7", "gpio8", "gpio9", "gpio10", "gpio11",
+ "gpio12", "gpio13", "gpio14", "gpio15", "gpio16", "gpio17",
+ "gpio18", "gpio19", "gpio20", "gpio21", "gpio22", "gpio23",
+ "gpio24", "gpio25", "gpio26", "gpio27", "gpio28", "gpio29",
+ "gpio30", "gpio31", "gpio32", "gpio33", "gpio34", "gpio35",
+ "gpio36", "gpio37", "gpio38", "gpio39", "gpio40", "gpio41",
+ "gpio42", "gpio43", "gpio44", "gpio45", "gpio46", "gpio47",
+ "gpio48", "gpio49", "gpio50", "gpio51", "gpio52", "gpio53",
+ "gpio54", "gpio55", "gpio56", "gpio57", "gpio58", "gpio59",
+ "gpio60", "gpio61", "gpio62", "gpio63", "gpio64", "gpio65",
+ "gpio66", "gpio67", "gpio68", "gpio69", "gpio70", "gpio71",
+ "gpio72", "gpio73", "gpio74", "gpio75", "gpio76", "gpio77",
+ "gpio78", "gpio79", "gpio80", "gpio81", "gpio82", "gpio83",
+ "gpio84", "gpio85", "gpio86", "gpio87", "gpio88", "gpio89",
+ "gpio90", "gpio91", "gpio92", "gpio93", "gpio94", "gpio95",
+ "gpio96", "gpio97", "gpio98", "gpio99", "gpio100", "gpio101",
+ "gpio102", "gpio103", "gpio104", "gpio105", "gpio106", "gpio107",
+ "gpio108", "gpio109", "gpio110", "gpio111", "gpio112", "gpio113",
+ "gpio114", "gpio115", "gpio116", "gpio117", "gpio118", "gpio119",
+ "gpio120", "gpio121", "gpio122", "gpio123", "gpio124", "gpio125",
+ "gpio126", "gpio127", "gpio128", "gpio129", "gpio130", "gpio131",
+ "gpio132", "gpio133", "gpio134", "gpio135", "gpio136", "gpio137",
+ "gpio138", "gpio139", "gpio140", "gpio141", "gpio142", "gpio143",
+ "gpio144", "gpio145", "gpio146", "gpio147", "gpio148", "gpio149",
+ "gpio150", "gpio151", "gpio152", "gpio153", "gpio154", "gpio155",
+ "gpio156", "gpio157", "gpio158", "gpio159", "gpio160", "gpio161",
+ "gpio162", "gpio163", "gpio164", "gpio165", "gpio166", "gpio167",
+ "gpio168", "gpio169", "gpio170", "gpio171", "gpio172", "gpio173",
+ "gpio174", "gpio175", "gpio176", "gpio177", "gpio178", "gpio179",
+ "gpio180",
+};
+
+static const char *const aoss_cti_groups[] = {
+ "gpio83",
+ "gpio84",
+ "gpio85",
+ "gpio86",
+};
+
+static const char *const atest_char_groups[] = {
+ "gpio176", "gpio177", "gpio178", "gpio179", "gpio180",
+};
+
+static const char *const atest_usb20_groups[] = {
+ "gpio126",
+ "gpio128",
+ "gpio130",
+};
+
+static const char *const atest_usb21_groups[] = {
+ "gpio127",
+ "gpio129",
+ "gpio131",
+};
+
+static const char *const aud_intfc0_clk_groups[] = {
+ "gpio57",
+};
+
+static const char *const aud_intfc0_data_groups[] = {
+ "gpio59", "gpio60", "gpio61", "gpio62", "gpio63", "gpio64", "gpio65", "gpio66",
+};
+
+static const char *const aud_intfc0_ws_groups[] = {
+ "gpio58",
+};
+
+static const char *const aud_intfc10_clk_groups[] = {
+ "gpio61",
+};
+
+static const char *const aud_intfc10_data_groups[] = {
+ "gpio81", "gpio82",
+};
+
+static const char *const aud_intfc10_ws_groups[] = {
+ "gpio62",
+};
+
+static const char *const aud_intfc1_clk_groups[] = {
+ "gpio67",
+};
+
+static const char *const aud_intfc1_data_groups[] = {
+ "gpio69", "gpio70", "gpio71", "gpio72", "gpio73", "gpio74", "gpio75", "gpio76",
+};
+
+static const char *const aud_intfc1_ws_groups[] = {
+ "gpio68",
+};
+
+static const char *const aud_intfc2_clk_groups[] = {
+ "gpio77",
+};
+
+static const char *const aud_intfc2_data_groups[] = {
+ "gpio79", "gpio80", "gpio81", "gpio82",
+};
+
+static const char *const aud_intfc2_ws_groups[] = {
+ "gpio78",
+};
+
+static const char *const aud_intfc3_clk_groups[] = {
+ "gpio83",
+};
+
+static const char *const aud_intfc3_data_groups[] = {
+ "gpio85", "gpio86",
+};
+
+static const char *const aud_intfc3_ws_groups[] = {
+ "gpio84",
+};
+
+static const char *const aud_intfc4_clk_groups[] = {
+ "gpio87",
+};
+
+static const char *const aud_intfc4_data_groups[] = {
+ "gpio89", "gpio90",
+};
+
+static const char *const aud_intfc4_ws_groups[] = {
+ "gpio88",
+};
+
+static const char *const aud_intfc5_clk_groups[] = {
+ "gpio91",
+};
+
+static const char *const aud_intfc5_data_groups[] = {
+ "gpio93", "gpio94",
+};
+
+static const char *const aud_intfc5_ws_groups[] = {
+ "gpio92",
+};
+
+static const char *const aud_intfc6_clk_groups[] = {
+ "gpio95",
+};
+
+static const char *const aud_intfc6_data_groups[] = {
+ "gpio97", "gpio98",
+};
+
+static const char *const aud_intfc6_ws_groups[] = {
+ "gpio96",
+};
+
+static const char *const aud_intfc7_clk_groups[] = {
+ "gpio63",
+};
+
+static const char *const aud_intfc7_data_groups[] = {
+ "gpio65", "gpio66",
+};
+
+static const char *const aud_intfc7_ws_groups[] = {
+ "gpio64",
+};
+
+static const char *const aud_intfc8_clk_groups[] = {
+ "gpio73",
+};
+
+static const char *const aud_intfc8_data_groups[] = {
+ "gpio75", "gpio76",
+};
+
+static const char *const aud_intfc8_ws_groups[] = {
+ "gpio74",
+};
+
+static const char *const aud_intfc9_clk_groups[] = {
+ "gpio70",
+};
+
+static const char *const aud_intfc9_data_groups[] = {
+ "gpio72",
+};
+
+static const char *const aud_intfc9_ws_groups[] = {
+ "gpio71",
+};
+
+static const char *const aud_mclk0_mira_groups[] = {
+ "gpio99",
+};
+
+static const char *const aud_mclk0_mirb_groups[] = {
+ "gpio86",
+};
+
+static const char *const aud_mclk1_mira_groups[] = {
+ "gpio100",
+};
+
+static const char *const aud_mclk1_mirb_groups[] = {
+ "gpio90",
+};
+
+static const char *const aud_mclk2_mira_groups[] = {
+ "gpio101",
+};
+
+static const char *const aud_mclk2_mirb_groups[] = {
+ "gpio94",
+};
+
+static const char *const aud_refclk0_groups[] = {
+ "gpio100",
+};
+
+static const char *const aud_refclk1_groups[] = {
+ "gpio101",
+};
+
+static const char *const bist_done_groups[] = {
+ "gpio168",
+};
+
+static const char *const ccu_async_in_groups[] = {
+ "gpio45", "gpio176", "gpio177", "gpio178", "gpio179", "gpio180",
+};
+
+static const char *const ccu_i2c_scl_groups[] = {
+ "gpio16", "gpio18", "gpio20", "gpio22", "gpio24",
+ "gpio114", "gpio116", "gpio126", "gpio130", "gpio132",
+};
+
+static const char *const ccu_i2c_sda_groups[] = {
+ "gpio15", "gpio17", "gpio19", "gpio21", "gpio23",
+ "gpio113", "gpio115", "gpio125", "gpio129", "gpio131",
+};
+
+static const char *const ccu_timer_groups[] = {
+ "gpio25", "gpio26", "gpio27", "gpio28", "gpio29", "gpio30",
+ "gpio31", "gpio32", "gpio33", "gpio34", "gpio143", "gpio144",
+ "gpio150", "gpio151", "gpio152", "gpio153",
+};
+
+static const char *const clink_debug_groups[] = {
+ "gpio12", "gpio13", "gpio14", "gpio51",
+ "gpio52", "gpio53", "gpio54", "gpio55",
+};
+
+static const char *const dbg_out_groups[] = {
+ "gpio113",
+};
+
+static const char *const dbg_out_clk_groups[] = {
+ "gpio165",
+};
+
+static const char *const ddr_bist_complete_groups[] = {
+ "gpio37",
+};
+
+static const char *const ddr_bist_fail_groups[] = {
+ "gpio39",
+};
+
+static const char *const ddr_bist_start_groups[] = {
+ "gpio36",
+};
+
+static const char *const ddr_bist_stop_groups[] = {
+ "gpio38",
+};
+
+static const char *const ddr_pxi_groups[] = {
+ "gpio99", "gpio100", "gpio109", "gpio110", "gpio113", "gpio114",
+ "gpio115", "gpio116", "gpio117", "gpio118", "gpio119", "gpio120",
+ "gpio121", "gpio122", "gpio126", "gpio127", "gpio128", "gpio129",
+ "gpio130", "gpio131", "gpio132", "gpio133", "gpio134", "gpio135",
+ "gpio136", "gpio137", "gpio138", "gpio139", "gpio162", "gpio163",
+ "gpio164", "gpio165",
+};
+
+static const char *const dp_rx0_groups[] = {
+ "gpio55", "gpio83", "gpio84", "gpio85", "gpio86",
+ "gpio88", "gpio89", "gpio137", "gpio138",
+};
+
+static const char *const dp_rx00_groups[] = {
+ "gpio99",
+};
+
+static const char *const dp_rx01_groups[] = {
+ "gpio100",
+};
+
+static const char *const dp_rx0_mute_groups[] = {
+ "gpio35",
+};
+
+static const char *const dp_rx1_groups[] = {
+ "gpio56", "gpio92", "gpio93", "gpio95", "gpio96",
+ "gpio97", "gpio98", "gpio158", "gpio159",
+};
+
+static const char *const dp_rx10_groups[] = {
+ "gpio121",
+};
+
+static const char *const dp_rx11_groups[] = {
+ "gpio122",
+};
+
+static const char *const dp_rx1_mute_groups[] = {
+ "gpio36",
+};
+
+static const char *const edp0_hot_groups[] = {
+ "gpio51",
+};
+
+static const char *const edp0_lcd_groups[] = {
+ "gpio47",
+};
+
+static const char *const edp1_hot_groups[] = {
+ "gpio52",
+};
+
+static const char *const edp1_lcd_groups[] = {
+ "gpio48",
+};
+
+static const char *const edp2_hot_groups[] = {
+ "gpio53",
+};
+
+static const char *const edp2_lcd_groups[] = {
+ "gpio49",
+};
+
+static const char *const edp3_hot_groups[] = {
+ "gpio54",
+};
+
+static const char *const edp3_lcd_groups[] = {
+ "gpio50",
+};
+
+static const char *const emac0_mcg_groups[] = {
+ "gpio16", "gpio17", "gpio18", "gpio19",
+};
+
+static const char *const emac0_mdc_groups[] = {
+ "gpio47",
+};
+
+static const char *const emac0_mdio_groups[] = {
+ "gpio48",
+};
+
+static const char *const emac0_ptp_groups[] = {
+ "gpio133", "gpio134", "gpio135", "gpio136",
+ "gpio139", "gpio140", "gpio141", "gpio142",
+};
+
+static const char *const emac1_mcg_groups[] = {
+ "gpio20", "gpio21", "gpio22", "gpio23",
+};
+
+static const char *const emac1_mdc_groups[] = {
+ "gpio49",
+};
+
+static const char *const emac1_mdio_groups[] = {
+ "gpio50",
+};
+
+static const char *const emac1_ptp_groups[] = {
+ "gpio37", "gpio38", "gpio39", "gpio40",
+ "gpio41", "gpio42", "gpio43", "gpio44",
+};
+
+static const char *const gcc_gp1_clk_groups[] = {
+ "gpio51",
+};
+
+static const char *const gcc_gp2_clk_groups[] = {
+ "gpio52",
+};
+
+static const char *const gcc_gp3_clk_groups[] = {
+ "gpio42",
+};
+
+static const char *const gcc_gp4_clk_groups[] = {
+ "gpio43",
+};
+
+static const char *const gcc_gp5_clk_groups[] = {
+ "gpio105",
+};
+
+static const char *const gcc_gp6_clk_groups[] = {
+ "gpio106",
+};
+
+static const char *const gcc_gp7_clk_groups[] = {
+ "gpio13",
+};
+
+static const char *const gcc_gp8_clk_groups[] = {
+ "gpio14",
+};
+
+static const char *const jitter_bist_groups[] = {
+ "gpio123",
+ "gpio138",
+};
+
+static const char *const lbist_pass_groups[] = {
+ "gpio121",
+};
+
+static const char *const mbist_pass_groups[] = {
+ "gpio122",
+};
+
+static const char *const mdp0_vsync_out_groups[] = {
+ "gpio113", "gpio114", "gpio115", "gpio116", "gpio121", "gpio122",
+ "gpio139", "gpio140", "gpio141", "gpio142", "gpio143",
+};
+
+static const char *const mdp1_vsync_out_groups[] = {
+ "gpio123", "gpio124", "gpio125", "gpio126", "gpio129", "gpio130",
+ "gpio131", "gpio132", "gpio133", "gpio134", "gpio135",
+};
+
+static const char *const mdp_vsync_e_groups[] = {
+ "gpio109",
+};
+
+static const char *const mdp_vsync_p_groups[] = {
+ "gpio110",
+};
+
+static const char *const mdp_vsync_s_groups[] = {
+ "gpio144",
+};
+
+static const char *const pcie0_clk_req_n_groups[] = {
+ "gpio1",
+};
+
+static const char *const pcie1_clk_req_n_groups[] = {
+ "gpio4",
+};
+
+static const char *const pcie2_clk_req_n_groups[] = {
+ "gpio7",
+};
+
+static const char *const pcie3_clk_req_n_groups[] = {
+ "gpio10",
+};
+
+static const char *const phase_flag_groups[] = {
+ "gpio67", "gpio68", "gpio69", "gpio70", "gpio71", "gpio72", "gpio73", "gpio74",
+ "gpio75", "gpio76", "gpio77", "gpio78", "gpio79", "gpio80", "gpio81", "gpio82",
+ "gpio83", "gpio84", "gpio85", "gpio86", "gpio87", "gpio88", "gpio89", "gpio90",
+ "gpio91", "gpio92", "gpio93", "gpio94", "gpio95", "gpio96", "gpio98", "gpio101",
+};
+
+static const char *const pll_bist_sync_groups[] = {
+ "gpio176",
+};
+
+static const char *const pll_clk_aux_groups[] = {
+ "gpio100",
+};
+
+static const char *const prng_rosc0_groups[] = {
+ "gpio117",
+};
+
+static const char *const prng_rosc1_groups[] = {
+ "gpio118",
+};
+
+static const char *const pwrbrk_i_n_groups[] = {
+ "gpio167",
+};
+
+static const char *const qdss_cti_groups[] = {
+ "gpio41", "gpio42", "gpio110", "gpio138",
+ "gpio142", "gpio144", "gpio162", "gpio163",
+};
+
+static const char *const qdss_groups[] = {
+ "gpio67", "gpio68", "gpio69", "gpio70", "gpio71", "gpio72", "gpio73", "gpio74",
+ "gpio75", "gpio76", "gpio77", "gpio78", "gpio79", "gpio80", "gpio81", "gpio82",
+ "gpio83", "gpio84", "gpio85", "gpio86", "gpio87", "gpio88", "gpio89", "gpio90",
+ "gpio91", "gpio92", "gpio93", "gpio94", "gpio95", "gpio96", "gpio97", "gpio98",
+ "gpio99", "gpio100", "gpio101", "gpio108",
+};
+
+static const char *const qspi_groups[] = {
+ "gpio102", "gpio103", "gpio104", "gpio105", "gpio106", "gpio107", "gpio108",
+};
+
+static const char *const qup0_se0_groups[] = {
+ "gpio109", "gpio110", "gpio111", "gpio112",
+};
+
+static const char *const qup0_se1_groups[] = {
+ "gpio109", "gpio110", "gpio111", "gpio112",
+};
+
+static const char *const qup0_se2_groups[] = {
+ "gpio113", "gpio114", "gpio115", "gpio116",
+};
+
+static const char *const qup0_se3_groups[] = {
+ "gpio113", "gpio114", "gpio115", "gpio116",
+};
+
+static const char *const qup0_se4_groups[] = {
+ "gpio117", "gpio118", "gpio119", "gpio120",
+};
+
+static const char *const qup0_se5_groups[] = {
+ "gpio109", "gpio110", "gpio121", "gpio122",
+};
+
+static const char *const qup1_se0_groups[] = {
+ "gpio123", "gpio124", "gpio125", "gpio126",
+};
+
+static const char *const qup1_se1_groups[] = {
+ "gpio123", "gpio124", "gpio125", "gpio126",
+};
+
+static const char *const qup1_se2_groups[] = {
+ "gpio127", "gpio128", "gpio129", "gpio130",
+};
+
+static const char *const qup1_se3_groups[] = {
+ "gpio129", "gpio130",
+};
+
+static const char *const qup1_se4_groups[] = {
+ "gpio131", "gpio132", "gpio137", "gpio138",
+};
+
+static const char *const qup1_se5_groups[] = {
+ "gpio133", "gpio134", "gpio135", "gpio136",
+};
+
+static const char *const qup1_se6_groups[] = {
+ "gpio131", "gpio132", "gpio137", "gpio138",
+};
+
+static const char *const qup2_se0_groups[] = {
+ "gpio139", "gpio140", "gpio141", "gpio142",
+};
+
+static const char *const qup2_se1_groups[] = {
+ "gpio143", "gpio144", "gpio154", "gpio155",
+};
+
+static const char *const qup2_se2_groups[] = {
+ "gpio145", "gpio146", "gpio147", "gpio148", "gpio149",
+};
+
+static const char *const qup2_se3_groups[] = {
+ "gpio150", "gpio151", "gpio152", "gpio153",
+};
+
+static const char *const qup2_se4_groups[] = {
+ "gpio143", "gpio144", "gpio150", "gpio151",
+ "gpio152", "gpio154", "gpio155",
+};
+
+static const char *const qup2_se5_groups[] = {
+ "gpio156", "gpio157", "gpio158", "gpio159",
+};
+
+static const char *const qup2_se6_groups[] = {
+ "gpio156", "gpio157", "gpio158", "gpio159",
+};
+
+static const char *const qup3_se0_mira_groups[] = {
+ "gpio102", "gpio103", "gpio104", "gpio105",
+ "gpio106", "gpio107", "gpio108",
+};
+
+static const char *const qup3_se0_mirb_groups[] = {
+ "gpio102", "gpio103",
+};
+
+static const char *const sailss_ospi_groups[] = {
+ "gpio164",
+ "gpio165",
+};
+
+static const char *const sdc4_clk_groups[] = {
+ "gpio175",
+};
+
+static const char *const sdc4_cmd_groups[] = {
+ "gpio174",
+};
+
+static const char *const sdc4_data_groups[] = {
+ "gpio170",
+ "gpio171",
+ "gpio172",
+ "gpio173",
+};
+
+static const char *const smb_alert_groups[] = {
+ "gpio110",
+};
+
+static const char *const smb_alert_n_groups[] = {
+ "gpio109",
+};
+
+static const char *const smb_clk_groups[] = {
+ "gpio112",
+};
+
+static const char *const smb_dat_groups[] = {
+ "gpio111",
+};
+
+static const char *const tb_trig_sdc4_groups[] = {
+ "gpio169",
+};
+
+static const char *const tmess_prng0_groups[] = {
+ "gpio94",
+};
+
+static const char *const tmess_prng1_groups[] = {
+ "gpio95",
+};
+
+static const char *const tsc_timer_groups[] = {
+ "gpio25", "gpio26", "gpio27", "gpio28", "gpio29",
+ "gpio30", "gpio31", "gpio32", "gpio33", "gpio34",
+};
+
+static const char *const tsense_pwm_groups[] = {
+ "gpio43", "gpio44", "gpio45", "gpio46", "gpio47", "gpio48", "gpio49", "gpio50",
+};
+
+static const char *const usb0_hs_groups[] = {
+ "gpio12",
+};
+
+static const char *const usb0_phy_ps_groups[] = {
+ "gpio164",
+};
+
+static const char *const usb1_hs_groups[] = {
+ "gpio13",
+};
+
+static const char *const usb1_phy_ps_groups[] = {
+ "gpio165",
+};
+
+static const char *const usb2_hs_groups[] = {
+ "gpio14",
+};
+
+static const char *const usxgmii0_phy_groups[] = {
+ "gpio45",
+};
+
+static const char *const usxgmii1_phy_groups[] = {
+ "gpio46",
+};
+
+static const char *const vsense_trigger_mirnat_groups[] = {
+ "gpio132",
+};
+
+static const char *const wcn_sw_groups[] = {
+ "gpio161",
+};
+
+static const char *const wcn_sw_ctrl_groups[] = {
+ "gpio160",
+};
+
+static const struct pinfunction nord_functions[] = {
+ MSM_GPIO_PIN_FUNCTION(gpio),
+ MSM_PIN_FUNCTION(aoss_cti),
+ MSM_PIN_FUNCTION(atest_char),
+ MSM_PIN_FUNCTION(atest_usb20),
+ MSM_PIN_FUNCTION(atest_usb21),
+ MSM_PIN_FUNCTION(aud_intfc0_clk),
+ MSM_PIN_FUNCTION(aud_intfc0_data),
+ MSM_PIN_FUNCTION(aud_intfc0_ws),
+ MSM_PIN_FUNCTION(aud_intfc10_clk),
+ MSM_PIN_FUNCTION(aud_intfc10_data),
+ MSM_PIN_FUNCTION(aud_intfc10_ws),
+ MSM_PIN_FUNCTION(aud_intfc1_clk),
+ MSM_PIN_FUNCTION(aud_intfc1_data),
+ MSM_PIN_FUNCTION(aud_intfc1_ws),
+ MSM_PIN_FUNCTION(aud_intfc2_clk),
+ MSM_PIN_FUNCTION(aud_intfc2_data),
+ MSM_PIN_FUNCTION(aud_intfc2_ws),
+ MSM_PIN_FUNCTION(aud_intfc3_clk),
+ MSM_PIN_FUNCTION(aud_intfc3_data),
+ MSM_PIN_FUNCTION(aud_intfc3_ws),
+ MSM_PIN_FUNCTION(aud_intfc4_clk),
+ MSM_PIN_FUNCTION(aud_intfc4_data),
+ MSM_PIN_FUNCTION(aud_intfc4_ws),
+ MSM_PIN_FUNCTION(aud_intfc5_clk),
+ MSM_PIN_FUNCTION(aud_intfc5_data),
+ MSM_PIN_FUNCTION(aud_intfc5_ws),
+ MSM_PIN_FUNCTION(aud_intfc6_clk),
+ MSM_PIN_FUNCTION(aud_intfc6_data),
+ MSM_PIN_FUNCTION(aud_intfc6_ws),
+ MSM_PIN_FUNCTION(aud_intfc7_clk),
+ MSM_PIN_FUNCTION(aud_intfc7_data),
+ MSM_PIN_FUNCTION(aud_intfc7_ws),
+ MSM_PIN_FUNCTION(aud_intfc8_clk),
+ MSM_PIN_FUNCTION(aud_intfc8_data),
+ MSM_PIN_FUNCTION(aud_intfc8_ws),
+ MSM_PIN_FUNCTION(aud_intfc9_clk),
+ MSM_PIN_FUNCTION(aud_intfc9_data),
+ MSM_PIN_FUNCTION(aud_intfc9_ws),
+ MSM_PIN_FUNCTION(aud_mclk0_mira),
+ MSM_PIN_FUNCTION(aud_mclk0_mirb),
+ MSM_PIN_FUNCTION(aud_mclk1_mira),
+ MSM_PIN_FUNCTION(aud_mclk1_mirb),
+ MSM_PIN_FUNCTION(aud_mclk2_mira),
+ MSM_PIN_FUNCTION(aud_mclk2_mirb),
+ MSM_PIN_FUNCTION(aud_refclk0),
+ MSM_PIN_FUNCTION(aud_refclk1),
+ MSM_PIN_FUNCTION(bist_done),
+ MSM_PIN_FUNCTION(ccu_async_in),
+ MSM_PIN_FUNCTION(ccu_i2c_scl),
+ MSM_PIN_FUNCTION(ccu_i2c_sda),
+ MSM_PIN_FUNCTION(ccu_timer),
+ MSM_PIN_FUNCTION(clink_debug),
+ MSM_PIN_FUNCTION(dbg_out),
+ MSM_PIN_FUNCTION(dbg_out_clk),
+ MSM_PIN_FUNCTION(ddr_bist_complete),
+ MSM_PIN_FUNCTION(ddr_bist_fail),
+ MSM_PIN_FUNCTION(ddr_bist_start),
+ MSM_PIN_FUNCTION(ddr_bist_stop),
+ MSM_PIN_FUNCTION(ddr_pxi),
+ MSM_PIN_FUNCTION(dp_rx0),
+ MSM_PIN_FUNCTION(dp_rx00),
+ MSM_PIN_FUNCTION(dp_rx01),
+ MSM_PIN_FUNCTION(dp_rx0_mute),
+ MSM_PIN_FUNCTION(dp_rx1),
+ MSM_PIN_FUNCTION(dp_rx10),
+ MSM_PIN_FUNCTION(dp_rx11),
+ MSM_PIN_FUNCTION(dp_rx1_mute),
+ MSM_PIN_FUNCTION(edp0_hot),
+ MSM_PIN_FUNCTION(edp0_lcd),
+ MSM_PIN_FUNCTION(edp1_hot),
+ MSM_PIN_FUNCTION(edp1_lcd),
+ MSM_PIN_FUNCTION(edp2_hot),
+ MSM_PIN_FUNCTION(edp2_lcd),
+ MSM_PIN_FUNCTION(edp3_hot),
+ MSM_PIN_FUNCTION(edp3_lcd),
+ MSM_PIN_FUNCTION(emac0_mcg),
+ MSM_PIN_FUNCTION(emac0_mdc),
+ MSM_PIN_FUNCTION(emac0_mdio),
+ MSM_PIN_FUNCTION(emac0_ptp),
+ MSM_PIN_FUNCTION(emac1_mcg),
+ MSM_PIN_FUNCTION(emac1_mdc),
+ MSM_PIN_FUNCTION(emac1_mdio),
+ MSM_PIN_FUNCTION(emac1_ptp),
+ MSM_PIN_FUNCTION(gcc_gp1_clk),
+ MSM_PIN_FUNCTION(gcc_gp2_clk),
+ MSM_PIN_FUNCTION(gcc_gp3_clk),
+ MSM_PIN_FUNCTION(gcc_gp4_clk),
+ MSM_PIN_FUNCTION(gcc_gp5_clk),
+ MSM_PIN_FUNCTION(gcc_gp6_clk),
+ MSM_PIN_FUNCTION(gcc_gp7_clk),
+ MSM_PIN_FUNCTION(gcc_gp8_clk),
+ MSM_PIN_FUNCTION(jitter_bist),
+ MSM_PIN_FUNCTION(lbist_pass),
+ MSM_PIN_FUNCTION(mbist_pass),
+ MSM_PIN_FUNCTION(mdp0_vsync_out),
+ MSM_PIN_FUNCTION(mdp1_vsync_out),
+ MSM_PIN_FUNCTION(mdp_vsync_e),
+ MSM_PIN_FUNCTION(mdp_vsync_p),
+ MSM_PIN_FUNCTION(mdp_vsync_s),
+ MSM_PIN_FUNCTION(pcie0_clk_req_n),
+ MSM_PIN_FUNCTION(pcie1_clk_req_n),
+ MSM_PIN_FUNCTION(pcie2_clk_req_n),
+ MSM_PIN_FUNCTION(pcie3_clk_req_n),
+ MSM_PIN_FUNCTION(phase_flag),
+ MSM_PIN_FUNCTION(pll_bist_sync),
+ MSM_PIN_FUNCTION(pll_clk_aux),
+ MSM_PIN_FUNCTION(prng_rosc0),
+ MSM_PIN_FUNCTION(prng_rosc1),
+ MSM_PIN_FUNCTION(pwrbrk_i_n),
+ MSM_PIN_FUNCTION(qdss_cti),
+ MSM_PIN_FUNCTION(qdss),
+ MSM_PIN_FUNCTION(qdss_cti),
+ MSM_PIN_FUNCTION(qspi),
+ MSM_PIN_FUNCTION(qup0_se0),
+ MSM_PIN_FUNCTION(qup0_se1),
+ MSM_PIN_FUNCTION(qup0_se2),
+ MSM_PIN_FUNCTION(qup0_se3),
+ MSM_PIN_FUNCTION(qup0_se4),
+ MSM_PIN_FUNCTION(qup0_se5),
+ MSM_PIN_FUNCTION(qup1_se0),
+ MSM_PIN_FUNCTION(qup1_se1),
+ MSM_PIN_FUNCTION(qup1_se2),
+ MSM_PIN_FUNCTION(qup1_se3),
+ MSM_PIN_FUNCTION(qup1_se4),
+ MSM_PIN_FUNCTION(qup1_se5),
+ MSM_PIN_FUNCTION(qup1_se6),
+ MSM_PIN_FUNCTION(qup2_se0),
+ MSM_PIN_FUNCTION(qup2_se1),
+ MSM_PIN_FUNCTION(qup2_se2),
+ MSM_PIN_FUNCTION(qup2_se3),
+ MSM_PIN_FUNCTION(qup2_se4),
+ MSM_PIN_FUNCTION(qup2_se5),
+ MSM_PIN_FUNCTION(qup2_se6),
+ MSM_PIN_FUNCTION(qup3_se0_mira),
+ MSM_PIN_FUNCTION(qup3_se0_mirb),
+ MSM_PIN_FUNCTION(sailss_ospi),
+ MSM_PIN_FUNCTION(sdc4_clk),
+ MSM_PIN_FUNCTION(sdc4_cmd),
+ MSM_PIN_FUNCTION(sdc4_data),
+ MSM_PIN_FUNCTION(smb_alert),
+ MSM_PIN_FUNCTION(smb_alert_n),
+ MSM_PIN_FUNCTION(smb_clk),
+ MSM_PIN_FUNCTION(smb_dat),
+ MSM_PIN_FUNCTION(tb_trig_sdc4),
+ MSM_PIN_FUNCTION(tmess_prng0),
+ MSM_PIN_FUNCTION(tmess_prng1),
+ MSM_PIN_FUNCTION(tsc_timer),
+ MSM_PIN_FUNCTION(tsense_pwm),
+ MSM_PIN_FUNCTION(usb0_hs),
+ MSM_PIN_FUNCTION(usb0_phy_ps),
+ MSM_PIN_FUNCTION(usb1_hs),
+ MSM_PIN_FUNCTION(usb1_phy_ps),
+ MSM_PIN_FUNCTION(usb2_hs),
+ MSM_PIN_FUNCTION(usxgmii0_phy),
+ MSM_PIN_FUNCTION(usxgmii1_phy),
+ MSM_PIN_FUNCTION(vsense_trigger_mirnat),
+ MSM_PIN_FUNCTION(wcn_sw),
+ MSM_PIN_FUNCTION(wcn_sw_ctrl),
+};
+
+/* Every pin is maintained as a single group, and missing or non-existing pin
+ * would be maintained as dummy group to synchronize pin group index with
+ * pin descriptor registered with pinctrl core.
+ * Clients would not be able to request these dummy pin groups.
+ */
+static const struct msm_pingroup nord_groups[] = {
+ [0] = PINGROUP(0, _, _, _, _, _, _, _, _, _, _, _),
+ [1] = PINGROUP(1, pcie0_clk_req_n, _, _, _, _, _, _, _, _, _, _),
+ [2] = PINGROUP(2, _, _, _, _, _, _, _, _, _, _, _),
+ [3] = PINGROUP(3, _, _, _, _, _, _, _, _, _, _, _),
+ [4] = PINGROUP(4, pcie1_clk_req_n, _, _, _, _, _, _, _, _, _, _),
+ [5] = PINGROUP(5, _, _, _, _, _, _, _, _, _, _, _),
+ [6] = PINGROUP(6, _, _, _, _, _, _, _, _, _, _, _),
+ [7] = PINGROUP(7, pcie2_clk_req_n, _, _, _, _, _, _, _, _, _, _),
+ [8] = PINGROUP(8, _, _, _, _, _, _, _, _, _, _, _),
+ [9] = PINGROUP(9, _, _, _, _, _, _, _, _, _, _, _),
+ [10] = PINGROUP(10, pcie3_clk_req_n, _, _, _, _, _, _, _, _, _, _),
+ [11] = PINGROUP(11, _, _, _, _, _, _, _, _, _, _, _),
+ [12] = PINGROUP(12, usb0_hs, clink_debug, _, _, _, _, _, _, _, _, _),
+ [13] = PINGROUP(13, usb1_hs, clink_debug, gcc_gp7_clk, _, _, _, _, _, _, _, _),
+ [14] = PINGROUP(14, usb2_hs, clink_debug, gcc_gp8_clk, _, _, _, _, _, _, _, _),
+ [15] = PINGROUP(15, ccu_i2c_sda, _, _, _, _, _, _, _, _, _, _),
+ [16] = PINGROUP(16, ccu_i2c_scl, emac0_mcg, _, _, _, _, _, _, _, _, _),
+ [17] = PINGROUP(17, ccu_i2c_sda, emac0_mcg, _, _, _, _, _, _, _, _, _),
+ [18] = PINGROUP(18, ccu_i2c_scl, emac0_mcg, _, _, _, _, _, _, _, _, _),
+ [19] = PINGROUP(19, ccu_i2c_sda, emac0_mcg, _, _, _, _, _, _, _, _, _),
+ [20] = PINGROUP(20, ccu_i2c_scl, emac1_mcg, _, _, _, _, _, _, _, _, _),
+ [21] = PINGROUP(21, ccu_i2c_sda, emac1_mcg, _, _, _, _, _, _, _, _, _),
+ [22] = PINGROUP(22, ccu_i2c_scl, emac1_mcg, _, _, _, _, _, _, _, _, _),
+ [23] = PINGROUP(23, ccu_i2c_sda, emac1_mcg, _, _, _, _, _, _, _, _, _),
+ [24] = PINGROUP(24, ccu_i2c_scl, _, _, _, _, _, _, _, _, _, _),
+ [25] = PINGROUP(25, ccu_timer, tsc_timer, _, _, _, _, _, _, _, _, _),
+ [26] = PINGROUP(26, ccu_timer, tsc_timer, _, _, _, _, _, _, _, _, _),
+ [27] = PINGROUP(27, ccu_timer, tsc_timer, _, _, _, _, _, _, _, _, _),
+ [28] = PINGROUP(28, ccu_timer, tsc_timer, _, _, _, _, _, _, _, _, _),
+ [29] = PINGROUP(29, ccu_timer, tsc_timer, _, _, _, _, _, _, _, _, _),
+ [30] = PINGROUP(30, ccu_timer, tsc_timer, _, _, _, _, _, _, _, _, _),
+ [31] = PINGROUP(31, ccu_timer, tsc_timer, _, _, _, _, _, _, _, _, _),
+ [32] = PINGROUP(32, ccu_timer, tsc_timer, _, _, _, _, _, _, _, _, _),
+ [33] = PINGROUP(33, ccu_timer, tsc_timer, _, _, _, _, _, _, _, _, _),
+ [34] = PINGROUP(34, ccu_timer, tsc_timer, _, _, _, _, _, _, _, _, _),
+ [35] = PINGROUP(35, dp_rx0_mute, _, _, _, _, _, _, _, _, _, _),
+ [36] = PINGROUP(36, dp_rx1_mute, ddr_bist_start, _, _, _, _, _, _, _, _, _),
+ [37] = PINGROUP(37, emac1_ptp, ddr_bist_complete, _, _, _, _, _, _, _, _, _),
+ [38] = PINGROUP(38, emac1_ptp, ddr_bist_stop, _, _, _, _, _, _, _, _, _),
+ [39] = PINGROUP(39, emac1_ptp, ddr_bist_fail, _, _, _, _, _, _, _, _, _),
+ [40] = PINGROUP(40, emac1_ptp, _, _, _, _, _, _, _, _, _, _),
+ [41] = PINGROUP(41, emac1_ptp, qdss_cti, _, _, _, _, _, _, _, _, _),
+ [42] = PINGROUP(42, emac1_ptp, qdss_cti, gcc_gp3_clk, _, _, _, _, _, _, _, _),
+ [43] = PINGROUP(43, emac1_ptp, gcc_gp4_clk, tsense_pwm, _, _, _, _, _, _, _, _),
+ [44] = PINGROUP(44, emac1_ptp, tsense_pwm, _, _, _, _, _, _, _, _, _),
+ [45] = PINGROUP(45, usxgmii0_phy, ccu_async_in, tsense_pwm, _, _, _, _, _, _, _, _),
+ [46] = PINGROUP(46, usxgmii1_phy, tsense_pwm, _, _, _, _, _, _, _, _, _),
+ [47] = PINGROUP(47, emac0_mdc, edp0_lcd, tsense_pwm, _, _, _, _, _, _, _, _),
+ [48] = PINGROUP(48, emac0_mdio, edp1_lcd, tsense_pwm, _, _, _, _, _, _, _, _),
+ [49] = PINGROUP(49, emac1_mdc, edp2_lcd, tsense_pwm, _, _, _, _, _, _, _, _),
+ [50] = PINGROUP(50, emac1_mdio, edp3_lcd, tsense_pwm, _, _, _, _, _, _, _, _),
+ [51] = PINGROUP(51, edp0_hot, clink_debug, gcc_gp1_clk, _, _, _, _, _, _, _, _),
+ [52] = PINGROUP(52, edp1_hot, clink_debug, gcc_gp2_clk, _, _, _, _, _, _, _, _),
+ [53] = PINGROUP(53, edp2_hot, clink_debug, _, _, _, _, _, _, _, _, _),
+ [54] = PINGROUP(54, edp3_hot, clink_debug, _, _, _, _, _, _, _, _, _),
+ [55] = PINGROUP(55, dp_rx0, clink_debug, _, _, _, _, _, _, _, _, _),
+ [56] = PINGROUP(56, dp_rx1, _, _, _, _, _, _, _, _, _, _),
+ [57] = PINGROUP(57, aud_intfc0_clk, _, _, _, _, _, _, _, _, _, _),
+ [58] = PINGROUP(58, aud_intfc0_ws, _, _, _, _, _, _, _, _, _, _),
+ [59] = PINGROUP(59, aud_intfc0_data, _, _, _, _, _, _, _, _, _, _),
+ [60] = PINGROUP(60, aud_intfc0_data, _, _, _, _, _, _, _, _, _, _),
+ [61] = PINGROUP(61, aud_intfc0_data, aud_intfc10_clk, _, _, _, _, _, _, _, _, _),
+ [62] = PINGROUP(62, aud_intfc0_data, aud_intfc10_ws, _, _, _, _, _, _, _, _, _),
+ [63] = PINGROUP(63, aud_intfc0_data, aud_intfc7_clk, _, _, _, _, _, _, _, _, _),
+ [64] = PINGROUP(64, aud_intfc0_data, aud_intfc7_ws, _, _, _, _, _, _, _, _, _),
+ [65] = PINGROUP(65, aud_intfc0_data, aud_intfc7_data, _, _, _, _, _, _, _, _, _),
+ [66] = PINGROUP(66, aud_intfc0_data, aud_intfc7_data, _, _, _, _, _, _, _, _, _),
+ [67] = PINGROUP(67, aud_intfc1_clk, phase_flag, _, qdss, _, _, _, _, _, _, _),
+ [68] = PINGROUP(68, aud_intfc1_ws, phase_flag, _, qdss, _, _, _, _, _, _, _),
+ [69] = PINGROUP(69, aud_intfc1_data, phase_flag, _, qdss, _, _, _, _, _, _, _),
+ [70] = PINGROUP(70, aud_intfc1_data, aud_intfc9_clk, phase_flag,
+ _, qdss, _, _, _, _, _, _),
+ [71] = PINGROUP(71, aud_intfc1_data, aud_intfc9_ws, phase_flag,
+ _, qdss, _, _, _, _, _, _),
+ [72] = PINGROUP(72, aud_intfc1_data, aud_intfc9_data, phase_flag,
+ _, qdss, _, _, _, _, _, _),
+ [73] = PINGROUP(73, aud_intfc1_data, aud_intfc8_clk, phase_flag,
+ _, qdss, _, _, _, _, _, _),
+ [74] = PINGROUP(74, aud_intfc1_data, aud_intfc8_ws, phase_flag,
+ _, qdss, _, _, _, _, _, _),
+ [75] = PINGROUP(75, aud_intfc1_data, aud_intfc8_data, phase_flag,
+ _, qdss, _, _, _, _, _, _),
+ [76] = PINGROUP(76, aud_intfc1_data, aud_intfc8_data, phase_flag,
+ _, qdss, _, _, _, _, _, _),
+ [77] = PINGROUP(77, aud_intfc2_clk, phase_flag, _, qdss, _, _, _, _, _, _, _),
+ [78] = PINGROUP(78, aud_intfc2_ws, phase_flag, _, qdss, _, _, _, _, _, _, _),
+ [79] = PINGROUP(79, aud_intfc2_data, phase_flag, _, qdss, _, _, _, _, _, _, _),
+ [80] = PINGROUP(80, aud_intfc2_data, phase_flag, _, _, qdss, _, _, _, _, _, _),
+ [81] = PINGROUP(81, aud_intfc2_data, aud_intfc10_data, phase_flag,
+ _, _, qdss, _, _, _, _, _),
+ [82] = PINGROUP(82, aud_intfc2_data, aud_intfc10_data, phase_flag,
+ _, qdss, _, _, _, _, _, _),
+ [83] = PINGROUP(83, aud_intfc3_clk, dp_rx0, aoss_cti, phase_flag, _, qdss,
+ _, _, _, _, _),
+ [84] = PINGROUP(84, aud_intfc3_ws, dp_rx0, aoss_cti, phase_flag, _, qdss,
+ _, _, _, _, _),
+ [85] = PINGROUP(85, aud_intfc3_data, dp_rx0, aoss_cti, phase_flag,
+ _, qdss, _, _, _, _, _),
+ [86] = PINGROUP(86, aud_intfc3_data, aud_mclk0_mirb, dp_rx0, aoss_cti, phase_flag,
+ _, qdss, _, _, _, _),
+ [87] = PINGROUP(87, aud_intfc4_clk, phase_flag, _, qdss, _, _, _, _, _, _, _),
+ [88] = PINGROUP(88, aud_intfc4_ws, dp_rx0, phase_flag, _, qdss, _, _, _, _, _, _),
+ [89] = PINGROUP(89, aud_intfc4_data, dp_rx0, phase_flag, _, qdss,
+ _, _, _, _, _, _),
+ [90] = PINGROUP(90, aud_intfc4_data, aud_mclk1_mirb, phase_flag,
+ _, qdss, _, _, _, _, _, _),
+ [91] = PINGROUP(91, aud_intfc5_clk, phase_flag, _, qdss, _, _, _, _, _, _, _),
+ [92] = PINGROUP(92, aud_intfc5_ws, dp_rx1, phase_flag, _, qdss, _, _, _, _, _, _),
+ [93] = PINGROUP(93, aud_intfc5_data, dp_rx1, phase_flag, _, qdss,
+ _, _, _, _, _, _),
+ [94] = PINGROUP(94, aud_intfc5_data, aud_mclk2_mirb, phase_flag, tmess_prng0,
+ _, qdss, _, _, _, _, _),
+ [95] = PINGROUP(95, aud_intfc6_clk, dp_rx1, phase_flag, tmess_prng1,
+ _, qdss, _, _, _, _, _),
+ [96] = PINGROUP(96, aud_intfc6_ws, dp_rx1, phase_flag, _, qdss,
+ _, _, _, _, _, _),
+ [97] = PINGROUP(97, aud_intfc6_data, dp_rx1, qdss, _, _, _, _, _, _, _, _),
+ [98] = PINGROUP(98, aud_intfc6_data, dp_rx1, phase_flag, _, qdss,
+ _, _, _, _, _, _),
+ [99] = PINGROUP(99, aud_mclk0_mira, qdss, dp_rx00, ddr_pxi, _, _, _, _, _, _, _),
+ [100] = PINGROUP(100, aud_mclk1_mira, aud_refclk0, pll_clk_aux,
+ qdss, dp_rx01, ddr_pxi, _, _, _, _, _),
+ [101] = PINGROUP(101, aud_mclk2_mira, aud_refclk1, phase_flag, _, qdss,
+ _, _, _, _, _, _),
+ [102] = PINGROUP(102, qspi, qup3_se0_mira, qup3_se0_mirb, _, _, _, _, _, _, _, _),
+ [103] = PINGROUP(103, qspi, qup3_se0_mira, qup3_se0_mirb, _, _, _, _, _, _, _, _),
+ [104] = PINGROUP(104, qspi, qup3_se0_mira, _, _, _, _, _, _, _, _, _),
+ [105] = PINGROUP(105, qspi, qup3_se0_mira, gcc_gp5_clk, _, _, _, _, _, _, _, _),
+ [106] = PINGROUP(106, qspi, qup3_se0_mira, gcc_gp6_clk, _, _, _, _, _, _, _, _),
+ [107] = PINGROUP(107, qspi, qup3_se0_mira, _, _, _, _, _, _, _, _, _),
+ [108] = PINGROUP(108, qspi, qup3_se0_mira, qdss, _, _, _, _, _, _, _, _),
+ [109] = PINGROUP(109, qup0_se0, qup0_se1, qup0_se5, mdp_vsync_e,
+ smb_alert_n, _, ddr_pxi, _, _, _, _),
+ [110] = PINGROUP(110, qup0_se0, qup0_se1, qup0_se5, qdss_cti,
+ mdp_vsync_p, smb_alert, _, ddr_pxi, _, _, _),
+ [111] = PINGROUP(111, qup0_se1, qup0_se0, smb_dat, _, _, _, _, _, _, _, _),
+ [112] = PINGROUP(112, qup0_se1, qup0_se0, smb_clk, _, _, _, _, _, _, _, _),
+ [113] = PINGROUP(113, qup0_se2, qup0_se3, ccu_i2c_sda, mdp0_vsync_out,
+ dbg_out, ddr_pxi, _, _, _, _, _),
+ [114] = PINGROUP(114, qup0_se2, qup0_se3, ccu_i2c_scl, mdp0_vsync_out,
+ _, ddr_pxi, _, _, _, _, _),
+ [115] = PINGROUP(115, qup0_se3, qup0_se2, ccu_i2c_sda, mdp0_vsync_out,
+ _, ddr_pxi, _, _, _, _, _),
+ [116] = PINGROUP(116, qup0_se3, qup0_se2, ccu_i2c_scl, mdp0_vsync_out,
+ _, ddr_pxi, _, _, _, _, _),
+ [117] = PINGROUP(117, qup0_se4, prng_rosc0, _, ddr_pxi, _, _, _, _, _, _, _),
+ [118] = PINGROUP(118, qup0_se4, prng_rosc1, _, ddr_pxi, _, _, _, _, _, _, _),
+ [119] = PINGROUP(119, qup0_se4, _, ddr_pxi, _, _, _, _, _, _, _, _),
+ [120] = PINGROUP(120, qup0_se4, _, ddr_pxi, _, _, _, _, _, _, _, _),
+ [121] = PINGROUP(121, qup0_se5, lbist_pass, mdp0_vsync_out, _, dp_rx10, ddr_pxi,
+ _, _, _, _, _),
+ [122] = PINGROUP(122, qup0_se5, mbist_pass, mdp0_vsync_out, _, dp_rx11, ddr_pxi,
+ _, _, _, _, _),
+ [123] = PINGROUP(123, qup1_se0, qup1_se1, mdp1_vsync_out, jitter_bist,
+ _, _, _, _, _, _, _),
+ [124] = PINGROUP(124, qup1_se0, qup1_se1, mdp1_vsync_out, _, _, _, _, _, _, _, _),
+ [125] = PINGROUP(125, qup1_se1, qup1_se0, ccu_i2c_sda, mdp1_vsync_out,
+ _, _, _, _, _, _, _),
+ [126] = PINGROUP(126, qup1_se1, qup1_se0, ccu_i2c_scl, mdp1_vsync_out,
+ _, atest_usb20, ddr_pxi, _, _, _, _),
+ [127] = PINGROUP(127, qup1_se2, qup1_se2, _, atest_usb21, ddr_pxi,
+ _, _, _, _, _, _),
+ [128] = PINGROUP(128, qup1_se2, qup1_se2, _, atest_usb20, ddr_pxi,
+ _, _, _, _, _, _),
+ [129] = PINGROUP(129, qup1_se3, qup1_se3, ccu_i2c_sda, mdp1_vsync_out,
+ _, atest_usb21, ddr_pxi, _, _, _, _),
+ [130] = PINGROUP(130, qup1_se3, qup1_se3, ccu_i2c_scl, mdp1_vsync_out,
+ _, atest_usb20, ddr_pxi, _, _, _, _),
+ [131] = PINGROUP(131, qup1_se4, qup1_se6, ccu_i2c_sda, mdp1_vsync_out,
+ _, atest_usb21, ddr_pxi, _, _, _, _),
+ [132] = PINGROUP(132, qup1_se4, qup1_se6, ccu_i2c_scl, mdp1_vsync_out,
+ _, vsense_trigger_mirnat, ddr_pxi, _, _, _, _),
+ [133] = PINGROUP(133, qup1_se5, emac0_ptp, mdp1_vsync_out, _, ddr_pxi,
+ _, _, _, _, _, _),
+ [134] = PINGROUP(134, qup1_se5, emac0_ptp, mdp1_vsync_out, _, ddr_pxi,
+ _, _, _, _, _, _),
+ [135] = PINGROUP(135, qup1_se5, emac0_ptp, mdp1_vsync_out, _, ddr_pxi,
+ _, _, _, _, _, _),
+ [136] = PINGROUP(136, qup1_se5, emac0_ptp, _, ddr_pxi, _, _, _, _, _, _, _),
+ [137] = PINGROUP(137, qup1_se6, qup1_se4, dp_rx0, _, ddr_pxi, _, _, _, _, _, _),
+ [138] = PINGROUP(138, qup1_se6, qup1_se4, dp_rx0, qdss_cti, jitter_bist, ddr_pxi,
+ _, _, _, _, _),
+ [139] = PINGROUP(139, qup2_se0, emac0_ptp, mdp0_vsync_out, ddr_pxi,
+ _, _, _, _, _, _, _),
+ [140] = PINGROUP(140, qup2_se0, emac0_ptp, mdp0_vsync_out, _, _, _, _, _, _, _, _),
+ [141] = PINGROUP(141, qup2_se0, emac0_ptp, mdp0_vsync_out, _, _, _, _, _, _, _, _),
+ [142] = PINGROUP(142, qup2_se0, emac0_ptp, qdss_cti, mdp0_vsync_out, _, _, _, _, _, _, _),
+ [143] = PINGROUP(143, qup2_se1, qup2_se4, ccu_timer, mdp0_vsync_out,
+ _, _, _, _, _, _, _),
+ [144] = PINGROUP(144, qup2_se1, qup2_se4, ccu_timer, qdss_cti, mdp_vsync_s,
+ _, _, _, _, _, _),
+ [145] = PINGROUP(145, qup2_se2, _, _, _, _, _, _, _, _, _, _),
+ [146] = PINGROUP(146, qup2_se2, _, _, _, _, _, _, _, _, _, _),
+ [147] = PINGROUP(147, qup2_se2, _, _, _, _, _, _, _, _, _, _),
+ [148] = PINGROUP(148, qup2_se2, _, _, _, _, _, _, _, _, _, _),
+ [149] = PINGROUP(149, qup2_se2, _, _, _, _, _, _, _, _, _, _),
+ [150] = PINGROUP(150, qup2_se3, qup2_se4, ccu_timer, _, _, _, _, _, _, _, _),
+ [151] = PINGROUP(151, qup2_se3, qup2_se4, ccu_timer, _, _, _, _, _, _, _, _),
+ [152] = PINGROUP(152, qup2_se3, qup2_se4, ccu_timer, _, _, _, _, _, _, _, _),
+ [153] = PINGROUP(153, qup2_se3, ccu_timer, _, _, _, _, _, _, _, _, _),
+ [154] = PINGROUP(154, qup2_se4, qup2_se1, _, _, _, _, _, _, _, _, _),
+ [155] = PINGROUP(155, qup2_se4, qup2_se1, _, _, _, _, _, _, _, _, _),
+ [156] = PINGROUP(156, qup2_se5, qup2_se6, _, _, _, _, _, _, _, _, _),
+ [157] = PINGROUP(157, qup2_se5, qup2_se6, _, _, _, _, _, _, _, _, _),
+ [158] = PINGROUP(158, qup2_se6, qup2_se5, dp_rx1, _, _, _, _, _, _, _, _),
+ [159] = PINGROUP(159, qup2_se6, qup2_se5, dp_rx1, _, _, _, _, _, _, _, _),
+ [160] = PINGROUP(160, wcn_sw_ctrl, _, _, _, _, _, _, _, _, _, _),
+ [161] = PINGROUP(161, wcn_sw, _, _, _, _, _, _, _, _, _, _),
+ [162] = PINGROUP(162, qdss_cti, _, ddr_pxi, _, _, _, _, _, _, _, _),
+ [163] = PINGROUP(163, qdss_cti, _, ddr_pxi, _, _, _, _, _, _, _, _),
+ [164] = PINGROUP(164, usb0_phy_ps, _, sailss_ospi, ddr_pxi, _, _, _, _, _, _, _),
+ [165] = PINGROUP(165, usb1_phy_ps, dbg_out_clk, sailss_ospi, ddr_pxi,
+ _, _, _, _, _, _, _),
+ [166] = PINGROUP(166, _, _, _, _, _, _, _, _, _, _, _),
+ [167] = PINGROUP(167, pwrbrk_i_n, _, _, _, _, _, _, _, _, _, _),
+ [168] = PINGROUP(168, bist_done, _, _, _, _, _, _, _, _, _, _),
+ [169] = PINGROUP(169, tb_trig_sdc4, _, _, _, _, _, _, _, _, _, _),
+ [170] = PINGROUP(170, sdc4_data, _, _, _, _, _, _, _, _, _, _),
+ [171] = PINGROUP(171, sdc4_data, _, _, _, _, _, _, _, _, _, _),
+ [172] = PINGROUP(172, sdc4_data, _, _, _, _, _, _, _, _, _, _),
+ [173] = PINGROUP(173, sdc4_data, _, _, _, _, _, _, _, _, _, _),
+ [174] = PINGROUP(174, sdc4_cmd, _, _, _, _, _, _, _, _, _, _),
+ [175] = PINGROUP(175, sdc4_clk, _, _, _, _, _, _, _, _, _, _),
+ [176] = PINGROUP(176, ccu_async_in, pll_bist_sync, atest_char,
+ _, _, _, _, _, _, _, _),
+ [177] = PINGROUP(177, ccu_async_in, atest_char, _, _, _, _, _, _, _, _, _),
+ [178] = PINGROUP(178, ccu_async_in, atest_char, _, _, _, _, _, _, _, _, _),
+ [179] = PINGROUP(179, ccu_async_in, atest_char, _, _, _, _, _, _, _, _, _),
+ [180] = PINGROUP(180, ccu_async_in, atest_char, _, _, _, _, _, _, _, _, _),
+ [181] = UFS_RESET(ufs_reset, 0xbd004, 0xbe000),
+};
+
+static const struct msm_gpio_wakeirq_map nord_pdc_map[] = {
+ { 0, 67 }, { 1, 68 }, { 2, 82 }, { 3, 69 }, { 4, 70 },
+ { 5, 83 }, { 6, 71 }, { 7, 72 }, { 8, 84 }, { 9, 73 },
+ { 10, 119 }, { 11, 85 }, { 45, 107 }, { 46, 98 }, { 102, 77 },
+ { 108, 78 }, { 110, 120 }, { 114, 80 }, { 116, 81 }, { 120, 117 },
+ { 124, 108 }, { 126, 99 }, { 128, 100 }, { 132, 101 }, { 138, 87 },
+ { 142, 88 }, { 144, 89 }, { 153, 90 }, { 157, 91 }, { 159, 118 },
+ { 160, 110 }, { 161, 79 }, { 166, 109 }, { 168, 111 },
+};
+
+static const struct msm_pinctrl_soc_data nord_tlmm = {
+ .pins = nord_pins,
+ .npins = ARRAY_SIZE(nord_pins),
+ .functions = nord_functions,
+ .nfunctions = ARRAY_SIZE(nord_functions),
+ .groups = nord_groups,
+ .ngroups = ARRAY_SIZE(nord_groups),
+ .ngpios = 182,
+ .wakeirq_map = nord_pdc_map,
+ .nwakeirq_map = ARRAY_SIZE(nord_pdc_map),
+ .egpio_func = 11,
+};
+
+static const struct of_device_id nord_tlmm_of_match[] = {
+ { .compatible = "qcom,nord-tlmm", .data = &nord_tlmm },
+ {},
+};
+MODULE_DEVICE_TABLE(of, nord_tlmm_of_match);
+
+static int nord_tlmm_probe(struct platform_device *pdev)
+{
+ const struct msm_pinctrl_soc_data *pinctrl_data;
+ struct device *dev = &pdev->dev;
+
+ pinctrl_data = device_get_match_data(dev);
+ if (!pinctrl_data)
+ return -EINVAL;
+
+ return msm_pinctrl_probe(pdev, &nord_tlmm);
+}
+
+static struct platform_driver nord_tlmm_driver = {
+ .driver = {
+ .name = "nord-tlmm",
+ .of_match_table = nord_tlmm_of_match,
+ },
+ .probe = nord_tlmm_probe,
+};
+
+static int __init nord_tlmm_init(void)
+{
+ return platform_driver_register(&nord_tlmm_driver);
+}
+arch_initcall(nord_tlmm_init);
+
+static void __exit nord_tlmm_exit(void)
+{
+ platform_driver_unregister(&nord_tlmm_driver);
+}
+module_exit(nord_tlmm_exit);
+
+MODULE_DESCRIPTION("Qualcomm Technologies Inc. Nordschleife TLMM driver");
+MODULE_LICENSE("GPL");
--
2.47.3
^ permalink raw reply related
* [PATCH v3 1/2] dt-bindings: pinctrl: describe the Qualcomm nord-tlmm
From: Bartosz Golaszewski @ 2026-04-28 13:48 UTC (permalink / raw)
To: Bjorn Andersson, Linus Walleij, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Richard Cochran, Bartosz Golaszewski, Shawn Guo,
Arnd Bergmann, Dmitry Baryshkov
Cc: linux-arm-msm, linux-gpio, devicetree, linux-kernel, netdev,
Bartosz Golaszewski
In-Reply-To: <20260428-nord-tlmm-v3-0-f16f08d084cc@oss.qualcomm.com>
Add a DT binding document describing the TLMM pin controller available
on the Nord platforms from Qualcomm.
Co-developed-by: Shawn Guo <shengchao.guo@oss.qualcomm.com>
Signed-off-by: Shawn Guo <shengchao.guo@oss.qualcomm.com>
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
---
.../bindings/pinctrl/qcom,nord-tlmm.yaml | 141 +++++++++++++++++++++
1 file changed, 141 insertions(+)
diff --git a/Documentation/devicetree/bindings/pinctrl/qcom,nord-tlmm.yaml b/Documentation/devicetree/bindings/pinctrl/qcom,nord-tlmm.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..4bb511719f3130fc208011b4a8b45f4cfcde8c9b
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/qcom,nord-tlmm.yaml
@@ -0,0 +1,141 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/pinctrl/qcom,nord-tlmm.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm Technologies, Inc. SA8797P TLMM block
+
+maintainers:
+ - Bartosz Golaszewski <brgl@kernel.org>
+
+description:
+ Top Level Mode Multiplexer pin controller in Qualcomm SA8797P SoC.
+
+allOf:
+ - $ref: /schemas/pinctrl/qcom,tlmm-common.yaml#
+
+properties:
+ compatible:
+ const: qcom,nord-tlmm
+
+ reg:
+ maxItems: 1
+
+ interrupts:
+ maxItems: 1
+
+ gpio-reserved-ranges:
+ minItems: 1
+ maxItems: 90
+
+ gpio-line-names:
+ maxItems: 181
+
+patternProperties:
+ "-state$":
+ oneOf:
+ - $ref: "#/$defs/qcom-nord-tlmm-state"
+ - patternProperties:
+ "-pins$":
+ $ref: "#/$defs/qcom-nord-tlmm-state"
+ additionalProperties: false
+
+$defs:
+ qcom-nord-tlmm-state:
+ type: object
+ description:
+ Pinctrl node's client devices use subnodes for desired pin configuration.
+ Client device subnodes use below standard properties.
+ $ref: qcom,tlmm-common.yaml#/$defs/qcom-tlmm-state
+ unevaluatedProperties: false
+
+ properties:
+ pins:
+ description:
+ List of gpio pins affected by the properties specified in this
+ subnode.
+ items:
+ oneOf:
+ - pattern: "^gpio([0-9]|[1-9][0-9]|1[0-7][0-9]|180)$"
+ - enum: [ ufs_reset ]
+ minItems: 1
+ maxItems: 16
+
+ function:
+ description:
+ Specify the alternative function to be configured for the specified
+ pins.
+
+ enum: [ aoss_cti, atest_char, atest_usb20, atest_usb21,
+ aud_intfc0_clk, aud_intfc0_data, aud_intfc0_ws,
+ aud_intfc10_clk, aud_intfc10_data, aud_intfc10_ws,
+ aud_intfc1_clk, aud_intfc1_data, aud_intfc1_ws,
+ aud_intfc2_clk, aud_intfc2_data, aud_intfc2_ws,
+ aud_intfc3_clk, aud_intfc3_data, aud_intfc3_ws,
+ aud_intfc4_clk, aud_intfc4_data, aud_intfc4_ws,
+ aud_intfc5_clk, aud_intfc5_data, aud_intfc5_ws,
+ aud_intfc6_clk, aud_intfc6_data, aud_intfc6_ws,
+ aud_intfc7_clk, aud_intfc7_data, aud_intfc7_ws,
+ aud_intfc8_clk, aud_intfc8_data, aud_intfc8_ws,
+ aud_intfc9_clk, aud_intfc9_data, aud_intfc9_ws,
+ aud_mclk0_mira, aud_mclk0_mirb, aud_mclk1_mira, aud_mclk1_mirb,
+ aud_mclk2_mira, aud_mclk2_mirb, aud_refclk0, aud_refclk1,
+ bist_done, ccu_async_in, ccu_i2c_scl, ccu_i2c_sda, ccu_timer,
+ clink_debug, dbg_out, dbg_out_clk,
+ ddr_bist_complete, ddr_bist_fail, ddr_bist_start, ddr_bist_stop,
+ ddr_pxi, dp_rx0, dp_rx00, dp_rx01, dp_rx0_mute, dp_rx1, dp_rx10,
+ dp_rx11, dp_rx1_mute,
+ edp0_hot, edp0_lcd, edp1_hot, edp1_lcd, edp2_hot, edp2_lcd,
+ edp3_hot, edp3_lcd,
+ emac0_mcg, emac0_mdc, emac0_mdio, emac0_ptp, emac1_mcg,
+ emac1_mdc, emac1_mdio, emac1_ptp,
+ gcc_gp1_clk, gcc_gp2_clk, gcc_gp3_clk, gcc_gp4_clk, gcc_gp5_clk,
+ gcc_gp6_clk, gcc_gp7_clk, gcc_gp8_clk, jitter_bist, lbist_pass,
+ mbist_pass, mdp0_vsync_out, mdp1_vsync_out, mdp_vsync_e,
+ mdp_vsync_p, mdp_vsync_s,
+ pcie0_clk_req_n, pcie1_clk_req_n, pcie2_clk_req_n,
+ pcie3_clk_req_n, phase_flag, pll_bist_sync, pll_clk_aux,
+ prng_rosc0, prng_rosc1, pwrbrk_i_n, qdss, qdss_cti, qspi,
+ qup0_se0, qup0_se1, qup0_se2, qup0_se3, qup0_se4, qup0_se5,
+ qup1_se0, qup1_se1, qup1_se3, qup1_se2, qup1_se4, qup1_se5,
+ qup1_se6, qup2_se0, qup2_se1, qup2_se2, qup2_se3, qup2_se4,
+ qup2_se5, qup2_se6,
+ sailss_ospi, sdc4_clk, sdc4_cmd, sdc4_data, smb_alert,
+ smb_alert_n, smb_clk, smb_dat, tb_trig_sdc4, tmess_prng0,
+ tmess_prng1, tsc_timer, tsense_pwm, usb0_hs,
+ usb0_phy_ps, usb1_hs, usb1_phy_ps, usb2_hs, usxgmii0_phy,
+ usxgmii1_phy, vsense_trigger_mirnat, wcn_sw, wcn_sw_ctrl]
+
+ required:
+ - pins
+
+required:
+ - compatible
+ - reg
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+
+ tlmm: pinctrl@f100000 {
+ compatible = "qcom,nord-tlmm";
+ reg = <0x0f100000 0xc0000>;
+ interrupts = <GIC_SPI 208 IRQ_TYPE_LEVEL_HIGH>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ gpio-ranges = <&tlmm 0 0 181>;
+ wakeup-parent = <&pdc>;
+
+ qup_uart15_default: qup-uart15-default-state {
+ pins = "gpio147", "gpio148";
+ function = "qup2_se2";
+ drive-strength = <2>;
+ bias-disable;
+ };
+ };
+...
--
2.47.3
^ permalink raw reply related
* [PATCH v3 0/2] pinctrl: qcom: add support for the TLMM controller on Nord platforms
From: Bartosz Golaszewski @ 2026-04-28 13:48 UTC (permalink / raw)
To: Bjorn Andersson, Linus Walleij, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Richard Cochran, Bartosz Golaszewski, Shawn Guo,
Arnd Bergmann, Dmitry Baryshkov
Cc: linux-arm-msm, linux-gpio, devicetree, linux-kernel, netdev,
Bartosz Golaszewski
This adds DT bindings describing the TLMM controller on Qualcomm Nord
platforms and implements the pinctrl driver.
More info on the platform here:
https://lore.kernel.org/all/20260427003531.229671-1-shengchao.guo@oss.qualcomm.com/
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
---
Changes in v3:
- Unify even more fine-grained pin functions into larger groups
- Fix the UFS_RESET() implementation and use correct offset for the IO
register
- Don't use uppercase hex numbers
- Make usage of the vendor name consistent with recent changes
- Make the driver default to ARCH_QCOM
- Link to v2: https://patch.msgid.link/20260427-nord-tlmm-v2-0-ade8e0f3d803@oss.qualcomm.com
Changes in v2:
- Order Kconfig entries alphabetically
- Fix the regex for the pin state pattern
- Fix maxItems for gpio-line-names
- Drop unneeded line break from bindings
- Rework the pin function naming to make resulting state entries in
devicetree more concise (drop the line number suffix)
- drop .intr_target_reg from PINGROUP()
- fix values for interrupt entries in PINGROUP()
- drop unused SDC_QDSD_PINGROUP() and QUP_I3C()
- drop the arm64 defconfig updates from series
- rebased on top of v7.1-rc1
- Link to v1: https://patch.msgid.link/20260403-nord-tlmm-v1-0-4864f400c700@oss.qualcomm.com
---
Bartosz Golaszewski (2):
dt-bindings: pinctrl: describe the Qualcomm nord-tlmm
pinctrl: qcom: add the TLMM driver for the Nord platforms
.../bindings/pinctrl/qcom,nord-tlmm.yaml | 141 ++
drivers/pinctrl/qcom/Kconfig.msm | 8 +
drivers/pinctrl/qcom/Makefile | 1 +
drivers/pinctrl/qcom/pinctrl-nord.c | 1771 ++++++++++++++++++++
4 files changed, 1921 insertions(+)
---
base-commit: 254f49634ee16a731174d2ae34bc50bd5f45e731
change-id: 20260403-nord-tlmm-b5878960cec6
Best regards,
--
Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
^ permalink raw reply
* Re: [PATCH net v4 0/5] nfc: fix multiple OOB reads in NCI and LLCP parsing paths
From: Paolo Abeni @ 2026-04-28 13:46 UTC (permalink / raw)
To: Simon Horman, Lekë Hapçiu
Cc: netdev, davem, edumazet, kuba, krzk, linux-kernel, stable,
David Heidelberg
In-Reply-To: <20260428125523.GQ900403@horms.kernel.org>
On 4/28/26 2:55 PM, Simon Horman wrote:
> On Fri, Apr 24, 2026 at 08:01:46PM +0200, Lekë Hapçiu wrote:
>> This series fixes five out-of-bounds / underflow bugs in the kernel NFC
>> stack. All are reachable from a remote NFC peer that the local stack
>> has already associated with; in the LLCP cases the peer only needs to
>> send a malformed frame.
>>
>> 1/5 nci: u8 underflow in nci_store_general_bytes_nfc_dep() lets the
>> attacker-controlled atr_res_len skip the GT-offset subtraction
>> and cause an OOB read/write against general_bytes[].
>> 2/5 llcp: parse_gb_tlv() / parse_connection_tlv() trust the TLV
>> length byte without checking remaining buffer, and the tlv16
>> accessors read past the end when length < 2.
>> 3/5 llcp: nfc_llcp_recv_snl() has the same TLV-length trust bug, and
>> its SDRES handler uses an unbounded "%.16s" pr_debug() that
>> walks past service_name_len.
>> 4/5 llcp: nfc_llcp_recv_dm() reads skb->data[3] without checking
>> skb->len, giving a 1-byte heap OOB read.
>> 5/5 llcp: nfc_llcp_connect_sn() walks the TLV array with no length
>> validation; a crafted CONNECT frame drops it into OOB reads /
>> an unbounded service-name pointer.
>>
>> The series applies on top of net/main.
>>
>> Lekë Hapçiu (5):
>> nfc: nci: fix u8 underflow in nci_store_general_bytes_nfc_dep
>> nfc: llcp: fix TLV parsing in parse_gb_tlv and parse_connection_tlv
>> nfc: llcp: fix TLV parsing OOB in nfc_llcp_recv_snl
>> nfc: llcp: fix OOB read of DM reason byte in nfc_llcp_recv_dm
>> nfc: llcp: fix TLV parsing OOB in nfc_llcp_connect_sn
>
> Hi,
>
> My only feedback on v4 of this patchset is that somehow the
> threading is broken: each of patch 1/5 - 5/5 should be a reply
> to the cover letter - 0/5 - but that does not seem to be the case.
> And some tooling, notably Sashiko, seems to rely on the
> entire patchset being contained in a single email thread.
Given the above, I suggest re-posting.
Also note that we are moving NFC to a specific subtree, see:
https://lore.kernel.org/netdev/938496c6-84c1-4d53-bb56-73bbd7b2bdd7@ixit.cz/
please wait a bit for resubmission, possibly David will be already ready
to catch them.
Thanks,
Paolo
^ permalink raw reply
* Re: [PATCH net-next 1/2] devlink, mlx5: add init/fini ops for shared devlink
From: Przemek Kitszel @ 2026-04-28 13:44 UTC (permalink / raw)
To: Jiri Pirko
Cc: netdev, Jakub Kicinski, intel-wired-lan, Tony Nguyen,
Jacob Keller, Lukasz Czapnik, Jedrzej Jagielski, Andrew Lunn,
David S. Miller, Eric Dumazet, Paolo Abeni, Saeed Mahameed,
Leon Romanovsky, Tariq Toukan, Mark Bloch, Simon Horman,
Aleksandr Loktionov
In-Reply-To: <afCU-3Xmole6v4X4@FV6GYCPJ69>
On 4/28/26 13:10, Jiri Pirko wrote:
> Tue, Apr 28, 2026 at 11:09:11AM +0200, przemyslaw.kitszel@intel.com wrote:
>> Add .shd_init() and .shd_fini() ops, that will be called for the first
>> devlink_shd_get() (to initialize driver' priv data) and on the last
>> devlink_shd_put() (to allow for the cleanup). Both ops are optional.
>>
>> .shd_init() could return an error, which will stop creation of shd
>> instance. The initializer also gets an additional, optional param,
>> that driver could use for any needs.
>>
>> If any of the callbacks will need to get devlink instance, it could
>> be accessed by shd_priv_to_devlink().
>>
>> Both callbacks are called with devl_lock held and devlink registered.
>>
>> Next commit will make use of the callbacks, another one will make use also
>> of the non-null additional param (outside of this series).
>>
>> Reviewed-by: Aleksandr Loktionov <aleksandr.loktionov@intel.com>
>> Signed-off-by: Przemek Kitszel <przemyslaw.kitszel@intel.com>
>> ---
>> first discussed at:
>> https://lore.kernel.org/netdev/20260325063143.261806-3-przemyslaw.kitszel@intel.com
>>
>> Sashiko suggested to convert devlink_shd_create() to return ERR_PTR(),
>> and propagate that up to the driver. It think it will just make code more
>> verbose for not much benefit. And drivers could just store err if they
>> want in the passed @init_param.
>>
>> ---
>> include/net/devlink.h | 26 +++++++++++++
>> .../ethernet/mellanox/mlx5/core/sh_devlink.c | 2 +-
>> net/devlink/sh_dev.c | 39 ++++++++++++++++++-
>> 3 files changed, 64 insertions(+), 3 deletions(-)
>>
>> diff --git a/include/net/devlink.h b/include/net/devlink.h
>> index bcd31de1f890..5d3a1337bfa1 100644
>> --- a/include/net/devlink.h
>> +++ b/include/net/devlink.h
>> @@ -1586,6 +1586,30 @@ struct devlink_ops {
>> struct devlink_rate *parent,
>> void *priv_child, void *priv_parent,
>> struct netlink_ext_ack *extack);
>> +
>> + /**
>> + * shd_init: Shared devlink instance initializer
>> + * @priv: shd_devlink' priv
>> + * @init_param: additional param to pass to driver callback
>> + *
>> + * Called once when the shared instance is first created (by the first
>> + * devlink_shd_get() call).
>> + * Should initialize the driver's private data embedded in the shared
>> + * devlink. May be NULL.
>> + *
>> + * Return: 0 on success, negative to prevent shared instance usage.
>> + */
>> + int (*shd_init)(void *priv, void *init_param);
>
> 1. "param" has specific meaning in devlink context
> 2. You don't use the arg in driver
>
> Care to drop it?
I have a user for it, but it will be a separate series
(I have already 15 patches there), will post RFC to link here
to the user, will that work?
my intention was to not tie touching mlx code with big series for intel
>
> Otherwise, this looks fine to me. Thanks! (small nitpick below)
ack for the nit
^ permalink raw reply
* Re: [PATCH] net: lan966x: avoid unregistering netdev on register failure
From: Simon Horman @ 2026-04-28 13:45 UTC (permalink / raw)
To: mhun512
Cc: 'Simon Horman', horatiu.vultur, UNGLinuxDriver,
andrew+netdev, davem, edumazet, kuba, pabeni, ae878000, netdev,
linux-kernel
In-Reply-To: <20260426142806.36028-1-mhun512@gmail.com>
From: 'Simon Horman' <horms@kernel.org>
This is an AI-generated review of your patch. The human sending this
email has considered the AI review valid, or at least plausible.
Full review at: https://sashiko.dev
---
net: lan966x: avoid unregistering netdev on register failure
lan966x_probe_port() stores the newly allocated net_device in the
port before calling register_netdev(). If register_netdev() fails,
the probe error path calls lan966x_cleanup_ports(), which sees
port->dev and calls unregister_netdev() for a device that was never
registered.
> diff --git a/drivers/net/ethernet/microchip/lan966x/lan966x_main.c b/drivers/net/ethernet/microchip/lan966x/lan966x_main.c
> index 47752d3fde0b..22c496f5882a 100644
> --- a/drivers/net/ethernet/microchip/lan966x/lan966x_main.c
> +++ b/drivers/net/ethernet/microchip/lan966x/lan966x_main.c
> @@ -873,6 +873,9 @@ static int lan966x_probe_port(struct lan966x *lan966x, u32 p,
> err = register_netdev(dev);
> if (err) {
> dev_err(lan966x->dev, "register_netdev failed\n");
> + phylink_destroy(phylink);
> + port->phylink = NULL;
> + port->dev = NULL;
By setting port->dev = NULL on registration failure, does this patch
inadvertently cause a null pointer dereference regression during error
handling?
If lan966x_probe_port() fails at register_netdev(), it now sets
port->dev = NULL and returns an error, leading to lan966x_cleanup_ports():
lan966x_main.c:lan966x_cleanup_ports() {
...
if (port->dev)
unregister_netdev(port->dev);
lan966x_xdp_port_deinit(port);
if (lan966x->fdma && lan966x->fdma_ndev == port->dev)
lan966x_fdma_netdev_deinit(lan966x, port->dev);
...
}
If fdma is enabled but lan966x->fdma_ndev was never initialized (which is
true if the first port fails, as lan966x_fdma_netdev_init() is called after
lan966x_probe_port()), both lan966x->fdma_ndev and port->dev will be NULL.
This makes the condition NULL == NULL evaluate to true, unconditionally
passing port->dev (NULL) to lan966x_fdma_netdev_deinit():
lan966x_fdma.c:lan966x_fdma_netdev_deinit() {
if (lan966x->fdma_ndev == dev) {
netif_napi_del(&lan966x->napi);
lan966x->fdma_ndev = NULL;
}
}
The check lan966x->fdma_ndev == dev again passes (NULL == NULL). It will then
call netif_napi_del(&lan966x->napi).
Because the fdma napi was never initialized via netif_napi_add(), its fields
are zeroed. When netif_napi_del() is called on this uninitialized napi struct,
it will attempt to lock the device:
include/linux/netdevice.h:__netif_napi_del() {
netdev_lock(napi->dev);
__netif_napi_del_locked(napi);
netdev_unlock(napi->dev);
}
Since napi->dev is NULL, netdev_lock() will dereference a null pointer.
A similar regression will occur if a subsequent port fails after the first
port was successfully cleaned up, as lan966x->fdma_ndev is reset to NULL
during the first port's cleanup.
> return err;
> }
--
pw-bot: changes-requested
^ permalink raw reply
* [PATCH] net: sunrpc: fix slab-out-of-bounds read in cache_seq_start_rcu
From: Alessandro Zanni @ 2026-04-28 13:42 UTC (permalink / raw)
To: chuck.lever, jlayton, neil, okorniev, Dai.Ngo, tom, trondmy, anna,
davem, edumazet, kuba, pabeni, horms
Cc: Alessandro Zanni, linux-nfs, netdev, linux-kernel,
syzbot+60cfa08822470bbebe44
Syzbot reported slab-out-of-bounds read in cache_seq_start_rcu().
The issue happens in function __cache_seq_start() when is invoked
hlist_for_each_entry_rcu() and the hash value is greater than the
hash_size.
This fix verifies that the hash index is within the hash_size value
before dereferencing the hash table: if the hash index is out of
bounds return NULL, otherwise access the value.
Fixes: ae74136b4bb6 ("SUNRPC: Allow cache lookups to use RCU protection rather than the r/w spinlock")
Reported-by: syzbot+60cfa08822470bbebe44@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=60cfa08822470bbebe44
Signed-off-by: Alessandro Zanni <alessandro.zanni87@gmail.com>
---
net/sunrpc/cache.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/net/sunrpc/cache.c b/net/sunrpc/cache.c
index 7081c1214e6c..aac5f03112f5 100644
--- a/net/sunrpc/cache.c
+++ b/net/sunrpc/cache.c
@@ -1348,6 +1348,9 @@ static void *__cache_seq_start(struct seq_file *m, loff_t *pos)
hash = n >> 32;
entry = n & ((1LL<<32) - 1);
+ if (hash >= cd->hash_size)
+ return NULL;
+
hlist_for_each_entry_rcu(ch, &cd->hash_table[hash], cache_list)
if (!entry--)
return ch;
--
2.47.3
^ permalink raw reply related
* [PATCH net] net: phy: micrel: fix LAN8814 QSGMII soft reset
From: Robert Marko @ 2026-04-28 13:41 UTC (permalink / raw)
To: andrew, hkallweit1, linux, davem, edumazet, kuba, pabeni,
Divya.Koppera, horatiu.vultur, netdev, linux-kernel
Cc: Robert Marko
LAN8814 QSGMII soft reset was moved into the probe function to avoid
triggering it for each of 4 PHY-s in the package.
However, that broke QSGMII link between the MAC and PHY on most LAN8814
PHY-s, specificaly for us on the Microchip LAN969x switch.
Reading the QSGMII status registers it was visible that lanes were only
partially synced.
It looks like the reset timing is crucial, so lets move the reset back
into the .config_init function but guard it with phy_package_init_once()
to avoid it being triggered on each of 4 PHY-s in the package.
Change the probe function to use phy_package_probe_once() for coma and PtP
setup.
Fixes: 96a9178a29a6 ("net: phy: micrel: lan8814 fix reset of the QSGMII interface")
Signed-off-by: Robert Marko <robert.marko@sartura.hr>
---
drivers/net/phy/micrel.c | 15 ++++++++-------
1 file changed, 8 insertions(+), 7 deletions(-)
diff --git a/drivers/net/phy/micrel.c b/drivers/net/phy/micrel.c
index 2aa1dedd21b8..e211a523c258 100644
--- a/drivers/net/phy/micrel.c
+++ b/drivers/net/phy/micrel.c
@@ -4548,6 +4548,13 @@ static int lan8814_config_init(struct phy_device *phydev)
struct kszphy_priv *lan8814 = phydev->priv;
int ret;
+ if (phy_package_init_once(phydev))
+ /* Reset the PHY */
+ lanphy_modify_page_reg(phydev, LAN8814_PAGE_COMMON_REGS,
+ LAN8814_QSGMII_SOFT_RESET,
+ LAN8814_QSGMII_SOFT_RESET_BIT,
+ LAN8814_QSGMII_SOFT_RESET_BIT);
+
/* Based on the interface type select how the advertise ability is
* encoded, to set as SGMII or as USGMII.
*/
@@ -4655,13 +4662,7 @@ static int lan8814_probe(struct phy_device *phydev)
priv->is_ptp_available = err == LAN8814_REV_LAN8814 ||
err == LAN8814_REV_LAN8818;
- if (phy_package_init_once(phydev)) {
- /* Reset the PHY */
- lanphy_modify_page_reg(phydev, LAN8814_PAGE_COMMON_REGS,
- LAN8814_QSGMII_SOFT_RESET,
- LAN8814_QSGMII_SOFT_RESET_BIT,
- LAN8814_QSGMII_SOFT_RESET_BIT);
-
+ if (phy_package_probe_once(phydev)) {
err = lan8814_release_coma_mode(phydev);
if (err)
return err;
--
2.54.0
^ permalink raw reply related
* Re: [PATCH net-next v9 4/4] tun/tap & vhost-net: avoid ptr_ring tail-drop when a qdisc is present
From: Simon Schippers @ 2026-04-28 13:41 UTC (permalink / raw)
To: Michael S. Tsirkin
Cc: willemdebruijn.kernel, jasowang, andrew+netdev, davem, edumazet,
kuba, pabeni, eperezma, leiyang, stephen, jon, tim.gebauer,
netdev, linux-kernel, kvm, virtualization
In-Reply-To: <20260428092150-mutt-send-email-mst@kernel.org>
On 4/28/26 15:22, Michael S. Tsirkin wrote:
> On Tue, Apr 28, 2026 at 03:10:44PM +0200, Simon Schippers wrote:
>> On 4/28/26 14:50, Michael S. Tsirkin wrote:
>>> On Tue, Apr 28, 2026 at 02:38:59PM +0200, Simon Schippers wrote:
>>>> This commit prevents tail-drop when a qdisc is present and the ptr_ring
>>>> becomes full. Once an entry is successfully produced and the ptr_ring
>>>> reaches capacity, the netdev queue is stopped instead of dropping
>>>> subsequent packets.
>>>>
>>>> If producing an entry fails anyways due to a race, tun_net_xmit returns
>>>> NETDEV_TX_BUSY, again avoiding a drop. Such races are expected because
>>>> LLTX is enabled and the transmit path operates without the usual locking.
>>>>
>>>> If no qdisc is present, the previous tail-drop behavior is preserved.
>>>>
>>>> The existing __tun_wake_queue() function of the consumer races with the
>>>> producer for waking/stopping the netdev queue: the consumer may drain
>>>> the ring just as the producer stops the queue, leading to a permanent
>>>> stall. To avoid this, the producer re-checks the ring after stopping
>>>> and wakes the queue itself if space was just made. An
>>>> smp_mb__after_atomic() is required so the re-peek of the ring sees any
>>>> drain that the consumer performed.
>>>> smp_mb__after_atomic() pairs with the test_and_clear_bit() inside of
>>>> netif_wake_subqueue():
>>>>
>>>> Consumer CPU Producer CPU
>>>> ======================== =========================
>>>> __ptr_ring_consume()
>>>> netif_wake_subqueue() netif_tx_stop_queue()
>>>> /\ smp_mb__after_atomic()
>>>> || __ptr_ring_produce_peek()
>>>> contains RMW operation
>>>> test_and_clear_bit()
>>>> /\
>>>> ||
>>>> "Fully ordered RMW:
>>>> smp_mb() before + after"
>>>> - atomic_t.txt
>>>>
>>>> Benchmarks:
>>>> The benchmarks show a slight regression in raw transmission performance,
>>>> though no packets are lost anymore.
>>>
>>> Could you include the packets received as well?
>>> To demonstrate the gains/lack of loss.
>>>
>>
>> Do you mean the number of packets received by the VM?
>> They should just be the same as the number sent (shown below), right?
>
> Minus the loss? Which this is about, right?
Yes. I simply calculated "Lost/s":
elapsed_time = 100e6 / sent_pps
Lost/s = total_errors / elapsed_time
To get back total_errors for example for TAP
1 thread sending:
elapsed_time = 100e6 / 1.136Mpps = 88s
3758 Mpps = total_errors / 88s
<=> total_errors = 331 million packets
So, out of 431 million packets sent, 100 million were successfully
delivered and 331 million were lost.
>
>> I assume they would be visible as RX-DRP for TAP.
>> For TAP + vhost-net I would have to rewrite the XDP drop
>> program to count the number of dropped packets...
>> And I would have to automate it...
>>
>>>>
>>>> The previously introduced threshold to only wake after the queue stopped
>>>> and half of the ring was consumed showed to be a descent choice:
>>>> Waking the queue whenever a consume made space in the ring strongly
>>>> degrades performance for tap, while waking only when the ring is empty
>>>> is too late and also hurts throughput for tap & tap+vhost-net.
>>>> Other ratios (3/4, 7/8) showed similar results (not shown here), so
>>>> 1/2 was chosen for the sake of simplicity for both tun/tap and
>>>> tun/tap+vhost-net.
>>>>
>>>> Test setup:
>>>> AMD Ryzen 5 5600X at 4.3 GHz, 3200 MHz RAM, isolated QEMU threads;
>>>> Average over 50 runs @ 100,000,000 packets. SRSO and spectre v2
>>>> mitigations disabled.
>>>>
>>>> Note for tap+vhost-net:
>>>> XDP drop program active in VM -> ~2.5x faster, slower for tap due to
>>>> more syscalls (high utilization of entry_SYSRETQ_unsafe_stack in perf)
>>>>
>>>> +--------------------------+--------------+----------------+----------+
>>>> | 1 thread | Stock | Patched with | diff |
>>>> | sending | | fq_codel qdisc | |
>>>> +------------+-------------+--------------+----------------+----------+
>>>> | TAP | Transmitted | 1.136 Mpps | 1.130 Mpps | -0.6% |
>>>> | +-------------+--------------+----------------+----------+
>>>> | | Lost/s | 3.758 Mpps | 0 pps | |
>>>> +------------+-------------+--------------+----------------+----------+
>>>> | TAP | Transmitted | 3.858 Mpps | 3.816 Mpps | -1.1% |
>>>> | +-------------+--------------+----------------+----------+
>>>> | +vhost-net | Lost/s | 789.8 Kpps | 0 pps | |
>>>> +------------+-------------+--------------+----------------+----------+
>>>>
>>>> +--------------------------+--------------+----------------+----------+
>>>> | 2 threads | Stock | Patched with | diff |
>>>> | sending | | fq_codel qdisc | |
>>>> +------------+-------------+--------------+----------------+----------+
>>>> | TAP | Transmitted | 1.117 Mpps | 1.087 Mpps | -2.7% |
>>>> | +-------------+--------------+----------------+----------+
>>>> | | Lost/s | 8.476 Mpps | 0 pps | |
>>>> +------------+-------------+--------------+----------------+----------+
>>>> | TAP | Transmitted | 3.679 Mpps | 3.464 Mpps | -5.8% |
>>>> | +-------------+--------------+----------------+----------+
>>>> | +vhost-net | Lost/s | 5.306 Mpps | 0 pps | |
>>>> +------------+-------------+--------------+----------------+----------+
>>>>
>>>> Co-developed-by: Tim Gebauer <tim.gebauer@tu-dortmund.de>
>>>> Signed-off-by: Tim Gebauer <tim.gebauer@tu-dortmund.de>
>>>> Signed-off-by: Simon Schippers <simon.schippers@tu-dortmund.de>
>>>> ---
>>>> drivers/net/tun.c | 30 ++++++++++++++++++++++++++++--
>>>> 1 file changed, 28 insertions(+), 2 deletions(-)
>>>>
>>>> diff --git a/drivers/net/tun.c b/drivers/net/tun.c
>>>> index efe809597622..c2a1618cc9db 100644
>>>> --- a/drivers/net/tun.c
>>>> +++ b/drivers/net/tun.c
>>>> @@ -1011,6 +1011,8 @@ static netdev_tx_t tun_net_xmit(struct sk_buff *skb, struct net_device *dev)
>>>> struct netdev_queue *queue;
>>>> struct tun_file *tfile;
>>>> int len = skb->len;
>>>> + bool qdisc_present;
>>>> + int ret;
>>>>
>>>> rcu_read_lock();
>>>> tfile = rcu_dereference(tun->tfiles[txq]);
>>>> @@ -1065,13 +1067,37 @@ static netdev_tx_t tun_net_xmit(struct sk_buff *skb, struct net_device *dev)
>>>>
>>>> nf_reset_ct(skb);
>>>>
>>>> - if (ptr_ring_produce(&tfile->tx_ring, skb)) {
>>>> + queue = netdev_get_tx_queue(dev, txq);
>>>> + qdisc_present = !qdisc_txq_has_no_queue(queue);
>>>> +
>>>> + spin_lock(&tfile->tx_ring.producer_lock);
>>>> + ret = __ptr_ring_produce(&tfile->tx_ring, skb);
>>>> + if (__ptr_ring_produce_peek(&tfile->tx_ring) && qdisc_present) {
>>>> + netif_tx_stop_queue(queue);
>>>> + /* Re-peek and wake if the consumer drained the ring
>>>> + * concurrently in a race. smp_mb__after_atomic() pairs
>>>> + * with the test_and_clear_bit() of netif_wake_subqueue()
>>>> + * in __tun_wake_queue().
>>>> + */
>>>> + smp_mb__after_atomic();
>>>> + if (!__ptr_ring_produce_peek(&tfile->tx_ring))
>>>> + netif_tx_wake_queue(queue);
>>>> + }
>>>> + spin_unlock(&tfile->tx_ring.producer_lock);
>>>> +
>>>> + if (ret) {
>>>> + /* If a qdisc is attached to our virtual device,
>>>> + * returning NETDEV_TX_BUSY is allowed.
>>>> + */
>>>> + if (qdisc_present) {
>>>> + rcu_read_unlock();
>>>> + return NETDEV_TX_BUSY;
>>>> + }
>>>> drop_reason = SKB_DROP_REASON_FULL_RING;
>>>> goto drop;
>>>> }
>>>>
>>>> /* dev->lltx requires to do our own update of trans_start */
>>>> - queue = netdev_get_tx_queue(dev, txq);
>>>> txq_trans_cond_update(queue);
>>>>
>>>> /* Notify and wake up reader process */
>>>> --
>>>> 2.43.0
>>>
>
^ permalink raw reply
* Re: [PATCH net-next] net: phy: aquantia: use ADVERTISE_XNP for extended next page advertising
From: Andrew Lunn @ 2026-04-28 13:38 UTC (permalink / raw)
To: Maxime Chevallier
Cc: Jakub Kicinski, davem, Eric Dumazet, Paolo Abeni, Simon Horman,
Russell King, Heiner Kallweit, Vladimir Oltean, Camelia Groza,
thomas.petazzoni, netdev, linux-kernel
In-Reply-To: <20260428125827.238469-1-maxime.chevallier@bootlin.com>
On Tue, Apr 28, 2026 at 02:58:27PM +0200, Maxime Chevallier wrote:
> When configuring the link parameters in forced mode for the AQR-105, the
> Extended Next Page bit gets advertised for Multi-Gigabit modes.
>
> This is done through bit 12 of MDIO_AN_ADVERTISE in MDIO_MMD_AN. This
> contains a copy of the MII_ADVERTISE, for which 802.3 defines bit 12 as
> the Extended Next Page advertising. This bit used to be marked as
> reserved, but a proper define for it was added in :
>
> commit e7a62edd34b1 ("net: phy: qcom: at803x: Use the correct bit to disable extended next page")
>
> Let's use it instead of the ADVERTISE_RESV definition, making the code
> more self-documenting.
>
> Signed-off-by: Maxime Chevallier <maxime.chevallier@bootlin.com>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Andrew
^ permalink raw reply
* Re: [PATCH net] sfc: fix error code in efx_devlink_info_running_versions()
From: Edward Cree @ 2026-04-28 13:36 UTC (permalink / raw)
To: Dan Carpenter, Alejandro Lucero
Cc: Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, Martin Habets, Jiri Pirko, netdev, linux-net-drivers,
linux-kernel, kernel-janitors
In-Reply-To: <aeyEzO6C-v6J1VHH@stanley.mountain>
On 25/04/2026 10:09, Dan Carpenter wrote:
> Return -EINVAL if efx_mcdi_rpc() doesn't return enough space.
>
> Fixes: 14743ddd2495 ("sfc: add devlink info support for ef100")
> Signed-off-by: Dan Carpenter <error27@gmail.com>
> ---
> drivers/net/ethernet/sfc/efx_devlink.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/net/ethernet/sfc/efx_devlink.c b/drivers/net/ethernet/sfc/efx_devlink.c
> index d842c60dfc10..45f412bb9b5d 100644
> --- a/drivers/net/ethernet/sfc/efx_devlink.c
> +++ b/drivers/net/ethernet/sfc/efx_devlink.c
> @@ -531,7 +531,7 @@ static int efx_devlink_info_running_versions(struct efx_nic *efx,
> if (rc || outlength < MC_CMD_GET_VERSION_OUT_LEN) {
> netif_err(efx, drv, efx->net_dev,
> "mcdi MC_CMD_GET_VERSION failed\n");
> - return rc;
> + return rc ?: -EINVAL;
> }
>
> /* Handle previous output */
Usual practice in sfc is to use -EIO for 'MC response was too short'; it
signifies misbehaviour from the hardware, not any invalid input argument
as -EINVAL would suggest.
Other than that, looks fine.
-ed
^ permalink raw reply
* Re: [PATCH net] bridge: mcast: Fix a false positive lockdep splat
From: Simon Horman @ 2026-04-28 13:35 UTC (permalink / raw)
To: idosch
Cc: 'Simon Horman', netdev, bridge, davem, kuba, pabeni,
edumazet, razor, herbert, linus.luessing
In-Reply-To: <20260426133435.207006-1-idosch@nvidia.com>
From: 'Simon Horman' <horms@kernel.org>
This is an AI-generated review of your patch. The human sending this
email has considered the AI review valid, or at least plausible.
Full review at: https://sashiko.dev
---
bridge: mcast: Fix a false positive lockdep splat
This commit defers the transmission of multicast queries to a high priority
workqueue to avoid a false positive lockdep splat caused by nested bridge
multicast lock acquisitions. It queues skbs to a per-context query_queue
and flushes them asynchronously.
Closes: https://lore.kernel.org/netdev/000000000000c4c9d405f2643e01@google.com/
> diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c
> index 881d866d687a..252c46977ed5 100644
> --- a/net/bridge/br_multicast.c
> +++ b/net/bridge/br_multicast.c
[ ... ]
> @@ -1804,9 +1826,8 @@ static void __br_multicast_send_query(struct net_bridge_mcast *brmctx,
> skb->dev = pmctx->port->dev;
> br_multicast_count(brmctx->br, pmctx->port, skb, igmp_type,
> BR_MCAST_DIR_TX);
> - NF_HOOK(NFPROTO_BRIDGE, NF_BR_LOCAL_OUT,
> - dev_net(pmctx->port->dev), NULL, skb, NULL, skb->dev,
> - br_dev_queue_push_xmit);
> + skb_queue_tail(&pmctx->query_queue, skb);
> + queue_work(system_highpri_wq, &pmctx->query_queue_work);
Can this code cause an out-of-memory condition if flooded with IGMP/MLD
Leave packets?
In the IGMP data path, br_multicast_leave_group() is triggered for each
received Leave packet. If the bridge is the active querier, it directly calls
__br_multicast_send_query() for each packet, which allocates a new query skb
and queues it here using skb_queue_tail().
Because the workqueue execution handles TX networking overhead, could softirq
RX packet processing outpace the workqueue's ability to dequeue them?
Since skb_queue_tail() does not impose any limits on the queue length, it
looks like this might result in an unbounded accumulation of skbs in the
query queue, potentially bypassing standard qdisc backpressure mechanisms and
exhausting system memory.
>
> if (over_lmqt && with_srcs && sflag) {
> over_lmqt = false;
> @@ -1816,7 +1837,8 @@ static void __br_multicast_send_query(struct net_bridge_mcast *brmctx,
> br_multicast_select_own_querier(brmctx, group, skb);
> br_multicast_count(brmctx->br, NULL, skb, igmp_type,
> BR_MCAST_DIR_RX);
> - netif_rx(skb);
> + skb_queue_tail(&brmctx->query_queue, skb);
> + queue_work(system_highpri_wq, &brmctx->query_queue_work);
> }
> }
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox