netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Sasha Levin <sashal@kernel.org>
To: linux-kernel@vger.kernel.org, stable@vger.kernel.org
Cc: Russell King <rmk+kernel@armlinux.org.uk>,
	Matteo Croce <mcroce@redhat.com>,
	"David S . Miller" <davem@davemloft.net>,
	Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
	netdev@vger.kernel.org
Subject: [PATCH AUTOSEL 5.6 218/606] net: mvpp2: fix RX hashing for non-10G ports
Date: Mon,  8 Jun 2020 19:05:43 -0400	[thread overview]
Message-ID: <20200608231211.3363633-218-sashal@kernel.org> (raw)
In-Reply-To: <20200608231211.3363633-1-sashal@kernel.org>

From: Russell King <rmk+kernel@armlinux.org.uk>

[ Upstream commit 3138a07ce219acde4c0d7ea0b6d54ba64153328b ]

When rxhash is enabled on any ethernet port except the first in each CP
block, traffic flow is prevented.  The analysis is below:

I've been investigating this afternoon, and what I've found, comparing
a kernel without 895586d5dc32 and with 895586d5dc32 applied is:

- The table programmed into the hardware via mvpp22_rss_fill_table()
  appears to be identical with or without the commit.

- When rxhash is enabled on eth2, mvpp2_rss_port_c2_enable() reports
  that c2.attr[0] and c2.attr[2] are written back containing:

   - with 895586d5dc32, failing:    00200000 40000000
   - without 895586d5dc32, working: 04000000 40000000

- When disabling rxhash, c2.attr[0] and c2.attr[2] are written back as:

   04000000 00000000

The second value represents the MVPP22_CLS_C2_ATTR2_RSS_EN bit, the
first value is the queue number, which comprises two fields. The high
5 bits are 24:29 and the low three are 21:23 inclusive. This comes
from:

       c2.attr[0] = MVPP22_CLS_C2_ATTR0_QHIGH(qh) |
                     MVPP22_CLS_C2_ATTR0_QLOW(ql);

So, the working case gives eth2 a queue id of 4.0, or 32 as per
port->first_rxq, and the non-working case a queue id of 0.1, or 1.
The allocation of queue IDs seems to be in mvpp2_port_probe():

        if (priv->hw_version == MVPP21)
                port->first_rxq = port->id * port->nrxqs;
        else
                port->first_rxq = port->id * priv->max_port_rxqs;

Where:

        if (priv->hw_version == MVPP21)
                priv->max_port_rxqs = 8;
        else
                priv->max_port_rxqs = 32;

Making the port 0 (eth0 / eth1) have port->first_rxq = 0, and port 1
(eth2) be 32. It seems the idea is that the first 32 queues belong to
port 0, the second 32 queues belong to port 1, etc.

mvpp2_rss_port_c2_enable() gets the queue number from it's parameter,
'ctx', which comes from mvpp22_rss_ctx(port, 0). This returns
port->rss_ctx[0].

mvpp22_rss_context_create() is responsible for allocating that, which
it does by looking for an unallocated priv->rss_tables[] pointer. This
table is shared amongst all ports on the CP silicon.

When we write the tables in mvpp22_rss_fill_table(), the RSS table
entry is defined by:

                u32 sel = MVPP22_RSS_INDEX_TABLE(rss_ctx) |
                          MVPP22_RSS_INDEX_TABLE_ENTRY(i);

where rss_ctx is the context ID (queue number) and i is the index in
the table.

If we look at what is written:

- The first table to be written has "sel" values of 00000000..0000001f,
  containing values 0..3. This appears to be for eth1. This is table 0,
  RX queue number 0.
- The second table has "sel" values of 00000100..0000011f, and appears
  to be for eth2.  These contain values 0x20..0x23. This is table 1,
  RX queue number 0.
- The third table has "sel" values of 00000200..0000021f, and appears
  to be for eth3.  These contain values 0x40..0x43. This is table 2,
  RX queue number 0.

How do queue numbers translate to the RSS table?  There is another
table - the RXQ2RSS table, indexed by the MVPP22_RSS_INDEX_QUEUE field
of MVPP22_RSS_INDEX and accessed through the MVPP22_RXQ2RSS_TABLE
register. Before 895586d5dc32, it was:

       mvpp2_write(priv, MVPP22_RSS_INDEX,
                   MVPP22_RSS_INDEX_QUEUE(port->first_rxq));
       mvpp2_write(priv, MVPP22_RXQ2RSS_TABLE,
                   MVPP22_RSS_TABLE_POINTER(port->id));

and after:

       mvpp2_write(priv, MVPP22_RSS_INDEX, MVPP22_RSS_INDEX_QUEUE(ctx));
       mvpp2_write(priv, MVPP22_RXQ2RSS_TABLE, MVPP22_RSS_TABLE_POINTER(ctx));

Before the commit, for eth2, that would've contained '32' for the
index and '1' for the table pointer - mapping queue 32 to table 1.
Remember that this is queue-high.queue-low of 4.0.

After the commit, we appear to map queue 1 to table 1. That again
looks fine on the face of it.

Section 9.3.1 of the A8040 manual seems indicate the reason that the
queue number is separated. queue-low seems to always come from the
classifier, whereas queue-high can be from the ingress physical port
number or the classifier depending on the MVPP2_CLS_SWFWD_PCTRL_REG.

We set the port bit in MVPP2_CLS_SWFWD_PCTRL_REG, meaning that queue-high
comes from the MVPP2_CLS_SWFWD_P2HQ_REG() register... and this seems to
be where our bug comes from.

mvpp2_cls_oversize_rxq_set() sets this up as:

        mvpp2_write(port->priv, MVPP2_CLS_SWFWD_P2HQ_REG(port->id),
                    (port->first_rxq >> MVPP2_CLS_OVERSIZE_RXQ_LOW_BITS));

        val = mvpp2_read(port->priv, MVPP2_CLS_SWFWD_PCTRL_REG);
        val |= MVPP2_CLS_SWFWD_PCTRL_MASK(port->id);
        mvpp2_write(port->priv, MVPP2_CLS_SWFWD_PCTRL_REG, val);

Setting the MVPP2_CLS_SWFWD_PCTRL_MASK bit means that the queue-high
for eth2 is _always_ 4, so only queues 32 through 39 inclusive are
available to eth2. Yet, we're trying to tell the classifier to set
queue-high, which will be ignored, to zero. Hence, the queue-high
field (MVPP22_CLS_C2_ATTR0_QHIGH()) from the classifier will be
ignored.

This means we end up directing traffic from eth2 not to queue 1, but
to queue 33, and then we tell it to look up queue 33 in the RSS table.
However, RSS table has not been programmed for queue 33, and so it ends
up (presumably) dropping the packets.

It seems that mvpp22_rss_context_create() doesn't take account of the
fact that the upper 5 bits of the queue ID can't actually be changed
due to the settings in mvpp2_cls_oversize_rxq_set(), _or_ it seems that
mvpp2_cls_oversize_rxq_set() has been missed in this commit. Either
way, these two functions mutually disagree with what queue number
should be used.

Looking deeper into what mvpp2_cls_oversize_rxq_set() and the MTU
validation is doing, it seems that MVPP2_CLS_SWFWD_P2HQ_REG() is used
for over-sized packets attempting to egress through this port. With
the classifier having had RSS enabled and directing eth2 traffic to
queue 1, we may still have packets appearing on queue 32 for this port.

However, the only way we may end up with over-sized packets attempting
to egress through eth2 - is if the A8040 forwards frames between its
ports. From what I can see, we don't support that feature, and the
kernel restricts the egress packet size to the MTU. In any case, if we
were to attempt to transmit an oversized packet, we have no support in
the kernel to deal with that appearing in the port's receive queue.

So, this patch attempts to solve the issue by clearing the
MVPP2_CLS_SWFWD_PCTRL_MASK() bit, allowing MVPP22_CLS_C2_ATTR0_QHIGH()
from the classifier to define the queue-high field of the queue number.

My testing seems to confirm my findings above - clearing this bit
means that if I enable rxhash on eth2, the interface can then pass
traffic, as we are now directing traffic to RX queue 1 rather than
queue 33. Traffic still seems to work with rxhash off as well.

Reported-by: Matteo Croce <mcroce@redhat.com>
Tested-by: Matteo Croce <mcroce@redhat.com>
Fixes: 895586d5dc32 ("net: mvpp2: cls: Use RSS contexts to handle RSS tables")
Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 drivers/net/ethernet/marvell/mvpp2/mvpp2_cls.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2_cls.c b/drivers/net/ethernet/marvell/mvpp2/mvpp2_cls.c
index 4344a59c823f..6122057d60c0 100644
--- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_cls.c
+++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_cls.c
@@ -1070,7 +1070,7 @@ void mvpp2_cls_oversize_rxq_set(struct mvpp2_port *port)
 		    (port->first_rxq >> MVPP2_CLS_OVERSIZE_RXQ_LOW_BITS));
 
 	val = mvpp2_read(port->priv, MVPP2_CLS_SWFWD_PCTRL_REG);
-	val |= MVPP2_CLS_SWFWD_PCTRL_MASK(port->id);
+	val &= ~MVPP2_CLS_SWFWD_PCTRL_MASK(port->id);
 	mvpp2_write(port->priv, MVPP2_CLS_SWFWD_PCTRL_REG, val);
 }
 
-- 
2.25.1


  parent reply	other threads:[~2020-06-09  0:27 UTC|newest]

Thread overview: 70+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <20200608231211.3363633-1-sashal@kernel.org>
2020-06-08 23:02 ` [PATCH AUTOSEL 5.6 006/606] bpf: Fix bug in mmap() implementation for BPF array map Sasha Levin
2020-06-08 23:02 ` [PATCH AUTOSEL 5.6 009/606] net/rds: Use ERR_PTR for rds_message_alloc_sgs() Sasha Levin
2020-06-08 23:03 ` [PATCH AUTOSEL 5.6 067/606] SUNRPC: Revert 241b1f419f0e ("SUNRPC: Remove xdr_buf_trim()") Sasha Levin
2020-06-08 23:03 ` [PATCH AUTOSEL 5.6 068/606] bpf: Fix sk_psock refcnt leak when receiving message Sasha Levin
2020-06-08 23:03 ` [PATCH AUTOSEL 5.6 075/606] bpf: Enforce returning 0 for fentry/fexit progs Sasha Levin
2020-06-08 23:03 ` [PATCH AUTOSEL 5.6 076/606] selftests/bpf: Enforce returning 0 for fentry/fexit programs Sasha Levin
2020-06-08 23:03 ` [PATCH AUTOSEL 5.6 077/606] bpf: Restrict bpf_trace_printk()'s %s usage and add %pks, %pus specifier Sasha Levin
2020-06-08 23:03 ` [PATCH AUTOSEL 5.6 102/606] net: drop_monitor: use IS_REACHABLE() to guard net_dm_hw_report() Sasha Levin
2020-06-08 23:03 ` [PATCH AUTOSEL 5.6 111/606] vhost/vsock: fix packet delivery order to monitoring devices Sasha Levin
2020-06-08 23:03 ` [PATCH AUTOSEL 5.6 112/606] aquantia: Fix the media type of AQC100 ethernet controller in the driver Sasha Levin
2020-06-08 23:03 ` [PATCH AUTOSEL 5.6 114/606] net/ena: Fix build warning in ena_xdp_set() Sasha Levin
2020-06-08 23:04 ` [PATCH AUTOSEL 5.6 117/606] ibmvnic: Skip fatal error reset after passive init Sasha Levin
2020-06-08 23:04 ` [PATCH AUTOSEL 5.6 121/606] gtp: set NLM_F_MULTI flag in gtp_genl_dump_pdp() Sasha Levin
2020-06-08 23:04 ` [PATCH AUTOSEL 5.6 124/606] stmmac: fix pointer check after utilization in stmmac_interrupt Sasha Levin
2020-06-08 23:04 ` [PATCH AUTOSEL 5.6 141/606] bpf: Restrict bpf_probe_read{, str}() only to archs where they work Sasha Levin
2020-06-08 23:04 ` [PATCH AUTOSEL 5.6 142/606] bpf: Add bpf_probe_read_{user, kernel}_str() to do_refine_retval_range Sasha Levin
2020-06-08 23:04 ` [PATCH AUTOSEL 5.6 168/606] kbuild: Remove debug info from kallsyms linking Sasha Levin
2020-06-08 23:05 ` [PATCH AUTOSEL 5.6 194/606] rxrpc: Fix the excessive initial retransmission timeout Sasha Levin
2020-06-08 23:05 ` [PATCH AUTOSEL 5.6 195/606] rxrpc: Fix a memory leak in rxkad_verify_response() Sasha Levin
2020-06-08 23:05 ` [PATCH AUTOSEL 5.6 198/606] flow_dissector: Drop BPF flow dissector prog ref on netns cleanup Sasha Levin
2020-06-08 23:05 ` [PATCH AUTOSEL 5.6 200/606] rxrpc: Trace discarded ACKs Sasha Levin
2020-06-08 23:05 ` [PATCH AUTOSEL 5.6 201/606] rxrpc: Fix ack discard Sasha Levin
2020-06-08 23:05 ` [PATCH AUTOSEL 5.6 202/606] bpf: Prevent mmap()'ing read-only maps as writable Sasha Levin
2020-06-08 23:05 ` [PATCH AUTOSEL 5.6 207/606] ax25: fix setsockopt(SO_BINDTODEVICE) Sasha Levin
2020-06-08 23:05 ` [PATCH AUTOSEL 5.6 208/606] dpaa_eth: fix usage as DSA master, try 3 Sasha Levin
2020-06-08 23:05 ` [PATCH AUTOSEL 5.6 209/606] ethtool: count header size in reply size estimate Sasha Levin
2020-06-08 23:05 ` [PATCH AUTOSEL 5.6 210/606] felix: Fix initialization of ioremap resources Sasha Levin
2020-06-08 23:05 ` [PATCH AUTOSEL 5.6 211/606] net: don't return invalid table id error when we fall back to PF_UNSPEC Sasha Levin
2020-06-08 23:05 ` [PATCH AUTOSEL 5.6 212/606] net: dsa: mt7530: fix roaming from DSA user ports Sasha Levin
2020-06-08 23:05 ` [PATCH AUTOSEL 5.6 213/606] net: ethernet: ti: cpsw: fix ASSERT_RTNL() warning during suspend Sasha Levin
2020-06-08 23:05 ` [PATCH AUTOSEL 5.6 214/606] __netif_receive_skb_core: pass skb by reference Sasha Levin
2020-06-08 23:05 ` [PATCH AUTOSEL 5.6 215/606] net: inet_csk: Fix so_reuseport bind-address cache in tb->fast* Sasha Levin
2020-06-08 23:05 ` [PATCH AUTOSEL 5.6 216/606] net: ipip: fix wrong address family in init error path Sasha Levin
2020-06-08 23:05 ` [PATCH AUTOSEL 5.6 217/606] net/mlx5: Add command entry handling completion Sasha Levin
2020-06-08 23:05 ` Sasha Levin [this message]
2020-06-08 23:05 ` [PATCH AUTOSEL 5.6 219/606] net: nlmsg_cancel() if put fails for nhmsg Sasha Levin
2020-06-08 23:05 ` [PATCH AUTOSEL 5.6 220/606] net: qrtr: Fix passing invalid reference to qrtr_local_enqueue() Sasha Levin
2020-06-08 23:05 ` [PATCH AUTOSEL 5.6 221/606] net: revert "net: get rid of an signed integer overflow in ip_idents_reserve()" Sasha Levin
2020-06-08 23:05 ` [PATCH AUTOSEL 5.6 222/606] net sched: fix reporting the first-time use timestamp Sasha Levin
2020-06-08 23:05 ` [PATCH AUTOSEL 5.6 223/606] net/tls: fix race condition causing kernel panic Sasha Levin
2020-06-08 23:05 ` [PATCH AUTOSEL 5.6 224/606] nexthop: Fix attribute checking for groups Sasha Levin
2020-06-08 23:05 ` [PATCH AUTOSEL 5.6 225/606] r8152: support additional Microsoft Surface Ethernet Adapter variant Sasha Levin
2020-06-08 23:05 ` [PATCH AUTOSEL 5.6 226/606] sctp: Don't add the shutdown timer if its already been added Sasha Levin
2020-06-08 23:05 ` [PATCH AUTOSEL 5.6 227/606] sctp: Start shutdown on association restart if in SHUTDOWN-SENT state and socket is closed Sasha Levin
2020-06-08 23:05 ` [PATCH AUTOSEL 5.6 228/606] tipc: block BH before using dst_cache Sasha Levin
2020-06-08 23:05 ` [PATCH AUTOSEL 5.6 229/606] net/mlx5e: kTLS, Destroy key object after destroying the TIS Sasha Levin
2020-06-08 23:05 ` [PATCH AUTOSEL 5.6 230/606] net/mlx5e: Fix inner tirs handling Sasha Levin
2020-06-08 23:05 ` [PATCH AUTOSEL 5.6 231/606] net/mlx5: Fix memory leak in mlx5_events_init Sasha Levin
2020-06-08 23:05 ` [PATCH AUTOSEL 5.6 232/606] net/mlx5e: Update netdev txq on completions during closure Sasha Levin
2020-06-08 23:05 ` [PATCH AUTOSEL 5.6 233/606] net/mlx5: Fix error flow in case of function_setup failure Sasha Levin
2020-06-08 23:05 ` [PATCH AUTOSEL 5.6 234/606] wireguard: noise: read preshared key while taking lock Sasha Levin
2020-06-08 23:06 ` [PATCH AUTOSEL 5.6 235/606] wireguard: queueing: preserve flow hash across packet scrubbing Sasha Levin
2020-06-08 23:06 ` [PATCH AUTOSEL 5.6 236/606] wireguard: noise: separate receive counter from send counter Sasha Levin
2020-06-08 23:06 ` [PATCH AUTOSEL 5.6 237/606] r8169: fix OCP access on RTL8117 Sasha Levin
2020-06-08 23:06 ` [PATCH AUTOSEL 5.6 238/606] net/mlx5: Fix a race when moving command interface to events mode Sasha Levin
2020-06-08 23:06 ` [PATCH AUTOSEL 5.6 239/606] net/mlx5: Fix cleaning unmanaged flow tables Sasha Levin
2020-06-08 23:06 ` [PATCH AUTOSEL 5.6 241/606] net/mlx5: Avoid processing commands before cmdif is ready Sasha Levin
2020-06-08 23:06 ` [PATCH AUTOSEL 5.6 242/606] net/mlx5: Annotate mutex destroy for root ns Sasha Levin
2020-06-08 23:06 ` [PATCH AUTOSEL 5.6 243/606] net/tls: fix encryption error checking Sasha Levin
2020-06-08 23:06 ` [PATCH AUTOSEL 5.6 244/606] net/tls: free record only on encryption error Sasha Levin
2020-06-08 23:06 ` [PATCH AUTOSEL 5.6 245/606] net: sun: fix missing release regions in cas_init_one() Sasha Levin
2020-06-08 23:06 ` [PATCH AUTOSEL 5.6 246/606] net/mlx4_core: fix a memory leak bug Sasha Levin
2020-06-08 23:06 ` [PATCH AUTOSEL 5.6 247/606] net: sgi: ioc3-eth: Fix return value check in ioc3eth_probe() Sasha Levin
2020-06-08 23:06 ` [PATCH AUTOSEL 5.6 248/606] mlxsw: spectrum: Fix use-after-free of split/unsplit/type_set in case reload fails Sasha Levin
2020-06-08 23:06 ` [PATCH AUTOSEL 5.6 249/606] net: mscc: ocelot: fix address ageing time (again) Sasha Levin
2020-06-08 23:06 ` [PATCH AUTOSEL 5.6 261/606] net: microchip: encx24j600: add missed kthread_stop Sasha Levin
2020-06-08 23:06 ` [PATCH AUTOSEL 5.6 272/606] net: freescale: select CONFIG_FIXED_PHY where needed Sasha Levin
2020-06-08 23:06 ` [PATCH AUTOSEL 5.6 287/606] samples: bpf: Fix build error Sasha Levin
2020-06-08 23:06 ` [PATCH AUTOSEL 5.6 288/606] drivers: net: hamradio: Fix suspicious RCU usage warning in bpqether.c Sasha Levin
2020-06-08 23:07 ` [PATCH AUTOSEL 5.6 325/606] libceph: ignore pool overlay and cache logic on redirects Sasha Levin

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20200608231211.3363633-218-sashal@kernel.org \
    --to=sashal@kernel.org \
    --cc=davem@davemloft.net \
    --cc=gregkh@linuxfoundation.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mcroce@redhat.com \
    --cc=netdev@vger.kernel.org \
    --cc=rmk+kernel@armlinux.org.uk \
    --cc=stable@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).