- 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:
Linus Torvalds 2021-11-02 06:20:58 -07:00
commit fc02cb2b37
2296 changed files with 209495 additions and 44392 deletions

View 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.

View 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.

View File

@ -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_DATASEC 15 /* Section */
#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.
``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.
*
* "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.
*/
union {
@ -465,6 +466,32 @@ map definition.
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
*****************

View File

@ -82,6 +82,15 @@ Testing and debugging BPF
s390
Licensing
=========
.. toctree::
:maxdepth: 1
bpf_licensing
Other
=====

View File

@ -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
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
-------------------

View 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>;
};
};

View File

@ -2,7 +2,8 @@
Required properties:
- 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
- interrupts and/or interrupts-extended: must be two cells, the first cell
is the general purpose interrupt line, while the second cell is the

View File

@ -46,6 +46,9 @@ patternProperties:
type: object
description: Ethernet switch ports
allOf:
- $ref: "http://devicetree.org/schemas/net/ethernet-controller.yaml#"
properties:
reg:
description: Port number
@ -73,11 +76,14 @@ patternProperties:
dsa-tag-protocol:
description:
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.
enum:
- dsa
- edsa
- ocelot
- ocelot-8021q
- seville
phy-handle: true
@ -91,6 +97,10 @@ patternProperties:
managed: true
rx-internal-delay-ps: true
tx-internal-delay-ps: true
required:
- reg

View File

@ -74,10 +74,42 @@ properties:
- compatible
- 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:
- compatible
- 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
examples:
@ -97,29 +129,40 @@ examples:
port@0 {
phy-handle = <&rgmii_phy6>;
phy-mode = "rgmii-id";
rx-internal-delay-ps = <0>;
tx-internal-delay-ps = <0>;
reg = <0>;
};
port@1 {
phy-handle = <&rgmii_phy3>;
phy-mode = "rgmii-id";
rx-internal-delay-ps = <0>;
tx-internal-delay-ps = <0>;
reg = <1>;
};
port@2 {
phy-handle = <&rgmii_phy4>;
phy-mode = "rgmii-id";
rx-internal-delay-ps = <0>;
tx-internal-delay-ps = <0>;
reg = <2>;
};
port@3 {
phy-handle = <&rgmii_phy4>;
phy-mode = "rgmii-id";
rx-internal-delay-ps = <0>;
tx-internal-delay-ps = <0>;
reg = <3>;
};
port@4 {
ethernet = <&enet2>;
phy-mode = "rgmii";
rx-internal-delay-ps = <0>;
tx-internal-delay-ps = <0>;
reg = <4>;
fixed-link {

View File

@ -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>;
};
};
};
};

View 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>;
};
};
};
};

View File

@ -9,6 +9,7 @@ SMI-based Realtek devices.
Required properties:
- compatible: must be exactly one of:
"realtek,rtl8365mb" (4+1 ports)
"realtek,rtl8366"
"realtek,rtl8366rb" (4+1 ports)
"realtek,rtl8366s" (4+1 ports)
@ -62,6 +63,8 @@ and subnodes of DSA switches.
Examples:
An example for the RTL8366RB:
switch {
compatible = "realtek,rtl8366rb";
/* 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 = <&ethphy0>;
};
port@1 {
reg = <1>;
label = "swp1";
phy-handle = <&ethphy1>;
};
port@2 {
reg = <2>;
label = "swp2";
phy-handle = <&ethphy2>;
};
port@3 {
reg = <3>;
label = "swp3";
phy-handle = <&ethphy3>;
};
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>;
};
};
};

View 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";
};

View File

@ -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";
};

View 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";
};

View File

@ -30,6 +30,10 @@ Required properties:
Optional elements: 'tsu_clk'
- 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
defined in ethernet.txt.

View File

@ -51,6 +51,9 @@ examples:
switch@10 {
compatible = "qca,qca8337";
reg = <0x10>;
/* ... */
ports {
/* ... */
};
};
};

View File

@ -100,15 +100,18 @@ additionalProperties: false
examples:
# Lager board
- |
#include <dt-bindings/clock/r8a7790-clock.h>
#include <dt-bindings/interrupt-controller/irq.h>
#include <dt-bindings/clock/r8a7790-cpg-mssr.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/power/r8a7790-sysc.h>
#include <dt-bindings/gpio/gpio.h>
ethernet@ee700000 {
compatible = "renesas,ether-r8a7790", "renesas,rcar-gen2-ether";
reg = <0xee700000 0x400>;
interrupt-parent = <&gic>;
interrupts = <0 162 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&mstp8_clks R8A7790_CLK_ETHER>;
interrupts = <GIC_SPI 162 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&cpg CPG_MOD 813>;
power-domains = <&sysc R8A7790_PD_ALWAYS_ON>;
resets = <&cpg 813>;
phy-mode = "rmii";
phy-handle = <&phy1>;
renesas,ether-link-active-low;
@ -116,8 +119,12 @@ examples:
#size-cells = <0>;
phy1: ethernet-phy@1 {
compatible = "ethernet-phy-id0022.1537",
"ethernet-phy-ieee802.3-c22";
reg = <1>;
interrupt-parent = <&irqc0>;
interrupts = <0 IRQ_TYPE_LEVEL_LOW>;
micrel,led-mode = <1>;
reset-gpios = <&gpio5 31 GPIO_ACTIVE_LOW>;
};
};

View File

@ -287,6 +287,7 @@ examples:
"ch13", "ch14", "ch15", "ch16", "ch17", "ch18",
"ch19", "ch20", "ch21", "ch22", "ch23", "ch24";
clocks = <&cpg CPG_MOD 812>;
clock-names = "fck";
iommus = <&ipmmu_ds0 16>;
power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
resets = <&cpg 812>;
@ -298,6 +299,8 @@ examples:
#size-cells = <0>;
phy0: ethernet-phy@0 {
compatible = "ethernet-phy-id0022.1622",
"ethernet-phy-ieee802.3-c22";
rxc-skew-ps = <1500>;
reg = <0>;
interrupt-parent = <&gpio2>;

View File

@ -24,6 +24,7 @@ properties:
- socionext,uniphier-ld11-ave4
- socionext,uniphier-ld20-ave4
- socionext,uniphier-pxs3-ave4
- socionext,uniphier-nx1-ave4
reg:
maxItems: 1

View File

@ -47,6 +47,11 @@ properties:
ieee80211-freq-limit: true
mediatek,eeprom-data:
$ref: /schemas/types.yaml#/definitions/uint32-array
description:
EEPROM data embedded as array.
mediatek,mtd-eeprom:
$ref: /schemas/types.yaml#/definitions/phandle-array
description:

View File

@ -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;
};
};

View File

@ -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";
};
};

View File

@ -131,6 +131,8 @@ patternProperties:
description: Asahi Kasei Corp.
"^asc,.*":
description: All Sensors Corporation
"^asix,.*":
description: ASIX Electronics Corporation
"^aspeed,.*":
description: ASPEED Technology Inc.
"^asus,.*":

View File

@ -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.
The recover function runs recover flow which reloads the driver and triggers fw
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:
@ -700,3 +702,61 @@ Eswitch QoS tracepoints:
$ cat /sys/kernel/debug/tracing/trace
...
<...>-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

View File

@ -22,6 +22,8 @@ Parameters
- Permanent
* - ``msix_vec_per_pf_min``
- Permanent
* - ``enable_remote_dev_reset``
- Runtime
The ``bnxt`` driver also implements the following driver-specific
parameters.

View File

@ -44,8 +44,8 @@ example usage
# Show all of the exposed regions with region sizes:
$ devlink region show
pci/0000:00:05.0/cr-space: size 1048576 snapshot [1 2]
pci/0000:00:05.0/fw-health: size 64 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] max 8
# Delete a snapshot using:
$ devlink region del pci/0000:00:05.0/cr-space snapshot 1

View File

@ -142,6 +142,10 @@ Users can request an immediate capture of a snapshot via the
.. 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 dump pci/0000:01:00.0/nvm-flash snapshot 1

View File

@ -47,3 +47,5 @@ parameters, info versions, and other features it supports.
ti-cpsw-switch
am65-nuss-cpsw-switch
prestera
iosm
octeontx2

View 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

View 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.

View File

@ -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
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
==============
@ -179,7 +184,7 @@ according to message purpose:
Userspace to kernel:
===================================== ================================
===================================== =================================
``ETHTOOL_MSG_STRSET_GET`` get string set
``ETHTOOL_MSG_LINKINFO_GET`` get 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_STATS_GET`` get standard statistics
``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:
@ -252,6 +259,7 @@ Kernel to userspace:
``ETHTOOL_MSG_MODULE_EEPROM_GET_REPLY`` read SFP module EEPROM
``ETHTOOL_MSG_STATS_GET_REPLY`` standard statistics
``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
@ -520,6 +528,8 @@ Link extended states:
power required from cable or module
``ETHTOOL_LINK_EXT_STATE_OVERHEAT`` The module is overheated
``ETHTOOL_LINK_EXT_STATE_MODULE`` Transceiver module issue
================================================ ============================================
Link extended substates:
@ -613,6 +623,14 @@ Link extended substates:
``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
=========
@ -1521,6 +1539,63 @@ Kernel response contents:
``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
===================
@ -1620,4 +1695,6 @@ are netlink only.
n/a ``ETHTOOL_MSG_CABLE_TEST_TDR_ACT``
n/a ``ETHTOOL_MSG_TUNNEL_INFO_GET``
n/a ``ETHTOOL_MSG_PHC_VCLOCKS_GET``
n/a ``ETHTOOL_MSG_MODULE_GET``
n/a ``ETHTOOL_MSG_MODULE_SET``
=================================== =====================================

View File

@ -989,14 +989,6 @@ tcp_challenge_ack_limit - INTEGER
in RFC 5961 (Improving TCP's Robustness to Blind In-Window Attacks)
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
=============
@ -1619,6 +1611,15 @@ arp_accept - BOOLEAN
gratuitous arp frame, the arp table will be updated regardless
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
The maximum number of multicast probes in INCOMPLETE state,
when the associated hardware address is unknown. Defaults
@ -2349,6 +2350,15 @@ ndisc_tclass - INTEGER
* 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
The interval in milliseconds in which the next unsolicited
MLDv1 report retransmit will take place.

View File

@ -300,3 +300,14 @@ sync_version - INTEGER
Kernels with this sync_version entry are able to receive messages
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.

View File

@ -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
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.

View File

@ -1026,6 +1026,14 @@ S: Maintained
F: Documentation/devicetree/bindings/iio/light/ams,as73211.yaml
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
M: Alexandru Tachici <alexandru.tachici@analog.com>
L: linux-iio@vger.kernel.org
@ -2908,6 +2916,12 @@ S: Maintained
F: Documentation/hwmon/asc7621.rst
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
M: Andrew Jeffery <andrew@aj.id.au>
L: linux-aspeed@lists.ozlabs.org (moderated for non-subscribers)
@ -3438,6 +3452,7 @@ S: Supported
F: arch/arm64/net/
BPF JIT for MIPS (32-BIT AND 64-BIT)
M: Johan Almbladh <johan.almbladh@anyfinetworks.com>
M: Paul Burton <paulburton@kernel.org>
L: netdev@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/pcs/
F: drivers/net/phy/
F: drivers/of/of_net.c
F: include/dt-bindings/net/qca-ar803x.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/uapi/linux/mdio.h
F: include/uapi/linux/mii.h
F: net/core/of_net.c
EXFAT FILE SYSTEM
M: Namjae Jeon <linkinjeon@kernel.org>
@ -11878,7 +11893,9 @@ F: drivers/mmc/host/mtk-sd.c
MEDIATEK MT76 WIRELESS LAN DRIVER
M: Felix Fietkau <nbd@nbd.name>
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
S: Maintained
F: drivers/net/wireless/mediatek/mt76/
@ -13109,6 +13126,7 @@ F: include/linux/dsa/
F: include/linux/platform_data/dsa.h
F: include/net/dsa.h
F: net/dsa/
F: tools/testing/selftests/drivers/net/dsa/
NETWORKING [GENERAL]
M: "David S. Miller" <davem@davemloft.net>
@ -15530,6 +15548,7 @@ M: ath9k-devel@qca.qualcomm.com
L: linux-wireless@vger.kernel.org
S: Supported
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/
QUALCOMM CAMERA SUBSYSTEM DRIVER
@ -15951,6 +15970,12 @@ L: linux-wireless@vger.kernel.org
S: Maintained
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
M: Amitkumar Karwar <amitkarwar@gmail.com>
M: Siva Rebbagondla <siva8118@gmail.com>

View File

@ -480,6 +480,8 @@ LZ4 = lz4c
XZ = xz
ZSTD = zstd
PAHOLE_FLAGS = $(shell PAHOLE=$(PAHOLE) $(srctree)/scripts/pahole-flags.sh)
CHECKFLAGS := -D__linux__ -Dlinux -D__STDC__ -Dunix -D__unix__ \
-Wbitwise -Wno-return-void -Wno-unknown-attribute $(CF)
NOSTDINC_FLAGS :=
@ -534,6 +536,7 @@ export KBUILD_CFLAGS CFLAGS_KERNEL CFLAGS_MODULE
export KBUILD_AFLAGS AFLAGS_KERNEL AFLAGS_MODULE
export KBUILD_AFLAGS_MODULE KBUILD_CFLAGS_MODULE KBUILD_LDFLAGS_MODULE
export KBUILD_AFLAGS_KERNEL KBUILD_CFLAGS_KERNEL
export PAHOLE_FLAGS
# Files to ignore in find ... statements

View File

@ -131,6 +131,8 @@
#define SO_BUF_LOCK 72
#define SO_RESERVE_MEM 73
#if !defined(__KERNEL__)
#if __BITS_PER_LONG == 64

View File

@ -1882,11 +1882,6 @@ static int validate_code(struct jit_ctx *ctx)
return 0;
}
void bpf_jit_compile(struct bpf_prog *prog)
{
/* Nothing to do here. We support Internal BPF. */
}
bool bpf_jit_needs_zext(void)
{
return true;

View File

@ -200,7 +200,7 @@ static struct net_device * __init nfeth_probe(int unit)
dev->irq = nfEtherIRQ;
dev->netdev_ops = &nfeth_netdev_ops;
memcpy(dev->dev_addr, mac, ETH_ALEN);
eth_hw_addr_set(dev, mac);
priv = netdev_priv(dev);
priv->ethX = unit;

View File

@ -56,7 +56,6 @@ config MIPS
select HAVE_ARCH_TRACEHOOK
select HAVE_ARCH_TRANSPARENT_HUGEPAGE if CPU_SUPPORTS_HUGEPAGES
select HAVE_ASM_MODVERSIONS
select HAVE_CBPF_JIT if !64BIT && !CPU_MICROMIPS
select HAVE_CONTEXT_TRACKING
select HAVE_TIF_NOHZ
select HAVE_C_RECORDMCOUNT
@ -64,7 +63,10 @@ config MIPS
select HAVE_DEBUG_STACKOVERFLOW
select HAVE_DMA_CONTIGUOUS
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_FAST_GUP
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
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
# answer,so we try hard to limit the available choices. Also the use of a

View File

@ -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_rx(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

View File

@ -145,6 +145,7 @@ Ip_u1(_mtlo);
Ip_u3u1u2(_mul);
Ip_u1u2(_multu);
Ip_u3u1u2(_mulu);
Ip_u3u1u2(_muhu);
Ip_u3u1u2(_nor);
Ip_u3u1u2(_or);
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_ehb(buf) uasm_i_sll(buf, 0, 0, 3)
#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)
#endif
#define uasm_i_ssnop(buf) uasm_i_sll(buf, 0, 0, 1)
static inline void uasm_i_drotr_safe(u32 **p, unsigned int a1,

View File

@ -142,6 +142,8 @@
#define SO_BUF_LOCK 72
#define SO_RESERVE_MEM 73
#if !defined(__KERNEL__)
#if __BITS_PER_LONG == 64

View File

@ -11,6 +11,7 @@
#include <linux/export.h>
#include <linux/spinlock.h>
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/err.h>
#include <linux/of.h>
@ -30,6 +31,7 @@
#define LTQ_DMA_PCTRL 0x44
#define LTQ_DMA_IRNEN 0xf4
#define DMA_ID_CHNR GENMASK(26, 20) /* channel number */
#define DMA_DESCPT BIT(3) /* descriptor complete irq */
#define DMA_TX BIT(8) /* TX channel direction */
#define DMA_CHAN_ON BIT(0) /* channel on / off bit */
@ -39,8 +41,11 @@
#define DMA_IRQ_ACK 0x7e /* IRQ status register */
#define DMA_POLL BIT(31) /* turn on channel polling */
#define DMA_CLK_DIV4 BIT(6) /* polling clock divider */
#define DMA_2W_BURST BIT(1) /* 2 word burst length */
#define DMA_MAX_CHANNEL 20 /* the soc has 20 channels */
#define DMA_PCTRL_2W_BURST 0x1 /* 2 word burst length */
#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_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);
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);
switch (p) {
@ -186,15 +191,44 @@ ltq_dma_init_port(int p)
* Tell the DMA engine to swap the endianness of data frames and
* 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);
break;
case DMA_PORT_DEU:
ltq_dma_w32((DMA_2W_BURST << 4) | (DMA_2W_BURST << 2),
default:
break;
}
switch (rx_burst) {
case 8:
ltq_dma_w32_mask(0x0c, (DMA_PCTRL_8W_BURST << DMA_RX_BURST_SHIFT),
LTQ_DMA_PCTRL);
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:
break;
}
@ -206,7 +240,7 @@ ltq_dma_init(struct platform_device *pdev)
{
struct clk *clk;
struct resource *res;
unsigned id;
unsigned int id, nchannels;
int i;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@ -222,21 +256,24 @@ ltq_dma_init(struct platform_device *pdev)
clk_enable(clk);
ltq_dma_w32_mask(0, DMA_RESET, LTQ_DMA_CTRL);
usleep_range(1, 10);
/* disable all interrupts */
ltq_dma_w32(0, LTQ_DMA_IRNEN);
/* 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(DMA_CHAN_RST, LTQ_DMA_CCTRL);
ltq_dma_w32(DMA_POLL | DMA_CLK_DIV4, LTQ_DMA_CPOLL);
ltq_dma_w32_mask(DMA_CHAN_ON, 0, LTQ_DMA_CCTRL);
}
id = ltq_dma_r32(LTQ_DMA_ID);
dev_info(&pdev->dev,
"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;
}

View File

@ -90,7 +90,7 @@ static const struct insn insn_table[insn_invalid] = {
RS | RT | RD},
[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_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},
[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},
@ -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_mulu] = {M(spec_op, 0, 0, 0, multu_mulu_op, multu_op),
RS | RT | RD},
[insn_muhu] = {M(spec_op, 0, 0, 0, multu_muhu_op, multu_op),
RS | RT | RD},
#ifndef CONFIG_CPU_MIPSR6
[insn_mul] = {M(spec2_op, 0, 0, 0, 0, mul_op), RS | RT | RD},
#else

View File

@ -59,7 +59,7 @@ enum opcode {
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_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_scd, insn_seleqz, insn_selnez, insn_sd, insn_sh, insn_sll,
insn_sllv, insn_slt, insn_slti, insn_sltiu, insn_sltu, insn_sra,
@ -344,6 +344,7 @@ I_u1(_mtlo)
I_u3u1u2(_mul)
I_u1u2(_multu)
I_u3u1u2(_mulu)
I_u3u1u2(_muhu)
I_u3u1u2(_nor)
I_u3u1u2(_or)
I_u2u1u3(_ori)

View File

@ -1,5 +1,10 @@
# SPDX-License-Identifier: GPL-2.0-only
# MIPS networking code
obj-$(CONFIG_MIPS_CBPF_JIT) += bpf_jit.o bpf_jit_asm.o
obj-$(CONFIG_MIPS_EBPF_JIT) += ebpf_jit.o
obj-$(CONFIG_BPF_JIT) += bpf_jit_comp.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

View File

@ -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 */

View File

@ -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

File diff suppressed because it is too large Load Diff

View 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 */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -123,6 +123,8 @@
#define SO_BUF_LOCK 0x4046
#define SO_RESERVE_MEM 0x4047
#if !defined(__KERNEL__)
#if __BITS_PER_LONG == 64

View File

@ -11,14 +11,23 @@
#include <linux/module.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)
{
const struct exception_table_entry *fixup;
fixup = search_exception_tables(regs->epc);
if (fixup) {
regs->epc = fixup->fixup;
return 1;
}
return 0;
if (!fixup)
return 0;
#ifdef CONFIG_BPF_JIT
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;
}

View File

@ -71,6 +71,7 @@ struct rv_jit_context {
int ninsns;
int epilogue_offset;
int *offset; /* BPF to RV */
int nexentries;
unsigned long flags;
int stack_size;
};

View File

@ -5,6 +5,7 @@
*
*/
#include <linux/bitfield.h>
#include <linux/bpf.h>
#include <linux/filter.h>
#include "bpf_jit.h"
@ -27,6 +28,21 @@ static const int regmap[] = {
[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 {
RV_CTX_F_SEEN_TAIL_CALL = 0,
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;
}
#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,
bool extra_pass)
{
@ -893,52 +972,86 @@ out_be:
/* LDX: dst = *(size *)(src + off) */
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:
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:
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:
if (is_12b_int(off)) {
emit_ld(rd, off, rs, ctx);
case BPF_LDX | BPF_PROBE_MEM | BPF_B:
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;
}
emit_imm(RV_REG_T1, off, ctx);
emit_add(RV_REG_T1, RV_REG_T1, rs, ctx);
emit_ld(rd, 0, RV_REG_T1, ctx);
ret = add_exception_handler(insn, ctx, rd, insn_len);
if (ret)
return ret;
break;
}
/* speculation barrier */
case BPF_ST | BPF_NOSPEC:
break;

View File

@ -11,7 +11,7 @@
#include "bpf_jit.h"
/* 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)
{
@ -41,12 +41,12 @@ bool bpf_jit_needs_zext(void)
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;
struct bpf_prog *tmp, *orig_prog = prog;
int pass = 0, prev_ninsns = 0, i;
struct rv_jit_data *jit_data;
struct rv_jit_context *ctx;
unsigned int image_size = 0;
if (!prog->jit_requested)
return orig_prog;
@ -73,7 +73,7 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
if (ctx->offset) {
extra_pass = true;
image_size = sizeof(*ctx->insns) * ctx->ninsns;
prog_size = sizeof(*ctx->insns) * ctx->ninsns;
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 (jit_data->header)
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 =
bpf_jit_binary_alloc(image_size,
bpf_jit_binary_alloc(prog_size + extable_size,
&jit_data->image,
sizeof(u32),
bpf_fill_ill_insns);
@ -131,9 +134,13 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
goto out_offset;
}
if (extable_size)
prog->aux->extable = (void *)ctx->insns + prog_size;
skip_init_ctx:
pass++;
ctx->ninsns = 0;
ctx->nexentries = 0;
bpf_jit_build_prologue(ctx);
if (build_body(ctx, extra_pass, NULL)) {
@ -144,11 +151,11 @@ skip_init_ctx:
bpf_jit_build_epilogue(ctx);
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->jited = 1;
prog->jited_len = image_size;
prog->jited_len = prog_size;
bpf_flush_icache(jit_data->header, ctx->insns + ctx->ninsns);

View File

@ -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,
struct qdio_initialize *init_data);
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,
unsigned int bufnr, unsigned int count, struct qaob *aob);
extern int qdio_start_irq(struct ccw_device *cdev);

View File

@ -124,6 +124,9 @@
#define SO_BUF_LOCK 0x0051
#define SO_RESERVE_MEM 0x0052
#if !defined(__KERNEL__)

View File

@ -276,7 +276,7 @@ static const struct ethtool_ops uml_net_ethtool_ops = {
void uml_net_setup_etheraddr(struct net_device *dev, char *str)
{
unsigned char *addr = dev->dev_addr;
u8 addr[ETH_ALEN];
char *end;
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[5]);
}
eth_hw_addr_set(dev, addr);
return;
random:

View File

@ -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
* 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);
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();
}
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_lbr_disable_all();
}
@ -2188,6 +2188,49 @@ static void intel_pmu_enable_all(int added)
__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:
* 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);
intel_bts_disable_local();
cpuc->enabled = 0;
__intel_pmu_disable_all();
__intel_pmu_disable_all(true);
handled = intel_pmu_drain_bts_buffer();
handled += intel_bts_interrupt();
status = intel_pmu_get_status();
@ -6299,9 +6342,21 @@ __init int intel_pmu_init(void)
x86_pmu.lbr_nr = 0;
}
if (x86_pmu.lbr_nr)
if (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);
/* Support full width counters using alternative MSR range */

View File

@ -1302,7 +1302,7 @@ void intel_pmu_pebs_disable_all(void)
struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
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)

View File

@ -228,20 +228,6 @@ static void __intel_pmu_lbr_enable(bool pmi)
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)
{
int i;
@ -779,8 +765,12 @@ void intel_pmu_lbr_disable_all(void)
{
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();
}
}
void intel_pmu_lbr_read_32(struct cpu_hw_events *cpuc)

View File

@ -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);
}
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);
struct event_constraint *

View File

@ -697,6 +697,20 @@ static void maybe_emit_mod(u8 **pprog, u32 dst_reg, u32 src_reg, bool is64)
*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) */
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 */
case BPF_ALU | BPF_NEG:
case BPF_ALU64 | BPF_NEG:
if (BPF_CLASS(insn->code) == BPF_ALU64)
EMIT1(add_1mod(0x48, dst_reg));
else if (is_ereg(dst_reg))
EMIT1(add_1mod(0x40, dst_reg));
maybe_emit_1mod(&prog, dst_reg,
BPF_CLASS(insn->code) == BPF_ALU64);
EMIT2(0xF7, add_1reg(0xD8, dst_reg));
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_OR | BPF_K:
case BPF_ALU64 | BPF_XOR | BPF_K:
if (BPF_CLASS(insn->code) == BPF_ALU64)
EMIT1(add_1mod(0x48, dst_reg));
else if (is_ereg(dst_reg))
EMIT1(add_1mod(0x40, dst_reg));
maybe_emit_1mod(&prog, dst_reg,
BPF_CLASS(insn->code) == BPF_ALU64);
/*
* 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_DIV | BPF_X:
case BPF_ALU64 | BPF_MOD | 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:
{
case BPF_ALU64 | BPF_DIV | BPF_K: {
bool is64 = BPF_CLASS(insn->code) == BPF_ALU64;
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)
EMIT1(0x52); /* push rdx */
/* mov r11, dst_reg */
EMIT_mov(AUX_REG, dst_reg);
if (BPF_SRC(insn->code) == BPF_X) {
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)
emit_mov_reg(&prog, is64, BPF_REG_0, src_reg);
else
emit_mov_imm32(&prog, is64, BPF_REG_0, imm32);
if (dst_reg != BPF_REG_0)
/* mov rax, dst_reg */
emit_mov_reg(&prog, is64, BPF_REG_0, dst_reg);
if (is64)
EMIT1(add_1mod(0x48, AUX_REG));
else if (is_ereg(AUX_REG))
EMIT1(add_1mod(0x40, AUX_REG));
/* mul(q) r11 */
EMIT2(0xF7, add_1reg(0xE0, AUX_REG));
/*
* xor edx, edx
* equivalent to 'xor rdx, rdx', but one byte less
*/
EMIT2(0x31, 0xd2);
/* 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)
EMIT1(0x5A); /* pop rdx */
if (dst_reg != BPF_REG_0) {
/* mov dst_reg, rax */
EMIT_mov(dst_reg, BPF_REG_0);
if (dst_reg != BPF_REG_0)
EMIT1(0x58); /* pop rax */
}
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 */
case BPF_ALU | BPF_LSH | 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_RSH | BPF_K:
case BPF_ALU64 | BPF_ARSH | BPF_K:
if (BPF_CLASS(insn->code) == BPF_ALU64)
EMIT1(add_1mod(0x48, dst_reg));
else if (is_ereg(dst_reg))
EMIT1(add_1mod(0x40, dst_reg));
maybe_emit_1mod(&prog, dst_reg,
BPF_CLASS(insn->code) == BPF_ALU64);
b3 = simple_alu_opcodes[BPF_OP(insn->code)];
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 */
if (BPF_CLASS(insn->code) == BPF_ALU64)
EMIT1(add_1mod(0x48, dst_reg));
else if (is_ereg(dst_reg))
EMIT1(add_1mod(0x40, dst_reg));
maybe_emit_1mod(&prog, dst_reg,
BPF_CLASS(insn->code) == BPF_ALU64);
b3 = simple_alu_opcodes[BPF_OP(insn->code)];
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_JMP32 | BPF_JSET | BPF_K:
/* test dst_reg, imm32 */
if (BPF_CLASS(insn->code) == BPF_JMP)
EMIT1(add_1mod(0x48, dst_reg));
else if (is_ereg(dst_reg))
EMIT1(add_1mod(0x40, dst_reg));
maybe_emit_1mod(&prog, dst_reg,
BPF_CLASS(insn->code) == BPF_JMP);
EMIT2_off32(0xF7, add_1reg(0xC0, dst_reg), imm32);
goto emit_cond_jmp;
@ -1466,10 +1469,8 @@ st: if (is_imm8(insn->off))
}
/* cmp dst_reg, imm8/32 */
if (BPF_CLASS(insn->code) == BPF_JMP)
EMIT1(add_1mod(0x48, dst_reg));
else if (is_ereg(dst_reg))
EMIT1(add_1mod(0x40, dst_reg));
maybe_emit_1mod(&prog, dst_reg,
BPF_CLASS(insn->code) == BPF_JMP);
if (is_imm8(imm32))
EMIT3(0x83, add_1reg(0xF8, dst_reg), imm32);

View File

@ -124,7 +124,7 @@ static char *split_if_spec(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)
goto random;
@ -147,6 +147,7 @@ static void setup_etheraddr(struct net_device *dev, char *str)
if (!is_local_ether_addr(addr))
pr_warn("%s: assigning a globally valid ethernet address\n",
dev->name);
eth_hw_addr_set(dev, addr);
return;
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))
return -EADDRNOTAVAIL;
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);
return 0;
}

View File

@ -15,7 +15,6 @@
#include <linux/of_graph.h>
#include <linux/of_irq.h>
#include <linux/property.h>
#include <linux/etherdevice.h>
#include <linux/phy.h>
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);
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: Pointer to the firmware node

View File

@ -14,7 +14,7 @@ static int regmap_mdio_read(struct mdio_device *mdio_dev, u32 reg, unsigned int
{
int ret;
ret = mdiobus_read(mdio_dev->bus, mdio_dev->addr, reg);
ret = mdiodev_read(mdio_dev, reg);
if (ret < 0)
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)
{
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)
@ -44,7 +44,7 @@ static int regmap_mdio_c22_write(void *context, unsigned int reg, unsigned int v
if (unlikely(reg & ~REGNUM_C22_MASK))
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 = {

View File

@ -20,7 +20,7 @@ MODULE_DESCRIPTION("Broadcom's specific AMBA driver");
MODULE_LICENSE("GPL");
/* 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 */
static DEFINE_MUTEX(bcma_buses_mutex);

View File

@ -1037,8 +1037,9 @@ static bool btintel_firmware_version(struct hci_dev *hdev,
params = (void *)(fw_ptr + sizeof(*cmd));
bt_dev_info(hdev, "Boot Address: 0x%x",
le32_to_cpu(params->boot_addr));
*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",
params->fw_build_num, params->fw_build_ww,
@ -1071,9 +1072,6 @@ int btintel_download_firmware(struct hci_dev *hdev,
/* Skip version checking */
break;
default:
/* Skip reading firmware file version in bootloader mode */
if (ver->fw_variant == 0x06)
break;
/* Skip download if firmware has the same version */
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;
u32 css_header_ver;
/* Skip reading firmware file version in bootloader mode */
if (ver->img_type != 0x01) {
/* Skip download if firmware has the same version */
if (btintel_firmware_version(hdev, ver->min_fw_build_nn,
ver->min_fw_build_cw,
ver->min_fw_build_yy,
fw, boot_param)) {
bt_dev_info(hdev, "Firmware already loaded");
/* Return -EALREADY to indicate that firmware has
* already been loaded.
*/
return -EALREADY;
}
/* Skip download if firmware has the same version */
if (btintel_firmware_version(hdev, ver->min_fw_build_nn,
ver->min_fw_build_cw,
ver->min_fw_build_yy,
fw, boot_param)) {
bt_dev_info(hdev, "Firmware already loaded");
/* Return -EALREADY to indicate that firmware has
* already been loaded.
*/
return -EALREADY;
}
/* 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,
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 };
u8 period[5] = { 0x04, 0x91, 0x02, 0x05, 0x00 };
u8 trace_enable = 0x02;
struct sk_buff *skb;
if (!features)
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");
@ -1303,11 +1302,95 @@ static int btintel_set_debug_features(struct hci_dev *hdev,
PTR_ERR(skb));
return PTR_ERR(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;
}
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,
struct intel_version *ver)
{
@ -1893,7 +1976,6 @@ static int btintel_bootloader_setup(struct hci_dev *hdev,
u32 boot_param;
char ddcname[64];
int err;
struct intel_debug_features features;
BT_DBG("%s", hdev->name);
@ -1934,14 +2016,7 @@ static int btintel_bootloader_setup(struct hci_dev *hdev,
btintel_load_ddc_config(hdev, ddcname);
}
/* 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) {
/* Set DDC mask for available debug features */
btintel_set_debug_features(hdev, &features);
}
hci_dev_clear_flag(hdev, HCI_QUALITY_REPORT);
/* Read the Intel version information after loading the FW */
err = btintel_read_version(hdev, &new_ver);
@ -2083,13 +2158,102 @@ done:
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,
struct intel_version_tlv *ver)
{
u32 boot_param;
char ddcname[64];
int err;
struct intel_debug_features features;
struct intel_version_tlv new_ver;
bt_dev_dbg(hdev, "");
@ -2125,14 +2289,10 @@ static int btintel_bootloader_setup_tlv(struct hci_dev *hdev,
*/
btintel_load_ddc_config(hdev, ddcname);
/* 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) {
/* Set DDC mask for available debug features */
btintel_set_debug_features(hdev, &features);
}
/* Read supported use cases and set callbacks to fetch datapath id */
btintel_configure_offload(hdev);
hci_dev_clear_flag(hdev, HCI_QUALITY_REPORT);
/* Read the Intel version information after loading the FW */
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_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 */
if (skb->len == sizeof(ver) && skb->data[1] == 0x37) {
bt_dev_dbg(hdev, "Read the legacy Intel version information");

View File

@ -132,6 +132,11 @@ struct intel_debug_features {
__u8 page1[16];
} __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_VARIANT(cnvx_bt) ((u8)(((cnvx_bt) & 0x003f0000) >> 16))
#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_secure_send_result(struct hci_dev *hdev,
const void *ptr, unsigned int len);
int btintel_set_quality_report(struct hci_dev *hdev, bool enable);
#else
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)
{
}
static inline int btintel_set_quality_report(struct hci_dev *hdev, bool enable)
{
return -ENODEV;
}
#endif

View File

@ -587,12 +587,12 @@ static int btmrvl_set_bdaddr(struct hci_dev *hdev, const bdaddr_t *bdaddr)
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_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->setup = btmrvl_setup;
hdev->set_bdaddr = btmrvl_set_bdaddr;
hdev->prevent_wake = btmrvl_prevent_wake;
hdev->wakeup = btmrvl_wakeup;
SET_HCIDEV_DEV(hdev, &card->func->dev);
hdev->dev_type = priv->btmrvl_dev.dev_type;

View File

@ -158,8 +158,10 @@ static int mtk_hci_wmt_sync(struct hci_dev *hdev,
int err;
hlen = sizeof(*hdr) + wmt_params->dlen;
if (hlen > 255)
return -EINVAL;
if (hlen > 255) {
err = -EINVAL;
goto err_free_skb;
}
hdr = (struct mtk_wmt_hdr *)&wc;
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);
if (err < 0) {
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
@ -190,13 +192,14 @@ static int mtk_hci_wmt_sync(struct hci_dev *hdev,
if (err == -EINTR) {
bt_dev_err(hdev, "Execution of wmt command interrupted");
clear_bit(BTMTKUART_TX_WAIT_VND_EVT, &bdev->tx_state);
return err;
goto err_free_skb;
}
if (err) {
bt_dev_err(hdev, "Execution of wmt command timed out");
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 */

View File

@ -19,7 +19,6 @@
#include <net/bluetooth/hci_core.h>
#include <asm/unaligned.h>
#include <net/rsi_91x.h>
#include <net/genetlink.h>
#define RSI_DMA_ALIGN 8
#define RSI_FRAME_DESC_SIZE 16

View File

@ -59,6 +59,7 @@ struct id_table {
__u8 hci_bus;
bool config_needed;
bool has_rom_version;
bool has_msft_ext;
char *fw_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),
.config_needed = false,
.has_rom_version = true,
.has_msft_ext = true,
.fw_name = "rtl_bt/rtl8821c_fw.bin",
.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),
.config_needed = false,
.has_rom_version = true,
.has_msft_ext = true,
.fw_name = "rtl_bt/rtl8761b_fw.bin",
.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),
.config_needed = true,
.has_rom_version = true,
.has_msft_ext = true,
.fw_name = "rtl_bt/rtl8822cs_fw.bin",
.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),
.config_needed = false,
.has_rom_version = true,
.has_msft_ext = true,
.fw_name = "rtl_bt/rtl8822cu_fw.bin",
.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),
.config_needed = true,
.has_rom_version = true,
.has_msft_ext = true,
.fw_name = "rtl_bt/rtl8822b_fw.bin",
.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),
.config_needed = false,
.has_rom_version = true,
.has_msft_ext = true,
.fw_name = "rtl_bt/rtl8852au_fw.bin",
.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);
lmp_subver = le16_to_cpu(resp->lmp_subver);
if (resp->hci_ver == 0x8 && le16_to_cpu(resp->hci_rev) == 0x826c &&
resp->lmp_ver == 0x8 && le16_to_cpu(resp->lmp_subver) == 0xa99e)
btrtl_dev->ic_info = btrtl_match_ic(lmp_subver, hci_rev, hci_ver,
hdev->bus);
if (!btrtl_dev->ic_info)
btrtl_dev->drop_fw = true;
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_rev = le16_to_cpu(resp->hci_rev);
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:
kfree_skb(skb);
btrtl_dev->ic_info = btrtl_match_ic(lmp_subver, hci_rev, hci_ver,
hdev->bus);
if (!btrtl_dev->ic_info) {
rtl_dev_info(hdev, "unknown IC info, lmp subver %04x, hci rev %04x, hci ver %04x",
lmp_subver, hci_rev, hci_ver);
@ -684,12 +693,8 @@ out_free:
/* The following chips supports the Microsoft vendor extension,
* therefore set the corresponding VsMsftOpCode.
*/
switch (lmp_subver) {
case RTL_ROM_LMP_8822B:
case RTL_ROM_LMP_8852A:
if (btrtl_dev->ic_info->has_msft_ext)
hci_set_msft_opcode(hdev, 0xFCF0);
break;
}
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:
set_bit(HCI_QUIRK_VALID_LE_STATES, &hdev->quirks);
set_bit(HCI_QUIRK_WIDEBAND_SPEECH_SUPPORTED, &hdev->quirks);
hci_set_aosp_capable(hdev);
break;
default:
rtl_dev_dbg(hdev, "Central-peripheral role not enabled.");

View File

@ -384,6 +384,12 @@ static const struct usb_device_id blacklist_table[] = {
/* Realtek 8852AE Bluetooth devices */
{ USB_DEVICE(0x0bda, 0xc852), .driver_info = BTUSB_REALTEK |
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 */
{ 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 |
BTUSB_WIDEBAND_SPEECH |
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 |
BTUSB_WIDEBAND_SPEECH |
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(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 */
{ USB_DEVICE(0x0b05, 0x190e), .driver_info = BTUSB_REALTEK |
BTUSB_WIDEBAND_SPEECH },
@ -451,10 +464,6 @@ static const struct usb_device_id blacklist_table[] = {
/* Additional Realtek 8822CE Bluetooth devices */
{ USB_DEVICE(0x04ca, 0x4005), .driver_info = BTUSB_REALTEK |
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 |
BTUSB_WIDEBAND_SPEECH },
{ 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)
{
struct btusb_data *data = hci_get_drvdata(hdev);
struct gpio_desc *reset_gpio = data->reset_gpio;
int err;
if (++data->cmd_timeout_cnt < 5)
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.");
/* This is not an unbalanced PM reference since the device will reset */
err = usb_autopm_get_interface(data->intf);
@ -2200,6 +2231,23 @@ struct btmtk_section_map {
};
} __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)
{
struct hci_dev *hdev = urb->context;
@ -2804,6 +2852,7 @@ static int btusb_mtk_setup(struct hci_dev *hdev)
case 0x7668:
fwname = FIRMWARE_MT7668;
break;
case 0x7922:
case 0x7961:
snprintf(fw_bin_name, sizeof(fw_bin_name),
"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;
}
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);
return !device_may_wakeup(&data->udev->dev);
return device_may_wakeup(&data->udev->dev);
}
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->send = btusb_send_frame;
hdev->notify = btusb_notify;
hdev->prevent_wake = btusb_prevent_wake;
hdev->wakeup = btusb_wakeup;
#ifdef CONFIG_PM
err = btusb_config_oob_wake(hdev);
@ -3819,6 +3868,7 @@ static int btusb_probe(struct usb_interface *intf,
hdev->shutdown = btusb_mtk_shutdown;
hdev->manufacturer = 70;
hdev->cmd_timeout = btusb_mtk_cmd_timeout;
hdev->set_bdaddr = btusb_set_bdaddr_mtk;
set_bit(HCI_QUIRK_NON_PERSISTENT_SETUP, &hdev->quirks);
data->recv_acl = btusb_recv_acl_mtk;
}

View File

@ -587,9 +587,11 @@ static int h5_recv(struct hci_uart *hu, const void *data, int count)
count -= processed;
}
pm_runtime_get(&hu->serdev->dev);
pm_runtime_mark_last_busy(&hu->serdev->dev);
pm_runtime_put_autosuspend(&hu->serdev->dev);
if (hu->serdev) {
pm_runtime_get(&hu->serdev->dev);
pm_runtime_mark_last_busy(&hu->serdev->dev);
pm_runtime_put_autosuspend(&hu->serdev->dev);
}
return 0;
}
@ -814,7 +816,6 @@ static int h5_serdev_probe(struct serdev_device *serdev)
struct device *dev = &serdev->dev;
struct h5 *h5;
const struct h5_device_data *data;
int err;
h5 = devm_kzalloc(dev, sizeof(*h5), GFP_KERNEL);
if (!h5)
@ -846,6 +847,8 @@ static int h5_serdev_probe(struct serdev_device *serdev)
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);
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))
return PTR_ERR(h5->device_wake_gpio);
err = 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;
return hci_uart_register_device(&h5->serdev_hu, &h5p);
}
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_baudrate(h5->hu->serdev, 115200);
pm_runtime_set_active(&h5->hu->serdev->dev);
pm_runtime_use_autosuspend(&h5->hu->serdev->dev);
pm_runtime_set_autosuspend_delay(&h5->hu->serdev->dev,
SUSPEND_TIMEOUT_MS);
pm_runtime_enable(&h5->hu->serdev->dev);
if (!test_bit(H5_WAKEUP_DISABLE, &h5->flags)) {
pm_runtime_set_active(&h5->hu->serdev->dev);
pm_runtime_use_autosuspend(&h5->hu->serdev->dev);
pm_runtime_set_autosuspend_delay(&h5->hu->serdev->dev,
SUSPEND_TIMEOUT_MS);
pm_runtime_enable(&h5->hu->serdev->dev);
}
/* The controller needs up to 500ms to wakeup */
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)
{
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->enable_gpio, 0);

View File

@ -479,6 +479,9 @@ static int hci_uart_tty_open(struct tty_struct *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
* hole
*/

View File

@ -1577,7 +1577,7 @@ static void qca_cmd_timeout(struct hci_dev *hdev)
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);
bool wakeup;
@ -1730,6 +1730,7 @@ retry:
if (qca_is_wcn399x(soc_type) ||
qca_is_wcn6750(soc_type)) {
set_bit(HCI_QUIRK_USE_BDADDR_PROPERTY, &hdev->quirks);
hci_set_aosp_capable(hdev);
ret = qca_read_soc_version(hdev, &ver, soc_type);
if (ret)
@ -1764,7 +1765,7 @@ retry:
qca_debugfs_init(hdev);
hu->hdev->hw_error = qca_hw_error;
hu->hdev->cmd_timeout = qca_cmd_timeout;
hu->hdev->prevent_wake = qca_prevent_wake;
hu->hdev->wakeup = qca_wakeup;
} else if (ret == -ENOENT) {
/* No patch/nvm-config found, run with original fw/config */
set_bit(QCA_ROM_FW, &qca->flags);

View File

@ -21,6 +21,7 @@
#include <linux/skbuff.h>
#include <linux/miscdevice.h>
#include <linux/debugfs.h>
#include <net/bluetooth/bluetooth.h>
#include <net/bluetooth/hci_core.h>
@ -37,6 +38,9 @@ struct vhci_data {
struct mutex open_mutex;
struct delayed_work open_timeout;
bool suspended;
bool wakeup;
};
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;
}
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)
{
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->flush = vhci_flush;
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 */
if (opcode & 0x40)
@ -129,6 +245,12 @@ static int __vhci_create_device(struct vhci_data *data, __u8 opcode)
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;
skb_put_u8(skb, 0xff);

View File

@ -1443,8 +1443,8 @@ static int fwnet_probe(struct fw_unit *unit,
struct net_device *net;
bool allocated_netdev = false;
struct fwnet_device *dev;
union fwnet_hwaddr ha;
int ret;
union fwnet_hwaddr *ha;
mutex_lock(&fwnet_device_mutex);
@ -1491,12 +1491,12 @@ static int fwnet_probe(struct fw_unit *unit,
net->max_mtu = 4096U;
/* Set our hardware address while we're at it */
ha = (union fwnet_hwaddr *)net->dev_addr;
put_unaligned_be64(card->guid, &ha->uc.uniq_id);
ha->uc.max_rec = dev->card->max_receive;
ha->uc.sspd = dev->card->link_speed;
put_unaligned_be16(dev->local_fifo >> 32, &ha->uc.fifo_hi);
put_unaligned_be32(dev->local_fifo & 0xffffffff, &ha->uc.fifo_lo);
ha.uc.uniq_id = cpu_to_be64(card->guid);
ha.uc.max_rec = dev->card->max_receive;
ha.uc.sspd = dev->card->link_speed;
ha.uc.fifo_hi = cpu_to_be16(dev->local_fifo >> 32);
ha.uc.fifo_lo = cpu_to_be32(dev->local_fifo & 0xffffffff);
dev_addr_set(net, ha.u);
memset(net->broadcast, -1, net->addr_len);

View File

@ -1055,14 +1055,16 @@ static const struct net_device_ops ssip_pn_ops = {
static void ssip_pn_setup(struct net_device *dev)
{
static const u8 addr = PN_MEDIA_SOS;
dev->features = 0;
dev->netdev_ops = &ssip_pn_ops;
dev->type = ARPHRD_PHONET;
dev->flags = IFF_POINTOPOINT | IFF_NOARP;
dev->mtu = SSIP_DEFAULT_MTU;
dev->hard_header_len = 1;
dev->dev_addr[0] = PN_MEDIA_SOS;
dev->addr_len = 1;
dev_addr_set(dev, &addr);
dev->tx_queue_len = SSIP_TXQUEUE_LEN;
dev->needs_free_netdev = true;

View File

@ -2275,7 +2275,7 @@ static void mlx4_ib_update_qps(struct mlx4_ib_dev *ibdev,
u64 release_mac = MLX4_IB_INVALID_MAC;
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);
/* no need for update QP1 and mac registration in non-SRIOV */

View File

@ -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)
{
return _mlx4_set_path(dev, &qp->ah_attr,
mlx4_mac_to_u64(smac),
ether_addr_to_u64(smac),
vlan_id,
path, &mqp->pri, port);
}

View File

@ -206,3 +206,29 @@ out:
kfree(in);
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);
}

View File

@ -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_mad_ifc(struct mlx5_core_dev *dev, const void *inb, void *outb,
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 */

View File

@ -1292,21 +1292,16 @@ static int devx_handle_mkey_indirect(struct devx_obj *obj,
struct mlx5_ib_dev *dev,
void *in, void *out)
{
struct mlx5_ib_devx_mr *devx_mr = &obj->devx_mr;
struct mlx5_core_mkey *mkey;
struct mlx5_ib_mkey *mkey = &obj->mkey;
void *mkc;
u8 key;
mkey = &devx_mr->mmkey;
mkc = MLX5_ADDR_OF(create_mkey_in, in, memory_key_mkey_entry);
key = MLX5_GET(mkc, mkc, mkey_7_0);
mkey->key = mlx5_idx_to_mkey(
MLX5_GET(create_mkey_out, out, mkey_index)) | key;
mkey->type = MLX5_MKEY_INDIRECT_DEVX;
mkey->iova = MLX5_GET64(mkc, mkc, start_addr);
mkey->size = MLX5_GET64(mkc, mkc, len);
mkey->pd = MLX5_GET(mkc, mkc, pd);
devx_mr->ndescs = MLX5_GET(mkc, mkc, translations_octword_size);
mkey->ndescs = MLX5_GET(mkc, mkc, translations_octword_size);
init_waitqueue_head(&mkey->wait);
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);
if (obj->flags & DEVX_OBJ_FLAGS_INDIRECT_MKEY &&
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 mmkey, we must wait for that to stop before freeing the
* 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)
ret = mlx5_core_destroy_dct(obj->ib_dev, &obj->core_dct);

View File

@ -16,7 +16,7 @@ struct devx_obj {
u32 dinbox[MLX5_MAX_DESTROY_INBOX_SIZE_DW];
u32 flags;
union {
struct mlx5_ib_devx_mr devx_mr;
struct mlx5_ib_mkey mkey;
struct mlx5_core_dct core_dct;
struct mlx5_core_cq core_cq;
u32 flow_counter_bulk_size;

View File

@ -1643,7 +1643,8 @@ static int allocate_uars(struct mlx5_ib_dev *dev, struct mlx5_ib_ucontext *conte
bfregi = &context->bfregi;
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)
goto error;
@ -1657,7 +1658,8 @@ static int allocate_uars(struct mlx5_ib_dev *dev, struct mlx5_ib_ucontext *conte
error:
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);
return err;
@ -1673,7 +1675,8 @@ static void deallocate_uars(struct mlx5_ib_dev *dev,
for (i = 0; i < bfregi->num_sys_pages; i++)
if (i < bfregi->num_static_sys_pages ||
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)
@ -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)
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_dyn = req.lib_caps & MLX5_LIB_CAP_DYN_UAR;
bfregi = &context->bfregi;
@ -1903,7 +1913,7 @@ static int mlx5_ib_alloc_ucontext(struct ib_ucontext *uctx,
/* updates req->total_num_bfregs */
err = calc_total_bfregs(dev, lib_uar_4k, &req, bfregi);
if (err)
goto out_ctx;
goto out_devx;
mutex_init(&bfregi->lock);
bfregi->lib_uar_4k = lib_uar_4k;
@ -1911,7 +1921,7 @@ static int mlx5_ib_alloc_ucontext(struct ib_ucontext *uctx,
GFP_KERNEL);
if (!bfregi->count) {
err = -ENOMEM;
goto out_ctx;
goto out_devx;
}
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;
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,
context->devx_uid);
if (err)
goto out_devx;
goto out_uars;
INIT_LIST_HEAD(&context->db_page_list);
mutex_init(&context->db_page_mutex);
@ -1972,9 +1975,6 @@ uar_done:
out_mdev:
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:
deallocate_uars(dev, context);
@ -1985,6 +1985,10 @@ out_sys_pages:
out_count:
kfree(bfregi->count);
out_devx:
if (req.flags & MLX5_IB_ALLOC_UCTX_DEVX)
mlx5_ib_devx_destroy(dev, context->devx_uid);
out_ctx:
return err;
}
@ -2021,12 +2025,12 @@ static void mlx5_ib_dealloc_ucontext(struct ib_ucontext *ibcontext)
bfregi = &context->bfregi;
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);
kfree(bfregi->sys_pages);
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,
@ -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_ib_dev *dev = to_mdev(entry->ucontext->device);
struct mlx5_var_table *var_table = &dev->var_table;
struct mlx5_ib_ucontext *context = to_mucontext(entry->ucontext);
switch (mentry->mmap_flag) {
case MLX5_IB_MMAP_TYPE_MEMIC:
@ -2133,7 +2138,8 @@ static void mlx5_ib_mmap_free(struct rdma_user_mmap_entry *entry)
break;
case MLX5_IB_MMAP_TYPE_UAR_WC:
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);
break;
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]++;
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) {
mlx5_ib_warn(dev, "UAR alloc failed\n");
goto free_bfreg;
@ -2240,7 +2247,7 @@ err:
if (!dyn_uar)
return err;
mlx5_cmd_free_uar(dev->mdev, idx);
mlx5_cmd_uar_dealloc(dev->mdev, idx, context->devx_uid);
free_bfreg:
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);
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)
goto end;
@ -3507,7 +3514,7 @@ alloc_uar_entry(struct mlx5_ib_ucontext *c,
return entry;
err_insert:
mlx5_cmd_free_uar(dev->mdev, uar_index);
mlx5_cmd_uar_dealloc(dev->mdev, uar_index, c->devx_uid);
end:
kfree(entry);
return ERR_PTR(err);

View File

@ -619,6 +619,20 @@ struct mlx5_user_mmap_entry {
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_DM_MEMIC_ALLOWED_ACCESS (IB_ACCESS_LOCAL_WRITE |\
@ -637,7 +651,7 @@ struct mlx5_user_mmap_entry {
struct mlx5_ib_mr {
struct ib_mr ibmr;
struct mlx5_core_mkey mmkey;
struct mlx5_ib_mkey mmkey;
/* User MR data */
struct mlx5_cache_ent *cache_ent;
@ -659,7 +673,6 @@ struct mlx5_ib_mr {
void *descs_alloc;
dma_addr_t desc_map;
int max_descs;
int ndescs;
int desc_size;
int access_mode;
@ -713,13 +726,7 @@ static inline bool is_dmabuf_mr(struct mlx5_ib_mr *mr)
struct mlx5_ib_mw {
struct ib_mw ibmw;
struct mlx5_core_mkey mmkey;
int ndescs;
};
struct mlx5_ib_devx_mr {
struct mlx5_core_mkey mmkey;
int ndescs;
struct mlx5_ib_mkey mmkey;
};
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,
struct mlx5_core_mkey *mmkey)
struct mlx5_ib_mkey *mmkey)
{
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 */
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))
wake_up(&mmkey->wait);
}
/* 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);
wait_event(mmkey->wait, refcount_read(&mmkey->usecount) == 0);

View File

@ -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);
}
static void
assign_mkey_variant(struct mlx5_ib_dev *dev, struct mlx5_core_mkey *mkey,
u32 *in)
static void assign_mkey_variant(struct mlx5_ib_dev *dev,
struct mlx5_ib_mkey *mkey, u32 *in)
{
u8 key = atomic_inc_return(&dev->mkey_var);
void *mkc;
@ -100,17 +99,22 @@ assign_mkey_variant(struct mlx5_ib_dev *dev, struct mlx5_core_mkey *mkey,
mkey->key = key;
}
static int
mlx5_ib_create_mkey(struct mlx5_ib_dev *dev, struct mlx5_core_mkey *mkey,
u32 *in, int inlen)
static int mlx5_ib_create_mkey(struct mlx5_ib_dev *dev,
struct mlx5_ib_mkey *mkey, u32 *in, int inlen)
{
int ret;
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
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,
u32 *in, int inlen, u32 *out, int outlen,
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)));
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)
@ -260,10 +264,11 @@ static struct mlx5_ib_mr *create_cache_mr(struct mlx5_cache_ent *ent)
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)
goto free_mr;
init_waitqueue_head(&mr->mmkey.wait);
mr->mmkey.type = MLX5_MKEY_MR;
WRITE_ONCE(ent->dev->cache.last_add, jiffies);
spin_lock_irq(&ent->lock);
@ -290,7 +295,7 @@ static void remove_cache_mr_locked(struct mlx5_cache_ent *ent)
ent->available_mrs--;
ent->total_mrs--;
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);
spin_lock_irq(&ent->lock);
}
@ -658,7 +663,7 @@ static void clean_keys(struct mlx5_ib_dev *dev, int c)
ent->available_mrs--;
ent->total_mrs--;
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) {
@ -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,
u64 length, int access_flags)
u64 length, int access_flags, u64 iova)
{
mr->ibmr.lkey = mr->mmkey.key;
mr->ibmr.rkey = mr->mmkey.key;
mr->ibmr.length = length;
mr->ibmr.device = &dev->ib_dev;
mr->ibmr.iova = iova;
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->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);
set_mr_fields(dev, mr, umem->length, access_flags);
set_mr_fields(dev, mr, umem->length, access_flags, iova);
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->pd = mr->ibmr.pd;
wr->mkey = mr->mmkey.key;
wr->length = mr->mmkey.size;
wr->virt_addr = mr->mmkey.iova;
wr->length = mr->ibmr.length;
wr->virt_addr = mr->ibmr.iova;
wr->access_flags = mr->access_flags;
wr->page_shift = mr->page_shift;
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->umem = umem;
set_mr_fields(dev, mr, umem->length, access_flags);
set_mr_fields(dev, mr, umem->length, access_flags, iova);
kvfree(in);
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);
set_mr_fields(dev, mr, length, acc);
set_mr_fields(dev, mr, length, acc, start_addr);
return &mr->ibmr;
@ -1709,7 +1712,6 @@ static int umr_rereg_pd_access(struct mlx5_ib_mr *mr, struct ib_pd *pd,
return err;
mr->access_flags = access_flags;
mr->mmkey.pd = to_mpd(pd)->pdn;
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) {
mr->ibmr.pd = pd;
mr->mmkey.pd = to_mpd(pd)->pdn;
upd_flags |= MLX5_IB_UPD_XLT_PD;
}
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->mmkey.iova = iova;
mr->mmkey.size = new_umem->length;
mr->ibmr.iova = iova;
mr->ibmr.length = new_umem->length;
mr->page_shift = order_base_2(page_size);
mr->umem = new_umem;
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;
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);
}
@ -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);
int inlen = MLX5_ST_SZ_BYTES(create_mkey_in);
struct mlx5_ib_mw *mw = to_mmw(ibmw);
unsigned int ndescs;
u32 *in = NULL;
void *mkc;
int ndescs;
int err;
struct mlx5_ib_alloc_mw req = {};
struct {
@ -2310,7 +2311,7 @@ int mlx5_ib_alloc_mw(struct ib_mw *ibmw, struct ib_udata *udata)
mw->mmkey.type = MLX5_MKEY_MW;
ibmw->rkey = mw->mmkey.key;
mw->ndescs = ndescs;
mw->mmkey.ndescs = ndescs;
resp.response_length =
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;
free_mkey:
mlx5_core_destroy_mkey(dev->mdev, &mw->mmkey);
mlx5_core_destroy_mkey(dev->mdev, mw->mmkey.key);
free:
kfree(in);
return err;
@ -2349,7 +2350,7 @@ int mlx5_ib_dealloc_mw(struct ib_mw *mw)
*/
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,
@ -2406,7 +2407,7 @@ mlx5_ib_map_pa_mr_sg_pi(struct ib_mr *ibmr, struct scatterlist *data_sg,
mr->meta_length = 0;
if (data_sg_nents == 1) {
n++;
mr->ndescs = 1;
mr->mmkey.ndescs = 1;
if (data_sg_offset)
sg_offset = *data_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)
*sg_offset_p = sg_offset;
mr->ndescs = i;
mr->mmkey.ndescs = i;
mr->data_length = mr->ibmr.length;
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);
__be64 *descs;
if (unlikely(mr->ndescs == mr->max_descs))
if (unlikely(mr->mmkey.ndescs == mr->max_descs))
return -ENOMEM;
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;
}
@ -2506,11 +2507,11 @@ static int mlx5_set_page_pi(struct ib_mr *ibmr, u64 addr)
struct mlx5_ib_mr *mr = to_mmr(ibmr);
__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;
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);
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;
int n;
pi_mr->ndescs = 0;
pi_mr->mmkey.ndescs = 0;
pi_mr->meta_ndescs = 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
*/
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);
/*
* 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;
int n;
pi_mr->ndescs = 0;
pi_mr->mmkey.ndescs = 0;
pi_mr->meta_ndescs = 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);
mr->ndescs = 0;
mr->mmkey.ndescs = 0;
mr->data_length = 0;
mr->data_iova = 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);
int n;
mr->ndescs = 0;
mr->mmkey.ndescs = 0;
ib_dma_sync_single_for_cpu(ibmr->device, mr->desc_map,
mr->desc_size * mr->max_descs,

View File

@ -430,7 +430,7 @@ static struct mlx5_ib_mr *implicit_get_child_mr(struct mlx5_ib_mr *imr,
mr->umem = &odp->umem;
mr->ibmr.lkey = 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;
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->mmkey.iova = 0;
imr->ibmr.iova = 0;
imr->umem = &umem_odp->umem;
imr->ibmr.lkey = 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);
if (unlikely(io_virt < mr->mmkey.iova))
if (unlikely(io_virt < mr->ibmr.iova))
return -EFAULT;
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) {
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))
return -EFAULT;
if (unlikely(user_va >= ib_umem_end(odp) ||
@ -788,7 +788,7 @@ struct pf_frame {
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)
return false;
@ -797,21 +797,6 @@ static bool mkey_is_eq(struct mlx5_core_mkey *mmkey, u32 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.
*
@ -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;
struct pf_frame *head = NULL, *frame;
struct mlx5_core_mkey *mmkey;
struct mlx5_ib_mkey *mmkey;
struct mlx5_ib_mr *mr;
struct mlx5_klm *pklm;
u32 *out = NULL;
size_t offset;
int ndescs;
io_virt += *bytes_committed;
bcnt -= *bytes_committed;
@ -885,8 +869,6 @@ next_mr:
case MLX5_MKEY_MW:
case MLX5_MKEY_INDIRECT_DEVX:
ndescs = get_indirect_num_descs(mmkey);
if (depth >= MLX5_CAP_GEN(dev->mdev, max_indirection)) {
mlx5_ib_dbg(dev, "indirection level exceeded\n");
ret = -EFAULT;
@ -894,7 +876,7 @@ next_mr:
}
outlen = MLX5_ST_SZ_BYTES(query_mkey_out) +
sizeof(*pklm) * (ndescs - 2);
sizeof(*pklm) * (mmkey->ndescs - 2);
if (outlen > cur_outlen) {
kfree(out);
@ -909,14 +891,14 @@ next_mr:
pklm = (struct mlx5_klm *)MLX5_ADDR_OF(query_mkey_out, out,
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)
goto end;
offset = io_virt - MLX5_GET64(query_mkey_out, out,
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)) {
offset -= be32_to_cpu(pklm->bcount);
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;
param = (struct mlx5_eq_param) {
.irq_index = MLX5_IRQ_EQ_CTRL,
.nent = MLX5_IB_NUM_PF_EQE,
};
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)
{
struct mlx5_ib_dev *dev = to_mdev(pd->device);
struct mlx5_core_mkey *mmkey;
struct mlx5_ib_mr *mr = NULL;
struct mlx5_ib_mkey *mmkey;
xa_lock(&dev->odp_mkeys);
mmkey = xa_load(&dev->odp_mkeys, mlx5_base_mkey(lkey));

View File

@ -217,7 +217,7 @@ static __be64 sig_mkey_mask(void)
static void set_reg_umr_seg(struct mlx5_wqe_umr_ctrl_seg *umr,
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));
@ -374,7 +374,7 @@ static void set_reg_mkey_seg(struct mlx5_mkey_seg *seg,
struct mlx5_ib_mr *mr,
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));
@ -439,7 +439,7 @@ static void set_reg_data_seg(struct mlx5_wqe_data_seg *dseg,
struct mlx5_ib_mr *mr,
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->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_pd *pd = to_mpd(qp->ibqp.pd);
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 atomic = wr->access & IB_ACCESS_REMOTE_ATOMIC;
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));
/* No UMR, use 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_iova = mr->data_iova;
if (mr->meta_ndescs) {

View File

@ -272,7 +272,7 @@ static int qedr_register_device(struct qedr_dev *dev)
static int qedr_alloc_mem_sb(struct qedr_dev *dev,
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;
int rc;

View File

@ -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,
struct dmx_section_filter **secfilter,
u8 *mac, u8 *mac_mask)
const u8 *mac, u8 *mac_mask)
{
struct dvb_net_priv *priv = netdev_priv(dev);
int ret;
@ -1052,7 +1052,7 @@ static int dvb_net_feed_start(struct net_device *dev)
int ret = 0, i;
struct dvb_net_priv *priv = netdev_priv(dev);
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);
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 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))
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);
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;

View File

@ -1350,7 +1350,7 @@ mpt_register_lan_device (MPT_ADAPTER *mpt_dev, int pnum)
HWaddr[5] = a[0];
dev->addr_len = FC_ALEN;
memcpy(dev->dev_addr, HWaddr, FC_ALEN);
dev_addr_set(dev, HWaddr);
memset(dev->broadcast, 0xff, FC_ALEN);
/* 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