* Re: [PATCH 2/2] usb: qmi_wwan: add D-Link DWM-222 device ID
From: David Miller @ 2017-08-02 17:47 UTC (permalink / raw)
To: marcan; +Cc: bjorn, netdev, linux-usb, linux-kernel, stable
In-Reply-To: <20170801154544.1104-1-marcan@marcan.st>
From: Hector Martin <marcan@marcan.st>
Date: Wed, 2 Aug 2017 00:45:44 +0900
> Signed-off-by: Hector Martin <marcan@marcan.st>
Applied.
^ permalink raw reply
* Re: [PATCH net-next] tcp: tcp_data_queue() cleanup
From: David Miller @ 2017-08-02 17:45 UTC (permalink / raw)
To: eric.dumazet; +Cc: netdev, fw
In-Reply-To: <1501596164.25002.4.camel@edumazet-glaptop3.roam.corp.google.com>
From: Eric Dumazet <eric.dumazet@gmail.com>
Date: Tue, 01 Aug 2017 07:02:44 -0700
> From: Eric Dumazet <edumazet@google.com>
>
> Commit c13ee2a4f03f ("tcp: reindent two spots after prequeue removal")
> removed code in tcp_data_queue().
>
> We can go a little farther, removing an always true test,
> and removing initializers for fragstolen and eaten variables.
>
> Signed-off-by: Eric Dumazet <edumazet@google.com>
Series applied, thanks!
^ permalink raw reply
* Re: [PATCH net 0/4] mlx4 misc fixes
From: David Miller @ 2017-08-02 17:44 UTC (permalink / raw)
To: tariqt; +Cc: netdev, eranbe
In-Reply-To: <1501595026-32368-1-git-send-email-tariqt@mellanox.com>
From: Tariq Toukan <tariqt@mellanox.com>
Date: Tue, 1 Aug 2017 16:43:42 +0300
> This patchset contains misc bug fixes from the team
> to the mlx4 Core and Eth drivers.
>
> Patch 1 by Inbar fixes a wrong ethtool indication for Wake-on-LAN.
> The other 3 patches by Jack add a missing capability description,
> and fixes the off-by-1 misalignment for the following capabilities
> descriptions.
>
> Series generated against net commit:
> cc75f8514db6 samples/bpf: fix bpf tunnel cleanup
Series applied, thanks!
^ permalink raw reply
* Re: [PATCH net-next] net: bcmgenet: drop COMPILE_TEST dependency
From: David Miller @ 2017-08-02 17:42 UTC (permalink / raw)
To: arnd; +Cc: f.fainelli, michael.chan, sathya.perla, netdev, linux-kernel
In-Reply-To: <20170801115121.1246540-1-arnd@arndb.de>
From: Arnd Bergmann <arnd@arndb.de>
Date: Tue, 1 Aug 2017 13:50:56 +0200
> The last patch added the dependency on 'OF && HAS_IOMEM' but left
> COMPILE_TEST as an alternative, which kind of defeats the purpose
> of adding the dependency, we still get randconfig build warnings:
>
> warning: (NET_DSA_BCM_SF2 && BCMGENET) selects MDIO_BCM_UNIMAC which has unmet direct dependencies (NETDEVICES && MDIO_BUS && HAS_IOMEM && OF_MDIO)
>
> For compile-testing purposes, we don't really need this anyway,
> as CONFIG_OF can be enabled on all architectures, and HAS_IOMEM
> is present on all architectures we do meaningful compile-testing on
> (the exception being arch/um).
>
> This makes both OF and HAS_IOMEM hard dependencies.
>
> Fixes: 5af74bb4fcf8 ("net: bcmgenet: Add dependency on HAS_IOMEM && OF")
> Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Applied.
^ permalink raw reply
* Re: [PATCH net 0/2] lan78xx: Fixes to lan78xx driver
From: David Miller @ 2017-08-02 17:40 UTC (permalink / raw)
To: Nisar.Sayed; +Cc: UNGLinuxDriver, netdev
In-Reply-To: <CE371C1263339941885964188A0225FA322BC3@CHN-SV-EXMX03.mchp-main.com>
From: <Nisar.Sayed@microchip.com>
Date: Tue, 1 Aug 2017 10:23:52 +0000
> From: Nisar Sayed <Nisar.Sayed@microchip.com>
>
> This series of patches are for lan78xx driver.
>
> These patches fixes potential issues associated with lan78xx driver
Series applied, thanks.
^ permalink raw reply
* Re: [PATCH v3 10/11] ARM64: dts: rockchip: Add gmac2phy node support for rk3328
From: Florian Fainelli @ 2017-08-02 17:40 UTC (permalink / raw)
To: David Wu, davem, heiko, andrew, robh+dt, mark.rutland,
catalin.marinas, will.deacon, olof, linux, arnd
Cc: peppe.cavallaro, alexandre.torgue, huangtao, hwg, netdev,
linux-arm-kernel, linux-rockchip, devicetree, linux-kernel
In-Reply-To: <1501655097-21054-1-git-send-email-david.wu@rock-chips.com>
On 08/01/2017 11:24 PM, David Wu wrote:
> The gmac2phy controller of rk3328 is connected to internal phy
> directly inside, add the node for the internal phy support.
>
> Signed-off-by: David Wu <david.wu@rock-chips.com>
> ---
> arch/arm64/boot/dts/rockchip/rk3328.dtsi | 25 +++++++++++++++++++++++++
> 1 file changed, 25 insertions(+)
>
> diff --git a/arch/arm64/boot/dts/rockchip/rk3328.dtsi b/arch/arm64/boot/dts/rockchip/rk3328.dtsi
> index 0be96ce..51c8c66 100644
> --- a/arch/arm64/boot/dts/rockchip/rk3328.dtsi
> +++ b/arch/arm64/boot/dts/rockchip/rk3328.dtsi
> @@ -63,6 +63,8 @@
> i2c1 = &i2c1;
> i2c2 = &i2c2;
> i2c3 = &i2c3;
> + ethernet0 = &gmac2io;
> + ethernet1 = &gmac2phy;
> };
>
> cpus {
> @@ -424,6 +426,29 @@
> status = "disabled";
> };
>
> + gmac2phy: eth@ff550000 {
> + compatible = "rockchip,rk3328-gmac";
> + reg = <0x0 0xff550000 0x0 0x10000>;
> + rockchip,grf = <&grf>;
> + interrupts = <GIC_SPI 21 IRQ_TYPE_LEVEL_HIGH>;
> + interrupt-names = "macirq";
> + clocks = <&cru SCLK_MAC2PHY_SRC>, <&cru SCLK_MAC2PHY_RXTX>,
> + <&cru SCLK_MAC2PHY_RXTX>, <&cru SCLK_MAC2PHY_REF>,
> + <&cru ACLK_MAC2PHY>, <&cru PCLK_MAC2PHY>,
> + <&cru SCLK_MAC2PHY_OUT>;
> + clock-names = "stmmaceth", "mac_clk_rx",
> + "mac_clk_tx", "clk_mac_ref",
> + "aclk_mac", "pclk_mac",
> + "clk_macphy";
> + resets = <&cru SRST_GMAC2PHY_A>, <&cru SRST_MACPHY>;
> + reset-names = "stmmaceth", "mac-phy";
> + phy-mode = "rmii";
> + phy-is-internal;
> + pinctrl-names = "default";
> + pinctrl-0 = <&fephyled_rxm1 &fephyled_linkm1>;
> + status = "disabled";
But where is the the phy-handle property that points to this internal
PHY? Even if it is internal, it should be described properly with a mdio
bus sub-node and a standard Ethernet PHY node as specified by both
Documentation/devicetree/bindings/net/mdio.txt and
Documentation/devicetree/bindings/net/phy.txt
That means we should at least see something like this (on top of what
you added already)
phy-handle = <&phy0>;
mdio {
compatible = "snps,dwmac-mdio";
#address-cells = <1>;
#size-cells = <0>;
phy@0 {
compatible = "ethernet-phy-id1234.d400", "ethernet-phy-802.3-c22";
reg = <0>;
phy-is-internal;
};
};
> + };
> +
> gic: interrupt-controller@ff811000 {
> compatible = "arm,gic-400";
> #interrupt-cells = <3>;
>
--
Florian
^ permalink raw reply
* [PATCH net-next] rds: reduce memory footprint for RDS when transport is RDMA
From: Sowmini Varadhan @ 2017-08-02 17:34 UTC (permalink / raw)
To: netdev, sowmini.varadhan
Cc: davem, rds-devel, sowmini.varadhan, santosh.shilimkar
RDS over IB does not use multipath RDS, so the array
of additional rds_conn_path structures is always superfluous
in this case. Reduce the memory footprint of the rds module
by making this a dynamic allocation predicated on whether
the transport is mp_capable.
Signed-off-by: Sowmini Varadhan <sowmini.varadhan@oracle.com>
Acked-by: Santosh Shilimkar <santosh.shilimkar@oracle.com>
Tested-by: Efrain Galaviz <efrain.galaviz@oracle.com>
---
net/rds/connection.c | 34 +++++++++++++++++++++++++---------
net/rds/rds.h | 2 +-
2 files changed, 26 insertions(+), 10 deletions(-)
diff --git a/net/rds/connection.c b/net/rds/connection.c
index 005bca6..7ee2d5d 100644
--- a/net/rds/connection.c
+++ b/net/rds/connection.c
@@ -151,6 +151,7 @@ static void __rds_conn_path_init(struct rds_connection *conn,
struct rds_transport *loop_trans;
unsigned long flags;
int ret, i;
+ int npaths = (trans->t_mp_capable ? RDS_MPATH_WORKERS : 1);
rcu_read_lock();
conn = rds_conn_lookup(net, head, laddr, faddr, trans);
@@ -172,6 +173,12 @@ static void __rds_conn_path_init(struct rds_connection *conn,
conn = ERR_PTR(-ENOMEM);
goto out;
}
+ conn->c_path = kcalloc(npaths, sizeof(struct rds_conn_path), gfp);
+ if (!conn->c_path) {
+ kmem_cache_free(rds_conn_slab, conn);
+ conn = ERR_PTR(-ENOMEM);
+ goto out;
+ }
INIT_HLIST_NODE(&conn->c_hash_node);
conn->c_laddr = laddr;
@@ -181,6 +188,7 @@ static void __rds_conn_path_init(struct rds_connection *conn,
ret = rds_cong_get_maps(conn);
if (ret) {
+ kfree(conn->c_path);
kmem_cache_free(rds_conn_slab, conn);
conn = ERR_PTR(ret);
goto out;
@@ -207,13 +215,14 @@ static void __rds_conn_path_init(struct rds_connection *conn,
conn->c_trans = trans;
init_waitqueue_head(&conn->c_hs_waitq);
- for (i = 0; i < RDS_MPATH_WORKERS; i++) {
+ for (i = 0; i < npaths; i++) {
__rds_conn_path_init(conn, &conn->c_path[i],
is_outgoing);
conn->c_path[i].cp_index = i;
}
ret = trans->conn_alloc(conn, gfp);
if (ret) {
+ kfree(conn->c_path);
kmem_cache_free(rds_conn_slab, conn);
conn = ERR_PTR(ret);
goto out;
@@ -236,6 +245,7 @@ static void __rds_conn_path_init(struct rds_connection *conn,
/* Creating passive conn */
if (parent->c_passive) {
trans->conn_free(conn->c_path[0].cp_transport_data);
+ kfree(conn->c_path);
kmem_cache_free(rds_conn_slab, conn);
conn = parent->c_passive;
} else {
@@ -252,7 +262,7 @@ static void __rds_conn_path_init(struct rds_connection *conn,
struct rds_conn_path *cp;
int i;
- for (i = 0; i < RDS_MPATH_WORKERS; i++) {
+ for (i = 0; i < npaths; i++) {
cp = &conn->c_path[i];
/* The ->conn_alloc invocation may have
* allocated resource for all paths, so all
@@ -261,6 +271,7 @@ static void __rds_conn_path_init(struct rds_connection *conn,
if (cp->cp_transport_data)
trans->conn_free(cp->cp_transport_data);
}
+ kfree(conn->c_path);
kmem_cache_free(rds_conn_slab, conn);
conn = found;
} else {
@@ -407,6 +418,7 @@ void rds_conn_destroy(struct rds_connection *conn)
unsigned long flags;
int i;
struct rds_conn_path *cp;
+ int npaths = (conn->c_trans->t_mp_capable ? RDS_MPATH_WORKERS : 1);
rdsdebug("freeing conn %p for %pI4 -> "
"%pI4\n", conn, &conn->c_laddr,
@@ -420,7 +432,7 @@ void rds_conn_destroy(struct rds_connection *conn)
synchronize_rcu();
/* shut the connection down */
- for (i = 0; i < RDS_MPATH_WORKERS; i++) {
+ for (i = 0; i < npaths; i++) {
cp = &conn->c_path[i];
rds_conn_path_destroy(cp);
BUG_ON(!list_empty(&cp->cp_retrans));
@@ -434,6 +446,7 @@ void rds_conn_destroy(struct rds_connection *conn)
rds_cong_remove_conn(conn);
put_net(conn->c_net);
+ kfree(conn->c_path);
kmem_cache_free(rds_conn_slab, conn);
spin_lock_irqsave(&rds_conn_lock, flags);
@@ -464,8 +477,12 @@ static void rds_conn_message_info(struct socket *sock, unsigned int len,
i++, head++) {
hlist_for_each_entry_rcu(conn, head, c_hash_node) {
struct rds_conn_path *cp;
+ int npaths;
+
+ npaths = (conn->c_trans->t_mp_capable ?
+ RDS_MPATH_WORKERS : 1);
- for (j = 0; j < RDS_MPATH_WORKERS; j++) {
+ for (j = 0; j < npaths; j++) {
cp = &conn->c_path[j];
if (want_send)
list = &cp->cp_send_queue;
@@ -486,8 +503,6 @@ static void rds_conn_message_info(struct socket *sock, unsigned int len,
}
spin_unlock_irqrestore(&cp->cp_lock, flags);
- if (!conn->c_trans->t_mp_capable)
- break;
}
}
}
@@ -571,15 +586,16 @@ static void rds_walk_conn_path_info(struct socket *sock, unsigned int len,
i++, head++) {
hlist_for_each_entry_rcu(conn, head, c_hash_node) {
struct rds_conn_path *cp;
+ int npaths;
- for (j = 0; j < RDS_MPATH_WORKERS; j++) {
+ npaths = (conn->c_trans->t_mp_capable ?
+ RDS_MPATH_WORKERS : 1);
+ for (j = 0; j < npaths; j++) {
cp = &conn->c_path[j];
/* XXX no cp_lock usage.. */
if (!visitor(cp, buffer))
continue;
- if (!conn->c_trans->t_mp_capable)
- break;
}
/* We copy as much as we can fit in the buffer,
diff --git a/net/rds/rds.h b/net/rds/rds.h
index 3382695..2e0315b 100644
--- a/net/rds/rds.h
+++ b/net/rds/rds.h
@@ -154,7 +154,7 @@ struct rds_connection {
struct list_head c_map_item;
unsigned long c_map_queued;
- struct rds_conn_path c_path[RDS_MPATH_WORKERS];
+ struct rds_conn_path *c_path;
wait_queue_head_t c_hs_waitq; /* handshake waitq */
u32 c_my_gen_num;
--
1.7.1
^ permalink raw reply related
* Re: [PATCH v3 05/11] net: stmmac: dwmac-rk: Add internal phy support
From: Florian Fainelli @ 2017-08-02 17:38 UTC (permalink / raw)
To: David Wu, davem-fT/PcQaiUtIeIZ0/mPfg9Q,
heiko-4mtYJXux2i+zQB+pC5nmwQ, andrew-g2DYL2Zd6BY,
robh+dt-DgEjT+Ai2ygdnm+yROfE0A, mark.rutland-5wv7dgnIgG8,
catalin.marinas-5wv7dgnIgG8, will.deacon-5wv7dgnIgG8,
olof-nZhT3qVonbNeoWH0uzbU5w, linux-I+IVW8TIWO2tmTQ+vhA3Yw,
arnd-r2nGTMty4D4
Cc: peppe.cavallaro-qxv4g6HH51o, alexandre.torgue-qxv4g6HH51o,
huangtao-TNX95d0MmH7DzftRWevZcw, hwg-TNX95d0MmH7DzftRWevZcw,
netdev-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-rockchip-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <1501654888-19514-1-git-send-email-david.wu-TNX95d0MmH7DzftRWevZcw@public.gmane.org>
On 08/01/2017 11:21 PM, David Wu wrote:
> To make internal phy work, need to configure the phy_clock,
> phy cru_reset and related registers.
>
> Signed-off-by: David Wu <david.wu-TNX95d0MmH7DzftRWevZcw@public.gmane.org>
> ---
> .../devicetree/bindings/net/rockchip-dwmac.txt | 6 +-
> drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c | 81 ++++++++++++++++++++++
> 2 files changed, 86 insertions(+), 1 deletion(-)
>
> diff --git a/Documentation/devicetree/bindings/net/rockchip-dwmac.txt b/Documentation/devicetree/bindings/net/rockchip-dwmac.txt
> index 8f42755..ec39b31 100644
> --- a/Documentation/devicetree/bindings/net/rockchip-dwmac.txt
> +++ b/Documentation/devicetree/bindings/net/rockchip-dwmac.txt
> @@ -25,7 +25,8 @@ Required properties:
> - clock-names: One name for each entry in the clocks property.
> - phy-mode: See ethernet.txt file in the same directory.
> - pinctrl-names: Names corresponding to the numbered pinctrl states.
> - - pinctrl-0: pin-control mode. can be <&rgmii_pins> or <&rmii_pins>.
> + - pinctrl-0: pin-control mode. can be <&rgmii_pins>, <&rmii_pins> or led pins
> + for internal phy mode.
> - clock_in_out: For RGMII, it must be "input", means main clock(125MHz)
> is not sourced from SoC's PLL, but input from PHY; For RMII, "input" means
> PHY provides the reference clock(50MHz), "output" means GMAC provides the
> @@ -40,6 +41,9 @@ Optional properties:
> - tx_delay: Delay value for TXD timing. Range value is 0~0x7F, 0x30 as default.
> - rx_delay: Delay value for RXD timing. Range value is 0~0x7F, 0x10 as default.
> - phy-supply: phandle to a regulator if the PHY needs one
> + - clocks: <&cru MAC_PHY>: Clock selector for internal macphy
> + - phy-is-internal: A boolean property allows us to know that MAC will connect to
> + internal phy.
This is incorrect in two ways:
- this is a property of the PHY, so it should be documented as such in
Documentation/devicetree/bindings/net/phy.txt so other bindings can
re-use it
- if it was specific to your MAC you would expect a vendor prefix to
this property, which is not there
An alternative way to implement the external/internal logic selection
would be mandate that your Ethernet PHY node have a compatible string
like this:
phy@0 {
compatible = "ethernet-phy-id1234.d400", "ethernet-phy-802.3-c22";
};
Then you don't need this phy-is-internal property, because you can
locate the PHY node by the phy-handle (see more about that in a reply to
patch 10) and you can determine ahead of time whether this PHY is
internal or not based on its compatible string.
Thank you
>
> Example:
>
> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
> index a8e8fd5..7b80ab9 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
> @@ -41,6 +41,7 @@ struct rk_gmac_ops {
> void (*set_to_rmii)(struct rk_priv_data *bsp_priv);
> void (*set_rgmii_speed)(struct rk_priv_data *bsp_priv, int speed);
> void (*set_rmii_speed)(struct rk_priv_data *bsp_priv, int speed);
> + void (*internal_phy_powerup)(struct rk_priv_data *bsp_priv);
> };
>
> struct rk_priv_data {
> @@ -52,6 +53,7 @@ struct rk_priv_data {
>
> bool clk_enabled;
> bool clock_input;
> + bool internal_phy;
>
> struct clk *clk_mac;
> struct clk *gmac_clkin;
> @@ -61,6 +63,9 @@ struct rk_priv_data {
> struct clk *clk_mac_refout;
> struct clk *aclk_mac;
> struct clk *pclk_mac;
> + struct clk *clk_macphy;
> +
> + struct reset_control *macphy_reset;
>
> int tx_delay;
> int rx_delay;
> @@ -750,6 +755,50 @@ static void rk3399_set_rmii_speed(struct rk_priv_data *bsp_priv, int speed)
> .set_rmii_speed = rk3399_set_rmii_speed,
> };
>
> +#define RK_GRF_MACPHY_CON0 0xb00
> +#define RK_GRF_MACPHY_CON1 0xb04
> +#define RK_GRF_MACPHY_CON2 0xb08
> +#define RK_GRF_MACPHY_CON3 0xb0c
> +
> +#define RK_MACPHY_ENABLE GRF_BIT(0)
> +#define RK_MACPHY_DISABLE GRF_CLR_BIT(0)
> +#define RK_MACPHY_CFG_CLK_50M GRF_BIT(14)
> +#define RK_GMAC2PHY_RMII_MODE (GRF_BIT(6) | GRF_CLR_BIT(7))
> +#define RK_GRF_CON2_MACPHY_ID HIWORD_UPDATE(0x1234, 0xffff, 0)
> +#define RK_GRF_CON3_MACPHY_ID HIWORD_UPDATE(0x35, 0x3f, 0)
> +
> +static void rk_gmac_internal_phy_powerup(struct rk_priv_data *priv)
> +{
> + if (priv->ops->internal_phy_powerup)
> + priv->ops->internal_phy_powerup(priv);
> +
> + regmap_write(priv->grf, RK_GRF_MACPHY_CON0, RK_MACPHY_CFG_CLK_50M);
> + regmap_write(priv->grf, RK_GRF_MACPHY_CON0, RK_GMAC2PHY_RMII_MODE);
> +
> + regmap_write(priv->grf, RK_GRF_MACPHY_CON2, RK_GRF_CON2_MACPHY_ID);
> + regmap_write(priv->grf, RK_GRF_MACPHY_CON3, RK_GRF_CON3_MACPHY_ID);
> +
> + if (priv->macphy_reset) {
> + /* macphy needs to be disabled before trying to reset it */
> + regmap_write(priv->grf, RK_GRF_MACPHY_CON0, RK_MACPHY_DISABLE);
> + if (priv->macphy_reset)
> + reset_control_assert(priv->macphy_reset);
> + usleep_range(10, 20);
> + if (priv->macphy_reset)
> + reset_control_deassert(priv->macphy_reset);
> + usleep_range(10, 20);
> + regmap_write(priv->grf, RK_GRF_MACPHY_CON0, RK_MACPHY_ENABLE);
> + msleep(30);
> + }
> +}
> +
> +static void rk_gmac_internal_phy_powerdown(struct rk_priv_data *priv)
> +{
> + regmap_write(priv->grf, RK_GRF_MACPHY_CON0, RK_MACPHY_DISABLE);
> + if (priv->macphy_reset)
> + reset_control_assert(priv->macphy_reset);
> +}
> +
> static int gmac_clk_init(struct rk_priv_data *bsp_priv)
> {
> struct device *dev = &bsp_priv->pdev->dev;
> @@ -803,6 +852,14 @@ static int gmac_clk_init(struct rk_priv_data *bsp_priv)
> clk_set_rate(bsp_priv->clk_mac, 50000000);
> }
>
> + if (bsp_priv->internal_phy) {
> + bsp_priv->clk_macphy = devm_clk_get(dev, "clk_macphy");
> + if (IS_ERR(bsp_priv->clk_macphy))
> + dev_err(dev, "cannot get %s clock\n", "clk_macphy");
> + else
> + clk_set_rate(bsp_priv->clk_macphy, 50000000);
> + }
> +
> return 0;
> }
>
> @@ -826,6 +883,9 @@ static int gmac_clk_enable(struct rk_priv_data *bsp_priv, bool enable)
> bsp_priv->clk_mac_refout);
> }
>
> + if (!IS_ERR(bsp_priv->clk_macphy))
> + clk_prepare_enable(bsp_priv->clk_macphy);
> +
> if (!IS_ERR(bsp_priv->aclk_mac))
> clk_prepare_enable(bsp_priv->aclk_mac);
>
> @@ -858,6 +918,9 @@ static int gmac_clk_enable(struct rk_priv_data *bsp_priv, bool enable)
> bsp_priv->clk_mac_refout);
> }
>
> + if (!IS_ERR(bsp_priv->clk_macphy))
> + clk_disable_unprepare(bsp_priv->clk_macphy);
> +
> if (!IS_ERR(bsp_priv->aclk_mac))
> clk_disable_unprepare(bsp_priv->aclk_mac);
>
> @@ -940,6 +1003,18 @@ static struct rk_priv_data *rk_gmac_setup(struct platform_device *pdev,
> bsp_priv->clock_input = false;
> }
>
> + bsp_priv->internal_phy = device_property_read_bool(dev,
> + "phy-is-internal");
> + if (bsp_priv->internal_phy) {
> + bsp_priv->macphy_reset = devm_reset_control_get(dev, "mac-phy");
> + if (IS_ERR(bsp_priv->macphy_reset)) {
> + dev_info(dev, "no macphy_reset control found\n");
> + bsp_priv->macphy_reset = NULL;
> + }
> + }
> + dev_info(dev, "internal PHY? (%s).\n",
> + bsp_priv->internal_phy ? "yes" : "no");
> +
> ret = of_property_read_u32(dev->of_node, "tx_delay", &value);
> if (ret) {
> bsp_priv->tx_delay = 0x30;
> @@ -1014,6 +1089,9 @@ static int rk_gmac_powerup(struct rk_priv_data *bsp_priv)
> pm_runtime_enable(dev);
> pm_runtime_get_sync(dev);
>
> + if (bsp_priv->internal_phy)
> + rk_gmac_internal_phy_powerup(bsp_priv);
> +
> return 0;
> }
>
> @@ -1021,6 +1099,9 @@ static void rk_gmac_powerdown(struct rk_priv_data *gmac)
> {
> struct device *dev = &gmac->pdev->dev;
>
> + if (gmac->internal_phy)
> + rk_gmac_internal_phy_powerdown(gmac);
> +
> pm_runtime_put_sync(dev);
> pm_runtime_disable(dev);
>
>
--
Florian
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH V2] hyperv: netvsc: Neaten netvsc_send_pkt by using a temporary
From: David Miller @ 2017-08-02 17:36 UTC (permalink / raw)
To: joe; +Cc: kys, haiyangz, sthemmin, devel, netdev, linux-kernel
In-Reply-To: <280adfa19cb240fd843102215d423f9a2e724ff2.1501522035.git.joe@perches.com>
From: Joe Perches <joe@perches.com>
Date: Mon, 31 Jul 2017 10:30:54 -0700
> Repeated dereference of nvmsg.msg.v1_msg.send_rndis_pkt can be
> shortened by using a temporary. Do so.
>
> No change in object code.
>
> Miscellanea:
>
> o Use * const for rpkt and nvchan
>
> Signed-off-by: Joe Perches <joe@perches.com>
Applied to net-next.
^ permalink raw reply
* Re: [RFC PATCH v2 0/2] nb8800 suspend/resume support
From: Mason @ 2017-08-02 17:31 UTC (permalink / raw)
To: Mans Rullgard; +Cc: Florian Fainelli, David Miller, netdev, Linux ARM
In-Reply-To: <yw1xk22mgdcx.fsf@mansr.com>
On 02/08/2017 18:10, Måns Rullgård wrote:
> ping -f is limited to 100 packets per second.
> Use something like iperf in UDP mode instead.
CLIENT: DESKTOP
# iperf3 -c 172.27.64.45 -u -b 950M
Connecting to host 172.27.64.45, port 5201
[ 4] local 172.27.64.1 port 55533 connected to 172.27.64.45 port 5201
[ ID] Interval Transfer Bandwidth Total Datagrams
[ 4] 0.00-1.00 sec 102 MBytes 858 Mbits/sec 13091
[ 4] 1.00-2.00 sec 114 MBytes 953 Mbits/sec 14541
[ 4] 2.00-3.00 sec 114 MBytes 953 Mbits/sec 14542
[ 4] 3.00-4.00 sec 114 MBytes 953 Mbits/sec 14541
[ 4] 4.00-5.00 sec 114 MBytes 953 Mbits/sec 14542
[ 4] 5.00-6.00 sec 114 MBytes 953 Mbits/sec 14541
[ 4] 6.00-7.00 sec 114 MBytes 953 Mbits/sec 14535
[ 4] 7.00-8.00 sec 114 MBytes 953 Mbits/sec 14536
[ 4] 8.00-9.00 sec 114 MBytes 953 Mbits/sec 14543
[ 4] 9.00-10.00 sec 114 MBytes 953 Mbits/sec 14541
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval Transfer Bandwidth Jitter Lost/Total Datagrams
[ 4] 0.00-10.00 sec 1.10 GBytes 943 Mbits/sec 0.247 ms 132176/143788 (92%)
[ 4] Sent 143788 datagrams
iperf Done.
SERVER: TANGO BOARD
# iperf3 -s
Accepted connection from 172.27.64.1, port 44995
[ 5] local 172.27.64.45 port 5201 connected to 172.27.64.1 port 55533
[ ID] Interval Transfer Bandwidth Jitter Lost/Total Datagrams
[ 5] 0.00-1.00 sec 7.90 MBytes 66.2 Mbits/sec 0.218 ms 11365/12376 (92%)
[ 5] 1.00-2.00 sec 9.13 MBytes 76.6 Mbits/sec 0.230 ms 13381/14550 (92%)
[ 5] 2.00-3.00 sec 9.12 MBytes 76.5 Mbits/sec 0.290 ms 13372/14540 (92%)
[ 5] 3.00-4.00 sec 9.11 MBytes 76.4 Mbits/sec 0.292 ms 13369/14535 (92%)
[ 5] 4.00-5.00 sec 9.18 MBytes 77.0 Mbits/sec 0.178 ms 13374/14549 (92%)
[ 5] 5.00-6.00 sec 9.10 MBytes 76.3 Mbits/sec 0.228 ms 13367/14532 (92%)
[ 5] 6.00-7.00 sec 9.26 MBytes 77.7 Mbits/sec 0.607 ms 13356/14541 (92%)
[ 5] 7.00-8.00 sec 9.23 MBytes 77.4 Mbits/sec 0.507 ms 13364/14545 (92%)
[ 5] 8.00-9.00 sec 9.20 MBytes 77.1 Mbits/sec 0.215 ms 13351/14528 (92%)
[ 5] 9.00-10.00 sec 9.16 MBytes 76.9 Mbits/sec 0.188 ms 13356/14529 (92%)
[ 5] 10.00-10.04 sec 336 KBytes 72.2 Mbits/sec 0.247 ms 521/563 (93%)
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval Transfer Bandwidth Jitter Lost/Total Datagrams
[ 5] 0.00-10.04 sec 0.00 Bytes 0.00 bits/sec 0.247 ms 132176/143788 (92%)
There is some packet loss, but the board doesn't lose connectivity.
With smaller packets...
# iperf3 -c 172.27.64.45 -u -b 950M -l 800
Connecting to host 172.27.64.45, port 5201
[ 4] local 172.27.64.1 port 35197 connected to 172.27.64.45 port 5201
[ ID] Interval Transfer Bandwidth Total Datagrams
[ 4] 0.00-1.00 sec 90.6 MBytes 760 Mbits/sec 118724
[ 4] 1.00-2.00 sec 107 MBytes 894 Mbits/sec 139718
[ 4] 2.00-3.00 sec 106 MBytes 889 Mbits/sec 138918
[ 4] 3.00-4.00 sec 107 MBytes 895 Mbits/sec 139768
[ 4] 4.00-5.00 sec 106 MBytes 891 Mbits/sec 139275
[ 4] 5.00-6.00 sec 107 MBytes 895 Mbits/sec 139862
[ 4] 6.00-7.00 sec 107 MBytes 895 Mbits/sec 139825
[ 4] 7.00-8.00 sec 107 MBytes 895 Mbits/sec 139775
[ 4] 8.00-9.00 sec 107 MBytes 895 Mbits/sec 139849
[ 4] 9.00-10.00 sec 107 MBytes 895 Mbits/sec 139835
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval Transfer Bandwidth Jitter Lost/Total Datagrams
[ 4] 0.00-10.00 sec 1.02 GBytes 880 Mbits/sec 0.009 ms 564117/1375520 (41%)
[ 4] Sent 1375520 datagrams
iperf Done.
Accepted connection from 172.27.64.1, port 46151
[ 5] local 172.27.64.45 port 5201 connected to 172.27.64.1 port 35197
[ ID] Interval Transfer Bandwidth Jitter Lost/Total Datagrams
[ 5] 0.00-1.00 sec 60.8 MBytes 510 Mbits/sec 0.004 ms 33508/113252 (30%)
iperf3: OUT OF ORDER - incoming packet = 147146 and received packet = 0 AND SP = 147497
iperf3: OUT OF ORDER - incoming packet = 146128 and received packet = 0 AND SP = 147690
iperf3: OUT OF ORDER - incoming packet = 146067 and received packet = 0 AND SP = 147863
iperf3: OUT OF ORDER - incoming packet = 147242 and received packet = 0 AND SP = 148039
iperf3: OUT OF ORDER - incoming packet = 163837 and received packet = 0 AND SP = 164363
[ 5] 1.00-2.00 sec 61.0 MBytes 511 Mbits/sec 0.198 ms 59635/139649 (43%)
iperf3: OUT OF ORDER - incoming packet = 286437 and received packet = 0 AND SP = 287226
iperf3: OUT OF ORDER - incoming packet = 302990 and received packet = 0 AND SP = 305710
[ 5] 2.00-3.00 sec 61.5 MBytes 517 Mbits/sec 0.005 ms 58369/138944 (42%)
iperf3: OUT OF ORDER - incoming packet = 427697 and received packet = 0 AND SP = 428089
iperf3: OUT OF ORDER - incoming packet = 441087 and received packet = 0 AND SP = 442963
iperf3: OUT OF ORDER - incoming packet = 453844 and received packet = 0 AND SP = 454238
[ 5] 3.00-4.00 sec 61.7 MBytes 517 Mbits/sec 0.008 ms 58975/139795 (42%)
[ 5] 4.00-5.00 sec 61.3 MBytes 514 Mbits/sec 0.010 ms 58453/138795 (42%)
[ 5] 5.00-6.00 sec 61.2 MBytes 513 Mbits/sec 0.014 ms 60141/140338 (43%)
[ 5] 6.00-7.00 sec 61.3 MBytes 514 Mbits/sec 0.009 ms 59055/139384 (42%)
iperf3: OUT OF ORDER - incoming packet = 993646 and received packet = 0 AND SP = 994370
[ 5] 7.00-8.00 sec 61.0 MBytes 512 Mbits/sec 0.007 ms 60265/140210 (43%)
iperf3: OUT OF ORDER - incoming packet = 1134516 and received packet = 0 AND SP = 1135942
[ 5] 8.00-9.00 sec 62.6 MBytes 523 Mbits/sec 0.198 ms 57805/139795 (41%)
iperf3: OUT OF ORDER - incoming packet = 1275612 and received packet = 0 AND SP = 1277716
[ 5] 9.00-10.00 sec 64.0 MBytes 538 Mbits/sec 0.007 ms 56029/139888 (40%)
[ 5] 10.00-10.04 sec 2.74 MBytes 589 Mbits/sec 0.009 ms 1882/5470 (34%)
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval Transfer Bandwidth Jitter Lost/Total Datagrams
[ 5] 0.00-10.04 sec 0.00 Bytes 0.00 bits/sec 0.009 ms 564117/1375520 (41%)
[SUM] 0.0-10.0 sec 13 datagrams received out-of-order
A lot more packet loss, but RX holds on.
Regards.
^ permalink raw reply
* Re: [PATCH net] ppp: Fix a scheduling-while-atomic bug in del_chan
From: Cong Wang @ 2017-08-02 17:13 UTC (permalink / raw)
To: Gao Feng; +Cc: xeb, David Miller, Linux Kernel Network Developers
In-Reply-To: <CAM_iQpVEsTpg17RZ1Y1jN2e0wb_X6gtxx05rmUSGa=A=XSj=Eg@mail.gmail.com>
Hi, Gao
On Tue, Aug 1, 2017 at 1:39 PM, Cong Wang <xiyou.wangcong@gmail.com> wrote:
> From my understanding, this RCU is supposed to protect the pppox_sock
> pointers in 'callid_sock' which could be NULL'ed in del_chan(). And the
> pppox_sock is freed when the last refcnt is gone, that is, when sock
> dctor is called. pptp_release() is ONLY called when the fd in user-space
> is gone, not necessarily the last refcnt.
Your commit is probably not the right fix. Can you try the following fix?
diff --git a/drivers/net/ppp/pptp.c b/drivers/net/ppp/pptp.c
index 6dde9a0cfe76..e75bb95c107f 100644
--- a/drivers/net/ppp/pptp.c
+++ b/drivers/net/ppp/pptp.c
@@ -519,7 +519,6 @@ static int pptp_release(struct socket *sock)
po = pppox_sk(sk);
del_chan(po);
- synchronize_rcu();
pppox_unbind_sock(sk);
sk->sk_state = PPPOX_DEAD;
@@ -564,6 +563,7 @@ static int pptp_create(struct net *net, struct
socket *sock, int kern)
sk->sk_family = PF_PPPOX;
sk->sk_protocol = PX_PROTO_PPTP;
sk->sk_destruct = pptp_sock_destruct;
+ sock_set_flag(sk, SOCK_RCU_FREE);
po = pppox_sk(sk);
opt = &po->proto.pptp;
^ permalink raw reply related
* NetDev 2.2 Call for Papers Announced!
From: David Miller @ 2017-08-02 17:11 UTC (permalink / raw)
To: netdev; +Cc: lwn, sypeattle
Talk submissions are now open for netdev-2.2 in Seoul Korea.
http://www.netdevconf.org/2.2/submit-proposal.html
The dealine for submissions is September 20th, so please do not delay
so that we can put the schedule together in a timely fashion.
We are all looking forward to seeing everyone in Seoul in November!
^ permalink raw reply
* net: thunderx: Buffer overwrite on bgx_probe
From: Anton Vasilyev @ 2017-08-02 16:59 UTC (permalink / raw)
To: Sunil Goutham
Cc: Robert Richter, linux-arm-kernel, netdev, linux-kernel,
ldv-project
Hello.
While searching for memory errors in Linux kernel I've come across
drivers/net/ethernet/cavium/thunder/thunder_bgx.ko module.
I've found buffer overwrite at bgx_probe():
Consider device PCI_SUBSYS_DEVID_83XX_BGX.
max_bgx_per_node is set to 4 by set_max_bgx_per_node().
Then on branch:
pci_read_config_word(pdev, PCI_DEVICE_ID, &sdevid);
if (sdevid != PCI_DEVICE_ID_THUNDER_RGX) {
bgx->bgx_id = (pci_resource_start(pdev,
PCI_CFG_REG_BAR_NUM) >> 24) & BGX_ID_MASK;
bgx->bgx_id += nic_get_node_id(pdev) * max_bgx_per_node;
bgx->bgx_id could achieve value 3 + 3 * 4 = 15,
which lead to buffer overwrite on
bgx_vnic[bgx->bgx_id] = bgx;
Question: is it enough for fix to change bgx_vnic's size?
Found by Linux Driver Verification project (linuxtesting.org).
--
Anton Vasilyev
Linux Verification Center, ISPRAS
web: http://linuxtesting.org
e-mail: vasilyev@ispras.ru
^ permalink raw reply
* Re: [RFC PATCH v2 0/2] nb8800 suspend/resume support
From: Måns Rullgård @ 2017-08-02 16:43 UTC (permalink / raw)
To: Mason; +Cc: Florian Fainelli, David Miller, netdev, Linux ARM
In-Reply-To: <a7b76388-7a7c-01e0-3966-ff7ebb4df799@free.fr>
Mason <slash.tmp@free.fr> writes:
> On 02/08/2017 18:10, Måns Rullgård wrote:
>
>> Mason writes:
>>
>>> On 02/08/2017 17:56, Måns Rullgård wrote:
>>>
>>>> What does the tango5 do if you flood it with packets faster than the
>>>> kernel can keep up with? That would make it hit the end of the rx
>>>> chain, which is apparently what makes it miserable with the current dma
>>>> stop code.
>>>
>>> The simplest way to test this would be sending tiny packets
>>> as fast as possible, right? So ping -f on a GigE link should
>>> fit the bill?
>>
>> ping -f is limited to 100 packets per second. Use something like iperf
>> in UDP mode instead.
>
> ping -f can go 100 times faster than 100 pps:
>
> # ping -f -q -c 150000 -s 300 172.27.64.45
> PING 172.27.64.45 (172.27.64.45) 300(328) bytes of data.
>
> --- 172.27.64.45 ping statistics ---
> 150000 packets transmitted, 150000 received, 0% packet loss, time 15035ms
> rtt min/avg/max/mdev = 0.065/0.084/0.537/0.014 ms, ipg/ewma 0.100/0.087 ms
>
> 150,000 packets in 15 seconds = 10,000 pps
>
> (172.27.64.45 is the tango5 board)
>
> Ergo, dealing with 10,000 packets per second does not hose RX.
ping -f goes as fast as the other end replies or 100 per second,
whichever is higher, so says the man page.
--
Måns Rullgård
^ permalink raw reply
* Re: [RFC PATCH v2 0/2] nb8800 suspend/resume support
From: Mason @ 2017-08-02 16:39 UTC (permalink / raw)
To: Mans Rullgard; +Cc: Florian Fainelli, David Miller, netdev, Linux ARM
In-Reply-To: <yw1xk22mgdcx.fsf@mansr.com>
On 02/08/2017 18:10, Måns Rullgård wrote:
> Mason writes:
>
>> On 02/08/2017 17:56, Måns Rullgård wrote:
>>
>>> What does the tango5 do if you flood it with packets faster than the
>>> kernel can keep up with? That would make it hit the end of the rx
>>> chain, which is apparently what makes it miserable with the current dma
>>> stop code.
>>
>> The simplest way to test this would be sending tiny packets
>> as fast as possible, right? So ping -f on a GigE link should
>> fit the bill?
>
> ping -f is limited to 100 packets per second. Use something like iperf
> in UDP mode instead.
ping -f can go 100 times faster than 100 pps:
# ping -f -q -c 150000 -s 300 172.27.64.45
PING 172.27.64.45 (172.27.64.45) 300(328) bytes of data.
--- 172.27.64.45 ping statistics ---
150000 packets transmitted, 150000 received, 0% packet loss, time 15035ms
rtt min/avg/max/mdev = 0.065/0.084/0.537/0.014 ms, ipg/ewma 0.100/0.087 ms
150,000 packets in 15 seconds = 10,000 pps
(172.27.64.45 is the tango5 board)
Ergo, dealing with 10,000 packets per second does not hose RX.
Regards.
^ permalink raw reply
* RE: [PATCH V4 net-next 1/8] net: hns3: Add support of HNS3 Ethernet Driver for hip08 SoC
From: Salil Mehta @ 2017-08-02 16:38 UTC (permalink / raw)
To: Florian Fainelli, davem@davemloft.net
Cc: Zhuangyuzeng (Yisen), huangdaode, lipeng (Y),
mehta.salil.lnk@gmail.com, netdev@vger.kernel.org,
linux-kernel@vger.kernel.org, linux-rdma@vger.kernel.org,
Linuxarm
In-Reply-To: <79a3a952-acae-2a51-0d49-46acaf92cf3b@gmail.com>
Hi Florian,
> -----Original Message-----
> From: Salil Mehta
> Sent: Thursday, July 27, 2017 9:45 PM
> To: 'Florian Fainelli'; davem@davemloft.net
> Cc: Zhuangyuzeng (Yisen); huangdaode; lipeng (Y);
> mehta.salil.lnk@gmail.com; netdev@vger.kernel.org; linux-
> kernel@vger.kernel.org; linux-rdma@vger.kernel.org; Linuxarm
> Subject: RE: [PATCH V4 net-next 1/8] net: hns3: Add support of HNS3
> Ethernet Driver for hip08 SoC
>
> Hi Florian,
>
> > -----Original Message-----
> > From: Florian Fainelli [mailto:f.fainelli@gmail.com]
> > Sent: Sunday, July 23, 2017 6:24 PM
> > To: Salil Mehta; davem@davemloft.net
> > Cc: Zhuangyuzeng (Yisen); huangdaode; lipeng (Y);
> > mehta.salil.lnk@gmail.com; netdev@vger.kernel.org; linux-
> > kernel@vger.kernel.org; linux-rdma@vger.kernel.org; Linuxarm
> > Subject: Re: [PATCH V4 net-next 1/8] net: hns3: Add support of HNS3
> > Ethernet Driver for hip08 SoC
> >
> >
> >
> > On 07/22/2017 03:09 PM, Salil Mehta wrote:
> > > This patch adds the support of Hisilicon Network Subsystem 3
> > > Ethernet driver to hip08 family of SoCs.
> > >
> > > This driver includes basic Rx/Tx functionality. It also includes
> > > the client registration code with the HNAE3(Hisilicon Network
> > > Acceleration Engine 3) framework.
> > >
> > > This work provides the initial support to the hip08 SoC and
> > > would incrementally add features or enhancements.
> > >
> > > Signed-off-by: Daode Huang <huangdaode@hisilicon.com>
> > > Signed-off-by: lipeng <lipeng321@huawei.com>
> > > Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
> > > Signed-off-by: Yisen Zhuang <yisen.zhuang@huawei.com>
[...]
>
> >
> > > + hns3_nic_reclaim_one_desc(ring, &bytes, &pkts);
> > > + /* Issue prefetch for next Tx descriptor */
> > > + prefetch(&ring->desc_cb[ring->next_to_clean]);
> > > + budget--;
> > > + }
> > > +
> > > + ring->tqp_vector->tx_group.total_bytes += bytes;
> > > + ring->tqp_vector->tx_group.total_packets += pkts;
> > > +
> > > + dev_queue = netdev_get_tx_queue(netdev, ring->tqp->tqp_index);
> > > + netdev_tx_completed_queue(dev_queue, pkts, bytes);
> >
> > Where is flow control happening? Should not you wake the transmit
> queue
> > if you had to stop it somehow?
> Forgive me, I could not get this part. Flow control of what?
As discussed with you earlier, I have fixed the queue wakeup part
in Patch V6. Please have a look at it. Thanks!
Best regards
Salil
>
>
> >
> > I kind of stopped reviewing here.
> > --
> > Florian
^ permalink raw reply
* [PATCH] ipv4: Introduce ipip_offload_init helper function.
From: Tonghao Zhang @ 2017-08-02 16:34 UTC (permalink / raw)
To: netdev; +Cc: Tonghao Zhang
It's convenient to init ipip offload. We will check
the return value, and print KERN_CRIT info on failure.
Signed-off-by: Tonghao Zhang <xiangxia.m.yue@gmail.com>
---
net/ipv4/af_inet.c | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
index 5ce44fb..c888120 100644
--- a/net/ipv4/af_inet.c
+++ b/net/ipv4/af_inet.c
@@ -1763,6 +1763,11 @@ static int __init init_inet_pernet_ops(void)
},
};
+static int __init ipip_offload_init(void)
+{
+ return inet_add_offload(&ipip_offload, IPPROTO_IPIP);
+}
+
static int __init ipv4_offload_init(void)
{
/*
@@ -1772,9 +1777,10 @@ static int __init ipv4_offload_init(void)
pr_crit("%s: Cannot add UDP protocol offload\n", __func__);
if (tcpv4_offload_init() < 0)
pr_crit("%s: Cannot add TCP protocol offload\n", __func__);
+ if (ipip_offload_init() < 0)
+ pr_crit("%s: Cannot add IPIP protocol offload\n", __func__);
dev_add_offload(&ip_packet_offload);
- inet_add_offload(&ipip_offload, IPPROTO_IPIP);
return 0;
}
--
1.8.3.1
^ permalink raw reply related
* RE: [RFC PATCH v2 0/2] nb8800 suspend/resume support
From: David Laight @ 2017-08-02 16:19 UTC (permalink / raw)
To: 'Måns Rullgård', Mason
Cc: Florian Fainelli, David Miller, netdev, Linux ARM
In-Reply-To: <yw1xk22mgdcx.fsf@mansr.com>
From: Måns Rullgård
> Sent: 02 August 2017 17:10
...
> ping -f is limited to 100 packets per second. Use something like iperf
> in UDP mode instead.
Or break a MAC driver so it just saturates the network.
You might actually need bursts of traffic - otherwise the receiver
will be continuously out of rx buffers and no dma will be active.
David
^ permalink raw reply
* Re: [RFC PATCH v2 0/2] nb8800 suspend/resume support
From: Måns Rullgård @ 2017-08-02 16:10 UTC (permalink / raw)
To: Mason; +Cc: netdev, Florian Fainelli, David Miller, Linux ARM
In-Reply-To: <6906dccf-bec9-0fc8-a34a-c39c05ada917@free.fr>
Mason <slash.tmp@free.fr> writes:
> On 02/08/2017 17:56, Måns Rullgård wrote:
>
>> Mason writes:
>>
>>> From my perspective, the older method does not work on newer chips :-)
>>
>> It does work on tango4.
>
> Agreed.
>
>> What does the tango5 do if you flood it with packets faster than the
>> kernel can keep up with? That would make it hit the end of the rx
>> chain, which is apparently what makes it miserable with the current dma
>> stop code.
>
> The simplest way to test this would be sending tiny packets
> as fast as possible, right? So ping -f on a GigE link should
> fit the bill?
ping -f is limited to 100 packets per second. Use something like iperf
in UDP mode instead.
--
Måns Rullgård
^ permalink raw reply
* Re: [RFC PATCH v2 0/2] nb8800 suspend/resume support
From: Mason @ 2017-08-02 16:07 UTC (permalink / raw)
To: Mans Rullgard; +Cc: Florian Fainelli, David Miller, netdev, Linux ARM
In-Reply-To: <yw1xo9rygdyu.fsf@mansr.com>
On 02/08/2017 17:56, Måns Rullgård wrote:
> Mason writes:
>
>> From my perspective, the older method does not work on newer chips :-)
>
> It does work on tango4.
Agreed.
> What does the tango5 do if you flood it with packets faster than the
> kernel can keep up with? That would make it hit the end of the rx
> chain, which is apparently what makes it miserable with the current dma
> stop code.
The simplest way to test this would be sending tiny packets
as fast as possible, right? So ping -f on a GigE link should
fit the bill?
Regards.
^ permalink raw reply
* Re: [PATCH net-next] bpf: fix the printing of ifindex
From: John Fastabend @ 2017-08-02 16:06 UTC (permalink / raw)
To: William Tu, netdev
In-Reply-To: <1501688632-2709-1-git-send-email-u9012063@gmail.com>
On 08/02/2017 08:43 AM, William Tu wrote:
> Save the ifindex before it gets zeroed so the invalid
> ifindex can be printed out.
>
> Signed-off-by: William Tu <u9012063@gmail.com>
> ---
Thanks!
Acked-by: John Fastabend <john.fastabend@gmail.com>
^ permalink raw reply
* [PATCH V6 net-next 8/8] net: hns3: Add HNS3 driver to kernel build framework & MAINTAINERS
From: Salil Mehta @ 2017-08-02 15:59 UTC (permalink / raw)
To: davem
Cc: salil.mehta, yisen.zhuang, huangdaode, lipeng321, mehta.salil.lnk,
netdev, linux-kernel, linux-rdma, linuxarm
In-Reply-To: <20170802155952.185564-1-salil.mehta@huawei.com>
This patch updates the MAINTAINERS file with HNS3 Ethernet driver
maintainers names and other details. This also introduces the new
Makefiles required to build the HNS3 Ethernet driver and updates
the existing Kconfig file in the hisilicon folder.
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
---
MAINTAINERS | 8 +++++++
drivers/net/ethernet/hisilicon/Kconfig | 27 ++++++++++++++++++++++
drivers/net/ethernet/hisilicon/Makefile | 1 +
drivers/net/ethernet/hisilicon/hns3/Makefile | 7 ++++++
.../net/ethernet/hisilicon/hns3/hns3pf/Makefile | 11 +++++++++
5 files changed, 54 insertions(+)
create mode 100644 drivers/net/ethernet/hisilicon/hns3/Makefile
create mode 100644 drivers/net/ethernet/hisilicon/hns3/hns3pf/Makefile
diff --git a/MAINTAINERS b/MAINTAINERS
index 207e453..6b990da 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -6148,6 +6148,14 @@ S: Maintained
F: drivers/net/ethernet/hisilicon/
F: Documentation/devicetree/bindings/net/hisilicon*.txt
+HISILICON NETWORK SUBSYSTEM 3 DRIVER (HNS3)
+M: Yisen Zhuang <yisen.zhuang@huawei.com>
+M: Salil Mehta <salil.mehta@huawei.com>
+L: netdev@vger.kernel.org
+W: http://www.hisilicon.com
+S: Maintained
+F: drivers/net/ethernet/hisilicon/hns3/
+
HISILICON ROCE DRIVER
M: Lijun Ou <oulijun@huawei.com>
M: Wei Hu(Xavier) <xavier.huwei@huawei.com>
diff --git a/drivers/net/ethernet/hisilicon/Kconfig b/drivers/net/ethernet/hisilicon/Kconfig
index d11287e..91c7bdb 100644
--- a/drivers/net/ethernet/hisilicon/Kconfig
+++ b/drivers/net/ethernet/hisilicon/Kconfig
@@ -76,4 +76,31 @@ config HNS_ENET
This selects the general ethernet driver for HNS. This module make
use of any HNS AE driver, such as HNS_DSAF
+config HNS3
+ tristate "Hisilicon Network Subsystem Support HNS3 (Framework)"
+ depends on PCI
+ ---help---
+ This selects the framework support for Hisilicon Network Subsystem 3.
+ This layer facilitates clients like ENET, RoCE and user-space ethernet
+ drivers(like ODP)to register with HNAE devices and their associated
+ operations.
+
+config HNS3_HCLGE
+ tristate "Hisilicon HNS3 HCLGE Acceleration Engine & Compatibility Layer Support"
+ depends on PCI_MSI
+ depends on HNS3
+ ---help---
+ This selects the HNS3_HCLGE network acceleration engine & its hardware
+ compatibility layer. The engine would be used in Hisilicon hip08 family of
+ SoCs and further upcoming SoCs.
+
+config HNS3_ENET
+ tristate "Hisilicon HNS3 Ethernet Device Support"
+ depends on 64BIT && PCI
+ depends on HNS3 && HNS3_HCLGE
+ ---help---
+ This selects the Ethernet Driver for Hisilicon Network Subsystem 3 for hip08
+ family of SoCs. This module depends upon HNAE3 driver to access the HNAE3
+ devices and their associated operations.
+
endif # NET_VENDOR_HISILICON
diff --git a/drivers/net/ethernet/hisilicon/Makefile b/drivers/net/ethernet/hisilicon/Makefile
index 8661695..3828c43 100644
--- a/drivers/net/ethernet/hisilicon/Makefile
+++ b/drivers/net/ethernet/hisilicon/Makefile
@@ -6,4 +6,5 @@ obj-$(CONFIG_HIX5HD2_GMAC) += hix5hd2_gmac.o
obj-$(CONFIG_HIP04_ETH) += hip04_eth.o
obj-$(CONFIG_HNS_MDIO) += hns_mdio.o
obj-$(CONFIG_HNS) += hns/
+obj-$(CONFIG_HNS3) += hns3/
obj-$(CONFIG_HISI_FEMAC) += hisi_femac.o
diff --git a/drivers/net/ethernet/hisilicon/hns3/Makefile b/drivers/net/ethernet/hisilicon/hns3/Makefile
new file mode 100644
index 0000000..a9349e1
--- /dev/null
+++ b/drivers/net/ethernet/hisilicon/hns3/Makefile
@@ -0,0 +1,7 @@
+#
+# Makefile for the HISILICON network device drivers.
+#
+
+obj-$(CONFIG_HNS3) += hns3pf/
+
+obj-$(CONFIG_HNS3) += hnae3.o
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/Makefile b/drivers/net/ethernet/hisilicon/hns3/hns3pf/Makefile
new file mode 100644
index 0000000..162e8a42
--- /dev/null
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/Makefile
@@ -0,0 +1,11 @@
+#
+# Makefile for the HISILICON network device drivers.
+#
+
+ccflags-y := -Idrivers/net/ethernet/hisilicon/hns3
+
+obj-$(CONFIG_HNS3_HCLGE) += hclge.o
+hclge-objs = hclge_main.o hclge_cmd.o hclge_mdio.o hclge_tm.o
+
+obj-$(CONFIG_HNS3_ENET) += hns3.o
+hns3-objs = hns3_enet.o hns3_ethtool.o
--
2.7.4
^ permalink raw reply related
* [PATCH V6 net-next 7/8] net: hns3: Add Ethtool support to HNS3 driver
From: Salil Mehta @ 2017-08-02 15:59 UTC (permalink / raw)
To: davem
Cc: salil.mehta, yisen.zhuang, huangdaode, lipeng321, mehta.salil.lnk,
netdev, linux-kernel, linux-rdma, linuxarm
In-Reply-To: <20170802155952.185564-1-salil.mehta@huawei.com>
This patch adds the support of the Ethtool interface to
the HNS3 Ethernet driver. Various commands to read the
statistics, configure the offloading, loopback selftest etc.
are supported.
Signed-off-by: Daode Huang <huangdaode@hisilicon.com>
Signed-off-by: lipeng <lipeng321@huawei.com>
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
Signed-off-by: Yisen Zhuang <yisen.zhuang@huawei.com>
---
Patch V6: addressed below comments
1. Andrew Lunn
https://lkml.org/lkml/2017/7/28/745
Patch V5: addressed below comments
1. Florian Fainelli
https://lkml.org/lkml/2017/7/23/94
2. Stephen Hemminger
https://lkml.org/lkml/2017/7/23/101
Patch V4: addressed below comments
1. Andrew Lunn
Removed the support of loop PHY back for now
Patch V3: Address below comments
1. Stephen Hemminger
https://lkml.org/lkml/2017/6/13/974
2. Andrew Lunn
https://lkml.org/lkml/2017/6/13/1037
Patch V2: No change
Patch V1: Initial Submit
---
.../ethernet/hisilicon/hns3/hns3pf/hns3_ethtool.c | 482 +++++++++++++++++++++
1 file changed, 482 insertions(+)
create mode 100644 drivers/net/ethernet/hisilicon/hns3/hns3pf/hns3_ethtool.c
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hns3_ethtool.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hns3_ethtool.c
new file mode 100644
index 0000000..0ad65e4
--- /dev/null
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hns3_ethtool.c
@@ -0,0 +1,482 @@
+/*
+ * Copyright (c) 2016~2017 Hisilicon Limited.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/etherdevice.h>
+#include <linux/string.h>
+
+#include "hns3_enet.h"
+
+struct hns3_stats {
+ char stats_string[ETH_GSTRING_LEN];
+ int stats_size;
+ int stats_offset;
+};
+
+/* tqp related stats */
+#define HNS3_TQP_STAT(_string, _member) { \
+ .stats_string = _string, \
+ .stats_size = FIELD_SIZEOF(struct ring_stats, _member), \
+ .stats_offset = offsetof(struct hns3_enet_ring, stats), \
+} \
+
+static const struct hns3_stats hns3_txq_stats[] = {
+ /* Tx per-queue statistics */
+ HNS3_TQP_STAT("tx_io_err_cnt", io_err_cnt),
+ HNS3_TQP_STAT("tx_sw_err_cnt", sw_err_cnt),
+ HNS3_TQP_STAT("tx_seg_pkt_cnt", seg_pkt_cnt),
+ HNS3_TQP_STAT("tx_pkts", tx_pkts),
+ HNS3_TQP_STAT("tx_bytes", tx_bytes),
+ HNS3_TQP_STAT("tx_err_cnt", tx_err_cnt),
+ HNS3_TQP_STAT("tx_restart_queue", restart_queue),
+ HNS3_TQP_STAT("tx_busy", tx_busy),
+};
+
+#define HNS3_TXQ_STATS_COUNT ARRAY_SIZE(hns3_txq_stats)
+
+static const struct hns3_stats hns3_rxq_stats[] = {
+ /* Rx per-queue statistics */
+ HNS3_TQP_STAT("rx_io_err_cnt", io_err_cnt),
+ HNS3_TQP_STAT("rx_sw_err_cnt", sw_err_cnt),
+ HNS3_TQP_STAT("rx_seg_pkt_cnt", seg_pkt_cnt),
+ HNS3_TQP_STAT("rx_pkts", rx_pkts),
+ HNS3_TQP_STAT("rx_bytes", rx_bytes),
+ HNS3_TQP_STAT("rx_err_cnt", rx_err_cnt),
+ HNS3_TQP_STAT("rx_reuse_pg_cnt", reuse_pg_cnt),
+ HNS3_TQP_STAT("rx_err_pkt_len", err_pkt_len),
+ HNS3_TQP_STAT("rx_non_vld_descs", non_vld_descs),
+ HNS3_TQP_STAT("rx_err_bd_num", err_bd_num),
+ HNS3_TQP_STAT("rx_l2_err", l2_err),
+ HNS3_TQP_STAT("rx_l3l4_csum_err", l3l4_csum_err),
+};
+
+#define HNS3_RXQ_STATS_COUNT ARRAY_SIZE(hns3_rxq_stats)
+
+#define HNS3_TQP_STATS_COUNT (HNS3_TXQ_STATS_COUNT + HNS3_RXQ_STATS_COUNT)
+
+struct hns3_link_mode_mapping {
+ u32 hns3_link_mode;
+ u32 ethtool_link_mode;
+};
+
+static const struct hns3_link_mode_mapping hns3_lm_map[] = {
+ {HNS3_LM_FIBRE_BIT, ETHTOOL_LINK_MODE_FIBRE_BIT},
+ {HNS3_LM_AUTONEG_BIT, ETHTOOL_LINK_MODE_Autoneg_BIT},
+ {HNS3_LM_TP_BIT, ETHTOOL_LINK_MODE_TP_BIT},
+ {HNS3_LM_PAUSE_BIT, ETHTOOL_LINK_MODE_Pause_BIT},
+ {HNS3_LM_BACKPLANE_BIT, ETHTOOL_LINK_MODE_Backplane_BIT},
+ {HNS3_LM_10BASET_HALF_BIT, ETHTOOL_LINK_MODE_10baseT_Half_BIT},
+ {HNS3_LM_10BASET_FULL_BIT, ETHTOOL_LINK_MODE_10baseT_Full_BIT},
+ {HNS3_LM_100BASET_HALF_BIT, ETHTOOL_LINK_MODE_100baseT_Half_BIT},
+ {HNS3_LM_100BASET_FULL_BIT, ETHTOOL_LINK_MODE_100baseT_Full_BIT},
+ {HNS3_LM_1000BASET_FULL_BIT, ETHTOOL_LINK_MODE_1000baseT_Full_BIT},
+};
+
+static void hns3_driv_to_eth_caps(u32 caps, struct ethtool_link_ksettings *cmd,
+ bool is_advertised)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(hns3_lm_map); i++) {
+ if (!(caps & hns3_lm_map[i].hns3_link_mode))
+ continue;
+
+ if (is_advertised) {
+ ethtool_link_ksettings_zero_link_mode(cmd,
+ advertising);
+ __set_bit(hns3_lm_map[i].ethtool_link_mode,
+ cmd->link_modes.advertising);
+ } else {
+ ethtool_link_ksettings_zero_link_mode(cmd,
+ supported);
+ __set_bit(hns3_lm_map[i].ethtool_link_mode,
+ cmd->link_modes.supported);
+ }
+ }
+}
+
+static int hns3_get_sset_count(struct net_device *netdev, int stringset)
+{
+ struct hns3_nic_priv *priv = netdev_priv(netdev);
+ struct hnae3_handle *h = priv->ae_handle;
+ const struct hnae3_ae_ops *ops = h->ae_algo->ops;
+
+ if (!ops->get_sset_count)
+ return -EOPNOTSUPP;
+
+ switch (stringset) {
+ case ETH_SS_STATS:
+ return ((HNS3_TQP_STATS_COUNT * h->kinfo.num_tqps) +
+ ops->get_sset_count(h, stringset));
+
+ case ETH_SS_TEST:
+ return ops->get_sset_count(h, stringset);
+ }
+
+ return 0;
+}
+
+static void *hns3_update_strings(u8 *data, const struct hns3_stats *stats,
+ u32 stat_count, u32 num_tqps)
+{
+#define MAX_PREFIX_SIZE (8 + 4)
+ u32 size_left;
+ u32 i, j;
+ u32 n1;
+
+ for (i = 0; i < num_tqps; i++) {
+ for (j = 0; j < stat_count; j++) {
+ data[ETH_GSTRING_LEN - 1] = '\0';
+
+ /* first, prepend the prefix string */
+ n1 = snprintf(data, MAX_PREFIX_SIZE, "rcb_q%d_", i);
+ n1 = min_t(uint, n1, MAX_PREFIX_SIZE - 1);
+ size_left = (ETH_GSTRING_LEN - 1) - n1;
+
+ /* now, concatenate the stats string to it */
+ strncat(data, stats[j].stats_string, size_left);
+ data += ETH_GSTRING_LEN;
+ }
+ }
+
+ return data;
+}
+
+static u8 *hns3_get_strings_tqps(struct hnae3_handle *handle, u8 *data)
+{
+ struct hnae3_knic_private_info *kinfo = &handle->kinfo;
+
+ /* get strings for Tx */
+ data = hns3_update_strings(data, hns3_txq_stats, HNS3_TXQ_STATS_COUNT,
+ kinfo->num_tqps);
+
+ /* get strings for Rx */
+ data = hns3_update_strings(data, hns3_rxq_stats, HNS3_RXQ_STATS_COUNT,
+ kinfo->num_tqps);
+
+ return data;
+}
+
+static void hns3_get_strings(struct net_device *netdev, u32 stringset, u8 *data)
+{
+ struct hns3_nic_priv *priv = netdev_priv(netdev);
+ struct hnae3_handle *h = priv->ae_handle;
+ const struct hnae3_ae_ops *ops = h->ae_algo->ops;
+ char *buff = (char *)data;
+
+ if (!ops->get_strings)
+ return;
+
+ switch (stringset) {
+ case ETH_SS_STATS:
+ buff = hns3_get_strings_tqps(h, buff);
+ h->ae_algo->ops->get_strings(h, stringset, (u8 *)buff);
+ break;
+ case ETH_SS_TEST:
+ ops->get_strings(h, stringset, data);
+ break;
+ }
+}
+
+static u64 *hns3_get_stats_tqps(struct hnae3_handle *handle, u64 *data)
+{
+ struct hns3_nic_priv *nic_priv = (struct hns3_nic_priv *)handle->priv;
+ struct hnae3_knic_private_info *kinfo = &handle->kinfo;
+ struct hns3_enet_ring *ring;
+ u8 *stat;
+ u32 i;
+
+ /* get stats for Tx */
+ for (i = 0; i < kinfo->num_tqps; i++) {
+ ring = nic_priv->ring_data[i].ring;
+ for (i = 0; i < HNS3_TXQ_STATS_COUNT; i++) {
+ stat = (u8 *)ring + hns3_txq_stats[i].stats_offset;
+ *data++ = *(u64 *)stat;
+ }
+ }
+
+ /* get stats for Rx */
+ for (i = 0; i < kinfo->num_tqps; i++) {
+ ring = nic_priv->ring_data[i + kinfo->num_tqps].ring;
+ for (i = 0; i < HNS3_RXQ_STATS_COUNT; i++) {
+ stat = (u8 *)ring + hns3_rxq_stats[i].stats_offset;
+ *data++ = *(u64 *)stat;
+ }
+ }
+
+ return data;
+}
+
+/* hns3_get_stats - get detail statistics.
+ * @netdev: net device
+ * @stats: statistics info.
+ * @data: statistics data.
+ */
+void hns3_get_stats(struct net_device *netdev, struct ethtool_stats *stats,
+ u64 *data)
+{
+ struct hns3_nic_priv *priv = netdev_priv(netdev);
+ struct hnae3_handle *h = priv->ae_handle;
+ u64 *p = data;
+
+ if (!h->ae_algo->ops->get_stats || !h->ae_algo->ops->update_stats) {
+ netdev_err(netdev, "could not get any statistics\n");
+ return;
+ }
+
+ h->ae_algo->ops->update_stats(h, &netdev->stats);
+
+ /* get per-queue stats */
+ p = hns3_get_stats_tqps(h, p);
+
+ /* get MAC & other misc hardware stats */
+ h->ae_algo->ops->get_stats(h, p);
+}
+
+static void hns3_get_drvinfo(struct net_device *netdev,
+ struct ethtool_drvinfo *drvinfo)
+{
+ struct hns3_nic_priv *priv = netdev_priv(netdev);
+ struct hnae3_handle *h = priv->ae_handle;
+
+ strncpy(drvinfo->version, hns3_driver_version,
+ sizeof(drvinfo->version));
+ drvinfo->version[sizeof(drvinfo->version) - 1] = '\0';
+
+ strncpy(drvinfo->driver, h->pdev->driver->name,
+ sizeof(drvinfo->driver));
+ drvinfo->driver[sizeof(drvinfo->driver) - 1] = '\0';
+
+ strncpy(drvinfo->bus_info, pci_name(h->pdev),
+ sizeof(drvinfo->bus_info));
+ drvinfo->bus_info[ETHTOOL_BUSINFO_LEN - 1] = '\0';
+
+ snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version), "0x%08x",
+ priv->ae_handle->ae_algo->ops->get_fw_version(h));
+}
+
+static u32 hns3_get_link(struct net_device *netdev)
+{
+ struct hns3_nic_priv *priv = netdev_priv(netdev);
+ struct hnae3_handle *h;
+
+ h = priv->ae_handle;
+
+ if (h->ae_algo && h->ae_algo->ops && h->ae_algo->ops->get_status)
+ return h->ae_algo->ops->get_status(h);
+ else
+ return 0;
+}
+
+static void hns3_get_ringparam(struct net_device *netdev,
+ struct ethtool_ringparam *param)
+{
+ struct hns3_nic_priv *priv = netdev_priv(netdev);
+ int queue_num = priv->ae_handle->kinfo.num_tqps;
+
+ param->tx_max_pending = HNS3_RING_MAX_PENDING;
+ param->rx_max_pending = HNS3_RING_MAX_PENDING;
+
+ param->tx_pending = priv->ring_data[0].ring->desc_num;
+ param->rx_pending = priv->ring_data[queue_num].ring->desc_num;
+}
+
+static void hns3_get_pauseparam(struct net_device *netdev,
+ struct ethtool_pauseparam *param)
+{
+ struct hns3_nic_priv *priv = netdev_priv(netdev);
+ struct hnae3_handle *h = priv->ae_handle;
+
+ if (h->ae_algo && h->ae_algo->ops && h->ae_algo->ops->get_pauseparam)
+ h->ae_algo->ops->get_pauseparam(h, ¶m->autoneg,
+ ¶m->rx_pause, ¶m->tx_pause);
+}
+
+static int hns3_get_link_ksettings(struct net_device *netdev,
+ struct ethtool_link_ksettings *cmd)
+{
+ struct hns3_nic_priv *priv = netdev_priv(netdev);
+ struct hnae3_handle *h = priv->ae_handle;
+ u32 supported_caps;
+ u32 advertised_caps;
+ u8 media_type;
+ u8 link_stat;
+ u8 auto_neg;
+ u8 duplex;
+ u32 speed;
+
+ if (!h->ae_algo || !h->ae_algo->ops)
+ return -EOPNOTSUPP;
+
+ /* 1.auto_neg&speed&duplex from cmd */
+ if (h->ae_algo->ops->get_ksettings_an_result) {
+ h->ae_algo->ops->get_ksettings_an_result(h, &auto_neg,
+ &speed, &duplex);
+ cmd->base.autoneg = auto_neg;
+ cmd->base.speed = speed;
+ cmd->base.duplex = duplex;
+
+ link_stat = hns3_get_link(netdev);
+ if (!link_stat) {
+ cmd->base.speed = (u32)SPEED_UNKNOWN;
+ cmd->base.duplex = DUPLEX_UNKNOWN;
+ }
+ }
+
+ /* 2.media_type get from bios parameter block */
+ if (h->ae_algo->ops->get_media_type)
+ h->ae_algo->ops->get_media_type(h, &media_type);
+
+ switch (media_type) {
+ case HNAE3_MEDIA_TYPE_FIBER:
+ cmd->base.port = PORT_FIBRE;
+ supported_caps = HNS3_LM_FIBRE_BIT | HNS3_LM_AUTONEG_BIT |
+ HNS3_LM_PAUSE_BIT | HNS3_LM_1000BASET_FULL_BIT;
+
+ advertised_caps = supported_caps;
+ break;
+ case HNAE3_MEDIA_TYPE_COPPER:
+ cmd->base.port = PORT_TP;
+ supported_caps = HNS3_LM_TP_BIT | HNS3_LM_AUTONEG_BIT |
+ HNS3_LM_PAUSE_BIT | HNS3_LM_1000BASET_FULL_BIT |
+ HNS3_LM_100BASET_FULL_BIT | HNS3_LM_100BASET_HALF_BIT |
+ HNS3_LM_10BASET_FULL_BIT | HNS3_LM_10BASET_HALF_BIT;
+ advertised_caps = supported_caps;
+ break;
+ case HNAE3_MEDIA_TYPE_BACKPLANE:
+ cmd->base.port = PORT_NONE;
+ supported_caps = HNS3_LM_BACKPLANE_BIT | HNS3_LM_PAUSE_BIT |
+ HNS3_LM_AUTONEG_BIT | HNS3_LM_1000BASET_FULL_BIT |
+ HNS3_LM_100BASET_FULL_BIT | HNS3_LM_100BASET_HALF_BIT |
+ HNS3_LM_10BASET_FULL_BIT | HNS3_LM_10BASET_HALF_BIT;
+
+ advertised_caps = supported_caps;
+ break;
+ case HNAE3_MEDIA_TYPE_UNKNOWN:
+ default:
+ cmd->base.port = PORT_OTHER;
+ supported_caps = 0;
+ advertised_caps = 0;
+ break;
+ }
+
+ /* now, map driver link modes to ethtool link modes */
+ hns3_driv_to_eth_caps(supported_caps, cmd, false);
+ hns3_driv_to_eth_caps(advertised_caps, cmd, true);
+
+ /* 3.mdix_ctrl&mdix get from phy reg */
+ if (h->ae_algo->ops->get_mdix_mode)
+ h->ae_algo->ops->get_mdix_mode(h, &cmd->base.eth_tp_mdix_ctrl,
+ &cmd->base.eth_tp_mdix);
+ /* 4.mdio_support */
+ cmd->base.mdio_support = ETH_MDIO_SUPPORTS_C22;
+
+ return 0;
+}
+
+static u32 hns3_get_rss_key_size(struct net_device *netdev)
+{
+ struct hns3_nic_priv *priv = netdev_priv(netdev);
+ struct hnae3_handle *h = priv->ae_handle;
+
+ if (!h->ae_algo || !h->ae_algo->ops ||
+ !h->ae_algo->ops->get_rss_key_size)
+ return -EOPNOTSUPP;
+
+ return h->ae_algo->ops->get_rss_key_size(h);
+}
+
+static u32 hns3_get_rss_indir_size(struct net_device *netdev)
+{
+ struct hns3_nic_priv *priv = netdev_priv(netdev);
+ struct hnae3_handle *h = priv->ae_handle;
+
+ if (!h->ae_algo || !h->ae_algo->ops ||
+ !h->ae_algo->ops->get_rss_indir_size)
+ return -EOPNOTSUPP;
+
+ return h->ae_algo->ops->get_rss_indir_size(h);
+}
+
+static int hns3_get_rss(struct net_device *netdev, u32 *indir, u8 *key,
+ u8 *hfunc)
+{
+ struct hns3_nic_priv *priv = netdev_priv(netdev);
+ struct hnae3_handle *h = priv->ae_handle;
+
+ if (!h->ae_algo || !h->ae_algo->ops || !h->ae_algo->ops->get_rss)
+ return -EOPNOTSUPP;
+
+ return h->ae_algo->ops->get_rss(h, indir, key, hfunc);
+}
+
+static int hns3_set_rss(struct net_device *netdev, const u32 *indir,
+ const u8 *key, const u8 hfunc)
+{
+ struct hns3_nic_priv *priv = netdev_priv(netdev);
+ struct hnae3_handle *h = priv->ae_handle;
+
+ if (!h->ae_algo || !h->ae_algo->ops || !h->ae_algo->ops->set_rss)
+ return -EOPNOTSUPP;
+
+ /* currently we only support Toeplitz hash */
+ if ((hfunc != ETH_RSS_HASH_NO_CHANGE) && (hfunc != ETH_RSS_HASH_TOP)) {
+ netdev_err(netdev,
+ "hash func not supported (only Toeplitz hash)\n");
+ return -EOPNOTSUPP;
+ }
+ if (!indir) {
+ netdev_err(netdev,
+ "set rss failed for indir is empty\n");
+ return -EOPNOTSUPP;
+ }
+
+ return h->ae_algo->ops->set_rss(h, indir, key, hfunc);
+}
+
+static int hns3_get_rxnfc(struct net_device *netdev,
+ struct ethtool_rxnfc *cmd,
+ u32 *rule_locs)
+{
+ struct hns3_nic_priv *priv = netdev_priv(netdev);
+ struct hnae3_handle *h = priv->ae_handle;
+
+ if (!h->ae_algo || !h->ae_algo->ops || !h->ae_algo->ops->get_tc_size)
+ return -EOPNOTSUPP;
+
+ switch (cmd->cmd) {
+ case ETHTOOL_GRXRINGS:
+ cmd->data = h->ae_algo->ops->get_tc_size(h);
+ break;
+ default:
+ return -EOPNOTSUPP;
+ }
+
+ return 0;
+}
+
+static const struct ethtool_ops hns3_ethtool_ops = {
+ .get_drvinfo = hns3_get_drvinfo,
+ .get_link = hns3_get_link,
+ .get_ringparam = hns3_get_ringparam,
+ .get_pauseparam = hns3_get_pauseparam,
+ .get_strings = hns3_get_strings,
+ .get_ethtool_stats = hns3_get_stats,
+ .get_sset_count = hns3_get_sset_count,
+ .get_rxnfc = hns3_get_rxnfc,
+ .get_rxfh_key_size = hns3_get_rss_key_size,
+ .get_rxfh_indir_size = hns3_get_rss_indir_size,
+ .get_rxfh = hns3_get_rss,
+ .set_rxfh = hns3_set_rss,
+ .get_link_ksettings = hns3_get_link_ksettings,
+};
+
+void hns3_ethtool_set_ops(struct net_device *netdev)
+{
+ netdev->ethtool_ops = &hns3_ethtool_ops;
+}
--
2.7.4
^ permalink raw reply related
* [PATCH V6 net-next 6/8] net: hns3: Add MDIO support to HNS3 Ethernet driver for hip08 SoC
From: Salil Mehta @ 2017-08-02 15:59 UTC (permalink / raw)
To: davem-fT/PcQaiUtIeIZ0/mPfg9Q
Cc: salil.mehta-hv44wF8Li93QT0dZR+AlfA,
yisen.zhuang-hv44wF8Li93QT0dZR+AlfA,
huangdaode-C8/M+/jPZTeaMJb+Lgu22Q,
lipeng321-hv44wF8Li93QT0dZR+AlfA,
mehta.salil.lnk-Re5JQEeQqe8AvxtiuMwx3w,
netdev-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
linux-rdma-u79uwXL29TY76Z2rM5mHXA,
linuxarm-hv44wF8Li93QT0dZR+AlfA
In-Reply-To: <20170802155952.185564-1-salil.mehta-hv44wF8Li93QT0dZR+AlfA@public.gmane.org>
This patch adds the support of MDIO bus interface for HNS3 driver.
Code provides various interfaces to start and stop the PHY layer
and to read and write the MDIO bus or PHY.
Signed-off-by: Daode Huang <huangdaode-C8/M+/jPZTeaMJb+Lgu22Q@public.gmane.org>
Signed-off-by: lipeng <lipeng321-hv44wF8Li93QT0dZR+AlfA@public.gmane.org>
Signed-off-by: Salil Mehta <salil.mehta-hv44wF8Li93QT0dZR+AlfA@public.gmane.org>
Signed-off-by: Yisen Zhuang <yisen.zhuang-hv44wF8Li93QT0dZR+AlfA@public.gmane.org>
---
Patch V6: Addressed following comments:
1. Andrew Lunn
https://lkml.org/lkml/2017/7/28/741
https://lkml.org/lkml/2017/7/28/742
Patch V5: Addressed following comments:
1. Florian Fainelli
https://lkml.org/lkml/2017/7/23/91
Patch V4: Addressed following comments:
1. Andrew Lunn
https://lkml.org/lkml/2017/6/17/208
Patch V3: Addressed Below comments:
1. Florian Fainelli
https://lkml.org/lkml/2017/6/13/963
2. Andrew Lunn
https://lkml.org/lkml/2017/6/13/1039
Patch V2: Addressed below comments:
1. Florian Fainelli
https://lkml.org/lkml/2017/6/10/130
2. Andrew Lunn
https://lkml.org/lkml/2017/6/10/168
Patch V1: Initial Submit
---
.../ethernet/hisilicon/hns3/hns3pf/hclge_mdio.c | 213 +++++++++++++++++++++
.../ethernet/hisilicon/hns3/hns3pf/hclge_mdio.h | 17 ++
2 files changed, 230 insertions(+)
create mode 100644 drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.c
create mode 100644 drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.h
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.c
new file mode 100644
index 0000000..a2add8b
--- /dev/null
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.c
@@ -0,0 +1,213 @@
+/*
+ * Copyright (c) 2016~2017 Hisilicon Limited.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/etherdevice.h>
+#include <linux/kernel.h>
+
+#include "hclge_cmd.h"
+#include "hclge_main.h"
+#include "hclge_mdio.h"
+
+enum hclge_mdio_c22_op_seq {
+ HCLGE_MDIO_C22_WRITE = 1,
+ HCLGE_MDIO_C22_READ = 2
+};
+
+#define HCLGE_MDIO_CTRL_START_B 0
+#define HCLGE_MDIO_CTRL_ST_S 1
+#define HCLGE_MDIO_CTRL_ST_M (0x3 << HCLGE_MDIO_CTRL_ST_S)
+#define HCLGE_MDIO_CTRL_OP_S 3
+#define HCLGE_MDIO_CTRL_OP_M (0x3 << HCLGE_MDIO_CTRL_OP_S)
+
+#define HCLGE_MDIO_PHYID_S 0
+#define HCLGE_MDIO_PHYID_M (0x1f << HCLGE_MDIO_PHYID_S)
+
+#define HCLGE_MDIO_PHYREG_S 0
+#define HCLGE_MDIO_PHYREG_M (0x1f << HCLGE_MDIO_PHYREG_S)
+
+#define HCLGE_MDIO_STA_B 0
+
+struct hclge_mdio_cfg_cmd {
+ u8 ctrl_bit;
+ u8 phyid;
+ u8 phyad;
+ u8 rsvd;
+ __le16 reserve;
+ __le16 data_wr;
+ __le16 data_rd;
+ __le16 sta;
+};
+
+static int hclge_mdio_write(struct mii_bus *bus, int phyid, int regnum,
+ u16 data)
+{
+ struct hclge_mdio_cfg_cmd *mdio_cmd;
+ struct hclge_dev *hdev = bus->priv;
+ struct hclge_desc desc;
+ int ret;
+
+ hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_MDIO_CONFIG, false);
+
+ mdio_cmd = (struct hclge_mdio_cfg_cmd *)desc.data;
+
+ hnae_set_field(mdio_cmd->phyid, HCLGE_MDIO_PHYID_M,
+ HCLGE_MDIO_PHYID_S, phyid);
+ hnae_set_field(mdio_cmd->phyad, HCLGE_MDIO_PHYREG_M,
+ HCLGE_MDIO_PHYREG_S, regnum);
+
+ hnae_set_bit(mdio_cmd->ctrl_bit, HCLGE_MDIO_CTRL_START_B, 1);
+ hnae_set_field(mdio_cmd->ctrl_bit, HCLGE_MDIO_CTRL_ST_M,
+ HCLGE_MDIO_CTRL_ST_S, 1);
+ hnae_set_field(mdio_cmd->ctrl_bit, HCLGE_MDIO_CTRL_OP_M,
+ HCLGE_MDIO_CTRL_OP_S, HCLGE_MDIO_C22_WRITE);
+
+ mdio_cmd->data_wr = cpu_to_le16(data);
+
+ ret = hclge_cmd_send(&hdev->hw, &desc, 1);
+ if (ret) {
+ dev_err(&hdev->pdev->dev,
+ "mdio write fail when sending cmd, status is %d.\n",
+ ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int hclge_mdio_read(struct mii_bus *bus, int phyid, int regnum)
+{
+ struct hclge_mdio_cfg_cmd *mdio_cmd;
+ struct hclge_dev *hdev = bus->priv;
+ struct hclge_desc desc;
+ int ret;
+
+ hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_MDIO_CONFIG, true);
+
+ mdio_cmd = (struct hclge_mdio_cfg_cmd *)desc.data;
+
+ hnae_set_field(mdio_cmd->phyid, HCLGE_MDIO_PHYID_M,
+ HCLGE_MDIO_PHYID_S, phyid);
+ hnae_set_field(mdio_cmd->phyad, HCLGE_MDIO_PHYREG_M,
+ HCLGE_MDIO_PHYREG_S, regnum);
+
+ hnae_set_bit(mdio_cmd->ctrl_bit, HCLGE_MDIO_CTRL_START_B, 1);
+ hnae_set_field(mdio_cmd->ctrl_bit, HCLGE_MDIO_CTRL_ST_M,
+ HCLGE_MDIO_CTRL_ST_S, 1);
+ hnae_set_field(mdio_cmd->ctrl_bit, HCLGE_MDIO_CTRL_OP_M,
+ HCLGE_MDIO_CTRL_OP_S, HCLGE_MDIO_C22_READ);
+
+ /* Read out phy data */
+ ret = hclge_cmd_send(&hdev->hw, &desc, 1);
+ if (ret) {
+ dev_err(&hdev->pdev->dev,
+ "mdio read fail when get data, status is %d.\n",
+ ret);
+ return ret;
+ }
+
+ if (hnae_get_bit(le16_to_cpu(mdio_cmd->sta), HCLGE_MDIO_STA_B)) {
+ dev_err(&hdev->pdev->dev, "mdio read data error\n");
+ return -EIO;
+ }
+
+ return le16_to_cpu(mdio_cmd->data_rd);
+}
+
+int hclge_mac_mdio_config(struct hclge_dev *hdev)
+{
+ struct hclge_mac *mac = &hdev->hw.mac;
+ struct phy_device *phydev;
+ struct mii_bus *mdio_bus;
+ int ret;
+
+ if (hdev->hw.mac.phy_addr >= PHY_MAX_ADDR)
+ return 0;
+
+ mdio_bus = devm_mdiobus_alloc(&hdev->pdev->dev);
+ if (!mdio_bus)
+ return -ENOMEM;
+
+ mdio_bus->name = "hisilicon MII bus";
+ mdio_bus->read = hclge_mdio_read;
+ mdio_bus->write = hclge_mdio_write;
+ snprintf(mdio_bus->id, MII_BUS_ID_SIZE, "%s-%s", "mii",
+ dev_name(&hdev->pdev->dev));
+
+ mdio_bus->parent = &hdev->pdev->dev;
+ mdio_bus->priv = hdev;
+ mdio_bus->phy_mask = ~(1 << mac->phy_addr);
+ ret = mdiobus_register(mdio_bus);
+ if (ret) {
+ dev_err(mdio_bus->parent,
+ "Failed to register MDIO bus ret = %#x\n", ret);
+ return ret;
+ }
+
+ phydev = mdiobus_get_phy(mdio_bus, mac->phy_addr);
+ if (!phydev || IS_ERR(phydev)) {
+ dev_err(mdio_bus->parent, "Failed to get phy device\n");
+ mdiobus_unregister(mdio_bus);
+ return -EIO;
+ }
+
+ mac->phydev = phydev;
+ mac->mdio_bus = mdio_bus;
+
+ return 0;
+}
+
+static void hclge_mac_adjust_link(struct net_device *netdev)
+{
+ struct hnae3_handle *h = *((void **)netdev_priv(netdev));
+ struct hclge_vport *vport = hclge_get_vport(h);
+ struct hclge_dev *hdev = vport->back;
+ int duplex, speed;
+ int ret;
+
+ speed = netdev->phydev->speed;
+ duplex = netdev->phydev->duplex;
+
+ ret = hclge_cfg_mac_speed_dup(hdev, speed, duplex);
+ if (ret)
+ netdev_err(netdev, "failed to adjust link.\n");
+}
+
+int hclge_mac_start_phy(struct hclge_dev *hdev)
+{
+ struct net_device *netdev = hdev->vport[0].nic.netdev;
+ struct phy_device *phydev = hdev->hw.mac.phydev;
+ int ret;
+
+ if (!phydev)
+ return 0;
+
+ ret = phy_connect_direct(netdev, phydev,
+ hclge_mac_adjust_link,
+ PHY_INTERFACE_MODE_SGMII);
+ if (ret) {
+ netdev_err(netdev, "phy_connect_direct err.\n");
+ return ret;
+ }
+
+ phy_start(phydev);
+
+ return 0;
+}
+
+void hclge_mac_stop_phy(struct hclge_dev *hdev)
+{
+ struct net_device *netdev = hdev->vport[0].nic.netdev;
+ struct phy_device *phydev = netdev->phydev;
+
+ if (!phydev)
+ return;
+
+ phy_stop(phydev);
+ phy_disconnect(phydev);
+}
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.h
new file mode 100644
index 0000000..c5e91cf
--- /dev/null
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.h
@@ -0,0 +1,17 @@
+/*
+ * Copyright (c) 2016-2017 Hisilicon Limited.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __HCLGE_MDIO_H
+#define __HCLGE_MDIO_H
+
+int hclge_mac_mdio_config(struct hclge_dev *hdev);
+int hclge_mac_start_phy(struct hclge_dev *hdev);
+void hclge_mac_stop_phy(struct hclge_dev *hdev);
+
+#endif
--
2.7.4
--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* [PATCH V6 net-next 5/8] net: hns3: Add support of TX Scheduler & Shaper to HNS3 driver
From: Salil Mehta @ 2017-08-02 15:59 UTC (permalink / raw)
To: davem
Cc: salil.mehta, yisen.zhuang, huangdaode, lipeng321, mehta.salil.lnk,
netdev, linux-kernel, linux-rdma, linuxarm, Wei Hu
In-Reply-To: <20170802155952.185564-1-salil.mehta@huawei.com>
THis patch adds the support of the Scheduling and Shaping
functionalities during the transmit leg. This also adds the
support of Pause at MAC level. (Pause at per-priority level
shall be added later along with the DCB feature).
Hardware as such consists of two types of cofiguration of 6 level
schedulers. Algorithms varies according to the level and type
of scheduler being used. Current patch is used to initialize
the mapping, algorithms(like SP, DWRR etc) and shaper(CIR, PIR etc)
being used.
Signed-off-by: Daode Huang <huangdaode@hisilicon.com>
Signed-off-by: lipeng <lipeng321@huawei.com>
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
Signed-off-by: Yisen Zhuang <yisen.zhuang@huawei.com>
Signed-off-by: Wei Hu (Xavier) <xavier.huwei@huawei.com>
---
Patch V6: Addressed some internal comments
1. Fixed the return values from ENOMEM -> EINVAL
2. renamed to __HCLGE_TM_H macro in header file
Patch V5: Addressed comments by
1. Richard Cochran
https://lkml.org/lkml/2017/7/23/13
Patch V2,V4: No Change
Patch V1: Initial Submit
---
.../net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c | 1015 ++++++++++++++++++++
.../net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.h | 106 ++
2 files changed, 1121 insertions(+)
create mode 100644 drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c
create mode 100644 drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.h
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c
new file mode 100644
index 0000000..1c577d2
--- /dev/null
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c
@@ -0,0 +1,1015 @@
+/*
+ * Copyright (c) 2016~2017 Hisilicon Limited.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/etherdevice.h>
+
+#include "hclge_cmd.h"
+#include "hclge_main.h"
+#include "hclge_tm.h"
+
+enum hclge_shaper_level {
+ HCLGE_SHAPER_LVL_PRI = 0,
+ HCLGE_SHAPER_LVL_PG = 1,
+ HCLGE_SHAPER_LVL_PORT = 2,
+ HCLGE_SHAPER_LVL_QSET = 3,
+ HCLGE_SHAPER_LVL_CNT = 4,
+ HCLGE_SHAPER_LVL_VF = 0,
+ HCLGE_SHAPER_LVL_PF = 1,
+};
+
+#define HCLGE_SHAPER_BS_U_DEF 1
+#define HCLGE_SHAPER_BS_S_DEF 4
+
+#define HCLGE_ETHER_MAX_RATE 100000
+
+/* hclge_shaper_para_calc: calculate ir parameter for the shaper
+ * @ir: Rate to be config, its unit is Mbps
+ * @shaper_level: the shaper level. eg: port, pg, priority, queueset
+ * @ir_b: IR_B parameter of IR shaper
+ * @ir_u: IR_U parameter of IR shaper
+ * @ir_s: IR_S parameter of IR shaper
+ *
+ * the formula:
+ *
+ * IR_b * (2 ^ IR_u) * 8
+ * IR(Mbps) = ------------------------- * CLOCK(1000Mbps)
+ * Tick * (2 ^ IR_s)
+ *
+ * @return: 0: calculate sucessful, negative: fail
+ */
+static int hclge_shaper_para_calc(u32 ir, u8 shaper_level,
+ u8 *ir_b, u8 *ir_u, u8 *ir_s)
+{
+ const u16 tick_array[HCLGE_SHAPER_LVL_CNT] = {
+ 6 * 256, /* Prioriy level */
+ 6 * 32, /* Prioriy group level */
+ 6 * 8, /* Port level */
+ 6 * 256 /* Qset level */
+ };
+ u8 ir_u_calc = 0, ir_s_calc = 0;
+ u32 ir_calc;
+ u32 tick;
+
+ /* Calc tick */
+ if (shaper_level >= HCLGE_SHAPER_LVL_CNT)
+ return -EINVAL;
+
+ tick = tick_array[shaper_level];
+
+ /**
+ * Calc the speed if ir_b = 126, ir_u = 0 and ir_s = 0
+ * the formula is changed to:
+ * 126 * 1 * 8
+ * ir_calc = ---------------- * 1000
+ * tick * 1
+ */
+ ir_calc = (1008000 + (tick >> 1) - 1) / tick;
+
+ if (ir_calc == ir) {
+ *ir_b = 126;
+ *ir_u = 0;
+ *ir_s = 0;
+
+ return 0;
+ } else if (ir_calc > ir) {
+ /* Increasing the denominator to select ir_s value */
+ while (ir_calc > ir) {
+ ir_s_calc++;
+ ir_calc = 1008000 / (tick * (1 << ir_s_calc));
+ }
+
+ if (ir_calc == ir)
+ *ir_b = 126;
+ else
+ *ir_b = (ir * tick * (1 << ir_s_calc) + 4000) / 8000;
+ } else {
+ /* Increasing the numerator to select ir_u value */
+ u32 numerator;
+
+ while (ir_calc < ir) {
+ ir_u_calc++;
+ numerator = 1008000 * (1 << ir_u_calc);
+ ir_calc = (numerator + (tick >> 1)) / tick;
+ }
+
+ if (ir_calc == ir) {
+ *ir_b = 126;
+ } else {
+ u32 denominator = (8000 * (1 << --ir_u_calc));
+ *ir_b = (ir * tick + (denominator >> 1)) / denominator;
+ }
+ }
+
+ *ir_u = ir_u_calc;
+ *ir_s = ir_s_calc;
+
+ return 0;
+}
+
+static int hclge_mac_pause_en_cfg(struct hclge_dev *hdev, bool tx, bool rx)
+{
+ struct hclge_desc desc;
+
+ hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_CFG_MAC_PAUSE_EN, false);
+
+ desc.data[0] = cpu_to_le32((tx ? HCLGE_TX_MAC_PAUSE_EN_MSK : 0) |
+ (rx ? HCLGE_RX_MAC_PAUSE_EN_MSK : 0));
+
+ return hclge_cmd_send(&hdev->hw, &desc, 1);
+}
+
+static int hclge_fill_pri_array(struct hclge_dev *hdev, u8 *pri, u8 pri_id)
+{
+ u8 tc;
+
+ for (tc = 0; tc < hdev->tm_info.num_tc; tc++)
+ if (hdev->tm_info.tc_info[tc].up == pri_id)
+ break;
+
+ if (tc >= hdev->tm_info.num_tc)
+ return -EINVAL;
+
+ /**
+ * the register for priority has four bytes, the first bytes includes
+ * priority0 and priority1, the higher 4bit stands for priority1
+ * while the lower 4bit stands for priority0, as below:
+ * first byte: | pri_1 | pri_0 |
+ * second byte: | pri_3 | pri_2 |
+ * third byte: | pri_5 | pri_4 |
+ * fourth byte: | pri_7 | pri_6 |
+ */
+ pri[pri_id >> 1] |= tc << ((pri_id & 1) * 4);
+
+ return 0;
+}
+
+static int hclge_up_to_tc_map(struct hclge_dev *hdev)
+{
+ struct hclge_desc desc;
+ u8 *pri = (u8 *)desc.data;
+ u8 pri_id;
+ int ret;
+
+ hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_PRI_TO_TC_MAPPING, false);
+
+ for (pri_id = 0; pri_id < hdev->tm_info.num_tc; pri_id++) {
+ ret = hclge_fill_pri_array(hdev, pri, pri_id);
+ if (ret)
+ return ret;
+ }
+
+ return hclge_cmd_send(&hdev->hw, &desc, 1);
+}
+
+static int hclge_tm_pg_to_pri_map_cfg(struct hclge_dev *hdev,
+ u8 pg_id, u8 pri_bit_map)
+{
+ struct hclge_pg_to_pri_link_cmd *map;
+ struct hclge_desc desc;
+
+ hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_TM_PG_TO_PRI_LINK, false);
+
+ map = (struct hclge_pg_to_pri_link_cmd *)desc.data;
+
+ map->pg_id = pg_id;
+ map->pri_bit_map = pri_bit_map;
+
+ return hclge_cmd_send(&hdev->hw, &desc, 1);
+}
+
+static int hclge_tm_qs_to_pri_map_cfg(struct hclge_dev *hdev,
+ u16 qs_id, u8 pri)
+{
+ struct hclge_qs_to_pri_link_cmd *map;
+ struct hclge_desc desc;
+
+ hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_TM_QS_TO_PRI_LINK, false);
+
+ map = (struct hclge_qs_to_pri_link_cmd *)desc.data;
+
+ map->qs_id = cpu_to_le16(qs_id);
+ map->priority = pri;
+ map->link_vld = HCLGE_TM_QS_PRI_LINK_VLD_MSK;
+
+ return hclge_cmd_send(&hdev->hw, &desc, 1);
+}
+
+static int hclge_tm_q_to_qs_map_cfg(struct hclge_dev *hdev,
+ u8 q_id, u16 qs_id)
+{
+ struct hclge_nq_to_qs_link_cmd *map;
+ struct hclge_desc desc;
+
+ hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_TM_NQ_TO_QS_LINK, false);
+
+ map = (struct hclge_nq_to_qs_link_cmd *)desc.data;
+
+ map->nq_id = cpu_to_le16(q_id);
+ map->qset_id = cpu_to_le16(qs_id | HCLGE_TM_Q_QS_LINK_VLD_MSK);
+
+ return hclge_cmd_send(&hdev->hw, &desc, 1);
+}
+
+static int hclge_tm_pg_weight_cfg(struct hclge_dev *hdev, u8 pg_id,
+ u8 dwrr)
+{
+ struct hclge_pg_weight_cmd *weight;
+ struct hclge_desc desc;
+
+ hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_TM_PG_WEIGHT, false);
+
+ weight = (struct hclge_pg_weight_cmd *)desc.data;
+
+ weight->pg_id = pg_id;
+ weight->dwrr = dwrr;
+
+ return hclge_cmd_send(&hdev->hw, &desc, 1);
+}
+
+static int hclge_tm_pri_weight_cfg(struct hclge_dev *hdev, u8 pri_id,
+ u8 dwrr)
+{
+ struct hclge_priority_weight_cmd *weight;
+ struct hclge_desc desc;
+
+ hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_TM_PRI_WEIGHT, false);
+
+ weight = (struct hclge_priority_weight_cmd *)desc.data;
+
+ weight->pri_id = pri_id;
+ weight->dwrr = dwrr;
+
+ return hclge_cmd_send(&hdev->hw, &desc, 1);
+}
+
+static int hclge_tm_qs_weight_cfg(struct hclge_dev *hdev, u16 qs_id,
+ u8 dwrr)
+{
+ struct hclge_qs_weight_cmd *weight;
+ struct hclge_desc desc;
+
+ hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_TM_QS_WEIGHT, false);
+
+ weight = (struct hclge_qs_weight_cmd *)desc.data;
+
+ weight->qs_id = cpu_to_le16(qs_id);
+ weight->dwrr = dwrr;
+
+ return hclge_cmd_send(&hdev->hw, &desc, 1);
+}
+
+static int hclge_tm_pg_shapping_cfg(struct hclge_dev *hdev,
+ enum hclge_shap_bucket bucket, u8 pg_id,
+ u8 ir_b, u8 ir_u, u8 ir_s, u8 bs_b, u8 bs_s)
+{
+ struct hclge_pg_shapping_cmd *shap_cfg_cmd;
+ enum hclge_opcode_type opcode;
+ struct hclge_desc desc;
+
+ opcode = bucket ? HCLGE_OPC_TM_PG_P_SHAPPING :
+ HCLGE_OPC_TM_PG_C_SHAPPING;
+ hclge_cmd_setup_basic_desc(&desc, opcode, false);
+
+ shap_cfg_cmd = (struct hclge_pg_shapping_cmd *)desc.data;
+
+ shap_cfg_cmd->pg_id = pg_id;
+
+ hclge_tm_set_feild(shap_cfg_cmd->pg_shapping_para, IR_B, ir_b);
+ hclge_tm_set_feild(shap_cfg_cmd->pg_shapping_para, IR_U, ir_u);
+ hclge_tm_set_feild(shap_cfg_cmd->pg_shapping_para, IR_S, ir_s);
+ hclge_tm_set_feild(shap_cfg_cmd->pg_shapping_para, BS_B, bs_b);
+ hclge_tm_set_feild(shap_cfg_cmd->pg_shapping_para, BS_S, bs_s);
+
+ return hclge_cmd_send(&hdev->hw, &desc, 1);
+}
+
+static int hclge_tm_pri_shapping_cfg(struct hclge_dev *hdev,
+ enum hclge_shap_bucket bucket, u8 pri_id,
+ u8 ir_b, u8 ir_u, u8 ir_s,
+ u8 bs_b, u8 bs_s)
+{
+ struct hclge_pri_shapping_cmd *shap_cfg_cmd;
+ enum hclge_opcode_type opcode;
+ struct hclge_desc desc;
+
+ opcode = bucket ? HCLGE_OPC_TM_PRI_P_SHAPPING :
+ HCLGE_OPC_TM_PRI_C_SHAPPING;
+
+ hclge_cmd_setup_basic_desc(&desc, opcode, false);
+
+ shap_cfg_cmd = (struct hclge_pri_shapping_cmd *)desc.data;
+
+ shap_cfg_cmd->pri_id = pri_id;
+
+ hclge_tm_set_feild(shap_cfg_cmd->pri_shapping_para, IR_B, ir_b);
+ hclge_tm_set_feild(shap_cfg_cmd->pri_shapping_para, IR_U, ir_u);
+ hclge_tm_set_feild(shap_cfg_cmd->pri_shapping_para, IR_S, ir_s);
+ hclge_tm_set_feild(shap_cfg_cmd->pri_shapping_para, BS_B, bs_b);
+ hclge_tm_set_feild(shap_cfg_cmd->pri_shapping_para, BS_S, bs_s);
+
+ return hclge_cmd_send(&hdev->hw, &desc, 1);
+}
+
+static int hclge_tm_pg_schd_mode_cfg(struct hclge_dev *hdev, u8 pg_id)
+{
+ struct hclge_desc desc;
+
+ hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_TM_PG_SCH_MODE_CFG, false);
+
+ if (hdev->tm_info.pg_info[pg_id].pg_sch_mode == HCLGE_SCH_MODE_DWRR)
+ desc.data[1] = cpu_to_le32(HCLGE_TM_TX_SCHD_DWRR_MSK);
+ else
+ desc.data[1] = 0;
+
+ desc.data[0] = cpu_to_le32(pg_id);
+
+ return hclge_cmd_send(&hdev->hw, &desc, 1);
+}
+
+static int hclge_tm_pri_schd_mode_cfg(struct hclge_dev *hdev, u8 pri_id)
+{
+ struct hclge_desc desc;
+
+ hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_TM_PRI_SCH_MODE_CFG, false);
+
+ if (hdev->tm_info.tc_info[pri_id].tc_sch_mode == HCLGE_SCH_MODE_DWRR)
+ desc.data[1] = cpu_to_le32(HCLGE_TM_TX_SCHD_DWRR_MSK);
+ else
+ desc.data[1] = 0;
+
+ desc.data[0] = cpu_to_le32(pri_id);
+
+ return hclge_cmd_send(&hdev->hw, &desc, 1);
+}
+
+static int hclge_tm_qs_schd_mode_cfg(struct hclge_dev *hdev, u16 qs_id)
+{
+ struct hclge_desc desc;
+
+ hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_TM_QS_SCH_MODE_CFG, false);
+
+ if (hdev->tm_info.tc_info[qs_id].tc_sch_mode == HCLGE_SCH_MODE_DWRR)
+ desc.data[1] = cpu_to_le32(HCLGE_TM_TX_SCHD_DWRR_MSK);
+ else
+ desc.data[1] = 0;
+
+ desc.data[0] = cpu_to_le32(qs_id);
+
+ return hclge_cmd_send(&hdev->hw, &desc, 1);
+}
+
+static int hclge_tm_qs_bp_cfg(struct hclge_dev *hdev, u8 tc)
+{
+ struct hclge_bp_to_qs_map_cmd *bp_to_qs_map_cmd;
+ struct hclge_desc desc;
+
+ hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_TM_BP_TO_QSET_MAPPING,
+ false);
+
+ bp_to_qs_map_cmd = (struct hclge_bp_to_qs_map_cmd *)desc.data;
+
+ bp_to_qs_map_cmd->tc_id = tc;
+
+ /* Qset and tc is one by one mapping */
+ bp_to_qs_map_cmd->qs_bit_map = cpu_to_le32(1 << tc);
+
+ return hclge_cmd_send(&hdev->hw, &desc, 1);
+}
+
+static void hclge_tm_vport_tc_info_update(struct hclge_vport *vport)
+{
+ struct hnae3_knic_private_info *kinfo = &vport->nic.kinfo;
+ struct hclge_dev *hdev = vport->back;
+ u8 i;
+
+ kinfo = &vport->nic.kinfo;
+ vport->bw_limit = hdev->tm_info.pg_info[0].bw_limit;
+ kinfo->num_tc =
+ min_t(u16, kinfo->num_tqps, hdev->tm_info.num_tc);
+ kinfo->rss_size
+ = min_t(u16, hdev->rss_size_max,
+ kinfo->num_tqps / kinfo->num_tc);
+ vport->qs_offset = hdev->tm_info.num_tc * vport->vport_id;
+ vport->dwrr = 100; /* 100 percent as init */
+
+ for (i = 0; i < kinfo->num_tc; i++) {
+ if (hdev->hw_tc_map & BIT(i)) {
+ kinfo->tc_info[i].enable = true;
+ kinfo->tc_info[i].tqp_offset = i * kinfo->rss_size;
+ kinfo->tc_info[i].tqp_count = kinfo->rss_size;
+ kinfo->tc_info[i].tc = i;
+ kinfo->tc_info[i].up = hdev->tm_info.tc_info[i].up;
+ } else {
+ /* Set to default queue if TC is disable */
+ kinfo->tc_info[i].enable = false;
+ kinfo->tc_info[i].tqp_offset = 0;
+ kinfo->tc_info[i].tqp_count = 1;
+ kinfo->tc_info[i].tc = 0;
+ kinfo->tc_info[i].up = 0;
+ }
+ }
+}
+
+static void hclge_tm_vport_info_update(struct hclge_dev *hdev)
+{
+ struct hclge_vport *vport = hdev->vport;
+ u32 i;
+
+ for (i = 0; i < hdev->num_alloc_vport; i++) {
+ hclge_tm_vport_tc_info_update(vport);
+
+ vport++;
+ }
+}
+
+static void hclge_tm_tc_info_init(struct hclge_dev *hdev)
+{
+ u8 i;
+
+ for (i = 0; i < hdev->tm_info.num_tc; i++) {
+ hdev->tm_info.tc_info[i].tc_id = i;
+ hdev->tm_info.tc_info[i].tc_sch_mode = HCLGE_SCH_MODE_DWRR;
+ hdev->tm_info.tc_info[i].up = i;
+ hdev->tm_info.tc_info[i].pgid = 0;
+ hdev->tm_info.tc_info[i].bw_limit =
+ hdev->tm_info.pg_info[0].bw_limit;
+ }
+
+ hdev->flag &= ~HCLGE_FLAG_DCB_ENABLE;
+}
+
+static void hclge_tm_pg_info_init(struct hclge_dev *hdev)
+{
+ u8 i;
+
+ for (i = 0; i < hdev->tm_info.num_pg; i++) {
+ int k;
+
+ hdev->tm_info.pg_dwrr[i] = i ? 0 : 100;
+
+ hdev->tm_info.pg_info[i].pg_id = i;
+ hdev->tm_info.pg_info[i].pg_sch_mode = HCLGE_SCH_MODE_DWRR;
+
+ hdev->tm_info.pg_info[i].bw_limit = HCLGE_ETHER_MAX_RATE;
+
+ if (i != 0)
+ continue;
+
+ hdev->tm_info.pg_info[i].tc_bit_map = hdev->hw_tc_map;
+ for (k = 0; k < hdev->tm_info.num_tc; k++)
+ hdev->tm_info.pg_info[i].tc_dwrr[k] = 100;
+ }
+}
+
+static int hclge_tm_schd_info_init(struct hclge_dev *hdev)
+{
+ if ((hdev->tx_sch_mode != HCLGE_FLAG_TC_BASE_SCH_MODE) &&
+ (hdev->tm_info.num_pg != 1))
+ return -EINVAL;
+
+ hclge_tm_pg_info_init(hdev);
+
+ hclge_tm_tc_info_init(hdev);
+
+ hclge_tm_vport_info_update(hdev);
+
+ hdev->tm_info.fc_mode = HCLGE_FC_NONE;
+ hdev->fc_mode_last_time = hdev->tm_info.fc_mode;
+
+ return 0;
+}
+
+static int hclge_tm_pg_to_pri_map(struct hclge_dev *hdev)
+{
+ int ret;
+ u32 i;
+
+ if (hdev->tx_sch_mode != HCLGE_FLAG_TC_BASE_SCH_MODE)
+ return 0;
+
+ for (i = 0; i < hdev->tm_info.num_pg; i++) {
+ /* Cfg mapping */
+ ret = hclge_tm_pg_to_pri_map_cfg(
+ hdev, i, hdev->tm_info.pg_info[i].tc_bit_map);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static int hclge_tm_pg_shaper_cfg(struct hclge_dev *hdev)
+{
+ u8 ir_u, ir_b, ir_s;
+ int ret;
+ u32 i;
+
+ /* Cfg pg schd */
+ if (hdev->tx_sch_mode != HCLGE_FLAG_TC_BASE_SCH_MODE)
+ return 0;
+
+ /* Pg to pri */
+ for (i = 0; i < hdev->tm_info.num_pg; i++) {
+ /* Calc shaper para */
+ ret = hclge_shaper_para_calc(
+ hdev->tm_info.pg_info[i].bw_limit,
+ HCLGE_SHAPER_LVL_PG,
+ &ir_b, &ir_u, &ir_s);
+ if (ret)
+ return ret;
+
+ ret = hclge_tm_pg_shapping_cfg(hdev,
+ HCLGE_TM_SHAP_C_BUCKET, i,
+ 0, 0, 0, HCLGE_SHAPER_BS_U_DEF,
+ HCLGE_SHAPER_BS_S_DEF);
+ if (ret)
+ return ret;
+
+ ret = hclge_tm_pg_shapping_cfg(hdev,
+ HCLGE_TM_SHAP_P_BUCKET, i,
+ ir_b, ir_u, ir_s,
+ HCLGE_SHAPER_BS_U_DEF,
+ HCLGE_SHAPER_BS_S_DEF);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static int hclge_tm_pg_dwrr_cfg(struct hclge_dev *hdev)
+{
+ int ret;
+ u32 i;
+
+ /* cfg pg schd */
+ if (hdev->tx_sch_mode != HCLGE_FLAG_TC_BASE_SCH_MODE)
+ return 0;
+
+ /* pg to prio */
+ for (i = 0; i < hdev->tm_info.num_pg; i++) {
+ /* Cfg dwrr */
+ ret = hclge_tm_pg_weight_cfg(hdev, i,
+ hdev->tm_info.pg_dwrr[i]);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static int hclge_vport_q_to_qs_map(struct hclge_dev *hdev,
+ struct hclge_vport *vport)
+{
+ struct hnae3_knic_private_info *kinfo = &vport->nic.kinfo;
+ struct hnae3_queue **tqp = kinfo->tqp;
+ struct hnae3_tc_info *v_tc_info;
+ u32 i, j;
+ int ret;
+
+ for (i = 0; i < kinfo->num_tc; i++) {
+ v_tc_info = &kinfo->tc_info[i];
+ for (j = 0; j < v_tc_info->tqp_count; j++) {
+ struct hnae3_queue *q = tqp[v_tc_info->tqp_offset + j];
+
+ ret = hclge_tm_q_to_qs_map_cfg(hdev,
+ hclge_get_queue_id(q),
+ vport->qs_offset + i);
+ if (ret)
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
+static int hclge_tm_pri_q_qs_cfg(struct hclge_dev *hdev)
+{
+ struct hclge_vport *vport = hdev->vport;
+ int ret;
+ u32 i;
+
+ if (hdev->tx_sch_mode == HCLGE_FLAG_TC_BASE_SCH_MODE) {
+ /* Cfg qs -> pri mapping, one by one mapping */
+ for (i = 0; i < hdev->tm_info.num_tc; i++) {
+ ret = hclge_tm_qs_to_pri_map_cfg(hdev, i, i);
+ if (ret)
+ return ret;
+ }
+ } else if (hdev->tx_sch_mode == HCLGE_FLAG_VNET_BASE_SCH_MODE) {
+ int k;
+ /* Cfg qs -> pri mapping, qs = tc, pri = vf, 8 qs -> 1 pri */
+ for (k = 0; k < hdev->num_alloc_vport; k++)
+ for (i = 0; i < HNAE3_MAX_TC; i++) {
+ ret = hclge_tm_qs_to_pri_map_cfg(
+ hdev, vport[k].qs_offset + i, k);
+ if (ret)
+ return ret;
+ }
+ } else {
+ return -EINVAL;
+ }
+
+ /* Cfg q -> qs mapping */
+ for (i = 0; i < hdev->num_alloc_vport; i++) {
+ ret = hclge_vport_q_to_qs_map(hdev, vport);
+ if (ret)
+ return ret;
+
+ vport++;
+ }
+
+ return 0;
+}
+
+static int hclge_tm_pri_tc_base_shaper_cfg(struct hclge_dev *hdev)
+{
+ u8 ir_u, ir_b, ir_s;
+ int ret;
+ u32 i;
+
+ for (i = 0; i < hdev->tm_info.num_tc; i++) {
+ ret = hclge_shaper_para_calc(
+ hdev->tm_info.tc_info[i].bw_limit,
+ HCLGE_SHAPER_LVL_PRI,
+ &ir_b, &ir_u, &ir_s);
+ if (ret)
+ return ret;
+
+ ret = hclge_tm_pri_shapping_cfg(
+ hdev, HCLGE_TM_SHAP_C_BUCKET, i,
+ 0, 0, 0, HCLGE_SHAPER_BS_U_DEF,
+ HCLGE_SHAPER_BS_S_DEF);
+ if (ret)
+ return ret;
+
+ ret = hclge_tm_pri_shapping_cfg(
+ hdev, HCLGE_TM_SHAP_P_BUCKET, i,
+ ir_b, ir_u, ir_s, HCLGE_SHAPER_BS_U_DEF,
+ HCLGE_SHAPER_BS_S_DEF);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static int hclge_tm_pri_vnet_base_shaper_pri_cfg(struct hclge_vport *vport)
+{
+ struct hclge_dev *hdev = vport->back;
+ u8 ir_u, ir_b, ir_s;
+ int ret;
+
+ ret = hclge_shaper_para_calc(vport->bw_limit, HCLGE_SHAPER_LVL_VF,
+ &ir_b, &ir_u, &ir_s);
+ if (ret)
+ return ret;
+
+ ret = hclge_tm_pri_shapping_cfg(hdev, HCLGE_TM_SHAP_C_BUCKET,
+ vport->vport_id,
+ 0, 0, 0, HCLGE_SHAPER_BS_U_DEF,
+ HCLGE_SHAPER_BS_S_DEF);
+ if (ret)
+ return ret;
+
+ ret = hclge_tm_pri_shapping_cfg(hdev, HCLGE_TM_SHAP_P_BUCKET,
+ vport->vport_id,
+ ir_b, ir_u, ir_s,
+ HCLGE_SHAPER_BS_U_DEF,
+ HCLGE_SHAPER_BS_S_DEF);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static int hclge_tm_pri_vnet_base_shaper_qs_cfg(struct hclge_vport *vport)
+{
+ struct hnae3_knic_private_info *kinfo = &vport->nic.kinfo;
+ struct hclge_dev *hdev = vport->back;
+ struct hnae3_tc_info *v_tc_info;
+ u8 ir_u, ir_b, ir_s;
+ u32 i;
+ int ret;
+
+ for (i = 0; i < kinfo->num_tc; i++) {
+ v_tc_info = &kinfo->tc_info[i];
+ ret = hclge_shaper_para_calc(
+ hdev->tm_info.tc_info[i].bw_limit,
+ HCLGE_SHAPER_LVL_QSET,
+ &ir_b, &ir_u, &ir_s);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static int hclge_tm_pri_vnet_base_shaper_cfg(struct hclge_dev *hdev)
+{
+ struct hclge_vport *vport = hdev->vport;
+ int ret;
+ u32 i;
+
+ /* Need config vport shaper */
+ for (i = 0; i < hdev->num_alloc_vport; i++) {
+ ret = hclge_tm_pri_vnet_base_shaper_pri_cfg(vport);
+ if (ret)
+ return ret;
+
+ ret = hclge_tm_pri_vnet_base_shaper_qs_cfg(vport);
+ if (ret)
+ return ret;
+
+ vport++;
+ }
+
+ return 0;
+}
+
+static int hclge_tm_pri_shaper_cfg(struct hclge_dev *hdev)
+{
+ int ret;
+
+ if (hdev->tx_sch_mode == HCLGE_FLAG_TC_BASE_SCH_MODE) {
+ ret = hclge_tm_pri_tc_base_shaper_cfg(hdev);
+ if (ret)
+ return ret;
+ } else {
+ ret = hclge_tm_pri_vnet_base_shaper_cfg(hdev);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static int hclge_tm_pri_tc_base_dwrr_cfg(struct hclge_dev *hdev)
+{
+ struct hclge_pg_info *pg_info;
+ u8 dwrr;
+ int ret;
+ u32 i;
+
+ for (i = 0; i < hdev->tm_info.num_tc; i++) {
+ pg_info =
+ &hdev->tm_info.pg_info[hdev->tm_info.tc_info[i].pgid];
+ dwrr = pg_info->tc_dwrr[i];
+
+ ret = hclge_tm_pri_weight_cfg(hdev, i, dwrr);
+ if (ret)
+ return ret;
+
+ ret = hclge_tm_qs_weight_cfg(hdev, i, dwrr);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static int hclge_tm_pri_vnet_base_dwrr_pri_cfg(struct hclge_vport *vport)
+{
+ struct hnae3_knic_private_info *kinfo = &vport->nic.kinfo;
+ struct hclge_dev *hdev = vport->back;
+ int ret;
+ u8 i;
+
+ /* Vf dwrr */
+ ret = hclge_tm_pri_weight_cfg(hdev, vport->vport_id, vport->dwrr);
+ if (ret)
+ return ret;
+
+ /* Qset dwrr */
+ for (i = 0; i < kinfo->num_tc; i++) {
+ ret = hclge_tm_qs_weight_cfg(
+ hdev, vport->qs_offset + i,
+ hdev->tm_info.pg_info[0].tc_dwrr[i]);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static int hclge_tm_pri_vnet_base_dwrr_cfg(struct hclge_dev *hdev)
+{
+ struct hclge_vport *vport = hdev->vport;
+ int ret;
+ u32 i;
+
+ for (i = 0; i < hdev->num_alloc_vport; i++) {
+ ret = hclge_tm_pri_vnet_base_dwrr_pri_cfg(vport);
+ if (ret)
+ return ret;
+
+ vport++;
+ }
+
+ return 0;
+}
+
+static int hclge_tm_pri_dwrr_cfg(struct hclge_dev *hdev)
+{
+ int ret;
+
+ if (hdev->tx_sch_mode == HCLGE_FLAG_TC_BASE_SCH_MODE) {
+ ret = hclge_tm_pri_tc_base_dwrr_cfg(hdev);
+ if (ret)
+ return ret;
+ } else {
+ ret = hclge_tm_pri_vnet_base_dwrr_cfg(hdev);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static int hclge_tm_map_cfg(struct hclge_dev *hdev)
+{
+ int ret;
+
+ ret = hclge_tm_pg_to_pri_map(hdev);
+ if (ret)
+ return ret;
+
+ return hclge_tm_pri_q_qs_cfg(hdev);
+}
+
+static int hclge_tm_shaper_cfg(struct hclge_dev *hdev)
+{
+ int ret;
+
+ ret = hclge_tm_pg_shaper_cfg(hdev);
+ if (ret)
+ return ret;
+
+ return hclge_tm_pri_shaper_cfg(hdev);
+}
+
+int hclge_tm_dwrr_cfg(struct hclge_dev *hdev)
+{
+ int ret;
+
+ ret = hclge_tm_pg_dwrr_cfg(hdev);
+ if (ret)
+ return ret;
+
+ return hclge_tm_pri_dwrr_cfg(hdev);
+}
+
+static int hclge_tm_lvl2_schd_mode_cfg(struct hclge_dev *hdev)
+{
+ int ret;
+ u8 i;
+
+ /* Only being config on TC-Based scheduler mode */
+ if (hdev->tx_sch_mode == HCLGE_FLAG_VNET_BASE_SCH_MODE)
+ return 0;
+
+ for (i = 0; i < hdev->tm_info.num_pg; i++) {
+ ret = hclge_tm_pg_schd_mode_cfg(hdev, i);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static int hclge_tm_schd_mode_vnet_base_cfg(struct hclge_vport *vport)
+{
+ struct hnae3_knic_private_info *kinfo = &vport->nic.kinfo;
+ struct hclge_dev *hdev = vport->back;
+ int ret;
+ u8 i;
+
+ ret = hclge_tm_pri_schd_mode_cfg(hdev, vport->vport_id);
+ if (ret)
+ return ret;
+
+ for (i = 0; i < kinfo->num_tc; i++) {
+ ret = hclge_tm_qs_schd_mode_cfg(hdev, vport->qs_offset + i);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static int hclge_tm_lvl34_schd_mode_cfg(struct hclge_dev *hdev)
+{
+ struct hclge_vport *vport = hdev->vport;
+ int ret;
+ u8 i;
+
+ if (hdev->tx_sch_mode == HCLGE_FLAG_TC_BASE_SCH_MODE) {
+ for (i = 0; i < hdev->tm_info.num_tc; i++) {
+ ret = hclge_tm_pri_schd_mode_cfg(hdev, i);
+ if (ret)
+ return ret;
+
+ ret = hclge_tm_qs_schd_mode_cfg(hdev, i);
+ if (ret)
+ return ret;
+ }
+ } else {
+ for (i = 0; i < hdev->num_alloc_vport; i++) {
+ ret = hclge_tm_schd_mode_vnet_base_cfg(vport);
+ if (ret)
+ return ret;
+
+ vport++;
+ }
+ }
+
+ return 0;
+}
+
+static int hclge_tm_schd_mode_hw(struct hclge_dev *hdev)
+{
+ int ret;
+
+ ret = hclge_tm_lvl2_schd_mode_cfg(hdev);
+ if (ret)
+ return ret;
+
+ return hclge_tm_lvl34_schd_mode_cfg(hdev);
+}
+
+static int hclge_tm_schd_setup_hw(struct hclge_dev *hdev)
+{
+ int ret;
+
+ /* Cfg tm mapping */
+ ret = hclge_tm_map_cfg(hdev);
+ if (ret)
+ return ret;
+
+ /* Cfg tm shaper */
+ ret = hclge_tm_shaper_cfg(hdev);
+ if (ret)
+ return ret;
+
+ /* Cfg dwrr */
+ ret = hclge_tm_dwrr_cfg(hdev);
+ if (ret)
+ return ret;
+
+ /* Cfg schd mode for each level schd */
+ return hclge_tm_schd_mode_hw(hdev);
+}
+
+int hclge_pause_setup_hw(struct hclge_dev *hdev)
+{
+ bool en = hdev->tm_info.fc_mode != HCLGE_FC_PFC;
+ int ret;
+ u8 i;
+
+ ret = hclge_mac_pause_en_cfg(hdev, en, en);
+ if (ret)
+ return ret;
+
+ for (i = 0; i < hdev->tm_info.num_tc; i++) {
+ ret = hclge_tm_qs_bp_cfg(hdev, i);
+ if (ret)
+ return ret;
+ }
+
+ return hclge_up_to_tc_map(hdev);
+}
+
+int hclge_tm_init_hw(struct hclge_dev *hdev)
+{
+ int ret;
+
+ if ((hdev->tx_sch_mode != HCLGE_FLAG_TC_BASE_SCH_MODE) &&
+ (hdev->tx_sch_mode != HCLGE_FLAG_VNET_BASE_SCH_MODE))
+ return -ENOTSUPP;
+
+ ret = hclge_tm_schd_setup_hw(hdev);
+ if (ret)
+ return ret;
+
+ ret = hclge_pause_setup_hw(hdev);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+int hclge_tm_schd_init(struct hclge_dev *hdev)
+{
+ int ret = hclge_tm_schd_info_init(hdev);
+
+ if (ret)
+ return ret;
+
+ return hclge_tm_init_hw(hdev);
+}
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.h
new file mode 100644
index 0000000..7e67337
--- /dev/null
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.h
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2016~2017 Hisilicon Limited.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __HCLGE_TM_H
+#define __HCLGE_TM_H
+
+#include <linux/types.h>
+
+/* MAC Pause */
+#define HCLGE_TX_MAC_PAUSE_EN_MSK BIT(0)
+#define HCLGE_RX_MAC_PAUSE_EN_MSK BIT(1)
+
+#define HCLGE_TM_PORT_BASE_MODE_MSK BIT(0)
+
+/* SP or DWRR */
+#define HCLGE_TM_TX_SCHD_DWRR_MSK BIT(0)
+#define HCLGE_TM_TX_SCHD_SP_MSK (0xFE)
+
+struct hclge_pg_to_pri_link_cmd {
+ u8 pg_id;
+ u8 rsvd1[3];
+ u8 pri_bit_map;
+};
+
+struct hclge_qs_to_pri_link_cmd {
+ __le16 qs_id;
+ __le16 rsvd;
+ u8 priority;
+#define HCLGE_TM_QS_PRI_LINK_VLD_MSK BIT(0)
+ u8 link_vld;
+};
+
+struct hclge_nq_to_qs_link_cmd {
+ __le16 nq_id;
+ __le16 rsvd;
+#define HCLGE_TM_Q_QS_LINK_VLD_MSK BIT(10)
+ __le16 qset_id;
+};
+
+struct hclge_pg_weight_cmd {
+ u8 pg_id;
+ u8 dwrr;
+};
+
+struct hclge_priority_weight_cmd {
+ u8 pri_id;
+ u8 dwrr;
+};
+
+struct hclge_qs_weight_cmd {
+ __le16 qs_id;
+ u8 dwrr;
+};
+
+#define HCLGE_TM_SHAP_IR_B_MSK GENMASK(7, 0)
+#define HCLGE_TM_SHAP_IR_B_LSH 0
+#define HCLGE_TM_SHAP_IR_U_MSK GENMASK(11, 8)
+#define HCLGE_TM_SHAP_IR_U_LSH 8
+#define HCLGE_TM_SHAP_IR_S_MSK GENMASK(15, 12)
+#define HCLGE_TM_SHAP_IR_S_LSH 12
+#define HCLGE_TM_SHAP_BS_B_MSK GENMASK(20, 16)
+#define HCLGE_TM_SHAP_BS_B_LSH 16
+#define HCLGE_TM_SHAP_BS_S_MSK GENMASK(25, 21)
+#define HCLGE_TM_SHAP_BS_S_LSH 21
+
+enum hclge_shap_bucket {
+ HCLGE_TM_SHAP_C_BUCKET = 0,
+ HCLGE_TM_SHAP_P_BUCKET,
+};
+
+struct hclge_pri_shapping_cmd {
+ u8 pri_id;
+ u8 rsvd[3];
+ __le32 pri_shapping_para;
+};
+
+struct hclge_pg_shapping_cmd {
+ u8 pg_id;
+ u8 rsvd[3];
+ __le32 pg_shapping_para;
+};
+
+struct hclge_bp_to_qs_map_cmd {
+ u8 tc_id;
+ u8 rsvd[2];
+ u8 qs_group_id;
+ __le32 qs_bit_map;
+ u32 rsvd1;
+};
+
+#define hclge_tm_set_feild(dest, string, val) \
+ hnae_set_field((dest), (HCLGE_TM_SHAP_##string##_MSK), \
+ (HCLGE_TM_SHAP_##string##_LSH), val)
+#define hclge_tm_get_feild(src, string) \
+ hnae_get_field((src), (HCLGE_TM_SHAP_##string##_MSK), \
+ (HCLGE_TM_SHAP_##string##_LSH))
+
+int hclge_tm_schd_init(struct hclge_dev *hdev);
+int hclge_pause_setup_hw(struct hclge_dev *hdev);
+#endif
--
2.7.4
^ permalink raw reply related
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