From patchwork Thu Aug 18 10:29:22 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mattias Forsblad X-Patchwork-Id: 12946896 X-Patchwork-Delegate: kuba@kernel.org Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id DEB98C32772 for ; Thu, 18 Aug 2022 10:29:50 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S240228AbiHRK3t (ORCPT ); Thu, 18 Aug 2022 06:29:49 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:54096 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S239816AbiHRK3r (ORCPT ); Thu, 18 Aug 2022 06:29:47 -0400 Received: from mail-lf1-x129.google.com (mail-lf1-x129.google.com [IPv6:2a00:1450:4864:20::129]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 9FFD86F541 for ; Thu, 18 Aug 2022 03:29:46 -0700 (PDT) Received: by mail-lf1-x129.google.com with SMTP id l1so1042247lfk.8 for ; Thu, 18 Aug 2022 03:29:46 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc; bh=aW+aHfEKz9Sv7afAJq9m2sWM9XnfaKcvhG77LIZvwms=; b=c8hVbU2s9pkzNPWlnibKOA9DJDOLdIYKUsMFX45dX+JcLn8vKpZLgwfm7gkFG07Pbb GgVfrkf9WAdNzjoXSCHhusCDRtnBpahn7XMtVVN8m2UoFayI52MPUtrFoqw64Z54LcIT b2MtpBRB/yOKxaVHG8TY8suUadJRgsB5UapebRQKzV5euke6bRYv0m5eViSfhinwEdxZ je8C12LgR65Tad8+KYdSIR86j5U0BzBp2hRhI/A5CrL/0M044tO9N01ItBtMCK2QbjxV A/oPrSzW/cPD9rwjrI57cUg0Q4PJWXL3Hd14PDNixnXB+Q2SzEPaajCLhuIsksRLhWfx RigA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc; bh=aW+aHfEKz9Sv7afAJq9m2sWM9XnfaKcvhG77LIZvwms=; b=yR4sgxYHiscY3ro4UpDk4ppz61SplZIQpe1POrvTlfJl/9TPLQJ9e7r56YDoCETuSl sJPxU/dGMY9nywY+1PSiu6CNWBwXz/9/nhhwx3cswuaTa8eXTs5/iUs+0LTB1qZHZUAj ad1atE/qDMKIS2BAmBhgatVYx4+68Fvu8+Vj93+3AUIEwNUw8D71n/GWd4k/7E1cjg+/ eBgiyHy2hVEx4hZCc4DMXh8dhfCUMJxF1o79c1Q6rsPFTXqJzb8NWCaOSSY5JbPBVl0c QRhADaDUCPeYAiJ0RgNRZlhbtLuVvjew+WAQdruviYMG6H7hsDZqMtvkhgXkBaLkQop/ InlQ== X-Gm-Message-State: ACgBeo0GMegzUabUrjfMOt+zvhf2C+VFlrm6C6XwC5r2rBQ01gBYJpZa seoNmU0UgtApCKy2QNrwN5qo0mXB9yGMFA== X-Google-Smtp-Source: AA6agR7IaIEFwoELBF2qMPjWPTHOWO2Hxx2jYNcEyhhKoghPNkVvJwIEgTD2ilhoHs72sQYqpYe11w== X-Received: by 2002:a05:6512:1316:b0:48d:2549:1158 with SMTP id x22-20020a056512131600b0048d25491158mr700787lfu.626.1660818584759; Thu, 18 Aug 2022 03:29:44 -0700 (PDT) Received: from wse-c0089.raspi.local (h-98-128-229-160.NA.cust.bahnhof.se. [98.128.229.160]) by smtp.gmail.com with ESMTPSA id z10-20020a056512370a00b0048afa5daaf3sm171035lfr.123.2022.08.18.03.29.44 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 18 Aug 2022 03:29:44 -0700 (PDT) From: Mattias Forsblad To: netdev@vger.kernel.org Cc: Andrew Lunn , Vivien Didelot , Florian Fainelli , Vladimir Oltean , "David S . Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Mattias Forsblad Subject: [RFC net-next PATCH 1/3] dsa: Add ability to handle RMU frames. Date: Thu, 18 Aug 2022 12:29:22 +0200 Message-Id: <20220818102924.287719-2-mattias.forsblad@gmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220818102924.287719-1-mattias.forsblad@gmail.com> References: <20220818102924.287719-1-mattias.forsblad@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org X-Patchwork-Delegate: kuba@kernel.org X-Patchwork-State: RFC Support handling of layer 2 part for RMU frames which is handled in-band with other DSA traffic. Signed-off-by: Mattias Forsblad --- include/net/dsa.h | 7 +++ include/uapi/linux/if_ether.h | 1 + net/dsa/tag_dsa.c | 102 +++++++++++++++++++++++++++++++++- 3 files changed, 107 insertions(+), 3 deletions(-) diff --git a/include/net/dsa.h b/include/net/dsa.h index b902b31bebce..80955a9d5fd6 100644 --- a/include/net/dsa.h +++ b/include/net/dsa.h @@ -92,6 +92,7 @@ struct dsa_switch; struct dsa_device_ops { struct sk_buff *(*xmit)(struct sk_buff *skb, struct net_device *dev); struct sk_buff *(*rcv)(struct sk_buff *skb, struct net_device *dev); + int (*inband_xmit)(struct sk_buff *skb, struct net_device *dev, int seq_no); void (*flow_dissect)(const struct sk_buff *skb, __be16 *proto, int *offset); int (*connect)(struct dsa_switch *ds); @@ -1189,6 +1190,12 @@ struct dsa_switch_ops { void (*master_state_change)(struct dsa_switch *ds, const struct net_device *master, bool operational); + + /* + * RMU operations + */ + int (*inband_receive)(struct dsa_switch *ds, struct sk_buff *skb, + int seq_no); }; #define DSA_DEVLINK_PARAM_DRIVER(_id, _name, _type, _cmodes) \ diff --git a/include/uapi/linux/if_ether.h b/include/uapi/linux/if_ether.h index d370165bc621..9de1bdc7cccc 100644 --- a/include/uapi/linux/if_ether.h +++ b/include/uapi/linux/if_ether.h @@ -158,6 +158,7 @@ #define ETH_P_MCTP 0x00FA /* Management component transport * protocol packets */ +#define ETH_P_RMU_DSA 0x00FB /* RMU DSA protocol */ /* * This is an Ethernet frame header. diff --git a/net/dsa/tag_dsa.c b/net/dsa/tag_dsa.c index e4b6e3f2a3db..58b02109e4cf 100644 --- a/net/dsa/tag_dsa.c +++ b/net/dsa/tag_dsa.c @@ -123,6 +123,83 @@ enum dsa_code { DSA_CODE_RESERVED_7 = 7 }; +#define DSA_RMU_RESV1 0x3e +#define DSA_RMU 1 +#define DSA_RMU_PRIO 6 +#define DSA_RMU_RESV2 0xf + +static int dsa_inband_xmit_ll(struct sk_buff *skb, struct net_device *dev, + const u8 *header, int header_len, int seq_no) +{ + static const u8 dest_addr[ETH_ALEN] = { 0x01, 0x50, 0x43, 0x00, 0x00, 0x00 }; + struct dsa_port *dp; + struct ethhdr *eth; + u8 *data; + + if (!dev) + return -ENODEV; + + dp = dsa_slave_to_port(dev); + if (!dp) + return -ENODEV; + + /* Create RMU L2 header */ + data = skb_push(skb, 6); + data[0] = (DSA_CMD_FROM_CPU << 6) | dp->ds->index; + data[1] = DSA_RMU_RESV1 << 2 | DSA_RMU << 1; + data[2] = DSA_RMU_PRIO << 5 | DSA_RMU_RESV2; + data[3] = seq_no; + data[4] = 0; + data[5] = 0; + + /* Add header if any */ + if (header) { + data = skb_push(skb, header_len); + memcpy(data, header, header_len); + } + + /* Create MAC header */ + eth = (struct ethhdr *)skb_push(skb, 2 * ETH_ALEN); + memcpy(eth->h_source, dev->dev_addr, ETH_ALEN); + memcpy(eth->h_dest, dest_addr, ETH_ALEN); + + skb->protocol = htons(ETH_P_RMU_DSA); + + dev_queue_xmit(skb); + + return 0; +} + +static int dsa_inband_rcv_ll(struct sk_buff *skb, struct net_device *dev) +{ + int source_device, source_port; + struct dsa_switch *ds; + u8 *dsa_header; + int rcv_seqno; + int ret = 0; + + if (!dev || !dev->dsa_ptr) + return 0; + + ds = dev->dsa_ptr->ds; + + dsa_header = skb->data - 2; + + source_device = dsa_header[0] & 0x1f; + source_port = (dsa_header[1] >> 3) & 0x1f; + ds = dsa_switch_find(ds->dst->index, source_device); + + /* Get rcv seqno */ + rcv_seqno = dsa_header[3]; + + skb_pull(skb, DSA_HLEN); + + if (ds->ops && ds->ops->inband_receive(ds, skb, rcv_seqno)) + netdev_err(dev, "DSA inband: error decoding packet"); + + return ret; +} + static struct sk_buff *dsa_xmit_ll(struct sk_buff *skb, struct net_device *dev, u8 extra) { @@ -218,9 +295,7 @@ static struct sk_buff *dsa_rcv_ll(struct sk_buff *skb, struct net_device *dev, switch (code) { case DSA_CODE_FRAME2REG: - /* Remote management is not implemented yet, - * drop. - */ + dsa_inband_rcv_ll(skb, dev); return NULL; case DSA_CODE_ARP_MIRROR: case DSA_CODE_POLICY_MIRROR: @@ -325,6 +400,12 @@ static struct sk_buff *dsa_rcv_ll(struct sk_buff *skb, struct net_device *dev, #if IS_ENABLED(CONFIG_NET_DSA_TAG_DSA) +static int dsa_inband_xmit(struct sk_buff *skb, struct net_device *dev, + int seq_no) +{ + return dsa_inband_xmit_ll(skb, dev, NULL, 0, seq_no); +} + static struct sk_buff *dsa_xmit(struct sk_buff *skb, struct net_device *dev) { return dsa_xmit_ll(skb, dev, 0); @@ -343,6 +424,7 @@ static const struct dsa_device_ops dsa_netdev_ops = { .proto = DSA_TAG_PROTO_DSA, .xmit = dsa_xmit, .rcv = dsa_rcv, + .inband_xmit = dsa_inband_xmit, .needed_headroom = DSA_HLEN, }; @@ -354,6 +436,19 @@ MODULE_ALIAS_DSA_TAG_DRIVER(DSA_TAG_PROTO_DSA); #define EDSA_HLEN 8 +static int edsa_inband_xmit(struct sk_buff *skb, struct net_device *dev, + int seq_no) +{ + u8 edsa_header[4]; + + edsa_header[0] = (ETH_P_EDSA >> 8) & 0xff; + edsa_header[1] = ETH_P_EDSA & 0xff; + edsa_header[2] = 0x00; + edsa_header[3] = 0x00; + + return dsa_inband_xmit_ll(skb, dev, edsa_header, 4, seq_no); +} + static struct sk_buff *edsa_xmit(struct sk_buff *skb, struct net_device *dev) { u8 *edsa_header; @@ -385,6 +480,7 @@ static const struct dsa_device_ops edsa_netdev_ops = { .proto = DSA_TAG_PROTO_EDSA, .xmit = edsa_xmit, .rcv = edsa_rcv, + .inband_xmit = edsa_inband_xmit, .needed_headroom = EDSA_HLEN, }; From patchwork Thu Aug 18 10:29:23 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mattias Forsblad X-Patchwork-Id: 12946898 X-Patchwork-Delegate: kuba@kernel.org Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id DFD3BC32772 for ; Thu, 18 Aug 2022 10:29:59 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S243824AbiHRK36 (ORCPT ); Thu, 18 Aug 2022 06:29:58 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:54152 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S240270AbiHRK3u (ORCPT ); Thu, 18 Aug 2022 06:29:50 -0400 Received: from mail-lj1-x22d.google.com (mail-lj1-x22d.google.com [IPv6:2a00:1450:4864:20::22d]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id C4CE06F572 for ; Thu, 18 Aug 2022 03:29:47 -0700 (PDT) Received: by mail-lj1-x22d.google.com with SMTP id v10so1281973ljh.9 for ; Thu, 18 Aug 2022 03:29:47 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc; bh=kjVDYfx8q5Z156CEAHNw/QbqEtB2Dlc84vppNPIQgX0=; b=YU4zU+e66+RxKrXxU2MeqjHDPHtO3KySf44ocOPE3yNuTGtlmVXi9OQ+JV6bjo+qDn 9p5xsCsUZnigtAlIi1YcgcwZYvFB0+zjdlukeQ6mHS6wU20TNHU+yf8F0itCRmYW463v A3Xx/Y26+9GvU8K52fRt/GfuzuxsNuTJx3LtRgV9rK6YD41qsClHz8sidVX6RujD+IfK C4BK2yirK+u0HFj26sNBfhU5UqjoCmnwVEt6t5pJKWhc94/ZFV1cYrH+llRai0EIvDeJ /6fmfnMavui+du3lODi93WmAOUc3jDG6y5Jcox1KmwAcJ9lAh52yjBlpRyQphEPzuK25 hcQQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc; bh=kjVDYfx8q5Z156CEAHNw/QbqEtB2Dlc84vppNPIQgX0=; b=EpLl7hobBGhGzihvoLtDxKAJHH0JYphESrF/W7UrjAnRqYoIhBGZ8++8wpxg+kvMf5 XABjoHAEaagKHHl218O3QOK86I0vdl3Br51uyxPMDUu8bor5Qm9eAdcXwiKNzVtEhYNn s8rVUKTEm4JUAY3jY0P3IOgvndDnMWOmuHtOFYItFxj9AGwZ+wONNLjPGmoP65qCQdSH 1YPFQAssVsQTkC7z4XtdMeuTQEWgAQl6NZ2Zzfnv7lgvRc9kRMpjd1FLmcbaUqmJVbrX xerFxyKTYrTEEoBF8Rhn17PYIHz/iOucP5EAXcblbVa33Cx0PWXOkZhdALihX19cK2xR JxgQ== X-Gm-Message-State: ACgBeo27hf5Us2PCQ4OtoN+VSWPy7l2/4fWQO4zOPqA5qteMg0+F8TCU tOt1EUApubDfAwdSC/VAXAzQ8falyiq/lQ== X-Google-Smtp-Source: AA6agR43vOO8vMc3rNt+fjcnkzD7LH+5QL7JTeRB/s7XOFJKavR5Xdfg9vCIIlX3+35fMTP0LzOCWg== X-Received: by 2002:a2e:80d5:0:b0:25e:6a71:bf27 with SMTP id r21-20020a2e80d5000000b0025e6a71bf27mr687269ljg.472.1660818585654; Thu, 18 Aug 2022 03:29:45 -0700 (PDT) Received: from wse-c0089.raspi.local (h-98-128-229-160.NA.cust.bahnhof.se. [98.128.229.160]) by smtp.gmail.com with ESMTPSA id z10-20020a056512370a00b0048afa5daaf3sm171035lfr.123.2022.08.18.03.29.44 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 18 Aug 2022 03:29:45 -0700 (PDT) From: Mattias Forsblad To: netdev@vger.kernel.org Cc: Andrew Lunn , Vivien Didelot , Florian Fainelli , Vladimir Oltean , "David S . Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Mattias Forsblad Subject: [RFC net-next PATCH 2/3] mv88e6xxx: Implement remote management support (RMU) Date: Thu, 18 Aug 2022 12:29:23 +0200 Message-Id: <20220818102924.287719-3-mattias.forsblad@gmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220818102924.287719-1-mattias.forsblad@gmail.com> References: <20220818102924.287719-1-mattias.forsblad@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org X-Patchwork-Delegate: kuba@kernel.org X-Patchwork-State: RFC Implement support for handling RMU layer 3 frames including receive and transmit. Signed-off-by: Mattias Forsblad --- drivers/net/dsa/mv88e6xxx/Makefile | 1 + drivers/net/dsa/mv88e6xxx/chip.c | 19 ++- drivers/net/dsa/mv88e6xxx/chip.h | 20 +++ drivers/net/dsa/mv88e6xxx/global1.c | 84 +++++++++ drivers/net/dsa/mv88e6xxx/global1.h | 3 + drivers/net/dsa/mv88e6xxx/rmu.c | 256 ++++++++++++++++++++++++++++ drivers/net/dsa/mv88e6xxx/rmu.h | 18 ++ 7 files changed, 399 insertions(+), 2 deletions(-) create mode 100644 drivers/net/dsa/mv88e6xxx/rmu.c create mode 100644 drivers/net/dsa/mv88e6xxx/rmu.h diff --git a/drivers/net/dsa/mv88e6xxx/Makefile b/drivers/net/dsa/mv88e6xxx/Makefile index c8eca2b6f959..105d7bd832c9 100644 --- a/drivers/net/dsa/mv88e6xxx/Makefile +++ b/drivers/net/dsa/mv88e6xxx/Makefile @@ -15,3 +15,4 @@ mv88e6xxx-objs += port_hidden.o mv88e6xxx-$(CONFIG_NET_DSA_MV88E6XXX_PTP) += ptp.o mv88e6xxx-objs += serdes.o mv88e6xxx-objs += smi.o +mv88e6xxx-objs += rmu.o diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index 07e9a4da924c..888c6e47dd16 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -42,6 +42,7 @@ #include "ptp.h" #include "serdes.h" #include "smi.h" +#include "rmu.h" static void assert_reg_lock(struct mv88e6xxx_chip *chip) { @@ -1529,10 +1530,17 @@ static int mv88e6xxx_trunk_setup(struct mv88e6xxx_chip *chip) static int mv88e6xxx_rmu_setup(struct mv88e6xxx_chip *chip) { + int ret = 0; + if (chip->info->ops->rmu_disable) - return chip->info->ops->rmu_disable(chip); + ret = chip->info->ops->rmu_disable(chip); - return 0; + if (chip->info->ops->rmu_enable) { + ret += chip->info->ops->rmu_enable(chip); + ret += mv88e6xxx_rmu_init(chip); + } + + return ret; } static int mv88e6xxx_pot_setup(struct mv88e6xxx_chip *chip) @@ -4090,6 +4098,7 @@ static const struct mv88e6xxx_ops mv88e6085_ops = { .ppu_disable = mv88e6185_g1_ppu_disable, .reset = mv88e6185_g1_reset, .rmu_disable = mv88e6085_g1_rmu_disable, + .rmu_enable = mv88e6085_g1_rmu_enable, .vtu_getnext = mv88e6352_g1_vtu_getnext, .vtu_loadpurge = mv88e6352_g1_vtu_loadpurge, .stu_getnext = mv88e6352_g1_stu_getnext, @@ -4173,6 +4182,7 @@ static const struct mv88e6xxx_ops mv88e6097_ops = { .pot_clear = mv88e6xxx_g2_pot_clear, .reset = mv88e6352_g1_reset, .rmu_disable = mv88e6085_g1_rmu_disable, + .rmu_enable = mv88e6085_g1_rmu_enable, .vtu_getnext = mv88e6352_g1_vtu_getnext, .vtu_loadpurge = mv88e6352_g1_vtu_loadpurge, .phylink_get_caps = mv88e6095_phylink_get_caps, @@ -5292,6 +5302,7 @@ static const struct mv88e6xxx_ops mv88e6352_ops = { .pot_clear = mv88e6xxx_g2_pot_clear, .reset = mv88e6352_g1_reset, .rmu_disable = mv88e6352_g1_rmu_disable, + .rmu_enable = mv88e6352_g1_rmu_enable, .atu_get_hash = mv88e6165_g1_atu_get_hash, .atu_set_hash = mv88e6165_g1_atu_set_hash, .vtu_getnext = mv88e6352_g1_vtu_getnext, @@ -5359,6 +5370,7 @@ static const struct mv88e6xxx_ops mv88e6390_ops = { .pot_clear = mv88e6xxx_g2_pot_clear, .reset = mv88e6352_g1_reset, .rmu_disable = mv88e6390_g1_rmu_disable, + .rmu_enable = mv88e6390_g1_rmu_enable, .atu_get_hash = mv88e6165_g1_atu_get_hash, .atu_set_hash = mv88e6165_g1_atu_set_hash, .vtu_getnext = mv88e6390_g1_vtu_getnext, @@ -5426,6 +5438,7 @@ static const struct mv88e6xxx_ops mv88e6390x_ops = { .pot_clear = mv88e6xxx_g2_pot_clear, .reset = mv88e6352_g1_reset, .rmu_disable = mv88e6390_g1_rmu_disable, + .rmu_enable = mv88e6390_g1_rmu_enable, .atu_get_hash = mv88e6165_g1_atu_get_hash, .atu_set_hash = mv88e6165_g1_atu_set_hash, .vtu_getnext = mv88e6390_g1_vtu_getnext, @@ -5496,6 +5509,7 @@ static const struct mv88e6xxx_ops mv88e6393x_ops = { .pot_clear = mv88e6xxx_g2_pot_clear, .reset = mv88e6352_g1_reset, .rmu_disable = mv88e6390_g1_rmu_disable, + .rmu_enable = mv88e6390_g1_rmu_enable, .atu_get_hash = mv88e6165_g1_atu_get_hash, .atu_set_hash = mv88e6165_g1_atu_set_hash, .vtu_getnext = mv88e6390_g1_vtu_getnext, @@ -6918,6 +6932,7 @@ static const struct dsa_switch_ops mv88e6xxx_switch_ops = { .crosschip_lag_change = mv88e6xxx_crosschip_lag_change, .crosschip_lag_join = mv88e6xxx_crosschip_lag_join, .crosschip_lag_leave = mv88e6xxx_crosschip_lag_leave, + .inband_receive = mv88e6xxx_inband_rcv, }; static int mv88e6xxx_register_switch(struct mv88e6xxx_chip *chip) diff --git a/drivers/net/dsa/mv88e6xxx/chip.h b/drivers/net/dsa/mv88e6xxx/chip.h index e693154cf803..024f45cc1476 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.h +++ b/drivers/net/dsa/mv88e6xxx/chip.h @@ -33,6 +33,8 @@ #define MV88E6XXX_MAX_GPIO 16 +#define MV88E6XXX_WAIT_POLL_TIME_MS 200 + enum mv88e6xxx_egress_mode { MV88E6XXX_EGRESS_MODE_UNMODIFIED, MV88E6XXX_EGRESS_MODE_UNTAGGED, @@ -266,6 +268,7 @@ struct mv88e6xxx_vlan { struct mv88e6xxx_port { struct mv88e6xxx_chip *chip; int port; + u64 rmu_raw_stats[64]; struct mv88e6xxx_vlan bridge_pvid; u64 serdes_stats[2]; u64 atu_member_violation; @@ -282,6 +285,18 @@ struct mv88e6xxx_port { struct devlink_region *region; }; +struct mv88e6xxx_rmu { + /* RMU resources */ + struct net_device *netdev; + struct mv88e6xxx_bus_ops *ops; + struct completion completion; + /* Mutex for RMU operations */ + struct mutex mutex; + u16 got_id; + u8 request_cmd; + u8 seq_no; +}; + enum mv88e6xxx_region_id { MV88E6XXX_REGION_GLOBAL1 = 0, MV88E6XXX_REGION_GLOBAL2, @@ -410,12 +425,16 @@ struct mv88e6xxx_chip { /* Bridge MST to SID mappings */ struct list_head msts; + + /* RMU resources */ + struct mv88e6xxx_rmu rmu; }; struct mv88e6xxx_bus_ops { int (*read)(struct mv88e6xxx_chip *chip, int addr, int reg, u16 *val); int (*write)(struct mv88e6xxx_chip *chip, int addr, int reg, u16 val); int (*init)(struct mv88e6xxx_chip *chip); + int (*get_rmon)(struct mv88e6xxx_chip *chip, int port, uint64_t *data); }; struct mv88e6xxx_mdio_bus { @@ -637,6 +656,7 @@ struct mv88e6xxx_ops { /* Remote Management Unit operations */ int (*rmu_disable)(struct mv88e6xxx_chip *chip); + int (*rmu_enable)(struct mv88e6xxx_chip *chip); /* Precision Time Protocol operations */ const struct mv88e6xxx_ptp_ops *ptp_ops; diff --git a/drivers/net/dsa/mv88e6xxx/global1.c b/drivers/net/dsa/mv88e6xxx/global1.c index 5848112036b0..ba756d918e13 100644 --- a/drivers/net/dsa/mv88e6xxx/global1.c +++ b/drivers/net/dsa/mv88e6xxx/global1.c @@ -466,18 +466,102 @@ int mv88e6085_g1_rmu_disable(struct mv88e6xxx_chip *chip) MV88E6085_G1_CTL2_RM_ENABLE, 0); } +int mv88e6085_g1_rmu_enable(struct mv88e6xxx_chip *chip) +{ + int val = MV88E6352_G1_CTL2_RMU_MODE_DISABLED; + int upstream_port = -1; + + upstream_port = dsa_switch_upstream_port(chip->ds); + dev_err(chip->dev, "RMU: Enabling on port %d", upstream_port); + if (upstream_port < 0) + return -1; + + switch (upstream_port) { + case 9: + val = MV88E6085_G1_CTL2_RM_ENABLE; + break; + case 10: + val = MV88E6085_G1_CTL2_RM_ENABLE | MV88E6085_G1_CTL2_P10RM; + break; + default: + break; + } + + return mv88e6xxx_g1_ctl2_mask(chip, MV88E6085_G1_CTL2_P10RM | + MV88E6085_G1_CTL2_RM_ENABLE, val); +} + int mv88e6352_g1_rmu_disable(struct mv88e6xxx_chip *chip) { return mv88e6xxx_g1_ctl2_mask(chip, MV88E6352_G1_CTL2_RMU_MODE_MASK, MV88E6352_G1_CTL2_RMU_MODE_DISABLED); } +int mv88e6352_g1_rmu_enable(struct mv88e6xxx_chip *chip) +{ + int val = MV88E6352_G1_CTL2_RMU_MODE_DISABLED; + int upstream_port; + + upstream_port = dsa_switch_upstream_port(chip->ds); + dev_err(chip->dev, "RMU: Enabling on port %d", upstream_port); + if (upstream_port < 0) + return -1; + + switch (upstream_port) { + case 4: + val = MV88E6352_G1_CTL2_RMU_MODE_PORT_4; + break; + case 5: + val = MV88E6352_G1_CTL2_RMU_MODE_PORT_5; + break; + case 6: + val = MV88E6352_G1_CTL2_RMU_MODE_PORT_6; + break; + default: + break; + } + + return mv88e6xxx_g1_ctl2_mask(chip, MV88E6352_G1_CTL2_RMU_MODE_MASK, + val); +} + int mv88e6390_g1_rmu_disable(struct mv88e6xxx_chip *chip) { return mv88e6xxx_g1_ctl2_mask(chip, MV88E6390_G1_CTL2_RMU_MODE_MASK, MV88E6390_G1_CTL2_RMU_MODE_DISABLED); } +int mv88e6390_g1_rmu_enable(struct mv88e6xxx_chip *chip) +{ + int val = MV88E6390_G1_CTL2_RMU_MODE_DISABLED; + int upstream_port; + + upstream_port = dsa_switch_upstream_port(chip->ds); + dev_err(chip->dev, "RMU: Enabling on port %d", upstream_port); + if (upstream_port < 0) + return -1; + + switch (upstream_port) { + case 0: + val = MV88E6390_G1_CTL2_RMU_MODE_PORT_0; + break; + case 1: + val = MV88E6390_G1_CTL2_RMU_MODE_PORT_1; + break; + case 9: + val = MV88E6390_G1_CTL2_RMU_MODE_PORT_9; + break; + case 10: + val = MV88E6390_G1_CTL2_RMU_MODE_PORT_10; + break; + default: + break; + } + + return mv88e6xxx_g1_ctl2_mask(chip, MV88E6390_G1_CTL2_RMU_MODE_MASK, + val); +} + int mv88e6390_g1_stats_set_histogram(struct mv88e6xxx_chip *chip) { return mv88e6xxx_g1_ctl2_mask(chip, MV88E6390_G1_CTL2_HIST_MODE_MASK, diff --git a/drivers/net/dsa/mv88e6xxx/global1.h b/drivers/net/dsa/mv88e6xxx/global1.h index 65958b2a0d3a..7e786503734a 100644 --- a/drivers/net/dsa/mv88e6xxx/global1.h +++ b/drivers/net/dsa/mv88e6xxx/global1.h @@ -313,8 +313,11 @@ int mv88e6250_g1_ieee_pri_map(struct mv88e6xxx_chip *chip); int mv88e6185_g1_set_cascade_port(struct mv88e6xxx_chip *chip, int port); int mv88e6085_g1_rmu_disable(struct mv88e6xxx_chip *chip); +int mv88e6085_g1_rmu_enable(struct mv88e6xxx_chip *chip); int mv88e6352_g1_rmu_disable(struct mv88e6xxx_chip *chip); +int mv88e6352_g1_rmu_enable(struct mv88e6xxx_chip *chip); int mv88e6390_g1_rmu_disable(struct mv88e6xxx_chip *chip); +int mv88e6390_g1_rmu_enable(struct mv88e6xxx_chip *chip); int mv88e6xxx_g1_set_device_number(struct mv88e6xxx_chip *chip, int index); diff --git a/drivers/net/dsa/mv88e6xxx/rmu.c b/drivers/net/dsa/mv88e6xxx/rmu.c new file mode 100644 index 000000000000..ac68eef12521 --- /dev/null +++ b/drivers/net/dsa/mv88e6xxx/rmu.c @@ -0,0 +1,256 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Marvell 88E6xxx Switch Remote Management Unit Support + * + * Copyright (c) 2022 Mattias Forsblad + * + */ + +#include "rmu.h" +#include "global1.h" + +#define MAX_RMON 64 +#define RMON_REPLY 2 + +#define RMU_REQ_GET_ID 1 +#define RMU_REQ_DUMP_MIB 2 + +#define RMU_RESP_FORMAT_1 0x0001 +#define RMU_RESP_FORMAT_2 0x0002 + +#define RMU_RESP_CODE_GOT_ID 0x0000 +#define RMU_RESP_CODE_DUMP_MIB 0x1020 + +int mv88e6xxx_inband_rcv(struct dsa_switch *ds, struct sk_buff *skb, int seq_no) +{ + struct mv88e6xxx_chip *chip = ds->priv; + struct mv88e6xxx_port *port; + __be16 *prodnum; + __be16 *format; + __be16 *code; + __be32 *mib_data; + u8 pkt_dev; + u8 pkt_prt; + int i; + + if (!skb || !chip) + return 0; + + /* Extract response data */ + format = (__be16 *)&skb->data[0]; + if (*format != htons(RMU_RESP_FORMAT_1) && (*format != htons(RMU_RESP_FORMAT_2))) { + dev_err(chip->dev, "RMU: received unknown format 0x%04x", *format); + goto out; + } + + code = (__be16 *)&skb->data[4]; + if (*code == ntohs(0xffff)) { + netdev_err(skb->dev, "RMU: error response code 0x%04x", *code); + goto out; + } + + pkt_dev = skb->data[6] & 0x1f; + if (pkt_dev >= DSA_MAX_SWITCHES) { + netdev_err(skb->dev, "RMU: response from unknown chip %d\n", *code); + goto out; + } + + /* Check sequence number */ + if (seq_no != chip->rmu.seq_no) { + netdev_err(skb->dev, "RMU: wrong seqno received %d, expected %d", + seq_no, chip->rmu.seq_no); + goto out; + } + + /* Check response code */ + switch (chip->rmu.request_cmd) { + case RMU_REQ_GET_ID: { + if (*code == RMU_RESP_CODE_GOT_ID) { + prodnum = (__be16 *)&skb->data[2]; + chip->rmu.got_id = *prodnum; + dev_info(chip->dev, "RMU: received id OK with product number: 0x%04x\n", + chip->rmu.got_id); + } else { + dev_err(chip->dev, + "RMU: unknown response for GET_ID format 0x%04x code 0x%04x", + *format, *code); + } + break; + } + case RMU_REQ_DUMP_MIB: + if (*code == RMU_RESP_CODE_DUMP_MIB) { + pkt_prt = (skb->data[7] & 0x78) >> 3; + mib_data = (__be32 *)&skb->data[12]; + port = &chip->ports[pkt_prt]; + if (!port) { + dev_err(chip->dev, "RMU: illegal port number in response: %d\n", + pkt_prt); + goto out; + } + + /* Copy whole array for further + * processing according to chip type + */ + for (i = 0; i < MAX_RMON; i++) + port->rmu_raw_stats[i] = mib_data[i]; + } + break; + default: + dev_err(chip->dev, + "RMU: unknown response format 0x%04x and code 0x%04x from chip %d\n", + *format, *code, chip->ds->index); + break; + } + +out: + complete(&chip->rmu.completion); + + return 0; +} + +static int mv88e6xxx_rmu_tx(struct mv88e6xxx_chip *chip, int port, + const char *msg, int len) +{ + const struct dsa_device_ops *tag_ops; + const struct dsa_port *dp; + unsigned char *data; + struct sk_buff *skb; + + dp = dsa_to_port(chip->ds, port); + if (!dp || !dp->cpu_dp) + return 0; + + tag_ops = dp->cpu_dp->tag_ops; + if (!tag_ops) + return -ENODEV; + + skb = netdev_alloc_skb(chip->rmu.netdev, 64); + if (!skb) + return -ENOMEM; + + skb_reserve(skb, 2 * ETH_HLEN + tag_ops->needed_headroom); + skb_reset_network_header(skb); + skb->pkt_type = PACKET_OUTGOING; + skb->dev = chip->rmu.netdev; + + /* Create RMU L3 message */ + data = skb_put(skb, len); + memcpy(data, msg, len); + + return tag_ops->inband_xmit(skb, dp->slave, ++chip->rmu.seq_no); +} + +static int mv88e6xxx_rmu_send_wait(struct mv88e6xxx_chip *chip, int port, + int request, const char *msg, int len) +{ + const struct dsa_port *dp; + struct net_device *master; + int ret = 0; + + dp = dsa_to_port(chip->ds, port); + if (!dp) + return 0; + + master = dp->master; + + mutex_lock(&chip->rmu.mutex); + + chip->rmu.request_cmd = request; + + ret = mv88e6xxx_rmu_tx(chip, port, msg, len); + if (ret == -ENODEV) { + /* Device not ready yet? Try again later */ + ret = 0; + goto out; + } + + if (ret) { + dev_err(chip->dev, "RMU: error transmitting request (%d)", ret); + goto out; + } + + ret = wait_for_completion_timeout(&chip->rmu.completion, + msecs_to_jiffies(MV88E6XXX_WAIT_POLL_TIME_MS)); + if (ret == 0) { + dev_err(chip->dev, + "RMU: timeout waiting for request %d (%d) on dev:port %d:%d\n", + request, ret, chip->ds->index, port); + ret = -ETIMEDOUT; + } + +out: + mutex_unlock(&chip->rmu.mutex); + + return ret > 0 ? 0 : ret; +} + +static int mv88e6xxx_rmu_get_id(struct mv88e6xxx_chip *chip, int port) +{ + const u8 get_id[8] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + int ret = -1; + + if (chip->rmu.got_id) + return 0; + + chip->rmu.netdev = dev_get_by_name(&init_net, "chan0"); + if (!chip->rmu.netdev) { + dev_err(chip->dev, "RMU: unable to get interface"); + return -ENODEV; + } + + ret = mv88e6xxx_rmu_send_wait(chip, port, RMU_REQ_GET_ID, get_id, 8); + if (ret) { + dev_err(chip->dev, "RMU: error for command GET_ID %d index %d\n", ret, + chip->ds->index); + return ret; + } + + return 0; +} + +int mv88e6xxx_rmu_stats_get(struct mv88e6xxx_chip *chip, int port, uint64_t *data) +{ + u8 dump_mib[8] = { 0x00, 0x01, 0x00, 0x00, 0x10, 0x20, 0x00, 0x00 }; + int ret; + + if (!chip) + return 0; + + ret = mv88e6xxx_rmu_get_id(chip, port); + if (ret) + return ret; + + /* Send a GET_MIB command */ + dump_mib[7] = port; + ret = mv88e6xxx_rmu_send_wait(chip, port, RMU_REQ_DUMP_MIB, dump_mib, 8); + if (ret) { + dev_err(chip->dev, "RMU: error for command DUMP_MIB %d dev %d:%d\n", ret, + chip->ds->index, port); + return ret; + } + + /* Update MIB for port */ + if (chip->info->ops->stats_get_stats) + return chip->info->ops->stats_get_stats(chip, port, data); + + return 0; +} + +static struct mv88e6xxx_bus_ops mv88e6xxx_bus_ops = { + .get_rmon = mv88e6xxx_rmu_stats_get, +}; + +int mv88e6xxx_rmu_init(struct mv88e6xxx_chip *chip) +{ + int ret = 0; + + dev_info(chip->dev, "RMU: setting up for switch@%d", chip->sw_addr); + + init_completion(&chip->rmu.completion); + + mutex_init(&chip->rmu.mutex); + + chip->rmu.ops = &mv88e6xxx_bus_ops; + + return ret; +} diff --git a/drivers/net/dsa/mv88e6xxx/rmu.h b/drivers/net/dsa/mv88e6xxx/rmu.h new file mode 100644 index 000000000000..3f74e952cad9 --- /dev/null +++ b/drivers/net/dsa/mv88e6xxx/rmu.h @@ -0,0 +1,18 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Marvell 88E6xxx Switch Remote Management Unit Support + * + * Copyright (c) 2022 Mattias Forsblad + * + */ + +#ifndef _MV88E6XXX_RMU_H_ +#define _MV88E6XXX_RMU_H_ + +#include "chip.h" + +int mv88e6xxx_rmu_init(struct mv88e6xxx_chip *chip); + +int mv88e6xxx_inband_rcv(struct dsa_switch *ds, struct sk_buff *skb, int seq_no); + +#endif /* _MV88E6XXX_RMU_H_ */ From patchwork Thu Aug 18 10:29:24 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mattias Forsblad X-Patchwork-Id: 12946897 X-Patchwork-Delegate: kuba@kernel.org Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 56EBAC00140 for ; Thu, 18 Aug 2022 10:29:58 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S244084AbiHRK34 (ORCPT ); Thu, 18 Aug 2022 06:29:56 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:54154 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S239816AbiHRK3u (ORCPT ); Thu, 18 Aug 2022 06:29:50 -0400 Received: from mail-lj1-x22d.google.com (mail-lj1-x22d.google.com [IPv6:2a00:1450:4864:20::22d]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 7ED016FA05 for ; Thu, 18 Aug 2022 03:29:48 -0700 (PDT) Received: by mail-lj1-x22d.google.com with SMTP id q16so711778ljp.7 for ; Thu, 18 Aug 2022 03:29:48 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc; bh=eAHy0GgVxTHg1eUciceHmM/Hyp1NsAkVTFVZaJvQ9zY=; b=EePFQ4ppu84vqkjd7Tzzlqwgp7K+RPZHTJMHzKh6jWQHbJMdzUiTQrhB7PHRR8VT7v kxxMZJVtXHa6IRaF5jsDn6b5jXbTQI4y/QOLiyRzOi0WhxFyh/UbxBhcFkRllVPKjExD eOc5ikUIdZ4Iqa8Erao9Ck3L1bC1fVXf/KsnuqAJ43crez+yQJaXFVGs3Viy2m+w6C8C 9ebrxnSE8qnBDW18lK0vcnW+xf54Hl+Agb3c+RApvf0M8z4wjOPUHNhfvqKN+DJJFiXG dlRpLJAkT4T1lceUUxvGw5mSRL6V2HLaZljjQ8Fabf0af4IukZWIJs9M4NFl24CXGlYO fGtw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc; bh=eAHy0GgVxTHg1eUciceHmM/Hyp1NsAkVTFVZaJvQ9zY=; b=jp6VUVcLYMOBj2B2Ro7VdfYDCOaDqBpMR8fUsyORMXtNpNM9M5qBrkks8sg22obWr1 FyFUC+98Xpt2KjZfk1AUp4LbuoE8s/Tgyq6AYMW8uRNl4rkitk3jITjkc6hTRPI+3ag5 unwahv60hKbbREz1i1UCrNoDUbo1vucDb4xCQBDqK/SQfOsz1pwXgqGYAtMp6/6IGGJy 2MbGS8MWDJiwbaNeMzdJm1LIzDR8KsI2X6S0r4o3CxhOz/f3D/AkJVuOAvDLVPVFAYD0 sXRM2ZZGLd62qL8b+MVyimrZS03ReIWFbwSippz0ktd+lvy1tuoiRkBAhGC+XYMDeDAz BfJw== X-Gm-Message-State: ACgBeo3KPXNo/w4wLrqRrSPRPVrF7DuimgguOevF77UXhrtUIEnRi6hD XvAkUe3JMnK3DwLx0GYrYXTKI9AgadqFIw== X-Google-Smtp-Source: AA6agR4KOI0eQ5F1mJ6pidHUzTFHF/1ljDnwii/EleoMLuPiGTHBWCa3CPRKsRdAE9fC5yUqbTvEGQ== X-Received: by 2002:a05:651c:1248:b0:261:7fe4:9a99 with SMTP id h8-20020a05651c124800b002617fe49a99mr682651ljh.223.1660818586675; Thu, 18 Aug 2022 03:29:46 -0700 (PDT) Received: from wse-c0089.raspi.local (h-98-128-229-160.NA.cust.bahnhof.se. [98.128.229.160]) by smtp.gmail.com with ESMTPSA id z10-20020a056512370a00b0048afa5daaf3sm171035lfr.123.2022.08.18.03.29.45 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 18 Aug 2022 03:29:46 -0700 (PDT) From: Mattias Forsblad To: netdev@vger.kernel.org Cc: Andrew Lunn , Vivien Didelot , Florian Fainelli , Vladimir Oltean , "David S . Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Mattias Forsblad Subject: [RFC net-next PATCH 3/3] mv88e6xxx: rmon: Use RMU to collect rmon data. Date: Thu, 18 Aug 2022 12:29:24 +0200 Message-Id: <20220818102924.287719-4-mattias.forsblad@gmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220818102924.287719-1-mattias.forsblad@gmail.com> References: <20220818102924.287719-1-mattias.forsblad@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org X-Patchwork-Delegate: kuba@kernel.org X-Patchwork-State: RFC If RMU is supported, use that interface to collect rmon data. Signed-off-by: Mattias Forsblad --- drivers/net/dsa/mv88e6xxx/chip.c | 41 +++++++++++++++++++++++--------- 1 file changed, 30 insertions(+), 11 deletions(-) diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index 888c6e47dd16..344d6633ad6d 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -1226,16 +1226,29 @@ static int mv88e6xxx_stats_get_stats(struct mv88e6xxx_chip *chip, int port, u16 bank1_select, u16 histogram) { struct mv88e6xxx_hw_stat *stat; + int offset = 0; + u64 high; int i, j; for (i = 0, j = 0; i < ARRAY_SIZE(mv88e6xxx_hw_stats); i++) { stat = &mv88e6xxx_hw_stats[i]; if (stat->type & types) { - mv88e6xxx_reg_lock(chip); - data[j] = _mv88e6xxx_get_ethtool_stat(chip, stat, port, - bank1_select, - histogram); - mv88e6xxx_reg_unlock(chip); + if (chip->rmu.ops->get_rmon && !(stat->type & STATS_TYPE_PORT)) { + if (stat->type & STATS_TYPE_BANK1) + offset = 32; + + data[j] = chip->ports[port].rmu_raw_stats[stat->reg + offset]; + if (stat->size == 8) { + high = chip->ports[port].rmu_raw_stats[stat->reg + offset + + 1]; + data[j] += (high << 32); + } + } else { + mv88e6xxx_reg_lock(chip); + data[j] = _mv88e6xxx_get_ethtool_stat(chip, stat, port, + bank1_select, histogram); + mv88e6xxx_reg_unlock(chip); + } j++; } @@ -1310,16 +1323,22 @@ static void mv88e6xxx_get_ethtool_stats(struct dsa_switch *ds, int port, struct mv88e6xxx_chip *chip = ds->priv; int ret; - mv88e6xxx_reg_lock(chip); + if (chip->rmu.ops && chip->rmu.ops->get_rmon) { + ret = chip->rmu.ops->get_rmon(chip, port, data); + if (ret == -ETIMEDOUT) + return; + } else { - ret = mv88e6xxx_stats_snapshot(chip, port); - mv88e6xxx_reg_unlock(chip); + mv88e6xxx_reg_lock(chip); - if (ret < 0) - return; + ret = mv88e6xxx_stats_snapshot(chip, port); + mv88e6xxx_reg_unlock(chip); - mv88e6xxx_get_stats(chip, port, data); + if (ret < 0) + return; + mv88e6xxx_get_stats(chip, port, data); + } } static int mv88e6xxx_get_regs_len(struct dsa_switch *ds, int port)