* [PATCH 2/2] net: Replace dev_kfree_skb_any by dev_consume_skb_any
From: Huang Zijiang @ 2019-02-14 6:42 UTC (permalink / raw)
To: linux-net-drivers
Cc: ecree, bkenward, davem, netdev, linux-kernel, wang.yi59,
Huang Zijiang
The skb should be freed by dev_consume_skb_any() efx_tx_tso_fallback()
when skb is still used. The skb is be replaced by segments, so the
original skb should be consumed(not drop).
Signed-off-by: Huang Zijiang <huang.zijiang@zte.com.cn>
---
drivers/net/ethernet/sfc/tx.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/sfc/tx.c b/drivers/net/ethernet/sfc/tx.c
index c3ad564..ed551f0 100644
--- a/drivers/net/ethernet/sfc/tx.c
+++ b/drivers/net/ethernet/sfc/tx.c
@@ -471,7 +471,7 @@ static int efx_tx_tso_fallback(struct efx_tx_queue *tx_queue,
if (IS_ERR(segments))
return PTR_ERR(segments);
- dev_kfree_skb_any(skb);
+ dev_consume_skb_any(skb);
skb = segments;
while (skb) {
--
1.8.3.1
^ permalink raw reply related
* [PATCH 6/8] dt-bindings: net: stmmac: add syscfg clock property
From: Christophe Roullier @ 2019-02-14 6:46 UTC (permalink / raw)
To: robh, davem, joabreu, mark.rutland, mcoquelin.stm32,
alexandre.torgue, peppe.cavallaro
Cc: linux-stm32, linux-kernel, devicetree, linux-arm-kernel, netdev,
christophe.roullier, andrew
In-Reply-To: <1550126763-22669-1-git-send-email-christophe.roullier@st.com>
Need syscfg clock for MCU family in case bootloader does not
activate it.
Signed-off-by: Christophe Roullier <christophe.roullier@st.com>
---
Documentation/devicetree/bindings/net/stm32-dwmac.txt | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/Documentation/devicetree/bindings/net/stm32-dwmac.txt b/Documentation/devicetree/bindings/net/stm32-dwmac.txt
index f42dc68..524f8a0 100644
--- a/Documentation/devicetree/bindings/net/stm32-dwmac.txt
+++ b/Documentation/devicetree/bindings/net/stm32-dwmac.txt
@@ -14,8 +14,8 @@ Required properties:
- clock-names: Should be "stmmaceth" for the host clock.
Should be "mac-clk-tx" for the MAC TX clock.
Should be "mac-clk-rx" for the MAC RX clock.
- For MPU family need to add also "ethstp" for power mode clock and,
- "syscfg-clk" for SYSCFG clock.
+ Should be "syscfg-clk" for the SYSCFG clock.
+ For MPU family need to add also "ethstp" for power mode clock
- interrupt-names: Should contain a list of interrupt names corresponding to
the interrupts in the interrupts property, if available.
Should be "macirq" for the main MAC IRQ
--
2.7.4
^ permalink raw reply related
* [PATCH 7/8] ARM: dts: stm32: Add Ethernet support on stm32h7 SOC and activate it for eval and disco boards
From: Christophe Roullier @ 2019-02-14 6:46 UTC (permalink / raw)
To: robh, davem, joabreu, mark.rutland, mcoquelin.stm32,
alexandre.torgue, peppe.cavallaro
Cc: linux-stm32, linux-kernel, devicetree, linux-arm-kernel, netdev,
christophe.roullier, andrew
In-Reply-To: <1550126763-22669-1-git-send-email-christophe.roullier@st.com>
Synopsys GMAC 4.10 is used. And Phy mode for eval and disco is RMII
with PHY SMSC LAN8742
Signed-off-by: Christophe Roullier <christophe.roullier@st.com>
---
arch/arm/boot/dts/stm32h743-pinctrl.dtsi | 15 +++++++++++++++
arch/arm/boot/dts/stm32h743.dtsi | 19 +++++++++++++++++++
arch/arm/boot/dts/stm32h743i-disco.dts | 17 +++++++++++++++++
arch/arm/boot/dts/stm32h743i-eval.dts | 17 +++++++++++++++++
4 files changed, 68 insertions(+)
diff --git a/arch/arm/boot/dts/stm32h743-pinctrl.dtsi b/arch/arm/boot/dts/stm32h743-pinctrl.dtsi
index 24be8e6..980b276 100644
--- a/arch/arm/boot/dts/stm32h743-pinctrl.dtsi
+++ b/arch/arm/boot/dts/stm32h743-pinctrl.dtsi
@@ -173,6 +173,21 @@
};
};
+ ethernet_rmii: rmii@0 {
+ pins {
+ pinmux = <STM32_PINMUX('G', 11, AF11)>,
+ <STM32_PINMUX('G', 13, AF11)>,
+ <STM32_PINMUX('G', 12, AF11)>,
+ <STM32_PINMUX('C', 4, AF11)>,
+ <STM32_PINMUX('C', 5, AF11)>,
+ <STM32_PINMUX('A', 7, AF11)>,
+ <STM32_PINMUX('C', 1, AF11)>,
+ <STM32_PINMUX('A', 2, AF11)>,
+ <STM32_PINMUX('A', 1, AF11)>;
+ slew-rate = <2>;
+ };
+ };
+
usart1_pins: usart1@0 {
pins1 {
pinmux = <STM32_PINMUX('B', 14, AF4)>; /* USART1_TX */
diff --git a/arch/arm/boot/dts/stm32h743.dtsi b/arch/arm/boot/dts/stm32h743.dtsi
index cbdd69c..f6384af 100644
--- a/arch/arm/boot/dts/stm32h743.dtsi
+++ b/arch/arm/boot/dts/stm32h743.dtsi
@@ -511,6 +511,25 @@
status = "disabled";
};
};
+
+ syscfg: system-config@58000400 {
+ compatible = "syscon";
+ reg = <0x58000400 0x400>;
+ };
+
+ mac: ethernet@40028000 {
+ compatible = "st,stm32-dwmac", "snps,dwmac-4.10a";
+ reg = <0x40028000 0x8000>;
+ reg-names = "stmmaceth";
+ interrupts = <61>;
+ interrupt-names = "macirq";
+ clock-names = "stmmaceth", "mac-clk-tx", "mac-clk-rx",
+ "syscfg-clk";
+ clocks = <&rcc ETH1MAC_CK>, <&rcc ETH1TX_CK>, <&rcc ETH1RX_CK>, <&rcc SYSCFG_CK>;
+ st,syscon = <&syscfg 0x4>;
+ snps,pbl = <8>;
+ status = "disabled";
+ };
};
};
diff --git a/arch/arm/boot/dts/stm32h743i-disco.dts b/arch/arm/boot/dts/stm32h743i-disco.dts
index 45e088c..0f738d0 100644
--- a/arch/arm/boot/dts/stm32h743i-disco.dts
+++ b/arch/arm/boot/dts/stm32h743i-disco.dts
@@ -66,6 +66,23 @@
clock-frequency = <25000000>;
};
+&mac {
+ status = "okay";
+ pinctrl-0 = <ðernet_rmii>;
+ pinctrl-names = "default";
+ phy-mode = "rmii";
+ phy-handle = <&phy1>;
+
+ mdio0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "snps,dwmac-mdio";
+ phy1: ethernet-phy@1 {
+ reg = <0>;
+ };
+ };
+};
+
&usart2 {
pinctrl-0 = <&usart2_pins>;
pinctrl-names = "default";
diff --git a/arch/arm/boot/dts/stm32h743i-eval.dts b/arch/arm/boot/dts/stm32h743i-eval.dts
index 3f8e0c4..44997ba 100644
--- a/arch/arm/boot/dts/stm32h743i-eval.dts
+++ b/arch/arm/boot/dts/stm32h743i-eval.dts
@@ -104,6 +104,23 @@
status = "okay";
};
+&mac {
+ status = "okay";
+ pinctrl-0 = <ðernet_rmii>;
+ pinctrl-names = "default";
+ phy-mode = "rmii";
+ phy-handle = <&phy1>;
+
+ mdio0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "snps,dwmac-mdio";
+ phy1: ethernet-phy@1 {
+ reg = <0>;
+ };
+ };
+};
+
&usart1 {
pinctrl-0 = <&usart1_pins>;
pinctrl-names = "default";
--
2.7.4
^ permalink raw reply related
* [PATCH 5/8] net: ethernet: stmmac: update to be compatible with MCU family (stm32f4, stm32h7)
From: Christophe Roullier @ 2019-02-14 6:46 UTC (permalink / raw)
To: robh, davem, joabreu, mark.rutland, mcoquelin.stm32,
alexandre.torgue, peppe.cavallaro
Cc: linux-stm32, linux-kernel, devicetree, linux-arm-kernel, netdev,
christophe.roullier, andrew
In-Reply-To: <1550126763-22669-1-git-send-email-christophe.roullier@st.com>
Update glue codes to be compatible with MCU family.
Signed-off-by: Christophe Roullier <christophe.roullier@st.com>
---
drivers/net/ethernet/stmicro/stmmac/dwmac-stm32.c | 51 ++++++++++++++++++-----
1 file changed, 41 insertions(+), 10 deletions(-)
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-stm32.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-stm32.c
index cee59e8..20a2daa 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-stm32.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-stm32.c
@@ -6,7 +6,6 @@
* License terms: GNU General Public License (GPL), version 2
*
*/
-
#include <linux/clk.h>
#include <linux/kernel.h>
#include <linux/mfd/syscon.h>
@@ -119,12 +118,6 @@ static int stm32_dwmac_init(struct plat_stmmacenet_data *plat_dat)
struct stm32_dwmac *dwmac = plat_dat->bsp_priv;
int ret;
- if (dwmac->ops->set_mode) {
- ret = dwmac->ops->set_mode(plat_dat);
- if (ret)
- return ret;
- }
-
ret = clk_prepare_enable(dwmac->clk_tx);
if (ret)
return ret;
@@ -139,13 +132,26 @@ static int stm32_dwmac_init(struct plat_stmmacenet_data *plat_dat)
if (dwmac->ops->clk_prepare) {
ret = dwmac->ops->clk_prepare(dwmac, true);
+ if (ret)
+ goto err_clk_disable;
+ }
+
+ if (dwmac->ops->set_mode) {
+ ret = dwmac->ops->set_mode(plat_dat);
if (ret) {
- clk_disable_unprepare(dwmac->clk_rx);
- clk_disable_unprepare(dwmac->clk_tx);
+ if (dwmac->ops->clk_prepare)
+ dwmac->ops->clk_prepare(dwmac, false);
+ goto err_clk_disable;
}
}
return ret;
+
+err_clk_disable:
+ clk_disable_unprepare(dwmac->clk_rx);
+ clk_disable_unprepare(dwmac->clk_tx);
+
+ return ret;
}
static int stm32mp1_clk_prepare(struct stm32_dwmac *dwmac, bool prepare)
@@ -240,7 +246,19 @@ static int stm32mcu_set_mode(struct plat_stmmacenet_data *plat_dat)
}
return regmap_update_bits(dwmac->regmap, reg,
- dwmac->ops->syscfg_eth_mask, val);
+ dwmac->ops->syscfg_eth_mask, val << 23);
+}
+
+static int stm32mcu_clk_prepare(struct stm32_dwmac *dwmac, bool prepare)
+{
+ int ret = 0;
+
+ if (prepare)
+ ret = clk_prepare_enable(dwmac->syscfg_clk);
+ else
+ clk_disable_unprepare(dwmac->syscfg_clk);
+
+ return ret;
}
static void stm32_dwmac_clk_disable(struct stm32_dwmac *dwmac)
@@ -347,6 +365,17 @@ static int stm32mp1_parse_data(struct stm32_dwmac *dwmac,
return err;
}
+static int stm32mcu_parse_data(struct stm32_dwmac *dwmac,
+ struct device *dev)
+{
+ /* Clock for sysconfig */
+ dwmac->syscfg_clk = devm_clk_get(dev, "syscfg-clk");
+ if (IS_ERR(dwmac->syscfg_clk))
+ dev_warn(dev, "No syscfg clock provided...\n");
+
+ return 0;
+}
+
static int stm32_dwmac_probe(struct platform_device *pdev)
{
struct plat_stmmacenet_data *plat_dat;
@@ -493,7 +522,9 @@ static SIMPLE_DEV_PM_OPS(stm32_dwmac_pm_ops,
static struct stm32_ops stm32mcu_dwmac_data = {
.set_mode = stm32mcu_set_mode,
+ .clk_prepare = stm32mcu_clk_prepare,
.suspend = stm32mcu_suspend,
+ .parse_data = stm32mcu_parse_data,
.syscfg_eth_mask = SYSCFG_MCU_ETH_MASK
};
--
2.7.4
^ permalink raw reply related
* [PATCH 8/8] ARM: dts: stm32: add syscfg clock support for Ethernet on STM32F429 SoC
From: Christophe Roullier @ 2019-02-14 6:46 UTC (permalink / raw)
To: robh, davem, joabreu, mark.rutland, mcoquelin.stm32,
alexandre.torgue, peppe.cavallaro
Cc: linux-stm32, linux-kernel, devicetree, linux-arm-kernel, netdev,
christophe.roullier, andrew
In-Reply-To: <1550126763-22669-1-git-send-email-christophe.roullier@st.com>
This patch add syscfg clock support for Ethernet of the STM32F429 SoC.
Needed if bootloader do not manage it.
Signed-off-by: Christophe Roullier <christophe.roullier@st.com>
---
arch/arm/boot/dts/stm32f429.dtsi | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/arch/arm/boot/dts/stm32f429.dtsi b/arch/arm/boot/dts/stm32f429.dtsi
index 8d6f028..6f78346 100644
--- a/arch/arm/boot/dts/stm32f429.dtsi
+++ b/arch/arm/boot/dts/stm32f429.dtsi
@@ -657,10 +657,12 @@
reg-names = "stmmaceth";
interrupts = <61>;
interrupt-names = "macirq";
- clock-names = "stmmaceth", "mac-clk-tx", "mac-clk-rx";
+ clock-names = "stmmaceth", "mac-clk-tx", "mac-clk-rx",
+ "syscfg-clk";
clocks = <&rcc 0 STM32F4_AHB1_CLOCK(ETHMAC)>,
<&rcc 0 STM32F4_AHB1_CLOCK(ETHMACTX)>,
- <&rcc 0 STM32F4_AHB1_CLOCK(ETHMACRX)>;
+ <&rcc 0 STM32F4_AHB1_CLOCK(ETHMACRX)>,
+ <&rcc 0 STM32F4_APB2_CLOCK(SYSCFG)>;
st,syscon = <&syscfg 0x4>;
snps,pbl = <8>;
snps,mixed-burst;
--
2.7.4
^ permalink raw reply related
* [PATCH 2/8] net: ethernet: stmmac: update to support all PHY config for stm32mp157c.
From: Christophe Roullier @ 2019-02-14 6:45 UTC (permalink / raw)
To: robh, davem, joabreu, mark.rutland, mcoquelin.stm32,
alexandre.torgue, peppe.cavallaro
Cc: linux-stm32, linux-kernel, devicetree, linux-arm-kernel, netdev,
christophe.roullier, andrew
In-Reply-To: <1550126763-22669-1-git-send-email-christophe.roullier@st.com>
Update glue codes to support all PHY config on stm32mp157c
PHY_MODE (MII,GMII, RMII, RGMII) and in normal, PHY wo crystal (25Mhz),
PHY wo crystal (50Mhz), No 125Mhz from PHY config.
Signed-off-by: Christophe Roullier <christophe.roullier@st.com>
---
drivers/net/ethernet/stmicro/stmmac/dwmac-stm32.c | 102 +++++++++++++++++-----
1 file changed, 82 insertions(+), 20 deletions(-)
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-stm32.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-stm32.c
index d1cf145..cee59e8 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-stm32.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-stm32.c
@@ -25,9 +25,24 @@
#define SYSCFG_MCU_ETH_MASK BIT(23)
#define SYSCFG_MP1_ETH_MASK GENMASK(23, 16)
+#define SYSCFG_PMCCLRR_OFFSET 0x40
#define SYSCFG_PMCR_ETH_CLK_SEL BIT(16)
#define SYSCFG_PMCR_ETH_REF_CLK_SEL BIT(17)
+
+/* Ethernet PHY interface selection in register SYSCFG Configuration
+ *------------------------------------------
+ * src |BIT(23)| BIT(22)| BIT(21)|BIT(20)|
+ *------------------------------------------
+ * MII | 0 | 0 | 0 | 1 |
+ *------------------------------------------
+ * GMII | 0 | 0 | 0 | 0 |
+ *------------------------------------------
+ * RGMII | 0 | 0 | 1 | n/a |
+ *------------------------------------------
+ * RMII | 1 | 0 | 0 | n/a |
+ *------------------------------------------
+ */
#define SYSCFG_PMCR_ETH_SEL_MII BIT(20)
#define SYSCFG_PMCR_ETH_SEL_RGMII BIT(21)
#define SYSCFG_PMCR_ETH_SEL_RMII BIT(23)
@@ -35,15 +50,54 @@
#define SYSCFG_MCU_ETH_SEL_MII 0
#define SYSCFG_MCU_ETH_SEL_RMII 1
+/* STM32MP1 register definitions
+ *
+ * Below table summarizes the clock requirement and clock sources for
+ * supported phy interface modes.
+ * __________________________________________________________________________
+ *|PHY_MODE | Normal | PHY wo crystal| PHY wo crystal |No 125Mhz from PHY|
+ *| | | 25MHz | 50MHz | |
+ * ---------------------------------------------------------------------------
+ *| MII | - | eth-ck | n/a | n/a |
+ *| | | | | |
+ * ---------------------------------------------------------------------------
+ *| GMII | - | eth-ck | n/a | n/a |
+ *| | | | | |
+ * ---------------------------------------------------------------------------
+ *| RGMII | - | eth-ck | n/a | eth-ck (no pin) |
+ *| | | | | st,eth_clk_sel |
+ * ---------------------------------------------------------------------------
+ *| RMII | - | eth-ck | eth-ck | n/a |
+ *| | | | st,eth_ref_clk_sel | |
+ * ---------------------------------------------------------------------------
+ *
+ * BIT(17) : set this bit in RMII mode when you have PHY without crystal 50MHz
+ * BIT(16) : set this bit in GMII/RGMII PHY when you do not want use 125Mhz
+ * from PHY
+ *-----------------------------------------------------
+ * src | BIT(17) | BIT(16) |
+ *-----------------------------------------------------
+ * MII | n/a | n/a |
+ *-----------------------------------------------------
+ * GMII | n/a | st,eth_clk_sel |
+ *-----------------------------------------------------
+ * RGMII | n/a | st,eth_clk_sel |
+ *-----------------------------------------------------
+ * RMII | st,eth_ref_clk_sel | n/a |
+ *-----------------------------------------------------
+ *
+ */
+
struct stm32_dwmac {
struct clk *clk_tx;
struct clk *clk_rx;
struct clk *clk_eth_ck;
struct clk *clk_ethstp;
struct clk *syscfg_clk;
- bool int_phyclk; /* Clock from RCC to drive PHY */
+ int eth_clk_sel_reg;
+ int eth_ref_clk_sel_reg;
int irq_pwr_wakeup;
- u32 mode_reg; /* MAC glue-logic mode register */
+ u32 mode_reg; /* MAC glue-logic mode register */
struct regmap *regmap;
u32 speed;
const struct stm32_ops *ops;
@@ -103,7 +157,7 @@ static int stm32mp1_clk_prepare(struct stm32_dwmac *dwmac, bool prepare)
if (ret)
return ret;
- if (dwmac->int_phyclk) {
+ if (dwmac->clk_eth_ck) {
ret = clk_prepare_enable(dwmac->clk_eth_ck);
if (ret) {
clk_disable_unprepare(dwmac->syscfg_clk);
@@ -112,7 +166,7 @@ static int stm32mp1_clk_prepare(struct stm32_dwmac *dwmac, bool prepare)
}
} else {
clk_disable_unprepare(dwmac->syscfg_clk);
- if (dwmac->int_phyclk)
+ if (dwmac->clk_eth_ck)
clk_disable_unprepare(dwmac->clk_eth_ck);
}
return ret;
@@ -122,7 +176,7 @@ static int stm32mp1_set_mode(struct plat_stmmacenet_data *plat_dat)
{
struct stm32_dwmac *dwmac = plat_dat->bsp_priv;
u32 reg = dwmac->mode_reg;
- int val;
+ int val, ret;
switch (plat_dat->interface) {
case PHY_INTERFACE_MODE_MII:
@@ -131,19 +185,19 @@ static int stm32mp1_set_mode(struct plat_stmmacenet_data *plat_dat)
break;
case PHY_INTERFACE_MODE_GMII:
val = SYSCFG_PMCR_ETH_SEL_GMII;
- if (dwmac->int_phyclk)
+ if (dwmac->eth_clk_sel_reg)
val |= SYSCFG_PMCR_ETH_CLK_SEL;
pr_debug("SYSCFG init : PHY_INTERFACE_MODE_GMII\n");
break;
case PHY_INTERFACE_MODE_RMII:
val = SYSCFG_PMCR_ETH_SEL_RMII;
- if (dwmac->int_phyclk)
+ if (dwmac->eth_ref_clk_sel_reg)
val |= SYSCFG_PMCR_ETH_REF_CLK_SEL;
pr_debug("SYSCFG init : PHY_INTERFACE_MODE_RMII\n");
break;
case PHY_INTERFACE_MODE_RGMII:
val = SYSCFG_PMCR_ETH_SEL_RGMII;
- if (dwmac->int_phyclk)
+ if (dwmac->eth_clk_sel_reg)
val |= SYSCFG_PMCR_ETH_CLK_SEL;
pr_debug("SYSCFG init : PHY_INTERFACE_MODE_RGMII\n");
break;
@@ -154,6 +208,11 @@ static int stm32mp1_set_mode(struct plat_stmmacenet_data *plat_dat)
return -EINVAL;
}
+ /* Need to update PMCCLRR (clear register) */
+ ret = regmap_write(dwmac->regmap, reg + SYSCFG_PMCCLRR_OFFSET,
+ dwmac->ops->syscfg_eth_mask);
+
+ /* Update PMCSETR (set register) */
return regmap_update_bits(dwmac->regmap, reg,
dwmac->ops->syscfg_eth_mask, val);
}
@@ -237,22 +296,25 @@ static int stm32mp1_parse_data(struct stm32_dwmac *dwmac,
struct device_node *np = dev->of_node;
int err = 0;
- dwmac->int_phyclk = of_property_read_bool(np, "st,int-phyclk");
+ /* Gigabit Ethernet 125MHz clock selection. */
+ dwmac->eth_clk_sel_reg = of_property_read_bool(np, "st,eth_clk_sel");
- /* Check if internal clk from RCC selected */
- if (dwmac->int_phyclk) {
- /* Get ETH_CLK clocks */
- dwmac->clk_eth_ck = devm_clk_get(dev, "eth-ck");
- if (IS_ERR(dwmac->clk_eth_ck)) {
- dev_err(dev, "No ETH CK clock provided...\n");
- return PTR_ERR(dwmac->clk_eth_ck);
- }
+ /* Ethernet 50Mhz RMII clock selection */
+ dwmac->eth_ref_clk_sel_reg =
+ of_property_read_bool(np, "st,eth_ref_clk_sel");
+
+ /* Get ETH_CLK clocks */
+ dwmac->clk_eth_ck = devm_clk_get(dev, "eth-ck");
+ if (IS_ERR(dwmac->clk_eth_ck)) {
+ dev_warn(dev, "No phy clock provided...\n");
+ dwmac->clk_eth_ck = NULL;
}
/* Clock used for low power mode */
dwmac->clk_ethstp = devm_clk_get(dev, "ethstp");
if (IS_ERR(dwmac->clk_ethstp)) {
- dev_err(dev, "No ETH peripheral clock provided for CStop mode ...\n");
+ dev_err(dev,
+ "No ETH peripheral clock provided for CStop mode ...\n");
return PTR_ERR(dwmac->clk_ethstp);
}
@@ -268,7 +330,7 @@ static int stm32mp1_parse_data(struct stm32_dwmac *dwmac,
*/
dwmac->irq_pwr_wakeup = platform_get_irq_byname(pdev,
"stm32_pwr_wakeup");
- if (!dwmac->int_phyclk && dwmac->irq_pwr_wakeup >= 0) {
+ if (!dwmac->clk_eth_ck && dwmac->irq_pwr_wakeup >= 0) {
err = device_init_wakeup(&pdev->dev, true);
if (err) {
dev_err(&pdev->dev, "Failed to init wake up irq\n");
@@ -370,7 +432,7 @@ static int stm32mp1_suspend(struct stm32_dwmac *dwmac)
clk_disable_unprepare(dwmac->clk_tx);
clk_disable_unprepare(dwmac->syscfg_clk);
- if (dwmac->int_phyclk)
+ if (dwmac->clk_eth_ck)
clk_disable_unprepare(dwmac->clk_eth_ck);
return ret;
--
2.7.4
^ permalink raw reply related
* [PATCH 1/8] net: ethernet: stmmac: manage Ethernet WoL for stm32mp157c.
From: Christophe Roullier @ 2019-02-14 6:45 UTC (permalink / raw)
To: robh, davem, joabreu, mark.rutland, mcoquelin.stm32,
alexandre.torgue, peppe.cavallaro
Cc: linux-stm32, linux-kernel, devicetree, linux-arm-kernel, netdev,
christophe.roullier, andrew
In-Reply-To: <1550126763-22669-1-git-send-email-christophe.roullier@st.com>
Add glue codes to support magic packet on stm32mp157c
Signed-off-by: Christophe Roullier <christophe.roullier@st.com>
---
drivers/net/ethernet/stmicro/stmmac/dwmac-stm32.c | 30 ++++++++++++++++++++++-
1 file changed, 29 insertions(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-stm32.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-stm32.c
index 7e2e79d..d1cf145 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-stm32.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-stm32.c
@@ -42,6 +42,7 @@ struct stm32_dwmac {
struct clk *clk_ethstp;
struct clk *syscfg_clk;
bool int_phyclk; /* Clock from RCC to drive PHY */
+ int irq_pwr_wakeup;
u32 mode_reg; /* MAC glue-logic mode register */
struct regmap *regmap;
u32 speed;
@@ -232,7 +233,9 @@ static int stm32_dwmac_parse_data(struct stm32_dwmac *dwmac,
static int stm32mp1_parse_data(struct stm32_dwmac *dwmac,
struct device *dev)
{
+ struct platform_device *pdev = to_platform_device(dev);
struct device_node *np = dev->of_node;
+ int err = 0;
dwmac->int_phyclk = of_property_read_bool(np, "st,int-phyclk");
@@ -260,7 +263,26 @@ static int stm32mp1_parse_data(struct stm32_dwmac *dwmac,
return PTR_ERR(dwmac->syscfg_clk);
}
- return 0;
+ /* Get IRQ information early to have an ability to ask for deferred
+ * probe if needed before we went too far with resource allocation.
+ */
+ dwmac->irq_pwr_wakeup = platform_get_irq_byname(pdev,
+ "stm32_pwr_wakeup");
+ if (!dwmac->int_phyclk && dwmac->irq_pwr_wakeup >= 0) {
+ err = device_init_wakeup(&pdev->dev, true);
+ if (err) {
+ dev_err(&pdev->dev, "Failed to init wake up irq\n");
+ return err;
+ }
+ err = dev_pm_set_dedicated_wake_irq(&pdev->dev,
+ dwmac->irq_pwr_wakeup);
+ if (err) {
+ dev_err(&pdev->dev, "Failed to set wake up irq\n");
+ device_init_wakeup(&pdev->dev, false);
+ }
+ device_set_wakeup_enable(&pdev->dev, false);
+ }
+ return err;
}
static int stm32_dwmac_probe(struct platform_device *pdev)
@@ -326,9 +348,15 @@ static int stm32_dwmac_remove(struct platform_device *pdev)
struct net_device *ndev = platform_get_drvdata(pdev);
struct stmmac_priv *priv = netdev_priv(ndev);
int ret = stmmac_dvr_remove(&pdev->dev);
+ struct stm32_dwmac *dwmac = priv->plat->bsp_priv;
stm32_dwmac_clk_disable(priv->plat->bsp_priv);
+ if (dwmac->irq_pwr_wakeup >= 0) {
+ dev_pm_clear_wake_irq(&pdev->dev);
+ device_init_wakeup(&pdev->dev, false);
+ }
+
return ret;
}
--
2.7.4
^ permalink raw reply related
* [PATCH 3/8] dt-bindings: net: stmmac: add phys config properties
From: Christophe Roullier @ 2019-02-14 6:45 UTC (permalink / raw)
To: robh, davem, joabreu, mark.rutland, mcoquelin.stm32,
alexandre.torgue, peppe.cavallaro
Cc: linux-stm32, linux-kernel, devicetree, linux-arm-kernel, netdev,
christophe.roullier, andrew
In-Reply-To: <1550126763-22669-1-git-send-email-christophe.roullier@st.com>
Add properties to support all Phy config
PHY_MODE (MII,GMII, RMII, RGMII) and in normal, PHY wo crystal (25Mhz),
PHY wo crystal (50Mhz), No 125Mhz from PHY config.
Signed-off-by: Christophe Roullier <christophe.roullier@st.com>
---
Documentation/devicetree/bindings/net/stm32-dwmac.txt | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/Documentation/devicetree/bindings/net/stm32-dwmac.txt b/Documentation/devicetree/bindings/net/stm32-dwmac.txt
index 1341012..f42dc68 100644
--- a/Documentation/devicetree/bindings/net/stm32-dwmac.txt
+++ b/Documentation/devicetree/bindings/net/stm32-dwmac.txt
@@ -24,9 +24,9 @@ Required properties:
encompases the glue register, and the offset of the control register.
Optional properties:
-- clock-names: For MPU family "mac-clk-ck" for PHY without quartz
-- st,int-phyclk (boolean) : valid only where PHY do not have quartz and need to be clock
- by RCC
+- clock-names: For MPU family "eth-ck" for PHY without quartz
+- st,eth_clk_sel (boolean) : set this property in RGMII PHY when you do not want use 125Mhz
+- st,eth_ref_clk_sel (boolean) : set this property in RMII mode when you have PHY without crystal 50MHz
Example:
--
2.7.4
^ permalink raw reply related
* [PATCH 4/8] net: ethernet: stmmac: add management of clk_csr property
From: Christophe Roullier @ 2019-02-14 6:45 UTC (permalink / raw)
To: robh, davem, joabreu, mark.rutland, mcoquelin.stm32,
alexandre.torgue, peppe.cavallaro
Cc: linux-stm32, linux-kernel, devicetree, linux-arm-kernel, netdev,
christophe.roullier, andrew
In-Reply-To: <1550126763-22669-1-git-send-email-christophe.roullier@st.com>
In Documentation stmmac.txt there is possibility to
fixed CSR Clock range selection with property clk_csr.
This patch add the management of this property
For example to use it, add in your ethernet node DT:
clk_csr = <3>;
Signed-off-by: Christophe Roullier <christophe.roullier@st.com>
---
drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
index 2b800ce..3031f2b 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
@@ -408,6 +408,9 @@ stmmac_probe_config_dt(struct platform_device *pdev, const char **mac)
/* Default to phy auto-detection */
plat->phy_addr = -1;
+ /* Get clk_csr from device tree */
+ of_property_read_u32(np, "clk_csr", &plat->clk_csr);
+
/* "snps,phy-addr" is not a standard property. Mark it as deprecated
* and warn of its use. Remove this when phy node support is added.
*/
--
2.7.4
^ permalink raw reply related
* [PATCH 0/8] stmmac: add some fixes for stm32
From: Christophe Roullier @ 2019-02-14 6:45 UTC (permalink / raw)
To: robh, davem, joabreu, mark.rutland, mcoquelin.stm32,
alexandre.torgue, peppe.cavallaro
Cc: linux-stm32, linux-kernel, devicetree, linux-arm-kernel, netdev,
christophe.roullier, andrew
For common stmmac:
- Add support to set CSR Clock range selection in DT
For stm32mpu:
- Glue codes to support magic packet
- Glue codes to support all PHY config :
PHY_MODE (MII,GMII, RMII, RGMII) and in normal,
PHY wo crystal (25Mhz),
PHY wo crystal (50Mhz), No 125Mhz from PHY config
For stm32mcu:
- Add Ethernet support for stm32h7
- Add syscfg clk support for stm32f4
Christophe Roullier (8):
net: ethernet: stmmac: manage Ethernet WoL for stm32mp157c.
net: ethernet: stmmac: update to support all PHY config for
stm32mp157c.
dt-bindings: net: stmmac: add phys config properties
net: ethernet: stmmac: add management of clk_csr property
net: ethernet: stmmac: update to be compatible with MCU family
(stm32f4, stm32h7)
dt-bindings: net: stmmac: add syscfg clock property
ARM: dts: stm32: Add Ethernet support on stm32h7 SOC and activate it
for eval and disco boards
ARM: dts: stm32: add syscfg clock support for Ethernet on STM32F429
SoC
.../devicetree/bindings/net/stm32-dwmac.txt | 10 +-
arch/arm/boot/dts/stm32f429.dtsi | 6 +-
arch/arm/boot/dts/stm32h743-pinctrl.dtsi | 15 ++
arch/arm/boot/dts/stm32h743.dtsi | 19 +++
arch/arm/boot/dts/stm32h743i-disco.dts | 17 ++
arch/arm/boot/dts/stm32h743i-eval.dts | 17 ++
drivers/net/ethernet/stmicro/stmmac/dwmac-stm32.c | 179 +++++++++++++++++----
.../net/ethernet/stmicro/stmmac/stmmac_platform.c | 3 +
8 files changed, 230 insertions(+), 36 deletions(-)
--
2.7.4
^ permalink raw reply
* [PATCH] atm: clean up vcc_seq_next()
From: Dan Carpenter @ 2019-02-14 6:56 UTC (permalink / raw)
To: David S. Miller; +Cc: Joe Perches, netdev, kernel-janitors
It's confusing to call PTR_ERR(v). The PTR_ERR() function is basically
a fancy cast to long so it makes you wonder, was IS_ERR() intended? But
that doesn't make sense because vcc_walk() doesn't return error
pointers.
This patch doesn't affect runtime, it's just a cleanup.
Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
---
net/atm/proc.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/net/atm/proc.c b/net/atm/proc.c
index 0b0495a41bbe..d79221fd4dae 100644
--- a/net/atm/proc.c
+++ b/net/atm/proc.c
@@ -134,7 +134,8 @@ static void vcc_seq_stop(struct seq_file *seq, void *v)
static void *vcc_seq_next(struct seq_file *seq, void *v, loff_t *pos)
{
v = vcc_walk(seq, 1);
- *pos += !!PTR_ERR(v);
+ if (v)
+ (*pos)++;
return v;
}
--
2.17.1
^ permalink raw reply related
* Re: [PATCH v2 1/2] iwlwifi: Use kmemdup instead of duplicating its function
From: Luciano Coelho @ 2019-02-14 6:57 UTC (permalink / raw)
To: YueHaibing, johannes.berg, emmanuel.grumbach, linuxwifi, kvalo
Cc: linux-kernel, netdev, linux-wireless
In-Reply-To: <20190129032144.18120-2-yuehaibing@huawei.com>
On Tue, 2019-01-29 at 11:21 +0800, YueHaibing wrote:
> Use kmemdup rather than duplicating its implementation
>
> Signed-off-by: YueHaibing <yuehaibing@huawei.com>
> ---
> drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c | 8 ++------
> 1 file changed, 2 insertions(+), 6 deletions(-)
>
> diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c
> b/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c
> index d9afedc..569cc50 100644
> --- a/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c
> +++ b/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c
> @@ -1196,13 +1196,9 @@ iwl_parse_nvm_mcc_info(struct device *dev,
> const struct iwl_cfg *cfg,
> regd_to_copy = sizeof(struct ieee80211_regdomain) +
> valid_rules * sizeof(struct ieee80211_reg_rule);
>
> - copy_rd = kzalloc(regd_to_copy, GFP_KERNEL);
> - if (!copy_rd) {
> + copy_rd = kmemdup(regd, regd_to_copy, GFP_KERNEL);
> + if (!copy_rd)
> copy_rd = ERR_PTR(-ENOMEM);
> - goto out;
> - }
> -
> - memcpy(copy_rd, regd, regd_to_copy);
>
> out:
> kfree(regdb_ptrs);
This was already applied. Dropping.
--
Luca.
^ permalink raw reply
* Re: [PATCH v2 2/2] iwlwifi: Use struct_size() in kzalloc
From: Luciano Coelho @ 2019-02-14 6:58 UTC (permalink / raw)
To: YueHaibing, johannes.berg, emmanuel.grumbach, linuxwifi, kvalo
Cc: linux-kernel, netdev, linux-wireless
In-Reply-To: <20190129032144.18120-3-yuehaibing@huawei.com>
On Tue, 2019-01-29 at 11:21 +0800, YueHaibing wrote:
> Use struct_size() in kzalloc instead of the 'regd_to_copy'
>
> Signed-off-by: YueHaibing <yuehaibing@huawei.com>
> ---
Applied to our internal tree and it will reach the mainline following
our normal upstreaming process.
Thanks!
--
Luca.
^ permalink raw reply
* RE: [PATCH net-next 09/12] mlxsw: core: Extend hwmon interface with fan fault attribute
From: Vadim Pasternak @ 2019-02-14 7:06 UTC (permalink / raw)
To: Guenter Roeck, Andrew Lunn, Ido Schimmel
Cc: netdev@vger.kernel.org, davem@davemloft.net, Jiri Pirko, mlxsw
In-Reply-To: <470dd874-a3b8-3885-5077-f2b16d1a63ca@roeck-us.net>
> -----Original Message-----
> From: Guenter Roeck <groeck7@gmail.com> On Behalf Of Guenter Roeck
> Sent: Wednesday, February 13, 2019 5:03 PM
> To: Andrew Lunn <andrew@lunn.ch>; Ido Schimmel <idosch@mellanox.com>
> Cc: netdev@vger.kernel.org; davem@davemloft.net; Jiri Pirko
> <jiri@mellanox.com>; mlxsw <mlxsw@mellanox.com>; Vadim Pasternak
> <vadimp@mellanox.com>
> Subject: Re: [PATCH net-next 09/12] mlxsw: core: Extend hwmon interface with
> fan fault attribute
>
> On 2/13/19 5:53 AM, Andrew Lunn wrote:
> > On Wed, Feb 13, 2019 at 11:28:53AM +0000, Ido Schimmel wrote:
> >> From: Vadim Pasternak <vadimp@mellanox.com>
> >>
> >> Add new fan hwmon attribute for exposing fan faults (fault indication
> >> is read from Fan Out of Range Event Register).
> >>
> >> Signed-off-by: Vadim Pasternak <vadimp@mellanox.com>
> >> Reviewed-by: Jiri Pirko <jiri@mellanox.com>
> >> Signed-off-by: Ido Schimmel <idosch@mellanox.com>
> >
> > Hi Ido
> >
> > You should include the HWMON maintainer in the Cc: list.
> >
> > I would not be too surprised if he says to use
> > hwmon_device_register_with_info().
> >
>
> I would ask to do that for new drivers, but this is is not a new driver.
> On top of that, I wasn't included in its initial review. Since I wasn't involved, I
> have no idea what shape the driver is in, and for sure won't review it now (to
> retain my sanity).
>
> Only comment I have is that using the _with_info API and using devm_ functions
> might simplify the driver a lot. I'll be happy to do a review if/when that is done.
>
> Guenter
Hi Guenter,
Thank you for your comments.
But, this patch adds one new FAN attribute to the existing infrastructure.
At the time mlxsw core_hwmon module has been submitted, the API
hwmon_device_register_with_info() was not available yet.
Of course in a new modules we are using this API, like in
our mlxreg-fan for example.
The same is relevant for the patch 10/12 from this series – it also extends
the existing infrastructure.
But there, even in case of a new code the config structure for
hwmon_device_register_with_info() would be look like:
{
/* 3 entries like below - for chip ambient temperatures (could be from 1 to 3. */
HWMON_F_INPUT | HWMON_T_HIGHEST | HWMON_T_RESET_HISTORY,
...
/* 128 entries like below - for modules temperatures (could be from 16 to 128. */
HWMON_F_INPUT | HWMON_T_CRIT | HWMON_T_EMERGENCY, HWMON_T_FAULT | HWMON_T_LABEL,
...
/* 64 entries like below - for interconnects temperatures (could be from 0 to 64). */
HWMON_F_INPUT | HWMON_T_HIGHEST | HWMON_T_RESET_HISTORY | HWMON_T_LABEL,
0
};
Means we'll have 195 lines for configuration description and in case future systems will
be equipped with the bigger number of port slots and/or with the bigger number of
interconnects devices, the below structure will require modification.
Modification will be not necessary, in case we'll keep configuration like it is now.
Regarding devm_ API - it has been used initially in core_hwmon module, but the in
commit (9b3bc7db759e) it has been removed. And it was a good reason for that.
Chip can be re-programmed after initialization in case driver determines it needs to
flash a new firmware version. In such case after re-programming driver will make
registration again and among the other stuff it will make new registration with
hwmon subsystem. And in case it 's registered with
hwmon subsystem using devm_hwmon_device_register_with_groups(), the old
hwmon device (registered before the flashing) was never unregistered and was
referencing stale data, resulting in a use-after free.
^ permalink raw reply
* [PATCH net-next] net/tls: Move protocol constants from cipher context to tls context
From: Vakul Garg @ 2019-02-14 7:11 UTC (permalink / raw)
To: netdev@vger.kernel.org
Cc: borisp@mellanox.com, aviadye@mellanox.com, davejwatson@fb.com,
davem@davemloft.net, doronrk@fb.com, Vakul Garg
Each tls context maintains two cipher contexts (one each for tx and rx
directions). For each tls session, the constants such as protocol
version, ciphersuite, iv size, associated data size etc are same for
both the directions and need to be stored only once per tls context.
Hence these are moved from 'struct cipher_context' to 'struct
tls_prot_info' and stored only once in 'struct tls_context'.
Signed-off-by: Vakul Garg <vakul.garg@nxp.com>
---
include/net/tls.h | 46 +++++++++-----
net/tls/tls_device.c | 24 ++++---
net/tls/tls_main.c | 17 ++++-
net/tls/tls_sw.c | 172 +++++++++++++++++++++++++++------------------------
4 files changed, 149 insertions(+), 110 deletions(-)
diff --git a/include/net/tls.h b/include/net/tls.h
index a93a8ed8f716..a8b37226a287 100644
--- a/include/net/tls.h
+++ b/include/net/tls.h
@@ -199,15 +199,8 @@ enum {
};
struct cipher_context {
- u16 prepend_size;
- u16 tag_size;
- u16 overhead_size;
- u16 iv_size;
char *iv;
- u16 rec_seq_size;
char *rec_seq;
- u16 aad_size;
- u16 tail_size;
};
union tls_crypto_context {
@@ -218,7 +211,21 @@ union tls_crypto_context {
};
};
+struct tls_prot_info {
+ u16 version;
+ u16 cipher_type;
+ u16 prepend_size;
+ u16 tag_size;
+ u16 overhead_size;
+ u16 iv_size;
+ u16 rec_seq_size;
+ u16 aad_size;
+ u16 tail_size;
+};
+
struct tls_context {
+ struct tls_prot_info prot_info;
+
union tls_crypto_context crypto_send;
union tls_crypto_context crypto_recv;
@@ -401,16 +408,26 @@ static inline bool tls_bigint_increment(unsigned char *seq, int len)
return (i == -1);
}
+static inline struct tls_context *tls_get_ctx(const struct sock *sk)
+{
+ struct inet_connection_sock *icsk = inet_csk(sk);
+
+ return icsk->icsk_ulp_data;
+}
+
static inline void tls_advance_record_sn(struct sock *sk,
struct cipher_context *ctx,
int version)
{
- if (tls_bigint_increment(ctx->rec_seq, ctx->rec_seq_size))
+ struct tls_context *tls_ctx = tls_get_ctx(sk);
+ struct tls_prot_info *prot = &tls_ctx->prot_info;
+
+ if (tls_bigint_increment(ctx->rec_seq, prot->rec_seq_size))
tls_err_abort(sk, EBADMSG);
if (version != TLS_1_3_VERSION) {
tls_bigint_increment(ctx->iv + TLS_CIPHER_AES_GCM_128_SALT_SIZE,
- ctx->iv_size);
+ prot->iv_size);
}
}
@@ -420,9 +437,10 @@ static inline void tls_fill_prepend(struct tls_context *ctx,
unsigned char record_type,
int version)
{
- size_t pkt_len, iv_size = ctx->tx.iv_size;
+ struct tls_prot_info *prot = &ctx->prot_info;
+ size_t pkt_len, iv_size = prot->iv_size;
- pkt_len = plaintext_len + ctx->tx.tag_size;
+ pkt_len = plaintext_len + prot->tag_size;
if (version != TLS_1_3_VERSION) {
pkt_len += iv_size;
@@ -475,12 +493,6 @@ static inline void xor_iv_with_seq(int version, char *iv, char *seq)
}
}
-static inline struct tls_context *tls_get_ctx(const struct sock *sk)
-{
- struct inet_connection_sock *icsk = inet_csk(sk);
-
- return icsk->icsk_ulp_data;
-}
static inline struct tls_sw_context_rx *tls_sw_ctx_rx(
const struct tls_context *tls_ctx)
diff --git a/net/tls/tls_device.c b/net/tls/tls_device.c
index 7ee9008b2187..a5c17c47d08a 100644
--- a/net/tls/tls_device.c
+++ b/net/tls/tls_device.c
@@ -247,6 +247,7 @@ static int tls_push_record(struct sock *sk,
int flags,
unsigned char record_type)
{
+ struct tls_prot_info *prot = &ctx->prot_info;
struct tcp_sock *tp = tcp_sk(sk);
struct page_frag dummy_tag_frag;
skb_frag_t *frag;
@@ -256,7 +257,7 @@ static int tls_push_record(struct sock *sk,
frag = &record->frags[0];
tls_fill_prepend(ctx,
skb_frag_address(frag),
- record->len - ctx->tx.prepend_size,
+ record->len - prot->prepend_size,
record_type,
ctx->crypto_send.info.version);
@@ -264,7 +265,7 @@ static int tls_push_record(struct sock *sk,
dummy_tag_frag.page = skb_frag_page(frag);
dummy_tag_frag.offset = 0;
- tls_append_frag(record, &dummy_tag_frag, ctx->tx.tag_size);
+ tls_append_frag(record, &dummy_tag_frag, prot->tag_size);
record->end_seq = tp->write_seq + record->len;
spin_lock_irq(&offload_ctx->lock);
list_add_tail(&record->list, &offload_ctx->records_list);
@@ -347,6 +348,7 @@ static int tls_push_data(struct sock *sk,
unsigned char record_type)
{
struct tls_context *tls_ctx = tls_get_ctx(sk);
+ struct tls_prot_info *prot = &tls_ctx->prot_info;
struct tls_offload_context_tx *ctx = tls_offload_ctx_tx(tls_ctx);
int tls_push_record_flags = flags | MSG_SENDPAGE_NOTLAST;
int more = flags & (MSG_SENDPAGE_NOTLAST | MSG_MORE);
@@ -376,10 +378,10 @@ static int tls_push_data(struct sock *sk,
* we need to leave room for an authentication tag.
*/
max_open_record_len = TLS_MAX_PAYLOAD_SIZE +
- tls_ctx->tx.prepend_size;
+ prot->prepend_size;
do {
rc = tls_do_allocation(sk, ctx, pfrag,
- tls_ctx->tx.prepend_size);
+ prot->prepend_size);
if (rc) {
rc = sk_stream_wait_memory(sk, &timeo);
if (!rc)
@@ -397,7 +399,7 @@ static int tls_push_data(struct sock *sk,
size = orig_size;
destroy_record(record);
ctx->open_record = NULL;
- } else if (record->len > tls_ctx->tx.prepend_size) {
+ } else if (record->len > prot->prepend_size) {
goto last_record;
}
@@ -658,6 +660,8 @@ int tls_device_decrypted(struct sock *sk, struct sk_buff *skb)
int tls_set_device_offload(struct sock *sk, struct tls_context *ctx)
{
u16 nonce_size, tag_size, iv_size, rec_seq_size;
+ struct tls_context *tls_ctx = tls_get_ctx(sk);
+ struct tls_prot_info *prot = &tls_ctx->prot_info;
struct tls_record_info *start_marker_record;
struct tls_offload_context_tx *offload_ctx;
struct tls_crypto_info *crypto_info;
@@ -703,10 +707,10 @@ int tls_set_device_offload(struct sock *sk, struct tls_context *ctx)
goto free_offload_ctx;
}
- ctx->tx.prepend_size = TLS_HEADER_SIZE + nonce_size;
- ctx->tx.tag_size = tag_size;
- ctx->tx.overhead_size = ctx->tx.prepend_size + ctx->tx.tag_size;
- ctx->tx.iv_size = iv_size;
+ prot->prepend_size = TLS_HEADER_SIZE + nonce_size;
+ prot->tag_size = tag_size;
+ prot->overhead_size = prot->prepend_size + prot->tag_size;
+ prot->iv_size = iv_size;
ctx->tx.iv = kmalloc(iv_size + TLS_CIPHER_AES_GCM_128_SALT_SIZE,
GFP_KERNEL);
if (!ctx->tx.iv) {
@@ -716,7 +720,7 @@ int tls_set_device_offload(struct sock *sk, struct tls_context *ctx)
memcpy(ctx->tx.iv + TLS_CIPHER_AES_GCM_128_SALT_SIZE, iv, iv_size);
- ctx->tx.rec_seq_size = rec_seq_size;
+ prot->rec_seq_size = rec_seq_size;
ctx->tx.rec_seq = kmemdup(rec_seq, rec_seq_size, GFP_KERNEL);
if (!ctx->tx.rec_seq) {
rc = -ENOMEM;
diff --git a/net/tls/tls_main.c b/net/tls/tls_main.c
index d1c2fd9a3f63..caff15b2f9b2 100644
--- a/net/tls/tls_main.c
+++ b/net/tls/tls_main.c
@@ -435,6 +435,7 @@ static int do_tls_setsockopt_conf(struct sock *sk, char __user *optval,
unsigned int optlen, int tx)
{
struct tls_crypto_info *crypto_info;
+ struct tls_crypto_info *alt_crypto_info;
struct tls_context *ctx = tls_get_ctx(sk);
size_t optsize;
int rc = 0;
@@ -445,10 +446,13 @@ static int do_tls_setsockopt_conf(struct sock *sk, char __user *optval,
goto out;
}
- if (tx)
+ if (tx) {
crypto_info = &ctx->crypto_send.info;
- else
+ alt_crypto_info = &ctx->crypto_recv.info;
+ } else {
crypto_info = &ctx->crypto_recv.info;
+ alt_crypto_info = &ctx->crypto_send.info;
+ }
/* Currently we don't support set crypto info more than one time */
if (TLS_CRYPTO_INFO_READY(crypto_info)) {
@@ -469,6 +473,15 @@ static int do_tls_setsockopt_conf(struct sock *sk, char __user *optval,
goto err_crypto_info;
}
+ /* Ensure that TLS version and ciphers are same in both directions */
+ if (TLS_CRYPTO_INFO_READY(alt_crypto_info)) {
+ if (alt_crypto_info->version != crypto_info->version ||
+ alt_crypto_info->cipher_type != crypto_info->cipher_type) {
+ rc = -EINVAL;
+ goto err_crypto_info;
+ }
+ }
+
switch (crypto_info->cipher_type) {
case TLS_CIPHER_AES_GCM_128:
case TLS_CIPHER_AES_GCM_256: {
diff --git a/net/tls/tls_sw.c b/net/tls/tls_sw.c
index ae4784734547..71be8acfbc9b 100644
--- a/net/tls/tls_sw.c
+++ b/net/tls/tls_sw.c
@@ -127,7 +127,7 @@ static int padding_length(struct tls_sw_context_rx *ctx,
int sub = 0;
/* Determine zero-padding length */
- if (tls_ctx->crypto_recv.info.version == TLS_1_3_VERSION) {
+ if (tls_ctx->prot_info.version == TLS_1_3_VERSION) {
char content_type = 0;
int err;
int back = 17;
@@ -155,6 +155,7 @@ static void tls_decrypt_done(struct crypto_async_request *req, int err)
struct scatterlist *sgin = aead_req->src;
struct tls_sw_context_rx *ctx;
struct tls_context *tls_ctx;
+ struct tls_prot_info *prot;
struct scatterlist *sg;
struct sk_buff *skb;
unsigned int pages;
@@ -163,6 +164,7 @@ static void tls_decrypt_done(struct crypto_async_request *req, int err)
skb = (struct sk_buff *)req->data;
tls_ctx = tls_get_ctx(skb->sk);
ctx = tls_sw_ctx_rx(tls_ctx);
+ prot = &tls_ctx->prot_info;
/* Propagate if there was an err */
if (err) {
@@ -171,8 +173,8 @@ static void tls_decrypt_done(struct crypto_async_request *req, int err)
} else {
struct strp_msg *rxm = strp_msg(skb);
rxm->full_len -= padding_length(ctx, tls_ctx, skb);
- rxm->offset += tls_ctx->rx.prepend_size;
- rxm->full_len -= tls_ctx->rx.overhead_size;
+ rxm->offset += prot->prepend_size;
+ rxm->full_len -= prot->overhead_size;
}
/* After using skb->sk to propagate sk through crypto async callback
@@ -209,13 +211,14 @@ static int tls_do_decryption(struct sock *sk,
bool async)
{
struct tls_context *tls_ctx = tls_get_ctx(sk);
+ struct tls_prot_info *prot = &tls_ctx->prot_info;
struct tls_sw_context_rx *ctx = tls_sw_ctx_rx(tls_ctx);
int ret;
aead_request_set_tfm(aead_req, ctx->aead_recv);
- aead_request_set_ad(aead_req, tls_ctx->rx.aad_size);
+ aead_request_set_ad(aead_req, prot->aad_size);
aead_request_set_crypt(aead_req, sgin, sgout,
- data_len + tls_ctx->rx.tag_size,
+ data_len + prot->tag_size,
(u8 *)iv_recv);
if (async) {
@@ -253,12 +256,13 @@ static int tls_do_decryption(struct sock *sk,
static void tls_trim_both_msgs(struct sock *sk, int target_size)
{
struct tls_context *tls_ctx = tls_get_ctx(sk);
+ struct tls_prot_info *prot = &tls_ctx->prot_info;
struct tls_sw_context_tx *ctx = tls_sw_ctx_tx(tls_ctx);
struct tls_rec *rec = ctx->open_rec;
sk_msg_trim(sk, &rec->msg_plaintext, target_size);
if (target_size > 0)
- target_size += tls_ctx->tx.overhead_size;
+ target_size += prot->overhead_size;
sk_msg_trim(sk, &rec->msg_encrypted, target_size);
}
@@ -275,6 +279,7 @@ static int tls_alloc_encrypted_msg(struct sock *sk, int len)
static int tls_clone_plaintext_msg(struct sock *sk, int required)
{
struct tls_context *tls_ctx = tls_get_ctx(sk);
+ struct tls_prot_info *prot = &tls_ctx->prot_info;
struct tls_sw_context_tx *ctx = tls_sw_ctx_tx(tls_ctx);
struct tls_rec *rec = ctx->open_rec;
struct sk_msg *msg_pl = &rec->msg_plaintext;
@@ -290,7 +295,7 @@ static int tls_clone_plaintext_msg(struct sock *sk, int required)
/* Skip initial bytes in msg_en's data to be able to use
* same offset of both plain and encrypted data.
*/
- skip = tls_ctx->tx.prepend_size + msg_pl->sg.size;
+ skip = prot->prepend_size + msg_pl->sg.size;
return sk_msg_clone(sk, msg_pl, msg_en, skip, len);
}
@@ -298,6 +303,7 @@ static int tls_clone_plaintext_msg(struct sock *sk, int required)
static struct tls_rec *tls_get_rec(struct sock *sk)
{
struct tls_context *tls_ctx = tls_get_ctx(sk);
+ struct tls_prot_info *prot = &tls_ctx->prot_info;
struct tls_sw_context_tx *ctx = tls_sw_ctx_tx(tls_ctx);
struct sk_msg *msg_pl, *msg_en;
struct tls_rec *rec;
@@ -316,13 +322,11 @@ static struct tls_rec *tls_get_rec(struct sock *sk)
sk_msg_init(msg_en);
sg_init_table(rec->sg_aead_in, 2);
- sg_set_buf(&rec->sg_aead_in[0], rec->aad_space,
- tls_ctx->tx.aad_size);
+ sg_set_buf(&rec->sg_aead_in[0], rec->aad_space, prot->aad_size);
sg_unmark_end(&rec->sg_aead_in[1]);
sg_init_table(rec->sg_aead_out, 2);
- sg_set_buf(&rec->sg_aead_out[0], rec->aad_space,
- tls_ctx->tx.aad_size);
+ sg_set_buf(&rec->sg_aead_out[0], rec->aad_space, prot->aad_size);
sg_unmark_end(&rec->sg_aead_out[1]);
return rec;
@@ -411,6 +415,7 @@ static void tls_encrypt_done(struct crypto_async_request *req, int err)
struct aead_request *aead_req = (struct aead_request *)req;
struct sock *sk = req->data;
struct tls_context *tls_ctx = tls_get_ctx(sk);
+ struct tls_prot_info *prot = &tls_ctx->prot_info;
struct tls_sw_context_tx *ctx = tls_sw_ctx_tx(tls_ctx);
struct scatterlist *sge;
struct sk_msg *msg_en;
@@ -422,8 +427,8 @@ static void tls_encrypt_done(struct crypto_async_request *req, int err)
msg_en = &rec->msg_encrypted;
sge = sk_msg_elem(msg_en, msg_en->sg.curr);
- sge->offset -= tls_ctx->tx.prepend_size;
- sge->length += tls_ctx->tx.prepend_size;
+ sge->offset -= prot->prepend_size;
+ sge->length += prot->prepend_size;
/* Check if error is previously set on socket */
if (err || sk->sk_err) {
@@ -470,22 +475,23 @@ static int tls_do_encryption(struct sock *sk,
struct aead_request *aead_req,
size_t data_len, u32 start)
{
+ struct tls_prot_info *prot = &tls_ctx->prot_info;
struct tls_rec *rec = ctx->open_rec;
struct sk_msg *msg_en = &rec->msg_encrypted;
struct scatterlist *sge = sk_msg_elem(msg_en, start);
int rc;
memcpy(rec->iv_data, tls_ctx->tx.iv, sizeof(rec->iv_data));
- xor_iv_with_seq(tls_ctx->crypto_send.info.version, rec->iv_data,
+ xor_iv_with_seq(prot->version, rec->iv_data,
tls_ctx->tx.rec_seq);
- sge->offset += tls_ctx->tx.prepend_size;
- sge->length -= tls_ctx->tx.prepend_size;
+ sge->offset += prot->prepend_size;
+ sge->length -= prot->prepend_size;
msg_en->sg.curr = start;
aead_request_set_tfm(aead_req, ctx->aead_send);
- aead_request_set_ad(aead_req, tls_ctx->tx.aad_size);
+ aead_request_set_ad(aead_req, prot->aad_size);
aead_request_set_crypt(aead_req, rec->sg_aead_in,
rec->sg_aead_out,
data_len, rec->iv_data);
@@ -500,8 +506,8 @@ static int tls_do_encryption(struct sock *sk,
rc = crypto_aead_encrypt(aead_req);
if (!rc || rc != -EINPROGRESS) {
atomic_dec(&ctx->encrypt_pending);
- sge->offset -= tls_ctx->tx.prepend_size;
- sge->length += tls_ctx->tx.prepend_size;
+ sge->offset -= prot->prepend_size;
+ sge->length += prot->prepend_size;
}
if (!rc) {
@@ -513,8 +519,7 @@ static int tls_do_encryption(struct sock *sk,
/* Unhook the record from context if encryption is not failure */
ctx->open_rec = NULL;
- tls_advance_record_sn(sk, &tls_ctx->tx,
- tls_ctx->crypto_send.info.version);
+ tls_advance_record_sn(sk, &tls_ctx->tx, prot->version);
return rc;
}
@@ -640,6 +645,7 @@ static int tls_push_record(struct sock *sk, int flags,
unsigned char record_type)
{
struct tls_context *tls_ctx = tls_get_ctx(sk);
+ struct tls_prot_info *prot = &tls_ctx->prot_info;
struct tls_sw_context_tx *ctx = tls_sw_ctx_tx(tls_ctx);
struct tls_rec *rec = ctx->open_rec, *tmp = NULL;
u32 i, split_point, uninitialized_var(orig_end);
@@ -658,12 +664,12 @@ static int tls_push_record(struct sock *sk, int flags,
split = split_point && split_point < msg_pl->sg.size;
if (split) {
rc = tls_split_open_record(sk, rec, &tmp, msg_pl, msg_en,
- split_point, tls_ctx->tx.overhead_size,
+ split_point, prot->overhead_size,
&orig_end);
if (rc < 0)
return rc;
sk_msg_trim(sk, msg_en, msg_pl->sg.size +
- tls_ctx->tx.overhead_size);
+ prot->overhead_size);
}
rec->tx_flags = flags;
@@ -673,7 +679,7 @@ static int tls_push_record(struct sock *sk, int flags,
sk_msg_iter_var_prev(i);
rec->content_type = record_type;
- if (tls_ctx->crypto_send.info.version == TLS_1_3_VERSION) {
+ if (prot->version == TLS_1_3_VERSION) {
/* Add content type to end of message. No padding added */
sg_set_buf(&rec->sg_content_type, &rec->content_type, 1);
sg_mark_end(&rec->sg_content_type);
@@ -694,22 +700,20 @@ static int tls_push_record(struct sock *sk, int flags,
i = msg_en->sg.start;
sg_chain(rec->sg_aead_out, 2, &msg_en->sg.data[i]);
- tls_make_aad(rec->aad_space, msg_pl->sg.size + tls_ctx->tx.tail_size,
- tls_ctx->tx.rec_seq, tls_ctx->tx.rec_seq_size,
- record_type,
- tls_ctx->crypto_send.info.version);
+ tls_make_aad(rec->aad_space, msg_pl->sg.size + prot->tail_size,
+ tls_ctx->tx.rec_seq, prot->rec_seq_size,
+ record_type, prot->version);
tls_fill_prepend(tls_ctx,
page_address(sg_page(&msg_en->sg.data[i])) +
msg_en->sg.data[i].offset,
- msg_pl->sg.size + tls_ctx->tx.tail_size,
- record_type,
- tls_ctx->crypto_send.info.version);
+ msg_pl->sg.size + prot->tail_size,
+ record_type, prot->version);
tls_ctx->pending_open_record_frags = false;
rc = tls_do_encryption(sk, tls_ctx, ctx, req,
- msg_pl->sg.size + tls_ctx->tx.tail_size, i);
+ msg_pl->sg.size + prot->tail_size, i);
if (rc < 0) {
if (rc != -EINPROGRESS) {
tls_err_abort(sk, EBADMSG);
@@ -723,8 +727,7 @@ static int tls_push_record(struct sock *sk, int flags,
} else if (split) {
msg_pl = &tmp->msg_plaintext;
msg_en = &tmp->msg_encrypted;
- sk_msg_trim(sk, msg_en, msg_pl->sg.size +
- tls_ctx->tx.overhead_size);
+ sk_msg_trim(sk, msg_en, msg_pl->sg.size + prot->overhead_size);
tls_ctx->pending_open_record_frags = true;
ctx->open_rec = tmp;
}
@@ -859,6 +862,7 @@ int tls_sw_sendmsg(struct sock *sk, struct msghdr *msg, size_t size)
{
long timeo = sock_sndtimeo(sk, msg->msg_flags & MSG_DONTWAIT);
struct tls_context *tls_ctx = tls_get_ctx(sk);
+ struct tls_prot_info *prot = &tls_ctx->prot_info;
struct tls_sw_context_tx *ctx = tls_sw_ctx_tx(tls_ctx);
bool async_capable = ctx->async_capable;
unsigned char record_type = TLS_RECORD_TYPE_DATA;
@@ -925,7 +929,7 @@ int tls_sw_sendmsg(struct sock *sk, struct msghdr *msg, size_t size)
}
required_size = msg_pl->sg.size + try_to_copy +
- tls_ctx->tx.overhead_size;
+ prot->overhead_size;
if (!sk_stream_memory_free(sk))
goto wait_for_sndbuf;
@@ -994,8 +998,8 @@ int tls_sw_sendmsg(struct sock *sk, struct msghdr *msg, size_t size)
*/
try_to_copy -= required_size - msg_pl->sg.size;
full_record = true;
- sk_msg_trim(sk, msg_en, msg_pl->sg.size +
- tls_ctx->tx.overhead_size);
+ sk_msg_trim(sk, msg_en,
+ msg_pl->sg.size + prot->overhead_size);
}
if (try_to_copy) {
@@ -1081,6 +1085,7 @@ static int tls_sw_do_sendpage(struct sock *sk, struct page *page,
long timeo = sock_sndtimeo(sk, flags & MSG_DONTWAIT);
struct tls_context *tls_ctx = tls_get_ctx(sk);
struct tls_sw_context_tx *ctx = tls_sw_ctx_tx(tls_ctx);
+ struct tls_prot_info *prot = &tls_ctx->prot_info;
unsigned char record_type = TLS_RECORD_TYPE_DATA;
struct sk_msg *msg_pl;
struct tls_rec *rec;
@@ -1130,8 +1135,7 @@ static int tls_sw_do_sendpage(struct sock *sk, struct page *page,
full_record = true;
}
- required_size = msg_pl->sg.size + copy +
- tls_ctx->tx.overhead_size;
+ required_size = msg_pl->sg.size + copy + prot->overhead_size;
if (!sk_stream_memory_free(sk))
goto wait_for_sndbuf;
@@ -1330,6 +1334,7 @@ static int decrypt_internal(struct sock *sk, struct sk_buff *skb,
{
struct tls_context *tls_ctx = tls_get_ctx(sk);
struct tls_sw_context_rx *ctx = tls_sw_ctx_rx(tls_ctx);
+ struct tls_prot_info *prot = &tls_ctx->prot_info;
struct strp_msg *rxm = strp_msg(skb);
int n_sgin, n_sgout, nsg, mem_size, aead_size, err, pages = 0;
struct aead_request *aead_req;
@@ -1337,16 +1342,16 @@ static int decrypt_internal(struct sock *sk, struct sk_buff *skb,
u8 *aad, *iv, *mem = NULL;
struct scatterlist *sgin = NULL;
struct scatterlist *sgout = NULL;
- const int data_len = rxm->full_len - tls_ctx->rx.overhead_size +
- tls_ctx->rx.tail_size;
+ const int data_len = rxm->full_len - prot->overhead_size +
+ prot->tail_size;
if (*zc && (out_iov || out_sg)) {
if (out_iov)
n_sgout = iov_iter_npages(out_iov, INT_MAX) + 1;
else
n_sgout = sg_nents(out_sg);
- n_sgin = skb_nsg(skb, rxm->offset + tls_ctx->rx.prepend_size,
- rxm->full_len - tls_ctx->rx.prepend_size);
+ n_sgin = skb_nsg(skb, rxm->offset + prot->prepend_size,
+ rxm->full_len - prot->prepend_size);
} else {
n_sgout = 0;
*zc = false;
@@ -1363,7 +1368,7 @@ static int decrypt_internal(struct sock *sk, struct sk_buff *skb,
aead_size = sizeof(*aead_req) + crypto_aead_reqsize(ctx->aead_recv);
mem_size = aead_size + (nsg * sizeof(struct scatterlist));
- mem_size = mem_size + tls_ctx->rx.aad_size;
+ mem_size = mem_size + prot->aad_size;
mem_size = mem_size + crypto_aead_ivsize(ctx->aead_recv);
/* Allocate a single block of memory which contains
@@ -1379,37 +1384,35 @@ static int decrypt_internal(struct sock *sk, struct sk_buff *skb,
sgin = (struct scatterlist *)(mem + aead_size);
sgout = sgin + n_sgin;
aad = (u8 *)(sgout + n_sgout);
- iv = aad + tls_ctx->rx.aad_size;
+ iv = aad + prot->aad_size;
/* Prepare IV */
err = skb_copy_bits(skb, rxm->offset + TLS_HEADER_SIZE,
iv + TLS_CIPHER_AES_GCM_128_SALT_SIZE,
- tls_ctx->rx.iv_size);
+ prot->iv_size);
if (err < 0) {
kfree(mem);
return err;
}
- if (tls_ctx->crypto_recv.info.version == TLS_1_3_VERSION)
+ if (prot->version == TLS_1_3_VERSION)
memcpy(iv, tls_ctx->rx.iv, crypto_aead_ivsize(ctx->aead_recv));
else
memcpy(iv, tls_ctx->rx.iv, TLS_CIPHER_AES_GCM_128_SALT_SIZE);
- xor_iv_with_seq(tls_ctx->crypto_recv.info.version, iv,
- tls_ctx->rx.rec_seq);
+ xor_iv_with_seq(prot->version, iv, tls_ctx->rx.rec_seq);
/* Prepare AAD */
- tls_make_aad(aad, rxm->full_len - tls_ctx->rx.overhead_size +
- tls_ctx->rx.tail_size,
- tls_ctx->rx.rec_seq, tls_ctx->rx.rec_seq_size,
- ctx->control,
- tls_ctx->crypto_recv.info.version);
+ tls_make_aad(aad, rxm->full_len - prot->overhead_size +
+ prot->tail_size,
+ tls_ctx->rx.rec_seq, prot->rec_seq_size,
+ ctx->control, prot->version);
/* Prepare sgin */
sg_init_table(sgin, n_sgin);
- sg_set_buf(&sgin[0], aad, tls_ctx->rx.aad_size);
+ sg_set_buf(&sgin[0], aad, prot->aad_size);
err = skb_to_sgvec(skb, &sgin[1],
- rxm->offset + tls_ctx->rx.prepend_size,
- rxm->full_len - tls_ctx->rx.prepend_size);
+ rxm->offset + prot->prepend_size,
+ rxm->full_len - prot->prepend_size);
if (err < 0) {
kfree(mem);
return err;
@@ -1418,7 +1421,7 @@ static int decrypt_internal(struct sock *sk, struct sk_buff *skb,
if (n_sgout) {
if (out_iov) {
sg_init_table(sgout, n_sgout);
- sg_set_buf(&sgout[0], aad, tls_ctx->rx.aad_size);
+ sg_set_buf(&sgout[0], aad, prot->aad_size);
*chunk = 0;
err = tls_setup_from_iter(sk, out_iov, data_len,
@@ -1459,7 +1462,8 @@ static int decrypt_skb_update(struct sock *sk, struct sk_buff *skb,
{
struct tls_context *tls_ctx = tls_get_ctx(sk);
struct tls_sw_context_rx *ctx = tls_sw_ctx_rx(tls_ctx);
- int version = tls_ctx->crypto_recv.info.version;
+ struct tls_prot_info *prot = &tls_ctx->prot_info;
+ int version = prot->version;
struct strp_msg *rxm = strp_msg(skb);
int err = 0;
@@ -1480,8 +1484,8 @@ static int decrypt_skb_update(struct sock *sk, struct sk_buff *skb,
rxm->full_len -= padding_length(ctx, tls_ctx, skb);
- rxm->offset += tls_ctx->rx.prepend_size;
- rxm->full_len -= tls_ctx->rx.overhead_size;
+ rxm->offset += prot->prepend_size;
+ rxm->full_len -= prot->overhead_size;
tls_advance_record_sn(sk, &tls_ctx->rx, version);
ctx->decrypted = true;
ctx->saved_data_ready(sk);
@@ -1605,6 +1609,7 @@ int tls_sw_recvmsg(struct sock *sk,
{
struct tls_context *tls_ctx = tls_get_ctx(sk);
struct tls_sw_context_rx *ctx = tls_sw_ctx_rx(tls_ctx);
+ struct tls_prot_info *prot = &tls_ctx->prot_info;
struct sk_psock *psock;
unsigned char control = 0;
ssize_t decrypted = 0;
@@ -1667,11 +1672,11 @@ int tls_sw_recvmsg(struct sock *sk,
rxm = strp_msg(skb);
- to_decrypt = rxm->full_len - tls_ctx->rx.overhead_size;
+ to_decrypt = rxm->full_len - prot->overhead_size;
if (to_decrypt <= len && !is_kvec && !is_peek &&
ctx->control == TLS_RECORD_TYPE_DATA &&
- tls_ctx->crypto_recv.info.version != TLS_1_3_VERSION)
+ prot->version != TLS_1_3_VERSION)
zc = true;
/* Do not use async mode if record is non-data */
@@ -1875,6 +1880,7 @@ static int tls_read_size(struct strparser *strp, struct sk_buff *skb)
{
struct tls_context *tls_ctx = tls_get_ctx(strp->sk);
struct tls_sw_context_rx *ctx = tls_sw_ctx_rx(tls_ctx);
+ struct tls_prot_info *prot = &tls_ctx->prot_info;
char header[TLS_HEADER_SIZE + MAX_IV_SIZE];
struct strp_msg *rxm = strp_msg(skb);
size_t cipher_overhead;
@@ -1882,17 +1888,17 @@ static int tls_read_size(struct strparser *strp, struct sk_buff *skb)
int ret;
/* Verify that we have a full TLS header, or wait for more data */
- if (rxm->offset + tls_ctx->rx.prepend_size > skb->len)
+ if (rxm->offset + prot->prepend_size > skb->len)
return 0;
/* Sanity-check size of on-stack buffer. */
- if (WARN_ON(tls_ctx->rx.prepend_size > sizeof(header))) {
+ if (WARN_ON(prot->prepend_size > sizeof(header))) {
ret = -EINVAL;
goto read_failure;
}
/* Linearize header to local buffer */
- ret = skb_copy_bits(skb, rxm->offset, header, tls_ctx->rx.prepend_size);
+ ret = skb_copy_bits(skb, rxm->offset, header, prot->prepend_size);
if (ret < 0)
goto read_failure;
@@ -1901,12 +1907,12 @@ static int tls_read_size(struct strparser *strp, struct sk_buff *skb)
data_len = ((header[4] & 0xFF) | (header[3] << 8));
- cipher_overhead = tls_ctx->rx.tag_size;
- if (tls_ctx->crypto_recv.info.version != TLS_1_3_VERSION)
- cipher_overhead += tls_ctx->rx.iv_size;
+ cipher_overhead = prot->tag_size;
+ if (prot->version != TLS_1_3_VERSION)
+ cipher_overhead += prot->iv_size;
if (data_len > TLS_MAX_PAYLOAD_SIZE + cipher_overhead +
- tls_ctx->rx.tail_size) {
+ prot->tail_size) {
ret = -EMSGSIZE;
goto read_failure;
}
@@ -2066,6 +2072,8 @@ static void tx_work_handler(struct work_struct *work)
int tls_set_sw_offload(struct sock *sk, struct tls_context *ctx, int tx)
{
+ struct tls_context *tls_ctx = tls_get_ctx(sk);
+ struct tls_prot_info *prot = &tls_ctx->prot_info;
struct tls_crypto_info *crypto_info;
struct tls12_crypto_info_aes_gcm_128 *gcm_128_info;
struct tls12_crypto_info_aes_gcm_256 *gcm_256_info;
@@ -2171,18 +2179,20 @@ int tls_set_sw_offload(struct sock *sk, struct tls_context *ctx, int tx)
if (crypto_info->version == TLS_1_3_VERSION) {
nonce_size = 0;
- cctx->aad_size = TLS_HEADER_SIZE;
- cctx->tail_size = 1;
+ prot->aad_size = TLS_HEADER_SIZE;
+ prot->tail_size = 1;
} else {
- cctx->aad_size = TLS_AAD_SPACE_SIZE;
- cctx->tail_size = 0;
+ prot->aad_size = TLS_AAD_SPACE_SIZE;
+ prot->tail_size = 0;
}
- cctx->prepend_size = TLS_HEADER_SIZE + nonce_size;
- cctx->tag_size = tag_size;
- cctx->overhead_size = cctx->prepend_size + cctx->tag_size +
- cctx->tail_size;
- cctx->iv_size = iv_size;
+ prot->version = crypto_info->version;
+ prot->cipher_type = crypto_info->cipher_type;
+ prot->prepend_size = TLS_HEADER_SIZE + nonce_size;
+ prot->tag_size = tag_size;
+ prot->overhead_size = prot->prepend_size +
+ prot->tag_size + prot->tail_size;
+ prot->iv_size = iv_size;
cctx->iv = kmalloc(iv_size + TLS_CIPHER_AES_GCM_128_SALT_SIZE,
GFP_KERNEL);
if (!cctx->iv) {
@@ -2192,7 +2202,7 @@ int tls_set_sw_offload(struct sock *sk, struct tls_context *ctx, int tx)
/* Note: 128 & 256 bit salt are the same size */
memcpy(cctx->iv, salt, TLS_CIPHER_AES_GCM_128_SALT_SIZE);
memcpy(cctx->iv + TLS_CIPHER_AES_GCM_128_SALT_SIZE, iv, iv_size);
- cctx->rec_seq_size = rec_seq_size;
+ prot->rec_seq_size = rec_seq_size;
cctx->rec_seq = kmemdup(rec_seq, rec_seq_size, GFP_KERNEL);
if (!cctx->rec_seq) {
rc = -ENOMEM;
@@ -2215,7 +2225,7 @@ int tls_set_sw_offload(struct sock *sk, struct tls_context *ctx, int tx)
if (rc)
goto free_aead;
- rc = crypto_aead_setauthsize(*aead, cctx->tag_size);
+ rc = crypto_aead_setauthsize(*aead, prot->tag_size);
if (rc)
goto free_aead;
--
2.13.6
^ permalink raw reply related
* Re: stmmac / meson8b-dwmac
From: Simon Huelck @ 2019-02-14 7:21 UTC (permalink / raw)
To: Jose Abreu, Martin Blumenstingl
Cc: Emiliano Ingrassia, Gpeppe.cavallaro, alexandre.torgue,
linux-amlogic, netdev
In-Reply-To: <330a523a-c1d6-4a99-3287-459096af0330@synopsys.com>
Hi,
i used iperf2 on my odroid c2 , since this can do duplex tests ! iperf2 -c 10.10.11.1
-i1 -d
Do you really need the exact numbers ?
NON-duplex:
4.14.29 reached 930 MBits without the -d ( duplex option ), 5.0rc5 only
reaches 600MBits there
DUPLEX:
With the -d option things get worse on 4.14.29 , 600MBits in both
directions. on 5.0rc5 this is the 500 to 600 in one direction, the other
only 150MBits.
iperf3 is not duplex capable, i didnt test the reverse option, but
duplex tests show that one direction drops in performance when the other
is busy.
Do you really need the exact output ? I need to reflash my box then
..... if needed i would do so.
regards,
Simon
Am 11.02.2019 um 14:44 schrieb Jose Abreu:
> Hello,
>
> On 2/9/2019 1:09 AM, Martin Blumenstingl wrote:
>> (it's interesting that the sending direction has 445 retries)
> I saw this before and I think it was related with COE. Can you
> please disable all offloading and try again?
>
> Anyway, maybe Simon should bissect ? I think since 4.14 there are
> not that many commits in stmmac / meson8b-dwmac that can cause
> this behavior.
>
> Thanks,
> Jose Miguel Abreu
^ permalink raw reply
* Re: [PATCH net-next 1/2] net: phy: marvell: add new m88e1510 LED configuration
From: shenjian (K) @ 2019-02-14 7:24 UTC (permalink / raw)
To: Florian Fainelli, andrew, hkallweit1, davem
Cc: netdev, linux-kernel, linuxarm
In-Reply-To: <da37103d-ad41-7e27-bd6e-3a402bbaf096@gmail.com>
在 2019/2/14 12:06, Florian Fainelli 写道:
>
>
> On 2/13/2019 8:31 PM, Jian Shen wrote:
>> The default m88e1510 LED configuration is 0x1177, used LED[0]
>> for 1000M link, LED[1] for 100M link, and LED[2] for active.
>> But for our boards, we want to use 0x1040, which use LED[0] for
>> link, and LED[1] for active.
>>
>> This patch adds a new m88e1510 LED configuration for it.
>
> There appears to be a precedent with the DNS323 flag that was defined
> for the same purpose, but this unfortunately does not scale we cannot
> have every new platform come up with its own LED configuration without
> having a more structured approach to representing the LED configuration.
>
> Maybe we can encode the desired LED behavior in a more generic way and
> utilize the 32 flag bits available to denote a selection, e.g.:
>
> MARVELL_PHY_FLAG_LED0_100M BIT(3)
> MARVELL_PHY_FLAG_LED0_1000M BIT(4)
>
> etc.
>
> or maybe even better would be to expose the LEDs using the standard LEDs
> class subsystem and allow configuring different triggers. We have some
> amount of support for PHY LEDs already in tree, but AFAIR what we do not
> have support for is a "hardware blinking" trigger which those LEDs are.
>
Thanks Florian.
I agree that we should use a generic way.
Maybe I understood incorrectly, for "utilize the 32 flag bits available to denote a selection",
do you mean to define a serial flags for each usage of each led ?
For each led can be configured to several usages, include link/10M link/100M link/1000M link/active/...,
it needs a lot bits for these combination, e.g:
#define MARVELL_PHY_FLAG_LED0_LINK BIT(2)
#define MARVELL_PHY_FLAG_LED0_LINK_100M BIT(3)
#define MARVELL_PHY_FLAG_LED0_LINK_1000M BIT(4)
#define MARVELL_PHY_FLAG_LED0_ACTIVE BIT(5)
#define MARVELL_PHY_FLAG_LED1_LINK BIT(6)
#define MARVELL_PHY_FLAG_LED1_LINK_100M BIT(7)
#define MARVELL_PHY_FLAG_LED1_LINK_1000M BIT(8)
#define MARVELL_PHY_FLAG_LED1_ACTIVE BIT(9)
...
Jian Shen
>>
>> Signed-off-by: Jian Shen <shenjian15@huawei.com>
>> ---
>> drivers/net/phy/marvell.c | 22 +++++++++++++++++++++-
>> include/linux/marvell_phy.h | 1 +
>> 2 files changed, 22 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/net/phy/marvell.c b/drivers/net/phy/marvell.c
>> index 3ccba37..c195286 100644
>> --- a/drivers/net/phy/marvell.c
>> +++ b/drivers/net/phy/marvell.c
>> @@ -128,6 +128,10 @@
>> #define MII_PHY_LED_CTRL 16
>> #define MII_88E1121_PHY_LED_DEF 0x0030
>> #define MII_88E1510_PHY_LED_DEF 0x1177
>> +#define MII_88E1510_PHY_HNS3_LED_DEF 0x1040
>> +
>> +#define MII_88E1510_PHY_LED_POLARITY_CTRL 0x11
>> +#define MII_88E1510_PHY_HNS3_LED_POLARITY 0x4415
>>
>> #define MII_M1011_PHY_STATUS 0x11
>> #define MII_M1011_PHY_STATUS_1000 0x8000
>> @@ -619,12 +623,19 @@ static void marvell_config_led(struct phy_device *phydev)
>> def_config = MII_88E1121_PHY_LED_DEF;
>> break;
>> /* Default PHY LED config:
>> + * For hns3:
>> + * LED[0] .. Link
>> + * LED[1] .. Activity
>> + * For others:
>> * LED[0] .. 1000Mbps Link
>> * LED[1] .. 100Mbps Link
>> * LED[2] .. Blink, Activity
>> */
>> case MARVELL_PHY_FAMILY_ID(MARVELL_PHY_ID_88E1510):
>> - def_config = MII_88E1510_PHY_LED_DEF;
>> + if (phydev->dev_flags & MARVELL_PHY_M1510_HNS3_LEDS)
>> + def_config = MII_88E1510_PHY_HNS3_LED_DEF;
>> + else
>> + def_config = MII_88E1510_PHY_LED_DEF;
>> break;
>> default:
>> return;
>> @@ -634,6 +645,15 @@ static void marvell_config_led(struct phy_device *phydev)
>> def_config);
>> if (err < 0)
>> phydev_warn(phydev, "Fail to config marvell phy LED.\n");
>> +
>> + if (phydev->dev_flags & MARVELL_PHY_M1510_HNS3_LEDS) {
>> + err = phy_write_paged(phydev, MII_MARVELL_LED_PAGE,
>> + MII_88E1510_PHY_LED_POLARITY_CTRL,
>> + MII_88E1510_PHY_HNS3_LED_POLARITY);
>> + if (err < 0)
>> + phydev_warn(phydev,
>> + "Fail to config marvell phy LED polarity.\n");
>> + }
>> }
>>
>> static int marvell_config_init(struct phy_device *phydev)
>> diff --git a/include/linux/marvell_phy.h b/include/linux/marvell_phy.h
>> index 1eb6f24..99e0bbb 100644
>> --- a/include/linux/marvell_phy.h
>> +++ b/include/linux/marvell_phy.h
>> @@ -32,5 +32,6 @@
>> /* struct phy_device dev_flags definitions */
>> #define MARVELL_PHY_M1145_FLAGS_RESISTANCE 0x00000001
>> #define MARVELL_PHY_M1118_DNS323_LEDS 0x00000002
>> +#define MARVELL_PHY_M1510_HNS3_LEDS 0x00000004
>>
>> #endif /* _MARVELL_PHY_H */
>>
>
^ permalink raw reply
* Re: [PATCH net-next 2/2] net: hns3: add fixup handle for hns3 driver
From: shenjian (K) @ 2019-02-14 7:25 UTC (permalink / raw)
To: Florian Fainelli, andrew, hkallweit1, davem
Cc: netdev, linux-kernel, linuxarm
In-Reply-To: <a9086c2f-9d15-b3d0-9809-44385d6281ff@gmail.com>
在 2019/2/14 12:08, Florian Fainelli 写道:
>
>
> On 2/13/2019 8:31 PM, Jian Shen wrote:
>> The default led configuration of marvell 88E1510 is not fit
>> for hns3 driver, this patch fixes it.
>>
>> Signed-off-by: Jian Shen <shenjian15@huawei.com>
>> ---
>> .../net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.c | 19 +++++++++++++++++++
>> 1 file changed, 19 insertions(+)
>>
>> diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.c
>> index 84f2878..4c8346e 100644
>> --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.c
>> +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.c
>> @@ -2,6 +2,7 @@
>> // Copyright (c) 2016-2017 Hisilicon Limited.
>>
>> #include <linux/etherdevice.h>
>> +#include <linux/marvell_phy.h>
>> #include <linux/kernel.h>
>>
>> #include "hclge_cmd.h"
>> @@ -125,6 +126,13 @@ static int hclge_mdio_read(struct mii_bus *bus, int phyid, int regnum)
>> return le16_to_cpu(mdio_cmd->data_rd);
>> }
>>
>> +static int hclge_phy_marvell_fixup(struct phy_device *phydev)
>> +{
>> + phydev->dev_flags |= MARVELL_PHY_M1510_HNS3_LEDS;
>> +
>> + return 0;
>> +}
>> +
>> int hclge_mac_mdio_config(struct hclge_dev *hdev)
>> {
>> struct hclge_mac *mac = &hdev->hw.mac;
>> @@ -168,6 +176,15 @@ int hclge_mac_mdio_config(struct hclge_dev *hdev)
>> mac->phydev = phydev;
>> mac->mdio_bus = mdio_bus;
>>
>> + /* register the PHY board fixup (for Marvell 88E1510) */
>> + ret = phy_register_fixup_for_uid(MARVELL_PHY_ID_88E1510,
>> + MARVELL_PHY_ID_MASK,
>> + hclge_phy_marvell_fixup);
>> + /* we can live without it, so just issue a warning */
>> + if (ret)
>> + dev_warn(&hdev->pdev->dev,
>> + "Cannot register PHY board fixup\n");
>
> You don't need to register a fixup for passing your flags, you can do
> that at the time you attach to the PHY:
>
> https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/include/linux/phy.h#n945
>
>
Thanks, will fix it in next version.
>> +
>> return 0;
>> }
>>
>> @@ -240,6 +257,8 @@ void hclge_mac_disconnect_phy(struct hnae3_handle *handle)
>> if (!phydev)
>> return;
>>
>> + phy_unregister_fixup_for_uid(MARVELL_PHY_ID_88E1510,
>> + MARVELL_PHY_ID_MASK);
>> phy_disconnect(phydev);
>> }
>>
>>
>
^ permalink raw reply
* [Bug reporting] kernel panic during handle the dst unreach icmp msg.
From: 배석진 @ 2019-02-14 7:46 UTC (permalink / raw)
To: netdev@vger.kernel.org; +Cc: 배석진, 박종언
In-Reply-To: <CGME20190214074641epcms1p1db1c5589f96718a440a166328eec9ebd@epcms1p1>
Dear all,
https://www.mail-archive.com/netdev@vger.kernel.org/msg256527.html
as we concerned before at above mail thread,
we faced a problem cased by not removed socket.
(from now, 'the socket' means the socket alloced at 0xFFFFFFC0051E5E00)
#1. the socket is state in TIME_WAIT1. maybe it's process closed the socket.
below is memory dump information with Trace32.
(struct sock *)0xFFFFFFC0051E5E00 = 0xFFFFFFC0051E5E00 = end+0x3FF9E4CE00 -> (
__sk_common = (
...
skc_rcv_saddr = 0x0200A8C0, ==> 192.168.0.2
...
skc_state = 4, ==> TIME_WAIT1
...
skc_flags = 0x4301, ==> SOCK_DEAD(0x01) set
#2. user changed WIFI AP to another one, so previous netdevice deleted and destroied it's sockets.
[60392.948657][4: netd] 02-13 00:39:32.095 5249 5323 I NetdDestroyed 30 sockets on 192.168.0.2 in 2.7 ms
[60392.948705][4: netd] 02-13 00:39:32.095 5249 5323 D Netdnotify() code: 614, msg: Address removed 192.168.0.2/24 wlan0 128 0
--> the socket will be exist for a while.
because of 'sock_diag_destory() -> tcp_abort()' can not call tcp_done() for the socket.
but clearing the socket's sk_write_queue by calling tcp_write_queue_purge(sk).
#3. icmp msg(dst unreach) came for sent packet by the socket.
to retransmit them, lookup sk and fint it. (because the socket still exist)
but it's sk_write_queue was already cleared so has no skb to send.
and make the kernel bug.
<4>[60392.948306] I[1: ksoftirqd/1: 19] ------------[ cut here ]------------
<0>[60392.948334] I[1: ksoftirqd/1: 19] kernel BUG at net/ipv4/tcp_ipv4.c:519!
<2>[60392.948344] I[1: ksoftirqd/1: 19] sec_debug_set_extra_info_fault = BUG / 0xffffff80090351d0
<0>[60392.948386] I[1: ksoftirqd/1: 19] Internal error: Oops - BUG: 0 [#1] PREEMPT SMP
...
<4>[60392.950676] I[1: ksoftirqd/1: 19] PC is at tcp_v4_err+0x4b0/0x4bc
<4>[60392.950684] I[1: ksoftirqd/1: 19] LR is at tcp_v4_err+0x3ac/0x4bc
370 void tcp_v4_err(struct sk_buff *icmp_skb, u32 info)
371 {
...
516 icsk->icsk_rto = inet_csk_rto_backoff(icsk, TCP_RTO_MAX);
517
518 skb = tcp_write_queue_head(sk);
519 BUG_ON(!skb);
520
521 tcp_mstamp_refresh(tp);
we know that the line 519 removed on latest state. instead this will be shown to kernel panic.
how about below change? do not retransmit packets when socket was already closed.
best regards,
From: soukjin bae <soukjin.bae@samsung.com>
Date: Wen, 14 Jan 2019 14:26:35 +0900
Subject: net: Don't retransmit packets when socket was already closed
Signed-off-by: soukjin bae <soukjin.bae@samsung.com>
Signed-off-by: jongeon park <jongeon.park@samsung.com>
---
net/ipv4/tcp_ipv4 | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/net/ipv4/tcp_ipv4 b/net/ipv4/tcp_ipv4
index fe4daf6..654bd19 100755
--- a/net/ipv4/tcp_ipv4
+++ b/net/ipv4/tcp_ipv4
@@ -442,6 +465,10 @@ void tcp_v4_err(struct sk_buff *icmp_skb, u32 info)
err = EPROTO;
break;
case ICMP_DEST_UNREACH:
+ /* Don't retransmit packets when socket was already closed */
+ if (sock_flag(sk, SOCK_DEAD))
+ goto out;
+
if (code > NR_ICMP_UNREACH)
goto out;
^ permalink raw reply
* [PATCH net-next 10/12] net: sched: flower: protect flower classifier state with spinlock
From: Vlad Buslov @ 2019-02-14 7:47 UTC (permalink / raw)
To: netdev; +Cc: jhs, xiyou.wangcong, jiri, davem, Vlad Buslov
In-Reply-To: <20190214074712.17846-1-vladbu@mellanox.com>
struct tcf_proto was extended with spinlock to be used by classifiers
instead of global rtnl lock. Use it to protect shared flower classifier
data structures (handle_idr, mask hashtable and list) and fields of
individual filters that can be accessed concurrently. This patch set uses
tcf_proto->lock as per instance lock that protects all filters on
tcf_proto.
Signed-off-by: Vlad Buslov <vladbu@mellanox.com>
Acked-by: Jiri Pirko <jiri@mellanox.com>
---
net/sched/cls_flower.c | 36 ++++++++++++++++++++++++++++++------
1 file changed, 30 insertions(+), 6 deletions(-)
diff --git a/net/sched/cls_flower.c b/net/sched/cls_flower.c
index bfef7d6c597d..556f7a1c694a 100644
--- a/net/sched/cls_flower.c
+++ b/net/sched/cls_flower.c
@@ -384,7 +384,9 @@ static void fl_hw_destroy_filter(struct tcf_proto *tp, struct cls_fl_filter *f,
cls_flower.cookie = (unsigned long) f;
tc_setup_cb_call(block, TC_SETUP_CLSFLOWER, &cls_flower, false);
+ spin_lock(&tp->lock);
tcf_block_offload_dec(block, &f->flags);
+ spin_unlock(&tp->lock);
}
static int fl_hw_replace_filter(struct tcf_proto *tp,
@@ -422,7 +424,9 @@ static int fl_hw_replace_filter(struct tcf_proto *tp,
return err;
} else if (err > 0) {
f->in_hw_count = err;
+ spin_lock(&tp->lock);
tcf_block_offload_inc(block, &f->flags);
+ spin_unlock(&tp->lock);
}
if (skip_sw && !(f->flags & TCA_CLS_FLAGS_IN_HW))
@@ -510,18 +514,22 @@ static int __fl_delete(struct tcf_proto *tp, struct cls_fl_filter *f,
(*last) = false;
+ spin_lock(&tp->lock);
if (!f->deleted) {
f->deleted = true;
rhashtable_remove_fast(&f->mask->ht, &f->ht_node,
f->mask->filter_ht_params);
idr_remove(&head->handle_idr, f->handle);
list_del_rcu(&f->list);
+ spin_unlock(&tp->lock);
+
(*last) = fl_mask_put(head, f->mask, async);
if (!tc_skip_hw(f->flags))
fl_hw_destroy_filter(tp, f, extack);
tcf_unbind_filter(tp, &f->res);
__fl_put(f);
} else {
+ spin_unlock(&tp->lock);
err = -ENOENT;
}
@@ -1497,6 +1505,8 @@ static int fl_change(struct net *net, struct sk_buff *in_skb,
if (!tc_in_hw(fnew->flags))
fnew->flags |= TCA_CLS_FLAGS_NOT_IN_HW;
+ spin_lock(&tp->lock);
+
/* tp was deleted concurrently. EAGAIN will cause caller to lookup proto
* again or create new one, if necessary.
*/
@@ -1527,6 +1537,8 @@ static int fl_change(struct net *net, struct sk_buff *in_skb,
list_replace_rcu(&fold->list, &fnew->list);
fold->deleted = true;
+ spin_unlock(&tp->lock);
+
fl_mask_put(head, fold->mask, true);
if (!tc_skip_hw(fold->flags))
fl_hw_destroy_filter(tp, fold, NULL);
@@ -1571,6 +1583,7 @@ static int fl_change(struct net *net, struct sk_buff *in_skb,
goto errout_idr;
list_add_tail_rcu(&fnew->list, &fnew->mask->filters);
+ spin_unlock(&tp->lock);
}
*arg = fnew;
@@ -1583,6 +1596,7 @@ static int fl_change(struct net *net, struct sk_buff *in_skb,
if (!fold)
idr_remove(&head->handle_idr, fnew->handle);
errout_hw:
+ spin_unlock(&tp->lock);
if (!tc_skip_hw(fnew->flags))
fl_hw_destroy_filter(tp, fnew, NULL);
errout_mask:
@@ -1681,8 +1695,10 @@ static int fl_reoffload(struct tcf_proto *tp, bool add, tc_setup_cb_t *cb,
continue;
}
+ spin_lock(&tp->lock);
tc_cls_offload_cnt_update(block, &f->in_hw_count,
&f->flags, add);
+ spin_unlock(&tp->lock);
}
}
@@ -2216,6 +2232,7 @@ static int fl_dump(struct net *net, struct tcf_proto *tp, void *fh,
struct cls_fl_filter *f = fh;
struct nlattr *nest;
struct fl_flow_key *key, *mask;
+ bool skip_hw;
if (!f)
return skb->len;
@@ -2226,21 +2243,26 @@ static int fl_dump(struct net *net, struct tcf_proto *tp, void *fh,
if (!nest)
goto nla_put_failure;
+ spin_lock(&tp->lock);
+
if (f->res.classid &&
nla_put_u32(skb, TCA_FLOWER_CLASSID, f->res.classid))
- goto nla_put_failure;
+ goto nla_put_failure_locked;
key = &f->key;
mask = &f->mask->key;
+ skip_hw = tc_skip_hw(f->flags);
if (fl_dump_key(skb, net, key, mask))
- goto nla_put_failure;
-
- if (!tc_skip_hw(f->flags))
- fl_hw_update_stats(tp, f);
+ goto nla_put_failure_locked;
if (f->flags && nla_put_u32(skb, TCA_FLOWER_FLAGS, f->flags))
- goto nla_put_failure;
+ goto nla_put_failure_locked;
+
+ spin_unlock(&tp->lock);
+
+ if (!skip_hw)
+ fl_hw_update_stats(tp, f);
if (nla_put_u32(skb, TCA_FLOWER_IN_HW_COUNT, f->in_hw_count))
goto nla_put_failure;
@@ -2255,6 +2277,8 @@ static int fl_dump(struct net *net, struct tcf_proto *tp, void *fh,
return skb->len;
+nla_put_failure_locked:
+ spin_unlock(&tp->lock);
nla_put_failure:
nla_nest_cancel(skb, nest);
return -1;
--
2.13.6
^ permalink raw reply related
* [PATCH net-next 02/12] net: sched: flower: refactor fl_change
From: Vlad Buslov @ 2019-02-14 7:47 UTC (permalink / raw)
To: netdev; +Cc: jhs, xiyou.wangcong, jiri, davem, Vlad Buslov
In-Reply-To: <20190214074712.17846-1-vladbu@mellanox.com>
As a preparation for using classifier spinlock instead of relying on
external rtnl lock, rearrange code in fl_change. The goal is to group the
code which changes classifier state in single block in order to allow
following commits in this set to protect it from parallel modification with
tp->lock. Data structures that require tp->lock protection are mask
hashtable and filters list, and classifier handle_idr.
fl_hw_replace_filter() is a sleeping function and cannot be called while
holding a spinlock. In order to execute all sequence of changes to shared
classifier data structures atomically, call fl_hw_replace_filter() before
modifying them.
Signed-off-by: Vlad Buslov <vladbu@mellanox.com>
Acked-by: Jiri Pirko <jiri@mellanox.com>
---
net/sched/cls_flower.c | 85 ++++++++++++++++++++++++++------------------------
1 file changed, 44 insertions(+), 41 deletions(-)
diff --git a/net/sched/cls_flower.c b/net/sched/cls_flower.c
index 88d7af78ba7e..91596a6271f8 100644
--- a/net/sched/cls_flower.c
+++ b/net/sched/cls_flower.c
@@ -1354,90 +1354,93 @@ static int fl_change(struct net *net, struct sk_buff *in_skb,
if (err < 0)
goto errout;
- if (!handle) {
- handle = 1;
- err = idr_alloc_u32(&head->handle_idr, fnew, &handle,
- INT_MAX, GFP_KERNEL);
- } else if (!fold) {
- /* user specifies a handle and it doesn't exist */
- err = idr_alloc_u32(&head->handle_idr, fnew, &handle,
- handle, GFP_KERNEL);
- }
- if (err)
- goto errout;
- fnew->handle = handle;
-
if (tb[TCA_FLOWER_FLAGS]) {
fnew->flags = nla_get_u32(tb[TCA_FLOWER_FLAGS]);
if (!tc_flags_valid(fnew->flags)) {
err = -EINVAL;
- goto errout_idr;
+ goto errout;
}
}
err = fl_set_parms(net, tp, fnew, mask, base, tb, tca[TCA_RATE], ovr,
tp->chain->tmplt_priv, extack);
if (err)
- goto errout_idr;
+ goto errout;
err = fl_check_assign_mask(head, fnew, fold, mask);
if (err)
- goto errout_idr;
-
- if (!fold && __fl_lookup(fnew->mask, &fnew->mkey)) {
- err = -EEXIST;
- goto errout_mask;
- }
-
- err = rhashtable_insert_fast(&fnew->mask->ht, &fnew->ht_node,
- fnew->mask->filter_ht_params);
- if (err)
- goto errout_mask;
+ goto errout;
if (!tc_skip_hw(fnew->flags)) {
err = fl_hw_replace_filter(tp, fnew, extack);
if (err)
- goto errout_mask_ht;
+ goto errout_mask;
}
if (!tc_in_hw(fnew->flags))
fnew->flags |= TCA_CLS_FLAGS_NOT_IN_HW;
if (fold) {
+ fnew->handle = handle;
+
+ err = rhashtable_insert_fast(&fnew->mask->ht, &fnew->ht_node,
+ fnew->mask->filter_ht_params);
+ if (err)
+ goto errout_hw;
+
rhashtable_remove_fast(&fold->mask->ht,
&fold->ht_node,
fold->mask->filter_ht_params);
- if (!tc_skip_hw(fold->flags))
- fl_hw_destroy_filter(tp, fold, NULL);
- }
-
- *arg = fnew;
-
- if (fold) {
idr_replace(&head->handle_idr, fnew, fnew->handle);
list_replace_rcu(&fold->list, &fnew->list);
+
+ if (!tc_skip_hw(fold->flags))
+ fl_hw_destroy_filter(tp, fold, NULL);
tcf_unbind_filter(tp, &fold->res);
tcf_exts_get_net(&fold->exts);
tcf_queue_work(&fold->rwork, fl_destroy_filter_work);
} else {
+ if (__fl_lookup(fnew->mask, &fnew->mkey)) {
+ err = -EEXIST;
+ goto errout_hw;
+ }
+
+ if (handle) {
+ /* user specifies a handle and it doesn't exist */
+ err = idr_alloc_u32(&head->handle_idr, fnew, &handle,
+ handle, GFP_ATOMIC);
+ } else {
+ handle = 1;
+ err = idr_alloc_u32(&head->handle_idr, fnew, &handle,
+ INT_MAX, GFP_ATOMIC);
+ }
+ if (err)
+ goto errout_hw;
+ fnew->handle = handle;
+
+ err = rhashtable_insert_fast(&fnew->mask->ht, &fnew->ht_node,
+ fnew->mask->filter_ht_params);
+ if (err)
+ goto errout_idr;
+
list_add_tail_rcu(&fnew->list, &fnew->mask->filters);
}
+ *arg = fnew;
+
kfree(tb);
kfree(mask);
return 0;
-errout_mask_ht:
- rhashtable_remove_fast(&fnew->mask->ht, &fnew->ht_node,
- fnew->mask->filter_ht_params);
-
-errout_mask:
- fl_mask_put(head, fnew->mask, false);
-
errout_idr:
if (!fold)
idr_remove(&head->handle_idr, fnew->handle);
+errout_hw:
+ if (!tc_skip_hw(fnew->flags))
+ fl_hw_destroy_filter(tp, fnew, NULL);
+errout_mask:
+ fl_mask_put(head, fnew->mask, false);
errout:
tcf_exts_destroy(&fnew->exts);
kfree(fnew);
--
2.13.6
^ permalink raw reply related
* [PATCH net-next 04/12] net: sched: flower: track filter deletion with flag
From: Vlad Buslov @ 2019-02-14 7:47 UTC (permalink / raw)
To: netdev; +Cc: jhs, xiyou.wangcong, jiri, davem, Vlad Buslov
In-Reply-To: <20190214074712.17846-1-vladbu@mellanox.com>
In order to prevent double deletion of filter by concurrent tasks when rtnl
lock is not used for synchronization, add 'deleted' filter field. Check
value of this field when modifying filters and return error if concurrent
deletion is detected.
Refactor __fl_delete() to accept pointer to 'last' boolean as argument,
and return error code as function return value instead. This is necessary
to signal concurrent filter delete to caller.
Signed-off-by: Vlad Buslov <vladbu@mellanox.com>
Acked-by: Jiri Pirko <jiri@mellanox.com>
---
net/sched/cls_flower.c | 55 ++++++++++++++++++++++++++++++++++----------------
1 file changed, 38 insertions(+), 17 deletions(-)
diff --git a/net/sched/cls_flower.c b/net/sched/cls_flower.c
index b216ed26f344..fa5465f890e1 100644
--- a/net/sched/cls_flower.c
+++ b/net/sched/cls_flower.c
@@ -110,6 +110,7 @@ struct cls_fl_filter {
* synchronization. Use atomic reference counter to be concurrency-safe.
*/
refcount_t refcnt;
+ bool deleted;
};
static const struct rhashtable_params mask_ht_params = {
@@ -454,6 +455,8 @@ static void __fl_put(struct cls_fl_filter *f)
if (!refcount_dec_and_test(&f->refcnt))
return;
+ WARN_ON(!f->deleted);
+
if (tcf_exts_get_net(&f->exts))
tcf_queue_work(&f->rwork, fl_destroy_filter_work);
else
@@ -490,22 +493,31 @@ static struct cls_fl_filter *fl_get_next_filter(struct tcf_proto *tp,
return f;
}
-static bool __fl_delete(struct tcf_proto *tp, struct cls_fl_filter *f,
- struct netlink_ext_ack *extack)
+static int __fl_delete(struct tcf_proto *tp, struct cls_fl_filter *f,
+ bool *last, struct netlink_ext_ack *extack)
{
struct cls_fl_head *head = fl_head_dereference(tp);
bool async = tcf_exts_get_net(&f->exts);
- bool last;
-
- idr_remove(&head->handle_idr, f->handle);
- list_del_rcu(&f->list);
- last = fl_mask_put(head, f->mask, async);
- if (!tc_skip_hw(f->flags))
- fl_hw_destroy_filter(tp, f, extack);
- tcf_unbind_filter(tp, &f->res);
- __fl_put(f);
+ int err = 0;
+
+ (*last) = false;
+
+ if (!f->deleted) {
+ f->deleted = true;
+ rhashtable_remove_fast(&f->mask->ht, &f->ht_node,
+ f->mask->filter_ht_params);
+ idr_remove(&head->handle_idr, f->handle);
+ list_del_rcu(&f->list);
+ (*last) = fl_mask_put(head, f->mask, async);
+ if (!tc_skip_hw(f->flags))
+ fl_hw_destroy_filter(tp, f, extack);
+ tcf_unbind_filter(tp, &f->res);
+ __fl_put(f);
+ } else {
+ err = -ENOENT;
+ }
- return last;
+ return err;
}
static void fl_destroy_sleepable(struct work_struct *work)
@@ -525,10 +537,12 @@ static void fl_destroy(struct tcf_proto *tp, bool rtnl_held,
struct cls_fl_head *head = fl_head_dereference(tp);
struct fl_flow_mask *mask, *next_mask;
struct cls_fl_filter *f, *next;
+ bool last;
list_for_each_entry_safe(mask, next_mask, &head->masks, list) {
list_for_each_entry_safe(f, next, &mask->filters, list) {
- if (__fl_delete(tp, f, extack))
+ __fl_delete(tp, f, &last, extack);
+ if (last)
break;
}
}
@@ -1439,6 +1453,12 @@ static int fl_change(struct net *net, struct sk_buff *in_skb,
refcount_inc(&fnew->refcnt);
if (fold) {
+ /* Fold filter was deleted concurrently. Retry lookup. */
+ if (fold->deleted) {
+ err = -EAGAIN;
+ goto errout_hw;
+ }
+
fnew->handle = handle;
err = rhashtable_insert_fast(&fnew->mask->ht, &fnew->ht_node,
@@ -1451,6 +1471,7 @@ static int fl_change(struct net *net, struct sk_buff *in_skb,
fold->mask->filter_ht_params);
idr_replace(&head->handle_idr, fnew, fnew->handle);
list_replace_rcu(&fold->list, &fnew->list);
+ fold->deleted = true;
if (!tc_skip_hw(fold->flags))
fl_hw_destroy_filter(tp, fold, NULL);
@@ -1520,14 +1541,14 @@ static int fl_delete(struct tcf_proto *tp, void *arg, bool *last,
{
struct cls_fl_head *head = fl_head_dereference(tp);
struct cls_fl_filter *f = arg;
+ bool last_on_mask;
+ int err = 0;
- rhashtable_remove_fast(&f->mask->ht, &f->ht_node,
- f->mask->filter_ht_params);
- __fl_delete(tp, f, extack);
+ err = __fl_delete(tp, f, &last_on_mask, extack);
*last = list_empty(&head->masks);
__fl_put(f);
- return 0;
+ return err;
}
static void fl_walk(struct tcf_proto *tp, struct tcf_walker *arg,
--
2.13.6
^ permalink raw reply related
* [PATCH net-next 07/12] net: sched: flower: protect masks list with spinlock
From: Vlad Buslov @ 2019-02-14 7:47 UTC (permalink / raw)
To: netdev; +Cc: jhs, xiyou.wangcong, jiri, davem, Vlad Buslov
In-Reply-To: <20190214074712.17846-1-vladbu@mellanox.com>
Protect modifications of flower masks list with spinlock to remove
dependency on rtnl lock and allow concurrent access.
Signed-off-by: Vlad Buslov <vladbu@mellanox.com>
Acked-by: Jiri Pirko <jiri@mellanox.com>
---
net/sched/cls_flower.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/net/sched/cls_flower.c b/net/sched/cls_flower.c
index 2b032303f8d5..fc6371a9b0f9 100644
--- a/net/sched/cls_flower.c
+++ b/net/sched/cls_flower.c
@@ -88,6 +88,7 @@ struct fl_flow_tmplt {
struct cls_fl_head {
struct rhashtable ht;
+ spinlock_t masks_lock; /* Protect masks list */
struct list_head masks;
struct rcu_work rwork;
struct idr handle_idr;
@@ -312,6 +313,7 @@ static int fl_init(struct tcf_proto *tp)
if (!head)
return -ENOBUFS;
+ spin_lock_init(&head->masks_lock);
INIT_LIST_HEAD_RCU(&head->masks);
rcu_assign_pointer(tp->root, head);
idr_init(&head->handle_idr);
@@ -341,7 +343,11 @@ static bool fl_mask_put(struct cls_fl_head *head, struct fl_flow_mask *mask,
return false;
rhashtable_remove_fast(&head->ht, &mask->ht_node, mask_ht_params);
+
+ spin_lock(&head->masks_lock);
list_del_rcu(&mask->list);
+ spin_unlock(&head->masks_lock);
+
if (async)
tcf_queue_work(&mask->rwork, fl_mask_free_work);
else
@@ -1309,7 +1315,9 @@ static struct fl_flow_mask *fl_create_new_mask(struct cls_fl_head *head,
/* Wait until any potential concurrent users of mask are finished */
synchronize_rcu();
+ spin_lock(&head->masks_lock);
list_add_tail_rcu(&newmask->list, &head->masks);
+ spin_unlock(&head->masks_lock);
return newmask;
--
2.13.6
^ permalink raw reply related
* [PATCH net-next 09/12] net: sched: flower: handle concurrent tcf proto deletion
From: Vlad Buslov @ 2019-02-14 7:47 UTC (permalink / raw)
To: netdev; +Cc: jhs, xiyou.wangcong, jiri, davem, Vlad Buslov
In-Reply-To: <20190214074712.17846-1-vladbu@mellanox.com>
Without rtnl lock protection tcf proto can be deleted concurrently. Check
tcf proto 'deleting' flag after taking tcf spinlock to verify that no
concurrent deletion is in progress. Return EAGAIN error if concurrent
deletion detected, which will cause caller to retry and possibly create new
instance of tcf proto.
Signed-off-by: Vlad Buslov <vladbu@mellanox.com>
Acked-by: Jiri Pirko <jiri@mellanox.com>
---
net/sched/cls_flower.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/net/sched/cls_flower.c b/net/sched/cls_flower.c
index 114cb7876133..bfef7d6c597d 100644
--- a/net/sched/cls_flower.c
+++ b/net/sched/cls_flower.c
@@ -1497,6 +1497,14 @@ static int fl_change(struct net *net, struct sk_buff *in_skb,
if (!tc_in_hw(fnew->flags))
fnew->flags |= TCA_CLS_FLAGS_NOT_IN_HW;
+ /* tp was deleted concurrently. EAGAIN will cause caller to lookup proto
+ * again or create new one, if necessary.
+ */
+ if (tp->deleting) {
+ err = -EAGAIN;
+ goto errout_hw;
+ }
+
refcount_inc(&fnew->refcnt);
if (fold) {
/* Fold filter was deleted concurrently. Retry lookup. */
--
2.13.6
^ permalink raw reply related
* [PATCH net-next 01/12] net: sched: flower: don't check for rtnl on head dereference
From: Vlad Buslov @ 2019-02-14 7:47 UTC (permalink / raw)
To: netdev; +Cc: jhs, xiyou.wangcong, jiri, davem, Vlad Buslov
In-Reply-To: <20190214074712.17846-1-vladbu@mellanox.com>
Flower classifier only changes root pointer during init and destroy. Cls
API implements reference counting for tcf_proto, so there is no danger of
concurrent access to tp when it is being destroyed, even without protection
provided by rtnl lock.
Implement new function fl_head_dereference() to dereference tp->root
without checking for rtnl lock. Use it in all flower function that obtain
head pointer instead of rtnl_dereference().
Signed-off-by: Vlad Buslov <vladbu@mellanox.com>
Acked-by: Jiri Pirko <jiri@mellanox.com>
---
net/sched/cls_flower.c | 24 +++++++++++++++++-------
1 file changed, 17 insertions(+), 7 deletions(-)
diff --git a/net/sched/cls_flower.c b/net/sched/cls_flower.c
index 32fa3e20adc5..88d7af78ba7e 100644
--- a/net/sched/cls_flower.c
+++ b/net/sched/cls_flower.c
@@ -433,10 +433,20 @@ static void fl_hw_update_stats(struct tcf_proto *tp, struct cls_fl_filter *f)
cls_flower.stats.lastused);
}
+static struct cls_fl_head *fl_head_dereference(struct tcf_proto *tp)
+{
+ /* Flower classifier only changes root pointer during init and destroy.
+ * Cls API implements reference counting for tcf_proto, so there is no
+ * danger of concurrent access to tp when it is being destroyed, even
+ * without protection provided by rtnl lock.
+ */
+ return rcu_dereference_protected(tp->root, 1);
+}
+
static bool __fl_delete(struct tcf_proto *tp, struct cls_fl_filter *f,
struct netlink_ext_ack *extack)
{
- struct cls_fl_head *head = rtnl_dereference(tp->root);
+ struct cls_fl_head *head = fl_head_dereference(tp);
bool async = tcf_exts_get_net(&f->exts);
bool last;
@@ -468,7 +478,7 @@ static void fl_destroy_sleepable(struct work_struct *work)
static void fl_destroy(struct tcf_proto *tp, bool rtnl_held,
struct netlink_ext_ack *extack)
{
- struct cls_fl_head *head = rtnl_dereference(tp->root);
+ struct cls_fl_head *head = fl_head_dereference(tp);
struct fl_flow_mask *mask, *next_mask;
struct cls_fl_filter *f, *next;
@@ -486,7 +496,7 @@ static void fl_destroy(struct tcf_proto *tp, bool rtnl_held,
static void *fl_get(struct tcf_proto *tp, u32 handle)
{
- struct cls_fl_head *head = rtnl_dereference(tp->root);
+ struct cls_fl_head *head = fl_head_dereference(tp);
return idr_find(&head->handle_idr, handle);
}
@@ -1304,7 +1314,7 @@ static int fl_change(struct net *net, struct sk_buff *in_skb,
void **arg, bool ovr, bool rtnl_held,
struct netlink_ext_ack *extack)
{
- struct cls_fl_head *head = rtnl_dereference(tp->root);
+ struct cls_fl_head *head = fl_head_dereference(tp);
struct cls_fl_filter *fold = *arg;
struct cls_fl_filter *fnew;
struct fl_flow_mask *mask;
@@ -1441,7 +1451,7 @@ static int fl_change(struct net *net, struct sk_buff *in_skb,
static int fl_delete(struct tcf_proto *tp, void *arg, bool *last,
bool rtnl_held, struct netlink_ext_ack *extack)
{
- struct cls_fl_head *head = rtnl_dereference(tp->root);
+ struct cls_fl_head *head = fl_head_dereference(tp);
struct cls_fl_filter *f = arg;
rhashtable_remove_fast(&f->mask->ht, &f->ht_node,
@@ -1454,7 +1464,7 @@ static int fl_delete(struct tcf_proto *tp, void *arg, bool *last,
static void fl_walk(struct tcf_proto *tp, struct tcf_walker *arg,
bool rtnl_held)
{
- struct cls_fl_head *head = rtnl_dereference(tp->root);
+ struct cls_fl_head *head = fl_head_dereference(tp);
struct cls_fl_filter *f;
arg->count = arg->skip;
@@ -1473,7 +1483,7 @@ static void fl_walk(struct tcf_proto *tp, struct tcf_walker *arg,
static int fl_reoffload(struct tcf_proto *tp, bool add, tc_setup_cb_t *cb,
void *cb_priv, struct netlink_ext_ack *extack)
{
- struct cls_fl_head *head = rtnl_dereference(tp->root);
+ struct cls_fl_head *head = fl_head_dereference(tp);
struct tc_cls_flower_offload cls_flower = {};
struct tcf_block *block = tp->chain->block;
struct fl_flow_mask *mask;
--
2.13.6
^ 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