Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
Pull networking fixes from David Miller: "Lots of bug fixes here: 1) Out of bounds access in __bpf_skc_lookup, from Lorenz Bauer. 2) Fix rate reporting in cfg80211_calculate_bitrate_he(), from John Crispin. 3) Use after free in psock backlog workqueue, from John Fastabend. 4) Fix source port matching in fdb peer flow rule of mlx5, from Raed Salem. 5) Use atomic_inc_not_zero() in fl6_sock_lookup(), from Eric Dumazet. 6) Network header needs to be set for packet redirect in nfp, from John Hurley. 7) Fix udp zerocopy refcnt, from Willem de Bruijn. 8) Don't assume linear buffers in vxlan and geneve error handlers, from Stefano Brivio. 9) Fix TOS matching in mlxsw, from Jiri Pirko. 10) More SCTP cookie memory leak fixes, from Neil Horman. 11) Fix VLAN filtering in rtl8366, from Linus Walluij. 12) Various TCP SACK payload size and fragmentation memory limit fixes from Eric Dumazet. 13) Use after free in pneigh_get_next(), also from Eric Dumazet. 14) LAPB control block leak fix from Jeremy Sowden" * git://git.kernel.org/pub/scm/linux/kernel/git/davem/net: (145 commits) lapb: fixed leak of control-blocks. tipc: purge deferredq list for each grp member in tipc_group_delete ax25: fix inconsistent lock state in ax25_destroy_timer neigh: fix use-after-free read in pneigh_get_next tcp: fix compile error if !CONFIG_SYSCTL hv_sock: Suppress bogus "may be used uninitialized" warnings be2net: Fix number of Rx queues used for flow hashing net: handle 802.1P vlan 0 packets properly tcp: enforce tcp_min_snd_mss in tcp_mtu_probing() tcp: add tcp_min_snd_mss sysctl tcp: tcp_fragment() should apply sane memory limits tcp: limit payload size of sacked skbs Revert "net: phylink: set the autoneg state in phylink_phy_change" bpf: fix nested bpf tracepoints with per-cpu data bpf: Fix out of bounds memory access in bpf_sk_storage vsock/virtio: set SOCK_DONE on peer shutdown net: dsa: rtl8366: Fix up VLAN filtering net: phylink: set the autoneg state in phylink_phy_change net: add high_order_alloc_disable sysctl/static key tcp: add tcp_tx_skb_cache sysctl ...
This commit is contained in:
commit
da0f382029
|
@ -29,7 +29,7 @@ Contact: Bjørn Mork <bjorn@mork.no>
|
|||
Description:
|
||||
Unsigned integer.
|
||||
|
||||
Write a number ranging from 1 to 127 to add a qmap mux
|
||||
Write a number ranging from 1 to 254 to add a qmap mux
|
||||
based network device, supported by recent Qualcomm based
|
||||
modems.
|
||||
|
||||
|
@ -46,5 +46,5 @@ Contact: Bjørn Mork <bjorn@mork.no>
|
|||
Description:
|
||||
Unsigned integer.
|
||||
|
||||
Write a number ranging from 1 to 127 to delete a previously
|
||||
Write a number ranging from 1 to 254 to delete a previously
|
||||
created qmap mux based network device.
|
||||
|
|
|
@ -4,6 +4,7 @@ Required properties:
|
|||
- compatible: Should be one of the following:
|
||||
- "microchip,mcp2510" for MCP2510.
|
||||
- "microchip,mcp2515" for MCP2515.
|
||||
- "microchip,mcp25625" for MCP25625.
|
||||
- reg: SPI chip select.
|
||||
- clocks: The clock feeding the CAN controller.
|
||||
- interrupts: Should contain IRQ line for the CAN controller.
|
||||
|
|
|
@ -316,16 +316,16 @@ A: When a netdev of a physical NIC is initialized, Linux usually
|
|||
all the traffic, you can force the netdev to only have 1 queue, queue
|
||||
id 0, and then bind to queue 0. You can use ethtool to do this::
|
||||
|
||||
sudo ethtool -L <interface> combined 1
|
||||
sudo ethtool -L <interface> combined 1
|
||||
|
||||
If you want to only see part of the traffic, you can program the
|
||||
NIC through ethtool to filter out your traffic to a single queue id
|
||||
that you can bind your XDP socket to. Here is one example in which
|
||||
UDP traffic to and from port 4242 are sent to queue 2::
|
||||
|
||||
sudo ethtool -N <interface> rx-flow-hash udp4 fn
|
||||
sudo ethtool -N <interface> flow-type udp4 src-port 4242 dst-port \
|
||||
4242 action 2
|
||||
sudo ethtool -N <interface> rx-flow-hash udp4 fn
|
||||
sudo ethtool -N <interface> flow-type udp4 src-port 4242 dst-port \
|
||||
4242 action 2
|
||||
|
||||
A number of other ways are possible all up to the capabilitites of
|
||||
the NIC you have.
|
||||
|
|
|
@ -255,6 +255,14 @@ tcp_base_mss - INTEGER
|
|||
Path MTU discovery (MTU probing). If MTU probing is enabled,
|
||||
this is the initial MSS used by the connection.
|
||||
|
||||
tcp_min_snd_mss - INTEGER
|
||||
TCP SYN and SYNACK messages usually advertise an ADVMSS option,
|
||||
as described in RFC 1122 and RFC 6691.
|
||||
If this ADVMSS option is smaller than tcp_min_snd_mss,
|
||||
it is silently capped to tcp_min_snd_mss.
|
||||
|
||||
Default : 48 (at least 8 bytes of payload per segment)
|
||||
|
||||
tcp_congestion_control - STRING
|
||||
Set the congestion control algorithm to be used for new
|
||||
connections. The algorithm "reno" is always available, but
|
||||
|
@ -772,6 +780,14 @@ tcp_challenge_ack_limit - INTEGER
|
|||
in RFC 5961 (Improving TCP's Robustness to Blind In-Window Attacks)
|
||||
Default: 100
|
||||
|
||||
tcp_rx_skb_cache - BOOLEAN
|
||||
Controls a per TCP socket cache of one skb, that might help
|
||||
performance of some workloads. This might be dangerous
|
||||
on systems with a lot of TCP sockets, since it increases
|
||||
memory usage.
|
||||
|
||||
Default: 0 (disabled)
|
||||
|
||||
UDP variables:
|
||||
|
||||
udp_l3mdev_accept - BOOLEAN
|
||||
|
|
|
@ -389,7 +389,7 @@ Multipath RDS (mprds)
|
|||
a common (to all paths) part, and a per-path struct rds_conn_path. All
|
||||
I/O workqs and reconnect threads are driven from the rds_conn_path.
|
||||
Transports such as TCP that are multipath capable may then set up a
|
||||
TPC socket per rds_conn_path, and this is managed by the transport via
|
||||
TCP socket per rds_conn_path, and this is managed by the transport via
|
||||
the transport privatee cp_transport_data pointer.
|
||||
|
||||
Transports announce themselves as multipath capable by setting the
|
||||
|
|
|
@ -338,6 +338,7 @@
|
|||
#define PPC_INST_MADDLD 0x10000033
|
||||
#define PPC_INST_DIVWU 0x7c000396
|
||||
#define PPC_INST_DIVD 0x7c0003d2
|
||||
#define PPC_INST_DIVDU 0x7c000392
|
||||
#define PPC_INST_RLWINM 0x54000000
|
||||
#define PPC_INST_RLWINM_DOT 0x54000001
|
||||
#define PPC_INST_RLWIMI 0x50000000
|
||||
|
|
|
@ -112,7 +112,7 @@
|
|||
___PPC_RA(a) | IMM_L(i))
|
||||
#define PPC_DIVWU(d, a, b) EMIT(PPC_INST_DIVWU | ___PPC_RT(d) | \
|
||||
___PPC_RA(a) | ___PPC_RB(b))
|
||||
#define PPC_DIVD(d, a, b) EMIT(PPC_INST_DIVD | ___PPC_RT(d) | \
|
||||
#define PPC_DIVDU(d, a, b) EMIT(PPC_INST_DIVDU | ___PPC_RT(d) | \
|
||||
___PPC_RA(a) | ___PPC_RB(b))
|
||||
#define PPC_AND(d, a, b) EMIT(PPC_INST_AND | ___PPC_RA(d) | \
|
||||
___PPC_RS(a) | ___PPC_RB(b))
|
||||
|
|
|
@ -395,12 +395,12 @@ static int bpf_jit_build_body(struct bpf_prog *fp, u32 *image,
|
|||
case BPF_ALU64 | BPF_DIV | BPF_X: /* dst /= src */
|
||||
case BPF_ALU64 | BPF_MOD | BPF_X: /* dst %= src */
|
||||
if (BPF_OP(code) == BPF_MOD) {
|
||||
PPC_DIVD(b2p[TMP_REG_1], dst_reg, src_reg);
|
||||
PPC_DIVDU(b2p[TMP_REG_1], dst_reg, src_reg);
|
||||
PPC_MULD(b2p[TMP_REG_1], src_reg,
|
||||
b2p[TMP_REG_1]);
|
||||
PPC_SUB(dst_reg, dst_reg, b2p[TMP_REG_1]);
|
||||
} else
|
||||
PPC_DIVD(dst_reg, dst_reg, src_reg);
|
||||
PPC_DIVDU(dst_reg, dst_reg, src_reg);
|
||||
break;
|
||||
case BPF_ALU | BPF_MOD | BPF_K: /* (u32) dst %= (u32) imm */
|
||||
case BPF_ALU | BPF_DIV | BPF_K: /* (u32) dst /= (u32) imm */
|
||||
|
@ -428,7 +428,7 @@ static int bpf_jit_build_body(struct bpf_prog *fp, u32 *image,
|
|||
break;
|
||||
case BPF_ALU64:
|
||||
if (BPF_OP(code) == BPF_MOD) {
|
||||
PPC_DIVD(b2p[TMP_REG_2], dst_reg,
|
||||
PPC_DIVDU(b2p[TMP_REG_2], dst_reg,
|
||||
b2p[TMP_REG_1]);
|
||||
PPC_MULD(b2p[TMP_REG_1],
|
||||
b2p[TMP_REG_1],
|
||||
|
@ -436,7 +436,7 @@ static int bpf_jit_build_body(struct bpf_prog *fp, u32 *image,
|
|||
PPC_SUB(dst_reg, dst_reg,
|
||||
b2p[TMP_REG_1]);
|
||||
} else
|
||||
PPC_DIVD(dst_reg, dst_reg,
|
||||
PPC_DIVDU(dst_reg, dst_reg,
|
||||
b2p[TMP_REG_1]);
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -751,22 +751,32 @@ static int emit_insn(const struct bpf_insn *insn, struct rv_jit_context *ctx,
|
|||
case BPF_ALU | BPF_ADD | BPF_X:
|
||||
case BPF_ALU64 | BPF_ADD | BPF_X:
|
||||
emit(is64 ? rv_add(rd, rd, rs) : rv_addw(rd, rd, rs), ctx);
|
||||
if (!is64)
|
||||
emit_zext_32(rd, ctx);
|
||||
break;
|
||||
case BPF_ALU | BPF_SUB | BPF_X:
|
||||
case BPF_ALU64 | BPF_SUB | BPF_X:
|
||||
emit(is64 ? rv_sub(rd, rd, rs) : rv_subw(rd, rd, rs), ctx);
|
||||
if (!is64)
|
||||
emit_zext_32(rd, ctx);
|
||||
break;
|
||||
case BPF_ALU | BPF_AND | BPF_X:
|
||||
case BPF_ALU64 | BPF_AND | BPF_X:
|
||||
emit(rv_and(rd, rd, rs), ctx);
|
||||
if (!is64)
|
||||
emit_zext_32(rd, ctx);
|
||||
break;
|
||||
case BPF_ALU | BPF_OR | BPF_X:
|
||||
case BPF_ALU64 | BPF_OR | BPF_X:
|
||||
emit(rv_or(rd, rd, rs), ctx);
|
||||
if (!is64)
|
||||
emit_zext_32(rd, ctx);
|
||||
break;
|
||||
case BPF_ALU | BPF_XOR | BPF_X:
|
||||
case BPF_ALU64 | BPF_XOR | BPF_X:
|
||||
emit(rv_xor(rd, rd, rs), ctx);
|
||||
if (!is64)
|
||||
emit_zext_32(rd, ctx);
|
||||
break;
|
||||
case BPF_ALU | BPF_MUL | BPF_X:
|
||||
case BPF_ALU64 | BPF_MUL | BPF_X:
|
||||
|
@ -789,14 +799,20 @@ static int emit_insn(const struct bpf_insn *insn, struct rv_jit_context *ctx,
|
|||
case BPF_ALU | BPF_LSH | BPF_X:
|
||||
case BPF_ALU64 | BPF_LSH | BPF_X:
|
||||
emit(is64 ? rv_sll(rd, rd, rs) : rv_sllw(rd, rd, rs), ctx);
|
||||
if (!is64)
|
||||
emit_zext_32(rd, ctx);
|
||||
break;
|
||||
case BPF_ALU | BPF_RSH | BPF_X:
|
||||
case BPF_ALU64 | BPF_RSH | BPF_X:
|
||||
emit(is64 ? rv_srl(rd, rd, rs) : rv_srlw(rd, rd, rs), ctx);
|
||||
if (!is64)
|
||||
emit_zext_32(rd, ctx);
|
||||
break;
|
||||
case BPF_ALU | BPF_ARSH | BPF_X:
|
||||
case BPF_ALU64 | BPF_ARSH | BPF_X:
|
||||
emit(is64 ? rv_sra(rd, rd, rs) : rv_sraw(rd, rd, rs), ctx);
|
||||
if (!is64)
|
||||
emit_zext_32(rd, ctx);
|
||||
break;
|
||||
|
||||
/* dst = -dst */
|
||||
|
@ -804,6 +820,8 @@ static int emit_insn(const struct bpf_insn *insn, struct rv_jit_context *ctx,
|
|||
case BPF_ALU64 | BPF_NEG:
|
||||
emit(is64 ? rv_sub(rd, RV_REG_ZERO, rd) :
|
||||
rv_subw(rd, RV_REG_ZERO, rd), ctx);
|
||||
if (!is64)
|
||||
emit_zext_32(rd, ctx);
|
||||
break;
|
||||
|
||||
/* dst = BSWAP##imm(dst) */
|
||||
|
@ -958,14 +976,20 @@ out_be:
|
|||
case BPF_ALU | BPF_LSH | BPF_K:
|
||||
case BPF_ALU64 | BPF_LSH | BPF_K:
|
||||
emit(is64 ? rv_slli(rd, rd, imm) : rv_slliw(rd, rd, imm), ctx);
|
||||
if (!is64)
|
||||
emit_zext_32(rd, ctx);
|
||||
break;
|
||||
case BPF_ALU | BPF_RSH | BPF_K:
|
||||
case BPF_ALU64 | BPF_RSH | BPF_K:
|
||||
emit(is64 ? rv_srli(rd, rd, imm) : rv_srliw(rd, rd, imm), ctx);
|
||||
if (!is64)
|
||||
emit_zext_32(rd, ctx);
|
||||
break;
|
||||
case BPF_ALU | BPF_ARSH | BPF_K:
|
||||
case BPF_ALU64 | BPF_ARSH | BPF_K:
|
||||
emit(is64 ? rv_srai(rd, rd, imm) : rv_sraiw(rd, rd, imm), ctx);
|
||||
if (!is64)
|
||||
emit_zext_32(rd, ctx);
|
||||
break;
|
||||
|
||||
/* JUMP off */
|
||||
|
|
|
@ -186,9 +186,7 @@ struct jit_context {
|
|||
#define BPF_MAX_INSN_SIZE 128
|
||||
#define BPF_INSN_SAFETY 64
|
||||
|
||||
#define AUX_STACK_SPACE 40 /* Space for RBX, R13, R14, R15, tailcnt */
|
||||
|
||||
#define PROLOGUE_SIZE 37
|
||||
#define PROLOGUE_SIZE 20
|
||||
|
||||
/*
|
||||
* Emit x86-64 prologue code for BPF program and check its size.
|
||||
|
@ -199,44 +197,19 @@ static void emit_prologue(u8 **pprog, u32 stack_depth, bool ebpf_from_cbpf)
|
|||
u8 *prog = *pprog;
|
||||
int cnt = 0;
|
||||
|
||||
/* push rbp */
|
||||
EMIT1(0x55);
|
||||
|
||||
/* mov rbp,rsp */
|
||||
EMIT3(0x48, 0x89, 0xE5);
|
||||
|
||||
/* sub rsp, rounded_stack_depth + AUX_STACK_SPACE */
|
||||
EMIT3_off32(0x48, 0x81, 0xEC,
|
||||
round_up(stack_depth, 8) + AUX_STACK_SPACE);
|
||||
|
||||
/* sub rbp, AUX_STACK_SPACE */
|
||||
EMIT4(0x48, 0x83, 0xED, AUX_STACK_SPACE);
|
||||
|
||||
/* mov qword ptr [rbp+0],rbx */
|
||||
EMIT4(0x48, 0x89, 0x5D, 0);
|
||||
/* mov qword ptr [rbp+8],r13 */
|
||||
EMIT4(0x4C, 0x89, 0x6D, 8);
|
||||
/* mov qword ptr [rbp+16],r14 */
|
||||
EMIT4(0x4C, 0x89, 0x75, 16);
|
||||
/* mov qword ptr [rbp+24],r15 */
|
||||
EMIT4(0x4C, 0x89, 0x7D, 24);
|
||||
|
||||
EMIT1(0x55); /* push rbp */
|
||||
EMIT3(0x48, 0x89, 0xE5); /* mov rbp, rsp */
|
||||
/* sub rsp, rounded_stack_depth */
|
||||
EMIT3_off32(0x48, 0x81, 0xEC, round_up(stack_depth, 8));
|
||||
EMIT1(0x53); /* push rbx */
|
||||
EMIT2(0x41, 0x55); /* push r13 */
|
||||
EMIT2(0x41, 0x56); /* push r14 */
|
||||
EMIT2(0x41, 0x57); /* push r15 */
|
||||
if (!ebpf_from_cbpf) {
|
||||
/*
|
||||
* Clear the tail call counter (tail_call_cnt): for eBPF tail
|
||||
* calls we need to reset the counter to 0. It's done in two
|
||||
* instructions, resetting RAX register to 0, and moving it
|
||||
* to the counter location.
|
||||
*/
|
||||
|
||||
/* xor eax, eax */
|
||||
EMIT2(0x31, 0xc0);
|
||||
/* mov qword ptr [rbp+32], rax */
|
||||
EMIT4(0x48, 0x89, 0x45, 32);
|
||||
|
||||
/* zero init tail_call_cnt */
|
||||
EMIT2(0x6a, 0x00);
|
||||
BUILD_BUG_ON(cnt != PROLOGUE_SIZE);
|
||||
}
|
||||
|
||||
*pprog = prog;
|
||||
}
|
||||
|
||||
|
@ -281,13 +254,13 @@ static void emit_bpf_tail_call(u8 **pprog)
|
|||
* if (tail_call_cnt > MAX_TAIL_CALL_CNT)
|
||||
* goto out;
|
||||
*/
|
||||
EMIT2_off32(0x8B, 0x85, 36); /* mov eax, dword ptr [rbp + 36] */
|
||||
EMIT2_off32(0x8B, 0x85, -36 - MAX_BPF_STACK); /* mov eax, dword ptr [rbp - 548] */
|
||||
EMIT3(0x83, 0xF8, MAX_TAIL_CALL_CNT); /* cmp eax, MAX_TAIL_CALL_CNT */
|
||||
#define OFFSET2 (30 + RETPOLINE_RAX_BPF_JIT_SIZE)
|
||||
EMIT2(X86_JA, OFFSET2); /* ja out */
|
||||
label2 = cnt;
|
||||
EMIT3(0x83, 0xC0, 0x01); /* add eax, 1 */
|
||||
EMIT2_off32(0x89, 0x85, 36); /* mov dword ptr [rbp + 36], eax */
|
||||
EMIT2_off32(0x89, 0x85, -36 - MAX_BPF_STACK); /* mov dword ptr [rbp -548], eax */
|
||||
|
||||
/* prog = array->ptrs[index]; */
|
||||
EMIT4_off32(0x48, 0x8B, 0x84, 0xD6, /* mov rax, [rsi + rdx * 8 + offsetof(...)] */
|
||||
|
@ -1036,19 +1009,14 @@ emit_jmp:
|
|||
seen_exit = true;
|
||||
/* Update cleanup_addr */
|
||||
ctx->cleanup_addr = proglen;
|
||||
/* mov rbx, qword ptr [rbp+0] */
|
||||
EMIT4(0x48, 0x8B, 0x5D, 0);
|
||||
/* mov r13, qword ptr [rbp+8] */
|
||||
EMIT4(0x4C, 0x8B, 0x6D, 8);
|
||||
/* mov r14, qword ptr [rbp+16] */
|
||||
EMIT4(0x4C, 0x8B, 0x75, 16);
|
||||
/* mov r15, qword ptr [rbp+24] */
|
||||
EMIT4(0x4C, 0x8B, 0x7D, 24);
|
||||
|
||||
/* add rbp, AUX_STACK_SPACE */
|
||||
EMIT4(0x48, 0x83, 0xC5, AUX_STACK_SPACE);
|
||||
EMIT1(0xC9); /* leave */
|
||||
EMIT1(0xC3); /* ret */
|
||||
if (!bpf_prog_was_classic(bpf_prog))
|
||||
EMIT1(0x5B); /* get rid of tail_call_cnt */
|
||||
EMIT2(0x41, 0x5F); /* pop r15 */
|
||||
EMIT2(0x41, 0x5E); /* pop r14 */
|
||||
EMIT2(0x41, 0x5D); /* pop r13 */
|
||||
EMIT1(0x5B); /* pop rbx */
|
||||
EMIT1(0xC9); /* leave */
|
||||
EMIT1(0xC3); /* ret */
|
||||
break;
|
||||
|
||||
default:
|
||||
|
|
|
@ -166,7 +166,7 @@
|
|||
#define FLEXCAN_MB_CNT_LENGTH(x) (((x) & 0xf) << 16)
|
||||
#define FLEXCAN_MB_CNT_TIMESTAMP(x) ((x) & 0xffff)
|
||||
|
||||
#define FLEXCAN_TIMEOUT_US (50)
|
||||
#define FLEXCAN_TIMEOUT_US (250)
|
||||
|
||||
/* FLEXCAN hardware feature flags
|
||||
*
|
||||
|
@ -1583,9 +1583,6 @@ static int flexcan_probe(struct platform_device *pdev)
|
|||
dev_dbg(&pdev->dev, "failed to setup stop-mode\n");
|
||||
}
|
||||
|
||||
dev_info(&pdev->dev, "device registered (reg_base=%p, irq=%d)\n",
|
||||
priv->regs, dev->irq);
|
||||
|
||||
return 0;
|
||||
|
||||
failed_register:
|
||||
|
|
|
@ -822,6 +822,27 @@ static int m_can_poll(struct napi_struct *napi, int quota)
|
|||
if (!irqstatus)
|
||||
goto end;
|
||||
|
||||
/* Errata workaround for issue "Needless activation of MRAF irq"
|
||||
* During frame reception while the MCAN is in Error Passive state
|
||||
* and the Receive Error Counter has the value MCAN_ECR.REC = 127,
|
||||
* it may happen that MCAN_IR.MRAF is set although there was no
|
||||
* Message RAM access failure.
|
||||
* If MCAN_IR.MRAF is enabled, an interrupt to the Host CPU is generated
|
||||
* The Message RAM Access Failure interrupt routine needs to check
|
||||
* whether MCAN_ECR.RP = ’1’ and MCAN_ECR.REC = 127.
|
||||
* In this case, reset MCAN_IR.MRAF. No further action is required.
|
||||
*/
|
||||
if ((priv->version <= 31) && (irqstatus & IR_MRAF) &&
|
||||
(m_can_read(priv, M_CAN_ECR) & ECR_RP)) {
|
||||
struct can_berr_counter bec;
|
||||
|
||||
__m_can_get_berr_counter(dev, &bec);
|
||||
if (bec.rxerr == 127) {
|
||||
m_can_write(priv, M_CAN_IR, IR_MRAF);
|
||||
irqstatus &= ~IR_MRAF;
|
||||
}
|
||||
}
|
||||
|
||||
psr = m_can_read(priv, M_CAN_PSR);
|
||||
if (irqstatus & IR_ERR_STATE)
|
||||
work_done += m_can_handle_state_errors(dev, psr);
|
||||
|
|
|
@ -9,9 +9,10 @@ config CAN_HI311X
|
|||
Driver for the Holt HI311x SPI CAN controllers.
|
||||
|
||||
config CAN_MCP251X
|
||||
tristate "Microchip MCP251x SPI CAN controllers"
|
||||
tristate "Microchip MCP251x and MCP25625 SPI CAN controllers"
|
||||
depends on HAS_DMA
|
||||
---help---
|
||||
Driver for the Microchip MCP251x SPI CAN controllers.
|
||||
Driver for the Microchip MCP251x and MCP25625 SPI CAN
|
||||
controllers.
|
||||
|
||||
endmenu
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* CAN bus driver for Microchip 251x CAN Controller with SPI Interface
|
||||
* CAN bus driver for Microchip 251x/25625 CAN Controller with SPI Interface
|
||||
*
|
||||
* MCP2510 support and bug fixes by Christian Pellegrin
|
||||
* <chripell@evolware.org>
|
||||
|
@ -28,7 +28,7 @@
|
|||
* static struct spi_board_info spi_board_info[] = {
|
||||
* {
|
||||
* .modalias = "mcp2510",
|
||||
* // or "mcp2515" depending on your controller
|
||||
* // "mcp2515" or "mcp25625" depending on your controller
|
||||
* .platform_data = &mcp251x_info,
|
||||
* .irq = IRQ_EINT13,
|
||||
* .max_speed_hz = 2*1000*1000,
|
||||
|
@ -224,6 +224,7 @@ static const struct can_bittiming_const mcp251x_bittiming_const = {
|
|||
enum mcp251x_model {
|
||||
CAN_MCP251X_MCP2510 = 0x2510,
|
||||
CAN_MCP251X_MCP2515 = 0x2515,
|
||||
CAN_MCP251X_MCP25625 = 0x25625,
|
||||
};
|
||||
|
||||
struct mcp251x_priv {
|
||||
|
@ -266,7 +267,6 @@ static inline int mcp251x_is_##_model(struct spi_device *spi) \
|
|||
}
|
||||
|
||||
MCP251X_IS(2510);
|
||||
MCP251X_IS(2515);
|
||||
|
||||
static void mcp251x_clean(struct net_device *net)
|
||||
{
|
||||
|
@ -625,7 +625,7 @@ static int mcp251x_hw_reset(struct spi_device *spi)
|
|||
|
||||
/* Wait for oscillator startup timer after reset */
|
||||
mdelay(MCP251X_OST_DELAY_MS);
|
||||
|
||||
|
||||
reg = mcp251x_read_reg(spi, CANSTAT);
|
||||
if ((reg & CANCTRL_REQOP_MASK) != CANCTRL_REQOP_CONF)
|
||||
return -ENODEV;
|
||||
|
@ -806,9 +806,8 @@ static irqreturn_t mcp251x_can_ist(int irq, void *dev_id)
|
|||
/* receive buffer 0 */
|
||||
if (intf & CANINTF_RX0IF) {
|
||||
mcp251x_hw_rx(spi, 0);
|
||||
/*
|
||||
* Free one buffer ASAP
|
||||
* (The MCP2515 does this automatically.)
|
||||
/* Free one buffer ASAP
|
||||
* (The MCP2515/25625 does this automatically.)
|
||||
*/
|
||||
if (mcp251x_is_2510(spi))
|
||||
mcp251x_write_bits(spi, CANINTF, CANINTF_RX0IF, 0x00);
|
||||
|
@ -817,7 +816,7 @@ static irqreturn_t mcp251x_can_ist(int irq, void *dev_id)
|
|||
/* receive buffer 1 */
|
||||
if (intf & CANINTF_RX1IF) {
|
||||
mcp251x_hw_rx(spi, 1);
|
||||
/* the MCP2515 does this automatically */
|
||||
/* The MCP2515/25625 does this automatically. */
|
||||
if (mcp251x_is_2510(spi))
|
||||
clear_intf |= CANINTF_RX1IF;
|
||||
}
|
||||
|
@ -992,6 +991,10 @@ static const struct of_device_id mcp251x_of_match[] = {
|
|||
.compatible = "microchip,mcp2515",
|
||||
.data = (void *)CAN_MCP251X_MCP2515,
|
||||
},
|
||||
{
|
||||
.compatible = "microchip,mcp25625",
|
||||
.data = (void *)CAN_MCP251X_MCP25625,
|
||||
},
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, mcp251x_of_match);
|
||||
|
@ -1005,6 +1008,10 @@ static const struct spi_device_id mcp251x_id_table[] = {
|
|||
.name = "mcp2515",
|
||||
.driver_data = (kernel_ulong_t)CAN_MCP251X_MCP2515,
|
||||
},
|
||||
{
|
||||
.name = "mcp25625",
|
||||
.driver_data = (kernel_ulong_t)CAN_MCP251X_MCP25625,
|
||||
},
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(spi, mcp251x_id_table);
|
||||
|
@ -1245,5 +1252,5 @@ module_spi_driver(mcp251x_can_driver);
|
|||
|
||||
MODULE_AUTHOR("Chris Elston <celston@katalix.com>, "
|
||||
"Christian Pellegrin <chripell@evolware.org>");
|
||||
MODULE_DESCRIPTION("Microchip 251x CAN driver");
|
||||
MODULE_DESCRIPTION("Microchip 251x/25625 CAN driver");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
|
|
|
@ -102,12 +102,6 @@ config CAN_PEAK_USB
|
|||
|
||||
(see also http://www.peak-system.com).
|
||||
|
||||
config CAN_MCBA_USB
|
||||
tristate "Microchip CAN BUS Analyzer interface"
|
||||
---help---
|
||||
This driver supports the CAN BUS Analyzer interface
|
||||
from Microchip (http://www.microchip.com/development-tools/).
|
||||
|
||||
config CAN_UCAN
|
||||
tristate "Theobroma Systems UCAN interface"
|
||||
---help---
|
||||
|
|
|
@ -1435,7 +1435,7 @@ static const struct xcan_devtype_data xcan_canfd_data = {
|
|||
XCAN_FLAG_RXMNF |
|
||||
XCAN_FLAG_TX_MAILBOXES |
|
||||
XCAN_FLAG_RX_FIFO_MULTI,
|
||||
.bittiming_const = &xcan_bittiming_const,
|
||||
.bittiming_const = &xcan_bittiming_const_canfd,
|
||||
.btr_ts2_shift = XCAN_BTR_TS2_SHIFT_CANFD,
|
||||
.btr_sjw_shift = XCAN_BTR_SJW_SHIFT_CANFD,
|
||||
.bus_clk_name = "s_axi_aclk",
|
||||
|
|
|
@ -9,8 +9,8 @@ obj-$(CONFIG_NET_DSA_LANTIQ_GSWIP) += lantiq_gswip.o
|
|||
obj-$(CONFIG_NET_DSA_MT7530) += mt7530.o
|
||||
obj-$(CONFIG_NET_DSA_MV88E6060) += mv88e6060.o
|
||||
obj-$(CONFIG_NET_DSA_QCA8K) += qca8k.o
|
||||
obj-$(CONFIG_NET_DSA_REALTEK_SMI) += realtek.o
|
||||
realtek-objs := realtek-smi.o rtl8366.o rtl8366rb.o
|
||||
obj-$(CONFIG_NET_DSA_REALTEK_SMI) += realtek-smi.o
|
||||
realtek-smi-objs := realtek-smi-core.o rtl8366.o rtl8366rb.o
|
||||
obj-$(CONFIG_NET_DSA_SMSC_LAN9303) += lan9303-core.o
|
||||
obj-$(CONFIG_NET_DSA_SMSC_LAN9303_I2C) += lan9303_i2c.o
|
||||
obj-$(CONFIG_NET_DSA_SMSC_LAN9303_MDIO) += lan9303_mdio.o
|
||||
|
|
|
@ -83,6 +83,9 @@ static void ksz_mib_read_work(struct work_struct *work)
|
|||
int i;
|
||||
|
||||
for (i = 0; i < dev->mib_port_cnt; i++) {
|
||||
if (dsa_is_unused_port(dev->ds, i))
|
||||
continue;
|
||||
|
||||
p = &dev->ports[i];
|
||||
mib = &p->mib;
|
||||
mutex_lock(&mib->cnt_mutex);
|
||||
|
|
|
@ -40,7 +40,7 @@
|
|||
#include <linux/bitops.h>
|
||||
#include <linux/if_bridge.h>
|
||||
|
||||
#include "realtek-smi.h"
|
||||
#include "realtek-smi-core.h"
|
||||
|
||||
#define REALTEK_SMI_ACK_RETRY_COUNT 5
|
||||
#define REALTEK_SMI_HW_STOP_DELAY 25 /* msecs */
|
|
@ -11,7 +11,7 @@
|
|||
#include <linux/if_bridge.h>
|
||||
#include <net/dsa.h>
|
||||
|
||||
#include "realtek-smi.h"
|
||||
#include "realtek-smi-core.h"
|
||||
|
||||
int rtl8366_mc_is_used(struct realtek_smi *smi, int mc_index, int *used)
|
||||
{
|
||||
|
@ -307,7 +307,8 @@ int rtl8366_vlan_filtering(struct dsa_switch *ds, int port, bool vlan_filtering)
|
|||
struct rtl8366_vlan_4k vlan4k;
|
||||
int ret;
|
||||
|
||||
if (!smi->ops->is_vlan_valid(smi, port))
|
||||
/* Use VLAN nr port + 1 since VLAN0 is not valid */
|
||||
if (!smi->ops->is_vlan_valid(smi, port + 1))
|
||||
return -EINVAL;
|
||||
|
||||
dev_info(smi->dev, "%s filtering on port %d\n",
|
||||
|
@ -318,12 +319,12 @@ int rtl8366_vlan_filtering(struct dsa_switch *ds, int port, bool vlan_filtering)
|
|||
* The hardware support filter ID (FID) 0..7, I have no clue how to
|
||||
* support this in the driver when the callback only says on/off.
|
||||
*/
|
||||
ret = smi->ops->get_vlan_4k(smi, port, &vlan4k);
|
||||
ret = smi->ops->get_vlan_4k(smi, port + 1, &vlan4k);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Just set the filter to FID 1 for now then */
|
||||
ret = rtl8366_set_vlan(smi, port,
|
||||
ret = rtl8366_set_vlan(smi, port + 1,
|
||||
vlan4k.member,
|
||||
vlan4k.untag,
|
||||
1);
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
#include <linux/of_irq.h>
|
||||
#include <linux/regmap.h>
|
||||
|
||||
#include "realtek-smi.h"
|
||||
#include "realtek-smi-core.h"
|
||||
|
||||
#define RTL8366RB_PORT_NUM_CPU 5
|
||||
#define RTL8366RB_NUM_PORTS 6
|
||||
|
|
|
@ -50,7 +50,7 @@ config XSURF100
|
|||
tristate "Amiga XSurf 100 AX88796/NE2000 clone support"
|
||||
depends on ZORRO
|
||||
select AX88796
|
||||
select ASIX_PHY
|
||||
select AX88796B_PHY
|
||||
help
|
||||
This driver is for the Individual Computers X-Surf 100 Ethernet
|
||||
card (based on the Asix AX88796 chip). If you have such a card,
|
||||
|
|
|
@ -1101,7 +1101,7 @@ static int be_get_rxnfc(struct net_device *netdev, struct ethtool_rxnfc *cmd,
|
|||
cmd->data = be_get_rss_hash_opts(adapter, cmd->flow_type);
|
||||
break;
|
||||
case ETHTOOL_GRXRINGS:
|
||||
cmd->data = adapter->num_rx_qs - 1;
|
||||
cmd->data = adapter->num_rx_qs;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
|
|
|
@ -428,9 +428,10 @@ static int reset_rx_pools(struct ibmvnic_adapter *adapter)
|
|||
if (rx_pool->buff_size != be64_to_cpu(size_array[i])) {
|
||||
free_long_term_buff(adapter, &rx_pool->long_term_buff);
|
||||
rx_pool->buff_size = be64_to_cpu(size_array[i]);
|
||||
alloc_long_term_buff(adapter, &rx_pool->long_term_buff,
|
||||
rx_pool->size *
|
||||
rx_pool->buff_size);
|
||||
rc = alloc_long_term_buff(adapter,
|
||||
&rx_pool->long_term_buff,
|
||||
rx_pool->size *
|
||||
rx_pool->buff_size);
|
||||
} else {
|
||||
rc = reset_long_term_buff(adapter,
|
||||
&rx_pool->long_term_buff);
|
||||
|
@ -696,9 +697,9 @@ static int init_tx_pools(struct net_device *netdev)
|
|||
return rc;
|
||||
}
|
||||
|
||||
init_one_tx_pool(netdev, &adapter->tso_pool[i],
|
||||
IBMVNIC_TSO_BUFS,
|
||||
IBMVNIC_TSO_BUF_SZ);
|
||||
rc = init_one_tx_pool(netdev, &adapter->tso_pool[i],
|
||||
IBMVNIC_TSO_BUFS,
|
||||
IBMVNIC_TSO_BUF_SZ);
|
||||
if (rc) {
|
||||
release_tx_pools(adapter);
|
||||
return rc;
|
||||
|
@ -1745,7 +1746,8 @@ static int do_reset(struct ibmvnic_adapter *adapter,
|
|||
|
||||
ibmvnic_cleanup(netdev);
|
||||
|
||||
if (adapter->reset_reason != VNIC_RESET_MOBILITY &&
|
||||
if (reset_state == VNIC_OPEN &&
|
||||
adapter->reset_reason != VNIC_RESET_MOBILITY &&
|
||||
adapter->reset_reason != VNIC_RESET_FAILOVER) {
|
||||
rc = __ibmvnic_close(netdev);
|
||||
if (rc)
|
||||
|
@ -1844,6 +1846,9 @@ static int do_reset(struct ibmvnic_adapter *adapter,
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* refresh device's multicast list */
|
||||
ibmvnic_set_multi(netdev);
|
||||
|
||||
/* kick napi */
|
||||
for (i = 0; i < adapter->req_rx_queues; i++)
|
||||
napi_schedule(&adapter->napi[i]);
|
||||
|
|
|
@ -1905,8 +1905,7 @@ static int mvpp2_prs_ip6_init(struct mvpp2 *priv)
|
|||
}
|
||||
|
||||
/* Find tcam entry with matched pair <vid,port> */
|
||||
static int mvpp2_prs_vid_range_find(struct mvpp2 *priv, int pmap, u16 vid,
|
||||
u16 mask)
|
||||
static int mvpp2_prs_vid_range_find(struct mvpp2_port *port, u16 vid, u16 mask)
|
||||
{
|
||||
unsigned char byte[2], enable[2];
|
||||
struct mvpp2_prs_entry pe;
|
||||
|
@ -1914,13 +1913,13 @@ static int mvpp2_prs_vid_range_find(struct mvpp2 *priv, int pmap, u16 vid,
|
|||
int tid;
|
||||
|
||||
/* Go through the all entries with MVPP2_PRS_LU_VID */
|
||||
for (tid = MVPP2_PE_VID_FILT_RANGE_START;
|
||||
tid <= MVPP2_PE_VID_FILT_RANGE_END; tid++) {
|
||||
if (!priv->prs_shadow[tid].valid ||
|
||||
priv->prs_shadow[tid].lu != MVPP2_PRS_LU_VID)
|
||||
for (tid = MVPP2_PRS_VID_PORT_FIRST(port->id);
|
||||
tid <= MVPP2_PRS_VID_PORT_LAST(port->id); tid++) {
|
||||
if (!port->priv->prs_shadow[tid].valid ||
|
||||
port->priv->prs_shadow[tid].lu != MVPP2_PRS_LU_VID)
|
||||
continue;
|
||||
|
||||
mvpp2_prs_init_from_hw(priv, &pe, tid);
|
||||
mvpp2_prs_init_from_hw(port->priv, &pe, tid);
|
||||
|
||||
mvpp2_prs_tcam_data_byte_get(&pe, 2, &byte[0], &enable[0]);
|
||||
mvpp2_prs_tcam_data_byte_get(&pe, 3, &byte[1], &enable[1]);
|
||||
|
@ -1950,7 +1949,7 @@ int mvpp2_prs_vid_entry_add(struct mvpp2_port *port, u16 vid)
|
|||
memset(&pe, 0, sizeof(pe));
|
||||
|
||||
/* Scan TCAM and see if entry with this <vid,port> already exist */
|
||||
tid = mvpp2_prs_vid_range_find(priv, (1 << port->id), vid, mask);
|
||||
tid = mvpp2_prs_vid_range_find(port, vid, mask);
|
||||
|
||||
reg_val = mvpp2_read(priv, MVPP2_MH_REG(port->id));
|
||||
if (reg_val & MVPP2_DSA_EXTENDED)
|
||||
|
@ -2008,7 +2007,7 @@ void mvpp2_prs_vid_entry_remove(struct mvpp2_port *port, u16 vid)
|
|||
int tid;
|
||||
|
||||
/* Scan TCAM and see if entry with this <vid,port> already exist */
|
||||
tid = mvpp2_prs_vid_range_find(priv, (1 << port->id), vid, 0xfff);
|
||||
tid = mvpp2_prs_vid_range_find(port, vid, 0xfff);
|
||||
|
||||
/* No such entry */
|
||||
if (tid < 0)
|
||||
|
@ -2026,8 +2025,10 @@ void mvpp2_prs_vid_remove_all(struct mvpp2_port *port)
|
|||
|
||||
for (tid = MVPP2_PRS_VID_PORT_FIRST(port->id);
|
||||
tid <= MVPP2_PRS_VID_PORT_LAST(port->id); tid++) {
|
||||
if (priv->prs_shadow[tid].valid)
|
||||
mvpp2_prs_vid_entry_remove(port, tid);
|
||||
if (priv->prs_shadow[tid].valid) {
|
||||
mvpp2_prs_hw_inv(priv, tid);
|
||||
priv->prs_shadow[tid].valid = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -441,6 +441,10 @@ static int mlx5_internal_err_ret_value(struct mlx5_core_dev *dev, u16 op,
|
|||
case MLX5_CMD_OP_CREATE_GENERAL_OBJECT:
|
||||
case MLX5_CMD_OP_MODIFY_GENERAL_OBJECT:
|
||||
case MLX5_CMD_OP_QUERY_GENERAL_OBJECT:
|
||||
case MLX5_CMD_OP_CREATE_UCTX:
|
||||
case MLX5_CMD_OP_DESTROY_UCTX:
|
||||
case MLX5_CMD_OP_CREATE_UMEM:
|
||||
case MLX5_CMD_OP_DESTROY_UMEM:
|
||||
case MLX5_CMD_OP_ALLOC_MEMIC:
|
||||
*status = MLX5_DRIVER_STATUS_ABORTED;
|
||||
*synd = MLX5_DRIVER_SYND;
|
||||
|
@ -629,6 +633,10 @@ const char *mlx5_command_str(int command)
|
|||
MLX5_COMMAND_STR_CASE(ALLOC_MEMIC);
|
||||
MLX5_COMMAND_STR_CASE(DEALLOC_MEMIC);
|
||||
MLX5_COMMAND_STR_CASE(QUERY_HOST_PARAMS);
|
||||
MLX5_COMMAND_STR_CASE(CREATE_UCTX);
|
||||
MLX5_COMMAND_STR_CASE(DESTROY_UCTX);
|
||||
MLX5_COMMAND_STR_CASE(CREATE_UMEM);
|
||||
MLX5_COMMAND_STR_CASE(DESTROY_UMEM);
|
||||
default: return "unknown command opcode";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -248,11 +248,32 @@ void mlx5_unregister_interface(struct mlx5_interface *intf)
|
|||
}
|
||||
EXPORT_SYMBOL(mlx5_unregister_interface);
|
||||
|
||||
/* Must be called with intf_mutex held */
|
||||
static bool mlx5_has_added_dev_by_protocol(struct mlx5_core_dev *mdev, int protocol)
|
||||
{
|
||||
struct mlx5_device_context *dev_ctx;
|
||||
struct mlx5_interface *intf;
|
||||
bool found = false;
|
||||
|
||||
list_for_each_entry(intf, &intf_list, list) {
|
||||
if (intf->protocol == protocol) {
|
||||
dev_ctx = mlx5_get_device(intf, &mdev->priv);
|
||||
if (dev_ctx && test_bit(MLX5_INTERFACE_ADDED, &dev_ctx->state))
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
void mlx5_reload_interface(struct mlx5_core_dev *mdev, int protocol)
|
||||
{
|
||||
mutex_lock(&mlx5_intf_mutex);
|
||||
mlx5_remove_dev_by_protocol(mdev, protocol);
|
||||
mlx5_add_dev_by_protocol(mdev, protocol);
|
||||
if (mlx5_has_added_dev_by_protocol(mdev, protocol)) {
|
||||
mlx5_remove_dev_by_protocol(mdev, protocol);
|
||||
mlx5_add_dev_by_protocol(mdev, protocol);
|
||||
}
|
||||
mutex_unlock(&mlx5_intf_mutex);
|
||||
}
|
||||
|
||||
|
|
|
@ -385,6 +385,7 @@ struct mlx5e_txqsq {
|
|||
/* control path */
|
||||
struct mlx5_wq_ctrl wq_ctrl;
|
||||
struct mlx5e_channel *channel;
|
||||
int ch_ix;
|
||||
int txq_ix;
|
||||
u32 rate_limit;
|
||||
struct work_struct recover_work;
|
||||
|
@ -1112,6 +1113,7 @@ void mlx5e_del_vxlan_port(struct net_device *netdev, struct udp_tunnel_info *ti)
|
|||
netdev_features_t mlx5e_features_check(struct sk_buff *skb,
|
||||
struct net_device *netdev,
|
||||
netdev_features_t features);
|
||||
int mlx5e_set_features(struct net_device *netdev, netdev_features_t features);
|
||||
#ifdef CONFIG_MLX5_ESWITCH
|
||||
int mlx5e_set_vf_mac(struct net_device *dev, int vf, u8 *mac);
|
||||
int mlx5e_set_vf_rate(struct net_device *dev, int vf, int min_tx_rate, int max_tx_rate);
|
||||
|
|
|
@ -11,24 +11,25 @@ static int get_route_and_out_devs(struct mlx5e_priv *priv,
|
|||
struct net_device **route_dev,
|
||||
struct net_device **out_dev)
|
||||
{
|
||||
struct net_device *uplink_dev, *uplink_upper, *real_dev;
|
||||
struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
|
||||
struct net_device *uplink_dev, *uplink_upper;
|
||||
bool dst_is_lag_dev;
|
||||
|
||||
real_dev = is_vlan_dev(dev) ? vlan_dev_real_dev(dev) : dev;
|
||||
uplink_dev = mlx5_eswitch_uplink_get_proto_dev(esw, REP_ETH);
|
||||
uplink_upper = netdev_master_upper_dev_get(uplink_dev);
|
||||
dst_is_lag_dev = (uplink_upper &&
|
||||
netif_is_lag_master(uplink_upper) &&
|
||||
dev == uplink_upper &&
|
||||
real_dev == uplink_upper &&
|
||||
mlx5_lag_is_sriov(priv->mdev));
|
||||
|
||||
/* if the egress device isn't on the same HW e-switch or
|
||||
* it's a LAG device, use the uplink
|
||||
*/
|
||||
if (!netdev_port_same_parent_id(priv->netdev, dev) ||
|
||||
if (!netdev_port_same_parent_id(priv->netdev, real_dev) ||
|
||||
dst_is_lag_dev) {
|
||||
*route_dev = uplink_dev;
|
||||
*out_dev = *route_dev;
|
||||
*route_dev = dev;
|
||||
*out_dev = uplink_dev;
|
||||
} else {
|
||||
*route_dev = dev;
|
||||
if (is_vlan_dev(*route_dev))
|
||||
|
|
|
@ -1082,6 +1082,7 @@ static int mlx5e_alloc_txqsq(struct mlx5e_channel *c,
|
|||
sq->clock = &mdev->clock;
|
||||
sq->mkey_be = c->mkey_be;
|
||||
sq->channel = c;
|
||||
sq->ch_ix = c->ix;
|
||||
sq->txq_ix = txq_ix;
|
||||
sq->uar_map = mdev->mlx5e_res.bfreg.map;
|
||||
sq->min_inline_mode = params->tx_min_inline_mode;
|
||||
|
@ -3635,8 +3636,7 @@ static int mlx5e_handle_feature(struct net_device *netdev,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int mlx5e_set_features(struct net_device *netdev,
|
||||
netdev_features_t features)
|
||||
int mlx5e_set_features(struct net_device *netdev, netdev_features_t features)
|
||||
{
|
||||
netdev_features_t oper_features = netdev->features;
|
||||
int err = 0;
|
||||
|
@ -5108,6 +5108,11 @@ static void mlx5e_detach(struct mlx5_core_dev *mdev, void *vpriv)
|
|||
struct mlx5e_priv *priv = vpriv;
|
||||
struct net_device *netdev = priv->netdev;
|
||||
|
||||
#ifdef CONFIG_MLX5_ESWITCH
|
||||
if (MLX5_ESWITCH_MANAGER(mdev) && vpriv == mdev)
|
||||
return;
|
||||
#endif
|
||||
|
||||
if (!netif_device_present(netdev))
|
||||
return;
|
||||
|
||||
|
|
|
@ -1351,6 +1351,7 @@ static const struct net_device_ops mlx5e_netdev_ops_uplink_rep = {
|
|||
.ndo_get_vf_stats = mlx5e_get_vf_stats,
|
||||
.ndo_set_vf_vlan = mlx5e_uplink_rep_set_vf_vlan,
|
||||
.ndo_get_port_parent_id = mlx5e_rep_get_port_parent_id,
|
||||
.ndo_set_features = mlx5e_set_features,
|
||||
};
|
||||
|
||||
bool mlx5e_eswitch_rep(struct net_device *netdev)
|
||||
|
@ -1425,10 +1426,9 @@ static void mlx5e_build_rep_netdev(struct net_device *netdev)
|
|||
|
||||
netdev->watchdog_timeo = 15 * HZ;
|
||||
|
||||
netdev->features |= NETIF_F_NETNS_LOCAL;
|
||||
|
||||
netdev->features |= NETIF_F_HW_TC | NETIF_F_NETNS_LOCAL;
|
||||
netdev->hw_features |= NETIF_F_HW_TC;
|
||||
|
||||
netdev->hw_features |= NETIF_F_HW_TC;
|
||||
netdev->hw_features |= NETIF_F_SG;
|
||||
netdev->hw_features |= NETIF_F_IP_CSUM;
|
||||
netdev->hw_features |= NETIF_F_IPV6_CSUM;
|
||||
|
@ -1437,7 +1437,9 @@ static void mlx5e_build_rep_netdev(struct net_device *netdev)
|
|||
netdev->hw_features |= NETIF_F_TSO6;
|
||||
netdev->hw_features |= NETIF_F_RXCSUM;
|
||||
|
||||
if (rep->vport != MLX5_VPORT_UPLINK)
|
||||
if (rep->vport == MLX5_VPORT_UPLINK)
|
||||
netdev->hw_features |= NETIF_F_HW_VLAN_CTAG_RX;
|
||||
else
|
||||
netdev->features |= NETIF_F_VLAN_CHALLENGED;
|
||||
|
||||
netdev->features |= netdev->hw_features;
|
||||
|
|
|
@ -2812,9 +2812,6 @@ static int parse_tc_fdb_actions(struct mlx5e_priv *priv,
|
|||
if (!flow_action_has_entries(flow_action))
|
||||
return -EINVAL;
|
||||
|
||||
attr->in_rep = rpriv->rep;
|
||||
attr->in_mdev = priv->mdev;
|
||||
|
||||
flow_action_for_each(i, act, flow_action) {
|
||||
switch (act->id) {
|
||||
case FLOW_ACTION_DROP:
|
||||
|
|
|
@ -113,13 +113,13 @@ static inline int mlx5e_get_dscp_up(struct mlx5e_priv *priv, struct sk_buff *skb
|
|||
u16 mlx5e_select_queue(struct net_device *dev, struct sk_buff *skb,
|
||||
struct net_device *sb_dev)
|
||||
{
|
||||
int channel_ix = netdev_pick_tx(dev, skb, NULL);
|
||||
int txq_ix = netdev_pick_tx(dev, skb, NULL);
|
||||
struct mlx5e_priv *priv = netdev_priv(dev);
|
||||
u16 num_channels;
|
||||
int up = 0;
|
||||
|
||||
if (!netdev_get_num_tc(dev))
|
||||
return channel_ix;
|
||||
return txq_ix;
|
||||
|
||||
#ifdef CONFIG_MLX5_CORE_EN_DCB
|
||||
if (priv->dcbx_dp.trust_state == MLX5_QPTS_TRUST_DSCP)
|
||||
|
@ -129,14 +129,14 @@ u16 mlx5e_select_queue(struct net_device *dev, struct sk_buff *skb,
|
|||
if (skb_vlan_tag_present(skb))
|
||||
up = skb_vlan_tag_get_prio(skb);
|
||||
|
||||
/* channel_ix can be larger than num_channels since
|
||||
/* txq_ix can be larger than num_channels since
|
||||
* dev->num_real_tx_queues = num_channels * num_tc
|
||||
*/
|
||||
num_channels = priv->channels.params.num_channels;
|
||||
if (channel_ix >= num_channels)
|
||||
channel_ix = reciprocal_scale(channel_ix, num_channels);
|
||||
if (txq_ix >= num_channels)
|
||||
txq_ix = priv->txq2sq[txq_ix]->ch_ix;
|
||||
|
||||
return priv->channel_tc2txq[channel_ix][up];
|
||||
return priv->channel_tc2txq[txq_ix][up];
|
||||
}
|
||||
|
||||
static inline int mlx5e_skb_l2_header_offset(struct sk_buff *skb)
|
||||
|
|
|
@ -997,7 +997,7 @@ static inline void mlxsw_reg_spaft_pack(char *payload, u8 local_port,
|
|||
MLXSW_REG_ZERO(spaft, payload);
|
||||
mlxsw_reg_spaft_local_port_set(payload, local_port);
|
||||
mlxsw_reg_spaft_allow_untagged_set(payload, allow_untagged);
|
||||
mlxsw_reg_spaft_allow_prio_tagged_set(payload, true);
|
||||
mlxsw_reg_spaft_allow_prio_tagged_set(payload, allow_untagged);
|
||||
mlxsw_reg_spaft_allow_tagged_set(payload, true);
|
||||
}
|
||||
|
||||
|
|
|
@ -4280,13 +4280,16 @@ static void mlxsw_sp_traps_fini(struct mlxsw_sp *mlxsw_sp)
|
|||
}
|
||||
}
|
||||
|
||||
#define MLXSW_SP_LAG_SEED_INIT 0xcafecafe
|
||||
|
||||
static int mlxsw_sp_lag_init(struct mlxsw_sp *mlxsw_sp)
|
||||
{
|
||||
char slcr_pl[MLXSW_REG_SLCR_LEN];
|
||||
u32 seed;
|
||||
int err;
|
||||
|
||||
seed = jhash(mlxsw_sp->base_mac, sizeof(mlxsw_sp->base_mac), 0);
|
||||
seed = jhash(mlxsw_sp->base_mac, sizeof(mlxsw_sp->base_mac),
|
||||
MLXSW_SP_LAG_SEED_INIT);
|
||||
mlxsw_reg_slcr_pack(slcr_pl, MLXSW_REG_SLCR_LAG_HASH_SMAC |
|
||||
MLXSW_REG_SLCR_LAG_HASH_DMAC |
|
||||
MLXSW_REG_SLCR_LAG_HASH_ETHERTYPE |
|
||||
|
|
|
@ -437,8 +437,8 @@ static const struct mlxsw_sp_sb_pr mlxsw_sp1_sb_prs[] = {
|
|||
MLXSW_SP1_SB_PR_CPU_SIZE, true, false),
|
||||
};
|
||||
|
||||
#define MLXSW_SP2_SB_PR_INGRESS_SIZE 40960000
|
||||
#define MLXSW_SP2_SB_PR_EGRESS_SIZE 40960000
|
||||
#define MLXSW_SP2_SB_PR_INGRESS_SIZE 38128752
|
||||
#define MLXSW_SP2_SB_PR_EGRESS_SIZE 38128752
|
||||
#define MLXSW_SP2_SB_PR_CPU_SIZE (256 * 1000)
|
||||
|
||||
/* Order according to mlxsw_sp2_sb_pool_dess */
|
||||
|
|
|
@ -247,8 +247,8 @@ static int mlxsw_sp_flower_parse_ip(struct mlxsw_sp *mlxsw_sp,
|
|||
match.mask->tos & 0x3);
|
||||
|
||||
mlxsw_sp_acl_rulei_keymask_u32(rulei, MLXSW_AFK_ELEMENT_IP_DSCP,
|
||||
match.key->tos >> 6,
|
||||
match.mask->tos >> 6);
|
||||
match.key->tos >> 2,
|
||||
match.mask->tos >> 2);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -2363,7 +2363,7 @@ static void mlxsw_sp_router_probe_unresolved_nexthops(struct work_struct *work)
|
|||
static void
|
||||
mlxsw_sp_nexthop_neigh_update(struct mlxsw_sp *mlxsw_sp,
|
||||
struct mlxsw_sp_neigh_entry *neigh_entry,
|
||||
bool removing);
|
||||
bool removing, bool dead);
|
||||
|
||||
static enum mlxsw_reg_rauht_op mlxsw_sp_rauht_op(bool adding)
|
||||
{
|
||||
|
@ -2507,7 +2507,8 @@ static void mlxsw_sp_router_neigh_event_work(struct work_struct *work)
|
|||
|
||||
memcpy(neigh_entry->ha, ha, ETH_ALEN);
|
||||
mlxsw_sp_neigh_entry_update(mlxsw_sp, neigh_entry, entry_connected);
|
||||
mlxsw_sp_nexthop_neigh_update(mlxsw_sp, neigh_entry, !entry_connected);
|
||||
mlxsw_sp_nexthop_neigh_update(mlxsw_sp, neigh_entry, !entry_connected,
|
||||
dead);
|
||||
|
||||
if (!neigh_entry->connected && list_empty(&neigh_entry->nexthop_list))
|
||||
mlxsw_sp_neigh_entry_destroy(mlxsw_sp, neigh_entry);
|
||||
|
@ -3472,13 +3473,79 @@ static void __mlxsw_sp_nexthop_neigh_update(struct mlxsw_sp_nexthop *nh,
|
|||
nh->update = 1;
|
||||
}
|
||||
|
||||
static int
|
||||
mlxsw_sp_nexthop_dead_neigh_replace(struct mlxsw_sp *mlxsw_sp,
|
||||
struct mlxsw_sp_neigh_entry *neigh_entry)
|
||||
{
|
||||
struct neighbour *n, *old_n = neigh_entry->key.n;
|
||||
struct mlxsw_sp_nexthop *nh;
|
||||
bool entry_connected;
|
||||
u8 nud_state, dead;
|
||||
int err;
|
||||
|
||||
nh = list_first_entry(&neigh_entry->nexthop_list,
|
||||
struct mlxsw_sp_nexthop, neigh_list_node);
|
||||
|
||||
n = neigh_lookup(nh->nh_grp->neigh_tbl, &nh->gw_addr, nh->rif->dev);
|
||||
if (!n) {
|
||||
n = neigh_create(nh->nh_grp->neigh_tbl, &nh->gw_addr,
|
||||
nh->rif->dev);
|
||||
if (IS_ERR(n))
|
||||
return PTR_ERR(n);
|
||||
neigh_event_send(n, NULL);
|
||||
}
|
||||
|
||||
mlxsw_sp_neigh_entry_remove(mlxsw_sp, neigh_entry);
|
||||
neigh_entry->key.n = n;
|
||||
err = mlxsw_sp_neigh_entry_insert(mlxsw_sp, neigh_entry);
|
||||
if (err)
|
||||
goto err_neigh_entry_insert;
|
||||
|
||||
read_lock_bh(&n->lock);
|
||||
nud_state = n->nud_state;
|
||||
dead = n->dead;
|
||||
read_unlock_bh(&n->lock);
|
||||
entry_connected = nud_state & NUD_VALID && !dead;
|
||||
|
||||
list_for_each_entry(nh, &neigh_entry->nexthop_list,
|
||||
neigh_list_node) {
|
||||
neigh_release(old_n);
|
||||
neigh_clone(n);
|
||||
__mlxsw_sp_nexthop_neigh_update(nh, !entry_connected);
|
||||
mlxsw_sp_nexthop_group_refresh(mlxsw_sp, nh->nh_grp);
|
||||
}
|
||||
|
||||
neigh_release(n);
|
||||
|
||||
return 0;
|
||||
|
||||
err_neigh_entry_insert:
|
||||
neigh_entry->key.n = old_n;
|
||||
mlxsw_sp_neigh_entry_insert(mlxsw_sp, neigh_entry);
|
||||
neigh_release(n);
|
||||
return err;
|
||||
}
|
||||
|
||||
static void
|
||||
mlxsw_sp_nexthop_neigh_update(struct mlxsw_sp *mlxsw_sp,
|
||||
struct mlxsw_sp_neigh_entry *neigh_entry,
|
||||
bool removing)
|
||||
bool removing, bool dead)
|
||||
{
|
||||
struct mlxsw_sp_nexthop *nh;
|
||||
|
||||
if (list_empty(&neigh_entry->nexthop_list))
|
||||
return;
|
||||
|
||||
if (dead) {
|
||||
int err;
|
||||
|
||||
err = mlxsw_sp_nexthop_dead_neigh_replace(mlxsw_sp,
|
||||
neigh_entry);
|
||||
if (err)
|
||||
dev_err(mlxsw_sp->bus_info->dev, "Failed to replace dead neigh\n");
|
||||
return;
|
||||
}
|
||||
|
||||
list_for_each_entry(nh, &neigh_entry->nexthop_list,
|
||||
neigh_list_node) {
|
||||
__mlxsw_sp_nexthop_neigh_update(nh, removing);
|
||||
|
|
|
@ -1867,6 +1867,7 @@ static int nfp_net_rx(struct nfp_net_rx_ring *rx_ring, int budget)
|
|||
napi_gro_receive(&rx_ring->r_vec->napi, skb);
|
||||
} else {
|
||||
skb->dev = netdev;
|
||||
skb_reset_network_header(skb);
|
||||
__skb_push(skb, ETH_HLEN);
|
||||
dev_queue_xmit(skb);
|
||||
}
|
||||
|
|
|
@ -395,7 +395,7 @@ static int geneve_udp_encap_err_lookup(struct sock *sk, struct sk_buff *skb)
|
|||
u8 zero_vni[3] = { 0 };
|
||||
u8 *vni = zero_vni;
|
||||
|
||||
if (skb->len < GENEVE_BASE_HLEN)
|
||||
if (!pskb_may_pull(skb, skb_transport_offset(skb) + GENEVE_BASE_HLEN))
|
||||
return -EINVAL;
|
||||
|
||||
geneveh = geneve_hdr(skb);
|
||||
|
|
|
@ -2407,7 +2407,7 @@ static struct hv_driver netvsc_drv = {
|
|||
.probe = netvsc_probe,
|
||||
.remove = netvsc_remove,
|
||||
.driver = {
|
||||
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
|
||||
.probe_type = PROBE_FORCE_SYNCHRONOUS,
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
@ -254,7 +254,7 @@ config AQUANTIA_PHY
|
|||
---help---
|
||||
Currently supports the Aquantia AQ1202, AQ2104, AQR105, AQR405
|
||||
|
||||
config ASIX_PHY
|
||||
config AX88796B_PHY
|
||||
tristate "Asix PHYs"
|
||||
help
|
||||
Currently supports the Asix Electronics PHY found in the X-Surf 100
|
||||
|
|
|
@ -52,7 +52,7 @@ ifdef CONFIG_HWMON
|
|||
aquantia-objs += aquantia_hwmon.o
|
||||
endif
|
||||
obj-$(CONFIG_AQUANTIA_PHY) += aquantia.o
|
||||
obj-$(CONFIG_ASIX_PHY) += asix.o
|
||||
obj-$(CONFIG_AX88796B_PHY) += ax88796b.o
|
||||
obj-$(CONFIG_AT803X_PHY) += at803x.o
|
||||
obj-$(CONFIG_BCM63XX_PHY) += bcm63xx.o
|
||||
obj-$(CONFIG_BCM7XXX_PHY) += bcm7xxx.o
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include <linux/usb/cdc.h>
|
||||
#include <linux/usb/usbnet.h>
|
||||
#include <linux/usb/cdc-wdm.h>
|
||||
#include <linux/u64_stats_sync.h>
|
||||
|
||||
/* This driver supports wwan (3G/LTE/?) devices using a vendor
|
||||
* specific management protocol called Qualcomm MSM Interface (QMI) -
|
||||
|
@ -75,6 +76,7 @@ struct qmimux_hdr {
|
|||
struct qmimux_priv {
|
||||
struct net_device *real_dev;
|
||||
u8 mux_id;
|
||||
struct pcpu_sw_netstats __percpu *stats64;
|
||||
};
|
||||
|
||||
static int qmimux_open(struct net_device *dev)
|
||||
|
@ -101,19 +103,65 @@ static netdev_tx_t qmimux_start_xmit(struct sk_buff *skb, struct net_device *dev
|
|||
struct qmimux_priv *priv = netdev_priv(dev);
|
||||
unsigned int len = skb->len;
|
||||
struct qmimux_hdr *hdr;
|
||||
netdev_tx_t ret;
|
||||
|
||||
hdr = skb_push(skb, sizeof(struct qmimux_hdr));
|
||||
hdr->pad = 0;
|
||||
hdr->mux_id = priv->mux_id;
|
||||
hdr->pkt_len = cpu_to_be16(len);
|
||||
skb->dev = priv->real_dev;
|
||||
return dev_queue_xmit(skb);
|
||||
ret = dev_queue_xmit(skb);
|
||||
|
||||
if (likely(ret == NET_XMIT_SUCCESS || ret == NET_XMIT_CN)) {
|
||||
struct pcpu_sw_netstats *stats64 = this_cpu_ptr(priv->stats64);
|
||||
|
||||
u64_stats_update_begin(&stats64->syncp);
|
||||
stats64->tx_packets++;
|
||||
stats64->tx_bytes += len;
|
||||
u64_stats_update_end(&stats64->syncp);
|
||||
} else {
|
||||
dev->stats.tx_dropped++;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void qmimux_get_stats64(struct net_device *net,
|
||||
struct rtnl_link_stats64 *stats)
|
||||
{
|
||||
struct qmimux_priv *priv = netdev_priv(net);
|
||||
unsigned int start;
|
||||
int cpu;
|
||||
|
||||
netdev_stats_to_stats64(stats, &net->stats);
|
||||
|
||||
for_each_possible_cpu(cpu) {
|
||||
struct pcpu_sw_netstats *stats64;
|
||||
u64 rx_packets, rx_bytes;
|
||||
u64 tx_packets, tx_bytes;
|
||||
|
||||
stats64 = per_cpu_ptr(priv->stats64, cpu);
|
||||
|
||||
do {
|
||||
start = u64_stats_fetch_begin_irq(&stats64->syncp);
|
||||
rx_packets = stats64->rx_packets;
|
||||
rx_bytes = stats64->rx_bytes;
|
||||
tx_packets = stats64->tx_packets;
|
||||
tx_bytes = stats64->tx_bytes;
|
||||
} while (u64_stats_fetch_retry_irq(&stats64->syncp, start));
|
||||
|
||||
stats->rx_packets += rx_packets;
|
||||
stats->rx_bytes += rx_bytes;
|
||||
stats->tx_packets += tx_packets;
|
||||
stats->tx_bytes += tx_bytes;
|
||||
}
|
||||
}
|
||||
|
||||
static const struct net_device_ops qmimux_netdev_ops = {
|
||||
.ndo_open = qmimux_open,
|
||||
.ndo_stop = qmimux_stop,
|
||||
.ndo_start_xmit = qmimux_start_xmit,
|
||||
.ndo_open = qmimux_open,
|
||||
.ndo_stop = qmimux_stop,
|
||||
.ndo_start_xmit = qmimux_start_xmit,
|
||||
.ndo_get_stats64 = qmimux_get_stats64,
|
||||
};
|
||||
|
||||
static void qmimux_setup(struct net_device *dev)
|
||||
|
@ -153,7 +201,7 @@ static bool qmimux_has_slaves(struct usbnet *dev)
|
|||
|
||||
static int qmimux_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
|
||||
{
|
||||
unsigned int len, offset = 0;
|
||||
unsigned int len, offset = 0, pad_len, pkt_len;
|
||||
struct qmimux_hdr *hdr;
|
||||
struct net_device *net;
|
||||
struct sk_buff *skbn;
|
||||
|
@ -171,10 +219,16 @@ static int qmimux_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
|
|||
if (hdr->pad & 0x80)
|
||||
goto skip;
|
||||
|
||||
/* extract padding length and check for valid length info */
|
||||
pad_len = hdr->pad & 0x3f;
|
||||
if (len == 0 || pad_len >= len)
|
||||
goto skip;
|
||||
pkt_len = len - pad_len;
|
||||
|
||||
net = qmimux_find_dev(dev, hdr->mux_id);
|
||||
if (!net)
|
||||
goto skip;
|
||||
skbn = netdev_alloc_skb(net, len);
|
||||
skbn = netdev_alloc_skb(net, pkt_len);
|
||||
if (!skbn)
|
||||
return 0;
|
||||
skbn->dev = net;
|
||||
|
@ -191,9 +245,20 @@ static int qmimux_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
|
|||
goto skip;
|
||||
}
|
||||
|
||||
skb_put_data(skbn, skb->data + offset + qmimux_hdr_sz, len);
|
||||
if (netif_rx(skbn) != NET_RX_SUCCESS)
|
||||
skb_put_data(skbn, skb->data + offset + qmimux_hdr_sz, pkt_len);
|
||||
if (netif_rx(skbn) != NET_RX_SUCCESS) {
|
||||
net->stats.rx_errors++;
|
||||
return 0;
|
||||
} else {
|
||||
struct pcpu_sw_netstats *stats64;
|
||||
struct qmimux_priv *priv = netdev_priv(net);
|
||||
|
||||
stats64 = this_cpu_ptr(priv->stats64);
|
||||
u64_stats_update_begin(&stats64->syncp);
|
||||
stats64->rx_packets++;
|
||||
stats64->rx_bytes += pkt_len;
|
||||
u64_stats_update_end(&stats64->syncp);
|
||||
}
|
||||
|
||||
skip:
|
||||
offset += len + qmimux_hdr_sz;
|
||||
|
@ -217,6 +282,12 @@ static int qmimux_register_device(struct net_device *real_dev, u8 mux_id)
|
|||
priv->mux_id = mux_id;
|
||||
priv->real_dev = real_dev;
|
||||
|
||||
priv->stats64 = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats);
|
||||
if (!priv->stats64) {
|
||||
err = -ENOBUFS;
|
||||
goto out_free_newdev;
|
||||
}
|
||||
|
||||
err = register_netdevice(new_dev);
|
||||
if (err < 0)
|
||||
goto out_free_newdev;
|
||||
|
@ -241,13 +312,15 @@ out_free_newdev:
|
|||
return err;
|
||||
}
|
||||
|
||||
static void qmimux_unregister_device(struct net_device *dev)
|
||||
static void qmimux_unregister_device(struct net_device *dev,
|
||||
struct list_head *head)
|
||||
{
|
||||
struct qmimux_priv *priv = netdev_priv(dev);
|
||||
struct net_device *real_dev = priv->real_dev;
|
||||
|
||||
free_percpu(priv->stats64);
|
||||
netdev_upper_dev_unlink(real_dev, dev);
|
||||
unregister_netdevice(dev);
|
||||
unregister_netdevice_queue(dev, head);
|
||||
|
||||
/* Get rid of the reference to real_dev */
|
||||
dev_put(real_dev);
|
||||
|
@ -356,8 +429,8 @@ static ssize_t add_mux_store(struct device *d, struct device_attribute *attr, c
|
|||
if (kstrtou8(buf, 0, &mux_id))
|
||||
return -EINVAL;
|
||||
|
||||
/* mux_id [1 - 0x7f] range empirically found */
|
||||
if (mux_id < 1 || mux_id > 0x7f)
|
||||
/* mux_id [1 - 254] for compatibility with ip(8) and the rmnet driver */
|
||||
if (mux_id < 1 || mux_id > 254)
|
||||
return -EINVAL;
|
||||
|
||||
if (!rtnl_trylock())
|
||||
|
@ -418,7 +491,7 @@ static ssize_t del_mux_store(struct device *d, struct device_attribute *attr, c
|
|||
ret = -EINVAL;
|
||||
goto err;
|
||||
}
|
||||
qmimux_unregister_device(del_dev);
|
||||
qmimux_unregister_device(del_dev, NULL);
|
||||
|
||||
if (!qmimux_has_slaves(dev))
|
||||
info->flags &= ~QMI_WWAN_FLAG_MUX;
|
||||
|
@ -1428,6 +1501,7 @@ static void qmi_wwan_disconnect(struct usb_interface *intf)
|
|||
struct qmi_wwan_state *info;
|
||||
struct list_head *iter;
|
||||
struct net_device *ldev;
|
||||
LIST_HEAD(list);
|
||||
|
||||
/* called twice if separate control and data intf */
|
||||
if (!dev)
|
||||
|
@ -1440,8 +1514,9 @@ static void qmi_wwan_disconnect(struct usb_interface *intf)
|
|||
}
|
||||
rcu_read_lock();
|
||||
netdev_for_each_upper_dev_rcu(dev->net, ldev, iter)
|
||||
qmimux_unregister_device(ldev);
|
||||
qmimux_unregister_device(ldev, &list);
|
||||
rcu_read_unlock();
|
||||
unregister_netdevice_many(&list);
|
||||
rtnl_unlock();
|
||||
info->flags &= ~QMI_WWAN_FLAG_MUX;
|
||||
}
|
||||
|
|
|
@ -1766,7 +1766,7 @@ static int vxlan_err_lookup(struct sock *sk, struct sk_buff *skb)
|
|||
struct vxlanhdr *hdr;
|
||||
__be32 vni;
|
||||
|
||||
if (skb->len < VXLAN_HLEN)
|
||||
if (!pskb_may_pull(skb, skb_transport_offset(skb) + VXLAN_HLEN))
|
||||
return -EINVAL;
|
||||
|
||||
hdr = vxlan_hdr(skb);
|
||||
|
|
|
@ -2747,3 +2747,42 @@ void iwl_fw_dbg_periodic_trig_handler(struct timer_list *t)
|
|||
jiffies + msecs_to_jiffies(collect_interval));
|
||||
}
|
||||
}
|
||||
|
||||
#define FSEQ_REG(x) { .addr = (x), .str = #x, }
|
||||
|
||||
void iwl_fw_error_print_fseq_regs(struct iwl_fw_runtime *fwrt)
|
||||
{
|
||||
struct iwl_trans *trans = fwrt->trans;
|
||||
unsigned long flags;
|
||||
int i;
|
||||
struct {
|
||||
u32 addr;
|
||||
const char *str;
|
||||
} fseq_regs[] = {
|
||||
FSEQ_REG(FSEQ_ERROR_CODE),
|
||||
FSEQ_REG(FSEQ_TOP_INIT_VERSION),
|
||||
FSEQ_REG(FSEQ_CNVIO_INIT_VERSION),
|
||||
FSEQ_REG(FSEQ_OTP_VERSION),
|
||||
FSEQ_REG(FSEQ_TOP_CONTENT_VERSION),
|
||||
FSEQ_REG(FSEQ_ALIVE_TOKEN),
|
||||
FSEQ_REG(FSEQ_CNVI_ID),
|
||||
FSEQ_REG(FSEQ_CNVR_ID),
|
||||
FSEQ_REG(CNVI_AUX_MISC_CHIP),
|
||||
FSEQ_REG(CNVR_AUX_MISC_CHIP),
|
||||
FSEQ_REG(CNVR_SCU_SD_REGS_SD_REG_DIG_DCDC_VTRIM),
|
||||
FSEQ_REG(CNVR_SCU_SD_REGS_SD_REG_ACTIVE_VDIG_MIRROR),
|
||||
};
|
||||
|
||||
if (!iwl_trans_grab_nic_access(trans, &flags))
|
||||
return;
|
||||
|
||||
IWL_ERR(fwrt, "Fseq Registers:\n");
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(fseq_regs); i++)
|
||||
IWL_ERR(fwrt, "0x%08X | %s\n",
|
||||
iwl_read_prph_no_grab(trans, fseq_regs[i].addr),
|
||||
fseq_regs[i].str);
|
||||
|
||||
iwl_trans_release_nic_access(trans, &flags);
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_fw_error_print_fseq_regs);
|
||||
|
|
|
@ -471,4 +471,6 @@ static inline void iwl_fw_error_collect(struct iwl_fw_runtime *fwrt)
|
|||
}
|
||||
|
||||
void iwl_fw_dbg_periodic_trig_handler(struct timer_list *t);
|
||||
|
||||
void iwl_fw_error_print_fseq_regs(struct iwl_fw_runtime *fwrt);
|
||||
#endif /* __iwl_fw_dbg_h__ */
|
||||
|
|
|
@ -1597,7 +1597,6 @@ static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context)
|
|||
goto free;
|
||||
|
||||
out_free_fw:
|
||||
iwl_dealloc_ucode(drv);
|
||||
release_firmware(ucode_raw);
|
||||
out_unbind:
|
||||
complete(&drv->request_firmware_complete);
|
||||
|
|
|
@ -395,7 +395,11 @@ enum {
|
|||
WFPM_AUX_CTL_AUX_IF_MAC_OWNER_MSK = 0x80000000,
|
||||
};
|
||||
|
||||
#define AUX_MISC_REG 0xA200B0
|
||||
#define CNVI_AUX_MISC_CHIP 0xA200B0
|
||||
#define CNVR_AUX_MISC_CHIP 0xA2B800
|
||||
#define CNVR_SCU_SD_REGS_SD_REG_DIG_DCDC_VTRIM 0xA29890
|
||||
#define CNVR_SCU_SD_REGS_SD_REG_ACTIVE_VDIG_MIRROR 0xA29938
|
||||
|
||||
enum {
|
||||
HW_STEP_LOCATION_BITS = 24,
|
||||
};
|
||||
|
@ -408,7 +412,12 @@ enum aux_misc_master1_en {
|
|||
#define AUX_MISC_MASTER1_SMPHR_STATUS 0xA20800
|
||||
#define RSA_ENABLE 0xA24B08
|
||||
#define PREG_AUX_BUS_WPROT_0 0xA04CC0
|
||||
#define PREG_PRPH_WPROT_0 0xA04CE0
|
||||
|
||||
/* device family 9000 WPROT register */
|
||||
#define PREG_PRPH_WPROT_9000 0xA04CE0
|
||||
/* device family 22000 WPROT register */
|
||||
#define PREG_PRPH_WPROT_22000 0xA04D00
|
||||
|
||||
#define SB_CPU_1_STATUS 0xA01E30
|
||||
#define SB_CPU_2_STATUS 0xA01E34
|
||||
#define UMAG_SB_CPU_1_STATUS 0xA038C0
|
||||
|
@ -442,4 +451,13 @@ enum {
|
|||
|
||||
#define UREG_DOORBELL_TO_ISR6 0xA05C04
|
||||
#define UREG_DOORBELL_TO_ISR6_NMI_BIT BIT(0)
|
||||
|
||||
#define FSEQ_ERROR_CODE 0xA340C8
|
||||
#define FSEQ_TOP_INIT_VERSION 0xA34038
|
||||
#define FSEQ_CNVIO_INIT_VERSION 0xA3403C
|
||||
#define FSEQ_OTP_VERSION 0xA340FC
|
||||
#define FSEQ_TOP_CONTENT_VERSION 0xA340F4
|
||||
#define FSEQ_ALIVE_TOKEN 0xA340F0
|
||||
#define FSEQ_CNVI_ID 0xA3408C
|
||||
#define FSEQ_CNVR_ID 0xA34090
|
||||
#endif /* __iwl_prph_h__ */
|
||||
|
|
|
@ -1972,26 +1972,6 @@ out:
|
|||
}
|
||||
}
|
||||
|
||||
static void iwl_mvm_read_d3_sram(struct iwl_mvm *mvm)
|
||||
{
|
||||
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
||||
const struct fw_img *img = &mvm->fw->img[IWL_UCODE_WOWLAN];
|
||||
u32 len = img->sec[IWL_UCODE_SECTION_DATA].len;
|
||||
u32 offs = img->sec[IWL_UCODE_SECTION_DATA].offset;
|
||||
|
||||
if (!mvm->store_d3_resume_sram)
|
||||
return;
|
||||
|
||||
if (!mvm->d3_resume_sram) {
|
||||
mvm->d3_resume_sram = kzalloc(len, GFP_KERNEL);
|
||||
if (!mvm->d3_resume_sram)
|
||||
return;
|
||||
}
|
||||
|
||||
iwl_trans_read_mem_bytes(mvm->trans, offs, mvm->d3_resume_sram, len);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void iwl_mvm_d3_disconnect_iter(void *data, u8 *mac,
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
|
@ -2054,8 +2034,6 @@ static int __iwl_mvm_resume(struct iwl_mvm *mvm, bool test)
|
|||
}
|
||||
|
||||
iwl_fw_dbg_read_d3_debug_data(&mvm->fwrt);
|
||||
/* query SRAM first in case we want event logging */
|
||||
iwl_mvm_read_d3_sram(mvm);
|
||||
|
||||
if (iwl_mvm_check_rt_status(mvm, vif)) {
|
||||
set_bit(STATUS_FW_ERROR, &mvm->trans->status);
|
||||
|
|
|
@ -1557,59 +1557,6 @@ static ssize_t iwl_dbgfs_bcast_filters_macs_write(struct iwl_mvm *mvm,
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
static ssize_t iwl_dbgfs_d3_sram_write(struct iwl_mvm *mvm, char *buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
int store;
|
||||
|
||||
if (sscanf(buf, "%d", &store) != 1)
|
||||
return -EINVAL;
|
||||
|
||||
mvm->store_d3_resume_sram = store;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t iwl_dbgfs_d3_sram_read(struct file *file, char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct iwl_mvm *mvm = file->private_data;
|
||||
const struct fw_img *img;
|
||||
int ofs, len, pos = 0;
|
||||
size_t bufsz, ret;
|
||||
char *buf;
|
||||
u8 *ptr = mvm->d3_resume_sram;
|
||||
|
||||
img = &mvm->fw->img[IWL_UCODE_WOWLAN];
|
||||
len = img->sec[IWL_UCODE_SECTION_DATA].len;
|
||||
|
||||
bufsz = len * 4 + 256;
|
||||
buf = kzalloc(bufsz, GFP_KERNEL);
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
|
||||
pos += scnprintf(buf, bufsz, "D3 SRAM capture: %sabled\n",
|
||||
mvm->store_d3_resume_sram ? "en" : "dis");
|
||||
|
||||
if (ptr) {
|
||||
for (ofs = 0; ofs < len; ofs += 16) {
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
"0x%.4x %16ph\n", ofs, ptr + ofs);
|
||||
}
|
||||
} else {
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
"(no data captured)\n");
|
||||
}
|
||||
|
||||
ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
|
||||
|
||||
kfree(buf);
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
#define PRINT_MVM_REF(ref) do { \
|
||||
if (mvm->refs[ref]) \
|
||||
pos += scnprintf(buf + pos, bufsz - pos, \
|
||||
|
@ -1940,9 +1887,6 @@ MVM_DEBUGFS_READ_WRITE_FILE_OPS(bcast_filters, 256);
|
|||
MVM_DEBUGFS_READ_WRITE_FILE_OPS(bcast_filters_macs, 256);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
MVM_DEBUGFS_READ_WRITE_FILE_OPS(d3_sram, 8);
|
||||
#endif
|
||||
#ifdef CONFIG_ACPI
|
||||
MVM_DEBUGFS_READ_FILE_OPS(sar_geo_profile);
|
||||
#endif
|
||||
|
@ -2159,7 +2103,6 @@ void iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir)
|
|||
#endif
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
MVM_DEBUGFS_ADD_FILE(d3_sram, mvm->debugfs_dir, 0600);
|
||||
MVM_DEBUGFS_ADD_FILE(d3_test, mvm->debugfs_dir, 0400);
|
||||
debugfs_create_bool("d3_wake_sysassert", 0600, mvm->debugfs_dir,
|
||||
&mvm->d3_wake_sysassert);
|
||||
|
|
|
@ -311,6 +311,8 @@ static int iwl_mvm_load_ucode_wait_alive(struct iwl_mvm *mvm,
|
|||
int ret;
|
||||
enum iwl_ucode_type old_type = mvm->fwrt.cur_fw_img;
|
||||
static const u16 alive_cmd[] = { MVM_ALIVE };
|
||||
bool run_in_rfkill =
|
||||
ucode_type == IWL_UCODE_INIT || iwl_mvm_has_unified_ucode(mvm);
|
||||
|
||||
if (ucode_type == IWL_UCODE_REGULAR &&
|
||||
iwl_fw_dbg_conf_usniffer(mvm->fw, FW_DBG_START_FROM_ALIVE) &&
|
||||
|
@ -328,7 +330,12 @@ static int iwl_mvm_load_ucode_wait_alive(struct iwl_mvm *mvm,
|
|||
alive_cmd, ARRAY_SIZE(alive_cmd),
|
||||
iwl_alive_fn, &alive_data);
|
||||
|
||||
ret = iwl_trans_start_fw(mvm->trans, fw, ucode_type == IWL_UCODE_INIT);
|
||||
/*
|
||||
* We want to load the INIT firmware even in RFKILL
|
||||
* For the unified firmware case, the ucode_type is not
|
||||
* INIT, but we still need to run it.
|
||||
*/
|
||||
ret = iwl_trans_start_fw(mvm->trans, fw, run_in_rfkill);
|
||||
if (ret) {
|
||||
iwl_fw_set_current_image(&mvm->fwrt, old_type);
|
||||
iwl_remove_notification(&mvm->notif_wait, &alive_wait);
|
||||
|
@ -433,7 +440,8 @@ static int iwl_run_unified_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm)
|
|||
* commands
|
||||
*/
|
||||
ret = iwl_mvm_send_cmd_pdu(mvm, WIDE_ID(SYSTEM_GROUP,
|
||||
INIT_EXTENDED_CFG_CMD), 0,
|
||||
INIT_EXTENDED_CFG_CMD),
|
||||
CMD_SEND_IN_RFKILL,
|
||||
sizeof(init_cfg), &init_cfg);
|
||||
if (ret) {
|
||||
IWL_ERR(mvm, "Failed to run init config command: %d\n",
|
||||
|
@ -457,7 +465,8 @@ static int iwl_run_unified_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm)
|
|||
}
|
||||
|
||||
ret = iwl_mvm_send_cmd_pdu(mvm, WIDE_ID(REGULATORY_AND_NVM_GROUP,
|
||||
NVM_ACCESS_COMPLETE), 0,
|
||||
NVM_ACCESS_COMPLETE),
|
||||
CMD_SEND_IN_RFKILL,
|
||||
sizeof(nvm_complete), &nvm_complete);
|
||||
if (ret) {
|
||||
IWL_ERR(mvm, "Failed to run complete NVM access: %d\n",
|
||||
|
@ -482,6 +491,8 @@ static int iwl_run_unified_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm)
|
|||
}
|
||||
}
|
||||
|
||||
mvm->rfkill_safe_init_done = true;
|
||||
|
||||
return 0;
|
||||
|
||||
error:
|
||||
|
@ -526,7 +537,7 @@ int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm)
|
|||
|
||||
lockdep_assert_held(&mvm->mutex);
|
||||
|
||||
if (WARN_ON_ONCE(mvm->calibrating))
|
||||
if (WARN_ON_ONCE(mvm->rfkill_safe_init_done))
|
||||
return 0;
|
||||
|
||||
iwl_init_notification_wait(&mvm->notif_wait,
|
||||
|
@ -576,7 +587,7 @@ int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm)
|
|||
goto remove_notif;
|
||||
}
|
||||
|
||||
mvm->calibrating = true;
|
||||
mvm->rfkill_safe_init_done = true;
|
||||
|
||||
/* Send TX valid antennas before triggering calibrations */
|
||||
ret = iwl_send_tx_ant_cfg(mvm, iwl_mvm_get_valid_tx_ant(mvm));
|
||||
|
@ -612,7 +623,7 @@ int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm)
|
|||
remove_notif:
|
||||
iwl_remove_notification(&mvm->notif_wait, &calib_wait);
|
||||
out:
|
||||
mvm->calibrating = false;
|
||||
mvm->rfkill_safe_init_done = false;
|
||||
if (iwlmvm_mod_params.init_dbg && !mvm->nvm_data) {
|
||||
/* we want to debug INIT and we have no NVM - fake */
|
||||
mvm->nvm_data = kzalloc(sizeof(struct iwl_nvm_data) +
|
||||
|
|
|
@ -1209,7 +1209,7 @@ static void iwl_mvm_restart_cleanup(struct iwl_mvm *mvm)
|
|||
|
||||
mvm->scan_status = 0;
|
||||
mvm->ps_disabled = false;
|
||||
mvm->calibrating = false;
|
||||
mvm->rfkill_safe_init_done = false;
|
||||
|
||||
/* just in case one was running */
|
||||
iwl_mvm_cleanup_roc_te(mvm);
|
||||
|
|
|
@ -880,7 +880,7 @@ struct iwl_mvm {
|
|||
struct iwl_mvm_vif *bf_allowed_vif;
|
||||
|
||||
bool hw_registered;
|
||||
bool calibrating;
|
||||
bool rfkill_safe_init_done;
|
||||
bool support_umac_log;
|
||||
|
||||
u32 ampdu_ref;
|
||||
|
@ -1039,8 +1039,6 @@ struct iwl_mvm {
|
|||
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
||||
bool d3_wake_sysassert;
|
||||
bool d3_test_active;
|
||||
bool store_d3_resume_sram;
|
||||
void *d3_resume_sram;
|
||||
u32 d3_test_pme_ptr;
|
||||
struct ieee80211_vif *keep_vif;
|
||||
u32 last_netdetect_scans; /* no. of scans in the last net-detect wake */
|
||||
|
|
|
@ -918,9 +918,6 @@ static void iwl_op_mode_mvm_stop(struct iwl_op_mode *op_mode)
|
|||
kfree(mvm->error_recovery_buf);
|
||||
mvm->error_recovery_buf = NULL;
|
||||
|
||||
#if defined(CONFIG_PM_SLEEP) && defined(CONFIG_IWLWIFI_DEBUGFS)
|
||||
kfree(mvm->d3_resume_sram);
|
||||
#endif
|
||||
iwl_trans_op_mode_leave(mvm->trans);
|
||||
|
||||
iwl_phy_db_free(mvm->phy_db);
|
||||
|
@ -1212,7 +1209,8 @@ void iwl_mvm_set_hw_ctkill_state(struct iwl_mvm *mvm, bool state)
|
|||
static bool iwl_mvm_set_hw_rfkill_state(struct iwl_op_mode *op_mode, bool state)
|
||||
{
|
||||
struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode);
|
||||
bool calibrating = READ_ONCE(mvm->calibrating);
|
||||
bool rfkill_safe_init_done = READ_ONCE(mvm->rfkill_safe_init_done);
|
||||
bool unified = iwl_mvm_has_unified_ucode(mvm);
|
||||
|
||||
if (state)
|
||||
set_bit(IWL_MVM_STATUS_HW_RFKILL, &mvm->status);
|
||||
|
@ -1221,15 +1219,23 @@ static bool iwl_mvm_set_hw_rfkill_state(struct iwl_op_mode *op_mode, bool state)
|
|||
|
||||
iwl_mvm_set_rfkill_state(mvm);
|
||||
|
||||
/* iwl_run_init_mvm_ucode is waiting for results, abort it */
|
||||
if (calibrating)
|
||||
/* iwl_run_init_mvm_ucode is waiting for results, abort it. */
|
||||
if (rfkill_safe_init_done)
|
||||
iwl_abort_notification_waits(&mvm->notif_wait);
|
||||
|
||||
/*
|
||||
* Don't ask the transport to stop the firmware. We'll do it
|
||||
* after cfg80211 takes us down.
|
||||
*/
|
||||
if (unified)
|
||||
return false;
|
||||
|
||||
/*
|
||||
* Stop the device if we run OPERATIONAL firmware or if we are in the
|
||||
* middle of the calibrations.
|
||||
*/
|
||||
return state && (mvm->fwrt.cur_fw_img != IWL_UCODE_INIT || calibrating);
|
||||
return state && (mvm->fwrt.cur_fw_img != IWL_UCODE_INIT ||
|
||||
rfkill_safe_init_done);
|
||||
}
|
||||
|
||||
static void iwl_mvm_free_skb(struct iwl_op_mode *op_mode, struct sk_buff *skb)
|
||||
|
|
|
@ -441,7 +441,8 @@ void rs_fw_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
|
|||
*/
|
||||
sta->max_amsdu_len = max_amsdu_len;
|
||||
|
||||
ret = iwl_mvm_send_cmd_pdu(mvm, cmd_id, 0, sizeof(cfg_cmd), &cfg_cmd);
|
||||
ret = iwl_mvm_send_cmd_pdu(mvm, cmd_id, CMD_ASYNC, sizeof(cfg_cmd),
|
||||
&cfg_cmd);
|
||||
if (ret)
|
||||
IWL_ERR(mvm, "Failed to send rate scale config (%d)\n", ret);
|
||||
}
|
||||
|
|
|
@ -596,6 +596,8 @@ void iwl_mvm_dump_nic_error_log(struct iwl_mvm *mvm)
|
|||
iwl_mvm_dump_lmac_error_log(mvm, 1);
|
||||
|
||||
iwl_mvm_dump_umac_error_log(mvm);
|
||||
|
||||
iwl_fw_error_print_fseq_regs(&mvm->fwrt);
|
||||
}
|
||||
|
||||
int iwl_mvm_reconfig_scd(struct iwl_mvm *mvm, int queue, int fifo, int sta_id,
|
||||
|
|
|
@ -928,7 +928,7 @@ static inline void iwl_enable_rfkill_int(struct iwl_trans *trans)
|
|||
MSIX_HW_INT_CAUSES_REG_RF_KILL);
|
||||
}
|
||||
|
||||
if (trans->cfg->device_family == IWL_DEVICE_FAMILY_9000) {
|
||||
if (trans->cfg->device_family >= IWL_DEVICE_FAMILY_9000) {
|
||||
/*
|
||||
* On 9000-series devices this bit isn't enabled by default, so
|
||||
* when we power down the device we need set the bit to allow it
|
||||
|
|
|
@ -1698,10 +1698,40 @@ static int iwl_pcie_init_msix_handler(struct pci_dev *pdev,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int iwl_trans_pcie_clear_persistence_bit(struct iwl_trans *trans)
|
||||
{
|
||||
u32 hpm, wprot;
|
||||
|
||||
switch (trans->cfg->device_family) {
|
||||
case IWL_DEVICE_FAMILY_9000:
|
||||
wprot = PREG_PRPH_WPROT_9000;
|
||||
break;
|
||||
case IWL_DEVICE_FAMILY_22000:
|
||||
wprot = PREG_PRPH_WPROT_22000;
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
hpm = iwl_read_umac_prph_no_grab(trans, HPM_DEBUG);
|
||||
if (hpm != 0xa5a5a5a0 && (hpm & PERSISTENCE_BIT)) {
|
||||
u32 wprot_val = iwl_read_umac_prph_no_grab(trans, wprot);
|
||||
|
||||
if (wprot_val & PREG_WFPM_ACCESS) {
|
||||
IWL_ERR(trans,
|
||||
"Error, can not clear persistence bit\n");
|
||||
return -EPERM;
|
||||
}
|
||||
iwl_write_umac_prph_no_grab(trans, HPM_DEBUG,
|
||||
hpm & ~PERSISTENCE_BIT);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _iwl_trans_pcie_start_hw(struct iwl_trans *trans, bool low_power)
|
||||
{
|
||||
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
|
||||
u32 hpm;
|
||||
int err;
|
||||
|
||||
lockdep_assert_held(&trans_pcie->mutex);
|
||||
|
@ -1712,19 +1742,9 @@ static int _iwl_trans_pcie_start_hw(struct iwl_trans *trans, bool low_power)
|
|||
return err;
|
||||
}
|
||||
|
||||
hpm = iwl_read_umac_prph_no_grab(trans, HPM_DEBUG);
|
||||
if (hpm != 0xa5a5a5a0 && (hpm & PERSISTENCE_BIT)) {
|
||||
int wfpm_val = iwl_read_umac_prph_no_grab(trans,
|
||||
PREG_PRPH_WPROT_0);
|
||||
|
||||
if (wfpm_val & PREG_WFPM_ACCESS) {
|
||||
IWL_ERR(trans,
|
||||
"Error, can not clear persistence bit\n");
|
||||
return -EPERM;
|
||||
}
|
||||
iwl_write_umac_prph_no_grab(trans, HPM_DEBUG,
|
||||
hpm & ~PERSISTENCE_BIT);
|
||||
}
|
||||
err = iwl_trans_pcie_clear_persistence_bit(trans);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
iwl_trans_pcie_sw_reset(trans);
|
||||
|
||||
|
@ -3526,7 +3546,8 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev,
|
|||
hw_step |= ENABLE_WFPM;
|
||||
iwl_write_umac_prph_no_grab(trans, WFPM_CTRL_REG,
|
||||
hw_step);
|
||||
hw_step = iwl_read_prph_no_grab(trans, AUX_MISC_REG);
|
||||
hw_step = iwl_read_prph_no_grab(trans,
|
||||
CNVI_AUX_MISC_CHIP);
|
||||
hw_step = (hw_step >> HW_STEP_LOCATION_BITS) & 0xF;
|
||||
if (hw_step == 0x3)
|
||||
trans->hw_rev = (trans->hw_rev & 0xFFFFFFF3) |
|
||||
|
@ -3577,7 +3598,9 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev,
|
|||
}
|
||||
} 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 != &iwl_ax200_cfg_cc &&
|
||||
trans->cfg != &killer1650x_2ax_cfg &&
|
||||
trans->cfg != &killer1650w_2ax_cfg) ||
|
||||
trans->hw_rev == CSR_HW_REV_TYPE_QNJ_B0)) {
|
||||
u32 hw_status;
|
||||
|
||||
|
|
|
@ -3851,6 +3851,7 @@ static int __init init_mac80211_hwsim(void)
|
|||
break;
|
||||
case HWSIM_REGTEST_STRICT_ALL:
|
||||
param.reg_strict = true;
|
||||
/* fall through */
|
||||
case HWSIM_REGTEST_DRIVER_REG_ALL:
|
||||
param.reg_alpha2 = hwsim_alpha2s[0];
|
||||
break;
|
||||
|
|
|
@ -329,6 +329,8 @@ static int mwifiex_uap_parse_tail_ies(struct mwifiex_private *priv,
|
|||
struct ieee80211_vendor_ie *vendorhdr;
|
||||
u16 gen_idx = MWIFIEX_AUTO_IDX_MASK, ie_len = 0;
|
||||
int left_len, parsed_len = 0;
|
||||
unsigned int token_len;
|
||||
int err = 0;
|
||||
|
||||
if (!info->tail || !info->tail_len)
|
||||
return 0;
|
||||
|
@ -344,6 +346,12 @@ static int mwifiex_uap_parse_tail_ies(struct mwifiex_private *priv,
|
|||
*/
|
||||
while (left_len > sizeof(struct ieee_types_header)) {
|
||||
hdr = (void *)(info->tail + parsed_len);
|
||||
token_len = hdr->len + sizeof(struct ieee_types_header);
|
||||
if (token_len > left_len) {
|
||||
err = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
switch (hdr->element_id) {
|
||||
case WLAN_EID_SSID:
|
||||
case WLAN_EID_SUPP_RATES:
|
||||
|
@ -361,17 +369,20 @@ static int mwifiex_uap_parse_tail_ies(struct mwifiex_private *priv,
|
|||
if (cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT,
|
||||
WLAN_OUI_TYPE_MICROSOFT_WMM,
|
||||
(const u8 *)hdr,
|
||||
hdr->len + sizeof(struct ieee_types_header)))
|
||||
token_len))
|
||||
break;
|
||||
/* fall through */
|
||||
default:
|
||||
memcpy(gen_ie->ie_buffer + ie_len, hdr,
|
||||
hdr->len + sizeof(struct ieee_types_header));
|
||||
ie_len += hdr->len + sizeof(struct ieee_types_header);
|
||||
if (ie_len + token_len > IEEE_MAX_IE_SIZE) {
|
||||
err = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
memcpy(gen_ie->ie_buffer + ie_len, hdr, token_len);
|
||||
ie_len += token_len;
|
||||
break;
|
||||
}
|
||||
left_len -= hdr->len + sizeof(struct ieee_types_header);
|
||||
parsed_len += hdr->len + sizeof(struct ieee_types_header);
|
||||
left_len -= token_len;
|
||||
parsed_len += token_len;
|
||||
}
|
||||
|
||||
/* parse only WPA vendor IE from tail, WMM IE is configured by
|
||||
|
@ -381,15 +392,17 @@ static int mwifiex_uap_parse_tail_ies(struct mwifiex_private *priv,
|
|||
WLAN_OUI_TYPE_MICROSOFT_WPA,
|
||||
info->tail, info->tail_len);
|
||||
if (vendorhdr) {
|
||||
memcpy(gen_ie->ie_buffer + ie_len, vendorhdr,
|
||||
vendorhdr->len + sizeof(struct ieee_types_header));
|
||||
ie_len += vendorhdr->len + sizeof(struct ieee_types_header);
|
||||
token_len = vendorhdr->len + sizeof(struct ieee_types_header);
|
||||
if (ie_len + token_len > IEEE_MAX_IE_SIZE) {
|
||||
err = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
memcpy(gen_ie->ie_buffer + ie_len, vendorhdr, token_len);
|
||||
ie_len += token_len;
|
||||
}
|
||||
|
||||
if (!ie_len) {
|
||||
kfree(gen_ie);
|
||||
return 0;
|
||||
}
|
||||
if (!ie_len)
|
||||
goto out;
|
||||
|
||||
gen_ie->ie_index = cpu_to_le16(gen_idx);
|
||||
gen_ie->mgmt_subtype_mask = cpu_to_le16(MGMT_MASK_BEACON |
|
||||
|
@ -399,13 +412,15 @@ static int mwifiex_uap_parse_tail_ies(struct mwifiex_private *priv,
|
|||
|
||||
if (mwifiex_update_uap_custom_ie(priv, gen_ie, &gen_idx, NULL, NULL,
|
||||
NULL, NULL)) {
|
||||
kfree(gen_ie);
|
||||
return -1;
|
||||
err = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
priv->gen_idx = gen_idx;
|
||||
|
||||
out:
|
||||
kfree(gen_ie);
|
||||
return 0;
|
||||
return err;
|
||||
}
|
||||
|
||||
/* This function parses different IEs-head & tail IEs, beacon IEs,
|
||||
|
|
|
@ -1247,6 +1247,8 @@ int mwifiex_update_bss_desc_with_ie(struct mwifiex_adapter *adapter,
|
|||
}
|
||||
switch (element_id) {
|
||||
case WLAN_EID_SSID:
|
||||
if (element_len > IEEE80211_MAX_SSID_LEN)
|
||||
return -EINVAL;
|
||||
bss_entry->ssid.ssid_len = element_len;
|
||||
memcpy(bss_entry->ssid.ssid, (current_ptr + 2),
|
||||
element_len);
|
||||
|
@ -1256,6 +1258,8 @@ int mwifiex_update_bss_desc_with_ie(struct mwifiex_adapter *adapter,
|
|||
break;
|
||||
|
||||
case WLAN_EID_SUPP_RATES:
|
||||
if (element_len > MWIFIEX_SUPPORTED_RATES)
|
||||
return -EINVAL;
|
||||
memcpy(bss_entry->data_rates, current_ptr + 2,
|
||||
element_len);
|
||||
memcpy(bss_entry->supported_rates, current_ptr + 2,
|
||||
|
@ -1265,6 +1269,8 @@ int mwifiex_update_bss_desc_with_ie(struct mwifiex_adapter *adapter,
|
|||
break;
|
||||
|
||||
case WLAN_EID_FH_PARAMS:
|
||||
if (element_len + 2 < sizeof(*fh_param_set))
|
||||
return -EINVAL;
|
||||
fh_param_set =
|
||||
(struct ieee_types_fh_param_set *) current_ptr;
|
||||
memcpy(&bss_entry->phy_param_set.fh_param_set,
|
||||
|
@ -1273,6 +1279,8 @@ int mwifiex_update_bss_desc_with_ie(struct mwifiex_adapter *adapter,
|
|||
break;
|
||||
|
||||
case WLAN_EID_DS_PARAMS:
|
||||
if (element_len + 2 < sizeof(*ds_param_set))
|
||||
return -EINVAL;
|
||||
ds_param_set =
|
||||
(struct ieee_types_ds_param_set *) current_ptr;
|
||||
|
||||
|
@ -1284,6 +1292,8 @@ int mwifiex_update_bss_desc_with_ie(struct mwifiex_adapter *adapter,
|
|||
break;
|
||||
|
||||
case WLAN_EID_CF_PARAMS:
|
||||
if (element_len + 2 < sizeof(*cf_param_set))
|
||||
return -EINVAL;
|
||||
cf_param_set =
|
||||
(struct ieee_types_cf_param_set *) current_ptr;
|
||||
memcpy(&bss_entry->ss_param_set.cf_param_set,
|
||||
|
@ -1292,6 +1302,8 @@ int mwifiex_update_bss_desc_with_ie(struct mwifiex_adapter *adapter,
|
|||
break;
|
||||
|
||||
case WLAN_EID_IBSS_PARAMS:
|
||||
if (element_len + 2 < sizeof(*ibss_param_set))
|
||||
return -EINVAL;
|
||||
ibss_param_set =
|
||||
(struct ieee_types_ibss_param_set *)
|
||||
current_ptr;
|
||||
|
@ -1301,10 +1313,14 @@ int mwifiex_update_bss_desc_with_ie(struct mwifiex_adapter *adapter,
|
|||
break;
|
||||
|
||||
case WLAN_EID_ERP_INFO:
|
||||
if (!element_len)
|
||||
return -EINVAL;
|
||||
bss_entry->erp_flags = *(current_ptr + 2);
|
||||
break;
|
||||
|
||||
case WLAN_EID_PWR_CONSTRAINT:
|
||||
if (!element_len)
|
||||
return -EINVAL;
|
||||
bss_entry->local_constraint = *(current_ptr + 2);
|
||||
bss_entry->sensed_11h = true;
|
||||
break;
|
||||
|
@ -1345,6 +1361,9 @@ int mwifiex_update_bss_desc_with_ie(struct mwifiex_adapter *adapter,
|
|||
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;
|
||||
|
||||
|
|
|
@ -8,7 +8,8 @@
|
|||
#include "reg.h"
|
||||
#include "debug.h"
|
||||
|
||||
void rtw_fw_c2h_cmd_handle_ext(struct rtw_dev *rtwdev, struct sk_buff *skb)
|
||||
static void rtw_fw_c2h_cmd_handle_ext(struct rtw_dev *rtwdev,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
struct rtw_c2h_cmd *c2h;
|
||||
u8 sub_cmd_id;
|
||||
|
@ -47,7 +48,8 @@ void rtw_fw_c2h_cmd_handle(struct rtw_dev *rtwdev, struct sk_buff *skb)
|
|||
}
|
||||
}
|
||||
|
||||
void rtw_fw_send_h2c_command(struct rtw_dev *rtwdev, u8 *h2c)
|
||||
static void rtw_fw_send_h2c_command(struct rtw_dev *rtwdev,
|
||||
u8 *h2c)
|
||||
{
|
||||
u8 box;
|
||||
u8 box_state;
|
||||
|
|
|
@ -162,7 +162,8 @@ static void rtw_watch_dog_work(struct work_struct *work)
|
|||
rtwdev->stats.tx_cnt = 0;
|
||||
rtwdev->stats.rx_cnt = 0;
|
||||
|
||||
rtw_iterate_vifs(rtwdev, rtw_vif_watch_dog_iter, &data);
|
||||
/* use atomic version to avoid taking local->iflist_mtx mutex */
|
||||
rtw_iterate_vifs_atomic(rtwdev, rtw_vif_watch_dog_iter, &data);
|
||||
|
||||
/* fw supports only one station associated to enter lps, if there are
|
||||
* more than two stations associated to the AP, then we can not enter
|
||||
|
|
|
@ -144,10 +144,10 @@ static void rtw_phy_stat_rssi_iter(void *data, struct ieee80211_sta *sta)
|
|||
struct rtw_phy_stat_iter_data *iter_data = data;
|
||||
struct rtw_dev *rtwdev = iter_data->rtwdev;
|
||||
struct rtw_sta_info *si = (struct rtw_sta_info *)sta->drv_priv;
|
||||
u8 rssi, rssi_level;
|
||||
u8 rssi;
|
||||
|
||||
rssi = ewma_rssi_read(&si->avg_rssi);
|
||||
rssi_level = rtw_phy_get_rssi_level(si->rssi_level, rssi);
|
||||
si->rssi_level = rtw_phy_get_rssi_level(si->rssi_level, rssi);
|
||||
|
||||
rtw_fw_send_rssi_info(rtwdev, si);
|
||||
|
||||
|
@ -423,6 +423,11 @@ static u64 rtw_phy_db_2_linear(u8 power_db)
|
|||
u8 i, j;
|
||||
u64 linear;
|
||||
|
||||
if (power_db > 96)
|
||||
power_db = 96;
|
||||
else if (power_db < 1)
|
||||
return 1;
|
||||
|
||||
/* 1dB ~ 96dB */
|
||||
i = (power_db - 1) >> 3;
|
||||
j = (power_db - 1) - (i << 3);
|
||||
|
@ -848,12 +853,13 @@ u8 rtw_vht_2s_rates[] = {
|
|||
DESC_RATEVHT2SS_MCS6, DESC_RATEVHT2SS_MCS7,
|
||||
DESC_RATEVHT2SS_MCS8, DESC_RATEVHT2SS_MCS9
|
||||
};
|
||||
u8 rtw_cck_size = ARRAY_SIZE(rtw_cck_rates);
|
||||
u8 rtw_ofdm_size = ARRAY_SIZE(rtw_ofdm_rates);
|
||||
u8 rtw_ht_1s_size = ARRAY_SIZE(rtw_ht_1s_rates);
|
||||
u8 rtw_ht_2s_size = ARRAY_SIZE(rtw_ht_2s_rates);
|
||||
u8 rtw_vht_1s_size = ARRAY_SIZE(rtw_vht_1s_rates);
|
||||
u8 rtw_vht_2s_size = ARRAY_SIZE(rtw_vht_2s_rates);
|
||||
|
||||
static u8 rtw_cck_size = ARRAY_SIZE(rtw_cck_rates);
|
||||
static u8 rtw_ofdm_size = ARRAY_SIZE(rtw_ofdm_rates);
|
||||
static u8 rtw_ht_1s_size = ARRAY_SIZE(rtw_ht_1s_rates);
|
||||
static u8 rtw_ht_2s_size = ARRAY_SIZE(rtw_ht_2s_rates);
|
||||
static u8 rtw_vht_1s_size = ARRAY_SIZE(rtw_vht_1s_rates);
|
||||
static u8 rtw_vht_2s_size = ARRAY_SIZE(rtw_vht_2s_rates);
|
||||
u8 *rtw_rate_section[RTW_RATE_SECTION_MAX] = {
|
||||
rtw_cck_rates, rtw_ofdm_rates,
|
||||
rtw_ht_1s_rates, rtw_ht_2s_rates,
|
||||
|
|
|
@ -929,11 +929,15 @@ static int rsi_sdio_ta_reset(struct rsi_hw *adapter)
|
|||
u32 addr;
|
||||
u8 *data;
|
||||
|
||||
data = kzalloc(RSI_9116_REG_SIZE, GFP_KERNEL);
|
||||
if (!data)
|
||||
return -ENOMEM;
|
||||
|
||||
status = rsi_sdio_master_access_msword(adapter, TA_BASE_ADDR);
|
||||
if (status < 0) {
|
||||
rsi_dbg(ERR_ZONE,
|
||||
"Unable to set ms word to common reg\n");
|
||||
return status;
|
||||
goto err;
|
||||
}
|
||||
|
||||
rsi_dbg(INIT_ZONE, "%s: Bring TA out of reset\n", __func__);
|
||||
|
@ -944,7 +948,7 @@ static int rsi_sdio_ta_reset(struct rsi_hw *adapter)
|
|||
RSI_9116_REG_SIZE);
|
||||
if (status < 0) {
|
||||
rsi_dbg(ERR_ZONE, "Unable to hold TA threads\n");
|
||||
return status;
|
||||
goto err;
|
||||
}
|
||||
|
||||
put_unaligned_le32(TA_SOFT_RST_CLR, data);
|
||||
|
@ -954,7 +958,7 @@ static int rsi_sdio_ta_reset(struct rsi_hw *adapter)
|
|||
RSI_9116_REG_SIZE);
|
||||
if (status < 0) {
|
||||
rsi_dbg(ERR_ZONE, "Unable to get TA out of reset\n");
|
||||
return status;
|
||||
goto err;
|
||||
}
|
||||
|
||||
put_unaligned_le32(TA_PC_ZERO, data);
|
||||
|
@ -964,7 +968,8 @@ static int rsi_sdio_ta_reset(struct rsi_hw *adapter)
|
|||
RSI_9116_REG_SIZE);
|
||||
if (status < 0) {
|
||||
rsi_dbg(ERR_ZONE, "Unable to Reset TA PC value\n");
|
||||
return -EINVAL;
|
||||
status = -EINVAL;
|
||||
goto err;
|
||||
}
|
||||
|
||||
put_unaligned_le32(TA_RELEASE_THREAD_VALUE, data);
|
||||
|
@ -974,17 +979,19 @@ static int rsi_sdio_ta_reset(struct rsi_hw *adapter)
|
|||
RSI_9116_REG_SIZE);
|
||||
if (status < 0) {
|
||||
rsi_dbg(ERR_ZONE, "Unable to release TA threads\n");
|
||||
return status;
|
||||
goto err;
|
||||
}
|
||||
|
||||
status = rsi_sdio_master_access_msword(adapter, MISC_CFG_BASE_ADDR);
|
||||
if (status < 0) {
|
||||
rsi_dbg(ERR_ZONE, "Unable to set ms word to common reg\n");
|
||||
return status;
|
||||
goto err;
|
||||
}
|
||||
rsi_dbg(INIT_ZONE, "***** TA Reset done *****\n");
|
||||
|
||||
return 0;
|
||||
err:
|
||||
kfree(data);
|
||||
return status;
|
||||
}
|
||||
|
||||
static struct rsi_host_intf_ops sdio_host_intf_ops = {
|
||||
|
|
|
@ -238,6 +238,12 @@ int bpf_percpu_cgroup_storage_update(struct bpf_map *map, void *key,
|
|||
#define BPF_CGROUP_RUN_PROG_UDP6_SENDMSG_LOCK(sk, uaddr, t_ctx) \
|
||||
BPF_CGROUP_RUN_SA_PROG_LOCK(sk, uaddr, BPF_CGROUP_UDP6_SENDMSG, t_ctx)
|
||||
|
||||
#define BPF_CGROUP_RUN_PROG_UDP4_RECVMSG_LOCK(sk, uaddr) \
|
||||
BPF_CGROUP_RUN_SA_PROG_LOCK(sk, uaddr, BPF_CGROUP_UDP4_RECVMSG, NULL)
|
||||
|
||||
#define BPF_CGROUP_RUN_PROG_UDP6_RECVMSG_LOCK(sk, uaddr) \
|
||||
BPF_CGROUP_RUN_SA_PROG_LOCK(sk, uaddr, BPF_CGROUP_UDP6_RECVMSG, NULL)
|
||||
|
||||
#define BPF_CGROUP_RUN_PROG_SOCK_OPS(sock_ops) \
|
||||
({ \
|
||||
int __ret = 0; \
|
||||
|
@ -339,6 +345,8 @@ static inline int bpf_percpu_cgroup_storage_update(struct bpf_map *map,
|
|||
#define BPF_CGROUP_RUN_PROG_INET6_CONNECT_LOCK(sk, uaddr) ({ 0; })
|
||||
#define BPF_CGROUP_RUN_PROG_UDP4_SENDMSG_LOCK(sk, uaddr, t_ctx) ({ 0; })
|
||||
#define BPF_CGROUP_RUN_PROG_UDP6_SENDMSG_LOCK(sk, uaddr, t_ctx) ({ 0; })
|
||||
#define BPF_CGROUP_RUN_PROG_UDP4_RECVMSG_LOCK(sk, uaddr) ({ 0; })
|
||||
#define BPF_CGROUP_RUN_PROG_UDP6_RECVMSG_LOCK(sk, uaddr) ({ 0; })
|
||||
#define BPF_CGROUP_RUN_PROG_SOCK_OPS(sock_ops) ({ 0; })
|
||||
#define BPF_CGROUP_RUN_PROG_DEVICE_CGROUP(type,major,minor,access) ({ 0; })
|
||||
#define BPF_CGROUP_RUN_PROG_SYSCTL(head,table,write,buf,count,pos,nbuf) ({ 0; })
|
||||
|
|
|
@ -600,7 +600,6 @@ void bpf_map_area_free(void *base);
|
|||
void bpf_map_init_from_attr(struct bpf_map *map, union bpf_attr *attr);
|
||||
|
||||
extern int sysctl_unprivileged_bpf_disabled;
|
||||
extern int sysctl_bpf_stats_enabled;
|
||||
|
||||
int bpf_map_new_fd(struct bpf_map *map, int flags);
|
||||
int bpf_prog_new_fd(struct bpf_prog *prog);
|
||||
|
|
|
@ -123,11 +123,20 @@ int mac_link_state(struct net_device *ndev,
|
|||
* @mode: one of %MLO_AN_FIXED, %MLO_AN_PHY, %MLO_AN_INBAND.
|
||||
* @state: a pointer to a &struct phylink_link_state.
|
||||
*
|
||||
* Note - not all members of @state are valid. In particular,
|
||||
* @state->lp_advertising, @state->link, @state->an_complete are never
|
||||
* guaranteed to be correct, and so any mac_config() implementation must
|
||||
* never reference these fields.
|
||||
*
|
||||
* The action performed depends on the currently selected mode:
|
||||
*
|
||||
* %MLO_AN_FIXED, %MLO_AN_PHY:
|
||||
* Configure the specified @state->speed, @state->duplex and
|
||||
* @state->pause (%MLO_PAUSE_TX / %MLO_PAUSE_RX) mode.
|
||||
* @state->pause (%MLO_PAUSE_TX / %MLO_PAUSE_RX) modes over a link
|
||||
* specified by @state->interface. @state->advertising may be used,
|
||||
* but is not required. Other members of @state must be ignored.
|
||||
*
|
||||
* Valid state members: interface, speed, duplex, pause, advertising.
|
||||
*
|
||||
* %MLO_AN_INBAND:
|
||||
* place the link in an inband negotiation mode (such as 802.3z
|
||||
|
@ -150,6 +159,8 @@ int mac_link_state(struct net_device *ndev,
|
|||
* responsible for reading the configuration word and configuring
|
||||
* itself accordingly.
|
||||
*
|
||||
* Valid state members: interface, an_enabled, pause, advertising.
|
||||
*
|
||||
* Implementations are expected to update the MAC to reflect the
|
||||
* requested settings - i.o.w., if nothing has changed between two
|
||||
* calls, no action is expected. If only flow control settings have
|
||||
|
|
|
@ -351,6 +351,8 @@ static inline void sk_psock_update_proto(struct sock *sk,
|
|||
static inline void sk_psock_restore_proto(struct sock *sk,
|
||||
struct sk_psock *psock)
|
||||
{
|
||||
sk->sk_write_space = psock->saved_write_space;
|
||||
|
||||
if (psock->sk_proto) {
|
||||
sk->sk_prot = psock->sk_proto;
|
||||
psock->sk_proto = NULL;
|
||||
|
|
|
@ -63,6 +63,9 @@ extern int proc_doulongvec_ms_jiffies_minmax(struct ctl_table *table, int,
|
|||
void __user *, size_t *, loff_t *);
|
||||
extern int proc_do_large_bitmap(struct ctl_table *, int,
|
||||
void __user *, size_t *, loff_t *);
|
||||
extern int proc_do_static_key(struct ctl_table *table, int write,
|
||||
void __user *buffer, size_t *lenp,
|
||||
loff_t *ppos);
|
||||
|
||||
/*
|
||||
* Register a set of sysctl names by calling register_sysctl_table
|
||||
|
|
|
@ -484,4 +484,8 @@ static inline u16 tcp_mss_clamp(const struct tcp_sock *tp, u16 mss)
|
|||
|
||||
return (user_mss && user_mss < mss) ? user_mss : mss;
|
||||
}
|
||||
|
||||
int tcp_skb_shift(struct sk_buff *to, struct sk_buff *from, int pcount,
|
||||
int shiftlen);
|
||||
|
||||
#endif /* _LINUX_TCP_H */
|
||||
|
|
|
@ -309,6 +309,22 @@ static inline struct inet6_dev *__in6_dev_get(const struct net_device *dev)
|
|||
return rcu_dereference_rtnl(dev->ip6_ptr);
|
||||
}
|
||||
|
||||
/**
|
||||
* __in6_dev_stats_get - get inet6_dev pointer for stats
|
||||
* @dev: network device
|
||||
* @skb: skb for original incoming interface if neeeded
|
||||
*
|
||||
* Caller must hold rcu_read_lock or RTNL, because this function
|
||||
* does not take a reference on the inet6_dev.
|
||||
*/
|
||||
static inline struct inet6_dev *__in6_dev_stats_get(const struct net_device *dev,
|
||||
const struct sk_buff *skb)
|
||||
{
|
||||
if (netif_is_l3_master(dev))
|
||||
dev = dev_get_by_index_rcu(dev_net(dev), inet6_iif(skb));
|
||||
return __in6_dev_get(dev);
|
||||
}
|
||||
|
||||
/**
|
||||
* __in6_dev_get_safely - get inet6_dev pointer from netdevice
|
||||
* @dev: network device
|
||||
|
|
|
@ -3839,7 +3839,8 @@ struct cfg80211_ops {
|
|||
* on wiphy_new(), but can be changed by the driver if it has a good
|
||||
* reason to override the default
|
||||
* @WIPHY_FLAG_4ADDR_AP: supports 4addr mode even on AP (with a single station
|
||||
* on a VLAN interface)
|
||||
* on a VLAN interface). This flag also serves an extra purpose of
|
||||
* supporting 4ADDR AP mode on devices which do not support AP/VLAN iftype.
|
||||
* @WIPHY_FLAG_4ADDR_STATION: supports 4addr mode even as a station
|
||||
* @WIPHY_FLAG_CONTROL_PORT_PROTOCOL: This device supports setting the
|
||||
* control port protocol ethertype. The device also honours the
|
||||
|
|
|
@ -46,6 +46,7 @@ struct flow_dissector_key_tags {
|
|||
|
||||
struct flow_dissector_key_vlan {
|
||||
u16 vlan_id:12,
|
||||
vlan_dei:1,
|
||||
vlan_priority:3;
|
||||
__be16 vlan_tpid;
|
||||
};
|
||||
|
|
|
@ -117,6 +117,7 @@ struct netns_ipv4 {
|
|||
#endif
|
||||
int sysctl_tcp_mtu_probing;
|
||||
int sysctl_tcp_base_mss;
|
||||
int sysctl_tcp_min_snd_mss;
|
||||
int sysctl_tcp_probe_threshold;
|
||||
u32 sysctl_tcp_probe_interval;
|
||||
|
||||
|
|
|
@ -1463,12 +1463,14 @@ static inline void sk_mem_uncharge(struct sock *sk, int size)
|
|||
__sk_mem_reclaim(sk, 1 << 20);
|
||||
}
|
||||
|
||||
DECLARE_STATIC_KEY_FALSE(tcp_tx_skb_cache_key);
|
||||
static inline void sk_wmem_free_skb(struct sock *sk, struct sk_buff *skb)
|
||||
{
|
||||
sock_set_flag(sk, SOCK_QUEUE_SHRUNK);
|
||||
sk->sk_wmem_queued -= skb->truesize;
|
||||
sk_mem_uncharge(sk, skb->truesize);
|
||||
if (!sk->sk_tx_skb_cache && !skb_cloned(skb)) {
|
||||
if (static_branch_unlikely(&tcp_tx_skb_cache_key) &&
|
||||
!sk->sk_tx_skb_cache && !skb_cloned(skb)) {
|
||||
skb_zcopy_clear(skb, true);
|
||||
sk->sk_tx_skb_cache = skb;
|
||||
return;
|
||||
|
@ -2433,13 +2435,11 @@ static inline void skb_setup_tx_timestamp(struct sk_buff *skb, __u16 tsflags)
|
|||
* This routine must be called with interrupts disabled or with the socket
|
||||
* locked so that the sk_buff queue operation is ok.
|
||||
*/
|
||||
DECLARE_STATIC_KEY_FALSE(tcp_rx_skb_cache_key);
|
||||
static inline void sk_eat_skb(struct sock *sk, struct sk_buff *skb)
|
||||
{
|
||||
__skb_unlink(skb, &sk->sk_receive_queue);
|
||||
if (
|
||||
#ifdef CONFIG_RPS
|
||||
!static_branch_unlikely(&rps_needed) &&
|
||||
#endif
|
||||
if (static_branch_unlikely(&tcp_rx_skb_cache_key) &&
|
||||
!sk->sk_rx_skb_cache) {
|
||||
sk->sk_rx_skb_cache = skb;
|
||||
skb_orphan(skb);
|
||||
|
@ -2534,6 +2534,8 @@ extern int sysctl_optmem_max;
|
|||
extern __u32 sysctl_wmem_default;
|
||||
extern __u32 sysctl_rmem_default;
|
||||
|
||||
DECLARE_STATIC_KEY_FALSE(net_high_order_alloc_disable_key);
|
||||
|
||||
static inline int sk_get_wmem0(const struct sock *sk, const struct proto *proto)
|
||||
{
|
||||
/* Does this proto have per netns sysctl_wmem ? */
|
||||
|
|
|
@ -51,6 +51,8 @@ void tcp_time_wait(struct sock *sk, int state, int timeo);
|
|||
|
||||
#define MAX_TCP_HEADER (128 + MAX_HEADER)
|
||||
#define MAX_TCP_OPTION_SPACE 40
|
||||
#define TCP_MIN_SND_MSS 48
|
||||
#define TCP_MIN_GSO_SIZE (TCP_MIN_SND_MSS - MAX_TCP_OPTION_SPACE)
|
||||
|
||||
/*
|
||||
* Never offer a window over 32767 without using window scaling. Some
|
||||
|
|
|
@ -192,6 +192,8 @@ enum bpf_attach_type {
|
|||
BPF_LIRC_MODE2,
|
||||
BPF_FLOW_DISSECTOR,
|
||||
BPF_CGROUP_SYSCTL,
|
||||
BPF_CGROUP_UDP4_RECVMSG,
|
||||
BPF_CGROUP_UDP6_RECVMSG,
|
||||
__MAX_BPF_ATTACH_TYPE
|
||||
};
|
||||
|
||||
|
@ -3376,8 +3378,8 @@ struct bpf_raw_tracepoint_args {
|
|||
/* DIRECT: Skip the FIB rules and go to FIB table associated with device
|
||||
* OUTPUT: Do lookup from egress perspective; default is ingress
|
||||
*/
|
||||
#define BPF_FIB_LOOKUP_DIRECT BIT(0)
|
||||
#define BPF_FIB_LOOKUP_OUTPUT BIT(1)
|
||||
#define BPF_FIB_LOOKUP_DIRECT (1U << 0)
|
||||
#define BPF_FIB_LOOKUP_OUTPUT (1U << 1)
|
||||
|
||||
enum {
|
||||
BPF_FIB_LKUP_RET_SUCCESS, /* lookup successful */
|
||||
|
|
|
@ -283,6 +283,7 @@ enum
|
|||
LINUX_MIB_TCPACKCOMPRESSED, /* TCPAckCompressed */
|
||||
LINUX_MIB_TCPZEROWINDOWDROP, /* TCPZeroWindowDrop */
|
||||
LINUX_MIB_TCPRCVQDROP, /* TCPRcvQDrop */
|
||||
LINUX_MIB_TCPWQUEUETOOBIG, /* TCPWqueueTooBig */
|
||||
__LINUX_MIB_MAX
|
||||
};
|
||||
|
||||
|
|
|
@ -2097,7 +2097,6 @@ int __weak skb_copy_bits(const struct sk_buff *skb, int offset, void *to,
|
|||
|
||||
DEFINE_STATIC_KEY_FALSE(bpf_stats_enabled_key);
|
||||
EXPORT_SYMBOL(bpf_stats_enabled_key);
|
||||
int sysctl_bpf_stats_enabled __read_mostly;
|
||||
|
||||
/* All definitions of tracepoints related to BPF. */
|
||||
#define CREATE_TRACE_POINTS
|
||||
|
|
|
@ -178,6 +178,7 @@ static void dev_map_free(struct bpf_map *map)
|
|||
if (!dev)
|
||||
continue;
|
||||
|
||||
free_percpu(dev->bulkq);
|
||||
dev_put(dev->dev);
|
||||
kfree(dev);
|
||||
}
|
||||
|
@ -273,6 +274,7 @@ void __dev_map_flush(struct bpf_map *map)
|
|||
unsigned long *bitmap = this_cpu_ptr(dtab->flush_needed);
|
||||
u32 bit;
|
||||
|
||||
rcu_read_lock();
|
||||
for_each_set_bit(bit, bitmap, map->max_entries) {
|
||||
struct bpf_dtab_netdev *dev = READ_ONCE(dtab->netdev_map[bit]);
|
||||
struct xdp_bulk_queue *bq;
|
||||
|
@ -283,11 +285,12 @@ void __dev_map_flush(struct bpf_map *map)
|
|||
if (unlikely(!dev))
|
||||
continue;
|
||||
|
||||
__clear_bit(bit, bitmap);
|
||||
|
||||
bq = this_cpu_ptr(dev->bulkq);
|
||||
bq_xmit_all(dev, bq, XDP_XMIT_FLUSH, true);
|
||||
|
||||
__clear_bit(bit, bitmap);
|
||||
}
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
/* rcu_read_lock (from syscall and BPF contexts) ensures that if a delete and/or
|
||||
|
@ -380,6 +383,7 @@ static void dev_map_flush_old(struct bpf_dtab_netdev *dev)
|
|||
|
||||
int cpu;
|
||||
|
||||
rcu_read_lock();
|
||||
for_each_online_cpu(cpu) {
|
||||
bitmap = per_cpu_ptr(dev->dtab->flush_needed, cpu);
|
||||
__clear_bit(dev->bit, bitmap);
|
||||
|
@ -387,6 +391,7 @@ static void dev_map_flush_old(struct bpf_dtab_netdev *dev)
|
|||
bq = per_cpu_ptr(dev->bulkq, cpu);
|
||||
bq_xmit_all(dev, bq, XDP_XMIT_FLUSH, false);
|
||||
}
|
||||
rcu_read_unlock();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -716,9 +716,14 @@ find_leftmost:
|
|||
* have exact two children, so this function will never return NULL.
|
||||
*/
|
||||
for (node = search_root; node;) {
|
||||
if (!(node->flags & LPM_TREE_NODE_FLAG_IM))
|
||||
if (node->flags & LPM_TREE_NODE_FLAG_IM) {
|
||||
node = rcu_dereference(node->child[0]);
|
||||
} else {
|
||||
next_node = node;
|
||||
node = rcu_dereference(node->child[0]);
|
||||
node = rcu_dereference(node->child[0]);
|
||||
if (!node)
|
||||
node = rcu_dereference(next_node->child[1]);
|
||||
}
|
||||
}
|
||||
do_copy:
|
||||
next_key->prefixlen = next_node->prefixlen;
|
||||
|
|
|
@ -1573,6 +1573,8 @@ bpf_prog_load_check_attach_type(enum bpf_prog_type prog_type,
|
|||
case BPF_CGROUP_INET6_CONNECT:
|
||||
case BPF_CGROUP_UDP4_SENDMSG:
|
||||
case BPF_CGROUP_UDP6_SENDMSG:
|
||||
case BPF_CGROUP_UDP4_RECVMSG:
|
||||
case BPF_CGROUP_UDP6_RECVMSG:
|
||||
return 0;
|
||||
default:
|
||||
return -EINVAL;
|
||||
|
@ -1867,6 +1869,8 @@ static int bpf_prog_attach(const union bpf_attr *attr)
|
|||
case BPF_CGROUP_INET6_CONNECT:
|
||||
case BPF_CGROUP_UDP4_SENDMSG:
|
||||
case BPF_CGROUP_UDP6_SENDMSG:
|
||||
case BPF_CGROUP_UDP4_RECVMSG:
|
||||
case BPF_CGROUP_UDP6_RECVMSG:
|
||||
ptype = BPF_PROG_TYPE_CGROUP_SOCK_ADDR;
|
||||
break;
|
||||
case BPF_CGROUP_SOCK_OPS:
|
||||
|
@ -1952,6 +1956,8 @@ static int bpf_prog_detach(const union bpf_attr *attr)
|
|||
case BPF_CGROUP_INET6_CONNECT:
|
||||
case BPF_CGROUP_UDP4_SENDMSG:
|
||||
case BPF_CGROUP_UDP6_SENDMSG:
|
||||
case BPF_CGROUP_UDP4_RECVMSG:
|
||||
case BPF_CGROUP_UDP6_RECVMSG:
|
||||
ptype = BPF_PROG_TYPE_CGROUP_SOCK_ADDR;
|
||||
break;
|
||||
case BPF_CGROUP_SOCK_OPS:
|
||||
|
@ -2003,6 +2009,8 @@ static int bpf_prog_query(const union bpf_attr *attr,
|
|||
case BPF_CGROUP_INET6_CONNECT:
|
||||
case BPF_CGROUP_UDP4_SENDMSG:
|
||||
case BPF_CGROUP_UDP6_SENDMSG:
|
||||
case BPF_CGROUP_UDP4_RECVMSG:
|
||||
case BPF_CGROUP_UDP6_RECVMSG:
|
||||
case BPF_CGROUP_SOCK_OPS:
|
||||
case BPF_CGROUP_DEVICE:
|
||||
case BPF_CGROUP_SYSCTL:
|
||||
|
|
|
@ -5353,9 +5353,12 @@ static int check_return_code(struct bpf_verifier_env *env)
|
|||
struct tnum range = tnum_range(0, 1);
|
||||
|
||||
switch (env->prog->type) {
|
||||
case BPF_PROG_TYPE_CGROUP_SOCK_ADDR:
|
||||
if (env->prog->expected_attach_type == BPF_CGROUP_UDP4_RECVMSG ||
|
||||
env->prog->expected_attach_type == BPF_CGROUP_UDP6_RECVMSG)
|
||||
range = tnum_range(1, 1);
|
||||
case BPF_PROG_TYPE_CGROUP_SKB:
|
||||
case BPF_PROG_TYPE_CGROUP_SOCK:
|
||||
case BPF_PROG_TYPE_CGROUP_SOCK_ADDR:
|
||||
case BPF_PROG_TYPE_SOCK_OPS:
|
||||
case BPF_PROG_TYPE_CGROUP_DEVICE:
|
||||
case BPF_PROG_TYPE_CGROUP_SYSCTL:
|
||||
|
@ -5372,16 +5375,17 @@ static int check_return_code(struct bpf_verifier_env *env)
|
|||
}
|
||||
|
||||
if (!tnum_in(range, reg->var_off)) {
|
||||
char tn_buf[48];
|
||||
|
||||
verbose(env, "At program exit the register R0 ");
|
||||
if (!tnum_is_unknown(reg->var_off)) {
|
||||
char tn_buf[48];
|
||||
|
||||
tnum_strn(tn_buf, sizeof(tn_buf), reg->var_off);
|
||||
verbose(env, "has value %s", tn_buf);
|
||||
} else {
|
||||
verbose(env, "has unknown scalar value");
|
||||
}
|
||||
verbose(env, " should have been 0 or 1\n");
|
||||
tnum_strn(tn_buf, sizeof(tn_buf), range);
|
||||
verbose(env, " should have been in %s\n", tn_buf);
|
||||
return -EINVAL;
|
||||
}
|
||||
return 0;
|
||||
|
|
|
@ -230,11 +230,6 @@ static int proc_dostring_coredump(struct ctl_table *table, int write,
|
|||
#endif
|
||||
static int proc_dopipe_max_size(struct ctl_table *table, int write,
|
||||
void __user *buffer, size_t *lenp, loff_t *ppos);
|
||||
#ifdef CONFIG_BPF_SYSCALL
|
||||
static int proc_dointvec_minmax_bpf_stats(struct ctl_table *table, int write,
|
||||
void __user *buffer, size_t *lenp,
|
||||
loff_t *ppos);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_MAGIC_SYSRQ
|
||||
/* Note: sysrq code uses its own private copy */
|
||||
|
@ -1253,12 +1248,10 @@ static struct ctl_table kern_table[] = {
|
|||
},
|
||||
{
|
||||
.procname = "bpf_stats_enabled",
|
||||
.data = &sysctl_bpf_stats_enabled,
|
||||
.maxlen = sizeof(sysctl_bpf_stats_enabled),
|
||||
.data = &bpf_stats_enabled_key.key,
|
||||
.maxlen = sizeof(bpf_stats_enabled_key),
|
||||
.mode = 0644,
|
||||
.proc_handler = proc_dointvec_minmax_bpf_stats,
|
||||
.extra1 = &zero,
|
||||
.extra2 = &one,
|
||||
.proc_handler = proc_do_static_key,
|
||||
},
|
||||
#endif
|
||||
#if defined(CONFIG_TREE_RCU) || defined(CONFIG_PREEMPT_RCU)
|
||||
|
@ -3374,26 +3367,35 @@ int proc_do_large_bitmap(struct ctl_table *table, int write,
|
|||
|
||||
#endif /* CONFIG_PROC_SYSCTL */
|
||||
|
||||
#if defined(CONFIG_BPF_SYSCALL) && defined(CONFIG_SYSCTL)
|
||||
static int proc_dointvec_minmax_bpf_stats(struct ctl_table *table, int write,
|
||||
void __user *buffer, size_t *lenp,
|
||||
loff_t *ppos)
|
||||
#if defined(CONFIG_SYSCTL)
|
||||
int proc_do_static_key(struct ctl_table *table, int write,
|
||||
void __user *buffer, size_t *lenp,
|
||||
loff_t *ppos)
|
||||
{
|
||||
int ret, bpf_stats = *(int *)table->data;
|
||||
struct ctl_table tmp = *table;
|
||||
struct static_key *key = (struct static_key *)table->data;
|
||||
static DEFINE_MUTEX(static_key_mutex);
|
||||
int val, ret;
|
||||
struct ctl_table tmp = {
|
||||
.data = &val,
|
||||
.maxlen = sizeof(val),
|
||||
.mode = table->mode,
|
||||
.extra1 = &zero,
|
||||
.extra2 = &one,
|
||||
};
|
||||
|
||||
if (write && !capable(CAP_SYS_ADMIN))
|
||||
return -EPERM;
|
||||
|
||||
tmp.data = &bpf_stats;
|
||||
mutex_lock(&static_key_mutex);
|
||||
val = static_key_enabled(key);
|
||||
ret = proc_dointvec_minmax(&tmp, write, buffer, lenp, ppos);
|
||||
if (write && !ret) {
|
||||
*(int *)table->data = bpf_stats;
|
||||
if (bpf_stats)
|
||||
static_branch_enable(&bpf_stats_enabled_key);
|
||||
if (val)
|
||||
static_key_enable(key);
|
||||
else
|
||||
static_branch_disable(&bpf_stats_enabled_key);
|
||||
static_key_disable(key);
|
||||
}
|
||||
mutex_unlock(&static_key_mutex);
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -410,8 +410,6 @@ static const struct bpf_func_proto bpf_perf_event_read_value_proto = {
|
|||
.arg4_type = ARG_CONST_SIZE,
|
||||
};
|
||||
|
||||
static DEFINE_PER_CPU(struct perf_sample_data, bpf_trace_sd);
|
||||
|
||||
static __always_inline u64
|
||||
__bpf_perf_event_output(struct pt_regs *regs, struct bpf_map *map,
|
||||
u64 flags, struct perf_sample_data *sd)
|
||||
|
@ -442,24 +440,50 @@ __bpf_perf_event_output(struct pt_regs *regs, struct bpf_map *map,
|
|||
return perf_event_output(event, sd, regs);
|
||||
}
|
||||
|
||||
/*
|
||||
* Support executing tracepoints in normal, irq, and nmi context that each call
|
||||
* bpf_perf_event_output
|
||||
*/
|
||||
struct bpf_trace_sample_data {
|
||||
struct perf_sample_data sds[3];
|
||||
};
|
||||
|
||||
static DEFINE_PER_CPU(struct bpf_trace_sample_data, bpf_trace_sds);
|
||||
static DEFINE_PER_CPU(int, bpf_trace_nest_level);
|
||||
BPF_CALL_5(bpf_perf_event_output, struct pt_regs *, regs, struct bpf_map *, map,
|
||||
u64, flags, void *, data, u64, size)
|
||||
{
|
||||
struct perf_sample_data *sd = this_cpu_ptr(&bpf_trace_sd);
|
||||
struct bpf_trace_sample_data *sds = this_cpu_ptr(&bpf_trace_sds);
|
||||
int nest_level = this_cpu_inc_return(bpf_trace_nest_level);
|
||||
struct perf_raw_record raw = {
|
||||
.frag = {
|
||||
.size = size,
|
||||
.data = data,
|
||||
},
|
||||
};
|
||||
struct perf_sample_data *sd;
|
||||
int err;
|
||||
|
||||
if (unlikely(flags & ~(BPF_F_INDEX_MASK)))
|
||||
return -EINVAL;
|
||||
if (WARN_ON_ONCE(nest_level > ARRAY_SIZE(sds->sds))) {
|
||||
err = -EBUSY;
|
||||
goto out;
|
||||
}
|
||||
|
||||
sd = &sds->sds[nest_level - 1];
|
||||
|
||||
if (unlikely(flags & ~(BPF_F_INDEX_MASK))) {
|
||||
err = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
perf_sample_data_init(sd, 0, 0);
|
||||
sd->raw = &raw;
|
||||
|
||||
return __bpf_perf_event_output(regs, map, flags, sd);
|
||||
err = __bpf_perf_event_output(regs, map, flags, sd);
|
||||
|
||||
out:
|
||||
this_cpu_dec(bpf_trace_nest_level);
|
||||
return err;
|
||||
}
|
||||
|
||||
static const struct bpf_func_proto bpf_perf_event_output_proto = {
|
||||
|
@ -822,16 +846,48 @@ pe_prog_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
|
|||
/*
|
||||
* bpf_raw_tp_regs are separate from bpf_pt_regs used from skb/xdp
|
||||
* to avoid potential recursive reuse issue when/if tracepoints are added
|
||||
* inside bpf_*_event_output, bpf_get_stackid and/or bpf_get_stack
|
||||
* inside bpf_*_event_output, bpf_get_stackid and/or bpf_get_stack.
|
||||
*
|
||||
* Since raw tracepoints run despite bpf_prog_active, support concurrent usage
|
||||
* in normal, irq, and nmi context.
|
||||
*/
|
||||
static DEFINE_PER_CPU(struct pt_regs, bpf_raw_tp_regs);
|
||||
struct bpf_raw_tp_regs {
|
||||
struct pt_regs regs[3];
|
||||
};
|
||||
static DEFINE_PER_CPU(struct bpf_raw_tp_regs, bpf_raw_tp_regs);
|
||||
static DEFINE_PER_CPU(int, bpf_raw_tp_nest_level);
|
||||
static struct pt_regs *get_bpf_raw_tp_regs(void)
|
||||
{
|
||||
struct bpf_raw_tp_regs *tp_regs = this_cpu_ptr(&bpf_raw_tp_regs);
|
||||
int nest_level = this_cpu_inc_return(bpf_raw_tp_nest_level);
|
||||
|
||||
if (WARN_ON_ONCE(nest_level > ARRAY_SIZE(tp_regs->regs))) {
|
||||
this_cpu_dec(bpf_raw_tp_nest_level);
|
||||
return ERR_PTR(-EBUSY);
|
||||
}
|
||||
|
||||
return &tp_regs->regs[nest_level - 1];
|
||||
}
|
||||
|
||||
static void put_bpf_raw_tp_regs(void)
|
||||
{
|
||||
this_cpu_dec(bpf_raw_tp_nest_level);
|
||||
}
|
||||
|
||||
BPF_CALL_5(bpf_perf_event_output_raw_tp, struct bpf_raw_tracepoint_args *, args,
|
||||
struct bpf_map *, map, u64, flags, void *, data, u64, size)
|
||||
{
|
||||
struct pt_regs *regs = this_cpu_ptr(&bpf_raw_tp_regs);
|
||||
struct pt_regs *regs = get_bpf_raw_tp_regs();
|
||||
int ret;
|
||||
|
||||
if (IS_ERR(regs))
|
||||
return PTR_ERR(regs);
|
||||
|
||||
perf_fetch_caller_regs(regs);
|
||||
return ____bpf_perf_event_output(regs, map, flags, data, size);
|
||||
ret = ____bpf_perf_event_output(regs, map, flags, data, size);
|
||||
|
||||
put_bpf_raw_tp_regs();
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct bpf_func_proto bpf_perf_event_output_proto_raw_tp = {
|
||||
|
@ -848,12 +904,18 @@ static const struct bpf_func_proto bpf_perf_event_output_proto_raw_tp = {
|
|||
BPF_CALL_3(bpf_get_stackid_raw_tp, struct bpf_raw_tracepoint_args *, args,
|
||||
struct bpf_map *, map, u64, flags)
|
||||
{
|
||||
struct pt_regs *regs = this_cpu_ptr(&bpf_raw_tp_regs);
|
||||
struct pt_regs *regs = get_bpf_raw_tp_regs();
|
||||
int ret;
|
||||
|
||||
if (IS_ERR(regs))
|
||||
return PTR_ERR(regs);
|
||||
|
||||
perf_fetch_caller_regs(regs);
|
||||
/* similar to bpf_perf_event_output_tp, but pt_regs fetched differently */
|
||||
return bpf_get_stackid((unsigned long) regs, (unsigned long) map,
|
||||
flags, 0, 0);
|
||||
ret = bpf_get_stackid((unsigned long) regs, (unsigned long) map,
|
||||
flags, 0, 0);
|
||||
put_bpf_raw_tp_regs();
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct bpf_func_proto bpf_get_stackid_proto_raw_tp = {
|
||||
|
@ -868,11 +930,17 @@ static const struct bpf_func_proto bpf_get_stackid_proto_raw_tp = {
|
|||
BPF_CALL_4(bpf_get_stack_raw_tp, struct bpf_raw_tracepoint_args *, args,
|
||||
void *, buf, u32, size, u64, flags)
|
||||
{
|
||||
struct pt_regs *regs = this_cpu_ptr(&bpf_raw_tp_regs);
|
||||
struct pt_regs *regs = get_bpf_raw_tp_regs();
|
||||
int ret;
|
||||
|
||||
if (IS_ERR(regs))
|
||||
return PTR_ERR(regs);
|
||||
|
||||
perf_fetch_caller_regs(regs);
|
||||
return bpf_get_stack((unsigned long) regs, (unsigned long) buf,
|
||||
(unsigned long) size, flags, 0);
|
||||
ret = bpf_get_stack((unsigned long) regs, (unsigned long) buf,
|
||||
(unsigned long) size, flags, 0);
|
||||
put_bpf_raw_tp_regs();
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct bpf_func_proto bpf_get_stack_proto_raw_tp = {
|
||||
|
|
|
@ -426,9 +426,11 @@ int ax25_rt_autobind(ax25_cb *ax25, ax25_address *addr)
|
|||
}
|
||||
|
||||
if (ax25->sk != NULL) {
|
||||
local_bh_disable();
|
||||
bh_lock_sock(ax25->sk);
|
||||
sock_reset_flag(ax25->sk, SOCK_ZAPPED);
|
||||
bh_unlock_sock(ax25->sk);
|
||||
local_bh_enable();
|
||||
}
|
||||
|
||||
put:
|
||||
|
|
|
@ -99,6 +99,7 @@ EXPORT_SYMBOL(can_ioctl);
|
|||
static void can_sock_destruct(struct sock *sk)
|
||||
{
|
||||
skb_queue_purge(&sk->sk_receive_queue);
|
||||
skb_queue_purge(&sk->sk_error_queue);
|
||||
}
|
||||
|
||||
static const struct can_proto *can_get_proto(int protocol)
|
||||
|
@ -952,6 +953,8 @@ static struct pernet_operations can_pernet_ops __read_mostly = {
|
|||
|
||||
static __init int can_init(void)
|
||||
{
|
||||
int err;
|
||||
|
||||
/* check for correct padding to be able to use the structs similarly */
|
||||
BUILD_BUG_ON(offsetof(struct can_frame, can_dlc) !=
|
||||
offsetof(struct canfd_frame, len) ||
|
||||
|
@ -965,15 +968,31 @@ static __init int can_init(void)
|
|||
if (!rcv_cache)
|
||||
return -ENOMEM;
|
||||
|
||||
register_pernet_subsys(&can_pernet_ops);
|
||||
err = register_pernet_subsys(&can_pernet_ops);
|
||||
if (err)
|
||||
goto out_pernet;
|
||||
|
||||
/* protocol register */
|
||||
sock_register(&can_family_ops);
|
||||
register_netdevice_notifier(&can_netdev_notifier);
|
||||
err = sock_register(&can_family_ops);
|
||||
if (err)
|
||||
goto out_sock;
|
||||
err = register_netdevice_notifier(&can_netdev_notifier);
|
||||
if (err)
|
||||
goto out_notifier;
|
||||
|
||||
dev_add_pack(&can_packet);
|
||||
dev_add_pack(&canfd_packet);
|
||||
|
||||
return 0;
|
||||
|
||||
out_notifier:
|
||||
sock_unregister(PF_CAN);
|
||||
out_sock:
|
||||
unregister_pernet_subsys(&can_pernet_ops);
|
||||
out_pernet:
|
||||
kmem_cache_destroy(rcv_cache);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static __exit void can_exit(void)
|
||||
|
|
|
@ -633,7 +633,8 @@ static struct bpf_map *bpf_sk_storage_map_alloc(union bpf_attr *attr)
|
|||
return ERR_PTR(-ENOMEM);
|
||||
bpf_map_init_from_attr(&smap->map, attr);
|
||||
|
||||
smap->bucket_log = ilog2(roundup_pow_of_two(num_possible_cpus()));
|
||||
/* Use at least 2 buckets, select_bucket() is undefined behavior with 1 bucket */
|
||||
smap->bucket_log = max_t(u32, 1, ilog2(roundup_pow_of_two(num_possible_cpus())));
|
||||
nbuckets = 1U << smap->bucket_log;
|
||||
smap->buckets = kvcalloc(sizeof(*smap->buckets), nbuckets,
|
||||
GFP_USER | __GFP_NOWARN);
|
||||
|
|
|
@ -4923,8 +4923,36 @@ skip_classify:
|
|||
}
|
||||
|
||||
if (unlikely(skb_vlan_tag_present(skb))) {
|
||||
if (skb_vlan_tag_get_id(skb))
|
||||
check_vlan_id:
|
||||
if (skb_vlan_tag_get_id(skb)) {
|
||||
/* Vlan id is non 0 and vlan_do_receive() above couldn't
|
||||
* find vlan device.
|
||||
*/
|
||||
skb->pkt_type = PACKET_OTHERHOST;
|
||||
} else if (skb->protocol == cpu_to_be16(ETH_P_8021Q) ||
|
||||
skb->protocol == cpu_to_be16(ETH_P_8021AD)) {
|
||||
/* Outer header is 802.1P with vlan 0, inner header is
|
||||
* 802.1Q or 802.1AD and vlan_do_receive() above could
|
||||
* not find vlan dev for vlan id 0.
|
||||
*/
|
||||
__vlan_hwaccel_clear_tag(skb);
|
||||
skb = skb_vlan_untag(skb);
|
||||
if (unlikely(!skb))
|
||||
goto out;
|
||||
if (vlan_do_receive(&skb))
|
||||
/* After stripping off 802.1P header with vlan 0
|
||||
* vlan dev is found for inner header.
|
||||
*/
|
||||
goto another_round;
|
||||
else if (unlikely(!skb))
|
||||
goto out;
|
||||
else
|
||||
/* We have stripped outer 802.1P vlan 0 header.
|
||||
* But could not find vlan dev.
|
||||
* check again for vlan id to set OTHERHOST.
|
||||
*/
|
||||
goto check_vlan_id;
|
||||
}
|
||||
/* Note: we might in the future use prio bits
|
||||
* and set skb->priority like in vlan_do_receive()
|
||||
* For the time being, just ignore Priority Code Point
|
||||
|
|
|
@ -3020,6 +3020,11 @@ ethtool_rx_flow_rule_create(const struct ethtool_rx_flow_spec_input *input)
|
|||
match->mask.vlan.vlan_id =
|
||||
ntohs(ext_m_spec->vlan_tci) & 0x0fff;
|
||||
|
||||
match->key.vlan.vlan_dei =
|
||||
!!(ext_h_spec->vlan_tci & htons(0x1000));
|
||||
match->mask.vlan.vlan_dei =
|
||||
!!(ext_m_spec->vlan_tci & htons(0x1000));
|
||||
|
||||
match->key.vlan.vlan_priority =
|
||||
(ntohs(ext_h_spec->vlan_tci) & 0xe000) >> 13;
|
||||
match->mask.vlan.vlan_priority =
|
||||
|
|
|
@ -5300,7 +5300,13 @@ __bpf_skc_lookup(struct sk_buff *skb, struct bpf_sock_tuple *tuple, u32 len,
|
|||
struct net *net;
|
||||
int sdif;
|
||||
|
||||
family = len == sizeof(tuple->ipv4) ? AF_INET : AF_INET6;
|
||||
if (len == sizeof(tuple->ipv4))
|
||||
family = AF_INET;
|
||||
else if (len == sizeof(tuple->ipv6))
|
||||
family = AF_INET6;
|
||||
else
|
||||
return NULL;
|
||||
|
||||
if (unlikely(family == AF_UNSPEC || flags ||
|
||||
!((s32)netns_id < 0 || netns_id <= S32_MAX)))
|
||||
goto out;
|
||||
|
@ -5333,8 +5339,14 @@ __bpf_sk_lookup(struct sk_buff *skb, struct bpf_sock_tuple *tuple, u32 len,
|
|||
struct sock *sk = __bpf_skc_lookup(skb, tuple, len, caller_net,
|
||||
ifindex, proto, netns_id, flags);
|
||||
|
||||
if (sk)
|
||||
if (sk) {
|
||||
sk = sk_to_full_sk(sk);
|
||||
if (!sk_fullsock(sk)) {
|
||||
if (!sock_flag(sk, SOCK_RCU_FREE))
|
||||
sock_gen_put(sk);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return sk;
|
||||
}
|
||||
|
@ -5365,8 +5377,14 @@ bpf_sk_lookup(struct sk_buff *skb, struct bpf_sock_tuple *tuple, u32 len,
|
|||
struct sock *sk = bpf_skc_lookup(skb, tuple, len, proto, netns_id,
|
||||
flags);
|
||||
|
||||
if (sk)
|
||||
if (sk) {
|
||||
sk = sk_to_full_sk(sk);
|
||||
if (!sk_fullsock(sk)) {
|
||||
if (!sock_flag(sk, SOCK_RCU_FREE))
|
||||
sock_gen_put(sk);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return sk;
|
||||
}
|
||||
|
@ -6726,6 +6744,7 @@ static bool sock_addr_is_valid_access(int off, int size,
|
|||
case BPF_CGROUP_INET4_BIND:
|
||||
case BPF_CGROUP_INET4_CONNECT:
|
||||
case BPF_CGROUP_UDP4_SENDMSG:
|
||||
case BPF_CGROUP_UDP4_RECVMSG:
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
|
@ -6736,6 +6755,7 @@ static bool sock_addr_is_valid_access(int off, int size,
|
|||
case BPF_CGROUP_INET6_BIND:
|
||||
case BPF_CGROUP_INET6_CONNECT:
|
||||
case BPF_CGROUP_UDP6_SENDMSG:
|
||||
case BPF_CGROUP_UDP6_RECVMSG:
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
|
|
|
@ -3203,6 +3203,7 @@ static void *neigh_get_idx_any(struct seq_file *seq, loff_t *pos)
|
|||
}
|
||||
|
||||
void *neigh_seq_start(struct seq_file *seq, loff_t *pos, struct neigh_table *tbl, unsigned int neigh_seq_flags)
|
||||
__acquires(tbl->lock)
|
||||
__acquires(rcu_bh)
|
||||
{
|
||||
struct neigh_seq_state *state = seq->private;
|
||||
|
@ -3213,6 +3214,7 @@ void *neigh_seq_start(struct seq_file *seq, loff_t *pos, struct neigh_table *tbl
|
|||
|
||||
rcu_read_lock_bh();
|
||||
state->nht = rcu_dereference_bh(tbl->nht);
|
||||
read_lock(&tbl->lock);
|
||||
|
||||
return *pos ? neigh_get_idx_any(seq, pos) : SEQ_START_TOKEN;
|
||||
}
|
||||
|
@ -3246,8 +3248,13 @@ out:
|
|||
EXPORT_SYMBOL(neigh_seq_next);
|
||||
|
||||
void neigh_seq_stop(struct seq_file *seq, void *v)
|
||||
__releases(tbl->lock)
|
||||
__releases(rcu_bh)
|
||||
{
|
||||
struct neigh_seq_state *state = seq->private;
|
||||
struct neigh_table *tbl = state->tbl;
|
||||
|
||||
read_unlock(&tbl->lock);
|
||||
rcu_read_unlock_bh();
|
||||
}
|
||||
EXPORT_SYMBOL(neigh_seq_stop);
|
||||
|
|
|
@ -2337,6 +2337,7 @@ do_frag_list:
|
|||
kv.iov_base = skb->data + offset;
|
||||
kv.iov_len = slen;
|
||||
memset(&msg, 0, sizeof(msg));
|
||||
msg.msg_flags = MSG_DONTWAIT;
|
||||
|
||||
ret = kernel_sendmsg_locked(sk, &msg, &kv, 1, slen);
|
||||
if (ret <= 0)
|
||||
|
|
|
@ -1850,6 +1850,9 @@ struct sock *sk_clone_lock(const struct sock *sk, const gfp_t priority)
|
|||
goto out;
|
||||
}
|
||||
RCU_INIT_POINTER(newsk->sk_reuseport_cb, NULL);
|
||||
#ifdef CONFIG_BPF_SYSCALL
|
||||
RCU_INIT_POINTER(newsk->sk_bpf_storage, NULL);
|
||||
#endif
|
||||
|
||||
newsk->sk_err = 0;
|
||||
newsk->sk_err_soft = 0;
|
||||
|
@ -2320,6 +2323,7 @@ static void sk_leave_memory_pressure(struct sock *sk)
|
|||
|
||||
/* On 32bit arches, an skb frag is limited to 2^15 */
|
||||
#define SKB_FRAG_PAGE_ORDER get_order(32768)
|
||||
DEFINE_STATIC_KEY_FALSE(net_high_order_alloc_disable_key);
|
||||
|
||||
/**
|
||||
* skb_page_frag_refill - check that a page_frag contains enough room
|
||||
|
@ -2344,7 +2348,8 @@ bool skb_page_frag_refill(unsigned int sz, struct page_frag *pfrag, gfp_t gfp)
|
|||
}
|
||||
|
||||
pfrag->offset = 0;
|
||||
if (SKB_FRAG_PAGE_ORDER) {
|
||||
if (SKB_FRAG_PAGE_ORDER &&
|
||||
!static_branch_unlikely(&net_high_order_alloc_disable_key)) {
|
||||
/* Avoid direct reclaim but allow kswapd to wake */
|
||||
pfrag->page = alloc_pages((gfp & ~__GFP_DIRECT_RECLAIM) |
|
||||
__GFP_COMP | __GFP_NOWARN |
|
||||
|
|
|
@ -562,6 +562,13 @@ static struct ctl_table net_core_table[] = {
|
|||
.extra1 = &zero,
|
||||
.extra2 = &two,
|
||||
},
|
||||
{
|
||||
.procname = "high_order_alloc_disable",
|
||||
.data = &net_high_order_alloc_disable_key.key,
|
||||
.maxlen = sizeof(net_high_order_alloc_disable_key),
|
||||
.mode = 0644,
|
||||
.proc_handler = proc_do_static_key,
|
||||
},
|
||||
{ }
|
||||
};
|
||||
|
||||
|
|
|
@ -964,7 +964,7 @@ static int fib_check_nh_v4_gw(struct net *net, struct fib_nh *nh, u32 table,
|
|||
{
|
||||
struct net_device *dev;
|
||||
struct fib_result res;
|
||||
int err;
|
||||
int err = 0;
|
||||
|
||||
if (nh->fib_nh_flags & RTNH_F_ONLINK) {
|
||||
unsigned int addr_type;
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue