Core:
- Remove socket skb caches - Add a SO_RESERVE_MEM socket op to forward allocate buffer space and avoid memory accounting overhead on each message sent - Introduce managed neighbor entries - added by control plane and resolved by the kernel for use in acceleration paths (BPF / XDP right now, HW offload users will benefit as well) - Make neighbor eviction on link down controllable by userspace to work around WiFi networks with bad roaming implementations - vrf: Rework interaction with netfilter/conntrack - fq_codel: implement L4S style ce_threshold_ect1 marking - sch: Eliminate unnecessary RCU waits in mini_qdisc_pair_swap() BPF: - Add support for new btf kind BTF_KIND_TAG, arbitrary type tagging as implemented in LLVM14 - Introduce bpf_get_branch_snapshot() to capture Last Branch Records - Implement variadic trace_printk helper - Add a new Bloomfilter map type - Track <8-byte scalar spill and refill - Access hw timestamp through BPF's __sk_buff - Disallow unprivileged BPF by default - Document BPF licensing Netfilter: - Introduce egress hook for looking at raw outgoing packets - Allow matching on and modifying inner headers / payload data - Add NFT_META_IFTYPE to match on the interface type either from ingress or egress Protocols: - Multi-Path TCP: - increase default max additional subflows to 2 - rework forward memory allocation - add getsockopts: MPTCP_INFO, MPTCP_TCPINFO, MPTCP_SUBFLOW_ADDRS - MCTP flow support allowing lower layer drivers to configure msg muxing as needed - Automatic Multicast Tunneling (AMT) driver based on RFC7450 - HSR support the redbox supervision frames (IEC-62439-3:2018) - Support for the ip6ip6 encapsulation of IOAM - Netlink interface for CAN-FD's Transmitter Delay Compensation - Support SMC-Rv2 eliminating the current same-subnet restriction, by exploiting the UDP encapsulation feature of RoCE adapters - TLS: add SM4 GCM/CCM crypto support - Bluetooth: initial support for link quality and audio/codec offload Driver APIs: - Add a batched interface for RX buffer allocation in AF_XDP buffer pool - ethtool: Add ability to control transceiver modules' power mode - phy: Introduce supported interfaces bitmap to express MAC capabilities and simplify PHY code - Drop rtnl_lock from DSA .port_fdb_{add,del} callbacks New drivers: - WiFi driver for Realtek 8852AE 802.11ax devices (rtw89) - Ethernet driver for ASIX AX88796C SPI device (x88796c) Drivers: - Broadcom PHYs - support 72165, 7712 16nm PHYs - support IDDQ-SR for additional power savings - PHY support for QCA8081, QCA9561 PHYs - NXP DPAA2: support for IRQ coalescing - NXP Ethernet (enetc): support for software TCP segmentation - Renesas Ethernet (ravb) - support DMAC and EMAC blocks of Gigabit-capable IP found on RZ/G2L SoC - Intel 100G Ethernet - support for eswitch offload of TC/OvS flow API, including offload of GRE, VxLAN, Geneve tunneling - support application device queues - ability to assign Rx and Tx queues to application threads - PTP and PPS (pulse-per-second) extensions - Broadcom Ethernet (bnxt) - devlink health reporting and device reload extensions - Mellanox Ethernet (mlx5) - offload macvlan interfaces - support HW offload of TC rules involving OVS internal ports - support HW-GRO and header/data split - support application device queues - Marvell OcteonTx2: - add XDP support for PF - add PTP support for VF - Qualcomm Ethernet switch (qca8k): support for QCA8328 - Realtek Ethernet DSA switch (rtl8366rb) - support bridge offload - support STP, fast aging, disabling address learning - support for Realtek RTL8365MB-VC, a 4+1 port 10M/100M/1GE switch - Mellanox Ethernet/IB switch (mlxsw) - multi-level qdisc hierarchy offload (e.g. RED, prio and shaping) - offload root TBF qdisc as port shaper - support multiple routing interface MAC address prefixes - support for IP-in-IP with IPv6 underlay - MediaTek WiFi (mt76) - mt7921 - ASPM, 6GHz, SDIO and testmode support - mt7915 - LED and TWT support - Qualcomm WiFi (ath11k) - include channel rx and tx time in survey dump statistics - support for 80P80 and 160 MHz bandwidths - support channel 2 in 6 GHz band - spectral scan support for QCN9074 - support for rx decapsulation offload (data frames in 802.3 format) - Qualcomm phone SoC WiFi (wcn36xx) - enable Idle Mode Power Save (IMPS) to reduce power consumption during idle - Bluetooth driver support for MediaTek MT7922 and MT7921 - Enable support for AOSP Bluetooth extension in Qualcomm WCN399x and Realtek 8822C/8852A - Microsoft vNIC driver (mana) - support hibernation and kexec - Google vNIC driver (gve) - support for jumbo frames - implement Rx page reuse Refactor: - Make all writes to netdev->dev_addr go thru helpers, so that we can add this address to the address rbtree and handle the updates - Various TCP cleanups and optimizations including improvements to CPU cache use - Simplify the gnet_stats, Qdisc stats' handling and remove qdisc->running sequence counter - Driver changes and API updates to address devlink locking deficiencies Signed-off-by: Jakub Kicinski <kuba@kernel.org> -----BEGIN PGP SIGNATURE----- iQIzBAABCAAdFiEE6jPA+I1ugmIBA4hXMUZtbf5SIrsFAmGAzX4ACgkQMUZtbf5S IrvW3g//Q0ZLrOuHK9pZ8sCXMMhDj8qL6ajm0otMddHWA/+1UglwVBKFhsajfxOf wJ/5LZis+XKLpLqKTU5chKVfn39HuDGe/D3l+egi01Gv5BW0+XzEhagfyR5tJX5z wsGG5CXO/we/laVSzRiFtwwVEKHKN20YC+tIQwYOYP5Wy3q4G7qDsFhT7GqgsGCS n74QUEAIB5Tz0ODWFqLtbsySzIurXrskibwt5T9bvAAlPw/lCU68mmG+NVJ7VddO lBbNkLMOo8yW9Ci20H09SrYd4jZTmMARo9tsFO1tAvAMk7qpn0Wd8pnOYTjFFoMD +qjiFSVMh7E0JGb8Y7NCvwaB99suAK5rfGP68Xwe62DfP7vYWEx4pZGxBP19F4ld 6Kn1ME33BX9rUF9tBecf0bdKfJUwB2Q2Xou/b9laG04bwiqsc9iG5FQq1C46lnLZ QdzNiS1My4dJMczkWt66HF3Kx30ibwHfvKMIHjf4PqkzEatkv6Y6SBZ57KXL+Lde 0BQSFhbf0tm2Gf55etzrczLElI3uqHSFWUNZZ2Bt6WmzO1e6tpV9nAtRWF4C/dFg QDpLJtOOOY65uq+qz09zoPfv2lem868SrCAuFrVn99bEpYjx/CGNFDeEI02l6jyr 84eUxd364UcbIk3fc+eTGdXHLQNVk30G0AHVBBxaWNIidwfqXeE= =srde -----END PGP SIGNATURE----- Merge tag 'net-next-for-5.16' of git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-next Pull networking updates from Jakub Kicinski: "Core: - Remove socket skb caches - Add a SO_RESERVE_MEM socket op to forward allocate buffer space and avoid memory accounting overhead on each message sent - Introduce managed neighbor entries - added by control plane and resolved by the kernel for use in acceleration paths (BPF / XDP right now, HW offload users will benefit as well) - Make neighbor eviction on link down controllable by userspace to work around WiFi networks with bad roaming implementations - vrf: Rework interaction with netfilter/conntrack - fq_codel: implement L4S style ce_threshold_ect1 marking - sch: Eliminate unnecessary RCU waits in mini_qdisc_pair_swap() BPF: - Add support for new btf kind BTF_KIND_TAG, arbitrary type tagging as implemented in LLVM14 - Introduce bpf_get_branch_snapshot() to capture Last Branch Records - Implement variadic trace_printk helper - Add a new Bloomfilter map type - Track <8-byte scalar spill and refill - Access hw timestamp through BPF's __sk_buff - Disallow unprivileged BPF by default - Document BPF licensing Netfilter: - Introduce egress hook for looking at raw outgoing packets - Allow matching on and modifying inner headers / payload data - Add NFT_META_IFTYPE to match on the interface type either from ingress or egress Protocols: - Multi-Path TCP: - increase default max additional subflows to 2 - rework forward memory allocation - add getsockopts: MPTCP_INFO, MPTCP_TCPINFO, MPTCP_SUBFLOW_ADDRS - MCTP flow support allowing lower layer drivers to configure msg muxing as needed - Automatic Multicast Tunneling (AMT) driver based on RFC7450 - HSR support the redbox supervision frames (IEC-62439-3:2018) - Support for the ip6ip6 encapsulation of IOAM - Netlink interface for CAN-FD's Transmitter Delay Compensation - Support SMC-Rv2 eliminating the current same-subnet restriction, by exploiting the UDP encapsulation feature of RoCE adapters - TLS: add SM4 GCM/CCM crypto support - Bluetooth: initial support for link quality and audio/codec offload Driver APIs: - Add a batched interface for RX buffer allocation in AF_XDP buffer pool - ethtool: Add ability to control transceiver modules' power mode - phy: Introduce supported interfaces bitmap to express MAC capabilities and simplify PHY code - Drop rtnl_lock from DSA .port_fdb_{add,del} callbacks New drivers: - WiFi driver for Realtek 8852AE 802.11ax devices (rtw89) - Ethernet driver for ASIX AX88796C SPI device (x88796c) Drivers: - Broadcom PHYs - support 72165, 7712 16nm PHYs - support IDDQ-SR for additional power savings - PHY support for QCA8081, QCA9561 PHYs - NXP DPAA2: support for IRQ coalescing - NXP Ethernet (enetc): support for software TCP segmentation - Renesas Ethernet (ravb) - support DMAC and EMAC blocks of Gigabit-capable IP found on RZ/G2L SoC - Intel 100G Ethernet - support for eswitch offload of TC/OvS flow API, including offload of GRE, VxLAN, Geneve tunneling - support application device queues - ability to assign Rx and Tx queues to application threads - PTP and PPS (pulse-per-second) extensions - Broadcom Ethernet (bnxt) - devlink health reporting and device reload extensions - Mellanox Ethernet (mlx5) - offload macvlan interfaces - support HW offload of TC rules involving OVS internal ports - support HW-GRO and header/data split - support application device queues - Marvell OcteonTx2: - add XDP support for PF - add PTP support for VF - Qualcomm Ethernet switch (qca8k): support for QCA8328 - Realtek Ethernet DSA switch (rtl8366rb) - support bridge offload - support STP, fast aging, disabling address learning - support for Realtek RTL8365MB-VC, a 4+1 port 10M/100M/1GE switch - Mellanox Ethernet/IB switch (mlxsw) - multi-level qdisc hierarchy offload (e.g. RED, prio and shaping) - offload root TBF qdisc as port shaper - support multiple routing interface MAC address prefixes - support for IP-in-IP with IPv6 underlay - MediaTek WiFi (mt76) - mt7921 - ASPM, 6GHz, SDIO and testmode support - mt7915 - LED and TWT support - Qualcomm WiFi (ath11k) - include channel rx and tx time in survey dump statistics - support for 80P80 and 160 MHz bandwidths - support channel 2 in 6 GHz band - spectral scan support for QCN9074 - support for rx decapsulation offload (data frames in 802.3 format) - Qualcomm phone SoC WiFi (wcn36xx) - enable Idle Mode Power Save (IMPS) to reduce power consumption during idle - Bluetooth driver support for MediaTek MT7922 and MT7921 - Enable support for AOSP Bluetooth extension in Qualcomm WCN399x and Realtek 8822C/8852A - Microsoft vNIC driver (mana) - support hibernation and kexec - Google vNIC driver (gve) - support for jumbo frames - implement Rx page reuse Refactor: - Make all writes to netdev->dev_addr go thru helpers, so that we can add this address to the address rbtree and handle the updates - Various TCP cleanups and optimizations including improvements to CPU cache use - Simplify the gnet_stats, Qdisc stats' handling and remove qdisc->running sequence counter - Driver changes and API updates to address devlink locking deficiencies" * tag 'net-next-for-5.16' of git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-next: (2122 commits) Revert "net: avoid double accounting for pure zerocopy skbs" selftests: net: add arp_ndisc_evict_nocarrier net: ndisc: introduce ndisc_evict_nocarrier sysctl parameter net: arp: introduce arp_evict_nocarrier sysctl parameter libbpf: Deprecate AF_XDP support kbuild: Unify options for BTF generation for vmlinux and modules selftests/bpf: Add a testcase for 64-bit bounds propagation issue. bpf: Fix propagation of signed bounds from 64-bit min/max into 32-bit. bpf: Fix propagation of bounds from 64-bit min/max into 32-bit and var_off. net: vmxnet3: remove multiple false checks in vmxnet3_ethtool.c net: avoid double accounting for pure zerocopy skbs tcp: rename sk_wmem_free_skb netdevsim: fix uninit value in nsim_drv_configure_vfs() selftests/bpf: Fix also no-alu32 strobemeta selftest bpf: Add missing map_delete_elem method to bloom filter map selftests/bpf: Add bloom map success test for userspace calls bpf: Add alignment padding for "map_extra" + consolidate holes bpf: Bloom filter map naming fixups selftests/bpf: Add test cases for struct_ops prog bpf: Add dummy BPF STRUCT_OPS for test purpose ...
This commit is contained in:
commit
fc02cb2b37
174
Documentation/ABI/testing/sysfs-timecard
Normal file
174
Documentation/ABI/testing/sysfs-timecard
Normal file
@ -0,0 +1,174 @@
|
|||||||
|
What: /sys/class/timecard/
|
||||||
|
Date: September 2021
|
||||||
|
Contact: Jonathan Lemon <jonathan.lemon@gmail.com>
|
||||||
|
Description: This directory contains files and directories
|
||||||
|
providing a standardized interface to the ancillary
|
||||||
|
features of the OpenCompute timecard.
|
||||||
|
|
||||||
|
What: /sys/class/timecard/ocpN/
|
||||||
|
Date: September 2021
|
||||||
|
Contact: Jonathan Lemon <jonathan.lemon@gmail.com>
|
||||||
|
Description: This directory contains the attributes of the Nth timecard
|
||||||
|
registered.
|
||||||
|
|
||||||
|
What: /sys/class/timecard/ocpN/available_clock_sources
|
||||||
|
Date: September 2021
|
||||||
|
Contact: Jonathan Lemon <jonathan.lemon@gmail.com>
|
||||||
|
Description: (RO) The list of available time sources that the PHC
|
||||||
|
uses for clock adjustments.
|
||||||
|
|
||||||
|
==== =================================================
|
||||||
|
NONE no adjustments
|
||||||
|
PPS adjustments come from the PPS1 selector (default)
|
||||||
|
TOD adjustments from the GNSS/TOD module
|
||||||
|
IRIG adjustments from external IRIG-B signal
|
||||||
|
DCF adjustments from external DCF signal
|
||||||
|
==== =================================================
|
||||||
|
|
||||||
|
What: /sys/class/timecard/ocpN/available_sma_inputs
|
||||||
|
Date: September 2021
|
||||||
|
Contact: Jonathan Lemon <jonathan.lemon@gmail.com>
|
||||||
|
Description: (RO) Set of available destinations (sinks) for a SMA
|
||||||
|
input signal.
|
||||||
|
|
||||||
|
===== ================================================
|
||||||
|
10Mhz signal is used as the 10Mhz reference clock
|
||||||
|
PPS1 signal is sent to the PPS1 selector
|
||||||
|
PPS2 signal is sent to the PPS2 selector
|
||||||
|
TS1 signal is sent to timestamper 1
|
||||||
|
TS2 signal is sent to timestamper 2
|
||||||
|
IRIG signal is sent to the IRIG-B module
|
||||||
|
DCF signal is sent to the DCF module
|
||||||
|
===== ================================================
|
||||||
|
|
||||||
|
What: /sys/class/timecard/ocpN/available_sma_outputs
|
||||||
|
Date: May 2021
|
||||||
|
Contact: Jonathan Lemon <jonathan.lemon@gmail.com>
|
||||||
|
Description: (RO) Set of available sources for a SMA output signal.
|
||||||
|
|
||||||
|
===== ================================================
|
||||||
|
10Mhz output is from the 10Mhz reference clock
|
||||||
|
PHC output PPS is from the PHC clock
|
||||||
|
MAC output PPS is from the Miniature Atomic Clock
|
||||||
|
GNSS output PPS is from the GNSS module
|
||||||
|
GNSS2 output PPS is from the second GNSS module
|
||||||
|
IRIG output is from the PHC, in IRIG-B format
|
||||||
|
DCF output is from the PHC, in DCF format
|
||||||
|
===== ================================================
|
||||||
|
|
||||||
|
What: /sys/class/timecard/ocpN/clock_source
|
||||||
|
Date: September 2021
|
||||||
|
Contact: Jonathan Lemon <jonathan.lemon@gmail.com>
|
||||||
|
Description: (RW) Contains the current synchronization source used by
|
||||||
|
the PHC. May be changed by writing one of the listed
|
||||||
|
values from the available_clock_sources attribute set.
|
||||||
|
|
||||||
|
What: /sys/class/timecard/ocpN/gnss_sync
|
||||||
|
Date: September 2021
|
||||||
|
Contact: Jonathan Lemon <jonathan.lemon@gmail.com>
|
||||||
|
Description: (RO) Indicates whether a valid GNSS signal is received,
|
||||||
|
or when the signal was lost.
|
||||||
|
|
||||||
|
What: /sys/class/timecard/ocpN/i2c
|
||||||
|
Date: September 2021
|
||||||
|
Contact: Jonathan Lemon <jonathan.lemon@gmail.com>
|
||||||
|
Description: This optional attribute links to the associated i2c device.
|
||||||
|
|
||||||
|
What: /sys/class/timecard/ocpN/irig_b_mode
|
||||||
|
Date: September 2021
|
||||||
|
Contact: Jonathan Lemon <jonathan.lemon@gmail.com>
|
||||||
|
Description: (RW) An integer from 0-7 indicating the timecode format
|
||||||
|
of the IRIG-B output signal: B00<n>
|
||||||
|
|
||||||
|
What: /sys/class/timecard/ocpN/pps
|
||||||
|
Date: September 2021
|
||||||
|
Contact: Jonathan Lemon <jonathan.lemon@gmail.com>
|
||||||
|
Description: This optional attribute links to the associated PPS device.
|
||||||
|
|
||||||
|
What: /sys/class/timecard/ocpN/ptp
|
||||||
|
Date: September 2021
|
||||||
|
Contact: Jonathan Lemon <jonathan.lemon@gmail.com>
|
||||||
|
Description: This attribute links to the associated PTP device.
|
||||||
|
|
||||||
|
What: /sys/class/timecard/ocpN/serialnum
|
||||||
|
Date: September 2021
|
||||||
|
Contact: Jonathan Lemon <jonathan.lemon@gmail.com>
|
||||||
|
Description: (RO) Provides the serial number of the timecard.
|
||||||
|
|
||||||
|
What: /sys/class/timecard/ocpN/sma1
|
||||||
|
What: /sys/class/timecard/ocpN/sma2
|
||||||
|
What: /sys/class/timecard/ocpN/sma3
|
||||||
|
What: /sys/class/timecard/ocpN/sma4
|
||||||
|
Date: September 2021
|
||||||
|
Contact: Jonathan Lemon <jonathan.lemon@gmail.com>
|
||||||
|
Description: (RW) These attributes specify the direction of the signal
|
||||||
|
on the associated SMA connectors, and also the signal sink
|
||||||
|
or source.
|
||||||
|
|
||||||
|
The display format of the attribute is a space separated
|
||||||
|
list of signals, prefixed by the input/output direction.
|
||||||
|
|
||||||
|
The signal direction may be changed (if supported) by
|
||||||
|
prefixing the signal list with either "in:" or "out:".
|
||||||
|
If neither prefix is present, then the direction is unchanged.
|
||||||
|
|
||||||
|
The output signal may be changed by writing one of the listed
|
||||||
|
values from the available_sma_outputs attribute set.
|
||||||
|
|
||||||
|
The input destinations may be changed by writing multiple
|
||||||
|
values from the available_sma_inputs attribute set,
|
||||||
|
separated by spaces. If there are duplicated input
|
||||||
|
destinations between connectors, the lowest numbered SMA
|
||||||
|
connector is given priority.
|
||||||
|
|
||||||
|
Note that not all input combinations may make sense.
|
||||||
|
|
||||||
|
The 10Mhz reference clock input is currently only valid
|
||||||
|
on SMA1 and may not be combined with other destination sinks.
|
||||||
|
|
||||||
|
What: /sys/class/timecard/ocpN/ts_window_adjust
|
||||||
|
Date: September 2021
|
||||||
|
Contact: Jonathan Lemon <jonathan.lemon@gmail.com>
|
||||||
|
Description: (RW) When retrieving the PHC with the PTP SYS_OFFSET_EXTENDED
|
||||||
|
ioctl, a system timestamp is made before and after the PHC
|
||||||
|
time is retrieved. The midpoint between the two system
|
||||||
|
timestamps is usually taken to be the SYS time associated
|
||||||
|
with the PHC time. This estimate may be wrong, as it depends
|
||||||
|
on PCI latencies, and when the PHC time was latched
|
||||||
|
|
||||||
|
The attribute value reduces the end timestamp by the given
|
||||||
|
number of nanoseconds, so the computed midpoint matches the
|
||||||
|
retrieved PHC time.
|
||||||
|
|
||||||
|
The initial value is set based on measured PCI latency and
|
||||||
|
the estimated point where the FPGA latches the PHC time. This
|
||||||
|
value may be changed by writing an unsigned integer.
|
||||||
|
|
||||||
|
What: /sys/class/timecard/ocpN/ttyGNSS
|
||||||
|
What: /sys/class/timecard/ocpN/ttyGNSS2
|
||||||
|
Date: September 2021
|
||||||
|
Contact: Jonathan Lemon <jonathan.lemon@gmail.com>
|
||||||
|
Description: These optional attributes link to the TTY serial ports
|
||||||
|
associated with the GNSS devices.
|
||||||
|
|
||||||
|
What: /sys/class/timecard/ocpN/ttyMAC
|
||||||
|
Date: September 2021
|
||||||
|
Contact: Jonathan Lemon <jonathan.lemon@gmail.com>
|
||||||
|
Description: This optional attribute links to the TTY serial port
|
||||||
|
associated with the Miniature Atomic Clock.
|
||||||
|
|
||||||
|
What: /sys/class/timecard/ocpN/ttyNMEA
|
||||||
|
Date: September 2021
|
||||||
|
Contact: Jonathan Lemon <jonathan.lemon@gmail.com>
|
||||||
|
Description: This optional attribute links to the TTY serial port
|
||||||
|
which outputs the PHC time in NMEA ZDA format.
|
||||||
|
|
||||||
|
What: /sys/class/timecard/ocpN/utc_tai_offset
|
||||||
|
Date: September 2021
|
||||||
|
Contact: Jonathan Lemon <jonathan.lemon@gmail.com>
|
||||||
|
Description: (RW) The DCF and IRIG output signals are in UTC, while the
|
||||||
|
TimeCard operates on TAI. This attribute allows setting the
|
||||||
|
offset in seconds, which is added to the TAI timebase for
|
||||||
|
these formats.
|
||||||
|
|
||||||
|
The offset may be changed by writing an unsigned integer.
|
92
Documentation/bpf/bpf_licensing.rst
Normal file
92
Documentation/bpf/bpf_licensing.rst
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
=============
|
||||||
|
BPF licensing
|
||||||
|
=============
|
||||||
|
|
||||||
|
Background
|
||||||
|
==========
|
||||||
|
|
||||||
|
* Classic BPF was BSD licensed
|
||||||
|
|
||||||
|
"BPF" was originally introduced as BSD Packet Filter in
|
||||||
|
http://www.tcpdump.org/papers/bpf-usenix93.pdf. The corresponding instruction
|
||||||
|
set and its implementation came from BSD with BSD license. That original
|
||||||
|
instruction set is now known as "classic BPF".
|
||||||
|
|
||||||
|
However an instruction set is a specification for machine-language interaction,
|
||||||
|
similar to a programming language. It is not a code. Therefore, the
|
||||||
|
application of a BSD license may be misleading in a certain context, as the
|
||||||
|
instruction set may enjoy no copyright protection.
|
||||||
|
|
||||||
|
* eBPF (extended BPF) instruction set continues to be BSD
|
||||||
|
|
||||||
|
In 2014, the classic BPF instruction set was significantly extended. We
|
||||||
|
typically refer to this instruction set as eBPF to disambiguate it from cBPF.
|
||||||
|
The eBPF instruction set is still BSD licensed.
|
||||||
|
|
||||||
|
Implementations of eBPF
|
||||||
|
=======================
|
||||||
|
|
||||||
|
Using the eBPF instruction set requires implementing code in both kernel space
|
||||||
|
and user space.
|
||||||
|
|
||||||
|
In Linux Kernel
|
||||||
|
---------------
|
||||||
|
|
||||||
|
The reference implementations of the eBPF interpreter and various just-in-time
|
||||||
|
compilers are part of Linux and are GPLv2 licensed. The implementation of
|
||||||
|
eBPF helper functions is also GPLv2 licensed. Interpreters, JITs, helpers,
|
||||||
|
and verifiers are called eBPF runtime.
|
||||||
|
|
||||||
|
In User Space
|
||||||
|
-------------
|
||||||
|
|
||||||
|
There are also implementations of eBPF runtime (interpreter, JITs, helper
|
||||||
|
functions) under
|
||||||
|
Apache2 (https://github.com/iovisor/ubpf),
|
||||||
|
MIT (https://github.com/qmonnet/rbpf), and
|
||||||
|
BSD (https://github.com/DPDK/dpdk/blob/main/lib/librte_bpf).
|
||||||
|
|
||||||
|
In HW
|
||||||
|
-----
|
||||||
|
|
||||||
|
The HW can choose to execute eBPF instruction natively and provide eBPF runtime
|
||||||
|
in HW or via the use of implementing firmware with a proprietary license.
|
||||||
|
|
||||||
|
In other operating systems
|
||||||
|
--------------------------
|
||||||
|
|
||||||
|
Other kernels or user space implementations of eBPF instruction set and runtime
|
||||||
|
can have proprietary licenses.
|
||||||
|
|
||||||
|
Using BPF programs in the Linux kernel
|
||||||
|
======================================
|
||||||
|
|
||||||
|
Linux Kernel (while being GPLv2) allows linking of proprietary kernel modules
|
||||||
|
under these rules:
|
||||||
|
Documentation/process/license-rules.rst
|
||||||
|
|
||||||
|
When a kernel module is loaded, the linux kernel checks which functions it
|
||||||
|
intends to use. If any function is marked as "GPL only," the corresponding
|
||||||
|
module or program has to have GPL compatible license.
|
||||||
|
|
||||||
|
Loading BPF program into the Linux kernel is similar to loading a kernel
|
||||||
|
module. BPF is loaded at run time and not statically linked to the Linux
|
||||||
|
kernel. BPF program loading follows the same license checking rules as kernel
|
||||||
|
modules. BPF programs can be proprietary if they don't use "GPL only" BPF
|
||||||
|
helper functions.
|
||||||
|
|
||||||
|
Further, some BPF program types - Linux Security Modules (LSM) and TCP
|
||||||
|
Congestion Control (struct_ops), as of Aug 2021 - are required to be GPL
|
||||||
|
compatible even if they don't use "GPL only" helper functions directly. The
|
||||||
|
registration step of LSM and TCP congestion control modules of the Linux
|
||||||
|
kernel is done through EXPORT_SYMBOL_GPL kernel functions. In that sense LSM
|
||||||
|
and struct_ops BPF programs are implicitly calling "GPL only" functions.
|
||||||
|
The same restriction applies to BPF programs that call kernel functions
|
||||||
|
directly via unstable interface also known as "kfunc".
|
||||||
|
|
||||||
|
Packaging BPF programs with user space applications
|
||||||
|
====================================================
|
||||||
|
|
||||||
|
Generally, proprietary-licensed applications and GPL licensed BPF programs
|
||||||
|
written for the Linux kernel in the same package can co-exist because they are
|
||||||
|
separate executable processes. This applies to both cBPF and eBPF programs.
|
@ -85,6 +85,7 @@ sequentially and type id is assigned to each recognized type starting from id
|
|||||||
#define BTF_KIND_VAR 14 /* Variable */
|
#define BTF_KIND_VAR 14 /* Variable */
|
||||||
#define BTF_KIND_DATASEC 15 /* Section */
|
#define BTF_KIND_DATASEC 15 /* Section */
|
||||||
#define BTF_KIND_FLOAT 16 /* Floating point */
|
#define BTF_KIND_FLOAT 16 /* Floating point */
|
||||||
|
#define BTF_KIND_DECL_TAG 17 /* Decl Tag */
|
||||||
|
|
||||||
Note that the type section encodes debug info, not just pure types.
|
Note that the type section encodes debug info, not just pure types.
|
||||||
``BTF_KIND_FUNC`` is not a type, and it represents a defined subprogram.
|
``BTF_KIND_FUNC`` is not a type, and it represents a defined subprogram.
|
||||||
@ -106,7 +107,7 @@ Each type contains the following common data::
|
|||||||
* "size" tells the size of the type it is describing.
|
* "size" tells the size of the type it is describing.
|
||||||
*
|
*
|
||||||
* "type" is used by PTR, TYPEDEF, VOLATILE, CONST, RESTRICT,
|
* "type" is used by PTR, TYPEDEF, VOLATILE, CONST, RESTRICT,
|
||||||
* FUNC and FUNC_PROTO.
|
* FUNC, FUNC_PROTO and DECL_TAG.
|
||||||
* "type" is a type_id referring to another type.
|
* "type" is a type_id referring to another type.
|
||||||
*/
|
*/
|
||||||
union {
|
union {
|
||||||
@ -465,6 +466,32 @@ map definition.
|
|||||||
|
|
||||||
No additional type data follow ``btf_type``.
|
No additional type data follow ``btf_type``.
|
||||||
|
|
||||||
|
2.2.17 BTF_KIND_DECL_TAG
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
``struct btf_type`` encoding requirement:
|
||||||
|
* ``name_off``: offset to a non-empty string
|
||||||
|
* ``info.kind_flag``: 0
|
||||||
|
* ``info.kind``: BTF_KIND_DECL_TAG
|
||||||
|
* ``info.vlen``: 0
|
||||||
|
* ``type``: ``struct``, ``union``, ``func``, ``var`` or ``typedef``
|
||||||
|
|
||||||
|
``btf_type`` is followed by ``struct btf_decl_tag``.::
|
||||||
|
|
||||||
|
struct btf_decl_tag {
|
||||||
|
__u32 component_idx;
|
||||||
|
};
|
||||||
|
|
||||||
|
The ``name_off`` encodes btf_decl_tag attribute string.
|
||||||
|
The ``type`` should be ``struct``, ``union``, ``func``, ``var`` or ``typedef``.
|
||||||
|
For ``var`` or ``typedef`` type, ``btf_decl_tag.component_idx`` must be ``-1``.
|
||||||
|
For the other three types, if the btf_decl_tag attribute is
|
||||||
|
applied to the ``struct``, ``union`` or ``func`` itself,
|
||||||
|
``btf_decl_tag.component_idx`` must be ``-1``. Otherwise,
|
||||||
|
the attribute is applied to a ``struct``/``union`` member or
|
||||||
|
a ``func`` argument, and ``btf_decl_tag.component_idx`` should be a
|
||||||
|
valid index (starting from 0) pointing to a member or an argument.
|
||||||
|
|
||||||
3. BTF Kernel API
|
3. BTF Kernel API
|
||||||
*****************
|
*****************
|
||||||
|
|
||||||
|
@ -82,6 +82,15 @@ Testing and debugging BPF
|
|||||||
s390
|
s390
|
||||||
|
|
||||||
|
|
||||||
|
Licensing
|
||||||
|
=========
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:maxdepth: 1
|
||||||
|
|
||||||
|
bpf_licensing
|
||||||
|
|
||||||
|
|
||||||
Other
|
Other
|
||||||
=====
|
=====
|
||||||
|
|
||||||
|
@ -150,6 +150,46 @@ mirror of the mainline's version of libbpf for a stand-alone build.
|
|||||||
However, all changes to libbpf's code base must be upstreamed through
|
However, all changes to libbpf's code base must be upstreamed through
|
||||||
the mainline kernel tree.
|
the mainline kernel tree.
|
||||||
|
|
||||||
|
|
||||||
|
API documentation convention
|
||||||
|
============================
|
||||||
|
|
||||||
|
The libbpf API is documented via comments above definitions in
|
||||||
|
header files. These comments can be rendered by doxygen and sphinx
|
||||||
|
for well organized html output. This section describes the
|
||||||
|
convention in which these comments should be formated.
|
||||||
|
|
||||||
|
Here is an example from btf.h:
|
||||||
|
|
||||||
|
.. code-block:: c
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief **btf__new()** creates a new instance of a BTF object from the raw
|
||||||
|
* bytes of an ELF's BTF section
|
||||||
|
* @param data raw bytes
|
||||||
|
* @param size number of bytes passed in `data`
|
||||||
|
* @return new BTF object instance which has to be eventually freed with
|
||||||
|
* **btf__free()**
|
||||||
|
*
|
||||||
|
* On error, error-code-encoded-as-pointer is returned, not a NULL. To extract
|
||||||
|
* error code from such a pointer `libbpf_get_error()` should be used. If
|
||||||
|
* `libbpf_set_strict_mode(LIBBPF_STRICT_CLEAN_PTRS)` is enabled, NULL is
|
||||||
|
* returned on error instead. In both cases thread-local `errno` variable is
|
||||||
|
* always set to error code as well.
|
||||||
|
*/
|
||||||
|
|
||||||
|
The comment must start with a block comment of the form '/\*\*'.
|
||||||
|
|
||||||
|
The documentation always starts with a @brief directive. This line is a short
|
||||||
|
description about this API. It starts with the name of the API, denoted in bold
|
||||||
|
like so: **api_name**. Please include an open and close parenthesis if this is a
|
||||||
|
function. Follow with the short description of the API. A longer form description
|
||||||
|
can be added below the last directive, at the bottom of the comment.
|
||||||
|
|
||||||
|
Parameters are denoted with the @param directive, there should be one for each
|
||||||
|
parameter. If this is a function with a non-void return, use the @return directive
|
||||||
|
to document it.
|
||||||
|
|
||||||
License
|
License
|
||||||
-------------------
|
-------------------
|
||||||
|
|
||||||
|
73
Documentation/devicetree/bindings/net/asix,ax88796c.yaml
Normal file
73
Documentation/devicetree/bindings/net/asix,ax88796c.yaml
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
|
||||||
|
%YAML 1.2
|
||||||
|
---
|
||||||
|
$id: http://devicetree.org/schemas/net/asix,ax88796c.yaml#
|
||||||
|
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||||
|
|
||||||
|
title: ASIX AX88796C SPI Ethernet Adapter
|
||||||
|
|
||||||
|
maintainers:
|
||||||
|
- Łukasz Stelmach <l.stelmach@samsung.com>
|
||||||
|
|
||||||
|
description: |
|
||||||
|
ASIX AX88796C is an Ethernet controller with a built in PHY. This
|
||||||
|
describes SPI mode of the chip.
|
||||||
|
|
||||||
|
The node for this driver must be a child node of an SPI controller,
|
||||||
|
hence all mandatory properties described in
|
||||||
|
../spi/spi-controller.yaml must be specified.
|
||||||
|
|
||||||
|
allOf:
|
||||||
|
- $ref: ethernet-controller.yaml#
|
||||||
|
|
||||||
|
properties:
|
||||||
|
compatible:
|
||||||
|
const: asix,ax88796c
|
||||||
|
|
||||||
|
reg:
|
||||||
|
maxItems: 1
|
||||||
|
|
||||||
|
spi-max-frequency:
|
||||||
|
maximum: 40000000
|
||||||
|
|
||||||
|
interrupts:
|
||||||
|
maxItems: 1
|
||||||
|
|
||||||
|
reset-gpios:
|
||||||
|
description:
|
||||||
|
A GPIO line handling reset of the chip. As the line is active low,
|
||||||
|
it should be marked GPIO_ACTIVE_LOW.
|
||||||
|
maxItems: 1
|
||||||
|
|
||||||
|
local-mac-address: true
|
||||||
|
|
||||||
|
mac-address: true
|
||||||
|
|
||||||
|
required:
|
||||||
|
- compatible
|
||||||
|
- reg
|
||||||
|
- spi-max-frequency
|
||||||
|
- interrupts
|
||||||
|
- reset-gpios
|
||||||
|
|
||||||
|
additionalProperties: false
|
||||||
|
|
||||||
|
examples:
|
||||||
|
# Artik5 eval board
|
||||||
|
- |
|
||||||
|
#include <dt-bindings/interrupt-controller/irq.h>
|
||||||
|
#include <dt-bindings/gpio/gpio.h>
|
||||||
|
spi0 {
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <0>;
|
||||||
|
|
||||||
|
ethernet@0 {
|
||||||
|
compatible = "asix,ax88796c";
|
||||||
|
reg = <0x0>;
|
||||||
|
local-mac-address = [00 00 00 00 00 00]; /* Filled in by a bootloader */
|
||||||
|
interrupt-parent = <&gpx2>;
|
||||||
|
interrupts = <0 IRQ_TYPE_LEVEL_LOW>;
|
||||||
|
spi-max-frequency = <40000000>;
|
||||||
|
reset-gpios = <&gpe0 2 GPIO_ACTIVE_LOW>;
|
||||||
|
};
|
||||||
|
};
|
@ -2,7 +2,8 @@
|
|||||||
|
|
||||||
Required properties:
|
Required properties:
|
||||||
- compatible: should contain one of "brcm,genet-v1", "brcm,genet-v2",
|
- compatible: should contain one of "brcm,genet-v1", "brcm,genet-v2",
|
||||||
"brcm,genet-v3", "brcm,genet-v4", "brcm,genet-v5", "brcm,bcm2711-genet-v5".
|
"brcm,genet-v3", "brcm,genet-v4", "brcm,genet-v5", "brcm,bcm2711-genet-v5" or
|
||||||
|
"brcm,bcm7712-genet-v5".
|
||||||
- reg: address and length of the register set for the device
|
- reg: address and length of the register set for the device
|
||||||
- interrupts and/or interrupts-extended: must be two cells, the first cell
|
- interrupts and/or interrupts-extended: must be two cells, the first cell
|
||||||
is the general purpose interrupt line, while the second cell is the
|
is the general purpose interrupt line, while the second cell is the
|
||||||
|
@ -46,6 +46,9 @@ patternProperties:
|
|||||||
type: object
|
type: object
|
||||||
description: Ethernet switch ports
|
description: Ethernet switch ports
|
||||||
|
|
||||||
|
allOf:
|
||||||
|
- $ref: "http://devicetree.org/schemas/net/ethernet-controller.yaml#"
|
||||||
|
|
||||||
properties:
|
properties:
|
||||||
reg:
|
reg:
|
||||||
description: Port number
|
description: Port number
|
||||||
@ -73,11 +76,14 @@ patternProperties:
|
|||||||
dsa-tag-protocol:
|
dsa-tag-protocol:
|
||||||
description:
|
description:
|
||||||
Instead of the default, the switch will use this tag protocol if
|
Instead of the default, the switch will use this tag protocol if
|
||||||
possible. Useful when a device supports multiple protcols and
|
possible. Useful when a device supports multiple protocols and
|
||||||
the default is incompatible with the Ethernet device.
|
the default is incompatible with the Ethernet device.
|
||||||
enum:
|
enum:
|
||||||
- dsa
|
- dsa
|
||||||
- edsa
|
- edsa
|
||||||
|
- ocelot
|
||||||
|
- ocelot-8021q
|
||||||
|
- seville
|
||||||
|
|
||||||
phy-handle: true
|
phy-handle: true
|
||||||
|
|
||||||
@ -91,6 +97,10 @@ patternProperties:
|
|||||||
|
|
||||||
managed: true
|
managed: true
|
||||||
|
|
||||||
|
rx-internal-delay-ps: true
|
||||||
|
|
||||||
|
tx-internal-delay-ps: true
|
||||||
|
|
||||||
required:
|
required:
|
||||||
- reg
|
- reg
|
||||||
|
|
||||||
|
@ -74,10 +74,42 @@ properties:
|
|||||||
- compatible
|
- compatible
|
||||||
- reg
|
- reg
|
||||||
|
|
||||||
|
patternProperties:
|
||||||
|
"^(ethernet-)?ports$":
|
||||||
|
patternProperties:
|
||||||
|
"^(ethernet-)?port@[0-9]+$":
|
||||||
|
allOf:
|
||||||
|
- if:
|
||||||
|
properties:
|
||||||
|
phy-mode:
|
||||||
|
contains:
|
||||||
|
enum:
|
||||||
|
- rgmii
|
||||||
|
- rgmii-rxid
|
||||||
|
- rgmii-txid
|
||||||
|
- rgmii-id
|
||||||
|
then:
|
||||||
|
properties:
|
||||||
|
rx-internal-delay-ps:
|
||||||
|
$ref: "#/$defs/internal-delay-ps"
|
||||||
|
tx-internal-delay-ps:
|
||||||
|
$ref: "#/$defs/internal-delay-ps"
|
||||||
|
|
||||||
required:
|
required:
|
||||||
- compatible
|
- compatible
|
||||||
- reg
|
- reg
|
||||||
|
|
||||||
|
$defs:
|
||||||
|
internal-delay-ps:
|
||||||
|
description:
|
||||||
|
Disable tunable delay lines using 0 ps, or enable them and select
|
||||||
|
the phase between 1640 ps (73.8 degree shift at 1Gbps) and 2260 ps
|
||||||
|
(101.7 degree shift) in increments of 0.9 degrees (20 ps).
|
||||||
|
enum:
|
||||||
|
[0, 1640, 1660, 1680, 1700, 1720, 1740, 1760, 1780, 1800, 1820, 1840,
|
||||||
|
1860, 1880, 1900, 1920, 1940, 1960, 1980, 2000, 2020, 2040, 2060, 2080,
|
||||||
|
2100, 2120, 2140, 2160, 2180, 2200, 2220, 2240, 2260]
|
||||||
|
|
||||||
unevaluatedProperties: false
|
unevaluatedProperties: false
|
||||||
|
|
||||||
examples:
|
examples:
|
||||||
@ -97,29 +129,40 @@ examples:
|
|||||||
port@0 {
|
port@0 {
|
||||||
phy-handle = <&rgmii_phy6>;
|
phy-handle = <&rgmii_phy6>;
|
||||||
phy-mode = "rgmii-id";
|
phy-mode = "rgmii-id";
|
||||||
|
rx-internal-delay-ps = <0>;
|
||||||
|
tx-internal-delay-ps = <0>;
|
||||||
reg = <0>;
|
reg = <0>;
|
||||||
};
|
};
|
||||||
|
|
||||||
port@1 {
|
port@1 {
|
||||||
phy-handle = <&rgmii_phy3>;
|
phy-handle = <&rgmii_phy3>;
|
||||||
phy-mode = "rgmii-id";
|
phy-mode = "rgmii-id";
|
||||||
|
rx-internal-delay-ps = <0>;
|
||||||
|
tx-internal-delay-ps = <0>;
|
||||||
reg = <1>;
|
reg = <1>;
|
||||||
};
|
};
|
||||||
|
|
||||||
port@2 {
|
port@2 {
|
||||||
phy-handle = <&rgmii_phy4>;
|
phy-handle = <&rgmii_phy4>;
|
||||||
phy-mode = "rgmii-id";
|
phy-mode = "rgmii-id";
|
||||||
|
rx-internal-delay-ps = <0>;
|
||||||
|
tx-internal-delay-ps = <0>;
|
||||||
reg = <2>;
|
reg = <2>;
|
||||||
};
|
};
|
||||||
|
|
||||||
port@3 {
|
port@3 {
|
||||||
|
phy-handle = <&rgmii_phy4>;
|
||||||
phy-mode = "rgmii-id";
|
phy-mode = "rgmii-id";
|
||||||
|
rx-internal-delay-ps = <0>;
|
||||||
|
tx-internal-delay-ps = <0>;
|
||||||
reg = <3>;
|
reg = <3>;
|
||||||
};
|
};
|
||||||
|
|
||||||
port@4 {
|
port@4 {
|
||||||
ethernet = <&enet2>;
|
ethernet = <&enet2>;
|
||||||
phy-mode = "rgmii";
|
phy-mode = "rgmii";
|
||||||
|
rx-internal-delay-ps = <0>;
|
||||||
|
tx-internal-delay-ps = <0>;
|
||||||
reg = <4>;
|
reg = <4>;
|
||||||
|
|
||||||
fixed-link {
|
fixed-link {
|
||||||
|
@ -1,215 +0,0 @@
|
|||||||
* Qualcomm Atheros QCA8xxx switch family
|
|
||||||
|
|
||||||
Required properties:
|
|
||||||
|
|
||||||
- compatible: should be one of:
|
|
||||||
"qca,qca8327"
|
|
||||||
"qca,qca8334"
|
|
||||||
"qca,qca8337"
|
|
||||||
|
|
||||||
- #size-cells: must be 0
|
|
||||||
- #address-cells: must be 1
|
|
||||||
|
|
||||||
Optional properties:
|
|
||||||
|
|
||||||
- reset-gpios: GPIO to be used to reset the whole device
|
|
||||||
|
|
||||||
Subnodes:
|
|
||||||
|
|
||||||
The integrated switch subnode should be specified according to the binding
|
|
||||||
described in dsa/dsa.txt. If the QCA8K switch is connect to a SoC's external
|
|
||||||
mdio-bus each subnode describing a port needs to have a valid phandle
|
|
||||||
referencing the internal PHY it is connected to. This is because there's no
|
|
||||||
N:N mapping of port and PHY id.
|
|
||||||
To declare the internal mdio-bus configuration, declare a mdio node in the
|
|
||||||
switch node and declare the phandle for the port referencing the internal
|
|
||||||
PHY is connected to. In this config a internal mdio-bus is registered and
|
|
||||||
the mdio MASTER is used as communication.
|
|
||||||
|
|
||||||
Don't use mixed external and internal mdio-bus configurations, as this is
|
|
||||||
not supported by the hardware.
|
|
||||||
|
|
||||||
The CPU port of this switch is always port 0.
|
|
||||||
|
|
||||||
A CPU port node has the following optional node:
|
|
||||||
|
|
||||||
- fixed-link : Fixed-link subnode describing a link to a non-MDIO
|
|
||||||
managed entity. See
|
|
||||||
Documentation/devicetree/bindings/net/fixed-link.txt
|
|
||||||
for details.
|
|
||||||
|
|
||||||
For QCA8K the 'fixed-link' sub-node supports only the following properties:
|
|
||||||
|
|
||||||
- 'speed' (integer, mandatory), to indicate the link speed. Accepted
|
|
||||||
values are 10, 100 and 1000
|
|
||||||
- 'full-duplex' (boolean, optional), to indicate that full duplex is
|
|
||||||
used. When absent, half duplex is assumed.
|
|
||||||
|
|
||||||
Examples:
|
|
||||||
|
|
||||||
for the external mdio-bus configuration:
|
|
||||||
|
|
||||||
&mdio0 {
|
|
||||||
phy_port1: phy@0 {
|
|
||||||
reg = <0>;
|
|
||||||
};
|
|
||||||
|
|
||||||
phy_port2: phy@1 {
|
|
||||||
reg = <1>;
|
|
||||||
};
|
|
||||||
|
|
||||||
phy_port3: phy@2 {
|
|
||||||
reg = <2>;
|
|
||||||
};
|
|
||||||
|
|
||||||
phy_port4: phy@3 {
|
|
||||||
reg = <3>;
|
|
||||||
};
|
|
||||||
|
|
||||||
phy_port5: phy@4 {
|
|
||||||
reg = <4>;
|
|
||||||
};
|
|
||||||
|
|
||||||
switch@10 {
|
|
||||||
compatible = "qca,qca8337";
|
|
||||||
#address-cells = <1>;
|
|
||||||
#size-cells = <0>;
|
|
||||||
|
|
||||||
reset-gpios = <&gpio 42 GPIO_ACTIVE_LOW>;
|
|
||||||
reg = <0x10>;
|
|
||||||
|
|
||||||
ports {
|
|
||||||
#address-cells = <1>;
|
|
||||||
#size-cells = <0>;
|
|
||||||
port@0 {
|
|
||||||
reg = <0>;
|
|
||||||
label = "cpu";
|
|
||||||
ethernet = <&gmac1>;
|
|
||||||
phy-mode = "rgmii";
|
|
||||||
fixed-link {
|
|
||||||
speed = 1000;
|
|
||||||
full-duplex;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
port@1 {
|
|
||||||
reg = <1>;
|
|
||||||
label = "lan1";
|
|
||||||
phy-handle = <&phy_port1>;
|
|
||||||
};
|
|
||||||
|
|
||||||
port@2 {
|
|
||||||
reg = <2>;
|
|
||||||
label = "lan2";
|
|
||||||
phy-handle = <&phy_port2>;
|
|
||||||
};
|
|
||||||
|
|
||||||
port@3 {
|
|
||||||
reg = <3>;
|
|
||||||
label = "lan3";
|
|
||||||
phy-handle = <&phy_port3>;
|
|
||||||
};
|
|
||||||
|
|
||||||
port@4 {
|
|
||||||
reg = <4>;
|
|
||||||
label = "lan4";
|
|
||||||
phy-handle = <&phy_port4>;
|
|
||||||
};
|
|
||||||
|
|
||||||
port@5 {
|
|
||||||
reg = <5>;
|
|
||||||
label = "wan";
|
|
||||||
phy-handle = <&phy_port5>;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
for the internal master mdio-bus configuration:
|
|
||||||
|
|
||||||
&mdio0 {
|
|
||||||
switch@10 {
|
|
||||||
compatible = "qca,qca8337";
|
|
||||||
#address-cells = <1>;
|
|
||||||
#size-cells = <0>;
|
|
||||||
|
|
||||||
reset-gpios = <&gpio 42 GPIO_ACTIVE_LOW>;
|
|
||||||
reg = <0x10>;
|
|
||||||
|
|
||||||
ports {
|
|
||||||
#address-cells = <1>;
|
|
||||||
#size-cells = <0>;
|
|
||||||
|
|
||||||
port@0 {
|
|
||||||
reg = <0>;
|
|
||||||
label = "cpu";
|
|
||||||
ethernet = <&gmac1>;
|
|
||||||
phy-mode = "rgmii";
|
|
||||||
fixed-link {
|
|
||||||
speed = 1000;
|
|
||||||
full-duplex;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
port@1 {
|
|
||||||
reg = <1>;
|
|
||||||
label = "lan1";
|
|
||||||
phy-mode = "internal";
|
|
||||||
phy-handle = <&phy_port1>;
|
|
||||||
};
|
|
||||||
|
|
||||||
port@2 {
|
|
||||||
reg = <2>;
|
|
||||||
label = "lan2";
|
|
||||||
phy-mode = "internal";
|
|
||||||
phy-handle = <&phy_port2>;
|
|
||||||
};
|
|
||||||
|
|
||||||
port@3 {
|
|
||||||
reg = <3>;
|
|
||||||
label = "lan3";
|
|
||||||
phy-mode = "internal";
|
|
||||||
phy-handle = <&phy_port3>;
|
|
||||||
};
|
|
||||||
|
|
||||||
port@4 {
|
|
||||||
reg = <4>;
|
|
||||||
label = "lan4";
|
|
||||||
phy-mode = "internal";
|
|
||||||
phy-handle = <&phy_port4>;
|
|
||||||
};
|
|
||||||
|
|
||||||
port@5 {
|
|
||||||
reg = <5>;
|
|
||||||
label = "wan";
|
|
||||||
phy-mode = "internal";
|
|
||||||
phy-handle = <&phy_port5>;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
mdio {
|
|
||||||
#address-cells = <1>;
|
|
||||||
#size-cells = <0>;
|
|
||||||
|
|
||||||
phy_port1: phy@0 {
|
|
||||||
reg = <0>;
|
|
||||||
};
|
|
||||||
|
|
||||||
phy_port2: phy@1 {
|
|
||||||
reg = <1>;
|
|
||||||
};
|
|
||||||
|
|
||||||
phy_port3: phy@2 {
|
|
||||||
reg = <2>;
|
|
||||||
};
|
|
||||||
|
|
||||||
phy_port4: phy@3 {
|
|
||||||
reg = <3>;
|
|
||||||
};
|
|
||||||
|
|
||||||
phy_port5: phy@4 {
|
|
||||||
reg = <4>;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
362
Documentation/devicetree/bindings/net/dsa/qca8k.yaml
Normal file
362
Documentation/devicetree/bindings/net/dsa/qca8k.yaml
Normal file
@ -0,0 +1,362 @@
|
|||||||
|
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||||
|
%YAML 1.2
|
||||||
|
---
|
||||||
|
$id: http://devicetree.org/schemas/net/dsa/qca8k.yaml#
|
||||||
|
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||||
|
|
||||||
|
title: Qualcomm Atheros QCA83xx switch family
|
||||||
|
|
||||||
|
maintainers:
|
||||||
|
- John Crispin <john@phrozen.org>
|
||||||
|
|
||||||
|
description:
|
||||||
|
If the QCA8K switch is connect to an SoC's external mdio-bus, each subnode
|
||||||
|
describing a port needs to have a valid phandle referencing the internal PHY
|
||||||
|
it is connected to. This is because there is no N:N mapping of port and PHY
|
||||||
|
ID. To declare the internal mdio-bus configuration, declare an MDIO node in
|
||||||
|
the switch node and declare the phandle for the port, referencing the internal
|
||||||
|
PHY it is connected to. In this config, an internal mdio-bus is registered and
|
||||||
|
the MDIO master is used for communication. Mixed external and internal
|
||||||
|
mdio-bus configurations are not supported by the hardware.
|
||||||
|
|
||||||
|
properties:
|
||||||
|
compatible:
|
||||||
|
oneOf:
|
||||||
|
- enum:
|
||||||
|
- qca,qca8327
|
||||||
|
- qca,qca8328
|
||||||
|
- qca,qca8334
|
||||||
|
- qca,qca8337
|
||||||
|
description: |
|
||||||
|
qca,qca8328: referenced as AR8328(N)-AK1(A/B) QFN 176 pin package
|
||||||
|
qca,qca8327: referenced as AR8327(N)-AL1A DR-QFN 148 pin package
|
||||||
|
qca,qca8334: referenced as QCA8334-AL3C QFN 88 pin package
|
||||||
|
qca,qca8337: referenced as QCA8337N-AL3(B/C) DR-QFN 148 pin package
|
||||||
|
|
||||||
|
reg:
|
||||||
|
maxItems: 1
|
||||||
|
|
||||||
|
reset-gpios:
|
||||||
|
description:
|
||||||
|
GPIO to be used to reset the whole device
|
||||||
|
maxItems: 1
|
||||||
|
|
||||||
|
qca,ignore-power-on-sel:
|
||||||
|
$ref: /schemas/types.yaml#/definitions/flag
|
||||||
|
description:
|
||||||
|
Ignore power-on pin strapping to configure LED open-drain or EEPROM
|
||||||
|
presence. This is needed for devices with incorrect configuration or when
|
||||||
|
the OEM has decided not to use pin strapping and falls back to SW regs.
|
||||||
|
|
||||||
|
qca,led-open-drain:
|
||||||
|
$ref: /schemas/types.yaml#/definitions/flag
|
||||||
|
description:
|
||||||
|
Set LEDs to open-drain mode. This requires the qca,ignore-power-on-sel to
|
||||||
|
be set, otherwise the driver will fail at probe. This is required if the
|
||||||
|
OEM does not use pin strapping to set this mode and prefers to set it
|
||||||
|
using SW regs. The pin strappings related to LED open-drain mode are
|
||||||
|
B68 on the QCA832x and B49 on the QCA833x.
|
||||||
|
|
||||||
|
mdio:
|
||||||
|
type: object
|
||||||
|
description: Qca8k switch have an internal mdio to access switch port.
|
||||||
|
If this is not present, the legacy mapping is used and the
|
||||||
|
internal mdio access is used.
|
||||||
|
With the legacy mapping the reg corresponding to the internal
|
||||||
|
mdio is the switch reg with an offset of -1.
|
||||||
|
|
||||||
|
properties:
|
||||||
|
'#address-cells':
|
||||||
|
const: 1
|
||||||
|
'#size-cells':
|
||||||
|
const: 0
|
||||||
|
|
||||||
|
patternProperties:
|
||||||
|
"^(ethernet-)?phy@[0-4]$":
|
||||||
|
type: object
|
||||||
|
|
||||||
|
allOf:
|
||||||
|
- $ref: "http://devicetree.org/schemas/net/mdio.yaml#"
|
||||||
|
|
||||||
|
properties:
|
||||||
|
reg:
|
||||||
|
maxItems: 1
|
||||||
|
|
||||||
|
required:
|
||||||
|
- reg
|
||||||
|
|
||||||
|
patternProperties:
|
||||||
|
"^(ethernet-)?ports$":
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
'#address-cells':
|
||||||
|
const: 1
|
||||||
|
'#size-cells':
|
||||||
|
const: 0
|
||||||
|
|
||||||
|
patternProperties:
|
||||||
|
"^(ethernet-)?port@[0-6]$":
|
||||||
|
type: object
|
||||||
|
description: Ethernet switch ports
|
||||||
|
|
||||||
|
properties:
|
||||||
|
reg:
|
||||||
|
description: Port number
|
||||||
|
|
||||||
|
label:
|
||||||
|
description:
|
||||||
|
Describes the label associated with this port, which will become
|
||||||
|
the netdev name
|
||||||
|
$ref: /schemas/types.yaml#/definitions/string
|
||||||
|
|
||||||
|
link:
|
||||||
|
description:
|
||||||
|
Should be a list of phandles to other switch's DSA port. This
|
||||||
|
port is used as the outgoing port towards the phandle ports. The
|
||||||
|
full routing information must be given, not just the one hop
|
||||||
|
routes to neighbouring switches
|
||||||
|
$ref: /schemas/types.yaml#/definitions/phandle-array
|
||||||
|
|
||||||
|
ethernet:
|
||||||
|
description:
|
||||||
|
Should be a phandle to a valid Ethernet device node. This host
|
||||||
|
device is what the switch port is connected to
|
||||||
|
$ref: /schemas/types.yaml#/definitions/phandle
|
||||||
|
|
||||||
|
phy-handle: true
|
||||||
|
|
||||||
|
phy-mode: true
|
||||||
|
|
||||||
|
fixed-link: true
|
||||||
|
|
||||||
|
mac-address: true
|
||||||
|
|
||||||
|
sfp: true
|
||||||
|
|
||||||
|
qca,sgmii-rxclk-falling-edge:
|
||||||
|
$ref: /schemas/types.yaml#/definitions/flag
|
||||||
|
description:
|
||||||
|
Set the receive clock phase to falling edge. Mostly commonly used on
|
||||||
|
the QCA8327 with CPU port 0 set to SGMII.
|
||||||
|
|
||||||
|
qca,sgmii-txclk-falling-edge:
|
||||||
|
$ref: /schemas/types.yaml#/definitions/flag
|
||||||
|
description:
|
||||||
|
Set the transmit clock phase to falling edge.
|
||||||
|
|
||||||
|
qca,sgmii-enable-pll:
|
||||||
|
$ref: /schemas/types.yaml#/definitions/flag
|
||||||
|
description:
|
||||||
|
For SGMII CPU port, explicitly enable PLL, TX and RX chain along with
|
||||||
|
Signal Detection. On the QCA8327 this should not be enabled, otherwise
|
||||||
|
the SGMII port will not initialize. When used on the QCA8337, revision 3
|
||||||
|
or greater, a warning will be displayed. When the CPU port is set to
|
||||||
|
SGMII on the QCA8337, it is advised to set this unless a communication
|
||||||
|
issue is observed.
|
||||||
|
|
||||||
|
required:
|
||||||
|
- reg
|
||||||
|
|
||||||
|
additionalProperties: false
|
||||||
|
|
||||||
|
oneOf:
|
||||||
|
- required:
|
||||||
|
- ports
|
||||||
|
- required:
|
||||||
|
- ethernet-ports
|
||||||
|
|
||||||
|
required:
|
||||||
|
- compatible
|
||||||
|
- reg
|
||||||
|
|
||||||
|
additionalProperties: true
|
||||||
|
|
||||||
|
examples:
|
||||||
|
- |
|
||||||
|
#include <dt-bindings/gpio/gpio.h>
|
||||||
|
|
||||||
|
mdio {
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <0>;
|
||||||
|
|
||||||
|
external_phy_port1: ethernet-phy@0 {
|
||||||
|
reg = <0>;
|
||||||
|
};
|
||||||
|
|
||||||
|
external_phy_port2: ethernet-phy@1 {
|
||||||
|
reg = <1>;
|
||||||
|
};
|
||||||
|
|
||||||
|
external_phy_port3: ethernet-phy@2 {
|
||||||
|
reg = <2>;
|
||||||
|
};
|
||||||
|
|
||||||
|
external_phy_port4: ethernet-phy@3 {
|
||||||
|
reg = <3>;
|
||||||
|
};
|
||||||
|
|
||||||
|
external_phy_port5: ethernet-phy@4 {
|
||||||
|
reg = <4>;
|
||||||
|
};
|
||||||
|
|
||||||
|
switch@10 {
|
||||||
|
compatible = "qca,qca8337";
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <0>;
|
||||||
|
reset-gpios = <&gpio 42 GPIO_ACTIVE_LOW>;
|
||||||
|
reg = <0x10>;
|
||||||
|
|
||||||
|
ports {
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <0>;
|
||||||
|
|
||||||
|
port@0 {
|
||||||
|
reg = <0>;
|
||||||
|
label = "cpu";
|
||||||
|
ethernet = <&gmac1>;
|
||||||
|
phy-mode = "rgmii";
|
||||||
|
|
||||||
|
fixed-link {
|
||||||
|
speed = <1000>;
|
||||||
|
full-duplex;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
port@1 {
|
||||||
|
reg = <1>;
|
||||||
|
label = "lan1";
|
||||||
|
phy-handle = <&external_phy_port1>;
|
||||||
|
};
|
||||||
|
|
||||||
|
port@2 {
|
||||||
|
reg = <2>;
|
||||||
|
label = "lan2";
|
||||||
|
phy-handle = <&external_phy_port2>;
|
||||||
|
};
|
||||||
|
|
||||||
|
port@3 {
|
||||||
|
reg = <3>;
|
||||||
|
label = "lan3";
|
||||||
|
phy-handle = <&external_phy_port3>;
|
||||||
|
};
|
||||||
|
|
||||||
|
port@4 {
|
||||||
|
reg = <4>;
|
||||||
|
label = "lan4";
|
||||||
|
phy-handle = <&external_phy_port4>;
|
||||||
|
};
|
||||||
|
|
||||||
|
port@5 {
|
||||||
|
reg = <5>;
|
||||||
|
label = "wan";
|
||||||
|
phy-handle = <&external_phy_port5>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
- |
|
||||||
|
#include <dt-bindings/gpio/gpio.h>
|
||||||
|
|
||||||
|
mdio {
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <0>;
|
||||||
|
|
||||||
|
switch@10 {
|
||||||
|
compatible = "qca,qca8337";
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <0>;
|
||||||
|
reset-gpios = <&gpio 42 GPIO_ACTIVE_LOW>;
|
||||||
|
reg = <0x10>;
|
||||||
|
|
||||||
|
ports {
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <0>;
|
||||||
|
|
||||||
|
port@0 {
|
||||||
|
reg = <0>;
|
||||||
|
label = "cpu";
|
||||||
|
ethernet = <&gmac1>;
|
||||||
|
phy-mode = "rgmii";
|
||||||
|
|
||||||
|
fixed-link {
|
||||||
|
speed = <1000>;
|
||||||
|
full-duplex;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
port@1 {
|
||||||
|
reg = <1>;
|
||||||
|
label = "lan1";
|
||||||
|
phy-mode = "internal";
|
||||||
|
phy-handle = <&internal_phy_port1>;
|
||||||
|
};
|
||||||
|
|
||||||
|
port@2 {
|
||||||
|
reg = <2>;
|
||||||
|
label = "lan2";
|
||||||
|
phy-mode = "internal";
|
||||||
|
phy-handle = <&internal_phy_port2>;
|
||||||
|
};
|
||||||
|
|
||||||
|
port@3 {
|
||||||
|
reg = <3>;
|
||||||
|
label = "lan3";
|
||||||
|
phy-mode = "internal";
|
||||||
|
phy-handle = <&internal_phy_port3>;
|
||||||
|
};
|
||||||
|
|
||||||
|
port@4 {
|
||||||
|
reg = <4>;
|
||||||
|
label = "lan4";
|
||||||
|
phy-mode = "internal";
|
||||||
|
phy-handle = <&internal_phy_port4>;
|
||||||
|
};
|
||||||
|
|
||||||
|
port@5 {
|
||||||
|
reg = <5>;
|
||||||
|
label = "wan";
|
||||||
|
phy-mode = "internal";
|
||||||
|
phy-handle = <&internal_phy_port5>;
|
||||||
|
};
|
||||||
|
|
||||||
|
port@6 {
|
||||||
|
reg = <0>;
|
||||||
|
label = "cpu";
|
||||||
|
ethernet = <&gmac1>;
|
||||||
|
phy-mode = "sgmii";
|
||||||
|
|
||||||
|
qca,sgmii-rxclk-falling-edge;
|
||||||
|
|
||||||
|
fixed-link {
|
||||||
|
speed = <1000>;
|
||||||
|
full-duplex;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
mdio {
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <0>;
|
||||||
|
|
||||||
|
internal_phy_port1: ethernet-phy@0 {
|
||||||
|
reg = <0>;
|
||||||
|
};
|
||||||
|
|
||||||
|
internal_phy_port2: ethernet-phy@1 {
|
||||||
|
reg = <1>;
|
||||||
|
};
|
||||||
|
|
||||||
|
internal_phy_port3: ethernet-phy@2 {
|
||||||
|
reg = <2>;
|
||||||
|
};
|
||||||
|
|
||||||
|
internal_phy_port4: ethernet-phy@3 {
|
||||||
|
reg = <3>;
|
||||||
|
};
|
||||||
|
|
||||||
|
internal_phy_port5: ethernet-phy@4 {
|
||||||
|
reg = <4>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
@ -9,6 +9,7 @@ SMI-based Realtek devices.
|
|||||||
Required properties:
|
Required properties:
|
||||||
|
|
||||||
- compatible: must be exactly one of:
|
- compatible: must be exactly one of:
|
||||||
|
"realtek,rtl8365mb" (4+1 ports)
|
||||||
"realtek,rtl8366"
|
"realtek,rtl8366"
|
||||||
"realtek,rtl8366rb" (4+1 ports)
|
"realtek,rtl8366rb" (4+1 ports)
|
||||||
"realtek,rtl8366s" (4+1 ports)
|
"realtek,rtl8366s" (4+1 ports)
|
||||||
@ -62,6 +63,8 @@ and subnodes of DSA switches.
|
|||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
|
|
||||||
|
An example for the RTL8366RB:
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
compatible = "realtek,rtl8366rb";
|
compatible = "realtek,rtl8366rb";
|
||||||
/* 22 = MDIO (has input reads), 21 = MDC (clock, output only) */
|
/* 22 = MDIO (has input reads), 21 = MDC (clock, output only) */
|
||||||
@ -151,3 +154,87 @@ switch {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
An example for the RTL8365MB-VC:
|
||||||
|
|
||||||
|
switch {
|
||||||
|
compatible = "realtek,rtl8365mb";
|
||||||
|
mdc-gpios = <&gpio1 16 GPIO_ACTIVE_HIGH>;
|
||||||
|
mdio-gpios = <&gpio1 17 GPIO_ACTIVE_HIGH>;
|
||||||
|
reset-gpios = <&gpio5 0 GPIO_ACTIVE_LOW>;
|
||||||
|
|
||||||
|
switch_intc: interrupt-controller {
|
||||||
|
interrupt-parent = <&gpio5>;
|
||||||
|
interrupts = <1 IRQ_TYPE_LEVEL_LOW>;
|
||||||
|
interrupt-controller;
|
||||||
|
#address-cells = <0>;
|
||||||
|
#interrupt-cells = <1>;
|
||||||
|
};
|
||||||
|
|
||||||
|
ports {
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <0>;
|
||||||
|
reg = <0>;
|
||||||
|
port@0 {
|
||||||
|
reg = <0>;
|
||||||
|
label = "swp0";
|
||||||
|
phy-handle = <ðphy0>;
|
||||||
|
};
|
||||||
|
port@1 {
|
||||||
|
reg = <1>;
|
||||||
|
label = "swp1";
|
||||||
|
phy-handle = <ðphy1>;
|
||||||
|
};
|
||||||
|
port@2 {
|
||||||
|
reg = <2>;
|
||||||
|
label = "swp2";
|
||||||
|
phy-handle = <ðphy2>;
|
||||||
|
};
|
||||||
|
port@3 {
|
||||||
|
reg = <3>;
|
||||||
|
label = "swp3";
|
||||||
|
phy-handle = <ðphy3>;
|
||||||
|
};
|
||||||
|
port@6 {
|
||||||
|
reg = <6>;
|
||||||
|
label = "cpu";
|
||||||
|
ethernet = <&fec1>;
|
||||||
|
phy-mode = "rgmii";
|
||||||
|
tx-internal-delay-ps = <2000>;
|
||||||
|
rx-internal-delay-ps = <2000>;
|
||||||
|
|
||||||
|
fixed-link {
|
||||||
|
speed = <1000>;
|
||||||
|
full-duplex;
|
||||||
|
pause;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
mdio {
|
||||||
|
compatible = "realtek,smi-mdio";
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <0>;
|
||||||
|
|
||||||
|
ethphy0: phy@0 {
|
||||||
|
reg = <0>;
|
||||||
|
interrupt-parent = <&switch_intc>;
|
||||||
|
interrupts = <0>;
|
||||||
|
};
|
||||||
|
ethphy1: phy@1 {
|
||||||
|
reg = <1>;
|
||||||
|
interrupt-parent = <&switch_intc>;
|
||||||
|
interrupts = <1>;
|
||||||
|
};
|
||||||
|
ethphy2: phy@2 {
|
||||||
|
reg = <2>;
|
||||||
|
interrupt-parent = <&switch_intc>;
|
||||||
|
interrupts = <2>;
|
||||||
|
};
|
||||||
|
ethphy3: phy@3 {
|
||||||
|
reg = <3>;
|
||||||
|
interrupt-parent = <&switch_intc>;
|
||||||
|
interrupts = <3>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
69
Documentation/devicetree/bindings/net/lantiq,etop-xway.yaml
Normal file
69
Documentation/devicetree/bindings/net/lantiq,etop-xway.yaml
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||||
|
%YAML 1.2
|
||||||
|
---
|
||||||
|
$id: http://devicetree.org/schemas/net/lantiq,etop-xway.yaml#
|
||||||
|
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||||
|
|
||||||
|
title: Lantiq Xway ETOP Ethernet driver
|
||||||
|
|
||||||
|
maintainers:
|
||||||
|
- John Crispin <john@phrozen.org>
|
||||||
|
|
||||||
|
properties:
|
||||||
|
$nodename:
|
||||||
|
pattern: "^ethernet@[0-9a-f]+$"
|
||||||
|
|
||||||
|
compatible:
|
||||||
|
const: lantiq,etop-xway
|
||||||
|
|
||||||
|
reg:
|
||||||
|
maxItems: 1
|
||||||
|
|
||||||
|
interrupts:
|
||||||
|
items:
|
||||||
|
- description: TX interrupt
|
||||||
|
- description: RX interrupt
|
||||||
|
|
||||||
|
interrupt-names:
|
||||||
|
items:
|
||||||
|
- const: tx
|
||||||
|
- const: rx
|
||||||
|
|
||||||
|
lantiq,tx-burst-length:
|
||||||
|
$ref: /schemas/types.yaml#/definitions/uint32
|
||||||
|
description: |
|
||||||
|
TX programmable burst length.
|
||||||
|
enum: [2, 4, 8]
|
||||||
|
|
||||||
|
lantiq,rx-burst-length:
|
||||||
|
$ref: /schemas/types.yaml#/definitions/uint32
|
||||||
|
description: |
|
||||||
|
RX programmable burst length.
|
||||||
|
enum: [2, 4, 8]
|
||||||
|
|
||||||
|
phy-mode: true
|
||||||
|
|
||||||
|
required:
|
||||||
|
- compatible
|
||||||
|
- reg
|
||||||
|
- interrupt-parent
|
||||||
|
- interrupts
|
||||||
|
- interrupt-names
|
||||||
|
- lantiq,tx-burst-length
|
||||||
|
- lantiq,rx-burst-length
|
||||||
|
- phy-mode
|
||||||
|
|
||||||
|
additionalProperties: false
|
||||||
|
|
||||||
|
examples:
|
||||||
|
- |
|
||||||
|
ethernet@e180000 {
|
||||||
|
compatible = "lantiq,etop-xway";
|
||||||
|
reg = <0xe180000 0x40000>;
|
||||||
|
interrupt-parent = <&icu0>;
|
||||||
|
interrupts = <73>, <78>;
|
||||||
|
interrupt-names = "tx", "rx";
|
||||||
|
lantiq,tx-burst-length = <8>;
|
||||||
|
lantiq,rx-burst-length = <8>;
|
||||||
|
phy-mode = "rmii";
|
||||||
|
};
|
@ -1,21 +0,0 @@
|
|||||||
Lantiq xRX200 GSWIP PMAC Ethernet driver
|
|
||||||
==================================
|
|
||||||
|
|
||||||
Required properties:
|
|
||||||
|
|
||||||
- compatible : "lantiq,xrx200-net" for the PMAC of the embedded
|
|
||||||
: GSWIP in the xXR200
|
|
||||||
- reg : memory range of the PMAC core inside of the GSWIP core
|
|
||||||
- interrupts : TX and RX DMA interrupts. Use interrupt-names "tx" for
|
|
||||||
: the TX interrupt and "rx" for the RX interrupt.
|
|
||||||
|
|
||||||
Example:
|
|
||||||
|
|
||||||
ethernet@e10b308 {
|
|
||||||
#address-cells = <1>;
|
|
||||||
#size-cells = <0>;
|
|
||||||
compatible = "lantiq,xrx200-net";
|
|
||||||
reg = <0xe10b308 0xcf8>;
|
|
||||||
interrupts = <73>, <72>;
|
|
||||||
interrupt-names = "tx", "rx";
|
|
||||||
};
|
|
59
Documentation/devicetree/bindings/net/lantiq,xrx200-net.yaml
Normal file
59
Documentation/devicetree/bindings/net/lantiq,xrx200-net.yaml
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||||
|
%YAML 1.2
|
||||||
|
---
|
||||||
|
$id: http://devicetree.org/schemas/net/lantiq,xrx200-net.yaml#
|
||||||
|
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||||
|
|
||||||
|
title: Lantiq xRX200 GSWIP PMAC Ethernet driver
|
||||||
|
|
||||||
|
maintainers:
|
||||||
|
- Hauke Mehrtens <hauke@hauke-m.de>
|
||||||
|
|
||||||
|
properties:
|
||||||
|
$nodename:
|
||||||
|
pattern: "^ethernet@[0-9a-f]+$"
|
||||||
|
|
||||||
|
compatible:
|
||||||
|
const: lantiq,xrx200-net
|
||||||
|
|
||||||
|
reg:
|
||||||
|
maxItems: 1
|
||||||
|
|
||||||
|
interrupts:
|
||||||
|
items:
|
||||||
|
- description: TX interrupt
|
||||||
|
- description: RX interrupt
|
||||||
|
|
||||||
|
interrupt-names:
|
||||||
|
items:
|
||||||
|
- const: tx
|
||||||
|
- const: rx
|
||||||
|
|
||||||
|
'#address-cells':
|
||||||
|
const: 1
|
||||||
|
|
||||||
|
'#size-cells':
|
||||||
|
const: 0
|
||||||
|
|
||||||
|
required:
|
||||||
|
- compatible
|
||||||
|
- reg
|
||||||
|
- interrupt-parent
|
||||||
|
- interrupts
|
||||||
|
- interrupt-names
|
||||||
|
- "#address-cells"
|
||||||
|
- "#size-cells"
|
||||||
|
|
||||||
|
additionalProperties: false
|
||||||
|
|
||||||
|
examples:
|
||||||
|
- |
|
||||||
|
ethernet@e10b308 {
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <0>;
|
||||||
|
compatible = "lantiq,xrx200-net";
|
||||||
|
reg = <0xe10b308 0xcf8>;
|
||||||
|
interrupt-parent = <&icu0>;
|
||||||
|
interrupts = <73>, <72>;
|
||||||
|
interrupt-names = "tx", "rx";
|
||||||
|
};
|
@ -30,6 +30,10 @@ Required properties:
|
|||||||
Optional elements: 'tsu_clk'
|
Optional elements: 'tsu_clk'
|
||||||
- clocks: Phandles to input clocks.
|
- clocks: Phandles to input clocks.
|
||||||
|
|
||||||
|
Optional properties:
|
||||||
|
- mdio: node containing PHY children. If this node is not present, then PHYs
|
||||||
|
will be direct children.
|
||||||
|
|
||||||
The MAC address will be determined using the optional properties
|
The MAC address will be determined using the optional properties
|
||||||
defined in ethernet.txt.
|
defined in ethernet.txt.
|
||||||
|
|
||||||
|
@ -51,6 +51,9 @@ examples:
|
|||||||
switch@10 {
|
switch@10 {
|
||||||
compatible = "qca,qca8337";
|
compatible = "qca,qca8337";
|
||||||
reg = <0x10>;
|
reg = <0x10>;
|
||||||
/* ... */
|
|
||||||
|
ports {
|
||||||
|
/* ... */
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@ -100,15 +100,18 @@ additionalProperties: false
|
|||||||
examples:
|
examples:
|
||||||
# Lager board
|
# Lager board
|
||||||
- |
|
- |
|
||||||
#include <dt-bindings/clock/r8a7790-clock.h>
|
#include <dt-bindings/clock/r8a7790-cpg-mssr.h>
|
||||||
#include <dt-bindings/interrupt-controller/irq.h>
|
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||||
|
#include <dt-bindings/power/r8a7790-sysc.h>
|
||||||
|
#include <dt-bindings/gpio/gpio.h>
|
||||||
|
|
||||||
ethernet@ee700000 {
|
ethernet@ee700000 {
|
||||||
compatible = "renesas,ether-r8a7790", "renesas,rcar-gen2-ether";
|
compatible = "renesas,ether-r8a7790", "renesas,rcar-gen2-ether";
|
||||||
reg = <0xee700000 0x400>;
|
reg = <0xee700000 0x400>;
|
||||||
interrupt-parent = <&gic>;
|
interrupts = <GIC_SPI 162 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
interrupts = <0 162 IRQ_TYPE_LEVEL_HIGH>;
|
clocks = <&cpg CPG_MOD 813>;
|
||||||
clocks = <&mstp8_clks R8A7790_CLK_ETHER>;
|
power-domains = <&sysc R8A7790_PD_ALWAYS_ON>;
|
||||||
|
resets = <&cpg 813>;
|
||||||
phy-mode = "rmii";
|
phy-mode = "rmii";
|
||||||
phy-handle = <&phy1>;
|
phy-handle = <&phy1>;
|
||||||
renesas,ether-link-active-low;
|
renesas,ether-link-active-low;
|
||||||
@ -116,8 +119,12 @@ examples:
|
|||||||
#size-cells = <0>;
|
#size-cells = <0>;
|
||||||
|
|
||||||
phy1: ethernet-phy@1 {
|
phy1: ethernet-phy@1 {
|
||||||
|
compatible = "ethernet-phy-id0022.1537",
|
||||||
|
"ethernet-phy-ieee802.3-c22";
|
||||||
reg = <1>;
|
reg = <1>;
|
||||||
interrupt-parent = <&irqc0>;
|
interrupt-parent = <&irqc0>;
|
||||||
interrupts = <0 IRQ_TYPE_LEVEL_LOW>;
|
interrupts = <0 IRQ_TYPE_LEVEL_LOW>;
|
||||||
|
micrel,led-mode = <1>;
|
||||||
|
reset-gpios = <&gpio5 31 GPIO_ACTIVE_LOW>;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@ -287,6 +287,7 @@ examples:
|
|||||||
"ch13", "ch14", "ch15", "ch16", "ch17", "ch18",
|
"ch13", "ch14", "ch15", "ch16", "ch17", "ch18",
|
||||||
"ch19", "ch20", "ch21", "ch22", "ch23", "ch24";
|
"ch19", "ch20", "ch21", "ch22", "ch23", "ch24";
|
||||||
clocks = <&cpg CPG_MOD 812>;
|
clocks = <&cpg CPG_MOD 812>;
|
||||||
|
clock-names = "fck";
|
||||||
iommus = <&ipmmu_ds0 16>;
|
iommus = <&ipmmu_ds0 16>;
|
||||||
power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
|
power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
|
||||||
resets = <&cpg 812>;
|
resets = <&cpg 812>;
|
||||||
@ -298,6 +299,8 @@ examples:
|
|||||||
#size-cells = <0>;
|
#size-cells = <0>;
|
||||||
|
|
||||||
phy0: ethernet-phy@0 {
|
phy0: ethernet-phy@0 {
|
||||||
|
compatible = "ethernet-phy-id0022.1622",
|
||||||
|
"ethernet-phy-ieee802.3-c22";
|
||||||
rxc-skew-ps = <1500>;
|
rxc-skew-ps = <1500>;
|
||||||
reg = <0>;
|
reg = <0>;
|
||||||
interrupt-parent = <&gpio2>;
|
interrupt-parent = <&gpio2>;
|
||||||
|
@ -24,6 +24,7 @@ properties:
|
|||||||
- socionext,uniphier-ld11-ave4
|
- socionext,uniphier-ld11-ave4
|
||||||
- socionext,uniphier-ld20-ave4
|
- socionext,uniphier-ld20-ave4
|
||||||
- socionext,uniphier-pxs3-ave4
|
- socionext,uniphier-pxs3-ave4
|
||||||
|
- socionext,uniphier-nx1-ave4
|
||||||
|
|
||||||
reg:
|
reg:
|
||||||
maxItems: 1
|
maxItems: 1
|
||||||
|
@ -47,6 +47,11 @@ properties:
|
|||||||
|
|
||||||
ieee80211-freq-limit: true
|
ieee80211-freq-limit: true
|
||||||
|
|
||||||
|
mediatek,eeprom-data:
|
||||||
|
$ref: /schemas/types.yaml#/definitions/uint32-array
|
||||||
|
description:
|
||||||
|
EEPROM data embedded as array.
|
||||||
|
|
||||||
mediatek,mtd-eeprom:
|
mediatek,mtd-eeprom:
|
||||||
$ref: /schemas/types.yaml#/definitions/phandle-array
|
$ref: /schemas/types.yaml#/definitions/phandle-array
|
||||||
description:
|
description:
|
||||||
|
@ -1,48 +0,0 @@
|
|||||||
* Qualcomm Atheros ath9k wireless devices
|
|
||||||
|
|
||||||
This node provides properties for configuring the ath9k wireless device. The
|
|
||||||
node is expected to be specified as a child node of the PCI controller to
|
|
||||||
which the wireless chip is connected.
|
|
||||||
|
|
||||||
Required properties:
|
|
||||||
- compatible: For PCI and PCIe devices this should be an identifier following
|
|
||||||
the format as defined in "PCI Bus Binding to Open Firmware"
|
|
||||||
Revision 2.1. One of the possible formats is "pciVVVV,DDDD"
|
|
||||||
where VVVV is the PCI vendor ID and DDDD is PCI device ID.
|
|
||||||
Typically QCA's PCI vendor ID 168c is used while the PCI device
|
|
||||||
ID depends on the chipset - see the following (possibly
|
|
||||||
incomplete) list:
|
|
||||||
- 0023 for AR5416
|
|
||||||
- 0024 for AR5418
|
|
||||||
- 0027 for AR9160
|
|
||||||
- 0029 for AR9220 and AR9223
|
|
||||||
- 002a for AR9280 and AR9283
|
|
||||||
- 002b for AR9285
|
|
||||||
- 002c for AR2427
|
|
||||||
- 002d for AR9227
|
|
||||||
- 002e for AR9287
|
|
||||||
- 0030 for AR9380, AR9381 and AR9382
|
|
||||||
- 0032 for AR9485
|
|
||||||
- 0033 for AR9580 and AR9590
|
|
||||||
- 0034 for AR9462
|
|
||||||
- 0036 for AR9565
|
|
||||||
- 0037 for AR9485
|
|
||||||
- reg: Address and length of the register set for the device.
|
|
||||||
|
|
||||||
Optional properties:
|
|
||||||
- qca,no-eeprom: Indicates that there is no physical EEPROM connected to the
|
|
||||||
ath9k wireless chip (in this case the calibration /
|
|
||||||
EEPROM data will be loaded from userspace using the
|
|
||||||
kernel firmware loader).
|
|
||||||
|
|
||||||
The MAC address will be determined using the optional properties defined in
|
|
||||||
net/ethernet.txt.
|
|
||||||
|
|
||||||
In this example, the node is defined as child node of the PCI controller:
|
|
||||||
&pci0 {
|
|
||||||
wifi@168c,002d {
|
|
||||||
compatible = "pci168c,002d";
|
|
||||||
reg = <0x7000 0 0 0 0x1000>;
|
|
||||||
qca,no-eeprom;
|
|
||||||
};
|
|
||||||
};
|
|
@ -0,0 +1,90 @@
|
|||||||
|
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||||
|
%YAML 1.2
|
||||||
|
---
|
||||||
|
$id: http://devicetree.org/schemas/net/wireless/qca,ath9k.yaml#
|
||||||
|
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||||
|
|
||||||
|
title: Qualcomm Atheros ath9k wireless devices Generic Binding
|
||||||
|
|
||||||
|
maintainers:
|
||||||
|
- Kalle Valo <kvalo@codeaurora.org>
|
||||||
|
|
||||||
|
description: |
|
||||||
|
This node provides properties for configuring the ath9k wireless device.
|
||||||
|
The node is expected to be specified as a child node of the PCI controller
|
||||||
|
to which the wireless chip is connected.
|
||||||
|
|
||||||
|
allOf:
|
||||||
|
- $ref: ieee80211.yaml#
|
||||||
|
|
||||||
|
properties:
|
||||||
|
compatible:
|
||||||
|
enum:
|
||||||
|
- pci168c,0023 # AR5416
|
||||||
|
- pci168c,0024 # AR5418
|
||||||
|
- pci168c,0027 # AR9160
|
||||||
|
- pci168c,0029 # AR9220 and AR9223
|
||||||
|
- pci168c,002a # AR9280 and AR9283
|
||||||
|
- pci168c,002b # AR9285
|
||||||
|
- pci168c,002c # AR2427 - 802.11n bonded out
|
||||||
|
- pci168c,002d # AR9227
|
||||||
|
- pci168c,002e # AR9287
|
||||||
|
- pci168c,0030 # AR9380, AR9381 and AR9382
|
||||||
|
- pci168c,0032 # AR9485
|
||||||
|
- pci168c,0033 # AR9580 and AR9590
|
||||||
|
- pci168c,0034 # AR9462
|
||||||
|
- pci168c,0036 # AR9565
|
||||||
|
- pci168c,0037 # AR1111 and AR9485
|
||||||
|
|
||||||
|
reg:
|
||||||
|
maxItems: 1
|
||||||
|
|
||||||
|
interrupts:
|
||||||
|
maxItems: 1
|
||||||
|
|
||||||
|
ieee80211-freq-limit: true
|
||||||
|
|
||||||
|
qca,no-eeprom:
|
||||||
|
$ref: /schemas/types.yaml#/definitions/flag
|
||||||
|
description:
|
||||||
|
Indicates that there is no physical EEPROM connected
|
||||||
|
|
||||||
|
nvmem-cells:
|
||||||
|
items:
|
||||||
|
- description: Reference to an nvmem node for the MAC address
|
||||||
|
- description: Reference to an nvmem node for calibration data
|
||||||
|
|
||||||
|
nvmem-cell-names:
|
||||||
|
items:
|
||||||
|
- const: mac-address
|
||||||
|
- const: calibration
|
||||||
|
|
||||||
|
required:
|
||||||
|
- compatible
|
||||||
|
- reg
|
||||||
|
|
||||||
|
additionalProperties: false
|
||||||
|
|
||||||
|
examples:
|
||||||
|
- |
|
||||||
|
pcie0 {
|
||||||
|
#address-cells = <3>;
|
||||||
|
#size-cells = <2>;
|
||||||
|
wifi@0,0 {
|
||||||
|
compatible = "pci168c,002d";
|
||||||
|
reg = <0 0 0 0 0>;
|
||||||
|
interrupts = <3>;
|
||||||
|
qca,no-eeprom;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
- |
|
||||||
|
pci0 {
|
||||||
|
#address-cells = <3>;
|
||||||
|
#size-cells = <2>;
|
||||||
|
wifi@0,11 {
|
||||||
|
compatible = "pci168c,0029";
|
||||||
|
reg = <0x8800 0 0 0 0>;
|
||||||
|
nvmem-cells = <&macaddr_art_c>, <&cal_art_1000>;
|
||||||
|
nvmem-cell-names = "mac-address", "calibration";
|
||||||
|
};
|
||||||
|
};
|
@ -131,6 +131,8 @@ patternProperties:
|
|||||||
description: Asahi Kasei Corp.
|
description: Asahi Kasei Corp.
|
||||||
"^asc,.*":
|
"^asc,.*":
|
||||||
description: All Sensors Corporation
|
description: All Sensors Corporation
|
||||||
|
"^asix,.*":
|
||||||
|
description: ASIX Electronics Corporation
|
||||||
"^aspeed,.*":
|
"^aspeed,.*":
|
||||||
description: ASPEED Technology Inc.
|
description: ASPEED Technology Inc.
|
||||||
"^asus,.*":
|
"^asus,.*":
|
||||||
|
@ -543,6 +543,8 @@ The CR-space dump uses vsc interface which is valid even if the FW command
|
|||||||
interface is not functional, which is the case in most FW fatal errors.
|
interface is not functional, which is the case in most FW fatal errors.
|
||||||
The recover function runs recover flow which reloads the driver and triggers fw
|
The recover function runs recover flow which reloads the driver and triggers fw
|
||||||
reset if needed.
|
reset if needed.
|
||||||
|
On firmware error, the health buffer is dumped into the dmesg. The log
|
||||||
|
level is derived from the error's severity (given in health buffer).
|
||||||
|
|
||||||
User commands examples:
|
User commands examples:
|
||||||
|
|
||||||
@ -700,3 +702,61 @@ Eswitch QoS tracepoints:
|
|||||||
$ cat /sys/kernel/debug/tracing/trace
|
$ cat /sys/kernel/debug/tracing/trace
|
||||||
...
|
...
|
||||||
<...>-27418 [006] .... 76547.187258: mlx5_esw_group_qos_destroy: (0000:82:00.0) group=000000007b576bb3 tsar_ix=1
|
<...>-27418 [006] .... 76547.187258: mlx5_esw_group_qos_destroy: (0000:82:00.0) group=000000007b576bb3 tsar_ix=1
|
||||||
|
|
||||||
|
SF tracepoints:
|
||||||
|
|
||||||
|
- mlx5_sf_add: trace addition of the SF port::
|
||||||
|
|
||||||
|
$ echo mlx5:mlx5_sf_add >> /sys/kernel/debug/tracing/set_event
|
||||||
|
$ cat /sys/kernel/debug/tracing/trace
|
||||||
|
...
|
||||||
|
devlink-9363 [031] ..... 24610.188722: mlx5_sf_add: (0000:06:00.0) port_index=32768 controller=0 hw_id=0x8000 sfnum=88
|
||||||
|
|
||||||
|
- mlx5_sf_free: trace freeing of the SF port::
|
||||||
|
|
||||||
|
$ echo mlx5:mlx5_sf_free >> /sys/kernel/debug/tracing/set_event
|
||||||
|
$ cat /sys/kernel/debug/tracing/trace
|
||||||
|
...
|
||||||
|
devlink-9830 [038] ..... 26300.404749: mlx5_sf_free: (0000:06:00.0) port_index=32768 controller=0 hw_id=0x8000
|
||||||
|
|
||||||
|
- mlx5_sf_hwc_alloc: trace allocating of the hardware SF context::
|
||||||
|
|
||||||
|
$ echo mlx5:mlx5_sf_hwc_alloc >> /sys/kernel/debug/tracing/set_event
|
||||||
|
$ cat /sys/kernel/debug/tracing/trace
|
||||||
|
...
|
||||||
|
devlink-9775 [031] ..... 26296.385259: mlx5_sf_hwc_alloc: (0000:06:00.0) controller=0 hw_id=0x8000 sfnum=88
|
||||||
|
|
||||||
|
- mlx5_sf_hwc_free: trace freeing of the hardware SF context::
|
||||||
|
|
||||||
|
$ echo mlx5:mlx5_sf_hwc_free >> /sys/kernel/debug/tracing/set_event
|
||||||
|
$ cat /sys/kernel/debug/tracing/trace
|
||||||
|
...
|
||||||
|
kworker/u128:3-9093 [046] ..... 24625.365771: mlx5_sf_hwc_free: (0000:06:00.0) hw_id=0x8000
|
||||||
|
|
||||||
|
- mlx5_sf_hwc_deferred_free : trace deferred freeing of the hardware SF context::
|
||||||
|
|
||||||
|
$ echo mlx5:mlx5_sf_hwc_deferred_free >> /sys/kernel/debug/tracing/set_event
|
||||||
|
$ cat /sys/kernel/debug/tracing/trace
|
||||||
|
...
|
||||||
|
devlink-9519 [046] ..... 24624.400271: mlx5_sf_hwc_deferred_free: (0000:06:00.0) hw_id=0x8000
|
||||||
|
|
||||||
|
- mlx5_sf_vhca_event: trace SF vhca event and state::
|
||||||
|
|
||||||
|
$ echo mlx5:mlx5_sf_vhca_event >> /sys/kernel/debug/tracing/set_event
|
||||||
|
$ cat /sys/kernel/debug/tracing/trace
|
||||||
|
...
|
||||||
|
kworker/u128:3-9093 [046] ..... 24625.365525: mlx5_sf_vhca_event: (0000:06:00.0) hw_id=0x8000 sfnum=88 vhca_state=1
|
||||||
|
|
||||||
|
- mlx5_sf_dev_add : trace SF device add event::
|
||||||
|
|
||||||
|
$ echo mlx5:mlx5_sf_dev_add>> /sys/kernel/debug/tracing/set_event
|
||||||
|
$ cat /sys/kernel/debug/tracing/trace
|
||||||
|
...
|
||||||
|
kworker/u128:3-9093 [000] ..... 24616.524495: mlx5_sf_dev_add: (0000:06:00.0) sfdev=00000000fc5d96fd aux_id=4 hw_id=0x8000 sfnum=88
|
||||||
|
|
||||||
|
- mlx5_sf_dev_del : trace SF device delete event::
|
||||||
|
|
||||||
|
$ echo mlx5:mlx5_sf_dev_del >> /sys/kernel/debug/tracing/set_event
|
||||||
|
$ cat /sys/kernel/debug/tracing/trace
|
||||||
|
...
|
||||||
|
kworker/u128:3-9093 [044] ..... 24624.400749: mlx5_sf_dev_del: (0000:06:00.0) sfdev=00000000fc5d96fd aux_id=4 hw_id=0x8000 sfnum=88
|
||||||
|
@ -22,6 +22,8 @@ Parameters
|
|||||||
- Permanent
|
- Permanent
|
||||||
* - ``msix_vec_per_pf_min``
|
* - ``msix_vec_per_pf_min``
|
||||||
- Permanent
|
- Permanent
|
||||||
|
* - ``enable_remote_dev_reset``
|
||||||
|
- Runtime
|
||||||
|
|
||||||
The ``bnxt`` driver also implements the following driver-specific
|
The ``bnxt`` driver also implements the following driver-specific
|
||||||
parameters.
|
parameters.
|
||||||
|
@ -44,8 +44,8 @@ example usage
|
|||||||
|
|
||||||
# Show all of the exposed regions with region sizes:
|
# Show all of the exposed regions with region sizes:
|
||||||
$ devlink region show
|
$ devlink region show
|
||||||
pci/0000:00:05.0/cr-space: size 1048576 snapshot [1 2]
|
pci/0000:00:05.0/cr-space: size 1048576 snapshot [1 2] max 8
|
||||||
pci/0000:00:05.0/fw-health: size 64 snapshot [1 2]
|
pci/0000:00:05.0/fw-health: size 64 snapshot [1 2] max 8
|
||||||
|
|
||||||
# Delete a snapshot using:
|
# Delete a snapshot using:
|
||||||
$ devlink region del pci/0000:00:05.0/cr-space snapshot 1
|
$ devlink region del pci/0000:00:05.0/cr-space snapshot 1
|
||||||
|
@ -142,6 +142,10 @@ Users can request an immediate capture of a snapshot via the
|
|||||||
|
|
||||||
.. code:: shell
|
.. code:: shell
|
||||||
|
|
||||||
|
$ devlink region show
|
||||||
|
pci/0000:01:00.0/nvm-flash: size 10485760 snapshot [] max 1
|
||||||
|
pci/0000:01:00.0/device-caps: size 4096 snapshot [] max 10
|
||||||
|
|
||||||
$ devlink region new pci/0000:01:00.0/nvm-flash snapshot 1
|
$ devlink region new pci/0000:01:00.0/nvm-flash snapshot 1
|
||||||
$ devlink region dump pci/0000:01:00.0/nvm-flash snapshot 1
|
$ devlink region dump pci/0000:01:00.0/nvm-flash snapshot 1
|
||||||
|
|
||||||
|
@ -47,3 +47,5 @@ parameters, info versions, and other features it supports.
|
|||||||
ti-cpsw-switch
|
ti-cpsw-switch
|
||||||
am65-nuss-cpsw-switch
|
am65-nuss-cpsw-switch
|
||||||
prestera
|
prestera
|
||||||
|
iosm
|
||||||
|
octeontx2
|
||||||
|
162
Documentation/networking/devlink/iosm.rst
Normal file
162
Documentation/networking/devlink/iosm.rst
Normal file
@ -0,0 +1,162 @@
|
|||||||
|
.. SPDX-License-Identifier: GPL-2.0
|
||||||
|
|
||||||
|
====================
|
||||||
|
iosm devlink support
|
||||||
|
====================
|
||||||
|
|
||||||
|
This document describes the devlink features implemented by the ``iosm``
|
||||||
|
device driver.
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
==========
|
||||||
|
|
||||||
|
The ``iosm`` driver implements the following driver-specific parameters.
|
||||||
|
|
||||||
|
.. list-table:: Driver-specific parameters implemented
|
||||||
|
:widths: 5 5 5 85
|
||||||
|
|
||||||
|
* - Name
|
||||||
|
- Type
|
||||||
|
- Mode
|
||||||
|
- Description
|
||||||
|
* - ``erase_full_flash``
|
||||||
|
- u8
|
||||||
|
- runtime
|
||||||
|
- erase_full_flash parameter is used to check if full erase is required for
|
||||||
|
the device during firmware flashing.
|
||||||
|
If set, Full nand erase command will be sent to the device. By default,
|
||||||
|
only conditional erase support is enabled.
|
||||||
|
|
||||||
|
|
||||||
|
Flash Update
|
||||||
|
============
|
||||||
|
|
||||||
|
The ``iosm`` driver implements support for flash update using the
|
||||||
|
``devlink-flash`` interface.
|
||||||
|
|
||||||
|
It supports updating the device flash using a combined flash image which contains
|
||||||
|
the Bootloader images and other modem software images.
|
||||||
|
|
||||||
|
The driver uses DEVLINK_SUPPORT_FLASH_UPDATE_COMPONENT to identify type of
|
||||||
|
firmware image that need to be flashed as requested by user space application.
|
||||||
|
Supported firmware image types.
|
||||||
|
|
||||||
|
.. list-table:: Firmware Image types
|
||||||
|
:widths: 15 85
|
||||||
|
|
||||||
|
* - Name
|
||||||
|
- Description
|
||||||
|
* - ``PSI RAM``
|
||||||
|
- Primary Signed Image
|
||||||
|
* - ``EBL``
|
||||||
|
- External Bootloader
|
||||||
|
* - ``FLS``
|
||||||
|
- Modem Software Image
|
||||||
|
|
||||||
|
PSI RAM and EBL are the RAM images which are injected to the device when the
|
||||||
|
device is in BOOT ROM stage. Once this is successful, the actual modem firmware
|
||||||
|
image is flashed to the device. The modem software image contains multiple files
|
||||||
|
each having one secure bin file and at least one Loadmap/Region file. For flashing
|
||||||
|
these files, appropriate commands are sent to the modem device along with the
|
||||||
|
data required for flashing. The data like region count and address of each region
|
||||||
|
has to be passed to the driver using the devlink param command.
|
||||||
|
|
||||||
|
If the device has to be fully erased before firmware flashing, user application
|
||||||
|
need to set the erase_full_flash parameter using devlink param command.
|
||||||
|
By default, conditional erase feature is supported.
|
||||||
|
|
||||||
|
Flash Commands:
|
||||||
|
===============
|
||||||
|
1) When modem is in Boot ROM stage, user can use below command to inject PSI RAM
|
||||||
|
image using devlink flash command.
|
||||||
|
|
||||||
|
$ devlink dev flash pci/0000:02:00.0 file <PSI_RAM_File_name>
|
||||||
|
|
||||||
|
2) If user want to do a full erase, below command need to be issued to set the
|
||||||
|
erase full flash param (To be set only if full erase required).
|
||||||
|
|
||||||
|
$ devlink dev param set pci/0000:02:00.0 name erase_full_flash value true cmode runtime
|
||||||
|
|
||||||
|
3) Inject EBL after the modem is in PSI stage.
|
||||||
|
|
||||||
|
$ devlink dev flash pci/0000:02:00.0 file <EBL_File_name>
|
||||||
|
|
||||||
|
4) Once EBL is injected successfully, then the actual firmware flashing takes
|
||||||
|
place. Below is the sequence of commands used for each of the firmware images.
|
||||||
|
|
||||||
|
a) Flash secure bin file.
|
||||||
|
|
||||||
|
$ devlink dev flash pci/0000:02:00.0 file <Secure_bin_file_name>
|
||||||
|
|
||||||
|
b) Flashing the Loadmap/Region file
|
||||||
|
|
||||||
|
$ devlink dev flash pci/0000:02:00.0 file <Load_map_file_name>
|
||||||
|
|
||||||
|
Regions
|
||||||
|
=======
|
||||||
|
|
||||||
|
The ``iosm`` driver supports dumping the coredump logs.
|
||||||
|
|
||||||
|
In case a firmware encounters an exception, a snapshot will be taken by the
|
||||||
|
driver. Following regions are accessed for device internal data.
|
||||||
|
|
||||||
|
.. list-table:: Regions implemented
|
||||||
|
:widths: 15 85
|
||||||
|
|
||||||
|
* - Name
|
||||||
|
- Description
|
||||||
|
* - ``report.json``
|
||||||
|
- The summary of exception details logged as part of this region.
|
||||||
|
* - ``coredump.fcd``
|
||||||
|
- This region contains the details related to the exception occurred in the
|
||||||
|
device (RAM dump).
|
||||||
|
* - ``cdd.log``
|
||||||
|
- This region contains the logs related to the modem CDD driver.
|
||||||
|
* - ``eeprom.bin``
|
||||||
|
- This region contains the eeprom logs.
|
||||||
|
* - ``bootcore_trace.bin``
|
||||||
|
- This region contains the current instance of bootloader logs.
|
||||||
|
* - ``bootcore_prev_trace.bin``
|
||||||
|
- This region contains the previous instance of bootloader logs.
|
||||||
|
|
||||||
|
|
||||||
|
Region commands
|
||||||
|
===============
|
||||||
|
|
||||||
|
$ devlink region show
|
||||||
|
|
||||||
|
$ devlink region new pci/0000:02:00.0/report.json
|
||||||
|
|
||||||
|
$ devlink region dump pci/0000:02:00.0/report.json snapshot 0
|
||||||
|
|
||||||
|
$ devlink region del pci/0000:02:00.0/report.json snapshot 0
|
||||||
|
|
||||||
|
$ devlink region new pci/0000:02:00.0/coredump.fcd
|
||||||
|
|
||||||
|
$ devlink region dump pci/0000:02:00.0/coredump.fcd snapshot 1
|
||||||
|
|
||||||
|
$ devlink region del pci/0000:02:00.0/coredump.fcd snapshot 1
|
||||||
|
|
||||||
|
$ devlink region new pci/0000:02:00.0/cdd.log
|
||||||
|
|
||||||
|
$ devlink region dump pci/0000:02:00.0/cdd.log snapshot 2
|
||||||
|
|
||||||
|
$ devlink region del pci/0000:02:00.0/cdd.log snapshot 2
|
||||||
|
|
||||||
|
$ devlink region new pci/0000:02:00.0/eeprom.bin
|
||||||
|
|
||||||
|
$ devlink region dump pci/0000:02:00.0/eeprom.bin snapshot 3
|
||||||
|
|
||||||
|
$ devlink region del pci/0000:02:00.0/eeprom.bin snapshot 3
|
||||||
|
|
||||||
|
$ devlink region new pci/0000:02:00.0/bootcore_trace.bin
|
||||||
|
|
||||||
|
$ devlink region dump pci/0000:02:00.0/bootcore_trace.bin snapshot 4
|
||||||
|
|
||||||
|
$ devlink region del pci/0000:02:00.0/bootcore_trace.bin snapshot 4
|
||||||
|
|
||||||
|
$ devlink region new pci/0000:02:00.0/bootcore_prev_trace.bin
|
||||||
|
|
||||||
|
$ devlink region dump pci/0000:02:00.0/bootcore_prev_trace.bin snapshot 5
|
||||||
|
|
||||||
|
$ devlink region del pci/0000:02:00.0/bootcore_prev_trace.bin snapshot 5
|
42
Documentation/networking/devlink/octeontx2.rst
Normal file
42
Documentation/networking/devlink/octeontx2.rst
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
.. SPDX-License-Identifier: GPL-2.0
|
||||||
|
|
||||||
|
=========================
|
||||||
|
octeontx2 devlink support
|
||||||
|
=========================
|
||||||
|
|
||||||
|
This document describes the devlink features implemented by the ``octeontx2 AF, PF and VF``
|
||||||
|
device drivers.
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
==========
|
||||||
|
|
||||||
|
The ``octeontx2 PF and VF`` drivers implement the following driver-specific parameters.
|
||||||
|
|
||||||
|
.. list-table:: Driver-specific parameters implemented
|
||||||
|
:widths: 5 5 5 85
|
||||||
|
|
||||||
|
* - Name
|
||||||
|
- Type
|
||||||
|
- Mode
|
||||||
|
- Description
|
||||||
|
* - ``mcam_count``
|
||||||
|
- u16
|
||||||
|
- runtime
|
||||||
|
- Select number of match CAM entries to be allocated for an interface.
|
||||||
|
The same is used for ntuple filters of the interface. Supported by
|
||||||
|
PF and VF drivers.
|
||||||
|
|
||||||
|
The ``octeontx2 AF`` driver implements the following driver-specific parameters.
|
||||||
|
|
||||||
|
.. list-table:: Driver-specific parameters implemented
|
||||||
|
:widths: 5 5 5 85
|
||||||
|
|
||||||
|
* - Name
|
||||||
|
- Type
|
||||||
|
- Mode
|
||||||
|
- Description
|
||||||
|
* - ``dwrr_mtu``
|
||||||
|
- u32
|
||||||
|
- runtime
|
||||||
|
- Use to set the quantum which hardware uses for scheduling among transmit queues.
|
||||||
|
Hardware uses weighted DWRR algorithm to schedule among all transmit queues.
|
@ -41,6 +41,11 @@ In the message structure descriptions below, if an attribute name is suffixed
|
|||||||
with "+", parent nest can contain multiple attributes of the same type. This
|
with "+", parent nest can contain multiple attributes of the same type. This
|
||||||
implements an array of entries.
|
implements an array of entries.
|
||||||
|
|
||||||
|
Attributes that need to be filled-in by device drivers and that are dumped to
|
||||||
|
user space based on whether they are valid or not should not use zero as a
|
||||||
|
valid value. This avoids the need to explicitly signal the validity of the
|
||||||
|
attribute in the device driver API.
|
||||||
|
|
||||||
|
|
||||||
Request header
|
Request header
|
||||||
==============
|
==============
|
||||||
@ -179,7 +184,7 @@ according to message purpose:
|
|||||||
|
|
||||||
Userspace to kernel:
|
Userspace to kernel:
|
||||||
|
|
||||||
===================================== ================================
|
===================================== =================================
|
||||||
``ETHTOOL_MSG_STRSET_GET`` get string set
|
``ETHTOOL_MSG_STRSET_GET`` get string set
|
||||||
``ETHTOOL_MSG_LINKINFO_GET`` get link settings
|
``ETHTOOL_MSG_LINKINFO_GET`` get link settings
|
||||||
``ETHTOOL_MSG_LINKINFO_SET`` set link settings
|
``ETHTOOL_MSG_LINKINFO_SET`` set link settings
|
||||||
@ -213,7 +218,9 @@ Userspace to kernel:
|
|||||||
``ETHTOOL_MSG_MODULE_EEPROM_GET`` read SFP module EEPROM
|
``ETHTOOL_MSG_MODULE_EEPROM_GET`` read SFP module EEPROM
|
||||||
``ETHTOOL_MSG_STATS_GET`` get standard statistics
|
``ETHTOOL_MSG_STATS_GET`` get standard statistics
|
||||||
``ETHTOOL_MSG_PHC_VCLOCKS_GET`` get PHC virtual clocks info
|
``ETHTOOL_MSG_PHC_VCLOCKS_GET`` get PHC virtual clocks info
|
||||||
===================================== ================================
|
``ETHTOOL_MSG_MODULE_SET`` set transceiver module parameters
|
||||||
|
``ETHTOOL_MSG_MODULE_GET`` get transceiver module parameters
|
||||||
|
===================================== =================================
|
||||||
|
|
||||||
Kernel to userspace:
|
Kernel to userspace:
|
||||||
|
|
||||||
@ -252,6 +259,7 @@ Kernel to userspace:
|
|||||||
``ETHTOOL_MSG_MODULE_EEPROM_GET_REPLY`` read SFP module EEPROM
|
``ETHTOOL_MSG_MODULE_EEPROM_GET_REPLY`` read SFP module EEPROM
|
||||||
``ETHTOOL_MSG_STATS_GET_REPLY`` standard statistics
|
``ETHTOOL_MSG_STATS_GET_REPLY`` standard statistics
|
||||||
``ETHTOOL_MSG_PHC_VCLOCKS_GET_REPLY`` PHC virtual clocks info
|
``ETHTOOL_MSG_PHC_VCLOCKS_GET_REPLY`` PHC virtual clocks info
|
||||||
|
``ETHTOOL_MSG_MODULE_GET_REPLY`` transceiver module parameters
|
||||||
======================================== =================================
|
======================================== =================================
|
||||||
|
|
||||||
``GET`` requests are sent by userspace applications to retrieve device
|
``GET`` requests are sent by userspace applications to retrieve device
|
||||||
@ -520,6 +528,8 @@ Link extended states:
|
|||||||
power required from cable or module
|
power required from cable or module
|
||||||
|
|
||||||
``ETHTOOL_LINK_EXT_STATE_OVERHEAT`` The module is overheated
|
``ETHTOOL_LINK_EXT_STATE_OVERHEAT`` The module is overheated
|
||||||
|
|
||||||
|
``ETHTOOL_LINK_EXT_STATE_MODULE`` Transceiver module issue
|
||||||
================================================ ============================================
|
================================================ ============================================
|
||||||
|
|
||||||
Link extended substates:
|
Link extended substates:
|
||||||
@ -613,6 +623,14 @@ Link extended substates:
|
|||||||
``ETHTOOL_LINK_EXT_SUBSTATE_CI_CABLE_TEST_FAILURE`` Cable test failure
|
``ETHTOOL_LINK_EXT_SUBSTATE_CI_CABLE_TEST_FAILURE`` Cable test failure
|
||||||
=================================================== ============================================
|
=================================================== ============================================
|
||||||
|
|
||||||
|
Transceiver module issue substates:
|
||||||
|
|
||||||
|
=================================================== ============================================
|
||||||
|
``ETHTOOL_LINK_EXT_SUBSTATE_MODULE_CMIS_NOT_READY`` The CMIS Module State Machine did not reach
|
||||||
|
the ModuleReady state. For example, if the
|
||||||
|
module is stuck at ModuleFault state
|
||||||
|
=================================================== ============================================
|
||||||
|
|
||||||
DEBUG_GET
|
DEBUG_GET
|
||||||
=========
|
=========
|
||||||
|
|
||||||
@ -1521,6 +1539,63 @@ Kernel response contents:
|
|||||||
``ETHTOOL_A_PHC_VCLOCKS_INDEX`` s32 PHC index array
|
``ETHTOOL_A_PHC_VCLOCKS_INDEX`` s32 PHC index array
|
||||||
==================================== ====== ==========================
|
==================================== ====== ==========================
|
||||||
|
|
||||||
|
MODULE_GET
|
||||||
|
==========
|
||||||
|
|
||||||
|
Gets transceiver module parameters.
|
||||||
|
|
||||||
|
Request contents:
|
||||||
|
|
||||||
|
===================================== ====== ==========================
|
||||||
|
``ETHTOOL_A_MODULE_HEADER`` nested request header
|
||||||
|
===================================== ====== ==========================
|
||||||
|
|
||||||
|
Kernel response contents:
|
||||||
|
|
||||||
|
====================================== ====== ==========================
|
||||||
|
``ETHTOOL_A_MODULE_HEADER`` nested reply header
|
||||||
|
``ETHTOOL_A_MODULE_POWER_MODE_POLICY`` u8 power mode policy
|
||||||
|
``ETHTOOL_A_MODULE_POWER_MODE`` u8 operational power mode
|
||||||
|
====================================== ====== ==========================
|
||||||
|
|
||||||
|
The optional ``ETHTOOL_A_MODULE_POWER_MODE_POLICY`` attribute encodes the
|
||||||
|
transceiver module power mode policy enforced by the host. The default policy
|
||||||
|
is driver-dependent, but "auto" is the recommended default and it should be
|
||||||
|
implemented by new drivers and drivers where conformance to a legacy behavior
|
||||||
|
is not critical.
|
||||||
|
|
||||||
|
The optional ``ETHTHOOL_A_MODULE_POWER_MODE`` attribute encodes the operational
|
||||||
|
power mode policy of the transceiver module. It is only reported when a module
|
||||||
|
is plugged-in. Possible values are:
|
||||||
|
|
||||||
|
.. kernel-doc:: include/uapi/linux/ethtool.h
|
||||||
|
:identifiers: ethtool_module_power_mode
|
||||||
|
|
||||||
|
MODULE_SET
|
||||||
|
==========
|
||||||
|
|
||||||
|
Sets transceiver module parameters.
|
||||||
|
|
||||||
|
Request contents:
|
||||||
|
|
||||||
|
====================================== ====== ==========================
|
||||||
|
``ETHTOOL_A_MODULE_HEADER`` nested request header
|
||||||
|
``ETHTOOL_A_MODULE_POWER_MODE_POLICY`` u8 power mode policy
|
||||||
|
====================================== ====== ==========================
|
||||||
|
|
||||||
|
When set, the optional ``ETHTOOL_A_MODULE_POWER_MODE_POLICY`` attribute is used
|
||||||
|
to set the transceiver module power policy enforced by the host. Possible
|
||||||
|
values are:
|
||||||
|
|
||||||
|
.. kernel-doc:: include/uapi/linux/ethtool.h
|
||||||
|
:identifiers: ethtool_module_power_mode_policy
|
||||||
|
|
||||||
|
For SFF-8636 modules, low power mode is forced by the host according to table
|
||||||
|
6-10 in revision 2.10a of the specification.
|
||||||
|
|
||||||
|
For CMIS modules, low power mode is forced by the host according to table 6-12
|
||||||
|
in revision 5.0 of the specification.
|
||||||
|
|
||||||
Request translation
|
Request translation
|
||||||
===================
|
===================
|
||||||
|
|
||||||
@ -1620,4 +1695,6 @@ are netlink only.
|
|||||||
n/a ``ETHTOOL_MSG_CABLE_TEST_TDR_ACT``
|
n/a ``ETHTOOL_MSG_CABLE_TEST_TDR_ACT``
|
||||||
n/a ``ETHTOOL_MSG_TUNNEL_INFO_GET``
|
n/a ``ETHTOOL_MSG_TUNNEL_INFO_GET``
|
||||||
n/a ``ETHTOOL_MSG_PHC_VCLOCKS_GET``
|
n/a ``ETHTOOL_MSG_PHC_VCLOCKS_GET``
|
||||||
|
n/a ``ETHTOOL_MSG_MODULE_GET``
|
||||||
|
n/a ``ETHTOOL_MSG_MODULE_SET``
|
||||||
=================================== =====================================
|
=================================== =====================================
|
||||||
|
@ -989,14 +989,6 @@ tcp_challenge_ack_limit - INTEGER
|
|||||||
in RFC 5961 (Improving TCP's Robustness to Blind In-Window Attacks)
|
in RFC 5961 (Improving TCP's Robustness to Blind In-Window Attacks)
|
||||||
Default: 1000
|
Default: 1000
|
||||||
|
|
||||||
tcp_rx_skb_cache - BOOLEAN
|
|
||||||
Controls a per TCP socket cache of one skb, that might help
|
|
||||||
performance of some workloads. This might be dangerous
|
|
||||||
on systems with a lot of TCP sockets, since it increases
|
|
||||||
memory usage.
|
|
||||||
|
|
||||||
Default: 0 (disabled)
|
|
||||||
|
|
||||||
UDP variables
|
UDP variables
|
||||||
=============
|
=============
|
||||||
|
|
||||||
@ -1619,6 +1611,15 @@ arp_accept - BOOLEAN
|
|||||||
gratuitous arp frame, the arp table will be updated regardless
|
gratuitous arp frame, the arp table will be updated regardless
|
||||||
if this setting is on or off.
|
if this setting is on or off.
|
||||||
|
|
||||||
|
arp_evict_nocarrier - BOOLEAN
|
||||||
|
Clears the ARP cache on NOCARRIER events. This option is important for
|
||||||
|
wireless devices where the ARP cache should not be cleared when roaming
|
||||||
|
between access points on the same network. In most cases this should
|
||||||
|
remain as the default (1).
|
||||||
|
|
||||||
|
- 1 - (default): Clear the ARP cache on NOCARRIER events
|
||||||
|
- 0 - Do not clear ARP cache on NOCARRIER events
|
||||||
|
|
||||||
mcast_solicit - INTEGER
|
mcast_solicit - INTEGER
|
||||||
The maximum number of multicast probes in INCOMPLETE state,
|
The maximum number of multicast probes in INCOMPLETE state,
|
||||||
when the associated hardware address is unknown. Defaults
|
when the associated hardware address is unknown. Defaults
|
||||||
@ -2349,6 +2350,15 @@ ndisc_tclass - INTEGER
|
|||||||
|
|
||||||
* 0 - (default)
|
* 0 - (default)
|
||||||
|
|
||||||
|
ndisc_evict_nocarrier - BOOLEAN
|
||||||
|
Clears the neighbor discovery table on NOCARRIER events. This option is
|
||||||
|
important for wireless devices where the neighbor discovery cache should
|
||||||
|
not be cleared when roaming between access points on the same network.
|
||||||
|
In most cases this should remain as the default (1).
|
||||||
|
|
||||||
|
- 1 - (default): Clear neighbor discover cache on NOCARRIER events.
|
||||||
|
- 0 - Do not clear neighbor discovery cache on NOCARRIER events.
|
||||||
|
|
||||||
mldv1_unsolicited_report_interval - INTEGER
|
mldv1_unsolicited_report_interval - INTEGER
|
||||||
The interval in milliseconds in which the next unsolicited
|
The interval in milliseconds in which the next unsolicited
|
||||||
MLDv1 report retransmit will take place.
|
MLDv1 report retransmit will take place.
|
||||||
|
@ -300,3 +300,14 @@ sync_version - INTEGER
|
|||||||
|
|
||||||
Kernels with this sync_version entry are able to receive messages
|
Kernels with this sync_version entry are able to receive messages
|
||||||
of both version 1 and version 2 of the synchronisation protocol.
|
of both version 1 and version 2 of the synchronisation protocol.
|
||||||
|
|
||||||
|
run_estimation - BOOLEAN
|
||||||
|
0 - disabled
|
||||||
|
not 0 - enabled (default)
|
||||||
|
|
||||||
|
If disabled, the estimation will be stop, and you can't see
|
||||||
|
any update on speed estimation data.
|
||||||
|
|
||||||
|
You can always re-enable estimation by setting this value to 1.
|
||||||
|
But be careful, the first estimation after re-enable is not
|
||||||
|
accurate.
|
||||||
|
@ -211,3 +211,62 @@ remote address is already known, or the message does not require a reply.
|
|||||||
|
|
||||||
Like the send calls, sockets will only receive responses to requests they have
|
Like the send calls, sockets will only receive responses to requests they have
|
||||||
sent (TO=1) and may only respond (TO=0) to requests they have received.
|
sent (TO=1) and may only respond (TO=0) to requests they have received.
|
||||||
|
|
||||||
|
Kernel internals
|
||||||
|
================
|
||||||
|
|
||||||
|
There are a few possible packet flows in the MCTP stack:
|
||||||
|
|
||||||
|
1. local TX to remote endpoint, message <= MTU::
|
||||||
|
|
||||||
|
sendmsg()
|
||||||
|
-> mctp_local_output()
|
||||||
|
: route lookup
|
||||||
|
-> rt->output() (== mctp_route_output)
|
||||||
|
-> dev_queue_xmit()
|
||||||
|
|
||||||
|
2. local TX to remote endpoint, message > MTU::
|
||||||
|
|
||||||
|
sendmsg()
|
||||||
|
-> mctp_local_output()
|
||||||
|
-> mctp_do_fragment_route()
|
||||||
|
: creates packet-sized skbs. For each new skb:
|
||||||
|
-> rt->output() (== mctp_route_output)
|
||||||
|
-> dev_queue_xmit()
|
||||||
|
|
||||||
|
3. remote TX to local endpoint, single-packet message::
|
||||||
|
|
||||||
|
mctp_pkttype_receive()
|
||||||
|
: route lookup
|
||||||
|
-> rt->output() (== mctp_route_input)
|
||||||
|
: sk_key lookup
|
||||||
|
-> sock_queue_rcv_skb()
|
||||||
|
|
||||||
|
4. remote TX to local endpoint, multiple-packet message::
|
||||||
|
|
||||||
|
mctp_pkttype_receive()
|
||||||
|
: route lookup
|
||||||
|
-> rt->output() (== mctp_route_input)
|
||||||
|
: sk_key lookup
|
||||||
|
: stores skb in struct sk_key->reasm_head
|
||||||
|
|
||||||
|
mctp_pkttype_receive()
|
||||||
|
: route lookup
|
||||||
|
-> rt->output() (== mctp_route_input)
|
||||||
|
: sk_key lookup
|
||||||
|
: finds existing reassembly in sk_key->reasm_head
|
||||||
|
: appends new fragment
|
||||||
|
-> sock_queue_rcv_skb()
|
||||||
|
|
||||||
|
Key refcounts
|
||||||
|
-------------
|
||||||
|
|
||||||
|
* keys are refed by:
|
||||||
|
|
||||||
|
- a skb: during route output, stored in ``skb->cb``.
|
||||||
|
|
||||||
|
- netns and sock lists.
|
||||||
|
|
||||||
|
* keys can be associated with a device, in which case they hold a
|
||||||
|
reference to the dev (set through ``key->dev``, counted through
|
||||||
|
``dev->key_count``). Multiple keys can reference the device.
|
||||||
|
29
MAINTAINERS
29
MAINTAINERS
@ -1026,6 +1026,14 @@ S: Maintained
|
|||||||
F: Documentation/devicetree/bindings/iio/light/ams,as73211.yaml
|
F: Documentation/devicetree/bindings/iio/light/ams,as73211.yaml
|
||||||
F: drivers/iio/light/as73211.c
|
F: drivers/iio/light/as73211.c
|
||||||
|
|
||||||
|
AMT (Automatic Multicast Tunneling)
|
||||||
|
M: Taehee Yoo <ap420073@gmail.com>
|
||||||
|
L: netdev@vger.kernel.org
|
||||||
|
S: Maintained
|
||||||
|
T: git git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net.git
|
||||||
|
T: git git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-next.git
|
||||||
|
F: drivers/net/amt.c
|
||||||
|
|
||||||
ANALOG DEVICES INC AD7192 DRIVER
|
ANALOG DEVICES INC AD7192 DRIVER
|
||||||
M: Alexandru Tachici <alexandru.tachici@analog.com>
|
M: Alexandru Tachici <alexandru.tachici@analog.com>
|
||||||
L: linux-iio@vger.kernel.org
|
L: linux-iio@vger.kernel.org
|
||||||
@ -2908,6 +2916,12 @@ S: Maintained
|
|||||||
F: Documentation/hwmon/asc7621.rst
|
F: Documentation/hwmon/asc7621.rst
|
||||||
F: drivers/hwmon/asc7621.c
|
F: drivers/hwmon/asc7621.c
|
||||||
|
|
||||||
|
ASIX AX88796C SPI ETHERNET ADAPTER
|
||||||
|
M: Łukasz Stelmach <l.stelmach@samsung.com>
|
||||||
|
S: Maintained
|
||||||
|
F: Documentation/devicetree/bindings/net/asix,ax88796c.yaml
|
||||||
|
F: drivers/net/ethernet/asix/ax88796c_*
|
||||||
|
|
||||||
ASPEED PINCTRL DRIVERS
|
ASPEED PINCTRL DRIVERS
|
||||||
M: Andrew Jeffery <andrew@aj.id.au>
|
M: Andrew Jeffery <andrew@aj.id.au>
|
||||||
L: linux-aspeed@lists.ozlabs.org (moderated for non-subscribers)
|
L: linux-aspeed@lists.ozlabs.org (moderated for non-subscribers)
|
||||||
@ -3438,6 +3452,7 @@ S: Supported
|
|||||||
F: arch/arm64/net/
|
F: arch/arm64/net/
|
||||||
|
|
||||||
BPF JIT for MIPS (32-BIT AND 64-BIT)
|
BPF JIT for MIPS (32-BIT AND 64-BIT)
|
||||||
|
M: Johan Almbladh <johan.almbladh@anyfinetworks.com>
|
||||||
M: Paul Burton <paulburton@kernel.org>
|
M: Paul Burton <paulburton@kernel.org>
|
||||||
L: netdev@vger.kernel.org
|
L: netdev@vger.kernel.org
|
||||||
L: bpf@vger.kernel.org
|
L: bpf@vger.kernel.org
|
||||||
@ -7034,7 +7049,6 @@ F: drivers/net/mdio/fwnode_mdio.c
|
|||||||
F: drivers/net/mdio/of_mdio.c
|
F: drivers/net/mdio/of_mdio.c
|
||||||
F: drivers/net/pcs/
|
F: drivers/net/pcs/
|
||||||
F: drivers/net/phy/
|
F: drivers/net/phy/
|
||||||
F: drivers/of/of_net.c
|
|
||||||
F: include/dt-bindings/net/qca-ar803x.h
|
F: include/dt-bindings/net/qca-ar803x.h
|
||||||
F: include/linux/*mdio*.h
|
F: include/linux/*mdio*.h
|
||||||
F: include/linux/mdio/*.h
|
F: include/linux/mdio/*.h
|
||||||
@ -7046,6 +7060,7 @@ F: include/linux/platform_data/mdio-gpio.h
|
|||||||
F: include/trace/events/mdio.h
|
F: include/trace/events/mdio.h
|
||||||
F: include/uapi/linux/mdio.h
|
F: include/uapi/linux/mdio.h
|
||||||
F: include/uapi/linux/mii.h
|
F: include/uapi/linux/mii.h
|
||||||
|
F: net/core/of_net.c
|
||||||
|
|
||||||
EXFAT FILE SYSTEM
|
EXFAT FILE SYSTEM
|
||||||
M: Namjae Jeon <linkinjeon@kernel.org>
|
M: Namjae Jeon <linkinjeon@kernel.org>
|
||||||
@ -11878,7 +11893,9 @@ F: drivers/mmc/host/mtk-sd.c
|
|||||||
MEDIATEK MT76 WIRELESS LAN DRIVER
|
MEDIATEK MT76 WIRELESS LAN DRIVER
|
||||||
M: Felix Fietkau <nbd@nbd.name>
|
M: Felix Fietkau <nbd@nbd.name>
|
||||||
M: Lorenzo Bianconi <lorenzo.bianconi83@gmail.com>
|
M: Lorenzo Bianconi <lorenzo.bianconi83@gmail.com>
|
||||||
R: Ryder Lee <ryder.lee@mediatek.com>
|
M: Ryder Lee <ryder.lee@mediatek.com>
|
||||||
|
R: Shayne Chen <shayne.chen@mediatek.com>
|
||||||
|
R: Sean Wang <sean.wang@mediatek.com>
|
||||||
L: linux-wireless@vger.kernel.org
|
L: linux-wireless@vger.kernel.org
|
||||||
S: Maintained
|
S: Maintained
|
||||||
F: drivers/net/wireless/mediatek/mt76/
|
F: drivers/net/wireless/mediatek/mt76/
|
||||||
@ -13109,6 +13126,7 @@ F: include/linux/dsa/
|
|||||||
F: include/linux/platform_data/dsa.h
|
F: include/linux/platform_data/dsa.h
|
||||||
F: include/net/dsa.h
|
F: include/net/dsa.h
|
||||||
F: net/dsa/
|
F: net/dsa/
|
||||||
|
F: tools/testing/selftests/drivers/net/dsa/
|
||||||
|
|
||||||
NETWORKING [GENERAL]
|
NETWORKING [GENERAL]
|
||||||
M: "David S. Miller" <davem@davemloft.net>
|
M: "David S. Miller" <davem@davemloft.net>
|
||||||
@ -15530,6 +15548,7 @@ M: ath9k-devel@qca.qualcomm.com
|
|||||||
L: linux-wireless@vger.kernel.org
|
L: linux-wireless@vger.kernel.org
|
||||||
S: Supported
|
S: Supported
|
||||||
W: https://wireless.wiki.kernel.org/en/users/Drivers/ath9k
|
W: https://wireless.wiki.kernel.org/en/users/Drivers/ath9k
|
||||||
|
F: Documentation/devicetree/bindings/net/wireless/qca,ath9k.yaml
|
||||||
F: drivers/net/wireless/ath/ath9k/
|
F: drivers/net/wireless/ath/ath9k/
|
||||||
|
|
||||||
QUALCOMM CAMERA SUBSYSTEM DRIVER
|
QUALCOMM CAMERA SUBSYSTEM DRIVER
|
||||||
@ -15951,6 +15970,12 @@ L: linux-wireless@vger.kernel.org
|
|||||||
S: Maintained
|
S: Maintained
|
||||||
F: drivers/net/wireless/realtek/rtw88/
|
F: drivers/net/wireless/realtek/rtw88/
|
||||||
|
|
||||||
|
REALTEK WIRELESS DRIVER (rtw89)
|
||||||
|
M: Ping-Ke Shih <pkshih@realtek.com>
|
||||||
|
L: linux-wireless@vger.kernel.org
|
||||||
|
S: Maintained
|
||||||
|
F: drivers/net/wireless/realtek/rtw89/
|
||||||
|
|
||||||
REDPINE WIRELESS DRIVER
|
REDPINE WIRELESS DRIVER
|
||||||
M: Amitkumar Karwar <amitkarwar@gmail.com>
|
M: Amitkumar Karwar <amitkarwar@gmail.com>
|
||||||
M: Siva Rebbagondla <siva8118@gmail.com>
|
M: Siva Rebbagondla <siva8118@gmail.com>
|
||||||
|
3
Makefile
3
Makefile
@ -480,6 +480,8 @@ LZ4 = lz4c
|
|||||||
XZ = xz
|
XZ = xz
|
||||||
ZSTD = zstd
|
ZSTD = zstd
|
||||||
|
|
||||||
|
PAHOLE_FLAGS = $(shell PAHOLE=$(PAHOLE) $(srctree)/scripts/pahole-flags.sh)
|
||||||
|
|
||||||
CHECKFLAGS := -D__linux__ -Dlinux -D__STDC__ -Dunix -D__unix__ \
|
CHECKFLAGS := -D__linux__ -Dlinux -D__STDC__ -Dunix -D__unix__ \
|
||||||
-Wbitwise -Wno-return-void -Wno-unknown-attribute $(CF)
|
-Wbitwise -Wno-return-void -Wno-unknown-attribute $(CF)
|
||||||
NOSTDINC_FLAGS :=
|
NOSTDINC_FLAGS :=
|
||||||
@ -534,6 +536,7 @@ export KBUILD_CFLAGS CFLAGS_KERNEL CFLAGS_MODULE
|
|||||||
export KBUILD_AFLAGS AFLAGS_KERNEL AFLAGS_MODULE
|
export KBUILD_AFLAGS AFLAGS_KERNEL AFLAGS_MODULE
|
||||||
export KBUILD_AFLAGS_MODULE KBUILD_CFLAGS_MODULE KBUILD_LDFLAGS_MODULE
|
export KBUILD_AFLAGS_MODULE KBUILD_CFLAGS_MODULE KBUILD_LDFLAGS_MODULE
|
||||||
export KBUILD_AFLAGS_KERNEL KBUILD_CFLAGS_KERNEL
|
export KBUILD_AFLAGS_KERNEL KBUILD_CFLAGS_KERNEL
|
||||||
|
export PAHOLE_FLAGS
|
||||||
|
|
||||||
# Files to ignore in find ... statements
|
# Files to ignore in find ... statements
|
||||||
|
|
||||||
|
@ -131,6 +131,8 @@
|
|||||||
|
|
||||||
#define SO_BUF_LOCK 72
|
#define SO_BUF_LOCK 72
|
||||||
|
|
||||||
|
#define SO_RESERVE_MEM 73
|
||||||
|
|
||||||
#if !defined(__KERNEL__)
|
#if !defined(__KERNEL__)
|
||||||
|
|
||||||
#if __BITS_PER_LONG == 64
|
#if __BITS_PER_LONG == 64
|
||||||
|
@ -1882,11 +1882,6 @@ static int validate_code(struct jit_ctx *ctx)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void bpf_jit_compile(struct bpf_prog *prog)
|
|
||||||
{
|
|
||||||
/* Nothing to do here. We support Internal BPF. */
|
|
||||||
}
|
|
||||||
|
|
||||||
bool bpf_jit_needs_zext(void)
|
bool bpf_jit_needs_zext(void)
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
|
@ -200,7 +200,7 @@ static struct net_device * __init nfeth_probe(int unit)
|
|||||||
dev->irq = nfEtherIRQ;
|
dev->irq = nfEtherIRQ;
|
||||||
dev->netdev_ops = &nfeth_netdev_ops;
|
dev->netdev_ops = &nfeth_netdev_ops;
|
||||||
|
|
||||||
memcpy(dev->dev_addr, mac, ETH_ALEN);
|
eth_hw_addr_set(dev, mac);
|
||||||
|
|
||||||
priv = netdev_priv(dev);
|
priv = netdev_priv(dev);
|
||||||
priv->ethX = unit;
|
priv->ethX = unit;
|
||||||
|
@ -56,7 +56,6 @@ config MIPS
|
|||||||
select HAVE_ARCH_TRACEHOOK
|
select HAVE_ARCH_TRACEHOOK
|
||||||
select HAVE_ARCH_TRANSPARENT_HUGEPAGE if CPU_SUPPORTS_HUGEPAGES
|
select HAVE_ARCH_TRANSPARENT_HUGEPAGE if CPU_SUPPORTS_HUGEPAGES
|
||||||
select HAVE_ASM_MODVERSIONS
|
select HAVE_ASM_MODVERSIONS
|
||||||
select HAVE_CBPF_JIT if !64BIT && !CPU_MICROMIPS
|
|
||||||
select HAVE_CONTEXT_TRACKING
|
select HAVE_CONTEXT_TRACKING
|
||||||
select HAVE_TIF_NOHZ
|
select HAVE_TIF_NOHZ
|
||||||
select HAVE_C_RECORDMCOUNT
|
select HAVE_C_RECORDMCOUNT
|
||||||
@ -64,7 +63,10 @@ config MIPS
|
|||||||
select HAVE_DEBUG_STACKOVERFLOW
|
select HAVE_DEBUG_STACKOVERFLOW
|
||||||
select HAVE_DMA_CONTIGUOUS
|
select HAVE_DMA_CONTIGUOUS
|
||||||
select HAVE_DYNAMIC_FTRACE
|
select HAVE_DYNAMIC_FTRACE
|
||||||
select HAVE_EBPF_JIT if 64BIT && !CPU_MICROMIPS && TARGET_ISA_REV >= 2
|
select HAVE_EBPF_JIT if !CPU_MICROMIPS && \
|
||||||
|
!CPU_DADDI_WORKAROUNDS && \
|
||||||
|
!CPU_R4000_WORKAROUNDS && \
|
||||||
|
!CPU_R4400_WORKAROUNDS
|
||||||
select HAVE_EXIT_THREAD
|
select HAVE_EXIT_THREAD
|
||||||
select HAVE_FAST_GUP
|
select HAVE_FAST_GUP
|
||||||
select HAVE_FTRACE_MCOUNT_RECORD
|
select HAVE_FTRACE_MCOUNT_RECORD
|
||||||
@ -1211,15 +1213,6 @@ config SYS_SUPPORTS_RELOCATABLE
|
|||||||
The platform must provide plat_get_fdt() if it selects CONFIG_USE_OF
|
The platform must provide plat_get_fdt() if it selects CONFIG_USE_OF
|
||||||
to allow access to command line and entropy sources.
|
to allow access to command line and entropy sources.
|
||||||
|
|
||||||
config MIPS_CBPF_JIT
|
|
||||||
def_bool y
|
|
||||||
depends on BPF_JIT && HAVE_CBPF_JIT
|
|
||||||
|
|
||||||
config MIPS_EBPF_JIT
|
|
||||||
def_bool y
|
|
||||||
depends on BPF_JIT && HAVE_EBPF_JIT
|
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Endianness selection. Sufficiently obscure so many users don't know what to
|
# Endianness selection. Sufficiently obscure so many users don't know what to
|
||||||
# answer,so we try hard to limit the available choices. Also the use of a
|
# answer,so we try hard to limit the available choices. Also the use of a
|
||||||
|
@ -45,6 +45,6 @@ extern void ltq_dma_close(struct ltq_dma_channel *ch);
|
|||||||
extern void ltq_dma_alloc_tx(struct ltq_dma_channel *ch);
|
extern void ltq_dma_alloc_tx(struct ltq_dma_channel *ch);
|
||||||
extern void ltq_dma_alloc_rx(struct ltq_dma_channel *ch);
|
extern void ltq_dma_alloc_rx(struct ltq_dma_channel *ch);
|
||||||
extern void ltq_dma_free(struct ltq_dma_channel *ch);
|
extern void ltq_dma_free(struct ltq_dma_channel *ch);
|
||||||
extern void ltq_dma_init_port(int p);
|
extern void ltq_dma_init_port(int p, int tx_burst, int rx_burst);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -145,6 +145,7 @@ Ip_u1(_mtlo);
|
|||||||
Ip_u3u1u2(_mul);
|
Ip_u3u1u2(_mul);
|
||||||
Ip_u1u2(_multu);
|
Ip_u1u2(_multu);
|
||||||
Ip_u3u1u2(_mulu);
|
Ip_u3u1u2(_mulu);
|
||||||
|
Ip_u3u1u2(_muhu);
|
||||||
Ip_u3u1u2(_nor);
|
Ip_u3u1u2(_nor);
|
||||||
Ip_u3u1u2(_or);
|
Ip_u3u1u2(_or);
|
||||||
Ip_u2u1u3(_ori);
|
Ip_u2u1u3(_ori);
|
||||||
@ -248,7 +249,11 @@ static inline void uasm_l##lb(struct uasm_label **lab, u32 *addr) \
|
|||||||
#define uasm_i_bnezl(buf, rs, off) uasm_i_bnel(buf, rs, 0, off)
|
#define uasm_i_bnezl(buf, rs, off) uasm_i_bnel(buf, rs, 0, off)
|
||||||
#define uasm_i_ehb(buf) uasm_i_sll(buf, 0, 0, 3)
|
#define uasm_i_ehb(buf) uasm_i_sll(buf, 0, 0, 3)
|
||||||
#define uasm_i_move(buf, a, b) UASM_i_ADDU(buf, a, 0, b)
|
#define uasm_i_move(buf, a, b) UASM_i_ADDU(buf, a, 0, b)
|
||||||
|
#ifdef CONFIG_CPU_NOP_WORKAROUNDS
|
||||||
|
#define uasm_i_nop(buf) uasm_i_or(buf, 1, 1, 0)
|
||||||
|
#else
|
||||||
#define uasm_i_nop(buf) uasm_i_sll(buf, 0, 0, 0)
|
#define uasm_i_nop(buf) uasm_i_sll(buf, 0, 0, 0)
|
||||||
|
#endif
|
||||||
#define uasm_i_ssnop(buf) uasm_i_sll(buf, 0, 0, 1)
|
#define uasm_i_ssnop(buf) uasm_i_sll(buf, 0, 0, 1)
|
||||||
|
|
||||||
static inline void uasm_i_drotr_safe(u32 **p, unsigned int a1,
|
static inline void uasm_i_drotr_safe(u32 **p, unsigned int a1,
|
||||||
|
@ -142,6 +142,8 @@
|
|||||||
|
|
||||||
#define SO_BUF_LOCK 72
|
#define SO_BUF_LOCK 72
|
||||||
|
|
||||||
|
#define SO_RESERVE_MEM 73
|
||||||
|
|
||||||
#if !defined(__KERNEL__)
|
#if !defined(__KERNEL__)
|
||||||
|
|
||||||
#if __BITS_PER_LONG == 64
|
#if __BITS_PER_LONG == 64
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
#include <linux/export.h>
|
#include <linux/export.h>
|
||||||
#include <linux/spinlock.h>
|
#include <linux/spinlock.h>
|
||||||
#include <linux/clk.h>
|
#include <linux/clk.h>
|
||||||
|
#include <linux/delay.h>
|
||||||
#include <linux/err.h>
|
#include <linux/err.h>
|
||||||
#include <linux/of.h>
|
#include <linux/of.h>
|
||||||
|
|
||||||
@ -30,6 +31,7 @@
|
|||||||
#define LTQ_DMA_PCTRL 0x44
|
#define LTQ_DMA_PCTRL 0x44
|
||||||
#define LTQ_DMA_IRNEN 0xf4
|
#define LTQ_DMA_IRNEN 0xf4
|
||||||
|
|
||||||
|
#define DMA_ID_CHNR GENMASK(26, 20) /* channel number */
|
||||||
#define DMA_DESCPT BIT(3) /* descriptor complete irq */
|
#define DMA_DESCPT BIT(3) /* descriptor complete irq */
|
||||||
#define DMA_TX BIT(8) /* TX channel direction */
|
#define DMA_TX BIT(8) /* TX channel direction */
|
||||||
#define DMA_CHAN_ON BIT(0) /* channel on / off bit */
|
#define DMA_CHAN_ON BIT(0) /* channel on / off bit */
|
||||||
@ -39,8 +41,11 @@
|
|||||||
#define DMA_IRQ_ACK 0x7e /* IRQ status register */
|
#define DMA_IRQ_ACK 0x7e /* IRQ status register */
|
||||||
#define DMA_POLL BIT(31) /* turn on channel polling */
|
#define DMA_POLL BIT(31) /* turn on channel polling */
|
||||||
#define DMA_CLK_DIV4 BIT(6) /* polling clock divider */
|
#define DMA_CLK_DIV4 BIT(6) /* polling clock divider */
|
||||||
#define DMA_2W_BURST BIT(1) /* 2 word burst length */
|
#define DMA_PCTRL_2W_BURST 0x1 /* 2 word burst length */
|
||||||
#define DMA_MAX_CHANNEL 20 /* the soc has 20 channels */
|
#define DMA_PCTRL_4W_BURST 0x2 /* 4 word burst length */
|
||||||
|
#define DMA_PCTRL_8W_BURST 0x3 /* 8 word burst length */
|
||||||
|
#define DMA_TX_BURST_SHIFT 4 /* tx burst shift */
|
||||||
|
#define DMA_RX_BURST_SHIFT 2 /* rx burst shift */
|
||||||
#define DMA_ETOP_ENDIANNESS (0xf << 8) /* endianness swap etop channels */
|
#define DMA_ETOP_ENDIANNESS (0xf << 8) /* endianness swap etop channels */
|
||||||
#define DMA_WEIGHT (BIT(17) | BIT(16)) /* default channel wheight */
|
#define DMA_WEIGHT (BIT(17) | BIT(16)) /* default channel wheight */
|
||||||
|
|
||||||
@ -177,7 +182,7 @@ ltq_dma_free(struct ltq_dma_channel *ch)
|
|||||||
EXPORT_SYMBOL_GPL(ltq_dma_free);
|
EXPORT_SYMBOL_GPL(ltq_dma_free);
|
||||||
|
|
||||||
void
|
void
|
||||||
ltq_dma_init_port(int p)
|
ltq_dma_init_port(int p, int tx_burst, int rx_burst)
|
||||||
{
|
{
|
||||||
ltq_dma_w32(p, LTQ_DMA_PS);
|
ltq_dma_w32(p, LTQ_DMA_PS);
|
||||||
switch (p) {
|
switch (p) {
|
||||||
@ -186,15 +191,44 @@ ltq_dma_init_port(int p)
|
|||||||
* Tell the DMA engine to swap the endianness of data frames and
|
* Tell the DMA engine to swap the endianness of data frames and
|
||||||
* drop packets if the channel arbitration fails.
|
* drop packets if the channel arbitration fails.
|
||||||
*/
|
*/
|
||||||
ltq_dma_w32_mask(0, DMA_ETOP_ENDIANNESS | DMA_PDEN,
|
ltq_dma_w32_mask(0, (DMA_ETOP_ENDIANNESS | DMA_PDEN),
|
||||||
LTQ_DMA_PCTRL);
|
LTQ_DMA_PCTRL);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DMA_PORT_DEU:
|
default:
|
||||||
ltq_dma_w32((DMA_2W_BURST << 4) | (DMA_2W_BURST << 2),
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (rx_burst) {
|
||||||
|
case 8:
|
||||||
|
ltq_dma_w32_mask(0x0c, (DMA_PCTRL_8W_BURST << DMA_RX_BURST_SHIFT),
|
||||||
LTQ_DMA_PCTRL);
|
LTQ_DMA_PCTRL);
|
||||||
break;
|
break;
|
||||||
|
case 4:
|
||||||
|
ltq_dma_w32_mask(0x0c, (DMA_PCTRL_4W_BURST << DMA_RX_BURST_SHIFT),
|
||||||
|
LTQ_DMA_PCTRL);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
ltq_dma_w32_mask(0x0c, (DMA_PCTRL_2W_BURST << DMA_RX_BURST_SHIFT),
|
||||||
|
LTQ_DMA_PCTRL);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (tx_burst) {
|
||||||
|
case 8:
|
||||||
|
ltq_dma_w32_mask(0x30, (DMA_PCTRL_8W_BURST << DMA_TX_BURST_SHIFT),
|
||||||
|
LTQ_DMA_PCTRL);
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
ltq_dma_w32_mask(0x30, (DMA_PCTRL_4W_BURST << DMA_TX_BURST_SHIFT),
|
||||||
|
LTQ_DMA_PCTRL);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
ltq_dma_w32_mask(0x30, (DMA_PCTRL_2W_BURST << DMA_TX_BURST_SHIFT),
|
||||||
|
LTQ_DMA_PCTRL);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -206,7 +240,7 @@ ltq_dma_init(struct platform_device *pdev)
|
|||||||
{
|
{
|
||||||
struct clk *clk;
|
struct clk *clk;
|
||||||
struct resource *res;
|
struct resource *res;
|
||||||
unsigned id;
|
unsigned int id, nchannels;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||||
@ -222,21 +256,24 @@ ltq_dma_init(struct platform_device *pdev)
|
|||||||
clk_enable(clk);
|
clk_enable(clk);
|
||||||
ltq_dma_w32_mask(0, DMA_RESET, LTQ_DMA_CTRL);
|
ltq_dma_w32_mask(0, DMA_RESET, LTQ_DMA_CTRL);
|
||||||
|
|
||||||
|
usleep_range(1, 10);
|
||||||
|
|
||||||
/* disable all interrupts */
|
/* disable all interrupts */
|
||||||
ltq_dma_w32(0, LTQ_DMA_IRNEN);
|
ltq_dma_w32(0, LTQ_DMA_IRNEN);
|
||||||
|
|
||||||
/* reset/configure each channel */
|
/* reset/configure each channel */
|
||||||
for (i = 0; i < DMA_MAX_CHANNEL; i++) {
|
id = ltq_dma_r32(LTQ_DMA_ID);
|
||||||
|
nchannels = ((id & DMA_ID_CHNR) >> 20);
|
||||||
|
for (i = 0; i < nchannels; i++) {
|
||||||
ltq_dma_w32(i, LTQ_DMA_CS);
|
ltq_dma_w32(i, LTQ_DMA_CS);
|
||||||
ltq_dma_w32(DMA_CHAN_RST, LTQ_DMA_CCTRL);
|
ltq_dma_w32(DMA_CHAN_RST, LTQ_DMA_CCTRL);
|
||||||
ltq_dma_w32(DMA_POLL | DMA_CLK_DIV4, LTQ_DMA_CPOLL);
|
ltq_dma_w32(DMA_POLL | DMA_CLK_DIV4, LTQ_DMA_CPOLL);
|
||||||
ltq_dma_w32_mask(DMA_CHAN_ON, 0, LTQ_DMA_CCTRL);
|
ltq_dma_w32_mask(DMA_CHAN_ON, 0, LTQ_DMA_CCTRL);
|
||||||
}
|
}
|
||||||
|
|
||||||
id = ltq_dma_r32(LTQ_DMA_ID);
|
|
||||||
dev_info(&pdev->dev,
|
dev_info(&pdev->dev,
|
||||||
"Init done - hw rev: %X, ports: %d, channels: %d\n",
|
"Init done - hw rev: %X, ports: %d, channels: %d\n",
|
||||||
id & 0x1f, (id >> 16) & 0xf, id >> 20);
|
id & 0x1f, (id >> 16) & 0xf, nchannels);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -90,7 +90,7 @@ static const struct insn insn_table[insn_invalid] = {
|
|||||||
RS | RT | RD},
|
RS | RT | RD},
|
||||||
[insn_dmtc0] = {M(cop0_op, dmtc_op, 0, 0, 0, 0), RT | RD | SET},
|
[insn_dmtc0] = {M(cop0_op, dmtc_op, 0, 0, 0, 0), RT | RD | SET},
|
||||||
[insn_dmultu] = {M(spec_op, 0, 0, 0, 0, dmultu_op), RS | RT},
|
[insn_dmultu] = {M(spec_op, 0, 0, 0, 0, dmultu_op), RS | RT},
|
||||||
[insn_dmulu] = {M(spec_op, 0, 0, 0, dmult_dmul_op, dmultu_op),
|
[insn_dmulu] = {M(spec_op, 0, 0, 0, dmultu_dmulu_op, dmultu_op),
|
||||||
RS | RT | RD},
|
RS | RT | RD},
|
||||||
[insn_drotr] = {M(spec_op, 1, 0, 0, 0, dsrl_op), RT | RD | RE},
|
[insn_drotr] = {M(spec_op, 1, 0, 0, 0, dsrl_op), RT | RD | RE},
|
||||||
[insn_drotr32] = {M(spec_op, 1, 0, 0, 0, dsrl32_op), RT | RD | RE},
|
[insn_drotr32] = {M(spec_op, 1, 0, 0, 0, dsrl32_op), RT | RD | RE},
|
||||||
@ -150,6 +150,8 @@ static const struct insn insn_table[insn_invalid] = {
|
|||||||
[insn_mtlo] = {M(spec_op, 0, 0, 0, 0, mtlo_op), RS},
|
[insn_mtlo] = {M(spec_op, 0, 0, 0, 0, mtlo_op), RS},
|
||||||
[insn_mulu] = {M(spec_op, 0, 0, 0, multu_mulu_op, multu_op),
|
[insn_mulu] = {M(spec_op, 0, 0, 0, multu_mulu_op, multu_op),
|
||||||
RS | RT | RD},
|
RS | RT | RD},
|
||||||
|
[insn_muhu] = {M(spec_op, 0, 0, 0, multu_muhu_op, multu_op),
|
||||||
|
RS | RT | RD},
|
||||||
#ifndef CONFIG_CPU_MIPSR6
|
#ifndef CONFIG_CPU_MIPSR6
|
||||||
[insn_mul] = {M(spec2_op, 0, 0, 0, 0, mul_op), RS | RT | RD},
|
[insn_mul] = {M(spec2_op, 0, 0, 0, 0, mul_op), RS | RT | RD},
|
||||||
#else
|
#else
|
||||||
|
@ -59,7 +59,7 @@ enum opcode {
|
|||||||
insn_lddir, insn_ldpte, insn_ldx, insn_lh, insn_lhu, insn_ll, insn_lld,
|
insn_lddir, insn_ldpte, insn_ldx, insn_lh, insn_lhu, insn_ll, insn_lld,
|
||||||
insn_lui, insn_lw, insn_lwu, insn_lwx, insn_mfc0, insn_mfhc0, insn_mfhi,
|
insn_lui, insn_lw, insn_lwu, insn_lwx, insn_mfc0, insn_mfhc0, insn_mfhi,
|
||||||
insn_mflo, insn_modu, insn_movn, insn_movz, insn_mtc0, insn_mthc0,
|
insn_mflo, insn_modu, insn_movn, insn_movz, insn_mtc0, insn_mthc0,
|
||||||
insn_mthi, insn_mtlo, insn_mul, insn_multu, insn_mulu, insn_nor,
|
insn_mthi, insn_mtlo, insn_mul, insn_multu, insn_mulu, insn_muhu, insn_nor,
|
||||||
insn_or, insn_ori, insn_pref, insn_rfe, insn_rotr, insn_sb, insn_sc,
|
insn_or, insn_ori, insn_pref, insn_rfe, insn_rotr, insn_sb, insn_sc,
|
||||||
insn_scd, insn_seleqz, insn_selnez, insn_sd, insn_sh, insn_sll,
|
insn_scd, insn_seleqz, insn_selnez, insn_sd, insn_sh, insn_sll,
|
||||||
insn_sllv, insn_slt, insn_slti, insn_sltiu, insn_sltu, insn_sra,
|
insn_sllv, insn_slt, insn_slti, insn_sltiu, insn_sltu, insn_sra,
|
||||||
@ -344,6 +344,7 @@ I_u1(_mtlo)
|
|||||||
I_u3u1u2(_mul)
|
I_u3u1u2(_mul)
|
||||||
I_u1u2(_multu)
|
I_u1u2(_multu)
|
||||||
I_u3u1u2(_mulu)
|
I_u3u1u2(_mulu)
|
||||||
|
I_u3u1u2(_muhu)
|
||||||
I_u3u1u2(_nor)
|
I_u3u1u2(_nor)
|
||||||
I_u3u1u2(_or)
|
I_u3u1u2(_or)
|
||||||
I_u2u1u3(_ori)
|
I_u2u1u3(_ori)
|
||||||
|
@ -1,5 +1,10 @@
|
|||||||
# SPDX-License-Identifier: GPL-2.0-only
|
# SPDX-License-Identifier: GPL-2.0-only
|
||||||
# MIPS networking code
|
# MIPS networking code
|
||||||
|
|
||||||
obj-$(CONFIG_MIPS_CBPF_JIT) += bpf_jit.o bpf_jit_asm.o
|
obj-$(CONFIG_BPF_JIT) += bpf_jit_comp.o
|
||||||
obj-$(CONFIG_MIPS_EBPF_JIT) += ebpf_jit.o
|
|
||||||
|
ifeq ($(CONFIG_32BIT),y)
|
||||||
|
obj-$(CONFIG_BPF_JIT) += bpf_jit_comp32.o
|
||||||
|
else
|
||||||
|
obj-$(CONFIG_BPF_JIT) += bpf_jit_comp64.o
|
||||||
|
endif
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -1,81 +0,0 @@
|
|||||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
|
||||||
/*
|
|
||||||
* Just-In-Time compiler for BPF filters on MIPS
|
|
||||||
*
|
|
||||||
* Copyright (c) 2014 Imagination Technologies Ltd.
|
|
||||||
* Author: Markos Chandras <markos.chandras@imgtec.com>
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef BPF_JIT_MIPS_OP_H
|
|
||||||
#define BPF_JIT_MIPS_OP_H
|
|
||||||
|
|
||||||
/* Registers used by JIT */
|
|
||||||
#define MIPS_R_ZERO 0
|
|
||||||
#define MIPS_R_V0 2
|
|
||||||
#define MIPS_R_A0 4
|
|
||||||
#define MIPS_R_A1 5
|
|
||||||
#define MIPS_R_T4 12
|
|
||||||
#define MIPS_R_T5 13
|
|
||||||
#define MIPS_R_T6 14
|
|
||||||
#define MIPS_R_T7 15
|
|
||||||
#define MIPS_R_S0 16
|
|
||||||
#define MIPS_R_S1 17
|
|
||||||
#define MIPS_R_S2 18
|
|
||||||
#define MIPS_R_S3 19
|
|
||||||
#define MIPS_R_S4 20
|
|
||||||
#define MIPS_R_S5 21
|
|
||||||
#define MIPS_R_S6 22
|
|
||||||
#define MIPS_R_S7 23
|
|
||||||
#define MIPS_R_SP 29
|
|
||||||
#define MIPS_R_RA 31
|
|
||||||
|
|
||||||
/* Conditional codes */
|
|
||||||
#define MIPS_COND_EQ 0x1
|
|
||||||
#define MIPS_COND_GE (0x1 << 1)
|
|
||||||
#define MIPS_COND_GT (0x1 << 2)
|
|
||||||
#define MIPS_COND_NE (0x1 << 3)
|
|
||||||
#define MIPS_COND_ALL (0x1 << 4)
|
|
||||||
/* Conditionals on X register or K immediate */
|
|
||||||
#define MIPS_COND_X (0x1 << 5)
|
|
||||||
#define MIPS_COND_K (0x1 << 6)
|
|
||||||
|
|
||||||
#define r_ret MIPS_R_V0
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Use 2 scratch registers to avoid pipeline interlocks.
|
|
||||||
* There is no overhead during epilogue and prologue since
|
|
||||||
* any of the $s0-$s6 registers will only be preserved if
|
|
||||||
* they are going to actually be used.
|
|
||||||
*/
|
|
||||||
#define r_skb_hl MIPS_R_S0 /* skb header length */
|
|
||||||
#define r_skb_data MIPS_R_S1 /* skb actual data */
|
|
||||||
#define r_off MIPS_R_S2
|
|
||||||
#define r_A MIPS_R_S3
|
|
||||||
#define r_X MIPS_R_S4
|
|
||||||
#define r_skb MIPS_R_S5
|
|
||||||
#define r_M MIPS_R_S6
|
|
||||||
#define r_skb_len MIPS_R_S7
|
|
||||||
#define r_s0 MIPS_R_T4 /* scratch reg 1 */
|
|
||||||
#define r_s1 MIPS_R_T5 /* scratch reg 2 */
|
|
||||||
#define r_tmp_imm MIPS_R_T6 /* No need to preserve this */
|
|
||||||
#define r_tmp MIPS_R_T7 /* No need to preserve this */
|
|
||||||
#define r_zero MIPS_R_ZERO
|
|
||||||
#define r_sp MIPS_R_SP
|
|
||||||
#define r_ra MIPS_R_RA
|
|
||||||
|
|
||||||
#ifndef __ASSEMBLY__
|
|
||||||
|
|
||||||
/* Declare ASM helpers */
|
|
||||||
|
|
||||||
#define DECLARE_LOAD_FUNC(func) \
|
|
||||||
extern u8 func(unsigned long *skb, int offset); \
|
|
||||||
extern u8 func##_negative(unsigned long *skb, int offset); \
|
|
||||||
extern u8 func##_positive(unsigned long *skb, int offset)
|
|
||||||
|
|
||||||
DECLARE_LOAD_FUNC(sk_load_word);
|
|
||||||
DECLARE_LOAD_FUNC(sk_load_half);
|
|
||||||
DECLARE_LOAD_FUNC(sk_load_byte);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* BPF_JIT_MIPS_OP_H */
|
|
@ -1,285 +0,0 @@
|
|||||||
/*
|
|
||||||
* bpf_jib_asm.S: Packet/header access helper functions for MIPS/MIPS64 BPF
|
|
||||||
* compiler.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2015 Imagination Technologies Ltd.
|
|
||||||
* Author: Markos Chandras <markos.chandras@imgtec.com>
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
|
||||||
* under the terms of the GNU General Public License as published by the
|
|
||||||
* Free Software Foundation; version 2 of the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <asm/asm.h>
|
|
||||||
#include <asm/isa-rev.h>
|
|
||||||
#include <asm/regdef.h>
|
|
||||||
#include "bpf_jit.h"
|
|
||||||
|
|
||||||
/* ABI
|
|
||||||
*
|
|
||||||
* r_skb_hl skb header length
|
|
||||||
* r_skb_data skb data
|
|
||||||
* r_off(a1) offset register
|
|
||||||
* r_A BPF register A
|
|
||||||
* r_X PF register X
|
|
||||||
* r_skb(a0) *skb
|
|
||||||
* r_M *scratch memory
|
|
||||||
* r_skb_le skb length
|
|
||||||
* r_s0 Scratch register 0
|
|
||||||
* r_s1 Scratch register 1
|
|
||||||
*
|
|
||||||
* On entry:
|
|
||||||
* a0: *skb
|
|
||||||
* a1: offset (imm or imm + X)
|
|
||||||
*
|
|
||||||
* All non-BPF-ABI registers are free for use. On return, we only
|
|
||||||
* care about r_ret. The BPF-ABI registers are assumed to remain
|
|
||||||
* unmodified during the entire filter operation.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define skb a0
|
|
||||||
#define offset a1
|
|
||||||
#define SKF_LL_OFF (-0x200000) /* Can't include linux/filter.h in assembly */
|
|
||||||
|
|
||||||
/* We know better :) so prevent assembler reordering etc */
|
|
||||||
.set noreorder
|
|
||||||
|
|
||||||
#define is_offset_negative(TYPE) \
|
|
||||||
/* If offset is negative we have more work to do */ \
|
|
||||||
slti t0, offset, 0; \
|
|
||||||
bgtz t0, bpf_slow_path_##TYPE##_neg; \
|
|
||||||
/* Be careful what follows in DS. */
|
|
||||||
|
|
||||||
#define is_offset_in_header(SIZE, TYPE) \
|
|
||||||
/* Reading from header? */ \
|
|
||||||
addiu $r_s0, $r_skb_hl, -SIZE; \
|
|
||||||
slt t0, $r_s0, offset; \
|
|
||||||
bgtz t0, bpf_slow_path_##TYPE; \
|
|
||||||
|
|
||||||
LEAF(sk_load_word)
|
|
||||||
is_offset_negative(word)
|
|
||||||
FEXPORT(sk_load_word_positive)
|
|
||||||
is_offset_in_header(4, word)
|
|
||||||
/* Offset within header boundaries */
|
|
||||||
PTR_ADDU t1, $r_skb_data, offset
|
|
||||||
.set reorder
|
|
||||||
lw $r_A, 0(t1)
|
|
||||||
.set noreorder
|
|
||||||
#ifdef CONFIG_CPU_LITTLE_ENDIAN
|
|
||||||
# if MIPS_ISA_REV >= 2
|
|
||||||
wsbh t0, $r_A
|
|
||||||
rotr $r_A, t0, 16
|
|
||||||
# else
|
|
||||||
sll t0, $r_A, 24
|
|
||||||
srl t1, $r_A, 24
|
|
||||||
srl t2, $r_A, 8
|
|
||||||
or t0, t0, t1
|
|
||||||
andi t2, t2, 0xff00
|
|
||||||
andi t1, $r_A, 0xff00
|
|
||||||
or t0, t0, t2
|
|
||||||
sll t1, t1, 8
|
|
||||||
or $r_A, t0, t1
|
|
||||||
# endif
|
|
||||||
#endif
|
|
||||||
jr $r_ra
|
|
||||||
move $r_ret, zero
|
|
||||||
END(sk_load_word)
|
|
||||||
|
|
||||||
LEAF(sk_load_half)
|
|
||||||
is_offset_negative(half)
|
|
||||||
FEXPORT(sk_load_half_positive)
|
|
||||||
is_offset_in_header(2, half)
|
|
||||||
/* Offset within header boundaries */
|
|
||||||
PTR_ADDU t1, $r_skb_data, offset
|
|
||||||
lhu $r_A, 0(t1)
|
|
||||||
#ifdef CONFIG_CPU_LITTLE_ENDIAN
|
|
||||||
# if MIPS_ISA_REV >= 2
|
|
||||||
wsbh $r_A, $r_A
|
|
||||||
# else
|
|
||||||
sll t0, $r_A, 8
|
|
||||||
srl t1, $r_A, 8
|
|
||||||
andi t0, t0, 0xff00
|
|
||||||
or $r_A, t0, t1
|
|
||||||
# endif
|
|
||||||
#endif
|
|
||||||
jr $r_ra
|
|
||||||
move $r_ret, zero
|
|
||||||
END(sk_load_half)
|
|
||||||
|
|
||||||
LEAF(sk_load_byte)
|
|
||||||
is_offset_negative(byte)
|
|
||||||
FEXPORT(sk_load_byte_positive)
|
|
||||||
is_offset_in_header(1, byte)
|
|
||||||
/* Offset within header boundaries */
|
|
||||||
PTR_ADDU t1, $r_skb_data, offset
|
|
||||||
lbu $r_A, 0(t1)
|
|
||||||
jr $r_ra
|
|
||||||
move $r_ret, zero
|
|
||||||
END(sk_load_byte)
|
|
||||||
|
|
||||||
/*
|
|
||||||
* call skb_copy_bits:
|
|
||||||
* (prototype in linux/skbuff.h)
|
|
||||||
*
|
|
||||||
* int skb_copy_bits(sk_buff *skb, int offset, void *to, int len)
|
|
||||||
*
|
|
||||||
* o32 mandates we leave 4 spaces for argument registers in case
|
|
||||||
* the callee needs to use them. Even though we don't care about
|
|
||||||
* the argument registers ourselves, we need to allocate that space
|
|
||||||
* to remain ABI compliant since the callee may want to use that space.
|
|
||||||
* We also allocate 2 more spaces for $r_ra and our return register (*to).
|
|
||||||
*
|
|
||||||
* n64 is a bit different. The *caller* will allocate the space to preserve
|
|
||||||
* the arguments. So in 64-bit kernels, we allocate the 4-arg space for no
|
|
||||||
* good reason but it does not matter that much really.
|
|
||||||
*
|
|
||||||
* (void *to) is returned in r_s0
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
#ifdef CONFIG_CPU_LITTLE_ENDIAN
|
|
||||||
#define DS_OFFSET(SIZE) (4 * SZREG)
|
|
||||||
#else
|
|
||||||
#define DS_OFFSET(SIZE) ((4 * SZREG) + (4 - SIZE))
|
|
||||||
#endif
|
|
||||||
#define bpf_slow_path_common(SIZE) \
|
|
||||||
/* Quick check. Are we within reasonable boundaries? */ \
|
|
||||||
LONG_ADDIU $r_s1, $r_skb_len, -SIZE; \
|
|
||||||
sltu $r_s0, offset, $r_s1; \
|
|
||||||
beqz $r_s0, fault; \
|
|
||||||
/* Load 4th argument in DS */ \
|
|
||||||
LONG_ADDIU a3, zero, SIZE; \
|
|
||||||
PTR_ADDIU $r_sp, $r_sp, -(6 * SZREG); \
|
|
||||||
PTR_LA t0, skb_copy_bits; \
|
|
||||||
PTR_S $r_ra, (5 * SZREG)($r_sp); \
|
|
||||||
/* Assign low slot to a2 */ \
|
|
||||||
PTR_ADDIU a2, $r_sp, DS_OFFSET(SIZE); \
|
|
||||||
jalr t0; \
|
|
||||||
/* Reset our destination slot (DS but it's ok) */ \
|
|
||||||
INT_S zero, (4 * SZREG)($r_sp); \
|
|
||||||
/* \
|
|
||||||
* skb_copy_bits returns 0 on success and -EFAULT \
|
|
||||||
* on error. Our data live in a2. Do not bother with \
|
|
||||||
* our data if an error has been returned. \
|
|
||||||
*/ \
|
|
||||||
/* Restore our frame */ \
|
|
||||||
PTR_L $r_ra, (5 * SZREG)($r_sp); \
|
|
||||||
INT_L $r_s0, (4 * SZREG)($r_sp); \
|
|
||||||
bltz v0, fault; \
|
|
||||||
PTR_ADDIU $r_sp, $r_sp, 6 * SZREG; \
|
|
||||||
move $r_ret, zero; \
|
|
||||||
|
|
||||||
NESTED(bpf_slow_path_word, (6 * SZREG), $r_sp)
|
|
||||||
bpf_slow_path_common(4)
|
|
||||||
#ifdef CONFIG_CPU_LITTLE_ENDIAN
|
|
||||||
# if MIPS_ISA_REV >= 2
|
|
||||||
wsbh t0, $r_s0
|
|
||||||
jr $r_ra
|
|
||||||
rotr $r_A, t0, 16
|
|
||||||
# else
|
|
||||||
sll t0, $r_s0, 24
|
|
||||||
srl t1, $r_s0, 24
|
|
||||||
srl t2, $r_s0, 8
|
|
||||||
or t0, t0, t1
|
|
||||||
andi t2, t2, 0xff00
|
|
||||||
andi t1, $r_s0, 0xff00
|
|
||||||
or t0, t0, t2
|
|
||||||
sll t1, t1, 8
|
|
||||||
jr $r_ra
|
|
||||||
or $r_A, t0, t1
|
|
||||||
# endif
|
|
||||||
#else
|
|
||||||
jr $r_ra
|
|
||||||
move $r_A, $r_s0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
END(bpf_slow_path_word)
|
|
||||||
|
|
||||||
NESTED(bpf_slow_path_half, (6 * SZREG), $r_sp)
|
|
||||||
bpf_slow_path_common(2)
|
|
||||||
#ifdef CONFIG_CPU_LITTLE_ENDIAN
|
|
||||||
# if MIPS_ISA_REV >= 2
|
|
||||||
jr $r_ra
|
|
||||||
wsbh $r_A, $r_s0
|
|
||||||
# else
|
|
||||||
sll t0, $r_s0, 8
|
|
||||||
andi t1, $r_s0, 0xff00
|
|
||||||
andi t0, t0, 0xff00
|
|
||||||
srl t1, t1, 8
|
|
||||||
jr $r_ra
|
|
||||||
or $r_A, t0, t1
|
|
||||||
# endif
|
|
||||||
#else
|
|
||||||
jr $r_ra
|
|
||||||
move $r_A, $r_s0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
END(bpf_slow_path_half)
|
|
||||||
|
|
||||||
NESTED(bpf_slow_path_byte, (6 * SZREG), $r_sp)
|
|
||||||
bpf_slow_path_common(1)
|
|
||||||
jr $r_ra
|
|
||||||
move $r_A, $r_s0
|
|
||||||
|
|
||||||
END(bpf_slow_path_byte)
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Negative entry points
|
|
||||||
*/
|
|
||||||
.macro bpf_is_end_of_data
|
|
||||||
li t0, SKF_LL_OFF
|
|
||||||
/* Reading link layer data? */
|
|
||||||
slt t1, offset, t0
|
|
||||||
bgtz t1, fault
|
|
||||||
/* Be careful what follows in DS. */
|
|
||||||
.endm
|
|
||||||
/*
|
|
||||||
* call skb_copy_bits:
|
|
||||||
* (prototype in linux/filter.h)
|
|
||||||
*
|
|
||||||
* void *bpf_internal_load_pointer_neg_helper(const struct sk_buff *skb,
|
|
||||||
* int k, unsigned int size)
|
|
||||||
*
|
|
||||||
* see above (bpf_slow_path_common) for ABI restrictions
|
|
||||||
*/
|
|
||||||
#define bpf_negative_common(SIZE) \
|
|
||||||
PTR_ADDIU $r_sp, $r_sp, -(6 * SZREG); \
|
|
||||||
PTR_LA t0, bpf_internal_load_pointer_neg_helper; \
|
|
||||||
PTR_S $r_ra, (5 * SZREG)($r_sp); \
|
|
||||||
jalr t0; \
|
|
||||||
li a2, SIZE; \
|
|
||||||
PTR_L $r_ra, (5 * SZREG)($r_sp); \
|
|
||||||
/* Check return pointer */ \
|
|
||||||
beqz v0, fault; \
|
|
||||||
PTR_ADDIU $r_sp, $r_sp, 6 * SZREG; \
|
|
||||||
/* Preserve our pointer */ \
|
|
||||||
move $r_s0, v0; \
|
|
||||||
/* Set return value */ \
|
|
||||||
move $r_ret, zero; \
|
|
||||||
|
|
||||||
bpf_slow_path_word_neg:
|
|
||||||
bpf_is_end_of_data
|
|
||||||
NESTED(sk_load_word_negative, (6 * SZREG), $r_sp)
|
|
||||||
bpf_negative_common(4)
|
|
||||||
jr $r_ra
|
|
||||||
lw $r_A, 0($r_s0)
|
|
||||||
END(sk_load_word_negative)
|
|
||||||
|
|
||||||
bpf_slow_path_half_neg:
|
|
||||||
bpf_is_end_of_data
|
|
||||||
NESTED(sk_load_half_negative, (6 * SZREG), $r_sp)
|
|
||||||
bpf_negative_common(2)
|
|
||||||
jr $r_ra
|
|
||||||
lhu $r_A, 0($r_s0)
|
|
||||||
END(sk_load_half_negative)
|
|
||||||
|
|
||||||
bpf_slow_path_byte_neg:
|
|
||||||
bpf_is_end_of_data
|
|
||||||
NESTED(sk_load_byte_negative, (6 * SZREG), $r_sp)
|
|
||||||
bpf_negative_common(1)
|
|
||||||
jr $r_ra
|
|
||||||
lbu $r_A, 0($r_s0)
|
|
||||||
END(sk_load_byte_negative)
|
|
||||||
|
|
||||||
fault:
|
|
||||||
jr $r_ra
|
|
||||||
addiu $r_ret, zero, 1
|
|
1034
arch/mips/net/bpf_jit_comp.c
Normal file
1034
arch/mips/net/bpf_jit_comp.c
Normal file
File diff suppressed because it is too large
Load Diff
235
arch/mips/net/bpf_jit_comp.h
Normal file
235
arch/mips/net/bpf_jit_comp.h
Normal file
@ -0,0 +1,235 @@
|
|||||||
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
|
/*
|
||||||
|
* Just-In-Time compiler for eBPF bytecode on 32-bit and 64-bit MIPS.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2021 Anyfi Networks AB.
|
||||||
|
* Author: Johan Almbladh <johan.almbladh@gmail.com>
|
||||||
|
*
|
||||||
|
* Based on code and ideas from
|
||||||
|
* Copyright (c) 2017 Cavium, Inc.
|
||||||
|
* Copyright (c) 2017 Shubham Bansal <illusionist.neo@gmail.com>
|
||||||
|
* Copyright (c) 2011 Mircea Gherzan <mgherzan@gmail.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _BPF_JIT_COMP_H
|
||||||
|
#define _BPF_JIT_COMP_H
|
||||||
|
|
||||||
|
/* MIPS registers */
|
||||||
|
#define MIPS_R_ZERO 0 /* Const zero */
|
||||||
|
#define MIPS_R_AT 1 /* Asm temp */
|
||||||
|
#define MIPS_R_V0 2 /* Result */
|
||||||
|
#define MIPS_R_V1 3 /* Result */
|
||||||
|
#define MIPS_R_A0 4 /* Argument */
|
||||||
|
#define MIPS_R_A1 5 /* Argument */
|
||||||
|
#define MIPS_R_A2 6 /* Argument */
|
||||||
|
#define MIPS_R_A3 7 /* Argument */
|
||||||
|
#define MIPS_R_A4 8 /* Arg (n64) */
|
||||||
|
#define MIPS_R_A5 9 /* Arg (n64) */
|
||||||
|
#define MIPS_R_A6 10 /* Arg (n64) */
|
||||||
|
#define MIPS_R_A7 11 /* Arg (n64) */
|
||||||
|
#define MIPS_R_T0 8 /* Temp (o32) */
|
||||||
|
#define MIPS_R_T1 9 /* Temp (o32) */
|
||||||
|
#define MIPS_R_T2 10 /* Temp (o32) */
|
||||||
|
#define MIPS_R_T3 11 /* Temp (o32) */
|
||||||
|
#define MIPS_R_T4 12 /* Temporary */
|
||||||
|
#define MIPS_R_T5 13 /* Temporary */
|
||||||
|
#define MIPS_R_T6 14 /* Temporary */
|
||||||
|
#define MIPS_R_T7 15 /* Temporary */
|
||||||
|
#define MIPS_R_S0 16 /* Saved */
|
||||||
|
#define MIPS_R_S1 17 /* Saved */
|
||||||
|
#define MIPS_R_S2 18 /* Saved */
|
||||||
|
#define MIPS_R_S3 19 /* Saved */
|
||||||
|
#define MIPS_R_S4 20 /* Saved */
|
||||||
|
#define MIPS_R_S5 21 /* Saved */
|
||||||
|
#define MIPS_R_S6 22 /* Saved */
|
||||||
|
#define MIPS_R_S7 23 /* Saved */
|
||||||
|
#define MIPS_R_T8 24 /* Temporary */
|
||||||
|
#define MIPS_R_T9 25 /* Temporary */
|
||||||
|
/* MIPS_R_K0 26 Reserved */
|
||||||
|
/* MIPS_R_K1 27 Reserved */
|
||||||
|
#define MIPS_R_GP 28 /* Global ptr */
|
||||||
|
#define MIPS_R_SP 29 /* Stack ptr */
|
||||||
|
#define MIPS_R_FP 30 /* Frame ptr */
|
||||||
|
#define MIPS_R_RA 31 /* Return */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Jump address mask for immediate jumps. The four most significant bits
|
||||||
|
* must be equal to PC.
|
||||||
|
*/
|
||||||
|
#define MIPS_JMP_MASK 0x0fffffffUL
|
||||||
|
|
||||||
|
/* Maximum number of iterations in offset table computation */
|
||||||
|
#define JIT_MAX_ITERATIONS 8
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Jump pseudo-instructions used internally
|
||||||
|
* for branch conversion and branch optimization.
|
||||||
|
*/
|
||||||
|
#define JIT_JNSET 0xe0
|
||||||
|
#define JIT_JNOP 0xf0
|
||||||
|
|
||||||
|
/* Descriptor flag for PC-relative branch conversion */
|
||||||
|
#define JIT_DESC_CONVERT BIT(31)
|
||||||
|
|
||||||
|
/* JIT context for an eBPF program */
|
||||||
|
struct jit_context {
|
||||||
|
struct bpf_prog *program; /* The eBPF program being JITed */
|
||||||
|
u32 *descriptors; /* eBPF to JITed CPU insn descriptors */
|
||||||
|
u32 *target; /* JITed code buffer */
|
||||||
|
u32 bpf_index; /* Index of current BPF program insn */
|
||||||
|
u32 jit_index; /* Index of current JIT target insn */
|
||||||
|
u32 changes; /* Number of PC-relative branch conv */
|
||||||
|
u32 accessed; /* Bit mask of read eBPF registers */
|
||||||
|
u32 clobbered; /* Bit mask of modified CPU registers */
|
||||||
|
u32 stack_size; /* Total allocated stack size in bytes */
|
||||||
|
u32 saved_size; /* Size of callee-saved registers */
|
||||||
|
u32 stack_used; /* Stack size used for function calls */
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Emit the instruction if the JIT memory space has been allocated */
|
||||||
|
#define __emit(ctx, func, ...) \
|
||||||
|
do { \
|
||||||
|
if ((ctx)->target != NULL) { \
|
||||||
|
u32 *p = &(ctx)->target[ctx->jit_index]; \
|
||||||
|
uasm_i_##func(&p, ##__VA_ARGS__); \
|
||||||
|
} \
|
||||||
|
(ctx)->jit_index++; \
|
||||||
|
} while (0)
|
||||||
|
#define emit(...) __emit(__VA_ARGS__)
|
||||||
|
|
||||||
|
/* Workaround for R10000 ll/sc errata */
|
||||||
|
#ifdef CONFIG_WAR_R10000
|
||||||
|
#define LLSC_beqz beqzl
|
||||||
|
#else
|
||||||
|
#define LLSC_beqz beqz
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Workaround for Loongson-3 ll/sc errata */
|
||||||
|
#ifdef CONFIG_CPU_LOONGSON3_WORKAROUNDS
|
||||||
|
#define LLSC_sync(ctx) emit(ctx, sync, 0)
|
||||||
|
#define LLSC_offset 4
|
||||||
|
#else
|
||||||
|
#define LLSC_sync(ctx)
|
||||||
|
#define LLSC_offset 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Workaround for Loongson-2F jump errata */
|
||||||
|
#ifdef CONFIG_CPU_JUMP_WORKAROUNDS
|
||||||
|
#define JALR_MASK 0xffffffffcfffffffULL
|
||||||
|
#else
|
||||||
|
#define JALR_MASK (~0ULL)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Mark a BPF register as accessed, it needs to be
|
||||||
|
* initialized by the program if expected, e.g. FP.
|
||||||
|
*/
|
||||||
|
static inline void access_reg(struct jit_context *ctx, u8 reg)
|
||||||
|
{
|
||||||
|
ctx->accessed |= BIT(reg);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Mark a CPU register as clobbered, it needs to be
|
||||||
|
* saved/restored by the program if callee-saved.
|
||||||
|
*/
|
||||||
|
static inline void clobber_reg(struct jit_context *ctx, u8 reg)
|
||||||
|
{
|
||||||
|
ctx->clobbered |= BIT(reg);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Push registers on the stack, starting at a given depth from the stack
|
||||||
|
* pointer and increasing. The next depth to be written is returned.
|
||||||
|
*/
|
||||||
|
int push_regs(struct jit_context *ctx, u32 mask, u32 excl, int depth);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Pop registers from the stack, starting at a given depth from the stack
|
||||||
|
* pointer and increasing. The next depth to be read is returned.
|
||||||
|
*/
|
||||||
|
int pop_regs(struct jit_context *ctx, u32 mask, u32 excl, int depth);
|
||||||
|
|
||||||
|
/* Compute the 28-bit jump target address from a BPF program location */
|
||||||
|
int get_target(struct jit_context *ctx, u32 loc);
|
||||||
|
|
||||||
|
/* Compute the PC-relative offset to relative BPF program offset */
|
||||||
|
int get_offset(const struct jit_context *ctx, int off);
|
||||||
|
|
||||||
|
/* dst = imm (32-bit) */
|
||||||
|
void emit_mov_i(struct jit_context *ctx, u8 dst, s32 imm);
|
||||||
|
|
||||||
|
/* dst = src (32-bit) */
|
||||||
|
void emit_mov_r(struct jit_context *ctx, u8 dst, u8 src);
|
||||||
|
|
||||||
|
/* Validate ALU/ALU64 immediate range */
|
||||||
|
bool valid_alu_i(u8 op, s32 imm);
|
||||||
|
|
||||||
|
/* Rewrite ALU/ALU64 immediate operation */
|
||||||
|
bool rewrite_alu_i(u8 op, s32 imm, u8 *alu, s32 *val);
|
||||||
|
|
||||||
|
/* ALU immediate operation (32-bit) */
|
||||||
|
void emit_alu_i(struct jit_context *ctx, u8 dst, s32 imm, u8 op);
|
||||||
|
|
||||||
|
/* ALU register operation (32-bit) */
|
||||||
|
void emit_alu_r(struct jit_context *ctx, u8 dst, u8 src, u8 op);
|
||||||
|
|
||||||
|
/* Atomic read-modify-write (32-bit) */
|
||||||
|
void emit_atomic_r(struct jit_context *ctx, u8 dst, u8 src, s16 off, u8 code);
|
||||||
|
|
||||||
|
/* Atomic compare-and-exchange (32-bit) */
|
||||||
|
void emit_cmpxchg_r(struct jit_context *ctx, u8 dst, u8 src, u8 res, s16 off);
|
||||||
|
|
||||||
|
/* Swap bytes and truncate a register word or half word */
|
||||||
|
void emit_bswap_r(struct jit_context *ctx, u8 dst, u32 width);
|
||||||
|
|
||||||
|
/* Validate JMP/JMP32 immediate range */
|
||||||
|
bool valid_jmp_i(u8 op, s32 imm);
|
||||||
|
|
||||||
|
/* Prepare a PC-relative jump operation with immediate conditional */
|
||||||
|
void setup_jmp_i(struct jit_context *ctx, s32 imm, u8 width,
|
||||||
|
u8 bpf_op, s16 bpf_off, u8 *jit_op, s32 *jit_off);
|
||||||
|
|
||||||
|
/* Prepare a PC-relative jump operation with register conditional */
|
||||||
|
void setup_jmp_r(struct jit_context *ctx, bool same_reg,
|
||||||
|
u8 bpf_op, s16 bpf_off, u8 *jit_op, s32 *jit_off);
|
||||||
|
|
||||||
|
/* Finish a PC-relative jump operation */
|
||||||
|
int finish_jmp(struct jit_context *ctx, u8 jit_op, s16 bpf_off);
|
||||||
|
|
||||||
|
/* Conditional JMP/JMP32 immediate */
|
||||||
|
void emit_jmp_i(struct jit_context *ctx, u8 dst, s32 imm, s32 off, u8 op);
|
||||||
|
|
||||||
|
/* Conditional JMP/JMP32 register */
|
||||||
|
void emit_jmp_r(struct jit_context *ctx, u8 dst, u8 src, s32 off, u8 op);
|
||||||
|
|
||||||
|
/* Jump always */
|
||||||
|
int emit_ja(struct jit_context *ctx, s16 off);
|
||||||
|
|
||||||
|
/* Jump to epilogue */
|
||||||
|
int emit_exit(struct jit_context *ctx);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Build program prologue to set up the stack and registers.
|
||||||
|
* This function is implemented separately for 32-bit and 64-bit JITs.
|
||||||
|
*/
|
||||||
|
void build_prologue(struct jit_context *ctx);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Build the program epilogue to restore the stack and registers.
|
||||||
|
* This function is implemented separately for 32-bit and 64-bit JITs.
|
||||||
|
*/
|
||||||
|
void build_epilogue(struct jit_context *ctx, int dest_reg);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Convert an eBPF instruction to native instruction, i.e
|
||||||
|
* JITs an eBPF instruction.
|
||||||
|
* Returns :
|
||||||
|
* 0 - Successfully JITed an 8-byte eBPF instruction
|
||||||
|
* >0 - Successfully JITed a 16-byte eBPF instruction
|
||||||
|
* <0 - Failed to JIT.
|
||||||
|
* This function is implemented separately for 32-bit and 64-bit JITs.
|
||||||
|
*/
|
||||||
|
int build_insn(const struct bpf_insn *insn, struct jit_context *ctx);
|
||||||
|
|
||||||
|
#endif /* _BPF_JIT_COMP_H */
|
1899
arch/mips/net/bpf_jit_comp32.c
Normal file
1899
arch/mips/net/bpf_jit_comp32.c
Normal file
File diff suppressed because it is too large
Load Diff
1060
arch/mips/net/bpf_jit_comp64.c
Normal file
1060
arch/mips/net/bpf_jit_comp64.c
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -123,6 +123,8 @@
|
|||||||
|
|
||||||
#define SO_BUF_LOCK 0x4046
|
#define SO_BUF_LOCK 0x4046
|
||||||
|
|
||||||
|
#define SO_RESERVE_MEM 0x4047
|
||||||
|
|
||||||
#if !defined(__KERNEL__)
|
#if !defined(__KERNEL__)
|
||||||
|
|
||||||
#if __BITS_PER_LONG == 64
|
#if __BITS_PER_LONG == 64
|
||||||
|
@ -11,14 +11,23 @@
|
|||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/uaccess.h>
|
#include <linux/uaccess.h>
|
||||||
|
|
||||||
|
#ifdef CONFIG_BPF_JIT
|
||||||
|
int rv_bpf_fixup_exception(const struct exception_table_entry *ex, struct pt_regs *regs);
|
||||||
|
#endif
|
||||||
|
|
||||||
int fixup_exception(struct pt_regs *regs)
|
int fixup_exception(struct pt_regs *regs)
|
||||||
{
|
{
|
||||||
const struct exception_table_entry *fixup;
|
const struct exception_table_entry *fixup;
|
||||||
|
|
||||||
fixup = search_exception_tables(regs->epc);
|
fixup = search_exception_tables(regs->epc);
|
||||||
if (fixup) {
|
if (!fixup)
|
||||||
regs->epc = fixup->fixup;
|
return 0;
|
||||||
return 1;
|
|
||||||
}
|
#ifdef CONFIG_BPF_JIT
|
||||||
return 0;
|
if (regs->epc >= BPF_JIT_REGION_START && regs->epc < BPF_JIT_REGION_END)
|
||||||
|
return rv_bpf_fixup_exception(fixup, regs);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
regs->epc = fixup->fixup;
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -71,6 +71,7 @@ struct rv_jit_context {
|
|||||||
int ninsns;
|
int ninsns;
|
||||||
int epilogue_offset;
|
int epilogue_offset;
|
||||||
int *offset; /* BPF to RV */
|
int *offset; /* BPF to RV */
|
||||||
|
int nexentries;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
int stack_size;
|
int stack_size;
|
||||||
};
|
};
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <linux/bitfield.h>
|
||||||
#include <linux/bpf.h>
|
#include <linux/bpf.h>
|
||||||
#include <linux/filter.h>
|
#include <linux/filter.h>
|
||||||
#include "bpf_jit.h"
|
#include "bpf_jit.h"
|
||||||
@ -27,6 +28,21 @@ static const int regmap[] = {
|
|||||||
[BPF_REG_AX] = RV_REG_T0,
|
[BPF_REG_AX] = RV_REG_T0,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const int pt_regmap[] = {
|
||||||
|
[RV_REG_A0] = offsetof(struct pt_regs, a0),
|
||||||
|
[RV_REG_A1] = offsetof(struct pt_regs, a1),
|
||||||
|
[RV_REG_A2] = offsetof(struct pt_regs, a2),
|
||||||
|
[RV_REG_A3] = offsetof(struct pt_regs, a3),
|
||||||
|
[RV_REG_A4] = offsetof(struct pt_regs, a4),
|
||||||
|
[RV_REG_A5] = offsetof(struct pt_regs, a5),
|
||||||
|
[RV_REG_S1] = offsetof(struct pt_regs, s1),
|
||||||
|
[RV_REG_S2] = offsetof(struct pt_regs, s2),
|
||||||
|
[RV_REG_S3] = offsetof(struct pt_regs, s3),
|
||||||
|
[RV_REG_S4] = offsetof(struct pt_regs, s4),
|
||||||
|
[RV_REG_S5] = offsetof(struct pt_regs, s5),
|
||||||
|
[RV_REG_T0] = offsetof(struct pt_regs, t0),
|
||||||
|
};
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
RV_CTX_F_SEEN_TAIL_CALL = 0,
|
RV_CTX_F_SEEN_TAIL_CALL = 0,
|
||||||
RV_CTX_F_SEEN_CALL = RV_REG_RA,
|
RV_CTX_F_SEEN_CALL = RV_REG_RA,
|
||||||
@ -440,6 +456,69 @@ static int emit_call(bool fixed, u64 addr, struct rv_jit_context *ctx)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define BPF_FIXUP_OFFSET_MASK GENMASK(26, 0)
|
||||||
|
#define BPF_FIXUP_REG_MASK GENMASK(31, 27)
|
||||||
|
|
||||||
|
int rv_bpf_fixup_exception(const struct exception_table_entry *ex,
|
||||||
|
struct pt_regs *regs)
|
||||||
|
{
|
||||||
|
off_t offset = FIELD_GET(BPF_FIXUP_OFFSET_MASK, ex->fixup);
|
||||||
|
int regs_offset = FIELD_GET(BPF_FIXUP_REG_MASK, ex->fixup);
|
||||||
|
|
||||||
|
*(unsigned long *)((void *)regs + pt_regmap[regs_offset]) = 0;
|
||||||
|
regs->epc = (unsigned long)&ex->fixup - offset;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* For accesses to BTF pointers, add an entry to the exception table */
|
||||||
|
static int add_exception_handler(const struct bpf_insn *insn,
|
||||||
|
struct rv_jit_context *ctx,
|
||||||
|
int dst_reg, int insn_len)
|
||||||
|
{
|
||||||
|
struct exception_table_entry *ex;
|
||||||
|
unsigned long pc;
|
||||||
|
off_t offset;
|
||||||
|
|
||||||
|
if (!ctx->insns || !ctx->prog->aux->extable || BPF_MODE(insn->code) != BPF_PROBE_MEM)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (WARN_ON_ONCE(ctx->nexentries >= ctx->prog->aux->num_exentries))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
if (WARN_ON_ONCE(insn_len > ctx->ninsns))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
if (WARN_ON_ONCE(!rvc_enabled() && insn_len == 1))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
ex = &ctx->prog->aux->extable[ctx->nexentries];
|
||||||
|
pc = (unsigned long)&ctx->insns[ctx->ninsns - insn_len];
|
||||||
|
|
||||||
|
offset = pc - (long)&ex->insn;
|
||||||
|
if (WARN_ON_ONCE(offset >= 0 || offset < INT_MIN))
|
||||||
|
return -ERANGE;
|
||||||
|
ex->insn = pc;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Since the extable follows the program, the fixup offset is always
|
||||||
|
* negative and limited to BPF_JIT_REGION_SIZE. Store a positive value
|
||||||
|
* to keep things simple, and put the destination register in the upper
|
||||||
|
* bits. We don't need to worry about buildtime or runtime sort
|
||||||
|
* modifying the upper bits because the table is already sorted, and
|
||||||
|
* isn't part of the main exception table.
|
||||||
|
*/
|
||||||
|
offset = (long)&ex->fixup - (pc + insn_len * sizeof(u16));
|
||||||
|
if (!FIELD_FIT(BPF_FIXUP_OFFSET_MASK, offset))
|
||||||
|
return -ERANGE;
|
||||||
|
|
||||||
|
ex->fixup = FIELD_PREP(BPF_FIXUP_OFFSET_MASK, offset) |
|
||||||
|
FIELD_PREP(BPF_FIXUP_REG_MASK, dst_reg);
|
||||||
|
|
||||||
|
ctx->nexentries++;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int bpf_jit_emit_insn(const struct bpf_insn *insn, struct rv_jit_context *ctx,
|
int bpf_jit_emit_insn(const struct bpf_insn *insn, struct rv_jit_context *ctx,
|
||||||
bool extra_pass)
|
bool extra_pass)
|
||||||
{
|
{
|
||||||
@ -893,52 +972,86 @@ int bpf_jit_emit_insn(const struct bpf_insn *insn, struct rv_jit_context *ctx,
|
|||||||
|
|
||||||
/* LDX: dst = *(size *)(src + off) */
|
/* LDX: dst = *(size *)(src + off) */
|
||||||
case BPF_LDX | BPF_MEM | BPF_B:
|
case BPF_LDX | BPF_MEM | BPF_B:
|
||||||
if (is_12b_int(off)) {
|
|
||||||
emit(rv_lbu(rd, off, rs), ctx);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
emit_imm(RV_REG_T1, off, ctx);
|
|
||||||
emit_add(RV_REG_T1, RV_REG_T1, rs, ctx);
|
|
||||||
emit(rv_lbu(rd, 0, RV_REG_T1), ctx);
|
|
||||||
if (insn_is_zext(&insn[1]))
|
|
||||||
return 1;
|
|
||||||
break;
|
|
||||||
case BPF_LDX | BPF_MEM | BPF_H:
|
case BPF_LDX | BPF_MEM | BPF_H:
|
||||||
if (is_12b_int(off)) {
|
|
||||||
emit(rv_lhu(rd, off, rs), ctx);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
emit_imm(RV_REG_T1, off, ctx);
|
|
||||||
emit_add(RV_REG_T1, RV_REG_T1, rs, ctx);
|
|
||||||
emit(rv_lhu(rd, 0, RV_REG_T1), ctx);
|
|
||||||
if (insn_is_zext(&insn[1]))
|
|
||||||
return 1;
|
|
||||||
break;
|
|
||||||
case BPF_LDX | BPF_MEM | BPF_W:
|
case BPF_LDX | BPF_MEM | BPF_W:
|
||||||
if (is_12b_int(off)) {
|
|
||||||
emit(rv_lwu(rd, off, rs), ctx);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
emit_imm(RV_REG_T1, off, ctx);
|
|
||||||
emit_add(RV_REG_T1, RV_REG_T1, rs, ctx);
|
|
||||||
emit(rv_lwu(rd, 0, RV_REG_T1), ctx);
|
|
||||||
if (insn_is_zext(&insn[1]))
|
|
||||||
return 1;
|
|
||||||
break;
|
|
||||||
case BPF_LDX | BPF_MEM | BPF_DW:
|
case BPF_LDX | BPF_MEM | BPF_DW:
|
||||||
if (is_12b_int(off)) {
|
case BPF_LDX | BPF_PROBE_MEM | BPF_B:
|
||||||
emit_ld(rd, off, rs, ctx);
|
case BPF_LDX | BPF_PROBE_MEM | BPF_H:
|
||||||
|
case BPF_LDX | BPF_PROBE_MEM | BPF_W:
|
||||||
|
case BPF_LDX | BPF_PROBE_MEM | BPF_DW:
|
||||||
|
{
|
||||||
|
int insn_len, insns_start;
|
||||||
|
|
||||||
|
switch (BPF_SIZE(code)) {
|
||||||
|
case BPF_B:
|
||||||
|
if (is_12b_int(off)) {
|
||||||
|
insns_start = ctx->ninsns;
|
||||||
|
emit(rv_lbu(rd, off, rs), ctx);
|
||||||
|
insn_len = ctx->ninsns - insns_start;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
emit_imm(RV_REG_T1, off, ctx);
|
||||||
|
emit_add(RV_REG_T1, RV_REG_T1, rs, ctx);
|
||||||
|
insns_start = ctx->ninsns;
|
||||||
|
emit(rv_lbu(rd, 0, RV_REG_T1), ctx);
|
||||||
|
insn_len = ctx->ninsns - insns_start;
|
||||||
|
if (insn_is_zext(&insn[1]))
|
||||||
|
return 1;
|
||||||
|
break;
|
||||||
|
case BPF_H:
|
||||||
|
if (is_12b_int(off)) {
|
||||||
|
insns_start = ctx->ninsns;
|
||||||
|
emit(rv_lhu(rd, off, rs), ctx);
|
||||||
|
insn_len = ctx->ninsns - insns_start;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
emit_imm(RV_REG_T1, off, ctx);
|
||||||
|
emit_add(RV_REG_T1, RV_REG_T1, rs, ctx);
|
||||||
|
insns_start = ctx->ninsns;
|
||||||
|
emit(rv_lhu(rd, 0, RV_REG_T1), ctx);
|
||||||
|
insn_len = ctx->ninsns - insns_start;
|
||||||
|
if (insn_is_zext(&insn[1]))
|
||||||
|
return 1;
|
||||||
|
break;
|
||||||
|
case BPF_W:
|
||||||
|
if (is_12b_int(off)) {
|
||||||
|
insns_start = ctx->ninsns;
|
||||||
|
emit(rv_lwu(rd, off, rs), ctx);
|
||||||
|
insn_len = ctx->ninsns - insns_start;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
emit_imm(RV_REG_T1, off, ctx);
|
||||||
|
emit_add(RV_REG_T1, RV_REG_T1, rs, ctx);
|
||||||
|
insns_start = ctx->ninsns;
|
||||||
|
emit(rv_lwu(rd, 0, RV_REG_T1), ctx);
|
||||||
|
insn_len = ctx->ninsns - insns_start;
|
||||||
|
if (insn_is_zext(&insn[1]))
|
||||||
|
return 1;
|
||||||
|
break;
|
||||||
|
case BPF_DW:
|
||||||
|
if (is_12b_int(off)) {
|
||||||
|
insns_start = ctx->ninsns;
|
||||||
|
emit_ld(rd, off, rs, ctx);
|
||||||
|
insn_len = ctx->ninsns - insns_start;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
emit_imm(RV_REG_T1, off, ctx);
|
||||||
|
emit_add(RV_REG_T1, RV_REG_T1, rs, ctx);
|
||||||
|
insns_start = ctx->ninsns;
|
||||||
|
emit_ld(rd, 0, RV_REG_T1, ctx);
|
||||||
|
insn_len = ctx->ninsns - insns_start;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
emit_imm(RV_REG_T1, off, ctx);
|
ret = add_exception_handler(insn, ctx, rd, insn_len);
|
||||||
emit_add(RV_REG_T1, RV_REG_T1, rs, ctx);
|
if (ret)
|
||||||
emit_ld(rd, 0, RV_REG_T1, ctx);
|
return ret;
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
/* speculation barrier */
|
/* speculation barrier */
|
||||||
case BPF_ST | BPF_NOSPEC:
|
case BPF_ST | BPF_NOSPEC:
|
||||||
break;
|
break;
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
#include "bpf_jit.h"
|
#include "bpf_jit.h"
|
||||||
|
|
||||||
/* Number of iterations to try until offsets converge. */
|
/* Number of iterations to try until offsets converge. */
|
||||||
#define NR_JIT_ITERATIONS 16
|
#define NR_JIT_ITERATIONS 32
|
||||||
|
|
||||||
static int build_body(struct rv_jit_context *ctx, bool extra_pass, int *offset)
|
static int build_body(struct rv_jit_context *ctx, bool extra_pass, int *offset)
|
||||||
{
|
{
|
||||||
@ -41,12 +41,12 @@ bool bpf_jit_needs_zext(void)
|
|||||||
|
|
||||||
struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
|
struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
|
||||||
{
|
{
|
||||||
|
unsigned int prog_size = 0, extable_size = 0;
|
||||||
bool tmp_blinded = false, extra_pass = false;
|
bool tmp_blinded = false, extra_pass = false;
|
||||||
struct bpf_prog *tmp, *orig_prog = prog;
|
struct bpf_prog *tmp, *orig_prog = prog;
|
||||||
int pass = 0, prev_ninsns = 0, i;
|
int pass = 0, prev_ninsns = 0, i;
|
||||||
struct rv_jit_data *jit_data;
|
struct rv_jit_data *jit_data;
|
||||||
struct rv_jit_context *ctx;
|
struct rv_jit_context *ctx;
|
||||||
unsigned int image_size = 0;
|
|
||||||
|
|
||||||
if (!prog->jit_requested)
|
if (!prog->jit_requested)
|
||||||
return orig_prog;
|
return orig_prog;
|
||||||
@ -73,7 +73,7 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
|
|||||||
|
|
||||||
if (ctx->offset) {
|
if (ctx->offset) {
|
||||||
extra_pass = true;
|
extra_pass = true;
|
||||||
image_size = sizeof(*ctx->insns) * ctx->ninsns;
|
prog_size = sizeof(*ctx->insns) * ctx->ninsns;
|
||||||
goto skip_init_ctx;
|
goto skip_init_ctx;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -102,10 +102,13 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
|
|||||||
if (ctx->ninsns == prev_ninsns) {
|
if (ctx->ninsns == prev_ninsns) {
|
||||||
if (jit_data->header)
|
if (jit_data->header)
|
||||||
break;
|
break;
|
||||||
|
/* obtain the actual image size */
|
||||||
|
extable_size = prog->aux->num_exentries *
|
||||||
|
sizeof(struct exception_table_entry);
|
||||||
|
prog_size = sizeof(*ctx->insns) * ctx->ninsns;
|
||||||
|
|
||||||
image_size = sizeof(*ctx->insns) * ctx->ninsns;
|
|
||||||
jit_data->header =
|
jit_data->header =
|
||||||
bpf_jit_binary_alloc(image_size,
|
bpf_jit_binary_alloc(prog_size + extable_size,
|
||||||
&jit_data->image,
|
&jit_data->image,
|
||||||
sizeof(u32),
|
sizeof(u32),
|
||||||
bpf_fill_ill_insns);
|
bpf_fill_ill_insns);
|
||||||
@ -131,9 +134,13 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
|
|||||||
goto out_offset;
|
goto out_offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (extable_size)
|
||||||
|
prog->aux->extable = (void *)ctx->insns + prog_size;
|
||||||
|
|
||||||
skip_init_ctx:
|
skip_init_ctx:
|
||||||
pass++;
|
pass++;
|
||||||
ctx->ninsns = 0;
|
ctx->ninsns = 0;
|
||||||
|
ctx->nexentries = 0;
|
||||||
|
|
||||||
bpf_jit_build_prologue(ctx);
|
bpf_jit_build_prologue(ctx);
|
||||||
if (build_body(ctx, extra_pass, NULL)) {
|
if (build_body(ctx, extra_pass, NULL)) {
|
||||||
@ -144,11 +151,11 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
|
|||||||
bpf_jit_build_epilogue(ctx);
|
bpf_jit_build_epilogue(ctx);
|
||||||
|
|
||||||
if (bpf_jit_enable > 1)
|
if (bpf_jit_enable > 1)
|
||||||
bpf_jit_dump(prog->len, image_size, pass, ctx->insns);
|
bpf_jit_dump(prog->len, prog_size, pass, ctx->insns);
|
||||||
|
|
||||||
prog->bpf_func = (void *)ctx->insns;
|
prog->bpf_func = (void *)ctx->insns;
|
||||||
prog->jited = 1;
|
prog->jited = 1;
|
||||||
prog->jited_len = image_size;
|
prog->jited_len = prog_size;
|
||||||
|
|
||||||
bpf_flush_icache(jit_data->header, ctx->insns + ctx->ninsns);
|
bpf_flush_icache(jit_data->header, ctx->insns + ctx->ninsns);
|
||||||
|
|
||||||
|
@ -349,8 +349,6 @@ extern int qdio_allocate(struct ccw_device *cdev, unsigned int no_input_qs,
|
|||||||
extern int qdio_establish(struct ccw_device *cdev,
|
extern int qdio_establish(struct ccw_device *cdev,
|
||||||
struct qdio_initialize *init_data);
|
struct qdio_initialize *init_data);
|
||||||
extern int qdio_activate(struct ccw_device *);
|
extern int qdio_activate(struct ccw_device *);
|
||||||
extern struct qaob *qdio_allocate_aob(void);
|
|
||||||
extern void qdio_release_aob(struct qaob *);
|
|
||||||
extern int do_QDIO(struct ccw_device *cdev, unsigned int callflags, int q_nr,
|
extern int do_QDIO(struct ccw_device *cdev, unsigned int callflags, int q_nr,
|
||||||
unsigned int bufnr, unsigned int count, struct qaob *aob);
|
unsigned int bufnr, unsigned int count, struct qaob *aob);
|
||||||
extern int qdio_start_irq(struct ccw_device *cdev);
|
extern int qdio_start_irq(struct ccw_device *cdev);
|
||||||
|
@ -124,6 +124,9 @@
|
|||||||
|
|
||||||
#define SO_BUF_LOCK 0x0051
|
#define SO_BUF_LOCK 0x0051
|
||||||
|
|
||||||
|
#define SO_RESERVE_MEM 0x0052
|
||||||
|
|
||||||
|
|
||||||
#if !defined(__KERNEL__)
|
#if !defined(__KERNEL__)
|
||||||
|
|
||||||
|
|
||||||
|
@ -276,7 +276,7 @@ static const struct ethtool_ops uml_net_ethtool_ops = {
|
|||||||
|
|
||||||
void uml_net_setup_etheraddr(struct net_device *dev, char *str)
|
void uml_net_setup_etheraddr(struct net_device *dev, char *str)
|
||||||
{
|
{
|
||||||
unsigned char *addr = dev->dev_addr;
|
u8 addr[ETH_ALEN];
|
||||||
char *end;
|
char *end;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
@ -316,6 +316,7 @@ void uml_net_setup_etheraddr(struct net_device *dev, char *str)
|
|||||||
addr[0] | 0x02, addr[1], addr[2], addr[3], addr[4],
|
addr[0] | 0x02, addr[1], addr[2], addr[3], addr[4],
|
||||||
addr[5]);
|
addr[5]);
|
||||||
}
|
}
|
||||||
|
eth_hw_addr_set(dev, addr);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
random:
|
random:
|
||||||
|
@ -2145,19 +2145,19 @@ static __initconst const u64 knl_hw_cache_extra_regs
|
|||||||
* However, there are some cases which may change PEBS status, e.g. PMI
|
* However, there are some cases which may change PEBS status, e.g. PMI
|
||||||
* throttle. The PEBS_ENABLE should be updated where the status changes.
|
* throttle. The PEBS_ENABLE should be updated where the status changes.
|
||||||
*/
|
*/
|
||||||
static void __intel_pmu_disable_all(void)
|
static __always_inline void __intel_pmu_disable_all(bool bts)
|
||||||
{
|
{
|
||||||
struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
|
struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
|
||||||
|
|
||||||
wrmsrl(MSR_CORE_PERF_GLOBAL_CTRL, 0);
|
wrmsrl(MSR_CORE_PERF_GLOBAL_CTRL, 0);
|
||||||
|
|
||||||
if (test_bit(INTEL_PMC_IDX_FIXED_BTS, cpuc->active_mask))
|
if (bts && test_bit(INTEL_PMC_IDX_FIXED_BTS, cpuc->active_mask))
|
||||||
intel_pmu_disable_bts();
|
intel_pmu_disable_bts();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void intel_pmu_disable_all(void)
|
static __always_inline void intel_pmu_disable_all(void)
|
||||||
{
|
{
|
||||||
__intel_pmu_disable_all();
|
__intel_pmu_disable_all(true);
|
||||||
intel_pmu_pebs_disable_all();
|
intel_pmu_pebs_disable_all();
|
||||||
intel_pmu_lbr_disable_all();
|
intel_pmu_lbr_disable_all();
|
||||||
}
|
}
|
||||||
@ -2188,6 +2188,49 @@ static void intel_pmu_enable_all(int added)
|
|||||||
__intel_pmu_enable_all(added, false);
|
__intel_pmu_enable_all(added, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static noinline int
|
||||||
|
__intel_pmu_snapshot_branch_stack(struct perf_branch_entry *entries,
|
||||||
|
unsigned int cnt, unsigned long flags)
|
||||||
|
{
|
||||||
|
struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
|
||||||
|
|
||||||
|
intel_pmu_lbr_read();
|
||||||
|
cnt = min_t(unsigned int, cnt, x86_pmu.lbr_nr);
|
||||||
|
|
||||||
|
memcpy(entries, cpuc->lbr_entries, sizeof(struct perf_branch_entry) * cnt);
|
||||||
|
intel_pmu_enable_all(0);
|
||||||
|
local_irq_restore(flags);
|
||||||
|
return cnt;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
intel_pmu_snapshot_branch_stack(struct perf_branch_entry *entries, unsigned int cnt)
|
||||||
|
{
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
|
/* must not have branches... */
|
||||||
|
local_irq_save(flags);
|
||||||
|
__intel_pmu_disable_all(false); /* we don't care about BTS */
|
||||||
|
__intel_pmu_pebs_disable_all();
|
||||||
|
__intel_pmu_lbr_disable();
|
||||||
|
/* ... until here */
|
||||||
|
return __intel_pmu_snapshot_branch_stack(entries, cnt, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
intel_pmu_snapshot_arch_branch_stack(struct perf_branch_entry *entries, unsigned int cnt)
|
||||||
|
{
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
|
/* must not have branches... */
|
||||||
|
local_irq_save(flags);
|
||||||
|
__intel_pmu_disable_all(false); /* we don't care about BTS */
|
||||||
|
__intel_pmu_pebs_disable_all();
|
||||||
|
__intel_pmu_arch_lbr_disable();
|
||||||
|
/* ... until here */
|
||||||
|
return __intel_pmu_snapshot_branch_stack(entries, cnt, flags);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Workaround for:
|
* Workaround for:
|
||||||
* Intel Errata AAK100 (model 26)
|
* Intel Errata AAK100 (model 26)
|
||||||
@ -2937,7 +2980,7 @@ static int intel_pmu_handle_irq(struct pt_regs *regs)
|
|||||||
apic_write(APIC_LVTPC, APIC_DM_NMI);
|
apic_write(APIC_LVTPC, APIC_DM_NMI);
|
||||||
intel_bts_disable_local();
|
intel_bts_disable_local();
|
||||||
cpuc->enabled = 0;
|
cpuc->enabled = 0;
|
||||||
__intel_pmu_disable_all();
|
__intel_pmu_disable_all(true);
|
||||||
handled = intel_pmu_drain_bts_buffer();
|
handled = intel_pmu_drain_bts_buffer();
|
||||||
handled += intel_bts_interrupt();
|
handled += intel_bts_interrupt();
|
||||||
status = intel_pmu_get_status();
|
status = intel_pmu_get_status();
|
||||||
@ -6299,9 +6342,21 @@ __init int intel_pmu_init(void)
|
|||||||
x86_pmu.lbr_nr = 0;
|
x86_pmu.lbr_nr = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (x86_pmu.lbr_nr)
|
if (x86_pmu.lbr_nr) {
|
||||||
pr_cont("%d-deep LBR, ", x86_pmu.lbr_nr);
|
pr_cont("%d-deep LBR, ", x86_pmu.lbr_nr);
|
||||||
|
|
||||||
|
/* only support branch_stack snapshot for perfmon >= v2 */
|
||||||
|
if (x86_pmu.disable_all == intel_pmu_disable_all) {
|
||||||
|
if (boot_cpu_has(X86_FEATURE_ARCH_LBR)) {
|
||||||
|
static_call_update(perf_snapshot_branch_stack,
|
||||||
|
intel_pmu_snapshot_arch_branch_stack);
|
||||||
|
} else {
|
||||||
|
static_call_update(perf_snapshot_branch_stack,
|
||||||
|
intel_pmu_snapshot_branch_stack);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
intel_pmu_check_extra_regs(x86_pmu.extra_regs);
|
intel_pmu_check_extra_regs(x86_pmu.extra_regs);
|
||||||
|
|
||||||
/* Support full width counters using alternative MSR range */
|
/* Support full width counters using alternative MSR range */
|
||||||
|
@ -1302,7 +1302,7 @@ void intel_pmu_pebs_disable_all(void)
|
|||||||
struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
|
struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
|
||||||
|
|
||||||
if (cpuc->pebs_enabled)
|
if (cpuc->pebs_enabled)
|
||||||
wrmsrl(MSR_IA32_PEBS_ENABLE, 0);
|
__intel_pmu_pebs_disable_all();
|
||||||
}
|
}
|
||||||
|
|
||||||
static int intel_pmu_pebs_fixup_ip(struct pt_regs *regs)
|
static int intel_pmu_pebs_fixup_ip(struct pt_regs *regs)
|
||||||
|
@ -228,20 +228,6 @@ static void __intel_pmu_lbr_enable(bool pmi)
|
|||||||
wrmsrl(MSR_ARCH_LBR_CTL, lbr_select | ARCH_LBR_CTL_LBREN);
|
wrmsrl(MSR_ARCH_LBR_CTL, lbr_select | ARCH_LBR_CTL_LBREN);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __intel_pmu_lbr_disable(void)
|
|
||||||
{
|
|
||||||
u64 debugctl;
|
|
||||||
|
|
||||||
if (static_cpu_has(X86_FEATURE_ARCH_LBR)) {
|
|
||||||
wrmsrl(MSR_ARCH_LBR_CTL, 0);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
rdmsrl(MSR_IA32_DEBUGCTLMSR, debugctl);
|
|
||||||
debugctl &= ~(DEBUGCTLMSR_LBR | DEBUGCTLMSR_FREEZE_LBRS_ON_PMI);
|
|
||||||
wrmsrl(MSR_IA32_DEBUGCTLMSR, debugctl);
|
|
||||||
}
|
|
||||||
|
|
||||||
void intel_pmu_lbr_reset_32(void)
|
void intel_pmu_lbr_reset_32(void)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
@ -779,8 +765,12 @@ void intel_pmu_lbr_disable_all(void)
|
|||||||
{
|
{
|
||||||
struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
|
struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
|
||||||
|
|
||||||
if (cpuc->lbr_users && !vlbr_exclude_host())
|
if (cpuc->lbr_users && !vlbr_exclude_host()) {
|
||||||
|
if (static_cpu_has(X86_FEATURE_ARCH_LBR))
|
||||||
|
return __intel_pmu_arch_lbr_disable();
|
||||||
|
|
||||||
__intel_pmu_lbr_disable();
|
__intel_pmu_lbr_disable();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void intel_pmu_lbr_read_32(struct cpu_hw_events *cpuc)
|
void intel_pmu_lbr_read_32(struct cpu_hw_events *cpuc)
|
||||||
|
@ -1242,6 +1242,25 @@ static inline bool intel_pmu_has_bts(struct perf_event *event)
|
|||||||
return intel_pmu_has_bts_period(event, hwc->sample_period);
|
return intel_pmu_has_bts_period(event, hwc->sample_period);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static __always_inline void __intel_pmu_pebs_disable_all(void)
|
||||||
|
{
|
||||||
|
wrmsrl(MSR_IA32_PEBS_ENABLE, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static __always_inline void __intel_pmu_arch_lbr_disable(void)
|
||||||
|
{
|
||||||
|
wrmsrl(MSR_ARCH_LBR_CTL, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static __always_inline void __intel_pmu_lbr_disable(void)
|
||||||
|
{
|
||||||
|
u64 debugctl;
|
||||||
|
|
||||||
|
rdmsrl(MSR_IA32_DEBUGCTLMSR, debugctl);
|
||||||
|
debugctl &= ~(DEBUGCTLMSR_LBR | DEBUGCTLMSR_FREEZE_LBRS_ON_PMI);
|
||||||
|
wrmsrl(MSR_IA32_DEBUGCTLMSR, debugctl);
|
||||||
|
}
|
||||||
|
|
||||||
int intel_pmu_save_and_restart(struct perf_event *event);
|
int intel_pmu_save_and_restart(struct perf_event *event);
|
||||||
|
|
||||||
struct event_constraint *
|
struct event_constraint *
|
||||||
|
@ -697,6 +697,20 @@ static void maybe_emit_mod(u8 **pprog, u32 dst_reg, u32 src_reg, bool is64)
|
|||||||
*pprog = prog;
|
*pprog = prog;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Similar version of maybe_emit_mod() for a single register
|
||||||
|
*/
|
||||||
|
static void maybe_emit_1mod(u8 **pprog, u32 reg, bool is64)
|
||||||
|
{
|
||||||
|
u8 *prog = *pprog;
|
||||||
|
|
||||||
|
if (is64)
|
||||||
|
EMIT1(add_1mod(0x48, reg));
|
||||||
|
else if (is_ereg(reg))
|
||||||
|
EMIT1(add_1mod(0x40, reg));
|
||||||
|
*pprog = prog;
|
||||||
|
}
|
||||||
|
|
||||||
/* LDX: dst_reg = *(u8*)(src_reg + off) */
|
/* LDX: dst_reg = *(u8*)(src_reg + off) */
|
||||||
static void emit_ldx(u8 **pprog, u32 size, u32 dst_reg, u32 src_reg, int off)
|
static void emit_ldx(u8 **pprog, u32 size, u32 dst_reg, u32 src_reg, int off)
|
||||||
{
|
{
|
||||||
@ -925,10 +939,8 @@ static int do_jit(struct bpf_prog *bpf_prog, int *addrs, u8 *image,
|
|||||||
/* neg dst */
|
/* neg dst */
|
||||||
case BPF_ALU | BPF_NEG:
|
case BPF_ALU | BPF_NEG:
|
||||||
case BPF_ALU64 | BPF_NEG:
|
case BPF_ALU64 | BPF_NEG:
|
||||||
if (BPF_CLASS(insn->code) == BPF_ALU64)
|
maybe_emit_1mod(&prog, dst_reg,
|
||||||
EMIT1(add_1mod(0x48, dst_reg));
|
BPF_CLASS(insn->code) == BPF_ALU64);
|
||||||
else if (is_ereg(dst_reg))
|
|
||||||
EMIT1(add_1mod(0x40, dst_reg));
|
|
||||||
EMIT2(0xF7, add_1reg(0xD8, dst_reg));
|
EMIT2(0xF7, add_1reg(0xD8, dst_reg));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -942,10 +954,8 @@ static int do_jit(struct bpf_prog *bpf_prog, int *addrs, u8 *image,
|
|||||||
case BPF_ALU64 | BPF_AND | BPF_K:
|
case BPF_ALU64 | BPF_AND | BPF_K:
|
||||||
case BPF_ALU64 | BPF_OR | BPF_K:
|
case BPF_ALU64 | BPF_OR | BPF_K:
|
||||||
case BPF_ALU64 | BPF_XOR | BPF_K:
|
case BPF_ALU64 | BPF_XOR | BPF_K:
|
||||||
if (BPF_CLASS(insn->code) == BPF_ALU64)
|
maybe_emit_1mod(&prog, dst_reg,
|
||||||
EMIT1(add_1mod(0x48, dst_reg));
|
BPF_CLASS(insn->code) == BPF_ALU64);
|
||||||
else if (is_ereg(dst_reg))
|
|
||||||
EMIT1(add_1mod(0x40, dst_reg));
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* b3 holds 'normal' opcode, b2 short form only valid
|
* b3 holds 'normal' opcode, b2 short form only valid
|
||||||
@ -1002,52 +1012,7 @@ static int do_jit(struct bpf_prog *bpf_prog, int *addrs, u8 *image,
|
|||||||
case BPF_ALU64 | BPF_MOD | BPF_X:
|
case BPF_ALU64 | BPF_MOD | BPF_X:
|
||||||
case BPF_ALU64 | BPF_DIV | BPF_X:
|
case BPF_ALU64 | BPF_DIV | BPF_X:
|
||||||
case BPF_ALU64 | BPF_MOD | BPF_K:
|
case BPF_ALU64 | BPF_MOD | BPF_K:
|
||||||
case BPF_ALU64 | BPF_DIV | BPF_K:
|
case BPF_ALU64 | BPF_DIV | BPF_K: {
|
||||||
EMIT1(0x50); /* push rax */
|
|
||||||
EMIT1(0x52); /* push rdx */
|
|
||||||
|
|
||||||
if (BPF_SRC(insn->code) == BPF_X)
|
|
||||||
/* mov r11, src_reg */
|
|
||||||
EMIT_mov(AUX_REG, src_reg);
|
|
||||||
else
|
|
||||||
/* mov r11, imm32 */
|
|
||||||
EMIT3_off32(0x49, 0xC7, 0xC3, imm32);
|
|
||||||
|
|
||||||
/* mov rax, dst_reg */
|
|
||||||
EMIT_mov(BPF_REG_0, dst_reg);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* xor edx, edx
|
|
||||||
* equivalent to 'xor rdx, rdx', but one byte less
|
|
||||||
*/
|
|
||||||
EMIT2(0x31, 0xd2);
|
|
||||||
|
|
||||||
if (BPF_CLASS(insn->code) == BPF_ALU64)
|
|
||||||
/* div r11 */
|
|
||||||
EMIT3(0x49, 0xF7, 0xF3);
|
|
||||||
else
|
|
||||||
/* div r11d */
|
|
||||||
EMIT3(0x41, 0xF7, 0xF3);
|
|
||||||
|
|
||||||
if (BPF_OP(insn->code) == BPF_MOD)
|
|
||||||
/* mov r11, rdx */
|
|
||||||
EMIT3(0x49, 0x89, 0xD3);
|
|
||||||
else
|
|
||||||
/* mov r11, rax */
|
|
||||||
EMIT3(0x49, 0x89, 0xC3);
|
|
||||||
|
|
||||||
EMIT1(0x5A); /* pop rdx */
|
|
||||||
EMIT1(0x58); /* pop rax */
|
|
||||||
|
|
||||||
/* mov dst_reg, r11 */
|
|
||||||
EMIT_mov(dst_reg, AUX_REG);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case BPF_ALU | BPF_MUL | BPF_K:
|
|
||||||
case BPF_ALU | BPF_MUL | BPF_X:
|
|
||||||
case BPF_ALU64 | BPF_MUL | BPF_K:
|
|
||||||
case BPF_ALU64 | BPF_MUL | BPF_X:
|
|
||||||
{
|
|
||||||
bool is64 = BPF_CLASS(insn->code) == BPF_ALU64;
|
bool is64 = BPF_CLASS(insn->code) == BPF_ALU64;
|
||||||
|
|
||||||
if (dst_reg != BPF_REG_0)
|
if (dst_reg != BPF_REG_0)
|
||||||
@ -1055,30 +1020,74 @@ static int do_jit(struct bpf_prog *bpf_prog, int *addrs, u8 *image,
|
|||||||
if (dst_reg != BPF_REG_3)
|
if (dst_reg != BPF_REG_3)
|
||||||
EMIT1(0x52); /* push rdx */
|
EMIT1(0x52); /* push rdx */
|
||||||
|
|
||||||
/* mov r11, dst_reg */
|
if (BPF_SRC(insn->code) == BPF_X) {
|
||||||
EMIT_mov(AUX_REG, dst_reg);
|
if (src_reg == BPF_REG_0 ||
|
||||||
|
src_reg == BPF_REG_3) {
|
||||||
|
/* mov r11, src_reg */
|
||||||
|
EMIT_mov(AUX_REG, src_reg);
|
||||||
|
src_reg = AUX_REG;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* mov r11, imm32 */
|
||||||
|
EMIT3_off32(0x49, 0xC7, 0xC3, imm32);
|
||||||
|
src_reg = AUX_REG;
|
||||||
|
}
|
||||||
|
|
||||||
if (BPF_SRC(insn->code) == BPF_X)
|
if (dst_reg != BPF_REG_0)
|
||||||
emit_mov_reg(&prog, is64, BPF_REG_0, src_reg);
|
/* mov rax, dst_reg */
|
||||||
else
|
emit_mov_reg(&prog, is64, BPF_REG_0, dst_reg);
|
||||||
emit_mov_imm32(&prog, is64, BPF_REG_0, imm32);
|
|
||||||
|
|
||||||
if (is64)
|
/*
|
||||||
EMIT1(add_1mod(0x48, AUX_REG));
|
* xor edx, edx
|
||||||
else if (is_ereg(AUX_REG))
|
* equivalent to 'xor rdx, rdx', but one byte less
|
||||||
EMIT1(add_1mod(0x40, AUX_REG));
|
*/
|
||||||
/* mul(q) r11 */
|
EMIT2(0x31, 0xd2);
|
||||||
EMIT2(0xF7, add_1reg(0xE0, AUX_REG));
|
|
||||||
|
/* div src_reg */
|
||||||
|
maybe_emit_1mod(&prog, src_reg, is64);
|
||||||
|
EMIT2(0xF7, add_1reg(0xF0, src_reg));
|
||||||
|
|
||||||
|
if (BPF_OP(insn->code) == BPF_MOD &&
|
||||||
|
dst_reg != BPF_REG_3)
|
||||||
|
/* mov dst_reg, rdx */
|
||||||
|
emit_mov_reg(&prog, is64, dst_reg, BPF_REG_3);
|
||||||
|
else if (BPF_OP(insn->code) == BPF_DIV &&
|
||||||
|
dst_reg != BPF_REG_0)
|
||||||
|
/* mov dst_reg, rax */
|
||||||
|
emit_mov_reg(&prog, is64, dst_reg, BPF_REG_0);
|
||||||
|
|
||||||
if (dst_reg != BPF_REG_3)
|
if (dst_reg != BPF_REG_3)
|
||||||
EMIT1(0x5A); /* pop rdx */
|
EMIT1(0x5A); /* pop rdx */
|
||||||
if (dst_reg != BPF_REG_0) {
|
if (dst_reg != BPF_REG_0)
|
||||||
/* mov dst_reg, rax */
|
|
||||||
EMIT_mov(dst_reg, BPF_REG_0);
|
|
||||||
EMIT1(0x58); /* pop rax */
|
EMIT1(0x58); /* pop rax */
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case BPF_ALU | BPF_MUL | BPF_K:
|
||||||
|
case BPF_ALU64 | BPF_MUL | BPF_K:
|
||||||
|
maybe_emit_mod(&prog, dst_reg, dst_reg,
|
||||||
|
BPF_CLASS(insn->code) == BPF_ALU64);
|
||||||
|
|
||||||
|
if (is_imm8(imm32))
|
||||||
|
/* imul dst_reg, dst_reg, imm8 */
|
||||||
|
EMIT3(0x6B, add_2reg(0xC0, dst_reg, dst_reg),
|
||||||
|
imm32);
|
||||||
|
else
|
||||||
|
/* imul dst_reg, dst_reg, imm32 */
|
||||||
|
EMIT2_off32(0x69,
|
||||||
|
add_2reg(0xC0, dst_reg, dst_reg),
|
||||||
|
imm32);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case BPF_ALU | BPF_MUL | BPF_X:
|
||||||
|
case BPF_ALU64 | BPF_MUL | BPF_X:
|
||||||
|
maybe_emit_mod(&prog, src_reg, dst_reg,
|
||||||
|
BPF_CLASS(insn->code) == BPF_ALU64);
|
||||||
|
|
||||||
|
/* imul dst_reg, src_reg */
|
||||||
|
EMIT3(0x0F, 0xAF, add_2reg(0xC0, src_reg, dst_reg));
|
||||||
|
break;
|
||||||
|
|
||||||
/* Shifts */
|
/* Shifts */
|
||||||
case BPF_ALU | BPF_LSH | BPF_K:
|
case BPF_ALU | BPF_LSH | BPF_K:
|
||||||
case BPF_ALU | BPF_RSH | BPF_K:
|
case BPF_ALU | BPF_RSH | BPF_K:
|
||||||
@ -1086,10 +1095,8 @@ static int do_jit(struct bpf_prog *bpf_prog, int *addrs, u8 *image,
|
|||||||
case BPF_ALU64 | BPF_LSH | BPF_K:
|
case BPF_ALU64 | BPF_LSH | BPF_K:
|
||||||
case BPF_ALU64 | BPF_RSH | BPF_K:
|
case BPF_ALU64 | BPF_RSH | BPF_K:
|
||||||
case BPF_ALU64 | BPF_ARSH | BPF_K:
|
case BPF_ALU64 | BPF_ARSH | BPF_K:
|
||||||
if (BPF_CLASS(insn->code) == BPF_ALU64)
|
maybe_emit_1mod(&prog, dst_reg,
|
||||||
EMIT1(add_1mod(0x48, dst_reg));
|
BPF_CLASS(insn->code) == BPF_ALU64);
|
||||||
else if (is_ereg(dst_reg))
|
|
||||||
EMIT1(add_1mod(0x40, dst_reg));
|
|
||||||
|
|
||||||
b3 = simple_alu_opcodes[BPF_OP(insn->code)];
|
b3 = simple_alu_opcodes[BPF_OP(insn->code)];
|
||||||
if (imm32 == 1)
|
if (imm32 == 1)
|
||||||
@ -1120,10 +1127,8 @@ static int do_jit(struct bpf_prog *bpf_prog, int *addrs, u8 *image,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* shl %rax, %cl | shr %rax, %cl | sar %rax, %cl */
|
/* shl %rax, %cl | shr %rax, %cl | sar %rax, %cl */
|
||||||
if (BPF_CLASS(insn->code) == BPF_ALU64)
|
maybe_emit_1mod(&prog, dst_reg,
|
||||||
EMIT1(add_1mod(0x48, dst_reg));
|
BPF_CLASS(insn->code) == BPF_ALU64);
|
||||||
else if (is_ereg(dst_reg))
|
|
||||||
EMIT1(add_1mod(0x40, dst_reg));
|
|
||||||
|
|
||||||
b3 = simple_alu_opcodes[BPF_OP(insn->code)];
|
b3 = simple_alu_opcodes[BPF_OP(insn->code)];
|
||||||
EMIT2(0xD3, add_1reg(b3, dst_reg));
|
EMIT2(0xD3, add_1reg(b3, dst_reg));
|
||||||
@ -1430,10 +1435,8 @@ st: if (is_imm8(insn->off))
|
|||||||
case BPF_JMP | BPF_JSET | BPF_K:
|
case BPF_JMP | BPF_JSET | BPF_K:
|
||||||
case BPF_JMP32 | BPF_JSET | BPF_K:
|
case BPF_JMP32 | BPF_JSET | BPF_K:
|
||||||
/* test dst_reg, imm32 */
|
/* test dst_reg, imm32 */
|
||||||
if (BPF_CLASS(insn->code) == BPF_JMP)
|
maybe_emit_1mod(&prog, dst_reg,
|
||||||
EMIT1(add_1mod(0x48, dst_reg));
|
BPF_CLASS(insn->code) == BPF_JMP);
|
||||||
else if (is_ereg(dst_reg))
|
|
||||||
EMIT1(add_1mod(0x40, dst_reg));
|
|
||||||
EMIT2_off32(0xF7, add_1reg(0xC0, dst_reg), imm32);
|
EMIT2_off32(0xF7, add_1reg(0xC0, dst_reg), imm32);
|
||||||
goto emit_cond_jmp;
|
goto emit_cond_jmp;
|
||||||
|
|
||||||
@ -1466,10 +1469,8 @@ st: if (is_imm8(insn->off))
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* cmp dst_reg, imm8/32 */
|
/* cmp dst_reg, imm8/32 */
|
||||||
if (BPF_CLASS(insn->code) == BPF_JMP)
|
maybe_emit_1mod(&prog, dst_reg,
|
||||||
EMIT1(add_1mod(0x48, dst_reg));
|
BPF_CLASS(insn->code) == BPF_JMP);
|
||||||
else if (is_ereg(dst_reg))
|
|
||||||
EMIT1(add_1mod(0x40, dst_reg));
|
|
||||||
|
|
||||||
if (is_imm8(imm32))
|
if (is_imm8(imm32))
|
||||||
EMIT3(0x83, add_1reg(0xF8, dst_reg), imm32);
|
EMIT3(0x83, add_1reg(0xF8, dst_reg), imm32);
|
||||||
|
@ -124,7 +124,7 @@ static char *split_if_spec(char *str, ...)
|
|||||||
|
|
||||||
static void setup_etheraddr(struct net_device *dev, char *str)
|
static void setup_etheraddr(struct net_device *dev, char *str)
|
||||||
{
|
{
|
||||||
unsigned char *addr = dev->dev_addr;
|
u8 addr[ETH_ALEN];
|
||||||
|
|
||||||
if (str == NULL)
|
if (str == NULL)
|
||||||
goto random;
|
goto random;
|
||||||
@ -147,6 +147,7 @@ static void setup_etheraddr(struct net_device *dev, char *str)
|
|||||||
if (!is_local_ether_addr(addr))
|
if (!is_local_ether_addr(addr))
|
||||||
pr_warn("%s: assigning a globally valid ethernet address\n",
|
pr_warn("%s: assigning a globally valid ethernet address\n",
|
||||||
dev->name);
|
dev->name);
|
||||||
|
eth_hw_addr_set(dev, addr);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
random:
|
random:
|
||||||
@ -467,7 +468,7 @@ static int iss_net_set_mac(struct net_device *dev, void *addr)
|
|||||||
if (!is_valid_ether_addr(hwaddr->sa_data))
|
if (!is_valid_ether_addr(hwaddr->sa_data))
|
||||||
return -EADDRNOTAVAIL;
|
return -EADDRNOTAVAIL;
|
||||||
spin_lock_bh(&lp->lock);
|
spin_lock_bh(&lp->lock);
|
||||||
memcpy(dev->dev_addr, hwaddr->sa_data, ETH_ALEN);
|
eth_hw_addr_set(dev, hwaddr->sa_data);
|
||||||
spin_unlock_bh(&lp->lock);
|
spin_unlock_bh(&lp->lock);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -15,7 +15,6 @@
|
|||||||
#include <linux/of_graph.h>
|
#include <linux/of_graph.h>
|
||||||
#include <linux/of_irq.h>
|
#include <linux/of_irq.h>
|
||||||
#include <linux/property.h>
|
#include <linux/property.h>
|
||||||
#include <linux/etherdevice.h>
|
|
||||||
#include <linux/phy.h>
|
#include <linux/phy.h>
|
||||||
|
|
||||||
struct fwnode_handle *dev_fwnode(struct device *dev)
|
struct fwnode_handle *dev_fwnode(struct device *dev)
|
||||||
@ -935,68 +934,6 @@ int device_get_phy_mode(struct device *dev)
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(device_get_phy_mode);
|
EXPORT_SYMBOL_GPL(device_get_phy_mode);
|
||||||
|
|
||||||
static void *fwnode_get_mac_addr(struct fwnode_handle *fwnode,
|
|
||||||
const char *name, char *addr,
|
|
||||||
int alen)
|
|
||||||
{
|
|
||||||
int ret = fwnode_property_read_u8_array(fwnode, name, addr, alen);
|
|
||||||
|
|
||||||
if (ret == 0 && alen == ETH_ALEN && is_valid_ether_addr(addr))
|
|
||||||
return addr;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* fwnode_get_mac_address - Get the MAC from the firmware node
|
|
||||||
* @fwnode: Pointer to the firmware node
|
|
||||||
* @addr: Address of buffer to store the MAC in
|
|
||||||
* @alen: Length of the buffer pointed to by addr, should be ETH_ALEN
|
|
||||||
*
|
|
||||||
* Search the firmware node for the best MAC address to use. 'mac-address' is
|
|
||||||
* checked first, because that is supposed to contain to "most recent" MAC
|
|
||||||
* address. If that isn't set, then 'local-mac-address' is checked next,
|
|
||||||
* because that is the default address. If that isn't set, then the obsolete
|
|
||||||
* 'address' is checked, just in case we're using an old device tree.
|
|
||||||
*
|
|
||||||
* Note that the 'address' property is supposed to contain a virtual address of
|
|
||||||
* the register set, but some DTS files have redefined that property to be the
|
|
||||||
* MAC address.
|
|
||||||
*
|
|
||||||
* All-zero MAC addresses are rejected, because those could be properties that
|
|
||||||
* exist in the firmware tables, but were not updated by the firmware. For
|
|
||||||
* example, the DTS could define 'mac-address' and 'local-mac-address', with
|
|
||||||
* zero MAC addresses. Some older U-Boots only initialized 'local-mac-address'.
|
|
||||||
* In this case, the real MAC is in 'local-mac-address', and 'mac-address'
|
|
||||||
* exists but is all zeros.
|
|
||||||
*/
|
|
||||||
void *fwnode_get_mac_address(struct fwnode_handle *fwnode, char *addr, int alen)
|
|
||||||
{
|
|
||||||
char *res;
|
|
||||||
|
|
||||||
res = fwnode_get_mac_addr(fwnode, "mac-address", addr, alen);
|
|
||||||
if (res)
|
|
||||||
return res;
|
|
||||||
|
|
||||||
res = fwnode_get_mac_addr(fwnode, "local-mac-address", addr, alen);
|
|
||||||
if (res)
|
|
||||||
return res;
|
|
||||||
|
|
||||||
return fwnode_get_mac_addr(fwnode, "address", addr, alen);
|
|
||||||
}
|
|
||||||
EXPORT_SYMBOL(fwnode_get_mac_address);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* device_get_mac_address - Get the MAC for a given device
|
|
||||||
* @dev: Pointer to the device
|
|
||||||
* @addr: Address of buffer to store the MAC in
|
|
||||||
* @alen: Length of the buffer pointed to by addr, should be ETH_ALEN
|
|
||||||
*/
|
|
||||||
void *device_get_mac_address(struct device *dev, char *addr, int alen)
|
|
||||||
{
|
|
||||||
return fwnode_get_mac_address(dev_fwnode(dev), addr, alen);
|
|
||||||
}
|
|
||||||
EXPORT_SYMBOL(device_get_mac_address);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* fwnode_irq_get - Get IRQ directly from a fwnode
|
* fwnode_irq_get - Get IRQ directly from a fwnode
|
||||||
* @fwnode: Pointer to the firmware node
|
* @fwnode: Pointer to the firmware node
|
||||||
|
@ -14,7 +14,7 @@ static int regmap_mdio_read(struct mdio_device *mdio_dev, u32 reg, unsigned int
|
|||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = mdiobus_read(mdio_dev->bus, mdio_dev->addr, reg);
|
ret = mdiodev_read(mdio_dev, reg);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
@ -24,7 +24,7 @@ static int regmap_mdio_read(struct mdio_device *mdio_dev, u32 reg, unsigned int
|
|||||||
|
|
||||||
static int regmap_mdio_write(struct mdio_device *mdio_dev, u32 reg, unsigned int val)
|
static int regmap_mdio_write(struct mdio_device *mdio_dev, u32 reg, unsigned int val)
|
||||||
{
|
{
|
||||||
return mdiobus_write(mdio_dev->bus, mdio_dev->addr, reg, val);
|
return mdiodev_write(mdio_dev, reg, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int regmap_mdio_c22_read(void *context, unsigned int reg, unsigned int *val)
|
static int regmap_mdio_c22_read(void *context, unsigned int reg, unsigned int *val)
|
||||||
@ -44,7 +44,7 @@ static int regmap_mdio_c22_write(void *context, unsigned int reg, unsigned int v
|
|||||||
if (unlikely(reg & ~REGNUM_C22_MASK))
|
if (unlikely(reg & ~REGNUM_C22_MASK))
|
||||||
return -ENXIO;
|
return -ENXIO;
|
||||||
|
|
||||||
return mdiobus_write(mdio_dev->bus, mdio_dev->addr, reg, val);
|
return mdiodev_write(mdio_dev, reg, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct regmap_bus regmap_mdio_c22_bus = {
|
static const struct regmap_bus regmap_mdio_c22_bus = {
|
||||||
|
@ -20,7 +20,7 @@ MODULE_DESCRIPTION("Broadcom's specific AMBA driver");
|
|||||||
MODULE_LICENSE("GPL");
|
MODULE_LICENSE("GPL");
|
||||||
|
|
||||||
/* contains the number the next bus should get. */
|
/* contains the number the next bus should get. */
|
||||||
static unsigned int bcma_bus_next_num = 0;
|
static unsigned int bcma_bus_next_num;
|
||||||
|
|
||||||
/* bcma_buses_mutex locks the bcma_bus_next_num */
|
/* bcma_buses_mutex locks the bcma_bus_next_num */
|
||||||
static DEFINE_MUTEX(bcma_buses_mutex);
|
static DEFINE_MUTEX(bcma_buses_mutex);
|
||||||
|
@ -1037,8 +1037,9 @@ static bool btintel_firmware_version(struct hci_dev *hdev,
|
|||||||
|
|
||||||
params = (void *)(fw_ptr + sizeof(*cmd));
|
params = (void *)(fw_ptr + sizeof(*cmd));
|
||||||
|
|
||||||
bt_dev_info(hdev, "Boot Address: 0x%x",
|
*boot_addr = le32_to_cpu(params->boot_addr);
|
||||||
le32_to_cpu(params->boot_addr));
|
|
||||||
|
bt_dev_info(hdev, "Boot Address: 0x%x", *boot_addr);
|
||||||
|
|
||||||
bt_dev_info(hdev, "Firmware Version: %u-%u.%u",
|
bt_dev_info(hdev, "Firmware Version: %u-%u.%u",
|
||||||
params->fw_build_num, params->fw_build_ww,
|
params->fw_build_num, params->fw_build_ww,
|
||||||
@ -1071,9 +1072,6 @@ int btintel_download_firmware(struct hci_dev *hdev,
|
|||||||
/* Skip version checking */
|
/* Skip version checking */
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
/* Skip reading firmware file version in bootloader mode */
|
|
||||||
if (ver->fw_variant == 0x06)
|
|
||||||
break;
|
|
||||||
|
|
||||||
/* Skip download if firmware has the same version */
|
/* Skip download if firmware has the same version */
|
||||||
if (btintel_firmware_version(hdev, ver->fw_build_num,
|
if (btintel_firmware_version(hdev, ver->fw_build_num,
|
||||||
@ -1114,19 +1112,16 @@ static int btintel_download_fw_tlv(struct hci_dev *hdev,
|
|||||||
int err;
|
int err;
|
||||||
u32 css_header_ver;
|
u32 css_header_ver;
|
||||||
|
|
||||||
/* Skip reading firmware file version in bootloader mode */
|
/* Skip download if firmware has the same version */
|
||||||
if (ver->img_type != 0x01) {
|
if (btintel_firmware_version(hdev, ver->min_fw_build_nn,
|
||||||
/* Skip download if firmware has the same version */
|
ver->min_fw_build_cw,
|
||||||
if (btintel_firmware_version(hdev, ver->min_fw_build_nn,
|
ver->min_fw_build_yy,
|
||||||
ver->min_fw_build_cw,
|
fw, boot_param)) {
|
||||||
ver->min_fw_build_yy,
|
bt_dev_info(hdev, "Firmware already loaded");
|
||||||
fw, boot_param)) {
|
/* Return -EALREADY to indicate that firmware has
|
||||||
bt_dev_info(hdev, "Firmware already loaded");
|
* already been loaded.
|
||||||
/* Return -EALREADY to indicate that firmware has
|
*/
|
||||||
* already been loaded.
|
return -EALREADY;
|
||||||
*/
|
|
||||||
return -EALREADY;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The firmware variant determines if the device is in bootloader
|
/* The firmware variant determines if the device is in bootloader
|
||||||
@ -1285,12 +1280,16 @@ static int btintel_read_debug_features(struct hci_dev *hdev,
|
|||||||
static int btintel_set_debug_features(struct hci_dev *hdev,
|
static int btintel_set_debug_features(struct hci_dev *hdev,
|
||||||
const struct intel_debug_features *features)
|
const struct intel_debug_features *features)
|
||||||
{
|
{
|
||||||
u8 mask[11] = { 0x0a, 0x92, 0x02, 0x07, 0x00, 0x00, 0x00, 0x00,
|
u8 mask[11] = { 0x0a, 0x92, 0x02, 0x7f, 0x00, 0x00, 0x00, 0x00,
|
||||||
0x00, 0x00, 0x00 };
|
0x00, 0x00, 0x00 };
|
||||||
|
u8 period[5] = { 0x04, 0x91, 0x02, 0x05, 0x00 };
|
||||||
|
u8 trace_enable = 0x02;
|
||||||
struct sk_buff *skb;
|
struct sk_buff *skb;
|
||||||
|
|
||||||
if (!features)
|
if (!features) {
|
||||||
|
bt_dev_warn(hdev, "Debug features not read");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
if (!(features->page1[0] & 0x3f)) {
|
if (!(features->page1[0] & 0x3f)) {
|
||||||
bt_dev_info(hdev, "Telemetry exception format not supported");
|
bt_dev_info(hdev, "Telemetry exception format not supported");
|
||||||
@ -1303,11 +1302,95 @@ static int btintel_set_debug_features(struct hci_dev *hdev,
|
|||||||
PTR_ERR(skb));
|
PTR_ERR(skb));
|
||||||
return PTR_ERR(skb);
|
return PTR_ERR(skb);
|
||||||
}
|
}
|
||||||
|
|
||||||
kfree_skb(skb);
|
kfree_skb(skb);
|
||||||
|
|
||||||
|
skb = __hci_cmd_sync(hdev, 0xfc8b, 5, period, HCI_INIT_TIMEOUT);
|
||||||
|
if (IS_ERR(skb)) {
|
||||||
|
bt_dev_err(hdev, "Setting periodicity for link statistics traces failed (%ld)",
|
||||||
|
PTR_ERR(skb));
|
||||||
|
return PTR_ERR(skb);
|
||||||
|
}
|
||||||
|
kfree_skb(skb);
|
||||||
|
|
||||||
|
skb = __hci_cmd_sync(hdev, 0xfca1, 1, &trace_enable, HCI_INIT_TIMEOUT);
|
||||||
|
if (IS_ERR(skb)) {
|
||||||
|
bt_dev_err(hdev, "Enable tracing of link statistics events failed (%ld)",
|
||||||
|
PTR_ERR(skb));
|
||||||
|
return PTR_ERR(skb);
|
||||||
|
}
|
||||||
|
kfree_skb(skb);
|
||||||
|
|
||||||
|
bt_dev_info(hdev, "set debug features: trace_enable 0x%02x mask 0x%02x",
|
||||||
|
trace_enable, mask[3]);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int btintel_reset_debug_features(struct hci_dev *hdev,
|
||||||
|
const struct intel_debug_features *features)
|
||||||
|
{
|
||||||
|
u8 mask[11] = { 0x0a, 0x92, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00 };
|
||||||
|
u8 trace_enable = 0x00;
|
||||||
|
struct sk_buff *skb;
|
||||||
|
|
||||||
|
if (!features) {
|
||||||
|
bt_dev_warn(hdev, "Debug features not read");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(features->page1[0] & 0x3f)) {
|
||||||
|
bt_dev_info(hdev, "Telemetry exception format not supported");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Should stop the trace before writing ddc event mask. */
|
||||||
|
skb = __hci_cmd_sync(hdev, 0xfca1, 1, &trace_enable, HCI_INIT_TIMEOUT);
|
||||||
|
if (IS_ERR(skb)) {
|
||||||
|
bt_dev_err(hdev, "Stop tracing of link statistics events failed (%ld)",
|
||||||
|
PTR_ERR(skb));
|
||||||
|
return PTR_ERR(skb);
|
||||||
|
}
|
||||||
|
kfree_skb(skb);
|
||||||
|
|
||||||
|
skb = __hci_cmd_sync(hdev, 0xfc8b, 11, mask, HCI_INIT_TIMEOUT);
|
||||||
|
if (IS_ERR(skb)) {
|
||||||
|
bt_dev_err(hdev, "Setting Intel telemetry ddc write event mask failed (%ld)",
|
||||||
|
PTR_ERR(skb));
|
||||||
|
return PTR_ERR(skb);
|
||||||
|
}
|
||||||
|
kfree_skb(skb);
|
||||||
|
|
||||||
|
bt_dev_info(hdev, "reset debug features: trace_enable 0x%02x mask 0x%02x",
|
||||||
|
trace_enable, mask[3]);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int btintel_set_quality_report(struct hci_dev *hdev, bool enable)
|
||||||
|
{
|
||||||
|
struct intel_debug_features features;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
bt_dev_dbg(hdev, "enable %d", enable);
|
||||||
|
|
||||||
|
/* Read the Intel supported features and if new exception formats
|
||||||
|
* supported, need to load the additional DDC config to enable.
|
||||||
|
*/
|
||||||
|
err = btintel_read_debug_features(hdev, &features);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
/* Set or reset the debug features. */
|
||||||
|
if (enable)
|
||||||
|
err = btintel_set_debug_features(hdev, &features);
|
||||||
|
else
|
||||||
|
err = btintel_reset_debug_features(hdev, &features);
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(btintel_set_quality_report);
|
||||||
|
|
||||||
static const struct firmware *btintel_legacy_rom_get_fw(struct hci_dev *hdev,
|
static const struct firmware *btintel_legacy_rom_get_fw(struct hci_dev *hdev,
|
||||||
struct intel_version *ver)
|
struct intel_version *ver)
|
||||||
{
|
{
|
||||||
@ -1893,7 +1976,6 @@ static int btintel_bootloader_setup(struct hci_dev *hdev,
|
|||||||
u32 boot_param;
|
u32 boot_param;
|
||||||
char ddcname[64];
|
char ddcname[64];
|
||||||
int err;
|
int err;
|
||||||
struct intel_debug_features features;
|
|
||||||
|
|
||||||
BT_DBG("%s", hdev->name);
|
BT_DBG("%s", hdev->name);
|
||||||
|
|
||||||
@ -1934,14 +2016,7 @@ static int btintel_bootloader_setup(struct hci_dev *hdev,
|
|||||||
btintel_load_ddc_config(hdev, ddcname);
|
btintel_load_ddc_config(hdev, ddcname);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Read the Intel supported features and if new exception formats
|
hci_dev_clear_flag(hdev, HCI_QUALITY_REPORT);
|
||||||
* supported, need to load the additional DDC config to enable.
|
|
||||||
*/
|
|
||||||
err = btintel_read_debug_features(hdev, &features);
|
|
||||||
if (!err) {
|
|
||||||
/* Set DDC mask for available debug features */
|
|
||||||
btintel_set_debug_features(hdev, &features);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Read the Intel version information after loading the FW */
|
/* Read the Intel version information after loading the FW */
|
||||||
err = btintel_read_version(hdev, &new_ver);
|
err = btintel_read_version(hdev, &new_ver);
|
||||||
@ -2083,13 +2158,102 @@ static int btintel_prepare_fw_download_tlv(struct hci_dev *hdev,
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int btintel_get_codec_config_data(struct hci_dev *hdev,
|
||||||
|
__u8 link, struct bt_codec *codec,
|
||||||
|
__u8 *ven_len, __u8 **ven_data)
|
||||||
|
{
|
||||||
|
int err = 0;
|
||||||
|
|
||||||
|
if (!ven_data || !ven_len)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
*ven_len = 0;
|
||||||
|
*ven_data = NULL;
|
||||||
|
|
||||||
|
if (link != ESCO_LINK) {
|
||||||
|
bt_dev_err(hdev, "Invalid link type(%u)", link);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
*ven_data = kmalloc(sizeof(__u8), GFP_KERNEL);
|
||||||
|
if (!*ven_data) {
|
||||||
|
err = -ENOMEM;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* supports only CVSD and mSBC offload codecs */
|
||||||
|
switch (codec->id) {
|
||||||
|
case 0x02:
|
||||||
|
**ven_data = 0x00;
|
||||||
|
break;
|
||||||
|
case 0x05:
|
||||||
|
**ven_data = 0x01;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
err = -EINVAL;
|
||||||
|
bt_dev_err(hdev, "Invalid codec id(%u)", codec->id);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
/* codec and its capabilities are pre-defined to ids
|
||||||
|
* preset id = 0x00 represents CVSD codec with sampling rate 8K
|
||||||
|
* preset id = 0x01 represents mSBC codec with sampling rate 16K
|
||||||
|
*/
|
||||||
|
*ven_len = sizeof(__u8);
|
||||||
|
return err;
|
||||||
|
|
||||||
|
error:
|
||||||
|
kfree(*ven_data);
|
||||||
|
*ven_data = NULL;
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int btintel_get_data_path_id(struct hci_dev *hdev, __u8 *data_path_id)
|
||||||
|
{
|
||||||
|
/* Intel uses 1 as data path id for all the usecases */
|
||||||
|
*data_path_id = 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int btintel_configure_offload(struct hci_dev *hdev)
|
||||||
|
{
|
||||||
|
struct sk_buff *skb;
|
||||||
|
int err = 0;
|
||||||
|
struct intel_offload_use_cases *use_cases;
|
||||||
|
|
||||||
|
skb = __hci_cmd_sync(hdev, 0xfc86, 0, NULL, HCI_INIT_TIMEOUT);
|
||||||
|
if (IS_ERR(skb)) {
|
||||||
|
bt_dev_err(hdev, "Reading offload use cases failed (%ld)",
|
||||||
|
PTR_ERR(skb));
|
||||||
|
return PTR_ERR(skb);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (skb->len < sizeof(*use_cases)) {
|
||||||
|
err = -EIO;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
use_cases = (void *)skb->data;
|
||||||
|
|
||||||
|
if (use_cases->status) {
|
||||||
|
err = -bt_to_errno(skb->data[0]);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (use_cases->preset[0] & 0x03) {
|
||||||
|
hdev->get_data_path_id = btintel_get_data_path_id;
|
||||||
|
hdev->get_codec_config_data = btintel_get_codec_config_data;
|
||||||
|
}
|
||||||
|
error:
|
||||||
|
kfree_skb(skb);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
static int btintel_bootloader_setup_tlv(struct hci_dev *hdev,
|
static int btintel_bootloader_setup_tlv(struct hci_dev *hdev,
|
||||||
struct intel_version_tlv *ver)
|
struct intel_version_tlv *ver)
|
||||||
{
|
{
|
||||||
u32 boot_param;
|
u32 boot_param;
|
||||||
char ddcname[64];
|
char ddcname[64];
|
||||||
int err;
|
int err;
|
||||||
struct intel_debug_features features;
|
|
||||||
struct intel_version_tlv new_ver;
|
struct intel_version_tlv new_ver;
|
||||||
|
|
||||||
bt_dev_dbg(hdev, "");
|
bt_dev_dbg(hdev, "");
|
||||||
@ -2125,14 +2289,10 @@ static int btintel_bootloader_setup_tlv(struct hci_dev *hdev,
|
|||||||
*/
|
*/
|
||||||
btintel_load_ddc_config(hdev, ddcname);
|
btintel_load_ddc_config(hdev, ddcname);
|
||||||
|
|
||||||
/* Read the Intel supported features and if new exception formats
|
/* Read supported use cases and set callbacks to fetch datapath id */
|
||||||
* supported, need to load the additional DDC config to enable.
|
btintel_configure_offload(hdev);
|
||||||
*/
|
|
||||||
err = btintel_read_debug_features(hdev, &features);
|
hci_dev_clear_flag(hdev, HCI_QUALITY_REPORT);
|
||||||
if (!err) {
|
|
||||||
/* Set DDC mask for available debug features */
|
|
||||||
btintel_set_debug_features(hdev, &features);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Read the Intel version information after loading the FW */
|
/* Read the Intel version information after loading the FW */
|
||||||
err = btintel_read_version_tlv(hdev, &new_ver);
|
err = btintel_read_version_tlv(hdev, &new_ver);
|
||||||
@ -2232,6 +2392,9 @@ static int btintel_setup_combined(struct hci_dev *hdev)
|
|||||||
set_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, &hdev->quirks);
|
set_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, &hdev->quirks);
|
||||||
set_bit(HCI_QUIRK_NON_PERSISTENT_DIAG, &hdev->quirks);
|
set_bit(HCI_QUIRK_NON_PERSISTENT_DIAG, &hdev->quirks);
|
||||||
|
|
||||||
|
/* Set up the quality report callback for Intel devices */
|
||||||
|
hdev->set_quality_report = btintel_set_quality_report;
|
||||||
|
|
||||||
/* For Legacy device, check the HW platform value and size */
|
/* For Legacy device, check the HW platform value and size */
|
||||||
if (skb->len == sizeof(ver) && skb->data[1] == 0x37) {
|
if (skb->len == sizeof(ver) && skb->data[1] == 0x37) {
|
||||||
bt_dev_dbg(hdev, "Read the legacy Intel version information");
|
bt_dev_dbg(hdev, "Read the legacy Intel version information");
|
||||||
|
@ -132,6 +132,11 @@ struct intel_debug_features {
|
|||||||
__u8 page1[16];
|
__u8 page1[16];
|
||||||
} __packed;
|
} __packed;
|
||||||
|
|
||||||
|
struct intel_offload_use_cases {
|
||||||
|
__u8 status;
|
||||||
|
__u8 preset[8];
|
||||||
|
} __packed;
|
||||||
|
|
||||||
#define INTEL_HW_PLATFORM(cnvx_bt) ((u8)(((cnvx_bt) & 0x0000ff00) >> 8))
|
#define INTEL_HW_PLATFORM(cnvx_bt) ((u8)(((cnvx_bt) & 0x0000ff00) >> 8))
|
||||||
#define INTEL_HW_VARIANT(cnvx_bt) ((u8)(((cnvx_bt) & 0x003f0000) >> 16))
|
#define INTEL_HW_VARIANT(cnvx_bt) ((u8)(((cnvx_bt) & 0x003f0000) >> 16))
|
||||||
#define INTEL_CNVX_TOP_TYPE(cnvx_top) ((cnvx_top) & 0x00000fff)
|
#define INTEL_CNVX_TOP_TYPE(cnvx_top) ((cnvx_top) & 0x00000fff)
|
||||||
@ -204,6 +209,7 @@ int btintel_configure_setup(struct hci_dev *hdev);
|
|||||||
void btintel_bootup(struct hci_dev *hdev, const void *ptr, unsigned int len);
|
void btintel_bootup(struct hci_dev *hdev, const void *ptr, unsigned int len);
|
||||||
void btintel_secure_send_result(struct hci_dev *hdev,
|
void btintel_secure_send_result(struct hci_dev *hdev,
|
||||||
const void *ptr, unsigned int len);
|
const void *ptr, unsigned int len);
|
||||||
|
int btintel_set_quality_report(struct hci_dev *hdev, bool enable);
|
||||||
#else
|
#else
|
||||||
|
|
||||||
static inline int btintel_check_bdaddr(struct hci_dev *hdev)
|
static inline int btintel_check_bdaddr(struct hci_dev *hdev)
|
||||||
@ -294,4 +300,9 @@ static inline void btintel_secure_send_result(struct hci_dev *hdev,
|
|||||||
const void *ptr, unsigned int len)
|
const void *ptr, unsigned int len)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline int btintel_set_quality_report(struct hci_dev *hdev, bool enable)
|
||||||
|
{
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -587,12 +587,12 @@ static int btmrvl_set_bdaddr(struct hci_dev *hdev, const bdaddr_t *bdaddr)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool btmrvl_prevent_wake(struct hci_dev *hdev)
|
static bool btmrvl_wakeup(struct hci_dev *hdev)
|
||||||
{
|
{
|
||||||
struct btmrvl_private *priv = hci_get_drvdata(hdev);
|
struct btmrvl_private *priv = hci_get_drvdata(hdev);
|
||||||
struct btmrvl_sdio_card *card = priv->btmrvl_dev.card;
|
struct btmrvl_sdio_card *card = priv->btmrvl_dev.card;
|
||||||
|
|
||||||
return !device_may_wakeup(&card->func->dev);
|
return device_may_wakeup(&card->func->dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -696,7 +696,7 @@ int btmrvl_register_hdev(struct btmrvl_private *priv)
|
|||||||
hdev->send = btmrvl_send_frame;
|
hdev->send = btmrvl_send_frame;
|
||||||
hdev->setup = btmrvl_setup;
|
hdev->setup = btmrvl_setup;
|
||||||
hdev->set_bdaddr = btmrvl_set_bdaddr;
|
hdev->set_bdaddr = btmrvl_set_bdaddr;
|
||||||
hdev->prevent_wake = btmrvl_prevent_wake;
|
hdev->wakeup = btmrvl_wakeup;
|
||||||
SET_HCIDEV_DEV(hdev, &card->func->dev);
|
SET_HCIDEV_DEV(hdev, &card->func->dev);
|
||||||
|
|
||||||
hdev->dev_type = priv->btmrvl_dev.dev_type;
|
hdev->dev_type = priv->btmrvl_dev.dev_type;
|
||||||
|
@ -158,8 +158,10 @@ static int mtk_hci_wmt_sync(struct hci_dev *hdev,
|
|||||||
int err;
|
int err;
|
||||||
|
|
||||||
hlen = sizeof(*hdr) + wmt_params->dlen;
|
hlen = sizeof(*hdr) + wmt_params->dlen;
|
||||||
if (hlen > 255)
|
if (hlen > 255) {
|
||||||
return -EINVAL;
|
err = -EINVAL;
|
||||||
|
goto err_free_skb;
|
||||||
|
}
|
||||||
|
|
||||||
hdr = (struct mtk_wmt_hdr *)&wc;
|
hdr = (struct mtk_wmt_hdr *)&wc;
|
||||||
hdr->dir = 1;
|
hdr->dir = 1;
|
||||||
@ -173,7 +175,7 @@ static int mtk_hci_wmt_sync(struct hci_dev *hdev,
|
|||||||
err = __hci_cmd_send(hdev, 0xfc6f, hlen, &wc);
|
err = __hci_cmd_send(hdev, 0xfc6f, hlen, &wc);
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
clear_bit(BTMTKUART_TX_WAIT_VND_EVT, &bdev->tx_state);
|
clear_bit(BTMTKUART_TX_WAIT_VND_EVT, &bdev->tx_state);
|
||||||
return err;
|
goto err_free_skb;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The vendor specific WMT commands are all answered by a vendor
|
/* The vendor specific WMT commands are all answered by a vendor
|
||||||
@ -190,13 +192,14 @@ static int mtk_hci_wmt_sync(struct hci_dev *hdev,
|
|||||||
if (err == -EINTR) {
|
if (err == -EINTR) {
|
||||||
bt_dev_err(hdev, "Execution of wmt command interrupted");
|
bt_dev_err(hdev, "Execution of wmt command interrupted");
|
||||||
clear_bit(BTMTKUART_TX_WAIT_VND_EVT, &bdev->tx_state);
|
clear_bit(BTMTKUART_TX_WAIT_VND_EVT, &bdev->tx_state);
|
||||||
return err;
|
goto err_free_skb;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (err) {
|
if (err) {
|
||||||
bt_dev_err(hdev, "Execution of wmt command timed out");
|
bt_dev_err(hdev, "Execution of wmt command timed out");
|
||||||
clear_bit(BTMTKUART_TX_WAIT_VND_EVT, &bdev->tx_state);
|
clear_bit(BTMTKUART_TX_WAIT_VND_EVT, &bdev->tx_state);
|
||||||
return -ETIMEDOUT;
|
err = -ETIMEDOUT;
|
||||||
|
goto err_free_skb;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Parse and handle the return WMT event */
|
/* Parse and handle the return WMT event */
|
||||||
|
@ -19,7 +19,6 @@
|
|||||||
#include <net/bluetooth/hci_core.h>
|
#include <net/bluetooth/hci_core.h>
|
||||||
#include <asm/unaligned.h>
|
#include <asm/unaligned.h>
|
||||||
#include <net/rsi_91x.h>
|
#include <net/rsi_91x.h>
|
||||||
#include <net/genetlink.h>
|
|
||||||
|
|
||||||
#define RSI_DMA_ALIGN 8
|
#define RSI_DMA_ALIGN 8
|
||||||
#define RSI_FRAME_DESC_SIZE 16
|
#define RSI_FRAME_DESC_SIZE 16
|
||||||
|
@ -59,6 +59,7 @@ struct id_table {
|
|||||||
__u8 hci_bus;
|
__u8 hci_bus;
|
||||||
bool config_needed;
|
bool config_needed;
|
||||||
bool has_rom_version;
|
bool has_rom_version;
|
||||||
|
bool has_msft_ext;
|
||||||
char *fw_name;
|
char *fw_name;
|
||||||
char *cfg_name;
|
char *cfg_name;
|
||||||
};
|
};
|
||||||
@ -121,6 +122,7 @@ static const struct id_table ic_id_table[] = {
|
|||||||
{ IC_INFO(RTL_ROM_LMP_8821A, 0xc, 0x8, HCI_USB),
|
{ IC_INFO(RTL_ROM_LMP_8821A, 0xc, 0x8, HCI_USB),
|
||||||
.config_needed = false,
|
.config_needed = false,
|
||||||
.has_rom_version = true,
|
.has_rom_version = true,
|
||||||
|
.has_msft_ext = true,
|
||||||
.fw_name = "rtl_bt/rtl8821c_fw.bin",
|
.fw_name = "rtl_bt/rtl8821c_fw.bin",
|
||||||
.cfg_name = "rtl_bt/rtl8821c_config" },
|
.cfg_name = "rtl_bt/rtl8821c_config" },
|
||||||
|
|
||||||
@ -135,6 +137,7 @@ static const struct id_table ic_id_table[] = {
|
|||||||
{ IC_INFO(RTL_ROM_LMP_8761A, 0xb, 0xa, HCI_UART),
|
{ IC_INFO(RTL_ROM_LMP_8761A, 0xb, 0xa, HCI_UART),
|
||||||
.config_needed = false,
|
.config_needed = false,
|
||||||
.has_rom_version = true,
|
.has_rom_version = true,
|
||||||
|
.has_msft_ext = true,
|
||||||
.fw_name = "rtl_bt/rtl8761b_fw.bin",
|
.fw_name = "rtl_bt/rtl8761b_fw.bin",
|
||||||
.cfg_name = "rtl_bt/rtl8761b_config" },
|
.cfg_name = "rtl_bt/rtl8761b_config" },
|
||||||
|
|
||||||
@ -149,6 +152,7 @@ static const struct id_table ic_id_table[] = {
|
|||||||
{ IC_INFO(RTL_ROM_LMP_8822B, 0xc, 0xa, HCI_UART),
|
{ IC_INFO(RTL_ROM_LMP_8822B, 0xc, 0xa, HCI_UART),
|
||||||
.config_needed = true,
|
.config_needed = true,
|
||||||
.has_rom_version = true,
|
.has_rom_version = true,
|
||||||
|
.has_msft_ext = true,
|
||||||
.fw_name = "rtl_bt/rtl8822cs_fw.bin",
|
.fw_name = "rtl_bt/rtl8822cs_fw.bin",
|
||||||
.cfg_name = "rtl_bt/rtl8822cs_config" },
|
.cfg_name = "rtl_bt/rtl8822cs_config" },
|
||||||
|
|
||||||
@ -156,6 +160,7 @@ static const struct id_table ic_id_table[] = {
|
|||||||
{ IC_INFO(RTL_ROM_LMP_8822B, 0xc, 0xa, HCI_USB),
|
{ IC_INFO(RTL_ROM_LMP_8822B, 0xc, 0xa, HCI_USB),
|
||||||
.config_needed = false,
|
.config_needed = false,
|
||||||
.has_rom_version = true,
|
.has_rom_version = true,
|
||||||
|
.has_msft_ext = true,
|
||||||
.fw_name = "rtl_bt/rtl8822cu_fw.bin",
|
.fw_name = "rtl_bt/rtl8822cu_fw.bin",
|
||||||
.cfg_name = "rtl_bt/rtl8822cu_config" },
|
.cfg_name = "rtl_bt/rtl8822cu_config" },
|
||||||
|
|
||||||
@ -163,6 +168,7 @@ static const struct id_table ic_id_table[] = {
|
|||||||
{ IC_INFO(RTL_ROM_LMP_8822B, 0xb, 0x7, HCI_USB),
|
{ IC_INFO(RTL_ROM_LMP_8822B, 0xb, 0x7, HCI_USB),
|
||||||
.config_needed = true,
|
.config_needed = true,
|
||||||
.has_rom_version = true,
|
.has_rom_version = true,
|
||||||
|
.has_msft_ext = true,
|
||||||
.fw_name = "rtl_bt/rtl8822b_fw.bin",
|
.fw_name = "rtl_bt/rtl8822b_fw.bin",
|
||||||
.cfg_name = "rtl_bt/rtl8822b_config" },
|
.cfg_name = "rtl_bt/rtl8822b_config" },
|
||||||
|
|
||||||
@ -170,6 +176,7 @@ static const struct id_table ic_id_table[] = {
|
|||||||
{ IC_INFO(RTL_ROM_LMP_8852A, 0xa, 0xb, HCI_USB),
|
{ IC_INFO(RTL_ROM_LMP_8852A, 0xa, 0xb, HCI_USB),
|
||||||
.config_needed = false,
|
.config_needed = false,
|
||||||
.has_rom_version = true,
|
.has_rom_version = true,
|
||||||
|
.has_msft_ext = true,
|
||||||
.fw_name = "rtl_bt/rtl8852au_fw.bin",
|
.fw_name = "rtl_bt/rtl8852au_fw.bin",
|
||||||
.cfg_name = "rtl_bt/rtl8852au_config" },
|
.cfg_name = "rtl_bt/rtl8852au_config" },
|
||||||
};
|
};
|
||||||
@ -594,8 +601,10 @@ struct btrtl_device_info *btrtl_initialize(struct hci_dev *hdev,
|
|||||||
hci_rev = le16_to_cpu(resp->hci_rev);
|
hci_rev = le16_to_cpu(resp->hci_rev);
|
||||||
lmp_subver = le16_to_cpu(resp->lmp_subver);
|
lmp_subver = le16_to_cpu(resp->lmp_subver);
|
||||||
|
|
||||||
if (resp->hci_ver == 0x8 && le16_to_cpu(resp->hci_rev) == 0x826c &&
|
btrtl_dev->ic_info = btrtl_match_ic(lmp_subver, hci_rev, hci_ver,
|
||||||
resp->lmp_ver == 0x8 && le16_to_cpu(resp->lmp_subver) == 0xa99e)
|
hdev->bus);
|
||||||
|
|
||||||
|
if (!btrtl_dev->ic_info)
|
||||||
btrtl_dev->drop_fw = true;
|
btrtl_dev->drop_fw = true;
|
||||||
|
|
||||||
if (btrtl_dev->drop_fw) {
|
if (btrtl_dev->drop_fw) {
|
||||||
@ -634,13 +643,13 @@ struct btrtl_device_info *btrtl_initialize(struct hci_dev *hdev,
|
|||||||
hci_ver = resp->hci_ver;
|
hci_ver = resp->hci_ver;
|
||||||
hci_rev = le16_to_cpu(resp->hci_rev);
|
hci_rev = le16_to_cpu(resp->hci_rev);
|
||||||
lmp_subver = le16_to_cpu(resp->lmp_subver);
|
lmp_subver = le16_to_cpu(resp->lmp_subver);
|
||||||
|
|
||||||
|
btrtl_dev->ic_info = btrtl_match_ic(lmp_subver, hci_rev, hci_ver,
|
||||||
|
hdev->bus);
|
||||||
}
|
}
|
||||||
out_free:
|
out_free:
|
||||||
kfree_skb(skb);
|
kfree_skb(skb);
|
||||||
|
|
||||||
btrtl_dev->ic_info = btrtl_match_ic(lmp_subver, hci_rev, hci_ver,
|
|
||||||
hdev->bus);
|
|
||||||
|
|
||||||
if (!btrtl_dev->ic_info) {
|
if (!btrtl_dev->ic_info) {
|
||||||
rtl_dev_info(hdev, "unknown IC info, lmp subver %04x, hci rev %04x, hci ver %04x",
|
rtl_dev_info(hdev, "unknown IC info, lmp subver %04x, hci rev %04x, hci ver %04x",
|
||||||
lmp_subver, hci_rev, hci_ver);
|
lmp_subver, hci_rev, hci_ver);
|
||||||
@ -684,12 +693,8 @@ struct btrtl_device_info *btrtl_initialize(struct hci_dev *hdev,
|
|||||||
/* The following chips supports the Microsoft vendor extension,
|
/* The following chips supports the Microsoft vendor extension,
|
||||||
* therefore set the corresponding VsMsftOpCode.
|
* therefore set the corresponding VsMsftOpCode.
|
||||||
*/
|
*/
|
||||||
switch (lmp_subver) {
|
if (btrtl_dev->ic_info->has_msft_ext)
|
||||||
case RTL_ROM_LMP_8822B:
|
|
||||||
case RTL_ROM_LMP_8852A:
|
|
||||||
hci_set_msft_opcode(hdev, 0xFCF0);
|
hci_set_msft_opcode(hdev, 0xFCF0);
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return btrtl_dev;
|
return btrtl_dev;
|
||||||
|
|
||||||
@ -746,6 +751,7 @@ void btrtl_set_quirks(struct hci_dev *hdev, struct btrtl_device_info *btrtl_dev)
|
|||||||
case CHIP_ID_8852A:
|
case CHIP_ID_8852A:
|
||||||
set_bit(HCI_QUIRK_VALID_LE_STATES, &hdev->quirks);
|
set_bit(HCI_QUIRK_VALID_LE_STATES, &hdev->quirks);
|
||||||
set_bit(HCI_QUIRK_WIDEBAND_SPEECH_SUPPORTED, &hdev->quirks);
|
set_bit(HCI_QUIRK_WIDEBAND_SPEECH_SUPPORTED, &hdev->quirks);
|
||||||
|
hci_set_aosp_capable(hdev);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
rtl_dev_dbg(hdev, "Central-peripheral role not enabled.");
|
rtl_dev_dbg(hdev, "Central-peripheral role not enabled.");
|
||||||
|
@ -384,6 +384,12 @@ static const struct usb_device_id blacklist_table[] = {
|
|||||||
/* Realtek 8852AE Bluetooth devices */
|
/* Realtek 8852AE Bluetooth devices */
|
||||||
{ USB_DEVICE(0x0bda, 0xc852), .driver_info = BTUSB_REALTEK |
|
{ USB_DEVICE(0x0bda, 0xc852), .driver_info = BTUSB_REALTEK |
|
||||||
BTUSB_WIDEBAND_SPEECH },
|
BTUSB_WIDEBAND_SPEECH },
|
||||||
|
{ USB_DEVICE(0x0bda, 0x4852), .driver_info = BTUSB_REALTEK |
|
||||||
|
BTUSB_WIDEBAND_SPEECH },
|
||||||
|
{ USB_DEVICE(0x04c5, 0x165c), .driver_info = BTUSB_REALTEK |
|
||||||
|
BTUSB_WIDEBAND_SPEECH },
|
||||||
|
{ USB_DEVICE(0x04ca, 0x4006), .driver_info = BTUSB_REALTEK |
|
||||||
|
BTUSB_WIDEBAND_SPEECH },
|
||||||
|
|
||||||
/* Realtek Bluetooth devices */
|
/* Realtek Bluetooth devices */
|
||||||
{ USB_VENDOR_AND_INTERFACE_INFO(0x0bda, 0xe0, 0x01, 0x01),
|
{ USB_VENDOR_AND_INTERFACE_INFO(0x0bda, 0xe0, 0x01, 0x01),
|
||||||
@ -410,6 +416,9 @@ static const struct usb_device_id blacklist_table[] = {
|
|||||||
{ USB_DEVICE(0x13d3, 0x3563), .driver_info = BTUSB_MEDIATEK |
|
{ USB_DEVICE(0x13d3, 0x3563), .driver_info = BTUSB_MEDIATEK |
|
||||||
BTUSB_WIDEBAND_SPEECH |
|
BTUSB_WIDEBAND_SPEECH |
|
||||||
BTUSB_VALID_LE_STATES },
|
BTUSB_VALID_LE_STATES },
|
||||||
|
{ USB_DEVICE(0x13d3, 0x3564), .driver_info = BTUSB_MEDIATEK |
|
||||||
|
BTUSB_WIDEBAND_SPEECH |
|
||||||
|
BTUSB_VALID_LE_STATES },
|
||||||
{ USB_DEVICE(0x0489, 0xe0cd), .driver_info = BTUSB_MEDIATEK |
|
{ USB_DEVICE(0x0489, 0xe0cd), .driver_info = BTUSB_MEDIATEK |
|
||||||
BTUSB_WIDEBAND_SPEECH |
|
BTUSB_WIDEBAND_SPEECH |
|
||||||
BTUSB_VALID_LE_STATES },
|
BTUSB_VALID_LE_STATES },
|
||||||
@ -433,6 +442,10 @@ static const struct usb_device_id blacklist_table[] = {
|
|||||||
{ USB_DEVICE(0x0bda, 0xb009), .driver_info = BTUSB_REALTEK },
|
{ USB_DEVICE(0x0bda, 0xb009), .driver_info = BTUSB_REALTEK },
|
||||||
{ USB_DEVICE(0x2ff8, 0xb011), .driver_info = BTUSB_REALTEK },
|
{ USB_DEVICE(0x2ff8, 0xb011), .driver_info = BTUSB_REALTEK },
|
||||||
|
|
||||||
|
/* Additional Realtek 8761B Bluetooth devices */
|
||||||
|
{ USB_DEVICE(0x2357, 0x0604), .driver_info = BTUSB_REALTEK |
|
||||||
|
BTUSB_WIDEBAND_SPEECH },
|
||||||
|
|
||||||
/* Additional Realtek 8761BU Bluetooth devices */
|
/* Additional Realtek 8761BU Bluetooth devices */
|
||||||
{ USB_DEVICE(0x0b05, 0x190e), .driver_info = BTUSB_REALTEK |
|
{ USB_DEVICE(0x0b05, 0x190e), .driver_info = BTUSB_REALTEK |
|
||||||
BTUSB_WIDEBAND_SPEECH },
|
BTUSB_WIDEBAND_SPEECH },
|
||||||
@ -451,10 +464,6 @@ static const struct usb_device_id blacklist_table[] = {
|
|||||||
/* Additional Realtek 8822CE Bluetooth devices */
|
/* Additional Realtek 8822CE Bluetooth devices */
|
||||||
{ USB_DEVICE(0x04ca, 0x4005), .driver_info = BTUSB_REALTEK |
|
{ USB_DEVICE(0x04ca, 0x4005), .driver_info = BTUSB_REALTEK |
|
||||||
BTUSB_WIDEBAND_SPEECH },
|
BTUSB_WIDEBAND_SPEECH },
|
||||||
/* Bluetooth component of Realtek 8852AE device */
|
|
||||||
{ USB_DEVICE(0x04ca, 0x4006), .driver_info = BTUSB_REALTEK |
|
|
||||||
BTUSB_WIDEBAND_SPEECH },
|
|
||||||
|
|
||||||
{ USB_DEVICE(0x04c5, 0x161f), .driver_info = BTUSB_REALTEK |
|
{ USB_DEVICE(0x04c5, 0x161f), .driver_info = BTUSB_REALTEK |
|
||||||
BTUSB_WIDEBAND_SPEECH },
|
BTUSB_WIDEBAND_SPEECH },
|
||||||
{ USB_DEVICE(0x0b05, 0x18ef), .driver_info = BTUSB_REALTEK |
|
{ USB_DEVICE(0x0b05, 0x18ef), .driver_info = BTUSB_REALTEK |
|
||||||
@ -652,11 +661,33 @@ static void btusb_rtl_cmd_timeout(struct hci_dev *hdev)
|
|||||||
static void btusb_qca_cmd_timeout(struct hci_dev *hdev)
|
static void btusb_qca_cmd_timeout(struct hci_dev *hdev)
|
||||||
{
|
{
|
||||||
struct btusb_data *data = hci_get_drvdata(hdev);
|
struct btusb_data *data = hci_get_drvdata(hdev);
|
||||||
|
struct gpio_desc *reset_gpio = data->reset_gpio;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
if (++data->cmd_timeout_cnt < 5)
|
if (++data->cmd_timeout_cnt < 5)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (reset_gpio) {
|
||||||
|
bt_dev_err(hdev, "Reset qca device via bt_en gpio");
|
||||||
|
|
||||||
|
/* Toggle the hard reset line. The qca bt device is going to
|
||||||
|
* yank itself off the USB and then replug. The cleanup is handled
|
||||||
|
* correctly on the way out (standard USB disconnect), and the new
|
||||||
|
* device is detected cleanly and bound to the driver again like
|
||||||
|
* it should be.
|
||||||
|
*/
|
||||||
|
if (test_and_set_bit(BTUSB_HW_RESET_ACTIVE, &data->flags)) {
|
||||||
|
bt_dev_err(hdev, "last reset failed? Not resetting again");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
gpiod_set_value_cansleep(reset_gpio, 0);
|
||||||
|
msleep(200);
|
||||||
|
gpiod_set_value_cansleep(reset_gpio, 1);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
bt_dev_err(hdev, "Multiple cmd timeouts seen. Resetting usb device.");
|
bt_dev_err(hdev, "Multiple cmd timeouts seen. Resetting usb device.");
|
||||||
/* This is not an unbalanced PM reference since the device will reset */
|
/* This is not an unbalanced PM reference since the device will reset */
|
||||||
err = usb_autopm_get_interface(data->intf);
|
err = usb_autopm_get_interface(data->intf);
|
||||||
@ -2200,6 +2231,23 @@ struct btmtk_section_map {
|
|||||||
};
|
};
|
||||||
} __packed;
|
} __packed;
|
||||||
|
|
||||||
|
static int btusb_set_bdaddr_mtk(struct hci_dev *hdev, const bdaddr_t *bdaddr)
|
||||||
|
{
|
||||||
|
struct sk_buff *skb;
|
||||||
|
long ret;
|
||||||
|
|
||||||
|
skb = __hci_cmd_sync(hdev, 0xfc1a, sizeof(bdaddr), bdaddr, HCI_INIT_TIMEOUT);
|
||||||
|
if (IS_ERR(skb)) {
|
||||||
|
ret = PTR_ERR(skb);
|
||||||
|
bt_dev_err(hdev, "changing Mediatek device address failed (%ld)",
|
||||||
|
ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
kfree_skb(skb);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static void btusb_mtk_wmt_recv(struct urb *urb)
|
static void btusb_mtk_wmt_recv(struct urb *urb)
|
||||||
{
|
{
|
||||||
struct hci_dev *hdev = urb->context;
|
struct hci_dev *hdev = urb->context;
|
||||||
@ -2804,6 +2852,7 @@ static int btusb_mtk_setup(struct hci_dev *hdev)
|
|||||||
case 0x7668:
|
case 0x7668:
|
||||||
fwname = FIRMWARE_MT7668;
|
fwname = FIRMWARE_MT7668;
|
||||||
break;
|
break;
|
||||||
|
case 0x7922:
|
||||||
case 0x7961:
|
case 0x7961:
|
||||||
snprintf(fw_bin_name, sizeof(fw_bin_name),
|
snprintf(fw_bin_name, sizeof(fw_bin_name),
|
||||||
"mediatek/BT_RAM_CODE_MT%04x_1_%x_hdr.bin",
|
"mediatek/BT_RAM_CODE_MT%04x_1_%x_hdr.bin",
|
||||||
@ -3591,11 +3640,11 @@ static void btusb_check_needs_reset_resume(struct usb_interface *intf)
|
|||||||
interface_to_usbdev(intf)->quirks |= USB_QUIRK_RESET_RESUME;
|
interface_to_usbdev(intf)->quirks |= USB_QUIRK_RESET_RESUME;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool btusb_prevent_wake(struct hci_dev *hdev)
|
static bool btusb_wakeup(struct hci_dev *hdev)
|
||||||
{
|
{
|
||||||
struct btusb_data *data = hci_get_drvdata(hdev);
|
struct btusb_data *data = hci_get_drvdata(hdev);
|
||||||
|
|
||||||
return !device_may_wakeup(&data->udev->dev);
|
return device_may_wakeup(&data->udev->dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int btusb_shutdown_qca(struct hci_dev *hdev)
|
static int btusb_shutdown_qca(struct hci_dev *hdev)
|
||||||
@ -3752,7 +3801,7 @@ static int btusb_probe(struct usb_interface *intf,
|
|||||||
hdev->flush = btusb_flush;
|
hdev->flush = btusb_flush;
|
||||||
hdev->send = btusb_send_frame;
|
hdev->send = btusb_send_frame;
|
||||||
hdev->notify = btusb_notify;
|
hdev->notify = btusb_notify;
|
||||||
hdev->prevent_wake = btusb_prevent_wake;
|
hdev->wakeup = btusb_wakeup;
|
||||||
|
|
||||||
#ifdef CONFIG_PM
|
#ifdef CONFIG_PM
|
||||||
err = btusb_config_oob_wake(hdev);
|
err = btusb_config_oob_wake(hdev);
|
||||||
@ -3819,6 +3868,7 @@ static int btusb_probe(struct usb_interface *intf,
|
|||||||
hdev->shutdown = btusb_mtk_shutdown;
|
hdev->shutdown = btusb_mtk_shutdown;
|
||||||
hdev->manufacturer = 70;
|
hdev->manufacturer = 70;
|
||||||
hdev->cmd_timeout = btusb_mtk_cmd_timeout;
|
hdev->cmd_timeout = btusb_mtk_cmd_timeout;
|
||||||
|
hdev->set_bdaddr = btusb_set_bdaddr_mtk;
|
||||||
set_bit(HCI_QUIRK_NON_PERSISTENT_SETUP, &hdev->quirks);
|
set_bit(HCI_QUIRK_NON_PERSISTENT_SETUP, &hdev->quirks);
|
||||||
data->recv_acl = btusb_recv_acl_mtk;
|
data->recv_acl = btusb_recv_acl_mtk;
|
||||||
}
|
}
|
||||||
|
@ -587,9 +587,11 @@ static int h5_recv(struct hci_uart *hu, const void *data, int count)
|
|||||||
count -= processed;
|
count -= processed;
|
||||||
}
|
}
|
||||||
|
|
||||||
pm_runtime_get(&hu->serdev->dev);
|
if (hu->serdev) {
|
||||||
pm_runtime_mark_last_busy(&hu->serdev->dev);
|
pm_runtime_get(&hu->serdev->dev);
|
||||||
pm_runtime_put_autosuspend(&hu->serdev->dev);
|
pm_runtime_mark_last_busy(&hu->serdev->dev);
|
||||||
|
pm_runtime_put_autosuspend(&hu->serdev->dev);
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -814,7 +816,6 @@ static int h5_serdev_probe(struct serdev_device *serdev)
|
|||||||
struct device *dev = &serdev->dev;
|
struct device *dev = &serdev->dev;
|
||||||
struct h5 *h5;
|
struct h5 *h5;
|
||||||
const struct h5_device_data *data;
|
const struct h5_device_data *data;
|
||||||
int err;
|
|
||||||
|
|
||||||
h5 = devm_kzalloc(dev, sizeof(*h5), GFP_KERNEL);
|
h5 = devm_kzalloc(dev, sizeof(*h5), GFP_KERNEL);
|
||||||
if (!h5)
|
if (!h5)
|
||||||
@ -846,6 +847,8 @@ static int h5_serdev_probe(struct serdev_device *serdev)
|
|||||||
h5->vnd = data->vnd;
|
h5->vnd = data->vnd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (data->driver_info & H5_INFO_WAKEUP_DISABLE)
|
||||||
|
set_bit(H5_WAKEUP_DISABLE, &h5->flags);
|
||||||
|
|
||||||
h5->enable_gpio = devm_gpiod_get_optional(dev, "enable", GPIOD_OUT_LOW);
|
h5->enable_gpio = devm_gpiod_get_optional(dev, "enable", GPIOD_OUT_LOW);
|
||||||
if (IS_ERR(h5->enable_gpio))
|
if (IS_ERR(h5->enable_gpio))
|
||||||
@ -856,14 +859,7 @@ static int h5_serdev_probe(struct serdev_device *serdev)
|
|||||||
if (IS_ERR(h5->device_wake_gpio))
|
if (IS_ERR(h5->device_wake_gpio))
|
||||||
return PTR_ERR(h5->device_wake_gpio);
|
return PTR_ERR(h5->device_wake_gpio);
|
||||||
|
|
||||||
err = hci_uart_register_device(&h5->serdev_hu, &h5p);
|
return hci_uart_register_device(&h5->serdev_hu, &h5p);
|
||||||
if (err)
|
|
||||||
return err;
|
|
||||||
|
|
||||||
if (data->driver_info & H5_INFO_WAKEUP_DISABLE)
|
|
||||||
set_bit(H5_WAKEUP_DISABLE, &h5->flags);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void h5_serdev_remove(struct serdev_device *serdev)
|
static void h5_serdev_remove(struct serdev_device *serdev)
|
||||||
@ -962,11 +958,13 @@ static void h5_btrtl_open(struct h5 *h5)
|
|||||||
serdev_device_set_parity(h5->hu->serdev, SERDEV_PARITY_EVEN);
|
serdev_device_set_parity(h5->hu->serdev, SERDEV_PARITY_EVEN);
|
||||||
serdev_device_set_baudrate(h5->hu->serdev, 115200);
|
serdev_device_set_baudrate(h5->hu->serdev, 115200);
|
||||||
|
|
||||||
pm_runtime_set_active(&h5->hu->serdev->dev);
|
if (!test_bit(H5_WAKEUP_DISABLE, &h5->flags)) {
|
||||||
pm_runtime_use_autosuspend(&h5->hu->serdev->dev);
|
pm_runtime_set_active(&h5->hu->serdev->dev);
|
||||||
pm_runtime_set_autosuspend_delay(&h5->hu->serdev->dev,
|
pm_runtime_use_autosuspend(&h5->hu->serdev->dev);
|
||||||
SUSPEND_TIMEOUT_MS);
|
pm_runtime_set_autosuspend_delay(&h5->hu->serdev->dev,
|
||||||
pm_runtime_enable(&h5->hu->serdev->dev);
|
SUSPEND_TIMEOUT_MS);
|
||||||
|
pm_runtime_enable(&h5->hu->serdev->dev);
|
||||||
|
}
|
||||||
|
|
||||||
/* The controller needs up to 500ms to wakeup */
|
/* The controller needs up to 500ms to wakeup */
|
||||||
gpiod_set_value_cansleep(h5->enable_gpio, 1);
|
gpiod_set_value_cansleep(h5->enable_gpio, 1);
|
||||||
@ -976,7 +974,8 @@ static void h5_btrtl_open(struct h5 *h5)
|
|||||||
|
|
||||||
static void h5_btrtl_close(struct h5 *h5)
|
static void h5_btrtl_close(struct h5 *h5)
|
||||||
{
|
{
|
||||||
pm_runtime_disable(&h5->hu->serdev->dev);
|
if (!test_bit(H5_WAKEUP_DISABLE, &h5->flags))
|
||||||
|
pm_runtime_disable(&h5->hu->serdev->dev);
|
||||||
|
|
||||||
gpiod_set_value_cansleep(h5->device_wake_gpio, 0);
|
gpiod_set_value_cansleep(h5->device_wake_gpio, 0);
|
||||||
gpiod_set_value_cansleep(h5->enable_gpio, 0);
|
gpiod_set_value_cansleep(h5->enable_gpio, 0);
|
||||||
|
@ -479,6 +479,9 @@ static int hci_uart_tty_open(struct tty_struct *tty)
|
|||||||
|
|
||||||
BT_DBG("tty %p", tty);
|
BT_DBG("tty %p", tty);
|
||||||
|
|
||||||
|
if (!capable(CAP_NET_ADMIN))
|
||||||
|
return -EPERM;
|
||||||
|
|
||||||
/* Error if the tty has no write op instead of leaving an exploitable
|
/* Error if the tty has no write op instead of leaving an exploitable
|
||||||
* hole
|
* hole
|
||||||
*/
|
*/
|
||||||
|
@ -1577,7 +1577,7 @@ static void qca_cmd_timeout(struct hci_dev *hdev)
|
|||||||
mutex_unlock(&qca->hci_memdump_lock);
|
mutex_unlock(&qca->hci_memdump_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool qca_prevent_wake(struct hci_dev *hdev)
|
static bool qca_wakeup(struct hci_dev *hdev)
|
||||||
{
|
{
|
||||||
struct hci_uart *hu = hci_get_drvdata(hdev);
|
struct hci_uart *hu = hci_get_drvdata(hdev);
|
||||||
bool wakeup;
|
bool wakeup;
|
||||||
@ -1730,6 +1730,7 @@ static int qca_setup(struct hci_uart *hu)
|
|||||||
if (qca_is_wcn399x(soc_type) ||
|
if (qca_is_wcn399x(soc_type) ||
|
||||||
qca_is_wcn6750(soc_type)) {
|
qca_is_wcn6750(soc_type)) {
|
||||||
set_bit(HCI_QUIRK_USE_BDADDR_PROPERTY, &hdev->quirks);
|
set_bit(HCI_QUIRK_USE_BDADDR_PROPERTY, &hdev->quirks);
|
||||||
|
hci_set_aosp_capable(hdev);
|
||||||
|
|
||||||
ret = qca_read_soc_version(hdev, &ver, soc_type);
|
ret = qca_read_soc_version(hdev, &ver, soc_type);
|
||||||
if (ret)
|
if (ret)
|
||||||
@ -1764,7 +1765,7 @@ static int qca_setup(struct hci_uart *hu)
|
|||||||
qca_debugfs_init(hdev);
|
qca_debugfs_init(hdev);
|
||||||
hu->hdev->hw_error = qca_hw_error;
|
hu->hdev->hw_error = qca_hw_error;
|
||||||
hu->hdev->cmd_timeout = qca_cmd_timeout;
|
hu->hdev->cmd_timeout = qca_cmd_timeout;
|
||||||
hu->hdev->prevent_wake = qca_prevent_wake;
|
hu->hdev->wakeup = qca_wakeup;
|
||||||
} else if (ret == -ENOENT) {
|
} else if (ret == -ENOENT) {
|
||||||
/* No patch/nvm-config found, run with original fw/config */
|
/* No patch/nvm-config found, run with original fw/config */
|
||||||
set_bit(QCA_ROM_FW, &qca->flags);
|
set_bit(QCA_ROM_FW, &qca->flags);
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
|
|
||||||
#include <linux/skbuff.h>
|
#include <linux/skbuff.h>
|
||||||
#include <linux/miscdevice.h>
|
#include <linux/miscdevice.h>
|
||||||
|
#include <linux/debugfs.h>
|
||||||
|
|
||||||
#include <net/bluetooth/bluetooth.h>
|
#include <net/bluetooth/bluetooth.h>
|
||||||
#include <net/bluetooth/hci_core.h>
|
#include <net/bluetooth/hci_core.h>
|
||||||
@ -37,6 +38,9 @@ struct vhci_data {
|
|||||||
|
|
||||||
struct mutex open_mutex;
|
struct mutex open_mutex;
|
||||||
struct delayed_work open_timeout;
|
struct delayed_work open_timeout;
|
||||||
|
|
||||||
|
bool suspended;
|
||||||
|
bool wakeup;
|
||||||
};
|
};
|
||||||
|
|
||||||
static int vhci_open_dev(struct hci_dev *hdev)
|
static int vhci_open_dev(struct hci_dev *hdev)
|
||||||
@ -73,6 +77,115 @@ static int vhci_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int vhci_get_data_path_id(struct hci_dev *hdev, u8 *data_path_id)
|
||||||
|
{
|
||||||
|
*data_path_id = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int vhci_get_codec_config_data(struct hci_dev *hdev, __u8 type,
|
||||||
|
struct bt_codec *codec, __u8 *vnd_len,
|
||||||
|
__u8 **vnd_data)
|
||||||
|
{
|
||||||
|
if (type != ESCO_LINK)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
*vnd_len = 0;
|
||||||
|
*vnd_data = NULL;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool vhci_wakeup(struct hci_dev *hdev)
|
||||||
|
{
|
||||||
|
struct vhci_data *data = hci_get_drvdata(hdev);
|
||||||
|
|
||||||
|
return data->wakeup;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t force_suspend_read(struct file *file, char __user *user_buf,
|
||||||
|
size_t count, loff_t *ppos)
|
||||||
|
{
|
||||||
|
struct vhci_data *data = file->private_data;
|
||||||
|
char buf[3];
|
||||||
|
|
||||||
|
buf[0] = data->suspended ? 'Y' : 'N';
|
||||||
|
buf[1] = '\n';
|
||||||
|
buf[2] = '\0';
|
||||||
|
return simple_read_from_buffer(user_buf, count, ppos, buf, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t force_suspend_write(struct file *file,
|
||||||
|
const char __user *user_buf,
|
||||||
|
size_t count, loff_t *ppos)
|
||||||
|
{
|
||||||
|
struct vhci_data *data = file->private_data;
|
||||||
|
bool enable;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
err = kstrtobool_from_user(user_buf, count, &enable);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
if (data->suspended == enable)
|
||||||
|
return -EALREADY;
|
||||||
|
|
||||||
|
if (enable)
|
||||||
|
err = hci_suspend_dev(data->hdev);
|
||||||
|
else
|
||||||
|
err = hci_resume_dev(data->hdev);
|
||||||
|
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
data->suspended = enable;
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct file_operations force_suspend_fops = {
|
||||||
|
.open = simple_open,
|
||||||
|
.read = force_suspend_read,
|
||||||
|
.write = force_suspend_write,
|
||||||
|
.llseek = default_llseek,
|
||||||
|
};
|
||||||
|
|
||||||
|
static ssize_t force_wakeup_read(struct file *file, char __user *user_buf,
|
||||||
|
size_t count, loff_t *ppos)
|
||||||
|
{
|
||||||
|
struct vhci_data *data = file->private_data;
|
||||||
|
char buf[3];
|
||||||
|
|
||||||
|
buf[0] = data->wakeup ? 'Y' : 'N';
|
||||||
|
buf[1] = '\n';
|
||||||
|
buf[2] = '\0';
|
||||||
|
return simple_read_from_buffer(user_buf, count, ppos, buf, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t force_wakeup_write(struct file *file,
|
||||||
|
const char __user *user_buf, size_t count,
|
||||||
|
loff_t *ppos)
|
||||||
|
{
|
||||||
|
struct vhci_data *data = file->private_data;
|
||||||
|
bool enable;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
err = kstrtobool_from_user(user_buf, count, &enable);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
if (data->wakeup == enable)
|
||||||
|
return -EALREADY;
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct file_operations force_wakeup_fops = {
|
||||||
|
.open = simple_open,
|
||||||
|
.read = force_wakeup_read,
|
||||||
|
.write = force_wakeup_write,
|
||||||
|
.llseek = default_llseek,
|
||||||
|
};
|
||||||
|
|
||||||
static int __vhci_create_device(struct vhci_data *data, __u8 opcode)
|
static int __vhci_create_device(struct vhci_data *data, __u8 opcode)
|
||||||
{
|
{
|
||||||
struct hci_dev *hdev;
|
struct hci_dev *hdev;
|
||||||
@ -112,6 +225,9 @@ static int __vhci_create_device(struct vhci_data *data, __u8 opcode)
|
|||||||
hdev->close = vhci_close_dev;
|
hdev->close = vhci_close_dev;
|
||||||
hdev->flush = vhci_flush;
|
hdev->flush = vhci_flush;
|
||||||
hdev->send = vhci_send_frame;
|
hdev->send = vhci_send_frame;
|
||||||
|
hdev->get_data_path_id = vhci_get_data_path_id;
|
||||||
|
hdev->get_codec_config_data = vhci_get_codec_config_data;
|
||||||
|
hdev->wakeup = vhci_wakeup;
|
||||||
|
|
||||||
/* bit 6 is for external configuration */
|
/* bit 6 is for external configuration */
|
||||||
if (opcode & 0x40)
|
if (opcode & 0x40)
|
||||||
@ -129,6 +245,12 @@ static int __vhci_create_device(struct vhci_data *data, __u8 opcode)
|
|||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
debugfs_create_file("force_suspend", 0644, hdev->debugfs, data,
|
||||||
|
&force_suspend_fops);
|
||||||
|
|
||||||
|
debugfs_create_file("force_wakeup", 0644, hdev->debugfs, data,
|
||||||
|
&force_wakeup_fops);
|
||||||
|
|
||||||
hci_skb_pkt_type(skb) = HCI_VENDOR_PKT;
|
hci_skb_pkt_type(skb) = HCI_VENDOR_PKT;
|
||||||
|
|
||||||
skb_put_u8(skb, 0xff);
|
skb_put_u8(skb, 0xff);
|
||||||
|
@ -1443,8 +1443,8 @@ static int fwnet_probe(struct fw_unit *unit,
|
|||||||
struct net_device *net;
|
struct net_device *net;
|
||||||
bool allocated_netdev = false;
|
bool allocated_netdev = false;
|
||||||
struct fwnet_device *dev;
|
struct fwnet_device *dev;
|
||||||
|
union fwnet_hwaddr ha;
|
||||||
int ret;
|
int ret;
|
||||||
union fwnet_hwaddr *ha;
|
|
||||||
|
|
||||||
mutex_lock(&fwnet_device_mutex);
|
mutex_lock(&fwnet_device_mutex);
|
||||||
|
|
||||||
@ -1491,12 +1491,12 @@ static int fwnet_probe(struct fw_unit *unit,
|
|||||||
net->max_mtu = 4096U;
|
net->max_mtu = 4096U;
|
||||||
|
|
||||||
/* Set our hardware address while we're at it */
|
/* Set our hardware address while we're at it */
|
||||||
ha = (union fwnet_hwaddr *)net->dev_addr;
|
ha.uc.uniq_id = cpu_to_be64(card->guid);
|
||||||
put_unaligned_be64(card->guid, &ha->uc.uniq_id);
|
ha.uc.max_rec = dev->card->max_receive;
|
||||||
ha->uc.max_rec = dev->card->max_receive;
|
ha.uc.sspd = dev->card->link_speed;
|
||||||
ha->uc.sspd = dev->card->link_speed;
|
ha.uc.fifo_hi = cpu_to_be16(dev->local_fifo >> 32);
|
||||||
put_unaligned_be16(dev->local_fifo >> 32, &ha->uc.fifo_hi);
|
ha.uc.fifo_lo = cpu_to_be32(dev->local_fifo & 0xffffffff);
|
||||||
put_unaligned_be32(dev->local_fifo & 0xffffffff, &ha->uc.fifo_lo);
|
dev_addr_set(net, ha.u);
|
||||||
|
|
||||||
memset(net->broadcast, -1, net->addr_len);
|
memset(net->broadcast, -1, net->addr_len);
|
||||||
|
|
||||||
|
@ -1055,14 +1055,16 @@ static const struct net_device_ops ssip_pn_ops = {
|
|||||||
|
|
||||||
static void ssip_pn_setup(struct net_device *dev)
|
static void ssip_pn_setup(struct net_device *dev)
|
||||||
{
|
{
|
||||||
|
static const u8 addr = PN_MEDIA_SOS;
|
||||||
|
|
||||||
dev->features = 0;
|
dev->features = 0;
|
||||||
dev->netdev_ops = &ssip_pn_ops;
|
dev->netdev_ops = &ssip_pn_ops;
|
||||||
dev->type = ARPHRD_PHONET;
|
dev->type = ARPHRD_PHONET;
|
||||||
dev->flags = IFF_POINTOPOINT | IFF_NOARP;
|
dev->flags = IFF_POINTOPOINT | IFF_NOARP;
|
||||||
dev->mtu = SSIP_DEFAULT_MTU;
|
dev->mtu = SSIP_DEFAULT_MTU;
|
||||||
dev->hard_header_len = 1;
|
dev->hard_header_len = 1;
|
||||||
dev->dev_addr[0] = PN_MEDIA_SOS;
|
|
||||||
dev->addr_len = 1;
|
dev->addr_len = 1;
|
||||||
|
dev_addr_set(dev, &addr);
|
||||||
dev->tx_queue_len = SSIP_TXQUEUE_LEN;
|
dev->tx_queue_len = SSIP_TXQUEUE_LEN;
|
||||||
|
|
||||||
dev->needs_free_netdev = true;
|
dev->needs_free_netdev = true;
|
||||||
|
@ -2275,7 +2275,7 @@ static void mlx4_ib_update_qps(struct mlx4_ib_dev *ibdev,
|
|||||||
u64 release_mac = MLX4_IB_INVALID_MAC;
|
u64 release_mac = MLX4_IB_INVALID_MAC;
|
||||||
struct mlx4_ib_qp *qp;
|
struct mlx4_ib_qp *qp;
|
||||||
|
|
||||||
new_smac = mlx4_mac_to_u64(dev->dev_addr);
|
new_smac = ether_addr_to_u64(dev->dev_addr);
|
||||||
atomic64_set(&ibdev->iboe.mac[port - 1], new_smac);
|
atomic64_set(&ibdev->iboe.mac[port - 1], new_smac);
|
||||||
|
|
||||||
/* no need for update QP1 and mac registration in non-SRIOV */
|
/* no need for update QP1 and mac registration in non-SRIOV */
|
||||||
|
@ -1853,7 +1853,7 @@ static int mlx4_set_path(struct mlx4_ib_dev *dev, const struct ib_qp_attr *qp,
|
|||||||
u16 vlan_id, u8 *smac)
|
u16 vlan_id, u8 *smac)
|
||||||
{
|
{
|
||||||
return _mlx4_set_path(dev, &qp->ah_attr,
|
return _mlx4_set_path(dev, &qp->ah_attr,
|
||||||
mlx4_mac_to_u64(smac),
|
ether_addr_to_u64(smac),
|
||||||
vlan_id,
|
vlan_id,
|
||||||
path, &mqp->pri, port);
|
path, &mqp->pri, port);
|
||||||
}
|
}
|
||||||
|
@ -206,3 +206,29 @@ int mlx5_cmd_mad_ifc(struct mlx5_core_dev *dev, const void *inb, void *outb,
|
|||||||
kfree(in);
|
kfree(in);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int mlx5_cmd_uar_alloc(struct mlx5_core_dev *dev, u32 *uarn, u16 uid)
|
||||||
|
{
|
||||||
|
u32 out[MLX5_ST_SZ_DW(alloc_uar_out)] = {};
|
||||||
|
u32 in[MLX5_ST_SZ_DW(alloc_uar_in)] = {};
|
||||||
|
int err;
|
||||||
|
|
||||||
|
MLX5_SET(alloc_uar_in, in, opcode, MLX5_CMD_OP_ALLOC_UAR);
|
||||||
|
MLX5_SET(alloc_uar_in, in, uid, uid);
|
||||||
|
err = mlx5_cmd_exec_inout(dev, alloc_uar, in, out);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
*uarn = MLX5_GET(alloc_uar_out, out, uar);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int mlx5_cmd_uar_dealloc(struct mlx5_core_dev *dev, u32 uarn, u16 uid)
|
||||||
|
{
|
||||||
|
u32 in[MLX5_ST_SZ_DW(dealloc_uar_in)] = {};
|
||||||
|
|
||||||
|
MLX5_SET(dealloc_uar_in, in, opcode, MLX5_CMD_OP_DEALLOC_UAR);
|
||||||
|
MLX5_SET(dealloc_uar_in, in, uar, uarn);
|
||||||
|
MLX5_SET(dealloc_uar_in, in, uid, uid);
|
||||||
|
return mlx5_cmd_exec_in(dev, dealloc_uar, in);
|
||||||
|
}
|
||||||
|
@ -57,4 +57,6 @@ int mlx5_cmd_xrcd_alloc(struct mlx5_core_dev *dev, u32 *xrcdn, u16 uid);
|
|||||||
int mlx5_cmd_xrcd_dealloc(struct mlx5_core_dev *dev, u32 xrcdn, u16 uid);
|
int mlx5_cmd_xrcd_dealloc(struct mlx5_core_dev *dev, u32 xrcdn, u16 uid);
|
||||||
int mlx5_cmd_mad_ifc(struct mlx5_core_dev *dev, const void *inb, void *outb,
|
int mlx5_cmd_mad_ifc(struct mlx5_core_dev *dev, const void *inb, void *outb,
|
||||||
u16 opmod, u8 port);
|
u16 opmod, u8 port);
|
||||||
|
int mlx5_cmd_uar_alloc(struct mlx5_core_dev *dev, u32 *uarn, u16 uid);
|
||||||
|
int mlx5_cmd_uar_dealloc(struct mlx5_core_dev *dev, u32 uarn, u16 uid);
|
||||||
#endif /* MLX5_IB_CMD_H */
|
#endif /* MLX5_IB_CMD_H */
|
||||||
|
@ -1292,21 +1292,16 @@ static int devx_handle_mkey_indirect(struct devx_obj *obj,
|
|||||||
struct mlx5_ib_dev *dev,
|
struct mlx5_ib_dev *dev,
|
||||||
void *in, void *out)
|
void *in, void *out)
|
||||||
{
|
{
|
||||||
struct mlx5_ib_devx_mr *devx_mr = &obj->devx_mr;
|
struct mlx5_ib_mkey *mkey = &obj->mkey;
|
||||||
struct mlx5_core_mkey *mkey;
|
|
||||||
void *mkc;
|
void *mkc;
|
||||||
u8 key;
|
u8 key;
|
||||||
|
|
||||||
mkey = &devx_mr->mmkey;
|
|
||||||
mkc = MLX5_ADDR_OF(create_mkey_in, in, memory_key_mkey_entry);
|
mkc = MLX5_ADDR_OF(create_mkey_in, in, memory_key_mkey_entry);
|
||||||
key = MLX5_GET(mkc, mkc, mkey_7_0);
|
key = MLX5_GET(mkc, mkc, mkey_7_0);
|
||||||
mkey->key = mlx5_idx_to_mkey(
|
mkey->key = mlx5_idx_to_mkey(
|
||||||
MLX5_GET(create_mkey_out, out, mkey_index)) | key;
|
MLX5_GET(create_mkey_out, out, mkey_index)) | key;
|
||||||
mkey->type = MLX5_MKEY_INDIRECT_DEVX;
|
mkey->type = MLX5_MKEY_INDIRECT_DEVX;
|
||||||
mkey->iova = MLX5_GET64(mkc, mkc, start_addr);
|
mkey->ndescs = MLX5_GET(mkc, mkc, translations_octword_size);
|
||||||
mkey->size = MLX5_GET64(mkc, mkc, len);
|
|
||||||
mkey->pd = MLX5_GET(mkc, mkc, pd);
|
|
||||||
devx_mr->ndescs = MLX5_GET(mkc, mkc, translations_octword_size);
|
|
||||||
init_waitqueue_head(&mkey->wait);
|
init_waitqueue_head(&mkey->wait);
|
||||||
|
|
||||||
return mlx5r_store_odp_mkey(dev, mkey);
|
return mlx5r_store_odp_mkey(dev, mkey);
|
||||||
@ -1384,13 +1379,13 @@ static int devx_obj_cleanup(struct ib_uobject *uobject,
|
|||||||
dev = mlx5_udata_to_mdev(&attrs->driver_udata);
|
dev = mlx5_udata_to_mdev(&attrs->driver_udata);
|
||||||
if (obj->flags & DEVX_OBJ_FLAGS_INDIRECT_MKEY &&
|
if (obj->flags & DEVX_OBJ_FLAGS_INDIRECT_MKEY &&
|
||||||
xa_erase(&obj->ib_dev->odp_mkeys,
|
xa_erase(&obj->ib_dev->odp_mkeys,
|
||||||
mlx5_base_mkey(obj->devx_mr.mmkey.key)))
|
mlx5_base_mkey(obj->mkey.key)))
|
||||||
/*
|
/*
|
||||||
* The pagefault_single_data_segment() does commands against
|
* The pagefault_single_data_segment() does commands against
|
||||||
* the mmkey, we must wait for that to stop before freeing the
|
* the mmkey, we must wait for that to stop before freeing the
|
||||||
* mkey, as another allocation could get the same mkey #.
|
* mkey, as another allocation could get the same mkey #.
|
||||||
*/
|
*/
|
||||||
mlx5r_deref_wait_odp_mkey(&obj->devx_mr.mmkey);
|
mlx5r_deref_wait_odp_mkey(&obj->mkey);
|
||||||
|
|
||||||
if (obj->flags & DEVX_OBJ_FLAGS_DCT)
|
if (obj->flags & DEVX_OBJ_FLAGS_DCT)
|
||||||
ret = mlx5_core_destroy_dct(obj->ib_dev, &obj->core_dct);
|
ret = mlx5_core_destroy_dct(obj->ib_dev, &obj->core_dct);
|
||||||
|
@ -16,7 +16,7 @@ struct devx_obj {
|
|||||||
u32 dinbox[MLX5_MAX_DESTROY_INBOX_SIZE_DW];
|
u32 dinbox[MLX5_MAX_DESTROY_INBOX_SIZE_DW];
|
||||||
u32 flags;
|
u32 flags;
|
||||||
union {
|
union {
|
||||||
struct mlx5_ib_devx_mr devx_mr;
|
struct mlx5_ib_mkey mkey;
|
||||||
struct mlx5_core_dct core_dct;
|
struct mlx5_core_dct core_dct;
|
||||||
struct mlx5_core_cq core_cq;
|
struct mlx5_core_cq core_cq;
|
||||||
u32 flow_counter_bulk_size;
|
u32 flow_counter_bulk_size;
|
||||||
|
@ -1643,7 +1643,8 @@ static int allocate_uars(struct mlx5_ib_dev *dev, struct mlx5_ib_ucontext *conte
|
|||||||
|
|
||||||
bfregi = &context->bfregi;
|
bfregi = &context->bfregi;
|
||||||
for (i = 0; i < bfregi->num_static_sys_pages; i++) {
|
for (i = 0; i < bfregi->num_static_sys_pages; i++) {
|
||||||
err = mlx5_cmd_alloc_uar(dev->mdev, &bfregi->sys_pages[i]);
|
err = mlx5_cmd_uar_alloc(dev->mdev, &bfregi->sys_pages[i],
|
||||||
|
context->devx_uid);
|
||||||
if (err)
|
if (err)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
@ -1657,7 +1658,8 @@ static int allocate_uars(struct mlx5_ib_dev *dev, struct mlx5_ib_ucontext *conte
|
|||||||
|
|
||||||
error:
|
error:
|
||||||
for (--i; i >= 0; i--)
|
for (--i; i >= 0; i--)
|
||||||
if (mlx5_cmd_free_uar(dev->mdev, bfregi->sys_pages[i]))
|
if (mlx5_cmd_uar_dealloc(dev->mdev, bfregi->sys_pages[i],
|
||||||
|
context->devx_uid))
|
||||||
mlx5_ib_warn(dev, "failed to free uar %d\n", i);
|
mlx5_ib_warn(dev, "failed to free uar %d\n", i);
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
@ -1673,7 +1675,8 @@ static void deallocate_uars(struct mlx5_ib_dev *dev,
|
|||||||
for (i = 0; i < bfregi->num_sys_pages; i++)
|
for (i = 0; i < bfregi->num_sys_pages; i++)
|
||||||
if (i < bfregi->num_static_sys_pages ||
|
if (i < bfregi->num_static_sys_pages ||
|
||||||
bfregi->sys_pages[i] != MLX5_IB_INVALID_UAR_INDEX)
|
bfregi->sys_pages[i] != MLX5_IB_INVALID_UAR_INDEX)
|
||||||
mlx5_cmd_free_uar(dev->mdev, bfregi->sys_pages[i]);
|
mlx5_cmd_uar_dealloc(dev->mdev, bfregi->sys_pages[i],
|
||||||
|
context->devx_uid);
|
||||||
}
|
}
|
||||||
|
|
||||||
int mlx5_ib_enable_lb(struct mlx5_ib_dev *dev, bool td, bool qp)
|
int mlx5_ib_enable_lb(struct mlx5_ib_dev *dev, bool td, bool qp)
|
||||||
@ -1891,6 +1894,13 @@ static int mlx5_ib_alloc_ucontext(struct ib_ucontext *uctx,
|
|||||||
if (req.num_low_latency_bfregs > req.total_num_bfregs - 1)
|
if (req.num_low_latency_bfregs > req.total_num_bfregs - 1)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
|
if (req.flags & MLX5_IB_ALLOC_UCTX_DEVX) {
|
||||||
|
err = mlx5_ib_devx_create(dev, true);
|
||||||
|
if (err < 0)
|
||||||
|
goto out_ctx;
|
||||||
|
context->devx_uid = err;
|
||||||
|
}
|
||||||
|
|
||||||
lib_uar_4k = req.lib_caps & MLX5_LIB_CAP_4K_UAR;
|
lib_uar_4k = req.lib_caps & MLX5_LIB_CAP_4K_UAR;
|
||||||
lib_uar_dyn = req.lib_caps & MLX5_LIB_CAP_DYN_UAR;
|
lib_uar_dyn = req.lib_caps & MLX5_LIB_CAP_DYN_UAR;
|
||||||
bfregi = &context->bfregi;
|
bfregi = &context->bfregi;
|
||||||
@ -1903,7 +1913,7 @@ static int mlx5_ib_alloc_ucontext(struct ib_ucontext *uctx,
|
|||||||
/* updates req->total_num_bfregs */
|
/* updates req->total_num_bfregs */
|
||||||
err = calc_total_bfregs(dev, lib_uar_4k, &req, bfregi);
|
err = calc_total_bfregs(dev, lib_uar_4k, &req, bfregi);
|
||||||
if (err)
|
if (err)
|
||||||
goto out_ctx;
|
goto out_devx;
|
||||||
|
|
||||||
mutex_init(&bfregi->lock);
|
mutex_init(&bfregi->lock);
|
||||||
bfregi->lib_uar_4k = lib_uar_4k;
|
bfregi->lib_uar_4k = lib_uar_4k;
|
||||||
@ -1911,7 +1921,7 @@ static int mlx5_ib_alloc_ucontext(struct ib_ucontext *uctx,
|
|||||||
GFP_KERNEL);
|
GFP_KERNEL);
|
||||||
if (!bfregi->count) {
|
if (!bfregi->count) {
|
||||||
err = -ENOMEM;
|
err = -ENOMEM;
|
||||||
goto out_ctx;
|
goto out_devx;
|
||||||
}
|
}
|
||||||
|
|
||||||
bfregi->sys_pages = kcalloc(bfregi->num_sys_pages,
|
bfregi->sys_pages = kcalloc(bfregi->num_sys_pages,
|
||||||
@ -1927,17 +1937,10 @@ static int mlx5_ib_alloc_ucontext(struct ib_ucontext *uctx,
|
|||||||
goto out_sys_pages;
|
goto out_sys_pages;
|
||||||
|
|
||||||
uar_done:
|
uar_done:
|
||||||
if (req.flags & MLX5_IB_ALLOC_UCTX_DEVX) {
|
|
||||||
err = mlx5_ib_devx_create(dev, true);
|
|
||||||
if (err < 0)
|
|
||||||
goto out_uars;
|
|
||||||
context->devx_uid = err;
|
|
||||||
}
|
|
||||||
|
|
||||||
err = mlx5_ib_alloc_transport_domain(dev, &context->tdn,
|
err = mlx5_ib_alloc_transport_domain(dev, &context->tdn,
|
||||||
context->devx_uid);
|
context->devx_uid);
|
||||||
if (err)
|
if (err)
|
||||||
goto out_devx;
|
goto out_uars;
|
||||||
|
|
||||||
INIT_LIST_HEAD(&context->db_page_list);
|
INIT_LIST_HEAD(&context->db_page_list);
|
||||||
mutex_init(&context->db_page_mutex);
|
mutex_init(&context->db_page_mutex);
|
||||||
@ -1972,9 +1975,6 @@ static int mlx5_ib_alloc_ucontext(struct ib_ucontext *uctx,
|
|||||||
|
|
||||||
out_mdev:
|
out_mdev:
|
||||||
mlx5_ib_dealloc_transport_domain(dev, context->tdn, context->devx_uid);
|
mlx5_ib_dealloc_transport_domain(dev, context->tdn, context->devx_uid);
|
||||||
out_devx:
|
|
||||||
if (req.flags & MLX5_IB_ALLOC_UCTX_DEVX)
|
|
||||||
mlx5_ib_devx_destroy(dev, context->devx_uid);
|
|
||||||
|
|
||||||
out_uars:
|
out_uars:
|
||||||
deallocate_uars(dev, context);
|
deallocate_uars(dev, context);
|
||||||
@ -1985,6 +1985,10 @@ static int mlx5_ib_alloc_ucontext(struct ib_ucontext *uctx,
|
|||||||
out_count:
|
out_count:
|
||||||
kfree(bfregi->count);
|
kfree(bfregi->count);
|
||||||
|
|
||||||
|
out_devx:
|
||||||
|
if (req.flags & MLX5_IB_ALLOC_UCTX_DEVX)
|
||||||
|
mlx5_ib_devx_destroy(dev, context->devx_uid);
|
||||||
|
|
||||||
out_ctx:
|
out_ctx:
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
@ -2021,12 +2025,12 @@ static void mlx5_ib_dealloc_ucontext(struct ib_ucontext *ibcontext)
|
|||||||
bfregi = &context->bfregi;
|
bfregi = &context->bfregi;
|
||||||
mlx5_ib_dealloc_transport_domain(dev, context->tdn, context->devx_uid);
|
mlx5_ib_dealloc_transport_domain(dev, context->tdn, context->devx_uid);
|
||||||
|
|
||||||
if (context->devx_uid)
|
|
||||||
mlx5_ib_devx_destroy(dev, context->devx_uid);
|
|
||||||
|
|
||||||
deallocate_uars(dev, context);
|
deallocate_uars(dev, context);
|
||||||
kfree(bfregi->sys_pages);
|
kfree(bfregi->sys_pages);
|
||||||
kfree(bfregi->count);
|
kfree(bfregi->count);
|
||||||
|
|
||||||
|
if (context->devx_uid)
|
||||||
|
mlx5_ib_devx_destroy(dev, context->devx_uid);
|
||||||
}
|
}
|
||||||
|
|
||||||
static phys_addr_t uar_index2pfn(struct mlx5_ib_dev *dev,
|
static phys_addr_t uar_index2pfn(struct mlx5_ib_dev *dev,
|
||||||
@ -2119,6 +2123,7 @@ static void mlx5_ib_mmap_free(struct rdma_user_mmap_entry *entry)
|
|||||||
struct mlx5_user_mmap_entry *mentry = to_mmmap(entry);
|
struct mlx5_user_mmap_entry *mentry = to_mmmap(entry);
|
||||||
struct mlx5_ib_dev *dev = to_mdev(entry->ucontext->device);
|
struct mlx5_ib_dev *dev = to_mdev(entry->ucontext->device);
|
||||||
struct mlx5_var_table *var_table = &dev->var_table;
|
struct mlx5_var_table *var_table = &dev->var_table;
|
||||||
|
struct mlx5_ib_ucontext *context = to_mucontext(entry->ucontext);
|
||||||
|
|
||||||
switch (mentry->mmap_flag) {
|
switch (mentry->mmap_flag) {
|
||||||
case MLX5_IB_MMAP_TYPE_MEMIC:
|
case MLX5_IB_MMAP_TYPE_MEMIC:
|
||||||
@ -2133,7 +2138,8 @@ static void mlx5_ib_mmap_free(struct rdma_user_mmap_entry *entry)
|
|||||||
break;
|
break;
|
||||||
case MLX5_IB_MMAP_TYPE_UAR_WC:
|
case MLX5_IB_MMAP_TYPE_UAR_WC:
|
||||||
case MLX5_IB_MMAP_TYPE_UAR_NC:
|
case MLX5_IB_MMAP_TYPE_UAR_NC:
|
||||||
mlx5_cmd_free_uar(dev->mdev, mentry->page_idx);
|
mlx5_cmd_uar_dealloc(dev->mdev, mentry->page_idx,
|
||||||
|
context->devx_uid);
|
||||||
kfree(mentry);
|
kfree(mentry);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -2211,7 +2217,8 @@ static int uar_mmap(struct mlx5_ib_dev *dev, enum mlx5_ib_mmap_cmd cmd,
|
|||||||
bfregi->count[bfreg_dyn_idx]++;
|
bfregi->count[bfreg_dyn_idx]++;
|
||||||
mutex_unlock(&bfregi->lock);
|
mutex_unlock(&bfregi->lock);
|
||||||
|
|
||||||
err = mlx5_cmd_alloc_uar(dev->mdev, &uar_index);
|
err = mlx5_cmd_uar_alloc(dev->mdev, &uar_index,
|
||||||
|
context->devx_uid);
|
||||||
if (err) {
|
if (err) {
|
||||||
mlx5_ib_warn(dev, "UAR alloc failed\n");
|
mlx5_ib_warn(dev, "UAR alloc failed\n");
|
||||||
goto free_bfreg;
|
goto free_bfreg;
|
||||||
@ -2240,7 +2247,7 @@ static int uar_mmap(struct mlx5_ib_dev *dev, enum mlx5_ib_mmap_cmd cmd,
|
|||||||
if (!dyn_uar)
|
if (!dyn_uar)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
mlx5_cmd_free_uar(dev->mdev, idx);
|
mlx5_cmd_uar_dealloc(dev->mdev, idx, context->devx_uid);
|
||||||
|
|
||||||
free_bfreg:
|
free_bfreg:
|
||||||
mlx5_ib_free_bfreg(dev, bfregi, bfreg_dyn_idx);
|
mlx5_ib_free_bfreg(dev, bfregi, bfreg_dyn_idx);
|
||||||
@ -3489,7 +3496,7 @@ alloc_uar_entry(struct mlx5_ib_ucontext *c,
|
|||||||
return ERR_PTR(-ENOMEM);
|
return ERR_PTR(-ENOMEM);
|
||||||
|
|
||||||
dev = to_mdev(c->ibucontext.device);
|
dev = to_mdev(c->ibucontext.device);
|
||||||
err = mlx5_cmd_alloc_uar(dev->mdev, &uar_index);
|
err = mlx5_cmd_uar_alloc(dev->mdev, &uar_index, c->devx_uid);
|
||||||
if (err)
|
if (err)
|
||||||
goto end;
|
goto end;
|
||||||
|
|
||||||
@ -3507,7 +3514,7 @@ alloc_uar_entry(struct mlx5_ib_ucontext *c,
|
|||||||
return entry;
|
return entry;
|
||||||
|
|
||||||
err_insert:
|
err_insert:
|
||||||
mlx5_cmd_free_uar(dev->mdev, uar_index);
|
mlx5_cmd_uar_dealloc(dev->mdev, uar_index, c->devx_uid);
|
||||||
end:
|
end:
|
||||||
kfree(entry);
|
kfree(entry);
|
||||||
return ERR_PTR(err);
|
return ERR_PTR(err);
|
||||||
|
@ -619,6 +619,20 @@ struct mlx5_user_mmap_entry {
|
|||||||
u32 page_idx;
|
u32 page_idx;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum mlx5_mkey_type {
|
||||||
|
MLX5_MKEY_MR = 1,
|
||||||
|
MLX5_MKEY_MW,
|
||||||
|
MLX5_MKEY_INDIRECT_DEVX,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct mlx5_ib_mkey {
|
||||||
|
u32 key;
|
||||||
|
enum mlx5_mkey_type type;
|
||||||
|
unsigned int ndescs;
|
||||||
|
struct wait_queue_head wait;
|
||||||
|
refcount_t usecount;
|
||||||
|
};
|
||||||
|
|
||||||
#define MLX5_IB_MTT_PRESENT (MLX5_IB_MTT_READ | MLX5_IB_MTT_WRITE)
|
#define MLX5_IB_MTT_PRESENT (MLX5_IB_MTT_READ | MLX5_IB_MTT_WRITE)
|
||||||
|
|
||||||
#define MLX5_IB_DM_MEMIC_ALLOWED_ACCESS (IB_ACCESS_LOCAL_WRITE |\
|
#define MLX5_IB_DM_MEMIC_ALLOWED_ACCESS (IB_ACCESS_LOCAL_WRITE |\
|
||||||
@ -637,7 +651,7 @@ struct mlx5_user_mmap_entry {
|
|||||||
|
|
||||||
struct mlx5_ib_mr {
|
struct mlx5_ib_mr {
|
||||||
struct ib_mr ibmr;
|
struct ib_mr ibmr;
|
||||||
struct mlx5_core_mkey mmkey;
|
struct mlx5_ib_mkey mmkey;
|
||||||
|
|
||||||
/* User MR data */
|
/* User MR data */
|
||||||
struct mlx5_cache_ent *cache_ent;
|
struct mlx5_cache_ent *cache_ent;
|
||||||
@ -659,7 +673,6 @@ struct mlx5_ib_mr {
|
|||||||
void *descs_alloc;
|
void *descs_alloc;
|
||||||
dma_addr_t desc_map;
|
dma_addr_t desc_map;
|
||||||
int max_descs;
|
int max_descs;
|
||||||
int ndescs;
|
|
||||||
int desc_size;
|
int desc_size;
|
||||||
int access_mode;
|
int access_mode;
|
||||||
|
|
||||||
@ -713,13 +726,7 @@ static inline bool is_dmabuf_mr(struct mlx5_ib_mr *mr)
|
|||||||
|
|
||||||
struct mlx5_ib_mw {
|
struct mlx5_ib_mw {
|
||||||
struct ib_mw ibmw;
|
struct ib_mw ibmw;
|
||||||
struct mlx5_core_mkey mmkey;
|
struct mlx5_ib_mkey mmkey;
|
||||||
int ndescs;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct mlx5_ib_devx_mr {
|
|
||||||
struct mlx5_core_mkey mmkey;
|
|
||||||
int ndescs;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct mlx5_ib_umr_context {
|
struct mlx5_ib_umr_context {
|
||||||
@ -1579,7 +1586,7 @@ static inline bool mlx5_ib_can_reconfig_with_umr(struct mlx5_ib_dev *dev,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static inline int mlx5r_store_odp_mkey(struct mlx5_ib_dev *dev,
|
static inline int mlx5r_store_odp_mkey(struct mlx5_ib_dev *dev,
|
||||||
struct mlx5_core_mkey *mmkey)
|
struct mlx5_ib_mkey *mmkey)
|
||||||
{
|
{
|
||||||
refcount_set(&mmkey->usecount, 1);
|
refcount_set(&mmkey->usecount, 1);
|
||||||
|
|
||||||
@ -1588,14 +1595,14 @@ static inline int mlx5r_store_odp_mkey(struct mlx5_ib_dev *dev,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* deref an mkey that can participate in ODP flow */
|
/* deref an mkey that can participate in ODP flow */
|
||||||
static inline void mlx5r_deref_odp_mkey(struct mlx5_core_mkey *mmkey)
|
static inline void mlx5r_deref_odp_mkey(struct mlx5_ib_mkey *mmkey)
|
||||||
{
|
{
|
||||||
if (refcount_dec_and_test(&mmkey->usecount))
|
if (refcount_dec_and_test(&mmkey->usecount))
|
||||||
wake_up(&mmkey->wait);
|
wake_up(&mmkey->wait);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* deref an mkey that can participate in ODP flow and wait for relese */
|
/* deref an mkey that can participate in ODP flow and wait for relese */
|
||||||
static inline void mlx5r_deref_wait_odp_mkey(struct mlx5_core_mkey *mmkey)
|
static inline void mlx5r_deref_wait_odp_mkey(struct mlx5_ib_mkey *mmkey)
|
||||||
{
|
{
|
||||||
mlx5r_deref_odp_mkey(mmkey);
|
mlx5r_deref_odp_mkey(mmkey);
|
||||||
wait_event(mmkey->wait, refcount_read(&mmkey->usecount) == 0);
|
wait_event(mmkey->wait, refcount_read(&mmkey->usecount) == 0);
|
||||||
|
@ -88,9 +88,8 @@ static void set_mkc_access_pd_addr_fields(void *mkc, int acc, u64 start_addr,
|
|||||||
MLX5_SET64(mkc, mkc, start_addr, start_addr);
|
MLX5_SET64(mkc, mkc, start_addr, start_addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void assign_mkey_variant(struct mlx5_ib_dev *dev,
|
||||||
assign_mkey_variant(struct mlx5_ib_dev *dev, struct mlx5_core_mkey *mkey,
|
struct mlx5_ib_mkey *mkey, u32 *in)
|
||||||
u32 *in)
|
|
||||||
{
|
{
|
||||||
u8 key = atomic_inc_return(&dev->mkey_var);
|
u8 key = atomic_inc_return(&dev->mkey_var);
|
||||||
void *mkc;
|
void *mkc;
|
||||||
@ -100,17 +99,22 @@ assign_mkey_variant(struct mlx5_ib_dev *dev, struct mlx5_core_mkey *mkey,
|
|||||||
mkey->key = key;
|
mkey->key = key;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int mlx5_ib_create_mkey(struct mlx5_ib_dev *dev,
|
||||||
mlx5_ib_create_mkey(struct mlx5_ib_dev *dev, struct mlx5_core_mkey *mkey,
|
struct mlx5_ib_mkey *mkey, u32 *in, int inlen)
|
||||||
u32 *in, int inlen)
|
|
||||||
{
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
assign_mkey_variant(dev, mkey, in);
|
assign_mkey_variant(dev, mkey, in);
|
||||||
return mlx5_core_create_mkey(dev->mdev, mkey, in, inlen);
|
ret = mlx5_core_create_mkey(dev->mdev, &mkey->key, in, inlen);
|
||||||
|
if (!ret)
|
||||||
|
init_waitqueue_head(&mkey->wait);
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
mlx5_ib_create_mkey_cb(struct mlx5_ib_dev *dev,
|
mlx5_ib_create_mkey_cb(struct mlx5_ib_dev *dev,
|
||||||
struct mlx5_core_mkey *mkey,
|
struct mlx5_ib_mkey *mkey,
|
||||||
struct mlx5_async_ctx *async_ctx,
|
struct mlx5_async_ctx *async_ctx,
|
||||||
u32 *in, int inlen, u32 *out, int outlen,
|
u32 *in, int inlen, u32 *out, int outlen,
|
||||||
struct mlx5_async_work *context)
|
struct mlx5_async_work *context)
|
||||||
@ -133,7 +137,7 @@ static int destroy_mkey(struct mlx5_ib_dev *dev, struct mlx5_ib_mr *mr)
|
|||||||
{
|
{
|
||||||
WARN_ON(xa_load(&dev->odp_mkeys, mlx5_base_mkey(mr->mmkey.key)));
|
WARN_ON(xa_load(&dev->odp_mkeys, mlx5_base_mkey(mr->mmkey.key)));
|
||||||
|
|
||||||
return mlx5_core_destroy_mkey(dev->mdev, &mr->mmkey);
|
return mlx5_core_destroy_mkey(dev->mdev, mr->mmkey.key);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void create_mkey_callback(int status, struct mlx5_async_work *context)
|
static void create_mkey_callback(int status, struct mlx5_async_work *context)
|
||||||
@ -260,10 +264,11 @@ static struct mlx5_ib_mr *create_cache_mr(struct mlx5_cache_ent *ent)
|
|||||||
goto free_in;
|
goto free_in;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = mlx5_core_create_mkey(ent->dev->mdev, &mr->mmkey, in, inlen);
|
err = mlx5_core_create_mkey(ent->dev->mdev, &mr->mmkey.key, in, inlen);
|
||||||
if (err)
|
if (err)
|
||||||
goto free_mr;
|
goto free_mr;
|
||||||
|
|
||||||
|
init_waitqueue_head(&mr->mmkey.wait);
|
||||||
mr->mmkey.type = MLX5_MKEY_MR;
|
mr->mmkey.type = MLX5_MKEY_MR;
|
||||||
WRITE_ONCE(ent->dev->cache.last_add, jiffies);
|
WRITE_ONCE(ent->dev->cache.last_add, jiffies);
|
||||||
spin_lock_irq(&ent->lock);
|
spin_lock_irq(&ent->lock);
|
||||||
@ -290,7 +295,7 @@ static void remove_cache_mr_locked(struct mlx5_cache_ent *ent)
|
|||||||
ent->available_mrs--;
|
ent->available_mrs--;
|
||||||
ent->total_mrs--;
|
ent->total_mrs--;
|
||||||
spin_unlock_irq(&ent->lock);
|
spin_unlock_irq(&ent->lock);
|
||||||
mlx5_core_destroy_mkey(ent->dev->mdev, &mr->mmkey);
|
mlx5_core_destroy_mkey(ent->dev->mdev, mr->mmkey.key);
|
||||||
kfree(mr);
|
kfree(mr);
|
||||||
spin_lock_irq(&ent->lock);
|
spin_lock_irq(&ent->lock);
|
||||||
}
|
}
|
||||||
@ -658,7 +663,7 @@ static void clean_keys(struct mlx5_ib_dev *dev, int c)
|
|||||||
ent->available_mrs--;
|
ent->available_mrs--;
|
||||||
ent->total_mrs--;
|
ent->total_mrs--;
|
||||||
spin_unlock_irq(&ent->lock);
|
spin_unlock_irq(&ent->lock);
|
||||||
mlx5_core_destroy_mkey(dev->mdev, &mr->mmkey);
|
mlx5_core_destroy_mkey(dev->mdev, mr->mmkey.key);
|
||||||
}
|
}
|
||||||
|
|
||||||
list_for_each_entry_safe(mr, tmp_mr, &del_list, list) {
|
list_for_each_entry_safe(mr, tmp_mr, &del_list, list) {
|
||||||
@ -911,12 +916,13 @@ static struct mlx5_cache_ent *mr_cache_ent_from_order(struct mlx5_ib_dev *dev,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void set_mr_fields(struct mlx5_ib_dev *dev, struct mlx5_ib_mr *mr,
|
static void set_mr_fields(struct mlx5_ib_dev *dev, struct mlx5_ib_mr *mr,
|
||||||
u64 length, int access_flags)
|
u64 length, int access_flags, u64 iova)
|
||||||
{
|
{
|
||||||
mr->ibmr.lkey = mr->mmkey.key;
|
mr->ibmr.lkey = mr->mmkey.key;
|
||||||
mr->ibmr.rkey = mr->mmkey.key;
|
mr->ibmr.rkey = mr->mmkey.key;
|
||||||
mr->ibmr.length = length;
|
mr->ibmr.length = length;
|
||||||
mr->ibmr.device = &dev->ib_dev;
|
mr->ibmr.device = &dev->ib_dev;
|
||||||
|
mr->ibmr.iova = iova;
|
||||||
mr->access_flags = access_flags;
|
mr->access_flags = access_flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -974,11 +980,8 @@ static struct mlx5_ib_mr *alloc_cacheable_mr(struct ib_pd *pd,
|
|||||||
|
|
||||||
mr->ibmr.pd = pd;
|
mr->ibmr.pd = pd;
|
||||||
mr->umem = umem;
|
mr->umem = umem;
|
||||||
mr->mmkey.iova = iova;
|
|
||||||
mr->mmkey.size = umem->length;
|
|
||||||
mr->mmkey.pd = to_mpd(pd)->pdn;
|
|
||||||
mr->page_shift = order_base_2(page_size);
|
mr->page_shift = order_base_2(page_size);
|
||||||
set_mr_fields(dev, mr, umem->length, access_flags);
|
set_mr_fields(dev, mr, umem->length, access_flags, iova);
|
||||||
|
|
||||||
return mr;
|
return mr;
|
||||||
}
|
}
|
||||||
@ -1087,8 +1090,8 @@ static void *mlx5_ib_create_xlt_wr(struct mlx5_ib_mr *mr,
|
|||||||
wr->wr.opcode = MLX5_IB_WR_UMR;
|
wr->wr.opcode = MLX5_IB_WR_UMR;
|
||||||
wr->pd = mr->ibmr.pd;
|
wr->pd = mr->ibmr.pd;
|
||||||
wr->mkey = mr->mmkey.key;
|
wr->mkey = mr->mmkey.key;
|
||||||
wr->length = mr->mmkey.size;
|
wr->length = mr->ibmr.length;
|
||||||
wr->virt_addr = mr->mmkey.iova;
|
wr->virt_addr = mr->ibmr.iova;
|
||||||
wr->access_flags = mr->access_flags;
|
wr->access_flags = mr->access_flags;
|
||||||
wr->page_shift = mr->page_shift;
|
wr->page_shift = mr->page_shift;
|
||||||
wr->xlt_size = sg->length;
|
wr->xlt_size = sg->length;
|
||||||
@ -1340,7 +1343,7 @@ static struct mlx5_ib_mr *reg_create(struct ib_pd *pd, struct ib_umem *umem,
|
|||||||
}
|
}
|
||||||
mr->mmkey.type = MLX5_MKEY_MR;
|
mr->mmkey.type = MLX5_MKEY_MR;
|
||||||
mr->umem = umem;
|
mr->umem = umem;
|
||||||
set_mr_fields(dev, mr, umem->length, access_flags);
|
set_mr_fields(dev, mr, umem->length, access_flags, iova);
|
||||||
kvfree(in);
|
kvfree(in);
|
||||||
|
|
||||||
mlx5_ib_dbg(dev, "mkey = 0x%x\n", mr->mmkey.key);
|
mlx5_ib_dbg(dev, "mkey = 0x%x\n", mr->mmkey.key);
|
||||||
@ -1387,7 +1390,7 @@ static struct ib_mr *mlx5_ib_get_dm_mr(struct ib_pd *pd, u64 start_addr,
|
|||||||
|
|
||||||
kfree(in);
|
kfree(in);
|
||||||
|
|
||||||
set_mr_fields(dev, mr, length, acc);
|
set_mr_fields(dev, mr, length, acc, start_addr);
|
||||||
|
|
||||||
return &mr->ibmr;
|
return &mr->ibmr;
|
||||||
|
|
||||||
@ -1709,7 +1712,6 @@ static int umr_rereg_pd_access(struct mlx5_ib_mr *mr, struct ib_pd *pd,
|
|||||||
return err;
|
return err;
|
||||||
|
|
||||||
mr->access_flags = access_flags;
|
mr->access_flags = access_flags;
|
||||||
mr->mmkey.pd = to_mpd(pd)->pdn;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1754,7 +1756,6 @@ static int umr_rereg_pas(struct mlx5_ib_mr *mr, struct ib_pd *pd,
|
|||||||
|
|
||||||
if (flags & IB_MR_REREG_PD) {
|
if (flags & IB_MR_REREG_PD) {
|
||||||
mr->ibmr.pd = pd;
|
mr->ibmr.pd = pd;
|
||||||
mr->mmkey.pd = to_mpd(pd)->pdn;
|
|
||||||
upd_flags |= MLX5_IB_UPD_XLT_PD;
|
upd_flags |= MLX5_IB_UPD_XLT_PD;
|
||||||
}
|
}
|
||||||
if (flags & IB_MR_REREG_ACCESS) {
|
if (flags & IB_MR_REREG_ACCESS) {
|
||||||
@ -1763,8 +1764,8 @@ static int umr_rereg_pas(struct mlx5_ib_mr *mr, struct ib_pd *pd,
|
|||||||
}
|
}
|
||||||
|
|
||||||
mr->ibmr.length = new_umem->length;
|
mr->ibmr.length = new_umem->length;
|
||||||
mr->mmkey.iova = iova;
|
mr->ibmr.iova = iova;
|
||||||
mr->mmkey.size = new_umem->length;
|
mr->ibmr.length = new_umem->length;
|
||||||
mr->page_shift = order_base_2(page_size);
|
mr->page_shift = order_base_2(page_size);
|
||||||
mr->umem = new_umem;
|
mr->umem = new_umem;
|
||||||
err = mlx5_ib_update_mr_pas(mr, upd_flags);
|
err = mlx5_ib_update_mr_pas(mr, upd_flags);
|
||||||
@ -1834,7 +1835,7 @@ struct ib_mr *mlx5_ib_rereg_user_mr(struct ib_mr *ib_mr, int flags, u64 start,
|
|||||||
mr->umem = NULL;
|
mr->umem = NULL;
|
||||||
atomic_sub(ib_umem_num_pages(umem), &dev->mdev->priv.reg_pages);
|
atomic_sub(ib_umem_num_pages(umem), &dev->mdev->priv.reg_pages);
|
||||||
|
|
||||||
return create_real_mr(new_pd, umem, mr->mmkey.iova,
|
return create_real_mr(new_pd, umem, mr->ibmr.iova,
|
||||||
new_access_flags);
|
new_access_flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2263,9 +2264,9 @@ int mlx5_ib_alloc_mw(struct ib_mw *ibmw, struct ib_udata *udata)
|
|||||||
struct mlx5_ib_dev *dev = to_mdev(ibmw->device);
|
struct mlx5_ib_dev *dev = to_mdev(ibmw->device);
|
||||||
int inlen = MLX5_ST_SZ_BYTES(create_mkey_in);
|
int inlen = MLX5_ST_SZ_BYTES(create_mkey_in);
|
||||||
struct mlx5_ib_mw *mw = to_mmw(ibmw);
|
struct mlx5_ib_mw *mw = to_mmw(ibmw);
|
||||||
|
unsigned int ndescs;
|
||||||
u32 *in = NULL;
|
u32 *in = NULL;
|
||||||
void *mkc;
|
void *mkc;
|
||||||
int ndescs;
|
|
||||||
int err;
|
int err;
|
||||||
struct mlx5_ib_alloc_mw req = {};
|
struct mlx5_ib_alloc_mw req = {};
|
||||||
struct {
|
struct {
|
||||||
@ -2310,7 +2311,7 @@ int mlx5_ib_alloc_mw(struct ib_mw *ibmw, struct ib_udata *udata)
|
|||||||
|
|
||||||
mw->mmkey.type = MLX5_MKEY_MW;
|
mw->mmkey.type = MLX5_MKEY_MW;
|
||||||
ibmw->rkey = mw->mmkey.key;
|
ibmw->rkey = mw->mmkey.key;
|
||||||
mw->ndescs = ndescs;
|
mw->mmkey.ndescs = ndescs;
|
||||||
|
|
||||||
resp.response_length =
|
resp.response_length =
|
||||||
min(offsetofend(typeof(resp), response_length), udata->outlen);
|
min(offsetofend(typeof(resp), response_length), udata->outlen);
|
||||||
@ -2330,7 +2331,7 @@ int mlx5_ib_alloc_mw(struct ib_mw *ibmw, struct ib_udata *udata)
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
free_mkey:
|
free_mkey:
|
||||||
mlx5_core_destroy_mkey(dev->mdev, &mw->mmkey);
|
mlx5_core_destroy_mkey(dev->mdev, mw->mmkey.key);
|
||||||
free:
|
free:
|
||||||
kfree(in);
|
kfree(in);
|
||||||
return err;
|
return err;
|
||||||
@ -2349,7 +2350,7 @@ int mlx5_ib_dealloc_mw(struct ib_mw *mw)
|
|||||||
*/
|
*/
|
||||||
mlx5r_deref_wait_odp_mkey(&mmw->mmkey);
|
mlx5r_deref_wait_odp_mkey(&mmw->mmkey);
|
||||||
|
|
||||||
return mlx5_core_destroy_mkey(dev->mdev, &mmw->mmkey);
|
return mlx5_core_destroy_mkey(dev->mdev, mmw->mmkey.key);
|
||||||
}
|
}
|
||||||
|
|
||||||
int mlx5_ib_check_mr_status(struct ib_mr *ibmr, u32 check_mask,
|
int mlx5_ib_check_mr_status(struct ib_mr *ibmr, u32 check_mask,
|
||||||
@ -2406,7 +2407,7 @@ mlx5_ib_map_pa_mr_sg_pi(struct ib_mr *ibmr, struct scatterlist *data_sg,
|
|||||||
mr->meta_length = 0;
|
mr->meta_length = 0;
|
||||||
if (data_sg_nents == 1) {
|
if (data_sg_nents == 1) {
|
||||||
n++;
|
n++;
|
||||||
mr->ndescs = 1;
|
mr->mmkey.ndescs = 1;
|
||||||
if (data_sg_offset)
|
if (data_sg_offset)
|
||||||
sg_offset = *data_sg_offset;
|
sg_offset = *data_sg_offset;
|
||||||
mr->data_length = sg_dma_len(data_sg) - sg_offset;
|
mr->data_length = sg_dma_len(data_sg) - sg_offset;
|
||||||
@ -2459,7 +2460,7 @@ mlx5_ib_sg_to_klms(struct mlx5_ib_mr *mr,
|
|||||||
if (sg_offset_p)
|
if (sg_offset_p)
|
||||||
*sg_offset_p = sg_offset;
|
*sg_offset_p = sg_offset;
|
||||||
|
|
||||||
mr->ndescs = i;
|
mr->mmkey.ndescs = i;
|
||||||
mr->data_length = mr->ibmr.length;
|
mr->data_length = mr->ibmr.length;
|
||||||
|
|
||||||
if (meta_sg_nents) {
|
if (meta_sg_nents) {
|
||||||
@ -2492,11 +2493,11 @@ static int mlx5_set_page(struct ib_mr *ibmr, u64 addr)
|
|||||||
struct mlx5_ib_mr *mr = to_mmr(ibmr);
|
struct mlx5_ib_mr *mr = to_mmr(ibmr);
|
||||||
__be64 *descs;
|
__be64 *descs;
|
||||||
|
|
||||||
if (unlikely(mr->ndescs == mr->max_descs))
|
if (unlikely(mr->mmkey.ndescs == mr->max_descs))
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
descs = mr->descs;
|
descs = mr->descs;
|
||||||
descs[mr->ndescs++] = cpu_to_be64(addr | MLX5_EN_RD | MLX5_EN_WR);
|
descs[mr->mmkey.ndescs++] = cpu_to_be64(addr | MLX5_EN_RD | MLX5_EN_WR);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -2506,11 +2507,11 @@ static int mlx5_set_page_pi(struct ib_mr *ibmr, u64 addr)
|
|||||||
struct mlx5_ib_mr *mr = to_mmr(ibmr);
|
struct mlx5_ib_mr *mr = to_mmr(ibmr);
|
||||||
__be64 *descs;
|
__be64 *descs;
|
||||||
|
|
||||||
if (unlikely(mr->ndescs + mr->meta_ndescs == mr->max_descs))
|
if (unlikely(mr->mmkey.ndescs + mr->meta_ndescs == mr->max_descs))
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
descs = mr->descs;
|
descs = mr->descs;
|
||||||
descs[mr->ndescs + mr->meta_ndescs++] =
|
descs[mr->mmkey.ndescs + mr->meta_ndescs++] =
|
||||||
cpu_to_be64(addr | MLX5_EN_RD | MLX5_EN_WR);
|
cpu_to_be64(addr | MLX5_EN_RD | MLX5_EN_WR);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -2526,7 +2527,7 @@ mlx5_ib_map_mtt_mr_sg_pi(struct ib_mr *ibmr, struct scatterlist *data_sg,
|
|||||||
struct mlx5_ib_mr *pi_mr = mr->mtt_mr;
|
struct mlx5_ib_mr *pi_mr = mr->mtt_mr;
|
||||||
int n;
|
int n;
|
||||||
|
|
||||||
pi_mr->ndescs = 0;
|
pi_mr->mmkey.ndescs = 0;
|
||||||
pi_mr->meta_ndescs = 0;
|
pi_mr->meta_ndescs = 0;
|
||||||
pi_mr->meta_length = 0;
|
pi_mr->meta_length = 0;
|
||||||
|
|
||||||
@ -2560,7 +2561,7 @@ mlx5_ib_map_mtt_mr_sg_pi(struct ib_mr *ibmr, struct scatterlist *data_sg,
|
|||||||
* metadata offset at the first metadata page
|
* metadata offset at the first metadata page
|
||||||
*/
|
*/
|
||||||
pi_mr->pi_iova = (iova & page_mask) +
|
pi_mr->pi_iova = (iova & page_mask) +
|
||||||
pi_mr->ndescs * ibmr->page_size +
|
pi_mr->mmkey.ndescs * ibmr->page_size +
|
||||||
(pi_mr->ibmr.iova & ~page_mask);
|
(pi_mr->ibmr.iova & ~page_mask);
|
||||||
/*
|
/*
|
||||||
* In order to use one MTT MR for data and metadata, we register
|
* In order to use one MTT MR for data and metadata, we register
|
||||||
@ -2591,7 +2592,7 @@ mlx5_ib_map_klm_mr_sg_pi(struct ib_mr *ibmr, struct scatterlist *data_sg,
|
|||||||
struct mlx5_ib_mr *pi_mr = mr->klm_mr;
|
struct mlx5_ib_mr *pi_mr = mr->klm_mr;
|
||||||
int n;
|
int n;
|
||||||
|
|
||||||
pi_mr->ndescs = 0;
|
pi_mr->mmkey.ndescs = 0;
|
||||||
pi_mr->meta_ndescs = 0;
|
pi_mr->meta_ndescs = 0;
|
||||||
pi_mr->meta_length = 0;
|
pi_mr->meta_length = 0;
|
||||||
|
|
||||||
@ -2626,7 +2627,7 @@ int mlx5_ib_map_mr_sg_pi(struct ib_mr *ibmr, struct scatterlist *data_sg,
|
|||||||
|
|
||||||
WARN_ON(ibmr->type != IB_MR_TYPE_INTEGRITY);
|
WARN_ON(ibmr->type != IB_MR_TYPE_INTEGRITY);
|
||||||
|
|
||||||
mr->ndescs = 0;
|
mr->mmkey.ndescs = 0;
|
||||||
mr->data_length = 0;
|
mr->data_length = 0;
|
||||||
mr->data_iova = 0;
|
mr->data_iova = 0;
|
||||||
mr->meta_ndescs = 0;
|
mr->meta_ndescs = 0;
|
||||||
@ -2682,7 +2683,7 @@ int mlx5_ib_map_mr_sg(struct ib_mr *ibmr, struct scatterlist *sg, int sg_nents,
|
|||||||
struct mlx5_ib_mr *mr = to_mmr(ibmr);
|
struct mlx5_ib_mr *mr = to_mmr(ibmr);
|
||||||
int n;
|
int n;
|
||||||
|
|
||||||
mr->ndescs = 0;
|
mr->mmkey.ndescs = 0;
|
||||||
|
|
||||||
ib_dma_sync_single_for_cpu(ibmr->device, mr->desc_map,
|
ib_dma_sync_single_for_cpu(ibmr->device, mr->desc_map,
|
||||||
mr->desc_size * mr->max_descs,
|
mr->desc_size * mr->max_descs,
|
||||||
|
@ -430,7 +430,7 @@ static struct mlx5_ib_mr *implicit_get_child_mr(struct mlx5_ib_mr *imr,
|
|||||||
mr->umem = &odp->umem;
|
mr->umem = &odp->umem;
|
||||||
mr->ibmr.lkey = mr->mmkey.key;
|
mr->ibmr.lkey = mr->mmkey.key;
|
||||||
mr->ibmr.rkey = mr->mmkey.key;
|
mr->ibmr.rkey = mr->mmkey.key;
|
||||||
mr->mmkey.iova = idx * MLX5_IMR_MTT_SIZE;
|
mr->ibmr.iova = idx * MLX5_IMR_MTT_SIZE;
|
||||||
mr->parent = imr;
|
mr->parent = imr;
|
||||||
odp->private = mr;
|
odp->private = mr;
|
||||||
|
|
||||||
@ -500,7 +500,7 @@ struct mlx5_ib_mr *mlx5_ib_alloc_implicit_mr(struct mlx5_ib_pd *pd,
|
|||||||
}
|
}
|
||||||
|
|
||||||
imr->ibmr.pd = &pd->ibpd;
|
imr->ibmr.pd = &pd->ibpd;
|
||||||
imr->mmkey.iova = 0;
|
imr->ibmr.iova = 0;
|
||||||
imr->umem = &umem_odp->umem;
|
imr->umem = &umem_odp->umem;
|
||||||
imr->ibmr.lkey = imr->mmkey.key;
|
imr->ibmr.lkey = imr->mmkey.key;
|
||||||
imr->ibmr.rkey = imr->mmkey.key;
|
imr->ibmr.rkey = imr->mmkey.key;
|
||||||
@ -738,7 +738,7 @@ static int pagefault_mr(struct mlx5_ib_mr *mr, u64 io_virt, size_t bcnt,
|
|||||||
{
|
{
|
||||||
struct ib_umem_odp *odp = to_ib_umem_odp(mr->umem);
|
struct ib_umem_odp *odp = to_ib_umem_odp(mr->umem);
|
||||||
|
|
||||||
if (unlikely(io_virt < mr->mmkey.iova))
|
if (unlikely(io_virt < mr->ibmr.iova))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
|
|
||||||
if (mr->umem->is_dmabuf)
|
if (mr->umem->is_dmabuf)
|
||||||
@ -747,7 +747,7 @@ static int pagefault_mr(struct mlx5_ib_mr *mr, u64 io_virt, size_t bcnt,
|
|||||||
if (!odp->is_implicit_odp) {
|
if (!odp->is_implicit_odp) {
|
||||||
u64 user_va;
|
u64 user_va;
|
||||||
|
|
||||||
if (check_add_overflow(io_virt - mr->mmkey.iova,
|
if (check_add_overflow(io_virt - mr->ibmr.iova,
|
||||||
(u64)odp->umem.address, &user_va))
|
(u64)odp->umem.address, &user_va))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
if (unlikely(user_va >= ib_umem_end(odp) ||
|
if (unlikely(user_va >= ib_umem_end(odp) ||
|
||||||
@ -788,7 +788,7 @@ struct pf_frame {
|
|||||||
int depth;
|
int depth;
|
||||||
};
|
};
|
||||||
|
|
||||||
static bool mkey_is_eq(struct mlx5_core_mkey *mmkey, u32 key)
|
static bool mkey_is_eq(struct mlx5_ib_mkey *mmkey, u32 key)
|
||||||
{
|
{
|
||||||
if (!mmkey)
|
if (!mmkey)
|
||||||
return false;
|
return false;
|
||||||
@ -797,21 +797,6 @@ static bool mkey_is_eq(struct mlx5_core_mkey *mmkey, u32 key)
|
|||||||
return mmkey->key == key;
|
return mmkey->key == key;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int get_indirect_num_descs(struct mlx5_core_mkey *mmkey)
|
|
||||||
{
|
|
||||||
struct mlx5_ib_mw *mw;
|
|
||||||
struct mlx5_ib_devx_mr *devx_mr;
|
|
||||||
|
|
||||||
if (mmkey->type == MLX5_MKEY_MW) {
|
|
||||||
mw = container_of(mmkey, struct mlx5_ib_mw, mmkey);
|
|
||||||
return mw->ndescs;
|
|
||||||
}
|
|
||||||
|
|
||||||
devx_mr = container_of(mmkey, struct mlx5_ib_devx_mr,
|
|
||||||
mmkey);
|
|
||||||
return devx_mr->ndescs;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Handle a single data segment in a page-fault WQE or RDMA region.
|
* Handle a single data segment in a page-fault WQE or RDMA region.
|
||||||
*
|
*
|
||||||
@ -831,12 +816,11 @@ static int pagefault_single_data_segment(struct mlx5_ib_dev *dev,
|
|||||||
{
|
{
|
||||||
int npages = 0, ret, i, outlen, cur_outlen = 0, depth = 0;
|
int npages = 0, ret, i, outlen, cur_outlen = 0, depth = 0;
|
||||||
struct pf_frame *head = NULL, *frame;
|
struct pf_frame *head = NULL, *frame;
|
||||||
struct mlx5_core_mkey *mmkey;
|
struct mlx5_ib_mkey *mmkey;
|
||||||
struct mlx5_ib_mr *mr;
|
struct mlx5_ib_mr *mr;
|
||||||
struct mlx5_klm *pklm;
|
struct mlx5_klm *pklm;
|
||||||
u32 *out = NULL;
|
u32 *out = NULL;
|
||||||
size_t offset;
|
size_t offset;
|
||||||
int ndescs;
|
|
||||||
|
|
||||||
io_virt += *bytes_committed;
|
io_virt += *bytes_committed;
|
||||||
bcnt -= *bytes_committed;
|
bcnt -= *bytes_committed;
|
||||||
@ -885,8 +869,6 @@ static int pagefault_single_data_segment(struct mlx5_ib_dev *dev,
|
|||||||
|
|
||||||
case MLX5_MKEY_MW:
|
case MLX5_MKEY_MW:
|
||||||
case MLX5_MKEY_INDIRECT_DEVX:
|
case MLX5_MKEY_INDIRECT_DEVX:
|
||||||
ndescs = get_indirect_num_descs(mmkey);
|
|
||||||
|
|
||||||
if (depth >= MLX5_CAP_GEN(dev->mdev, max_indirection)) {
|
if (depth >= MLX5_CAP_GEN(dev->mdev, max_indirection)) {
|
||||||
mlx5_ib_dbg(dev, "indirection level exceeded\n");
|
mlx5_ib_dbg(dev, "indirection level exceeded\n");
|
||||||
ret = -EFAULT;
|
ret = -EFAULT;
|
||||||
@ -894,7 +876,7 @@ static int pagefault_single_data_segment(struct mlx5_ib_dev *dev,
|
|||||||
}
|
}
|
||||||
|
|
||||||
outlen = MLX5_ST_SZ_BYTES(query_mkey_out) +
|
outlen = MLX5_ST_SZ_BYTES(query_mkey_out) +
|
||||||
sizeof(*pklm) * (ndescs - 2);
|
sizeof(*pklm) * (mmkey->ndescs - 2);
|
||||||
|
|
||||||
if (outlen > cur_outlen) {
|
if (outlen > cur_outlen) {
|
||||||
kfree(out);
|
kfree(out);
|
||||||
@ -909,14 +891,14 @@ static int pagefault_single_data_segment(struct mlx5_ib_dev *dev,
|
|||||||
pklm = (struct mlx5_klm *)MLX5_ADDR_OF(query_mkey_out, out,
|
pklm = (struct mlx5_klm *)MLX5_ADDR_OF(query_mkey_out, out,
|
||||||
bsf0_klm0_pas_mtt0_1);
|
bsf0_klm0_pas_mtt0_1);
|
||||||
|
|
||||||
ret = mlx5_core_query_mkey(dev->mdev, mmkey, out, outlen);
|
ret = mlx5_core_query_mkey(dev->mdev, mmkey->key, out, outlen);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto end;
|
goto end;
|
||||||
|
|
||||||
offset = io_virt - MLX5_GET64(query_mkey_out, out,
|
offset = io_virt - MLX5_GET64(query_mkey_out, out,
|
||||||
memory_key_mkey_entry.start_addr);
|
memory_key_mkey_entry.start_addr);
|
||||||
|
|
||||||
for (i = 0; bcnt && i < ndescs; i++, pklm++) {
|
for (i = 0; bcnt && i < mmkey->ndescs; i++, pklm++) {
|
||||||
if (offset >= be32_to_cpu(pklm->bcount)) {
|
if (offset >= be32_to_cpu(pklm->bcount)) {
|
||||||
offset -= be32_to_cpu(pklm->bcount);
|
offset -= be32_to_cpu(pklm->bcount);
|
||||||
continue;
|
continue;
|
||||||
@ -1559,6 +1541,7 @@ int mlx5r_odp_create_eq(struct mlx5_ib_dev *dev, struct mlx5_ib_pf_eq *eq)
|
|||||||
|
|
||||||
eq->irq_nb.notifier_call = mlx5_ib_eq_pf_int;
|
eq->irq_nb.notifier_call = mlx5_ib_eq_pf_int;
|
||||||
param = (struct mlx5_eq_param) {
|
param = (struct mlx5_eq_param) {
|
||||||
|
.irq_index = MLX5_IRQ_EQ_CTRL,
|
||||||
.nent = MLX5_IB_NUM_PF_EQE,
|
.nent = MLX5_IB_NUM_PF_EQE,
|
||||||
};
|
};
|
||||||
param.mask[0] = 1ull << MLX5_EVENT_TYPE_PAGE_FAULT;
|
param.mask[0] = 1ull << MLX5_EVENT_TYPE_PAGE_FAULT;
|
||||||
@ -1703,8 +1686,8 @@ get_prefetchable_mr(struct ib_pd *pd, enum ib_uverbs_advise_mr_advice advice,
|
|||||||
u32 lkey)
|
u32 lkey)
|
||||||
{
|
{
|
||||||
struct mlx5_ib_dev *dev = to_mdev(pd->device);
|
struct mlx5_ib_dev *dev = to_mdev(pd->device);
|
||||||
struct mlx5_core_mkey *mmkey;
|
|
||||||
struct mlx5_ib_mr *mr = NULL;
|
struct mlx5_ib_mr *mr = NULL;
|
||||||
|
struct mlx5_ib_mkey *mmkey;
|
||||||
|
|
||||||
xa_lock(&dev->odp_mkeys);
|
xa_lock(&dev->odp_mkeys);
|
||||||
mmkey = xa_load(&dev->odp_mkeys, mlx5_base_mkey(lkey));
|
mmkey = xa_load(&dev->odp_mkeys, mlx5_base_mkey(lkey));
|
||||||
|
@ -217,7 +217,7 @@ static __be64 sig_mkey_mask(void)
|
|||||||
static void set_reg_umr_seg(struct mlx5_wqe_umr_ctrl_seg *umr,
|
static void set_reg_umr_seg(struct mlx5_wqe_umr_ctrl_seg *umr,
|
||||||
struct mlx5_ib_mr *mr, u8 flags, bool atomic)
|
struct mlx5_ib_mr *mr, u8 flags, bool atomic)
|
||||||
{
|
{
|
||||||
int size = (mr->ndescs + mr->meta_ndescs) * mr->desc_size;
|
int size = (mr->mmkey.ndescs + mr->meta_ndescs) * mr->desc_size;
|
||||||
|
|
||||||
memset(umr, 0, sizeof(*umr));
|
memset(umr, 0, sizeof(*umr));
|
||||||
|
|
||||||
@ -374,7 +374,7 @@ static void set_reg_mkey_seg(struct mlx5_mkey_seg *seg,
|
|||||||
struct mlx5_ib_mr *mr,
|
struct mlx5_ib_mr *mr,
|
||||||
u32 key, int access)
|
u32 key, int access)
|
||||||
{
|
{
|
||||||
int ndescs = ALIGN(mr->ndescs + mr->meta_ndescs, 8) >> 1;
|
int ndescs = ALIGN(mr->mmkey.ndescs + mr->meta_ndescs, 8) >> 1;
|
||||||
|
|
||||||
memset(seg, 0, sizeof(*seg));
|
memset(seg, 0, sizeof(*seg));
|
||||||
|
|
||||||
@ -439,7 +439,7 @@ static void set_reg_data_seg(struct mlx5_wqe_data_seg *dseg,
|
|||||||
struct mlx5_ib_mr *mr,
|
struct mlx5_ib_mr *mr,
|
||||||
struct mlx5_ib_pd *pd)
|
struct mlx5_ib_pd *pd)
|
||||||
{
|
{
|
||||||
int bcount = mr->desc_size * (mr->ndescs + mr->meta_ndescs);
|
int bcount = mr->desc_size * (mr->mmkey.ndescs + mr->meta_ndescs);
|
||||||
|
|
||||||
dseg->addr = cpu_to_be64(mr->desc_map);
|
dseg->addr = cpu_to_be64(mr->desc_map);
|
||||||
dseg->byte_count = cpu_to_be32(ALIGN(bcount, 64));
|
dseg->byte_count = cpu_to_be32(ALIGN(bcount, 64));
|
||||||
@ -861,7 +861,7 @@ static int set_reg_wr(struct mlx5_ib_qp *qp,
|
|||||||
struct mlx5_ib_mr *mr = to_mmr(wr->mr);
|
struct mlx5_ib_mr *mr = to_mmr(wr->mr);
|
||||||
struct mlx5_ib_pd *pd = to_mpd(qp->ibqp.pd);
|
struct mlx5_ib_pd *pd = to_mpd(qp->ibqp.pd);
|
||||||
struct mlx5_ib_dev *dev = to_mdev(pd->ibpd.device);
|
struct mlx5_ib_dev *dev = to_mdev(pd->ibpd.device);
|
||||||
int mr_list_size = (mr->ndescs + mr->meta_ndescs) * mr->desc_size;
|
int mr_list_size = (mr->mmkey.ndescs + mr->meta_ndescs) * mr->desc_size;
|
||||||
bool umr_inline = mr_list_size <= MLX5_IB_SQ_UMR_INLINE_THRESHOLD;
|
bool umr_inline = mr_list_size <= MLX5_IB_SQ_UMR_INLINE_THRESHOLD;
|
||||||
bool atomic = wr->access & IB_ACCESS_REMOTE_ATOMIC;
|
bool atomic = wr->access & IB_ACCESS_REMOTE_ATOMIC;
|
||||||
u8 flags = 0;
|
u8 flags = 0;
|
||||||
@ -1111,7 +1111,7 @@ static int handle_reg_mr_integrity(struct mlx5_ib_dev *dev,
|
|||||||
memset(&pa_pi_mr, 0, sizeof(struct mlx5_ib_mr));
|
memset(&pa_pi_mr, 0, sizeof(struct mlx5_ib_mr));
|
||||||
/* No UMR, use local_dma_lkey */
|
/* No UMR, use local_dma_lkey */
|
||||||
pa_pi_mr.ibmr.lkey = mr->ibmr.pd->local_dma_lkey;
|
pa_pi_mr.ibmr.lkey = mr->ibmr.pd->local_dma_lkey;
|
||||||
pa_pi_mr.ndescs = mr->ndescs;
|
pa_pi_mr.mmkey.ndescs = mr->mmkey.ndescs;
|
||||||
pa_pi_mr.data_length = mr->data_length;
|
pa_pi_mr.data_length = mr->data_length;
|
||||||
pa_pi_mr.data_iova = mr->data_iova;
|
pa_pi_mr.data_iova = mr->data_iova;
|
||||||
if (mr->meta_ndescs) {
|
if (mr->meta_ndescs) {
|
||||||
|
@ -272,7 +272,7 @@ static int qedr_register_device(struct qedr_dev *dev)
|
|||||||
static int qedr_alloc_mem_sb(struct qedr_dev *dev,
|
static int qedr_alloc_mem_sb(struct qedr_dev *dev,
|
||||||
struct qed_sb_info *sb_info, u16 sb_id)
|
struct qed_sb_info *sb_info, u16 sb_id)
|
||||||
{
|
{
|
||||||
struct status_block_e4 *sb_virt;
|
struct status_block *sb_virt;
|
||||||
dma_addr_t sb_phys;
|
dma_addr_t sb_phys;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
|
@ -1008,7 +1008,7 @@ static u8 mask_promisc[6]={0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
|||||||
|
|
||||||
static int dvb_net_filter_sec_set(struct net_device *dev,
|
static int dvb_net_filter_sec_set(struct net_device *dev,
|
||||||
struct dmx_section_filter **secfilter,
|
struct dmx_section_filter **secfilter,
|
||||||
u8 *mac, u8 *mac_mask)
|
const u8 *mac, u8 *mac_mask)
|
||||||
{
|
{
|
||||||
struct dvb_net_priv *priv = netdev_priv(dev);
|
struct dvb_net_priv *priv = netdev_priv(dev);
|
||||||
int ret;
|
int ret;
|
||||||
@ -1052,7 +1052,7 @@ static int dvb_net_feed_start(struct net_device *dev)
|
|||||||
int ret = 0, i;
|
int ret = 0, i;
|
||||||
struct dvb_net_priv *priv = netdev_priv(dev);
|
struct dvb_net_priv *priv = netdev_priv(dev);
|
||||||
struct dmx_demux *demux = priv->demux;
|
struct dmx_demux *demux = priv->demux;
|
||||||
unsigned char *mac = (unsigned char *) dev->dev_addr;
|
const unsigned char *mac = (const unsigned char *) dev->dev_addr;
|
||||||
|
|
||||||
netdev_dbg(dev, "rx_mode %i\n", priv->rx_mode);
|
netdev_dbg(dev, "rx_mode %i\n", priv->rx_mode);
|
||||||
mutex_lock(&priv->mutex);
|
mutex_lock(&priv->mutex);
|
||||||
@ -1272,7 +1272,7 @@ static int dvb_net_set_mac (struct net_device *dev, void *p)
|
|||||||
struct dvb_net_priv *priv = netdev_priv(dev);
|
struct dvb_net_priv *priv = netdev_priv(dev);
|
||||||
struct sockaddr *addr=p;
|
struct sockaddr *addr=p;
|
||||||
|
|
||||||
memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
|
eth_hw_addr_set(dev, addr->sa_data);
|
||||||
|
|
||||||
if (netif_running(dev))
|
if (netif_running(dev))
|
||||||
schedule_work(&priv->restart_net_feed_wq);
|
schedule_work(&priv->restart_net_feed_wq);
|
||||||
@ -1367,7 +1367,7 @@ static int dvb_net_add_if(struct dvb_net *dvbnet, u16 pid, u8 feedtype)
|
|||||||
dvbnet->dvbdev->adapter->num, if_num);
|
dvbnet->dvbdev->adapter->num, if_num);
|
||||||
|
|
||||||
net->addr_len = 6;
|
net->addr_len = 6;
|
||||||
memcpy(net->dev_addr, dvbnet->dvbdev->adapter->proposed_mac, 6);
|
eth_hw_addr_set(net, dvbnet->dvbdev->adapter->proposed_mac);
|
||||||
|
|
||||||
dvbnet->device[if_num] = net;
|
dvbnet->device[if_num] = net;
|
||||||
|
|
||||||
|
@ -1350,7 +1350,7 @@ mpt_register_lan_device (MPT_ADAPTER *mpt_dev, int pnum)
|
|||||||
HWaddr[5] = a[0];
|
HWaddr[5] = a[0];
|
||||||
|
|
||||||
dev->addr_len = FC_ALEN;
|
dev->addr_len = FC_ALEN;
|
||||||
memcpy(dev->dev_addr, HWaddr, FC_ALEN);
|
dev_addr_set(dev, HWaddr);
|
||||||
memset(dev->broadcast, 0xff, FC_ALEN);
|
memset(dev->broadcast, 0xff, FC_ALEN);
|
||||||
|
|
||||||
/* The Tx queue is 127 deep on the 909.
|
/* The Tx queue is 127 deep on the 909.
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user