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:
commit
f86d1fbbe7
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
----------------------------------------------------------
|
||||
|
||||
|
|
|
@ -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
|
||||
=================
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@ that goes into great technical depth about the BPF Architecture.
|
|||
faq
|
||||
syscall_api
|
||||
helpers
|
||||
kfuncs
|
||||
programs
|
||||
maps
|
||||
bpf_prog_run
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
|
@ -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
|
||||
---
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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:
|
||||
|
|
|
@ -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>;
|
||||
};
|
|
@ -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>;
|
||||
};
|
|
@ -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>;
|
||||
};
|
||||
|
|
@ -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>;
|
||||
|
|
|
@ -48,7 +48,7 @@ properties:
|
|||
"^led@[01]$":
|
||||
type: object
|
||||
description: Hellcreek leds
|
||||
$ref: ../../leds/common.yaml#
|
||||
$ref: /schemas/leds/common.yaml#
|
||||
|
||||
properties:
|
||||
reg:
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
|
@ -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>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
|
@ -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.
|
||||
|
||||
ð {
|
||||
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.
|
||||
|
||||
ð {
|
||||
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;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
|
@ -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>;
|
||||
};
|
||||
};
|
||||
};
|
|
@ -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
|
||||
|
||||
...
|
||||
|
|
|
@ -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:
|
||||
- |
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
||||
|
|
|
@ -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:
|
||||
- |
|
||||
|
|
|
@ -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:
|
||||
- |
|
||||
|
|
|
@ -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:
|
||||
- |
|
||||
|
|
|
@ -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:
|
||||
- |
|
||||
|
|
|
@ -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";
|
||||
};
|
|
@ -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";
|
||||
};
|
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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>;
|
||||
};
|
||||
|
|
|
@ -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;
|
||||
};
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
|
@ -10,6 +10,7 @@ Contents:
|
|||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
can327
|
||||
ctu/ctucanfd-driver
|
||||
freescale/flexcan
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
========================
|
||||
|
|
|
@ -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
|
|
@ -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.
|
|
@ -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
|
|
@ -38,6 +38,7 @@ general.
|
|||
devlink-region
|
||||
devlink-resource
|
||||
devlink-reload
|
||||
devlink-selftests
|
||||
devlink-trap
|
||||
devlink-linecard
|
||||
|
||||
|
|
|
@ -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
|
||||
=====================
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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``.
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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.
|
||||
|
|
49
MAINTAINERS
49
MAINTAINERS
|
@ -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>
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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>;
|
||||
};
|
||||
};
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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>;
|
||||
};
|
||||
};
|
||||
|
|
|
@ -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>;
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -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>;
|
||||
|
|
|
@ -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>;
|
||||
|
|
|
@ -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>;
|
||||
};
|
||||
|
||||
|
|
|
@ -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";
|
||||
};
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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>;
|
||||
/*
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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";
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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>;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)) {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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, ¶ms);
|
||||
}
|
||||
|
||||
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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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/
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -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 */
|
||||
|
||||
|
|
|
@ -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
Loading…
Reference in New Issue