Networking changes for 6.0.

Core
 ----
 
  - Refactor the forward memory allocation to better cope with memory
    pressure with many open sockets, moving from a per socket cache to
    a per-CPU one
 
  - Replace rwlocks with RCU for better fairness in ping, raw sockets
    and IP multicast router.
 
  - Network-side support for IO uring zero-copy send.
 
  - A few skb drop reason improvements, including codegen the source file
    with string mapping instead of using macro magic.
 
  - Rename reference tracking helpers to a more consistent
    netdev_* schema.
 
  - Adapt u64_stats_t type to address load/store tearing issues.
 
  - Refine debug helper usage to reduce the log noise caused by bots.
 
 BPF
 ---
  - Improve socket map performance, avoiding skb cloning on read
    operation.
 
  - Add support for 64 bits enum, to match types exposed by kernel.
 
  - Introduce support for sleepable uprobes program.
 
  - Introduce support for enum textual representation in libbpf.
 
  - New helpers to implement synproxy with eBPF/XDP.
 
  - Improve loop performances, inlining indirect calls when
    possible.
 
  - Removed all the deprecated libbpf APIs.
 
  - Implement new eBPF-based LSM flavor.
 
  - Add type match support, which allow accurate queries to the
    eBPF used types.
 
  - A few TCP congetsion control framework usability improvements.
 
  - Add new infrastructure to manipulate CT entries via eBPF programs.
 
  - Allow for livepatch (KLP) and BPF trampolines to attach to the same
    kernel function.
 
 Protocols
 ---------
 
  - Introduce per network namespace lookup tables for unix sockets,
    increasing scalability and reducing contention.
 
  - Preparation work for Wi-Fi 7 Multi-Link Operation (MLO) support.
 
  - Add support to forciby close TIME_WAIT TCP sockets via user-space
    tools.
 
  - Significant performance improvement for the TLS 1.3 receive path,
    both for zero-copy and not-zero-copy.
 
  - Support for changing the initial MTPCP subflow priority/backup
    status
 
  - Introduce virtually contingus buffers for sockets over RDMA,
    to cope better with memory pressure.
 
  - Extend CAN ethtool support with timestamping capabilities
 
  - Refactor CAN build infrastructure to allow building only the needed
    features.
 
 Driver API
 ----------
 
  - Remove devlink mutex to allow parallel commands on multiple links.
 
  - Add support for pause stats in distributed switch.
 
  - Implement devlink helpers to query and flash line cards.
 
  - New helper for phy mode to register conversion.
 
 New hardware / drivers
 ----------------------
 
  - Ethernet DSA driver for the rockchip mt7531 on BPI-R2 Pro.
 
  - Ethernet DSA driver for the Renesas RZ/N1 A5PSW switch.
 
  - Ethernet DSA driver for the Microchip LAN937x switch.
 
  - Ethernet PHY driver for the Aquantia AQR113C EPHY.
 
  - CAN driver for the OBD-II ELM327 interface.
 
  - CAN driver for RZ/N1 SJA1000 CAN controller.
 
  - Bluetooth: Infineon CYW55572 Wi-Fi plus Bluetooth combo device.
 
 Drivers
 -------
 
  - Intel Ethernet NICs:
    - i40e: add support for vlan pruning
    - i40e: add support for XDP framented packets
    - ice: improved vlan offload support
    - ice: add support for PPPoE offload
 
  - Mellanox Ethernet (mlx5)
    - refactor packet steering offload for performance and scalability
    - extend support for TC offload
    - refactor devlink code to clean-up the locking schema
    - support stacked vlans for bridge offloads
    - use TLS objects pool to improve connection rate
 
  - Netronome Ethernet NICs (nfp):
    - extend support for IPv6 fields mangling offload
    - add support for vepa mode in HW bridge
    - better support for virtio data path acceleration (VDPA)
    - enable TSO by default
 
  - Microsoft vNIC driver (mana)
    - add support for XDP redirect
 
  - Others Ethernet drivers:
    - bonding: add per-port priority support
    - microchip lan743x: extend phy support
    - Fungible funeth: support UDP segmentation offload and XDP xmit
    - Solarflare EF100: add support for virtual function representors
    - MediaTek SoC: add XDP support
 
  - Mellanox Ethernet/IB switch (mlxsw):
    - dropped support for unreleased H/W (XM router).
    - improved stats accuracy
    - unified bridge model coversion improving scalability
      (parts 1-6)
    - support for PTP in Spectrum-2 asics
 
  - Broadcom PHYs
    - add PTP support for BCM54210E
    - add support for the BCM53128 internal PHY
 
  - Marvell Ethernet switches (prestera):
    - implement support for multicast forwarding offload
 
  - Embedded Ethernet switches:
    - refactor OcteonTx MAC filter for better scalability
    - improve TC H/W offload for the Felix driver
    - refactor the Microchip ksz8 and ksz9477 drivers to share
      the probe code (parts 1, 2), add support for phylink
      mac configuration
 
  - Other WiFi:
    - Microchip wilc1000: diable WEP support and enable WPA3
    - Atheros ath10k: encapsulation offload support
 
 Old code removal:
 
  - Neterion vxge ethernet driver: this is untouched since more than
    10 years.
 
 Signed-off-by: Paolo Abeni <pabeni@redhat.com>
 -----BEGIN PGP SIGNATURE-----
 
 iQJGBAABCAAwFiEEg1AjqC77wbdLX2LbKSR5jcyPE6QFAmLqN+oSHHBhYmVuaUBy
 ZWRoYXQuY29tAAoJECkkeY3MjxOkB9kQAI9VqW0c3SfiTJnkVBEIovZ6Tnh5stD2
 UYFkh1BdchLsYxi7W4XMpVPSzRztiTP87mIx5c/KvIzj+QNeWL1XWRJSPdI9HhTD
 pTAA/tM2OG7bqrbyQiKDNfpQdNl7+kk1RwnYd+f9RFl1QVuIJaYhmjVwrsN5xF/+
 jUsotpROarM2dGFWiFwJbKhP2zMDT+6qEEahM8pEPggKhv8wRLYjany2cZVEe4e0
 WGUpbINAS8gEKm0Ob922WaDfDrcK/N1Z0jNz/kMaENkK18Vvc7F6bCO0DzAawKX9
 QZMMwm6mHp3EThflJAMAzCGIYiIcwLhykgdyj8rrjPhFrWbMD2Sdsbo21HOXU/8j
 u4aAhVl+d+h7emmbgBoJ8sycVJ7BQlXz7lX20sTgADv9xI4/dPhQ17CMRuwX6fXX
 JSrn6P6e1LTV5CEg6vrlSPnKPY6uhFn/cPw47FxCjRwJ9phVnp+8uZWQmf9Pz3yf
 Ok/tcj+juFbsmuOshHy2cbRkuNZNS0oRWlSTBo5795ZwOLSakMonR3L+ev2aOvzz
 DVrFp2Y/iIVwMSFdCbouYdYnhArPRhOAtCmZc2afY8aBN7aaMgrdTy3+mzUoHy3I
 FG3K+VuKpfi0vY4zn6ZoLZDIpyXIoJJ93RcSGltD32t3Dp1RaQMVEI4s45k05PVm
 1nYpXKHA8qML
 =hxEG
 -----END PGP SIGNATURE-----

Merge tag 'net-next-6.0' of git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-next

Pull networking changes from Paolo Abeni:
 "Core:

   - Refactor the forward memory allocation to better cope with memory
     pressure with many open sockets, moving from a per socket cache to
     a per-CPU one

   - Replace rwlocks with RCU for better fairness in ping, raw sockets
     and IP multicast router.

   - Network-side support for IO uring zero-copy send.

   - A few skb drop reason improvements, including codegen the source
     file with string mapping instead of using macro magic.

   - Rename reference tracking helpers to a more consistent netdev_*
     schema.

   - Adapt u64_stats_t type to address load/store tearing issues.

   - Refine debug helper usage to reduce the log noise caused by bots.

  BPF:

   - Improve socket map performance, avoiding skb cloning on read
     operation.

   - Add support for 64 bits enum, to match types exposed by kernel.

   - Introduce support for sleepable uprobes program.

   - Introduce support for enum textual representation in libbpf.

   - New helpers to implement synproxy with eBPF/XDP.

   - Improve loop performances, inlining indirect calls when possible.

   - Removed all the deprecated libbpf APIs.

   - Implement new eBPF-based LSM flavor.

   - Add type match support, which allow accurate queries to the eBPF
     used types.

   - A few TCP congetsion control framework usability improvements.

   - Add new infrastructure to manipulate CT entries via eBPF programs.

   - Allow for livepatch (KLP) and BPF trampolines to attach to the same
     kernel function.

  Protocols:

   - Introduce per network namespace lookup tables for unix sockets,
     increasing scalability and reducing contention.

   - Preparation work for Wi-Fi 7 Multi-Link Operation (MLO) support.

   - Add support to forciby close TIME_WAIT TCP sockets via user-space
     tools.

   - Significant performance improvement for the TLS 1.3 receive path,
     both for zero-copy and not-zero-copy.

   - Support for changing the initial MTPCP subflow priority/backup
     status

   - Introduce virtually contingus buffers for sockets over RDMA, to
     cope better with memory pressure.

   - Extend CAN ethtool support with timestamping capabilities

   - Refactor CAN build infrastructure to allow building only the needed
     features.

  Driver API:

   - Remove devlink mutex to allow parallel commands on multiple links.

   - Add support for pause stats in distributed switch.

   - Implement devlink helpers to query and flash line cards.

   - New helper for phy mode to register conversion.

  New hardware / drivers:

   - Ethernet DSA driver for the rockchip mt7531 on BPI-R2 Pro.

   - Ethernet DSA driver for the Renesas RZ/N1 A5PSW switch.

   - Ethernet DSA driver for the Microchip LAN937x switch.

   - Ethernet PHY driver for the Aquantia AQR113C EPHY.

   - CAN driver for the OBD-II ELM327 interface.

   - CAN driver for RZ/N1 SJA1000 CAN controller.

   - Bluetooth: Infineon CYW55572 Wi-Fi plus Bluetooth combo device.

  Drivers:

   - Intel Ethernet NICs:
      - i40e: add support for vlan pruning
      - i40e: add support for XDP framented packets
      - ice: improved vlan offload support
      - ice: add support for PPPoE offload

   - Mellanox Ethernet (mlx5)
      - refactor packet steering offload for performance and scalability
      - extend support for TC offload
      - refactor devlink code to clean-up the locking schema
      - support stacked vlans for bridge offloads
      - use TLS objects pool to improve connection rate

   - Netronome Ethernet NICs (nfp):
      - extend support for IPv6 fields mangling offload
      - add support for vepa mode in HW bridge
      - better support for virtio data path acceleration (VDPA)
      - enable TSO by default

   - Microsoft vNIC driver (mana)
      - add support for XDP redirect

   - Others Ethernet drivers:
      - bonding: add per-port priority support
      - microchip lan743x: extend phy support
      - Fungible funeth: support UDP segmentation offload and XDP xmit
      - Solarflare EF100: add support for virtual function representors
      - MediaTek SoC: add XDP support

   - Mellanox Ethernet/IB switch (mlxsw):
      - dropped support for unreleased H/W (XM router).
      - improved stats accuracy
      - unified bridge model coversion improving scalability (parts 1-6)
      - support for PTP in Spectrum-2 asics

   - Broadcom PHYs
      - add PTP support for BCM54210E
      - add support for the BCM53128 internal PHY

   - Marvell Ethernet switches (prestera):
      - implement support for multicast forwarding offload

   - Embedded Ethernet switches:
      - refactor OcteonTx MAC filter for better scalability
      - improve TC H/W offload for the Felix driver
      - refactor the Microchip ksz8 and ksz9477 drivers to share the
        probe code (parts 1, 2), add support for phylink mac
        configuration

   - Other WiFi:
      - Microchip wilc1000: diable WEP support and enable WPA3
      - Atheros ath10k: encapsulation offload support

  Old code removal:

   - Neterion vxge ethernet driver: this is untouched since more than 10 years"

* tag 'net-next-6.0' of git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-next: (1890 commits)
  doc: sfp-phylink: Fix a broken reference
  wireguard: selftests: support UML
  wireguard: allowedips: don't corrupt stack when detecting overflow
  wireguard: selftests: update config fragments
  wireguard: ratelimiter: use hrtimer in selftest
  net/mlx5e: xsk: Discard unaligned XSK frames on striding RQ
  net: usb: ax88179_178a: Bind only to vendor-specific interface
  selftests: net: fix IOAM test skip return code
  net: usb: make USB_RTL8153_ECM non user configurable
  net: marvell: prestera: remove reduntant code
  octeontx2-pf: Reduce minimum mtu size to 60
  net: devlink: Fix missing mutex_unlock() call
  net/tls: Remove redundant workqueue flush before destroy
  net: txgbe: Fix an error handling path in txgbe_probe()
  net: dsa: Fix spelling mistakes and cleanup code
  Documentation: devlink: add add devlink-selftests to the table of contents
  dccp: put dccp_qpolicy_full() and dccp_qpolicy_push() in the same lock
  net: ionic: fix error check for vlan flags in ionic_set_nic_features()
  net: ice: fix error NETIF_F_HW_VLAN_CTAG_FILTER check in ice_vsi_sync_fltr()
  nfp: flower: add support for tunnel offload without key ID
  ...
This commit is contained in:
Linus Torvalds 2022-08-03 16:29:08 -07:00
commit f86d1fbbe7
1753 changed files with 93378 additions and 64340 deletions

View File

@ -46,33 +46,69 @@ Description:
that is supported by the hardware. The possible values
are "MAPv4" or "MAPv5".
What: .../XXXXXXX.ipa/endpoint_id/
Date: July 2022
KernelVersion: v5.19
Contact: Alex Elder <elder@kernel.org>
Description:
The .../XXXXXXX.ipa/endpoint_id/ directory contains
attributes that define IDs associated with IPA
endpoints. The "rx" or "tx" in an endpoint name is
from the perspective of the AP. An endpoint ID is a
small unsigned integer.
What: .../XXXXXXX.ipa/endpoint_id/modem_rx
Date: July 2022
KernelVersion: v5.19
Contact: Alex Elder <elder@kernel.org>
Description:
The .../XXXXXXX.ipa/endpoint_id/modem_rx file contains
the ID of the AP endpoint on which packets originating
from the embedded modem are received.
What: .../XXXXXXX.ipa/endpoint_id/modem_tx
Date: July 2022
KernelVersion: v5.19
Contact: Alex Elder <elder@kernel.org>
Description:
The .../XXXXXXX.ipa/endpoint_id/modem_tx file contains
the ID of the AP endpoint on which packets destined
for the embedded modem are sent.
What: .../XXXXXXX.ipa/endpoint_id/monitor_rx
Date: July 2022
KernelVersion: v5.19
Contact: Alex Elder <elder@kernel.org>
Description:
The .../XXXXXXX.ipa/endpoint_id/monitor_rx file contains
the ID of the AP endpoint on which IPA "monitor" data is
received. The monitor endpoint supplies replicas of
packets that enter the IPA hardware for processing.
Each replicated packet is preceded by a fixed-size "ODL"
header (see .../XXXXXXX.ipa/feature/monitor, above).
Large packets are truncated, to reduce the bandwidth
required to provide the monitor function.
What: .../XXXXXXX.ipa/modem/
Date: June 2021
KernelVersion: v5.14
Contact: Alex Elder <elder@kernel.org>
Description:
The .../XXXXXXX.ipa/modem/ directory contains a set of
attributes describing properties of the modem execution
environment reachable by the IPA hardware.
The .../XXXXXXX.ipa/modem/ directory contains attributes
describing properties of the modem embedded in the SoC.
What: .../XXXXXXX.ipa/modem/rx_endpoint_id
Date: June 2021
KernelVersion: v5.14
Contact: Alex Elder <elder@kernel.org>
Description:
The .../XXXXXXX.ipa/feature/rx_endpoint_id file contains
the AP endpoint ID that receives packets originating from
the modem execution environment. The "rx" is from the
perspective of the AP; this endpoint is considered an "IPA
producer". An endpoint ID is a small unsigned integer.
The .../XXXXXXX.ipa/modem/rx_endpoint_id file duplicates
the value found in .../XXXXXXX.ipa/endpoint_id/modem_rx.
What: .../XXXXXXX.ipa/modem/tx_endpoint_id
Date: June 2021
KernelVersion: v5.14
Contact: Alex Elder <elder@kernel.org>
Description:
The .../XXXXXXX.ipa/feature/tx_endpoint_id file contains
the AP endpoint ID used to transmit packets destined for
the modem execution environment. The "tx" is from the
perspective of the AP; this endpoint is considered an "IPA
consumer". An endpoint ID is a small unsigned integer.
The .../XXXXXXX.ipa/modem/tx_endpoint_id file duplicates
the value found in .../XXXXXXX.ipa/endpoint_id/modem_tx.

View File

@ -391,6 +391,18 @@ GRO has decided not to coalesce, it is placed on a per-NAPI list. This
list is then passed to the stack when the number of segments reaches the
gro_normal_batch limit.
high_order_alloc_disable
------------------------
By default the allocator for page frags tries to use high order pages (order-3
on x86). While the default behavior gives good results in most cases, some users
might have hit a contention in page allocations/freeing. This was especially
true on older kernels (< 5.14) when high-order pages were not stored on per-cpu
lists. This allows to opt-in for order-0 allocation instead but is now mostly of
historical importance.
Default: 0
2. /proc/sys/net/unix - Parameters for Unix domain sockets
----------------------------------------------------------

View File

@ -74,7 +74,7 @@ sequentially and type id is assigned to each recognized type starting from id
#define BTF_KIND_ARRAY 3 /* Array */
#define BTF_KIND_STRUCT 4 /* Struct */
#define BTF_KIND_UNION 5 /* Union */
#define BTF_KIND_ENUM 6 /* Enumeration */
#define BTF_KIND_ENUM 6 /* Enumeration up to 32-bit values */
#define BTF_KIND_FWD 7 /* Forward */
#define BTF_KIND_TYPEDEF 8 /* Typedef */
#define BTF_KIND_VOLATILE 9 /* Volatile */
@ -87,6 +87,7 @@ sequentially and type id is assigned to each recognized type starting from id
#define BTF_KIND_FLOAT 16 /* Floating point */
#define BTF_KIND_DECL_TAG 17 /* Decl Tag */
#define BTF_KIND_TYPE_TAG 18 /* Type Tag */
#define BTF_KIND_ENUM64 19 /* Enumeration up to 64-bit values */
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.
@ -101,10 +102,10 @@ Each type contains the following common data::
* bits 24-28: kind (e.g. int, ptr, array...etc)
* bits 29-30: unused
* bit 31: kind_flag, currently used by
* struct, union and fwd
* struct, union, fwd, enum and enum64.
*/
__u32 info;
/* "size" is used by INT, ENUM, STRUCT and UNION.
/* "size" is used by INT, ENUM, STRUCT, UNION and ENUM64.
* "size" tells the size of the type it is describing.
*
* "type" is used by PTR, TYPEDEF, VOLATILE, CONST, RESTRICT,
@ -281,10 +282,10 @@ modes exist:
``struct btf_type`` encoding requirement:
* ``name_off``: 0 or offset to a valid C identifier
* ``info.kind_flag``: 0
* ``info.kind_flag``: 0 for unsigned, 1 for signed
* ``info.kind``: BTF_KIND_ENUM
* ``info.vlen``: number of enum values
* ``size``: 4
* ``size``: 1/2/4/8
``btf_type`` is followed by ``info.vlen`` number of ``struct btf_enum``.::
@ -297,6 +298,10 @@ The ``btf_enum`` encoding:
* ``name_off``: offset to a valid C identifier
* ``val``: any value
If the original enum value is signed and the size is less than 4,
that value will be sign extended into 4 bytes. If the size is 8,
the value will be truncated into 4 bytes.
2.2.7 BTF_KIND_FWD
~~~~~~~~~~~~~~~~~~
@ -364,7 +369,8 @@ No additional type data follow ``btf_type``.
* ``name_off``: offset to a valid C identifier
* ``info.kind_flag``: 0
* ``info.kind``: BTF_KIND_FUNC
* ``info.vlen``: 0
* ``info.vlen``: linkage information (BTF_FUNC_STATIC, BTF_FUNC_GLOBAL
or BTF_FUNC_EXTERN)
* ``type``: a BTF_KIND_FUNC_PROTO type
No additional type data follow ``btf_type``.
@ -375,6 +381,9 @@ type. The BTF_KIND_FUNC may in turn be referenced by a func_info in the
:ref:`BTF_Ext_Section` (ELF) or in the arguments to :ref:`BPF_Prog_Load`
(ABI).
Currently, only linkage values of BTF_FUNC_STATIC and BTF_FUNC_GLOBAL are
supported in the kernel.
2.2.13 BTF_KIND_FUNC_PROTO
~~~~~~~~~~~~~~~~~~~~~~~~~~
@ -493,7 +502,7 @@ 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.
2.2.17 BTF_KIND_TYPE_TAG
2.2.18 BTF_KIND_TYPE_TAG
~~~~~~~~~~~~~~~~~~~~~~~~
``struct btf_type`` encoding requirement:
@ -516,6 +525,32 @@ type_tag, then zero or more const/volatile/restrict/typedef
and finally the base type. The base type is one of
int, ptr, array, struct, union, enum, func_proto and float types.
2.2.19 BTF_KIND_ENUM64
~~~~~~~~~~~~~~~~~~~~~~
``struct btf_type`` encoding requirement:
* ``name_off``: 0 or offset to a valid C identifier
* ``info.kind_flag``: 0 for unsigned, 1 for signed
* ``info.kind``: BTF_KIND_ENUM64
* ``info.vlen``: number of enum values
* ``size``: 1/2/4/8
``btf_type`` is followed by ``info.vlen`` number of ``struct btf_enum64``.::
struct btf_enum64 {
__u32 name_off;
__u32 val_lo32;
__u32 val_hi32;
};
The ``btf_enum64`` encoding:
* ``name_off``: offset to a valid C identifier
* ``val_lo32``: lower 32-bit value for a 64-bit value
* ``val_hi32``: high 32-bit value for a 64-bit value
If the original enum value is signed and the size is less than 8,
that value will be sign extended into 8 bytes.
3. BTF Kernel API
=================

View File

@ -19,6 +19,7 @@ that goes into great technical depth about the BPF Architecture.
faq
syscall_api
helpers
kfuncs
programs
maps
bpf_prog_run

View File

@ -127,7 +127,7 @@ BPF_XOR | BPF_K | BPF_ALU64 means::
Byte swap instructions
----------------------
The byte swap instructions use an instruction class of ``BFP_ALU`` and a 4-bit
The byte swap instructions use an instruction class of ``BPF_ALU`` and a 4-bit
code field of ``BPF_END``.
The byte swap instructions operate on the destination register
@ -351,7 +351,7 @@ These instructions have seven implicit operands:
* Register R0 is an implicit output which contains the data fetched from
the packet.
* Registers R1-R5 are scratch registers that are clobbered after a call to
``BPF_ABS | BPF_LD`` or ``BPF_IND`` | BPF_LD instructions.
``BPF_ABS | BPF_LD`` or ``BPF_IND | BPF_LD`` instructions.
These instructions have an implicit program exit condition as well. When an
eBPF program is trying to access the data beyond the packet boundary, the

View File

@ -0,0 +1,170 @@
=============================
BPF Kernel Functions (kfuncs)
=============================
1. Introduction
===============
BPF Kernel Functions or more commonly known as kfuncs are functions in the Linux
kernel which are exposed for use by BPF programs. Unlike normal BPF helpers,
kfuncs do not have a stable interface and can change from one kernel release to
another. Hence, BPF programs need to be updated in response to changes in the
kernel.
2. Defining a kfunc
===================
There are two ways to expose a kernel function to BPF programs, either make an
existing function in the kernel visible, or add a new wrapper for BPF. In both
cases, care must be taken that BPF program can only call such function in a
valid context. To enforce this, visibility of a kfunc can be per program type.
If you are not creating a BPF wrapper for existing kernel function, skip ahead
to :ref:`BPF_kfunc_nodef`.
2.1 Creating a wrapper kfunc
----------------------------
When defining a wrapper kfunc, the wrapper function should have extern linkage.
This prevents the compiler from optimizing away dead code, as this wrapper kfunc
is not invoked anywhere in the kernel itself. It is not necessary to provide a
prototype in a header for the wrapper kfunc.
An example is given below::
/* Disables missing prototype warnings */
__diag_push();
__diag_ignore_all("-Wmissing-prototypes",
"Global kfuncs as their definitions will be in BTF");
struct task_struct *bpf_find_get_task_by_vpid(pid_t nr)
{
return find_get_task_by_vpid(nr);
}
__diag_pop();
A wrapper kfunc is often needed when we need to annotate parameters of the
kfunc. Otherwise one may directly make the kfunc visible to the BPF program by
registering it with the BPF subsystem. See :ref:`BPF_kfunc_nodef`.
2.2 Annotating kfunc parameters
-------------------------------
Similar to BPF helpers, there is sometime need for additional context required
by the verifier to make the usage of kernel functions safer and more useful.
Hence, we can annotate a parameter by suffixing the name of the argument of the
kfunc with a __tag, where tag may be one of the supported annotations.
2.2.1 __sz Annotation
---------------------
This annotation is used to indicate a memory and size pair in the argument list.
An example is given below::
void bpf_memzero(void *mem, int mem__sz)
{
...
}
Here, the verifier will treat first argument as a PTR_TO_MEM, and second
argument as its size. By default, without __sz annotation, the size of the type
of the pointer is used. Without __sz annotation, a kfunc cannot accept a void
pointer.
.. _BPF_kfunc_nodef:
2.3 Using an existing kernel function
-------------------------------------
When an existing function in the kernel is fit for consumption by BPF programs,
it can be directly registered with the BPF subsystem. However, care must still
be taken to review the context in which it will be invoked by the BPF program
and whether it is safe to do so.
2.4 Annotating kfuncs
---------------------
In addition to kfuncs' arguments, verifier may need more information about the
type of kfunc(s) being registered with the BPF subsystem. To do so, we define
flags on a set of kfuncs as follows::
BTF_SET8_START(bpf_task_set)
BTF_ID_FLAGS(func, bpf_get_task_pid, KF_ACQUIRE | KF_RET_NULL)
BTF_ID_FLAGS(func, bpf_put_pid, KF_RELEASE)
BTF_SET8_END(bpf_task_set)
This set encodes the BTF ID of each kfunc listed above, and encodes the flags
along with it. Ofcourse, it is also allowed to specify no flags.
2.4.1 KF_ACQUIRE flag
---------------------
The KF_ACQUIRE flag is used to indicate that the kfunc returns a pointer to a
refcounted object. The verifier will then ensure that the pointer to the object
is eventually released using a release kfunc, or transferred to a map using a
referenced kptr (by invoking bpf_kptr_xchg). If not, the verifier fails the
loading of the BPF program until no lingering references remain in all possible
explored states of the program.
2.4.2 KF_RET_NULL flag
----------------------
The KF_RET_NULL flag is used to indicate that the pointer returned by the kfunc
may be NULL. Hence, it forces the user to do a NULL check on the pointer
returned from the kfunc before making use of it (dereferencing or passing to
another helper). This flag is often used in pairing with KF_ACQUIRE flag, but
both are orthogonal to each other.
2.4.3 KF_RELEASE flag
---------------------
The KF_RELEASE flag is used to indicate that the kfunc releases the pointer
passed in to it. There can be only one referenced pointer that can be passed in.
All copies of the pointer being released are invalidated as a result of invoking
kfunc with this flag.
2.4.4 KF_KPTR_GET flag
----------------------
The KF_KPTR_GET flag is used to indicate that the kfunc takes the first argument
as a pointer to kptr, safely increments the refcount of the object it points to,
and returns a reference to the user. The rest of the arguments may be normal
arguments of a kfunc. The KF_KPTR_GET flag should be used in conjunction with
KF_ACQUIRE and KF_RET_NULL flags.
2.4.5 KF_TRUSTED_ARGS flag
--------------------------
The KF_TRUSTED_ARGS flag is used for kfuncs taking pointer arguments. It
indicates that the all pointer arguments will always be refcounted, and have
their offset set to 0. It can be used to enforce that a pointer to a refcounted
object acquired from a kfunc or BPF helper is passed as an argument to this
kfunc without any modifications (e.g. pointer arithmetic) such that it is
trusted and points to the original object. This flag is often used for kfuncs
that operate (change some property, perform some operation) on an object that
was obtained using an acquire kfunc. Such kfuncs need an unchanged pointer to
ensure the integrity of the operation being performed on the expected object.
2.5 Registering the kfuncs
--------------------------
Once the kfunc is prepared for use, the final step to making it visible is
registering it with the BPF subsystem. Registration is done per BPF program
type. An example is shown below::
BTF_SET8_START(bpf_task_set)
BTF_ID_FLAGS(func, bpf_get_task_pid, KF_ACQUIRE | KF_RET_NULL)
BTF_ID_FLAGS(func, bpf_put_pid, KF_RELEASE)
BTF_SET8_END(bpf_task_set)
static const struct btf_kfunc_id_set bpf_task_kfunc_set = {
.owner = THIS_MODULE,
.set = &bpf_task_set,
};
static int init_subsystem(void)
{
return register_btf_kfunc_id_set(BPF_PROG_TYPE_TRACING, &bpf_task_kfunc_set);
}
late_initcall(init_subsystem);

View File

@ -9,8 +9,8 @@ described here. It's recommended to follow these conventions whenever a
new function or type is added to keep libbpf API clean and consistent.
All types and functions provided by libbpf API should have one of the
following prefixes: ``bpf_``, ``btf_``, ``libbpf_``, ``xsk_``,
``btf_dump_``, ``ring_buffer_``, ``perf_buffer_``.
following prefixes: ``bpf_``, ``btf_``, ``libbpf_``, ``btf_dump_``,
``ring_buffer_``, ``perf_buffer_``.
System call wrappers
--------------------
@ -59,15 +59,6 @@ Auxiliary functions and types that don't fit well in any of categories
described above should have ``libbpf_`` prefix, e.g.
``libbpf_get_error`` or ``libbpf_prog_type_by_name``.
AF_XDP functions
-------------------
AF_XDP functions should have an ``xsk_`` prefix, e.g.
``xsk_umem__get_data`` or ``xsk_umem__create``. The interface consists
of both low-level ring access functions and high-level configuration
functions. These can be mixed and matched. Note that these functions
are not reentrant for performance reasons.
ABI
---

View File

@ -0,0 +1,185 @@
.. SPDX-License-Identifier: GPL-2.0-only
.. Copyright (C) 2022 Red Hat, Inc.
===============================================
BPF_MAP_TYPE_HASH, with PERCPU and LRU Variants
===============================================
.. note::
- ``BPF_MAP_TYPE_HASH`` was introduced in kernel version 3.19
- ``BPF_MAP_TYPE_PERCPU_HASH`` was introduced in version 4.6
- Both ``BPF_MAP_TYPE_LRU_HASH`` and ``BPF_MAP_TYPE_LRU_PERCPU_HASH``
were introduced in version 4.10
``BPF_MAP_TYPE_HASH`` and ``BPF_MAP_TYPE_PERCPU_HASH`` provide general
purpose hash map storage. Both the key and the value can be structs,
allowing for composite keys and values.
The kernel is responsible for allocating and freeing key/value pairs, up
to the max_entries limit that you specify. Hash maps use pre-allocation
of hash table elements by default. The ``BPF_F_NO_PREALLOC`` flag can be
used to disable pre-allocation when it is too memory expensive.
``BPF_MAP_TYPE_PERCPU_HASH`` provides a separate value slot per
CPU. The per-cpu values are stored internally in an array.
The ``BPF_MAP_TYPE_LRU_HASH`` and ``BPF_MAP_TYPE_LRU_PERCPU_HASH``
variants add LRU semantics to their respective hash tables. An LRU hash
will automatically evict the least recently used entries when the hash
table reaches capacity. An LRU hash maintains an internal LRU list that
is used to select elements for eviction. This internal LRU list is
shared across CPUs but it is possible to request a per CPU LRU list with
the ``BPF_F_NO_COMMON_LRU`` flag when calling ``bpf_map_create``.
Usage
=====
.. c:function::
long bpf_map_update_elem(struct bpf_map *map, const void *key, const void *value, u64 flags)
Hash entries can be added or updated using the ``bpf_map_update_elem()``
helper. This helper replaces existing elements atomically. The ``flags``
parameter can be used to control the update behaviour:
- ``BPF_ANY`` will create a new element or update an existing element
- ``BPF_NOEXIST`` will create a new element only if one did not already
exist
- ``BPF_EXIST`` will update an existing element
``bpf_map_update_elem()`` returns 0 on success, or negative error in
case of failure.
.. c:function::
void *bpf_map_lookup_elem(struct bpf_map *map, const void *key)
Hash entries can be retrieved using the ``bpf_map_lookup_elem()``
helper. This helper returns a pointer to the value associated with
``key``, or ``NULL`` if no entry was found.
.. c:function::
long bpf_map_delete_elem(struct bpf_map *map, const void *key)
Hash entries can be deleted using the ``bpf_map_delete_elem()``
helper. This helper will return 0 on success, or negative error in case
of failure.
Per CPU Hashes
--------------
For ``BPF_MAP_TYPE_PERCPU_HASH`` and ``BPF_MAP_TYPE_LRU_PERCPU_HASH``
the ``bpf_map_update_elem()`` and ``bpf_map_lookup_elem()`` helpers
automatically access the hash slot for the current CPU.
.. c:function::
void *bpf_map_lookup_percpu_elem(struct bpf_map *map, const void *key, u32 cpu)
The ``bpf_map_lookup_percpu_elem()`` helper can be used to lookup the
value in the hash slot for a specific CPU. Returns value associated with
``key`` on ``cpu`` , or ``NULL`` if no entry was found or ``cpu`` is
invalid.
Concurrency
-----------
Values stored in ``BPF_MAP_TYPE_HASH`` can be accessed concurrently by
programs running on different CPUs. Since Kernel version 5.1, the BPF
infrastructure provides ``struct bpf_spin_lock`` to synchronise access.
See ``tools/testing/selftests/bpf/progs/test_spin_lock.c``.
Userspace
---------
.. c:function::
int bpf_map_get_next_key(int fd, const void *cur_key, void *next_key)
In userspace, it is possible to iterate through the keys of a hash using
libbpf's ``bpf_map_get_next_key()`` function. The first key can be fetched by
calling ``bpf_map_get_next_key()`` with ``cur_key`` set to
``NULL``. Subsequent calls will fetch the next key that follows the
current key. ``bpf_map_get_next_key()`` returns 0 on success, -ENOENT if
cur_key is the last key in the hash, or negative error in case of
failure.
Note that if ``cur_key`` gets deleted then ``bpf_map_get_next_key()``
will instead return the *first* key in the hash table which is
undesirable. It is recommended to use batched lookup if there is going
to be key deletion intermixed with ``bpf_map_get_next_key()``.
Examples
========
Please see the ``tools/testing/selftests/bpf`` directory for functional
examples. The code snippets below demonstrates API usage.
This example shows how to declare an LRU Hash with a struct key and a
struct value.
.. code-block:: c
#include <linux/bpf.h>
#include <bpf/bpf_helpers.h>
struct key {
__u32 srcip;
};
struct value {
__u64 packets;
__u64 bytes;
};
struct {
__uint(type, BPF_MAP_TYPE_LRU_HASH);
__uint(max_entries, 32);
__type(key, struct key);
__type(value, struct value);
} packet_stats SEC(".maps");
This example shows how to create or update hash values using atomic
instructions:
.. code-block:: c
static void update_stats(__u32 srcip, int bytes)
{
struct key key = {
.srcip = srcip,
};
struct value *value = bpf_map_lookup_elem(&packet_stats, &key);
if (value) {
__sync_fetch_and_add(&value->packets, 1);
__sync_fetch_and_add(&value->bytes, bytes);
} else {
struct value newval = { 1, bytes };
bpf_map_update_elem(&packet_stats, &key, &newval, BPF_NOEXIST);
}
}
Userspace walking the map elements from the map declared above:
.. code-block:: c
#include <bpf/libbpf.h>
#include <bpf/bpf.h>
static void walk_hash_elements(int map_fd)
{
struct key *cur_key = NULL;
struct key next_key;
struct value value;
int err;
for (;;) {
err = bpf_map_get_next_key(map_fd, cur_key, &next_key);
if (err)
break;
bpf_map_lookup_elem(map_fd, &next_key, &value);
// Use key and value here
cur_key = &next_key;
}
}

View File

@ -23,6 +23,8 @@ properties:
- brcm,bcm4345c5
- brcm,bcm43540-bt
- brcm,bcm4335a0
- brcm,bcm4349-bt
- infineon,cyw55572-bt
shutdown-gpios:
maxItems: 1
@ -92,6 +94,13 @@ properties:
pcm-sync-mode: slave, master
pcm-clock-mode: slave, master
brcm,requires-autobaud-mode:
type: boolean
description:
Set this property if autobaud mode is required. Autobaud mode is required
if the device's initial baud rate in normal mode is not supported by the
host or if the device requires autobaud mode startup before loading FW.
interrupts:
items:
- description: Handle to the line HOST_WAKE used to wake
@ -108,6 +117,22 @@ properties:
required:
- compatible
dependencies:
brcm,requires-autobaud-mode: [ 'shutdown-gpios' ]
if:
not:
properties:
compatible:
contains:
enum:
- brcm,bcm20702a1
- brcm,bcm4329-bt
- brcm,bcm4330-bt
then:
properties:
reset-gpios: false
additionalProperties: false
examples:

View File

@ -0,0 +1,45 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/net/can/microchip,mpfs-can.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title:
Microchip PolarFire SoC (MPFS) can controller
maintainers:
- Conor Dooley <conor.dooley@microchip.com>
allOf:
- $ref: can-controller.yaml#
properties:
compatible:
const: microchip,mpfs-can
reg:
maxItems: 1
interrupts:
maxItems: 1
clocks:
maxItems: 1
required:
- compatible
- reg
- interrupts
- clocks
additionalProperties: false
examples:
- |
can@2010c000 {
compatible = "microchip,mpfs-can";
reg = <0x2010c000 0x1000>;
clocks = <&clkcfg 17>;
interrupt-parent = <&plic>;
interrupts = <56>;
};

View File

@ -0,0 +1,132 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/net/can/nxp,sja1000.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Memory mapped SJA1000 CAN controller from NXP (formerly Philips)
maintainers:
- Wolfgang Grandegger <wg@grandegger.com>
properties:
compatible:
oneOf:
- enum:
- nxp,sja1000
- technologic,sja1000
- items:
- enum:
- renesas,r9a06g032-sja1000 # RZ/N1D
- renesas,r9a06g033-sja1000 # RZ/N1S
- const: renesas,rzn1-sja1000 # RZ/N1
reg:
maxItems: 1
interrupts:
maxItems: 1
clocks:
maxItems: 1
reg-io-width:
$ref: /schemas/types.yaml#/definitions/uint32
description: I/O register width (in bytes) implemented by this device
default: 1
enum: [ 1, 2, 4 ]
nxp,external-clock-frequency:
$ref: /schemas/types.yaml#/definitions/uint32
default: 16000000
description: |
Frequency of the external oscillator clock in Hz.
The internal clock frequency used by the SJA1000 is half of that value.
nxp,tx-output-mode:
$ref: /schemas/types.yaml#/definitions/uint32
enum: [ 0, 1, 2, 3 ]
default: 1
description: |
operation mode of the TX output control logic. Valid values are:
<0> : bi-phase output mode
<1> : normal output mode (default)
<2> : test output mode
<3> : clock output mode
nxp,tx-output-config:
$ref: /schemas/types.yaml#/definitions/uint32
default: 0x02
description: |
TX output pin configuration. Valid values are any one of the below
or combination of TX0 and TX1:
<0x01> : TX0 invert
<0x02> : TX0 pull-down (default)
<0x04> : TX0 pull-up
<0x06> : TX0 push-pull
<0x08> : TX1 invert
<0x10> : TX1 pull-down
<0x20> : TX1 pull-up
<0x30> : TX1 push-pull
nxp,clock-out-frequency:
$ref: /schemas/types.yaml#/definitions/uint32
description: |
clock frequency in Hz on the CLKOUT pin.
If not specified or if the specified value is 0, the CLKOUT pin
will be disabled.
nxp,no-comparator-bypass:
type: boolean
description: Allows to disable the CAN input comparator.
required:
- compatible
- reg
- interrupts
allOf:
- $ref: can-controller.yaml#
- if:
properties:
compatible:
contains:
enum:
- technologic,sja1000
- renesas,rzn1-sja1000
then:
required:
- reg-io-width
- if:
properties:
compatible:
contains:
const: renesas,rzn1-sja1000
then:
required:
- clocks
unevaluatedProperties: false
examples:
- |
can@1a000 {
compatible = "technologic,sja1000";
reg = <0x1a000 0x100>;
interrupts = <1>;
reg-io-width = <2>;
nxp,tx-output-config = <0x06>;
nxp,external-clock-frequency = <24000000>;
};
- |
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/clock/r9a06g032-sysctrl.h>
can@52104000 {
compatible = "renesas,r9a06g032-sja1000", "renesas,rzn1-sja1000";
reg = <0x52104000 0x800>;
reg-io-width = <4>;
interrupts = <GIC_SPI 95 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&sysctrl R9A06G032_HCLK_CAN0>;
};

View File

@ -1,58 +0,0 @@
Memory mapped SJA1000 CAN controller from NXP (formerly Philips)
Required properties:
- compatible : should be one of "nxp,sja1000", "technologic,sja1000".
- reg : should specify the chip select, address offset and size required
to map the registers of the SJA1000. The size is usually 0x80.
- interrupts: property with a value describing the interrupt source
(number and sensitivity) required for the SJA1000.
Optional properties:
- reg-io-width : Specify the size (in bytes) of the IO accesses that
should be performed on the device. Valid value is 1, 2 or 4.
This property is ignored for technologic version.
Default to 1 (8 bits).
- nxp,external-clock-frequency : Frequency of the external oscillator
clock in Hz. Note that the internal clock frequency used by the
SJA1000 is half of that value. If not specified, a default value
of 16000000 (16 MHz) is used.
- nxp,tx-output-mode : operation mode of the TX output control logic:
<0x0> : bi-phase output mode
<0x1> : normal output mode (default)
<0x2> : test output mode
<0x3> : clock output mode
- nxp,tx-output-config : TX output pin configuration:
<0x01> : TX0 invert
<0x02> : TX0 pull-down (default)
<0x04> : TX0 pull-up
<0x06> : TX0 push-pull
<0x08> : TX1 invert
<0x10> : TX1 pull-down
<0x20> : TX1 pull-up
<0x30> : TX1 push-pull
- nxp,clock-out-frequency : clock frequency in Hz on the CLKOUT pin.
If not specified or if the specified value is 0, the CLKOUT pin
will be disabled.
- nxp,no-comparator-bypass : Allows to disable the CAN input comparator.
For further information, please have a look to the SJA1000 data sheet.
Examples:
can@3,100 {
compatible = "nxp,sja1000";
reg = <3 0x100 0x80>;
interrupts = <2 0>;
interrupt-parent = <&mpic>;
nxp,external-clock-frequency = <16000000>;
};

View File

@ -23,11 +23,20 @@ properties:
- cdns,zynq-gem # Xilinx Zynq-7xxx SoC
- cdns,zynqmp-gem # Xilinx Zynq Ultrascale+ MPSoC
- const: cdns,gem # Generic
deprecated: true
- items:
- enum:
- xlnx,versal-gem # Xilinx Versal
- xlnx,zynq-gem # Xilinx Zynq-7xxx SoC
- xlnx,zynqmp-gem # Xilinx Zynq Ultrascale+ MPSoC
- const: cdns,gem # Generic
- items:
- enum:
- cdns,at91sam9260-macb # Atmel at91sam9 SoCs
- cdns,sam9x60-macb # Microchip sam9x60 SoC
- microchip,mpfs-macb # Microchip PolarFire SoC
- const: cdns,macb # Generic
- items:
@ -181,7 +190,7 @@ examples:
#address-cells = <2>;
#size-cells = <2>;
gem1: ethernet@ff0c0000 {
compatible = "cdns,zynqmp-gem", "cdns,gem";
compatible = "xlnx,zynqmp-gem", "cdns,gem";
interrupt-parent = <&gic>;
interrupts = <0 59 4>, <0 59 4>;
reg = <0x0 0xff0c0000 0x0 0x1000>;

View File

@ -48,7 +48,7 @@ properties:
"^led@[01]$":
type: object
description: Hellcreek leds
$ref: ../../leds/common.yaml#
$ref: /schemas/leds/common.yaml#
properties:
reg:

View File

@ -0,0 +1,407 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/net/dsa/mediatek,mt7530.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Mediatek MT7530 Ethernet switch
maintainers:
- Sean Wang <sean.wang@mediatek.com>
- Landen Chao <Landen.Chao@mediatek.com>
- DENG Qingfang <dqfext@gmail.com>
description: |
Port 5 of mt7530 and mt7621 switch is muxed between:
1. GMAC5: GMAC5 can interface with another external MAC or PHY.
2. PHY of port 0 or port 4: PHY interfaces with an external MAC like 2nd GMAC
of the SOC. Used in many setups where port 0/4 becomes the WAN port.
Note: On a MT7621 SOC with integrated switch: 2nd GMAC can only connected to
GMAC5 when the gpios for RGMII2 (GPIO 22-33) are not used and not
connected to external component!
Port 5 modes/configurations:
1. Port 5 is disabled and isolated: An external phy can interface to the 2nd
GMAC of the SOC.
In the case of a build-in MT7530 switch, port 5 shares the RGMII bus with 2nd
GMAC and an optional external phy. Mind the GPIO/pinctl settings of the SOC!
2. Port 5 is muxed to PHY of port 0/4: Port 0/4 interfaces with 2nd GMAC.
It is a simple MAC to PHY interface, port 5 needs to be setup for xMII mode
and RGMII delay.
3. Port 5 is muxed to GMAC5 and can interface to an external phy.
Port 5 becomes an extra switch port.
Only works on platform where external phy TX<->RX lines are swapped.
Like in the Ubiquiti ER-X-SFP.
4. Port 5 is muxed to GMAC5 and interfaces with the 2nd GAMC as 2nd CPU port.
Currently a 2nd CPU port is not supported by DSA code.
Depending on how the external PHY is wired:
1. normal: The PHY can only connect to 2nd GMAC but not to the switch
2. swapped: RGMII TX, RX are swapped; external phy interface with the switch as
a ethernet port. But can't interface to the 2nd GMAC.
Based on the DT the port 5 mode is configured.
Driver tries to lookup the phy-handle of the 2nd GMAC of the master device.
When phy-handle matches PHY of port 0 or 4 then port 5 set-up as mode 2.
phy-mode must be set, see also example 2 below!
* mt7621: phy-mode = "rgmii-txid";
* mt7623: phy-mode = "rgmii";
CPU-Ports need a phy-mode property:
Allowed values on mt7530 and mt7621:
- "rgmii"
- "trgmii"
On mt7531:
- "1000base-x"
- "2500base-x"
- "rgmii"
- "sgmii"
properties:
compatible:
enum:
- mediatek,mt7530
- mediatek,mt7531
- mediatek,mt7621
reg:
maxItems: 1
core-supply:
description:
Phandle to the regulator node necessary for the core power.
"#gpio-cells":
const: 2
gpio-controller:
type: boolean
description:
if defined, MT7530's LED controller will run on GPIO mode.
"#interrupt-cells":
const: 1
interrupt-controller: true
interrupts:
maxItems: 1
io-supply:
description:
Phandle to the regulator node necessary for the I/O power.
See Documentation/devicetree/bindings/regulator/mt6323-regulator.txt
for details for the regulator setup on these boards.
mediatek,mcm:
type: boolean
description:
if defined, indicates that either MT7530 is the part on multi-chip
module belong to MT7623A has or the remotely standalone chip as the
function MT7623N reference board provided for.
reset-gpios:
maxItems: 1
reset-names:
const: mcm
resets:
description:
Phandle pointing to the system reset controller with line index for
the ethsys.
maxItems: 1
patternProperties:
"^(ethernet-)?ports$":
type: object
patternProperties:
"^(ethernet-)?port@[0-9]+$":
type: object
description: Ethernet switch ports
unevaluatedProperties: false
properties:
reg:
description:
Port address described must be 5 or 6 for CPU port and from 0
to 5 for user ports.
allOf:
- $ref: dsa-port.yaml#
- if:
properties:
label:
items:
- const: cpu
then:
required:
- reg
- phy-mode
required:
- compatible
- reg
allOf:
- $ref: "dsa.yaml#"
- if:
required:
- mediatek,mcm
then:
required:
- resets
- reset-names
- dependencies:
interrupt-controller: [ interrupts ]
- if:
properties:
compatible:
items:
- const: mediatek,mt7530
then:
required:
- core-supply
- io-supply
unevaluatedProperties: false
examples:
- |
#include <dt-bindings/gpio/gpio.h>
mdio {
#address-cells = <1>;
#size-cells = <0>;
switch@0 {
compatible = "mediatek,mt7530";
reg = <0>;
core-supply = <&mt6323_vpa_reg>;
io-supply = <&mt6323_vemc3v3_reg>;
reset-gpios = <&pio 33 GPIO_ACTIVE_HIGH>;
ethernet-ports {
#address-cells = <1>;
#size-cells = <0>;
port@0 {
reg = <0>;
label = "lan0";
};
port@1 {
reg = <1>;
label = "lan1";
};
port@2 {
reg = <2>;
label = "lan2";
};
port@3 {
reg = <3>;
label = "lan3";
};
port@4 {
reg = <4>;
label = "wan";
};
port@6 {
reg = <6>;
label = "cpu";
ethernet = <&gmac0>;
phy-mode = "trgmii";
fixed-link {
speed = <1000>;
full-duplex;
};
};
};
};
};
- |
//Example 2: MT7621: Port 4 is WAN port: 2nd GMAC -> Port 5 -> PHY port 4.
ethernet {
#address-cells = <1>;
#size-cells = <0>;
gmac0: mac@0 {
compatible = "mediatek,eth-mac";
reg = <0>;
phy-mode = "rgmii";
fixed-link {
speed = <1000>;
full-duplex;
pause;
};
};
gmac1: mac@1 {
compatible = "mediatek,eth-mac";
reg = <1>;
phy-mode = "rgmii-txid";
phy-handle = <&phy4>;
};
mdio: mdio-bus {
#address-cells = <1>;
#size-cells = <0>;
/* Internal phy */
phy4: ethernet-phy@4 {
reg = <4>;
};
mt7530: switch@1f {
compatible = "mediatek,mt7621";
reg = <0x1f>;
mediatek,mcm;
resets = <&rstctrl 2>;
reset-names = "mcm";
ethernet-ports {
#address-cells = <1>;
#size-cells = <0>;
port@0 {
reg = <0>;
label = "lan0";
};
port@1 {
reg = <1>;
label = "lan1";
};
port@2 {
reg = <2>;
label = "lan2";
};
port@3 {
reg = <3>;
label = "lan3";
};
/* Commented out. Port 4 is handled by 2nd GMAC.
port@4 {
reg = <4>;
label = "lan4";
};
*/
port@6 {
reg = <6>;
label = "cpu";
ethernet = <&gmac0>;
phy-mode = "rgmii";
fixed-link {
speed = <1000>;
full-duplex;
pause;
};
};
};
};
};
};
- |
//Example 3: MT7621: Port 5 is connected to external PHY: Port 5 -> external PHY.
ethernet {
#address-cells = <1>;
#size-cells = <0>;
gmac_0: mac@0 {
compatible = "mediatek,eth-mac";
reg = <0>;
phy-mode = "rgmii";
fixed-link {
speed = <1000>;
full-duplex;
pause;
};
};
mdio0: mdio-bus {
#address-cells = <1>;
#size-cells = <0>;
/* External phy */
ephy5: ethernet-phy@7 {
reg = <7>;
};
switch@1f {
compatible = "mediatek,mt7621";
reg = <0x1f>;
mediatek,mcm;
resets = <&rstctrl 2>;
reset-names = "mcm";
ethernet-ports {
#address-cells = <1>;
#size-cells = <0>;
port@0 {
reg = <0>;
label = "lan0";
};
port@1 {
reg = <1>;
label = "lan1";
};
port@2 {
reg = <2>;
label = "lan2";
};
port@3 {
reg = <3>;
label = "lan3";
};
port@4 {
reg = <4>;
label = "lan4";
};
port@5 {
reg = <5>;
label = "lan5";
phy-mode = "rgmii";
phy-handle = <&ephy5>;
};
cpu_port0: port@6 {
reg = <6>;
label = "cpu";
ethernet = <&gmac_0>;
phy-mode = "rgmii";
fixed-link {
speed = <1000>;
full-duplex;
pause;
};
};
};
};
};
};

View File

@ -0,0 +1,192 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/net/dsa/microchip,lan937x.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: LAN937x Ethernet Switch Series Tree Bindings
maintainers:
- UNGLinuxDriver@microchip.com
allOf:
- $ref: dsa.yaml#
properties:
compatible:
enum:
- microchip,lan9370
- microchip,lan9371
- microchip,lan9372
- microchip,lan9373
- microchip,lan9374
reg:
maxItems: 1
spi-max-frequency:
maximum: 50000000
reset-gpios:
description: Optional gpio specifier for a reset line
maxItems: 1
mdio:
$ref: /schemas/net/mdio.yaml#
unevaluatedProperties: false
patternProperties:
"^(ethernet-)?ports$":
patternProperties:
"^(ethernet-)?port@[0-9]+$":
allOf:
- if:
properties:
phy-mode:
contains:
enum:
- rgmii
- rgmii-id
- rgmii-txid
- rgmii-rxid
then:
properties:
rx-internal-delay-ps:
enum: [0, 2000]
default: 0
tx-internal-delay-ps:
enum: [0, 2000]
default: 0
required:
- compatible
- reg
unevaluatedProperties: false
examples:
- |
#include <dt-bindings/gpio/gpio.h>
macb0 {
#address-cells = <1>;
#size-cells = <0>;
fixed-link {
speed = <1000>;
full-duplex;
};
};
spi {
#address-cells = <1>;
#size-cells = <0>;
lan9374: switch@0 {
compatible = "microchip,lan9374";
reg = <0>;
spi-max-frequency = <44000000>;
ethernet-ports {
#address-cells = <1>;
#size-cells = <0>;
port@0 {
reg = <0>;
label = "lan1";
phy-mode = "internal";
phy-handle = <&t1phy0>;
};
port@1 {
reg = <1>;
label = "lan2";
phy-mode = "internal";
phy-handle = <&t1phy1>;
};
port@2 {
reg = <2>;
label = "lan4";
phy-mode = "internal";
phy-handle = <&t1phy2>;
};
port@3 {
reg = <3>;
label = "lan6";
phy-mode = "internal";
phy-handle = <&t1phy3>;
};
port@4 {
reg = <4>;
phy-mode = "rgmii";
tx-internal-delay-ps = <2000>;
rx-internal-delay-ps = <2000>;
ethernet = <&macb0>;
fixed-link {
speed = <1000>;
full-duplex;
};
};
port@5 {
reg = <5>;
label = "lan7";
phy-mode = "rgmii";
tx-internal-delay-ps = <2000>;
rx-internal-delay-ps = <2000>;
fixed-link {
speed = <1000>;
full-duplex;
};
};
port@6 {
reg = <6>;
label = "lan5";
phy-mode = "internal";
phy-handle = <&t1phy6>;
};
port@7 {
reg = <7>;
label = "lan3";
phy-mode = "internal";
phy-handle = <&t1phy7>;
};
};
mdio {
#address-cells = <1>;
#size-cells = <0>;
t1phy0: ethernet-phy@0{
reg = <0x0>;
};
t1phy1: ethernet-phy@1{
reg = <0x1>;
};
t1phy2: ethernet-phy@2{
reg = <0x2>;
};
t1phy3: ethernet-phy@3{
reg = <0x3>;
};
t1phy6: ethernet-phy@6{
reg = <0x6>;
};
t1phy7: ethernet-phy@7{
reg = <0x7>;
};
};
};
};

View File

@ -1,327 +0,0 @@
Mediatek MT7530 Ethernet switch
================================
Required properties:
- compatible: may be compatible = "mediatek,mt7530"
or compatible = "mediatek,mt7621"
or compatible = "mediatek,mt7531"
- #address-cells: Must be 1.
- #size-cells: Must be 0.
- mediatek,mcm: Boolean; if defined, indicates that either MT7530 is the part
on multi-chip module belong to MT7623A has or the remotely standalone
chip as the function MT7623N reference board provided for.
If compatible mediatek,mt7530 is set then the following properties are required
- core-supply: Phandle to the regulator node necessary for the core power.
- io-supply: Phandle to the regulator node necessary for the I/O power.
See Documentation/devicetree/bindings/regulator/mt6323-regulator.txt
for details for the regulator setup on these boards.
If the property mediatek,mcm isn't defined, following property is required
- reset-gpios: Should be a gpio specifier for a reset line.
Else, following properties are required
- resets : Phandle pointing to the system reset controller with
line index for the ethsys.
- reset-names : Should be set to "mcm".
Required properties for the child nodes within ports container:
- reg: Port address described must be 6 for CPU port and from 0 to 5 for
user ports.
- phy-mode: String, the following values are acceptable for port labeled
"cpu":
If compatible mediatek,mt7530 or mediatek,mt7621 is set,
must be either "trgmii" or "rgmii"
If compatible mediatek,mt7531 is set,
must be either "sgmii", "1000base-x" or "2500base-x"
Port 5 of mt7530 and mt7621 switch is muxed between:
1. GMAC5: GMAC5 can interface with another external MAC or PHY.
2. PHY of port 0 or port 4: PHY interfaces with an external MAC like 2nd GMAC
of the SOC. Used in many setups where port 0/4 becomes the WAN port.
Note: On a MT7621 SOC with integrated switch: 2nd GMAC can only connected to
GMAC5 when the gpios for RGMII2 (GPIO 22-33) are not used and not
connected to external component!
Port 5 modes/configurations:
1. Port 5 is disabled and isolated: An external phy can interface to the 2nd
GMAC of the SOC.
In the case of a build-in MT7530 switch, port 5 shares the RGMII bus with 2nd
GMAC and an optional external phy. Mind the GPIO/pinctl settings of the SOC!
2. Port 5 is muxed to PHY of port 0/4: Port 0/4 interfaces with 2nd GMAC.
It is a simple MAC to PHY interface, port 5 needs to be setup for xMII mode
and RGMII delay.
3. Port 5 is muxed to GMAC5 and can interface to an external phy.
Port 5 becomes an extra switch port.
Only works on platform where external phy TX<->RX lines are swapped.
Like in the Ubiquiti ER-X-SFP.
4. Port 5 is muxed to GMAC5 and interfaces with the 2nd GAMC as 2nd CPU port.
Currently a 2nd CPU port is not supported by DSA code.
Depending on how the external PHY is wired:
1. normal: The PHY can only connect to 2nd GMAC but not to the switch
2. swapped: RGMII TX, RX are swapped; external phy interface with the switch as
a ethernet port. But can't interface to the 2nd GMAC.
Based on the DT the port 5 mode is configured.
Driver tries to lookup the phy-handle of the 2nd GMAC of the master device.
When phy-handle matches PHY of port 0 or 4 then port 5 set-up as mode 2.
phy-mode must be set, see also example 2 below!
* mt7621: phy-mode = "rgmii-txid";
* mt7623: phy-mode = "rgmii";
Optional properties:
- gpio-controller: Boolean; if defined, MT7530's LED controller will run on
GPIO mode.
- #gpio-cells: Must be 2 if gpio-controller is defined.
- interrupt-controller: Boolean; Enables the internal interrupt controller.
If interrupt-controller is defined, the following properties are required.
- #interrupt-cells: Must be 1.
- interrupts: Parent interrupt for the interrupt controller.
See Documentation/devicetree/bindings/net/dsa/dsa.txt for a list of additional
required, optional properties and how the integrated switch subnodes must
be specified.
Example:
&mdio0 {
switch@0 {
compatible = "mediatek,mt7530";
#address-cells = <1>;
#size-cells = <0>;
reg = <0>;
core-supply = <&mt6323_vpa_reg>;
io-supply = <&mt6323_vemc3v3_reg>;
reset-gpios = <&pio 33 0>;
ports {
#address-cells = <1>;
#size-cells = <0>;
reg = <0>;
port@0 {
reg = <0>;
label = "lan0";
};
port@1 {
reg = <1>;
label = "lan1";
};
port@2 {
reg = <2>;
label = "lan2";
};
port@3 {
reg = <3>;
label = "lan3";
};
port@4 {
reg = <4>;
label = "wan";
};
port@6 {
reg = <6>;
label = "cpu";
ethernet = <&gmac0>;
phy-mode = "trgmii";
fixed-link {
speed = <1000>;
full-duplex;
};
};
};
};
};
Example 2: MT7621: Port 4 is WAN port: 2nd GMAC -> Port 5 -> PHY port 4.
&eth {
gmac0: mac@0 {
compatible = "mediatek,eth-mac";
reg = <0>;
phy-mode = "rgmii";
fixed-link {
speed = <1000>;
full-duplex;
pause;
};
};
gmac1: mac@1 {
compatible = "mediatek,eth-mac";
reg = <1>;
phy-mode = "rgmii-txid";
phy-handle = <&phy4>;
};
mdio: mdio-bus {
#address-cells = <1>;
#size-cells = <0>;
/* Internal phy */
phy4: ethernet-phy@4 {
reg = <4>;
};
mt7530: switch@1f {
compatible = "mediatek,mt7621";
#address-cells = <1>;
#size-cells = <0>;
reg = <0x1f>;
pinctrl-names = "default";
mediatek,mcm;
resets = <&rstctrl 2>;
reset-names = "mcm";
ports {
#address-cells = <1>;
#size-cells = <0>;
port@0 {
reg = <0>;
label = "lan0";
};
port@1 {
reg = <1>;
label = "lan1";
};
port@2 {
reg = <2>;
label = "lan2";
};
port@3 {
reg = <3>;
label = "lan3";
};
/* Commented out. Port 4 is handled by 2nd GMAC.
port@4 {
reg = <4>;
label = "lan4";
};
*/
cpu_port0: port@6 {
reg = <6>;
label = "cpu";
ethernet = <&gmac0>;
phy-mode = "rgmii";
fixed-link {
speed = <1000>;
full-duplex;
pause;
};
};
};
};
};
};
Example 3: MT7621: Port 5 is connected to external PHY: Port 5 -> external PHY.
&eth {
gmac0: mac@0 {
compatible = "mediatek,eth-mac";
reg = <0>;
phy-mode = "rgmii";
fixed-link {
speed = <1000>;
full-duplex;
pause;
};
};
mdio: mdio-bus {
#address-cells = <1>;
#size-cells = <0>;
/* External phy */
ephy5: ethernet-phy@7 {
reg = <7>;
};
mt7530: switch@1f {
compatible = "mediatek,mt7621";
#address-cells = <1>;
#size-cells = <0>;
reg = <0x1f>;
pinctrl-names = "default";
mediatek,mcm;
resets = <&rstctrl 2>;
reset-names = "mcm";
ports {
#address-cells = <1>;
#size-cells = <0>;
port@0 {
reg = <0>;
label = "lan0";
};
port@1 {
reg = <1>;
label = "lan1";
};
port@2 {
reg = <2>;
label = "lan2";
};
port@3 {
reg = <3>;
label = "lan3";
};
port@4 {
reg = <4>;
label = "lan4";
};
port@5 {
reg = <5>;
label = "lan5";
phy-mode = "rgmii";
phy-handle = <&ephy5>;
};
cpu_port0: port@6 {
reg = <6>;
label = "cpu";
ethernet = <&gmac0>;
phy-mode = "rgmii";
fixed-link {
speed = <1000>;
full-duplex;
pause;
};
};
};
};
};
};

View File

@ -0,0 +1,157 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/net/dsa/renesas,rzn1-a5psw.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Renesas RZ/N1 Advanced 5 ports ethernet switch
maintainers:
- Clément Léger <clement.leger@bootlin.com>
description: |
The advanced 5 ports switch is present on the Renesas RZ/N1 SoC family and
handles 4 ports + 1 CPU management port.
allOf:
- $ref: dsa.yaml#
properties:
compatible:
items:
- enum:
- renesas,r9a06g032-a5psw
- const: renesas,rzn1-a5psw
reg:
maxItems: 1
interrupts:
items:
- description: Device Level Ring (DLR) interrupt
- description: Switch interrupt
- description: Parallel Redundancy Protocol (PRP) interrupt
- description: Integrated HUB module interrupt
- description: Receive Pattern Match interrupt
interrupt-names:
items:
- const: dlr
- const: switch
- const: prp
- const: hub
- const: ptrn
power-domains:
maxItems: 1
mdio:
$ref: /schemas/net/mdio.yaml#
unevaluatedProperties: false
clocks:
items:
- description: AHB clock used for the switch register interface
- description: Switch system clock
clock-names:
items:
- const: hclk
- const: clk
ethernet-ports:
type: object
properties:
'#address-cells':
const: 1
'#size-cells':
const: 0
patternProperties:
"^(ethernet-)?port@[0-4]$":
type: object
description: Ethernet switch ports
properties:
pcs-handle:
description:
phandle pointing to a PCS sub-node compatible with
renesas,rzn1-miic.yaml#
$ref: /schemas/types.yaml#/definitions/phandle
unevaluatedProperties: false
required:
- compatible
- reg
- clocks
- clock-names
- power-domains
examples:
- |
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/clock/r9a06g032-sysctrl.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
switch@44050000 {
compatible = "renesas,r9a06g032-a5psw", "renesas,rzn1-a5psw";
reg = <0x44050000 0x10000>;
clocks = <&sysctrl R9A06G032_HCLK_SWITCH>, <&sysctrl R9A06G032_CLK_SWITCH>;
clock-names = "hclk", "clk";
power-domains = <&sysctrl>;
interrupts = <GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 42 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 43 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 44 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 45 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "dlr", "switch", "prp", "hub", "ptrn";
dsa,member = <0 0>;
ethernet-ports {
#address-cells = <1>;
#size-cells = <0>;
port@0 {
reg = <0>;
label = "lan0";
phy-handle = <&switch0phy3>;
pcs-handle = <&mii_conv4>;
};
port@1 {
reg = <1>;
label = "lan1";
phy-handle = <&switch0phy1>;
pcs-handle = <&mii_conv3>;
};
port@4 {
reg = <4>;
ethernet = <&gmac2>;
label = "cpu";
fixed-link {
speed = <1000>;
full-duplex;
};
};
};
mdio {
#address-cells = <1>;
#size-cells = <0>;
reset-gpios = <&gpio0a 2 GPIO_ACTIVE_HIGH>;
reset-delay-us = <15>;
clock-frequency = <2500000>;
switch0phy1: ethernet-phy@1{
reg = <1>;
};
switch0phy3: ethernet-phy@3{
reg = <3>;
};
};
};

View File

@ -133,12 +133,6 @@ properties:
and is useful for determining certain configuration settings
such as flow control thresholds.
rx-internal-delay-ps:
description: |
RGMII Receive Clock Delay defined in pico seconds.
This is used for controllers that have configurable RX internal delays.
If this property is present then the MAC applies the RX delay.
sfp:
$ref: /schemas/types.yaml#/definitions/phandle
description:
@ -150,12 +144,6 @@ properties:
The size of the controller\'s transmit fifo in bytes. This
is used for components that can have configurable fifo sizes.
tx-internal-delay-ps:
description: |
RGMII Transmit Clock Delay defined in pico seconds.
This is used for controllers that have configurable TX internal delays.
If this property is present then the MAC applies the TX delay.
managed:
description:
Specifies the PHY management type. If auto is set and fixed-link
@ -227,6 +215,29 @@ properties:
required:
- speed
allOf:
- if:
properties:
phy-mode:
contains:
enum:
- rgmii
- rgmii-rxid
- rgmii-txid
- rgmii-id
then:
properties:
rx-internal-delay-ps:
description:
RGMII Receive Clock Delay defined in pico seconds.This is used for
controllers that have configurable RX internal delays. If this
property is present then the MAC applies the RX delay.
tx-internal-delay-ps:
description:
RGMII Transmit Clock Delay defined in pico seconds.This is used for
controllers that have configurable TX internal delays. If this
property is present then the MAC applies the TX delay.
additionalProperties: true
...

View File

@ -58,6 +58,11 @@ properties:
- fsl,imx8qxp-fec
- const: fsl,imx8qm-fec
- const: fsl,imx6sx-fec
- items:
- enum:
- fsl,imx8ulp-fec
- const: fsl,imx6ul-fec
- const: fsl,imx6q-fec
reg:
maxItems: 1
@ -121,6 +126,10 @@ properties:
mac-address: true
nvmem-cells: true
nvmem-cell-names: true
tx-internal-delay-ps:
enum: [0, 2000]
@ -216,7 +225,7 @@ required:
# least undocumented properties. However, PHY may have a deprecated option to
# place PHY OF properties in the MAC node, such as Micrel PHY, and we can find
# these boards which is based on i.MX6QDL.
additionalProperties: false
unevaluatedProperties: false
examples:
- |

View File

@ -23,6 +23,7 @@ properties:
- mediatek,mt8516-eth
- mediatek,mt8518-eth
- mediatek,mt8175-eth
- mediatek,mt8365-eth
reg:
maxItems: 1
@ -47,6 +48,22 @@ properties:
Phandle to the device containing the PERICFG register range. This is used
to control the MII mode.
mediatek,rmii-rxc:
type: boolean
description:
If present, indicates that the RMII reference clock, which is from external
PHYs, is connected to RXC pin. Otherwise, is connected to TXC pin.
mediatek,rxc-inverse:
type: boolean
description:
If present, indicates that clock on RXC pad will be inversed.
mediatek,txc-inverse:
type: boolean
description:
If present, indicates that clock on TXC pad will be inversed.
mdio:
$ref: mdio.yaml#
unevaluatedProperties: false

View File

@ -16,6 +16,7 @@ Optional properties:
KSZ8051: register 0x1f, bits 5..4
KSZ8081: register 0x1f, bits 5..4
KSZ8091: register 0x1f, bits 5..4
LAN8814: register EP5.0, bit 6
See the respective PHY datasheet for the mode values.

View File

@ -58,7 +58,6 @@ properties:
spi-cpha: true
spi-cpol: true
spi-max-frequency: true
required:
- compatible
@ -85,6 +84,7 @@ allOf:
contains:
const: marvell,nfc-spi
then:
$ref: /schemas/spi/spi-peripheral-props.yaml#
properties:
break-control: false
flow-control: false
@ -108,7 +108,7 @@ allOf:
spi-max-frequency: false
reg: false
additionalProperties: false
unevaluatedProperties: false
examples:
- |

View File

@ -30,8 +30,6 @@ properties:
reg:
maxItems: 1
spi-max-frequency: true
uicc-present:
type: boolean
description: |
@ -55,10 +53,11 @@ then:
properties:
spi-max-frequency: false
else:
$ref: /schemas/spi/spi-peripheral-props.yaml#
required:
- spi-max-frequency
additionalProperties: false
unevaluatedProperties: false
examples:
- |

View File

@ -25,8 +25,6 @@ properties:
st95hfvin-supply:
description: ST95HF transceiver's Vin regulator supply
spi-max-frequency: true
required:
- compatible
- enable-gpio
@ -34,7 +32,10 @@ required:
- reg
- spi-max-frequency
additionalProperties: false
allOf:
- $ref: /schemas/spi/spi-peripheral-props.yaml#
unevaluatedProperties: false
examples:
- |

View File

@ -40,8 +40,6 @@ properties:
reg:
maxItems: 1
spi-max-frequency: true
ti,enable-gpios:
minItems: 1
maxItems: 2
@ -65,7 +63,10 @@ required:
- ti,enable-gpios
- vin-supply
additionalProperties: false
allOf:
- $ref: /schemas/spi/spi-peripheral-props.yaml#
unevaluatedProperties: false
examples:
- |

View File

@ -1,85 +0,0 @@
Small Form Factor (SFF) Committee Small Form-factor Pluggable (SFP)
Transceiver
Required properties:
- compatible : must be one of
"sff,sfp" for SFP modules
"sff,sff" for soldered down SFF modules
- i2c-bus : phandle of an I2C bus controller for the SFP two wire serial
interface
Optional Properties:
- mod-def0-gpios : GPIO phandle and a specifier of the MOD-DEF0 (AKA Mod_ABS)
module presence input gpio signal, active (module absent) high. Must
not be present for SFF modules
- los-gpios : GPIO phandle and a specifier of the Receiver Loss of Signal
Indication input gpio signal, active (signal lost) high
- tx-fault-gpios : GPIO phandle and a specifier of the Module Transmitter
Fault input gpio signal, active (fault condition) high
- tx-disable-gpios : GPIO phandle and a specifier of the Transmitter Disable
output gpio signal, active (Tx disable) high
- rate-select0-gpios : GPIO phandle and a specifier of the Rx Signaling Rate
Select (AKA RS0) output gpio signal, low: low Rx rate, high: high Rx rate
Must not be present for SFF modules
- rate-select1-gpios : GPIO phandle and a specifier of the Tx Signaling Rate
Select (AKA RS1) output gpio signal (SFP+ only), low: low Tx rate, high:
high Tx rate. Must not be present for SFF modules
- maximum-power-milliwatt : Maximum module power consumption
Specifies the maximum power consumption allowable by a module in the
slot, in milli-Watts. Presently, modules can be up to 1W, 1.5W or 2W.
Example #1: Direct serdes to SFP connection
sfp_eth3: sfp-eth3 {
compatible = "sff,sfp";
i2c-bus = <&sfp_1g_i2c>;
los-gpios = <&cpm_gpio2 22 GPIO_ACTIVE_HIGH>;
mod-def0-gpios = <&cpm_gpio2 21 GPIO_ACTIVE_LOW>;
maximum-power-milliwatt = <1000>;
pinctrl-names = "default";
pinctrl-0 = <&cpm_sfp_1g_pins &cps_sfp_1g_pins>;
tx-disable-gpios = <&cps_gpio1 24 GPIO_ACTIVE_HIGH>;
tx-fault-gpios = <&cpm_gpio2 19 GPIO_ACTIVE_HIGH>;
};
&cps_emac3 {
phy-names = "comphy";
phys = <&cps_comphy5 0>;
sfp = <&sfp_eth3>;
};
Example #2: Serdes to PHY to SFP connection
sfp_eth0: sfp-eth0 {
compatible = "sff,sfp";
i2c-bus = <&sfpp0_i2c>;
los-gpios = <&cps_gpio1 28 GPIO_ACTIVE_HIGH>;
mod-def0-gpios = <&cps_gpio1 27 GPIO_ACTIVE_LOW>;
pinctrl-names = "default";
pinctrl-0 = <&cps_sfpp0_pins>;
tx-disable-gpios = <&cps_gpio1 29 GPIO_ACTIVE_HIGH>;
tx-fault-gpios = <&cps_gpio1 26 GPIO_ACTIVE_HIGH>;
};
p0_phy: ethernet-phy@0 {
compatible = "ethernet-phy-ieee802.3-c45";
pinctrl-names = "default";
pinctrl-0 = <&cpm_phy0_pins &cps_phy0_pins>;
reg = <0>;
interrupt = <&cpm_gpio2 18 IRQ_TYPE_EDGE_FALLING>;
sfp = <&sfp_eth0>;
};
&cpm_eth0 {
phy = <&p0_phy>;
phy-mode = "10gbase-kr";
};

View File

@ -0,0 +1,142 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: "http://devicetree.org/schemas/net/sff,sfp.yaml#"
$schema: "http://devicetree.org/meta-schemas/core.yaml#"
title: Small Form Factor (SFF) Committee Small Form-factor Pluggable (SFP)
Transceiver
maintainers:
- Russell King <linux@armlinux.org.uk>
properties:
compatible:
enum:
- sff,sfp # for SFP modules
- sff,sff # for soldered down SFF modules
i2c-bus:
$ref: /schemas/types.yaml#/definitions/phandle
description:
phandle of an I2C bus controller for the SFP two wire serial
maximum-power-milliwatt:
maxItems: 1
description:
Maximum module power consumption Specifies the maximum power consumption
allowable by a module in the slot, in milli-Watts. Presently, modules can
be up to 1W, 1.5W or 2W.
"mod-def0-gpios":
maxItems: 1
description:
GPIO phandle and a specifier of the MOD-DEF0 (AKA Mod_ABS) module
presence input gpio signal, active (module absent) high. Must not be
present for SFF modules
"los-gpios":
maxItems: 1
description:
GPIO phandle and a specifier of the Receiver Loss of Signal Indication
input gpio signal, active (signal lost) high
"tx-fault-gpios":
maxItems: 1
description:
GPIO phandle and a specifier of the Module Transmitter Fault input gpio
signal, active (fault condition) high
"tx-disable-gpios":
maxItems: 1
description:
GPIO phandle and a specifier of the Transmitter Disable output gpio
signal, active (Tx disable) high
"rate-select0-gpios":
maxItems: 1
description:
GPIO phandle and a specifier of the Rx Signaling Rate Select (AKA RS0)
output gpio signal, low - low Rx rate, high - high Rx rate Must not be
present for SFF modules
"rate-select1-gpios":
maxItems: 1
description:
GPIO phandle and a specifier of the Tx Signaling Rate Select (AKA RS1)
output gpio signal (SFP+ only), low - low Tx rate, high - high Tx rate. Must
not be present for SFF modules
allOf:
- if:
properties:
compatible:
contains:
const: sff,sff
then:
properties:
mod-def0-gpios: false
rate-select0-gpios: false
rate-select1-gpios: false
required:
- compatible
- i2c-bus
additionalProperties: false
examples:
- | # Direct serdes to SFP connection
#include <dt-bindings/gpio/gpio.h>
sfp1: sfp {
compatible = "sff,sfp";
i2c-bus = <&sfp_1g_i2c>;
los-gpios = <&cpm_gpio2 22 GPIO_ACTIVE_HIGH>;
mod-def0-gpios = <&cpm_gpio2 21 GPIO_ACTIVE_LOW>;
maximum-power-milliwatt = <1000>;
pinctrl-names = "default";
pinctrl-0 = <&cpm_sfp_1g_pins &cps_sfp_1g_pins>;
tx-disable-gpios = <&cps_gpio1 24 GPIO_ACTIVE_HIGH>;
tx-fault-gpios = <&cpm_gpio2 19 GPIO_ACTIVE_HIGH>;
};
ethernet {
phy-names = "comphy";
phys = <&cps_comphy5 0>;
sfp = <&sfp1>;
};
- | # Serdes to PHY to SFP connection
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
sfp2: sfp {
compatible = "sff,sfp";
i2c-bus = <&sfp_i2c>;
los-gpios = <&cps_gpio1 28 GPIO_ACTIVE_HIGH>;
mod-def0-gpios = <&cps_gpio1 27 GPIO_ACTIVE_LOW>;
pinctrl-names = "default";
pinctrl-0 = <&cps_sfpp0_pins>;
tx-disable-gpios = <&cps_gpio1 29 GPIO_ACTIVE_HIGH>;
tx-fault-gpios = <&cps_gpio1 26 GPIO_ACTIVE_HIGH>;
};
mdio {
#address-cells = <1>;
#size-cells = <0>;
phy: ethernet-phy@0 {
compatible = "ethernet-phy-ieee802.3-c45";
pinctrl-names = "default";
pinctrl-0 = <&cpm_phy0_pins &cps_phy0_pins>;
reg = <0>;
interrupt = <&cpm_gpio2 18 IRQ_TYPE_EDGE_FALLING>;
sfp = <&sfp2>;
};
};
ethernet {
phy = <&phy>;
phy-mode = "10gbase-kr";
};

View File

@ -65,6 +65,8 @@ properties:
- ingenic,x2000-mac
- loongson,ls2k-dwmac
- loongson,ls7a-dwmac
- renesas,r9a06g032-gmac
- renesas,rzn1-gmac
- rockchip,px30-gmac
- rockchip,rk3128-gmac
- rockchip,rk3228-gmac
@ -135,6 +137,9 @@ properties:
reset-names:
const: stmmaceth
power-domains:
maxItems: 1
mac-mode:
$ref: ethernet-controller.yaml#/properties/phy-connection-type
description:

View File

@ -31,6 +31,16 @@ properties:
reg:
maxItems: 1
nvmem-cells:
maxItems: 1
description:
Nvmem data cell containing the value to write to the
IO_IMPEDANCE_CTRL field of the IO_MUX_CFG register.
nvmem-cell-names:
items:
- const: io_impedance_ctrl
ti,min-output-impedance:
type: boolean
description: |
@ -42,9 +52,11 @@ properties:
description: |
MAC Interface Impedance control to set the programmable output impedance
to a maximum value (70 ohms).
Note: ti,min-output-impedance and ti,max-output-impedance are mutually
exclusive. When both properties are present ti,max-output-impedance
takes precedence.
Note: Specifying an io_impedance_ctrl nvmem cell or one of the
ti,min-output-impedance, ti,max-output-impedance properties
are mutually exclusive. If more than one is present, an nvmem
cell takes precedence over ti,max-output-impedance, which in
turn takes precedence over ti,min-output-impedance.
tx-fifo-depth:
$ref: /schemas/types.yaml#/definitions/uint32

View File

@ -75,6 +75,16 @@ properties:
items:
pattern: '^[A-Z][A-Z]-[A-Z][0-9A-Z]-[0-9]+$'
brcm,ccode-map-trivial:
description: |
Use a trivial mapping of ISO3166 country codes to brcmfmac firmware
country code and revision: cc -> { cc, 0 }. In other words, assume that
the CLM blob firmware uses ISO3166 country codes as well, and that all
revisions are zero. This property is mutually exclusive with
brcm,ccode-map. If both properties are specified, then brcm,ccode-map
takes precedence.
type: boolean
required:
- compatible
- reg

View File

@ -54,6 +54,16 @@ properties:
reset-names:
const: consys
clocks:
maxItems: 2
description:
Specify the consys clocks for mt7986.
clock-names:
items:
- const: mcu
- const: ap2conn
mediatek,infracfg:
$ref: /schemas/types.yaml#/definitions/phandle
description:
@ -269,5 +279,8 @@ examples:
<0x10003000 0x1000>,
<0x11d10000 0x1000>;
interrupts = <GIC_SPI 213 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&topckgen 50>,
<&topckgen 62>;
clock-names = "mcu", "ap2conn";
memory-region = <&wmcpu_emi>;
};

View File

@ -0,0 +1,63 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/net/xlnx,emaclite.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Xilinx Emaclite Ethernet controller
maintainers:
- Radhey Shyam Pandey <radhey.shyam.pandey@amd.com>
- Harini Katakam <harini.katakam@amd.com>
allOf:
- $ref: ethernet-controller.yaml#
properties:
compatible:
enum:
- xlnx,opb-ethernetlite-1.01.a
- xlnx,opb-ethernetlite-1.01.b
- xlnx,xps-ethernetlite-1.00.a
- xlnx,xps-ethernetlite-2.00.a
- xlnx,xps-ethernetlite-2.01.a
- xlnx,xps-ethernetlite-3.00.a
reg:
maxItems: 1
interrupts:
maxItems: 1
phy-handle: true
local-mac-address: true
xlnx,tx-ping-pong:
type: boolean
description: hardware supports tx ping pong buffer.
xlnx,rx-ping-pong:
type: boolean
description: hardware supports rx ping pong buffer.
required:
- compatible
- reg
- interrupts
- phy-handle
additionalProperties: false
examples:
- |
axi_ethernetlite_1: ethernet@40e00000 {
compatible = "xlnx,xps-ethernetlite-3.00.a";
reg = <0x40e00000 0x10000>;
interrupt-parent = <&axi_intc_1>;
interrupts = <1>;
local-mac-address = [00 00 00 00 00 00];
phy-handle = <&phy0>;
xlnx,rx-ping-pong;
xlnx,tx-ping-pong;
};

View File

@ -780,6 +780,17 @@ peer_notif_delay
value is 0 which means to match the value of the link monitor
interval.
prio
Slave priority. A higher number means higher priority.
The primary slave has the highest priority. This option also
follows the primary_reselect rules.
This option could only be configured via netlink, and is only valid
for active-backup(1), balance-tlb (5) and balance-alb (6) mode.
The valid value range is a signed 32 bit integer.
The default value is 0.
primary
A string (eth0, eth2, etc) specifying which slave is the

View File

@ -168,7 +168,7 @@ reflect the correct [#f1]_ traffic on the node the loopback of the sent
data has to be performed right after a successful transmission. If
the CAN network interface is not capable of performing the loopback for
some reason the SocketCAN core can do this task as a fallback solution.
See :ref:`socketcan-local-loopback1` for details (recommended).
See :ref:`socketcan-local-loopback2` for details (recommended).
The loopback functionality is enabled by default to reflect standard
networking behaviour for CAN applications. Due to some requests from

View File

@ -0,0 +1,331 @@
.. SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
can327: ELM327 driver for Linux SocketCAN
==========================================
Authors
--------
Max Staudt <max@enpas.org>
Motivation
-----------
This driver aims to lower the initial cost for hackers interested in
working with CAN buses.
CAN adapters are expensive, few, and far between.
ELM327 interfaces are cheap and plentiful.
Let's use ELM327s as CAN adapters.
Introduction
-------------
This driver is an effort to turn abundant ELM327 based OBD interfaces
into full fledged (as far as possible) CAN interfaces.
Since the ELM327 was never meant to be a stand alone CAN controller,
the driver has to switch between its modes as quickly as possible in
order to fake full-duplex operation.
As such, can327 is a best effort driver. However, this is more than
enough to implement simple request-response protocols (such as OBD II),
and to monitor broadcast messages on a bus (such as in a vehicle).
Most ELM327s come as nondescript serial devices, attached via USB or
Bluetooth. The driver cannot recognize them by itself, and as such it
is up to the user to attach it in form of a TTY line discipline
(similar to PPP, SLIP, slcan, ...).
This driver is meant for ELM327 versions 1.4b and up, see below for
known limitations in older controllers and clones.
Data sheet
-----------
The official data sheets can be found at ELM electronics' home page:
https://www.elmelectronics.com/
How to attach the line discipline
----------------------------------
Every ELM327 chip is factory programmed to operate at a serial setting
of 38400 baud/s, 8 data bits, no parity, 1 stopbit.
If you have kept this default configuration, the line discipline can
be attached on a command prompt as follows::
sudo ldattach \
--debug \
--speed 38400 \
--eightbits \
--noparity \
--onestopbit \
--iflag -ICRNL,INLCR,-IXOFF \
30 \
/dev/ttyUSB0
To change the ELM327's serial settings, please refer to its data
sheet. This needs to be done before attaching the line discipline.
Once the ldisc is attached, the CAN interface starts out unconfigured.
Set the speed before starting it::
# The interface needs to be down to change parameters
sudo ip link set can0 down
sudo ip link set can0 type can bitrate 500000
sudo ip link set can0 up
500000 bit/s is a common rate for OBD-II diagnostics.
If you're connecting straight to a car's OBD port, this is the speed
that most cars (but not all!) expect.
After this, you can set out as usual with candump, cansniffer, etc.
How to check the controller version
------------------------------------
Use a terminal program to attach to the controller.
After issuing the "``AT WS``" command, the controller will respond with
its version::
>AT WS
ELM327 v1.4b
>
Note that clones may claim to be any version they like.
It is not indicative of their actual feature set.
Communication example
----------------------
This is a short and incomplete introduction on how to talk to an ELM327.
It is here to guide understanding of the controller's and the driver's
limitation (listed below) as well as manual testing.
The ELM327 has two modes:
- Command mode
- Reception mode
In command mode, it expects one command per line, terminated by CR.
By default, the prompt is a "``>``", after which a command can be
entered::
>ATE1
OK
>
The init script in the driver switches off several configuration options
that are only meaningful in the original OBD scenario the chip is meant
for, and are actually a hindrance for can327.
When a command is not recognized, such as by an older version of the
ELM327, a question mark is printed as a response instead of OK::
>ATUNKNOWN
?
>
At present, can327 does not evaluate this response. See the section
below on known limitations for details.
When a CAN frame is to be sent, the target address is configured, after
which the frame is sent as a command that consists of the data's hex
dump::
>ATSH123
OK
>DEADBEEF12345678
OK
>
The above interaction sends the SFF frame "``DE AD BE EF 12 34 56 78``"
with (11 bit) CAN ID ``0x123``.
For this to function, the controller must be configured for SFF sending
mode (using "``AT PB``", see code or datasheet).
Once a frame has been sent and wait-for-reply mode is on (``ATR1``,
configured on ``listen-only=off``), or when the reply timeout expires
and the driver sets the controller into monitoring mode (``ATMA``),
the ELM327 will send one line for each received CAN frame, consisting
of CAN ID, DLC, and data::
123 8 DEADBEEF12345678
For EFF (29 bit) CAN frames, the address format is slightly different,
which can327 uses to tell the two apart::
12 34 56 78 8 DEADBEEF12345678
The ELM327 will receive both SFF and EFF frames - the current CAN
config (``ATPB``) does not matter.
If the ELM327's internal UART sending buffer runs full, it will abort
the monitoring mode, print "BUFFER FULL" and drop back into command
mode. Note that in this case, unlike with other error messages, the
error message may appear on the same line as the last (usually
incomplete) data frame::
12 34 56 78 8 DEADBEEF123 BUFFER FULL
Known limitations of the controller
------------------------------------
- Clone devices ("v1.5" and others)
Sending RTR frames is not supported and will be dropped silently.
Receiving RTR with DLC 8 will appear to be a regular frame with
the last received frame's DLC and payload.
"``AT CSM``" (CAN Silent Monitoring, i.e. don't send CAN ACKs) is
not supported, and is hard coded to ON. Thus, frames are not ACKed
while listening: "``AT MA``" (Monitor All) will always be "silent".
However, immediately after sending a frame, the ELM327 will be in
"receive reply" mode, in which it *does* ACK any received frames.
Once the bus goes silent, or an error occurs (such as BUFFER FULL),
or the receive reply timeout runs out, the ELM327 will end reply
reception mode on its own and can327 will fall back to "``AT MA``"
in order to keep monitoring the bus.
Other limitations may apply, depending on the clone and the quality
of its firmware.
- All versions
No full duplex operation is supported. The driver will switch
between input/output mode as quickly as possible.
The length of outgoing RTR frames cannot be set. In fact, some
clones (tested with one identifying as "``v1.5``") are unable to
send RTR frames at all.
We don't have a way to get real-time notifications on CAN errors.
While there is a command (``AT CS``) to retrieve some basic stats,
we don't poll it as it would force us to interrupt reception mode.
- Versions prior to 1.4b
These versions do not send CAN ACKs when in monitoring mode (AT MA).
However, they do send ACKs while waiting for a reply immediately
after sending a frame. The driver maximizes this time to make the
controller as useful as possible.
Starting with version 1.4b, the ELM327 supports the "``AT CSM``"
command, and the "listen-only" CAN option will take effect.
- Versions prior to 1.4
These chips do not support the "``AT PB``" command, and thus cannot
change bitrate or SFF/EFF mode on-the-fly. This will have to be
programmed by the user before attaching the line discipline. See the
data sheet for details.
- Versions prior to 1.3
These chips cannot be used at all with can327. They do not support
the "``AT D1``" command, which is necessary to avoid parsing conflicts
on incoming data, as well as distinction of RTR frame lengths.
Specifically, this allows for easy distinction of SFF and EFF
frames, and to check whether frames are complete. While it is possible
to deduce the type and length from the length of the line the ELM327
sends us, this method fails when the ELM327's UART output buffer
overruns. It may abort sending in the middle of the line, which will
then be mistaken for something else.
Known limitations of the driver
--------------------------------
- No 8/7 timing.
ELM327 can only set CAN bitrates that are of the form 500000/n, where
n is an integer divisor.
However there is an exception: With a separate flag, it may set the
speed to be 8/7 of the speed indicated by the divisor.
This mode is not currently implemented.
- No evaluation of command responses.
The ELM327 will reply with OK when a command is understood, and with ?
when it is not. The driver does not currently check this, and simply
assumes that the chip understands every command.
The driver is built such that functionality degrades gracefully
nevertheless. See the section on known limitations of the controller.
- No use of hardware CAN ID filtering
An ELM327's UART sending buffer will easily overflow on heavy CAN bus
load, resulting in the "``BUFFER FULL``" message. Using the hardware
filters available through "``AT CF xxx``" and "``AT CM xxx``" would be
helpful here, however SocketCAN does not currently provide a facility
to make use of such hardware features.
Rationale behind the chosen configuration
------------------------------------------
``AT E1``
Echo on
We need this to be able to get a prompt reliably.
``AT S1``
Spaces on
We need this to distinguish 11/29 bit CAN addresses received.
Note:
We can usually do this using the line length (odd/even),
but this fails if the line is not transmitted fully to
the host (BUFFER FULL).
``AT D1``
DLC on
We need this to tell the "length" of RTR frames.
A note on CAN bus termination
------------------------------
Your adapter may have resistors soldered in which are meant to terminate
the bus. This is correct when it is plugged into a OBD-II socket, but
not helpful when trying to tap into the middle of an existing CAN bus.
If communications don't work with the adapter connected, check for the
termination resistors on its PCB and try removing them.

View File

@ -10,6 +10,7 @@ Contents:
.. toctree::
:maxdepth: 2
can327
ctu/ctucanfd-driver
freescale/flexcan

View File

@ -42,7 +42,6 @@ Contents:
mellanox/mlx5
microsoft/netvsc
neterion/s2io
neterion/vxge
netronome/nfp
pensando/ionic
smsc/smc9
@ -52,6 +51,7 @@ Contents:
ti/am65_nuss_cpsw_switchdev
ti/tlan
toshiba/spider_net
wangxun/txgbe
.. only:: subproject and html

View File

@ -901,6 +901,15 @@ To enable/disable UDP Segmentation Offload, issue the following command::
# ethtool -K <ethX> tx-udp-segmentation [off|on]
GNSS module
-----------
Allows user to read messages from the GNSS module and write supported commands.
If the module is physically present, driver creates 2 TTYs for each supported
device in /dev, ttyGNSS_<device>:<function>_0 and _1. First one (_0) is RW and
the second one is RO.
The protocol of write commands is dependent on the GNSS module as the driver
writes raw bytes from the TTY to the GNSS i2c. Please refer to the module
documentation for details.
Performance Optimization
========================

View File

@ -1,115 +0,0 @@
.. SPDX-License-Identifier: GPL-2.0
==============================================================================
Neterion's (Formerly S2io) X3100 Series 10GbE PCIe Server Adapter Linux driver
==============================================================================
.. Contents
1) Introduction
2) Features supported
3) Configurable driver parameters
4) Troubleshooting
1. Introduction
===============
This Linux driver supports all Neterion's X3100 series 10 GbE PCIe I/O
Virtualized Server adapters.
The X3100 series supports four modes of operation, configurable via
firmware:
- Single function mode
- Multi function mode
- SRIOV mode
- MRIOV mode
The functions share a 10GbE link and the pci-e bus, but hardly anything else
inside the ASIC. Features like independent hw reset, statistics, bandwidth/
priority allocation and guarantees, GRO, TSO, interrupt moderation etc are
supported independently on each function.
(See below for a complete list of features supported for both IPv4 and IPv6)
2. Features supported
=====================
i) Single function mode (up to 17 queues)
ii) Multi function mode (up to 17 functions)
iii) PCI-SIG's I/O Virtualization
- Single Root mode: v1.0 (up to 17 functions)
- Multi-Root mode: v1.0 (up to 17 functions)
iv) Jumbo frames
X3100 Series supports MTU up to 9600 bytes, modifiable using
ip command.
v) Offloads supported: (Enabled by default)
- Checksum offload (TCP/UDP/IP) on transmit and receive paths
- TCP Segmentation Offload (TSO) on transmit path
- Generic Receive Offload (GRO) on receive path
vi) MSI-X: (Enabled by default)
Resulting in noticeable performance improvement (up to 7% on certain
platforms).
vii) NAPI: (Enabled by default)
For better Rx interrupt moderation.
viii)RTH (Receive Traffic Hash): (Enabled by default)
Receive side steering for better scaling.
ix) Statistics
Comprehensive MAC-level and software statistics displayed using
"ethtool -S" option.
x) Multiple hardware queues: (Enabled by default)
Up to 17 hardware based transmit and receive data channels, with
multiple steering options (transmit multiqueue enabled by default).
3) Configurable driver parameters:
----------------------------------
i) max_config_dev
Specifies maximum device functions to be enabled.
Valid range: 1-8
ii) max_config_port
Specifies number of ports to be enabled.
Valid range: 1,2
Default: 1
iii) max_config_vpath
Specifies maximum VPATH(s) configured for each device function.
Valid range: 1-17
iv) vlan_tag_strip
Enables/disables vlan tag stripping from all received tagged frames that
are not replicated at the internal L2 switch.
Valid range: 0,1 (disabled, enabled respectively)
Default: 1
v) addr_learn_en
Enable learning the mac address of the guest OS interface in
virtualization environment.
Valid range: 0,1 (disabled, enabled respectively)
Default: 0

View File

@ -0,0 +1,20 @@
.. SPDX-License-Identifier: GPL-2.0
================================================================
Linux Base Driver for WangXun(R) 10 Gigabit PCI Express Adapters
================================================================
WangXun 10 Gigabit Linux driver.
Copyright (c) 2015 - 2022 Beijing WangXun Technology Co., Ltd.
Contents
========
- Support
Support
=======
If you got any problem, contact Wangxun support team via support@trustnetic.com
and Cc: netdev.

View File

@ -0,0 +1,38 @@
.. SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
=================
Devlink Selftests
=================
The ``devlink-selftests`` API allows executing selftests on the device.
Tests Mask
==========
The ``devlink-selftests`` command should be run with a mask indicating
the tests to be executed.
Tests Description
=================
The following is a list of tests that drivers may execute.
.. list-table:: List of tests
:widths: 5 90
* - Name
- Description
* - ``DEVLINK_SELFTEST_FLASH``
- Devices may have the firmware on non-volatile memory on the board, e.g.
flash. This particular test helps to run a flash selftest on the device.
Implementation of the test is left to the driver/firmware.
example usage
-------------
.. code:: shell
# Query selftests supported on the devlink device
$ devlink dev selftests show DEV
# Query selftests supported on all devlink devices
$ devlink dev selftests show
# Executes selftests on the device
$ devlink dev selftests run DEV id flash

View File

@ -38,6 +38,7 @@ general.
devlink-region
devlink-resource
devlink-reload
devlink-selftests
devlink-trap
devlink-linecard

View File

@ -58,6 +58,30 @@ The ``mlxsw`` driver reports the following versions
- running
- Three digit firmware version
Line card auxiliary device info versions
========================================
The ``mlxsw`` driver reports the following versions for line card auxiliary device
.. list-table:: devlink info versions implemented
:widths: 5 5 90
* - Name
- Type
- Description
* - ``hw.revision``
- fixed
- The hardware revision for this line card
* - ``ini.version``
- running
- Version of line card INI loaded
* - ``fw.psid``
- fixed
- Line card device PSID
* - ``fw.version``
- running
- Three digit firmware version of line card device
Driver-specific Traps
=====================

View File

@ -202,6 +202,12 @@ neigh/default/unres_qlen - INTEGER
Default: 101
neigh/default/interval_probe_time_ms - INTEGER
The probe interval for neighbor entries with NTF_MANAGED flag,
the min value is 1.
Default: 5000
mtu_expires - INTEGER
Time, in seconds, that cached PMTU information is kept.
@ -630,6 +636,16 @@ tcp_recovery - INTEGER
Default: 0x1
tcp_reflect_tos - BOOLEAN
For listening sockets, reuse the DSCP value of the initial SYN message
for outgoing packets. This allows to have both directions of a TCP
stream to use the same DSCP value, assuming DSCP remains unchanged for
the lifetime of the connection.
This options affects both IPv4 and IPv6.
Default: 0 (disabled)
tcp_reordering - INTEGER
Initial reordering level of packets in a TCP stream.
TCP stack can then dynamically adjust flow reordering level
@ -1623,12 +1639,15 @@ arp_notify - BOOLEAN
or hardware address changes.
== ==========================================================
arp_accept - BOOLEAN
Define behavior for gratuitous ARP frames who's IP is not
already present in the ARP table:
arp_accept - INTEGER
Define behavior for accepting gratuitous ARP (garp) frames from devices
that are not already present in the ARP table:
- 0 - don't create new entries in the ARP table
- 1 - create new entries in the ARP table
- 2 - create new entries only if the source IP address is in the same
subnet as an address configured on the interface that received the
garp message.
Both replies and requests type gratuitous arp will trigger the
ARP table to be updated, if this setting is on.
@ -2470,27 +2489,36 @@ drop_unsolicited_na - BOOLEAN
By default this is turned off.
accept_untracked_na - BOOLEAN
Add a new neighbour cache entry in STALE state for routers on receiving a
neighbour advertisement (either solicited or unsolicited) with target
link-layer address option specified if no neighbour entry is already
present for the advertised IPv6 address. Without this knob, NAs received
for untracked addresses (absent in neighbour cache) are silently ignored.
accept_untracked_na - INTEGER
Define behavior for accepting neighbor advertisements from devices that
are absent in the neighbor cache:
This is as per router-side behaviour documented in RFC9131.
- 0 - (default) Do not accept unsolicited and untracked neighbor
advertisements.
This has lower precedence than drop_unsolicited_na.
- 1 - Add a new neighbor cache entry in STALE state for routers on
receiving a neighbor advertisement (either solicited or unsolicited)
with target link-layer address option specified if no neighbor entry
is already present for the advertised IPv6 address. Without this knob,
NAs received for untracked addresses (absent in neighbor cache) are
silently ignored.
This will optimize the return path for the initial off-link communication
that is initiated by a directly connected host, by ensuring that
the first-hop router which turns on this setting doesn't have to
buffer the initial return packets to do neighbour-solicitation.
The prerequisite is that the host is configured to send
unsolicited neighbour advertisements on interface bringup.
This setting should be used in conjunction with the ndisc_notify setting
on the host to satisfy this prerequisite.
This is as per router-side behavior documented in RFC9131.
By default this is turned off.
This has lower precedence than drop_unsolicited_na.
This will optimize the return path for the initial off-link
communication that is initiated by a directly connected host, by
ensuring that the first-hop router which turns on this setting doesn't
have to buffer the initial return packets to do neighbor-solicitation.
The prerequisite is that the host is configured to send unsolicited
neighbor advertisements on interface bringup. This setting should be
used in conjunction with the ndisc_notify setting on the host to
satisfy this prerequisite.
- 2 - Extend option (1) to add a new neighbor cache entry only if the
source IP address is in the same subnet as an address configured on
the interface that received the neighbor advertisement.
enhanced_dad - BOOLEAN
Include a nonce option in the IPv6 neighbor solicitation messages used for

View File

@ -203,7 +203,7 @@ this documentation.
The :c:func:`validate` method should mask the supplied supported mask,
and ``state->advertising`` with the supported ethtool link modes.
These are the new ethtool link modes, so bitmask operations must be
used. For an example, see drivers/net/ethernet/marvell/mvneta.c.
used. For an example, see ``drivers/net/ethernet/marvell/mvneta.c``.
The :c:func:`mac_link_state` method is used to read the link state
from the MAC, and report back the settings that the MAC is currently
@ -224,7 +224,7 @@ this documentation.
function should modify the state and only take the link down when
absolutely necessary to change the MAC configuration. An example
of how to do this can be found in :c:func:`mvneta_mac_config` in
drivers/net/ethernet/marvell/mvneta.c.
``drivers/net/ethernet/marvell/mvneta.c``.
For further information on these methods, please see the inline
documentation in :c:type:`struct phylink_mac_ops <phylink_mac_ops>`.
@ -281,4 +281,4 @@ as necessary.
For information describing the SFP cage in DT, please see the binding
documentation in the kernel source tree
``Documentation/devicetree/bindings/net/sff,sfp.txt``
``Documentation/devicetree/bindings/net/sff,sfp.yaml``.

View File

@ -21,3 +21,16 @@ autocorking_size - INTEGER
know how/when to uncork their sockets.
Default: 64K
smcr_buf_type - INTEGER
Controls which type of sndbufs and RMBs to use in later newly created
SMC-R link group. Only for SMC-R.
Default: 0 (physically contiguous sndbufs and RMBs)
Possible values:
- 0 - Use physically contiguous buffers
- 1 - Use virtually contiguous buffers
- 2 - Mixed use of the two types. Try physically contiguous buffers first.
If not available, use virtually contiguous buffers then.

View File

@ -214,6 +214,44 @@ of calling send directly after a handshake using gnutls.
Since it doesn't implement a full record layer, control
messages are not supported.
Optional optimizations
----------------------
There are certain condition-specific optimizations the TLS ULP can make,
if requested. Those optimizations are either not universally beneficial
or may impact correctness, hence they require an opt-in.
All options are set per-socket using setsockopt(), and their
state can be checked using getsockopt() and via socket diag (``ss``).
TLS_TX_ZEROCOPY_RO
~~~~~~~~~~~~~~~~~~
For device offload only. Allow sendfile() data to be transmitted directly
to the NIC without making an in-kernel copy. This allows true zero-copy
behavior when device offload is enabled.
The application must make sure that the data is not modified between being
submitted and transmission completing. In other words this is mostly
applicable if the data sent on a socket via sendfile() is read-only.
Modifying the data may result in different versions of the data being used
for the original TCP transmission and TCP retransmissions. To the receiver
this will look like TLS records had been tampered with and will result
in record authentication failures.
TLS_RX_EXPECT_NO_PAD
~~~~~~~~~~~~~~~~~~~~
TLS 1.3 only. Expect the sender to not pad records. This allows the data
to be decrypted directly into user space buffers with TLS 1.3.
This optimization is safe to enable only if the remote end is trusted,
otherwise it is an attack vector to doubling the TLS processing cost.
If the record decrypted turns out to had been padded or is not a data
record it will be decrypted again into a kernel buffer without zero copy.
Such events are counted in the ``TlsDecryptRetry`` statistic.
Statistics
==========
@ -239,3 +277,12 @@ TLS implementation exposes the following per-namespace statistics
- ``TlsDeviceRxResync`` -
number of RX resyncs sent to NICs handling cryptography
- ``TlsDecryptRetry`` -
number of RX records which had to be re-decrypted due to
``TLS_RX_EXPECT_NO_PAD`` mis-prediction. Note that this counter will
also increment for non-data records.
- ``TlsRxNoPadViolation`` -
number of data RX records which had to be re-decrypted due to
``TLS_RX_EXPECT_NO_PAD`` mis-prediction.

View File

@ -171,7 +171,6 @@ F: drivers/scsi/53c700*
6LOWPAN GENERIC (BTLE/IEEE 802.15.4)
M: Alexander Aring <alex.aring@gmail.com>
M: Jukka Rissanen <jukka.rissanen@linux.intel.com>
L: linux-bluetooth@vger.kernel.org
L: linux-wpan@vger.kernel.org
S: Maintained
@ -7430,6 +7429,13 @@ L: netdev@vger.kernel.org
S: Maintained
F: drivers/net/ethernet/ibm/ehea/
ELM327 CAN NETWORK DRIVER
M: Max Staudt <max@enpas.org>
L: linux-can@vger.kernel.org
S: Maintained
F: Documentation/networking/device_drivers/can/can327.rst
F: drivers/net/can/can327.c
EM28XX VIDEO4LINUX DRIVER
M: Mauro Carvalho Chehab <mchehab@kernel.org>
L: linux-media@vger.kernel.org
@ -7537,6 +7543,13 @@ S: Maintained
F: include/linux/errseq.h
F: lib/errseq.c
ESD CAN/USB DRIVERS
M: Frank Jungclaus <frank.jungclaus@esd.eu>
R: socketcan@esd.eu
L: linux-can@vger.kernel.org
S: Maintained
F: drivers/net/can/usb/esd_usb.c
ET131X NETWORK DRIVER
M: Mark Einon <mark.einon@gmail.com>
S: Odd Fixes
@ -13233,6 +13246,7 @@ M: UNGLinuxDriver@microchip.com
L: netdev@vger.kernel.org
S: Maintained
F: Documentation/devicetree/bindings/net/dsa/microchip,ksz.yaml
F: Documentation/devicetree/bindings/net/dsa/microchip,lan937x.yaml
F: drivers/net/dsa/microchip/*
F: include/linux/platform_data/microchip-ksz.h
F: net/dsa/tag_ksz.c
@ -13896,12 +13910,11 @@ L: netdev@vger.kernel.org
S: Maintained
F: net/sched/sch_netem.c
NETERION 10GbE DRIVERS (s2io/vxge)
NETERION 10GbE DRIVERS (s2io)
M: Jon Mason <jdmason@kudzu.us>
L: netdev@vger.kernel.org
S: Supported
F: Documentation/networking/device_drivers/ethernet/neterion/s2io.rst
F: Documentation/networking/device_drivers/ethernet/neterion/vxge.rst
F: drivers/net/ethernet/neterion/
NETFILTER
@ -17246,6 +17259,19 @@ S: Supported
F: Documentation/devicetree/bindings/iio/adc/renesas,rzg2l-adc.yaml
F: drivers/iio/adc/rzg2l_adc.c
RENESAS RZ/N1 A5PSW SWITCH DRIVER
M: Clément Léger <clement.leger@bootlin.com>
L: linux-renesas-soc@vger.kernel.org
L: netdev@vger.kernel.org
S: Maintained
F: Documentation/devicetree/bindings/net/dsa/renesas,rzn1-a5psw.yaml
F: Documentation/devicetree/bindings/net/pcs/renesas,rzn1-miic.yaml
F: drivers/net/dsa/rzn1_a5psw*
F: drivers/net/pcs/pcs-rzn1-miic.c
F: include/dt-bindings/net/pcs-rzn1-miic.h
F: include/linux/pcs-rzn1-miic.h
F: net/dsa/tag_rzn1_a5psw.c
RENESAS RZ/N1 RTC CONTROLLER DRIVER
M: Miquel Raynal <miquel.raynal@bootlin.com>
L: linux-rtc@vger.kernel.org
@ -18230,6 +18256,7 @@ SFF/SFP/SFP+ MODULE SUPPORT
M: Russell King <linux@armlinux.org.uk>
L: netdev@vger.kernel.org
S: Maintained
F: Documentation/devicetree/bindings/net/sff,sfp.yaml
F: drivers/net/phy/phylink.c
F: drivers/net/phy/sfp*
F: include/linux/mdio/mdio-i2c.h
@ -18516,6 +18543,12 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/git/vbabka/slab.git
F: include/linux/sl?b*.h
F: mm/sl?b*
SLCAN CAN NETWORK DRIVER
M: Dario Binacchi <dario.binacchi@amarulasolutions.com>
L: linux-can@vger.kernel.org
S: Maintained
F: drivers/net/can/slcan/
SLEEPABLE READ-COPY UPDATE (SRCU)
M: Lai Jiangshan <jiangshanlai@gmail.com>
M: "Paul E. McKenney" <paulmck@kernel.org>
@ -21642,6 +21675,13 @@ L: linux-input@vger.kernel.org
S: Maintained
F: drivers/input/tablet/wacom_serial4.c
WANGXUN ETHERNET DRIVER
M: Jiawen Wu <jiawenwu@trustnetic.com>
L: netdev@vger.kernel.org
S: Maintained
F: Documentation/networking/device_drivers/ethernet/wangxun/txgbe.rst
F: drivers/net/ethernet/wangxun/
WATCHDOG DEVICE DRIVERS
M: Wim Van Sebroeck <wim@linux-watchdog.org>
M: Guenter Roeck <linux@roeck-us.net>
@ -21958,8 +21998,7 @@ F: include/uapi/linux/if_xdp.h
F: include/uapi/linux/xdp_diag.h
F: include/net/netns/xdp.h
F: net/xdp/
F: samples/bpf/xdpsock*
F: tools/lib/bpf/xsk*
F: tools/testing/selftests/bpf/*xsk*
XEN BLOCK SUBSYSTEM
M: Roger Pau Monné <roger.pau@citrix.com>

View File

@ -712,22 +712,6 @@ static inline void emit_alu_r(const u8 dst, const u8 src, const bool is64,
}
}
/* ALU operation (32 bit)
* dst = dst (op) src
*/
static inline void emit_a32_alu_r(const s8 dst, const s8 src,
struct jit_ctx *ctx, const bool is64,
const bool hi, const u8 op) {
const s8 *tmp = bpf2a32[TMP_REG_1];
s8 rn, rd;
rn = arm_bpf_get_reg32(src, tmp[1], ctx);
rd = arm_bpf_get_reg32(dst, tmp[0], ctx);
/* ALU operation */
emit_alu_r(rd, rn, is64, hi, op, ctx);
arm_bpf_put_reg32(dst, rd, ctx);
}
/* ALU operation (64 bit) */
static inline void emit_a32_alu_r64(const bool is64, const s8 dst[],
const s8 src[], struct jit_ctx *ctx,

View File

@ -34,28 +34,28 @@
sfp0: sfp-0 {
compatible = "sff,sfp";
i2c-bus = <&sfp0_i2c>;
mod-def0-gpio = <&gpio2 0 GPIO_ACTIVE_LOW>;
mod-def0-gpios = <&gpio2 0 GPIO_ACTIVE_LOW>;
maximum-power-milliwatt = <2000>;
};
sfp1: sfp-1 {
compatible = "sff,sfp";
i2c-bus = <&sfp1_i2c>;
mod-def0-gpio = <&gpio2 9 GPIO_ACTIVE_LOW>;
mod-def0-gpios = <&gpio2 9 GPIO_ACTIVE_LOW>;
maximum-power-milliwatt = <2000>;
};
sfp2: sfp-2 {
compatible = "sff,sfp";
i2c-bus = <&sfp2_i2c>;
mod-def0-gpio = <&gpio2 10 GPIO_ACTIVE_LOW>;
mod-def0-gpios = <&gpio2 10 GPIO_ACTIVE_LOW>;
maximum-power-milliwatt = <2000>;
};
sfp3: sfp-3 {
compatible = "sff,sfp";
i2c-bus = <&sfp3_i2c>;
mod-def0-gpio = <&gpio2 11 GPIO_ACTIVE_LOW>;
mod-def0-gpios = <&gpio2 11 GPIO_ACTIVE_LOW>;
maximum-power-milliwatt = <2000>;
};
};

View File

@ -100,11 +100,11 @@
sfp: sfp {
compatible = "sff,sfp";
i2c-bus = <&i2c0>;
los-gpio = <&moxtet_sfp 0 GPIO_ACTIVE_HIGH>;
tx-fault-gpio = <&moxtet_sfp 1 GPIO_ACTIVE_HIGH>;
mod-def0-gpio = <&moxtet_sfp 2 GPIO_ACTIVE_LOW>;
tx-disable-gpio = <&moxtet_sfp 4 GPIO_ACTIVE_HIGH>;
rate-select0-gpio = <&moxtet_sfp 5 GPIO_ACTIVE_HIGH>;
los-gpios = <&moxtet_sfp 0 GPIO_ACTIVE_HIGH>;
tx-fault-gpios = <&moxtet_sfp 1 GPIO_ACTIVE_HIGH>;
mod-def0-gpios = <&moxtet_sfp 2 GPIO_ACTIVE_LOW>;
tx-disable-gpios = <&moxtet_sfp 4 GPIO_ACTIVE_HIGH>;
rate-select0-gpios = <&moxtet_sfp 5 GPIO_ACTIVE_HIGH>;
maximum-power-milliwatt = <3000>;
/* enabled by U-Boot if SFP module is present */

View File

@ -65,20 +65,20 @@
sfp_eth0: sfp-eth0 {
compatible = "sff,sfp";
i2c-bus = <&i2c0>;
los-gpio = <&gpiosb 2 GPIO_ACTIVE_HIGH>;
mod-def0-gpio = <&gpiosb 3 GPIO_ACTIVE_LOW>;
tx-disable-gpio = <&gpiosb 4 GPIO_ACTIVE_HIGH>;
tx-fault-gpio = <&gpiosb 5 GPIO_ACTIVE_HIGH>;
los-gpios = <&gpiosb 2 GPIO_ACTIVE_HIGH>;
mod-def0-gpios = <&gpiosb 3 GPIO_ACTIVE_LOW>;
tx-disable-gpios = <&gpiosb 4 GPIO_ACTIVE_HIGH>;
tx-fault-gpios = <&gpiosb 5 GPIO_ACTIVE_HIGH>;
maximum-power-milliwatt = <3000>;
};
sfp_eth1: sfp-eth1 {
compatible = "sff,sfp";
i2c-bus = <&i2c1>;
los-gpio = <&gpiosb 7 GPIO_ACTIVE_HIGH>;
mod-def0-gpio = <&gpiosb 8 GPIO_ACTIVE_LOW>;
tx-disable-gpio = <&gpiosb 9 GPIO_ACTIVE_HIGH>;
tx-fault-gpio = <&gpiosb 10 GPIO_ACTIVE_HIGH>;
los-gpios = <&gpiosb 7 GPIO_ACTIVE_HIGH>;
mod-def0-gpios = <&gpiosb 8 GPIO_ACTIVE_LOW>;
tx-disable-gpios = <&gpiosb 9 GPIO_ACTIVE_HIGH>;
tx-fault-gpios = <&gpiosb 10 GPIO_ACTIVE_HIGH>;
maximum-power-milliwatt = <3000>;
};
};

View File

@ -34,20 +34,20 @@
sfp_eth0: sfp-eth0 {
compatible = "sff,sfp";
i2c-bus = <&cp0_i2c1>;
los-gpio = <&sfp_gpio 3 GPIO_ACTIVE_HIGH>;
mod-def0-gpio = <&sfp_gpio 2 GPIO_ACTIVE_LOW>;
tx-disable-gpio = <&sfp_gpio 1 GPIO_ACTIVE_HIGH>;
tx-fault-gpio = <&sfp_gpio 0 GPIO_ACTIVE_HIGH>;
los-gpios = <&sfp_gpio 3 GPIO_ACTIVE_HIGH>;
mod-def0-gpios = <&sfp_gpio 2 GPIO_ACTIVE_LOW>;
tx-disable-gpios = <&sfp_gpio 1 GPIO_ACTIVE_HIGH>;
tx-fault-gpios = <&sfp_gpio 0 GPIO_ACTIVE_HIGH>;
};
/* SFP 1G */
sfp_eth2: sfp-eth2 {
compatible = "sff,sfp";
i2c-bus = <&cp0_i2c0>;
los-gpio = <&sfp_gpio 7 GPIO_ACTIVE_HIGH>;
mod-def0-gpio = <&sfp_gpio 6 GPIO_ACTIVE_LOW>;
tx-disable-gpio = <&sfp_gpio 5 GPIO_ACTIVE_HIGH>;
tx-fault-gpio = <&sfp_gpio 4 GPIO_ACTIVE_HIGH>;
los-gpios = <&sfp_gpio 7 GPIO_ACTIVE_HIGH>;
mod-def0-gpios = <&sfp_gpio 6 GPIO_ACTIVE_LOW>;
tx-disable-gpios = <&sfp_gpio 5 GPIO_ACTIVE_HIGH>;
tx-fault-gpios = <&sfp_gpio 4 GPIO_ACTIVE_HIGH>;
};
};

View File

@ -64,8 +64,8 @@
sfp_cp0_eth0: sfp-cp0-eth0 {
compatible = "sff,sfp";
i2c-bus = <&cp0_i2c1>;
mod-def0-gpio = <&cp0_gpio2 17 GPIO_ACTIVE_LOW>;
tx-disable-gpio = <&cp1_gpio1 29 GPIO_ACTIVE_HIGH>;
mod-def0-gpios = <&cp0_gpio2 17 GPIO_ACTIVE_LOW>;
tx-disable-gpios = <&cp1_gpio1 29 GPIO_ACTIVE_HIGH>;
pinctrl-names = "default";
pinctrl-0 = <&cp0_sfp_present_pins &cp1_sfp_tx_disable_pins>;
maximum-power-milliwatt = <2000>;

View File

@ -65,10 +65,10 @@
/* CON15,16 - CPM lane 4 */
compatible = "sff,sfp";
i2c-bus = <&sfpp0_i2c>;
los-gpio = <&cp1_gpio1 28 GPIO_ACTIVE_HIGH>;
mod-def0-gpio = <&cp1_gpio1 27 GPIO_ACTIVE_LOW>;
tx-disable-gpio = <&cp1_gpio1 29 GPIO_ACTIVE_HIGH>;
tx-fault-gpio = <&cp1_gpio1 26 GPIO_ACTIVE_HIGH>;
los-gpios = <&cp1_gpio1 28 GPIO_ACTIVE_HIGH>;
mod-def0-gpios = <&cp1_gpio1 27 GPIO_ACTIVE_LOW>;
tx-disable-gpios = <&cp1_gpio1 29 GPIO_ACTIVE_HIGH>;
tx-fault-gpios = <&cp1_gpio1 26 GPIO_ACTIVE_HIGH>;
pinctrl-names = "default";
pinctrl-0 = <&cp1_sfpp0_pins>;
maximum-power-milliwatt = <2000>;
@ -78,10 +78,10 @@
/* CON17,18 - CPS lane 4 */
compatible = "sff,sfp";
i2c-bus = <&sfpp1_i2c>;
los-gpio = <&cp1_gpio1 8 GPIO_ACTIVE_HIGH>;
mod-def0-gpio = <&cp1_gpio1 11 GPIO_ACTIVE_LOW>;
tx-disable-gpio = <&cp1_gpio1 10 GPIO_ACTIVE_HIGH>;
tx-fault-gpio = <&cp0_gpio2 30 GPIO_ACTIVE_HIGH>;
los-gpios = <&cp1_gpio1 8 GPIO_ACTIVE_HIGH>;
mod-def0-gpios = <&cp1_gpio1 11 GPIO_ACTIVE_LOW>;
tx-disable-gpios = <&cp1_gpio1 10 GPIO_ACTIVE_HIGH>;
tx-fault-gpios = <&cp0_gpio2 30 GPIO_ACTIVE_HIGH>;
pinctrl-names = "default";
pinctrl-0 = <&cp1_sfpp1_pins &cp0_sfpp1_pins>;
maximum-power-milliwatt = <2000>;
@ -91,10 +91,10 @@
/* CON13,14 - CPS lane 5 */
compatible = "sff,sfp";
i2c-bus = <&sfp_1g_i2c>;
los-gpio = <&cp0_gpio2 22 GPIO_ACTIVE_HIGH>;
mod-def0-gpio = <&cp0_gpio2 21 GPIO_ACTIVE_LOW>;
tx-disable-gpio = <&cp1_gpio1 24 GPIO_ACTIVE_HIGH>;
tx-fault-gpio = <&cp0_gpio2 19 GPIO_ACTIVE_HIGH>;
los-gpios = <&cp0_gpio2 22 GPIO_ACTIVE_HIGH>;
mod-def0-gpios = <&cp0_gpio2 21 GPIO_ACTIVE_LOW>;
tx-disable-gpios = <&cp1_gpio1 24 GPIO_ACTIVE_HIGH>;
tx-fault-gpios = <&cp0_gpio2 19 GPIO_ACTIVE_HIGH>;
pinctrl-names = "default";
pinctrl-0 = <&cp0_sfp_1g_pins &cp1_sfp_1g_pins>;
maximum-power-milliwatt = <2000>;

View File

@ -67,20 +67,20 @@
sfp_cp0_eth0: sfp-cp0-eth0 {
compatible = "sff,sfp";
i2c-bus = <&sfpplus0_i2c>;
los-gpio = <&sfpplus_gpio 11 GPIO_ACTIVE_HIGH>;
mod-def0-gpio = <&sfpplus_gpio 10 GPIO_ACTIVE_LOW>;
tx-disable-gpio = <&sfpplus_gpio 9 GPIO_ACTIVE_HIGH>;
tx-fault-gpio = <&sfpplus_gpio 8 GPIO_ACTIVE_HIGH>;
los-gpios = <&sfpplus_gpio 11 GPIO_ACTIVE_HIGH>;
mod-def0-gpios = <&sfpplus_gpio 10 GPIO_ACTIVE_LOW>;
tx-disable-gpios = <&sfpplus_gpio 9 GPIO_ACTIVE_HIGH>;
tx-fault-gpios = <&sfpplus_gpio 8 GPIO_ACTIVE_HIGH>;
maximum-power-milliwatt = <3000>;
};
sfp_cp1_eth0: sfp-cp1-eth0 {
compatible = "sff,sfp";
i2c-bus = <&sfpplus1_i2c>;
los-gpio = <&sfpplus_gpio 3 GPIO_ACTIVE_HIGH>;
mod-def0-gpio = <&sfpplus_gpio 2 GPIO_ACTIVE_LOW>;
tx-disable-gpio = <&sfpplus_gpio 1 GPIO_ACTIVE_HIGH>;
tx-fault-gpio = <&sfpplus_gpio 0 GPIO_ACTIVE_HIGH>;
los-gpios = <&sfpplus_gpio 3 GPIO_ACTIVE_HIGH>;
mod-def0-gpios = <&sfpplus_gpio 2 GPIO_ACTIVE_LOW>;
tx-disable-gpios = <&sfpplus_gpio 1 GPIO_ACTIVE_HIGH>;
tx-fault-gpios = <&sfpplus_gpio 0 GPIO_ACTIVE_HIGH>;
maximum-power-milliwatt = <3000>;
};

View File

@ -78,9 +78,9 @@
compatible = "sff,sfp";
i2c-bus = <&cp0_i2c1>;
mod-def0-gpios = <&expander0 3 GPIO_ACTIVE_LOW>;
los-gpio = <&expander0 15 GPIO_ACTIVE_HIGH>;
tx-disable-gpio = <&expander0 2 GPIO_ACTIVE_HIGH>;
tx-fault-gpio = <&cp0_gpio1 24 GPIO_ACTIVE_HIGH>;
los-gpios = <&expander0 15 GPIO_ACTIVE_HIGH>;
tx-disable-gpios = <&expander0 2 GPIO_ACTIVE_HIGH>;
tx-fault-gpios = <&cp0_gpio1 24 GPIO_ACTIVE_HIGH>;
maximum-power-milliwatt = <3000>;
status = "okay";
};

View File

@ -90,10 +90,10 @@
cp0_sfp_eth0: sfp-eth@0 {
compatible = "sff,sfp";
i2c-bus = <&cp0_sfpp0_i2c>;
los-gpio = <&cp0_module_expander1 11 GPIO_ACTIVE_HIGH>;
mod-def0-gpio = <&cp0_module_expander1 10 GPIO_ACTIVE_LOW>;
tx-disable-gpio = <&cp0_module_expander1 9 GPIO_ACTIVE_HIGH>;
tx-fault-gpio = <&cp0_module_expander1 8 GPIO_ACTIVE_HIGH>;
los-gpios = <&cp0_module_expander1 11 GPIO_ACTIVE_HIGH>;
mod-def0-gpios = <&cp0_module_expander1 10 GPIO_ACTIVE_LOW>;
tx-disable-gpios = <&cp0_module_expander1 9 GPIO_ACTIVE_HIGH>;
tx-fault-gpios = <&cp0_module_expander1 8 GPIO_ACTIVE_HIGH>;
/*
* SFP cages are unconnected on early PCBs because of an the I2C
* lanes not being connected. Prevent the port for being

View File

@ -37,10 +37,10 @@
cp1_sfp_eth1: sfp-eth1 {
compatible = "sff,sfp";
i2c-bus = <&cp1_i2c0>;
los-gpio = <&cp1_gpio1 11 GPIO_ACTIVE_HIGH>;
mod-def0-gpio = <&cp1_gpio1 10 GPIO_ACTIVE_LOW>;
tx-disable-gpio = <&cp1_gpio1 9 GPIO_ACTIVE_HIGH>;
tx-fault-gpio = <&cp1_gpio1 8 GPIO_ACTIVE_HIGH>;
los-gpios = <&cp1_gpio1 11 GPIO_ACTIVE_HIGH>;
mod-def0-gpios = <&cp1_gpio1 10 GPIO_ACTIVE_LOW>;
tx-disable-gpios = <&cp1_gpio1 9 GPIO_ACTIVE_HIGH>;
tx-fault-gpios = <&cp1_gpio1 8 GPIO_ACTIVE_HIGH>;
pinctrl-names = "default";
pinctrl-0 = <&cp1_sfp_pins>;
/*

View File

@ -57,10 +57,10 @@
cp2_sfp_eth0: sfp-eth0 {
compatible = "sff,sfp";
i2c-bus = <&cp2_sfpp0_i2c>;
los-gpio = <&cp2_module_expander1 11 GPIO_ACTIVE_HIGH>;
mod-def0-gpio = <&cp2_module_expander1 10 GPIO_ACTIVE_LOW>;
tx-disable-gpio = <&cp2_module_expander1 9 GPIO_ACTIVE_HIGH>;
tx-fault-gpio = <&cp2_module_expander1 8 GPIO_ACTIVE_HIGH>;
los-gpios = <&cp2_module_expander1 11 GPIO_ACTIVE_HIGH>;
mod-def0-gpios = <&cp2_module_expander1 10 GPIO_ACTIVE_LOW>;
tx-disable-gpios = <&cp2_module_expander1 9 GPIO_ACTIVE_HIGH>;
tx-fault-gpios = <&cp2_module_expander1 8 GPIO_ACTIVE_HIGH>;
/*
* SFP cages are unconnected on early PCBs because of an the I2C
* lanes not being connected. Prevent the port for being

View File

@ -458,6 +458,54 @@
status = "okay";
};
&mdio0 {
#address-cells = <1>;
#size-cells = <0>;
switch@0 {
compatible = "mediatek,mt7531";
reg = <0>;
ports {
#address-cells = <1>;
#size-cells = <0>;
port@1 {
reg = <1>;
label = "lan0";
};
port@2 {
reg = <2>;
label = "lan1";
};
port@3 {
reg = <3>;
label = "lan2";
};
port@4 {
reg = <4>;
label = "lan3";
};
port@5 {
reg = <5>;
label = "cpu";
ethernet = <&gmac0>;
phy-mode = "rgmii";
fixed-link {
speed = <1000>;
full-duplex;
pause;
};
};
};
};
};
&mdio1 {
rgmii_phy1: ethernet-phy@0 {
compatible = "ethernet-phy-ieee802.3-c22";

View File

@ -510,6 +510,9 @@ u32 aarch64_insn_gen_load_store_imm(enum aarch64_insn_register reg,
unsigned int imm,
enum aarch64_insn_size_type size,
enum aarch64_insn_ldst_type type);
u32 aarch64_insn_gen_load_literal(unsigned long pc, unsigned long addr,
enum aarch64_insn_register reg,
bool is64bit);
u32 aarch64_insn_gen_load_store_pair(enum aarch64_insn_register reg1,
enum aarch64_insn_register reg2,
enum aarch64_insn_register base,

View File

@ -323,7 +323,7 @@ static u32 aarch64_insn_encode_ldst_size(enum aarch64_insn_size_type type,
return insn;
}
static inline long branch_imm_common(unsigned long pc, unsigned long addr,
static inline long label_imm_common(unsigned long pc, unsigned long addr,
long range)
{
long offset;
@ -354,7 +354,7 @@ u32 __kprobes aarch64_insn_gen_branch_imm(unsigned long pc, unsigned long addr,
* ARM64 virtual address arrangement guarantees all kernel and module
* texts are within +/-128M.
*/
offset = branch_imm_common(pc, addr, SZ_128M);
offset = label_imm_common(pc, addr, SZ_128M);
if (offset >= SZ_128M)
return AARCH64_BREAK_FAULT;
@ -382,7 +382,7 @@ u32 aarch64_insn_gen_comp_branch_imm(unsigned long pc, unsigned long addr,
u32 insn;
long offset;
offset = branch_imm_common(pc, addr, SZ_1M);
offset = label_imm_common(pc, addr, SZ_1M);
if (offset >= SZ_1M)
return AARCH64_BREAK_FAULT;
@ -421,7 +421,7 @@ u32 aarch64_insn_gen_cond_branch_imm(unsigned long pc, unsigned long addr,
u32 insn;
long offset;
offset = branch_imm_common(pc, addr, SZ_1M);
offset = label_imm_common(pc, addr, SZ_1M);
insn = aarch64_insn_get_bcond_value();
@ -543,6 +543,28 @@ u32 aarch64_insn_gen_load_store_imm(enum aarch64_insn_register reg,
return aarch64_insn_encode_immediate(AARCH64_INSN_IMM_12, insn, imm);
}
u32 aarch64_insn_gen_load_literal(unsigned long pc, unsigned long addr,
enum aarch64_insn_register reg,
bool is64bit)
{
u32 insn;
long offset;
offset = label_imm_common(pc, addr, SZ_1M);
if (offset >= SZ_1M)
return AARCH64_BREAK_FAULT;
insn = aarch64_insn_get_ldr_lit_value();
if (is64bit)
insn |= BIT(30);
insn = aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RT, insn, reg);
return aarch64_insn_encode_immediate(AARCH64_INSN_IMM_19, insn,
offset >> 2);
}
u32 aarch64_insn_gen_load_store_pair(enum aarch64_insn_register reg1,
enum aarch64_insn_register reg2,
enum aarch64_insn_register base,

View File

@ -80,6 +80,12 @@
#define A64_STR64I(Xt, Xn, imm) A64_LS_IMM(Xt, Xn, imm, 64, STORE)
#define A64_LDR64I(Xt, Xn, imm) A64_LS_IMM(Xt, Xn, imm, 64, LOAD)
/* LDR (literal) */
#define A64_LDR32LIT(Wt, offset) \
aarch64_insn_gen_load_literal(0, offset, Wt, false)
#define A64_LDR64LIT(Xt, offset) \
aarch64_insn_gen_load_literal(0, offset, Xt, true)
/* Load/store register pair */
#define A64_LS_PAIR(Rt, Rt2, Rn, offset, ls, type) \
aarch64_insn_gen_load_store_pair(Rt, Rt2, Rn, offset, \
@ -270,6 +276,7 @@
#define A64_BTI_C A64_HINT(AARCH64_INSN_HINT_BTIC)
#define A64_BTI_J A64_HINT(AARCH64_INSN_HINT_BTIJ)
#define A64_BTI_JC A64_HINT(AARCH64_INSN_HINT_BTIJC)
#define A64_NOP A64_HINT(AARCH64_INSN_HINT_NOP)
/* DMB */
#define A64_DMB_ISH aarch64_insn_gen_dmb(AARCH64_INSN_MB_ISH)

View File

@ -10,6 +10,7 @@
#include <linux/bitfield.h>
#include <linux/bpf.h>
#include <linux/filter.h>
#include <linux/memory.h>
#include <linux/printk.h>
#include <linux/slab.h>
@ -18,6 +19,7 @@
#include <asm/cacheflush.h>
#include <asm/debug-monitors.h>
#include <asm/insn.h>
#include <asm/patching.h>
#include <asm/set_memory.h>
#include "bpf_jit.h"
@ -78,6 +80,15 @@ struct jit_ctx {
int fpb_offset;
};
struct bpf_plt {
u32 insn_ldr; /* load target */
u32 insn_br; /* branch to target */
u64 target; /* target value */
};
#define PLT_TARGET_SIZE sizeof_field(struct bpf_plt, target)
#define PLT_TARGET_OFFSET offsetof(struct bpf_plt, target)
static inline void emit(const u32 insn, struct jit_ctx *ctx)
{
if (ctx->image != NULL)
@ -140,6 +151,12 @@ static inline void emit_a64_mov_i64(const int reg, const u64 val,
}
}
static inline void emit_bti(u32 insn, struct jit_ctx *ctx)
{
if (IS_ENABLED(CONFIG_ARM64_BTI_KERNEL))
emit(insn, ctx);
}
/*
* Kernel addresses in the vmalloc space use at most 48 bits, and the
* remaining bits are guaranteed to be 0x1. So we can compose the address
@ -159,6 +176,14 @@ static inline void emit_addr_mov_i64(const int reg, const u64 val,
}
}
static inline void emit_call(u64 target, struct jit_ctx *ctx)
{
u8 tmp = bpf2a64[TMP_REG_1];
emit_addr_mov_i64(tmp, target, ctx);
emit(A64_BLR(tmp), ctx);
}
static inline int bpf2a64_offset(int bpf_insn, int off,
const struct jit_ctx *ctx)
{
@ -235,17 +260,35 @@ static bool is_lsi_offset(int offset, int scale)
return true;
}
/* generated prologue:
* bti c // if CONFIG_ARM64_BTI_KERNEL
* mov x9, lr
* nop // POKE_OFFSET
* paciasp // if CONFIG_ARM64_PTR_AUTH_KERNEL
* stp x29, lr, [sp, #-16]!
* mov x29, sp
* stp x19, x20, [sp, #-16]!
* stp x21, x22, [sp, #-16]!
* stp x25, x26, [sp, #-16]!
* stp x27, x28, [sp, #-16]!
* mov x25, sp
* mov tcc, #0
* // PROLOGUE_OFFSET
*/
#define BTI_INSNS (IS_ENABLED(CONFIG_ARM64_BTI_KERNEL) ? 1 : 0)
#define PAC_INSNS (IS_ENABLED(CONFIG_ARM64_PTR_AUTH_KERNEL) ? 1 : 0)
/* Offset of nop instruction in bpf prog entry to be poked */
#define POKE_OFFSET (BTI_INSNS + 1)
/* Tail call offset to jump into */
#if IS_ENABLED(CONFIG_ARM64_BTI_KERNEL) || \
IS_ENABLED(CONFIG_ARM64_PTR_AUTH_KERNEL)
#define PROLOGUE_OFFSET 9
#else
#define PROLOGUE_OFFSET 8
#endif
#define PROLOGUE_OFFSET (BTI_INSNS + 2 + PAC_INSNS + 8)
static int build_prologue(struct jit_ctx *ctx, bool ebpf_from_cbpf)
{
const struct bpf_prog *prog = ctx->prog;
const bool is_main_prog = prog->aux->func_idx == 0;
const u8 r6 = bpf2a64[BPF_REG_6];
const u8 r7 = bpf2a64[BPF_REG_7];
const u8 r8 = bpf2a64[BPF_REG_8];
@ -279,12 +322,14 @@ static int build_prologue(struct jit_ctx *ctx, bool ebpf_from_cbpf)
*
*/
emit_bti(A64_BTI_C, ctx);
emit(A64_MOV(1, A64_R(9), A64_LR), ctx);
emit(A64_NOP, ctx);
/* Sign lr */
if (IS_ENABLED(CONFIG_ARM64_PTR_AUTH_KERNEL))
emit(A64_PACIASP, ctx);
/* BTI landing pad */
else if (IS_ENABLED(CONFIG_ARM64_BTI_KERNEL))
emit(A64_BTI_C, ctx);
/* Save FP and LR registers to stay align with ARM64 AAPCS */
emit(A64_PUSH(A64_FP, A64_LR, A64_SP), ctx);
@ -299,7 +344,7 @@ static int build_prologue(struct jit_ctx *ctx, bool ebpf_from_cbpf)
/* Set up BPF prog stack base register */
emit(A64_MOV(1, fp, A64_SP), ctx);
if (!ebpf_from_cbpf) {
if (!ebpf_from_cbpf && is_main_prog) {
/* Initialize tail_call_cnt */
emit(A64_MOVZ(1, tcc, 0, 0), ctx);
@ -311,8 +356,7 @@ static int build_prologue(struct jit_ctx *ctx, bool ebpf_from_cbpf)
}
/* BTI landing pad for the tail call, done with a BR */
if (IS_ENABLED(CONFIG_ARM64_BTI_KERNEL))
emit(A64_BTI_J, ctx);
emit_bti(A64_BTI_J, ctx);
}
emit(A64_SUB_I(1, fpb, fp, ctx->fpb_offset), ctx);
@ -556,6 +600,53 @@ static int emit_ll_sc_atomic(const struct bpf_insn *insn, struct jit_ctx *ctx)
return 0;
}
void dummy_tramp(void);
asm (
" .pushsection .text, \"ax\", @progbits\n"
" .global dummy_tramp\n"
" .type dummy_tramp, %function\n"
"dummy_tramp:"
#if IS_ENABLED(CONFIG_ARM64_BTI_KERNEL)
" bti j\n" /* dummy_tramp is called via "br x10" */
#endif
" mov x10, x30\n"
" mov x30, x9\n"
" ret x10\n"
" .size dummy_tramp, .-dummy_tramp\n"
" .popsection\n"
);
/* build a plt initialized like this:
*
* plt:
* ldr tmp, target
* br tmp
* target:
* .quad dummy_tramp
*
* when a long jump trampoline is attached, target is filled with the
* trampoline address, and when the trampoline is removed, target is
* restored to dummy_tramp address.
*/
static void build_plt(struct jit_ctx *ctx)
{
const u8 tmp = bpf2a64[TMP_REG_1];
struct bpf_plt *plt = NULL;
/* make sure target is 64-bit aligned */
if ((ctx->idx + PLT_TARGET_OFFSET / AARCH64_INSN_SIZE) % 2)
emit(A64_NOP, ctx);
plt = (struct bpf_plt *)(ctx->image + ctx->idx);
/* plt is called via bl, no BTI needed here */
emit(A64_LDR64LIT(tmp, 2 * AARCH64_INSN_SIZE), ctx);
emit(A64_BR(tmp), ctx);
if (ctx->image)
plt->target = (u64)&dummy_tramp;
}
static void build_epilogue(struct jit_ctx *ctx)
{
const u8 r0 = bpf2a64[BPF_REG_0];
@ -990,8 +1081,7 @@ emit_cond_jmp:
&func_addr, &func_addr_fixed);
if (ret < 0)
return ret;
emit_addr_mov_i64(tmp, func_addr, ctx);
emit(A64_BLR(tmp), ctx);
emit_call(func_addr, ctx);
emit(A64_MOV(1, r0, A64_R(0)), ctx);
break;
}
@ -1335,6 +1425,13 @@ static int validate_code(struct jit_ctx *ctx)
if (a64_insn == AARCH64_BREAK_FAULT)
return -1;
}
return 0;
}
static int validate_ctx(struct jit_ctx *ctx)
{
if (validate_code(ctx))
return -1;
if (WARN_ON_ONCE(ctx->exentry_idx != ctx->prog->aux->num_exentries))
return -1;
@ -1355,7 +1452,7 @@ struct arm64_jit_data {
struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
{
int image_size, prog_size, extable_size;
int image_size, prog_size, extable_size, extable_align, extable_offset;
struct bpf_prog *tmp, *orig_prog = prog;
struct bpf_binary_header *header;
struct arm64_jit_data *jit_data;
@ -1425,13 +1522,17 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
ctx.epilogue_offset = ctx.idx;
build_epilogue(&ctx);
build_plt(&ctx);
extable_align = __alignof__(struct exception_table_entry);
extable_size = prog->aux->num_exentries *
sizeof(struct exception_table_entry);
/* Now we know the actual image size. */
prog_size = sizeof(u32) * ctx.idx;
image_size = prog_size + extable_size;
/* also allocate space for plt target */
extable_offset = round_up(prog_size + PLT_TARGET_SIZE, extable_align);
image_size = extable_offset + extable_size;
header = bpf_jit_binary_alloc(image_size, &image_ptr,
sizeof(u32), jit_fill_hole);
if (header == NULL) {
@ -1443,7 +1544,7 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
ctx.image = (__le32 *)image_ptr;
if (extable_size)
prog->aux->extable = (void *)image_ptr + prog_size;
prog->aux->extable = (void *)image_ptr + extable_offset;
skip_init_ctx:
ctx.idx = 0;
ctx.exentry_idx = 0;
@ -1457,9 +1558,10 @@ skip_init_ctx:
}
build_epilogue(&ctx);
build_plt(&ctx);
/* 3. Extra pass to validate JITed code. */
if (validate_code(&ctx)) {
if (validate_ctx(&ctx)) {
bpf_jit_binary_free(header);
prog = orig_prog;
goto out_off;
@ -1530,3 +1632,589 @@ void bpf_jit_free_exec(void *addr)
{
return vfree(addr);
}
/* Indicate the JIT backend supports mixing bpf2bpf and tailcalls. */
bool bpf_jit_supports_subprog_tailcalls(void)
{
return true;
}
static void invoke_bpf_prog(struct jit_ctx *ctx, struct bpf_tramp_link *l,
int args_off, int retval_off, int run_ctx_off,
bool save_ret)
{
u32 *branch;
u64 enter_prog;
u64 exit_prog;
struct bpf_prog *p = l->link.prog;
int cookie_off = offsetof(struct bpf_tramp_run_ctx, bpf_cookie);
if (p->aux->sleepable) {
enter_prog = (u64)__bpf_prog_enter_sleepable;
exit_prog = (u64)__bpf_prog_exit_sleepable;
} else {
enter_prog = (u64)__bpf_prog_enter;
exit_prog = (u64)__bpf_prog_exit;
}
if (l->cookie == 0) {
/* if cookie is zero, one instruction is enough to store it */
emit(A64_STR64I(A64_ZR, A64_SP, run_ctx_off + cookie_off), ctx);
} else {
emit_a64_mov_i64(A64_R(10), l->cookie, ctx);
emit(A64_STR64I(A64_R(10), A64_SP, run_ctx_off + cookie_off),
ctx);
}
/* save p to callee saved register x19 to avoid loading p with mov_i64
* each time.
*/
emit_addr_mov_i64(A64_R(19), (const u64)p, ctx);
/* arg1: prog */
emit(A64_MOV(1, A64_R(0), A64_R(19)), ctx);
/* arg2: &run_ctx */
emit(A64_ADD_I(1, A64_R(1), A64_SP, run_ctx_off), ctx);
emit_call(enter_prog, ctx);
/* if (__bpf_prog_enter(prog) == 0)
* goto skip_exec_of_prog;
*/
branch = ctx->image + ctx->idx;
emit(A64_NOP, ctx);
/* save return value to callee saved register x20 */
emit(A64_MOV(1, A64_R(20), A64_R(0)), ctx);
emit(A64_ADD_I(1, A64_R(0), A64_SP, args_off), ctx);
if (!p->jited)
emit_addr_mov_i64(A64_R(1), (const u64)p->insnsi, ctx);
emit_call((const u64)p->bpf_func, ctx);
if (save_ret)
emit(A64_STR64I(A64_R(0), A64_SP, retval_off), ctx);
if (ctx->image) {
int offset = &ctx->image[ctx->idx] - branch;
*branch = A64_CBZ(1, A64_R(0), offset);
}
/* arg1: prog */
emit(A64_MOV(1, A64_R(0), A64_R(19)), ctx);
/* arg2: start time */
emit(A64_MOV(1, A64_R(1), A64_R(20)), ctx);
/* arg3: &run_ctx */
emit(A64_ADD_I(1, A64_R(2), A64_SP, run_ctx_off), ctx);
emit_call(exit_prog, ctx);
}
static void invoke_bpf_mod_ret(struct jit_ctx *ctx, struct bpf_tramp_links *tl,
int args_off, int retval_off, int run_ctx_off,
u32 **branches)
{
int i;
/* The first fmod_ret program will receive a garbage return value.
* Set this to 0 to avoid confusing the program.
*/
emit(A64_STR64I(A64_ZR, A64_SP, retval_off), ctx);
for (i = 0; i < tl->nr_links; i++) {
invoke_bpf_prog(ctx, tl->links[i], args_off, retval_off,
run_ctx_off, true);
/* if (*(u64 *)(sp + retval_off) != 0)
* goto do_fexit;
*/
emit(A64_LDR64I(A64_R(10), A64_SP, retval_off), ctx);
/* Save the location of branch, and generate a nop.
* This nop will be replaced with a cbnz later.
*/
branches[i] = ctx->image + ctx->idx;
emit(A64_NOP, ctx);
}
}
static void save_args(struct jit_ctx *ctx, int args_off, int nargs)
{
int i;
for (i = 0; i < nargs; i++) {
emit(A64_STR64I(i, A64_SP, args_off), ctx);
args_off += 8;
}
}
static void restore_args(struct jit_ctx *ctx, int args_off, int nargs)
{
int i;
for (i = 0; i < nargs; i++) {
emit(A64_LDR64I(i, A64_SP, args_off), ctx);
args_off += 8;
}
}
/* Based on the x86's implementation of arch_prepare_bpf_trampoline().
*
* bpf prog and function entry before bpf trampoline hooked:
* mov x9, lr
* nop
*
* bpf prog and function entry after bpf trampoline hooked:
* mov x9, lr
* bl <bpf_trampoline or plt>
*
*/
static int prepare_trampoline(struct jit_ctx *ctx, struct bpf_tramp_image *im,
struct bpf_tramp_links *tlinks, void *orig_call,
int nargs, u32 flags)
{
int i;
int stack_size;
int retaddr_off;
int regs_off;
int retval_off;
int args_off;
int nargs_off;
int ip_off;
int run_ctx_off;
struct bpf_tramp_links *fentry = &tlinks[BPF_TRAMP_FENTRY];
struct bpf_tramp_links *fexit = &tlinks[BPF_TRAMP_FEXIT];
struct bpf_tramp_links *fmod_ret = &tlinks[BPF_TRAMP_MODIFY_RETURN];
bool save_ret;
u32 **branches = NULL;
/* trampoline stack layout:
* [ parent ip ]
* [ FP ]
* SP + retaddr_off [ self ip ]
* [ FP ]
*
* [ padding ] align SP to multiples of 16
*
* [ x20 ] callee saved reg x20
* SP + regs_off [ x19 ] callee saved reg x19
*
* SP + retval_off [ return value ] BPF_TRAMP_F_CALL_ORIG or
* BPF_TRAMP_F_RET_FENTRY_RET
*
* [ argN ]
* [ ... ]
* SP + args_off [ arg1 ]
*
* SP + nargs_off [ args count ]
*
* SP + ip_off [ traced function ] BPF_TRAMP_F_IP_ARG flag
*
* SP + run_ctx_off [ bpf_tramp_run_ctx ]
*/
stack_size = 0;
run_ctx_off = stack_size;
/* room for bpf_tramp_run_ctx */
stack_size += round_up(sizeof(struct bpf_tramp_run_ctx), 8);
ip_off = stack_size;
/* room for IP address argument */
if (flags & BPF_TRAMP_F_IP_ARG)
stack_size += 8;
nargs_off = stack_size;
/* room for args count */
stack_size += 8;
args_off = stack_size;
/* room for args */
stack_size += nargs * 8;
/* room for return value */
retval_off = stack_size;
save_ret = flags & (BPF_TRAMP_F_CALL_ORIG | BPF_TRAMP_F_RET_FENTRY_RET);
if (save_ret)
stack_size += 8;
/* room for callee saved registers, currently x19 and x20 are used */
regs_off = stack_size;
stack_size += 16;
/* round up to multiples of 16 to avoid SPAlignmentFault */
stack_size = round_up(stack_size, 16);
/* return address locates above FP */
retaddr_off = stack_size + 8;
/* bpf trampoline may be invoked by 3 instruction types:
* 1. bl, attached to bpf prog or kernel function via short jump
* 2. br, attached to bpf prog or kernel function via long jump
* 3. blr, working as a function pointer, used by struct_ops.
* So BTI_JC should used here to support both br and blr.
*/
emit_bti(A64_BTI_JC, ctx);
/* frame for parent function */
emit(A64_PUSH(A64_FP, A64_R(9), A64_SP), ctx);
emit(A64_MOV(1, A64_FP, A64_SP), ctx);
/* frame for patched function */
emit(A64_PUSH(A64_FP, A64_LR, A64_SP), ctx);
emit(A64_MOV(1, A64_FP, A64_SP), ctx);
/* allocate stack space */
emit(A64_SUB_I(1, A64_SP, A64_SP, stack_size), ctx);
if (flags & BPF_TRAMP_F_IP_ARG) {
/* save ip address of the traced function */
emit_addr_mov_i64(A64_R(10), (const u64)orig_call, ctx);
emit(A64_STR64I(A64_R(10), A64_SP, ip_off), ctx);
}
/* save args count*/
emit(A64_MOVZ(1, A64_R(10), nargs, 0), ctx);
emit(A64_STR64I(A64_R(10), A64_SP, nargs_off), ctx);
/* save args */
save_args(ctx, args_off, nargs);
/* save callee saved registers */
emit(A64_STR64I(A64_R(19), A64_SP, regs_off), ctx);
emit(A64_STR64I(A64_R(20), A64_SP, regs_off + 8), ctx);
if (flags & BPF_TRAMP_F_CALL_ORIG) {
emit_addr_mov_i64(A64_R(0), (const u64)im, ctx);
emit_call((const u64)__bpf_tramp_enter, ctx);
}
for (i = 0; i < fentry->nr_links; i++)
invoke_bpf_prog(ctx, fentry->links[i], args_off,
retval_off, run_ctx_off,
flags & BPF_TRAMP_F_RET_FENTRY_RET);
if (fmod_ret->nr_links) {
branches = kcalloc(fmod_ret->nr_links, sizeof(u32 *),
GFP_KERNEL);
if (!branches)
return -ENOMEM;
invoke_bpf_mod_ret(ctx, fmod_ret, args_off, retval_off,
run_ctx_off, branches);
}
if (flags & BPF_TRAMP_F_CALL_ORIG) {
restore_args(ctx, args_off, nargs);
/* call original func */
emit(A64_LDR64I(A64_R(10), A64_SP, retaddr_off), ctx);
emit(A64_BLR(A64_R(10)), ctx);
/* store return value */
emit(A64_STR64I(A64_R(0), A64_SP, retval_off), ctx);
/* reserve a nop for bpf_tramp_image_put */
im->ip_after_call = ctx->image + ctx->idx;
emit(A64_NOP, ctx);
}
/* update the branches saved in invoke_bpf_mod_ret with cbnz */
for (i = 0; i < fmod_ret->nr_links && ctx->image != NULL; i++) {
int offset = &ctx->image[ctx->idx] - branches[i];
*branches[i] = A64_CBNZ(1, A64_R(10), offset);
}
for (i = 0; i < fexit->nr_links; i++)
invoke_bpf_prog(ctx, fexit->links[i], args_off, retval_off,
run_ctx_off, false);
if (flags & BPF_TRAMP_F_CALL_ORIG) {
im->ip_epilogue = ctx->image + ctx->idx;
emit_addr_mov_i64(A64_R(0), (const u64)im, ctx);
emit_call((const u64)__bpf_tramp_exit, ctx);
}
if (flags & BPF_TRAMP_F_RESTORE_REGS)
restore_args(ctx, args_off, nargs);
/* restore callee saved register x19 and x20 */
emit(A64_LDR64I(A64_R(19), A64_SP, regs_off), ctx);
emit(A64_LDR64I(A64_R(20), A64_SP, regs_off + 8), ctx);
if (save_ret)
emit(A64_LDR64I(A64_R(0), A64_SP, retval_off), ctx);
/* reset SP */
emit(A64_MOV(1, A64_SP, A64_FP), ctx);
/* pop frames */
emit(A64_POP(A64_FP, A64_LR, A64_SP), ctx);
emit(A64_POP(A64_FP, A64_R(9), A64_SP), ctx);
if (flags & BPF_TRAMP_F_SKIP_FRAME) {
/* skip patched function, return to parent */
emit(A64_MOV(1, A64_LR, A64_R(9)), ctx);
emit(A64_RET(A64_R(9)), ctx);
} else {
/* return to patched function */
emit(A64_MOV(1, A64_R(10), A64_LR), ctx);
emit(A64_MOV(1, A64_LR, A64_R(9)), ctx);
emit(A64_RET(A64_R(10)), ctx);
}
if (ctx->image)
bpf_flush_icache(ctx->image, ctx->image + ctx->idx);
kfree(branches);
return ctx->idx;
}
int arch_prepare_bpf_trampoline(struct bpf_tramp_image *im, void *image,
void *image_end, const struct btf_func_model *m,
u32 flags, struct bpf_tramp_links *tlinks,
void *orig_call)
{
int ret;
int nargs = m->nr_args;
int max_insns = ((long)image_end - (long)image) / AARCH64_INSN_SIZE;
struct jit_ctx ctx = {
.image = NULL,
.idx = 0,
};
/* the first 8 arguments are passed by registers */
if (nargs > 8)
return -ENOTSUPP;
ret = prepare_trampoline(&ctx, im, tlinks, orig_call, nargs, flags);
if (ret < 0)
return ret;
if (ret > max_insns)
return -EFBIG;
ctx.image = image;
ctx.idx = 0;
jit_fill_hole(image, (unsigned int)(image_end - image));
ret = prepare_trampoline(&ctx, im, tlinks, orig_call, nargs, flags);
if (ret > 0 && validate_code(&ctx) < 0)
ret = -EINVAL;
if (ret > 0)
ret *= AARCH64_INSN_SIZE;
return ret;
}
static bool is_long_jump(void *ip, void *target)
{
long offset;
/* NULL target means this is a NOP */
if (!target)
return false;
offset = (long)target - (long)ip;
return offset < -SZ_128M || offset >= SZ_128M;
}
static int gen_branch_or_nop(enum aarch64_insn_branch_type type, void *ip,
void *addr, void *plt, u32 *insn)
{
void *target;
if (!addr) {
*insn = aarch64_insn_gen_nop();
return 0;
}
if (is_long_jump(ip, addr))
target = plt;
else
target = addr;
*insn = aarch64_insn_gen_branch_imm((unsigned long)ip,
(unsigned long)target,
type);
return *insn != AARCH64_BREAK_FAULT ? 0 : -EFAULT;
}
/* Replace the branch instruction from @ip to @old_addr in a bpf prog or a bpf
* trampoline with the branch instruction from @ip to @new_addr. If @old_addr
* or @new_addr is NULL, the old or new instruction is NOP.
*
* When @ip is the bpf prog entry, a bpf trampoline is being attached or
* detached. Since bpf trampoline and bpf prog are allocated separately with
* vmalloc, the address distance may exceed 128MB, the maximum branch range.
* So long jump should be handled.
*
* When a bpf prog is constructed, a plt pointing to empty trampoline
* dummy_tramp is placed at the end:
*
* bpf_prog:
* mov x9, lr
* nop // patchsite
* ...
* ret
*
* plt:
* ldr x10, target
* br x10
* target:
* .quad dummy_tramp // plt target
*
* This is also the state when no trampoline is attached.
*
* When a short-jump bpf trampoline is attached, the patchsite is patched
* to a bl instruction to the trampoline directly:
*
* bpf_prog:
* mov x9, lr
* bl <short-jump bpf trampoline address> // patchsite
* ...
* ret
*
* plt:
* ldr x10, target
* br x10
* target:
* .quad dummy_tramp // plt target
*
* When a long-jump bpf trampoline is attached, the plt target is filled with
* the trampoline address and the patchsite is patched to a bl instruction to
* the plt:
*
* bpf_prog:
* mov x9, lr
* bl plt // patchsite
* ...
* ret
*
* plt:
* ldr x10, target
* br x10
* target:
* .quad <long-jump bpf trampoline address> // plt target
*
* The dummy_tramp is used to prevent another CPU from jumping to unknown
* locations during the patching process, making the patching process easier.
*/
int bpf_arch_text_poke(void *ip, enum bpf_text_poke_type poke_type,
void *old_addr, void *new_addr)
{
int ret;
u32 old_insn;
u32 new_insn;
u32 replaced;
struct bpf_plt *plt = NULL;
unsigned long size = 0UL;
unsigned long offset = ~0UL;
enum aarch64_insn_branch_type branch_type;
char namebuf[KSYM_NAME_LEN];
void *image = NULL;
u64 plt_target = 0ULL;
bool poking_bpf_entry;
if (!__bpf_address_lookup((unsigned long)ip, &size, &offset, namebuf))
/* Only poking bpf text is supported. Since kernel function
* entry is set up by ftrace, we reply on ftrace to poke kernel
* functions.
*/
return -ENOTSUPP;
image = ip - offset;
/* zero offset means we're poking bpf prog entry */
poking_bpf_entry = (offset == 0UL);
/* bpf prog entry, find plt and the real patchsite */
if (poking_bpf_entry) {
/* plt locates at the end of bpf prog */
plt = image + size - PLT_TARGET_OFFSET;
/* skip to the nop instruction in bpf prog entry:
* bti c // if BTI enabled
* mov x9, x30
* nop
*/
ip = image + POKE_OFFSET * AARCH64_INSN_SIZE;
}
/* long jump is only possible at bpf prog entry */
if (WARN_ON((is_long_jump(ip, new_addr) || is_long_jump(ip, old_addr)) &&
!poking_bpf_entry))
return -EINVAL;
if (poke_type == BPF_MOD_CALL)
branch_type = AARCH64_INSN_BRANCH_LINK;
else
branch_type = AARCH64_INSN_BRANCH_NOLINK;
if (gen_branch_or_nop(branch_type, ip, old_addr, plt, &old_insn) < 0)
return -EFAULT;
if (gen_branch_or_nop(branch_type, ip, new_addr, plt, &new_insn) < 0)
return -EFAULT;
if (is_long_jump(ip, new_addr))
plt_target = (u64)new_addr;
else if (is_long_jump(ip, old_addr))
/* if the old target is a long jump and the new target is not,
* restore the plt target to dummy_tramp, so there is always a
* legal and harmless address stored in plt target, and we'll
* never jump from plt to an unknown place.
*/
plt_target = (u64)&dummy_tramp;
if (plt_target) {
/* non-zero plt_target indicates we're patching a bpf prog,
* which is read only.
*/
if (set_memory_rw(PAGE_MASK & ((uintptr_t)&plt->target), 1))
return -EFAULT;
WRITE_ONCE(plt->target, plt_target);
set_memory_ro(PAGE_MASK & ((uintptr_t)&plt->target), 1);
/* since plt target points to either the new trampoline
* or dummy_tramp, even if another CPU reads the old plt
* target value before fetching the bl instruction to plt,
* it will be brought back by dummy_tramp, so no barrier is
* required here.
*/
}
/* if the old target and the new target are both long jumps, no
* patching is required
*/
if (old_insn == new_insn)
return 0;
mutex_lock(&text_mutex);
if (aarch64_insn_read(ip, &replaced)) {
ret = -EFAULT;
goto out;
}
if (replaced != old_insn) {
ret = -EFAULT;
goto out;
}
/* We call aarch64_insn_patch_text_nosync() to replace instruction
* atomically, so no other CPUs will fetch a half-new and half-old
* instruction. But there is chance that another CPU executes the
* old instruction after the patching operation finishes (e.g.,
* pipeline not flushed, or icache not synchronized yet).
*
* 1. when a new trampoline is attached, it is not a problem for
* different CPUs to jump to different trampolines temporarily.
*
* 2. when an old trampoline is freed, we should wait for all other
* CPUs to exit the trampoline and make sure the trampoline is no
* longer reachable, since bpf_tramp_image_put() function already
* uses percpu_ref and task-based rcu to do the sync, no need to call
* the sync version here, see bpf_tramp_image_put() for details.
*/
ret = aarch64_insn_patch_text_nosync(ip, new_insn);
out:
mutex_unlock(&text_mutex);
return ret;
}

View File

@ -343,6 +343,24 @@
status = "disabled";
};
can0: can@2010c000 {
compatible = "microchip,mpfs-can";
reg = <0x0 0x2010c000 0x0 0x1000>;
clocks = <&clkcfg CLK_CAN0>;
interrupt-parent = <&plic>;
interrupts = <56>;
status = "disabled";
};
can1: can@2010d000 {
compatible = "microchip,mpfs-can";
reg = <0x0 0x2010d000 0x0 0x1000>;
clocks = <&clkcfg CLK_CAN1>;
interrupt-parent = <&plic>;
interrupts = <57>;
status = "disabled";
};
mac0: ethernet@20110000 {
compatible = "cdns,macb";
reg = <0x0 0x20110000 0x0 0x2000>;

View File

@ -69,6 +69,7 @@ struct rv_jit_context {
struct bpf_prog *prog;
u16 *insns; /* RV insns */
int ninsns;
int body_len;
int epilogue_offset;
int *offset; /* BPF to RV */
int nexentries;

View File

@ -44,7 +44,7 @@ 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;
int pass = 0, prev_ninsns = 0, prologue_len, i;
struct rv_jit_data *jit_data;
struct rv_jit_context *ctx;
@ -95,6 +95,7 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
prog = orig_prog;
goto out_offset;
}
ctx->body_len = ctx->ninsns;
bpf_jit_build_prologue(ctx);
ctx->epilogue_offset = ctx->ninsns;
bpf_jit_build_epilogue(ctx);
@ -161,6 +162,11 @@ skip_init_ctx:
if (!prog->is_func || extra_pass) {
bpf_jit_binary_lock_ro(jit_data->header);
prologue_len = ctx->epilogue_offset - ctx->body_len;
for (i = 0; i < prog->len; i++)
ctx->offset[i] = ninsns_rvoff(prologue_len +
ctx->offset[i]);
bpf_prog_fill_jited_linfo(prog, ctx->offset);
out_offset:
kfree(ctx->offset);
kfree(jit_data);

View File

@ -1785,6 +1785,10 @@ static int invoke_bpf_prog(const struct btf_func_model *m, u8 **pprog,
struct bpf_tramp_link *l, int stack_size,
int run_ctx_off, bool save_ret)
{
void (*exit)(struct bpf_prog *prog, u64 start,
struct bpf_tramp_run_ctx *run_ctx) = __bpf_prog_exit;
u64 (*enter)(struct bpf_prog *prog,
struct bpf_tramp_run_ctx *run_ctx) = __bpf_prog_enter;
u8 *prog = *pprog;
u8 *jmp_insn;
int ctx_cookie_off = offsetof(struct bpf_tramp_run_ctx, bpf_cookie);
@ -1803,15 +1807,21 @@ static int invoke_bpf_prog(const struct btf_func_model *m, u8 **pprog,
*/
emit_stx(&prog, BPF_DW, BPF_REG_FP, BPF_REG_1, -run_ctx_off + ctx_cookie_off);
if (p->aux->sleepable) {
enter = __bpf_prog_enter_sleepable;
exit = __bpf_prog_exit_sleepable;
} else if (p->expected_attach_type == BPF_LSM_CGROUP) {
enter = __bpf_prog_enter_lsm_cgroup;
exit = __bpf_prog_exit_lsm_cgroup;
}
/* arg1: mov rdi, progs[i] */
emit_mov_imm64(&prog, BPF_REG_1, (long) p >> 32, (u32) (long) p);
/* arg2: lea rsi, [rbp - ctx_cookie_off] */
EMIT4(0x48, 0x8D, 0x75, -run_ctx_off);
if (emit_call(&prog,
p->aux->sleepable ? __bpf_prog_enter_sleepable :
__bpf_prog_enter, prog))
return -EINVAL;
if (emit_call(&prog, enter, prog))
return -EINVAL;
/* remember prog start time returned by __bpf_prog_enter */
emit_mov_reg(&prog, true, BPF_REG_6, BPF_REG_0);
@ -1855,10 +1865,8 @@ static int invoke_bpf_prog(const struct btf_func_model *m, u8 **pprog,
emit_mov_reg(&prog, true, BPF_REG_2, BPF_REG_6);
/* arg3: lea rdx, [rbp - run_ctx_off] */
EMIT4(0x48, 0x8D, 0x55, -run_ctx_off);
if (emit_call(&prog,
p->aux->sleepable ? __bpf_prog_exit_sleepable :
__bpf_prog_exit, prog))
return -EINVAL;
if (emit_call(&prog, exit, prog))
return -EINVAL;
*pprog = prog;
return 0;
@ -1942,23 +1950,6 @@ static int invoke_bpf_mod_ret(const struct btf_func_model *m, u8 **pprog,
return 0;
}
static bool is_valid_bpf_tramp_flags(unsigned int flags)
{
if ((flags & BPF_TRAMP_F_RESTORE_REGS) &&
(flags & BPF_TRAMP_F_SKIP_FRAME))
return false;
/*
* BPF_TRAMP_F_RET_FENTRY_RET is only used by bpf_struct_ops,
* and it must be used alone.
*/
if ((flags & BPF_TRAMP_F_RET_FENTRY_RET) &&
(flags & ~BPF_TRAMP_F_RET_FENTRY_RET))
return false;
return true;
}
/* Example:
* __be16 eth_type_trans(struct sk_buff *skb, struct net_device *dev);
* its 'struct btf_func_model' will be nr_args=2
@ -2037,9 +2028,6 @@ int arch_prepare_bpf_trampoline(struct bpf_tramp_image *im, void *image, void *i
if (nr_args > 6)
return -ENOTSUPP;
if (!is_valid_bpf_tramp_flags(flags))
return -EINVAL;
/* Generated trampoline stack layout:
*
* RBP + 8 [ return address ]
@ -2145,10 +2133,15 @@ int arch_prepare_bpf_trampoline(struct bpf_tramp_image *im, void *image, void *i
if (flags & BPF_TRAMP_F_CALL_ORIG) {
restore_regs(m, &prog, nr_args, regs_off);
/* call original function */
if (emit_call(&prog, orig_call, prog)) {
ret = -EINVAL;
goto cleanup;
if (flags & BPF_TRAMP_F_ORIG_STACK) {
emit_ldx(&prog, BPF_DW, BPF_REG_0, BPF_REG_FP, 8);
EMIT2(0xff, 0xd0); /* call *rax */
} else {
/* call original function */
if (emit_call(&prog, orig_call, prog)) {
ret = -EINVAL;
goto cleanup;
}
}
/* remember return value in a stack for bpf prog to access */
emit_stx(&prog, BPF_DW, BPF_REG_FP, BPF_REG_0, -8);
@ -2506,3 +2499,34 @@ void *bpf_arch_text_copy(void *dst, void *src, size_t len)
return ERR_PTR(-EINVAL);
return dst;
}
/* Indicate the JIT backend supports mixing bpf2bpf and tailcalls. */
bool bpf_jit_supports_subprog_tailcalls(void)
{
return true;
}
void bpf_jit_free(struct bpf_prog *prog)
{
if (prog->jited) {
struct x64_jit_data *jit_data = prog->aux->jit_data;
struct bpf_binary_header *hdr;
/*
* If we fail the final pass of JIT (from jit_subprogs),
* the program may not be finalized yet. Call finalize here
* before freeing it.
*/
if (jit_data) {
bpf_jit_binary_pack_finalize(prog, jit_data->header,
jit_data->rw_header);
kvfree(jit_data->addrs);
kfree(jit_data);
}
hdr = bpf_jit_binary_pack_hdr(prog);
bpf_jit_binary_pack_free(hdr, NULL);
WARN_ON_ONCE(!bpf_prog_kallsyms_verify_off(prog));
}
bpf_prog_unlock_free(prog);
}

View File

@ -780,14 +780,11 @@ static int he_init_group(struct he_dev *he_dev, int group)
G0_RBPS_BS + (group * 32));
/* bitmap table */
he_dev->rbpl_table = kmalloc_array(BITS_TO_LONGS(RBPL_TABLE_SIZE),
sizeof(*he_dev->rbpl_table),
GFP_KERNEL);
he_dev->rbpl_table = bitmap_zalloc(RBPL_TABLE_SIZE, GFP_KERNEL);
if (!he_dev->rbpl_table) {
hprintk("unable to allocate rbpl bitmap table\n");
return -ENOMEM;
}
bitmap_zero(he_dev->rbpl_table, RBPL_TABLE_SIZE);
/* rbpl_virt 64-bit pointers */
he_dev->rbpl_virt = kmalloc_array(RBPL_TABLE_SIZE,
@ -902,7 +899,7 @@ out_destroy_rbpl_pool:
out_free_rbpl_virt:
kfree(he_dev->rbpl_virt);
out_free_rbpl_table:
kfree(he_dev->rbpl_table);
bitmap_free(he_dev->rbpl_table);
return -ENOMEM;
}
@ -1578,7 +1575,7 @@ he_stop(struct he_dev *he_dev)
}
kfree(he_dev->rbpl_virt);
kfree(he_dev->rbpl_table);
bitmap_free(he_dev->rbpl_table);
dma_pool_destroy(he_dev->rbpl_pool);
if (he_dev->rbrq_base)

View File

@ -739,7 +739,7 @@ static u16 ia_eeprom_get (IADEV *iadev, u32 addr)
u32 t;
int i;
/*
* Read the first bit that was clocked with the falling edge of the
* Read the first bit that was clocked with the falling edge of
* the last command data clock
*/
NVRAM_CMD(IAREAD + addr);

View File

@ -403,6 +403,13 @@ static int btbcm_read_info(struct hci_dev *hdev)
bt_dev_info(hdev, "BCM: chip id %u", skb->data[1]);
kfree_skb(skb);
return 0;
}
static int btbcm_print_controller_features(struct hci_dev *hdev)
{
struct sk_buff *skb;
/* Read Controller Features */
skb = btbcm_read_controller_features(hdev);
if (IS_ERR(skb))
@ -454,6 +461,8 @@ static const struct bcm_subver_table bcm_uart_subver_table[] = {
{ 0x6606, "BCM4345C5" }, /* 003.006.006 */
{ 0x230f, "BCM4356A2" }, /* 001.003.015 */
{ 0x220e, "BCM20702A1" }, /* 001.002.014 */
{ 0x420d, "BCM4349B1" }, /* 002.002.013 */
{ 0x420e, "BCM4349B1" }, /* 002.002.014 */
{ 0x4217, "BCM4329B1" }, /* 002.002.023 */
{ 0x6106, "BCM4359C0" }, /* 003.001.006 */
{ 0x4106, "BCM4335A0" }, /* 002.001.006 */
@ -514,7 +523,7 @@ static const char *btbcm_get_board_name(struct device *dev)
#endif
}
int btbcm_initialize(struct hci_dev *hdev, bool *fw_load_done)
int btbcm_initialize(struct hci_dev *hdev, bool *fw_load_done, bool use_autobaud_mode)
{
u16 subver, rev, pid, vid;
struct sk_buff *skb;
@ -551,9 +560,16 @@ int btbcm_initialize(struct hci_dev *hdev, bool *fw_load_done)
if (err)
return err;
}
err = btbcm_print_local_name(hdev);
if (err)
return err;
if (!use_autobaud_mode) {
err = btbcm_print_controller_features(hdev);
if (err)
return err;
err = btbcm_print_local_name(hdev);
if (err)
return err;
}
bcm_subver_table = (hdev->bus == HCI_USB) ? bcm_usb_subver_table :
bcm_uart_subver_table;
@ -636,13 +652,13 @@ int btbcm_initialize(struct hci_dev *hdev, bool *fw_load_done)
}
EXPORT_SYMBOL_GPL(btbcm_initialize);
int btbcm_finalize(struct hci_dev *hdev, bool *fw_load_done)
int btbcm_finalize(struct hci_dev *hdev, bool *fw_load_done, bool use_autobaud_mode)
{
int err;
/* Re-initialize if necessary */
if (*fw_load_done) {
err = btbcm_initialize(hdev, fw_load_done);
err = btbcm_initialize(hdev, fw_load_done, use_autobaud_mode);
if (err)
return err;
}
@ -658,15 +674,16 @@ EXPORT_SYMBOL_GPL(btbcm_finalize);
int btbcm_setup_patchram(struct hci_dev *hdev)
{
bool fw_load_done = false;
bool use_autobaud_mode = false;
int err;
/* Initialize */
err = btbcm_initialize(hdev, &fw_load_done);
err = btbcm_initialize(hdev, &fw_load_done, use_autobaud_mode);
if (err)
return err;
/* Re-initialize after loading Patch */
return btbcm_finalize(hdev, &fw_load_done);
return btbcm_finalize(hdev, &fw_load_done, use_autobaud_mode);
}
EXPORT_SYMBOL_GPL(btbcm_setup_patchram);

View File

@ -62,8 +62,8 @@ int btbcm_write_pcm_int_params(struct hci_dev *hdev,
int btbcm_setup_patchram(struct hci_dev *hdev);
int btbcm_setup_apple(struct hci_dev *hdev);
int btbcm_initialize(struct hci_dev *hdev, bool *fw_load_done);
int btbcm_finalize(struct hci_dev *hdev, bool *fw_load_done);
int btbcm_initialize(struct hci_dev *hdev, bool *fw_load_done, bool use_autobaud_mode);
int btbcm_finalize(struct hci_dev *hdev, bool *fw_load_done, bool use_autobaud_mode);
#else
@ -104,12 +104,12 @@ static inline int btbcm_setup_apple(struct hci_dev *hdev)
return 0;
}
static inline int btbcm_initialize(struct hci_dev *hdev, bool *fw_load_done)
static inline int btbcm_initialize(struct hci_dev *hdev, bool *fw_load_done, bool use_autobaud_mode)
{
return 0;
}
static inline int btbcm_finalize(struct hci_dev *hdev, bool *fw_load_done)
static inline int btbcm_finalize(struct hci_dev *hdev, bool *fw_load_done, bool use_autobaud_mode)
{
return 0;
}

View File

@ -1282,6 +1282,13 @@ err:
hci_reset_dev(hdev);
}
static bool btmtksdio_sdio_inband_wakeup(struct hci_dev *hdev)
{
struct btmtksdio_dev *bdev = hci_get_drvdata(hdev);
return device_may_wakeup(bdev->dev);
}
static bool btmtksdio_sdio_wakeup(struct hci_dev *hdev)
{
struct btmtksdio_dev *bdev = hci_get_drvdata(hdev);
@ -1349,6 +1356,14 @@ static int btmtksdio_probe(struct sdio_func *func,
hdev->shutdown = btmtksdio_shutdown;
hdev->send = btmtksdio_send_frame;
hdev->wakeup = btmtksdio_sdio_wakeup;
/*
* If SDIO controller supports wake on Bluetooth, sending a wakeon
* command is not necessary.
*/
if (device_can_wakeup(func->card->host->parent))
hdev->wakeup = btmtksdio_sdio_inband_wakeup;
else
hdev->wakeup = btmtksdio_sdio_wakeup;
hdev->set_bdaddr = btmtk_set_bdaddr;
SET_HCIDEV_DEV(hdev, &func->dev);

View File

@ -330,7 +330,7 @@ static int rtlbt_parse_firmware(struct hci_dev *hdev,
/* Loop from the end of the firmware parsing instructions, until
* we find an instruction that identifies the "project ID" for the
* hardware supported by this firwmare file.
* Once we have that, we double-check that that project_id is suitable
* Once we have that, we double-check that project_id is suitable
* for the hardware we are working with.
*/
while (fwptr >= btrtl_dev->fw_data + (sizeof(*epatch_info) + 3)) {

View File

@ -427,6 +427,18 @@ static const struct usb_device_id blacklist_table[] = {
{ USB_DEVICE(0x04ca, 0x4006), .driver_info = BTUSB_REALTEK |
BTUSB_WIDEBAND_SPEECH },
/* Realtek 8852CE Bluetooth devices */
{ USB_DEVICE(0x04ca, 0x4007), .driver_info = BTUSB_REALTEK |
BTUSB_WIDEBAND_SPEECH },
{ USB_DEVICE(0x04c5, 0x1675), .driver_info = BTUSB_REALTEK |
BTUSB_WIDEBAND_SPEECH },
{ USB_DEVICE(0x0cb8, 0xc558), .driver_info = BTUSB_REALTEK |
BTUSB_WIDEBAND_SPEECH },
{ USB_DEVICE(0x13d3, 0x3587), .driver_info = BTUSB_REALTEK |
BTUSB_WIDEBAND_SPEECH },
{ USB_DEVICE(0x13d3, 0x3586), .driver_info = BTUSB_REALTEK |
BTUSB_WIDEBAND_SPEECH },
/* Realtek Bluetooth devices */
{ USB_VENDOR_AND_INTERFACE_INFO(0x0bda, 0xe0, 0x01, 0x01),
.driver_info = BTUSB_REALTEK },
@ -477,6 +489,12 @@ static const struct usb_device_id blacklist_table[] = {
{ USB_DEVICE(0x0489, 0xe0d9), .driver_info = BTUSB_MEDIATEK |
BTUSB_WIDEBAND_SPEECH |
BTUSB_VALID_LE_STATES },
{ USB_DEVICE(0x13d3, 0x3568), .driver_info = BTUSB_MEDIATEK |
BTUSB_WIDEBAND_SPEECH |
BTUSB_VALID_LE_STATES },
{ USB_DEVICE(0x0489, 0xe0e2), .driver_info = BTUSB_MEDIATEK |
BTUSB_WIDEBAND_SPEECH |
BTUSB_VALID_LE_STATES },
/* Additional Realtek 8723AE Bluetooth devices */
{ USB_DEVICE(0x0930, 0x021d), .driver_info = BTUSB_REALTEK },
@ -893,11 +911,21 @@ static int btusb_recv_bulk(struct btusb_data *data, void *buffer, int count)
hci_skb_expect(skb) -= len;
if (skb->len == HCI_ACL_HDR_SIZE) {
__u16 handle = __le16_to_cpu(hci_acl_hdr(skb)->handle);
__le16 dlen = hci_acl_hdr(skb)->dlen;
__u8 type;
/* Complete ACL header */
hci_skb_expect(skb) = __le16_to_cpu(dlen);
/* Detect if ISO packet has been sent over bulk */
if (hci_conn_num(data->hdev, ISO_LINK)) {
type = hci_conn_lookup_type(data->hdev,
hci_handle(handle));
if (type == ISO_LINK)
hci_skb_pkt_type(skb) = HCI_ISODATA_PKT;
}
if (skb_tailroom(skb) < hci_skb_expect(skb)) {
kfree_skb(skb);
skb = NULL;
@ -1762,6 +1790,13 @@ static int btusb_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
hdev->stat.sco_tx++;
return submit_tx_urb(hdev, urb);
case HCI_ISODATA_PKT:
urb = alloc_bulk_urb(hdev, skb);
if (IS_ERR(urb))
return PTR_ERR(urb);
return submit_or_queue_tx_urb(hdev, urb);
}
return -EILSEQ;
@ -2069,7 +2104,6 @@ static int btusb_setup_csr(struct hci_dev *hdev)
* without these the controller will lock up.
*/
set_bit(HCI_QUIRK_BROKEN_STORED_LINK_KEY, &hdev->quirks);
set_bit(HCI_QUIRK_BROKEN_ERR_DATA_REPORTING, &hdev->quirks);
set_bit(HCI_QUIRK_BROKEN_FILTER_CLEAR_ALL, &hdev->quirks);
set_bit(HCI_QUIRK_NO_SUSPEND_NOTIFIER, &hdev->quirks);
@ -2255,6 +2289,13 @@ static int btusb_send_frame_intel(struct hci_dev *hdev, struct sk_buff *skb)
hdev->stat.sco_tx++;
return submit_tx_urb(hdev, urb);
case HCI_ISODATA_PKT:
urb = alloc_bulk_urb(hdev, skb);
if (IS_ERR(urb))
return PTR_ERR(urb);
return submit_or_queue_tx_urb(hdev, urb);
}
return -EILSEQ;
@ -3352,7 +3393,6 @@ static int btusb_setup_qca(struct hci_dev *hdev)
* work with the likes of HSP/HFP mSBC.
*/
set_bit(HCI_QUIRK_BROKEN_ENHANCED_SETUP_SYNC_CONN, &hdev->quirks);
set_bit(HCI_QUIRK_BROKEN_ERR_DATA_REPORTING, &hdev->quirks);
return 0;
}
@ -3795,6 +3835,7 @@ static int btusb_probe(struct usb_interface *intf,
hdev->manufacturer = 70;
hdev->cmd_timeout = btusb_mtk_cmd_timeout;
hdev->set_bdaddr = btmtk_set_bdaddr;
set_bit(HCI_QUIRK_BROKEN_ENHANCED_SETUP_SYNC_CONN, &hdev->quirks);
set_bit(HCI_QUIRK_NON_PERSISTENT_SETUP, &hdev->quirks);
data->recv_acl = btusb_recv_acl_mtk;
}

View File

@ -53,10 +53,12 @@
* struct bcm_device_data - device specific data
* @no_early_set_baudrate: Disallow set baudrate before driver setup()
* @drive_rts_on_open: drive RTS signal on ->open() when platform requires it
* @max_autobaud_speed: max baudrate supported by device in autobaud mode
*/
struct bcm_device_data {
bool no_early_set_baudrate;
bool drive_rts_on_open;
u32 max_autobaud_speed;
};
/**
@ -99,6 +101,8 @@ struct bcm_device_data {
* @no_early_set_baudrate: don't set_baudrate before setup()
* @drive_rts_on_open: drive RTS signal on ->open() when platform requires it
* @pcm_int_params: keep the initial PCM configuration
* @use_autobaud_mode: start Bluetooth device in autobaud mode
* @max_autobaud_speed: max baudrate supported by device in autobaud mode
*/
struct bcm_device {
/* Must be the first member, hci_serdev.c expects this. */
@ -136,7 +140,9 @@ struct bcm_device {
#endif
bool no_early_set_baudrate;
bool drive_rts_on_open;
bool use_autobaud_mode;
u8 pcm_int_params[5];
u32 max_autobaud_speed;
};
/* generic bcm uart resources */
@ -472,15 +478,20 @@ static int bcm_open(struct hci_uart *hu)
out:
if (bcm->dev) {
if (bcm->dev->drive_rts_on_open)
if (bcm->dev->use_autobaud_mode)
hci_uart_set_flow_control(hu, false); /* Assert BT_UART_CTS_N */
else if (bcm->dev->drive_rts_on_open)
hci_uart_set_flow_control(hu, true);
hu->init_speed = bcm->dev->init_speed;
if (bcm->dev->use_autobaud_mode && bcm->dev->max_autobaud_speed)
hu->init_speed = min(bcm->dev->oper_speed, bcm->dev->max_autobaud_speed);
else
hu->init_speed = bcm->dev->init_speed;
/* If oper_speed is set, ldisc/serdev will set the baudrate
* before calling setup()
*/
if (!bcm->dev->no_early_set_baudrate)
if (!bcm->dev->no_early_set_baudrate && !bcm->dev->use_autobaud_mode)
hu->oper_speed = bcm->dev->oper_speed;
err = bcm_gpio_set_power(bcm->dev, true);
@ -564,6 +575,7 @@ static int bcm_setup(struct hci_uart *hu)
{
struct bcm_data *bcm = hu->priv;
bool fw_load_done = false;
bool use_autobaud_mode = (bcm->dev ? bcm->dev->use_autobaud_mode : 0);
unsigned int speed;
int err;
@ -572,7 +584,7 @@ static int bcm_setup(struct hci_uart *hu)
hu->hdev->set_diag = bcm_set_diag;
hu->hdev->set_bdaddr = btbcm_set_bdaddr;
err = btbcm_initialize(hu->hdev, &fw_load_done);
err = btbcm_initialize(hu->hdev, &fw_load_done, use_autobaud_mode);
if (err)
return err;
@ -580,8 +592,8 @@ static int bcm_setup(struct hci_uart *hu)
return 0;
/* Init speed if any */
if (hu->init_speed)
speed = hu->init_speed;
if (bcm->dev && bcm->dev->init_speed)
speed = bcm->dev->init_speed;
else if (hu->proto->init_speed)
speed = hu->proto->init_speed;
else
@ -616,7 +628,7 @@ static int bcm_setup(struct hci_uart *hu)
btbcm_write_pcm_int_params(hu->hdev, &params);
}
err = btbcm_finalize(hu->hdev, &fw_load_done);
err = btbcm_finalize(hu->hdev, &fw_load_done, use_autobaud_mode);
if (err)
return err;
@ -1197,6 +1209,8 @@ static int bcm_acpi_probe(struct bcm_device *dev)
static int bcm_of_probe(struct bcm_device *bdev)
{
bdev->use_autobaud_mode = device_property_read_bool(bdev->dev,
"brcm,requires-autobaud-mode");
device_property_read_u32(bdev->dev, "max-speed", &bdev->oper_speed);
device_property_read_u8_array(bdev->dev, "brcm,bt-pcm-int-params",
bdev->pcm_int_params, 5);
@ -1512,6 +1526,7 @@ static int bcm_serdev_probe(struct serdev_device *serdev)
data = device_get_match_data(bcmdev->dev);
if (data) {
bcmdev->max_autobaud_speed = data->max_autobaud_speed;
bcmdev->no_early_set_baudrate = data->no_early_set_baudrate;
bcmdev->drive_rts_on_open = data->drive_rts_on_open;
}
@ -1535,6 +1550,10 @@ static struct bcm_device_data bcm43438_device_data = {
.drive_rts_on_open = true,
};
static struct bcm_device_data cyw55572_device_data = {
.max_autobaud_speed = 921600,
};
static const struct of_device_id bcm_bluetooth_of_match[] = {
{ .compatible = "brcm,bcm20702a1" },
{ .compatible = "brcm,bcm4329-bt" },
@ -1544,8 +1563,10 @@ static const struct of_device_id bcm_bluetooth_of_match[] = {
{ .compatible = "brcm,bcm43430a0-bt" },
{ .compatible = "brcm,bcm43430a1-bt" },
{ .compatible = "brcm,bcm43438-bt", .data = &bcm43438_device_data },
{ .compatible = "brcm,bcm4349-bt", .data = &bcm43438_device_data },
{ .compatible = "brcm,bcm43540-bt", .data = &bcm4354_device_data },
{ .compatible = "brcm,bcm4335a0" },
{ .compatible = "infineon,cyw55572-bt", .data = &cyw55572_device_data },
{ },
};
MODULE_DEVICE_TABLE(of, bcm_bluetooth_of_match);

View File

@ -1217,7 +1217,11 @@ static struct platform_driver intel_driver = {
int __init intel_init(void)
{
platform_driver_register(&intel_driver);
int err;
err = platform_driver_register(&intel_driver);
if (err)
return err;
return hci_uart_register_proto(&intel_proto);
}

View File

@ -1588,7 +1588,7 @@ static bool qca_wakeup(struct hci_dev *hdev)
wakeup = device_may_wakeup(hu->serdev->ctrl->dev.parent);
bt_dev_dbg(hu->hdev, "wakeup status : %d", wakeup);
return !wakeup;
return wakeup;
}
static int qca_regulator_init(struct hci_uart *hu)

View File

@ -231,6 +231,15 @@ static int hci_uart_setup(struct hci_dev *hdev)
return 0;
}
/* Check if the device is wakeable */
static bool hci_uart_wakeup(struct hci_dev *hdev)
{
/* HCI UART devices are assumed to be wakeable by default.
* Implement wakeup callback to override this behavior.
*/
return true;
}
/** hci_uart_write_wakeup - transmit buffer wakeup
* @serdev: serial device
*
@ -342,6 +351,8 @@ int hci_uart_register_device(struct hci_uart *hu,
hdev->flush = hci_uart_flush;
hdev->send = hci_uart_send_frame;
hdev->setup = hci_uart_setup;
if (!hdev->wakeup)
hdev->wakeup = hci_uart_wakeup;
SET_HCIDEV_DEV(hdev, &hu->serdev->dev);
if (test_bit(HCI_UART_NO_SUSPEND_NOTIFIER, &hu->flags))

View File

@ -201,15 +201,6 @@ struct fwnet_packet_task {
u8 enqueued;
};
/*
* Get fifo address embedded in hwaddr
*/
static __u64 fwnet_hwaddr_fifo(union fwnet_hwaddr *ha)
{
return (u64)get_unaligned_be16(&ha->uc.fifo_hi) << 32
| get_unaligned_be32(&ha->uc.fifo_lo);
}
/*
* saddr == NULL means use device source address.
* daddr == NULL means leave destination address (eg unresolved arp).
@ -1306,7 +1297,7 @@ static netdev_tx_t fwnet_tx(struct sk_buff *skb, struct net_device *net)
max_payload = peer->max_payload;
datagram_label_ptr = &peer->datagram_label;
ptask->fifo_addr = fwnet_hwaddr_fifo(ha);
ptask->fifo_addr = get_unaligned_be48(ha->uc.fifo);
ptask->generation = generation;
ptask->dest_node = dest_node;
ptask->speed = peer->speed;
@ -1494,8 +1485,7 @@ static int fwnet_probe(struct fw_unit *unit,
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);
put_unaligned_be48(dev->local_fifo, ha.uc.fifo);
dev_addr_set(net, ha.u);
memset(net->broadcast, -1, net->addr_len);

View File

@ -336,9 +336,15 @@ err_copy:
static enum mlx5_sw_icm_type get_icm_type(int uapi_type)
{
return uapi_type == MLX5_IB_UAPI_DM_TYPE_STEERING_SW_ICM ?
MLX5_SW_ICM_TYPE_STEERING :
MLX5_SW_ICM_TYPE_HEADER_MODIFY;
switch (uapi_type) {
case MLX5_IB_UAPI_DM_TYPE_HEADER_MODIFY_SW_ICM:
return MLX5_SW_ICM_TYPE_HEADER_MODIFY;
case MLX5_IB_UAPI_DM_TYPE_HEADER_MODIFY_PATTERN_SW_ICM:
return MLX5_SW_ICM_TYPE_HEADER_MODIFY_PATTERN;
case MLX5_IB_UAPI_DM_TYPE_STEERING_SW_ICM:
default:
return MLX5_SW_ICM_TYPE_STEERING;
}
}
static struct ib_dm *handle_alloc_dm_sw_icm(struct ib_ucontext *ctx,
@ -347,11 +353,32 @@ static struct ib_dm *handle_alloc_dm_sw_icm(struct ib_ucontext *ctx,
int type)
{
struct mlx5_core_dev *dev = to_mdev(ctx->device)->mdev;
enum mlx5_sw_icm_type icm_type = get_icm_type(type);
enum mlx5_sw_icm_type icm_type;
struct mlx5_ib_dm_icm *dm;
u64 act_size;
int err;
if (!capable(CAP_SYS_RAWIO) || !capable(CAP_NET_RAW))
return ERR_PTR(-EPERM);
switch (type) {
case MLX5_IB_UAPI_DM_TYPE_STEERING_SW_ICM:
case MLX5_IB_UAPI_DM_TYPE_HEADER_MODIFY_SW_ICM:
if (!(MLX5_CAP_FLOWTABLE_NIC_RX(dev, sw_owner) ||
MLX5_CAP_FLOWTABLE_NIC_TX(dev, sw_owner) ||
MLX5_CAP_FLOWTABLE_NIC_RX(dev, sw_owner_v2) ||
MLX5_CAP_FLOWTABLE_NIC_TX(dev, sw_owner_v2)))
return ERR_PTR(-EOPNOTSUPP);
break;
case MLX5_IB_UAPI_DM_TYPE_HEADER_MODIFY_PATTERN_SW_ICM:
if (!MLX5_CAP_FLOWTABLE_NIC_RX(dev, sw_owner_v2) ||
!MLX5_CAP_FLOWTABLE_NIC_TX(dev, sw_owner_v2))
return ERR_PTR(-EOPNOTSUPP);
break;
default:
return ERR_PTR(-EOPNOTSUPP);
}
dm = kzalloc(sizeof(*dm), GFP_KERNEL);
if (!dm)
return ERR_PTR(-ENOMEM);
@ -359,19 +386,6 @@ static struct ib_dm *handle_alloc_dm_sw_icm(struct ib_ucontext *ctx,
dm->base.type = type;
dm->base.ibdm.device = ctx->device;
if (!capable(CAP_SYS_RAWIO) || !capable(CAP_NET_RAW)) {
err = -EPERM;
goto free;
}
if (!(MLX5_CAP_FLOWTABLE_NIC_RX(dev, sw_owner) ||
MLX5_CAP_FLOWTABLE_NIC_TX(dev, sw_owner) ||
MLX5_CAP_FLOWTABLE_NIC_RX(dev, sw_owner_v2) ||
MLX5_CAP_FLOWTABLE_NIC_TX(dev, sw_owner_v2))) {
err = -EOPNOTSUPP;
goto free;
}
/* Allocation size must a multiple of the basic block size
* and a power of 2.
*/
@ -379,6 +393,8 @@ static struct ib_dm *handle_alloc_dm_sw_icm(struct ib_ucontext *ctx,
act_size = roundup_pow_of_two(act_size);
dm->base.size = act_size;
icm_type = get_icm_type(type);
err = mlx5_dm_sw_icm_alloc(dev, icm_type, act_size, attr->alignment,
to_mucontext(ctx)->devx_uid,
&dm->base.dev_addr, &dm->obj_id);
@ -420,8 +436,8 @@ struct ib_dm *mlx5_ib_alloc_dm(struct ib_device *ibdev,
case MLX5_IB_UAPI_DM_TYPE_MEMIC:
return handle_alloc_dm_memic(context, attr, attrs);
case MLX5_IB_UAPI_DM_TYPE_STEERING_SW_ICM:
return handle_alloc_dm_sw_icm(context, attr, attrs, type);
case MLX5_IB_UAPI_DM_TYPE_HEADER_MODIFY_SW_ICM:
case MLX5_IB_UAPI_DM_TYPE_HEADER_MODIFY_PATTERN_SW_ICM:
return handle_alloc_dm_sw_icm(context, attr, attrs, type);
default:
return ERR_PTR(-EOPNOTSUPP);
@ -474,6 +490,7 @@ static int mlx5_ib_dealloc_dm(struct ib_dm *ibdm,
return 0;
case MLX5_IB_UAPI_DM_TYPE_STEERING_SW_ICM:
case MLX5_IB_UAPI_DM_TYPE_HEADER_MODIFY_SW_ICM:
case MLX5_IB_UAPI_DM_TYPE_HEADER_MODIFY_PATTERN_SW_ICM:
return mlx5_dm_icm_dealloc(ctx, to_icm(ibdm));
default:
return -EOPNOTSUPP;

View File

@ -1083,6 +1083,7 @@ struct ib_mr *mlx5_ib_reg_dm_mr(struct ib_pd *pd, struct ib_dm *dm,
break;
case MLX5_IB_UAPI_DM_TYPE_STEERING_SW_ICM:
case MLX5_IB_UAPI_DM_TYPE_HEADER_MODIFY_SW_ICM:
case MLX5_IB_UAPI_DM_TYPE_HEADER_MODIFY_PATTERN_SW_ICM:
if (attr->access_flags & ~MLX5_IB_DM_SW_ICM_ALLOWED_ACCESS)
return ERR_PTR(-EINVAL);

View File

@ -573,7 +573,7 @@ int ipoib_send(struct net_device *dev, struct sk_buff *skb,
unsigned int usable_sge = priv->max_send_sge - !!skb_headlen(skb);
if (skb_is_gso(skb)) {
hlen = skb_transport_offset(skb) + tcp_hdrlen(skb);
hlen = skb_tcp_all_headers(skb);
phead = skb->data;
if (unlikely(!skb_pull(skb, hlen))) {
ipoib_warn(priv, "linear data too small\n");

View File

@ -1557,7 +1557,7 @@ reset_hfcsusb(struct hfcsusb *hw)
write_reg(hw, HFCUSB_USB_SIZE, (hw->packet_size / 8) |
((hw->packet_size / 8) << 4));
/* set USB_SIZE_I to match the the wMaxPacketSize for ISO transfers */
/* set USB_SIZE_I to match the wMaxPacketSize for ISO transfers */
write_reg(hw, HFCUSB_USB_SIZE_I, hw->iso_packet_size);
/* enable PCM/GCI master mode */

View File

@ -500,6 +500,8 @@ config NET_SB1000
source "drivers/net/phy/Kconfig"
source "drivers/net/can/Kconfig"
source "drivers/net/mctp/Kconfig"
source "drivers/net/mdio/Kconfig"

View File

@ -449,7 +449,7 @@ out:
dev_put(amt->dev);
}
/* Non-existant group is created as INCLUDE {empty}:
/* Non-existent group is created as INCLUDE {empty}:
*
* RFC 3376 - 5.1. Action on Change of Interface State
*
@ -1400,11 +1400,11 @@ static void amt_add_srcs(struct amt_dev *amt, struct amt_tunnel_list *tunnel,
int i;
if (!v6) {
igmp_grec = (struct igmpv3_grec *)grec;
igmp_grec = grec;
nsrcs = ntohs(igmp_grec->grec_nsrcs);
} else {
#if IS_ENABLED(CONFIG_IPV6)
mld_grec = (struct mld2_grec *)grec;
mld_grec = grec;
nsrcs = ntohs(mld_grec->grec_nsrcs);
#else
return;
@ -1485,11 +1485,11 @@ static void amt_lookup_act_srcs(struct amt_tunnel_list *tunnel,
int i, j;
if (!v6) {
igmp_grec = (struct igmpv3_grec *)grec;
igmp_grec = grec;
nsrcs = ntohs(igmp_grec->grec_nsrcs);
} else {
#if IS_ENABLED(CONFIG_IPV6)
mld_grec = (struct mld2_grec *)grec;
mld_grec = grec;
nsrcs = ntohs(mld_grec->grec_nsrcs);
#else
return;

View File

@ -1026,12 +1026,38 @@ out:
}
/**
* bond_choose_primary_or_current - select the primary or high priority slave
* @bond: our bonding struct
*
* - Check if there is a primary link. If the primary link was set and is up,
* go on and do link reselection.
*
* - If primary link is not set or down, find the highest priority link.
* If the highest priority link is not current slave, set it as primary
* link and do link reselection.
*/
static struct slave *bond_choose_primary_or_current(struct bonding *bond)
{
struct slave *prim = rtnl_dereference(bond->primary_slave);
struct slave *curr = rtnl_dereference(bond->curr_active_slave);
struct slave *slave, *hprio = NULL;
struct list_head *iter;
if (!prim || prim->link != BOND_LINK_UP) {
bond_for_each_slave(bond, slave, iter) {
if (slave->link == BOND_LINK_UP) {
hprio = hprio ?: slave;
if (slave->prio > hprio->prio)
hprio = slave;
}
}
if (hprio && hprio != curr) {
prim = hprio;
goto link_reselect;
}
if (!curr || curr->link != BOND_LINK_UP)
return NULL;
return curr;
@ -1042,6 +1068,7 @@ static struct slave *bond_choose_primary_or_current(struct bonding *bond)
return prim;
}
link_reselect:
if (!curr || curr->link != BOND_LINK_UP)
return prim;
@ -6220,45 +6247,33 @@ int bond_create(struct net *net, const char *name)
{
struct net_device *bond_dev;
struct bonding *bond;
struct alb_bond_info *bond_info;
int res;
int res = -ENOMEM;
rtnl_lock();
bond_dev = alloc_netdev_mq(sizeof(struct bonding),
name ? name : "bond%d", NET_NAME_UNKNOWN,
bond_setup, tx_queues);
if (!bond_dev) {
pr_err("%s: eek! can't alloc netdev!\n", name);
rtnl_unlock();
return -ENOMEM;
}
if (!bond_dev)
goto out;
/*
* Initialize rx_hashtbl_used_head to RLB_NULL_INDEX.
* It is set to 0 by default which is wrong.
*/
bond = netdev_priv(bond_dev);
bond_info = &(BOND_ALB_INFO(bond));
bond_info->rx_hashtbl_used_head = RLB_NULL_INDEX;
dev_net_set(bond_dev, net);
bond_dev->rtnl_link_ops = &bond_link_ops;
res = register_netdevice(bond_dev);
if (res < 0) {
free_netdev(bond_dev);
rtnl_unlock();
return res;
goto out;
}
netif_carrier_off(bond_dev);
bond_work_init_all(bond);
out:
rtnl_unlock();
return 0;
return res;
}
static int __net_init bond_net_init(struct net *net)

View File

@ -27,6 +27,7 @@ static size_t bond_get_slave_size(const struct net_device *bond_dev,
nla_total_size(sizeof(u16)) + /* IFLA_BOND_SLAVE_AD_AGGREGATOR_ID */
nla_total_size(sizeof(u8)) + /* IFLA_BOND_SLAVE_AD_ACTOR_OPER_PORT_STATE */
nla_total_size(sizeof(u16)) + /* IFLA_BOND_SLAVE_AD_PARTNER_OPER_PORT_STATE */
nla_total_size(sizeof(s32)) + /* IFLA_BOND_SLAVE_PRIO */
0;
}
@ -53,6 +54,9 @@ static int bond_fill_slave_info(struct sk_buff *skb,
if (nla_put_u16(skb, IFLA_BOND_SLAVE_QUEUE_ID, slave->queue_id))
goto nla_put_failure;
if (nla_put_s32(skb, IFLA_BOND_SLAVE_PRIO, slave->prio))
goto nla_put_failure;
if (BOND_MODE(slave->bond) == BOND_MODE_8023AD) {
const struct aggregator *agg;
const struct port *ad_port;
@ -117,6 +121,7 @@ static const struct nla_policy bond_policy[IFLA_BOND_MAX + 1] = {
static const struct nla_policy bond_slave_policy[IFLA_BOND_SLAVE_MAX + 1] = {
[IFLA_BOND_SLAVE_QUEUE_ID] = { .type = NLA_U16 },
[IFLA_BOND_SLAVE_PRIO] = { .type = NLA_S32 },
};
static int bond_validate(struct nlattr *tb[], struct nlattr *data[],
@ -151,7 +156,18 @@ static int bond_slave_changelink(struct net_device *bond_dev,
snprintf(queue_id_str, sizeof(queue_id_str), "%s:%u\n",
slave_dev->name, queue_id);
bond_opt_initstr(&newval, queue_id_str);
err = __bond_opt_set(bond, BOND_OPT_QUEUE_ID, &newval);
err = __bond_opt_set(bond, BOND_OPT_QUEUE_ID, &newval,
data[IFLA_BOND_SLAVE_QUEUE_ID], extack);
if (err)
return err;
}
if (data[IFLA_BOND_SLAVE_PRIO]) {
int prio = nla_get_s32(data[IFLA_BOND_SLAVE_PRIO]);
bond_opt_slave_initval(&newval, &slave_dev, prio);
err = __bond_opt_set(bond, BOND_OPT_PRIO, &newval,
data[IFLA_BOND_SLAVE_PRIO], extack);
if (err)
return err;
}
@ -175,7 +191,8 @@ static int bond_changelink(struct net_device *bond_dev, struct nlattr *tb[],
int mode = nla_get_u8(data[IFLA_BOND_MODE]);
bond_opt_initval(&newval, mode);
err = __bond_opt_set(bond, BOND_OPT_MODE, &newval);
err = __bond_opt_set(bond, BOND_OPT_MODE, &newval,
data[IFLA_BOND_MODE], extack);
if (err)
return err;
}
@ -192,7 +209,8 @@ static int bond_changelink(struct net_device *bond_dev, struct nlattr *tb[],
active_slave = slave_dev->name;
}
bond_opt_initstr(&newval, active_slave);
err = __bond_opt_set(bond, BOND_OPT_ACTIVE_SLAVE, &newval);
err = __bond_opt_set(bond, BOND_OPT_ACTIVE_SLAVE, &newval,
data[IFLA_BOND_ACTIVE_SLAVE], extack);
if (err)
return err;
}
@ -200,7 +218,8 @@ static int bond_changelink(struct net_device *bond_dev, struct nlattr *tb[],
miimon = nla_get_u32(data[IFLA_BOND_MIIMON]);
bond_opt_initval(&newval, miimon);
err = __bond_opt_set(bond, BOND_OPT_MIIMON, &newval);
err = __bond_opt_set(bond, BOND_OPT_MIIMON, &newval,
data[IFLA_BOND_MIIMON], extack);
if (err)
return err;
}
@ -208,7 +227,8 @@ static int bond_changelink(struct net_device *bond_dev, struct nlattr *tb[],
int updelay = nla_get_u32(data[IFLA_BOND_UPDELAY]);
bond_opt_initval(&newval, updelay);
err = __bond_opt_set(bond, BOND_OPT_UPDELAY, &newval);
err = __bond_opt_set(bond, BOND_OPT_UPDELAY, &newval,
data[IFLA_BOND_UPDELAY], extack);
if (err)
return err;
}
@ -216,7 +236,8 @@ static int bond_changelink(struct net_device *bond_dev, struct nlattr *tb[],
int downdelay = nla_get_u32(data[IFLA_BOND_DOWNDELAY]);
bond_opt_initval(&newval, downdelay);
err = __bond_opt_set(bond, BOND_OPT_DOWNDELAY, &newval);
err = __bond_opt_set(bond, BOND_OPT_DOWNDELAY, &newval,
data[IFLA_BOND_DOWNDELAY], extack);
if (err)
return err;
}
@ -224,7 +245,8 @@ static int bond_changelink(struct net_device *bond_dev, struct nlattr *tb[],
int delay = nla_get_u32(data[IFLA_BOND_PEER_NOTIF_DELAY]);
bond_opt_initval(&newval, delay);
err = __bond_opt_set(bond, BOND_OPT_PEER_NOTIF_DELAY, &newval);
err = __bond_opt_set(bond, BOND_OPT_PEER_NOTIF_DELAY, &newval,
data[IFLA_BOND_PEER_NOTIF_DELAY], extack);
if (err)
return err;
}
@ -232,7 +254,8 @@ static int bond_changelink(struct net_device *bond_dev, struct nlattr *tb[],
int use_carrier = nla_get_u8(data[IFLA_BOND_USE_CARRIER]);
bond_opt_initval(&newval, use_carrier);
err = __bond_opt_set(bond, BOND_OPT_USE_CARRIER, &newval);
err = __bond_opt_set(bond, BOND_OPT_USE_CARRIER, &newval,
data[IFLA_BOND_USE_CARRIER], extack);
if (err)
return err;
}
@ -240,12 +263,14 @@ static int bond_changelink(struct net_device *bond_dev, struct nlattr *tb[],
int arp_interval = nla_get_u32(data[IFLA_BOND_ARP_INTERVAL]);
if (arp_interval && miimon) {
netdev_err(bond->dev, "ARP monitoring cannot be used with MII monitoring\n");
NL_SET_ERR_MSG_ATTR(extack, data[IFLA_BOND_ARP_INTERVAL],
"ARP monitoring cannot be used with MII monitoring");
return -EINVAL;
}
bond_opt_initval(&newval, arp_interval);
err = __bond_opt_set(bond, BOND_OPT_ARP_INTERVAL, &newval);
err = __bond_opt_set(bond, BOND_OPT_ARP_INTERVAL, &newval,
data[IFLA_BOND_ARP_INTERVAL], extack);
if (err)
return err;
}
@ -264,7 +289,9 @@ static int bond_changelink(struct net_device *bond_dev, struct nlattr *tb[],
bond_opt_initval(&newval, (__force u64)target);
err = __bond_opt_set(bond, BOND_OPT_ARP_TARGETS,
&newval);
&newval,
data[IFLA_BOND_ARP_IP_TARGET],
extack);
if (err)
break;
i++;
@ -292,7 +319,9 @@ static int bond_changelink(struct net_device *bond_dev, struct nlattr *tb[],
bond_opt_initextra(&newval, &addr6, sizeof(addr6));
err = __bond_opt_set(bond, BOND_OPT_NS_TARGETS,
&newval);
&newval,
data[IFLA_BOND_NS_IP6_TARGET],
extack);
if (err)
break;
i++;
@ -307,12 +336,14 @@ static int bond_changelink(struct net_device *bond_dev, struct nlattr *tb[],
int arp_validate = nla_get_u32(data[IFLA_BOND_ARP_VALIDATE]);
if (arp_validate && miimon) {
netdev_err(bond->dev, "ARP validating cannot be used with MII monitoring\n");
NL_SET_ERR_MSG_ATTR(extack, data[IFLA_BOND_ARP_INTERVAL],
"ARP validating cannot be used with MII monitoring");
return -EINVAL;
}
bond_opt_initval(&newval, arp_validate);
err = __bond_opt_set(bond, BOND_OPT_ARP_VALIDATE, &newval);
err = __bond_opt_set(bond, BOND_OPT_ARP_VALIDATE, &newval,
data[IFLA_BOND_ARP_VALIDATE], extack);
if (err)
return err;
}
@ -321,7 +352,8 @@ static int bond_changelink(struct net_device *bond_dev, struct nlattr *tb[],
nla_get_u32(data[IFLA_BOND_ARP_ALL_TARGETS]);
bond_opt_initval(&newval, arp_all_targets);
err = __bond_opt_set(bond, BOND_OPT_ARP_ALL_TARGETS, &newval);
err = __bond_opt_set(bond, BOND_OPT_ARP_ALL_TARGETS, &newval,
data[IFLA_BOND_ARP_ALL_TARGETS], extack);
if (err)
return err;
}
@ -335,7 +367,8 @@ static int bond_changelink(struct net_device *bond_dev, struct nlattr *tb[],
primary = dev->name;
bond_opt_initstr(&newval, primary);
err = __bond_opt_set(bond, BOND_OPT_PRIMARY, &newval);
err = __bond_opt_set(bond, BOND_OPT_PRIMARY, &newval,
data[IFLA_BOND_PRIMARY], extack);
if (err)
return err;
}
@ -344,7 +377,8 @@ static int bond_changelink(struct net_device *bond_dev, struct nlattr *tb[],
nla_get_u8(data[IFLA_BOND_PRIMARY_RESELECT]);
bond_opt_initval(&newval, primary_reselect);
err = __bond_opt_set(bond, BOND_OPT_PRIMARY_RESELECT, &newval);
err = __bond_opt_set(bond, BOND_OPT_PRIMARY_RESELECT, &newval,
data[IFLA_BOND_PRIMARY_RESELECT], extack);
if (err)
return err;
}
@ -353,7 +387,8 @@ static int bond_changelink(struct net_device *bond_dev, struct nlattr *tb[],
nla_get_u8(data[IFLA_BOND_FAIL_OVER_MAC]);
bond_opt_initval(&newval, fail_over_mac);
err = __bond_opt_set(bond, BOND_OPT_FAIL_OVER_MAC, &newval);
err = __bond_opt_set(bond, BOND_OPT_FAIL_OVER_MAC, &newval,
data[IFLA_BOND_FAIL_OVER_MAC], extack);
if (err)
return err;
}
@ -362,7 +397,8 @@ static int bond_changelink(struct net_device *bond_dev, struct nlattr *tb[],
nla_get_u8(data[IFLA_BOND_XMIT_HASH_POLICY]);
bond_opt_initval(&newval, xmit_hash_policy);
err = __bond_opt_set(bond, BOND_OPT_XMIT_HASH, &newval);
err = __bond_opt_set(bond, BOND_OPT_XMIT_HASH, &newval,
data[IFLA_BOND_XMIT_HASH_POLICY], extack);
if (err)
return err;
}
@ -371,7 +407,8 @@ static int bond_changelink(struct net_device *bond_dev, struct nlattr *tb[],
nla_get_u32(data[IFLA_BOND_RESEND_IGMP]);
bond_opt_initval(&newval, resend_igmp);
err = __bond_opt_set(bond, BOND_OPT_RESEND_IGMP, &newval);
err = __bond_opt_set(bond, BOND_OPT_RESEND_IGMP, &newval,
data[IFLA_BOND_RESEND_IGMP], extack);
if (err)
return err;
}
@ -380,7 +417,8 @@ static int bond_changelink(struct net_device *bond_dev, struct nlattr *tb[],
nla_get_u8(data[IFLA_BOND_NUM_PEER_NOTIF]);
bond_opt_initval(&newval, num_peer_notif);
err = __bond_opt_set(bond, BOND_OPT_NUM_PEER_NOTIF, &newval);
err = __bond_opt_set(bond, BOND_OPT_NUM_PEER_NOTIF, &newval,
data[IFLA_BOND_NUM_PEER_NOTIF], extack);
if (err)
return err;
}
@ -389,7 +427,8 @@ static int bond_changelink(struct net_device *bond_dev, struct nlattr *tb[],
nla_get_u8(data[IFLA_BOND_ALL_SLAVES_ACTIVE]);
bond_opt_initval(&newval, all_slaves_active);
err = __bond_opt_set(bond, BOND_OPT_ALL_SLAVES_ACTIVE, &newval);
err = __bond_opt_set(bond, BOND_OPT_ALL_SLAVES_ACTIVE, &newval,
data[IFLA_BOND_ALL_SLAVES_ACTIVE], extack);
if (err)
return err;
}
@ -398,7 +437,8 @@ static int bond_changelink(struct net_device *bond_dev, struct nlattr *tb[],
nla_get_u32(data[IFLA_BOND_MIN_LINKS]);
bond_opt_initval(&newval, min_links);
err = __bond_opt_set(bond, BOND_OPT_MINLINKS, &newval);
err = __bond_opt_set(bond, BOND_OPT_MINLINKS, &newval,
data[IFLA_BOND_MIN_LINKS], extack);
if (err)
return err;
}
@ -407,7 +447,8 @@ static int bond_changelink(struct net_device *bond_dev, struct nlattr *tb[],
nla_get_u32(data[IFLA_BOND_LP_INTERVAL]);
bond_opt_initval(&newval, lp_interval);
err = __bond_opt_set(bond, BOND_OPT_LP_INTERVAL, &newval);
err = __bond_opt_set(bond, BOND_OPT_LP_INTERVAL, &newval,
data[IFLA_BOND_LP_INTERVAL], extack);
if (err)
return err;
}
@ -416,7 +457,8 @@ static int bond_changelink(struct net_device *bond_dev, struct nlattr *tb[],
nla_get_u32(data[IFLA_BOND_PACKETS_PER_SLAVE]);
bond_opt_initval(&newval, packets_per_slave);
err = __bond_opt_set(bond, BOND_OPT_PACKETS_PER_SLAVE, &newval);
err = __bond_opt_set(bond, BOND_OPT_PACKETS_PER_SLAVE, &newval,
data[IFLA_BOND_PACKETS_PER_SLAVE], extack);
if (err)
return err;
}
@ -425,7 +467,8 @@ static int bond_changelink(struct net_device *bond_dev, struct nlattr *tb[],
int lacp_active = nla_get_u8(data[IFLA_BOND_AD_LACP_ACTIVE]);
bond_opt_initval(&newval, lacp_active);
err = __bond_opt_set(bond, BOND_OPT_LACP_ACTIVE, &newval);
err = __bond_opt_set(bond, BOND_OPT_LACP_ACTIVE, &newval,
data[IFLA_BOND_AD_LACP_ACTIVE], extack);
if (err)
return err;
}
@ -435,7 +478,8 @@ static int bond_changelink(struct net_device *bond_dev, struct nlattr *tb[],
nla_get_u8(data[IFLA_BOND_AD_LACP_RATE]);
bond_opt_initval(&newval, lacp_rate);
err = __bond_opt_set(bond, BOND_OPT_LACP_RATE, &newval);
err = __bond_opt_set(bond, BOND_OPT_LACP_RATE, &newval,
data[IFLA_BOND_AD_LACP_RATE], extack);
if (err)
return err;
}
@ -444,7 +488,8 @@ static int bond_changelink(struct net_device *bond_dev, struct nlattr *tb[],
nla_get_u8(data[IFLA_BOND_AD_SELECT]);
bond_opt_initval(&newval, ad_select);
err = __bond_opt_set(bond, BOND_OPT_AD_SELECT, &newval);
err = __bond_opt_set(bond, BOND_OPT_AD_SELECT, &newval,
data[IFLA_BOND_AD_SELECT], extack);
if (err)
return err;
}
@ -453,7 +498,8 @@ static int bond_changelink(struct net_device *bond_dev, struct nlattr *tb[],
nla_get_u16(data[IFLA_BOND_AD_ACTOR_SYS_PRIO]);
bond_opt_initval(&newval, actor_sys_prio);
err = __bond_opt_set(bond, BOND_OPT_AD_ACTOR_SYS_PRIO, &newval);
err = __bond_opt_set(bond, BOND_OPT_AD_ACTOR_SYS_PRIO, &newval,
data[IFLA_BOND_AD_ACTOR_SYS_PRIO], extack);
if (err)
return err;
}
@ -462,7 +508,8 @@ static int bond_changelink(struct net_device *bond_dev, struct nlattr *tb[],
nla_get_u16(data[IFLA_BOND_AD_USER_PORT_KEY]);
bond_opt_initval(&newval, port_key);
err = __bond_opt_set(bond, BOND_OPT_AD_USER_PORT_KEY, &newval);
err = __bond_opt_set(bond, BOND_OPT_AD_USER_PORT_KEY, &newval,
data[IFLA_BOND_AD_USER_PORT_KEY], extack);
if (err)
return err;
}
@ -472,7 +519,8 @@ static int bond_changelink(struct net_device *bond_dev, struct nlattr *tb[],
bond_opt_initval(&newval,
nla_get_u64(data[IFLA_BOND_AD_ACTOR_SYSTEM]));
err = __bond_opt_set(bond, BOND_OPT_AD_ACTOR_SYSTEM, &newval);
err = __bond_opt_set(bond, BOND_OPT_AD_ACTOR_SYSTEM, &newval,
data[IFLA_BOND_AD_ACTOR_SYSTEM], extack);
if (err)
return err;
}
@ -480,7 +528,8 @@ static int bond_changelink(struct net_device *bond_dev, struct nlattr *tb[],
int dynamic_lb = nla_get_u8(data[IFLA_BOND_TLB_DYNAMIC_LB]);
bond_opt_initval(&newval, dynamic_lb);
err = __bond_opt_set(bond, BOND_OPT_TLB_DYNAMIC_LB, &newval);
err = __bond_opt_set(bond, BOND_OPT_TLB_DYNAMIC_LB, &newval,
data[IFLA_BOND_TLB_DYNAMIC_LB], extack);
if (err)
return err;
}
@ -489,7 +538,8 @@ static int bond_changelink(struct net_device *bond_dev, struct nlattr *tb[],
int missed_max = nla_get_u8(data[IFLA_BOND_MISSED_MAX]);
bond_opt_initval(&newval, missed_max);
err = __bond_opt_set(bond, BOND_OPT_MISSED_MAX, &newval);
err = __bond_opt_set(bond, BOND_OPT_MISSED_MAX, &newval,
data[IFLA_BOND_MISSED_MAX], extack);
if (err)
return err;
}

View File

@ -40,6 +40,8 @@ static int bond_option_arp_validate_set(struct bonding *bond,
const struct bond_opt_value *newval);
static int bond_option_arp_all_targets_set(struct bonding *bond,
const struct bond_opt_value *newval);
static int bond_option_prio_set(struct bonding *bond,
const struct bond_opt_value *newval);
static int bond_option_primary_set(struct bonding *bond,
const struct bond_opt_value *newval);
static int bond_option_primary_reselect_set(struct bonding *bond,
@ -365,6 +367,16 @@ static const struct bond_option bond_opts[BOND_OPT_LAST] = {
.values = bond_intmax_tbl,
.set = bond_option_miimon_set
},
[BOND_OPT_PRIO] = {
.id = BOND_OPT_PRIO,
.name = "prio",
.desc = "Link priority for failover re-selection",
.flags = BOND_OPTFLAG_RAWVAL,
.unsuppmodes = BOND_MODE_ALL_EX(BIT(BOND_MODE_ACTIVEBACKUP) |
BIT(BOND_MODE_TLB) |
BIT(BOND_MODE_ALB)),
.set = bond_option_prio_set
},
[BOND_OPT_PRIMARY] = {
.id = BOND_OPT_PRIMARY,
.name = "primary",
@ -632,27 +644,35 @@ static int bond_opt_check_deps(struct bonding *bond,
}
static void bond_opt_dep_print(struct bonding *bond,
const struct bond_option *opt)
const struct bond_option *opt,
struct nlattr *bad_attr,
struct netlink_ext_ack *extack)
{
const struct bond_opt_value *modeval;
struct bond_params *params;
params = &bond->params;
modeval = bond_opt_get_val(BOND_OPT_MODE, params->mode);
if (test_bit(params->mode, &opt->unsuppmodes))
if (test_bit(params->mode, &opt->unsuppmodes)) {
netdev_err(bond->dev, "option %s: mode dependency failed, not supported in mode %s(%llu)\n",
opt->name, modeval->string, modeval->value);
NL_SET_ERR_MSG_ATTR(extack, bad_attr,
"option not supported in mode");
}
}
static void bond_opt_error_interpret(struct bonding *bond,
const struct bond_option *opt,
int error, const struct bond_opt_value *val)
int error, const struct bond_opt_value *val,
struct nlattr *bad_attr,
struct netlink_ext_ack *extack)
{
const struct bond_opt_value *minval, *maxval;
char *p;
switch (error) {
case -EINVAL:
NL_SET_ERR_MSG_ATTR(extack, bad_attr, "invalid option value");
if (val) {
if (val->string) {
/* sometimes RAWVAL opts may have new lines */
@ -674,13 +694,17 @@ static void bond_opt_error_interpret(struct bonding *bond,
opt->name, minval ? minval->value : 0, maxval->value);
break;
case -EACCES:
bond_opt_dep_print(bond, opt);
bond_opt_dep_print(bond, opt, bad_attr, extack);
break;
case -ENOTEMPTY:
NL_SET_ERR_MSG_ATTR(extack, bad_attr,
"unable to set option because the bond device has slaves");
netdev_err(bond->dev, "option %s: unable to set because the bond device has slaves\n",
opt->name);
break;
case -EBUSY:
NL_SET_ERR_MSG_ATTR(extack, bad_attr,
"unable to set option because the bond is up");
netdev_err(bond->dev, "option %s: unable to set because the bond device is up\n",
opt->name);
break;
@ -691,6 +715,8 @@ static void bond_opt_error_interpret(struct bonding *bond,
*p = '\0';
netdev_err(bond->dev, "option %s: interface %s does not exist!\n",
opt->name, val->string);
NL_SET_ERR_MSG_ATTR(extack, bad_attr,
"interface does not exist");
}
break;
default:
@ -703,13 +729,17 @@ static void bond_opt_error_interpret(struct bonding *bond,
* @bond: target bond device
* @option: option to set
* @val: value to set it to
* @bad_attr: netlink attribue that caused the error
* @extack: extended netlink error structure, used when an error message
* needs to be returned to the caller via netlink
*
* This function is used to change the bond's option value, it can be
* used for both enabling/changing an option and for disabling it. RTNL lock
* must be obtained before calling this function.
*/
int __bond_opt_set(struct bonding *bond,
unsigned int option, struct bond_opt_value *val)
unsigned int option, struct bond_opt_value *val,
struct nlattr *bad_attr, struct netlink_ext_ack *extack)
{
const struct bond_opt_value *retval = NULL;
const struct bond_option *opt;
@ -731,7 +761,7 @@ int __bond_opt_set(struct bonding *bond,
ret = opt->set(bond, retval);
out:
if (ret)
bond_opt_error_interpret(bond, opt, ret, val);
bond_opt_error_interpret(bond, opt, ret, val, bad_attr, extack);
return ret;
}
@ -753,7 +783,7 @@ int __bond_opt_set_notify(struct bonding *bond,
ASSERT_RTNL();
ret = __bond_opt_set(bond, option, val);
ret = __bond_opt_set(bond, option, val, NULL, NULL);
if (!ret && (bond->dev->reg_state == NETREG_REGISTERED))
call_netdevice_notifiers(NETDEV_CHANGEINFODATA, bond->dev);
@ -1288,6 +1318,27 @@ static int bond_option_missed_max_set(struct bonding *bond,
return 0;
}
static int bond_option_prio_set(struct bonding *bond,
const struct bond_opt_value *newval)
{
struct slave *slave;
slave = bond_slave_get_rtnl(newval->slave_dev);
if (!slave) {
netdev_dbg(newval->slave_dev, "%s called on NULL slave\n", __func__);
return -ENODEV;
}
slave->prio = newval->value;
if (rtnl_dereference(bond->primary_slave))
slave_warn(bond->dev, slave->dev,
"prio updated, but will not affect failover re-selection as primary slave have been set\n");
else
bond_select_active_slave(bond);
return 0;
}
static int bond_option_primary_set(struct bonding *bond,
const struct bond_opt_value *newval)
{

View File

@ -1,5 +1,26 @@
# SPDX-License-Identifier: GPL-2.0-only
menu "CAN Device Drivers"
menuconfig CAN_DEV
tristate "CAN Device Drivers"
default y
depends on CAN
help
Controller Area Network (CAN) is serial communications protocol up to
1Mbit/s for its original release (now known as Classical CAN) and up
to 8Mbit/s for the more recent CAN with Flexible Data-Rate
(CAN-FD). The CAN bus was originally mainly for automotive, but is now
widely used in marine (NMEA2000), industrial, and medical
applications. More information on the CAN network protocol family
PF_CAN is contained in <Documentation/networking/can.rst>.
This section contains all the CAN(-FD) device drivers including the
virtual ones. If you own such devices or plan to use the virtual CAN
interfaces to develop applications, say Y here.
To compile as a module, choose M here: the module will be called
can-dev.
if CAN_DEV
config CAN_VCAN
tristate "Virtual Local CAN Interface (vcan)"
@ -28,35 +49,22 @@ config CAN_VXCAN
This driver can also be built as a module. If so, the module
will be called vxcan.
config CAN_SLCAN
tristate "Serial / USB serial CAN Adaptors (slcan)"
depends on TTY
help
CAN driver for several 'low cost' CAN interfaces that are attached
via serial lines or via USB-to-serial adapters using the LAWICEL
ASCII protocol. The driver implements the tty linediscipline N_SLCAN.
As only the sending and receiving of CAN frames is implemented, this
driver should work with the (serial/USB) CAN hardware from:
www.canusb.com / www.can232.com / www.mictronics.de / www.canhack.de
Userspace tools to attach the SLCAN line discipline (slcan_attach,
slcand) can be found in the can-utils at the linux-can project, see
https://github.com/linux-can/can-utils for details.
The slcan driver supports up to 10 CAN netdevices by default which
can be changed by the 'maxdev=xx' module option. This driver can
also be built as a module. If so, the module will be called slcan.
config CAN_DEV
tristate "Platform CAN drivers with Netlink support"
config CAN_NETLINK
bool "CAN device drivers with Netlink support"
default y
help
Enables the common framework for platform CAN drivers with Netlink
support. This is the standard library for CAN drivers.
If unsure, say Y.
Enables the common framework for CAN device drivers. This is the
standard library and provides features for the Netlink interface such
as bittiming validation, support of CAN error states, device restart
and others.
if CAN_DEV
The additional features selected by this option will be added to the
can-dev module.
This is required by all platform and hardware CAN drivers. If you
plan to use such devices or if unsure, say Y.
if CAN_NETLINK
config CAN_CALC_BITTIMING
bool "CAN bit-timing calculation"
@ -69,8 +77,15 @@ config CAN_CALC_BITTIMING
source clock frequencies. Disabling saves some space, but then the
bit-timing parameters must be specified directly using the Netlink
arguments "tq", "prop_seg", "phase_seg1", "phase_seg2" and "sjw".
The additional features selected by this option will be added to the
can-dev module.
If unsure, say Y.
config CAN_RX_OFFLOAD
bool
config CAN_AT91
tristate "Atmel AT91 onchip CAN controller"
depends on (ARCH_AT91 || COMPILE_TEST) && HAS_IOMEM
@ -78,10 +93,29 @@ config CAN_AT91
This is a driver for the SoC CAN controller in Atmel's AT91SAM9263
and AT91SAM9X5 processors.
config CAN_CAN327
tristate "Serial / USB serial ELM327 based OBD-II Interfaces (can327)"
depends on TTY
select CAN_RX_OFFLOAD
help
CAN driver for several 'low cost' OBD-II interfaces based on the
ELM327 OBD-II interpreter chip.
This is a best effort driver - the ELM327 interface was never
designed to be used as a standalone CAN interface. However, it can
still be used for simple request-response protocols (such as OBD II),
and to monitor broadcast messages on a bus (such as in a vehicle).
Please refer to the documentation for information on how to use it:
Documentation/networking/device_drivers/can/can327.rst
If this driver is built as a module, it will be called can327.
config CAN_FLEXCAN
tristate "Support for Freescale FLEXCAN based chips"
depends on OF || COLDFIRE || COMPILE_TEST
depends on HAS_IOMEM
select CAN_RX_OFFLOAD
help
Say Y here if you want to support for Freescale FlexCAN.
@ -118,6 +152,26 @@ config CAN_KVASER_PCIEFD
Kvaser Mini PCI Express HS v2
Kvaser Mini PCI Express 2xHS v2
config CAN_SLCAN
tristate "Serial / USB serial CAN Adaptors (slcan)"
depends on TTY
help
CAN driver for several 'low cost' CAN interfaces that are attached
via serial lines or via USB-to-serial adapters using the LAWICEL
ASCII protocol. The driver implements the tty linediscipline N_SLCAN.
As only the sending and receiving of CAN frames is implemented, this
driver should work with the (serial/USB) CAN hardware from:
www.canusb.com / www.can232.com / www.mictronics.de / www.canhack.de
Userspace tools to attach the SLCAN line discipline (slcan_attach,
slcand) can be found in the can-utils at the linux-can project, see
https://github.com/linux-can/can-utils for details.
The slcan driver supports up to 10 CAN netdevices by default which
can be changed by the 'maxdev=xx' module option. This driver can
also be built as a module. If so, the module will be called slcan.
config CAN_SUN4I
tristate "Allwinner A10 CAN controller"
depends on MACH_SUN4I || MACH_SUN7I || COMPILE_TEST
@ -131,6 +185,7 @@ config CAN_SUN4I
config CAN_TI_HECC
depends on ARM
tristate "TI High End CAN Controller"
select CAN_RX_OFFLOAD
help
Driver for TI HECC (High End CAN Controller) module found on many
TI devices. The device specifications are available from www.ti.com
@ -164,7 +219,7 @@ source "drivers/net/can/softing/Kconfig"
source "drivers/net/can/spi/Kconfig"
source "drivers/net/can/usb/Kconfig"
endif
endif #CAN_NETLINK
config CAN_DEBUG_DEVICES
bool "CAN devices debugging messages"
@ -174,4 +229,4 @@ config CAN_DEBUG_DEVICES
a problem with CAN support and want to see more of what is going
on.
endmenu
endif #CAN_DEV

View File

@ -5,7 +5,7 @@
obj-$(CONFIG_CAN_VCAN) += vcan.o
obj-$(CONFIG_CAN_VXCAN) += vxcan.o
obj-$(CONFIG_CAN_SLCAN) += slcan.o
obj-$(CONFIG_CAN_SLCAN) += slcan/
obj-y += dev/
obj-y += rcar/
@ -14,6 +14,7 @@ obj-y += usb/
obj-y += softing/
obj-$(CONFIG_CAN_AT91) += at91_can.o
obj-$(CONFIG_CAN_CAN327) += can327.o
obj-$(CONFIG_CAN_CC770) += cc770/
obj-$(CONFIG_CAN_C_CAN) += c_can/
obj-$(CONFIG_CAN_CTUCANFD) += ctucanfd/

View File

@ -8,6 +8,7 @@
#include <linux/clk.h>
#include <linux/errno.h>
#include <linux/ethtool.h>
#include <linux/if_arp.h>
#include <linux/interrupt.h>
#include <linux/kernel.h>
@ -1152,6 +1153,10 @@ static const struct net_device_ops at91_netdev_ops = {
.ndo_change_mtu = can_change_mtu,
};
static const struct ethtool_ops at91_ethtool_ops = {
.get_ts_info = ethtool_op_get_ts_info,
};
static ssize_t mb0_id_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
@ -1293,6 +1298,7 @@ static int at91_can_probe(struct platform_device *pdev)
}
dev->netdev_ops = &at91_netdev_ops;
dev->ethtool_ops = &at91_ethtool_ops;
dev->irq = irq;
dev->flags |= IFF_ECHO;

View File

@ -223,7 +223,7 @@ int c_can_power_up(struct net_device *dev);
int c_can_power_down(struct net_device *dev);
#endif
void c_can_set_ethtool_ops(struct net_device *dev);
extern const struct ethtool_ops c_can_ethtool_ops;
static inline u8 c_can_get_tx_head(const struct c_can_tx_ring *ring)
{

View File

@ -24,11 +24,7 @@ static void c_can_get_ringparam(struct net_device *netdev,
ring->tx_pending = priv->msg_obj_tx_num;
}
static const struct ethtool_ops c_can_ethtool_ops = {
const struct ethtool_ops c_can_ethtool_ops = {
.get_ringparam = c_can_get_ringparam,
.get_ts_info = ethtool_op_get_ts_info,
};
void c_can_set_ethtool_ops(struct net_device *netdev)
{
netdev->ethtool_ops = &c_can_ethtool_ops;
}

View File

@ -952,15 +952,14 @@ static int c_can_handle_state_change(struct net_device *dev,
switch (error_type) {
case C_CAN_NO_ERROR:
/* error warning state */
cf->can_id |= CAN_ERR_CRTL;
cf->can_id |= CAN_ERR_CRTL | CAN_ERR_CNT;
cf->data[1] = CAN_ERR_CRTL_ACTIVE;
cf->data[6] = bec.txerr;
cf->data[7] = bec.rxerr;
break;
case C_CAN_ERROR_WARNING:
/* error warning state */
cf->can_id |= CAN_ERR_CRTL;
cf->can_id |= CAN_ERR_CRTL | CAN_ERR_CNT;
cf->data[1] = (bec.txerr > bec.rxerr) ?
CAN_ERR_CRTL_TX_WARNING :
CAN_ERR_CRTL_RX_WARNING;
@ -970,7 +969,7 @@ static int c_can_handle_state_change(struct net_device *dev,
break;
case C_CAN_ERROR_PASSIVE:
/* error passive state */
cf->can_id |= CAN_ERR_CRTL;
cf->can_id |= CAN_ERR_CRTL | CAN_ERR_CNT;
if (rx_err_passive)
cf->data[1] |= CAN_ERR_CRTL_RX_PASSIVE;
if (bec.txerr > 127)
@ -1365,7 +1364,7 @@ int register_c_can_dev(struct net_device *dev)
dev->flags |= IFF_ECHO; /* we support local echo */
dev->netdev_ops = &c_can_netdev_ops;
c_can_set_ethtool_ops(dev);
dev->ethtool_ops = &c_can_ethtool_ops;
return register_candev(dev);
}

1144
drivers/net/can/can327.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -17,6 +17,7 @@
#include <linux/ptrace.h>
#include <linux/string.h>
#include <linux/errno.h>
#include <linux/ethtool.h>
#include <linux/netdevice.h>
#include <linux/if_arp.h>
#include <linux/if_ether.h>
@ -512,6 +513,7 @@ static int cc770_err(struct net_device *dev, u8 status)
/* Use extended functions of the CC770 */
if (priv->control_normal_mode & CTRL_EAF) {
cf->can_id |= CAN_ERR_CNT;
cf->data[6] = cc770_read_reg(priv, tx_error_counter);
cf->data[7] = cc770_read_reg(priv, rx_error_counter);
}
@ -835,6 +837,10 @@ static const struct net_device_ops cc770_netdev_ops = {
.ndo_change_mtu = can_change_mtu,
};
static const struct ethtool_ops cc770_ethtool_ops = {
.get_ts_info = ethtool_op_get_ts_info,
};
int register_cc770dev(struct net_device *dev)
{
struct cc770_priv *priv = netdev_priv(dev);
@ -845,6 +851,7 @@ int register_cc770dev(struct net_device *dev)
return err;
dev->netdev_ops = &cc770_netdev_ops;
dev->ethtool_ops = &cc770_ethtool_ops;
dev->flags |= IFF_ECHO; /* we support local echo */

View File

@ -19,6 +19,7 @@
#include <linux/clk.h>
#include <linux/errno.h>
#include <linux/ethtool.h>
#include <linux/init.h>
#include <linux/bitfield.h>
#include <linux/interrupt.h>
@ -847,7 +848,7 @@ static void ctucan_err_interrupt(struct net_device *ndev, u32 isr)
case CAN_STATE_ERROR_PASSIVE:
priv->can.can_stats.error_passive++;
if (skb) {
cf->can_id |= CAN_ERR_CRTL;
cf->can_id |= CAN_ERR_CRTL | CAN_ERR_CNT;
cf->data[1] = (bec.rxerr > 127) ?
CAN_ERR_CRTL_RX_PASSIVE :
CAN_ERR_CRTL_TX_PASSIVE;
@ -858,7 +859,7 @@ static void ctucan_err_interrupt(struct net_device *ndev, u32 isr)
case CAN_STATE_ERROR_WARNING:
priv->can.can_stats.error_warning++;
if (skb) {
cf->can_id |= CAN_ERR_CRTL;
cf->can_id |= CAN_ERR_CRTL | CAN_ERR_CNT;
cf->data[1] |= (bec.txerr > bec.rxerr) ?
CAN_ERR_CRTL_TX_WARNING :
CAN_ERR_CRTL_RX_WARNING;
@ -867,6 +868,7 @@ static void ctucan_err_interrupt(struct net_device *ndev, u32 isr)
}
break;
case CAN_STATE_ERROR_ACTIVE:
cf->can_id |= CAN_ERR_CNT;
cf->data[1] = CAN_ERR_CRTL_ACTIVE;
cf->data[6] = bec.txerr;
cf->data[7] = bec.rxerr;
@ -1087,7 +1089,7 @@ clear:
/**
* ctucan_interrupt() - CAN Isr
* @irq: irq number
* @dev_id: device id poniter
* @dev_id: device id pointer
*
* This is the CTU CAN FD ISR. It checks for the type of interrupt
* and invokes the corresponding ISR.
@ -1300,6 +1302,10 @@ static const struct net_device_ops ctucan_netdev_ops = {
.ndo_change_mtu = can_change_mtu,
};
static const struct ethtool_ops ctucan_ethtool_ops = {
.get_ts_info = ethtool_op_get_ts_info,
};
int ctucan_suspend(struct device *dev)
{
struct net_device *ndev = dev_get_drvdata(dev);
@ -1376,6 +1382,7 @@ int ctucan_probe_common(struct device *dev, void __iomem *addr, int irq, unsigne
set_drvdata_fnc(dev, ndev);
SET_NETDEV_DEV(ndev, dev);
ndev->netdev_ops = &ctucan_netdev_ops;
ndev->ethtool_ops = &ctucan_ethtool_ops;
/* Getting the can_clk info */
if (!can_clk_rate) {

Some files were not shown because too many files have changed in this diff Show More