The following commit has been merged in the master branch: commit af144a983402f7fd324ce556d9f9011a8b3e01fe Merge: 6413139dfc641aaaa30580b59696a5f7ea274194 e858faf556d4e14c750ba1e8852783c6f9520a0e Author: David S. Miller davem@davemloft.net Date: Mon Jul 8 19:48:57 2019 -0700
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
Two cases of overlapping changes, nothing fancy.
Signed-off-by: David S. Miller davem@davemloft.net
diff --combined MAINTAINERS index 22655aa84a46,54691cc484da..cfa9ed89c031 --- a/MAINTAINERS +++ b/MAINTAINERS @@@ -1140,15 -1140,6 +1140,15 @@@ L: linux-media@vger.kernel.or S: Maintained F: drivers/media/i2c/aptina-pll.*
+AQUANTIA ETHERNET DRIVER (atlantic) +M: Igor Russkikh igor.russkikh@aquantia.com +L: netdev@vger.kernel.org +S: Supported +W: http://www.aquantia.com +Q: http://patchwork.ozlabs.org/project/netdev/list/ +F: drivers/net/ethernet/aquantia/atlantic/ +F: Documentation/networking/device_drivers/aquantia/atlantic.txt + ARC FRAMEBUFFER DRIVER M: Jaya Kumar jayalk@intworks.biz S: Maintained @@@ -4933,6 -4924,13 +4933,6 @@@ L: linux-kernel@vger.kernel.or S: Maintained F: drivers/staging/fsl-dpaa2/ethsw
-DPAA2 PTP CLOCK DRIVER -M: Yangbo Lu yangbo.lu@nxp.com -L: netdev@vger.kernel.org -S: Maintained -F: drivers/net/ethernet/freescale/dpaa2/dpaa2-ptp* -F: drivers/net/ethernet/freescale/dpaa2/dprtc* - DPT_I2O SCSI RAID DRIVER M: Adaptec OEM Raid Solutions aacraid@microsemi.com L: linux-scsi@vger.kernel.org @@@ -5604,8 -5602,7 +5604,8 @@@ F: include/linux/dynamic_debug. DYNAMIC INTERRUPT MODERATION M: Tal Gilboa talgi@mellanox.com S: Maintained -F: include/linux/net_dim.h +F: include/linux/dim.h +F: lib/dim/
DZ DECSTATION DZ11 SERIAL DRIVER M: "Maciej W. Rozycki" macro@linux-mips.org @@@ -6375,8 -6372,6 +6375,8 @@@ FREESCALE QORIQ PTP CLOCK DRIVE M: Yangbo Lu yangbo.lu@nxp.com L: netdev@vger.kernel.org S: Maintained +F: drivers/net/ethernet/freescale/dpaa2/dpaa2-ptp* +F: drivers/net/ethernet/freescale/dpaa2/dprtc* F: drivers/net/ethernet/freescale/enetc/enetc_ptp.c F: drivers/ptp/ptp_qoriq.c F: drivers/ptp/ptp_qoriq_debugfs.c @@@ -6697,7 -6692,9 +6697,7 @@@ M: Paul Bolle <pebolle@tiscali.nl L: gigaset307x-common@lists.sourceforge.net W: http://gigaset307x.sourceforge.net/ S: Odd Fixes -F: Documentation/isdn/README.gigaset -F: drivers/isdn/gigaset/ -F: include/uapi/linux/gigaset_dev.h +F: drivers/staging/isdn/gigaset/
GNSS SUBSYSTEM M: Johan Hovold johan@kernel.org @@@ -6720,15 -6717,6 +6720,15 @@@ L: linux-input@vger.kernel.or S: Maintained F: drivers/input/touchscreen/goodix.c
+GOOGLE ETHERNET DRIVERS +M: Catherine Sullivan csully@google.com +R: Sagi Shahar sagis@google.com +R: Jon Olson jonolson@google.com +L: netdev@vger.kernel.org +S: Supported +F: Documentation/networking/device_drivers/google/gve.txt +F: drivers/net/ethernet/google + GPD POCKET FAN DRIVER M: Hans de Goede hdegoede@redhat.com L: platform-driver-x86@vger.kernel.org @@@ -8388,26 -8376,18 +8388,26 @@@ S: Supporte W: http://www.linux-iscsi.org F: drivers/infiniband/ulp/isert
-ISDN SUBSYSTEM +ISDN/mISDN SUBSYSTEM M: Karsten Keil isdn@linux-pingi.de L: isdn4linux@listserv.isdn4linux.de (subscribers-only) L: netdev@vger.kernel.org W: http://www.isdn4linux.de -T: git git://git.kernel.org/pub/scm/linux/kernel/git/kkeil/isdn-2.6.git S: Maintained +F: drivers/isdn/mISDN +F: drivers/isdn/hardware + +ISDN/CAPI SUBSYSTEM +M: Karsten Keil isdn@linux-pingi.de +L: isdn4linux@listserv.isdn4linux.de (subscribers-only) +L: netdev@vger.kernel.org +W: http://www.isdn4linux.de +S: Odd Fixes F: Documentation/isdn/ -F: drivers/isdn/ -F: include/linux/isdn.h +F: drivers/isdn/capi/ +F: drivers/staging/isdn/ +F: net/bluetooth/cmtp/ F: include/linux/isdn/ -F: include/uapi/linux/isdn.h F: include/uapi/linux/isdn/
IT87 HARDWARE MONITORING DRIVER @@@ -10123,7 -10103,6 +10123,7 @@@ Q: http://patchwork.ozlabs.org/project/ S: Supported F: drivers/net/ethernet/mellanox/mlx5/core/ F: include/linux/mlx5/ +F: Documentation/networking/device_drivers/mellanox/
MELLANOX MLX5 IB driver M: Leon Romanovsky leonro@mellanox.com @@@ -10887,7 -10866,7 +10887,7 @@@ F: drivers/net/ethernet/neterion
NETFILTER M: Pablo Neira Ayuso pablo@netfilter.org -M: Jozsef Kadlecsik kadlec@blackhole.kfki.hu +M: Jozsef Kadlecsik kadlec@netfilter.org M: Florian Westphal fw@strlen.de L: netfilter-devel@vger.kernel.org L: coreteam@netfilter.org @@@ -11100,15 -11079,6 +11100,15 @@@ L: netdev@vger.kernel.or S: Supported F: drivers/net/ethernet/qlogic/netxen/
+NEXTHOP +M: David Ahern dsahern@kernel.org +L: netdev@vger.kernel.org +S: Maintained +F: include/net/nexthop.h +F: include/uapi/linux/nexthop.h +F: include/net/netns/nexthop.h +F: net/ipv4/nexthop.c + NFC SUBSYSTEM L: netdev@vger.kernel.org S: Orphan @@@ -11902,14 -11872,6 +11902,14 @@@ F: kernel/padata. F: include/linux/padata.h F: Documentation/padata.txt
+PAGE POOL +M: Jesper Dangaard Brouer hawk@kernel.org +M: Ilias Apalodimas ilias.apalodimas@linaro.org +L: netdev@vger.kernel.org +S: Supported +F: net/core/page_pool.c +F: include/net/page_pool.h + PANASONIC LAPTOP ACPI EXTRAS DRIVER M: Harald Welte laforge@gnumonks.org L: platform-driver-x86@vger.kernel.org @@@ -17312,6 -17274,7 +17312,7 @@@ N: xd XDP SOCKETS (AF_XDP) M: Björn Töpel bjorn.topel@intel.com M: Magnus Karlsson magnus.karlsson@intel.com + R: Jonathan Lemon jonathan.lemon@gmail.com L: netdev@vger.kernel.org L: bpf@vger.kernel.org S: Maintained diff --combined arch/x86/net/bpf_jit_comp32.c index 133433d181ba,1d12d2174085..393d251798c0 --- a/arch/x86/net/bpf_jit_comp32.c +++ b/arch/x86/net/bpf_jit_comp32.c @@@ -253,14 -253,13 +253,14 @@@ static inline void emit_ia32_mov_r(cons /* dst = src */ static inline void emit_ia32_mov_r64(const bool is64, const u8 dst[], const u8 src[], bool dstk, - bool sstk, u8 **pprog) + bool sstk, u8 **pprog, + const struct bpf_prog_aux *aux) { emit_ia32_mov_r(dst_lo, src_lo, dstk, sstk, pprog); if (is64) /* complete 8 byte move */ emit_ia32_mov_r(dst_hi, src_hi, dstk, sstk, pprog); - else + else if (!aux->verifier_zext) /* zero out high 4 bytes */ emit_ia32_mov_i(dst_hi, 0, dstk, pprog); } @@@ -314,8 -313,7 +314,8 @@@ static inline void emit_ia32_mul_r(cons }
static inline void emit_ia32_to_le_r64(const u8 dst[], s32 val, - bool dstk, u8 **pprog) + bool dstk, u8 **pprog, + const struct bpf_prog_aux *aux) { u8 *prog = *pprog; int cnt = 0; @@@ -336,14 -334,12 +336,14 @@@ */ EMIT2(0x0F, 0xB7); EMIT1(add_2reg(0xC0, dreg_lo, dreg_lo)); - /* xor dreg_hi,dreg_hi */ - EMIT2(0x33, add_2reg(0xC0, dreg_hi, dreg_hi)); + if (!aux->verifier_zext) + /* xor dreg_hi,dreg_hi */ + EMIT2(0x33, add_2reg(0xC0, dreg_hi, dreg_hi)); break; case 32: - /* xor dreg_hi,dreg_hi */ - EMIT2(0x33, add_2reg(0xC0, dreg_hi, dreg_hi)); + if (!aux->verifier_zext) + /* xor dreg_hi,dreg_hi */ + EMIT2(0x33, add_2reg(0xC0, dreg_hi, dreg_hi)); break; case 64: /* nop */ @@@ -362,8 -358,7 +362,8 @@@ }
static inline void emit_ia32_to_be_r64(const u8 dst[], s32 val, - bool dstk, u8 **pprog) + bool dstk, u8 **pprog, + const struct bpf_prog_aux *aux) { u8 *prog = *pprog; int cnt = 0; @@@ -385,18 -380,16 +385,18 @@@ EMIT2(0x0F, 0xB7); EMIT1(add_2reg(0xC0, dreg_lo, dreg_lo));
- /* xor dreg_hi,dreg_hi */ - EMIT2(0x33, add_2reg(0xC0, dreg_hi, dreg_hi)); + if (!aux->verifier_zext) + /* xor dreg_hi,dreg_hi */ + EMIT2(0x33, add_2reg(0xC0, dreg_hi, dreg_hi)); break; case 32: /* Emit 'bswap eax' to swap lower 4 bytes */ EMIT1(0x0F); EMIT1(add_1reg(0xC8, dreg_lo));
- /* xor dreg_hi,dreg_hi */ - EMIT2(0x33, add_2reg(0xC0, dreg_hi, dreg_hi)); + if (!aux->verifier_zext) + /* xor dreg_hi,dreg_hi */ + EMIT2(0x33, add_2reg(0xC0, dreg_hi, dreg_hi)); break; case 64: /* Emit 'bswap eax' to swap lower 4 bytes */ @@@ -576,7 -569,7 +576,7 @@@ static inline void emit_ia32_alu_r(cons static inline void emit_ia32_alu_r64(const bool is64, const u8 op, const u8 dst[], const u8 src[], bool dstk, bool sstk, - u8 **pprog) + u8 **pprog, const struct bpf_prog_aux *aux) { u8 *prog = *pprog;
@@@ -584,7 -577,7 +584,7 @@@ if (is64) emit_ia32_alu_r(is64, true, op, dst_hi, src_hi, dstk, sstk, &prog); - else + else if (!aux->verifier_zext) emit_ia32_mov_i(dst_hi, 0, dstk, &prog); *pprog = prog; } @@@ -675,8 -668,7 +675,8 @@@ static inline void emit_ia32_alu_i(cons /* ALU operation (64 bit) */ static inline void emit_ia32_alu_i64(const bool is64, const u8 op, const u8 dst[], const u32 val, - bool dstk, u8 **pprog) + bool dstk, u8 **pprog, + const struct bpf_prog_aux *aux) { u8 *prog = *pprog; u32 hi = 0; @@@ -687,7 -679,7 +687,7 @@@ emit_ia32_alu_i(is64, false, op, dst_lo, val, dstk, &prog); if (is64) emit_ia32_alu_i(is64, true, op, dst_hi, hi, dstk, &prog); - else + else if (!aux->verifier_zext) emit_ia32_mov_i(dst_hi, 0, dstk, &prog);
*pprog = prog; @@@ -732,9 -724,6 +732,6 @@@ static inline void emit_ia32_lsh_r64(co { u8 *prog = *pprog; int cnt = 0; - static int jmp_label1 = -1; - static int jmp_label2 = -1; - static int jmp_label3 = -1; u8 dreg_lo = dstk ? IA32_EAX : dst_lo; u8 dreg_hi = dstk ? IA32_EDX : dst_hi;
@@@ -753,78 -742,22 +750,22 @@@ /* mov ecx,src_lo */ EMIT2(0x8B, add_2reg(0xC0, src_lo, IA32_ECX));
- /* cmp ecx,32 */ - EMIT3(0x83, add_1reg(0xF8, IA32_ECX), 32); - /* Jumps when >= 32 */ - if (is_imm8(jmp_label(jmp_label1, 2))) - EMIT2(IA32_JAE, jmp_label(jmp_label1, 2)); - else - EMIT2_off32(0x0F, IA32_JAE + 0x10, jmp_label(jmp_label1, 6)); - - /* < 32 */ - /* shl dreg_hi,cl */ - EMIT2(0xD3, add_1reg(0xE0, dreg_hi)); - /* mov ebx,dreg_lo */ - EMIT2(0x8B, add_2reg(0xC0, dreg_lo, IA32_EBX)); + /* shld dreg_hi,dreg_lo,cl */ + EMIT3(0x0F, 0xA5, add_2reg(0xC0, dreg_hi, dreg_lo)); /* shl dreg_lo,cl */ EMIT2(0xD3, add_1reg(0xE0, dreg_lo));
- /* IA32_ECX = -IA32_ECX + 32 */ - /* neg ecx */ - EMIT2(0xF7, add_1reg(0xD8, IA32_ECX)); - /* add ecx,32 */ - EMIT3(0x83, add_1reg(0xC0, IA32_ECX), 32); - - /* shr ebx,cl */ - EMIT2(0xD3, add_1reg(0xE8, IA32_EBX)); - /* or dreg_hi,ebx */ - EMIT2(0x09, add_2reg(0xC0, dreg_hi, IA32_EBX)); - - /* goto out; */ - if (is_imm8(jmp_label(jmp_label3, 2))) - EMIT2(0xEB, jmp_label(jmp_label3, 2)); - else - EMIT1_off32(0xE9, jmp_label(jmp_label3, 5)); - - /* >= 32 */ - if (jmp_label1 == -1) - jmp_label1 = cnt; + /* if ecx >= 32, mov dreg_lo into dreg_hi and clear dreg_lo */
- /* cmp ecx,64 */ - EMIT3(0x83, add_1reg(0xF8, IA32_ECX), 64); - /* Jumps when >= 64 */ - if (is_imm8(jmp_label(jmp_label2, 2))) - EMIT2(IA32_JAE, jmp_label(jmp_label2, 2)); - else - EMIT2_off32(0x0F, IA32_JAE + 0x10, jmp_label(jmp_label2, 6)); + /* cmp ecx,32 */ + EMIT3(0x83, add_1reg(0xF8, IA32_ECX), 32); + /* skip the next two instructions (4 bytes) when < 32 */ + EMIT2(IA32_JB, 4);
- /* >= 32 && < 64 */ - /* sub ecx,32 */ - EMIT3(0x83, add_1reg(0xE8, IA32_ECX), 32); - /* shl dreg_lo,cl */ - EMIT2(0xD3, add_1reg(0xE0, dreg_lo)); /* mov dreg_hi,dreg_lo */ EMIT2(0x89, add_2reg(0xC0, dreg_hi, dreg_lo)); - - /* xor dreg_lo,dreg_lo */ - EMIT2(0x33, add_2reg(0xC0, dreg_lo, dreg_lo)); - - /* goto out; */ - if (is_imm8(jmp_label(jmp_label3, 2))) - EMIT2(0xEB, jmp_label(jmp_label3, 2)); - else - EMIT1_off32(0xE9, jmp_label(jmp_label3, 5)); - - /* >= 64 */ - if (jmp_label2 == -1) - jmp_label2 = cnt; /* xor dreg_lo,dreg_lo */ EMIT2(0x33, add_2reg(0xC0, dreg_lo, dreg_lo)); - /* xor dreg_hi,dreg_hi */ - EMIT2(0x33, add_2reg(0xC0, dreg_hi, dreg_hi)); - - if (jmp_label3 == -1) - jmp_label3 = cnt;
if (dstk) { /* mov dword ptr [ebp+off],dreg_lo */ @@@ -844,9 -777,6 +785,6 @@@ static inline void emit_ia32_arsh_r64(c { u8 *prog = *pprog; int cnt = 0; - static int jmp_label1 = -1; - static int jmp_label2 = -1; - static int jmp_label3 = -1; u8 dreg_lo = dstk ? IA32_EAX : dst_lo; u8 dreg_hi = dstk ? IA32_EDX : dst_hi;
@@@ -865,78 -795,22 +803,22 @@@ /* mov ecx,src_lo */ EMIT2(0x8B, add_2reg(0xC0, src_lo, IA32_ECX));
- /* cmp ecx,32 */ - EMIT3(0x83, add_1reg(0xF8, IA32_ECX), 32); - /* Jumps when >= 32 */ - if (is_imm8(jmp_label(jmp_label1, 2))) - EMIT2(IA32_JAE, jmp_label(jmp_label1, 2)); - else - EMIT2_off32(0x0F, IA32_JAE + 0x10, jmp_label(jmp_label1, 6)); - - /* < 32 */ - /* lshr dreg_lo,cl */ - EMIT2(0xD3, add_1reg(0xE8, dreg_lo)); - /* mov ebx,dreg_hi */ - EMIT2(0x8B, add_2reg(0xC0, dreg_hi, IA32_EBX)); - /* ashr dreg_hi,cl */ + /* shrd dreg_lo,dreg_hi,cl */ + EMIT3(0x0F, 0xAD, add_2reg(0xC0, dreg_lo, dreg_hi)); + /* sar dreg_hi,cl */ EMIT2(0xD3, add_1reg(0xF8, dreg_hi));
- /* IA32_ECX = -IA32_ECX + 32 */ - /* neg ecx */ - EMIT2(0xF7, add_1reg(0xD8, IA32_ECX)); - /* add ecx,32 */ - EMIT3(0x83, add_1reg(0xC0, IA32_ECX), 32); - - /* shl ebx,cl */ - EMIT2(0xD3, add_1reg(0xE0, IA32_EBX)); - /* or dreg_lo,ebx */ - EMIT2(0x09, add_2reg(0xC0, dreg_lo, IA32_EBX)); - - /* goto out; */ - if (is_imm8(jmp_label(jmp_label3, 2))) - EMIT2(0xEB, jmp_label(jmp_label3, 2)); - else - EMIT1_off32(0xE9, jmp_label(jmp_label3, 5)); - - /* >= 32 */ - if (jmp_label1 == -1) - jmp_label1 = cnt; + /* if ecx >= 32, mov dreg_hi to dreg_lo and set/clear dreg_hi depending on sign */
- /* cmp ecx,64 */ - EMIT3(0x83, add_1reg(0xF8, IA32_ECX), 64); - /* Jumps when >= 64 */ - if (is_imm8(jmp_label(jmp_label2, 2))) - EMIT2(IA32_JAE, jmp_label(jmp_label2, 2)); - else - EMIT2_off32(0x0F, IA32_JAE + 0x10, jmp_label(jmp_label2, 6)); + /* cmp ecx,32 */ + EMIT3(0x83, add_1reg(0xF8, IA32_ECX), 32); + /* skip the next two instructions (5 bytes) when < 32 */ + EMIT2(IA32_JB, 5);
- /* >= 32 && < 64 */ - /* sub ecx,32 */ - EMIT3(0x83, add_1reg(0xE8, IA32_ECX), 32); - /* ashr dreg_hi,cl */ - EMIT2(0xD3, add_1reg(0xF8, dreg_hi)); /* mov dreg_lo,dreg_hi */ EMIT2(0x89, add_2reg(0xC0, dreg_lo, dreg_hi)); - - /* ashr dreg_hi,imm8 */ - EMIT3(0xC1, add_1reg(0xF8, dreg_hi), 31); - - /* goto out; */ - if (is_imm8(jmp_label(jmp_label3, 2))) - EMIT2(0xEB, jmp_label(jmp_label3, 2)); - else - EMIT1_off32(0xE9, jmp_label(jmp_label3, 5)); - - /* >= 64 */ - if (jmp_label2 == -1) - jmp_label2 = cnt; - /* ashr dreg_hi,imm8 */ + /* sar dreg_hi,31 */ EMIT3(0xC1, add_1reg(0xF8, dreg_hi), 31); - /* mov dreg_lo,dreg_hi */ - EMIT2(0x89, add_2reg(0xC0, dreg_lo, dreg_hi)); - - if (jmp_label3 == -1) - jmp_label3 = cnt;
if (dstk) { /* mov dword ptr [ebp+off],dreg_lo */ @@@ -956,9 -830,6 +838,6 @@@ static inline void emit_ia32_rsh_r64(co { u8 *prog = *pprog; int cnt = 0; - static int jmp_label1 = -1; - static int jmp_label2 = -1; - static int jmp_label3 = -1; u8 dreg_lo = dstk ? IA32_EAX : dst_lo; u8 dreg_hi = dstk ? IA32_EDX : dst_hi;
@@@ -977,77 -848,23 +856,23 @@@ /* mov ecx,src_lo */ EMIT2(0x8B, add_2reg(0xC0, src_lo, IA32_ECX));
- /* cmp ecx,32 */ - EMIT3(0x83, add_1reg(0xF8, IA32_ECX), 32); - /* Jumps when >= 32 */ - if (is_imm8(jmp_label(jmp_label1, 2))) - EMIT2(IA32_JAE, jmp_label(jmp_label1, 2)); - else - EMIT2_off32(0x0F, IA32_JAE + 0x10, jmp_label(jmp_label1, 6)); - - /* < 32 */ - /* lshr dreg_lo,cl */ - EMIT2(0xD3, add_1reg(0xE8, dreg_lo)); - /* mov ebx,dreg_hi */ - EMIT2(0x8B, add_2reg(0xC0, dreg_hi, IA32_EBX)); + /* shrd dreg_lo,dreg_hi,cl */ + EMIT3(0x0F, 0xAD, add_2reg(0xC0, dreg_lo, dreg_hi)); /* shr dreg_hi,cl */ EMIT2(0xD3, add_1reg(0xE8, dreg_hi));
- /* IA32_ECX = -IA32_ECX + 32 */ - /* neg ecx */ - EMIT2(0xF7, add_1reg(0xD8, IA32_ECX)); - /* add ecx,32 */ - EMIT3(0x83, add_1reg(0xC0, IA32_ECX), 32); - - /* shl ebx,cl */ - EMIT2(0xD3, add_1reg(0xE0, IA32_EBX)); - /* or dreg_lo,ebx */ - EMIT2(0x09, add_2reg(0xC0, dreg_lo, IA32_EBX)); + /* if ecx >= 32, mov dreg_hi to dreg_lo and clear dreg_hi */
- /* goto out; */ - if (is_imm8(jmp_label(jmp_label3, 2))) - EMIT2(0xEB, jmp_label(jmp_label3, 2)); - else - EMIT1_off32(0xE9, jmp_label(jmp_label3, 5)); - - /* >= 32 */ - if (jmp_label1 == -1) - jmp_label1 = cnt; - /* cmp ecx,64 */ - EMIT3(0x83, add_1reg(0xF8, IA32_ECX), 64); - /* Jumps when >= 64 */ - if (is_imm8(jmp_label(jmp_label2, 2))) - EMIT2(IA32_JAE, jmp_label(jmp_label2, 2)); - else - EMIT2_off32(0x0F, IA32_JAE + 0x10, jmp_label(jmp_label2, 6)); + /* cmp ecx,32 */ + EMIT3(0x83, add_1reg(0xF8, IA32_ECX), 32); + /* skip the next two instructions (4 bytes) when < 32 */ + EMIT2(IA32_JB, 4);
- /* >= 32 && < 64 */ - /* sub ecx,32 */ - EMIT3(0x83, add_1reg(0xE8, IA32_ECX), 32); - /* shr dreg_hi,cl */ - EMIT2(0xD3, add_1reg(0xE8, dreg_hi)); /* mov dreg_lo,dreg_hi */ EMIT2(0x89, add_2reg(0xC0, dreg_lo, dreg_hi)); /* xor dreg_hi,dreg_hi */ EMIT2(0x33, add_2reg(0xC0, dreg_hi, dreg_hi));
- /* goto out; */ - if (is_imm8(jmp_label(jmp_label3, 2))) - EMIT2(0xEB, jmp_label(jmp_label3, 2)); - else - EMIT1_off32(0xE9, jmp_label(jmp_label3, 5)); - - /* >= 64 */ - if (jmp_label2 == -1) - jmp_label2 = cnt; - /* xor dreg_lo,dreg_lo */ - EMIT2(0x33, add_2reg(0xC0, dreg_lo, dreg_lo)); - /* xor dreg_hi,dreg_hi */ - EMIT2(0x33, add_2reg(0xC0, dreg_hi, dreg_hi)); - - if (jmp_label3 == -1) - jmp_label3 = cnt; - if (dstk) { /* mov dword ptr [ebp+off],dreg_lo */ EMIT3(0x89, add_2reg(0x40, IA32_EBP, dreg_lo), @@@ -1077,27 -894,10 +902,10 @@@ static inline void emit_ia32_lsh_i64(co } /* Do LSH operation */ if (val < 32) { - /* shl dreg_hi,imm8 */ - EMIT3(0xC1, add_1reg(0xE0, dreg_hi), val); - /* mov ebx,dreg_lo */ - EMIT2(0x8B, add_2reg(0xC0, dreg_lo, IA32_EBX)); + /* shld dreg_hi,dreg_lo,imm8 */ + EMIT4(0x0F, 0xA4, add_2reg(0xC0, dreg_hi, dreg_lo), val); /* shl dreg_lo,imm8 */ EMIT3(0xC1, add_1reg(0xE0, dreg_lo), val); - - /* IA32_ECX = 32 - val */ - /* mov ecx,val */ - EMIT2(0xB1, val); - /* movzx ecx,ecx */ - EMIT3(0x0F, 0xB6, add_2reg(0xC0, IA32_ECX, IA32_ECX)); - /* neg ecx */ - EMIT2(0xF7, add_1reg(0xD8, IA32_ECX)); - /* add ecx,32 */ - EMIT3(0x83, add_1reg(0xC0, IA32_ECX), 32); - - /* shr ebx,cl */ - EMIT2(0xD3, add_1reg(0xE8, IA32_EBX)); - /* or dreg_hi,ebx */ - EMIT2(0x09, add_2reg(0xC0, dreg_hi, IA32_EBX)); } else if (val >= 32 && val < 64) { u32 value = val - 32;
@@@ -1143,27 -943,10 +951,10 @@@ static inline void emit_ia32_rsh_i64(co
/* Do RSH operation */ if (val < 32) { - /* shr dreg_lo,imm8 */ - EMIT3(0xC1, add_1reg(0xE8, dreg_lo), val); - /* mov ebx,dreg_hi */ - EMIT2(0x8B, add_2reg(0xC0, dreg_hi, IA32_EBX)); + /* shrd dreg_lo,dreg_hi,imm8 */ + EMIT4(0x0F, 0xAC, add_2reg(0xC0, dreg_lo, dreg_hi), val); /* shr dreg_hi,imm8 */ EMIT3(0xC1, add_1reg(0xE8, dreg_hi), val); - - /* IA32_ECX = 32 - val */ - /* mov ecx,val */ - EMIT2(0xB1, val); - /* movzx ecx,ecx */ - EMIT3(0x0F, 0xB6, add_2reg(0xC0, IA32_ECX, IA32_ECX)); - /* neg ecx */ - EMIT2(0xF7, add_1reg(0xD8, IA32_ECX)); - /* add ecx,32 */ - EMIT3(0x83, add_1reg(0xC0, IA32_ECX), 32); - - /* shl ebx,cl */ - EMIT2(0xD3, add_1reg(0xE0, IA32_EBX)); - /* or dreg_lo,ebx */ - EMIT2(0x09, add_2reg(0xC0, dreg_lo, IA32_EBX)); } else if (val >= 32 && val < 64) { u32 value = val - 32;
@@@ -1208,27 -991,10 +999,10 @@@ static inline void emit_ia32_arsh_i64(c } /* Do RSH operation */ if (val < 32) { - /* shr dreg_lo,imm8 */ - EMIT3(0xC1, add_1reg(0xE8, dreg_lo), val); - /* mov ebx,dreg_hi */ - EMIT2(0x8B, add_2reg(0xC0, dreg_hi, IA32_EBX)); + /* shrd dreg_lo,dreg_hi,imm8 */ + EMIT4(0x0F, 0xAC, add_2reg(0xC0, dreg_lo, dreg_hi), val); /* ashr dreg_hi,imm8 */ EMIT3(0xC1, add_1reg(0xF8, dreg_hi), val); - - /* IA32_ECX = 32 - val */ - /* mov ecx,val */ - EMIT2(0xB1, val); - /* movzx ecx,ecx */ - EMIT3(0x0F, 0xB6, add_2reg(0xC0, IA32_ECX, IA32_ECX)); - /* neg ecx */ - EMIT2(0xF7, add_1reg(0xD8, IA32_ECX)); - /* add ecx,32 */ - EMIT3(0x83, add_1reg(0xC0, IA32_ECX), 32); - - /* shl ebx,cl */ - EMIT2(0xD3, add_1reg(0xE0, IA32_EBX)); - /* or dreg_lo,ebx */ - EMIT2(0x09, add_2reg(0xC0, dreg_lo, IA32_EBX)); } else if (val >= 32 && val < 64) { u32 value = val - 32;
@@@ -1721,13 -1487,8 +1495,13 @@@ static int do_jit(struct bpf_prog *bpf_ case BPF_ALU64 | BPF_MOV | BPF_X: switch (BPF_SRC(code)) { case BPF_X: - emit_ia32_mov_r64(is64, dst, src, dstk, - sstk, &prog); + if (imm32 == 1) { + /* Special mov32 for zext. */ + emit_ia32_mov_i(dst_hi, 0, dstk, &prog); + break; + } + emit_ia32_mov_r64(is64, dst, src, dstk, sstk, + &prog, bpf_prog->aux); break; case BPF_K: /* Sign-extend immediate value to dst reg */ @@@ -1767,13 -1528,11 +1541,13 @@@ switch (BPF_SRC(code)) { case BPF_X: emit_ia32_alu_r64(is64, BPF_OP(code), dst, - src, dstk, sstk, &prog); + src, dstk, sstk, &prog, + bpf_prog->aux); break; case BPF_K: emit_ia32_alu_i64(is64, BPF_OP(code), dst, - imm32, dstk, &prog); + imm32, dstk, &prog, + bpf_prog->aux); break; } break; @@@ -1792,8 -1551,7 +1566,8 @@@ false, &prog); break; } - emit_ia32_mov_i(dst_hi, 0, dstk, &prog); + if (!bpf_prog->aux->verifier_zext) + emit_ia32_mov_i(dst_hi, 0, dstk, &prog); break; case BPF_ALU | BPF_LSH | BPF_X: case BPF_ALU | BPF_RSH | BPF_X: @@@ -1813,8 -1571,7 +1587,8 @@@ &prog); break; } - emit_ia32_mov_i(dst_hi, 0, dstk, &prog); + if (!bpf_prog->aux->verifier_zext) + emit_ia32_mov_i(dst_hi, 0, dstk, &prog); break; /* dst = dst / src(imm) */ /* dst = dst % src(imm) */ @@@ -1836,8 -1593,7 +1610,8 @@@ &prog); break; } - emit_ia32_mov_i(dst_hi, 0, dstk, &prog); + if (!bpf_prog->aux->verifier_zext) + emit_ia32_mov_i(dst_hi, 0, dstk, &prog); break; case BPF_ALU64 | BPF_DIV | BPF_K: case BPF_ALU64 | BPF_DIV | BPF_X: @@@ -1854,8 -1610,7 +1628,8 @@@ EMIT2_off32(0xC7, add_1reg(0xC0, IA32_ECX), imm32); emit_ia32_shift_r(BPF_OP(code), dst_lo, IA32_ECX, dstk, false, &prog); - emit_ia32_mov_i(dst_hi, 0, dstk, &prog); + if (!bpf_prog->aux->verifier_zext) + emit_ia32_mov_i(dst_hi, 0, dstk, &prog); break; /* dst = dst << imm */ case BPF_ALU64 | BPF_LSH | BPF_K: @@@ -1891,8 -1646,7 +1665,8 @@@ case BPF_ALU | BPF_NEG: emit_ia32_alu_i(is64, false, BPF_OP(code), dst_lo, 0, dstk, &prog); - emit_ia32_mov_i(dst_hi, 0, dstk, &prog); + if (!bpf_prog->aux->verifier_zext) + emit_ia32_mov_i(dst_hi, 0, dstk, &prog); break; /* dst = ~dst (64 bit) */ case BPF_ALU64 | BPF_NEG: @@@ -1912,13 -1666,11 +1686,13 @@@ break; /* dst = htole(dst) */ case BPF_ALU | BPF_END | BPF_FROM_LE: - emit_ia32_to_le_r64(dst, imm32, dstk, &prog); + emit_ia32_to_le_r64(dst, imm32, dstk, &prog, + bpf_prog->aux); break; /* dst = htobe(dst) */ case BPF_ALU | BPF_END | BPF_FROM_BE: - emit_ia32_to_be_r64(dst, imm32, dstk, &prog); + emit_ia32_to_be_r64(dst, imm32, dstk, &prog, + bpf_prog->aux); break; /* dst = imm64 */ case BPF_LD | BPF_IMM | BPF_DW: { @@@ -2073,8 -1825,6 +1847,8 @@@ case BPF_B: case BPF_H: case BPF_W: + if (!bpf_prog->aux->verifier_zext) + break; if (dstk) { EMIT3(0xC7, add_1reg(0x40, IA32_EBP), STACK_VAR(dst_hi)); @@@ -2499,11 -2249,6 +2273,11 @@@ notyet return proglen; }
+bool bpf_jit_needs_zext(void) +{ + return true; +} + struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog) { struct bpf_binary_header *header = NULL; diff --combined drivers/net/bonding/bond_main.c index 302499ae05e6,b0aab3a0a1bf..9b7016abca2f --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@@ -613,8 -613,8 +613,8 @@@ static int bond_set_dev_addr(struct net { int err;
- netdev_dbg(bond_dev, "bond_dev=%p slave_dev=%p slave_dev->name=%s slave_dev->addr_len=%d\n", - bond_dev, slave_dev, slave_dev->name, slave_dev->addr_len); + slave_dbg(bond_dev, slave_dev, "bond_dev=%p slave_dev=%p slave_dev->addr_len=%d\n", + bond_dev, slave_dev, slave_dev->addr_len); err = dev_pre_changeaddr_notify(bond_dev, slave_dev->dev_addr, NULL); if (err) return err; @@@ -661,8 -661,8 +661,8 @@@ static void bond_do_fail_over_mac(struc if (new_active) { rv = bond_set_dev_addr(bond->dev, new_active->dev); if (rv) - netdev_err(bond->dev, "Error %d setting MAC of slave %s\n", - -rv, bond->dev->name); + slave_err(bond->dev, new_active->dev, "Error %d setting bond MAC from slave\n", + -rv); } break; case BOND_FOM_FOLLOW: @@@ -692,8 -692,8 +692,8 @@@ rv = dev_set_mac_address(new_active->dev, (struct sockaddr *)&ss, NULL); if (rv) { - netdev_err(bond->dev, "Error %d setting MAC of slave %s\n", - -rv, new_active->dev->name); + slave_err(bond->dev, new_active->dev, "Error %d setting MAC of new active slave\n", + -rv); goto out; }
@@@ -707,8 -707,8 +707,8 @@@ rv = dev_set_mac_address(old_active->dev, (struct sockaddr *)&ss, NULL); if (rv) - netdev_err(bond->dev, "Error %d setting MAC of slave %s\n", - -rv, new_active->dev->name); + slave_err(bond->dev, old_active->dev, "Error %d setting MAC of old active slave\n", + -rv); out: break; default: @@@ -796,8 -796,6 +796,8 @@@ static bool bond_should_notify_peers(st slave ? slave->dev->name : "NULL");
if (!slave || !bond->send_peer_notif || + bond->send_peer_notif % + max(1, bond->params.peer_notif_delay) != 0 || !netif_carrier_ok(bond->dev) || test_bit(__LINK_STATE_LINKWATCH_PENDING, &slave->dev->state)) return false; @@@ -836,8 -834,9 +836,8 @@@ void bond_change_active_slave(struct bo
if (new_active->link == BOND_LINK_BACK) { if (bond_uses_primary(bond)) { - netdev_info(bond->dev, "making interface %s the new active one %d ms earlier\n", - new_active->dev->name, - (bond->params.updelay - new_active->delay) * bond->params.miimon); + slave_info(bond->dev, new_active->dev, "making interface the new active one %d ms earlier\n", + (bond->params.updelay - new_active->delay) * bond->params.miimon); }
new_active->delay = 0; @@@ -851,7 -850,8 +851,7 @@@ bond_alb_handle_link_change(bond, new_active, BOND_LINK_UP); } else { if (bond_uses_primary(bond)) { - netdev_info(bond->dev, "making interface %s the new active one\n", - new_active->dev->name); + slave_info(bond->dev, new_active->dev, "making interface the new active one\n"); } } } @@@ -888,18 -888,15 +888,18 @@@
if (netif_running(bond->dev)) { bond->send_peer_notif = - bond->params.num_peer_notif; + bond->params.num_peer_notif * + max(1, bond->params.peer_notif_delay); should_notify_peers = bond_should_notify_peers(bond); }
call_netdevice_notifiers(NETDEV_BONDING_FAILOVER, bond->dev); - if (should_notify_peers) + if (should_notify_peers) { + bond->send_peer_notif--; call_netdevice_notifiers(NETDEV_NOTIFY_PEERS, bond->dev); + } } }
@@@ -942,7 -939,7 +942,7 @@@ void bond_select_active_slave(struct bo return;
if (netif_carrier_ok(bond->dev)) - netdev_info(bond->dev, "first active interface up!\n"); + netdev_info(bond->dev, "active interface up!\n"); else netdev_info(bond->dev, "now running without any active interface!\n"); } @@@ -1080,16 -1077,12 +1080,16 @@@ static netdev_features_t bond_fix_featu #define BOND_ENC_FEATURES (NETIF_F_HW_CSUM | NETIF_F_SG | \ NETIF_F_RXCSUM | NETIF_F_ALL_TSO)
+#define BOND_MPLS_FEATURES (NETIF_F_HW_CSUM | NETIF_F_SG | \ + NETIF_F_ALL_TSO) + static void bond_compute_features(struct bonding *bond) { unsigned int dst_release_flag = IFF_XMIT_DST_RELEASE | IFF_XMIT_DST_RELEASE_PERM; netdev_features_t vlan_features = BOND_VLAN_FEATURES; netdev_features_t enc_features = BOND_ENC_FEATURES; + netdev_features_t mpls_features = BOND_MPLS_FEATURES; struct net_device *bond_dev = bond->dev; struct list_head *iter; struct slave *slave; @@@ -1100,7 -1093,6 +1100,7 @@@ if (!bond_has_slaves(bond)) goto done; vlan_features &= NETIF_F_ALL_FOR_ALL; + mpls_features &= NETIF_F_ALL_FOR_ALL;
bond_for_each_slave(bond, slave, iter) { vlan_features = netdev_increment_features(vlan_features, @@@ -1109,11 -1101,6 +1109,11 @@@ enc_features = netdev_increment_features(enc_features, slave->dev->hw_enc_features, BOND_ENC_FEATURES); + + mpls_features = netdev_increment_features(mpls_features, + slave->dev->mpls_features, + BOND_MPLS_FEATURES); + dst_release_flag &= slave->dev->priv_flags; if (slave->dev->hard_header_len > max_hard_header_len) max_hard_header_len = slave->dev->hard_header_len; @@@ -1127,7 -1114,6 +1127,7 @@@ done bond_dev->vlan_features = vlan_features; bond_dev->hw_enc_features = enc_features | NETIF_F_GSO_ENCAP_ALL | NETIF_F_GSO_UDP_L4; + bond_dev->mpls_features = mpls_features; bond_dev->gso_max_segs = gso_max_segs; netif_set_gso_max_size(bond_dev, gso_max_size);
@@@ -1383,14 -1369,15 +1383,14 @@@ int bond_enslave(struct net_device *bon if (!bond->params.use_carrier && slave_dev->ethtool_ops->get_link == NULL && slave_ops->ndo_do_ioctl == NULL) { - netdev_warn(bond_dev, "no link monitoring support for %s\n", - slave_dev->name); + slave_warn(bond_dev, slave_dev, "no link monitoring support\n"); }
/* already in-use? */ if (netdev_is_rx_handler_busy(slave_dev)) { NL_SET_ERR_MSG(extack, "Device is in use and cannot be enslaved"); - netdev_err(bond_dev, - "Error: Device is in use and cannot be enslaved\n"); + slave_err(bond_dev, slave_dev, + "Error: Device is in use and cannot be enslaved\n"); return -EBUSY; }
@@@ -1403,16 -1390,21 +1403,16 @@@ /* vlan challenged mutual exclusion */ /* no need to lock since we're protected by rtnl_lock */ if (slave_dev->features & NETIF_F_VLAN_CHALLENGED) { - netdev_dbg(bond_dev, "%s is NETIF_F_VLAN_CHALLENGED\n", - slave_dev->name); + slave_dbg(bond_dev, slave_dev, "is NETIF_F_VLAN_CHALLENGED\n"); if (vlan_uses_dev(bond_dev)) { NL_SET_ERR_MSG(extack, "Can not enslave VLAN challenged device to VLAN enabled bond"); - netdev_err(bond_dev, "Error: cannot enslave VLAN challenged slave %s on VLAN enabled bond %s\n", - slave_dev->name, bond_dev->name); + slave_err(bond_dev, slave_dev, "Error: cannot enslave VLAN challenged slave on VLAN enabled bond\n"); return -EPERM; } else { - netdev_warn(bond_dev, "enslaved VLAN challenged slave %s. Adding VLANs will be blocked as long as %s is part of bond %s\n", - slave_dev->name, slave_dev->name, - bond_dev->name); + slave_warn(bond_dev, slave_dev, "enslaved VLAN challenged slave. Adding VLANs will be blocked as long as it is part of bond.\n"); } } else { - netdev_dbg(bond_dev, "%s is !NETIF_F_VLAN_CHALLENGED\n", - slave_dev->name); + slave_dbg(bond_dev, slave_dev, "is !NETIF_F_VLAN_CHALLENGED\n"); }
/* Old ifenslave binaries are no longer supported. These can @@@ -1422,7 -1414,8 +1422,7 @@@ */ if (slave_dev->flags & IFF_UP) { NL_SET_ERR_MSG(extack, "Device can not be enslaved while up"); - netdev_err(bond_dev, "%s is up - this may be due to an out of date ifenslave\n", - slave_dev->name); + slave_err(bond_dev, slave_dev, "slave is up - this may be due to an out of date ifenslave\n"); return -EPERM; }
@@@ -1435,14 -1428,14 +1435,14 @@@ */ if (!bond_has_slaves(bond)) { if (bond_dev->type != slave_dev->type) { - netdev_dbg(bond_dev, "change device type from %d to %d\n", - bond_dev->type, slave_dev->type); + slave_dbg(bond_dev, slave_dev, "change device type from %d to %d\n", + bond_dev->type, slave_dev->type);
res = call_netdevice_notifiers(NETDEV_PRE_TYPE_CHANGE, bond_dev); res = notifier_to_errno(res); if (res) { - netdev_err(bond_dev, "refused to change device type\n"); + slave_err(bond_dev, slave_dev, "refused to change device type\n"); return -EBUSY; }
@@@ -1462,31 -1455,31 +1462,31 @@@ } } else if (bond_dev->type != slave_dev->type) { NL_SET_ERR_MSG(extack, "Device type is different from other slaves"); - netdev_err(bond_dev, "%s ether type (%d) is different from other slaves (%d), can not enslave it\n", - slave_dev->name, slave_dev->type, bond_dev->type); + slave_err(bond_dev, slave_dev, "ether type (%d) is different from other slaves (%d), can not enslave it\n", + slave_dev->type, bond_dev->type); return -EINVAL; }
if (slave_dev->type == ARPHRD_INFINIBAND && BOND_MODE(bond) != BOND_MODE_ACTIVEBACKUP) { NL_SET_ERR_MSG(extack, "Only active-backup mode is supported for infiniband slaves"); - netdev_warn(bond_dev, "Type (%d) supports only active-backup mode\n", - slave_dev->type); + slave_warn(bond_dev, slave_dev, "Type (%d) supports only active-backup mode\n", + slave_dev->type); res = -EOPNOTSUPP; goto err_undo_flags; }
if (!slave_ops->ndo_set_mac_address || slave_dev->type == ARPHRD_INFINIBAND) { - netdev_warn(bond_dev, "The slave device specified does not support setting the MAC address\n"); + slave_warn(bond_dev, slave_dev, "The slave device specified does not support setting the MAC address\n"); if (BOND_MODE(bond) == BOND_MODE_ACTIVEBACKUP && bond->params.fail_over_mac != BOND_FOM_ACTIVE) { if (!bond_has_slaves(bond)) { bond->params.fail_over_mac = BOND_FOM_ACTIVE; - netdev_warn(bond_dev, "Setting fail_over_mac to active for active-backup mode\n"); + slave_warn(bond_dev, slave_dev, "Setting fail_over_mac to active for active-backup mode\n"); } else { NL_SET_ERR_MSG(extack, "Slave device does not support setting the MAC address, but fail_over_mac is not set to active"); - netdev_err(bond_dev, "The slave device specified does not support setting the MAC address, but fail_over_mac is not set to active\n"); + slave_err(bond_dev, slave_dev, "The slave device specified does not support setting the MAC address, but fail_over_mac is not set to active\n"); res = -EOPNOTSUPP; goto err_undo_flags; } @@@ -1522,7 -1515,7 +1522,7 @@@ new_slave->original_mtu = slave_dev->mtu; res = dev_set_mtu(slave_dev, bond->dev->mtu); if (res) { - netdev_dbg(bond_dev, "Error %d calling dev_set_mtu\n", res); + slave_err(bond_dev, slave_dev, "Error %d calling dev_set_mtu\n", res); goto err_free; }
@@@ -1543,7 -1536,7 +1543,7 @@@ res = dev_set_mac_address(slave_dev, (struct sockaddr *)&ss, extack); if (res) { - netdev_dbg(bond_dev, "Error %d calling set_mac_address\n", res); + slave_err(bond_dev, slave_dev, "Error %d calling set_mac_address\n", res); goto err_restore_mtu; } } @@@ -1554,7 -1547,7 +1554,7 @@@ /* open the slave since the application closed it */ res = dev_open(slave_dev, extack); if (res) { - netdev_dbg(bond_dev, "Opening slave %s failed\n", slave_dev->name); + slave_err(bond_dev, slave_dev, "Opening slave failed\n"); goto err_restore_mac; }
@@@ -1573,7 -1566,8 +1573,7 @@@
res = vlan_vids_add_by_dev(slave_dev, bond_dev); if (res) { - netdev_err(bond_dev, "Couldn't add bond vlan ids to %s\n", - slave_dev->name); + slave_err(bond_dev, slave_dev, "Couldn't add bond vlan ids\n"); goto err_close; }
@@@ -1603,10 -1597,12 +1603,10 @@@ * supported); thus, we don't need to change * the messages for netif_carrier. */ - netdev_warn(bond_dev, "MII and ETHTOOL support not available for interface %s, and arp_interval/arp_ip_target module parameters not specified, thus bonding will not detect link failures! see bonding.txt for details\n", - slave_dev->name); + slave_warn(bond_dev, slave_dev, "MII and ETHTOOL support not available for slave, and arp_interval/arp_ip_target module parameters not specified, thus bonding will not detect link failures! see bonding.txt for details\n"); } else if (link_reporting == -1) { /* unable get link status using mii/ethtool */ - netdev_warn(bond_dev, "can't get link status from interface %s; the network driver associated with this interface does not support MII or ETHTOOL link status reporting, thus miimon has no effect on this interface\n", - slave_dev->name); + slave_warn(bond_dev, slave_dev, "can't get link status from slave; the network driver associated with this interface does not support MII or ETHTOOL link status reporting, thus miimon has no effect on this interface\n"); } }
@@@ -1640,9 -1636,9 +1640,9 @@@
if (new_slave->link != BOND_LINK_DOWN) new_slave->last_link_up = jiffies; - netdev_dbg(bond_dev, "Initial state of slave_dev is BOND_LINK_%s\n", - new_slave->link == BOND_LINK_DOWN ? "DOWN" : - (new_slave->link == BOND_LINK_UP ? "UP" : "BACK")); + slave_dbg(bond_dev, slave_dev, "Initial state of slave is BOND_LINK_%s\n", + new_slave->link == BOND_LINK_DOWN ? "DOWN" : + (new_slave->link == BOND_LINK_UP ? "UP" : "BACK"));
if (bond_uses_primary(bond) && bond->params.primary[0]) { /* if there is a primary slave, remember it */ @@@ -1683,7 -1679,7 +1683,7 @@@ bond_set_slave_inactive_flags(new_slave, BOND_SLAVE_NOTIFY_NOW); break; default: - netdev_dbg(bond_dev, "This slave is always active in trunk mode\n"); + slave_dbg(bond_dev, slave_dev, "This slave is always active in trunk mode\n");
/* always active in trunk mode */ bond_set_active_slave(new_slave); @@@ -1702,7 -1698,7 +1702,7 @@@ #ifdef CONFIG_NET_POLL_CONTROLLER if (bond->dev->npinfo) { if (slave_enable_netpoll(new_slave)) { - netdev_info(bond_dev, "master_dev is using netpoll, but new slave device does not support netpoll\n"); + slave_info(bond_dev, slave_dev, "master_dev is using netpoll, but new slave device does not support netpoll\n"); res = -EBUSY; goto err_detach; } @@@ -1715,19 -1711,19 +1715,19 @@@ res = netdev_rx_handler_register(slave_dev, bond_handle_frame, new_slave); if (res) { - netdev_dbg(bond_dev, "Error %d calling netdev_rx_handler_register\n", res); + slave_dbg(bond_dev, slave_dev, "Error %d calling netdev_rx_handler_register\n", res); goto err_detach; }
res = bond_master_upper_dev_link(bond, new_slave, extack); if (res) { - netdev_dbg(bond_dev, "Error %d calling bond_master_upper_dev_link\n", res); + slave_dbg(bond_dev, slave_dev, "Error %d calling bond_master_upper_dev_link\n", res); goto err_unregister; }
res = bond_sysfs_slave_add(new_slave); if (res) { - netdev_dbg(bond_dev, "Error %d calling bond_sysfs_slave_add\n", res); + slave_dbg(bond_dev, slave_dev, "Error %d calling bond_sysfs_slave_add\n", res); goto err_upper_unlink; }
@@@ -1781,9 -1777,10 +1781,9 @@@ bond_update_slave_arr(bond, NULL);
- netdev_info(bond_dev, "Enslaving %s as %s interface with %s link\n", - slave_dev->name, - bond_is_active_slave(new_slave) ? "an active" : "a backup", - new_slave->link != BOND_LINK_DOWN ? "an up" : "a down"); + slave_info(bond_dev, slave_dev, "Enslaving as %s interface with %s link\n", + bond_is_active_slave(new_slave) ? "an active" : "a backup", + new_slave->link != BOND_LINK_DOWN ? "an up" : "a down");
/* enslave is successful */ bond_queue_slave_event(new_slave); @@@ -1878,7 -1875,8 +1878,7 @@@ static int __bond_release_one(struct ne /* slave is not a slave or master is not master of this slave */ if (!(slave_dev->flags & IFF_SLAVE) || !netdev_has_upper_dev(slave_dev, bond_dev)) { - netdev_dbg(bond_dev, "cannot release %s\n", - slave_dev->name); + slave_dbg(bond_dev, slave_dev, "cannot release slave\n"); return -EINVAL; }
@@@ -1887,7 -1885,8 +1887,7 @@@ slave = bond_get_slave_by_dev(bond, slave_dev); if (!slave) { /* not a slave of this bond */ - netdev_info(bond_dev, "%s not enslaved\n", - slave_dev->name); + slave_info(bond_dev, slave_dev, "interface not enslaved\n"); unblock_netpoll_tx(); return -EINVAL; } @@@ -1911,8 -1910,9 +1911,8 @@@ if (bond_mode_can_use_xmit_hash(bond)) bond_update_slave_arr(bond, slave);
- netdev_info(bond_dev, "Releasing %s interface %s\n", - bond_is_active_slave(slave) ? "active" : "backup", - slave_dev->name); + slave_info(bond_dev, slave_dev, "Releasing %s interface\n", + bond_is_active_slave(slave) ? "active" : "backup");
oldcurrent = rcu_access_pointer(bond->curr_active_slave);
@@@ -1922,8 -1922,9 +1922,8 @@@ BOND_MODE(bond) != BOND_MODE_ACTIVEBACKUP)) { if (ether_addr_equal_64bits(bond_dev->dev_addr, slave->perm_hwaddr) && bond_has_slaves(bond)) - netdev_warn(bond_dev, "the permanent HWaddr of %s - %pM - is still in use by %s - set the HWaddr of %s to a different address to avoid conflicts\n", - slave_dev->name, slave->perm_hwaddr, - bond_dev->name, slave_dev->name); + slave_warn(bond_dev, slave_dev, "the permanent HWaddr of slave - %pM - is still in use by bond - set the HWaddr of slave to a different address to avoid conflicts\n", + slave->perm_hwaddr); }
if (rtnl_dereference(bond->primary_slave) == slave) @@@ -1971,7 -1972,8 +1971,7 @@@ bond_compute_features(bond); if (!(bond_dev->features & NETIF_F_VLAN_CHALLENGED) && (old_features & NETIF_F_VLAN_CHALLENGED)) - netdev_info(bond_dev, "last VLAN challenged slave %s left bond %s - VLAN blocking is removed\n", - slave_dev->name, bond_dev->name); + slave_info(bond_dev, slave_dev, "last VLAN challenged slave left bond - VLAN blocking is removed\n");
vlan_vids_del_by_dev(slave_dev, bond_dev);
@@@ -2031,8 -2033,8 +2031,8 @@@ int bond_release(struct net_device *bon /* First release a slave and then destroy the bond if no more slaves are left. * Must be under rtnl_lock when this function is called. */ -static int bond_release_and_destroy(struct net_device *bond_dev, - struct net_device *slave_dev) +static int bond_release_and_destroy(struct net_device *bond_dev, + struct net_device *slave_dev) { struct bonding *bond = netdev_priv(bond_dev); int ret; @@@ -2040,7 -2042,8 +2040,7 @@@ ret = __bond_release_one(bond_dev, slave_dev, false, true); if (ret == 0 && !bond_has_slaves(bond)) { bond_dev->priv_flags |= IFF_DISABLE_NETPOLL; - netdev_info(bond_dev, "Destroying bond %s\n", - bond_dev->name); + netdev_info(bond_dev, "Destroying bond\n"); bond_remove_proc_entry(bond); unregister_netdevice(bond_dev); } @@@ -2098,12 -2101,13 +2098,12 @@@ static int bond_miimon_inspect(struct b commit++; slave->delay = bond->params.downdelay; if (slave->delay) { - netdev_info(bond->dev, "link status down for %sinterface %s, disabling it in %d ms\n", - (BOND_MODE(bond) == - BOND_MODE_ACTIVEBACKUP) ? - (bond_is_active_slave(slave) ? - "active " : "backup ") : "", - slave->dev->name, - bond->params.downdelay * bond->params.miimon); + slave_info(bond->dev, slave->dev, "link status down for %sinterface, disabling it in %d ms\n", + (BOND_MODE(bond) == + BOND_MODE_ACTIVEBACKUP) ? + (bond_is_active_slave(slave) ? + "active " : "backup ") : "", + bond->params.downdelay * bond->params.miimon); } /*FALLTHRU*/ case BOND_LINK_FAIL: @@@ -2111,9 -2115,10 +2111,9 @@@ /* recovered before downdelay expired */ bond_propose_link_state(slave, BOND_LINK_UP); slave->last_link_up = jiffies; - netdev_info(bond->dev, "link status up again after %d ms for interface %s\n", - (bond->params.downdelay - slave->delay) * - bond->params.miimon, - slave->dev->name); + slave_info(bond->dev, slave->dev, "link status up again after %d ms\n", + (bond->params.downdelay - slave->delay) * + bond->params.miimon); commit++; continue; } @@@ -2136,18 -2141,20 +2136,18 @@@ slave->delay = bond->params.updelay;
if (slave->delay) { - netdev_info(bond->dev, "link status up for interface %s, enabling it in %d ms\n", - slave->dev->name, - ignore_updelay ? 0 : - bond->params.updelay * - bond->params.miimon); + slave_info(bond->dev, slave->dev, "link status up, enabling it in %d ms\n", + ignore_updelay ? 0 : + bond->params.updelay * + bond->params.miimon); } /*FALLTHRU*/ case BOND_LINK_BACK: if (!link_state) { bond_propose_link_state(slave, BOND_LINK_DOWN); - netdev_info(bond->dev, "link status down again after %d ms for interface %s\n", - (bond->params.updelay - slave->delay) * - bond->params.miimon, - slave->dev->name); + slave_info(bond->dev, slave->dev, "link status down again after %d ms\n", + (bond->params.updelay - slave->delay) * + bond->params.miimon); commit++; continue; } @@@ -2203,8 -2210,9 +2203,8 @@@ static void bond_miimon_commit(struct b bond_needs_speed_duplex(bond)) { slave->link = BOND_LINK_DOWN; if (net_ratelimit()) - netdev_warn(bond->dev, - "failed to get link speed/duplex for %s\n", - slave->dev->name); + slave_warn(bond->dev, slave->dev, + "failed to get link speed/duplex\n"); continue; } bond_set_slave_link_state(slave, BOND_LINK_UP, @@@ -2223,9 -2231,10 +2223,9 @@@ bond_set_backup_slave(slave); }
- netdev_info(bond->dev, "link status definitely up for interface %s, %u Mbps %s duplex\n", - slave->dev->name, - slave->speed == SPEED_UNKNOWN ? 0 : slave->speed, - slave->duplex ? "full" : "half"); + slave_info(bond->dev, slave->dev, "link status definitely up, %u Mbps %s duplex\n", + slave->speed == SPEED_UNKNOWN ? 0 : slave->speed, + slave->duplex ? "full" : "half");
bond_miimon_link_change(bond, slave, BOND_LINK_UP);
@@@ -2246,7 -2255,8 +2246,7 @@@ bond_set_slave_inactive_flags(slave, BOND_SLAVE_NOTIFY_NOW);
- netdev_info(bond->dev, "link status definitely down for interface %s, disabling it\n", - slave->dev->name); + slave_info(bond->dev, slave->dev, "link status definitely down, disabling slave\n");
bond_miimon_link_change(bond, slave, BOND_LINK_DOWN);
@@@ -2256,8 -2266,8 +2256,8 @@@ continue;
default: - netdev_err(bond->dev, "invalid new link %d on slave %s\n", - slave->new_link, slave->dev->name); + slave_err(bond->dev, slave->dev, "invalid new link %d on slave\n", + slave->new_link); slave->new_link = BOND_LINK_NOCHANGE;
continue; @@@ -2284,7 -2294,6 +2284,7 @@@ static void bond_mii_monitor(struct wor struct bonding *bond = container_of(work, struct bonding, mii_work.work); bool should_notify_peers = false; + bool commit; unsigned long delay; struct slave *slave; struct list_head *iter; @@@ -2295,19 -2304,12 +2295,19 @@@ goto re_arm;
rcu_read_lock(); - should_notify_peers = bond_should_notify_peers(bond); - - if (bond_miimon_inspect(bond)) { + commit = !!bond_miimon_inspect(bond); + if (bond->send_peer_notif) { rcu_read_unlock(); + if (rtnl_trylock()) { + bond->send_peer_notif--; + rtnl_unlock(); + } + } else { + rcu_read_unlock(); + }
+ if (commit) { /* Race avoidance with bond_close cancel of workqueue */ if (!rtnl_trylock()) { delay = 1; @@@ -2321,7 -2323,8 +2321,7 @@@ bond_miimon_commit(bond);
rtnl_unlock(); /* might sleep, hold no other locks */ - } else - rcu_read_unlock(); + }
re_arm: if (bond->params.miimon) @@@ -2361,16 -2364,15 +2361,16 @@@ static bool bond_has_this_ip(struct bon * switches in VLAN mode (especially if ports are configured as * "native" to a VLAN) might not pass non-tagged frames. */ -static void bond_arp_send(struct net_device *slave_dev, int arp_op, - __be32 dest_ip, __be32 src_ip, - struct bond_vlan_tag *tags) +static void bond_arp_send(struct slave *slave, int arp_op, __be32 dest_ip, + __be32 src_ip, struct bond_vlan_tag *tags) { struct sk_buff *skb; struct bond_vlan_tag *outer_tag = tags; + struct net_device *slave_dev = slave->dev; + struct net_device *bond_dev = slave->bond->dev;
- netdev_dbg(slave_dev, "arp %d on slave %s: dst %pI4 src %pI4\n", - arp_op, slave_dev->name, &dest_ip, &src_ip); + slave_dbg(bond_dev, slave_dev, "arp %d on slave: dst %pI4 src %pI4\n", + arp_op, &dest_ip, &src_ip);
skb = arp_create(arp_op, ETH_P_ARP, dest_ip, slave_dev, src_ip, NULL, slave_dev->dev_addr, NULL); @@@ -2392,8 -2394,8 +2392,8 @@@ continue; }
- netdev_dbg(slave_dev, "inner tag: proto %X vid %X\n", - ntohs(outer_tag->vlan_proto), tags->vlan_id); + slave_dbg(bond_dev, slave_dev, "inner tag: proto %X vid %X\n", + ntohs(outer_tag->vlan_proto), tags->vlan_id); skb = vlan_insert_tag_set_proto(skb, tags->vlan_proto, tags->vlan_id); if (!skb) { @@@ -2405,8 -2407,8 +2405,8 @@@ } /* Set the outer tag */ if (outer_tag->vlan_id) { - netdev_dbg(slave_dev, "outer tag: proto %X vid %X\n", - ntohs(outer_tag->vlan_proto), outer_tag->vlan_id); + slave_dbg(bond_dev, slave_dev, "outer tag: proto %X vid %X\n", + ntohs(outer_tag->vlan_proto), outer_tag->vlan_id); __vlan_hwaccel_put_tag(skb, outer_tag->vlan_proto, outer_tag->vlan_id); } @@@ -2463,8 -2465,7 +2463,8 @@@ static void bond_arp_send_all(struct bo int i;
for (i = 0; i < BOND_MAX_ARP_TARGETS && targets[i]; i++) { - netdev_dbg(bond->dev, "basa: target %pI4\n", &targets[i]); + slave_dbg(bond->dev, slave->dev, "%s: target %pI4\n", + __func__, &targets[i]); tags = NULL;
/* Find out through which dev should the packet go */ @@@ -2478,7 -2479,7 +2478,7 @@@ net_warn_ratelimited("%s: no route to arp_ip_target %pI4 and arp_validate is set\n", bond->dev->name, &targets[i]); - bond_arp_send(slave->dev, ARPOP_REQUEST, targets[i], + bond_arp_send(slave, ARPOP_REQUEST, targets[i], 0, tags); continue; } @@@ -2495,7 -2496,7 +2495,7 @@@ goto found;
/* Not our device - skip */ - netdev_dbg(bond->dev, "no path to arp_ip_target %pI4 via rt.dev %s\n", + slave_dbg(bond->dev, slave->dev, "no path to arp_ip_target %pI4 via rt.dev %s\n", &targets[i], rt->dst.dev ? rt->dst.dev->name : "NULL");
ip_rt_put(rt); @@@ -2504,7 -2505,8 +2504,7 @@@ found: addr = bond_confirm_addr(rt->dst.dev, targets[i], 0); ip_rt_put(rt); - bond_arp_send(slave->dev, ARPOP_REQUEST, targets[i], - addr, tags); + bond_arp_send(slave, ARPOP_REQUEST, targets[i], addr, tags); kfree(tags); } } @@@ -2514,15 -2516,15 +2514,15 @@@ static void bond_validate_arp(struct bo int i;
if (!sip || !bond_has_this_ip(bond, tip)) { - netdev_dbg(bond->dev, "bva: sip %pI4 tip %pI4 not found\n", - &sip, &tip); + slave_dbg(bond->dev, slave->dev, "%s: sip %pI4 tip %pI4 not found\n", + __func__, &sip, &tip); return; }
i = bond_get_targets_ip(bond->params.arp_targets, sip); if (i == -1) { - netdev_dbg(bond->dev, "bva: sip %pI4 not found in targets\n", - &sip); + slave_dbg(bond->dev, slave->dev, "%s: sip %pI4 not found in targets\n", + __func__, &sip); return; } slave->last_rx = jiffies; @@@ -2550,8 -2552,8 +2550,8 @@@ int bond_arp_rcv(const struct sk_buff *
alen = arp_hdr_len(bond->dev);
- netdev_dbg(bond->dev, "bond_arp_rcv: skb->dev %s\n", - skb->dev->name); + slave_dbg(bond->dev, slave->dev, "%s: skb->dev %s\n", + __func__, skb->dev->name);
if (alen > skb_headlen(skb)) { arp = kmalloc(alen, GFP_ATOMIC); @@@ -2575,10 -2577,10 +2575,10 @@@ arp_ptr += 4 + bond->dev->addr_len; memcpy(&tip, arp_ptr, 4);
- netdev_dbg(bond->dev, "bond_arp_rcv: %s/%d av %d sv %d sip %pI4 tip %pI4\n", - slave->dev->name, bond_slave_state(slave), - bond->params.arp_validate, slave_do_arp_validate(bond, slave), - &sip, &tip); + slave_dbg(bond->dev, slave->dev, "%s: %s/%d av %d sv %d sip %pI4 tip %pI4\n", + __func__, slave->dev->name, bond_slave_state(slave), + bond->params.arp_validate, slave_do_arp_validate(bond, slave), + &sip, &tip);
curr_active_slave = rcu_dereference(bond->curr_active_slave); curr_arp_slave = rcu_dereference(bond->current_arp_slave); @@@ -2681,10 -2683,12 +2681,10 @@@ static void bond_loadbalance_arp_mon(st * is closed. */ if (!oldcurrent) { - netdev_info(bond->dev, "link status definitely up for interface %s\n", - slave->dev->name); + slave_info(bond->dev, slave->dev, "link status definitely up\n"); do_failover = 1; } else { - netdev_info(bond->dev, "interface %s is now up\n", - slave->dev->name); + slave_info(bond->dev, slave->dev, "interface is now up\n"); } } } else { @@@ -2703,7 -2707,8 +2703,7 @@@ if (slave->link_failure_count < UINT_MAX) slave->link_failure_count++;
- netdev_info(bond->dev, "interface %s is now down\n", - slave->dev->name); + slave_info(bond->dev, slave->dev, "interface is now down\n");
if (slave == oldcurrent) do_failover = 1; @@@ -2853,7 -2858,8 +2853,7 @@@ static void bond_ab_arp_commit(struct b RCU_INIT_POINTER(bond->current_arp_slave, NULL); }
- netdev_info(bond->dev, "link status definitely up for interface %s\n", - slave->dev->name); + slave_info(bond->dev, slave->dev, "link status definitely up\n");
if (!rtnl_dereference(bond->curr_active_slave) || slave == rtnl_dereference(bond->primary_slave)) @@@ -2872,7 -2878,8 +2872,7 @@@ bond_set_slave_inactive_flags(slave, BOND_SLAVE_NOTIFY_NOW);
- netdev_info(bond->dev, "link status definitely down for interface %s, disabling it\n", - slave->dev->name); + slave_info(bond->dev, slave->dev, "link status definitely down, disabling slave\n");
if (slave == rtnl_dereference(bond->curr_active_slave)) { RCU_INIT_POINTER(bond->current_arp_slave, NULL); @@@ -2882,8 -2889,8 +2882,8 @@@ continue;
default: - netdev_err(bond->dev, "impossible: new_link %d on slave %s\n", - slave->new_link, slave->dev->name); + slave_err(bond->dev, slave->dev, "impossible: new_link %d on slave\n", + slave->new_link); continue; }
@@@ -2954,7 -2961,8 +2954,7 @@@ static bool bond_ab_arp_probe(struct bo bond_set_slave_inactive_flags(slave, BOND_SLAVE_NOTIFY_LATER);
- netdev_info(bond->dev, "backup interface %s is now down\n", - slave->dev->name); + slave_info(bond->dev, slave->dev, "backup interface is now down\n"); } if (slave == curr_arp_slave) found = true; @@@ -3066,8 -3074,6 +3066,8 @@@ static int bond_master_netdev_event(uns { struct bonding *event_bond = netdev_priv(bond_dev);
+ netdev_dbg(bond_dev, "%s called\n", __func__); + switch (event) { case NETDEV_CHANGENAME: return bond_event_changename(event_bond); @@@ -3077,6 -3083,10 +3077,6 @@@ case NETDEV_REGISTER: bond_create_proc_entry(event_bond); break; - case NETDEV_NOTIFY_PEERS: - if (event_bond->send_peer_notif) - event_bond->send_peer_notif--; - break; default: break; } @@@ -3095,17 -3105,12 +3095,17 @@@ static int bond_slave_netdev_event(unsi * before netdev_rx_handler_register is called in which case * slave will be NULL */ - if (!slave) + if (!slave) { + netdev_dbg(slave_dev, "%s called on NULL slave\n", __func__); return NOTIFY_DONE; + } + bond_dev = slave->bond->dev; bond = slave->bond; primary = rtnl_dereference(bond->primary_slave);
+ slave_dbg(bond_dev, slave_dev, "%s called\n", __func__); + switch (event) { case NETDEV_UNREGISTER: if (bond_dev->type != ARPHRD_ETHER) @@@ -3207,8 -3212,7 +3207,8 @@@ static int bond_netdev_event(struct not { struct net_device *event_dev = netdev_notifier_info_to_dev(ptr);
- netdev_dbg(event_dev, "event: %lx\n", event); + netdev_dbg(event_dev, "%s received %s\n", + __func__, netdev_cmd_to_name(event));
if (!(event_dev->priv_flags & IFF_BONDING)) return NOTIFY_DONE; @@@ -3216,13 -3220,16 +3216,13 @@@ if (event_dev->flags & IFF_MASTER) { int ret;
- netdev_dbg(event_dev, "IFF_MASTER\n"); ret = bond_master_netdev_event(event, event_dev); if (ret != NOTIFY_DONE) return ret; }
- if (event_dev->flags & IFF_SLAVE) { - netdev_dbg(event_dev, "IFF_SLAVE\n"); + if (event_dev->flags & IFF_SLAVE) return bond_slave_netdev_event(event, event_dev); - }
return NOTIFY_DONE; } @@@ -3539,11 -3546,12 +3539,11 @@@ static int bond_do_ioctl(struct net_dev
slave_dev = __dev_get_by_name(net, ifr->ifr_slave);
- netdev_dbg(bond_dev, "slave_dev=%p:\n", slave_dev); + slave_dbg(bond_dev, slave_dev, "slave_dev=%p:\n", slave_dev);
if (!slave_dev) return -ENODEV;
- netdev_dbg(bond_dev, "slave_dev->name=%s:\n", slave_dev->name); switch (cmd) { case BOND_ENSLAVE_OLD: case SIOCBONDENSLAVE: @@@ -3668,7 -3676,7 +3668,7 @@@ static int bond_change_mtu(struct net_d netdev_dbg(bond_dev, "bond=%p, new_mtu=%d\n", bond, new_mtu);
bond_for_each_slave(bond, slave, iter) { - netdev_dbg(bond_dev, "s %p c_m %p\n", + slave_dbg(bond_dev, slave->dev, "s %p c_m %p\n", slave, slave->dev->netdev_ops->ndo_change_mtu);
res = dev_set_mtu(slave->dev, new_mtu); @@@ -3682,8 -3690,8 +3682,8 @@@ * means changing their mtu from timer context, which * is probably not a good idea. */ - netdev_dbg(bond_dev, "err %d %s\n", res, - slave->dev->name); + slave_dbg(bond_dev, slave->dev, "err %d setting mtu to %d\n", + res, new_mtu); goto unwind; } } @@@ -3701,9 -3709,10 +3701,9 @@@ unwind break;
tmp_res = dev_set_mtu(rollback_slave->dev, bond_dev->mtu); - if (tmp_res) { - netdev_dbg(bond_dev, "unwind err %d dev %s\n", - tmp_res, rollback_slave->dev->name); - } + if (tmp_res) + slave_dbg(bond_dev, rollback_slave->dev, "unwind err %d\n", + tmp_res); }
return res; @@@ -3727,7 -3736,7 +3727,7 @@@ static int bond_set_mac_address(struct return bond_alb_set_mac_address(bond_dev, addr);
- netdev_dbg(bond_dev, "bond=%p\n", bond); + netdev_dbg(bond_dev, "%s: bond=%p\n", __func__, bond);
/* If fail_over_mac is enabled, do nothing and return success. * Returning an error causes ifenslave to fail. @@@ -3740,8 -3749,7 +3740,8 @@@ return -EADDRNOTAVAIL;
bond_for_each_slave(bond, slave, iter) { - netdev_dbg(bond_dev, "slave %p %s\n", slave, slave->dev->name); + slave_dbg(bond_dev, slave->dev, "%s: slave=%p\n", + __func__, slave); res = dev_set_mac_address(slave->dev, addr, NULL); if (res) { /* TODO: consider downing the slave @@@ -3750,8 -3758,7 +3750,8 @@@ * breakage anyway until ARP finish * updating, so... */ - netdev_dbg(bond_dev, "err %d %s\n", res, slave->dev->name); + slave_dbg(bond_dev, slave->dev, "%s: err %d\n", + __func__, res); goto unwind; } } @@@ -3774,8 -3781,8 +3774,8 @@@ unwind tmp_res = dev_set_mac_address(rollback_slave->dev, (struct sockaddr *)&tmp_ss, NULL); if (tmp_res) { - netdev_dbg(bond_dev, "unwind err %d dev %s\n", - tmp_res, rollback_slave->dev->name); + slave_dbg(bond_dev, rollback_slave->dev, "%s: unwind err %d\n", + __func__, tmp_res); } }
@@@ -3859,8 -3866,8 +3859,8 @@@ static netdev_tx_t bond_xmit_roundrobin struct net_device *bond_dev) { struct bonding *bond = netdev_priv(bond_dev); - struct iphdr *iph = ip_hdr(skb); struct slave *slave; + int slave_cnt; u32 slave_id;
/* Start with the curr_active_slave that joined the bond as the @@@ -3869,23 -3876,32 +3869,32 @@@ * send the join/membership reports. The curr_active_slave found * will send all of this type of traffic. */ - if (iph->protocol == IPPROTO_IGMP && skb->protocol == htons(ETH_P_IP)) { - slave = rcu_dereference(bond->curr_active_slave); - if (slave) - bond_dev_queue_xmit(bond, skb, slave->dev); - else - bond_xmit_slave_id(bond, skb, 0); - } else { - int slave_cnt = READ_ONCE(bond->slave_cnt); + if (skb->protocol == htons(ETH_P_IP)) { + int noff = skb_network_offset(skb); + struct iphdr *iph;
- if (likely(slave_cnt)) { - slave_id = bond_rr_gen_slave_id(bond); - bond_xmit_slave_id(bond, skb, slave_id % slave_cnt); - } else { - bond_tx_drop(bond_dev, skb); + if (unlikely(!pskb_may_pull(skb, noff + sizeof(*iph)))) + goto non_igmp; + + iph = ip_hdr(skb); + if (iph->protocol == IPPROTO_IGMP) { + slave = rcu_dereference(bond->curr_active_slave); + if (slave) + bond_dev_queue_xmit(bond, skb, slave->dev); + else + bond_xmit_slave_id(bond, skb, 0); + return NETDEV_TX_OK; } }
+ non_igmp: + slave_cnt = READ_ONCE(bond->slave_cnt); + if (likely(slave_cnt)) { + slave_id = bond_rr_gen_slave_id(bond); + bond_xmit_slave_id(bond, skb, slave_id % slave_cnt); + } else { + bond_tx_drop(bond_dev, skb); + } return NETDEV_TX_OK; }
@@@ -3996,8 -4012,9 +4005,8 @@@ int bond_update_slave_arr(struct bondin if (skipslave == slave) continue;
- netdev_dbg(bond->dev, - "Adding slave dev %s to tx hash array[%d]\n", - slave->dev->name, new_arr->count); + slave_dbg(bond->dev, slave->dev, "Adding slave to tx hash array[%d]\n", + new_arr->count);
new_arr->arr[new_arr->count++] = slave; } @@@ -4699,7 -4716,6 +4708,7 @@@ static int bond_check_params(struct bon params->arp_all_targets = arp_all_targets_value; params->updelay = updelay; params->downdelay = downdelay; + params->peer_notif_delay = 0; params->use_carrier = use_carrier; params->lacp_fast = lacp_fast; params->primary[0] = 0; diff --combined drivers/net/dsa/mv88e6xxx/chip.c index 40b1fb22d8df,2e8b1ab2c6f7..6b17cd961d06 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@@ -118,9 -118,9 +118,9 @@@ static irqreturn_t mv88e6xxx_g1_irq_thr u16 ctl1; int err;
- mutex_lock(&chip->reg_lock); + mv88e6xxx_reg_lock(chip); err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_STS, ®); - mutex_unlock(&chip->reg_lock); + mv88e6xxx_reg_unlock(chip);
if (err) goto out; @@@ -135,13 -135,13 +135,13 @@@ } }
- mutex_lock(&chip->reg_lock); + mv88e6xxx_reg_lock(chip); err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_CTL1, &ctl1); if (err) goto unlock; err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_STS, ®); unlock: - mutex_unlock(&chip->reg_lock); + mv88e6xxx_reg_unlock(chip); if (err) goto out; ctl1 &= GENMASK(chip->g1_irq.nirqs, 0); @@@ -162,7 -162,7 +162,7 @@@ static void mv88e6xxx_g1_irq_bus_lock(s { struct mv88e6xxx_chip *chip = irq_data_get_irq_chip_data(d);
- mutex_lock(&chip->reg_lock); + mv88e6xxx_reg_lock(chip); }
static void mv88e6xxx_g1_irq_bus_sync_unlock(struct irq_data *d) @@@ -184,7 -184,7 +184,7 @@@ goto out;
out: - mutex_unlock(&chip->reg_lock); + mv88e6xxx_reg_unlock(chip); }
static const struct irq_chip mv88e6xxx_g1_irq_chip = { @@@ -239,9 -239,9 +239,9 @@@ static void mv88e6xxx_g1_irq_free(struc */ free_irq(chip->irq, chip);
- mutex_lock(&chip->reg_lock); + mv88e6xxx_reg_lock(chip); mv88e6xxx_g1_irq_free_common(chip); - mutex_unlock(&chip->reg_lock); + mv88e6xxx_reg_unlock(chip); }
static int mv88e6xxx_g1_irq_setup_common(struct mv88e6xxx_chip *chip) @@@ -310,12 -310,12 +310,12 @@@ static int mv88e6xxx_g1_irq_setup(struc */ irq_set_lockdep_class(chip->irq, &lock_key, &request_key);
- mutex_unlock(&chip->reg_lock); + mv88e6xxx_reg_unlock(chip); err = request_threaded_irq(chip->irq, NULL, mv88e6xxx_g1_irq_thread_fn, IRQF_ONESHOT | IRQF_SHARED, dev_name(chip->dev), chip); - mutex_lock(&chip->reg_lock); + mv88e6xxx_reg_lock(chip); if (err) mv88e6xxx_g1_irq_free_common(chip);
@@@ -359,9 -359,9 +359,9 @@@ static void mv88e6xxx_irq_poll_free(str kthread_cancel_delayed_work_sync(&chip->irq_poll_work); kthread_destroy_worker(chip->kworker);
- mutex_lock(&chip->reg_lock); + mv88e6xxx_reg_lock(chip); mv88e6xxx_g1_irq_free_common(chip); - mutex_unlock(&chip->reg_lock); + mv88e6xxx_reg_unlock(chip); }
int mv88e6xxx_wait(struct mv88e6xxx_chip *chip, int addr, int reg, u16 mask) @@@ -496,11 -496,11 +496,11 @@@ static void mv88e6xxx_adjust_link(struc mv88e6xxx_phy_is_internal(ds, port)) return;
- mutex_lock(&chip->reg_lock); + mv88e6xxx_reg_lock(chip); err = mv88e6xxx_port_setup_mac(chip, port, phydev->link, phydev->speed, phydev->duplex, phydev->pause, phydev->interface); - mutex_unlock(&chip->reg_lock); + mv88e6xxx_reg_unlock(chip);
if (err && err != -EOPNOTSUPP) dev_err(ds->dev, "p%d: failed to configure MAC\n", port); @@@ -616,12 -616,12 +616,12 @@@ static int mv88e6xxx_link_state(struct struct mv88e6xxx_chip *chip = ds->priv; int err;
- mutex_lock(&chip->reg_lock); + mv88e6xxx_reg_lock(chip); if (chip->info->ops->port_link_state) err = chip->info->ops->port_link_state(chip, port, state); else err = -EOPNOTSUPP; - mutex_unlock(&chip->reg_lock); + mv88e6xxx_reg_unlock(chip);
return err; } @@@ -651,10 -651,10 +651,10 @@@ static void mv88e6xxx_mac_config(struc } pause = !!phylink_test(state->advertising, Pause);
- mutex_lock(&chip->reg_lock); + mv88e6xxx_reg_lock(chip); err = mv88e6xxx_port_setup_mac(chip, port, link, speed, duplex, pause, state->interface); - mutex_unlock(&chip->reg_lock); + mv88e6xxx_reg_unlock(chip);
if (err && err != -EOPNOTSUPP) dev_err(ds->dev, "p%d: failed to configure MAC\n", port); @@@ -665,9 -665,9 +665,9 @@@ static void mv88e6xxx_mac_link_force(st struct mv88e6xxx_chip *chip = ds->priv; int err;
- mutex_lock(&chip->reg_lock); + mv88e6xxx_reg_lock(chip); err = chip->info->ops->port_set_link(chip, port, link); - mutex_unlock(&chip->reg_lock); + mv88e6xxx_reg_unlock(chip);
if (err) dev_err(chip->dev, "p%d: failed to force MAC link\n", port); @@@ -825,12 -825,6 +825,12 @@@ static int mv88e6095_stats_get_strings( STATS_TYPE_BANK0 | STATS_TYPE_PORT); }
+static int mv88e6250_stats_get_strings(struct mv88e6xxx_chip *chip, + uint8_t *data) +{ + return mv88e6xxx_stats_get_strings(chip, data, STATS_TYPE_BANK0); +} + static int mv88e6320_stats_get_strings(struct mv88e6xxx_chip *chip, uint8_t *data) { @@@ -865,7 -859,7 +865,7 @@@ static void mv88e6xxx_get_strings(struc if (stringset != ETH_SS_STATS) return;
- mutex_lock(&chip->reg_lock); + mv88e6xxx_reg_lock(chip);
if (chip->info->ops->stats_get_strings) count = chip->info->ops->stats_get_strings(chip, data); @@@ -878,7 -872,7 +878,7 @@@ data += count * ETH_GSTRING_LEN; mv88e6xxx_atu_vtu_get_strings(data);
- mutex_unlock(&chip->reg_lock); + mv88e6xxx_reg_unlock(chip); }
static int mv88e6xxx_stats_get_sset_count(struct mv88e6xxx_chip *chip, @@@ -901,11 -895,6 +901,11 @@@ static int mv88e6095_stats_get_sset_cou STATS_TYPE_PORT); }
+static int mv88e6250_stats_get_sset_count(struct mv88e6xxx_chip *chip) +{ + return mv88e6xxx_stats_get_sset_count(chip, STATS_TYPE_BANK0); +} + static int mv88e6320_stats_get_sset_count(struct mv88e6xxx_chip *chip) { return mv88e6xxx_stats_get_sset_count(chip, STATS_TYPE_BANK0 | @@@ -921,7 -910,7 +921,7 @@@ static int mv88e6xxx_get_sset_count(str if (sset != ETH_SS_STATS) return 0;
- mutex_lock(&chip->reg_lock); + mv88e6xxx_reg_lock(chip); if (chip->info->ops->stats_get_sset_count) count = chip->info->ops->stats_get_sset_count(chip); if (count < 0) @@@ -938,7 -927,7 +938,7 @@@ count += ARRAY_SIZE(mv88e6xxx_atu_vtu_stats_strings);
out: - mutex_unlock(&chip->reg_lock); + mv88e6xxx_reg_unlock(chip);
return count; } @@@ -953,11 -942,11 +953,11 @@@ static int mv88e6xxx_stats_get_stats(st for (i = 0, j = 0; i < ARRAY_SIZE(mv88e6xxx_hw_stats); i++) { stat = &mv88e6xxx_hw_stats[i]; if (stat->type & types) { - mutex_lock(&chip->reg_lock); + mv88e6xxx_reg_lock(chip); data[j] = _mv88e6xxx_get_ethtool_stat(chip, stat, port, bank1_select, histogram); - mutex_unlock(&chip->reg_lock); + mv88e6xxx_reg_unlock(chip);
j++; } @@@ -973,13 -962,6 +973,13 @@@ static int mv88e6095_stats_get_stats(st 0, MV88E6XXX_G1_STATS_OP_HIST_RX_TX); }
+static int mv88e6250_stats_get_stats(struct mv88e6xxx_chip *chip, int port, + uint64_t *data) +{ + return mv88e6xxx_stats_get_stats(chip, port, data, STATS_TYPE_BANK0, + 0, MV88E6XXX_G1_STATS_OP_HIST_RX_TX); +} + static int mv88e6320_stats_get_stats(struct mv88e6xxx_chip *chip, int port, uint64_t *data) { @@@ -1016,14 -998,14 +1016,14 @@@ static void mv88e6xxx_get_stats(struct if (chip->info->ops->stats_get_stats) count = chip->info->ops->stats_get_stats(chip, port, data);
- mutex_lock(&chip->reg_lock); + mv88e6xxx_reg_lock(chip); if (chip->info->ops->serdes_get_stats) { data += count; count = chip->info->ops->serdes_get_stats(chip, port, data); } data += count; mv88e6xxx_atu_vtu_get_stats(chip, port, data); - mutex_unlock(&chip->reg_lock); + mv88e6xxx_reg_unlock(chip); }
static void mv88e6xxx_get_ethtool_stats(struct dsa_switch *ds, int port, @@@ -1032,10 -1014,10 +1032,10 @@@ struct mv88e6xxx_chip *chip = ds->priv; int ret;
- mutex_lock(&chip->reg_lock); + mv88e6xxx_reg_lock(chip);
ret = mv88e6xxx_stats_snapshot(chip, port); - mutex_unlock(&chip->reg_lock); + mv88e6xxx_reg_unlock(chip);
if (ret < 0) return; @@@ -1062,7 -1044,7 +1062,7 @@@ static void mv88e6xxx_get_regs(struct d
memset(p, 0xff, 32 * sizeof(u16));
- mutex_lock(&chip->reg_lock); + mv88e6xxx_reg_lock(chip);
for (i = 0; i < 32; i++) {
@@@ -1071,7 -1053,7 +1071,7 @@@ p[i] = reg; }
- mutex_unlock(&chip->reg_lock); + mv88e6xxx_reg_unlock(chip); }
static int mv88e6xxx_get_mac_eee(struct dsa_switch *ds, int port, @@@ -1137,9 -1119,9 +1137,9 @@@ static void mv88e6xxx_port_stp_state_se struct mv88e6xxx_chip *chip = ds->priv; int err;
- mutex_lock(&chip->reg_lock); + mv88e6xxx_reg_lock(chip); err = mv88e6xxx_port_set_state(chip, port, state); - mutex_unlock(&chip->reg_lock); + mv88e6xxx_reg_unlock(chip);
if (err) dev_err(ds->dev, "p%d: failed to update state\n", port); @@@ -1324,9 -1306,9 +1324,9 @@@ static void mv88e6xxx_port_fast_age(str struct mv88e6xxx_chip *chip = ds->priv; int err;
- mutex_lock(&chip->reg_lock); + mv88e6xxx_reg_lock(chip); err = mv88e6xxx_g1_atu_remove(chip, 0, port, false); - mutex_unlock(&chip->reg_lock); + mv88e6xxx_reg_unlock(chip);
if (err) dev_err(ds->dev, "p%d: failed to flush ATU\n", port); @@@ -1454,7 -1436,7 +1454,7 @@@ static int mv88e6xxx_port_check_hw_vlan if (!vid_begin) return -EOPNOTSUPP;
- mutex_lock(&chip->reg_lock); + mv88e6xxx_reg_lock(chip);
do { err = mv88e6xxx_vtu_getnext(chip, &vlan); @@@ -1494,7 -1476,7 +1494,7 @@@ } while (vlan.vid < vid_end);
unlock: - mutex_unlock(&chip->reg_lock); + mv88e6xxx_reg_unlock(chip);
return err; } @@@ -1510,9 -1492,9 +1510,9 @@@ static int mv88e6xxx_port_vlan_filterin if (!chip->info->max_vid) return -EOPNOTSUPP;
- mutex_lock(&chip->reg_lock); + mv88e6xxx_reg_lock(chip); err = mv88e6xxx_port_set_8021q_mode(chip, port, mode); - mutex_unlock(&chip->reg_lock); + mv88e6xxx_reg_unlock(chip);
return err; } @@@ -1646,7 -1628,7 +1646,7 @@@ static void mv88e6xxx_port_vlan_add(str else member = MV88E6XXX_G1_VTU_DATA_MEMBER_TAG_TAGGED;
- mutex_lock(&chip->reg_lock); + mv88e6xxx_reg_lock(chip);
for (vid = vlan->vid_begin; vid <= vlan->vid_end; ++vid) if (_mv88e6xxx_port_vlan_add(chip, port, vid, member)) @@@ -1657,7 -1639,7 +1657,7 @@@ dev_err(ds->dev, "p%d: failed to set PVID %d\n", port, vlan->vid_end);
- mutex_unlock(&chip->reg_lock); + mv88e6xxx_reg_unlock(chip); }
static int _mv88e6xxx_port_vlan_del(struct mv88e6xxx_chip *chip, @@@ -1703,7 -1685,7 +1703,7 @@@ static int mv88e6xxx_port_vlan_del(stru if (!chip->info->max_vid) return -EOPNOTSUPP;
- mutex_lock(&chip->reg_lock); + mv88e6xxx_reg_lock(chip);
err = mv88e6xxx_port_get_pvid(chip, port, &pvid); if (err) @@@ -1722,7 -1704,7 +1722,7 @@@ }
unlock: - mutex_unlock(&chip->reg_lock); + mv88e6xxx_reg_unlock(chip);
return err; } @@@ -1733,10 -1715,10 +1733,10 @@@ static int mv88e6xxx_port_fdb_add(struc struct mv88e6xxx_chip *chip = ds->priv; int err;
- mutex_lock(&chip->reg_lock); + mv88e6xxx_reg_lock(chip); err = mv88e6xxx_port_db_load_purge(chip, port, addr, vid, MV88E6XXX_G1_ATU_DATA_STATE_UC_STATIC); - mutex_unlock(&chip->reg_lock); + mv88e6xxx_reg_unlock(chip);
return err; } @@@ -1747,10 -1729,10 +1747,10 @@@ static int mv88e6xxx_port_fdb_del(struc struct mv88e6xxx_chip *chip = ds->priv; int err;
- mutex_lock(&chip->reg_lock); + mv88e6xxx_reg_lock(chip); err = mv88e6xxx_port_db_load_purge(chip, port, addr, vid, MV88E6XXX_G1_ATU_DATA_STATE_UNUSED); - mutex_unlock(&chip->reg_lock); + mv88e6xxx_reg_unlock(chip);
return err; } @@@ -1767,7 -1749,9 +1767,7 @@@ static int mv88e6xxx_port_db_dump_fid(s eth_broadcast_addr(addr.mac);
do { - mutex_lock(&chip->reg_lock); err = mv88e6xxx_g1_atu_getnext(chip, fid, &addr); - mutex_unlock(&chip->reg_lock); if (err) return err;
@@@ -1800,7 -1784,10 +1800,7 @@@ static int mv88e6xxx_port_db_dump(struc int err;
/* Dump port's default Filtering Information Database (VLAN ID 0) */ - mutex_lock(&chip->reg_lock); err = mv88e6xxx_port_get_fid(chip, port, &fid); - mutex_unlock(&chip->reg_lock); - if (err) return err;
@@@ -1810,7 -1797,9 +1810,7 @@@
/* Dump VLANs' Filtering Information Databases */ do { - mutex_lock(&chip->reg_lock); err = mv88e6xxx_vtu_getnext(chip, &vlan); - mutex_unlock(&chip->reg_lock); if (err) return err;
@@@ -1830,13 -1819,8 +1830,13 @@@ static int mv88e6xxx_port_fdb_dump(stru dsa_fdb_dump_cb_t *cb, void *data) { struct mv88e6xxx_chip *chip = ds->priv; + int err;
- return mv88e6xxx_port_db_dump(chip, port, cb, data); + mv88e6xxx_reg_lock(chip); + err = mv88e6xxx_port_db_dump(chip, port, cb, data); + mv88e6xxx_reg_unlock(chip); + + return err; }
static int mv88e6xxx_bridge_map(struct mv88e6xxx_chip *chip, @@@ -1883,9 -1867,9 +1883,9 @@@ static int mv88e6xxx_port_bridge_join(s struct mv88e6xxx_chip *chip = ds->priv; int err;
- mutex_lock(&chip->reg_lock); + mv88e6xxx_reg_lock(chip); err = mv88e6xxx_bridge_map(chip, br); - mutex_unlock(&chip->reg_lock); + mv88e6xxx_reg_unlock(chip);
return err; } @@@ -1895,11 -1879,11 +1895,11 @@@ static void mv88e6xxx_port_bridge_leave { struct mv88e6xxx_chip *chip = ds->priv;
- mutex_lock(&chip->reg_lock); + mv88e6xxx_reg_lock(chip); if (mv88e6xxx_bridge_map(chip, br) || mv88e6xxx_port_vlan_map(chip, port)) dev_err(ds->dev, "failed to remap in-chip Port VLAN\n"); - mutex_unlock(&chip->reg_lock); + mv88e6xxx_reg_unlock(chip); }
static int mv88e6xxx_crosschip_bridge_join(struct dsa_switch *ds, int dev, @@@ -1911,9 -1895,9 +1911,9 @@@ if (!mv88e6xxx_has_pvt(chip)) return 0;
- mutex_lock(&chip->reg_lock); + mv88e6xxx_reg_lock(chip); err = mv88e6xxx_pvt_map(chip, dev, port); - mutex_unlock(&chip->reg_lock); + mv88e6xxx_reg_unlock(chip);
return err; } @@@ -1926,10 -1910,10 +1926,10 @@@ static void mv88e6xxx_crosschip_bridge_ if (!mv88e6xxx_has_pvt(chip)) return;
- mutex_lock(&chip->reg_lock); + mv88e6xxx_reg_lock(chip); if (mv88e6xxx_pvt_map(chip, dev, port)) dev_err(ds->dev, "failed to remap cross-chip Port VLAN\n"); - mutex_unlock(&chip->reg_lock); + mv88e6xxx_reg_unlock(chip); }
static int mv88e6xxx_software_reset(struct mv88e6xxx_chip *chip) @@@ -2280,14 -2264,14 +2280,14 @@@ static int mv88e6xxx_port_enable(struc struct mv88e6xxx_chip *chip = ds->priv; int err;
- mutex_lock(&chip->reg_lock); + mv88e6xxx_reg_lock(chip);
err = mv88e6xxx_serdes_power(chip, port, true);
if (!err && chip->info->ops->serdes_irq_setup) err = chip->info->ops->serdes_irq_setup(chip, port);
- mutex_unlock(&chip->reg_lock); + mv88e6xxx_reg_unlock(chip);
return err; } @@@ -2296,7 -2280,7 +2296,7 @@@ static void mv88e6xxx_port_disable(stru { struct mv88e6xxx_chip *chip = ds->priv;
- mutex_lock(&chip->reg_lock); + mv88e6xxx_reg_lock(chip);
if (mv88e6xxx_port_set_state(chip, port, BR_STATE_DISABLED)) dev_err(chip->dev, "failed to disable port\n"); @@@ -2307,7 -2291,7 +2307,7 @@@ if (mv88e6xxx_serdes_power(chip, port, false)) dev_err(chip->dev, "failed to power off SERDES\n");
- mutex_unlock(&chip->reg_lock); + mv88e6xxx_reg_unlock(chip); }
static int mv88e6xxx_set_ageing_time(struct dsa_switch *ds, @@@ -2316,9 -2300,9 +2316,9 @@@ struct mv88e6xxx_chip *chip = ds->priv; int err;
- mutex_lock(&chip->reg_lock); + mv88e6xxx_reg_lock(chip); err = mv88e6xxx_g1_atu_set_age_time(chip, ageing_time); - mutex_unlock(&chip->reg_lock); + mv88e6xxx_reg_unlock(chip);
return err; } @@@ -2448,7 -2432,7 +2448,7 @@@ static int mv88e6xxx_setup(struct dsa_s chip->ds = ds; ds->slave_mii_bus = mv88e6xxx_default_mdio_bus(chip);
- mutex_lock(&chip->reg_lock); + mv88e6xxx_reg_lock(chip);
if (chip->info->ops->setup_errata) { err = chip->info->ops->setup_errata(chip); @@@ -2555,7 -2539,7 +2555,7 @@@ goto unlock;
unlock: - mutex_unlock(&chip->reg_lock); + mv88e6xxx_reg_unlock(chip);
return err; } @@@ -2570,9 -2554,9 +2570,9 @@@ static int mv88e6xxx_mdio_read(struct m if (!chip->info->ops->phy_read) return -EOPNOTSUPP;
- mutex_lock(&chip->reg_lock); + mv88e6xxx_reg_lock(chip); err = chip->info->ops->phy_read(chip, bus, phy, reg, &val); - mutex_unlock(&chip->reg_lock); + mv88e6xxx_reg_unlock(chip);
if (reg == MII_PHYSID2) { /* Some internal PHYs don't have a model number. */ @@@ -2605,9 -2589,9 +2605,9 @@@ static int mv88e6xxx_mdio_write(struct if (!chip->info->ops->phy_write) return -EOPNOTSUPP;
- mutex_lock(&chip->reg_lock); + mv88e6xxx_reg_lock(chip); err = chip->info->ops->phy_write(chip, bus, phy, reg, val); - mutex_unlock(&chip->reg_lock); + mv88e6xxx_reg_unlock(chip);
return err; } @@@ -2622,9 -2606,9 +2622,9 @@@ static int mv88e6xxx_mdio_register(stru int err;
if (external) { - mutex_lock(&chip->reg_lock); + mv88e6xxx_reg_lock(chip); err = mv88e6xxx_g2_scratch_gpio_set_smi(chip, true); - mutex_unlock(&chip->reg_lock); + mv88e6xxx_reg_unlock(chip);
if (err) return err; @@@ -2745,9 -2729,9 +2745,9 @@@ static int mv88e6xxx_get_eeprom(struct if (!chip->info->ops->get_eeprom) return -EOPNOTSUPP;
- mutex_lock(&chip->reg_lock); + mv88e6xxx_reg_lock(chip); err = chip->info->ops->get_eeprom(chip, eeprom, data); - mutex_unlock(&chip->reg_lock); + mv88e6xxx_reg_unlock(chip);
if (err) return err; @@@ -2769,9 -2753,9 +2769,9 @@@ static int mv88e6xxx_set_eeprom(struct if (eeprom->magic != 0xc3ec4951) return -EINVAL;
- mutex_lock(&chip->reg_lock); + mv88e6xxx_reg_lock(chip); err = chip->info->ops->set_eeprom(chip, eeprom, data); - mutex_unlock(&chip->reg_lock); + mv88e6xxx_reg_unlock(chip);
return err; } @@@ -3460,44 -3444,6 +3460,44 @@@ static const struct mv88e6xxx_ops mv88e .phylink_validate = mv88e6352_phylink_validate, };
+static const struct mv88e6xxx_ops mv88e6250_ops = { + /* MV88E6XXX_FAMILY_6250 */ + .ieee_pri_map = mv88e6250_g1_ieee_pri_map, + .ip_pri_map = mv88e6085_g1_ip_pri_map, + .irl_init_all = mv88e6352_g2_irl_init_all, + .get_eeprom = mv88e6xxx_g2_get_eeprom16, + .set_eeprom = mv88e6xxx_g2_set_eeprom16, + .set_switch_mac = mv88e6xxx_g2_set_switch_mac, + .phy_read = mv88e6xxx_g2_smi_phy_read, + .phy_write = mv88e6xxx_g2_smi_phy_write, + .port_set_link = mv88e6xxx_port_set_link, + .port_set_duplex = mv88e6xxx_port_set_duplex, + .port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay, + .port_set_speed = mv88e6250_port_set_speed, + .port_tag_remap = mv88e6095_port_tag_remap, + .port_set_frame_mode = mv88e6351_port_set_frame_mode, + .port_set_egress_floods = mv88e6352_port_set_egress_floods, + .port_set_ether_type = mv88e6351_port_set_ether_type, + .port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting, + .port_pause_limit = mv88e6097_port_pause_limit, + .port_disable_pri_override = mv88e6xxx_port_disable_pri_override, + .port_link_state = mv88e6250_port_link_state, + .stats_snapshot = mv88e6320_g1_stats_snapshot, + .stats_set_histogram = mv88e6095_g1_stats_set_histogram, + .stats_get_sset_count = mv88e6250_stats_get_sset_count, + .stats_get_strings = mv88e6250_stats_get_strings, + .stats_get_stats = mv88e6250_stats_get_stats, + .set_cpu_port = mv88e6095_g1_set_cpu_port, + .set_egress_port = mv88e6095_g1_set_egress_port, + .watchdog_ops = &mv88e6250_watchdog_ops, + .mgmt_rsvd2cpu = mv88e6352_g2_mgmt_rsvd2cpu, + .pot_clear = mv88e6xxx_g2_pot_clear, + .reset = mv88e6250_g1_reset, + .vtu_getnext = mv88e6250_g1_vtu_getnext, + .vtu_loadpurge = mv88e6250_g1_vtu_loadpurge, + .phylink_validate = mv88e6065_phylink_validate, +}; + static const struct mv88e6xxx_ops mv88e6290_ops = { /* MV88E6XXX_FAMILY_6390 */ .setup_errata = mv88e6390_setup_errata, @@@ -4283,27 -4229,6 +4283,27 @@@ static const struct mv88e6xxx_info mv88 .ops = &mv88e6240_ops, },
+ [MV88E6250] = { + .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6250, + .family = MV88E6XXX_FAMILY_6250, + .name = "Marvell 88E6250", + .num_databases = 64, + .num_ports = 7, + .num_internal_phys = 5, + .max_vid = 4095, + .port_base_addr = 0x08, + .phy_base_addr = 0x00, + .global1_addr = 0x0f, + .global2_addr = 0x07, + .age_time_coeff = 15000, + .g1_irqs = 9, + .g2_irqs = 10, + .atu_move_port_mask = 0xf, + .dual_chip = true, + .tag_protocol = DSA_TAG_PROTO_DSA, + .ops = &mv88e6250_ops, + }, + [MV88E6290] = { .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6290, .family = MV88E6XXX_FAMILY_6390, @@@ -4532,9 -4457,9 +4532,9 @@@ static int mv88e6xxx_detect(struct mv88 u16 id; int err;
- mutex_lock(&chip->reg_lock); + mv88e6xxx_reg_lock(chip); err = mv88e6xxx_port_read(chip, 0, MV88E6XXX_PORT_SWITCH_ID, &id); - mutex_unlock(&chip->reg_lock); + mv88e6xxx_reg_unlock(chip); if (err) return err;
@@@ -4597,12 -4522,12 +4597,12 @@@ static void mv88e6xxx_port_mdb_add(stru { struct mv88e6xxx_chip *chip = ds->priv;
- mutex_lock(&chip->reg_lock); + mv88e6xxx_reg_lock(chip); if (mv88e6xxx_port_db_load_purge(chip, port, mdb->addr, mdb->vid, MV88E6XXX_G1_ATU_DATA_STATE_MC_STATIC)) dev_err(ds->dev, "p%d: failed to load multicast MAC address\n", port); - mutex_unlock(&chip->reg_lock); + mv88e6xxx_reg_unlock(chip); }
static int mv88e6xxx_port_mdb_del(struct dsa_switch *ds, int port, @@@ -4611,10 -4536,10 +4611,10 @@@ struct mv88e6xxx_chip *chip = ds->priv; int err;
- mutex_lock(&chip->reg_lock); + mv88e6xxx_reg_lock(chip); err = mv88e6xxx_port_db_load_purge(chip, port, mdb->addr, mdb->vid, MV88E6XXX_G1_ATU_DATA_STATE_UNUSED); - mutex_unlock(&chip->reg_lock); + mv88e6xxx_reg_unlock(chip);
return err; } @@@ -4625,12 -4550,12 +4625,12 @@@ static int mv88e6xxx_port_egress_floods struct mv88e6xxx_chip *chip = ds->priv; int err = -EOPNOTSUPP;
- mutex_lock(&chip->reg_lock); + mv88e6xxx_reg_lock(chip); if (chip->info->ops->port_set_egress_floods) err = chip->info->ops->port_set_egress_floods(chip, port, unicast, multicast); - mutex_unlock(&chip->reg_lock); + mv88e6xxx_reg_unlock(chip);
return err; } @@@ -4786,6 -4711,8 +4786,8 @@@ static int mv88e6xxx_probe(struct mdio_ err = PTR_ERR(chip->reset); goto out; } + if (chip->reset) + usleep_range(1000, 2000);
err = mv88e6xxx_detect(chip); if (err) @@@ -4801,9 -4728,9 +4803,9 @@@ chip->eeprom_len = pdata->eeprom_len; }
- mutex_lock(&chip->reg_lock); + mv88e6xxx_reg_lock(chip); err = mv88e6xxx_switch_reset(chip); - mutex_unlock(&chip->reg_lock); + mv88e6xxx_reg_unlock(chip); if (err) goto out;
@@@ -4822,12 -4749,12 +4824,12 @@@ * the PHYs will link their interrupts to these interrupt * controllers */ - mutex_lock(&chip->reg_lock); + mv88e6xxx_reg_lock(chip); if (chip->irq > 0) err = mv88e6xxx_g1_irq_setup(chip); else err = mv88e6xxx_irq_poll_setup(chip); - mutex_unlock(&chip->reg_lock); + mv88e6xxx_reg_unlock(chip);
if (err) goto out; @@@ -4912,10 -4839,6 +4914,10 @@@ static const struct of_device_id mv88e6 .compatible = "marvell,mv88e6190", .data = &mv88e6xxx_table[MV88E6190], }, + { + .compatible = "marvell,mv88e6250", + .data = &mv88e6xxx_table[MV88E6250], + }, { /* sentinel */ }, };
diff --combined drivers/net/ethernet/allwinner/sun4i-emac.c index 6253e5ed6e16,40a359dd90b4..3434730a7699 --- a/drivers/net/ethernet/allwinner/sun4i-emac.c +++ b/drivers/net/ethernet/allwinner/sun4i-emac.c @@@ -224,8 -224,8 +224,8 @@@ static int emac_ioctl(struct net_devic static void emac_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) { - strlcpy(info->driver, DRV_NAME, sizeof(DRV_NAME)); - strlcpy(info->version, DRV_VERSION, sizeof(DRV_VERSION)); + strlcpy(info->driver, DRV_NAME, sizeof(info->driver)); + strlcpy(info->version, DRV_VERSION, sizeof(info->version)); strlcpy(info->bus_info, dev_name(&dev->dev), sizeof(info->bus_info)); }
@@@ -818,6 -818,7 +818,6 @@@ static int emac_probe(struct platform_d SET_NETDEV_DEV(ndev, &pdev->dev);
db = netdev_priv(ndev); - memset(db, 0, sizeof(*db));
db->dev = &pdev->dev; db->ndev = ndev; diff --combined drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c index c4986b519191,c12c1bab0fe4..656ed80647f0 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c @@@ -684,7 -684,7 +684,7 @@@ static void *bnx2x_frag_alloc(const str if (unlikely(gfpflags_allow_blocking(gfp_mask))) return (void *)__get_free_page(gfp_mask);
- return netdev_alloc_frag(fp->rx_frag_size); + return napi_alloc_frag(fp->rx_frag_size); }
return kmalloc(fp->rx_buf_size + NET_SKB_PAD, gfp_mask); @@@ -3857,9 -3857,12 +3857,12 @@@ netdev_tx_t bnx2x_start_xmit(struct sk_
if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP)) { if (!(bp->flags & TX_TIMESTAMPING_EN)) { + bp->eth_stats.ptp_skip_tx_ts++; BNX2X_ERR("Tx timestamping was not enabled, this packet will not be timestamped\n"); } else if (bp->ptp_tx_skb) { - BNX2X_ERR("The device supports only a single outstanding packet to timestamp, this packet will not be timestamped\n"); + bp->eth_stats.ptp_skip_tx_ts++; + netdev_err_once(bp->dev, + "Device supports only a single outstanding packet to timestamp, this packet won't be timestamped\n"); } else { skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS; /* schedule check for Tx timestamp */ diff --combined drivers/net/ethernet/broadcom/bnxt/bnxt.c index d25bb385b3b9,9090c79387c1..e9d3bd80f2dd --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c @@@ -54,7 -54,6 +54,7 @@@ #include <net/pkt_cls.h> #include <linux/hwmon.h> #include <linux/hwmon-sysfs.h> +#include <net/page_pool.h>
#include "bnxt_hsi.h" #include "bnxt.h" @@@ -669,20 -668,19 +669,20 @@@ next_tx_int }
static struct page *__bnxt_alloc_rx_page(struct bnxt *bp, dma_addr_t *mapping, + struct bnxt_rx_ring_info *rxr, gfp_t gfp) { struct device *dev = &bp->pdev->dev; struct page *page;
- page = alloc_page(gfp); + page = page_pool_dev_alloc_pages(rxr->page_pool); if (!page) return NULL;
*mapping = dma_map_page_attrs(dev, page, 0, PAGE_SIZE, bp->rx_dir, DMA_ATTR_WEAK_ORDERING); if (dma_mapping_error(dev, *mapping)) { - __free_page(page); + page_pool_recycle_direct(rxr->page_pool, page); return NULL; } *mapping += bp->rx_dma_offset; @@@ -718,8 -716,7 +718,8 @@@ int bnxt_alloc_rx_data(struct bnxt *bp dma_addr_t mapping;
if (BNXT_RX_PAGE_MODE(bp)) { - struct page *page = __bnxt_alloc_rx_page(bp, &mapping, gfp); + struct page *page = + __bnxt_alloc_rx_page(bp, &mapping, rxr, gfp);
if (!page) return -ENOMEM; @@@ -1992,9 -1989,6 +1992,9 @@@ static int __bnxt_poll_work(struct bnx } }
+ if (event & BNXT_REDIRECT_EVENT) + xdp_do_flush_map(); + if (event & BNXT_TX_EVENT) { struct bnxt_tx_ring_info *txr = bnapi->tx_ring; u16 prod = txr->tx_prod; @@@ -2136,12 -2130,12 +2136,12 @@@ static int bnxt_poll(struct napi_struc } } if (bp->flags & BNXT_FLAG_DIM) { - struct net_dim_sample dim_sample; + struct dim_sample dim_sample;
- net_dim_sample(cpr->event_ctr, - cpr->rx_packets, - cpr->rx_bytes, - &dim_sample); + dim_update_sample(cpr->event_ctr, + cpr->rx_packets, + cpr->rx_bytes, + &dim_sample); net_dim(&cpr->dim, dim_sample); } return work_done; @@@ -2260,23 -2254,9 +2260,23 @@@ static void bnxt_free_tx_skbs(struct bn
for (j = 0; j < max_idx;) { struct bnxt_sw_tx_bd *tx_buf = &txr->tx_buf_ring[j]; - struct sk_buff *skb = tx_buf->skb; + struct sk_buff *skb; int k, last;
+ if (i < bp->tx_nr_rings_xdp && + tx_buf->action == XDP_REDIRECT) { + dma_unmap_single(&pdev->dev, + dma_unmap_addr(tx_buf, mapping), + dma_unmap_len(tx_buf, len), + PCI_DMA_TODEVICE); + xdp_return_frame(tx_buf->xdpf); + tx_buf->action = 0; + tx_buf->xdpf = NULL; + j++; + continue; + } + + skb = tx_buf->skb; if (!skb) { j++; continue; @@@ -2363,7 -2343,7 +2363,7 @@@ static void bnxt_free_rx_skbs(struct bn dma_unmap_page_attrs(&pdev->dev, mapping, PAGE_SIZE, bp->rx_dir, DMA_ATTR_WEAK_ORDERING); - __free_page(data); + page_pool_recycle_direct(rxr->page_pool, data); } else { dma_unmap_single_attrs(&pdev->dev, mapping, bp->rx_buf_use_size, @@@ -2500,8 -2480,6 +2500,8 @@@ static void bnxt_free_rx_rings(struct b if (xdp_rxq_info_is_reg(&rxr->xdp_rxq)) xdp_rxq_info_unreg(&rxr->xdp_rxq);
+ rxr->page_pool = NULL; + kfree(rxr->rx_tpa); rxr->rx_tpa = NULL;
@@@ -2516,26 -2494,6 +2516,26 @@@ } }
+static int bnxt_alloc_rx_page_pool(struct bnxt *bp, + struct bnxt_rx_ring_info *rxr) +{ + struct page_pool_params pp = { 0 }; + + pp.pool_size = bp->rx_ring_size; + pp.nid = dev_to_node(&bp->pdev->dev); + pp.dev = &bp->pdev->dev; + pp.dma_dir = DMA_BIDIRECTIONAL; + + rxr->page_pool = page_pool_create(&pp); + if (IS_ERR(rxr->page_pool)) { + int err = PTR_ERR(rxr->page_pool); + + rxr->page_pool = NULL; + return err; + } + return 0; +} + static int bnxt_alloc_rx_rings(struct bnxt *bp) { int i, rc, agg_rings = 0, tpa_rings = 0; @@@ -2555,26 -2513,9 +2555,26 @@@
ring = &rxr->rx_ring_struct;
+ rc = bnxt_alloc_rx_page_pool(bp, rxr); + if (rc) + return rc; + rc = xdp_rxq_info_reg(&rxr->xdp_rxq, bp->dev, i); - if (rc < 0) + if (rc < 0) { + page_pool_free(rxr->page_pool); + rxr->page_pool = NULL; return rc; + } + + rc = xdp_rxq_info_reg_mem_model(&rxr->xdp_rxq, + MEM_TYPE_PAGE_POOL, + rxr->page_pool); + if (rc) { + xdp_rxq_info_unreg(&rxr->xdp_rxq); + page_pool_free(rxr->page_pool); + rxr->page_pool = NULL; + return rc; + }
rc = bnxt_alloc_ring(bp, &ring->ring_mem); if (rc) @@@ -5567,7 -5508,16 +5567,16 @@@ static int bnxt_cp_rings_in_use(struct
static int bnxt_get_func_stat_ctxs(struct bnxt *bp) { - return bp->cp_nr_rings + bnxt_get_ulp_stat_ctxs(bp); + int ulp_stat = bnxt_get_ulp_stat_ctxs(bp); + int cp = bp->cp_nr_rings; + + if (!ulp_stat) + return cp; + + if (bnxt_nq_rings_in_use(bp) > cp + bnxt_get_ulp_msix_num(bp)) + return bnxt_get_ulp_msix_base(bp) + ulp_stat; + + return cp + ulp_stat; }
static bool bnxt_need_reserve_rings(struct bnxt *bp) @@@ -7536,11 -7486,7 +7545,7 @@@ unsigned int bnxt_get_avail_cp_rings_fo
unsigned int bnxt_get_avail_stat_ctxs_for_en(struct bnxt *bp) { - unsigned int stat; - - stat = bnxt_get_max_func_stat_ctxs(bp) - bnxt_get_ulp_stat_ctxs(bp); - stat -= bp->cp_nr_rings; - return stat; + return bnxt_get_max_func_stat_ctxs(bp) - bnxt_get_func_stat_ctxs(bp); }
int bnxt_get_avail_msix(struct bnxt *bp, int num) @@@ -7872,7 -7818,7 +7877,7 @@@ static void bnxt_enable_napi(struct bnx
if (bp->bnapi[i]->rx_ring) { INIT_WORK(&cpr->dim.work, bnxt_dim_work); - cpr->dim.mode = NET_DIM_CQ_PERIOD_MODE_START_FROM_EQE; + cpr->dim.mode = DIM_CQ_PERIOD_MODE_START_FROM_EQE; } napi_enable(&bp->bnapi[i]->napi); } @@@ -10292,7 -10238,6 +10297,7 @@@ static const struct net_device_ops bnxt .ndo_udp_tunnel_add = bnxt_udp_tunnel_add, .ndo_udp_tunnel_del = bnxt_udp_tunnel_del, .ndo_bpf = bnxt_xdp, + .ndo_xdp_xmit = bnxt_xdp_xmit, .ndo_bridge_getlink = bnxt_bridge_getlink, .ndo_bridge_setlink = bnxt_bridge_setlink, .ndo_get_devlink_port = bnxt_get_devlink_port, @@@ -10322,10 -10267,10 +10327,10 @@@ static void bnxt_remove_one(struct pci_ bnxt_dcb_free(bp); kfree(bp->edev); bp->edev = NULL; + bnxt_cleanup_pci(bp); bnxt_free_ctx_mem(bp); kfree(bp->ctx); bp->ctx = NULL; - bnxt_cleanup_pci(bp); bnxt_free_port_stats(bp); free_netdev(dev); } @@@ -10919,6 -10864,7 +10924,7 @@@ static void bnxt_shutdown(struct pci_de
if (system_state == SYSTEM_POWER_OFF) { bnxt_clear_int_mode(bp); + pci_disable_device(pdev); pci_wake_from_d3(pdev, bp->wol); pci_set_power_state(pdev, PCI_D3hot); } diff --combined drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c index a0f3277447f5,ec68707c3338..c7ee63d69679 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c @@@ -2799,7 -2799,7 +2799,7 @@@ static int bnxt_run_loopback(struct bnx dev_kfree_skb(skb); return -EIO; } - bnxt_xmit_xdp(bp, txr, map, pkt_size, 0); + bnxt_xmit_bd(bp, txr, map, pkt_size);
/* Sync BD data before updating doorbell */ wmb(); @@@ -2842,7 -2842,7 +2842,7 @@@ static void bnxt_self_test(struct net_d bool offline = false; u8 test_results = 0; u8 test_mask = 0; - int rc, i; + int rc = 0, i;
if (!bp->num_tests || !BNXT_SINGLE_PF(bp)) return; @@@ -2913,9 -2913,9 +2913,9 @@@ } bnxt_hwrm_phy_loopback(bp, false, false); bnxt_half_close_nic(bp); - bnxt_open_nic(bp, false, true); + rc = bnxt_open_nic(bp, false, true); } - if (bnxt_test_irq(bp)) { + if (rc || bnxt_test_irq(bp)) { buf[BNXT_IRQ_TEST_IDX] = 1; etest->flags |= ETH_TEST_FL_FAILED; } diff --combined drivers/net/ethernet/cadence/macb.h index 515bfd2c9e3f,98735584570d..03983bd46eef --- a/drivers/net/ethernet/cadence/macb.h +++ b/drivers/net/ethernet/cadence/macb.h @@@ -496,7 -496,11 +496,11 @@@
/* Bitfields in TISUBN */ #define GEM_SUBNSINCR_OFFSET 0 - #define GEM_SUBNSINCR_SIZE 16 + #define GEM_SUBNSINCRL_OFFSET 24 + #define GEM_SUBNSINCRL_SIZE 8 + #define GEM_SUBNSINCRH_OFFSET 0 + #define GEM_SUBNSINCRH_SIZE 16 + #define GEM_SUBNSINCR_SIZE 24
/* Bitfields in TI */ #define GEM_NSINCR_OFFSET 0 @@@ -834,6 -838,9 +838,9 @@@ struct gem_tx_ts /* limit RX checksum offload to TCP and UDP packets */ #define GEM_RX_CSUM_CHECKED_MASK 2
+ /* Scaled PPM fraction */ + #define PPM_FRACTION 16 + /* struct macb_tx_skb - data about an skb which is being transmitted * @skb: skb currently being transmitted, only set for the last buffer * of the frame @@@ -1060,8 -1067,7 +1067,8 @@@ struct macb_or_gem_ops int (*mog_alloc_rx_buffers)(struct macb *bp); void (*mog_free_rx_buffers)(struct macb *bp); void (*mog_init_rings)(struct macb *bp); - int (*mog_rx)(struct macb_queue *queue, int budget); + int (*mog_rx)(struct macb_queue *queue, struct napi_struct *napi, + int budget); };
/* MACB-PTP interface: adapt to platform needs. */ diff --combined drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index 3425d4dda03d,11b6feb33b54..bdedde99148a --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@@ -35,7 -35,6 +35,7 @@@ #include <linux/seq_file.h> #endif /* CONFIG_DEBUG_FS */ #include <linux/net_tstamp.h> +#include <linux/phylink.h> #include <net/pkt_cls.h> #include "stmmac_ptp.h" #include "stmmac.h" @@@ -319,6 -318,21 +319,6 @@@ static inline u32 stmmac_rx_dirty(struc }
/** - * stmmac_hw_fix_mac_speed - callback for speed selection - * @priv: driver private structure - * Description: on some platforms (e.g. ST), some HW system configuration - * registers have to be set according to the link speed negotiated. - */ -static inline void stmmac_hw_fix_mac_speed(struct stmmac_priv *priv) -{ - struct net_device *ndev = priv->dev; - struct phy_device *phydev = ndev->phydev; - - if (likely(priv->plat->fix_mac_speed)) - priv->plat->fix_mac_speed(priv->plat->bsp_priv, phydev->speed); -} - -/** * stmmac_enable_eee_mode - check and enter in LPI mode * @priv: driver private structure * Description: this function is to verify and enter in LPI mode in case of @@@ -381,7 -395,14 +381,7 @@@ static void stmmac_eee_ctrl_timer(struc */ bool stmmac_eee_init(struct stmmac_priv *priv) { - struct net_device *ndev = priv->dev; - int interface = priv->plat->interface; - bool ret = false; - - if ((interface != PHY_INTERFACE_MODE_MII) && - (interface != PHY_INTERFACE_MODE_GMII) && - !phy_interface_mode_is_rgmii(interface)) - goto out; + int tx_lpi_timer = priv->tx_lpi_timer;
/* Using PCS we cannot dial with the phy registers at this stage * so we do not support extra feature like EEE. @@@ -389,35 -410,52 +389,35 @@@ if ((priv->hw->pcs == STMMAC_PCS_RGMII) || (priv->hw->pcs == STMMAC_PCS_TBI) || (priv->hw->pcs == STMMAC_PCS_RTBI)) - goto out; - - /* MAC core supports the EEE feature. */ - if (priv->dma_cap.eee) { - int tx_lpi_timer = priv->tx_lpi_timer; - - /* Check if the PHY supports EEE */ - if (phy_init_eee(ndev->phydev, 1)) { - /* To manage at run-time if the EEE cannot be supported - * anymore (for example because the lp caps have been - * changed). - * In that case the driver disable own timers. - */ - mutex_lock(&priv->lock); - if (priv->eee_active) { - netdev_dbg(priv->dev, "disable EEE\n"); - del_timer_sync(&priv->eee_ctrl_timer); - stmmac_set_eee_timer(priv, priv->hw, 0, - tx_lpi_timer); - } - priv->eee_active = 0; - mutex_unlock(&priv->lock); - goto out; - } - /* Activate the EEE and start timers */ - mutex_lock(&priv->lock); - if (!priv->eee_active) { - priv->eee_active = 1; - timer_setup(&priv->eee_ctrl_timer, - stmmac_eee_ctrl_timer, 0); - mod_timer(&priv->eee_ctrl_timer, - STMMAC_LPI_T(eee_timer)); - - stmmac_set_eee_timer(priv, priv->hw, - STMMAC_DEFAULT_LIT_LS, tx_lpi_timer); - } - /* Set HW EEE according to the speed */ - stmmac_set_eee_pls(priv, priv->hw, ndev->phydev->link); + return false; + + /* Check if MAC core supports the EEE feature. */ + if (!priv->dma_cap.eee) + return false; + + mutex_lock(&priv->lock);
- ret = true; + /* Check if it needs to be deactivated */ + if (!priv->eee_active) { + if (priv->eee_enabled) { + netdev_dbg(priv->dev, "disable EEE\n"); + del_timer_sync(&priv->eee_ctrl_timer); + stmmac_set_eee_timer(priv, priv->hw, 0, tx_lpi_timer); + } mutex_unlock(&priv->lock); + return false; + }
- netdev_dbg(priv->dev, "Energy-Efficient Ethernet initialized\n"); + if (priv->eee_active && !priv->eee_enabled) { + timer_setup(&priv->eee_ctrl_timer, stmmac_eee_ctrl_timer, 0); + mod_timer(&priv->eee_ctrl_timer, STMMAC_LPI_T(eee_timer)); + stmmac_set_eee_timer(priv, priv->hw, STMMAC_DEFAULT_LIT_LS, + tx_lpi_timer); } -out: - return ret; + + mutex_unlock(&priv->lock); + netdev_dbg(priv->dev, "Energy-Efficient Ethernet initialized\n"); + return true; }
/* stmmac_get_tx_hwtstamp - get HW TX timestamps @@@ -800,171 -838,97 +800,171 @@@ static void stmmac_mac_flow_ctrl(struc priv->pause, tx_cnt); }
-/** - * stmmac_adjust_link - adjusts the link parameters - * @dev: net device structure - * Description: this is the helper called by the physical abstraction layer - * drivers to communicate the phy link status. According the speed and duplex - * this driver can invoke registered glue-logic as well. - * It also invoke the eee initialization because it could happen when switch - * on different networks (that are eee capable). - */ -static void stmmac_adjust_link(struct net_device *dev) +static void stmmac_validate(struct phylink_config *config, + unsigned long *supported, + struct phylink_link_state *state) { - struct stmmac_priv *priv = netdev_priv(dev); - struct phy_device *phydev = dev->phydev; - bool new_state = false; + struct stmmac_priv *priv = netdev_priv(to_net_dev(config->dev)); + __ETHTOOL_DECLARE_LINK_MODE_MASK(mac_supported) = { 0, }; + __ETHTOOL_DECLARE_LINK_MODE_MASK(mask) = { 0, }; + int tx_cnt = priv->plat->tx_queues_to_use; + int max_speed = priv->plat->max_speed;
- if (!phydev) - return; + phylink_set(mac_supported, 10baseT_Half); + phylink_set(mac_supported, 10baseT_Full); + phylink_set(mac_supported, 100baseT_Half); + phylink_set(mac_supported, 100baseT_Full); + + phylink_set(mac_supported, Autoneg); + phylink_set(mac_supported, Pause); + phylink_set(mac_supported, Asym_Pause); + phylink_set_port_modes(mac_supported); + + if (priv->plat->has_gmac || + priv->plat->has_gmac4 || + priv->plat->has_xgmac) { + phylink_set(mac_supported, 1000baseT_Half); + phylink_set(mac_supported, 1000baseT_Full); + phylink_set(mac_supported, 1000baseKX_Full); + }
- mutex_lock(&priv->lock); + /* Cut down 1G if asked to */ + if ((max_speed > 0) && (max_speed < 1000)) { + phylink_set(mask, 1000baseT_Full); + phylink_set(mask, 1000baseX_Full); + } else if (priv->plat->has_xgmac) { + phylink_set(mac_supported, 2500baseT_Full); + phylink_set(mac_supported, 5000baseT_Full); + phylink_set(mac_supported, 10000baseSR_Full); + phylink_set(mac_supported, 10000baseLR_Full); + phylink_set(mac_supported, 10000baseER_Full); + phylink_set(mac_supported, 10000baseLRM_Full); + phylink_set(mac_supported, 10000baseT_Full); + phylink_set(mac_supported, 10000baseKX4_Full); + phylink_set(mac_supported, 10000baseKR_Full); + }
- if (phydev->link) { - u32 ctrl = readl(priv->ioaddr + MAC_CTRL_REG); + /* Half-Duplex can only work with single queue */ + if (tx_cnt > 1) { + phylink_set(mask, 10baseT_Half); + phylink_set(mask, 100baseT_Half); + phylink_set(mask, 1000baseT_Half); + }
- /* Now we make sure that we can be in full duplex mode. - * If not, we operate in half-duplex mode. */ - if (phydev->duplex != priv->oldduplex) { - new_state = true; - if (!phydev->duplex) - ctrl &= ~priv->hw->link.duplex; - else - ctrl |= priv->hw->link.duplex; - priv->oldduplex = phydev->duplex; - } - /* Flow Control operation */ - if (phydev->pause) - stmmac_mac_flow_ctrl(priv, phydev->duplex); - - if (phydev->speed != priv->speed) { - new_state = true; - ctrl &= ~priv->hw->link.speed_mask; - switch (phydev->speed) { - case SPEED_1000: - ctrl |= priv->hw->link.speed1000; - break; - case SPEED_100: - ctrl |= priv->hw->link.speed100; - break; - case SPEED_10: - ctrl |= priv->hw->link.speed10; - break; - default: - netif_warn(priv, link, priv->dev, - "broken speed: %d\n", phydev->speed); - phydev->speed = SPEED_UNKNOWN; - break; - } - if (phydev->speed != SPEED_UNKNOWN) - stmmac_hw_fix_mac_speed(priv); - priv->speed = phydev->speed; - } + bitmap_and(supported, supported, mac_supported, + __ETHTOOL_LINK_MODE_MASK_NBITS); + bitmap_andnot(supported, supported, mask, + __ETHTOOL_LINK_MODE_MASK_NBITS); + bitmap_and(state->advertising, state->advertising, mac_supported, + __ETHTOOL_LINK_MODE_MASK_NBITS); + bitmap_andnot(state->advertising, state->advertising, mask, + __ETHTOOL_LINK_MODE_MASK_NBITS); +} + +static int stmmac_mac_link_state(struct phylink_config *config, + struct phylink_link_state *state) +{ + return -EOPNOTSUPP; +} + +static void stmmac_mac_config(struct phylink_config *config, unsigned int mode, + const struct phylink_link_state *state) +{ + struct stmmac_priv *priv = netdev_priv(to_net_dev(config->dev)); + u32 ctrl;
- writel(ctrl, priv->ioaddr + MAC_CTRL_REG); + ctrl = readl(priv->ioaddr + MAC_CTRL_REG); + ctrl &= ~priv->hw->link.speed_mask;
- if (!priv->oldlink) { - new_state = true; - priv->oldlink = true; + if (state->interface == PHY_INTERFACE_MODE_USXGMII) { + switch (state->speed) { + case SPEED_10000: + ctrl |= priv->hw->link.xgmii.speed10000; + break; + case SPEED_5000: + ctrl |= priv->hw->link.xgmii.speed5000; + break; + case SPEED_2500: + ctrl |= priv->hw->link.xgmii.speed2500; + break; + default: + return; + } + } else { + switch (state->speed) { + case SPEED_2500: + ctrl |= priv->hw->link.speed2500; + break; + case SPEED_1000: + ctrl |= priv->hw->link.speed1000; + break; + case SPEED_100: + ctrl |= priv->hw->link.speed100; + break; + case SPEED_10: + ctrl |= priv->hw->link.speed10; + break; + default: + return; } - } else if (priv->oldlink) { - new_state = true; - priv->oldlink = false; - priv->speed = SPEED_UNKNOWN; - priv->oldduplex = DUPLEX_UNKNOWN; }
- if (new_state && netif_msg_link(priv)) - phy_print_status(phydev); + priv->speed = state->speed;
- mutex_unlock(&priv->lock); + if (priv->plat->fix_mac_speed) + priv->plat->fix_mac_speed(priv->plat->bsp_priv, state->speed);
- if (phydev->is_pseudo_fixed_link) - /* Stop PHY layer to call the hook to adjust the link in case - * of a switch is attached to the stmmac driver. - */ - phydev->irq = PHY_IGNORE_INTERRUPT; + if (!state->duplex) + ctrl &= ~priv->hw->link.duplex; else - /* At this stage, init the EEE if supported. - * Never called in case of fixed_link. - */ + ctrl |= priv->hw->link.duplex; + + /* Flow Control operation */ + if (state->pause) + stmmac_mac_flow_ctrl(priv, state->duplex); + + writel(ctrl, priv->ioaddr + MAC_CTRL_REG); +} + +static void stmmac_mac_an_restart(struct phylink_config *config) +{ + /* Not Supported */ +} + +static void stmmac_mac_link_down(struct phylink_config *config, + unsigned int mode, phy_interface_t interface) +{ + struct stmmac_priv *priv = netdev_priv(to_net_dev(config->dev)); + + stmmac_mac_set(priv, priv->ioaddr, false); + priv->eee_active = false; + stmmac_eee_init(priv); + stmmac_set_eee_pls(priv, priv->hw, false); +} + +static void stmmac_mac_link_up(struct phylink_config *config, + unsigned int mode, phy_interface_t interface, + struct phy_device *phy) +{ + struct stmmac_priv *priv = netdev_priv(to_net_dev(config->dev)); + + stmmac_mac_set(priv, priv->ioaddr, true); + if (phy && priv->dma_cap.eee) { + priv->eee_active = phy_init_eee(phy, 1) >= 0; priv->eee_enabled = stmmac_eee_init(priv); + stmmac_set_eee_pls(priv, priv->hw, true); + } }
+static const struct phylink_mac_ops stmmac_phylink_mac_ops = { + .validate = stmmac_validate, + .mac_link_state = stmmac_mac_link_state, + .mac_config = stmmac_mac_config, + .mac_an_restart = stmmac_mac_an_restart, + .mac_link_down = stmmac_mac_link_down, + .mac_link_up = stmmac_mac_link_up, +}; + /** * stmmac_check_pcs_mode - verify if RGMII/SGMII is supported * @priv: driver private structure @@@ -1001,48 -965,79 +1001,48 @@@ static void stmmac_check_pcs_mode(struc static int stmmac_init_phy(struct net_device *dev) { struct stmmac_priv *priv = netdev_priv(dev); - u32 tx_cnt = priv->plat->tx_queues_to_use; - struct phy_device *phydev; - char phy_id_fmt[MII_BUS_ID_SIZE + 3]; - char bus_id[MII_BUS_ID_SIZE]; - int interface = priv->plat->interface; - int max_speed = priv->plat->max_speed; - priv->oldlink = false; - priv->speed = SPEED_UNKNOWN; - priv->oldduplex = DUPLEX_UNKNOWN; + struct device_node *node; + int ret;
- if (priv->plat->phy_node) { - phydev = of_phy_connect(dev, priv->plat->phy_node, - &stmmac_adjust_link, 0, interface); - } else { - snprintf(bus_id, MII_BUS_ID_SIZE, "stmmac-%x", - priv->plat->bus_id); + node = priv->plat->phylink_node;
- snprintf(phy_id_fmt, MII_BUS_ID_SIZE + 3, PHY_ID_FMT, bus_id, - priv->plat->phy_addr); - netdev_dbg(priv->dev, "%s: trying to attach to %s\n", __func__, - phy_id_fmt); + if (node) + ret = phylink_of_phy_connect(priv->phylink, node, 0);
- phydev = phy_connect(dev, phy_id_fmt, &stmmac_adjust_link, - interface); - } + /* Some DT bindings do not set-up the PHY handle. Let's try to + * manually parse it + */ + if (!node || ret) { + int addr = priv->plat->phy_addr; + struct phy_device *phydev;
- if (IS_ERR_OR_NULL(phydev)) { - netdev_err(priv->dev, "Could not attach to PHY\n"); - if (!phydev) + phydev = mdiobus_get_phy(priv->mii, addr); + if (!phydev) { + netdev_err(priv->dev, "no phy at addr %d\n", addr); return -ENODEV; + }
- return PTR_ERR(phydev); + ret = phylink_connect_phy(priv->phylink, phydev); }
- /* Stop Advertising 1000BASE Capability if interface is not GMII */ - if ((interface == PHY_INTERFACE_MODE_MII) || - (interface == PHY_INTERFACE_MODE_RMII) || - (max_speed < 1000 && max_speed > 0)) - phy_set_max_speed(phydev, SPEED_100); + return ret; +}
- /* - * Half-duplex mode not supported with multiqueue - * half-duplex can only works with single queue - */ - if (tx_cnt > 1) { - phy_remove_link_mode(phydev, - ETHTOOL_LINK_MODE_10baseT_Half_BIT); - phy_remove_link_mode(phydev, - ETHTOOL_LINK_MODE_100baseT_Half_BIT); - phy_remove_link_mode(phydev, - ETHTOOL_LINK_MODE_1000baseT_Half_BIT); - } +static int stmmac_phy_setup(struct stmmac_priv *priv) +{ + struct fwnode_handle *fwnode = of_fwnode_handle(priv->plat->phylink_node); + int mode = priv->plat->interface; + struct phylink *phylink;
- /* - * Broken HW is sometimes missing the pull-up resistor on the - * MDIO line, which results in reads to non-existent devices returning - * 0 rather than 0xffff. Catch this here and treat 0 as a non-existent - * device as well. - * Note: phydev->phy_id is the result of reading the UID PHY registers. - */ - if (!priv->plat->phy_node && phydev->phy_id == 0) { - phy_disconnect(phydev); - return -ENODEV; - } + priv->phylink_config.dev = &priv->dev->dev; + priv->phylink_config.type = PHYLINK_NETDEV;
- /* stmmac_adjust_link will change this to PHY_IGNORE_INTERRUPT to avoid - * subsequent PHY polling, make sure we force a link transition if - * we have a UP/DOWN/UP transition - */ - if (phydev->is_pseudo_fixed_link) - phydev->irq = PHY_POLL; + phylink = phylink_create(&priv->phylink_config, fwnode, + mode, &stmmac_phylink_mac_ops); + if (IS_ERR(phylink)) + return PTR_ERR(phylink);
- phy_attached_info(phydev); + priv->phylink = phylink; return 0; }
@@@ -2054,15 -2049,14 +2054,15 @@@ static int stmmac_napi_check(struct stm struct stmmac_channel *ch = &priv->channel[chan];
if ((status & handle_rx) && (chan < priv->plat->rx_queues_to_use)) { - stmmac_disable_dma_irq(priv, priv->ioaddr, chan); - napi_schedule_irqoff(&ch->rx_napi); + if (napi_schedule_prep(&ch->rx_napi)) { + stmmac_disable_dma_irq(priv, priv->ioaddr, chan); + __napi_schedule_irqoff(&ch->rx_napi); + status |= handle_tx; + } }
- if ((status & handle_tx) && (chan < priv->plat->tx_queues_to_use)) { - stmmac_disable_dma_irq(priv, priv->ioaddr, chan); + if ((status & handle_tx) && (chan < priv->plat->tx_queues_to_use)) napi_schedule_irqoff(&ch->tx_napi); - }
return status; } @@@ -2124,10 -2118,10 +2124,10 @@@ static void stmmac_mmc_setup(struct stm unsigned int mode = MMC_CNTRL_RESET_ON_READ | MMC_CNTRL_COUNTER_RESET | MMC_CNTRL_PRESET | MMC_CNTRL_FULL_HALF_PRESET;
- dwmac_mmc_intr_all_mask(priv->mmcaddr); + stmmac_mmc_intr_all_mask(priv, priv->mmcaddr);
if (priv->dma_cap.rmon) { - dwmac_mmc_ctrl(priv->mmcaddr, mode); + stmmac_mmc_ctrl(priv, priv->mmcaddr, mode); memset(&priv->mmc, 0, sizeof(struct stmmac_counters)); } else netdev_info(priv->dev, "No MAC Management Counters available\n"); @@@ -2160,8 -2154,8 +2160,8 @@@ static void stmmac_check_ether_addr(str stmmac_get_umac_addr(priv, priv->hw, priv->dev->dev_addr, 0); if (!is_valid_ether_addr(priv->dev->dev_addr)) eth_hw_addr_random(priv->dev); - netdev_info(priv->dev, "device MAC address %pM\n", - priv->dev->dev_addr); + dev_info(priv->device, "device MAC address %pM\n", + priv->dev->dev_addr); } }
@@@ -2567,9 -2561,9 +2567,9 @@@ static int stmmac_hw_setup(struct net_d priv->tx_lpi_timer = STMMAC_DEFAULT_TWT_LS;
if (priv->use_riwt) { - ret = stmmac_rx_watchdog(priv, priv->ioaddr, MAX_DMA_RIWT, rx_cnt); + ret = stmmac_rx_watchdog(priv, priv->ioaddr, MIN_DMA_RIWT, rx_cnt); if (!ret) - priv->rx_riwt = MAX_DMA_RIWT; + priv->rx_riwt = MIN_DMA_RIWT; }
if (priv->hw->pcs) @@@ -2653,7 -2647,8 +2653,7 @@@ static int stmmac_open(struct net_devic
stmmac_init_tx_coalesce(priv);
- if (dev->phydev) - phy_start(dev->phydev); + phylink_start(priv->phylink);
/* Request the IRQ lines */ ret = request_irq(dev->irq, stmmac_interrupt, @@@ -2700,7 -2695,8 +2700,7 @@@ lpiirq_error wolirq_error: free_irq(dev->irq, dev); irq_error: - if (dev->phydev) - phy_stop(dev->phydev); + phylink_stop(priv->phylink);
for (chan = 0; chan < priv->plat->tx_queues_to_use; chan++) del_timer_sync(&priv->tx_queue[chan].txtimer); @@@ -2709,7 -2705,9 +2709,7 @@@ init_error: free_dma_desc_resources(priv); dma_desc_error: - if (dev->phydev) - phy_disconnect(dev->phydev); - + phylink_disconnect_phy(priv->phylink); return ret; }
@@@ -2728,8 -2726,10 +2728,8 @@@ static int stmmac_release(struct net_de del_timer_sync(&priv->eee_ctrl_timer);
/* Stop and disconnect the PHY */ - if (dev->phydev) { - phy_stop(dev->phydev); - phy_disconnect(dev->phydev); - } + phylink_stop(priv->phylink); + phylink_disconnect_phy(priv->phylink);
stmmac_stop_all_queues(priv);
@@@ -2772,7 -2772,7 +2772,7 @@@ * This function fills descriptor and request new descriptors according to * buffer length to fill */ -static void stmmac_tso_allocator(struct stmmac_priv *priv, unsigned int des, +static void stmmac_tso_allocator(struct stmmac_priv *priv, dma_addr_t des, int total_len, bool last_segment, u32 queue) { struct stmmac_tx_queue *tx_q = &priv->tx_queue[queue]; @@@ -2783,18 -2783,11 +2783,18 @@@ tmp_len = total_len;
while (tmp_len > 0) { + dma_addr_t curr_addr; + tx_q->cur_tx = STMMAC_GET_ENTRY(tx_q->cur_tx, DMA_TX_SIZE); WARN_ON(tx_q->tx_skbuff[tx_q->cur_tx]); desc = tx_q->dma_tx + tx_q->cur_tx;
- desc->des0 = cpu_to_le32(des + (total_len - tmp_len)); + curr_addr = des + (total_len - tmp_len); + if (priv->dma_cap.addr64 <= 32) + desc->des0 = cpu_to_le32(curr_addr); + else + stmmac_set_desc_addr(priv, desc, curr_addr); + buff_size = tmp_len >= TSO_MAX_BUFF_SIZE ? TSO_MAX_BUFF_SIZE : tmp_len;
@@@ -2840,12 -2833,11 +2840,12 @@@ static netdev_tx_t stmmac_tso_xmit(stru struct stmmac_priv *priv = netdev_priv(dev); int nfrags = skb_shinfo(skb)->nr_frags; u32 queue = skb_get_queue_mapping(skb); - unsigned int first_entry, des; + unsigned int first_entry; struct stmmac_tx_queue *tx_q; int tmp_pay_len = 0; u32 pay_len, mss; u8 proto_hdr_len; + dma_addr_t des; int i;
tx_q = &priv->tx_queue[queue]; @@@ -2902,19 -2894,14 +2902,19 @@@ tx_q->tx_skbuff_dma[first_entry].buf = des; tx_q->tx_skbuff_dma[first_entry].len = skb_headlen(skb);
- first->des0 = cpu_to_le32(des); + if (priv->dma_cap.addr64 <= 32) { + first->des0 = cpu_to_le32(des);
- /* Fill start of payload in buff2 of first descriptor */ - if (pay_len) - first->des1 = cpu_to_le32(des + proto_hdr_len); + /* Fill start of payload in buff2 of first descriptor */ + if (pay_len) + first->des1 = cpu_to_le32(des + proto_hdr_len);
- /* If needed take extra descriptors to fill the remaining payload */ - tmp_pay_len = pay_len - TSO_MAX_BUFF_SIZE; + /* If needed take extra descriptors to fill the remaining payload */ + tmp_pay_len = pay_len - TSO_MAX_BUFF_SIZE; + } else { + stmmac_set_desc_addr(priv, first, des); + tmp_pay_len = pay_len; + }
stmmac_tso_allocator(priv, des, tmp_pay_len, (nfrags == 0), queue);
@@@ -3044,12 -3031,12 +3044,12 @@@ static netdev_tx_t stmmac_xmit(struct s int i, csum_insertion = 0, is_jumbo = 0; u32 queue = skb_get_queue_mapping(skb); int nfrags = skb_shinfo(skb)->nr_frags; - int entry; - unsigned int first_entry; struct dma_desc *desc, *first; struct stmmac_tx_queue *tx_q; + unsigned int first_entry; unsigned int enh_desc; - unsigned int des; + dma_addr_t des; + int entry;
tx_q = &priv->tx_queue[queue];
@@@ -3058,17 -3045,8 +3058,8 @@@
/* Manage oversized TCP frames for GMAC4 device */ if (skb_is_gso(skb) && priv->tso) { - if (skb_shinfo(skb)->gso_type & (SKB_GSO_TCPV4 | SKB_GSO_TCPV6)) { - /* - * There is no way to determine the number of TSO - * capable Queues. Let's use always the Queue 0 - * because if TSO is supported then at least this - * one will be capable. - */ - skb_set_queue_mapping(skb, 0); - + if (skb_shinfo(skb)->gso_type & (SKB_GSO_TCPV4 | SKB_GSO_TCPV6)) return stmmac_tso_xmit(skb, dev); - } }
if (unlikely(stmmac_tx_avail(priv, queue) < nfrags + 1)) { @@@ -3347,8 -3325,6 +3338,8 @@@ static inline void stmmac_rx_refill(str entry = STMMAC_GET_ENTRY(entry, DMA_RX_SIZE); } rx_q->dirty_rx = entry; + rx_q->rx_tail_addr = rx_q->dma_rx_phy + + (rx_q->dirty_rx * sizeof(struct dma_desc)); stmmac_set_rx_tail_ptr(priv, priv->ioaddr, rx_q->rx_tail_addr, queue); }
@@@ -3583,8 -3559,8 +3574,8 @@@ static int stmmac_napi_poll_tx(struct n work_done = stmmac_tx_clean(priv, DMA_TX_SIZE, chan); work_done = min(work_done, budget);
- if (work_done < budget && napi_complete_done(napi, work_done)) - stmmac_enable_dma_irq(priv, priv->ioaddr, chan); + if (work_done < budget) + napi_complete_done(napi, work_done);
/* Force transmission restart */ tx_q = &priv->tx_queue[chan]; @@@ -3807,7 -3783,6 +3798,7 @@@ static void stmmac_poll_controller(stru */ static int stmmac_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) { + struct stmmac_priv *priv = netdev_priv (dev); int ret = -EOPNOTSUPP;
if (!netif_running(dev)) @@@ -3817,7 -3792,9 +3808,7 @@@ case SIOCGMIIPHY: case SIOCGMIIREG: case SIOCSMIIREG: - if (!dev->phydev) - return -EINVAL; - ret = phy_mii_ioctl(dev->phydev, rq, cmd); + ret = phylink_mii_ioctl(priv->phylink, rq, cmd); break; case SIOCSHWTSTAMP: ret = stmmac_hwtstamp_set(dev, rq); @@@ -3886,6 -3863,22 +3877,22 @@@ static int stmmac_setup_tc(struct net_d } }
+ static u16 stmmac_select_queue(struct net_device *dev, struct sk_buff *skb, + struct net_device *sb_dev) + { + if (skb_shinfo(skb)->gso_type & (SKB_GSO_TCPV4 | SKB_GSO_TCPV6)) { + /* + * There is no way to determine the number of TSO + * capable Queues. Let's use always the Queue 0 + * because if TSO is supported then at least this + * one will be capable. + */ + return 0; + } + + return netdev_pick_tx(dev, skb, NULL) % dev->real_num_tx_queues; + } + static int stmmac_set_mac_address(struct net_device *ndev, void *addr) { struct stmmac_priv *priv = netdev_priv(ndev); @@@ -4102,6 -4095,7 +4109,7 @@@ static const struct net_device_ops stmm .ndo_tx_timeout = stmmac_tx_timeout, .ndo_do_ioctl = stmmac_ioctl, .ndo_setup_tc = stmmac_setup_tc, + .ndo_select_queue = stmmac_select_queue, #ifdef CONFIG_NET_POLL_CONTROLLER .ndo_poll_controller = stmmac_poll_controller, #endif @@@ -4251,8 -4245,9 +4259,8 @@@ int stmmac_dvr_probe(struct device *dev u32 queue, maxq; int ret = 0;
- ndev = alloc_etherdev_mqs(sizeof(struct stmmac_priv), - MTL_MAX_TX_QUEUES, - MTL_MAX_RX_QUEUES); + ndev = devm_alloc_etherdev_mqs(device, sizeof(struct stmmac_priv), + MTL_MAX_TX_QUEUES, MTL_MAX_RX_QUEUES); if (!ndev) return -ENOMEM;
@@@ -4284,7 -4279,8 +4292,7 @@@ priv->wq = create_singlethread_workqueue("stmmac_wq"); if (!priv->wq) { dev_err(priv->device, "failed to create workqueue\n"); - ret = -ENOMEM; - goto error_wq; + return -ENOMEM; }
INIT_WORK(&priv->service_task, stmmac_service_task); @@@ -4331,24 -4327,6 +4339,24 @@@ priv->tso = true; dev_info(priv->device, "TSO feature enabled\n"); } + + if (priv->dma_cap.addr64) { + ret = dma_set_mask_and_coherent(device, + DMA_BIT_MASK(priv->dma_cap.addr64)); + if (!ret) { + dev_info(priv->device, "Using %d bits DMA width\n", + priv->dma_cap.addr64); + } else { + ret = dma_set_mask_and_coherent(device, DMA_BIT_MASK(32)); + if (ret) { + dev_err(priv->device, "Failed to set DMA Mask\n"); + goto error_hw_init; + } + + priv->dma_cap.addr64 = 32; + } + } + ndev->features |= ndev->hw_features | NETIF_F_HIGHDMA; ndev->watchdog_timeo = msecs_to_jiffies(watchdog); #ifdef STMMAC_VLAN_TAG_USED @@@ -4426,12 -4404,6 +4434,12 @@@ } }
+ ret = stmmac_phy_setup(priv); + if (ret) { + netdev_err(ndev, "failed to setup phy (%d)\n", ret); + goto error_phy_setup; + } + ret = register_netdev(ndev); if (ret) { dev_err(priv->device, "%s: ERROR %i registering the device\n", @@@ -4449,8 -4421,6 +4457,8 @@@ return ret;
error_netdev_register: + phylink_destroy(priv->phylink); +error_phy_setup: if (priv->hw->pcs != STMMAC_PCS_RGMII && priv->hw->pcs != STMMAC_PCS_TBI && priv->hw->pcs != STMMAC_PCS_RTBI) @@@ -4466,6 -4436,8 +4474,6 @@@ error_mdio_register } error_hw_init: destroy_workqueue(priv->wq); -error_wq: - free_netdev(ndev);
return ret; } @@@ -4492,7 -4464,6 +4500,7 @@@ int stmmac_dvr_remove(struct device *de stmmac_mac_set(priv, priv->ioaddr, false); netif_carrier_off(ndev); unregister_netdev(ndev); + phylink_destroy(priv->phylink); if (priv->plat->stmmac_rst) reset_control_assert(priv->plat->stmmac_rst); clk_disable_unprepare(priv->plat->pclk); @@@ -4503,6 -4474,7 +4511,6 @@@ stmmac_mdio_unregister(ndev); destroy_workqueue(priv->wq); mutex_destroy(&priv->lock); - free_netdev(ndev);
return 0; } @@@ -4523,7 -4495,8 +4531,7 @@@ int stmmac_suspend(struct device *dev if (!ndev || !netif_running(ndev)) return 0;
- if (ndev->phydev) - phy_stop(ndev->phydev); + phylink_stop(priv->phylink);
mutex_lock(&priv->lock);
@@@ -4548,7 -4521,9 +4556,7 @@@ } mutex_unlock(&priv->lock);
- priv->oldlink = false; priv->speed = SPEED_UNKNOWN; - priv->oldduplex = DUPLEX_UNKNOWN; return 0; } EXPORT_SYMBOL_GPL(stmmac_suspend); @@@ -4632,7 -4607,8 +4640,7 @@@ int stmmac_resume(struct device *dev
mutex_unlock(&priv->lock);
- if (ndev->phydev) - phy_start(ndev->phydev); + phylink_start(priv->phylink);
return 0; } diff --combined drivers/net/ethernet/ti/cpsw.c index f16aefd8870b,4e3026f9abed..f320f9a0de8b --- a/drivers/net/ethernet/ti/cpsw.c +++ b/drivers/net/ethernet/ti/cpsw.c @@@ -31,10 -31,6 +31,10 @@@ #include <linux/if_vlan.h> #include <linux/kmemleak.h> #include <linux/sys_soc.h> +#include <net/page_pool.h> +#include <linux/bpf.h> +#include <linux/bpf_trace.h> +#include <linux/filter.h>
#include <linux/pinctrl/consumer.h> #include <net/pkt_cls.h> @@@ -64,10 -60,6 +64,10 @@@ static int descs_pool_size = CPSW_CPDMA module_param(descs_pool_size, int, 0444); MODULE_PARM_DESC(descs_pool_size, "Number of CPDMA CPPI descriptors in pool");
+/* The buf includes headroom compatible with both skb and xdpf */ +#define CPSW_HEADROOM_NA (max(XDP_PACKET_HEADROOM, NET_SKB_PAD) + NET_IP_ALIGN) +#define CPSW_HEADROOM ALIGN(CPSW_HEADROOM_NA, sizeof(long)) + #define for_each_slave(priv, func, arg...) \ do { \ struct cpsw_slave *slave; \ @@@ -82,11 -74,6 +82,11 @@@ (func)(slave++, ##arg); \ } while (0)
+#define CPSW_XMETA_OFFSET ALIGN(sizeof(struct xdp_frame), sizeof(long)) + +#define CPSW_XDP_CONSUMED 1 +#define CPSW_XDP_PASS 0 + static int cpsw_ndo_vlan_rx_add_vid(struct net_device *ndev, __be16 proto, u16 vid);
@@@ -350,58 -337,24 +350,58 @@@ void cpsw_intr_disable(struct cpsw_comm return; }
+static int cpsw_is_xdpf_handle(void *handle) +{ + return (unsigned long)handle & BIT(0); +} + +static void *cpsw_xdpf_to_handle(struct xdp_frame *xdpf) +{ + return (void *)((unsigned long)xdpf | BIT(0)); +} + +static struct xdp_frame *cpsw_handle_to_xdpf(void *handle) +{ + return (struct xdp_frame *)((unsigned long)handle & ~BIT(0)); +} + +struct __aligned(sizeof(long)) cpsw_meta_xdp { + struct net_device *ndev; + int ch; +}; + void cpsw_tx_handler(void *token, int len, int status) { + struct cpsw_meta_xdp *xmeta; + struct xdp_frame *xdpf; + struct net_device *ndev; struct netdev_queue *txq; - struct sk_buff *skb = token; - struct net_device *ndev = skb->dev; - struct cpsw_common *cpsw = ndev_to_cpsw(ndev); + struct sk_buff *skb; + int ch; + + if (cpsw_is_xdpf_handle(token)) { + xdpf = cpsw_handle_to_xdpf(token); + xmeta = (void *)xdpf + CPSW_XMETA_OFFSET; + ndev = xmeta->ndev; + ch = xmeta->ch; + xdp_return_frame(xdpf); + } else { + skb = token; + ndev = skb->dev; + ch = skb_get_queue_mapping(skb); + cpts_tx_timestamp(ndev_to_cpsw(ndev)->cpts, skb); + dev_kfree_skb_any(skb); + }
/* Check whether the queue is stopped due to stalled tx dma, if the * queue is stopped then start the queue as we have free desc for tx */ - txq = netdev_get_tx_queue(ndev, skb_get_queue_mapping(skb)); + txq = netdev_get_tx_queue(ndev, ch); if (unlikely(netif_tx_queue_stopped(txq))) netif_tx_wake_queue(txq);
- cpts_tx_timestamp(cpsw->cpts, skb); ndev->stats.tx_packets++; ndev->stats.tx_bytes += len; - dev_kfree_skb_any(skb); }
static void cpsw_rx_vlan_encap(struct sk_buff *skb) @@@ -447,252 -400,24 +447,252 @@@ } }
+static int cpsw_xdp_tx_frame(struct cpsw_priv *priv, struct xdp_frame *xdpf, + struct page *page) +{ + struct cpsw_common *cpsw = priv->cpsw; + struct cpsw_meta_xdp *xmeta; + struct cpdma_chan *txch; + dma_addr_t dma; + int ret, port; + + xmeta = (void *)xdpf + CPSW_XMETA_OFFSET; + xmeta->ndev = priv->ndev; + xmeta->ch = 0; + txch = cpsw->txv[0].ch; + + port = priv->emac_port + cpsw->data.dual_emac; + if (page) { + dma = page_pool_get_dma_addr(page); + dma += xdpf->headroom + sizeof(struct xdp_frame); + ret = cpdma_chan_submit_mapped(txch, cpsw_xdpf_to_handle(xdpf), + dma, xdpf->len, port); + } else { + if (sizeof(*xmeta) > xdpf->headroom) { + xdp_return_frame_rx_napi(xdpf); + return -EINVAL; + } + + ret = cpdma_chan_submit(txch, cpsw_xdpf_to_handle(xdpf), + xdpf->data, xdpf->len, port); + } + + if (ret) { + priv->ndev->stats.tx_dropped++; + xdp_return_frame_rx_napi(xdpf); + } + + return ret; +} + +static int cpsw_run_xdp(struct cpsw_priv *priv, int ch, struct xdp_buff *xdp, + struct page *page) +{ + struct cpsw_common *cpsw = priv->cpsw; + struct net_device *ndev = priv->ndev; + int ret = CPSW_XDP_CONSUMED; + struct xdp_frame *xdpf; + struct bpf_prog *prog; + u32 act; + + rcu_read_lock(); + + prog = READ_ONCE(priv->xdp_prog); + if (!prog) { + ret = CPSW_XDP_PASS; + goto out; + } + + act = bpf_prog_run_xdp(prog, xdp); + switch (act) { + case XDP_PASS: + ret = CPSW_XDP_PASS; + break; + case XDP_TX: + xdpf = convert_to_xdp_frame(xdp); + if (unlikely(!xdpf)) + goto drop; + + cpsw_xdp_tx_frame(priv, xdpf, page); + break; + case XDP_REDIRECT: + if (xdp_do_redirect(ndev, xdp, prog)) + goto drop; + + /* Have to flush here, per packet, instead of doing it in bulk + * at the end of the napi handler. The RX devices on this + * particular hardware is sharing a common queue, so the + * incoming device might change per packet. + */ + xdp_do_flush_map(); + break; + default: + bpf_warn_invalid_xdp_action(act); + /* fall through */ + case XDP_ABORTED: + trace_xdp_exception(ndev, prog, act); + /* fall through -- handle aborts by dropping packet */ + case XDP_DROP: + goto drop; + } +out: + rcu_read_unlock(); + return ret; +drop: + rcu_read_unlock(); + page_pool_recycle_direct(cpsw->page_pool[ch], page); + return ret; +} + +static unsigned int cpsw_rxbuf_total_len(unsigned int len) +{ + len += CPSW_HEADROOM; + len += SKB_DATA_ALIGN(sizeof(struct skb_shared_info)); + + return SKB_DATA_ALIGN(len); +} + +static struct page_pool *cpsw_create_page_pool(struct cpsw_common *cpsw, + int size) +{ + struct page_pool_params pp_params; + struct page_pool *pool; + + pp_params.order = 0; + pp_params.flags = PP_FLAG_DMA_MAP; + pp_params.pool_size = size; + pp_params.nid = NUMA_NO_NODE; + pp_params.dma_dir = DMA_BIDIRECTIONAL; + pp_params.dev = cpsw->dev; + + pool = page_pool_create(&pp_params); + if (IS_ERR(pool)) + dev_err(cpsw->dev, "cannot create rx page pool\n"); + + return pool; +} + +static int cpsw_ndev_create_xdp_rxq(struct cpsw_priv *priv, int ch) +{ + struct cpsw_common *cpsw = priv->cpsw; + struct xdp_rxq_info *rxq; + struct page_pool *pool; + int ret; + + pool = cpsw->page_pool[ch]; + rxq = &priv->xdp_rxq[ch]; + + ret = xdp_rxq_info_reg(rxq, priv->ndev, ch); + if (ret) + return ret; + + ret = xdp_rxq_info_reg_mem_model(rxq, MEM_TYPE_PAGE_POOL, pool); + if (ret) + xdp_rxq_info_unreg(rxq); + + return ret; +} + +static void cpsw_ndev_destroy_xdp_rxq(struct cpsw_priv *priv, int ch) +{ + struct xdp_rxq_info *rxq = &priv->xdp_rxq[ch]; + + if (!xdp_rxq_info_is_reg(rxq)) + return; + + xdp_rxq_info_unreg(rxq); +} + +static int cpsw_create_rx_pool(struct cpsw_common *cpsw, int ch) +{ + struct page_pool *pool; + int ret = 0, pool_size; + + pool_size = cpdma_chan_get_rx_buf_num(cpsw->rxv[ch].ch); + pool = cpsw_create_page_pool(cpsw, pool_size); + if (IS_ERR(pool)) + ret = PTR_ERR(pool); + else + cpsw->page_pool[ch] = pool; + + return ret; +} + +void cpsw_destroy_xdp_rxqs(struct cpsw_common *cpsw) +{ + struct net_device *ndev; + int i, ch; + + for (ch = 0; ch < cpsw->rx_ch_num; ch++) { + for (i = 0; i < cpsw->data.slaves; i++) { + ndev = cpsw->slaves[i].ndev; + if (!ndev) + continue; + + cpsw_ndev_destroy_xdp_rxq(netdev_priv(ndev), ch); + } + + page_pool_destroy(cpsw->page_pool[ch]); + cpsw->page_pool[ch] = NULL; + } +} + +int cpsw_create_xdp_rxqs(struct cpsw_common *cpsw) +{ + struct net_device *ndev; + int i, ch, ret; + + for (ch = 0; ch < cpsw->rx_ch_num; ch++) { + ret = cpsw_create_rx_pool(cpsw, ch); + if (ret) + goto err_cleanup; + + /* using same page pool is allowed as no running rx handlers + * simultaneously for both ndevs + */ + for (i = 0; i < cpsw->data.slaves; i++) { + ndev = cpsw->slaves[i].ndev; + if (!ndev) + continue; + + ret = cpsw_ndev_create_xdp_rxq(netdev_priv(ndev), ch); + if (ret) + goto err_cleanup; + } + } + + return 0; + +err_cleanup: + cpsw_destroy_xdp_rxqs(cpsw); + + return ret; +} + static void cpsw_rx_handler(void *token, int len, int status) { - struct cpdma_chan *ch; - struct sk_buff *skb = token; - struct sk_buff *new_skb; - struct net_device *ndev = skb->dev; - int ret = 0, port; - struct cpsw_common *cpsw = ndev_to_cpsw(ndev); + struct page *new_page, *page = token; + void *pa = page_address(page); + struct cpsw_meta_xdp *xmeta = pa + CPSW_XMETA_OFFSET; + struct cpsw_common *cpsw = ndev_to_cpsw(xmeta->ndev); + int pkt_size = cpsw->rx_packet_max; + int ret = 0, port, ch = xmeta->ch; + int headroom = CPSW_HEADROOM; + struct net_device *ndev = xmeta->ndev; struct cpsw_priv *priv; + struct page_pool *pool; + struct sk_buff *skb; + struct xdp_buff xdp; + dma_addr_t dma;
- if (cpsw->data.dual_emac) { + if (cpsw->data.dual_emac && status >= 0) { port = CPDMA_RX_SOURCE_PORT(status); - if (port) { + if (port) ndev = cpsw->slaves[--port].ndev; - skb->dev = ndev; - } }
+ priv = netdev_priv(ndev); + pool = cpsw->page_pool[ch]; if (unlikely(status < 0) || unlikely(!netif_running(ndev))) { /* In dual emac mode check for all interfaces */ if (cpsw->data.dual_emac && cpsw->usage_count && @@@ -701,88 -426,47 +701,88 @@@ * is already down and the other interface is up * and running, instead of freeing which results * in reducing of the number of rx descriptor in - * DMA engine, requeue skb back to cpdma. + * DMA engine, requeue page back to cpdma. */ - new_skb = skb; + new_page = page; goto requeue; }
- /* the interface is going down, skbs are purged */ - dev_kfree_skb_any(skb); + /* the interface is going down, pages are purged */ + page_pool_recycle_direct(pool, page); return; }
- new_skb = netdev_alloc_skb_ip_align(ndev, cpsw->rx_packet_max); - if (new_skb) { - skb_copy_queue_mapping(new_skb, skb); - skb_put(skb, len); - if (status & CPDMA_RX_VLAN_ENCAP) - cpsw_rx_vlan_encap(skb); - priv = netdev_priv(ndev); - if (priv->rx_ts_enabled) - cpts_rx_timestamp(cpsw->cpts, skb); - skb->protocol = eth_type_trans(skb, ndev); - netif_receive_skb(skb); - ndev->stats.rx_bytes += len; - ndev->stats.rx_packets++; - kmemleak_not_leak(new_skb); - } else { + new_page = page_pool_dev_alloc_pages(pool); + if (unlikely(!new_page)) { + new_page = page; ndev->stats.rx_dropped++; - new_skb = skb; + goto requeue; }
-requeue: - if (netif_dormant(ndev)) { - dev_kfree_skb_any(new_skb); - return; + if (priv->xdp_prog) { + if (status & CPDMA_RX_VLAN_ENCAP) { + xdp.data = pa + CPSW_HEADROOM + + CPSW_RX_VLAN_ENCAP_HDR_SIZE; + xdp.data_end = xdp.data + len - + CPSW_RX_VLAN_ENCAP_HDR_SIZE; + } else { + xdp.data = pa + CPSW_HEADROOM; + xdp.data_end = xdp.data + len; + } + + xdp_set_data_meta_invalid(&xdp); + + xdp.data_hard_start = pa; + xdp.rxq = &priv->xdp_rxq[ch]; + + ret = cpsw_run_xdp(priv, ch, &xdp, page); + if (ret != CPSW_XDP_PASS) + goto requeue; + + /* XDP prog might have changed packet data and boundaries */ + len = xdp.data_end - xdp.data; + headroom = xdp.data - xdp.data_hard_start; + + /* XDP prog can modify vlan tag, so can't use encap header */ + status &= ~CPDMA_RX_VLAN_ENCAP; }
- ch = cpsw->rxv[skb_get_queue_mapping(new_skb)].ch; - ret = cpdma_chan_submit(ch, new_skb, new_skb->data, - skb_tailroom(new_skb), 0); - if (WARN_ON(ret < 0)) - dev_kfree_skb_any(new_skb); + /* pass skb to netstack if no XDP prog or returned XDP_PASS */ + skb = build_skb(pa, cpsw_rxbuf_total_len(pkt_size)); + if (!skb) { + ndev->stats.rx_dropped++; + page_pool_recycle_direct(pool, page); + goto requeue; + } + + skb_reserve(skb, headroom); + skb_put(skb, len); + skb->dev = ndev; + if (status & CPDMA_RX_VLAN_ENCAP) + cpsw_rx_vlan_encap(skb); + if (priv->rx_ts_enabled) + cpts_rx_timestamp(cpsw->cpts, skb); + skb->protocol = eth_type_trans(skb, ndev); + + /* unmap page as no netstack skb page recycling */ + page_pool_release_page(pool, page); + netif_receive_skb(skb); + + ndev->stats.rx_bytes += len; + ndev->stats.rx_packets++; + +requeue: + xmeta = page_address(new_page) + CPSW_XMETA_OFFSET; + xmeta->ndev = ndev; + xmeta->ch = ch; + + dma = page_pool_get_dma_addr(new_page) + CPSW_HEADROOM; + ret = cpdma_chan_submit_mapped(cpsw->rxv[ch].ch, new_page, dma, + pkt_size, 0); + if (ret < 0) { + WARN_ON(ret == -ENOMEM); + page_pool_recycle_direct(pool, new_page); + } }
void cpsw_split_res(struct cpsw_common *cpsw) @@@ -1351,39 -1035,33 +1351,39 @@@ static void cpsw_init_host_port(struct int cpsw_fill_rx_channels(struct cpsw_priv *priv) { struct cpsw_common *cpsw = priv->cpsw; - struct sk_buff *skb; + struct cpsw_meta_xdp *xmeta; + struct page_pool *pool; + struct page *page; int ch_buf_num; int ch, i, ret; + dma_addr_t dma;
for (ch = 0; ch < cpsw->rx_ch_num; ch++) { + pool = cpsw->page_pool[ch]; ch_buf_num = cpdma_chan_get_rx_buf_num(cpsw->rxv[ch].ch); for (i = 0; i < ch_buf_num; i++) { - skb = __netdev_alloc_skb_ip_align(priv->ndev, - cpsw->rx_packet_max, - GFP_KERNEL); - if (!skb) { - cpsw_err(priv, ifup, "cannot allocate skb\n"); + page = page_pool_dev_alloc_pages(pool); + if (!page) { + cpsw_err(priv, ifup, "allocate rx page err\n"); return -ENOMEM; }
- skb_set_queue_mapping(skb, ch); - ret = cpdma_chan_submit(cpsw->rxv[ch].ch, skb, - skb->data, skb_tailroom(skb), - 0); + xmeta = page_address(page) + CPSW_XMETA_OFFSET; + xmeta->ndev = priv->ndev; + xmeta->ch = ch; + + dma = page_pool_get_dma_addr(page) + CPSW_HEADROOM; + ret = cpdma_chan_idle_submit_mapped(cpsw->rxv[ch].ch, + page, dma, + cpsw->rx_packet_max, + 0); if (ret < 0) { cpsw_err(priv, ifup, - "cannot submit skb to channel %d rx, error %d\n", + "cannot submit page to channel %d rx, error %d\n", ch, ret); - kfree_skb(skb); + page_pool_recycle_direct(pool, page); return ret; } - kmemleak_not_leak(skb); }
cpsw_info(priv, ifup, "ch %d rx, submitted %d descriptors\n", @@@ -1719,13 -1397,6 +1719,13 @@@ static int cpsw_ndo_open(struct net_dev enable_irq(cpsw->irqs_table[0]); }
+ /* create rxqs for both infs in dual mac as they use same pool + * and must be destroyed together when no users. + */ + ret = cpsw_create_xdp_rxqs(cpsw); + if (ret < 0) + goto err_cleanup; + ret = cpsw_fill_rx_channels(priv); if (ret < 0) goto err_cleanup; @@@ -1752,11 -1423,7 +1752,11 @@@ return 0;
err_cleanup: - cpdma_ctlr_stop(cpsw->dma); + if (!cpsw->usage_count) { + cpdma_ctlr_stop(cpsw->dma); + cpsw_destroy_xdp_rxqs(cpsw); + } + for_each_slave(priv, cpsw_slave_stop, cpsw); pm_runtime_put_sync(cpsw->dev); netif_carrier_off(priv->ndev); @@@ -1780,7 -1447,6 +1780,7 @@@ static int cpsw_ndo_stop(struct net_dev cpsw_intr_disable(cpsw); cpdma_ctlr_stop(cpsw->dma); cpsw_ale_stop(cpsw->ale); + cpsw_destroy_xdp_rxqs(cpsw); } for_each_slave(priv, cpsw_slave_stop, cpsw);
@@@ -2338,64 -2004,6 +2338,64 @@@ static int cpsw_ndo_setup_tc(struct net } }
+static int cpsw_xdp_prog_setup(struct cpsw_priv *priv, struct netdev_bpf *bpf) +{ + struct bpf_prog *prog = bpf->prog; + + if (!priv->xdpi.prog && !prog) + return 0; + + if (!xdp_attachment_flags_ok(&priv->xdpi, bpf)) + return -EBUSY; + + WRITE_ONCE(priv->xdp_prog, prog); + + xdp_attachment_setup(&priv->xdpi, bpf); + + return 0; +} + +static int cpsw_ndo_bpf(struct net_device *ndev, struct netdev_bpf *bpf) +{ + struct cpsw_priv *priv = netdev_priv(ndev); + + switch (bpf->command) { + case XDP_SETUP_PROG: + return cpsw_xdp_prog_setup(priv, bpf); + + case XDP_QUERY_PROG: + return xdp_attachment_query(&priv->xdpi, bpf); + + default: + return -EINVAL; + } +} + +static int cpsw_ndo_xdp_xmit(struct net_device *ndev, int n, + struct xdp_frame **frames, u32 flags) +{ + struct cpsw_priv *priv = netdev_priv(ndev); + struct xdp_frame *xdpf; + int i, drops = 0; + + if (unlikely(flags & ~XDP_XMIT_FLAGS_MASK)) + return -EINVAL; + + for (i = 0; i < n; i++) { + xdpf = frames[i]; + if (xdpf->len < CPSW_MIN_PACKET_SIZE) { + xdp_return_frame_rx_napi(xdpf); + drops++; + continue; + } + + if (cpsw_xdp_tx_frame(priv, xdpf, NULL)) + drops++; + } + + return n - drops; +} + #ifdef CONFIG_NET_POLL_CONTROLLER static void cpsw_ndo_poll_controller(struct net_device *ndev) { @@@ -2424,8 -2032,6 +2424,8 @@@ static const struct net_device_ops cpsw .ndo_vlan_rx_add_vid = cpsw_ndo_vlan_rx_add_vid, .ndo_vlan_rx_kill_vid = cpsw_ndo_vlan_rx_kill_vid, .ndo_setup_tc = cpsw_ndo_setup_tc, + .ndo_bpf = cpsw_ndo_bpf, + .ndo_xdp_xmit = cpsw_ndo_xdp_xmit, };
static void cpsw_get_drvinfo(struct net_device *ndev, @@@ -2573,6 -2179,7 +2573,7 @@@ static int cpsw_probe_dt(struct cpsw_pl return ret; }
+ slave_data->slave_node = slave_node; slave_data->phy_node = of_parse_phandle(slave_node, "phy-handle", 0); parp = of_get_property(slave_node, "phy_id", &lenp); @@@ -2656,7 -2263,8 +2657,7 @@@ no_phy_slave
static void cpsw_remove_dt(struct platform_device *pdev) { - struct net_device *ndev = platform_get_drvdata(pdev); - struct cpsw_common *cpsw = ndev_to_cpsw(ndev); + struct cpsw_common *cpsw = platform_get_drvdata(pdev); struct cpsw_platform_data *data = &cpsw->data; struct device_node *node = pdev->dev.of_node; struct device_node *slave_node; @@@ -2723,6 -2331,7 +2724,7 @@@ static int cpsw_probe_dual_emac(struct
/* register the network device */ SET_NETDEV_DEV(ndev, cpsw->dev); + ndev->dev.of_node = cpsw->slaves[1].data->slave_node; ret = register_netdev(ndev); if (ret) dev_err(cpsw->dev, "cpsw: error registering net device\n"); @@@ -2867,7 -2476,7 +2869,7 @@@ static int cpsw_probe(struct platform_d goto clean_cpts; }
- platform_set_drvdata(pdev, ndev); + platform_set_drvdata(pdev, cpsw); priv = netdev_priv(ndev); priv->cpsw = cpsw; priv->ndev = ndev; @@@ -2900,6 -2509,7 +2902,7 @@@
/* register the network device */ SET_NETDEV_DEV(ndev, dev); + ndev->dev.of_node = cpsw->slaves[0].data->slave_node; ret = register_netdev(ndev); if (ret) { dev_err(dev, "error registering net device\n"); @@@ -2960,8 -2570,9 +2963,8 @@@ clean_runtime_disable_ret
static int cpsw_remove(struct platform_device *pdev) { - struct net_device *ndev = platform_get_drvdata(pdev); - struct cpsw_common *cpsw = ndev_to_cpsw(ndev); - int ret; + struct cpsw_common *cpsw = platform_get_drvdata(pdev); + int i, ret;
ret = pm_runtime_get_sync(&pdev->dev); if (ret < 0) { @@@ -2969,9 -2580,9 +2972,9 @@@ return ret; }
- if (cpsw->data.dual_emac) - unregister_netdev(cpsw->slaves[1].ndev); - unregister_netdev(ndev); + for (i = 0; i < cpsw->data.slaves; i++) + if (cpsw->slaves[i].ndev) + unregister_netdev(cpsw->slaves[i].ndev);
cpts_release(cpsw->cpts); cpdma_ctlr_destroy(cpsw->dma); @@@ -2984,13 -2595,20 +2987,13 @@@ #ifdef CONFIG_PM_SLEEP static int cpsw_suspend(struct device *dev) { - struct net_device *ndev = dev_get_drvdata(dev); - struct cpsw_common *cpsw = ndev_to_cpsw(ndev); - - if (cpsw->data.dual_emac) { - int i; + struct cpsw_common *cpsw = dev_get_drvdata(dev); + int i;
- for (i = 0; i < cpsw->data.slaves; i++) { + for (i = 0; i < cpsw->data.slaves; i++) + if (cpsw->slaves[i].ndev) if (netif_running(cpsw->slaves[i].ndev)) cpsw_ndo_stop(cpsw->slaves[i].ndev); - } - } else { - if (netif_running(ndev)) - cpsw_ndo_stop(ndev); - }
/* Select sleep pin state */ pinctrl_pm_select_sleep_state(dev); @@@ -3000,20 -2618,25 +3003,20 @@@
static int cpsw_resume(struct device *dev) { - struct net_device *ndev = dev_get_drvdata(dev); - struct cpsw_common *cpsw = ndev_to_cpsw(ndev); + struct cpsw_common *cpsw = dev_get_drvdata(dev); + int i;
/* Select default pin state */ pinctrl_pm_select_default_state(dev);
/* shut up ASSERT_RTNL() warning in netif_set_real_num_tx/rx_queues */ rtnl_lock(); - if (cpsw->data.dual_emac) { - int i;
- for (i = 0; i < cpsw->data.slaves; i++) { + for (i = 0; i < cpsw->data.slaves; i++) + if (cpsw->slaves[i].ndev) if (netif_running(cpsw->slaves[i].ndev)) cpsw_ndo_open(cpsw->slaves[i].ndev); - } - } else { - if (netif_running(ndev)) - cpsw_ndo_open(ndev); - } + rtnl_unlock();
return 0; diff --combined drivers/net/ethernet/ti/cpsw_priv.h index 086bf38a4736,e32f11da2dce..362c5a986869 --- a/drivers/net/ethernet/ti/cpsw_priv.h +++ b/drivers/net/ethernet/ti/cpsw_priv.h @@@ -272,6 -272,7 +272,7 @@@ struct cpsw_host_regs };
struct cpsw_slave_data { + struct device_node *slave_node; struct device_node *phy_node; char phy_id[MII_BUS_ID_SIZE]; int phy_if; @@@ -346,7 -347,6 +347,7 @@@ struct cpsw_common int rx_ch_num, tx_ch_num; int speed; int usage_count; + struct page_pool *page_pool[CPSW_MAX_QUEUES]; };
struct cpsw_priv { @@@ -361,10 -361,6 +362,10 @@@ int shp_cfg_speed; int tx_ts_enabled; int rx_ts_enabled; + struct bpf_prog *xdp_prog; + struct xdp_rxq_info xdp_rxq[CPSW_MAX_QUEUES]; + struct xdp_attachment_info xdpi; + u32 emac_port; struct cpsw_common *cpsw; }; @@@ -396,8 -392,6 +397,8 @@@ int cpsw_fill_rx_channels(struct cpsw_p void cpsw_intr_enable(struct cpsw_common *cpsw); void cpsw_intr_disable(struct cpsw_common *cpsw); void cpsw_tx_handler(void *token, int len, int status); +int cpsw_create_xdp_rxqs(struct cpsw_common *cpsw); +void cpsw_destroy_xdp_rxqs(struct cpsw_common *cpsw);
/* ethtool */ u32 cpsw_get_msglevel(struct net_device *ndev); diff --combined drivers/net/vxlan.c index 5e2323592e08,b4283f52a09d..3d9bcc957f7d --- a/drivers/net/vxlan.c +++ b/drivers/net/vxlan.c @@@ -468,19 -468,14 +468,19 @@@ static u32 eth_vni_hash(const unsigned return jhash_2words(key, vni, vxlan_salt) & (FDB_HASH_SIZE - 1); }
+static u32 fdb_head_index(struct vxlan_dev *vxlan, const u8 *mac, __be32 vni) +{ + if (vxlan->cfg.flags & VXLAN_F_COLLECT_METADATA) + return eth_vni_hash(mac, vni); + else + return eth_hash(mac); +} + /* Hash chain to use given mac address */ static inline struct hlist_head *vxlan_fdb_head(struct vxlan_dev *vxlan, const u8 *mac, __be32 vni) { - if (vxlan->cfg.flags & VXLAN_F_COLLECT_METADATA) - return &vxlan->fdb_head[eth_vni_hash(mac, vni)]; - else - return &vxlan->fdb_head[eth_hash(mac)]; + return &vxlan->fdb_head[fdb_head_index(vxlan, mac, vni)]; }
/* Look up Ethernet address in forwarding table */ @@@ -595,8 -590,8 +595,8 @@@ int vxlan_fdb_replay(const struct net_d return -EINVAL; vxlan = netdev_priv(dev);
- spin_lock_bh(&vxlan->hash_lock); for (h = 0; h < FDB_HASH_SIZE; ++h) { + spin_lock_bh(&vxlan->hash_lock[h]); hlist_for_each_entry(f, &vxlan->fdb_head[h], hlist) { if (f->vni == vni) { list_for_each_entry(rdst, &f->remotes, list) { @@@ -604,16 -599,14 +604,16 @@@ f, rdst, extack); if (rc) - goto out; + goto unlock; } } } + spin_unlock_bh(&vxlan->hash_lock[h]); } + return 0;
-out: - spin_unlock_bh(&vxlan->hash_lock); +unlock: + spin_unlock_bh(&vxlan->hash_lock[h]); return rc; } EXPORT_SYMBOL_GPL(vxlan_fdb_replay); @@@ -629,15 -622,14 +629,15 @@@ void vxlan_fdb_clear_offload(const stru return; vxlan = netdev_priv(dev);
- spin_lock_bh(&vxlan->hash_lock); for (h = 0; h < FDB_HASH_SIZE; ++h) { + spin_lock_bh(&vxlan->hash_lock[h]); hlist_for_each_entry(f, &vxlan->fdb_head[h], hlist) if (f->vni == vni) list_for_each_entry(rdst, &f->remotes, list) rdst->offloaded = false; + spin_unlock_bh(&vxlan->hash_lock[h]); } - spin_unlock_bh(&vxlan->hash_lock); + } EXPORT_SYMBOL_GPL(vxlan_fdb_clear_offload);
@@@ -812,6 -804,14 +812,14 @@@ static struct vxlan_fdb *vxlan_fdb_allo return f; }
+ static void vxlan_fdb_insert(struct vxlan_dev *vxlan, const u8 *mac, + __be32 src_vni, struct vxlan_fdb *f) + { + ++vxlan->addrcnt; + hlist_add_head_rcu(&f->hlist, + vxlan_fdb_head(vxlan, mac, src_vni)); + } + static int vxlan_fdb_create(struct vxlan_dev *vxlan, const u8 *mac, union vxlan_addr *ip, __u16 state, __be16 port, __be32 src_vni, @@@ -837,18 -837,13 +845,13 @@@ return rc; }
- ++vxlan->addrcnt; - hlist_add_head_rcu(&f->hlist, - vxlan_fdb_head(vxlan, mac, src_vni)); - *fdb = f;
return 0; }
- static void vxlan_fdb_free(struct rcu_head *head) + static void __vxlan_fdb_free(struct vxlan_fdb *f) { - struct vxlan_fdb *f = container_of(head, struct vxlan_fdb, rcu); struct vxlan_rdst *rd, *nd;
list_for_each_entry_safe(rd, nd, &f->remotes, list) { @@@ -858,6 -853,13 +861,13 @@@ kfree(f); }
+ static void vxlan_fdb_free(struct rcu_head *head) + { + struct vxlan_fdb *f = container_of(head, struct vxlan_fdb, rcu); + + __vxlan_fdb_free(f); + } + static void vxlan_fdb_destroy(struct vxlan_dev *vxlan, struct vxlan_fdb *f, bool do_notify, bool swdev_notify) { @@@ -985,6 -987,7 +995,7 @@@ static int vxlan_fdb_update_create(stru if (rc < 0) return rc;
+ vxlan_fdb_insert(vxlan, mac, src_vni, f); rc = vxlan_fdb_notify(vxlan, f, first_remote_rtnl(f), RTM_NEWNEIGH, swdev_notify, extack); if (rc) @@@ -1113,7 -1116,6 +1124,7 @@@ static int vxlan_fdb_add(struct ndmsg * __be16 port; __be32 src_vni, vni; u32 ifindex; + u32 hash_index; int err;
if (!(ndm->ndm_state & (NUD_PERMANENT|NUD_REACHABLE))) { @@@ -1132,13 -1134,12 +1143,13 @@@ if (vxlan->default_dst.remote_ip.sa.sa_family != ip.sa.sa_family) return -EAFNOSUPPORT;
- spin_lock_bh(&vxlan->hash_lock); + hash_index = fdb_head_index(vxlan, addr, src_vni); + spin_lock_bh(&vxlan->hash_lock[hash_index]); err = vxlan_fdb_update(vxlan, addr, &ip, ndm->ndm_state, flags, port, src_vni, vni, ifindex, ndm->ndm_flags | NTF_VXLAN_ADDED_BY_USER, true, extack); - spin_unlock_bh(&vxlan->hash_lock); + spin_unlock_bh(&vxlan->hash_lock[hash_index]);
return err; } @@@ -1186,18 -1187,16 +1197,18 @@@ static int vxlan_fdb_delete(struct ndms __be32 src_vni, vni; __be16 port; u32 ifindex; + u32 hash_index; int err;
err = vxlan_fdb_parse(tb, vxlan, &ip, &port, &src_vni, &vni, &ifindex); if (err) return err;
- spin_lock_bh(&vxlan->hash_lock); + hash_index = fdb_head_index(vxlan, addr, src_vni); + spin_lock_bh(&vxlan->hash_lock[hash_index]); err = __vxlan_fdb_delete(vxlan, addr, ip, port, src_vni, vni, ifindex, true); - spin_unlock_bh(&vxlan->hash_lock); + spin_unlock_bh(&vxlan->hash_lock[hash_index]);
return err; } @@@ -1309,10 -1308,8 +1320,10 @@@ static bool vxlan_snoop(struct net_devi f->updated = jiffies; vxlan_fdb_notify(vxlan, f, rdst, RTM_NEWNEIGH, true, NULL); } else { + u32 hash_index = fdb_head_index(vxlan, src_mac, vni); + /* learned new entry */ - spin_lock(&vxlan->hash_lock); + spin_lock(&vxlan->hash_lock[hash_index]);
/* close off race between vxlan_flush and incoming packets */ if (netif_running(dev)) @@@ -1323,7 -1320,7 +1334,7 @@@ vni, vxlan->default_dst.remote_vni, ifindex, NTF_SELF, true, NULL); - spin_unlock(&vxlan->hash_lock); + spin_unlock(&vxlan->hash_lock[hash_index]); }
return false; @@@ -2233,7 -2230,7 +2244,7 @@@ static struct rtable *vxlan_get_route(s fl4.fl4_sport = sport;
rt = ip_route_output_key(vxlan->net, &fl4); - if (likely(!IS_ERR(rt))) { + if (!IS_ERR(rt)) { if (rt->dst.dev == dev) { netdev_dbg(dev, "circular route to %pI4\n", &daddr); ip_rt_put(rt); @@@ -2713,7 -2710,7 +2724,7 @@@ static void vxlan_cleanup(struct timer_ for (h = 0; h < FDB_HASH_SIZE; ++h) { struct hlist_node *p, *n;
- spin_lock(&vxlan->hash_lock); + spin_lock(&vxlan->hash_lock[h]); hlist_for_each_safe(p, n, &vxlan->fdb_head[h]) { struct vxlan_fdb *f = container_of(p, struct vxlan_fdb, hlist); @@@ -2735,7 -2732,7 +2746,7 @@@ } else if (time_before(timeout, next_timer)) next_timer = timeout; } - spin_unlock(&vxlan->hash_lock); + spin_unlock(&vxlan->hash_lock[h]); }
mod_timer(&vxlan->age_timer, next_timer); @@@ -2778,13 -2775,12 +2789,13 @@@ static int vxlan_init(struct net_devic static void vxlan_fdb_delete_default(struct vxlan_dev *vxlan, __be32 vni) { struct vxlan_fdb *f; + u32 hash_index = fdb_head_index(vxlan, all_zeros_mac, vni);
- spin_lock_bh(&vxlan->hash_lock); + spin_lock_bh(&vxlan->hash_lock[hash_index]); f = __vxlan_find_mac(vxlan, all_zeros_mac, vni); if (f) vxlan_fdb_destroy(vxlan, f, true, true); - spin_unlock_bh(&vxlan->hash_lock); + spin_unlock_bh(&vxlan->hash_lock[hash_index]); }
static void vxlan_uninit(struct net_device *dev) @@@ -2829,10 -2825,9 +2840,10 @@@ static void vxlan_flush(struct vxlan_de { unsigned int h;
- spin_lock_bh(&vxlan->hash_lock); for (h = 0; h < FDB_HASH_SIZE; ++h) { struct hlist_node *p, *n; + + spin_lock_bh(&vxlan->hash_lock[h]); hlist_for_each_safe(p, n, &vxlan->fdb_head[h]) { struct vxlan_fdb *f = container_of(p, struct vxlan_fdb, hlist); @@@ -2842,8 -2837,8 +2853,8 @@@ if (!is_zero_ether_addr(f->eth_addr)) vxlan_fdb_destroy(vxlan, f, true, true); } + spin_unlock_bh(&vxlan->hash_lock[h]); } - spin_unlock_bh(&vxlan->hash_lock); }
/* Cleanup timer and forwarding table on shutdown */ @@@ -3027,6 -3022,7 +3038,6 @@@ static void vxlan_setup(struct net_devi dev->max_mtu = ETH_MAX_MTU;
INIT_LIST_HEAD(&vxlan->next); - spin_lock_init(&vxlan->hash_lock);
timer_setup(&vxlan->age_timer, vxlan_cleanup, TIMER_DEFERRABLE);
@@@ -3034,10 -3030,8 +3045,10 @@@
gro_cells_init(&vxlan->gro_cells, dev);
- for (h = 0; h < FDB_HASH_SIZE; ++h) + for (h = 0; h < FDB_HASH_SIZE; ++h) { + spin_lock_init(&vxlan->hash_lock[h]); INIT_HLIST_HEAD(&vxlan->fdb_head[h]); + } }
static void vxlan_ether_setup(struct net_device *dev) @@@ -3588,12 -3582,17 +3599,17 @@@ static int __vxlan_dev_create(struct ne if (err) goto errout;
- /* notify default fdb entry */ if (f) { + vxlan_fdb_insert(vxlan, all_zeros_mac, + vxlan->default_dst.remote_vni, f); + + /* notify default fdb entry */ err = vxlan_fdb_notify(vxlan, f, first_remote_rtnl(f), RTM_NEWNEIGH, true, extack); - if (err) - goto errout; + if (err) { + vxlan_fdb_destroy(vxlan, f, false, false); + goto unregister; + } }
list_add(&vxlan->next, &vn->vxlan_list); @@@ -3605,7 -3604,8 +3621,8 @@@ errout * destroy the entry by hand here. */ if (f) - vxlan_fdb_destroy(vxlan, f, false, false); + __vxlan_fdb_free(f); + unregister: if (unregister) unregister_netdevice(dev); return err; @@@ -3931,9 -3931,7 +3948,9 @@@ static int vxlan_changelink(struct net_
/* handle default dst entry */ if (!vxlan_addr_equal(&conf.remote_ip, &dst->remote_ip)) { - spin_lock_bh(&vxlan->hash_lock); + u32 hash_index = fdb_head_index(vxlan, all_zeros_mac, conf.vni); + + spin_lock_bh(&vxlan->hash_lock[hash_index]); if (!vxlan_addr_any(&conf.remote_ip)) { err = vxlan_fdb_update(vxlan, all_zeros_mac, &conf.remote_ip, @@@ -3944,7 -3942,7 +3961,7 @@@ conf.remote_ifindex, NTF_SELF, true, extack); if (err) { - spin_unlock_bh(&vxlan->hash_lock); + spin_unlock_bh(&vxlan->hash_lock[hash_index]); return err; } } @@@ -3956,7 -3954,7 +3973,7 @@@ dst->remote_vni, dst->remote_ifindex, true); - spin_unlock_bh(&vxlan->hash_lock); + spin_unlock_bh(&vxlan->hash_lock[hash_index]); }
if (conf.age_interval != vxlan->cfg.age_interval) @@@ -4211,11 -4209,8 +4228,11 @@@ vxlan_fdb_offloaded_set(struct net_devi struct vxlan_dev *vxlan = netdev_priv(dev); struct vxlan_rdst *rdst; struct vxlan_fdb *f; + u32 hash_index; + + hash_index = fdb_head_index(vxlan, fdb_info->eth_addr, fdb_info->vni);
- spin_lock_bh(&vxlan->hash_lock); + spin_lock_bh(&vxlan->hash_lock[hash_index]);
f = vxlan_find_mac(vxlan, fdb_info->eth_addr, fdb_info->vni); if (!f) @@@ -4231,7 -4226,7 +4248,7 @@@ rdst->offloaded = fdb_info->offloaded;
out: - spin_unlock_bh(&vxlan->hash_lock); + spin_unlock_bh(&vxlan->hash_lock[hash_index]); }
static int @@@ -4240,13 -4235,11 +4257,13 @@@ vxlan_fdb_external_learn_add(struct net { struct vxlan_dev *vxlan = netdev_priv(dev); struct netlink_ext_ack *extack; + u32 hash_index; int err;
+ hash_index = fdb_head_index(vxlan, fdb_info->eth_addr, fdb_info->vni); extack = switchdev_notifier_info_to_extack(&fdb_info->info);
- spin_lock_bh(&vxlan->hash_lock); + spin_lock_bh(&vxlan->hash_lock[hash_index]); err = vxlan_fdb_update(vxlan, fdb_info->eth_addr, &fdb_info->remote_ip, NUD_REACHABLE, NLM_F_CREATE | NLM_F_REPLACE, @@@ -4256,7 -4249,7 +4273,7 @@@ fdb_info->remote_ifindex, NTF_USE | NTF_SELF | NTF_EXT_LEARNED, false, extack); - spin_unlock_bh(&vxlan->hash_lock); + spin_unlock_bh(&vxlan->hash_lock[hash_index]);
return err; } @@@ -4267,11 -4260,9 +4284,11 @@@ vxlan_fdb_external_learn_del(struct net { struct vxlan_dev *vxlan = netdev_priv(dev); struct vxlan_fdb *f; + u32 hash_index; int err = 0;
- spin_lock_bh(&vxlan->hash_lock); + hash_index = fdb_head_index(vxlan, fdb_info->eth_addr, fdb_info->vni); + spin_lock_bh(&vxlan->hash_lock[hash_index]);
f = vxlan_find_mac(vxlan, fdb_info->eth_addr, fdb_info->vni); if (!f) @@@ -4285,7 -4276,7 +4302,7 @@@ fdb_info->remote_ifindex, false);
- spin_unlock_bh(&vxlan->hash_lock); + spin_unlock_bh(&vxlan->hash_lock[hash_index]);
return err; } diff --combined drivers/net/wireless/intel/iwlwifi/pcie/trans.c index 602c31b3992a,38ab24d96244..f5df5b370d78 --- a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c @@@ -90,10 -90,8 +90,10 @@@
void iwl_trans_pcie_dump_regs(struct iwl_trans *trans) { -#define PCI_DUMP_SIZE 64 -#define PREFIX_LEN 32 +#define PCI_DUMP_SIZE 352 +#define PCI_MEM_DUMP_SIZE 64 +#define PCI_PARENT_DUMP_SIZE 524 +#define PREFIX_LEN 32 struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); struct pci_dev *pdev = trans_pcie->pci_dev; u32 i, pos, alloc_size, *ptr, *buf; @@@ -104,15 -102,11 +104,15 @@@
/* Should be a multiple of 4 */ BUILD_BUG_ON(PCI_DUMP_SIZE > 4096 || PCI_DUMP_SIZE & 0x3); + BUILD_BUG_ON(PCI_MEM_DUMP_SIZE > 4096 || PCI_MEM_DUMP_SIZE & 0x3); + BUILD_BUG_ON(PCI_PARENT_DUMP_SIZE > 4096 || PCI_PARENT_DUMP_SIZE & 0x3); + /* Alloc a max size buffer */ - if (PCI_ERR_ROOT_ERR_SRC + 4 > PCI_DUMP_SIZE) - alloc_size = PCI_ERR_ROOT_ERR_SRC + 4 + PREFIX_LEN; - else - alloc_size = PCI_DUMP_SIZE + PREFIX_LEN; + alloc_size = PCI_ERR_ROOT_ERR_SRC + 4 + PREFIX_LEN; + alloc_size = max_t(u32, alloc_size, PCI_DUMP_SIZE + PREFIX_LEN); + alloc_size = max_t(u32, alloc_size, PCI_MEM_DUMP_SIZE + PREFIX_LEN); + alloc_size = max_t(u32, alloc_size, PCI_PARENT_DUMP_SIZE + PREFIX_LEN); + buf = kmalloc(alloc_size, GFP_ATOMIC); if (!buf) return; @@@ -129,7 -123,7 +129,7 @@@ print_hex_dump(KERN_ERR, prefix, DUMP_PREFIX_OFFSET, 32, 4, buf, i, 0);
IWL_ERR(trans, "iwlwifi device memory mapped registers:\n"); - for (i = 0, ptr = buf; i < PCI_DUMP_SIZE; i += 4, ptr++) + for (i = 0, ptr = buf; i < PCI_MEM_DUMP_SIZE; i += 4, ptr++) *ptr = iwl_read32(trans, i); print_hex_dump(KERN_ERR, prefix, DUMP_PREFIX_OFFSET, 32, 4, buf, i, 0);
@@@ -152,7 -146,7 +152,7 @@@
IWL_ERR(trans, "iwlwifi parent port (%s) config registers:\n", pci_name(pdev)); - for (i = 0, ptr = buf; i < PCI_DUMP_SIZE; i += 4, ptr++) + for (i = 0, ptr = buf; i < PCI_PARENT_DUMP_SIZE; i += 4, ptr++) if (pci_read_config_dword(pdev, i, ptr)) goto err_read; print_hex_dump(KERN_ERR, prefix, DUMP_PREFIX_OFFSET, 32, 4, buf, i, 0); @@@ -194,14 -188,14 +194,14 @@@ static void iwl_pcie_free_fw_monitor(st { int i;
- for (i = 0; i < trans->num_blocks; i++) { - dma_free_coherent(trans->dev, trans->fw_mon[i].size, - trans->fw_mon[i].block, - trans->fw_mon[i].physical); - trans->fw_mon[i].block = NULL; - trans->fw_mon[i].physical = 0; - trans->fw_mon[i].size = 0; - trans->num_blocks--; + for (i = 0; i < trans->dbg.num_blocks; i++) { + dma_free_coherent(trans->dev, trans->dbg.fw_mon[i].size, + trans->dbg.fw_mon[i].block, + trans->dbg.fw_mon[i].physical); + trans->dbg.fw_mon[i].block = NULL; + trans->dbg.fw_mon[i].physical = 0; + trans->dbg.fw_mon[i].size = 0; + trans->dbg.num_blocks--; } }
@@@ -236,10 -230,10 +236,10 @@@ static void iwl_pcie_alloc_fw_monitor_b (unsigned long)BIT(power - 10), (unsigned long)BIT(max_power - 10));
- trans->fw_mon[trans->num_blocks].block = cpu_addr; - trans->fw_mon[trans->num_blocks].physical = phys; - trans->fw_mon[trans->num_blocks].size = size; - trans->num_blocks++; + trans->dbg.fw_mon[trans->dbg.num_blocks].block = cpu_addr; + trans->dbg.fw_mon[trans->dbg.num_blocks].physical = phys; + trans->dbg.fw_mon[trans->dbg.num_blocks].size = size; + trans->dbg.num_blocks++; }
void iwl_pcie_alloc_fw_monitor(struct iwl_trans *trans, u8 max_power) @@@ -260,7 -254,7 +260,7 @@@ * This function allocats the default fw monitor. * The optional additional ones will be allocated in runtime */ - if (trans->num_blocks) + if (trans->dbg.num_blocks) return;
iwl_pcie_alloc_fw_monitor_block(trans, max_power, 11); @@@ -895,21 -889,21 +895,21 @@@ static int iwl_pcie_load_cpu_sections(s
void iwl_pcie_apply_destination(struct iwl_trans *trans) { - const struct iwl_fw_dbg_dest_tlv_v1 *dest = trans->dbg_dest_tlv; + const struct iwl_fw_dbg_dest_tlv_v1 *dest = trans->dbg.dest_tlv; int i;
- if (trans->ini_valid) { - if (!trans->num_blocks) + if (trans->dbg.ini_valid) { + if (!trans->dbg.num_blocks) return;
IWL_DEBUG_FW(trans, "WRT: applying DRAM buffer[0] destination\n"); iwl_write_umac_prph(trans, MON_BUFF_BASE_ADDR_VER2, - trans->fw_mon[0].physical >> + trans->dbg.fw_mon[0].physical >> MON_BUFF_SHIFT_VER2); iwl_write_umac_prph(trans, MON_BUFF_END_ADDR_VER2, - (trans->fw_mon[0].physical + - trans->fw_mon[0].size - 256) >> + (trans->dbg.fw_mon[0].physical + + trans->dbg.fw_mon[0].size - 256) >> MON_BUFF_SHIFT_VER2); return; } @@@ -922,7 -916,7 +922,7 @@@ else IWL_WARN(trans, "PCI should have external buffer debug\n");
- for (i = 0; i < trans->dbg_n_dest_reg; i++) { + for (i = 0; i < trans->dbg.n_dest_reg; i++) { u32 addr = le32_to_cpu(dest->reg_ops[i].addr); u32 val = le32_to_cpu(dest->reg_ops[i].val);
@@@ -961,19 -955,18 +961,19 @@@ }
monitor: - if (dest->monitor_mode == EXTERNAL_MODE && trans->fw_mon[0].size) { + if (dest->monitor_mode == EXTERNAL_MODE && trans->dbg.fw_mon[0].size) { iwl_write_prph(trans, le32_to_cpu(dest->base_reg), - trans->fw_mon[0].physical >> dest->base_shift); + trans->dbg.fw_mon[0].physical >> + dest->base_shift); if (trans->cfg->device_family >= IWL_DEVICE_FAMILY_8000) iwl_write_prph(trans, le32_to_cpu(dest->end_reg), - (trans->fw_mon[0].physical + - trans->fw_mon[0].size - 256) >> + (trans->dbg.fw_mon[0].physical + + trans->dbg.fw_mon[0].size - 256) >> dest->end_shift); else iwl_write_prph(trans, le32_to_cpu(dest->end_reg), - (trans->fw_mon[0].physical + - trans->fw_mon[0].size) >> + (trans->dbg.fw_mon[0].physical + + trans->dbg.fw_mon[0].size) >> dest->end_shift); } } @@@ -1010,12 -1003,12 +1010,12 @@@ static int iwl_pcie_load_given_ucode(st trans->cfg->device_family == IWL_DEVICE_FAMILY_7000) { iwl_pcie_alloc_fw_monitor(trans, 0);
- if (trans->fw_mon[0].size) { + if (trans->dbg.fw_mon[0].size) { iwl_write_prph(trans, MON_BUFF_BASE_ADDR, - trans->fw_mon[0].physical >> 4); + trans->dbg.fw_mon[0].physical >> 4); iwl_write_prph(trans, MON_BUFF_END_ADDR, - (trans->fw_mon[0].physical + - trans->fw_mon[0].size) >> 4); + (trans->dbg.fw_mon[0].physical + + trans->dbg.fw_mon[0].size) >> 4); } } else if (iwl_pcie_dbg_on(trans)) { iwl_pcie_apply_destination(trans); @@@ -1243,7 -1236,7 +1243,7 @@@ static void _iwl_trans_pcie_stop_device trans_pcie->is_down = true;
/* Stop dbgc before stopping device */ - _iwl_fw_dbg_stop_recording(trans, NULL); + iwl_fw_dbg_stop_recording(trans, NULL);
/* tell the device to stop sending interrupts */ iwl_disable_interrupts(trans); @@@ -2736,8 -2729,8 +2736,8 @@@ static int iwl_dbgfs_monitor_data_open( struct iwl_trans *trans = inode->i_private; struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
- if (!trans->dbg_dest_tlv || - trans->dbg_dest_tlv->monitor_mode != EXTERNAL_MODE) { + if (!trans->dbg.dest_tlv || + trans->dbg.dest_tlv->monitor_mode != EXTERNAL_MODE) { IWL_ERR(trans, "Debug destination is not set to DRAM\n"); return -ENOENT; } @@@ -2784,22 -2777,22 +2784,22 @@@ static ssize_t iwl_dbgfs_monitor_data_r { struct iwl_trans *trans = file->private_data; struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - void *cpu_addr = (void *)trans->fw_mon[0].block, *curr_buf; + void *cpu_addr = (void *)trans->dbg.fw_mon[0].block, *curr_buf; struct cont_rec *data = &trans_pcie->fw_mon_data; u32 write_ptr_addr, wrap_cnt_addr, write_ptr, wrap_cnt; ssize_t size, bytes_copied = 0; bool b_full;
- if (trans->dbg_dest_tlv) { + if (trans->dbg.dest_tlv) { write_ptr_addr = - le32_to_cpu(trans->dbg_dest_tlv->write_ptr_reg); - wrap_cnt_addr = le32_to_cpu(trans->dbg_dest_tlv->wrap_count); + le32_to_cpu(trans->dbg.dest_tlv->write_ptr_reg); + wrap_cnt_addr = le32_to_cpu(trans->dbg.dest_tlv->wrap_count); } else { write_ptr_addr = MON_BUFF_WRPTR; wrap_cnt_addr = MON_BUFF_CYCLE_CNT; }
- if (unlikely(!trans->dbg_rec_on)) + if (unlikely(!trans->dbg.rec_on)) return 0;
mutex_lock(&data->mutex); @@@ -2823,7 -2816,7 +2823,7 @@@
} else if (data->prev_wrap_cnt == wrap_cnt - 1 && write_ptr < data->prev_wr_ptr) { - size = trans->fw_mon[0].size - data->prev_wr_ptr; + size = trans->dbg.fw_mon[0].size - data->prev_wr_ptr; curr_buf = cpu_addr + data->prev_wr_ptr; b_full = iwl_write_to_user_buf(user_buf, count, curr_buf, &size, @@@ -3042,10 -3035,14 +3042,10 @@@ iwl_trans_pcie_dump_pointers(struct iwl base_high = DBGC_CUR_DBGBUF_BASE_ADDR_MSB; write_ptr = DBGC_CUR_DBGBUF_STATUS; wrap_cnt = DBGC_DBGBUF_WRAP_AROUND; - } else if (trans->ini_valid) { - base = iwl_umac_prph(trans, MON_BUFF_BASE_ADDR_VER2); - write_ptr = iwl_umac_prph(trans, MON_BUFF_WRPTR_VER2); - wrap_cnt = iwl_umac_prph(trans, MON_BUFF_CYCLE_CNT_VER2); - } else if (trans->dbg_dest_tlv) { - write_ptr = le32_to_cpu(trans->dbg_dest_tlv->write_ptr_reg); - wrap_cnt = le32_to_cpu(trans->dbg_dest_tlv->wrap_count); - base = le32_to_cpu(trans->dbg_dest_tlv->base_reg); + } else if (trans->dbg.dest_tlv) { + write_ptr = le32_to_cpu(trans->dbg.dest_tlv->write_ptr_reg); + wrap_cnt = le32_to_cpu(trans->dbg.dest_tlv->wrap_count); + base = le32_to_cpu(trans->dbg.dest_tlv->base_reg); } else { base = MON_BUFF_BASE_ADDR; write_ptr = MON_BUFF_WRPTR; @@@ -3072,10 -3069,11 +3072,10 @@@ iwl_trans_pcie_dump_monitor(struct iwl_ { u32 len = 0;
- if ((trans->num_blocks && + if (trans->dbg.dest_tlv || + (trans->dbg.num_blocks && (trans->cfg->device_family == IWL_DEVICE_FAMILY_7000 || - trans->cfg->device_family >= IWL_DEVICE_FAMILY_AX210 || - trans->ini_valid)) || - (trans->dbg_dest_tlv && !trans->ini_valid)) { + trans->cfg->device_family >= IWL_DEVICE_FAMILY_AX210))) { struct iwl_fw_error_dump_fw_mon *fw_mon_data;
(*data)->type = cpu_to_le32(IWL_FW_ERROR_DUMP_FW_MONITOR); @@@ -3084,32 -3082,32 +3084,32 @@@ iwl_trans_pcie_dump_pointers(trans, fw_mon_data);
len += sizeof(**data) + sizeof(*fw_mon_data); - if (trans->num_blocks) { + if (trans->dbg.num_blocks) { memcpy(fw_mon_data->data, - trans->fw_mon[0].block, - trans->fw_mon[0].size); + trans->dbg.fw_mon[0].block, + trans->dbg.fw_mon[0].size);
- monitor_len = trans->fw_mon[0].size; - } else if (trans->dbg_dest_tlv->monitor_mode == SMEM_MODE) { + monitor_len = trans->dbg.fw_mon[0].size; + } else if (trans->dbg.dest_tlv->monitor_mode == SMEM_MODE) { u32 base = le32_to_cpu(fw_mon_data->fw_mon_base_ptr); /* * Update pointers to reflect actual values after * shifting */ - if (trans->dbg_dest_tlv->version) { + if (trans->dbg.dest_tlv->version) { base = (iwl_read_prph(trans, base) & IWL_LDBG_M2S_BUF_BA_MSK) << - trans->dbg_dest_tlv->base_shift; + trans->dbg.dest_tlv->base_shift; base *= IWL_M2S_UNIT_SIZE; base += trans->cfg->smem_offset; } else { base = iwl_read_prph(trans, base) << - trans->dbg_dest_tlv->base_shift; + trans->dbg.dest_tlv->base_shift; }
iwl_trans_read_mem(trans, base, fw_mon_data->data, monitor_len / sizeof(u32)); - } else if (trans->dbg_dest_tlv->monitor_mode == MARBH_MODE) { + } else if (trans->dbg.dest_tlv->monitor_mode == MARBH_MODE) { monitor_len = iwl_trans_pci_dump_marbh_monitor(trans, fw_mon_data, @@@ -3128,40 -3126,40 +3128,40 @@@
static int iwl_trans_get_fw_monitor_len(struct iwl_trans *trans, u32 *len) { - if (trans->num_blocks) { + if (trans->dbg.num_blocks) { *len += sizeof(struct iwl_fw_error_dump_data) + sizeof(struct iwl_fw_error_dump_fw_mon) + - trans->fw_mon[0].size; - return trans->fw_mon[0].size; - } else if (trans->dbg_dest_tlv) { + trans->dbg.fw_mon[0].size; + return trans->dbg.fw_mon[0].size; + } else if (trans->dbg.dest_tlv) { u32 base, end, cfg_reg, monitor_len;
- if (trans->dbg_dest_tlv->version == 1) { - cfg_reg = le32_to_cpu(trans->dbg_dest_tlv->base_reg); + if (trans->dbg.dest_tlv->version == 1) { + cfg_reg = le32_to_cpu(trans->dbg.dest_tlv->base_reg); cfg_reg = iwl_read_prph(trans, cfg_reg); base = (cfg_reg & IWL_LDBG_M2S_BUF_BA_MSK) << - trans->dbg_dest_tlv->base_shift; + trans->dbg.dest_tlv->base_shift; base *= IWL_M2S_UNIT_SIZE; base += trans->cfg->smem_offset;
monitor_len = (cfg_reg & IWL_LDBG_M2S_BUF_SIZE_MSK) >> - trans->dbg_dest_tlv->end_shift; + trans->dbg.dest_tlv->end_shift; monitor_len *= IWL_M2S_UNIT_SIZE; } else { - base = le32_to_cpu(trans->dbg_dest_tlv->base_reg); - end = le32_to_cpu(trans->dbg_dest_tlv->end_reg); + base = le32_to_cpu(trans->dbg.dest_tlv->base_reg); + end = le32_to_cpu(trans->dbg.dest_tlv->end_reg);
base = iwl_read_prph(trans, base) << - trans->dbg_dest_tlv->base_shift; + trans->dbg.dest_tlv->base_shift; end = iwl_read_prph(trans, end) << - trans->dbg_dest_tlv->end_shift; + trans->dbg.dest_tlv->end_shift;
/* Make "end" point to the actual end */ if (trans->cfg->device_family >= IWL_DEVICE_FAMILY_8000 || - trans->dbg_dest_tlv->monitor_mode == MARBH_MODE) - end += (1 << trans->dbg_dest_tlv->end_shift); + trans->dbg.dest_tlv->monitor_mode == MARBH_MODE) + end += (1 << trans->dbg.dest_tlv->end_shift); monitor_len = end - base; } *len += sizeof(struct iwl_fw_error_dump_data) + @@@ -3194,7 -3192,7 +3194,7 @@@ static struct iwl_trans_dump_dat len = sizeof(*dump_data);
/* host commands */ - if (dump_mask & BIT(IWL_FW_ERROR_DUMP_TXCMD)) + if (dump_mask & BIT(IWL_FW_ERROR_DUMP_TXCMD) && cmdq) len += sizeof(*data) + cmdq->n_window * (sizeof(*txcmd) + TFD_MAX_PAYLOAD_SIZE); @@@ -3246,7 -3244,7 +3246,7 @@@ len = 0; data = (void *)dump_data->data;
- if (dump_mask & BIT(IWL_FW_ERROR_DUMP_TXCMD)) { + if (dump_mask & BIT(IWL_FW_ERROR_DUMP_TXCMD) && cmdq) { u16 tfd_size = trans_pcie->tfd_size;
data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_TXCMD); @@@ -3571,15 -3569,17 +3571,17 @@@ struct iwl_trans *iwl_trans_pcie_alloc( trans->cfg = &iwlax210_2ax_cfg_so_jf_a0; } else if (CSR_HW_RF_ID_TYPE_CHIP_ID(trans->hw_rf_id) == CSR_HW_RF_ID_TYPE_CHIP_ID(CSR_HW_RF_ID_TYPE_GF)) { - trans->cfg = &iwlax210_2ax_cfg_so_gf_a0; + trans->cfg = &iwlax211_2ax_cfg_so_gf_a0; } else if (CSR_HW_RF_ID_TYPE_CHIP_ID(trans->hw_rf_id) == CSR_HW_RF_ID_TYPE_CHIP_ID(CSR_HW_RF_ID_TYPE_GF4)) { - trans->cfg = &iwlax210_2ax_cfg_so_gf4_a0; + trans->cfg = &iwlax411_2ax_cfg_so_gf4_a0; } } else if (cfg == &iwl_ax101_cfg_qu_hr) { - if (CSR_HW_RF_ID_TYPE_CHIP_ID(trans->hw_rf_id) == - CSR_HW_RF_ID_TYPE_CHIP_ID(CSR_HW_RF_ID_TYPE_HR) && - trans->hw_rev == CSR_HW_REV_TYPE_QNJ_B0) { + if ((CSR_HW_RF_ID_TYPE_CHIP_ID(trans->hw_rf_id) == + CSR_HW_RF_ID_TYPE_CHIP_ID(CSR_HW_RF_ID_TYPE_HR) && + trans->hw_rev == CSR_HW_REV_TYPE_QNJ_B0) || + (CSR_HW_RF_ID_TYPE_CHIP_ID(trans->hw_rf_id) == + CSR_HW_RF_ID_TYPE_CHIP_ID(CSR_HW_RF_ID_TYPE_HR1))) { trans->cfg = &iwl22000_2ax_cfg_qnj_hr_b0; } else if (CSR_HW_RF_ID_TYPE_CHIP_ID(trans->hw_rf_id) == CSR_HW_RF_ID_TYPE_CHIP_ID(CSR_HW_RF_ID_TYPE_HR)) { @@@ -3601,8 -3601,9 +3603,9 @@@ } else if (CSR_HW_RF_ID_TYPE_CHIP_ID(trans->hw_rf_id) == CSR_HW_RF_ID_TYPE_CHIP_ID(CSR_HW_RF_ID_TYPE_HR) && ((trans->cfg != &iwl_ax200_cfg_cc && - trans->cfg != &killer1650x_2ax_cfg && - trans->cfg != &killer1650w_2ax_cfg) || + trans->cfg != &killer1650x_2ax_cfg && + trans->cfg != &killer1650w_2ax_cfg && + trans->cfg != &iwl_ax201_cfg_quz_hr) || trans->hw_rev == CSR_HW_REV_TYPE_QNJ_B0)) { u32 hw_status;
@@@ -3683,7 -3684,6 +3686,7 @@@ void iwl_trans_pcie_sync_nmi(struct iwl { struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); unsigned long timeout = jiffies + IWL_TRANS_NMI_TIMEOUT; + bool interrupts_enabled = test_bit(STATUS_INT_ENABLED, &trans->status); u32 inta_addr, sw_err_bit;
if (trans_pcie->msix_enabled) { @@@ -3694,12 -3694,7 +3697,12 @@@ sw_err_bit = CSR_INT_BIT_SW_ERR; }
- iwl_disable_interrupts(trans); + /* if the interrupts were already disabled, there is no point in + * calling iwl_disable_interrupts + */ + if (interrupts_enabled) + iwl_disable_interrupts(trans); + iwl_force_nmi(trans); while (time_after(timeout, jiffies)) { u32 inta_hw = iwl_read32(trans, inta_addr); @@@ -3713,13 -3708,6 +3716,13 @@@
mdelay(1); } - iwl_enable_interrupts(trans); + + /* enable interrupts only if there were already enabled before this + * function to avoid a case were the driver enable interrupts before + * proper configurations were made + */ + if (interrupts_enabled) + iwl_enable_interrupts(trans); + iwl_trans_fw_error(trans); } diff --combined drivers/net/wireless/marvell/mwifiex/scan.c index d870d4b2e03d,e2786ab612ca..0d6d41727037 --- a/drivers/net/wireless/marvell/mwifiex/scan.c +++ b/drivers/net/wireless/marvell/mwifiex/scan.c @@@ -1361,21 -1361,25 +1361,25 @@@ int mwifiex_update_bss_desc_with_ie(str break;
case WLAN_EID_VENDOR_SPECIFIC: - if (element_len + 2 < sizeof(vendor_ie->vend_hdr)) - return -EINVAL; - vendor_ie = (struct ieee_types_vendor_specific *) current_ptr;
- if (!memcmp - (vendor_ie->vend_hdr.oui, wpa_oui, - sizeof(wpa_oui))) { + /* 802.11 requires at least 3-byte OUI. */ + if (element_len < sizeof(vendor_ie->vend_hdr.oui.oui)) + return -EINVAL; + + /* Not long enough for a match? Skip it. */ + if (element_len < sizeof(wpa_oui)) + break; + + if (!memcmp(&vendor_ie->vend_hdr.oui, wpa_oui, + sizeof(wpa_oui))) { bss_entry->bcn_wpa_ie = (struct ieee_types_vendor_specific *) current_ptr; bss_entry->wpa_offset = (u16) (current_ptr - bss_entry->beacon_buf); - } else if (!memcmp(vendor_ie->vend_hdr.oui, wmm_oui, + } else if (!memcmp(&vendor_ie->vend_hdr.oui, wmm_oui, sizeof(wmm_oui))) { if (total_ie_len == sizeof(struct ieee_types_wmm_parameter) || @@@ -1500,6 -1504,7 +1504,6 @@@ int mwifiex_scan_networks(struct mwifie u8 filtered_scan; u8 scan_current_chan_only; u8 max_chan_per_scan; - unsigned long flags;
if (adapter->scan_processing) { mwifiex_dbg(adapter, WARN, @@@ -1520,9 -1525,9 +1524,9 @@@ return -EFAULT; }
- spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags); + spin_lock_bh(&adapter->mwifiex_cmd_lock); adapter->scan_processing = true; - spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags); + spin_unlock_bh(&adapter->mwifiex_cmd_lock);
scan_cfg_out = kzalloc(sizeof(union mwifiex_scan_cmd_config_tlv), GFP_KERNEL); @@@ -1550,12 -1555,13 +1554,12 @@@
/* Get scan command from scan_pending_q and put to cmd_pending_q */ if (!ret) { - spin_lock_irqsave(&adapter->scan_pending_q_lock, flags); + spin_lock_bh(&adapter->scan_pending_q_lock); if (!list_empty(&adapter->scan_pending_q)) { cmd_node = list_first_entry(&adapter->scan_pending_q, struct cmd_ctrl_node, list); list_del(&cmd_node->list); - spin_unlock_irqrestore(&adapter->scan_pending_q_lock, - flags); + spin_unlock_bh(&adapter->scan_pending_q_lock); mwifiex_insert_cmd_to_pending_q(adapter, cmd_node); queue_work(adapter->workqueue, &adapter->main_work);
@@@ -1566,7 -1572,8 +1570,7 @@@ mwifiex_wait_queue_complete(adapter, cmd_node); } } else { - spin_unlock_irqrestore(&adapter->scan_pending_q_lock, - flags); + spin_unlock_bh(&adapter->scan_pending_q_lock); } }
@@@ -1574,9 -1581,9 +1578,9 @@@ kfree(scan_chan_list); done: if (ret) { - spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags); + spin_lock_bh(&adapter->mwifiex_cmd_lock); adapter->scan_processing = false; - spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags); + spin_unlock_bh(&adapter->mwifiex_cmd_lock); } return ret; } @@@ -1712,6 -1719,7 +1716,6 @@@ static int mwifiex_update_curr_bss_para { struct mwifiex_bssdescriptor *bss_desc; int ret; - unsigned long flags;
/* Allocate and fill new bss descriptor */ bss_desc = kzalloc(sizeof(struct mwifiex_bssdescriptor), GFP_KERNEL); @@@ -1726,7 -1734,7 +1730,7 @@@ if (ret) goto done;
- spin_lock_irqsave(&priv->curr_bcn_buf_lock, flags); + spin_lock_bh(&priv->curr_bcn_buf_lock); /* Make a copy of current BSSID descriptor */ memcpy(&priv->curr_bss_params.bss_descriptor, bss_desc, sizeof(priv->curr_bss_params.bss_descriptor)); @@@ -1735,7 -1743,7 +1739,7 @@@ * in mwifiex_save_curr_bcn() */ mwifiex_save_curr_bcn(priv); - spin_unlock_irqrestore(&priv->curr_bcn_buf_lock, flags); + spin_unlock_bh(&priv->curr_bcn_buf_lock);
done: /* beacon_ie buffer was allocated in function @@@ -1989,14 -1997,15 +1993,14 @@@ static void mwifiex_check_next_scan_com { struct mwifiex_adapter *adapter = priv->adapter; struct cmd_ctrl_node *cmd_node; - unsigned long flags;
- spin_lock_irqsave(&adapter->scan_pending_q_lock, flags); + spin_lock_bh(&adapter->scan_pending_q_lock); if (list_empty(&adapter->scan_pending_q)) { - spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags); + spin_unlock_bh(&adapter->scan_pending_q_lock);
- spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags); + spin_lock_bh(&adapter->mwifiex_cmd_lock); adapter->scan_processing = false; - spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags); + spin_unlock_bh(&adapter->mwifiex_cmd_lock);
mwifiex_active_scan_req_for_passive_chan(priv);
@@@ -2020,13 -2029,13 +2024,13 @@@ } } else if ((priv->scan_aborting && !priv->scan_request) || priv->scan_block) { - spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags); + spin_unlock_bh(&adapter->scan_pending_q_lock);
mwifiex_cancel_pending_scan_cmd(adapter);
- spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags); + spin_lock_bh(&adapter->mwifiex_cmd_lock); adapter->scan_processing = false; - spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags); + spin_unlock_bh(&adapter->mwifiex_cmd_lock);
if (!adapter->active_scan_triggered) { if (priv->scan_request) { @@@ -2052,7 -2061,7 +2056,7 @@@ cmd_node = list_first_entry(&adapter->scan_pending_q, struct cmd_ctrl_node, list); list_del(&cmd_node->list); - spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags); + spin_unlock_bh(&adapter->scan_pending_q_lock); mwifiex_insert_cmd_to_pending_q(adapter, cmd_node); }
@@@ -2062,14 -2071,15 +2066,14 @@@ void mwifiex_cancel_scan(struct mwifiex_adapter *adapter) { struct mwifiex_private *priv; - unsigned long cmd_flags; int i;
mwifiex_cancel_pending_scan_cmd(adapter);
if (adapter->scan_processing) { - spin_lock_irqsave(&adapter->mwifiex_cmd_lock, cmd_flags); + spin_lock_bh(&adapter->mwifiex_cmd_lock); adapter->scan_processing = false; - spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, cmd_flags); + spin_unlock_bh(&adapter->mwifiex_cmd_lock); for (i = 0; i < adapter->priv_num; i++) { priv = adapter->priv[i]; if (!priv) @@@ -2551,6 -2561,7 +2555,6 @@@ int mwifiex_ret_802_11_scan_ext(struct
struct host_cmd_ds_command *cmd_ptr; struct cmd_ctrl_node *cmd_node; - unsigned long cmd_flags, scan_flags; bool complete_scan = false;
mwifiex_dbg(adapter, INFO, "info: EXT scan returns successfully\n"); @@@ -2585,8 -2596,8 +2589,8 @@@ sizeof(struct mwifiex_ie_types_header)); }
- spin_lock_irqsave(&adapter->cmd_pending_q_lock, cmd_flags); - spin_lock_irqsave(&adapter->scan_pending_q_lock, scan_flags); + spin_lock_bh(&adapter->cmd_pending_q_lock); + spin_lock_bh(&adapter->scan_pending_q_lock); if (list_empty(&adapter->scan_pending_q)) { complete_scan = true; list_for_each_entry(cmd_node, &adapter->cmd_pending_q, list) { @@@ -2600,8 -2611,8 +2604,8 @@@ } } } - spin_unlock_irqrestore(&adapter->scan_pending_q_lock, scan_flags); - spin_unlock_irqrestore(&adapter->cmd_pending_q_lock, cmd_flags); + spin_unlock_bh(&adapter->scan_pending_q_lock); + spin_unlock_bh(&adapter->cmd_pending_q_lock);
if (complete_scan) mwifiex_complete_scan(priv); @@@ -2773,12 -2784,13 +2777,12 @@@ mwifiex_queue_scan_cmd(struct mwifiex_p struct cmd_ctrl_node *cmd_node) { struct mwifiex_adapter *adapter = priv->adapter; - unsigned long flags;
cmd_node->wait_q_enabled = true; cmd_node->condition = &adapter->scan_wait_q_woken; - spin_lock_irqsave(&adapter->scan_pending_q_lock, flags); + spin_lock_bh(&adapter->scan_pending_q_lock); list_add_tail(&cmd_node->list, &adapter->scan_pending_q); - spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags); + spin_unlock_bh(&adapter->scan_pending_q_lock); }
/* diff --combined drivers/net/wireless/marvell/mwifiex/wmm.c index 0301bc33f554,64916ba15df5..41f0231376c0 --- a/drivers/net/wireless/marvell/mwifiex/wmm.c +++ b/drivers/net/wireless/marvell/mwifiex/wmm.c @@@ -138,6 -138,7 +138,6 @@@ void mwifiex_ralist_add(struct mwifiex_ struct mwifiex_ra_list_tbl *ra_list; struct mwifiex_adapter *adapter = priv->adapter; struct mwifiex_sta_node *node; - unsigned long flags;
for (i = 0; i < MAX_NUM_TID; ++i) { @@@ -162,7 -163,7 +162,7 @@@ ra_list->is_11n_enabled = IS_11N_ENABLED(priv); } } else { - spin_lock_irqsave(&priv->sta_list_spinlock, flags); + spin_lock_bh(&priv->sta_list_spinlock); node = mwifiex_get_sta_entry(priv, ra); if (node) ra_list->tx_paused = node->tx_pause; @@@ -170,7 -171,7 +170,7 @@@ mwifiex_is_sta_11n_enabled(priv, node); if (ra_list->is_11n_enabled) ra_list->max_amsdu = node->max_amsdu; - spin_unlock_irqrestore(&priv->sta_list_spinlock, flags); + spin_unlock_bh(&priv->sta_list_spinlock); }
mwifiex_dbg(adapter, DATA, "data: ralist %p: is_11n_enabled=%d\n", @@@ -239,7 -240,7 +239,7 @@@ mwifiex_wmm_setup_queue_priorities(stru mwifiex_dbg(priv->adapter, INFO, "info: WMM Parameter IE: version=%d,\t" "qos_info Parameter Set Count=%d, Reserved=%#x\n", - wmm_ie->vend_hdr.version, wmm_ie->qos_info_bitmap & + wmm_ie->version, wmm_ie->qos_info_bitmap & IEEE80211_WMM_IE_AP_QOSINFO_PARAM_SET_CNT_MASK, wmm_ie->reserved);
@@@ -582,10 -583,11 +582,10 @@@ static int mwifiex_free_ack_frame(int i void mwifiex_clean_txrx(struct mwifiex_private *priv) { - unsigned long flags; struct sk_buff *skb, *tmp;
mwifiex_11n_cleanup_reorder_tbl(priv); - spin_lock_irqsave(&priv->wmm.ra_list_spinlock, flags); + spin_lock_bh(&priv->wmm.ra_list_spinlock);
mwifiex_wmm_cleanup_queues(priv); mwifiex_11n_delete_all_tx_ba_stream_tbl(priv); @@@ -599,7 -601,7 +599,7 @@@ if (priv->adapter->if_ops.clean_pcie_ring && !test_bit(MWIFIEX_SURPRISE_REMOVED, &priv->adapter->work_flags)) priv->adapter->if_ops.clean_pcie_ring(priv->adapter); - spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, flags); + spin_unlock_bh(&priv->wmm.ra_list_spinlock);
skb_queue_walk_safe(&priv->tdls_txq, skb, tmp) { skb_unlink(skb, &priv->tdls_txq); @@@ -640,9 -642,10 +640,9 @@@ void mwifiex_update_ralist_tx_pause(str { struct mwifiex_ra_list_tbl *ra_list; u32 pkt_cnt = 0, tx_pkts_queued; - unsigned long flags; int i;
- spin_lock_irqsave(&priv->wmm.ra_list_spinlock, flags); + spin_lock_bh(&priv->wmm.ra_list_spinlock);
for (i = 0; i < MAX_NUM_TID; ++i) { ra_list = mwifiex_wmm_get_ralist_node(priv, i, mac); @@@ -668,7 -671,7 +668,7 @@@ atomic_set(&priv->wmm.tx_pkts_queued, tx_pkts_queued); atomic_set(&priv->wmm.highest_queued_prio, HIGH_PRIO_TID); } - spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, flags); + spin_unlock_bh(&priv->wmm.ra_list_spinlock); }
/* This function updates non-tdls peer ralist tx_pause while @@@ -679,9 -682,10 +679,9 @@@ void mwifiex_update_ralist_tx_pause_in_ { struct mwifiex_ra_list_tbl *ra_list; u32 pkt_cnt = 0, tx_pkts_queued; - unsigned long flags; int i;
- spin_lock_irqsave(&priv->wmm.ra_list_spinlock, flags); + spin_lock_bh(&priv->wmm.ra_list_spinlock);
for (i = 0; i < MAX_NUM_TID; ++i) { list_for_each_entry(ra_list, &priv->wmm.tid_tbl_ptr[i].ra_list, @@@ -712,7 -716,7 +712,7 @@@ atomic_set(&priv->wmm.tx_pkts_queued, tx_pkts_queued); atomic_set(&priv->wmm.highest_queued_prio, HIGH_PRIO_TID); } - spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, flags); + spin_unlock_bh(&priv->wmm.ra_list_spinlock); }
/* @@@ -744,9 -748,10 +744,9 @@@ voi mwifiex_wmm_del_peer_ra_list(struct mwifiex_private *priv, const u8 *ra_addr) { struct mwifiex_ra_list_tbl *ra_list; - unsigned long flags; int i;
- spin_lock_irqsave(&priv->wmm.ra_list_spinlock, flags); + spin_lock_bh(&priv->wmm.ra_list_spinlock);
for (i = 0; i < MAX_NUM_TID; ++i) { ra_list = mwifiex_wmm_get_ralist_node(priv, i, ra_addr); @@@ -762,7 -767,7 +762,7 @@@ list_del(&ra_list->list); kfree(ra_list); } - spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, flags); + spin_unlock_bh(&priv->wmm.ra_list_spinlock); }
/* @@@ -813,6 -818,7 +813,6 @@@ mwifiex_wmm_add_buf_txqueue(struct mwif u32 tid; struct mwifiex_ra_list_tbl *ra_list; u8 ra[ETH_ALEN], tid_down; - unsigned long flags; struct list_head list_head; int tdls_status = TDLS_NOT_SETUP; struct ethhdr *eth_hdr = (struct ethhdr *)skb->data; @@@ -838,7 -844,7 +838,7 @@@
tid = skb->priority;
- spin_lock_irqsave(&priv->wmm.ra_list_spinlock, flags); + spin_lock_bh(&priv->wmm.ra_list_spinlock);
tid_down = mwifiex_wmm_downgrade_tid(priv, tid);
@@@ -858,7 -864,8 +858,7 @@@ break; case TDLS_SETUP_INPROGRESS: skb_queue_tail(&priv->tdls_txq, skb); - spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, - flags); + spin_unlock_bh(&priv->wmm.ra_list_spinlock); return; default: list_head = priv->wmm.tid_tbl_ptr[tid_down].ra_list; @@@ -874,7 -881,7 +874,7 @@@ }
if (!ra_list) { - spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, flags); + spin_unlock_bh(&priv->wmm.ra_list_spinlock); mwifiex_write_data_complete(adapter, skb, 0, -1); return; } @@@ -894,7 -901,7 +894,7 @@@ else atomic_inc(&priv->wmm.tx_pkts_queued);
- spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, flags); + spin_unlock_bh(&priv->wmm.ra_list_spinlock); }
/* @@@ -1085,6 -1092,7 +1085,6 @@@ mwifiex_wmm_get_highest_priolist_ptr(st struct mwifiex_ra_list_tbl *ptr; struct mwifiex_tid_tbl *tid_ptr; atomic_t *hqp; - unsigned long flags_ra; int i, j;
/* check the BSS with highest priority first */ @@@ -1110,7 -1118,8 +1110,7 @@@ try_again hqp = &priv_tmp->wmm.highest_queued_prio; for (i = atomic_read(hqp); i >= LOW_PRIO_TID; --i) {
- spin_lock_irqsave(&priv_tmp->wmm. - ra_list_spinlock, flags_ra); + spin_lock_bh(&priv_tmp->wmm.ra_list_spinlock);
tid_ptr = &(priv_tmp)->wmm. tid_tbl_ptr[tos_to_tid[i]]; @@@ -1125,7 -1134,9 +1125,7 @@@ goto found; }
- spin_unlock_irqrestore(&priv_tmp->wmm. - ra_list_spinlock, - flags_ra); + spin_unlock_bh(&priv_tmp->wmm.ra_list_spinlock); }
if (atomic_read(&priv_tmp->wmm.tx_pkts_queued) != 0) { @@@ -1147,7 -1158,7 +1147,7 @@@ found /* holds ra_list_spinlock */ if (atomic_read(hqp) > i) atomic_set(hqp, i); - spin_unlock_irqrestore(&priv_tmp->wmm.ra_list_spinlock, flags_ra); + spin_unlock_bh(&priv_tmp->wmm.ra_list_spinlock);
*priv = priv_tmp; *tid = tos_to_tid[i]; @@@ -1171,23 -1182,24 +1171,23 @@@ void mwifiex_rotate_priolists(struct mw struct mwifiex_adapter *adapter = priv->adapter; struct mwifiex_bss_prio_tbl *tbl = adapter->bss_prio_tbl; struct mwifiex_tid_tbl *tid_ptr = &priv->wmm.tid_tbl_ptr[tid]; - unsigned long flags;
- spin_lock_irqsave(&tbl[priv->bss_priority].bss_prio_lock, flags); + spin_lock_bh(&tbl[priv->bss_priority].bss_prio_lock); /* * dirty trick: we remove 'head' temporarily and reinsert it after * curr bss node. imagine list to stay fixed while head is moved */ list_move(&tbl[priv->bss_priority].bss_prio_head, &tbl[priv->bss_priority].bss_prio_cur->list); - spin_unlock_irqrestore(&tbl[priv->bss_priority].bss_prio_lock, flags); + spin_unlock_bh(&tbl[priv->bss_priority].bss_prio_lock);
- spin_lock_irqsave(&priv->wmm.ra_list_spinlock, flags); + spin_lock_bh(&priv->wmm.ra_list_spinlock); if (mwifiex_is_ralist_valid(priv, ra, tid)) { priv->wmm.packets_out[tid]++; /* same as above */ list_move(&tid_ptr->ra_list, &ra->list); } - spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, flags); + spin_unlock_bh(&priv->wmm.ra_list_spinlock); }
/* @@@ -1224,7 -1236,8 +1224,7 @@@ mwifiex_is_11n_aggragation_possible(str */ static void mwifiex_send_single_packet(struct mwifiex_private *priv, - struct mwifiex_ra_list_tbl *ptr, int ptr_index, - unsigned long ra_list_flags) + struct mwifiex_ra_list_tbl *ptr, int ptr_index) __releases(&priv->wmm.ra_list_spinlock) { struct sk_buff *skb, *skb_next; @@@ -1233,7 -1246,8 +1233,7 @@@ struct mwifiex_txinfo *tx_info;
if (skb_queue_empty(&ptr->skb_head)) { - spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, - ra_list_flags); + spin_unlock_bh(&priv->wmm.ra_list_spinlock); mwifiex_dbg(adapter, DATA, "data: nothing to send\n"); return; } @@@ -1251,17 -1265,18 +1251,17 @@@ else skb_next = NULL;
- spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, ra_list_flags); + spin_unlock_bh(&priv->wmm.ra_list_spinlock);
tx_param.next_pkt_len = ((skb_next) ? skb_next->len + sizeof(struct txpd) : 0);
if (mwifiex_process_tx(priv, skb, &tx_param) == -EBUSY) { /* Queue the packet back at the head */ - spin_lock_irqsave(&priv->wmm.ra_list_spinlock, ra_list_flags); + spin_lock_bh(&priv->wmm.ra_list_spinlock);
if (!mwifiex_is_ralist_valid(priv, ptr, ptr_index)) { - spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, - ra_list_flags); + spin_unlock_bh(&priv->wmm.ra_list_spinlock); mwifiex_write_data_complete(adapter, skb, 0, -1); return; } @@@ -1271,7 -1286,8 +1271,7 @@@ ptr->total_pkt_count++; ptr->ba_pkt_count++; tx_info->flags |= MWIFIEX_BUF_FLAG_REQUEUED_PKT; - spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, - ra_list_flags); + spin_unlock_bh(&priv->wmm.ra_list_spinlock); } else { mwifiex_rotate_priolists(priv, ptr, ptr_index); atomic_dec(&priv->wmm.tx_pkts_queued); @@@ -1307,7 -1323,8 +1307,7 @@@ mwifiex_is_ptr_processed(struct mwifiex */ static void mwifiex_send_processed_packet(struct mwifiex_private *priv, - struct mwifiex_ra_list_tbl *ptr, int ptr_index, - unsigned long ra_list_flags) + struct mwifiex_ra_list_tbl *ptr, int ptr_index) __releases(&priv->wmm.ra_list_spinlock) { struct mwifiex_tx_param tx_param; @@@ -1317,7 -1334,8 +1317,7 @@@ struct mwifiex_txinfo *tx_info;
if (skb_queue_empty(&ptr->skb_head)) { - spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, - ra_list_flags); + spin_unlock_bh(&priv->wmm.ra_list_spinlock); return; }
@@@ -1325,7 -1343,8 +1325,7 @@@
if (adapter->data_sent || adapter->tx_lock_flag) { ptr->total_pkt_count--; - spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, - ra_list_flags); + spin_unlock_bh(&priv->wmm.ra_list_spinlock); skb_queue_tail(&adapter->tx_data_q, skb); atomic_dec(&priv->wmm.tx_pkts_queued); atomic_inc(&adapter->tx_queued); @@@ -1339,7 -1358,7 +1339,7 @@@
tx_info = MWIFIEX_SKB_TXCB(skb);
- spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, ra_list_flags); + spin_unlock_bh(&priv->wmm.ra_list_spinlock);
tx_param.next_pkt_len = ((skb_next) ? skb_next->len + @@@ -1355,10 -1374,11 +1355,10 @@@ switch (ret) { case -EBUSY: mwifiex_dbg(adapter, ERROR, "data: -EBUSY is returned\n"); - spin_lock_irqsave(&priv->wmm.ra_list_spinlock, ra_list_flags); + spin_lock_bh(&priv->wmm.ra_list_spinlock);
if (!mwifiex_is_ralist_valid(priv, ptr, ptr_index)) { - spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, - ra_list_flags); + spin_unlock_bh(&priv->wmm.ra_list_spinlock); mwifiex_write_data_complete(adapter, skb, 0, -1); return; } @@@ -1366,7 -1386,8 +1366,7 @@@ skb_queue_tail(&ptr->skb_head, skb);
tx_info->flags |= MWIFIEX_BUF_FLAG_REQUEUED_PKT; - spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, - ra_list_flags); + spin_unlock_bh(&priv->wmm.ra_list_spinlock); break; case -1: mwifiex_dbg(adapter, ERROR, "host_to_card failed: %#x\n", ret); @@@ -1383,9 -1404,10 +1383,9 @@@ if (ret != -EBUSY) { mwifiex_rotate_priolists(priv, ptr, ptr_index); atomic_dec(&priv->wmm.tx_pkts_queued); - spin_lock_irqsave(&priv->wmm.ra_list_spinlock, ra_list_flags); + spin_lock_bh(&priv->wmm.ra_list_spinlock); ptr->total_pkt_count--; - spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, - ra_list_flags); + spin_unlock_bh(&priv->wmm.ra_list_spinlock); } }
@@@ -1401,6 -1423,7 +1401,6 @@@ mwifiex_dequeue_tx_packet(struct mwifie int ptr_index = 0; u8 ra[ETH_ALEN]; int tid_del = 0, tid = 0; - unsigned long flags;
ptr = mwifiex_wmm_get_highest_priolist_ptr(adapter, &priv, &ptr_index); if (!ptr) @@@ -1410,14 -1433,14 +1410,14 @@@
mwifiex_dbg(adapter, DATA, "data: tid=%d\n", tid);
- spin_lock_irqsave(&priv->wmm.ra_list_spinlock, flags); + spin_lock_bh(&priv->wmm.ra_list_spinlock); if (!mwifiex_is_ralist_valid(priv, ptr, ptr_index)) { - spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, flags); + spin_unlock_bh(&priv->wmm.ra_list_spinlock); return -1; }
if (mwifiex_is_ptr_processed(priv, ptr)) { - mwifiex_send_processed_packet(priv, ptr, ptr_index, flags); + mwifiex_send_processed_packet(priv, ptr, ptr_index); /* ra_list_spinlock has been freed in mwifiex_send_processed_packet() */ return 0; @@@ -1432,12 -1455,12 +1432,12 @@@ mwifiex_is_amsdu_allowed(priv, tid) && mwifiex_is_11n_aggragation_possible(priv, ptr, adapter->tx_buf_size)) - mwifiex_11n_aggregate_pkt(priv, ptr, ptr_index, flags); + mwifiex_11n_aggregate_pkt(priv, ptr, ptr_index); /* ra_list_spinlock has been freed in * mwifiex_11n_aggregate_pkt() */ else - mwifiex_send_single_packet(priv, ptr, ptr_index, flags); + mwifiex_send_single_packet(priv, ptr, ptr_index); /* ra_list_spinlock has been freed in * mwifiex_send_single_packet() */ @@@ -1458,11 -1481,11 +1458,11 @@@ if (mwifiex_is_amsdu_allowed(priv, tid) && mwifiex_is_11n_aggragation_possible(priv, ptr, adapter->tx_buf_size)) - mwifiex_11n_aggregate_pkt(priv, ptr, ptr_index, flags); + mwifiex_11n_aggregate_pkt(priv, ptr, ptr_index); /* ra_list_spinlock has been freed in mwifiex_11n_aggregate_pkt() */ else - mwifiex_send_single_packet(priv, ptr, ptr_index, flags); + mwifiex_send_single_packet(priv, ptr, ptr_index); /* ra_list_spinlock has been freed in mwifiex_send_single_packet() */ } diff --combined drivers/net/wireless/mediatek/mt76/mt76.h index 56bf93a8988e,889b76deb703..989386ecb5e4 --- a/drivers/net/wireless/mediatek/mt76/mt76.h +++ b/drivers/net/wireless/mediatek/mt76/mt76.h @@@ -30,6 -30,7 +30,7 @@@ #define MT_TX_RING_SIZE 256 #define MT_MCU_RING_SIZE 32 #define MT_RX_BUF_SIZE 2048 + #define MT_SKB_HEAD_LEN 128
struct mt76_dev; struct mt76_wcid; @@@ -258,11 -259,10 +259,11 @@@ struct mt76_rx_tid #define MT_TX_CB_TXS_DONE BIT(1) #define MT_TX_CB_TXS_FAILED BIT(2)
-#define MT_PACKET_ID_MASK GENMASK(7, 0) +#define MT_PACKET_ID_MASK GENMASK(6, 0) #define MT_PACKET_ID_NO_ACK 0 #define MT_PACKET_ID_NO_SKB 1 #define MT_PACKET_ID_FIRST 2 +#define MT_PACKET_ID_HAS_RATE BIT(7)
#define MT_TX_STATUS_SKB_TIMEOUT HZ
@@@ -382,8 -382,7 +383,8 @@@ enum mt76u_out_ep __MT_EP_OUT_MAX, };
-#define MT_SG_MAX_SIZE 8 +#define MT_TX_SG_MAX_SIZE 8 +#define MT_RX_SG_MAX_SIZE 1 #define MT_NUM_TX_ENTRIES 256 #define MT_NUM_RX_ENTRIES 128 #define MCU_RESP_URB_SIZE 1024 @@@ -395,7 -394,9 +396,7 @@@ struct mt76_usb struct delayed_work stat_work;
u8 out_ep[__MT_EP_OUT_MAX]; - u16 out_max_packet; u8 in_ep[__MT_EP_IN_MAX]; - u16 in_max_packet; bool sg_en;
struct mt76u_mcu { @@@ -452,7 -453,6 +453,7 @@@ struct mt76_dev int tx_dma_idx[4];
struct tasklet_struct tx_tasklet; + struct napi_struct tx_napi; struct delayed_work mac_work;
wait_queue_head_t tx_wait; @@@ -484,8 -484,6 +485,8 @@@ int txpower_conf; int txpower_cur;
+ enum nl80211_dfs_regions region; + u32 debugfs_reg;
struct led_classdev led_cdev; @@@ -691,14 -689,6 +692,14 @@@ static inline void mt76_insert_hdr_pad( skb->data[len + 1] = 0; }
+static inline bool mt76_is_skb_pktid(u8 pktid) +{ + if (pktid & MT_PACKET_ID_HAS_RATE) + return false; + + return pktid >= MT_PACKET_ID_FIRST; +} + void mt76_rx(struct mt76_dev *dev, enum mt76_rxq_id q, struct sk_buff *skb); void mt76_tx(struct mt76_dev *dev, struct ieee80211_sta *sta, struct mt76_wcid *wcid, struct sk_buff *skb); @@@ -760,10 -750,6 +761,10 @@@ void mt76_csa_check(struct mt76_dev *de void mt76_csa_finish(struct mt76_dev *dev);
int mt76_set_tim(struct ieee80211_hw *hw, struct ieee80211_sta *sta, bool set); +void mt76_insert_ccmp_hdr(struct sk_buff *skb, u8 key_id); +int mt76_get_rate(struct mt76_dev *dev, + struct ieee80211_supported_band *sband, + int idx, bool cck);
/* internal */ void mt76_tx_free(struct mt76_dev *dev); diff --combined drivers/net/wireless/mediatek/mt76/usb.c index 61b27f3ec6e4,dd90427b2d67..fb87ce7fbdf6 --- a/drivers/net/wireless/mediatek/mt76/usb.c +++ b/drivers/net/wireless/mediatek/mt76/usb.c @@@ -267,10 -267,12 +267,10 @@@ mt76u_set_endpoints(struct usb_interfac if (usb_endpoint_is_bulk_in(ep_desc) && in_ep < __MT_EP_IN_MAX) { usb->in_ep[in_ep] = usb_endpoint_num(ep_desc); - usb->in_max_packet = usb_endpoint_maxp(ep_desc); in_ep++; } else if (usb_endpoint_is_bulk_out(ep_desc) && out_ep < __MT_EP_OUT_MAX) { usb->out_ep[out_ep] = usb_endpoint_num(ep_desc); - usb->out_max_packet = usb_endpoint_maxp(ep_desc); out_ep++; } } @@@ -331,13 -333,12 +331,13 @@@ mt76u_refill_rx(struct mt76_dev *dev, s }
static int -mt76u_urb_alloc(struct mt76_dev *dev, struct mt76_queue_entry *e) +mt76u_urb_alloc(struct mt76_dev *dev, struct mt76_queue_entry *e, + int sg_max_size) { unsigned int size = sizeof(struct urb);
if (dev->usb.sg_en) - size += MT_SG_MAX_SIZE * sizeof(struct scatterlist); + size += sg_max_size * sizeof(struct scatterlist);
e->urb = kzalloc(size, GFP_KERNEL); if (!e->urb) @@@ -356,12 -357,11 +356,12 @@@ mt76u_rx_urb_alloc(struct mt76_dev *dev { int err;
- err = mt76u_urb_alloc(dev, e); + err = mt76u_urb_alloc(dev, e, MT_RX_SG_MAX_SIZE); if (err) return err;
- return mt76u_refill_rx(dev, e->urb, MT_SG_MAX_SIZE, GFP_KERNEL); + return mt76u_refill_rx(dev, e->urb, MT_RX_SG_MAX_SIZE, + GFP_KERNEL); }
static void mt76u_urb_free(struct urb *urb) @@@ -429,6 -429,42 +429,42 @@@ static int mt76u_get_rx_entry_len(u8 *d return dma_len; }
+ static struct sk_buff * + mt76u_build_rx_skb(void *data, int len, int buf_size) + { + struct sk_buff *skb; + + if (SKB_WITH_OVERHEAD(buf_size) < MT_DMA_HDR_LEN + len) { + struct page *page; + + /* slow path, not enough space for data and + * skb_shared_info + */ + skb = alloc_skb(MT_SKB_HEAD_LEN, GFP_ATOMIC); + if (!skb) + return NULL; + + skb_put_data(skb, data + MT_DMA_HDR_LEN, MT_SKB_HEAD_LEN); + data += (MT_DMA_HDR_LEN + MT_SKB_HEAD_LEN); + page = virt_to_head_page(data); + skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags, + page, data - page_address(page), + len - MT_SKB_HEAD_LEN, buf_size); + + return skb; + } + + /* fast path */ + skb = build_skb(data, buf_size); + if (!skb) + return NULL; + + skb_reserve(skb, MT_DMA_HDR_LEN); + __skb_put(skb, len); + + return skb; + } + static int mt76u_process_rx_entry(struct mt76_dev *dev, struct urb *urb) { @@@ -446,19 -482,11 +482,11 @@@ return 0;
data_len = min_t(int, len, data_len - MT_DMA_HDR_LEN); - if (MT_DMA_HDR_LEN + data_len > SKB_WITH_OVERHEAD(q->buf_size)) { - dev_err_ratelimited(dev->dev, "rx data too big %d\n", data_len); - return 0; - } - - skb = build_skb(data, q->buf_size); + skb = mt76u_build_rx_skb(data, data_len, q->buf_size); if (!skb) return 0;
- skb_reserve(skb, MT_DMA_HDR_LEN); - __skb_put(skb, data_len); len -= data_len; - while (len > 0 && nsgs < urb->num_sgs) { data_len = min_t(int, len, urb->sg[nsgs].length); skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags, @@@ -577,9 -605,8 +605,9 @@@ static int mt76u_alloc_rx(struct mt76_d if (!q->entry) return -ENOMEM;
- q->buf_size = dev->usb.sg_en ? MT_RX_BUF_SIZE : PAGE_SIZE; q->ndesc = MT_NUM_RX_ENTRIES; + q->buf_size = PAGE_SIZE; + for (i = 0; i < q->ndesc; i++) { err = mt76u_rx_urb_alloc(dev, &q->entry[i]); if (err < 0) @@@ -736,7 -763,7 +764,7 @@@ mt76u_tx_setup_buffers(struct mt76_dev urb->transfer_buffer = skb->data; return 0; } else { - sg_init_table(urb->sg, MT_SG_MAX_SIZE); + sg_init_table(urb->sg, MT_TX_SG_MAX_SIZE); urb->num_sgs = skb_to_sgvec(skb, urb->sg, 0, skb->len); if (urb->num_sgs == 0) return -ENOMEM; @@@ -830,8 -857,7 +858,8 @@@ static int mt76u_alloc_tx(struct mt76_d
q->ndesc = MT_NUM_TX_ENTRIES; for (j = 0; j < q->ndesc; j++) { - err = mt76u_urb_alloc(dev, &q->entry[j]); + err = mt76u_urb_alloc(dev, &q->entry[j], + MT_TX_SG_MAX_SIZE); if (err < 0) return err; } diff --combined include/linux/phylink.h index 0fe57a261c9c,5b130140fb8f..300ecdb6790a --- a/include/linux/phylink.h +++ b/include/linux/phylink.h @@@ -54,21 -54,6 +54,21 @@@ struct phylink_link_state unsigned int an_complete:1; };
+enum phylink_op_type { + PHYLINK_NETDEV = 0, + PHYLINK_DEV, +}; + +/** + * struct phylink_config - PHYLINK configuration structure + * @dev: a pointer to a struct device associated with the MAC + * @type: operation type of PHYLINK instance + */ +struct phylink_config { + struct device *dev; + enum phylink_op_type type; +}; + /** * struct phylink_mac_ops - MAC operations structure. * @validate: Validate and update the link configuration. @@@ -81,17 -66,16 +81,17 @@@ * The individual methods are described more fully below. */ struct phylink_mac_ops { - void (*validate)(struct net_device *ndev, unsigned long *supported, + void (*validate)(struct phylink_config *config, + unsigned long *supported, struct phylink_link_state *state); - int (*mac_link_state)(struct net_device *ndev, + int (*mac_link_state)(struct phylink_config *config, struct phylink_link_state *state); - void (*mac_config)(struct net_device *ndev, unsigned int mode, + void (*mac_config)(struct phylink_config *config, unsigned int mode, const struct phylink_link_state *state); - void (*mac_an_restart)(struct net_device *ndev); - void (*mac_link_down)(struct net_device *ndev, unsigned int mode, + void (*mac_an_restart)(struct phylink_config *config); + void (*mac_link_down)(struct phylink_config *config, unsigned int mode, phy_interface_t interface); - void (*mac_link_up)(struct net_device *ndev, unsigned int mode, + void (*mac_link_up)(struct phylink_config *config, unsigned int mode, phy_interface_t interface, struct phy_device *phy); }; @@@ -99,7 -83,7 +99,7 @@@ #if 0 /* For kernel-doc purposes only. */ /** * validate - Validate and update the link configuration - * @ndev: a pointer to a &struct net_device for the MAC. + * @config: a pointer to a &struct phylink_config. * @supported: ethtool bitmask for supported link modes. * @state: a pointer to a &struct phylink_link_state. * @@@ -109,19 -93,26 +109,26 @@@ * Note that the PHY may be able to transform from one connection * technology to another, so, eg, don't clear 1000BaseX just * because the MAC is unable to BaseX mode. This is more about - * clearing unsupported speeds and duplex settings. + * clearing unsupported speeds and duplex settings. The port modes + * should not be cleared; phylink_set_port_modes() will help with this. * * If the @state->interface mode is %PHY_INTERFACE_MODE_1000BASEX * or %PHY_INTERFACE_MODE_2500BASEX, select the appropriate mode * based on @state->advertising and/or @state->speed and update - * @state->interface accordingly. + * @state->interface accordingly. See phylink_helper_basex_speed(). + * + * When @state->interface is %PHY_INTERFACE_MODE_NA, phylink expects the + * MAC driver to return all supported link modes. + * + * If the @state->interface mode is not supported, then the @supported + * mask must be cleared. */ -void validate(struct net_device *ndev, unsigned long *supported, +void validate(struct phylink_config *config, unsigned long *supported, struct phylink_link_state *state);
/** * mac_link_state() - Read the current link state from the hardware - * @ndev: a pointer to a &struct net_device for the MAC. + * @config: a pointer to a &struct phylink_config. * @state: a pointer to a &struct phylink_link_state. * * Read the current link state from the MAC, reporting the current @@@ -130,12 -121,12 +137,12 @@@ * negotiation completion state in @state->an_complete, and link * up state in @state->link. */ -int mac_link_state(struct net_device *ndev, +int mac_link_state(struct phylink_config *config, struct phylink_link_state *state);
/** * mac_config() - configure the MAC for the selected mode and state - * @ndev: a pointer to a &struct net_device for the MAC. + * @config: a pointer to a &struct phylink_config. * @mode: one of %MLO_AN_FIXED, %MLO_AN_PHY, %MLO_AN_INBAND. * @state: a pointer to a &struct phylink_link_state. * @@@ -184,18 -175,18 +191,18 @@@ * down. This "update" behaviour is critical to avoid bouncing the * link up status. */ -void mac_config(struct net_device *ndev, unsigned int mode, +void mac_config(struct phylink_config *config, unsigned int mode, const struct phylink_link_state *state);
/** * mac_an_restart() - restart 802.3z BaseX autonegotiation - * @ndev: a pointer to a &struct net_device for the MAC. + * @config: a pointer to a &struct phylink_config. */ -void mac_an_restart(struct net_device *ndev); +void mac_an_restart(struct phylink_config *config);
/** * mac_link_down() - take the link down - * @ndev: a pointer to a &struct net_device for the MAC. + * @config: a pointer to a &struct phylink_config. * @mode: link autonegotiation mode * @interface: link &typedef phy_interface_t mode * @@@ -204,12 -195,12 +211,12 @@@ * Energy Efficient Ethernet MAC configuration. Interface type * selection must be done in mac_config(). */ -void mac_link_down(struct net_device *ndev, unsigned int mode, +void mac_link_down(struct phylink_config *config, unsigned int mode, phy_interface_t interface);
/** * mac_link_up() - allow the link to come up - * @ndev: a pointer to a &struct net_device for the MAC. + * @config: a pointer to a &struct phylink_config. * @mode: link autonegotiation mode * @interface: link &typedef phy_interface_t mode * @phy: any attached phy @@@ -220,14 -211,13 +227,14 @@@ * phy_init_eee() and perform appropriate MAC configuration for EEE. * Interface type selection must be done in mac_config(). */ -void mac_link_up(struct net_device *ndev, unsigned int mode, +void mac_link_up(struct phylink_config *config, unsigned int mode, phy_interface_t interface, struct phy_device *phy); #endif
-struct phylink *phylink_create(struct net_device *, struct fwnode_handle *, - phy_interface_t iface, const struct phylink_mac_ops *ops); +struct phylink *phylink_create(struct phylink_config *, struct fwnode_handle *, + phy_interface_t iface, + const struct phylink_mac_ops *ops); void phylink_destroy(struct phylink *);
int phylink_connect_phy(struct phylink *, struct phy_device *); diff --combined include/net/ip_vs.h index cb1ad0cc5c7b,b36a1df93e7c..3759167f91f5 --- a/include/net/ip_vs.h +++ b/include/net/ip_vs.h @@@ -603,7 -603,6 +603,7 @@@ struct ip_vs_dest_user_kern
u16 tun_type; /* tunnel type */ __be16 tun_port; /* tunnel port */ + u16 tun_flags; /* tunnel flags */ };
@@@ -666,7 -665,6 +666,7 @@@ struct ip_vs_dest atomic_t last_weight; /* server latest weight */ __u16 tun_type; /* tunnel type */ __be16 tun_port; /* tunnel port */ + __u16 tun_flags; /* tunnel flags */
refcount_t refcnt; /* reference counter */ struct ip_vs_stats stats; /* statistics */ @@@ -810,11 -808,12 +810,12 @@@ struct ipvs_master_sync_state struct ip_vs_sync_buff *sync_buff; unsigned long sync_queue_len; unsigned int sync_queue_delay; - struct task_struct *master_thread; struct delayed_work master_wakeup_work; struct netns_ipvs *ipvs; };
+ struct ip_vs_sync_thread_data; + /* How much time to keep dests in trash */ #define IP_VS_DEST_TRASH_PERIOD (120 * HZ)
@@@ -945,7 -944,8 +946,8 @@@ struct netns_ipvs spinlock_t sync_lock; struct ipvs_master_sync_state *ms; spinlock_t sync_buff_lock; - struct task_struct **backup_threads; + struct ip_vs_sync_thread_data *master_tinfo; + struct ip_vs_sync_thread_data *backup_tinfo; int threads_mask; volatile int sync_state; struct mutex sync_mutex; @@@ -1406,9 -1406,6 +1408,9 @@@ bool ip_vs_has_real_service(struct netn struct ip_vs_dest * ip_vs_find_real_service(struct netns_ipvs *ipvs, int af, __u16 protocol, const union nf_inet_addr *daddr, __be16 dport); +struct ip_vs_dest *ip_vs_find_tunnel(struct netns_ipvs *ipvs, int af, + const union nf_inet_addr *daddr, + __be16 tun_port);
int ip_vs_use_count_inc(void); void ip_vs_use_count_dec(void); @@@ -1502,9 -1499,6 +1504,9 @@@ static inline int ip_vs_todrop(struct n static inline int ip_vs_todrop(struct netns_ipvs *ipvs) { return 0; } #endif
+#define IP_VS_DFWD_METHOD(dest) (atomic_read(&(dest)->conn_flags) & \ + IP_VS_CONN_F_FWD_MASK) + /* ip_vs_fwd_tag returns the forwarding tag of the connection */ #define IP_VS_FWD_METHOD(cp) (cp->flags & IP_VS_CONN_F_FWD_MASK)
diff --combined include/net/tls.h index 0279938386ab,889df0312cd1..176d0b039f32 --- a/include/net/tls.h +++ b/include/net/tls.h @@@ -40,7 -40,6 +40,7 @@@ #include <linux/socket.h> #include <linux/tcp.h> #include <linux/skmsg.h> +#include <linux/netdevice.h>
#include <net/tcp.h> #include <net/strparser.h> @@@ -62,7 -61,6 +62,7 @@@ #define TLS_DEVICE_NAME_MAX 32
#define MAX_IV_SIZE 16 +#define TLS_MAX_REC_SEQ_SIZE 8
/* For AES-CCM, the full 16-bytes of IV is made of '4' fields of given sizes. * @@@ -199,24 -197,20 +199,24 @@@ struct tls_offload_context_tx
struct scatterlist sg_tx_data[MAX_SKB_FRAGS]; void (*sk_destruct)(struct sock *sk); - u8 driver_state[]; + u8 driver_state[] __aligned(8); /* The TLS layer reserves room for driver specific state * Currently the belief is that there is not enough * driver specific state to justify another layer of indirection */ -#define TLS_DRIVER_STATE_SIZE (max_t(size_t, 8, sizeof(void *))) +#define TLS_DRIVER_STATE_SIZE_TX 16 };
#define TLS_OFFLOAD_CONTEXT_SIZE_TX \ - (ALIGN(sizeof(struct tls_offload_context_tx), sizeof(void *)) + \ - TLS_DRIVER_STATE_SIZE) + (sizeof(struct tls_offload_context_tx) + TLS_DRIVER_STATE_SIZE_TX)
enum tls_context_flags { TLS_RX_SYNC_RUNNING = 0, + /* Unlike RX where resync is driven entirely by the core in TX only + * the driver knows when things went out of sync, so we need the flag + * to be atomic. + */ + TLS_TX_SYNC_SCHED = 1, };
struct cipher_context { @@@ -246,32 -240,34 +246,32 @@@ struct tls_prot_info };
struct tls_context { + /* read-only cache line */ struct tls_prot_info prot_info;
- union tls_crypto_context crypto_send; - union tls_crypto_context crypto_recv; + u8 tx_conf:3; + u8 rx_conf:3;
- struct list_head list; - struct net_device *netdev; - refcount_t refcount; + int (*push_pending_record)(struct sock *sk, int flags); + void (*sk_write_space)(struct sock *sk);
void *priv_ctx_tx; void *priv_ctx_rx;
- u8 tx_conf:3; - u8 rx_conf:3; + struct net_device *netdev;
+ /* rw cache line */ struct cipher_context tx; struct cipher_context rx;
struct scatterlist *partially_sent_record; u16 partially_sent_offset;
- unsigned long flags; bool in_tcp_sendpages; bool pending_open_record_frags; + unsigned long flags;
- int (*push_pending_record)(struct sock *sk, int flags); - - void (*sk_write_space)(struct sock *sk); + /* cache cold stuff */ void (*sk_destruct)(struct sock *sk); void (*sk_proto_close)(struct sock *sk, long timeout);
@@@ -283,12 -279,6 +283,12 @@@ int __user *optlen); int (*hash)(struct sock *sk); void (*unhash)(struct sock *sk); + + union tls_crypto_context crypto_send; + union tls_crypto_context crypto_recv; + + struct list_head list; + refcount_t refcount; };
enum tls_offload_ctx_dir { @@@ -304,49 -294,26 +304,50 @@@ struct tlsdev_ops void (*tls_dev_del)(struct net_device *netdev, struct tls_context *ctx, enum tls_offload_ctx_dir direction); - void (*tls_dev_resync_rx)(struct net_device *netdev, - struct sock *sk, u32 seq, u64 rcd_sn); + void (*tls_dev_resync)(struct net_device *netdev, + struct sock *sk, u32 seq, u8 *rcd_sn, + enum tls_offload_ctx_dir direction); };
+enum tls_offload_sync_type { + TLS_OFFLOAD_SYNC_TYPE_DRIVER_REQ = 0, + TLS_OFFLOAD_SYNC_TYPE_CORE_NEXT_HINT = 1, +}; + +#define TLS_DEVICE_RESYNC_NH_START_IVAL 2 +#define TLS_DEVICE_RESYNC_NH_MAX_IVAL 128 + struct tls_offload_context_rx { /* sw must be the first member of tls_offload_context_rx */ struct tls_sw_context_rx sw; - atomic64_t resync_req; - u8 driver_state[]; + enum tls_offload_sync_type resync_type; + /* this member is set regardless of resync_type, to avoid branches */ + u8 resync_nh_reset:1; + /* CORE_NEXT_HINT-only member, but use the hole here */ + u8 resync_nh_do_now:1; + union { + /* TLS_OFFLOAD_SYNC_TYPE_DRIVER_REQ */ + struct { + atomic64_t resync_req; + }; + /* TLS_OFFLOAD_SYNC_TYPE_CORE_NEXT_HINT */ + struct { + u32 decrypted_failed; + u32 decrypted_tgt; + } resync_nh; + }; + u8 driver_state[] __aligned(8); /* The TLS layer reserves room for driver specific state * Currently the belief is that there is not enough * driver specific state to justify another layer of indirection */ +#define TLS_DRIVER_STATE_SIZE_RX 8 };
#define TLS_OFFLOAD_CONTEXT_SIZE_RX \ - (ALIGN(sizeof(struct tls_offload_context_rx), sizeof(void *)) + \ - TLS_DRIVER_STATE_SIZE) + (sizeof(struct tls_offload_context_rx) + TLS_DRIVER_STATE_SIZE_RX)
+ void tls_ctx_free(struct tls_context *ctx); int wait_on_pending_writer(struct sock *sk, long *timeo); int tls_sk_query(struct sock *sk, int optname, char __user *optval, int __user *optlen); @@@ -465,15 -432,19 +466,15 @@@ static inline struct tls_context *tls_g }
static inline void tls_advance_record_sn(struct sock *sk, - struct cipher_context *ctx, - int version) + struct tls_prot_info *prot, + struct cipher_context *ctx) { - struct tls_context *tls_ctx = tls_get_ctx(sk); - struct tls_prot_info *prot = &tls_ctx->prot_info; - if (tls_bigint_increment(ctx->rec_seq, prot->rec_seq_size)) tls_err_abort(sk, EBADMSG);
- if (version != TLS_1_3_VERSION) { + if (prot->version != TLS_1_3_VERSION) tls_bigint_increment(ctx->iv + TLS_CIPHER_AES_GCM_128_SALT_SIZE, prot->iv_size); - } }
static inline void tls_fill_prepend(struct tls_context *ctx, @@@ -575,23 -546,6 +576,23 @@@ tls_offload_ctx_rx(const struct tls_con return (struct tls_offload_context_rx *)tls_ctx->priv_ctx_rx; }
+#if IS_ENABLED(CONFIG_TLS_DEVICE) +static inline void *__tls_driver_ctx(struct tls_context *tls_ctx, + enum tls_offload_ctx_dir direction) +{ + if (direction == TLS_OFFLOAD_CTX_DIR_TX) + return tls_offload_ctx_tx(tls_ctx)->driver_state; + else + return tls_offload_ctx_rx(tls_ctx)->driver_state; +} + +static inline void * +tls_driver_ctx(const struct sock *sk, enum tls_offload_ctx_dir direction) +{ + return __tls_driver_ctx(tls_get_ctx(sk), direction); +} +#endif + /* The TLS context is valid until sk_destruct is called */ static inline void tls_offload_rx_resync_request(struct sock *sk, __be32 seq) { @@@ -601,31 -555,6 +602,31 @@@ atomic64_set(&rx_ctx->resync_req, ((u64)ntohl(seq) << 32) | 1); }
+static inline void +tls_offload_rx_resync_set_type(struct sock *sk, enum tls_offload_sync_type type) +{ + struct tls_context *tls_ctx = tls_get_ctx(sk); + + tls_offload_ctx_rx(tls_ctx)->resync_type = type; +} + +static inline void tls_offload_tx_resync_request(struct sock *sk) +{ + struct tls_context *tls_ctx = tls_get_ctx(sk); + + WARN_ON(test_and_set_bit(TLS_TX_SYNC_SCHED, &tls_ctx->flags)); +} + +/* Driver's seq tracking has to be disabled until resync succeeded */ +static inline bool tls_offload_tx_resync_pending(struct sock *sk) +{ + struct tls_context *tls_ctx = tls_get_ctx(sk); + bool ret; + + ret = test_bit(TLS_TX_SYNC_SCHED, &tls_ctx->flags); + smp_mb__after_atomic(); + return ret; +}
int tls_proccess_cmsg(struct sock *sk, struct msghdr *msg, unsigned char *record_type); @@@ -634,7 -563,6 +635,7 @@@ void tls_unregister_device(struct tls_d int tls_device_decrypted(struct sock *sk, struct sk_buff *skb); int decrypt_skb(struct sock *sk, struct sk_buff *skb, struct scatterlist *sgout); +struct sk_buff *tls_encrypt_skb(struct sk_buff *skb);
struct sk_buff *tls_validate_xmit_skb(struct sock *sk, struct net_device *dev, @@@ -647,6 -575,6 +648,6 @@@ int tls_sw_fallback_init(struct sock *s int tls_set_device_offload_rx(struct sock *sk, struct tls_context *ctx);
void tls_device_offload_cleanup_rx(struct sock *sk); -void handle_device_resync(struct sock *sk, u32 seq, u64 rcd_sn); +void tls_device_rx_resync_new_rec(struct sock *sk, u32 rcd_len, u32 seq);
#endif /* _TLS_OFFLOAD_H */ diff --combined include/net/xdp_sock.h index de4e3a353df3,7da155164947..69796d264f06 --- a/include/net/xdp_sock.h +++ b/include/net/xdp_sock.h @@@ -58,17 -58,20 +58,22 @@@ struct xdp_sock struct xdp_umem *umem; struct list_head flush_node; u16 queue_id; - struct xsk_queue *tx ____cacheline_aligned_in_smp; - struct list_head list; bool zc; + enum { + XSK_READY = 0, + XSK_BOUND, + XSK_UNBOUND, + } state; /* Protects multiple processes in the control path */ struct mutex mutex; + struct xsk_queue *tx ____cacheline_aligned_in_smp; + struct list_head list; /* Mutual exclusion of NAPI TX thread and sendmsg error paths * in the SKB destructor callback. */ spinlock_t tx_completion_lock; + /* Protects generic receive. */ + spinlock_t rx_lock; u64 rx_dropped; };
@@@ -79,11 -82,10 +84,11 @@@ int xsk_rcv(struct xdp_sock *xs, struc void xsk_flush(struct xdp_sock *xs); bool xsk_is_setup_for_bpf_map(struct xdp_sock *xs); /* Used from netdev driver */ +bool xsk_umem_has_addrs(struct xdp_umem *umem, u32 cnt); u64 *xsk_umem_peek_addr(struct xdp_umem *umem, u64 *addr); void xsk_umem_discard_addr(struct xdp_umem *umem); void xsk_umem_complete_tx(struct xdp_umem *umem, u32 nb_entries); -bool xsk_umem_consume_tx(struct xdp_umem *umem, dma_addr_t *dma, u32 *len); +bool xsk_umem_consume_tx(struct xdp_umem *umem, struct xdp_desc *desc); void xsk_umem_consume_tx_done(struct xdp_umem *umem); struct xdp_umem_fq_reuse *xsk_reuseq_prepare(u32 nentries); struct xdp_umem_fq_reuse *xsk_reuseq_swap(struct xdp_umem *umem, @@@ -102,16 -104,6 +107,16 @@@ static inline dma_addr_t xdp_umem_get_d }
/* Reuse-queue aware version of FILL queue helpers */ +static inline bool xsk_umem_has_addrs_rq(struct xdp_umem *umem, u32 cnt) +{ + struct xdp_umem_fq_reuse *rq = umem->fq_reuse; + + if (rq->length >= cnt) + return true; + + return xsk_umem_has_addrs(umem, cnt - rq->length); +} + static inline u64 *xsk_umem_peek_addr_rq(struct xdp_umem *umem, u64 *addr) { struct xdp_umem_fq_reuse *rq = umem->fq_reuse; @@@ -159,11 -151,6 +164,11 @@@ static inline bool xsk_is_setup_for_bpf return false; }
+static inline bool xsk_umem_has_addrs(struct xdp_umem *umem, u32 cnt) +{ + return false; +} + static inline u64 *xsk_umem_peek_addr(struct xdp_umem *umem, u64 *addr) { return NULL; @@@ -177,8 -164,8 +182,8 @@@ static inline void xsk_umem_complete_tx { }
-static inline bool xsk_umem_consume_tx(struct xdp_umem *umem, dma_addr_t *dma, - u32 *len) +static inline bool xsk_umem_consume_tx(struct xdp_umem *umem, + struct xdp_desc *desc) { return false; } @@@ -218,11 -205,6 +223,11 @@@ static inline dma_addr_t xdp_umem_get_d return 0; }
+static inline bool xsk_umem_has_addrs_rq(struct xdp_umem *umem, u32 cnt) +{ + return false; +} + static inline u64 *xsk_umem_peek_addr_rq(struct xdp_umem *umem, u64 *addr) { return NULL; diff --combined include/uapi/linux/bpf.h index c318385aba51,29a5bc3d5c66..5695ab53e354 --- a/include/uapi/linux/bpf.h +++ b/include/uapi/linux/bpf.h @@@ -170,7 -170,6 +170,7 @@@ enum bpf_prog_type BPF_PROG_TYPE_FLOW_DISSECTOR, BPF_PROG_TYPE_CGROUP_SYSCTL, BPF_PROG_TYPE_RAW_TRACEPOINT_WRITABLE, + BPF_PROG_TYPE_CGROUP_SOCKOPT, };
enum bpf_attach_type { @@@ -195,8 -194,6 +195,8 @@@ BPF_CGROUP_SYSCTL, BPF_CGROUP_UDP4_RECVMSG, BPF_CGROUP_UDP6_RECVMSG, + BPF_CGROUP_GETSOCKOPT, + BPF_CGROUP_SETSOCKOPT, __MAX_BPF_ATTACH_TYPE };
@@@ -265,24 -262,6 +265,24 @@@ */ #define BPF_F_ANY_ALIGNMENT (1U << 1)
+/* BPF_F_TEST_RND_HI32 is used in BPF_PROG_LOAD command for testing purpose. + * Verifier does sub-register def/use analysis and identifies instructions whose + * def only matters for low 32-bit, high 32-bit is never referenced later + * through implicit zero extension. Therefore verifier notifies JIT back-ends + * that it is safe to ignore clearing high 32-bit for these instructions. This + * saves some back-ends a lot of code-gen. However such optimization is not + * necessary on some arches, for example x86_64, arm64 etc, whose JIT back-ends + * hence hasn't used verifier's analysis result. But, we really want to have a + * way to be able to verify the correctness of the described optimization on + * x86_64 on which testsuites are frequently exercised. + * + * So, this flag is introduced. Once it is set, verifier will randomize high + * 32-bit for those instructions who has been identified as safe to ignore them. + * Then, if verifier is not doing correct analysis, such randomization will + * regress tests to expose bugs. + */ +#define BPF_F_TEST_RND_HI32 (1U << 2) + /* When BPF ldimm64's insn[0].src_reg != 0 then this can have * two extensions: * @@@ -1571,11 -1550,8 +1571,11 @@@ union bpf_attr * but this is only implemented for native XDP (with driver * support) as of this writing). * - * All values for *flags* are reserved for future usage, and must - * be left at zero. + * The lower two bits of *flags* are used as the return code if + * the map lookup fails. This is so that the return value can be + * one of the XDP program return codes up to XDP_TX, as chosen by + * the caller. Any higher bits in the *flags* argument must be + * unset. * * When used to redirect packets to net devices, this helper * provides a high performance increase over **bpf_redirect**\ (). @@@ -1770,7 -1746,6 +1770,7 @@@ * * **BPF_SOCK_OPS_RTO_CB_FLAG** (retransmission time out) * * **BPF_SOCK_OPS_RETRANS_CB_FLAG** (retransmission) * * **BPF_SOCK_OPS_STATE_CB_FLAG** (TCP state change) + * * **BPF_SOCK_OPS_RTT_CB_FLAG** (every RTT) * * Therefore, this function can be used to clear a callback flag by * setting the appropriate bit to zero. e.g. to disable the RTO @@@ -2699,20 -2674,6 +2699,20 @@@ * 0 on success. * * **-ENOENT** if the bpf-local-storage cannot be found. + * + * int bpf_send_signal(u32 sig) + * Description + * Send signal *sig* to the current task. + * Return + * 0 on success or successfully queued. + * + * **-EBUSY** if work queue under nmi is full. + * + * **-EINVAL** if *sig* is invalid. + * + * **-EPERM** if no permission to send the *sig*. + * + * **-EAGAIN** if bpf program can try again. */ #define __BPF_FUNC_MAPPER(FN) \ FN(unspec), \ @@@ -2823,8 -2784,7 +2823,8 @@@ FN(strtol), \ FN(strtoul), \ FN(sk_storage_get), \ - FN(sk_storage_delete), + FN(sk_storage_delete), \ + FN(send_signal),
/* integer value in 'imm' field of BPF_CALL instruction selects which helper * function eBPF program intends to call @@@ -3073,12 -3033,6 +3073,12 @@@ struct bpf_tcp_sock * sum(delta(snd_una)), or how many bytes * were acked. */ + __u32 dsack_dups; /* RFC4898 tcpEStatsStackDSACKDups + * total number of DSACK blocks received + */ + __u32 delivered; /* Total data packets delivered incl. rexmits */ + __u32 delivered_ce; /* Like the above but only ECE marked packets */ + __u32 icsk_retransmits; /* Number of unrecovered [RTO] timeouts */ };
struct bpf_sock_tuple { @@@ -3098,10 -3052,6 +3098,10 @@@ }; };
+struct bpf_xdp_sock { + __u32 queue_id; +}; + #define XDP_PACKET_HEADROOM 256
/* User return codes for XDP prog type. @@@ -3193,6 -3143,7 +3193,7 @@@ struct bpf_prog_info char name[BPF_OBJ_NAME_LEN]; __u32 ifindex; __u32 gpl_compatible:1; + __u32 :31; /* alignment pad */ __u64 netns_dev; __u64 netns_ino; __u32 nr_jited_ksyms; @@@ -3247,7 -3198,7 +3248,7 @@@ struct bpf_sock_addr __u32 user_ip4; /* Allows 1,2,4-byte read and 4-byte write. * Stored in network byte order. */ - __u32 user_ip6[4]; /* Allows 1,2,4-byte read an 4-byte write. + __u32 user_ip6[4]; /* Allows 1,2,4-byte read and 4,8-byte write. * Stored in network byte order. */ __u32 user_port; /* Allows 4-byte read and write. @@@ -3256,13 -3207,12 +3257,13 @@@ __u32 family; /* Allows 4-byte read, but no write */ __u32 type; /* Allows 4-byte read, but no write */ __u32 protocol; /* Allows 4-byte read, but no write */ - __u32 msg_src_ip4; /* Allows 1,2,4-byte read an 4-byte write. + __u32 msg_src_ip4; /* Allows 1,2,4-byte read and 4-byte write. * Stored in network byte order. */ - __u32 msg_src_ip6[4]; /* Allows 1,2,4-byte read an 4-byte write. + __u32 msg_src_ip6[4]; /* Allows 1,2,4-byte read and 4,8-byte write. * Stored in network byte order. */ + __bpf_md_ptr(struct bpf_sock *, sk); };
/* User bpf_sock_ops struct to access socket values and specify request ops @@@ -3314,15 -3264,13 +3315,15 @@@ struct bpf_sock_ops __u32 sk_txhash; __u64 bytes_received; __u64 bytes_acked; + __bpf_md_ptr(struct bpf_sock *, sk); };
/* Definitions for bpf_sock_ops_cb_flags */ #define BPF_SOCK_OPS_RTO_CB_FLAG (1<<0) #define BPF_SOCK_OPS_RETRANS_CB_FLAG (1<<1) #define BPF_SOCK_OPS_STATE_CB_FLAG (1<<2) -#define BPF_SOCK_OPS_ALL_CB_FLAGS 0x7 /* Mask of all currently +#define BPF_SOCK_OPS_RTT_CB_FLAG (1<<3) +#define BPF_SOCK_OPS_ALL_CB_FLAGS 0xF /* Mask of all currently * supported cb flags */
@@@ -3377,8 -3325,6 +3378,8 @@@ enum BPF_SOCK_OPS_TCP_LISTEN_CB, /* Called on listen(2), right after * socket transition to LISTEN state. */ + BPF_SOCK_OPS_RTT_CB, /* Called on every RTT. + */ };
/* List of TCP states. There is a build check in net/ipv4/tcp.c to detect @@@ -3557,15 -3503,4 +3558,15 @@@ struct bpf_sysctl */ };
+struct bpf_sockopt { + __bpf_md_ptr(struct bpf_sock *, sk); + __bpf_md_ptr(void *, optval); + __bpf_md_ptr(void *, optval_end); + + __s32 level; + __s32 optname; + __s32 optlen; + __s32 retval; +}; + #endif /* _UAPI__LINUX_BPF_H__ */ diff --combined include/uapi/linux/nl80211.h index 8fc3a43cac75,fa7ebbc6ff27..75758ec26c8b --- a/include/uapi/linux/nl80211.h +++ b/include/uapi/linux/nl80211.h @@@ -235,15 -235,6 +235,15 @@@ */
/** + * DOC: SAE authentication offload + * + * By setting @NL80211_EXT_FEATURE_SAE_OFFLOAD flag drivers can indicate they + * support offloading SAE authentication for WPA3-Personal networks. In + * %NL80211_CMD_CONNECT the password for SAE should be specified using + * %NL80211_ATTR_SAE_PASSWORD. + */ + +/** * enum nl80211_commands - supported nl80211 commands * * @NL80211_CMD_UNSPEC: unspecified command to catch errors @@@ -2350,12 -2341,6 +2350,12 @@@ enum nl80211_commands * should be picking up the lowest tx power, either tx power per-interface * or per-station. * + * @NL80211_ATTR_SAE_PASSWORD: attribute for passing SAE password material. It + * is used with %NL80211_CMD_CONNECT to provide password for offloading + * SAE authentication for WPA3-Personal networks. + * + * @NL80211_ATTR_TWT_RESPONDER: Enable target wait time responder support. + * * @NUM_NL80211_ATTR: total number of nl80211_attrs available * @NL80211_ATTR_MAX: highest attribute number currently defined * @__NL80211_ATTR_AFTER_LAST: internal use @@@ -2809,10 -2794,6 +2809,10 @@@ enum nl80211_attrs NL80211_ATTR_STA_TX_POWER_SETTING, NL80211_ATTR_STA_TX_POWER,
+ NL80211_ATTR_SAE_PASSWORD, + + NL80211_ATTR_TWT_RESPONDER, + /* add attributes here, update the policy in nl80211.c */
__NL80211_ATTR_AFTER_LAST, @@@ -4425,7 -4406,6 +4425,7 @@@ enum nl80211_mfp enum nl80211_wpa_versions { NL80211_WPA_VERSION_1 = 1 << 0, NL80211_WPA_VERSION_2 = 1 << 1, + NL80211_WPA_VERSION_3 = 1 << 2, };
/** @@@ -5334,7 -5314,7 +5334,7 @@@ enum nl80211_feature_flags NL80211_FEATURE_TDLS_CHANNEL_SWITCH = 1 << 28, NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR = 1 << 29, NL80211_FEATURE_SCHED_SCAN_RANDOM_MAC_ADDR = 1 << 30, - NL80211_FEATURE_ND_RANDOM_MAC_ADDR = 1 << 31, + NL80211_FEATURE_ND_RANDOM_MAC_ADDR = 1U << 31, };
/** @@@ -5442,9 -5422,6 +5442,9 @@@ * @NL80211_EXT_FEATURE_STA_TX_PWR: This driver supports controlling tx power * to a station. * + * @NL80211_EXT_FEATURE_SAE_OFFLOAD: Device wants to do SAE authentication in + * station mode (SAE password is passed as part of the connect command). + * * @NUM_NL80211_EXT_FEATURES: number of extended features. * @MAX_NL80211_EXT_FEATURES: highest extended feature index. */ @@@ -5489,7 -5466,6 +5489,7 @@@ enum nl80211_ext_feature_index NL80211_EXT_FEATURE_SCHED_SCAN_BAND_SPECIFIC_RSSI_THOLD, NL80211_EXT_FEATURE_EXT_KEY_ID, NL80211_EXT_FEATURE_STA_TX_PWR, + NL80211_EXT_FEATURE_SAE_OFFLOAD,
/* add new features before the definition below */ NUM_NL80211_EXT_FEATURES, diff --combined kernel/bpf/core.c index e2c1b43728da,f2148db91439..16079550db6d --- a/kernel/bpf/core.c +++ b/kernel/bpf/core.c @@@ -1364,10 -1364,10 +1364,10 @@@ select_insn insn++; CONT; ALU_ARSH_X: - DST = (u64) (u32) ((*(s32 *) &DST) >> SRC); + DST = (u64) (u32) (((s32) DST) >> SRC); CONT; ALU_ARSH_K: - DST = (u64) (u32) ((*(s32 *) &DST) >> IMM); + DST = (u64) (u32) (((s32) DST) >> IMM); CONT; ALU64_ARSH_X: (*(s64 *) &DST) >>= SRC; @@@ -1791,42 -1791,38 +1791,42 @@@ struct bpf_prog_array *bpf_prog_array_a return &empty_prog_array.hdr; }
-void bpf_prog_array_free(struct bpf_prog_array __rcu *progs) +void bpf_prog_array_free(struct bpf_prog_array *progs) { - if (!progs || - progs == (struct bpf_prog_array __rcu *)&empty_prog_array.hdr) + if (!progs || progs == &empty_prog_array.hdr) return; kfree_rcu(progs, rcu); }
-int bpf_prog_array_length(struct bpf_prog_array __rcu *array) +int bpf_prog_array_length(struct bpf_prog_array *array) { struct bpf_prog_array_item *item; u32 cnt = 0;
- rcu_read_lock(); - item = rcu_dereference(array)->items; - for (; item->prog; item++) + for (item = array->items; item->prog; item++) if (item->prog != &dummy_bpf_prog.prog) cnt++; - rcu_read_unlock(); return cnt; }
+bool bpf_prog_array_is_empty(struct bpf_prog_array *array) +{ + struct bpf_prog_array_item *item; + + for (item = array->items; item->prog; item++) + if (item->prog != &dummy_bpf_prog.prog) + return false; + return true; +}
-static bool bpf_prog_array_copy_core(struct bpf_prog_array __rcu *array, +static bool bpf_prog_array_copy_core(struct bpf_prog_array *array, u32 *prog_ids, u32 request_cnt) { struct bpf_prog_array_item *item; int i = 0;
- item = rcu_dereference_check(array, 1)->items; - for (; item->prog; item++) { + for (item = array->items; item->prog; item++) { if (item->prog == &dummy_bpf_prog.prog) continue; prog_ids[i] = item->prog->aux->id; @@@ -1839,7 -1835,7 +1839,7 @@@ return !!(item->prog); }
-int bpf_prog_array_copy_to_user(struct bpf_prog_array __rcu *array, +int bpf_prog_array_copy_to_user(struct bpf_prog_array *array, __u32 __user *prog_ids, u32 cnt) { unsigned long err = 0; @@@ -1850,12 -1846,18 +1850,12 @@@ * cnt = bpf_prog_array_length(); * if (cnt > 0) * bpf_prog_array_copy_to_user(..., cnt); - * so below kcalloc doesn't need extra cnt > 0 check, but - * bpf_prog_array_length() releases rcu lock and - * prog array could have been swapped with empty or larger array, - * so always copy 'cnt' prog_ids to the user. - * In a rare race the user will see zero prog_ids + * so below kcalloc doesn't need extra cnt > 0 check. */ ids = kcalloc(cnt, sizeof(u32), GFP_USER | __GFP_NOWARN); if (!ids) return -ENOMEM; - rcu_read_lock(); nospc = bpf_prog_array_copy_core(array, ids, cnt); - rcu_read_unlock(); err = copy_to_user(prog_ids, ids, cnt * sizeof(u32)); kfree(ids); if (err) @@@ -1865,19 -1867,19 +1865,19 @@@ return 0; }
-void bpf_prog_array_delete_safe(struct bpf_prog_array __rcu *array, +void bpf_prog_array_delete_safe(struct bpf_prog_array *array, struct bpf_prog *old_prog) { - struct bpf_prog_array_item *item = array->items; + struct bpf_prog_array_item *item;
- for (; item->prog; item++) + for (item = array->items; item->prog; item++) if (item->prog == old_prog) { WRITE_ONCE(item->prog, &dummy_bpf_prog.prog); break; } }
-int bpf_prog_array_copy(struct bpf_prog_array __rcu *old_array, +int bpf_prog_array_copy(struct bpf_prog_array *old_array, struct bpf_prog *exclude_prog, struct bpf_prog *include_prog, struct bpf_prog_array **new_array) @@@ -1941,7 -1943,7 +1941,7 @@@ return 0; }
-int bpf_prog_array_copy_info(struct bpf_prog_array __rcu *array, +int bpf_prog_array_copy_info(struct bpf_prog_array *array, u32 *prog_ids, u32 request_cnt, u32 *prog_cnt) { @@@ -2084,15 -2086,6 +2084,15 @@@ bool __weak bpf_helper_changes_pkt_data return false; }
+/* Return TRUE if the JIT backend wants verifier to enable sub-register usage + * analysis code and wants explicit zero extension inserted by verifier. + * Otherwise, return FALSE. + */ +bool __weak bpf_jit_needs_zext(void) +{ + return false; +} + /* To execute LD_ABS/LD_IND instructions __bpf_prog_run() may call * skb_copy_bits(), so provide a weak definition of it for NET-less config. */ @@@ -2110,4 -2103,3 +2110,4 @@@ EXPORT_SYMBOL(bpf_stats_enabled_key) #include <linux/bpf_trace.h>
EXPORT_TRACEPOINT_SYMBOL_GPL(xdp_exception); +EXPORT_TRACEPOINT_SYMBOL_GPL(xdp_bulk_tx); diff --combined net/batman-adv/hard-interface.c index b5465e6e380d,3719cfd026f0..c90e47342bb0 --- a/net/batman-adv/hard-interface.c +++ b/net/batman-adv/hard-interface.c @@@ -16,7 -16,6 +16,7 @@@ #include <linux/if_ether.h> #include <linux/kernel.h> #include <linux/kref.h> +#include <linux/limits.h> #include <linux/list.h> #include <linux/netdevice.h> #include <linux/printk.h> @@@ -796,6 -795,9 +796,9 @@@ int batadv_hardif_enable_interface(stru
batadv_hardif_recalc_extra_skbroom(soft_iface);
+ if (bat_priv->algo_ops->iface.enabled) + bat_priv->algo_ops->iface.enabled(hard_iface); + out: return 0;
@@@ -921,7 -923,9 +924,7 @@@ batadv_hardif_add_interface(struct net_ hard_iface->soft_iface = NULL; hard_iface->if_status = BATADV_IF_NOT_IN_USE;
- ret = batadv_debugfs_add_hardif(hard_iface); - if (ret) - goto free_sysfs; + batadv_debugfs_add_hardif(hard_iface);
INIT_LIST_HEAD(&hard_iface->list); INIT_HLIST_HEAD(&hard_iface->neigh_list); @@@ -943,6 -947,8 +946,6 @@@
return hard_iface;
-free_sysfs: - batadv_sysfs_del_hardif(&hard_iface->hardif_obj); free_if: kfree(hard_iface); release_dev: diff --combined net/batman-adv/types.h index c2996296b953,e0b25104cbfa..6ae139d74e0f --- a/net/batman-adv/types.h +++ b/net/batman-adv/types.h @@@ -14,22 -14,20 +14,22 @@@ #include <linux/average.h> #include <linux/bitops.h> #include <linux/compiler.h> +#include <linux/if.h> #include <linux/if_ether.h> #include <linux/kref.h> #include <linux/netdevice.h> #include <linux/netlink.h> #include <linux/sched.h> /* for linux/wait.h */ +#include <linux/seq_file.h> +#include <linux/skbuff.h> #include <linux/spinlock.h> +#include <linux/timer.h> #include <linux/types.h> #include <linux/wait.h> #include <linux/workqueue.h> #include <uapi/linux/batadv_packet.h> #include <uapi/linux/batman_adv.h>
-struct seq_file; - #ifdef CONFIG_BATMAN_ADV_DAT
/** @@@ -404,17 -402,6 +404,17 @@@ struct batadv_orig_node * list */ struct hlist_node mcast_want_all_ipv6_node; + + /** + * @mcast_want_all_rtr4_node: a list node for the mcast.want_all_rtr4 + * list + */ + struct hlist_node mcast_want_all_rtr4_node; + /** + * @mcast_want_all_rtr6_node: a list node for the mcast.want_all_rtr6 + * list + */ + struct hlist_node mcast_want_all_rtr6_node; #endif
/** @capabilities: announced capabilities of this originator */ @@@ -1182,26 -1169,6 +1182,26 @@@ struct batadv_mcast_querier_state };
/** + * struct batadv_mcast_mla_flags - flags for the querier, bridge and tvlv state + */ +struct batadv_mcast_mla_flags { + /** @querier_ipv4: the current state of an IGMP querier in the mesh */ + struct batadv_mcast_querier_state querier_ipv4; + + /** @querier_ipv6: the current state of an MLD querier in the mesh */ + struct batadv_mcast_querier_state querier_ipv6; + + /** @enabled: whether the multicast tvlv is currently enabled */ + unsigned char enabled:1; + + /** @bridged: whether the soft interface has a bridge on top */ + unsigned char bridged:1; + + /** @tvlv_flags: the flags we have last sent in our mcast tvlv */ + u8 tvlv_flags; +}; + +/** * struct batadv_priv_mcast - per mesh interface mcast data */ struct batadv_priv_mcast { @@@ -1229,22 -1196,20 +1229,22 @@@ */ struct hlist_head want_all_ipv6_list;
- /** @querier_ipv4: the current state of an IGMP querier in the mesh */ - struct batadv_mcast_querier_state querier_ipv4; - - /** @querier_ipv6: the current state of an MLD querier in the mesh */ - struct batadv_mcast_querier_state querier_ipv6; - - /** @flags: the flags we have last sent in our mcast tvlv */ - u8 flags; + /** + * @want_all_rtr4_list: a list of orig_nodes wanting all routable IPv4 + * multicast traffic + */ + struct hlist_head want_all_rtr4_list;
- /** @enabled: whether the multicast tvlv is currently enabled */ - unsigned char enabled:1; + /** + * @want_all_rtr6_list: a list of orig_nodes wanting all routable IPv6 + * multicast traffic + */ + struct hlist_head want_all_rtr6_list;
- /** @bridged: whether the soft interface has a bridge on top */ - unsigned char bridged:1; + /** + * @mla_flags: flags for the querier, bridge and tvlv state + */ + struct batadv_mcast_mla_flags mla_flags;
/** * @mla_lock: a lock protecting mla_list and mla_flags @@@ -1263,12 -1228,6 +1263,12 @@@ /** @num_want_all_ipv6: counter for items in want_all_ipv6_list */ atomic_t num_want_all_ipv6;
+ /** @num_want_all_rtr4: counter for items in want_all_rtr4_list */ + atomic_t num_want_all_rtr4; + + /** @num_want_all_rtr6: counter for items in want_all_rtr6_list */ + atomic_t num_want_all_rtr6; + /** * @want_lists_lock: lock for protecting modifications to mcasts * want_all_{unsnoopables,ipv4,ipv6}_list (traversals are rcu-locked) @@@ -2170,6 -2129,9 +2170,9 @@@ struct batadv_algo_iface_ops /** @enable: init routing info when hard-interface is enabled */ int (*enable)(struct batadv_hard_iface *hard_iface);
+ /** @enabled: notification when hard-interface was enabled (optional) */ + void (*enabled)(struct batadv_hard_iface *hard_iface); + /** @disable: de-init routing info when hard-interface is disabled */ void (*disable)(struct batadv_hard_iface *hard_iface);
diff --combined net/bridge/br_input.c index 512383d5e53f,52c712984cc7..09b1dd8cd853 --- a/net/bridge/br_input.c +++ b/net/bridge/br_input.c @@@ -74,7 -74,6 +74,6 @@@ int br_handle_frame_finish(struct net * struct net_bridge_fdb_entry *dst = NULL; struct net_bridge_mdb_entry *mdst; bool local_rcv, mcast_hit = false; - const unsigned char *dest; struct net_bridge *br; u16 vid = 0;
@@@ -92,10 -91,9 +91,9 @@@ br_fdb_update(br, p, eth_hdr(skb)->h_source, vid, false);
local_rcv = !!(br->dev->flags & IFF_PROMISC); - dest = eth_hdr(skb)->h_dest; - if (is_multicast_ether_addr(dest)) { + if (is_multicast_ether_addr(eth_hdr(skb)->h_dest)) { /* by definition the broadcast is also a multicast address */ - if (is_broadcast_ether_addr(dest)) { + if (is_broadcast_ether_addr(eth_hdr(skb)->h_dest)) { pkt_type = BR_PKT_BROADCAST; local_rcv = true; } else { @@@ -145,7 -143,7 +143,7 @@@ } break; case BR_PKT_UNICAST: - dst = br_fdb_find_rcu(br, dest, vid); + dst = br_fdb_find_rcu(br, eth_hdr(skb)->h_dest, vid); default: break; } @@@ -234,7 -232,7 +232,7 @@@ static int nf_hook_bridge_pre(struct sk kfree_skb(skb); return RX_HANDLER_CONSUMED; case NF_QUEUE: - ret = nf_queue(skb, &state, e, i, verdict); + ret = nf_queue(skb, &state, i, verdict); if (ret == 1) continue; return RX_HANDLER_CONSUMED; diff --combined net/core/filter.c index 4481e950f020,3fdf1b21be36..47f6386fb17a --- a/net/core/filter.c +++ b/net/core/filter.c @@@ -62,7 -62,6 +62,7 @@@ #include <net/inet_hashtables.h> #include <net/inet6_hashtables.h> #include <net/ip_fib.h> +#include <net/nexthop.h> #include <net/flow.h> #include <net/arp.h> #include <net/ipv6.h> @@@ -2158,8 -2157,8 +2158,8 @@@ BPF_CALL_2(bpf_redirect, u32, ifindex, if (unlikely(flags & ~(BPF_F_INGRESS))) return TC_ACT_SHOT;
- ri->ifindex = ifindex; ri->flags = flags; + ri->tgt_index = ifindex;
return TC_ACT_REDIRECT; } @@@ -2169,8 -2168,8 +2169,8 @@@ int skb_do_redirect(struct sk_buff *skb struct bpf_redirect_info *ri = this_cpu_ptr(&bpf_redirect_info); struct net_device *dev;
- dev = dev_get_by_index_rcu(dev_net(skb->dev), ri->ifindex); - ri->ifindex = 0; + dev = dev_get_by_index_rcu(dev_net(skb->dev), ri->tgt_index); + ri->tgt_index = 0; if (unlikely(!dev)) { kfree_skb(skb); return -EINVAL; @@@ -3488,11 -3487,11 +3488,11 @@@ xdp_do_redirect_slow(struct net_device struct bpf_prog *xdp_prog, struct bpf_redirect_info *ri) { struct net_device *fwd; - u32 index = ri->ifindex; + u32 index = ri->tgt_index; int err;
fwd = dev_get_by_index_rcu(dev_net(dev), index); - ri->ifindex = 0; + ri->tgt_index = 0; if (unlikely(!fwd)) { err = -EINVAL; goto err; @@@ -3523,6 -3522,7 +3523,6 @@@ static int __bpf_tx_xdp_map(struct net_ err = dev_map_enqueue(dst, xdp, dev_rx); if (unlikely(err)) return err; - __dev_map_insert_ctx(map, index); break; } case BPF_MAP_TYPE_CPUMAP: { @@@ -3531,6 -3531,7 +3531,6 @@@ err = cpu_map_enqueue(rcpu, xdp, dev_rx); if (unlikely(err)) return err; - __cpu_map_insert_ctx(map, index); break; } case BPF_MAP_TYPE_XSKMAP: { @@@ -3604,14 -3605,18 +3604,14 @@@ static int xdp_do_redirect_map(struct n struct bpf_prog *xdp_prog, struct bpf_map *map, struct bpf_redirect_info *ri) { - u32 index = ri->ifindex; - void *fwd = NULL; + u32 index = ri->tgt_index; + void *fwd = ri->tgt_value; int err;
- ri->ifindex = 0; + ri->tgt_index = 0; + ri->tgt_value = NULL; WRITE_ONCE(ri->map, NULL);
- fwd = __xdp_map_lookup_elem(map, index); - if (unlikely(!fwd)) { - err = -EINVAL; - goto err; - } if (ri->map_to_flush && unlikely(ri->map_to_flush != map)) xdp_do_flush_map();
@@@ -3647,14 -3652,19 +3647,14 @@@ static int xdp_do_generic_redirect_map( struct bpf_map *map) { struct bpf_redirect_info *ri = this_cpu_ptr(&bpf_redirect_info); - u32 index = ri->ifindex; - void *fwd = NULL; + u32 index = ri->tgt_index; + void *fwd = ri->tgt_value; int err = 0;
- ri->ifindex = 0; + ri->tgt_index = 0; + ri->tgt_value = NULL; WRITE_ONCE(ri->map, NULL);
- fwd = __xdp_map_lookup_elem(map, index); - if (unlikely(!fwd)) { - err = -EINVAL; - goto err; - } - if (map->map_type == BPF_MAP_TYPE_DEVMAP) { struct bpf_dtab_netdev *dst = fwd;
@@@ -3686,14 -3696,14 +3686,14 @@@ int xdp_do_generic_redirect(struct net_ { struct bpf_redirect_info *ri = this_cpu_ptr(&bpf_redirect_info); struct bpf_map *map = READ_ONCE(ri->map); - u32 index = ri->ifindex; + u32 index = ri->tgt_index; struct net_device *fwd; int err = 0;
if (map) return xdp_do_generic_redirect_map(dev, skb, xdp, xdp_prog, map); - ri->ifindex = 0; + ri->tgt_index = 0; fwd = dev_get_by_index_rcu(dev_net(dev), index); if (unlikely(!fwd)) { err = -EINVAL; @@@ -3721,9 -3731,8 +3721,9 @@@ BPF_CALL_2(bpf_xdp_redirect, u32, ifind if (unlikely(flags)) return XDP_ABORTED;
- ri->ifindex = ifindex; ri->flags = flags; + ri->tgt_index = ifindex; + ri->tgt_value = NULL; WRITE_ONCE(ri->map, NULL);
return XDP_REDIRECT; @@@ -3742,23 -3751,11 +3742,23 @@@ BPF_CALL_3(bpf_xdp_redirect_map, struc { struct bpf_redirect_info *ri = this_cpu_ptr(&bpf_redirect_info);
- if (unlikely(flags)) + /* Lower bits of the flags are used as return code on lookup failure */ + if (unlikely(flags > XDP_TX)) return XDP_ABORTED;
- ri->ifindex = ifindex; + ri->tgt_value = __xdp_map_lookup_elem(map, ifindex); + if (unlikely(!ri->tgt_value)) { + /* If the lookup fails we want to clear out the state in the + * redirect_info struct completely, so that if an eBPF program + * performs multiple lookups, the last one always takes + * precedence. + */ + WRITE_ONCE(ri->map, NULL); + return flags; + } + ri->flags = flags; + ri->tgt_index = ifindex; WRITE_ONCE(ri->map, map);
return XDP_REDIRECT; @@@ -4673,7 -4670,7 +4673,7 @@@ static int bpf_ipv4_fib_lookup(struct n if (res.type != RTN_UNICAST) return BPF_FIB_LKUP_RET_NOT_FWDED;
- if (res.fi->fib_nhs > 1) + if (fib_info_num_path(res.fi) > 1) fib_select_path(net, &res, &fl4, NULL);
if (check_mtu) { @@@ -4740,7 -4737,7 +4740,7 @@@ static int bpf_ipv6_fib_lookup(struct n return -ENODEV;
idev = __in6_dev_get_safely(dev); - if (unlikely(!idev || !net->ipv6.devconf_all->forwarding)) + if (unlikely(!idev || !idev->cnf.forwarding)) return BPF_FIB_LKUP_RET_FWD_DISABLED;
if (flags & BPF_FIB_LOOKUP_OUTPUT) { @@@ -5194,6 -5191,54 +5194,6 @@@ static const struct bpf_func_proto bpf_ }; #endif /* CONFIG_IPV6_SEG6_BPF */
-#define CONVERT_COMMON_TCP_SOCK_FIELDS(md_type, CONVERT) \ -do { \ - switch (si->off) { \ - case offsetof(md_type, snd_cwnd): \ - CONVERT(snd_cwnd); break; \ - case offsetof(md_type, srtt_us): \ - CONVERT(srtt_us); break; \ - case offsetof(md_type, snd_ssthresh): \ - CONVERT(snd_ssthresh); break; \ - case offsetof(md_type, rcv_nxt): \ - CONVERT(rcv_nxt); break; \ - case offsetof(md_type, snd_nxt): \ - CONVERT(snd_nxt); break; \ - case offsetof(md_type, snd_una): \ - CONVERT(snd_una); break; \ - case offsetof(md_type, mss_cache): \ - CONVERT(mss_cache); break; \ - case offsetof(md_type, ecn_flags): \ - CONVERT(ecn_flags); break; \ - case offsetof(md_type, rate_delivered): \ - CONVERT(rate_delivered); break; \ - case offsetof(md_type, rate_interval_us): \ - CONVERT(rate_interval_us); break; \ - case offsetof(md_type, packets_out): \ - CONVERT(packets_out); break; \ - case offsetof(md_type, retrans_out): \ - CONVERT(retrans_out); break; \ - case offsetof(md_type, total_retrans): \ - CONVERT(total_retrans); break; \ - case offsetof(md_type, segs_in): \ - CONVERT(segs_in); break; \ - case offsetof(md_type, data_segs_in): \ - CONVERT(data_segs_in); break; \ - case offsetof(md_type, segs_out): \ - CONVERT(segs_out); break; \ - case offsetof(md_type, data_segs_out): \ - CONVERT(data_segs_out); break; \ - case offsetof(md_type, lost_out): \ - CONVERT(lost_out); break; \ - case offsetof(md_type, sacked_out): \ - CONVERT(sacked_out); break; \ - case offsetof(md_type, bytes_received): \ - CONVERT(bytes_received); break; \ - case offsetof(md_type, bytes_acked): \ - CONVERT(bytes_acked); break; \ - } \ -} while (0) - #ifdef CONFIG_INET static struct sock *sk_lookup(struct net *net, struct bpf_sock_tuple *tuple, int dif, int sdif, u8 family, u8 proto) @@@ -5544,8 -5589,7 +5544,8 @@@ static const struct bpf_func_proto bpf_ bool bpf_tcp_sock_is_valid_access(int off, int size, enum bpf_access_type type, struct bpf_insn_access_aux *info) { - if (off < 0 || off >= offsetofend(struct bpf_tcp_sock, bytes_acked)) + if (off < 0 || off >= offsetofend(struct bpf_tcp_sock, + icsk_retransmits)) return false;
if (off % size != 0) @@@ -5576,19 -5620,8 +5576,19 @@@ u32 bpf_tcp_sock_convert_ctx_access(enu offsetof(struct tcp_sock, FIELD)); \ } while (0)
- CONVERT_COMMON_TCP_SOCK_FIELDS(struct bpf_tcp_sock, - BPF_TCP_SOCK_GET_COMMON); +#define BPF_INET_SOCK_GET_COMMON(FIELD) \ + do { \ + BUILD_BUG_ON(FIELD_SIZEOF(struct inet_connection_sock, \ + FIELD) > \ + FIELD_SIZEOF(struct bpf_tcp_sock, FIELD)); \ + *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF( \ + struct inet_connection_sock, \ + FIELD), \ + si->dst_reg, si->src_reg, \ + offsetof( \ + struct inet_connection_sock, \ + FIELD)); \ + } while (0)
if (insn > insn_buf) return insn - insn_buf; @@@ -5604,81 -5637,6 +5604,81 @@@ offsetof(struct tcp_sock, rtt_min) + offsetof(struct minmax_sample, v)); break; + case offsetof(struct bpf_tcp_sock, snd_cwnd): + BPF_TCP_SOCK_GET_COMMON(snd_cwnd); + break; + case offsetof(struct bpf_tcp_sock, srtt_us): + BPF_TCP_SOCK_GET_COMMON(srtt_us); + break; + case offsetof(struct bpf_tcp_sock, snd_ssthresh): + BPF_TCP_SOCK_GET_COMMON(snd_ssthresh); + break; + case offsetof(struct bpf_tcp_sock, rcv_nxt): + BPF_TCP_SOCK_GET_COMMON(rcv_nxt); + break; + case offsetof(struct bpf_tcp_sock, snd_nxt): + BPF_TCP_SOCK_GET_COMMON(snd_nxt); + break; + case offsetof(struct bpf_tcp_sock, snd_una): + BPF_TCP_SOCK_GET_COMMON(snd_una); + break; + case offsetof(struct bpf_tcp_sock, mss_cache): + BPF_TCP_SOCK_GET_COMMON(mss_cache); + break; + case offsetof(struct bpf_tcp_sock, ecn_flags): + BPF_TCP_SOCK_GET_COMMON(ecn_flags); + break; + case offsetof(struct bpf_tcp_sock, rate_delivered): + BPF_TCP_SOCK_GET_COMMON(rate_delivered); + break; + case offsetof(struct bpf_tcp_sock, rate_interval_us): + BPF_TCP_SOCK_GET_COMMON(rate_interval_us); + break; + case offsetof(struct bpf_tcp_sock, packets_out): + BPF_TCP_SOCK_GET_COMMON(packets_out); + break; + case offsetof(struct bpf_tcp_sock, retrans_out): + BPF_TCP_SOCK_GET_COMMON(retrans_out); + break; + case offsetof(struct bpf_tcp_sock, total_retrans): + BPF_TCP_SOCK_GET_COMMON(total_retrans); + break; + case offsetof(struct bpf_tcp_sock, segs_in): + BPF_TCP_SOCK_GET_COMMON(segs_in); + break; + case offsetof(struct bpf_tcp_sock, data_segs_in): + BPF_TCP_SOCK_GET_COMMON(data_segs_in); + break; + case offsetof(struct bpf_tcp_sock, segs_out): + BPF_TCP_SOCK_GET_COMMON(segs_out); + break; + case offsetof(struct bpf_tcp_sock, data_segs_out): + BPF_TCP_SOCK_GET_COMMON(data_segs_out); + break; + case offsetof(struct bpf_tcp_sock, lost_out): + BPF_TCP_SOCK_GET_COMMON(lost_out); + break; + case offsetof(struct bpf_tcp_sock, sacked_out): + BPF_TCP_SOCK_GET_COMMON(sacked_out); + break; + case offsetof(struct bpf_tcp_sock, bytes_received): + BPF_TCP_SOCK_GET_COMMON(bytes_received); + break; + case offsetof(struct bpf_tcp_sock, bytes_acked): + BPF_TCP_SOCK_GET_COMMON(bytes_acked); + break; + case offsetof(struct bpf_tcp_sock, dsack_dups): + BPF_TCP_SOCK_GET_COMMON(dsack_dups); + break; + case offsetof(struct bpf_tcp_sock, delivered): + BPF_TCP_SOCK_GET_COMMON(delivered); + break; + case offsetof(struct bpf_tcp_sock, delivered_ce): + BPF_TCP_SOCK_GET_COMMON(delivered_ce); + break; + case offsetof(struct bpf_tcp_sock, icsk_retransmits): + BPF_INET_SOCK_GET_COMMON(icsk_retransmits); + break; }
return insn - insn_buf; @@@ -5692,7 -5650,7 +5692,7 @@@ BPF_CALL_1(bpf_tcp_sock, struct sock * return (unsigned long)NULL; }
-static const struct bpf_func_proto bpf_tcp_sock_proto = { +const struct bpf_func_proto bpf_tcp_sock_proto = { .func = bpf_tcp_sock, .gpl_only = false, .ret_type = RET_PTR_TO_TCP_SOCK_OR_NULL, @@@ -5736,46 -5694,6 +5736,46 @@@ BPF_CALL_1(bpf_skb_ecn_set_ce, struct s return INET_ECN_set_ce(skb); }
+bool bpf_xdp_sock_is_valid_access(int off, int size, enum bpf_access_type type, + struct bpf_insn_access_aux *info) +{ + if (off < 0 || off >= offsetofend(struct bpf_xdp_sock, queue_id)) + return false; + + if (off % size != 0) + return false; + + switch (off) { + default: + return size == sizeof(__u32); + } +} + +u32 bpf_xdp_sock_convert_ctx_access(enum bpf_access_type type, + const struct bpf_insn *si, + struct bpf_insn *insn_buf, + struct bpf_prog *prog, u32 *target_size) +{ + struct bpf_insn *insn = insn_buf; + +#define BPF_XDP_SOCK_GET(FIELD) \ + do { \ + BUILD_BUG_ON(FIELD_SIZEOF(struct xdp_sock, FIELD) > \ + FIELD_SIZEOF(struct bpf_xdp_sock, FIELD)); \ + *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(struct xdp_sock, FIELD),\ + si->dst_reg, si->src_reg, \ + offsetof(struct xdp_sock, FIELD)); \ + } while (0) + + switch (si->off) { + case offsetof(struct bpf_xdp_sock, queue_id): + BPF_XDP_SOCK_GET(queue_id); + break; + } + + return insn - insn_buf; +} + static const struct bpf_func_proto bpf_skb_ecn_set_ce_proto = { .func = bpf_skb_ecn_set_ce, .gpl_only = false, @@@ -5978,10 -5896,6 +5978,10 @@@ sock_addr_func_proto(enum bpf_func_id f case BPF_FUNC_skc_lookup_tcp: return &bpf_sock_addr_skc_lookup_tcp_proto; #endif /* CONFIG_INET */ + case BPF_FUNC_sk_storage_get: + return &bpf_sk_storage_get_proto; + case BPF_FUNC_sk_storage_delete: + return &bpf_sk_storage_delete_proto; default: return bpf_base_func_proto(func_id); } @@@ -6019,10 -5933,6 +6019,10 @@@ cg_skb_func_proto(enum bpf_func_id func return &bpf_sk_storage_get_proto; case BPF_FUNC_sk_storage_delete: return &bpf_sk_storage_delete_proto; +#ifdef CONFIG_SOCK_CGROUP_DATA + case BPF_FUNC_skb_cgroup_id: + return &bpf_skb_cgroup_id_proto; +#endif #ifdef CONFIG_INET case BPF_FUNC_tcp_sock: return &bpf_tcp_sock_proto; @@@ -6203,14 -6113,6 +6203,14 @@@ sock_ops_func_proto(enum bpf_func_id fu return &bpf_get_local_storage_proto; case BPF_FUNC_perf_event_output: return &bpf_sockopt_event_output_proto; + case BPF_FUNC_sk_storage_get: + return &bpf_sk_storage_get_proto; + case BPF_FUNC_sk_storage_delete: + return &bpf_sk_storage_delete_proto; +#ifdef CONFIG_INET + case BPF_FUNC_tcp_sock: + return &bpf_tcp_sock_proto; +#endif /* CONFIG_INET */ default: return bpf_base_func_proto(func_id); } @@@ -6890,16 -6792,6 +6890,16 @@@ static bool sock_addr_is_valid_access(i if (!bpf_ctx_narrow_access_ok(off, size, size_default)) return false; } else { + if (bpf_ctx_wide_store_ok(off, size, + struct bpf_sock_addr, + user_ip6)) + return true; + + if (bpf_ctx_wide_store_ok(off, size, + struct bpf_sock_addr, + msg_src_ip6)) + return true; + if (size != size_default) return false; } @@@ -6908,13 -6800,6 +6908,13 @@@ if (size != size_default) return false; break; + case offsetof(struct bpf_sock_addr, sk): + if (type != BPF_READ) + return false; + if (size != sizeof(__u64)) + return false; + info->reg_type = PTR_TO_SOCKET; + break; default: if (type == BPF_READ) { if (size != size_default) @@@ -6958,11 -6843,6 +6958,11 @@@ static bool sock_ops_is_valid_access(in if (size != sizeof(__u64)) return false; break; + case offsetof(struct bpf_sock_ops, sk): + if (size != sizeof(__u64)) + return false; + info->reg_type = PTR_TO_SOCKET_OR_NULL; + break; default: if (size != size_default) return false; @@@ -7740,6 -7620,9 +7740,6 @@@ static u32 xdp_convert_ctx_access(enum /* SOCK_ADDR_STORE_NESTED_FIELD_OFF() has semantic similar to * SOCK_ADDR_LOAD_NESTED_FIELD_SIZE_OFF() but for store operation. * - * It doesn't support SIZE argument though since narrow stores are not - * supported for now. - * * In addition it uses Temporary Field TF (member of struct S) as the 3rd * "register" since two registers available in convert_ctx_access are not * enough: we can't override neither SRC, since it contains value to store, nor @@@ -7747,7 -7630,7 +7747,7 @@@ * instructions. But we need a temporary place to save pointer to nested * structure whose field we want to store to. */ -#define SOCK_ADDR_STORE_NESTED_FIELD_OFF(S, NS, F, NF, OFF, TF) \ +#define SOCK_ADDR_STORE_NESTED_FIELD_OFF(S, NS, F, NF, SIZE, OFF, TF) \ do { \ int tmp_reg = BPF_REG_9; \ if (si->src_reg == tmp_reg || si->dst_reg == tmp_reg) \ @@@ -7758,7 -7641,8 +7758,7 @@@ offsetof(S, TF)); \ *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(S, F), tmp_reg, \ si->dst_reg, offsetof(S, F)); \ - *insn++ = BPF_STX_MEM( \ - BPF_FIELD_SIZEOF(NS, NF), tmp_reg, si->src_reg, \ + *insn++ = BPF_STX_MEM(SIZE, tmp_reg, si->src_reg, \ bpf_target_off(NS, NF, FIELD_SIZEOF(NS, NF), \ target_size) \ + OFF); \ @@@ -7770,8 -7654,8 +7770,8 @@@ TF) \ do { \ if (type == BPF_WRITE) { \ - SOCK_ADDR_STORE_NESTED_FIELD_OFF(S, NS, F, NF, OFF, \ - TF); \ + SOCK_ADDR_STORE_NESTED_FIELD_OFF(S, NS, F, NF, SIZE, \ + OFF, TF); \ } else { \ SOCK_ADDR_LOAD_NESTED_FIELD_SIZE_OFF( \ S, NS, F, NF, SIZE, OFF); \ @@@ -7866,11 -7750,6 +7866,11 @@@ static u32 sock_addr_convert_ctx_access struct bpf_sock_addr_kern, struct in6_addr, t_ctx, s6_addr32[0], BPF_SIZE(si->code), off, tmp_reg); break; + case offsetof(struct bpf_sock_addr, sk): + *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(struct bpf_sock_addr_kern, sk), + si->dst_reg, si->src_reg, + offsetof(struct bpf_sock_addr_kern, sk)); + break; }
return insn - insn_buf; @@@ -7958,6 -7837,9 +7958,6 @@@ static u32 sock_ops_convert_ctx_access( SOCK_OPS_GET_FIELD(BPF_FIELD, OBJ_FIELD, OBJ); \ } while (0)
- CONVERT_COMMON_TCP_SOCK_FIELDS(struct bpf_sock_ops, - SOCK_OPS_GET_TCP_SOCK_FIELD); - if (insn > insn_buf) return insn - insn_buf;
@@@ -8127,82 -8009,6 +8127,82 @@@ SOCK_OPS_GET_OR_SET_FIELD(sk_txhash, sk_txhash, struct sock, type); break; + case offsetof(struct bpf_sock_ops, snd_cwnd): + SOCK_OPS_GET_TCP_SOCK_FIELD(snd_cwnd); + break; + case offsetof(struct bpf_sock_ops, srtt_us): + SOCK_OPS_GET_TCP_SOCK_FIELD(srtt_us); + break; + case offsetof(struct bpf_sock_ops, snd_ssthresh): + SOCK_OPS_GET_TCP_SOCK_FIELD(snd_ssthresh); + break; + case offsetof(struct bpf_sock_ops, rcv_nxt): + SOCK_OPS_GET_TCP_SOCK_FIELD(rcv_nxt); + break; + case offsetof(struct bpf_sock_ops, snd_nxt): + SOCK_OPS_GET_TCP_SOCK_FIELD(snd_nxt); + break; + case offsetof(struct bpf_sock_ops, snd_una): + SOCK_OPS_GET_TCP_SOCK_FIELD(snd_una); + break; + case offsetof(struct bpf_sock_ops, mss_cache): + SOCK_OPS_GET_TCP_SOCK_FIELD(mss_cache); + break; + case offsetof(struct bpf_sock_ops, ecn_flags): + SOCK_OPS_GET_TCP_SOCK_FIELD(ecn_flags); + break; + case offsetof(struct bpf_sock_ops, rate_delivered): + SOCK_OPS_GET_TCP_SOCK_FIELD(rate_delivered); + break; + case offsetof(struct bpf_sock_ops, rate_interval_us): + SOCK_OPS_GET_TCP_SOCK_FIELD(rate_interval_us); + break; + case offsetof(struct bpf_sock_ops, packets_out): + SOCK_OPS_GET_TCP_SOCK_FIELD(packets_out); + break; + case offsetof(struct bpf_sock_ops, retrans_out): + SOCK_OPS_GET_TCP_SOCK_FIELD(retrans_out); + break; + case offsetof(struct bpf_sock_ops, total_retrans): + SOCK_OPS_GET_TCP_SOCK_FIELD(total_retrans); + break; + case offsetof(struct bpf_sock_ops, segs_in): + SOCK_OPS_GET_TCP_SOCK_FIELD(segs_in); + break; + case offsetof(struct bpf_sock_ops, data_segs_in): + SOCK_OPS_GET_TCP_SOCK_FIELD(data_segs_in); + break; + case offsetof(struct bpf_sock_ops, segs_out): + SOCK_OPS_GET_TCP_SOCK_FIELD(segs_out); + break; + case offsetof(struct bpf_sock_ops, data_segs_out): + SOCK_OPS_GET_TCP_SOCK_FIELD(data_segs_out); + break; + case offsetof(struct bpf_sock_ops, lost_out): + SOCK_OPS_GET_TCP_SOCK_FIELD(lost_out); + break; + case offsetof(struct bpf_sock_ops, sacked_out): + SOCK_OPS_GET_TCP_SOCK_FIELD(sacked_out); + break; + case offsetof(struct bpf_sock_ops, bytes_received): + SOCK_OPS_GET_TCP_SOCK_FIELD(bytes_received); + break; + case offsetof(struct bpf_sock_ops, bytes_acked): + SOCK_OPS_GET_TCP_SOCK_FIELD(bytes_acked); + break; + case offsetof(struct bpf_sock_ops, sk): + *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF( + struct bpf_sock_ops_kern, + is_fullsock), + si->dst_reg, si->src_reg, + offsetof(struct bpf_sock_ops_kern, + is_fullsock)); + *insn++ = BPF_JMP_IMM(BPF_JEQ, si->dst_reg, 0, 1); + *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF( + struct bpf_sock_ops_kern, sk), + si->dst_reg, si->src_reg, + offsetof(struct bpf_sock_ops_kern, sk)); + break; } return insn - insn_buf; } diff --combined net/ipv4/devinet.c index 137d1892395d,c5ebfa199794..a4b5bd4d2c89 --- a/net/ipv4/devinet.c +++ b/net/ipv4/devinet.c @@@ -62,6 -62,11 +62,11 @@@ #include <net/net_namespace.h> #include <net/addrconf.h>
+ #define IPV6ONLY_FLAGS \ + (IFA_F_NODAD | IFA_F_OPTIMISTIC | IFA_F_DADFAILED | \ + IFA_F_HOMEADDRESS | IFA_F_TENTATIVE | \ + IFA_F_MANAGETEMPADDR | IFA_F_STABLE_PRIVACY) + static struct ipv4_devconf ipv4_devconf = { .data = { [IPV4_DEVCONF_ACCEPT_REDIRECTS - 1] = 1, @@@ -190,8 -195,7 +195,8 @@@ static void rtmsg_ifa(int event, struc
static BLOCKING_NOTIFIER_HEAD(inetaddr_chain); static BLOCKING_NOTIFIER_HEAD(inetaddr_validator_chain); -static void inet_del_ifa(struct in_device *in_dev, struct in_ifaddr **ifap, +static void inet_del_ifa(struct in_device *in_dev, + struct in_ifaddr __rcu **ifap, int destroy); #ifdef CONFIG_SYSCTL static int devinet_sysctl_register(struct in_device *idev); @@@ -297,8 -301,8 +302,8 @@@ static void in_dev_rcu_put(struct rcu_h
static void inetdev_destroy(struct in_device *in_dev) { - struct in_ifaddr *ifa; struct net_device *dev; + struct in_ifaddr *ifa;
ASSERT_RTNL();
@@@ -308,7 -312,7 +313,7 @@@
ip_mc_destroy_dev(in_dev);
- while ((ifa = in_dev->ifa_list) != NULL) { + while ((ifa = rtnl_dereference(in_dev->ifa_list)) != NULL) { inet_del_ifa(in_dev, &in_dev->ifa_list, 0); inet_free_ifa(ifa); } @@@ -324,35 -328,30 +329,35 @@@
int inet_addr_onlink(struct in_device *in_dev, __be32 a, __be32 b) { + const struct in_ifaddr *ifa; + rcu_read_lock(); - for_primary_ifa(in_dev) { + in_dev_for_each_ifa_rcu(ifa, in_dev) { if (inet_ifa_match(a, ifa)) { if (!b || inet_ifa_match(b, ifa)) { rcu_read_unlock(); return 1; } } - } endfor_ifa(in_dev); + } rcu_read_unlock(); return 0; }
-static void __inet_del_ifa(struct in_device *in_dev, struct in_ifaddr **ifap, - int destroy, struct nlmsghdr *nlh, u32 portid) +static void __inet_del_ifa(struct in_device *in_dev, + struct in_ifaddr __rcu **ifap, + int destroy, struct nlmsghdr *nlh, u32 portid) { struct in_ifaddr *promote = NULL; - struct in_ifaddr *ifa, *ifa1 = *ifap; - struct in_ifaddr *last_prim = in_dev->ifa_list; + struct in_ifaddr *ifa, *ifa1; + struct in_ifaddr *last_prim; struct in_ifaddr *prev_prom = NULL; int do_promote = IN_DEV_PROMOTE_SECONDARIES(in_dev);
ASSERT_RTNL();
+ ifa1 = rtnl_dereference(*ifap); + last_prim = rtnl_dereference(in_dev->ifa_list); if (in_dev->dead) goto no_promotions;
@@@ -361,9 -360,9 +366,9 @@@ **/
if (!(ifa1->ifa_flags & IFA_F_SECONDARY)) { - struct in_ifaddr **ifap1 = &ifa1->ifa_next; + struct in_ifaddr __rcu **ifap1 = &ifa1->ifa_next;
- while ((ifa = *ifap1) != NULL) { + while ((ifa = rtnl_dereference(*ifap1)) != NULL) { if (!(ifa->ifa_flags & IFA_F_SECONDARY) && ifa1->ifa_scope <= ifa->ifa_scope) last_prim = ifa; @@@ -396,7 -395,7 +401,7 @@@ * and later to add them back with new prefsrc. Do this * while all addresses are on the device list. */ - for (ifa = promote; ifa; ifa = ifa->ifa_next) { + for (ifa = promote; ifa; ifa = rtnl_dereference(ifa->ifa_next)) { if (ifa1->ifa_mask == ifa->ifa_mask && inet_ifa_match(ifa1->ifa_address, ifa)) fib_del_ifaddr(ifa, ifa1); @@@ -422,25 -421,19 +427,25 @@@ no_promotions blocking_notifier_call_chain(&inetaddr_chain, NETDEV_DOWN, ifa1);
if (promote) { - struct in_ifaddr *next_sec = promote->ifa_next; + struct in_ifaddr *next_sec;
+ next_sec = rtnl_dereference(promote->ifa_next); if (prev_prom) { - prev_prom->ifa_next = promote->ifa_next; - promote->ifa_next = last_prim->ifa_next; - last_prim->ifa_next = promote; + struct in_ifaddr *last_sec; + + rcu_assign_pointer(prev_prom->ifa_next, next_sec); + + last_sec = rtnl_dereference(last_prim->ifa_next); + rcu_assign_pointer(promote->ifa_next, last_sec); + rcu_assign_pointer(last_prim->ifa_next, promote); }
promote->ifa_flags &= ~IFA_F_SECONDARY; rtmsg_ifa(RTM_NEWADDR, promote, nlh, portid); blocking_notifier_call_chain(&inetaddr_chain, NETDEV_UP, promote); - for (ifa = next_sec; ifa; ifa = ifa->ifa_next) { + for (ifa = next_sec; ifa; + ifa = rtnl_dereference(ifa->ifa_next)) { if (ifa1->ifa_mask != ifa->ifa_mask || !inet_ifa_match(ifa1->ifa_address, ifa)) continue; @@@ -452,8 -445,7 +457,8 @@@ inet_free_ifa(ifa1); }
-static void inet_del_ifa(struct in_device *in_dev, struct in_ifaddr **ifap, +static void inet_del_ifa(struct in_device *in_dev, + struct in_ifaddr __rcu **ifap, int destroy) { __inet_del_ifa(in_dev, ifap, destroy, NULL, 0); @@@ -466,10 -458,9 +471,10 @@@ static DECLARE_DELAYED_WORK(check_lifet static int __inet_insert_ifa(struct in_ifaddr *ifa, struct nlmsghdr *nlh, u32 portid, struct netlink_ext_ack *extack) { + struct in_ifaddr __rcu **last_primary, **ifap; struct in_device *in_dev = ifa->ifa_dev; - struct in_ifaddr *ifa1, **ifap, **last_primary; struct in_validator_info ivi; + struct in_ifaddr *ifa1; int ret;
ASSERT_RTNL(); @@@ -482,10 -473,11 +487,13 @@@ ifa->ifa_flags &= ~IFA_F_SECONDARY; last_primary = &in_dev->ifa_list;
+ /* Don't set IPv6 only flags to IPv4 addresses */ + ifa->ifa_flags &= ~IPV6ONLY_FLAGS; + - for (ifap = &in_dev->ifa_list; (ifa1 = *ifap) != NULL; - ifap = &ifa1->ifa_next) { + ifap = &in_dev->ifa_list; + ifa1 = rtnl_dereference(*ifap); + + while (ifa1) { if (!(ifa1->ifa_flags & IFA_F_SECONDARY) && ifa->ifa_scope <= ifa1->ifa_scope) last_primary = &ifa1->ifa_next; @@@ -501,9 -493,6 +509,9 @@@ } ifa->ifa_flags |= IFA_F_SECONDARY; } + + ifap = &ifa1->ifa_next; + ifa1 = rtnl_dereference(*ifap); }
/* Allow any devices that wish to register ifaddr validtors to weigh @@@ -529,8 -518,8 +537,8 @@@ ifap = last_primary; }
- ifa->ifa_next = *ifap; - *ifap = ifa; + rcu_assign_pointer(ifa->ifa_next, *ifap); + rcu_assign_pointer(*ifap, ifa);
inet_hash_insert(dev_net(in_dev->dev), ifa);
@@@ -595,14 -584,12 +603,14 @@@ EXPORT_SYMBOL(inetdev_by_index) struct in_ifaddr *inet_ifa_byprefix(struct in_device *in_dev, __be32 prefix, __be32 mask) { + struct in_ifaddr *ifa; + ASSERT_RTNL();
- for_primary_ifa(in_dev) { + in_dev_for_each_ifa_rtnl(ifa, in_dev) { if (ifa->ifa_mask == mask && inet_ifa_match(prefix, ifa)) return ifa; - } endfor_ifa(in_dev); + } return NULL; }
@@@ -630,12 -617,10 +638,12 @@@ static int inet_rtm_deladdr(struct sk_b struct netlink_ext_ack *extack) { struct net *net = sock_net(skb->sk); + struct in_ifaddr __rcu **ifap; struct nlattr *tb[IFA_MAX+1]; struct in_device *in_dev; struct ifaddrmsg *ifm; - struct in_ifaddr *ifa, **ifap; + struct in_ifaddr *ifa; + int err = -EINVAL;
ASSERT_RTNL(); @@@ -652,7 -637,7 +660,7 @@@ goto errout; }
- for (ifap = &in_dev->ifa_list; (ifa = *ifap) != NULL; + for (ifap = &in_dev->ifa_list; (ifa = rtnl_dereference(*ifap)) != NULL; ifap = &ifa->ifa_next) { if (tb[IFA_LOCAL] && ifa->ifa_local != nla_get_in_addr(tb[IFA_LOCAL])) @@@ -740,19 -725,15 +748,19 @@@ static void check_lifetime(struct work_
if (ifa->ifa_valid_lft != INFINITY_LIFE_TIME && age >= ifa->ifa_valid_lft) { - struct in_ifaddr **ifap; + struct in_ifaddr __rcu **ifap; + struct in_ifaddr *tmp;
- for (ifap = &ifa->ifa_dev->ifa_list; - *ifap != NULL; ifap = &(*ifap)->ifa_next) { - if (*ifap == ifa) { + ifap = &ifa->ifa_dev->ifa_list; + tmp = rtnl_dereference(*ifap); + while (tmp) { + if (tmp == ifa) { inet_del_ifa(ifa->ifa_dev, ifap, 1); break; } + ifap = &tmp->ifa_next; + tmp = rtnl_dereference(*ifap); } } else if (ifa->ifa_preferred_lft != INFINITY_LIFE_TIME && @@@ -896,12 -877,13 +904,12 @@@ errout static struct in_ifaddr *find_matching_ifa(struct in_ifaddr *ifa) { struct in_device *in_dev = ifa->ifa_dev; - struct in_ifaddr *ifa1, **ifap; + struct in_ifaddr *ifa1;
if (!ifa->ifa_local) return NULL;
- for (ifap = &in_dev->ifa_list; (ifa1 = *ifap) != NULL; - ifap = &ifa1->ifa_next) { + in_dev_for_each_ifa_rtnl(ifa1, in_dev) { if (ifa1->ifa_mask == ifa->ifa_mask && inet_ifa_match(ifa1->ifa_address, ifa) && ifa1->ifa_local == ifa->ifa_local) @@@ -996,8 -978,8 +1004,8 @@@ int devinet_ioctl(struct net *net, unsi { struct sockaddr_in sin_orig; struct sockaddr_in *sin = (struct sockaddr_in *)&ifr->ifr_addr; + struct in_ifaddr __rcu **ifap = NULL; struct in_device *in_dev; - struct in_ifaddr **ifap = NULL; struct in_ifaddr *ifa = NULL; struct net_device *dev; char *colon; @@@ -1068,9 -1050,7 +1076,9 @@@ /* note: we only do this for a limited set of ioctls and only if the original address family was AF_INET. This is checked above. */ - for (ifap = &in_dev->ifa_list; (ifa = *ifap) != NULL; + + for (ifap = &in_dev->ifa_list; + (ifa = rtnl_dereference(*ifap)) != NULL; ifap = &ifa->ifa_next) { if (!strcmp(ifr->ifr_name, ifa->ifa_label) && sin_orig.sin_addr.s_addr == @@@ -1083,8 -1063,7 +1091,8 @@@ 4.3BSD-style and passed in junk so we fall back to comparing just the label */ if (!ifa) { - for (ifap = &in_dev->ifa_list; (ifa = *ifap) != NULL; + for (ifap = &in_dev->ifa_list; + (ifa = rtnl_dereference(*ifap)) != NULL; ifap = &ifa->ifa_next) if (!strcmp(ifr->ifr_name, ifa->ifa_label)) break; @@@ -1233,7 -1212,7 +1241,7 @@@ out static int inet_gifconf(struct net_device *dev, char __user *buf, int len, int size) { struct in_device *in_dev = __in_dev_get_rtnl(dev); - struct in_ifaddr *ifa; + const struct in_ifaddr *ifa; struct ifreq ifr; int done = 0;
@@@ -1243,7 -1222,7 +1251,7 @@@ if (!in_dev) goto out;
- for (ifa = in_dev->ifa_list; ifa; ifa = ifa->ifa_next) { + in_dev_for_each_ifa_rtnl(ifa, in_dev) { if (!buf) { done += size; continue; @@@ -1271,24 -1250,18 +1279,24 @@@ out static __be32 in_dev_select_addr(const struct in_device *in_dev, int scope) { - for_primary_ifa(in_dev) { + const struct in_ifaddr *ifa; + + in_dev_for_each_ifa_rcu(ifa, in_dev) { + if (ifa->ifa_flags & IFA_F_SECONDARY) + continue; if (ifa->ifa_scope != RT_SCOPE_LINK && ifa->ifa_scope <= scope) return ifa->ifa_local; - } endfor_ifa(in_dev); + }
return 0; }
__be32 inet_select_addr(const struct net_device *dev, __be32 dst, int scope) { + const struct in_ifaddr *ifa; __be32 addr = 0; + unsigned char localnet_scope = RT_SCOPE_HOST; struct in_device *in_dev; struct net *net = dev_net(dev); int master_idx; @@@ -1298,13 -1271,8 +1306,13 @@@ if (!in_dev) goto no_in_dev;
- for_primary_ifa(in_dev) { - if (ifa->ifa_scope > scope) + if (unlikely(IN_DEV_ROUTE_LOCALNET(in_dev))) + localnet_scope = RT_SCOPE_LINK; + + in_dev_for_each_ifa_rcu(ifa, in_dev) { + if (ifa->ifa_flags & IFA_F_SECONDARY) + continue; + if (min(ifa->ifa_scope, localnet_scope) > scope) continue; if (!dst || inet_ifa_match(dst, ifa)) { addr = ifa->ifa_local; @@@ -1312,7 -1280,7 +1320,7 @@@ } if (!addr) addr = ifa->ifa_local; - } endfor_ifa(in_dev); + }
if (addr) goto out_unlock; @@@ -1357,20 -1325,13 +1365,20 @@@ EXPORT_SYMBOL(inet_select_addr) static __be32 confirm_addr_indev(struct in_device *in_dev, __be32 dst, __be32 local, int scope) { - int same = 0; + unsigned char localnet_scope = RT_SCOPE_HOST; + const struct in_ifaddr *ifa; __be32 addr = 0; + int same = 0; + + if (unlikely(IN_DEV_ROUTE_LOCALNET(in_dev))) + localnet_scope = RT_SCOPE_LINK; + + in_dev_for_each_ifa_rcu(ifa, in_dev) { + unsigned char min_scope = min(ifa->ifa_scope, localnet_scope);
- for_ifa(in_dev) { if (!addr && (local == ifa->ifa_local || !local) && - ifa->ifa_scope <= scope) { + min_scope <= scope) { addr = ifa->ifa_local; if (same) break; @@@ -1385,7 -1346,7 +1393,7 @@@ if (inet_ifa_match(addr, ifa)) break; /* No, then can we use new local src? */ - if (ifa->ifa_scope <= scope) { + if (min_scope <= scope) { addr = ifa->ifa_local; break; } @@@ -1393,7 -1354,7 +1401,7 @@@ same = 0; } } - } endfor_ifa(in_dev); + }
return same ? addr : 0; } @@@ -1467,7 -1428,7 +1475,7 @@@ static void inetdev_changename(struct n struct in_ifaddr *ifa; int named = 0;
- for (ifa = in_dev->ifa_list; ifa; ifa = ifa->ifa_next) { + in_dev_for_each_ifa_rtnl(ifa, in_dev) { char old[IFNAMSIZ], *dot;
memcpy(old, ifa->ifa_label, IFNAMSIZ); @@@ -1497,9 -1458,10 +1505,9 @@@ static void inetdev_send_gratuitous_arp struct in_device *in_dev)
{ - struct in_ifaddr *ifa; + const struct in_ifaddr *ifa;
- for (ifa = in_dev->ifa_list; ifa; - ifa = ifa->ifa_next) { + in_dev_for_each_ifa_rtnl(ifa, in_dev) { arp_send(ARPOP_REQUEST, ETH_P_ARP, ifa->ifa_local, dev, ifa->ifa_local, NULL, @@@ -1769,17 -1731,15 +1777,17 @@@ static int in_dev_dump_addr(struct in_d int ip_idx = 0; int err;
- for (ifa = in_dev->ifa_list; ifa; ifa = ifa->ifa_next, ip_idx++) { - if (ip_idx < s_ip_idx) + in_dev_for_each_ifa_rtnl(ifa, in_dev) { + if (ip_idx < s_ip_idx) { + ip_idx++; continue; - + } err = inet_fill_ifaddr(skb, ifa, fillargs); if (err < 0) goto done;
nl_dump_check_consistent(cb, nlmsg_hdr(skb)); + ip_idx++; } err = 0;
diff --combined net/ipv4/igmp.c index 9a206931a342,85107bf812f2..180f6896b98b --- a/net/ipv4/igmp.c +++ b/net/ipv4/igmp.c @@@ -332,15 -332,14 +332,15 @@@ static __be32 igmpv3_get_srcaddr(struc const struct flowi4 *fl4) { struct in_device *in_dev = __in_dev_get_rcu(dev); + const struct in_ifaddr *ifa;
if (!in_dev) return htonl(INADDR_ANY);
- for_ifa(in_dev) { + in_dev_for_each_ifa_rcu(ifa, in_dev) { if (fl4->saddr == ifa->ifa_local) return fl4->saddr; - } endfor_ifa(in_dev); + }
return htonl(INADDR_ANY); } @@@ -1229,12 -1228,8 +1229,8 @@@ static void igmpv3_del_delrec(struct in if (pmc) { im->interface = pmc->interface; if (im->sfmode == MCAST_INCLUDE) { - im->tomb = pmc->tomb; - pmc->tomb = NULL; - - im->sources = pmc->sources; - pmc->sources = NULL; - + swap(im->tomb, pmc->tomb); + swap(im->sources, pmc->sources); for (psf = im->sources; psf; psf = psf->sf_next) psf->sf_crcount = in_dev->mr_qrv ?: net->ipv4.sysctl_igmp_qrv; } else { diff --combined net/ipv4/route.c index abaa7f9371e5,b2b35b38724d..517300d587a7 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@@ -95,7 -95,6 +95,7 @@@ #include <net/inetpeer.h> #include <net/sock.h> #include <net/ip_fib.h> +#include <net/nexthop.h> #include <net/arp.h> #include <net/tcp.h> #include <net/icmp.h> @@@ -448,7 -447,7 +448,7 @@@ static struct neighbour *ipv4_neigh_loo n = ip_neigh_gw4(dev, pkey); }
- if (n && !refcount_inc_not_zero(&n->refcnt)) + if (!IS_ERR(n) && !refcount_inc_not_zero(&n->refcnt)) n = NULL;
rcu_read_unlock_bh(); @@@ -1532,6 -1531,7 +1532,6 @@@ static void ipv4_dst_destroy(struct dst
void rt_flush_dev(struct net_device *dev) { - struct net *net = dev_net(dev); struct rtable *rt; int cpu;
@@@ -1542,7 -1542,7 +1542,7 @@@ list_for_each_entry(rt, &ul->head, rt_uncached) { if (rt->dst.dev != dev) continue; - rt->dst.dev = net->loopback_dev; + rt->dst.dev = blackhole_netdev; dev_hold(rt->dst.dev); dev_put(dev); } @@@ -1580,7 -1580,7 +1580,7 @@@ static void rt_set_nexthop(struct rtabl ip_dst_init_metrics(&rt->dst, fi->fib_metrics);
#ifdef CONFIG_IP_ROUTE_CLASSID - { + if (nhc->nhc_family == AF_INET) { struct fib_nh *nh;
nh = container_of(nhc, struct fib_nh, nh_common); @@@ -1962,36 -1962,6 +1962,36 @@@ int fib_multipath_hash(const struct ne hash_keys.basic.ip_proto = fl4->flowi4_proto; } break; + case 2: + memset(&hash_keys, 0, sizeof(hash_keys)); + /* skb is currently provided only when forwarding */ + if (skb) { + struct flow_keys keys; + + skb_flow_dissect_flow_keys(skb, &keys, 0); + /* Inner can be v4 or v6 */ + if (keys.control.addr_type == FLOW_DISSECTOR_KEY_IPV4_ADDRS) { + hash_keys.control.addr_type = FLOW_DISSECTOR_KEY_IPV4_ADDRS; + hash_keys.addrs.v4addrs.src = keys.addrs.v4addrs.src; + hash_keys.addrs.v4addrs.dst = keys.addrs.v4addrs.dst; + } else if (keys.control.addr_type == FLOW_DISSECTOR_KEY_IPV6_ADDRS) { + hash_keys.control.addr_type = FLOW_DISSECTOR_KEY_IPV6_ADDRS; + hash_keys.addrs.v6addrs.src = keys.addrs.v6addrs.src; + hash_keys.addrs.v6addrs.dst = keys.addrs.v6addrs.dst; + hash_keys.tags.flow_label = keys.tags.flow_label; + hash_keys.basic.ip_proto = keys.basic.ip_proto; + } else { + /* Same as case 0 */ + hash_keys.control.addr_type = FLOW_DISSECTOR_KEY_IPV4_ADDRS; + ip_multipath_l3_keys(skb, &hash_keys); + } + } else { + /* Same as case 0 */ + hash_keys.control.addr_type = FLOW_DISSECTOR_KEY_IPV4_ADDRS; + hash_keys.addrs.v4addrs.src = fl4->saddr; + hash_keys.addrs.v4addrs.dst = fl4->daddr; + } + break; } mhash = flow_hash_from_keys(&hash_keys);
@@@ -2009,7 -1979,7 +2009,7 @@@ static int ip_mkroute_input(struct sk_b struct flow_keys *hkeys) { #ifdef CONFIG_IP_ROUTE_MULTIPATH - if (res->fi && res->fi->fib_nhs > 1) { + if (res->fi && fib_info_num_path(res->fi) > 1) { int h = fib_multipath_hash(res->fi->fib_net, NULL, skb, hkeys);
fib_select_multipath(res, h); @@@ -2744,7 -2714,7 +2744,7 @@@ static int rt_fill_info(struct net *net r->rtm_family = AF_INET; r->rtm_dst_len = 32; r->rtm_src_len = 0; - r->rtm_tos = fl4->flowi4_tos; + r->rtm_tos = fl4 ? fl4->flowi4_tos : 0; r->rtm_table = table_id < 256 ? table_id : RT_TABLE_COMPAT; if (nla_put_u32(skb, RTA_TABLE, table_id)) goto nla_put_failure; @@@ -2772,7 -2742,7 +2772,7 @@@ nla_put_u32(skb, RTA_FLOW, rt->dst.tclassid)) goto nla_put_failure; #endif - if (!rt_is_input_route(rt) && + if (fl4 && !rt_is_input_route(rt) && fl4->saddr != src) { if (nla_put_in_addr(skb, RTA_PREFSRC, fl4->saddr)) goto nla_put_failure; @@@ -2812,40 -2782,36 +2812,40 @@@ if (rtnetlink_put_metrics(skb, metrics) < 0) goto nla_put_failure;
- if (fl4->flowi4_mark && - nla_put_u32(skb, RTA_MARK, fl4->flowi4_mark)) - goto nla_put_failure; - - if (!uid_eq(fl4->flowi4_uid, INVALID_UID) && - nla_put_u32(skb, RTA_UID, - from_kuid_munged(current_user_ns(), fl4->flowi4_uid))) - goto nla_put_failure; + if (fl4) { + if (fl4->flowi4_mark && + nla_put_u32(skb, RTA_MARK, fl4->flowi4_mark)) + goto nla_put_failure;
- error = rt->dst.error; + if (!uid_eq(fl4->flowi4_uid, INVALID_UID) && + nla_put_u32(skb, RTA_UID, + from_kuid_munged(current_user_ns(), + fl4->flowi4_uid))) + goto nla_put_failure;
- if (rt_is_input_route(rt)) { + if (rt_is_input_route(rt)) { #ifdef CONFIG_IP_MROUTE - if (ipv4_is_multicast(dst) && !ipv4_is_local_multicast(dst) && - IPV4_DEVCONF_ALL(net, MC_FORWARDING)) { - int err = ipmr_get_route(net, skb, - fl4->saddr, fl4->daddr, - r, portid); - - if (err <= 0) { - if (err == 0) - return 0; - goto nla_put_failure; - } - } else + if (ipv4_is_multicast(dst) && + !ipv4_is_local_multicast(dst) && + IPV4_DEVCONF_ALL(net, MC_FORWARDING)) { + int err = ipmr_get_route(net, skb, + fl4->saddr, fl4->daddr, + r, portid); + + if (err <= 0) { + if (err == 0) + return 0; + goto nla_put_failure; + } + } else #endif - if (nla_put_u32(skb, RTA_IIF, fl4->flowi4_iif)) - goto nla_put_failure; + if (nla_put_u32(skb, RTA_IIF, fl4->flowi4_iif)) + goto nla_put_failure; + } }
+ error = rt->dst.error; + if (rtnl_put_cacheinfo(skb, &rt->dst, 0, expires, error) < 0) goto nla_put_failure;
@@@ -2857,80 -2823,6 +2857,80 @@@ nla_put_failure return -EMSGSIZE; }
+static int fnhe_dump_bucket(struct net *net, struct sk_buff *skb, + struct netlink_callback *cb, u32 table_id, + struct fnhe_hash_bucket *bucket, int genid, + int *fa_index, int fa_start) +{ + int i; + + for (i = 0; i < FNHE_HASH_SIZE; i++) { + struct fib_nh_exception *fnhe; + + for (fnhe = rcu_dereference(bucket[i].chain); fnhe; + fnhe = rcu_dereference(fnhe->fnhe_next)) { + struct rtable *rt; + int err; + + if (*fa_index < fa_start) + goto next; + + if (fnhe->fnhe_genid != genid) + goto next; + + if (fnhe->fnhe_expires && + time_after(jiffies, fnhe->fnhe_expires)) + goto next; + + rt = rcu_dereference(fnhe->fnhe_rth_input); + if (!rt) + rt = rcu_dereference(fnhe->fnhe_rth_output); + if (!rt) + goto next; + + err = rt_fill_info(net, fnhe->fnhe_daddr, 0, rt, + table_id, NULL, skb, + NETLINK_CB(cb->skb).portid, + cb->nlh->nlmsg_seq); + if (err) + return err; +next: + (*fa_index)++; + } + } + + return 0; +} + +int fib_dump_info_fnhe(struct sk_buff *skb, struct netlink_callback *cb, + u32 table_id, struct fib_info *fi, + int *fa_index, int fa_start) +{ + struct net *net = sock_net(cb->skb->sk); + int nhsel, genid = fnhe_genid(net); + + for (nhsel = 0; nhsel < fib_info_num_path(fi); nhsel++) { + struct fib_nh_common *nhc = fib_info_nhc(fi, nhsel); + struct fnhe_hash_bucket *bucket; + int err; + + if (nhc->nhc_flags & RTNH_F_DEAD) + continue; + + rcu_read_lock(); + bucket = rcu_dereference(nhc->nhc_exceptions); + err = 0; + if (bucket) + err = fnhe_dump_bucket(net, skb, cb, table_id, bucket, + genid, fa_index, fa_start); + rcu_read_unlock(); + if (err) + return err; + } + + return 0; +} + static struct sk_buff *inet_rtm_getroute_build_skb(__be32 src, __be32 dst, u8 ip_proto, __be16 sport, __be16 dport) @@@ -3338,11 -3230,9 +3338,11 @@@ static struct ctl_table ipv4_route_tabl { } };
+static const char ipv4_route_flush_procname[] = "flush"; + static struct ctl_table ipv4_route_flush_table[] = { { - .procname = "flush", + .procname = ipv4_route_flush_procname, .maxlen = sizeof(int), .mode = 0200, .proc_handler = ipv4_sysctl_rtcache_flush, @@@ -3360,11 -3250,9 +3360,11 @@@ static __net_init int sysctl_route_net_ if (!tbl) goto err_dup;
- /* Don't export sysctls to unprivileged users */ - if (net->user_ns != &init_user_ns) - tbl[0].procname = NULL; + /* Don't export non-whitelisted sysctls to unprivileged users */ + if (net->user_ns != &init_user_ns) { + if (tbl[0].procname != ipv4_route_flush_procname) + tbl[0].procname = NULL; + } } tbl[0].extra1 = net;
diff --combined net/ipv4/tcp.c index 47c217905864,2eebd092c3c1..7846afacdf0b --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@@ -2614,6 -2614,8 +2614,8 @@@ int tcp_disconnect(struct sock *sk, in tcp_saved_syn_free(tp); tp->compressed_ack = 0; tp->bytes_sent = 0; + tp->bytes_acked = 0; + tp->bytes_received = 0; tp->bytes_retrans = 0; tp->duplicate_sack[0].start_seq = 0; tp->duplicate_sack[0].end_seq = 0; @@@ -2741,21 -2743,6 +2743,21 @@@ static int tcp_repair_options_est(struc return 0; }
+DEFINE_STATIC_KEY_FALSE(tcp_tx_delay_enabled); +EXPORT_SYMBOL(tcp_tx_delay_enabled); + +static void tcp_enable_tx_delay(void) +{ + if (!static_branch_unlikely(&tcp_tx_delay_enabled)) { + static int __tcp_tx_delay_enabled = 0; + + if (cmpxchg(&__tcp_tx_delay_enabled, 0, 1) == 0) { + static_branch_enable(&tcp_tx_delay_enabled); + pr_info("TCP_TX_DELAY enabled\n"); + } + } +} + /* * Socket option code for TCP. */ @@@ -2806,23 -2793,15 +2808,23 @@@ static int do_tcp_setsockopt(struct soc return err; } case TCP_FASTOPEN_KEY: { - __u8 key[TCP_FASTOPEN_KEY_LENGTH]; + __u8 key[TCP_FASTOPEN_KEY_BUF_LENGTH]; + __u8 *backup_key = NULL;
- if (optlen != sizeof(key)) + /* Allow a backup key as well to facilitate key rotation + * First key is the active one. + */ + if (optlen != TCP_FASTOPEN_KEY_LENGTH && + optlen != TCP_FASTOPEN_KEY_BUF_LENGTH) return -EINVAL;
if (copy_from_user(key, optval, optlen)) return -EFAULT;
- return tcp_fastopen_reset_cipher(net, sk, key, sizeof(key)); + if (optlen == TCP_FASTOPEN_KEY_BUF_LENGTH) + backup_key = key + TCP_FASTOPEN_KEY_LENGTH; + + return tcp_fastopen_reset_cipher(net, sk, key, backup_key); } default: /* fallthru */ @@@ -3106,11 -3085,6 +3108,11 @@@ else tp->recvmsg_inq = val; break; + case TCP_TX_DELAY: + if (val) + tcp_enable_tx_delay(); + tp->tcp_tx_delay = val; + break; default: err = -ENOPROTOOPT; break; @@@ -3481,23 -3455,21 +3483,23 @@@ static int do_tcp_getsockopt(struct soc return 0;
case TCP_FASTOPEN_KEY: { - __u8 key[TCP_FASTOPEN_KEY_LENGTH]; + __u8 key[TCP_FASTOPEN_KEY_BUF_LENGTH]; struct tcp_fastopen_context *ctx; + unsigned int key_len = 0;
if (get_user(len, optlen)) return -EFAULT;
rcu_read_lock(); ctx = rcu_dereference(icsk->icsk_accept_queue.fastopenq.ctx); - if (ctx) - memcpy(key, ctx->key, sizeof(key)); - else - len = 0; + if (ctx) { + key_len = tcp_fastopen_context_len(ctx) * + TCP_FASTOPEN_KEY_LENGTH; + memcpy(&key[0], &ctx->key[0], key_len); + } rcu_read_unlock();
- len = min_t(unsigned int, len, sizeof(key)); + len = min_t(unsigned int, len, key_len); if (put_user(len, optlen)) return -EFAULT; if (copy_to_user(optval, key, len)) @@@ -3570,10 -3542,6 +3572,10 @@@ val = tp->fastopen_no_cookie; break;
+ case TCP_TX_DELAY: + val = tp->tcp_tx_delay; + break; + case TCP_TIMESTAMP: val = tcp_time_stamp_raw() + tp->tsoffset; break; diff --combined net/key/af_key.c index 39b3d95094eb,fe5fc4bab7ee..b67ed3a8486c --- a/net/key/af_key.c +++ b/net/key/af_key.c @@@ -928,7 -928,8 +928,7 @@@ static struct sk_buff *__pfkey_xfrm_sta pfkey_sockaddr_fill(&x->props.saddr, 0, (struct sockaddr *) (addr + 1), x->props.family); - if (!addr->sadb_address_prefixlen) - BUG(); + BUG_ON(!addr->sadb_address_prefixlen);
/* dst address */ addr = skb_put(skb, sizeof(struct sadb_address) + sockaddr_size); @@@ -943,7 -944,8 +943,7 @@@ pfkey_sockaddr_fill(&x->id.daddr, 0, (struct sockaddr *) (addr + 1), x->props.family); - if (!addr->sadb_address_prefixlen) - BUG(); + BUG_ON(!addr->sadb_address_prefixlen);
if (!xfrm_addr_equal(&x->sel.saddr, &x->props.saddr, x->props.family)) { @@@ -2436,8 -2438,10 +2436,10 @@@ static int key_pol_get_resp(struct soc goto out; } err = pfkey_xfrm_policy2msg(out_skb, xp, dir); - if (err < 0) + if (err < 0) { + kfree_skb(out_skb); goto out; + }
out_hdr = (struct sadb_msg *) out_skb->data; out_hdr->sadb_msg_version = hdr->sadb_msg_version; @@@ -2688,8 -2692,10 +2690,10 @@@ static int dump_sp(struct xfrm_policy * return PTR_ERR(out_skb);
err = pfkey_xfrm_policy2msg(out_skb, xp, dir); - if (err < 0) + if (err < 0) { + kfree_skb(out_skb); return err; + }
out_hdr = (struct sadb_msg *) out_skb->data; out_hdr->sadb_msg_version = pfk->dump.msg_version; diff --combined net/netfilter/ipvs/ip_vs_core.c index dd4727a5d6ec,d5103a9eb302..46f06f92ab8f --- a/net/netfilter/ipvs/ip_vs_core.c +++ b/net/netfilter/ipvs/ip_vs_core.c @@@ -34,8 -34,6 +34,8 @@@ #include <net/tcp.h> #include <net/udp.h> #include <net/icmp.h> /* for icmp_send */ +#include <net/gue.h> +#include <net/gre.h> #include <net/route.h> #include <net/ip6_checksum.h> #include <net/netns/generic.h> /* net_generic() */ @@@ -894,7 -892,7 +894,7 @@@ static int handle_response_icmp(int af if (IPPROTO_TCP == protocol || IPPROTO_UDP == protocol || IPPROTO_SCTP == protocol) offset += 2 * sizeof(__u16); - if (!skb_make_writable(skb, offset)) + if (skb_ensure_writable(skb, offset)) goto out;
#ifdef CONFIG_IP_VS_IPV6 @@@ -1284,7 -1282,7 +1284,7 @@@ handle_response(int af, struct sk_buff
IP_VS_DBG_PKT(11, af, pp, skb, iph->off, "Outgoing packet");
- if (!skb_make_writable(skb, iph->len)) + if (skb_ensure_writable(skb, iph->len)) goto drop;
/* mangle the packet */ @@@ -1576,73 -1574,6 +1576,73 @@@ ip_vs_try_to_schedule(struct netns_ipv return 1; }
+/* Check the UDP tunnel and return its header length */ +static int ipvs_udp_decap(struct netns_ipvs *ipvs, struct sk_buff *skb, + unsigned int offset, __u16 af, + const union nf_inet_addr *daddr, __u8 *proto) +{ + struct udphdr _udph, *udph; + struct ip_vs_dest *dest; + + udph = skb_header_pointer(skb, offset, sizeof(_udph), &_udph); + if (!udph) + goto unk; + offset += sizeof(struct udphdr); + dest = ip_vs_find_tunnel(ipvs, af, daddr, udph->dest); + if (!dest) + goto unk; + if (dest->tun_type == IP_VS_CONN_F_TUNNEL_TYPE_GUE) { + struct guehdr _gueh, *gueh; + + gueh = skb_header_pointer(skb, offset, sizeof(_gueh), &_gueh); + if (!gueh) + goto unk; + if (gueh->control != 0 || gueh->version != 0) + goto unk; + /* Later we can support also IPPROTO_IPV6 */ + if (gueh->proto_ctype != IPPROTO_IPIP) + goto unk; + *proto = gueh->proto_ctype; + return sizeof(struct udphdr) + sizeof(struct guehdr) + + (gueh->hlen << 2); + } + +unk: + return 0; +} + +/* Check the GRE tunnel and return its header length */ +static int ipvs_gre_decap(struct netns_ipvs *ipvs, struct sk_buff *skb, + unsigned int offset, __u16 af, + const union nf_inet_addr *daddr, __u8 *proto) +{ + struct gre_base_hdr _greh, *greh; + struct ip_vs_dest *dest; + + greh = skb_header_pointer(skb, offset, sizeof(_greh), &_greh); + if (!greh) + goto unk; + dest = ip_vs_find_tunnel(ipvs, af, daddr, 0); + if (!dest) + goto unk; + if (dest->tun_type == IP_VS_CONN_F_TUNNEL_TYPE_GRE) { + __be16 type; + + /* Only support version 0 and C (csum) */ + if ((greh->flags & ~GRE_CSUM) != 0) + goto unk; + type = greh->protocol; + /* Later we can support also IPPROTO_IPV6 */ + if (type != htons(ETH_P_IP)) + goto unk; + *proto = IPPROTO_IPIP; + return gre_calc_hlen(gre_flags_to_tnl_flags(greh->flags)); + } + +unk: + return 0; +} + /* * Handle ICMP messages in the outside-to-inside direction (incoming). * Find any that might be relevant, check against existing connections, @@@ -1662,7 -1593,6 +1662,7 @@@ ip_vs_in_icmp(struct netns_ipvs *ipvs, struct ip_vs_proto_data *pd; unsigned int offset, offset2, ihl, verdict; bool ipip, new_cp = false; + union nf_inet_addr *raddr;
*related = 1;
@@@ -1701,56 -1631,20 +1701,56 @@@ cih = skb_header_pointer(skb, offset, sizeof(_ciph), &_ciph); if (cih == NULL) return NF_ACCEPT; /* The packet looks wrong, ignore */ + raddr = (union nf_inet_addr *)&cih->daddr;
/* Special case for errors for IPIP packets */ ipip = false; if (cih->protocol == IPPROTO_IPIP) { + struct ip_vs_dest *dest; + if (unlikely(cih->frag_off & htons(IP_OFFSET))) return NF_ACCEPT; /* Error for our IPIP must arrive at LOCAL_IN */ if (!(skb_rtable(skb)->rt_flags & RTCF_LOCAL)) return NF_ACCEPT; + dest = ip_vs_find_tunnel(ipvs, AF_INET, raddr, 0); + /* Only for known tunnel */ + if (!dest || dest->tun_type != IP_VS_CONN_F_TUNNEL_TYPE_IPIP) + return NF_ACCEPT; offset += cih->ihl * 4; cih = skb_header_pointer(skb, offset, sizeof(_ciph), &_ciph); if (cih == NULL) return NF_ACCEPT; /* The packet looks wrong, ignore */ ipip = true; + } else if ((cih->protocol == IPPROTO_UDP || /* Can be UDP encap */ + cih->protocol == IPPROTO_GRE) && /* Can be GRE encap */ + /* Error for our tunnel must arrive at LOCAL_IN */ + (skb_rtable(skb)->rt_flags & RTCF_LOCAL)) { + __u8 iproto; + int ulen; + + /* Non-first fragment has no UDP header */ + if (unlikely(cih->frag_off & htons(IP_OFFSET))) + return NF_ACCEPT; + offset2 = offset + cih->ihl * 4; + if (cih->protocol == IPPROTO_UDP) + ulen = ipvs_udp_decap(ipvs, skb, offset2, AF_INET, + raddr, &iproto); + else + ulen = ipvs_gre_decap(ipvs, skb, offset2, AF_INET, + raddr, &iproto); + if (ulen > 0) { + /* Skip IP and UDP/GRE tunnel headers */ + offset = offset2 + ulen; + /* Now we should be at the original IP header */ + cih = skb_header_pointer(skb, offset, sizeof(_ciph), + &_ciph); + if (cih && cih->version == 4 && cih->ihl >= 5 && + iproto == IPPROTO_IPIP) + ipip = true; + else + return NF_ACCEPT; + } }
pd = ip_vs_proto_data_get(ipvs, cih->protocol); @@@ -2351,7 -2245,6 +2351,6 @@@ static const struct nf_hook_ops ip_vs_o static int __net_init __ip_vs_init(struct net *net) { struct netns_ipvs *ipvs; - int ret;
ipvs = net_generic(net, ip_vs_net_id); if (ipvs == NULL) @@@ -2383,17 -2276,11 +2382,11 @@@ if (ip_vs_sync_net_init(ipvs) < 0) goto sync_fail;
- ret = nf_register_net_hooks(net, ip_vs_ops, ARRAY_SIZE(ip_vs_ops)); - if (ret < 0) - goto hook_fail; - return 0; /* * Error handling */
- hook_fail: - ip_vs_sync_net_cleanup(ipvs); sync_fail: ip_vs_conn_net_cleanup(ipvs); conn_fail: @@@ -2423,6 -2310,19 +2416,19 @@@ static void __net_exit __ip_vs_cleanup( net->ipvs = NULL; }
+ static int __net_init __ip_vs_dev_init(struct net *net) + { + int ret; + + ret = nf_register_net_hooks(net, ip_vs_ops, ARRAY_SIZE(ip_vs_ops)); + if (ret < 0) + goto hook_fail; + return 0; + + hook_fail: + return ret; + } + static void __net_exit __ip_vs_dev_cleanup(struct net *net) { struct netns_ipvs *ipvs = net_ipvs(net); @@@ -2442,6 -2342,7 +2448,7 @@@ static struct pernet_operations ipvs_co };
static struct pernet_operations ipvs_core_dev_ops = { + .init = __ip_vs_dev_init, .exit = __ip_vs_dev_cleanup, };
diff --combined net/netfilter/ipvs/ip_vs_ctl.c index 998353bec74f,741d91aa4a8d..07e0967bf129 --- a/net/netfilter/ipvs/ip_vs_ctl.c +++ b/net/netfilter/ipvs/ip_vs_ctl.c @@@ -510,37 -510,15 +510,37 @@@ static inline unsigned int ip_vs_rs_has static void ip_vs_rs_hash(struct netns_ipvs *ipvs, struct ip_vs_dest *dest) { unsigned int hash; + __be16 port;
if (dest->in_rs_table) return;
+ switch (IP_VS_DFWD_METHOD(dest)) { + case IP_VS_CONN_F_MASQ: + port = dest->port; + break; + case IP_VS_CONN_F_TUNNEL: + switch (dest->tun_type) { + case IP_VS_CONN_F_TUNNEL_TYPE_GUE: + port = dest->tun_port; + break; + case IP_VS_CONN_F_TUNNEL_TYPE_IPIP: + case IP_VS_CONN_F_TUNNEL_TYPE_GRE: + port = 0; + break; + default: + return; + } + break; + default: + return; + } + /* * Hash by proto,addr,port, * which are the parameters of the real service. */ - hash = ip_vs_rs_hashkey(dest->af, &dest->addr, dest->port); + hash = ip_vs_rs_hashkey(dest->af, &dest->addr, port);
hlist_add_head_rcu(&dest->d_list, &ipvs->rs_table[hash]); dest->in_rs_table = 1; @@@ -572,8 -550,7 +572,8 @@@ bool ip_vs_has_real_service(struct netn if (dest->port == dport && dest->af == af && ip_vs_addr_equal(af, &dest->addr, daddr) && - (dest->protocol == protocol || dest->vfwmark)) { + (dest->protocol == protocol || dest->vfwmark) && + IP_VS_DFWD_METHOD(dest) == IP_VS_CONN_F_MASQ) { /* HIT */ return true; } @@@ -603,37 -580,7 +603,37 @@@ struct ip_vs_dest *ip_vs_find_real_serv if (dest->port == dport && dest->af == af && ip_vs_addr_equal(af, &dest->addr, daddr) && - (dest->protocol == protocol || dest->vfwmark)) { + (dest->protocol == protocol || dest->vfwmark) && + IP_VS_DFWD_METHOD(dest) == IP_VS_CONN_F_MASQ) { + /* HIT */ + return dest; + } + } + + return NULL; +} + +/* Find real service record by <af,addr,tun_port>. + * In case of multiple records with the same <af,addr,tun_port>, only + * the first found record is returned. + * + * To be called under RCU lock. + */ +struct ip_vs_dest *ip_vs_find_tunnel(struct netns_ipvs *ipvs, int af, + const union nf_inet_addr *daddr, + __be16 tun_port) +{ + struct ip_vs_dest *dest; + unsigned int hash; + + /* Check for "full" addressed entries */ + hash = ip_vs_rs_hashkey(af, daddr, tun_port); + + hlist_for_each_entry_rcu(dest, &ipvs->rs_table[hash], d_list) { + if (dest->tun_port == tun_port && + dest->af == af && + ip_vs_addr_equal(af, &dest->addr, daddr) && + IP_VS_DFWD_METHOD(dest) == IP_VS_CONN_F_TUNNEL) { /* HIT */ return dest; } @@@ -879,29 -826,24 +879,29 @@@ __ip_vs_update_dest(struct ip_vs_servic conn_flags = udest->conn_flags & IP_VS_CONN_F_DEST_MASK; conn_flags |= IP_VS_CONN_F_INACTIVE;
+ /* Need to rehash? */ + if ((udest->conn_flags & IP_VS_CONN_F_FWD_MASK) != + IP_VS_DFWD_METHOD(dest) || + udest->tun_type != dest->tun_type || + udest->tun_port != dest->tun_port) + ip_vs_rs_unhash(dest); + /* set the tunnel info */ dest->tun_type = udest->tun_type; dest->tun_port = udest->tun_port; + dest->tun_flags = udest->tun_flags;
/* set the IP_VS_CONN_F_NOOUTPUT flag if not masquerading/NAT */ if ((conn_flags & IP_VS_CONN_F_FWD_MASK) != IP_VS_CONN_F_MASQ) { conn_flags |= IP_VS_CONN_F_NOOUTPUT; } else { - /* - * Put the real service in rs_table if not present. - * For now only for NAT! - */ - ip_vs_rs_hash(ipvs, dest); /* FTP-NAT requires conntrack for mangling */ if (svc->port == FTPPORT) ip_vs_register_conntrack(svc); } atomic_set(&dest->conn_flags, conn_flags); + /* Put the real service in rs_table if not present. */ + ip_vs_rs_hash(ipvs, dest);
/* bind the service */ old_svc = rcu_dereference_protected(dest->svc, 1); @@@ -2454,9 -2396,7 +2454,7 @@@ do_ip_vs_set_ctl(struct sock *sk, int c cfg.syncid = dm->syncid; ret = start_sync_thread(ipvs, &cfg, dm->state); } else { - mutex_lock(&ipvs->sync_mutex); ret = stop_sync_thread(ipvs, dm->state); - mutex_unlock(&ipvs->sync_mutex); } goto out_dec; } @@@ -2964,7 -2904,6 +2962,7 @@@ static const struct nla_policy ip_vs_de [IPVS_DEST_ATTR_ADDR_FAMILY] = { .type = NLA_U16 }, [IPVS_DEST_ATTR_TUN_TYPE] = { .type = NLA_U8 }, [IPVS_DEST_ATTR_TUN_PORT] = { .type = NLA_U16 }, + [IPVS_DEST_ATTR_TUN_FLAGS] = { .type = NLA_U16 }, };
static int ip_vs_genl_fill_stats(struct sk_buff *skb, int container_type, @@@ -3271,8 -3210,6 +3269,8 @@@ static int ip_vs_genl_fill_dest(struct dest->tun_type) || nla_put_be16(skb, IPVS_DEST_ATTR_TUN_PORT, dest->tun_port) || + nla_put_u16(skb, IPVS_DEST_ATTR_TUN_FLAGS, + dest->tun_flags) || nla_put_u32(skb, IPVS_DEST_ATTR_U_THRESH, dest->u_threshold) || nla_put_u32(skb, IPVS_DEST_ATTR_L_THRESH, dest->l_threshold) || nla_put_u32(skb, IPVS_DEST_ATTR_ACTIVE_CONNS, @@@ -3393,8 -3330,7 +3391,8 @@@ static int ip_vs_genl_parse_dest(struc /* If a full entry was requested, check for the additional fields */ if (full_entry) { struct nlattr *nla_fwd, *nla_weight, *nla_u_thresh, - *nla_l_thresh, *nla_tun_type, *nla_tun_port; + *nla_l_thresh, *nla_tun_type, *nla_tun_port, + *nla_tun_flags;
nla_fwd = attrs[IPVS_DEST_ATTR_FWD_METHOD]; nla_weight = attrs[IPVS_DEST_ATTR_WEIGHT]; @@@ -3402,7 -3338,6 +3400,7 @@@ nla_l_thresh = attrs[IPVS_DEST_ATTR_L_THRESH]; nla_tun_type = attrs[IPVS_DEST_ATTR_TUN_TYPE]; nla_tun_port = attrs[IPVS_DEST_ATTR_TUN_PORT]; + nla_tun_flags = attrs[IPVS_DEST_ATTR_TUN_FLAGS];
if (!(nla_fwd && nla_weight && nla_u_thresh && nla_l_thresh)) return -EINVAL; @@@ -3418,9 -3353,6 +3416,9 @@@
if (nla_tun_port) udest->tun_port = nla_get_be16(nla_tun_port); + + if (nla_tun_flags) + udest->tun_flags = nla_get_u16(nla_tun_flags); }
return 0; @@@ -3581,10 -3513,8 +3579,8 @@@ static int ip_vs_genl_del_daemon(struc if (!attrs[IPVS_DAEMON_ATTR_STATE]) return -EINVAL;
- mutex_lock(&ipvs->sync_mutex); ret = stop_sync_thread(ipvs, nla_get_u32(attrs[IPVS_DAEMON_ATTR_STATE])); - mutex_unlock(&ipvs->sync_mutex); return ret; }
diff --combined net/netfilter/nf_nat_proto.c index 888292e8fbb2,83a24cc5753b..7ac733ebd060 --- a/net/netfilter/nf_nat_proto.c +++ b/net/netfilter/nf_nat_proto.c @@@ -70,7 -70,7 +70,7 @@@ static bool udp_manip_pkt(struct sk_buf struct udphdr *hdr; bool do_csum;
- if (!skb_make_writable(skb, hdroff + sizeof(*hdr))) + if (skb_ensure_writable(skb, hdroff + sizeof(*hdr))) return false;
hdr = (struct udphdr *)(skb->data + hdroff); @@@ -88,7 -88,7 +88,7 @@@ static bool udplite_manip_pkt(struct sk #ifdef CONFIG_NF_CT_PROTO_UDPLITE struct udphdr *hdr;
- if (!skb_make_writable(skb, hdroff + sizeof(*hdr))) + if (skb_ensure_writable(skb, hdroff + sizeof(*hdr))) return false;
hdr = (struct udphdr *)(skb->data + hdroff); @@@ -114,7 -114,7 +114,7 @@@ sctp_manip_pkt(struct sk_buff *skb if (skb->len >= hdroff + sizeof(*hdr)) hdrsize = sizeof(*hdr);
- if (!skb_make_writable(skb, hdroff + hdrsize)) + if (skb_ensure_writable(skb, hdroff + hdrsize)) return false;
hdr = (struct sctphdr *)(skb->data + hdroff); @@@ -155,7 -155,7 +155,7 @@@ tcp_manip_pkt(struct sk_buff *skb if (skb->len >= hdroff + sizeof(struct tcphdr)) hdrsize = sizeof(struct tcphdr);
- if (!skb_make_writable(skb, hdroff + hdrsize)) + if (skb_ensure_writable(skb, hdroff + hdrsize)) return false;
hdr = (struct tcphdr *)(skb->data + hdroff); @@@ -195,7 -195,7 +195,7 @@@ dccp_manip_pkt(struct sk_buff *skb if (skb->len >= hdroff + sizeof(struct dccp_hdr)) hdrsize = sizeof(struct dccp_hdr);
- if (!skb_make_writable(skb, hdroff + hdrsize)) + if (skb_ensure_writable(skb, hdroff + hdrsize)) return false;
hdr = (struct dccp_hdr *)(skb->data + hdroff); @@@ -229,7 -229,7 +229,7 @@@ icmp_manip_pkt(struct sk_buff *skb { struct icmphdr *hdr;
- if (!skb_make_writable(skb, hdroff + sizeof(*hdr))) + if (skb_ensure_writable(skb, hdroff + sizeof(*hdr))) return false;
hdr = (struct icmphdr *)(skb->data + hdroff); @@@ -247,7 -247,7 +247,7 @@@ icmpv6_manip_pkt(struct sk_buff *skb { struct icmp6hdr *hdr;
- if (!skb_make_writable(skb, hdroff + sizeof(*hdr))) + if (skb_ensure_writable(skb, hdroff + sizeof(*hdr))) return false;
hdr = (struct icmp6hdr *)(skb->data + hdroff); @@@ -275,7 -275,7 +275,7 @@@ gre_manip_pkt(struct sk_buff *skb
/* pgreh includes two optional 32bit fields which are not required * to be there. That's where the magic '8' comes from */ - if (!skb_make_writable(skb, hdroff + sizeof(*pgreh) - 8)) + if (skb_ensure_writable(skb, hdroff + sizeof(*pgreh) - 8)) return false;
greh = (void *)skb->data + hdroff; @@@ -347,7 -347,7 +347,7 @@@ static bool nf_nat_ipv4_manip_pkt(struc struct iphdr *iph; unsigned int hdroff;
- if (!skb_make_writable(skb, iphdroff + sizeof(*iph))) + if (skb_ensure_writable(skb, iphdroff + sizeof(*iph))) return false;
iph = (void *)skb->data + iphdroff; @@@ -378,7 -378,7 +378,7 @@@ static bool nf_nat_ipv6_manip_pkt(struc int hdroff; u8 nexthdr;
- if (!skb_make_writable(skb, iphdroff + sizeof(*ipv6h))) + if (skb_ensure_writable(skb, iphdroff + sizeof(*ipv6h))) return false;
ipv6h = (void *)skb->data + iphdroff; @@@ -562,9 -562,9 +562,9 @@@ int nf_nat_icmp_reply_translation(struc
WARN_ON(ctinfo != IP_CT_RELATED && ctinfo != IP_CT_RELATED_REPLY);
- if (!skb_make_writable(skb, hdrlen + sizeof(*inside))) + if (skb_ensure_writable(skb, hdrlen + sizeof(*inside))) return 0; - if (nf_ip_checksum(skb, hooknum, hdrlen, 0)) + if (nf_ip_checksum(skb, hooknum, hdrlen, IPPROTO_ICMP)) return 0;
inside = (void *)skb->data + hdrlen; @@@ -784,7 -784,7 +784,7 @@@ int nf_nat_icmpv6_reply_translation(str
WARN_ON(ctinfo != IP_CT_RELATED && ctinfo != IP_CT_RELATED_REPLY);
- if (!skb_make_writable(skb, hdrlen + sizeof(*inside))) + if (skb_ensure_writable(skb, hdrlen + sizeof(*inside))) return 0; if (nf_ip6_checksum(skb, hooknum, hdrlen, IPPROTO_ICMPV6)) return 0; diff --combined net/netfilter/nf_queue.c index c72a5bdd123f,2c440015ff0c..a2b58de82600 --- a/net/netfilter/nf_queue.c +++ b/net/netfilter/nf_queue.c @@@ -156,6 -156,7 +156,6 @@@ static void nf_ip6_saveroute(const stru }
static int __nf_queue(struct sk_buff *skb, const struct nf_hook_state *state, - const struct nf_hook_entries *entries, unsigned int index, unsigned int queuenum) { int status = -ENOENT; @@@ -189,6 -190,11 +189,11 @@@ goto err; }
+ if (!skb_dst_force(skb) && state->hook != NF_INET_PRE_ROUTING) { + status = -ENETDOWN; + goto err; + } + *entry = (struct nf_queue_entry) { .skb = skb, .state = *state, @@@ -197,7 -203,6 +202,6 @@@ };
nf_queue_entry_get_refs(entry); - skb_dst_force(skb);
switch (entry->state.pf) { case AF_INET: @@@ -224,11 -229,12 +228,11 @@@ err
/* Packets leaving via this function must come back through nf_reinject(). */ int nf_queue(struct sk_buff *skb, struct nf_hook_state *state, - const struct nf_hook_entries *entries, unsigned int index, - unsigned int verdict) + unsigned int index, unsigned int verdict) { int ret;
- ret = __nf_queue(skb, state, entries, index, verdict >> NF_VERDICT_QBITS); + ret = __nf_queue(skb, state, index, verdict >> NF_VERDICT_QBITS); if (ret < 0) { if (ret == -ESRCH && (verdict & NF_VERDICT_FLAG_QUEUE_BYPASS)) @@@ -334,7 -340,7 +338,7 @@@ next_hook local_bh_enable(); break; case NF_QUEUE: - err = nf_queue(skb, &entry->state, hooks, i, verdict); + err = nf_queue(skb, &entry->state, i, verdict); if (err == 1) goto next_hook; break; diff --combined net/sched/cls_flower.c index ce2e9b1c9850,fdeede3af72e..5d4935b51e6f --- a/net/sched/cls_flower.c +++ b/net/sched/cls_flower.c @@@ -27,7 -27,7 +27,7 @@@ #include <net/dst_metadata.h>
struct fl_flow_key { - int indev_ifindex; + struct flow_dissector_key_meta meta; struct flow_dissector_key_control control; struct flow_dissector_key_control enc_control; struct flow_dissector_key_basic basic; @@@ -284,7 -284,7 +284,7 @@@ static int fl_classify(struct sk_buff * list_for_each_entry_rcu(mask, &head->masks, list) { fl_clear_masked_range(&skb_key, mask);
- skb_key.indev_ifindex = skb->skb_iif; + skb_flow_dissect_meta(skb, &mask->dissector, &skb_key); /* skb_flow_dissect() does not set n_proto in case an unknown * protocol, so do it rather here. */ @@@ -524,24 -524,6 +524,6 @@@ static struct cls_fl_filter *__fl_get(s return f; }
- static struct cls_fl_filter *fl_get_next_filter(struct tcf_proto *tp, - unsigned long *handle) - { - struct cls_fl_head *head = fl_head_dereference(tp); - struct cls_fl_filter *f; - - rcu_read_lock(); - while ((f = idr_get_next_ul(&head->handle_idr, handle))) { - /* don't return filters that are being deleted */ - if (refcount_inc_not_zero(&f->refcnt)) - break; - ++(*handle); - } - rcu_read_unlock(); - - return f; - } - static int __fl_delete(struct tcf_proto *tp, struct cls_fl_filter *f, bool *last, bool rtnl_held, struct netlink_ext_ack *extack) @@@ -1021,14 -1003,15 +1003,14 @@@ static int fl_set_key(struct net *net, { __be16 ethertype; int ret = 0; -#ifdef CONFIG_NET_CLS_IND + if (tb[TCA_FLOWER_INDEV]) { int err = tcf_change_indev(net, tb[TCA_FLOWER_INDEV], extack); if (err < 0) return err; - key->indev_ifindex = err; - mask->indev_ifindex = 0xffffffff; + key->meta.ingress_ifindex = err; + mask->meta.ingress_ifindex = 0xffffffff; } -#endif
fl_set_key_val(tb, key->eth.dst, TCA_FLOWER_KEY_ETH_DST, mask->eth.dst, TCA_FLOWER_KEY_ETH_DST_MASK, @@@ -1281,8 -1264,6 +1263,8 @@@ static void fl_init_dissector(struct fl struct flow_dissector_key keys[FLOW_DISSECTOR_KEY_MAX]; size_t cnt = 0;
+ FL_KEY_SET_IF_MASKED(mask, keys, cnt, + FLOW_DISSECTOR_KEY_META, meta); FL_KEY_SET(keys, cnt, FLOW_DISSECTOR_KEY_CONTROL, control); FL_KEY_SET(keys, cnt, FLOW_DISSECTOR_KEY_BASIC, basic); FL_KEY_SET_IF_MASKED(mask, keys, cnt, @@@ -1692,20 -1673,25 +1674,25 @@@ static int fl_delete(struct tcf_proto * static void fl_walk(struct tcf_proto *tp, struct tcf_walker *arg, bool rtnl_held) { + struct cls_fl_head *head = fl_head_dereference(tp); + unsigned long id = arg->cookie, tmp; struct cls_fl_filter *f;
arg->count = arg->skip;
- while ((f = fl_get_next_filter(tp, &arg->cookie)) != NULL) { + idr_for_each_entry_continue_ul(&head->handle_idr, f, tmp, id) { + /* don't return filters that are being deleted */ + if (!refcount_inc_not_zero(&f->refcnt)) + continue; if (arg->fn(tp, f, arg) < 0) { __fl_put(f); arg->stop = 1; break; } __fl_put(f); - arg->cookie++; arg->count++; } + arg->cookie = id; }
static struct cls_fl_filter * @@@ -2124,10 -2110,10 +2111,10 @@@ static int fl_dump_key_enc_opt(struct s static int fl_dump_key(struct sk_buff *skb, struct net *net, struct fl_flow_key *key, struct fl_flow_key *mask) { - if (mask->indev_ifindex) { + if (mask->meta.ingress_ifindex) { struct net_device *dev;
- dev = __dev_get_by_index(net, key->indev_ifindex); + dev = __dev_get_by_index(net, key->meta.ingress_ifindex); if (dev && nla_put_string(skb, TCA_FLOWER_INDEV, dev->name)) goto nla_put_failure; } diff --combined net/tls/tls_device.c index 40076f423dcb,eb8f24f420f0..92fd1352c037 --- a/net/tls/tls_device.c +++ b/net/tls/tls_device.c @@@ -61,7 -61,7 +61,7 @@@ static void tls_device_free_ctx(struct if (ctx->rx_conf == TLS_HW) kfree(tls_offload_ctx_rx(ctx));
- kfree(ctx); + tls_ctx_free(ctx); }
static void tls_device_gc_task(struct work_struct *work) @@@ -209,29 -209,6 +209,29 @@@ void tls_device_free_resources_tx(struc tls_free_partial_record(sk, tls_ctx); }
+static void tls_device_resync_tx(struct sock *sk, struct tls_context *tls_ctx, + u32 seq) +{ + struct net_device *netdev; + struct sk_buff *skb; + u8 *rcd_sn; + + skb = tcp_write_queue_tail(sk); + if (skb) + TCP_SKB_CB(skb)->eor = 1; + + rcd_sn = tls_ctx->tx.rec_seq; + + down_read(&device_offload_lock); + netdev = tls_ctx->netdev; + if (netdev) + netdev->tlsdev_ops->tls_dev_resync(netdev, sk, seq, rcd_sn, + TLS_OFFLOAD_CTX_DIR_TX); + up_read(&device_offload_lock); + + clear_bit_unlock(TLS_TX_SYNC_SCHED, &tls_ctx->flags); +} + static void tls_append_frag(struct tls_record_info *record, struct page_frag *pfrag, int size) @@@ -275,7 -252,7 +275,7 @@@ static int tls_push_record(struct sock skb_frag_address(frag), record->len - prot->prepend_size, record_type, - ctx->crypto_send.info.version); + prot->version);
/* HW doesn't care about the data in the tag, because it fills it. */ dummy_tag_frag.page = skb_frag_page(frag); @@@ -287,11 -264,7 +287,11 @@@ list_add_tail(&record->list, &offload_ctx->records_list); spin_unlock_irq(&offload_ctx->lock); offload_ctx->open_record = NULL; - tls_advance_record_sn(sk, &ctx->tx, ctx->crypto_send.info.version); + + if (test_bit(TLS_TX_SYNC_SCHED, &ctx->flags)) + tls_device_resync_tx(sk, ctx, tp->write_seq); + + tls_advance_record_sn(sk, prot, &ctx->tx);
for (i = 0; i < record->num_frags; i++) { frag = &record->frags[i]; @@@ -578,7 -551,7 +578,7 @@@ void tls_device_write_space(struct soc }
static void tls_device_resync_rx(struct tls_context *tls_ctx, - struct sock *sk, u32 seq, u64 rcd_sn) + struct sock *sk, u32 seq, u8 *rcd_sn) { struct net_device *netdev;
@@@ -586,17 -559,14 +586,17 @@@ return; netdev = READ_ONCE(tls_ctx->netdev); if (netdev) - netdev->tlsdev_ops->tls_dev_resync_rx(netdev, sk, seq, rcd_sn); + netdev->tlsdev_ops->tls_dev_resync(netdev, sk, seq, rcd_sn, + TLS_OFFLOAD_CTX_DIR_RX); clear_bit_unlock(TLS_RX_SYNC_RUNNING, &tls_ctx->flags); }
-void handle_device_resync(struct sock *sk, u32 seq, u64 rcd_sn) +void tls_device_rx_resync_new_rec(struct sock *sk, u32 rcd_len, u32 seq) { struct tls_context *tls_ctx = tls_get_ctx(sk); struct tls_offload_context_rx *rx_ctx; + u8 rcd_sn[TLS_MAX_REC_SEQ_SIZE]; + struct tls_prot_info *prot; u32 is_req_pending; s64 resync_req; u32 req_seq; @@@ -604,83 -574,15 +604,83 @@@ if (tls_ctx->rx_conf != TLS_HW) return;
+ prot = &tls_ctx->prot_info; rx_ctx = tls_offload_ctx_rx(tls_ctx); - resync_req = atomic64_read(&rx_ctx->resync_req); - req_seq = (resync_req >> 32) - ((u32)TLS_HEADER_SIZE - 1); - is_req_pending = resync_req; + memcpy(rcd_sn, tls_ctx->rx.rec_seq, prot->rec_seq_size);
- if (unlikely(is_req_pending) && req_seq == seq && - atomic64_try_cmpxchg(&rx_ctx->resync_req, &resync_req, 0)) { + switch (rx_ctx->resync_type) { + case TLS_OFFLOAD_SYNC_TYPE_DRIVER_REQ: + resync_req = atomic64_read(&rx_ctx->resync_req); + req_seq = resync_req >> 32; seq += TLS_HEADER_SIZE - 1; - tls_device_resync_rx(tls_ctx, sk, seq, rcd_sn); + is_req_pending = resync_req; + + if (likely(!is_req_pending) || req_seq != seq || + !atomic64_try_cmpxchg(&rx_ctx->resync_req, &resync_req, 0)) + return; + break; + case TLS_OFFLOAD_SYNC_TYPE_CORE_NEXT_HINT: + if (likely(!rx_ctx->resync_nh_do_now)) + return; + + /* head of next rec is already in, note that the sock_inq will + * include the currently parsed message when called from parser + */ + if (tcp_inq(sk) > rcd_len) + return; + + rx_ctx->resync_nh_do_now = 0; + seq += rcd_len; + tls_bigint_increment(rcd_sn, prot->rec_seq_size); + break; + } + + tls_device_resync_rx(tls_ctx, sk, seq, rcd_sn); +} + +static void tls_device_core_ctrl_rx_resync(struct tls_context *tls_ctx, + struct tls_offload_context_rx *ctx, + struct sock *sk, struct sk_buff *skb) +{ + struct strp_msg *rxm; + + /* device will request resyncs by itself based on stream scan */ + if (ctx->resync_type != TLS_OFFLOAD_SYNC_TYPE_CORE_NEXT_HINT) + return; + /* already scheduled */ + if (ctx->resync_nh_do_now) + return; + /* seen decrypted fragments since last fully-failed record */ + if (ctx->resync_nh_reset) { + ctx->resync_nh_reset = 0; + ctx->resync_nh.decrypted_failed = 1; + ctx->resync_nh.decrypted_tgt = TLS_DEVICE_RESYNC_NH_START_IVAL; + return; + } + + if (++ctx->resync_nh.decrypted_failed <= ctx->resync_nh.decrypted_tgt) + return; + + /* doing resync, bump the next target in case it fails */ + if (ctx->resync_nh.decrypted_tgt < TLS_DEVICE_RESYNC_NH_MAX_IVAL) + ctx->resync_nh.decrypted_tgt *= 2; + else + ctx->resync_nh.decrypted_tgt += TLS_DEVICE_RESYNC_NH_MAX_IVAL; + + rxm = strp_msg(skb); + + /* head of next rec is already in, parser will sync for us */ + if (tcp_inq(sk) > rxm->full_len) { + ctx->resync_nh_do_now = 1; + } else { + struct tls_prot_info *prot = &tls_ctx->prot_info; + u8 rcd_sn[TLS_MAX_REC_SEQ_SIZE]; + + memcpy(rcd_sn, tls_ctx->rx.rec_seq, prot->rec_seq_size); + tls_bigint_increment(rcd_sn, prot->rec_seq_size); + + tls_device_resync_rx(tls_ctx, sk, tcp_sk(sk)->copied_seq, + rcd_sn); } }
@@@ -708,10 -610,8 +708,10 @@@ static int tls_device_reencrypt(struct sg_set_buf(&sg[0], buf, rxm->full_len + TLS_HEADER_SIZE + TLS_CIPHER_AES_GCM_128_IV_SIZE); - skb_copy_bits(skb, offset, buf, - TLS_HEADER_SIZE + TLS_CIPHER_AES_GCM_128_IV_SIZE); + err = skb_copy_bits(skb, offset, buf, + TLS_HEADER_SIZE + TLS_CIPHER_AES_GCM_128_IV_SIZE); + if (err) + goto free_buf;
/* We are interested only in the decrypted data not the auth */ err = decrypt_skb(sk, skb, sg); @@@ -725,11 -625,8 +725,11 @@@ if (skb_pagelen(skb) > offset) { copy = min_t(int, skb_pagelen(skb) - offset, data_len);
- if (skb->decrypted) - skb_store_bits(skb, offset, buf, copy); + if (skb->decrypted) { + err = skb_store_bits(skb, offset, buf, copy); + if (err) + goto free_buf; + }
offset += copy; buf += copy; @@@ -752,11 -649,8 +752,11 @@@ copy = min_t(int, skb_iter->len - frag_pos, data_len + rxm->offset - offset);
- if (skb_iter->decrypted) - skb_store_bits(skb_iter, frag_pos, buf, copy); + if (skb_iter->decrypted) { + err = skb_store_bits(skb_iter, frag_pos, buf, copy); + if (err) + goto free_buf; + }
offset += copy; buf += copy; @@@ -777,6 -671,10 +777,6 @@@ int tls_device_decrypted(struct sock *s int is_encrypted = !is_decrypted; struct sk_buff *skb_iter;
- /* Skip if it is already decrypted */ - if (ctx->sw.decrypted) - return 0; - /* Check if all the data is decrypted already */ skb_walk_frags(skb, skb_iter) { is_decrypted &= skb_iter->decrypted; @@@ -785,21 -683,12 +785,21 @@@
ctx->sw.decrypted |= is_decrypted;
- /* Return immedeatly if the record is either entirely plaintext or + /* Return immediately if the record is either entirely plaintext or * entirely ciphertext. Otherwise handle reencrypt partially decrypted * record. */ - return (is_encrypted || is_decrypted) ? 0 : - tls_device_reencrypt(sk, skb); + if (is_decrypted) { + ctx->resync_nh_reset = 1; + return 0; + } + if (is_encrypted) { + tls_device_core_ctrl_rx_resync(tls_ctx, ctx, sk, skb); + return 0; + } + + ctx->resync_nh_reset = 1; + return tls_device_reencrypt(sk, skb); }
static void tls_device_attach(struct tls_context *ctx, struct sock *sk, @@@ -853,6 -742,11 +853,11 @@@ int tls_set_device_offload(struct sock }
crypto_info = &ctx->crypto_send.info; + if (crypto_info->version != TLS_1_2_VERSION) { + rc = -EOPNOTSUPP; + goto free_offload_ctx; + } + switch (crypto_info->cipher_type) { case TLS_CIPHER_AES_GCM_128: nonce_size = TLS_CIPHER_AES_GCM_128_IV_SIZE; @@@ -868,12 -762,6 +873,12 @@@ goto free_offload_ctx; }
+ /* Sanity-check the rec_seq_size for stack allocations */ + if (rec_seq_size > TLS_MAX_REC_SEQ_SIZE) { + rc = -EINVAL; + goto free_offload_ctx; + } + prot->prepend_size = TLS_HEADER_SIZE + nonce_size; prot->tag_size = tag_size; prot->overhead_size = prot->prepend_size + prot->tag_size; @@@ -993,6 -881,9 +998,9 @@@ int tls_set_device_offload_rx(struct so struct net_device *netdev; int rc = 0;
+ if (ctx->crypto_recv.info.version != TLS_1_2_VERSION) + return -EOPNOTSUPP; + /* We support starting offload on multiple sockets * concurrently, so we only need a read lock here. * This lock must precede get_netdev_for_sock to prevent races between @@@ -1025,7 -916,6 +1033,7 @@@ rc = -ENOMEM; goto release_netdev; } + context->resync_nh_reset = 1;
ctx->priv_ctx_rx = context; rc = tls_set_sw_offload(sk, ctx, 0); @@@ -1133,7 -1023,7 +1141,7 @@@ static int tls_dev_event(struct notifie case NETDEV_REGISTER: case NETDEV_FEAT_CHANGE: if ((dev->features & NETIF_F_HW_TLS_RX) && - !dev->tlsdev_ops->tls_dev_resync_rx) + !dev->tlsdev_ops->tls_dev_resync) return NOTIFY_BAD;
if (dev->tlsdev_ops && diff --combined net/tls/tls_sw.c index db585964b52b,e2385183526e..53b4ad94e74a --- a/net/tls/tls_sw.c +++ b/net/tls/tls_sw.c @@@ -534,7 -534,7 +534,7 @@@ static int tls_do_encryption(struct soc
/* Unhook the record from context if encryption is not failure */ ctx->open_rec = NULL; - tls_advance_record_sn(sk, &tls_ctx->tx, prot->version); + tls_advance_record_sn(sk, prot, &tls_ctx->tx); return rc; }
@@@ -1485,16 -1485,15 +1485,16 @@@ static int decrypt_skb_update(struct so struct tls_context *tls_ctx = tls_get_ctx(sk); struct tls_sw_context_rx *ctx = tls_sw_ctx_rx(tls_ctx); struct tls_prot_info *prot = &tls_ctx->prot_info; - int version = prot->version; struct strp_msg *rxm = strp_msg(skb); int pad, err = 0;
if (!ctx->decrypted) { #ifdef CONFIG_TLS_DEVICE - err = tls_device_decrypted(sk, skb); - if (err < 0) - return err; + if (tls_ctx->rx_conf == TLS_HW) { + err = tls_device_decrypted(sk, skb); + if (err < 0) + return err; + } #endif /* Still not decrypted after tls_device */ if (!ctx->decrypted) { @@@ -1502,8 -1501,8 +1502,8 @@@ async); if (err < 0) { if (err == -EINPROGRESS) - tls_advance_record_sn(sk, &tls_ctx->rx, - version); + tls_advance_record_sn(sk, prot, + &tls_ctx->rx);
return err; } @@@ -1518,7 -1517,7 +1518,7 @@@ rxm->full_len -= pad; rxm->offset += prot->prepend_size; rxm->full_len -= prot->overhead_size; - tls_advance_record_sn(sk, &tls_ctx->rx, version); + tls_advance_record_sn(sk, prot, &tls_ctx->rx); ctx->decrypted = true; ctx->saved_data_ready(sk); } else { @@@ -1959,7 -1958,8 +1959,8 @@@ bool tls_sw_stream_read(const struct so ingress_empty = list_empty(&psock->ingress_msg); rcu_read_unlock();
- return !ingress_empty || ctx->recv_pkt; + return !ingress_empty || ctx->recv_pkt || + !skb_queue_empty(&ctx->rx_list); }
static int tls_read_size(struct strparser *strp, struct sk_buff *skb) @@@ -2014,8 -2014,8 +2015,8 @@@ goto read_failure; } #ifdef CONFIG_TLS_DEVICE - handle_device_resync(strp->sk, TCP_SKB_CB(skb)->seq + rxm->offset, - *(u64*)tls_ctx->rx.rec_seq); + tls_device_rx_resync_new_rec(strp->sk, data_len + TLS_HEADER_SIZE, + TCP_SKB_CB(skb)->seq + rxm->offset); #endif return data_len + TLS_HEADER_SIZE;
@@@ -2282,9 -2282,8 +2283,9 @@@ int tls_set_sw_offload(struct sock *sk goto free_priv; }
- /* Sanity-check the IV size for stack allocations. */ - if (iv_size > MAX_IV_SIZE || nonce_size > MAX_IV_SIZE) { + /* Sanity-check the sizes for stack allocations. */ + if (iv_size > MAX_IV_SIZE || nonce_size > MAX_IV_SIZE || + rec_seq_size > TLS_MAX_REC_SEQ_SIZE) { rc = -EINVAL; goto free_priv; } diff --combined net/xdp/xsk.c index 0574f008954c,f53a6ef7c155..d4d6f10aa936 --- a/net/xdp/xsk.c +++ b/net/xdp/xsk.c @@@ -37,12 -37,6 +37,12 @@@ bool xsk_is_setup_for_bpf_map(struct xd READ_ONCE(xs->umem->fq); }
+bool xsk_umem_has_addrs(struct xdp_umem *umem, u32 cnt) +{ + return xskq_has_addrs(umem->fq, cnt); +} +EXPORT_SYMBOL(xsk_umem_has_addrs); + u64 *xsk_umem_peek_addr(struct xdp_umem *umem, u64 *addr) { return xskq_peek_addr(umem->fq, addr); @@@ -129,17 -123,13 +129,17 @@@ int xsk_generic_rcv(struct xdp_sock *xs u64 addr; int err;
- if (xs->dev != xdp->rxq->dev || xs->queue_id != xdp->rxq->queue_index) - return -EINVAL; + spin_lock_bh(&xs->rx_lock); + + if (xs->dev != xdp->rxq->dev || xs->queue_id != xdp->rxq->queue_index) { + err = -EINVAL; + goto out_unlock; + }
if (!xskq_peek_addr(xs->umem->fq, &addr) || len > xs->umem->chunk_size_nohr - XDP_PACKET_HEADROOM) { - xs->rx_dropped++; - return -ENOSPC; + err = -ENOSPC; + goto out_drop; }
addr += xs->umem->headroom; @@@ -148,21 -138,13 +148,21 @@@ memcpy(buffer, xdp->data_meta, len + metalen); addr += metalen; err = xskq_produce_batch_desc(xs->rx, addr, len); - if (!err) { - xskq_discard_addr(xs->umem->fq); - xsk_flush(xs); - return 0; - } + if (err) + goto out_drop; + + xskq_discard_addr(xs->umem->fq); + xskq_produce_flush_desc(xs->rx); + + spin_unlock_bh(&xs->rx_lock);
+ xs->sk.sk_data_ready(&xs->sk); + return 0; + +out_drop: xs->rx_dropped++; +out_unlock: + spin_unlock_bh(&xs->rx_lock); return err; }
@@@ -184,18 -166,22 +184,18 @@@ void xsk_umem_consume_tx_done(struct xd } EXPORT_SYMBOL(xsk_umem_consume_tx_done);
-bool xsk_umem_consume_tx(struct xdp_umem *umem, dma_addr_t *dma, u32 *len) +bool xsk_umem_consume_tx(struct xdp_umem *umem, struct xdp_desc *desc) { - struct xdp_desc desc; struct xdp_sock *xs;
rcu_read_lock(); list_for_each_entry_rcu(xs, &umem->xsk_list, list) { - if (!xskq_peek_desc(xs->tx, &desc)) + if (!xskq_peek_desc(xs->tx, desc)) continue;
- if (xskq_produce_addr_lazy(umem->cq, desc.addr)) + if (xskq_produce_addr_lazy(umem->cq, desc->addr)) goto out;
- *dma = xdp_umem_get_dma(umem, desc.addr); - *len = desc.len; - xskq_discard_desc(xs->tx); rcu_read_unlock(); return true; @@@ -349,6 -335,22 +349,22 @@@ static int xsk_init_queue(u32 entries, return 0; }
+ static void xsk_unbind_dev(struct xdp_sock *xs) + { + struct net_device *dev = xs->dev; + + if (!dev || xs->state != XSK_BOUND) + return; + + xs->state = XSK_UNBOUND; + + /* Wait for driver to stop using the xdp socket. */ + xdp_del_sk_umem(xs->umem, xs); + xs->dev = NULL; + synchronize_net(); + dev_put(dev); + } + static int xsk_release(struct socket *sock) { struct sock *sk = sock->sk; @@@ -368,15 -370,7 +384,7 @@@ sock_prot_inuse_add(net, sk->sk_prot, -1); local_bh_enable();
- if (xs->dev) { - struct net_device *dev = xs->dev; - - /* Wait for driver to stop using the xdp socket. */ - xdp_del_sk_umem(xs->umem, xs); - xs->dev = NULL; - synchronize_net(); - dev_put(dev); - } + xsk_unbind_dev(xs);
xskq_destroy(xs->rx); xskq_destroy(xs->tx); @@@ -426,7 -420,7 +434,7 @@@ static int xsk_bind(struct socket *sock return -EINVAL;
mutex_lock(&xs->mutex); - if (xs->dev) { + if (xs->state != XSK_READY) { err = -EBUSY; goto out_release; } @@@ -506,6 -500,8 +514,8 @@@ out_unlock: if (err) dev_put(dev); + else + xs->state = XSK_BOUND; out_release: mutex_unlock(&xs->mutex); return err; @@@ -534,6 -530,10 +544,10 @@@ static int xsk_setsockopt(struct socke return -EFAULT;
mutex_lock(&xs->mutex); + if (xs->state != XSK_READY) { + mutex_unlock(&xs->mutex); + return -EBUSY; + } q = (optname == XDP_TX_RING) ? &xs->tx : &xs->rx; err = xsk_init_queue(entries, q, false); mutex_unlock(&xs->mutex); @@@ -548,7 -548,7 +562,7 @@@ return -EFAULT;
mutex_lock(&xs->mutex); - if (xs->umem) { + if (xs->state != XSK_READY || xs->umem) { mutex_unlock(&xs->mutex); return -EBUSY; } @@@ -575,6 -575,10 +589,10 @@@ return -EFAULT;
mutex_lock(&xs->mutex); + if (xs->state != XSK_READY) { + mutex_unlock(&xs->mutex); + return -EBUSY; + } if (!xs->umem) { mutex_unlock(&xs->mutex); return -EINVAL; @@@ -658,26 -662,6 +676,26 @@@ static int xsk_getsockopt(struct socke
return 0; } + case XDP_OPTIONS: + { + struct xdp_options opts = {}; + + if (len < sizeof(opts)) + return -EINVAL; + + mutex_lock(&xs->mutex); + if (xs->zc) + opts.flags |= XDP_OPTIONS_ZEROCOPY; + mutex_unlock(&xs->mutex); + + len = sizeof(opts); + if (copy_to_user(optval, &opts, len)) + return -EFAULT; + if (put_user(len, optlen)) + return -EFAULT; + + return 0; + } default: break; } @@@ -696,6 -680,9 +714,9 @@@ static int xsk_mmap(struct file *file, unsigned long pfn; struct page *qpg;
+ if (xs->state != XSK_READY) + return -EBUSY; + if (offset == XDP_PGOFF_RX_RING) { q = READ_ONCE(xs->rx); } else if (offset == XDP_PGOFF_TX_RING) { @@@ -727,6 -714,38 +748,38 @@@ size, vma->vm_page_prot); }
+ static int xsk_notifier(struct notifier_block *this, + unsigned long msg, void *ptr) + { + struct net_device *dev = netdev_notifier_info_to_dev(ptr); + struct net *net = dev_net(dev); + struct sock *sk; + + switch (msg) { + case NETDEV_UNREGISTER: + mutex_lock(&net->xdp.lock); + sk_for_each(sk, &net->xdp.list) { + struct xdp_sock *xs = xdp_sk(sk); + + mutex_lock(&xs->mutex); + if (xs->dev == dev) { + sk->sk_err = ENETDOWN; + if (!sock_flag(sk, SOCK_DEAD)) + sk->sk_error_report(sk); + + xsk_unbind_dev(xs); + + /* Clear device references in umem. */ + xdp_umem_clear_dev(xs->umem); + } + mutex_unlock(&xs->mutex); + } + mutex_unlock(&net->xdp.lock); + break; + } + return NOTIFY_DONE; + } + static struct proto xsk_proto = { .name = "XDP", .owner = THIS_MODULE, @@@ -798,8 -817,8 +851,9 @@@ static int xsk_create(struct net *net, sock_set_flag(sk, SOCK_RCU_FREE);
xs = xdp_sk(sk); + xs->state = XSK_READY; mutex_init(&xs->mutex); + spin_lock_init(&xs->rx_lock); spin_lock_init(&xs->tx_completion_lock);
mutex_lock(&net->xdp.lock); @@@ -819,6 -838,10 +873,10 @@@ static const struct net_proto_family xs .owner = THIS_MODULE, };
+ static struct notifier_block xsk_netdev_notifier = { + .notifier_call = xsk_notifier, + }; + static int __net_init xsk_net_init(struct net *net) { mutex_init(&net->xdp.lock); @@@ -851,8 -874,15 +909,15 @@@ static int __init xsk_init(void err = register_pernet_subsys(&xsk_net_ops); if (err) goto out_sk; + + err = register_netdevice_notifier(&xsk_netdev_notifier); + if (err) + goto out_pernet; + return 0;
+ out_pernet: + unregister_pernet_subsys(&xsk_net_ops); out_sk: sock_unregister(PF_XDP); out_proto: diff --combined net/xdp/xsk_queue.h index 12b49784a6d5,cba4a640d5e8..909c5168ed0f --- a/net/xdp/xsk_queue.h +++ b/net/xdp/xsk_queue.h @@@ -117,20 -117,6 +117,20 @@@ static inline u32 xskq_nb_free(struct x return q->nentries - (producer - q->cons_tail); }
+static inline bool xskq_has_addrs(struct xsk_queue *q, u32 cnt) +{ + u32 entries = q->prod_tail - q->cons_tail; + + if (entries >= cnt) + return true; + + /* Refresh the local pointer. */ + q->prod_tail = READ_ONCE(q->ring->producer); + entries = q->prod_tail - q->cons_tail; + + return entries >= cnt; +} + /* UMEM queue */
static inline bool xskq_is_valid_addr(struct xsk_queue *q, u64 addr) @@@ -302,7 -288,7 +302,7 @@@ static inline void xskq_produce_flush_d /* Order producer and data */ smp_wmb(); /* B, matches C */
- q->prod_tail = q->prod_head, + q->prod_tail = q->prod_head; WRITE_ONCE(q->ring->producer, q->prod_tail); }
diff --combined net/xfrm/xfrm_interface.c index f8eb9e342173,7dbe0c608df5..74868f9d81fb --- a/net/xfrm/xfrm_interface.c +++ b/net/xfrm/xfrm_interface.c @@@ -133,7 -133,7 +133,7 @@@ static void xfrmi_dev_free(struct net_d free_percpu(dev->tstats); }
- static int xfrmi_create2(struct net_device *dev) + static int xfrmi_create(struct net_device *dev) { struct xfrm_if *xi = netdev_priv(dev); struct net *net = dev_net(dev); @@@ -156,54 -156,7 +156,7 @@@ out return err; }
- static struct xfrm_if *xfrmi_create(struct net *net, struct xfrm_if_parms *p) - { - struct net_device *dev; - struct xfrm_if *xi; - char name[IFNAMSIZ]; - int err; - - if (p->name[0]) { - strlcpy(name, p->name, IFNAMSIZ); - } else { - err = -EINVAL; - goto failed; - } - - dev = alloc_netdev(sizeof(*xi), name, NET_NAME_UNKNOWN, xfrmi_dev_setup); - if (!dev) { - err = -EAGAIN; - goto failed; - } - - dev_net_set(dev, net); - - xi = netdev_priv(dev); - xi->p = *p; - xi->net = net; - xi->dev = dev; - xi->phydev = dev_get_by_index(net, p->link); - if (!xi->phydev) { - err = -ENODEV; - goto failed_free; - } - - err = xfrmi_create2(dev); - if (err < 0) - goto failed_dev_put; - - return xi; - - failed_dev_put: - dev_put(xi->phydev); - failed_free: - free_netdev(dev); - failed: - return ERR_PTR(err); - } - - static struct xfrm_if *xfrmi_locate(struct net *net, struct xfrm_if_parms *p, - int create) + static struct xfrm_if *xfrmi_locate(struct net *net, struct xfrm_if_parms *p) { struct xfrm_if __rcu **xip; struct xfrm_if *xi; @@@ -211,17 -164,11 +164,11 @@@
for (xip = &xfrmn->xfrmi[0]; (xi = rtnl_dereference(*xip)) != NULL; - xip = &xi->next) { - if (xi->p.if_id == p->if_id) { - if (create) - return ERR_PTR(-EEXIST); - + xip = &xi->next) + if (xi->p.if_id == p->if_id) return xi; - } - } - if (!create) - return ERR_PTR(-ENODEV); - return xfrmi_create(net, p); + + return NULL; }
static void xfrmi_dev_uninit(struct net_device *dev) @@@ -686,21 -633,33 +633,33 @@@ static int xfrmi_newlink(struct net *sr struct netlink_ext_ack *extack) { struct net *net = dev_net(dev); - struct xfrm_if_parms *p; + struct xfrm_if_parms p; struct xfrm_if *xi; + int err;
- xi = netdev_priv(dev); - p = &xi->p; - - xfrmi_netlink_parms(data, p); + xfrmi_netlink_parms(data, &p);
if (!tb[IFLA_IFNAME]) return -EINVAL;
- nla_strlcpy(p->name, tb[IFLA_IFNAME], IFNAMSIZ); + nla_strlcpy(p.name, tb[IFLA_IFNAME], IFNAMSIZ);
- xi = xfrmi_locate(net, p, 1); - return PTR_ERR_OR_ZERO(xi); + xi = xfrmi_locate(net, &p); + if (xi) + return -EEXIST; + + xi = netdev_priv(dev); + xi->p = p; + xi->net = net; + xi->dev = dev; + xi->phydev = dev_get_by_index(net, p.link); + if (!xi->phydev) + return -ENODEV; + + err = xfrmi_create(dev); + if (err < 0) + dev_put(xi->phydev); + return err; }
static void xfrmi_dellink(struct net_device *dev, struct list_head *head) @@@ -717,9 -676,8 +676,8 @@@ static int xfrmi_changelink(struct net_
xfrmi_netlink_parms(data, &xi->p);
- xi = xfrmi_locate(net, &xi->p, 0); - - if (IS_ERR_OR_NULL(xi)) { + xi = xfrmi_locate(net, &xi->p); + if (!xi) { xi = netdev_priv(dev); } else { if (xi->dev != dev) @@@ -793,6 -751,11 +751,6 @@@ static void __net_exit xfrmi_destroy_in unregister_netdevice_many(&list); }
-static int __net_init xfrmi_init_net(struct net *net) -{ - return 0; -} - static void __net_exit xfrmi_exit_net(struct net *net) { struct xfrmi_net *xfrmn = net_generic(net, xfrmi_net_id); @@@ -803,6 -766,7 +761,6 @@@ }
static struct pernet_operations xfrmi_net_ops = { - .init = xfrmi_init_net, .exit = xfrmi_exit_net, .id = &xfrmi_net_id, .size = sizeof(struct xfrmi_net), diff --combined net/xfrm/xfrm_policy.c index 1070dfece76b,4fb58dfecc7a..8ca637a72697 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c @@@ -585,9 -585,6 +585,6 @@@ static void xfrm_bydst_resize(struct ne odst = rcu_dereference_protected(net->xfrm.policy_bydst[dir].table, lockdep_is_held(&net->xfrm.xfrm_policy_lock));
- odst = rcu_dereference_protected(net->xfrm.policy_bydst[dir].table, - lockdep_is_held(&net->xfrm.xfrm_policy_lock)); - for (i = hmask; i >= 0; i--) xfrm_dst_hash_transfer(net, odst + i, ndst, nhashmask, dir);
@@@ -1280,13 -1277,17 +1277,17 @@@ static void xfrm_hash_rebuild(struct wo
hlist_for_each_entry_safe(policy, n, &net->xfrm.policy_inexact[dir], - bydst_inexact_list) + bydst_inexact_list) { + hlist_del_rcu(&policy->bydst); hlist_del_init(&policy->bydst_inexact_list); + }
hmask = net->xfrm.policy_bydst[dir].hmask; odst = net->xfrm.policy_bydst[dir].table; - for (i = hmask; i >= 0; i--) - INIT_HLIST_HEAD(odst + i); + for (i = hmask; i >= 0; i--) { + hlist_for_each_entry_safe(policy, n, odst + i, bydst) + hlist_del_rcu(&policy->bydst); + } if ((dir & XFRM_POLICY_MASK) == XFRM_POLICY_OUT) { /* dir out => dst = remote, src = local */ net->xfrm.policy_bydst[dir].dbits4 = rbits4; @@@ -1315,8 -1316,6 +1316,6 @@@ chain = policy_hash_bysel(net, &policy->selector, policy->family, dir);
- hlist_del_rcu(&policy->bydst); - if (!chain) { void *p = xfrm_policy_inexact_insert(policy, dir, 0);
@@@ -3628,7 -3627,7 +3627,7 @@@ int __xfrm_policy_check(struct sock *sk } xfrm_nr = ti; if (npols > 1) { - xfrm_tmpl_sort(stp, tpp, xfrm_nr, family, net); + xfrm_tmpl_sort(stp, tpp, xfrm_nr, family); tpp = stp; }
diff --combined samples/bpf/xdp_redirect_user.c index 39de06f3ec25,003c0c6e38c5..5440cd620607 --- a/samples/bpf/xdp_redirect_user.c +++ b/samples/bpf/xdp_redirect_user.c @@@ -10,14 -10,13 +10,14 @@@ #include <stdlib.h> #include <stdbool.h> #include <string.h> +#include <net/if.h> #include <unistd.h> #include <libgen.h> #include <sys/resource.h>
#include "bpf_util.h" #include <bpf/bpf.h> -#include "bpf/libbpf.h" +#include "libbpf.h"
static int ifindex_in; static int ifindex_out; @@@ -86,7 -85,7 +86,7 @@@ static void poll_stats(int interval, in static void usage(const char *prog) { fprintf(stderr, - "usage: %s [OPTS] IFINDEX_IN IFINDEX_OUT\n\n" + "usage: %s [OPTS] <IFNAME|IFINDEX>_IN <IFNAME|IFINDEX>_OUT\n\n" "OPTS:\n" " -S use skb-mode\n" " -N enforce native mode\n" @@@ -129,7 -128,7 +129,7 @@@ int main(int argc, char **argv }
if (optind == argc) { - printf("usage: %s IFINDEX_IN IFINDEX_OUT\n", argv[0]); + printf("usage: %s <IFNAME|IFINDEX>_IN <IFNAME|IFINDEX>_OUT\n", argv[0]); return 1; }
@@@ -138,14 -137,8 +138,14 @@@ return 1; }
- ifindex_in = strtoul(argv[optind], NULL, 0); - ifindex_out = strtoul(argv[optind + 1], NULL, 0); + ifindex_in = if_nametoindex(argv[optind]); + if (!ifindex_in) + ifindex_in = strtoul(argv[optind], NULL, 0); + + ifindex_out = if_nametoindex(argv[optind + 1]); + if (!ifindex_out) + ifindex_out = strtoul(argv[optind + 1], NULL, 0); + printf("input: %d output: %d\n", ifindex_in, ifindex_out);
snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]); @@@ -196,7 -189,7 +196,7 @@@ }
memset(&info, 0, sizeof(info)); - ret = bpf_obj_get_info_by_fd(prog_fd, &info, &info_len); + ret = bpf_obj_get_info_by_fd(dummy_prog_fd, &info, &info_len); if (ret) { printf("can't get prog info - %s\n", strerror(errno)); return ret; diff --combined tools/bpf/bpftool/cgroup.c index 390b89a224f1,a13fb7265d1a..f3c05b08c68c --- a/tools/bpf/bpftool/cgroup.c +++ b/tools/bpf/bpftool/cgroup.c @@@ -26,8 -26,7 +26,8 @@@ " sock_ops | device | bind4 | bind6 |\n" \ " post_bind4 | post_bind6 | connect4 |\n" \ " connect6 | sendmsg4 | sendmsg6 |\n" \ - " recvmsg4 | recvmsg6 | sysctl }" + " recvmsg4 | recvmsg6 | sysctl |\n" \ + " getsockopt | setsockopt }"
static const char * const attach_type_strings[] = { [BPF_CGROUP_INET_INGRESS] = "ingress", @@@ -46,8 -45,6 +46,8 @@@ [BPF_CGROUP_SYSCTL] = "sysctl", [BPF_CGROUP_UDP4_RECVMSG] = "recvmsg4", [BPF_CGROUP_UDP6_RECVMSG] = "recvmsg6", + [BPF_CGROUP_GETSOCKOPT] = "getsockopt", + [BPF_CGROUP_SETSOCKOPT] = "setsockopt", [__MAX_BPF_ATTACH_TYPE] = NULL, };
@@@ -171,7 -168,7 +171,7 @@@ static int do_show(int argc, char **arg
cgroup_fd = open(argv[0], O_RDONLY); if (cgroup_fd < 0) { - p_err("can't open cgroup %s", argv[1]); + p_err("can't open cgroup %s", argv[0]); goto exit; }
@@@ -359,7 -356,7 +359,7 @@@ static int do_attach(int argc, char **a
cgroup_fd = open(argv[0], O_RDONLY); if (cgroup_fd < 0) { - p_err("can't open cgroup %s", argv[1]); + p_err("can't open cgroup %s", argv[0]); goto exit; }
@@@ -417,7 -414,7 +417,7 @@@ static int do_detach(int argc, char **a
cgroup_fd = open(argv[0], O_RDONLY); if (cgroup_fd < 0) { - p_err("can't open cgroup %s", argv[1]); + p_err("can't open cgroup %s", argv[0]); goto exit; }
diff --combined tools/include/uapi/linux/bpf.h index e692bb21846f,29a5bc3d5c66..402208581b2d --- a/tools/include/uapi/linux/bpf.h +++ b/tools/include/uapi/linux/bpf.h @@@ -170,7 -170,6 +170,7 @@@ enum bpf_prog_type BPF_PROG_TYPE_FLOW_DISSECTOR, BPF_PROG_TYPE_CGROUP_SYSCTL, BPF_PROG_TYPE_RAW_TRACEPOINT_WRITABLE, + BPF_PROG_TYPE_CGROUP_SOCKOPT, };
enum bpf_attach_type { @@@ -195,8 -194,6 +195,8 @@@ BPF_CGROUP_SYSCTL, BPF_CGROUP_UDP4_RECVMSG, BPF_CGROUP_UDP6_RECVMSG, + BPF_CGROUP_GETSOCKOPT, + BPF_CGROUP_SETSOCKOPT, __MAX_BPF_ATTACH_TYPE };
@@@ -265,24 -262,6 +265,24 @@@ */ #define BPF_F_ANY_ALIGNMENT (1U << 1)
+/* BPF_F_TEST_RND_HI32 is used in BPF_PROG_LOAD command for testing purpose. + * Verifier does sub-register def/use analysis and identifies instructions whose + * def only matters for low 32-bit, high 32-bit is never referenced later + * through implicit zero extension. Therefore verifier notifies JIT back-ends + * that it is safe to ignore clearing high 32-bit for these instructions. This + * saves some back-ends a lot of code-gen. However such optimization is not + * necessary on some arches, for example x86_64, arm64 etc, whose JIT back-ends + * hence hasn't used verifier's analysis result. But, we really want to have a + * way to be able to verify the correctness of the described optimization on + * x86_64 on which testsuites are frequently exercised. + * + * So, this flag is introduced. Once it is set, verifier will randomize high + * 32-bit for those instructions who has been identified as safe to ignore them. + * Then, if verifier is not doing correct analysis, such randomization will + * regress tests to expose bugs. + */ +#define BPF_F_TEST_RND_HI32 (1U << 2) + /* When BPF ldimm64's insn[0].src_reg != 0 then this can have * two extensions: * @@@ -1767,7 -1746,6 +1767,7 @@@ union bpf_attr * * **BPF_SOCK_OPS_RTO_CB_FLAG** (retransmission time out) * * **BPF_SOCK_OPS_RETRANS_CB_FLAG** (retransmission) * * **BPF_SOCK_OPS_STATE_CB_FLAG** (TCP state change) + * * **BPF_SOCK_OPS_RTT_CB_FLAG** (every RTT) * * Therefore, this function can be used to clear a callback flag by * setting the appropriate bit to zero. e.g. to disable the RTO @@@ -2696,20 -2674,6 +2696,20 @@@ * 0 on success. * * **-ENOENT** if the bpf-local-storage cannot be found. + * + * int bpf_send_signal(u32 sig) + * Description + * Send signal *sig* to the current task. + * Return + * 0 on success or successfully queued. + * + * **-EBUSY** if work queue under nmi is full. + * + * **-EINVAL** if *sig* is invalid. + * + * **-EPERM** if no permission to send the *sig*. + * + * **-EAGAIN** if bpf program can try again. */ #define __BPF_FUNC_MAPPER(FN) \ FN(unspec), \ @@@ -2820,8 -2784,7 +2820,8 @@@ FN(strtol), \ FN(strtoul), \ FN(sk_storage_get), \ - FN(sk_storage_delete), + FN(sk_storage_delete), \ + FN(send_signal),
/* integer value in 'imm' field of BPF_CALL instruction selects which helper * function eBPF program intends to call @@@ -3070,12 -3033,6 +3070,12 @@@ struct bpf_tcp_sock * sum(delta(snd_una)), or how many bytes * were acked. */ + __u32 dsack_dups; /* RFC4898 tcpEStatsStackDSACKDups + * total number of DSACK blocks received + */ + __u32 delivered; /* Total data packets delivered incl. rexmits */ + __u32 delivered_ce; /* Like the above but only ECE marked packets */ + __u32 icsk_retransmits; /* Number of unrecovered [RTO] timeouts */ };
struct bpf_sock_tuple { @@@ -3095,10 -3052,6 +3095,10 @@@ }; };
+struct bpf_xdp_sock { + __u32 queue_id; +}; + #define XDP_PACKET_HEADROOM 256
/* User return codes for XDP prog type. @@@ -3190,6 -3143,7 +3190,7 @@@ struct bpf_prog_info char name[BPF_OBJ_NAME_LEN]; __u32 ifindex; __u32 gpl_compatible:1; + __u32 :31; /* alignment pad */ __u64 netns_dev; __u64 netns_ino; __u32 nr_jited_ksyms; @@@ -3244,7 -3198,7 +3245,7 @@@ struct bpf_sock_addr __u32 user_ip4; /* Allows 1,2,4-byte read and 4-byte write. * Stored in network byte order. */ - __u32 user_ip6[4]; /* Allows 1,2,4-byte read an 4-byte write. + __u32 user_ip6[4]; /* Allows 1,2,4-byte read and 4,8-byte write. * Stored in network byte order. */ __u32 user_port; /* Allows 4-byte read and write. @@@ -3253,13 -3207,12 +3254,13 @@@ __u32 family; /* Allows 4-byte read, but no write */ __u32 type; /* Allows 4-byte read, but no write */ __u32 protocol; /* Allows 4-byte read, but no write */ - __u32 msg_src_ip4; /* Allows 1,2,4-byte read an 4-byte write. + __u32 msg_src_ip4; /* Allows 1,2,4-byte read and 4-byte write. * Stored in network byte order. */ - __u32 msg_src_ip6[4]; /* Allows 1,2,4-byte read an 4-byte write. + __u32 msg_src_ip6[4]; /* Allows 1,2,4-byte read and 4,8-byte write. * Stored in network byte order. */ + __bpf_md_ptr(struct bpf_sock *, sk); };
/* User bpf_sock_ops struct to access socket values and specify request ops @@@ -3311,15 -3264,13 +3312,15 @@@ struct bpf_sock_ops __u32 sk_txhash; __u64 bytes_received; __u64 bytes_acked; + __bpf_md_ptr(struct bpf_sock *, sk); };
/* Definitions for bpf_sock_ops_cb_flags */ #define BPF_SOCK_OPS_RTO_CB_FLAG (1<<0) #define BPF_SOCK_OPS_RETRANS_CB_FLAG (1<<1) #define BPF_SOCK_OPS_STATE_CB_FLAG (1<<2) -#define BPF_SOCK_OPS_ALL_CB_FLAGS 0x7 /* Mask of all currently +#define BPF_SOCK_OPS_RTT_CB_FLAG (1<<3) +#define BPF_SOCK_OPS_ALL_CB_FLAGS 0xF /* Mask of all currently * supported cb flags */
@@@ -3374,8 -3325,6 +3375,8 @@@ enum BPF_SOCK_OPS_TCP_LISTEN_CB, /* Called on listen(2), right after * socket transition to LISTEN state. */ + BPF_SOCK_OPS_RTT_CB, /* Called on every RTT. + */ };
/* List of TCP states. There is a build check in net/ipv4/tcp.c to detect @@@ -3554,15 -3503,4 +3555,15 @@@ struct bpf_sysctl */ };
+struct bpf_sockopt { + __bpf_md_ptr(struct bpf_sock *, sk); + __bpf_md_ptr(void *, optval); + __bpf_md_ptr(void *, optval_end); + + __s32 level; + __s32 optname; + __s32 optlen; + __s32 retval; +}; + #endif /* _UAPI__LINUX_BPF_H__ */ diff --combined tools/testing/selftests/bpf/progs/test_lwt_seg6local.c index 7c7cb3177463,e2f6ed0a583d..a334a0e882e4 --- a/tools/testing/selftests/bpf/progs/test_lwt_seg6local.c +++ b/tools/testing/selftests/bpf/progs/test_lwt_seg6local.c @@@ -6,6 -6,13 +6,6 @@@ #include "bpf_helpers.h" #include "bpf_endian.h"
-#define bpf_printk(fmt, ...) \ -({ \ - char ____fmt[] = fmt; \ - bpf_trace_printk(____fmt, sizeof(____fmt), \ - ##__VA_ARGS__); \ -}) - /* Packet parsing state machine helpers. */ #define cursor_advance(_cursor, _len) \ ({ void *_tmp = _cursor; _cursor += _len; _tmp; }) @@@ -54,7 -61,7 +54,7 @@@ struct sr6_tlv_t unsigned char value[0]; } BPF_PACKET_HEADER;
- __attribute__((always_inline)) struct ip6_srh_t *get_srh(struct __sk_buff *skb) + static __always_inline struct ip6_srh_t *get_srh(struct __sk_buff *skb) { void *cursor, *data_end; struct ip6_srh_t *srh; @@@ -88,7 -95,7 +88,7 @@@ return srh; }
- __attribute__((always_inline)) + static __always_inline int update_tlv_pad(struct __sk_buff *skb, uint32_t new_pad, uint32_t old_pad, uint32_t pad_off) { @@@ -118,7 -125,7 +118,7 @@@ return 0; }
- __attribute__((always_inline)) + static __always_inline int is_valid_tlv_boundary(struct __sk_buff *skb, struct ip6_srh_t *srh, uint32_t *tlv_off, uint32_t *pad_size, uint32_t *pad_off) @@@ -177,7 -184,7 +177,7 @@@ return 0; }
- __attribute__((always_inline)) + static __always_inline int add_tlv(struct __sk_buff *skb, struct ip6_srh_t *srh, uint32_t tlv_off, struct sr6_tlv_t *itlv, uint8_t tlv_size) { @@@ -221,7 -228,7 +221,7 @@@ return update_tlv_pad(skb, new_pad, pad_size, pad_off); }
- __attribute__((always_inline)) + static __always_inline int delete_tlv(struct __sk_buff *skb, struct ip6_srh_t *srh, uint32_t tlv_off) { @@@ -259,7 -266,7 +259,7 @@@ return update_tlv_pad(skb, new_pad, pad_size, pad_off); }
- __attribute__((always_inline)) + static __always_inline int has_egr_tlv(struct __sk_buff *skb, struct ip6_srh_t *srh) { int tlv_offset = sizeof(struct ip6_t) + sizeof(struct ip6_srh_t) + diff --combined tools/testing/selftests/net/config index e4b878d95ba0,3dea2cba2325..b8503a8119b0 --- a/tools/testing/selftests/net/config +++ b/tools/testing/selftests/net/config @@@ -25,6 -25,4 +25,7 @@@ CONFIG_NF_TABLES_IPV6= CONFIG_NF_TABLES_IPV4=y CONFIG_NFT_CHAIN_NAT_IPV6=m CONFIG_NFT_CHAIN_NAT_IPV4=m +CONFIG_NET_SCH_FQ=m +CONFIG_NET_SCH_ETF=m +CONFIG_TEST_BLACKHOLE_DEV=m + CONFIG_KALLSYMS=y diff --combined tools/testing/selftests/tc-testing/tc-tests/filters/tests.json index 8135778040c2,16559c436f21..0f89cd50a94b --- a/tools/testing/selftests/tc-testing/tc-tests/filters/tests.json +++ b/tools/testing/selftests/tc-testing/tc-tests/filters/tests.json @@@ -6,9 -6,6 +6,9 @@@ "filter", "u32" ], + "plugins": { + "requires": "nsPlugin" + }, "setup": [ "$TC qdisc add dev $DEV1 ingress" ], @@@ -28,9 -25,6 +28,9 @@@ "filter", "matchall" ], + "plugins": { + "requires": "nsPlugin" + }, "setup": [ "$TC qdisc add dev $DEV1 clsact", "$TC filter add dev $DEV1 protocol all pref 1 ingress handle 0x1234 matchall action ok" @@@ -45,15 -39,31 +45,34 @@@ ] }, { + "id": "2ff3", + "name": "Add flower with max handle and then dump it", + "category": [ + "filter", + "flower" + ], + "setup": [ + "$TC qdisc add dev $DEV2 ingress" + ], + "cmdUnderTest": "$TC filter add dev $DEV2 protocol ip pref 1 parent ffff: handle 0xffffffff flower action ok", + "expExitCode": "0", + "verifyCmd": "$TC filter show dev $DEV2 ingress", + "matchPattern": "filter protocol ip pref 1 flower.*handle 0xffffffff", + "matchCount": "1", + "teardown": [ + "$TC qdisc del dev $DEV2 ingress" + ] + }, + { "id": "d052", "name": "Add 1M filters with the same action", "category": [ "filter", "flower" ], + "plugins": { + "requires": "nsPlugin" + }, "setup": [ "$TC qdisc add dev $DEV2 ingress", "./tdc_batch.py $DEV2 $BATCH_FILE --share_action -n 1000000" @@@ -75,9 -85,6 +94,9 @@@ "filter", "flower" ], + "plugins": { + "requires": "nsPlugin" + }, "setup": [ "$TC qdisc add dev $DEV2 ingress", "$TC filter add dev $DEV2 protocol ip prio 1 parent ffff: flower dst_mac e4:11:22:11:4a:51 src_mac e4:11:22:11:4a:50 ip_proto tcp src_ip 1.1.1.1 dst_ip 2.2.2.2 action drop"
linux-merge@lists.open-mesh.org