* Re: [RFT net-next v3 0/5] dwmac-meson8b: RGMII clock fixes for Meson8b
From: Emiliano Ingrassia @ 2017-12-29 12:04 UTC (permalink / raw)
To: Martin Blumenstingl
Cc: linus.luessing, Neil Armstrong, netdev, peppe.cavallaro,
alexandre.torgue, khilman, linux-amlogic, jbrunet
In-Reply-To: <CAFBinCDVRNKBTG0CHcmV9iJ9gb2VeODCfU6BO+dyRU6bVwkffg@mail.gmail.com>
[-- Attachment #1: Type: text/plain, Size: 8645 bytes --]
Hi Martin,
On Fri, Dec 29, 2017 at 08:48:54AM +0100, Martin Blumenstingl wrote:
> Hi Emiliano,
>
> On Fri, Dec 29, 2017 at 2:31 AM, Emiliano Ingrassia
> <ingrassia@epigenesys.com> wrote:
> > Hi Martin, Hi Dave,
> >
> > On Thu, Dec 28, 2017 at 11:21:23PM +0100, Martin Blumenstingl wrote:
> >> Hi Dave,
> >>
> >> please do not apply this series until it got a Tested-by from Emiliano.
> >>
> >>
> >> Hi Emiliano,
> >>
> >> you reported [0] that you couldn't get dwmac-meson8b to work on your
> >> Odroid-C1. With your findings (register dumps, clk_summary output, etc.)
> >> I think I was able to find a fix: it consists of two patches (which you
> >> find in this series)
> >>
> >> Unfortunately I don't have any Meson8b boards with RGMII PHY so I could
> >> only partially test this (I could only check if the clocks were
> >> calculated correctly when using a dummy 500002394Hz input clock instead
> >> of MPLL2).
> >>
> >> Could you please give this series a try and let me know about the
> >> results?
> >> You obviously still need your two "ARM: dts: meson8b" patches which
> >> - add the amlogic,meson8b-dwmac" compatible to meson8b.dtsi
> >> - enable Ethernet on the Odroid-C1
> >>
> >> When testing on Meson8b this also needs a fix for the MPLL clock driver:
> >> "clk: meson: mpll: use 64-bit maths in params_from_rate", see:
> >> https://patchwork.kernel.org/patch/10131677/
> >>
> >>
> >> I have tested this myself on a Khadas VIM (GXL SoC, internal RMII PHY)
> >> and a Khadas VIM2 (GXM SoC, external RGMII PHY). Both are still working
> >> fine (so let's hope that this also fixes your Meson8b issue :)).
> >>
> >>
> >> changes since v1 at [1]:
> >> - changed the subject of the cover-letter to indicate that this is all
> >> about the RGMII clock
> >> - added PATCH #1 which ensures that we don't unnecessarily change the
> >> parent clocks in RMII mode (and also makes the code easier to
> >> understand)
> >> - changed subject of PATCH #2 (formerly PATCH #1) to state that this
> >> is about the RGMII clock
> >> - added Jerome's Reviewed-by to PATCH #2 (formerly PATCH #1)
> >> - replaced PATCH #3 (formerly PATCH #2) with one that sets
> >> CLK_SET_RATE_PARENT on the mux and thus re-configures the MPLL2 clock
> >> on Meson8b correctly
> >>
> >> changes since v2 at [2]:
> >> - added PATCH #2 to make the following patch easier
> >> - Emiliano reported that there's currently another bug in the
> >> dwmac-meson8b driver which prevents it from working with RGMII PHYs on
> >> Meson8b: bit 10 of the PRG_ETH0 register is configures a clock gate
> >> (instead of a divide by 5 or divide by 10 clock divider). This has not
> >> been visible on GXBB and later due to the input clock which always led
> >> to a selection of "divide by 10" (which is done internally in the IP
> >> block, but the bit actually means "enable RGMII clock output").
> >> PATCH #3 was added to address this issue.
> >> - the commit message of PATCH #4 and #5 (formerly PATCH #2 and #3) were
> >> updated and the patch itself rebased because the m25_div clock was
> >> removed with the new PATCH #3 (so some of the statements were not
> >> valid anymore)
> >>
> >
> > Here is the clk_summary relative to ethernet on Odroid-C1+
> > with this new series applied:
> >
> > xtal 1 1 24000000 0 0
> > sys_pll 0 0 1200000000 0 0
> > cpu_clk 0 0 1200000000 0 0
> > vid_pll 0 0 732000000 0 0
> > fixed_pll 2 2 2550000000 0 0
> > mpll2 1 1 249999701 0 0
> > c9410000.ethernet#m250_sel 1 1 249999701 0 0
> > c9410000.ethernet#m250_div 1 1 249999701 0 0
> > c9410000.ethernet#fixed_div10 1 1 24999970 0 0
> > c9410000.ethernet#m25_en 1 1 24999970 0 0
> >
> > The ethernet prg0 register is set to 0x74A1 which should be correct with
> > respect to the information contained in the S805 SoC manual.
> > Actually, the ethernet is not yet fully functional.
> > Trying to ping the board, I can see ARP request from host to board using
> > tcpdump. However, the host can't see any response.
> great - we're getting closer!
>
> > Following the U-Boot value for prg0 register, which is 0x7d21, I also
> > tried to set bit 11. As expected, this did not have any influence.
> it *may* be something outside the PRG_ETH0 register than
> to confirm that: could you temporarily revert the last patch from this
> series ("net: stmmac: dwmac-meson8b: propagate rate changes to the
> parent clock")? this way MPLL2 will stay at ~500MHz and PRG_ETH0
> should be identical to what u-boot sets (apart from bit 11, but that
> is only relevant in RMII mode according to the datasheet)
>
Here is the clk_summary after your suggestion:
xtal 1 1 24000000 0 0
sys_pll 0 0 1200000000 0 0
cpu_clk 0 0 1200000000 0 0
vid_pll 0 0 732000000 0 0
fixed_pll 2 2 2550000000 0 0
mpll2 1 1 500002394 0 0
c9410000.ethernet#m250_sel 1 1 500002394 0 0
c9410000.ethernet#m250_div 1 1 166667465 0 0
c9410000.ethernet#fixed_div10 1 1 16666746 0 0
c9410000.ethernet#m25_en 1 1 16666746 0 0
which seems worse. Pinging the board, I still see ARP request/reply via
tcpdump. The host, however, can't see any.
> > Another thing that we should check is the "Ethernet Memory PD" (see S805
> > manual - sec. 5.4) register which bits 3-2 enable/disable ethernet
> > normal operation. However, those bits are already cleared by U-Boot.
> if the peripheral registers itself are configured correctly it's
> typically one of these issues:
> - gate clock not being enabled (can you confirm that you hav the
> "stmmaceth" with CLKID_ETH in the ethmac node?)
- yes, I have;
> - incorrect pinmux settings (as a hack I would remove all ethernet
> pinctrl properties/nodes from meson8b.dtsi and meson8b-odroidc1.dts.
> before booting the mainline kernel you'll need to use Ethernet from
> within u-boot once)
- tried; nothing changed;
> - incorrect TX delay (amlogic,tx-delay-ns = <2> should be defined in
> meson8b-odroidc1.dts, but the driver should auto-select that value if
> it's missing)
- defined as in odroid-c2 dts;
> - IP block being in some undefined state which can be brought back
> into a working state by adding the reset line (RESET_ETHERNET)
- I have it;
> - Ethernet PHY being in some undefined state can be brought back into
> a working state by adding the reset line (GPIOH_4, see
> meson-gxbb-odroidc2.dts how to use that)
- have it.
> - I have not seen that the power-domains ("Ethernet Memory PD") were a
> problem yet, but you already checked that
>
> maybe you can share your current .dts patch and a boot-log so others
> can have a look as well?
>
OK, no problem.
> > Thank you for the support.
> thank you for your patience as well, most people would have given up by now
>
> > Best regards,
> >
> > Emiliano
> >
> >>
> >> [0] http://lists.infradead.org/pipermail/linux-amlogic/2017-December/005596.html
> >> [1] http://lists.infradead.org/pipermail/linux-amlogic/2017-December/005848.html
> >> [2] http://lists.infradead.org/pipermail/linux-amlogic/2017-December/005861.html
> >>
> >>
> >> Martin Blumenstingl (5):
> >> net: stmmac: dwmac-meson8b: only configure the clocks in RGMII mode
> >> net: stmmac: dwmac-meson8b: simplify generating the clock names
> >> net: stmmac: dwmac-meson8b: fix internal RGMII clock configuration
> >> net: stmmac: dwmac-meson8b: fix setting the RGMII clock on Meson8b
> >> net: stmmac: dwmac-meson8b: propagate rate changes to the parent clock
> >>
> >> .../net/ethernet/stmicro/stmmac/dwmac-meson8b.c | 119 +++++++++++----------
> >> 1 file changed, 63 insertions(+), 56 deletions(-)
> >>
> >> --
> >> 2.15.1
> >>
>
>
> Regards
> Martin
>
Regards,
Emiliano
> _______________________________________________
> linux-amlogic mailing list
> linux-amlogic@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-amlogic
[-- Attachment #2: meson8b.dtsi --]
[-- Type: text/plain, Size: 7728 bytes --]
/*
* Copyright 2015 Endless Mobile, Inc.
* Author: Carlo Caione <carlo@endlessm.com>
*
* This file is dual-licensed: you can use it either under the terms
* of the GPL or the X11 license, at your option. Note that this dual
* licensing only applies to this file, and not this project as a
* whole.
*
* a) This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* Or, alternatively,
*
* b) Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#include <dt-bindings/clock/meson8b-clkc.h>
#include <dt-bindings/gpio/meson8b-gpio.h>
#include <dt-bindings/reset/amlogic,meson8b-reset.h>
#include <dt-bindings/reset/amlogic,meson8b-clkc-reset.h>
#include "meson.dtsi"
/ {
cpus {
#address-cells = <1>;
#size-cells = <0>;
cpu@200 {
device_type = "cpu";
compatible = "arm,cortex-a5";
next-level-cache = <&L2>;
reg = <0x200>;
enable-method = "amlogic,meson8b-smp";
resets = <&clkc CLKC_RESET_CPU0_SOFT_RESET>;
};
cpu@201 {
device_type = "cpu";
compatible = "arm,cortex-a5";
next-level-cache = <&L2>;
reg = <0x201>;
enable-method = "amlogic,meson8b-smp";
resets = <&clkc CLKC_RESET_CPU1_SOFT_RESET>;
};
cpu@202 {
device_type = "cpu";
compatible = "arm,cortex-a5";
next-level-cache = <&L2>;
reg = <0x202>;
enable-method = "amlogic,meson8b-smp";
resets = <&clkc CLKC_RESET_CPU2_SOFT_RESET>;
};
cpu@203 {
device_type = "cpu";
compatible = "arm,cortex-a5";
next-level-cache = <&L2>;
reg = <0x203>;
enable-method = "amlogic,meson8b-smp";
resets = <&clkc CLKC_RESET_CPU3_SOFT_RESET>;
};
};
reserved-memory {
#address-cells = <1>;
#size-cells = <1>;
ranges;
/* 2 MiB reserved for Hardware ROM Firmware? */
hwrom@0 {
reg = <0x0 0x200000>;
no-map;
};
};
scu@c4300000 {
compatible = "arm,cortex-a5-scu";
reg = <0xc4300000 0x100>;
};
}; /* end of / */
&aobus {
pmu: pmu@e0 {
compatible = "amlogic,meson8b-pmu", "syscon";
reg = <0xe0 0x18>;
};
pinctrl_aobus: pinctrl@84 {
compatible = "amlogic,meson8b-aobus-pinctrl";
reg = <0x84 0xc>;
#address-cells = <1>;
#size-cells = <1>;
ranges;
gpio_ao: ao-bank@14 {
reg = <0x14 0x4>,
<0x2c 0x4>,
<0x24 0x8>;
reg-names = "mux", "pull", "gpio";
gpio-controller;
#gpio-cells = <2>;
gpio-ranges = <&pinctrl_aobus 0 0 16>;
};
uart_ao_a_pins: uart_ao_a {
mux {
groups = "uart_tx_ao_a", "uart_rx_ao_a";
function = "uart_ao";
};
};
};
};
&cbus {
clkc: clock-controller@4000 {
#clock-cells = <1>;
#reset-cells = <1>;
compatible = "amlogic,meson8b-clkc";
reg = <0x8000 0x4>, <0x4000 0x460>;
};
reset: reset-controller@4404 {
compatible = "amlogic,meson8b-reset";
reg = <0x4404 0x20>;
#reset-cells = <1>;
};
analog_top: analog-top@81a8 {
compatible = "amlogic,meson8b-analog-top", "syscon";
reg = <0x81a8 0x14>;
};
pwm_ef: pwm@86c0 {
compatible = "amlogic,meson8b-pwm";
reg = <0x86c0 0x10>;
#pwm-cells = <3>;
status = "disabled";
};
pinctrl_cbus: pinctrl@9880 {
compatible = "amlogic,meson8b-cbus-pinctrl";
reg = <0x9880 0x10>;
#address-cells = <1>;
#size-cells = <1>;
ranges;
gpio: banks@80b0 {
reg = <0x80b0 0x28>,
<0x80e8 0x18>,
<0x8120 0x18>,
<0x8030 0x38>;
reg-names = "mux", "pull", "pull-enable", "gpio";
gpio-controller;
#gpio-cells = <2>;
gpio-ranges = <&pinctrl_cbus 0 0 130>;
};
eth_rgmii_pins: eth-rgmii {
mux {
groups = "eth_tx_clk",
"eth_tx_en",
"eth_txd1_0",
"eth_txd1_1",
"eth_txd0_0",
"eth_txd0_1",
"eth_rx_clk",
"eth_rx_dv",
"eth_rxd1",
"eth_rxd0",
"eth_mdio_en",
"eth_mdc",
"eth_ref_clk",
"eth_txd2",
"eth_txd3";
function = "ethernet";
};
};
};
};
&ahb_sram {
smp-sram@1ff80 {
compatible = "amlogic,meson8b-smp-sram";
reg = <0x1ff80 0x8>;
};
};
&efuse {
compatible = "amlogic,meson8b-efuse";
clocks = <&clkc CLKID_EFUSE>;
clock-names = "core";
};
ðmac {
compatible = "amlogic,meson8b-dwmac", "snps,dwmac-3.70a", "snps,dwmac";
reg = <0xc9410000 0x10000
0xc1108140 0x4>;
clocks = <&clkc CLKID_ETH>,
<&clkc CLKID_MPLL2>,
<&clkc CLKID_MPLL2>;
clock-names = "stmmaceth", "clkin0", "clkin1";
resets = <&reset RESET_ETHERNET>;
reset-names = "stmmaceth";
};
&gpio_intc {
compatible = "amlogic,meson-gpio-intc",
"amlogic,meson8b-gpio-intc";
status = "okay";
};
&hwrng {
compatible = "amlogic,meson8b-rng", "amlogic,meson-rng";
clocks = <&clkc CLKID_RNG0>;
clock-names = "core";
};
&L2 {
arm,data-latency = <3 3 3>;
arm,tag-latency = <2 2 2>;
arm,filter-ranges = <0x100000 0xc0000000>;
};
&pwm_ab {
compatible = "amlogic,meson8b-pwm";
};
&pwm_cd {
compatible = "amlogic,meson8b-pwm";
};
&saradc {
compatible = "amlogic,meson8b-saradc", "amlogic,meson-saradc";
clocks = <&clkc CLKID_XTAL>,
<&clkc CLKID_SAR_ADC>,
<&clkc CLKID_SANA>;
clock-names = "clkin", "core", "sana";
};
&sdio {
compatible = "amlogic,meson8b-sdio", "amlogic,meson-mx-sdio";
clocks = <&clkc CLKID_SDIO>, <&clkc CLKID_CLK81>;
clock-names = "core", "clkin";
};
&uart_AO {
clocks = <&clkc CLKID_CLK81>;
};
&uart_A {
clocks = <&clkc CLKID_CLK81>;
};
&uart_B {
clocks = <&clkc CLKID_CLK81>;
};
&uart_C {
clocks = <&clkc CLKID_CLK81>;
};
&usb0 {
compatible = "amlogic,meson8b-usb", "snps,dwc2";
clocks = <&clkc CLKID_USB0_DDR_BRIDGE>;
clock-names = "otg";
};
&usb1 {
compatible = "amlogic,meson8b-usb", "snps,dwc2";
clocks = <&clkc CLKID_USB1_DDR_BRIDGE>;
clock-names = "otg";
};
&usb0_phy {
compatible = "amlogic,meson8b-usb2-phy", "amlogic,meson-mx-usb2-phy";
clocks = <&clkc CLKID_USB>, <&clkc CLKID_USB0>;
clock-names = "usb_general", "usb";
resets = <&reset RESET_USB_OTG>;
};
&usb1_phy {
compatible = "amlogic,meson8b-usb2-phy", "amlogic,meson-mx-usb2-phy";
clocks = <&clkc CLKID_USB>, <&clkc CLKID_USB1>;
clock-names = "usb_general", "usb";
resets = <&reset RESET_USB_OTG>;
};
&wdt {
compatible = "amlogic,meson8b-wdt";
};
[-- Attachment #3: meson8b-odroidc1.dts --]
[-- Type: text/plain, Size: 3850 bytes --]
/*
* Copyright 2015 Endless Mobile, Inc.
* Author: Carlo Caione <carlo@endlessm.com>
*
* This file is dual-licensed: you can use it either under the terms
* of the GPL or the X11 license, at your option. Note that this dual
* licensing only applies to this file, and not this project as a
* whole.
*
* a) This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* Or, alternatively,
*
* b) Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
/dts-v1/;
#include "meson8b.dtsi"
#include <dt-bindings/gpio/gpio.h>
/ {
model = "Hardkernel ODROID-C1";
compatible = "hardkernel,odroid-c1", "amlogic,meson8b";
aliases {
serial0 = &uart_AO;
};
memory {
reg = <0x40000000 0x40000000>;
};
leds {
compatible = "gpio-leds";
blue {
label = "c1:blue:alive";
gpios = <&gpio_ao GPIOAO_13 GPIO_ACTIVE_LOW>;
linux,default-trigger = "heartbeat";
default-state = "off";
};
};
};
&uart_AO {
status = "okay";
pinctrl-0 = <&uart_ao_a_pins>;
pinctrl-names = "default";
};
&gpio_ao {
/*
* WARNING: The USB Hub on the Odroid-C1/C1+ needs a reset signal
* to be turned high in order to be detected by the USB Controller.
* This signal should be handled by a USB specific power sequence
* in order to reset the Hub when USB bus is powered down.
*/
usb-hub {
gpio-hog;
gpios = <GPIOAO_4 GPIO_ACTIVE_HIGH>;
output-high;
line-name = "usb-hub-reset";
};
};
&usb1_phy {
status = "okay";
};
&usb1 {
status = "okay";
};
ðmac {
status = "okay";
snps,reset-gpio = <&gpio GPIOH_4 GPIO_ACTIVE_HIGH>;
snps,reset-active-low;
snps,reset-delays-us = <0 10000 30000>;
pinctrl-0 = <ð_rgmii_pins>;
pinctrl-names = "default";
phy-mode = "rgmii";
phy-handle = <ð_phy>;
amlogic,tx-delay-ns = <2>;
mdio {
compatible = "snps,dwmac-mdio";
#address-cells = <1>;
#size-cells = <0>;
eth_phy: ethernet-phy@0 {
/* ethernet PHY RTL8211F */
compatible = "ethernet-phy-id001c.c916",
"ethernet-phy-ieee802.3-c22";
reg = <0>;
max-speed = <1000>;
eee-broken-1000t;
interrupt-parent = <&gpio_intc>;
interrupts = <17 IRQ_TYPE_LEVEL_LOW>;
};
};
};
^ permalink raw reply
* Re: [PATCH] NET: usb: qmi_wwan: add support for YUGA CLM920-NC5 PID 0x9625
From: Bjørn Mork @ 2017-12-29 11:45 UTC (permalink / raw)
To: SZ Lin (林上智)
Cc: netdev-u79uwXL29TY76Z2rM5mHXA, linux-usb-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <20171229090217.6933-1-sz.lin-D4fb9hXD9d4@public.gmane.org>
"SZ Lin (林上智)" <sz.lin-D4fb9hXD9d4@public.gmane.org> writes:
> This patch adds support for PID 0x9625 of YUGA CLM920-NC5.
>
> YUGA CLM920-NC5 needs to enable QMI_WWAN_QUIRK_DTR before QMI operation.
>
> qmicli -d /dev/cdc-wdm0 -p --dms-get-revision
> [/dev/cdc-wdm0] Device revision retrieved:
> Revision: 'CLM920_NC5-V1 1 [Oct 23 2016 19:00:00]'
>
> Signed-off-by: SZ Lin (林上智) <sz.lin-D4fb9hXD9d4@public.gmane.org>
> ---
> drivers/net/usb/qmi_wwan.c | 1 +
> 1 file changed, 1 insertion(+)
>
> diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c
> index 3000ddd1c7e2..728819feab44 100644
> --- a/drivers/net/usb/qmi_wwan.c
> +++ b/drivers/net/usb/qmi_wwan.c
> @@ -1100,6 +1100,7 @@ static const struct usb_device_id products[] = {
> {QMI_FIXED_INTF(0x05c6, 0x9084, 4)},
> {QMI_FIXED_INTF(0x05c6, 0x920d, 0)},
> {QMI_FIXED_INTF(0x05c6, 0x920d, 5)},
> + {QMI_QUIRK_SET_DTR(0x05c6, 0x9625, 4)}, /* YUGA CLM920-NC5 */
> {QMI_FIXED_INTF(0x0846, 0x68a2, 8)},
> {QMI_FIXED_INTF(0x12d1, 0x140c, 1)}, /* Huawei E173 */
> {QMI_FIXED_INTF(0x12d1, 0x14ac, 1)}, /* Huawei E1820 */
Perfect. Thanks
Acked-by: Bjørn Mork <bjorn-yOkvZcmFvRU@public.gmane.org>
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH net-next 5/6] arm64: dts: marvell: mcbin: enable the fourth network interface
From: Russell King - ARM Linux @ 2017-12-29 11:38 UTC (permalink / raw)
To: Marcin Wojtas
Cc: Thomas Petazzoni, Andrew Lunn, Florian Fainelli, Yan Markman,
Jason Cooper, netdev, Antoine Tenart, linux-kernel, kishon,
nadavh, Miquèl Raynal, Gregory Clément, Stefan Chulski,
David S. Miller, linux-arm-kernel, Sebastian Hesselbarth
In-Reply-To: <CAPv3WKdNCOB=1BqGXw7gXZNX+bBhOXVfheYPjC4CFZjfiOXyHQ@mail.gmail.com>
On Fri, Dec 29, 2017 at 12:12:15PM +0100, Marcin Wojtas wrote:
> Hi Russell,
>
> I see that I misspelled your email address, hence the series remained unnoticed:
> https://lkml.org/lkml/2017/12/18/216
>
> In terms of the phylink support, I think the most important are:
> * 3/8
> https://lkml.org/lkml/2017/12/18/211
> * 7/8
> https://lkml.org/lkml/2017/12/18/207
>
> I think the way of obtaining PHY fwnode and connecting it from the
> latter patch could be incorporated to the phylink code. Although I
> didn't get much feedback, the whole ACPI-handling of MDIO bus and the
> PHYs touch ACPI specification and I expect it a slower to get merged.
> Hence my idea is following:
> * Send v2 with ACPI supporting link-irq only in mvpp2.c
> * Extract MDIO bus handling for ACPI and propose PHY handling
> modifications in phylink.
>
> This way we may push the two things forwards in more efficient way.
> I'm looking forward to your opinion.
Agreed - as we have very few users of phylink at the moment (they're
mostly all in external trees) we can easily change the phylink
interfaces. The first step is solving the ACPI representation of the
MDIO bus and attached devices, and until that is settled, not much can
be done.
However, it seems to me that the issues of adding ACPI to mvpp2 vs
adding phylink to mvpp2 are two entirely separate problems that don't
really conflict with each other - since the "phy" problem afflicts
both.
However, I'm not sure what this "link-irq" thing is that you talk
about (and I suspect it's one of the things that I've been trying for
months to find out about from Antoine when he says that there's stuff
that mvpp2 supports that phylink doesn't.) So, I'm left to guess, and
I guess it's the mvpp2-variant of mvneta's in-band autonegotiation.
Continuing to guess from the mvpp2 phylink conversion patch, this mvpp2
variant is selected by not providing a phy handle in DT, whereas
mvneta's variant is selected using the ethernet-standard property
'managed = "in-band-status"'.
If my guessing is correct, I have to wonder why mvpp2 invented a
different way to represent this from mvneta? This makes it much more
difficult to convert mvpp2 to phylink, and it also makes it difficult
to add SFP support ignoring the phylink issue (since there is no phy
handle there either.)
--
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line in suburbia: sync at 8.8Mbps down 630kbps up
According to speedtest.net: 8.21Mbps down 510kbps up
^ permalink raw reply
* Re: [PATCH net-next 5/6] arm64: dts: marvell: mcbin: enable the fourth network interface
From: Marcin Wojtas @ 2017-12-29 11:12 UTC (permalink / raw)
To: Russell King - ARM Linux
Cc: Antoine Tenart, Florian Fainelli, Andrew Lunn, Thomas Petazzoni,
Yan Markman, Jason Cooper, netdev, linux-kernel, kishon, nadavh,
Miquèl Raynal, Gregory Clément, Stefan Chulski,
David S. Miller, linux-arm-kernel, Sebastian Hesselbarth
In-Reply-To: <20171228184642.GV10595@n2100.armlinux.org.uk>
Hi Russell,
2017-12-28 19:46 GMT+01:00 Russell King - ARM Linux <linux@armlinux.org.uk>:
> On Thu, Dec 28, 2017 at 07:27:39PM +0100, Antoine Tenart wrote:
>> Hi Florian,
>>
>> On Thu, Dec 28, 2017 at 07:02:09AM -0800, Florian Fainelli wrote:
>> > On 12/28/2017 02:05 AM, Antoine Tenart wrote:
>> > > On Thu, Dec 28, 2017 at 08:46:23AM +0100, Andrew Lunn wrote:
>> > >> On Wed, Dec 27, 2017 at 10:24:01PM +0000, Russell King - ARM Linux wrote:
>> > >>> On Wed, Dec 27, 2017 at 11:14:45PM +0100, Antoine Tenart wrote:
>> > >>>>
>> > >>>> +&cps_eth2 {
>> > >>>> + /* CPS Lane 5 */
>> > >>>> + status = "okay";
>> > >>>> + phy-mode = "2500base-x";
>> > >>>> + /* Generic PHY, providing serdes lanes */
>> > >>>> + phys = <&cps_comphy5 2>;
>> > >>>> +};
>> > >>>> +
>> > >>>
>> > >>> This is wrong. This lane is connected to a SFP cage which can support
>> > >>> more than just 2500base-X. Tying it in this way to 2500base-X means
>> > >>> that this port does not support conenctions at 1000base-X, despite
>> > >>> that's one of the most popular and more standardised speeds.
>> > >>>
>> > >>
>> > >> I agree with Russell here. SFP modules are hot pluggable, and support
>> > >> a range of interface modes. You need to query what the SFP module is
>> > >> in order to know how to configure the SERDES interface. The phylink
>> > >> infrastructure does that for you.
>> > >
>> > > Sure, I understand. We'll be able to support such interfaces only when
>> > > the phylink PPv2 support lands in.
>> >
>> > Should we expect PHYLINK support to make it as the first patch in your
>> > v2 of this patch series, or is someone else doing that?
>>
>> No, the phylink patch conflicts with Marcin's ACPI series and we agreed
>> to let him get his series merged first. And I will probably work on a
>> few other topics before having the chance to work on it. So it'll
>> probably be me doing that, but not right now.
>
> ACPI is going to be a problem with phylink for a while. There's patches
> queued in net-next which convert phylink and SFP mostly to the fwnode
> and property based systems, but phylib and i2c do not seem to have the
> necessary bits to be able to deal with those.
>
> Specifically, in DT we have "of_find_i2c_adapter_by_node()" but afaics
> there is no equivalent in ACPI - which means in an ACPI based system
> we have no way to determine the I2C bus associated with a SFP socket,
> which is a rather fundamental issue for SFP modules.
>
> For phylib side, there's "of_phy_attach()" but again there is no
> equivalent in ACPI. This should not be that much of a problem, because
> network drivers using the DT phylib calls (eg, "of_phy_connect()") are
> already restricted by this. That may have been solved by Marcin's
> series, but I've not seen it to know.
>
I see that I misspelled your email address, hence the series remained unnoticed:
https://lkml.org/lkml/2017/12/18/216
In terms of the phylink support, I think the most important are:
* 3/8
https://lkml.org/lkml/2017/12/18/211
* 7/8
https://lkml.org/lkml/2017/12/18/207
I think the way of obtaining PHY fwnode and connecting it from the
latter patch could be incorporated to the phylink code. Although I
didn't get much feedback, the whole ACPI-handling of MDIO bus and the
PHYs touch ACPI specification and I expect it a slower to get merged.
Hence my idea is following:
* Send v2 with ACPI supporting link-irq only in mvpp2.c
* Extract MDIO bus handling for ACPI and propose PHY handling
modifications in phylink.
This way we may push the two things forwards in more efficient way.
I'm looking forward to your opinion.
Best regards,
Marcin
^ permalink raw reply
* [iptables] extensions: add support for 'srh' match
From: Ahmed Abdelsalam @ 2017-12-29 11:08 UTC (permalink / raw)
To: pablo, kadlec, fw, davem, kuznet, yoshfuji
Cc: linux-kernel, netfilter-devel, coreteam, netdev, amsalam20
This patch adds a new exetension to iptables to supprt 'srh' match
The implementation considers revision 7 of the SRH draft.
https://tools.ietf.org/html/draft-ietf-6man-segment-routing-header-07
Signed-off-by: Ahmed Abdelsalam <amsalam20@gmail.com>
---
extensions/libip6t_srh.c | 283 ++++++++++++++++++++++++++++++++
include/linux/netfilter_ipv6/ip6t_srh.h | 63 +++++++
2 files changed, 346 insertions(+)
create mode 100644 extensions/libip6t_srh.c
create mode 100644 include/linux/netfilter_ipv6/ip6t_srh.h
diff --git a/extensions/libip6t_srh.c b/extensions/libip6t_srh.c
new file mode 100644
index 0000000..fd92ba1
--- /dev/null
+++ b/extensions/libip6t_srh.c
@@ -0,0 +1,283 @@
+/**
+ * Segment Routing Header 'srh' match extension
+ *
+ * Author:
+ * Ahmed Abdelsalam <amsalam20@gmail.com>
+ */
+
+#include <stdio.h>
+#include <xtables.h>
+#include <linux/netfilter_ipv6/ip6t_srh.h>
+#include <string.h>
+
+/* srh command-line options */
+enum {
+ O_SRH_NEXTHDR,
+ O_SRH_LEN_EQ,
+ O_SRH_LEN_GT,
+ O_SRH_LEN_LT,
+ O_SRH_SEGS_EQ,
+ O_SRH_SEGS_GT,
+ O_SRH_SEGS_LT,
+ O_SRH_LAST_EQ,
+ O_SRH_LAST_GT,
+ O_SRH_LAST_LT,
+ O_SRH_TAG,
+};
+
+static void srh_help(void)
+{
+ printf(
+"srh match options:\n"
+"[!] --srh-next-hdr next-hdr Next Header value of SRH\n"
+"[!] --srh-len-eq hdr_len Hdr Ext Len value of SRH\n"
+"[!] --srh-len-gt hdr_len Hdr Ext Len value of SRH\n"
+"[!] --srh-len-lt hdr_len Hdr Ext Len value of SRH\n"
+"[!] --srh-segs-eq segs_left Segments Left value of SRH\n"
+"[!] --srh-segs-gt segs_left Segments Left value of SRH\n"
+"[!] --srh-segs-lt segs_left Segments Left value of SRH\n"
+"[!] --srh-last-eq last_entry Last Entry value of SRH\n"
+"[!] --srh-last-gt last_entry Last Entry value of SRH\n"
+"[!] --srh-last-lt last_entry Last Entry value of SRH\n"
+"[!] --srh-tag tag Tag value of SRH\n");
+}
+
+#define s struct ip6t_srh
+static const struct xt_option_entry srh_opts[] = {
+ { .name = "srh-next-hdr", .id = O_SRH_NEXTHDR, .type = XTTYPE_UINT8,
+ .flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, next_hdr)},
+ { .name = "srh-len-eq", .id = O_SRH_LEN_EQ, .type = XTTYPE_UINT8,
+ .flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, hdr_len)},
+ { .name = "srh-len-gt", .id = O_SRH_LEN_GT, .type = XTTYPE_UINT8,
+ .flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, hdr_len)},
+ { .name = "srh-len-lt", .id = O_SRH_LEN_LT, .type = XTTYPE_UINT8,
+ .flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, hdr_len)},
+ { .name = "srh-segs-eq", .id = O_SRH_SEGS_EQ, .type = XTTYPE_UINT8,
+ .flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, segs_left)},
+ { .name = "srh-segs-gt", .id = O_SRH_SEGS_GT, .type = XTTYPE_UINT8,
+ .flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, segs_left)},
+ { .name = "srh-segs-lt", .id = O_SRH_SEGS_LT, .type = XTTYPE_UINT8,
+ .flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, segs_left)},
+ { .name = "srh-last-eq", .id = O_SRH_LAST_EQ, .type = XTTYPE_UINT8,
+ .flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, last_entry)},
+ { .name = "srh-last-gt", .id = O_SRH_LAST_GT, .type = XTTYPE_UINT8,
+ flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, last_entry)},
+ { .name = "srh-last-lt", .id = O_SRH_LAST_LT, .type = XTTYPE_UINT8,
+ .flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, last_entry)},
+ { .name = "srh-tag", .id = O_SRH_TAG, .type = XTTYPE_UINT16,
+ .flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, tag)},
+ { }
+};
+#undef s
+
+static void srh_init(struct xt_entry_match *m)
+{
+ struct ip6t_srh *srhinfo = (void *)m->data;
+
+ srhinfo->mt_flags = 0;
+ srhinfo->mt_invflags = 0;
+}
+
+static void srh_parse(struct xt_option_call *cb)
+{
+ struct ip6t_srh *srhinfo = cb->data;
+
+ xtables_option_parse(cb);
+ switch (cb->entry->id) {
+ case O_SRH_NEXTHDR:
+ srhinfo->mt_flags |= IP6T_SRH_NEXTHDR;
+ if (cb->invert)
+ srhinfo->mt_invflags |= IP6T_SRH_INV_NEXTHDR;
+ break;
+ case O_SRH_LEN_EQ:
+ srhinfo->mt_flags |= IP6T_SRH_LEN_EQ;
+ if (cb->invert)
+ srhinfo->mt_invflags |= IP6T_SRH_INV_LEN_EQ;
+ break;
+ case O_SRH_LEN_GT:
+ srhinfo->mt_flags |= IP6T_SRH_LEN_GT;
+ if (cb->invert)
+ srhinfo->mt_invflags |= IP6T_SRH_INV_LEN_GT;
+ break;
+ case O_SRH_LEN_LT:
+ srhinfo->mt_flags |= IP6T_SRH_LEN_LT;
+ if (cb->invert)
+ srhinfo->mt_invflags |= IP6T_SRH_INV_LEN_LT;
+ break;
+ case O_SRH_SEGS_EQ:
+ srhinfo->mt_flags |= IP6T_SRH_SEGS_EQ;
+ if (cb->invert)
+ srhinfo->mt_invflags |= IP6T_SRH_INV_SEGS_EQ;
+ break;
+ case O_SRH_SEGS_GT:
+ srhinfo->mt_flags |= IP6T_SRH_SEGS_GT;
+ if (cb->invert)
+ srhinfo->mt_invflags |= IP6T_SRH_INV_SEGS_GT;
+ break;
+ case O_SRH_SEGS_LT:
+ srhinfo->mt_flags |= IP6T_SRH_SEGS_LT;
+ if (cb->invert)
+ srhinfo->mt_invflags |= IP6T_SRH_INV_SEGS_LT;
+ break;
+ case O_SRH_LAST_EQ:
+ srhinfo->mt_flags |= IP6T_SRH_LAST_EQ;
+ if (cb->invert)
+ srhinfo->mt_invflags |= IP6T_SRH_INV_LAST_EQ;
+ break;
+ case O_SRH_LAST_GT:
+ srhinfo->mt_flags |= IP6T_SRH_LAST_GT;
+ if (cb->invert)
+ srhinfo->mt_invflags |= IP6T_SRH_INV_LAST_GT;
+ break;
+ case O_SRH_LAST_LT:
+ srhinfo->mt_flags |= IP6T_SRH_LAST_LT;
+ if (cb->invert)
+ srhinfo->mt_invflags |= IP6T_SRH_INV_LAST_LT;
+ break;
+ case O_SRH_TAG:
+ srhinfo->mt_flags |= IP6T_SRH_TAG;
+ if (cb->invert)
+ srhinfo->mt_invflags |= IP6T_SRH_INV_TAG;
+ break;
+ }
+}
+
+static const char *pinv(bool invert)
+{
+ const char *inv = invert ? "!" : " ";
+ return inv;
+}
+
+static void srh_print(const void *ip, const struct xt_entry_match *match,
+ int numeric)
+{
+ const struct ip6t_srh *srhinfo = (struct ip6t_srh *)match->data;
+
+ printf(" srh ");
+
+ if (srhinfo->mt_flags & IP6T_SRH_NEXTHDR)
+ printf("next-hdr %s=%d ",
+ pinv(srhinfo->mt_invflags & IP6T_SRH_INV_NEXTHDR),
+ srhinfo->next_hdr);
+
+ if (srhinfo->mt_flags & IP6T_SRH_LEN_EQ)
+ printf("hdr-len %s=%d ",
+ pinv(srhinfo->mt_invflags & IP6T_SRH_INV_LEN_EQ),
+ srhinfo->hdr_len);
+ if (srhinfo->mt_flags & IP6T_SRH_LEN_GT)
+ printf("hdr-len %s>%d ",
+ pinv(srhinfo->mt_invflags & IP6T_SRH_INV_LEN_GT),
+ srhinfo->hdr_len);
+ if (srhinfo->mt_flags & IP6T_SRH_LEN_LT)
+ printf("hdr-len %s<%d ",
+ pinv(srhinfo->mt_invflags & IP6T_SRH_INV_LEN_LT),
+ srhinfo->hdr_len);
+
+ if (srhinfo->mt_flags & IP6T_SRH_SEGS_EQ)
+ printf("segs-left %s=%d ",
+ pinv(srhinfo->mt_invflags & IP6T_SRH_INV_SEGS_EQ),
+ srhinfo->segs_left);
+ if (srhinfo->mt_flags & IP6T_SRH_SEGS_GT)
+ printf("segs-left %s>%d ",
+ pinv(srhinfo->mt_invflags & IP6T_SRH_INV_SEGS_GT),
+ srhinfo->segs_left);
+ if (srhinfo->mt_flags & IP6T_SRH_SEGS_LT)
+ printf("segs-left %s<%d ",
+ pinv(srhinfo->mt_invflags & IP6T_SRH_INV_SEGS_LT),
+ srhinfo->segs_left);
+
+ if (srhinfo->mt_flags & IP6T_SRH_LAST_EQ)
+ printf("last-entry %s=%d ",
+ pinv(srhinfo->mt_invflags & IP6T_SRH_INV_LAST_EQ),
+ srhinfo->last_entry);
+ if (srhinfo->mt_flags & IP6T_SRH_LAST_GT)
+ printf("last-entry %s>%d ",
+ pinv(srhinfo->mt_invflags & IP6T_SRH_INV_LAST_GT),
+ srhinfo->last_entry);
+ if (srhinfo->mt_flags & IP6T_SRH_LAST_LT)
+ printf("last-entry %s<%d ",
+ pinv(srhinfo->mt_invflags & IP6T_SRH_INV_LAST_LT),
+ srhinfo->last_entry);
+
+ if (srhinfo->mt_flags & IP6T_SRH_TAG)
+ printf("tag %s=%d ",
+ pinv(srhinfo->mt_invflags & IP6T_SRH_INV_TAG),
+ srhinfo->tag);
+
+}
+
+static void srh_save(const void *ip, const struct xt_entry_match *match)
+{
+ const struct ip6t_srh *srhinfo = (struct ip6t_srh *)match->data;
+
+ printf(" srh ");
+
+ if (srhinfo->mt_flags & IP6T_SRH_NEXTHDR)
+ printf("next-hdr %s=%d ",
+ pinv(srhinfo->mt_invflags & IP6T_SRH_INV_NEXTHDR),
+ srhinfo->next_hdr);
+
+ if (srhinfo->mt_flags & IP6T_SRH_LEN_EQ)
+ printf("hdr-len %s=%d ",
+ pinv(srhinfo->mt_invflags & IP6T_SRH_INV_LEN_EQ),
+ srhinfo->hdr_len);
+ if (srhinfo->mt_flags & IP6T_SRH_LEN_GT)
+ printf("hdr-len %s>%d ",
+ pinv(srhinfo->mt_invflags & IP6T_SRH_INV_LEN_GT),
+ srhinfo->hdr_len);
+ if (srhinfo->mt_flags & IP6T_SRH_LEN_LT)
+ printf("hdr-len %s<%d ",
+ pinv(srhinfo->mt_invflags & IP6T_SRH_INV_LEN_LT),
+ srhinfo->hdr_len);
+
+ if (srhinfo->mt_flags & IP6T_SRH_SEGS_EQ)
+ printf("segs-left %s=%d ",
+ pinv(srhinfo->mt_invflags & IP6T_SRH_INV_SEGS_EQ),
+ srhinfo->segs_left);
+ if (srhinfo->mt_flags & IP6T_SRH_SEGS_GT)
+ printf("segs-left %s>%d ",
+ pinv(srhinfo->mt_invflags & IP6T_SRH_INV_SEGS_GT),
+ srhinfo->segs_left);
+ if (srhinfo->mt_flags & IP6T_SRH_SEGS_LT)
+ printf("segs-left %s<%d ",
+ pinv(srhinfo->mt_invflags & IP6T_SRH_INV_SEGS_LT),
+ srhinfo->segs_left);
+
+ if (srhinfo->mt_flags & IP6T_SRH_LAST_EQ)
+ printf("last-entry %s=%d ",
+ pinv(srhinfo->mt_invflags & IP6T_SRH_INV_LAST_EQ),
+ srhinfo->last_entry);
+ if (srhinfo->mt_flags & IP6T_SRH_LAST_GT)
+ printf("last-entry %s>%d ",
+ pinv(srhinfo->mt_invflags & IP6T_SRH_INV_LAST_GT),
+ srhinfo->last_entry);
+ if (srhinfo->mt_flags & IP6T_SRH_LAST_LT)
+ printf("last-entry %s<%d ",
+ pinv(srhinfo->mt_invflags & IP6T_SRH_INV_LAST_LT),
+ srhinfo->last_entry);
+
+ if (srhinfo->mt_flags & IP6T_SRH_TAG)
+ printf("tag %s=%d ",
+ pinv(srhinfo->mt_invflags & IP6T_SRH_INV_TAG),
+ srhinfo->tag);
+}
+
+static struct xtables_match srh_mt6_reg = {
+ .name = "srh",
+ .version = XTABLES_VERSION,
+ .family = NFPROTO_IPV6,
+ .size = XT_ALIGN(sizeof(struct ip6t_srh)),
+ .userspacesize = XT_ALIGN(sizeof(struct ip6t_srh)),
+ .help = srh_help,
+ .init = srh_init,
+ .print = srh_print,
+ .save = srh_save,
+ .x6_parse = srh_parse,
+ .x6_options = srh_opts,
+};
+
+void
+_init(void)
+{
+ xtables_register_match(&srh_mt6_reg);
+}
diff --git a/include/linux/netfilter_ipv6/ip6t_srh.h b/include/linux/netfilter_ipv6/ip6t_srh.h
new file mode 100644
index 0000000..bc27197
--- /dev/null
+++ b/include/linux/netfilter_ipv6/ip6t_srh.h
@@ -0,0 +1,63 @@
+/**
+ * Definitions for Segment Routing Header 'srh' match
+ *
+ * Author:
+ * Ahmed Abdelsalam <amsalam20@gmail.com>
+ */
+
+#ifndef _IP6T_SRH_H
+#define _IP6T_SRH_H
+
+#include <linux/types.h>
+#include <linux/netfilter.h>
+
+/* Values for "mt_flags" field in struct ip6t_srh */
+#define IP6T_SRH_NEXTHDR 0x0001
+#define IP6T_SRH_LEN_EQ 0x0002
+#define IP6T_SRH_LEN_GT 0x0004
+#define IP6T_SRH_LEN_LT 0x0008
+#define IP6T_SRH_SEGS_EQ 0x0010
+#define IP6T_SRH_SEGS_GT 0x0020
+#define IP6T_SRH_SEGS_LT 0x0040
+#define IP6T_SRH_LAST_EQ 0x0080
+#define IP6T_SRH_LAST_GT 0x0100
+#define IP6T_SRH_LAST_LT 0x0200
+#define IP6T_SRH_TAG 0x0400
+#define IP6T_SRH_MASK 0x07FF
+
+/* Values for "mt_invflags" field in struct ip6t_srh */
+#define IP6T_SRH_INV_NEXTHDR 0x0001
+#define IP6T_SRH_INV_LEN_EQ 0x0002
+#define IP6T_SRH_INV_LEN_GT 0x0004
+#define IP6T_SRH_INV_LEN_LT 0x0008
+#define IP6T_SRH_INV_SEGS_EQ 0x0010
+#define IP6T_SRH_INV_SEGS_GT 0x0020
+#define IP6T_SRH_INV_SEGS_LT 0x0040
+#define IP6T_SRH_INV_LAST_EQ 0x0080
+#define IP6T_SRH_INV_LAST_GT 0x0100
+#define IP6T_SRH_INV_LAST_LT 0x0200
+#define IP6T_SRH_INV_TAG 0x0400
+#define IP6T_SRH_INV_MASK 0x07FF
+
+/**
+ * struct ip6t_srh - SRH match options
+ * @ next_hdr: Next header field of SRH
+ * @ hdr_len: Extension header length field of SRH
+ * @ segs_left: Segments left field of SRH
+ * @ last_entry: Last entry field of SRH
+ * @ tag: Tag field of SRH
+ * @ mt_flags: match options
+ * @ mt_invflags: Invert the sense of match options
+ */
+
+struct ip6t_srh {
+ __u8 next_hdr;
+ __u8 hdr_len;
+ __u8 segs_left;
+ __u8 last_entry;
+ __u16 tag;
+ __u16 mt_flags;
+ __u16 mt_invflags;
+};
+
+#endif /*_IP6T_SRH_H*/
--
2.1.4
^ permalink raw reply related
* [net-next] netfilter: add segment routing header 'srh' match
From: Ahmed Abdelsalam @ 2017-12-29 11:07 UTC (permalink / raw)
To: pablo, kadlec, fw, davem, kuznet, yoshfuji
Cc: linux-kernel, netfilter-devel, coreteam, netdev, amsalam20
It allows matching packets based on Segment Routing Header
(SRH) information.
The implementation considers revision 7 of the SRH draft.
https://tools.ietf.org/html/draft-ietf-6man-segment-routing-header-07
Currently supported match options include:
(1) Next Header
(2) Hdr Ext Len
(3) Segments Left
(4) Last Entry
(5) Tag value of SRH
Signed-off-by: Ahmed Abdelsalam <amsalam20@gmail.com>
---
include/uapi/linux/netfilter_ipv6/ip6t_srh.h | 63 ++++++++++
net/ipv6/netfilter/Kconfig | 9 ++
net/ipv6/netfilter/Makefile | 1 +
net/ipv6/netfilter/ip6t_srh.c | 165 +++++++++++++++++++++++++++
4 files changed, 238 insertions(+)
create mode 100644 include/uapi/linux/netfilter_ipv6/ip6t_srh.h
create mode 100644 net/ipv6/netfilter/ip6t_srh.c
diff --git a/include/uapi/linux/netfilter_ipv6/ip6t_srh.h b/include/uapi/linux/netfilter_ipv6/ip6t_srh.h
new file mode 100644
index 0000000..1b5dbd8
--- /dev/null
+++ b/include/uapi/linux/netfilter_ipv6/ip6t_srh.h
@@ -0,0 +1,63 @@
+/**
+ * Definitions for Segment Routing Header 'srh' match
+ *
+ * Author:
+ * Ahmed Abdelsalam <amsalam20@gmail.com>
+ */
+
+#ifndef _IP6T_SRH_H
+#define _IP6T_SRH_H
+
+#include <linux/types.h>
+#include <linux/netfilter.h>
+
+/* Values for "mt_flags" field in struct ip6t_srh */
+#define IP6T_SRH_NEXTHDR 0x0001
+#define IP6T_SRH_LEN_EQ 0x0002
+#define IP6T_SRH_LEN_GT 0x0004
+#define IP6T_SRH_LEN_LT 0x0008
+#define IP6T_SRH_SEGS_EQ 0x0010
+#define IP6T_SRH_SEGS_GT 0x0020
+#define IP6T_SRH_SEGS_LT 0x0040
+#define IP6T_SRH_LAST_EQ 0x0080
+#define IP6T_SRH_LAST_GT 0x0100
+#define IP6T_SRH_LAST_LT 0x0200
+#define IP6T_SRH_TAG 0x0400
+#define IP6T_SRH_MASK 0x07FF
+
+/* Values for "mt_invflags" field in struct ip6t_srh */
+#define IP6T_SRH_INV_NEXTHDR 0x0001
+#define IP6T_SRH_INV_LEN_EQ 0x0002
+#define IP6T_SRH_INV_LEN_GT 0x0004
+#define IP6T_SRH_INV_LEN_LT 0x0008
+#define IP6T_SRH_INV_SEGS_EQ 0x0010
+#define IP6T_SRH_INV_SEGS_GT 0x0020
+#define IP6T_SRH_INV_SEGS_LT 0x0040
+#define IP6T_SRH_INV_LAST_EQ 0x0080
+#define IP6T_SRH_INV_LAST_GT 0x0100
+#define IP6T_SRH_INV_LAST_LT 0x0200
+#define IP6T_SRH_INV_TAG 0x0400
+#define IP6T_SRH_INV_MASK 0x07FF
+
+/**
+ * struct ip6t_srh - SRH match options
+ * @ next_hdr: Next header field of SRH
+ * @ hdr_len: Extension header length field of SRH
+ * @ segs_left: Segments left field of SRH
+ * @ last_entry: Last entry field of SRH
+ * @ tag: Tag field of SRH
+ * @ mt_flags: match options
+ * @ mt_invflags: Invert the sense of match options
+ */
+
+struct ip6t_srh {
+ __u8 next_hdr;
+ __u8 hdr_len;
+ __u8 segs_left;
+ __u8 last_entry;
+ __u16 tag;
+ __u16 mt_flags;
+ __u16 mt_invflags;
+};
+
+#endif /*_IP6T_SRH_H*/
diff --git a/net/ipv6/netfilter/Kconfig b/net/ipv6/netfilter/Kconfig
index 6acb2ee..e1818eb 100644
--- a/net/ipv6/netfilter/Kconfig
+++ b/net/ipv6/netfilter/Kconfig
@@ -232,6 +232,15 @@ config IP6_NF_MATCH_RT
To compile it as a module, choose M here. If unsure, say N.
+config IP6_NF_MATCH_SRH
+ tristate '"srh" Segment Routing header match support'
+ depends on NETFILTER_ADVANCED
+ help
+ srh matching allows you to match packets based on the segment
+ routing header of the packet.
+
+ To compile it as a module, choose M here. If unsure, say N.
+
# The targets
config IP6_NF_TARGET_HL
tristate '"HL" hoplimit target support'
diff --git a/net/ipv6/netfilter/Makefile b/net/ipv6/netfilter/Makefile
index c6ee0cd..e0d51a9 100644
--- a/net/ipv6/netfilter/Makefile
+++ b/net/ipv6/netfilter/Makefile
@@ -54,6 +54,7 @@ obj-$(CONFIG_IP6_NF_MATCH_MH) += ip6t_mh.o
obj-$(CONFIG_IP6_NF_MATCH_OPTS) += ip6t_hbh.o
obj-$(CONFIG_IP6_NF_MATCH_RPFILTER) += ip6t_rpfilter.o
obj-$(CONFIG_IP6_NF_MATCH_RT) += ip6t_rt.o
+obj-$(CONFIG_IP6_NF_MATCH_SRH) += ip6t_srh.o
# targets
obj-$(CONFIG_IP6_NF_TARGET_MASQUERADE) += ip6t_MASQUERADE.o
diff --git a/net/ipv6/netfilter/ip6t_srh.c b/net/ipv6/netfilter/ip6t_srh.c
new file mode 100644
index 0000000..75e41dc9
--- /dev/null
+++ b/net/ipv6/netfilter/ip6t_srh.c
@@ -0,0 +1,165 @@
+/*
+ * Kernel module to match Segment Routing Header (SRH) parameters.
+ *
+ * Author:
+ * Ahmed Abdelsalam <amsalam20@gmail.com>
+ *
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <linux/ipv6.h>
+#include <linux/types.h>
+#include <net/ipv6.h>
+#include <net/seg6.h>
+
+#include <linux/netfilter/x_tables.h>
+#include <linux/netfilter_ipv6/ip6t_srh.h>
+#include <linux/netfilter_ipv6/ip6_tables.h>
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Xtables: IPv6 Segment Routing Header match");
+MODULE_AUTHOR("Ahmed Abdelsalam <amsalam20@gmail.com>");
+
+/* Test a struct->mt_invflags and a boolean for inequality */
+#define NF_SRH_INVF(ptr, flag, boolean) \
+ ((boolean) ^ !!((ptr)->mt_invflags & (flag)))
+
+static bool srh_mt6(const struct sk_buff *skb, struct xt_action_param *par)
+{
+ const struct ip6t_srh *srhinfo = par->matchinfo;
+ struct ipv6_sr_hdr *srh;
+ struct ipv6_sr_hdr _srh;
+ int hdrlen, srhoff = 0;
+
+ if (ipv6_find_hdr(skb, &srhoff, IPPROTO_ROUTING, NULL, NULL) < 0)
+ return false;
+
+ srh = skb_header_pointer(skb, srhoff, sizeof(_srh), &_srh);
+
+ if (!srh)
+ return false;
+
+ hdrlen = ipv6_optlen(srh);
+ if (skb->len - srhoff < hdrlen)
+ return false;
+
+ if (srh->type != IPV6_SRCRT_TYPE_4)
+ return false;
+
+ if (srh->segments_left > srh->first_segment)
+ return false;
+
+ /* Next Header matching */
+ if (srhinfo->mt_flags & IP6T_SRH_NEXTHDR)
+ if (NF_SRH_INVF(srhinfo, IP6T_SRH_INV_NEXTHDR,
+ !(srh->nexthdr == srhinfo->next_hdr)))
+ return false;
+
+ /* Header Extension Length matching */
+ if (srhinfo->mt_flags & IP6T_SRH_LEN_EQ)
+ if (NF_SRH_INVF(srhinfo, IP6T_SRH_INV_LEN_EQ,
+ !(srh->hdrlen == srhinfo->hdr_len)))
+ return false;
+
+ if (srhinfo->mt_flags & IP6T_SRH_LEN_GT)
+ if (NF_SRH_INVF(srhinfo, IP6T_SRH_INV_LEN_GT,
+ !(srh->hdrlen > srhinfo->hdr_len)))
+ return false;
+
+ if (srhinfo->mt_flags & IP6T_SRH_LEN_LT)
+ if (NF_SRH_INVF(srhinfo, IP6T_SRH_INV_LEN_LT,
+ !(srh->hdrlen < srhinfo->hdr_len)))
+ return false;
+
+ /* Segments Left matching */
+ if (srhinfo->mt_flags & IP6T_SRH_SEGS_EQ)
+ if (NF_SRH_INVF(srhinfo, IP6T_SRH_INV_SEGS_EQ,
+ !(srh->segments_left == srhinfo->segs_left)))
+ return false;
+
+ if (srhinfo->mt_flags & IP6T_SRH_SEGS_GT)
+ if (NF_SRH_INVF(srhinfo, IP6T_SRH_INV_SEGS_GT,
+ !(srh->segments_left > srhinfo->segs_left)))
+ return false;
+
+ if (srhinfo->mt_flags & IP6T_SRH_SEGS_LT)
+ if (NF_SRH_INVF(srhinfo, IP6T_SRH_INV_SEGS_LT,
+ !(srh->segments_left < srhinfo->segs_left)))
+ return false;
+
+ /**
+ * Last Entry matching
+ * Last_Entry field was introduced in revision 6 of the SRH draft.
+ * It was called First_Segment in the previous revision
+ */
+ if (srhinfo->mt_flags & IP6T_SRH_LAST_EQ)
+ if (NF_SRH_INVF(srhinfo, IP6T_SRH_INV_LAST_EQ,
+ !(srh->first_segment == srhinfo->last_entry)))
+ return false;
+
+ if (srhinfo->mt_flags & IP6T_SRH_LAST_GT)
+ if (NF_SRH_INVF(srhinfo, IP6T_SRH_INV_LAST_GT,
+ !(srh->first_segment > srhinfo->last_entry)))
+ return false;
+
+ if (srhinfo->mt_flags & IP6T_SRH_LAST_LT)
+ if (NF_SRH_INVF(srhinfo, IP6T_SRH_INV_LAST_LT,
+ !(srh->first_segment < srhinfo->last_entry)))
+ return false;
+
+ /**
+ * Tag matchig
+ * Tag field was introduced in revision 6 of the SRH draft.
+ */
+ if (srhinfo->mt_flags & IP6T_SRH_TAG)
+ if (NF_SRH_INVF(srhinfo, IP6T_SRH_INV_TAG,
+ !(srh->tag == srhinfo->tag)))
+ return false;
+ return true;
+}
+
+static int srh_mt6_check(const struct xt_mtchk_param *par)
+{
+ const struct ip6t_srh *srhinfo = par->matchinfo;
+
+ if (srhinfo->mt_flags & ~IP6T_SRH_MASK) {
+ pr_debug("unknown srh match flags %X\n", srhinfo->mt_flags);
+ return -EINVAL;
+ }
+
+ if (srhinfo->mt_invflags & ~IP6T_SRH_INV_MASK) {
+ pr_debug("unknown srh invflags %X\n", srhinfo->mt_invflags);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static struct xt_match srh_mt6_reg __read_mostly = {
+ .name = "srh",
+ .family = NFPROTO_IPV6,
+ .match = srh_mt6,
+ .matchsize = sizeof(struct ip6t_srh),
+ .checkentry = srh_mt6_check,
+ .me = THIS_MODULE,
+};
+
+static int __init srh_mt6_init(void)
+{
+ return xt_register_match(&srh_mt6_reg);
+}
+
+static void __exit srh_mt6_exit(void)
+{
+ xt_unregister_match(&srh_mt6_reg);
+}
+
+module_init(srh_mt6_init);
+module_exit(srh_mt6_exit);
--
2.1.4
^ permalink raw reply related
* Re: [PATCH][next] wcn36xx: remove redundant assignment to msg_body.min_ch_time
From: Colin Ian King @ 2017-12-29 10:52 UTC (permalink / raw)
To: Loic Poulain, Bjorn Andersson
Cc: Eugene Krasnikov, Kalle Valo, wcn36xx, linux-wireless, netdev,
kernel-janitors, linux-kernel
In-Reply-To: <CAMZdPi8hYToYoPSMggPY-tVpsJNL2W57uzB+d0nSLdfNtPK6Cg@mail.gmail.com>
On 29/12/17 07:44, Loic Poulain wrote:
> Hi Colin, Bjorn,
>
> On 26 December 2017 at 21:13, Bjorn Andersson
> <bjorn.andersson@linaro.org> wrote:
>> On Tue 19 Dec 09:04 PST 2017, Colin King wrote:
>>
>>> From: Colin Ian King <colin.king@canonical.com>
>>>
>>> msg_body.min_ch_time is being assigned twice; remove the redundant
>>> first assignment.
>>>
>>> Detected by CoverityScan, CID#1463042 ("Unused Value")
>>>
>>
>> Happy to see Coverity working for us :)
>>
>>
>> This should have had a:
>>
>> Fixes: 2f3bef4b247e ("wcn36xx: Add hardware scan offload support")
>>
>>> Signed-off-by: Colin Ian King <colin.king@canonical.com>
>>> ---
>>> drivers/net/wireless/ath/wcn36xx/smd.c | 1 -
>>> 1 file changed, 1 deletion(-)
>>>
>>> diff --git a/drivers/net/wireless/ath/wcn36xx/smd.c b/drivers/net/wireless/ath/wcn36xx/smd.c
>>> index 2914618a0335..bab2eca5fcac 100644
>>> --- a/drivers/net/wireless/ath/wcn36xx/smd.c
>>> +++ b/drivers/net/wireless/ath/wcn36xx/smd.c
>>> @@ -625,7 +625,6 @@ int wcn36xx_smd_start_hw_scan(struct wcn36xx *wcn, struct ieee80211_vif *vif,
>>> INIT_HAL_MSG(msg_body, WCN36XX_HAL_START_SCAN_OFFLOAD_REQ);
>>>
>>> msg_body.scan_type = WCN36XX_HAL_SCAN_TYPE_ACTIVE;
>>> - msg_body.min_ch_time = 30;
>>> msg_body.min_ch_time = 100;
>>
>> But I strongly suspect the second line is supposed to be max_ch_time.
>>
>> @Loic, do you agree?
>
> You're absolutely right.
> Colin could you please update your patch accordingly?
Resent as "wcn36xx: fix incorrect assignment to msg_body.min_ch_time"
>
> Regards,
> Loic
> --
> To unsubscribe from this list: send the line "unsubscribe kernel-janitors" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
>
^ permalink raw reply
* [PATCH net-next 2/2] tuntap: XDP transmission
From: Jason Wang @ 2017-12-29 10:00 UTC (permalink / raw)
To: netdev, linux-kernel; +Cc: mst, jbrouer, Jason Wang, Jesper Dangaard Brouer
In-Reply-To: <1514541604-12728-1-git-send-email-jasowang@redhat.com>
This patch implements XDP transmission for TAP. Since we can't create
new queues for TAP during XDP set, exist ptr_ring was reused for
queuing XDP buffers. To differ xdp_buff from sk_buff, TUN_XDP_FLAG
(0x1ULL) was encoded into lowest bit of xpd_buff pointer during
ptr_ring_produce, and was decoded during consuming. XDP metadata was
stored in the headroom of the packet which should work in most of
cases since driver usually reserve enough headroom. Very minor changes
were done for vhost_net: it just need to peek the length depends on
the type of pointer.
Tests was done on two Intel E5-2630 2.40GHz machines connected back to
back through two 82599ES. Traffic were generated through MoonGen and
testpmd(rxonly) in guest reports 2.97Mpps when xdp_redirect_map is
doing redirection from ixgbe to TAP.
Cc: Jesper Dangaard Brouer <brouer@redhat.com>
Signed-off-by: Jason Wang <jasowang@redhat.com>
---
drivers/net/tun.c | 205 ++++++++++++++++++++++++++++++++++++++++---------
drivers/vhost/net.c | 13 +++-
include/linux/if_tun.h | 17 ++++
3 files changed, 197 insertions(+), 38 deletions(-)
diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index 2c89efe..be6d993 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -240,6 +240,24 @@ struct tun_struct {
struct tun_steering_prog __rcu *steering_prog;
};
+bool tun_is_xdp_buff(void *ptr)
+{
+ return (unsigned long)ptr & TUN_XDP_FLAG;
+}
+EXPORT_SYMBOL(tun_is_xdp_buff);
+
+void *tun_xdp_to_ptr(void *ptr)
+{
+ return (void *)((unsigned long)ptr | TUN_XDP_FLAG);
+}
+EXPORT_SYMBOL(tun_xdp_to_ptr);
+
+void *tun_ptr_to_xdp(void *ptr)
+{
+ return (void *)((unsigned long)ptr & ~TUN_XDP_FLAG);
+}
+EXPORT_SYMBOL(tun_ptr_to_xdp);
+
static int tun_napi_receive(struct napi_struct *napi, int budget)
{
struct tun_file *tfile = container_of(napi, struct tun_file, napi);
@@ -630,12 +648,25 @@ static struct tun_struct *tun_enable_queue(struct tun_file *tfile)
return tun;
}
+static void tun_ptr_free(void *ptr)
+{
+ if (!ptr)
+ return;
+ if (tun_is_xdp_buff(ptr)) {
+ struct xdp_buff *xdp = tun_ptr_to_xdp(ptr);
+
+ put_page(virt_to_head_page(xdp->data));
+ } else {
+ __skb_array_destroy_skb(ptr);
+ }
+}
+
static void tun_queue_purge(struct tun_file *tfile)
{
- struct sk_buff *skb;
+ void *ptr;
- while ((skb = ptr_ring_consume(&tfile->tx_ring)) != NULL)
- kfree_skb(skb);
+ while ((ptr = ptr_ring_consume(&tfile->tx_ring)) != NULL)
+ tun_ptr_free(ptr);
skb_queue_purge(&tfile->sk.sk_write_queue);
skb_queue_purge(&tfile->sk.sk_error_queue);
@@ -688,8 +719,7 @@ static void __tun_detach(struct tun_file *tfile, bool clean)
unregister_netdevice(tun->dev);
}
if (tun)
- ptr_ring_cleanup(&tfile->tx_ring,
- __skb_array_destroy_skb);
+ ptr_ring_cleanup(&tfile->tx_ring, tun_ptr_free);
sock_put(&tfile->sk);
}
}
@@ -1201,6 +1231,54 @@ static const struct net_device_ops tun_netdev_ops = {
.ndo_get_stats64 = tun_net_get_stats64,
};
+static int tun_xdp_xmit(struct net_device *dev, struct xdp_buff *xdp)
+{
+ struct tun_struct *tun = netdev_priv(dev);
+ struct xdp_buff *buff = xdp->data_hard_start;
+ int headroom = xdp->data - xdp->data_hard_start;
+ struct tun_file *tfile;
+ u32 numqueues;
+ int ret = 0;
+
+ /* Assure headroom is available and buff is properly aligned */
+ if (unlikely(headroom < sizeof(*xdp) || tun_is_xdp_buff(xdp)))
+ return -ENOSPC;
+
+ *buff = *xdp;
+
+ rcu_read_lock();
+
+ numqueues = READ_ONCE(tun->numqueues);
+ if (!numqueues) {
+ ret = -ENOSPC;
+ goto out;
+ }
+ tfile = rcu_dereference(tun->tfiles[smp_processor_id() %
+ numqueues]);
+ /* Encode the XDP flag into lowest bit for consumer to differ
+ * XDP buffer from sk_buff.
+ */
+ if (ptr_ring_produce(&tfile->tx_ring, tun_xdp_to_ptr(buff))) {
+ this_cpu_inc(tun->pcpu_stats->tx_dropped);
+ ret = -ENOSPC;
+ }
+
+out:
+ rcu_read_unlock();
+ return ret;
+}
+
+static void tun_xdp_flush(struct net_device *dev)
+{
+ struct tun_struct *tun = netdev_priv(dev);
+ struct tun_file *tfile = tun->tfiles[0];
+
+ /* Notify and wake up reader process */
+ if (tfile->flags & TUN_FASYNC)
+ kill_fasync(&tfile->fasync, SIGIO, POLL_IN);
+ tfile->socket.sk->sk_data_ready(tfile->socket.sk);
+}
+
static const struct net_device_ops tap_netdev_ops = {
.ndo_uninit = tun_net_uninit,
.ndo_open = tun_net_open,
@@ -1218,6 +1296,8 @@ static const struct net_device_ops tap_netdev_ops = {
.ndo_set_rx_headroom = tun_set_headroom,
.ndo_get_stats64 = tun_net_get_stats64,
.ndo_bpf = tun_xdp,
+ .ndo_xdp_xmit = tun_xdp_xmit,
+ .ndo_xdp_flush = tun_xdp_flush,
};
static void tun_flow_init(struct tun_struct *tun)
@@ -1841,6 +1921,40 @@ static ssize_t tun_chr_write_iter(struct kiocb *iocb, struct iov_iter *from)
return result;
}
+static ssize_t tun_put_user_xdp(struct tun_struct *tun,
+ struct tun_file *tfile,
+ struct xdp_buff *xdp,
+ struct iov_iter *iter)
+{
+ int vnet_hdr_sz = 0;
+ size_t size = xdp->data_end - xdp->data;
+ struct tun_pcpu_stats *stats;
+ size_t ret;
+
+ if (tun->flags & IFF_VNET_HDR) {
+ struct virtio_net_hdr gso = { 0 };
+
+ vnet_hdr_sz = READ_ONCE(tun->vnet_hdr_sz);
+ if (unlikely(iov_iter_count(iter) < vnet_hdr_sz))
+ return -EINVAL;
+ if (unlikely(copy_to_iter(&gso, sizeof(gso), iter) !=
+ sizeof(gso)))
+ return -EFAULT;
+ iov_iter_advance(iter, vnet_hdr_sz - sizeof(gso));
+ }
+
+ ret = copy_to_iter(xdp->data, size, iter) + vnet_hdr_sz;
+
+ stats = get_cpu_ptr(tun->pcpu_stats);
+ u64_stats_update_begin(&stats->syncp);
+ stats->tx_packets++;
+ stats->tx_bytes += ret;
+ u64_stats_update_end(&stats->syncp);
+ put_cpu_ptr(tun->pcpu_stats);
+
+ return ret;
+}
+
/* Put packet to the user space buffer */
static ssize_t tun_put_user(struct tun_struct *tun,
struct tun_file *tfile,
@@ -1938,15 +2052,14 @@ static ssize_t tun_put_user(struct tun_struct *tun,
return total;
}
-static struct sk_buff *tun_ring_recv(struct tun_file *tfile, int noblock,
- int *err)
+static void *tun_ring_recv(struct tun_file *tfile, int noblock, int *err)
{
DECLARE_WAITQUEUE(wait, current);
- struct sk_buff *skb = NULL;
+ void *ptr = NULL;
int error = 0;
- skb = ptr_ring_consume(&tfile->tx_ring);
- if (skb)
+ ptr = ptr_ring_consume(&tfile->tx_ring);
+ if (ptr)
goto out;
if (noblock) {
error = -EAGAIN;
@@ -1957,8 +2070,8 @@ static struct sk_buff *tun_ring_recv(struct tun_file *tfile, int noblock,
current->state = TASK_INTERRUPTIBLE;
while (1) {
- skb = ptr_ring_consume(&tfile->tx_ring);
- if (skb)
+ ptr = ptr_ring_consume(&tfile->tx_ring);
+ if (ptr)
break;
if (signal_pending(current)) {
error = -ERESTARTSYS;
@@ -1977,36 +2090,42 @@ static struct sk_buff *tun_ring_recv(struct tun_file *tfile, int noblock,
out:
*err = error;
- return skb;
+ return ptr;
}
static ssize_t tun_do_read(struct tun_struct *tun, struct tun_file *tfile,
struct iov_iter *to,
- int noblock, struct sk_buff *skb)
+ int noblock, void *ptr)
{
ssize_t ret;
int err;
tun_debug(KERN_INFO, tun, "tun_do_read\n");
- if (!iov_iter_count(to)) {
- if (skb)
- kfree_skb(skb);
- return 0;
- }
+ if (!iov_iter_count(to))
+ tun_ptr_free(ptr);
- if (!skb) {
+ if (!ptr) {
/* Read frames from ring */
- skb = tun_ring_recv(tfile, noblock, &err);
- if (!skb)
+ ptr = tun_ring_recv(tfile, noblock, &err);
+ if (!ptr)
return err;
}
- ret = tun_put_user(tun, tfile, skb, to);
- if (unlikely(ret < 0))
- kfree_skb(skb);
- else
- consume_skb(skb);
+ if (tun_is_xdp_buff(ptr)) {
+ struct xdp_buff *xdp = tun_ptr_to_xdp(ptr);
+
+ ret = tun_put_user_xdp(tun, tfile, xdp, to);
+ put_page(virt_to_head_page(xdp->data));
+ } else {
+ struct sk_buff *skb = ptr;
+
+ ret = tun_put_user(tun, tfile, skb, to);
+ if (unlikely(ret < 0))
+ kfree_skb(skb);
+ else
+ consume_skb(skb);
+ }
return ret;
}
@@ -2143,12 +2262,12 @@ static int tun_recvmsg(struct socket *sock, struct msghdr *m, size_t total_len,
{
struct tun_file *tfile = container_of(sock, struct tun_file, socket);
struct tun_struct *tun = tun_get(tfile);
- struct sk_buff *skb = m->msg_control;
+ void *ptr = m->msg_control;
int ret;
if (!tun) {
ret = -EBADFD;
- goto out_free_skb;
+ goto out_free;
}
if (flags & ~(MSG_DONTWAIT|MSG_TRUNC|MSG_ERRQUEUE)) {
@@ -2160,7 +2279,7 @@ static int tun_recvmsg(struct socket *sock, struct msghdr *m, size_t total_len,
SOL_PACKET, TUN_TX_TIMESTAMP);
goto out;
}
- ret = tun_do_read(tun, tfile, &m->msg_iter, flags & MSG_DONTWAIT, skb);
+ ret = tun_do_read(tun, tfile, &m->msg_iter, flags & MSG_DONTWAIT, ptr);
if (ret > (ssize_t)total_len) {
m->msg_flags |= MSG_TRUNC;
ret = flags & MSG_TRUNC ? ret : total_len;
@@ -2171,12 +2290,25 @@ static int tun_recvmsg(struct socket *sock, struct msghdr *m, size_t total_len,
out_put_tun:
tun_put(tun);
-out_free_skb:
- if (skb)
- kfree_skb(skb);
+out_free:
+ tun_ptr_free(ptr);
return ret;
}
+static int tun_ptr_peek_len(void *ptr)
+{
+ if (likely(ptr)) {
+ if (tun_is_xdp_buff(ptr)) {
+ struct xdp_buff *xdp = tun_ptr_to_xdp(ptr);
+
+ return xdp->data_end - xdp->data;
+ }
+ return __skb_array_len_with_tag(ptr);
+ } else {
+ return 0;
+ }
+}
+
static int tun_peek_len(struct socket *sock)
{
struct tun_file *tfile = container_of(sock, struct tun_file, socket);
@@ -2187,7 +2319,7 @@ static int tun_peek_len(struct socket *sock)
if (!tun)
return 0;
- ret = PTR_RING_PEEK_CALL(&tfile->tx_ring, __skb_array_len_with_tag);
+ ret = PTR_RING_PEEK_CALL(&tfile->tx_ring, tun_ptr_peek_len);
tun_put(tun);
return ret;
@@ -3110,7 +3242,7 @@ static int tun_queue_resize(struct tun_struct *tun)
ret = ptr_ring_resize_multiple(rings, n,
dev->tx_queue_len, GFP_KERNEL,
- __skb_array_destroy_skb);
+ tun_ptr_free);
kfree(rings);
return ret;
@@ -3191,8 +3323,7 @@ struct socket *tun_get_socket(struct file *file)
struct tun_file *tfile;
if (file->f_op != &tun_fops)
return ERR_PTR(-EINVAL);
- tfile = file->private_data;
- if (!tfile)
+ tfile = file->private_data; if (!tfile)
return ERR_PTR(-EBADFD);
return &tfile->socket;
}
diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c
index c316555..a5a1db6 100644
--- a/drivers/vhost/net.c
+++ b/drivers/vhost/net.c
@@ -175,6 +175,17 @@ static void vhost_net_buf_unproduce(struct vhost_net_virtqueue *nvq)
}
}
+static int vhost_net_buf_peek_len(void *ptr)
+{
+ if (tun_is_xdp_buff(ptr)) {
+ struct xdp_buff *xdp = tun_ptr_to_xdp(ptr);
+
+ return xdp->data_end - xdp->data;
+ }
+
+ return __skb_array_len_with_tag(ptr);
+}
+
static int vhost_net_buf_peek(struct vhost_net_virtqueue *nvq)
{
struct vhost_net_buf *rxq = &nvq->rxq;
@@ -186,7 +197,7 @@ static int vhost_net_buf_peek(struct vhost_net_virtqueue *nvq)
return 0;
out:
- return __skb_array_len_with_tag(vhost_net_buf_get_ptr(rxq));
+ return vhost_net_buf_peek_len(vhost_net_buf_get_ptr(rxq));
}
static void vhost_net_buf_init(struct vhost_net_buf *rxq)
diff --git a/include/linux/if_tun.h b/include/linux/if_tun.h
index bdee9b8..1cafdc2 100644
--- a/include/linux/if_tun.h
+++ b/include/linux/if_tun.h
@@ -17,9 +17,14 @@
#include <uapi/linux/if_tun.h>
+#define TUN_XDP_FLAG 0x1ULL
+
#if defined(CONFIG_TUN) || defined(CONFIG_TUN_MODULE)
struct socket *tun_get_socket(struct file *);
struct ptr_ring *tun_get_tx_ring(struct file *file);
+bool tun_is_xdp_buff(void *ptr);
+void *tun_xdp_to_ptr(void *ptr);
+void *tun_ptr_to_xdp(void *ptr);
#else
#include <linux/err.h>
#include <linux/errno.h>
@@ -33,5 +38,17 @@ static inline struct ptr_ring *tun_get_tx_ring(struct file *f)
{
return ERR_PTR(-EINVAL);
}
+static inline bool tun_is_xdp_buff(void *ptr)
+{
+ return false;
+}
+void *tun_xdp_to_ptr(void *ptr)
+{
+ return NULL;
+}
+void *tun_ptr_to_xdp(void *ptr)
+{
+ return NULL;
+}
#endif /* CONFIG_TUN */
#endif /* __IF_TUN_H */
--
2.7.4
^ permalink raw reply related
* [PATCH net-next 1/2] tun/tap: use ptr_ring instead of skb_array
From: Jason Wang @ 2017-12-29 10:00 UTC (permalink / raw)
To: netdev, linux-kernel; +Cc: mst, jbrouer, Jason Wang
In-Reply-To: <1514541604-12728-1-git-send-email-jasowang@redhat.com>
This patch switches to use ptr_ring instead of skb_array. This will be
used to enqueue different types of pointers by encoding type into
lower bits.
Signed-off-by: Jason Wang <jasowang@redhat.com>
---
drivers/net/tap.c | 41 +++++++++++++++++++++--------------------
drivers/net/tun.c | 42 ++++++++++++++++++++++--------------------
drivers/vhost/net.c | 39 ++++++++++++++++++++-------------------
include/linux/if_tap.h | 6 +++---
include/linux/if_tun.h | 4 ++--
5 files changed, 68 insertions(+), 64 deletions(-)
diff --git a/drivers/net/tap.c b/drivers/net/tap.c
index 0a886fda..7c38659 100644
--- a/drivers/net/tap.c
+++ b/drivers/net/tap.c
@@ -330,7 +330,7 @@ rx_handler_result_t tap_handle_frame(struct sk_buff **pskb)
if (!q)
return RX_HANDLER_PASS;
- if (__skb_array_full(&q->skb_array))
+ if (__ptr_ring_full(&q->ring))
goto drop;
skb_push(skb, ETH_HLEN);
@@ -348,7 +348,7 @@ rx_handler_result_t tap_handle_frame(struct sk_buff **pskb)
goto drop;
if (!segs) {
- if (skb_array_produce(&q->skb_array, skb))
+ if (ptr_ring_produce(&q->ring, skb))
goto drop;
goto wake_up;
}
@@ -358,7 +358,7 @@ rx_handler_result_t tap_handle_frame(struct sk_buff **pskb)
struct sk_buff *nskb = segs->next;
segs->next = NULL;
- if (skb_array_produce(&q->skb_array, segs)) {
+ if (ptr_ring_produce(&q->ring, segs)) {
kfree_skb(segs);
kfree_skb_list(nskb);
break;
@@ -375,7 +375,7 @@ rx_handler_result_t tap_handle_frame(struct sk_buff **pskb)
!(features & NETIF_F_CSUM_MASK) &&
skb_checksum_help(skb))
goto drop;
- if (skb_array_produce(&q->skb_array, skb))
+ if (ptr_ring_produce(&q->ring, skb))
goto drop;
}
@@ -497,7 +497,7 @@ static void tap_sock_destruct(struct sock *sk)
{
struct tap_queue *q = container_of(sk, struct tap_queue, sk);
- skb_array_cleanup(&q->skb_array);
+ ptr_ring_cleanup(&q->ring, __skb_array_destroy_skb);
}
static int tap_open(struct inode *inode, struct file *file)
@@ -517,7 +517,7 @@ static int tap_open(struct inode *inode, struct file *file)
&tap_proto, 0);
if (!q)
goto err;
- if (skb_array_init(&q->skb_array, tap->dev->tx_queue_len, GFP_KERNEL)) {
+ if (ptr_ring_init(&q->ring, tap->dev->tx_queue_len, GFP_KERNEL)) {
sk_free(&q->sk);
goto err;
}
@@ -546,7 +546,7 @@ static int tap_open(struct inode *inode, struct file *file)
err = tap_set_queue(tap, file, q);
if (err) {
- /* tap_sock_destruct() will take care of freeing skb_array */
+ /* tap_sock_destruct() will take care of freeing ptr_ring */
goto err_put;
}
@@ -583,7 +583,7 @@ static unsigned int tap_poll(struct file *file, poll_table *wait)
mask = 0;
poll_wait(file, &q->wq.wait, wait);
- if (!skb_array_empty(&q->skb_array))
+ if (!ptr_ring_empty(&q->ring))
mask |= POLLIN | POLLRDNORM;
if (sock_writeable(&q->sk) ||
@@ -844,7 +844,7 @@ static ssize_t tap_do_read(struct tap_queue *q,
TASK_INTERRUPTIBLE);
/* Read frames from the queue */
- skb = skb_array_consume(&q->skb_array);
+ skb = ptr_ring_consume(&q->ring);
if (skb)
break;
if (noblock) {
@@ -1176,7 +1176,7 @@ static int tap_peek_len(struct socket *sock)
{
struct tap_queue *q = container_of(sock, struct tap_queue,
sock);
- return skb_array_peek_len(&q->skb_array);
+ return PTR_RING_PEEK_CALL(&q->ring, __skb_array_len_with_tag);
}
/* Ops structure to mimic raw sockets with tun */
@@ -1202,7 +1202,7 @@ struct socket *tap_get_socket(struct file *file)
}
EXPORT_SYMBOL_GPL(tap_get_socket);
-struct skb_array *tap_get_skb_array(struct file *file)
+struct ptr_ring *tap_get_ptr_ring(struct file *file)
{
struct tap_queue *q;
@@ -1211,29 +1211,30 @@ struct skb_array *tap_get_skb_array(struct file *file)
q = file->private_data;
if (!q)
return ERR_PTR(-EBADFD);
- return &q->skb_array;
+ return &q->ring;
}
-EXPORT_SYMBOL_GPL(tap_get_skb_array);
+EXPORT_SYMBOL_GPL(tap_get_ptr_ring);
int tap_queue_resize(struct tap_dev *tap)
{
struct net_device *dev = tap->dev;
struct tap_queue *q;
- struct skb_array **arrays;
+ struct ptr_ring **rings;
int n = tap->numqueues;
int ret, i = 0;
- arrays = kmalloc_array(n, sizeof(*arrays), GFP_KERNEL);
- if (!arrays)
+ rings = kmalloc_array(n, sizeof(*rings), GFP_KERNEL);
+ if (!rings)
return -ENOMEM;
list_for_each_entry(q, &tap->queue_list, next)
- arrays[i++] = &q->skb_array;
+ rings[i++] = &q->ring;
- ret = skb_array_resize_multiple(arrays, n,
- dev->tx_queue_len, GFP_KERNEL);
+ ret = ptr_ring_resize_multiple(rings, n,
+ dev->tx_queue_len, GFP_KERNEL,
+ __skb_array_destroy_skb);
- kfree(arrays);
+ kfree(rings);
return ret;
}
EXPORT_SYMBOL_GPL(tap_queue_resize);
diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index e367d631..2c89efe 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -179,7 +179,7 @@ struct tun_file {
struct mutex napi_mutex; /* Protects access to the above napi */
struct list_head next;
struct tun_struct *detached;
- struct skb_array tx_array;
+ struct ptr_ring tx_ring;
};
struct tun_flow_entry {
@@ -634,7 +634,7 @@ static void tun_queue_purge(struct tun_file *tfile)
{
struct sk_buff *skb;
- while ((skb = skb_array_consume(&tfile->tx_array)) != NULL)
+ while ((skb = ptr_ring_consume(&tfile->tx_ring)) != NULL)
kfree_skb(skb);
skb_queue_purge(&tfile->sk.sk_write_queue);
@@ -688,7 +688,8 @@ static void __tun_detach(struct tun_file *tfile, bool clean)
unregister_netdevice(tun->dev);
}
if (tun)
- skb_array_cleanup(&tfile->tx_array);
+ ptr_ring_cleanup(&tfile->tx_ring,
+ __skb_array_destroy_skb);
sock_put(&tfile->sk);
}
}
@@ -777,7 +778,7 @@ static int tun_attach(struct tun_struct *tun, struct file *file,
}
if (!tfile->detached &&
- skb_array_init(&tfile->tx_array, dev->tx_queue_len, GFP_KERNEL)) {
+ ptr_ring_init(&tfile->tx_ring, dev->tx_queue_len, GFP_KERNEL)) {
err = -ENOMEM;
goto out;
}
@@ -1027,7 +1028,7 @@ static netdev_tx_t tun_net_xmit(struct sk_buff *skb, struct net_device *dev)
nf_reset(skb);
- if (skb_array_produce(&tfile->tx_array, skb))
+ if (ptr_ring_produce(&tfile->tx_ring, skb))
goto drop;
/* Notify and wake up reader process */
@@ -1295,7 +1296,7 @@ static unsigned int tun_chr_poll(struct file *file, poll_table *wait)
poll_wait(file, sk_sleep(sk), wait);
- if (!skb_array_empty(&tfile->tx_array))
+ if (!ptr_ring_empty(&tfile->tx_ring))
mask |= POLLIN | POLLRDNORM;
if (tun->dev->flags & IFF_UP &&
@@ -1944,7 +1945,7 @@ static struct sk_buff *tun_ring_recv(struct tun_file *tfile, int noblock,
struct sk_buff *skb = NULL;
int error = 0;
- skb = skb_array_consume(&tfile->tx_array);
+ skb = ptr_ring_consume(&tfile->tx_ring);
if (skb)
goto out;
if (noblock) {
@@ -1956,7 +1957,7 @@ static struct sk_buff *tun_ring_recv(struct tun_file *tfile, int noblock,
current->state = TASK_INTERRUPTIBLE;
while (1) {
- skb = skb_array_consume(&tfile->tx_array);
+ skb = ptr_ring_consume(&tfile->tx_ring);
if (skb)
break;
if (signal_pending(current)) {
@@ -2186,7 +2187,7 @@ static int tun_peek_len(struct socket *sock)
if (!tun)
return 0;
- ret = skb_array_peek_len(&tfile->tx_array);
+ ret = PTR_RING_PEEK_CALL(&tfile->tx_ring, __skb_array_len_with_tag);
tun_put(tun);
return ret;
@@ -3092,25 +3093,26 @@ static int tun_queue_resize(struct tun_struct *tun)
{
struct net_device *dev = tun->dev;
struct tun_file *tfile;
- struct skb_array **arrays;
+ struct ptr_ring **rings;
int n = tun->numqueues + tun->numdisabled;
int ret, i;
- arrays = kmalloc_array(n, sizeof(*arrays), GFP_KERNEL);
- if (!arrays)
+ rings = kmalloc_array(n, sizeof(*rings), GFP_KERNEL);
+ if (!rings)
return -ENOMEM;
for (i = 0; i < tun->numqueues; i++) {
tfile = rtnl_dereference(tun->tfiles[i]);
- arrays[i] = &tfile->tx_array;
+ rings[i] = &tfile->tx_ring;
}
list_for_each_entry(tfile, &tun->disabled, next)
- arrays[i++] = &tfile->tx_array;
+ rings[i++] = &tfile->tx_ring;
- ret = skb_array_resize_multiple(arrays, n,
- dev->tx_queue_len, GFP_KERNEL);
+ ret = ptr_ring_resize_multiple(rings, n,
+ dev->tx_queue_len, GFP_KERNEL,
+ __skb_array_destroy_skb);
- kfree(arrays);
+ kfree(rings);
return ret;
}
@@ -3196,7 +3198,7 @@ struct socket *tun_get_socket(struct file *file)
}
EXPORT_SYMBOL_GPL(tun_get_socket);
-struct skb_array *tun_get_skb_array(struct file *file)
+struct ptr_ring *tun_get_tx_ring(struct file *file)
{
struct tun_file *tfile;
@@ -3205,9 +3207,9 @@ struct skb_array *tun_get_skb_array(struct file *file)
tfile = file->private_data;
if (!tfile)
return ERR_PTR(-EBADFD);
- return &tfile->tx_array;
+ return &tfile->tx_ring;
}
-EXPORT_SYMBOL_GPL(tun_get_skb_array);
+EXPORT_SYMBOL_GPL(tun_get_tx_ring);
module_init(tun_init);
module_exit(tun_cleanup);
diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c
index c7bdeb6..c316555 100644
--- a/drivers/vhost/net.c
+++ b/drivers/vhost/net.c
@@ -89,7 +89,7 @@ struct vhost_net_ubuf_ref {
#define VHOST_RX_BATCH 64
struct vhost_net_buf {
- struct sk_buff **queue;
+ void **queue;
int tail;
int head;
};
@@ -108,7 +108,7 @@ struct vhost_net_virtqueue {
/* Reference counting for outstanding ubufs.
* Protected by vq mutex. Writers must also take device mutex. */
struct vhost_net_ubuf_ref *ubufs;
- struct skb_array *rx_array;
+ struct ptr_ring *rx_ring;
struct vhost_net_buf rxq;
};
@@ -158,7 +158,7 @@ static int vhost_net_buf_produce(struct vhost_net_virtqueue *nvq)
struct vhost_net_buf *rxq = &nvq->rxq;
rxq->head = 0;
- rxq->tail = skb_array_consume_batched(nvq->rx_array, rxq->queue,
+ rxq->tail = ptr_ring_consume_batched(nvq->rx_ring, rxq->queue,
VHOST_RX_BATCH);
return rxq->tail;
}
@@ -167,9 +167,10 @@ static void vhost_net_buf_unproduce(struct vhost_net_virtqueue *nvq)
{
struct vhost_net_buf *rxq = &nvq->rxq;
- if (nvq->rx_array && !vhost_net_buf_is_empty(rxq)) {
- skb_array_unconsume(nvq->rx_array, rxq->queue + rxq->head,
- vhost_net_buf_get_size(rxq));
+ if (nvq->rx_ring && !vhost_net_buf_is_empty(rxq)) {
+ ptr_ring_unconsume(nvq->rx_ring, rxq->queue + rxq->head,
+ vhost_net_buf_get_size(rxq),
+ __skb_array_destroy_skb);
rxq->head = rxq->tail = 0;
}
}
@@ -583,7 +584,7 @@ static int peek_head_len(struct vhost_net_virtqueue *rvq, struct sock *sk)
int len = 0;
unsigned long flags;
- if (rvq->rx_array)
+ if (rvq->rx_ring)
return vhost_net_buf_peek(rvq);
spin_lock_irqsave(&sk->sk_receive_queue.lock, flags);
@@ -790,7 +791,7 @@ static void handle_rx(struct vhost_net *net)
* they refilled. */
goto out;
}
- if (nvq->rx_array)
+ if (nvq->rx_ring)
msg.msg_control = vhost_net_buf_consume(&nvq->rxq);
/* On overrun, truncate and discard */
if (unlikely(headcount > UIO_MAXIOV)) {
@@ -896,7 +897,7 @@ static int vhost_net_open(struct inode *inode, struct file *f)
struct vhost_net *n;
struct vhost_dev *dev;
struct vhost_virtqueue **vqs;
- struct sk_buff **queue;
+ void **queue;
int i;
n = kvmalloc(sizeof *n, GFP_KERNEL | __GFP_RETRY_MAYFAIL);
@@ -908,7 +909,7 @@ static int vhost_net_open(struct inode *inode, struct file *f)
return -ENOMEM;
}
- queue = kmalloc_array(VHOST_RX_BATCH, sizeof(struct sk_buff *),
+ queue = kmalloc_array(VHOST_RX_BATCH, sizeof(void *),
GFP_KERNEL);
if (!queue) {
kfree(vqs);
@@ -1046,23 +1047,23 @@ static struct socket *get_raw_socket(int fd)
return ERR_PTR(r);
}
-static struct skb_array *get_tap_skb_array(int fd)
+static struct ptr_ring *get_tap_ptr_ring(int fd)
{
- struct skb_array *array;
+ struct ptr_ring *ring;
struct file *file = fget(fd);
if (!file)
return NULL;
- array = tun_get_skb_array(file);
- if (!IS_ERR(array))
+ ring = tun_get_tx_ring(file);
+ if (!IS_ERR(ring))
goto out;
- array = tap_get_skb_array(file);
- if (!IS_ERR(array))
+ ring = tap_get_ptr_ring(file);
+ if (!IS_ERR(ring))
goto out;
- array = NULL;
+ ring = NULL;
out:
fput(file);
- return array;
+ return ring;
}
static struct socket *get_tap_socket(int fd)
@@ -1143,7 +1144,7 @@ static long vhost_net_set_backend(struct vhost_net *n, unsigned index, int fd)
vq->private_data = sock;
vhost_net_buf_unproduce(nvq);
if (index == VHOST_NET_VQ_RX)
- nvq->rx_array = get_tap_skb_array(fd);
+ nvq->rx_ring = get_tap_ptr_ring(fd);
r = vhost_vq_init_access(vq);
if (r)
goto err_used;
diff --git a/include/linux/if_tap.h b/include/linux/if_tap.h
index 3ecef57..8e66866 100644
--- a/include/linux/if_tap.h
+++ b/include/linux/if_tap.h
@@ -4,7 +4,7 @@
#if IS_ENABLED(CONFIG_TAP)
struct socket *tap_get_socket(struct file *);
-struct skb_array *tap_get_skb_array(struct file *file);
+struct ptr_ring *tap_get_ptr_ring(struct file *file);
#else
#include <linux/err.h>
#include <linux/errno.h>
@@ -14,7 +14,7 @@ static inline struct socket *tap_get_socket(struct file *f)
{
return ERR_PTR(-EINVAL);
}
-static inline struct skb_array *tap_get_skb_array(struct file *f)
+static inline struct ptr_ring *tap_get_ptr_ring(struct file *f)
{
return ERR_PTR(-EINVAL);
}
@@ -70,7 +70,7 @@ struct tap_queue {
u16 queue_index;
bool enabled;
struct list_head next;
- struct skb_array skb_array;
+ struct ptr_ring ring;
};
rx_handler_result_t tap_handle_frame(struct sk_buff **pskb);
diff --git a/include/linux/if_tun.h b/include/linux/if_tun.h
index bf9bdf4..bdee9b8 100644
--- a/include/linux/if_tun.h
+++ b/include/linux/if_tun.h
@@ -19,7 +19,7 @@
#if defined(CONFIG_TUN) || defined(CONFIG_TUN_MODULE)
struct socket *tun_get_socket(struct file *);
-struct skb_array *tun_get_skb_array(struct file *file);
+struct ptr_ring *tun_get_tx_ring(struct file *file);
#else
#include <linux/err.h>
#include <linux/errno.h>
@@ -29,7 +29,7 @@ static inline struct socket *tun_get_socket(struct file *f)
{
return ERR_PTR(-EINVAL);
}
-static inline struct skb_array *tun_get_skb_array(struct file *f)
+static inline struct ptr_ring *tun_get_tx_ring(struct file *f)
{
return ERR_PTR(-EINVAL);
}
--
2.7.4
^ permalink raw reply related
* [PATCH net-next 0/2] XDP transmission for tuntap
From: Jason Wang @ 2017-12-29 10:00 UTC (permalink / raw)
To: netdev, linux-kernel; +Cc: mst, jbrouer, Jason Wang
Hi all:
This series tries to implement XDP transmission (ndo_xdp_xmit) for
tuntap. Pointer ring was used for queuing both XDP buffers and
sk_buff, this is done by encoding the type into lowest bit of the
pointer and storin XDP metadata in the headroom of XDP buff.
Tests gets 3.05 Mpps when doing xdp_redirect_map from ixgbe to VM
(testpmd + virtio-net in guest).
Please review.
Thanks
Jason Wang (2):
tun/tap: use ptr_ring instead of skb_array
tuntap: XDP transmission
drivers/net/tap.c | 41 ++++-----
drivers/net/tun.c | 233 ++++++++++++++++++++++++++++++++++++++-----------
drivers/vhost/net.c | 52 ++++++-----
include/linux/if_tap.h | 6 +-
include/linux/if_tun.h | 21 ++++-
5 files changed, 258 insertions(+), 95 deletions(-)
--
2.7.4
^ permalink raw reply
* [PATCH net-next] net: hns: add ACPI mode support for ethtool -p
From: Peng Li @ 2017-12-29 9:11 UTC (permalink / raw)
To: davem; +Cc: netdev, linux-kernel, linuxarm, salil.mehta, lipeng321
From: Jian Shen <shenjian15@huawei.com>
The locate operation interface of fiber port can only
work with DT mode. Add a new interface to control the
locate led for ACPI mode.
Signed-off-by: Jian Shen <shenjian15@huawei.com>
Signed-off-by: Peng Li <lipeng321@huawei.com>
Tested-by: Zhou Wang <wangzhou1@hisilicon.com>
---
drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c | 2 +-
drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.c | 57 +++++++++++++++++++++-
2 files changed, 57 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c
index 8b5cdf4..cac86e9 100644
--- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c
+++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c
@@ -1168,7 +1168,7 @@ void hns_set_led_opt(struct hns_mac_cb *mac_cb)
int hns_cpld_led_set_id(struct hns_mac_cb *mac_cb,
enum hnae_led_state status)
{
- if (!mac_cb || !mac_cb->cpld_ctrl)
+ if (!mac_cb)
return 0;
return mac_cb->dsaf_dev->misc_op->cpld_set_led_id(mac_cb, status);
diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.c
index 408b63f..ca247c2 100644
--- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.c
+++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.c
@@ -18,6 +18,7 @@ enum _dsm_op_index {
HNS_OP_LED_SET_FUNC = 0x3,
HNS_OP_GET_PORT_TYPE_FUNC = 0x4,
HNS_OP_GET_SFP_STAT_FUNC = 0x5,
+ HNS_OP_LOCATE_LED_SET_FUNC = 0x6,
};
enum _dsm_rst_type {
@@ -81,6 +82,33 @@ static void hns_dsaf_acpi_ledctrl_by_port(struct hns_mac_cb *mac_cb, u8 op_type,
ACPI_FREE(obj);
}
+static void hns_dsaf_acpi_locate_ledctrl_by_port(struct hns_mac_cb *mac_cb,
+ u8 op_type, u32 locate,
+ u32 port)
+{
+ union acpi_object obj_args[2], argv4;
+ union acpi_object *obj;
+
+ obj_args[0].integer.type = ACPI_TYPE_INTEGER;
+ obj_args[0].integer.value = locate;
+ obj_args[1].integer.type = ACPI_TYPE_INTEGER;
+ obj_args[1].integer.value = port;
+
+ argv4.type = ACPI_TYPE_PACKAGE;
+ argv4.package.count = 2;
+ argv4.package.elements = obj_args;
+
+ obj = acpi_evaluate_dsm(ACPI_HANDLE(mac_cb->dev),
+ &hns_dsaf_acpi_dsm_guid, 0, op_type, &argv4);
+ if (!obj) {
+ dev_err(mac_cb->dev, "ledctrl fail, locate:%d port:%d!\n",
+ locate, port);
+ return;
+ }
+
+ ACPI_FREE(obj);
+}
+
static void hns_cpld_set_led(struct hns_mac_cb *mac_cb, int link_status,
u16 speed, int data)
{
@@ -160,6 +188,9 @@ static void cpld_led_reset_acpi(struct hns_mac_cb *mac_cb)
static int cpld_set_led_id(struct hns_mac_cb *mac_cb,
enum hnae_led_state status)
{
+ if (!mac_cb->cpld_ctrl)
+ return 0;
+
switch (status) {
case HNAE_LED_ACTIVE:
mac_cb->cpld_led_value =
@@ -184,6 +215,30 @@ static int cpld_set_led_id(struct hns_mac_cb *mac_cb,
return 0;
}
+static int cpld_set_led_id_acpi(struct hns_mac_cb *mac_cb,
+ enum hnae_led_state status)
+{
+ switch (status) {
+ case HNAE_LED_ACTIVE:
+ hns_dsaf_acpi_locate_ledctrl_by_port(mac_cb,
+ HNS_OP_LOCATE_LED_SET_FUNC,
+ CPLD_LED_ON_VALUE,
+ mac_cb->mac_id);
+ break;
+ case HNAE_LED_INACTIVE:
+ hns_dsaf_acpi_locate_ledctrl_by_port(mac_cb,
+ HNS_OP_LOCATE_LED_SET_FUNC,
+ CPLD_LED_DEFAULT_VALUE,
+ mac_cb->mac_id);
+ break;
+ default:
+ dev_err(mac_cb->dev, "invalid led state: %d!", status);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
#define RESET_REQ_OR_DREQ 1
static void hns_dsaf_acpi_srst_by_port(struct dsaf_device *dsaf_dev, u8 op_type,
@@ -660,7 +715,7 @@ struct dsaf_misc_op *hns_misc_op_get(struct dsaf_device *dsaf_dev)
} else if (is_acpi_node(dsaf_dev->dev->fwnode)) {
misc_op->cpld_set_led = hns_cpld_set_led_acpi;
misc_op->cpld_reset_led = cpld_led_reset_acpi;
- misc_op->cpld_set_led_id = cpld_set_led_id;
+ misc_op->cpld_set_led_id = cpld_set_led_id_acpi;
misc_op->dsaf_reset = hns_dsaf_rst_acpi;
misc_op->xge_srst = hns_dsaf_xge_srst_by_port_acpi;
--
1.9.1
^ permalink raw reply related
* [PATCH][V2] wcn36xx: fix incorrect assignment to msg_body.min_ch_time
From: Colin King @ 2017-12-29 9:07 UTC (permalink / raw)
To: Eugene Krasnikov, Kalle Valo, wcn36xx, linux-wireless, netdev
Cc: kernel-janitors, linux-kernel
In-Reply-To: <20171229090732.14928-1-colin.king@canonical.com>
From: Colin Ian King <colin.king@canonical.com>
The second assignment to msg_body.min_ch_time is incorrect, it
should actually be to msg_body.max_ch_time.
Thanks to Bjorn Andersson for identifying the correct way to fix
this as my original fix was incorrect.
Detected by CoverityScan, CID#1463042 ("Unused Value")
Fixes: 2f3bef4b247e ("wcn36xx: Add hardware scan offload support")
Signed-off-by: Colin Ian King <colin.king@canonical.com>
---
drivers/net/wireless/ath/wcn36xx/smd.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/wireless/ath/wcn36xx/smd.c b/drivers/net/wireless/ath/wcn36xx/smd.c
index 2914618a0335..2a4871ca9c72 100644
--- a/drivers/net/wireless/ath/wcn36xx/smd.c
+++ b/drivers/net/wireless/ath/wcn36xx/smd.c
@@ -626,7 +626,7 @@ int wcn36xx_smd_start_hw_scan(struct wcn36xx *wcn, struct ieee80211_vif *vif,
msg_body.scan_type = WCN36XX_HAL_SCAN_TYPE_ACTIVE;
msg_body.min_ch_time = 30;
- msg_body.min_ch_time = 100;
+ msg_body.max_ch_time = 100;
msg_body.scan_hidden = 1;
memcpy(msg_body.mac, vif->addr, ETH_ALEN);
msg_body.p2p_search = vif->p2p;
--
2.14.1
^ permalink raw reply related
* [PATCH][V2] wcn36xx: fix incorrect assignment to msg_body.min_ch_time
From: Colin King @ 2017-12-29 9:07 UTC (permalink / raw)
To: Eugene Krasnikov, Kalle Valo, wcn36xx, linux-wireless, netdev
Cc: kernel-janitors, linux-kernel
From: Colin Ian King <colin.king@canonical.com>
The second assignment to msg_body.min_ch_time is incorrect, it
should actually be to msg_body.max_ch_time.
Thanks to Bjorn Andersson for identifying the correct way to fix
this as my original fix was incorrect.
Detected by CoverityScan, CID#1463042 ("Unused Value")
Fixes: 2f3bef4b247e ("wcn36xx: Add hardware scan offload support")
Signed-off-by: Colin Ian King <colin.king@canonical.com>
---
drivers/net/wireless/ath/wcn36xx/smd.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/wireless/ath/wcn36xx/smd.c b/drivers/net/wireless/ath/wcn36xx/smd.c
index 2914618a0335..2a4871ca9c72 100644
--- a/drivers/net/wireless/ath/wcn36xx/smd.c
+++ b/drivers/net/wireless/ath/wcn36xx/smd.c
@@ -626,7 +626,7 @@ int wcn36xx_smd_start_hw_scan(struct wcn36xx *wcn, struct ieee80211_vif *vif,
msg_body.scan_type = WCN36XX_HAL_SCAN_TYPE_ACTIVE;
msg_body.min_ch_time = 30;
- msg_body.min_ch_time = 100;
+ msg_body.max_ch_time = 100;
msg_body.scan_hidden = 1;
memcpy(msg_body.mac, vif->addr, ETH_ALEN);
msg_body.p2p_search = vif->p2p;
--
2.14.1
^ permalink raw reply related
* [PATCH] NET: usb: qmi_wwan: add support for YUGA CLM920-NC5 PID 0x9625
From: SZ Lin (林上智) @ 2017-12-29 9:02 UTC (permalink / raw)
Cc: SZ Lin (林上智), Bjørn Mork, netdev,
linux-usb, linux-kernel
This patch adds support for PID 0x9625 of YUGA CLM920-NC5.
YUGA CLM920-NC5 needs to enable QMI_WWAN_QUIRK_DTR before QMI operation.
qmicli -d /dev/cdc-wdm0 -p --dms-get-revision
[/dev/cdc-wdm0] Device revision retrieved:
Revision: 'CLM920_NC5-V1 1 [Oct 23 2016 19:00:00]'
Signed-off-by: SZ Lin (林上智) <sz.lin@moxa.com>
---
drivers/net/usb/qmi_wwan.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c
index 3000ddd1c7e2..728819feab44 100644
--- a/drivers/net/usb/qmi_wwan.c
+++ b/drivers/net/usb/qmi_wwan.c
@@ -1100,6 +1100,7 @@ static const struct usb_device_id products[] = {
{QMI_FIXED_INTF(0x05c6, 0x9084, 4)},
{QMI_FIXED_INTF(0x05c6, 0x920d, 0)},
{QMI_FIXED_INTF(0x05c6, 0x920d, 5)},
+ {QMI_QUIRK_SET_DTR(0x05c6, 0x9625, 4)}, /* YUGA CLM920-NC5 */
{QMI_FIXED_INTF(0x0846, 0x68a2, 8)},
{QMI_FIXED_INTF(0x12d1, 0x140c, 1)}, /* Huawei E173 */
{QMI_FIXED_INTF(0x12d1, 0x14ac, 1)}, /* Huawei E1820 */
--
2.15.1
^ permalink raw reply related
* Re: iproute2 net-next
From: Jiri Pirko @ 2017-12-29 8:58 UTC (permalink / raw)
To: Daniel Borkmann; +Cc: Leon Romanovsky, Stephen Hemminger, netdev, dsa
In-Reply-To: <5f75c535-e4a0-1cfa-d4b0-c3c60d50a1c6@iogearbox.net>
Fri, Dec 29, 2017 at 12:46:31AM CET, daniel@iogearbox.net wrote:
>On 12/26/2017 10:35 AM, Leon Romanovsky wrote:
>> On Mon, Dec 25, 2017 at 10:14:26PM -0800, Stephen Hemminger wrote:
>>> On Tue, 26 Dec 2017 06:47:43 +0200
>>> Leon Romanovsky <leon@kernel.org> wrote:
>>>
>>>> On Mon, Dec 25, 2017 at 10:49:19AM -0800, Stephen Hemminger wrote:
>>>>> David Ahern has agreed to take over managing the net-next branch of iproute2.
>>>>> The new location is:
>>>>> https://git.kernel.org/pub/scm/linux/kernel/git/dsahern/iproute2-next.git/
>>>>>
>>>>> In the past, I have accepted new features into iproute2 master branch, but
>>>>> am changing the policy so that outside of the merge window (up until -rc1)
>>>>> new features will get put into net-next to get some more review and testing
>>>>> time. This means that things like the proposed batch streaming mode will
>>>>> go through net-next.
>>>>
>>>> Did you consider to create one shared repo for the iproute2 to allow
>>>> multiple committers workflow?
>>>
>>> For now having separate trees is best, there is no need for multiple
>>> committers the load is very light.
>>>
>>>> It will be much convenient for the users to have one place for
>>>> master/stable/net-next branches, instead of actually following two
>>>> different repositories.
>>>
>>> If you are doing network development, you already need to deal with
>>> multiple repo's on the kernel side so there is no difference.
>>
>> I agree with you that one extra "git remote add .." is not so huge and
>> all people who develop for the netdev will do it. My concern is about
>> Documentation and newcomers, who will have a hard time to find a right
>> tree.
>
>I guess it would certainly help to identify the official repo to rebase
>against much quicker if it would be under a common group on korg e.g.
>
> * iproute2/iproute2.git - for current cycle
> * iproute2/iproute2-next.git - for net-next bits
>
>and also be in line with other tooling (ethtool and others), even if
>not as high volume, but it would make it unambiguous right away from
>the other, private iproute2 repos on korg, imho. Just a thought.
+1
I was about to suggest this. This is nice opportunity to do such change.
>
>>>> Example, of such shared repo:
>>>> BPF: https://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next.git/
>>>> Bluetooth: https://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth-next.git/
>>>> RDMA: https://git.kernel.org/pub/scm/linux/kernel/git/rdma/rdma.git/
>>>
>>> Most of these are high volume or vendor silo'd which is not the case here.
>Cheers,
>Daniel
^ permalink raw reply
* Re: [RFC PATCH bpf-next v2 1/4] tracing/kprobe: bpf: Check error injectable event is on function entry
From: Masami Hiramatsu @ 2017-12-29 8:20 UTC (permalink / raw)
To: Alexei Starovoitov
Cc: Steven Rostedt, Alexei Starovoitov, Josef Bacik, mingo, davem,
netdev, linux-kernel, ast, kernel-team, daniel, linux-btrfs,
darrick.wong, Josef Bacik, Akinobu Mita
In-Reply-To: <b6057235-a1f4-a461-a2d5-295e964249ea@fb.com>
On Thu, 28 Dec 2017 17:03:24 -0800
Alexei Starovoitov <ast@fb.com> wrote:
> On 12/28/17 12:20 AM, Masami Hiramatsu wrote:
> > On Wed, 27 Dec 2017 20:32:07 -0800
> > Alexei Starovoitov <ast@fb.com> wrote:
> >
> >> On 12/27/17 8:16 PM, Steven Rostedt wrote:
> >>> On Wed, 27 Dec 2017 19:45:42 -0800
> >>> Alexei Starovoitov <ast@fb.com> wrote:
> >>>
> >>>> I don't think that's the case. My reading of current
> >>>> trace_kprobe_ftrace() -> arch_check_ftrace_location()
> >>>> is that it will not be true for old mcount case.
> >>>
> >>> In the old mcount case, you can't use ftrace to return without calling
> >>> the function. That is, no modification of the return ip, unless you
> >>> created a trampoline that could handle arbitrary stack frames, and
> >>> remove them from the stack before returning back to the function.
> >>
> >> correct. I was saying that trace_kprobe_ftrace() won't let us do
> >> bpf_override_return with old mcount.
> >
> > No, trace_kprobe_ftrace() just checks the given address will be
> > managed by ftrace. you can see arch_check_ftrace_location() in kernel/kprobes.c.
> >
> > FYI, CONFIG_KPROBES_ON_FTRACE depends on DYNAMIC_FTRACE_WITH_REGS, and
> > DYNAMIC_FTRACE_WITH_REGS doesn't depend on CC_USING_FENTRY.
> > This means if you compile kernel with old gcc and enable DYNAMIC_FTRACE,
> > kprobes uses ftrace on mcount address which is NOT the entry point
> > of target function.
>
> ok. fair enough. I think we can gate the feature to !mcount only.
>
> > On the other hand, changing IP feature has been implemented originaly
> > by kprobes with int3 (sw breakpoint). This means you can use kprobes
> > at correct address (the entry address of the function) you can hijack
> > the function, as jprobe did.
> >
> >>>> As far as the rest of your arguments it very much puzzles me that
> >>>> you claim that this patch suppose to work based on historical
> >>>> reasoning whereas you did NOT test it.
> >>>
> >>> I believe that Masami is saying that the modification of the IP from
> >>> kprobes has been very well tested. But I'm guessing that you still want
> >>> a test case for using kprobes in this particular instance. It's not the
> >>> implementation of modifying the IP that you are worried about, but the
> >>> implementation of BPF using it in this case. Right?
> >>
> >> exactly. No doubt that old code works.
> >> But it doesn't mean that bpf_override_return() will continue to
> >> work in kprobes that are not ftrace based.
> >> I suspect Josef's existing test case will cover this situation.
> >> Probably only special .config is needed to disable ftrace, so
> >> "kprobe on entry but not ftrace" check will kick in.
> >
> > Right. If you need to test it, you can run Josef's test case without
> > CONFIG_DYNAMIC_FTRACE.
>
> It should be obvious that the person who submits the patch
> must run the tests.
>
> >> But I didn't get an impression that this situation was tested.
> >> Instead I see only logical reasoning that it's _supposed_ to work.
> >> That's not enough.
> >
> > OK, so would you just ask me to run samples/bpf ?
>
> Please run Josef's test in the !ftrace setup.
Yes, I'll add the result of the test case.
Thank you,
--
Masami Hiramatsu <mhiramat@kernel.org>
^ permalink raw reply
* Re: [PATCH net 3/3] eet: ena: invoke netif_carrier_off() only after netdev registered
From: Jakub Kicinski @ 2017-12-29 8:09 UTC (permalink / raw)
To: Belgazal, Netanel
Cc: davem@davemloft.net, netdev@vger.kernel.org, Woodhouse, David,
Machulsky, Zorik, Matushevsky, Alexander, Bshara, Saeed,
Wilson, Matt, Liguori, Anthony, Bshara, Nafea, Schmeilin, Evgeny,
Tzalik, Guy
In-Reply-To: <B0951795-C990-49ED-9972-CDEED0F160A6@amazon.com>
On Fri, 29 Dec 2017 08:00:33 +0000, Belgazal, Netanel wrote:
> Yes, I mean in my driver.
> netif_carrier_off() have no effect when netdev is uninitialized.
Please look at the implementation again, test_*and_set*_bit().
> So I must call it after register_netdev().
Is there a user-visible problem you're trying to solve here?
^ permalink raw reply
* Re: [PATCH net 3/3] eet: ena: invoke netif_carrier_off() only after netdev registered
From: Belgazal, Netanel @ 2017-12-29 8:00 UTC (permalink / raw)
To: Jakub Kicinski
Cc: davem@davemloft.net, netdev@vger.kernel.org, Woodhouse, David,
Machulsky, Zorik, Matushevsky, Alexander, Bshara, Saeed,
Wilson, Matt, Liguori, Anthony, Bshara, Nafea, Schmeilin, Evgeny,
Tzalik, Guy
In-Reply-To: <20171228234603.436ba946@cakuba.netronome.com>
Yes, I mean in my driver.
netif_carrier_off() have no effect when netdev is uninitialized.
So I must call it after register_netdev().
On 12/29/17, 9:46 AM, "Jakub Kicinski" <kubakici@wp.pl> wrote:
By "should" you mean in your driver, right? I think calling
netif_carrier_off() on an unregistered netdev is a pretty standard
thing to do for drivers which manage carrier state.
^ permalink raw reply
* Re: [RFT net-next v3 0/5] dwmac-meson8b: RGMII clock fixes for Meson8b
From: Martin Blumenstingl @ 2017-12-29 7:52 UTC (permalink / raw)
To: Emiliano Ingrassia
Cc: netdev, linus.luessing, khilman, linux-amlogic, jbrunet,
Neil Armstrong, peppe.cavallaro, alexandre.torgue
In-Reply-To: <CAFBinCDVRNKBTG0CHcmV9iJ9gb2VeODCfU6BO+dyRU6bVwkffg@mail.gmail.com>
On Fri, Dec 29, 2017 at 8:48 AM, Martin Blumenstingl
<martin.blumenstingl@googlemail.com> wrote:
> Hi Emiliano,
>
> On Fri, Dec 29, 2017 at 2:31 AM, Emiliano Ingrassia
> <ingrassia@epigenesys.com> wrote:
>> Hi Martin, Hi Dave,
>>
>> On Thu, Dec 28, 2017 at 11:21:23PM +0100, Martin Blumenstingl wrote:
>>> Hi Dave,
>>>
>>> please do not apply this series until it got a Tested-by from Emiliano.
>>>
>>>
>>> Hi Emiliano,
>>>
>>> you reported [0] that you couldn't get dwmac-meson8b to work on your
>>> Odroid-C1. With your findings (register dumps, clk_summary output, etc.)
>>> I think I was able to find a fix: it consists of two patches (which you
>>> find in this series)
>>>
>>> Unfortunately I don't have any Meson8b boards with RGMII PHY so I could
>>> only partially test this (I could only check if the clocks were
>>> calculated correctly when using a dummy 500002394Hz input clock instead
>>> of MPLL2).
>>>
>>> Could you please give this series a try and let me know about the
>>> results?
>>> You obviously still need your two "ARM: dts: meson8b" patches which
>>> - add the amlogic,meson8b-dwmac" compatible to meson8b.dtsi
>>> - enable Ethernet on the Odroid-C1
>>>
>>> When testing on Meson8b this also needs a fix for the MPLL clock driver:
>>> "clk: meson: mpll: use 64-bit maths in params_from_rate", see:
>>> https://patchwork.kernel.org/patch/10131677/
>>>
>>>
>>> I have tested this myself on a Khadas VIM (GXL SoC, internal RMII PHY)
>>> and a Khadas VIM2 (GXM SoC, external RGMII PHY). Both are still working
>>> fine (so let's hope that this also fixes your Meson8b issue :)).
>>>
>>>
>>> changes since v1 at [1]:
>>> - changed the subject of the cover-letter to indicate that this is all
>>> about the RGMII clock
>>> - added PATCH #1 which ensures that we don't unnecessarily change the
>>> parent clocks in RMII mode (and also makes the code easier to
>>> understand)
>>> - changed subject of PATCH #2 (formerly PATCH #1) to state that this
>>> is about the RGMII clock
>>> - added Jerome's Reviewed-by to PATCH #2 (formerly PATCH #1)
>>> - replaced PATCH #3 (formerly PATCH #2) with one that sets
>>> CLK_SET_RATE_PARENT on the mux and thus re-configures the MPLL2 clock
>>> on Meson8b correctly
>>>
>>> changes since v2 at [2]:
>>> - added PATCH #2 to make the following patch easier
>>> - Emiliano reported that there's currently another bug in the
>>> dwmac-meson8b driver which prevents it from working with RGMII PHYs on
>>> Meson8b: bit 10 of the PRG_ETH0 register is configures a clock gate
>>> (instead of a divide by 5 or divide by 10 clock divider). This has not
>>> been visible on GXBB and later due to the input clock which always led
>>> to a selection of "divide by 10" (which is done internally in the IP
>>> block, but the bit actually means "enable RGMII clock output").
>>> PATCH #3 was added to address this issue.
>>> - the commit message of PATCH #4 and #5 (formerly PATCH #2 and #3) were
>>> updated and the patch itself rebased because the m25_div clock was
>>> removed with the new PATCH #3 (so some of the statements were not
>>> valid anymore)
>>>
>>
>> Here is the clk_summary relative to ethernet on Odroid-C1+
>> with this new series applied:
>>
>> xtal 1 1 24000000 0 0
>> sys_pll 0 0 1200000000 0 0
>> cpu_clk 0 0 1200000000 0 0
>> vid_pll 0 0 732000000 0 0
>> fixed_pll 2 2 2550000000 0 0
>> mpll2 1 1 249999701 0 0
>> c9410000.ethernet#m250_sel 1 1 249999701 0 0
>> c9410000.ethernet#m250_div 1 1 249999701 0 0
>> c9410000.ethernet#fixed_div10 1 1 24999970 0 0
>> c9410000.ethernet#m25_en 1 1 24999970 0 0
>>
>> The ethernet prg0 register is set to 0x74A1 which should be correct with
>> respect to the information contained in the S805 SoC manual.
>> Actually, the ethernet is not yet fully functional.
>> Trying to ping the board, I can see ARP request from host to board using
>> tcpdump. However, the host can't see any response.
> great - we're getting closer!
>
>> Following the U-Boot value for prg0 register, which is 0x7d21, I also
>> tried to set bit 11. As expected, this did not have any influence.
> it *may* be something outside the PRG_ETH0 register than
> to confirm that: could you temporarily revert the last patch from this
> series ("net: stmmac: dwmac-meson8b: propagate rate changes to the
> parent clock")? this way MPLL2 will stay at ~500MHz and PRG_ETH0
> should be identical to what u-boot sets (apart from bit 11, but that
> is only relevant in RMII mode according to the datasheet)
>
>> Another thing that we should check is the "Ethernet Memory PD" (see S805
>> manual - sec. 5.4) register which bits 3-2 enable/disable ethernet
>> normal operation. However, those bits are already cleared by U-Boot.
> if the peripheral registers itself are configured correctly it's
> typically one of these issues:
> - gate clock not being enabled (can you confirm that you hav the
> "stmmaceth" with CLKID_ETH in the ethmac node?)
> - incorrect pinmux settings (as a hack I would remove all ethernet
> pinctrl properties/nodes from meson8b.dtsi and meson8b-odroidc1.dts.
> before booting the mainline kernel you'll need to use Ethernet from
> within u-boot once)
> - incorrect TX delay (amlogic,tx-delay-ns = <2> should be defined in
> meson8b-odroidc1.dts, but the driver should auto-select that value if
> it's missing)
> - IP block being in some undefined state which can be brought back
> into a working state by adding the reset line (RESET_ETHERNET)
> - Ethernet PHY being in some undefined state can be brought back into
> a working state by adding the reset line (GPIOH_4, see
> meson-gxbb-odroidc2.dts how to use that)
> - I have not seen that the power-domains ("Ethernet Memory PD") were a
> problem yet, but you already checked that
and I forgot the "eee-broken-1000t;" property on the PHY! have a look
at meson-gxbb-odroidc2.dts - I would assume that the ethmac node in
your meson8b-odroidc1.dts looks almost identical (no interrupt
configuration inside the PHY node, different reset-GPIO)
>
> maybe you can share your current .dts patch and a boot-log so others
> can have a look as well?
>
>> Thank you for the support.
> thank you for your patience as well, most people would have given up by now
>
>> Best regards,
>>
>> Emiliano
>>
>>>
>>> [0] http://lists.infradead.org/pipermail/linux-amlogic/2017-December/005596.html
>>> [1] http://lists.infradead.org/pipermail/linux-amlogic/2017-December/005848.html
>>> [2] http://lists.infradead.org/pipermail/linux-amlogic/2017-December/005861.html
>>>
>>>
>>> Martin Blumenstingl (5):
>>> net: stmmac: dwmac-meson8b: only configure the clocks in RGMII mode
>>> net: stmmac: dwmac-meson8b: simplify generating the clock names
>>> net: stmmac: dwmac-meson8b: fix internal RGMII clock configuration
>>> net: stmmac: dwmac-meson8b: fix setting the RGMII clock on Meson8b
>>> net: stmmac: dwmac-meson8b: propagate rate changes to the parent clock
>>>
>>> .../net/ethernet/stmicro/stmmac/dwmac-meson8b.c | 119 +++++++++++----------
>>> 1 file changed, 63 insertions(+), 56 deletions(-)
>>>
>>> --
>>> 2.15.1
>>>
>
>
> Regards
> Martin
^ permalink raw reply
* Re: [RFT net-next v3 0/5] dwmac-meson8b: RGMII clock fixes for Meson8b
From: Martin Blumenstingl @ 2017-12-29 7:48 UTC (permalink / raw)
To: Emiliano Ingrassia
Cc: netdev, linus.luessing, khilman, linux-amlogic, jbrunet,
Neil Armstrong, peppe.cavallaro, alexandre.torgue
In-Reply-To: <20171229013116.GA5446@ingrassia.epigenesys.com>
Hi Emiliano,
On Fri, Dec 29, 2017 at 2:31 AM, Emiliano Ingrassia
<ingrassia@epigenesys.com> wrote:
> Hi Martin, Hi Dave,
>
> On Thu, Dec 28, 2017 at 11:21:23PM +0100, Martin Blumenstingl wrote:
>> Hi Dave,
>>
>> please do not apply this series until it got a Tested-by from Emiliano.
>>
>>
>> Hi Emiliano,
>>
>> you reported [0] that you couldn't get dwmac-meson8b to work on your
>> Odroid-C1. With your findings (register dumps, clk_summary output, etc.)
>> I think I was able to find a fix: it consists of two patches (which you
>> find in this series)
>>
>> Unfortunately I don't have any Meson8b boards with RGMII PHY so I could
>> only partially test this (I could only check if the clocks were
>> calculated correctly when using a dummy 500002394Hz input clock instead
>> of MPLL2).
>>
>> Could you please give this series a try and let me know about the
>> results?
>> You obviously still need your two "ARM: dts: meson8b" patches which
>> - add the amlogic,meson8b-dwmac" compatible to meson8b.dtsi
>> - enable Ethernet on the Odroid-C1
>>
>> When testing on Meson8b this also needs a fix for the MPLL clock driver:
>> "clk: meson: mpll: use 64-bit maths in params_from_rate", see:
>> https://patchwork.kernel.org/patch/10131677/
>>
>>
>> I have tested this myself on a Khadas VIM (GXL SoC, internal RMII PHY)
>> and a Khadas VIM2 (GXM SoC, external RGMII PHY). Both are still working
>> fine (so let's hope that this also fixes your Meson8b issue :)).
>>
>>
>> changes since v1 at [1]:
>> - changed the subject of the cover-letter to indicate that this is all
>> about the RGMII clock
>> - added PATCH #1 which ensures that we don't unnecessarily change the
>> parent clocks in RMII mode (and also makes the code easier to
>> understand)
>> - changed subject of PATCH #2 (formerly PATCH #1) to state that this
>> is about the RGMII clock
>> - added Jerome's Reviewed-by to PATCH #2 (formerly PATCH #1)
>> - replaced PATCH #3 (formerly PATCH #2) with one that sets
>> CLK_SET_RATE_PARENT on the mux and thus re-configures the MPLL2 clock
>> on Meson8b correctly
>>
>> changes since v2 at [2]:
>> - added PATCH #2 to make the following patch easier
>> - Emiliano reported that there's currently another bug in the
>> dwmac-meson8b driver which prevents it from working with RGMII PHYs on
>> Meson8b: bit 10 of the PRG_ETH0 register is configures a clock gate
>> (instead of a divide by 5 or divide by 10 clock divider). This has not
>> been visible on GXBB and later due to the input clock which always led
>> to a selection of "divide by 10" (which is done internally in the IP
>> block, but the bit actually means "enable RGMII clock output").
>> PATCH #3 was added to address this issue.
>> - the commit message of PATCH #4 and #5 (formerly PATCH #2 and #3) were
>> updated and the patch itself rebased because the m25_div clock was
>> removed with the new PATCH #3 (so some of the statements were not
>> valid anymore)
>>
>
> Here is the clk_summary relative to ethernet on Odroid-C1+
> with this new series applied:
>
> xtal 1 1 24000000 0 0
> sys_pll 0 0 1200000000 0 0
> cpu_clk 0 0 1200000000 0 0
> vid_pll 0 0 732000000 0 0
> fixed_pll 2 2 2550000000 0 0
> mpll2 1 1 249999701 0 0
> c9410000.ethernet#m250_sel 1 1 249999701 0 0
> c9410000.ethernet#m250_div 1 1 249999701 0 0
> c9410000.ethernet#fixed_div10 1 1 24999970 0 0
> c9410000.ethernet#m25_en 1 1 24999970 0 0
>
> The ethernet prg0 register is set to 0x74A1 which should be correct with
> respect to the information contained in the S805 SoC manual.
> Actually, the ethernet is not yet fully functional.
> Trying to ping the board, I can see ARP request from host to board using
> tcpdump. However, the host can't see any response.
great - we're getting closer!
> Following the U-Boot value for prg0 register, which is 0x7d21, I also
> tried to set bit 11. As expected, this did not have any influence.
it *may* be something outside the PRG_ETH0 register than
to confirm that: could you temporarily revert the last patch from this
series ("net: stmmac: dwmac-meson8b: propagate rate changes to the
parent clock")? this way MPLL2 will stay at ~500MHz and PRG_ETH0
should be identical to what u-boot sets (apart from bit 11, but that
is only relevant in RMII mode according to the datasheet)
> Another thing that we should check is the "Ethernet Memory PD" (see S805
> manual - sec. 5.4) register which bits 3-2 enable/disable ethernet
> normal operation. However, those bits are already cleared by U-Boot.
if the peripheral registers itself are configured correctly it's
typically one of these issues:
- gate clock not being enabled (can you confirm that you hav the
"stmmaceth" with CLKID_ETH in the ethmac node?)
- incorrect pinmux settings (as a hack I would remove all ethernet
pinctrl properties/nodes from meson8b.dtsi and meson8b-odroidc1.dts.
before booting the mainline kernel you'll need to use Ethernet from
within u-boot once)
- incorrect TX delay (amlogic,tx-delay-ns = <2> should be defined in
meson8b-odroidc1.dts, but the driver should auto-select that value if
it's missing)
- IP block being in some undefined state which can be brought back
into a working state by adding the reset line (RESET_ETHERNET)
- Ethernet PHY being in some undefined state can be brought back into
a working state by adding the reset line (GPIOH_4, see
meson-gxbb-odroidc2.dts how to use that)
- I have not seen that the power-domains ("Ethernet Memory PD") were a
problem yet, but you already checked that
maybe you can share your current .dts patch and a boot-log so others
can have a look as well?
> Thank you for the support.
thank you for your patience as well, most people would have given up by now
> Best regards,
>
> Emiliano
>
>>
>> [0] http://lists.infradead.org/pipermail/linux-amlogic/2017-December/005596.html
>> [1] http://lists.infradead.org/pipermail/linux-amlogic/2017-December/005848.html
>> [2] http://lists.infradead.org/pipermail/linux-amlogic/2017-December/005861.html
>>
>>
>> Martin Blumenstingl (5):
>> net: stmmac: dwmac-meson8b: only configure the clocks in RGMII mode
>> net: stmmac: dwmac-meson8b: simplify generating the clock names
>> net: stmmac: dwmac-meson8b: fix internal RGMII clock configuration
>> net: stmmac: dwmac-meson8b: fix setting the RGMII clock on Meson8b
>> net: stmmac: dwmac-meson8b: propagate rate changes to the parent clock
>>
>> .../net/ethernet/stmicro/stmmac/dwmac-meson8b.c | 119 +++++++++++----------
>> 1 file changed, 63 insertions(+), 56 deletions(-)
>>
>> --
>> 2.15.1
>>
Regards
Martin
^ permalink raw reply
* Re: [PATCH net 3/3] eet: ena: invoke netif_carrier_off() only after netdev registered
From: Jakub Kicinski @ 2017-12-29 7:46 UTC (permalink / raw)
To: netanel
Cc: davem, netdev, dwmw, zorik, matua, saeedb, msw, aliguori, nafea,
evgenys, gtzalik
In-Reply-To: <1514496620-69953-4-git-send-email-netanel@amazon.com>
On Thu, 28 Dec 2017 21:30:20 +0000, netanel@amazon.com wrote:
> From: Netanel Belgazal <netanel@amazon.com>
>
> netif_carrier_off() should be called only after register netdev.
> Move the function's call after the registration.
By "should" you mean in your driver, right? I think calling
netif_carrier_off() on an unregistered netdev is a pretty standard
thing to do for drivers which manage carrier state.
> Signed-off-by: Netanel Belgazal <netanel@amazon.com>
> ---
> drivers/net/ethernet/amazon/ena/ena_netdev.c | 4 ++--
> 1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/net/ethernet/amazon/ena/ena_netdev.c b/drivers/net/ethernet/amazon/ena/ena_netdev.c
> index fbe21a817bd8..ee50c56765a4 100644
> --- a/drivers/net/ethernet/amazon/ena/ena_netdev.c
> +++ b/drivers/net/ethernet/amazon/ena/ena_netdev.c
> @@ -3276,14 +3276,14 @@ static int ena_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
>
> memcpy(adapter->netdev->perm_addr, adapter->mac_addr, netdev->addr_len);
>
> - netif_carrier_off(netdev);
> -
> rc = register_netdev(netdev);
> if (rc) {
> dev_err(&pdev->dev, "Cannot register net device\n");
> goto err_rss;
> }
>
> + netif_carrier_off(netdev);
> +
> INIT_WORK(&adapter->reset_task, ena_fw_reset_device);
This looks suspicious. After you call register_netdev() someone can
open the device and link may come up before you clear it again with
carrier off. Leading to netdev without a carrier until it's reopened.
> adapter->last_keep_alive_jiffies = jiffies;
^ permalink raw reply
* Re: [PATCH][next] wcn36xx: remove redundant assignment to msg_body.min_ch_time
From: Loic Poulain @ 2017-12-29 7:44 UTC (permalink / raw)
To: Bjorn Andersson
Cc: Colin King, Eugene Krasnikov, Kalle Valo, wcn36xx, linux-wireless,
netdev, kernel-janitors, linux-kernel
In-Reply-To: <20171226201312.GA7480@builder>
Hi Colin, Bjorn,
On 26 December 2017 at 21:13, Bjorn Andersson
<bjorn.andersson@linaro.org> wrote:
> On Tue 19 Dec 09:04 PST 2017, Colin King wrote:
>
>> From: Colin Ian King <colin.king@canonical.com>
>>
>> msg_body.min_ch_time is being assigned twice; remove the redundant
>> first assignment.
>>
>> Detected by CoverityScan, CID#1463042 ("Unused Value")
>>
>
> Happy to see Coverity working for us :)
>
>
> This should have had a:
>
> Fixes: 2f3bef4b247e ("wcn36xx: Add hardware scan offload support")
>
>> Signed-off-by: Colin Ian King <colin.king@canonical.com>
>> ---
>> drivers/net/wireless/ath/wcn36xx/smd.c | 1 -
>> 1 file changed, 1 deletion(-)
>>
>> diff --git a/drivers/net/wireless/ath/wcn36xx/smd.c b/drivers/net/wireless/ath/wcn36xx/smd.c
>> index 2914618a0335..bab2eca5fcac 100644
>> --- a/drivers/net/wireless/ath/wcn36xx/smd.c
>> +++ b/drivers/net/wireless/ath/wcn36xx/smd.c
>> @@ -625,7 +625,6 @@ int wcn36xx_smd_start_hw_scan(struct wcn36xx *wcn, struct ieee80211_vif *vif,
>> INIT_HAL_MSG(msg_body, WCN36XX_HAL_START_SCAN_OFFLOAD_REQ);
>>
>> msg_body.scan_type = WCN36XX_HAL_SCAN_TYPE_ACTIVE;
>> - msg_body.min_ch_time = 30;
>> msg_body.min_ch_time = 100;
>
> But I strongly suspect the second line is supposed to be max_ch_time.
>
> @Loic, do you agree?
You're absolutely right.
Colin could you please update your patch accordingly?
Regards,
Loic
^ permalink raw reply
* Re: [RFC PATCH bpf-next v2 4/4] error-injection: Support fault injection framework
From: Masami Hiramatsu @ 2017-12-29 7:34 UTC (permalink / raw)
To: Alexei Starovoitov
Cc: Alexei Starovoitov, Josef Bacik, rostedt, mingo, davem, netdev,
linux-kernel, ast, kernel-team, daniel, linux-btrfs, darrick.wong,
Josef Bacik, Akinobu Mita
In-Reply-To: <099fa7d4-435a-3fa4-841c-17603a45e77e@fb.com>
On Thu, 28 Dec 2017 17:11:31 -0800
Alexei Starovoitov <ast@fb.com> wrote:
> On 12/27/17 11:51 PM, Masami Hiramatsu wrote:
> >
> > Then what happen if the user set invalid retval to those functions?
> > even if we limit the injectable functions, it can cause a problem,
> >
> > for example,
> >
> > obj = func_return_object();
> > if (!obj) {
> > handling_error...;
> > }
> > obj->field = x;
> >
> > In this case, obviously func_return_object() must return NULL if there is
> > an error, not -ENOMEM. But without the correct retval information, how would
> > you check the BPF code doesn't cause a trouble?
> > Currently it seems you are expecting only the functions which return error code.
> >
> > ret = func_return_state();
> > if (ret < 0) {
> > handling_error...;
> > }
> >
> > But how we can distinguish those?
> >
> > If we have the error range for each function, we can ensure what is
> > *correct* error code, NULL or errno, or any other error numbers. :)
>
> messing up return values may cause problems and range check is
> not going to magically help.
> The caller may handle only a certain set of errors or interpret
> some of them like EBUSY as a signal to retry.
> It's plain impossible to make sure that kernel will be functional
> after error injection has been made.
Hmm, if so, why we need this injectable table?
If we can not make sure the safeness of the error injection (of course, yes)
why we need to limit the error injection on such limited functions?
I think we don't need it anymore. Any function can be injectable, and no
need to make sure the safeness.
Thank you,
> Like kmalloc() unconditionally returning NULL will be deadly
> for the kernel, hence this patch 4/4 has very limited practical
> use. The bpf program need to make intelligent decisions when
> to return an error and what kind of error to return.
> Doing blank range check adds a false sense of additional safety.
> More so it wastes kilobytes of memory to do this check, hence nack.
>
--
Masami Hiramatsu <mhiramat@kernel.org>
^ permalink raw reply
* [PATCH RESEND 3/3] net: Remove spinlock from get_net_ns_by_id()
From: Kirill Tkhai @ 2017-12-29 7:30 UTC (permalink / raw)
To: netdev, davem; +Cc: eric.dumazet, ktkhai, ebiederm
In-Reply-To: <151453250786.12258.8455863810071017385.stgit@localhost.localdomain>
idr_find() is safe under rcu_read_lock() and
maybe_get_net() guarantees that net is alive.
Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com>
---
net/core/net_namespace.c | 2 --
1 file changed, 2 deletions(-)
diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c
index 6a4eab438221..a675f35a18ff 100644
--- a/net/core/net_namespace.c
+++ b/net/core/net_namespace.c
@@ -279,11 +279,9 @@ struct net *get_net_ns_by_id(struct net *net, int id)
return NULL;
rcu_read_lock();
- spin_lock_bh(&net->nsid_lock);
peer = idr_find(&net->netns_ids, id);
if (peer)
peer = maybe_get_net(peer);
- spin_unlock_bh(&net->nsid_lock);
rcu_read_unlock();
return peer;
^ permalink raw reply related
* [PATCH RESEND 2/3] net: Add BUG_ON() to get_net()
From: Kirill Tkhai @ 2017-12-29 7:29 UTC (permalink / raw)
To: netdev, davem; +Cc: eric.dumazet, ktkhai, ebiederm
In-Reply-To: <151453250786.12258.8455863810071017385.stgit@localhost.localdomain>
Since people may mistakenly obtain destroying net
from net_namespace_list and from net::netns_ids
without checking for its net::counter, let's protect
against such situations and insert BUG_ON() to stop
move on after this.
Panic is better, than memory corruption and undefined
behavior.
Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com>
---
include/net/net_namespace.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h
index 10f99dafd5ac..ff0e47471d5b 100644
--- a/include/net/net_namespace.h
+++ b/include/net/net_namespace.h
@@ -195,7 +195,7 @@ void __put_net(struct net *net);
static inline struct net *get_net(struct net *net)
{
- atomic_inc(&net->count);
+ BUG_ON(atomic_inc_return(&net->count) <= 1);
return net;
}
^ 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