mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2024-12-29 17:23:36 +00:00
Networking changes for 5.18.
Core ---- - Introduce XDP multi-buffer support, allowing the use of XDP with jumbo frame MTUs and combination with Rx coalescing offloads (LRO). - Speed up netns dismantling (5x) and lower the memory cost a little. Remove unnecessary per-netns sockets. Scope some lists to a netns. Cut down RCU syncing. Use batch methods. Allow netdev registration to complete out of order. - Support distinguishing timestamp types (ingress vs egress) and maintaining them across packet scrubbing points (e.g. redirect). - Continue the work of annotating packet drop reasons throughout the stack. - Switch netdev error counters from an atomic to dynamically allocated per-CPU counters. - Rework a few preempt_disable(), local_irq_save() and busy waiting sections problematic on PREEMPT_RT. - Extend the ref_tracker to allow catching use-after-free bugs. BPF --- - Introduce "packing allocator" for BPF JIT images. JITed code is marked read only, and used to be allocated at page granularity. Custom allocator allows for more efficient memory use, lower iTLB pressure and prevents identity mapping huge pages from getting split. - Make use of BTF type annotations (e.g. __user, __percpu) to enforce the correct probe read access method, add appropriate helpers. - Convert the BPF preload to use light skeleton and drop the user-mode-driver dependency. - Allow XDP BPF_PROG_RUN test infra to send real packets, enabling its use as a packet generator. - Allow local storage memory to be allocated with GFP_KERNEL if called from a hook allowed to sleep. - Introduce fprobe (multi kprobe) to speed up mass attachment (arch bits to come later). - Add unstable conntrack lookup helpers for BPF by using the BPF kfunc infra. - Allow cgroup BPF progs to return custom errors to user space. - Add support for AF_UNIX iterator batching. - Allow iterator programs to use sleepable helpers. - Support JIT of add, and, or, xor and xchg atomic ops on arm64. - Add BTFGen support to bpftool which allows to use CO-RE in kernels without BTF info. - Large number of libbpf API improvements, cleanups and deprecations. Protocols --------- - Micro-optimize UDPv6 Tx, gaining up to 5% in test on dummy netdev. - Adjust TSO packet sizes based on min_rtt, allowing very low latency links (data centers) to always send full-sized TSO super-frames. - Make IPv6 flow label changes (AKA hash rethink) more configurable, via sysctl and setsockopt. Distinguish between server and client behavior. - VxLAN support to "collect metadata" devices to terminate only configured VNIs. This is similar to VLAN filtering in the bridge. - Support inserting IPv6 IOAM information to a fraction of frames. - Add protocol attribute to IP addresses to allow identifying where given address comes from (kernel-generated, DHCP etc.) - Support setting socket and IPv6 options via cmsg on ping6 sockets. - Reject mis-use of ECN bits in IP headers as part of DSCP/TOS. Define dscp_t and stop taking ECN bits into account in fib-rules. - Add support for locked bridge ports (for 802.1X). - tun: support NAPI for packets received from batched XDP buffs, doubling the performance in some scenarios. - IPv6 extension header handling in Open vSwitch. - Support IPv6 control message load balancing in bonding, prevent neighbor solicitation and advertisement from using the wrong port. Support NS/NA monitor selection similar to existing ARP monitor. - SMC - improve performance with TCP_CORK and sendfile() - support auto-corking - support TCP_NODELAY - MCTP (Management Component Transport Protocol) - add user space tag control interface - I2C binding driver (as specified by DMTF DSP0237) - Multi-BSSID beacon handling in AP mode for WiFi. - Bluetooth: - handle MSFT Monitor Device Event - add MGMT Adv Monitor Device Found/Lost events - Multi-Path TCP: - add support for the SO_SNDTIMEO socket option - lots of selftest cleanups and improvements - Increase the max PDU size in CAN ISOTP to 64 kB. Driver API ---------- - Add HW counters for SW netdevs, a mechanism for devices which offload packet forwarding to report packet statistics back to software interfaces such as tunnels. - Select the default NIC queue count as a fraction of number of physical CPU cores, instead of hard-coding to 8. - Expose devlink instance locks to drivers. Allow device layer of drivers to use that lock directly instead of creating their own which always runs into ordering issues in devlink callbacks. - Add header/data split indication to guide user space enabling of TCP zero-copy Rx. - Allow configuring completion queue event size. - Refactor page_pool to enable fragmenting after allocation. - Add allocation and page reuse statistics to page_pool. - Improve Multiple Spanning Trees support in the bridge to allow reuse of topologies across VLANs, saving HW resources in switches. - DSA (Distributed Switch Architecture): - replay and offload of host VLAN entries - offload of static and local FDB entries on LAG interfaces - FDB isolation and unicast filtering New hardware / drivers ---------------------- - Ethernet: - LAN937x T1 PHYs - Davicom DM9051 SPI NIC driver - Realtek RTL8367S, RTL8367RB-VB switch and MDIO - Microchip ksz8563 switches - Netronome NFP3800 SmartNICs - Fungible SmartNICs - MediaTek MT8195 switches - WiFi: - mt76: MediaTek mt7916 - mt76: MediaTek mt7921u USB adapters - brcmfmac: Broadcom BCM43454/6 - Mobile: - iosm: Intel M.2 7360 WWAN card Drivers ------- - Convert many drivers to the new phylink API built for split PCS designs but also simplifying other cases. - Intel Ethernet NICs: - add TTY for GNSS module for E810T device - improve AF_XDP performance - GTP-C and GTP-U filter offload - QinQ VLAN support - Mellanox Ethernet NICs (mlx5): - support xdp->data_meta - multi-buffer XDP - offload tc push_eth and pop_eth actions - Netronome Ethernet NICs (nfp): - flow-independent tc action hardware offload (police / meter) - AF_XDP - Other Ethernet NICs: - at803x: fiber and SFP support - xgmac: mdio: preamble suppression and custom MDC frequencies - r8169: enable ASPM L1.2 if system vendor flags it as safe - macb/gem: ZynqMP SGMII - hns3: add TX push mode - dpaa2-eth: software TSO - lan743x: multi-queue, mdio, SGMII, PTP - axienet: NAPI and GRO support - Mellanox Ethernet switches (mlxsw): - source and dest IP address rewrites - RJ45 ports - Marvell Ethernet switches (prestera): - basic routing offload - multi-chain TC ACL offload - NXP embedded Ethernet switches (ocelot & felix): - PTP over UDP with the ocelot-8021q DSA tagging protocol - basic QoS classification on Felix DSA switch using dcbnl - port mirroring for ocelot switches - Microchip high-speed industrial Ethernet (sparx5): - offloading of bridge port flooding flags - PTP Hardware Clock - Other embedded switches: - lan966x: PTP Hardward Clock - qca8k: mdio read/write operations via crafted Ethernet packets - Qualcomm 802.11ax WiFi (ath11k): - add LDPC FEC type and 802.11ax High Efficiency data in radiotap - enable RX PPDU stats in monitor co-exist mode - Intel WiFi (iwlwifi): - UHB TAS enablement via BIOS - band disablement via BIOS - channel switch offload - 32 Rx AMPDU sessions in newer devices - MediaTek WiFi (mt76): - background radar detection - thermal management improvements on mt7915 - SAR support for more mt76 platforms - MBSSID and 6 GHz band on mt7915 - RealTek WiFi: - rtw89: AP mode - rtw89: 160 MHz channels and 6 GHz band - rtw89: hardware scan - Bluetooth: - mt7921s: wake on Bluetooth, SCO over I2S, wide-band-speed (WBS) - Microchip CAN (mcp251xfd): - multiple RX-FIFOs and runtime configurable RX/TX rings - internal PLL, runtime PM handling simplification - improve chip detection and error handling after wakeup Signed-off-by: Jakub Kicinski <kuba@kernel.org> -----BEGIN PGP SIGNATURE----- iQIzBAABCAAdFiEE6jPA+I1ugmIBA4hXMUZtbf5SIrsFAmI7YBcACgkQMUZtbf5S IrveSBAAmSNJlUK6vPsnNzs7IhsZnfI/AUjm2TCLZnlhKttbpI4A/4Pohk33V7RS FGX7f8kjEfhUwrIiLDgeCnztNHRECrCmk6aZc/jLEvecmTauJ+f6kjShkDY/wix+ AkPHmrZnQeLPAEVuljDdV+sL6ik08+zQL7PazIYHsaSKKC0MGQptRwcri8PLRAKE KPBAhVhleq2rAZ/ntprSN52F4Af6rpFTrPIWuN8Bqdbc9dy5094LT0mpOOWYvgr3 /DLvvAPuLemwyIQkjWknVKBRUAQcmNPC+BY3J8K3LRaiNhekGqOFan46BfqP+k2J 6DWu0Qrp2yWt4BMOeEToZR5rA6v5suUAMIBu8PRZIDkINXQMlIxHfGjZyNm0rVfw 7edNri966yus9OdzwPa32MIG3oC6PnVAwYCJAjjBMNS8sSIkp7wgHLkgWN4UFe2H K/e6z8TLF4UQ+zFM0aGI5WZ+9QqWkTWEDF3R3OhdFpGrznna0gxmkOeV2YvtsgxY cbS0vV9Zj73o+bYzgBKJsw/dAjyLdXoHUGvus26VLQ78S/VGunVKtItwoxBAYmZo krW964qcC89YofzSi8RSKLHuEWtNWZbVm8YXr75u6jpr5GhMBu0CYefLs+BuZcxy dw8c69cGneVbGZmY2J3rBhDkchbuICl8vdUPatGrOJAoaFdYKuw= =ELpe -----END PGP SIGNATURE----- Merge tag 'net-next-5.18' of git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-next Pull networking updates from Jakub Kicinski: "The sprinkling of SPI drivers is because we added a new one and Mark sent us a SPI driver interface conversion pull request. Core ---- - Introduce XDP multi-buffer support, allowing the use of XDP with jumbo frame MTUs and combination with Rx coalescing offloads (LRO). - Speed up netns dismantling (5x) and lower the memory cost a little. Remove unnecessary per-netns sockets. Scope some lists to a netns. Cut down RCU syncing. Use batch methods. Allow netdev registration to complete out of order. - Support distinguishing timestamp types (ingress vs egress) and maintaining them across packet scrubbing points (e.g. redirect). - Continue the work of annotating packet drop reasons throughout the stack. - Switch netdev error counters from an atomic to dynamically allocated per-CPU counters. - Rework a few preempt_disable(), local_irq_save() and busy waiting sections problematic on PREEMPT_RT. - Extend the ref_tracker to allow catching use-after-free bugs. BPF --- - Introduce "packing allocator" for BPF JIT images. JITed code is marked read only, and used to be allocated at page granularity. Custom allocator allows for more efficient memory use, lower iTLB pressure and prevents identity mapping huge pages from getting split. - Make use of BTF type annotations (e.g. __user, __percpu) to enforce the correct probe read access method, add appropriate helpers. - Convert the BPF preload to use light skeleton and drop the user-mode-driver dependency. - Allow XDP BPF_PROG_RUN test infra to send real packets, enabling its use as a packet generator. - Allow local storage memory to be allocated with GFP_KERNEL if called from a hook allowed to sleep. - Introduce fprobe (multi kprobe) to speed up mass attachment (arch bits to come later). - Add unstable conntrack lookup helpers for BPF by using the BPF kfunc infra. - Allow cgroup BPF progs to return custom errors to user space. - Add support for AF_UNIX iterator batching. - Allow iterator programs to use sleepable helpers. - Support JIT of add, and, or, xor and xchg atomic ops on arm64. - Add BTFGen support to bpftool which allows to use CO-RE in kernels without BTF info. - Large number of libbpf API improvements, cleanups and deprecations. Protocols --------- - Micro-optimize UDPv6 Tx, gaining up to 5% in test on dummy netdev. - Adjust TSO packet sizes based on min_rtt, allowing very low latency links (data centers) to always send full-sized TSO super-frames. - Make IPv6 flow label changes (AKA hash rethink) more configurable, via sysctl and setsockopt. Distinguish between server and client behavior. - VxLAN support to "collect metadata" devices to terminate only configured VNIs. This is similar to VLAN filtering in the bridge. - Support inserting IPv6 IOAM information to a fraction of frames. - Add protocol attribute to IP addresses to allow identifying where given address comes from (kernel-generated, DHCP etc.) - Support setting socket and IPv6 options via cmsg on ping6 sockets. - Reject mis-use of ECN bits in IP headers as part of DSCP/TOS. Define dscp_t and stop taking ECN bits into account in fib-rules. - Add support for locked bridge ports (for 802.1X). - tun: support NAPI for packets received from batched XDP buffs, doubling the performance in some scenarios. - IPv6 extension header handling in Open vSwitch. - Support IPv6 control message load balancing in bonding, prevent neighbor solicitation and advertisement from using the wrong port. Support NS/NA monitor selection similar to existing ARP monitor. - SMC - improve performance with TCP_CORK and sendfile() - support auto-corking - support TCP_NODELAY - MCTP (Management Component Transport Protocol) - add user space tag control interface - I2C binding driver (as specified by DMTF DSP0237) - Multi-BSSID beacon handling in AP mode for WiFi. - Bluetooth: - handle MSFT Monitor Device Event - add MGMT Adv Monitor Device Found/Lost events - Multi-Path TCP: - add support for the SO_SNDTIMEO socket option - lots of selftest cleanups and improvements - Increase the max PDU size in CAN ISOTP to 64 kB. Driver API ---------- - Add HW counters for SW netdevs, a mechanism for devices which offload packet forwarding to report packet statistics back to software interfaces such as tunnels. - Select the default NIC queue count as a fraction of number of physical CPU cores, instead of hard-coding to 8. - Expose devlink instance locks to drivers. Allow device layer of drivers to use that lock directly instead of creating their own which always runs into ordering issues in devlink callbacks. - Add header/data split indication to guide user space enabling of TCP zero-copy Rx. - Allow configuring completion queue event size. - Refactor page_pool to enable fragmenting after allocation. - Add allocation and page reuse statistics to page_pool. - Improve Multiple Spanning Trees support in the bridge to allow reuse of topologies across VLANs, saving HW resources in switches. - DSA (Distributed Switch Architecture): - replay and offload of host VLAN entries - offload of static and local FDB entries on LAG interfaces - FDB isolation and unicast filtering New hardware / drivers ---------------------- - Ethernet: - LAN937x T1 PHYs - Davicom DM9051 SPI NIC driver - Realtek RTL8367S, RTL8367RB-VB switch and MDIO - Microchip ksz8563 switches - Netronome NFP3800 SmartNICs - Fungible SmartNICs - MediaTek MT8195 switches - WiFi: - mt76: MediaTek mt7916 - mt76: MediaTek mt7921u USB adapters - brcmfmac: Broadcom BCM43454/6 - Mobile: - iosm: Intel M.2 7360 WWAN card Drivers ------- - Convert many drivers to the new phylink API built for split PCS designs but also simplifying other cases. - Intel Ethernet NICs: - add TTY for GNSS module for E810T device - improve AF_XDP performance - GTP-C and GTP-U filter offload - QinQ VLAN support - Mellanox Ethernet NICs (mlx5): - support xdp->data_meta - multi-buffer XDP - offload tc push_eth and pop_eth actions - Netronome Ethernet NICs (nfp): - flow-independent tc action hardware offload (police / meter) - AF_XDP - Other Ethernet NICs: - at803x: fiber and SFP support - xgmac: mdio: preamble suppression and custom MDC frequencies - r8169: enable ASPM L1.2 if system vendor flags it as safe - macb/gem: ZynqMP SGMII - hns3: add TX push mode - dpaa2-eth: software TSO - lan743x: multi-queue, mdio, SGMII, PTP - axienet: NAPI and GRO support - Mellanox Ethernet switches (mlxsw): - source and dest IP address rewrites - RJ45 ports - Marvell Ethernet switches (prestera): - basic routing offload - multi-chain TC ACL offload - NXP embedded Ethernet switches (ocelot & felix): - PTP over UDP with the ocelot-8021q DSA tagging protocol - basic QoS classification on Felix DSA switch using dcbnl - port mirroring for ocelot switches - Microchip high-speed industrial Ethernet (sparx5): - offloading of bridge port flooding flags - PTP Hardware Clock - Other embedded switches: - lan966x: PTP Hardward Clock - qca8k: mdio read/write operations via crafted Ethernet packets - Qualcomm 802.11ax WiFi (ath11k): - add LDPC FEC type and 802.11ax High Efficiency data in radiotap - enable RX PPDU stats in monitor co-exist mode - Intel WiFi (iwlwifi): - UHB TAS enablement via BIOS - band disablement via BIOS - channel switch offload - 32 Rx AMPDU sessions in newer devices - MediaTek WiFi (mt76): - background radar detection - thermal management improvements on mt7915 - SAR support for more mt76 platforms - MBSSID and 6 GHz band on mt7915 - RealTek WiFi: - rtw89: AP mode - rtw89: 160 MHz channels and 6 GHz band - rtw89: hardware scan - Bluetooth: - mt7921s: wake on Bluetooth, SCO over I2S, wide-band-speed (WBS) - Microchip CAN (mcp251xfd): - multiple RX-FIFOs and runtime configurable RX/TX rings - internal PLL, runtime PM handling simplification - improve chip detection and error handling after wakeup" * tag 'net-next-5.18' of git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-next: (2521 commits) llc: fix netdevice reference leaks in llc_ui_bind() drivers: ethernet: cpsw: fix panic when interrupt coaleceing is set via ethtool ice: don't allow to run ice_send_event_to_aux() in atomic ctx ice: fix 'scheduling while atomic' on aux critical err interrupt net/sched: fix incorrect vlan_push_eth dest field net: bridge: mst: Restrict info size queries to bridge ports net: marvell: prestera: add missing destroy_workqueue() in prestera_module_init() drivers: net: xgene: Fix regression in CRC stripping net: geneve: add missing netlink policy and size for IFLA_GENEVE_INNER_PROTO_INHERIT net: dsa: fix missing host-filtered multicast addresses net/mlx5e: Fix build warning, detected write beyond size of field iwlwifi: mvm: Don't fail if PPAG isn't supported selftests/bpf: Fix kprobe_multi test. Revert "rethook: x86: Add rethook x86 implementation" Revert "arm64: rethook: Add arm64 rethook implementation" Revert "powerpc: Add rethook support" Revert "ARM: rethook: Add rethook arm implementation" netdevice: add missing dm_private kdoc net: bridge: mst: prevent NULL deref in br_mst_info_size() selftests: forwarding: Use same VRF for port and VLAN upper ...
This commit is contained in:
commit
169e77764a
@ -37,8 +37,15 @@ Description: (RO) Set of available destinations (sinks) for a SMA
|
||||
PPS2 signal is sent to the PPS2 selector
|
||||
TS1 signal is sent to timestamper 1
|
||||
TS2 signal is sent to timestamper 2
|
||||
TS3 signal is sent to timestamper 3
|
||||
TS4 signal is sent to timestamper 4
|
||||
IRIG signal is sent to the IRIG-B module
|
||||
DCF signal is sent to the DCF module
|
||||
FREQ1 signal is sent to frequency counter 1
|
||||
FREQ2 signal is sent to frequency counter 2
|
||||
FREQ3 signal is sent to frequency counter 3
|
||||
FREQ4 signal is sent to frequency counter 4
|
||||
None signal input is disabled
|
||||
===== ================================================
|
||||
|
||||
What: /sys/class/timecard/ocpN/available_sma_outputs
|
||||
@ -50,10 +57,16 @@ Description: (RO) Set of available sources for a SMA output signal.
|
||||
10Mhz output is from the 10Mhz reference clock
|
||||
PHC output PPS is from the PHC clock
|
||||
MAC output PPS is from the Miniature Atomic Clock
|
||||
GNSS output PPS is from the GNSS module
|
||||
GNSS1 output PPS is from the first GNSS module
|
||||
GNSS2 output PPS is from the second GNSS module
|
||||
IRIG output is from the PHC, in IRIG-B format
|
||||
DCF output is from the PHC, in DCF format
|
||||
GEN1 output is from frequency generator 1
|
||||
GEN2 output is from frequency generator 2
|
||||
GEN3 output is from frequency generator 3
|
||||
GEN4 output is from frequency generator 4
|
||||
GND output is GND
|
||||
VCC output is VCC
|
||||
===== ================================================
|
||||
|
||||
What: /sys/class/timecard/ocpN/clock_source
|
||||
@ -63,6 +76,97 @@ Description: (RW) Contains the current synchronization source used by
|
||||
the PHC. May be changed by writing one of the listed
|
||||
values from the available_clock_sources attribute set.
|
||||
|
||||
What: /sys/class/timecard/ocpN/clock_status_drift
|
||||
Date: March 2022
|
||||
Contact: Jonathan Lemon <jonathan.lemon@gmail.com>
|
||||
Description: (RO) Contains the current drift value used by the firmware
|
||||
for internal disciplining of the atomic clock.
|
||||
|
||||
What: /sys/class/timecard/ocpN/clock_status_offset
|
||||
Date: March 2022
|
||||
Contact: Jonathan Lemon <jonathan.lemon@gmail.com>
|
||||
Description: (RO) Contains the current offset value used by the firmware
|
||||
for internal disciplining of the atomic clock.
|
||||
|
||||
What: /sys/class/timecard/ocpN/freqX
|
||||
Date: March 2022
|
||||
Contact: Jonathan Lemon <jonathan.lemon@gmail.com>
|
||||
Description: (RO) Optional directory containing the sysfs nodes for
|
||||
frequency counter <X>.
|
||||
|
||||
What: /sys/class/timecard/ocpN/freqX/frequency
|
||||
Date: March 2022
|
||||
Contact: Jonathan Lemon <jonathan.lemon@gmail.com>
|
||||
Description: (RO) Contains the measured frequency over the specified
|
||||
measurement period.
|
||||
|
||||
What: /sys/class/timecard/ocpN/freqX/seconds
|
||||
Date: March 2022
|
||||
Contact: Jonathan Lemon <jonathan.lemon@gmail.com>
|
||||
Description: (RW) Specifies the number of seconds from 0-255 that the
|
||||
frequency should be measured over. Write 0 to disable.
|
||||
|
||||
What: /sys/class/timecard/ocpN/genX
|
||||
Date: March 2022
|
||||
Contact: Jonathan Lemon <jonathan.lemon@gmail.com>
|
||||
Description: (RO) Optional directory containing the sysfs nodes for
|
||||
frequency generator <X>.
|
||||
|
||||
What: /sys/class/timecard/ocpN/genX/duty
|
||||
Date: March 2022
|
||||
Contact: Jonathan Lemon <jonathan.lemon@gmail.com>
|
||||
Description: (RO) Specifies the signal duty cycle as a percentage from 1-99.
|
||||
|
||||
What: /sys/class/timecard/ocpN/genX/period
|
||||
Date: March 2022
|
||||
Contact: Jonathan Lemon <jonathan.lemon@gmail.com>
|
||||
Description: (RO) Specifies the signal period in nanoseconds.
|
||||
|
||||
What: /sys/class/timecard/ocpN/genX/phase
|
||||
Date: March 2022
|
||||
Contact: Jonathan Lemon <jonathan.lemon@gmail.com>
|
||||
Description: (RO) Specifies the signal phase offset in nanoseconds.
|
||||
|
||||
What: /sys/class/timecard/ocpN/genX/polarity
|
||||
Date: March 2022
|
||||
Contact: Jonathan Lemon <jonathan.lemon@gmail.com>
|
||||
Description: (RO) Specifies the signal polarity, either 1 or 0.
|
||||
|
||||
What: /sys/class/timecard/ocpN/genX/running
|
||||
Date: March 2022
|
||||
Contact: Jonathan Lemon <jonathan.lemon@gmail.com>
|
||||
Description: (RO) Either 0 or 1, showing if the signal generator is running.
|
||||
|
||||
What: /sys/class/timecard/ocpN/genX/start
|
||||
Date: March 2022
|
||||
Contact: Jonathan Lemon <jonathan.lemon@gmail.com>
|
||||
Description: (RO) Shows the time in <sec>.<nsec> that the signal generator
|
||||
started running.
|
||||
|
||||
What: /sys/class/timecard/ocpN/genX/signal
|
||||
Date: March 2022
|
||||
Contact: Jonathan Lemon <jonathan.lemon@gmail.com>
|
||||
Description: (RW) Used to start the signal generator, and summarize
|
||||
the current status.
|
||||
|
||||
The signal generator may be started by writing the signal
|
||||
period, followed by the optional signal values. If the
|
||||
optional values are not provided, they default to the current
|
||||
settings, which may be obtained from the other sysfs nodes.
|
||||
|
||||
period [duty [phase [polarity]]]
|
||||
|
||||
echo 500000000 > signal # 1/2 second period
|
||||
echo 1000000 40 100 > signal
|
||||
echo 0 > signal # turn off generator
|
||||
|
||||
Period and phase are specified in nanoseconds. Duty cycle is
|
||||
a percentage from 1-99. Polarity is 1 or 0.
|
||||
|
||||
Reading this node will return:
|
||||
|
||||
period duty phase polarity start_time
|
||||
|
||||
What: /sys/class/timecard/ocpN/gnss_sync
|
||||
Date: September 2021
|
||||
Contact: Jonathan Lemon <jonathan.lemon@gmail.com>
|
||||
@ -126,6 +230,16 @@ Description: (RW) These attributes specify the direction of the signal
|
||||
The 10Mhz reference clock input is currently only valid
|
||||
on SMA1 and may not be combined with other destination sinks.
|
||||
|
||||
What: /sys/class/timecard/ocpN/tod_correction
|
||||
Date: March 2022
|
||||
Contact: Jonathan Lemon <jonathan.lemon@gmail.com>
|
||||
Description: (RW) The incoming GNSS signal is in UTC time, and the NMEA
|
||||
format messages do not provide a TAI offset. This sets the
|
||||
correction value for the incoming time.
|
||||
|
||||
If UBX_LS is enabled, this should be 0, and the offset is
|
||||
taken from the UBX-NAV-TIMELS message.
|
||||
|
||||
What: /sys/class/timecard/ocpN/ts_window_adjust
|
||||
Date: September 2021
|
||||
Contact: Jonathan Lemon <jonathan.lemon@gmail.com>
|
||||
|
@ -365,6 +365,15 @@ new netns has been created.
|
||||
|
||||
Default : 0 (for compatibility reasons)
|
||||
|
||||
txrehash
|
||||
--------
|
||||
|
||||
Controls default hash rethink behaviour on listening socket when SO_TXREHASH
|
||||
option is set to SOCK_TXREHASH_DEFAULT (i. e. not overridden by setsockopt).
|
||||
|
||||
If set to 1 (default), hash rethink is performed on listening socket.
|
||||
If set to 0, hash rethink is not performed.
|
||||
|
||||
2. /proc/sys/net/unix - Parameters for Unix domain sockets
|
||||
----------------------------------------------------------
|
||||
|
||||
|
117
Documentation/bpf/bpf_prog_run.rst
Normal file
117
Documentation/bpf/bpf_prog_run.rst
Normal file
@ -0,0 +1,117 @@
|
||||
.. SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
===================================
|
||||
Running BPF programs from userspace
|
||||
===================================
|
||||
|
||||
This document describes the ``BPF_PROG_RUN`` facility for running BPF programs
|
||||
from userspace.
|
||||
|
||||
.. contents::
|
||||
:local:
|
||||
:depth: 2
|
||||
|
||||
|
||||
Overview
|
||||
--------
|
||||
|
||||
The ``BPF_PROG_RUN`` command can be used through the ``bpf()`` syscall to
|
||||
execute a BPF program in the kernel and return the results to userspace. This
|
||||
can be used to unit test BPF programs against user-supplied context objects, and
|
||||
as way to explicitly execute programs in the kernel for their side effects. The
|
||||
command was previously named ``BPF_PROG_TEST_RUN``, and both constants continue
|
||||
to be defined in the UAPI header, aliased to the same value.
|
||||
|
||||
The ``BPF_PROG_RUN`` command can be used to execute BPF programs of the
|
||||
following types:
|
||||
|
||||
- ``BPF_PROG_TYPE_SOCKET_FILTER``
|
||||
- ``BPF_PROG_TYPE_SCHED_CLS``
|
||||
- ``BPF_PROG_TYPE_SCHED_ACT``
|
||||
- ``BPF_PROG_TYPE_XDP``
|
||||
- ``BPF_PROG_TYPE_SK_LOOKUP``
|
||||
- ``BPF_PROG_TYPE_CGROUP_SKB``
|
||||
- ``BPF_PROG_TYPE_LWT_IN``
|
||||
- ``BPF_PROG_TYPE_LWT_OUT``
|
||||
- ``BPF_PROG_TYPE_LWT_XMIT``
|
||||
- ``BPF_PROG_TYPE_LWT_SEG6LOCAL``
|
||||
- ``BPF_PROG_TYPE_FLOW_DISSECTOR``
|
||||
- ``BPF_PROG_TYPE_STRUCT_OPS``
|
||||
- ``BPF_PROG_TYPE_RAW_TRACEPOINT``
|
||||
- ``BPF_PROG_TYPE_SYSCALL``
|
||||
|
||||
When using the ``BPF_PROG_RUN`` command, userspace supplies an input context
|
||||
object and (for program types operating on network packets) a buffer containing
|
||||
the packet data that the BPF program will operate on. The kernel will then
|
||||
execute the program and return the results to userspace. Note that programs will
|
||||
not have any side effects while being run in this mode; in particular, packets
|
||||
will not actually be redirected or dropped, the program return code will just be
|
||||
returned to userspace. A separate mode for live execution of XDP programs is
|
||||
provided, documented separately below.
|
||||
|
||||
Running XDP programs in "live frame mode"
|
||||
-----------------------------------------
|
||||
|
||||
The ``BPF_PROG_RUN`` command has a separate mode for running live XDP programs,
|
||||
which can be used to execute XDP programs in a way where packets will actually
|
||||
be processed by the kernel after the execution of the XDP program as if they
|
||||
arrived on a physical interface. This mode is activated by setting the
|
||||
``BPF_F_TEST_XDP_LIVE_FRAMES`` flag when supplying an XDP program to
|
||||
``BPF_PROG_RUN``.
|
||||
|
||||
The live packet mode is optimised for high performance execution of the supplied
|
||||
XDP program many times (suitable for, e.g., running as a traffic generator),
|
||||
which means the semantics are not quite as straight-forward as the regular test
|
||||
run mode. Specifically:
|
||||
|
||||
- When executing an XDP program in live frame mode, the result of the execution
|
||||
will not be returned to userspace; instead, the kernel will perform the
|
||||
operation indicated by the program's return code (drop the packet, redirect
|
||||
it, etc). For this reason, setting the ``data_out`` or ``ctx_out`` attributes
|
||||
in the syscall parameters when running in this mode will be rejected. In
|
||||
addition, not all failures will be reported back to userspace directly;
|
||||
specifically, only fatal errors in setup or during execution (like memory
|
||||
allocation errors) will halt execution and return an error. If an error occurs
|
||||
in packet processing, like a failure to redirect to a given interface,
|
||||
execution will continue with the next repetition; these errors can be detected
|
||||
via the same trace points as for regular XDP programs.
|
||||
|
||||
- Userspace can supply an ifindex as part of the context object, just like in
|
||||
the regular (non-live) mode. The XDP program will be executed as though the
|
||||
packet arrived on this interface; i.e., the ``ingress_ifindex`` of the context
|
||||
object will point to that interface. Furthermore, if the XDP program returns
|
||||
``XDP_PASS``, the packet will be injected into the kernel networking stack as
|
||||
though it arrived on that ifindex, and if it returns ``XDP_TX``, the packet
|
||||
will be transmitted *out* of that same interface. Do note, though, that
|
||||
because the program execution is not happening in driver context, an
|
||||
``XDP_TX`` is actually turned into the same action as an ``XDP_REDIRECT`` to
|
||||
that same interface (i.e., it will only work if the driver has support for the
|
||||
``ndo_xdp_xmit`` driver op).
|
||||
|
||||
- When running the program with multiple repetitions, the execution will happen
|
||||
in batches. The batch size defaults to 64 packets (which is same as the
|
||||
maximum NAPI receive batch size), but can be specified by userspace through
|
||||
the ``batch_size`` parameter, up to a maximum of 256 packets. For each batch,
|
||||
the kernel executes the XDP program repeatedly, each invocation getting a
|
||||
separate copy of the packet data. For each repetition, if the program drops
|
||||
the packet, the data page is immediately recycled (see below). Otherwise, the
|
||||
packet is buffered until the end of the batch, at which point all packets
|
||||
buffered this way during the batch are transmitted at once.
|
||||
|
||||
- When setting up the test run, the kernel will initialise a pool of memory
|
||||
pages of the same size as the batch size. Each memory page will be initialised
|
||||
with the initial packet data supplied by userspace at ``BPF_PROG_RUN``
|
||||
invocation. When possible, the pages will be recycled on future program
|
||||
invocations, to improve performance. Pages will generally be recycled a full
|
||||
batch at a time, except when a packet is dropped (by return code or because
|
||||
of, say, a redirection error), in which case that page will be recycled
|
||||
immediately. If a packet ends up being passed to the regular networking stack
|
||||
(because the XDP program returns ``XDP_PASS``, or because it ends up being
|
||||
redirected to an interface that injects it into the stack), the page will be
|
||||
released and a new one will be allocated when the pool is empty.
|
||||
|
||||
When recycling, the page content is not rewritten; only the packet boundary
|
||||
pointers (``data``, ``data_end`` and ``data_meta``) in the context object will
|
||||
be reset to the original values. This means that if a program rewrites the
|
||||
packet contents, it has to be prepared to see either the original content or
|
||||
the modified version on subsequent invocations.
|
@ -503,6 +503,19 @@ valid index (starting from 0) pointing to a member or an argument.
|
||||
* ``info.vlen``: 0
|
||||
* ``type``: the type with ``btf_type_tag`` attribute
|
||||
|
||||
Currently, ``BTF_KIND_TYPE_TAG`` is only emitted for pointer types.
|
||||
It has the following btf type chain:
|
||||
::
|
||||
|
||||
ptr -> [type_tag]*
|
||||
-> [const | volatile | restrict | typedef]*
|
||||
-> base_type
|
||||
|
||||
Basically, a pointer type points to zero or more
|
||||
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.
|
||||
|
||||
3. BTF Kernel API
|
||||
=================
|
||||
|
||||
@ -565,18 +578,15 @@ A map can be created with ``btf_fd`` and specified key/value type id.::
|
||||
In libbpf, the map can be defined with extra annotation like below:
|
||||
::
|
||||
|
||||
struct bpf_map_def SEC("maps") btf_map = {
|
||||
.type = BPF_MAP_TYPE_ARRAY,
|
||||
.key_size = sizeof(int),
|
||||
.value_size = sizeof(struct ipv_counts),
|
||||
.max_entries = 4,
|
||||
};
|
||||
BPF_ANNOTATE_KV_PAIR(btf_map, int, struct ipv_counts);
|
||||
struct {
|
||||
__uint(type, BPF_MAP_TYPE_ARRAY);
|
||||
__type(key, int);
|
||||
__type(value, struct ipv_counts);
|
||||
__uint(max_entries, 4);
|
||||
} btf_map SEC(".maps");
|
||||
|
||||
Here, the parameters for macro BPF_ANNOTATE_KV_PAIR are map name, key and
|
||||
value types for the map. During ELF parsing, libbpf is able to extract
|
||||
key/value type_id's and assign them to BPF_MAP_CREATE attributes
|
||||
automatically.
|
||||
During ELF parsing, libbpf is able to extract key/value type_id's and assign
|
||||
them to BPF_MAP_CREATE attributes automatically.
|
||||
|
||||
.. _BPF_Prog_Load:
|
||||
|
||||
@ -824,13 +834,12 @@ structure has bitfields. For example, for the following map,::
|
||||
___A b1:4;
|
||||
enum A b2:4;
|
||||
};
|
||||
struct bpf_map_def SEC("maps") tmpmap = {
|
||||
.type = BPF_MAP_TYPE_ARRAY,
|
||||
.key_size = sizeof(__u32),
|
||||
.value_size = sizeof(struct tmp_t),
|
||||
.max_entries = 1,
|
||||
};
|
||||
BPF_ANNOTATE_KV_PAIR(tmpmap, int, struct tmp_t);
|
||||
struct {
|
||||
__uint(type, BPF_MAP_TYPE_ARRAY);
|
||||
__type(key, int);
|
||||
__type(value, struct tmp_t);
|
||||
__uint(max_entries, 1);
|
||||
} tmpmap SEC(".maps");
|
||||
|
||||
bpftool is able to pretty print like below:
|
||||
::
|
||||
|
@ -21,6 +21,7 @@ that goes into great technical depth about the BPF Architecture.
|
||||
helpers
|
||||
programs
|
||||
maps
|
||||
bpf_prog_run
|
||||
classic_vs_extended.rst
|
||||
bpf_licensing
|
||||
test_debug
|
||||
|
@ -22,7 +22,13 @@ necessary across calls.
|
||||
Instruction encoding
|
||||
====================
|
||||
|
||||
eBPF uses 64-bit instructions with the following encoding:
|
||||
eBPF has two instruction encodings:
|
||||
|
||||
* the basic instruction encoding, which uses 64 bits to encode an instruction
|
||||
* the wide instruction encoding, which appends a second 64-bit immediate value
|
||||
(imm64) after the basic instruction for a total of 128 bits.
|
||||
|
||||
The basic instruction encoding looks as follows:
|
||||
|
||||
============= ======= =============== ==================== ============
|
||||
32 bits (MSB) 16 bits 4 bits 4 bits 8 bits (LSB)
|
||||
@ -82,9 +88,9 @@ BPF_ALU uses 32-bit wide operands while BPF_ALU64 uses 64-bit wide operands for
|
||||
otherwise identical operations.
|
||||
The code field encodes the operation as below:
|
||||
|
||||
======== ===== ==========================
|
||||
======== ===== =================================================
|
||||
code value description
|
||||
======== ===== ==========================
|
||||
======== ===== =================================================
|
||||
BPF_ADD 0x00 dst += src
|
||||
BPF_SUB 0x10 dst -= src
|
||||
BPF_MUL 0x20 dst \*= src
|
||||
@ -98,8 +104,8 @@ The code field encodes the operation as below:
|
||||
BPF_XOR 0xa0 dst ^= src
|
||||
BPF_MOV 0xb0 dst = src
|
||||
BPF_ARSH 0xc0 sign extending shift right
|
||||
BPF_END 0xd0 endianness conversion
|
||||
======== ===== ==========================
|
||||
BPF_END 0xd0 byte swap operations (see separate section below)
|
||||
======== ===== =================================================
|
||||
|
||||
BPF_ADD | BPF_X | BPF_ALU means::
|
||||
|
||||
@ -118,6 +124,42 @@ BPF_XOR | BPF_K | BPF_ALU64 means::
|
||||
src_reg = src_reg ^ imm32
|
||||
|
||||
|
||||
Byte swap instructions
|
||||
----------------------
|
||||
|
||||
The byte swap instructions use an instruction class of ``BFP_ALU`` and a 4-bit
|
||||
code field of ``BPF_END``.
|
||||
|
||||
The byte swap instructions instructions operate on the destination register
|
||||
only and do not use a separate source register or immediate value.
|
||||
|
||||
The 1-bit source operand field in the opcode is used to to select what byte
|
||||
order the operation convert from or to:
|
||||
|
||||
========= ===== =================================================
|
||||
source value description
|
||||
========= ===== =================================================
|
||||
BPF_TO_LE 0x00 convert between host byte order and little endian
|
||||
BPF_TO_BE 0x08 convert between host byte order and big endian
|
||||
========= ===== =================================================
|
||||
|
||||
The imm field encodes the width of the swap operations. The following widths
|
||||
are supported: 16, 32 and 64.
|
||||
|
||||
Examples:
|
||||
|
||||
``BPF_ALU | BPF_TO_LE | BPF_END`` with imm = 16 means::
|
||||
|
||||
dst_reg = htole16(dst_reg)
|
||||
|
||||
``BPF_ALU | BPF_TO_BE | BPF_END`` with imm = 64 means::
|
||||
|
||||
dst_reg = htobe64(dst_reg)
|
||||
|
||||
``BPF_FROM_LE`` and ``BPF_FROM_BE`` exist as aliases for ``BPF_TO_LE`` and
|
||||
``BPF_TO_LE`` respetively.
|
||||
|
||||
|
||||
Jump instructions
|
||||
-----------------
|
||||
|
||||
@ -176,63 +218,96 @@ The mode modifier is one of:
|
||||
============= ===== ====================================
|
||||
mode modifier value description
|
||||
============= ===== ====================================
|
||||
BPF_IMM 0x00 used for 64-bit mov
|
||||
BPF_ABS 0x20 legacy BPF packet access
|
||||
BPF_IND 0x40 legacy BPF packet access
|
||||
BPF_MEM 0x60 all normal load and store operations
|
||||
BPF_IMM 0x00 64-bit immediate instructions
|
||||
BPF_ABS 0x20 legacy BPF packet access (absolute)
|
||||
BPF_IND 0x40 legacy BPF packet access (indirect)
|
||||
BPF_MEM 0x60 regular load and store operations
|
||||
BPF_ATOMIC 0xc0 atomic operations
|
||||
============= ===== ====================================
|
||||
|
||||
BPF_MEM | <size> | BPF_STX means::
|
||||
|
||||
Regular load and store operations
|
||||
---------------------------------
|
||||
|
||||
The ``BPF_MEM`` mode modifier is used to encode regular load and store
|
||||
instructions that transfer data between a register and memory.
|
||||
|
||||
``BPF_MEM | <size> | BPF_STX`` means::
|
||||
|
||||
*(size *) (dst_reg + off) = src_reg
|
||||
|
||||
BPF_MEM | <size> | BPF_ST means::
|
||||
``BPF_MEM | <size> | BPF_ST`` means::
|
||||
|
||||
*(size *) (dst_reg + off) = imm32
|
||||
|
||||
BPF_MEM | <size> | BPF_LDX means::
|
||||
``BPF_MEM | <size> | BPF_LDX`` means::
|
||||
|
||||
dst_reg = *(size *) (src_reg + off)
|
||||
|
||||
Where size is one of: BPF_B or BPF_H or BPF_W or BPF_DW.
|
||||
Where size is one of: ``BPF_B``, ``BPF_H``, ``BPF_W``, or ``BPF_DW``.
|
||||
|
||||
Atomic operations
|
||||
-----------------
|
||||
|
||||
eBPF includes atomic operations, which use the immediate field for extra
|
||||
encoding::
|
||||
Atomic operations are operations that operate on memory and can not be
|
||||
interrupted or corrupted by other access to the same memory region
|
||||
by other eBPF programs or means outside of this specification.
|
||||
|
||||
.imm = BPF_ADD, .code = BPF_ATOMIC | BPF_W | BPF_STX: lock xadd *(u32 *)(dst_reg + off16) += src_reg
|
||||
.imm = BPF_ADD, .code = BPF_ATOMIC | BPF_DW | BPF_STX: lock xadd *(u64 *)(dst_reg + off16) += src_reg
|
||||
All atomic operations supported by eBPF are encoded as store operations
|
||||
that use the ``BPF_ATOMIC`` mode modifier as follows:
|
||||
|
||||
The basic atomic operations supported are::
|
||||
* ``BPF_ATOMIC | BPF_W | BPF_STX`` for 32-bit operations
|
||||
* ``BPF_ATOMIC | BPF_DW | BPF_STX`` for 64-bit operations
|
||||
* 8-bit and 16-bit wide atomic operations are not supported.
|
||||
|
||||
BPF_ADD
|
||||
BPF_AND
|
||||
BPF_OR
|
||||
BPF_XOR
|
||||
The imm field is used to encode the actual atomic operation.
|
||||
Simple atomic operation use a subset of the values defined to encode
|
||||
arithmetic operations in the imm field to encode the atomic operation:
|
||||
|
||||
Each having equivalent semantics with the ``BPF_ADD`` example, that is: the
|
||||
memory location addresed by ``dst_reg + off`` is atomically modified, with
|
||||
``src_reg`` as the other operand. If the ``BPF_FETCH`` flag is set in the
|
||||
immediate, then these operations also overwrite ``src_reg`` with the
|
||||
value that was in memory before it was modified.
|
||||
======== ===== ===========
|
||||
imm value description
|
||||
======== ===== ===========
|
||||
BPF_ADD 0x00 atomic add
|
||||
BPF_OR 0x40 atomic or
|
||||
BPF_AND 0x50 atomic and
|
||||
BPF_XOR 0xa0 atomic xor
|
||||
======== ===== ===========
|
||||
|
||||
The more special operations are::
|
||||
|
||||
BPF_XCHG
|
||||
``BPF_ATOMIC | BPF_W | BPF_STX`` with imm = BPF_ADD means::
|
||||
|
||||
This atomically exchanges ``src_reg`` with the value addressed by ``dst_reg +
|
||||
off``. ::
|
||||
*(u32 *)(dst_reg + off16) += src_reg
|
||||
|
||||
BPF_CMPXCHG
|
||||
``BPF_ATOMIC | BPF_DW | BPF_STX`` with imm = BPF ADD means::
|
||||
|
||||
This atomically compares the value addressed by ``dst_reg + off`` with
|
||||
``R0``. If they match it is replaced with ``src_reg``. In either case, the
|
||||
value that was there before is zero-extended and loaded back to ``R0``.
|
||||
*(u64 *)(dst_reg + off16) += src_reg
|
||||
|
||||
Note that 1 and 2 byte atomic operations are not supported.
|
||||
``BPF_XADD`` is a deprecated name for ``BPF_ATOMIC | BPF_ADD``.
|
||||
|
||||
In addition to the simple atomic operations, there also is a modifier and
|
||||
two complex atomic operations:
|
||||
|
||||
=========== ================ ===========================
|
||||
imm value description
|
||||
=========== ================ ===========================
|
||||
BPF_FETCH 0x01 modifier: return old value
|
||||
BPF_XCHG 0xe0 | BPF_FETCH atomic exchange
|
||||
BPF_CMPXCHG 0xf0 | BPF_FETCH atomic compare and exchange
|
||||
=========== ================ ===========================
|
||||
|
||||
The ``BPF_FETCH`` modifier is optional for simple atomic operations, and
|
||||
always set for the complex atomic operations. If the ``BPF_FETCH`` flag
|
||||
is set, then the operation also overwrites ``src_reg`` with the value that
|
||||
was in memory before it was modified.
|
||||
|
||||
The ``BPF_XCHG`` operation atomically exchanges ``src_reg`` with the value
|
||||
addressed by ``dst_reg + off``.
|
||||
|
||||
The ``BPF_CMPXCHG`` operation atomically compares the value addressed by
|
||||
``dst_reg + off`` with ``R0``. If they match, the value addressed by
|
||||
``dst_reg + off`` is replaced with ``src_reg``. In either case, the
|
||||
value that was at ``dst_reg + off`` before the operation is zero-extended
|
||||
and loaded back to ``R0``.
|
||||
|
||||
Clang can generate atomic instructions by default when ``-mcpu=v3`` is
|
||||
enabled. If a lower version for ``-mcpu`` is set, the only atomic instruction
|
||||
@ -240,40 +315,52 @@ Clang can generate is ``BPF_ADD`` *without* ``BPF_FETCH``. If you need to enable
|
||||
the atomics features, while keeping a lower ``-mcpu`` version, you can use
|
||||
``-Xclang -target-feature -Xclang +alu32``.
|
||||
|
||||
You may encounter ``BPF_XADD`` - this is a legacy name for ``BPF_ATOMIC``,
|
||||
referring to the exclusive-add operation encoded when the immediate field is
|
||||
zero.
|
||||
64-bit immediate instructions
|
||||
-----------------------------
|
||||
|
||||
16-byte instructions
|
||||
--------------------
|
||||
Instructions with the ``BPF_IMM`` mode modifier use the wide instruction
|
||||
encoding for an extra imm64 value.
|
||||
|
||||
eBPF has one 16-byte instruction: ``BPF_LD | BPF_DW | BPF_IMM`` which consists
|
||||
of two consecutive ``struct bpf_insn`` 8-byte blocks and interpreted as single
|
||||
instruction that loads 64-bit immediate value into a dst_reg.
|
||||
There is currently only one such instruction.
|
||||
|
||||
Packet access instructions
|
||||
--------------------------
|
||||
``BPF_LD | BPF_DW | BPF_IMM`` means::
|
||||
|
||||
eBPF has two non-generic instructions: (BPF_ABS | <size> | BPF_LD) and
|
||||
(BPF_IND | <size> | BPF_LD) which are used to access packet data.
|
||||
dst_reg = imm64
|
||||
|
||||
They had to be carried over from classic BPF to have strong performance of
|
||||
socket filters running in eBPF interpreter. These instructions can only
|
||||
be used when interpreter context is a pointer to ``struct sk_buff`` and
|
||||
have seven implicit operands. Register R6 is an implicit input that must
|
||||
contain pointer to sk_buff. Register R0 is an implicit output which contains
|
||||
the data fetched from the packet. Registers R1-R5 are scratch registers
|
||||
and must not be used to store the data across BPF_ABS | BPF_LD or
|
||||
BPF_IND | BPF_LD instructions.
|
||||
|
||||
These instructions have implicit program exit condition as well. When
|
||||
eBPF program is trying to access the data beyond the packet boundary,
|
||||
the interpreter will abort the execution of the program. JIT compilers
|
||||
therefore must preserve this property. src_reg and imm32 fields are
|
||||
explicit inputs to these instructions.
|
||||
Legacy BPF Packet access instructions
|
||||
-------------------------------------
|
||||
|
||||
For example, BPF_IND | BPF_W | BPF_LD means::
|
||||
eBPF has special instructions for access to packet data that have been
|
||||
carried over from classic BPF to retain the performance of legacy socket
|
||||
filters running in the eBPF interpreter.
|
||||
|
||||
The instructions come in two forms: ``BPF_ABS | <size> | BPF_LD`` and
|
||||
``BPF_IND | <size> | BPF_LD``.
|
||||
|
||||
These instructions are used to access packet data and can only be used when
|
||||
the program context is a pointer to networking packet. ``BPF_ABS``
|
||||
accesses packet data at an absolute offset specified by the immediate data
|
||||
and ``BPF_IND`` access packet data at an offset that includes the value of
|
||||
a register in addition to the immediate data.
|
||||
|
||||
These instructions have seven implicit operands:
|
||||
|
||||
* Register R6 is an implicit input that must contain pointer to a
|
||||
struct sk_buff.
|
||||
* 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.
|
||||
|
||||
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
|
||||
program execution will be aborted.
|
||||
|
||||
``BPF_ABS | BPF_W | BPF_LD`` means::
|
||||
|
||||
R0 = ntohl(*(u32 *) (((struct sk_buff *) R6)->data + imm32))
|
||||
|
||||
``BPF_IND | BPF_W | BPF_LD`` means::
|
||||
|
||||
R0 = ntohl(*(u32 *) (((struct sk_buff *) R6)->data + src_reg + imm32))
|
||||
|
||||
and R1 - R5 are clobbered.
|
||||
|
@ -329,7 +329,7 @@ Program with unreachable instructions::
|
||||
BPF_EXIT_INSN(),
|
||||
};
|
||||
|
||||
Error:
|
||||
Error::
|
||||
|
||||
unreachable insn 1
|
||||
|
||||
|
@ -95,6 +95,10 @@ wants to support one of the below features, it should adapt these bindings.
|
||||
- smbus-alert
|
||||
states that the optional SMBus-Alert feature apply to this bus.
|
||||
|
||||
- mctp-controller
|
||||
indicates that the system is accessible via this bus as an endpoint for
|
||||
MCTP over I2C transport.
|
||||
|
||||
Required properties (per child device)
|
||||
--------------------------------------
|
||||
|
||||
|
@ -10,6 +10,9 @@ maintainers:
|
||||
- Chen-Yu Tsai <wens@csie.org>
|
||||
- Maxime Ripard <mripard@kernel.org>
|
||||
|
||||
allOf:
|
||||
- $ref: can-controller.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
oneOf:
|
||||
|
@ -9,7 +9,10 @@ title: Bosch MCAN controller Bindings
|
||||
description: Bosch MCAN controller for CAN bus
|
||||
|
||||
maintainers:
|
||||
- Sriram Dash <sriram.dash@samsung.com>
|
||||
- Chandrasekar Ramakrishnan <rcsekar@samsung.com>
|
||||
|
||||
allOf:
|
||||
- $ref: can-controller.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
@ -66,8 +69,8 @@ properties:
|
||||
M_CAN includes the following elements according to user manual:
|
||||
11-bit Filter 0-128 elements / 0-128 words
|
||||
29-bit Filter 0-64 elements / 0-128 words
|
||||
Rx FIFO 0 0-64 elements / 0-1152 words
|
||||
Rx FIFO 1 0-64 elements / 0-1152 words
|
||||
Rx FIFO 0 0-64 elements / 0-1152 words
|
||||
Rx FIFO 1 0-64 elements / 0-1152 words
|
||||
Rx Buffers 0-64 elements / 0-1152 words
|
||||
Tx Event FIFO 0-32 elements / 0-64 words
|
||||
Tx Buffers 0-32 elements / 0-576 words
|
||||
|
@ -11,6 +11,9 @@ title:
|
||||
maintainers:
|
||||
- Marc Kleine-Budde <mkl@pengutronix.de>
|
||||
|
||||
allOf:
|
||||
- $ref: can-controller.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
oneOf:
|
||||
|
@ -35,6 +35,8 @@ properties:
|
||||
- renesas,r9a07g044-canfd # RZ/G2{L,LC}
|
||||
- const: renesas,rzg2l-canfd # RZ/G2L family
|
||||
|
||||
- const: renesas,r8a779a0-canfd # R-Car V3U
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
|
161
Documentation/devicetree/bindings/net/can/xilinx,can.yaml
Normal file
161
Documentation/devicetree/bindings/net/can/xilinx,can.yaml
Normal file
@ -0,0 +1,161 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/net/can/xilinx,can.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title:
|
||||
Xilinx Axi CAN/Zynq CANPS controller
|
||||
|
||||
maintainers:
|
||||
- Appana Durga Kedareswara rao <appana.durga.rao@xilinx.com>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- xlnx,zynq-can-1.0
|
||||
- xlnx,axi-can-1.00.a
|
||||
- xlnx,canfd-1.0
|
||||
- xlnx,canfd-2.0
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
minItems: 1
|
||||
maxItems: 2
|
||||
|
||||
clock-names:
|
||||
maxItems: 2
|
||||
|
||||
power-domains:
|
||||
maxItems: 1
|
||||
|
||||
tx-fifo-depth:
|
||||
$ref: "/schemas/types.yaml#/definitions/uint32"
|
||||
description: CAN Tx fifo depth (Zynq, Axi CAN).
|
||||
|
||||
rx-fifo-depth:
|
||||
$ref: "/schemas/types.yaml#/definitions/uint32"
|
||||
description: CAN Rx fifo depth (Zynq, Axi CAN, CAN FD in sequential Rx mode)
|
||||
|
||||
tx-mailbox-count:
|
||||
$ref: "/schemas/types.yaml#/definitions/uint32"
|
||||
description: CAN Tx mailbox buffer count (CAN FD)
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- interrupts
|
||||
- clocks
|
||||
- clock-names
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
allOf:
|
||||
- $ref: can-controller.yaml#
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- xlnx,zynq-can-1.0
|
||||
|
||||
then:
|
||||
properties:
|
||||
clock-names:
|
||||
items:
|
||||
- const: can_clk
|
||||
- const: pclk
|
||||
required:
|
||||
- tx-fifo-depth
|
||||
- rx-fifo-depth
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- xlnx,axi-can-1.00.a
|
||||
|
||||
then:
|
||||
properties:
|
||||
clock-names:
|
||||
items:
|
||||
- const: can_clk
|
||||
- const: s_axi_aclk
|
||||
required:
|
||||
- tx-fifo-depth
|
||||
- rx-fifo-depth
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- xlnx,canfd-1.0
|
||||
- xlnx,canfd-2.0
|
||||
|
||||
then:
|
||||
properties:
|
||||
clock-names:
|
||||
items:
|
||||
- const: can_clk
|
||||
- const: s_axi_aclk
|
||||
required:
|
||||
- tx-mailbox-count
|
||||
- rx-fifo-depth
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||
|
||||
can@e0008000 {
|
||||
compatible = "xlnx,zynq-can-1.0";
|
||||
reg = <0xe0008000 0x1000>;
|
||||
clocks = <&clkc 19>, <&clkc 36>;
|
||||
clock-names = "can_clk", "pclk";
|
||||
interrupts = <GIC_SPI 28 IRQ_TYPE_LEVEL_HIGH>;
|
||||
interrupt-parent = <&intc>;
|
||||
tx-fifo-depth = <0x40>;
|
||||
rx-fifo-depth = <0x40>;
|
||||
};
|
||||
|
||||
- |
|
||||
can@40000000 {
|
||||
compatible = "xlnx,axi-can-1.00.a";
|
||||
reg = <0x40000000 0x10000>;
|
||||
clocks = <&clkc 0>, <&clkc 1>;
|
||||
clock-names = "can_clk", "s_axi_aclk";
|
||||
interrupt-parent = <&intc>;
|
||||
interrupts = <GIC_SPI 59 IRQ_TYPE_EDGE_RISING>;
|
||||
tx-fifo-depth = <0x40>;
|
||||
rx-fifo-depth = <0x40>;
|
||||
};
|
||||
|
||||
- |
|
||||
can@40000000 {
|
||||
compatible = "xlnx,canfd-1.0";
|
||||
reg = <0x40000000 0x2000>;
|
||||
clocks = <&clkc 0>, <&clkc 1>;
|
||||
clock-names = "can_clk", "s_axi_aclk";
|
||||
interrupt-parent = <&intc>;
|
||||
interrupts = <GIC_SPI 59 IRQ_TYPE_EDGE_RISING>;
|
||||
tx-mailbox-count = <0x20>;
|
||||
rx-fifo-depth = <0x20>;
|
||||
};
|
||||
|
||||
- |
|
||||
can@ff060000 {
|
||||
compatible = "xlnx,canfd-2.0";
|
||||
reg = <0xff060000 0x6000>;
|
||||
clocks = <&clkc 0>, <&clkc 1>;
|
||||
clock-names = "can_clk", "s_axi_aclk";
|
||||
interrupt-parent = <&intc>;
|
||||
interrupts = <GIC_SPI 59 IRQ_TYPE_EDGE_RISING>;
|
||||
tx-mailbox-count = <0x20>;
|
||||
rx-fifo-depth = <0x40>;
|
||||
};
|
@ -1,61 +0,0 @@
|
||||
Xilinx Axi CAN/Zynq CANPS controller Device Tree Bindings
|
||||
---------------------------------------------------------
|
||||
|
||||
Required properties:
|
||||
- compatible : Should be:
|
||||
- "xlnx,zynq-can-1.0" for Zynq CAN controllers
|
||||
- "xlnx,axi-can-1.00.a" for Axi CAN controllers
|
||||
- "xlnx,canfd-1.0" for CAN FD controllers
|
||||
- "xlnx,canfd-2.0" for CAN FD 2.0 controllers
|
||||
- reg : Physical base address and size of the controller
|
||||
registers map.
|
||||
- interrupts : Property with a value describing the interrupt
|
||||
number.
|
||||
- clock-names : List of input clock names
|
||||
- "can_clk", "pclk" (For CANPS),
|
||||
- "can_clk", "s_axi_aclk" (For AXI CAN and CAN FD).
|
||||
(See clock bindings for details).
|
||||
- clocks : Clock phandles (see clock bindings for details).
|
||||
- tx-fifo-depth : Can Tx fifo depth (Zynq, Axi CAN).
|
||||
- rx-fifo-depth : Can Rx fifo depth (Zynq, Axi CAN, CAN FD in
|
||||
sequential Rx mode).
|
||||
- tx-mailbox-count : Can Tx mailbox buffer count (CAN FD).
|
||||
- rx-mailbox-count : Can Rx mailbox buffer count (CAN FD in mailbox Rx
|
||||
mode).
|
||||
|
||||
|
||||
Example:
|
||||
|
||||
For Zynq CANPS Dts file:
|
||||
zynq_can_0: can@e0008000 {
|
||||
compatible = "xlnx,zynq-can-1.0";
|
||||
clocks = <&clkc 19>, <&clkc 36>;
|
||||
clock-names = "can_clk", "pclk";
|
||||
reg = <0xe0008000 0x1000>;
|
||||
interrupts = <0 28 4>;
|
||||
interrupt-parent = <&intc>;
|
||||
tx-fifo-depth = <0x40>;
|
||||
rx-fifo-depth = <0x40>;
|
||||
};
|
||||
For Axi CAN Dts file:
|
||||
axi_can_0: axi-can@40000000 {
|
||||
compatible = "xlnx,axi-can-1.00.a";
|
||||
clocks = <&clkc 0>, <&clkc 1>;
|
||||
clock-names = "can_clk","s_axi_aclk" ;
|
||||
reg = <0x40000000 0x10000>;
|
||||
interrupt-parent = <&intc>;
|
||||
interrupts = <0 59 1>;
|
||||
tx-fifo-depth = <0x40>;
|
||||
rx-fifo-depth = <0x40>;
|
||||
};
|
||||
For CAN FD Dts file:
|
||||
canfd_0: canfd@40000000 {
|
||||
compatible = "xlnx,canfd-1.0";
|
||||
clocks = <&clkc 0>, <&clkc 1>;
|
||||
clock-names = "can_clk", "s_axi_aclk";
|
||||
reg = <0x40000000 0x2000>;
|
||||
interrupt-parent = <&intc>;
|
||||
interrupts = <0 59 1>;
|
||||
tx-mailbox-count = <0x20>;
|
||||
rx-fifo-depth = <0x20>;
|
||||
};
|
@ -81,6 +81,25 @@ properties:
|
||||
|
||||
phy-handle: true
|
||||
|
||||
phys:
|
||||
maxItems: 1
|
||||
|
||||
phy-names:
|
||||
const: sgmii-phy
|
||||
description:
|
||||
Required with ZynqMP SoC when in SGMII mode.
|
||||
Should reference PS-GTR generic PHY device for this controller
|
||||
instance. See ZynqMP example.
|
||||
|
||||
resets:
|
||||
maxItems: 1
|
||||
description:
|
||||
Recommended with ZynqMP, specify reset control for this
|
||||
controller instance with zynqmp-reset driver.
|
||||
|
||||
reset-names:
|
||||
maxItems: 1
|
||||
|
||||
fixed-link: true
|
||||
|
||||
iommus:
|
||||
@ -157,3 +176,40 @@ examples:
|
||||
reset-gpios = <&pioE 6 1>;
|
||||
};
|
||||
};
|
||||
|
||||
- |
|
||||
#include <dt-bindings/clock/xlnx-zynqmp-clk.h>
|
||||
#include <dt-bindings/power/xlnx-zynqmp-power.h>
|
||||
#include <dt-bindings/reset/xlnx-zynqmp-resets.h>
|
||||
#include <dt-bindings/phy/phy.h>
|
||||
|
||||
bus {
|
||||
#address-cells = <2>;
|
||||
#size-cells = <2>;
|
||||
gem1: ethernet@ff0c0000 {
|
||||
compatible = "cdns,zynqmp-gem", "cdns,gem";
|
||||
interrupt-parent = <&gic>;
|
||||
interrupts = <0 59 4>, <0 59 4>;
|
||||
reg = <0x0 0xff0c0000 0x0 0x1000>;
|
||||
clocks = <&zynqmp_clk LPD_LSBUS>, <&zynqmp_clk GEM1_REF>,
|
||||
<&zynqmp_clk GEM1_TX>, <&zynqmp_clk GEM1_RX>,
|
||||
<&zynqmp_clk GEM_TSU>;
|
||||
clock-names = "pclk", "hclk", "tx_clk", "rx_clk", "tsu_clk";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
#stream-id-cells = <1>;
|
||||
iommus = <&smmu 0x875>;
|
||||
power-domains = <&zynqmp_firmware PD_ETH_1>;
|
||||
resets = <&zynqmp_reset ZYNQMP_RESET_GEM1>;
|
||||
reset-names = "gem1_rst";
|
||||
status = "okay";
|
||||
phy-mode = "sgmii";
|
||||
phy-names = "sgmii-phy";
|
||||
phys = <&psgtr 1 PHY_TYPE_SGMII 1 1>;
|
||||
fixed-link {
|
||||
speed = <1000>;
|
||||
full-duplex;
|
||||
pause;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
62
Documentation/devicetree/bindings/net/davicom,dm9051.yaml
Normal file
62
Documentation/devicetree/bindings/net/davicom,dm9051.yaml
Normal file
@ -0,0 +1,62 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/net/davicom,dm9051.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Davicom DM9051 SPI Ethernet Controller
|
||||
|
||||
maintainers:
|
||||
- Joseph CHANG <josright123@gmail.com>
|
||||
|
||||
description: |
|
||||
The DM9051 is a fully integrated and cost-effective low pin count single
|
||||
chip Fast Ethernet controller with a Serial Peripheral Interface (SPI).
|
||||
|
||||
allOf:
|
||||
- $ref: ethernet-controller.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: davicom,dm9051
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
spi-max-frequency:
|
||||
maximum: 45000000
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
local-mac-address: true
|
||||
|
||||
mac-address: true
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- spi-max-frequency
|
||||
- interrupts
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
# Raspberry Pi platform
|
||||
- |
|
||||
/* for Raspberry Pi with pin control stuff for GPIO irq */
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
spi {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
ethernet@0 {
|
||||
compatible = "davicom,dm9051";
|
||||
reg = <0>; /* spi chip select */
|
||||
local-mac-address = [00 00 00 00 00 00];
|
||||
interrupt-parent = <&gpio>;
|
||||
interrupts = <26 IRQ_TYPE_LEVEL_LOW>;
|
||||
spi-max-frequency = <31200000>;
|
||||
};
|
||||
};
|
@ -51,6 +51,8 @@ properties:
|
||||
- edsa
|
||||
- ocelot
|
||||
- ocelot-8021q
|
||||
- rtl8_4
|
||||
- rtl8_4t
|
||||
- seville
|
||||
|
||||
phy-handle: true
|
||||
|
@ -42,6 +42,12 @@ properties:
|
||||
description:
|
||||
Set if the output SYNCLKO frequency should be set to 125MHz instead of 25MHz.
|
||||
|
||||
microchip,synclko-disable:
|
||||
$ref: /schemas/types.yaml#/definitions/flag
|
||||
description:
|
||||
Set if the output SYNCLKO clock should be disabled. Do not mix with
|
||||
microchip,synclko-125.
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
@ -1,240 +0,0 @@
|
||||
Realtek SMI-based Switches
|
||||
==========================
|
||||
|
||||
The SMI "Simple Management Interface" is a two-wire protocol using
|
||||
bit-banged GPIO that while it reuses the MDIO lines MCK and MDIO does
|
||||
not use the MDIO protocol. This binding defines how to specify the
|
||||
SMI-based Realtek devices.
|
||||
|
||||
Required properties:
|
||||
|
||||
- compatible: must be exactly one of:
|
||||
"realtek,rtl8365mb" (4+1 ports)
|
||||
"realtek,rtl8366"
|
||||
"realtek,rtl8366rb" (4+1 ports)
|
||||
"realtek,rtl8366s" (4+1 ports)
|
||||
"realtek,rtl8367"
|
||||
"realtek,rtl8367b"
|
||||
"realtek,rtl8368s" (8 port)
|
||||
"realtek,rtl8369"
|
||||
"realtek,rtl8370" (8 port)
|
||||
|
||||
Required properties:
|
||||
- mdc-gpios: GPIO line for the MDC clock line.
|
||||
- mdio-gpios: GPIO line for the MDIO data line.
|
||||
- reset-gpios: GPIO line for the reset signal.
|
||||
|
||||
Optional properties:
|
||||
- realtek,disable-leds: if the LED drivers are not used in the
|
||||
hardware design this will disable them so they are not turned on
|
||||
and wasting power.
|
||||
|
||||
Required subnodes:
|
||||
|
||||
- interrupt-controller
|
||||
|
||||
This defines an interrupt controller with an IRQ line (typically
|
||||
a GPIO) that will demultiplex and handle the interrupt from the single
|
||||
interrupt line coming out of one of the SMI-based chips. It most
|
||||
importantly provides link up/down interrupts to the PHY blocks inside
|
||||
the ASIC.
|
||||
|
||||
Required properties of interrupt-controller:
|
||||
|
||||
- interrupt: parent interrupt, see interrupt-controller/interrupts.txt
|
||||
- interrupt-controller: see interrupt-controller/interrupts.txt
|
||||
- #address-cells: should be <0>
|
||||
- #interrupt-cells: should be <1>
|
||||
|
||||
- mdio
|
||||
|
||||
This defines the internal MDIO bus of the SMI device, mostly for the
|
||||
purpose of being able to hook the interrupts to the right PHY and
|
||||
the right PHY to the corresponding port.
|
||||
|
||||
Required properties of mdio:
|
||||
|
||||
- compatible: should be set to "realtek,smi-mdio" for all SMI devices
|
||||
|
||||
See net/mdio.txt for additional MDIO bus properties.
|
||||
|
||||
See net/dsa/dsa.txt for a list of additional required and optional properties
|
||||
and subnodes of DSA switches.
|
||||
|
||||
Examples:
|
||||
|
||||
An example for the RTL8366RB:
|
||||
|
||||
switch {
|
||||
compatible = "realtek,rtl8366rb";
|
||||
/* 22 = MDIO (has input reads), 21 = MDC (clock, output only) */
|
||||
mdc-gpios = <&gpio0 21 GPIO_ACTIVE_HIGH>;
|
||||
mdio-gpios = <&gpio0 22 GPIO_ACTIVE_HIGH>;
|
||||
reset-gpios = <&gpio0 14 GPIO_ACTIVE_LOW>;
|
||||
|
||||
switch_intc: interrupt-controller {
|
||||
/* GPIO 15 provides the interrupt */
|
||||
interrupt-parent = <&gpio0>;
|
||||
interrupts = <15 IRQ_TYPE_LEVEL_LOW>;
|
||||
interrupt-controller;
|
||||
#address-cells = <0>;
|
||||
#interrupt-cells = <1>;
|
||||
};
|
||||
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
reg = <0>;
|
||||
port@0 {
|
||||
reg = <0>;
|
||||
label = "lan0";
|
||||
phy-handle = <&phy0>;
|
||||
};
|
||||
port@1 {
|
||||
reg = <1>;
|
||||
label = "lan1";
|
||||
phy-handle = <&phy1>;
|
||||
};
|
||||
port@2 {
|
||||
reg = <2>;
|
||||
label = "lan2";
|
||||
phy-handle = <&phy2>;
|
||||
};
|
||||
port@3 {
|
||||
reg = <3>;
|
||||
label = "lan3";
|
||||
phy-handle = <&phy3>;
|
||||
};
|
||||
port@4 {
|
||||
reg = <4>;
|
||||
label = "wan";
|
||||
phy-handle = <&phy4>;
|
||||
};
|
||||
port@5 {
|
||||
reg = <5>;
|
||||
label = "cpu";
|
||||
ethernet = <&gmac0>;
|
||||
phy-mode = "rgmii";
|
||||
fixed-link {
|
||||
speed = <1000>;
|
||||
full-duplex;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
mdio {
|
||||
compatible = "realtek,smi-mdio", "dsa-mdio";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
phy0: phy@0 {
|
||||
reg = <0>;
|
||||
interrupt-parent = <&switch_intc>;
|
||||
interrupts = <0>;
|
||||
};
|
||||
phy1: phy@1 {
|
||||
reg = <1>;
|
||||
interrupt-parent = <&switch_intc>;
|
||||
interrupts = <1>;
|
||||
};
|
||||
phy2: phy@2 {
|
||||
reg = <2>;
|
||||
interrupt-parent = <&switch_intc>;
|
||||
interrupts = <2>;
|
||||
};
|
||||
phy3: phy@3 {
|
||||
reg = <3>;
|
||||
interrupt-parent = <&switch_intc>;
|
||||
interrupts = <3>;
|
||||
};
|
||||
phy4: phy@4 {
|
||||
reg = <4>;
|
||||
interrupt-parent = <&switch_intc>;
|
||||
interrupts = <12>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
An example for the RTL8365MB-VC:
|
||||
|
||||
switch {
|
||||
compatible = "realtek,rtl8365mb";
|
||||
mdc-gpios = <&gpio1 16 GPIO_ACTIVE_HIGH>;
|
||||
mdio-gpios = <&gpio1 17 GPIO_ACTIVE_HIGH>;
|
||||
reset-gpios = <&gpio5 0 GPIO_ACTIVE_LOW>;
|
||||
|
||||
switch_intc: interrupt-controller {
|
||||
interrupt-parent = <&gpio5>;
|
||||
interrupts = <1 IRQ_TYPE_LEVEL_LOW>;
|
||||
interrupt-controller;
|
||||
#address-cells = <0>;
|
||||
#interrupt-cells = <1>;
|
||||
};
|
||||
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
reg = <0>;
|
||||
port@0 {
|
||||
reg = <0>;
|
||||
label = "swp0";
|
||||
phy-handle = <ðphy0>;
|
||||
};
|
||||
port@1 {
|
||||
reg = <1>;
|
||||
label = "swp1";
|
||||
phy-handle = <ðphy1>;
|
||||
};
|
||||
port@2 {
|
||||
reg = <2>;
|
||||
label = "swp2";
|
||||
phy-handle = <ðphy2>;
|
||||
};
|
||||
port@3 {
|
||||
reg = <3>;
|
||||
label = "swp3";
|
||||
phy-handle = <ðphy3>;
|
||||
};
|
||||
port@6 {
|
||||
reg = <6>;
|
||||
label = "cpu";
|
||||
ethernet = <&fec1>;
|
||||
phy-mode = "rgmii";
|
||||
tx-internal-delay-ps = <2000>;
|
||||
rx-internal-delay-ps = <2000>;
|
||||
|
||||
fixed-link {
|
||||
speed = <1000>;
|
||||
full-duplex;
|
||||
pause;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
mdio {
|
||||
compatible = "realtek,smi-mdio";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
ethphy0: phy@0 {
|
||||
reg = <0>;
|
||||
interrupt-parent = <&switch_intc>;
|
||||
interrupts = <0>;
|
||||
};
|
||||
ethphy1: phy@1 {
|
||||
reg = <1>;
|
||||
interrupt-parent = <&switch_intc>;
|
||||
interrupts = <1>;
|
||||
};
|
||||
ethphy2: phy@2 {
|
||||
reg = <2>;
|
||||
interrupt-parent = <&switch_intc>;
|
||||
interrupts = <2>;
|
||||
};
|
||||
ethphy3: phy@3 {
|
||||
reg = <3>;
|
||||
interrupt-parent = <&switch_intc>;
|
||||
interrupts = <3>;
|
||||
};
|
||||
};
|
||||
};
|
394
Documentation/devicetree/bindings/net/dsa/realtek.yaml
Normal file
394
Documentation/devicetree/bindings/net/dsa/realtek.yaml
Normal file
@ -0,0 +1,394 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/net/dsa/realtek.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Realtek switches for unmanaged switches
|
||||
|
||||
allOf:
|
||||
- $ref: dsa.yaml#
|
||||
|
||||
maintainers:
|
||||
- Linus Walleij <linus.walleij@linaro.org>
|
||||
|
||||
description:
|
||||
Realtek advertises these chips as fast/gigabit switches or unmanaged
|
||||
switches. They can be controlled using different interfaces, like SMI,
|
||||
MDIO or SPI.
|
||||
|
||||
The SMI "Simple Management Interface" is a two-wire protocol using
|
||||
bit-banged GPIO that while it reuses the MDIO lines MCK and MDIO does
|
||||
not use the MDIO protocol. This binding defines how to specify the
|
||||
SMI-based Realtek devices. The realtek-smi driver is a platform driver
|
||||
and it must be inserted inside a platform node.
|
||||
|
||||
The MDIO-connected switches use MDIO protocol to access their registers.
|
||||
The realtek-mdio driver is an MDIO driver and it must be inserted inside
|
||||
an MDIO node.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- realtek,rtl8365mb
|
||||
- realtek,rtl8366
|
||||
- realtek,rtl8366rb
|
||||
- realtek,rtl8366s
|
||||
- realtek,rtl8367
|
||||
- realtek,rtl8367b
|
||||
- realtek,rtl8367rb
|
||||
- realtek,rtl8367s
|
||||
- realtek,rtl8368s
|
||||
- realtek,rtl8369
|
||||
- realtek,rtl8370
|
||||
description: |
|
||||
realtek,rtl8365mb: 4+1 ports
|
||||
realtek,rtl8366: 5+1 ports
|
||||
realtek,rtl8366rb: 5+1 ports
|
||||
realtek,rtl8366s: 5+1 ports
|
||||
realtek,rtl8367:
|
||||
realtek,rtl8367b:
|
||||
realtek,rtl8367rb: 5+2 ports
|
||||
realtek,rtl8367s: 5+2 ports
|
||||
realtek,rtl8368s: 8 ports
|
||||
realtek,rtl8369: 8+1 ports
|
||||
realtek,rtl8370: 8+2 ports
|
||||
|
||||
mdc-gpios:
|
||||
description: GPIO line for the MDC clock line.
|
||||
maxItems: 1
|
||||
|
||||
mdio-gpios:
|
||||
description: GPIO line for the MDIO data line.
|
||||
maxItems: 1
|
||||
|
||||
reset-gpios:
|
||||
description: GPIO to be used to reset the whole device
|
||||
maxItems: 1
|
||||
|
||||
realtek,disable-leds:
|
||||
type: boolean
|
||||
description: |
|
||||
if the LED drivers are not used in the hardware design,
|
||||
this will disable them so they are not turned on
|
||||
and wasting power.
|
||||
|
||||
interrupt-controller:
|
||||
type: object
|
||||
description: |
|
||||
This defines an interrupt controller with an IRQ line (typically
|
||||
a GPIO) that will demultiplex and handle the interrupt from the single
|
||||
interrupt line coming out of one of the Realtek switch chips. It most
|
||||
importantly provides link up/down interrupts to the PHY blocks inside
|
||||
the ASIC.
|
||||
|
||||
properties:
|
||||
|
||||
interrupt-controller: true
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
description:
|
||||
A single IRQ line from the switch, either active LOW or HIGH
|
||||
|
||||
'#address-cells':
|
||||
const: 0
|
||||
|
||||
'#interrupt-cells':
|
||||
const: 1
|
||||
|
||||
required:
|
||||
- interrupt-controller
|
||||
- '#address-cells'
|
||||
- '#interrupt-cells'
|
||||
|
||||
mdio:
|
||||
$ref: /schemas/net/mdio.yaml#
|
||||
unevaluatedProperties: false
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: realtek,smi-mdio
|
||||
|
||||
if:
|
||||
required:
|
||||
- reg
|
||||
|
||||
then:
|
||||
not:
|
||||
required:
|
||||
- mdc-gpios
|
||||
- mdio-gpios
|
||||
- mdio
|
||||
|
||||
properties:
|
||||
mdc-gpios: false
|
||||
mdio-gpios: false
|
||||
mdio: false
|
||||
|
||||
else:
|
||||
required:
|
||||
- mdc-gpios
|
||||
- mdio-gpios
|
||||
- mdio
|
||||
- reset-gpios
|
||||
|
||||
required:
|
||||
- compatible
|
||||
|
||||
# - mdc-gpios
|
||||
# - mdio-gpios
|
||||
# - reset-gpios
|
||||
# - mdio
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
|
||||
platform {
|
||||
switch {
|
||||
compatible = "realtek,rtl8366rb";
|
||||
/* 22 = MDIO (has input reads), 21 = MDC (clock, output only) */
|
||||
mdc-gpios = <&gpio0 21 GPIO_ACTIVE_HIGH>;
|
||||
mdio-gpios = <&gpio0 22 GPIO_ACTIVE_HIGH>;
|
||||
reset-gpios = <&gpio0 14 GPIO_ACTIVE_LOW>;
|
||||
|
||||
switch_intc1: interrupt-controller {
|
||||
/* GPIO 15 provides the interrupt */
|
||||
interrupt-parent = <&gpio0>;
|
||||
interrupts = <15 IRQ_TYPE_LEVEL_LOW>;
|
||||
interrupt-controller;
|
||||
#address-cells = <0>;
|
||||
#interrupt-cells = <1>;
|
||||
};
|
||||
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
port@0 {
|
||||
reg = <0>;
|
||||
label = "lan0";
|
||||
phy-handle = <&phy0>;
|
||||
};
|
||||
port@1 {
|
||||
reg = <1>;
|
||||
label = "lan1";
|
||||
phy-handle = <&phy1>;
|
||||
};
|
||||
port@2 {
|
||||
reg = <2>;
|
||||
label = "lan2";
|
||||
phy-handle = <&phy2>;
|
||||
};
|
||||
port@3 {
|
||||
reg = <3>;
|
||||
label = "lan3";
|
||||
phy-handle = <&phy3>;
|
||||
};
|
||||
port@4 {
|
||||
reg = <4>;
|
||||
label = "wan";
|
||||
phy-handle = <&phy4>;
|
||||
};
|
||||
port@5 {
|
||||
reg = <5>;
|
||||
label = "cpu";
|
||||
ethernet = <&gmac0>;
|
||||
phy-mode = "rgmii";
|
||||
fixed-link {
|
||||
speed = <1000>;
|
||||
full-duplex;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
mdio {
|
||||
compatible = "realtek,smi-mdio";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
phy0: ethernet-phy@0 {
|
||||
reg = <0>;
|
||||
interrupt-parent = <&switch_intc1>;
|
||||
interrupts = <0>;
|
||||
};
|
||||
phy1: ethernet-phy@1 {
|
||||
reg = <1>;
|
||||
interrupt-parent = <&switch_intc1>;
|
||||
interrupts = <1>;
|
||||
};
|
||||
phy2: ethernet-phy@2 {
|
||||
reg = <2>;
|
||||
interrupt-parent = <&switch_intc1>;
|
||||
interrupts = <2>;
|
||||
};
|
||||
phy3: ethernet-phy@3 {
|
||||
reg = <3>;
|
||||
interrupt-parent = <&switch_intc1>;
|
||||
interrupts = <3>;
|
||||
};
|
||||
phy4: ethernet-phy@4 {
|
||||
reg = <4>;
|
||||
interrupt-parent = <&switch_intc1>;
|
||||
interrupts = <12>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
- |
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
|
||||
platform {
|
||||
switch {
|
||||
compatible = "realtek,rtl8365mb";
|
||||
mdc-gpios = <&gpio1 16 GPIO_ACTIVE_HIGH>;
|
||||
mdio-gpios = <&gpio1 17 GPIO_ACTIVE_HIGH>;
|
||||
reset-gpios = <&gpio5 0 GPIO_ACTIVE_LOW>;
|
||||
|
||||
switch_intc2: interrupt-controller {
|
||||
interrupt-parent = <&gpio5>;
|
||||
interrupts = <1 IRQ_TYPE_LEVEL_LOW>;
|
||||
interrupt-controller;
|
||||
#address-cells = <0>;
|
||||
#interrupt-cells = <1>;
|
||||
};
|
||||
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
port@0 {
|
||||
reg = <0>;
|
||||
label = "swp0";
|
||||
phy-handle = <ðphy0>;
|
||||
};
|
||||
port@1 {
|
||||
reg = <1>;
|
||||
label = "swp1";
|
||||
phy-handle = <ðphy1>;
|
||||
};
|
||||
port@2 {
|
||||
reg = <2>;
|
||||
label = "swp2";
|
||||
phy-handle = <ðphy2>;
|
||||
};
|
||||
port@3 {
|
||||
reg = <3>;
|
||||
label = "swp3";
|
||||
phy-handle = <ðphy3>;
|
||||
};
|
||||
port@6 {
|
||||
reg = <6>;
|
||||
label = "cpu";
|
||||
ethernet = <&fec1>;
|
||||
phy-mode = "rgmii";
|
||||
tx-internal-delay-ps = <2000>;
|
||||
rx-internal-delay-ps = <2000>;
|
||||
|
||||
fixed-link {
|
||||
speed = <1000>;
|
||||
full-duplex;
|
||||
pause;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
mdio {
|
||||
compatible = "realtek,smi-mdio";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
ethphy0: ethernet-phy@0 {
|
||||
reg = <0>;
|
||||
interrupt-parent = <&switch_intc2>;
|
||||
interrupts = <0>;
|
||||
};
|
||||
ethphy1: ethernet-phy@1 {
|
||||
reg = <1>;
|
||||
interrupt-parent = <&switch_intc2>;
|
||||
interrupts = <1>;
|
||||
};
|
||||
ethphy2: ethernet-phy@2 {
|
||||
reg = <2>;
|
||||
interrupt-parent = <&switch_intc2>;
|
||||
interrupts = <2>;
|
||||
};
|
||||
ethphy3: ethernet-phy@3 {
|
||||
reg = <3>;
|
||||
interrupt-parent = <&switch_intc2>;
|
||||
interrupts = <3>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
- |
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
|
||||
mdio {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
switch@29 {
|
||||
compatible = "realtek,rtl8367s";
|
||||
reg = <29>;
|
||||
|
||||
reset-gpios = <&gpio2 20 GPIO_ACTIVE_LOW>;
|
||||
|
||||
switch_intc3: interrupt-controller {
|
||||
interrupt-parent = <&gpio0>;
|
||||
interrupts = <11 IRQ_TYPE_EDGE_FALLING>;
|
||||
interrupt-controller;
|
||||
#address-cells = <0>;
|
||||
#interrupt-cells = <1>;
|
||||
};
|
||||
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
port@0 {
|
||||
reg = <0>;
|
||||
label = "lan4";
|
||||
};
|
||||
|
||||
port@1 {
|
||||
reg = <1>;
|
||||
label = "lan3";
|
||||
};
|
||||
|
||||
port@2 {
|
||||
reg = <2>;
|
||||
label = "lan2";
|
||||
};
|
||||
|
||||
port@3 {
|
||||
reg = <3>;
|
||||
label = "lan1";
|
||||
};
|
||||
|
||||
port@4 {
|
||||
reg = <4>;
|
||||
label = "wan";
|
||||
};
|
||||
|
||||
port@7 {
|
||||
reg = <7>;
|
||||
ethernet = <ðernet>;
|
||||
phy-mode = "rgmii";
|
||||
tx-internal-delay-ps = <2000>;
|
||||
rx-internal-delay-ps = <0>;
|
||||
|
||||
fixed-link {
|
||||
speed = <1000>;
|
||||
full-duplex;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
@ -388,14 +388,24 @@ PROPERTIES
|
||||
Value type: <prop-encoded-array>
|
||||
Definition: A standard property.
|
||||
|
||||
- bus-frequency
|
||||
- clocks
|
||||
Usage: optional
|
||||
Value type: <phandle>
|
||||
Definition: A reference to the input clock of the controller
|
||||
from which the MDC frequency is derived.
|
||||
|
||||
- clock-frequency
|
||||
Usage: optional
|
||||
Value type: <u32>
|
||||
Definition: Specifies the external MDIO bus clock speed to
|
||||
be used, if different from the standard 2.5 MHz.
|
||||
This may be due to the standard speed being unsupported (e.g.
|
||||
due to a hardware problem), or to advertise that all relevant
|
||||
components in the system support a faster speed.
|
||||
Definition: Specifies the external MDC frequency, in Hertz, to
|
||||
be used. Requires that the input clock is specified in the
|
||||
"clocks" property. See also: mdio.yaml.
|
||||
|
||||
- suppress-preamble
|
||||
Usage: optional
|
||||
Value type: <boolean>
|
||||
Definition: Disable generation of preamble bits. See also:
|
||||
mdio.yaml.
|
||||
|
||||
- interrupts
|
||||
Usage: required for external MDIO
|
||||
|
@ -5,6 +5,7 @@ Required properties:
|
||||
"marvell,armada-370-neta"
|
||||
"marvell,armada-xp-neta"
|
||||
"marvell,armada-3700-neta"
|
||||
"marvell,armada-ac5-neta"
|
||||
- reg: address and length of the register set for the device.
|
||||
- interrupts: interrupt for the device
|
||||
- phy: See ethernet.txt file in the same directory.
|
||||
|
@ -0,0 +1,92 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/net/mctp-i2c-controller.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: MCTP I2C transport binding
|
||||
|
||||
maintainers:
|
||||
- Matt Johnston <matt@codeconstruct.com.au>
|
||||
|
||||
description: |
|
||||
An mctp-i2c-controller defines a local MCTP endpoint on an I2C controller.
|
||||
MCTP I2C is specified by DMTF DSP0237.
|
||||
|
||||
An mctp-i2c-controller must be attached to an I2C adapter which supports
|
||||
slave functionality. I2C busses (either directly or as subordinate mux
|
||||
busses) are attached to the mctp-i2c-controller with a 'mctp-controller'
|
||||
property on each used bus. Each mctp-controller I2C bus will be presented
|
||||
to the host system as a separate MCTP I2C instance.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: mctp-i2c-controller
|
||||
|
||||
reg:
|
||||
minimum: 0x40000000
|
||||
maximum: 0x4000007f
|
||||
description: |
|
||||
7 bit I2C address of the local endpoint.
|
||||
I2C_OWN_SLAVE_ADDRESS (1<<30) flag must be set.
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
||||
examples:
|
||||
- |
|
||||
// Basic case of a single I2C bus
|
||||
#include <dt-bindings/i2c/i2c.h>
|
||||
|
||||
i2c {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
mctp-controller;
|
||||
|
||||
mctp@30 {
|
||||
compatible = "mctp-i2c-controller";
|
||||
reg = <(0x30 | I2C_OWN_SLAVE_ADDRESS)>;
|
||||
};
|
||||
};
|
||||
|
||||
- |
|
||||
// Mux topology with multiple MCTP-handling busses under
|
||||
// a single mctp-i2c-controller.
|
||||
// i2c1 and i2c6 can have MCTP devices, i2c5 does not.
|
||||
#include <dt-bindings/i2c/i2c.h>
|
||||
|
||||
i2c1: i2c {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
mctp-controller;
|
||||
|
||||
mctp@50 {
|
||||
compatible = "mctp-i2c-controller";
|
||||
reg = <(0x50 | I2C_OWN_SLAVE_ADDRESS)>;
|
||||
};
|
||||
};
|
||||
|
||||
i2c-mux {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
i2c-parent = <&i2c1>;
|
||||
|
||||
i2c5: i2c@0 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
reg = <0>;
|
||||
eeprom@33 {
|
||||
reg = <0x33>;
|
||||
};
|
||||
};
|
||||
|
||||
i2c6: i2c@1 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
reg = <1>;
|
||||
mctp-controller;
|
||||
};
|
||||
};
|
@ -1,91 +0,0 @@
|
||||
MediaTek DWMAC glue layer controller
|
||||
|
||||
This file documents platform glue layer for stmmac.
|
||||
Please see stmmac.txt for the other unchanged properties.
|
||||
|
||||
The device node has following properties.
|
||||
|
||||
Required properties:
|
||||
- compatible: Should be "mediatek,mt2712-gmac" for MT2712 SoC
|
||||
- reg: Address and length of the register set for the device
|
||||
- interrupts: Should contain the MAC interrupts
|
||||
- interrupt-names: Should contain a list of interrupt names corresponding to
|
||||
the interrupts in the interrupts property, if available.
|
||||
Should be "macirq" for the main MAC IRQ
|
||||
- clocks: Must contain a phandle for each entry in clock-names.
|
||||
- clock-names: The name of the clock listed in the clocks property. These are
|
||||
"axi", "apb", "mac_main", "ptp_ref", "rmii_internal" for MT2712 SoC.
|
||||
- mac-address: See ethernet.txt in the same directory
|
||||
- phy-mode: See ethernet.txt in the same directory
|
||||
- mediatek,pericfg: A phandle to the syscon node that control ethernet
|
||||
interface and timing delay.
|
||||
|
||||
Optional properties:
|
||||
- mediatek,tx-delay-ps: TX clock delay macro value. Default is 0.
|
||||
It should be defined for RGMII/MII interface.
|
||||
It should be defined for RMII interface when the reference clock is from MT2712 SoC.
|
||||
- mediatek,rx-delay-ps: RX clock delay macro value. Default is 0.
|
||||
It should be defined for RGMII/MII interface.
|
||||
It should be defined for RMII interface.
|
||||
Both delay properties need to be a multiple of 170 for RGMII interface,
|
||||
or will round down. Range 0~31*170.
|
||||
Both delay properties need to be a multiple of 550 for MII/RMII interface,
|
||||
or will round down. Range 0~31*550.
|
||||
|
||||
- mediatek,rmii-rxc: boolean property, if present indicates that the RMII
|
||||
reference clock, which is from external PHYs, is connected to RXC pin
|
||||
on MT2712 SoC.
|
||||
Otherwise, is connected to TXC pin.
|
||||
- mediatek,rmii-clk-from-mac: boolean property, if present indicates that
|
||||
MT2712 SoC provides the RMII reference clock, which outputs to TXC pin only.
|
||||
- mediatek,txc-inverse: boolean property, if present indicates that
|
||||
1. tx clock will be inversed in MII/RGMII case,
|
||||
2. tx clock inside MAC will be inversed relative to reference clock
|
||||
which is from external PHYs in RMII case, and it rarely happen.
|
||||
3. the reference clock, which outputs to TXC pin will be inversed in RMII case
|
||||
when the reference clock is from MT2712 SoC.
|
||||
- mediatek,rxc-inverse: boolean property, if present indicates that
|
||||
1. rx clock will be inversed in MII/RGMII case.
|
||||
2. reference clock will be inversed when arrived at MAC in RMII case, when
|
||||
the reference clock is from external PHYs.
|
||||
3. the inside clock, which be sent to MAC, will be inversed in RMII case when
|
||||
the reference clock is from MT2712 SoC.
|
||||
- assigned-clocks: mac_main and ptp_ref clocks
|
||||
- assigned-clock-parents: parent clocks of the assigned clocks
|
||||
|
||||
Example:
|
||||
eth: ethernet@1101c000 {
|
||||
compatible = "mediatek,mt2712-gmac";
|
||||
reg = <0 0x1101c000 0 0x1300>;
|
||||
interrupts = <GIC_SPI 237 IRQ_TYPE_LEVEL_LOW>;
|
||||
interrupt-names = "macirq";
|
||||
phy-mode ="rgmii-rxid";
|
||||
mac-address = [00 55 7b b5 7d f7];
|
||||
clock-names = "axi",
|
||||
"apb",
|
||||
"mac_main",
|
||||
"ptp_ref",
|
||||
"rmii_internal";
|
||||
clocks = <&pericfg CLK_PERI_GMAC>,
|
||||
<&pericfg CLK_PERI_GMAC_PCLK>,
|
||||
<&topckgen CLK_TOP_ETHER_125M_SEL>,
|
||||
<&topckgen CLK_TOP_ETHER_50M_SEL>,
|
||||
<&topckgen CLK_TOP_ETHER_50M_RMII_SEL>;
|
||||
assigned-clocks = <&topckgen CLK_TOP_ETHER_125M_SEL>,
|
||||
<&topckgen CLK_TOP_ETHER_50M_SEL>,
|
||||
<&topckgen CLK_TOP_ETHER_50M_RMII_SEL>;
|
||||
assigned-clock-parents = <&topckgen CLK_TOP_ETHERPLL_125M>,
|
||||
<&topckgen CLK_TOP_APLL1_D3>,
|
||||
<&topckgen CLK_TOP_ETHERPLL_50M>;
|
||||
power-domains = <&scpsys MT2712_POWER_DOMAIN_AUDIO>;
|
||||
mediatek,pericfg = <&pericfg>;
|
||||
mediatek,tx-delay-ps = <1530>;
|
||||
mediatek,rx-delay-ps = <1530>;
|
||||
mediatek,rmii-rxc;
|
||||
mediatek,txc-inverse;
|
||||
mediatek,rxc-inverse;
|
||||
snps,txpbl = <1>;
|
||||
snps,rxpbl = <1>;
|
||||
snps,reset-gpio = <&pio 87 GPIO_ACTIVE_LOW>;
|
||||
snps,reset-active-low;
|
||||
};
|
175
Documentation/devicetree/bindings/net/mediatek-dwmac.yaml
Normal file
175
Documentation/devicetree/bindings/net/mediatek-dwmac.yaml
Normal file
@ -0,0 +1,175 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/net/mediatek-dwmac.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: MediaTek DWMAC glue layer controller
|
||||
|
||||
maintainers:
|
||||
- Biao Huang <biao.huang@mediatek.com>
|
||||
|
||||
description:
|
||||
This file documents platform glue layer for stmmac.
|
||||
|
||||
# We need a select here so we don't match all nodes with 'snps,dwmac'
|
||||
select:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- mediatek,mt2712-gmac
|
||||
- mediatek,mt8195-gmac
|
||||
required:
|
||||
- compatible
|
||||
|
||||
allOf:
|
||||
- $ref: "snps,dwmac.yaml#"
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
oneOf:
|
||||
- items:
|
||||
- enum:
|
||||
- mediatek,mt2712-gmac
|
||||
- const: snps,dwmac-4.20a
|
||||
- items:
|
||||
- enum:
|
||||
- mediatek,mt8195-gmac
|
||||
- const: snps,dwmac-5.10a
|
||||
|
||||
clocks:
|
||||
minItems: 5
|
||||
items:
|
||||
- description: AXI clock
|
||||
- description: APB clock
|
||||
- description: MAC Main clock
|
||||
- description: PTP clock
|
||||
- description: RMII reference clock provided by MAC
|
||||
- description: MAC clock gate
|
||||
|
||||
clock-names:
|
||||
minItems: 5
|
||||
items:
|
||||
- const: axi
|
||||
- const: apb
|
||||
- const: mac_main
|
||||
- const: ptp_ref
|
||||
- const: rmii_internal
|
||||
- const: mac_cg
|
||||
|
||||
mediatek,pericfg:
|
||||
$ref: /schemas/types.yaml#/definitions/phandle
|
||||
description:
|
||||
The phandle to the syscon node that control ethernet
|
||||
interface and timing delay.
|
||||
|
||||
mediatek,tx-delay-ps:
|
||||
description:
|
||||
The internal TX clock delay (provided by this driver) in nanoseconds.
|
||||
For MT2712 RGMII interface, Allowed value need to be a multiple of 170,
|
||||
or will round down. Range 0~31*170.
|
||||
For MT2712 RMII/MII interface, Allowed value need to be a multiple of 550,
|
||||
or will round down. Range 0~31*550.
|
||||
For MT8195 RGMII/RMII/MII interface, Allowed value need to be a multiple of 290,
|
||||
or will round down. Range 0~31*290.
|
||||
|
||||
mediatek,rx-delay-ps:
|
||||
description:
|
||||
The internal RX clock delay (provided by this driver) in nanoseconds.
|
||||
For MT2712 RGMII interface, Allowed value need to be a multiple of 170,
|
||||
or will round down. Range 0~31*170.
|
||||
For MT2712 RMII/MII interface, Allowed value need to be a multiple of 550,
|
||||
or will round down. Range 0~31*550.
|
||||
For MT8195 RGMII/RMII/MII interface, Allowed value need to be a multiple
|
||||
of 290, or will round down. Range 0~31*290.
|
||||
|
||||
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,rmii-clk-from-mac:
|
||||
type: boolean
|
||||
description:
|
||||
If present, indicates that MAC provides the RMII reference clock, which
|
||||
outputs to TXC pin only.
|
||||
|
||||
mediatek,txc-inverse:
|
||||
type: boolean
|
||||
description:
|
||||
If present, indicates that
|
||||
1. tx clock will be inversed in MII/RGMII case,
|
||||
2. tx clock inside MAC will be inversed relative to reference clock
|
||||
which is from external PHYs in RMII case, and it rarely happen.
|
||||
3. the reference clock, which outputs to TXC pin will be inversed in RMII case
|
||||
when the reference clock is from MAC.
|
||||
|
||||
mediatek,rxc-inverse:
|
||||
type: boolean
|
||||
description:
|
||||
If present, indicates that
|
||||
1. rx clock will be inversed in MII/RGMII case.
|
||||
2. reference clock will be inversed when arrived at MAC in RMII case, when
|
||||
the reference clock is from external PHYs.
|
||||
3. the inside clock, which be sent to MAC, will be inversed in RMII case when
|
||||
the reference clock is from MAC.
|
||||
|
||||
mediatek,mac-wol:
|
||||
type: boolean
|
||||
description:
|
||||
If present, indicates that MAC supports WOL(Wake-On-LAN), and MAC WOL will be enabled.
|
||||
Otherwise, PHY WOL is perferred.
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- interrupts
|
||||
- interrupt-names
|
||||
- clocks
|
||||
- clock-names
|
||||
- phy-mode
|
||||
- mediatek,pericfg
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/clock/mt2712-clk.h>
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
#include <dt-bindings/power/mt2712-power.h>
|
||||
|
||||
eth: ethernet@1101c000 {
|
||||
compatible = "mediatek,mt2712-gmac", "snps,dwmac-4.20a";
|
||||
reg = <0x1101c000 0x1300>;
|
||||
interrupts = <GIC_SPI 237 IRQ_TYPE_LEVEL_LOW>;
|
||||
interrupt-names = "macirq";
|
||||
phy-mode ="rgmii-rxid";
|
||||
mac-address = [00 55 7b b5 7d f7];
|
||||
clock-names = "axi",
|
||||
"apb",
|
||||
"mac_main",
|
||||
"ptp_ref",
|
||||
"rmii_internal";
|
||||
clocks = <&pericfg CLK_PERI_GMAC>,
|
||||
<&pericfg CLK_PERI_GMAC_PCLK>,
|
||||
<&topckgen CLK_TOP_ETHER_125M_SEL>,
|
||||
<&topckgen CLK_TOP_ETHER_50M_SEL>,
|
||||
<&topckgen CLK_TOP_ETHER_50M_RMII_SEL>;
|
||||
assigned-clocks = <&topckgen CLK_TOP_ETHER_125M_SEL>,
|
||||
<&topckgen CLK_TOP_ETHER_50M_SEL>,
|
||||
<&topckgen CLK_TOP_ETHER_50M_RMII_SEL>;
|
||||
assigned-clock-parents = <&topckgen CLK_TOP_ETHERPLL_125M>,
|
||||
<&topckgen CLK_TOP_APLL1_D3>,
|
||||
<&topckgen CLK_TOP_ETHERPLL_50M>;
|
||||
power-domains = <&scpsys MT2712_POWER_DOMAIN_AUDIO>;
|
||||
mediatek,pericfg = <&pericfg>;
|
||||
mediatek,tx-delay-ps = <1530>;
|
||||
snps,txpbl = <1>;
|
||||
snps,rxpbl = <1>;
|
||||
snps,reset-gpio = <&pio 87 GPIO_ACTIVE_LOW>;
|
||||
snps,reset-delays-us = <0 10000 10000>;
|
||||
};
|
@ -45,3 +45,20 @@ Optional properties:
|
||||
|
||||
In fiber mode, auto-negotiation is disabled and the PHY can only work in
|
||||
100base-fx (full and half duplex) modes.
|
||||
|
||||
- lan8814,ignore-ts: If present the PHY will not support timestamping.
|
||||
|
||||
This option acts as check whether Timestamping is supported by
|
||||
hardware or not. LAN8814 phy support hardware tmestamping.
|
||||
|
||||
- lan8814,latency_rx_10: Configures Latency value of phy in ingress at 10 Mbps.
|
||||
|
||||
- lan8814,latency_tx_10: Configures Latency value of phy in egress at 10 Mbps.
|
||||
|
||||
- lan8814,latency_rx_100: Configures Latency value of phy in ingress at 100 Mbps.
|
||||
|
||||
- lan8814,latency_tx_100: Configures Latency value of phy in egress at 100 Mbps.
|
||||
|
||||
- lan8814,latency_rx_1000: Configures Latency value of phy in ingress at 1000 Mbps.
|
||||
|
||||
- lan8814,latency_tx_1000: Configures Latency value of phy in egress at 1000 Mbps.
|
||||
|
@ -38,6 +38,7 @@ properties:
|
||||
- description: register based extraction
|
||||
- description: frame dma based extraction
|
||||
- description: analyzer interrupt
|
||||
- description: ptp interrupt
|
||||
|
||||
interrupt-names:
|
||||
minItems: 1
|
||||
@ -45,6 +46,7 @@ properties:
|
||||
- const: xtr
|
||||
- const: fdma
|
||||
- const: ana
|
||||
- const: ptp
|
||||
|
||||
resets:
|
||||
items:
|
||||
|
@ -53,12 +53,14 @@ properties:
|
||||
items:
|
||||
- description: register based extraction
|
||||
- description: frame dma based extraction
|
||||
- description: ptp interrupt
|
||||
|
||||
interrupt-names:
|
||||
minItems: 1
|
||||
items:
|
||||
- const: xtr
|
||||
- const: fdma
|
||||
- const: ptp
|
||||
|
||||
resets:
|
||||
items:
|
||||
|
@ -2,7 +2,7 @@ Microsemi MII Management Controller (MIIM) / MDIO
|
||||
=================================================
|
||||
|
||||
Properties:
|
||||
- compatible: must be "mscc,ocelot-miim"
|
||||
- compatible: must be "mscc,ocelot-miim" or "microchip,lan966x-miim"
|
||||
- reg: The base address of the MDIO bus controller register bank. Optionally, a
|
||||
second register bank can be defined if there is an associated reset register
|
||||
for internal PHYs
|
||||
|
@ -45,8 +45,10 @@ properties:
|
||||
|
||||
- items:
|
||||
- enum:
|
||||
- renesas,r9a07g043-gbeth # RZ/G2UL
|
||||
- renesas,r9a07g044-gbeth # RZ/G2{L,LC}
|
||||
- const: renesas,rzg2l-gbeth # RZ/G2L
|
||||
- renesas,r9a07g054-gbeth # RZ/V2L
|
||||
- const: renesas,rzg2l-gbeth # RZ/{G2L,G2UL,V2L} family
|
||||
|
||||
reg: true
|
||||
|
||||
|
@ -18,7 +18,7 @@ description: |
|
||||
wireless device. The node is expected to be specified as a child
|
||||
node of the PCI controller to which the wireless chip is connected.
|
||||
Alternatively, it can specify the wireless part of the MT7628/MT7688
|
||||
or MT7622 SoC.
|
||||
or MT7622/MT7986 SoC.
|
||||
|
||||
allOf:
|
||||
- $ref: ieee80211.yaml#
|
||||
@ -29,9 +29,13 @@ properties:
|
||||
- mediatek,mt76
|
||||
- mediatek,mt7628-wmac
|
||||
- mediatek,mt7622-wmac
|
||||
- mediatek,mt7986-wmac
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
minItems: 1
|
||||
maxItems: 3
|
||||
description:
|
||||
MT7986 should contain 3 regions consys, dcm, and sku, in this order.
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
@ -39,6 +43,17 @@ properties:
|
||||
power-domains:
|
||||
maxItems: 1
|
||||
|
||||
memory-region:
|
||||
maxItems: 1
|
||||
|
||||
resets:
|
||||
maxItems: 1
|
||||
description:
|
||||
Specify the consys reset for mt7986.
|
||||
|
||||
reset-name:
|
||||
const: consys
|
||||
|
||||
mediatek,infracfg:
|
||||
$ref: /schemas/types.yaml#/definitions/phandle
|
||||
description:
|
||||
@ -69,6 +84,15 @@ properties:
|
||||
calibration data is generic and specific calibration data should be
|
||||
pulled from the OTP ROM
|
||||
|
||||
mediatek,disable-radar-background:
|
||||
type: boolean
|
||||
description:
|
||||
Disable/enable radar/CAC detection running on a dedicated offchannel
|
||||
chain available on some hw.
|
||||
Background radar/CAC detection allows to avoid the CAC downtime
|
||||
switching on a different channel during CAC detection on the selected
|
||||
radar channel.
|
||||
|
||||
led:
|
||||
type: object
|
||||
$ref: /schemas/leds/common.yaml#
|
||||
@ -165,7 +189,7 @@ required:
|
||||
- compatible
|
||||
- reg
|
||||
|
||||
additionalProperties: false
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
@ -231,3 +255,15 @@ examples:
|
||||
|
||||
power-domains = <&scpsys 3>;
|
||||
};
|
||||
|
||||
- |
|
||||
wifi@18000000 {
|
||||
compatible = "mediatek,mt7986-wmac";
|
||||
resets = <&watchdog 23>;
|
||||
reset-names = "consys";
|
||||
reg = <0x18000000 0x1000000>,
|
||||
<0x10003000 0x1000>,
|
||||
<0x11d10000 0x1000>;
|
||||
interrupts = <GIC_SPI 213 IRQ_TYPE_LEVEL_HIGH>;
|
||||
memory-region = <&wmcpu_emi>;
|
||||
};
|
||||
|
40
Documentation/devicetree/bindings/phy/fsl,lynx-28g.yaml
Normal file
40
Documentation/devicetree/bindings/phy/fsl,lynx-28g.yaml
Normal file
@ -0,0 +1,40 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/phy/fsl,lynx-28g.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Freescale Lynx 28G SerDes PHY binding
|
||||
|
||||
maintainers:
|
||||
- Ioana Ciornei <ioana.ciornei@nxp.com>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- fsl,lynx-28g
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
"#phy-cells":
|
||||
const: 1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- "#phy-cells"
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
soc {
|
||||
#address-cells = <2>;
|
||||
#size-cells = <2>;
|
||||
serdes_1: phy@1ea0000 {
|
||||
compatible = "fsl,lynx-28g";
|
||||
reg = <0x0 0x1ea0000 0x0 0x1e30>;
|
||||
#phy-cells = <1>;
|
||||
};
|
||||
};
|
103
Documentation/devicetree/bindings/phy/transmit-amplitude.yaml
Normal file
103
Documentation/devicetree/bindings/phy/transmit-amplitude.yaml
Normal file
@ -0,0 +1,103 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/phy/transmit-amplitude.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Common PHY and network PCS transmit amplitude property binding
|
||||
|
||||
description:
|
||||
Binding describing the peak-to-peak transmit amplitude for common PHYs
|
||||
and network PCSes.
|
||||
|
||||
maintainers:
|
||||
- Marek Behún <kabel@kernel.org>
|
||||
|
||||
properties:
|
||||
tx-p2p-microvolt:
|
||||
description:
|
||||
Transmit amplitude voltages in microvolts, peak-to-peak. If this property
|
||||
contains multiple values for various PHY modes, the
|
||||
'tx-p2p-microvolt-names' property must be provided and contain
|
||||
corresponding mode names.
|
||||
|
||||
tx-p2p-microvolt-names:
|
||||
description: |
|
||||
Names of the modes corresponding to voltages in the 'tx-p2p-microvolt'
|
||||
property. Required only if multiple voltages are provided.
|
||||
|
||||
If a value of 'default' is provided, the system should use it for any PHY
|
||||
mode that is otherwise not defined here. If 'default' is not provided, the
|
||||
system should use manufacturer default value.
|
||||
minItems: 1
|
||||
maxItems: 16
|
||||
items:
|
||||
enum:
|
||||
- default
|
||||
|
||||
# ethernet modes
|
||||
- sgmii
|
||||
- qsgmii
|
||||
- xgmii
|
||||
- 1000base-x
|
||||
- 2500base-x
|
||||
- 5gbase-r
|
||||
- rxaui
|
||||
- xaui
|
||||
- 10gbase-kr
|
||||
- usxgmii
|
||||
- 10gbase-r
|
||||
- 25gbase-r
|
||||
|
||||
# PCIe modes
|
||||
- pcie
|
||||
- pcie1
|
||||
- pcie2
|
||||
- pcie3
|
||||
- pcie4
|
||||
- pcie5
|
||||
- pcie6
|
||||
|
||||
# USB modes
|
||||
- usb
|
||||
- usb-ls
|
||||
- usb-fs
|
||||
- usb-hs
|
||||
- usb-ss
|
||||
- usb-ss+
|
||||
- usb-4
|
||||
|
||||
# storage modes
|
||||
- sata
|
||||
- ufs-hs
|
||||
- ufs-hs-a
|
||||
- ufs-hs-b
|
||||
|
||||
# display modes
|
||||
- lvds
|
||||
- dp
|
||||
- dp-rbr
|
||||
- dp-hbr
|
||||
- dp-hbr2
|
||||
- dp-hbr3
|
||||
- dp-uhbr-10
|
||||
- dp-uhbr-13.5
|
||||
- dp-uhbr-20
|
||||
|
||||
# camera modes
|
||||
- mipi-dphy
|
||||
- mipi-dphy-univ
|
||||
- mipi-dphy-v2.5-univ
|
||||
|
||||
dependencies:
|
||||
tx-p2p-microvolt-names: [ tx-p2p-microvolt ]
|
||||
|
||||
additionalProperties: true
|
||||
|
||||
examples:
|
||||
- |
|
||||
phy: phy {
|
||||
#phy-cells = <1>;
|
||||
tx-p2p-microvolt = <915000>, <1100000>, <1200000>;
|
||||
tx-p2p-microvolt-names = "2500base-x", "usb-hs", "usb-ss";
|
||||
};
|
@ -313,6 +313,17 @@ arp_ip_target
|
||||
maximum number of targets that can be specified is 16. The
|
||||
default value is no IP addresses.
|
||||
|
||||
ns_ip6_target
|
||||
|
||||
Specifies the IPv6 addresses to use as IPv6 monitoring peers when
|
||||
arp_interval is > 0. These are the targets of the NS request
|
||||
sent to determine the health of the link to the targets.
|
||||
Specify these values in ffff:ffff::ffff:ffff format. Multiple IPv6
|
||||
addresses must be separated by a comma. At least one IPv6
|
||||
address must be given for NS/NA monitoring to function. The
|
||||
maximum number of targets that can be specified is 16. The
|
||||
default value is no IPv6 addresses.
|
||||
|
||||
arp_validate
|
||||
|
||||
Specifies whether or not ARP probes and replies should be
|
||||
|
@ -4,6 +4,22 @@ Linux Devlink Documentation
|
||||
devlink is an API to expose device information and resources not directly
|
||||
related to any device class, such as chip-wide/switch-ASIC-wide configuration.
|
||||
|
||||
Locking
|
||||
-------
|
||||
|
||||
Driver facing APIs are currently transitioning to allow more explicit
|
||||
locking. Drivers can use the existing ``devlink_*`` set of APIs, or
|
||||
new APIs prefixed by ``devl_*``. The older APIs handle all the locking
|
||||
in devlink core, but don't allow registration of most sub-objects once
|
||||
the main devlink object is itself registered. The newer ``devl_*`` APIs assume
|
||||
the devlink instance lock is already held. Drivers can take the instance
|
||||
lock by calling ``devl_lock()``. It is also held in most of the callbacks.
|
||||
Eventually all callbacks will be invoked under the devlink instance lock,
|
||||
refer to the use of the ``DEVLINK_NL_FLAG_NO_LOCK`` flag in devlink core
|
||||
to find out which callbacks are not converted, yet.
|
||||
|
||||
Drivers are encouraged to use the devlink instance lock for their own needs.
|
||||
|
||||
Interface documentation
|
||||
-----------------------
|
||||
|
||||
|
@ -293,6 +293,33 @@ of dropped frames, which is a sum of frames dropped due to timing violations,
|
||||
lack of destination ports and MTU enforcement checks). Byte-level counters are
|
||||
not available.
|
||||
|
||||
Limitations
|
||||
===========
|
||||
|
||||
The SJA1105 switch family always performs VLAN processing. When configured as
|
||||
VLAN-unaware, frames carry a different VLAN tag internally, depending on
|
||||
whether the port is standalone or under a VLAN-unaware bridge.
|
||||
|
||||
The virtual link keys are always fixed at {MAC DA, VLAN ID, VLAN PCP}, but the
|
||||
driver asks for the VLAN ID and VLAN PCP when the port is under a VLAN-aware
|
||||
bridge. Otherwise, it fills in the VLAN ID and PCP automatically, based on
|
||||
whether the port is standalone or in a VLAN-unaware bridge, and accepts only
|
||||
"VLAN-unaware" tc-flower keys (MAC DA).
|
||||
|
||||
The existing tc-flower keys that are offloaded using virtual links are no
|
||||
longer operational after one of the following happens:
|
||||
|
||||
- port was standalone and joins a bridge (VLAN-aware or VLAN-unaware)
|
||||
- port is part of a bridge whose VLAN awareness state changes
|
||||
- port was part of a bridge and becomes standalone
|
||||
- port was standalone, but another port joins a VLAN-aware bridge and this
|
||||
changes the global VLAN awareness state of the bridge
|
||||
|
||||
The driver cannot veto all these operations, and it cannot update/remove the
|
||||
existing tc-flower filters either. So for proper operation, the tc-flower
|
||||
filters should be installed only after the forwarding configuration of the port
|
||||
has been made, and removed by user space before making any changes to it.
|
||||
|
||||
Device Tree bindings and board design
|
||||
=====================================
|
||||
|
||||
|
@ -860,8 +860,17 @@ Kernel response contents:
|
||||
``ETHTOOL_A_RINGS_RX_JUMBO`` u32 size of RX jumbo ring
|
||||
``ETHTOOL_A_RINGS_TX`` u32 size of TX ring
|
||||
``ETHTOOL_A_RINGS_RX_BUF_LEN`` u32 size of buffers on the ring
|
||||
``ETHTOOL_A_RINGS_TCP_DATA_SPLIT`` u8 TCP header / data split
|
||||
``ETHTOOL_A_RINGS_CQE_SIZE`` u32 Size of TX/RX CQE
|
||||
==================================== ====== ===========================
|
||||
|
||||
``ETHTOOL_A_RINGS_TCP_DATA_SPLIT`` indicates whether the device is usable with
|
||||
page-flipping TCP zero-copy receive (``getsockopt(TCP_ZEROCOPY_RECEIVE)``).
|
||||
If enabled the device is configured to place frame headers and data into
|
||||
separate buffers. The device configuration must make it possible to receive
|
||||
full memory pages of data, for example because MTU is high enough or through
|
||||
HW-GRO.
|
||||
|
||||
|
||||
RINGS_SET
|
||||
=========
|
||||
@ -877,6 +886,7 @@ Request contents:
|
||||
``ETHTOOL_A_RINGS_RX_JUMBO`` u32 size of RX jumbo ring
|
||||
``ETHTOOL_A_RINGS_TX`` u32 size of TX ring
|
||||
``ETHTOOL_A_RINGS_RX_BUF_LEN`` u32 size of buffers on the ring
|
||||
``ETHTOOL_A_RINGS_CQE_SIZE`` u32 Size of TX/RX CQE
|
||||
==================================== ====== ===========================
|
||||
|
||||
Kernel checks that requested ring sizes do not exceed limits reported by
|
||||
@ -884,6 +894,15 @@ driver. Driver may impose additional constraints and may not suspport all
|
||||
attributes.
|
||||
|
||||
|
||||
``ETHTOOL_A_RINGS_CQE_SIZE`` specifies the completion queue event size.
|
||||
Completion queue events(CQE) are the events posted by NIC to indicate the
|
||||
completion status of a packet when the packet is sent(like send success or
|
||||
error) or received(like pointers to packet fragments). The CQE size parameter
|
||||
enables to modify the CQE size other than default size if NIC supports it.
|
||||
A bigger CQE can have more receive buffer pointers inturn NIC can transfer
|
||||
a bigger frame from wire. Based on the NIC hardware, the overall completion
|
||||
queue size can be adjusted in the driver if CQE size is modified.
|
||||
|
||||
CHANNELS_GET
|
||||
============
|
||||
|
||||
|
@ -96,6 +96,7 @@ Contents:
|
||||
sctp
|
||||
secid
|
||||
seg6-sysctl
|
||||
smc-sysctl
|
||||
statistics
|
||||
strparser
|
||||
switchdev
|
||||
|
@ -878,6 +878,29 @@ tcp_min_tso_segs - INTEGER
|
||||
|
||||
Default: 2
|
||||
|
||||
tcp_tso_rtt_log - INTEGER
|
||||
Adjustment of TSO packet sizes based on min_rtt
|
||||
|
||||
Starting from linux-5.18, TCP autosizing can be tweaked
|
||||
for flows having small RTT.
|
||||
|
||||
Old autosizing was splitting the pacing budget to send 1024 TSO
|
||||
per second.
|
||||
|
||||
tso_packet_size = sk->sk_pacing_rate / 1024;
|
||||
|
||||
With the new mechanism, we increase this TSO sizing using:
|
||||
|
||||
distance = min_rtt_usec / (2^tcp_tso_rtt_log)
|
||||
tso_packet_size += gso_max_size >> distance;
|
||||
|
||||
This means that flows between very close hosts can use bigger
|
||||
TSO packets, reducing their cpu costs.
|
||||
|
||||
If you want to use the old autosizing, set this sysctl to 0.
|
||||
|
||||
Default: 9 (2^9 = 512 usec)
|
||||
|
||||
tcp_pacing_ss_ratio - INTEGER
|
||||
sk->sk_pacing_rate is set by TCP stack using a ratio applied
|
||||
to current rate. (current_rate = cwnd * mss / srtt)
|
||||
|
@ -212,6 +212,54 @@ remote address is already known, or the message does not require a reply.
|
||||
Like the send calls, sockets will only receive responses to requests they have
|
||||
sent (TO=1) and may only respond (TO=0) to requests they have received.
|
||||
|
||||
``ioctl(SIOCMCTPALLOCTAG)`` and ``ioctl(SIOCMCTPDROPTAG)``
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
These tags give applications more control over MCTP message tags, by allocating
|
||||
(and dropping) tag values explicitly, rather than the kernel automatically
|
||||
allocating a per-message tag at ``sendmsg()`` time.
|
||||
|
||||
In general, you will only need to use these ioctls if your MCTP protocol does
|
||||
not fit the usual request/response model. For example, if you need to persist
|
||||
tags across multiple requests, or a request may generate more than one response.
|
||||
In these cases, the ioctls allow you to decouple the tag allocation (and
|
||||
release) from individual message send and receive operations.
|
||||
|
||||
Both ioctls are passed a pointer to a ``struct mctp_ioc_tag_ctl``:
|
||||
|
||||
.. code-block:: C
|
||||
|
||||
struct mctp_ioc_tag_ctl {
|
||||
mctp_eid_t peer_addr;
|
||||
__u8 tag;
|
||||
__u16 flags;
|
||||
};
|
||||
|
||||
``SIOCMCTPALLOCTAG`` allocates a tag for a specific peer, which an application
|
||||
can use in future ``sendmsg()`` calls. The application populates the
|
||||
``peer_addr`` member with the remote EID. Other fields must be zero.
|
||||
|
||||
On return, the ``tag`` member will be populated with the allocated tag value.
|
||||
The allocated tag will have the following tag bits set:
|
||||
|
||||
- ``MCTP_TAG_OWNER``: it only makes sense to allocate tags if you're the tag
|
||||
owner
|
||||
|
||||
- ``MCTP_TAG_PREALLOC``: to indicate to ``sendmsg()`` that this is a
|
||||
preallocated tag.
|
||||
|
||||
- ... and the actual tag value, within the least-significant three bits
|
||||
(``MCTP_TAG_MASK``). Note that zero is a valid tag value.
|
||||
|
||||
The tag value should be used as-is for the ``smctp_tag`` member of ``struct
|
||||
sockaddr_mctp``.
|
||||
|
||||
``SIOCMCTPDROPTAG`` releases a tag that has been previously allocated by a
|
||||
``SIOCMCTPALLOCTAG`` ioctl. The ``peer_addr`` must be the same as used for the
|
||||
allocation, and the ``tag`` value must match exactly the tag returned from the
|
||||
allocation (including the ``MCTP_TAG_OWNER`` and ``MCTP_TAG_PREALLOC`` bits).
|
||||
The ``flags`` field must be zero.
|
||||
|
||||
Kernel internals
|
||||
================
|
||||
|
||||
|
@ -105,6 +105,47 @@ a page will cause no race conditions is enough.
|
||||
Please note the caller must not use data area after running
|
||||
page_pool_put_page_bulk(), as this function overwrites it.
|
||||
|
||||
* page_pool_get_stats(): Retrieve statistics about the page_pool. This API
|
||||
is only available if the kernel has been configured with
|
||||
``CONFIG_PAGE_POOL_STATS=y``. A pointer to a caller allocated ``struct
|
||||
page_pool_stats`` structure is passed to this API which is filled in. The
|
||||
caller can then report those stats to the user (perhaps via ethtool,
|
||||
debugfs, etc.). See below for an example usage of this API.
|
||||
|
||||
Stats API and structures
|
||||
------------------------
|
||||
If the kernel is configured with ``CONFIG_PAGE_POOL_STATS=y``, the API
|
||||
``page_pool_get_stats()`` and structures described below are available. It
|
||||
takes a pointer to a ``struct page_pool`` and a pointer to a ``struct
|
||||
page_pool_stats`` allocated by the caller.
|
||||
|
||||
The API will fill in the provided ``struct page_pool_stats`` with
|
||||
statistics about the page_pool.
|
||||
|
||||
The stats structure has the following fields::
|
||||
|
||||
struct page_pool_stats {
|
||||
struct page_pool_alloc_stats alloc_stats;
|
||||
struct page_pool_recycle_stats recycle_stats;
|
||||
};
|
||||
|
||||
|
||||
The ``struct page_pool_alloc_stats`` has the following fields:
|
||||
* ``fast``: successful fast path allocations
|
||||
* ``slow``: slow path order-0 allocations
|
||||
* ``slow_high_order``: slow path high order allocations
|
||||
* ``empty``: ptr ring is empty, so a slow path allocation was forced.
|
||||
* ``refill``: an allocation which triggered a refill of the cache
|
||||
* ``waive``: pages obtained from the ptr ring that cannot be added to
|
||||
the cache due to a NUMA mismatch.
|
||||
|
||||
The ``struct page_pool_recycle_stats`` has the following fields:
|
||||
* ``cached``: recycling placed page in the page pool cache
|
||||
* ``cache_full``: page pool cache was full
|
||||
* ``ring``: page placed into the ptr ring
|
||||
* ``ring_full``: page released from page pool because the ptr ring was full
|
||||
* ``released_refcnt``: page released (and not recycled) because refcnt > 1
|
||||
|
||||
Coding examples
|
||||
===============
|
||||
|
||||
@ -157,6 +198,21 @@ NAPI poller
|
||||
}
|
||||
}
|
||||
|
||||
Stats
|
||||
-----
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
#ifdef CONFIG_PAGE_POOL_STATS
|
||||
/* retrieve stats */
|
||||
struct page_pool_stats stats = { 0 };
|
||||
if (page_pool_get_stats(page_pool, &stats)) {
|
||||
/* perhaps the driver reports statistics with ethool */
|
||||
ethtool_print_allocation_stats(&stats.alloc_stats);
|
||||
ethtool_print_recycle_stats(&stats.recycle_stats);
|
||||
}
|
||||
#endif
|
||||
|
||||
Driver unload
|
||||
-------------
|
||||
|
||||
|
23
Documentation/networking/smc-sysctl.rst
Normal file
23
Documentation/networking/smc-sysctl.rst
Normal file
@ -0,0 +1,23 @@
|
||||
.. SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
==========
|
||||
SMC Sysctl
|
||||
==========
|
||||
|
||||
/proc/sys/net/smc/* Variables
|
||||
=============================
|
||||
|
||||
autocorking_size - INTEGER
|
||||
Setting SMC auto corking size:
|
||||
SMC auto corking is like TCP auto corking from the application's
|
||||
perspective of view. When applications do consecutive small
|
||||
write()/sendmsg() system calls, we try to coalesce these small writes
|
||||
as much as possible, to lower total amount of CDC and RDMA Write been
|
||||
sent.
|
||||
autocorking_size limits the maximum corked bytes that can be sent to
|
||||
the under device in 1 single sending. If set to 0, the SMC auto corking
|
||||
is disabled.
|
||||
Applications can still use TCP_CORK for optimal behavior when they
|
||||
know how/when to uncork their sockets.
|
||||
|
||||
Default: 64K
|
@ -668,7 +668,7 @@ timestamping:
|
||||
(through another RX timestamping FIFO). Deferral on RX is typically
|
||||
necessary when retrieving the timestamp needs a sleepable context. In
|
||||
that case, it is the responsibility of the DSA driver to call
|
||||
``netif_rx_ni()`` on the freshly timestamped skb.
|
||||
``netif_rx()`` on the freshly timestamped skb.
|
||||
|
||||
3.2.2 Ethernet PHYs
|
||||
^^^^^^^^^^^^^^^^^^^
|
||||
|
174
Documentation/trace/fprobe.rst
Normal file
174
Documentation/trace/fprobe.rst
Normal file
@ -0,0 +1,174 @@
|
||||
.. SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
==================================
|
||||
Fprobe - Function entry/exit probe
|
||||
==================================
|
||||
|
||||
.. Author: Masami Hiramatsu <mhiramat@kernel.org>
|
||||
|
||||
Introduction
|
||||
============
|
||||
|
||||
Fprobe is a function entry/exit probe mechanism based on ftrace.
|
||||
Instead of using ftrace full feature, if you only want to attach callbacks
|
||||
on function entry and exit, similar to the kprobes and kretprobes, you can
|
||||
use fprobe. Compared with kprobes and kretprobes, fprobe gives faster
|
||||
instrumentation for multiple functions with single handler. This document
|
||||
describes how to use fprobe.
|
||||
|
||||
The usage of fprobe
|
||||
===================
|
||||
|
||||
The fprobe is a wrapper of ftrace (+ kretprobe-like return callback) to
|
||||
attach callbacks to multiple function entry and exit. User needs to set up
|
||||
the `struct fprobe` and pass it to `register_fprobe()`.
|
||||
|
||||
Typically, `fprobe` data structure is initialized with the `entry_handler`
|
||||
and/or `exit_handler` as below.
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
struct fprobe fp = {
|
||||
.entry_handler = my_entry_callback,
|
||||
.exit_handler = my_exit_callback,
|
||||
};
|
||||
|
||||
To enable the fprobe, call one of register_fprobe(), register_fprobe_ips(), and
|
||||
register_fprobe_syms(). These functions register the fprobe with different types
|
||||
of parameters.
|
||||
|
||||
The register_fprobe() enables a fprobe by function-name filters.
|
||||
E.g. this enables @fp on "func*()" function except "func2()".::
|
||||
|
||||
register_fprobe(&fp, "func*", "func2");
|
||||
|
||||
The register_fprobe_ips() enables a fprobe by ftrace-location addresses.
|
||||
E.g.
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
unsigned long ips[] = { 0x.... };
|
||||
|
||||
register_fprobe_ips(&fp, ips, ARRAY_SIZE(ips));
|
||||
|
||||
And the register_fprobe_syms() enables a fprobe by symbol names.
|
||||
E.g.
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
char syms[] = {"func1", "func2", "func3"};
|
||||
|
||||
register_fprobe_syms(&fp, syms, ARRAY_SIZE(syms));
|
||||
|
||||
To disable (remove from functions) this fprobe, call::
|
||||
|
||||
unregister_fprobe(&fp);
|
||||
|
||||
You can temporally (soft) disable the fprobe by::
|
||||
|
||||
disable_fprobe(&fp);
|
||||
|
||||
and resume by::
|
||||
|
||||
enable_fprobe(&fp);
|
||||
|
||||
The above is defined by including the header::
|
||||
|
||||
#include <linux/fprobe.h>
|
||||
|
||||
Same as ftrace, the registered callbacks will start being called some time
|
||||
after the register_fprobe() is called and before it returns. See
|
||||
:file:`Documentation/trace/ftrace.rst`.
|
||||
|
||||
Also, the unregister_fprobe() will guarantee that the both enter and exit
|
||||
handlers are no longer being called by functions after unregister_fprobe()
|
||||
returns as same as unregister_ftrace_function().
|
||||
|
||||
The fprobe entry/exit handler
|
||||
=============================
|
||||
|
||||
The prototype of the entry/exit callback function is as follows:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
void callback_func(struct fprobe *fp, unsigned long entry_ip, struct pt_regs *regs);
|
||||
|
||||
Note that both entry and exit callbacks have same ptototype. The @entry_ip is
|
||||
saved at function entry and passed to exit handler.
|
||||
|
||||
@fp
|
||||
This is the address of `fprobe` data structure related to this handler.
|
||||
You can embed the `fprobe` to your data structure and get it by
|
||||
container_of() macro from @fp. The @fp must not be NULL.
|
||||
|
||||
@entry_ip
|
||||
This is the ftrace address of the traced function (both entry and exit).
|
||||
Note that this may not be the actual entry address of the function but
|
||||
the address where the ftrace is instrumented.
|
||||
|
||||
@regs
|
||||
This is the `pt_regs` data structure at the entry and exit. Note that
|
||||
the instruction pointer of @regs may be different from the @entry_ip
|
||||
in the entry_handler. If you need traced instruction pointer, you need
|
||||
to use @entry_ip. On the other hand, in the exit_handler, the instruction
|
||||
pointer of @regs is set to the currect return address.
|
||||
|
||||
Share the callbacks with kprobes
|
||||
================================
|
||||
|
||||
Since the recursion safeness of the fprobe (and ftrace) is a bit different
|
||||
from the kprobes, this may cause an issue if user wants to run the same
|
||||
code from the fprobe and the kprobes.
|
||||
|
||||
Kprobes has per-cpu 'current_kprobe' variable which protects the kprobe
|
||||
handler from recursion in all cases. On the other hand, fprobe uses
|
||||
only ftrace_test_recursion_trylock(). This allows interrupt context to
|
||||
call another (or same) fprobe while the fprobe user handler is running.
|
||||
|
||||
This is not a matter if the common callback code has its own recursion
|
||||
detection, or it can handle the recursion in the different contexts
|
||||
(normal/interrupt/NMI.)
|
||||
But if it relies on the 'current_kprobe' recursion lock, it has to check
|
||||
kprobe_running() and use kprobe_busy_*() APIs.
|
||||
|
||||
Fprobe has FPROBE_FL_KPROBE_SHARED flag to do this. If your common callback
|
||||
code will be shared with kprobes, please set FPROBE_FL_KPROBE_SHARED
|
||||
*before* registering the fprobe, like:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
fprobe.flags = FPROBE_FL_KPROBE_SHARED;
|
||||
|
||||
register_fprobe(&fprobe, "func*", NULL);
|
||||
|
||||
This will protect your common callback from the nested call.
|
||||
|
||||
The missed counter
|
||||
==================
|
||||
|
||||
The `fprobe` data structure has `fprobe::nmissed` counter field as same as
|
||||
kprobes.
|
||||
This counter counts up when;
|
||||
|
||||
- fprobe fails to take ftrace_recursion lock. This usually means that a function
|
||||
which is traced by other ftrace users is called from the entry_handler.
|
||||
|
||||
- fprobe fails to setup the function exit because of the shortage of rethook
|
||||
(the shadow stack for hooking the function return.)
|
||||
|
||||
The `fprobe::nmissed` field counts up in both cases. Therefore, the former
|
||||
skips both of entry and exit callback and the latter skips the exit
|
||||
callback, but in both case the counter will increase by 1.
|
||||
|
||||
Note that if you set the FTRACE_OPS_FL_RECURSION and/or FTRACE_OPS_FL_RCU to
|
||||
`fprobe::ops::flags` (ftrace_ops::flags) when registering the fprobe, this
|
||||
counter may not work correctly, because ftrace skips the fprobe function which
|
||||
increase the counter.
|
||||
|
||||
|
||||
Functions and structures
|
||||
========================
|
||||
|
||||
.. kernel-doc:: include/linux/fprobe.h
|
||||
.. kernel-doc:: kernel/trace/fprobe.c
|
||||
|
@ -9,6 +9,7 @@ Linux Tracing Technologies
|
||||
tracepoint-analysis
|
||||
ftrace
|
||||
ftrace-uses
|
||||
fprobe
|
||||
kprobes
|
||||
kprobetrace
|
||||
uprobetracer
|
||||
|
27
MAINTAINERS
27
MAINTAINERS
@ -3538,6 +3538,8 @@ F: net/sched/act_bpf.c
|
||||
F: net/sched/cls_bpf.c
|
||||
F: samples/bpf/
|
||||
F: scripts/bpf_doc.py
|
||||
F: scripts/pahole-flags.sh
|
||||
F: scripts/pahole-version.sh
|
||||
F: tools/bpf/
|
||||
F: tools/lib/bpf/
|
||||
F: tools/testing/selftests/bpf/
|
||||
@ -3830,9 +3832,6 @@ BROADCOM BRCM80211 IEEE802.11n WIRELESS DRIVER
|
||||
M: Arend van Spriel <aspriel@gmail.com>
|
||||
M: Franky Lin <franky.lin@broadcom.com>
|
||||
M: Hante Meuleman <hante.meuleman@broadcom.com>
|
||||
M: Chi-hsien Lin <chi-hsien.lin@infineon.com>
|
||||
M: Wright Feng <wright.feng@infineon.com>
|
||||
M: Chung-hsien Hsu <chung-hsien.hsu@infineon.com>
|
||||
L: linux-wireless@vger.kernel.org
|
||||
L: brcm80211-dev-list.pdl@broadcom.com
|
||||
L: SHA-cyfmac-dev-list@infineon.com
|
||||
@ -7949,6 +7948,12 @@ L: platform-driver-x86@vger.kernel.org
|
||||
S: Maintained
|
||||
F: drivers/platform/x86/fujitsu-tablet.c
|
||||
|
||||
FUNGIBLE ETHERNET DRIVERS
|
||||
M: Dimitris Michailidis <dmichail@fungible.com>
|
||||
L: netdev@vger.kernel.org
|
||||
S: Supported
|
||||
F: drivers/net/ethernet/fungible/
|
||||
|
||||
FUSE: FILESYSTEM IN USERSPACE
|
||||
M: Miklos Szeredi <miklos@szeredi.hu>
|
||||
L: linux-fsdevel@vger.kernel.org
|
||||
@ -10809,7 +10814,6 @@ L7 BPF FRAMEWORK
|
||||
M: John Fastabend <john.fastabend@gmail.com>
|
||||
M: Daniel Borkmann <daniel@iogearbox.net>
|
||||
M: Jakub Sitnicki <jakub@cloudflare.com>
|
||||
M: Lorenz Bauer <lmb@cloudflare.com>
|
||||
L: netdev@vger.kernel.org
|
||||
L: bpf@vger.kernel.org
|
||||
S: Maintained
|
||||
@ -11377,6 +11381,13 @@ S: Maintained
|
||||
W: http://linux-test-project.github.io/
|
||||
T: git git://github.com/linux-test-project/ltp.git
|
||||
|
||||
LYNX 28G SERDES PHY DRIVER
|
||||
M: Ioana Ciornei <ioana.ciornei@nxp.com>
|
||||
L: netdev@vger.kernel.org
|
||||
S: Supported
|
||||
F: Documentation/devicetree/bindings/phy/fsl,lynx-28g.yaml
|
||||
F: drivers/phy/freescale/phy-fsl-lynx-28g.c
|
||||
|
||||
LYNX PCS MODULE
|
||||
M: Ioana Ciornei <ioana.ciornei@nxp.com>
|
||||
L: netdev@vger.kernel.org
|
||||
@ -12217,6 +12228,7 @@ R: Shayne Chen <shayne.chen@mediatek.com>
|
||||
R: Sean Wang <sean.wang@mediatek.com>
|
||||
L: linux-wireless@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/devicetree/bindings/net/wireless/mediatek,mt76.yaml
|
||||
F: drivers/net/wireless/mediatek/mt76/
|
||||
|
||||
MEDIATEK MT7601U WIRELESS LAN DRIVER
|
||||
@ -15996,8 +16008,8 @@ M: Kalle Valo <kvalo@kernel.org>
|
||||
L: ath11k@lists.infradead.org
|
||||
S: Supported
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/ath.git
|
||||
F: Documentation/devicetree/bindings/net/wireless/qcom,ath11k.yaml
|
||||
F: drivers/net/wireless/ath/ath11k/
|
||||
F: Documentation/devicetree/bindings/net/wireless/qcom,ath11k.txt
|
||||
|
||||
QUALCOMM ATHEROS ATH9K WIRELESS DRIVER
|
||||
M: Toke Høiland-Jørgensen <toke@toke.dk>
|
||||
@ -16446,9 +16458,8 @@ REALTEK RTL83xx SMI DSA ROUTER CHIPS
|
||||
M: Linus Walleij <linus.walleij@linaro.org>
|
||||
M: Alvin Šipraga <alsi@bang-olufsen.dk>
|
||||
S: Maintained
|
||||
F: Documentation/devicetree/bindings/net/dsa/realtek-smi.txt
|
||||
F: drivers/net/dsa/realtek-smi*
|
||||
F: drivers/net/dsa/rtl83*
|
||||
F: Documentation/devicetree/bindings/net/dsa/realtek.yaml
|
||||
F: drivers/net/dsa/realtek/*
|
||||
|
||||
REALTEK WIRELESS DRIVER (rtlwifi family)
|
||||
M: Ping-Ke Shih <pkshih@realtek.com>
|
||||
|
@ -133,6 +133,8 @@
|
||||
|
||||
#define SO_RESERVE_MEM 73
|
||||
|
||||
#define SO_TXREHASH 74
|
||||
|
||||
#if !defined(__KERNEL__)
|
||||
|
||||
#if __BITS_PER_LONG == 64
|
||||
|
@ -1864,7 +1864,7 @@ static int build_body(struct jit_ctx *ctx)
|
||||
if (ctx->target == NULL)
|
||||
ctx->offsets[i] = ctx->idx;
|
||||
|
||||
/* If unsuccesfull, return with error code */
|
||||
/* If unsuccesful, return with error code */
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
@ -1973,7 +1973,7 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
|
||||
* for jit, although it can decrease the size of the image.
|
||||
*
|
||||
* As each arm instruction is of length 32bit, we are translating
|
||||
* number of JITed intructions into the size required to store these
|
||||
* number of JITed instructions into the size required to store these
|
||||
* JITed code.
|
||||
*/
|
||||
image_size = sizeof(u32) * ctx.idx;
|
||||
|
@ -63,21 +63,25 @@ sfp3: sfp-3 {
|
||||
&dpmac7 {
|
||||
sfp = <&sfp0>;
|
||||
managed = "in-band-status";
|
||||
phys = <&serdes_1 3>;
|
||||
};
|
||||
|
||||
&dpmac8 {
|
||||
sfp = <&sfp1>;
|
||||
managed = "in-band-status";
|
||||
phys = <&serdes_1 2>;
|
||||
};
|
||||
|
||||
&dpmac9 {
|
||||
sfp = <&sfp2>;
|
||||
managed = "in-band-status";
|
||||
phys = <&serdes_1 1>;
|
||||
};
|
||||
|
||||
&dpmac10 {
|
||||
sfp = <&sfp3>;
|
||||
managed = "in-band-status";
|
||||
phys = <&serdes_1 0>;
|
||||
};
|
||||
|
||||
&emdio2 {
|
||||
|
@ -612,6 +612,12 @@ soc {
|
||||
ranges;
|
||||
dma-ranges = <0x0 0x0 0x0 0x0 0x10000 0x00000000>;
|
||||
|
||||
serdes_1: phy@1ea0000 {
|
||||
compatible = "fsl,lynx-28g";
|
||||
reg = <0x0 0x1ea0000 0x0 0x1e30>;
|
||||
#phy-cells = <1>;
|
||||
};
|
||||
|
||||
crypto: crypto@8000000 {
|
||||
compatible = "fsl,sec-v5.0", "fsl,sec-v4.0";
|
||||
fsl,sec-era = <10>;
|
||||
|
@ -110,6 +110,7 @@ ð {
|
||||
phy-handle = <ðernet_phy0>;
|
||||
mediatek,tx-delay-ps = <1530>;
|
||||
snps,reset-gpio = <&pio 87 GPIO_ACTIVE_LOW>;
|
||||
snps,reset-delays-us = <0 10000 10000>;
|
||||
pinctrl-names = "default", "sleep";
|
||||
pinctrl-0 = <ð_default>;
|
||||
pinctrl-1 = <ð_sleep>;
|
||||
|
@ -726,7 +726,7 @@ queue2 {
|
||||
};
|
||||
|
||||
eth: ethernet@1101c000 {
|
||||
compatible = "mediatek,mt2712-gmac";
|
||||
compatible = "mediatek,mt2712-gmac", "snps,dwmac-4.20a";
|
||||
reg = <0 0x1101c000 0 0x1300>;
|
||||
interrupts = <GIC_SPI 237 IRQ_TYPE_LEVEL_LOW>;
|
||||
interrupt-names = "macirq";
|
||||
@ -734,15 +734,19 @@ eth: ethernet@1101c000 {
|
||||
clock-names = "axi",
|
||||
"apb",
|
||||
"mac_main",
|
||||
"ptp_ref";
|
||||
"ptp_ref",
|
||||
"rmii_internal";
|
||||
clocks = <&pericfg CLK_PERI_GMAC>,
|
||||
<&pericfg CLK_PERI_GMAC_PCLK>,
|
||||
<&topckgen CLK_TOP_ETHER_125M_SEL>,
|
||||
<&topckgen CLK_TOP_ETHER_50M_SEL>;
|
||||
<&topckgen CLK_TOP_ETHER_50M_SEL>,
|
||||
<&topckgen CLK_TOP_ETHER_50M_RMII_SEL>;
|
||||
assigned-clocks = <&topckgen CLK_TOP_ETHER_125M_SEL>,
|
||||
<&topckgen CLK_TOP_ETHER_50M_SEL>;
|
||||
<&topckgen CLK_TOP_ETHER_50M_SEL>,
|
||||
<&topckgen CLK_TOP_ETHER_50M_RMII_SEL>;
|
||||
assigned-clock-parents = <&topckgen CLK_TOP_ETHERPLL_125M>,
|
||||
<&topckgen CLK_TOP_APLL1_D3>;
|
||||
<&topckgen CLK_TOP_APLL1_D3>,
|
||||
<&topckgen CLK_TOP_ETHERPLL_50M>;
|
||||
power-domains = <&scpsys MT2712_POWER_DOMAIN_AUDIO>;
|
||||
mediatek,pericfg = <&pericfg>;
|
||||
snps,axi-config = <&stmmac_axi_setup>;
|
||||
|
@ -471,9 +471,10 @@ switch: switch@0x600000000 {
|
||||
<0x6 0x10004000 0x7fc000>,
|
||||
<0x6 0x11010000 0xaf0000>;
|
||||
reg-names = "cpu", "dev", "gcb";
|
||||
interrupt-names = "xtr", "fdma";
|
||||
interrupt-names = "xtr", "fdma", "ptp";
|
||||
interrupts = <GIC_SPI 30 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 25 IRQ_TYPE_LEVEL_HIGH>;
|
||||
<GIC_SPI 25 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 27 IRQ_TYPE_LEVEL_HIGH>;
|
||||
resets = <&reset 0>;
|
||||
reset-names = "switch";
|
||||
};
|
||||
|
@ -510,6 +510,8 @@ gem0: ethernet@ff0b0000 {
|
||||
#size-cells = <0>;
|
||||
iommus = <&smmu 0x874>;
|
||||
power-domains = <&zynqmp_firmware PD_ETH_0>;
|
||||
resets = <&zynqmp_reset ZYNQMP_RESET_GEM0>;
|
||||
reset-names = "gem0_rst";
|
||||
};
|
||||
|
||||
gem1: ethernet@ff0c0000 {
|
||||
@ -523,6 +525,8 @@ gem1: ethernet@ff0c0000 {
|
||||
#size-cells = <0>;
|
||||
iommus = <&smmu 0x875>;
|
||||
power-domains = <&zynqmp_firmware PD_ETH_1>;
|
||||
resets = <&zynqmp_reset ZYNQMP_RESET_GEM1>;
|
||||
reset-names = "gem1_rst";
|
||||
};
|
||||
|
||||
gem2: ethernet@ff0d0000 {
|
||||
@ -536,6 +540,8 @@ gem2: ethernet@ff0d0000 {
|
||||
#size-cells = <0>;
|
||||
iommus = <&smmu 0x876>;
|
||||
power-domains = <&zynqmp_firmware PD_ETH_2>;
|
||||
resets = <&zynqmp_reset ZYNQMP_RESET_GEM2>;
|
||||
reset-names = "gem2_rst";
|
||||
};
|
||||
|
||||
gem3: ethernet@ff0e0000 {
|
||||
@ -549,6 +555,8 @@ gem3: ethernet@ff0e0000 {
|
||||
#size-cells = <0>;
|
||||
iommus = <&smmu 0x877>;
|
||||
power-domains = <&zynqmp_firmware PD_ETH_3>;
|
||||
resets = <&zynqmp_reset ZYNQMP_RESET_GEM3>;
|
||||
reset-names = "gem3_rst";
|
||||
};
|
||||
|
||||
gpio: gpio@ff0a0000 {
|
||||
|
@ -88,17 +88,42 @@
|
||||
/* [Rn] = Rt; (atomic) Rs = [state] */
|
||||
#define A64_STXR(sf, Rt, Rn, Rs) \
|
||||
A64_LSX(sf, Rt, Rn, Rs, STORE_EX)
|
||||
/* [Rn] = Rt (store release); (atomic) Rs = [state] */
|
||||
#define A64_STLXR(sf, Rt, Rn, Rs) \
|
||||
aarch64_insn_gen_load_store_ex(Rt, Rn, Rs, A64_SIZE(sf), \
|
||||
AARCH64_INSN_LDST_STORE_REL_EX)
|
||||
|
||||
/*
|
||||
* LSE atomics
|
||||
*
|
||||
* STADD is simply encoded as an alias for LDADD with XZR as
|
||||
* the destination register.
|
||||
* ST{ADD,CLR,SET,EOR} is simply encoded as an alias for
|
||||
* LDD{ADD,CLR,SET,EOR} with XZR as the destination register.
|
||||
*/
|
||||
#define A64_STADD(sf, Rn, Rs) \
|
||||
#define A64_ST_OP(sf, Rn, Rs, op) \
|
||||
aarch64_insn_gen_atomic_ld_op(A64_ZR, Rn, Rs, \
|
||||
A64_SIZE(sf), AARCH64_INSN_MEM_ATOMIC_ADD, \
|
||||
A64_SIZE(sf), AARCH64_INSN_MEM_ATOMIC_##op, \
|
||||
AARCH64_INSN_MEM_ORDER_NONE)
|
||||
/* [Rn] <op>= Rs */
|
||||
#define A64_STADD(sf, Rn, Rs) A64_ST_OP(sf, Rn, Rs, ADD)
|
||||
#define A64_STCLR(sf, Rn, Rs) A64_ST_OP(sf, Rn, Rs, CLR)
|
||||
#define A64_STEOR(sf, Rn, Rs) A64_ST_OP(sf, Rn, Rs, EOR)
|
||||
#define A64_STSET(sf, Rn, Rs) A64_ST_OP(sf, Rn, Rs, SET)
|
||||
|
||||
#define A64_LD_OP_AL(sf, Rt, Rn, Rs, op) \
|
||||
aarch64_insn_gen_atomic_ld_op(Rt, Rn, Rs, \
|
||||
A64_SIZE(sf), AARCH64_INSN_MEM_ATOMIC_##op, \
|
||||
AARCH64_INSN_MEM_ORDER_ACQREL)
|
||||
/* Rt = [Rn] (load acquire); [Rn] <op>= Rs (store release) */
|
||||
#define A64_LDADDAL(sf, Rt, Rn, Rs) A64_LD_OP_AL(sf, Rt, Rn, Rs, ADD)
|
||||
#define A64_LDCLRAL(sf, Rt, Rn, Rs) A64_LD_OP_AL(sf, Rt, Rn, Rs, CLR)
|
||||
#define A64_LDEORAL(sf, Rt, Rn, Rs) A64_LD_OP_AL(sf, Rt, Rn, Rs, EOR)
|
||||
#define A64_LDSETAL(sf, Rt, Rn, Rs) A64_LD_OP_AL(sf, Rt, Rn, Rs, SET)
|
||||
/* Rt = [Rn] (load acquire); [Rn] = Rs (store release) */
|
||||
#define A64_SWPAL(sf, Rt, Rn, Rs) A64_LD_OP_AL(sf, Rt, Rn, Rs, SWP)
|
||||
/* Rs = CAS(Rn, Rs, Rt) (load acquire & store release) */
|
||||
#define A64_CASAL(sf, Rt, Rn, Rs) \
|
||||
aarch64_insn_gen_cas(Rt, Rn, Rs, A64_SIZE(sf), \
|
||||
AARCH64_INSN_MEM_ORDER_ACQREL)
|
||||
|
||||
/* Add/subtract (immediate) */
|
||||
#define A64_ADDSUB_IMM(sf, Rd, Rn, imm12, type) \
|
||||
@ -203,6 +228,9 @@
|
||||
#define A64_ANDS(sf, Rd, Rn, Rm) A64_LOGIC_SREG(sf, Rd, Rn, Rm, AND_SETFLAGS)
|
||||
/* Rn & Rm; set condition flags */
|
||||
#define A64_TST(sf, Rn, Rm) A64_ANDS(sf, A64_ZR, Rn, Rm)
|
||||
/* Rd = ~Rm (alias of ORN with A64_ZR as Rn) */
|
||||
#define A64_MVN(sf, Rd, Rm) \
|
||||
A64_LOGIC_SREG(sf, Rd, A64_ZR, Rm, ORN)
|
||||
|
||||
/* Logical (immediate) */
|
||||
#define A64_LOGIC_IMM(sf, Rd, Rn, imm, type) ({ \
|
||||
@ -226,4 +254,7 @@
|
||||
#define A64_BTI_J A64_HINT(AARCH64_INSN_HINT_BTIJ)
|
||||
#define A64_BTI_JC A64_HINT(AARCH64_INSN_HINT_BTIJC)
|
||||
|
||||
/* DMB */
|
||||
#define A64_DMB_ISH aarch64_insn_gen_dmb(AARCH64_INSN_MB_ISH)
|
||||
|
||||
#endif /* _BPF_JIT_H */
|
||||
|
@ -27,6 +27,17 @@
|
||||
#define TCALL_CNT (MAX_BPF_JIT_REG + 2)
|
||||
#define TMP_REG_3 (MAX_BPF_JIT_REG + 3)
|
||||
|
||||
#define check_imm(bits, imm) do { \
|
||||
if ((((imm) > 0) && ((imm) >> (bits))) || \
|
||||
(((imm) < 0) && (~(imm) >> (bits)))) { \
|
||||
pr_info("[%2d] imm=%d(0x%x) out of range\n", \
|
||||
i, imm, imm); \
|
||||
return -EINVAL; \
|
||||
} \
|
||||
} while (0)
|
||||
#define check_imm19(imm) check_imm(19, imm)
|
||||
#define check_imm26(imm) check_imm(26, imm)
|
||||
|
||||
/* Map BPF registers to A64 registers */
|
||||
static const int bpf2a64[] = {
|
||||
/* return value from in-kernel function, and exit value from eBPF */
|
||||
@ -329,6 +340,170 @@ static int emit_bpf_tail_call(struct jit_ctx *ctx)
|
||||
#undef jmp_offset
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ARM64_LSE_ATOMICS
|
||||
static int emit_lse_atomic(const struct bpf_insn *insn, struct jit_ctx *ctx)
|
||||
{
|
||||
const u8 code = insn->code;
|
||||
const u8 dst = bpf2a64[insn->dst_reg];
|
||||
const u8 src = bpf2a64[insn->src_reg];
|
||||
const u8 tmp = bpf2a64[TMP_REG_1];
|
||||
const u8 tmp2 = bpf2a64[TMP_REG_2];
|
||||
const bool isdw = BPF_SIZE(code) == BPF_DW;
|
||||
const s16 off = insn->off;
|
||||
u8 reg;
|
||||
|
||||
if (!off) {
|
||||
reg = dst;
|
||||
} else {
|
||||
emit_a64_mov_i(1, tmp, off, ctx);
|
||||
emit(A64_ADD(1, tmp, tmp, dst), ctx);
|
||||
reg = tmp;
|
||||
}
|
||||
|
||||
switch (insn->imm) {
|
||||
/* lock *(u32/u64 *)(dst_reg + off) <op>= src_reg */
|
||||
case BPF_ADD:
|
||||
emit(A64_STADD(isdw, reg, src), ctx);
|
||||
break;
|
||||
case BPF_AND:
|
||||
emit(A64_MVN(isdw, tmp2, src), ctx);
|
||||
emit(A64_STCLR(isdw, reg, tmp2), ctx);
|
||||
break;
|
||||
case BPF_OR:
|
||||
emit(A64_STSET(isdw, reg, src), ctx);
|
||||
break;
|
||||
case BPF_XOR:
|
||||
emit(A64_STEOR(isdw, reg, src), ctx);
|
||||
break;
|
||||
/* src_reg = atomic_fetch_<op>(dst_reg + off, src_reg) */
|
||||
case BPF_ADD | BPF_FETCH:
|
||||
emit(A64_LDADDAL(isdw, src, reg, src), ctx);
|
||||
break;
|
||||
case BPF_AND | BPF_FETCH:
|
||||
emit(A64_MVN(isdw, tmp2, src), ctx);
|
||||
emit(A64_LDCLRAL(isdw, src, reg, tmp2), ctx);
|
||||
break;
|
||||
case BPF_OR | BPF_FETCH:
|
||||
emit(A64_LDSETAL(isdw, src, reg, src), ctx);
|
||||
break;
|
||||
case BPF_XOR | BPF_FETCH:
|
||||
emit(A64_LDEORAL(isdw, src, reg, src), ctx);
|
||||
break;
|
||||
/* src_reg = atomic_xchg(dst_reg + off, src_reg); */
|
||||
case BPF_XCHG:
|
||||
emit(A64_SWPAL(isdw, src, reg, src), ctx);
|
||||
break;
|
||||
/* r0 = atomic_cmpxchg(dst_reg + off, r0, src_reg); */
|
||||
case BPF_CMPXCHG:
|
||||
emit(A64_CASAL(isdw, src, reg, bpf2a64[BPF_REG_0]), ctx);
|
||||
break;
|
||||
default:
|
||||
pr_err_once("unknown atomic op code %02x\n", insn->imm);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
static inline int emit_lse_atomic(const struct bpf_insn *insn, struct jit_ctx *ctx)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int emit_ll_sc_atomic(const struct bpf_insn *insn, struct jit_ctx *ctx)
|
||||
{
|
||||
const u8 code = insn->code;
|
||||
const u8 dst = bpf2a64[insn->dst_reg];
|
||||
const u8 src = bpf2a64[insn->src_reg];
|
||||
const u8 tmp = bpf2a64[TMP_REG_1];
|
||||
const u8 tmp2 = bpf2a64[TMP_REG_2];
|
||||
const u8 tmp3 = bpf2a64[TMP_REG_3];
|
||||
const int i = insn - ctx->prog->insnsi;
|
||||
const s32 imm = insn->imm;
|
||||
const s16 off = insn->off;
|
||||
const bool isdw = BPF_SIZE(code) == BPF_DW;
|
||||
u8 reg;
|
||||
s32 jmp_offset;
|
||||
|
||||
if (!off) {
|
||||
reg = dst;
|
||||
} else {
|
||||
emit_a64_mov_i(1, tmp, off, ctx);
|
||||
emit(A64_ADD(1, tmp, tmp, dst), ctx);
|
||||
reg = tmp;
|
||||
}
|
||||
|
||||
if (imm == BPF_ADD || imm == BPF_AND ||
|
||||
imm == BPF_OR || imm == BPF_XOR) {
|
||||
/* lock *(u32/u64 *)(dst_reg + off) <op>= src_reg */
|
||||
emit(A64_LDXR(isdw, tmp2, reg), ctx);
|
||||
if (imm == BPF_ADD)
|
||||
emit(A64_ADD(isdw, tmp2, tmp2, src), ctx);
|
||||
else if (imm == BPF_AND)
|
||||
emit(A64_AND(isdw, tmp2, tmp2, src), ctx);
|
||||
else if (imm == BPF_OR)
|
||||
emit(A64_ORR(isdw, tmp2, tmp2, src), ctx);
|
||||
else
|
||||
emit(A64_EOR(isdw, tmp2, tmp2, src), ctx);
|
||||
emit(A64_STXR(isdw, tmp2, reg, tmp3), ctx);
|
||||
jmp_offset = -3;
|
||||
check_imm19(jmp_offset);
|
||||
emit(A64_CBNZ(0, tmp3, jmp_offset), ctx);
|
||||
} else if (imm == (BPF_ADD | BPF_FETCH) ||
|
||||
imm == (BPF_AND | BPF_FETCH) ||
|
||||
imm == (BPF_OR | BPF_FETCH) ||
|
||||
imm == (BPF_XOR | BPF_FETCH)) {
|
||||
/* src_reg = atomic_fetch_<op>(dst_reg + off, src_reg) */
|
||||
const u8 ax = bpf2a64[BPF_REG_AX];
|
||||
|
||||
emit(A64_MOV(isdw, ax, src), ctx);
|
||||
emit(A64_LDXR(isdw, src, reg), ctx);
|
||||
if (imm == (BPF_ADD | BPF_FETCH))
|
||||
emit(A64_ADD(isdw, tmp2, src, ax), ctx);
|
||||
else if (imm == (BPF_AND | BPF_FETCH))
|
||||
emit(A64_AND(isdw, tmp2, src, ax), ctx);
|
||||
else if (imm == (BPF_OR | BPF_FETCH))
|
||||
emit(A64_ORR(isdw, tmp2, src, ax), ctx);
|
||||
else
|
||||
emit(A64_EOR(isdw, tmp2, src, ax), ctx);
|
||||
emit(A64_STLXR(isdw, tmp2, reg, tmp3), ctx);
|
||||
jmp_offset = -3;
|
||||
check_imm19(jmp_offset);
|
||||
emit(A64_CBNZ(0, tmp3, jmp_offset), ctx);
|
||||
emit(A64_DMB_ISH, ctx);
|
||||
} else if (imm == BPF_XCHG) {
|
||||
/* src_reg = atomic_xchg(dst_reg + off, src_reg); */
|
||||
emit(A64_MOV(isdw, tmp2, src), ctx);
|
||||
emit(A64_LDXR(isdw, src, reg), ctx);
|
||||
emit(A64_STLXR(isdw, tmp2, reg, tmp3), ctx);
|
||||
jmp_offset = -2;
|
||||
check_imm19(jmp_offset);
|
||||
emit(A64_CBNZ(0, tmp3, jmp_offset), ctx);
|
||||
emit(A64_DMB_ISH, ctx);
|
||||
} else if (imm == BPF_CMPXCHG) {
|
||||
/* r0 = atomic_cmpxchg(dst_reg + off, r0, src_reg); */
|
||||
const u8 r0 = bpf2a64[BPF_REG_0];
|
||||
|
||||
emit(A64_MOV(isdw, tmp2, r0), ctx);
|
||||
emit(A64_LDXR(isdw, r0, reg), ctx);
|
||||
emit(A64_EOR(isdw, tmp3, r0, tmp2), ctx);
|
||||
jmp_offset = 4;
|
||||
check_imm19(jmp_offset);
|
||||
emit(A64_CBNZ(isdw, tmp3, jmp_offset), ctx);
|
||||
emit(A64_STLXR(isdw, src, reg, tmp3), ctx);
|
||||
jmp_offset = -4;
|
||||
check_imm19(jmp_offset);
|
||||
emit(A64_CBNZ(0, tmp3, jmp_offset), ctx);
|
||||
emit(A64_DMB_ISH, ctx);
|
||||
} else {
|
||||
pr_err_once("unknown atomic op code %02x\n", imm);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void build_epilogue(struct jit_ctx *ctx)
|
||||
{
|
||||
const u8 r0 = bpf2a64[BPF_REG_0];
|
||||
@ -434,29 +609,16 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx,
|
||||
const u8 src = bpf2a64[insn->src_reg];
|
||||
const u8 tmp = bpf2a64[TMP_REG_1];
|
||||
const u8 tmp2 = bpf2a64[TMP_REG_2];
|
||||
const u8 tmp3 = bpf2a64[TMP_REG_3];
|
||||
const s16 off = insn->off;
|
||||
const s32 imm = insn->imm;
|
||||
const int i = insn - ctx->prog->insnsi;
|
||||
const bool is64 = BPF_CLASS(code) == BPF_ALU64 ||
|
||||
BPF_CLASS(code) == BPF_JMP;
|
||||
const bool isdw = BPF_SIZE(code) == BPF_DW;
|
||||
u8 jmp_cond, reg;
|
||||
u8 jmp_cond;
|
||||
s32 jmp_offset;
|
||||
u32 a64_insn;
|
||||
int ret;
|
||||
|
||||
#define check_imm(bits, imm) do { \
|
||||
if ((((imm) > 0) && ((imm) >> (bits))) || \
|
||||
(((imm) < 0) && (~(imm) >> (bits)))) { \
|
||||
pr_info("[%2d] imm=%d(0x%x) out of range\n", \
|
||||
i, imm, imm); \
|
||||
return -EINVAL; \
|
||||
} \
|
||||
} while (0)
|
||||
#define check_imm19(imm) check_imm(19, imm)
|
||||
#define check_imm26(imm) check_imm(26, imm)
|
||||
|
||||
switch (code) {
|
||||
/* dst = src */
|
||||
case BPF_ALU | BPF_MOV | BPF_X:
|
||||
@ -891,33 +1053,12 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx,
|
||||
|
||||
case BPF_STX | BPF_ATOMIC | BPF_W:
|
||||
case BPF_STX | BPF_ATOMIC | BPF_DW:
|
||||
if (insn->imm != BPF_ADD) {
|
||||
pr_err_once("unknown atomic op code %02x\n", insn->imm);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* STX XADD: lock *(u32 *)(dst + off) += src
|
||||
* and
|
||||
* STX XADD: lock *(u64 *)(dst + off) += src
|
||||
*/
|
||||
|
||||
if (!off) {
|
||||
reg = dst;
|
||||
} else {
|
||||
emit_a64_mov_i(1, tmp, off, ctx);
|
||||
emit(A64_ADD(1, tmp, tmp, dst), ctx);
|
||||
reg = tmp;
|
||||
}
|
||||
if (cpus_have_cap(ARM64_HAS_LSE_ATOMICS)) {
|
||||
emit(A64_STADD(isdw, reg, src), ctx);
|
||||
} else {
|
||||
emit(A64_LDXR(isdw, tmp2, reg), ctx);
|
||||
emit(A64_ADD(isdw, tmp2, tmp2, src), ctx);
|
||||
emit(A64_STXR(isdw, tmp2, reg, tmp3), ctx);
|
||||
jmp_offset = -3;
|
||||
check_imm19(jmp_offset);
|
||||
emit(A64_CBNZ(0, tmp3, jmp_offset), ctx);
|
||||
}
|
||||
if (cpus_have_cap(ARM64_HAS_LSE_ATOMICS))
|
||||
ret = emit_lse_atomic(insn, ctx);
|
||||
else
|
||||
ret = emit_ll_sc_atomic(insn, ctx);
|
||||
if (ret)
|
||||
return ret;
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -1049,15 +1190,18 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
|
||||
goto out_off;
|
||||
}
|
||||
|
||||
/* 1. Initial fake pass to compute ctx->idx. */
|
||||
|
||||
/* Fake pass to fill in ctx->offset. */
|
||||
if (build_body(&ctx, extra_pass)) {
|
||||
/*
|
||||
* 1. Initial fake pass to compute ctx->idx and ctx->offset.
|
||||
*
|
||||
* BPF line info needs ctx->offset[i] to be the offset of
|
||||
* instruction[i] in jited image, so build prologue first.
|
||||
*/
|
||||
if (build_prologue(&ctx, was_classic)) {
|
||||
prog = orig_prog;
|
||||
goto out_off;
|
||||
}
|
||||
|
||||
if (build_prologue(&ctx, was_classic)) {
|
||||
if (build_body(&ctx, extra_pass)) {
|
||||
prog = orig_prog;
|
||||
goto out_off;
|
||||
}
|
||||
@ -1130,6 +1274,11 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
|
||||
prog->jited_len = prog_size;
|
||||
|
||||
if (!prog->is_func || extra_pass) {
|
||||
int i;
|
||||
|
||||
/* offset[prog->len] is the size of program */
|
||||
for (i = 0; i <= prog->len; i++)
|
||||
ctx.offset[i] *= AARCH64_INSN_SIZE;
|
||||
bpf_prog_fill_jited_linfo(prog, ctx.offset + 1);
|
||||
out_off:
|
||||
kfree(ctx.offset);
|
||||
@ -1143,6 +1292,11 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
|
||||
return prog;
|
||||
}
|
||||
|
||||
bool bpf_jit_supports_kfunc_call(void)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
u64 bpf_jit_alloc_exec_limit(void)
|
||||
{
|
||||
return VMALLOC_END - VMALLOC_START;
|
||||
|
@ -144,6 +144,8 @@
|
||||
|
||||
#define SO_RESERVE_MEM 73
|
||||
|
||||
#define SO_TXREHASH 74
|
||||
|
||||
#if !defined(__KERNEL__)
|
||||
|
||||
#if __BITS_PER_LONG == 64
|
||||
|
@ -125,6 +125,8 @@
|
||||
|
||||
#define SO_RESERVE_MEM 0x4047
|
||||
|
||||
#define SO_TXREHASH 0x4048
|
||||
|
||||
#if !defined(__KERNEL__)
|
||||
|
||||
#if __BITS_PER_LONG == 64
|
||||
|
@ -112,6 +112,13 @@ static __always_inline __wsum csum_add(__wsum csum, __wsum addend)
|
||||
#endif
|
||||
}
|
||||
|
||||
#define HAVE_ARCH_CSUM_SHIFT
|
||||
static __always_inline __wsum csum_shift(__wsum sum, int offset)
|
||||
{
|
||||
/* rotate sum to align it with a 16b boundary */
|
||||
return (__force __wsum)rol32((__force u32)sum, (offset & 1) << 3);
|
||||
}
|
||||
|
||||
/*
|
||||
* This is a version of ip_compute_csum() optimized for IP headers,
|
||||
* which always checksum on 4 octet boundaries. ihl is the number
|
||||
|
@ -264,7 +264,7 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *fp)
|
||||
fp->jited = 1;
|
||||
fp->jited_len = proglen + FUNCTION_DESCR_SIZE;
|
||||
|
||||
bpf_flush_icache(bpf_hdr, (u8 *)bpf_hdr + (bpf_hdr->pages * PAGE_SIZE));
|
||||
bpf_flush_icache(bpf_hdr, (u8 *)bpf_hdr + bpf_hdr->size);
|
||||
if (!fp->is_func || extra_pass) {
|
||||
bpf_jit_binary_lock_ro(bpf_hdr);
|
||||
bpf_prog_fill_jited_linfo(fp, addrs);
|
||||
|
@ -126,6 +126,8 @@
|
||||
|
||||
#define SO_RESERVE_MEM 0x0052
|
||||
|
||||
#define SO_TXREHASH 0x0053
|
||||
|
||||
|
||||
#if !defined(__KERNEL__)
|
||||
|
||||
|
@ -1599,7 +1599,7 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
|
||||
if (bpf_jit_enable > 1)
|
||||
bpf_jit_dump(prog->len, image_size, pass, ctx.image);
|
||||
|
||||
bpf_flush_icache(header, (u8 *)header + (header->pages * PAGE_SIZE));
|
||||
bpf_flush_icache(header, (u8 *)header + header->size);
|
||||
|
||||
if (!prog->is_func || extra_pass) {
|
||||
bpf_jit_binary_lock_ro(header);
|
||||
|
@ -161,6 +161,7 @@ config X86
|
||||
select HAVE_ALIGNED_STRUCT_PAGE if SLUB
|
||||
select HAVE_ARCH_AUDITSYSCALL
|
||||
select HAVE_ARCH_HUGE_VMAP if X86_64 || X86_PAE
|
||||
select HAVE_ARCH_HUGE_VMALLOC if X86_64
|
||||
select HAVE_ARCH_JUMP_LABEL
|
||||
select HAVE_ARCH_JUMP_LABEL_RELATIVE
|
||||
select HAVE_ARCH_KASAN if X86_64
|
||||
|
@ -44,6 +44,7 @@ extern void text_poke_early(void *addr, const void *opcode, size_t len);
|
||||
extern void *text_poke(void *addr, const void *opcode, size_t len);
|
||||
extern void text_poke_sync(void);
|
||||
extern void *text_poke_kgdb(void *addr, const void *opcode, size_t len);
|
||||
extern void *text_poke_copy(void *addr, const void *opcode, size_t len);
|
||||
extern int poke_int3_handler(struct pt_regs *regs);
|
||||
extern void text_poke_bp(void *addr, const void *opcode, size_t len, const void *emulate);
|
||||
|
||||
|
@ -1102,6 +1102,40 @@ void *text_poke_kgdb(void *addr, const void *opcode, size_t len)
|
||||
return __text_poke(addr, opcode, len);
|
||||
}
|
||||
|
||||
/**
|
||||
* text_poke_copy - Copy instructions into (an unused part of) RX memory
|
||||
* @addr: address to modify
|
||||
* @opcode: source of the copy
|
||||
* @len: length to copy, could be more than 2x PAGE_SIZE
|
||||
*
|
||||
* Not safe against concurrent execution; useful for JITs to dump
|
||||
* new code blocks into unused regions of RX memory. Can be used in
|
||||
* conjunction with synchronize_rcu_tasks() to wait for existing
|
||||
* execution to quiesce after having made sure no existing functions
|
||||
* pointers are live.
|
||||
*/
|
||||
void *text_poke_copy(void *addr, const void *opcode, size_t len)
|
||||
{
|
||||
unsigned long start = (unsigned long)addr;
|
||||
size_t patched = 0;
|
||||
|
||||
if (WARN_ON_ONCE(core_kernel_text(start)))
|
||||
return NULL;
|
||||
|
||||
mutex_lock(&text_mutex);
|
||||
while (patched < len) {
|
||||
unsigned long ptr = start + patched;
|
||||
size_t s;
|
||||
|
||||
s = min_t(size_t, PAGE_SIZE * 2 - offset_in_page(ptr), len - patched);
|
||||
|
||||
__text_poke((void *)ptr, opcode + patched, s);
|
||||
patched += s;
|
||||
}
|
||||
mutex_unlock(&text_mutex);
|
||||
return addr;
|
||||
}
|
||||
|
||||
static void do_sync_core(void *info)
|
||||
{
|
||||
sync_core();
|
||||
|
@ -330,8 +330,7 @@ static int emit_jump(u8 **pprog, void *func, void *ip)
|
||||
}
|
||||
|
||||
static int __bpf_arch_text_poke(void *ip, enum bpf_text_poke_type t,
|
||||
void *old_addr, void *new_addr,
|
||||
const bool text_live)
|
||||
void *old_addr, void *new_addr)
|
||||
{
|
||||
const u8 *nop_insn = x86_nops[5];
|
||||
u8 old_insn[X86_PATCH_SIZE];
|
||||
@ -365,10 +364,7 @@ static int __bpf_arch_text_poke(void *ip, enum bpf_text_poke_type t,
|
||||
goto out;
|
||||
ret = 1;
|
||||
if (memcmp(ip, new_insn, X86_PATCH_SIZE)) {
|
||||
if (text_live)
|
||||
text_poke_bp(ip, new_insn, X86_PATCH_SIZE, NULL);
|
||||
else
|
||||
memcpy(ip, new_insn, X86_PATCH_SIZE);
|
||||
text_poke_bp(ip, new_insn, X86_PATCH_SIZE, NULL);
|
||||
ret = 0;
|
||||
}
|
||||
out:
|
||||
@ -384,7 +380,7 @@ int bpf_arch_text_poke(void *ip, enum bpf_text_poke_type t,
|
||||
/* BPF poking in modules is not supported */
|
||||
return -EINVAL;
|
||||
|
||||
return __bpf_arch_text_poke(ip, t, old_addr, new_addr, true);
|
||||
return __bpf_arch_text_poke(ip, t, old_addr, new_addr);
|
||||
}
|
||||
|
||||
#define EMIT_LFENCE() EMIT3(0x0F, 0xAE, 0xE8)
|
||||
@ -558,24 +554,15 @@ static void bpf_tail_call_direct_fixup(struct bpf_prog *prog)
|
||||
mutex_lock(&array->aux->poke_mutex);
|
||||
target = array->ptrs[poke->tail_call.key];
|
||||
if (target) {
|
||||
/* Plain memcpy is used when image is not live yet
|
||||
* and still not locked as read-only. Once poke
|
||||
* location is active (poke->tailcall_target_stable),
|
||||
* any parallel bpf_arch_text_poke() might occur
|
||||
* still on the read-write image until we finally
|
||||
* locked it as read-only. Both modifications on
|
||||
* the given image are under text_mutex to avoid
|
||||
* interference.
|
||||
*/
|
||||
ret = __bpf_arch_text_poke(poke->tailcall_target,
|
||||
BPF_MOD_JUMP, NULL,
|
||||
(u8 *)target->bpf_func +
|
||||
poke->adj_off, false);
|
||||
poke->adj_off);
|
||||
BUG_ON(ret < 0);
|
||||
ret = __bpf_arch_text_poke(poke->tailcall_bypass,
|
||||
BPF_MOD_JUMP,
|
||||
(u8 *)poke->tailcall_target +
|
||||
X86_PATCH_SIZE, NULL, false);
|
||||
X86_PATCH_SIZE, NULL);
|
||||
BUG_ON(ret < 0);
|
||||
}
|
||||
WRITE_ONCE(poke->tailcall_target_stable, true);
|
||||
@ -787,7 +774,6 @@ static int emit_atomic(u8 **pprog, u8 atomic_op,
|
||||
/* emit opcode */
|
||||
switch (atomic_op) {
|
||||
case BPF_ADD:
|
||||
case BPF_SUB:
|
||||
case BPF_AND:
|
||||
case BPF_OR:
|
||||
case BPF_XOR:
|
||||
@ -867,7 +853,7 @@ static void emit_nops(u8 **pprog, int len)
|
||||
|
||||
#define INSN_SZ_DIFF (((addrs[i] - addrs[i - 1]) - (prog - temp)))
|
||||
|
||||
static int do_jit(struct bpf_prog *bpf_prog, int *addrs, u8 *image,
|
||||
static int do_jit(struct bpf_prog *bpf_prog, int *addrs, u8 *image, u8 *rw_image,
|
||||
int oldproglen, struct jit_context *ctx, bool jmp_padding)
|
||||
{
|
||||
bool tail_call_reachable = bpf_prog->aux->tail_call_reachable;
|
||||
@ -894,8 +880,8 @@ static int do_jit(struct bpf_prog *bpf_prog, int *addrs, u8 *image,
|
||||
push_callee_regs(&prog, callee_regs_used);
|
||||
|
||||
ilen = prog - temp;
|
||||
if (image)
|
||||
memcpy(image + proglen, temp, ilen);
|
||||
if (rw_image)
|
||||
memcpy(rw_image + proglen, temp, ilen);
|
||||
proglen += ilen;
|
||||
addrs[0] = proglen;
|
||||
prog = temp;
|
||||
@ -1324,6 +1310,9 @@ st: if (is_imm8(insn->off))
|
||||
pr_err("extable->insn doesn't fit into 32-bit\n");
|
||||
return -EFAULT;
|
||||
}
|
||||
/* switch ex to rw buffer for writes */
|
||||
ex = (void *)rw_image + ((void *)ex - (void *)image);
|
||||
|
||||
ex->insn = delta;
|
||||
|
||||
ex->data = EX_TYPE_BPF;
|
||||
@ -1706,7 +1695,7 @@ st: if (is_imm8(insn->off))
|
||||
pr_err("bpf_jit: fatal error\n");
|
||||
return -EFAULT;
|
||||
}
|
||||
memcpy(image + proglen, temp, ilen);
|
||||
memcpy(rw_image + proglen, temp, ilen);
|
||||
}
|
||||
proglen += ilen;
|
||||
addrs[i] = proglen;
|
||||
@ -2247,6 +2236,7 @@ int arch_prepare_bpf_dispatcher(void *image, s64 *funcs, int num_funcs)
|
||||
}
|
||||
|
||||
struct x64_jit_data {
|
||||
struct bpf_binary_header *rw_header;
|
||||
struct bpf_binary_header *header;
|
||||
int *addrs;
|
||||
u8 *image;
|
||||
@ -2259,6 +2249,7 @@ struct x64_jit_data {
|
||||
|
||||
struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
|
||||
{
|
||||
struct bpf_binary_header *rw_header = NULL;
|
||||
struct bpf_binary_header *header = NULL;
|
||||
struct bpf_prog *tmp, *orig_prog = prog;
|
||||
struct x64_jit_data *jit_data;
|
||||
@ -2267,6 +2258,7 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
|
||||
bool tmp_blinded = false;
|
||||
bool extra_pass = false;
|
||||
bool padding = false;
|
||||
u8 *rw_image = NULL;
|
||||
u8 *image = NULL;
|
||||
int *addrs;
|
||||
int pass;
|
||||
@ -2302,6 +2294,8 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
|
||||
oldproglen = jit_data->proglen;
|
||||
image = jit_data->image;
|
||||
header = jit_data->header;
|
||||
rw_header = jit_data->rw_header;
|
||||
rw_image = (void *)rw_header + ((void *)image - (void *)header);
|
||||
extra_pass = true;
|
||||
padding = true;
|
||||
goto skip_init_addrs;
|
||||
@ -2332,13 +2326,22 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
|
||||
for (pass = 0; pass < MAX_PASSES || image; pass++) {
|
||||
if (!padding && pass >= PADDING_PASSES)
|
||||
padding = true;
|
||||
proglen = do_jit(prog, addrs, image, oldproglen, &ctx, padding);
|
||||
proglen = do_jit(prog, addrs, image, rw_image, oldproglen, &ctx, padding);
|
||||
if (proglen <= 0) {
|
||||
out_image:
|
||||
image = NULL;
|
||||
if (header)
|
||||
bpf_jit_binary_free(header);
|
||||
if (header) {
|
||||
bpf_arch_text_copy(&header->size, &rw_header->size,
|
||||
sizeof(rw_header->size));
|
||||
bpf_jit_binary_pack_free(header, rw_header);
|
||||
}
|
||||
/* Fall back to interpreter mode */
|
||||
prog = orig_prog;
|
||||
if (extra_pass) {
|
||||
prog->bpf_func = NULL;
|
||||
prog->jited = 0;
|
||||
prog->jited_len = 0;
|
||||
}
|
||||
goto out_addrs;
|
||||
}
|
||||
if (image) {
|
||||
@ -2361,8 +2364,9 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
|
||||
sizeof(struct exception_table_entry);
|
||||
|
||||
/* allocate module memory for x86 insns and extable */
|
||||
header = bpf_jit_binary_alloc(roundup(proglen, align) + extable_size,
|
||||
&image, align, jit_fill_hole);
|
||||
header = bpf_jit_binary_pack_alloc(roundup(proglen, align) + extable_size,
|
||||
&image, align, &rw_header, &rw_image,
|
||||
jit_fill_hole);
|
||||
if (!header) {
|
||||
prog = orig_prog;
|
||||
goto out_addrs;
|
||||
@ -2378,14 +2382,27 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
|
||||
|
||||
if (image) {
|
||||
if (!prog->is_func || extra_pass) {
|
||||
/*
|
||||
* bpf_jit_binary_pack_finalize fails in two scenarios:
|
||||
* 1) header is not pointing to proper module memory;
|
||||
* 2) the arch doesn't support bpf_arch_text_copy().
|
||||
*
|
||||
* Both cases are serious bugs and justify WARN_ON.
|
||||
*/
|
||||
if (WARN_ON(bpf_jit_binary_pack_finalize(prog, header, rw_header))) {
|
||||
/* header has been freed */
|
||||
header = NULL;
|
||||
goto out_image;
|
||||
}
|
||||
|
||||
bpf_tail_call_direct_fixup(prog);
|
||||
bpf_jit_binary_lock_ro(header);
|
||||
} else {
|
||||
jit_data->addrs = addrs;
|
||||
jit_data->ctx = ctx;
|
||||
jit_data->proglen = proglen;
|
||||
jit_data->image = image;
|
||||
jit_data->header = header;
|
||||
jit_data->rw_header = rw_header;
|
||||
}
|
||||
prog->bpf_func = (void *)image;
|
||||
prog->jited = 1;
|
||||
@ -2413,3 +2430,10 @@ bool bpf_jit_supports_kfunc_call(void)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void *bpf_arch_text_copy(void *dst, void *src, size_t len)
|
||||
{
|
||||
if (text_poke_copy(dst, src, len) == NULL)
|
||||
return ERR_PTR(-EINVAL);
|
||||
return dst;
|
||||
}
|
||||
|
@ -304,7 +304,7 @@ static int iss_net_rx(struct net_device *dev)
|
||||
|
||||
lp->stats.rx_bytes += skb->len;
|
||||
lp->stats.rx_packets++;
|
||||
netif_rx_ni(skb);
|
||||
netif_rx(skb);
|
||||
return pkt_len;
|
||||
}
|
||||
kfree_skb(skb);
|
||||
|
@ -861,7 +861,6 @@ static void ns_init_card_error(ns_dev *card, int error)
|
||||
static scq_info *get_scq(ns_dev *card, int size, u32 scd)
|
||||
{
|
||||
scq_info *scq;
|
||||
int i;
|
||||
|
||||
if (size != VBR_SCQSIZE && size != CBR_SCQSIZE)
|
||||
return NULL;
|
||||
@ -875,9 +874,8 @@ static scq_info *get_scq(ns_dev *card, int size, u32 scd)
|
||||
kfree(scq);
|
||||
return NULL;
|
||||
}
|
||||
scq->skb = kmalloc_array(size / NS_SCQE_SIZE,
|
||||
sizeof(*scq->skb),
|
||||
GFP_KERNEL);
|
||||
scq->skb = kcalloc(size / NS_SCQE_SIZE, sizeof(*scq->skb),
|
||||
GFP_KERNEL);
|
||||
if (!scq->skb) {
|
||||
dma_free_coherent(&card->pcidev->dev,
|
||||
2 * size, scq->org, scq->dma);
|
||||
@ -890,15 +888,11 @@ static scq_info *get_scq(ns_dev *card, int size, u32 scd)
|
||||
scq->last = scq->base + (scq->num_entries - 1);
|
||||
scq->tail = scq->last;
|
||||
scq->scd = scd;
|
||||
scq->num_entries = size / NS_SCQE_SIZE;
|
||||
scq->tbd_count = 0;
|
||||
init_waitqueue_head(&scq->scqfull_waitq);
|
||||
scq->full = 0;
|
||||
spin_lock_init(&scq->lock);
|
||||
|
||||
for (i = 0; i < scq->num_entries; i++)
|
||||
scq->skb[i] = NULL;
|
||||
|
||||
return scq;
|
||||
}
|
||||
|
||||
|
@ -303,7 +303,7 @@ u32 bcma_chipco_gpio_outen(struct bcma_drv_cc *cc, u32 mask, u32 value)
|
||||
EXPORT_SYMBOL_GPL(bcma_chipco_gpio_outen);
|
||||
|
||||
/*
|
||||
* If the bit is set to 0, chipcommon controlls this GPIO,
|
||||
* If the bit is set to 0, chipcommon controls this GPIO,
|
||||
* if the bit is set to 1, it is used by some part of the chip and not our code.
|
||||
*/
|
||||
u32 bcma_chipco_gpio_control(struct bcma_drv_cc *cc, u32 mask, u32 value)
|
||||
|
@ -206,7 +206,7 @@ static void bcma_pmu_resources_init(struct bcma_drv_cc *cc)
|
||||
usleep_range(2000, 2500);
|
||||
}
|
||||
|
||||
/* Disable to allow reading SPROM. Don't know the adventages of enabling it. */
|
||||
/* Disable to allow reading SPROM. Don't know the advantages of enabling it. */
|
||||
void bcma_chipco_bcm4331_ext_pa_lines_ctl(struct bcma_drv_cc *cc, bool enable)
|
||||
{
|
||||
struct bcma_bus *bus = cc->core->bus;
|
||||
@ -234,7 +234,7 @@ static void bcma_pmu_workarounds(struct bcma_drv_cc *cc)
|
||||
switch (bus->chipinfo.id) {
|
||||
case BCMA_CHIP_ID_BCM4313:
|
||||
/*
|
||||
* enable 12 mA drive strenth for 4313 and set chipControl
|
||||
* enable 12 mA drive strength for 4313 and set chipControl
|
||||
* register bit 1
|
||||
*/
|
||||
bcma_chipco_chipctl_maskset(cc, 0,
|
||||
@ -249,7 +249,7 @@ static void bcma_pmu_workarounds(struct bcma_drv_cc *cc)
|
||||
case BCMA_CHIP_ID_BCM43224:
|
||||
case BCMA_CHIP_ID_BCM43421:
|
||||
/*
|
||||
* enable 12 mA drive strenth for 43224 and set chipControl
|
||||
* enable 12 mA drive strength for 43224 and set chipControl
|
||||
* register bit 15
|
||||
*/
|
||||
if (bus->chipinfo.rev == 0) {
|
||||
|
@ -181,7 +181,6 @@ int bcma_gpio_init(struct bcma_drv_cc *cc)
|
||||
chip->set = bcma_gpio_set_value;
|
||||
chip->direction_input = bcma_gpio_direction_input;
|
||||
chip->direction_output = bcma_gpio_direction_output;
|
||||
chip->owner = THIS_MODULE;
|
||||
chip->parent = bus->dev;
|
||||
#if IS_BUILTIN(CONFIG_OF)
|
||||
chip->of_node = cc->core->dev.of_node;
|
||||
|
@ -61,7 +61,7 @@ static u32 bcma_get_cfgspace_addr(struct bcma_drv_pci *pc, unsigned int dev,
|
||||
{
|
||||
u32 addr = 0;
|
||||
|
||||
/* Issue config commands only when the data link is up (atleast
|
||||
/* Issue config commands only when the data link is up (at least
|
||||
* one external pcie device is present).
|
||||
*/
|
||||
if (dev >= 2 || !(bcma_pcie_read(pc, BCMA_CORE_PCI_DLLP_LSREG)
|
||||
@ -295,7 +295,7 @@ static u8 bcma_find_pci_capability(struct bcma_drv_pci *pc, unsigned int dev,
|
||||
if (cap_ptr == 0x00)
|
||||
return cap_ptr;
|
||||
|
||||
/* loop thr'u the capability list and see if the requested capabilty
|
||||
/* loop through the capability list and see if the requested capability
|
||||
* exists */
|
||||
bcma_extpci_read_config(pc, dev, func, cap_ptr, &cap_id, sizeof(u8));
|
||||
while (cap_id != req_cap_id) {
|
||||
@ -317,7 +317,7 @@ static u8 bcma_find_pci_capability(struct bcma_drv_pci *pc, unsigned int dev,
|
||||
|
||||
*buflen = 0;
|
||||
|
||||
/* copy the cpability data excluding cap ID and next ptr */
|
||||
/* copy the capability data excluding cap ID and next ptr */
|
||||
cap_data = cap_ptr + 2;
|
||||
if ((bufsize + cap_data) > PCI_CONFIG_SPACE_SIZE)
|
||||
bufsize = PCI_CONFIG_SPACE_SIZE - cap_data;
|
||||
|
@ -293,7 +293,7 @@ static int bcma_register_devices(struct bcma_bus *bus)
|
||||
int err;
|
||||
|
||||
list_for_each_entry(core, &bus->cores, list) {
|
||||
/* We support that cores ourself */
|
||||
/* We support that core ourselves */
|
||||
switch (core->id.id) {
|
||||
case BCMA_CORE_4706_CHIPCOMMON:
|
||||
case BCMA_CORE_CHIPCOMMON:
|
||||
@ -369,7 +369,7 @@ void bcma_unregister_cores(struct bcma_bus *bus)
|
||||
if (bus->hosttype == BCMA_HOSTTYPE_SOC)
|
||||
platform_device_unregister(bus->drv_cc.watchdog);
|
||||
|
||||
/* Now noone uses internally-handled cores, we can free them */
|
||||
/* Now no one uses internally-handled cores, we can free them */
|
||||
list_for_each_entry_safe(core, tmp, &bus->cores, list) {
|
||||
list_del(&core->list);
|
||||
put_device(&core->dev);
|
||||
|
@ -28,7 +28,7 @@ static int(*get_fallback_sprom)(struct bcma_bus *dev, struct ssb_sprom *out);
|
||||
* callback handler which fills the SPROM data structure. The fallback is
|
||||
* used for PCI based BCMA devices, where no valid SPROM can be found
|
||||
* in the shadow registers and to provide the SPROM for SoCs where BCMA is
|
||||
* to controll the system bus.
|
||||
* to control the system bus.
|
||||
*
|
||||
* This function is useful for weird architectures that have a half-assed
|
||||
* BCMA device hardwired to their PCI bus.
|
||||
@ -281,7 +281,7 @@ static void bcma_sprom_extract_r8(struct bcma_bus *bus, const u16 *sprom)
|
||||
SPEX(alpha2[0], SSB_SPROM8_CCODE, 0xff00, 8);
|
||||
SPEX(alpha2[1], SSB_SPROM8_CCODE, 0x00ff, 0);
|
||||
|
||||
/* Extract cores power info info */
|
||||
/* Extract core's power info */
|
||||
for (i = 0; i < ARRAY_SIZE(pwr_info_offset); i++) {
|
||||
o = pwr_info_offset[i];
|
||||
SPEX(core_pwr_info[i].itssi_2g, o + SSB_SROM8_2G_MAXP_ITSSI,
|
||||
|
@ -400,6 +400,7 @@ config BT_MTKSDIO
|
||||
config BT_MTKUART
|
||||
tristate "MediaTek HCI UART driver"
|
||||
depends on SERIAL_DEV_BUS
|
||||
select BT_MTK
|
||||
help
|
||||
MediaTek Bluetooth HCI UART driver.
|
||||
This driver is required if you want to use MediaTek Bluetooth
|
||||
|
@ -10,7 +10,6 @@
|
||||
#include <linux/slab.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/firmware.h>
|
||||
#include <linux/usb.h>
|
||||
#include <asm/unaligned.h>
|
||||
|
@ -9,7 +9,6 @@
|
||||
|
||||
#include <linux/module.h>
|
||||
|
||||
#include <linux/atomic.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/slab.h>
|
||||
|
@ -2428,10 +2428,15 @@ static int btintel_setup_combined(struct hci_dev *hdev)
|
||||
|
||||
/* Apply the device specific HCI quirks
|
||||
*
|
||||
* WBS for SdP - SdP and Stp have a same hw_varaint but
|
||||
* different fw_variant
|
||||
* WBS for SdP - For the Legacy ROM products, only SdP
|
||||
* supports the WBS. But the version information is not
|
||||
* enough to use here because the StP2 and SdP have same
|
||||
* hw_variant and fw_variant. So, this flag is set by
|
||||
* the transport driver (btusb) based on the HW info
|
||||
* (idProduct)
|
||||
*/
|
||||
if (ver.hw_variant == 0x08 && ver.fw_variant == 0x22)
|
||||
if (!btintel_test_flag(hdev,
|
||||
INTEL_ROM_LEGACY_NO_WBS_SUPPORT))
|
||||
set_bit(HCI_QUIRK_WIDEBAND_SPEECH_SUPPORTED,
|
||||
&hdev->quirks);
|
||||
|
||||
|
@ -152,6 +152,7 @@ enum {
|
||||
INTEL_BROKEN_INITIAL_NCMD,
|
||||
INTEL_BROKEN_SHUTDOWN_LED,
|
||||
INTEL_ROM_LEGACY,
|
||||
INTEL_ROM_LEGACY_NO_WBS_SUPPORT,
|
||||
|
||||
__INTEL_NUM_FLAGS,
|
||||
};
|
||||
|
@ -1,4 +1,4 @@
|
||||
/**
|
||||
/*
|
||||
* Marvell Bluetooth driver: debugfs related functions
|
||||
*
|
||||
* Copyright (C) 2009, Marvell International Ltd.
|
||||
|
@ -1,4 +1,4 @@
|
||||
/**
|
||||
/*
|
||||
* Marvell BT-over-SDIO driver: SDIO interface related functions.
|
||||
*
|
||||
* Copyright (C) 2009, Marvell International Ltd.
|
||||
|
@ -285,6 +285,7 @@ MODULE_AUTHOR("Mark Chen <mark-yw.chen@mediatek.com>");
|
||||
MODULE_DESCRIPTION("Bluetooth support for MediaTek devices ver " VERSION);
|
||||
MODULE_VERSION(VERSION);
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_FIRMWARE(FIRMWARE_MT7622);
|
||||
MODULE_FIRMWARE(FIRMWARE_MT7663);
|
||||
MODULE_FIRMWARE(FIRMWARE_MT7668);
|
||||
MODULE_FIRMWARE(FIRMWARE_MT7961);
|
||||
|
@ -1,14 +1,26 @@
|
||||
/* SPDX-License-Identifier: ISC */
|
||||
/* Copyright (C) 2021 MediaTek Inc. */
|
||||
|
||||
#define FIRMWARE_MT7622 "mediatek/mt7622pr2h.bin"
|
||||
#define FIRMWARE_MT7663 "mediatek/mt7663pr2h.bin"
|
||||
#define FIRMWARE_MT7668 "mediatek/mt7668pr2h.bin"
|
||||
#define FIRMWARE_MT7961 "mediatek/BT_RAM_CODE_MT7961_1_2_hdr.bin"
|
||||
|
||||
#define HCI_EV_WMT 0xe4
|
||||
#define HCI_WMT_MAX_EVENT_SIZE 64
|
||||
|
||||
#define BTMTK_WMT_REG_WRITE 0x1
|
||||
#define BTMTK_WMT_REG_READ 0x2
|
||||
|
||||
#define MT7921_BTSYS_RST 0x70002610
|
||||
#define MT7921_BTSYS_RST_WITH_GPIO BIT(7)
|
||||
|
||||
#define MT7921_PINMUX_0 0x70005050
|
||||
#define MT7921_PINMUX_1 0x70005054
|
||||
|
||||
#define MT7921_DLSTATUS 0x7c053c10
|
||||
#define BT_DL_STATE BIT(1)
|
||||
|
||||
enum {
|
||||
BTMTK_WMT_PATCH_DWNLD = 0x1,
|
||||
BTMTK_WMT_TEST = 0x2,
|
||||
@ -68,6 +80,37 @@ struct btmtk_tci_sleep {
|
||||
u8 time_compensation;
|
||||
} __packed;
|
||||
|
||||
struct btmtk_wakeon {
|
||||
u8 mode;
|
||||
u8 gpo;
|
||||
u8 active_high;
|
||||
__le16 enable_delay;
|
||||
__le16 wakeup_delay;
|
||||
} __packed;
|
||||
|
||||
struct btmtk_sco {
|
||||
u8 clock_config;
|
||||
u8 transmit_format_config;
|
||||
u8 channel_format_config;
|
||||
u8 channel_select_config;
|
||||
} __packed;
|
||||
|
||||
struct reg_read_cmd {
|
||||
u8 type;
|
||||
u8 rsv;
|
||||
u8 num;
|
||||
__le32 addr;
|
||||
} __packed;
|
||||
|
||||
struct reg_write_cmd {
|
||||
u8 type;
|
||||
u8 rsv;
|
||||
u8 num;
|
||||
__le32 addr;
|
||||
__le32 data;
|
||||
__le32 mask;
|
||||
} __packed;
|
||||
|
||||
struct btmtk_hci_wmt_params {
|
||||
u8 op;
|
||||
u8 flag;
|
||||
|
@ -12,10 +12,12 @@
|
||||
|
||||
#include <asm/unaligned.h>
|
||||
#include <linux/atomic.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/iopoll.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/skbuff.h>
|
||||
|
||||
@ -31,28 +33,32 @@
|
||||
|
||||
#define VERSION "0.1"
|
||||
|
||||
#define MTKBTSDIO_AUTOSUSPEND_DELAY 8000
|
||||
#define MTKBTSDIO_AUTOSUSPEND_DELAY 1000
|
||||
|
||||
static bool enable_autosuspend;
|
||||
static bool enable_autosuspend = true;
|
||||
|
||||
struct btmtksdio_data {
|
||||
const char *fwname;
|
||||
u16 chipid;
|
||||
bool lp_mbox_supported;
|
||||
};
|
||||
|
||||
static const struct btmtksdio_data mt7663_data = {
|
||||
.fwname = FIRMWARE_MT7663,
|
||||
.chipid = 0x7663,
|
||||
.lp_mbox_supported = false,
|
||||
};
|
||||
|
||||
static const struct btmtksdio_data mt7668_data = {
|
||||
.fwname = FIRMWARE_MT7668,
|
||||
.chipid = 0x7668,
|
||||
.lp_mbox_supported = false,
|
||||
};
|
||||
|
||||
static const struct btmtksdio_data mt7921_data = {
|
||||
.fwname = FIRMWARE_MT7961,
|
||||
.chipid = 0x7921,
|
||||
.lp_mbox_supported = true,
|
||||
};
|
||||
|
||||
static const struct sdio_device_id btmtksdio_table[] = {
|
||||
@ -79,6 +85,7 @@ MODULE_DEVICE_TABLE(sdio, btmtksdio_table);
|
||||
|
||||
#define MTK_REG_CHCR 0xc
|
||||
#define C_INT_CLR_CTRL BIT(1)
|
||||
#define BT_RST_DONE BIT(8)
|
||||
|
||||
/* CHISR have the same bits field definition with CHIER */
|
||||
#define MTK_REG_CHISR 0x10
|
||||
@ -87,8 +94,17 @@ MODULE_DEVICE_TABLE(sdio, btmtksdio_table);
|
||||
#define RX_DONE_INT BIT(1)
|
||||
#define TX_EMPTY BIT(2)
|
||||
#define TX_FIFO_OVERFLOW BIT(8)
|
||||
#define FW_MAILBOX_INT BIT(15)
|
||||
#define INT_MASK GENMASK(15, 0)
|
||||
#define RX_PKT_LEN GENMASK(31, 16)
|
||||
|
||||
#define MTK_REG_CSICR 0xc0
|
||||
#define CSICR_CLR_MBOX_ACK BIT(0)
|
||||
#define MTK_REG_PH2DSM0R 0xc4
|
||||
#define PH2DSM0R_DRIVER_OWN BIT(0)
|
||||
#define MTK_REG_PD2HRM0R 0xdc
|
||||
#define PD2HRM0R_DRV_OWN BIT(0)
|
||||
|
||||
#define MTK_REG_CTDR 0x18
|
||||
|
||||
#define MTK_REG_CRDR 0x1c
|
||||
@ -100,6 +116,8 @@ MODULE_DEVICE_TABLE(sdio, btmtksdio_table);
|
||||
#define BTMTKSDIO_TX_WAIT_VND_EVT 1
|
||||
#define BTMTKSDIO_HW_TX_READY 2
|
||||
#define BTMTKSDIO_FUNC_ENABLED 3
|
||||
#define BTMTKSDIO_PATCH_ENABLED 4
|
||||
#define BTMTKSDIO_HW_RESET_ACTIVE 5
|
||||
|
||||
struct mtkbtsdio_hdr {
|
||||
__le16 len;
|
||||
@ -119,6 +137,8 @@ struct btmtksdio_dev {
|
||||
struct sk_buff *evt_skb;
|
||||
|
||||
const struct btmtksdio_data *data;
|
||||
|
||||
struct gpio_desc *reset;
|
||||
};
|
||||
|
||||
static int mtk_hci_wmt_sync(struct hci_dev *hdev,
|
||||
@ -278,19 +298,89 @@ static u32 btmtksdio_drv_own_query(struct btmtksdio_dev *bdev)
|
||||
return sdio_readl(bdev->func, MTK_REG_CHLPCR, NULL);
|
||||
}
|
||||
|
||||
static u32 btmtksdio_drv_own_query_79xx(struct btmtksdio_dev *bdev)
|
||||
{
|
||||
return sdio_readl(bdev->func, MTK_REG_PD2HRM0R, NULL);
|
||||
}
|
||||
|
||||
static u32 btmtksdio_chcr_query(struct btmtksdio_dev *bdev)
|
||||
{
|
||||
return sdio_readl(bdev->func, MTK_REG_CHCR, NULL);
|
||||
}
|
||||
|
||||
static int btmtksdio_fw_pmctrl(struct btmtksdio_dev *bdev)
|
||||
{
|
||||
u32 status;
|
||||
int err;
|
||||
|
||||
sdio_claim_host(bdev->func);
|
||||
|
||||
if (bdev->data->lp_mbox_supported &&
|
||||
test_bit(BTMTKSDIO_PATCH_ENABLED, &bdev->tx_state)) {
|
||||
sdio_writel(bdev->func, CSICR_CLR_MBOX_ACK, MTK_REG_CSICR,
|
||||
&err);
|
||||
err = readx_poll_timeout(btmtksdio_drv_own_query_79xx, bdev,
|
||||
status, !(status & PD2HRM0R_DRV_OWN),
|
||||
2000, 1000000);
|
||||
if (err < 0) {
|
||||
bt_dev_err(bdev->hdev, "mailbox ACK not cleared");
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
/* Return ownership to the device */
|
||||
sdio_writel(bdev->func, C_FW_OWN_REQ_SET, MTK_REG_CHLPCR, &err);
|
||||
if (err < 0)
|
||||
goto out;
|
||||
|
||||
err = readx_poll_timeout(btmtksdio_drv_own_query, bdev, status,
|
||||
!(status & C_COM_DRV_OWN), 2000, 1000000);
|
||||
|
||||
out:
|
||||
sdio_release_host(bdev->func);
|
||||
|
||||
if (err < 0)
|
||||
bt_dev_err(bdev->hdev, "Cannot return ownership to device");
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int btmtksdio_drv_pmctrl(struct btmtksdio_dev *bdev)
|
||||
{
|
||||
u32 status;
|
||||
int err;
|
||||
|
||||
sdio_claim_host(bdev->func);
|
||||
|
||||
/* Get ownership from the device */
|
||||
sdio_writel(bdev->func, C_FW_OWN_REQ_CLR, MTK_REG_CHLPCR, &err);
|
||||
if (err < 0)
|
||||
goto out;
|
||||
|
||||
err = readx_poll_timeout(btmtksdio_drv_own_query, bdev, status,
|
||||
status & C_COM_DRV_OWN, 2000, 1000000);
|
||||
|
||||
if (!err && bdev->data->lp_mbox_supported &&
|
||||
test_bit(BTMTKSDIO_PATCH_ENABLED, &bdev->tx_state))
|
||||
err = readx_poll_timeout(btmtksdio_drv_own_query_79xx, bdev,
|
||||
status, status & PD2HRM0R_DRV_OWN,
|
||||
2000, 1000000);
|
||||
|
||||
out:
|
||||
sdio_release_host(bdev->func);
|
||||
|
||||
if (err < 0)
|
||||
bt_dev_err(bdev->hdev, "Cannot get ownership from device");
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int btmtksdio_recv_event(struct hci_dev *hdev, struct sk_buff *skb)
|
||||
{
|
||||
struct btmtksdio_dev *bdev = hci_get_drvdata(hdev);
|
||||
struct hci_event_hdr *hdr = (void *)skb->data;
|
||||
int err;
|
||||
|
||||
/* Fix up the vendor event id with 0xff for vendor specific instead
|
||||
* of 0xe4 so that event send via monitoring socket can be parsed
|
||||
* properly.
|
||||
*/
|
||||
if (hdr->evt == 0xe4)
|
||||
hdr->evt = HCI_EV_VENDOR;
|
||||
|
||||
/* When someone waits for the WMT event, the skb is being cloned
|
||||
* and being processed the events from there then.
|
||||
*/
|
||||
@ -306,7 +396,7 @@ static int btmtksdio_recv_event(struct hci_dev *hdev, struct sk_buff *skb)
|
||||
if (err < 0)
|
||||
goto err_free_skb;
|
||||
|
||||
if (hdr->evt == HCI_EV_VENDOR) {
|
||||
if (hdr->evt == HCI_EV_WMT) {
|
||||
if (test_and_clear_bit(BTMTKSDIO_TX_WAIT_VND_EVT,
|
||||
&bdev->tx_state)) {
|
||||
/* Barrier to sync with other CPUs */
|
||||
@ -480,6 +570,13 @@ static void btmtksdio_txrx_work(struct work_struct *work)
|
||||
* FIFO.
|
||||
*/
|
||||
sdio_writel(bdev->func, int_status, MTK_REG_CHISR, NULL);
|
||||
int_status &= INT_MASK;
|
||||
|
||||
if ((int_status & FW_MAILBOX_INT) &&
|
||||
bdev->data->chipid == 0x7921) {
|
||||
sdio_writel(bdev->func, PH2DSM0R_DRIVER_OWN,
|
||||
MTK_REG_PH2DSM0R, 0);
|
||||
}
|
||||
|
||||
if (int_status & FW_OWN_BACK_INT)
|
||||
bt_dev_dbg(bdev->hdev, "Get fw own back");
|
||||
@ -531,7 +628,7 @@ static void btmtksdio_interrupt(struct sdio_func *func)
|
||||
static int btmtksdio_open(struct hci_dev *hdev)
|
||||
{
|
||||
struct btmtksdio_dev *bdev = hci_get_drvdata(hdev);
|
||||
u32 status, val;
|
||||
u32 val;
|
||||
int err;
|
||||
|
||||
sdio_claim_host(bdev->func);
|
||||
@ -542,18 +639,10 @@ static int btmtksdio_open(struct hci_dev *hdev)
|
||||
|
||||
set_bit(BTMTKSDIO_FUNC_ENABLED, &bdev->tx_state);
|
||||
|
||||
/* Get ownership from the device */
|
||||
sdio_writel(bdev->func, C_FW_OWN_REQ_CLR, MTK_REG_CHLPCR, &err);
|
||||
err = btmtksdio_drv_pmctrl(bdev);
|
||||
if (err < 0)
|
||||
goto err_disable_func;
|
||||
|
||||
err = readx_poll_timeout(btmtksdio_drv_own_query, bdev, status,
|
||||
status & C_COM_DRV_OWN, 2000, 1000000);
|
||||
if (err < 0) {
|
||||
bt_dev_err(bdev->hdev, "Cannot get ownership from device");
|
||||
goto err_disable_func;
|
||||
}
|
||||
|
||||
/* Disable interrupt & mask out all interrupt sources */
|
||||
sdio_writel(bdev->func, C_INT_EN_CLR, MTK_REG_CHLPCR, &err);
|
||||
if (err < 0)
|
||||
@ -623,8 +712,6 @@ static int btmtksdio_open(struct hci_dev *hdev)
|
||||
static int btmtksdio_close(struct hci_dev *hdev)
|
||||
{
|
||||
struct btmtksdio_dev *bdev = hci_get_drvdata(hdev);
|
||||
u32 status;
|
||||
int err;
|
||||
|
||||
sdio_claim_host(bdev->func);
|
||||
|
||||
@ -635,13 +722,7 @@ static int btmtksdio_close(struct hci_dev *hdev)
|
||||
|
||||
cancel_work_sync(&bdev->txrx_work);
|
||||
|
||||
/* Return ownership to the device */
|
||||
sdio_writel(bdev->func, C_FW_OWN_REQ_SET, MTK_REG_CHLPCR, NULL);
|
||||
|
||||
err = readx_poll_timeout(btmtksdio_drv_own_query, bdev, status,
|
||||
!(status & C_COM_DRV_OWN), 2000, 1000000);
|
||||
if (err < 0)
|
||||
bt_dev_err(bdev->hdev, "Cannot return ownership to device");
|
||||
btmtksdio_fw_pmctrl(bdev);
|
||||
|
||||
clear_bit(BTMTKSDIO_FUNC_ENABLED, &bdev->tx_state);
|
||||
sdio_disable_func(bdev->func);
|
||||
@ -686,6 +767,7 @@ static int btmtksdio_func_query(struct hci_dev *hdev)
|
||||
|
||||
static int mt76xx_setup(struct hci_dev *hdev, const char *fwname)
|
||||
{
|
||||
struct btmtksdio_dev *bdev = hci_get_drvdata(hdev);
|
||||
struct btmtk_hci_wmt_params wmt_params;
|
||||
struct btmtk_tci_sleep tci_sleep;
|
||||
struct sk_buff *skb;
|
||||
@ -746,6 +828,8 @@ static int mt76xx_setup(struct hci_dev *hdev, const char *fwname)
|
||||
return err;
|
||||
}
|
||||
|
||||
set_bit(BTMTKSDIO_PATCH_ENABLED, &bdev->tx_state);
|
||||
|
||||
ignore_func_on:
|
||||
/* Apply the low power environment setup */
|
||||
tci_sleep.mode = 0x5;
|
||||
@ -768,6 +852,7 @@ static int mt76xx_setup(struct hci_dev *hdev, const char *fwname)
|
||||
|
||||
static int mt79xx_setup(struct hci_dev *hdev, const char *fwname)
|
||||
{
|
||||
struct btmtksdio_dev *bdev = hci_get_drvdata(hdev);
|
||||
struct btmtk_hci_wmt_params wmt_params;
|
||||
u8 param = 0x1;
|
||||
int err;
|
||||
@ -793,19 +878,15 @@ static int mt79xx_setup(struct hci_dev *hdev, const char *fwname)
|
||||
|
||||
hci_set_msft_opcode(hdev, 0xFD30);
|
||||
hci_set_aosp_capable(hdev);
|
||||
set_bit(BTMTKSDIO_PATCH_ENABLED, &bdev->tx_state);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int btsdio_mtk_reg_read(struct hci_dev *hdev, u32 reg, u32 *val)
|
||||
static int btmtksdio_mtk_reg_read(struct hci_dev *hdev, u32 reg, u32 *val)
|
||||
{
|
||||
struct btmtk_hci_wmt_params wmt_params;
|
||||
struct reg_read_cmd {
|
||||
u8 type;
|
||||
u8 rsv;
|
||||
u8 num;
|
||||
__le32 addr;
|
||||
} __packed reg_read = {
|
||||
struct reg_read_cmd reg_read = {
|
||||
.type = 1,
|
||||
.num = 1,
|
||||
};
|
||||
@ -821,7 +902,7 @@ static int btsdio_mtk_reg_read(struct hci_dev *hdev, u32 reg, u32 *val)
|
||||
|
||||
err = mtk_hci_wmt_sync(hdev, &wmt_params);
|
||||
if (err < 0) {
|
||||
bt_dev_err(hdev, "Failed to read reg(%d)", err);
|
||||
bt_dev_err(hdev, "Failed to read reg (%d)", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
@ -830,6 +911,151 @@ static int btsdio_mtk_reg_read(struct hci_dev *hdev, u32 reg, u32 *val)
|
||||
return err;
|
||||
}
|
||||
|
||||
static int btmtksdio_mtk_reg_write(struct hci_dev *hdev, u32 reg, u32 val, u32 mask)
|
||||
{
|
||||
struct btmtk_hci_wmt_params wmt_params;
|
||||
const struct reg_write_cmd reg_write = {
|
||||
.type = 1,
|
||||
.num = 1,
|
||||
.addr = cpu_to_le32(reg),
|
||||
.data = cpu_to_le32(val),
|
||||
.mask = cpu_to_le32(mask),
|
||||
};
|
||||
int err, status;
|
||||
|
||||
wmt_params.op = BTMTK_WMT_REGISTER;
|
||||
wmt_params.flag = BTMTK_WMT_REG_WRITE;
|
||||
wmt_params.dlen = sizeof(reg_write);
|
||||
wmt_params.data = ®_write;
|
||||
wmt_params.status = &status;
|
||||
|
||||
err = mtk_hci_wmt_sync(hdev, &wmt_params);
|
||||
if (err < 0)
|
||||
bt_dev_err(hdev, "Failed to write reg (%d)", err);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int btmtksdio_get_data_path_id(struct hci_dev *hdev, __u8 *data_path_id)
|
||||
{
|
||||
/* uses 1 as data path id for all the usecases */
|
||||
*data_path_id = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int btmtksdio_get_codec_config_data(struct hci_dev *hdev,
|
||||
__u8 link, struct bt_codec *codec,
|
||||
__u8 *ven_len, __u8 **ven_data)
|
||||
{
|
||||
int err = 0;
|
||||
|
||||
if (!ven_data || !ven_len)
|
||||
return -EINVAL;
|
||||
|
||||
*ven_len = 0;
|
||||
*ven_data = NULL;
|
||||
|
||||
if (link != ESCO_LINK) {
|
||||
bt_dev_err(hdev, "Invalid link type(%u)", link);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
*ven_data = kmalloc(sizeof(__u8), GFP_KERNEL);
|
||||
if (!ven_data) {
|
||||
err = -ENOMEM;
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* supports only CVSD and mSBC offload codecs */
|
||||
switch (codec->id) {
|
||||
case 0x02:
|
||||
**ven_data = 0x00;
|
||||
break;
|
||||
case 0x05:
|
||||
**ven_data = 0x01;
|
||||
break;
|
||||
default:
|
||||
err = -EINVAL;
|
||||
bt_dev_err(hdev, "Invalid codec id(%u)", codec->id);
|
||||
goto error;
|
||||
}
|
||||
/* codec and its capabilities are pre-defined to ids
|
||||
* preset id = 0x00 represents CVSD codec with sampling rate 8K
|
||||
* preset id = 0x01 represents mSBC codec with sampling rate 16K
|
||||
*/
|
||||
*ven_len = sizeof(__u8);
|
||||
return err;
|
||||
|
||||
error:
|
||||
kfree(*ven_data);
|
||||
*ven_data = NULL;
|
||||
return err;
|
||||
}
|
||||
|
||||
static int btmtksdio_sco_setting(struct hci_dev *hdev)
|
||||
{
|
||||
const struct btmtk_sco sco_setting = {
|
||||
.clock_config = 0x49,
|
||||
.channel_format_config = 0x80,
|
||||
};
|
||||
struct sk_buff *skb;
|
||||
u32 val;
|
||||
int err;
|
||||
|
||||
/* Enable SCO over I2S/PCM for MediaTek chipset */
|
||||
skb = __hci_cmd_sync(hdev, 0xfc72, sizeof(sco_setting),
|
||||
&sco_setting, HCI_CMD_TIMEOUT);
|
||||
if (IS_ERR(skb))
|
||||
return PTR_ERR(skb);
|
||||
|
||||
kfree_skb(skb);
|
||||
|
||||
err = btmtksdio_mtk_reg_read(hdev, MT7921_PINMUX_0, &val);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
val |= 0x11000000;
|
||||
err = btmtksdio_mtk_reg_write(hdev, MT7921_PINMUX_0, val, ~0);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
err = btmtksdio_mtk_reg_read(hdev, MT7921_PINMUX_1, &val);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
val |= 0x00000101;
|
||||
err = btmtksdio_mtk_reg_write(hdev, MT7921_PINMUX_1, val, ~0);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
hdev->get_data_path_id = btmtksdio_get_data_path_id;
|
||||
hdev->get_codec_config_data = btmtksdio_get_codec_config_data;
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int btmtksdio_reset_setting(struct hci_dev *hdev)
|
||||
{
|
||||
int err;
|
||||
u32 val;
|
||||
|
||||
err = btmtksdio_mtk_reg_read(hdev, MT7921_PINMUX_1, &val);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
val |= 0x20; /* set the pin (bit field 11:8) work as GPIO mode */
|
||||
err = btmtksdio_mtk_reg_write(hdev, MT7921_PINMUX_1, val, ~0);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
err = btmtksdio_mtk_reg_read(hdev, MT7921_BTSYS_RST, &val);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
val |= MT7921_BTSYS_RST_WITH_GPIO;
|
||||
return btmtksdio_mtk_reg_write(hdev, MT7921_BTSYS_RST, val, ~0);
|
||||
}
|
||||
|
||||
static int btmtksdio_setup(struct hci_dev *hdev)
|
||||
{
|
||||
struct btmtksdio_dev *bdev = hci_get_drvdata(hdev);
|
||||
@ -837,20 +1063,39 @@ static int btmtksdio_setup(struct hci_dev *hdev)
|
||||
unsigned long long duration;
|
||||
char fwname[64];
|
||||
int err, dev_id;
|
||||
u32 fw_version = 0;
|
||||
u32 fw_version = 0, val;
|
||||
|
||||
calltime = ktime_get();
|
||||
set_bit(BTMTKSDIO_HW_TX_READY, &bdev->tx_state);
|
||||
|
||||
switch (bdev->data->chipid) {
|
||||
case 0x7921:
|
||||
err = btsdio_mtk_reg_read(hdev, 0x70010200, &dev_id);
|
||||
if (test_bit(BTMTKSDIO_HW_RESET_ACTIVE, &bdev->tx_state)) {
|
||||
err = btmtksdio_mtk_reg_read(hdev, MT7921_DLSTATUS,
|
||||
&val);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
val &= ~BT_DL_STATE;
|
||||
err = btmtksdio_mtk_reg_write(hdev, MT7921_DLSTATUS,
|
||||
val, ~0);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
btmtksdio_fw_pmctrl(bdev);
|
||||
msleep(20);
|
||||
btmtksdio_drv_pmctrl(bdev);
|
||||
|
||||
clear_bit(BTMTKSDIO_HW_RESET_ACTIVE, &bdev->tx_state);
|
||||
}
|
||||
|
||||
err = btmtksdio_mtk_reg_read(hdev, 0x70010200, &dev_id);
|
||||
if (err < 0) {
|
||||
bt_dev_err(hdev, "Failed to get device id (%d)", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
err = btsdio_mtk_reg_read(hdev, 0x80021004, &fw_version);
|
||||
err = btmtksdio_mtk_reg_read(hdev, 0x80021004, &fw_version);
|
||||
if (err < 0) {
|
||||
bt_dev_err(hdev, "Failed to get fw version (%d)", err);
|
||||
return err;
|
||||
@ -862,6 +1107,38 @@ static int btmtksdio_setup(struct hci_dev *hdev)
|
||||
err = mt79xx_setup(hdev, fwname);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
err = btmtksdio_fw_pmctrl(bdev);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
err = btmtksdio_drv_pmctrl(bdev);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
/* Enable SCO over I2S/PCM */
|
||||
err = btmtksdio_sco_setting(hdev);
|
||||
if (err < 0) {
|
||||
bt_dev_err(hdev, "Failed to enable SCO setting (%d)", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Enable WBS with mSBC codec */
|
||||
set_bit(HCI_QUIRK_WIDEBAND_SPEECH_SUPPORTED, &hdev->quirks);
|
||||
|
||||
/* Enable GPIO reset mechanism */
|
||||
if (bdev->reset) {
|
||||
err = btmtksdio_reset_setting(hdev);
|
||||
if (err < 0) {
|
||||
bt_dev_err(hdev, "Failed to enable Reset setting (%d)", err);
|
||||
devm_gpiod_put(bdev->dev, bdev->reset);
|
||||
bdev->reset = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Valid LE States quirk for MediaTek 7921 */
|
||||
set_bit(HCI_QUIRK_VALID_LE_STATES, &hdev->quirks);
|
||||
|
||||
break;
|
||||
case 0x7663:
|
||||
case 0x7668:
|
||||
@ -958,6 +1235,73 @@ static int btmtksdio_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void btmtksdio_cmd_timeout(struct hci_dev *hdev)
|
||||
{
|
||||
struct btmtksdio_dev *bdev = hci_get_drvdata(hdev);
|
||||
u32 status;
|
||||
int err;
|
||||
|
||||
if (!bdev->reset || bdev->data->chipid != 0x7921)
|
||||
return;
|
||||
|
||||
pm_runtime_get_sync(bdev->dev);
|
||||
|
||||
if (test_and_set_bit(BTMTKSDIO_HW_RESET_ACTIVE, &bdev->tx_state))
|
||||
return;
|
||||
|
||||
sdio_claim_host(bdev->func);
|
||||
|
||||
sdio_writel(bdev->func, C_INT_EN_CLR, MTK_REG_CHLPCR, NULL);
|
||||
skb_queue_purge(&bdev->txq);
|
||||
cancel_work_sync(&bdev->txrx_work);
|
||||
|
||||
gpiod_set_value_cansleep(bdev->reset, 1);
|
||||
msleep(100);
|
||||
gpiod_set_value_cansleep(bdev->reset, 0);
|
||||
|
||||
err = readx_poll_timeout(btmtksdio_chcr_query, bdev, status,
|
||||
status & BT_RST_DONE, 100000, 2000000);
|
||||
if (err < 0) {
|
||||
bt_dev_err(hdev, "Failed to reset (%d)", err);
|
||||
goto err;
|
||||
}
|
||||
|
||||
clear_bit(BTMTKSDIO_PATCH_ENABLED, &bdev->tx_state);
|
||||
err:
|
||||
sdio_release_host(bdev->func);
|
||||
|
||||
pm_runtime_put_noidle(bdev->dev);
|
||||
pm_runtime_disable(bdev->dev);
|
||||
|
||||
hci_reset_dev(hdev);
|
||||
}
|
||||
|
||||
static bool btmtksdio_sdio_wakeup(struct hci_dev *hdev)
|
||||
{
|
||||
struct btmtksdio_dev *bdev = hci_get_drvdata(hdev);
|
||||
bool may_wakeup = device_may_wakeup(bdev->dev);
|
||||
const struct btmtk_wakeon bt_awake = {
|
||||
.mode = 0x1,
|
||||
.gpo = 0,
|
||||
.active_high = 0x1,
|
||||
.enable_delay = cpu_to_le16(0xc80),
|
||||
.wakeup_delay = cpu_to_le16(0x20),
|
||||
};
|
||||
|
||||
if (may_wakeup && bdev->data->chipid == 0x7921) {
|
||||
struct sk_buff *skb;
|
||||
|
||||
skb = __hci_cmd_sync(hdev, 0xfc27, sizeof(bt_awake),
|
||||
&bt_awake, HCI_CMD_TIMEOUT);
|
||||
if (IS_ERR(skb))
|
||||
may_wakeup = false;
|
||||
else
|
||||
kfree_skb(skb);
|
||||
}
|
||||
|
||||
return may_wakeup;
|
||||
}
|
||||
|
||||
static int btmtksdio_probe(struct sdio_func *func,
|
||||
const struct sdio_device_id *id)
|
||||
{
|
||||
@ -993,10 +1337,12 @@ static int btmtksdio_probe(struct sdio_func *func,
|
||||
|
||||
hdev->open = btmtksdio_open;
|
||||
hdev->close = btmtksdio_close;
|
||||
hdev->cmd_timeout = btmtksdio_cmd_timeout;
|
||||
hdev->flush = btmtksdio_flush;
|
||||
hdev->setup = btmtksdio_setup;
|
||||
hdev->shutdown = btmtksdio_shutdown;
|
||||
hdev->send = btmtksdio_send_frame;
|
||||
hdev->wakeup = btmtksdio_sdio_wakeup;
|
||||
hdev->set_bdaddr = btmtk_set_bdaddr;
|
||||
|
||||
SET_HCIDEV_DEV(hdev, &func->dev);
|
||||
@ -1004,6 +1350,8 @@ static int btmtksdio_probe(struct sdio_func *func,
|
||||
hdev->manufacturer = 70;
|
||||
set_bit(HCI_QUIRK_NON_PERSISTENT_SETUP, &hdev->quirks);
|
||||
|
||||
sdio_set_drvdata(func, bdev);
|
||||
|
||||
err = hci_register_dev(hdev);
|
||||
if (err < 0) {
|
||||
dev_err(&func->dev, "Can't register HCI device\n");
|
||||
@ -1011,8 +1359,6 @@ static int btmtksdio_probe(struct sdio_func *func,
|
||||
return err;
|
||||
}
|
||||
|
||||
sdio_set_drvdata(func, bdev);
|
||||
|
||||
/* pm_runtime_enable would be done after the firmware is being
|
||||
* downloaded because the core layer probably already enables
|
||||
* runtime PM for this func such as the case host->caps &
|
||||
@ -1032,7 +1378,18 @@ static int btmtksdio_probe(struct sdio_func *func,
|
||||
*/
|
||||
pm_runtime_put_noidle(bdev->dev);
|
||||
|
||||
return 0;
|
||||
err = device_init_wakeup(bdev->dev, true);
|
||||
if (err)
|
||||
bt_dev_err(hdev, "failed to initialize device wakeup");
|
||||
|
||||
bdev->dev->of_node = of_find_compatible_node(NULL, NULL,
|
||||
"mediatek,mt7921s-bluetooth");
|
||||
bdev->reset = devm_gpiod_get_optional(bdev->dev, "reset",
|
||||
GPIOD_OUT_LOW);
|
||||
if (IS_ERR(bdev->reset))
|
||||
err = PTR_ERR(bdev->reset);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static void btmtksdio_remove(struct sdio_func *func)
|
||||
@ -1058,7 +1415,6 @@ static int btmtksdio_runtime_suspend(struct device *dev)
|
||||
{
|
||||
struct sdio_func *func = dev_to_sdio_func(dev);
|
||||
struct btmtksdio_dev *bdev;
|
||||
u32 status;
|
||||
int err;
|
||||
|
||||
bdev = sdio_get_drvdata(func);
|
||||
@ -1070,18 +1426,9 @@ static int btmtksdio_runtime_suspend(struct device *dev)
|
||||
|
||||
sdio_set_host_pm_flags(func, MMC_PM_KEEP_POWER);
|
||||
|
||||
sdio_claim_host(bdev->func);
|
||||
err = btmtksdio_fw_pmctrl(bdev);
|
||||
|
||||
sdio_writel(bdev->func, C_FW_OWN_REQ_SET, MTK_REG_CHLPCR, &err);
|
||||
if (err < 0)
|
||||
goto out;
|
||||
|
||||
err = readx_poll_timeout(btmtksdio_drv_own_query, bdev, status,
|
||||
!(status & C_COM_DRV_OWN), 2000, 1000000);
|
||||
out:
|
||||
bt_dev_info(bdev->hdev, "status (%d) return ownership to device", err);
|
||||
|
||||
sdio_release_host(bdev->func);
|
||||
bt_dev_dbg(bdev->hdev, "status (%d) return ownership to device", err);
|
||||
|
||||
return err;
|
||||
}
|
||||
@ -1090,7 +1437,6 @@ static int btmtksdio_runtime_resume(struct device *dev)
|
||||
{
|
||||
struct sdio_func *func = dev_to_sdio_func(dev);
|
||||
struct btmtksdio_dev *bdev;
|
||||
u32 status;
|
||||
int err;
|
||||
|
||||
bdev = sdio_get_drvdata(func);
|
||||
@ -1100,18 +1446,9 @@ static int btmtksdio_runtime_resume(struct device *dev)
|
||||
if (!test_bit(BTMTKSDIO_FUNC_ENABLED, &bdev->tx_state))
|
||||
return 0;
|
||||
|
||||
sdio_claim_host(bdev->func);
|
||||
err = btmtksdio_drv_pmctrl(bdev);
|
||||
|
||||
sdio_writel(bdev->func, C_FW_OWN_REQ_CLR, MTK_REG_CHLPCR, &err);
|
||||
if (err < 0)
|
||||
goto out;
|
||||
|
||||
err = readx_poll_timeout(btmtksdio_drv_own_query, bdev, status,
|
||||
status & C_COM_DRV_OWN, 2000, 1000000);
|
||||
out:
|
||||
bt_dev_info(bdev->hdev, "status (%d) get ownership from device", err);
|
||||
|
||||
sdio_release_host(bdev->func);
|
||||
bt_dev_dbg(bdev->hdev, "status (%d) get ownership from device", err);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
@ -28,13 +28,10 @@
|
||||
#include <net/bluetooth/hci_core.h>
|
||||
|
||||
#include "h4_recv.h"
|
||||
#include "btmtk.h"
|
||||
|
||||
#define VERSION "0.2"
|
||||
|
||||
#define FIRMWARE_MT7622 "mediatek/mt7622pr2h.bin"
|
||||
#define FIRMWARE_MT7663 "mediatek/mt7663pr2h.bin"
|
||||
#define FIRMWARE_MT7668 "mediatek/mt7668pr2h.bin"
|
||||
|
||||
#define MTK_STP_TLR_SIZE 2
|
||||
|
||||
#define BTMTKUART_TX_STATE_ACTIVE 1
|
||||
@ -44,25 +41,6 @@
|
||||
|
||||
#define BTMTKUART_FLAG_STANDALONE_HW BIT(0)
|
||||
|
||||
enum {
|
||||
MTK_WMT_PATCH_DWNLD = 0x1,
|
||||
MTK_WMT_TEST = 0x2,
|
||||
MTK_WMT_WAKEUP = 0x3,
|
||||
MTK_WMT_HIF = 0x4,
|
||||
MTK_WMT_FUNC_CTRL = 0x6,
|
||||
MTK_WMT_RST = 0x7,
|
||||
MTK_WMT_SEMAPHORE = 0x17,
|
||||
};
|
||||
|
||||
enum {
|
||||
BTMTK_WMT_INVALID,
|
||||
BTMTK_WMT_PATCH_UNDONE,
|
||||
BTMTK_WMT_PATCH_DONE,
|
||||
BTMTK_WMT_ON_UNDONE,
|
||||
BTMTK_WMT_ON_DONE,
|
||||
BTMTK_WMT_ON_PROGRESS,
|
||||
};
|
||||
|
||||
struct mtk_stp_hdr {
|
||||
u8 prefix;
|
||||
__be16 dlen;
|
||||
@ -74,44 +52,6 @@ struct btmtkuart_data {
|
||||
const char *fwname;
|
||||
};
|
||||
|
||||
struct mtk_wmt_hdr {
|
||||
u8 dir;
|
||||
u8 op;
|
||||
__le16 dlen;
|
||||
u8 flag;
|
||||
} __packed;
|
||||
|
||||
struct mtk_hci_wmt_cmd {
|
||||
struct mtk_wmt_hdr hdr;
|
||||
u8 data[256];
|
||||
} __packed;
|
||||
|
||||
struct btmtk_hci_wmt_evt {
|
||||
struct hci_event_hdr hhdr;
|
||||
struct mtk_wmt_hdr whdr;
|
||||
} __packed;
|
||||
|
||||
struct btmtk_hci_wmt_evt_funcc {
|
||||
struct btmtk_hci_wmt_evt hwhdr;
|
||||
__be16 status;
|
||||
} __packed;
|
||||
|
||||
struct btmtk_tci_sleep {
|
||||
u8 mode;
|
||||
__le16 duration;
|
||||
__le16 host_duration;
|
||||
u8 host_wakeup_pin;
|
||||
u8 time_compensation;
|
||||
} __packed;
|
||||
|
||||
struct btmtk_hci_wmt_params {
|
||||
u8 op;
|
||||
u8 flag;
|
||||
u16 dlen;
|
||||
const void *data;
|
||||
u32 *status;
|
||||
};
|
||||
|
||||
struct btmtkuart_dev {
|
||||
struct hci_dev *hdev;
|
||||
struct serdev_device *serdev;
|
||||
@ -153,29 +93,36 @@ static int mtk_hci_wmt_sync(struct hci_dev *hdev,
|
||||
struct btmtk_hci_wmt_evt_funcc *wmt_evt_funcc;
|
||||
u32 hlen, status = BTMTK_WMT_INVALID;
|
||||
struct btmtk_hci_wmt_evt *wmt_evt;
|
||||
struct mtk_hci_wmt_cmd wc;
|
||||
struct mtk_wmt_hdr *hdr;
|
||||
struct btmtk_hci_wmt_cmd *wc;
|
||||
struct btmtk_wmt_hdr *hdr;
|
||||
int err;
|
||||
|
||||
/* Send the WMT command and wait until the WMT event returns */
|
||||
hlen = sizeof(*hdr) + wmt_params->dlen;
|
||||
if (hlen > 255) {
|
||||
err = -EINVAL;
|
||||
goto err_free_skb;
|
||||
}
|
||||
|
||||
hdr = (struct mtk_wmt_hdr *)&wc;
|
||||
wc = kzalloc(hlen, GFP_KERNEL);
|
||||
if (!wc) {
|
||||
err = -ENOMEM;
|
||||
goto err_free_skb;
|
||||
}
|
||||
|
||||
hdr = &wc->hdr;
|
||||
hdr->dir = 1;
|
||||
hdr->op = wmt_params->op;
|
||||
hdr->dlen = cpu_to_le16(wmt_params->dlen + 1);
|
||||
hdr->flag = wmt_params->flag;
|
||||
memcpy(wc.data, wmt_params->data, wmt_params->dlen);
|
||||
memcpy(wc->data, wmt_params->data, wmt_params->dlen);
|
||||
|
||||
set_bit(BTMTKUART_TX_WAIT_VND_EVT, &bdev->tx_state);
|
||||
|
||||
err = __hci_cmd_send(hdev, 0xfc6f, hlen, &wc);
|
||||
err = __hci_cmd_send(hdev, 0xfc6f, hlen, wc);
|
||||
if (err < 0) {
|
||||
clear_bit(BTMTKUART_TX_WAIT_VND_EVT, &bdev->tx_state);
|
||||
goto err_free_skb;
|
||||
goto err_free_wc;
|
||||
}
|
||||
|
||||
/* The vendor specific WMT commands are all answered by a vendor
|
||||
@ -192,14 +139,14 @@ static int mtk_hci_wmt_sync(struct hci_dev *hdev,
|
||||
if (err == -EINTR) {
|
||||
bt_dev_err(hdev, "Execution of wmt command interrupted");
|
||||
clear_bit(BTMTKUART_TX_WAIT_VND_EVT, &bdev->tx_state);
|
||||
goto err_free_skb;
|
||||
goto err_free_wc;
|
||||
}
|
||||
|
||||
if (err) {
|
||||
bt_dev_err(hdev, "Execution of wmt command timed out");
|
||||
clear_bit(BTMTKUART_TX_WAIT_VND_EVT, &bdev->tx_state);
|
||||
err = -ETIMEDOUT;
|
||||
goto err_free_skb;
|
||||
goto err_free_wc;
|
||||
}
|
||||
|
||||
/* Parse and handle the return WMT event */
|
||||
@ -208,17 +155,17 @@ static int mtk_hci_wmt_sync(struct hci_dev *hdev,
|
||||
bt_dev_err(hdev, "Wrong op received %d expected %d",
|
||||
wmt_evt->whdr.op, hdr->op);
|
||||
err = -EIO;
|
||||
goto err_free_skb;
|
||||
goto err_free_wc;
|
||||
}
|
||||
|
||||
switch (wmt_evt->whdr.op) {
|
||||
case MTK_WMT_SEMAPHORE:
|
||||
case BTMTK_WMT_SEMAPHORE:
|
||||
if (wmt_evt->whdr.flag == 2)
|
||||
status = BTMTK_WMT_PATCH_UNDONE;
|
||||
else
|
||||
status = BTMTK_WMT_PATCH_DONE;
|
||||
break;
|
||||
case MTK_WMT_FUNC_CTRL:
|
||||
case BTMTK_WMT_FUNC_CTRL:
|
||||
wmt_evt_funcc = (struct btmtk_hci_wmt_evt_funcc *)wmt_evt;
|
||||
if (be16_to_cpu(wmt_evt_funcc->status) == 0x404)
|
||||
status = BTMTK_WMT_ON_DONE;
|
||||
@ -232,6 +179,8 @@ static int mtk_hci_wmt_sync(struct hci_dev *hdev,
|
||||
if (wmt_params->status)
|
||||
*wmt_params->status = status;
|
||||
|
||||
err_free_wc:
|
||||
kfree(wc);
|
||||
err_free_skb:
|
||||
kfree_skb(bdev->evt_skb);
|
||||
bdev->evt_skb = NULL;
|
||||
@ -239,95 +188,12 @@ static int mtk_hci_wmt_sync(struct hci_dev *hdev,
|
||||
return err;
|
||||
}
|
||||
|
||||
static int mtk_setup_firmware(struct hci_dev *hdev, const char *fwname)
|
||||
{
|
||||
struct btmtk_hci_wmt_params wmt_params;
|
||||
const struct firmware *fw;
|
||||
const u8 *fw_ptr;
|
||||
size_t fw_size;
|
||||
int err, dlen;
|
||||
u8 flag;
|
||||
|
||||
err = request_firmware(&fw, fwname, &hdev->dev);
|
||||
if (err < 0) {
|
||||
bt_dev_err(hdev, "Failed to load firmware file (%d)", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
fw_ptr = fw->data;
|
||||
fw_size = fw->size;
|
||||
|
||||
/* The size of patch header is 30 bytes, should be skip */
|
||||
if (fw_size < 30) {
|
||||
err = -EINVAL;
|
||||
goto free_fw;
|
||||
}
|
||||
|
||||
fw_size -= 30;
|
||||
fw_ptr += 30;
|
||||
flag = 1;
|
||||
|
||||
wmt_params.op = MTK_WMT_PATCH_DWNLD;
|
||||
wmt_params.status = NULL;
|
||||
|
||||
while (fw_size > 0) {
|
||||
dlen = min_t(int, 250, fw_size);
|
||||
|
||||
/* Tell device the position in sequence */
|
||||
if (fw_size - dlen <= 0)
|
||||
flag = 3;
|
||||
else if (fw_size < fw->size - 30)
|
||||
flag = 2;
|
||||
|
||||
wmt_params.flag = flag;
|
||||
wmt_params.dlen = dlen;
|
||||
wmt_params.data = fw_ptr;
|
||||
|
||||
err = mtk_hci_wmt_sync(hdev, &wmt_params);
|
||||
if (err < 0) {
|
||||
bt_dev_err(hdev, "Failed to send wmt patch dwnld (%d)",
|
||||
err);
|
||||
goto free_fw;
|
||||
}
|
||||
|
||||
fw_size -= dlen;
|
||||
fw_ptr += dlen;
|
||||
}
|
||||
|
||||
wmt_params.op = MTK_WMT_RST;
|
||||
wmt_params.flag = 4;
|
||||
wmt_params.dlen = 0;
|
||||
wmt_params.data = NULL;
|
||||
wmt_params.status = NULL;
|
||||
|
||||
/* Activate funciton the firmware providing to */
|
||||
err = mtk_hci_wmt_sync(hdev, &wmt_params);
|
||||
if (err < 0) {
|
||||
bt_dev_err(hdev, "Failed to send wmt rst (%d)", err);
|
||||
goto free_fw;
|
||||
}
|
||||
|
||||
/* Wait a few moments for firmware activation done */
|
||||
usleep_range(10000, 12000);
|
||||
|
||||
free_fw:
|
||||
release_firmware(fw);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int btmtkuart_recv_event(struct hci_dev *hdev, struct sk_buff *skb)
|
||||
{
|
||||
struct btmtkuart_dev *bdev = hci_get_drvdata(hdev);
|
||||
struct hci_event_hdr *hdr = (void *)skb->data;
|
||||
int err;
|
||||
|
||||
/* Fix up the vendor event id with 0xff for vendor specific instead
|
||||
* of 0xe4 so that event send via monitoring socket can be parsed
|
||||
* properly.
|
||||
*/
|
||||
if (hdr->evt == 0xe4)
|
||||
hdr->evt = HCI_EV_VENDOR;
|
||||
|
||||
/* When someone waits for the WMT event, the skb is being cloned
|
||||
* and being processed the events from there then.
|
||||
*/
|
||||
@ -343,7 +209,7 @@ static int btmtkuart_recv_event(struct hci_dev *hdev, struct sk_buff *skb)
|
||||
if (err < 0)
|
||||
goto err_free_skb;
|
||||
|
||||
if (hdr->evt == HCI_EV_VENDOR) {
|
||||
if (hdr->evt == HCI_EV_WMT) {
|
||||
if (test_and_clear_bit(BTMTKUART_TX_WAIT_VND_EVT,
|
||||
&bdev->tx_state)) {
|
||||
/* Barrier to sync with other CPUs */
|
||||
@ -645,7 +511,7 @@ static int btmtkuart_func_query(struct hci_dev *hdev)
|
||||
u8 param = 0;
|
||||
|
||||
/* Query whether the function is enabled */
|
||||
wmt_params.op = MTK_WMT_FUNC_CTRL;
|
||||
wmt_params.op = BTMTK_WMT_FUNC_CTRL;
|
||||
wmt_params.flag = 4;
|
||||
wmt_params.dlen = sizeof(param);
|
||||
wmt_params.data = ¶m;
|
||||
@ -672,7 +538,7 @@ static int btmtkuart_change_baudrate(struct hci_dev *hdev)
|
||||
* ready to change a new baudrate.
|
||||
*/
|
||||
baudrate = cpu_to_le32(bdev->desired_speed);
|
||||
wmt_params.op = MTK_WMT_HIF;
|
||||
wmt_params.op = BTMTK_WMT_HIF;
|
||||
wmt_params.flag = 1;
|
||||
wmt_params.dlen = 4;
|
||||
wmt_params.data = &baudrate;
|
||||
@ -706,7 +572,7 @@ static int btmtkuart_change_baudrate(struct hci_dev *hdev)
|
||||
usleep_range(20000, 22000);
|
||||
|
||||
/* Test the new baudrate */
|
||||
wmt_params.op = MTK_WMT_TEST;
|
||||
wmt_params.op = BTMTK_WMT_TEST;
|
||||
wmt_params.flag = 7;
|
||||
wmt_params.dlen = 0;
|
||||
wmt_params.data = NULL;
|
||||
@ -741,7 +607,7 @@ static int btmtkuart_setup(struct hci_dev *hdev)
|
||||
* do any setups.
|
||||
*/
|
||||
if (test_bit(BTMTKUART_REQUIRED_WAKEUP, &bdev->tx_state)) {
|
||||
wmt_params.op = MTK_WMT_WAKEUP;
|
||||
wmt_params.op = BTMTK_WMT_WAKEUP;
|
||||
wmt_params.flag = 3;
|
||||
wmt_params.dlen = 0;
|
||||
wmt_params.data = NULL;
|
||||
@ -760,7 +626,7 @@ static int btmtkuart_setup(struct hci_dev *hdev)
|
||||
btmtkuart_change_baudrate(hdev);
|
||||
|
||||
/* Query whether the firmware is already download */
|
||||
wmt_params.op = MTK_WMT_SEMAPHORE;
|
||||
wmt_params.op = BTMTK_WMT_SEMAPHORE;
|
||||
wmt_params.flag = 1;
|
||||
wmt_params.dlen = 0;
|
||||
wmt_params.data = NULL;
|
||||
@ -778,7 +644,7 @@ static int btmtkuart_setup(struct hci_dev *hdev)
|
||||
}
|
||||
|
||||
/* Setup a firmware which the device definitely requires */
|
||||
err = mtk_setup_firmware(hdev, bdev->data->fwname);
|
||||
err = btmtk_setup_firmware(hdev, bdev->data->fwname, mtk_hci_wmt_sync);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
@ -801,7 +667,7 @@ static int btmtkuart_setup(struct hci_dev *hdev)
|
||||
}
|
||||
|
||||
/* Enable Bluetooth protocol */
|
||||
wmt_params.op = MTK_WMT_FUNC_CTRL;
|
||||
wmt_params.op = BTMTK_WMT_FUNC_CTRL;
|
||||
wmt_params.flag = 0;
|
||||
wmt_params.dlen = sizeof(param);
|
||||
wmt_params.data = ¶m;
|
||||
@ -846,7 +712,7 @@ static int btmtkuart_shutdown(struct hci_dev *hdev)
|
||||
int err;
|
||||
|
||||
/* Disable the device */
|
||||
wmt_params.op = MTK_WMT_FUNC_CTRL;
|
||||
wmt_params.op = BTMTK_WMT_FUNC_CTRL;
|
||||
wmt_params.flag = 0;
|
||||
wmt_params.dlen = sizeof(param);
|
||||
wmt_params.data = ¶m;
|
||||
@ -1007,6 +873,7 @@ static int btmtkuart_probe(struct serdev_device *serdev)
|
||||
hdev->setup = btmtkuart_setup;
|
||||
hdev->shutdown = btmtkuart_shutdown;
|
||||
hdev->send = btmtkuart_send_frame;
|
||||
hdev->set_bdaddr = btmtk_set_bdaddr;
|
||||
SET_HCIDEV_DEV(hdev, &serdev->dev);
|
||||
|
||||
hdev->manufacturer = 70;
|
||||
@ -1131,6 +998,3 @@ MODULE_AUTHOR("Sean Wang <sean.wang@mediatek.com>");
|
||||
MODULE_DESCRIPTION("MediaTek Bluetooth Serial driver ver " VERSION);
|
||||
MODULE_VERSION(VERSION);
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_FIRMWARE(FIRMWARE_MT7622);
|
||||
MODULE_FIRMWARE(FIRMWARE_MT7663);
|
||||
MODULE_FIRMWARE(FIRMWARE_MT7668);
|
||||
|
@ -49,6 +49,7 @@ enum btrtl_chip_id {
|
||||
CHIP_ID_8822C = 13,
|
||||
CHIP_ID_8761B,
|
||||
CHIP_ID_8852A = 18,
|
||||
CHIP_ID_8852B = 20,
|
||||
};
|
||||
|
||||
struct id_table {
|
||||
@ -148,6 +149,14 @@ static const struct id_table ic_id_table[] = {
|
||||
.fw_name = "rtl_bt/rtl8761bu_fw.bin",
|
||||
.cfg_name = "rtl_bt/rtl8761bu_config" },
|
||||
|
||||
/* 8822C with UART interface */
|
||||
{ IC_INFO(RTL_ROM_LMP_8822B, 0xc, 0x8, HCI_UART),
|
||||
.config_needed = true,
|
||||
.has_rom_version = true,
|
||||
.has_msft_ext = true,
|
||||
.fw_name = "rtl_bt/rtl8822cs_fw.bin",
|
||||
.cfg_name = "rtl_bt/rtl8822cs_config" },
|
||||
|
||||
/* 8822C with UART interface */
|
||||
{ IC_INFO(RTL_ROM_LMP_8822B, 0xc, 0xa, HCI_UART),
|
||||
.config_needed = true,
|
||||
@ -179,6 +188,14 @@ static const struct id_table ic_id_table[] = {
|
||||
.has_msft_ext = true,
|
||||
.fw_name = "rtl_bt/rtl8852au_fw.bin",
|
||||
.cfg_name = "rtl_bt/rtl8852au_config" },
|
||||
|
||||
/* 8852B */
|
||||
{ IC_INFO(RTL_ROM_LMP_8852A, 0xb, 0xb, HCI_USB),
|
||||
.config_needed = false,
|
||||
.has_rom_version = true,
|
||||
.has_msft_ext = true,
|
||||
.fw_name = "rtl_bt/rtl8852bu_fw.bin",
|
||||
.cfg_name = "rtl_bt/rtl8852bu_config" },
|
||||
};
|
||||
|
||||
static const struct id_table *btrtl_match_ic(u16 lmp_subver, u16 hci_rev,
|
||||
@ -287,6 +304,7 @@ static int rtlbt_parse_firmware(struct hci_dev *hdev,
|
||||
{ RTL_ROM_LMP_8822B, 13 }, /* 8822C */
|
||||
{ RTL_ROM_LMP_8761A, 14 }, /* 8761B */
|
||||
{ RTL_ROM_LMP_8852A, 18 }, /* 8852A */
|
||||
{ RTL_ROM_LMP_8852A, 20 }, /* 8852B */
|
||||
};
|
||||
|
||||
min_size = sizeof(struct rtl_epatch_header) + sizeof(extension_sig) + 3;
|
||||
@ -749,6 +767,7 @@ void btrtl_set_quirks(struct hci_dev *hdev, struct btrtl_device_info *btrtl_dev)
|
||||
switch (btrtl_dev->project_id) {
|
||||
case CHIP_ID_8822C:
|
||||
case CHIP_ID_8852A:
|
||||
case CHIP_ID_8852B:
|
||||
set_bit(HCI_QUIRK_VALID_LE_STATES, &hdev->quirks);
|
||||
set_bit(HCI_QUIRK_WIDEBAND_SPEECH_SUPPORTED, &hdev->quirks);
|
||||
hci_set_aosp_capable(hdev);
|
||||
@ -926,3 +945,5 @@ MODULE_FIRMWARE("rtl_bt/rtl8822b_fw.bin");
|
||||
MODULE_FIRMWARE("rtl_bt/rtl8822b_config.bin");
|
||||
MODULE_FIRMWARE("rtl_bt/rtl8852au_fw.bin");
|
||||
MODULE_FIRMWARE("rtl_bt/rtl8852au_config.bin");
|
||||
MODULE_FIRMWARE("rtl_bt/rtl8852bu_fw.bin");
|
||||
MODULE_FIRMWARE("rtl_bt/rtl8852bu_config.bin");
|
||||
|
@ -36,32 +36,33 @@ static bool reset = true;
|
||||
|
||||
static struct usb_driver btusb_driver;
|
||||
|
||||
#define BTUSB_IGNORE 0x01
|
||||
#define BTUSB_DIGIANSWER 0x02
|
||||
#define BTUSB_CSR 0x04
|
||||
#define BTUSB_SNIFFER 0x08
|
||||
#define BTUSB_BCM92035 0x10
|
||||
#define BTUSB_BROKEN_ISOC 0x20
|
||||
#define BTUSB_WRONG_SCO_MTU 0x40
|
||||
#define BTUSB_ATH3012 0x80
|
||||
#define BTUSB_INTEL_COMBINED 0x100
|
||||
#define BTUSB_INTEL_BOOT 0x200
|
||||
#define BTUSB_BCM_PATCHRAM 0x400
|
||||
#define BTUSB_MARVELL 0x800
|
||||
#define BTUSB_SWAVE 0x1000
|
||||
#define BTUSB_AMP 0x4000
|
||||
#define BTUSB_QCA_ROME 0x8000
|
||||
#define BTUSB_BCM_APPLE 0x10000
|
||||
#define BTUSB_REALTEK 0x20000
|
||||
#define BTUSB_BCM2045 0x40000
|
||||
#define BTUSB_IFNUM_2 0x80000
|
||||
#define BTUSB_CW6622 0x100000
|
||||
#define BTUSB_MEDIATEK 0x200000
|
||||
#define BTUSB_WIDEBAND_SPEECH 0x400000
|
||||
#define BTUSB_VALID_LE_STATES 0x800000
|
||||
#define BTUSB_QCA_WCN6855 0x1000000
|
||||
#define BTUSB_INTEL_BROKEN_SHUTDOWN_LED 0x2000000
|
||||
#define BTUSB_INTEL_BROKEN_INITIAL_NCMD 0x4000000
|
||||
#define BTUSB_IGNORE BIT(0)
|
||||
#define BTUSB_DIGIANSWER BIT(1)
|
||||
#define BTUSB_CSR BIT(2)
|
||||
#define BTUSB_SNIFFER BIT(3)
|
||||
#define BTUSB_BCM92035 BIT(4)
|
||||
#define BTUSB_BROKEN_ISOC BIT(5)
|
||||
#define BTUSB_WRONG_SCO_MTU BIT(6)
|
||||
#define BTUSB_ATH3012 BIT(7)
|
||||
#define BTUSB_INTEL_COMBINED BIT(8)
|
||||
#define BTUSB_INTEL_BOOT BIT(9)
|
||||
#define BTUSB_BCM_PATCHRAM BIT(10)
|
||||
#define BTUSB_MARVELL BIT(11)
|
||||
#define BTUSB_SWAVE BIT(12)
|
||||
#define BTUSB_AMP BIT(13)
|
||||
#define BTUSB_QCA_ROME BIT(14)
|
||||
#define BTUSB_BCM_APPLE BIT(15)
|
||||
#define BTUSB_REALTEK BIT(16)
|
||||
#define BTUSB_BCM2045 BIT(17)
|
||||
#define BTUSB_IFNUM_2 BIT(18)
|
||||
#define BTUSB_CW6622 BIT(19)
|
||||
#define BTUSB_MEDIATEK BIT(20)
|
||||
#define BTUSB_WIDEBAND_SPEECH BIT(21)
|
||||
#define BTUSB_VALID_LE_STATES BIT(22)
|
||||
#define BTUSB_QCA_WCN6855 BIT(23)
|
||||
#define BTUSB_INTEL_BROKEN_SHUTDOWN_LED BIT(24)
|
||||
#define BTUSB_INTEL_BROKEN_INITIAL_NCMD BIT(25)
|
||||
#define BTUSB_INTEL_NO_WBS_SUPPORT BIT(26)
|
||||
|
||||
static const struct usb_device_id btusb_table[] = {
|
||||
/* Generic Bluetooth USB device */
|
||||
@ -383,11 +384,14 @@ static const struct usb_device_id blacklist_table[] = {
|
||||
{ USB_DEVICE(0x8087, 0x0029), .driver_info = BTUSB_INTEL_COMBINED },
|
||||
{ USB_DEVICE(0x8087, 0x0032), .driver_info = BTUSB_INTEL_COMBINED },
|
||||
{ USB_DEVICE(0x8087, 0x0033), .driver_info = BTUSB_INTEL_COMBINED },
|
||||
{ USB_DEVICE(0x8087, 0x0035), .driver_info = BTUSB_INTEL_COMBINED },
|
||||
{ USB_DEVICE(0x8087, 0x07da), .driver_info = BTUSB_CSR },
|
||||
{ USB_DEVICE(0x8087, 0x07dc), .driver_info = BTUSB_INTEL_COMBINED |
|
||||
BTUSB_INTEL_NO_WBS_SUPPORT |
|
||||
BTUSB_INTEL_BROKEN_INITIAL_NCMD |
|
||||
BTUSB_INTEL_BROKEN_SHUTDOWN_LED },
|
||||
{ USB_DEVICE(0x8087, 0x0a2a), .driver_info = BTUSB_INTEL_COMBINED |
|
||||
BTUSB_INTEL_NO_WBS_SUPPORT |
|
||||
BTUSB_INTEL_BROKEN_SHUTDOWN_LED },
|
||||
{ USB_DEVICE(0x8087, 0x0a2b), .driver_info = BTUSB_INTEL_COMBINED },
|
||||
{ USB_DEVICE(0x8087, 0x0aa7), .driver_info = BTUSB_INTEL_COMBINED |
|
||||
@ -405,6 +409,8 @@ static const struct usb_device_id blacklist_table[] = {
|
||||
BTUSB_WIDEBAND_SPEECH },
|
||||
|
||||
/* Realtek 8852AE Bluetooth devices */
|
||||
{ USB_DEVICE(0x0bda, 0x2852), .driver_info = BTUSB_REALTEK |
|
||||
BTUSB_WIDEBAND_SPEECH },
|
||||
{ USB_DEVICE(0x0bda, 0xc852), .driver_info = BTUSB_REALTEK |
|
||||
BTUSB_WIDEBAND_SPEECH },
|
||||
{ USB_DEVICE(0x0bda, 0x385a), .driver_info = BTUSB_REALTEK |
|
||||
@ -429,6 +435,11 @@ static const struct usb_device_id blacklist_table[] = {
|
||||
/* Additional MediaTek MT7615E Bluetooth devices */
|
||||
{ USB_DEVICE(0x13d3, 0x3560), .driver_info = BTUSB_MEDIATEK},
|
||||
|
||||
/* Additional MediaTek MT7663 Bluetooth devices */
|
||||
{ USB_DEVICE(0x043e, 0x310c), .driver_info = BTUSB_MEDIATEK |
|
||||
BTUSB_WIDEBAND_SPEECH |
|
||||
BTUSB_VALID_LE_STATES },
|
||||
|
||||
/* Additional MediaTek MT7668 Bluetooth devices */
|
||||
{ USB_DEVICE(0x043e, 0x3109), .driver_info = BTUSB_MEDIATEK |
|
||||
BTUSB_WIDEBAND_SPEECH |
|
||||
@ -444,6 +455,9 @@ static const struct usb_device_id blacklist_table[] = {
|
||||
{ USB_DEVICE(0x13d3, 0x3564), .driver_info = BTUSB_MEDIATEK |
|
||||
BTUSB_WIDEBAND_SPEECH |
|
||||
BTUSB_VALID_LE_STATES },
|
||||
{ USB_DEVICE(0x13d3, 0x3567), .driver_info = BTUSB_MEDIATEK |
|
||||
BTUSB_WIDEBAND_SPEECH |
|
||||
BTUSB_VALID_LE_STATES },
|
||||
{ USB_DEVICE(0x0489, 0xe0cd), .driver_info = BTUSB_MEDIATEK |
|
||||
BTUSB_WIDEBAND_SPEECH |
|
||||
BTUSB_VALID_LE_STATES },
|
||||
@ -463,6 +477,7 @@ static const struct usb_device_id blacklist_table[] = {
|
||||
/* Additional Realtek 8723BE Bluetooth devices */
|
||||
{ USB_DEVICE(0x0489, 0xe085), .driver_info = BTUSB_REALTEK },
|
||||
{ USB_DEVICE(0x0489, 0xe08b), .driver_info = BTUSB_REALTEK },
|
||||
{ USB_DEVICE(0x04f2, 0xb49f), .driver_info = BTUSB_REALTEK },
|
||||
{ USB_DEVICE(0x13d3, 0x3410), .driver_info = BTUSB_REALTEK },
|
||||
{ USB_DEVICE(0x13d3, 0x3416), .driver_info = BTUSB_REALTEK },
|
||||
{ USB_DEVICE(0x13d3, 0x3459), .driver_info = BTUSB_REALTEK },
|
||||
@ -482,6 +497,8 @@ static const struct usb_device_id blacklist_table[] = {
|
||||
/* Additional Realtek 8761BU Bluetooth devices */
|
||||
{ USB_DEVICE(0x0b05, 0x190e), .driver_info = BTUSB_REALTEK |
|
||||
BTUSB_WIDEBAND_SPEECH },
|
||||
{ USB_DEVICE(0x2550, 0x8761), .driver_info = BTUSB_REALTEK |
|
||||
BTUSB_WIDEBAND_SPEECH },
|
||||
|
||||
/* Additional Realtek 8821AE Bluetooth devices */
|
||||
{ USB_DEVICE(0x0b05, 0x17dc), .driver_info = BTUSB_REALTEK },
|
||||
@ -2041,6 +2058,8 @@ static int btusb_setup_csr(struct hci_dev *hdev)
|
||||
*/
|
||||
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);
|
||||
|
||||
/* Clear the reset quirk since this is not an actual
|
||||
* early Bluetooth 1.1 device from CSR.
|
||||
@ -2051,16 +2070,16 @@ static int btusb_setup_csr(struct hci_dev *hdev)
|
||||
/*
|
||||
* Special workaround for these BT 4.0 chip clones, and potentially more:
|
||||
*
|
||||
* - 0x0134: a Barrot 8041a02 (HCI rev: 0x1012 sub: 0x0810)
|
||||
* - 0x0134: a Barrot 8041a02 (HCI rev: 0x0810 sub: 0x1012)
|
||||
* - 0x7558: IC markings FR3191AHAL 749H15143 (HCI rev/sub-version: 0x0709)
|
||||
*
|
||||
* These controllers are really messed-up.
|
||||
*
|
||||
* 1. Their bulk RX endpoint will never report any data unless
|
||||
* the device was suspended at least once (yes, really).
|
||||
* the device was suspended at least once (yes, really).
|
||||
* 2. They will not wakeup when autosuspended and receiving data
|
||||
* on their bulk RX endpoint from e.g. a keyboard or mouse
|
||||
* (IOW remote-wakeup support is broken for the bulk endpoint).
|
||||
* on their bulk RX endpoint from e.g. a keyboard or mouse
|
||||
* (IOW remote-wakeup support is broken for the bulk endpoint).
|
||||
*
|
||||
* To fix 1. enable runtime-suspend, force-suspend the
|
||||
* HCI and then wake-it up by disabling runtime-suspend.
|
||||
@ -2080,7 +2099,7 @@ static int btusb_setup_csr(struct hci_dev *hdev)
|
||||
if (ret >= 0)
|
||||
msleep(200);
|
||||
else
|
||||
bt_dev_err(hdev, "CSR: Failed to suspend the device for our Barrot 8041a02 receive-issue workaround");
|
||||
bt_dev_warn(hdev, "CSR: Couldn't suspend the device for our Barrot 8041a02 receive-issue workaround");
|
||||
|
||||
pm_runtime_forbid(&data->udev->dev);
|
||||
|
||||
@ -2245,7 +2264,6 @@ static void btusb_mtk_wmt_recv(struct urb *urb)
|
||||
{
|
||||
struct hci_dev *hdev = urb->context;
|
||||
struct btusb_data *data = hci_get_drvdata(hdev);
|
||||
struct hci_event_hdr *hdr;
|
||||
struct sk_buff *skb;
|
||||
int err;
|
||||
|
||||
@ -2265,13 +2283,6 @@ static void btusb_mtk_wmt_recv(struct urb *urb)
|
||||
hci_skb_pkt_type(skb) = HCI_EVENT_PKT;
|
||||
skb_put_data(skb, urb->transfer_buffer, urb->actual_length);
|
||||
|
||||
hdr = (void *)skb->data;
|
||||
/* Fix up the vendor event id with 0xff for vendor specific
|
||||
* instead of 0xe4 so that event send via monitoring socket can
|
||||
* be parsed properly.
|
||||
*/
|
||||
hdr->evt = 0xff;
|
||||
|
||||
/* When someone waits for the WMT event, the skb is being cloned
|
||||
* and being processed the events from there then.
|
||||
*/
|
||||
@ -2988,6 +2999,7 @@ static int btusb_set_bdaddr_wcn6855(struct hci_dev *hdev,
|
||||
#define QCA_PATCH_UPDATED 0x80
|
||||
#define QCA_DFU_TIMEOUT 3000
|
||||
#define QCA_FLAG_MULTI_NVM 0x80
|
||||
#define QCA_BT_RESET_WAIT_MS 100
|
||||
|
||||
#define WCN6855_2_0_RAM_VERSION_GF 0x400c1200
|
||||
#define WCN6855_2_1_RAM_VERSION_GF 0x400c1211
|
||||
@ -3314,6 +3326,13 @@ static int btusb_setup_qca(struct hci_dev *hdev)
|
||||
err = btusb_setup_qca_load_nvm(hdev, &ver, info);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
/* WCN6855 2.1 will reset to apply firmware downloaded here, so
|
||||
* wait ~100ms for reset Done then go ahead, otherwise, it maybe
|
||||
* cause potential enable failure.
|
||||
*/
|
||||
if (info->rom_version == 0x00130201)
|
||||
msleep(QCA_BT_RESET_WAIT_MS);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -3737,6 +3756,9 @@ static int btusb_probe(struct usb_interface *intf,
|
||||
hdev->send = btusb_send_frame_intel;
|
||||
hdev->cmd_timeout = btusb_intel_cmd_timeout;
|
||||
|
||||
if (id->driver_info & BTUSB_INTEL_NO_WBS_SUPPORT)
|
||||
btintel_set_flag(hdev, INTEL_ROM_LEGACY_NO_WBS_SUPPORT);
|
||||
|
||||
if (id->driver_info & BTUSB_INTEL_BROKEN_INITIAL_NCMD)
|
||||
btintel_set_flag(hdev, INTEL_BROKEN_INITIAL_NCMD);
|
||||
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/gpio/machine.h>
|
||||
#include <linux/tty.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/dmi.h>
|
||||
@ -870,7 +871,23 @@ static int bcm_resume(struct device *dev)
|
||||
#endif
|
||||
|
||||
/* Some firmware reports an IRQ which does not work (wrong pin in fw table?) */
|
||||
static struct gpiod_lookup_table asus_tf103c_irq_gpios = {
|
||||
.dev_id = "serial0-0",
|
||||
.table = {
|
||||
GPIO_LOOKUP("INT33FC:02", 17, "host-wakeup-alt", GPIO_ACTIVE_HIGH),
|
||||
{ }
|
||||
},
|
||||
};
|
||||
|
||||
static const struct dmi_system_id bcm_broken_irq_dmi_table[] = {
|
||||
{
|
||||
.ident = "Asus TF103C",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "TF103C"),
|
||||
},
|
||||
.driver_data = &asus_tf103c_irq_gpios,
|
||||
},
|
||||
{
|
||||
.ident = "Meegopad T08",
|
||||
.matches = {
|
||||
@ -1027,7 +1044,8 @@ static struct clk *bcm_get_txco(struct device *dev)
|
||||
|
||||
static int bcm_get_resources(struct bcm_device *dev)
|
||||
{
|
||||
const struct dmi_system_id *dmi_id;
|
||||
const struct dmi_system_id *broken_irq_dmi_id;
|
||||
const char *irq_con_id = "host-wakeup";
|
||||
int err;
|
||||
|
||||
dev->name = dev_name(dev->dev);
|
||||
@ -1083,23 +1101,33 @@ static int bcm_get_resources(struct bcm_device *dev)
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
broken_irq_dmi_id = dmi_first_match(bcm_broken_irq_dmi_table);
|
||||
if (broken_irq_dmi_id && broken_irq_dmi_id->driver_data) {
|
||||
gpiod_add_lookup_table(broken_irq_dmi_id->driver_data);
|
||||
irq_con_id = "host-wakeup-alt";
|
||||
dev->irq_active_low = false;
|
||||
dev->irq = 0;
|
||||
}
|
||||
|
||||
/* IRQ can be declared in ACPI table as Interrupt or GpioInt */
|
||||
if (dev->irq <= 0) {
|
||||
struct gpio_desc *gpio;
|
||||
|
||||
gpio = devm_gpiod_get_optional(dev->dev, "host-wakeup",
|
||||
GPIOD_IN);
|
||||
gpio = devm_gpiod_get_optional(dev->dev, irq_con_id, GPIOD_IN);
|
||||
if (IS_ERR(gpio))
|
||||
return PTR_ERR(gpio);
|
||||
|
||||
dev->irq = gpiod_to_irq(gpio);
|
||||
}
|
||||
|
||||
dmi_id = dmi_first_match(bcm_broken_irq_dmi_table);
|
||||
if (dmi_id) {
|
||||
dev_info(dev->dev, "%s: Has a broken IRQ config, disabling IRQ support / runtime-pm\n",
|
||||
dmi_id->ident);
|
||||
dev->irq = 0;
|
||||
if (broken_irq_dmi_id) {
|
||||
if (broken_irq_dmi_id->driver_data) {
|
||||
gpiod_remove_lookup_table(broken_irq_dmi_id->driver_data);
|
||||
} else {
|
||||
dev_info(dev->dev, "%s: Has a broken IRQ config, disabling IRQ support / runtime-pm\n",
|
||||
broken_irq_dmi_id->ident);
|
||||
dev->irq = 0;
|
||||
}
|
||||
}
|
||||
|
||||
dev_dbg(dev->dev, "BCM irq: %d\n", dev->irq);
|
||||
@ -1513,6 +1541,8 @@ static const struct of_device_id bcm_bluetooth_of_match[] = {
|
||||
{ .compatible = "brcm,bcm4330-bt" },
|
||||
{ .compatible = "brcm,bcm4334-bt" },
|
||||
{ .compatible = "brcm,bcm4345c5" },
|
||||
{ .compatible = "brcm,bcm43430a0-bt" },
|
||||
{ .compatible = "brcm,bcm43430a1-bt" },
|
||||
{ .compatible = "brcm,bcm43438-bt", .data = &bcm43438_device_data },
|
||||
{ .compatible = "brcm,bcm43540-bt", .data = &bcm4354_device_data },
|
||||
{ .compatible = "brcm,bcm4335a0" },
|
||||
|
@ -629,9 +629,11 @@ static int h5_enqueue(struct hci_uart *hu, struct sk_buff *skb)
|
||||
break;
|
||||
}
|
||||
|
||||
pm_runtime_get_sync(&hu->serdev->dev);
|
||||
pm_runtime_mark_last_busy(&hu->serdev->dev);
|
||||
pm_runtime_put_autosuspend(&hu->serdev->dev);
|
||||
if (hu->serdev) {
|
||||
pm_runtime_get_sync(&hu->serdev->dev);
|
||||
pm_runtime_mark_last_busy(&hu->serdev->dev);
|
||||
pm_runtime_put_autosuspend(&hu->serdev->dev);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -966,6 +968,11 @@ static void h5_btrtl_open(struct h5 *h5)
|
||||
pm_runtime_enable(&h5->hu->serdev->dev);
|
||||
}
|
||||
|
||||
/* The controller needs reset to startup */
|
||||
gpiod_set_value_cansleep(h5->enable_gpio, 0);
|
||||
gpiod_set_value_cansleep(h5->device_wake_gpio, 0);
|
||||
msleep(100);
|
||||
|
||||
/* The controller needs up to 500ms to wakeup */
|
||||
gpiod_set_value_cansleep(h5->enable_gpio, 1);
|
||||
gpiod_set_value_cansleep(h5->device_wake_gpio, 1);
|
||||
|
@ -509,7 +509,7 @@ static int send_command_from_firmware(struct ll_device *lldev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
/*
|
||||
* download_firmware -
|
||||
* internal function which parses through the .bts firmware
|
||||
* script file intreprets SEND, DELAY actions only as of now
|
||||
|
@ -305,6 +305,8 @@ int hci_uart_register_device(struct hci_uart *hu,
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
percpu_init_rwsem(&hu->proto_lock);
|
||||
|
||||
err = p->open(hu);
|
||||
if (err)
|
||||
goto err_open;
|
||||
@ -327,7 +329,6 @@ int hci_uart_register_device(struct hci_uart *hu,
|
||||
|
||||
INIT_WORK(&hu->init_ready, hci_uart_init_work);
|
||||
INIT_WORK(&hu->write_work, hci_uart_write_work);
|
||||
percpu_init_rwsem(&hu->proto_lock);
|
||||
|
||||
/* Only when vendor specific setup callback is provided, consider
|
||||
* the manufacturer information valid. This avoids filling in the
|
||||
|
@ -433,8 +433,7 @@ void mlx5_ib_init_cong_debugfs(struct mlx5_ib_dev *dev, u32 port_num)
|
||||
|
||||
dev->port[port_num].dbg_cc_params = dbg_cc_params;
|
||||
|
||||
dbg_cc_params->root = debugfs_create_dir("cc_params",
|
||||
mdev->priv.dbg_root);
|
||||
dbg_cc_params->root = debugfs_create_dir("cc_params", mlx5_debugfs_get_dev_root(mdev));
|
||||
|
||||
for (i = 0; i < MLX5_IB_DBG_CC_MAX; i++) {
|
||||
dbg_cc_params->params[i].offset = i;
|
||||
|
@ -1055,7 +1055,7 @@ static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_OTHER)(
|
||||
int cmd_out_len = uverbs_attr_get_len(attrs,
|
||||
MLX5_IB_ATTR_DEVX_OTHER_CMD_OUT);
|
||||
void *cmd_out;
|
||||
int err;
|
||||
int err, err2;
|
||||
int uid;
|
||||
|
||||
c = devx_ufile2uctx(attrs);
|
||||
@ -1076,14 +1076,16 @@ static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_OTHER)(
|
||||
return PTR_ERR(cmd_out);
|
||||
|
||||
MLX5_SET(general_obj_in_cmd_hdr, cmd_in, uid, uid);
|
||||
err = mlx5_cmd_exec(dev->mdev, cmd_in,
|
||||
uverbs_attr_get_len(attrs, MLX5_IB_ATTR_DEVX_OTHER_CMD_IN),
|
||||
cmd_out, cmd_out_len);
|
||||
if (err)
|
||||
err = mlx5_cmd_do(dev->mdev, cmd_in,
|
||||
uverbs_attr_get_len(attrs, MLX5_IB_ATTR_DEVX_OTHER_CMD_IN),
|
||||
cmd_out, cmd_out_len);
|
||||
if (err && err != -EREMOTEIO)
|
||||
return err;
|
||||
|
||||
return uverbs_copy_to(attrs, MLX5_IB_ATTR_DEVX_OTHER_CMD_OUT, cmd_out,
|
||||
err2 = uverbs_copy_to(attrs, MLX5_IB_ATTR_DEVX_OTHER_CMD_OUT, cmd_out,
|
||||
cmd_out_len);
|
||||
|
||||
return err2 ?: err;
|
||||
}
|
||||
|
||||
static void devx_obj_build_destroy_cmd(void *in, void *out, void *din,
|
||||
@ -1457,7 +1459,7 @@ static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_OBJ_CREATE)(
|
||||
u32 out[MLX5_ST_SZ_DW(general_obj_out_cmd_hdr)];
|
||||
struct devx_obj *obj;
|
||||
u16 obj_type = 0;
|
||||
int err;
|
||||
int err, err2 = 0;
|
||||
int uid;
|
||||
u32 obj_id;
|
||||
u16 opcode;
|
||||
@ -1497,15 +1499,18 @@ static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_OBJ_CREATE)(
|
||||
!is_apu_cq(dev, cmd_in)) {
|
||||
obj->flags |= DEVX_OBJ_FLAGS_CQ;
|
||||
obj->core_cq.comp = devx_cq_comp;
|
||||
err = mlx5_core_create_cq(dev->mdev, &obj->core_cq,
|
||||
cmd_in, cmd_in_len, cmd_out,
|
||||
cmd_out_len);
|
||||
err = mlx5_create_cq(dev->mdev, &obj->core_cq,
|
||||
cmd_in, cmd_in_len, cmd_out,
|
||||
cmd_out_len);
|
||||
} else {
|
||||
err = mlx5_cmd_exec(dev->mdev, cmd_in,
|
||||
cmd_in_len,
|
||||
cmd_out, cmd_out_len);
|
||||
err = mlx5_cmd_do(dev->mdev, cmd_in, cmd_in_len,
|
||||
cmd_out, cmd_out_len);
|
||||
}
|
||||
|
||||
if (err == -EREMOTEIO)
|
||||
err2 = uverbs_copy_to(attrs,
|
||||
MLX5_IB_ATTR_DEVX_OBJ_CREATE_CMD_OUT,
|
||||
cmd_out, cmd_out_len);
|
||||
if (err)
|
||||
goto obj_free;
|
||||
|
||||
@ -1548,7 +1553,7 @@ static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_OBJ_CREATE)(
|
||||
sizeof(out));
|
||||
obj_free:
|
||||
kfree(obj);
|
||||
return err;
|
||||
return err2 ?: err;
|
||||
}
|
||||
|
||||
static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_OBJ_MODIFY)(
|
||||
@ -1563,7 +1568,7 @@ static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_OBJ_MODIFY)(
|
||||
&attrs->driver_udata, struct mlx5_ib_ucontext, ibucontext);
|
||||
struct mlx5_ib_dev *mdev = to_mdev(c->ibucontext.device);
|
||||
void *cmd_out;
|
||||
int err;
|
||||
int err, err2;
|
||||
int uid;
|
||||
|
||||
if (MLX5_GET(general_obj_in_cmd_hdr, cmd_in, vhca_tunnel_id))
|
||||
@ -1586,14 +1591,16 @@ static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_OBJ_MODIFY)(
|
||||
MLX5_SET(general_obj_in_cmd_hdr, cmd_in, uid, uid);
|
||||
devx_set_umem_valid(cmd_in);
|
||||
|
||||
err = mlx5_cmd_exec(mdev->mdev, cmd_in,
|
||||
uverbs_attr_get_len(attrs, MLX5_IB_ATTR_DEVX_OBJ_MODIFY_CMD_IN),
|
||||
cmd_out, cmd_out_len);
|
||||
if (err)
|
||||
err = mlx5_cmd_do(mdev->mdev, cmd_in,
|
||||
uverbs_attr_get_len(attrs, MLX5_IB_ATTR_DEVX_OBJ_MODIFY_CMD_IN),
|
||||
cmd_out, cmd_out_len);
|
||||
if (err && err != -EREMOTEIO)
|
||||
return err;
|
||||
|
||||
return uverbs_copy_to(attrs, MLX5_IB_ATTR_DEVX_OBJ_MODIFY_CMD_OUT,
|
||||
err2 = uverbs_copy_to(attrs, MLX5_IB_ATTR_DEVX_OBJ_MODIFY_CMD_OUT,
|
||||
cmd_out, cmd_out_len);
|
||||
|
||||
return err2 ?: err;
|
||||
}
|
||||
|
||||
static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_OBJ_QUERY)(
|
||||
@ -1607,7 +1614,7 @@ static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_OBJ_QUERY)(
|
||||
struct mlx5_ib_ucontext *c = rdma_udata_to_drv_context(
|
||||
&attrs->driver_udata, struct mlx5_ib_ucontext, ibucontext);
|
||||
void *cmd_out;
|
||||
int err;
|
||||
int err, err2;
|
||||
int uid;
|
||||
struct mlx5_ib_dev *mdev = to_mdev(c->ibucontext.device);
|
||||
|
||||
@ -1629,14 +1636,16 @@ static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_OBJ_QUERY)(
|
||||
return PTR_ERR(cmd_out);
|
||||
|
||||
MLX5_SET(general_obj_in_cmd_hdr, cmd_in, uid, uid);
|
||||
err = mlx5_cmd_exec(mdev->mdev, cmd_in,
|
||||
uverbs_attr_get_len(attrs, MLX5_IB_ATTR_DEVX_OBJ_QUERY_CMD_IN),
|
||||
cmd_out, cmd_out_len);
|
||||
if (err)
|
||||
err = mlx5_cmd_do(mdev->mdev, cmd_in,
|
||||
uverbs_attr_get_len(attrs, MLX5_IB_ATTR_DEVX_OBJ_QUERY_CMD_IN),
|
||||
cmd_out, cmd_out_len);
|
||||
if (err && err != -EREMOTEIO)
|
||||
return err;
|
||||
|
||||
return uverbs_copy_to(attrs, MLX5_IB_ATTR_DEVX_OBJ_QUERY_CMD_OUT,
|
||||
err2 = uverbs_copy_to(attrs, MLX5_IB_ATTR_DEVX_OBJ_QUERY_CMD_OUT,
|
||||
cmd_out, cmd_out_len);
|
||||
|
||||
return err2 ?: err;
|
||||
}
|
||||
|
||||
struct devx_async_event_queue {
|
||||
|
@ -4178,7 +4178,7 @@ static int mlx5_ib_stage_delay_drop_init(struct mlx5_ib_dev *dev)
|
||||
if (!mlx5_debugfs_root)
|
||||
return 0;
|
||||
|
||||
root = debugfs_create_dir("delay_drop", dev->mdev->priv.dbg_root);
|
||||
root = debugfs_create_dir("delay_drop", mlx5_debugfs_get_dev_root(dev->mdev));
|
||||
dev->delay_drop.dir_debugfs = root;
|
||||
|
||||
debugfs_create_atomic_t("num_timeout_events", 0400, root,
|
||||
|
@ -140,6 +140,19 @@ static int destroy_mkey(struct mlx5_ib_dev *dev, struct mlx5_ib_mr *mr)
|
||||
return mlx5_core_destroy_mkey(dev->mdev, mr->mmkey.key);
|
||||
}
|
||||
|
||||
static void create_mkey_warn(struct mlx5_ib_dev *dev, int status, void *out)
|
||||
{
|
||||
if (status == -ENXIO) /* core driver is not available */
|
||||
return;
|
||||
|
||||
mlx5_ib_warn(dev, "async reg mr failed. status %d\n", status);
|
||||
if (status != -EREMOTEIO) /* driver specific failure */
|
||||
return;
|
||||
|
||||
/* Failed in FW, print cmd out failure details */
|
||||
mlx5_cmd_out_err(dev->mdev, MLX5_CMD_OP_CREATE_MKEY, 0, out);
|
||||
}
|
||||
|
||||
static void create_mkey_callback(int status, struct mlx5_async_work *context)
|
||||
{
|
||||
struct mlx5_ib_mr *mr =
|
||||
@ -149,7 +162,7 @@ static void create_mkey_callback(int status, struct mlx5_async_work *context)
|
||||
unsigned long flags;
|
||||
|
||||
if (status) {
|
||||
mlx5_ib_warn(dev, "async reg mr failed. status %d\n", status);
|
||||
create_mkey_warn(dev, status, mr->out);
|
||||
kfree(mr);
|
||||
spin_lock_irqsave(&ent->lock, flags);
|
||||
ent->pending--;
|
||||
@ -683,7 +696,7 @@ static void mlx5_mr_cache_debugfs_init(struct mlx5_ib_dev *dev)
|
||||
if (!mlx5_debugfs_root || dev->is_rep)
|
||||
return;
|
||||
|
||||
cache->root = debugfs_create_dir("mr_cache", dev->mdev->priv.dbg_root);
|
||||
cache->root = debugfs_create_dir("mr_cache", mlx5_debugfs_get_dev_root(dev->mdev));
|
||||
|
||||
for (i = 0; i < MAX_MR_CACHE_ENTRIES; i++) {
|
||||
ent = &cache->ent[i];
|
||||
|
@ -4465,6 +4465,7 @@ static int mlx5_ib_modify_dct(struct ib_qp *ibqp, struct ib_qp_attr *attr,
|
||||
err = mlx5_core_create_dct(dev, &qp->dct.mdct, qp->dct.in,
|
||||
MLX5_ST_SZ_BYTES(create_dct_in), out,
|
||||
sizeof(out));
|
||||
err = mlx5_cmd_check(dev->mdev, err, qp->dct.in, out);
|
||||
if (err)
|
||||
return err;
|
||||
resp.dctn = qp->dct.mdct.mqp.qpn;
|
||||
|
@ -220,7 +220,7 @@ int mlx5_core_create_dct(struct mlx5_ib_dev *dev, struct mlx5_core_dct *dct,
|
||||
init_completion(&dct->drained);
|
||||
MLX5_SET(create_dct_in, in, opcode, MLX5_CMD_OP_CREATE_DCT);
|
||||
|
||||
err = mlx5_cmd_exec(dev->mdev, in, inlen, out, outlen);
|
||||
err = mlx5_cmd_do(dev->mdev, in, inlen, out, outlen);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
|
@ -1062,7 +1062,7 @@ ipac_rme(struct hscx_hw *hx)
|
||||
if (!hx->bch.rx_skb)
|
||||
return;
|
||||
if (hx->bch.rx_skb->len < 2) {
|
||||
pr_debug("%s: B%1d frame to short %d\n",
|
||||
pr_debug("%s: B%1d frame too short %d\n",
|
||||
hx->ip->name, hx->bch.nr, hx->bch.rx_skb->len);
|
||||
skb_trim(hx->bch.rx_skb, 0);
|
||||
} else {
|
||||
|
@ -466,7 +466,7 @@ isar_rcv_frame(struct isar_ch *ch)
|
||||
rcv_mbox(ch->is, ptr);
|
||||
if (ch->is->cmsb & HDLC_FED) {
|
||||
if (ch->bch.rx_skb->len < 3) { /* last 2 are the FCS */
|
||||
pr_debug("%s: ISAR frame to short %d\n",
|
||||
pr_debug("%s: ISAR frame too short %d\n",
|
||||
ch->is->name, ch->bch.rx_skb->len);
|
||||
skb_trim(ch->bch.rx_skb, 0);
|
||||
break;
|
||||
@ -542,7 +542,7 @@ isar_rcv_frame(struct isar_ch *ch)
|
||||
rcv_mbox(ch->is, ptr);
|
||||
if (ch->is->cmsb & HDLC_FED) {
|
||||
if (ch->bch.rx_skb->len < 3) { /* last 2 are the FCS */
|
||||
pr_info("%s: ISAR frame to short %d\n",
|
||||
pr_info("%s: ISAR frame too short %d\n",
|
||||
ch->is->name, ch->bch.rx_skb->len);
|
||||
skb_trim(ch->bch.rx_skb, 0);
|
||||
break;
|
||||
|
@ -247,7 +247,7 @@ xpnet_receive(short partid, int channel, struct xpnet_message *msg)
|
||||
xpnet_device->stats.rx_packets++;
|
||||
xpnet_device->stats.rx_bytes += skb->len + ETH_HLEN;
|
||||
|
||||
netif_rx_ni(skb);
|
||||
netif_rx(skb);
|
||||
xpc_received(partid, channel, (void *)msg);
|
||||
}
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user