Merge tag 'net-next-5.10' of git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-next
Pull networking updates from Jakub Kicinski: - Add redirect_neigh() BPF packet redirect helper, allowing to limit stack traversal in common container configs and improving TCP back-pressure. Daniel reports ~10Gbps => ~15Gbps single stream TCP performance gain. - Expand netlink policy support and improve policy export to user space. (Ge)netlink core performs request validation according to declared policies. Expand the expressiveness of those policies (min/max length and bitmasks). Allow dumping policies for particular commands. This is used for feature discovery by user space (instead of kernel version parsing or trial and error). - Support IGMPv3/MLDv2 multicast listener discovery protocols in bridge. - Allow more than 255 IPv4 multicast interfaces. - Add support for Type of Service (ToS) reflection in SYN/SYN-ACK packets of TCPv6. - In Multi-patch TCP (MPTCP) support concurrent transmission of data on multiple subflows in a load balancing scenario. Enhance advertising addresses via the RM_ADDR/ADD_ADDR options. - Support SMC-Dv2 version of SMC, which enables multi-subnet deployments. - Allow more calls to same peer in RxRPC. - Support two new Controller Area Network (CAN) protocols - CAN-FD and ISO 15765-2:2016. - Add xfrm/IPsec compat layer, solving the 32bit user space on 64bit kernel problem. - Add TC actions for implementing MPLS L2 VPNs. - Improve nexthop code - e.g. handle various corner cases when nexthop objects are removed from groups better, skip unnecessary notifications and make it easier to offload nexthops into HW by converting to a blocking notifier. - Support adding and consuming TCP header options by BPF programs, opening the doors for easy experimental and deployment-specific TCP option use. - Reorganize TCP congestion control (CC) initialization to simplify life of TCP CC implemented in BPF. - Add support for shipping BPF programs with the kernel and loading them early on boot via the User Mode Driver mechanism, hence reusing all the user space infra we have. - Support sleepable BPF programs, initially targeting LSM and tracing. - Add bpf_d_path() helper for returning full path for given 'struct path'. - Make bpf_tail_call compatible with bpf-to-bpf calls. - Allow BPF programs to call map_update_elem on sockmaps. - Add BPF Type Format (BTF) support for type and enum discovery, as well as support for using BTF within the kernel itself (current use is for pretty printing structures). - Support listing and getting information about bpf_links via the bpf syscall. - Enhance kernel interfaces around NIC firmware update. Allow specifying overwrite mask to control if settings etc. are reset during update; report expected max time operation may take to users; support firmware activation without machine reboot incl. limits of how much impact reset may have (e.g. dropping link or not). - Extend ethtool configuration interface to report IEEE-standard counters, to limit the need for per-vendor logic in user space. - Adopt or extend devlink use for debug, monitoring, fw update in many drivers (dsa loop, ice, ionic, sja1105, qed, mlxsw, mv88e6xxx, dpaa2-eth). - In mlxsw expose critical and emergency SFP module temperature alarms. Refactor port buffer handling to make the defaults more suitable and support setting these values explicitly via the DCBNL interface. - Add XDP support for Intel's igb driver. - Support offloading TC flower classification and filtering rules to mscc_ocelot switches. - Add PTP support for Marvell Octeontx2 and PP2.2 hardware, as well as fixed interval period pulse generator and one-step timestamping in dpaa-eth. - Add support for various auth offloads in WiFi APs, e.g. SAE (WPA3) offload. - Add Lynx PHY/PCS MDIO module, and convert various drivers which have this HW to use it. Convert mvpp2 to split PCS. - Support Marvell Prestera 98DX3255 24-port switch ASICs, as well as 7-port Mediatek MT7531 IP. - Add initial support for QCA6390 and IPQ6018 in ath11k WiFi driver, and wcn3680 support in wcn36xx. - Improve performance for packets which don't require much offloads on recent Mellanox NICs by 20% by making multiple packets share a descriptor entry. - Move chelsio inline crypto drivers (for TLS and IPsec) from the crypto subtree to drivers/net. Move MDIO drivers out of the phy directory. - Clean up a lot of W=1 warnings, reportedly the actively developed subsections of networking drivers should now build W=1 warning free. - Make sure drivers don't use in_interrupt() to dynamically adapt their code. Convert tasklets to use new tasklet_setup API (sadly this conversion is not yet complete). * tag 'net-next-5.10' of git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-next: (2583 commits) Revert "bpfilter: Fix build error with CONFIG_BPFILTER_UMH" net, sockmap: Don't call bpf_prog_put() on NULL pointer bpf, selftest: Fix flaky tcp_hdr_options test when adding addr to lo bpf, sockmap: Add locking annotations to iterator netfilter: nftables: allow re-computing sctp CRC-32C in 'payload' statements net: fix pos incrementment in ipv6_route_seq_next net/smc: fix invalid return code in smcd_new_buf_create() net/smc: fix valid DMBE buffer sizes net/smc: fix use-after-free of delayed events bpfilter: Fix build error with CONFIG_BPFILTER_UMH cxgb4/ch_ipsec: Replace the module name to ch_ipsec from chcr net: sched: Fix suspicious RCU usage while accessing tcf_tunnel_info bpf: Fix register equivalence tracking. rxrpc: Fix loss of final ack on shutdown rxrpc: Fix bundle counting for exclusive connections netfilter: restore NF_INET_NUMHOOKS ibmveth: Identify ingress large send packets. ibmveth: Switch order of ibmveth_helper calls. cxgb4: handle 4-tuple PEDIT to NAT mode translation selftests: Add VRF route leaking tests ...
This commit is contained in:
4
CREDITS
4
CREDITS
@@ -191,6 +191,10 @@ N: Krishna Balasubramanian
|
||||
E: balasub@cis.ohio-state.edu
|
||||
D: Wrote SYS V IPC (part of standard kernel since 0.99.10)
|
||||
|
||||
B: Robert Baldyga
|
||||
E: r.baldyga@hackerion.com
|
||||
D: Samsung S3FWRN5 NCI NFC Controller
|
||||
|
||||
N: Chris Ball
|
||||
E: chris@printf.net
|
||||
D: Former maintainer of the MMC/SD/SDIO subsystem.
|
||||
|
@@ -1349,6 +1349,11 @@
|
||||
Format: <interval>,<probability>,<space>,<times>
|
||||
See also Documentation/fault-injection/.
|
||||
|
||||
fb_tunnels= [NET]
|
||||
Format: { initns | none }
|
||||
See Documentation/admin-guide/sysctl/net.rst for
|
||||
fb_tunnels_only_for_init_ns
|
||||
|
||||
floppy= [HW]
|
||||
See Documentation/admin-guide/blockdev/floppy.rst.
|
||||
|
||||
|
@@ -300,7 +300,6 @@ Note:
|
||||
0: 0 1 2 3 4 5 6 7
|
||||
RSS hash key:
|
||||
84:50:f4:00:a8:15:d1:a7:e9:7f:1d:60:35:c7:47:25:42:97:74:ca:56:bb:b6:a1:d8:43:e3:c9:0c:fd:17:55:c2:3a:4d:69:ed:f1:42:89
|
||||
|
||||
netdev_tstamp_prequeue
|
||||
----------------------
|
||||
|
||||
@@ -321,11 +320,20 @@ fb_tunnels_only_for_init_net
|
||||
----------------------------
|
||||
|
||||
Controls if fallback tunnels (like tunl0, gre0, gretap0, erspan0,
|
||||
sit0, ip6tnl0, ip6gre0) are automatically created when a new
|
||||
network namespace is created, if corresponding tunnel is present
|
||||
in initial network namespace.
|
||||
If set to 1, these devices are not automatically created, and
|
||||
user space is responsible for creating them if needed.
|
||||
sit0, ip6tnl0, ip6gre0) are automatically created. There are 3 possibilities
|
||||
(a) value = 0; respective fallback tunnels are created when module is
|
||||
loaded in every net namespaces (backward compatible behavior).
|
||||
(b) value = 1; [kcmd value: initns] respective fallback tunnels are
|
||||
created only in init net namespace and every other net namespace will
|
||||
not have them.
|
||||
(c) value = 2; [kcmd value: none] fallback tunnels are not created
|
||||
when a module is loaded in any of the net namespace. Setting value to
|
||||
"2" is pointless after boot if these modules are built-in, so there is
|
||||
a kernel command-line option that can change this default. Please refer to
|
||||
Documentation/admin-guide/kernel-parameters.txt for additional details.
|
||||
|
||||
Not creating fallback tunnels gives control to userspace to create
|
||||
whatever is needed only and avoid creating devices which are redundant.
|
||||
|
||||
Default : 0 (for compatibility reasons)
|
||||
|
||||
|
@@ -60,13 +60,13 @@ Q: Where can I find patches currently under discussion for BPF subsystem?
|
||||
A: All patches that are Cc'ed to netdev are queued for review under netdev
|
||||
patchwork project:
|
||||
|
||||
http://patchwork.ozlabs.org/project/netdev/list/
|
||||
https://patchwork.kernel.org/project/netdevbpf/list/
|
||||
|
||||
Those patches which target BPF, are assigned to a 'bpf' delegate for
|
||||
further processing from BPF maintainers. The current queue with
|
||||
patches under review can be found at:
|
||||
|
||||
https://patchwork.ozlabs.org/project/netdev/list/?delegate=77147
|
||||
https://patchwork.kernel.org/project/netdevbpf/list/?delegate=121173
|
||||
|
||||
Once the patches have been reviewed by the BPF community as a whole
|
||||
and approved by the BPF maintainers, their status in patchwork will be
|
||||
@@ -149,7 +149,7 @@ In case the patch or patch series has to be reworked and sent out
|
||||
again in a second or later revision, it is also required to add a
|
||||
version number (``v2``, ``v3``, ...) into the subject prefix::
|
||||
|
||||
git format-patch --subject-prefix='PATCH net-next v2' start..finish
|
||||
git format-patch --subject-prefix='PATCH bpf-next v2' start..finish
|
||||
|
||||
When changes have been requested to the patch series, always send the
|
||||
whole patch series again with the feedback incorporated (never send
|
||||
@@ -479,12 +479,13 @@ LLVM's static compiler lists the supported targets through
|
||||
|
||||
$ llc --version
|
||||
LLVM (http://llvm.org/):
|
||||
LLVM version 6.0.0svn
|
||||
LLVM version 10.0.0
|
||||
Optimized build.
|
||||
Default target: x86_64-unknown-linux-gnu
|
||||
Host CPU: skylake
|
||||
|
||||
Registered Targets:
|
||||
aarch64 - AArch64 (little endian)
|
||||
bpf - BPF (host endian)
|
||||
bpfeb - BPF (big endian)
|
||||
bpfel - BPF (little endian)
|
||||
@@ -517,6 +518,10 @@ from the git repositories::
|
||||
The built binaries can then be found in the build/bin/ directory, where
|
||||
you can point the PATH variable to.
|
||||
|
||||
Set ``-DLLVM_TARGETS_TO_BUILD`` equal to the target you wish to build, you
|
||||
will find a full list of targets within the llvm-project/llvm/lib/Target
|
||||
directory.
|
||||
|
||||
Q: Reporting LLVM BPF issues
|
||||
----------------------------
|
||||
Q: Should I notify BPF kernel maintainers about issues in LLVM's BPF code
|
||||
|
@@ -724,6 +724,31 @@ want to define unused entry in BTF_ID_LIST, like::
|
||||
BTF_ID_UNUSED
|
||||
BTF_ID(struct, task_struct)
|
||||
|
||||
The ``BTF_SET_START/END`` macros pair defines sorted list of BTF ID values
|
||||
and their count, with following syntax::
|
||||
|
||||
BTF_SET_START(set)
|
||||
BTF_ID(type1, name1)
|
||||
BTF_ID(type2, name2)
|
||||
BTF_SET_END(set)
|
||||
|
||||
resulting in following layout in .BTF_ids section::
|
||||
|
||||
__BTF_ID__set__set:
|
||||
.zero 4
|
||||
__BTF_ID__type1__name1__3:
|
||||
.zero 4
|
||||
__BTF_ID__type2__name2__4:
|
||||
.zero 4
|
||||
|
||||
The ``struct btf_id_set set;`` variable is defined to access the list.
|
||||
|
||||
The ``typeX`` name can be one of following::
|
||||
|
||||
struct, union, typedef, func
|
||||
|
||||
and is used as a filter when resolving the BTF ID value.
|
||||
|
||||
All the BTF ID lists and sets are compiled in the .BTF_ids section and
|
||||
resolved during the linking phase of kernel build by ``resolve_btfids`` tool.
|
||||
|
||||
|
@@ -52,6 +52,7 @@ Program types
|
||||
prog_cgroup_sysctl
|
||||
prog_flow_dissector
|
||||
bpf_lsm
|
||||
prog_sk_lookup
|
||||
|
||||
|
||||
Map types
|
||||
|
98
Documentation/bpf/prog_sk_lookup.rst
Normal file
98
Documentation/bpf/prog_sk_lookup.rst
Normal file
@@ -0,0 +1,98 @@
|
||||
.. SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
|
||||
|
||||
=====================
|
||||
BPF sk_lookup program
|
||||
=====================
|
||||
|
||||
BPF sk_lookup program type (``BPF_PROG_TYPE_SK_LOOKUP``) introduces programmability
|
||||
into the socket lookup performed by the transport layer when a packet is to be
|
||||
delivered locally.
|
||||
|
||||
When invoked BPF sk_lookup program can select a socket that will receive the
|
||||
incoming packet by calling the ``bpf_sk_assign()`` BPF helper function.
|
||||
|
||||
Hooks for a common attach point (``BPF_SK_LOOKUP``) exist for both TCP and UDP.
|
||||
|
||||
Motivation
|
||||
==========
|
||||
|
||||
BPF sk_lookup program type was introduced to address setup scenarios where
|
||||
binding sockets to an address with ``bind()`` socket call is impractical, such
|
||||
as:
|
||||
|
||||
1. receiving connections on a range of IP addresses, e.g. 192.0.2.0/24, when
|
||||
binding to a wildcard address ``INADRR_ANY`` is not possible due to a port
|
||||
conflict,
|
||||
2. receiving connections on all or a wide range of ports, i.e. an L7 proxy use
|
||||
case.
|
||||
|
||||
Such setups would require creating and ``bind()``'ing one socket to each of the
|
||||
IP address/port in the range, leading to resource consumption and potential
|
||||
latency spikes during socket lookup.
|
||||
|
||||
Attachment
|
||||
==========
|
||||
|
||||
BPF sk_lookup program can be attached to a network namespace with
|
||||
``bpf(BPF_LINK_CREATE, ...)`` syscall using the ``BPF_SK_LOOKUP`` attach type and a
|
||||
netns FD as attachment ``target_fd``.
|
||||
|
||||
Multiple programs can be attached to one network namespace. Programs will be
|
||||
invoked in the same order as they were attached.
|
||||
|
||||
Hooks
|
||||
=====
|
||||
|
||||
The attached BPF sk_lookup programs run whenever the transport layer needs to
|
||||
find a listening (TCP) or an unconnected (UDP) socket for an incoming packet.
|
||||
|
||||
Incoming traffic to established (TCP) and connected (UDP) sockets is delivered
|
||||
as usual without triggering the BPF sk_lookup hook.
|
||||
|
||||
The attached BPF programs must return with either ``SK_PASS`` or ``SK_DROP``
|
||||
verdict code. As for other BPF program types that are network filters,
|
||||
``SK_PASS`` signifies that the socket lookup should continue on to regular
|
||||
hashtable-based lookup, while ``SK_DROP`` causes the transport layer to drop the
|
||||
packet.
|
||||
|
||||
A BPF sk_lookup program can also select a socket to receive the packet by
|
||||
calling ``bpf_sk_assign()`` BPF helper. Typically, the program looks up a socket
|
||||
in a map holding sockets, such as ``SOCKMAP`` or ``SOCKHASH``, and passes a
|
||||
``struct bpf_sock *`` to ``bpf_sk_assign()`` helper to record the
|
||||
selection. Selecting a socket only takes effect if the program has terminated
|
||||
with ``SK_PASS`` code.
|
||||
|
||||
When multiple programs are attached, the end result is determined from return
|
||||
codes of all the programs according to the following rules:
|
||||
|
||||
1. If any program returned ``SK_PASS`` and selected a valid socket, the socket
|
||||
is used as the result of the socket lookup.
|
||||
2. If more than one program returned ``SK_PASS`` and selected a socket, the last
|
||||
selection takes effect.
|
||||
3. If any program returned ``SK_DROP``, and no program returned ``SK_PASS`` and
|
||||
selected a socket, socket lookup fails.
|
||||
4. If all programs returned ``SK_PASS`` and none of them selected a socket,
|
||||
socket lookup continues on.
|
||||
|
||||
API
|
||||
===
|
||||
|
||||
In its context, an instance of ``struct bpf_sk_lookup``, BPF sk_lookup program
|
||||
receives information about the packet that triggered the socket lookup. Namely:
|
||||
|
||||
* IP version (``AF_INET`` or ``AF_INET6``),
|
||||
* L4 protocol identifier (``IPPROTO_TCP`` or ``IPPROTO_UDP``),
|
||||
* source and destination IP address,
|
||||
* source and destination L4 port,
|
||||
* the socket that has been selected with ``bpf_sk_assign()``.
|
||||
|
||||
Refer to ``struct bpf_sk_lookup`` declaration in ``linux/bpf.h`` user API
|
||||
header, and `bpf-helpers(7)
|
||||
<https://man7.org/linux/man-pages/man7/bpf-helpers.7.html>`_ man-page section
|
||||
for ``bpf_sk_assign()`` for details.
|
||||
|
||||
Example
|
||||
=======
|
||||
|
||||
See ``tools/testing/selftests/bpf/prog_tests/sk_lookup.c`` for the reference
|
||||
implementation.
|
@@ -50,6 +50,13 @@ Optional properties:
|
||||
- reset-names: If the "reset" property is specified, this property should have
|
||||
the value "switch" to denote the switch reset line.
|
||||
|
||||
- clocks: when provided, the first phandle is to the switch's main clock and
|
||||
is valid for both BCM7445 and BCM7278. The second phandle is only applicable
|
||||
to BCM7445 and is to support dividing the switch core clock.
|
||||
|
||||
- clock-names: when provided, the first phandle must be "sw_switch", and the
|
||||
second must be named "sw_switch_mdiv".
|
||||
|
||||
Port subnodes:
|
||||
|
||||
Optional properties:
|
||||
|
@@ -20,6 +20,11 @@ Optional properties:
|
||||
- systemport,num-tier1-arb: number of tier 1 arbiters, an integer
|
||||
- systemport,num-txq: number of HW transmit queues, an integer
|
||||
- systemport,num-rxq: number of HW receive queues, an integer
|
||||
- clocks: When provided, must be two phandles to the functional clocks nodes of
|
||||
the SYSTEMPORT block. The first phandle is the main SYSTEMPORT clock used
|
||||
during normal operation, while the second phandle is the Wake-on-LAN clock.
|
||||
- clock-names: When provided, names of the functional clock phandles, first
|
||||
name should be "sw_sysport" and second should be "sw_sysportwol".
|
||||
|
||||
Example:
|
||||
ethernet@f04a0000 {
|
||||
|
@@ -4,6 +4,12 @@ Required properties:
|
||||
|
||||
- compatible : Should be "fsl,<processor>-flexcan"
|
||||
|
||||
where <processor> is imx8qm, imx6q, imx28, imx53, imx35, imx25, p1010,
|
||||
vf610, ls1021ar2, lx2160ar1, ls1028ar1.
|
||||
|
||||
The ls1028ar1 must be followed by lx2160ar1, e.g.
|
||||
- "fsl,ls1028ar1-flexcan", "fsl,lx2160ar1-flexcan"
|
||||
|
||||
An implementation should also claim any of the following compatibles
|
||||
that it is fully backwards compatible with:
|
||||
|
||||
@@ -25,12 +31,10 @@ Optional properties:
|
||||
endian.
|
||||
|
||||
- fsl,stop-mode: register bits of stop mode control, the format is
|
||||
<&gpr req_gpr req_bit ack_gpr ack_bit>.
|
||||
<&gpr req_gpr req_bit>.
|
||||
gpr is the phandle to general purpose register node.
|
||||
req_gpr is the gpr register offset of CAN stop request.
|
||||
req_bit is the bit offset of CAN stop request.
|
||||
ack_gpr is the gpr register offset of CAN stop acknowledge.
|
||||
ack_bit is the bit offset of CAN stop acknowledge.
|
||||
|
||||
- fsl,clk-source: Select the clock source to the CAN Protocol Engine (PE).
|
||||
It's SoC Implementation dependent. Refer to RM for detailed
|
||||
|
@@ -12,6 +12,9 @@ Required properties:
|
||||
Optional properties:
|
||||
- vdd-supply: Regulator that powers the CAN controller.
|
||||
- xceiver-supply: Regulator that powers the CAN transceiver.
|
||||
- gpio-controller: Indicates this device is a GPIO controller.
|
||||
- #gpio-cells: Should be two. The first cell is the pin number and
|
||||
the second cell is used to specify the gpio polarity.
|
||||
|
||||
Example:
|
||||
can0: can@1 {
|
||||
@@ -19,7 +22,9 @@ Example:
|
||||
reg = <1>;
|
||||
clocks = <&clk24m>;
|
||||
interrupt-parent = <&gpio4>;
|
||||
interrupts = <13 0x2>;
|
||||
interrupts = <13 IRQ_TYPE_LEVEL_LOW>;
|
||||
vdd-supply = <®5v0>;
|
||||
xceiver-supply = <®5v0>;
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
};
|
||||
|
@@ -0,0 +1,79 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/net/can/microchip,mcp251xfd.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title:
|
||||
Microchip MCP2517FD and MCP2518FD stand-alone CAN controller device tree
|
||||
bindings
|
||||
|
||||
maintainers:
|
||||
- Marc Kleine-Budde <mkl@pengutronix.de>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
oneOf:
|
||||
- const: microchip,mcp2517fd
|
||||
description: for MCP2517FD
|
||||
- const: microchip,mcp2518fd
|
||||
description: for MCP2518FD
|
||||
- const: microchip,mcp251xfd
|
||||
description: to autodetect chip variant
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
maxItems: 1
|
||||
|
||||
vdd-supply:
|
||||
description: Regulator that powers the CAN controller.
|
||||
|
||||
xceiver-supply:
|
||||
description: Regulator that powers the CAN transceiver.
|
||||
|
||||
microchip,rx-int-gpios:
|
||||
description:
|
||||
GPIO phandle of GPIO connected to to INT1 pin of the MCP251XFD, which
|
||||
signals a pending RX interrupt.
|
||||
maxItems: 1
|
||||
|
||||
spi-max-frequency:
|
||||
description:
|
||||
Must be half or less of "clocks" frequency.
|
||||
maximum: 20000000
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- interrupts
|
||||
- clocks
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
|
||||
spi0 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
can@0 {
|
||||
compatible = "microchip,mcp251xfd";
|
||||
reg = <0>;
|
||||
clocks = <&can0_osc>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&can0_pins>;
|
||||
spi-max-frequency = <20000000>;
|
||||
interrupts-extended = <&gpio 13 IRQ_TYPE_LEVEL_LOW>;
|
||||
microchip,rx-int-gpios = <&gpio 27 GPIO_ACTIVE_LOW>;
|
||||
vdd-supply = <®5v0>;
|
||||
xceiver-supply = <®5v0>;
|
||||
};
|
||||
};
|
@@ -2,13 +2,15 @@ Renesas R-Car CAN controller Device Tree Bindings
|
||||
-------------------------------------------------
|
||||
|
||||
Required properties:
|
||||
- compatible: "renesas,can-r8a7743" if CAN controller is a part of R8A7743 SoC.
|
||||
- compatible: "renesas,can-r8a7742" if CAN controller is a part of R8A7742 SoC.
|
||||
"renesas,can-r8a7743" if CAN controller is a part of R8A7743 SoC.
|
||||
"renesas,can-r8a7744" if CAN controller is a part of R8A7744 SoC.
|
||||
"renesas,can-r8a7745" if CAN controller is a part of R8A7745 SoC.
|
||||
"renesas,can-r8a77470" if CAN controller is a part of R8A77470 SoC.
|
||||
"renesas,can-r8a774a1" if CAN controller is a part of R8A774A1 SoC.
|
||||
"renesas,can-r8a774b1" if CAN controller is a part of R8A774B1 SoC.
|
||||
"renesas,can-r8a774c0" if CAN controller is a part of R8A774C0 SoC.
|
||||
"renesas,can-r8a774e1" if CAN controller is a part of R8A774E1 SoC.
|
||||
"renesas,can-r8a7778" if CAN controller is a part of R8A7778 SoC.
|
||||
"renesas,can-r8a7779" if CAN controller is a part of R8A7779 SoC.
|
||||
"renesas,can-r8a7790" if CAN controller is a part of R8A7790 SoC.
|
||||
@@ -37,8 +39,8 @@ Required properties:
|
||||
- pinctrl-0: pin control group to be used for this controller.
|
||||
- pinctrl-names: must be "default".
|
||||
|
||||
Required properties for R8A774A1, R8A774B1, R8A774C0, R8A7795, R8A7796,
|
||||
R8A77965, R8A77990, and R8A77995:
|
||||
Required properties for R8A774A1, R8A774B1, R8A774C0, R8A774E1, R8A7795,
|
||||
R8A7796, R8A77965, R8A77990, and R8A77995:
|
||||
For the denoted SoCs, "clkp2" can be CANFD clock. This is a div6 clock and can
|
||||
be used by both CAN and CAN FD controller at the same time. It needs to be
|
||||
scaled to maximum frequency if any of these controllers use it. This is done
|
||||
|
@@ -7,6 +7,7 @@ Required properties:
|
||||
- "renesas,r8a774a1-canfd" for R8A774A1 (RZ/G2M) compatible controller.
|
||||
- "renesas,r8a774b1-canfd" for R8A774B1 (RZ/G2N) compatible controller.
|
||||
- "renesas,r8a774c0-canfd" for R8A774C0 (RZ/G2E) compatible controller.
|
||||
- "renesas,r8a774e1-canfd" for R8A774E1 (RZ/G2H) compatible controller.
|
||||
- "renesas,r8a7795-canfd" for R8A7795 (R-Car H3) compatible controller.
|
||||
- "renesas,r8a7796-canfd" for R8A7796 (R-Car M3-W) compatible controller.
|
||||
- "renesas,r8a77965-canfd" for R8A77965 (R-Car M3-N) compatible controller.
|
||||
@@ -32,8 +33,8 @@ The name of the child nodes are "channel0" and "channel1" respectively. Each
|
||||
child node supports the "status" property only, which is used to
|
||||
enable/disable the respective channel.
|
||||
|
||||
Required properties for R8A774A1, R8A774B1, R8A774C0, R8A7795, R8A7796,
|
||||
R8A77965, R8A77990, and R8A77995:
|
||||
Required properties for R8A774A1, R8A774B1, R8A774C0, R8A774E1, R8A7795,
|
||||
R8A7796, R8A77965, R8A77990, and R8A77995:
|
||||
In the denoted SoCs, canfd clock is a div6 clock and can be used by both CAN
|
||||
and CAN FD controller at the same time. It needs to be scaled to maximum
|
||||
frequency if any of these controllers use it. This is done using the below
|
||||
|
@@ -95,7 +95,7 @@ Ethernet switch connected via MDIO to the host, CPU port wired to eth0:
|
||||
|
||||
fixed-link {
|
||||
speed = <1000>;
|
||||
duplex-full;
|
||||
full-duplex;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -104,8 +104,9 @@ Ethernet switch connected via MDIO to the host, CPU port wired to eth0:
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
switch0: ethernet-switch@30 {
|
||||
switch0: ethernet-switch@1e {
|
||||
compatible = "brcm,bcm53125";
|
||||
reg = <30>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
@@ -128,7 +129,7 @@ Ethernet switch connected via MDIO to the host, CPU port wired to eth0:
|
||||
label = "cable-modem";
|
||||
fixed-link {
|
||||
speed = <1000>;
|
||||
duplex-full;
|
||||
full-duplex;
|
||||
};
|
||||
phy-mode = "rgmii-txid";
|
||||
};
|
||||
@@ -138,7 +139,7 @@ Ethernet switch connected via MDIO to the host, CPU port wired to eth0:
|
||||
label = "cpu";
|
||||
fixed-link {
|
||||
speed = <1000>;
|
||||
duplex-full;
|
||||
full-duplex;
|
||||
};
|
||||
phy-mode = "rgmii-txid";
|
||||
ethernet = <ð0>;
|
||||
|
@@ -5,6 +5,7 @@ Required properties:
|
||||
|
||||
- compatible: may be compatible = "mediatek,mt7530"
|
||||
or compatible = "mediatek,mt7621"
|
||||
or compatible = "mediatek,mt7531"
|
||||
- #address-cells: Must be 1.
|
||||
- #size-cells: Must be 0.
|
||||
- mediatek,mcm: Boolean; if defined, indicates that either MT7530 is the part
|
||||
@@ -32,10 +33,14 @@ Required properties for the child nodes within ports container:
|
||||
|
||||
- reg: Port address described must be 6 for CPU port and from 0 to 5 for
|
||||
user ports.
|
||||
- phy-mode: String, must be either "trgmii" or "rgmii" for port labeled
|
||||
"cpu".
|
||||
- phy-mode: String, the following values are acceptable for port labeled
|
||||
"cpu":
|
||||
If compatible mediatek,mt7530 or mediatek,mt7621 is set,
|
||||
must be either "trgmii" or "rgmii"
|
||||
If compatible mediatek,mt7531 is set,
|
||||
must be either "sgmii", "1000base-x" or "2500base-x"
|
||||
|
||||
Port 5 of the switch is muxed between:
|
||||
Port 5 of mt7530 and mt7621 switch is muxed between:
|
||||
1. GMAC5: GMAC5 can interface with another external MAC or PHY.
|
||||
2. PHY of port 0 or port 4: PHY interfaces with an external MAC like 2nd GMAC
|
||||
of the SOC. Used in many setups where port 0/4 becomes the WAN port.
|
||||
|
@@ -120,6 +120,13 @@ properties:
|
||||
and is useful for determining certain configuration settings
|
||||
such as flow control thresholds.
|
||||
|
||||
rx-internal-delay-ps:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
description: |
|
||||
RGMII Receive Clock Delay defined in pico seconds.
|
||||
This is used for controllers that have configurable RX internal delays.
|
||||
If this property is present then the MAC applies the RX delay.
|
||||
|
||||
sfp:
|
||||
$ref: /schemas/types.yaml#definitions/phandle
|
||||
description:
|
||||
@@ -131,6 +138,13 @@ properties:
|
||||
The size of the controller\'s transmit fifo in bytes. This
|
||||
is used for components that can have configurable fifo sizes.
|
||||
|
||||
tx-internal-delay-ps:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
description: |
|
||||
RGMII Transmit Clock Delay defined in pico seconds.
|
||||
This is used for controllers that have configurable TX internal delays.
|
||||
If this property is present then the MAC applies the TX delay.
|
||||
|
||||
managed:
|
||||
description:
|
||||
Specifies the PHY management type. If auto is set and fixed-link
|
||||
|
130
Documentation/devicetree/bindings/net/intel,dwmac-plat.yaml
Normal file
130
Documentation/devicetree/bindings/net/intel,dwmac-plat.yaml
Normal file
@@ -0,0 +1,130 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/net/intel,dwmac-plat.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Intel DWMAC glue layer Device Tree Bindings
|
||||
|
||||
maintainers:
|
||||
- Vineetha G. Jaya Kumaran <vineetha.g.jaya.kumaran@intel.com>
|
||||
|
||||
select:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- intel,keembay-dwmac
|
||||
required:
|
||||
- compatible
|
||||
|
||||
allOf:
|
||||
- $ref: "snps,dwmac.yaml#"
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
oneOf:
|
||||
- items:
|
||||
- enum:
|
||||
- intel,keembay-dwmac
|
||||
- const: snps,dwmac-4.10a
|
||||
|
||||
clocks:
|
||||
items:
|
||||
- description: GMAC main clock
|
||||
- description: PTP reference clock
|
||||
- description: Tx clock
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: stmmaceth
|
||||
- const: ptp_ref
|
||||
- const: tx_clk
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- clocks
|
||||
- clock-names
|
||||
|
||||
examples:
|
||||
# FIXME: Remove defines and include the correct header file
|
||||
# once it is available in mainline.
|
||||
- |
|
||||
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
#define MOVISOC_KMB_PSS_GBE
|
||||
#define MOVISOC_KMB_PSS_AUX_GBE_PTP
|
||||
#define MOVISOC_KMB_PSS_AUX_GBE_TX
|
||||
|
||||
stmmac_axi_setup: stmmac-axi-config {
|
||||
snps,lpi_en;
|
||||
snps,wr_osr_lmt = <0x0>;
|
||||
snps,rd_osr_lmt = <0x2>;
|
||||
snps,blen = <0 0 0 0 16 8 4>;
|
||||
};
|
||||
|
||||
mtl_rx_setup: rx-queues-config {
|
||||
snps,rx-queues-to-use = <2>;
|
||||
snps,rx-sched-sp;
|
||||
queue0 {
|
||||
snps,dcb-algorithm;
|
||||
snps,map-to-dma-channel = <0x0>;
|
||||
snps,priority = <0x0>;
|
||||
};
|
||||
|
||||
queue1 {
|
||||
snps,dcb-algorithm;
|
||||
snps,map-to-dma-channel = <0x1>;
|
||||
snps,priority = <0x1>;
|
||||
};
|
||||
};
|
||||
|
||||
mtl_tx_setup: tx-queues-config {
|
||||
snps,tx-queues-to-use = <2>;
|
||||
snps,tx-sched-wrr;
|
||||
queue0 {
|
||||
snps,weight = <0x10>;
|
||||
snps,dcb-algorithm;
|
||||
snps,priority = <0x0>;
|
||||
};
|
||||
|
||||
queue1 {
|
||||
snps,weight = <0x10>;
|
||||
snps,dcb-algorithm;
|
||||
snps,priority = <0x1>;
|
||||
};
|
||||
};
|
||||
|
||||
gmac0: ethernet@3a000000 {
|
||||
compatible = "intel,keembay-dwmac", "snps,dwmac-4.10a";
|
||||
interrupts = <GIC_SPI 119 IRQ_TYPE_LEVEL_HIGH>;
|
||||
interrupt-names = "macirq";
|
||||
reg = <0x3a000000 0x8000>;
|
||||
snps,perfect-filter-entries = <128>;
|
||||
phy-handle = <ð_phy0>;
|
||||
phy-mode = "rgmii";
|
||||
rx-fifo-depth = <4096>;
|
||||
tx-fifo-depth = <4096>;
|
||||
clock-names = "stmmaceth", "ptp_ref", "tx_clk";
|
||||
clocks = <&scmi_clk MOVISOC_KMB_PSS_GBE>,
|
||||
<&scmi_clk MOVISOC_KMB_PSS_AUX_GBE_PTP>,
|
||||
<&scmi_clk MOVISOC_KMB_PSS_AUX_GBE_TX>;
|
||||
snps,pbl = <0x4>;
|
||||
snps,axi-config = <&stmmac_axi_setup>;
|
||||
snps,mtl-rx-config = <&mtl_rx_setup>;
|
||||
snps,mtl-tx-config = <&mtl_tx_setup>;
|
||||
snps,tso;
|
||||
status = "okay";
|
||||
|
||||
mdio0 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
compatible = "snps,dwmac-mdio";
|
||||
|
||||
ethernet-phy@0 {
|
||||
reg = <0>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
...
|
@@ -45,3 +45,37 @@ dfx-server {
|
||||
ranges = <0 MBUS_ID(0x08, 0x00) 0 0x100000>;
|
||||
reg = <MBUS_ID(0x08, 0x00) 0 0x100000>;
|
||||
};
|
||||
|
||||
Marvell Prestera SwitchDev bindings
|
||||
-----------------------------------
|
||||
Optional properties:
|
||||
- compatible: must be "marvell,prestera"
|
||||
- base-mac-provider: describes handle to node which provides base mac address,
|
||||
might be a static base mac address or nvme cell provider.
|
||||
|
||||
Example:
|
||||
|
||||
eeprom_mac_addr: eeprom-mac-addr {
|
||||
compatible = "eeprom,mac-addr-cell";
|
||||
status = "okay";
|
||||
|
||||
nvmem = <&eeprom_at24>;
|
||||
};
|
||||
|
||||
prestera {
|
||||
compatible = "marvell,prestera";
|
||||
status = "okay";
|
||||
|
||||
base-mac-provider = <&eeprom_mac_addr>;
|
||||
};
|
||||
|
||||
The current implementation of Prestera Switchdev PCI interface driver requires
|
||||
that BAR2 is assigned to 0xf6000000 as base address from the PCI IO range:
|
||||
|
||||
&cp0_pcie0 {
|
||||
ranges = <0x81000000 0x0 0xfb000000 0x0 0xfb000000 0x0 0xf0000
|
||||
0x82000000 0x0 0xf6000000 0x0 0xf6000000 0x0 0x2000000
|
||||
0x82000000 0x0 0xf9000000 0x0 0xf9000000 0x0 0x100000>;
|
||||
phys = <&cp0_comphy0 0>;
|
||||
status = "okay";
|
||||
};
|
||||
|
@@ -1,25 +0,0 @@
|
||||
* Samsung S3FWRN5 NCI NFC Controller
|
||||
|
||||
Required properties:
|
||||
- compatible: Should be "samsung,s3fwrn5-i2c".
|
||||
- reg: address on the bus
|
||||
- interrupts: GPIO interrupt to which the chip is connected
|
||||
- s3fwrn5,en-gpios: Output GPIO pin used for enabling/disabling the chip
|
||||
- s3fwrn5,fw-gpios: Output GPIO pin used to enter firmware mode and
|
||||
sleep/wakeup control
|
||||
|
||||
Example:
|
||||
|
||||
&hsi2c_4 {
|
||||
s3fwrn5@27 {
|
||||
compatible = "samsung,s3fwrn5-i2c";
|
||||
|
||||
reg = <0x27>;
|
||||
|
||||
interrupt-parent = <&gpa1>;
|
||||
interrupts = <3 0 0>;
|
||||
|
||||
s3fwrn5,en-gpios = <&gpf1 4 0>;
|
||||
s3fwrn5,fw-gpios = <&gpj0 2 0>;
|
||||
};
|
||||
};
|
@@ -0,0 +1,73 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/net/nfc/samsung,s3fwrn5.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Samsung S3FWRN5 NCI NFC Controller
|
||||
|
||||
maintainers:
|
||||
- Krzysztof Kozlowski <krzk@kernel.org>
|
||||
- Krzysztof Opasiak <k.opasiak@samsung.com>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: samsung,s3fwrn5-i2c
|
||||
|
||||
en-gpios:
|
||||
maxItems: 1
|
||||
description:
|
||||
Output GPIO pin used for enabling/disabling the chip
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
wake-gpios:
|
||||
maxItems: 1
|
||||
description:
|
||||
Output GPIO pin used to enter firmware mode and sleep/wakeup control
|
||||
|
||||
s3fwrn5,en-gpios:
|
||||
maxItems: 1
|
||||
deprecated: true
|
||||
description:
|
||||
Use en-gpios
|
||||
|
||||
s3fwrn5,fw-gpios:
|
||||
maxItems: 1
|
||||
deprecated: true
|
||||
description:
|
||||
Use wake-gpios
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- en-gpios
|
||||
- interrupts
|
||||
- reg
|
||||
- wake-gpios
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
|
||||
i2c4 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
s3fwrn5@27 {
|
||||
compatible = "samsung,s3fwrn5-i2c";
|
||||
reg = <0x27>;
|
||||
|
||||
interrupt-parent = <&gpa1>;
|
||||
interrupts = <3 IRQ_TYPE_LEVEL_HIGH>;
|
||||
|
||||
en-gpios = <&gpf1 4 GPIO_ACTIVE_HIGH>;
|
||||
wake-gpios = <&gpj0 2 GPIO_ACTIVE_HIGH>;
|
||||
};
|
||||
};
|
262
Documentation/devicetree/bindings/net/renesas,etheravb.yaml
Normal file
262
Documentation/devicetree/bindings/net/renesas,etheravb.yaml
Normal file
@@ -0,0 +1,262 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/net/renesas,etheravb.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Renesas Ethernet AVB
|
||||
|
||||
maintainers:
|
||||
- Sergei Shtylyov <sergei.shtylyov@gmail.com>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
oneOf:
|
||||
- items:
|
||||
- enum:
|
||||
- renesas,etheravb-r8a7742 # RZ/G1H
|
||||
- renesas,etheravb-r8a7743 # RZ/G1M
|
||||
- renesas,etheravb-r8a7744 # RZ/G1N
|
||||
- renesas,etheravb-r8a7745 # RZ/G1E
|
||||
- renesas,etheravb-r8a77470 # RZ/G1C
|
||||
- renesas,etheravb-r8a7790 # R-Car H2
|
||||
- renesas,etheravb-r8a7791 # R-Car M2-W
|
||||
- renesas,etheravb-r8a7792 # R-Car V2H
|
||||
- renesas,etheravb-r8a7793 # R-Car M2-N
|
||||
- renesas,etheravb-r8a7794 # R-Car E2
|
||||
- const: renesas,etheravb-rcar-gen2 # R-Car Gen2 and RZ/G1
|
||||
|
||||
- items:
|
||||
- enum:
|
||||
- renesas,etheravb-r8a774a1 # RZ/G2M
|
||||
- renesas,etheravb-r8a774b1 # RZ/G2N
|
||||
- renesas,etheravb-r8a774c0 # RZ/G2E
|
||||
- renesas,etheravb-r8a774e1 # RZ/G2H
|
||||
- renesas,etheravb-r8a7795 # R-Car H3
|
||||
- renesas,etheravb-r8a7796 # R-Car M3-W
|
||||
- renesas,etheravb-r8a77961 # R-Car M3-W+
|
||||
- renesas,etheravb-r8a77965 # R-Car M3-N
|
||||
- renesas,etheravb-r8a77970 # R-Car V3M
|
||||
- renesas,etheravb-r8a77980 # R-Car V3H
|
||||
- renesas,etheravb-r8a77990 # R-Car E3
|
||||
- renesas,etheravb-r8a77995 # R-Car D3
|
||||
- const: renesas,etheravb-rcar-gen3 # R-Car Gen3 and RZ/G2
|
||||
|
||||
reg: true
|
||||
|
||||
interrupts: true
|
||||
|
||||
interrupt-names: true
|
||||
|
||||
clocks:
|
||||
maxItems: 1
|
||||
|
||||
iommus:
|
||||
maxItems: 1
|
||||
|
||||
power-domains:
|
||||
maxItems: 1
|
||||
|
||||
resets:
|
||||
maxItems: 1
|
||||
|
||||
phy-mode: true
|
||||
|
||||
phy-handle: true
|
||||
|
||||
'#address-cells':
|
||||
description: Number of address cells for the MDIO bus.
|
||||
const: 1
|
||||
|
||||
'#size-cells':
|
||||
description: Number of size cells on the MDIO bus.
|
||||
const: 0
|
||||
|
||||
renesas,no-ether-link:
|
||||
type: boolean
|
||||
description:
|
||||
Specify when a board does not provide a proper AVB_LINK signal.
|
||||
|
||||
renesas,ether-link-active-low:
|
||||
type: boolean
|
||||
description:
|
||||
Specify when the AVB_LINK signal is active-low instead of normal
|
||||
active-high.
|
||||
|
||||
rx-internal-delay-ps:
|
||||
enum: [0, 1800]
|
||||
|
||||
tx-internal-delay-ps:
|
||||
enum: [0, 2000]
|
||||
|
||||
patternProperties:
|
||||
"^ethernet-phy@[0-9a-f]$":
|
||||
type: object
|
||||
$ref: ethernet-phy.yaml#
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- interrupts
|
||||
- clocks
|
||||
- power-domains
|
||||
- resets
|
||||
- phy-mode
|
||||
- phy-handle
|
||||
- '#address-cells'
|
||||
- '#size-cells'
|
||||
|
||||
allOf:
|
||||
- $ref: ethernet-controller.yaml#
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- renesas,etheravb-rcar-gen2
|
||||
- renesas,etheravb-r8a7795
|
||||
- renesas,etheravb-r8a7796
|
||||
- renesas,etheravb-r8a77961
|
||||
- renesas,etheravb-r8a77965
|
||||
then:
|
||||
properties:
|
||||
reg:
|
||||
items:
|
||||
- description: MAC register block
|
||||
- description: Stream buffer
|
||||
else:
|
||||
properties:
|
||||
reg:
|
||||
items:
|
||||
- description: MAC register block
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
const: renesas,etheravb-rcar-gen2
|
||||
then:
|
||||
properties:
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
interrupt-names:
|
||||
items:
|
||||
- const: mux
|
||||
rx-internal-delay-ps: false
|
||||
else:
|
||||
properties:
|
||||
interrupts:
|
||||
minItems: 25
|
||||
maxItems: 25
|
||||
interrupt-names:
|
||||
items:
|
||||
pattern: '^ch[0-9]+$'
|
||||
required:
|
||||
- interrupt-names
|
||||
- rx-internal-delay-ps
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- renesas,etheravb-r8a774a1
|
||||
- renesas,etheravb-r8a774b1
|
||||
- renesas,etheravb-r8a7795
|
||||
- renesas,etheravb-r8a7796
|
||||
- renesas,etheravb-r8a77961
|
||||
- renesas,etheravb-r8a77965
|
||||
- renesas,etheravb-r8a77970
|
||||
- renesas,etheravb-r8a77980
|
||||
then:
|
||||
required:
|
||||
- tx-internal-delay-ps
|
||||
else:
|
||||
properties:
|
||||
tx-internal-delay-ps: false
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
const: renesas,etheravb-r8a77995
|
||||
then:
|
||||
properties:
|
||||
rx-internal-delay-ps:
|
||||
const: 1800
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
const: renesas,etheravb-r8a77980
|
||||
then:
|
||||
properties:
|
||||
tx-internal-delay-ps:
|
||||
const: 2000
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/clock/r8a7795-cpg-mssr.h>
|
||||
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||
#include <dt-bindings/power/r8a7795-sysc.h>
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
aliases {
|
||||
ethernet0 = &avb;
|
||||
};
|
||||
|
||||
avb: ethernet@e6800000 {
|
||||
compatible = "renesas,etheravb-r8a7795",
|
||||
"renesas,etheravb-rcar-gen3";
|
||||
reg = <0xe6800000 0x800>, <0xe6a00000 0x10000>;
|
||||
interrupts = <GIC_SPI 39 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 41 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 42 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 43 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 44 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 45 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 46 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 47 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 48 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 49 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 50 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 51 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 52 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 53 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 54 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 56 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 57 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 58 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 59 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 60 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 61 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 62 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 63 IRQ_TYPE_LEVEL_HIGH>;
|
||||
interrupt-names = "ch0", "ch1", "ch2", "ch3", "ch4", "ch5", "ch6",
|
||||
"ch7", "ch8", "ch9", "ch10", "ch11", "ch12",
|
||||
"ch13", "ch14", "ch15", "ch16", "ch17", "ch18",
|
||||
"ch19", "ch20", "ch21", "ch22", "ch23", "ch24";
|
||||
clocks = <&cpg CPG_MOD 812>;
|
||||
iommus = <&ipmmu_ds0 16>;
|
||||
power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
|
||||
resets = <&cpg 812>;
|
||||
phy-mode = "rgmii";
|
||||
phy-handle = <&phy0>;
|
||||
rx-internal-delay-ps = <0>;
|
||||
tx-internal-delay-ps = <2000>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
phy0: ethernet-phy@0 {
|
||||
rxc-skew-ps = <1500>;
|
||||
reg = <0>;
|
||||
interrupt-parent = <&gpio2>;
|
||||
interrupts = <11 IRQ_TYPE_LEVEL_LOW>;
|
||||
reset-gpios = <&gpio2 10 GPIO_ACTIVE_LOW>;
|
||||
};
|
||||
};
|
@@ -1,135 +0,0 @@
|
||||
* Renesas Electronics Ethernet AVB
|
||||
|
||||
This file provides information on what the device node for the Ethernet AVB
|
||||
interface contains.
|
||||
|
||||
Required properties:
|
||||
- compatible: Must contain one or more of the following:
|
||||
- "renesas,etheravb-r8a7742" for the R8A7742 SoC.
|
||||
- "renesas,etheravb-r8a7743" for the R8A7743 SoC.
|
||||
- "renesas,etheravb-r8a7744" for the R8A7744 SoC.
|
||||
- "renesas,etheravb-r8a7745" for the R8A7745 SoC.
|
||||
- "renesas,etheravb-r8a77470" for the R8A77470 SoC.
|
||||
- "renesas,etheravb-r8a7790" for the R8A7790 SoC.
|
||||
- "renesas,etheravb-r8a7791" for the R8A7791 SoC.
|
||||
- "renesas,etheravb-r8a7792" for the R8A7792 SoC.
|
||||
- "renesas,etheravb-r8a7793" for the R8A7793 SoC.
|
||||
- "renesas,etheravb-r8a7794" for the R8A7794 SoC.
|
||||
- "renesas,etheravb-rcar-gen2" as a fallback for the above
|
||||
R-Car Gen2 and RZ/G1 devices.
|
||||
|
||||
- "renesas,etheravb-r8a774a1" for the R8A774A1 SoC.
|
||||
- "renesas,etheravb-r8a774b1" for the R8A774B1 SoC.
|
||||
- "renesas,etheravb-r8a774c0" for the R8A774C0 SoC.
|
||||
- "renesas,etheravb-r8a774e1" for the R8A774E1 SoC.
|
||||
- "renesas,etheravb-r8a7795" for the R8A7795 SoC.
|
||||
- "renesas,etheravb-r8a7796" for the R8A77960 SoC.
|
||||
- "renesas,etheravb-r8a77961" for the R8A77961 SoC.
|
||||
- "renesas,etheravb-r8a77965" for the R8A77965 SoC.
|
||||
- "renesas,etheravb-r8a77970" for the R8A77970 SoC.
|
||||
- "renesas,etheravb-r8a77980" for the R8A77980 SoC.
|
||||
- "renesas,etheravb-r8a77990" for the R8A77990 SoC.
|
||||
- "renesas,etheravb-r8a77995" for the R8A77995 SoC.
|
||||
- "renesas,etheravb-rcar-gen3" as a fallback for the above
|
||||
R-Car Gen3 and RZ/G2 devices.
|
||||
|
||||
When compatible with the generic version, nodes must list the
|
||||
SoC-specific version corresponding to the platform first followed by
|
||||
the generic version.
|
||||
|
||||
- reg: Offset and length of (1) the register block and (2) the stream buffer.
|
||||
The region for the register block is mandatory.
|
||||
The region for the stream buffer is optional, as it is only present on
|
||||
R-Car Gen2 and RZ/G1 SoCs, and on R-Car H3 (R8A7795), M3-W (R8A77960),
|
||||
M3-W+ (R8A77961), and M3-N (R8A77965).
|
||||
- interrupts: A list of interrupt-specifiers, one for each entry in
|
||||
interrupt-names.
|
||||
If interrupt-names is not present, an interrupt specifier
|
||||
for a single muxed interrupt.
|
||||
- phy-mode: see ethernet.txt file in the same directory.
|
||||
- phy-handle: see ethernet.txt file in the same directory.
|
||||
- #address-cells: number of address cells for the MDIO bus, must be equal to 1.
|
||||
- #size-cells: number of size cells on the MDIO bus, must be equal to 0.
|
||||
- clocks: clock phandle and specifier pair.
|
||||
- pinctrl-0: phandle, referring to a default pin configuration node.
|
||||
|
||||
Optional properties:
|
||||
- interrupt-names: A list of interrupt names.
|
||||
For the R-Car Gen 3 SoCs this property is mandatory;
|
||||
it should include one entry per channel, named "ch%u",
|
||||
where %u is the channel number ranging from 0 to 24.
|
||||
For other SoCs this property is optional; if present
|
||||
it should contain "mux" for a single muxed interrupt.
|
||||
- pinctrl-names: pin configuration state name ("default").
|
||||
- renesas,no-ether-link: boolean, specify when a board does not provide a proper
|
||||
AVB_LINK signal.
|
||||
- renesas,ether-link-active-low: boolean, specify when the AVB_LINK signal is
|
||||
active-low instead of normal active-high.
|
||||
|
||||
Example:
|
||||
|
||||
ethernet@e6800000 {
|
||||
compatible = "renesas,etheravb-r8a7795", "renesas,etheravb-rcar-gen3";
|
||||
reg = <0 0xe6800000 0 0x800>, <0 0xe6a00000 0 0x10000>;
|
||||
interrupt-parent = <&gic>;
|
||||
interrupts = <GIC_SPI 39 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 41 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 42 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 43 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 44 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 45 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 46 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 47 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 48 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 49 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 50 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 51 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 52 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 53 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 54 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 56 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 57 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 58 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 59 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 60 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 61 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 62 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 63 IRQ_TYPE_LEVEL_HIGH>;
|
||||
interrupt-names = "ch0", "ch1", "ch2", "ch3",
|
||||
"ch4", "ch5", "ch6", "ch7",
|
||||
"ch8", "ch9", "ch10", "ch11",
|
||||
"ch12", "ch13", "ch14", "ch15",
|
||||
"ch16", "ch17", "ch18", "ch19",
|
||||
"ch20", "ch21", "ch22", "ch23",
|
||||
"ch24";
|
||||
clocks = <&cpg CPG_MOD 812>;
|
||||
power-domains = <&cpg>;
|
||||
phy-mode = "rgmii-id";
|
||||
phy-handle = <&phy0>;
|
||||
|
||||
pinctrl-0 = <ðer_pins>;
|
||||
pinctrl-names = "default";
|
||||
renesas,no-ether-link;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
phy0: ethernet-phy@0 {
|
||||
rxc-skew-ps = <900>;
|
||||
rxdv-skew-ps = <0>;
|
||||
rxd0-skew-ps = <0>;
|
||||
rxd1-skew-ps = <0>;
|
||||
rxd2-skew-ps = <0>;
|
||||
rxd3-skew-ps = <0>;
|
||||
txc-skew-ps = <900>;
|
||||
txen-skew-ps = <0>;
|
||||
txd0-skew-ps = <0>;
|
||||
txd1-skew-ps = <0>;
|
||||
txd2-skew-ps = <0>;
|
||||
txd3-skew-ps = <0>;
|
||||
reg = <0>;
|
||||
interrupt-parent = <&gpio2>;
|
||||
interrupts = <11 IRQ_TYPE_LEVEL_LOW>;
|
||||
};
|
||||
};
|
@@ -5,6 +5,10 @@ through an Ethernet OF device node.
|
||||
|
||||
Optional properties:
|
||||
|
||||
- clocks:
|
||||
The clock used as phy reference clock and is connected to phy
|
||||
pin XTAL1/CLKIN.
|
||||
|
||||
- smsc,disable-energy-detect:
|
||||
If set, do not enable energy detect mode for the SMSC phy.
|
||||
default: enable energy detect mode
|
||||
|
80
Documentation/devicetree/bindings/net/ti,dp83822.yaml
Normal file
80
Documentation/devicetree/bindings/net/ti,dp83822.yaml
Normal file
@@ -0,0 +1,80 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0+ OR BSD-2-Clause)
|
||||
# Copyright (C) 2020 Texas Instruments Incorporated
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: "http://devicetree.org/schemas/net/ti,dp83822.yaml#"
|
||||
$schema: "http://devicetree.org/meta-schemas/core.yaml#"
|
||||
|
||||
title: TI DP83822 ethernet PHY
|
||||
|
||||
maintainers:
|
||||
- Dan Murphy <dmurphy@ti.com>
|
||||
|
||||
description: |
|
||||
The DP83822 is a low-power, single-port, 10/100 Mbps Ethernet PHY. It
|
||||
provides all of the physical layer functions needed to transmit and receive
|
||||
data over standard, twisted-pair cables or to connect to an external,
|
||||
fiber-optic transceiver. Additionally, the DP83822 provides flexibility to
|
||||
connect to a MAC through a standard MII, RMII, or RGMII interface
|
||||
|
||||
Specifications about the Ethernet PHY can be found at:
|
||||
http://www.ti.com/lit/ds/symlink/dp83822i.pdf
|
||||
|
||||
allOf:
|
||||
- $ref: "ethernet-phy.yaml#"
|
||||
|
||||
properties:
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
ti,link-loss-low:
|
||||
type: boolean
|
||||
description: |
|
||||
DP83822 PHY in Fiber mode only.
|
||||
Sets the DP83822 to detect a link drop condition when the signal goes
|
||||
high. If not set then link drop will occur when the signal goes low.
|
||||
This property is only applicable if the fiber mode support is strapped
|
||||
to on.
|
||||
|
||||
ti,fiber-mode:
|
||||
type: boolean
|
||||
description: |
|
||||
DP83822 PHY only.
|
||||
If present the DP83822 PHY is configured to operate in fiber mode
|
||||
Fiber mode support can also be strapped. If the strap pin is not set
|
||||
correctly or not set at all then this boolean can be used to enable it.
|
||||
If the fiber mode is not strapped then signal detection for the PHY
|
||||
is disabled.
|
||||
In fiber mode, auto-negotiation is disabled and the PHY can only work in
|
||||
100base-fx (full and half duplex) modes.
|
||||
|
||||
rx-internal-delay-ps:
|
||||
description: |
|
||||
DP83822 PHY only.
|
||||
Setting this property to a non-zero number sets the RX internal delay
|
||||
for the PHY. The internal delay for the PHY is fixed to 3.5ns relative
|
||||
to receive data.
|
||||
|
||||
tx-internal-delay-ps:
|
||||
description: |
|
||||
DP83822 PHY only.
|
||||
Setting this property to a non-zero number sets the TX internal delay
|
||||
for the PHY. The internal delay for the PHY is fixed to 3.5ns relative
|
||||
to transmit data.
|
||||
|
||||
required:
|
||||
- reg
|
||||
|
||||
examples:
|
||||
- |
|
||||
mdio0 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
ethphy0: ethernet-phy@0 {
|
||||
reg = <0>;
|
||||
rx-internal-delay-ps = <1>;
|
||||
tx-internal-delay-ps = <1>;
|
||||
};
|
||||
};
|
||||
|
||||
...
|
@@ -65,7 +65,8 @@ Optional properties:
|
||||
the length can vary between hw versions.
|
||||
- <supply-name>-supply: handle to the regulator device tree node
|
||||
optional "supply-name" are "vdd-0.8-cx-mx",
|
||||
"vdd-1.8-xo", "vdd-1.3-rfa" and "vdd-3.3-ch0".
|
||||
"vdd-1.8-xo", "vdd-1.3-rfa", "vdd-3.3-ch0",
|
||||
and "vdd-3.3-ch1".
|
||||
- memory-region:
|
||||
Usage: optional
|
||||
Value type: <phandle>
|
||||
@@ -204,6 +205,7 @@ wifi@18000000 {
|
||||
vdd-1.8-xo-supply = <&vreg_l7a_1p8>;
|
||||
vdd-1.3-rfa-supply = <&vreg_l17a_1p3>;
|
||||
vdd-3.3-ch0-supply = <&vreg_l25a_3p3>;
|
||||
vdd-3.3-ch1-supply = <&vreg_l26a_3p3>;
|
||||
memory-region = <&wifi_msa_mem>;
|
||||
iommus = <&apps_smmu 0x0040 0x1>;
|
||||
qcom,msa-fixed-perm;
|
||||
|
@@ -17,7 +17,9 @@ description: |
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: qcom,ipq8074-wifi
|
||||
enum:
|
||||
- qcom,ipq8074-wifi
|
||||
- qcom,ipq6018-wifi
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
@@ -18,6 +18,8 @@ Clock Properties:
|
||||
- fsl,tmr-add Frequency compensation value.
|
||||
- fsl,tmr-fiper1 Fixed interval period pulse generator.
|
||||
- fsl,tmr-fiper2 Fixed interval period pulse generator.
|
||||
- fsl,tmr-fiper3 Fixed interval period pulse generator.
|
||||
Supported only on DPAA2 and ENETC hardware.
|
||||
- fsl,max-adj Maximum frequency adjustment in parts per billion.
|
||||
- fsl,extts-fifo The presence of this property indicates hardware
|
||||
support for the external trigger stamp FIFO.
|
||||
|
@@ -12,79 +12,32 @@ Device registration
|
||||
:doc: Device registration
|
||||
|
||||
.. kernel-doc:: include/net/cfg80211.h
|
||||
:functions: ieee80211_channel_flags
|
||||
|
||||
.. kernel-doc:: include/net/cfg80211.h
|
||||
:functions: ieee80211_channel
|
||||
|
||||
.. kernel-doc:: include/net/cfg80211.h
|
||||
:functions: ieee80211_rate_flags
|
||||
|
||||
.. kernel-doc:: include/net/cfg80211.h
|
||||
:functions: ieee80211_rate
|
||||
|
||||
.. kernel-doc:: include/net/cfg80211.h
|
||||
:functions: ieee80211_sta_ht_cap
|
||||
|
||||
.. kernel-doc:: include/net/cfg80211.h
|
||||
:functions: ieee80211_supported_band
|
||||
|
||||
.. kernel-doc:: include/net/cfg80211.h
|
||||
:functions: cfg80211_signal_type
|
||||
|
||||
.. kernel-doc:: include/net/cfg80211.h
|
||||
:functions: wiphy_params_flags
|
||||
|
||||
.. kernel-doc:: include/net/cfg80211.h
|
||||
:functions: wiphy_flags
|
||||
|
||||
.. kernel-doc:: include/net/cfg80211.h
|
||||
:functions: wiphy
|
||||
|
||||
.. kernel-doc:: include/net/cfg80211.h
|
||||
:functions: wireless_dev
|
||||
|
||||
.. kernel-doc:: include/net/cfg80211.h
|
||||
:functions: wiphy_new
|
||||
|
||||
.. kernel-doc:: include/net/cfg80211.h
|
||||
:functions: wiphy_read_of_freq_limits
|
||||
|
||||
.. kernel-doc:: include/net/cfg80211.h
|
||||
:functions: wiphy_register
|
||||
|
||||
.. kernel-doc:: include/net/cfg80211.h
|
||||
:functions: wiphy_unregister
|
||||
|
||||
.. kernel-doc:: include/net/cfg80211.h
|
||||
:functions: wiphy_free
|
||||
|
||||
.. kernel-doc:: include/net/cfg80211.h
|
||||
:functions: wiphy_name
|
||||
|
||||
.. kernel-doc:: include/net/cfg80211.h
|
||||
:functions: wiphy_dev
|
||||
|
||||
.. kernel-doc:: include/net/cfg80211.h
|
||||
:functions: wiphy_priv
|
||||
|
||||
.. kernel-doc:: include/net/cfg80211.h
|
||||
:functions: priv_to_wiphy
|
||||
|
||||
.. kernel-doc:: include/net/cfg80211.h
|
||||
:functions: set_wiphy_dev
|
||||
|
||||
.. kernel-doc:: include/net/cfg80211.h
|
||||
:functions: wdev_priv
|
||||
|
||||
.. kernel-doc:: include/net/cfg80211.h
|
||||
:functions: ieee80211_iface_limit
|
||||
|
||||
.. kernel-doc:: include/net/cfg80211.h
|
||||
:functions: ieee80211_iface_combination
|
||||
|
||||
.. kernel-doc:: include/net/cfg80211.h
|
||||
:functions: cfg80211_check_combinations
|
||||
:functions:
|
||||
ieee80211_channel_flags
|
||||
ieee80211_channel
|
||||
ieee80211_rate_flags
|
||||
ieee80211_rate
|
||||
ieee80211_sta_ht_cap
|
||||
ieee80211_supported_band
|
||||
cfg80211_signal_type
|
||||
wiphy_params_flags
|
||||
wiphy_flags
|
||||
wiphy
|
||||
wireless_dev
|
||||
wiphy_new
|
||||
wiphy_read_of_freq_limits
|
||||
wiphy_register
|
||||
wiphy_unregister
|
||||
wiphy_free
|
||||
wiphy_name
|
||||
wiphy_dev
|
||||
wiphy_priv
|
||||
priv_to_wiphy
|
||||
set_wiphy_dev
|
||||
wdev_priv
|
||||
ieee80211_iface_limit
|
||||
ieee80211_iface_combination
|
||||
cfg80211_check_combinations
|
||||
|
||||
Actions and configuration
|
||||
=========================
|
||||
@@ -93,139 +46,52 @@ Actions and configuration
|
||||
:doc: Actions and configuration
|
||||
|
||||
.. kernel-doc:: include/net/cfg80211.h
|
||||
:functions: cfg80211_ops
|
||||
|
||||
.. kernel-doc:: include/net/cfg80211.h
|
||||
:functions: vif_params
|
||||
|
||||
.. kernel-doc:: include/net/cfg80211.h
|
||||
:functions: key_params
|
||||
|
||||
.. kernel-doc:: include/net/cfg80211.h
|
||||
:functions: survey_info_flags
|
||||
|
||||
.. kernel-doc:: include/net/cfg80211.h
|
||||
:functions: survey_info
|
||||
|
||||
.. kernel-doc:: include/net/cfg80211.h
|
||||
:functions: cfg80211_beacon_data
|
||||
|
||||
.. kernel-doc:: include/net/cfg80211.h
|
||||
:functions: cfg80211_ap_settings
|
||||
|
||||
.. kernel-doc:: include/net/cfg80211.h
|
||||
:functions: station_parameters
|
||||
|
||||
.. kernel-doc:: include/net/cfg80211.h
|
||||
:functions: rate_info_flags
|
||||
|
||||
.. kernel-doc:: include/net/cfg80211.h
|
||||
:functions: rate_info
|
||||
|
||||
.. kernel-doc:: include/net/cfg80211.h
|
||||
:functions: station_info
|
||||
|
||||
.. kernel-doc:: include/net/cfg80211.h
|
||||
:functions: monitor_flags
|
||||
|
||||
.. kernel-doc:: include/net/cfg80211.h
|
||||
:functions: mpath_info_flags
|
||||
|
||||
.. kernel-doc:: include/net/cfg80211.h
|
||||
:functions: mpath_info
|
||||
|
||||
.. kernel-doc:: include/net/cfg80211.h
|
||||
:functions: bss_parameters
|
||||
|
||||
.. kernel-doc:: include/net/cfg80211.h
|
||||
:functions: ieee80211_txq_params
|
||||
|
||||
.. kernel-doc:: include/net/cfg80211.h
|
||||
:functions: cfg80211_crypto_settings
|
||||
|
||||
.. kernel-doc:: include/net/cfg80211.h
|
||||
:functions: cfg80211_auth_request
|
||||
|
||||
.. kernel-doc:: include/net/cfg80211.h
|
||||
:functions: cfg80211_assoc_request
|
||||
|
||||
.. kernel-doc:: include/net/cfg80211.h
|
||||
:functions: cfg80211_deauth_request
|
||||
|
||||
.. kernel-doc:: include/net/cfg80211.h
|
||||
:functions: cfg80211_disassoc_request
|
||||
|
||||
.. kernel-doc:: include/net/cfg80211.h
|
||||
:functions: cfg80211_ibss_params
|
||||
|
||||
.. kernel-doc:: include/net/cfg80211.h
|
||||
:functions: cfg80211_connect_params
|
||||
|
||||
.. kernel-doc:: include/net/cfg80211.h
|
||||
:functions: cfg80211_pmksa
|
||||
|
||||
.. kernel-doc:: include/net/cfg80211.h
|
||||
:functions: cfg80211_rx_mlme_mgmt
|
||||
|
||||
.. kernel-doc:: include/net/cfg80211.h
|
||||
:functions: cfg80211_auth_timeout
|
||||
|
||||
.. kernel-doc:: include/net/cfg80211.h
|
||||
:functions: cfg80211_rx_assoc_resp
|
||||
|
||||
.. kernel-doc:: include/net/cfg80211.h
|
||||
:functions: cfg80211_assoc_timeout
|
||||
|
||||
.. kernel-doc:: include/net/cfg80211.h
|
||||
:functions: cfg80211_tx_mlme_mgmt
|
||||
|
||||
.. kernel-doc:: include/net/cfg80211.h
|
||||
:functions: cfg80211_ibss_joined
|
||||
|
||||
.. kernel-doc:: include/net/cfg80211.h
|
||||
:functions: cfg80211_connect_resp_params
|
||||
|
||||
.. kernel-doc:: include/net/cfg80211.h
|
||||
:functions: cfg80211_connect_done
|
||||
|
||||
.. kernel-doc:: include/net/cfg80211.h
|
||||
:functions: cfg80211_connect_result
|
||||
|
||||
.. kernel-doc:: include/net/cfg80211.h
|
||||
:functions: cfg80211_connect_bss
|
||||
|
||||
.. kernel-doc:: include/net/cfg80211.h
|
||||
:functions: cfg80211_connect_timeout
|
||||
|
||||
.. kernel-doc:: include/net/cfg80211.h
|
||||
:functions: cfg80211_roamed
|
||||
|
||||
.. kernel-doc:: include/net/cfg80211.h
|
||||
:functions: cfg80211_disconnected
|
||||
|
||||
.. kernel-doc:: include/net/cfg80211.h
|
||||
:functions: cfg80211_ready_on_channel
|
||||
|
||||
.. kernel-doc:: include/net/cfg80211.h
|
||||
:functions: cfg80211_remain_on_channel_expired
|
||||
|
||||
.. kernel-doc:: include/net/cfg80211.h
|
||||
:functions: cfg80211_new_sta
|
||||
|
||||
.. kernel-doc:: include/net/cfg80211.h
|
||||
:functions: cfg80211_rx_mgmt
|
||||
|
||||
.. kernel-doc:: include/net/cfg80211.h
|
||||
:functions: cfg80211_mgmt_tx_status
|
||||
|
||||
.. kernel-doc:: include/net/cfg80211.h
|
||||
:functions: cfg80211_cqm_rssi_notify
|
||||
|
||||
.. kernel-doc:: include/net/cfg80211.h
|
||||
:functions: cfg80211_cqm_pktloss_notify
|
||||
|
||||
.. kernel-doc:: include/net/cfg80211.h
|
||||
:functions: cfg80211_michael_mic_failure
|
||||
:functions:
|
||||
cfg80211_ops
|
||||
vif_params
|
||||
key_params
|
||||
survey_info_flags
|
||||
survey_info
|
||||
cfg80211_beacon_data
|
||||
cfg80211_ap_settings
|
||||
station_parameters
|
||||
rate_info_flags
|
||||
rate_info
|
||||
station_info
|
||||
monitor_flags
|
||||
mpath_info_flags
|
||||
mpath_info
|
||||
bss_parameters
|
||||
ieee80211_txq_params
|
||||
cfg80211_crypto_settings
|
||||
cfg80211_auth_request
|
||||
cfg80211_assoc_request
|
||||
cfg80211_deauth_request
|
||||
cfg80211_disassoc_request
|
||||
cfg80211_ibss_params
|
||||
cfg80211_connect_params
|
||||
cfg80211_pmksa
|
||||
cfg80211_rx_mlme_mgmt
|
||||
cfg80211_auth_timeout
|
||||
cfg80211_rx_assoc_resp
|
||||
cfg80211_assoc_timeout
|
||||
cfg80211_tx_mlme_mgmt
|
||||
cfg80211_ibss_joined
|
||||
cfg80211_connect_resp_params
|
||||
cfg80211_connect_done
|
||||
cfg80211_connect_result
|
||||
cfg80211_connect_bss
|
||||
cfg80211_connect_timeout
|
||||
cfg80211_roamed
|
||||
cfg80211_disconnected
|
||||
cfg80211_ready_on_channel
|
||||
cfg80211_remain_on_channel_expired
|
||||
cfg80211_new_sta
|
||||
cfg80211_rx_mgmt
|
||||
cfg80211_mgmt_tx_status
|
||||
cfg80211_cqm_rssi_notify
|
||||
cfg80211_cqm_pktloss_notify
|
||||
cfg80211_michael_mic_failure
|
||||
|
||||
Scanning and BSS list handling
|
||||
==============================
|
||||
@@ -234,34 +100,17 @@ Scanning and BSS list handling
|
||||
:doc: Scanning and BSS list handling
|
||||
|
||||
.. kernel-doc:: include/net/cfg80211.h
|
||||
:functions: cfg80211_ssid
|
||||
|
||||
.. kernel-doc:: include/net/cfg80211.h
|
||||
:functions: cfg80211_scan_request
|
||||
|
||||
.. kernel-doc:: include/net/cfg80211.h
|
||||
:functions: cfg80211_scan_done
|
||||
|
||||
.. kernel-doc:: include/net/cfg80211.h
|
||||
:functions: cfg80211_bss
|
||||
|
||||
.. kernel-doc:: include/net/cfg80211.h
|
||||
:functions: cfg80211_inform_bss
|
||||
|
||||
.. kernel-doc:: include/net/cfg80211.h
|
||||
:functions: cfg80211_inform_bss_frame_data
|
||||
|
||||
.. kernel-doc:: include/net/cfg80211.h
|
||||
:functions: cfg80211_inform_bss_data
|
||||
|
||||
.. kernel-doc:: include/net/cfg80211.h
|
||||
:functions: cfg80211_unlink_bss
|
||||
|
||||
.. kernel-doc:: include/net/cfg80211.h
|
||||
:functions: cfg80211_find_ie
|
||||
|
||||
.. kernel-doc:: include/net/cfg80211.h
|
||||
:functions: ieee80211_bss_get_ie
|
||||
:functions:
|
||||
cfg80211_ssid
|
||||
cfg80211_scan_request
|
||||
cfg80211_scan_done
|
||||
cfg80211_bss
|
||||
cfg80211_inform_bss
|
||||
cfg80211_inform_bss_frame_data
|
||||
cfg80211_inform_bss_data
|
||||
cfg80211_unlink_bss
|
||||
cfg80211_find_ie
|
||||
ieee80211_bss_get_ie
|
||||
|
||||
Utility functions
|
||||
=================
|
||||
@@ -270,25 +119,14 @@ Utility functions
|
||||
:doc: Utility functions
|
||||
|
||||
.. kernel-doc:: include/net/cfg80211.h
|
||||
:functions: ieee80211_channel_to_frequency
|
||||
|
||||
.. kernel-doc:: include/net/cfg80211.h
|
||||
:functions: ieee80211_frequency_to_channel
|
||||
|
||||
.. kernel-doc:: include/net/cfg80211.h
|
||||
:functions: ieee80211_get_channel
|
||||
|
||||
.. kernel-doc:: include/net/cfg80211.h
|
||||
:functions: ieee80211_get_response_rate
|
||||
|
||||
.. kernel-doc:: include/net/cfg80211.h
|
||||
:functions: ieee80211_hdrlen
|
||||
|
||||
.. kernel-doc:: include/net/cfg80211.h
|
||||
:functions: ieee80211_get_hdrlen_from_skb
|
||||
|
||||
.. kernel-doc:: include/net/cfg80211.h
|
||||
:functions: ieee80211_radiotap_iterator
|
||||
:functions:
|
||||
ieee80211_channel_to_frequency
|
||||
ieee80211_frequency_to_channel
|
||||
ieee80211_get_channel
|
||||
ieee80211_get_response_rate
|
||||
ieee80211_hdrlen
|
||||
ieee80211_get_hdrlen_from_skb
|
||||
ieee80211_radiotap_iterator
|
||||
|
||||
Data path helpers
|
||||
=================
|
||||
@@ -297,13 +135,10 @@ Data path helpers
|
||||
:doc: Data path helpers
|
||||
|
||||
.. kernel-doc:: include/net/cfg80211.h
|
||||
:functions: ieee80211_data_to_8023
|
||||
|
||||
.. kernel-doc:: include/net/cfg80211.h
|
||||
:functions: ieee80211_amsdu_to_8023s
|
||||
|
||||
.. kernel-doc:: include/net/cfg80211.h
|
||||
:functions: cfg80211_classify8021d
|
||||
:functions:
|
||||
ieee80211_data_to_8023
|
||||
ieee80211_amsdu_to_8023s
|
||||
cfg80211_classify8021d
|
||||
|
||||
Regulatory enforcement infrastructure
|
||||
=====================================
|
||||
@@ -312,13 +147,10 @@ Regulatory enforcement infrastructure
|
||||
:doc: Regulatory enforcement infrastructure
|
||||
|
||||
.. kernel-doc:: include/net/cfg80211.h
|
||||
:functions: regulatory_hint
|
||||
|
||||
.. kernel-doc:: include/net/cfg80211.h
|
||||
:functions: wiphy_apply_custom_regulatory
|
||||
|
||||
.. kernel-doc:: include/net/cfg80211.h
|
||||
:functions: freq_reg_info
|
||||
:functions:
|
||||
regulatory_hint
|
||||
wiphy_apply_custom_regulatory
|
||||
freq_reg_info
|
||||
|
||||
RFkill integration
|
||||
==================
|
||||
@@ -327,13 +159,10 @@ RFkill integration
|
||||
:doc: RFkill integration
|
||||
|
||||
.. kernel-doc:: include/net/cfg80211.h
|
||||
:functions: wiphy_rfkill_set_hw_state
|
||||
|
||||
.. kernel-doc:: include/net/cfg80211.h
|
||||
:functions: wiphy_rfkill_start_polling
|
||||
|
||||
.. kernel-doc:: include/net/cfg80211.h
|
||||
:functions: wiphy_rfkill_stop_polling
|
||||
:functions:
|
||||
wiphy_rfkill_set_hw_state
|
||||
wiphy_rfkill_start_polling
|
||||
wiphy_rfkill_stop_polling
|
||||
|
||||
Test mode
|
||||
=========
|
||||
@@ -342,13 +171,8 @@ Test mode
|
||||
:doc: Test mode
|
||||
|
||||
.. kernel-doc:: include/net/cfg80211.h
|
||||
:functions: cfg80211_testmode_alloc_reply_skb
|
||||
|
||||
.. kernel-doc:: include/net/cfg80211.h
|
||||
:functions: cfg80211_testmode_reply
|
||||
|
||||
.. kernel-doc:: include/net/cfg80211.h
|
||||
:functions: cfg80211_testmode_alloc_event_skb
|
||||
|
||||
.. kernel-doc:: include/net/cfg80211.h
|
||||
:functions: cfg80211_testmode_event
|
||||
:functions:
|
||||
cfg80211_testmode_alloc_reply_skb
|
||||
cfg80211_testmode_reply
|
||||
cfg80211_testmode_alloc_event_skb
|
||||
cfg80211_testmode_event
|
||||
|
@@ -15,25 +15,14 @@ appropriate trigger, which will then be triggered appropriately by
|
||||
mac80211.
|
||||
|
||||
.. kernel-doc:: include/net/mac80211.h
|
||||
:functions: ieee80211_get_tx_led_name
|
||||
|
||||
.. kernel-doc:: include/net/mac80211.h
|
||||
:functions: ieee80211_get_rx_led_name
|
||||
|
||||
.. kernel-doc:: include/net/mac80211.h
|
||||
:functions: ieee80211_get_assoc_led_name
|
||||
|
||||
.. kernel-doc:: include/net/mac80211.h
|
||||
:functions: ieee80211_get_radio_led_name
|
||||
|
||||
.. kernel-doc:: include/net/mac80211.h
|
||||
:functions: ieee80211_tpt_blink
|
||||
|
||||
.. kernel-doc:: include/net/mac80211.h
|
||||
:functions: ieee80211_tpt_led_trigger_flags
|
||||
|
||||
.. kernel-doc:: include/net/mac80211.h
|
||||
:functions: ieee80211_create_tpt_led_trigger
|
||||
:functions:
|
||||
ieee80211_get_tx_led_name
|
||||
ieee80211_get_rx_led_name
|
||||
ieee80211_get_assoc_led_name
|
||||
ieee80211_get_radio_led_name
|
||||
ieee80211_tpt_blink
|
||||
ieee80211_tpt_led_trigger_flags
|
||||
ieee80211_create_tpt_led_trigger
|
||||
|
||||
Hardware crypto acceleration
|
||||
============================
|
||||
@@ -42,22 +31,13 @@ Hardware crypto acceleration
|
||||
:doc: Hardware crypto acceleration
|
||||
|
||||
.. kernel-doc:: include/net/mac80211.h
|
||||
:functions: set_key_cmd
|
||||
|
||||
.. kernel-doc:: include/net/mac80211.h
|
||||
:functions: ieee80211_key_conf
|
||||
|
||||
.. kernel-doc:: include/net/mac80211.h
|
||||
:functions: ieee80211_key_flags
|
||||
|
||||
.. kernel-doc:: include/net/mac80211.h
|
||||
:functions: ieee80211_get_tkip_p1k
|
||||
|
||||
.. kernel-doc:: include/net/mac80211.h
|
||||
:functions: ieee80211_get_tkip_p1k_iv
|
||||
|
||||
.. kernel-doc:: include/net/mac80211.h
|
||||
:functions: ieee80211_get_tkip_p2k
|
||||
:functions:
|
||||
set_key_cmd
|
||||
ieee80211_key_conf
|
||||
ieee80211_key_flags
|
||||
ieee80211_get_tkip_p1k
|
||||
ieee80211_get_tkip_p1k_iv
|
||||
ieee80211_get_tkip_p2k
|
||||
|
||||
Powersave support
|
||||
=================
|
||||
@@ -99,28 +79,15 @@ support for powersaving clients
|
||||
:doc: AP support for powersaving clients
|
||||
|
||||
.. kernel-doc:: include/net/mac80211.h
|
||||
:functions: ieee80211_get_buffered_bc
|
||||
|
||||
.. kernel-doc:: include/net/mac80211.h
|
||||
:functions: ieee80211_beacon_get
|
||||
|
||||
.. kernel-doc:: include/net/mac80211.h
|
||||
:functions: ieee80211_sta_eosp
|
||||
|
||||
.. kernel-doc:: include/net/mac80211.h
|
||||
:functions: ieee80211_frame_release_type
|
||||
|
||||
.. kernel-doc:: include/net/mac80211.h
|
||||
:functions: ieee80211_sta_ps_transition
|
||||
|
||||
.. kernel-doc:: include/net/mac80211.h
|
||||
:functions: ieee80211_sta_ps_transition_ni
|
||||
|
||||
.. kernel-doc:: include/net/mac80211.h
|
||||
:functions: ieee80211_sta_set_buffered
|
||||
|
||||
.. kernel-doc:: include/net/mac80211.h
|
||||
:functions: ieee80211_sta_block_awake
|
||||
:functions:
|
||||
ieee80211_get_buffered_bc
|
||||
ieee80211_beacon_get
|
||||
ieee80211_sta_eosp
|
||||
ieee80211_frame_release_type
|
||||
ieee80211_sta_ps_transition
|
||||
ieee80211_sta_ps_transition_ni
|
||||
ieee80211_sta_set_buffered
|
||||
ieee80211_sta_block_awake
|
||||
|
||||
Supporting multiple virtual interfaces
|
||||
======================================
|
||||
@@ -134,10 +101,9 @@ addresses here, note which configurations are supported by mac80211, add
|
||||
notes about supporting hw crypto with it.
|
||||
|
||||
.. kernel-doc:: include/net/mac80211.h
|
||||
:functions: ieee80211_iterate_active_interfaces
|
||||
|
||||
.. kernel-doc:: include/net/mac80211.h
|
||||
:functions: ieee80211_iterate_active_interfaces_atomic
|
||||
:functions:
|
||||
ieee80211_iterate_active_interfaces
|
||||
ieee80211_iterate_active_interfaces_atomic
|
||||
|
||||
Station handling
|
||||
================
|
||||
@@ -145,16 +111,11 @@ Station handling
|
||||
TODO
|
||||
|
||||
.. kernel-doc:: include/net/mac80211.h
|
||||
:functions: ieee80211_sta
|
||||
|
||||
.. kernel-doc:: include/net/mac80211.h
|
||||
:functions: sta_notify_cmd
|
||||
|
||||
.. kernel-doc:: include/net/mac80211.h
|
||||
:functions: ieee80211_find_sta
|
||||
|
||||
.. kernel-doc:: include/net/mac80211.h
|
||||
:functions: ieee80211_find_sta_by_ifaddr
|
||||
:functions:
|
||||
ieee80211_sta
|
||||
sta_notify_cmd
|
||||
ieee80211_find_sta
|
||||
ieee80211_find_sta_by_ifaddr
|
||||
|
||||
Hardware scan offload
|
||||
=====================
|
||||
@@ -193,10 +154,9 @@ Spatial Multiplexing Powersave (SMPS)
|
||||
:doc: Spatial multiplexing power save
|
||||
|
||||
.. kernel-doc:: include/net/mac80211.h
|
||||
:functions: ieee80211_request_smps
|
||||
|
||||
.. kernel-doc:: include/net/mac80211.h
|
||||
:functions: ieee80211_smps_mode
|
||||
:functions:
|
||||
ieee80211_request_smps
|
||||
ieee80211_smps_mode
|
||||
|
||||
TBD
|
||||
|
||||
@@ -209,22 +169,13 @@ Rate Control API
|
||||
TBD
|
||||
|
||||
.. kernel-doc:: include/net/mac80211.h
|
||||
:functions: ieee80211_start_tx_ba_session
|
||||
|
||||
.. kernel-doc:: include/net/mac80211.h
|
||||
:functions: ieee80211_start_tx_ba_cb_irqsafe
|
||||
|
||||
.. kernel-doc:: include/net/mac80211.h
|
||||
:functions: ieee80211_stop_tx_ba_session
|
||||
|
||||
.. kernel-doc:: include/net/mac80211.h
|
||||
:functions: ieee80211_stop_tx_ba_cb_irqsafe
|
||||
|
||||
.. kernel-doc:: include/net/mac80211.h
|
||||
:functions: ieee80211_rate_control_changed
|
||||
|
||||
.. kernel-doc:: include/net/mac80211.h
|
||||
:functions: ieee80211_tx_rate_control
|
||||
:functions:
|
||||
ieee80211_start_tx_ba_session
|
||||
ieee80211_start_tx_ba_cb_irqsafe
|
||||
ieee80211_stop_tx_ba_session
|
||||
ieee80211_stop_tx_ba_cb_irqsafe
|
||||
ieee80211_rate_control_changed
|
||||
ieee80211_tx_rate_control
|
||||
|
||||
TBD
|
||||
|
||||
@@ -261,10 +212,9 @@ Programming information
|
||||
-----------------------
|
||||
|
||||
.. kernel-doc:: net/mac80211/sta_info.h
|
||||
:functions: sta_info
|
||||
|
||||
.. kernel-doc:: net/mac80211/sta_info.h
|
||||
:functions: ieee80211_sta_info_flags
|
||||
:functions:
|
||||
sta_info
|
||||
ieee80211_sta_info_flags
|
||||
|
||||
STA information lifetime rules
|
||||
------------------------------
|
||||
@@ -276,13 +226,10 @@ Aggregation Functions
|
||||
=====================
|
||||
|
||||
.. kernel-doc:: net/mac80211/sta_info.h
|
||||
:functions: sta_ampdu_mlme
|
||||
|
||||
.. kernel-doc:: net/mac80211/sta_info.h
|
||||
:functions: tid_ampdu_tx
|
||||
|
||||
.. kernel-doc:: net/mac80211/sta_info.h
|
||||
:functions: tid_ampdu_rx
|
||||
:functions:
|
||||
sta_ampdu_mlme
|
||||
tid_ampdu_tx
|
||||
tid_ampdu_rx
|
||||
|
||||
Synchronisation Functions
|
||||
=========================
|
||||
|
@@ -30,31 +30,16 @@ Finally, a discussion of hardware capabilities should be done with
|
||||
references to other parts of the book.
|
||||
|
||||
.. kernel-doc:: include/net/mac80211.h
|
||||
:functions: ieee80211_hw
|
||||
|
||||
.. kernel-doc:: include/net/mac80211.h
|
||||
:functions: ieee80211_hw_flags
|
||||
|
||||
.. kernel-doc:: include/net/mac80211.h
|
||||
:functions: SET_IEEE80211_DEV
|
||||
|
||||
.. kernel-doc:: include/net/mac80211.h
|
||||
:functions: SET_IEEE80211_PERM_ADDR
|
||||
|
||||
.. kernel-doc:: include/net/mac80211.h
|
||||
:functions: ieee80211_ops
|
||||
|
||||
.. kernel-doc:: include/net/mac80211.h
|
||||
:functions: ieee80211_alloc_hw
|
||||
|
||||
.. kernel-doc:: include/net/mac80211.h
|
||||
:functions: ieee80211_register_hw
|
||||
|
||||
.. kernel-doc:: include/net/mac80211.h
|
||||
:functions: ieee80211_unregister_hw
|
||||
|
||||
.. kernel-doc:: include/net/mac80211.h
|
||||
:functions: ieee80211_free_hw
|
||||
:functions:
|
||||
ieee80211_hw
|
||||
ieee80211_hw_flags
|
||||
SET_IEEE80211_DEV
|
||||
SET_IEEE80211_PERM_ADDR
|
||||
ieee80211_ops
|
||||
ieee80211_alloc_hw
|
||||
ieee80211_register_hw
|
||||
ieee80211_unregister_hw
|
||||
ieee80211_free_hw
|
||||
|
||||
PHY configuration
|
||||
=================
|
||||
@@ -65,10 +50,9 @@ This chapter should describe PHY handling including start/stop callbacks
|
||||
and the various structures used.
|
||||
|
||||
.. kernel-doc:: include/net/mac80211.h
|
||||
:functions: ieee80211_conf
|
||||
|
||||
.. kernel-doc:: include/net/mac80211.h
|
||||
:functions: ieee80211_conf_flags
|
||||
:functions:
|
||||
ieee80211_conf
|
||||
ieee80211_conf_flags
|
||||
|
||||
Virtual interfaces
|
||||
==================
|
||||
@@ -123,79 +107,32 @@ functions/definitions
|
||||
---------------------
|
||||
|
||||
.. kernel-doc:: include/net/mac80211.h
|
||||
:functions: ieee80211_rx_status
|
||||
|
||||
.. kernel-doc:: include/net/mac80211.h
|
||||
:functions: mac80211_rx_encoding_flags
|
||||
|
||||
.. kernel-doc:: include/net/mac80211.h
|
||||
:functions: mac80211_rx_flags
|
||||
|
||||
.. kernel-doc:: include/net/mac80211.h
|
||||
:functions: mac80211_tx_info_flags
|
||||
|
||||
.. kernel-doc:: include/net/mac80211.h
|
||||
:functions: mac80211_tx_control_flags
|
||||
|
||||
.. kernel-doc:: include/net/mac80211.h
|
||||
:functions: mac80211_rate_control_flags
|
||||
|
||||
.. kernel-doc:: include/net/mac80211.h
|
||||
:functions: ieee80211_tx_rate
|
||||
|
||||
.. kernel-doc:: include/net/mac80211.h
|
||||
:functions: ieee80211_tx_info
|
||||
|
||||
.. kernel-doc:: include/net/mac80211.h
|
||||
:functions: ieee80211_tx_info_clear_status
|
||||
|
||||
.. kernel-doc:: include/net/mac80211.h
|
||||
:functions: ieee80211_rx
|
||||
|
||||
.. kernel-doc:: include/net/mac80211.h
|
||||
:functions: ieee80211_rx_ni
|
||||
|
||||
.. kernel-doc:: include/net/mac80211.h
|
||||
:functions: ieee80211_rx_irqsafe
|
||||
|
||||
.. kernel-doc:: include/net/mac80211.h
|
||||
:functions: ieee80211_tx_status
|
||||
|
||||
.. kernel-doc:: include/net/mac80211.h
|
||||
:functions: ieee80211_tx_status_ni
|
||||
|
||||
.. kernel-doc:: include/net/mac80211.h
|
||||
:functions: ieee80211_tx_status_irqsafe
|
||||
|
||||
.. kernel-doc:: include/net/mac80211.h
|
||||
:functions: ieee80211_rts_get
|
||||
|
||||
.. kernel-doc:: include/net/mac80211.h
|
||||
:functions: ieee80211_rts_duration
|
||||
|
||||
.. kernel-doc:: include/net/mac80211.h
|
||||
:functions: ieee80211_ctstoself_get
|
||||
|
||||
.. kernel-doc:: include/net/mac80211.h
|
||||
:functions: ieee80211_ctstoself_duration
|
||||
|
||||
.. kernel-doc:: include/net/mac80211.h
|
||||
:functions: ieee80211_generic_frame_duration
|
||||
|
||||
.. kernel-doc:: include/net/mac80211.h
|
||||
:functions: ieee80211_wake_queue
|
||||
|
||||
.. kernel-doc:: include/net/mac80211.h
|
||||
:functions: ieee80211_stop_queue
|
||||
|
||||
.. kernel-doc:: include/net/mac80211.h
|
||||
:functions: ieee80211_wake_queues
|
||||
|
||||
.. kernel-doc:: include/net/mac80211.h
|
||||
:functions: ieee80211_stop_queues
|
||||
|
||||
.. kernel-doc:: include/net/mac80211.h
|
||||
:functions: ieee80211_queue_stopped
|
||||
:functions:
|
||||
ieee80211_rx_status
|
||||
mac80211_rx_encoding_flags
|
||||
mac80211_rx_flags
|
||||
mac80211_tx_info_flags
|
||||
mac80211_tx_control_flags
|
||||
mac80211_rate_control_flags
|
||||
ieee80211_tx_rate
|
||||
ieee80211_tx_info
|
||||
ieee80211_tx_info_clear_status
|
||||
ieee80211_rx
|
||||
ieee80211_rx_ni
|
||||
ieee80211_rx_irqsafe
|
||||
ieee80211_tx_status
|
||||
ieee80211_tx_status_ni
|
||||
ieee80211_tx_status_irqsafe
|
||||
ieee80211_rts_get
|
||||
ieee80211_rts_duration
|
||||
ieee80211_ctstoself_get
|
||||
ieee80211_ctstoself_duration
|
||||
ieee80211_generic_frame_duration
|
||||
ieee80211_wake_queue
|
||||
ieee80211_stop_queue
|
||||
ieee80211_wake_queues
|
||||
ieee80211_stop_queues
|
||||
ieee80211_queue_stopped
|
||||
|
||||
Frame filtering
|
||||
===============
|
||||
@@ -213,7 +150,6 @@ The mac80211 workqueue
|
||||
:doc: mac80211 workqueue
|
||||
|
||||
.. kernel-doc:: include/net/mac80211.h
|
||||
:functions: ieee80211_queue_work
|
||||
|
||||
.. kernel-doc:: include/net/mac80211.h
|
||||
:functions: ieee80211_queue_delayed_work
|
||||
:functions:
|
||||
ieee80211_queue_work
|
||||
ieee80211_queue_delayed_work
|
||||
|
@@ -258,14 +258,21 @@ socket into zero-copy mode or fail.
|
||||
XDP_SHARED_UMEM bind flag
|
||||
-------------------------
|
||||
|
||||
This flag enables you to bind multiple sockets to the same UMEM, but
|
||||
only if they share the same queue id. In this mode, each socket has
|
||||
their own RX and TX rings, but the UMEM (tied to the fist socket
|
||||
created) only has a single FILL ring and a single COMPLETION
|
||||
ring. To use this mode, create the first socket and bind it in the normal
|
||||
way. Create a second socket and create an RX and a TX ring, or at
|
||||
least one of them, but no FILL or COMPLETION rings as the ones from
|
||||
the first socket will be used. In the bind call, set he
|
||||
This flag enables you to bind multiple sockets to the same UMEM. It
|
||||
works on the same queue id, between queue ids and between
|
||||
netdevs/devices. In this mode, each socket has their own RX and TX
|
||||
rings as usual, but you are going to have one or more FILL and
|
||||
COMPLETION ring pairs. You have to create one of these pairs per
|
||||
unique netdev and queue id tuple that you bind to.
|
||||
|
||||
Starting with the case were we would like to share a UMEM between
|
||||
sockets bound to the same netdev and queue id. The UMEM (tied to the
|
||||
fist socket created) will only have a single FILL ring and a single
|
||||
COMPLETION ring as there is only on unique netdev,queue_id tuple that
|
||||
we have bound to. To use this mode, create the first socket and bind
|
||||
it in the normal way. Create a second socket and create an RX and a TX
|
||||
ring, or at least one of them, but no FILL or COMPLETION rings as the
|
||||
ones from the first socket will be used. In the bind call, set he
|
||||
XDP_SHARED_UMEM option and provide the initial socket's fd in the
|
||||
sxdp_shared_umem_fd field. You can attach an arbitrary number of extra
|
||||
sockets this way.
|
||||
@@ -305,11 +312,41 @@ concurrently. There are no synchronization primitives in the
|
||||
libbpf code that protects multiple users at this point in time.
|
||||
|
||||
Libbpf uses this mode if you create more than one socket tied to the
|
||||
same umem. However, note that you need to supply the
|
||||
same UMEM. However, note that you need to supply the
|
||||
XSK_LIBBPF_FLAGS__INHIBIT_PROG_LOAD libbpf_flag with the
|
||||
xsk_socket__create calls and load your own XDP program as there is no
|
||||
built in one in libbpf that will route the traffic for you.
|
||||
|
||||
The second case is when you share a UMEM between sockets that are
|
||||
bound to different queue ids and/or netdevs. In this case you have to
|
||||
create one FILL ring and one COMPLETION ring for each unique
|
||||
netdev,queue_id pair. Let us say you want to create two sockets bound
|
||||
to two different queue ids on the same netdev. Create the first socket
|
||||
and bind it in the normal way. Create a second socket and create an RX
|
||||
and a TX ring, or at least one of them, and then one FILL and
|
||||
COMPLETION ring for this socket. Then in the bind call, set he
|
||||
XDP_SHARED_UMEM option and provide the initial socket's fd in the
|
||||
sxdp_shared_umem_fd field as you registered the UMEM on that
|
||||
socket. These two sockets will now share one and the same UMEM.
|
||||
|
||||
There is no need to supply an XDP program like the one in the previous
|
||||
case where sockets were bound to the same queue id and
|
||||
device. Instead, use the NIC's packet steering capabilities to steer
|
||||
the packets to the right queue. In the previous example, there is only
|
||||
one queue shared among sockets, so the NIC cannot do this steering. It
|
||||
can only steer between queues.
|
||||
|
||||
In libbpf, you need to use the xsk_socket__create_shared() API as it
|
||||
takes a reference to a FILL ring and a COMPLETION ring that will be
|
||||
created for you and bound to the shared UMEM. You can use this
|
||||
function for all the sockets you create, or you can use it for the
|
||||
second and following ones and use xsk_socket__create() for the first
|
||||
one. Both methods yield the same result.
|
||||
|
||||
Note that a UMEM can be shared between sockets on the same queue id
|
||||
and device, as well as between queues on the same device and between
|
||||
devices at the same time.
|
||||
|
||||
XDP_USE_NEED_WAKEUP bind flag
|
||||
-----------------------------
|
||||
|
||||
@@ -364,7 +401,7 @@ resources by only setting up one of them. Both the FILL ring and the
|
||||
COMPLETION ring are mandatory as you need to have a UMEM tied to your
|
||||
socket. But if the XDP_SHARED_UMEM flag is used, any socket after the
|
||||
first one does not have a UMEM and should in that case not have any
|
||||
FILL or COMPLETION rings created as the ones from the shared umem will
|
||||
FILL or COMPLETION rings created as the ones from the shared UMEM will
|
||||
be used. Note, that the rings are single-producer single-consumer, so
|
||||
do not try to access them from multiple processes at the same
|
||||
time. See the XDP_SHARED_UMEM section.
|
||||
@@ -567,6 +604,17 @@ A: The short answer is no, that is not supported at the moment. The
|
||||
switch, or other distribution mechanism, in your NIC to direct
|
||||
traffic to the correct queue id and socket.
|
||||
|
||||
Q: My packets are sometimes corrupted. What is wrong?
|
||||
|
||||
A: Care has to be taken not to feed the same buffer in the UMEM into
|
||||
more than one ring at the same time. If you for example feed the
|
||||
same buffer into the FILL ring and the TX ring at the same time, the
|
||||
NIC might receive data into the buffer at the same time it is
|
||||
sending it. This will cause some packets to become corrupted. Same
|
||||
thing goes for feeding the same buffer into the FILL rings
|
||||
belonging to different queue ids or netdevs bound with the
|
||||
XDP_SHARED_UMEM flag.
|
||||
|
||||
Credits
|
||||
=======
|
||||
|
||||
|
@@ -10,4 +10,3 @@ Contents:
|
||||
|
||||
linux_caif
|
||||
caif
|
||||
spi_porting
|
||||
|
@@ -1,229 +0,0 @@
|
||||
.. SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
================
|
||||
CAIF SPI porting
|
||||
================
|
||||
|
||||
CAIF SPI basics
|
||||
===============
|
||||
|
||||
Running CAIF over SPI needs some extra setup, owing to the nature of SPI.
|
||||
Two extra GPIOs have been added in order to negotiate the transfers
|
||||
between the master and the slave. The minimum requirement for running
|
||||
CAIF over SPI is a SPI slave chip and two GPIOs (more details below).
|
||||
Please note that running as a slave implies that you need to keep up
|
||||
with the master clock. An overrun or underrun event is fatal.
|
||||
|
||||
CAIF SPI framework
|
||||
==================
|
||||
|
||||
To make porting as easy as possible, the CAIF SPI has been divided in
|
||||
two parts. The first part (called the interface part) deals with all
|
||||
generic functionality such as length framing, SPI frame negotiation
|
||||
and SPI frame delivery and transmission. The other part is the CAIF
|
||||
SPI slave device part, which is the module that you have to write if
|
||||
you want to run SPI CAIF on a new hardware. This part takes care of
|
||||
the physical hardware, both with regard to SPI and to GPIOs.
|
||||
|
||||
- Implementing a CAIF SPI device:
|
||||
|
||||
- Functionality provided by the CAIF SPI slave device:
|
||||
|
||||
In order to implement a SPI device you will, as a minimum,
|
||||
need to implement the following
|
||||
functions:
|
||||
|
||||
::
|
||||
|
||||
int (*init_xfer) (struct cfspi_xfer * xfer, struct cfspi_dev *dev):
|
||||
|
||||
This function is called by the CAIF SPI interface to give
|
||||
you a chance to set up your hardware to be ready to receive
|
||||
a stream of data from the master. The xfer structure contains
|
||||
both physical and logical addresses, as well as the total length
|
||||
of the transfer in both directions.The dev parameter can be used
|
||||
to map to different CAIF SPI slave devices.
|
||||
|
||||
::
|
||||
|
||||
void (*sig_xfer) (bool xfer, struct cfspi_dev *dev):
|
||||
|
||||
This function is called by the CAIF SPI interface when the output
|
||||
(SPI_INT) GPIO needs to change state. The boolean value of the xfer
|
||||
variable indicates whether the GPIO should be asserted (HIGH) or
|
||||
deasserted (LOW). The dev parameter can be used to map to different CAIF
|
||||
SPI slave devices.
|
||||
|
||||
- Functionality provided by the CAIF SPI interface:
|
||||
|
||||
::
|
||||
|
||||
void (*ss_cb) (bool assert, struct cfspi_ifc *ifc);
|
||||
|
||||
This function is called by the CAIF SPI slave device in order to
|
||||
signal a change of state of the input GPIO (SS) to the interface.
|
||||
Only active edges are mandatory to be reported.
|
||||
This function can be called from IRQ context (recommended in order
|
||||
not to introduce latency). The ifc parameter should be the pointer
|
||||
returned from the platform probe function in the SPI device structure.
|
||||
|
||||
::
|
||||
|
||||
void (*xfer_done_cb) (struct cfspi_ifc *ifc);
|
||||
|
||||
This function is called by the CAIF SPI slave device in order to
|
||||
report that a transfer is completed. This function should only be
|
||||
called once both the transmission and the reception are completed.
|
||||
This function can be called from IRQ context (recommended in order
|
||||
not to introduce latency). The ifc parameter should be the pointer
|
||||
returned from the platform probe function in the SPI device structure.
|
||||
|
||||
- Connecting the bits and pieces:
|
||||
|
||||
- Filling in the SPI slave device structure:
|
||||
|
||||
Connect the necessary callback functions.
|
||||
|
||||
Indicate clock speed (used to calculate toggle delays).
|
||||
|
||||
Chose a suitable name (helps debugging if you use several CAIF
|
||||
SPI slave devices).
|
||||
|
||||
Assign your private data (can be used to map to your
|
||||
structure).
|
||||
|
||||
- Filling in the SPI slave platform device structure:
|
||||
|
||||
Add name of driver to connect to ("cfspi_sspi").
|
||||
|
||||
Assign the SPI slave device structure as platform data.
|
||||
|
||||
Padding
|
||||
=======
|
||||
|
||||
In order to optimize throughput, a number of SPI padding options are provided.
|
||||
Padding can be enabled independently for uplink and downlink transfers.
|
||||
Padding can be enabled for the head, the tail and for the total frame size.
|
||||
The padding needs to be correctly configured on both sides of the link.
|
||||
The padding can be changed via module parameters in cfspi_sspi.c or via
|
||||
the sysfs directory of the cfspi_sspi driver (before device registration).
|
||||
|
||||
- CAIF SPI device template::
|
||||
|
||||
/*
|
||||
* Copyright (C) ST-Ericsson AB 2010
|
||||
* Author: Daniel Martensson / Daniel.Martensson@stericsson.com
|
||||
* License terms: GNU General Public License (GPL), version 2.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/wait.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <net/caif/caif_spi.h>
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
struct sspi_struct {
|
||||
struct cfspi_dev sdev;
|
||||
struct cfspi_xfer *xfer;
|
||||
};
|
||||
|
||||
static struct sspi_struct slave;
|
||||
static struct platform_device slave_device;
|
||||
|
||||
static irqreturn_t sspi_irq(int irq, void *arg)
|
||||
{
|
||||
/* You only need to trigger on an edge to the active state of the
|
||||
* SS signal. Once a edge is detected, the ss_cb() function should be
|
||||
* called with the parameter assert set to true. It is OK
|
||||
* (and even advised) to call the ss_cb() function in IRQ context in
|
||||
* order not to add any delay. */
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static void sspi_complete(void *context)
|
||||
{
|
||||
/* Normally the DMA or the SPI framework will call you back
|
||||
* in something similar to this. The only thing you need to
|
||||
* do is to call the xfer_done_cb() function, providing the pointer
|
||||
* to the CAIF SPI interface. It is OK to call this function
|
||||
* from IRQ context. */
|
||||
}
|
||||
|
||||
static int sspi_init_xfer(struct cfspi_xfer *xfer, struct cfspi_dev *dev)
|
||||
{
|
||||
/* Store transfer info. For a normal implementation you should
|
||||
* set up your DMA here and make sure that you are ready to
|
||||
* receive the data from the master SPI. */
|
||||
|
||||
struct sspi_struct *sspi = (struct sspi_struct *)dev->priv;
|
||||
|
||||
sspi->xfer = xfer;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void sspi_sig_xfer(bool xfer, struct cfspi_dev *dev)
|
||||
{
|
||||
/* If xfer is true then you should assert the SPI_INT to indicate to
|
||||
* the master that you are ready to receive the data from the master
|
||||
* SPI. If xfer is false then you should de-assert SPI_INT to indicate
|
||||
* that the transfer is done.
|
||||
*/
|
||||
|
||||
struct sspi_struct *sspi = (struct sspi_struct *)dev->priv;
|
||||
}
|
||||
|
||||
static void sspi_release(struct device *dev)
|
||||
{
|
||||
/*
|
||||
* Here you should release your SPI device resources.
|
||||
*/
|
||||
}
|
||||
|
||||
static int __init sspi_init(void)
|
||||
{
|
||||
/* Here you should initialize your SPI device by providing the
|
||||
* necessary functions, clock speed, name and private data. Once
|
||||
* done, you can register your device with the
|
||||
* platform_device_register() function. This function will return
|
||||
* with the CAIF SPI interface initialized. This is probably also
|
||||
* the place where you should set up your GPIOs, interrupts and SPI
|
||||
* resources. */
|
||||
|
||||
int res = 0;
|
||||
|
||||
/* Initialize slave device. */
|
||||
slave.sdev.init_xfer = sspi_init_xfer;
|
||||
slave.sdev.sig_xfer = sspi_sig_xfer;
|
||||
slave.sdev.clk_mhz = 13;
|
||||
slave.sdev.priv = &slave;
|
||||
slave.sdev.name = "spi_sspi";
|
||||
slave_device.dev.release = sspi_release;
|
||||
|
||||
/* Initialize platform device. */
|
||||
slave_device.name = "cfspi_sspi";
|
||||
slave_device.dev.platform_data = &slave.sdev;
|
||||
|
||||
/* Register platform device. */
|
||||
res = platform_device_register(&slave_device);
|
||||
if (res) {
|
||||
printk(KERN_WARNING "sspi_init: failed to register dev.\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static void __exit sspi_exit(void)
|
||||
{
|
||||
platform_device_del(&slave_device);
|
||||
}
|
||||
|
||||
module_init(sspi_init);
|
||||
module_exit(sspi_exit);
|
@@ -39,16 +39,6 @@ debug logs.
|
||||
Some of the ENA devices support a working mode called Low-latency
|
||||
Queue (LLQ), which saves several more microseconds.
|
||||
|
||||
Supported PCI vendor ID/device IDs
|
||||
==================================
|
||||
|
||||
========= =======================
|
||||
1d0f:0ec2 ENA PF
|
||||
1d0f:1ec2 ENA PF with LLQ support
|
||||
1d0f:ec20 ENA VF
|
||||
1d0f:ec21 ENA VF with LLQ support
|
||||
========= =======================
|
||||
|
||||
ENA Source Code Directory Structure
|
||||
===================================
|
||||
|
||||
@@ -212,20 +202,11 @@ In adaptive interrupt moderation mode the interrupt delay value is
|
||||
updated by the driver dynamically and adjusted every NAPI cycle
|
||||
according to the traffic nature.
|
||||
|
||||
By default ENA driver applies adaptive coalescing on Rx traffic and
|
||||
conventional coalescing on Tx traffic.
|
||||
|
||||
Adaptive coalescing can be switched on/off through ethtool(8)
|
||||
adaptive_rx on|off parameter.
|
||||
|
||||
The driver chooses interrupt delay value according to the number of
|
||||
bytes and packets received between interrupt unmasking and interrupt
|
||||
posting. The driver uses interrupt delay table that subdivides the
|
||||
range of received bytes/packets into 5 levels and assigns interrupt
|
||||
delay value to each level.
|
||||
|
||||
The user can enable/disable adaptive moderation, modify the interrupt
|
||||
delay table and restore its default values through sysfs.
|
||||
More information about Adaptive Interrupt Moderation (DIM) can be found in
|
||||
Documentation/networking/net_dim.rst
|
||||
|
||||
RX copybreak
|
||||
============
|
||||
@@ -274,7 +255,7 @@ RSS
|
||||
inputs for hash functions.
|
||||
- The driver configures RSS settings using the AQ SetFeature command
|
||||
(ENA_ADMIN_RSS_HASH_FUNCTION, ENA_ADMIN_RSS_HASH_INPUT and
|
||||
ENA_ADMIN_RSS_REDIRECTION_TABLE_CONFIG properties).
|
||||
ENA_ADMIN_RSS_INDIRECTION_TABLE_CONFIG properties).
|
||||
- If the NETIF_F_RXHASH flag is set, the 32-bit result of the hash
|
||||
function delivered in the Rx CQ descriptor is set in the received
|
||||
SKB.
|
||||
|
@@ -16,6 +16,34 @@ Note that the file name is a path relative to the firmware loading path
|
||||
(usually ``/lib/firmware/``). Drivers may send status updates to inform
|
||||
user space about the progress of the update operation.
|
||||
|
||||
Overwrite Mask
|
||||
==============
|
||||
|
||||
The ``devlink-flash`` command allows optionally specifying a mask indicating
|
||||
how the device should handle subsections of flash components when updating.
|
||||
This mask indicates the set of sections which are allowed to be overwritten.
|
||||
|
||||
.. list-table:: List of overwrite mask bits
|
||||
:widths: 5 95
|
||||
|
||||
* - Name
|
||||
- Description
|
||||
* - ``DEVLINK_FLASH_OVERWRITE_SETTINGS``
|
||||
- Indicates that the device should overwrite settings in the components
|
||||
being updated with the settings found in the provided image.
|
||||
* - ``DEVLINK_FLASH_OVERWRITE_IDENTIFIERS``
|
||||
- Indicates that the device should overwrite identifiers in the
|
||||
components being updated with the identifiers found in the provided
|
||||
image. This includes MAC addresses, serial IDs, and similar device
|
||||
identifiers.
|
||||
|
||||
Multiple overwrite bits may be combined and requested together. If no bits
|
||||
are provided, it is expected that the device only update firmware binaries
|
||||
in the components being updated. Settings and identifiers are expected to be
|
||||
preserved across the update. A device may not support every combination and
|
||||
the driver for such a device must reject any combination which cannot be
|
||||
faithfully implemented.
|
||||
|
||||
Firmware Loading
|
||||
================
|
||||
|
||||
|
@@ -108,3 +108,9 @@ own name.
|
||||
* - ``region_snapshot_enable``
|
||||
- Boolean
|
||||
- Enable capture of ``devlink-region`` snapshots.
|
||||
* - ``enable_remote_dev_reset``
|
||||
- Boolean
|
||||
- Enable device reset by remote host. When cleared, the device driver
|
||||
will NACK any attempt of other host to reset the device. This parameter
|
||||
is useful for setups where a device is shared by different hosts, such
|
||||
as multi-host setup.
|
||||
|
81
Documentation/networking/devlink/devlink-reload.rst
Normal file
81
Documentation/networking/devlink/devlink-reload.rst
Normal file
@@ -0,0 +1,81 @@
|
||||
.. SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
==============
|
||||
Devlink Reload
|
||||
==============
|
||||
|
||||
``devlink-reload`` provides mechanism to reinit driver entities, applying
|
||||
``devlink-params`` and ``devlink-resources`` new values. It also provides
|
||||
mechanism to activate firmware.
|
||||
|
||||
Reload Actions
|
||||
==============
|
||||
|
||||
User may select a reload action.
|
||||
By default ``driver_reinit`` action is selected.
|
||||
|
||||
.. list-table:: Possible reload actions
|
||||
:widths: 5 90
|
||||
|
||||
* - Name
|
||||
- Description
|
||||
* - ``driver-reinit``
|
||||
- Devlink driver entities re-initialization, including applying
|
||||
new values to devlink entities which are used during driver
|
||||
load such as ``devlink-params`` in configuration mode
|
||||
``driverinit`` or ``devlink-resources``
|
||||
* - ``fw_activate``
|
||||
- Firmware activate. Activates new firmware if such image is stored and
|
||||
pending activation. If no limitation specified this action may involve
|
||||
firmware reset. If no new image pending this action will reload current
|
||||
firmware image.
|
||||
|
||||
Note that even though user asks for a specific action, the driver
|
||||
implementation might require to perform another action alongside with
|
||||
it. For example, some driver do not support driver reinitialization
|
||||
being performed without fw activation. Therefore, the devlink reload
|
||||
command returns the list of actions which were actrually performed.
|
||||
|
||||
Reload Limits
|
||||
=============
|
||||
|
||||
By default reload actions are not limited and driver implementation may
|
||||
include reset or downtime as needed to perform the actions.
|
||||
|
||||
However, some drivers support action limits, which limit the action
|
||||
implementation to specific constraints.
|
||||
|
||||
.. list-table:: Possible reload limits
|
||||
:widths: 5 90
|
||||
|
||||
* - Name
|
||||
- Description
|
||||
* - ``no_reset``
|
||||
- No reset allowed, no down time allowed, no link flap and no
|
||||
configuration is lost.
|
||||
|
||||
Change Namespace
|
||||
================
|
||||
|
||||
The netns option allows user to be able to move devlink instances into
|
||||
namespaces during devlink reload operation.
|
||||
By default all devlink instances are created in init_net and stay there.
|
||||
|
||||
example usage
|
||||
-------------
|
||||
|
||||
.. code:: shell
|
||||
|
||||
$ devlink dev reload help
|
||||
$ devlink dev reload DEV [ netns { PID | NAME | ID } ] [ action { driver_reinit | fw_activate } ] [ limit no_reset ]
|
||||
|
||||
# Run reload command for devlink driver entities re-initialization:
|
||||
$ devlink dev reload pci/0000:82:00.0 action driver_reinit
|
||||
reload_actions_performed:
|
||||
driver_reinit
|
||||
|
||||
# Run reload command to activate firmware:
|
||||
# Note that mlx5 driver reloads the driver while activating firmware
|
||||
$ devlink dev reload pci/0000:82:00.0 action fw_activate
|
||||
reload_actions_performed:
|
||||
driver_reinit fw_activate
|
@@ -409,6 +409,73 @@ be added to the following table:
|
||||
- ``drop``
|
||||
- Traps packets dropped due to the RED (Random Early Detection) algorithm
|
||||
(i.e., early drops)
|
||||
* - ``vxlan_parsing``
|
||||
- ``drop``
|
||||
- Traps packets dropped due to an error in the VXLAN header parsing which
|
||||
might be because of packet truncation or the I flag is not set.
|
||||
* - ``llc_snap_parsing``
|
||||
- ``drop``
|
||||
- Traps packets dropped due to an error in the LLC+SNAP header parsing
|
||||
* - ``vlan_parsing``
|
||||
- ``drop``
|
||||
- Traps packets dropped due to an error in the VLAN header parsing. Could
|
||||
include unexpected packet truncation.
|
||||
* - ``pppoe_ppp_parsing``
|
||||
- ``drop``
|
||||
- Traps packets dropped due to an error in the PPPoE+PPP header parsing.
|
||||
This could include finding a session ID of 0xFFFF (which is reserved and
|
||||
not for use), a PPPoE length which is larger than the frame received or
|
||||
any common error on this type of header
|
||||
* - ``mpls_parsing``
|
||||
- ``drop``
|
||||
- Traps packets dropped due to an error in the MPLS header parsing which
|
||||
could include unexpected header truncation
|
||||
* - ``arp_parsing``
|
||||
- ``drop``
|
||||
- Traps packets dropped due to an error in the ARP header parsing
|
||||
* - ``ip_1_parsing``
|
||||
- ``drop``
|
||||
- Traps packets dropped due to an error in the first IP header parsing.
|
||||
This packet trap could include packets which do not pass an IP checksum
|
||||
check, a header length check (a minimum of 20 bytes), which might suffer
|
||||
from packet truncation thus the total length field exceeds the received
|
||||
packet length etc
|
||||
* - ``ip_n_parsing``
|
||||
- ``drop``
|
||||
- Traps packets dropped due to an error in the parsing of the last IP
|
||||
header (the inner one in case of an IP over IP tunnel). The same common
|
||||
error checking is performed here as for the ip_1_parsing trap
|
||||
* - ``gre_parsing``
|
||||
- ``drop``
|
||||
- Traps packets dropped due to an error in the GRE header parsing
|
||||
* - ``udp_parsing``
|
||||
- ``drop``
|
||||
- Traps packets dropped due to an error in the UDP header parsing.
|
||||
This packet trap could include checksum errorrs, an improper UDP
|
||||
length detected (smaller than 8 bytes) or detection of header
|
||||
truncation.
|
||||
* - ``tcp_parsing``
|
||||
- ``drop``
|
||||
- Traps packets dropped due to an error in the TCP header parsing.
|
||||
This could include TCP checksum errors, improper combination of SYN, FIN
|
||||
and/or RESET etc.
|
||||
* - ``ipsec_parsing``
|
||||
- ``drop``
|
||||
- Traps packets dropped due to an error in the IPSEC header parsing
|
||||
* - ``sctp_parsing``
|
||||
- ``drop``
|
||||
- Traps packets dropped due to an error in the SCTP header parsing.
|
||||
This would mean that port number 0 was used or that the header is
|
||||
truncated.
|
||||
* - ``dccp_parsing``
|
||||
- ``drop``
|
||||
- Traps packets dropped due to an error in the DCCP header parsing
|
||||
* - ``gtp_parsing``
|
||||
- ``drop``
|
||||
- Traps packets dropped due to an error in the GTP header parsing
|
||||
* - ``esp_parsing``
|
||||
- ``drop``
|
||||
- Traps packets dropped due to an error in the ESP header parsing
|
||||
|
||||
Driver-specific Packet Traps
|
||||
============================
|
||||
@@ -509,6 +576,9 @@ narrow. The description of these groups must be added to the following table:
|
||||
* - ``acl_trap``
|
||||
- Contains packet traps for packets that were trapped (logged) by the
|
||||
device during ACL processing
|
||||
* - ``parser_error_drops``
|
||||
- Contains packet traps for packets that were marked by the device during
|
||||
parsing as erroneous
|
||||
|
||||
Packet Trap Policers
|
||||
====================
|
||||
|
@@ -69,6 +69,11 @@ The ``ice`` driver reports the following versions
|
||||
- The version of the DDP package that is active in the device. Note
|
||||
that both the name (as reported by ``fw.app.name``) and version are
|
||||
required to uniquely identify the package.
|
||||
* - ``fw.app.bundle_id``
|
||||
- 0xc0000001
|
||||
- Unique identifier for the DDP package loaded in the device. Also
|
||||
referred to as the DDP Track ID. Can be used to uniquely identify
|
||||
the specific DDP package.
|
||||
* - ``fw.netlist``
|
||||
- running
|
||||
- 1.1.2000-6.7.0
|
||||
@@ -81,6 +86,37 @@ The ``ice`` driver reports the following versions
|
||||
- 0xee16ced7
|
||||
- The first 4 bytes of the hash of the netlist module contents.
|
||||
|
||||
Flash Update
|
||||
============
|
||||
|
||||
The ``ice`` driver implements support for flash update using the
|
||||
``devlink-flash`` interface. It supports updating the device flash using a
|
||||
combined flash image that contains the ``fw.mgmt``, ``fw.undi``, and
|
||||
``fw.netlist`` components.
|
||||
|
||||
.. list-table:: List of supported overwrite modes
|
||||
:widths: 5 95
|
||||
|
||||
* - Bits
|
||||
- Behavior
|
||||
* - ``DEVLINK_FLASH_OVERWRITE_SETTINGS``
|
||||
- Do not preserve settings stored in the flash components being
|
||||
updated. This includes overwriting the port configuration that
|
||||
determines the number of physical functions the device will
|
||||
initialize with.
|
||||
* - ``DEVLINK_FLASH_OVERWRITE_SETTINGS`` and ``DEVLINK_FLASH_OVERWRITE_IDENTIFIERS``
|
||||
- Do not preserve either settings or identifiers. Overwrite everything
|
||||
in the flash with the contents from the provided image, without
|
||||
performing any preservation. This includes overwriting device
|
||||
identifying fields such as the MAC address, VPD area, and device
|
||||
serial number. It is expected that this combination be used with an
|
||||
image customized for the specific device.
|
||||
|
||||
The ice hardware does not support overwriting only identifiers while
|
||||
preserving settings, and thus ``DEVLINK_FLASH_OVERWRITE_IDENTIFIERS`` on its
|
||||
own will be rejected. If no overwrite mask is provided, the firmware will be
|
||||
instructed to preserve all settings and identifying fields when updating.
|
||||
|
||||
Regions
|
||||
=======
|
||||
|
||||
|
@@ -20,6 +20,7 @@ general.
|
||||
devlink-params
|
||||
devlink-region
|
||||
devlink-resource
|
||||
devlink-reload
|
||||
devlink-trap
|
||||
|
||||
Driver-specific documentation
|
||||
|
@@ -68,6 +68,7 @@ the flags may not apply to requests. Recognized flags are:
|
||||
================================= ===================================
|
||||
``ETHTOOL_FLAG_COMPACT_BITSETS`` use compact format bitsets in reply
|
||||
``ETHTOOL_FLAG_OMIT_REPLY`` omit optional reply (_SET and _ACT)
|
||||
``ETHTOOL_FLAG_STATS`` include optional device statistics
|
||||
================================= ===================================
|
||||
|
||||
New request flags should follow the general idea that if the flag is not set,
|
||||
@@ -991,8 +992,18 @@ Kernel response contents:
|
||||
``ETHTOOL_A_PAUSE_AUTONEG`` bool pause autonegotiation
|
||||
``ETHTOOL_A_PAUSE_RX`` bool receive pause frames
|
||||
``ETHTOOL_A_PAUSE_TX`` bool transmit pause frames
|
||||
``ETHTOOL_A_PAUSE_STATS`` nested pause statistics
|
||||
===================================== ====== ==========================
|
||||
|
||||
``ETHTOOL_A_PAUSE_STATS`` are reported if ``ETHTOOL_FLAG_STATS`` was set
|
||||
in ``ETHTOOL_A_HEADER_FLAGS``.
|
||||
It will be empty if driver did not report any statistics. Drivers fill in
|
||||
the statistics in the following structure:
|
||||
|
||||
.. kernel-doc:: include/linux/ethtool.h
|
||||
:identifiers: ethtool_pause_stats
|
||||
|
||||
Each member has a corresponding attribute defined.
|
||||
|
||||
PAUSE_SET
|
||||
============
|
||||
|
@@ -93,6 +93,7 @@ Contents:
|
||||
sctp
|
||||
secid
|
||||
seg6-sysctl
|
||||
statistics
|
||||
strparser
|
||||
switchdev
|
||||
sysfs-tagging
|
||||
|
@@ -134,6 +134,15 @@ PHY Support
|
||||
.. kernel-doc:: drivers/net/phy/phy.c
|
||||
:internal:
|
||||
|
||||
.. kernel-doc:: drivers/net/phy/phy-core.c
|
||||
:export:
|
||||
|
||||
.. kernel-doc:: drivers/net/phy/phy-c45.c
|
||||
:export:
|
||||
|
||||
.. kernel-doc:: include/linux/phy.h
|
||||
:internal:
|
||||
|
||||
.. kernel-doc:: drivers/net/phy/phy_device.c
|
||||
:export:
|
||||
|
||||
|
@@ -4,124 +4,364 @@
|
||||
L2TP
|
||||
====
|
||||
|
||||
This document describes how to use the kernel's L2TP drivers to
|
||||
provide L2TP functionality. L2TP is a protocol that tunnels one or
|
||||
more sessions over an IP tunnel. It is commonly used for VPNs
|
||||
(L2TP/IPSec) and by ISPs to tunnel subscriber PPP sessions over an IP
|
||||
network infrastructure. With L2TPv3, it is also useful as a Layer-2
|
||||
tunneling infrastructure.
|
||||
Layer 2 Tunneling Protocol (L2TP) allows L2 frames to be tunneled over
|
||||
an IP network.
|
||||
|
||||
Features
|
||||
This document covers the kernel's L2TP subsystem. It documents kernel
|
||||
APIs for application developers who want to use the L2TP subsystem and
|
||||
it provides some technical details about the internal implementation
|
||||
which may be useful to kernel developers and maintainers.
|
||||
|
||||
Overview
|
||||
========
|
||||
|
||||
L2TPv2 (PPP over L2TP (UDP tunnels)).
|
||||
L2TPv3 ethernet pseudowires.
|
||||
L2TPv3 PPP pseudowires.
|
||||
L2TPv3 IP encapsulation.
|
||||
Netlink sockets for L2TPv3 configuration management.
|
||||
The kernel's L2TP subsystem implements the datapath for L2TPv2 and
|
||||
L2TPv3. L2TPv2 is carried over UDP. L2TPv3 is carried over UDP or
|
||||
directly over IP (protocol 115).
|
||||
|
||||
History
|
||||
=======
|
||||
The L2TP RFCs define two basic kinds of L2TP packets: control packets
|
||||
(the "control plane"), and data packets (the "data plane"). The kernel
|
||||
deals only with data packets. The more complex control packets are
|
||||
handled by user space.
|
||||
|
||||
The original pppol2tp driver was introduced in 2.6.23 and provided
|
||||
L2TPv2 functionality (rfc2661). L2TPv2 is used to tunnel one or more PPP
|
||||
sessions over a UDP tunnel.
|
||||
An L2TP tunnel carries one or more L2TP sessions. Each tunnel is
|
||||
associated with a socket. Each session is associated with a virtual
|
||||
netdevice, e.g. ``pppN``, ``l2tpethN``, through which data frames pass
|
||||
to/from L2TP. Fields in the L2TP header identify the tunnel or session
|
||||
and whether it is a control or data packet. When tunnels and sessions
|
||||
are set up using the Linux kernel API, we're just setting up the L2TP
|
||||
data path. All aspects of the control protocol are to be handled by
|
||||
user space.
|
||||
|
||||
L2TPv3 (rfc3931) changes the protocol to allow different frame types
|
||||
to be passed over an L2TP tunnel by moving the PPP-specific parts of
|
||||
the protocol out of the core L2TP packet headers. Each frame type is
|
||||
known as a pseudowire type. Ethernet, PPP, HDLC, Frame Relay and ATM
|
||||
pseudowires for L2TP are defined in separate RFC standards. Another
|
||||
change for L2TPv3 is that it can be carried directly over IP with no
|
||||
UDP header (UDP is optional). It is also possible to create static
|
||||
unmanaged L2TPv3 tunnels manually without a control protocol
|
||||
(userspace daemon) to manage them.
|
||||
This split in responsibilities leads to a natural sequence of
|
||||
operations when establishing tunnels and sessions. The procedure looks
|
||||
like this:
|
||||
|
||||
To support L2TPv3, the original pppol2tp driver was split up to
|
||||
separate the L2TP and PPP functionality. Existing L2TPv2 userspace
|
||||
apps should be unaffected as the original pppol2tp sockets API is
|
||||
retained. L2TPv3, however, uses netlink to manage L2TPv3 tunnels and
|
||||
sessions.
|
||||
1) Create a tunnel socket. Exchange L2TP control protocol messages
|
||||
with the peer over that socket in order to establish a tunnel.
|
||||
|
||||
Design
|
||||
======
|
||||
2) Create a tunnel context in the kernel, using information
|
||||
obtained from the peer using the control protocol messages.
|
||||
|
||||
The L2TP protocol separates control and data frames. The L2TP kernel
|
||||
drivers handle only L2TP data frames; control frames are always
|
||||
handled by userspace. L2TP control frames carry messages between L2TP
|
||||
clients/servers and are used to setup / teardown tunnels and
|
||||
sessions. An L2TP client or server is implemented in userspace.
|
||||
3) Exchange L2TP control protocol messages with the peer over the
|
||||
tunnel socket in order to establish a session.
|
||||
|
||||
Each L2TP tunnel is implemented using a UDP or L2TPIP socket; L2TPIP
|
||||
provides L2TPv3 IP encapsulation (no UDP) and is implemented using a
|
||||
new l2tpip socket family. The tunnel socket is typically created by
|
||||
userspace, though for unmanaged L2TPv3 tunnels, the socket can also be
|
||||
created by the kernel. Each L2TP session (pseudowire) gets a network
|
||||
interface instance. In the case of PPP, these interfaces are created
|
||||
indirectly by pppd using a pppol2tp socket. In the case of ethernet,
|
||||
the netdevice is created upon a netlink request to create an L2TPv3
|
||||
ethernet pseudowire.
|
||||
4) Create a session context in the kernel using information
|
||||
obtained from the peer using the control protocol messages.
|
||||
|
||||
For PPP, the PPPoL2TP driver, net/l2tp/l2tp_ppp.c, provides a
|
||||
mechanism by which PPP frames carried through an L2TP session are
|
||||
passed through the kernel's PPP subsystem. The standard PPP daemon,
|
||||
pppd, handles all PPP interaction with the peer. PPP network
|
||||
interfaces are created for each local PPP endpoint. The kernel's PPP
|
||||
subsystem arranges for PPP control frames to be delivered to pppd,
|
||||
while data frames are forwarded as usual.
|
||||
L2TP APIs
|
||||
=========
|
||||
|
||||
For ethernet, the L2TPETH driver, net/l2tp/l2tp_eth.c, implements a
|
||||
netdevice driver, managing virtual ethernet devices, one per
|
||||
pseudowire. These interfaces can be managed using standard Linux tools
|
||||
such as "ip" and "ifconfig". If only IP frames are passed over the
|
||||
tunnel, the interface can be given an IP addresses of itself and its
|
||||
peer. If non-IP frames are to be passed over the tunnel, the interface
|
||||
can be added to a bridge using brctl. All L2TP datapath protocol
|
||||
functions are handled by the L2TP core driver.
|
||||
This section documents each userspace API of the L2TP subsystem.
|
||||
|
||||
Each tunnel and session within a tunnel is assigned a unique tunnel_id
|
||||
and session_id. These ids are carried in the L2TP header of every
|
||||
control and data packet. (Actually, in L2TPv3, the tunnel_id isn't
|
||||
present in data frames - it is inferred from the IP connection on
|
||||
which the packet was received.) The L2TP driver uses the ids to lookup
|
||||
internal tunnel and/or session contexts to determine how to handle the
|
||||
packet. Zero tunnel / session ids are treated specially - zero ids are
|
||||
never assigned to tunnels or sessions in the network. In the driver,
|
||||
the tunnel context keeps a reference to the tunnel UDP or L2TPIP
|
||||
socket. The session context holds data that lets the driver interface
|
||||
to the kernel's network frame type subsystems, i.e. PPP, ethernet.
|
||||
Tunnel Sockets
|
||||
--------------
|
||||
|
||||
Userspace Programming
|
||||
=====================
|
||||
L2TPv2 always uses UDP. L2TPv3 may use UDP or IP encapsulation.
|
||||
|
||||
For L2TPv2, there are a number of requirements on the userspace L2TP
|
||||
daemon in order to use the pppol2tp driver.
|
||||
To create a tunnel socket for use by L2TP, the standard POSIX
|
||||
socket API is used.
|
||||
|
||||
1. Use a UDP socket per tunnel.
|
||||
For example, for a tunnel using IPv4 addresses and UDP encapsulation::
|
||||
|
||||
2. Create a single PPPoL2TP socket per tunnel bound to a special null
|
||||
session id. This is used only for communicating with the driver but
|
||||
must remain open while the tunnel is active. Opening this tunnel
|
||||
management socket causes the driver to mark the tunnel socket as an
|
||||
L2TP UDP encapsulation socket and flags it for use by the
|
||||
referenced tunnel id. This hooks up the UDP receive path via
|
||||
udp_encap_rcv() in net/ipv4/udp.c. PPP data frames are never passed
|
||||
in this special PPPoX socket.
|
||||
int sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
||||
|
||||
3. Create a PPPoL2TP socket per L2TP session. This is typically done
|
||||
by starting pppd with the pppol2tp plugin and appropriate
|
||||
arguments. A PPPoL2TP tunnel management socket (Step 2) must be
|
||||
created before the first PPPoL2TP session socket is created.
|
||||
Or for a tunnel using IPv6 addresses and IP encapsulation::
|
||||
|
||||
int sockfd = socket(AF_INET6, SOCK_DGRAM, IPPROTO_L2TP);
|
||||
|
||||
UDP socket programming doesn't need to be covered here.
|
||||
|
||||
IPPROTO_L2TP is an IP protocol type implemented by the kernel's L2TP
|
||||
subsystem. The L2TPIP socket address is defined in struct
|
||||
sockaddr_l2tpip and struct sockaddr_l2tpip6 at
|
||||
`include/uapi/linux/l2tp.h`_. The address includes the L2TP tunnel
|
||||
(connection) id. To use L2TP IP encapsulation, an L2TPv3 application
|
||||
should bind the L2TPIP socket using the locally assigned
|
||||
tunnel id. When the peer's tunnel id and IP address is known, a
|
||||
connect must be done.
|
||||
|
||||
If the L2TP application needs to handle L2TPv3 tunnel setup requests
|
||||
from peers using L2TPIP, it must open a dedicated L2TPIP
|
||||
socket to listen for those requests and bind the socket using tunnel
|
||||
id 0 since tunnel setup requests are addressed to tunnel id 0.
|
||||
|
||||
An L2TP tunnel and all of its sessions are automatically closed when
|
||||
its tunnel socket is closed.
|
||||
|
||||
Netlink API
|
||||
-----------
|
||||
|
||||
L2TP applications use netlink to manage L2TP tunnel and session
|
||||
instances in the kernel. The L2TP netlink API is defined in
|
||||
`include/uapi/linux/l2tp.h`_.
|
||||
|
||||
L2TP uses `Generic Netlink`_ (GENL). Several commands are defined:
|
||||
Create, Delete, Modify and Get for tunnel and session
|
||||
instances, e.g. ``L2TP_CMD_TUNNEL_CREATE``. The API header lists the
|
||||
netlink attribute types that can be used with each command.
|
||||
|
||||
Tunnel and session instances are identified by a locally unique
|
||||
32-bit id. L2TP tunnel ids are given by ``L2TP_ATTR_CONN_ID`` and
|
||||
``L2TP_ATTR_PEER_CONN_ID`` attributes and L2TP session ids are given
|
||||
by ``L2TP_ATTR_SESSION_ID`` and ``L2TP_ATTR_PEER_SESSION_ID``
|
||||
attributes. If netlink is used to manage L2TPv2 tunnel and session
|
||||
instances, the L2TPv2 16-bit tunnel/session id is cast to a 32-bit
|
||||
value in these attributes.
|
||||
|
||||
In the ``L2TP_CMD_TUNNEL_CREATE`` command, ``L2TP_ATTR_FD`` tells the
|
||||
kernel the tunnel socket fd being used. If not specified, the kernel
|
||||
creates a kernel socket for the tunnel, using IP parameters set in
|
||||
``L2TP_ATTR_IP[6]_SADDR``, ``L2TP_ATTR_IP[6]_DADDR``,
|
||||
``L2TP_ATTR_UDP_SPORT``, ``L2TP_ATTR_UDP_DPORT`` attributes. Kernel
|
||||
sockets are used to implement unmanaged L2TPv3 tunnels (iproute2's "ip
|
||||
l2tp" commands). If ``L2TP_ATTR_FD`` is given, it must be a socket fd
|
||||
that is already bound and connected. There is more information about
|
||||
unmanaged tunnels later in this document.
|
||||
|
||||
``L2TP_CMD_TUNNEL_CREATE`` attributes:-
|
||||
|
||||
================== ======== ===
|
||||
Attribute Required Use
|
||||
================== ======== ===
|
||||
CONN_ID Y Sets the tunnel (connection) id.
|
||||
PEER_CONN_ID Y Sets the peer tunnel (connection) id.
|
||||
PROTO_VERSION Y Protocol version. 2 or 3.
|
||||
ENCAP_TYPE Y Encapsulation type: UDP or IP.
|
||||
FD N Tunnel socket file descriptor.
|
||||
UDP_CSUM N Enable IPv4 UDP checksums. Used only if FD is
|
||||
not set.
|
||||
UDP_ZERO_CSUM6_TX N Zero IPv6 UDP checksum on transmit. Used only
|
||||
if FD is not set.
|
||||
UDP_ZERO_CSUM6_RX N Zero IPv6 UDP checksum on receive. Used only if
|
||||
FD is not set.
|
||||
IP_SADDR N IPv4 source address. Used only if FD is not
|
||||
set.
|
||||
IP_DADDR N IPv4 destination address. Used only if FD is
|
||||
not set.
|
||||
UDP_SPORT N UDP source port. Used only if FD is not set.
|
||||
UDP_DPORT N UDP destination port. Used only if FD is not
|
||||
set.
|
||||
IP6_SADDR N IPv6 source address. Used only if FD is not
|
||||
set.
|
||||
IP6_DADDR N IPv6 destination address. Used only if FD is
|
||||
not set.
|
||||
DEBUG N Debug flags.
|
||||
================== ======== ===
|
||||
|
||||
``L2TP_CMD_TUNNEL_DESTROY`` attributes:-
|
||||
|
||||
================== ======== ===
|
||||
Attribute Required Use
|
||||
================== ======== ===
|
||||
CONN_ID Y Identifies the tunnel id to be destroyed.
|
||||
================== ======== ===
|
||||
|
||||
``L2TP_CMD_TUNNEL_MODIFY`` attributes:-
|
||||
|
||||
================== ======== ===
|
||||
Attribute Required Use
|
||||
================== ======== ===
|
||||
CONN_ID Y Identifies the tunnel id to be modified.
|
||||
DEBUG N Debug flags.
|
||||
================== ======== ===
|
||||
|
||||
``L2TP_CMD_TUNNEL_GET`` attributes:-
|
||||
|
||||
================== ======== ===
|
||||
Attribute Required Use
|
||||
================== ======== ===
|
||||
CONN_ID N Identifies the tunnel id to be queried.
|
||||
Ignored in DUMP requests.
|
||||
================== ======== ===
|
||||
|
||||
``L2TP_CMD_SESSION_CREATE`` attributes:-
|
||||
|
||||
================== ======== ===
|
||||
Attribute Required Use
|
||||
================== ======== ===
|
||||
CONN_ID Y The parent tunnel id.
|
||||
SESSION_ID Y Sets the session id.
|
||||
PEER_SESSION_ID Y Sets the parent session id.
|
||||
PW_TYPE Y Sets the pseudowire type.
|
||||
DEBUG N Debug flags.
|
||||
RECV_SEQ N Enable rx data sequence numbers.
|
||||
SEND_SEQ N Enable tx data sequence numbers.
|
||||
LNS_MODE N Enable LNS mode (auto-enable data sequence
|
||||
numbers).
|
||||
RECV_TIMEOUT N Timeout to wait when reordering received
|
||||
packets.
|
||||
L2SPEC_TYPE N Sets layer2-specific-sublayer type (L2TPv3
|
||||
only).
|
||||
COOKIE N Sets optional cookie (L2TPv3 only).
|
||||
PEER_COOKIE N Sets optional peer cookie (L2TPv3 only).
|
||||
IFNAME N Sets interface name (L2TPv3 only).
|
||||
================== ======== ===
|
||||
|
||||
For Ethernet session types, this will create an l2tpeth virtual
|
||||
interface which can then be configured as required. For PPP session
|
||||
types, a PPPoL2TP socket must also be opened and connected, mapping it
|
||||
onto the new session. This is covered in "PPPoL2TP Sockets" later.
|
||||
|
||||
``L2TP_CMD_SESSION_DESTROY`` attributes:-
|
||||
|
||||
================== ======== ===
|
||||
Attribute Required Use
|
||||
================== ======== ===
|
||||
CONN_ID Y Identifies the parent tunnel id of the session
|
||||
to be destroyed.
|
||||
SESSION_ID Y Identifies the session id to be destroyed.
|
||||
IFNAME N Identifies the session by interface name. If
|
||||
set, this overrides any CONN_ID and SESSION_ID
|
||||
attributes. Currently supported for L2TPv3
|
||||
Ethernet sessions only.
|
||||
================== ======== ===
|
||||
|
||||
``L2TP_CMD_SESSION_MODIFY`` attributes:-
|
||||
|
||||
================== ======== ===
|
||||
Attribute Required Use
|
||||
================== ======== ===
|
||||
CONN_ID Y Identifies the parent tunnel id of the session
|
||||
to be modified.
|
||||
SESSION_ID Y Identifies the session id to be modified.
|
||||
IFNAME N Identifies the session by interface name. If
|
||||
set, this overrides any CONN_ID and SESSION_ID
|
||||
attributes. Currently supported for L2TPv3
|
||||
Ethernet sessions only.
|
||||
DEBUG N Debug flags.
|
||||
RECV_SEQ N Enable rx data sequence numbers.
|
||||
SEND_SEQ N Enable tx data sequence numbers.
|
||||
LNS_MODE N Enable LNS mode (auto-enable data sequence
|
||||
numbers).
|
||||
RECV_TIMEOUT N Timeout to wait when reordering received
|
||||
packets.
|
||||
================== ======== ===
|
||||
|
||||
``L2TP_CMD_SESSION_GET`` attributes:-
|
||||
|
||||
================== ======== ===
|
||||
Attribute Required Use
|
||||
================== ======== ===
|
||||
CONN_ID N Identifies the tunnel id to be queried.
|
||||
Ignored for DUMP requests.
|
||||
SESSION_ID N Identifies the session id to be queried.
|
||||
Ignored for DUMP requests.
|
||||
IFNAME N Identifies the session by interface name.
|
||||
If set, this overrides any CONN_ID and
|
||||
SESSION_ID attributes. Ignored for DUMP
|
||||
requests. Currently supported for L2TPv3
|
||||
Ethernet sessions only.
|
||||
================== ======== ===
|
||||
|
||||
Application developers should refer to `include/uapi/linux/l2tp.h`_ for
|
||||
netlink command and attribute definitions.
|
||||
|
||||
Sample userspace code using libmnl_:
|
||||
|
||||
- Open L2TP netlink socket::
|
||||
|
||||
struct nl_sock *nl_sock;
|
||||
int l2tp_nl_family_id;
|
||||
|
||||
nl_sock = nl_socket_alloc();
|
||||
genl_connect(nl_sock);
|
||||
genl_id = genl_ctrl_resolve(nl_sock, L2TP_GENL_NAME);
|
||||
|
||||
- Create a tunnel::
|
||||
|
||||
struct nlmsghdr *nlh;
|
||||
struct genlmsghdr *gnlh;
|
||||
|
||||
nlh = mnl_nlmsg_put_header(buf);
|
||||
nlh->nlmsg_type = genl_id; /* assigned to genl socket */
|
||||
nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
|
||||
nlh->nlmsg_seq = seq;
|
||||
|
||||
gnlh = mnl_nlmsg_put_extra_header(nlh, sizeof(*gnlh));
|
||||
gnlh->cmd = L2TP_CMD_TUNNEL_CREATE;
|
||||
gnlh->version = L2TP_GENL_VERSION;
|
||||
gnlh->reserved = 0;
|
||||
|
||||
mnl_attr_put_u32(nlh, L2TP_ATTR_FD, tunl_sock_fd);
|
||||
mnl_attr_put_u32(nlh, L2TP_ATTR_CONN_ID, tid);
|
||||
mnl_attr_put_u32(nlh, L2TP_ATTR_PEER_CONN_ID, peer_tid);
|
||||
mnl_attr_put_u8(nlh, L2TP_ATTR_PROTO_VERSION, protocol_version);
|
||||
mnl_attr_put_u16(nlh, L2TP_ATTR_ENCAP_TYPE, encap);
|
||||
|
||||
- Create a session::
|
||||
|
||||
struct nlmsghdr *nlh;
|
||||
struct genlmsghdr *gnlh;
|
||||
|
||||
nlh = mnl_nlmsg_put_header(buf);
|
||||
nlh->nlmsg_type = genl_id; /* assigned to genl socket */
|
||||
nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
|
||||
nlh->nlmsg_seq = seq;
|
||||
|
||||
gnlh = mnl_nlmsg_put_extra_header(nlh, sizeof(*gnlh));
|
||||
gnlh->cmd = L2TP_CMD_SESSION_CREATE;
|
||||
gnlh->version = L2TP_GENL_VERSION;
|
||||
gnlh->reserved = 0;
|
||||
|
||||
mnl_attr_put_u32(nlh, L2TP_ATTR_CONN_ID, tid);
|
||||
mnl_attr_put_u32(nlh, L2TP_ATTR_PEER_CONN_ID, peer_tid);
|
||||
mnl_attr_put_u32(nlh, L2TP_ATTR_SESSION_ID, sid);
|
||||
mnl_attr_put_u32(nlh, L2TP_ATTR_PEER_SESSION_ID, peer_sid);
|
||||
mnl_attr_put_u16(nlh, L2TP_ATTR_PW_TYPE, pwtype);
|
||||
/* there are other session options which can be set using netlink
|
||||
* attributes during session creation -- see l2tp.h
|
||||
*/
|
||||
|
||||
- Delete a session::
|
||||
|
||||
struct nlmsghdr *nlh;
|
||||
struct genlmsghdr *gnlh;
|
||||
|
||||
nlh = mnl_nlmsg_put_header(buf);
|
||||
nlh->nlmsg_type = genl_id; /* assigned to genl socket */
|
||||
nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
|
||||
nlh->nlmsg_seq = seq;
|
||||
|
||||
gnlh = mnl_nlmsg_put_extra_header(nlh, sizeof(*gnlh));
|
||||
gnlh->cmd = L2TP_CMD_SESSION_DELETE;
|
||||
gnlh->version = L2TP_GENL_VERSION;
|
||||
gnlh->reserved = 0;
|
||||
|
||||
mnl_attr_put_u32(nlh, L2TP_ATTR_CONN_ID, tid);
|
||||
mnl_attr_put_u32(nlh, L2TP_ATTR_SESSION_ID, sid);
|
||||
|
||||
- Delete a tunnel and all of its sessions (if any)::
|
||||
|
||||
struct nlmsghdr *nlh;
|
||||
struct genlmsghdr *gnlh;
|
||||
|
||||
nlh = mnl_nlmsg_put_header(buf);
|
||||
nlh->nlmsg_type = genl_id; /* assigned to genl socket */
|
||||
nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
|
||||
nlh->nlmsg_seq = seq;
|
||||
|
||||
gnlh = mnl_nlmsg_put_extra_header(nlh, sizeof(*gnlh));
|
||||
gnlh->cmd = L2TP_CMD_TUNNEL_DELETE;
|
||||
gnlh->version = L2TP_GENL_VERSION;
|
||||
gnlh->reserved = 0;
|
||||
|
||||
mnl_attr_put_u32(nlh, L2TP_ATTR_CONN_ID, tid);
|
||||
|
||||
PPPoL2TP Session Socket API
|
||||
---------------------------
|
||||
|
||||
For PPP session types, a PPPoL2TP socket must be opened and connected
|
||||
to the L2TP session.
|
||||
|
||||
When creating PPPoL2TP sockets, the application provides information
|
||||
to the driver about the socket in a socket connect() call. Source and
|
||||
destination tunnel and session ids are provided, as well as the file
|
||||
descriptor of a UDP socket. See struct pppol2tp_addr in
|
||||
include/linux/if_pppol2tp.h. Note that zero tunnel / session ids are
|
||||
treated specially. When creating the per-tunnel PPPoL2TP management
|
||||
socket in Step 2 above, zero source and destination session ids are
|
||||
specified, which tells the driver to prepare the supplied UDP file
|
||||
descriptor for use as an L2TP tunnel socket.
|
||||
to the kernel about the tunnel and session in a socket connect()
|
||||
call. Source and destination tunnel and session ids are provided, as
|
||||
well as the file descriptor of a UDP or L2TPIP socket. See struct
|
||||
pppol2tp_addr in `include/linux/if_pppol2tp.h`_. For historical reasons,
|
||||
there are unfortunately slightly different address structures for
|
||||
L2TPv2/L2TPv3 IPv4/IPv6 tunnels and userspace must use the appropriate
|
||||
structure that matches the tunnel socket type.
|
||||
|
||||
Userspace may control behavior of the tunnel or session using
|
||||
setsockopt and ioctl on the PPPoX socket. The following socket
|
||||
@@ -138,159 +378,20 @@ LNSMODE - 0 => act as LAC.
|
||||
REORDERTO reorder timeout (in millisecs). If 0, don't try to reorder.
|
||||
========= ===========================================================
|
||||
|
||||
Only the DEBUG option is supported by the special tunnel management
|
||||
PPPoX socket.
|
||||
|
||||
In addition to the standard PPP ioctls, a PPPIOCGL2TPSTATS is provided
|
||||
to retrieve tunnel and session statistics from the kernel using the
|
||||
PPPoX socket of the appropriate tunnel or session.
|
||||
|
||||
For L2TPv3, userspace must use the netlink API defined in
|
||||
include/linux/l2tp.h to manage tunnel and session contexts. The
|
||||
general procedure to create a new L2TP tunnel with one session is:-
|
||||
Sample userspace code:
|
||||
|
||||
1. Open a GENL socket using L2TP_GENL_NAME for configuring the kernel
|
||||
using netlink.
|
||||
|
||||
2. Create a UDP or L2TPIP socket for the tunnel.
|
||||
|
||||
3. Create a new L2TP tunnel using a L2TP_CMD_TUNNEL_CREATE
|
||||
request. Set attributes according to desired tunnel parameters,
|
||||
referencing the UDP or L2TPIP socket created in the previous step.
|
||||
|
||||
4. Create a new L2TP session in the tunnel using a
|
||||
L2TP_CMD_SESSION_CREATE request.
|
||||
|
||||
The tunnel and all of its sessions are closed when the tunnel socket
|
||||
is closed. The netlink API may also be used to delete sessions and
|
||||
tunnels. Configuration and status info may be set or read using netlink.
|
||||
|
||||
The L2TP driver also supports static (unmanaged) L2TPv3 tunnels. These
|
||||
are where there is no L2TP control message exchange with the peer to
|
||||
setup the tunnel; the tunnel is configured manually at each end of the
|
||||
tunnel. There is no need for an L2TP userspace application in this
|
||||
case -- the tunnel socket is created by the kernel and configured
|
||||
using parameters sent in the L2TP_CMD_TUNNEL_CREATE netlink
|
||||
request. The "ip" utility of iproute2 has commands for managing static
|
||||
L2TPv3 tunnels; do "ip l2tp help" for more information.
|
||||
|
||||
Debugging
|
||||
=========
|
||||
|
||||
The driver supports a flexible debug scheme where kernel trace
|
||||
messages may be optionally enabled per tunnel and per session. Care is
|
||||
needed when debugging a live system since the messages are not
|
||||
rate-limited and a busy system could be swamped. Userspace uses
|
||||
setsockopt on the PPPoX socket to set a debug mask.
|
||||
|
||||
The following debug mask bits are available:
|
||||
|
||||
================ ==============================
|
||||
L2TP_MSG_DEBUG verbose debug (if compiled in)
|
||||
L2TP_MSG_CONTROL userspace - kernel interface
|
||||
L2TP_MSG_SEQ sequence numbers handling
|
||||
L2TP_MSG_DATA data packets
|
||||
================ ==============================
|
||||
|
||||
If enabled, files under a l2tp debugfs directory can be used to dump
|
||||
kernel state about L2TP tunnels and sessions. To access it, the
|
||||
debugfs filesystem must first be mounted::
|
||||
|
||||
# mount -t debugfs debugfs /debug
|
||||
|
||||
Files under the l2tp directory can then be accessed::
|
||||
|
||||
# cat /debug/l2tp/tunnels
|
||||
|
||||
The debugfs files should not be used by applications to obtain L2TP
|
||||
state information because the file format is subject to change. It is
|
||||
implemented to provide extra debug information to help diagnose
|
||||
problems.) Users should use the netlink API.
|
||||
|
||||
/proc/net/pppol2tp is also provided for backwards compatibility with
|
||||
the original pppol2tp driver. It lists information about L2TPv2
|
||||
tunnels and sessions only. Its use is discouraged.
|
||||
|
||||
Unmanaged L2TPv3 Tunnels
|
||||
========================
|
||||
|
||||
Some commercial L2TP products support unmanaged L2TPv3 ethernet
|
||||
tunnels, where there is no L2TP control protocol; tunnels are
|
||||
configured at each side manually. New commands are available in
|
||||
iproute2's ip utility to support this.
|
||||
|
||||
To create an L2TPv3 ethernet pseudowire between local host 192.168.1.1
|
||||
and peer 192.168.1.2, using IP addresses 10.5.1.1 and 10.5.1.2 for the
|
||||
tunnel endpoints::
|
||||
|
||||
# ip l2tp add tunnel tunnel_id 1 peer_tunnel_id 1 udp_sport 5000 \
|
||||
udp_dport 5000 encap udp local 192.168.1.1 remote 192.168.1.2
|
||||
# ip l2tp add session tunnel_id 1 session_id 1 peer_session_id 1
|
||||
# ip -s -d show dev l2tpeth0
|
||||
# ip addr add 10.5.1.2/32 peer 10.5.1.1/32 dev l2tpeth0
|
||||
# ip li set dev l2tpeth0 up
|
||||
|
||||
Choose IP addresses to be the address of a local IP interface and that
|
||||
of the remote system. The IP addresses of the l2tpeth0 interface can be
|
||||
anything suitable.
|
||||
|
||||
Repeat the above at the peer, with ports, tunnel/session ids and IP
|
||||
addresses reversed. The tunnel and session IDs can be any non-zero
|
||||
32-bit number, but the values must be reversed at the peer.
|
||||
|
||||
======================== ===================
|
||||
Host 1 Host2
|
||||
======================== ===================
|
||||
udp_sport=5000 udp_sport=5001
|
||||
udp_dport=5001 udp_dport=5000
|
||||
tunnel_id=42 tunnel_id=45
|
||||
peer_tunnel_id=45 peer_tunnel_id=42
|
||||
session_id=128 session_id=5196755
|
||||
peer_session_id=5196755 peer_session_id=128
|
||||
======================== ===================
|
||||
|
||||
When done at both ends of the tunnel, it should be possible to send
|
||||
data over the network. e.g.::
|
||||
|
||||
# ping 10.5.1.1
|
||||
|
||||
|
||||
Sample Userspace Code
|
||||
=====================
|
||||
|
||||
1. Create tunnel management PPPoX socket::
|
||||
|
||||
kernel_fd = socket(AF_PPPOX, SOCK_DGRAM, PX_PROTO_OL2TP);
|
||||
if (kernel_fd >= 0) {
|
||||
struct sockaddr_pppol2tp sax;
|
||||
struct sockaddr_in const *peer_addr;
|
||||
|
||||
peer_addr = l2tp_tunnel_get_peer_addr(tunnel);
|
||||
memset(&sax, 0, sizeof(sax));
|
||||
sax.sa_family = AF_PPPOX;
|
||||
sax.sa_protocol = PX_PROTO_OL2TP;
|
||||
sax.pppol2tp.fd = udp_fd; /* fd of tunnel UDP socket */
|
||||
sax.pppol2tp.addr.sin_addr.s_addr = peer_addr->sin_addr.s_addr;
|
||||
sax.pppol2tp.addr.sin_port = peer_addr->sin_port;
|
||||
sax.pppol2tp.addr.sin_family = AF_INET;
|
||||
sax.pppol2tp.s_tunnel = tunnel_id;
|
||||
sax.pppol2tp.s_session = 0; /* special case: mgmt socket */
|
||||
sax.pppol2tp.d_tunnel = 0;
|
||||
sax.pppol2tp.d_session = 0; /* special case: mgmt socket */
|
||||
|
||||
if(connect(kernel_fd, (struct sockaddr *)&sax, sizeof(sax) ) < 0 ) {
|
||||
perror("connect failed");
|
||||
result = -errno;
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
2. Create session PPPoX data socket::
|
||||
- Create session PPPoX data socket::
|
||||
|
||||
struct sockaddr_pppol2tp sax;
|
||||
int fd;
|
||||
|
||||
/* Note, the target socket must be bound already, else it will not be ready */
|
||||
/* Note, the tunnel socket must be bound already, else it
|
||||
* will not be ready
|
||||
*/
|
||||
sax.sa_family = AF_PPPOX;
|
||||
sax.sa_protocol = PX_PROTO_OL2TP;
|
||||
sax.pppol2tp.fd = tunnel_fd;
|
||||
@@ -303,7 +404,7 @@ Sample Userspace Code
|
||||
sax.pppol2tp.d_session = peer_session_id;
|
||||
|
||||
/* session_fd is the fd of the session's PPPoL2TP socket.
|
||||
* tunnel_fd is the fd of the tunnel UDP socket.
|
||||
* tunnel_fd is the fd of the tunnel UDP / L2TPIP socket.
|
||||
*/
|
||||
fd = connect(session_fd, (struct sockaddr *)&sax, sizeof(sax));
|
||||
if (fd < 0 ) {
|
||||
@@ -311,48 +412,266 @@ Sample Userspace Code
|
||||
}
|
||||
return 0;
|
||||
|
||||
Old L2TPv2-only API
|
||||
-------------------
|
||||
|
||||
When L2TP was first added to the Linux kernel in 2.6.23, it
|
||||
implemented only L2TPv2 and did not include a netlink API. Instead,
|
||||
tunnel and session instances in the kernel were managed directly using
|
||||
only PPPoL2TP sockets. The PPPoL2TP socket is used as described in
|
||||
section "PPPoL2TP Session Socket API" but tunnel and session instances
|
||||
are automatically created on a connect() of the socket instead of
|
||||
being created by a separate netlink request:
|
||||
|
||||
- Tunnels are managed using a tunnel management socket which is a
|
||||
dedicated PPPoL2TP socket, connected to (invalid) session
|
||||
id 0. The L2TP tunnel instance is created when the PPPoL2TP
|
||||
tunnel management socket is connected and is destroyed when the
|
||||
socket is closed.
|
||||
|
||||
- Session instances are created in the kernel when a PPPoL2TP
|
||||
socket is connected to a non-zero session id. Session parameters
|
||||
are set using setsockopt. The L2TP session instance is destroyed
|
||||
when the socket is closed.
|
||||
|
||||
This API is still supported but its use is discouraged. Instead, new
|
||||
L2TPv2 applications should use netlink to first create the tunnel and
|
||||
session, then create a PPPoL2TP socket for the session.
|
||||
|
||||
Unmanaged L2TPv3 tunnels
|
||||
------------------------
|
||||
|
||||
The kernel L2TP subsystem also supports static (unmanaged) L2TPv3
|
||||
tunnels. Unmanaged tunnels have no userspace tunnel socket, and
|
||||
exchange no control messages with the peer to set up the tunnel; the
|
||||
tunnel is configured manually at each end of the tunnel. All
|
||||
configuration is done using netlink. There is no need for an L2TP
|
||||
userspace application in this case -- the tunnel socket is created by
|
||||
the kernel and configured using parameters sent in the
|
||||
``L2TP_CMD_TUNNEL_CREATE`` netlink request. The ``ip`` utility of
|
||||
``iproute2`` has commands for managing static L2TPv3 tunnels; do ``ip
|
||||
l2tp help`` for more information.
|
||||
|
||||
Debugging
|
||||
---------
|
||||
|
||||
The L2TP subsystem offers a range of debugging interfaces through the
|
||||
debugfs filesystem.
|
||||
|
||||
To access these interfaces, the debugfs filesystem must first be mounted::
|
||||
|
||||
# mount -t debugfs debugfs /debug
|
||||
|
||||
Files under the l2tp directory can then be accessed, providing a summary
|
||||
of the current population of tunnel and session contexts existing in the
|
||||
kernel::
|
||||
|
||||
# cat /debug/l2tp/tunnels
|
||||
|
||||
The debugfs files should not be used by applications to obtain L2TP
|
||||
state information because the file format is subject to change. It is
|
||||
implemented to provide extra debug information to help diagnose
|
||||
problems. Applications should instead use the netlink API.
|
||||
|
||||
In addition the L2TP subsystem implements tracepoints using the standard
|
||||
kernel event tracing API. The available L2TP events can be reviewed as
|
||||
follows::
|
||||
|
||||
# find /debug/tracing/events/l2tp
|
||||
|
||||
Finally, /proc/net/pppol2tp is also provided for backwards compatibility
|
||||
with the original pppol2tp code. It lists information about L2TPv2
|
||||
tunnels and sessions only. Its use is discouraged.
|
||||
|
||||
Internal Implementation
|
||||
=======================
|
||||
|
||||
The driver keeps a struct l2tp_tunnel context per L2TP tunnel and a
|
||||
struct l2tp_session context for each session. The l2tp_tunnel is
|
||||
always associated with a UDP or L2TP/IP socket and keeps a list of
|
||||
sessions in the tunnel. The l2tp_session context keeps kernel state
|
||||
about the session. It has private data which is used for data specific
|
||||
to the session type. With L2TPv2, the session always carried PPP
|
||||
traffic. With L2TPv3, the session can also carry ethernet frames
|
||||
(ethernet pseudowire) or other data types such as ATM, HDLC or Frame
|
||||
Relay.
|
||||
This section is for kernel developers and maintainers.
|
||||
|
||||
When a tunnel is first opened, the reference count on the socket is
|
||||
increased using sock_hold(). This ensures that the kernel socket
|
||||
cannot be removed while L2TP's data structures reference it.
|
||||
Sockets
|
||||
-------
|
||||
|
||||
Some L2TP sessions also have a socket (PPP pseudowires) while others
|
||||
do not (ethernet pseudowires). We can't use the socket reference count
|
||||
as the reference count for session contexts. The L2TP implementation
|
||||
therefore has its own internal reference counts on the session
|
||||
contexts.
|
||||
UDP sockets are implemented by the networking core. When an L2TP
|
||||
tunnel is created using a UDP socket, the socket is set up as an
|
||||
encapsulated UDP socket by setting encap_rcv and encap_destroy
|
||||
callbacks on the UDP socket. l2tp_udp_encap_recv is called when
|
||||
packets are received on the socket. l2tp_udp_encap_destroy is called
|
||||
when userspace closes the socket.
|
||||
|
||||
To Do
|
||||
=====
|
||||
L2TPIP sockets are implemented in `net/l2tp/l2tp_ip.c`_ and
|
||||
`net/l2tp/l2tp_ip6.c`_.
|
||||
|
||||
Add L2TP tunnel switching support. This would route tunneled traffic
|
||||
from one L2TP tunnel into another. Specified in
|
||||
http://tools.ietf.org/html/draft-ietf-l2tpext-tunnel-switching-08
|
||||
Tunnels
|
||||
-------
|
||||
|
||||
Add L2TPv3 VLAN pseudowire support.
|
||||
The kernel keeps a struct l2tp_tunnel context per L2TP tunnel. The
|
||||
l2tp_tunnel is always associated with a UDP or L2TP/IP socket and
|
||||
keeps a list of sessions in the tunnel. When a tunnel is first
|
||||
registered with L2TP core, the reference count on the socket is
|
||||
increased. This ensures that the socket cannot be removed while L2TP's
|
||||
data structures reference it.
|
||||
|
||||
Add L2TPv3 IP pseudowire support.
|
||||
Tunnels are identified by a unique tunnel id. The id is 16-bit for
|
||||
L2TPv2 and 32-bit for L2TPv3. Internally, the id is stored as a 32-bit
|
||||
value.
|
||||
|
||||
Add L2TPv3 ATM pseudowire support.
|
||||
Tunnels are kept in a per-net list, indexed by tunnel id. The tunnel
|
||||
id namespace is shared by L2TPv2 and L2TPv3. The tunnel context can be
|
||||
derived from the socket's sk_user_data.
|
||||
|
||||
Handling tunnel socket close is perhaps the most tricky part of the
|
||||
L2TP implementation. If userspace closes a tunnel socket, the L2TP
|
||||
tunnel and all of its sessions must be closed and destroyed. Since the
|
||||
tunnel context holds a ref on the tunnel socket, the socket's
|
||||
sk_destruct won't be called until the tunnel sock_put's its
|
||||
socket. For UDP sockets, when userspace closes the tunnel socket, the
|
||||
socket's encap_destroy handler is invoked, which L2TP uses to initiate
|
||||
its tunnel close actions. For L2TPIP sockets, the socket's close
|
||||
handler initiates the same tunnel close actions. All sessions are
|
||||
first closed. Each session drops its tunnel ref. When the tunnel ref
|
||||
reaches zero, the tunnel puts its socket ref. When the socket is
|
||||
eventually destroyed, it's sk_destruct finally frees the L2TP tunnel
|
||||
context.
|
||||
|
||||
Sessions
|
||||
--------
|
||||
|
||||
The kernel keeps a struct l2tp_session context for each session. Each
|
||||
session has private data which is used for data specific to the
|
||||
session type. With L2TPv2, the session always carries PPP
|
||||
traffic. With L2TPv3, the session can carry Ethernet frames (Ethernet
|
||||
pseudowire) or other data types such as PPP, ATM, HDLC or Frame
|
||||
Relay. Linux currently implements only Ethernet and PPP session types.
|
||||
|
||||
Some L2TP session types also have a socket (PPP pseudowires) while
|
||||
others do not (Ethernet pseudowires). We can't therefore use the
|
||||
socket reference count as the reference count for session
|
||||
contexts. The L2TP implementation therefore has its own internal
|
||||
reference counts on the session contexts.
|
||||
|
||||
Like tunnels, L2TP sessions are identified by a unique
|
||||
session id. Just as with tunnel ids, the session id is 16-bit for
|
||||
L2TPv2 and 32-bit for L2TPv3. Internally, the id is stored as a 32-bit
|
||||
value.
|
||||
|
||||
Sessions hold a ref on their parent tunnel to ensure that the tunnel
|
||||
stays extant while one or more sessions references it.
|
||||
|
||||
Sessions are kept in a per-tunnel list, indexed by session id. L2TPv3
|
||||
sessions are also kept in a per-net list indexed by session id,
|
||||
because L2TPv3 session ids are unique across all tunnels and L2TPv3
|
||||
data packets do not contain a tunnel id in the header. This list is
|
||||
therefore needed to find the session context associated with a
|
||||
received data packet when the tunnel context cannot be derived from
|
||||
the tunnel socket.
|
||||
|
||||
Although the L2TPv3 RFC specifies that L2TPv3 session ids are not
|
||||
scoped by the tunnel, the kernel does not police this for L2TPv3 UDP
|
||||
tunnels and does not add sessions of L2TPv3 UDP tunnels into the
|
||||
per-net session list. In the UDP receive code, we must trust that the
|
||||
tunnel can be identified using the tunnel socket's sk_user_data and
|
||||
lookup the session in the tunnel's session list instead of the per-net
|
||||
session list.
|
||||
|
||||
PPP
|
||||
---
|
||||
|
||||
`net/l2tp/l2tp_ppp.c`_ implements the PPPoL2TP socket family. Each PPP
|
||||
session has a PPPoL2TP socket.
|
||||
|
||||
The PPPoL2TP socket's sk_user_data references the l2tp_session.
|
||||
|
||||
Userspace sends and receives PPP packets over L2TP using a PPPoL2TP
|
||||
socket. Only PPP control frames pass over this socket: PPP data
|
||||
packets are handled entirely by the kernel, passing between the L2TP
|
||||
session and its associated ``pppN`` netdev through the PPP channel
|
||||
interface of the kernel PPP subsystem.
|
||||
|
||||
The L2TP PPP implementation handles the closing of a PPPoL2TP socket
|
||||
by closing its corresponding L2TP session. This is complicated because
|
||||
it must consider racing with netlink session create/destroy requests
|
||||
and pppol2tp_connect trying to reconnect with a session that is in the
|
||||
process of being closed. Unlike tunnels, PPP sessions do not hold a
|
||||
ref on their associated socket, so code must be careful to sock_hold
|
||||
the socket where necessary. For all the details, see commit
|
||||
3d609342cc04129ff7568e19316ce3d7451a27e8.
|
||||
|
||||
Ethernet
|
||||
--------
|
||||
|
||||
`net/l2tp/l2tp_eth.c`_ implements L2TPv3 Ethernet pseudowires. It
|
||||
manages a netdev for each session.
|
||||
|
||||
L2TP Ethernet sessions are created and destroyed by netlink request,
|
||||
or are destroyed when the tunnel is destroyed. Unlike PPP sessions,
|
||||
Ethernet sessions do not have an associated socket.
|
||||
|
||||
Miscellaneous
|
||||
=============
|
||||
|
||||
The L2TP drivers were developed as part of the OpenL2TP project by
|
||||
Katalix Systems Ltd. OpenL2TP is a full-featured L2TP client / server,
|
||||
designed from the ground up to have the L2TP datapath in the
|
||||
kernel. The project also implemented the pppol2tp plugin for pppd
|
||||
which allows pppd to use the kernel driver. Details can be found at
|
||||
http://www.openl2tp.org.
|
||||
RFCs
|
||||
----
|
||||
|
||||
The kernel code implements the datapath features specified in the
|
||||
following RFCs:
|
||||
|
||||
======= =============== ===================================
|
||||
RFC2661 L2TPv2 https://tools.ietf.org/html/rfc2661
|
||||
RFC3931 L2TPv3 https://tools.ietf.org/html/rfc3931
|
||||
RFC4719 L2TPv3 Ethernet https://tools.ietf.org/html/rfc4719
|
||||
======= =============== ===================================
|
||||
|
||||
Implementations
|
||||
---------------
|
||||
|
||||
A number of open source applications use the L2TP kernel subsystem:
|
||||
|
||||
============ ==============================================
|
||||
iproute2 https://github.com/shemminger/iproute2
|
||||
go-l2tp https://github.com/katalix/go-l2tp
|
||||
tunneldigger https://github.com/wlanslovenija/tunneldigger
|
||||
xl2tpd https://github.com/xelerance/xl2tpd
|
||||
============ ==============================================
|
||||
|
||||
Limitations
|
||||
-----------
|
||||
|
||||
The current implementation has a number of limitations:
|
||||
|
||||
1) Multiple UDP sockets with the same 5-tuple address cannot be
|
||||
used. The kernel's tunnel context is identified using private
|
||||
data associated with the socket so it is important that each
|
||||
socket is uniquely identified by its address.
|
||||
|
||||
2) Interfacing with openvswitch is not yet implemented. It may be
|
||||
useful to map OVS Ethernet and VLAN ports into L2TPv3 tunnels.
|
||||
|
||||
3) VLAN pseudowires are implemented using an ``l2tpethN`` interface
|
||||
configured with a VLAN sub-interface. Since L2TPv3 VLAN
|
||||
pseudowires carry one and only one VLAN, it may be better to use
|
||||
a single netdevice rather than an ``l2tpethN`` and ``l2tpethN``:M
|
||||
pair per VLAN session. The netlink attribute
|
||||
``L2TP_ATTR_VLAN_ID`` was added for this, but it was never
|
||||
implemented.
|
||||
|
||||
Testing
|
||||
-------
|
||||
|
||||
Unmanaged L2TPv3 Ethernet features are tested by the kernel's built-in
|
||||
selftests. See `tools/testing/selftests/net/l2tp.sh`_.
|
||||
|
||||
Another test suite, l2tp-ktest_, covers all
|
||||
of the L2TP APIs and tunnel/session types. This may be integrated into
|
||||
the kernel's built-in L2TP selftests in the future.
|
||||
|
||||
.. Links
|
||||
.. _Generic Netlink: generic_netlink.html
|
||||
.. _libmnl: https://www.netfilter.org/projects/libmnl
|
||||
.. _include/uapi/linux/l2tp.h: ../../../include/uapi/linux/l2tp.h
|
||||
.. _include/linux/if_pppol2tp.h: ../../../include/linux/if_pppol2tp.h
|
||||
.. _net/l2tp/l2tp_ip.c: ../../../net/l2tp/l2tp_ip.c
|
||||
.. _net/l2tp/l2tp_ip6.c: ../../../net/l2tp/l2tp_ip6.c
|
||||
.. _net/l2tp/l2tp_ppp.c: ../../../net/l2tp/l2tp_ppp.c
|
||||
.. _net/l2tp/l2tp_eth.c: ../../../net/l2tp/l2tp_eth.c
|
||||
.. _tools/testing/selftests/net/l2tp.sh: ../../../tools/testing/selftests/net/l2tp.sh
|
||||
.. _l2tp-ktest: https://github.com/katalix/l2tp-ktest
|
||||
|
@@ -465,9 +465,9 @@ XPS Configuration
|
||||
-----------------
|
||||
|
||||
XPS is only available if the kconfig symbol CONFIG_XPS is enabled (on by
|
||||
default for SMP). The functionality remains disabled until explicitly
|
||||
configured. To enable XPS, the bitmap of CPUs/receive-queues that may
|
||||
use a transmit queue is configured using the sysfs file entry:
|
||||
default for SMP). If compiled in, it is driver dependent whether, and
|
||||
how, XPS is configured at device init. The mapping of CPUs/receive-queues
|
||||
to transmit queue can be inspected and configured using sysfs:
|
||||
|
||||
For selection based on CPUs map::
|
||||
|
||||
|
179
Documentation/networking/statistics.rst
Normal file
179
Documentation/networking/statistics.rst
Normal file
@@ -0,0 +1,179 @@
|
||||
.. SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
====================
|
||||
Interface statistics
|
||||
====================
|
||||
|
||||
Overview
|
||||
========
|
||||
|
||||
This document is a guide to Linux network interface statistics.
|
||||
|
||||
There are three main sources of interface statistics in Linux:
|
||||
|
||||
- standard interface statistics based on
|
||||
:c:type:`struct rtnl_link_stats64 <rtnl_link_stats64>`;
|
||||
- protocol-specific statistics; and
|
||||
- driver-defined statistics available via ethtool.
|
||||
|
||||
Standard interface statistics
|
||||
-----------------------------
|
||||
|
||||
There are multiple interfaces to reach the standard statistics.
|
||||
Most commonly used is the `ip` command from `iproute2`::
|
||||
|
||||
$ ip -s -s link show dev ens4u1u1
|
||||
6: ens4u1u1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP mode DEFAULT group default qlen 1000
|
||||
link/ether 48:2a:e3:4c:b1:d1 brd ff:ff:ff:ff:ff:ff
|
||||
RX: bytes packets errors dropped overrun mcast
|
||||
74327665117 69016965 0 0 0 0
|
||||
RX errors: length crc frame fifo missed
|
||||
0 0 0 0 0
|
||||
TX: bytes packets errors dropped carrier collsns
|
||||
21405556176 44608960 0 0 0 0
|
||||
TX errors: aborted fifo window heartbeat transns
|
||||
0 0 0 0 128
|
||||
altname enp58s0u1u1
|
||||
|
||||
Note that `-s` has been specified twice to see all members of
|
||||
:c:type:`struct rtnl_link_stats64 <rtnl_link_stats64>`.
|
||||
If `-s` is specified once the detailed errors won't be shown.
|
||||
|
||||
`ip` supports JSON formatting via the `-j` option.
|
||||
|
||||
Protocol-specific statistics
|
||||
----------------------------
|
||||
|
||||
Some of the interfaces used for configuring devices are also able
|
||||
to report related statistics. For example ethtool interface used
|
||||
to configure pause frames can report corresponding hardware counters::
|
||||
|
||||
$ ethtool --include-statistics -a eth0
|
||||
Pause parameters for eth0:
|
||||
Autonegotiate: on
|
||||
RX: on
|
||||
TX: on
|
||||
Statistics:
|
||||
tx_pause_frames: 1
|
||||
rx_pause_frames: 1
|
||||
|
||||
Driver-defined statistics
|
||||
-------------------------
|
||||
|
||||
Driver-defined ethtool statistics can be dumped using `ethtool -S $ifc`, e.g.::
|
||||
|
||||
$ ethtool -S ens4u1u1
|
||||
NIC statistics:
|
||||
tx_single_collisions: 0
|
||||
tx_multi_collisions: 0
|
||||
|
||||
uAPIs
|
||||
=====
|
||||
|
||||
procfs
|
||||
------
|
||||
|
||||
The historical `/proc/net/dev` text interface gives access to the list
|
||||
of interfaces as well as their statistics.
|
||||
|
||||
Note that even though this interface is using
|
||||
:c:type:`struct rtnl_link_stats64 <rtnl_link_stats64>`
|
||||
internally it combines some of the fields.
|
||||
|
||||
sysfs
|
||||
-----
|
||||
|
||||
Each device directory in sysfs contains a `statistics` directory (e.g.
|
||||
`/sys/class/net/lo/statistics/`) with files corresponding to
|
||||
members of :c:type:`struct rtnl_link_stats64 <rtnl_link_stats64>`.
|
||||
|
||||
This simple interface is convenient especially in constrained/embedded
|
||||
environments without access to tools. However, it's inefficient when
|
||||
reading multiple stats as it internally performs a full dump of
|
||||
:c:type:`struct rtnl_link_stats64 <rtnl_link_stats64>`
|
||||
and reports only the stat corresponding to the accessed file.
|
||||
|
||||
Sysfs files are documented in
|
||||
`Documentation/ABI/testing/sysfs-class-net-statistics`.
|
||||
|
||||
|
||||
netlink
|
||||
-------
|
||||
|
||||
`rtnetlink` (`NETLINK_ROUTE`) is the preferred method of accessing
|
||||
:c:type:`struct rtnl_link_stats64 <rtnl_link_stats64>` stats.
|
||||
|
||||
Statistics are reported both in the responses to link information
|
||||
requests (`RTM_GETLINK`) and statistic requests (`RTM_GETSTATS`,
|
||||
when `IFLA_STATS_LINK_64` bit is set in the `.filter_mask` of the request).
|
||||
|
||||
ethtool
|
||||
-------
|
||||
|
||||
Ethtool IOCTL interface allows drivers to report implementation
|
||||
specific statistics. Historically it has also been used to report
|
||||
statistics for which other APIs did not exist, like per-device-queue
|
||||
statistics, or standard-based statistics (e.g. RFC 2863).
|
||||
|
||||
Statistics and their string identifiers are retrieved separately.
|
||||
Identifiers via `ETHTOOL_GSTRINGS` with `string_set` set to `ETH_SS_STATS`,
|
||||
and values via `ETHTOOL_GSTATS`. User space should use `ETHTOOL_GDRVINFO`
|
||||
to retrieve the number of statistics (`.n_stats`).
|
||||
|
||||
ethtool-netlink
|
||||
---------------
|
||||
|
||||
Ethtool netlink is a replacement for the older IOCTL interface.
|
||||
|
||||
Protocol-related statistics can be requested in get commands by setting
|
||||
the `ETHTOOL_FLAG_STATS` flag in `ETHTOOL_A_HEADER_FLAGS`. Currently
|
||||
statistics are supported in the following commands:
|
||||
|
||||
- `ETHTOOL_MSG_PAUSE_GET`
|
||||
|
||||
debugfs
|
||||
-------
|
||||
|
||||
Some drivers expose extra statistics via `debugfs`.
|
||||
|
||||
struct rtnl_link_stats64
|
||||
========================
|
||||
|
||||
.. kernel-doc:: include/uapi/linux/if_link.h
|
||||
:identifiers: rtnl_link_stats64
|
||||
|
||||
Notes for driver authors
|
||||
========================
|
||||
|
||||
Drivers should report all statistics which have a matching member in
|
||||
:c:type:`struct rtnl_link_stats64 <rtnl_link_stats64>` exclusively
|
||||
via `.ndo_get_stats64`. Reporting such standard stats via ethtool
|
||||
or debugfs will not be accepted.
|
||||
|
||||
Drivers must ensure best possible compliance with
|
||||
:c:type:`struct rtnl_link_stats64 <rtnl_link_stats64>`.
|
||||
Please note for example that detailed error statistics must be
|
||||
added into the general `rx_error` / `tx_error` counters.
|
||||
|
||||
The `.ndo_get_stats64` callback can not sleep because of accesses
|
||||
via `/proc/net/dev`. If driver may sleep when retrieving the statistics
|
||||
from the device it should do so periodically asynchronously and only return
|
||||
a recent copy from `.ndo_get_stats64`. Ethtool interrupt coalescing interface
|
||||
allows setting the frequency of refreshing statistics, if needed.
|
||||
|
||||
Retrieving ethtool statistics is a multi-syscall process, drivers are advised
|
||||
to keep the number of statistics constant to avoid race conditions with
|
||||
user space trying to read them.
|
||||
|
||||
Statistics must persist across routine operations like bringing the interface
|
||||
down and up.
|
||||
|
||||
Kernel-internal data structures
|
||||
-------------------------------
|
||||
|
||||
The following structures are internal to the kernel, their members are
|
||||
translated to netlink attributes when dumped. Drivers must not overwrite
|
||||
the statistics they don't report with 0.
|
||||
|
||||
.. kernel-doc:: include/linux/ethtool.h
|
||||
:identifiers: ethtool_pause_stats
|
@@ -58,3 +58,31 @@ forwarding table using the new bridge command.
|
||||
3. Show forwarding table::
|
||||
|
||||
# bridge fdb show dev vxlan0
|
||||
|
||||
The following NIC features may indicate support for UDP tunnel-related
|
||||
offloads (most commonly VXLAN features, but support for a particular
|
||||
encapsulation protocol is NIC specific):
|
||||
|
||||
- `tx-udp_tnl-segmentation`
|
||||
- `tx-udp_tnl-csum-segmentation`
|
||||
ability to perform TCP segmentation offload of UDP encapsulated frames
|
||||
|
||||
- `rx-udp_tunnel-port-offload`
|
||||
receive side parsing of UDP encapsulated frames which allows NICs to
|
||||
perform protocol-aware offloads, like checksum validation offload of
|
||||
inner frames (only needed by NICs without protocol-agnostic offloads)
|
||||
|
||||
For devices supporting `rx-udp_tunnel-port-offload` the list of currently
|
||||
offloaded ports can be interrogated with `ethtool`::
|
||||
|
||||
$ ethtool --show-tunnels eth0
|
||||
Tunnel information for eth0:
|
||||
UDP port table 0:
|
||||
Size: 4
|
||||
Types: vxlan
|
||||
No entries
|
||||
UDP port table 1:
|
||||
Size: 4
|
||||
Types: geneve, vxlan-gpe
|
||||
Entries (1):
|
||||
port 1230, vxlan-gpe
|
||||
|
50
MAINTAINERS
50
MAINTAINERS
@@ -1259,7 +1259,7 @@ S: Supported
|
||||
F: Documentation/devicetree/bindings/net/apm-xgene-enet.txt
|
||||
F: Documentation/devicetree/bindings/net/apm-xgene-mdio.txt
|
||||
F: drivers/net/ethernet/apm/xgene/
|
||||
F: drivers/net/phy/mdio-xgene.c
|
||||
F: drivers/net/mdio/mdio-xgene.c
|
||||
|
||||
APPLIED MICRO (APM) X-GENE SOC PMU
|
||||
M: Khuong Dinh <khuong@os.amperecomputing.com>
|
||||
@@ -3238,7 +3238,7 @@ M: Daniel Borkmann <daniel@iogearbox.net>
|
||||
R: Martin KaFai Lau <kafai@fb.com>
|
||||
R: Song Liu <songliubraving@fb.com>
|
||||
R: Yonghong Song <yhs@fb.com>
|
||||
R: Andrii Nakryiko <andriin@fb.com>
|
||||
R: Andrii Nakryiko <andrii@kernel.org>
|
||||
R: John Fastabend <john.fastabend@gmail.com>
|
||||
R: KP Singh <kpsingh@chromium.org>
|
||||
L: netdev@vger.kernel.org
|
||||
@@ -3914,6 +3914,7 @@ F: include/net/netns/can.h
|
||||
F: include/uapi/linux/can.h
|
||||
F: include/uapi/linux/can/bcm.h
|
||||
F: include/uapi/linux/can/gw.h
|
||||
F: include/uapi/linux/can/isotp.h
|
||||
F: include/uapi/linux/can/raw.h
|
||||
F: net/can/
|
||||
|
||||
@@ -4713,6 +4714,15 @@ S: Supported
|
||||
W: http://www.chelsio.com
|
||||
F: drivers/crypto/chelsio
|
||||
|
||||
CXGB4 INLINE CRYPTO DRIVER
|
||||
M: Ayush Sawal <ayush.sawal@chelsio.com>
|
||||
M: Vinay Kumar Yadav <vinay.yadav@chelsio.com>
|
||||
M: Rohit Maheshwari <rohitm@chelsio.com>
|
||||
L: netdev@vger.kernel.org
|
||||
S: Supported
|
||||
W: http://www.chelsio.com
|
||||
F: drivers/net/ethernet/chelsio/inline_crypto/
|
||||
|
||||
CXGB4 ETHERNET DRIVER (CXGB4)
|
||||
M: Vishal Kulkarni <vishal@chelsio.com>
|
||||
L: netdev@vger.kernel.org
|
||||
@@ -6546,11 +6556,14 @@ F: Documentation/devicetree/bindings/net/ethernet-phy.yaml
|
||||
F: Documentation/devicetree/bindings/net/mdio*
|
||||
F: Documentation/devicetree/bindings/net/qca,ar803x.yaml
|
||||
F: Documentation/networking/phy.rst
|
||||
F: drivers/net/mdio/
|
||||
F: drivers/net/mdio/of_mdio.c
|
||||
F: drivers/net/pcs/
|
||||
F: drivers/net/phy/
|
||||
F: drivers/of/of_mdio.c
|
||||
F: drivers/of/of_net.c
|
||||
F: include/dt-bindings/net/qca-ar803x.h
|
||||
F: include/linux/*mdio*.h
|
||||
F: include/linux/mdio/*.h
|
||||
F: include/linux/of_net.h
|
||||
F: include/linux/phy.h
|
||||
F: include/linux/phy_fixed.h
|
||||
@@ -10347,6 +10360,13 @@ S: Maintained
|
||||
W: http://linux-test-project.github.io/
|
||||
T: git git://github.com/linux-test-project/ltp.git
|
||||
|
||||
LYNX PCS MODULE
|
||||
M: Ioana Ciornei <ioana.ciornei@nxp.com>
|
||||
L: netdev@vger.kernel.org
|
||||
S: Supported
|
||||
F: drivers/net/pcs/pcs-lynx.c
|
||||
F: include/linux/pcs-lynx.h
|
||||
|
||||
M68K ARCHITECTURE
|
||||
M: Geert Uytterhoeven <geert@linux-m68k.org>
|
||||
L: linux-m68k@lists.linux-m68k.org
|
||||
@@ -10554,7 +10574,7 @@ M: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
L: netdev@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/devicetree/bindings/net/marvell,mvusb.yaml
|
||||
F: drivers/net/phy/mdio-mvusb.c
|
||||
F: drivers/net/mdio/mdio-mvusb.c
|
||||
|
||||
MARVELL XENON MMC/SD/SDIO HOST CONTROLLER DRIVER
|
||||
M: Hu Ziji <huziji@marvell.com>
|
||||
@@ -10701,6 +10721,15 @@ L: linux-input@vger.kernel.org
|
||||
S: Maintained
|
||||
F: drivers/hid/hid-mcp2221.c
|
||||
|
||||
MCP251XFD SPI-CAN NETWORK DRIVER
|
||||
M: Marc Kleine-Budde <mkl@pengutronix.de>
|
||||
M: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
|
||||
R: Thomas Kopp <thomas.kopp@microchip.com>
|
||||
L: linux-can@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/devicetree/bindings/net/can/microchip,mcp251xfd.yaml
|
||||
F: drivers/net/can/spi/mcp251xfd/
|
||||
|
||||
MCP4018 AND MCP4531 MICROCHIP DIGITAL POTENTIOMETER DRIVERS
|
||||
M: Peter Rosin <peda@axentia.se>
|
||||
L: linux-iio@vger.kernel.org
|
||||
@@ -12090,7 +12119,6 @@ M: Neil Horman <nhorman@tuxdriver.com>
|
||||
L: netdev@vger.kernel.org
|
||||
S: Maintained
|
||||
W: https://fedorahosted.org/dropwatch/
|
||||
F: include/net/drop_monitor.h
|
||||
F: include/uapi/linux/net_dropmon.h
|
||||
F: net/core/drop_monitor.c
|
||||
|
||||
@@ -12185,6 +12213,7 @@ F: net/ipv6/ipcomp6.c
|
||||
F: net/ipv6/xfrm*
|
||||
F: net/key/
|
||||
F: net/xfrm/
|
||||
F: tools/testing/selftests/net/ipsec.c
|
||||
|
||||
NETWORKING [IPv4/IPv6]
|
||||
M: "David S. Miller" <davem@davemloft.net>
|
||||
@@ -12597,6 +12626,7 @@ F: drivers/net/dsa/ocelot/*
|
||||
F: drivers/net/ethernet/mscc/
|
||||
F: include/soc/mscc/ocelot*
|
||||
F: net/dsa/tag_ocelot.c
|
||||
F: tools/testing/selftests/drivers/net/ocelot/*
|
||||
|
||||
OCXL (Open Coherent Accelerator Processor Interface OpenCAPI) DRIVER
|
||||
M: Frederic Barrat <fbarrat@linux.ibm.com>
|
||||
@@ -15372,10 +15402,11 @@ F: drivers/media/platform/s3c-camif/
|
||||
F: include/media/drv-intf/s3c_camif.h
|
||||
|
||||
SAMSUNG S3FWRN5 NFC DRIVER
|
||||
M: Robert Baldyga <r.baldyga@samsung.com>
|
||||
M: Krzysztof Kozlowski <krzk@kernel.org>
|
||||
M: Krzysztof Opasiak <k.opasiak@samsung.com>
|
||||
L: linux-nfc@lists.01.org (moderated for non-subscribers)
|
||||
S: Supported
|
||||
S: Maintained
|
||||
F: Documentation/devicetree/bindings/net/nfc/samsung,s3fwrn5.yaml
|
||||
F: drivers/nfc/s3fwrn5
|
||||
|
||||
SAMSUNG S5C73M3 CAMERA DRIVER
|
||||
@@ -15762,6 +15793,7 @@ L: netdev@vger.kernel.org
|
||||
S: Maintained
|
||||
F: drivers/net/phy/phylink.c
|
||||
F: drivers/net/phy/sfp*
|
||||
F: include/linux/mdio/mdio-i2c.h
|
||||
F: include/linux/phylink.h
|
||||
F: include/linux/sfp.h
|
||||
K: phylink\.h|struct\s+phylink|\.phylink|>phylink_|phylink_(autoneg|clear|connect|create|destroy|disconnect|ethtool|helper|mac|mii|of|set|start|stop|test|validate)
|
||||
@@ -16851,8 +16883,8 @@ SYNOPSYS DESIGNWARE ETHERNET XPCS DRIVER
|
||||
M: Jose Abreu <Jose.Abreu@synopsys.com>
|
||||
L: netdev@vger.kernel.org
|
||||
S: Supported
|
||||
F: drivers/net/phy/mdio-xpcs.c
|
||||
F: include/linux/mdio-xpcs.h
|
||||
F: drivers/net/pcs/pcs-xpcs.c
|
||||
F: include/linux/pcs/pcs-xpcs.h
|
||||
|
||||
SYNOPSYS DESIGNWARE I2C DRIVER
|
||||
M: Jarkko Nikula <jarkko.nikula@linux.intel.com>
|
||||
|
4
Makefile
4
Makefile
@@ -1071,13 +1071,15 @@ ifdef CONFIG_STACK_VALIDATION
|
||||
endif
|
||||
endif
|
||||
|
||||
ifdef CONFIG_BPF
|
||||
ifdef CONFIG_DEBUG_INFO_BTF
|
||||
ifeq ($(has_libelf),1)
|
||||
resolve_btfids_target := tools/bpf/resolve_btfids FORCE
|
||||
else
|
||||
ERROR_RESOLVE_BTFIDS := 1
|
||||
endif
|
||||
endif
|
||||
endif # CONFIG_DEBUG_INFO_BTF
|
||||
endif # CONFIG_BPF
|
||||
|
||||
PHONY += prepare0
|
||||
|
||||
|
@@ -795,8 +795,8 @@
|
||||
reg = <0x27>;
|
||||
interrupt-parent = <&gpa1>;
|
||||
interrupts = <3 IRQ_TYPE_LEVEL_HIGH>;
|
||||
s3fwrn5,en-gpios = <&gpf1 4 GPIO_ACTIVE_HIGH>;
|
||||
s3fwrn5,fw-gpios = <&gpj0 2 GPIO_ACTIVE_HIGH>;
|
||||
en-gpios = <&gpf1 4 GPIO_ACTIVE_HIGH>;
|
||||
wake-gpios = <&gpj0 2 GPIO_ACTIVE_HIGH>;
|
||||
};
|
||||
};
|
||||
|
||||
|
@@ -199,6 +199,7 @@
|
||||
&enetc_port0 {
|
||||
phy-handle = <&sgmii_phy0>;
|
||||
phy-connection-type = "sgmii";
|
||||
managed = "in-band-status";
|
||||
status = "okay";
|
||||
|
||||
mdio {
|
||||
|
@@ -143,6 +143,56 @@
|
||||
mdio: mdio-bus {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
switch@0 {
|
||||
compatible = "mediatek,mt7531";
|
||||
reg = <0>;
|
||||
reset-gpios = <&pio 54 0>;
|
||||
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
port@0 {
|
||||
reg = <0>;
|
||||
label = "wan";
|
||||
};
|
||||
|
||||
port@1 {
|
||||
reg = <1>;
|
||||
label = "lan0";
|
||||
};
|
||||
|
||||
port@2 {
|
||||
reg = <2>;
|
||||
label = "lan1";
|
||||
};
|
||||
|
||||
port@3 {
|
||||
reg = <3>;
|
||||
label = "lan2";
|
||||
};
|
||||
|
||||
port@4 {
|
||||
reg = <4>;
|
||||
label = "lan3";
|
||||
};
|
||||
|
||||
port@6 {
|
||||
reg = <6>;
|
||||
label = "cpu";
|
||||
ethernet = <&gmac0>;
|
||||
phy-mode = "2500base-x";
|
||||
|
||||
fixed-link {
|
||||
speed = <2500>;
|
||||
full-duplex;
|
||||
pause;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
|
@@ -105,20 +105,71 @@
|
||||
pinctrl-0 = <ð_pins>;
|
||||
status = "okay";
|
||||
|
||||
gmac1: mac@1 {
|
||||
gmac0: mac@0 {
|
||||
compatible = "mediatek,eth-mac";
|
||||
reg = <1>;
|
||||
phy-handle = <&phy5>;
|
||||
reg = <0>;
|
||||
phy-mode = "2500base-x";
|
||||
|
||||
fixed-link {
|
||||
speed = <2500>;
|
||||
full-duplex;
|
||||
pause;
|
||||
};
|
||||
};
|
||||
|
||||
mdio-bus {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
phy5: ethernet-phy@5 {
|
||||
reg = <5>;
|
||||
phy-mode = "sgmii";
|
||||
switch@0 {
|
||||
compatible = "mediatek,mt7531";
|
||||
reg = <0>;
|
||||
reset-gpios = <&pio 54 0>;
|
||||
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
port@0 {
|
||||
reg = <0>;
|
||||
label = "lan0";
|
||||
};
|
||||
|
||||
port@1 {
|
||||
reg = <1>;
|
||||
label = "lan1";
|
||||
};
|
||||
|
||||
port@2 {
|
||||
reg = <2>;
|
||||
label = "lan2";
|
||||
};
|
||||
|
||||
port@3 {
|
||||
reg = <3>;
|
||||
label = "lan3";
|
||||
};
|
||||
|
||||
port@4 {
|
||||
reg = <4>;
|
||||
label = "wan";
|
||||
};
|
||||
|
||||
port@6 {
|
||||
reg = <6>;
|
||||
label = "cpu";
|
||||
ethernet = <&gmac0>;
|
||||
phy-mode = "2500base-x";
|
||||
|
||||
fixed-link {
|
||||
speed = <2500>;
|
||||
full-duplex;
|
||||
pause;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
|
@@ -134,11 +134,13 @@
|
||||
<0x1280000 0x100>,
|
||||
<0x1800000 0x80000>,
|
||||
<0x1880000 0x10000>,
|
||||
<0x1040000 0x10000>,
|
||||
<0x1050000 0x10000>,
|
||||
<0x1060000 0x10000>;
|
||||
reg-names = "sys", "rew", "qs", "ptp", "port0", "port1",
|
||||
"port2", "port3", "port4", "port5", "port6",
|
||||
"port7", "port8", "port9", "port10", "qsys",
|
||||
"ana", "s2";
|
||||
"ana", "s0", "s1", "s2";
|
||||
interrupts = <18 21 22>;
|
||||
interrupt-names = "ptp_rdy", "xtr", "inj";
|
||||
|
||||
|
@@ -64,6 +64,40 @@
|
||||
phy_sgmii_2: ethernet-phy@3 {
|
||||
reg = <0x03>;
|
||||
};
|
||||
|
||||
/* VSC8514 QSGMII PHY */
|
||||
phy_qsgmii_0: ethernet-phy@4 {
|
||||
reg = <0x4>;
|
||||
};
|
||||
|
||||
phy_qsgmii_1: ethernet-phy@5 {
|
||||
reg = <0x5>;
|
||||
};
|
||||
|
||||
phy_qsgmii_2: ethernet-phy@6 {
|
||||
reg = <0x6>;
|
||||
};
|
||||
|
||||
phy_qsgmii_3: ethernet-phy@7 {
|
||||
reg = <0x7>;
|
||||
};
|
||||
|
||||
/* VSC8514 QSGMII PHY */
|
||||
phy_qsgmii_4: ethernet-phy@8 {
|
||||
reg = <0x8>;
|
||||
};
|
||||
|
||||
phy_qsgmii_5: ethernet-phy@9 {
|
||||
reg = <0x9>;
|
||||
};
|
||||
|
||||
phy_qsgmii_6: ethernet-phy@a {
|
||||
reg = <0xa>;
|
||||
};
|
||||
|
||||
phy_qsgmii_7: ethernet-phy@b {
|
||||
reg = <0xb>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
@@ -76,3 +110,76 @@
|
||||
};
|
||||
|
||||
#include "t1040si-post.dtsi"
|
||||
|
||||
&seville_switch {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&seville_port0 {
|
||||
managed = "in-band-status";
|
||||
phy-handle = <&phy_qsgmii_0>;
|
||||
phy-mode = "qsgmii";
|
||||
label = "ETH5";
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&seville_port1 {
|
||||
managed = "in-band-status";
|
||||
phy-handle = <&phy_qsgmii_1>;
|
||||
phy-mode = "qsgmii";
|
||||
label = "ETH4";
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&seville_port2 {
|
||||
managed = "in-band-status";
|
||||
phy-handle = <&phy_qsgmii_2>;
|
||||
phy-mode = "qsgmii";
|
||||
label = "ETH7";
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&seville_port3 {
|
||||
managed = "in-band-status";
|
||||
phy-handle = <&phy_qsgmii_3>;
|
||||
phy-mode = "qsgmii";
|
||||
label = "ETH6";
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&seville_port4 {
|
||||
managed = "in-band-status";
|
||||
phy-handle = <&phy_qsgmii_4>;
|
||||
phy-mode = "qsgmii";
|
||||
label = "ETH9";
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&seville_port5 {
|
||||
managed = "in-band-status";
|
||||
phy-handle = <&phy_qsgmii_5>;
|
||||
phy-mode = "qsgmii";
|
||||
label = "ETH8";
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&seville_port6 {
|
||||
managed = "in-band-status";
|
||||
phy-handle = <&phy_qsgmii_6>;
|
||||
phy-mode = "qsgmii";
|
||||
label = "ETH11";
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&seville_port7 {
|
||||
managed = "in-band-status";
|
||||
phy-handle = <&phy_qsgmii_7>;
|
||||
phy-mode = "qsgmii";
|
||||
label = "ETH10";
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&seville_port8 {
|
||||
ethernet = <&enet0>;
|
||||
status = "okay";
|
||||
};
|
||||
|
@@ -628,6 +628,84 @@
|
||||
status = "disabled";
|
||||
};
|
||||
};
|
||||
|
||||
seville_switch: ethernet-switch@800000 {
|
||||
compatible = "mscc,vsc9953-switch";
|
||||
reg = <0x800000 0x290000>;
|
||||
interrupts = <26 2 0 0>;
|
||||
interrupt-names = "xtr";
|
||||
little-endian;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
status = "disabled";
|
||||
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
seville_port0: port@0 {
|
||||
reg = <0>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
seville_port1: port@1 {
|
||||
reg = <1>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
seville_port2: port@2 {
|
||||
reg = <2>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
seville_port3: port@3 {
|
||||
reg = <3>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
seville_port4: port@4 {
|
||||
reg = <4>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
seville_port5: port@5 {
|
||||
reg = <5>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
seville_port6: port@6 {
|
||||
reg = <6>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
seville_port7: port@7 {
|
||||
reg = <7>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
seville_port8: port@8 {
|
||||
reg = <8>;
|
||||
phy-mode = "internal";
|
||||
status = "disabled";
|
||||
|
||||
fixed-link {
|
||||
speed = <2500>;
|
||||
full-duplex;
|
||||
};
|
||||
};
|
||||
|
||||
seville_port9: port@9 {
|
||||
reg = <9>;
|
||||
phy-mode = "internal";
|
||||
status = "disabled";
|
||||
|
||||
fixed-link {
|
||||
speed = <2500>;
|
||||
full-duplex;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&qe {
|
||||
|
@@ -238,7 +238,10 @@ extern void ccw_device_get_schid(struct ccw_device *, struct subchannel_id *);
|
||||
struct channel_path_desc_fmt0 *ccw_device_get_chp_desc(struct ccw_device *, int);
|
||||
u8 *ccw_device_get_util_str(struct ccw_device *cdev, int chp_idx);
|
||||
int ccw_device_pnso(struct ccw_device *cdev,
|
||||
struct chsc_pnso_area *pnso_area,
|
||||
struct chsc_pnso_resume_token resume_token,
|
||||
int cnc);
|
||||
struct chsc_pnso_area *pnso_area, u8 oc,
|
||||
struct chsc_pnso_resume_token resume_token, int cnc);
|
||||
int ccw_device_get_cssid(struct ccw_device *cdev, u8 *cssid);
|
||||
int ccw_device_get_iid(struct ccw_device *cdev, u8 *iid);
|
||||
int ccw_device_get_chpid(struct ccw_device *cdev, int chp_idx, u8 *chpid);
|
||||
int ccw_device_get_chid(struct ccw_device *cdev, int chp_idx, u16 *chid);
|
||||
#endif /* _S390_CCWDEV_H_ */
|
||||
|
@@ -11,6 +11,13 @@
|
||||
|
||||
#include <uapi/asm/chsc.h>
|
||||
|
||||
/**
|
||||
* Operation codes for CHSC PNSO:
|
||||
* PNSO_OC_NET_BRIDGE_INFO - only addresses that are visible to a bridgeport
|
||||
* PNSO_OC_NET_ADDR_INFO - all addresses
|
||||
*/
|
||||
#define PNSO_OC_NET_BRIDGE_INFO 0
|
||||
#define PNSO_OC_NET_ADDR_INFO 3
|
||||
/**
|
||||
* struct chsc_pnso_naid_l2 - network address information descriptor
|
||||
* @nit: Network interface token
|
||||
|
@@ -36,7 +36,9 @@ struct css_general_char {
|
||||
u64 alt_ssi : 1; /* bit 108 */
|
||||
u64 : 1;
|
||||
u64 narf : 1; /* bit 110 */
|
||||
u64 : 12;
|
||||
u64 : 5;
|
||||
u64 enarf: 1; /* bit 116 */
|
||||
u64 : 6;
|
||||
u64 util_str : 1;/* bit 123 */
|
||||
} __packed;
|
||||
|
||||
|
@@ -50,7 +50,6 @@ struct bpf_jit {
|
||||
int r14_thunk_ip; /* Address of expoline thunk for 'br %r14' */
|
||||
int tail_call_start; /* Tail call start offset */
|
||||
int excnt; /* Number of exception table entries */
|
||||
int labels[1]; /* Labels for local jumps */
|
||||
};
|
||||
|
||||
#define SEEN_MEM BIT(0) /* use mem[] for temporary storage */
|
||||
@@ -229,18 +228,18 @@ static inline void reg_set_seen(struct bpf_jit *jit, u32 b1)
|
||||
REG_SET_SEEN(b3); \
|
||||
})
|
||||
|
||||
#define EMIT6_PCREL_LABEL(op1, op2, b1, b2, label, mask) \
|
||||
#define EMIT6_PCREL_RIEB(op1, op2, b1, b2, mask, target) \
|
||||
({ \
|
||||
int rel = (jit->labels[label] - jit->prg) >> 1; \
|
||||
unsigned int rel = (int)((target) - jit->prg) / 2; \
|
||||
_EMIT6((op1) | reg(b1, b2) << 16 | (rel & 0xffff), \
|
||||
(op2) | (mask) << 12); \
|
||||
REG_SET_SEEN(b1); \
|
||||
REG_SET_SEEN(b2); \
|
||||
})
|
||||
|
||||
#define EMIT6_PCREL_IMM_LABEL(op1, op2, b1, imm, label, mask) \
|
||||
#define EMIT6_PCREL_RIEC(op1, op2, b1, imm, mask, target) \
|
||||
({ \
|
||||
int rel = (jit->labels[label] - jit->prg) >> 1; \
|
||||
unsigned int rel = (int)((target) - jit->prg) / 2; \
|
||||
_EMIT6((op1) | (reg_high(b1) | (mask)) << 16 | \
|
||||
(rel & 0xffff), (op2) | ((imm) & 0xff) << 8); \
|
||||
REG_SET_SEEN(b1); \
|
||||
@@ -1282,7 +1281,9 @@ static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp,
|
||||
EMIT4(0xb9040000, BPF_REG_0, REG_2);
|
||||
break;
|
||||
}
|
||||
case BPF_JMP | BPF_TAIL_CALL:
|
||||
case BPF_JMP | BPF_TAIL_CALL: {
|
||||
int patch_1_clrj, patch_2_clij, patch_3_brc;
|
||||
|
||||
/*
|
||||
* Implicit input:
|
||||
* B1: pointer to ctx
|
||||
@@ -1300,16 +1301,10 @@ static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp,
|
||||
EMIT6_DISP_LH(0xe3000000, 0x0016, REG_W1, REG_0, BPF_REG_2,
|
||||
offsetof(struct bpf_array, map.max_entries));
|
||||
/* if ((u32)%b3 >= (u32)%w1) goto out; */
|
||||
if (!is_first_pass(jit) && can_use_rel(jit, jit->labels[0])) {
|
||||
/* clrj %b3,%w1,0xa,label0 */
|
||||
EMIT6_PCREL_LABEL(0xec000000, 0x0077, BPF_REG_3,
|
||||
REG_W1, 0, 0xa);
|
||||
} else {
|
||||
/* clr %b3,%w1 */
|
||||
EMIT2(0x1500, BPF_REG_3, REG_W1);
|
||||
/* brcl 0xa,label0 */
|
||||
EMIT6_PCREL_RILC(0xc0040000, 0xa, jit->labels[0]);
|
||||
}
|
||||
/* clrj %b3,%w1,0xa,out */
|
||||
patch_1_clrj = jit->prg;
|
||||
EMIT6_PCREL_RIEB(0xec000000, 0x0077, BPF_REG_3, REG_W1, 0xa,
|
||||
jit->prg);
|
||||
|
||||
/*
|
||||
* if (tail_call_cnt++ > MAX_TAIL_CALL_CNT)
|
||||
@@ -1324,16 +1319,10 @@ static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp,
|
||||
EMIT4_IMM(0xa7080000, REG_W0, 1);
|
||||
/* laal %w1,%w0,off(%r15) */
|
||||
EMIT6_DISP_LH(0xeb000000, 0x00fa, REG_W1, REG_W0, REG_15, off);
|
||||
if (!is_first_pass(jit) && can_use_rel(jit, jit->labels[0])) {
|
||||
/* clij %w1,MAX_TAIL_CALL_CNT,0x2,label0 */
|
||||
EMIT6_PCREL_IMM_LABEL(0xec000000, 0x007f, REG_W1,
|
||||
MAX_TAIL_CALL_CNT, 0, 0x2);
|
||||
} else {
|
||||
/* clfi %w1,MAX_TAIL_CALL_CNT */
|
||||
EMIT6_IMM(0xc20f0000, REG_W1, MAX_TAIL_CALL_CNT);
|
||||
/* brcl 0x2,label0 */
|
||||
EMIT6_PCREL_RILC(0xc0040000, 0x2, jit->labels[0]);
|
||||
}
|
||||
/* clij %w1,MAX_TAIL_CALL_CNT,0x2,out */
|
||||
patch_2_clij = jit->prg;
|
||||
EMIT6_PCREL_RIEC(0xec000000, 0x007f, REG_W1, MAX_TAIL_CALL_CNT,
|
||||
2, jit->prg);
|
||||
|
||||
/*
|
||||
* prog = array->ptrs[index];
|
||||
@@ -1348,13 +1337,9 @@ static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp,
|
||||
/* ltg %r1,prog(%b2,%r1) */
|
||||
EMIT6_DISP_LH(0xe3000000, 0x0002, REG_1, BPF_REG_2,
|
||||
REG_1, offsetof(struct bpf_array, ptrs));
|
||||
if (!is_first_pass(jit) && can_use_rel(jit, jit->labels[0])) {
|
||||
/* brc 0x8,label0 */
|
||||
EMIT4_PCREL_RIC(0xa7040000, 0x8, jit->labels[0]);
|
||||
} else {
|
||||
/* brcl 0x8,label0 */
|
||||
EMIT6_PCREL_RILC(0xc0040000, 0x8, jit->labels[0]);
|
||||
}
|
||||
/* brc 0x8,out */
|
||||
patch_3_brc = jit->prg;
|
||||
EMIT4_PCREL_RIC(0xa7040000, 8, jit->prg);
|
||||
|
||||
/*
|
||||
* Restore registers before calling function
|
||||
@@ -1371,8 +1356,16 @@ static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp,
|
||||
/* bc 0xf,tail_call_start(%r1) */
|
||||
_EMIT4(0x47f01000 + jit->tail_call_start);
|
||||
/* out: */
|
||||
jit->labels[0] = jit->prg;
|
||||
if (jit->prg_buf) {
|
||||
*(u16 *)(jit->prg_buf + patch_1_clrj + 2) =
|
||||
(jit->prg - patch_1_clrj) >> 1;
|
||||
*(u16 *)(jit->prg_buf + patch_2_clij + 2) =
|
||||
(jit->prg - patch_2_clij) >> 1;
|
||||
*(u16 *)(jit->prg_buf + patch_3_brc + 2) =
|
||||
(jit->prg - patch_3_brc) >> 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case BPF_JMP | BPF_EXIT: /* return b0 */
|
||||
last = (i == fp->len - 1) ? 1 : 0;
|
||||
if (last)
|
||||
|
@@ -314,19 +314,19 @@ static inline void mds_idle_clear_cpu_buffers(void)
|
||||
* lfence
|
||||
* jmp spec_trap
|
||||
* do_rop:
|
||||
* mov %rax,(%rsp) for x86_64
|
||||
* mov %rcx,(%rsp) for x86_64
|
||||
* mov %edx,(%esp) for x86_32
|
||||
* retq
|
||||
*
|
||||
* Without retpolines configured:
|
||||
*
|
||||
* jmp *%rax for x86_64
|
||||
* jmp *%rcx for x86_64
|
||||
* jmp *%edx for x86_32
|
||||
*/
|
||||
#ifdef CONFIG_RETPOLINE
|
||||
# ifdef CONFIG_X86_64
|
||||
# define RETPOLINE_RAX_BPF_JIT_SIZE 17
|
||||
# define RETPOLINE_RAX_BPF_JIT() \
|
||||
# define RETPOLINE_RCX_BPF_JIT_SIZE 17
|
||||
# define RETPOLINE_RCX_BPF_JIT() \
|
||||
do { \
|
||||
EMIT1_off32(0xE8, 7); /* callq do_rop */ \
|
||||
/* spec_trap: */ \
|
||||
@@ -334,7 +334,7 @@ do { \
|
||||
EMIT3(0x0F, 0xAE, 0xE8); /* lfence */ \
|
||||
EMIT2(0xEB, 0xF9); /* jmp spec_trap */ \
|
||||
/* do_rop: */ \
|
||||
EMIT4(0x48, 0x89, 0x04, 0x24); /* mov %rax,(%rsp) */ \
|
||||
EMIT4(0x48, 0x89, 0x0C, 0x24); /* mov %rcx,(%rsp) */ \
|
||||
EMIT1(0xC3); /* retq */ \
|
||||
} while (0)
|
||||
# else /* !CONFIG_X86_64 */
|
||||
@@ -352,9 +352,9 @@ do { \
|
||||
# endif
|
||||
#else /* !CONFIG_RETPOLINE */
|
||||
# ifdef CONFIG_X86_64
|
||||
# define RETPOLINE_RAX_BPF_JIT_SIZE 2
|
||||
# define RETPOLINE_RAX_BPF_JIT() \
|
||||
EMIT2(0xFF, 0xE0); /* jmp *%rax */
|
||||
# define RETPOLINE_RCX_BPF_JIT_SIZE 2
|
||||
# define RETPOLINE_RCX_BPF_JIT() \
|
||||
EMIT2(0xFF, 0xE1); /* jmp *%rcx */
|
||||
# else /* !CONFIG_X86_64 */
|
||||
# define RETPOLINE_EDX_BPF_JIT() \
|
||||
EMIT2(0xFF, 0xE2) /* jmp *%edx */
|
||||
|
@@ -221,14 +221,48 @@ struct jit_context {
|
||||
|
||||
/* Number of bytes emit_patch() needs to generate instructions */
|
||||
#define X86_PATCH_SIZE 5
|
||||
/* Number of bytes that will be skipped on tailcall */
|
||||
#define X86_TAIL_CALL_OFFSET 11
|
||||
|
||||
#define PROLOGUE_SIZE 25
|
||||
static void push_callee_regs(u8 **pprog, bool *callee_regs_used)
|
||||
{
|
||||
u8 *prog = *pprog;
|
||||
int cnt = 0;
|
||||
|
||||
if (callee_regs_used[0])
|
||||
EMIT1(0x53); /* push rbx */
|
||||
if (callee_regs_used[1])
|
||||
EMIT2(0x41, 0x55); /* push r13 */
|
||||
if (callee_regs_used[2])
|
||||
EMIT2(0x41, 0x56); /* push r14 */
|
||||
if (callee_regs_used[3])
|
||||
EMIT2(0x41, 0x57); /* push r15 */
|
||||
*pprog = prog;
|
||||
}
|
||||
|
||||
static void pop_callee_regs(u8 **pprog, bool *callee_regs_used)
|
||||
{
|
||||
u8 *prog = *pprog;
|
||||
int cnt = 0;
|
||||
|
||||
if (callee_regs_used[3])
|
||||
EMIT2(0x41, 0x5F); /* pop r15 */
|
||||
if (callee_regs_used[2])
|
||||
EMIT2(0x41, 0x5E); /* pop r14 */
|
||||
if (callee_regs_used[1])
|
||||
EMIT2(0x41, 0x5D); /* pop r13 */
|
||||
if (callee_regs_used[0])
|
||||
EMIT1(0x5B); /* pop rbx */
|
||||
*pprog = prog;
|
||||
}
|
||||
|
||||
/*
|
||||
* Emit x86-64 prologue code for BPF program and check its size.
|
||||
* bpf_tail_call helper will skip it while jumping into another program
|
||||
* Emit x86-64 prologue code for BPF program.
|
||||
* bpf_tail_call helper will skip the first X86_TAIL_CALL_OFFSET bytes
|
||||
* while jumping to another program
|
||||
*/
|
||||
static void emit_prologue(u8 **pprog, u32 stack_depth, bool ebpf_from_cbpf)
|
||||
static void emit_prologue(u8 **pprog, u32 stack_depth, bool ebpf_from_cbpf,
|
||||
bool tail_call_reachable, bool is_subprog)
|
||||
{
|
||||
u8 *prog = *pprog;
|
||||
int cnt = X86_PATCH_SIZE;
|
||||
@@ -238,19 +272,19 @@ static void emit_prologue(u8 **pprog, u32 stack_depth, bool ebpf_from_cbpf)
|
||||
*/
|
||||
memcpy(prog, ideal_nops[NOP_ATOMIC5], cnt);
|
||||
prog += cnt;
|
||||
if (!ebpf_from_cbpf) {
|
||||
if (tail_call_reachable && !is_subprog)
|
||||
EMIT2(0x31, 0xC0); /* xor eax, eax */
|
||||
else
|
||||
EMIT2(0x66, 0x90); /* nop2 */
|
||||
}
|
||||
EMIT1(0x55); /* push rbp */
|
||||
EMIT3(0x48, 0x89, 0xE5); /* mov rbp, rsp */
|
||||
/* sub rsp, rounded_stack_depth */
|
||||
if (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) {
|
||||
/* zero init tail_call_cnt */
|
||||
EMIT2(0x6a, 0x00);
|
||||
BUILD_BUG_ON(cnt != PROLOGUE_SIZE);
|
||||
}
|
||||
if (tail_call_reachable)
|
||||
EMIT1(0x50); /* push rax */
|
||||
*pprog = prog;
|
||||
}
|
||||
|
||||
@@ -314,13 +348,14 @@ static int __bpf_arch_text_poke(void *ip, enum bpf_text_poke_type t,
|
||||
mutex_lock(&text_mutex);
|
||||
if (memcmp(ip, old_insn, X86_PATCH_SIZE))
|
||||
goto out;
|
||||
ret = 1;
|
||||
if (memcmp(ip, new_insn, X86_PATCH_SIZE)) {
|
||||
if (text_live)
|
||||
text_poke_bp(ip, new_insn, X86_PATCH_SIZE, NULL);
|
||||
else
|
||||
memcpy(ip, new_insn, X86_PATCH_SIZE);
|
||||
}
|
||||
ret = 0;
|
||||
}
|
||||
out:
|
||||
mutex_unlock(&text_mutex);
|
||||
return ret;
|
||||
@@ -337,6 +372,22 @@ int bpf_arch_text_poke(void *ip, enum bpf_text_poke_type t,
|
||||
return __bpf_arch_text_poke(ip, t, old_addr, new_addr, true);
|
||||
}
|
||||
|
||||
static int get_pop_bytes(bool *callee_regs_used)
|
||||
{
|
||||
int bytes = 0;
|
||||
|
||||
if (callee_regs_used[3])
|
||||
bytes += 2;
|
||||
if (callee_regs_used[2])
|
||||
bytes += 2;
|
||||
if (callee_regs_used[1])
|
||||
bytes += 2;
|
||||
if (callee_regs_used[0])
|
||||
bytes += 1;
|
||||
|
||||
return bytes;
|
||||
}
|
||||
|
||||
/*
|
||||
* Generate the following code:
|
||||
*
|
||||
@@ -351,12 +402,32 @@ int bpf_arch_text_poke(void *ip, enum bpf_text_poke_type t,
|
||||
* goto *(prog->bpf_func + prologue_size);
|
||||
* out:
|
||||
*/
|
||||
static void emit_bpf_tail_call_indirect(u8 **pprog)
|
||||
static void emit_bpf_tail_call_indirect(u8 **pprog, bool *callee_regs_used,
|
||||
u32 stack_depth)
|
||||
{
|
||||
int tcc_off = -4 - round_up(stack_depth, 8);
|
||||
u8 *prog = *pprog;
|
||||
int label1, label2, label3;
|
||||
int pop_bytes = 0;
|
||||
int off1 = 42;
|
||||
int off2 = 31;
|
||||
int off3 = 9;
|
||||
int cnt = 0;
|
||||
|
||||
/* count the additional bytes used for popping callee regs from stack
|
||||
* that need to be taken into account for each of the offsets that
|
||||
* are used for bailing out of the tail call
|
||||
*/
|
||||
pop_bytes = get_pop_bytes(callee_regs_used);
|
||||
off1 += pop_bytes;
|
||||
off2 += pop_bytes;
|
||||
off3 += pop_bytes;
|
||||
|
||||
if (stack_depth) {
|
||||
off1 += 7;
|
||||
off2 += 7;
|
||||
off3 += 7;
|
||||
}
|
||||
|
||||
/*
|
||||
* rdi - pointer to ctx
|
||||
* rsi - pointer to bpf_array
|
||||
@@ -370,72 +441,112 @@ static void emit_bpf_tail_call_indirect(u8 **pprog)
|
||||
EMIT2(0x89, 0xD2); /* mov edx, edx */
|
||||
EMIT3(0x39, 0x56, /* cmp dword ptr [rsi + 16], edx */
|
||||
offsetof(struct bpf_array, map.max_entries));
|
||||
#define OFFSET1 (41 + RETPOLINE_RAX_BPF_JIT_SIZE) /* Number of bytes to jump */
|
||||
#define OFFSET1 (off1 + RETPOLINE_RCX_BPF_JIT_SIZE) /* Number of bytes to jump */
|
||||
EMIT2(X86_JBE, OFFSET1); /* jbe out */
|
||||
label1 = cnt;
|
||||
|
||||
/*
|
||||
* if (tail_call_cnt > MAX_TAIL_CALL_CNT)
|
||||
* goto out;
|
||||
*/
|
||||
EMIT2_off32(0x8B, 0x85, -36 - MAX_BPF_STACK); /* mov eax, dword ptr [rbp - 548] */
|
||||
EMIT2_off32(0x8B, 0x85, tcc_off); /* mov eax, dword ptr [rbp - tcc_off] */
|
||||
EMIT3(0x83, 0xF8, MAX_TAIL_CALL_CNT); /* cmp eax, MAX_TAIL_CALL_CNT */
|
||||
#define OFFSET2 (30 + RETPOLINE_RAX_BPF_JIT_SIZE)
|
||||
#define OFFSET2 (off2 + RETPOLINE_RCX_BPF_JIT_SIZE)
|
||||
EMIT2(X86_JA, OFFSET2); /* ja out */
|
||||
label2 = cnt;
|
||||
EMIT3(0x83, 0xC0, 0x01); /* add eax, 1 */
|
||||
EMIT2_off32(0x89, 0x85, -36 - MAX_BPF_STACK); /* mov dword ptr [rbp -548], eax */
|
||||
EMIT2_off32(0x89, 0x85, tcc_off); /* mov dword ptr [rbp - tcc_off], eax */
|
||||
|
||||
/* prog = array->ptrs[index]; */
|
||||
EMIT4_off32(0x48, 0x8B, 0x84, 0xD6, /* mov rax, [rsi + rdx * 8 + offsetof(...)] */
|
||||
EMIT4_off32(0x48, 0x8B, 0x8C, 0xD6, /* mov rcx, [rsi + rdx * 8 + offsetof(...)] */
|
||||
offsetof(struct bpf_array, ptrs));
|
||||
|
||||
/*
|
||||
* if (prog == NULL)
|
||||
* goto out;
|
||||
*/
|
||||
EMIT3(0x48, 0x85, 0xC0); /* test rax,rax */
|
||||
#define OFFSET3 (8 + RETPOLINE_RAX_BPF_JIT_SIZE)
|
||||
EMIT3(0x48, 0x85, 0xC9); /* test rcx,rcx */
|
||||
#define OFFSET3 (off3 + RETPOLINE_RCX_BPF_JIT_SIZE)
|
||||
EMIT2(X86_JE, OFFSET3); /* je out */
|
||||
label3 = cnt;
|
||||
|
||||
/* goto *(prog->bpf_func + prologue_size); */
|
||||
EMIT4(0x48, 0x8B, 0x40, /* mov rax, qword ptr [rax + 32] */
|
||||
*pprog = prog;
|
||||
pop_callee_regs(pprog, callee_regs_used);
|
||||
prog = *pprog;
|
||||
|
||||
EMIT1(0x58); /* pop rax */
|
||||
if (stack_depth)
|
||||
EMIT3_off32(0x48, 0x81, 0xC4, /* add rsp, sd */
|
||||
round_up(stack_depth, 8));
|
||||
|
||||
/* goto *(prog->bpf_func + X86_TAIL_CALL_OFFSET); */
|
||||
EMIT4(0x48, 0x8B, 0x49, /* mov rcx, qword ptr [rcx + 32] */
|
||||
offsetof(struct bpf_prog, bpf_func));
|
||||
EMIT4(0x48, 0x83, 0xC0, PROLOGUE_SIZE); /* add rax, prologue_size */
|
||||
|
||||
EMIT4(0x48, 0x83, 0xC1, /* add rcx, X86_TAIL_CALL_OFFSET */
|
||||
X86_TAIL_CALL_OFFSET);
|
||||
/*
|
||||
* Wow we're ready to jump into next BPF program
|
||||
* Now we're ready to jump into next BPF program
|
||||
* rdi == ctx (1st arg)
|
||||
* rax == prog->bpf_func + prologue_size
|
||||
* rcx == prog->bpf_func + X86_TAIL_CALL_OFFSET
|
||||
*/
|
||||
RETPOLINE_RAX_BPF_JIT();
|
||||
RETPOLINE_RCX_BPF_JIT();
|
||||
|
||||
/* out: */
|
||||
BUILD_BUG_ON(cnt - label1 != OFFSET1);
|
||||
BUILD_BUG_ON(cnt - label2 != OFFSET2);
|
||||
BUILD_BUG_ON(cnt - label3 != OFFSET3);
|
||||
*pprog = prog;
|
||||
}
|
||||
|
||||
static void emit_bpf_tail_call_direct(struct bpf_jit_poke_descriptor *poke,
|
||||
u8 **pprog, int addr, u8 *image)
|
||||
u8 **pprog, int addr, u8 *image,
|
||||
bool *callee_regs_used, u32 stack_depth)
|
||||
{
|
||||
int tcc_off = -4 - round_up(stack_depth, 8);
|
||||
u8 *prog = *pprog;
|
||||
int pop_bytes = 0;
|
||||
int off1 = 20;
|
||||
int poke_off;
|
||||
int cnt = 0;
|
||||
|
||||
/* count the additional bytes used for popping callee regs to stack
|
||||
* that need to be taken into account for jump offset that is used for
|
||||
* bailing out from of the tail call when limit is reached
|
||||
*/
|
||||
pop_bytes = get_pop_bytes(callee_regs_used);
|
||||
off1 += pop_bytes;
|
||||
|
||||
/*
|
||||
* total bytes for:
|
||||
* - nop5/ jmpq $off
|
||||
* - pop callee regs
|
||||
* - sub rsp, $val if depth > 0
|
||||
* - pop rax
|
||||
*/
|
||||
poke_off = X86_PATCH_SIZE + pop_bytes + 1;
|
||||
if (stack_depth) {
|
||||
poke_off += 7;
|
||||
off1 += 7;
|
||||
}
|
||||
|
||||
/*
|
||||
* if (tail_call_cnt > MAX_TAIL_CALL_CNT)
|
||||
* goto out;
|
||||
*/
|
||||
EMIT2_off32(0x8B, 0x85, -36 - MAX_BPF_STACK); /* mov eax, dword ptr [rbp - 548] */
|
||||
EMIT2_off32(0x8B, 0x85, tcc_off); /* mov eax, dword ptr [rbp - tcc_off] */
|
||||
EMIT3(0x83, 0xF8, MAX_TAIL_CALL_CNT); /* cmp eax, MAX_TAIL_CALL_CNT */
|
||||
EMIT2(X86_JA, 14); /* ja out */
|
||||
EMIT2(X86_JA, off1); /* ja out */
|
||||
EMIT3(0x83, 0xC0, 0x01); /* add eax, 1 */
|
||||
EMIT2_off32(0x89, 0x85, -36 - MAX_BPF_STACK); /* mov dword ptr [rbp -548], eax */
|
||||
EMIT2_off32(0x89, 0x85, tcc_off); /* mov dword ptr [rbp - tcc_off], eax */
|
||||
|
||||
poke->ip = image + (addr - X86_PATCH_SIZE);
|
||||
poke->adj_off = PROLOGUE_SIZE;
|
||||
poke->tailcall_bypass = image + (addr - poke_off - X86_PATCH_SIZE);
|
||||
poke->adj_off = X86_TAIL_CALL_OFFSET;
|
||||
poke->tailcall_target = image + (addr - X86_PATCH_SIZE);
|
||||
poke->bypass_addr = (u8 *)poke->tailcall_target + X86_PATCH_SIZE;
|
||||
|
||||
emit_jump(&prog, (u8 *)poke->tailcall_target + X86_PATCH_SIZE,
|
||||
poke->tailcall_bypass);
|
||||
|
||||
*pprog = prog;
|
||||
pop_callee_regs(pprog, callee_regs_used);
|
||||
prog = *pprog;
|
||||
EMIT1(0x58); /* pop rax */
|
||||
if (stack_depth)
|
||||
EMIT3_off32(0x48, 0x81, 0xC4, round_up(stack_depth, 8));
|
||||
|
||||
memcpy(prog, ideal_nops[NOP_ATOMIC5], X86_PATCH_SIZE);
|
||||
prog += X86_PATCH_SIZE;
|
||||
@@ -453,7 +564,7 @@ static void bpf_tail_call_direct_fixup(struct bpf_prog *prog)
|
||||
|
||||
for (i = 0; i < prog->aux->size_poke_tab; i++) {
|
||||
poke = &prog->aux->poke_tab[i];
|
||||
WARN_ON_ONCE(READ_ONCE(poke->ip_stable));
|
||||
WARN_ON_ONCE(READ_ONCE(poke->tailcall_target_stable));
|
||||
|
||||
if (poke->reason != BPF_POKE_REASON_TAIL_CALL)
|
||||
continue;
|
||||
@@ -464,18 +575,25 @@ static void bpf_tail_call_direct_fixup(struct bpf_prog *prog)
|
||||
if (target) {
|
||||
/* Plain memcpy is used when image is not live yet
|
||||
* and still not locked as read-only. Once poke
|
||||
* location is active (poke->ip_stable), any parallel
|
||||
* bpf_arch_text_poke() might occur still on the
|
||||
* read-write image until we finally locked it as
|
||||
* read-only. Both modifications on the given image
|
||||
* are under text_mutex to avoid interference.
|
||||
* location is active (poke->tailcall_target_stable),
|
||||
* any parallel bpf_arch_text_poke() might occur
|
||||
* still on the read-write image until we finally
|
||||
* locked it as read-only. Both modifications on
|
||||
* the given image are under text_mutex to avoid
|
||||
* interference.
|
||||
*/
|
||||
ret = __bpf_arch_text_poke(poke->ip, BPF_MOD_JUMP, NULL,
|
||||
ret = __bpf_arch_text_poke(poke->tailcall_target,
|
||||
BPF_MOD_JUMP, NULL,
|
||||
(u8 *)target->bpf_func +
|
||||
poke->adj_off, false);
|
||||
BUG_ON(ret < 0);
|
||||
ret = __bpf_arch_text_poke(poke->tailcall_bypass,
|
||||
BPF_MOD_JUMP,
|
||||
(u8 *)poke->tailcall_target +
|
||||
X86_PATCH_SIZE, NULL, false);
|
||||
BUG_ON(ret < 0);
|
||||
}
|
||||
WRITE_ONCE(poke->ip_stable, true);
|
||||
WRITE_ONCE(poke->tailcall_target_stable, true);
|
||||
mutex_unlock(&array->aux->poke_mutex);
|
||||
}
|
||||
}
|
||||
@@ -652,19 +770,49 @@ static bool ex_handler_bpf(const struct exception_table_entry *x,
|
||||
return true;
|
||||
}
|
||||
|
||||
static void detect_reg_usage(struct bpf_insn *insn, int insn_cnt,
|
||||
bool *regs_used, bool *tail_call_seen)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 1; i <= insn_cnt; i++, insn++) {
|
||||
if (insn->code == (BPF_JMP | BPF_TAIL_CALL))
|
||||
*tail_call_seen = true;
|
||||
if (insn->dst_reg == BPF_REG_6 || insn->src_reg == BPF_REG_6)
|
||||
regs_used[0] = true;
|
||||
if (insn->dst_reg == BPF_REG_7 || insn->src_reg == BPF_REG_7)
|
||||
regs_used[1] = true;
|
||||
if (insn->dst_reg == BPF_REG_8 || insn->src_reg == BPF_REG_8)
|
||||
regs_used[2] = true;
|
||||
if (insn->dst_reg == BPF_REG_9 || insn->src_reg == BPF_REG_9)
|
||||
regs_used[3] = true;
|
||||
}
|
||||
}
|
||||
|
||||
static int do_jit(struct bpf_prog *bpf_prog, int *addrs, u8 *image,
|
||||
int oldproglen, struct jit_context *ctx)
|
||||
{
|
||||
bool tail_call_reachable = bpf_prog->aux->tail_call_reachable;
|
||||
struct bpf_insn *insn = bpf_prog->insnsi;
|
||||
bool callee_regs_used[4] = {};
|
||||
int insn_cnt = bpf_prog->len;
|
||||
bool tail_call_seen = false;
|
||||
bool seen_exit = false;
|
||||
u8 temp[BPF_MAX_INSN_SIZE + BPF_INSN_SAFETY];
|
||||
int i, cnt = 0, excnt = 0;
|
||||
int proglen = 0;
|
||||
u8 *prog = temp;
|
||||
|
||||
detect_reg_usage(insn, insn_cnt, callee_regs_used,
|
||||
&tail_call_seen);
|
||||
|
||||
/* tail call's presence in current prog implies it is reachable */
|
||||
tail_call_reachable |= tail_call_seen;
|
||||
|
||||
emit_prologue(&prog, bpf_prog->aux->stack_depth,
|
||||
bpf_prog_was_classic(bpf_prog));
|
||||
bpf_prog_was_classic(bpf_prog), tail_call_reachable,
|
||||
bpf_prog->aux->func_idx != 0);
|
||||
push_callee_regs(&prog, callee_regs_used);
|
||||
addrs[0] = prog - temp;
|
||||
|
||||
for (i = 1; i <= insn_cnt; i++, insn++) {
|
||||
@@ -1102,16 +1250,27 @@ xadd: if (is_imm8(insn->off))
|
||||
/* call */
|
||||
case BPF_JMP | BPF_CALL:
|
||||
func = (u8 *) __bpf_call_base + imm32;
|
||||
if (tail_call_reachable) {
|
||||
EMIT3_off32(0x48, 0x8B, 0x85,
|
||||
-(bpf_prog->aux->stack_depth + 8));
|
||||
if (!imm32 || emit_call(&prog, func, image + addrs[i - 1] + 7))
|
||||
return -EINVAL;
|
||||
} else {
|
||||
if (!imm32 || emit_call(&prog, func, image + addrs[i - 1]))
|
||||
return -EINVAL;
|
||||
}
|
||||
break;
|
||||
|
||||
case BPF_JMP | BPF_TAIL_CALL:
|
||||
if (imm32)
|
||||
emit_bpf_tail_call_direct(&bpf_prog->aux->poke_tab[imm32 - 1],
|
||||
&prog, addrs[i], image);
|
||||
&prog, addrs[i], image,
|
||||
callee_regs_used,
|
||||
bpf_prog->aux->stack_depth);
|
||||
else
|
||||
emit_bpf_tail_call_indirect(&prog);
|
||||
emit_bpf_tail_call_indirect(&prog,
|
||||
callee_regs_used,
|
||||
bpf_prog->aux->stack_depth);
|
||||
break;
|
||||
|
||||
/* cond jump */
|
||||
@@ -1294,12 +1453,7 @@ emit_jmp:
|
||||
seen_exit = true;
|
||||
/* Update cleanup_addr */
|
||||
ctx->cleanup_addr = proglen;
|
||||
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 */
|
||||
pop_callee_regs(&prog, callee_regs_used);
|
||||
EMIT1(0xC9); /* leave */
|
||||
EMIT1(0xC3); /* ret */
|
||||
break;
|
||||
@@ -1379,10 +1533,15 @@ static int invoke_bpf_prog(const struct btf_func_model *m, u8 **pprog,
|
||||
u8 *prog = *pprog;
|
||||
int cnt = 0;
|
||||
|
||||
if (p->aux->sleepable) {
|
||||
if (emit_call(&prog, __bpf_prog_enter_sleepable, prog))
|
||||
return -EINVAL;
|
||||
} else {
|
||||
if (emit_call(&prog, __bpf_prog_enter, prog))
|
||||
return -EINVAL;
|
||||
/* remember prog start time returned by __bpf_prog_enter */
|
||||
emit_mov_reg(&prog, true, BPF_REG_6, BPF_REG_0);
|
||||
}
|
||||
|
||||
/* arg1: lea rdi, [rbp - stack_size] */
|
||||
EMIT4(0x48, 0x8D, 0x7D, -stack_size);
|
||||
@@ -1402,6 +1561,10 @@ static int invoke_bpf_prog(const struct btf_func_model *m, u8 **pprog,
|
||||
if (mod_ret)
|
||||
emit_stx(&prog, BPF_DW, BPF_REG_FP, BPF_REG_0, -8);
|
||||
|
||||
if (p->aux->sleepable) {
|
||||
if (emit_call(&prog, __bpf_prog_exit_sleepable, prog))
|
||||
return -EINVAL;
|
||||
} else {
|
||||
/* arg1: mov rdi, progs[i] */
|
||||
emit_mov_imm64(&prog, BPF_REG_1, (long) p >> 32,
|
||||
(u32) (long) p);
|
||||
@@ -1409,6 +1572,7 @@ static int invoke_bpf_prog(const struct btf_func_model *m, u8 **pprog,
|
||||
emit_mov_reg(&prog, true, BPF_REG_2, BPF_REG_6);
|
||||
if (emit_call(&prog, __bpf_prog_exit, prog))
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
*pprog = prog;
|
||||
return 0;
|
||||
|
@@ -327,7 +327,7 @@ done:
|
||||
*/
|
||||
|
||||
|
||||
static struct atmdev_ops atmtcp_v_dev_ops = {
|
||||
static const struct atmdev_ops atmtcp_v_dev_ops = {
|
||||
.dev_close = atmtcp_v_dev_close,
|
||||
.open = atmtcp_v_open,
|
||||
.close = atmtcp_v_close,
|
||||
|
@@ -419,12 +419,12 @@ void bcma_core_pci_hostmode_init(struct bcma_drv_pci *pc)
|
||||
pc_host->pci_ops.read = bcma_core_pci_hostmode_read_config;
|
||||
pc_host->pci_ops.write = bcma_core_pci_hostmode_write_config;
|
||||
|
||||
pc_host->mem_resource.name = "BCMA PCIcore external memory",
|
||||
pc_host->mem_resource.name = "BCMA PCIcore external memory";
|
||||
pc_host->mem_resource.start = BCMA_SOC_PCI_DMA;
|
||||
pc_host->mem_resource.end = BCMA_SOC_PCI_DMA + BCMA_SOC_PCI_DMA_SZ - 1;
|
||||
pc_host->mem_resource.flags = IORESOURCE_MEM | IORESOURCE_PCI_FIXED;
|
||||
|
||||
pc_host->io_resource.name = "BCMA PCIcore external I/O",
|
||||
pc_host->io_resource.name = "BCMA PCIcore external I/O";
|
||||
pc_host->io_resource.start = 0x100;
|
||||
pc_host->io_resource.end = 0x7FF;
|
||||
pc_host->io_resource.flags = IORESOURCE_IO | IORESOURCE_PCI_FIXED;
|
||||
|
@@ -2184,7 +2184,7 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct genl_ops nbd_connect_genl_ops[] = {
|
||||
static const struct genl_small_ops nbd_connect_genl_ops[] = {
|
||||
{
|
||||
.cmd = NBD_CMD_CONNECT,
|
||||
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
|
||||
@@ -2216,8 +2216,8 @@ static struct genl_family nbd_genl_family __ro_after_init = {
|
||||
.name = NBD_GENL_FAMILY_NAME,
|
||||
.version = NBD_GENL_VERSION,
|
||||
.module = THIS_MODULE,
|
||||
.ops = nbd_connect_genl_ops,
|
||||
.n_ops = ARRAY_SIZE(nbd_connect_genl_ops),
|
||||
.small_ops = nbd_connect_genl_ops,
|
||||
.n_small_ops = ARRAY_SIZE(nbd_connect_genl_ops),
|
||||
.maxattr = NBD_ATTR_MAX,
|
||||
.policy = nbd_attr_policy,
|
||||
.mcgrps = nbd_mcast_grps,
|
||||
|
@@ -19,6 +19,10 @@
|
||||
#define VERSION "0.1"
|
||||
|
||||
#define BDADDR_INTEL (&(bdaddr_t){{0x00, 0x8b, 0x9e, 0x19, 0x03, 0x00}})
|
||||
#define RSA_HEADER_LEN 644
|
||||
#define CSS_HEADER_OFFSET 8
|
||||
#define ECDSA_OFFSET 644
|
||||
#define ECDSA_HEADER_LEN 320
|
||||
|
||||
int btintel_check_bdaddr(struct hci_dev *hdev)
|
||||
{
|
||||
@@ -360,6 +364,144 @@ int btintel_read_version(struct hci_dev *hdev, struct intel_version *ver)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(btintel_read_version);
|
||||
|
||||
void btintel_version_info_tlv(struct hci_dev *hdev, struct intel_version_tlv *version)
|
||||
{
|
||||
const char *variant;
|
||||
|
||||
switch (version->img_type) {
|
||||
case 0x01:
|
||||
variant = "Bootloader";
|
||||
bt_dev_info(hdev, "Device revision is %u", version->dev_rev_id);
|
||||
bt_dev_info(hdev, "Secure boot is %s",
|
||||
version->secure_boot ? "enabled" : "disabled");
|
||||
bt_dev_info(hdev, "OTP lock is %s",
|
||||
version->otp_lock ? "enabled" : "disabled");
|
||||
bt_dev_info(hdev, "API lock is %s",
|
||||
version->api_lock ? "enabled" : "disabled");
|
||||
bt_dev_info(hdev, "Debug lock is %s",
|
||||
version->debug_lock ? "enabled" : "disabled");
|
||||
bt_dev_info(hdev, "Minimum firmware build %u week %u %u",
|
||||
version->min_fw_build_nn, version->min_fw_build_cw,
|
||||
2000 + version->min_fw_build_yy);
|
||||
break;
|
||||
case 0x03:
|
||||
variant = "Firmware";
|
||||
break;
|
||||
default:
|
||||
bt_dev_err(hdev, "Unsupported image type(%02x)", version->img_type);
|
||||
goto done;
|
||||
}
|
||||
|
||||
bt_dev_info(hdev, "%s timestamp %u.%u buildtype %u build %u", variant,
|
||||
2000 + (version->timestamp >> 8), version->timestamp & 0xff,
|
||||
version->build_type, version->build_num);
|
||||
|
||||
done:
|
||||
return;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(btintel_version_info_tlv);
|
||||
|
||||
int btintel_read_version_tlv(struct hci_dev *hdev, struct intel_version_tlv *version)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
const u8 param[1] = { 0xFF };
|
||||
|
||||
if (!version)
|
||||
return -EINVAL;
|
||||
|
||||
skb = __hci_cmd_sync(hdev, 0xfc05, 1, param, HCI_CMD_TIMEOUT);
|
||||
if (IS_ERR(skb)) {
|
||||
bt_dev_err(hdev, "Reading Intel version information failed (%ld)",
|
||||
PTR_ERR(skb));
|
||||
return PTR_ERR(skb);
|
||||
}
|
||||
|
||||
if (skb->data[0]) {
|
||||
bt_dev_err(hdev, "Intel Read Version command failed (%02x)",
|
||||
skb->data[0]);
|
||||
kfree_skb(skb);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/* Consume Command Complete Status field */
|
||||
skb_pull(skb, 1);
|
||||
|
||||
/* Event parameters contatin multiple TLVs. Read each of them
|
||||
* and only keep the required data. Also, it use existing legacy
|
||||
* version field like hw_platform, hw_variant, and fw_variant
|
||||
* to keep the existing setup flow
|
||||
*/
|
||||
while (skb->len) {
|
||||
struct intel_tlv *tlv;
|
||||
|
||||
tlv = (struct intel_tlv *)skb->data;
|
||||
switch (tlv->type) {
|
||||
case INTEL_TLV_CNVI_TOP:
|
||||
version->cnvi_top = get_unaligned_le32(tlv->val);
|
||||
break;
|
||||
case INTEL_TLV_CNVR_TOP:
|
||||
version->cnvr_top = get_unaligned_le32(tlv->val);
|
||||
break;
|
||||
case INTEL_TLV_CNVI_BT:
|
||||
version->cnvi_bt = get_unaligned_le32(tlv->val);
|
||||
break;
|
||||
case INTEL_TLV_CNVR_BT:
|
||||
version->cnvr_bt = get_unaligned_le32(tlv->val);
|
||||
break;
|
||||
case INTEL_TLV_DEV_REV_ID:
|
||||
version->dev_rev_id = get_unaligned_le16(tlv->val);
|
||||
break;
|
||||
case INTEL_TLV_IMAGE_TYPE:
|
||||
version->img_type = tlv->val[0];
|
||||
break;
|
||||
case INTEL_TLV_TIME_STAMP:
|
||||
version->timestamp = get_unaligned_le16(tlv->val);
|
||||
break;
|
||||
case INTEL_TLV_BUILD_TYPE:
|
||||
version->build_type = tlv->val[0];
|
||||
break;
|
||||
case INTEL_TLV_BUILD_NUM:
|
||||
version->build_num = get_unaligned_le32(tlv->val);
|
||||
break;
|
||||
case INTEL_TLV_SECURE_BOOT:
|
||||
version->secure_boot = tlv->val[0];
|
||||
break;
|
||||
case INTEL_TLV_OTP_LOCK:
|
||||
version->otp_lock = tlv->val[0];
|
||||
break;
|
||||
case INTEL_TLV_API_LOCK:
|
||||
version->api_lock = tlv->val[0];
|
||||
break;
|
||||
case INTEL_TLV_DEBUG_LOCK:
|
||||
version->debug_lock = tlv->val[0];
|
||||
break;
|
||||
case INTEL_TLV_MIN_FW:
|
||||
version->min_fw_build_nn = tlv->val[0];
|
||||
version->min_fw_build_cw = tlv->val[1];
|
||||
version->min_fw_build_yy = tlv->val[2];
|
||||
break;
|
||||
case INTEL_TLV_LIMITED_CCE:
|
||||
version->limited_cce = tlv->val[0];
|
||||
break;
|
||||
case INTEL_TLV_SBE_TYPE:
|
||||
version->sbe_type = tlv->val[0];
|
||||
break;
|
||||
case INTEL_TLV_OTP_BDADDR:
|
||||
memcpy(&version->otp_bd_addr, tlv->val, tlv->len);
|
||||
break;
|
||||
default:
|
||||
/* Ignore rest of information */
|
||||
break;
|
||||
}
|
||||
/* consume the current tlv and move to next*/
|
||||
skb_pull(skb, tlv->len + sizeof(*tlv));
|
||||
}
|
||||
|
||||
kfree_skb(skb);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(btintel_read_version_tlv);
|
||||
|
||||
/* ------- REGMAP IBT SUPPORT ------- */
|
||||
|
||||
#define IBT_REG_MODE_8BIT 0x00
|
||||
@@ -626,12 +768,10 @@ int btintel_read_boot_params(struct hci_dev *hdev,
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(btintel_read_boot_params);
|
||||
|
||||
int btintel_download_firmware(struct hci_dev *hdev, const struct firmware *fw,
|
||||
u32 *boot_param)
|
||||
static int btintel_sfi_rsa_header_secure_send(struct hci_dev *hdev,
|
||||
const struct firmware *fw)
|
||||
{
|
||||
int err;
|
||||
const u8 *fw_ptr;
|
||||
u32 frag_len;
|
||||
|
||||
/* Start the firmware download transaction with the Init fragment
|
||||
* represented by the 128 bytes of CSS header.
|
||||
@@ -660,8 +800,56 @@ int btintel_download_firmware(struct hci_dev *hdev, const struct firmware *fw,
|
||||
goto done;
|
||||
}
|
||||
|
||||
fw_ptr = fw->data + 644;
|
||||
done:
|
||||
return err;
|
||||
}
|
||||
|
||||
static int btintel_sfi_ecdsa_header_secure_send(struct hci_dev *hdev,
|
||||
const struct firmware *fw)
|
||||
{
|
||||
int err;
|
||||
|
||||
/* Start the firmware download transaction with the Init fragment
|
||||
* represented by the 128 bytes of CSS header.
|
||||
*/
|
||||
err = btintel_secure_send(hdev, 0x00, 128, fw->data + 644);
|
||||
if (err < 0) {
|
||||
bt_dev_err(hdev, "Failed to send firmware header (%d)", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Send the 96 bytes of public key information from the firmware
|
||||
* as the PKey fragment.
|
||||
*/
|
||||
err = btintel_secure_send(hdev, 0x03, 96, fw->data + 644 + 128);
|
||||
if (err < 0) {
|
||||
bt_dev_err(hdev, "Failed to send firmware pkey (%d)", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Send the 96 bytes of signature information from the firmware
|
||||
* as the Sign fragment
|
||||
*/
|
||||
err = btintel_secure_send(hdev, 0x02, 96, fw->data + 644 + 224);
|
||||
if (err < 0) {
|
||||
bt_dev_err(hdev, "Failed to send firmware signature (%d)",
|
||||
err);
|
||||
return err;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int btintel_download_firmware_payload(struct hci_dev *hdev,
|
||||
const struct firmware *fw,
|
||||
u32 *boot_param, size_t offset)
|
||||
{
|
||||
int err;
|
||||
const u8 *fw_ptr;
|
||||
u32 frag_len;
|
||||
|
||||
fw_ptr = fw->data + offset;
|
||||
frag_len = 0;
|
||||
err = -EINVAL;
|
||||
|
||||
while (fw_ptr - fw->data < fw->size) {
|
||||
struct hci_command_hdr *cmd = (void *)(fw_ptr + frag_len);
|
||||
@@ -707,8 +895,99 @@ int btintel_download_firmware(struct hci_dev *hdev, const struct firmware *fw,
|
||||
done:
|
||||
return err;
|
||||
}
|
||||
|
||||
int btintel_download_firmware(struct hci_dev *hdev,
|
||||
const struct firmware *fw,
|
||||
u32 *boot_param)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = btintel_sfi_rsa_header_secure_send(hdev, fw);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
return btintel_download_firmware_payload(hdev, fw, boot_param,
|
||||
RSA_HEADER_LEN);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(btintel_download_firmware);
|
||||
|
||||
int btintel_download_firmware_newgen(struct hci_dev *hdev,
|
||||
const struct firmware *fw, u32 *boot_param,
|
||||
u8 hw_variant, u8 sbe_type)
|
||||
{
|
||||
int err;
|
||||
u32 css_header_ver;
|
||||
|
||||
/* iBT hardware variants 0x0b, 0x0c, 0x11, 0x12, 0x13, 0x14 support
|
||||
* only RSA secure boot engine. Hence, the corresponding sfi file will
|
||||
* have RSA header of 644 bytes followed by Command Buffer.
|
||||
*
|
||||
* iBT hardware variants 0x17, 0x18 onwards support both RSA and ECDSA
|
||||
* secure boot engine. As a result, the corresponding sfi file will
|
||||
* have RSA header of 644, ECDSA header of 320 bytes followed by
|
||||
* Command Buffer.
|
||||
*
|
||||
* CSS Header byte positions 0x08 to 0x0B represent the CSS Header
|
||||
* version: RSA(0x00010000) , ECDSA (0x00020000)
|
||||
*/
|
||||
css_header_ver = get_unaligned_le32(fw->data + CSS_HEADER_OFFSET);
|
||||
if (css_header_ver != 0x00010000) {
|
||||
bt_dev_err(hdev, "Invalid CSS Header version");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (hw_variant <= 0x14) {
|
||||
if (sbe_type != 0x00) {
|
||||
bt_dev_err(hdev, "Invalid SBE type for hardware variant (%d)",
|
||||
hw_variant);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
err = btintel_sfi_rsa_header_secure_send(hdev, fw);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = btintel_download_firmware_payload(hdev, fw, boot_param, RSA_HEADER_LEN);
|
||||
if (err)
|
||||
return err;
|
||||
} else if (hw_variant >= 0x17) {
|
||||
/* Check if CSS header for ECDSA follows the RSA header */
|
||||
if (fw->data[ECDSA_OFFSET] != 0x06)
|
||||
return -EINVAL;
|
||||
|
||||
/* Check if the CSS Header version is ECDSA(0x00020000) */
|
||||
css_header_ver = get_unaligned_le32(fw->data + ECDSA_OFFSET + CSS_HEADER_OFFSET);
|
||||
if (css_header_ver != 0x00020000) {
|
||||
bt_dev_err(hdev, "Invalid CSS Header version");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (sbe_type == 0x00) {
|
||||
err = btintel_sfi_rsa_header_secure_send(hdev, fw);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = btintel_download_firmware_payload(hdev, fw,
|
||||
boot_param,
|
||||
RSA_HEADER_LEN + ECDSA_HEADER_LEN);
|
||||
if (err)
|
||||
return err;
|
||||
} else if (sbe_type == 0x01) {
|
||||
err = btintel_sfi_ecdsa_header_secure_send(hdev, fw);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = btintel_download_firmware_payload(hdev, fw,
|
||||
boot_param,
|
||||
RSA_HEADER_LEN + ECDSA_HEADER_LEN);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(btintel_download_firmware_newgen);
|
||||
|
||||
void btintel_reset_to_bootloader(struct hci_dev *hdev)
|
||||
{
|
||||
struct intel_reset params;
|
||||
|
@@ -6,6 +6,72 @@
|
||||
* Copyright (C) 2015 Intel Corporation
|
||||
*/
|
||||
|
||||
/* List of tlv type */
|
||||
enum {
|
||||
INTEL_TLV_CNVI_TOP = 0x10,
|
||||
INTEL_TLV_CNVR_TOP,
|
||||
INTEL_TLV_CNVI_BT,
|
||||
INTEL_TLV_CNVR_BT,
|
||||
INTEL_TLV_CNVI_OTP,
|
||||
INTEL_TLV_CNVR_OTP,
|
||||
INTEL_TLV_DEV_REV_ID,
|
||||
INTEL_TLV_USB_VENDOR_ID,
|
||||
INTEL_TLV_USB_PRODUCT_ID,
|
||||
INTEL_TLV_PCIE_VENDOR_ID,
|
||||
INTEL_TLV_PCIE_DEVICE_ID,
|
||||
INTEL_TLV_PCIE_SUBSYSTEM_ID,
|
||||
INTEL_TLV_IMAGE_TYPE,
|
||||
INTEL_TLV_TIME_STAMP,
|
||||
INTEL_TLV_BUILD_TYPE,
|
||||
INTEL_TLV_BUILD_NUM,
|
||||
INTEL_TLV_FW_BUILD_PRODUCT,
|
||||
INTEL_TLV_FW_BUILD_HW,
|
||||
INTEL_TLV_FW_STEP,
|
||||
INTEL_TLV_BT_SPEC,
|
||||
INTEL_TLV_MFG_NAME,
|
||||
INTEL_TLV_HCI_REV,
|
||||
INTEL_TLV_LMP_SUBVER,
|
||||
INTEL_TLV_OTP_PATCH_VER,
|
||||
INTEL_TLV_SECURE_BOOT,
|
||||
INTEL_TLV_KEY_FROM_HDR,
|
||||
INTEL_TLV_OTP_LOCK,
|
||||
INTEL_TLV_API_LOCK,
|
||||
INTEL_TLV_DEBUG_LOCK,
|
||||
INTEL_TLV_MIN_FW,
|
||||
INTEL_TLV_LIMITED_CCE,
|
||||
INTEL_TLV_SBE_TYPE,
|
||||
INTEL_TLV_OTP_BDADDR,
|
||||
INTEL_TLV_UNLOCKED_STATE
|
||||
};
|
||||
|
||||
struct intel_tlv {
|
||||
u8 type;
|
||||
u8 len;
|
||||
u8 val[0];
|
||||
} __packed;
|
||||
|
||||
struct intel_version_tlv {
|
||||
u32 cnvi_top;
|
||||
u32 cnvr_top;
|
||||
u32 cnvi_bt;
|
||||
u32 cnvr_bt;
|
||||
u16 dev_rev_id;
|
||||
u8 img_type;
|
||||
u16 timestamp;
|
||||
u8 build_type;
|
||||
u32 build_num;
|
||||
u8 secure_boot;
|
||||
u8 otp_lock;
|
||||
u8 api_lock;
|
||||
u8 debug_lock;
|
||||
u8 min_fw_build_nn;
|
||||
u8 min_fw_build_cw;
|
||||
u8 min_fw_build_yy;
|
||||
u8 limited_cce;
|
||||
u8 sbe_type;
|
||||
bdaddr_t otp_bd_addr;
|
||||
};
|
||||
|
||||
struct intel_version {
|
||||
u8 status;
|
||||
u8 hw_platform;
|
||||
@@ -77,12 +143,14 @@ int btintel_set_diag_mfg(struct hci_dev *hdev, bool enable);
|
||||
void btintel_hw_error(struct hci_dev *hdev, u8 code);
|
||||
|
||||
void btintel_version_info(struct hci_dev *hdev, struct intel_version *ver);
|
||||
void btintel_version_info_tlv(struct hci_dev *hdev, struct intel_version_tlv *version);
|
||||
int btintel_secure_send(struct hci_dev *hdev, u8 fragment_type, u32 plen,
|
||||
const void *param);
|
||||
int btintel_load_ddc_config(struct hci_dev *hdev, const char *ddc_name);
|
||||
int btintel_set_event_mask(struct hci_dev *hdev, bool debug);
|
||||
int btintel_set_event_mask_mfg(struct hci_dev *hdev, bool debug);
|
||||
int btintel_read_version(struct hci_dev *hdev, struct intel_version *ver);
|
||||
int btintel_read_version_tlv(struct hci_dev *hdev, struct intel_version_tlv *ver);
|
||||
|
||||
struct regmap *btintel_regmap_init(struct hci_dev *hdev, u16 opcode_read,
|
||||
u16 opcode_write);
|
||||
@@ -91,6 +159,10 @@ int btintel_read_boot_params(struct hci_dev *hdev,
|
||||
struct intel_boot_params *params);
|
||||
int btintel_download_firmware(struct hci_dev *dev, const struct firmware *fw,
|
||||
u32 *boot_param);
|
||||
int btintel_download_firmware_newgen(struct hci_dev *hdev,
|
||||
const struct firmware *fw,
|
||||
u32 *boot_param, u8 hw_variant,
|
||||
u8 sbe_type);
|
||||
void btintel_reset_to_bootloader(struct hci_dev *hdev);
|
||||
int btintel_read_debug_features(struct hci_dev *hdev,
|
||||
struct intel_debug_features *features);
|
||||
@@ -137,6 +209,11 @@ static inline void btintel_version_info(struct hci_dev *hdev,
|
||||
{
|
||||
}
|
||||
|
||||
static inline void btintel_version_info_tlv(struct hci_dev *hdev,
|
||||
struct intel_version_tlv *version)
|
||||
{
|
||||
}
|
||||
|
||||
static inline int btintel_secure_send(struct hci_dev *hdev, u8 fragment_type,
|
||||
u32 plen, const void *param)
|
||||
{
|
||||
@@ -165,6 +242,12 @@ static inline int btintel_read_version(struct hci_dev *hdev,
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static inline int btintel_read_version_tlv(struct hci_dev *hdev,
|
||||
struct intel_version_tlv *ver)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static inline struct regmap *btintel_regmap_init(struct hci_dev *hdev,
|
||||
u16 opcode_read,
|
||||
u16 opcode_write)
|
||||
@@ -191,6 +274,14 @@ static inline int btintel_download_firmware(struct hci_dev *dev,
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static inline int btintel_download_firmware_newgen(struct hci_dev *hdev,
|
||||
const struct firmware *fw,
|
||||
u32 *boot_param,
|
||||
u8 hw_variant, u8 sbe_type)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static inline void btintel_reset_to_bootloader(struct hci_dev *hdev)
|
||||
{
|
||||
}
|
||||
|
@@ -215,30 +215,7 @@ static const struct btmrvl_sdio_card_reg btmrvl_reg_8897 = {
|
||||
.fw_dump_end = 0xea,
|
||||
};
|
||||
|
||||
static const struct btmrvl_sdio_card_reg btmrvl_reg_8977 = {
|
||||
.cfg = 0x00,
|
||||
.host_int_mask = 0x08,
|
||||
.host_intstatus = 0x0c,
|
||||
.card_status = 0x5c,
|
||||
.sq_read_base_addr_a0 = 0xf8,
|
||||
.sq_read_base_addr_a1 = 0xf9,
|
||||
.card_revision = 0xc8,
|
||||
.card_fw_status0 = 0xe8,
|
||||
.card_fw_status1 = 0xe9,
|
||||
.card_rx_len = 0xea,
|
||||
.card_rx_unit = 0xeb,
|
||||
.io_port_0 = 0xe4,
|
||||
.io_port_1 = 0xe5,
|
||||
.io_port_2 = 0xe6,
|
||||
.int_read_to_clear = true,
|
||||
.host_int_rsr = 0x04,
|
||||
.card_misc_cfg = 0xD8,
|
||||
.fw_dump_ctrl = 0xf0,
|
||||
.fw_dump_start = 0xf1,
|
||||
.fw_dump_end = 0xf8,
|
||||
};
|
||||
|
||||
static const struct btmrvl_sdio_card_reg btmrvl_reg_8987 = {
|
||||
static const struct btmrvl_sdio_card_reg btmrvl_reg_89xx = {
|
||||
.cfg = 0x00,
|
||||
.host_int_mask = 0x08,
|
||||
.host_intstatus = 0x0c,
|
||||
@@ -261,29 +238,6 @@ static const struct btmrvl_sdio_card_reg btmrvl_reg_8987 = {
|
||||
.fw_dump_end = 0xf8,
|
||||
};
|
||||
|
||||
static const struct btmrvl_sdio_card_reg btmrvl_reg_8997 = {
|
||||
.cfg = 0x00,
|
||||
.host_int_mask = 0x08,
|
||||
.host_intstatus = 0x0c,
|
||||
.card_status = 0x5c,
|
||||
.sq_read_base_addr_a0 = 0xf8,
|
||||
.sq_read_base_addr_a1 = 0xf9,
|
||||
.card_revision = 0xc8,
|
||||
.card_fw_status0 = 0xe8,
|
||||
.card_fw_status1 = 0xe9,
|
||||
.card_rx_len = 0xea,
|
||||
.card_rx_unit = 0xeb,
|
||||
.io_port_0 = 0xe4,
|
||||
.io_port_1 = 0xe5,
|
||||
.io_port_2 = 0xe6,
|
||||
.int_read_to_clear = true,
|
||||
.host_int_rsr = 0x04,
|
||||
.card_misc_cfg = 0xD8,
|
||||
.fw_dump_ctrl = 0xf0,
|
||||
.fw_dump_start = 0xf1,
|
||||
.fw_dump_end = 0xf8,
|
||||
};
|
||||
|
||||
static const struct btmrvl_sdio_device btmrvl_sdio_sd8688 = {
|
||||
.helper = "mrvl/sd8688_helper.bin",
|
||||
.firmware = "mrvl/sd8688.bin",
|
||||
@@ -332,7 +286,7 @@ static const struct btmrvl_sdio_device btmrvl_sdio_sd8897 = {
|
||||
static const struct btmrvl_sdio_device btmrvl_sdio_sd8977 = {
|
||||
.helper = NULL,
|
||||
.firmware = "mrvl/sdsd8977_combo_v2.bin",
|
||||
.reg = &btmrvl_reg_8977,
|
||||
.reg = &btmrvl_reg_89xx,
|
||||
.support_pscan_win_report = true,
|
||||
.sd_blksz_fw_dl = 256,
|
||||
.supports_fw_dump = true,
|
||||
@@ -341,7 +295,7 @@ static const struct btmrvl_sdio_device btmrvl_sdio_sd8977 = {
|
||||
static const struct btmrvl_sdio_device btmrvl_sdio_sd8987 = {
|
||||
.helper = NULL,
|
||||
.firmware = "mrvl/sd8987_uapsta.bin",
|
||||
.reg = &btmrvl_reg_8987,
|
||||
.reg = &btmrvl_reg_89xx,
|
||||
.support_pscan_win_report = true,
|
||||
.sd_blksz_fw_dl = 256,
|
||||
.supports_fw_dump = true,
|
||||
@@ -350,7 +304,7 @@ static const struct btmrvl_sdio_device btmrvl_sdio_sd8987 = {
|
||||
static const struct btmrvl_sdio_device btmrvl_sdio_sd8997 = {
|
||||
.helper = NULL,
|
||||
.firmware = "mrvl/sdsd8997_combo_v4.bin",
|
||||
.reg = &btmrvl_reg_8997,
|
||||
.reg = &btmrvl_reg_89xx,
|
||||
.support_pscan_win_report = true,
|
||||
.sd_blksz_fw_dl = 256,
|
||||
.supports_fw_dump = true,
|
||||
|
@@ -496,7 +496,7 @@ static void btmtksdio_interrupt(struct sdio_func *func)
|
||||
sdio_claim_host(bdev->func);
|
||||
|
||||
/* Disable interrupt */
|
||||
sdio_writel(func, C_INT_EN_CLR, MTK_REG_CHLPCR, 0);
|
||||
sdio_writel(func, C_INT_EN_CLR, MTK_REG_CHLPCR, NULL);
|
||||
|
||||
int_status = sdio_readl(func, MTK_REG_CHISR, NULL);
|
||||
|
||||
@@ -530,7 +530,7 @@ static void btmtksdio_interrupt(struct sdio_func *func)
|
||||
}
|
||||
|
||||
/* Enable interrupt */
|
||||
sdio_writel(func, C_INT_EN_SET, MTK_REG_CHLPCR, 0);
|
||||
sdio_writel(func, C_INT_EN_SET, MTK_REG_CHLPCR, NULL);
|
||||
|
||||
pm_runtime_mark_last_busy(bdev->dev);
|
||||
pm_runtime_put_autosuspend(bdev->dev);
|
||||
|
@@ -59,6 +59,7 @@ static struct usb_driver btusb_driver;
|
||||
#define BTUSB_MEDIATEK 0x200000
|
||||
#define BTUSB_WIDEBAND_SPEECH 0x400000
|
||||
#define BTUSB_VALID_LE_STATES 0x800000
|
||||
#define BTUSB_QCA_WCN6855 0x1000000
|
||||
|
||||
static const struct usb_device_id btusb_table[] = {
|
||||
/* Generic Bluetooth USB device */
|
||||
@@ -254,24 +255,46 @@ static const struct usb_device_id blacklist_table[] = {
|
||||
{ USB_DEVICE(0x0489, 0xe03c), .driver_info = BTUSB_ATH3012 },
|
||||
|
||||
/* QCA ROME chipset */
|
||||
{ USB_DEVICE(0x0cf3, 0x535b), .driver_info = BTUSB_QCA_ROME },
|
||||
{ USB_DEVICE(0x0cf3, 0xe007), .driver_info = BTUSB_QCA_ROME },
|
||||
{ USB_DEVICE(0x0cf3, 0xe009), .driver_info = BTUSB_QCA_ROME },
|
||||
{ USB_DEVICE(0x0cf3, 0xe010), .driver_info = BTUSB_QCA_ROME },
|
||||
{ USB_DEVICE(0x0cf3, 0xe300), .driver_info = BTUSB_QCA_ROME },
|
||||
{ USB_DEVICE(0x0cf3, 0xe301), .driver_info = BTUSB_QCA_ROME },
|
||||
{ USB_DEVICE(0x0cf3, 0xe360), .driver_info = BTUSB_QCA_ROME },
|
||||
{ USB_DEVICE(0x0489, 0xe092), .driver_info = BTUSB_QCA_ROME },
|
||||
{ USB_DEVICE(0x0489, 0xe09f), .driver_info = BTUSB_QCA_ROME },
|
||||
{ USB_DEVICE(0x0489, 0xe0a2), .driver_info = BTUSB_QCA_ROME },
|
||||
{ USB_DEVICE(0x04ca, 0x3011), .driver_info = BTUSB_QCA_ROME },
|
||||
{ USB_DEVICE(0x04ca, 0x3015), .driver_info = BTUSB_QCA_ROME },
|
||||
{ USB_DEVICE(0x04ca, 0x3016), .driver_info = BTUSB_QCA_ROME },
|
||||
{ USB_DEVICE(0x04ca, 0x301a), .driver_info = BTUSB_QCA_ROME },
|
||||
{ USB_DEVICE(0x04ca, 0x3021), .driver_info = BTUSB_QCA_ROME },
|
||||
{ USB_DEVICE(0x13d3, 0x3491), .driver_info = BTUSB_QCA_ROME },
|
||||
{ USB_DEVICE(0x13d3, 0x3496), .driver_info = BTUSB_QCA_ROME },
|
||||
{ USB_DEVICE(0x13d3, 0x3501), .driver_info = BTUSB_QCA_ROME },
|
||||
{ USB_DEVICE(0x0cf3, 0x535b), .driver_info = BTUSB_QCA_ROME |
|
||||
BTUSB_WIDEBAND_SPEECH },
|
||||
{ USB_DEVICE(0x0cf3, 0xe007), .driver_info = BTUSB_QCA_ROME |
|
||||
BTUSB_WIDEBAND_SPEECH },
|
||||
{ USB_DEVICE(0x0cf3, 0xe009), .driver_info = BTUSB_QCA_ROME |
|
||||
BTUSB_WIDEBAND_SPEECH },
|
||||
{ USB_DEVICE(0x0cf3, 0xe010), .driver_info = BTUSB_QCA_ROME |
|
||||
BTUSB_WIDEBAND_SPEECH },
|
||||
{ USB_DEVICE(0x0cf3, 0xe300), .driver_info = BTUSB_QCA_ROME |
|
||||
BTUSB_WIDEBAND_SPEECH },
|
||||
{ USB_DEVICE(0x0cf3, 0xe301), .driver_info = BTUSB_QCA_ROME |
|
||||
BTUSB_WIDEBAND_SPEECH },
|
||||
{ USB_DEVICE(0x0cf3, 0xe360), .driver_info = BTUSB_QCA_ROME |
|
||||
BTUSB_WIDEBAND_SPEECH },
|
||||
{ USB_DEVICE(0x0489, 0xe092), .driver_info = BTUSB_QCA_ROME |
|
||||
BTUSB_WIDEBAND_SPEECH },
|
||||
{ USB_DEVICE(0x0489, 0xe09f), .driver_info = BTUSB_QCA_ROME |
|
||||
BTUSB_WIDEBAND_SPEECH },
|
||||
{ USB_DEVICE(0x0489, 0xe0a2), .driver_info = BTUSB_QCA_ROME |
|
||||
BTUSB_WIDEBAND_SPEECH },
|
||||
{ USB_DEVICE(0x04ca, 0x3011), .driver_info = BTUSB_QCA_ROME |
|
||||
BTUSB_WIDEBAND_SPEECH },
|
||||
{ USB_DEVICE(0x04ca, 0x3015), .driver_info = BTUSB_QCA_ROME |
|
||||
BTUSB_WIDEBAND_SPEECH },
|
||||
{ USB_DEVICE(0x04ca, 0x3016), .driver_info = BTUSB_QCA_ROME |
|
||||
BTUSB_WIDEBAND_SPEECH },
|
||||
{ USB_DEVICE(0x04ca, 0x301a), .driver_info = BTUSB_QCA_ROME |
|
||||
BTUSB_WIDEBAND_SPEECH },
|
||||
{ USB_DEVICE(0x04ca, 0x3021), .driver_info = BTUSB_QCA_ROME |
|
||||
BTUSB_WIDEBAND_SPEECH },
|
||||
{ USB_DEVICE(0x13d3, 0x3491), .driver_info = BTUSB_QCA_ROME |
|
||||
BTUSB_WIDEBAND_SPEECH },
|
||||
{ USB_DEVICE(0x13d3, 0x3496), .driver_info = BTUSB_QCA_ROME |
|
||||
BTUSB_WIDEBAND_SPEECH },
|
||||
{ USB_DEVICE(0x13d3, 0x3501), .driver_info = BTUSB_QCA_ROME |
|
||||
BTUSB_WIDEBAND_SPEECH },
|
||||
|
||||
/* QCA WCN6855 chipset */
|
||||
{ USB_DEVICE(0x0cf3, 0xe600), .driver_info = BTUSB_QCA_WCN6855 |
|
||||
BTUSB_WIDEBAND_SPEECH },
|
||||
|
||||
/* Broadcom BCM2035 */
|
||||
{ USB_DEVICE(0x0a5c, 0x2009), .driver_info = BTUSB_BCM92035 },
|
||||
@@ -2338,10 +2361,10 @@ static bool btusb_setup_intel_new_get_fw_name(struct intel_version *ver,
|
||||
|
||||
static int btusb_intel_download_firmware(struct hci_dev *hdev,
|
||||
struct intel_version *ver,
|
||||
struct intel_boot_params *params)
|
||||
struct intel_boot_params *params,
|
||||
u32 *boot_param)
|
||||
{
|
||||
const struct firmware *fw;
|
||||
u32 boot_param;
|
||||
char fwname[64];
|
||||
int err;
|
||||
struct btusb_data *data = hci_get_drvdata(hdev);
|
||||
@@ -2479,7 +2502,7 @@ static int btusb_intel_download_firmware(struct hci_dev *hdev,
|
||||
set_bit(BTUSB_DOWNLOADING, &data->flags);
|
||||
|
||||
/* Start firmware downloading and get boot parameter */
|
||||
err = btintel_download_firmware(hdev, fw, &boot_param);
|
||||
err = btintel_download_firmware(hdev, fw, boot_param);
|
||||
if (err < 0) {
|
||||
/* When FW download fails, send Intel Reset to retry
|
||||
* FW download.
|
||||
@@ -2561,7 +2584,7 @@ static int btusb_setup_intel_new(struct hci_dev *hdev)
|
||||
return err;
|
||||
}
|
||||
|
||||
err = btusb_intel_download_firmware(hdev, &ver, ¶ms);
|
||||
err = btusb_intel_download_firmware(hdev, &ver, ¶ms, &boot_param);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
@@ -2896,6 +2919,7 @@ static int btusb_mtk_submit_wmt_recv_urb(struct hci_dev *hdev)
|
||||
buf = kmalloc(size, GFP_KERNEL);
|
||||
if (!buf) {
|
||||
kfree(dr);
|
||||
usb_free_urb(urb);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
@@ -3390,6 +3414,27 @@ static int btusb_set_bdaddr_ath3012(struct hci_dev *hdev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int btusb_set_bdaddr_wcn6855(struct hci_dev *hdev,
|
||||
const bdaddr_t *bdaddr)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
u8 buf[6];
|
||||
long ret;
|
||||
|
||||
memcpy(buf, bdaddr, sizeof(bdaddr_t));
|
||||
|
||||
skb = __hci_cmd_sync_ev(hdev, 0xfc14, sizeof(buf), buf,
|
||||
HCI_EV_CMD_COMPLETE, HCI_INIT_TIMEOUT);
|
||||
if (IS_ERR(skb)) {
|
||||
ret = PTR_ERR(skb);
|
||||
bt_dev_err(hdev, "Change address command failed (%ld)", ret);
|
||||
return ret;
|
||||
}
|
||||
kfree_skb(skb);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define QCA_DFU_PACKET_LEN 4096
|
||||
|
||||
#define QCA_GET_TARGET_VERSION 0x09
|
||||
@@ -3409,7 +3454,8 @@ struct qca_version {
|
||||
} __packed;
|
||||
|
||||
struct qca_rampatch_version {
|
||||
__le16 rom_version;
|
||||
__le16 rom_version_high;
|
||||
__le16 rom_version_low;
|
||||
__le16 patch_version;
|
||||
} __packed;
|
||||
|
||||
@@ -3421,12 +3467,14 @@ struct qca_device_info {
|
||||
};
|
||||
|
||||
static const struct qca_device_info qca_devices_table[] = {
|
||||
{ 0x00000100, 20, 4, 10 }, /* Rome 1.0 */
|
||||
{ 0x00000101, 20, 4, 10 }, /* Rome 1.1 */
|
||||
{ 0x00000200, 28, 4, 18 }, /* Rome 2.0 */
|
||||
{ 0x00000201, 28, 4, 18 }, /* Rome 2.1 */
|
||||
{ 0x00000300, 28, 4, 18 }, /* Rome 3.0 */
|
||||
{ 0x00000302, 28, 4, 18 }, /* Rome 3.2 */
|
||||
{ 0x00000100, 20, 4, 8 }, /* Rome 1.0 */
|
||||
{ 0x00000101, 20, 4, 8 }, /* Rome 1.1 */
|
||||
{ 0x00000200, 28, 4, 16 }, /* Rome 2.0 */
|
||||
{ 0x00000201, 28, 4, 16 }, /* Rome 2.1 */
|
||||
{ 0x00000300, 28, 4, 16 }, /* Rome 3.0 */
|
||||
{ 0x00000302, 28, 4, 16 }, /* Rome 3.2 */
|
||||
{ 0x00130100, 40, 4, 16 }, /* WCN6855 1.0 */
|
||||
{ 0x00130200, 40, 4, 16 }, /* WCN6855 2.0 */
|
||||
};
|
||||
|
||||
static int btusb_qca_send_vendor_req(struct usb_device *udev, u8 request,
|
||||
@@ -3528,8 +3576,8 @@ static int btusb_setup_qca_load_rampatch(struct hci_dev *hdev,
|
||||
{
|
||||
struct qca_rampatch_version *rver;
|
||||
const struct firmware *fw;
|
||||
u32 ver_rom, ver_patch;
|
||||
u16 rver_rom, rver_patch;
|
||||
u32 ver_rom, ver_patch, rver_rom;
|
||||
u16 rver_rom_low, rver_rom_high, rver_patch;
|
||||
char fwname[64];
|
||||
int err;
|
||||
|
||||
@@ -3548,9 +3596,16 @@ static int btusb_setup_qca_load_rampatch(struct hci_dev *hdev,
|
||||
bt_dev_info(hdev, "using rampatch file: %s", fwname);
|
||||
|
||||
rver = (struct qca_rampatch_version *)(fw->data + info->ver_offset);
|
||||
rver_rom = le16_to_cpu(rver->rom_version);
|
||||
rver_rom_low = le16_to_cpu(rver->rom_version_low);
|
||||
rver_patch = le16_to_cpu(rver->patch_version);
|
||||
|
||||
if (ver_rom & ~0xffffU) {
|
||||
rver_rom_high = le16_to_cpu(rver->rom_version_high);
|
||||
rver_rom = le32_to_cpu(rver_rom_high << 16 | rver_rom_low);
|
||||
} else {
|
||||
rver_rom = rver_rom_low;
|
||||
}
|
||||
|
||||
bt_dev_info(hdev, "QCA: patch rome 0x%x build 0x%x, "
|
||||
"firmware rome 0x%x build 0x%x",
|
||||
rver_rom, rver_patch, ver_rom, ver_patch);
|
||||
@@ -3624,9 +3679,6 @@ static int btusb_setup_qca(struct hci_dev *hdev)
|
||||
return err;
|
||||
|
||||
ver_rom = le32_to_cpu(ver.rom_version);
|
||||
/* Don't care about high ROM versions */
|
||||
if (ver_rom & ~0xffffU)
|
||||
return 0;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(qca_devices_table); i++) {
|
||||
if (ver_rom == qca_devices_table[i].rom_version)
|
||||
@@ -4062,6 +4114,13 @@ static int btusb_probe(struct usb_interface *intf,
|
||||
btusb_check_needs_reset_resume(intf);
|
||||
}
|
||||
|
||||
if (id->driver_info & BTUSB_QCA_WCN6855) {
|
||||
data->setup_on_usb = btusb_setup_qca;
|
||||
hdev->set_bdaddr = btusb_set_bdaddr_wcn6855;
|
||||
hdev->cmd_timeout = btusb_qca_cmd_timeout;
|
||||
set_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, &hdev->quirks);
|
||||
}
|
||||
|
||||
if (id->driver_info & BTUSB_AMP) {
|
||||
/* AMP controllers do not support SCO packets */
|
||||
data->isoc = NULL;
|
||||
|
@@ -793,8 +793,6 @@ static int h5_serdev_probe(struct serdev_device *serdev)
|
||||
if (!h5)
|
||||
return -ENOMEM;
|
||||
|
||||
set_bit(HCI_UART_RESET_ON_INIT, &h5->serdev_hu.hdev_flags);
|
||||
|
||||
h5->hu = &h5->serdev_hu;
|
||||
h5->serdev_hu.serdev = serdev;
|
||||
serdev_device_set_drvdata(serdev, h5);
|
||||
|
@@ -288,7 +288,7 @@ static irqreturn_t intel_irq(int irq, void *dev_id)
|
||||
|
||||
static int intel_set_power(struct hci_uart *hu, bool powered)
|
||||
{
|
||||
struct list_head *p;
|
||||
struct intel_device *idev;
|
||||
int err = -ENODEV;
|
||||
|
||||
if (!hu->tty->dev)
|
||||
@@ -296,10 +296,7 @@ static int intel_set_power(struct hci_uart *hu, bool powered)
|
||||
|
||||
mutex_lock(&intel_device_list_lock);
|
||||
|
||||
list_for_each(p, &intel_device_list) {
|
||||
struct intel_device *idev = list_entry(p, struct intel_device,
|
||||
list);
|
||||
|
||||
list_for_each_entry(idev, &intel_device_list, list) {
|
||||
/* tty device and pdev device should share the same parent
|
||||
* which is the UART port.
|
||||
*/
|
||||
@@ -362,19 +359,16 @@ static int intel_set_power(struct hci_uart *hu, bool powered)
|
||||
|
||||
static void intel_busy_work(struct work_struct *work)
|
||||
{
|
||||
struct list_head *p;
|
||||
struct intel_data *intel = container_of(work, struct intel_data,
|
||||
busy_work);
|
||||
struct intel_device *idev;
|
||||
|
||||
if (!intel->hu->tty->dev)
|
||||
return;
|
||||
|
||||
/* Link is busy, delay the suspend */
|
||||
mutex_lock(&intel_device_list_lock);
|
||||
list_for_each(p, &intel_device_list) {
|
||||
struct intel_device *idev = list_entry(p, struct intel_device,
|
||||
list);
|
||||
|
||||
list_for_each_entry(idev, &intel_device_list, list) {
|
||||
if (intel->hu->tty->dev->parent == idev->pdev->dev.parent) {
|
||||
pm_runtime_get(&idev->pdev->dev);
|
||||
pm_runtime_mark_last_busy(&idev->pdev->dev);
|
||||
@@ -533,7 +527,7 @@ static int intel_setup(struct hci_uart *hu)
|
||||
struct sk_buff *skb;
|
||||
struct intel_version ver;
|
||||
struct intel_boot_params params;
|
||||
struct list_head *p;
|
||||
struct intel_device *idev;
|
||||
const struct firmware *fw;
|
||||
char fwname[64];
|
||||
u32 boot_param;
|
||||
@@ -693,14 +687,11 @@ static int intel_setup(struct hci_uart *hu)
|
||||
case 0x0b: /* SfP */
|
||||
case 0x0c: /* WsP */
|
||||
snprintf(fwname, sizeof(fwname), "intel/ibt-%u-%u.sfi",
|
||||
le16_to_cpu(ver.hw_variant),
|
||||
le16_to_cpu(params.dev_revid));
|
||||
ver.hw_variant, le16_to_cpu(params.dev_revid));
|
||||
break;
|
||||
case 0x12: /* ThP */
|
||||
snprintf(fwname, sizeof(fwname), "intel/ibt-%u-%u-%u.sfi",
|
||||
le16_to_cpu(ver.hw_variant),
|
||||
le16_to_cpu(ver.hw_revision),
|
||||
le16_to_cpu(ver.fw_revision));
|
||||
ver.hw_variant, ver.hw_revision, ver.fw_revision);
|
||||
break;
|
||||
default:
|
||||
bt_dev_err(hdev, "Unsupported Intel hardware variant (%u)",
|
||||
@@ -722,14 +713,11 @@ static int intel_setup(struct hci_uart *hu)
|
||||
case 0x0b: /* SfP */
|
||||
case 0x0c: /* WsP */
|
||||
snprintf(fwname, sizeof(fwname), "intel/ibt-%u-%u.ddc",
|
||||
le16_to_cpu(ver.hw_variant),
|
||||
le16_to_cpu(params.dev_revid));
|
||||
ver.hw_variant, le16_to_cpu(params.dev_revid));
|
||||
break;
|
||||
case 0x12: /* ThP */
|
||||
snprintf(fwname, sizeof(fwname), "intel/ibt-%u-%u-%u.ddc",
|
||||
le16_to_cpu(ver.hw_variant),
|
||||
le16_to_cpu(ver.hw_revision),
|
||||
le16_to_cpu(ver.fw_revision));
|
||||
ver.hw_variant, ver.hw_revision, ver.fw_revision);
|
||||
break;
|
||||
default:
|
||||
bt_dev_err(hdev, "Unsupported Intel hardware variant (%u)",
|
||||
@@ -839,13 +827,11 @@ done:
|
||||
* until further LPM TX notification.
|
||||
*/
|
||||
mutex_lock(&intel_device_list_lock);
|
||||
list_for_each(p, &intel_device_list) {
|
||||
struct intel_device *dev = list_entry(p, struct intel_device,
|
||||
list);
|
||||
list_for_each_entry(idev, &intel_device_list, list) {
|
||||
if (!hu->tty->dev)
|
||||
break;
|
||||
if (hu->tty->dev->parent == dev->pdev->dev.parent) {
|
||||
if (device_may_wakeup(&dev->pdev->dev)) {
|
||||
if (hu->tty->dev->parent == idev->pdev->dev.parent) {
|
||||
if (device_may_wakeup(&idev->pdev->dev)) {
|
||||
set_bit(STATE_LPM_ENABLED, &intel->flags);
|
||||
set_bit(STATE_TX_ACTIVE, &intel->flags);
|
||||
}
|
||||
@@ -999,7 +985,7 @@ static int intel_recv(struct hci_uart *hu, const void *data, int count)
|
||||
static int intel_enqueue(struct hci_uart *hu, struct sk_buff *skb)
|
||||
{
|
||||
struct intel_data *intel = hu->priv;
|
||||
struct list_head *p;
|
||||
struct intel_device *idev;
|
||||
|
||||
BT_DBG("hu %p skb %p", hu, skb);
|
||||
|
||||
@@ -1010,10 +996,7 @@ static int intel_enqueue(struct hci_uart *hu, struct sk_buff *skb)
|
||||
* completed before enqueuing any packet.
|
||||
*/
|
||||
mutex_lock(&intel_device_list_lock);
|
||||
list_for_each(p, &intel_device_list) {
|
||||
struct intel_device *idev = list_entry(p, struct intel_device,
|
||||
list);
|
||||
|
||||
list_for_each_entry(idev, &intel_device_list, list) {
|
||||
if (hu->tty->dev->parent == idev->pdev->dev.parent) {
|
||||
pm_runtime_get_sync(&idev->pdev->dev);
|
||||
pm_runtime_mark_last_busy(&idev->pdev->dev);
|
||||
@@ -1076,7 +1059,8 @@ static const struct hci_uart_proto intel_proto = {
|
||||
#ifdef CONFIG_ACPI
|
||||
static const struct acpi_device_id intel_acpi_match[] = {
|
||||
{ "INT33E1", 0 },
|
||||
{ },
|
||||
{ "INT33E3", 0 },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(acpi, intel_acpi_match);
|
||||
#endif
|
||||
@@ -1138,9 +1122,9 @@ static const struct acpi_gpio_params reset_gpios = { 0, 0, false };
|
||||
static const struct acpi_gpio_params host_wake_gpios = { 1, 0, false };
|
||||
|
||||
static const struct acpi_gpio_mapping acpi_hci_intel_gpios[] = {
|
||||
{ "reset-gpios", &reset_gpios, 1 },
|
||||
{ "host-wake-gpios", &host_wake_gpios, 1 },
|
||||
{ },
|
||||
{ "reset-gpios", &reset_gpios, 1, ACPI_GPIO_QUIRK_ONLY_GPIOIO },
|
||||
{ "host-wake-gpios", &host_wake_gpios, 1, ACPI_GPIO_QUIRK_ONLY_GPIOIO },
|
||||
{ }
|
||||
};
|
||||
|
||||
static int intel_probe(struct platform_device *pdev)
|
||||
|
@@ -538,6 +538,7 @@ static void hci_uart_tty_close(struct tty_struct *tty)
|
||||
clear_bit(HCI_UART_PROTO_READY, &hu->flags);
|
||||
percpu_up_write(&hu->proto_lock);
|
||||
|
||||
cancel_work_sync(&hu->init_ready);
|
||||
cancel_work_sync(&hu->write_work);
|
||||
|
||||
if (hdev) {
|
||||
|
@@ -693,8 +693,6 @@ static int qca_close(struct hci_uart *hu)
|
||||
destroy_workqueue(qca->workqueue);
|
||||
qca->hu = NULL;
|
||||
|
||||
qca_power_shutdown(hu);
|
||||
|
||||
kfree_skb(qca->rx_skb);
|
||||
|
||||
hu->priv = NULL;
|
||||
@@ -2007,7 +2005,6 @@ static int qca_serdev_probe(struct serdev_device *serdev)
|
||||
err = hci_uart_register_device(&qcadev->serdev_hu, &qca_proto);
|
||||
if (err) {
|
||||
BT_ERR("Rome serdev registration failed");
|
||||
if (qcadev->susclk)
|
||||
clk_disable_unprepare(qcadev->susclk);
|
||||
return err;
|
||||
}
|
||||
@@ -2032,8 +2029,9 @@ static int qca_serdev_probe(struct serdev_device *serdev)
|
||||
static void qca_serdev_remove(struct serdev_device *serdev)
|
||||
{
|
||||
struct qca_serdev *qcadev = serdev_device_get_drvdata(serdev);
|
||||
struct qca_power *power = qcadev->bt_power;
|
||||
|
||||
if (qca_is_wcn399x(qcadev->btsoc_type))
|
||||
if (qca_is_wcn399x(qcadev->btsoc_type) && power->vregs_on)
|
||||
qca_power_shutdown(&qcadev->serdev_hu);
|
||||
else if (qcadev->susclk)
|
||||
clk_disable_unprepare(qcadev->susclk);
|
||||
|
@@ -113,8 +113,22 @@ static int hci_uart_flush(struct hci_dev *hdev)
|
||||
/* Initialize device */
|
||||
static int hci_uart_open(struct hci_dev *hdev)
|
||||
{
|
||||
struct hci_uart *hu = hci_get_drvdata(hdev);
|
||||
int err;
|
||||
|
||||
BT_DBG("%s %p", hdev->name, hdev);
|
||||
|
||||
/* When Quirk HCI_QUIRK_NON_PERSISTENT_SETUP is set by
|
||||
* driver, BT SoC is completely turned OFF during
|
||||
* BT OFF. Upon next BT ON UART port should be opened.
|
||||
*/
|
||||
if (!test_bit(HCI_UART_PROTO_READY, &hu->flags)) {
|
||||
err = serdev_device_open(hu->serdev);
|
||||
if (err)
|
||||
return err;
|
||||
set_bit(HCI_UART_PROTO_READY, &hu->flags);
|
||||
}
|
||||
|
||||
/* Undo clearing this from hci_uart_close() */
|
||||
hdev->flush = hci_uart_flush;
|
||||
|
||||
@@ -124,11 +138,25 @@ static int hci_uart_open(struct hci_dev *hdev)
|
||||
/* Close device */
|
||||
static int hci_uart_close(struct hci_dev *hdev)
|
||||
{
|
||||
struct hci_uart *hu = hci_get_drvdata(hdev);
|
||||
|
||||
BT_DBG("hdev %p", hdev);
|
||||
|
||||
if (!test_bit(HCI_UART_PROTO_READY, &hu->flags))
|
||||
return 0;
|
||||
|
||||
hci_uart_flush(hdev);
|
||||
hdev->flush = NULL;
|
||||
|
||||
/* When QUIRK HCI_QUIRK_NON_PERSISTENT_SETUP is set by driver,
|
||||
* BT SOC is completely powered OFF during BT OFF, holding port
|
||||
* open may drain the battery.
|
||||
*/
|
||||
if (test_bit(HCI_QUIRK_NON_PERSISTENT_SETUP, &hdev->quirks)) {
|
||||
clear_bit(HCI_UART_PROTO_READY, &hu->flags);
|
||||
serdev_device_close(hu->serdev);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -354,7 +382,7 @@ void hci_uart_unregister_device(struct hci_uart *hu)
|
||||
{
|
||||
struct hci_dev *hdev = hu->hdev;
|
||||
|
||||
clear_bit(HCI_UART_PROTO_READY, &hu->flags);
|
||||
cancel_work_sync(&hu->init_ready);
|
||||
if (test_bit(HCI_UART_REGISTERED, &hu->flags))
|
||||
hci_unregister_dev(hdev);
|
||||
hci_free_dev(hdev);
|
||||
@@ -362,6 +390,10 @@ void hci_uart_unregister_device(struct hci_uart *hu)
|
||||
cancel_work_sync(&hu->write_work);
|
||||
|
||||
hu->proto->close(hu);
|
||||
|
||||
if (test_bit(HCI_UART_PROTO_READY, &hu->flags)) {
|
||||
clear_bit(HCI_UART_PROTO_READY, &hu->flags);
|
||||
serdev_device_close(hu->serdev);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(hci_uart_unregister_device);
|
||||
|
@@ -197,17 +197,12 @@ int cn_add_callback(struct cb_id *id, const char *name,
|
||||
void (*callback)(struct cn_msg *,
|
||||
struct netlink_skb_parms *))
|
||||
{
|
||||
int err;
|
||||
struct cn_dev *dev = &cdev;
|
||||
|
||||
if (!cn_already_initialized)
|
||||
return -EAGAIN;
|
||||
|
||||
err = cn_queue_add_callback(dev->cbdev, name, id, callback);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
return 0;
|
||||
return cn_queue_add_callback(dev->cbdev, name, id, callback);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(cn_add_callback);
|
||||
|
||||
|
@@ -21,35 +21,3 @@ config CRYPTO_DEV_CHELSIO
|
||||
|
||||
To compile this driver as a module, choose M here: the module
|
||||
will be called chcr.
|
||||
|
||||
config CHELSIO_IPSEC_INLINE
|
||||
bool "Chelsio IPSec XFRM Tx crypto offload"
|
||||
depends on CHELSIO_T4
|
||||
depends on CRYPTO_DEV_CHELSIO
|
||||
depends on XFRM_OFFLOAD
|
||||
depends on INET_ESP_OFFLOAD || INET6_ESP_OFFLOAD
|
||||
default n
|
||||
help
|
||||
Enable support for IPSec Tx Inline.
|
||||
|
||||
config CRYPTO_DEV_CHELSIO_TLS
|
||||
tristate "Chelsio Crypto Inline TLS Driver"
|
||||
depends on CHELSIO_T4
|
||||
depends on TLS_TOE
|
||||
select CRYPTO_DEV_CHELSIO
|
||||
help
|
||||
Support Chelsio Inline TLS with Chelsio crypto accelerator.
|
||||
|
||||
To compile this driver as a module, choose M here: the module
|
||||
will be called chtls.
|
||||
|
||||
config CHELSIO_TLS_DEVICE
|
||||
bool "Chelsio Inline KTLS Offload"
|
||||
depends on CHELSIO_T4
|
||||
depends on TLS_DEVICE
|
||||
select CRYPTO_DEV_CHELSIO
|
||||
default y
|
||||
help
|
||||
This flag enables support for kernel tls offload over Chelsio T6
|
||||
crypto accelerator. CONFIG_CHELSIO_TLS_DEVICE flag can be enabled
|
||||
only if CONFIG_TLS and CONFIG_TLS_DEVICE flags are enabled.
|
||||
|
@@ -3,8 +3,3 @@ ccflags-y := -I $(srctree)/drivers/net/ethernet/chelsio/cxgb4
|
||||
|
||||
obj-$(CONFIG_CRYPTO_DEV_CHELSIO) += chcr.o
|
||||
chcr-objs := chcr_core.o chcr_algo.o
|
||||
#ifdef CONFIG_CHELSIO_TLS_DEVICE
|
||||
chcr-objs += chcr_ktls.o
|
||||
#endif
|
||||
chcr-$(CONFIG_CHELSIO_IPSEC_INLINE) += chcr_ipsec.o
|
||||
obj-$(CONFIG_CRYPTO_DEV_CHELSIO_TLS) += chtls/
|
||||
|
@@ -86,39 +86,6 @@
|
||||
KEY_CONTEXT_OPAD_PRESENT_M)
|
||||
#define KEY_CONTEXT_OPAD_PRESENT_F KEY_CONTEXT_OPAD_PRESENT_V(1U)
|
||||
|
||||
#define TLS_KEYCTX_RXFLIT_CNT_S 24
|
||||
#define TLS_KEYCTX_RXFLIT_CNT_V(x) ((x) << TLS_KEYCTX_RXFLIT_CNT_S)
|
||||
|
||||
#define TLS_KEYCTX_RXPROT_VER_S 20
|
||||
#define TLS_KEYCTX_RXPROT_VER_M 0xf
|
||||
#define TLS_KEYCTX_RXPROT_VER_V(x) ((x) << TLS_KEYCTX_RXPROT_VER_S)
|
||||
|
||||
#define TLS_KEYCTX_RXCIPH_MODE_S 16
|
||||
#define TLS_KEYCTX_RXCIPH_MODE_M 0xf
|
||||
#define TLS_KEYCTX_RXCIPH_MODE_V(x) ((x) << TLS_KEYCTX_RXCIPH_MODE_S)
|
||||
|
||||
#define TLS_KEYCTX_RXAUTH_MODE_S 12
|
||||
#define TLS_KEYCTX_RXAUTH_MODE_M 0xf
|
||||
#define TLS_KEYCTX_RXAUTH_MODE_V(x) ((x) << TLS_KEYCTX_RXAUTH_MODE_S)
|
||||
|
||||
#define TLS_KEYCTX_RXCIAU_CTRL_S 11
|
||||
#define TLS_KEYCTX_RXCIAU_CTRL_V(x) ((x) << TLS_KEYCTX_RXCIAU_CTRL_S)
|
||||
|
||||
#define TLS_KEYCTX_RX_SEQCTR_S 9
|
||||
#define TLS_KEYCTX_RX_SEQCTR_M 0x3
|
||||
#define TLS_KEYCTX_RX_SEQCTR_V(x) ((x) << TLS_KEYCTX_RX_SEQCTR_S)
|
||||
|
||||
#define TLS_KEYCTX_RX_VALID_S 8
|
||||
#define TLS_KEYCTX_RX_VALID_V(x) ((x) << TLS_KEYCTX_RX_VALID_S)
|
||||
|
||||
#define TLS_KEYCTX_RXCK_SIZE_S 3
|
||||
#define TLS_KEYCTX_RXCK_SIZE_M 0x7
|
||||
#define TLS_KEYCTX_RXCK_SIZE_V(x) ((x) << TLS_KEYCTX_RXCK_SIZE_S)
|
||||
|
||||
#define TLS_KEYCTX_RXMK_SIZE_S 0
|
||||
#define TLS_KEYCTX_RXMK_SIZE_M 0x7
|
||||
#define TLS_KEYCTX_RXMK_SIZE_V(x) ((x) << TLS_KEYCTX_RXMK_SIZE_S)
|
||||
|
||||
#define CHCR_HASH_MAX_DIGEST_SIZE 64
|
||||
#define CHCR_MAX_SHA_DIGEST_SIZE 64
|
||||
|
||||
|
@@ -33,23 +33,8 @@ static int cpl_fw6_pld_handler(struct adapter *adap, unsigned char *input);
|
||||
static void *chcr_uld_add(const struct cxgb4_lld_info *lld);
|
||||
static int chcr_uld_state_change(void *handle, enum cxgb4_state state);
|
||||
|
||||
#if defined(CONFIG_CHELSIO_TLS_DEVICE)
|
||||
static const struct tlsdev_ops chcr_ktls_ops = {
|
||||
.tls_dev_add = chcr_ktls_dev_add,
|
||||
.tls_dev_del = chcr_ktls_dev_del,
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_CHELSIO_IPSEC_INLINE
|
||||
static void update_netdev_features(void);
|
||||
#endif /* CONFIG_CHELSIO_IPSEC_INLINE */
|
||||
|
||||
static chcr_handler_func work_handlers[NUM_CPL_CMDS] = {
|
||||
[CPL_FW6_PLD] = cpl_fw6_pld_handler,
|
||||
#ifdef CONFIG_CHELSIO_TLS_DEVICE
|
||||
[CPL_ACT_OPEN_RPL] = chcr_ktls_cpl_act_open_rpl,
|
||||
[CPL_SET_TCB_RPL] = chcr_ktls_cpl_set_tcb_rpl,
|
||||
#endif
|
||||
};
|
||||
|
||||
static struct cxgb4_uld_info chcr_uld_info = {
|
||||
@@ -60,12 +45,6 @@ static struct cxgb4_uld_info chcr_uld_info = {
|
||||
.add = chcr_uld_add,
|
||||
.state_change = chcr_uld_state_change,
|
||||
.rx_handler = chcr_uld_rx_handler,
|
||||
#if defined(CONFIG_CHELSIO_IPSEC_INLINE) || defined(CONFIG_CHELSIO_TLS_DEVICE)
|
||||
.tx_handler = chcr_uld_tx_handler,
|
||||
#endif /* CONFIG_CHELSIO_IPSEC_INLINE || CONFIG_CHELSIO_TLS_DEVICE */
|
||||
#if defined(CONFIG_CHELSIO_TLS_DEVICE)
|
||||
.tlsdev_ops = &chcr_ktls_ops,
|
||||
#endif
|
||||
};
|
||||
|
||||
static void detach_work_fn(struct work_struct *work)
|
||||
@@ -241,23 +220,6 @@ int chcr_uld_rx_handler(void *handle, const __be64 *rsp,
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_CHELSIO_IPSEC_INLINE) || defined(CONFIG_CHELSIO_TLS_DEVICE)
|
||||
int chcr_uld_tx_handler(struct sk_buff *skb, struct net_device *dev)
|
||||
{
|
||||
/* In case if skb's decrypted bit is set, it's nic tls packet, else it's
|
||||
* ipsec packet.
|
||||
*/
|
||||
#ifdef CONFIG_CHELSIO_TLS_DEVICE
|
||||
if (skb->decrypted)
|
||||
return chcr_ktls_xmit(skb, dev);
|
||||
#endif
|
||||
#ifdef CONFIG_CHELSIO_IPSEC_INLINE
|
||||
return chcr_ipsec_xmit(skb, dev);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_CHELSIO_IPSEC_INLINE || CONFIG_CHELSIO_TLS_DEVICE */
|
||||
|
||||
static void chcr_detach_device(struct uld_ctx *u_ctx)
|
||||
{
|
||||
struct chcr_dev *dev = &u_ctx->dev;
|
||||
@@ -305,24 +267,6 @@ static int chcr_uld_state_change(void *handle, enum cxgb4_state state)
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_CHELSIO_IPSEC_INLINE
|
||||
static void update_netdev_features(void)
|
||||
{
|
||||
struct uld_ctx *u_ctx, *tmp;
|
||||
|
||||
mutex_lock(&drv_data.drv_mutex);
|
||||
list_for_each_entry_safe(u_ctx, tmp, &drv_data.inact_dev, entry) {
|
||||
if (u_ctx->lldi.crypto & ULP_CRYPTO_IPSEC_INLINE)
|
||||
chcr_add_xfrmops(&u_ctx->lldi);
|
||||
}
|
||||
list_for_each_entry_safe(u_ctx, tmp, &drv_data.act_dev, entry) {
|
||||
if (u_ctx->lldi.crypto & ULP_CRYPTO_IPSEC_INLINE)
|
||||
chcr_add_xfrmops(&u_ctx->lldi);
|
||||
}
|
||||
mutex_unlock(&drv_data.drv_mutex);
|
||||
}
|
||||
#endif /* CONFIG_CHELSIO_IPSEC_INLINE */
|
||||
|
||||
static int __init chcr_crypto_init(void)
|
||||
{
|
||||
INIT_LIST_HEAD(&drv_data.act_dev);
|
||||
@@ -332,12 +276,6 @@ static int __init chcr_crypto_init(void)
|
||||
drv_data.last_dev = NULL;
|
||||
cxgb4_register_uld(CXGB4_ULD_CRYPTO, &chcr_uld_info);
|
||||
|
||||
#ifdef CONFIG_CHELSIO_IPSEC_INLINE
|
||||
rtnl_lock();
|
||||
update_netdev_features();
|
||||
rtnl_unlock();
|
||||
#endif /* CONFIG_CHELSIO_IPSEC_INLINE */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@@ -72,54 +72,6 @@ struct _key_ctx {
|
||||
unsigned char key[];
|
||||
};
|
||||
|
||||
#define KEYCTX_TX_WR_IV_S 55
|
||||
#define KEYCTX_TX_WR_IV_M 0x1ffULL
|
||||
#define KEYCTX_TX_WR_IV_V(x) ((x) << KEYCTX_TX_WR_IV_S)
|
||||
#define KEYCTX_TX_WR_IV_G(x) \
|
||||
(((x) >> KEYCTX_TX_WR_IV_S) & KEYCTX_TX_WR_IV_M)
|
||||
|
||||
#define KEYCTX_TX_WR_AAD_S 47
|
||||
#define KEYCTX_TX_WR_AAD_M 0xffULL
|
||||
#define KEYCTX_TX_WR_AAD_V(x) ((x) << KEYCTX_TX_WR_AAD_S)
|
||||
#define KEYCTX_TX_WR_AAD_G(x) (((x) >> KEYCTX_TX_WR_AAD_S) & \
|
||||
KEYCTX_TX_WR_AAD_M)
|
||||
|
||||
#define KEYCTX_TX_WR_AADST_S 39
|
||||
#define KEYCTX_TX_WR_AADST_M 0xffULL
|
||||
#define KEYCTX_TX_WR_AADST_V(x) ((x) << KEYCTX_TX_WR_AADST_S)
|
||||
#define KEYCTX_TX_WR_AADST_G(x) \
|
||||
(((x) >> KEYCTX_TX_WR_AADST_S) & KEYCTX_TX_WR_AADST_M)
|
||||
|
||||
#define KEYCTX_TX_WR_CIPHER_S 30
|
||||
#define KEYCTX_TX_WR_CIPHER_M 0x1ffULL
|
||||
#define KEYCTX_TX_WR_CIPHER_V(x) ((x) << KEYCTX_TX_WR_CIPHER_S)
|
||||
#define KEYCTX_TX_WR_CIPHER_G(x) \
|
||||
(((x) >> KEYCTX_TX_WR_CIPHER_S) & KEYCTX_TX_WR_CIPHER_M)
|
||||
|
||||
#define KEYCTX_TX_WR_CIPHERST_S 23
|
||||
#define KEYCTX_TX_WR_CIPHERST_M 0x7f
|
||||
#define KEYCTX_TX_WR_CIPHERST_V(x) ((x) << KEYCTX_TX_WR_CIPHERST_S)
|
||||
#define KEYCTX_TX_WR_CIPHERST_G(x) \
|
||||
(((x) >> KEYCTX_TX_WR_CIPHERST_S) & KEYCTX_TX_WR_CIPHERST_M)
|
||||
|
||||
#define KEYCTX_TX_WR_AUTH_S 14
|
||||
#define KEYCTX_TX_WR_AUTH_M 0x1ff
|
||||
#define KEYCTX_TX_WR_AUTH_V(x) ((x) << KEYCTX_TX_WR_AUTH_S)
|
||||
#define KEYCTX_TX_WR_AUTH_G(x) \
|
||||
(((x) >> KEYCTX_TX_WR_AUTH_S) & KEYCTX_TX_WR_AUTH_M)
|
||||
|
||||
#define KEYCTX_TX_WR_AUTHST_S 7
|
||||
#define KEYCTX_TX_WR_AUTHST_M 0x7f
|
||||
#define KEYCTX_TX_WR_AUTHST_V(x) ((x) << KEYCTX_TX_WR_AUTHST_S)
|
||||
#define KEYCTX_TX_WR_AUTHST_G(x) \
|
||||
(((x) >> KEYCTX_TX_WR_AUTHST_S) & KEYCTX_TX_WR_AUTHST_M)
|
||||
|
||||
#define KEYCTX_TX_WR_AUTHIN_S 0
|
||||
#define KEYCTX_TX_WR_AUTHIN_M 0x7f
|
||||
#define KEYCTX_TX_WR_AUTHIN_V(x) ((x) << KEYCTX_TX_WR_AUTHIN_S)
|
||||
#define KEYCTX_TX_WR_AUTHIN_G(x) \
|
||||
(((x) >> KEYCTX_TX_WR_AUTHIN_S) & KEYCTX_TX_WR_AUTHIN_M)
|
||||
|
||||
#define WQ_RETRY 5
|
||||
struct chcr_driver_data {
|
||||
struct list_head act_dev;
|
||||
@@ -157,42 +109,6 @@ struct uld_ctx {
|
||||
struct chcr_dev dev;
|
||||
};
|
||||
|
||||
struct sge_opaque_hdr {
|
||||
void *dev;
|
||||
dma_addr_t addr[MAX_SKB_FRAGS + 1];
|
||||
};
|
||||
|
||||
struct chcr_ipsec_req {
|
||||
struct ulp_txpkt ulptx;
|
||||
struct ulptx_idata sc_imm;
|
||||
struct cpl_tx_sec_pdu sec_cpl;
|
||||
struct _key_ctx key_ctx;
|
||||
};
|
||||
|
||||
struct chcr_ipsec_wr {
|
||||
struct fw_ulptx_wr wreq;
|
||||
struct chcr_ipsec_req req;
|
||||
};
|
||||
|
||||
#define ESN_IV_INSERT_OFFSET 12
|
||||
struct chcr_ipsec_aadiv {
|
||||
__be32 spi;
|
||||
u8 seq_no[8];
|
||||
u8 iv[8];
|
||||
};
|
||||
|
||||
struct ipsec_sa_entry {
|
||||
int hmac_ctrl;
|
||||
u16 esn;
|
||||
u16 resv;
|
||||
unsigned int enckey_len;
|
||||
unsigned int kctx_len;
|
||||
unsigned int authsize;
|
||||
__be32 key_ctx_hdr;
|
||||
char salt[MAX_SALT];
|
||||
char key[2 * AES_MAX_KEY_SIZE];
|
||||
};
|
||||
|
||||
/*
|
||||
* sgl_len - calculates the size of an SGL of the given capacity
|
||||
* @n: the number of SGL entries
|
||||
@@ -221,18 +137,4 @@ int chcr_uld_rx_handler(void *handle, const __be64 *rsp,
|
||||
int chcr_uld_tx_handler(struct sk_buff *skb, struct net_device *dev);
|
||||
int chcr_handle_resp(struct crypto_async_request *req, unsigned char *input,
|
||||
int err);
|
||||
int chcr_ipsec_xmit(struct sk_buff *skb, struct net_device *dev);
|
||||
void chcr_add_xfrmops(const struct cxgb4_lld_info *lld);
|
||||
#ifdef CONFIG_CHELSIO_TLS_DEVICE
|
||||
int chcr_ktls_cpl_act_open_rpl(struct adapter *adap, unsigned char *input);
|
||||
int chcr_ktls_cpl_set_tcb_rpl(struct adapter *adap, unsigned char *input);
|
||||
int chcr_ktls_xmit(struct sk_buff *skb, struct net_device *dev);
|
||||
extern int chcr_ktls_dev_add(struct net_device *netdev, struct sock *sk,
|
||||
enum tls_offload_ctx_dir direction,
|
||||
struct tls_crypto_info *crypto_info,
|
||||
u32 start_offload_tcp_sn);
|
||||
extern void chcr_ktls_dev_del(struct net_device *netdev,
|
||||
struct tls_context *tls_ctx,
|
||||
enum tls_offload_ctx_dir direction);
|
||||
#endif
|
||||
#endif /* __CHCR_CORE_H__ */
|
||||
|
@@ -97,41 +97,9 @@ static void hfi1_ipoib_dev_get_stats64(struct net_device *dev,
|
||||
struct rtnl_link_stats64 *storage)
|
||||
{
|
||||
struct hfi1_ipoib_dev_priv *priv = hfi1_ipoib_priv(dev);
|
||||
u64 rx_packets = 0ull;
|
||||
u64 rx_bytes = 0ull;
|
||||
u64 tx_packets = 0ull;
|
||||
u64 tx_bytes = 0ull;
|
||||
int i;
|
||||
|
||||
netdev_stats_to_stats64(storage, &dev->stats);
|
||||
|
||||
for_each_possible_cpu(i) {
|
||||
const struct pcpu_sw_netstats *stats;
|
||||
unsigned int start;
|
||||
u64 trx_packets;
|
||||
u64 trx_bytes;
|
||||
u64 ttx_packets;
|
||||
u64 ttx_bytes;
|
||||
|
||||
stats = per_cpu_ptr(priv->netstats, i);
|
||||
do {
|
||||
start = u64_stats_fetch_begin_irq(&stats->syncp);
|
||||
trx_packets = stats->rx_packets;
|
||||
trx_bytes = stats->rx_bytes;
|
||||
ttx_packets = stats->tx_packets;
|
||||
ttx_bytes = stats->tx_bytes;
|
||||
} while (u64_stats_fetch_retry_irq(&stats->syncp, start));
|
||||
|
||||
rx_packets += trx_packets;
|
||||
rx_bytes += trx_bytes;
|
||||
tx_packets += ttx_packets;
|
||||
tx_bytes += ttx_bytes;
|
||||
}
|
||||
|
||||
storage->rx_packets += rx_packets;
|
||||
storage->rx_bytes += rx_bytes;
|
||||
storage->tx_packets += tx_packets;
|
||||
storage->tx_bytes += tx_bytes;
|
||||
dev_fetch_sw_netstats(storage, priv->netstats);
|
||||
}
|
||||
|
||||
static const struct net_device_ops hfi1_ipoib_netdev_ops = {
|
||||
|
@@ -473,6 +473,10 @@ config NET_SB1000
|
||||
|
||||
source "drivers/net/phy/Kconfig"
|
||||
|
||||
source "drivers/net/mdio/Kconfig"
|
||||
|
||||
source "drivers/net/pcs/Kconfig"
|
||||
|
||||
source "drivers/net/plip/Kconfig"
|
||||
|
||||
source "drivers/net/ppp/Kconfig"
|
||||
|
@@ -21,6 +21,8 @@ obj-$(CONFIG_MDIO) += mdio.o
|
||||
obj-$(CONFIG_NET) += Space.o loopback.o
|
||||
obj-$(CONFIG_NETCONSOLE) += netconsole.o
|
||||
obj-y += phy/
|
||||
obj-y += mdio/
|
||||
obj-y += pcs/
|
||||
obj-$(CONFIG_RIONET) += rionet.o
|
||||
obj-$(CONFIG_NET_TEAM) += team/
|
||||
obj-$(CONFIG_TUN) += tun.o
|
||||
|
@@ -70,6 +70,8 @@ static const char *version =
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/jiffies.h>
|
||||
|
||||
#include <net/Space.h>
|
||||
|
||||
#include <asm/io.h>
|
||||
#include <asm/dma.h>
|
||||
|
||||
|
@@ -229,6 +229,8 @@ static int dma;
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/gfp.h>
|
||||
|
||||
#include <net/Space.h>
|
||||
|
||||
#include <asm/dma.h>
|
||||
#include <asm/io.h>
|
||||
|
||||
|
@@ -54,7 +54,6 @@ struct bareudp_dev {
|
||||
static int bareudp_udp_encap_recv(struct sock *sk, struct sk_buff *skb)
|
||||
{
|
||||
struct metadata_dst *tun_dst = NULL;
|
||||
struct pcpu_sw_netstats *stats;
|
||||
struct bareudp_dev *bareudp;
|
||||
unsigned short family;
|
||||
unsigned int len;
|
||||
@@ -160,13 +159,9 @@ static int bareudp_udp_encap_recv(struct sock *sk, struct sk_buff *skb)
|
||||
|
||||
len = skb->len;
|
||||
err = gro_cells_receive(&bareudp->gro_cells, skb);
|
||||
if (likely(err == NET_RX_SUCCESS)) {
|
||||
stats = this_cpu_ptr(bareudp->dev->tstats);
|
||||
u64_stats_update_begin(&stats->syncp);
|
||||
stats->rx_packets++;
|
||||
stats->rx_bytes += len;
|
||||
u64_stats_update_end(&stats->syncp);
|
||||
}
|
||||
if (likely(err == NET_RX_SUCCESS))
|
||||
dev_sw_netstats_rx_add(bareudp->dev, len);
|
||||
|
||||
return 0;
|
||||
drop:
|
||||
/* Consume bad packet */
|
||||
|
@@ -20,25 +20,6 @@ config CAIF_TTY
|
||||
identified as N_CAIF. When this ldisc is opened from user space
|
||||
it will redirect the TTY's traffic into the CAIF stack.
|
||||
|
||||
config CAIF_SPI_SLAVE
|
||||
tristate "CAIF SPI transport driver for slave interface"
|
||||
depends on CAIF && HAS_DMA
|
||||
default n
|
||||
help
|
||||
The CAIF Link layer SPI Protocol driver for Slave SPI interface.
|
||||
This driver implements a platform driver to accommodate for a
|
||||
platform specific SPI device. A sample CAIF SPI Platform device is
|
||||
provided in <file:Documentation/networking/caif/spi_porting.rst>.
|
||||
|
||||
config CAIF_SPI_SYNC
|
||||
bool "Next command and length in start of frame"
|
||||
depends on CAIF_SPI_SLAVE
|
||||
default n
|
||||
help
|
||||
Putting the next command and length in the start of the frame can
|
||||
help to synchronize to the next transfer in case of over or under-runs.
|
||||
This option also needs to be enabled on the modem.
|
||||
|
||||
config CAIF_HSI
|
||||
tristate "CAIF HSI transport driver"
|
||||
depends on CAIF
|
||||
|
@@ -4,10 +4,6 @@ ccflags-$(CONFIG_CAIF_DEBUG) := -DDEBUG
|
||||
# Serial interface
|
||||
obj-$(CONFIG_CAIF_TTY) += caif_serial.o
|
||||
|
||||
# SPI slave physical interfaces module
|
||||
cfspi_slave-objs := caif_spi.o caif_spi_slave.o
|
||||
obj-$(CONFIG_CAIF_SPI_SLAVE) += cfspi_slave.o
|
||||
|
||||
# HSI interface
|
||||
obj-$(CONFIG_CAIF_HSI) += caif_hsi.o
|
||||
|
||||
|
@@ -458,15 +458,7 @@ static int cfhsi_rx_desc(struct cfhsi_desc *desc, struct cfhsi *cfhsi)
|
||||
skb_reset_mac_header(skb);
|
||||
skb->dev = cfhsi->ndev;
|
||||
|
||||
/*
|
||||
* We are in a callback handler and
|
||||
* unfortunately we don't know what context we're
|
||||
* running in.
|
||||
*/
|
||||
if (in_interrupt())
|
||||
netif_rx(skb);
|
||||
else
|
||||
netif_rx_ni(skb);
|
||||
netif_rx_any_context(skb);
|
||||
|
||||
/* Update network statistics. */
|
||||
cfhsi->ndev->stats.rx_packets++;
|
||||
@@ -587,14 +579,7 @@ static int cfhsi_rx_pld(struct cfhsi_desc *desc, struct cfhsi *cfhsi)
|
||||
skb_reset_mac_header(skb);
|
||||
skb->dev = cfhsi->ndev;
|
||||
|
||||
/*
|
||||
* We're called in callback from HSI
|
||||
* and don't know the context we're running in.
|
||||
*/
|
||||
if (in_interrupt())
|
||||
netif_rx(skb);
|
||||
else
|
||||
netif_rx_ni(skb);
|
||||
netif_rx_any_context(skb);
|
||||
|
||||
/* Update network statistics. */
|
||||
cfhsi->ndev->stats.rx_packets++;
|
||||
|
@@ -1,874 +0,0 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (C) ST-Ericsson AB 2010
|
||||
* Author: Daniel Martensson
|
||||
*/
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/completion.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/if_arp.h>
|
||||
#include <net/caif/caif_layer.h>
|
||||
#include <net/caif/caif_spi.h>
|
||||
|
||||
#ifndef CONFIG_CAIF_SPI_SYNC
|
||||
#define FLAVOR "Flavour: Vanilla.\n"
|
||||
#else
|
||||
#define FLAVOR "Flavour: Master CMD&LEN at start.\n"
|
||||
#endif /* CONFIG_CAIF_SPI_SYNC */
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Daniel Martensson");
|
||||
MODULE_DESCRIPTION("CAIF SPI driver");
|
||||
|
||||
/* Returns the number of padding bytes for alignment. */
|
||||
#define PAD_POW2(x, pow) ((((x)&((pow)-1))==0) ? 0 : (((pow)-((x)&((pow)-1)))))
|
||||
|
||||
static bool spi_loop;
|
||||
module_param(spi_loop, bool, 0444);
|
||||
MODULE_PARM_DESC(spi_loop, "SPI running in loopback mode.");
|
||||
|
||||
/* SPI frame alignment. */
|
||||
module_param(spi_frm_align, int, 0444);
|
||||
MODULE_PARM_DESC(spi_frm_align, "SPI frame alignment.");
|
||||
|
||||
/*
|
||||
* SPI padding options.
|
||||
* Warning: must be a base of 2 (& operation used) and can not be zero !
|
||||
*/
|
||||
module_param(spi_up_head_align, int, 0444);
|
||||
MODULE_PARM_DESC(spi_up_head_align, "SPI uplink head alignment.");
|
||||
|
||||
module_param(spi_up_tail_align, int, 0444);
|
||||
MODULE_PARM_DESC(spi_up_tail_align, "SPI uplink tail alignment.");
|
||||
|
||||
module_param(spi_down_head_align, int, 0444);
|
||||
MODULE_PARM_DESC(spi_down_head_align, "SPI downlink head alignment.");
|
||||
|
||||
module_param(spi_down_tail_align, int, 0444);
|
||||
MODULE_PARM_DESC(spi_down_tail_align, "SPI downlink tail alignment.");
|
||||
|
||||
#ifdef CONFIG_ARM
|
||||
#define BYTE_HEX_FMT "%02X"
|
||||
#else
|
||||
#define BYTE_HEX_FMT "%02hhX"
|
||||
#endif
|
||||
|
||||
#define SPI_MAX_PAYLOAD_SIZE 4096
|
||||
/*
|
||||
* Threshold values for the SPI packet queue. Flowcontrol will be asserted
|
||||
* when the number of packets exceeds HIGH_WATER_MARK. It will not be
|
||||
* deasserted before the number of packets drops below LOW_WATER_MARK.
|
||||
*/
|
||||
#define LOW_WATER_MARK 100
|
||||
#define HIGH_WATER_MARK (LOW_WATER_MARK*5)
|
||||
|
||||
#ifndef CONFIG_HAS_DMA
|
||||
|
||||
/*
|
||||
* We sometimes use UML for debugging, but it cannot handle
|
||||
* dma_alloc_coherent so we have to wrap it.
|
||||
*/
|
||||
static inline void *dma_alloc(struct cfspi *cfspi, dma_addr_t *daddr)
|
||||
{
|
||||
return kmalloc(SPI_DMA_BUF_LEN, GFP_KERNEL);
|
||||
}
|
||||
|
||||
static inline void dma_free(struct cfspi *cfspi, void *cpu_addr,
|
||||
dma_addr_t handle)
|
||||
{
|
||||
kfree(cpu_addr);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static inline void *dma_alloc(struct cfspi *cfspi, dma_addr_t *daddr)
|
||||
{
|
||||
return dma_alloc_coherent(&cfspi->pdev->dev, SPI_DMA_BUF_LEN, daddr,
|
||||
GFP_KERNEL);
|
||||
}
|
||||
|
||||
static inline void dma_free(struct cfspi *cfspi, void *cpu_addr,
|
||||
dma_addr_t handle)
|
||||
{
|
||||
dma_free_coherent(&cfspi->pdev->dev, SPI_DMA_BUF_LEN, cpu_addr, handle);
|
||||
}
|
||||
#endif /* CONFIG_HAS_DMA */
|
||||
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
|
||||
#define DEBUGFS_BUF_SIZE 4096
|
||||
|
||||
static struct dentry *dbgfs_root;
|
||||
|
||||
static inline void driver_debugfs_create(void)
|
||||
{
|
||||
dbgfs_root = debugfs_create_dir(cfspi_spi_driver.driver.name, NULL);
|
||||
}
|
||||
|
||||
static inline void driver_debugfs_remove(void)
|
||||
{
|
||||
debugfs_remove(dbgfs_root);
|
||||
}
|
||||
|
||||
static inline void dev_debugfs_rem(struct cfspi *cfspi)
|
||||
{
|
||||
debugfs_remove(cfspi->dbgfs_frame);
|
||||
debugfs_remove(cfspi->dbgfs_state);
|
||||
debugfs_remove(cfspi->dbgfs_dir);
|
||||
}
|
||||
|
||||
static ssize_t dbgfs_state(struct file *file, char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
char *buf;
|
||||
int len = 0;
|
||||
ssize_t size;
|
||||
struct cfspi *cfspi = file->private_data;
|
||||
|
||||
buf = kzalloc(DEBUGFS_BUF_SIZE, GFP_KERNEL);
|
||||
if (!buf)
|
||||
return 0;
|
||||
|
||||
/* Print out debug information. */
|
||||
len += scnprintf((buf + len), (DEBUGFS_BUF_SIZE - len),
|
||||
"CAIF SPI debug information:\n");
|
||||
|
||||
len += scnprintf((buf + len), (DEBUGFS_BUF_SIZE - len), FLAVOR);
|
||||
|
||||
len += scnprintf((buf + len), (DEBUGFS_BUF_SIZE - len),
|
||||
"STATE: %d\n", cfspi->dbg_state);
|
||||
len += scnprintf((buf + len), (DEBUGFS_BUF_SIZE - len),
|
||||
"Previous CMD: 0x%x\n", cfspi->pcmd);
|
||||
len += scnprintf((buf + len), (DEBUGFS_BUF_SIZE - len),
|
||||
"Current CMD: 0x%x\n", cfspi->cmd);
|
||||
len += scnprintf((buf + len), (DEBUGFS_BUF_SIZE - len),
|
||||
"Previous TX len: %d\n", cfspi->tx_ppck_len);
|
||||
len += scnprintf((buf + len), (DEBUGFS_BUF_SIZE - len),
|
||||
"Previous RX len: %d\n", cfspi->rx_ppck_len);
|
||||
len += scnprintf((buf + len), (DEBUGFS_BUF_SIZE - len),
|
||||
"Current TX len: %d\n", cfspi->tx_cpck_len);
|
||||
len += scnprintf((buf + len), (DEBUGFS_BUF_SIZE - len),
|
||||
"Current RX len: %d\n", cfspi->rx_cpck_len);
|
||||
len += scnprintf((buf + len), (DEBUGFS_BUF_SIZE - len),
|
||||
"Next TX len: %d\n", cfspi->tx_npck_len);
|
||||
len += scnprintf((buf + len), (DEBUGFS_BUF_SIZE - len),
|
||||
"Next RX len: %d\n", cfspi->rx_npck_len);
|
||||
|
||||
if (len > DEBUGFS_BUF_SIZE)
|
||||
len = DEBUGFS_BUF_SIZE;
|
||||
|
||||
size = simple_read_from_buffer(user_buf, count, ppos, buf, len);
|
||||
kfree(buf);
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static ssize_t print_frame(char *buf, size_t size, char *frm,
|
||||
size_t count, size_t cut)
|
||||
{
|
||||
int len = 0;
|
||||
int i;
|
||||
for (i = 0; i < count; i++) {
|
||||
len += scnprintf((buf + len), (size - len),
|
||||
"[0x" BYTE_HEX_FMT "]",
|
||||
frm[i]);
|
||||
if ((i == cut) && (count > (cut * 2))) {
|
||||
/* Fast forward. */
|
||||
i = count - cut;
|
||||
len += scnprintf((buf + len), (size - len),
|
||||
"--- %zu bytes skipped ---\n",
|
||||
count - (cut * 2));
|
||||
}
|
||||
|
||||
if ((!(i % 10)) && i) {
|
||||
len += scnprintf((buf + len), (DEBUGFS_BUF_SIZE - len),
|
||||
"\n");
|
||||
}
|
||||
}
|
||||
len += scnprintf((buf + len), (DEBUGFS_BUF_SIZE - len), "\n");
|
||||
return len;
|
||||
}
|
||||
|
||||
static ssize_t dbgfs_frame(struct file *file, char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
char *buf;
|
||||
int len = 0;
|
||||
ssize_t size;
|
||||
struct cfspi *cfspi;
|
||||
|
||||
cfspi = file->private_data;
|
||||
buf = kzalloc(DEBUGFS_BUF_SIZE, GFP_KERNEL);
|
||||
if (!buf)
|
||||
return 0;
|
||||
|
||||
/* Print out debug information. */
|
||||
len += scnprintf((buf + len), (DEBUGFS_BUF_SIZE - len),
|
||||
"Current frame:\n");
|
||||
|
||||
len += scnprintf((buf + len), (DEBUGFS_BUF_SIZE - len),
|
||||
"Tx data (Len: %d):\n", cfspi->tx_cpck_len);
|
||||
|
||||
len += print_frame((buf + len), (DEBUGFS_BUF_SIZE - len),
|
||||
cfspi->xfer.va_tx[0],
|
||||
(cfspi->tx_cpck_len + SPI_CMD_SZ), 100);
|
||||
|
||||
len += scnprintf((buf + len), (DEBUGFS_BUF_SIZE - len),
|
||||
"Rx data (Len: %d):\n", cfspi->rx_cpck_len);
|
||||
|
||||
len += print_frame((buf + len), (DEBUGFS_BUF_SIZE - len),
|
||||
cfspi->xfer.va_rx,
|
||||
(cfspi->rx_cpck_len + SPI_CMD_SZ), 100);
|
||||
|
||||
size = simple_read_from_buffer(user_buf, count, ppos, buf, len);
|
||||
kfree(buf);
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static const struct file_operations dbgfs_state_fops = {
|
||||
.open = simple_open,
|
||||
.read = dbgfs_state,
|
||||
.owner = THIS_MODULE
|
||||
};
|
||||
|
||||
static const struct file_operations dbgfs_frame_fops = {
|
||||
.open = simple_open,
|
||||
.read = dbgfs_frame,
|
||||
.owner = THIS_MODULE
|
||||
};
|
||||
|
||||
static inline void dev_debugfs_add(struct cfspi *cfspi)
|
||||
{
|
||||
cfspi->dbgfs_dir = debugfs_create_dir(cfspi->pdev->name, dbgfs_root);
|
||||
cfspi->dbgfs_state = debugfs_create_file("state", 0444,
|
||||
cfspi->dbgfs_dir, cfspi,
|
||||
&dbgfs_state_fops);
|
||||
cfspi->dbgfs_frame = debugfs_create_file("frame", 0444,
|
||||
cfspi->dbgfs_dir, cfspi,
|
||||
&dbgfs_frame_fops);
|
||||
}
|
||||
|
||||
inline void cfspi_dbg_state(struct cfspi *cfspi, int state)
|
||||
{
|
||||
cfspi->dbg_state = state;
|
||||
};
|
||||
#else
|
||||
|
||||
static inline void driver_debugfs_create(void)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void driver_debugfs_remove(void)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void dev_debugfs_add(struct cfspi *cfspi)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void dev_debugfs_rem(struct cfspi *cfspi)
|
||||
{
|
||||
}
|
||||
|
||||
inline void cfspi_dbg_state(struct cfspi *cfspi, int state)
|
||||
{
|
||||
}
|
||||
#endif /* CONFIG_DEBUG_FS */
|
||||
|
||||
static LIST_HEAD(cfspi_list);
|
||||
static spinlock_t cfspi_list_lock;
|
||||
|
||||
/* SPI uplink head alignment. */
|
||||
static ssize_t up_head_align_show(struct device_driver *driver, char *buf)
|
||||
{
|
||||
return sprintf(buf, "%d\n", spi_up_head_align);
|
||||
}
|
||||
|
||||
static DRIVER_ATTR_RO(up_head_align);
|
||||
|
||||
/* SPI uplink tail alignment. */
|
||||
static ssize_t up_tail_align_show(struct device_driver *driver, char *buf)
|
||||
{
|
||||
return sprintf(buf, "%d\n", spi_up_tail_align);
|
||||
}
|
||||
|
||||
static DRIVER_ATTR_RO(up_tail_align);
|
||||
|
||||
/* SPI downlink head alignment. */
|
||||
static ssize_t down_head_align_show(struct device_driver *driver, char *buf)
|
||||
{
|
||||
return sprintf(buf, "%d\n", spi_down_head_align);
|
||||
}
|
||||
|
||||
static DRIVER_ATTR_RO(down_head_align);
|
||||
|
||||
/* SPI downlink tail alignment. */
|
||||
static ssize_t down_tail_align_show(struct device_driver *driver, char *buf)
|
||||
{
|
||||
return sprintf(buf, "%d\n", spi_down_tail_align);
|
||||
}
|
||||
|
||||
static DRIVER_ATTR_RO(down_tail_align);
|
||||
|
||||
/* SPI frame alignment. */
|
||||
static ssize_t frame_align_show(struct device_driver *driver, char *buf)
|
||||
{
|
||||
return sprintf(buf, "%d\n", spi_frm_align);
|
||||
}
|
||||
|
||||
static DRIVER_ATTR_RO(frame_align);
|
||||
|
||||
int cfspi_xmitfrm(struct cfspi *cfspi, u8 *buf, size_t len)
|
||||
{
|
||||
u8 *dst = buf;
|
||||
caif_assert(buf);
|
||||
|
||||
if (cfspi->slave && !cfspi->slave_talked)
|
||||
cfspi->slave_talked = true;
|
||||
|
||||
do {
|
||||
struct sk_buff *skb;
|
||||
struct caif_payload_info *info;
|
||||
int spad = 0;
|
||||
int epad;
|
||||
|
||||
skb = skb_dequeue(&cfspi->chead);
|
||||
if (!skb)
|
||||
break;
|
||||
|
||||
/*
|
||||
* Calculate length of frame including SPI padding.
|
||||
* The payload position is found in the control buffer.
|
||||
*/
|
||||
info = (struct caif_payload_info *)&skb->cb;
|
||||
|
||||
/*
|
||||
* Compute head offset i.e. number of bytes to add to
|
||||
* get the start of the payload aligned.
|
||||
*/
|
||||
if (spi_up_head_align > 1) {
|
||||
spad = 1 + PAD_POW2((info->hdr_len + 1), spi_up_head_align);
|
||||
*dst = (u8)(spad - 1);
|
||||
dst += spad;
|
||||
}
|
||||
|
||||
/* Copy in CAIF frame. */
|
||||
skb_copy_bits(skb, 0, dst, skb->len);
|
||||
dst += skb->len;
|
||||
cfspi->ndev->stats.tx_packets++;
|
||||
cfspi->ndev->stats.tx_bytes += skb->len;
|
||||
|
||||
/*
|
||||
* Compute tail offset i.e. number of bytes to add to
|
||||
* get the complete CAIF frame aligned.
|
||||
*/
|
||||
epad = PAD_POW2((skb->len + spad), spi_up_tail_align);
|
||||
dst += epad;
|
||||
|
||||
dev_kfree_skb(skb);
|
||||
|
||||
} while ((dst - buf) < len);
|
||||
|
||||
return dst - buf;
|
||||
}
|
||||
|
||||
int cfspi_xmitlen(struct cfspi *cfspi)
|
||||
{
|
||||
struct sk_buff *skb = NULL;
|
||||
int frm_len = 0;
|
||||
int pkts = 0;
|
||||
|
||||
/*
|
||||
* Decommit previously committed frames.
|
||||
* skb_queue_splice_tail(&cfspi->chead,&cfspi->qhead)
|
||||
*/
|
||||
while (skb_peek(&cfspi->chead)) {
|
||||
skb = skb_dequeue_tail(&cfspi->chead);
|
||||
skb_queue_head(&cfspi->qhead, skb);
|
||||
}
|
||||
|
||||
do {
|
||||
struct caif_payload_info *info = NULL;
|
||||
int spad = 0;
|
||||
int epad = 0;
|
||||
|
||||
skb = skb_dequeue(&cfspi->qhead);
|
||||
if (!skb)
|
||||
break;
|
||||
|
||||
/*
|
||||
* Calculate length of frame including SPI padding.
|
||||
* The payload position is found in the control buffer.
|
||||
*/
|
||||
info = (struct caif_payload_info *)&skb->cb;
|
||||
|
||||
/*
|
||||
* Compute head offset i.e. number of bytes to add to
|
||||
* get the start of the payload aligned.
|
||||
*/
|
||||
if (spi_up_head_align > 1)
|
||||
spad = 1 + PAD_POW2((info->hdr_len + 1), spi_up_head_align);
|
||||
|
||||
/*
|
||||
* Compute tail offset i.e. number of bytes to add to
|
||||
* get the complete CAIF frame aligned.
|
||||
*/
|
||||
epad = PAD_POW2((skb->len + spad), spi_up_tail_align);
|
||||
|
||||
if ((skb->len + spad + epad + frm_len) <= CAIF_MAX_SPI_FRAME) {
|
||||
skb_queue_tail(&cfspi->chead, skb);
|
||||
pkts++;
|
||||
frm_len += skb->len + spad + epad;
|
||||
} else {
|
||||
/* Put back packet. */
|
||||
skb_queue_head(&cfspi->qhead, skb);
|
||||
break;
|
||||
}
|
||||
} while (pkts <= CAIF_MAX_SPI_PKTS);
|
||||
|
||||
/*
|
||||
* Send flow on if previously sent flow off
|
||||
* and now go below the low water mark
|
||||
*/
|
||||
if (cfspi->flow_off_sent && cfspi->qhead.qlen < cfspi->qd_low_mark &&
|
||||
cfspi->cfdev.flowctrl) {
|
||||
cfspi->flow_off_sent = 0;
|
||||
cfspi->cfdev.flowctrl(cfspi->ndev, 1);
|
||||
}
|
||||
|
||||
return frm_len;
|
||||
}
|
||||
|
||||
static void cfspi_ss_cb(bool assert, struct cfspi_ifc *ifc)
|
||||
{
|
||||
struct cfspi *cfspi = (struct cfspi *)ifc->priv;
|
||||
|
||||
/*
|
||||
* The slave device is the master on the link. Interrupts before the
|
||||
* slave has transmitted are considered spurious.
|
||||
*/
|
||||
if (cfspi->slave && !cfspi->slave_talked) {
|
||||
printk(KERN_WARNING "CFSPI: Spurious SS interrupt.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!in_interrupt())
|
||||
spin_lock(&cfspi->lock);
|
||||
if (assert) {
|
||||
set_bit(SPI_SS_ON, &cfspi->state);
|
||||
set_bit(SPI_XFER, &cfspi->state);
|
||||
} else {
|
||||
set_bit(SPI_SS_OFF, &cfspi->state);
|
||||
}
|
||||
if (!in_interrupt())
|
||||
spin_unlock(&cfspi->lock);
|
||||
|
||||
/* Wake up the xfer thread. */
|
||||
if (assert)
|
||||
wake_up_interruptible(&cfspi->wait);
|
||||
}
|
||||
|
||||
static void cfspi_xfer_done_cb(struct cfspi_ifc *ifc)
|
||||
{
|
||||
struct cfspi *cfspi = (struct cfspi *)ifc->priv;
|
||||
|
||||
/* Transfer done, complete work queue */
|
||||
complete(&cfspi->comp);
|
||||
}
|
||||
|
||||
static netdev_tx_t cfspi_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
{
|
||||
struct cfspi *cfspi = NULL;
|
||||
unsigned long flags;
|
||||
if (!dev)
|
||||
return -EINVAL;
|
||||
|
||||
cfspi = netdev_priv(dev);
|
||||
|
||||
skb_queue_tail(&cfspi->qhead, skb);
|
||||
|
||||
spin_lock_irqsave(&cfspi->lock, flags);
|
||||
if (!test_and_set_bit(SPI_XFER, &cfspi->state)) {
|
||||
/* Wake up xfer thread. */
|
||||
wake_up_interruptible(&cfspi->wait);
|
||||
}
|
||||
spin_unlock_irqrestore(&cfspi->lock, flags);
|
||||
|
||||
/* Send flow off if number of bytes is above high water mark */
|
||||
if (!cfspi->flow_off_sent &&
|
||||
cfspi->qhead.qlen > cfspi->qd_high_mark &&
|
||||
cfspi->cfdev.flowctrl) {
|
||||
cfspi->flow_off_sent = 1;
|
||||
cfspi->cfdev.flowctrl(cfspi->ndev, 0);
|
||||
}
|
||||
|
||||
return NETDEV_TX_OK;
|
||||
}
|
||||
|
||||
int cfspi_rxfrm(struct cfspi *cfspi, u8 *buf, size_t len)
|
||||
{
|
||||
u8 *src = buf;
|
||||
|
||||
caif_assert(buf != NULL);
|
||||
|
||||
do {
|
||||
int res;
|
||||
struct sk_buff *skb = NULL;
|
||||
int spad = 0;
|
||||
int epad = 0;
|
||||
int pkt_len = 0;
|
||||
|
||||
/*
|
||||
* Compute head offset i.e. number of bytes added to
|
||||
* get the start of the payload aligned.
|
||||
*/
|
||||
if (spi_down_head_align > 1) {
|
||||
spad = 1 + *src;
|
||||
src += spad;
|
||||
}
|
||||
|
||||
/* Read length of CAIF frame (little endian). */
|
||||
pkt_len = *src;
|
||||
pkt_len |= ((*(src+1)) << 8) & 0xFF00;
|
||||
pkt_len += 2; /* Add FCS fields. */
|
||||
|
||||
/* Get a suitable caif packet and copy in data. */
|
||||
|
||||
skb = netdev_alloc_skb(cfspi->ndev, pkt_len + 1);
|
||||
caif_assert(skb != NULL);
|
||||
|
||||
skb_put_data(skb, src, pkt_len);
|
||||
src += pkt_len;
|
||||
|
||||
skb->protocol = htons(ETH_P_CAIF);
|
||||
skb_reset_mac_header(skb);
|
||||
|
||||
/*
|
||||
* Push received packet up the stack.
|
||||
*/
|
||||
if (!spi_loop)
|
||||
res = netif_rx_ni(skb);
|
||||
else
|
||||
res = cfspi_xmit(skb, cfspi->ndev);
|
||||
|
||||
if (!res) {
|
||||
cfspi->ndev->stats.rx_packets++;
|
||||
cfspi->ndev->stats.rx_bytes += pkt_len;
|
||||
} else
|
||||
cfspi->ndev->stats.rx_dropped++;
|
||||
|
||||
/*
|
||||
* Compute tail offset i.e. number of bytes added to
|
||||
* get the complete CAIF frame aligned.
|
||||
*/
|
||||
epad = PAD_POW2((pkt_len + spad), spi_down_tail_align);
|
||||
src += epad;
|
||||
} while ((src - buf) < len);
|
||||
|
||||
return src - buf;
|
||||
}
|
||||
|
||||
static int cfspi_open(struct net_device *dev)
|
||||
{
|
||||
netif_wake_queue(dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cfspi_close(struct net_device *dev)
|
||||
{
|
||||
netif_stop_queue(dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cfspi_init(struct net_device *dev)
|
||||
{
|
||||
int res = 0;
|
||||
struct cfspi *cfspi = netdev_priv(dev);
|
||||
|
||||
/* Set flow info. */
|
||||
cfspi->flow_off_sent = 0;
|
||||
cfspi->qd_low_mark = LOW_WATER_MARK;
|
||||
cfspi->qd_high_mark = HIGH_WATER_MARK;
|
||||
|
||||
/* Set slave info. */
|
||||
if (!strncmp(cfspi_spi_driver.driver.name, "cfspi_sspi", 10)) {
|
||||
cfspi->slave = true;
|
||||
cfspi->slave_talked = false;
|
||||
} else {
|
||||
cfspi->slave = false;
|
||||
cfspi->slave_talked = false;
|
||||
}
|
||||
|
||||
/* Allocate DMA buffers. */
|
||||
cfspi->xfer.va_tx[0] = dma_alloc(cfspi, &cfspi->xfer.pa_tx[0]);
|
||||
if (!cfspi->xfer.va_tx[0]) {
|
||||
res = -ENODEV;
|
||||
goto err_dma_alloc_tx_0;
|
||||
}
|
||||
|
||||
cfspi->xfer.va_rx = dma_alloc(cfspi, &cfspi->xfer.pa_rx);
|
||||
|
||||
if (!cfspi->xfer.va_rx) {
|
||||
res = -ENODEV;
|
||||
goto err_dma_alloc_rx;
|
||||
}
|
||||
|
||||
/* Initialize the work queue. */
|
||||
INIT_WORK(&cfspi->work, cfspi_xfer);
|
||||
|
||||
/* Initialize spin locks. */
|
||||
spin_lock_init(&cfspi->lock);
|
||||
|
||||
/* Initialize flow control state. */
|
||||
cfspi->flow_stop = false;
|
||||
|
||||
/* Initialize wait queue. */
|
||||
init_waitqueue_head(&cfspi->wait);
|
||||
|
||||
/* Create work thread. */
|
||||
cfspi->wq = create_singlethread_workqueue(dev->name);
|
||||
if (!cfspi->wq) {
|
||||
printk(KERN_WARNING "CFSPI: failed to create work queue.\n");
|
||||
res = -ENODEV;
|
||||
goto err_create_wq;
|
||||
}
|
||||
|
||||
/* Initialize work queue. */
|
||||
init_completion(&cfspi->comp);
|
||||
|
||||
/* Create debugfs entries. */
|
||||
dev_debugfs_add(cfspi);
|
||||
|
||||
/* Set up the ifc. */
|
||||
cfspi->ifc.ss_cb = cfspi_ss_cb;
|
||||
cfspi->ifc.xfer_done_cb = cfspi_xfer_done_cb;
|
||||
cfspi->ifc.priv = cfspi;
|
||||
|
||||
/* Add CAIF SPI device to list. */
|
||||
spin_lock(&cfspi_list_lock);
|
||||
list_add_tail(&cfspi->list, &cfspi_list);
|
||||
spin_unlock(&cfspi_list_lock);
|
||||
|
||||
/* Schedule the work queue. */
|
||||
queue_work(cfspi->wq, &cfspi->work);
|
||||
|
||||
return 0;
|
||||
|
||||
err_create_wq:
|
||||
dma_free(cfspi, cfspi->xfer.va_rx, cfspi->xfer.pa_rx);
|
||||
err_dma_alloc_rx:
|
||||
dma_free(cfspi, cfspi->xfer.va_tx[0], cfspi->xfer.pa_tx[0]);
|
||||
err_dma_alloc_tx_0:
|
||||
return res;
|
||||
}
|
||||
|
||||
static void cfspi_uninit(struct net_device *dev)
|
||||
{
|
||||
struct cfspi *cfspi = netdev_priv(dev);
|
||||
|
||||
/* Remove from list. */
|
||||
spin_lock(&cfspi_list_lock);
|
||||
list_del(&cfspi->list);
|
||||
spin_unlock(&cfspi_list_lock);
|
||||
|
||||
cfspi->ndev = NULL;
|
||||
/* Free DMA buffers. */
|
||||
dma_free(cfspi, cfspi->xfer.va_rx, cfspi->xfer.pa_rx);
|
||||
dma_free(cfspi, cfspi->xfer.va_tx[0], cfspi->xfer.pa_tx[0]);
|
||||
set_bit(SPI_TERMINATE, &cfspi->state);
|
||||
wake_up_interruptible(&cfspi->wait);
|
||||
destroy_workqueue(cfspi->wq);
|
||||
/* Destroy debugfs directory and files. */
|
||||
dev_debugfs_rem(cfspi);
|
||||
return;
|
||||
}
|
||||
|
||||
static const struct net_device_ops cfspi_ops = {
|
||||
.ndo_open = cfspi_open,
|
||||
.ndo_stop = cfspi_close,
|
||||
.ndo_init = cfspi_init,
|
||||
.ndo_uninit = cfspi_uninit,
|
||||
.ndo_start_xmit = cfspi_xmit
|
||||
};
|
||||
|
||||
static void cfspi_setup(struct net_device *dev)
|
||||
{
|
||||
struct cfspi *cfspi = netdev_priv(dev);
|
||||
dev->features = 0;
|
||||
dev->netdev_ops = &cfspi_ops;
|
||||
dev->type = ARPHRD_CAIF;
|
||||
dev->flags = IFF_NOARP | IFF_POINTOPOINT;
|
||||
dev->priv_flags |= IFF_NO_QUEUE;
|
||||
dev->mtu = SPI_MAX_PAYLOAD_SIZE;
|
||||
dev->needs_free_netdev = true;
|
||||
skb_queue_head_init(&cfspi->qhead);
|
||||
skb_queue_head_init(&cfspi->chead);
|
||||
cfspi->cfdev.link_select = CAIF_LINK_HIGH_BANDW;
|
||||
cfspi->cfdev.use_frag = false;
|
||||
cfspi->cfdev.use_stx = false;
|
||||
cfspi->cfdev.use_fcs = false;
|
||||
cfspi->ndev = dev;
|
||||
}
|
||||
|
||||
int cfspi_spi_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct cfspi *cfspi = NULL;
|
||||
struct net_device *ndev;
|
||||
struct cfspi_dev *dev;
|
||||
int res;
|
||||
dev = (struct cfspi_dev *)pdev->dev.platform_data;
|
||||
|
||||
if (!dev)
|
||||
return -ENODEV;
|
||||
|
||||
ndev = alloc_netdev(sizeof(struct cfspi), "cfspi%d",
|
||||
NET_NAME_UNKNOWN, cfspi_setup);
|
||||
if (!ndev)
|
||||
return -ENOMEM;
|
||||
|
||||
cfspi = netdev_priv(ndev);
|
||||
netif_stop_queue(ndev);
|
||||
cfspi->ndev = ndev;
|
||||
cfspi->pdev = pdev;
|
||||
|
||||
/* Assign the SPI device. */
|
||||
cfspi->dev = dev;
|
||||
/* Assign the device ifc to this SPI interface. */
|
||||
dev->ifc = &cfspi->ifc;
|
||||
|
||||
/* Register network device. */
|
||||
res = register_netdev(ndev);
|
||||
if (res) {
|
||||
printk(KERN_ERR "CFSPI: Reg. error: %d.\n", res);
|
||||
goto err_net_reg;
|
||||
}
|
||||
return res;
|
||||
|
||||
err_net_reg:
|
||||
free_netdev(ndev);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int cfspi_spi_remove(struct platform_device *pdev)
|
||||
{
|
||||
/* Everything is done in cfspi_uninit(). */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit cfspi_exit_module(void)
|
||||
{
|
||||
struct list_head *list_node;
|
||||
struct list_head *n;
|
||||
struct cfspi *cfspi = NULL;
|
||||
|
||||
list_for_each_safe(list_node, n, &cfspi_list) {
|
||||
cfspi = list_entry(list_node, struct cfspi, list);
|
||||
unregister_netdev(cfspi->ndev);
|
||||
}
|
||||
|
||||
/* Destroy sysfs files. */
|
||||
driver_remove_file(&cfspi_spi_driver.driver,
|
||||
&driver_attr_up_head_align);
|
||||
driver_remove_file(&cfspi_spi_driver.driver,
|
||||
&driver_attr_up_tail_align);
|
||||
driver_remove_file(&cfspi_spi_driver.driver,
|
||||
&driver_attr_down_head_align);
|
||||
driver_remove_file(&cfspi_spi_driver.driver,
|
||||
&driver_attr_down_tail_align);
|
||||
driver_remove_file(&cfspi_spi_driver.driver, &driver_attr_frame_align);
|
||||
/* Unregister platform driver. */
|
||||
platform_driver_unregister(&cfspi_spi_driver);
|
||||
/* Destroy debugfs root directory. */
|
||||
driver_debugfs_remove();
|
||||
}
|
||||
|
||||
static int __init cfspi_init_module(void)
|
||||
{
|
||||
int result;
|
||||
|
||||
/* Initialize spin lock. */
|
||||
spin_lock_init(&cfspi_list_lock);
|
||||
|
||||
/* Register platform driver. */
|
||||
result = platform_driver_register(&cfspi_spi_driver);
|
||||
if (result) {
|
||||
printk(KERN_ERR "Could not register platform SPI driver.\n");
|
||||
goto err_dev_register;
|
||||
}
|
||||
|
||||
/* Create sysfs files. */
|
||||
result =
|
||||
driver_create_file(&cfspi_spi_driver.driver,
|
||||
&driver_attr_up_head_align);
|
||||
if (result) {
|
||||
printk(KERN_ERR "Sysfs creation failed 1.\n");
|
||||
goto err_create_up_head_align;
|
||||
}
|
||||
|
||||
result =
|
||||
driver_create_file(&cfspi_spi_driver.driver,
|
||||
&driver_attr_up_tail_align);
|
||||
if (result) {
|
||||
printk(KERN_ERR "Sysfs creation failed 2.\n");
|
||||
goto err_create_up_tail_align;
|
||||
}
|
||||
|
||||
result =
|
||||
driver_create_file(&cfspi_spi_driver.driver,
|
||||
&driver_attr_down_head_align);
|
||||
if (result) {
|
||||
printk(KERN_ERR "Sysfs creation failed 3.\n");
|
||||
goto err_create_down_head_align;
|
||||
}
|
||||
|
||||
result =
|
||||
driver_create_file(&cfspi_spi_driver.driver,
|
||||
&driver_attr_down_tail_align);
|
||||
if (result) {
|
||||
printk(KERN_ERR "Sysfs creation failed 4.\n");
|
||||
goto err_create_down_tail_align;
|
||||
}
|
||||
|
||||
result =
|
||||
driver_create_file(&cfspi_spi_driver.driver,
|
||||
&driver_attr_frame_align);
|
||||
if (result) {
|
||||
printk(KERN_ERR "Sysfs creation failed 5.\n");
|
||||
goto err_create_frame_align;
|
||||
}
|
||||
driver_debugfs_create();
|
||||
return result;
|
||||
|
||||
err_create_frame_align:
|
||||
driver_remove_file(&cfspi_spi_driver.driver,
|
||||
&driver_attr_down_tail_align);
|
||||
err_create_down_tail_align:
|
||||
driver_remove_file(&cfspi_spi_driver.driver,
|
||||
&driver_attr_down_head_align);
|
||||
err_create_down_head_align:
|
||||
driver_remove_file(&cfspi_spi_driver.driver,
|
||||
&driver_attr_up_tail_align);
|
||||
err_create_up_tail_align:
|
||||
driver_remove_file(&cfspi_spi_driver.driver,
|
||||
&driver_attr_up_head_align);
|
||||
err_create_up_head_align:
|
||||
platform_driver_unregister(&cfspi_spi_driver);
|
||||
err_dev_register:
|
||||
return result;
|
||||
}
|
||||
|
||||
module_init(cfspi_init_module);
|
||||
module_exit(cfspi_exit_module);
|
@@ -1,254 +0,0 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (C) ST-Ericsson AB 2010
|
||||
* Author: Daniel Martensson
|
||||
*/
|
||||
#include <linux/module.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/semaphore.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/completion.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/debugfs.h>
|
||||
#include <net/caif/caif_spi.h>
|
||||
|
||||
#ifndef CONFIG_CAIF_SPI_SYNC
|
||||
#define SPI_DATA_POS 0
|
||||
static inline int forward_to_spi_cmd(struct cfspi *cfspi)
|
||||
{
|
||||
return cfspi->rx_cpck_len;
|
||||
}
|
||||
#else
|
||||
#define SPI_DATA_POS SPI_CMD_SZ
|
||||
static inline int forward_to_spi_cmd(struct cfspi *cfspi)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
int spi_frm_align = 2;
|
||||
|
||||
/*
|
||||
* SPI padding options.
|
||||
* Warning: must be a base of 2 (& operation used) and can not be zero !
|
||||
*/
|
||||
int spi_up_head_align = 1 << 1;
|
||||
int spi_up_tail_align = 1 << 0;
|
||||
int spi_down_head_align = 1 << 2;
|
||||
int spi_down_tail_align = 1 << 1;
|
||||
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
static inline void debugfs_store_prev(struct cfspi *cfspi)
|
||||
{
|
||||
/* Store previous command for debugging reasons.*/
|
||||
cfspi->pcmd = cfspi->cmd;
|
||||
/* Store previous transfer. */
|
||||
cfspi->tx_ppck_len = cfspi->tx_cpck_len;
|
||||
cfspi->rx_ppck_len = cfspi->rx_cpck_len;
|
||||
}
|
||||
#else
|
||||
static inline void debugfs_store_prev(struct cfspi *cfspi)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
void cfspi_xfer(struct work_struct *work)
|
||||
{
|
||||
struct cfspi *cfspi;
|
||||
u8 *ptr = NULL;
|
||||
unsigned long flags;
|
||||
int ret;
|
||||
cfspi = container_of(work, struct cfspi, work);
|
||||
|
||||
/* Initialize state. */
|
||||
cfspi->cmd = SPI_CMD_EOT;
|
||||
|
||||
for (;;) {
|
||||
|
||||
cfspi_dbg_state(cfspi, CFSPI_STATE_WAITING);
|
||||
|
||||
/* Wait for master talk or transmit event. */
|
||||
wait_event_interruptible(cfspi->wait,
|
||||
test_bit(SPI_XFER, &cfspi->state) ||
|
||||
test_bit(SPI_TERMINATE, &cfspi->state));
|
||||
|
||||
if (test_bit(SPI_TERMINATE, &cfspi->state))
|
||||
return;
|
||||
|
||||
#if CFSPI_DBG_PREFILL
|
||||
/* Prefill buffers for easier debugging. */
|
||||
memset(cfspi->xfer.va_tx, 0xFF, SPI_DMA_BUF_LEN);
|
||||
memset(cfspi->xfer.va_rx, 0xFF, SPI_DMA_BUF_LEN);
|
||||
#endif /* CFSPI_DBG_PREFILL */
|
||||
|
||||
cfspi_dbg_state(cfspi, CFSPI_STATE_AWAKE);
|
||||
|
||||
/* Check whether we have a committed frame. */
|
||||
if (cfspi->tx_cpck_len) {
|
||||
int len;
|
||||
|
||||
cfspi_dbg_state(cfspi, CFSPI_STATE_FETCH_PKT);
|
||||
|
||||
/* Copy committed SPI frames after the SPI indication. */
|
||||
ptr = (u8 *) cfspi->xfer.va_tx;
|
||||
ptr += SPI_IND_SZ;
|
||||
len = cfspi_xmitfrm(cfspi, ptr, cfspi->tx_cpck_len);
|
||||
WARN_ON(len != cfspi->tx_cpck_len);
|
||||
}
|
||||
|
||||
cfspi_dbg_state(cfspi, CFSPI_STATE_GET_NEXT);
|
||||
|
||||
/* Get length of next frame to commit. */
|
||||
cfspi->tx_npck_len = cfspi_xmitlen(cfspi);
|
||||
|
||||
WARN_ON(cfspi->tx_npck_len > SPI_DMA_BUF_LEN);
|
||||
|
||||
/*
|
||||
* Add indication and length at the beginning of the frame,
|
||||
* using little endian.
|
||||
*/
|
||||
ptr = (u8 *) cfspi->xfer.va_tx;
|
||||
*ptr++ = SPI_CMD_IND;
|
||||
*ptr++ = (SPI_CMD_IND & 0xFF00) >> 8;
|
||||
*ptr++ = cfspi->tx_npck_len & 0x00FF;
|
||||
*ptr++ = (cfspi->tx_npck_len & 0xFF00) >> 8;
|
||||
|
||||
/* Calculate length of DMAs. */
|
||||
cfspi->xfer.tx_dma_len = cfspi->tx_cpck_len + SPI_IND_SZ;
|
||||
cfspi->xfer.rx_dma_len = cfspi->rx_cpck_len + SPI_CMD_SZ;
|
||||
|
||||
/* Add SPI TX frame alignment padding, if necessary. */
|
||||
if (cfspi->tx_cpck_len &&
|
||||
(cfspi->xfer.tx_dma_len % spi_frm_align)) {
|
||||
|
||||
cfspi->xfer.tx_dma_len += spi_frm_align -
|
||||
(cfspi->xfer.tx_dma_len % spi_frm_align);
|
||||
}
|
||||
|
||||
/* Add SPI RX frame alignment padding, if necessary. */
|
||||
if (cfspi->rx_cpck_len &&
|
||||
(cfspi->xfer.rx_dma_len % spi_frm_align)) {
|
||||
|
||||
cfspi->xfer.rx_dma_len += spi_frm_align -
|
||||
(cfspi->xfer.rx_dma_len % spi_frm_align);
|
||||
}
|
||||
|
||||
cfspi_dbg_state(cfspi, CFSPI_STATE_INIT_XFER);
|
||||
|
||||
/* Start transfer. */
|
||||
ret = cfspi->dev->init_xfer(&cfspi->xfer, cfspi->dev);
|
||||
WARN_ON(ret);
|
||||
|
||||
cfspi_dbg_state(cfspi, CFSPI_STATE_WAIT_ACTIVE);
|
||||
|
||||
/*
|
||||
* TODO: We might be able to make an assumption if this is the
|
||||
* first loop. Make sure that minimum toggle time is respected.
|
||||
*/
|
||||
udelay(MIN_TRANSITION_TIME_USEC);
|
||||
|
||||
cfspi_dbg_state(cfspi, CFSPI_STATE_SIG_ACTIVE);
|
||||
|
||||
/* Signal that we are ready to receive data. */
|
||||
cfspi->dev->sig_xfer(true, cfspi->dev);
|
||||
|
||||
cfspi_dbg_state(cfspi, CFSPI_STATE_WAIT_XFER_DONE);
|
||||
|
||||
/* Wait for transfer completion. */
|
||||
wait_for_completion(&cfspi->comp);
|
||||
|
||||
cfspi_dbg_state(cfspi, CFSPI_STATE_XFER_DONE);
|
||||
|
||||
if (cfspi->cmd == SPI_CMD_EOT) {
|
||||
/*
|
||||
* Clear the master talk bit. A xfer is always at
|
||||
* least two bursts.
|
||||
*/
|
||||
clear_bit(SPI_SS_ON, &cfspi->state);
|
||||
}
|
||||
|
||||
cfspi_dbg_state(cfspi, CFSPI_STATE_WAIT_INACTIVE);
|
||||
|
||||
/* Make sure that the minimum toggle time is respected. */
|
||||
if (SPI_XFER_TIME_USEC(cfspi->xfer.tx_dma_len,
|
||||
cfspi->dev->clk_mhz) <
|
||||
MIN_TRANSITION_TIME_USEC) {
|
||||
|
||||
udelay(MIN_TRANSITION_TIME_USEC -
|
||||
SPI_XFER_TIME_USEC
|
||||
(cfspi->xfer.tx_dma_len, cfspi->dev->clk_mhz));
|
||||
}
|
||||
|
||||
cfspi_dbg_state(cfspi, CFSPI_STATE_SIG_INACTIVE);
|
||||
|
||||
/* De-assert transfer signal. */
|
||||
cfspi->dev->sig_xfer(false, cfspi->dev);
|
||||
|
||||
/* Check whether we received a CAIF packet. */
|
||||
if (cfspi->rx_cpck_len) {
|
||||
int len;
|
||||
|
||||
cfspi_dbg_state(cfspi, CFSPI_STATE_DELIVER_PKT);
|
||||
|
||||
/* Parse SPI frame. */
|
||||
ptr = ((u8 *)(cfspi->xfer.va_rx + SPI_DATA_POS));
|
||||
|
||||
len = cfspi_rxfrm(cfspi, ptr, cfspi->rx_cpck_len);
|
||||
WARN_ON(len != cfspi->rx_cpck_len);
|
||||
}
|
||||
|
||||
/* Check the next SPI command and length. */
|
||||
ptr = (u8 *) cfspi->xfer.va_rx;
|
||||
|
||||
ptr += forward_to_spi_cmd(cfspi);
|
||||
|
||||
cfspi->cmd = *ptr++;
|
||||
cfspi->cmd |= ((*ptr++) << 8) & 0xFF00;
|
||||
cfspi->rx_npck_len = *ptr++;
|
||||
cfspi->rx_npck_len |= ((*ptr++) << 8) & 0xFF00;
|
||||
|
||||
WARN_ON(cfspi->rx_npck_len > SPI_DMA_BUF_LEN);
|
||||
WARN_ON(cfspi->cmd > SPI_CMD_EOT);
|
||||
|
||||
debugfs_store_prev(cfspi);
|
||||
|
||||
/* Check whether the master issued an EOT command. */
|
||||
if (cfspi->cmd == SPI_CMD_EOT) {
|
||||
/* Reset state. */
|
||||
cfspi->tx_cpck_len = 0;
|
||||
cfspi->rx_cpck_len = 0;
|
||||
} else {
|
||||
/* Update state. */
|
||||
cfspi->tx_cpck_len = cfspi->tx_npck_len;
|
||||
cfspi->rx_cpck_len = cfspi->rx_npck_len;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check whether we need to clear the xfer bit.
|
||||
* Spin lock needed for packet insertion.
|
||||
* Test and clear of different bits
|
||||
* are not supported.
|
||||
*/
|
||||
spin_lock_irqsave(&cfspi->lock, flags);
|
||||
if (cfspi->cmd == SPI_CMD_EOT && !cfspi_xmitlen(cfspi)
|
||||
&& !test_bit(SPI_SS_ON, &cfspi->state))
|
||||
clear_bit(SPI_XFER, &cfspi->state);
|
||||
|
||||
spin_unlock_irqrestore(&cfspi->lock, flags);
|
||||
}
|
||||
}
|
||||
|
||||
struct platform_driver cfspi_spi_driver = {
|
||||
.probe = cfspi_spi_probe,
|
||||
.remove = cfspi_spi_remove,
|
||||
.driver = {
|
||||
.name = "cfspi_sspi",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
};
|
@@ -652,7 +652,7 @@ static int cfv_probe(struct virtio_device *vdev)
|
||||
const char *cfv_netdev_name = "cfvrt";
|
||||
struct net_device *netdev;
|
||||
struct cfv_info *cfv;
|
||||
int err = -EINVAL;
|
||||
int err;
|
||||
|
||||
netdev = alloc_netdev(sizeof(struct cfv_info), cfv_netdev_name,
|
||||
NET_NAME_UNKNOWN, cfv_netdev_setup);
|
||||
|
@@ -41,8 +41,8 @@ config CAN_SLCAN
|
||||
www.canusb.com / www.can232.com / www.mictronics.de / www.canhack.de
|
||||
|
||||
Userspace tools to attach the SLCAN line discipline (slcan_attach,
|
||||
slcand) can be found in the can-utils at the SocketCAN SVN, see
|
||||
http://developer.berlios.de/projects/socketcan for details.
|
||||
slcand) can be found in the can-utils at the linux-can project, see
|
||||
https://github.com/linux-can/can-utils for details.
|
||||
|
||||
The slcan driver supports up to 10 CAN netdevices by default which
|
||||
can be changed by the 'maxdev=xx' module option. This driver can
|
||||
|
@@ -643,7 +643,7 @@ static void at91_read_msg(struct net_device *dev, unsigned int mb)
|
||||
*
|
||||
* The first message goes into mb nr. 1 and issues an interrupt. All
|
||||
* rx ints are disabled in the interrupt handler and a napi poll is
|
||||
* scheduled. We read the mailbox, but do _not_ reenable the mb (to
|
||||
* scheduled. We read the mailbox, but do _not_ re-enable the mb (to
|
||||
* receive another message).
|
||||
*
|
||||
* lower mbxs upper
|
||||
@@ -661,13 +661,13 @@ static void at91_read_msg(struct net_device *dev, unsigned int mb)
|
||||
*
|
||||
* The variable priv->rx_next points to the next mailbox to read a
|
||||
* message from. As long we're in the lower mailboxes we just read the
|
||||
* mailbox but not reenable it.
|
||||
* mailbox but not re-enable it.
|
||||
*
|
||||
* With completion of the last of the lower mailboxes, we reenable the
|
||||
* With completion of the last of the lower mailboxes, we re-enable the
|
||||
* whole first group, but continue to look for filled mailboxes in the
|
||||
* upper mailboxes. Imagine the second group like overflow mailboxes,
|
||||
* which takes CAN messages if the lower goup is full. While in the
|
||||
* upper group we reenable the mailbox right after reading it. Giving
|
||||
* upper group we re-enable the mailbox right after reading it. Giving
|
||||
* the chip more room to store messages.
|
||||
*
|
||||
* After finishing we look again in the lower group if we've still
|
||||
|
@@ -356,15 +356,6 @@ static void c_can_setup_tx_object(struct net_device *dev, int iface,
|
||||
}
|
||||
}
|
||||
|
||||
static inline void c_can_activate_all_lower_rx_msg_obj(struct net_device *dev,
|
||||
int iface)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = C_CAN_MSG_OBJ_RX_FIRST; i <= C_CAN_MSG_RX_LOW_LAST; i++)
|
||||
c_can_object_get(dev, iface, i, IF_COMM_CLR_NEWDAT);
|
||||
}
|
||||
|
||||
static int c_can_handle_lost_msg_obj(struct net_device *dev,
|
||||
int iface, int objno, u32 ctrl)
|
||||
{
|
||||
|
@@ -81,7 +81,7 @@ enum reg {
|
||||
C_CAN_FUNCTION_REG,
|
||||
};
|
||||
|
||||
static const u16 reg_map_c_can[] = {
|
||||
static const u16 __maybe_unused reg_map_c_can[] = {
|
||||
[C_CAN_CTRL_REG] = 0x00,
|
||||
[C_CAN_STS_REG] = 0x02,
|
||||
[C_CAN_ERR_CNT_REG] = 0x04,
|
||||
@@ -121,7 +121,7 @@ static const u16 reg_map_c_can[] = {
|
||||
[C_CAN_MSGVAL2_REG] = 0xB2,
|
||||
};
|
||||
|
||||
static const u16 reg_map_d_can[] = {
|
||||
static const u16 __maybe_unused reg_map_d_can[] = {
|
||||
[C_CAN_CTRL_REG] = 0x00,
|
||||
[C_CAN_CTRL_EX_REG] = 0x02,
|
||||
[C_CAN_STS_REG] = 0x04,
|
||||
|
@@ -538,7 +538,7 @@ static int cc770_err(struct net_device *dev, u8 status)
|
||||
priv->can.can_stats.error_warning++;
|
||||
}
|
||||
} else {
|
||||
/* Back to error avtive */
|
||||
/* Back to error active */
|
||||
cf->can_id |= CAN_ERR_PROT;
|
||||
cf->data[2] = CAN_ERR_PROT_ACTIVE;
|
||||
priv->can.state = CAN_STATE_ERROR_ACTIVE;
|
||||
|
@@ -184,7 +184,7 @@ struct cc770_priv {
|
||||
u8 control_normal_mode; /* Control register for normal mode */
|
||||
u8 cpu_interface; /* CPU interface register */
|
||||
u8 clkout; /* Clock out register */
|
||||
u8 bus_config; /* Bus conffiguration register */
|
||||
u8 bus_config; /* Bus configuration register */
|
||||
|
||||
struct sk_buff *tx_skb;
|
||||
};
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user