Merge pull request #986 from kernelkit/mvpp2-tcam-fix

Fix `mvpp2` TCAM memory corruption
This commit is contained in:
Tobias Waldekranz
2025-03-19 16:13:13 +01:00
committed by GitHub
36 changed files with 651 additions and 68 deletions
+8
View File
@@ -3,6 +3,13 @@ Change Log
All notable changes to the project are documented in this file.
[v24.11.2][] - 2025-03-19
-------------------------
### Fixes
- Fix TCAM memory corruption in `mvpp2` Ethernet controller
[v24.11.1][] - 2024-11-29
-------------------------
@@ -1410,6 +1417,7 @@ Supported YANG models in addition to those used by sysrepo and netopeer:
[buildroot]: https://buildroot.org/
[UNRELEASED]: https://github.com/kernelkit/infix/compare/v24.11.0...HEAD
[v24.11.2]: https://github.com/kernelkit/infix/compare/v24.11.1...v24.11.2
[v24.11.1]: https://github.com/kernelkit/infix/compare/v24.11.0...v24.11.1
[v24.11.0]: https://github.com/kernelkit/infix/compare/v24.10.0...v24.11.0
[v24.10.2]: https://github.com/kernelkit/infix/compare/v24.10.1...v24.10.2
@@ -1,8 +1,8 @@
From 4be3e500b670f7b98e3dd6696b8e51e83f122c65 Mon Sep 17 00:00:00 2001
From: Christian Marangi <ansuelsmth@gmail.com>
Date: Thu, 25 Jan 2024 21:36:59 +0100
Subject: [PATCH 01/35] net: phy: add support for PHY LEDs polarity modes
Organization: Addiva Elektronik
Subject: [PATCH 01/36] net: phy: add support for PHY LEDs polarity modes
Organization: Wires
Add support for PHY LEDs polarity modes. Some PHY require LED to be set
to active low to be turned ON. Adds support for this by declaring
@@ -1,9 +1,9 @@
From 4833b140cd11a57dd9f59754cdacfd71bc564c8f Mon Sep 17 00:00:00 2001
From: Tobias Waldekranz <tobias@waldekranz.com>
Date: Mon, 4 Dec 2023 11:08:11 +0100
Subject: [PATCH 02/35] net: mvmdio: Support setting the MDC frequency on XSMI
Subject: [PATCH 02/36] net: mvmdio: Support setting the MDC frequency on XSMI
controllers
Organization: Addiva Elektronik
Organization: Wires
Support the standard "clock-frequency" attribute to set the generated
MDC frequency. If not specified, the driver will leave the divisor
@@ -1,9 +1,9 @@
From 50a2973e8a520a82e9f9ec15a1f69e059ce7a334 Mon Sep 17 00:00:00 2001
From: Tobias Waldekranz <tobias@waldekranz.com>
Date: Thu, 14 Dec 2023 14:50:23 +0100
Subject: [PATCH 03/35] net: dsa: mv88e6xxx: Create API to read a single stat
Subject: [PATCH 03/36] net: dsa: mv88e6xxx: Create API to read a single stat
counter
Organization: Addiva Elektronik
Organization: Wires
This change contains no functional change. We simply push the hardware
specific stats logic to a function reading a single counter, rather
@@ -1,8 +1,8 @@
From 5916503e23e7f85796c1f927747e66b9535bac53 Mon Sep 17 00:00:00 2001
From: Tobias Waldekranz <tobias@waldekranz.com>
Date: Thu, 14 Dec 2023 14:50:25 +0100
Subject: [PATCH 04/35] net: dsa: mv88e6xxx: Give each hw stat an ID
Organization: Addiva Elektronik
Subject: [PATCH 04/36] net: dsa: mv88e6xxx: Give each hw stat an ID
Organization: Wires
With the upcoming standard counter group support, we are no longer
reading out the whole set of counters, but rather mapping a subset to
@@ -1,9 +1,9 @@
From 32dda6562734ec8ee667bc546f3ef56794d5bf82 Mon Sep 17 00:00:00 2001
From: Tobias Waldekranz <tobias@waldekranz.com>
Date: Thu, 14 Dec 2023 14:50:26 +0100
Subject: [PATCH 05/35] net: dsa: mv88e6xxx: Add "eth-mac" counter group
Subject: [PATCH 05/36] net: dsa: mv88e6xxx: Add "eth-mac" counter group
support
Organization: Addiva Elektronik
Organization: Wires
Report the applicable subset of an mv88e6xxx port's counters using
ethtool's standardized "eth-mac" counter group.
@@ -1,9 +1,9 @@
From 36adbdd466ec550cab8b2ae54177f674c02cf631 Mon Sep 17 00:00:00 2001
From: Tobias Waldekranz <tobias@waldekranz.com>
Date: Thu, 14 Dec 2023 14:50:27 +0100
Subject: [PATCH 06/35] net: dsa: mv88e6xxx: Limit histogram counters to
Subject: [PATCH 06/36] net: dsa: mv88e6xxx: Limit histogram counters to
ingress traffic
Organization: Addiva Elektronik
Organization: Wires
Chips in this family only have one set of histogram counters, which
can be used to count ingressing and/or egressing traffic. mv88e6xxx
@@ -1,8 +1,8 @@
From abfa532c1149525b128b8c76d80965f55e208240 Mon Sep 17 00:00:00 2001
From: Tobias Waldekranz <tobias@waldekranz.com>
Date: Thu, 14 Dec 2023 14:50:28 +0100
Subject: [PATCH 07/35] net: dsa: mv88e6xxx: Add "rmon" counter group support
Organization: Addiva Elektronik
Subject: [PATCH 07/36] net: dsa: mv88e6xxx: Add "rmon" counter group support
Organization: Wires
Report the applicable subset of an mv88e6xxx port's counters using
ethtool's standardized "rmon" counter group.
@@ -1,8 +1,8 @@
From 4407b94b4a08536fccb6eea2826955ff12d63ec2 Mon Sep 17 00:00:00 2001
From: Tobias Waldekranz <tobias@waldekranz.com>
Date: Thu, 16 Nov 2023 19:44:32 +0100
Subject: [PATCH 09/35] net: dsa: mv88e6xxx: Add LED infrastructure
Organization: Addiva Elektronik
Subject: [PATCH 09/36] net: dsa: mv88e6xxx: Add LED infrastructure
Organization: Wires
Parse DT for LEDs and register them for devices that support it,
though no actual implementations exist yet.
@@ -1,8 +1,8 @@
From a5cf5c0353db07e74d7a29dd4d5c2cb7775d5bec Mon Sep 17 00:00:00 2001
From: Tobias Waldekranz <tobias@waldekranz.com>
Date: Thu, 16 Nov 2023 21:59:35 +0100
Subject: [PATCH 10/35] net: dsa: mv88e6xxx: Add LED support for 6393X
Organization: Addiva Elektronik
Subject: [PATCH 10/36] net: dsa: mv88e6xxx: Add LED support for 6393X
Organization: Wires
Trigger support:
- "none"
@@ -1,9 +1,9 @@
From be94ec851dbb8e55c3f5e82f197b2dc59566aea2 Mon Sep 17 00:00:00 2001
From: Tobias Waldekranz <tobias@waldekranz.com>
Date: Tue, 12 Mar 2024 10:27:24 +0100
Subject: [PATCH 11/35] net: dsa: mv88e6xxx: Fix timeout on waiting for PPU on
Subject: [PATCH 11/36] net: dsa: mv88e6xxx: Fix timeout on waiting for PPU on
6393X
Organization: Addiva Elektronik
Organization: Wires
In a multi-chip setup, delays of up to 750ms are observed before the
device (6393X) signals completion of PPU initialization (Global 1,
@@ -1,9 +1,9 @@
From 69092f83541e6539ab82eec3052325c403675de4 Mon Sep 17 00:00:00 2001
From: Tobias Waldekranz <tobias@waldekranz.com>
Date: Tue, 16 Jan 2024 16:00:55 +0100
Subject: [PATCH 12/35] net: dsa: Support MDB memberships whose L2 addresses
Subject: [PATCH 12/36] net: dsa: Support MDB memberships whose L2 addresses
overlap
Organization: Addiva Elektronik
Organization: Wires
Multiple IP multicast groups (32 for v4, 2^80 for v6) map to the same
L2 address. This means that switchdev drivers may receive multiple MDB
@@ -1,9 +1,9 @@
From 7c19df77212d0728874515e97cf297863a6ff2cd Mon Sep 17 00:00:00 2001
From: Tobias Waldekranz <tobias@waldekranz.com>
Date: Tue, 19 Sep 2023 18:38:10 +0200
Subject: [PATCH 13/35] net: phy: marvell10g: Support firmware loading on
Subject: [PATCH 13/36] net: phy: marvell10g: Support firmware loading on
88X3310
Organization: Addiva Elektronik
Organization: Wires
When probing, if a device is waiting for firmware to be loaded into
its RAM, ask userspace for the binary and load it over XMDIO.
@@ -1,9 +1,9 @@
From 0c34b42b7a72ddf1af6f3534870d647801e493fa Mon Sep 17 00:00:00 2001
From: Tobias Waldekranz <tobias@waldekranz.com>
Date: Tue, 21 Nov 2023 20:15:24 +0100
Subject: [PATCH 14/35] net: phy: marvell10g: Fix power-up when strapped to
Subject: [PATCH 14/36] net: phy: marvell10g: Fix power-up when strapped to
start powered down
Organization: Addiva Elektronik
Organization: Wires
On devices which are hardware strapped to start powered down (PDSTATE
== 1), make sure that we clear the power-down bit on all units
@@ -1,8 +1,8 @@
From 6576918d3348f8e20802379d568d7632228af4d7 Mon Sep 17 00:00:00 2001
From: Tobias Waldekranz <tobias@waldekranz.com>
Date: Wed, 15 Nov 2023 20:58:42 +0100
Subject: [PATCH 15/35] net: phy: marvell10g: Add LED support for 88X3310
Organization: Addiva Elektronik
Subject: [PATCH 15/36] net: phy: marvell10g: Add LED support for 88X3310
Organization: Wires
Pickup the LEDs from the state in which the hardware reset or
bootloader left them, but also support further configuration via
@@ -1,9 +1,9 @@
From 1ad7f010e46133c725df5cab4d85f71f689ca191 Mon Sep 17 00:00:00 2001
From: Tobias Waldekranz <tobias@waldekranz.com>
Date: Tue, 12 Dec 2023 09:51:05 +0100
Subject: [PATCH 16/35] net: phy: marvell10g: Support LEDs tied to a single
Subject: [PATCH 16/36] net: phy: marvell10g: Support LEDs tied to a single
media side
Organization: Addiva Elektronik
Organization: Wires
In a combo-port setup, i.e. where both the copper and fiber interface
are available to the user, the LEDs may be physically located either
@@ -1,9 +1,9 @@
From 11b9a3e328241edede03b6615bb9b0f1a40b9b7d Mon Sep 17 00:00:00 2001
From: Tobias Waldekranz <tobias@waldekranz.com>
Date: Fri, 24 Nov 2023 23:29:55 +0100
Subject: [PATCH 17/35] nvmem: layouts: onie-tlv: Let device probe even when
Subject: [PATCH 17/36] nvmem: layouts: onie-tlv: Let device probe even when
TLV is invalid
Organization: Addiva Elektronik
Organization: Wires
Before this change, probing an NVMEM device, expected to contain a
valid TLV, would fail if it had not been provisioned yet. But an
@@ -1,9 +1,9 @@
From ce1148b5c2e33541ad13ff2c4769d0b37d4e42b9 Mon Sep 17 00:00:00 2001
From: Joachim Wiberg <troglobit@gmail.com>
Date: Mon, 4 Mar 2024 16:47:28 +0100
Subject: [PATCH 18/35] net: bridge: avoid classifying unknown multicast as
Subject: [PATCH 18/36] net: bridge: avoid classifying unknown multicast as
mrouters_only
Organization: Addiva Elektronik
Organization: Wires
Unknown multicast, MAC/IPv4/IPv6, should always be flooded according to
the per-port mcast_flood setting, as well as to detected and configured
@@ -1,9 +1,9 @@
From ce74ee8c5461cc53851ca323b4dfc9937cab0e41 Mon Sep 17 00:00:00 2001
From: Joachim Wiberg <troglobit@gmail.com>
Date: Tue, 5 Mar 2024 06:44:41 +0100
Subject: [PATCH 19/35] net: bridge: Ignore router ports when forwarding L2
Subject: [PATCH 19/36] net: bridge: Ignore router ports when forwarding L2
multicast
Organization: Addiva Elektronik
Organization: Wires
Multicast router ports are either statically configured or learned from
control protocol traffic (IGMP/MLD/PIM). These protocols regulate IP
@@ -1,8 +1,8 @@
From 3c9b05198e0b7193f2dcddc1860cd77f0adbc3a2 Mon Sep 17 00:00:00 2001
From: Tobias Waldekranz <tobias@waldekranz.com>
Date: Thu, 21 Mar 2024 19:12:15 +0100
Subject: [PATCH 20/35] net: dsa: Support EtherType based priority overrides
Organization: Addiva Elektronik
Subject: [PATCH 20/36] net: dsa: Support EtherType based priority overrides
Organization: Wires
Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com>
---
@@ -1,9 +1,9 @@
From 333134a4ff2b8dd7fb00a75560254de96d1082ad Mon Sep 17 00:00:00 2001
From: Tobias Waldekranz <tobias@waldekranz.com>
Date: Fri, 22 Mar 2024 16:15:43 +0100
Subject: [PATCH 21/35] net: dsa: mv88e6xxx: Support EtherType based priority
Subject: [PATCH 21/36] net: dsa: mv88e6xxx: Support EtherType based priority
overrides
Organization: Addiva Elektronik
Organization: Wires
Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com>
---
@@ -1,8 +1,8 @@
From cdddc24c05cedc0d0fabc48da17ec26aeb7c1ef9 Mon Sep 17 00:00:00 2001
From: Tobias Waldekranz <tobias@waldekranz.com>
Date: Wed, 27 Mar 2024 10:10:19 +0100
Subject: [PATCH 22/35] net: phy: Do not resume PHY when attaching
Organization: Addiva Elektronik
Subject: [PATCH 22/36] net: phy: Do not resume PHY when attaching
Organization: Wires
The PHY should not start negotiating with its link-partner until
explicitly instructed to do so.
@@ -1,9 +1,9 @@
From 1ec21a3fc54fb447501fd7edbf692b00a31fe3ec Mon Sep 17 00:00:00 2001
From: Tobias Waldekranz <tobias@waldekranz.com>
Date: Wed, 27 Mar 2024 15:52:43 +0100
Subject: [PATCH 23/35] net: dsa: mv88e6xxx: Improve indirect register access
Subject: [PATCH 23/36] net: dsa: mv88e6xxx: Improve indirect register access
perf on 6393
Organization: Addiva Elektronik
Organization: Wires
When operating in multi-chip mode, the 6393 family maps a subset of
commonly used global registers to the outermost address space (in
@@ -1,9 +1,9 @@
From 5d7be493dcaa75ee69d521043062389d7772f8dc Mon Sep 17 00:00:00 2001
From: Joachim Wiberg <troglobit@gmail.com>
Date: Thu, 4 Apr 2024 16:36:30 +0200
Subject: [PATCH 24/35] net: bridge: drop delay for applying strict multicast
Subject: [PATCH 24/36] net: bridge: drop delay for applying strict multicast
filtering
Organization: Addiva Elektronik
Organization: Wires
This *local* patch drops the initial delay before applying strict multicast
filtering, introduced in [1] and recently updated in [2].
@@ -1,9 +1,9 @@
From 492a824661dbc188b5abeb7434b5cf67c2016415 Mon Sep 17 00:00:00 2001
From: Tobias Waldekranz <tobias@waldekranz.com>
Date: Mon, 22 Apr 2024 23:18:01 +0200
Subject: [PATCH 25/35] net: dsa: mv88e6xxx: Honor ports being managed via
Subject: [PATCH 25/36] net: dsa: mv88e6xxx: Honor ports being managed via
in-band-status
Organization: Addiva Elektronik
Organization: Wires
Keep all link parameters in their unforced states when the port is
declared as being managed via in-band-status, and let the MAC
@@ -1,8 +1,8 @@
From c9c9597a47b00b720f5223c83ab05bb89481eda8 Mon Sep 17 00:00:00 2001
From: Tobias Waldekranz <tobias@waldekranz.com>
Date: Wed, 24 Apr 2024 21:35:26 +0200
Subject: [PATCH 26/35] net: dsa: mv88e6xxx: Fix port policy config on 6393X
Organization: Addiva Elektronik
Subject: [PATCH 26/36] net: dsa: mv88e6xxx: Fix port policy config on 6393X
Organization: Wires
mv88e6393x_port_policy_{read,write} expect the `pointer` argument to
be "pre-shifted" 8 bits.
@@ -1,9 +1,9 @@
From 4ff224b5f5de1347a1f686aa85cb918a7db18879 Mon Sep 17 00:00:00 2001
From: Tobias Waldekranz <tobias@waldekranz.com>
Date: Wed, 24 Apr 2024 22:41:04 +0200
Subject: [PATCH 27/35] net: dsa: mv88e6xxx: Limit rsvd2cpu policy to user
Subject: [PATCH 27/36] net: dsa: mv88e6xxx: Limit rsvd2cpu policy to user
ports on 6393X
Organization: Addiva Elektronik
Organization: Wires
For packets with a DA in the IEEE reserved L2 group range, originating
from a CPU, forward it as normal, rather than classifying it as
@@ -1,8 +1,8 @@
From f0d4beabe769fec594b309c3f1ebb79cfdbede8b Mon Sep 17 00:00:00 2001
From: Joachim Wiberg <troglobit@gmail.com>
Date: Mon, 29 Apr 2024 15:14:51 +0200
Subject: [PATCH 28/35] usb: core: adjust log level for unauthorized devices
Organization: Addiva Elektronik
Subject: [PATCH 28/36] usb: core: adjust log level for unauthorized devices
Organization: Wires
The fact that a USB device currently is not authorized is not an error,
so let's adjust the log level so these messages slip below radar for the
@@ -1,9 +1,9 @@
From 5f96d718c850084504c53ec0b8d9fcf75ea9996c Mon Sep 17 00:00:00 2001
From: Tobias Waldekranz <tobias@waldekranz.com>
Date: Wed, 15 May 2024 13:50:58 +0200
Subject: [PATCH 29/35] net: dsa: mv88e6xxx: Grab register lock during counter
Subject: [PATCH 29/36] net: dsa: mv88e6xxx: Grab register lock during counter
snapshotting
Organization: Addiva Elektronik
Organization: Wires
This was missing for the standard counter groups. Since no caller
already holds the lock, opt for pushing the locking down into
@@ -1,9 +1,9 @@
From 6d4c436335003259cc02a0f015fd3d1d54e988a2 Mon Sep 17 00:00:00 2001
From: Tobias Waldekranz <tobias@waldekranz.com>
Date: Thu, 16 May 2024 14:51:54 +0200
Subject: [PATCH 30/35] net: bridge: Differentiate MDB additions from
Subject: [PATCH 30/36] net: bridge: Differentiate MDB additions from
modifications
Organization: Addiva Elektronik
Organization: Wires
Before this change, the reception of an IGMPv3 report (and analogously
for MLDv2) that adds a new group, would trigger two MDB RTM_NEWMDB
@@ -1,9 +1,9 @@
From c333c612688d5e974b95fcf4b04f185d7cf4f80d Mon Sep 17 00:00:00 2001
From: Tobias Waldekranz <tobias@waldekranz.com>
Date: Tue, 28 May 2024 10:38:42 +0200
Subject: [PATCH 31/35] net: dsa: tag_dsa: Use tag priority as initial
Subject: [PATCH 31/36] net: dsa: tag_dsa: Use tag priority as initial
skb->priority
Organization: Addiva Elektronik
Organization: Wires
Use the 3-bit priority field from the DSA tag as the initial packet
priority on ingress to the CPU.
@@ -1,8 +1,8 @@
From 18c025745fd8b8c9b3e688e9d78668a56cf71217 Mon Sep 17 00:00:00 2001
From: Tobias Waldekranz <tobias@waldekranz.com>
Date: Tue, 28 May 2024 11:04:22 +0200
Subject: [PATCH 32/35] net: dsa: mv88e6xxx: Add mqprio qdisc support
Organization: Addiva Elektronik
Subject: [PATCH 32/36] net: dsa: mv88e6xxx: Add mqprio qdisc support
Organization: Wires
Add support for attaching mqprio qdisc's to mv88e6xxx ports and use
the packet's traffic class as the outgoing priority when no PCP bits
@@ -1,9 +1,9 @@
From f2d4ff12c7a0e644cbeac6675b755fb4a87b362a Mon Sep 17 00:00:00 2001
From: Tobias Waldekranz <tobias@waldekranz.com>
Date: Wed, 29 May 2024 13:20:41 +0200
Subject: [PATCH 33/35] net: dsa: mv88e6xxx: Use VLAN prio over IP when both
Subject: [PATCH 33/36] net: dsa: mv88e6xxx: Use VLAN prio over IP when both
are available
Organization: Addiva Elektronik
Organization: Wires
Switch the priority sourcing precdence to prefer VLAN PCP over IP
DSCP, when both are available.
@@ -1,9 +1,9 @@
From ceaaa4f44f9b3ec82c4e0a24c2322aae58fa3aa0 Mon Sep 17 00:00:00 2001
From: Joachim Wiberg <troglobit@gmail.com>
Date: Wed, 6 Nov 2024 15:39:33 +0100
Subject: [PATCH 34/35] net: dsa: mb88e6xxx: use EOPNOTSUPP for unsupported
Subject: [PATCH 34/36] net: dsa: mb88e6xxx: use EOPNOTSUPP for unsupported
flags
Organization: Addiva Elektronik
Organization: Wires
Make sure to return correct error code for unsupported flags, and
propagate any error.
@@ -1,8 +1,8 @@
From ab93e65511ee508d1b637e4ad0dc6dcddd2c48dc Mon Sep 17 00:00:00 2001
From: Tobias Waldekranz <tobias@waldekranz.com>
Date: Tue, 26 Nov 2024 19:45:59 +0100
Subject: [PATCH 35/35] net: dsa: mv88e6xxx: Trap locally terminated VLANs
Organization: Addiva Elektronik
Subject: [PATCH 35/36] net: dsa: mv88e6xxx: Trap locally terminated VLANs
Organization: Wires
Before this change, in a setup like the following, packets assigned to
VLAN 10 were forwarded between the switch ports, even though the
@@ -0,0 +1,575 @@
From 1527d6234666b2d275edaa9662f222214e030c41 Mon Sep 17 00:00:00 2001
From: Tobias Waldekranz <tobias@waldekranz.com>
Date: Tue, 18 Mar 2025 10:55:09 +0100
Subject: [PATCH 36/36] net: mvpp2: Prevent parser TCAM memory corruption
Organization: Wires
Protect the parser TCAM/SRAM memory, and the cached (shadow) SRAM
information, from concurrent modifications.
Both the TCAM and SRAM tables are indirectly accessed by configuring
an index register that selects the row to read or write to. This means
that operations must be atomic in order to, e.g., avoid spreading
writes across multiple rows. Since the shadow SRAM array is used to
find free rows in the hardware table, it must also be protected in
order to avoid TOCTOU errors where multiple cores allocate the same
row.
This issue was detected in a situation where `mvpp2_set_rx_mode()` ran
concurrently on two CPUs. In this particular case the
MVPP2_PE_MAC_UC_PROMISCUOUS entry was corrupted, causing the
classifier unit to drop all incoming unicast - indicated by the
`rx_classifier_drops` counter.
Fixes: 3f518509dedc ("ethernet: Add new driver for Marvell Armada 375 network unit")
Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com>
---
drivers/net/ethernet/marvell/mvpp2/mvpp2.h | 3 +-
.../net/ethernet/marvell/mvpp2/mvpp2_main.c | 3 +-
.../net/ethernet/marvell/mvpp2/mvpp2_prs.c | 146 ++++++++++++++----
3 files changed, 118 insertions(+), 34 deletions(-)
diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2.h b/drivers/net/ethernet/marvell/mvpp2/mvpp2.h
index e809f91c08fb..d980b8799d95 100644
--- a/drivers/net/ethernet/marvell/mvpp2/mvpp2.h
+++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2.h
@@ -1106,8 +1106,9 @@ struct mvpp2 {
/* Global TX Flow Control config */
bool global_tx_fc;
- /* Spinlocks for CM3 shared memory configuration */
+ /* Spinlocks for shared packet processor functional units */
spinlock_t mss_spinlock;
+ spinlock_t prs_spinlock;
};
struct mvpp2_pcpu_stats {
diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
index 34051c9abd97..0e69faedbf97 100644
--- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
+++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
@@ -7615,8 +7615,9 @@ static int mvpp2_probe(struct platform_device *pdev)
if (mvpp2_read(priv, MVPP2_VER_ID_REG) == MVPP2_VER_PP23)
priv->hw_version = MVPP23;
- /* Init mss lock */
+ /* Init shared packet processor functional unit locks */
spin_lock_init(&priv->mss_spinlock);
+ spin_lock_init(&priv->prs_spinlock);
/* Initialize network controller */
err = mvpp2_init(pdev, priv);
diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2_prs.c b/drivers/net/ethernet/marvell/mvpp2/mvpp2_prs.c
index 9af22f497a40..aa834153d99f 100644
--- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_prs.c
+++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_prs.c
@@ -43,8 +43,8 @@ static int mvpp2_prs_hw_write(struct mvpp2 *priv, struct mvpp2_prs_entry *pe)
}
/* Initialize tcam entry from hw */
-int mvpp2_prs_init_from_hw(struct mvpp2 *priv, struct mvpp2_prs_entry *pe,
- int tid)
+static int mvpp2_prs_init_from_hw_unlocked(struct mvpp2 *priv,
+ struct mvpp2_prs_entry *pe, int tid)
{
int i;
@@ -73,6 +73,19 @@ int mvpp2_prs_init_from_hw(struct mvpp2 *priv, struct mvpp2_prs_entry *pe,
return 0;
}
+int mvpp2_prs_init_from_hw(struct mvpp2 *priv, struct mvpp2_prs_entry *pe,
+ int tid)
+{
+ unsigned long flags;
+ int err;
+
+ spin_lock_irqsave(&priv->prs_spinlock, flags);
+ err = mvpp2_prs_init_from_hw_unlocked(priv, pe, tid);
+ spin_unlock_irqrestore(&priv->prs_spinlock, flags);
+
+ return err;
+}
+
/* Invalidate tcam hw entry */
static void mvpp2_prs_hw_inv(struct mvpp2 *priv, int index)
{
@@ -374,7 +387,7 @@ static int mvpp2_prs_flow_find(struct mvpp2 *priv, int flow)
priv->prs_shadow[tid].lu != MVPP2_PRS_LU_FLOWS)
continue;
- mvpp2_prs_init_from_hw(priv, &pe, tid);
+ mvpp2_prs_init_from_hw_unlocked(priv, &pe, tid);
bits = mvpp2_prs_sram_ai_get(&pe);
/* Sram store classification lookup ID in AI bits [5:0] */
@@ -441,7 +454,7 @@ static void mvpp2_prs_mac_drop_all_set(struct mvpp2 *priv, int port, bool add)
if (priv->prs_shadow[MVPP2_PE_DROP_ALL].valid) {
/* Entry exist - update port only */
- mvpp2_prs_init_from_hw(priv, &pe, MVPP2_PE_DROP_ALL);
+ mvpp2_prs_init_from_hw_unlocked(priv, &pe, MVPP2_PE_DROP_ALL);
} else {
/* Entry doesn't exist - create new */
memset(&pe, 0, sizeof(pe));
@@ -474,9 +487,12 @@ void mvpp2_prs_mac_promisc_set(struct mvpp2 *priv, int port,
{
struct mvpp2_prs_entry pe;
unsigned char cast_match;
+ unsigned long flags;
unsigned int ri;
int tid;
+ spin_lock_irqsave(&priv->prs_spinlock, flags);
+
if (l2_cast == MVPP2_PRS_L2_UNI_CAST) {
cast_match = MVPP2_PRS_UCAST_VAL;
tid = MVPP2_PE_MAC_UC_PROMISCUOUS;
@@ -489,7 +505,7 @@ void mvpp2_prs_mac_promisc_set(struct mvpp2 *priv, int port,
/* promiscuous mode - Accept unknown unicast or multicast packets */
if (priv->prs_shadow[tid].valid) {
- mvpp2_prs_init_from_hw(priv, &pe, tid);
+ mvpp2_prs_init_from_hw_unlocked(priv, &pe, tid);
} else {
memset(&pe, 0, sizeof(pe));
mvpp2_prs_tcam_lu_set(&pe, MVPP2_PRS_LU_MAC);
@@ -520,6 +536,8 @@ void mvpp2_prs_mac_promisc_set(struct mvpp2 *priv, int port,
mvpp2_prs_tcam_port_set(&pe, port, add);
mvpp2_prs_hw_write(priv, &pe);
+
+ spin_unlock_irqrestore(&priv->prs_spinlock, flags);
}
/* Set entry for dsa packets */
@@ -539,7 +557,7 @@ static void mvpp2_prs_dsa_tag_set(struct mvpp2 *priv, int port, bool add,
if (priv->prs_shadow[tid].valid) {
/* Entry exist - update port only */
- mvpp2_prs_init_from_hw(priv, &pe, tid);
+ mvpp2_prs_init_from_hw_unlocked(priv, &pe, tid);
} else {
/* Entry doesn't exist - create new */
memset(&pe, 0, sizeof(pe));
@@ -610,7 +628,7 @@ static void mvpp2_prs_dsa_tag_ethertype_set(struct mvpp2 *priv, int port,
if (priv->prs_shadow[tid].valid) {
/* Entry exist - update port only */
- mvpp2_prs_init_from_hw(priv, &pe, tid);
+ mvpp2_prs_init_from_hw_unlocked(priv, &pe, tid);
} else {
/* Entry doesn't exist - create new */
memset(&pe, 0, sizeof(pe));
@@ -673,7 +691,7 @@ static int mvpp2_prs_vlan_find(struct mvpp2 *priv, unsigned short tpid, int ai)
priv->prs_shadow[tid].lu != MVPP2_PRS_LU_VLAN)
continue;
- mvpp2_prs_init_from_hw(priv, &pe, tid);
+ mvpp2_prs_init_from_hw_unlocked(priv, &pe, tid);
match = mvpp2_prs_tcam_data_cmp(&pe, 0, tpid);
if (!match)
continue;
@@ -726,7 +744,7 @@ static int mvpp2_prs_vlan_add(struct mvpp2 *priv, unsigned short tpid, int ai,
priv->prs_shadow[tid_aux].lu != MVPP2_PRS_LU_VLAN)
continue;
- mvpp2_prs_init_from_hw(priv, &pe, tid_aux);
+ mvpp2_prs_init_from_hw_unlocked(priv, &pe, tid_aux);
ri_bits = mvpp2_prs_sram_ri_get(&pe);
if ((ri_bits & MVPP2_PRS_RI_VLAN_MASK) ==
MVPP2_PRS_RI_VLAN_DOUBLE)
@@ -760,7 +778,7 @@ static int mvpp2_prs_vlan_add(struct mvpp2 *priv, unsigned short tpid, int ai,
mvpp2_prs_shadow_set(priv, pe.index, MVPP2_PRS_LU_VLAN);
} else {
- mvpp2_prs_init_from_hw(priv, &pe, tid);
+ mvpp2_prs_init_from_hw_unlocked(priv, &pe, tid);
}
/* Update ports' mask */
mvpp2_prs_tcam_port_map_set(&pe, port_map);
@@ -800,7 +818,7 @@ static int mvpp2_prs_double_vlan_find(struct mvpp2 *priv, unsigned short tpid1,
priv->prs_shadow[tid].lu != MVPP2_PRS_LU_VLAN)
continue;
- mvpp2_prs_init_from_hw(priv, &pe, tid);
+ mvpp2_prs_init_from_hw_unlocked(priv, &pe, tid);
match = mvpp2_prs_tcam_data_cmp(&pe, 0, tpid1) &&
mvpp2_prs_tcam_data_cmp(&pe, 4, tpid2);
@@ -849,7 +867,7 @@ static int mvpp2_prs_double_vlan_add(struct mvpp2 *priv, unsigned short tpid1,
priv->prs_shadow[tid_aux].lu != MVPP2_PRS_LU_VLAN)
continue;
- mvpp2_prs_init_from_hw(priv, &pe, tid_aux);
+ mvpp2_prs_init_from_hw_unlocked(priv, &pe, tid_aux);
ri_bits = mvpp2_prs_sram_ri_get(&pe);
ri_bits &= MVPP2_PRS_RI_VLAN_MASK;
if (ri_bits == MVPP2_PRS_RI_VLAN_SINGLE ||
@@ -880,7 +898,7 @@ static int mvpp2_prs_double_vlan_add(struct mvpp2 *priv, unsigned short tpid1,
mvpp2_prs_shadow_set(priv, pe.index, MVPP2_PRS_LU_VLAN);
} else {
- mvpp2_prs_init_from_hw(priv, &pe, tid);
+ mvpp2_prs_init_from_hw_unlocked(priv, &pe, tid);
}
/* Update ports' mask */
@@ -1941,7 +1959,7 @@ static int mvpp2_prs_vid_range_find(struct mvpp2_port *port, u16 vid, u16 mask)
port->priv->prs_shadow[tid].lu != MVPP2_PRS_LU_VID)
continue;
- mvpp2_prs_init_from_hw(port->priv, &pe, tid);
+ mvpp2_prs_init_from_hw_unlocked(port->priv, &pe, tid);
mvpp2_prs_tcam_data_byte_get(&pe, 2, &byte[0], &enable[0]);
mvpp2_prs_tcam_data_byte_get(&pe, 3, &byte[1], &enable[1]);
@@ -1966,10 +1984,13 @@ int mvpp2_prs_vid_entry_add(struct mvpp2_port *port, u16 vid)
unsigned int mask = 0xfff, reg_val, shift;
struct mvpp2 *priv = port->priv;
struct mvpp2_prs_entry pe;
+ unsigned long flags;
int tid;
memset(&pe, 0, sizeof(pe));
+ spin_lock_irqsave(&priv->prs_spinlock, flags);
+
/* Scan TCAM and see if entry with this <vid,port> already exist */
tid = mvpp2_prs_vid_range_find(port, vid, mask);
@@ -1988,8 +2009,10 @@ int mvpp2_prs_vid_entry_add(struct mvpp2_port *port, u16 vid)
MVPP2_PRS_VLAN_FILT_MAX_ENTRY);
/* There isn't room for a new VID filter */
- if (tid < 0)
+ if (tid < 0) {
+ spin_unlock_irqrestore(&priv->prs_spinlock, flags);
return tid;
+ }
mvpp2_prs_tcam_lu_set(&pe, MVPP2_PRS_LU_VID);
pe.index = tid;
@@ -1997,7 +2020,7 @@ int mvpp2_prs_vid_entry_add(struct mvpp2_port *port, u16 vid)
/* Mask all ports */
mvpp2_prs_tcam_port_map_set(&pe, 0);
} else {
- mvpp2_prs_init_from_hw(priv, &pe, tid);
+ mvpp2_prs_init_from_hw_unlocked(priv, &pe, tid);
}
/* Enable the current port */
@@ -2019,6 +2042,7 @@ int mvpp2_prs_vid_entry_add(struct mvpp2_port *port, u16 vid)
mvpp2_prs_shadow_set(priv, pe.index, MVPP2_PRS_LU_VID);
mvpp2_prs_hw_write(priv, &pe);
+ spin_unlock_irqrestore(&priv->prs_spinlock, flags);
return 0;
}
@@ -2026,25 +2050,30 @@ int mvpp2_prs_vid_entry_add(struct mvpp2_port *port, u16 vid)
void mvpp2_prs_vid_entry_remove(struct mvpp2_port *port, u16 vid)
{
struct mvpp2 *priv = port->priv;
+ unsigned long flags;
int tid;
- /* Scan TCAM and see if entry with this <vid,port> already exist */
- tid = mvpp2_prs_vid_range_find(port, vid, 0xfff);
+ spin_lock_irqsave(&priv->prs_spinlock, flags);
- /* No such entry */
- if (tid < 0)
- return;
+ /* Invalidate TCAM entry with this <vid,port>, if it exists */
+ tid = mvpp2_prs_vid_range_find(port, vid, 0xfff);
+ if (tid >= 0) {
+ mvpp2_prs_hw_inv(priv, tid);
+ priv->prs_shadow[tid].valid = false;
+ }
- mvpp2_prs_hw_inv(priv, tid);
- priv->prs_shadow[tid].valid = false;
+ spin_unlock_irqrestore(&priv->prs_spinlock, flags);
}
/* Remove all existing VID filters on this port */
void mvpp2_prs_vid_remove_all(struct mvpp2_port *port)
{
struct mvpp2 *priv = port->priv;
+ unsigned long flags;
int tid;
+ spin_lock_irqsave(&priv->prs_spinlock, flags);
+
for (tid = MVPP2_PRS_VID_PORT_FIRST(port->id);
tid <= MVPP2_PRS_VID_PORT_LAST(port->id); tid++) {
if (priv->prs_shadow[tid].valid) {
@@ -2052,6 +2081,8 @@ void mvpp2_prs_vid_remove_all(struct mvpp2_port *port)
priv->prs_shadow[tid].valid = false;
}
}
+
+ spin_unlock_irqrestore(&priv->prs_spinlock, flags);
}
/* Remove VID filering entry for this port */
@@ -2059,11 +2090,16 @@ void mvpp2_prs_vid_disable_filtering(struct mvpp2_port *port)
{
unsigned int tid = MVPP2_PRS_VID_PORT_DFLT(port->id);
struct mvpp2 *priv = port->priv;
+ unsigned long flags;
+
+ spin_lock_irqsave(&priv->prs_spinlock, flags);
/* Invalidate the guard entry */
mvpp2_prs_hw_inv(priv, tid);
priv->prs_shadow[tid].valid = false;
+
+ spin_unlock_irqrestore(&priv->prs_spinlock, flags);
}
/* Add guard entry that drops packets when no VID is matched on this port */
@@ -2073,12 +2109,15 @@ void mvpp2_prs_vid_enable_filtering(struct mvpp2_port *port)
struct mvpp2 *priv = port->priv;
unsigned int reg_val, shift;
struct mvpp2_prs_entry pe;
+ unsigned long flags;
if (priv->prs_shadow[tid].valid)
return;
memset(&pe, 0, sizeof(pe));
+ spin_lock_irqsave(&priv->prs_spinlock, flags);
+
pe.index = tid;
reg_val = mvpp2_read(priv, MVPP2_MH_REG(port->id));
@@ -2111,6 +2150,8 @@ void mvpp2_prs_vid_enable_filtering(struct mvpp2_port *port)
/* Update shadow table */
mvpp2_prs_shadow_set(priv, pe.index, MVPP2_PRS_LU_VID);
mvpp2_prs_hw_write(priv, &pe);
+
+ spin_unlock_irqrestore(&priv->prs_spinlock, flags);
}
/* Parser default initialization */
@@ -2217,7 +2258,7 @@ mvpp2_prs_mac_da_range_find(struct mvpp2 *priv, int pmap, const u8 *da,
(priv->prs_shadow[tid].udf != udf_type))
continue;
- mvpp2_prs_init_from_hw(priv, &pe, tid);
+ mvpp2_prs_init_from_hw_unlocked(priv, &pe, tid);
entry_pmap = mvpp2_prs_tcam_port_map_get(&pe);
if (mvpp2_prs_mac_range_equals(&pe, da, mask) &&
@@ -2229,7 +2270,8 @@ mvpp2_prs_mac_da_range_find(struct mvpp2 *priv, int pmap, const u8 *da,
}
/* Update parser's mac da entry */
-int mvpp2_prs_mac_da_accept(struct mvpp2_port *port, const u8 *da, bool add)
+static int mvpp2_prs_mac_da_accept_unlocked(struct mvpp2_port *port,
+ const u8 *da, bool add)
{
unsigned char mask[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
struct mvpp2 *priv = port->priv;
@@ -2261,7 +2303,7 @@ int mvpp2_prs_mac_da_accept(struct mvpp2_port *port, const u8 *da, bool add)
/* Mask all ports */
mvpp2_prs_tcam_port_map_set(&pe, 0);
} else {
- mvpp2_prs_init_from_hw(priv, &pe, tid);
+ mvpp2_prs_init_from_hw_unlocked(priv, &pe, tid);
}
mvpp2_prs_tcam_lu_set(&pe, MVPP2_PRS_LU_MAC);
@@ -2317,6 +2359,18 @@ int mvpp2_prs_mac_da_accept(struct mvpp2_port *port, const u8 *da, bool add)
return 0;
}
+int mvpp2_prs_mac_da_accept(struct mvpp2_port *port, const u8 *da, bool add)
+{
+ unsigned long flags;
+ int err;
+
+ spin_lock_irqsave(&port->priv->prs_spinlock, flags);
+ err = mvpp2_prs_mac_da_accept_unlocked(port, da, add);
+ spin_unlock_irqrestore(&port->priv->prs_spinlock, flags);
+
+ return err;
+}
+
int mvpp2_prs_update_mac_da(struct net_device *dev, const u8 *da)
{
struct mvpp2_port *port = netdev_priv(dev);
@@ -2342,9 +2396,11 @@ void mvpp2_prs_mac_del_all(struct mvpp2_port *port)
{
struct mvpp2 *priv = port->priv;
struct mvpp2_prs_entry pe;
- unsigned long pmap;
+ unsigned long flags, pmap;
int index, tid;
+ spin_lock_irqsave(&priv->prs_spinlock, flags);
+
for (tid = MVPP2_PE_MAC_RANGE_START;
tid <= MVPP2_PE_MAC_RANGE_END; tid++) {
unsigned char da[ETH_ALEN], da_mask[ETH_ALEN];
@@ -2354,7 +2410,7 @@ void mvpp2_prs_mac_del_all(struct mvpp2_port *port)
(priv->prs_shadow[tid].udf != MVPP2_PRS_UDF_MAC_DEF))
continue;
- mvpp2_prs_init_from_hw(priv, &pe, tid);
+ mvpp2_prs_init_from_hw_unlocked(priv, &pe, tid);
pmap = mvpp2_prs_tcam_port_map_get(&pe);
@@ -2375,14 +2431,19 @@ void mvpp2_prs_mac_del_all(struct mvpp2_port *port)
continue;
/* Remove entry from TCAM */
- mvpp2_prs_mac_da_accept(port, da, false);
+ mvpp2_prs_mac_da_accept_unlocked(port, da, false);
}
+
+ spin_unlock_irqrestore(&priv->prs_spinlock, flags);
}
int mvpp2_prs_tag_mode_set(struct mvpp2 *priv, int port, int type)
{
+ unsigned long flags;
+
switch (type) {
case MVPP2_TAG_TYPE_EDSA:
+ spin_lock_irqsave(&priv->prs_spinlock, flags);
/* Add port to EDSA entries */
mvpp2_prs_dsa_tag_set(priv, port, true,
MVPP2_PRS_TAGGED, MVPP2_PRS_EDSA);
@@ -2393,9 +2454,11 @@ int mvpp2_prs_tag_mode_set(struct mvpp2 *priv, int port, int type)
MVPP2_PRS_TAGGED, MVPP2_PRS_DSA);
mvpp2_prs_dsa_tag_set(priv, port, false,
MVPP2_PRS_UNTAGGED, MVPP2_PRS_DSA);
+ spin_unlock_irqrestore(&priv->prs_spinlock, flags);
break;
case MVPP2_TAG_TYPE_DSA:
+ spin_lock_irqsave(&priv->prs_spinlock, flags);
/* Add port to DSA entries */
mvpp2_prs_dsa_tag_set(priv, port, true,
MVPP2_PRS_TAGGED, MVPP2_PRS_DSA);
@@ -2406,10 +2469,12 @@ int mvpp2_prs_tag_mode_set(struct mvpp2 *priv, int port, int type)
MVPP2_PRS_TAGGED, MVPP2_PRS_EDSA);
mvpp2_prs_dsa_tag_set(priv, port, false,
MVPP2_PRS_UNTAGGED, MVPP2_PRS_EDSA);
+ spin_unlock_irqrestore(&priv->prs_spinlock, flags);
break;
case MVPP2_TAG_TYPE_MH:
case MVPP2_TAG_TYPE_NONE:
+ spin_lock_irqsave(&priv->prs_spinlock, flags);
/* Remove port form EDSA and DSA entries */
mvpp2_prs_dsa_tag_set(priv, port, false,
MVPP2_PRS_TAGGED, MVPP2_PRS_DSA);
@@ -2419,6 +2484,7 @@ int mvpp2_prs_tag_mode_set(struct mvpp2 *priv, int port, int type)
MVPP2_PRS_TAGGED, MVPP2_PRS_EDSA);
mvpp2_prs_dsa_tag_set(priv, port, false,
MVPP2_PRS_UNTAGGED, MVPP2_PRS_EDSA);
+ spin_unlock_irqrestore(&priv->prs_spinlock, flags);
break;
default:
@@ -2433,15 +2499,20 @@ int mvpp2_prs_add_flow(struct mvpp2 *priv, int flow, u32 ri, u32 ri_mask)
{
struct mvpp2_prs_entry pe;
u8 *ri_byte, *ri_byte_mask;
+ unsigned long flags;
int tid, i;
memset(&pe, 0, sizeof(pe));
+ spin_lock_irqsave(&priv->prs_spinlock, flags);
+
tid = mvpp2_prs_tcam_first_free(priv,
MVPP2_PE_LAST_FREE_TID,
MVPP2_PE_FIRST_FREE_TID);
- if (tid < 0)
+ if (tid < 0) {
+ spin_unlock_irqrestore(&priv->prs_spinlock, flags);
return tid;
+ }
pe.index = tid;
@@ -2461,6 +2532,7 @@ int mvpp2_prs_add_flow(struct mvpp2 *priv, int flow, u32 ri, u32 ri_mask)
mvpp2_prs_tcam_port_map_set(&pe, MVPP2_PRS_PORT_MASK);
mvpp2_prs_hw_write(priv, &pe);
+ spin_unlock_irqrestore(&priv->prs_spinlock, flags);
return 0;
}
@@ -2468,10 +2540,13 @@ int mvpp2_prs_add_flow(struct mvpp2 *priv, int flow, u32 ri, u32 ri_mask)
int mvpp2_prs_def_flow(struct mvpp2_port *port)
{
struct mvpp2_prs_entry pe;
+ unsigned long flags;
int tid;
memset(&pe, 0, sizeof(pe));
+ spin_lock_irqsave(&port->priv->prs_spinlock, flags);
+
tid = mvpp2_prs_flow_find(port->priv, port->id);
/* Such entry not exist */
@@ -2480,8 +2555,10 @@ int mvpp2_prs_def_flow(struct mvpp2_port *port)
tid = mvpp2_prs_tcam_first_free(port->priv,
MVPP2_PE_LAST_FREE_TID,
MVPP2_PE_FIRST_FREE_TID);
- if (tid < 0)
+ if (tid < 0) {
+ spin_unlock_irqrestore(&port->priv->prs_spinlock, flags);
return tid;
+ }
pe.index = tid;
@@ -2492,28 +2569,33 @@ int mvpp2_prs_def_flow(struct mvpp2_port *port)
/* Update shadow table */
mvpp2_prs_shadow_set(port->priv, pe.index, MVPP2_PRS_LU_FLOWS);
} else {
- mvpp2_prs_init_from_hw(port->priv, &pe, tid);
+ mvpp2_prs_init_from_hw_unlocked(port->priv, &pe, tid);
}
mvpp2_prs_tcam_lu_set(&pe, MVPP2_PRS_LU_FLOWS);
mvpp2_prs_tcam_port_map_set(&pe, (1 << port->id));
mvpp2_prs_hw_write(port->priv, &pe);
+ spin_unlock_irqrestore(&port->priv->prs_spinlock, flags);
return 0;
}
int mvpp2_prs_hits(struct mvpp2 *priv, int index)
{
+ unsigned long flags;
u32 val;
if (index > MVPP2_PRS_TCAM_SRAM_SIZE)
return -EINVAL;
+ spin_lock_irqsave(&priv->prs_spinlock, flags);
+
mvpp2_write(priv, MVPP2_PRS_TCAM_HIT_IDX_REG, index);
val = mvpp2_read(priv, MVPP2_PRS_TCAM_HIT_CNT_REG);
val &= MVPP2_PRS_TCAM_HIT_CNT_MASK;
+ spin_unlock_irqrestore(&priv->prs_spinlock, flags);
return val;
}
--
2.43.0