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

Pull networking updates from Jakub Kicinski:
 "Core & protocols:

   - Continue Netlink conversions to per-namespace RTNL lock
     (IPv4 routing, routing rules, routing next hops, ARP ioctls)

   - Continue extending the use of netdev instance locks. As a driver
     opt-in protect queue operations and (in due course) ethtool
     operations with the instance lock and not RTNL lock.

   - Support collecting TCP timestamps (data submitted, sent, acked) in
     BPF, allowing for transparent (to the application) and lower
     overhead tracking of TCP RPC performance.

   - Tweak existing networking Rx zero-copy infra to support zero-copy
     Rx via io_uring.

   - Optimize MPTCP performance in single subflow mode by 29%.

   - Enable GRO on packets which went thru XDP CPU redirect (were queued
     for processing on a different CPU). Improving TCP stream
     performance up to 2x.

   - Improve performance of contended connect() by 200% by searching for
     an available 4-tuple under RCU rather than a spin lock. Bring an
     additional 229% improvement by tweaking hash distribution.

   - Avoid unconditionally touching sk_tsflags on RX, improving
     performance under UDP flood by as much as 10%.

   - Avoid skb_clone() dance in ping_rcv() to improve performance under
     ping flood.

   - Avoid FIB lookup in netfilter if socket is available, 20% perf win.

   - Rework network device creation (in-kernel) API to more clearly
     identify network namespaces and their roles. There are up to 4
     namespace roles but we used to have just 2 netns pointer arguments,
     interpreted differently based on context.

   - Use sysfs_break_active_protection() instead of trylock to avoid
     deadlocks between unregistering objects and sysfs access.

   - Add a new sysctl and sockopt for capping max retransmit timeout in
     TCP.

   - Support masking port and DSCP in routing rule matches.

   - Support dumping IPv4 multicast addresses with RTM_GETMULTICAST.

   - Support specifying at what time packet should be sent on AF_XDP
     sockets.

   - Expose TCP ULP diagnostic info (for TLS and MPTCP) to non-admin
     users.

   - Add Netlink YAML spec for WiFi (nl80211) and conntrack.

   - Introduce EXPORT_IPV6_MOD() and EXPORT_IPV6_MOD_GPL() for symbols
     which only need to be exported when IPv6 support is built as a
     module.

   - Age FDB entries based on Rx not Tx traffic in VxLAN, similar to
     normal bridging.

   - Allow users to specify source port range for GENEVE tunnels.

   - netconsole: allow attaching kernel release, CPU ID and task name to
     messages as metadata

  Driver API:

   - Continue rework / fixing of Energy Efficient Ethernet (EEE) across
     the SW layers. Delegate the responsibilities to phylink where
     possible. Improve its handling in phylib.

   - Support symmetric OR-XOR RSS hashing algorithm.

   - Support tracking and preserving IRQ affinity by NAPI itself.

   - Support loopback mode speed selection for interface selftests.

  Device drivers:

   - Remove the IBM LCS driver for s390

   - Remove the sb1000 cable modem driver

   - Add support for SFP module access over SMBus

   - Add MCTP transport driver for MCTP-over-USB

   - Enable XDP metadata support in multiple drivers

   - Ethernet high-speed NICs:
      - Broadcom (bnxt):
         - add PCIe TLP Processing Hints (TPH) support for new AMD
           platforms
         - support dumping RoCE queue state for debug
         - opt into instance locking
      - Intel (100G, ice, idpf):
         - ice: rework MSI-X IRQ management and distribution
         - ice: support for E830 devices
         - iavf: add support for Rx timestamping
         - iavf: opt into instance locking
      - nVidia/Mellanox:
         - mlx4: use page pool memory allocator for Rx
         - mlx5: support for one PTP device per hardware clock
         - mlx5: support for 200Gbps per-lane link modes
         - mlx5: move IPSec policy check after decryption
      - AMD/Solarflare:
         - support FW flashing via devlink
      - Cisco (enic):
         - use page pool memory allocator for Rx
         - enable 32, 64 byte CQEs
         - get max rx/tx ring size from the device
      - Meta (fbnic):
         - support flow steering and RSS configuration
         - report queue stats
         - support TCP segmentation
         - support IRQ coalescing
         - support ring size configuration
      - Marvell/Cavium:
         - support AF_XDP
      - Wangxun:
         - support for PTP clock and timestamping
      - Huawei (hibmcge):
         - checksum offload
         - add more statistics

   - Ethernet virtual:
      - VirtIO net:
         - aggressively suppress Tx completions, improve perf by 96%
           with 1 CPU and 55% with 2 CPUs
         - expose NAPI to IRQ mapping and persist NAPI settings
      - Google (gve):
         - support XDP in DQO RDA Queue Format
         - opt into instance locking
      - Microsoft vNIC:
         - support BIG TCP

   - Ethernet NICs consumer, and embedded:
      - Synopsys (stmmac):
         - cleanup Tx and Tx clock setting and other link-focused
           cleanups
         - enable SGMII and 2500BASEX mode switching for Intel platforms
         - support Sophgo SG2044
      - Broadcom switches (b53):
         - support for BCM53101
      - TI:
         - iep: add perout configuration support
         - icssg: support XDP
      - Cadence (macb):
         - implement BQL
      - Xilinx (axinet):
         - support dynamic IRQ moderation and changing coalescing at
           runtime
         - implement BQL
         - report standard stats
      - MediaTek:
         - support phylink managed EEE
      - Intel:
         - igc: don't restart the interface on every XDP program change
      - RealTek (r8169):
         - support reading registers of internal PHYs directly
         - increase max jumbo packet size on RTL8125/RTL8126
      - Airoha:
         - support for RISC-V NPU packet processing unit
         - enable scatter-gather and support MTU up to 9kB
      - Tehuti (tn40xx):
         - support cards with TN4010 MAC and an Aquantia AQR105 PHY

   - Ethernet PHYs:
      - support for TJA1102S, TJA1121
      - dp83tg720: add randomized polling intervals for link detection
      - dp83822: support changing the transmit amplitude voltage
      - support for LEDs on 88q2xxx

   - CAN:
      - canxl: support Remote Request Substitution bit access
      - flexcan: add S32G2/S32G3 SoC

   - WiFi:
      - remove cooked monitor support
      - strict mode for better AP testing
      - basic EPCS support
      - OMI RX bandwidth reduction support
      - batman-adv: add support for jumbo frames

   - WiFi drivers:
      - RealTek (rtw88):
         - support RTL8814AE and RTL8814AU
      - RealTek (rtw89):
         - switch using wiphy_lock and wiphy_work
         - add BB context to manipulate two PHY as preparation of MLO
         - improve BT-coexistence mechanism to play A2DP smoothly
      - Intel (iwlwifi):
         - add new iwlmld sub-driver for latest HW/FW combinations
      - MediaTek (mt76):
         - preparation for mt7996 Multi-Link Operation (MLO) support
      - Qualcomm/Atheros (ath12k):
         - continued work on MLO
      - Silabs (wfx):
         - Wake-on-WLAN support

   - Bluetooth:
      - add support for skb TX SND/COMPLETION timestamping
      - hci_core: enable buffer flow control for SCO/eSCO
      - coredump: log devcd dumps into the monitor

   - Bluetooth drivers:
      - intel: add support to configure TX power
      - nxp: handle bootloader error during cmd5 and cmd7"

* tag 'net-next-6.15' of git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-next: (1681 commits)
  unix: fix up for "apparmor: add fine grained af_unix mediation"
  mctp: Fix incorrect tx flow invalidation condition in mctp-i2c
  net: usb: asix: ax88772: Increase phy_name size
  net: phy: Introduce PHY_ID_SIZE — minimum size for PHY ID string
  net: libwx: fix Tx L4 checksum
  net: libwx: fix Tx descriptor content for some tunnel packets
  atm: Fix NULL pointer dereference
  net: tn40xx: add pci-id of the aqr105-based Tehuti TN4010 cards
  net: tn40xx: prepare tn40xx driver to find phy of the TN9510 card
  net: tn40xx: create swnode for mdio and aqr105 phy and add to mdiobus
  net: phy: aquantia: add essential functions to aqr105 driver
  net: phy: aquantia: search for firmware-name in fwnode
  net: phy: aquantia: add probe function to aqr105 for firmware loading
  net: phy: Add swnode support to mdiobus_scan
  gve: add XDP DROP and PASS support for DQ
  gve: update XDP allocation path support RX buffer posting
  gve: merge packet buffer size fields
  gve: update GQ RX to use buf_size
  gve: introduce config-based allocation for XDP
  gve: remove xdp_xsk_done and xdp_xsk_wakeup statistics
  ...
This commit is contained in:
Linus Torvalds
2025-03-26 21:48:21 -07:00
1522 changed files with 127615 additions and 39547 deletions

View File

@@ -3233,6 +3233,10 @@ N: Rui Prior
E: rprior@inescn.pt
D: ATM device driver for NICStAR based cards
N: Roopa Prabhu
E: roopa@nvidia.com
D: Bridge co-maintainer, vxlan and networking contributor
N: Stefan Probst
E: sp@caldera.de
D: The Linux Support Team Erlangen, 1993-97

View File

@@ -244,7 +244,7 @@ information about the interrupt from the irb parameter.
--------------------
The ccwgroup mechanism is designed to handle devices consisting of multiple ccw
devices, like lcs or ctc.
devices, like qeth or ctc.
The ccw driver provides a 'group' attribute. Piping bus ids of ccw devices to
this attributes creates a ccwgroup device consisting of these ccw devices (if

View File

@@ -63,6 +63,14 @@ properties:
"#size-cells":
const: 0
airoha,npu:
$ref: /schemas/types.yaml#/definitions/phandle
description:
Phandle to the node used to configure the NPU module.
The Airoha Network Processor Unit (NPU) provides a configuration
interface to implement hardware flow offloading programming Packet
Processor Engine (PPE) flow table.
patternProperties:
"^ethernet@[1-4]$":
type: object
@@ -132,6 +140,8 @@ examples:
<GIC_SPI 49 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 64 IRQ_TYPE_LEVEL_HIGH>;
airoha,npu = <&npu>;
#address-cells = <1>;
#size-cells = <0>;

View File

@@ -0,0 +1,84 @@
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/net/airoha,en7581-npu.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Airoha Network Processor Unit for EN7581 SoC
maintainers:
- Lorenzo Bianconi <lorenzo@kernel.org>
description:
The Airoha Network Processor Unit (NPU) provides a configuration interface
to implement wired and wireless hardware flow offloading programming Packet
Processor Engine (PPE) flow table.
properties:
compatible:
enum:
- airoha,en7581-npu
reg:
maxItems: 1
interrupts:
items:
- description: mbox host irq line
- description: watchdog0 irq line
- description: watchdog1 irq line
- description: watchdog2 irq line
- description: watchdog3 irq line
- description: watchdog4 irq line
- description: watchdog5 irq line
- description: watchdog6 irq line
- description: watchdog7 irq line
- description: wlan irq line0
- description: wlan irq line1
- description: wlan irq line2
- description: wlan irq line3
- description: wlan irq line4
- description: wlan irq line5
memory-region:
maxItems: 1
description:
Memory used to store NPU firmware binary.
required:
- compatible
- reg
- interrupts
- memory-region
additionalProperties: false
examples:
- |
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/interrupt-controller/irq.h>
soc {
#address-cells = <2>;
#size-cells = <2>;
npu@1e900000 {
compatible = "airoha,en7581-npu";
reg = <0 0x1e900000 0 0x313000>;
interrupts = <GIC_SPI 125 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 103 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 109 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 113 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 134 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 135 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 136 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 137 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 119 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 120 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 121 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 122 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 123 IRQ_TYPE_LEVEL_HIGH>;
memory-region = <&npu_binary>;
};
};

View File

@@ -152,6 +152,12 @@ properties:
The second range is is for the Amlogic specific configuration
(for example the PRG_ETHERNET register range on Meson8b and newer)
interrupts:
maxItems: 1
interrupt-names:
const: macirq
required:
- compatible
- reg

View File

@@ -17,6 +17,9 @@ description:
maintainers:
- Neeraj Sanjay Kale <neeraj.sanjaykale@nxp.com>
allOf:
- $ref: bluetooth-controller.yaml#
properties:
compatible:
enum:
@@ -40,10 +43,20 @@ properties:
Host-To-Chip power save mechanism is driven by this GPIO
connected to BT_WAKE_IN pin of the NXP chipset.
nxp,wakein-pin:
$ref: /schemas/types.yaml#/definitions/uint8
description:
The GPIO number of the NXP chipset used for BT_WAKE_IN.
nxp,wakeout-pin:
$ref: /schemas/types.yaml#/definitions/uint8
description:
The GPIO number of the NXP chipset used for BT_WAKE_OUT.
required:
- compatible
additionalProperties: false
unevaluatedProperties: false
examples:
- |
@@ -54,5 +67,8 @@ examples:
fw-init-baudrate = <3000000>;
firmware-name = "uartuart8987_bt_v0.bin";
device-wakeup-gpios = <&gpio 11 GPIO_ACTIVE_HIGH>;
nxp,wakein-pin = /bits/ 8 <18>;
nxp,wakeout-pin = /bits/ 8 <19>;
local-bd-address = [66 55 44 33 22 11];
};
};

View File

@@ -19,6 +19,7 @@ properties:
- qcom,qca2066-bt
- qcom,qca6174-bt
- qcom,qca9377-bt
- qcom,wcn3950-bt
- qcom,wcn3988-bt
- qcom,wcn3990-bt
- qcom,wcn3991-bt
@@ -138,6 +139,7 @@ allOf:
compatible:
contains:
enum:
- qcom,wcn3950-bt
- qcom,wcn3988-bt
- qcom,wcn3990-bt
- qcom,wcn3991-bt

View File

@@ -10,9 +10,6 @@ title:
maintainers:
- Marc Kleine-Budde <mkl@pengutronix.de>
allOf:
- $ref: can-controller.yaml#
properties:
compatible:
oneOf:
@@ -28,6 +25,7 @@ properties:
- fsl,vf610-flexcan
- fsl,ls1021ar2-flexcan
- fsl,lx2160ar1-flexcan
- nxp,s32g2-flexcan
- items:
- enum:
- fsl,imx53-flexcan
@@ -43,12 +41,25 @@ properties:
- enum:
- fsl,ls1028ar1-flexcan
- const: fsl,lx2160ar1-flexcan
- items:
- enum:
- nxp,s32g3-flexcan
- const: nxp,s32g2-flexcan
- items:
- enum:
- fsl,imx94-flexcan
- const: fsl,imx95-flexcan
reg:
maxItems: 1
interrupts:
maxItems: 1
minItems: 1
maxItems: 4
interrupt-names:
minItems: 1
maxItems: 4
clocks:
maxItems: 2
@@ -70,6 +81,9 @@ properties:
xceiver-supply:
description: Regulator that powers the CAN transceiver.
phys:
maxItems: 1
big-endian:
$ref: /schemas/types.yaml#/definitions/flag
description: |
@@ -136,6 +150,41 @@ required:
- reg
- interrupts
allOf:
- $ref: can-controller.yaml#
- if:
properties:
compatible:
contains:
const: nxp,s32g2-flexcan
then:
properties:
interrupts:
items:
- description: Message Buffer interrupt for mailboxes 0-7 and Enhanced RX FIFO
- description: Device state change
- description: Bus Error detection
- description: Message Buffer interrupt for mailboxes 8-127
interrupt-names:
items:
- const: mb-0
- const: state
- const: berr
- const: mb-1
required:
- interrupt-names
else:
properties:
interrupts:
maxItems: 1
interrupt-names: false
- if:
required:
- xceiver-supply
then:
properties:
phys: false
additionalProperties: false
examples:

View File

@@ -16,6 +16,7 @@ properties:
compatible:
oneOf:
- const: brcm,bcm5325
- const: brcm,bcm53101
- const: brcm,bcm53115
- const: brcm,bcm53125
- const: brcm,bcm53128
@@ -77,6 +78,7 @@ allOf:
contains:
enum:
- brcm,bcm5325
- brcm,bcm53101
- brcm,bcm53115
- brcm,bcm53125
- brcm,bcm53128

View File

@@ -232,6 +232,12 @@ properties:
PHY's that have configurable TX internal delays. If this property is
present then the PHY applies the TX delay.
tx-amplitude-100base-tx-percent:
description:
Transmit amplitude gain applied for 100BASE-TX. 100% matches 2V
peak-to-peak specified in ANSI X3.263. When omitted, the PHYs default
will be left as is.
leds:
type: object

View File

@@ -44,6 +44,9 @@ properties:
phy-mode:
enum:
- rgmii
- rgmii-id
- rgmii-rxid
- rgmii-txid
- rmii
phy-handle: true

View File

@@ -0,0 +1,112 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/net/fsl,gianfar-mdio.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Freescale Gianfar (TSEC) MDIO Device
description:
This binding describes the MDIO is a bus to which the PHY devices are
connected. For each device that exists on this bus, a child node should be
created.
Some TSECs are associated with an internal Ten-Bit Interface (TBI) PHY. This
PHY is accessed through the local MDIO bus. These buses are defined similarly
to the mdio buses, except they are compatible with "fsl,gianfar-tbi". The TBI
PHYs underneath them are similar to normal PHYs, but the reg property is
considered instructive, rather than descriptive. The reg property should be
chosen so it doesn't interfere with other PHYs on the bus.
maintainers:
- J. Neuschäfer <j.ne@posteo.net>
# This is needed to distinguish gianfar.yaml and gianfar-mdio.yaml, because
# both use compatible = "gianfar" (with different device_type values)
select:
oneOf:
- properties:
compatible:
contains:
const: gianfar
device_type:
const: mdio
required:
- device_type
- properties:
compatible:
contains:
enum:
- fsl,gianfar-tbi
- fsl,gianfar-mdio
- fsl,etsec2-tbi
- fsl,etsec2-mdio
- fsl,ucc-mdio
- ucc_geth_phy
required:
- compatible
properties:
compatible:
enum:
- fsl,gianfar-tbi
- fsl,gianfar-mdio
- fsl,etsec2-tbi
- fsl,etsec2-mdio
- fsl,ucc-mdio
- gianfar
- ucc_geth_phy
reg:
minItems: 1
items:
- description:
Offset and length of the register set for the device
- description:
Optionally, the offset and length of the TBIPA register (TBI PHY
address register). If TBIPA register is not specified, the driver
will attempt to infer it from the register set specified (your
mileage may vary).
device_type:
const: mdio
required:
- reg
- "#address-cells"
- "#size-cells"
allOf:
- $ref: mdio.yaml#
- if:
properties:
compatible:
contains:
const: ucc_geth_phy
then:
required:
- device_type
unevaluatedProperties: false
examples:
- |
soc {
#address-cells = <1>;
#size-cells = <1>;
mdio@24520 {
reg = <0x24520 0x20>;
compatible = "fsl,gianfar-mdio";
#address-cells = <1>;
#size-cells = <0>;
ethernet-phy@0 {
reg = <0>;
};
};
};

View File

@@ -0,0 +1,248 @@
# SPDX-License-Identifier: GPL-2.0
%YAML 1.2
---
$id: http://devicetree.org/schemas/net/fsl,gianfar.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Freescale Three-Speed Ethernet Controller (TSEC), "Gianfar"
maintainers:
- J. Neuschäfer <j.ne@posteo.net>
# This is needed to distinguish gianfar.yaml and gianfar-mdio.yaml, because
# both use compatible = "gianfar" (with different device_type values)
select:
oneOf:
- properties:
compatible:
contains:
const: gianfar
device_type:
const: network
required:
- device_type
- properties:
compatible:
const: fsl,etsec2
required:
- compatible
properties:
compatible:
enum:
- gianfar
- fsl,etsec2
device_type:
const: network
model:
enum:
- FEC
- TSEC
- eTSEC
reg:
maxItems: 1
ranges: true
"#address-cells":
enum: [ 1, 2 ]
"#size-cells":
enum: [ 1, 2 ]
cell-index:
$ref: /schemas/types.yaml#/definitions/uint32
interrupts:
minItems: 1
items:
- description: Transmit interrupt or single combined interrupt
- description: Receive interrupt
- description: Error interrupt
dma-coherent: true
fsl,magic-packet:
type: boolean
description:
If present, indicates that the hardware supports waking up via magic packet.
fsl,wake-on-filer:
type: boolean
description:
If present, indicates that the hardware supports waking up by Filer
General Purpose Interrupt (FGPI) asserted on the Rx int line. This is
an advanced power management capability allowing certain packet types
(user) defined by filer rules to wake up the system.
bd-stash:
type: boolean
description:
If present, indicates that the hardware supports stashing buffer
descriptors in the L2.
rx-stash-len:
$ref: /schemas/types.yaml#/definitions/uint32
description:
Denotes the number of bytes of a received buffer to stash in the L2.
rx-stash-idx:
$ref: /schemas/types.yaml#/definitions/uint32
description:
Denotes the index of the first byte from the received buffer to stash in
the L2.
fsl,num_rx_queues:
$ref: /schemas/types.yaml#/definitions/uint32
description: Number of receive queues
const: 8
fsl,num_tx_queues:
$ref: /schemas/types.yaml#/definitions/uint32
description: Number of transmit queues
const: 8
tbi-handle:
$ref: /schemas/types.yaml#/definitions/phandle
description: Reference (phandle) to the TBI node
required:
- compatible
- model
patternProperties:
"^mdio@[0-9a-f]+$":
$ref: /schemas/net/fsl,gianfar-mdio.yaml#
allOf:
- $ref: ethernet-controller.yaml#
# eTSEC2 controller nodes have "queue group" subnodes and don't need a "reg"
# property.
- if:
properties:
compatible:
contains:
const: fsl,etsec2
then:
patternProperties:
"^queue-group@[0-9a-f]+$":
type: object
properties:
reg:
maxItems: 1
interrupts:
items:
- description: Transmit interrupt
- description: Receive interrupt
- description: Error interrupt
required:
- reg
- interrupts
additionalProperties: false
else:
required:
- reg
# TSEC and eTSEC devices require three interrupts
- if:
properties:
model:
contains:
enum: [ TSEC, eTSEC ]
then:
properties:
interrupts:
items:
- description: Transmit interrupt
- description: Receive interrupt
- description: Error interrupt
unevaluatedProperties: false
examples:
- |
ethernet@24000 {
device_type = "network";
model = "TSEC";
compatible = "gianfar";
reg = <0x24000 0x1000>;
local-mac-address = [ 00 00 00 00 00 00 ];
interrupts = <29 2>, <30 2>, <34 2>;
interrupt-parent = <&mpic>;
phy-handle = <&phy0>;
};
- |
#include <dt-bindings/interrupt-controller/irq.h>
ethernet@24000 {
compatible = "gianfar";
reg = <0x24000 0x1000>;
ranges = <0x0 0x24000 0x1000>;
#address-cells = <1>;
#size-cells = <1>;
cell-index = <0>;
device_type = "network";
model = "eTSEC";
local-mac-address = [ 00 00 00 00 00 00 ];
interrupts = <32 IRQ_TYPE_LEVEL_LOW>,
<33 IRQ_TYPE_LEVEL_LOW>,
<34 IRQ_TYPE_LEVEL_LOW>;
interrupt-parent = <&ipic>;
mdio@520 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "fsl,gianfar-mdio";
reg = <0x520 0x20>;
};
};
- |
#include <dt-bindings/interrupt-controller/irq.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
bus {
#address-cells = <2>;
#size-cells = <2>;
ethernet {
compatible = "fsl,etsec2";
ranges;
device_type = "network";
#address-cells = <2>;
#size-cells = <2>;
interrupt-parent = <&gic>;
model = "eTSEC";
fsl,magic-packet;
dma-coherent;
queue-group@2d10000 {
reg = <0x0 0x2d10000 0x0 0x1000>;
interrupts = <GIC_SPI 144 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 145 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 146 IRQ_TYPE_LEVEL_HIGH>;
};
queue-group@2d14000 {
reg = <0x0 0x2d14000 0x0 0x1000>;
interrupts = <GIC_SPI 147 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 148 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 149 IRQ_TYPE_LEVEL_HIGH>;
};
};
};
...

View File

@@ -1,88 +1,14 @@
* MDIO IO device
The MDIO is a bus to which the PHY devices are connected. For each
device that exists on this bus, a child node should be created. See
the definition of the PHY node in booting-without-of.txt for an example
of how to define a PHY.
Required properties:
- reg : Offset and length of the register set for the device, and optionally
the offset and length of the TBIPA register (TBI PHY address
register). If TBIPA register is not specified, the driver will
attempt to infer it from the register set specified (your mileage may
vary).
- compatible : Should define the compatible device type for the
mdio. Currently supported strings/devices are:
- "fsl,gianfar-tbi"
- "fsl,gianfar-mdio"
- "fsl,etsec2-tbi"
- "fsl,etsec2-mdio"
- "fsl,ucc-mdio"
- "fsl,fman-mdio"
When device_type is "mdio", the following strings are also considered:
- "gianfar"
- "ucc_geth_phy"
Example:
mdio@24520 {
reg = <24520 20>;
compatible = "fsl,gianfar-mdio";
ethernet-phy@0 {
......
};
};
Refer to Documentation/devicetree/bindings/net/fsl,gianfar-mdio.yaml
* TBI Internal MDIO bus
As of this writing, every tsec is associated with an internal TBI PHY.
This PHY is accessed through the local MDIO bus. These buses are defined
similarly to the mdio buses, except they are compatible with "fsl,gianfar-tbi".
The TBI PHYs underneath them are similar to normal PHYs, but the reg property
is considered instructive, rather than descriptive. The reg property should
be chosen so it doesn't interfere with other PHYs on the bus.
Refer to Documentation/devicetree/bindings/net/fsl,gianfar-mdio.yaml
* Gianfar-compatible ethernet nodes
Properties:
- device_type : Should be "network"
- model : Model of the device. Can be "TSEC", "eTSEC", or "FEC"
- compatible : Should be "gianfar"
- reg : Offset and length of the register set for the device
- interrupts : For FEC devices, the first interrupt is the device's
interrupt. For TSEC and eTSEC devices, the first interrupt is
transmit, the second is receive, and the third is error.
- phy-handle : See ethernet.txt file in the same directory.
- fixed-link : See fixed-link.txt in the same directory.
- phy-connection-type : See ethernet.txt file in the same directory.
This property is only really needed if the connection is of type
"rgmii-id", as all other connection types are detected by hardware.
- fsl,magic-packet : If present, indicates that the hardware supports
waking up via magic packet.
- fsl,wake-on-filer : If present, indicates that the hardware supports
waking up by Filer General Purpose Interrupt (FGPI) asserted on the
Rx int line. This is an advanced power management capability allowing
certain packet types (user) defined by filer rules to wake up the system.
- bd-stash : If present, indicates that the hardware supports stashing
buffer descriptors in the L2.
- rx-stash-len : Denotes the number of bytes of a received buffer to stash
in the L2.
- rx-stash-idx : Denotes the index of the first byte from the received
buffer to stash in the L2.
Example:
ethernet@24000 {
device_type = "network";
model = "TSEC";
compatible = "gianfar";
reg = <0x24000 0x1000>;
local-mac-address = [ 00 E0 0C 00 73 00 ];
interrupts = <29 2 30 2 34 2>;
interrupt-parent = <&mpic>;
phy-handle = <&phy0>
};
Refer to Documentation/devicetree/bindings/net/fsl,gianfar.yaml
* Gianfar PTP clock nodes

View File

@@ -20,7 +20,7 @@ Example:
reg = <0>;
spi-max-frequency = <3000000>;
spi-cpol;
reset-gpio = <&gpio1 1 GPIO_ACTIVE_HIGH>;
reset-gpio = <&gpio1 1 GPIO_ACTIVE_LOW>;
irq-gpio = <&gpio1 2 GPIO_ACTIVE_HIGH>;
extclock-enable;
extclock-freq = 16000000;

View File

@@ -41,6 +41,12 @@ properties:
- const: ptp_ref
- const: tx_clk
interrupts:
maxItems: 1
interrupt-names:
const: macirq
required:
- compatible
- clocks

View File

@@ -64,6 +64,12 @@ properties:
- const: rmii_internal
- const: mac_cg
interrupts:
maxItems: 1
interrupt-names:
const: macirq
power-domains:
maxItems: 1

View File

@@ -56,6 +56,14 @@ properties:
- tx
- mem
interrupts:
maxItems: 2
interrupt-names:
items:
- const: macirq
- const: eth_wake_irq
intf_mode:
$ref: /schemas/types.yaml#/definitions/phandle-array
items:

View File

@@ -210,70 +210,70 @@ additionalProperties: false
examples:
- |
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/clock/qcom,rpmh.h>
#include <dt-bindings/interconnect/qcom,sdm845.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/clock/qcom,rpmh.h>
#include <dt-bindings/interconnect/qcom,sdm845.h>
smp2p-mpss {
compatible = "qcom,smp2p";
interrupts = <GIC_SPI 576 IRQ_TYPE_EDGE_RISING>;
mboxes = <&apss_shared 6>;
qcom,smem = <94>, <432>;
qcom,local-pid = <0>;
qcom,remote-pid = <5>;
smp2p-mpss {
compatible = "qcom,smp2p";
interrupts = <GIC_SPI 576 IRQ_TYPE_EDGE_RISING>;
mboxes = <&apss_shared 6>;
qcom,smem = <94>, <432>;
qcom,local-pid = <0>;
qcom,remote-pid = <5>;
ipa_smp2p_out: ipa-ap-to-modem {
qcom,entry-name = "ipa";
#qcom,smem-state-cells = <1>;
};
ipa_smp2p_in: ipa-modem-to-ap {
qcom,entry-name = "ipa";
interrupt-controller;
#interrupt-cells = <2>;
};
ipa_smp2p_out: ipa-ap-to-modem {
qcom,entry-name = "ipa";
#qcom,smem-state-cells = <1>;
};
ipa@1e40000 {
compatible = "qcom,sc7180-ipa";
qcom,gsi-loader = "self";
memory-region = <&ipa_fw_mem>;
firmware-name = "qcom/sc7180-trogdor/modem/modem.mbn";
iommus = <&apps_smmu 0x440 0x0>,
<&apps_smmu 0x442 0x0>;
reg = <0x1e40000 0x7000>,
<0x1e47000 0x2000>,
<0x1e04000 0x2c000>;
reg-names = "ipa-reg",
"ipa-shared",
"gsi";
interrupts-extended = <&intc GIC_SPI 311 IRQ_TYPE_EDGE_RISING>,
<&intc GIC_SPI 432 IRQ_TYPE_LEVEL_HIGH>,
<&ipa_smp2p_in 0 IRQ_TYPE_EDGE_RISING>,
<&ipa_smp2p_in 1 IRQ_TYPE_EDGE_RISING>;
interrupt-names = "ipa",
"gsi",
"ipa-clock-query",
"ipa-setup-ready";
clocks = <&rpmhcc RPMH_IPA_CLK>;
clock-names = "core";
interconnects =
<&aggre2_noc MASTER_IPA 0 &mc_virt SLAVE_EBI1 0>,
<&aggre2_noc MASTER_IPA 0 &system_noc SLAVE_IMEM 0>,
<&gem_noc MASTER_APPSS_PROC 0 &config_noc SLAVE_IPA_CFG 0>;
interconnect-names = "memory",
"imem",
"config";
qcom,qmp = <&aoss_qmp>;
qcom,smem-states = <&ipa_smp2p_out 0>,
<&ipa_smp2p_out 1>;
qcom,smem-state-names = "ipa-clock-enabled-valid",
"ipa-clock-enabled";
ipa_smp2p_in: ipa-modem-to-ap {
qcom,entry-name = "ipa";
interrupt-controller;
#interrupt-cells = <2>;
};
};
ipa@1e40000 {
compatible = "qcom,sc7180-ipa";
qcom,gsi-loader = "self";
memory-region = <&ipa_fw_mem>;
firmware-name = "qcom/sc7180-trogdor/modem/modem.mbn";
iommus = <&apps_smmu 0x440 0x0>,
<&apps_smmu 0x442 0x0>;
reg = <0x1e40000 0x7000>,
<0x1e47000 0x2000>,
<0x1e04000 0x2c000>;
reg-names = "ipa-reg",
"ipa-shared",
"gsi";
interrupts-extended = <&intc GIC_SPI 311 IRQ_TYPE_EDGE_RISING>,
<&intc GIC_SPI 432 IRQ_TYPE_LEVEL_HIGH>,
<&ipa_smp2p_in 0 IRQ_TYPE_EDGE_RISING>,
<&ipa_smp2p_in 1 IRQ_TYPE_EDGE_RISING>;
interrupt-names = "ipa",
"gsi",
"ipa-clock-query",
"ipa-setup-ready";
clocks = <&rpmhcc RPMH_IPA_CLK>;
clock-names = "core";
interconnects =
<&aggre2_noc MASTER_IPA 0 &mc_virt SLAVE_EBI1 0>,
<&aggre2_noc MASTER_IPA 0 &system_noc SLAVE_IMEM 0>,
<&gem_noc MASTER_APPSS_PROC 0 &config_noc SLAVE_IPA_CFG 0>;
interconnect-names = "memory",
"imem",
"config";
qcom,qmp = <&aoss_qmp>;
qcom,smem-states = <&ipa_smp2p_out 0>,
<&ipa_smp2p_out 1>;
qcom,smem-state-names = "ipa-clock-enabled-valid",
"ipa-clock-enabled";
};

View File

@@ -0,0 +1,86 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/net/realtek,rtl9301-mdio.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Realtek RTL9300 MDIO Controller
maintainers:
- Chris Packham <chris.packham@alliedtelesis.co.nz>
properties:
compatible:
oneOf:
- items:
- enum:
- realtek,rtl9302b-mdio
- realtek,rtl9302c-mdio
- realtek,rtl9303-mdio
- const: realtek,rtl9301-mdio
- const: realtek,rtl9301-mdio
'#address-cells':
const: 1
'#size-cells':
const: 0
reg:
maxItems: 1
patternProperties:
'^mdio-bus@[0-3]$':
$ref: mdio.yaml#
properties:
reg:
maxItems: 1
required:
- reg
patternProperties:
'^ethernet-phy@[a-f0-9]+$':
type: object
$ref: ethernet-phy.yaml#
unevaluatedProperties: false
unevaluatedProperties: false
required:
- compatible
- reg
unevaluatedProperties: false
examples:
- |
mdio-controller@ca00 {
compatible = "realtek,rtl9301-mdio";
reg = <0xca00 0x200>;
#address-cells = <1>;
#size-cells = <0>;
mdio-bus@0 {
reg = <0>;
#address-cells = <1>;
#size-cells = <0>;
ethernet-phy@0 {
compatible = "ethernet-phy-ieee802.3-c45";
reg = <0>;
};
};
mdio-bus@1 {
reg = <1>;
#address-cells = <1>;
#size-cells = <0>;
ethernet-phy@0 {
compatible = "ethernet-phy-ieee802.3-c45";
reg = <0>;
};
};
};

View File

@@ -1,7 +1,7 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/mfd/realtek,rtl9301-switch.yaml#
$id: http://devicetree.org/schemas/net/realtek,rtl9301-switch.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Realtek Switch with Internal CPU
@@ -14,6 +14,8 @@ description:
number of different peripherals are accessed through a common register block,
represented here as a syscon node.
$ref: ethernet-switch.yaml#/$defs/ethernet-ports
properties:
compatible:
items:
@@ -28,12 +30,23 @@ properties:
reg:
maxItems: 1
interrupts:
maxItems: 2
interrupt-names:
items:
- const: switch
- const: nic
'#address-cells':
const: 1
'#size-cells':
const: 1
ethernet-ports:
type: object
patternProperties:
'reboot@[0-9a-f]+$':
$ref: /schemas/power/reset/syscon-reboot.yaml#
@@ -41,9 +54,14 @@ patternProperties:
'i2c@[0-9a-f]+$':
$ref: /schemas/i2c/realtek,rtl9301-i2c.yaml#
'mdio-controller@[0-9a-f]+$':
$ref: realtek,rtl9301-mdio.yaml#
required:
- compatible
- reg
- interrupts
- interrupt-names
additionalProperties: false
@@ -52,6 +70,9 @@ examples:
ethernet-switch@1b000000 {
compatible = "realtek,rtl9301-switch", "syscon", "simple-mfd";
reg = <0x1b000000 0x10000>;
interrupt-parent = <&intc>;
interrupts = <23>, <24>;
interrupt-names = "switch", "nic";
#address-cells = <1>;
#size-cells = <1>;
@@ -110,5 +131,45 @@ examples:
};
};
};
mdio-controller@ca00 {
compatible = "realtek,rtl9301-mdio";
reg = <0xca00 0x200>;
#address-cells = <1>;
#size-cells = <0>;
mdio-bus@0 {
reg = <0>;
#address-cells = <1>;
#size-cells = <0>;
phy1: ethernet-phy@0 {
reg = <0>;
};
};
mdio-bus@1 {
reg = <1>;
#address-cells = <1>;
#size-cells = <0>;
phy2: ethernet-phy@0 {
reg = <0>;
};
};
};
ethernet-ports {
#address-cells = <1>;
#size-cells = <0>;
port@0 {
reg = <0>;
phy-handle = <&phy1>;
};
port@1 {
reg = <1>;
phy-handle = <&phy2>;
};
};
};

View File

@@ -32,6 +32,10 @@ properties:
shutdown-gpios:
maxItems: 1
default-blocked:
$ref: /schemas/types.yaml#/definitions/flag
description: configure rfkill state as blocked at boot
required:
- compatible
- radio-type
@@ -48,4 +52,5 @@ examples:
label = "rfkill-pcie-wlan";
radio-type = "wlan";
shutdown-gpios = <&gpio2 25 GPIO_ACTIVE_HIGH>;
default-blocked;
};

View File

@@ -24,6 +24,7 @@ select:
- rockchip,rk3366-gmac
- rockchip,rk3368-gmac
- rockchip,rk3399-gmac
- rockchip,rk3528-gmac
- rockchip,rk3568-gmac
- rockchip,rk3576-gmac
- rockchip,rk3588-gmac
@@ -32,9 +33,6 @@ select:
required:
- compatible
allOf:
- $ref: snps,dwmac.yaml#
properties:
compatible:
oneOf:
@@ -52,14 +50,25 @@ properties:
- rockchip,rv1108-gmac
- items:
- enum:
- rockchip,rk3528-gmac
- rockchip,rk3568-gmac
- rockchip,rk3576-gmac
- rockchip,rk3588-gmac
- rockchip,rv1126-gmac
- const: snps,dwmac-4.20a
interrupts:
minItems: 1
maxItems: 2
interrupt-names:
minItems: 1
items:
- const: macirq
- const: eth_wake_irq
clocks:
minItems: 5
minItems: 4
maxItems: 8
clock-names:
@@ -114,6 +123,36 @@ required:
- compatible
- clocks
- clock-names
- rockchip,grf
allOf:
- $ref: snps,dwmac.yaml#
- if:
properties:
compatible:
contains:
enum:
- rockchip,rk3576-gmac
- rockchip,rk3588-gmac
then:
required:
- rockchip,php-grf
else:
properties:
rockchip,php-grf: false
- if:
not:
properties:
compatible:
contains:
enum:
- rockchip,rk3528-gmac
then:
properties:
clocks:
minItems: 5
unevaluatedProperties: false

View File

@@ -32,6 +32,7 @@ select:
- snps,dwmac-4.20a
- snps,dwmac-5.10a
- snps,dwmac-5.20
- snps,dwmac-5.30a
- snps,dwxgmac
- snps,dwxgmac-2.10
@@ -98,10 +99,13 @@ properties:
- snps,dwmac-4.20a
- snps,dwmac-5.10a
- snps,dwmac-5.20
- snps,dwmac-5.30a
- snps,dwxgmac
- snps,dwxgmac-2.10
- sophgo,sg2044-dwmac
- starfive,jh7100-dwmac
- starfive,jh7110-dwmac
- tesla,fsd-ethqos
- thead,th1520-gmac
reg:
@@ -126,7 +130,7 @@ properties:
clocks:
minItems: 1
maxItems: 8
maxItems: 10
additionalItems: true
items:
- description: GMAC main clock
@@ -138,7 +142,7 @@ properties:
clock-names:
minItems: 1
maxItems: 8
maxItems: 10
additionalItems: true
contains:
enum:
@@ -490,6 +494,7 @@ properties:
snps,en-tx-lpi-clockgating:
$ref: /schemas/types.yaml#/definitions/flag
deprecated: true
description:
Enable gating of the MAC TX clock during TX low-power mode
@@ -631,6 +636,7 @@ allOf:
- snps,dwmac-4.20a
- snps,dwmac-5.10a
- snps,dwmac-5.20
- snps,dwmac-5.30a
- snps,dwxgmac
- snps,dwxgmac-2.10
- st,spear600-gmac

View File

@@ -0,0 +1,126 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/net/sophgo,sg2044-dwmac.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Sophgo SG2044 DWMAC glue layer
maintainers:
- Inochi Amaoto <inochiama@gmail.com>
select:
properties:
compatible:
contains:
enum:
- sophgo,sg2044-dwmac
required:
- compatible
properties:
compatible:
items:
- const: sophgo,sg2044-dwmac
- const: snps,dwmac-5.30a
reg:
maxItems: 1
clocks:
items:
- description: GMAC main clock
- description: PTP clock
- description: TX clock
clock-names:
items:
- const: stmmaceth
- const: ptp_ref
- const: tx
dma-noncoherent: true
interrupts:
maxItems: 1
interrupt-names:
maxItems: 1
resets:
maxItems: 1
reset-names:
const: stmmaceth
required:
- compatible
- reg
- clocks
- clock-names
- interrupts
- interrupt-names
- resets
- reset-names
allOf:
- $ref: snps,dwmac.yaml#
unevaluatedProperties: false
examples:
- |
#include <dt-bindings/interrupt-controller/irq.h>
ethernet@30006000 {
compatible = "sophgo,sg2044-dwmac", "snps,dwmac-5.30a";
reg = <0x30006000 0x4000>;
clocks = <&clk 151>, <&clk 152>, <&clk 154>;
clock-names = "stmmaceth", "ptp_ref", "tx";
interrupt-parent = <&intc>;
interrupts = <296 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "macirq";
resets = <&rst 30>;
reset-names = "stmmaceth";
snps,multicast-filter-bins = <0>;
snps,perfect-filter-entries = <1>;
snps,aal;
snps,tso;
snps,txpbl = <32>;
snps,rxpbl = <32>;
snps,mtl-rx-config = <&gmac0_mtl_rx_setup>;
snps,mtl-tx-config = <&gmac0_mtl_tx_setup>;
snps,axi-config = <&gmac0_stmmac_axi_setup>;
status = "disabled";
gmac0_mtl_rx_setup: rx-queues-config {
snps,rx-queues-to-use = <8>;
snps,rx-sched-wsp;
queue0 {};
queue1 {};
queue2 {};
queue3 {};
queue4 {};
queue5 {};
queue6 {};
queue7 {};
};
gmac0_mtl_tx_setup: tx-queues-config {
snps,tx-queues-to-use = <8>;
queue0 {};
queue1 {};
queue2 {};
queue3 {};
queue4 {};
queue5 {};
queue6 {};
queue7 {};
};
gmac0_stmmac_axi_setup: stmmac-axi-config {
snps,blen = <16 8 4 0 0 0 0>;
snps,wr_osr_lmt = <1>;
snps,rd_osr_lmt = <2>;
};
};

View File

@@ -54,6 +54,16 @@ properties:
items:
- const: stmmaceth
interrupts:
minItems: 1
maxItems: 2
interrupt-names:
minItems: 1
items:
- const: macirq
- const: eth_wake_irq
clocks:
minItems: 3
items:

View File

@@ -0,0 +1,118 @@
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
%YAML 1.2
---
$id: http://devicetree.org/schemas/net/tesla,fsd-ethqos.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: FSD Ethernet Quality of Service
maintainers:
- Swathi K S <swathi.ks@samsung.com>
description:
Tesla ethernet devices based on dwmmac support Gigabit ethernet.
allOf:
- $ref: snps,dwmac.yaml#
properties:
compatible:
const: tesla,fsd-ethqos
reg:
maxItems: 1
interrupts:
maxItems: 1
interrupt-names:
items:
- const: macirq
clocks:
minItems: 5
items:
- description: PTP clock
- description: Master bus clock
- description: Slave bus clock
- description: MAC TX clock
- description: MAC RX clock
- description: Master2 bus clock
- description: Slave2 bus clock
- description: RX MUX clock
- description: PHY RX clock
- description: PERIC RGMII clock
clock-names:
minItems: 5
items:
- const: ptp_ref
- const: master_bus
- const: slave_bus
- const: tx
- const: rx
- const: master2_bus
- const: slave2_bus
- const: eqos_rxclk_mux
- const: eqos_phyrxclk
- const: dout_peric_rgmii_clk
iommus:
maxItems: 1
phy-mode:
enum:
- rgmii
- rgmii-id
- rgmii-rxid
- rgmii-txid
required:
- compatible
- reg
- interrupts
- clocks
- clock-names
- iommus
- phy-mode
unevaluatedProperties: false
examples:
- |
#include <dt-bindings/clock/fsd-clk.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
soc {
#address-cells = <2>;
#size-cells = <2>;
ethernet1: ethernet@14300000 {
compatible = "tesla,fsd-ethqos";
reg = <0x0 0x14300000 0x0 0x10000>;
interrupts = <GIC_SPI 176 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "macirq";
clocks = <&clock_peric PERIC_EQOS_TOP_IPCLKPORT_CLK_PTP_REF_I>,
<&clock_peric PERIC_EQOS_TOP_IPCLKPORT_ACLK_I>,
<&clock_peric PERIC_EQOS_TOP_IPCLKPORT_HCLK_I>,
<&clock_peric PERIC_EQOS_TOP_IPCLKPORT_RGMII_CLK_I>,
<&clock_peric PERIC_EQOS_TOP_IPCLKPORT_CLK_RX_I>,
<&clock_peric PERIC_BUS_D_PERIC_IPCLKPORT_EQOSCLK>,
<&clock_peric PERIC_BUS_P_PERIC_IPCLKPORT_EQOSCLK>,
<&clock_peric PERIC_EQOS_PHYRXCLK_MUX>,
<&clock_peric PERIC_EQOS_PHYRXCLK>,
<&clock_peric PERIC_DOUT_RGMII_CLK>;
clock-names = "ptp_ref", "master_bus", "slave_bus","tx",
"rx", "master2_bus", "slave2_bus", "eqos_rxclk_mux",
"eqos_phyrxclk","dout_peric_rgmii_clk";
assigned-clocks = <&clock_peric PERIC_EQOS_PHYRXCLK_MUX>,
<&clock_peric PERIC_EQOS_PHYRXCLK>;
assigned-clock-parents = <&clock_peric PERIC_EQOS_PHYRXCLK>;
pinctrl-names = "default";
pinctrl-0 = <&eth1_tx_clk>, <&eth1_tx_data>, <&eth1_tx_ctrl>,
<&eth1_phy_intr>, <&eth1_rx_clk>, <&eth1_rx_data>,
<&eth1_rx_ctrl>, <&eth1_mdio>;
iommus = <&smmu_peric 0x0 0x1>;
phy-mode = "rgmii-id";
};
};
...

View File

@@ -42,6 +42,12 @@ properties:
- const: stmmaceth
- const: phy_ref_clk
interrupts:
maxItems: 1
interrupt-names:
const: macirq
required:
- compatible
- reg

View File

@@ -92,20 +92,41 @@ properties:
ieee80211-freq-limit: true
qcom,ath10k-calibration-data:
qcom,calibration-data:
$ref: /schemas/types.yaml#/definitions/uint8-array
description:
Calibration data + board-specific data as a byte array. The length
can vary between hardware versions.
qcom,ath10k-calibration-variant:
qcom,ath10k-calibration-data:
$ref: /schemas/types.yaml#/definitions/uint8-array
deprecated: true
description:
Calibration data + board-specific data as a byte array. The length
can vary between hardware versions.
qcom,calibration-variant:
$ref: /schemas/types.yaml#/definitions/string
description:
Unique variant identifier of the calibration data in board-2.bin
for designs with colliding bus and device specific ids
qcom,ath10k-calibration-variant:
$ref: /schemas/types.yaml#/definitions/string
deprecated: true
description:
Unique variant identifier of the calibration data in board-2.bin
for designs with colliding bus and device specific ids
qcom,pre-calibration-data:
$ref: /schemas/types.yaml#/definitions/uint8-array
description:
Pre-calibration data as a byte array. The length can vary between
hardware versions.
qcom,ath10k-pre-calibration-data:
$ref: /schemas/types.yaml#/definitions/uint8-array
deprecated: true
description:
Pre-calibration data as a byte array. The length can vary between
hardware versions.

View File

@@ -22,8 +22,15 @@ properties:
reg:
maxItems: 1
qcom,calibration-variant:
$ref: /schemas/types.yaml#/definitions/string
description: |
string to uniquely identify variant of the calibration data for designs
with colliding bus and device ids
qcom,ath11k-calibration-variant:
$ref: /schemas/types.yaml#/definitions/string
deprecated: true
description: |
string to uniquely identify variant of the calibration data for designs
with colliding bus and device ids
@@ -127,7 +134,7 @@ examples:
vddrfa1p2-supply = <&vreg_pmu_rfa_1p2>;
vddrfa1p8-supply = <&vreg_pmu_rfa_1p7>;
qcom,ath11k-calibration-variant = "LE_X13S";
qcom,calibration-variant = "LE_X13S";
};
};
};

View File

@@ -41,8 +41,15 @@ properties:
* reg
* reg-names
qcom,calibration-variant:
$ref: /schemas/types.yaml#/definitions/string
description:
string to uniquely identify variant of the calibration data in the
board-2.bin for designs with colliding bus and device specific ids
qcom,ath11k-calibration-variant:
$ref: /schemas/types.yaml#/definitions/string
deprecated: true
description:
string to uniquely identify variant of the calibration data in the
board-2.bin for designs with colliding bus and device specific ids

View File

@@ -52,8 +52,15 @@ properties:
reg:
maxItems: 1
qcom,calibration-variant:
$ref: /schemas/types.yaml#/definitions/string
description:
String to uniquely identify variant of the calibration data for designs
with colliding bus and device ids
qcom,ath12k-calibration-variant:
$ref: /schemas/types.yaml#/definitions/string
deprecated: true
description:
String to uniquely identify variant of the calibration data for designs
with colliding bus and device ids
@@ -103,7 +110,7 @@ examples:
compatible = "pci17cb,1109";
reg = <0x0 0x0 0x0 0x0 0x0>;
qcom,ath12k-calibration-variant = "RDP433_1";
qcom,calibration-variant = "RDP433_1";
ports {
#address-cells = <1>;
@@ -139,7 +146,7 @@ examples:
compatible = "pci17cb,1109";
reg = <0x0 0x0 0x0 0x0 0x0>;
qcom,ath12k-calibration-variant = "RDP433_2";
qcom,calibration-variant = "RDP433_2";
qcom,wsi-controller;
ports {
@@ -176,7 +183,7 @@ examples:
compatible = "pci17cb,1109";
reg = <0x0 0x0 0x0 0x0 0x0>;
qcom,ath12k-calibration-variant = "RDP433_3";
qcom,calibration-variant = "RDP433_3";
ports {
#address-cells = <1>;

View File

@@ -14,9 +14,10 @@ $defs:
pattern: ^[0-9A-Za-z_-]+( - 1)?$
minimum: 0
len-or-limit:
# literal int or limit based on fixed-width type e.g. u8-min, u16-max, etc.
# literal int, const name, or limit based on fixed-width type
# e.g. u8-min, u16-max, etc.
type: [ string, integer ]
pattern: ^[su](8|16|32|64)-(min|max)$
pattern: ^[0-9A-Za-z_-]+$
minimum: 0
# Schema for specs
@@ -160,7 +161,7 @@ properties:
type: string
type: &attr-type
enum: [ unused, pad, flag, binary,
uint, sint, u8, u16, u32, u64, s32, s64,
uint, sint, u8, u16, u32, u64, s8, s16, s32, s64,
string, nest, indexed-array, nest-type-value ]
doc:
description: Documentation of the attribute.

View File

@@ -14,9 +14,10 @@ $defs:
pattern: ^[0-9A-Za-z_-]+( - 1)?$
minimum: 0
len-or-limit:
# literal int or limit based on fixed-width type e.g. u8-min, u16-max, etc.
# literal int, const name, or limit based on fixed-width type
# e.g. u8-min, u16-max, etc.
type: [ string, integer ]
pattern: ^[su](8|16|32|64)-(min|max)$
pattern: ^[0-9A-Za-z_-]+$
minimum: 0
# Schema for specs
@@ -151,6 +152,9 @@ properties:
the right formatting mechanism when displaying values of this
type.
enum: [ hex, mac, fddi, ipv4, ipv6, uuid ]
struct:
description: Name of the nested struct type.
type: string
# End genetlink-legacy
attribute-sets:
@@ -203,7 +207,7 @@ properties:
type: &attr-type
description: The netlink attribute type
enum: [ unused, pad, flag, binary, bitfield32,
uint, sint, u8, u16, u32, u64, s32, s64,
uint, sint, u8, u16, u32, u64, s8, s16, s32, s64,
string, nest, indexed-array, nest-type-value ]
doc:
description: Documentation of the attribute.

View File

@@ -14,9 +14,10 @@ $defs:
pattern: ^[0-9A-Za-z_-]+( - 1)?$
minimum: 0
len-or-limit:
# literal int or limit based on fixed-width type e.g. u8-min, u16-max, etc.
# literal int, const name, or limit based on fixed-width type
# e.g. u8-min, u16-max, etc.
type: [ string, integer ]
pattern: ^[su](8|16|32|64)-(min|max)$
pattern: ^[0-9A-Za-z_-]+$
minimum: 0
# Schema for specs
@@ -123,7 +124,7 @@ properties:
type: string
type: &attr-type
enum: [ unused, pad, flag, binary,
uint, sint, u8, u16, u32, u64, s32, s64,
uint, sint, u8, u16, u32, u64, s8, s16, s32, s64,
string, nest, indexed-array, nest-type-value ]
doc:
description: Documentation of the attribute.

View File

@@ -0,0 +1,643 @@
# SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause)
name: conntrack
protocol: netlink-raw
protonum: 12
doc:
Netfilter connection tracking subsystem over nfnetlink
definitions:
-
name: nfgenmsg
type: struct
members:
-
name: nfgen-family
type: u8
-
name: version
type: u8
-
name: res-id
byte-order: big-endian
type: u16
-
name: nf-ct-tcp-flags-mask
type: struct
members:
-
name: flags
type: u8
enum: nf-ct-tcp-flags
enum-as-flags: true
-
name: mask
type: u8
enum: nf-ct-tcp-flags
enum-as-flags: true
-
name: nf-ct-tcp-flags
type: flags
entries:
- window-scale
- sack-perm
- close-init
- be-liberal
- unacked
- maxack
- challenge-ack
- simultaneous-open
-
name: nf-ct-tcp-state
type: enum
entries:
- none
- syn-sent
- syn-recv
- established
- fin-wait
- close-wait
- last-ack
- time-wait
- close
- syn-sent2
- max
- ignore
- retrans
- unack
- timeout-max
-
name: nf-ct-sctp-state
type: enum
entries:
- none
- cloned
- cookie-wait
- cookie-echoed
- established
- shutdown-sent
- shutdown-received
- shutdown-ack-sent
- shutdown-heartbeat-sent
-
name: nf-ct-status
type: flags
entries:
- expected
- seen-reply
- assured
- confirmed
- src-nat
- dst-nat
- seq-adj
- src-nat-done
- dst-nat-done
- dying
- fixed-timeout
- template
- nat-clash
- helper
- offload
- hw-offload
attribute-sets:
-
name: counter-attrs
attributes:
-
name: packets
type: u64
byte-order: big-endian
-
name: bytes
type: u64
byte-order: big-endian
-
name: packets-old
type: u32
-
name: bytes-old
type: u32
-
name: pad
type: pad
-
name: tuple-proto-attrs
attributes:
-
name: proto-num
type: u8
doc: l4 protocol number
-
name: proto-src-port
type: u16
byte-order: big-endian
doc: l4 source port
-
name: proto-dst-port
type: u16
byte-order: big-endian
doc: l4 source port
-
name: proto-icmp-id
type: u16
byte-order: big-endian
doc: l4 icmp id
-
name: proto-icmp-type
type: u8
-
name: proto-icmp-code
type: u8
-
name: proto-icmpv6-id
type: u16
byte-order: big-endian
doc: l4 icmp id
-
name: proto-icmpv6-type
type: u8
-
name: proto-icmpv6-code
type: u8
-
name: tuple-ip-attrs
attributes:
-
name: ip-v4-src
type: u32
byte-order: big-endian
display-hint: ipv4
doc: ipv4 source address
-
name: ip-v4-dst
type: u32
byte-order: big-endian
display-hint: ipv4
doc: ipv4 destination address
-
name: ip-v6-src
type: binary
checks:
min-len: 16
byte-order: big-endian
display-hint: ipv6
doc: ipv6 source address
-
name: ip-v6-dst
type: binary
checks:
min-len: 16
byte-order: big-endian
display-hint: ipv6
doc: ipv6 destination address
-
name: tuple-attrs
attributes:
-
name: tuple-ip
type: nest
nested-attributes: tuple-ip-attrs
doc: conntrack l3 information
-
name: tuple-proto
type: nest
nested-attributes: tuple-proto-attrs
doc: conntrack l4 information
-
name: tuple-zone
type: u16
byte-order: big-endian
doc: conntrack zone id
-
name: protoinfo-tcp-attrs
attributes:
-
name: tcp-state
type: u8
enum: nf-ct-tcp-state
doc: tcp connection state
-
name: tcp-wscale-original
type: u8
doc: window scaling factor in original direction
-
name: tcp-wscale-reply
type: u8
doc: window scaling factor in reply direction
-
name: tcp-flags-original
type: binary
struct: nf-ct-tcp-flags-mask
-
name: tcp-flags-reply
type: binary
struct: nf-ct-tcp-flags-mask
-
name: protoinfo-dccp-attrs
attributes:
-
name: dccp-state
type: u8
doc: dccp connection state
-
name: dccp-role
type: u8
-
name: dccp-handshake-seq
type: u64
byte-order: big-endian
-
name: dccp-pad
type: pad
-
name: protoinfo-sctp-attrs
attributes:
-
name: sctp-state
type: u8
doc: sctp connection state
enum: nf-ct-sctp-state
-
name: vtag-original
type: u32
byte-order: big-endian
-
name: vtag-reply
type: u32
byte-order: big-endian
-
name: protoinfo-attrs
attributes:
-
name: protoinfo-tcp
type: nest
nested-attributes: protoinfo-tcp-attrs
doc: conntrack tcp state information
-
name: protoinfo-dccp
type: nest
nested-attributes: protoinfo-dccp-attrs
doc: conntrack dccp state information
-
name: protoinfo-sctp
type: nest
nested-attributes: protoinfo-sctp-attrs
doc: conntrack sctp state information
-
name: help-attrs
attributes:
-
name: help-name
type: string
doc: helper name
-
name: nat-proto-attrs
attributes:
-
name: nat-port-min
type: u16
byte-order: big-endian
-
name: nat-port-max
type: u16
byte-order: big-endian
-
name: nat-attrs
attributes:
-
name: nat-v4-minip
type: u32
byte-order: big-endian
-
name: nat-v4-maxip
type: u32
byte-order: big-endian
-
name: nat-v6-minip
type: binary
-
name: nat-v6-maxip
type: binary
-
name: nat-proto
type: nest
nested-attributes: nat-proto-attrs
-
name: seqadj-attrs
attributes:
-
name: correction-pos
type: u32
byte-order: big-endian
-
name: offset-before
type: u32
byte-order: big-endian
-
name: offset-after
type: u32
byte-order: big-endian
-
name: secctx-attrs
attributes:
-
name: secctx-name
type: string
-
name: synproxy-attrs
attributes:
-
name: isn
type: u32
byte-order: big-endian
-
name: its
type: u32
byte-order: big-endian
-
name: tsoff
type: u32
byte-order: big-endian
-
name: conntrack-attrs
attributes:
-
name: tuple-orig
type: nest
nested-attributes: tuple-attrs
doc: conntrack l3+l4 protocol information, original direction
-
name: tuple-reply
type: nest
nested-attributes: tuple-attrs
doc: conntrack l3+l4 protocol information, reply direction
-
name: status
type: u32
byte-order: big-endian
enum: nf-ct-status
enum-as-flags: true
doc: conntrack flag bits
-
name: protoinfo
type: nest
nested-attributes: protoinfo-attrs
-
name: help
type: nest
nested-attributes: help-attrs
-
name: nat-src
type: nest
nested-attributes: nat-attrs
-
name: timeout
type: u32
byte-order: big-endian
-
name: mark
type: u32
byte-order: big-endian
-
name: counters-orig
type: nest
nested-attributes: counter-attrs
-
name: counters-reply
type: nest
nested-attributes: counter-attrs
-
name: use
type: u32
byte-order: big-endian
-
name: id
type: u32
byte-order: big-endian
-
name: nat-dst
type: nest
nested-attributes: nat-attrs
-
name: tuple-master
type: nest
nested-attributes: tuple-attrs
-
name: seq-adj-orig
type: nest
nested-attributes: seqadj-attrs
-
name: seq-adj-reply
type: nest
nested-attributes: seqadj-attrs
-
name: secmark
type: binary
doc: obsolete
-
name: zone
type: u16
byte-order: big-endian
doc: conntrack zone id
-
name: secctx
type: nest
nested-attributes: secctx-attrs
-
name: timestamp
type: u64
byte-order: big-endian
-
name: mark-mask
type: u32
byte-order: big-endian
-
name: labels
type: binary
-
name: labels mask
type: binary
-
name: synproxy
type: nest
nested-attributes: synproxy-attrs
-
name: filter
type: nest
nested-attributes: tuple-attrs
-
name: status-mask
type: u32
byte-order: big-endian
enum: nf-ct-status
enum-as-flags: true
doc: conntrack flag bits to change
-
name: timestamp-event
type: u64
byte-order: big-endian
-
name: conntrack-stats-attrs
attributes:
-
name: searched
type: u32
byte-order: big-endian
doc: obsolete
-
name: found
type: u32
byte-order: big-endian
-
name: new
type: u32
byte-order: big-endian
doc: obsolete
-
name: invalid
type: u32
byte-order: big-endian
doc: obsolete
-
name: ignore
type: u32
byte-order: big-endian
doc: obsolete
-
name: delete
type: u32
byte-order: big-endian
doc: obsolete
-
name: delete-list
type: u32
byte-order: big-endian
doc: obsolete
-
name: insert
type: u32
byte-order: big-endian
-
name: insert-failed
type: u32
byte-order: big-endian
-
name: drop
type: u32
byte-order: big-endian
-
name: early-drop
type: u32
byte-order: big-endian
-
name: error
type: u32
byte-order: big-endian
-
name: search-restart
type: u32
byte-order: big-endian
-
name: clash-resolve
type: u32
byte-order: big-endian
-
name: chain-toolong
type: u32
byte-order: big-endian
operations:
enum-model: directional
list:
-
name: get
doc: get / dump entries
attribute-set: conntrack-attrs
fixed-header: nfgenmsg
do:
request:
value: 0x101
attributes:
- tuple-orig
- tuple-reply
- zone
reply:
value: 0x100
attributes:
- tuple-orig
- tuple-reply
- status
- protoinfo
- help
- nat-src
- nat-dst
- timeout
- mark
- counter-orig
- counter-reply
- use
- id
- nat-dst
- tuple-master
- seq-adj-orig
- seq-adj-reply
- zone
- secctx
- labels
- synproxy
dump:
request:
value: 0x101
attributes:
- nfgen-family
- mark
- filter
- status
- zone
reply:
value: 0x100
attributes:
- tuple-orig
- tuple-reply
- status
- protoinfo
- help
- nat-src
- nat-dst
- timeout
- mark
- counter-orig
- counter-reply
- use
- id
- nat-dst
- tuple-master
- seq-adj-orig
- seq-adj-reply
- zone
- secctx
- labels
- synproxy
-
name: get-stats
doc: dump pcpu conntrack stats
attribute-set: conntrack-stats-attrs
fixed-header: nfgenmsg
dump:
request:
value: 0x104
reply:
value: 0x104
attributes:
- searched
- found
- insert
- insert-failed
- drop
- early-drop
- error
- search-restart
- clash-resolve
- chain-toolong

View File

@@ -1868,6 +1868,7 @@ operations:
- info-version-fixed
- info-version-running
- info-version-stored
- info-board-serial-number
dump:
reply: *info-get-reply

View File

@@ -70,6 +70,10 @@ definitions:
name: tx-checksum
doc:
L3 checksum HW offload is supported by the driver.
-
name: tx-launch-time-fifo
doc:
Launch time HW offload is supported by the driver.
-
name: queue-type
type: enum
@@ -114,6 +118,9 @@ attribute-sets:
doc: Bitmask of enabled AF_XDP features.
type: u64
enum: xsk-flags
-
name: io-uring-provider-info
attributes: []
-
name: page-pool
attributes:
@@ -171,6 +178,11 @@ attribute-sets:
name: dmabuf
doc: ID of the dmabuf this page-pool is attached to.
type: u32
-
name: io-uring
doc: io-uring memory provider information.
type: nest
nested-attributes: io-uring-provider-info
-
name: page-pool-info
subset-of: page-pool
@@ -268,6 +280,9 @@ attribute-sets:
doc: The timeout, in nanoseconds, of how long to suspend irq
processing, if event polling finds events
type: uint
-
name: xsk-info
attributes: []
-
name: queue
attributes:
@@ -286,6 +301,9 @@ attribute-sets:
-
name: type
doc: Queue type as rx, tx. Each queue type defines a separate ID space.
XDP TX queues allocated in the kernel are not linked to NAPIs and
thus not listed. AF_XDP queues will have more information set in
the xsk attribute.
type: u32
enum: queue-type
-
@@ -296,7 +314,16 @@ attribute-sets:
name: dmabuf
doc: ID of the dmabuf attached to this queue, if any.
type: u32
-
name: io-uring
doc: io_uring memory provider information.
type: nest
nested-attributes: io-uring-provider-info
-
name: xsk
doc: XSK information for this queue, if any.
type: nest
nested-attributes: xsk-info
-
name: qstats
doc: |
@@ -444,6 +471,8 @@ attribute-sets:
name: tx-needs-csum
doc: |
Number of packets that required the device to calculate the checksum.
This counter includes the number of GSO wire packets for which device
calculated the L4 checksum.
type: uint
-
name: tx-hw-gso-packets
@@ -572,6 +601,7 @@ operations:
- inflight-mem
- detach-time
- dmabuf
- io-uring
dump:
reply: *pp-reply
config-cond: page-pool
@@ -637,6 +667,8 @@ operations:
- napi-id
- ifindex
- dmabuf
- io-uring
- xsk
dump:
request:
attributes:
@@ -713,8 +745,8 @@ operations:
- irq-suspend-timeout
kernel-family:
headers: [ "linux/list.h"]
sock-priv: struct list_head
headers: [ "net/netdev_netlink.h"]
sock-priv: struct netdev_nl_sock
mcast-groups:
list:

File diff suppressed because it is too large Load Diff

View File

@@ -168,6 +168,29 @@ operations:
reply:
value: 20
attributes: *ifaddr-all
-
name: getmaddrs
doc: Get / dump IPv4/IPv6 multicast addresses.
attribute-set: addr-attrs
fixed-header: ifaddrmsg
do:
request:
value: 58
attributes:
- ifa-family
- ifa-index
reply:
value: 58
attributes: &mcaddr-attrs
- ifa-multicast
- ifa-cacheinfo
dump:
request:
value: 58
- ifa-family
reply:
value: 58
attributes: *mcaddr-attrs
mcast-groups:
list:

View File

@@ -770,6 +770,18 @@ definitions:
-
name: to
type: u32
-
name: ifla-geneve-port-range
type: struct
members:
-
name: low
type: u16
byte-order: big-endian
-
name: high
type: u16
byte-order: big-endian
-
name: ifla-vf-mac
type: struct
@@ -1148,6 +1160,9 @@ attribute-sets:
name: max-pacing-offload-horizon
type: uint
doc: EDT offload horizon supported by the device (in nsec).
-
name: netns-immutable
type: u8
-
name: af-spec-attrs
attributes:
@@ -1915,6 +1930,10 @@ attribute-sets:
-
name: inner-proto-inherit
type: flag
-
name: port-range
type: binary
struct: ifla-geneve-port-range
-
name: linkinfo-iptun-attrs
name-prefix: ifla-iptun-

View File

@@ -182,6 +182,18 @@ attribute-sets:
type: u32
byte-order: big-endian
display-hint: hex
-
name: sport-mask
type: u16
display-hint: hex
-
name: dport-mask
type: u16
display-hint: hex
-
name: dscp-mask
type: u8
display-hint: hex
operations:
enum-model: directional
@@ -215,6 +227,9 @@ operations:
- dscp
- flowlabel
- flowlabel-mask
- sport-mask
- dport-mask
- dscp-mask
-
name: newrule-ntf
doc: Notify a rule creation

View File

@@ -27,7 +27,7 @@ Load the batman-adv module into your kernel::
$ insmod batman-adv.ko
The module is now waiting for activation. You must add some interfaces on which
batman-adv can operate. The batman-adv soft-interface can be created using the
batman-adv can operate. The batman-adv mesh-interface can be created using the
iproute2 tool ``ip``::
$ ip link add name bat0 type batadv

View File

@@ -1,18 +0,0 @@
.. SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
Cable Modem Device Drivers
==========================
Contents:
.. toctree::
:maxdepth: 2
sb1000
.. only:: subproject and html
Indices
=======
* :ref:`genindex`

View File

@@ -1,222 +0,0 @@
.. SPDX-License-Identifier: GPL-2.0
===================
SB100 device driver
===================
sb1000 is a module network device driver for the General Instrument (also known
as NextLevel) SURFboard1000 internal cable modem board. This is an ISA card
which is used by a number of cable TV companies to provide cable modem access.
It's a one-way downstream-only cable modem, meaning that your upstream net link
is provided by your regular phone modem.
This driver was written by Franco Venturi <fventuri@mediaone.net>. He deserves
a great deal of thanks for this wonderful piece of code!
Needed tools
============
Support for this device is now a part of the standard Linux kernel. The
driver source code file is drivers/net/sb1000.c. In addition to this
you will need:
1. The "cmconfig" program. This is a utility which supplements "ifconfig"
to configure the cable modem and network interface (usually called "cm0");
2. Several PPP scripts which live in /etc/ppp to make connecting via your
cable modem easy.
These utilities can be obtained from:
http://www.jacksonville.net/~fventuri/
in Franco's original source code distribution .tar.gz file. Support for
the sb1000 driver can be found at:
- http://web.archive.org/web/%2E/http://home.adelphia.net/~siglercm/sb1000.html
- http://web.archive.org/web/%2E/http://linuxpower.cx/~cable/
along with these utilities.
3. The standard isapnp tools. These are necessary to configure your SB1000
card at boot time (or afterwards by hand) since it's a PnP card.
If you don't have these installed as a standard part of your Linux
distribution, you can find them at:
http://www.roestock.demon.co.uk/isapnptools/
or check your Linux distribution binary CD or their web site. For help with
isapnp, pnpdump, or /etc/isapnp.conf, go to:
http://www.roestock.demon.co.uk/isapnptools/isapnpfaq.html
Using the driver
================
To make the SB1000 card work, follow these steps:
1. Run ``make config``, or ``make menuconfig``, or ``make xconfig``, whichever
you prefer, in the top kernel tree directory to set up your kernel
configuration. Make sure to say "Y" to "Prompt for development drivers"
and to say "M" to the sb1000 driver. Also say "Y" or "M" to all the standard
networking questions to get TCP/IP and PPP networking support.
2. **BEFORE** you build the kernel, edit drivers/net/sb1000.c. Make sure
to redefine the value of READ_DATA_PORT to match the I/O address used
by isapnp to access your PnP cards. This is the value of READPORT in
/etc/isapnp.conf or given by the output of pnpdump.
3. Build and install the kernel and modules as usual.
4. Boot your new kernel following the usual procedures.
5. Set up to configure the new SB1000 PnP card by capturing the output
of "pnpdump" to a file and editing this file to set the correct I/O ports,
IRQ, and DMA settings for all your PnP cards. Make sure none of the settings
conflict with one another. Then test this configuration by running the
"isapnp" command with your new config file as the input. Check for
errors and fix as necessary. (As an aside, I use I/O ports 0x110 and
0x310 and IRQ 11 for my SB1000 card and these work well for me. YMMV.)
Then save the finished config file as /etc/isapnp.conf for proper
configuration on subsequent reboots.
6. Download the original file sb1000-1.1.2.tar.gz from Franco's site or one of
the others referenced above. As root, unpack it into a temporary directory
and do a ``make cmconfig`` and then ``install -c cmconfig /usr/local/sbin``.
Don't do ``make install`` because it expects to find all the utilities built
and ready for installation, not just cmconfig.
7. As root, copy all the files under the ppp/ subdirectory in Franco's
tar file into /etc/ppp, being careful not to overwrite any files that are
already in there. Then modify ppp@gi-on to set the correct login name,
phone number, and frequency for the cable modem. Also edit pap-secrets
to specify your login name and password and any site-specific information
you need.
8. Be sure to modify /etc/ppp/firewall to use ipchains instead of
the older ipfwadm commands from the 2.0.x kernels. There's a neat utility to
convert ipfwadm commands to ipchains commands:
http://users.dhp.com/~whisper/ipfwadm2ipchains/
You may also wish to modify the firewall script to implement a different
firewalling scheme.
9. Start the PPP connection via the script /etc/ppp/ppp@gi-on. You must be
root to do this. It's better to use a utility like sudo to execute
frequently used commands like this with root permissions if possible. If you
connect successfully the cable modem interface will come up and you'll see a
driver message like this at the console::
cm0: sb1000 at (0x110,0x310), csn 1, S/N 0x2a0d16d8, IRQ 11.
sb1000.c:v1.1.2 6/01/98 (fventuri@mediaone.net)
The "ifconfig" command should show two new interfaces, ppp0 and cm0.
The command "cmconfig cm0" will give you information about the cable modem
interface.
10. Try pinging a site via ``ping -c 5 www.yahoo.com``, for example. You should
see packets received.
11. If you can't get site names (like www.yahoo.com) to resolve into
IP addresses (like 204.71.200.67), be sure your /etc/resolv.conf file
has no syntax errors and has the right nameserver IP addresses in it.
If this doesn't help, try something like ``ping -c 5 204.71.200.67`` to
see if the networking is running but the DNS resolution is where the
problem lies.
12. If you still have problems, go to the support web sites mentioned above
and read the information and documentation there.
Common problems
===============
1. Packets go out on the ppp0 interface but don't come back on the cm0
interface. It looks like I'm connected but I can't even ping any
numerical IP addresses. (This happens predominantly on Debian systems due
to a default boot-time configuration script.)
Solution
As root ``echo 0 > /proc/sys/net/ipv4/conf/cm0/rp_filter`` so it
can share the same IP address as the ppp0 interface. Note that this
command should probably be added to the /etc/ppp/cablemodem script
*right*between* the "/sbin/ifconfig" and "/sbin/cmconfig" commands.
You may need to do this to /proc/sys/net/ipv4/conf/ppp0/rp_filter as well.
If you do this to /proc/sys/net/ipv4/conf/default/rp_filter on each reboot
(in rc.local or some such) then any interfaces can share the same IP
addresses.
2. I get "unresolved symbol" error messages on executing ``insmod sb1000.o``.
Solution
You probably have a non-matching kernel source tree and
/usr/include/linux and /usr/include/asm header files. Make sure you
install the correct versions of the header files in these two directories.
Then rebuild and reinstall the kernel.
3. When isapnp runs it reports an error, and my SB1000 card isn't working.
Solution
There's a problem with later versions of isapnp using the "(CHECK)"
option in the lines that allocate the two I/O addresses for the SB1000 card.
This first popped up on RH 6.0. Delete "(CHECK)" for the SB1000 I/O addresses.
Make sure they don't conflict with any other pieces of hardware first! Then
rerun isapnp and go from there.
4. I can't execute the /etc/ppp/ppp@gi-on file.
Solution
As root do ``chmod ug+x /etc/ppp/ppp@gi-on``.
5. The firewall script isn't working (with 2.2.x and higher kernels).
Solution
Use the ipfwadm2ipchains script referenced above to convert the
/etc/ppp/firewall script from the deprecated ipfwadm commands to ipchains.
6. I'm getting *tons* of firewall deny messages in the /var/kern.log,
/var/messages, and/or /var/syslog files, and they're filling up my /var
partition!!!
Solution
First, tell your ISP that you're receiving DoS (Denial of Service)
and/or portscanning (UDP connection attempts) attacks! Look over the deny
messages to figure out what the attack is and where it's coming from. Next,
edit /etc/ppp/cablemodem and make sure the ",nobroadcast" option is turned on
to the "cmconfig" command (uncomment that line). If you're not receiving these
denied packets on your broadcast interface (IP address xxx.yyy.zzz.255
typically), then someone is attacking your machine in particular. Be careful
out there....
7. Everything seems to work fine but my computer locks up after a while
(and typically during a lengthy download through the cable modem)!
Solution
You may need to add a short delay in the driver to 'slow down' the
SURFboard because your PC might not be able to keep up with the transfer rate
of the SB1000. To do this, it's probably best to download Franco's
sb1000-1.1.2.tar.gz archive and build and install sb1000.o manually. You'll
want to edit the 'Makefile' and look for the 'SB1000_DELAY'
define. Uncomment those 'CFLAGS' lines (and comment out the default ones)
and try setting the delay to something like 60 microseconds with:
'-DSB1000_DELAY=60'. Then do ``make`` and as root ``make install`` and try
it out. If it still doesn't work or you like playing with the driver, you may
try other numbers. Remember though that the higher the delay, the slower the
driver (which slows down the rest of the PC too when it is actively
used). Thanks to Ed Daiga for this tip!
Credits
=======
This README came from Franco Venturi's original README file which is
still supplied with his driver .tar.gz archive. I and all other sb1000 users
owe Franco a tremendous "Thank you!" Additional thanks goes to Carl Patten
and Ralph Bonnell who are now managing the Linux SB1000 web site, and to
the SB1000 users who reported and helped debug the common problems listed
above.
Clemmitt Sigler
csigler@vt.edu

View File

@@ -70,7 +70,7 @@ the DPSW object that it will probe:
Besides the configuration of the actual DPSW object, the dpaa2-switch driver
will need the following DPAA2 objects:
* 1 DPMCP - A Management Command Portal object is needed for any interraction
* 1 DPMCP - A Management Command Portal object is needed for any interaction
with the MC firmware.
* 1 DPBP - A Buffer Pool is used for seeding buffers intended for the Rx path

View File

@@ -1082,6 +1082,11 @@ like flow control, FEC and more.
need to replace the cable/transceiver.
- Error
* - `total_success_recovery_phy`
- The number of total successful recovery events of any type during
ports reset cycle.
- Error
* - `rx_out_of_buffer`
- Number of times receive queue had no software buffers allocated for the
adapter's incoming traffic.

View File

@@ -9,7 +9,6 @@ Contents:
:maxdepth: 2
atm/index
cable/index
can/index
cellular/index
ethernet/index

View File

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

View File

@@ -69,6 +69,17 @@ Parameters
To verify that value has been set:
$ devlink dev param show pci/0000:16:00.0 name tx_scheduling_layers
* - ``msix_vec_per_pf_max``
- driverinit
- Set the max MSI-X that can be used by the PF, rest can be utilized for
SRIOV. The range is from min value set in msix_vec_per_pf_min to
2k/number of ports.
* - ``msix_vec_per_pf_min``
- driverinit
- Set the min MSI-X that will be used by the PF. This value inform how many
MSI-X will be allocated statically. The range is from 2 to value set
in msix_vec_per_pf_max.
.. list-table:: Driver specific parameters implemented
:widths: 5 5 90

View File

@@ -280,6 +280,10 @@ Description of the vnic counters:
number of packets handled by the VNIC experiencing unexpected steering
failure (at any point in steering flow owned by the VNIC, including the FDB
for the eswitch owner).
- icm_consumption
amount of Interconnect Host Memory (ICM) consumed by the vnic in
granularity of 4KB. ICM is host memory allocated by SW upon HCA request
and is used for storing data structures that control HCA operation.
User commands examples:

View File

@@ -5,7 +5,7 @@ sfc devlink support
===================
This document describes the devlink features implemented by the ``sfc``
device driver for the ef100 device.
device driver for the ef10 and ef100 devices.
Info versions
=============
@@ -18,6 +18,10 @@ The ``sfc`` driver reports the following versions
* - Name
- Type
- Description
* - ``fw.bundle_id``
- stored
- Version of the firmware "bundle" image that was last used to update
multiple components.
* - ``fw.mgmt.suc``
- running
- For boards where the management function is split between multiple
@@ -55,3 +59,13 @@ The ``sfc`` driver reports the following versions
* - ``fw.uefi``
- running
- UEFI driver version (No UNDI support).
Flash Update
============
The ``sfc`` driver implements support for flash update using the
``devlink-flash`` interface. It supports updating the device flash using a
combined flash image ("bundle") that contains multiple components (on ef10,
typically ``fw.mgmt``, ``fw.app``, ``fw.exprom`` and ``fw.uefi``).
The driver does not support any overwrite mask flags.

View File

@@ -256,7 +256,7 @@ Testing
=======
More realistic example code can be found in the kernel source under
``tools/testing/selftests/net/ncdevmem.c``
``tools/testing/selftests/drivers/net/hw/ncdevmem.c``
ncdevmem is a devmem TCP netcat. It works very similarly to netcat, but
receives data directly into a udmabuf.
@@ -268,8 +268,7 @@ ncdevmem has a validation mode as well that expects a repeating pattern of
incoming data and validates it as such. For example, you can launch
ncdevmem on the server by::
ncdevmem -s <server IP> -c <client IP> -f eth1 -d 3 -n 0000:06:00.0 -l \
-p 5201 -v 7
ncdevmem -s <server IP> -c <client IP> -f <ifname> -l -p 5201 -v 7
On client side, use regular netcat to send TX data to ncdevmem process
on the server::

View File

@@ -1934,7 +1934,7 @@ ETHTOOL_A_RSS_INDIR attribute returns RSS indirection table where each byte
indicates queue number.
ETHTOOL_A_RSS_INPUT_XFRM attribute is a bitmap indicating the type of
transformation applied to the input protocol fields before given to the RSS
hfunc. Current supported option is symmetric-xor.
hfunc. Current supported options are symmetric-xor and symmetric-or-xor.
PLCA_GET_CFG
============

View File

@@ -705,6 +705,8 @@ tcp_retries2 - INTEGER
seconds and is a lower bound for the effective timeout.
TCP will effectively time out at the first RTO which exceeds the
hypothetical timeout.
If tcp_rto_max_ms is decreased, it is recommended to also
change tcp_retries2.
RFC 1122 recommends at least 100 seconds for the timeout,
which corresponds to a value of at least 8.
@@ -1227,8 +1229,8 @@ tcp_pingpong_thresh - INTEGER
tcp_rto_min_us - INTEGER
Minimal TCP retransmission timeout (in microseconds). Note that the
rto_min route option has the highest precedence for configuring this
setting, followed by the TCP_BPF_RTO_MIN socket option, followed by
this tcp_rto_min_us sysctl.
setting, followed by the TCP_BPF_RTO_MIN and TCP_RTO_MIN_US socket
options, followed by this tcp_rto_min_us sysctl.
The recommended practice is to use a value less or equal to 200000
microseconds.
@@ -1237,6 +1239,17 @@ tcp_rto_min_us - INTEGER
Default: 200000
tcp_rto_max_ms - INTEGER
Maximal TCP retransmission timeout (in ms).
Note that TCP_RTO_MAX_MS socket option has higher precedence.
When changing tcp_rto_max_ms, it is important to understand
that tcp_retries2 might need a change.
Possible Values: 1000 - 120,000
Default: 120,000
UDP variables
=============

View File

@@ -66,6 +66,90 @@ the library exclusively, or by the in-kernel system exclusively.
J1939 concepts
==============
Data Sent to the J1939 Stack
----------------------------
The data buffers sent to the J1939 stack from user space are not CAN frames
themselves. Instead, they are payloads that the J1939 stack converts into
proper CAN frames based on the size of the buffer and the type of transfer. The
size of the buffer influences how the stack processes the data and determines
the internal code path used for the transfer.
**Handling of Different Buffer Sizes:**
- **Buffers with a size of 8 bytes or less:**
- These are handled as simple sessions internally within the stack.
- The stack converts the buffer directly into a single CAN frame without
fragmentation.
- This type of transfer does not require an actual client (receiver) on the
receiving side.
- **Buffers up to 1785 bytes:**
- These are automatically handled as J1939 Transport Protocol (TP) transfers.
- Internally, the stack splits the buffer into multiple 8-byte CAN frames.
- TP transfers can be unicast or broadcast.
- **Broadcast TP:** Does not require a receiver on the other side and can be
used in broadcast scenarios.
- **Unicast TP:** Requires an active receiver (client) on the other side to
acknowledge the transfer.
- **Buffers from 1786 bytes up to 111 MiB:**
- These are handled as ISO 11783 Extended Transport Protocol (ETP) transfers.
- ETP transfers are used for larger payloads and are split into multiple CAN
frames internally.
- **ETP transfers (unicast):** Require a receiver on the other side to
process the incoming data and acknowledge each step of the transfer.
- ETP transfers cannot be broadcast like TP transfers, and always require a
receiver for operation.
**Non-Blocking Operation with `MSG_DONTWAIT`:**
The J1939 stack supports non-blocking operation when used in combination with
the `MSG_DONTWAIT` flag. In this mode, the stack attempts to take as much data
as the available memory for the socket allows. It returns the amount of data
that was successfully taken, and it is the responsibility of user space to
monitor this value and handle partial transfers.
- If the stack cannot take the entire buffer, it returns the number of bytes
successfully taken, and user space should handle the remainder.
- **Error handling:** When using `MSG_DONTWAIT`, the user must rely on the
error queue to detect transfer errors. See the **SO_J1939_ERRQUEUE** section
for details on how to subscribe to error notifications. Without the error
queue, there is no other way for user space to be notified of transfer errors
during non-blocking operations.
**Behavior and Requirements:**
- **Simple transfers (<= 8 bytes):** Do not require a receiver on the other
side, making them easy to send without needing address claiming or
coordination with a destination.
- **Unicast TP/ETP:** Requires a receiver on the other side to complete the
transfer. The receiver must acknowledge the transfer for the session to
proceed successfully.
- **Broadcast TP:** Allows sending data without a receiver, but only works for
TP transfers. ETP cannot be broadcast and always needs a receiving client.
These different behaviors depend heavily on the size of the buffer provided to
the stack, and the appropriate transport mechanism (TP or ETP) is selected
based on the payload size. The stack automatically manages the fragmentation
and reassembly of large payloads and ensures that the correct CAN frames are
generated and transmitted for each session.
PGN
---
@@ -338,6 +422,459 @@ with ``cmsg_level == SOL_J1939 && cmsg_type == SCM_J1939_DEST_ADDR``,
}
}
setsockopt(2)
^^^^^^^^^^^^^
The ``setsockopt(2)`` function is used to configure various socket-level
options for J1939 communication. The following options are supported:
``SO_J1939_FILTER``
~~~~~~~~~~~~~~~~~~~
The ``SO_J1939_FILTER`` option is essential when the default behavior of
``bind(2)`` and ``connect(2)`` is insufficient for specific use cases. By
default, ``bind(2)`` and ``connect(2)`` allow a socket to be associated with a
single unicast or broadcast address. However, there are scenarios where finer
control over the incoming messages is required, such as filtering by Parameter
Group Number (PGN) rather than by addresses.
For example, in a system where multiple types of J1939 messages are being
transmitted, a process might only be interested in a subset of those messages,
such as specific PGNs, and not want to receive all messages destined for its
address or broadcast to the bus.
By applying the ``SO_J1939_FILTER`` option, you can filter messages based on:
- **Source Address (SA)**: Filter messages coming from specific source
addresses.
- **Source Name**: Filter messages coming from ECUs with specific NAME
identifiers.
- **Parameter Group Number (PGN)**: Focus on receiving messages with specific
PGNs, filtering out irrelevant ones.
This filtering mechanism is particularly useful when:
- You want to receive a subset of messages based on their PGNs, even if the
address is the same.
- You need to handle both broadcast and unicast messages but only care about
certain message types or parameters.
- The ``bind(2)`` and ``connect(2)`` functions only allow binding to a single
address, which might not be sufficient if the process needs to handle multiple
PGNs but does not want to open multiple sockets.
To remove existing filters, you can pass ``optval == NULL`` or ``optlen == 0``
to ``setsockopt(2)``. This will clear all currently set filters. If you want to
**update** the set of filters, you must pass the updated filter set to
``setsockopt(2)``, as the new filter set will **replace** the old one entirely.
This behavior ensures that any previous filter configuration is discarded and
only the new set is applied.
Example of removing all filters:
.. code-block:: c
setsockopt(sock, SOL_CAN_J1939, SO_J1939_FILTER, NULL, 0);
**Maximum number of filters:** The maximum amount of filters that can be
applied using ``SO_J1939_FILTER`` is defined by ``J1939_FILTER_MAX``, which is
set to 512. This means you can configure up to 512 individual filters to match
your specific filtering needs.
Practical use case: **Monitoring Address Claiming**
One practical use case is monitoring the J1939 address claiming process by
filtering for specific PGNs related to address claiming. This allows a process
to monitor and handle address claims without processing unrelated messages.
Example:
.. code-block:: c
struct j1939_filter filt[] = {
{
.pgn = J1939_PGN_ADDRESS_CLAIMED,
.pgn_mask = J1939_PGN_PDU1_MAX,
}, {
.pgn = J1939_PGN_REQUEST,
.pgn_mask = J1939_PGN_PDU1_MAX,
}, {
.pgn = J1939_PGN_ADDRESS_COMMANDED,
.pgn_mask = J1939_PGN_MAX,
},
};
setsockopt(sock, SOL_CAN_J1939, SO_J1939_FILTER, &filt, sizeof(filt));
In this example, the socket will only receive messages with the PGNs related to
address claiming: ``J1939_PGN_ADDRESS_CLAIMED``, ``J1939_PGN_REQUEST``, and
``J1939_PGN_ADDRESS_COMMANDED``. This is particularly useful in scenarios where
you want to monitor and process address claims without being overwhelmed by
other traffic on the J1939 network.
``SO_J1939_PROMISC``
~~~~~~~~~~~~~~~~~~~~
The ``SO_J1939_PROMISC`` option enables socket-level promiscuous mode. When
this option is enabled, the socket will receive all J1939 traffic, regardless
of any filters set by ``bind()`` or ``connect()``. This is analogous to
enabling promiscuous mode for an Ethernet interface, where all traffic on the
network segment is captured.
However, **`SO_J1939_FILTER` has a higher priority** compared to
``SO_J1939_PROMISC``. This means that even in promiscuous mode, you can reduce
the number of packets received by applying specific filters with
`SO_J1939_FILTER`. The filters will limit which packets are passed to the
socket, allowing for more refined traffic selection while promiscuous mode is
active.
The acceptable value size for this option is ``sizeof(int)``, and the value is
only differentiated between `0` and non-zero. A value of `0` disables
promiscuous mode, while any non-zero value enables it.
This combination can be useful for debugging or monitoring specific types of
traffic while still capturing a broad set of messages.
Example:
.. code-block:: c
int value = 1;
setsockopt(sock, SOL_CAN_J1939, SO_J1939_PROMISC, &value, sizeof(value));
In this example, setting ``value`` to any non-zero value (e.g., `1`) enables
promiscuous mode, allowing the socket to receive all J1939 traffic on the
network.
``SO_BROADCAST``
~~~~~~~~~~~~~~~~
The ``SO_BROADCAST`` option enables the sending and receiving of broadcast
messages. By default, broadcast messages are disabled for J1939 sockets. When
this option is enabled, the socket will be allowed to send and receive
broadcast packets on the J1939 network.
Due to the nature of the CAN bus as a shared medium, all messages transmitted
on the bus are visible to all participants. In the context of J1939,
broadcasting refers to using a specific destination address field, where the
destination address is set to a value that indicates the message is intended
for all participants (usually a global address such as 0xFF). Enabling the
broadcast option allows the socket to send and receive such broadcast messages.
The acceptable value size for this option is ``sizeof(int)``, and the value is
only differentiated between `0` and non-zero. A value of `0` disables the
ability to send and receive broadcast messages, while any non-zero value
enables it.
Example:
.. code-block:: c
int value = 1;
setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &value, sizeof(value));
In this example, setting ``value`` to any non-zero value (e.g., `1`) enables
the socket to send and receive broadcast messages.
``SO_J1939_SEND_PRIO``
~~~~~~~~~~~~~~~~~~~~~~
The ``SO_J1939_SEND_PRIO`` option sets the priority of outgoing J1939 messages
for the socket. In J1939, messages can have different priorities, and lower
numerical values indicate higher priority. This option allows the user to
control the priority of messages sent from the socket by adjusting the priority
bits in the CAN identifier.
The acceptable value **size** for this option is ``sizeof(int)``, and the value
is expected to be in the range of 0 to 7, where `0` is the highest priority,
and `7` is the lowest. By default, the priority is set to `6` if this option is
not explicitly configured.
Note that the priority values `0` and `1` can only be set if the process has
the `CAP_NET_ADMIN` capability. These are reserved for high-priority traffic
and require administrative privileges.
Example:
.. code-block:: c
int prio = 3; // Priority value between 0 (highest) and 7 (lowest)
setsockopt(sock, SOL_CAN_J1939, SO_J1939_SEND_PRIO, &prio, sizeof(prio));
In this example, the priority is set to `3`, meaning the outgoing messages will
be sent with a moderate priority level.
``SO_J1939_ERRQUEUE``
~~~~~~~~~~~~~~~~~~~~~
The ``SO_J1939_ERRQUEUE`` option enables the socket to receive error messages
from the error queue, providing diagnostic information about transmission
failures, protocol violations, or other issues that occur during J1939
communication. Once this option is set, user space is required to handle
``MSG_ERRQUEUE`` messages.
Setting ``SO_J1939_ERRQUEUE`` to ``0`` will purge any currently present error
messages in the error queue. When enabled, error messages can be retrieved
using the ``recvmsg(2)`` system call.
When subscribing to the error queue, the following error events can be
accessed:
- **``J1939_EE_INFO_TX_ABORT``**: Transmission abort errors.
- **``J1939_EE_INFO_RX_RTS``**: Reception of RTS (Request to Send) control
frames.
- **``J1939_EE_INFO_RX_DPO``**: Reception of data packets with Data Page Offset
(DPO).
- **``J1939_EE_INFO_RX_ABORT``**: Reception abort errors.
The error queue can be used to correlate errors with specific message transfer
sessions using the session ID (``tskey``). The session ID is assigned via the
``SOF_TIMESTAMPING_OPT_ID`` flag, which is set by enabling the
``SO_TIMESTAMPING`` option.
If ``SO_J1939_ERRQUEUE`` is activated, the user is required to pull messages
from the error queue, meaning that using plain ``recv(2)`` is not sufficient
anymore. The user must use ``recvmsg(2)`` with appropriate flags to handle
error messages. Failure to do so can result in the socket becoming blocked with
unprocessed error messages in the queue.
It is **recommended** that ``SO_J1939_ERRQUEUE`` be used in combination with
``SO_TIMESTAMPING`` in most cases. This enables proper error handling along
with session tracking and timestamping, providing a more detailed analysis of
message transfers and errors.
The acceptable value **size** for this option is ``sizeof(int)``, and the value
is only differentiated between ``0`` and non-zero. A value of ``0`` disables
error queue reception and purges any existing error messages, while any
non-zero value enables it.
Example:
.. code-block:: c
int enable = 1; // Enable error queue reception
setsockopt(sock, SOL_CAN_J1939, SO_J1939_ERRQUEUE, &enable, sizeof(enable));
// Enable timestamping with session tracking via tskey
int timestamping = SOF_TIMESTAMPING_OPT_ID | SOF_TIMESTAMPING_TX_ACK |
SOF_TIMESTAMPING_TX_SCHED |
SOF_TIMESTAMPING_RX_SOFTWARE | SOF_TIMESTAMPING_OPT_CMSG;
setsockopt(sock, SOL_SOCKET, SO_TIMESTAMPING, &timestamping,
sizeof(timestamping));
When enabled, error messages can be retrieved using ``recvmsg(2)``. By
combining ``SO_J1939_ERRQUEUE`` with ``SO_TIMESTAMPING`` (with
``SOF_TIMESTAMPING_OPT_ID`` and ``SOF_TIMESTAMPING_OPT_CMSG`` enabled), the
user can track message transfers, retrieve precise timestamps, and correlate
errors with specific sessions.
For more information on enabling timestamps and session tracking, refer to the
`SO_TIMESTAMPING` section.
``SO_TIMESTAMPING``
~~~~~~~~~~~~~~~~~~~
The ``SO_TIMESTAMPING`` option allows the socket to receive timestamps for
various events related to message transmissions and receptions in J1939. This
option is often used in combination with ``SO_J1939_ERRQUEUE`` to provide
detailed diagnostic information, session tracking, and precise timing data for
message transfers.
In J1939, all payloads provided by user space, regardless of size, are
processed by the kernel as **sessions**. This includes both single-frame
messages (up to 8 bytes) and multi-frame protocols such as the Transport
Protocol (TP) and Extended Transport Protocol (ETP). Even for small,
single-frame messages, the kernel creates a session to manage the transmission
and reception. The concept of sessions allows the kernel to manage various
aspects of the protocol, such as reassembling multi-frame messages and tracking
the status of transmissions.
When receiving extended error messages from the error queue, the error
information is delivered through a `struct sock_extended_err`, accessible via
the control message (``cmsg``) retrieved using the ``recvmsg(2)`` system call.
There are two typical origins for the extended error messages in J1939:
1. ``serr->ee_origin == SO_EE_ORIGIN_TIMESTAMPING``:
In this case, the `serr->ee_info` field will contain one of the following
timestamp types:
- ``SCM_TSTAMP_SCHED``: This timestamp is valid for Extended Transport
Protocol (ETP) transfers and simple transfers (8 bytes or less). It
indicates when a message or set of frames has been scheduled for
transmission.
- For simple transfers (8 bytes or less), it marks the point when the
message is queued and ready to be sent onto the CAN bus.
- For ETP transfers, it is sent after receiving a CTS (Clear to Send)
frame on the sender side, indicating that a new set of frames has been
scheduled for transmission.
- The Transport Protocol (TP) case is currently not implemented for this
timestamp.
- On the receiver side, the counterpart to this event for ETP is
represented by the ``J1939_EE_INFO_RX_DPO`` message, which indicates the
reception of a Data Page Offset (DPO) control frame.
- ``SCM_TSTAMP_ACK``: This timestamp indicates the acknowledgment of the
message or session.
- For simple transfers (8 bytes or less), it marks when the message has
been sent and an echo confirmation has been received from the CAN
controller, indicating that the frame was transmitted onto the bus.
- For multi-frame transfers (TP or ETP), it signifies that the entire
session has been acknowledged, typically after receiving the End of
Message Acknowledgment (EOMA) packet.
2. ``serr->ee_origin == SO_EE_ORIGIN_LOCAL``:
In this case, the `serr->ee_info` field will contain one of the following
J1939 stack-specific message types:
- ``J1939_EE_INFO_TX_ABORT``: This message indicates that the transmission
of a message or session was aborted. The cause of the abort can come from
various sources:
- **CAN stack failure**: The J1939 stack was unable to pass the frame to
the CAN framework for transmission.
- **Echo failure**: The J1939 stack did not receive an echo confirmation
from the CAN controller, meaning the frame may not have been successfully
transmitted to the CAN bus.
- **Protocol-level issues**: For multi-frame transfers (TP/ETP), this
could include protocol-related errors, such as an abort signaled by the
receiver or a timeout at the protocol level, which causes the session to
terminate prematurely.
- The corresponding error code is stored in ``serr->ee_data``
(``session->err`` on kernel side), providing additional details about
the specific reason for the abort.
- ``J1939_EE_INFO_RX_RTS``: This message indicates that the J1939 stack has
received a Request to Send (RTS) control frame, signaling the start of a
multi-frame transfer using the Transport Protocol (TP) or Extended
Transport Protocol (ETP).
- It informs the receiver that the sender is ready to transmit a
multi-frame message and includes details about the total message size
and the number of frames to be sent.
- Statistics such as ``J1939_NLA_TOTAL_SIZE``, ``J1939_NLA_PGN``,
``J1939_NLA_SRC_NAME``, and ``J1939_NLA_DEST_NAME`` are provided along
with the ``J1939_EE_INFO_RX_RTS`` message, giving detailed information
about the incoming transfer.
- ``J1939_EE_INFO_RX_DPO``: This message indicates that the J1939 stack has
received a Data Page Offset (DPO) control frame, which is part of the
Extended Transport Protocol (ETP).
- The DPO frame signals the continuation of an ETP multi-frame message by
indicating the offset position in the data being transferred. It helps
the receiver manage large data sets by identifying which portion of the
message is being received.
- It is typically paired with a corresponding ``SCM_TSTAMP_SCHED`` event
on the sender side, which indicates when the next set of frames is
scheduled for transmission.
- This event includes statistics such as ``J1939_NLA_BYTES_ACKED``, which
tracks the number of bytes acknowledged up to that point in the session.
- ``J1939_EE_INFO_RX_ABORT``: This message indicates that the reception of a
multi-frame message (Transport Protocol or Extended Transport Protocol) has
been aborted.
- The abort can be triggered by protocol-level errors such as timeouts, an
unexpected frame, or a specific abort request from the sender.
- This message signals that the receiver cannot continue processing the
transfer, and the session is terminated.
- The corresponding error code is stored in ``serr->ee_data``
(``session->err`` on kernel side ), providing further details about the
reason for the abort, such as protocol violations or timeouts.
- After receiving this message, the receiver discards the partially received
frames, and the multi-frame session is considered incomplete.
In both cases, if ``SOF_TIMESTAMPING_OPT_ID`` is enabled, ``serr->ee_data``
will be set to the sessions unique identifier (``session->tskey``). This
allows user space to track message transfers by their session identifier across
multiple frames or stages.
In all other cases, ``serr->ee_errno`` will be set to ``ENOMSG``, except for
the ``J1939_EE_INFO_TX_ABORT`` and ``J1939_EE_INFO_RX_ABORT`` cases, where the
kernel sets ``serr->ee_data`` to the error stored in ``session->err``. All
protocol-specific errors are converted to standard kernel error values and
stored in ``session->err``. These error values are unified across system calls
and ``serr->ee_errno``. Some of the known error values are described in the
`Error Codes in the J1939 Stack` section.
When the `J1939_EE_INFO_RX_RTS` message is provided, it will include the
following statistics for multi-frame messages (TP and ETP):
- ``J1939_NLA_TOTAL_SIZE``: Total size of the message in the session.
- ``J1939_NLA_PGN``: Parameter Group Number (PGN) identifying the message type.
- ``J1939_NLA_SRC_NAME``: 64-bit name of the source ECU.
- ``J1939_NLA_DEST_NAME``: 64-bit name of the destination ECU.
- ``J1939_NLA_SRC_ADDR``: 8-bit source address of the sending ECU.
- ``J1939_NLA_DEST_ADDR``: 8-bit destination address of the receiving ECU.
- For other messages (including single-frame messages), only the following
statistic is included:
- ``J1939_NLA_BYTES_ACKED``: Number of bytes successfully acknowledged in the
session.
The key flags for ``SO_TIMESTAMPING`` include:
- ``SOF_TIMESTAMPING_OPT_ID``: Enables the use of a unique session identifier
(``tskey``) for each transfer. This identifier helps track message transfers
and errors as distinct sessions in user space. When this option is enabled,
``serr->ee_data`` will be set to ``session->tskey``.
- ``SOF_TIMESTAMPING_OPT_CMSG``: Sends timestamp information through control
messages (``struct scm_timestamping``), allowing the application to retrieve
timestamps alongside the data.
- ``SOF_TIMESTAMPING_TX_SCHED``: Provides the timestamp for when a message is
scheduled for transmission (``SCM_TSTAMP_SCHED``).
- ``SOF_TIMESTAMPING_TX_ACK``: Provides the timestamp for when a message
transmission is fully acknowledged (``SCM_TSTAMP_ACK``).
- ``SOF_TIMESTAMPING_RX_SOFTWARE``: Provides timestamps for reception-related
events (e.g., ``J1939_EE_INFO_RX_RTS``, ``J1939_EE_INFO_RX_DPO``,
``J1939_EE_INFO_RX_ABORT``).
These flags enable detailed monitoring of message lifecycles, including
transmission scheduling, acknowledgments, reception timestamps, and gathering
detailed statistics about the communication session, especially for multi-frame
payloads like TP and ETP.
Example:
.. code-block:: c
// Enable timestamping with various options, including session tracking and
// statistics
int sock_opt = SOF_TIMESTAMPING_OPT_CMSG |
SOF_TIMESTAMPING_TX_ACK |
SOF_TIMESTAMPING_TX_SCHED |
SOF_TIMESTAMPING_OPT_ID |
SOF_TIMESTAMPING_RX_SOFTWARE;
setsockopt(sock, SOL_SOCKET, SO_TIMESTAMPING, &sock_opt, sizeof(sock_opt));
Dynamic Addressing
------------------
@@ -458,3 +995,141 @@ Send:
};
sendto(sock, dat, sizeof(dat), 0, (const struct sockaddr *)&saddr, sizeof(saddr));
Error Codes in the J1939 Stack
------------------------------
This section lists all potential kernel error codes that can be exposed to user
space when interacting with the J1939 stack. It includes both standard error
codes and those derived from protocol-specific abort codes.
- ``EAGAIN``: Operation would block; retry may succeed. One common reason is
that an active TP or ETP session exists, and an attempt was made to start a
new overlapping TP or ETP session between the same peers.
- ``ENETDOWN``: Network is down. This occurs when the CAN interface is switched
to the "down" state.
- ``ENOBUFS``: No buffer space available. This error occurs when the CAN
interface's transmit (TX) queue is full, and no more messages can be queued.
- ``EOVERFLOW``: Value too large for defined data type. In J1939, this can
happen if the requested data lies outside of the queued buffer. For example,
if a CTS (Clear to Send) requests an offset not available in the kernel buffer
because user space did not provide enough data.
- ``EBUSY``: Device or resource is busy. For example, this occurs if an
identical session is already active and the stack is unable to recover from
the condition.
- ``EACCES``: Permission denied. This error can occur, for example, when
attempting to send broadcast messages, but the socket is not configured with
``SO_BROADCAST``.
- ``EADDRNOTAVAIL``: Address not available. This error occurs in cases such as:
- When attempting to use ``getsockname(2)`` to retrieve the peer's address,
but the socket is not connected.
- When trying to send data to or from a NAME, but address claiming for the
NAME was not performed or detected by the stack.
- ``EBADFD``: File descriptor in bad state. This error can occur if:
- Attempting to send data to an unbound socket.
- The socket is bound but has no source name, and the source address is
``J1939_NO_ADDR``.
- The ``can_ifindex`` is incorrect.
- ``EFAULT``: Bad address. Occurs mostly when the stack can't copy from or to a
sockptr, when there is insufficient data from user space, or when the buffer
provided by user space is not large enough for the requested data.
- ``EINTR``: A signal occurred before any data was transmitted; see ``signal(7)``.
- ``EINVAL``: Invalid argument passed. For example:
- ``msg->msg_namelen`` is less than ``J1939_MIN_NAMELEN``.
- ``addr->can_family`` is not equal to ``AF_CAN``.
- An incorrect PGN was provided.
- ``ENODEV``: No such device. This happens when the CAN network device cannot
be found for the provided ``can_ifindex`` or if ``can_ifindex`` is 0.
- ``ENOMEM``: Out of memory. Typically related to issues with memory allocation
in the stack.
- ``ENOPROTOOPT``: Protocol not available. This can occur when using
``getsockopt(2)`` or ``setsockopt(2)`` if the requested socket option is not
available.
- ``EDESTADDRREQ``: Destination address required. This error occurs:
- In the case of ``connect(2)``, if the ``struct sockaddr *uaddr`` is ``NULL``.
- In the case of ``send*(2)``, if there is an attempt to send an ETP message
to a broadcast address.
- ``EDOM``: Argument out of domain. This error may happen if attempting to send
a TP or ETP message to a PGN that is reserved for control PGNs for TP or ETP
operations.
- ``EIO``: I/O error. This can occur if the amount of data provided to the
socket for a TP or ETP session does not match the announced amount of data for
the session.
- ``ENOENT``: No such file or directory. This can happen when the stack
attempts to transfer CTS or EOMA but cannot find a matching receiving socket
anymore.
- ``ENOIOCTLCMD``: No ioctls are available for the socket layer.
- ``EPERM``: Operation not permitted. For example, this can occur if a
requested action requires ``CAP_NET_ADMIN`` privileges.
- ``ENETUNREACH``: Network unreachable. Most likely, this occurs when frames
cannot be transmitted to the CAN bus.
- ``ETIME``: Timer expired. This can happen if a timeout occurs while
attempting to send a simple message, for example, when an echo message from
the controller is not received.
- ``EPROTO``: Protocol error.
- Used for various protocol-level errors in J1939, including:
- Duplicate sequence number.
- Unexpected EDPO or ECTS packet.
- Invalid PGN or offset in EDPO/ECTS.
- Number of EDPO packets exceeded CTS allowance.
- Any other protocol-level error.
- ``EMSGSIZE``: Message too long.
- ``ENOMSG``: No message available.
- ``EALREADY``: The ECU is already engaged in one or more connection-managed
sessions and cannot support another.
- ``EHOSTUNREACH``: A timeout occurred, and the session was aborted.
- ``EBADMSG``: CTS (Clear to Send) messages were received during an active data
transfer, causing an abort.
- ``ENOTRECOVERABLE``: The maximum retransmission request limit was reached,
and the session cannot recover.
- ``ENOTCONN``: An unexpected data transfer packet was received.
- ``EILSEQ``: A bad sequence number was received, and the software could not
recover.

View File

@@ -200,7 +200,7 @@ while. Example use::
setsockopt(kcmfd, SOL_KCM, KCM_RECV_DISABLE, &val, sizeof(val))
BFP programs for message delineation
BPF programs for message delineation
------------------------------------
BPF programs can be compiled using the BPF LLVM backend. For example,

View File

@@ -30,6 +30,10 @@ allow_join_initial_addr_port - BOOLEAN
Default: 1
available_path_managers - STRING
Shows the available path managers choices that are registered. More
path managers may be available, but not loaded.
available_schedulers - STRING
Shows the available schedulers choices that are registered. More packet
schedulers may be available, but not loaded.
@@ -72,6 +76,23 @@ enabled - BOOLEAN
Default: 1 (enabled)
path_manager - STRING
Set the default path manager name to use for each new MPTCP
socket. In-kernel path management will control subflow
connections and address advertisements according to
per-namespace values configured over the MPTCP netlink
API. Userspace path management puts per-MPTCP-connection subflow
connection decisions and address advertisements under control of
a privileged userspace program, at the cost of more netlink
traffic to propagate all of the related events and commands.
This is a per-namespace sysctl.
* "kernel" - In-kernel path manager
* "userspace" - Userspace path manager
Default: "kernel"
pm_type - INTEGER
Set the default path manager type to use for each new MPTCP
socket. In-kernel path management will control subflow
@@ -84,6 +105,8 @@ pm_type - INTEGER
This is a per-namespace sysctl.
Deprecated since v6.15, use path_manager instead.
* 0 - In-kernel path manager
* 1 - Userspace path manager

View File

@@ -171,12 +171,43 @@ a channel as an IRQ/NAPI which services queues of a given type. For example,
a configuration of 1 ``rx``, 1 ``tx`` and 1 ``combined`` channel is expected
to utilize 3 interrupts, 2 Rx and 2 Tx queues.
Persistent NAPI config
----------------------
Drivers often allocate and free NAPI instances dynamically. This leads to loss
of NAPI-related user configuration each time NAPI instances are reallocated.
The netif_napi_add_config() API prevents this loss of configuration by
associating each NAPI instance with a persistent NAPI configuration based on
a driver defined index value, like a queue number.
Using this API allows for persistent NAPI IDs (among other settings), which can
be beneficial to userspace programs using ``SO_INCOMING_NAPI_ID``. See the
sections below for other NAPI configuration settings.
Drivers should try to use netif_napi_add_config() whenever possible.
User API
========
User interactions with NAPI depend on NAPI instance ID. The instance IDs
are only visible to the user thru the ``SO_INCOMING_NAPI_ID`` socket option.
It's not currently possible to query IDs used by a given device.
Users can query NAPI IDs for a device or device queue using netlink. This can
be done programmatically in a user application or by using a script included in
the kernel source tree: ``tools/net/ynl/pyynl/cli.py``.
For example, using the script to dump all of the queues for a device (which
will reveal each queue's NAPI ID):
.. code-block:: bash
$ kernel-source/tools/net/ynl/pyynl/cli.py \
--spec Documentation/netlink/specs/netdev.yaml \
--dump queue-get \
--json='{"ifindex": 2}'
See ``Documentation/netlink/specs/netdev.yaml`` for more details on
available operations and attributes.
Software IRQ coalescing
-----------------------

View File

@@ -12,11 +12,11 @@ struct inet_sock icsk_inet read_mostly r
struct request_sock_queue icsk_accept_queue
struct inet_bind_bucket icsk_bind_hash read_mostly tcp_set_state
struct inet_bind2_bucket icsk_bind2_hash read_mostly tcp_set_state,inet_put_port
unsigned_long icsk_timeout read_mostly inet_csk_reset_xmit_timer,tcp_connect
struct timer_list icsk_retransmit_timer read_mostly inet_csk_reset_xmit_timer,tcp_connect
struct timer_list icsk_retransmit_timer read_write inet_csk_reset_xmit_timer,tcp_connect
struct timer_list icsk_delack_timer read_mostly inet_csk_reset_xmit_timer,tcp_connect
u32 icsk_rto read_write tcp_cwnd_validate,tcp_schedule_loss_probe,tcp_connect_init,tcp_connect,tcp_write_xmit,tcp_push_one
u32 icsk_rto_min
u32 icsk_rto_max read_mostly tcp_reset_xmit_timer
u32 icsk_delack_max
u32 icsk_pmtu_cookie read_write tcp_sync_mss,tcp_current_mss,tcp_send_syn_data,tcp_connect_init,tcp_connect
struct tcp_congestion_ops icsk_ca_ops read_write tcp_cwnd_validate,tcp_tso_segs,tcp_ca_dst_init,tcp_connect_init,tcp_connect,tcp_write_xmit
@@ -38,7 +38,6 @@ struct icsk_ack_u8 quick read_write w
struct icsk_ack_u8 pingpong
struct icsk_ack_u8 retry write_mostly read_write inet_csk_clear_xmit_timer,tcp_rearm_rto,tcp_event_new_data_sent,tcp_write_xmit,__tcp_send_ack,tcp_send_ack,
struct icsk_ack_u8 ato read_mostly write_mostly tcp_dec_quickack_mode,tcp_event_ack_sent,__tcp_transmit_skb,__tcp_send_ack,tcp_send_ack
struct icsk_ack_unsigned_long timeout read_write read_write inet_csk_reset_xmit_timer,tcp_connect
struct icsk_ack_u32 lrcvtime read_write tcp_finish_connect,tcp_connect,tcp_event_data_sent,__tcp_transmit_skb
struct icsk_ack_u16 rcv_mss write_mostly read_mostly __tcp_select_window,__tcp_cleanup_rbuf,tcp_initialize_rcv_mss,tcp_connect_init
struct icsk_mtup_int search_high read_write tcp_mtup_init,tcp_sync_mss,tcp_connect_init,tcp_mtu_check_reprobe,tcp_write_xmit

View File

@@ -167,7 +167,7 @@ unsigned:1 wol_enabled
unsigned:1 threaded napi_poll(napi_enable,dev_set_threaded)
unsigned_long:1 see_all_hwtstamp_requests
unsigned_long:1 change_proto_down
unsigned_long:1 netns_local
unsigned_long:1 netns_immutable
unsigned_long:1 fcoe_mtu
struct list_head net_notifier_list
struct macsec_ops* macsec_ops

View File

@@ -86,6 +86,7 @@ u8 sysctl_tcp_sack
u8 sysctl_tcp_window_scaling tcp_syn_options,tcp_parse_options
u8 sysctl_tcp_timestamps
u8 sysctl_tcp_early_retrans read_mostly tcp_schedule_loss_probe(tcp_write_xmit)
u32 sysctl_tcp_rto_max_ms
u8 sysctl_tcp_recovery tcp_fastretrans_alert
u8 sysctl_tcp_thin_linear_timeouts tcp_retrans_timer(on_thin_streams)
u8 sysctl_tcp_slow_start_after_idle unlikely(tcp_cwnd_validate-network-not-starved)

View File

@@ -36,6 +36,7 @@ unsigned_long LINUX_MIB_TIMEWAITRECYCLED
unsigned_long LINUX_MIB_TIMEWAITKILLED
unsigned_long LINUX_MIB_PAWSACTIVEREJECTED
unsigned_long LINUX_MIB_PAWSESTABREJECTED
unsigned_long LINUX_MIB_TSECR_REJECTED
unsigned_long LINUX_MIB_DELAYEDACKLOST
unsigned_long LINUX_MIB_LISTENOVERFLOWS
unsigned_long LINUX_MIB_LISTENDROPS

View File

@@ -27,6 +27,7 @@ u32 dsack_dups
u32 snd_una read_mostly read_write tcp_wnd_end,tcp_urg_mode,tcp_minshall_check,tcp_cwnd_validate(tx);tcp_ack,tcp_may_update_window,tcp_clean_rtx_queue(write),tcp_ack_tstamp(rx)
u32 snd_sml read_write tcp_minshall_check,tcp_minshall_update
u32 rcv_tstamp read_mostly tcp_ack
void * tcp_clean_acked read_mostly tcp_ack
u32 lsndtime read_write tcp_slow_start_after_idle_check,tcp_event_data_sent
u32 last_oow_ack_time
u32 compressed_ack_rcv_nxt

View File

@@ -17,6 +17,8 @@ Release prepend support by Breno Leitao <leitao@debian.org>, Jul 7 2023
Userdata append support by Matthew Wood <thepacketgeek@gmail.com>, Jan 22 2024
Sysdata append support by Breno Leitao <leitao@debian.org>, Jan 15 2025
Please send bug reports to Matt Mackall <mpm@selenic.com>
Satyam Sharma <satyam.sharma@gmail.com>, and Cong Wang <xiyou.wangcong@gmail.com>
@@ -45,7 +47,7 @@ following format::
r if present, prepend kernel version (release) to the message
src-port source for UDP packets (defaults to 6665)
src-ip source IP to use (interface address)
dev network interface (eth0)
dev network interface name (eth0) or MAC address
tgt-port port for logging agent (6666)
tgt-ip IP address for logging agent
tgt-macaddr ethernet MAC address for logging agent (broadcast)
@@ -62,6 +64,10 @@ or using IPv6::
insmod netconsole netconsole=@/,@fd00:1:2:3::1/
or using a MAC address to select the egress interface::
linux netconsole=4444@10.0.0.1/22:33:44:55:66:77,9353@10.0.0.2/12:34:56:78:9a:bc
It also supports logging to multiple remote agents by specifying
parameters for the multiple agents separated by semicolons and the
complete string enclosed in "quotes", thusly::
@@ -238,6 +244,102 @@ Delete `userdata` entries with `rmdir`::
It is recommended to not write user data values with newlines.
Task name auto population in userdata
-------------------------------------
Inside the netconsole configfs hierarchy, there is a file called
`taskname_enabled` under the `userdata` directory. This file is used to enable
or disable the automatic task name population feature. This feature
automatically populates the current task name that is scheduled in the CPU
sneding the message.
To enable task name auto-population::
echo 1 > /sys/kernel/config/netconsole/target1/userdata/taskname_enabled
When this option is enabled, the netconsole messages will include an additional
line in the userdata field with the format `taskname=<task name>`. This allows
the receiver of the netconsole messages to easily find which application was
currently scheduled when that message was generated, providing extra context
for kernel messages and helping to categorize them.
Example::
echo "This is a message" > /dev/kmsg
12,607,22085407756,-;This is a message
taskname=echo
In this example, the message was generated while "echo" was the current
scheduled process.
Kernel release auto population in userdata
------------------------------------------
Within the netconsole configfs hierarchy, there is a file named `release_enabled`
located in the `userdata` directory. This file controls the kernel release
(version) auto-population feature, which appends the kernel release information
to userdata dictionary in every message sent.
To enable the release auto-population::
echo 1 > /sys/kernel/config/netconsole/target1/userdata/release_enabled
Example::
echo "This is a message" > /dev/kmsg
12,607,22085407756,-;This is a message
release=6.14.0-rc6-01219-g3c027fbd941d
.. note::
This feature provides the same data as the "release prepend" feature.
However, in this case, the release information is appended to the userdata
dictionary rather than being included in the message header.
CPU number auto population in userdata
--------------------------------------
Inside the netconsole configfs hierarchy, there is a file called
`cpu_nr` under the `userdata` directory. This file is used to enable or disable
the automatic CPU number population feature. This feature automatically
populates the CPU number that is sending the message.
To enable the CPU number auto-population::
echo 1 > /sys/kernel/config/netconsole/target1/userdata/cpu_nr
When this option is enabled, the netconsole messages will include an additional
line in the userdata field with the format `cpu=<cpu_number>`. This allows the
receiver of the netconsole messages to easily differentiate and demultiplex
messages originating from different CPUs, which is particularly useful when
dealing with parallel log output.
Example::
echo "This is a message" > /dev/kmsg
12,607,22085407756,-;This is a message
cpu=42
In this example, the message was sent by CPU 42.
.. note::
If the user has set a conflicting `cpu` key in the userdata dictionary,
both keys will be reported, with the kernel-populated entry appearing after
the user one. For example::
# User-defined CPU entry
mkdir -p /sys/kernel/config/netconsole/target1/userdata/cpu
echo "1" > /sys/kernel/config/netconsole/target1/userdata/cpu/value
Output might look like::
12,607,22085407756,-;This is a message
cpu=1
cpu=42 # kernel-populated value
Extended console:
=================

View File

@@ -210,49 +210,55 @@ packets is preferred.
struct net_device synchronization rules
=======================================
ndo_open:
Synchronization: rtnl_lock() semaphore.
Synchronization: rtnl_lock() semaphore. In addition, netdev instance
lock if the driver implements queue management or shaper API.
Context: process
ndo_stop:
Synchronization: rtnl_lock() semaphore.
Synchronization: rtnl_lock() semaphore. In addition, netdev instance
lock if the driver implements queue management or shaper API.
Context: process
Note: netif_running() is guaranteed false
ndo_do_ioctl:
Synchronization: rtnl_lock() semaphore.
Context: process
This is only called by network subsystems internally,
not by user space calling ioctl as it was in before
linux-5.14.
This is only called by network subsystems internally,
not by user space calling ioctl as it was in before
linux-5.14.
ndo_siocbond:
Synchronization: rtnl_lock() semaphore.
Synchronization: rtnl_lock() semaphore. In addition, netdev instance
lock if the driver implements queue management or shaper API.
Context: process
Used by the bonding driver for the SIOCBOND family of
ioctl commands.
Used by the bonding driver for the SIOCBOND family of
ioctl commands.
ndo_siocwandev:
Synchronization: rtnl_lock() semaphore.
Synchronization: rtnl_lock() semaphore. In addition, netdev instance
lock if the driver implements queue management or shaper API.
Context: process
Used by the drivers/net/wan framework to handle
the SIOCWANDEV ioctl with the if_settings structure.
ndo_siocdevprivate:
Synchronization: rtnl_lock() semaphore.
Synchronization: rtnl_lock() semaphore. In addition, netdev instance
lock if the driver implements queue management or shaper API.
Context: process
This is used to implement SIOCDEVPRIVATE ioctl helpers.
These should not be added to new drivers, so don't use.
ndo_eth_ioctl:
Synchronization: rtnl_lock() semaphore.
Synchronization: rtnl_lock() semaphore. In addition, netdev instance
lock if the driver implements queue management or shaper API.
Context: process
ndo_get_stats:
Synchronization: rtnl_lock() semaphore, or RCU.
Synchronization: RCU (can be called concurrently with the stats
update path).
Context: atomic (can't sleep under RCU)
ndo_start_xmit:
@@ -284,6 +290,16 @@ ndo_set_rx_mode:
Synchronization: netif_addr_lock spinlock.
Context: BHs disabled
ndo_setup_tc:
``TC_SETUP_BLOCK`` and ``TC_SETUP_FT`` are running under NFT locks
(i.e. no ``rtnl_lock`` and no device instance lock). The rest of
``tc_setup_type`` types run under netdev instance lock if the driver
implements queue management or shaper API.
Most ndo callbacks not specified in the list above are running
under ``rtnl_lock``. In addition, netdev instance lock is taken as well if
the driver implements queue management or shaper API.
struct napi_struct synchronization rules
========================================
napi->poll:
@@ -298,6 +314,35 @@ napi->poll:
softirq
will be called with interrupts disabled by netconsole.
struct netdev_queue_mgmt_ops synchronization rules
==================================================
All queue management ndo callbacks are holding netdev instance lock.
RTNL and netdev instance lock
=============================
Historically, all networking control operations were protected by a single
global lock known as ``rtnl_lock``. There is an ongoing effort to replace this
global lock with separate locks for each network namespace. Additionally,
properties of individual netdev are increasingly protected by per-netdev locks.
For device drivers that implement shaping or queue management APIs, all control
operations will be performed under the netdev instance lock. Currently, this
instance lock is acquired within the context of ``rtnl_lock``. The drivers
can also explicitly request instance lock to be acquired via
``request_ops_lock``. In the future, there will be an option for individual
drivers to opt out of using ``rtnl_lock`` and instead perform their control
operations directly under the netdev instance lock.
Devices drivers are encouraged to rely on the instance lock where possible.
For the (mostly software) drivers that need to interact with the core stack,
there are two sets of interfaces: ``dev_xxx`` and ``netif_xxx`` (e.g.,
``dev_set_mtu`` and ``netif_set_mtu``). The ``dev_xxx`` functions handle
acquiring the instance lock themselves, while the ``netif_xxx`` functions
assume that the driver has already acquired the instance lock.
NETDEV_INTERNAL symbol namespace
================================

View File

@@ -49,14 +49,21 @@ destination address) and TCP/UDP (source port, destination port) tuples
are swapped, the computed hash is the same. This is beneficial in some
applications that monitor TCP/IP flows (IDS, firewalls, ...etc) and need
both directions of the flow to land on the same Rx queue (and CPU). The
"Symmetric-XOR" is a type of RSS algorithms that achieves this hash
symmetry by XORing the input source and destination fields of the IP
and/or L4 protocols. This, however, results in reduced input entropy and
could potentially be exploited. Specifically, the algorithm XORs the input
"Symmetric-XOR" and "Symmetric-OR-XOR" are types of RSS algorithms that
achieve this hash symmetry by XOR/ORing the input source and destination
fields of the IP and/or L4 protocols. This, however, results in reduced
input entropy and could potentially be exploited.
Specifically, the "Symmetric-XOR" algorithm XORs the input
as follows::
# (SRC_IP ^ DST_IP, SRC_IP ^ DST_IP, SRC_PORT ^ DST_PORT, SRC_PORT ^ DST_PORT)
The "Symmetric-OR-XOR" algorithm, on the other hand, transforms the input as
follows::
# (SRC_IP | DST_IP, SRC_IP ^ DST_IP, SRC_PORT | DST_PORT, SRC_PORT ^ DST_PORT)
The result is then fed to the underlying RSS algorithm.
Some advanced NICs allow steering packets to queues based on
@@ -427,8 +434,10 @@ rps_dev_flow_table. The stack consults a CPU to hardware queue map which
is maintained by the NIC driver. This is an auto-generated reverse map of
the IRQ affinity table shown by /proc/interrupts. Drivers can use
functions in the cpu_rmap (“CPU affinity reverse map”) kernel library
to populate the map. For each CPU, the corresponding queue in the map is
set to be one whose processing CPU is closest in cache locality.
to populate the map. Alternatively, drivers can delegate the cpu_rmap
management to the Kernel by calling netif_enable_cpu_rmap(). For each CPU,
the corresponding queue in the map is set to be one whose processing CPU is
closest in cache locality.
Accelerated RFS Configuration

View File

@@ -180,7 +180,7 @@ There are seven callbacks:
struct contains two fields: offset and full_len. Offset is
where the message starts in the skb, and full_len is the
the length of the message. skb->len - offset may be greater
then full_len since strparser does not trim the skb.
than full_len since strparser does not trim the skb.
::

View File

@@ -137,7 +137,7 @@ would be sub-port 0 on port 1 on switch 1.
Port Features
^^^^^^^^^^^^^
dev->netns_local
dev->netns_immutable
If the switchdev driver (and device) only supports offloading of the default
network namespace (netns), the driver should set this private flag to prevent

View File

@@ -140,6 +140,14 @@ SOF_TIMESTAMPING_TX_ACK:
cumulative acknowledgment. The mechanism ignores SACK and FACK.
This flag can be enabled via both socket options and control messages.
SOF_TIMESTAMPING_TX_COMPLETION:
Request tx timestamps on packet tx completion. The completion
timestamp is generated by the kernel when it receives packet a
completion report from the hardware. Hardware may report multiple
packets at once, and completion timestamps reflect the timing of the
report and not actual tx time. This flag can be enabled via both
socket options and control messages.
1.3.2 Timestamp Reporting
^^^^^^^^^^^^^^^^^^^^^^^^^

View File

@@ -126,7 +126,8 @@ been setup for offload, it first calls into xdo_dev_offload_ok() with
the skb and the intended offload state to ask the driver if the offload
will serviceable. This can check the packet information to be sure the
offload can be supported (e.g. IPv4 or IPv6, no IPv4 options, etc) and
return true of false to signify its support.
return true or false to signify its support. In case driver doesn't implement
this callback, the stack provides reasonable defaults.
Crypto offload mode:
When ready to send, the driver needs to inspect the Tx packet for the

View File

@@ -50,6 +50,10 @@ The flags field enables the particular offload:
checksum. ``csum_start`` specifies byte offset of where the checksumming
should start and ``csum_offset`` specifies byte offset where the
device should store the computed checksum.
- ``XDP_TXMD_FLAGS_LAUNCH_TIME``: requests the device to schedule the
packet for transmission at a pre-determined time called launch time. The
value of launch time is indicated by ``launch_time`` field of
``union xsk_tx_metadata``.
Besides the flags above, in order to trigger the offloads, the first
packet's ``struct xdp_desc`` descriptor should set ``XDP_TX_METADATA``
@@ -65,6 +69,63 @@ In this case, when running in ``XDK_COPY`` mode, the TX checksum
is calculated on the CPU. Do not enable this option in production because
it will negatively affect performance.
Launch Time
===========
The value of the requested launch time should be based on the device's PTP
Hardware Clock (PHC) to ensure accuracy. AF_XDP takes a different data path
compared to the ETF queuing discipline, which organizes packets and delays
their transmission. Instead, AF_XDP immediately hands off the packets to
the device driver without rearranging their order or holding them prior to
transmission. Since the driver maintains FIFO behavior and does not perform
packet reordering, a packet with a launch time request will block other
packets in the same Tx Queue until it is sent. Therefore, it is recommended
to allocate separate queue for scheduling traffic that is intended for
future transmission.
In scenarios where the launch time offload feature is disabled, the device
driver is expected to disregard the launch time request. For correct
interpretation and meaningful operation, the launch time should never be
set to a value larger than the farthest programmable time in the future
(the horizon). Different devices have different hardware limitations on the
launch time offload feature.
stmmac driver
-------------
For stmmac, TSO and launch time (TBS) features are mutually exclusive for
each individual Tx Queue. By default, the driver configures Tx Queue 0 to
support TSO and the rest of the Tx Queues to support TBS. The launch time
hardware offload feature can be enabled or disabled by using the tc-etf
command to call the driver's ndo_setup_tc() callback.
The value of the launch time that is programmed in the Enhanced Normal
Transmit Descriptors is a 32-bit value, where the most significant 8 bits
represent the time in seconds and the remaining 24 bits represent the time
in 256 ns increments. The programmed launch time is compared against the
PTP time (bits[39:8]) and rolls over after 256 seconds. Therefore, the
horizon of the launch time for dwmac4 and dwxlgmac2 is 128 seconds in the
future.
igc driver
----------
For igc, all four Tx Queues support the launch time feature. The launch
time hardware offload feature can be enabled or disabled by using the
tc-etf command to call the driver's ndo_setup_tc() callback. When entering
TSN mode, the igc driver will reset the device and create a default Qbv
schedule with a 1-second cycle time, with all Tx Queues open at all times.
The value of the launch time that is programmed in the Advanced Transmit
Context Descriptor is a relative offset to the starting time of the Qbv
transmission window of the queue. The Frst flag of the descriptor can be
set to schedule the packet for the next Qbv cycle. Therefore, the horizon
of the launch time for i225 and i226 is the ending time of the next cycle
of the Qbv transmission window of the queue. For example, when the Qbv
cycle time is set to 1 second, the horizon of the launch time ranges
from 1 second to 2 seconds, depending on where the Qbv cycle is currently
running.
Querying Device Capabilities
============================
@@ -74,6 +135,7 @@ Refer to ``xsk-flags`` features bitmask in
- ``tx-timestamp``: device supports ``XDP_TXMD_FLAGS_TIMESTAMP``
- ``tx-checksum``: device supports ``XDP_TXMD_FLAGS_CHECKSUM``
- ``tx-launch-time-fifo``: device supports ``XDP_TXMD_FLAGS_LAUNCH_TIME``
See ``tools/net/ynl/samples/netdev.c`` on how to query this information.

View File

@@ -311,6 +311,14 @@ to the mailing list, e.g.::
Posting as one thread is discouraged because it confuses patchwork
(as of patchwork 2.2.2).
Co-posting selftests
--------------------
Selftests should be part of the same series as the code changes.
Specifically for fixes both code change and related test should go into
the same tree (the tests may lack a Fixes tag, which is expected).
Mixing code changes and test changes in a single commit is discouraged.
Preparing changes
-----------------

View File

@@ -727,7 +727,7 @@ L: linux-mediatek@lists.infradead.org (moderated for non-subscribers)
L: netdev@vger.kernel.org
S: Maintained
F: Documentation/devicetree/bindings/net/airoha,en7581-eth.yaml
F: drivers/net/ethernet/mediatek/airoha_eth.c
F: drivers/net/ethernet/airoha/
AIROHA PCIE PHY DRIVER
M: Lorenzo Bianconi <lorenzo@kernel.org>
@@ -8623,12 +8623,14 @@ F: Documentation/networking/devlink/etas_es58x.rst
F: drivers/net/can/usb/etas_es58x/
ETHERNET BRIDGE
M: Roopa Prabhu <roopa@nvidia.com>
M: Nikolay Aleksandrov <razor@blackwall.org>
M: Ido Schimmel <idosch@nvidia.com>
L: bridge@lists.linux.dev
L: netdev@vger.kernel.org
S: Maintained
W: http://www.linuxfoundation.org/en/Net:Bridge
F: include/linux/if_bridge.h
F: include/uapi/linux/if_bridge.h
F: include/linux/netfilter_bridge/
F: net/bridge/
@@ -11942,6 +11944,7 @@ L: platform-driver-x86@vger.kernel.org
S: Maintained
F: Documentation/ABI/testing/sysfs-platform-intel-pmc
F: drivers/platform/x86/intel/pmc/
F: include/linux/platform_data/x86/intel_pmc_ipc.h
INTEL PMIC GPIO DRIVERS
M: Andy Shevchenko <andy@kernel.org>
@@ -13979,6 +13982,7 @@ L: netdev@vger.kernel.org
S: Maintained
F: Documentation/networking/mctp.rst
F: drivers/net/mctp/
F: include/linux/usb/mctp-usb.h
F: include/net/mctp.h
F: include/net/mctpdevice.h
F: include/net/netns/mctp.h
@@ -24306,7 +24310,7 @@ W: http://vtun.sourceforge.net/tun
F: Documentation/networking/tuntap.rst
F: arch/um/os-Linux/drivers/
F: drivers/net/tap.c
F: drivers/net/tun.c
F: drivers/net/tun*
TURBOCHANNEL SUBSYSTEM
M: "Maciej W. Rozycki" <macro@orcam.me.uk>

View File

@@ -1781,7 +1781,6 @@
st,syscon = <&syscfg 0x4>;
snps,mixed-burst;
snps,pbl = <2>;
snps,en-tx-lpi-clockgating;
snps,axi-config = <&stmmac_axi_config_0>;
snps,tso;
access-controllers = <&etzpc 94>;

View File

@@ -132,16 +132,16 @@
#define SO_PASSPIDFD 0x404A
#define SO_PEERPIDFD 0x404B
#define SO_DEVMEM_LINEAR 78
#define SCM_DEVMEM_LINEAR SO_DEVMEM_LINEAR
#define SO_DEVMEM_DMABUF 79
#define SCM_DEVMEM_DMABUF SO_DEVMEM_DMABUF
#define SO_DEVMEM_DONTNEED 80
#define SCM_TS_OPT_ID 0x404C
#define SO_RCVPRIORITY 0x404D
#define SO_DEVMEM_LINEAR 0x404E
#define SCM_DEVMEM_LINEAR SO_DEVMEM_LINEAR
#define SO_DEVMEM_DMABUF 0x404F
#define SCM_DEVMEM_DMABUF SO_DEVMEM_DMABUF
#define SO_DEVMEM_DONTNEED 0x4050
#if !defined(__KERNEL__)
#if __BITS_PER_LONG == 64

View File

@@ -485,7 +485,6 @@ CONFIG_VIA_VELOCITY=m
CONFIG_PCMCIA_XIRC2PS=m
CONFIG_FDDI=y
CONFIG_SKFP=m
CONFIG_NET_SB1000=m
CONFIG_BROADCOM_PHY=m
CONFIG_CICADA_PHY=m
CONFIG_DAVICOM_PHY=m

View File

@@ -1022,7 +1022,6 @@
snps,force_thresh_dma_mode;
snps,axi-config = <&stmmac_axi_setup>;
snps,tso;
snps,en-tx-lpi-clockgating;
snps,txpbl = <16>;
snps,rxpbl = <16>;
starfive,syscon = <&aon_syscon 0xc 0x12>;
@@ -1053,7 +1052,6 @@
snps,force_thresh_dma_mode;
snps,axi-config = <&stmmac_axi_setup>;
snps,tso;
snps,en-tx-lpi-clockgating;
snps,txpbl = <16>;
snps,rxpbl = <16>;
starfive,syscon = <&sys_syscon 0x90 0x2>;

View File

@@ -54,7 +54,6 @@ enum interruption_class {
IRQIO_C70,
IRQIO_TAP,
IRQIO_VMR,
IRQIO_LCS,
IRQIO_CTC,
IRQIO_ADM,
IRQIO_CSC,

View File

@@ -84,7 +84,6 @@ static const struct irq_class irqclass_sub_desc[] = {
{.irq = IRQIO_C70, .name = "C70", .desc = "[I/O] 3270"},
{.irq = IRQIO_TAP, .name = "TAP", .desc = "[I/O] Tape"},
{.irq = IRQIO_VMR, .name = "VMR", .desc = "[I/O] Unit Record Devices"},
{.irq = IRQIO_LCS, .name = "LCS", .desc = "[I/O] LCS"},
{.irq = IRQIO_CTC, .name = "CTC", .desc = "[I/O] CTC"},
{.irq = IRQIO_ADM, .name = "ADM", .desc = "[I/O] EADM Subchannel"},
{.irq = IRQIO_CSC, .name = "CSC", .desc = "[I/O] CHSC Subchannel"},

View File

@@ -120,8 +120,6 @@ static const struct acpi_device_id acpi_pnp_device_ids[] = {
{"IBM0071"},
/* smsc-ircc2 */
{"SMCf010"},
/* sb1000 */
{"GIC1000"},
/* parport_pc */
{"PNP0400"}, /* Standard LPT Printer Port */
{"PNP0401"}, /* ECP Printer Port */

View File

@@ -365,9 +365,8 @@ static void bfusb_rx_complete(struct urb *urb)
buf += 3;
}
if (count < len) {
if (count < len)
bt_dev_err(data->hdev, "block extends over URB buffer ranges");
}
if ((hdr & 0xe1) == 0xc1)
bfusb_recv_block(data, hdr, buf, len);

View File

@@ -35,6 +35,11 @@ enum {
DSM_SET_RESET_METHOD = 3,
};
#define BTINTEL_BT_DOMAIN 0x12
#define BTINTEL_SAR_LEGACY 0
#define BTINTEL_SAR_INC_PWR 1
#define BTINTEL_SAR_INC_PWR_SUPPORTED 0
#define CMD_WRITE_BOOT_PARAMS 0xfc0e
struct cmd_write_boot_params {
__le32 boot_addr;
@@ -478,6 +483,7 @@ int btintel_version_info_tlv(struct hci_dev *hdev,
case 0x1c: /* Gale Peak (GaP) */
case 0x1d: /* BlazarU (BzrU) */
case 0x1e: /* BlazarI (Bzr) */
case 0x1f: /* Scorpious Peak */
break;
default:
bt_dev_err(hdev, "Unsupported Intel hardware variant (0x%x)",
@@ -2756,6 +2762,7 @@ static int btintel_set_dsbr(struct hci_dev *hdev, struct intel_version_tlv *ver)
/* DSBR command needs to be sent for,
* 1. BlazarI or BlazarIW + B0 step product in IML image.
* 2. Gale Peak2 or BlazarU in OP image.
* 3. Scorpious Peak in IML image.
*/
switch (cnvi) {
@@ -2771,6 +2778,10 @@ static int btintel_set_dsbr(struct hci_dev *hdev, struct intel_version_tlv *ver)
hdev->bus == HCI_USB)
break;
return 0;
case BTINTEL_CNVI_SCP:
if (ver->img_type == BTINTEL_IMG_IML)
break;
return 0;
default:
return 0;
}
@@ -2800,6 +2811,331 @@ static int btintel_set_dsbr(struct hci_dev *hdev, struct intel_version_tlv *ver)
return 0;
}
#ifdef CONFIG_ACPI
static acpi_status btintel_evaluate_acpi_method(struct hci_dev *hdev,
acpi_string method,
union acpi_object **ptr,
u8 pkg_size)
{
struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
union acpi_object *p;
acpi_status status;
acpi_handle handle;
handle = ACPI_HANDLE(GET_HCIDEV_DEV(hdev));
if (!handle) {
bt_dev_dbg(hdev, "ACPI-BT: No ACPI support for Bluetooth device");
return AE_NOT_EXIST;
}
status = acpi_evaluate_object(handle, method, NULL, &buffer);
if (ACPI_FAILURE(status)) {
bt_dev_dbg(hdev, "ACPI-BT: ACPI Failure: %s method: %s",
acpi_format_exception(status), method);
return status;
}
p = buffer.pointer;
if (p->type != ACPI_TYPE_PACKAGE || p->package.count < pkg_size) {
bt_dev_warn(hdev, "ACPI-BT: Invalid object type: %d or package count: %d",
p->type, p->package.count);
kfree(buffer.pointer);
return AE_ERROR;
}
*ptr = buffer.pointer;
return 0;
}
static union acpi_object *btintel_acpi_get_bt_pkg(union acpi_object *buffer)
{
union acpi_object *domain, *bt_pkg;
int i;
for (i = 1; i < buffer->package.count; i++) {
bt_pkg = &buffer->package.elements[i];
domain = &bt_pkg->package.elements[0];
if (domain->type == ACPI_TYPE_INTEGER &&
domain->integer.value == BTINTEL_BT_DOMAIN)
return bt_pkg;
}
return ERR_PTR(-ENOENT);
}
static int btintel_send_sar_ddc(struct hci_dev *hdev, struct btintel_cp_ddc_write *data, u8 len)
{
struct sk_buff *skb;
skb = __hci_cmd_sync(hdev, 0xfc8b, len, data, HCI_CMD_TIMEOUT);
if (IS_ERR(skb)) {
bt_dev_warn(hdev, "Failed to send sar ddc id:0x%4.4x (%ld)",
le16_to_cpu(data->id), PTR_ERR(skb));
return PTR_ERR(skb);
}
kfree_skb(skb);
return 0;
}
static int btintel_send_edr(struct hci_dev *hdev, struct btintel_cp_ddc_write *cmd,
int id, struct btintel_sar_inc_pwr *sar)
{
cmd->len = 5;
cmd->id = cpu_to_le16(id);
cmd->data[0] = sar->br >> 3;
cmd->data[1] = sar->edr2 >> 3;
cmd->data[2] = sar->edr3 >> 3;
return btintel_send_sar_ddc(hdev, cmd, 6);
}
static int btintel_send_le(struct hci_dev *hdev, struct btintel_cp_ddc_write *cmd,
int id, struct btintel_sar_inc_pwr *sar)
{
cmd->len = 3;
cmd->id = cpu_to_le16(id);
cmd->data[0] = min3(sar->le, sar->le_lr, sar->le_2mhz) >> 3;
return btintel_send_sar_ddc(hdev, cmd, 4);
}
static int btintel_send_br(struct hci_dev *hdev, struct btintel_cp_ddc_write *cmd,
int id, struct btintel_sar_inc_pwr *sar)
{
cmd->len = 3;
cmd->id = cpu_to_le16(id);
cmd->data[0] = sar->br >> 3;
return btintel_send_sar_ddc(hdev, cmd, 4);
}
static int btintel_send_br_mutual(struct hci_dev *hdev, struct btintel_cp_ddc_write *cmd,
int id, struct btintel_sar_inc_pwr *sar)
{
cmd->len = 3;
cmd->id = cpu_to_le16(id);
cmd->data[0] = sar->br;
return btintel_send_sar_ddc(hdev, cmd, 4);
}
static int btintel_send_edr2(struct hci_dev *hdev, struct btintel_cp_ddc_write *cmd,
int id, struct btintel_sar_inc_pwr *sar)
{
cmd->len = 3;
cmd->id = cpu_to_le16(id);
cmd->data[0] = sar->edr2;
return btintel_send_sar_ddc(hdev, cmd, 4);
}
static int btintel_send_edr3(struct hci_dev *hdev, struct btintel_cp_ddc_write *cmd,
int id, struct btintel_sar_inc_pwr *sar)
{
cmd->len = 3;
cmd->id = cpu_to_le16(id);
cmd->data[0] = sar->edr3;
return btintel_send_sar_ddc(hdev, cmd, 4);
}
static int btintel_set_legacy_sar(struct hci_dev *hdev, struct btintel_sar_inc_pwr *sar)
{
struct btintel_cp_ddc_write *cmd;
u8 buffer[64];
int ret;
cmd = (void *)buffer;
ret = btintel_send_br(hdev, cmd, 0x0131, sar);
if (ret)
return ret;
ret = btintel_send_br(hdev, cmd, 0x0132, sar);
if (ret)
return ret;
ret = btintel_send_le(hdev, cmd, 0x0133, sar);
if (ret)
return ret;
ret = btintel_send_edr(hdev, cmd, 0x0137, sar);
if (ret)
return ret;
ret = btintel_send_edr(hdev, cmd, 0x0138, sar);
if (ret)
return ret;
ret = btintel_send_edr(hdev, cmd, 0x013b, sar);
if (ret)
return ret;
ret = btintel_send_edr(hdev, cmd, 0x013c, sar);
return ret;
}
static int btintel_set_mutual_sar(struct hci_dev *hdev, struct btintel_sar_inc_pwr *sar)
{
struct btintel_cp_ddc_write *cmd;
struct sk_buff *skb;
u8 buffer[64];
bool enable;
int ret;
cmd = (void *)buffer;
cmd->len = 3;
cmd->id = cpu_to_le16(0x019e);
if (sar->revision == BTINTEL_SAR_INC_PWR &&
sar->inc_power_mode == BTINTEL_SAR_INC_PWR_SUPPORTED)
cmd->data[0] = 0x01;
else
cmd->data[0] = 0x00;
ret = btintel_send_sar_ddc(hdev, cmd, 4);
if (ret)
return ret;
if (sar->revision == BTINTEL_SAR_INC_PWR &&
sar->inc_power_mode == BTINTEL_SAR_INC_PWR_SUPPORTED) {
cmd->len = 3;
cmd->id = cpu_to_le16(0x019f);
cmd->data[0] = sar->sar_2400_chain_a;
ret = btintel_send_sar_ddc(hdev, cmd, 4);
if (ret)
return ret;
}
ret = btintel_send_br_mutual(hdev, cmd, 0x01a0, sar);
if (ret)
return ret;
ret = btintel_send_edr2(hdev, cmd, 0x01a1, sar);
if (ret)
return ret;
ret = btintel_send_edr3(hdev, cmd, 0x01a2, sar);
if (ret)
return ret;
ret = btintel_send_le(hdev, cmd, 0x01a3, sar);
if (ret)
return ret;
enable = true;
skb = __hci_cmd_sync(hdev, 0xfe25, 1, &enable, HCI_CMD_TIMEOUT);
if (IS_ERR(skb)) {
bt_dev_warn(hdev, "Failed to send Intel SAR Enable (%ld)", PTR_ERR(skb));
return PTR_ERR(skb);
}
kfree_skb(skb);
return 0;
}
static int btintel_sar_send_to_device(struct hci_dev *hdev, struct btintel_sar_inc_pwr *sar,
struct intel_version_tlv *ver)
{
u16 cnvi, cnvr;
int ret;
cnvi = ver->cnvi_top & 0xfff;
cnvr = ver->cnvr_top & 0xfff;
if (cnvi < BTINTEL_CNVI_BLAZARI && cnvr < BTINTEL_CNVR_FMP2) {
bt_dev_info(hdev, "Applying legacy Bluetooth SAR");
ret = btintel_set_legacy_sar(hdev, sar);
} else if (cnvi == BTINTEL_CNVI_GAP || cnvr == BTINTEL_CNVR_FMP2) {
bt_dev_info(hdev, "Applying mutual Bluetooth SAR");
ret = btintel_set_mutual_sar(hdev, sar);
} else {
ret = -EOPNOTSUPP;
}
return ret;
}
static int btintel_acpi_set_sar(struct hci_dev *hdev, struct intel_version_tlv *ver)
{
union acpi_object *bt_pkg, *buffer = NULL;
struct btintel_sar_inc_pwr sar;
acpi_status status;
u8 revision;
int ret;
status = btintel_evaluate_acpi_method(hdev, "BRDS", &buffer, 2);
if (ACPI_FAILURE(status))
return -ENOENT;
bt_pkg = btintel_acpi_get_bt_pkg(buffer);
if (IS_ERR(bt_pkg)) {
ret = PTR_ERR(bt_pkg);
goto error;
}
if (!bt_pkg->package.count) {
ret = -EINVAL;
goto error;
}
revision = buffer->package.elements[0].integer.value;
if (revision > BTINTEL_SAR_INC_PWR) {
bt_dev_dbg(hdev, "BT_SAR: revision: 0x%2.2x not supported", revision);
ret = -EOPNOTSUPP;
goto error;
}
memset(&sar, 0, sizeof(sar));
if (revision == BTINTEL_SAR_LEGACY && bt_pkg->package.count == 8) {
sar.revision = revision;
sar.bt_sar_bios = bt_pkg->package.elements[1].integer.value;
sar.br = bt_pkg->package.elements[2].integer.value;
sar.edr2 = bt_pkg->package.elements[3].integer.value;
sar.edr3 = bt_pkg->package.elements[4].integer.value;
sar.le = bt_pkg->package.elements[5].integer.value;
sar.le_2mhz = bt_pkg->package.elements[6].integer.value;
sar.le_lr = bt_pkg->package.elements[7].integer.value;
} else if (revision == BTINTEL_SAR_INC_PWR && bt_pkg->package.count == 10) {
sar.revision = revision;
sar.bt_sar_bios = bt_pkg->package.elements[1].integer.value;
sar.inc_power_mode = bt_pkg->package.elements[2].integer.value;
sar.sar_2400_chain_a = bt_pkg->package.elements[3].integer.value;
sar.br = bt_pkg->package.elements[4].integer.value;
sar.edr2 = bt_pkg->package.elements[5].integer.value;
sar.edr3 = bt_pkg->package.elements[6].integer.value;
sar.le = bt_pkg->package.elements[7].integer.value;
sar.le_2mhz = bt_pkg->package.elements[8].integer.value;
sar.le_lr = bt_pkg->package.elements[9].integer.value;
} else {
ret = -EINVAL;
goto error;
}
/* Apply only if it is enabled in BIOS */
if (sar.bt_sar_bios != 1) {
bt_dev_dbg(hdev, "Bluetooth SAR is not enabled");
ret = -EOPNOTSUPP;
goto error;
}
ret = btintel_sar_send_to_device(hdev, &sar, ver);
error:
kfree(buffer);
return ret;
}
#endif /* CONFIG_ACPI */
static int btintel_set_specific_absorption_rate(struct hci_dev *hdev,
struct intel_version_tlv *ver)
{
#ifdef CONFIG_ACPI
return btintel_acpi_set_sar(hdev, ver);
#endif
return 0;
}
int btintel_bootloader_setup_tlv(struct hci_dev *hdev,
struct intel_version_tlv *ver)
{
@@ -2877,6 +3213,9 @@ int btintel_bootloader_setup_tlv(struct hci_dev *hdev,
hci_dev_clear_flag(hdev, HCI_QUALITY_REPORT);
/* Send sar values to controller */
btintel_set_specific_absorption_rate(hdev, ver);
/* Set PPAG feature */
btintel_set_ppag(hdev, ver);
@@ -2919,6 +3258,7 @@ void btintel_set_msft_opcode(struct hci_dev *hdev, u8 hw_variant)
case 0x1c:
case 0x1d:
case 0x1e:
case 0x1f:
hci_set_msft_opcode(hdev, 0xFC1E);
break;
default:
@@ -3258,6 +3598,7 @@ static int btintel_setup_combined(struct hci_dev *hdev)
case 0x1b:
case 0x1d:
case 0x1e:
case 0x1f:
/* Display version information of TLV type */
btintel_version_info_tlv(hdev, &ver_tlv);

View File

@@ -56,6 +56,10 @@ struct intel_tlv {
#define BTINTEL_CNVI_BLAZARIW 0x901
#define BTINTEL_CNVI_GAP 0x910
#define BTINTEL_CNVI_BLAZARU 0x930
#define BTINTEL_CNVI_SCP 0xA00
/* CNVR */
#define BTINTEL_CNVR_FMP2 0x910
#define BTINTEL_IMG_BOOTLOADER 0x01 /* Bootloader image */
#define BTINTEL_IMG_IML 0x02 /* Intermediate image */
@@ -164,6 +168,26 @@ struct hci_ppag_enable_cmd {
#define INTEL_TLV_DEBUG_EXCEPTION 0x02
#define INTEL_TLV_TEST_EXCEPTION 0xDE
struct btintel_cp_ddc_write {
u8 len;
__le16 id;
u8 data[];
} __packed;
/* Bluetooth SAR feature (BRDS), Revision 1 */
struct btintel_sar_inc_pwr {
u8 revision;
u32 bt_sar_bios; /* Mode of SAR control to be used, 1:enabled in bios */
u32 inc_power_mode; /* Increased power mode */
u8 sar_2400_chain_a; /* Sar power restriction LB */
u8 br;
u8 edr2;
u8 edr3;
u8 le;
u8 le_2mhz;
u8 le_lr;
};
#define INTEL_HW_PLATFORM(cnvx_bt) ((u8)(((cnvx_bt) & 0x0000ff00) >> 8))
#define INTEL_HW_VARIANT(cnvx_bt) ((u8)(((cnvx_bt) & 0x003f0000) >> 16))
#define INTEL_CNVX_TOP_TYPE(cnvx_top) ((cnvx_top) & 0x00000fff)

View File

@@ -36,6 +36,7 @@
/* Intel Bluetooth PCIe device id table */
static const struct pci_device_id btintel_pcie_table[] = {
{ BTINTEL_PCI_DEVICE(0xA876, PCI_ANY_ID) },
{ BTINTEL_PCI_DEVICE(0xE476, PCI_ANY_ID) },
{ 0 }
};
MODULE_DEVICE_TABLE(pci, btintel_pcie_table);
@@ -48,6 +49,19 @@ MODULE_DEVICE_TABLE(pci, btintel_pcie_table);
#define BTINTEL_PCIE_HCI_EVT_PKT 0x00000004
#define BTINTEL_PCIE_HCI_ISO_PKT 0x00000005
#define BTINTEL_PCIE_MAGIC_NUM 0xA5A5A5A5
#define BTINTEL_PCIE_BLZR_HWEXP_SIZE 1024
#define BTINTEL_PCIE_BLZR_HWEXP_DMP_ADDR 0xB00A7C00
#define BTINTEL_PCIE_SCP_HWEXP_SIZE 4096
#define BTINTEL_PCIE_SCP_HWEXP_DMP_ADDR 0xB030F800
#define BTINTEL_PCIE_MAGIC_NUM 0xA5A5A5A5
#define BTINTEL_PCIE_TRIGGER_REASON_USER_TRIGGER 0x17A2
#define BTINTEL_PCIE_TRIGGER_REASON_FW_ASSERT 0x1E61
/* Alive interrupt context */
enum {
BTINTEL_PCIE_ROM,
@@ -59,6 +73,83 @@ enum {
BTINTEL_PCIE_D3
};
/* Structure for dbgc fragment buffer
* @buf_addr_lsb: LSB of the buffer's physical address
* @buf_addr_msb: MSB of the buffer's physical address
* @buf_size: Total size of the buffer
*/
struct btintel_pcie_dbgc_ctxt_buf {
u32 buf_addr_lsb;
u32 buf_addr_msb;
u32 buf_size;
};
/* Structure for dbgc fragment
* @magic_num: 0XA5A5A5A5
* @ver: For Driver-FW compatibility
* @total_size: Total size of the payload debug info
* @num_buf: Num of allocated debug bufs
* @bufs: All buffer's addresses and sizes
*/
struct btintel_pcie_dbgc_ctxt {
u32 magic_num;
u32 ver;
u32 total_size;
u32 num_buf;
struct btintel_pcie_dbgc_ctxt_buf bufs[BTINTEL_PCIE_DBGC_BUFFER_COUNT];
};
/* This function initializes the memory for DBGC buffers and formats the
* DBGC fragment which consists header info and DBGC buffer's LSB, MSB and
* size as the payload
*/
static int btintel_pcie_setup_dbgc(struct btintel_pcie_data *data)
{
struct btintel_pcie_dbgc_ctxt db_frag;
struct data_buf *buf;
int i;
data->dbgc.count = BTINTEL_PCIE_DBGC_BUFFER_COUNT;
data->dbgc.bufs = devm_kcalloc(&data->pdev->dev, data->dbgc.count,
sizeof(*buf), GFP_KERNEL);
if (!data->dbgc.bufs)
return -ENOMEM;
data->dbgc.buf_v_addr = dmam_alloc_coherent(&data->pdev->dev,
data->dbgc.count *
BTINTEL_PCIE_DBGC_BUFFER_SIZE,
&data->dbgc.buf_p_addr,
GFP_KERNEL | __GFP_NOWARN);
if (!data->dbgc.buf_v_addr)
return -ENOMEM;
data->dbgc.frag_v_addr = dmam_alloc_coherent(&data->pdev->dev,
sizeof(struct btintel_pcie_dbgc_ctxt),
&data->dbgc.frag_p_addr,
GFP_KERNEL | __GFP_NOWARN);
if (!data->dbgc.frag_v_addr)
return -ENOMEM;
data->dbgc.frag_size = sizeof(struct btintel_pcie_dbgc_ctxt);
db_frag.magic_num = BTINTEL_PCIE_MAGIC_NUM;
db_frag.ver = BTINTEL_PCIE_DBGC_FRAG_VERSION;
db_frag.total_size = BTINTEL_PCIE_DBGC_FRAG_PAYLOAD_SIZE;
db_frag.num_buf = BTINTEL_PCIE_DBGC_FRAG_BUFFER_COUNT;
for (i = 0; i < data->dbgc.count; i++) {
buf = &data->dbgc.bufs[i];
buf->data_p_addr = data->dbgc.buf_p_addr + i * BTINTEL_PCIE_DBGC_BUFFER_SIZE;
buf->data = data->dbgc.buf_v_addr + i * BTINTEL_PCIE_DBGC_BUFFER_SIZE;
db_frag.bufs[i].buf_addr_lsb = lower_32_bits(buf->data_p_addr);
db_frag.bufs[i].buf_addr_msb = upper_32_bits(buf->data_p_addr);
db_frag.bufs[i].buf_size = BTINTEL_PCIE_DBGC_BUFFER_SIZE;
}
memcpy(data->dbgc.frag_v_addr, &db_frag, sizeof(db_frag));
return 0;
}
static inline void ipc_print_ia_ring(struct hci_dev *hdev, struct ia *ia,
u16 queue_num)
{
@@ -273,6 +364,271 @@ static int btintel_pcie_reset_bt(struct btintel_pcie_data *data)
return reg == 0 ? 0 : -ENODEV;
}
static void btintel_pcie_mac_init(struct btintel_pcie_data *data)
{
u32 reg;
/* Set MAC_INIT bit to start primary bootloader */
reg = btintel_pcie_rd_reg32(data, BTINTEL_PCIE_CSR_FUNC_CTRL_REG);
reg &= ~(BTINTEL_PCIE_CSR_FUNC_CTRL_FUNC_INIT |
BTINTEL_PCIE_CSR_FUNC_CTRL_BUS_MASTER_DISCON |
BTINTEL_PCIE_CSR_FUNC_CTRL_SW_RESET);
reg |= (BTINTEL_PCIE_CSR_FUNC_CTRL_FUNC_ENA |
BTINTEL_PCIE_CSR_FUNC_CTRL_MAC_INIT);
btintel_pcie_wr_reg32(data, BTINTEL_PCIE_CSR_FUNC_CTRL_REG, reg);
}
static int btintel_pcie_add_dmp_data(struct hci_dev *hdev, const void *data, int size)
{
struct sk_buff *skb;
int err;
skb = alloc_skb(size, GFP_ATOMIC);
if (!skb)
return -ENOMEM;
skb_put_data(skb, data, size);
err = hci_devcd_append(hdev, skb);
if (err) {
bt_dev_err(hdev, "Failed to append data in the coredump");
return err;
}
return 0;
}
static int btintel_pcie_get_mac_access(struct btintel_pcie_data *data)
{
u32 reg;
int retry = 15;
reg = btintel_pcie_rd_reg32(data, BTINTEL_PCIE_CSR_FUNC_CTRL_REG);
reg |= BTINTEL_PCIE_CSR_FUNC_CTRL_STOP_MAC_ACCESS_DIS;
reg |= BTINTEL_PCIE_CSR_FUNC_CTRL_XTAL_CLK_REQ;
if ((reg & BTINTEL_PCIE_CSR_FUNC_CTRL_MAC_ACCESS_STS) == 0)
reg |= BTINTEL_PCIE_CSR_FUNC_CTRL_MAC_ACCESS_REQ;
btintel_pcie_wr_reg32(data, BTINTEL_PCIE_CSR_FUNC_CTRL_REG, reg);
do {
reg = btintel_pcie_rd_reg32(data, BTINTEL_PCIE_CSR_FUNC_CTRL_REG);
if (reg & BTINTEL_PCIE_CSR_FUNC_CTRL_MAC_ACCESS_STS)
return 0;
/* Need delay here for Target Access harwdware to settle down*/
usleep_range(1000, 1200);
} while (--retry > 0);
return -ETIME;
}
static void btintel_pcie_release_mac_access(struct btintel_pcie_data *data)
{
u32 reg;
reg = btintel_pcie_rd_reg32(data, BTINTEL_PCIE_CSR_FUNC_CTRL_REG);
if (reg & BTINTEL_PCIE_CSR_FUNC_CTRL_MAC_ACCESS_REQ)
reg &= ~BTINTEL_PCIE_CSR_FUNC_CTRL_MAC_ACCESS_REQ;
if (reg & BTINTEL_PCIE_CSR_FUNC_CTRL_STOP_MAC_ACCESS_DIS)
reg &= ~BTINTEL_PCIE_CSR_FUNC_CTRL_STOP_MAC_ACCESS_DIS;
if (reg & BTINTEL_PCIE_CSR_FUNC_CTRL_XTAL_CLK_REQ)
reg &= ~BTINTEL_PCIE_CSR_FUNC_CTRL_XTAL_CLK_REQ;
btintel_pcie_wr_reg32(data, BTINTEL_PCIE_CSR_FUNC_CTRL_REG, reg);
}
static void btintel_pcie_copy_tlv(struct sk_buff *skb, enum btintel_pcie_tlv_type type,
void *data, int size)
{
struct intel_tlv *tlv;
tlv = skb_put(skb, sizeof(*tlv) + size);
tlv->type = type;
tlv->len = size;
memcpy(tlv->val, data, tlv->len);
}
static int btintel_pcie_read_dram_buffers(struct btintel_pcie_data *data)
{
u32 offset, prev_size, wr_ptr_status, dump_size, i;
struct btintel_pcie_dbgc *dbgc = &data->dbgc;
u8 buf_idx, dump_time_len, fw_build;
struct hci_dev *hdev = data->hdev;
struct intel_tlv *tlv;
struct timespec64 now;
struct sk_buff *skb;
struct tm tm_now;
char buf[256];
u16 hdr_len;
int ret;
wr_ptr_status = btintel_pcie_rd_dev_mem(data, BTINTEL_PCIE_DBGC_CUR_DBGBUFF_STATUS);
offset = wr_ptr_status & BTINTEL_PCIE_DBG_OFFSET_BIT_MASK;
buf_idx = BTINTEL_PCIE_DBGC_DBG_BUF_IDX(wr_ptr_status);
if (buf_idx > dbgc->count) {
bt_dev_warn(hdev, "Buffer index is invalid");
return -EINVAL;
}
prev_size = buf_idx * BTINTEL_PCIE_DBGC_BUFFER_SIZE;
if (prev_size + offset >= prev_size)
data->dmp_hdr.write_ptr = prev_size + offset;
else
return -EINVAL;
ktime_get_real_ts64(&now);
time64_to_tm(now.tv_sec, 0, &tm_now);
dump_time_len = snprintf(buf, sizeof(buf), "Dump Time: %02d-%02d-%04ld %02d:%02d:%02d",
tm_now.tm_mday, tm_now.tm_mon + 1, tm_now.tm_year + 1900,
tm_now.tm_hour, tm_now.tm_min, tm_now.tm_sec);
fw_build = snprintf(buf + dump_time_len, sizeof(buf) - dump_time_len,
"Firmware Timestamp: Year %u WW %02u buildtype %u build %u",
2000 + (data->dmp_hdr.fw_timestamp >> 8),
data->dmp_hdr.fw_timestamp & 0xff, data->dmp_hdr.fw_build_type,
data->dmp_hdr.fw_build_num);
hdr_len = sizeof(*tlv) + sizeof(data->dmp_hdr.cnvi_bt) +
sizeof(*tlv) + sizeof(data->dmp_hdr.write_ptr) +
sizeof(*tlv) + sizeof(data->dmp_hdr.wrap_ctr) +
sizeof(*tlv) + sizeof(data->dmp_hdr.trigger_reason) +
sizeof(*tlv) + sizeof(data->dmp_hdr.fw_git_sha1) +
sizeof(*tlv) + sizeof(data->dmp_hdr.cnvr_top) +
sizeof(*tlv) + sizeof(data->dmp_hdr.cnvi_top) +
sizeof(*tlv) + dump_time_len +
sizeof(*tlv) + fw_build;
dump_size = hdr_len + sizeof(hdr_len);
skb = alloc_skb(dump_size, GFP_KERNEL);
if (!skb)
return -ENOMEM;
/* Add debug buffers data length to dump size */
dump_size += BTINTEL_PCIE_DBGC_BUFFER_SIZE * dbgc->count;
ret = hci_devcd_init(hdev, dump_size);
if (ret) {
bt_dev_err(hdev, "Failed to init devcoredump, err %d", ret);
kfree_skb(skb);
return ret;
}
skb_put_data(skb, &hdr_len, sizeof(hdr_len));
btintel_pcie_copy_tlv(skb, BTINTEL_CNVI_BT, &data->dmp_hdr.cnvi_bt,
sizeof(data->dmp_hdr.cnvi_bt));
btintel_pcie_copy_tlv(skb, BTINTEL_WRITE_PTR, &data->dmp_hdr.write_ptr,
sizeof(data->dmp_hdr.write_ptr));
data->dmp_hdr.wrap_ctr = btintel_pcie_rd_dev_mem(data,
BTINTEL_PCIE_DBGC_DBGBUFF_WRAP_ARND);
btintel_pcie_copy_tlv(skb, BTINTEL_WRAP_CTR, &data->dmp_hdr.wrap_ctr,
sizeof(data->dmp_hdr.wrap_ctr));
btintel_pcie_copy_tlv(skb, BTINTEL_TRIGGER_REASON, &data->dmp_hdr.trigger_reason,
sizeof(data->dmp_hdr.trigger_reason));
btintel_pcie_copy_tlv(skb, BTINTEL_FW_SHA, &data->dmp_hdr.fw_git_sha1,
sizeof(data->dmp_hdr.fw_git_sha1));
btintel_pcie_copy_tlv(skb, BTINTEL_CNVR_TOP, &data->dmp_hdr.cnvr_top,
sizeof(data->dmp_hdr.cnvr_top));
btintel_pcie_copy_tlv(skb, BTINTEL_CNVI_TOP, &data->dmp_hdr.cnvi_top,
sizeof(data->dmp_hdr.cnvi_top));
btintel_pcie_copy_tlv(skb, BTINTEL_DUMP_TIME, buf, dump_time_len);
btintel_pcie_copy_tlv(skb, BTINTEL_FW_BUILD, buf + dump_time_len, fw_build);
ret = hci_devcd_append(hdev, skb);
if (ret)
goto exit_err;
for (i = 0; i < dbgc->count; i++) {
ret = btintel_pcie_add_dmp_data(hdev, dbgc->bufs[i].data,
BTINTEL_PCIE_DBGC_BUFFER_SIZE);
if (ret)
break;
}
exit_err:
hci_devcd_complete(hdev);
return ret;
}
static void btintel_pcie_dump_traces(struct hci_dev *hdev)
{
struct btintel_pcie_data *data = hci_get_drvdata(hdev);
int ret = 0;
ret = btintel_pcie_get_mac_access(data);
if (ret) {
bt_dev_err(hdev, "Failed to get mac access: (%d)", ret);
return;
}
ret = btintel_pcie_read_dram_buffers(data);
btintel_pcie_release_mac_access(data);
if (ret)
bt_dev_err(hdev, "Failed to dump traces: (%d)", ret);
}
static void btintel_pcie_dump_hdr(struct hci_dev *hdev, struct sk_buff *skb)
{
struct btintel_pcie_data *data = hci_get_drvdata(hdev);
u16 len = skb->len;
u16 *hdrlen_ptr;
char buf[80];
hdrlen_ptr = skb_put_zero(skb, sizeof(len));
snprintf(buf, sizeof(buf), "Controller Name: 0x%X\n",
INTEL_HW_VARIANT(data->dmp_hdr.cnvi_bt));
skb_put_data(skb, buf, strlen(buf));
snprintf(buf, sizeof(buf), "Firmware Build Number: %u\n",
data->dmp_hdr.fw_build_num);
skb_put_data(skb, buf, strlen(buf));
snprintf(buf, sizeof(buf), "Driver: %s\n", data->dmp_hdr.driver_name);
skb_put_data(skb, buf, strlen(buf));
snprintf(buf, sizeof(buf), "Vendor: Intel\n");
skb_put_data(skb, buf, strlen(buf));
*hdrlen_ptr = skb->len - len;
}
static void btintel_pcie_dump_notify(struct hci_dev *hdev, int state)
{
struct btintel_pcie_data *data = hci_get_drvdata(hdev);
switch (state) {
case HCI_DEVCOREDUMP_IDLE:
data->dmp_hdr.state = HCI_DEVCOREDUMP_IDLE;
break;
case HCI_DEVCOREDUMP_ACTIVE:
data->dmp_hdr.state = HCI_DEVCOREDUMP_ACTIVE;
break;
case HCI_DEVCOREDUMP_TIMEOUT:
case HCI_DEVCOREDUMP_ABORT:
case HCI_DEVCOREDUMP_DONE:
data->dmp_hdr.state = HCI_DEVCOREDUMP_IDLE;
break;
}
}
/* This function enables BT function by setting BTINTEL_PCIE_CSR_FUNC_CTRL_MAC_INIT bit in
* BTINTEL_PCIE_CSR_FUNC_CTRL_REG register and wait for MSI-X with
* BTINTEL_PCIE_MSIX_HW_INT_CAUSES_GP0.
@@ -329,20 +685,6 @@ static int btintel_pcie_enable_bt(struct btintel_pcie_data *data)
return 0;
}
/* BIT(0) - ROM, BIT(1) - IML and BIT(3) - OP
* Sometimes during firmware image switching from ROM to IML or IML to OP image,
* the previous image bit is not cleared by firmware when alive interrupt is
* received. Driver needs to take care of these sticky bits when deciding the
* current image running on controller.
* Ex: 0x10 and 0x11 - both represents that controller is running IML
*/
static inline bool btintel_pcie_in_rom(struct btintel_pcie_data *data)
{
return data->boot_stage_cache & BTINTEL_PCIE_CSR_BOOT_STAGE_ROM &&
!(data->boot_stage_cache & BTINTEL_PCIE_CSR_BOOT_STAGE_IML) &&
!(data->boot_stage_cache & BTINTEL_PCIE_CSR_BOOT_STAGE_OPFW);
}
static inline bool btintel_pcie_in_op(struct btintel_pcie_data *data)
{
return data->boot_stage_cache & BTINTEL_PCIE_CSR_BOOT_STAGE_OPFW;
@@ -393,6 +735,27 @@ static inline char *btintel_pcie_alivectxt_state2str(u32 alive_intr_ctxt)
}
}
static int btintel_pcie_read_device_mem(struct btintel_pcie_data *data,
void *buf, u32 dev_addr, int len)
{
int err;
u32 *val = buf;
/* Get device mac access */
err = btintel_pcie_get_mac_access(data);
if (err) {
bt_dev_err(data->hdev, "Failed to get mac access %d", err);
return err;
}
for (; len > 0; len -= 4, dev_addr += 4, val++)
*val = btintel_pcie_rd_dev_mem(data, dev_addr);
btintel_pcie_release_mac_access(data);
return 0;
}
/* This function handles the MSI-X interrupt for gp0 cause (bit 0 in
* BTINTEL_PCIE_CSR_MSIX_HW_INT_CAUSES) which is sent for boot stage and image response.
*/
@@ -714,6 +1077,126 @@ exit_error:
return ret;
}
static void btintel_pcie_read_hwexp(struct btintel_pcie_data *data)
{
int len, err, offset, pending;
struct sk_buff *skb;
u8 *buf, prefix[64];
u32 addr, val;
u16 pkt_len;
struct tlv {
u8 type;
__le16 len;
u8 val[];
} __packed;
struct tlv *tlv;
switch (data->dmp_hdr.cnvi_top & 0xfff) {
case BTINTEL_CNVI_BLAZARI:
case BTINTEL_CNVI_BLAZARIW:
/* only from step B0 onwards */
if (INTEL_CNVX_TOP_STEP(data->dmp_hdr.cnvi_top) != 0x01)
return;
len = BTINTEL_PCIE_BLZR_HWEXP_SIZE; /* exception data length */
addr = BTINTEL_PCIE_BLZR_HWEXP_DMP_ADDR;
break;
case BTINTEL_CNVI_SCP:
len = BTINTEL_PCIE_SCP_HWEXP_SIZE;
addr = BTINTEL_PCIE_SCP_HWEXP_DMP_ADDR;
break;
default:
bt_dev_err(data->hdev, "Unsupported cnvi 0x%8.8x", data->dmp_hdr.cnvi_top);
return;
}
buf = kzalloc(len, GFP_KERNEL);
if (!buf)
goto exit_on_error;
btintel_pcie_mac_init(data);
err = btintel_pcie_read_device_mem(data, buf, addr, len);
if (err)
goto exit_on_error;
val = get_unaligned_le32(buf);
if (val != BTINTEL_PCIE_MAGIC_NUM) {
bt_dev_err(data->hdev, "Invalid exception dump signature: 0x%8.8x",
val);
goto exit_on_error;
}
snprintf(prefix, sizeof(prefix), "Bluetooth: %s: ", bt_dev_name(data->hdev));
offset = 4;
do {
pending = len - offset;
if (pending < sizeof(*tlv))
break;
tlv = (struct tlv *)(buf + offset);
/* If type == 0, then there are no more TLVs to be parsed */
if (!tlv->type) {
bt_dev_dbg(data->hdev, "Invalid TLV type 0");
break;
}
pkt_len = le16_to_cpu(tlv->len);
offset += sizeof(*tlv);
pending = len - offset;
if (pkt_len > pending)
break;
offset += pkt_len;
/* Only TLVs of type == 1 are HCI events, no need to process other
* TLVs
*/
if (tlv->type != 1)
continue;
bt_dev_dbg(data->hdev, "TLV packet length: %u", pkt_len);
if (pkt_len > HCI_MAX_EVENT_SIZE)
break;
skb = bt_skb_alloc(pkt_len, GFP_KERNEL);
if (!skb)
goto exit_on_error;
hci_skb_pkt_type(skb) = HCI_EVENT_PKT;
skb_put_data(skb, tlv->val, pkt_len);
/* copy Intel specific pcie packet type */
val = BTINTEL_PCIE_HCI_EVT_PKT;
memcpy(skb_push(skb, BTINTEL_PCIE_HCI_TYPE_LEN), &val,
BTINTEL_PCIE_HCI_TYPE_LEN);
print_hex_dump(KERN_DEBUG, prefix, DUMP_PREFIX_OFFSET, 16, 1,
tlv->val, pkt_len, false);
btintel_pcie_recv_frame(data, skb);
} while (offset < len);
exit_on_error:
kfree(buf);
}
static void btintel_pcie_msix_hw_exp_handler(struct btintel_pcie_data *data)
{
bt_dev_err(data->hdev, "Received hw exception interrupt");
if (test_and_set_bit(BTINTEL_PCIE_CORE_HALTED, &data->flags))
return;
if (test_and_set_bit(BTINTEL_PCIE_HWEXP_INPROGRESS, &data->flags))
return;
/* Trigger device core dump when there is HW exception */
if (!test_and_set_bit(BTINTEL_PCIE_COREDUMP_INPROGRESS, &data->flags))
data->dmp_hdr.trigger_reason = BTINTEL_PCIE_TRIGGER_REASON_FW_ASSERT;
queue_work(data->workqueue, &data->rx_work);
}
static void btintel_pcie_rx_work(struct work_struct *work)
{
struct btintel_pcie_data *data = container_of(work,
@@ -722,6 +1205,23 @@ static void btintel_pcie_rx_work(struct work_struct *work)
int err;
struct hci_dev *hdev = data->hdev;
if (test_bit(BTINTEL_PCIE_HWEXP_INPROGRESS, &data->flags)) {
/* Unlike usb products, controller will not send hardware
* exception event on exception. Instead controller writes the
* hardware event to device memory along with optional debug
* events, raises MSIX and halts. Driver shall read the
* exception event from device memory and passes it stack for
* further processing.
*/
btintel_pcie_read_hwexp(data);
clear_bit(BTINTEL_PCIE_HWEXP_INPROGRESS, &data->flags);
}
if (test_bit(BTINTEL_PCIE_COREDUMP_INPROGRESS, &data->flags)) {
btintel_pcie_dump_traces(data->hdev);
clear_bit(BTINTEL_PCIE_COREDUMP_INPROGRESS, &data->flags);
}
/* Process the sk_buf in queue and send to the HCI layer */
while ((skb = skb_dequeue(&data->rx_skb_q))) {
err = btintel_pcie_recv_frame(data, skb);
@@ -840,6 +1340,10 @@ static irqreturn_t btintel_pcie_irq_msix_handler(int irq, void *dev_id)
return IRQ_NONE;
}
/* This interrupt is raised when there is an hardware exception */
if (intr_hw & BTINTEL_PCIE_MSIX_HW_INT_CAUSES_HWEXP)
btintel_pcie_msix_hw_exp_handler(data);
/* This interrupt is triggered by the firmware after updating
* boot_stage register and image_response register
*/
@@ -920,7 +1424,8 @@ struct btintel_pcie_causes_list {
static struct btintel_pcie_causes_list causes_list[] = {
{ BTINTEL_PCIE_MSIX_FH_INT_CAUSES_0, BTINTEL_PCIE_CSR_MSIX_FH_INT_MASK, 0x00 },
{ BTINTEL_PCIE_MSIX_FH_INT_CAUSES_1, BTINTEL_PCIE_CSR_MSIX_FH_INT_MASK, 0x01 },
{ BTINTEL_PCIE_MSIX_HW_INT_CAUSES_GP0, BTINTEL_PCIE_CSR_MSIX_HW_INT_MASK, 0x20 },
{ BTINTEL_PCIE_MSIX_HW_INT_CAUSES_GP0, BTINTEL_PCIE_CSR_MSIX_HW_INT_MASK, 0x20 },
{ BTINTEL_PCIE_MSIX_HW_INT_CAUSES_HWEXP, BTINTEL_PCIE_CSR_MSIX_HW_INT_MASK, 0x23 },
};
/* This function configures the interrupt masks for both HW_INT_CAUSES and
@@ -1007,6 +1512,11 @@ static void btintel_pcie_init_ci(struct btintel_pcie_data *data,
ci->addr_urbdq1 = data->rxq.urbd1s_p_addr;
ci->num_urbdq1 = data->rxq.count;
ci->urbdq_db_vec = BTINTEL_PCIE_RXQ_NUM;
ci->dbg_output_mode = 0x01;
ci->dbgc_addr = data->dbgc.frag_p_addr;
ci->dbgc_size = data->dbgc.frag_size;
ci->dbg_preset = 0x00;
}
static void btintel_pcie_free_txq_bufs(struct btintel_pcie_data *data,
@@ -1219,6 +1729,11 @@ static int btintel_pcie_alloc(struct btintel_pcie_data *data)
/* Setup Index Array */
btintel_pcie_setup_ia(data, p_addr, v_addr, &data->ia);
/* Setup data buffers for dbgc */
err = btintel_pcie_setup_dbgc(data);
if (err)
goto exit_error_txq;
/* Setup Context Information */
p_addr += sizeof(u16) * BTINTEL_PCIE_NUM_QUEUES * 4;
v_addr += sizeof(u16) * BTINTEL_PCIE_NUM_QUEUES * 4;
@@ -1392,6 +1907,7 @@ static void btintel_pcie_release_hdev(struct btintel_pcie_data *data)
static int btintel_pcie_setup_internal(struct hci_dev *hdev)
{
struct btintel_pcie_data *data = hci_get_drvdata(hdev);
const u8 param[1] = { 0xFF };
struct intel_version_tlv ver_tlv;
struct sk_buff *skb;
@@ -1449,6 +1965,7 @@ static int btintel_pcie_setup_internal(struct hci_dev *hdev)
*/
switch (INTEL_HW_VARIANT(ver_tlv.cnvi_bt)) {
case 0x1e: /* BzrI */
case 0x1f: /* ScP */
/* Display version information of TLV type */
btintel_version_info_tlv(hdev, &ver_tlv);
@@ -1474,6 +1991,23 @@ static int btintel_pcie_setup_internal(struct hci_dev *hdev)
break;
}
data->dmp_hdr.cnvi_top = ver_tlv.cnvi_top;
data->dmp_hdr.cnvr_top = ver_tlv.cnvr_top;
data->dmp_hdr.fw_timestamp = ver_tlv.timestamp;
data->dmp_hdr.fw_build_type = ver_tlv.build_type;
data->dmp_hdr.fw_build_num = ver_tlv.build_num;
data->dmp_hdr.cnvi_bt = ver_tlv.cnvi_bt;
if (ver_tlv.img_type == 0x02 || ver_tlv.img_type == 0x03)
data->dmp_hdr.fw_git_sha1 = ver_tlv.git_sha1;
err = hci_devcd_register(hdev, btintel_pcie_dump_traces, btintel_pcie_dump_hdr,
btintel_pcie_dump_notify);
if (err) {
bt_dev_err(hdev, "Failed to register coredump (%d)", err);
goto exit_error;
}
btintel_print_fseq_info(hdev);
exit_error:
kfree_skb(skb);
@@ -1538,6 +2072,7 @@ static int btintel_pcie_setup_hdev(struct btintel_pcie_data *data)
goto exit_error;
}
data->dmp_hdr.driver_name = KBUILD_MODNAME;
return 0;
exit_error:
@@ -1650,11 +2185,28 @@ static void btintel_pcie_remove(struct pci_dev *pdev)
pci_set_drvdata(pdev, NULL);
}
#ifdef CONFIG_DEV_COREDUMP
static void btintel_pcie_coredump(struct device *dev)
{
struct pci_dev *pdev = to_pci_dev(dev);
struct btintel_pcie_data *data = pci_get_drvdata(pdev);
if (test_and_set_bit(BTINTEL_PCIE_COREDUMP_INPROGRESS, &data->flags))
return;
data->dmp_hdr.trigger_reason = BTINTEL_PCIE_TRIGGER_REASON_USER_TRIGGER;
queue_work(data->workqueue, &data->rx_work);
}
#endif
static struct pci_driver btintel_pcie_driver = {
.name = KBUILD_MODNAME,
.id_table = btintel_pcie_table,
.probe = btintel_pcie_probe,
.remove = btintel_pcie_remove,
#ifdef CONFIG_DEV_COREDUMP
.driver.coredump = btintel_pcie_coredump
#endif
};
module_pci_driver(btintel_pcie_driver);

View File

@@ -16,6 +16,8 @@
#define BTINTEL_PCIE_CSR_CI_ADDR_LSB_REG (BTINTEL_PCIE_CSR_BASE + 0x118)
#define BTINTEL_PCIE_CSR_CI_ADDR_MSB_REG (BTINTEL_PCIE_CSR_BASE + 0x11C)
#define BTINTEL_PCIE_CSR_IMG_RESPONSE_REG (BTINTEL_PCIE_CSR_BASE + 0x12C)
#define BTINTEL_PCIE_PRPH_DEV_ADDR_REG (BTINTEL_PCIE_CSR_BASE + 0x440)
#define BTINTEL_PCIE_PRPH_DEV_RD_REG (BTINTEL_PCIE_CSR_BASE + 0x458)
#define BTINTEL_PCIE_CSR_HBUS_TARG_WRPTR (BTINTEL_PCIE_CSR_BASE + 0x460)
/* BTINTEL_PCIE_CSR Function Control Register */
@@ -23,6 +25,12 @@
#define BTINTEL_PCIE_CSR_FUNC_CTRL_MAC_INIT (BIT(6))
#define BTINTEL_PCIE_CSR_FUNC_CTRL_FUNC_INIT (BIT(7))
#define BTINTEL_PCIE_CSR_FUNC_CTRL_MAC_ACCESS_STS (BIT(20))
#define BTINTEL_PCIE_CSR_FUNC_CTRL_MAC_ACCESS_REQ (BIT(21))
/* Stop MAC Access disconnection request */
#define BTINTEL_PCIE_CSR_FUNC_CTRL_STOP_MAC_ACCESS_DIS (BIT(22))
#define BTINTEL_PCIE_CSR_FUNC_CTRL_XTAL_CLK_REQ (BIT(23))
#define BTINTEL_PCIE_CSR_FUNC_CTRL_BUS_MASTER_STS (BIT(28))
#define BTINTEL_PCIE_CSR_FUNC_CTRL_BUS_MASTER_DISCON (BIT(29))
#define BTINTEL_PCIE_CSR_FUNC_CTRL_SW_RESET (BIT(31))
@@ -48,6 +56,30 @@
#define BTINTEL_PCIE_CSR_MSIX_IVAR_BASE (BTINTEL_PCIE_CSR_MSIX_BASE + 0x0880)
#define BTINTEL_PCIE_CSR_MSIX_IVAR(cause) (BTINTEL_PCIE_CSR_MSIX_IVAR_BASE + (cause))
/* IOSF Debug Register */
#define BTINTEL_PCIE_DBGC_BASE_ADDR (0xf3800300)
#define BTINTEL_PCIE_DBGC_CUR_DBGBUFF_STATUS (BTINTEL_PCIE_DBGC_BASE_ADDR + 0x1C)
#define BTINTEL_PCIE_DBGC_DBGBUFF_WRAP_ARND (BTINTEL_PCIE_DBGC_BASE_ADDR + 0x2C)
#define BTINTEL_PCIE_DBG_IDX_BIT_MASK 0x0F
#define BTINTEL_PCIE_DBGC_DBG_BUF_IDX(data) (((data) >> 24) & BTINTEL_PCIE_DBG_IDX_BIT_MASK)
#define BTINTEL_PCIE_DBG_OFFSET_BIT_MASK 0xFFFFFF
/* The DRAM buffer count, each buffer size, and
* fragment buffer size
*/
#define BTINTEL_PCIE_DBGC_BUFFER_COUNT 16
#define BTINTEL_PCIE_DBGC_BUFFER_SIZE (256 * 1024) /* 256 KB */
#define BTINTEL_PCIE_DBGC_FRAG_VERSION 1
#define BTINTEL_PCIE_DBGC_FRAG_BUFFER_COUNT BTINTEL_PCIE_DBGC_BUFFER_COUNT
/* Magic number(4), version(4), size of payload length(4) */
#define BTINTEL_PCIE_DBGC_FRAG_HEADER_SIZE 12
/* Num of alloc Dbg buff (4) + (LSB(4), MSB(4), Size(4)) for each buffer */
#define BTINTEL_PCIE_DBGC_FRAG_PAYLOAD_SIZE 196
/* Causes for the FH register interrupts */
enum msix_fh_int_causes {
BTINTEL_PCIE_MSIX_FH_INT_CAUSES_0 = BIT(0), /* cause 0 */
@@ -57,6 +89,7 @@ enum msix_fh_int_causes {
/* Causes for the HW register interrupts */
enum msix_hw_int_causes {
BTINTEL_PCIE_MSIX_HW_INT_CAUSES_GP0 = BIT(0), /* cause 32 */
BTINTEL_PCIE_MSIX_HW_INT_CAUSES_HWEXP = BIT(3), /* cause 35 */
};
/* PCIe device states
@@ -69,6 +102,25 @@ enum {
BTINTEL_PCIE_STATE_D3_HOT = 2,
BTINTEL_PCIE_STATE_D3_COLD = 3,
};
enum {
BTINTEL_PCIE_CORE_HALTED,
BTINTEL_PCIE_HWEXP_INPROGRESS,
BTINTEL_PCIE_COREDUMP_INPROGRESS
};
enum btintel_pcie_tlv_type {
BTINTEL_CNVI_BT,
BTINTEL_WRITE_PTR,
BTINTEL_WRAP_CTR,
BTINTEL_TRIGGER_REASON,
BTINTEL_FW_SHA,
BTINTEL_CNVR_TOP,
BTINTEL_CNVI_TOP,
BTINTEL_DUMP_TIME,
BTINTEL_FW_BUILD,
};
#define BTINTEL_PCIE_MSIX_NON_AUTO_CLEAR_CAUSE BIT(7)
/* Minimum and Maximum number of MSI-X Vector
@@ -325,6 +377,37 @@ struct rxq {
struct data_buf *bufs;
};
/* Structure for DRAM Buffer
* @count: Number of descriptors
* @buf: Array of data_buf structure
*/
struct btintel_pcie_dbgc {
u16 count;
void *frag_v_addr;
dma_addr_t frag_p_addr;
u16 frag_size;
dma_addr_t buf_p_addr;
void *buf_v_addr;
struct data_buf *bufs;
};
struct btintel_pcie_dump_header {
const char *driver_name;
u32 cnvi_top;
u32 cnvr_top;
u16 fw_timestamp;
u8 fw_build_type;
u32 fw_build_num;
u32 fw_git_sha1;
u32 cnvi_bt;
u32 write_ptr;
u32 wrap_ctr;
u16 trigger_reason;
int state;
};
/* struct btintel_pcie_data
* @pdev: pci device
* @hdev: hdev device
@@ -405,6 +488,8 @@ struct btintel_pcie_data {
struct txq txq;
struct rxq rxq;
u32 alive_intr_ctxt;
struct btintel_pcie_dbgc dbgc;
struct btintel_pcie_dump_header dmp_hdr;
};
static inline u32 btintel_pcie_rd_reg32(struct btintel_pcie_data *data,
@@ -444,3 +529,11 @@ static inline void btintel_pcie_clr_reg_bits(struct btintel_pcie_data *data,
r &= ~bits;
iowrite32(r, data->base_addr + offset);
}
static inline u32 btintel_pcie_rd_dev_mem(struct btintel_pcie_data *data,
u32 addr)
{
btintel_pcie_wr_reg32(data, BTINTEL_PCIE_PRPH_DEV_ADDR_REG, addr);
return btintel_pcie_rd_reg32(data, BTINTEL_PCIE_PRPH_DEV_RD_REG);
}

View File

@@ -1330,13 +1330,6 @@ int btmtk_usb_setup(struct hci_dev *hdev)
break;
case 0x7922:
case 0x7925:
/* Reset the device to ensure it's in the initial state before
* downloading the firmware to ensure.
*/
if (!test_bit(BTMTK_FIRMWARE_LOADED, &btmtk_data->flags))
btmtk_usb_subsys_reset(hdev, dev_id);
fallthrough;
case 0x7961:
btmtk_fw_get_filename(fw_bin_name, sizeof(fw_bin_name), dev_id,
fw_version, fw_flavor);
@@ -1345,12 +1338,9 @@ int btmtk_usb_setup(struct hci_dev *hdev)
btmtk_usb_hci_wmt_sync);
if (err < 0) {
bt_dev_err(hdev, "Failed to set up firmware (%d)", err);
clear_bit(BTMTK_FIRMWARE_LOADED, &btmtk_data->flags);
return err;
}
set_bit(BTMTK_FIRMWARE_LOADED, &btmtk_data->flags);
/* It's Device EndPoint Reset Option Register */
err = btmtk_usb_uhw_reg_write(hdev, MTK_EP_RST_OPT,
MTK_EP_RST_IN_OUT_OPT);

View File

@@ -610,7 +610,8 @@ static void btmtksdio_txrx_work(struct work_struct *work)
} while (int_status || time_is_before_jiffies(txrx_timeout));
/* Enable interrupt */
sdio_writel(bdev->func, C_INT_EN_SET, MTK_REG_CHLPCR, NULL);
if (bdev->func->irq_handler)
sdio_writel(bdev->func, C_INT_EN_SET, MTK_REG_CHLPCR, NULL);
sdio_release_host(bdev->func);

View File

@@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* NXP Bluetooth driver
* Copyright 2023 NXP
* Copyright 2023-2025 NXP
*/
#include <linux/module.h>
@@ -31,6 +31,7 @@
#define BTNXPUART_SERDEV_OPEN 4
#define BTNXPUART_IR_IN_PROGRESS 5
#define BTNXPUART_FW_DOWNLOAD_ABORT 6
#define BTNXPUART_FW_DUMP_IN_PROGRESS 7
/* NXP HW err codes */
#define BTNXPUART_IR_HW_ERR 0xb0
@@ -98,14 +99,19 @@
#define PS_STATE_AWAKE 0
#define PS_STATE_SLEEP 1
/* Bluetooth vendor command : Sleep mode */
/* NXP Vendor Commands. Refer user manual UM11628 on nxp.com */
/* Set custom BD Address */
#define HCI_NXP_SET_BD_ADDR 0xfc22
/* Set Auto-Sleep mode */
#define HCI_NXP_AUTO_SLEEP_MODE 0xfc23
/* Bluetooth vendor command : Wakeup method */
/* Set Wakeup method */
#define HCI_NXP_WAKEUP_METHOD 0xfc53
/* Bluetooth vendor command : Set operational baudrate */
/* Set operational baudrate */
#define HCI_NXP_SET_OPER_SPEED 0xfc09
/* Bluetooth vendor command: Independent Reset */
/* Independent Reset (Soft Reset) */
#define HCI_NXP_IND_RESET 0xfcfc
/* Bluetooth vendor command: Trigger FW dump */
#define HCI_NXP_TRIGGER_DUMP 0xfe91
/* Bluetooth Power State : Vendor cmd params */
#define BT_PS_ENABLE 0x02
@@ -162,6 +168,12 @@ struct btnxpuart_data {
const char *fw_name_old;
};
enum bootloader_param_change {
not_changed,
cmd_sent,
changed
};
struct btnxpuart_dev {
struct hci_dev *hdev;
struct serdev_device *serdev;
@@ -177,6 +189,7 @@ struct btnxpuart_dev {
u32 fw_v1_sent_bytes;
u32 fw_dnld_v3_offset;
u32 fw_v3_offset_correction;
u32 fw_v3_prev_sent;
u32 fw_v1_expected_len;
u32 boot_reg_offset;
wait_queue_head_t fw_dnld_done_wait_q;
@@ -185,8 +198,8 @@ struct btnxpuart_dev {
u32 new_baudrate;
u32 current_baudrate;
u32 fw_init_baudrate;
bool timeout_changed;
bool baudrate_changed;
enum bootloader_param_change timeout_changed;
enum bootloader_param_change baudrate_changed;
bool helper_downloaded;
struct ps_data psdata;
@@ -204,10 +217,11 @@ struct btnxpuart_dev {
#define NXP_NAK_V3 0x7b
#define NXP_CRC_ERROR_V3 0x7c
/* Bootloader signature error codes */
#define NXP_ACK_RX_TIMEOUT 0x0002 /* ACK not received from host */
#define NXP_HDR_RX_TIMEOUT 0x0003 /* FW Header chunk not received */
#define NXP_DATA_RX_TIMEOUT 0x0004 /* FW Data chunk not received */
/* Bootloader signature error codes: Refer AN12820 from nxp.com */
#define NXP_CRC_RX_ERROR BIT(0) /* CRC error in previous packet */
#define NXP_ACK_RX_TIMEOUT BIT(2) /* ACK not received from host */
#define NXP_HDR_RX_TIMEOUT BIT(3) /* FW Header chunk not received */
#define NXP_DATA_RX_TIMEOUT BIT(4) /* FW Data chunk not received */
#define HDR_LEN 16
@@ -310,6 +324,35 @@ union nxp_v3_rx_timeout_nak_u {
u8 buf[6];
};
struct nxp_v3_crc_nak {
u8 nak;
u8 crc;
} __packed;
union nxp_v3_crc_nak_u {
struct nxp_v3_crc_nak pkt;
u8 buf[2];
};
/* FW dump */
#define NXP_FW_DUMP_SIZE (1024 * 1000)
struct nxp_fw_dump_hdr {
__le16 seq_num;
__le16 reserved;
__le16 buf_type;
__le16 buf_len;
};
union nxp_set_bd_addr_payload {
struct {
u8 param_id;
u8 param_len;
u8 param[6];
} __packed data;
u8 buf[8];
};
static u8 crc8_table[CRC8_TABLE_SIZE];
/* Default configurations */
@@ -447,8 +490,14 @@ static int ps_setup(struct hci_dev *hdev)
return PTR_ERR(psdata->h2c_ps_gpio);
}
if (!psdata->h2c_ps_gpio)
if (device_property_read_u8(&serdev->dev, "nxp,wakein-pin", &psdata->h2c_wakeup_gpio)) {
psdata->h2c_wakeup_gpio = 0xff; /* 0xff: use default pin/gpio */
} else if (!psdata->h2c_ps_gpio) {
bt_dev_warn(hdev, "nxp,wakein-pin property without device-wakeup GPIO");
psdata->h2c_wakeup_gpio = 0xff;
}
device_property_read_u8(&serdev->dev, "nxp,wakeout-pin", &psdata->c2h_wakeup_gpio);
psdata->hdev = hdev;
INIT_WORK(&psdata->work, ps_work_func);
@@ -540,9 +589,11 @@ static int send_wakeup_method_cmd(struct hci_dev *hdev, void *data)
pcmd.c2h_wakeupmode = psdata->c2h_wakeupmode;
pcmd.c2h_wakeup_gpio = psdata->c2h_wakeup_gpio;
pcmd.h2c_wakeup_gpio = 0xff;
switch (psdata->h2c_wakeupmode) {
case WAKEUP_METHOD_GPIO:
pcmd.h2c_wakeupmode = BT_CTRL_WAKEUP_METHOD_GPIO;
pcmd.h2c_wakeup_gpio = psdata->h2c_wakeup_gpio;
break;
case WAKEUP_METHOD_DTR:
pcmd.h2c_wakeupmode = BT_CTRL_WAKEUP_METHOD_DSR;
@@ -552,7 +603,6 @@ static int send_wakeup_method_cmd(struct hci_dev *hdev, void *data)
pcmd.h2c_wakeupmode = BT_CTRL_WAKEUP_METHOD_BREAK;
break;
}
pcmd.h2c_wakeup_gpio = 0xff;
skb = nxp_drv_send_cmd(hdev, HCI_NXP_WAKEUP_METHOD, sizeof(pcmd), &pcmd);
if (IS_ERR(skb)) {
@@ -586,8 +636,13 @@ static void ps_init(struct hci_dev *hdev)
usleep_range(5000, 10000);
psdata->ps_state = PS_STATE_AWAKE;
psdata->c2h_wakeupmode = BT_HOST_WAKEUP_METHOD_NONE;
psdata->c2h_wakeup_gpio = 0xff;
if (psdata->c2h_wakeup_gpio) {
psdata->c2h_wakeupmode = BT_HOST_WAKEUP_METHOD_GPIO;
} else {
psdata->c2h_wakeupmode = BT_HOST_WAKEUP_METHOD_NONE;
psdata->c2h_wakeup_gpio = 0xff;
}
psdata->cur_h2c_wakeupmode = WAKEUP_METHOD_INVALID;
if (psdata->h2c_ps_gpio)
@@ -618,11 +673,6 @@ static void ps_init(struct hci_dev *hdev)
psdata->cur_psmode = PS_MODE_DISABLE;
psdata->target_ps_mode = DEFAULT_PS_MODE;
if (psdata->cur_h2c_wakeupmode != psdata->h2c_wakeupmode)
hci_cmd_sync_queue(hdev, send_wakeup_method_cmd, NULL, NULL);
if (psdata->cur_psmode != psdata->target_ps_mode)
hci_cmd_sync_queue(hdev, send_ps_cmd, NULL, NULL);
}
/* NXP Firmware Download Feature */
@@ -637,8 +687,8 @@ static int nxp_download_firmware(struct hci_dev *hdev)
nxpdev->boot_reg_offset = 0;
nxpdev->fw_dnld_v3_offset = 0;
nxpdev->fw_v3_offset_correction = 0;
nxpdev->baudrate_changed = false;
nxpdev->timeout_changed = false;
nxpdev->baudrate_changed = not_changed;
nxpdev->timeout_changed = not_changed;
nxpdev->helper_downloaded = false;
serdev_device_set_baudrate(nxpdev->serdev, HCI_NXP_PRI_BAUDRATE);
@@ -651,8 +701,10 @@ static int nxp_download_firmware(struct hci_dev *hdev)
&nxpdev->tx_state),
msecs_to_jiffies(60000));
release_firmware(nxpdev->fw);
memset(nxpdev->fw_name, 0, sizeof(nxpdev->fw_name));
if (nxpdev->fw && strlen(nxpdev->fw_name)) {
release_firmware(nxpdev->fw);
memset(nxpdev->fw_name, 0, sizeof(nxpdev->fw_name));
}
if (err == 0) {
bt_dev_err(hdev, "FW Download Timeout. offset: %d",
@@ -767,6 +819,16 @@ static bool is_fw_downloading(struct btnxpuart_dev *nxpdev)
return test_bit(BTNXPUART_FW_DOWNLOADING, &nxpdev->tx_state);
}
static bool ind_reset_in_progress(struct btnxpuart_dev *nxpdev)
{
return test_bit(BTNXPUART_IR_IN_PROGRESS, &nxpdev->tx_state);
}
static bool fw_dump_in_progress(struct btnxpuart_dev *nxpdev)
{
return test_bit(BTNXPUART_FW_DUMP_IN_PROGRESS, &nxpdev->tx_state);
}
static bool process_boot_signature(struct btnxpuart_dev *nxpdev)
{
if (test_bit(BTNXPUART_CHECK_BOOT_SIGNATURE, &nxpdev->tx_state)) {
@@ -860,15 +922,14 @@ static int nxp_recv_fw_req_v1(struct hci_dev *hdev, struct sk_buff *skb)
len = __le16_to_cpu(req->len);
if (!nxp_data->helper_fw_name) {
if (!nxpdev->timeout_changed) {
nxpdev->timeout_changed = nxp_fw_change_timeout(hdev,
len);
if (nxpdev->timeout_changed != changed) {
nxp_fw_change_timeout(hdev, len);
nxpdev->timeout_changed = changed;
goto free_skb;
}
if (!nxpdev->baudrate_changed) {
nxpdev->baudrate_changed = nxp_fw_change_baudrate(hdev,
len);
if (nxpdev->baudrate_changed) {
if (nxpdev->baudrate_changed != changed) {
if (nxp_fw_change_baudrate(hdev, len)) {
nxpdev->baudrate_changed = changed;
serdev_device_set_baudrate(nxpdev->serdev,
HCI_NXP_SEC_BAUDRATE);
serdev_device_set_flow_control(nxpdev->serdev, true);
@@ -1047,32 +1108,35 @@ static void nxp_handle_fw_download_error(struct hci_dev *hdev, struct v3_data_re
struct btnxpuart_dev *nxpdev = hci_get_drvdata(hdev);
__u32 offset = __le32_to_cpu(req->offset);
__u16 err = __le16_to_cpu(req->error);
union nxp_v3_rx_timeout_nak_u nak_tx_buf;
switch (err) {
case NXP_ACK_RX_TIMEOUT:
case NXP_HDR_RX_TIMEOUT:
case NXP_DATA_RX_TIMEOUT:
nak_tx_buf.pkt.nak = NXP_NAK_V3;
nak_tx_buf.pkt.offset = __cpu_to_le32(offset);
nak_tx_buf.pkt.crc = crc8(crc8_table, nak_tx_buf.buf,
sizeof(nak_tx_buf) - 1, 0xff);
serdev_device_write_buf(nxpdev->serdev, nak_tx_buf.buf,
sizeof(nak_tx_buf));
break;
default:
bt_dev_dbg(hdev, "Unknown bootloader error code: %d", err);
break;
union nxp_v3_rx_timeout_nak_u timeout_nak_buf;
union nxp_v3_crc_nak_u crc_nak_buf;
if (err & NXP_CRC_RX_ERROR) {
crc_nak_buf.pkt.nak = NXP_CRC_ERROR_V3;
crc_nak_buf.pkt.crc = crc8(crc8_table, crc_nak_buf.buf,
sizeof(crc_nak_buf) - 1, 0xff);
serdev_device_write_buf(nxpdev->serdev, crc_nak_buf.buf,
sizeof(crc_nak_buf));
} else if (err & NXP_ACK_RX_TIMEOUT ||
err & NXP_HDR_RX_TIMEOUT ||
err & NXP_DATA_RX_TIMEOUT) {
timeout_nak_buf.pkt.nak = NXP_NAK_V3;
timeout_nak_buf.pkt.offset = __cpu_to_le32(offset);
timeout_nak_buf.pkt.crc = crc8(crc8_table, timeout_nak_buf.buf,
sizeof(timeout_nak_buf) - 1, 0xff);
serdev_device_write_buf(nxpdev->serdev, timeout_nak_buf.buf,
sizeof(timeout_nak_buf));
} else {
bt_dev_err(hdev, "Unknown bootloader error code: %d", err);
}
}
static int nxp_recv_fw_req_v3(struct hci_dev *hdev, struct sk_buff *skb)
{
struct btnxpuart_dev *nxpdev = hci_get_drvdata(hdev);
struct v3_data_req *req;
__u16 len;
__u16 len = 0;
__u16 err = 0;
__u32 offset;
if (!process_boot_signature(nxpdev))
@@ -1082,23 +1146,40 @@ static int nxp_recv_fw_req_v3(struct hci_dev *hdev, struct sk_buff *skb)
if (!req || !nxpdev->fw)
goto free_skb;
if (!req->error) {
err = __le16_to_cpu(req->error);
if (!err) {
nxp_send_ack(NXP_ACK_V3, hdev);
if (nxpdev->timeout_changed == cmd_sent)
nxpdev->timeout_changed = changed;
if (nxpdev->baudrate_changed == cmd_sent)
nxpdev->baudrate_changed = changed;
} else {
nxp_handle_fw_download_error(hdev, req);
if (nxpdev->timeout_changed == cmd_sent &&
err == NXP_CRC_RX_ERROR) {
nxpdev->fw_v3_offset_correction -= nxpdev->fw_v3_prev_sent;
nxpdev->timeout_changed = not_changed;
}
if (nxpdev->baudrate_changed == cmd_sent &&
err == NXP_CRC_RX_ERROR) {
nxpdev->fw_v3_offset_correction -= nxpdev->fw_v3_prev_sent;
nxpdev->baudrate_changed = not_changed;
}
goto free_skb;
}
len = __le16_to_cpu(req->len);
if (!nxpdev->timeout_changed) {
nxpdev->timeout_changed = nxp_fw_change_timeout(hdev, len);
if (nxpdev->timeout_changed != changed) {
nxp_fw_change_timeout(hdev, len);
nxpdev->timeout_changed = cmd_sent;
goto free_skb;
}
if (!nxpdev->baudrate_changed) {
nxpdev->baudrate_changed = nxp_fw_change_baudrate(hdev, len);
if (nxpdev->baudrate_changed) {
if (nxpdev->baudrate_changed != changed) {
if (nxp_fw_change_baudrate(hdev, len)) {
nxpdev->baudrate_changed = cmd_sent;
serdev_device_set_baudrate(nxpdev->serdev,
HCI_NXP_SEC_BAUDRATE);
serdev_device_set_flow_control(nxpdev->serdev, true);
@@ -1130,6 +1211,7 @@ static int nxp_recv_fw_req_v3(struct hci_dev *hdev, struct sk_buff *skb)
nxpdev->fw_dnld_v3_offset, len);
free_skb:
nxpdev->fw_v3_prev_sent = len;
kfree_skb(skb);
return 0;
}
@@ -1168,7 +1250,7 @@ static int nxp_set_baudrate_cmd(struct hci_dev *hdev, void *data)
static int nxp_check_boot_sign(struct btnxpuart_dev *nxpdev)
{
serdev_device_set_baudrate(nxpdev->serdev, HCI_NXP_PRI_BAUDRATE);
if (test_bit(BTNXPUART_IR_IN_PROGRESS, &nxpdev->tx_state))
if (ind_reset_in_progress(nxpdev))
serdev_device_set_flow_control(nxpdev->serdev, false);
else
serdev_device_set_flow_control(nxpdev->serdev, true);
@@ -1197,6 +1279,102 @@ static int nxp_set_ind_reset(struct hci_dev *hdev, void *data)
return hci_recv_frame(hdev, skb);
}
/* Firmware dump */
static void nxp_coredump(struct hci_dev *hdev)
{
struct sk_buff *skb;
u8 pcmd = 2;
skb = nxp_drv_send_cmd(hdev, HCI_NXP_TRIGGER_DUMP, 1, &pcmd);
if (!IS_ERR(skb))
kfree_skb(skb);
}
static void nxp_coredump_hdr(struct hci_dev *hdev, struct sk_buff *skb)
{
/* Nothing to be added in FW dump header */
}
static int nxp_process_fw_dump(struct hci_dev *hdev, struct sk_buff *skb)
{
struct hci_acl_hdr *acl_hdr = (struct hci_acl_hdr *)skb_pull_data(skb,
sizeof(*acl_hdr));
struct nxp_fw_dump_hdr *fw_dump_hdr = (struct nxp_fw_dump_hdr *)skb->data;
struct btnxpuart_dev *nxpdev = hci_get_drvdata(hdev);
__u16 seq_num = __le16_to_cpu(fw_dump_hdr->seq_num);
__u16 buf_len = __le16_to_cpu(fw_dump_hdr->buf_len);
int err;
if (seq_num == 0x0001) {
if (test_and_set_bit(BTNXPUART_FW_DUMP_IN_PROGRESS, &nxpdev->tx_state)) {
bt_dev_err(hdev, "FW dump already in progress");
goto free_skb;
}
bt_dev_warn(hdev, "==== Start FW dump ===");
err = hci_devcd_init(hdev, NXP_FW_DUMP_SIZE);
if (err < 0)
goto free_skb;
schedule_delayed_work(&hdev->dump.dump_timeout,
msecs_to_jiffies(20000));
}
err = hci_devcd_append(hdev, skb_clone(skb, GFP_ATOMIC));
if (err < 0)
goto free_skb;
if (buf_len == 0) {
bt_dev_warn(hdev, "==== FW dump complete ===");
clear_bit(BTNXPUART_FW_DUMP_IN_PROGRESS, &nxpdev->tx_state);
hci_devcd_complete(hdev);
nxp_set_ind_reset(hdev, NULL);
}
free_skb:
kfree_skb(skb);
return 0;
}
static int nxp_recv_acl_pkt(struct hci_dev *hdev, struct sk_buff *skb)
{
__u16 handle = __le16_to_cpu(hci_acl_hdr(skb)->handle);
/* FW dump chunks are ACL packets with conn handle 0xfff */
if ((handle & 0x0FFF) == 0xFFF)
return nxp_process_fw_dump(hdev, skb);
else
return hci_recv_frame(hdev, skb);
}
static int nxp_set_bdaddr(struct hci_dev *hdev, const bdaddr_t *bdaddr)
{
union nxp_set_bd_addr_payload pcmd;
int err;
pcmd.data.param_id = 0xfe;
pcmd.data.param_len = 6;
memcpy(pcmd.data.param, bdaddr, 6);
/* BD address can be assigned only after first reset command. */
err = __hci_cmd_sync_status(hdev, HCI_OP_RESET, 0, NULL,
HCI_INIT_TIMEOUT);
if (err) {
bt_dev_err(hdev,
"Reset before setting local-bd-addr failed (%d)",
err);
return err;
}
err = __hci_cmd_sync_status(hdev, HCI_NXP_SET_BD_ADDR, sizeof(pcmd),
pcmd.buf, HCI_CMD_TIMEOUT);
if (err) {
bt_dev_err(hdev, "Changing device address failed (%d)", err);
return err;
}
return 0;
}
/* NXP protocol */
static int nxp_setup(struct hci_dev *hdev)
{
@@ -1216,11 +1394,6 @@ static int nxp_setup(struct hci_dev *hdev)
serdev_device_set_baudrate(nxpdev->serdev, nxpdev->fw_init_baudrate);
nxpdev->current_baudrate = nxpdev->fw_init_baudrate;
if (nxpdev->current_baudrate != HCI_NXP_SEC_BAUDRATE) {
nxpdev->new_baudrate = HCI_NXP_SEC_BAUDRATE;
hci_cmd_sync_queue(hdev, nxp_set_baudrate_cmd, NULL, NULL);
}
ps_init(hdev);
if (test_and_clear_bit(BTNXPUART_IR_IN_PROGRESS, &nxpdev->tx_state))
@@ -1229,6 +1402,22 @@ static int nxp_setup(struct hci_dev *hdev)
return 0;
}
static int nxp_post_init(struct hci_dev *hdev)
{
struct btnxpuart_dev *nxpdev = hci_get_drvdata(hdev);
struct ps_data *psdata = &nxpdev->psdata;
if (nxpdev->current_baudrate != HCI_NXP_SEC_BAUDRATE) {
nxpdev->new_baudrate = HCI_NXP_SEC_BAUDRATE;
nxp_set_baudrate_cmd(hdev, NULL);
}
if (psdata->cur_h2c_wakeupmode != psdata->h2c_wakeupmode)
send_wakeup_method_cmd(hdev, NULL);
if (psdata->cur_psmode != psdata->target_ps_mode)
send_ps_cmd(hdev, NULL);
return 0;
}
static void nxp_hw_err(struct hci_dev *hdev, u8 code)
{
struct btnxpuart_dev *nxpdev = hci_get_drvdata(hdev);
@@ -1247,25 +1436,44 @@ static int nxp_shutdown(struct hci_dev *hdev)
{
struct btnxpuart_dev *nxpdev = hci_get_drvdata(hdev);
struct sk_buff *skb;
u8 *status;
u8 pcmd = 0;
if (test_bit(BTNXPUART_IR_IN_PROGRESS, &nxpdev->tx_state)) {
if (ind_reset_in_progress(nxpdev)) {
skb = nxp_drv_send_cmd(hdev, HCI_NXP_IND_RESET, 1, &pcmd);
if (IS_ERR(skb))
return PTR_ERR(skb);
status = skb_pull_data(skb, 1);
if (status) {
serdev_device_set_flow_control(nxpdev->serdev, false);
set_bit(BTNXPUART_FW_DOWNLOADING, &nxpdev->tx_state);
}
kfree_skb(skb);
serdev_device_set_flow_control(nxpdev->serdev, false);
set_bit(BTNXPUART_FW_DOWNLOADING, &nxpdev->tx_state);
/* HCI_NXP_IND_RESET command may not returns any response */
if (!IS_ERR(skb))
kfree_skb(skb);
} else if (nxpdev->current_baudrate != nxpdev->fw_init_baudrate) {
nxpdev->new_baudrate = nxpdev->fw_init_baudrate;
nxp_set_baudrate_cmd(hdev, NULL);
}
return 0;
}
static bool nxp_wakeup(struct hci_dev *hdev)
{
struct btnxpuart_dev *nxpdev = hci_get_drvdata(hdev);
struct ps_data *psdata = &nxpdev->psdata;
if (psdata->c2h_wakeupmode != BT_HOST_WAKEUP_METHOD_NONE)
return true;
return false;
}
static void nxp_reset(struct hci_dev *hdev)
{
struct btnxpuart_dev *nxpdev = hci_get_drvdata(hdev);
if (!ind_reset_in_progress(nxpdev) && !fw_dump_in_progress(nxpdev)) {
bt_dev_dbg(hdev, "CMD Timeout detected. Resetting.");
nxp_set_ind_reset(hdev, NULL);
}
}
static int btnxpuart_queue_skb(struct hci_dev *hdev, struct sk_buff *skb)
{
struct btnxpuart_dev *nxpdev = hci_get_drvdata(hdev);
@@ -1286,6 +1494,9 @@ static int nxp_enqueue(struct hci_dev *hdev, struct sk_buff *skb)
struct wakeup_cmd_payload wakeup_parm;
__le32 baudrate_parm;
if (fw_dump_in_progress(nxpdev))
return -EBUSY;
/* if vendor commands are received from user space (e.g. hcitool), update
* driver flags accordingly and ask driver to re-send the command to FW.
* In case the payload for any command does not match expected payload
@@ -1454,7 +1665,7 @@ static int btnxpuart_flush(struct hci_dev *hdev)
}
static const struct h4_recv_pkt nxp_recv_pkts[] = {
{ H4_RECV_ACL, .recv = hci_recv_frame },
{ H4_RECV_ACL, .recv = nxp_recv_acl_pkt },
{ H4_RECV_SCO, .recv = hci_recv_frame },
{ H4_RECV_EVENT, .recv = hci_recv_frame },
{ H4_RECV_ISO, .recv = hci_recv_frame },
@@ -1476,11 +1687,13 @@ static size_t btnxpuart_receive_buf(struct serdev_device *serdev,
if (IS_ERR(nxpdev->rx_skb)) {
int err = PTR_ERR(nxpdev->rx_skb);
/* Safe to ignore out-of-sync bootloader signatures */
if (!is_fw_downloading(nxpdev))
if (!is_fw_downloading(nxpdev) &&
!ind_reset_in_progress(nxpdev))
bt_dev_err(nxpdev->hdev, "Frame reassembly failed (%d)", err);
return count;
}
if (!is_fw_downloading(nxpdev))
if (!is_fw_downloading(nxpdev) &&
!ind_reset_in_progress(nxpdev))
nxpdev->hdev->stat.byte_rx += count;
return count;
}
@@ -1499,6 +1712,7 @@ static int nxp_serdev_probe(struct serdev_device *serdev)
{
struct hci_dev *hdev;
struct btnxpuart_dev *nxpdev;
bdaddr_t ba = {0};
nxpdev = devm_kzalloc(&serdev->dev, sizeof(*nxpdev), GFP_KERNEL);
if (!nxpdev)
@@ -1543,11 +1757,21 @@ static int nxp_serdev_probe(struct serdev_device *serdev)
hdev->close = btnxpuart_close;
hdev->flush = btnxpuart_flush;
hdev->setup = nxp_setup;
hdev->post_init = nxp_post_init;
hdev->send = nxp_enqueue;
hdev->hw_error = nxp_hw_err;
hdev->shutdown = nxp_shutdown;
hdev->wakeup = nxp_wakeup;
hdev->reset = nxp_reset;
hdev->set_bdaddr = nxp_set_bdaddr;
SET_HCIDEV_DEV(hdev, &serdev->dev);
device_property_read_u8_array(&nxpdev->serdev->dev,
"local-bd-address",
(u8 *)&ba, sizeof(ba));
if (bacmp(&ba, BDADDR_ANY))
set_bit(HCI_QUIRK_USE_BDADDR_PROPERTY, &hdev->quirks);
if (hci_register_dev(hdev) < 0) {
dev_err(&serdev->dev, "Can't register HCI device\n");
goto probe_fail;
@@ -1556,6 +1780,8 @@ static int nxp_serdev_probe(struct serdev_device *serdev)
if (ps_setup(hdev))
goto probe_fail;
hci_devcd_register(hdev, nxp_coredump, nxp_coredump_hdr, NULL);
return 0;
probe_fail:
@@ -1573,16 +1799,15 @@ static void nxp_serdev_remove(struct serdev_device *serdev)
clear_bit(BTNXPUART_FW_DOWNLOADING, &nxpdev->tx_state);
wake_up_interruptible(&nxpdev->check_boot_sign_wait_q);
wake_up_interruptible(&nxpdev->fw_dnld_done_wait_q);
} else {
/* Restore FW baudrate to fw_init_baudrate if changed.
* This will ensure FW baudrate is in sync with
* driver baudrate in case this driver is re-inserted.
*/
if (nxpdev->current_baudrate != nxpdev->fw_init_baudrate) {
nxpdev->new_baudrate = nxpdev->fw_init_baudrate;
nxp_set_baudrate_cmd(hdev, NULL);
}
}
if (test_bit(HCI_RUNNING, &hdev->flags)) {
/* Ensure shutdown callback is executed before unregistering, so
* that baudrate is reset to initial value.
*/
nxp_shutdown(hdev);
}
ps_cleanup(nxpdev);
hci_unregister_dev(hdev);
hci_free_dev(hdev);
@@ -1608,6 +1833,17 @@ static int nxp_serdev_resume(struct device *dev)
}
#endif
#ifdef CONFIG_DEV_COREDUMP
static void nxp_serdev_coredump(struct device *dev)
{
struct btnxpuart_dev *nxpdev = dev_get_drvdata(dev);
struct hci_dev *hdev = nxpdev->hdev;
if (hdev->dump.coredump)
hdev->dump.coredump(hdev);
}
#endif
static struct btnxpuart_data w8987_data __maybe_unused = {
.helper_fw_name = NULL,
.fw_name = FIRMWARE_W8987,
@@ -1638,6 +1874,9 @@ static struct serdev_device_driver nxp_serdev_driver = {
.name = "btnxpuart",
.of_match_table = of_match_ptr(nxpuart_of_match_table),
.pm = &nxp_pm_ops,
#ifdef CONFIG_DEV_COREDUMP
.coredump = nxp_serdev_coredump,
#endif
},
};

View File

@@ -785,6 +785,7 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate,
const char *firmware_name, const char *rampatch_name)
{
struct qca_fw_config config = {};
const char *variant = "";
int err;
u8 rom_ver = 0;
u32 soc_ver;
@@ -815,6 +816,10 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate,
snprintf(config.fwname, sizeof(config.fwname), "qca/%s", rampatch_name);
} else {
switch (soc_type) {
case QCA_WCN3950:
snprintf(config.fwname, sizeof(config.fwname),
"qca/cmbtfw%02x.tlv", rom_ver);
break;
case QCA_WCN3990:
case QCA_WCN3991:
case QCA_WCN3998:
@@ -880,16 +885,23 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate,
}
} else {
switch (soc_type) {
case QCA_WCN3950:
if (le32_to_cpu(ver.soc_id) == QCA_WCN3950_SOC_ID_T)
variant = "t";
else if (le32_to_cpu(ver.soc_id) == QCA_WCN3950_SOC_ID_S)
variant = "u";
snprintf(config.fwname, sizeof(config.fwname),
"qca/cmnv%02x%s.bin", rom_ver, variant);
break;
case QCA_WCN3990:
case QCA_WCN3991:
case QCA_WCN3998:
if (le32_to_cpu(ver.soc_id) == QCA_WCN3991_SOC_ID) {
snprintf(config.fwname, sizeof(config.fwname),
"qca/crnv%02xu.bin", rom_ver);
} else {
snprintf(config.fwname, sizeof(config.fwname),
"qca/crnv%02x.bin", rom_ver);
}
if (le32_to_cpu(ver.soc_id) == QCA_WCN3991_SOC_ID)
variant = "u";
snprintf(config.fwname, sizeof(config.fwname),
"qca/crnv%02x%s.bin", rom_ver, variant);
break;
case QCA_WCN3988:
snprintf(config.fwname, sizeof(config.fwname),
@@ -948,6 +960,7 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate,
* VsMsftOpCode.
*/
switch (soc_type) {
case QCA_WCN3950:
case QCA_WCN3988:
case QCA_WCN3990:
case QCA_WCN3991:

View File

@@ -41,6 +41,9 @@
#define QCA_WCN3991_SOC_ID 0x40014320
#define QCA_WCN3950_SOC_ID_T 0x40074130
#define QCA_WCN3950_SOC_ID_S 0x40075130
/* QCA chipset version can be decided by patch and SoC
* version, combination with upper 2 bytes from SoC
* and lower 2 bytes from patch will be used.
@@ -145,6 +148,7 @@ enum qca_btsoc_type {
QCA_INVALID = -1,
QCA_AR3002,
QCA_ROME,
QCA_WCN3950,
QCA_WCN3988,
QCA_WCN3990,
QCA_WCN3998,

View File

@@ -376,10 +376,38 @@ static const struct usb_device_id quirks_table[] = {
BTUSB_WIDEBAND_SPEECH },
{ USB_DEVICE(0x0489, 0xe0f3), .driver_info = BTUSB_QCA_WCN6855 |
BTUSB_WIDEBAND_SPEECH },
{ USB_DEVICE(0x0489, 0xe100), .driver_info = BTUSB_QCA_WCN6855 |
BTUSB_WIDEBAND_SPEECH },
{ USB_DEVICE(0x0489, 0xe103), .driver_info = BTUSB_QCA_WCN6855 |
BTUSB_WIDEBAND_SPEECH },
{ USB_DEVICE(0x0489, 0xe10a), .driver_info = BTUSB_QCA_WCN6855 |
BTUSB_WIDEBAND_SPEECH },
{ USB_DEVICE(0x0489, 0xe10d), .driver_info = BTUSB_QCA_WCN6855 |
BTUSB_WIDEBAND_SPEECH },
{ USB_DEVICE(0x0489, 0xe11b), .driver_info = BTUSB_QCA_WCN6855 |
BTUSB_WIDEBAND_SPEECH },
{ USB_DEVICE(0x0489, 0xe11c), .driver_info = BTUSB_QCA_WCN6855 |
BTUSB_WIDEBAND_SPEECH },
{ USB_DEVICE(0x0489, 0xe11f), .driver_info = BTUSB_QCA_WCN6855 |
BTUSB_WIDEBAND_SPEECH },
{ USB_DEVICE(0x0489, 0xe141), .driver_info = BTUSB_QCA_WCN6855 |
BTUSB_WIDEBAND_SPEECH },
{ USB_DEVICE(0x0489, 0xe14a), .driver_info = BTUSB_QCA_WCN6855 |
BTUSB_WIDEBAND_SPEECH },
{ USB_DEVICE(0x0489, 0xe14b), .driver_info = BTUSB_QCA_WCN6855 |
BTUSB_WIDEBAND_SPEECH },
{ USB_DEVICE(0x0489, 0xe14d), .driver_info = BTUSB_QCA_WCN6855 |
BTUSB_WIDEBAND_SPEECH },
{ USB_DEVICE(0x13d3, 0x3623), .driver_info = BTUSB_QCA_WCN6855 |
BTUSB_WIDEBAND_SPEECH },
{ USB_DEVICE(0x13d3, 0x3624), .driver_info = BTUSB_QCA_WCN6855 |
BTUSB_WIDEBAND_SPEECH },
{ USB_DEVICE(0x2c7c, 0x0130), .driver_info = BTUSB_QCA_WCN6855 |
BTUSB_WIDEBAND_SPEECH },
{ USB_DEVICE(0x2c7c, 0x0131), .driver_info = BTUSB_QCA_WCN6855 |
BTUSB_WIDEBAND_SPEECH },
{ USB_DEVICE(0x2c7c, 0x0132), .driver_info = BTUSB_QCA_WCN6855 |
BTUSB_WIDEBAND_SPEECH },
/* Broadcom BCM2035 */
{ USB_DEVICE(0x0a5c, 0x2009), .driver_info = BTUSB_BCM92035 },
@@ -640,6 +668,10 @@ static const struct usb_device_id quirks_table[] = {
BTUSB_WIDEBAND_SPEECH },
{ USB_DEVICE(0x0489, 0xe102), .driver_info = BTUSB_MEDIATEK |
BTUSB_WIDEBAND_SPEECH },
{ USB_DEVICE(0x0489, 0xe152), .driver_info = BTUSB_MEDIATEK |
BTUSB_WIDEBAND_SPEECH },
{ USB_DEVICE(0x0489, 0xe153), .driver_info = BTUSB_MEDIATEK |
BTUSB_WIDEBAND_SPEECH },
{ USB_DEVICE(0x04ca, 0x3804), .driver_info = BTUSB_MEDIATEK |
BTUSB_WIDEBAND_SPEECH },
{ USB_DEVICE(0x04ca, 0x38e4), .driver_info = BTUSB_MEDIATEK |
@@ -2477,6 +2509,8 @@ static int btusb_setup_csr(struct hci_dev *hdev)
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);
set_bit(HCI_QUIRK_BROKEN_READ_VOICE_SETTING, &hdev->quirks);
set_bit(HCI_QUIRK_BROKEN_READ_PAGE_SCAN_TYPE, &hdev->quirks);
/* Clear the reset quirk since this is not an actual
* early Bluetooth 1.1 device from CSR.
@@ -2688,7 +2722,7 @@ static void btusb_mtk_claim_iso_intf(struct btusb_data *data)
device_unlock(&btmtk_data->isopkt_intf->dev);
if (err < 0) {
btmtk_data->isopkt_intf = NULL;
bt_dev_err(data->hdev, "Failed to claim iso interface");
bt_dev_err(data->hdev, "Failed to claim iso interface: %d", err);
return;
}

View File

@@ -102,7 +102,8 @@ static inline struct sk_buff *hci_uart_dequeue(struct hci_uart *hu)
if (!skb) {
percpu_down_read(&hu->proto_lock);
if (test_bit(HCI_UART_PROTO_READY, &hu->flags))
if (test_bit(HCI_UART_PROTO_READY, &hu->flags) ||
test_bit(HCI_UART_PROTO_INIT, &hu->flags))
skb = hu->proto->dequeue(hu);
percpu_up_read(&hu->proto_lock);
@@ -124,7 +125,8 @@ int hci_uart_tx_wakeup(struct hci_uart *hu)
if (!percpu_down_read_trylock(&hu->proto_lock))
return 0;
if (!test_bit(HCI_UART_PROTO_READY, &hu->flags))
if (!test_bit(HCI_UART_PROTO_READY, &hu->flags) &&
!test_bit(HCI_UART_PROTO_INIT, &hu->flags))
goto no_schedule;
set_bit(HCI_UART_TX_WAKEUP, &hu->tx_state);
@@ -278,7 +280,8 @@ static int hci_uart_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
percpu_down_read(&hu->proto_lock);
if (!test_bit(HCI_UART_PROTO_READY, &hu->flags)) {
if (!test_bit(HCI_UART_PROTO_READY, &hu->flags) &&
!test_bit(HCI_UART_PROTO_INIT, &hu->flags)) {
percpu_up_read(&hu->proto_lock);
return -EUNATCH;
}
@@ -585,7 +588,8 @@ static void hci_uart_tty_wakeup(struct tty_struct *tty)
if (tty != hu->tty)
return;
if (test_bit(HCI_UART_PROTO_READY, &hu->flags))
if (test_bit(HCI_UART_PROTO_READY, &hu->flags) ||
test_bit(HCI_UART_PROTO_INIT, &hu->flags))
hci_uart_tx_wakeup(hu);
}
@@ -611,7 +615,8 @@ static void hci_uart_tty_receive(struct tty_struct *tty, const u8 *data,
percpu_down_read(&hu->proto_lock);
if (!test_bit(HCI_UART_PROTO_READY, &hu->flags)) {
if (!test_bit(HCI_UART_PROTO_READY, &hu->flags) &&
!test_bit(HCI_UART_PROTO_INIT, &hu->flags)) {
percpu_up_read(&hu->proto_lock);
return;
}
@@ -707,12 +712,16 @@ static int hci_uart_set_proto(struct hci_uart *hu, int id)
hu->proto = p;
set_bit(HCI_UART_PROTO_INIT, &hu->flags);
err = hci_uart_register_dev(hu);
if (err) {
return err;
}
set_bit(HCI_UART_PROTO_READY, &hu->flags);
clear_bit(HCI_UART_PROTO_INIT, &hu->flags);
return 0;
}

View File

@@ -623,6 +623,7 @@ static int qca_open(struct hci_uart *hu)
qcadev = serdev_device_get_drvdata(hu->serdev);
switch (qcadev->btsoc_type) {
case QCA_WCN3950:
case QCA_WCN3988:
case QCA_WCN3990:
case QCA_WCN3991:
@@ -1366,6 +1367,7 @@ static int qca_set_baudrate(struct hci_dev *hdev, uint8_t baudrate)
/* Give the controller time to process the request */
switch (qca_soc_type(hu)) {
case QCA_WCN3950:
case QCA_WCN3988:
case QCA_WCN3990:
case QCA_WCN3991:
@@ -1452,6 +1454,7 @@ static unsigned int qca_get_speed(struct hci_uart *hu,
static int qca_check_speeds(struct hci_uart *hu)
{
switch (qca_soc_type(hu)) {
case QCA_WCN3950:
case QCA_WCN3988:
case QCA_WCN3990:
case QCA_WCN3991:
@@ -1494,6 +1497,7 @@ static int qca_set_speed(struct hci_uart *hu, enum qca_speed_type speed_type)
* changing the baudrate of chip and host.
*/
switch (soc_type) {
case QCA_WCN3950:
case QCA_WCN3988:
case QCA_WCN3990:
case QCA_WCN3991:
@@ -1528,6 +1532,7 @@ static int qca_set_speed(struct hci_uart *hu, enum qca_speed_type speed_type)
error:
switch (soc_type) {
case QCA_WCN3950:
case QCA_WCN3988:
case QCA_WCN3990:
case QCA_WCN3991:
@@ -1746,6 +1751,7 @@ static int qca_regulator_init(struct hci_uart *hu)
}
switch (soc_type) {
case QCA_WCN3950:
case QCA_WCN3988:
case QCA_WCN3990:
case QCA_WCN3991:
@@ -1776,6 +1782,7 @@ static int qca_regulator_init(struct hci_uart *hu)
qca_set_speed(hu, QCA_INIT_SPEED);
switch (soc_type) {
case QCA_WCN3950:
case QCA_WCN3988:
case QCA_WCN3990:
case QCA_WCN3991:
@@ -1807,6 +1814,7 @@ static int qca_power_on(struct hci_dev *hdev)
return 0;
switch (soc_type) {
case QCA_WCN3950:
case QCA_WCN3988:
case QCA_WCN3990:
case QCA_WCN3991:
@@ -1891,6 +1899,7 @@ static int qca_setup(struct hci_uart *hu)
soc_name = "qca2066";
break;
case QCA_WCN3950:
case QCA_WCN3988:
case QCA_WCN3990:
case QCA_WCN3991:
@@ -1925,6 +1934,7 @@ retry:
clear_bit(QCA_SSR_TRIGGERED, &qca->flags);
switch (soc_type) {
case QCA_WCN3950:
case QCA_WCN3988:
case QCA_WCN3990:
case QCA_WCN3991:
@@ -1958,6 +1968,7 @@ retry:
}
switch (soc_type) {
case QCA_WCN3950:
case QCA_WCN3988:
case QCA_WCN3990:
case QCA_WCN3991:
@@ -2046,6 +2057,17 @@ static const struct hci_uart_proto qca_proto = {
.dequeue = qca_dequeue,
};
static const struct qca_device_data qca_soc_data_wcn3950 __maybe_unused = {
.soc_type = QCA_WCN3950,
.vregs = (struct qca_vreg []) {
{ "vddio", 15000 },
{ "vddxo", 60000 },
{ "vddrf", 155000 },
{ "vddch0", 585000 },
},
.num_vregs = 4,
};
static const struct qca_device_data qca_soc_data_wcn3988 __maybe_unused = {
.soc_type = QCA_WCN3988,
.vregs = (struct qca_vreg []) {
@@ -2338,6 +2360,7 @@ static int qca_serdev_probe(struct serdev_device *serdev)
qcadev->btsoc_type = QCA_ROME;
switch (qcadev->btsoc_type) {
case QCA_WCN3950:
case QCA_WCN3988:
case QCA_WCN3990:
case QCA_WCN3991:
@@ -2359,6 +2382,7 @@ static int qca_serdev_probe(struct serdev_device *serdev)
switch (qcadev->btsoc_type) {
case QCA_WCN6855:
case QCA_WCN7850:
case QCA_WCN6750:
if (!device_property_present(&serdev->dev, "enable-gpios")) {
/*
* Backward compatibility with old DT sources. If the
@@ -2374,11 +2398,11 @@ static int qca_serdev_probe(struct serdev_device *serdev)
break;
}
fallthrough;
case QCA_WCN3950:
case QCA_WCN3988:
case QCA_WCN3990:
case QCA_WCN3991:
case QCA_WCN3998:
case QCA_WCN6750:
qcadev->bt_power->dev = &serdev->dev;
err = qca_init_regulators(qcadev->bt_power, data->vregs,
data->num_vregs);
@@ -2683,6 +2707,7 @@ static const struct of_device_id qca_bluetooth_of_match[] = {
{ .compatible = "qcom,qca6174-bt" },
{ .compatible = "qcom,qca6390-bt", .data = &qca_soc_data_qca6390},
{ .compatible = "qcom,qca9377-bt" },
{ .compatible = "qcom,wcn3950-bt", .data = &qca_soc_data_wcn3950},
{ .compatible = "qcom,wcn3988-bt", .data = &qca_soc_data_wcn3988},
{ .compatible = "qcom,wcn3990-bt", .data = &qca_soc_data_wcn3990},
{ .compatible = "qcom,wcn3991-bt", .data = &qca_soc_data_wcn3991},

View File

@@ -90,6 +90,7 @@ struct hci_uart {
#define HCI_UART_REGISTERED 1
#define HCI_UART_PROTO_READY 2
#define HCI_UART_NO_SUSPEND_NOTIFIER 3
#define HCI_UART_PROTO_INIT 4
/* TX states */
#define HCI_UART_SENDING 1

View File

@@ -316,7 +316,7 @@ static inline void force_devcd_timeout(struct hci_dev *hdev,
unsigned int timeout)
{
#ifdef CONFIG_DEV_COREDUMP
hdev->dump.timeout = msecs_to_jiffies(timeout * 1000);
hdev->dump.timeout = secs_to_jiffies(timeout);
#endif
}
@@ -416,6 +416,7 @@ static int __vhci_create_device(struct vhci_data *data, __u8 opcode)
hdev->wakeup = vhci_wakeup;
hdev->setup = vhci_setup;
set_bit(HCI_QUIRK_NON_PERSISTENT_SETUP, &hdev->quirks);
set_bit(HCI_QUIRK_SYNC_FLOWCTL_SUPPORTED, &hdev->quirks);
/* bit 6 is for external configuration */
if (opcode & 0x40)
@@ -645,7 +646,7 @@ static int vhci_open(struct inode *inode, struct file *file)
file->private_data = data;
nonseekable_open(inode, file);
schedule_delayed_work(&data->open_timeout, msecs_to_jiffies(1000));
schedule_delayed_work(&data->open_timeout, secs_to_jiffies(1));
return 0;
}

View File

@@ -443,8 +443,11 @@ static void dpll_pin_prop_free(struct dpll_pin_properties *prop)
static int dpll_pin_prop_dup(const struct dpll_pin_properties *src,
struct dpll_pin_properties *dst)
{
if (WARN_ON(src->freq_supported && !src->freq_supported_num))
return -EINVAL;
memcpy(dst, src, sizeof(*dst));
if (src->freq_supported && src->freq_supported_num) {
if (src->freq_supported) {
size_t freq_size = src->freq_supported_num *
sizeof(*src->freq_supported);
dst->freq_supported = kmemdup(src->freq_supported,

View File

@@ -203,6 +203,15 @@ static void of_gpio_try_fixup_polarity(const struct device_node *np,
*/
{ "qi,lb60", "rb-gpios", true },
#endif
#if IS_ENABLED(CONFIG_IEEE802154_CA8210)
/*
* According to the datasheet, the NRST pin 27 is an active-low
* signal. However, the device tree schema and admittedly
* the out-of-tree implementations have been used for a long
* time incorrectly by describing reset GPIO as active-high.
*/
{ "cascoda,ca8210", "reset-gpio", false },
#endif
#if IS_ENABLED(CONFIG_PCI_LANTIQ)
/*
* According to the PCI specification, the RST# pin is an

View File

@@ -498,8 +498,6 @@ static int irdma_save_msix_info(struct irdma_pci_f *rf)
iw_qvlist->num_vectors = rf->msix_count;
if (rf->msix_count <= num_online_cpus())
rf->msix_shared = true;
else if (rf->msix_count > num_online_cpus() + 1)
rf->msix_count = num_online_cpus() + 1;
pmsix = rf->msix_entries;
for (i = 0, ceq_idx = 0; i < rf->msix_count; i++, iw_qvinfo++) {

View File

@@ -206,6 +206,43 @@ static void irdma_lan_unregister_qset(struct irdma_sc_vsi *vsi,
ibdev_dbg(&iwdev->ibdev, "WS: LAN free_res for rdma qset failed.\n");
}
static int irdma_init_interrupts(struct irdma_pci_f *rf, struct ice_pf *pf)
{
int i;
rf->msix_count = num_online_cpus() + IRDMA_NUM_AEQ_MSIX;
rf->msix_entries = kcalloc(rf->msix_count, sizeof(*rf->msix_entries),
GFP_KERNEL);
if (!rf->msix_entries)
return -ENOMEM;
for (i = 0; i < rf->msix_count; i++)
if (ice_alloc_rdma_qvector(pf, &rf->msix_entries[i]))
break;
if (i < IRDMA_MIN_MSIX) {
for (; i > 0; i--)
ice_free_rdma_qvector(pf, &rf->msix_entries[i]);
kfree(rf->msix_entries);
return -ENOMEM;
}
rf->msix_count = i;
return 0;
}
static void irdma_deinit_interrupts(struct irdma_pci_f *rf, struct ice_pf *pf)
{
int i;
for (i = 0; i < rf->msix_count; i++)
ice_free_rdma_qvector(pf, &rf->msix_entries[i]);
kfree(rf->msix_entries);
}
static void irdma_remove(struct auxiliary_device *aux_dev)
{
struct iidc_auxiliary_dev *iidc_adev = container_of(aux_dev,
@@ -216,6 +253,7 @@ static void irdma_remove(struct auxiliary_device *aux_dev)
irdma_ib_unregister_device(iwdev);
ice_rdma_update_vsi_filter(pf, iwdev->vsi_num, false);
irdma_deinit_interrupts(iwdev->rf, pf);
pr_debug("INIT: Gen2 PF[%d] device remove success\n", PCI_FUNC(pf->pdev->devfn));
}
@@ -230,9 +268,7 @@ static void irdma_fill_device_info(struct irdma_device *iwdev, struct ice_pf *pf
rf->gen_ops.unregister_qset = irdma_lan_unregister_qset;
rf->hw.hw_addr = pf->hw.hw_addr;
rf->pcidev = pf->pdev;
rf->msix_count = pf->num_rdma_msix;
rf->pf_id = pf->hw.pf_id;
rf->msix_entries = &pf->msix_entries[pf->rdma_base_vector];
rf->default_vsi.vsi_idx = vsi->vsi_num;
rf->protocol_used = pf->rdma_mode & IIDC_RDMA_PROTOCOL_ROCEV2 ?
IRDMA_ROCE_PROTOCOL_ONLY : IRDMA_IWARP_PROTOCOL_ONLY;
@@ -281,6 +317,10 @@ static int irdma_probe(struct auxiliary_device *aux_dev, const struct auxiliary_
irdma_fill_device_info(iwdev, pf, vsi);
rf = iwdev->rf;
err = irdma_init_interrupts(rf, pf);
if (err)
goto err_init_interrupts;
err = irdma_ctrl_init_hw(rf);
if (err)
goto err_ctrl_init;
@@ -311,6 +351,8 @@ err_ibreg:
err_rt_init:
irdma_ctrl_deinit_hw(rf);
err_ctrl_init:
irdma_deinit_interrupts(rf, pf);
err_init_interrupts:
kfree(iwdev->rf);
ib_dealloc_device(&iwdev->ibdev);

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