Merge git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-next

Pull networking updates from David Miller:

 1) Add WireGuard

 2) Add HE and TWT support to ath11k driver, from John Crispin.

 3) Add ESP in TCP encapsulation support, from Sabrina Dubroca.

 4) Add variable window congestion control to TIPC, from Jon Maloy.

 5) Add BCM84881 PHY driver, from Russell King.

 6) Start adding netlink support for ethtool operations, from Michal
    Kubecek.

 7) Add XDP drop and TX action support to ena driver, from Sameeh
    Jubran.

 8) Add new ipv4 route notifications so that mlxsw driver does not have
    to handle identical routes itself. From Ido Schimmel.

 9) Add BPF dynamic program extensions, from Alexei Starovoitov.

10) Support RX and TX timestamping in igc, from Vinicius Costa Gomes.

11) Add support for macsec HW offloading, from Antoine Tenart.

12) Add initial support for MPTCP protocol, from Christoph Paasch,
    Matthieu Baerts, Florian Westphal, Peter Krystad, and many others.

13) Add Octeontx2 PF support, from Sunil Goutham, Geetha sowjanya, Linu
    Cherian, and others.

* git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-next: (1469 commits)
  net: phy: add default ARCH_BCM_IPROC for MDIO_BCM_IPROC
  udp: segment looped gso packets correctly
  netem: change mailing list
  qed: FW 8.42.2.0 debug features
  qed: rt init valid initialization changed
  qed: Debug feature: ilt and mdump
  qed: FW 8.42.2.0 Add fw overlay feature
  qed: FW 8.42.2.0 HSI changes
  qed: FW 8.42.2.0 iscsi/fcoe changes
  qed: Add abstraction for different hsi values per chip
  qed: FW 8.42.2.0 Additional ll2 type
  qed: Use dmae to write to widebus registers in fw_funcs
  qed: FW 8.42.2.0 Parser offsets modified
  qed: FW 8.42.2.0 Queue Manager changes
  qed: FW 8.42.2.0 Expose new registers and change windows
  qed: FW 8.42.2.0 Internal ram offsets modifications
  MAINTAINERS: Add entry for Marvell OcteonTX2 Physical Function driver
  Documentation: net: octeontx2: Add RVU HW and drivers overview
  octeontx2-pf: ethtool RSS config support
  octeontx2-pf: Add basic ethtool support
  ...
This commit is contained in:
Linus Torvalds 2020-01-28 16:02:33 -08:00
commit bd2463ac7d
1827 changed files with 156199 additions and 31437 deletions

View File

@ -0,0 +1,63 @@
What: /sys/bus/mdio_bus/devices/.../statistics/
Date: January 2020
KernelVersion: 5.6
Contact: netdev@vger.kernel.org
Description:
This folder contains statistics about global and per
MDIO bus address statistics.
What: /sys/bus/mdio_bus/devices/.../statistics/transfers
Date: January 2020
KernelVersion: 5.6
Contact: netdev@vger.kernel.org
Description:
Total number of transfers for this MDIO bus.
What: /sys/bus/mdio_bus/devices/.../statistics/errors
Date: January 2020
KernelVersion: 5.6
Contact: netdev@vger.kernel.org
Description:
Total number of transfer errors for this MDIO bus.
What: /sys/bus/mdio_bus/devices/.../statistics/writes
Date: January 2020
KernelVersion: 5.6
Contact: netdev@vger.kernel.org
Description:
Total number of write transactions for this MDIO bus.
What: /sys/bus/mdio_bus/devices/.../statistics/reads
Date: January 2020
KernelVersion: 5.6
Contact: netdev@vger.kernel.org
Description:
Total number of read transactions for this MDIO bus.
What: /sys/bus/mdio_bus/devices/.../statistics/transfers_<addr>
Date: January 2020
KernelVersion: 5.6
Contact: netdev@vger.kernel.org
Description:
Total number of transfers for this MDIO bus address.
What: /sys/bus/mdio_bus/devices/.../statistics/errors_<addr>
Date: January 2020
KernelVersion: 5.6
Contact: netdev@vger.kernel.org
Description:
Total number of transfer errors for this MDIO bus address.
What: /sys/bus/mdio_bus/devices/.../statistics/writes_<addr>
Date: January 2020
KernelVersion: 5.6
Contact: netdev@vger.kernel.org
Description:
Total number of write transactions for this MDIO bus address.
What: /sys/bus/mdio_bus/devices/.../statistics/reads_<addr>
Date: January 2020
KernelVersion: 5.6
Contact: netdev@vger.kernel.org
Description:
Total number of read transactions for this MDIO bus address.

View File

@ -11,6 +11,7 @@ Required properties:
- compatible: should contain one of the following:
* "brcm,bcm20702a1"
* "brcm,bcm4329-bt"
* "brcm,bcm4330-bt"
* "brcm,bcm43438-bt"
* "brcm,bcm4345c5"
@ -22,7 +23,9 @@ Optional properties:
- max-speed: see Documentation/devicetree/bindings/serial/slave-device.txt
- shutdown-gpios: GPIO specifier, used to enable the BT module
- device-wakeup-gpios: GPIO specifier, used to wakeup the controller
- host-wakeup-gpios: GPIO specifier, used to wakeup the host processor
- host-wakeup-gpios: GPIO specifier, used to wakeup the host processor.
deprecated, replaced by interrupts and
"host-wakeup" interrupt-names
- clocks: 1 or 2 clocks as defined in clock-names below, in that order
- clock-names: names for clock inputs, matching the clocks given
- "extclk": deprecated, replaced by "txco"
@ -30,7 +33,14 @@ Optional properties:
- "lpo": external low power 32.768 kHz clock
- vbat-supply: phandle to regulator supply for VBAT
- vddio-supply: phandle to regulator supply for VDDIO
- brcm,bt-pcm-int-params: configure PCM parameters via a 5-byte array
- sco-routing: 0 = PCM, 1 = Transport, 2 = Codec, 3 = I2S
- pcm-interface-rate: 128KBps, 256KBps, 512KBps, 1024KBps, 2048KBps
- pcm-frame-type: short, long
- pcm-sync-mode: slave, master
- pcm-clock-mode: slave, master
- interrupts: must be one, used to wakeup the host processor
- interrupt-names: must be "host-wakeup"
Example:
@ -41,5 +51,6 @@ Example:
bluetooth {
compatible = "brcm,bcm43438-bt";
max-speed = <921600>;
brcm,bt-pcm-int-params = [01 02 00 01 01];
};
};

View File

@ -0,0 +1,148 @@
Atheros AR9331 built-in switch
=============================
It is a switch built-in to Atheros AR9331 WiSoC and addressable over internal
MDIO bus. All PHYs are built-in as well.
Required properties:
- compatible: should be: "qca,ar9331-switch"
- reg: Address on the MII bus for the switch.
- resets : Must contain an entry for each entry in reset-names.
- reset-names : Must include the following entries: "switch"
- interrupt-parent: Phandle to the parent interrupt controller
- interrupts: IRQ line for the switch
- interrupt-controller: Indicates the switch is itself an interrupt
controller. This is used for the PHY interrupts.
- #interrupt-cells: must be 1
- mdio: Container of PHY and devices on the switches MDIO bus.
See Documentation/devicetree/bindings/net/dsa/dsa.txt for a list of additional
required and optional properties.
Examples:
eth0: ethernet@19000000 {
compatible = "qca,ar9330-eth";
reg = <0x19000000 0x200>;
interrupts = <4>;
resets = <&rst 9>, <&rst 22>;
reset-names = "mac", "mdio";
clocks = <&pll ATH79_CLK_AHB>, <&pll ATH79_CLK_AHB>;
clock-names = "eth", "mdio";
phy-mode = "mii";
phy-handle = <&phy_port4>;
};
eth1: ethernet@1a000000 {
compatible = "qca,ar9330-eth";
reg = <0x1a000000 0x200>;
interrupts = <5>;
resets = <&rst 13>, <&rst 23>;
reset-names = "mac", "mdio";
clocks = <&pll ATH79_CLK_AHB>, <&pll ATH79_CLK_AHB>;
clock-names = "eth", "mdio";
phy-mode = "gmii";
fixed-link {
speed = <1000>;
full-duplex;
};
mdio {
#address-cells = <1>;
#size-cells = <0>;
switch10: switch@10 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "qca,ar9331-switch";
reg = <0x10>;
resets = <&rst 8>;
reset-names = "switch";
interrupt-parent = <&miscintc>;
interrupts = <12>;
interrupt-controller;
#interrupt-cells = <1>;
ports {
#address-cells = <1>;
#size-cells = <0>;
switch_port0: port@0 {
reg = <0x0>;
label = "cpu";
ethernet = <&eth1>;
phy-mode = "gmii";
fixed-link {
speed = <1000>;
full-duplex;
};
};
switch_port1: port@1 {
reg = <0x1>;
phy-handle = <&phy_port0>;
phy-mode = "internal";
};
switch_port2: port@2 {
reg = <0x2>;
phy-handle = <&phy_port1>;
phy-mode = "internal";
};
switch_port3: port@3 {
reg = <0x3>;
phy-handle = <&phy_port2>;
phy-mode = "internal";
};
switch_port4: port@4 {
reg = <0x4>;
phy-handle = <&phy_port3>;
phy-mode = "internal";
};
};
mdio {
#address-cells = <1>;
#size-cells = <0>;
interrupt-parent = <&switch10>;
phy_port0: phy@0 {
reg = <0x0>;
interrupts = <0>;
};
phy_port1: phy@1 {
reg = <0x1>;
interrupts = <0>;
};
phy_port2: phy@2 {
reg = <0x2>;
interrupts = <0>;
};
phy_port3: phy@3 {
reg = <0x3>;
interrupts = <0>;
};
phy_port4: phy@4 {
reg = <0x4>;
interrupts = <0>;
};
};
};
};
};

View File

@ -14,7 +14,7 @@ Required properties:
Should be "macirq" for the main MAC IRQ
- clocks: Must contain a phandle for each entry in clock-names.
- clock-names: The name of the clock listed in the clocks property. These are
"axi", "apb", "mac_main", "ptp_ref" for MT2712 SoC
"axi", "apb", "mac_main", "ptp_ref", "rmii_internal" for MT2712 SoC.
- mac-address: See ethernet.txt in the same directory
- phy-mode: See ethernet.txt in the same directory
- mediatek,pericfg: A phandle to the syscon node that control ethernet
@ -23,8 +23,10 @@ Required properties:
Optional properties:
- mediatek,tx-delay-ps: TX clock delay macro value. Default is 0.
It should be defined for RGMII/MII interface.
It should be defined for RMII interface when the reference clock is from MT2712 SoC.
- mediatek,rx-delay-ps: RX clock delay macro value. Default is 0.
It should be defined for RGMII/MII/RMII interface.
It should be defined for RGMII/MII interface.
It should be defined for RMII interface.
Both delay properties need to be a multiple of 170 for RGMII interface,
or will round down. Range 0~31*170.
Both delay properties need to be a multiple of 550 for MII/RMII interface,
@ -34,13 +36,20 @@ or will round down. Range 0~31*550.
reference clock, which is from external PHYs, is connected to RXC pin
on MT2712 SoC.
Otherwise, is connected to TXC pin.
- mediatek,rmii-clk-from-mac: boolean property, if present indicates that
MT2712 SoC provides the RMII reference clock, which outputs to TXC pin only.
- mediatek,txc-inverse: boolean property, if present indicates that
1. tx clock will be inversed in MII/RGMII case,
2. tx clock inside MAC will be inversed relative to reference clock
which is from external PHYs in RMII case, and it rarely happen.
3. the reference clock, which outputs to TXC pin will be inversed in RMII case
when the reference clock is from MT2712 SoC.
- mediatek,rxc-inverse: boolean property, if present indicates that
1. rx clock will be inversed in MII/RGMII case.
2. reference clock will be inversed when arrived at MAC in RMII case.
2. reference clock will be inversed when arrived at MAC in RMII case, when
the reference clock is from external PHYs.
3. the inside clock, which be sent to MAC, will be inversed in RMII case when
the reference clock is from MT2712 SoC.
- assigned-clocks: mac_main and ptp_ref clocks
- assigned-clock-parents: parent clocks of the assigned clocks
@ -50,29 +59,33 @@ Example:
reg = <0 0x1101c000 0 0x1300>;
interrupts = <GIC_SPI 237 IRQ_TYPE_LEVEL_LOW>;
interrupt-names = "macirq";
phy-mode ="rgmii";
phy-mode ="rgmii-rxid";
mac-address = [00 55 7b b5 7d f7];
clock-names = "axi",
"apb",
"mac_main",
"ptp_ref",
"ptp_top";
"rmii_internal";
clocks = <&pericfg CLK_PERI_GMAC>,
<&pericfg CLK_PERI_GMAC_PCLK>,
<&topckgen CLK_TOP_ETHER_125M_SEL>,
<&topckgen CLK_TOP_ETHER_50M_SEL>;
<&topckgen CLK_TOP_ETHER_50M_SEL>,
<&topckgen CLK_TOP_ETHER_50M_RMII_SEL>;
assigned-clocks = <&topckgen CLK_TOP_ETHER_125M_SEL>,
<&topckgen CLK_TOP_ETHER_50M_SEL>;
<&topckgen CLK_TOP_ETHER_50M_SEL>,
<&topckgen CLK_TOP_ETHER_50M_RMII_SEL>;
assigned-clock-parents = <&topckgen CLK_TOP_ETHERPLL_125M>,
<&topckgen CLK_TOP_APLL1_D3>;
<&topckgen CLK_TOP_APLL1_D3>,
<&topckgen CLK_TOP_ETHERPLL_50M>;
power-domains = <&scpsys MT2712_POWER_DOMAIN_AUDIO>;
mediatek,pericfg = <&pericfg>;
mediatek,tx-delay-ps = <1530>;
mediatek,rx-delay-ps = <1530>;
mediatek,rmii-rxc;
mediatek,txc-inverse;
mediatek,rxc-inverse;
snps,txpbl = <32>;
snps,rxpbl = <32>;
snps,txpbl = <1>;
snps,rxpbl = <1>;
snps,reset-gpio = <&pio 87 GPIO_ACTIVE_LOW>;
snps,reset-active-low;
};

View File

@ -8,8 +8,6 @@ Required properties:
- ti,tx-internal-delay - RGMII Transmit Clock Delay - see dt-bindings/net/ti-dp83867.h
for applicable values. Required only if interface type is
PHY_INTERFACE_MODE_RGMII_ID or PHY_INTERFACE_MODE_RGMII_TXID
- ti,fifo-depth - Transmitt FIFO depth- see dt-bindings/net/ti-dp83867.h
for applicable values
Note: If the interface type is PHY_INTERFACE_MODE_RGMII the TX/RX clock delays
will be left at their default values, as set by the PHY's pin strapping.
@ -42,6 +40,14 @@ Optional property:
Some MACs work with differential SGMII clock.
See data manual for details.
- ti,fifo-depth - Transmitt FIFO depth- see dt-bindings/net/ti-dp83867.h
for applicable values (deprecated)
-tx-fifo-depth - As defined in the ethernet-controller.yaml. Values for
the depth can be found in dt-bindings/net/ti-dp83867.h
-rx-fifo-depth - As defined in the ethernet-controller.yaml. Values for
the depth can be found in dt-bindings/net/ti-dp83867.h
Note: ti,min-output-impedance and ti,max-output-impedance are mutually
exclusive. When both properties are present ti,max-output-impedance
takes precedence.
@ -55,7 +61,7 @@ Example:
reg = <0>;
ti,rx-internal-delay = <DP83867_RGMIIDCTL_2_25_NS>;
ti,tx-internal-delay = <DP83867_RGMIIDCTL_2_75_NS>;
ti,fifo-depth = <DP83867_PHYCR_FIFO_DEPTH_4_B_NIB>;
tx-fifo-depth = <DP83867_PHYCR_FIFO_DEPTH_4_B_NIB>;
};
Datasheet can be found:

View File

@ -50,7 +50,7 @@ Optional properties:
entry in clock-names.
- clock-names: Should contain the clock names "wifi_wcss_cmd", "wifi_wcss_ref",
"wifi_wcss_rtc" for "qcom,ipq4019-wifi" compatible target and
"cxo_ref_clk_pin" for "qcom,wcn3990-wifi"
"cxo_ref_clk_pin" and optionally "qdss" for "qcom,wcn3990-wifi"
compatible target.
- qcom,msi_addr: MSI interrupt address.
- qcom,msi_base: Base value to add before writing MSI data into
@ -88,6 +88,9 @@ Optional properties:
of the host capability QMI request
- qcom,xo-cal-data: xo cal offset to be configured in xo trim register.
- qcom,msa-fixed-perm: Boolean context flag to disable SCM call for statically
mapped msa region.
Example (to supply PCI based wifi block details):
In this example, the node is defined as child node of the PCI controller.
@ -185,4 +188,5 @@ wifi@18000000 {
vdd-3.3-ch0-supply = <&vreg_l25a_3p3>;
memory-region = <&wifi_msa_mem>;
iommus = <&apps_smmu 0x0040 0x1>;
qcom,msa-fixed-perm;
};

View File

@ -0,0 +1,273 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
# Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
%YAML 1.2
---
$id: http://devicetree.org/schemas/net/wireless/qcom,ath11k.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Qualcomm Technologies ath11k wireless devices Generic Binding
maintainers:
- Kalle Valo <kvalo@codeaurora.org>
description: |
These are dt entries for Qualcomm Technologies, Inc. IEEE 802.11ax
devices, for example like AHB based IPQ8074.
properties:
compatible:
const: qcom,ipq8074-wifi
reg:
maxItems: 1
interrupts:
items:
- description: misc-pulse1 interrupt events
- description: misc-latch interrupt events
- description: sw exception interrupt events
- description: watchdog interrupt events
- description: interrupt event for ring CE0
- description: interrupt event for ring CE1
- description: interrupt event for ring CE2
- description: interrupt event for ring CE3
- description: interrupt event for ring CE4
- description: interrupt event for ring CE5
- description: interrupt event for ring CE6
- description: interrupt event for ring CE7
- description: interrupt event for ring CE8
- description: interrupt event for ring CE9
- description: interrupt event for ring CE10
- description: interrupt event for ring CE11
- description: interrupt event for ring host2wbm-desc-feed
- description: interrupt event for ring host2reo-re-injection
- description: interrupt event for ring host2reo-command
- description: interrupt event for ring host2rxdma-monitor-ring3
- description: interrupt event for ring host2rxdma-monitor-ring2
- description: interrupt event for ring host2rxdma-monitor-ring1
- description: interrupt event for ring reo2ost-exception
- description: interrupt event for ring wbm2host-rx-release
- description: interrupt event for ring reo2host-status
- description: interrupt event for ring reo2host-destination-ring4
- description: interrupt event for ring reo2host-destination-ring3
- description: interrupt event for ring reo2host-destination-ring2
- description: interrupt event for ring reo2host-destination-ring1
- description: interrupt event for ring rxdma2host-monitor-destination-mac3
- description: interrupt event for ring rxdma2host-monitor-destination-mac2
- description: interrupt event for ring rxdma2host-monitor-destination-mac1
- description: interrupt event for ring ppdu-end-interrupts-mac3
- description: interrupt event for ring ppdu-end-interrupts-mac2
- description: interrupt event for ring ppdu-end-interrupts-mac1
- description: interrupt event for ring rxdma2host-monitor-status-ring-mac3
- description: interrupt event for ring rxdma2host-monitor-status-ring-mac2
- description: interrupt event for ring rxdma2host-monitor-status-ring-mac1
- description: interrupt event for ring host2rxdma-host-buf-ring-mac3
- description: interrupt event for ring host2rxdma-host-buf-ring-mac2
- description: interrupt event for ring host2rxdma-host-buf-ring-mac1
- description: interrupt event for ring rxdma2host-destination-ring-mac3
- description: interrupt event for ring rxdma2host-destination-ring-mac2
- description: interrupt event for ring rxdma2host-destination-ring-mac1
- description: interrupt event for ring host2tcl-input-ring4
- description: interrupt event for ring host2tcl-input-ring3
- description: interrupt event for ring host2tcl-input-ring2
- description: interrupt event for ring host2tcl-input-ring1
- description: interrupt event for ring wbm2host-tx-completions-ring3
- description: interrupt event for ring wbm2host-tx-completions-ring2
- description: interrupt event for ring wbm2host-tx-completions-ring1
- description: interrupt event for ring tcl2host-status-ring
interrupt-names:
items:
- const: misc-pulse1
- const: misc-latch
- const: sw-exception
- const: watchdog
- const: ce0
- const: ce1
- const: ce2
- const: ce3
- const: ce4
- const: ce5
- const: ce6
- const: ce7
- const: ce8
- const: ce9
- const: ce10
- const: ce11
- const: host2wbm-desc-feed
- const: host2reo-re-injection
- const: host2reo-command
- const: host2rxdma-monitor-ring3
- const: host2rxdma-monitor-ring2
- const: host2rxdma-monitor-ring1
- const: reo2ost-exception
- const: wbm2host-rx-release
- const: reo2host-status
- const: reo2host-destination-ring4
- const: reo2host-destination-ring3
- const: reo2host-destination-ring2
- const: reo2host-destination-ring1
- const: rxdma2host-monitor-destination-mac3
- const: rxdma2host-monitor-destination-mac2
- const: rxdma2host-monitor-destination-mac1
- const: ppdu-end-interrupts-mac3
- const: ppdu-end-interrupts-mac2
- const: ppdu-end-interrupts-mac1
- const: rxdma2host-monitor-status-ring-mac3
- const: rxdma2host-monitor-status-ring-mac2
- const: rxdma2host-monitor-status-ring-mac1
- const: host2rxdma-host-buf-ring-mac3
- const: host2rxdma-host-buf-ring-mac2
- const: host2rxdma-host-buf-ring-mac1
- const: rxdma2host-destination-ring-mac3
- const: rxdma2host-destination-ring-mac2
- const: rxdma2host-destination-ring-mac1
- const: host2tcl-input-ring4
- const: host2tcl-input-ring3
- const: host2tcl-input-ring2
- const: host2tcl-input-ring1
- const: wbm2host-tx-completions-ring3
- const: wbm2host-tx-completions-ring2
- const: wbm2host-tx-completions-ring1
- const: tcl2host-status-ring
qcom,rproc:
$ref: /schemas/types.yaml#definitions/phandle
description:
DT entry of q6v5-wcss remoteproc driver.
Phandle to a node that can contain the following properties
* compatible
* reg
* reg-names
required:
- compatible
- reg
- interrupts
- interrupt-names
- qcom,rproc
additionalProperties: false
examples:
- |
q6v5_wcss: q6v5_wcss@CD00000 {
compatible = "qcom,ipq8074-wcss-pil";
reg = <0xCD00000 0x4040>,
<0x4AB000 0x20>;
reg-names = "qdsp6",
"rmb";
};
wifi0: wifi@c000000 {
compatible = "qcom,ipq8074-wifi";
reg = <0xc000000 0x2000000>;
interrupts = <0 320 1>,
<0 319 1>,
<0 318 1>,
<0 317 1>,
<0 316 1>,
<0 315 1>,
<0 314 1>,
<0 311 1>,
<0 310 1>,
<0 411 1>,
<0 410 1>,
<0 40 1>,
<0 39 1>,
<0 302 1>,
<0 301 1>,
<0 37 1>,
<0 36 1>,
<0 296 1>,
<0 295 1>,
<0 294 1>,
<0 293 1>,
<0 292 1>,
<0 291 1>,
<0 290 1>,
<0 289 1>,
<0 288 1>,
<0 239 1>,
<0 236 1>,
<0 235 1>,
<0 234 1>,
<0 233 1>,
<0 232 1>,
<0 231 1>,
<0 230 1>,
<0 229 1>,
<0 228 1>,
<0 224 1>,
<0 223 1>,
<0 203 1>,
<0 183 1>,
<0 180 1>,
<0 179 1>,
<0 178 1>,
<0 177 1>,
<0 176 1>,
<0 163 1>,
<0 162 1>,
<0 160 1>,
<0 159 1>,
<0 158 1>,
<0 157 1>,
<0 156 1>;
interrupt-names = "misc-pulse1",
"misc-latch",
"sw-exception",
"watchdog",
"ce0",
"ce1",
"ce2",
"ce3",
"ce4",
"ce5",
"ce6",
"ce7",
"ce8",
"ce9",
"ce10",
"ce11",
"host2wbm-desc-feed",
"host2reo-re-injection",
"host2reo-command",
"host2rxdma-monitor-ring3",
"host2rxdma-monitor-ring2",
"host2rxdma-monitor-ring1",
"reo2ost-exception",
"wbm2host-rx-release",
"reo2host-status",
"reo2host-destination-ring4",
"reo2host-destination-ring3",
"reo2host-destination-ring2",
"reo2host-destination-ring1",
"rxdma2host-monitor-destination-mac3",
"rxdma2host-monitor-destination-mac2",
"rxdma2host-monitor-destination-mac1",
"ppdu-end-interrupts-mac3",
"ppdu-end-interrupts-mac2",
"ppdu-end-interrupts-mac1",
"rxdma2host-monitor-status-ring-mac3",
"rxdma2host-monitor-status-ring-mac2",
"rxdma2host-monitor-status-ring-mac1",
"host2rxdma-host-buf-ring-mac3",
"host2rxdma-host-buf-ring-mac2",
"host2rxdma-host-buf-ring-mac1",
"rxdma2host-destination-ring-mac3",
"rxdma2host-destination-ring-mac2",
"rxdma2host-destination-ring-mac1",
"host2tcl-input-ring4",
"host2tcl-input-ring3",
"host2tcl-input-ring2",
"host2tcl-input-ring1",
"wbm2host-tx-completions-ring3",
"wbm2host-tx-completions-ring2",
"wbm2host-tx-completions-ring1",
"tcl2host-status-ring";
qcom,rproc = <&q6v5_wcss>;
};

View File

@ -0,0 +1,35 @@
ZHAW InES PTP time stamping IP core
The IP core needs two different kinds of nodes. The control node
lives somewhere in the memory map and specifies the address of the
control registers. There can be up to three port handles placed as
attributes of PHY nodes. These associate a particular MII bus with a
port index within the IP core.
Required properties of the control node:
- compatible: "ines,ptp-ctrl"
- reg: physical address and size of the register bank
Required format of the port handle within the PHY node:
- timestamper: provides control node reference and
the port channel within the IP core
Example:
tstamper: timestamper@60000000 {
compatible = "ines,ptp-ctrl";
reg = <0x60000000 0x80>;
};
ethernet@80000000 {
...
mdio {
...
ethernet-phy@3 {
...
timestamper = <&tstamper 0>;
};
};
};

View File

@ -0,0 +1,42 @@
Time stamps from MII bus snooping devices
This binding supports non-PHY devices that snoop the MII bus and
provide time stamps. In contrast to PHY time stamping drivers (which
can simply attach their interface directly to the PHY instance), stand
alone MII time stamping drivers use this binding to specify the
connection between the snooping device and a given network interface.
Non-PHY MII time stamping drivers typically talk to the control
interface over another bus like I2C, SPI, UART, or via a memory mapped
peripheral. This controller device is associated with one or more
time stamping channels, each of which snoops on a MII bus.
The "timestamper" property lives in a phy node and links a time
stamping channel from the controller device to that phy's MII bus.
Example:
tstamper: timestamper@10000000 {
compatible = "ines,ptp-ctrl";
reg = <0x10000000 0x80>;
};
ethernet@20000000 {
mdio {
ethernet-phy@1 {
timestamper = <&tstamper 0>;
};
};
};
ethernet@30000000 {
mdio {
ethernet-phy@2 {
timestamper = <&tstamper 1>;
};
};
};
In this example, time stamps from the MII bus attached to phy@1 will
appear on time stamp channel 0 (zero), and those from phy@2 appear on
channel 1.

View File

@ -22,9 +22,11 @@ Contents:
intel/iavf
intel/ice
google/gve
marvell/octeontx2
mellanox/mlx5
netronome/nfp
pensando/ionic
stmicro/stmmac
.. only:: subproject and html

View File

@ -0,0 +1,159 @@
.. SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
====================================
Marvell OcteonTx2 RVU Kernel Drivers
====================================
Copyright (c) 2020 Marvell International Ltd.
Contents
========
- `Overview`_
- `Drivers`_
- `Basic packet flow`_
Overview
========
Resource virtualization unit (RVU) on Marvell's OcteonTX2 SOC maps HW
resources from the network, crypto and other functional blocks into
PCI-compatible physical and virtual functions. Each functional block
again has multiple local functions (LFs) for provisioning to PCI devices.
RVU supports multiple PCIe SRIOV physical functions (PFs) and virtual
functions (VFs). PF0 is called the administrative / admin function (AF)
and has privileges to provision RVU functional block's LFs to each of the
PF/VF.
RVU managed networking functional blocks
- Network pool or buffer allocator (NPA)
- Network interface controller (NIX)
- Network parser CAM (NPC)
- Schedule/Synchronize/Order unit (SSO)
- Loopback interface (LBK)
RVU managed non-networking functional blocks
- Crypto accelerator (CPT)
- Scheduled timers unit (TIM)
- Schedule/Synchronize/Order unit (SSO)
Used for both networking and non networking usecases
Resource provisioning examples
- A PF/VF with NIX-LF & NPA-LF resources works as a pure network device
- A PF/VF with CPT-LF resource works as a pure crypto offload device.
RVU functional blocks are highly configurable as per software requirements.
Firmware setups following stuff before kernel boots
- Enables required number of RVU PFs based on number of physical links.
- Number of VFs per PF are either static or configurable at compile time.
Based on config, firmware assigns VFs to each of the PFs.
- Also assigns MSIX vectors to each of PF and VFs.
- These are not changed after kernel boot.
Drivers
=======
Linux kernel will have multiple drivers registering to different PF and VFs
of RVU. Wrt networking there will be 3 flavours of drivers.
Admin Function driver
---------------------
As mentioned above RVU PF0 is called the admin function (AF), this driver
supports resource provisioning and configuration of functional blocks.
Doesn't handle any I/O. It sets up few basic stuff but most of the
funcionality is achieved via configuration requests from PFs and VFs.
PF/VFs communicates with AF via a shared memory region (mailbox). Upon
receiving requests AF does resource provisioning and other HW configuration.
AF is always attached to host kernel, but PFs and their VFs may be used by host
kernel itself, or attached to VMs or to userspace applications like
DPDK etc. So AF has to handle provisioning/configuration requests sent
by any device from any domain.
AF driver also interacts with underlying firmware to
- Manage physical ethernet links ie CGX LMACs.
- Retrieve information like speed, duplex, autoneg etc
- Retrieve PHY EEPROM and stats.
- Configure FEC, PAM modes
- etc
From pure networking side AF driver supports following functionality.
- Map a physical link to a RVU PF to which a netdev is registered.
- Attach NIX and NPA block LFs to RVU PF/VF which provide buffer pools, RQs, SQs
for regular networking functionality.
- Flow control (pause frames) enable/disable/config.
- HW PTP timestamping related config.
- NPC parser profile config, basically how to parse pkt and what info to extract.
- NPC extract profile config, what to extract from the pkt to match data in MCAM entries.
- Manage NPC MCAM entries, upon request can frame and install requested packet forwarding rules.
- Defines receive side scaling (RSS) algorithms.
- Defines segmentation offload algorithms (eg TSO)
- VLAN stripping, capture and insertion config.
- SSO and TIM blocks config which provide packet scheduling support.
- Debugfs support, to check current resource provising, current status of
NPA pools, NIX RQ, SQ and CQs, various stats etc which helps in debugging issues.
- And many more.
Physical Function driver
------------------------
This RVU PF handles IO, is mapped to a physical ethernet link and this
driver registers a netdev. This supports SR-IOV. As said above this driver
communicates with AF with a mailbox. To retrieve information from physical
links this driver talks to AF and AF gets that info from firmware and responds
back ie cannot talk to firmware directly.
Supports ethtool for configuring links, RSS, queue count, queue size,
flow control, ntuple filters, dump PHY EEPROM, config FEC etc.
Virtual Function driver
-----------------------
There are two types VFs, VFs that share the physical link with their parent
SR-IOV PF and the VFs which work in pairs using internal HW loopback channels (LBK).
Type1:
- These VFs and their parent PF share a physical link and used for outside communication.
- VFs cannot communicate with AF directly, they send mbox message to PF and PF
forwards that to AF. AF after processing, responds back to PF and PF forwards
the reply to VF.
- From functionality point of view there is no difference between PF and VF as same type
HW resources are attached to both. But user would be able to configure few stuff only
from PF as PF is treated as owner/admin of the link.
Type2:
- RVU PF0 ie admin function creates these VFs and maps them to loopback block's channels.
- A set of two VFs (VF0 & VF1, VF2 & VF3 .. so on) works as a pair ie pkts sent out of
VF0 will be received by VF1 and viceversa.
- These VFs can be used by applications or virtual machines to communicate between them
without sending traffic outside. There is no switch present in HW, hence the support
for loopback VFs.
- These communicate directly with AF (PF0) via mbox.
Except for the IO channels or links used for packet reception and transmission there is
no other difference between these VF types. AF driver takes care of IO channel mapping,
hence same VF driver works for both types of devices.
Basic packet flow
=================
Ingress
-------
1. CGX LMAC receives packet.
2. Forwards the packet to the NIX block.
3. Then submitted to NPC block for parsing and then MCAM lookup to get the destination RVU device.
4. NIX LF attached to the destination RVU device allocates a buffer from RQ mapped buffer pool of NPA block LF.
5. RQ may be selected by RSS or by configuring MCAM rule with a RQ number.
6. Packet is DMA'ed and driver is notified.
Egress
------
1. Driver prepares a send descriptor and submits to SQ for transmission.
2. The SQ is already configured (by AF) to transmit on a specific link/channel.
3. The SQ descriptor ring is maintained in buffers allocated from SQ mapped pool of NPA block LF.
4. NIX block transmits the pkt on the designated channel.
5. NPC MCAM entries can be installed to divert pkt onto a different channel.

View File

@ -82,3 +82,24 @@ Features
contain one or more packets. The send buffer is an optimization, the driver
will use slower method to handle very large packets or if the send buffer
area is exhausted.
XDP support
-----------
XDP (eXpress Data Path) is a feature that runs eBPF bytecode at the early
stage when packets arrive at a NIC card. The goal is to increase performance
for packet processing, reducing the overhead of SKB allocation and other
upper network layers.
hv_netvsc supports XDP in native mode, and transparently sets the XDP
program on the associated VF NIC as well.
Setting / unsetting XDP program on synthetic NIC (netvsc) propagates to
VF NIC automatically. Setting / unsetting XDP program on VF NIC directly
is not recommended, also not propagated to synthetic NIC, and may be
overwritten by setting of synthetic NIC.
XDP program cannot run with LRO (RSC) enabled, so you need to disable LRO
before running XDP:
ethtool -K eth0 lro off
XDP_REDIRECT action is not yet supported.

View File

@ -131,3 +131,119 @@ abi_drv_reset
abi_drv_load_ifc
Defines a list of PF devices allowed to load FW on the device.
This variable is not currently user configurable.
Statistics
==========
Following device statistics are available through the ``ethtool -S`` interface:
.. flat-table:: NFP device statistics
:header-rows: 1
:widths: 3 1 11
* - Name
- ID
- Meaning
* - dev_rx_discards
- 1
- Packet can be discarded on the RX path for one of the following reasons:
* The NIC is not in promisc mode, and the destination MAC address
doesn't match the interfaces' MAC address.
* The received packet is larger than the max buffer size on the host.
I.e. it exceeds the Layer 3 MRU.
* There is no freelist descriptor available on the host for the packet.
It is likely that the NIC couldn't cache one in time.
* A BPF program discarded the packet.
* The datapath drop action was executed.
* The MAC discarded the packet due to lack of ingress buffer space
on the NIC.
* - dev_rx_errors
- 2
- A packet can be counted (and dropped) as RX error for the following
reasons:
* A problem with the VEB lookup (only when SR-IOV is used).
* A physical layer problem that causes Ethernet errors, like FCS or
alignment errors. The cause is usually faulty cables or SFPs.
* - dev_rx_bytes
- 3
- Total number of bytes received.
* - dev_rx_uc_bytes
- 4
- Unicast bytes received.
* - dev_rx_mc_bytes
- 5
- Multicast bytes received.
* - dev_rx_bc_bytes
- 6
- Broadcast bytes received.
* - dev_rx_pkts
- 7
- Total number of packets received.
* - dev_rx_mc_pkts
- 8
- Multicast packets received.
* - dev_rx_bc_pkts
- 9
- Broadcast packets received.
* - dev_tx_discards
- 10
- A packet can be discarded in the TX direction if the MAC is
being flow controlled and the NIC runs out of TX queue space.
* - dev_tx_errors
- 11
- A packet can be counted as TX error (and dropped) for one for the
following reasons:
* The packet is an LSO segment, but the Layer 3 or Layer 4 offset
could not be determined. Therefore LSO could not continue.
* An invalid packet descriptor was received over PCIe.
* The packet Layer 3 length exceeds the device MTU.
* An error on the MAC/physical layer. Usually due to faulty cables or
SFPs.
* A CTM buffer could not be allocated.
* The packet offset was incorrect and could not be fixed by the NIC.
* - dev_tx_bytes
- 12
- Total number of bytes transmitted.
* - dev_tx_uc_bytes
- 13
- Unicast bytes transmitted.
* - dev_tx_mc_bytes
- 14
- Multicast bytes transmitted.
* - dev_tx_bc_bytes
- 15
- Broadcast bytes transmitted.
* - dev_tx_pkts
- 16
- Total number of packets transmitted.
* - dev_tx_mc_pkts
- 17
- Multicast packets transmitted.
* - dev_tx_bc_pkts
- 18
- Broadcast packets transmitted.
Note that statistics unknown to the driver will be displayed as
``dev_unknown_stat$ID``, where ``$ID`` refers to the second column
above.

View File

@ -0,0 +1,697 @@
.. SPDX-License-Identifier: GPL-2.0+
==============================================================
Linux Driver for the Synopsys(R) Ethernet Controllers "stmmac"
==============================================================
Authors: Giuseppe Cavallaro <peppe.cavallaro@st.com>,
Alexandre Torgue <alexandre.torgue@st.com>, Jose Abreu <joabreu@synopsys.com>
Contents
========
- In This Release
- Feature List
- Kernel Configuration
- Command Line Parameters
- Driver Information and Notes
- Debug Information
- Support
In This Release
===============
This file describes the stmmac Linux Driver for all the Synopsys(R) Ethernet
Controllers.
Currently, this network device driver is for all STi embedded MAC/GMAC
(i.e. 7xxx/5xxx SoCs), SPEAr (arm), Loongson1B (mips) and XILINX XC2V3000
FF1152AMT0221 D1215994A VIRTEX FPGA board. The Synopsys Ethernet QoS 5.0 IPK
is also supported.
DesignWare(R) Cores Ethernet MAC 10/100/1000 Universal version 3.70a
(and older) and DesignWare(R) Cores Ethernet Quality-of-Service version 4.0
(and upper) have been used for developing this driver as well as
DesignWare(R) Cores XGMAC - 10G Ethernet MAC.
This driver supports both the platform bus and PCI.
This driver includes support for the following Synopsys(R) DesignWare(R)
Cores Ethernet Controllers and corresponding minimum and maximum versions:
+-------------------------------+--------------+--------------+--------------+
| Controller Name | Min. Version | Max. Version | Abbrev. Name |
+===============================+==============+==============+==============+
| Ethernet MAC Universal | N/A | 3.73a | GMAC |
+-------------------------------+--------------+--------------+--------------+
| Ethernet Quality-of-Service | 4.00a | N/A | GMAC4+ |
+-------------------------------+--------------+--------------+--------------+
| XGMAC - 10G Ethernet MAC | 2.10a | N/A | XGMAC2+ |
+-------------------------------+--------------+--------------+--------------+
For questions related to hardware requirements, refer to the documentation
supplied with your Ethernet adapter. All hardware requirements listed apply
to use with Linux.
Feature List
============
The following features are available in this driver:
- GMII/MII/RGMII/SGMII/RMII/XGMII Interface
- Half-Duplex / Full-Duplex Operation
- Energy Efficient Ethernet (EEE)
- IEEE 802.3x PAUSE Packets (Flow Control)
- RMON/MIB Counters
- IEEE 1588 Timestamping (PTP)
- Pulse-Per-Second Output (PPS)
- MDIO Clause 22 / Clause 45 Interface
- MAC Loopback
- ARP Offloading
- Automatic CRC / PAD Insertion and Checking
- Checksum Offload for Received and Transmitted Packets
- Standard or Jumbo Ethernet Packets
- Source Address Insertion / Replacement
- VLAN TAG Insertion / Replacement / Deletion / Filtering (HASH and PERFECT)
- Programmable TX and RX Watchdog and Coalesce Settings
- Destination Address Filtering (PERFECT)
- HASH Filtering (Multicast)
- Layer 3 / Layer 4 Filtering
- Remote Wake-Up Detection
- Receive Side Scaling (RSS)
- Frame Preemption for TX and RX
- Programmable Burst Length, Threshold, Queue Size
- Multiple Queues (up to 8)
- Multiple Scheduling Algorithms (TX: WRR, DWRR, WFQ, SP, CBS, EST, TBS;
RX: WRR, SP)
- Flexible RX Parser
- TCP / UDP Segmentation Offload (TSO, USO)
- Split Header (SPH)
- Safety Features (ECC Protection, Data Parity Protection)
- Selftests using Ethtool
Kernel Configuration
====================
The kernel configuration option is ``CONFIG_STMMAC_ETH``:
- ``CONFIG_STMMAC_PLATFORM``: is to enable the platform driver.
- ``CONFIG_STMMAC_PCI``: is to enable the pci driver.
Command Line Parameters
=======================
If the driver is built as a module the following optional parameters are used
by entering them on the command line with the modprobe command using this
syntax (e.g. for PCI module)::
modprobe stmmac_pci [<option>=<VAL1>,<VAL2>,...]
Driver parameters can be also passed in command line by using::
stmmaceth=watchdog:100,chain_mode=1
The default value for each parameter is generally the recommended setting,
unless otherwise noted.
watchdog
--------
:Valid Range: 5000-None
:Default Value: 5000
This parameter overrides the transmit timeout in milliseconds.
debug
-----
:Valid Range: 0-16 (0=none,...,16=all)
:Default Value: 0
This parameter adjusts the level of debug messages displayed in the system
logs.
phyaddr
-------
:Valid Range: 0-31
:Default Value: -1
This parameter overrides the physical address of the PHY device.
flow_ctrl
---------
:Valid Range: 0-3 (0=off,1=rx,2=tx,3=rx/tx)
:Default Value: 3
This parameter changes the default Flow Control ability.
pause
-----
:Valid Range: 0-65535
:Default Value: 65535
This parameter changes the default Flow Control Pause time.
tc
--
:Valid Range: 64-256
:Default Value: 64
This parameter changes the default HW FIFO Threshold control value.
buf_sz
------
:Valid Range: 1536-16384
:Default Value: 1536
This parameter changes the default RX DMA packet buffer size.
eee_timer
---------
:Valid Range: 0-None
:Default Value: 1000
This parameter changes the default LPI TX Expiration time in milliseconds.
chain_mode
----------
:Valid Range: 0-1 (0=off,1=on)
:Default Value: 0
This parameter changes the default mode of operation from Ring Mode to
Chain Mode.
Driver Information and Notes
============================
Transmit Process
----------------
The xmit method is invoked when the kernel needs to transmit a packet; it sets
the descriptors in the ring and informs the DMA engine that there is a packet
ready to be transmitted.
By default, the driver sets the ``NETIF_F_SG`` bit in the features field of
the ``net_device`` structure, enabling the scatter-gather feature. This is
true on chips and configurations where the checksum can be done in hardware.
Once the controller has finished transmitting the packet, timer will be
scheduled to release the transmit resources.
Receive Process
---------------
When one or more packets are received, an interrupt happens. The interrupts
are not queued, so the driver has to scan all the descriptors in the ring
during the receive process.
This is based on NAPI, so the interrupt handler signals only if there is work
to be done, and it exits. Then the poll method will be scheduled at some
future point.
The incoming packets are stored, by the DMA, in a list of pre-allocated socket
buffers in order to avoid the memcpy (zero-copy).
Interrupt Mitigation
--------------------
The driver is able to mitigate the number of its DMA interrupts using NAPI for
the reception on chips older than the 3.50. New chips have an HW RX Watchdog
used for this mitigation.
Mitigation parameters can be tuned by ethtool.
WoL
---
Wake up on Lan feature through Magic and Unicast frames are supported for the
GMAC, GMAC4/5 and XGMAC core.
DMA Descriptors
---------------
Driver handles both normal and alternate descriptors. The latter has been only
tested on DesignWare(R) Cores Ethernet MAC Universal version 3.41a and later.
stmmac supports DMA descriptor to operate both in dual buffer (RING) and
linked-list(CHAINED) mode. In RING each descriptor points to two data buffer
pointers whereas in CHAINED mode they point to only one data buffer pointer.
RING mode is the default.
In CHAINED mode each descriptor will have pointer to next descriptor in the
list, hence creating the explicit chaining in the descriptor itself, whereas
such explicit chaining is not possible in RING mode.
Extended Descriptors
--------------------
The extended descriptors give us information about the Ethernet payload when
it is carrying PTP packets or TCP/UDP/ICMP over IP. These are not available on
GMAC Synopsys(R) chips older than the 3.50. At probe time the driver will
decide if these can be actually used. This support also is mandatory for PTPv2
because the extra descriptors are used for saving the hardware timestamps and
Extended Status.
Ethtool Support
---------------
Ethtool is supported. For example, driver statistics (including RMON),
internal errors can be taken using::
ethtool -S ethX
Ethtool selftests are also supported. This allows to do some early sanity
checks to the HW using MAC and PHY loopback mechanisms::
ethtool -t ethX
Jumbo and Segmentation Offloading
---------------------------------
Jumbo frames are supported and tested for the GMAC. The GSO has been also
added but it's performed in software. LRO is not supported.
TSO Support
-----------
TSO (TCP Segmentation Offload) feature is supported by GMAC > 4.x and XGMAC
chip family. When a packet is sent through TCP protocol, the TCP stack ensures
that the SKB provided to the low level driver (stmmac in our case) matches
with the maximum frame len (IP header + TCP header + payload <= 1500 bytes
(for MTU set to 1500)). It means that if an application using TCP want to send
a packet which will have a length (after adding headers) > 1514 the packet
will be split in several TCP packets: The data payload is split and headers
(TCP/IP ..) are added. It is done by software.
When TSO is enabled, the TCP stack doesn't care about the maximum frame length
and provide SKB packet to stmmac as it is. The GMAC IP will have to perform
the segmentation by it self to match with maximum frame length.
This feature can be enabled in device tree through ``snps,tso`` entry.
Energy Efficient Ethernet
-------------------------
Energy Efficient Ethernet (EEE) enables IEEE 802.3 MAC sublayer along with a
family of Physical layer to operate in the Low Power Idle (LPI) mode. The EEE
mode supports the IEEE 802.3 MAC operation at 100Mbps, 1000Mbps and 1Gbps.
The LPI mode allows power saving by switching off parts of the communication
device functionality when there is no data to be transmitted & received.
The system on both the side of the link can disable some functionalities and
save power during the period of low-link utilization. The MAC controls whether
the system should enter or exit the LPI mode and communicate this to PHY.
As soon as the interface is opened, the driver verifies if the EEE can be
supported. This is done by looking at both the DMA HW capability register and
the PHY devices MCD registers.
To enter in TX LPI mode the driver needs to have a software timer that enable
and disable the LPI mode when there is nothing to be transmitted.
Precision Time Protocol (PTP)
-----------------------------
The driver supports the IEEE 1588-2002, Precision Time Protocol (PTP), which
enables precise synchronization of clocks in measurement and control systems
implemented with technologies such as network communication.
In addition to the basic timestamp features mentioned in IEEE 1588-2002
Timestamps, new GMAC cores support the advanced timestamp features.
IEEE 1588-2008 can be enabled when configuring the Kernel.
SGMII/RGMII Support
-------------------
New GMAC devices provide own way to manage RGMII/SGMII. This information is
available at run-time by looking at the HW capability register. This means
that the stmmac can manage auto-negotiation and link status w/o using the
PHYLIB stuff. In fact, the HW provides a subset of extended registers to
restart the ANE, verify Full/Half duplex mode and Speed. Thanks to these
registers, it is possible to look at the Auto-negotiated Link Parter Ability.
Physical
--------
The driver is compatible with Physical Abstraction Layer to be connected with
PHY and GPHY devices.
Platform Information
--------------------
Several information can be passed through the platform and device-tree.
::
struct plat_stmmacenet_data {
1) Bus identifier::
int bus_id;
2) PHY Physical Address. If set to -1 the driver will pick the first PHY it
finds::
int phy_addr;
3) PHY Device Interface::
int interface;
4) Specific platform fields for the MDIO bus::
struct stmmac_mdio_bus_data *mdio_bus_data;
5) Internal DMA parameters::
struct stmmac_dma_cfg *dma_cfg;
6) Fixed CSR Clock Range selection::
int clk_csr;
7) HW uses the GMAC core::
int has_gmac;
8) If set the MAC will use Enhanced Descriptors::
int enh_desc;
9) Core is able to perform TX Checksum and/or RX Checksum in HW::
int tx_coe;
int rx_coe;
11) Some HWs are not able to perform the csum in HW for over-sized frames due
to limited buffer sizes. Setting this flag the csum will be done in SW on
JUMBO frames::
int bugged_jumbo;
12) Core has the embedded power module::
int pmt;
13) Force DMA to use the Store and Forward mode or Threshold mode::
int force_sf_dma_mode;
int force_thresh_dma_mode;
15) Force to disable the RX Watchdog feature and switch to NAPI mode::
int riwt_off;
16) Limit the maximum operating speed and MTU::
int max_speed;
int maxmtu;
18) Number of Multicast/Unicast filters::
int multicast_filter_bins;
int unicast_filter_entries;
20) Limit the maximum TX and RX FIFO size::
int tx_fifo_size;
int rx_fifo_size;
21) Use the specified number of TX and RX Queues::
u32 rx_queues_to_use;
u32 tx_queues_to_use;
22) Use the specified TX and RX scheduling algorithm::
u8 rx_sched_algorithm;
u8 tx_sched_algorithm;
23) Internal TX and RX Queue parameters::
struct stmmac_rxq_cfg rx_queues_cfg[MTL_MAX_RX_QUEUES];
struct stmmac_txq_cfg tx_queues_cfg[MTL_MAX_TX_QUEUES];
24) This callback is used for modifying some syscfg registers (on ST SoCs)
according to the link speed negotiated by the physical layer::
void (*fix_mac_speed)(void *priv, unsigned int speed);
25) Callbacks used for calling a custom initialization; This is sometimes
necessary on some platforms (e.g. ST boxes) where the HW needs to have set
some PIO lines or system cfg registers. init/exit callbacks should not use
or modify platform data::
int (*init)(struct platform_device *pdev, void *priv);
void (*exit)(struct platform_device *pdev, void *priv);
26) Perform HW setup of the bus. For example, on some ST platforms this field
is used to configure the AMBA bridge to generate more efficient STBus traffic::
struct mac_device_info *(*setup)(void *priv);
void *bsp_priv;
27) Internal clocks and rates::
struct clk *stmmac_clk;
struct clk *pclk;
struct clk *clk_ptp_ref;
unsigned int clk_ptp_rate;
unsigned int clk_ref_rate;
s32 ptp_max_adj;
28) Main reset::
struct reset_control *stmmac_rst;
29) AXI Internal Parameters::
struct stmmac_axi *axi;
30) HW uses GMAC>4 cores::
int has_gmac4;
31) HW is sun8i based::
bool has_sun8i;
32) Enables TSO feature::
bool tso_en;
33) Enables Receive Side Scaling (RSS) feature::
int rss_en;
34) MAC Port selection::
int mac_port_sel_speed;
35) Enables TX LPI Clock Gating::
bool en_tx_lpi_clockgating;
36) HW uses XGMAC>2.10 cores::
int has_xgmac;
::
}
For MDIO bus data, we have:
::
struct stmmac_mdio_bus_data {
1) PHY mask passed when MDIO bus is registered::
unsigned int phy_mask;
2) List of IRQs, one per PHY::
int *irqs;
3) If IRQs is NULL, use this for probed PHY::
int probed_phy_irq;
4) Set to true if PHY needs reset::
bool needs_reset;
::
}
For DMA engine configuration, we have:
::
struct stmmac_dma_cfg {
1) Programmable Burst Length (TX and RX)::
int pbl;
2) If set, DMA TX / RX will use this value rather than pbl::
int txpbl;
int rxpbl;
3) Enable 8xPBL::
bool pblx8;
4) Enable Fixed or Mixed burst::
int fixed_burst;
int mixed_burst;
5) Enable Address Aligned Beats::
bool aal;
6) Enable Enhanced Addressing (> 32 bits)::
bool eame;
::
}
For DMA AXI parameters, we have:
::
struct stmmac_axi {
1) Enable AXI LPI::
bool axi_lpi_en;
bool axi_xit_frm;
2) Set AXI Write / Read maximum outstanding requests::
u32 axi_wr_osr_lmt;
u32 axi_rd_osr_lmt;
3) Set AXI 4KB bursts::
bool axi_kbbe;
4) Set AXI maximum burst length map::
u32 axi_blen[AXI_BLEN];
5) Set AXI Fixed burst / mixed burst::
bool axi_fb;
bool axi_mb;
6) Set AXI rebuild incrx mode::
bool axi_rb;
::
}
For the RX Queues configuration, we have:
::
struct stmmac_rxq_cfg {
1) Mode to use (DCB or AVB)::
u8 mode_to_use;
2) DMA channel to use::
u32 chan;
3) Packet routing, if applicable::
u8 pkt_route;
4) Use priority routing, and priority to route::
bool use_prio;
u32 prio;
::
}
For the TX Queues configuration, we have:
::
struct stmmac_txq_cfg {
1) Queue weight in scheduler::
u32 weight;
2) Mode to use (DCB or AVB)::
u8 mode_to_use;
3) Credit Base Shaper Parameters::
u32 send_slope;
u32 idle_slope;
u32 high_credit;
u32 low_credit;
4) Use priority scheduling, and priority::
bool use_prio;
u32 prio;
::
}
Device Tree Information
-----------------------
Please refer to the following document:
Documentation/devicetree/bindings/net/snps,dwmac.yaml
HW Capabilities
---------------
Note that, starting from new chips, where it is available the HW capability
register, many configurations are discovered at run-time for example to
understand if EEE, HW csum, PTP, enhanced descriptor etc are actually
available. As strategy adopted in this driver, the information from the HW
capability register can replace what has been passed from the platform.
Debug Information
=================
The driver exports many information i.e. internal statistics, debug
information, MAC and DMA registers etc.
These can be read in several ways depending on the type of the information
actually needed.
For example a user can be use the ethtool support to get statistics: e.g.
using: ``ethtool -S ethX`` (that shows the Management counters (MMC) if
supported) or sees the MAC/DMA registers: e.g. using: ``ethtool -d ethX``
Compiling the Kernel with ``CONFIG_DEBUG_FS`` the driver will export the
following debugfs entries:
- ``descriptors_status``: To show the DMA TX/RX descriptor rings
- ``dma_cap``: To show the HW Capabilities
Developer can also use the ``debug`` module parameter to get further debug
information (please see: NETIF Msg Level).
Support
=======
If an issue is identified with the released source code on a supported kernel
with a supported adapter, email the specific information related to the
issue to netdev@vger.kernel.org

View File

@ -1,401 +0,0 @@
STMicroelectronics 10/100/1000 Synopsys Ethernet driver
Copyright (C) 2007-2015 STMicroelectronics Ltd
Author: Giuseppe Cavallaro <peppe.cavallaro@st.com>
This is the driver for the MAC 10/100/1000 on-chip Ethernet controllers
(Synopsys IP blocks).
Currently this network device driver is for all STi embedded MAC/GMAC
(i.e. 7xxx/5xxx SoCs), SPEAr (arm), Loongson1B (mips) and XLINX XC2V3000
FF1152AMT0221 D1215994A VIRTEX FPGA board.
DWC Ether MAC 10/100/1000 Universal version 3.70a (and older) and DWC Ether
MAC 10/100 Universal version 4.0 have been used for developing this driver.
This driver supports both the platform bus and PCI.
Please, for more information also visit: www.stlinux.com
1) Kernel Configuration
The kernel configuration option is STMMAC_ETH:
Device Drivers ---> Network device support ---> Ethernet (1000 Mbit) --->
STMicroelectronics 10/100/1000 Ethernet driver (STMMAC_ETH)
CONFIG_STMMAC_PLATFORM: is to enable the platform driver.
CONFIG_STMMAC_PCI: is to enable the pci driver.
2) Driver parameters list:
debug: message level (0: no output, 16: all);
phyaddr: to manually provide the physical address to the PHY device;
buf_sz: DMA buffer size;
tc: control the HW FIFO threshold;
watchdog: transmit timeout (in milliseconds);
flow_ctrl: Flow control ability [on/off];
pause: Flow Control Pause Time;
eee_timer: tx EEE timer;
chain_mode: select chain mode instead of ring.
3) Command line options
Driver parameters can be also passed in command line by using:
stmmaceth=watchdog:100,chain_mode=1
4) Driver information and notes
4.1) Transmit process
The xmit method is invoked when the kernel needs to transmit a packet; it sets
the descriptors in the ring and informs the DMA engine, that there is a packet
ready to be transmitted.
By default, the driver sets the NETIF_F_SG bit in the features field of the
net_device structure, enabling the scatter-gather feature. This is true on
chips and configurations where the checksum can be done in hardware.
Once the controller has finished transmitting the packet, timer will be
scheduled to release the transmit resources.
4.2) Receive process
When one or more packets are received, an interrupt happens. The interrupts
are not queued, so the driver has to scan all the descriptors in the ring during
the receive process.
This is based on NAPI, so the interrupt handler signals only if there is work
to be done, and it exits.
Then the poll method will be scheduled at some future point.
The incoming packets are stored, by the DMA, in a list of pre-allocated socket
buffers in order to avoid the memcpy (zero-copy).
4.3) Interrupt mitigation
The driver is able to mitigate the number of its DMA interrupts
using NAPI for the reception on chips older than the 3.50.
New chips have an HW RX-Watchdog used for this mitigation.
Mitigation parameters can be tuned by ethtool.
4.4) WOL
Wake up on Lan feature through Magic and Unicast frames are supported for the
GMAC core.
4.5) DMA descriptors
Driver handles both normal and alternate descriptors. The latter has been only
tested on DWC Ether MAC 10/100/1000 Universal version 3.41a and later.
STMMAC supports DMA descriptor to operate both in dual buffer (RING)
and linked-list(CHAINED) mode. In RING each descriptor points to two
data buffer pointers whereas in CHAINED mode they point to only one data
buffer pointer. RING mode is the default.
In CHAINED mode each descriptor will have pointer to next descriptor in
the list, hence creating the explicit chaining in the descriptor itself,
whereas such explicit chaining is not possible in RING mode.
4.5.1) Extended descriptors
The extended descriptors give us information about the Ethernet payload
when it is carrying PTP packets or TCP/UDP/ICMP over IP.
These are not available on GMAC Synopsys chips older than the 3.50.
At probe time the driver will decide if these can be actually used.
This support also is mandatory for PTPv2 because the extra descriptors
are used for saving the hardware timestamps and Extended Status.
4.6) Ethtool support
Ethtool is supported.
For example, driver statistics (including RMON), internal errors can be taken
using:
# ethtool -S ethX
command
4.7) Jumbo and Segmentation Offloading
Jumbo frames are supported and tested for the GMAC.
The GSO has been also added but it's performed in software.
LRO is not supported.
4.8) Physical
The driver is compatible with Physical Abstraction Layer to be connected with
PHY and GPHY devices.
4.9) Platform information
Several information can be passed through the platform and device-tree.
struct plat_stmmacenet_data {
char *phy_bus_name;
int bus_id;
int phy_addr;
int interface;
struct stmmac_mdio_bus_data *mdio_bus_data;
struct stmmac_dma_cfg *dma_cfg;
int clk_csr;
int has_gmac;
int enh_desc;
int tx_coe;
int rx_coe;
int bugged_jumbo;
int pmt;
int force_sf_dma_mode;
int force_thresh_dma_mode;
int riwt_off;
int max_speed;
int maxmtu;
void (*fix_mac_speed)(void *priv, unsigned int speed);
void (*bus_setup)(void __iomem *ioaddr);
int (*init)(struct platform_device *pdev, void *priv);
void (*exit)(struct platform_device *pdev, void *priv);
void *bsp_priv;
int has_gmac4;
bool tso_en;
};
Where:
o phy_bus_name: phy bus name to attach to the stmmac.
o bus_id: bus identifier.
o phy_addr: the physical address can be passed from the platform.
If it is set to -1 the driver will automatically
detect it at run-time by probing all the 32 addresses.
o interface: PHY device's interface.
o mdio_bus_data: specific platform fields for the MDIO bus.
o dma_cfg: internal DMA parameters
o pbl: the Programmable Burst Length is maximum number of beats to
be transferred in one DMA transaction.
GMAC also enables the 4xPBL by default. (8xPBL for GMAC 3.50 and newer)
o txpbl/rxpbl: GMAC and newer supports independent DMA pbl for tx/rx.
o pblx8: Enable 8xPBL (4xPBL for core rev < 3.50). Enabled by default.
o fixed_burst/mixed_burst/aal
o clk_csr: fixed CSR Clock range selection.
o has_gmac: uses the GMAC core.
o enh_desc: if sets the MAC will use the enhanced descriptor structure.
o tx_coe: core is able to perform the tx csum in HW.
o rx_coe: the supports three check sum offloading engine types:
type_1, type_2 (full csum) and no RX coe.
o bugged_jumbo: some HWs are not able to perform the csum in HW for
over-sized frames due to limited buffer sizes.
Setting this flag the csum will be done in SW on
JUMBO frames.
o pmt: core has the embedded power module (optional).
o force_sf_dma_mode: force DMA to use the Store and Forward mode
instead of the Threshold.
o force_thresh_dma_mode: force DMA to use the Threshold mode other than
the Store and Forward mode.
o riwt_off: force to disable the RX watchdog feature and switch to NAPI mode.
o fix_mac_speed: this callback is used for modifying some syscfg registers
(on ST SoCs) according to the link speed negotiated by the
physical layer .
o bus_setup: perform HW setup of the bus. For example, on some ST platforms
this field is used to configure the AMBA bridge to generate more
efficient STBus traffic.
o init/exit: callbacks used for calling a custom initialization;
this is sometime necessary on some platforms (e.g. ST boxes)
where the HW needs to have set some PIO lines or system cfg
registers. init/exit callbacks should not use or modify
platform data.
o bsp_priv: another private pointer.
o has_gmac4: uses GMAC4 core.
o tso_en: Enables TSO (TCP Segmentation Offload) feature.
For MDIO bus The we have:
struct stmmac_mdio_bus_data {
int (*phy_reset)(void *priv);
unsigned int phy_mask;
int *irqs;
int probed_phy_irq;
};
Where:
o phy_reset: hook to reset the phy device attached to the bus.
o phy_mask: phy mask passed when register the MDIO bus within the driver.
o irqs: list of IRQs, one per PHY.
o probed_phy_irq: if irqs is NULL, use this for probed PHY.
For DMA engine we have the following internal fields that should be
tuned according to the HW capabilities.
struct stmmac_dma_cfg {
int pbl;
int txpbl;
int rxpbl;
bool pblx8;
int fixed_burst;
int mixed_burst;
bool aal;
};
Where:
o pbl: Programmable Burst Length (tx and rx)
o txpbl: Transmit Programmable Burst Length. Only for GMAC and newer.
If set, DMA tx will use this value rather than pbl.
o rxpbl: Receive Programmable Burst Length. Only for GMAC and newer.
If set, DMA rx will use this value rather than pbl.
o pblx8: Enable 8xPBL (4xPBL for core rev < 3.50). Enabled by default.
o fixed_burst: program the DMA to use the fixed burst mode
o mixed_burst: program the DMA to use the mixed burst mode
o aal: Address-Aligned Beats
---
Below an example how the structures above are using on ST platforms.
static struct plat_stmmacenet_data stxYYY_ethernet_platform_data = {
.has_gmac = 0,
.enh_desc = 0,
.fix_mac_speed = stxYYY_ethernet_fix_mac_speed,
|
|-> to write an internal syscfg
| on this platform when the
| link speed changes from 10 to
| 100 and viceversa
.init = &stmmac_claim_resource,
|
|-> On ST SoC this calls own "PAD"
| manager framework to claim
| all the resources necessary
| (GPIO ...). The .custom_cfg field
| is used to pass a custom config.
};
Below the usage of the stmmac_mdio_bus_data: on this SoC, in fact,
there are two MAC cores: one MAC is for MDIO Bus/PHY emulation
with fixed_link support.
static struct stmmac_mdio_bus_data stmmac1_mdio_bus = {
.phy_reset = phy_reset;
|
|-> function to provide the phy_reset on this board
.phy_mask = 0,
};
static struct fixed_phy_status stmmac0_fixed_phy_status = {
.link = 1,
.speed = 100,
.duplex = 1,
};
During the board's device_init we can configure the first
MAC for fixed_link by calling:
fixed_phy_add(PHY_POLL, 1, &stmmac0_fixed_phy_status);
and the second one, with a real PHY device attached to the bus,
by using the stmmac_mdio_bus_data structure (to provide the id, the
reset procedure etc).
Note that, starting from new chips, where it is available the HW capability
register, many configurations are discovered at run-time for example to
understand if EEE, HW csum, PTP, enhanced descriptor etc are actually
available. As strategy adopted in this driver, the information from the HW
capability register can replace what has been passed from the platform.
4.10) Device-tree support.
Please see the following document:
Documentation/devicetree/bindings/net/stmmac.txt
4.11) This is a summary of the content of some relevant files:
o stmmac_main.c: implements the main network device driver;
o stmmac_mdio.c: provides MDIO functions;
o stmmac_pci: this is the PCI driver;
o stmmac_platform.c: this the platform driver (OF supported);
o stmmac_ethtool.c: implements the ethtool support;
o stmmac.h: private driver structure;
o common.h: common definitions and VFTs;
o mmc_core.c/mmc.h: Management MAC Counters;
o stmmac_hwtstamp.c: HW timestamp support for PTP;
o stmmac_ptp.c: PTP 1588 clock;
o stmmac_pcs.h: Physical Coding Sublayer common implementation;
o dwmac-<XXX>.c: these are for the platform glue-logic file; e.g. dwmac-sti.c
for STMicroelectronics SoCs.
- GMAC 3.x
o descs.h: descriptor structure definitions;
o dwmac1000_core.c: dwmac GiGa core functions;
o dwmac1000_dma.c: dma functions for the GMAC chip;
o dwmac1000.h: specific header file for the dwmac GiGa;
o dwmac100_core: dwmac 100 core code;
o dwmac100_dma.c: dma functions for the dwmac 100 chip;
o dwmac1000.h: specific header file for the MAC;
o dwmac_lib.c: generic DMA functions;
o enh_desc.c: functions for handling enhanced descriptors;
o norm_desc.c: functions for handling normal descriptors;
o chain_mode.c/ring_mode.c:: functions to manage RING/CHAINED modes;
- GMAC4.x generation
o dwmac4_core.c: dwmac GMAC4.x core functions;
o dwmac4_desc.c: functions for handling GMAC4.x descriptors;
o dwmac4_descs.h: descriptor definitions;
o dwmac4_dma.c: dma functions for the GMAC4.x chip;
o dwmac4_dma.h: dma definitions for the GMAC4.x chip;
o dwmac4.h: core definitions for the GMAC4.x chip;
o dwmac4_lib.c: generic GMAC4.x functions;
4.12) TSO support (GMAC4.x)
TSO (Tcp Segmentation Offload) feature is supported by GMAC 4.x chip family.
When a packet is sent through TCP protocol, the TCP stack ensures that
the SKB provided to the low level driver (stmmac in our case) matches with
the maximum frame len (IP header + TCP header + payload <= 1500 bytes (for
MTU set to 1500)). It means that if an application using TCP want to send a
packet which will have a length (after adding headers) > 1514 the packet
will be split in several TCP packets: The data payload is split and headers
(TCP/IP ..) are added. It is done by software.
When TSO is enabled, the TCP stack doesn't care about the maximum frame
length and provide SKB packet to stmmac as it is. The GMAC IP will have to
perform the segmentation by it self to match with maximum frame length.
This feature can be enabled in device tree through "snps,tso" entry.
5) Debug Information
The driver exports many information i.e. internal statistics,
debug information, MAC and DMA registers etc.
These can be read in several ways depending on the
type of the information actually needed.
For example a user can be use the ethtool support
to get statistics: e.g. using: ethtool -S ethX
(that shows the Management counters (MMC) if supported)
or sees the MAC/DMA registers: e.g. using: ethtool -d ethX
Compiling the Kernel with CONFIG_DEBUG_FS the driver will export the following
debugfs entries:
/sys/kernel/debug/stmmaceth/descriptors_status
To show the DMA TX/RX descriptor rings
Developer can also use the "debug" module parameter to get further debug
information (please see: NETIF Msg Level).
6) Energy Efficient Ethernet
Energy Efficient Ethernet(EEE) enables IEEE 802.3 MAC sublayer along
with a family of Physical layer to operate in the Low power Idle(LPI)
mode. The EEE mode supports the IEEE 802.3 MAC operation at 100Mbps,
1000Mbps & 10Gbps.
The LPI mode allows power saving by switching off parts of the
communication device functionality when there is no data to be
transmitted & received. The system on both the side of the link can
disable some functionalities & save power during the period of low-link
utilization. The MAC controls whether the system should enter or exit
the LPI mode & communicate this to PHY.
As soon as the interface is opened, the driver verifies if the EEE can
be supported. This is done by looking at both the DMA HW capability
register and the PHY devices MCD registers.
To enter in Tx LPI mode the driver needs to have a software timer
that enable and disable the LPI mode when there is nothing to be
transmitted.
7) Precision Time Protocol (PTP)
The driver supports the IEEE 1588-2002, Precision Time Protocol (PTP),
which enables precise synchronization of clocks in measurement and
control systems implemented with technologies such as network
communication.
In addition to the basic timestamp features mentioned in IEEE 1588-2002
Timestamps, new GMAC cores support the advanced timestamp features.
IEEE 1588-2008 that can be enabled when configure the Kernel.
8) SGMII/RGMII support
New GMAC devices provide own way to manage RGMII/SGMII.
This information is available at run-time by looking at the
HW capability register. This means that the stmmac can manage
auto-negotiation and link status w/o using the PHYLIB stuff.
In fact, the HW provides a subset of extended registers to
restart the ANE, verify Full/Half duplex mode and Speed.
Thanks to these registers, it is possible to look at the
Auto-negotiated Link Parter Ability.

View File

@ -39,7 +39,7 @@ but without enabling "switch" mode, or to different bridges.
Devlink configuration parameters
====================
See Documentation/networking/devlink-params-ti-cpsw-switch.txt
See Documentation/networking/devlink/ti-cpsw-switch.rst
====================
# Bridging in dual mac mode

View File

@ -1,86 +0,0 @@
The health mechanism is targeted for Real Time Alerting, in order to know when
something bad had happened to a PCI device
- Provide alert debug information
- Self healing
- If problem needs vendor support, provide a way to gather all needed debugging
information.
The main idea is to unify and centralize driver health reports in the
generic devlink instance and allow the user to set different
attributes of the health reporting and recovery procedures.
The devlink health reporter:
Device driver creates a "health reporter" per each error/health type.
Error/Health type can be a known/generic (eg pci error, fw error, rx/tx error)
or unknown (driver specific).
For each registered health reporter a driver can issue error/health reports
asynchronously. All health reports handling is done by devlink.
Device driver can provide specific callbacks for each "health reporter", e.g.
- Recovery procedures
- Diagnostics and object dump procedures
- OOB initial parameters
Different parts of the driver can register different types of health reporters
with different handlers.
Once an error is reported, devlink health will do the following actions:
* A log is being send to the kernel trace events buffer
* Health status and statistics are being updated for the reporter instance
* Object dump is being taken and saved at the reporter instance (as long as
there is no other dump which is already stored)
* Auto recovery attempt is being done. Depends on:
- Auto-recovery configuration
- Grace period vs. time passed since last recover
The user interface:
User can access/change each reporter's parameters and driver specific callbacks
via devlink, e.g per error type (per health reporter)
- Configure reporter's generic parameters (like: disable/enable auto recovery)
- Invoke recovery procedure
- Run diagnostics
- Object dump
The devlink health interface (via netlink):
DEVLINK_CMD_HEALTH_REPORTER_GET
Retrieves status and configuration info per DEV and reporter.
DEVLINK_CMD_HEALTH_REPORTER_SET
Allows reporter-related configuration setting.
DEVLINK_CMD_HEALTH_REPORTER_RECOVER
Triggers a reporter's recovery procedure.
DEVLINK_CMD_HEALTH_REPORTER_DIAGNOSE
Retrieves diagnostics data from a reporter on a device.
DEVLINK_CMD_HEALTH_REPORTER_DUMP_GET
Retrieves the last stored dump. Devlink health
saves a single dump. If an dump is not already stored by the devlink
for this reporter, devlink generates a new dump.
dump output is defined by the reporter.
DEVLINK_CMD_HEALTH_REPORTER_DUMP_CLEAR
Clears the last saved dump file for the specified reporter.
netlink
+--------------------------+
| |
| + |
| | |
+--------------------------+
|request for ops
|(diagnose,
mlx5_core devlink |recover,
|dump)
+--------+ +--------------------------+
| | | reporter| |
| | | +---------v----------+ |
| | ops execution | | | |
| <----------------------------------+ | |
| | | | | |
| | | + ^------------------+ |
| | | | request for ops |
| | | | (recover, dump) |
| | | | |
| | | +-+------------------+ |
| | health report | | health handler | |
| +-------------------------------> | |
| | | +--------------------+ |
| | health reporter create | |
| +----------------------------> |
+--------+ +--------------------------+

View File

@ -1,64 +0,0 @@
.. SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
=====================
Devlink info versions
=====================
board.id
========
Unique identifier of the board design.
board.rev
=========
Board design revision.
asic.id
=======
ASIC design identifier.
asic.rev
========
ASIC design revision.
board.manufacture
=================
An identifier of the company or the facility which produced the part.
fw
==
Overall firmware version, often representing the collection of
fw.mgmt, fw.app, etc.
fw.mgmt
=======
Control unit firmware version. This firmware is responsible for house
keeping tasks, PHY control etc. but not the packet-by-packet data path
operation.
fw.app
======
Data path microcode controlling high-speed packet processing.
fw.undi
=======
UNDI software, may include the UEFI driver, firmware or both.
fw.ncsi
=======
Version of the software responsible for supporting/handling the
Network Controller Sideband Interface.
fw.psid
=======
Unique identifier of the firmware parameter set.

View File

@ -1,18 +0,0 @@
enable_sriov [DEVICE, GENERIC]
Configuration mode: Permanent
ignore_ari [DEVICE, GENERIC]
Configuration mode: Permanent
msix_vec_per_pf_max [DEVICE, GENERIC]
Configuration mode: Permanent
msix_vec_per_pf_min [DEVICE, GENERIC]
Configuration mode: Permanent
gre_ver_check [DEVICE, DRIVER-SPECIFIC]
Generic Routing Encapsulation (GRE) version check will
be enabled in the device. If disabled, device skips
version checking for incoming packets.
Type: Boolean
Configuration mode: Permanent

View File

@ -1,17 +0,0 @@
flow_steering_mode [DEVICE, DRIVER-SPECIFIC]
Controls the flow steering mode of the driver.
Two modes are supported:
1. 'dmfs' - Device managed flow steering.
2. 'smfs - Software/Driver managed flow steering.
In DMFS mode, the HW steering entities are created and
managed through the Firmware.
In SMFS mode, the HW steering entities are created and
managed though by the driver directly into Hardware
without firmware intervention.
Type: String
Configuration mode: runtime
enable_roce [DEVICE, GENERIC]
Enable handling of RoCE traffic in the device.
Defaultly enabled.
Configuration mode: driverinit

View File

@ -1,10 +0,0 @@
fw_load_policy [DEVICE, GENERIC]
Configuration mode: driverinit
acl_region_rehash_interval [DEVICE, DRIVER-SPECIFIC]
Sets an interval for periodic ACL region rehashes.
The value is in milliseconds, minimal value is "3000".
Value "0" disables the periodic work.
The first rehash will be run right after value is set.
Type: u32
Configuration mode: runtime

View File

@ -1,7 +0,0 @@
ATU_hash [DEVICE, DRIVER-SPECIFIC]
Select one of four possible hashing algorithms for
MAC addresses in the Address Translation Unit.
A value of 3 seems to work better than the default of
1 when many MAC addresses have the same OUI.
Configuration mode: runtime
Type: u8. 0-3 valid.

View File

@ -1,5 +0,0 @@
fw_load_policy [DEVICE, GENERIC]
Configuration mode: permanent
reset_dev_on_drv_probe [DEVICE, GENERIC]
Configuration mode: permanent

View File

@ -1,10 +0,0 @@
ale_bypass [DEVICE, DRIVER-SPECIFIC]
Allows to enable ALE_CONTROL(4).BYPASS mode for debug purposes.
All packets will be sent to the Host port only if enabled.
Type: bool
Configuration mode: runtime
switch_mode [DEVICE, DRIVER-SPECIFIC]
Enable switch mode
Type: bool
Configuration mode: runtime

View File

@ -1,71 +0,0 @@
Devlink configuration parameters
================================
Following is the list of configuration parameters via devlink interface.
Each parameter can be generic or driver specific and are device level
parameters.
Note that the driver-specific files should contain the generic params
they support to, with supported config modes.
Each parameter can be set in different configuration modes:
runtime - set while driver is running, no reset required.
driverinit - applied while driver initializes, requires restart
driver by devlink reload command.
permanent - written to device's non-volatile memory, hard reset
required.
Following is the list of parameters:
====================================
enable_sriov [DEVICE, GENERIC]
Enable Single Root I/O Virtualisation (SRIOV) in
the device.
Type: Boolean
ignore_ari [DEVICE, GENERIC]
Ignore Alternative Routing-ID Interpretation (ARI)
capability. If enabled, adapter will ignore ARI
capability even when platforms has the support
enabled and creates same number of partitions when
platform does not support ARI.
Type: Boolean
msix_vec_per_pf_max [DEVICE, GENERIC]
Provides the maximum number of MSIX interrupts that
a device can create. Value is same across all
physical functions (PFs) in the device.
Type: u32
msix_vec_per_pf_min [DEVICE, GENERIC]
Provides the minimum number of MSIX interrupts required
for the device initialization. Value is same across all
physical functions (PFs) in the device.
Type: u32
fw_load_policy [DEVICE, GENERIC]
Controls the device's firmware loading policy.
Valid values:
* DEVLINK_PARAM_FW_LOAD_POLICY_VALUE_DRIVER (0)
Load firmware version preferred by the driver.
* DEVLINK_PARAM_FW_LOAD_POLICY_VALUE_FLASH (1)
Load firmware currently stored in flash.
* DEVLINK_PARAM_FW_LOAD_POLICY_VALUE_DISK (2)
Load firmware currently available on host's disk.
Type: u8
reset_dev_on_drv_probe [DEVICE, GENERIC]
Controls the device's reset policy on driver probe.
Valid values:
* DEVLINK_PARAM_RESET_DEV_ON_DRV_PROBE_VALUE_UNKNOWN (0)
Unknown or invalid value.
* DEVLINK_PARAM_RESET_DEV_ON_DRV_PROBE_VALUE_ALWAYS (1)
Always reset device on driver probe.
* DEVLINK_PARAM_RESET_DEV_ON_DRV_PROBE_VALUE_NEVER (2)
Never reset device on driver probe.
* DEVLINK_PARAM_RESET_DEV_ON_DRV_PROBE_VALUE_DISK (3)
Reset only if device firmware can be found in the
filesystem.
Type: u8
enable_roce [DEVICE, GENERIC]
Enable handling of RoCE traffic in the device.
Type: Boolean

View File

@ -1,20 +0,0 @@
.. SPDX-License-Identifier: GPL-2.0
======================
Devlink Trap netdevsim
======================
Driver-specific Traps
=====================
.. list-table:: List of Driver-specific Traps Registered by ``netdevsim``
:widths: 5 5 90
* - Name
- Type
- Description
* - ``fid_miss``
- ``exception``
- When a packet enters the device it is classified to a filtering
indentifier (FID) based on the ingress port and VLAN. This trap is used
to trap packets for which a FID could not be found

View File

@ -0,0 +1,74 @@
.. SPDX-License-Identifier: GPL-2.0
====================
bnxt devlink support
====================
This document describes the devlink features implemented by the ``bnxt``
device driver.
Parameters
==========
.. list-table:: Generic parameters implemented
* - Name
- Mode
* - ``enable_sriov``
- Permanent
* - ``ignore_ari``
- Permanent
* - ``msix_vec_per_pf_max``
- Permanent
* - ``msix_vec_per_pf_min``
- Permanent
The ``bnxt`` driver also implements the following driver-specific
parameters.
.. list-table:: Driver-specific parameters implemented
:widths: 5 5 5 85
* - Name
- Type
- Mode
- Description
* - ``gre_ver_check``
- Boolean
- Permanent
- Generic Routing Encapsulation (GRE) version check will be enabled in
the device. If disabled, the device will skip the version check for
incoming packets.
Info versions
=============
The ``bnxt_en`` driver reports the following versions
.. list-table:: devlink info versions implemented
:widths: 5 5 90
* - Name
- Type
- Description
* - ``asic.id``
- fixed
- ASIC design identifier
* - ``asic.rev``
- fixed
- ASIC design revision
* - ``fw.psid``
- stored, running
- Firmware parameter set version of the board
* - ``fw``
- stored, running
- Overall board firmware version
* - ``fw.app``
- stored, running
- Data path firmware version
* - ``fw.mgmt``
- stored, running
- Management firmware version
* - ``fw.roce``
- stored, running
- RoCE management firmware version

View File

@ -0,0 +1,252 @@
.. SPDX-License-Identifier: GPL-2.0
=============
Devlink DPIPE
=============
Background
==========
While performing the hardware offloading process, much of the hardware
specifics cannot be presented. These details are useful for debugging, and
``devlink-dpipe`` provides a standardized way to provide visibility into the
offloading process.
For example, the routing longest prefix match (LPM) algorithm used by the
Linux kernel may differ from the hardware implementation. The pipeline debug
API (DPIPE) is aimed at providing the user visibility into the ASIC's
pipeline in a generic way.
The hardware offload process is expected to be done in a way that the user
should not be able to distinguish between the hardware vs. software
implementation. In this process, hardware specifics are neglected. In
reality those details can have lots of meaning and should be exposed in some
standard way.
This problem is made even more complex when one wishes to offload the
control path of the whole networking stack to a switch ASIC. Due to
differences in the hardware and software models some processes cannot be
represented correctly.
One example is the kernel's LPM algorithm which in many cases differs
greatly to the hardware implementation. The configuration API is the same,
but one cannot rely on the Forward Information Base (FIB) to look like the
Level Path Compression trie (LPC-trie) in hardware.
In many situations trying to analyze systems failure solely based on the
kernel's dump may not be enough. By combining this data with complementary
information about the underlying hardware, this debugging can be made
easier; additionally, the information can be useful when debugging
performance issues.
Overview
========
The ``devlink-dpipe`` interface closes this gap. The hardware's pipeline is
modeled as a graph of match/action tables. Each table represents a specific
hardware block. This model is not new, first being used by the P4 language.
Traditionally it has been used as an alternative model for hardware
configuration, but the ``devlink-dpipe`` interface uses it for visibility
purposes as a standard complementary tool. The system's view from
``devlink-dpipe`` should change according to the changes done by the
standard configuration tools.
For example, its quiet common to implement Access Control Lists (ACL)
using Ternary Content Addressable Memory (TCAM). The TCAM memory can be
divided into TCAM regions. Complex TC filters can have multiple rules with
different priorities and different lookup keys. On the other hand hardware
TCAM regions have a predefined lookup key. Offloading the TC filter rules
using TCAM engine can result in multiple TCAM regions being interconnected
in a chain (which may affect the data path latency). In response to a new TC
filter new tables should be created describing those regions.
Model
=====
The ``DPIPE`` model introduces several objects:
* headers
* tables
* entries
A ``header`` describes packet formats and provides names for fields within
the packet. A ``table`` describes hardware blocks. An ``entry`` describes
the actual content of a specific table.
The hardware pipeline is not port specific, but rather describes the whole
ASIC. Thus it is tied to the top of the ``devlink`` infrastructure.
Drivers can register and unregister tables at run time, in order to support
dynamic behavior. This dynamic behavior is mandatory for describing hardware
blocks like TCAM regions which can be allocated and freed dynamically.
``devlink-dpipe`` generally is not intended for configuration. The exception
is hardware counting for a specific table.
The following commands are used to obtain the ``dpipe`` objects from
userspace:
* ``table_get``: Receive a table's description.
* ``headers_get``: Receive a device's supported headers.
* ``entries_get``: Receive a table's current entries.
* ``counters_set``: Enable or disable counters on a table.
Table
-----
The driver should implement the following operations for each table:
* ``matches_dump``: Dump the supported matches.
* ``actions_dump``: Dump the supported actions.
* ``entries_dump``: Dump the actual content of the table.
* ``counters_set_update``: Synchronize hardware with counters enabled or
disabled.
Header/Field
------------
In a similar way to P4 headers and fields are used to describe a table's
behavior. There is a slight difference between the standard protocol headers
and specific ASIC metadata. The protocol headers should be declared in the
``devlink`` core API. On the other hand ASIC meta data is driver specific
and should be defined in the driver. Additionally, each driver-specific
devlink documentation file should document the driver-specific ``dpipe``
headers it implements. The headers and fields are identified by enumeration.
In order to provide further visibility some ASIC metadata fields could be
mapped to kernel objects. For example, internal router interface indexes can
be directly mapped to the net device ifindex. FIB table indexes used by
different Virtual Routing and Forwarding (VRF) tables can be mapped to
internal routing table indexes.
Match
-----
Matches are kept primitive and close to hardware operation. Match types like
LPM are not supported due to the fact that this is exactly a process we wish
to describe in full detail. Example of matches:
* ``field_exact``: Exact match on a specific field.
* ``field_exact_mask``: Exact match on a specific field after masking.
* ``field_range``: Match on a specific range.
The id's of the header and the field should be specified in order to
identify the specific field. Furthermore, the header index should be
specified in order to distinguish multiple headers of the same type in a
packet (tunneling).
Action
------
Similar to match, the actions are kept primitive and close to hardware
operation. For example:
* ``field_modify``: Modify the field value.
* ``field_inc``: Increment the field value.
* ``push_header``: Add a header.
* ``pop_header``: Remove a header.
Entry
-----
Entries of a specific table can be dumped on demand. Each eentry is
identified with an index and its properties are described by a list of
match/action values and specific counter. By dumping the tables content the
interactions between tables can be resolved.
Abstraction Example
===================
The following is an example of the abstraction model of the L3 part of
Mellanox Spectrum ASIC. The blocks are described in the order they appear in
the pipeline. The table sizes in the following examples are not real
hardware sizes and are provided for demonstration purposes.
LPM
---
The LPM algorithm can be implemented as a list of hash tables. Each hash
table contains routes with the same prefix length. The root of the list is
/32, and in case of a miss the hardware will continue to the next hash
table. The depth of the search will affect the data path latency.
In case of a hit the entry contains information about the next stage of the
pipeline which resolves the MAC address. The next stage can be either local
host table for directly connected routes, or adjacency table for next-hops.
The ``meta.lpm_prefix`` field is used to connect two LPM tables.
.. code::
table lpm_prefix_16 {
size: 4096,
counters_enabled: true,
match: { meta.vr_id: exact,
ipv4.dst_addr: exact_mask,
ipv6.dst_addr: exact_mask,
meta.lpm_prefix: exact },
action: { meta.adj_index: set,
meta.adj_group_size: set,
meta.rif_port: set,
meta.lpm_prefix: set },
}
Local Host
----------
In the case of local routes the LPM lookup already resolves the egress
router interface (RIF), yet the exact MAC address is not known. The local
host table is a hash table combining the output interface id with
destination IP address as a key. The result is the MAC address.
.. code::
table local_host {
size: 4096,
counters_enabled: true,
match: { meta.rif_port: exact,
ipv4.dst_addr: exact},
action: { ethernet.daddr: set }
}
Adjacency
---------
In case of remote routes this table does the ECMP. The LPM lookup results in
ECMP group size and index that serves as a global offset into this table.
Concurrently a hash of the packet is generated. Based on the ECMP group size
and the packet's hash a local offset is generated. Multiple LPM entries can
point to the same adjacency group.
.. code::
table adjacency {
size: 4096,
counters_enabled: true,
match: { meta.adj_index: exact,
meta.adj_group_size: exact,
meta.packet_hash_index: exact },
action: { ethernet.daddr: set,
meta.erif: set }
}
ERIF
----
In case the egress RIF and destination MAC have been resolved by previous
tables this table does multiple operations like TTL decrease and MTU check.
Then the decision of forward/drop is taken and the port L3 statistics are
updated based on the packet's type (broadcast, unicast, multicast).
.. code::
table erif {
size: 800,
counters_enabled: true,
match: { meta.rif_port: exact,
meta.is_l3_unicast: exact,
meta.is_l3_broadcast: exact,
meta.is_l3_multicast, exact },
action: { meta.l3_drop: set,
meta.l3_forward: set }
}

View File

@ -0,0 +1,114 @@
.. SPDX-License-Identifier: GPL-2.0
==============
Devlink Health
==============
Background
==========
The ``devlink`` health mechanism is targeted for Real Time Alerting, in
order to know when something bad happened to a PCI device.
* Provide alert debug information.
* Self healing.
* If problem needs vendor support, provide a way to gather all needed
debugging information.
Overview
========
The main idea is to unify and centralize driver health reports in the
generic ``devlink`` instance and allow the user to set different
attributes of the health reporting and recovery procedures.
The ``devlink`` health reporter:
Device driver creates a "health reporter" per each error/health type.
Error/Health type can be a known/generic (eg pci error, fw error, rx/tx error)
or unknown (driver specific).
For each registered health reporter a driver can issue error/health reports
asynchronously. All health reports handling is done by ``devlink``.
Device driver can provide specific callbacks for each "health reporter", e.g.:
* Recovery procedures
* Diagnostics procedures
* Object dump procedures
* OOB initial parameters
Different parts of the driver can register different types of health reporters
with different handlers.
Actions
=======
Once an error is reported, devlink health will perform the following actions:
* A log is being send to the kernel trace events buffer
* Health status and statistics are being updated for the reporter instance
* Object dump is being taken and saved at the reporter instance (as long as
there is no other dump which is already stored)
* Auto recovery attempt is being done. Depends on:
- Auto-recovery configuration
- Grace period vs. time passed since last recover
User Interface
==============
User can access/change each reporter's parameters and driver specific callbacks
via ``devlink``, e.g per error type (per health reporter):
* Configure reporter's generic parameters (like: disable/enable auto recovery)
* Invoke recovery procedure
* Run diagnostics
* Object dump
.. list-table:: List of devlink health interfaces
:widths: 10 90
* - Name
- Description
* - ``DEVLINK_CMD_HEALTH_REPORTER_GET``
- Retrieves status and configuration info per DEV and reporter.
* - ``DEVLINK_CMD_HEALTH_REPORTER_SET``
- Allows reporter-related configuration setting.
* - ``DEVLINK_CMD_HEALTH_REPORTER_RECOVER``
- Triggers a reporter's recovery procedure.
* - ``DEVLINK_CMD_HEALTH_REPORTER_DIAGNOSE``
- Retrieves diagnostics data from a reporter on a device.
* - ``DEVLINK_CMD_HEALTH_REPORTER_DUMP_GET``
- Retrieves the last stored dump. Devlink health
saves a single dump. If an dump is not already stored by the devlink
for this reporter, devlink generates a new dump.
dump output is defined by the reporter.
* - ``DEVLINK_CMD_HEALTH_REPORTER_DUMP_CLEAR``
- Clears the last saved dump file for the specified reporter.
The following diagram provides a general overview of ``devlink-health``::
netlink
+--------------------------+
| |
| + |
| | |
+--------------------------+
|request for ops
|(diagnose,
mlx5_core devlink |recover,
|dump)
+--------+ +--------------------------+
| | | reporter| |
| | | +---------v----------+ |
| | ops execution | | | |
| <----------------------------------+ | |
| | | | | |
| | | + ^------------------+ |
| | | | request for ops |
| | | | (recover, dump) |
| | | | |
| | | +-+------------------+ |
| | health report | | health handler | |
| +-------------------------------> | |
| | | +--------------------+ |
| | health reporter create | |
| +----------------------------> |
+--------+ +--------------------------+

View File

@ -0,0 +1,100 @@
.. SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
============
Devlink Info
============
The ``devlink-info`` mechanism enables device drivers to report device
information in a generic fashion. It is extensible, and enables exporting
even device or driver specific information.
devlink supports representing the following types of versions
.. list-table:: List of version types
:widths: 5 95
* - Type
- Description
* - ``fixed``
- Represents fixed versions, which cannot change. For example,
component identifiers or the board version reported in the PCI VPD.
* - ``running``
- Represents the version of the currently running component. For
example the running version of firmware. These versions generally
only update after a reboot.
* - ``stored``
- Represents the version of a component as stored, such as after a
flash update. Stored values should update to reflect changes in the
flash even if a reboot has not yet occurred.
Generic Versions
================
It is expected that drivers use the following generic names for exporting
version information. Other information may be exposed using driver-specific
names, but these should be documented in the driver-specific file.
board.id
--------
Unique identifier of the board design.
board.rev
---------
Board design revision.
asic.id
-------
ASIC design identifier.
asic.rev
--------
ASIC design revision.
board.manufacture
-----------------
An identifier of the company or the facility which produced the part.
fw
--
Overall firmware version, often representing the collection of
fw.mgmt, fw.app, etc.
fw.mgmt
-------
Control unit firmware version. This firmware is responsible for house
keeping tasks, PHY control etc. but not the packet-by-packet data path
operation.
fw.app
------
Data path microcode controlling high-speed packet processing.
fw.undi
-------
UNDI software, may include the UEFI driver, firmware or both.
fw.ncsi
-------
Version of the software responsible for supporting/handling the
Network Controller Sideband Interface.
fw.psid
-------
Unique identifier of the firmware parameter set.
fw.roce
-------
RoCE firmware version which is responsible for handling roce
management.

View File

@ -0,0 +1,108 @@
.. SPDX-License-Identifier: GPL-2.0
==============
Devlink Params
==============
``devlink`` provides capability for a driver to expose device parameters for low
level device functionality. Since devlink can operate at the device-wide
level, it can be used to provide configuration that may affect multiple
ports on a single device.
This document describes a number of generic parameters that are supported
across multiple drivers. Each driver is also free to add their own
parameters. Each driver must document the specific parameters they support,
whether generic or not.
Configuration modes
===================
Parameters may be set in different configuration modes.
.. list-table:: Possible configuration modes
:widths: 5 90
* - Name
- Description
* - ``runtime``
- set while the driver is running, and takes effect immediately. No
reset is required.
* - ``driverinit``
- applied while the driver initializes. Requires the user to restart
the driver using the ``devlink`` reload command.
* - ``permanent``
- written to the device's non-volatile memory. A hard reset is required
for it to take effect.
Reloading
---------
In order for ``driverinit`` parameters to take effect, the driver must
support reloading via the ``devlink-reload`` command. This command will
request a reload of the device driver.
Generic configuration parameters
================================
The following is a list of generic configuration parameters that drivers may
add. Use of generic parameters is preferred over each driver creating their
own name.
.. list-table:: List of generic parameters
:widths: 5 5 90
* - Name
- Type
- Description
* - ``enable_sriov``
- Boolean
- Enable Single Root I/O Virtualization (SRIOV) in the device.
* - ``ignore_ari``
- Boolean
- Ignore Alternative Routing-ID Interpretation (ARI) capability. If
enabled, the adapter will ignore ARI capability even when the
platform has support enabled. The device will create the same number
of partitions as when the platform does not support ARI.
* - ``msix_vec_per_pf_max``
- u32
- Provides the maximum number of MSI-X interrupts that a device can
create. Value is the same across all physical functions (PFs) in the
device.
* - ``msix_vec_per_pf_min``
- u32
- Provides the minimum number of MSI-X interrupts required for the
device to initialize. Value is the same across all physical functions
(PFs) in the device.
* - ``fw_load_policy``
- u8
- Control the device's firmware loading policy.
- ``DEVLINK_PARAM_FW_LOAD_POLICY_VALUE_DRIVER`` (0)
Load firmware version preferred by the driver.
- ``DEVLINK_PARAM_FW_LOAD_POLICY_VALUE_FLASH`` (1)
Load firmware currently stored in flash.
- ``DEVLINK_PARAM_FW_LOAD_POLICY_VALUE_DISK`` (2)
Load firmware currently available on host's disk.
* - ``reset_dev_on_drv_probe``
- u8
- Controls the device's reset policy on driver probe.
- ``DEVLINK_PARAM_RESET_DEV_ON_DRV_PROBE_VALUE_UNKNOWN`` (0)
Unknown or invalid value.
- ``DEVLINK_PARAM_RESET_DEV_ON_DRV_PROBE_VALUE_ALWAYS`` (1)
Always reset device on driver probe.
- ``DEVLINK_PARAM_RESET_DEV_ON_DRV_PROBE_VALUE_NEVER`` (2)
Never reset device on driver probe.
- ``DEVLINK_PARAM_RESET_DEV_ON_DRV_PROBE_VALUE_DISK`` (3)
Reset the device only if firmware can be found in the filesystem.
* - ``enable_roce``
- Boolean
- Enable handling of RoCE traffic in the device.
* - ``internal_err_reset``
- Boolean
- When enabled, the device driver will reset the device on internal
errors.
* - ``max_macs``
- u32
- Specifies the maximum number of MAC addresses per ethernet port of
this device.
* - ``region_snapshot_enable``
- Boolean
- Enable capture of ``devlink-region`` snapshots.

View File

@ -0,0 +1,60 @@
.. SPDX-License-Identifier: GPL-2.0
==============
Devlink Region
==============
``devlink`` regions enable access to driver defined address regions using
devlink.
Each device can create and register its own supported address regions. The
region can then be accessed via the devlink region interface.
Region snapshots are collected by the driver, and can be accessed via read
or dump commands. This allows future analysis on the created snapshots.
Regions may optionally support triggering snapshots on demand.
The major benefit to creating a region is to provide access to internal
address regions that are otherwise inaccessible to the user.
Regions may also be used to provide an additional way to debug complex error
states, but see also :doc:`devlink-health`
example usage
-------------
.. code:: shell
$ devlink region help
$ devlink region show [ DEV/REGION ]
$ devlink region del DEV/REGION snapshot SNAPSHOT_ID
$ devlink region dump DEV/REGION [ snapshot SNAPSHOT_ID ]
$ devlink region read DEV/REGION [ snapshot SNAPSHOT_ID ]
address ADDRESS length length
# Show all of the exposed regions with region sizes:
$ devlink region show
pci/0000:00:05.0/cr-space: size 1048576 snapshot [1 2]
pci/0000:00:05.0/fw-health: size 64 snapshot [1 2]
# Delete a snapshot using:
$ devlink region del pci/0000:00:05.0/cr-space snapshot 1
# Trigger (request) a snapshot be taken:
$ devlink region trigger pci/0000:00:05.0/cr-space
# Dump a snapshot:
$ devlink region dump pci/0000:00:05.0/fw-health snapshot 1
0000000000000000 0014 95dc 0014 9514 0035 1670 0034 db30
0000000000000010 0000 0000 ffff ff04 0029 8c00 0028 8cc8
0000000000000020 0016 0bb8 0016 1720 0000 0000 c00f 3ffc
0000000000000030 bada cce5 bada cce5 bada cce5 bada cce5
# Read a specific part of a snapshot:
$ devlink region read pci/0000:00:05.0/fw-health snapshot 1 address 0
length 16
0000000000000000 0014 95dc 0014 9514 0035 1670 0034 db30
As regions are likely very device or driver specific, no generic regions are
defined. See the driver-specific documentation files for information on the
specific regions a driver supports.

View File

@ -0,0 +1,62 @@
.. SPDX-License-Identifier: GPL-2.0
================
Devlink Resource
================
``devlink`` provides the ability for drivers to register resources, which
can allow administrators to see the device restrictions for a given
resource, as well as how much of the given resource is currently
in use. Additionally, these resources can optionally have configurable size.
This could enable the administrator to limit the number of resources that
are used.
For example, the ``netdevsim`` driver enables ``/IPv4/fib`` and
``/IPv4/fib-rules`` as resources to limit the number of IPv4 FIB entries and
rules for a given device.
Resource Ids
============
Each resource is represented by an id, and contains information about its
current size and related sub resources. To access a sub resource, you
specify the path of the resource. For example ``/IPv4/fib`` is the id for
the ``fib`` sub-resource under the ``IPv4`` resource.
example usage
-------------
The resources exposed by the driver can be observed, for example:
.. code:: shell
$devlink resource show pci/0000:03:00.0
pci/0000:03:00.0:
name kvd size 245760 unit entry
resources:
name linear size 98304 occ 0 unit entry size_min 0 size_max 147456 size_gran 128
name hash_double size 60416 unit entry size_min 32768 size_max 180224 size_gran 128
name hash_single size 87040 unit entry size_min 65536 size_max 212992 size_gran 128
Some resource's size can be changed. Examples:
.. code:: shell
$devlink resource set pci/0000:03:00.0 path /kvd/hash_single size 73088
$devlink resource set pci/0000:03:00.0 path /kvd/hash_double size 74368
The changes do not apply immediately, this can be validated by the 'size_new'
attribute, which represents the pending change in size. For example:
.. code:: shell
$devlink resource show pci/0000:03:00.0
pci/0000:03:00.0:
name kvd size 245760 unit entry size_valid false
resources:
name linear size 98304 size_new 147456 occ 0 unit entry size_min 0 size_max 147456 size_gran 128
name hash_double size 60416 unit entry size_min 32768 size_max 180224 size_gran 128
name hash_single size 87040 unit entry size_min 65536 size_max 212992 size_gran 128
Note that changes in resource size may require a device reload to properly
take effect.

View File

@ -223,6 +223,21 @@ be added to the following table:
* - ``ipv6_lpm_miss``
- ``exception``
- Traps unicast IPv6 packets that did not match any route
* - ``non_routable_packet``
- ``drop``
- Traps packets that the device decided to drop because they are not
supposed to be routed. For example, IGMP queries can be flooded by the
device in layer 2 and reach the router. Such packets should not be
routed and instead dropped
* - ``decap_error``
- ``exception``
- Traps NVE and IPinIP packets that the device decided to drop because of
failure during decapsulation (e.g., packet being too short, reserved
bits set in VXLAN header)
* - ``overlay_smac_is_mc``
- ``drop``
- Traps NVE packets that the device decided to drop because their overlay
source MAC is multicast
Driver-specific Packet Traps
============================
@ -233,7 +248,8 @@ help debug packet drops caused by these exceptions. The following list includes
links to the description of driver-specific traps registered by various device
drivers:
* :doc:`devlink-trap-netdevsim`
* :doc:`netdevsim`
* :doc:`mlxsw`
Generic Packet Trap Groups
==========================
@ -258,6 +274,9 @@ narrow. The description of these groups must be added to the following table:
* - ``buffer_drops``
- Contains packet traps for packets that were dropped by the device due to
an enqueue decision
* - ``tunnel_drops``
- Contains packet traps for packets that were dropped by the device during
tunnel encapsulation / decapsulation
Testing
=======

View File

@ -0,0 +1,42 @@
Linux Devlink Documentation
===========================
devlink is an API to expose device information and resources not directly
related to any device class, such as chip-wide/switch-ASIC-wide configuration.
Interface documentation
-----------------------
The following pages describe various interfaces available through devlink in
general.
.. toctree::
:maxdepth: 1
devlink-dpipe
devlink-health
devlink-info
devlink-params
devlink-region
devlink-resource
devlink-trap
Driver-specific documentation
-----------------------------
Each driver that implements ``devlink`` is expected to document what
parameters, info versions, and other features it supports.
.. toctree::
:maxdepth: 1
bnxt
ionic
mlx4
mlx5
mlxsw
mv88e6xxx
netdevsim
nfp
qed
ti-cpsw-switch

View File

@ -0,0 +1,29 @@
.. SPDX-License-Identifier: GPL-2.0
=====================
ionic devlink support
=====================
This document describes the devlink features implemented by the ``ionic``
device driver.
Info versions
=============
The ``ionic`` driver reports the following versions
.. list-table:: devlink info versions implemented
:widths: 5 5 90
* - Name
- Type
- Description
* - ``fw``
- running
- Version of firmware running on the device
* - ``asic.id``
- fixed
- The ASIC type for this device
* - ``asic.rev``
- fixed
- The revision of the ASIC for this device

View File

@ -0,0 +1,56 @@
.. SPDX-License-Identifier: GPL-2.0
====================
mlx4 devlink support
====================
This document describes the devlink features implemented by the ``mlx4``
device driver.
Parameters
==========
.. list-table:: Generic parameters implemented
* - Name
- Mode
* - ``internal_err_reset``
- driverinit, runtime
* - ``max_macs``
- driverinit
* - ``region_snapshot_enable``
- driverinit, runtime
The ``mlx4`` driver also implements the following driver-specific
parameters.
.. list-table:: Driver-specific parameters implemented
:widths: 5 5 5 85
* - Name
- Type
- Mode
- Description
* - ``enable_64b_cqe_eqe``
- Boolean
- driverinit
- Enable 64 byte CQEs/EQEs, if the FW supports it.
* - ``enable_4k_uar``
- Boolean
- driverinit
- Enable using the 4k UAR.
The ``mlx4`` driver supports reloading via ``DEVLINK_CMD_RELOAD``
Regions
=======
The ``mlx4`` driver supports dumping the firmware PCI crspace and health
buffer during a critical firmware issue.
In case a firmware command times out, firmware getting stuck, or a non zero
value on the catastrophic buffer, a snapshot will be taken by the driver.
The ``cr-space`` region will contain the firmware PCI crspace contents. The
``fw-health`` region will contain the device firmware's health buffer.
Snapshots for both of these regions are taken on the same event triggers.

View File

@ -0,0 +1,59 @@
.. SPDX-License-Identifier: GPL-2.0
====================
mlx5 devlink support
====================
This document describes the devlink features implemented by the ``mlx5``
device driver.
Parameters
==========
.. list-table:: Generic parameters implemented
* - Name
- Mode
* - ``enable_roce``
- driverinit
The ``mlx5`` driver also implements the following driver-specific
parameters.
.. list-table:: Driver-specific parameters implemented
:widths: 5 5 5 85
* - Name
- Type
- Mode
- Description
* - ``flow_steering_mode``
- string
- runtime
- Controls the flow steering mode of the driver
* ``dmfs`` Device managed flow steering. In DMFS mode, the HW
steering entities are created and managed through firmware.
* ``smfs`` Software managed flow steering. In SMFS mode, the HW
steering entities are created and manage through the driver without
firmware intervention.
The ``mlx5`` driver supports reloading via ``DEVLINK_CMD_RELOAD``
Info versions
=============
The ``mlx5`` driver reports the following versions
.. list-table:: devlink info versions implemented
:widths: 5 5 90
* - Name
- Type
- Description
* - ``fw.psid``
- fixed
- Used to represent the board id of the device.
* - ``fw.version``
- stored, running
- Three digit major.minor.subminor firmware version number.

View File

@ -0,0 +1,81 @@
.. SPDX-License-Identifier: GPL-2.0
=====================
mlxsw devlink support
=====================
This document describes the devlink features implemented by the ``mlxsw``
device driver.
Parameters
==========
.. list-table:: Generic parameters implemented
* - Name
- Mode
* - ``fw_load_policy``
- driverinit
The ``mlxsw`` driver also implements the following driver-specific
parameters.
.. list-table:: Driver-specific parameters implemented
:widths: 5 5 5 85
* - Name
- Type
- Mode
- Description
* - ``acl_region_rehash_interval``
- u32
- runtime
- Sets an interval for periodic ACL region rehashes. The value is
specified in milliseconds, with a minimum of ``3000``. The value of
``0`` disables periodic work entirely. The first rehash will be run
immediately after the value is set.
The ``mlxsw`` driver supports reloading via ``DEVLINK_CMD_RELOAD``
Info versions
=============
The ``mlxsw`` driver reports the following versions
.. list-table:: devlink info versions implemented
:widths: 5 5 90
* - Name
- Type
- Description
* - ``hw.revision``
- fixed
- The hardware revision for this board
* - ``fw.psid``
- fixed
- Firmware PSID
* - ``fw.version``
- running
- Three digit firmware version
Driver-specific Traps
=====================
.. list-table:: List of Driver-specific Traps Registered by ``mlxsw``
:widths: 5 5 90
* - Name
- Type
- Description
* - ``irif_disabled``
- ``drop``
- Traps packets that the device decided to drop because they need to be
routed from a disabled router interface (RIF). This can happen during
RIF dismantle, when the RIF is first disabled before being removed
completely
* - ``erif_disabled``
- ``drop``
- Traps packets that the device decided to drop because they need to be
routed through a disabled router interface (RIF). This can happen during
RIF dismantle, when the RIF is first disabled before being removed
completely

View File

@ -0,0 +1,28 @@
.. SPDX-License-Identifier: GPL-2.0
=========================
mv88e6xxx devlink support
=========================
This document describes the devlink features implemented by the ``mv88e6xxx``
device driver.
Parameters
==========
The ``mv88e6xxx`` driver implements the following driver-specific parameters.
.. list-table:: Driver-specific parameters implemented
:widths: 5 5 5 85
* - Name
- Type
- Mode
- Description
* - ``ATU_hash``
- u8
- runtime
- Select one of four possible hashing algorithms for MAC addresses in
the Address Translation Unit. A value of 3 may work better than the
default of 1 when many MAC addresses have the same OUI. Only the
values 0 to 3 are valid for this parameter.

View File

@ -0,0 +1,72 @@
.. SPDX-License-Identifier: GPL-2.0
=========================
netdevsim devlink support
=========================
This document describes the ``devlink`` features supported by the
``netdevsim`` device driver.
Parameters
==========
.. list-table:: Generic parameters implemented
* - Name
- Mode
* - ``max_macs``
- driverinit
The ``netdevsim`` driver also implements the following driver-specific
parameters.
.. list-table:: Driver-specific parameters implemented
:widths: 5 5 5 85
* - Name
- Type
- Mode
- Description
* - ``test1``
- Boolean
- driverinit
- Test parameter used to show how a driver-specific devlink parameter
can be implemented.
The ``netdevsim`` driver supports reloading via ``DEVLINK_CMD_RELOAD``
Regions
=======
The ``netdevsim`` driver exposes a ``dummy`` region as an example of how the
devlink-region interfaces work. A snapshot is taken whenever the
``take_snapshot`` debugfs file is written to.
Resources
=========
The ``netdevsim`` driver exposes resources to control the number of FIB
entries and FIB rule entries that the driver will allow.
.. code:: shell
$ devlink resource set netdevsim/netdevsim0 path /IPv4/fib size 96
$ devlink resource set netdevsim/netdevsim0 path /IPv4/fib-rules size 16
$ devlink resource set netdevsim/netdevsim0 path /IPv6/fib size 64
$ devlink resource set netdevsim/netdevsim0 path /IPv6/fib-rules size 16
$ devlink dev reload netdevsim/netdevsim0
Driver-specific Traps
=====================
.. list-table:: List of Driver-specific Traps Registered by ``netdevsim``
:widths: 5 5 90
* - Name
- Type
- Description
* - ``fid_miss``
- ``exception``
- When a packet enters the device it is classified to a filtering
indentifier (FID) based on the ingress port and VLAN. This trap is used
to trap packets for which a FID could not be found

View File

@ -0,0 +1,65 @@
.. SPDX-License-Identifier: GPL-2.0
===================
nfp devlink support
===================
This document describes the devlink features implemented by the ``nfp``
device driver.
Parameters
==========
.. list-table:: Generic parameters implemented
* - Name
- Mode
* - ``fw_load_policy``
- permanent
* - ``reset_dev_on_drv_probe``
- permanent
Info versions
=============
The ``nfp`` driver reports the following versions
.. list-table:: devlink info versions implemented
:widths: 5 5 90
* - Name
- Type
- Description
* - ``board.id``
- fixed
- Part number identifying the board design
* - ``board.rev``
- fixed
- Revision of the board design
* - ``board.manufacture``
- fixed
- Vendor of the board design
* - ``board.model``
- fixed
- Model name of the board design
* - ``fw.bundle_id``
- stored, running
- Firmware bundle id
* - ``fw.mgmt``
- stored, running
- Version of the management firmware
* - ``fw.cpld``
- stored, running
- The CPLD firmware component version
* - ``fw.app``
- stored, running
- The APP firmware component version
* - ``fw.undi``
- stored, running
- The UNDI firmware component version
* - ``fw.ncsi``
- stored, running
- The NSCI firmware component version
* - ``chip.init``
- stored, running
- The CFGR firmware component version

View File

@ -0,0 +1,26 @@
.. SPDX-License-Identifier: GPL-2.0
===================
qed devlink support
===================
This document describes the devlink features implemented by the ``qed`` core
device driver.
Parameters
==========
The ``qed`` driver implements the following driver-specific parameters.
.. list-table:: Driver-specific parameters implemented
:widths: 5 5 5 85
* - Name
- Type
- Mode
- Description
* - ``iwarp_cmt``
- Boolean
- runtime
- Enable iWARP functionality for 100g devices. Note that this impacts
L2 performance, and is therefore not enabled by default.

View File

@ -0,0 +1,31 @@
.. SPDX-License-Identifier: GPL-2.0
==============================
ti-cpsw-switch devlink support
==============================
This document describes the devlink features implemented by the ``ti-cpsw-switch``
device driver.
Parameters
==========
The ``ti-cpsw-switch`` driver implements the following driver-specific
parameters.
.. list-table:: Driver-specific parameters implemented
:widths: 5 5 5 85
* - Name
- Type
- Mode
- Description
* - ``ale_bypass``
- Boolean
- runtime
- Enables ALE_CONTROL(4).BYPASS mode for debugging purposes. In this
mode, all packets will be sent to the host port only.
* - ``switch_mode``
- Boolean
- runtime
- Enable switch mode

View File

@ -0,0 +1,618 @@
=============================
Netlink interface for ethtool
=============================
Basic information
=================
Netlink interface for ethtool uses generic netlink family ``ethtool``
(userspace application should use macros ``ETHTOOL_GENL_NAME`` and
``ETHTOOL_GENL_VERSION`` defined in ``<linux/ethtool_netlink.h>`` uapi
header). This family does not use a specific header, all information in
requests and replies is passed using netlink attributes.
The ethtool netlink interface uses extended ACK for error and warning
reporting, userspace application developers are encouraged to make these
messages available to user in a suitable way.
Requests can be divided into three categories: "get" (retrieving information),
"set" (setting parameters) and "action" (invoking an action).
All "set" and "action" type requests require admin privileges
(``CAP_NET_ADMIN`` in the namespace). Most "get" type requests are allowed for
anyone but there are exceptions (where the response contains sensitive
information). In some cases, the request as such is allowed for anyone but
unprivileged users have attributes with sensitive information (e.g.
wake-on-lan password) omitted.
Conventions
===========
Attributes which represent a boolean value usually use NLA_U8 type so that we
can distinguish three states: "on", "off" and "not present" (meaning the
information is not available in "get" requests or value is not to be changed
in "set" requests). For these attributes, the "true" value should be passed as
number 1 but any non-zero value should be understood as "true" by recipient.
In the tables below, "bool" denotes NLA_U8 attributes interpreted in this way.
In the message structure descriptions below, if an attribute name is suffixed
with "+", parent nest can contain multiple attributes of the same type. This
implements an array of entries.
Request header
==============
Each request or reply message contains a nested attribute with common header.
Structure of this header is
============================== ====== =============================
``ETHTOOL_A_HEADER_DEV_INDEX`` u32 device ifindex
``ETHTOOL_A_HEADER_DEV_NAME`` string device name
``ETHTOOL_A_HEADER_FLAGS`` u32 flags common for all requests
============================== ====== =============================
``ETHTOOL_A_HEADER_DEV_INDEX`` and ``ETHTOOL_A_HEADER_DEV_NAME`` identify the
device message relates to. One of them is sufficient in requests, if both are
used, they must identify the same device. Some requests, e.g. global string
sets, do not require device identification. Most ``GET`` requests also allow
dump requests without device identification to query the same information for
all devices providing it (each device in a separate message).
``ETHTOOL_A_HEADER_FLAGS`` is a bitmap of request flags common for all request
types. The interpretation of these flags is the same for all request types but
the flags may not apply to requests. Recognized flags are:
================================= ===================================
``ETHTOOL_FLAG_COMPACT_BITSETS`` use compact format bitsets in reply
``ETHTOOL_FLAG_OMIT_REPLY`` omit optional reply (_SET and _ACT)
================================= ===================================
New request flags should follow the general idea that if the flag is not set,
the behaviour is backward compatible, i.e. requests from old clients not aware
of the flag should be interpreted the way the client expects. A client must
not set flags it does not understand.
Bit sets
========
For short bitmaps of (reasonably) fixed length, standard ``NLA_BITFIELD32``
type is used. For arbitrary length bitmaps, ethtool netlink uses a nested
attribute with contents of one of two forms: compact (two binary bitmaps
representing bit values and mask of affected bits) and bit-by-bit (list of
bits identified by either index or name).
Verbose (bit-by-bit) bitsets allow sending symbolic names for bits together
with their values which saves a round trip (when the bitset is passed in a
request) or at least a second request (when the bitset is in a reply). This is
useful for one shot applications like traditional ethtool command. On the
other hand, long running applications like ethtool monitor (displaying
notifications) or network management daemons may prefer fetching the names
only once and using compact form to save message size. Notifications from
ethtool netlink interface always use compact form for bitsets.
A bitset can represent either a value/mask pair (``ETHTOOL_A_BITSET_NOMASK``
not set) or a single bitmap (``ETHTOOL_A_BITSET_NOMASK`` set). In requests
modifying a bitmap, the former changes the bit set in mask to values set in
value and preserves the rest; the latter sets the bits set in the bitmap and
clears the rest.
Compact form: nested (bitset) atrribute contents:
============================ ====== ============================
``ETHTOOL_A_BITSET_NOMASK`` flag no mask, only a list
``ETHTOOL_A_BITSET_SIZE`` u32 number of significant bits
``ETHTOOL_A_BITSET_VALUE`` binary bitmap of bit values
``ETHTOOL_A_BITSET_MASK`` binary bitmap of valid bits
============================ ====== ============================
Value and mask must have length at least ``ETHTOOL_A_BITSET_SIZE`` bits
rounded up to a multiple of 32 bits. They consist of 32-bit words in host byte
order, words ordered from least significant to most significant (i.e. the same
way as bitmaps are passed with ioctl interface).
For compact form, ``ETHTOOL_A_BITSET_SIZE`` and ``ETHTOOL_A_BITSET_VALUE`` are
mandatory. ``ETHTOOL_A_BITSET_MASK`` attribute is mandatory if
``ETHTOOL_A_BITSET_NOMASK`` is not set (bitset represents a value/mask pair);
if ``ETHTOOL_A_BITSET_NOMASK`` is not set, ``ETHTOOL_A_BITSET_MASK`` is not
allowed (bitset represents a single bitmap.
Kernel bit set length may differ from userspace length if older application is
used on newer kernel or vice versa. If userspace bitmap is longer, an error is
issued only if the request actually tries to set values of some bits not
recognized by kernel.
Bit-by-bit form: nested (bitset) attribute contents:
+------------------------------------+--------+-----------------------------+
| ``ETHTOOL_A_BITSET_NOMASK`` | flag | no mask, only a list |
+------------------------------------+--------+-----------------------------+
| ``ETHTOOL_A_BITSET_SIZE`` | u32 | number of significant bits |
+------------------------------------+--------+-----------------------------+
| ``ETHTOOL_A_BITSET_BITS`` | nested | array of bits |
+-+----------------------------------+--------+-----------------------------+
| | ``ETHTOOL_A_BITSET_BITS_BIT+`` | nested | one bit |
+-+-+--------------------------------+--------+-----------------------------+
| | | ``ETHTOOL_A_BITSET_BIT_INDEX`` | u32 | bit index (0 for LSB) |
+-+-+--------------------------------+--------+-----------------------------+
| | | ``ETHTOOL_A_BITSET_BIT_NAME`` | string | bit name |
+-+-+--------------------------------+--------+-----------------------------+
| | | ``ETHTOOL_A_BITSET_BIT_VALUE`` | flag | present if bit is set |
+-+-+--------------------------------+--------+-----------------------------+
Bit size is optional for bit-by-bit form. ``ETHTOOL_A_BITSET_BITS`` nest can
only contain ``ETHTOOL_A_BITSET_BITS_BIT`` attributes but there can be an
arbitrary number of them. A bit may be identified by its index or by its
name. When used in requests, listed bits are set to 0 or 1 according to
``ETHTOOL_A_BITSET_BIT_VALUE``, the rest is preserved. A request fails if
index exceeds kernel bit length or if name is not recognized.
When ``ETHTOOL_A_BITSET_NOMASK`` flag is present, bitset is interpreted as
a simple bitmap. ``ETHTOOL_A_BITSET_BIT_VALUE`` attributes are not used in
such case. Such bitset represents a bitmap with listed bits set and the rest
zero.
In requests, application can use either form. Form used by kernel in reply is
determined by ``ETHTOOL_FLAG_COMPACT_BITSETS`` flag in flags field of request
header. Semantics of value and mask depends on the attribute.
List of message types
=====================
All constants identifying message types use ``ETHTOOL_CMD_`` prefix and suffix
according to message purpose:
============== ======================================
``_GET`` userspace request to retrieve data
``_SET`` userspace request to set data
``_ACT`` userspace request to perform an action
``_GET_REPLY`` kernel reply to a ``GET`` request
``_SET_REPLY`` kernel reply to a ``SET`` request
``_ACT_REPLY`` kernel reply to an ``ACT`` request
``_NTF`` kernel notification
============== ======================================
Userspace to kernel:
===================================== ================================
``ETHTOOL_MSG_STRSET_GET`` get string set
``ETHTOOL_MSG_LINKINFO_GET`` get link settings
``ETHTOOL_MSG_LINKINFO_SET`` set link settings
``ETHTOOL_MSG_LINKMODES_GET`` get link modes info
``ETHTOOL_MSG_LINKMODES_SET`` set link modes info
``ETHTOOL_MSG_LINKSTATE_GET`` get link state
``ETHTOOL_MSG_DEBUG_GET`` get debugging settings
``ETHTOOL_MSG_DEBUG_SET`` set debugging settings
``ETHTOOL_MSG_WOL_GET`` get wake-on-lan settings
``ETHTOOL_MSG_WOL_SET`` set wake-on-lan settings
===================================== ================================
Kernel to userspace:
===================================== =================================
``ETHTOOL_MSG_STRSET_GET_REPLY`` string set contents
``ETHTOOL_MSG_LINKINFO_GET_REPLY`` link settings
``ETHTOOL_MSG_LINKINFO_NTF`` link settings notification
``ETHTOOL_MSG_LINKMODES_GET_REPLY`` link modes info
``ETHTOOL_MSG_LINKMODES_NTF`` link modes notification
``ETHTOOL_MSG_LINKSTATE_GET_REPLY`` link state info
``ETHTOOL_MSG_DEBUG_GET_REPLY`` debugging settings
``ETHTOOL_MSG_DEBUG_NTF`` debugging settings notification
``ETHTOOL_MSG_WOL_GET_REPLY`` wake-on-lan settings
``ETHTOOL_MSG_WOL_NTF`` wake-on-lan settings notification
===================================== =================================
``GET`` requests are sent by userspace applications to retrieve device
information. They usually do not contain any message specific attributes.
Kernel replies with corresponding "GET_REPLY" message. For most types, ``GET``
request with ``NLM_F_DUMP`` and no device identification can be used to query
the information for all devices supporting the request.
If the data can be also modified, corresponding ``SET`` message with the same
layout as corresponding ``GET_REPLY`` is used to request changes. Only
attributes where a change is requested are included in such request (also, not
all attributes may be changed). Replies to most ``SET`` request consist only
of error code and extack; if kernel provides additional data, it is sent in
the form of corresponding ``SET_REPLY`` message which can be suppressed by
setting ``ETHTOOL_FLAG_OMIT_REPLY`` flag in request header.
Data modification also triggers sending a ``NTF`` message with a notification.
These usually bear only a subset of attributes which was affected by the
change. The same notification is issued if the data is modified using other
means (mostly ioctl ethtool interface). Unlike notifications from ethtool
netlink code which are only sent if something actually changed, notifications
triggered by ioctl interface may be sent even if the request did not actually
change any data.
``ACT`` messages request kernel (driver) to perform a specific action. If some
information is reported by kernel (which can be suppressed by setting
``ETHTOOL_FLAG_OMIT_REPLY`` flag in request header), the reply takes form of
an ``ACT_REPLY`` message. Performing an action also triggers a notification
(``NTF`` message).
Later sections describe the format and semantics of these messages.
STRSET_GET
==========
Requests contents of a string set as provided by ioctl commands
``ETHTOOL_GSSET_INFO`` and ``ETHTOOL_GSTRINGS.`` String sets are not user
writeable so that the corresponding ``STRSET_SET`` message is only used in
kernel replies. There are two types of string sets: global (independent of
a device, e.g. device feature names) and device specific (e.g. device private
flags).
Request contents:
+---------------------------------------+--------+------------------------+
| ``ETHTOOL_A_STRSET_HEADER`` | nested | request header |
+---------------------------------------+--------+------------------------+
| ``ETHTOOL_A_STRSET_STRINGSETS`` | nested | string set to request |
+-+-------------------------------------+--------+------------------------+
| | ``ETHTOOL_A_STRINGSETS_STRINGSET+`` | nested | one string set |
+-+-+-----------------------------------+--------+------------------------+
| | | ``ETHTOOL_A_STRINGSET_ID`` | u32 | set id |
+-+-+-----------------------------------+--------+------------------------+
Kernel response contents:
+---------------------------------------+--------+-----------------------+
| ``ETHTOOL_A_STRSET_HEADER`` | nested | reply header |
+---------------------------------------+--------+-----------------------+
| ``ETHTOOL_A_STRSET_STRINGSETS`` | nested | array of string sets |
+-+-------------------------------------+--------+-----------------------+
| | ``ETHTOOL_A_STRINGSETS_STRINGSET+`` | nested | one string set |
+-+-+-----------------------------------+--------+-----------------------+
| | | ``ETHTOOL_A_STRINGSET_ID`` | u32 | set id |
+-+-+-----------------------------------+--------+-----------------------+
| | | ``ETHTOOL_A_STRINGSET_COUNT`` | u32 | number of strings |
+-+-+-----------------------------------+--------+-----------------------+
| | | ``ETHTOOL_A_STRINGSET_STRINGS`` | nested | array of strings |
+-+-+-+---------------------------------+--------+-----------------------+
| | | | ``ETHTOOL_A_STRINGS_STRING+`` | nested | one string |
+-+-+-+-+-------------------------------+--------+-----------------------+
| | | | | ``ETHTOOL_A_STRING_INDEX`` | u32 | string index |
+-+-+-+-+-------------------------------+--------+-----------------------+
| | | | | ``ETHTOOL_A_STRING_VALUE`` | string | string value |
+-+-+-+-+-------------------------------+--------+-----------------------+
| ``ETHTOOL_A_STRSET_COUNTS_ONLY`` | flag | return only counts |
+---------------------------------------+--------+-----------------------+
Device identification in request header is optional. Depending on its presence
a and ``NLM_F_DUMP`` flag, there are three type of ``STRSET_GET`` requests:
- no ``NLM_F_DUMP,`` no device: get "global" stringsets
- no ``NLM_F_DUMP``, with device: get string sets related to the device
- ``NLM_F_DUMP``, no device: get device related string sets for all devices
If there is no ``ETHTOOL_A_STRSET_STRINGSETS`` array, all string sets of
requested type are returned, otherwise only those specified in the request.
Flag ``ETHTOOL_A_STRSET_COUNTS_ONLY`` tells kernel to only return string
counts of the sets, not the actual strings.
LINKINFO_GET
============
Requests link settings as provided by ``ETHTOOL_GLINKSETTINGS`` except for
link modes and autonegotiation related information. The request does not use
any attributes.
Request contents:
==================================== ====== ==========================
``ETHTOOL_A_LINKINFO_HEADER`` nested request header
==================================== ====== ==========================
Kernel response contents:
==================================== ====== ==========================
``ETHTOOL_A_LINKINFO_HEADER`` nested reply header
``ETHTOOL_A_LINKINFO_PORT`` u8 physical port
``ETHTOOL_A_LINKINFO_PHYADDR`` u8 phy MDIO address
``ETHTOOL_A_LINKINFO_TP_MDIX`` u8 MDI(-X) status
``ETHTOOL_A_LINKINFO_TP_MDIX_CTRL`` u8 MDI(-X) control
``ETHTOOL_A_LINKINFO_TRANSCEIVER`` u8 transceiver
==================================== ====== ==========================
Attributes and their values have the same meaning as matching members of the
corresponding ioctl structures.
``LINKINFO_GET`` allows dump requests (kernel returns reply message for all
devices supporting the request).
LINKINFO_SET
============
``LINKINFO_SET`` request allows setting some of the attributes reported by
``LINKINFO_GET``.
Request contents:
==================================== ====== ==========================
``ETHTOOL_A_LINKINFO_HEADER`` nested request header
``ETHTOOL_A_LINKINFO_PORT`` u8 physical port
``ETHTOOL_A_LINKINFO_PHYADDR`` u8 phy MDIO address
``ETHTOOL_A_LINKINFO_TP_MDIX_CTRL`` u8 MDI(-X) control
==================================== ====== ==========================
MDI(-X) status and transceiver cannot be set, request with the corresponding
attributes is rejected.
LINKMODES_GET
=============
Requests link modes (supported, advertised and peer advertised) and related
information (autonegotiation status, link speed and duplex) as provided by
``ETHTOOL_GLINKSETTINGS``. The request does not use any attributes.
Request contents:
==================================== ====== ==========================
``ETHTOOL_A_LINKMODES_HEADER`` nested request header
==================================== ====== ==========================
Kernel response contents:
==================================== ====== ==========================
``ETHTOOL_A_LINKMODES_HEADER`` nested reply header
``ETHTOOL_A_LINKMODES_AUTONEG`` u8 autonegotiation status
``ETHTOOL_A_LINKMODES_OURS`` bitset advertised link modes
``ETHTOOL_A_LINKMODES_PEER`` bitset partner link modes
``ETHTOOL_A_LINKMODES_SPEED`` u32 link speed (Mb/s)
``ETHTOOL_A_LINKMODES_DUPLEX`` u8 duplex mode
==================================== ====== ==========================
For ``ETHTOOL_A_LINKMODES_OURS``, value represents advertised modes and mask
represents supported modes. ``ETHTOOL_A_LINKMODES_PEER`` in the reply is a bit
list.
``LINKMODES_GET`` allows dump requests (kernel returns reply messages for all
devices supporting the request).
LINKMODES_SET
=============
Request contents:
==================================== ====== ==========================
``ETHTOOL_A_LINKMODES_HEADER`` nested request header
``ETHTOOL_A_LINKMODES_AUTONEG`` u8 autonegotiation status
``ETHTOOL_A_LINKMODES_OURS`` bitset advertised link modes
``ETHTOOL_A_LINKMODES_PEER`` bitset partner link modes
``ETHTOOL_A_LINKMODES_SPEED`` u32 link speed (Mb/s)
``ETHTOOL_A_LINKMODES_DUPLEX`` u8 duplex mode
==================================== ====== ==========================
``ETHTOOL_A_LINKMODES_OURS`` bit set allows setting advertised link modes. If
autonegotiation is on (either set now or kept from before), advertised modes
are not changed (no ``ETHTOOL_A_LINKMODES_OURS`` attribute) and at least one
of speed and duplex is specified, kernel adjusts advertised modes to all
supported modes matching speed, duplex or both (whatever is specified). This
autoselection is done on ethtool side with ioctl interface, netlink interface
is supposed to allow requesting changes without knowing what exactly kernel
supports.
LINKSTATE_GET
=============
Requests link state information. At the moment, only link up/down flag (as
provided by ``ETHTOOL_GLINK`` ioctl command) is provided but some future
extensions are planned (e.g. link down reason). This request does not have any
attributes.
Request contents:
==================================== ====== ==========================
``ETHTOOL_A_LINKSTATE_HEADER`` nested request header
==================================== ====== ==========================
Kernel response contents:
==================================== ====== ==========================
``ETHTOOL_A_LINKSTATE_HEADER`` nested reply header
``ETHTOOL_A_LINKSTATE_LINK`` bool link state (up/down)
==================================== ====== ==========================
For most NIC drivers, the value of ``ETHTOOL_A_LINKSTATE_LINK`` returns
carrier flag provided by ``netif_carrier_ok()`` but there are drivers which
define their own handler.
``LINKSTATE_GET`` allows dump requests (kernel returns reply messages for all
devices supporting the request).
DEBUG_GET
=========
Requests debugging settings of a device. At the moment, only message mask is
provided.
Request contents:
==================================== ====== ==========================
``ETHTOOL_A_DEBUG_HEADER`` nested request header
==================================== ====== ==========================
Kernel response contents:
==================================== ====== ==========================
``ETHTOOL_A_DEBUG_HEADER`` nested reply header
``ETHTOOL_A_DEBUG_MSGMASK`` bitset message mask
==================================== ====== ==========================
The message mask (``ETHTOOL_A_DEBUG_MSGMASK``) is equal to message level as
provided by ``ETHTOOL_GMSGLVL`` and set by ``ETHTOOL_SMSGLVL`` in ioctl
interface. While it is called message level there for historical reasons, most
drivers and almost all newer drivers use it as a mask of enabled message
classes (represented by ``NETIF_MSG_*`` constants); therefore netlink
interface follows its actual use in practice.
``DEBUG_GET`` allows dump requests (kernel returns reply messages for all
devices supporting the request).
DEBUG_SET
=========
Set or update debugging settings of a device. At the moment, only message mask
is supported.
Request contents:
==================================== ====== ==========================
``ETHTOOL_A_DEBUG_HEADER`` nested request header
``ETHTOOL_A_DEBUG_MSGMASK`` bitset message mask
==================================== ====== ==========================
``ETHTOOL_A_DEBUG_MSGMASK`` bit set allows setting or modifying mask of
enabled debugging message types for the device.
WOL_GET
=======
Query device wake-on-lan settings. Unlike most "GET" type requests,
``ETHTOOL_MSG_WOL_GET`` requires (netns) ``CAP_NET_ADMIN`` privileges as it
(potentially) provides SecureOn(tm) password which is confidential.
Request contents:
==================================== ====== ==========================
``ETHTOOL_A_WOL_HEADER`` nested request header
==================================== ====== ==========================
Kernel response contents:
==================================== ====== ==========================
``ETHTOOL_A_WOL_HEADER`` nested reply header
``ETHTOOL_A_WOL_MODES`` bitset mask of enabled WoL modes
``ETHTOOL_A_WOL_SOPASS`` binary SecureOn(tm) password
==================================== ====== ==========================
In reply, ``ETHTOOL_A_WOL_MODES`` mask consists of modes supported by the
device, value of modes which are enabled. ``ETHTOOL_A_WOL_SOPASS`` is only
included in reply if ``WAKE_MAGICSECURE`` mode is supported.
WOL_SET
=======
Set or update wake-on-lan settings.
Request contents:
==================================== ====== ==========================
``ETHTOOL_A_WOL_HEADER`` nested request header
``ETHTOOL_A_WOL_MODES`` bitset enabled WoL modes
``ETHTOOL_A_WOL_SOPASS`` binary SecureOn(tm) password
==================================== ====== ==========================
``ETHTOOL_A_WOL_SOPASS`` is only allowed for devices supporting
``WAKE_MAGICSECURE`` mode.
Request translation
===================
The following table maps ioctl commands to netlink commands providing their
functionality. Entries with "n/a" in right column are commands which do not
have their netlink replacement yet.
=================================== =====================================
ioctl command netlink command
=================================== =====================================
``ETHTOOL_GSET`` ``ETHTOOL_MSG_LINKINFO_GET``
``ETHTOOL_MSG_LINKMODES_GET``
``ETHTOOL_SSET`` ``ETHTOOL_MSG_LINKINFO_SET``
``ETHTOOL_MSG_LINKMODES_SET``
``ETHTOOL_GDRVINFO`` n/a
``ETHTOOL_GREGS`` n/a
``ETHTOOL_GWOL`` ``ETHTOOL_MSG_WOL_GET``
``ETHTOOL_SWOL`` ``ETHTOOL_MSG_WOL_SET``
``ETHTOOL_GMSGLVL`` ``ETHTOOL_MSG_DEBUG_GET``
``ETHTOOL_SMSGLVL`` ``ETHTOOL_MSG_DEBUG_SET``
``ETHTOOL_NWAY_RST`` n/a
``ETHTOOL_GLINK`` ``ETHTOOL_MSG_LINKSTATE_GET``
``ETHTOOL_GEEPROM`` n/a
``ETHTOOL_SEEPROM`` n/a
``ETHTOOL_GCOALESCE`` n/a
``ETHTOOL_SCOALESCE`` n/a
``ETHTOOL_GRINGPARAM`` n/a
``ETHTOOL_SRINGPARAM`` n/a
``ETHTOOL_GPAUSEPARAM`` n/a
``ETHTOOL_SPAUSEPARAM`` n/a
``ETHTOOL_GRXCSUM`` n/a
``ETHTOOL_SRXCSUM`` n/a
``ETHTOOL_GTXCSUM`` n/a
``ETHTOOL_STXCSUM`` n/a
``ETHTOOL_GSG`` n/a
``ETHTOOL_SSG`` n/a
``ETHTOOL_TEST`` n/a
``ETHTOOL_GSTRINGS`` ``ETHTOOL_MSG_STRSET_GET``
``ETHTOOL_PHYS_ID`` n/a
``ETHTOOL_GSTATS`` n/a
``ETHTOOL_GTSO`` n/a
``ETHTOOL_STSO`` n/a
``ETHTOOL_GPERMADDR`` rtnetlink ``RTM_GETLINK``
``ETHTOOL_GUFO`` n/a
``ETHTOOL_SUFO`` n/a
``ETHTOOL_GGSO`` n/a
``ETHTOOL_SGSO`` n/a
``ETHTOOL_GFLAGS`` n/a
``ETHTOOL_SFLAGS`` n/a
``ETHTOOL_GPFLAGS`` n/a
``ETHTOOL_SPFLAGS`` n/a
``ETHTOOL_GRXFH`` n/a
``ETHTOOL_SRXFH`` n/a
``ETHTOOL_GGRO`` n/a
``ETHTOOL_SGRO`` n/a
``ETHTOOL_GRXRINGS`` n/a
``ETHTOOL_GRXCLSRLCNT`` n/a
``ETHTOOL_GRXCLSRULE`` n/a
``ETHTOOL_GRXCLSRLALL`` n/a
``ETHTOOL_SRXCLSRLDEL`` n/a
``ETHTOOL_SRXCLSRLINS`` n/a
``ETHTOOL_FLASHDEV`` n/a
``ETHTOOL_RESET`` n/a
``ETHTOOL_SRXNTUPLE`` n/a
``ETHTOOL_GRXNTUPLE`` n/a
``ETHTOOL_GSSET_INFO`` ``ETHTOOL_MSG_STRSET_GET``
``ETHTOOL_GRXFHINDIR`` n/a
``ETHTOOL_SRXFHINDIR`` n/a
``ETHTOOL_GFEATURES`` n/a
``ETHTOOL_SFEATURES`` n/a
``ETHTOOL_GCHANNELS`` n/a
``ETHTOOL_SCHANNELS`` n/a
``ETHTOOL_SET_DUMP`` n/a
``ETHTOOL_GET_DUMP_FLAG`` n/a
``ETHTOOL_GET_DUMP_DATA`` n/a
``ETHTOOL_GET_TS_INFO`` n/a
``ETHTOOL_GMODULEINFO`` n/a
``ETHTOOL_GMODULEEEPROM`` n/a
``ETHTOOL_GEEE`` n/a
``ETHTOOL_SEEE`` n/a
``ETHTOOL_GRSSH`` n/a
``ETHTOOL_SRSSH`` n/a
``ETHTOOL_GTUNABLE`` n/a
``ETHTOOL_STUNABLE`` n/a
``ETHTOOL_GPHYSTATS`` n/a
``ETHTOOL_PERQUEUE`` n/a
``ETHTOOL_GLINKSETTINGS`` ``ETHTOOL_MSG_LINKINFO_GET``
``ETHTOOL_MSG_LINKMODES_GET``
``ETHTOOL_SLINKSETTINGS`` ``ETHTOOL_MSG_LINKINFO_SET``
``ETHTOOL_MSG_LINKMODES_SET``
``ETHTOOL_PHY_GTUNABLE`` n/a
``ETHTOOL_PHY_STUNABLE`` n/a
``ETHTOOL_GFECPARAM`` n/a
``ETHTOOL_SFECPARAM`` n/a
=================================== =====================================

View File

@ -13,9 +13,8 @@ Contents:
can_ucan_protocol
device_drivers/index
dsa/index
devlink-info-versions
devlink-trap
devlink-trap-netdevsim
devlink/index
ethtool-netlink
ieee802154
j1939
kapi

View File

@ -479,6 +479,10 @@ tcp_no_metrics_save - BOOLEAN
degradation. If set, TCP will not cache metrics on closing
connections.
tcp_no_ssthresh_metrics_save - BOOLEAN
Controls whether TCP saves ssthresh metrics in the route cache.
Default is 1, which disables ssthresh metrics.
tcp_orphan_retries - INTEGER
This value influences the timeout of a locally closed TCP connection,
when RTO retransmissions remain unacknowledged.

View File

@ -267,6 +267,24 @@ Some of the interface modes are described below:
duplex, pause or other settings. This is dependent on the MAC and/or
PHY behaviour.
``PHY_INTERFACE_MODE_10GBASER``
This is the IEEE 802.3 Clause 49 defined 10GBASE-R protocol used with
various different mediums. Please refer to the IEEE standard for a
definition of this.
Note: 10GBASE-R is just one protocol that can be used with XFI and SFI.
XFI and SFI permit multiple protocols over a single SERDES lane, and
also defines the electrical characteristics of the signals with a host
compliance board plugged into the host XFP/SFP connector. Therefore,
XFI and SFI are not PHY interface types in their own right.
``PHY_INTERFACE_MODE_10GKR``
This is the IEEE 802.3 Clause 49 defined 10GBASE-R with Clause 73
autonegotiation. Please refer to the IEEE standard for further
information.
Note: due to legacy usage, some 10GBASE-R usage incorrectly makes
use of this definition.
Pause frames / flow control
===========================

View File

@ -251,7 +251,8 @@ this documentation.
phylink_mac_change(priv->phylink, link_is_up);
where ``link_is_up`` is true if the link is currently up or false
otherwise.
otherwise. If a MAC is unable to provide these interrupts, then
it should set ``priv->phylink_config.pcs_poll = true;`` in step 9.
11. Verify that the driver does not call::

View File

@ -4865,6 +4865,7 @@ S: Supported
F: net/core/devlink.c
F: include/net/devlink.h
F: include/uapi/linux/devlink.h
F: Documentation/networking/devlink
DIALOG SEMICONDUCTOR DRIVERS
M: Support Opensource <support.opensource@diasemi.com>
@ -9927,7 +9928,7 @@ S: Maintained
F: drivers/net/dsa/mv88e6xxx/
F: include/linux/platform_data/mv88e6xxx.h
F: Documentation/devicetree/bindings/net/dsa/marvell.txt
F: Documentation/networking/devlink-params-mv88e6xxx.txt
F: Documentation/networking/devlink/mv88e6xxx.rst
MARVELL ARMADA DRM SUPPORT
M: Russell King <linux@armlinux.org.uk>
@ -9997,8 +9998,7 @@ F: drivers/net/ethernet/marvell/mvneta.*
MARVELL MWIFIEX WIRELESS DRIVER
M: Amitkumar Karwar <amitkarwar@gmail.com>
M: Nishant Sarmukadam <nishants@marvell.com>
M: Ganapathi Bhat <gbhat@marvell.com>
M: Ganapathi Bhat <ganapathi.bhat@nxp.com>
M: Xinming Hu <huxinming820@gmail.com>
L: linux-wireless@vger.kernel.org
S: Maintained
@ -10037,6 +10037,16 @@ M: Jerin Jacob <jerinj@marvell.com>
L: netdev@vger.kernel.org
S: Supported
F: drivers/net/ethernet/marvell/octeontx2/af/
F: Documentation/networking/device_drivers/marvell/octeontx2.rst
MARVELL OCTEONTX2 PHYSICAL FUNCTION DRIVER
M: Sunil Goutham <sgoutham@marvell.com>
M: Geetha sowjanya <gakula@marvell.com>
M: Subbaraya Sundeep <sbhatta@marvell.com>
M: hariprasad <hkelam@marvell.com>
L: netdev@vger.kernel.org
S: Supported
F: drivers/net/ethernet/marvell/octeontx2/nic/
MATROX FRAMEBUFFER DRIVER
L: linux-fbdev@vger.kernel.org
@ -11431,7 +11441,7 @@ F: Documentation/networking/net_failover.rst
NETEM NETWORK EMULATOR
M: Stephen Hemminger <stephen@networkplumber.org>
L: netem@lists.linux-foundation.org (moderated for non-subscribers)
L: netdev@vger.kernel.org
S: Maintained
F: net/sched/sch_netem.c
@ -11619,6 +11629,18 @@ F: net/ipv6/calipso.c
F: net/netfilter/xt_CONNSECMARK.c
F: net/netfilter/xt_SECMARK.c
NETWORKING [MPTCP]
M: Mat Martineau <mathew.j.martineau@linux.intel.com>
M: Matthieu Baerts <matthieu.baerts@tessares.net>
L: netdev@vger.kernel.org
L: mptcp@lists.01.org
W: https://github.com/multipath-tcp/mptcp_net-next/wiki
B: https://github.com/multipath-tcp/mptcp_net-next/issues
S: Maintained
F: include/net/mptcp.h
F: net/mptcp/
F: tools/testing/selftests/net/mptcp/
NETWORKING [TCP]
M: Eric Dumazet <edumazet@google.com>
L: netdev@vger.kernel.org
@ -13702,6 +13724,13 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/ath.git
S: Supported
F: drivers/net/wireless/ath/ath10k/
QUALCOMM ATHEROS ATH11K WIRELESS DRIVER
M: Kalle Valo <kvalo@codeaurora.org>
L: ath11k@lists.infradead.org
T: git git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/ath.git
S: Supported
F: drivers/net/wireless/ath/ath11k/
QUALCOMM ATHEROS ATH9K WIRELESS DRIVER
M: QCA ath9k Development <ath9k-devel@qca.qualcomm.com>
L: linux-wireless@vger.kernel.org
@ -15830,6 +15859,7 @@ M: Jose Abreu <joabreu@synopsys.com>
L: netdev@vger.kernel.org
W: http://www.stlinux.com
S: Supported
F: Documentation/networking/device_drivers/stmicro/
F: drivers/net/ethernet/stmicro/stmmac/
SUN3/3X
@ -17559,6 +17589,7 @@ F: net/vmw_vsock/diag.c
F: net/vmw_vsock/af_vsock_tap.c
F: net/vmw_vsock/virtio_transport_common.c
F: net/vmw_vsock/virtio_transport.c
F: net/vmw_vsock/vsock_loopback.c
F: drivers/net/vsockmon.c
F: drivers/vhost/vsock.c
F: tools/testing/vsock/
@ -17929,6 +17960,14 @@ L: linux-gpio@vger.kernel.org
S: Maintained
F: drivers/gpio/gpio-ws16c48.c
WIREGUARD SECURE NETWORK TUNNEL
M: Jason A. Donenfeld <Jason@zx2c4.com>
S: Maintained
F: drivers/net/wireguard/
F: tools/testing/selftests/wireguard/
L: wireguard@lists.zx2c4.com
L: netdev@vger.kernel.org
WISTRON LAPTOP BUTTON DRIVER
M: Miloslav Trmac <mitr@volny.cz>
S: Maintained

View File

@ -132,6 +132,22 @@ static struct platform_device fsg_leds = {
};
/* Built-in 10/100 Ethernet MAC interfaces */
static struct resource fsg_eth_npeb_resources[] = {
{
.start = IXP4XX_EthB_BASE_PHYS,
.end = IXP4XX_EthB_BASE_PHYS + 0x0fff,
.flags = IORESOURCE_MEM,
},
};
static struct resource fsg_eth_npec_resources[] = {
{
.start = IXP4XX_EthC_BASE_PHYS,
.end = IXP4XX_EthC_BASE_PHYS + 0x0fff,
.flags = IORESOURCE_MEM,
},
};
static struct eth_plat_info fsg_plat_eth[] = {
{
.phy = 5,
@ -151,12 +167,16 @@ static struct platform_device fsg_eth[] = {
.dev = {
.platform_data = fsg_plat_eth,
},
.num_resources = ARRAY_SIZE(fsg_eth_npeb_resources),
.resource = fsg_eth_npeb_resources,
}, {
.name = "ixp4xx_eth",
.id = IXP4XX_ETH_NPEC,
.dev = {
.platform_data = fsg_plat_eth + 1,
},
.num_resources = ARRAY_SIZE(fsg_eth_npec_resources),
.resource = fsg_eth_npec_resources,
}
};

View File

@ -11,6 +11,7 @@
#include <linux/irq.h>
#include <linux/kernel.h>
#include <linux/pci.h>
#include <linux/platform_data/wan_ixp4xx_hss.h>
#include <linux/serial_8250.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
@ -272,6 +273,22 @@ static struct platform_device device_uarts = {
/* Built-in 10/100 Ethernet MAC interfaces */
static struct resource eth_npeb_resources[] = {
{
.start = IXP4XX_EthB_BASE_PHYS,
.end = IXP4XX_EthB_BASE_PHYS + 0x0fff,
.flags = IORESOURCE_MEM,
},
};
static struct resource eth_npec_resources[] = {
{
.start = IXP4XX_EthC_BASE_PHYS,
.end = IXP4XX_EthC_BASE_PHYS + 0x0fff,
.flags = IORESOURCE_MEM,
},
};
static struct eth_plat_info eth_plat[] = {
{
.phy = 0,
@ -289,10 +306,14 @@ static struct platform_device device_eth_tab[] = {
.name = "ixp4xx_eth",
.id = IXP4XX_ETH_NPEB,
.dev.platform_data = eth_plat,
.num_resources = ARRAY_SIZE(eth_npeb_resources),
.resource = eth_npeb_resources,
}, {
.name = "ixp4xx_eth",
.id = IXP4XX_ETH_NPEC,
.dev.platform_data = eth_plat + 1,
.num_resources = ARRAY_SIZE(eth_npec_resources),
.resource = eth_npec_resources,
}
};
@ -405,6 +426,9 @@ static void __init gmlr_init(void)
if (hw_bits & CFG_HW_HAS_HSS1)
device_tab[devices++] = &device_hss_tab[1]; /* max index 5 */
hss_plat[0].timer_freq = ixp4xx_timer_freq;
hss_plat[1].timer_freq = ixp4xx_timer_freq;
gpio_request(GPIO_SCL, "SCL/clock");
gpio_request(GPIO_SDA, "SDA/data");
gpio_request(GPIO_STR, "strobe");

View File

@ -15,6 +15,7 @@
#ifndef __ASSEMBLY__
#include <linux/reboot.h>
#include <linux/platform_data/eth_ixp4xx.h>
#include <asm/types.h>
@ -92,27 +93,6 @@ struct ixp4xx_pata_data {
void __iomem *cs1;
};
#define IXP4XX_ETH_NPEA 0x00
#define IXP4XX_ETH_NPEB 0x10
#define IXP4XX_ETH_NPEC 0x20
/* Information about built-in Ethernet MAC interfaces */
struct eth_plat_info {
u8 phy; /* MII PHY ID, 0 - 31 */
u8 rxq; /* configurable, currently 0 - 31 only */
u8 txreadyq;
u8 hwaddr[6];
};
/* Information about built-in HSS (synchronous serial) interfaces */
struct hss_plat_info {
int (*set_clock)(int port, unsigned int clock_type);
int (*open)(int port, void *pdev,
void (*set_carrier_cb)(void *pdev, int carrier));
void (*close)(int port, void *pdev);
u8 txreadyq;
};
/*
* Frequency of clock used for primary clocksource
*/

View File

@ -187,6 +187,22 @@ static struct platform_device ixdp425_uart = {
};
/* Built-in 10/100 Ethernet MAC interfaces */
static struct resource ixp425_npeb_resources[] = {
{
.start = IXP4XX_EthB_BASE_PHYS,
.end = IXP4XX_EthB_BASE_PHYS + 0x0fff,
.flags = IORESOURCE_MEM,
},
};
static struct resource ixp425_npec_resources[] = {
{
.start = IXP4XX_EthC_BASE_PHYS,
.end = IXP4XX_EthC_BASE_PHYS + 0x0fff,
.flags = IORESOURCE_MEM,
},
};
static struct eth_plat_info ixdp425_plat_eth[] = {
{
.phy = 0,
@ -204,10 +220,14 @@ static struct platform_device ixdp425_eth[] = {
.name = "ixp4xx_eth",
.id = IXP4XX_ETH_NPEB,
.dev.platform_data = ixdp425_plat_eth,
.num_resources = ARRAY_SIZE(ixp425_npeb_resources),
.resource = ixp425_npeb_resources,
}, {
.name = "ixp4xx_eth",
.id = IXP4XX_ETH_NPEC,
.dev.platform_data = ixdp425_plat_eth + 1,
.num_resources = ARRAY_SIZE(ixp425_npec_resources),
.resource = ixp425_npec_resources,
}
};

View File

@ -165,6 +165,14 @@ static struct platform_device nas100d_uart = {
};
/* Built-in 10/100 Ethernet MAC interfaces */
static struct resource nas100d_eth_resources[] = {
{
.start = IXP4XX_EthB_BASE_PHYS,
.end = IXP4XX_EthB_BASE_PHYS + 0x0fff,
.flags = IORESOURCE_MEM,
},
};
static struct eth_plat_info nas100d_plat_eth[] = {
{
.phy = 0,
@ -178,6 +186,8 @@ static struct platform_device nas100d_eth[] = {
.name = "ixp4xx_eth",
.id = IXP4XX_ETH_NPEB,
.dev.platform_data = nas100d_plat_eth,
.num_resources = ARRAY_SIZE(nas100d_eth_resources),
.resource = nas100d_eth_resources,
}
};

View File

@ -185,6 +185,14 @@ static struct platform_device nslu2_uart = {
};
/* Built-in 10/100 Ethernet MAC interfaces */
static struct resource nslu2_eth_resources[] = {
{
.start = IXP4XX_EthB_BASE_PHYS,
.end = IXP4XX_EthB_BASE_PHYS + 0x0fff,
.flags = IORESOURCE_MEM,
},
};
static struct eth_plat_info nslu2_plat_eth[] = {
{
.phy = 1,
@ -198,6 +206,8 @@ static struct platform_device nslu2_eth[] = {
.name = "ixp4xx_eth",
.id = IXP4XX_ETH_NPEB,
.dev.platform_data = nslu2_plat_eth,
.num_resources = ARRAY_SIZE(nslu2_eth_resources),
.resource = nslu2_eth_resources,
}
};

View File

@ -170,6 +170,22 @@ static struct platform_device mic256_leds = {
};
/* Built-in 10/100 Ethernet MAC interfaces */
static struct resource ixp425_npeb_resources[] = {
{
.start = IXP4XX_EthB_BASE_PHYS,
.end = IXP4XX_EthB_BASE_PHYS + 0x0fff,
.flags = IORESOURCE_MEM,
},
};
static struct resource ixp425_npec_resources[] = {
{
.start = IXP4XX_EthC_BASE_PHYS,
.end = IXP4XX_EthC_BASE_PHYS + 0x0fff,
.flags = IORESOURCE_MEM,
},
};
static struct eth_plat_info ixdp425_plat_eth[] = {
{
.phy = 0,
@ -187,10 +203,14 @@ static struct platform_device ixdp425_eth[] = {
.name = "ixp4xx_eth",
.id = IXP4XX_ETH_NPEB,
.dev.platform_data = ixdp425_plat_eth,
.num_resources = ARRAY_SIZE(ixp425_npeb_resources),
.resource = ixp425_npeb_resources,
}, {
.name = "ixp4xx_eth",
.id = IXP4XX_ETH_NPEC,
.dev.platform_data = ixdp425_plat_eth + 1,
.num_resources = ARRAY_SIZE(ixp425_npec_resources),
.resource = ixp425_npec_resources,
},
};

View File

@ -124,6 +124,22 @@ static struct platform_device vulcan_uart = {
.num_resources = ARRAY_SIZE(vulcan_uart_resources),
};
static struct resource vulcan_npeb_resources[] = {
{
.start = IXP4XX_EthB_BASE_PHYS,
.end = IXP4XX_EthB_BASE_PHYS + 0x0fff,
.flags = IORESOURCE_MEM,
},
};
static struct resource vulcan_npec_resources[] = {
{
.start = IXP4XX_EthC_BASE_PHYS,
.end = IXP4XX_EthC_BASE_PHYS + 0x0fff,
.flags = IORESOURCE_MEM,
},
};
static struct eth_plat_info vulcan_plat_eth[] = {
[0] = {
.phy = 0,
@ -144,6 +160,8 @@ static struct platform_device vulcan_eth[] = {
.dev = {
.platform_data = &vulcan_plat_eth[0],
},
.num_resources = ARRAY_SIZE(vulcan_npeb_resources),
.resource = vulcan_npeb_resources,
},
[1] = {
.name = "ixp4xx_eth",
@ -151,6 +169,8 @@ static struct platform_device vulcan_eth[] = {
.dev = {
.platform_data = &vulcan_plat_eth[1],
},
.num_resources = ARRAY_SIZE(vulcan_npec_resources),
.resource = vulcan_npec_resources,
},
};

View File

@ -1260,12 +1260,9 @@ static inline void emit_push_r64(const s8 src[], struct jit_ctx *ctx)
static void build_prologue(struct jit_ctx *ctx)
{
const s8 r0 = bpf2a32[BPF_REG_0][1];
const s8 r2 = bpf2a32[BPF_REG_1][1];
const s8 r3 = bpf2a32[BPF_REG_1][0];
const s8 r4 = bpf2a32[BPF_REG_6][1];
const s8 fplo = bpf2a32[BPF_REG_FP][1];
const s8 fphi = bpf2a32[BPF_REG_FP][0];
const s8 arm_r0 = bpf2a32[BPF_REG_0][1];
const s8 *bpf_r1 = bpf2a32[BPF_REG_1];
const s8 *bpf_fp = bpf2a32[BPF_REG_FP];
const s8 *tcc = bpf2a32[TCALL_CNT];
/* Save callee saved registers. */
@ -1278,8 +1275,10 @@ static void build_prologue(struct jit_ctx *ctx)
emit(ARM_PUSH(CALLEE_PUSH_MASK), ctx);
emit(ARM_MOV_R(ARM_FP, ARM_SP), ctx);
#endif
/* Save frame pointer for later */
emit(ARM_SUB_I(ARM_IP, ARM_SP, SCRATCH_SIZE), ctx);
/* mov r3, #0 */
/* sub r2, sp, #SCRATCH_SIZE */
emit(ARM_MOV_I(bpf_r1[0], 0), ctx);
emit(ARM_SUB_I(bpf_r1[1], ARM_SP, SCRATCH_SIZE), ctx);
ctx->stack_size = imm8m(STACK_SIZE);
@ -1287,18 +1286,15 @@ static void build_prologue(struct jit_ctx *ctx)
emit(ARM_SUB_I(ARM_SP, ARM_SP, ctx->stack_size), ctx);
/* Set up BPF prog stack base register */
emit_a32_mov_r(fplo, ARM_IP, ctx);
emit_a32_mov_i(fphi, 0, ctx);
emit_a32_mov_r64(true, bpf_fp, bpf_r1, ctx);
/* mov r4, 0 */
emit(ARM_MOV_I(r4, 0), ctx);
/* Initialize Tail Count */
emit(ARM_MOV_I(bpf_r1[1], 0), ctx);
emit_a32_mov_r64(true, tcc, bpf_r1, ctx);
/* Move BPF_CTX to BPF_R1 */
emit(ARM_MOV_R(r3, r4), ctx);
emit(ARM_MOV_R(r2, r0), ctx);
/* Initialize Tail Count */
emit(ARM_STR_I(r4, ARM_FP, EBPF_SCRATCH_TO_ARM_FP(tcc[0])), ctx);
emit(ARM_STR_I(r4, ARM_FP, EBPF_SCRATCH_TO_ARM_FP(tcc[1])), ctx);
emit(ARM_MOV_R(bpf_r1[1], arm_r0), ctx);
/* end of prologue */
}

View File

@ -69,6 +69,7 @@ config ARM64
select ARCH_SUPPORTS_INT128 if CC_HAS_INT128 && (GCC_VERSION >= 50000 || CC_IS_CLANG)
select ARCH_SUPPORTS_NUMA_BALANCING
select ARCH_WANT_COMPAT_IPC_PARSE_VERSION if COMPAT
select ARCH_WANT_DEFAULT_BPF_JIT
select ARCH_WANT_DEFAULT_TOPDOWN_MMAP_LAYOUT
select ARCH_WANT_FRAME_POINTERS
select ARCH_WANT_HUGE_PMD_SHARE if ARM64_4K_PAGES || (ARM64_16K_PAGES && !ARM64_VA_BITS_36)

View File

@ -167,7 +167,7 @@ static int nfeth_xmit(struct sk_buff *skb, struct net_device *dev)
return 0;
}
static void nfeth_tx_timeout(struct net_device *dev)
static void nfeth_tx_timeout(struct net_device *dev, unsigned int txqueue)
{
dev->stats.tx_errors++;
netif_wake_queue(dev);

View File

@ -126,6 +126,9 @@
clocks = <&pll ATH79_CLK_AHB>, <&pll ATH79_CLK_AHB>;
clock-names = "eth", "mdio";
phy-mode = "mii";
phy-handle = <&phy_port4>;
status = "disabled";
};
@ -133,13 +136,127 @@
compatible = "qca,ar9330-eth";
reg = <0x1a000000 0x200>;
interrupts = <5>;
resets = <&rst 13>, <&rst 23>;
reset-names = "mac", "mdio";
clocks = <&pll ATH79_CLK_AHB>, <&pll ATH79_CLK_AHB>;
clock-names = "eth", "mdio";
phy-mode = "gmii";
status = "disabled";
fixed-link {
speed = <1000>;
full-duplex;
};
mdio {
#address-cells = <1>;
#size-cells = <0>;
switch10: switch@10 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "qca,ar9331-switch";
reg = <0x10>;
resets = <&rst 8>;
reset-names = "switch";
interrupt-parent = <&miscintc>;
interrupts = <12>;
interrupt-controller;
#interrupt-cells = <1>;
ports {
#address-cells = <1>;
#size-cells = <0>;
switch_port0: port@0 {
reg = <0x0>;
label = "cpu";
ethernet = <&eth1>;
phy-mode = "gmii";
fixed-link {
speed = <1000>;
full-duplex;
};
};
switch_port1: port@1 {
reg = <0x1>;
phy-handle = <&phy_port0>;
phy-mode = "internal";
status = "disabled";
};
switch_port2: port@2 {
reg = <0x2>;
phy-handle = <&phy_port1>;
phy-mode = "internal";
status = "disabled";
};
switch_port3: port@3 {
reg = <0x3>;
phy-handle = <&phy_port2>;
phy-mode = "internal";
status = "disabled";
};
switch_port4: port@4 {
reg = <0x4>;
phy-handle = <&phy_port3>;
phy-mode = "internal";
status = "disabled";
};
};
mdio {
#address-cells = <1>;
#size-cells = <0>;
interrupt-parent = <&switch10>;
phy_port0: phy@0 {
reg = <0x0>;
interrupts = <0>;
status = "disabled";
};
phy_port1: phy@1 {
reg = <0x1>;
interrupts = <0>;
status = "disabled";
};
phy_port2: phy@2 {
reg = <0x2>;
interrupts = <0>;
status = "disabled";
};
phy_port3: phy@3 {
reg = <0x3>;
interrupts = <0>;
status = "disabled";
};
phy_port4: phy@4 {
reg = <0x4>;
interrupts = <0>;
status = "disabled";
};
};
};
};
};
usb: usb@1b000100 {

View File

@ -84,3 +84,16 @@
&eth1 {
status = "okay";
};
&switch_port1 {
label = "lan0";
status = "okay";
};
&phy_port0 {
status = "okay";
};
&phy_port4 {
status = "okay";
};

View File

@ -82,4 +82,8 @@ struct riscv_pmu {
int irq;
};
#ifdef CONFIG_PERF_EVENTS
#define perf_arch_bpf_user_pt_regs(regs) (struct user_regs_struct *)regs
#endif
#endif /* _ASM_RISCV_PERF_EVENT_H */

View File

@ -94,6 +94,10 @@ extern pgd_t swapper_pg_dir[];
#define VMALLOC_END (PAGE_OFFSET - 1)
#define VMALLOC_START (PAGE_OFFSET - VMALLOC_SIZE)
#define BPF_JIT_REGION_SIZE (SZ_128M)
#define BPF_JIT_REGION_START (PAGE_OFFSET - BPF_JIT_REGION_SIZE)
#define BPF_JIT_REGION_END (VMALLOC_END)
/*
* Roughly size the vmemmap space to be large enough to fit enough
* struct pages to map half the virtual address space. Then

View File

@ -0,0 +1,9 @@
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
#ifndef _UAPI__ASM_BPF_PERF_EVENT_H__
#define _UAPI__ASM_BPF_PERF_EVENT_H__
#include <asm/ptrace.h>
typedef struct user_regs_struct bpf_user_pt_regs_t;
#endif /* _UAPI__ASM_BPF_PERF_EVENT_H__ */

View File

@ -120,6 +120,11 @@ static bool seen_reg(int reg, struct rv_jit_context *ctx)
return false;
}
static void mark_fp(struct rv_jit_context *ctx)
{
__set_bit(RV_CTX_F_SEEN_S5, &ctx->flags);
}
static void mark_call(struct rv_jit_context *ctx)
{
__set_bit(RV_CTX_F_SEEN_CALL, &ctx->flags);
@ -456,6 +461,11 @@ static u32 rv_amoadd_d(u8 rd, u8 rs2, u8 rs1, u8 aq, u8 rl)
return rv_amo_insn(0, aq, rl, rs2, rs1, 3, rd, 0x2f);
}
static u32 rv_auipc(u8 rd, u32 imm31_12)
{
return rv_u_insn(imm31_12, rd, 0x17);
}
static bool is_12b_int(s64 val)
{
return -(1 << 11) <= val && val < (1 << 11);
@ -479,27 +489,7 @@ static bool is_32b_int(s64 val)
static int is_12b_check(int off, int insn)
{
if (!is_12b_int(off)) {
pr_err("bpf-jit: insn=%d offset=%d not supported yet!\n",
insn, (int)off);
return -1;
}
return 0;
}
static int is_13b_check(int off, int insn)
{
if (!is_13b_int(off)) {
pr_err("bpf-jit: insn=%d offset=%d not supported yet!\n",
insn, (int)off);
return -1;
}
return 0;
}
static int is_21b_check(int off, int insn)
{
if (!is_21b_int(off)) {
pr_err("bpf-jit: insn=%d offset=%d not supported yet!\n",
pr_err("bpf-jit: insn=%d 12b < offset=%d not supported yet!\n",
insn, (int)off);
return -1;
}
@ -545,10 +535,13 @@ static void emit_imm(u8 rd, s64 val, struct rv_jit_context *ctx)
emit(rv_addi(rd, rd, lower), ctx);
}
static int rv_offset(int bpf_to, int bpf_from, struct rv_jit_context *ctx)
static int rv_offset(int insn, int off, struct rv_jit_context *ctx)
{
int from = ctx->offset[bpf_from] - 1, to = ctx->offset[bpf_to];
int from, to;
off++; /* BPF branch is from PC+1, RV is from PC */
from = (insn > 0) ? ctx->offset[insn - 1] : 0;
to = (insn + off > 0) ? ctx->offset[insn + off - 1] : 0;
return (to - from) << 2;
}
@ -559,7 +552,7 @@ static int epilogue_offset(struct rv_jit_context *ctx)
return (to - from) << 2;
}
static void __build_epilogue(u8 reg, struct rv_jit_context *ctx)
static void __build_epilogue(bool is_tail_call, struct rv_jit_context *ctx)
{
int stack_adjust = ctx->stack_size, store_offset = stack_adjust - 8;
@ -596,8 +589,114 @@ static void __build_epilogue(u8 reg, struct rv_jit_context *ctx)
emit(rv_addi(RV_REG_SP, RV_REG_SP, stack_adjust), ctx);
/* Set return value. */
emit(rv_addi(RV_REG_A0, RV_REG_A5, 0), ctx);
emit(rv_jalr(RV_REG_ZERO, reg, 0), ctx);
if (!is_tail_call)
emit(rv_addi(RV_REG_A0, RV_REG_A5, 0), ctx);
emit(rv_jalr(RV_REG_ZERO, is_tail_call ? RV_REG_T3 : RV_REG_RA,
is_tail_call ? 4 : 0), /* skip TCC init */
ctx);
}
/* return -1 or inverted cond */
static int invert_bpf_cond(u8 cond)
{
switch (cond) {
case BPF_JEQ:
return BPF_JNE;
case BPF_JGT:
return BPF_JLE;
case BPF_JLT:
return BPF_JGE;
case BPF_JGE:
return BPF_JLT;
case BPF_JLE:
return BPF_JGT;
case BPF_JNE:
return BPF_JEQ;
case BPF_JSGT:
return BPF_JSLE;
case BPF_JSLT:
return BPF_JSGE;
case BPF_JSGE:
return BPF_JSLT;
case BPF_JSLE:
return BPF_JSGT;
}
return -1;
}
static void emit_bcc(u8 cond, u8 rd, u8 rs, int rvoff,
struct rv_jit_context *ctx)
{
switch (cond) {
case BPF_JEQ:
emit(rv_beq(rd, rs, rvoff >> 1), ctx);
return;
case BPF_JGT:
emit(rv_bltu(rs, rd, rvoff >> 1), ctx);
return;
case BPF_JLT:
emit(rv_bltu(rd, rs, rvoff >> 1), ctx);
return;
case BPF_JGE:
emit(rv_bgeu(rd, rs, rvoff >> 1), ctx);
return;
case BPF_JLE:
emit(rv_bgeu(rs, rd, rvoff >> 1), ctx);
return;
case BPF_JNE:
emit(rv_bne(rd, rs, rvoff >> 1), ctx);
return;
case BPF_JSGT:
emit(rv_blt(rs, rd, rvoff >> 1), ctx);
return;
case BPF_JSLT:
emit(rv_blt(rd, rs, rvoff >> 1), ctx);
return;
case BPF_JSGE:
emit(rv_bge(rd, rs, rvoff >> 1), ctx);
return;
case BPF_JSLE:
emit(rv_bge(rs, rd, rvoff >> 1), ctx);
}
}
static void emit_branch(u8 cond, u8 rd, u8 rs, int rvoff,
struct rv_jit_context *ctx)
{
s64 upper, lower;
if (is_13b_int(rvoff)) {
emit_bcc(cond, rd, rs, rvoff, ctx);
return;
}
/* Adjust for jal */
rvoff -= 4;
/* Transform, e.g.:
* bne rd,rs,foo
* to
* beq rd,rs,<.L1>
* (auipc foo)
* jal(r) foo
* .L1
*/
cond = invert_bpf_cond(cond);
if (is_21b_int(rvoff)) {
emit_bcc(cond, rd, rs, 8, ctx);
emit(rv_jal(RV_REG_ZERO, rvoff >> 1), ctx);
return;
}
/* 32b No need for an additional rvoff adjustment, since we
* get that from the auipc at PC', where PC = PC' + 4.
*/
upper = (rvoff + (1 << 11)) >> 12;
lower = rvoff & 0xfff;
emit_bcc(cond, rd, rs, 12, ctx);
emit(rv_auipc(RV_REG_T1, upper), ctx);
emit(rv_jalr(RV_REG_ZERO, RV_REG_T1, lower), ctx);
}
static void emit_zext_32(u8 reg, struct rv_jit_context *ctx)
@ -627,18 +726,14 @@ static int emit_bpf_tail_call(int insn, struct rv_jit_context *ctx)
return -1;
emit(rv_lwu(RV_REG_T1, off, RV_REG_A1), ctx);
off = (tc_ninsn - (ctx->ninsns - start_insn)) << 2;
if (is_13b_check(off, insn))
return -1;
emit(rv_bgeu(RV_REG_A2, RV_REG_T1, off >> 1), ctx);
emit_branch(BPF_JGE, RV_REG_A2, RV_REG_T1, off, ctx);
/* if (TCC-- < 0)
* goto out;
*/
emit(rv_addi(RV_REG_T1, tcc, -1), ctx);
off = (tc_ninsn - (ctx->ninsns - start_insn)) << 2;
if (is_13b_check(off, insn))
return -1;
emit(rv_blt(tcc, RV_REG_ZERO, off >> 1), ctx);
emit_branch(BPF_JSLT, tcc, RV_REG_ZERO, off, ctx);
/* prog = array->ptrs[index];
* if (!prog)
@ -651,18 +746,15 @@ static int emit_bpf_tail_call(int insn, struct rv_jit_context *ctx)
return -1;
emit(rv_ld(RV_REG_T2, off, RV_REG_T2), ctx);
off = (tc_ninsn - (ctx->ninsns - start_insn)) << 2;
if (is_13b_check(off, insn))
return -1;
emit(rv_beq(RV_REG_T2, RV_REG_ZERO, off >> 1), ctx);
emit_branch(BPF_JEQ, RV_REG_T2, RV_REG_ZERO, off, ctx);
/* goto *(prog->bpf_func + 4); */
off = offsetof(struct bpf_prog, bpf_func);
if (is_12b_check(off, insn))
return -1;
emit(rv_ld(RV_REG_T3, off, RV_REG_T2), ctx);
emit(rv_addi(RV_REG_T3, RV_REG_T3, 4), ctx);
emit(rv_addi(RV_REG_TCC, RV_REG_T1, 0), ctx);
__build_epilogue(RV_REG_T3, ctx);
__build_epilogue(true, ctx);
return 0;
}
@ -687,13 +779,6 @@ static void init_regs(u8 *rd, u8 *rs, const struct bpf_insn *insn,
*rs = bpf_to_rv_reg(insn->src_reg, ctx);
}
static int rv_offset_check(int *rvoff, s16 off, int insn,
struct rv_jit_context *ctx)
{
*rvoff = rv_offset(insn + off, insn, ctx);
return is_13b_check(*rvoff, insn);
}
static void emit_zext_32_rd_rs(u8 *rd, u8 *rs, struct rv_jit_context *ctx)
{
emit(rv_addi(RV_REG_T2, *rd, 0), ctx);
@ -726,13 +811,57 @@ static void emit_sext_32_rd(u8 *rd, struct rv_jit_context *ctx)
*rd = RV_REG_T2;
}
static void emit_jump_and_link(u8 rd, s64 rvoff, bool force_jalr,
struct rv_jit_context *ctx)
{
s64 upper, lower;
if (rvoff && is_21b_int(rvoff) && !force_jalr) {
emit(rv_jal(rd, rvoff >> 1), ctx);
return;
}
upper = (rvoff + (1 << 11)) >> 12;
lower = rvoff & 0xfff;
emit(rv_auipc(RV_REG_T1, upper), ctx);
emit(rv_jalr(rd, RV_REG_T1, lower), ctx);
}
static bool is_signed_bpf_cond(u8 cond)
{
return cond == BPF_JSGT || cond == BPF_JSLT ||
cond == BPF_JSGE || cond == BPF_JSLE;
}
static int emit_call(bool fixed, u64 addr, struct rv_jit_context *ctx)
{
s64 off = 0;
u64 ip;
u8 rd;
if (addr && ctx->insns) {
ip = (u64)(long)(ctx->insns + ctx->ninsns);
off = addr - ip;
if (!is_32b_int(off)) {
pr_err("bpf-jit: target call addr %pK is out of range\n",
(void *)addr);
return -ERANGE;
}
}
emit_jump_and_link(RV_REG_RA, off, !fixed, ctx);
rd = bpf_to_rv_reg(BPF_REG_0, ctx);
emit(rv_addi(rd, RV_REG_A0, 0), ctx);
return 0;
}
static int emit_insn(const struct bpf_insn *insn, struct rv_jit_context *ctx,
bool extra_pass)
{
bool is64 = BPF_CLASS(insn->code) == BPF_ALU64 ||
BPF_CLASS(insn->code) == BPF_JMP;
int s, e, rvoff, i = insn - ctx->prog->insnsi;
struct bpf_prog_aux *aux = ctx->prog->aux;
int rvoff, i = insn - ctx->prog->insnsi;
u8 rd = -1, rs = -1, code = insn->code;
s16 off = insn->off;
s32 imm = insn->imm;
@ -1000,214 +1129,110 @@ out_be:
/* JUMP off */
case BPF_JMP | BPF_JA:
rvoff = rv_offset(i + off, i, ctx);
if (!is_21b_int(rvoff)) {
pr_err("bpf-jit: insn=%d offset=%d not supported yet!\n",
i, rvoff);
return -1;
}
emit(rv_jal(RV_REG_ZERO, rvoff >> 1), ctx);
rvoff = rv_offset(i, off, ctx);
emit_jump_and_link(RV_REG_ZERO, rvoff, false, ctx);
break;
/* IF (dst COND src) JUMP off */
case BPF_JMP | BPF_JEQ | BPF_X:
case BPF_JMP32 | BPF_JEQ | BPF_X:
if (rv_offset_check(&rvoff, off, i, ctx))
return -1;
if (!is64)
emit_zext_32_rd_rs(&rd, &rs, ctx);
emit(rv_beq(rd, rs, rvoff >> 1), ctx);
break;
case BPF_JMP | BPF_JGT | BPF_X:
case BPF_JMP32 | BPF_JGT | BPF_X:
if (rv_offset_check(&rvoff, off, i, ctx))
return -1;
if (!is64)
emit_zext_32_rd_rs(&rd, &rs, ctx);
emit(rv_bltu(rs, rd, rvoff >> 1), ctx);
break;
case BPF_JMP | BPF_JLT | BPF_X:
case BPF_JMP32 | BPF_JLT | BPF_X:
if (rv_offset_check(&rvoff, off, i, ctx))
return -1;
if (!is64)
emit_zext_32_rd_rs(&rd, &rs, ctx);
emit(rv_bltu(rd, rs, rvoff >> 1), ctx);
break;
case BPF_JMP | BPF_JGE | BPF_X:
case BPF_JMP32 | BPF_JGE | BPF_X:
if (rv_offset_check(&rvoff, off, i, ctx))
return -1;
if (!is64)
emit_zext_32_rd_rs(&rd, &rs, ctx);
emit(rv_bgeu(rd, rs, rvoff >> 1), ctx);
break;
case BPF_JMP | BPF_JLE | BPF_X:
case BPF_JMP32 | BPF_JLE | BPF_X:
if (rv_offset_check(&rvoff, off, i, ctx))
return -1;
if (!is64)
emit_zext_32_rd_rs(&rd, &rs, ctx);
emit(rv_bgeu(rs, rd, rvoff >> 1), ctx);
break;
case BPF_JMP | BPF_JNE | BPF_X:
case BPF_JMP32 | BPF_JNE | BPF_X:
if (rv_offset_check(&rvoff, off, i, ctx))
return -1;
if (!is64)
emit_zext_32_rd_rs(&rd, &rs, ctx);
emit(rv_bne(rd, rs, rvoff >> 1), ctx);
break;
case BPF_JMP | BPF_JSGT | BPF_X:
case BPF_JMP32 | BPF_JSGT | BPF_X:
if (rv_offset_check(&rvoff, off, i, ctx))
return -1;
if (!is64)
emit_sext_32_rd_rs(&rd, &rs, ctx);
emit(rv_blt(rs, rd, rvoff >> 1), ctx);
break;
case BPF_JMP | BPF_JSLT | BPF_X:
case BPF_JMP32 | BPF_JSLT | BPF_X:
if (rv_offset_check(&rvoff, off, i, ctx))
return -1;
if (!is64)
emit_sext_32_rd_rs(&rd, &rs, ctx);
emit(rv_blt(rd, rs, rvoff >> 1), ctx);
break;
case BPF_JMP | BPF_JSGE | BPF_X:
case BPF_JMP32 | BPF_JSGE | BPF_X:
if (rv_offset_check(&rvoff, off, i, ctx))
return -1;
if (!is64)
emit_sext_32_rd_rs(&rd, &rs, ctx);
emit(rv_bge(rd, rs, rvoff >> 1), ctx);
break;
case BPF_JMP | BPF_JSLE | BPF_X:
case BPF_JMP32 | BPF_JSLE | BPF_X:
if (rv_offset_check(&rvoff, off, i, ctx))
return -1;
if (!is64)
emit_sext_32_rd_rs(&rd, &rs, ctx);
emit(rv_bge(rs, rd, rvoff >> 1), ctx);
break;
case BPF_JMP | BPF_JSET | BPF_X:
case BPF_JMP32 | BPF_JSET | BPF_X:
if (rv_offset_check(&rvoff, off, i, ctx))
return -1;
if (!is64)
emit_zext_32_rd_rs(&rd, &rs, ctx);
emit(rv_and(RV_REG_T1, rd, rs), ctx);
emit(rv_bne(RV_REG_T1, RV_REG_ZERO, rvoff >> 1), ctx);
rvoff = rv_offset(i, off, ctx);
if (!is64) {
s = ctx->ninsns;
if (is_signed_bpf_cond(BPF_OP(code)))
emit_sext_32_rd_rs(&rd, &rs, ctx);
else
emit_zext_32_rd_rs(&rd, &rs, ctx);
e = ctx->ninsns;
/* Adjust for extra insns */
rvoff -= (e - s) << 2;
}
if (BPF_OP(code) == BPF_JSET) {
/* Adjust for and */
rvoff -= 4;
emit(rv_and(RV_REG_T1, rd, rs), ctx);
emit_branch(BPF_JNE, RV_REG_T1, RV_REG_ZERO, rvoff,
ctx);
} else {
emit_branch(BPF_OP(code), rd, rs, rvoff, ctx);
}
break;
/* IF (dst COND imm) JUMP off */
case BPF_JMP | BPF_JEQ | BPF_K:
case BPF_JMP32 | BPF_JEQ | BPF_K:
if (rv_offset_check(&rvoff, off, i, ctx))
return -1;
emit_imm(RV_REG_T1, imm, ctx);
if (!is64)
emit_zext_32_rd_t1(&rd, ctx);
emit(rv_beq(rd, RV_REG_T1, rvoff >> 1), ctx);
break;
case BPF_JMP | BPF_JGT | BPF_K:
case BPF_JMP32 | BPF_JGT | BPF_K:
if (rv_offset_check(&rvoff, off, i, ctx))
return -1;
emit_imm(RV_REG_T1, imm, ctx);
if (!is64)
emit_zext_32_rd_t1(&rd, ctx);
emit(rv_bltu(RV_REG_T1, rd, rvoff >> 1), ctx);
break;
case BPF_JMP | BPF_JLT | BPF_K:
case BPF_JMP32 | BPF_JLT | BPF_K:
if (rv_offset_check(&rvoff, off, i, ctx))
return -1;
emit_imm(RV_REG_T1, imm, ctx);
if (!is64)
emit_zext_32_rd_t1(&rd, ctx);
emit(rv_bltu(rd, RV_REG_T1, rvoff >> 1), ctx);
break;
case BPF_JMP | BPF_JGE | BPF_K:
case BPF_JMP32 | BPF_JGE | BPF_K:
if (rv_offset_check(&rvoff, off, i, ctx))
return -1;
emit_imm(RV_REG_T1, imm, ctx);
if (!is64)
emit_zext_32_rd_t1(&rd, ctx);
emit(rv_bgeu(rd, RV_REG_T1, rvoff >> 1), ctx);
break;
case BPF_JMP | BPF_JLE | BPF_K:
case BPF_JMP32 | BPF_JLE | BPF_K:
if (rv_offset_check(&rvoff, off, i, ctx))
return -1;
emit_imm(RV_REG_T1, imm, ctx);
if (!is64)
emit_zext_32_rd_t1(&rd, ctx);
emit(rv_bgeu(RV_REG_T1, rd, rvoff >> 1), ctx);
break;
case BPF_JMP | BPF_JNE | BPF_K:
case BPF_JMP32 | BPF_JNE | BPF_K:
if (rv_offset_check(&rvoff, off, i, ctx))
return -1;
emit_imm(RV_REG_T1, imm, ctx);
if (!is64)
emit_zext_32_rd_t1(&rd, ctx);
emit(rv_bne(rd, RV_REG_T1, rvoff >> 1), ctx);
break;
case BPF_JMP | BPF_JSGT | BPF_K:
case BPF_JMP32 | BPF_JSGT | BPF_K:
if (rv_offset_check(&rvoff, off, i, ctx))
return -1;
emit_imm(RV_REG_T1, imm, ctx);
if (!is64)
emit_sext_32_rd(&rd, ctx);
emit(rv_blt(RV_REG_T1, rd, rvoff >> 1), ctx);
break;
case BPF_JMP | BPF_JSLT | BPF_K:
case BPF_JMP32 | BPF_JSLT | BPF_K:
if (rv_offset_check(&rvoff, off, i, ctx))
return -1;
emit_imm(RV_REG_T1, imm, ctx);
if (!is64)
emit_sext_32_rd(&rd, ctx);
emit(rv_blt(rd, RV_REG_T1, rvoff >> 1), ctx);
break;
case BPF_JMP | BPF_JSGE | BPF_K:
case BPF_JMP32 | BPF_JSGE | BPF_K:
if (rv_offset_check(&rvoff, off, i, ctx))
return -1;
emit_imm(RV_REG_T1, imm, ctx);
if (!is64)
emit_sext_32_rd(&rd, ctx);
emit(rv_bge(rd, RV_REG_T1, rvoff >> 1), ctx);
break;
case BPF_JMP | BPF_JSLE | BPF_K:
case BPF_JMP32 | BPF_JSLE | BPF_K:
if (rv_offset_check(&rvoff, off, i, ctx))
return -1;
emit_imm(RV_REG_T1, imm, ctx);
if (!is64)
emit_sext_32_rd(&rd, ctx);
emit(rv_bge(RV_REG_T1, rd, rvoff >> 1), ctx);
break;
case BPF_JMP | BPF_JSET | BPF_K:
case BPF_JMP32 | BPF_JSET | BPF_K:
if (rv_offset_check(&rvoff, off, i, ctx))
return -1;
rvoff = rv_offset(i, off, ctx);
s = ctx->ninsns;
emit_imm(RV_REG_T1, imm, ctx);
if (!is64)
emit_zext_32_rd_t1(&rd, ctx);
emit(rv_and(RV_REG_T1, rd, RV_REG_T1), ctx);
emit(rv_bne(RV_REG_T1, RV_REG_ZERO, rvoff >> 1), ctx);
if (!is64) {
if (is_signed_bpf_cond(BPF_OP(code)))
emit_sext_32_rd(&rd, ctx);
else
emit_zext_32_rd_t1(&rd, ctx);
}
e = ctx->ninsns;
/* Adjust for extra insns */
rvoff -= (e - s) << 2;
if (BPF_OP(code) == BPF_JSET) {
/* Adjust for and */
rvoff -= 4;
emit(rv_and(RV_REG_T1, rd, RV_REG_T1), ctx);
emit_branch(BPF_JNE, RV_REG_T1, RV_REG_ZERO, rvoff,
ctx);
} else {
emit_branch(BPF_OP(code), rd, RV_REG_T1, rvoff, ctx);
}
break;
/* function call */
case BPF_JMP | BPF_CALL:
{
bool fixed;
int i, ret;
int ret;
u64 addr;
mark_call(ctx);
@ -1215,20 +1240,9 @@ out_be:
&fixed);
if (ret < 0)
return ret;
if (fixed) {
emit_imm(RV_REG_T1, addr, ctx);
} else {
i = ctx->ninsns;
emit_imm(RV_REG_T1, addr, ctx);
for (i = ctx->ninsns - i; i < 8; i++) {
/* nop */
emit(rv_addi(RV_REG_ZERO, RV_REG_ZERO, 0),
ctx);
}
}
emit(rv_jalr(RV_REG_RA, RV_REG_T1, 0), ctx);
rd = bpf_to_rv_reg(BPF_REG_0, ctx);
emit(rv_addi(rd, RV_REG_A0, 0), ctx);
ret = emit_call(fixed, addr, ctx);
if (ret)
return ret;
break;
}
/* tail call */
@ -1243,9 +1257,7 @@ out_be:
break;
rvoff = epilogue_offset(ctx);
if (is_21b_check(rvoff, i))
return -1;
emit(rv_jal(RV_REG_ZERO, rvoff >> 1), ctx);
emit_jump_and_link(RV_REG_ZERO, rvoff, false, ctx);
break;
/* dst = imm64 */
@ -1426,6 +1438,10 @@ static void build_prologue(struct rv_jit_context *ctx)
{
int stack_adjust = 0, store_offset, bpf_stack_adjust;
bpf_stack_adjust = round_up(ctx->prog->aux->stack_depth, 16);
if (bpf_stack_adjust)
mark_fp(ctx);
if (seen_reg(RV_REG_RA, ctx))
stack_adjust += 8;
stack_adjust += 8; /* RV_REG_FP */
@ -1443,7 +1459,6 @@ static void build_prologue(struct rv_jit_context *ctx)
stack_adjust += 8;
stack_adjust = round_up(stack_adjust, 16);
bpf_stack_adjust = round_up(ctx->prog->aux->stack_depth, 16);
stack_adjust += bpf_stack_adjust;
store_offset = stack_adjust - 8;
@ -1502,10 +1517,10 @@ static void build_prologue(struct rv_jit_context *ctx)
static void build_epilogue(struct rv_jit_context *ctx)
{
__build_epilogue(RV_REG_RA, ctx);
__build_epilogue(false, ctx);
}
static int build_body(struct rv_jit_context *ctx, bool extra_pass)
static int build_body(struct rv_jit_context *ctx, bool extra_pass, int *offset)
{
const struct bpf_prog *prog = ctx->prog;
int i;
@ -1517,12 +1532,12 @@ static int build_body(struct rv_jit_context *ctx, bool extra_pass)
ret = emit_insn(insn, ctx, extra_pass);
if (ret > 0) {
i++;
if (ctx->insns == NULL)
ctx->offset[i] = ctx->ninsns;
if (offset)
offset[i] = ctx->ninsns;
continue;
}
if (ctx->insns == NULL)
ctx->offset[i] = ctx->ninsns;
if (offset)
offset[i] = ctx->ninsns;
if (ret)
return ret;
}
@ -1548,9 +1563,10 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
{
bool tmp_blinded = false, extra_pass = false;
struct bpf_prog *tmp, *orig_prog = prog;
int pass = 0, prev_ninsns = 0, i;
struct rv_jit_data *jit_data;
unsigned int image_size = 0;
struct rv_jit_context *ctx;
unsigned int image_size;
if (!prog->jit_requested)
return orig_prog;
@ -1587,33 +1603,59 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
prog = orig_prog;
goto out_offset;
}
/* First pass generates the ctx->offset, but does not emit an image. */
if (build_body(ctx, extra_pass)) {
prog = orig_prog;
goto out_offset;
for (i = 0; i < prog->len; i++) {
prev_ninsns += 32;
ctx->offset[i] = prev_ninsns;
}
build_prologue(ctx);
ctx->epilogue_offset = ctx->ninsns;
build_epilogue(ctx);
/* Allocate image, now that we know the size. */
image_size = sizeof(u32) * ctx->ninsns;
jit_data->header = bpf_jit_binary_alloc(image_size, &jit_data->image,
sizeof(u32),
bpf_fill_ill_insns);
if (!jit_data->header) {
for (i = 0; i < 16; i++) {
pass++;
ctx->ninsns = 0;
if (build_body(ctx, extra_pass, ctx->offset)) {
prog = orig_prog;
goto out_offset;
}
build_prologue(ctx);
ctx->epilogue_offset = ctx->ninsns;
build_epilogue(ctx);
if (ctx->ninsns == prev_ninsns) {
if (jit_data->header)
break;
image_size = sizeof(u32) * ctx->ninsns;
jit_data->header =
bpf_jit_binary_alloc(image_size,
&jit_data->image,
sizeof(u32),
bpf_fill_ill_insns);
if (!jit_data->header) {
prog = orig_prog;
goto out_offset;
}
ctx->insns = (u32 *)jit_data->image;
/* Now, when the image is allocated, the image
* can potentially shrink more (auipc/jalr ->
* jal).
*/
}
prev_ninsns = ctx->ninsns;
}
if (i == 16) {
pr_err("bpf-jit: image did not converge in <%d passes!\n", i);
bpf_jit_binary_free(jit_data->header);
prog = orig_prog;
goto out_offset;
}
/* Second, real pass, that acutally emits the image. */
ctx->insns = (u32 *)jit_data->image;
skip_init_ctx:
pass++;
ctx->ninsns = 0;
build_prologue(ctx);
if (build_body(ctx, extra_pass)) {
if (build_body(ctx, extra_pass, NULL)) {
bpf_jit_binary_free(jit_data->header);
prog = orig_prog;
goto out_offset;
@ -1621,7 +1663,7 @@ skip_init_ctx:
build_epilogue(ctx);
if (bpf_jit_enable > 1)
bpf_jit_dump(prog->len, image_size, 2, ctx->insns);
bpf_jit_dump(prog->len, image_size, pass, ctx->insns);
prog->bpf_func = (void *)ctx->insns;
prog->jited = 1;
@ -1641,3 +1683,16 @@ out:
tmp : orig_prog);
return prog;
}
void *bpf_jit_alloc_exec(unsigned long size)
{
return __vmalloc_node_range(size, PAGE_SIZE, BPF_JIT_REGION_START,
BPF_JIT_REGION_END, GFP_KERNEL,
PAGE_KERNEL_EXEC, 0, NUMA_NO_NODE,
__builtin_return_address(0));
}
void bpf_jit_free_exec(void *addr)
{
return vfree(addr);
}

View File

@ -247,7 +247,7 @@ static void uml_net_set_multicast_list(struct net_device *dev)
return;
}
static void uml_net_tx_timeout(struct net_device *dev)
static void uml_net_tx_timeout(struct net_device *dev, unsigned int txqueue)
{
netif_trans_update(dev);
netif_wake_queue(dev);

View File

@ -1332,7 +1332,7 @@ static void vector_net_set_multicast_list(struct net_device *dev)
return;
}
static void vector_net_tx_timeout(struct net_device *dev)
static void vector_net_tx_timeout(struct net_device *dev, unsigned int txqueue)
{
struct vector_private *vp = netdev_priv(dev);

View File

@ -93,6 +93,7 @@ config X86
select ARCH_USE_QUEUED_RWLOCKS
select ARCH_USE_QUEUED_SPINLOCKS
select ARCH_WANT_BATCHED_UNMAP_TLB_FLUSH
select ARCH_WANT_DEFAULT_BPF_JIT if X86_64
select ARCH_WANTS_DYNAMIC_TASK_STRUCT
select ARCH_WANT_HUGE_PMD_SHARE
select ARCH_WANTS_THP_SWAP if X86_64

View File

@ -10,10 +10,12 @@
#include <linux/if_vlan.h>
#include <linux/bpf.h>
#include <linux/memory.h>
#include <linux/sort.h>
#include <asm/extable.h>
#include <asm/set_memory.h>
#include <asm/nospec-branch.h>
#include <asm/text-patching.h>
#include <asm/asm-prototypes.h>
static u8 *emit_code(u8 *ptr, u32 bytes, unsigned int len)
{
@ -1326,7 +1328,7 @@ emit_jmp:
return proglen;
}
static void save_regs(struct btf_func_model *m, u8 **prog, int nr_args,
static void save_regs(const struct btf_func_model *m, u8 **prog, int nr_args,
int stack_size)
{
int i;
@ -1342,7 +1344,7 @@ static void save_regs(struct btf_func_model *m, u8 **prog, int nr_args,
-(stack_size - i * 8));
}
static void restore_regs(struct btf_func_model *m, u8 **prog, int nr_args,
static void restore_regs(const struct btf_func_model *m, u8 **prog, int nr_args,
int stack_size)
{
int i;
@ -1359,7 +1361,7 @@ static void restore_regs(struct btf_func_model *m, u8 **prog, int nr_args,
-(stack_size - i * 8));
}
static int invoke_bpf(struct btf_func_model *m, u8 **pprog,
static int invoke_bpf(const struct btf_func_model *m, u8 **pprog,
struct bpf_prog **progs, int prog_cnt, int stack_size)
{
u8 *prog = *pprog;
@ -1454,7 +1456,8 @@ static int invoke_bpf(struct btf_func_model *m, u8 **pprog,
* add rsp, 8 // skip eth_type_trans's frame
* ret // return to its caller
*/
int arch_prepare_bpf_trampoline(void *image, struct btf_func_model *m, u32 flags,
int arch_prepare_bpf_trampoline(void *image, void *image_end,
const struct btf_func_model *m, u32 flags,
struct bpf_prog **fentry_progs, int fentry_cnt,
struct bpf_prog **fexit_progs, int fexit_cnt,
void *orig_call)
@ -1521,15 +1524,160 @@ int arch_prepare_bpf_trampoline(void *image, struct btf_func_model *m, u32 flags
/* skip our return address and return to parent */
EMIT4(0x48, 0x83, 0xC4, 8); /* add rsp, 8 */
EMIT1(0xC3); /* ret */
/* One half of the page has active running trampoline.
* Another half is an area for next trampoline.
* Make sure the trampoline generation logic doesn't overflow.
*/
if (WARN_ON_ONCE(prog - (u8 *)image > PAGE_SIZE / 2 - BPF_INSN_SAFETY))
/* Make sure the trampoline generation logic doesn't overflow */
if (WARN_ON_ONCE(prog > (u8 *)image_end - BPF_INSN_SAFETY))
return -EFAULT;
return prog - (u8 *)image;
}
static int emit_cond_near_jump(u8 **pprog, void *func, void *ip, u8 jmp_cond)
{
u8 *prog = *pprog;
int cnt = 0;
s64 offset;
offset = func - (ip + 2 + 4);
if (!is_simm32(offset)) {
pr_err("Target %p is out of range\n", func);
return -EINVAL;
}
EMIT2_off32(0x0F, jmp_cond + 0x10, offset);
*pprog = prog;
return 0;
}
static void emit_nops(u8 **pprog, unsigned int len)
{
unsigned int i, noplen;
u8 *prog = *pprog;
int cnt = 0;
while (len > 0) {
noplen = len;
if (noplen > ASM_NOP_MAX)
noplen = ASM_NOP_MAX;
for (i = 0; i < noplen; i++)
EMIT1(ideal_nops[noplen][i]);
len -= noplen;
}
*pprog = prog;
}
static int emit_fallback_jump(u8 **pprog)
{
u8 *prog = *pprog;
int err = 0;
#ifdef CONFIG_RETPOLINE
/* Note that this assumes the the compiler uses external
* thunks for indirect calls. Both clang and GCC use the same
* naming convention for external thunks.
*/
err = emit_jump(&prog, __x86_indirect_thunk_rdx, prog);
#else
int cnt = 0;
EMIT2(0xFF, 0xE2); /* jmp rdx */
#endif
*pprog = prog;
return err;
}
static int emit_bpf_dispatcher(u8 **pprog, int a, int b, s64 *progs)
{
u8 *jg_reloc, *jg_target, *prog = *pprog;
int pivot, err, jg_bytes = 1, cnt = 0;
s64 jg_offset;
if (a == b) {
/* Leaf node of recursion, i.e. not a range of indices
* anymore.
*/
EMIT1(add_1mod(0x48, BPF_REG_3)); /* cmp rdx,func */
if (!is_simm32(progs[a]))
return -1;
EMIT2_off32(0x81, add_1reg(0xF8, BPF_REG_3),
progs[a]);
err = emit_cond_near_jump(&prog, /* je func */
(void *)progs[a], prog,
X86_JE);
if (err)
return err;
err = emit_fallback_jump(&prog); /* jmp thunk/indirect */
if (err)
return err;
*pprog = prog;
return 0;
}
/* Not a leaf node, so we pivot, and recursively descend into
* the lower and upper ranges.
*/
pivot = (b - a) / 2;
EMIT1(add_1mod(0x48, BPF_REG_3)); /* cmp rdx,func */
if (!is_simm32(progs[a + pivot]))
return -1;
EMIT2_off32(0x81, add_1reg(0xF8, BPF_REG_3), progs[a + pivot]);
if (pivot > 2) { /* jg upper_part */
/* Require near jump. */
jg_bytes = 4;
EMIT2_off32(0x0F, X86_JG + 0x10, 0);
} else {
EMIT2(X86_JG, 0);
}
jg_reloc = prog;
err = emit_bpf_dispatcher(&prog, a, a + pivot, /* emit lower_part */
progs);
if (err)
return err;
/* From Intel 64 and IA-32 Architectures Optimization
* Reference Manual, 3.4.1.4 Code Alignment, Assembly/Compiler
* Coding Rule 11: All branch targets should be 16-byte
* aligned.
*/
jg_target = PTR_ALIGN(prog, 16);
if (jg_target != prog)
emit_nops(&prog, jg_target - prog);
jg_offset = prog - jg_reloc;
emit_code(jg_reloc - jg_bytes, jg_offset, jg_bytes);
err = emit_bpf_dispatcher(&prog, a + pivot + 1, /* emit upper_part */
b, progs);
if (err)
return err;
*pprog = prog;
return 0;
}
static int cmp_ips(const void *a, const void *b)
{
const s64 *ipa = a;
const s64 *ipb = b;
if (*ipa > *ipb)
return 1;
if (*ipa < *ipb)
return -1;
return 0;
}
int arch_prepare_bpf_dispatcher(void *image, s64 *funcs, int num_funcs)
{
u8 *prog = image;
sort(funcs, num_funcs, sizeof(funcs[0]), cmp_ips, NULL);
return emit_bpf_dispatcher(&prog, 0, num_funcs - 1, funcs);
}
struct x64_jit_data {
struct bpf_binary_header *header;
int *addrs;

View File

@ -455,7 +455,7 @@ static void iss_net_set_multicast_list(struct net_device *dev)
{
}
static void iss_net_tx_timeout(struct net_device *dev)
static void iss_net_tx_timeout(struct net_device *dev, unsigned int txqueue)
{
}

View File

@ -1414,12 +1414,14 @@ fore200e_open(struct atm_vcc *vcc)
static void
fore200e_close(struct atm_vcc* vcc)
{
struct fore200e* fore200e = FORE200E_DEV(vcc->dev);
struct fore200e_vcc* fore200e_vcc;
struct fore200e* fore200e;
struct fore200e_vc_map* vc_map;
unsigned long flags;
ASSERT(vcc);
fore200e = FORE200E_DEV(vcc->dev);
ASSERT((vcc->vpi >= 0) && (vcc->vpi < 1<<FORE200E_VPI_BITS));
ASSERT((vcc->vci >= 0) && (vcc->vci < 1<<FORE200E_VCI_BITS));
@ -1464,10 +1466,10 @@ fore200e_close(struct atm_vcc* vcc)
static int
fore200e_send(struct atm_vcc *vcc, struct sk_buff *skb)
{
struct fore200e* fore200e = FORE200E_DEV(vcc->dev);
struct fore200e_vcc* fore200e_vcc = FORE200E_VCC(vcc);
struct fore200e* fore200e;
struct fore200e_vcc* fore200e_vcc;
struct fore200e_vc_map* vc_map;
struct host_txq* txq = &fore200e->host_txq;
struct host_txq* txq;
struct host_txq_entry* entry;
struct tpd* tpd;
struct tpd_haddr tpd_haddr;
@ -1480,9 +1482,18 @@ fore200e_send(struct atm_vcc *vcc, struct sk_buff *skb)
unsigned char* data;
unsigned long flags;
ASSERT(vcc);
ASSERT(fore200e);
ASSERT(fore200e_vcc);
if (!vcc)
return -EINVAL;
fore200e = FORE200E_DEV(vcc->dev);
fore200e_vcc = FORE200E_VCC(vcc);
if (!fore200e)
return -EINVAL;
txq = &fore200e->host_txq;
if (!fore200e_vcc)
return -EINVAL;
if (!test_bit(ATM_VF_READY, &vcc->flags)) {
DPRINTK(1, "VC %d.%d.%d not ready for tx\n", vcc->itf, vcc->vpi, vcc->vpi);

View File

@ -219,7 +219,7 @@ static s32 bcma_erom_get_mst_port(struct bcma_bus *bus, u32 __iomem **eromptr)
static u32 bcma_erom_get_addr_desc(struct bcma_bus *bus, u32 __iomem **eromptr,
u32 type, u8 port)
{
u32 addrl, addrh, sizel, sizeh = 0;
u32 addrl, addrh, sizeh = 0;
u32 size;
u32 ent = bcma_erom_get_ent(bus, eromptr);
@ -239,12 +239,9 @@ static u32 bcma_erom_get_addr_desc(struct bcma_bus *bus, u32 __iomem **eromptr,
if ((ent & SCAN_ADDR_SZ) == SCAN_ADDR_SZ_SZD) {
size = bcma_erom_get_ent(bus, eromptr);
sizel = size & SCAN_SIZE_SZ;
if (size & SCAN_SIZE_SG32)
sizeh = bcma_erom_get_ent(bus, eromptr);
} else
sizel = SCAN_ADDR_SZ_BASE <<
((ent & SCAN_ADDR_SZ) >> SCAN_ADDR_SZ_SHIFT);
}
return addrl;
}

View File

@ -36,6 +36,7 @@ int btbcm_check_bdaddr(struct hci_dev *hdev)
HCI_INIT_TIMEOUT);
if (IS_ERR(skb)) {
int err = PTR_ERR(skb);
bt_dev_err(hdev, "BCM: Reading device address failed (%d)", err);
return err;
}
@ -107,6 +108,52 @@ int btbcm_set_bdaddr(struct hci_dev *hdev, const bdaddr_t *bdaddr)
}
EXPORT_SYMBOL_GPL(btbcm_set_bdaddr);
int btbcm_read_pcm_int_params(struct hci_dev *hdev,
struct bcm_set_pcm_int_params *params)
{
struct sk_buff *skb;
int err = 0;
skb = __hci_cmd_sync(hdev, 0xfc1d, 0, NULL, HCI_INIT_TIMEOUT);
if (IS_ERR(skb)) {
err = PTR_ERR(skb);
bt_dev_err(hdev, "BCM: Read PCM int params failed (%d)", err);
return err;
}
if (skb->len != 6 || skb->data[0]) {
bt_dev_err(hdev, "BCM: Read PCM int params length mismatch");
kfree_skb(skb);
return -EIO;
}
if (params)
memcpy(params, skb->data + 1, 5);
kfree_skb(skb);
return 0;
}
EXPORT_SYMBOL_GPL(btbcm_read_pcm_int_params);
int btbcm_write_pcm_int_params(struct hci_dev *hdev,
const struct bcm_set_pcm_int_params *params)
{
struct sk_buff *skb;
int err;
skb = __hci_cmd_sync(hdev, 0xfc1c, 5, params, HCI_INIT_TIMEOUT);
if (IS_ERR(skb)) {
err = PTR_ERR(skb);
bt_dev_err(hdev, "BCM: Write PCM int params failed (%d)", err);
return err;
}
kfree_skb(skb);
return 0;
}
EXPORT_SYMBOL_GPL(btbcm_write_pcm_int_params);
int btbcm_patchram(struct hci_dev *hdev, const struct firmware *fw)
{
const struct hci_command_hdr *cmd;
@ -177,6 +224,7 @@ static int btbcm_reset(struct hci_dev *hdev)
skb = __hci_cmd_sync(hdev, HCI_OP_RESET, 0, NULL, HCI_INIT_TIMEOUT);
if (IS_ERR(skb)) {
int err = PTR_ERR(skb);
bt_dev_err(hdev, "BCM: Reset failed (%d)", err);
return err;
}

View File

@ -54,6 +54,10 @@ struct bcm_set_pcm_format_params {
int btbcm_check_bdaddr(struct hci_dev *hdev);
int btbcm_set_bdaddr(struct hci_dev *hdev, const bdaddr_t *bdaddr);
int btbcm_patchram(struct hci_dev *hdev, const struct firmware *fw);
int btbcm_read_pcm_int_params(struct hci_dev *hdev,
struct bcm_set_pcm_int_params *params);
int btbcm_write_pcm_int_params(struct hci_dev *hdev,
const struct bcm_set_pcm_int_params *params);
int btbcm_setup_patchram(struct hci_dev *hdev);
int btbcm_setup_apple(struct hci_dev *hdev);
@ -74,6 +78,18 @@ static inline int btbcm_set_bdaddr(struct hci_dev *hdev, const bdaddr_t *bdaddr)
return -EOPNOTSUPP;
}
static inline int btbcm_read_pcm_int_params(struct hci_dev *hdev,
struct bcm_set_pcm_int_params *params)
{
return -EOPNOTSUPP;
}
static inline int btbcm_write_pcm_int_params(struct hci_dev *hdev,
const struct bcm_set_pcm_int_params *params)
{
return -EOPNOTSUPP;
}
static inline int btbcm_patchram(struct hci_dev *hdev, const struct firmware *fw)
{
return -EOPNOTSUPP;

View File

@ -370,11 +370,11 @@ static int rtlbt_parse_firmware(struct hci_dev *hdev,
* the end.
*/
len = patch_length;
buf = kmemdup(btrtl_dev->fw_data + patch_offset, patch_length,
GFP_KERNEL);
buf = kvmalloc(patch_length, GFP_KERNEL);
if (!buf)
return -ENOMEM;
memcpy(buf, btrtl_dev->fw_data + patch_offset, patch_length - 4);
memcpy(buf + patch_length - 4, &epatch_info->fw_version, 4);
*_buf = buf;
@ -460,8 +460,10 @@ static int rtl_load_file(struct hci_dev *hdev, const char *name, u8 **buff)
if (ret < 0)
return ret;
ret = fw->size;
*buff = kmemdup(fw->data, ret, GFP_KERNEL);
if (!*buff)
*buff = kvmalloc(fw->size, GFP_KERNEL);
if (*buff)
memcpy(*buff, fw->data, ret);
else
ret = -ENOMEM;
release_firmware(fw);
@ -499,14 +501,14 @@ static int btrtl_setup_rtl8723b(struct hci_dev *hdev,
goto out;
if (btrtl_dev->cfg_len > 0) {
tbuff = kzalloc(ret + btrtl_dev->cfg_len, GFP_KERNEL);
tbuff = kvzalloc(ret + btrtl_dev->cfg_len, GFP_KERNEL);
if (!tbuff) {
ret = -ENOMEM;
goto out;
}
memcpy(tbuff, fw_data, ret);
kfree(fw_data);
kvfree(fw_data);
memcpy(tbuff + ret, btrtl_dev->cfg_data, btrtl_dev->cfg_len);
ret += btrtl_dev->cfg_len;
@ -519,14 +521,14 @@ static int btrtl_setup_rtl8723b(struct hci_dev *hdev,
ret = rtl_download_firmware(hdev, fw_data, ret);
out:
kfree(fw_data);
kvfree(fw_data);
return ret;
}
void btrtl_free(struct btrtl_device_info *btrtl_dev)
{
kfree(btrtl_dev->fw_data);
kfree(btrtl_dev->cfg_data);
kvfree(btrtl_dev->fw_data);
kvfree(btrtl_dev->cfg_data);
kfree(btrtl_dev);
}
EXPORT_SYMBOL_GPL(btrtl_free);

View File

@ -145,11 +145,20 @@ static int btsdio_rx_packet(struct btsdio_data *data)
data->hdev->stat.byte_rx += len;
hci_skb_pkt_type(skb) = hdr[3];
err = hci_recv_frame(data->hdev, skb);
if (err < 0)
return err;
switch (hdr[3]) {
case HCI_EVENT_PKT:
case HCI_ACLDATA_PKT:
case HCI_SCODATA_PKT:
case HCI_ISODATA_PKT:
hci_skb_pkt_type(skb) = hdr[3];
err = hci_recv_frame(data->hdev, skb);
if (err < 0)
return err;
break;
default:
kfree_skb(skb);
return -EINVAL;
}
sdio_writeb(data->func, 0x00, REG_PC_RRT, NULL);

View File

@ -266,6 +266,7 @@ static const struct usb_device_id blacklist_table[] = {
{ USB_DEVICE(0x04ca, 0x3015), .driver_info = BTUSB_QCA_ROME },
{ USB_DEVICE(0x04ca, 0x3016), .driver_info = BTUSB_QCA_ROME },
{ USB_DEVICE(0x04ca, 0x301a), .driver_info = BTUSB_QCA_ROME },
{ USB_DEVICE(0x04ca, 0x3021), .driver_info = BTUSB_QCA_ROME },
{ USB_DEVICE(0x13d3, 0x3491), .driver_info = BTUSB_QCA_ROME },
{ USB_DEVICE(0x13d3, 0x3496), .driver_info = BTUSB_QCA_ROME },
{ USB_DEVICE(0x13d3, 0x3501), .driver_info = BTUSB_QCA_ROME },
@ -552,9 +553,9 @@ static void btusb_rtl_cmd_timeout(struct hci_dev *hdev)
}
bt_dev_err(hdev, "Reset Realtek device via gpio");
gpiod_set_value_cansleep(reset_gpio, 0);
msleep(200);
gpiod_set_value_cansleep(reset_gpio, 1);
msleep(200);
gpiod_set_value_cansleep(reset_gpio, 0);
}
static inline void btusb_free_frags(struct btusb_data *data)
@ -2602,7 +2603,7 @@ static void btusb_mtk_wmt_recv(struct urb *urb)
* and being processed the events from there then.
*/
if (test_bit(BTUSB_TX_WAIT_VND_EVT, &data->flags)) {
data->evt_skb = skb_clone(skb, GFP_KERNEL);
data->evt_skb = skb_clone(skb, GFP_ATOMIC);
if (!data->evt_skb)
goto err_out;
}
@ -2867,7 +2868,7 @@ static int btusb_mtk_setup_firmware(struct hci_dev *hdev, const char *fwname)
err = btusb_mtk_hci_wmt_sync(hdev, &wmt_params);
if (err < 0) {
bt_dev_err(hdev, "Failed to send wmt rst (%d)", err);
return err;
goto err_release_fw;
}
/* Wait a few moments for firmware activation done */
@ -3832,6 +3833,10 @@ static int btusb_probe(struct usb_interface *intf,
* (DEVICE_REMOTE_WAKEUP)
*/
set_bit(BTUSB_WAKEUP_DISABLE, &data->flags);
err = usb_autopm_get_interface(intf);
if (err < 0)
goto out_free_dev;
}
if (id->driver_info & BTUSB_AMP) {

View File

@ -13,6 +13,7 @@
#include <linux/module.h>
#include <linux/acpi.h>
#include <linux/of.h>
#include <linux/of_irq.h>
#include <linux/property.h>
#include <linux/platform_data/x86/apple.h>
#include <linux/platform_device.h>
@ -47,6 +48,15 @@
#define BCM_NUM_SUPPLIES 2
/**
* struct bcm_device_data - device specific data
* @no_early_set_baudrate: Disallow set baudrate before driver setup()
*/
struct bcm_device_data {
bool no_early_set_baudrate;
bool drive_rts_on_open;
};
/**
* struct bcm_device - device driver resources
* @serdev_hu: HCI UART controller struct
@ -79,6 +89,7 @@
* @hu: pointer to HCI UART controller struct,
* used to disable flow control during runtime suspend and system sleep
* @is_suspended: whether flow control is currently disabled
* @no_early_set_baudrate: don't set_baudrate before setup()
*/
struct bcm_device {
/* Must be the first member, hci_serdev.c expects this. */
@ -112,6 +123,9 @@ struct bcm_device {
struct hci_uart *hu;
bool is_suspended;
#endif
bool no_early_set_baudrate;
bool drive_rts_on_open;
u8 pcm_int_params[5];
};
/* generic bcm uart resources */
@ -445,11 +459,22 @@ static int bcm_open(struct hci_uart *hu)
out:
if (bcm->dev) {
hci_uart_set_flow_control(hu, true);
if (bcm->dev->drive_rts_on_open)
hci_uart_set_flow_control(hu, true);
hu->init_speed = bcm->dev->init_speed;
hu->oper_speed = bcm->dev->oper_speed;
/* If oper_speed is set, ldisc/serdev will set the baudrate
* before calling setup()
*/
if (!bcm->dev->no_early_set_baudrate)
hu->oper_speed = bcm->dev->oper_speed;
err = bcm_gpio_set_power(bcm->dev, true);
hci_uart_set_flow_control(hu, false);
if (bcm->dev->drive_rts_on_open)
hci_uart_set_flow_control(hu, false);
if (err)
goto err_unset_hu;
}
@ -565,6 +590,8 @@ static int bcm_setup(struct hci_uart *hu)
/* Operational speed if any */
if (hu->oper_speed)
speed = hu->oper_speed;
else if (bcm->dev && bcm->dev->oper_speed)
speed = bcm->dev->oper_speed;
else if (hu->proto->oper_speed)
speed = hu->proto->oper_speed;
else
@ -576,6 +603,16 @@ static int bcm_setup(struct hci_uart *hu)
host_set_baudrate(hu, speed);
}
/* PCM parameters if provided */
if (bcm->dev && bcm->dev->pcm_int_params[0] != 0xff) {
struct bcm_set_pcm_int_params params;
btbcm_read_pcm_int_params(hu->hdev, &params);
memcpy(&params, bcm->dev->pcm_int_params, 5);
btbcm_write_pcm_int_params(hu->hdev, &params);
}
finalize:
release_firmware(fw);
@ -1113,6 +1150,10 @@ static int bcm_acpi_probe(struct bcm_device *dev)
static int bcm_of_probe(struct bcm_device *bdev)
{
device_property_read_u32(bdev->dev, "max-speed", &bdev->oper_speed);
device_property_read_u8_array(bdev->dev, "brcm,bt-pcm-int-params",
bdev->pcm_int_params, 5);
bdev->irq = of_irq_get_byname(bdev->dev->of_node, "host-wakeup");
return 0;
}
@ -1128,6 +1169,9 @@ static int bcm_probe(struct platform_device *pdev)
dev->dev = &pdev->dev;
dev->irq = platform_get_irq(pdev, 0);
/* Initialize routing field to an unused value */
dev->pcm_int_params[0] = 0xff;
if (has_acpi_companion(&pdev->dev)) {
ret = bcm_acpi_probe(dev);
if (ret)
@ -1374,6 +1418,7 @@ static struct platform_driver bcm_driver = {
static int bcm_serdev_probe(struct serdev_device *serdev)
{
struct bcm_device *bcmdev;
const struct bcm_device_data *data;
int err;
bcmdev = devm_kzalloc(&serdev->dev, sizeof(*bcmdev), GFP_KERNEL);
@ -1387,6 +1432,9 @@ static int bcm_serdev_probe(struct serdev_device *serdev)
bcmdev->serdev_hu.serdev = serdev;
serdev_device_set_drvdata(serdev, bcmdev);
/* Initialize routing field to an unused value */
bcmdev->pcm_int_params[0] = 0xff;
if (has_acpi_companion(&serdev->dev))
err = bcm_acpi_probe(bcmdev);
else
@ -1408,6 +1456,12 @@ static int bcm_serdev_probe(struct serdev_device *serdev)
if (err)
dev_err(&serdev->dev, "Failed to power down\n");
data = device_get_match_data(bcmdev->dev);
if (data) {
bcmdev->no_early_set_baudrate = data->no_early_set_baudrate;
bcmdev->drive_rts_on_open = data->drive_rts_on_open;
}
return hci_uart_register_device(&bcmdev->serdev_hu, &bcm_proto);
}
@ -1419,12 +1473,21 @@ static void bcm_serdev_remove(struct serdev_device *serdev)
}
#ifdef CONFIG_OF
static struct bcm_device_data bcm4354_device_data = {
.no_early_set_baudrate = true,
};
static struct bcm_device_data bcm43438_device_data = {
.drive_rts_on_open = true,
};
static const struct of_device_id bcm_bluetooth_of_match[] = {
{ .compatible = "brcm,bcm20702a1" },
{ .compatible = "brcm,bcm4329-bt" },
{ .compatible = "brcm,bcm4345c5" },
{ .compatible = "brcm,bcm4330-bt" },
{ .compatible = "brcm,bcm43438-bt" },
{ .compatible = "brcm,bcm43540-bt" },
{ .compatible = "brcm,bcm43438-bt", .data = &bcm43438_device_data },
{ .compatible = "brcm,bcm43540-bt", .data = &bcm4354_device_data },
{ .compatible = "brcm,bcm4335a0" },
{ },
};

View File

@ -103,6 +103,7 @@ static const struct h4_recv_pkt h4_recv_pkts[] = {
{ H4_RECV_ACL, .recv = hci_recv_frame },
{ H4_RECV_SCO, .recv = hci_recv_frame },
{ H4_RECV_EVENT, .recv = hci_recv_frame },
{ H4_RECV_ISO, .recv = hci_recv_frame },
};
/* Recv data */

View File

@ -385,6 +385,7 @@ static void h5_complete_rx_pkt(struct hci_uart *hu)
case HCI_EVENT_PKT:
case HCI_ACLDATA_PKT:
case HCI_SCODATA_PKT:
case HCI_ISODATA_PKT:
hci_skb_pkt_type(h5->rx_skb) = H5_HDR_PKT_TYPE(hdr);
/* Remove Three-wire header */
@ -594,6 +595,7 @@ static int h5_enqueue(struct hci_uart *hu, struct sk_buff *skb)
break;
case HCI_SCODATA_PKT:
case HCI_ISODATA_PKT:
skb_queue_tail(&h5->unrel, skb);
break;
@ -636,6 +638,7 @@ static bool valid_packet_type(u8 type)
case HCI_ACLDATA_PKT:
case HCI_COMMAND_PKT:
case HCI_SCODATA_PKT:
case HCI_ISODATA_PKT:
case HCI_3WIRE_LINK_PKT:
case HCI_3WIRE_ACK_PKT:
return true;

View File

@ -20,6 +20,7 @@
#include <linux/completion.h>
#include <linux/debugfs.h>
#include <linux/delay.h>
#include <linux/devcoredump.h>
#include <linux/device.h>
#include <linux/gpio/consumer.h>
#include <linux/mod_devicetable.h>
@ -46,6 +47,7 @@
#define IBS_BTSOC_TX_IDLE_TIMEOUT_MS 40
#define IBS_HOST_TX_IDLE_TIMEOUT_MS 2000
#define CMD_TRANS_TIMEOUT_MS 100
#define MEMDUMP_TIMEOUT_MS 8000
/* susclk rate */
#define SUSCLK_RATE_32KHZ 32768
@ -53,12 +55,24 @@
/* Controller debug log header */
#define QCA_DEBUG_HANDLE 0x2EDC
/* max retry count when init fails */
#define MAX_INIT_RETRIES 3
/* Controller dump header */
#define QCA_SSR_DUMP_HANDLE 0x0108
#define QCA_DUMP_PACKET_SIZE 255
#define QCA_LAST_SEQUENCE_NUM 0xFFFF
#define QCA_CRASHBYTE_PACKET_LEN 1096
#define QCA_MEMDUMP_BYTE 0xFB
enum qca_flags {
QCA_IBS_ENABLED,
QCA_DROP_VENDOR_EVENT,
QCA_SUSPENDING,
QCA_MEMDUMP_COLLECTION
};
/* HCI_IBS transmit side sleep protocol states */
enum tx_ibs_states {
HCI_IBS_TX_ASLEEP,
@ -81,11 +95,40 @@ enum hci_ibs_clock_state_vote {
HCI_IBS_RX_VOTE_CLOCK_OFF,
};
/* Controller memory dump states */
enum qca_memdump_states {
QCA_MEMDUMP_IDLE,
QCA_MEMDUMP_COLLECTING,
QCA_MEMDUMP_COLLECTED,
QCA_MEMDUMP_TIMEOUT,
};
struct qca_memdump_data {
char *memdump_buf_head;
char *memdump_buf_tail;
u32 current_seq_no;
u32 received_dump;
};
struct qca_memdump_event_hdr {
__u8 evt;
__u8 plen;
__u16 opcode;
__u16 seq_no;
__u8 reserved;
} __packed;
struct qca_dump_size {
u32 dump_size;
} __packed;
struct qca_data {
struct hci_uart *hu;
struct sk_buff *rx_skb;
struct sk_buff_head txq;
struct sk_buff_head tx_wait_q; /* HCI_IBS wait queue */
struct sk_buff_head rx_memdump_q; /* Memdump wait queue */
spinlock_t hci_ibs_lock; /* HCI_IBS state lock */
u8 tx_ibs_state; /* HCI_IBS transmit side power state*/
u8 rx_ibs_state; /* HCI_IBS receive side power state */
@ -95,14 +138,18 @@ struct qca_data {
u32 tx_idle_delay;
struct timer_list wake_retrans_timer;
u32 wake_retrans;
struct timer_list memdump_timer;
struct workqueue_struct *workqueue;
struct work_struct ws_awake_rx;
struct work_struct ws_awake_device;
struct work_struct ws_rx_vote_off;
struct work_struct ws_tx_vote_off;
struct work_struct ctrl_memdump_evt;
struct qca_memdump_data *qca_memdump;
unsigned long flags;
struct completion drop_ev_comp;
wait_queue_head_t suspend_wait_q;
enum qca_memdump_states memdump_state;
/* For debugging purpose */
u64 ibs_sent_wacks;
@ -167,6 +214,7 @@ static int qca_regulator_enable(struct qca_serdev *qcadev);
static void qca_regulator_disable(struct qca_serdev *qcadev);
static void qca_power_shutdown(struct hci_uart *hu);
static int qca_power_off(struct hci_dev *hdev);
static void qca_controller_memdump(struct work_struct *work);
static enum qca_btsoc_type qca_soc_type(struct hci_uart *hu)
{
@ -474,12 +522,28 @@ static void hci_ibs_wake_retrans_timeout(struct timer_list *t)
hci_uart_tx_wakeup(hu);
}
static void hci_memdump_timeout(struct timer_list *t)
{
struct qca_data *qca = from_timer(qca, t, tx_idle_timer);
struct hci_uart *hu = qca->hu;
struct qca_memdump_data *qca_memdump = qca->qca_memdump;
char *memdump_buf = qca_memdump->memdump_buf_tail;
bt_dev_err(hu->hdev, "clearing allocated memory due to memdump timeout");
/* Inject hw error event to reset the device and driver. */
hci_reset_dev(hu->hdev);
vfree(memdump_buf);
kfree(qca_memdump);
qca->memdump_state = QCA_MEMDUMP_TIMEOUT;
del_timer(&qca->memdump_timer);
cancel_work_sync(&qca->ctrl_memdump_evt);
}
/* Initialize protocol */
static int qca_open(struct hci_uart *hu)
{
struct qca_serdev *qcadev;
struct qca_data *qca;
int ret;
BT_DBG("hu %p qca_open", hu);
@ -492,6 +556,7 @@ static int qca_open(struct hci_uart *hu)
skb_queue_head_init(&qca->txq);
skb_queue_head_init(&qca->tx_wait_q);
skb_queue_head_init(&qca->rx_memdump_q);
spin_lock_init(&qca->hci_ibs_lock);
qca->workqueue = alloc_ordered_workqueue("qca_wq", 0);
if (!qca->workqueue) {
@ -504,7 +569,7 @@ static int qca_open(struct hci_uart *hu)
INIT_WORK(&qca->ws_awake_device, qca_wq_awake_device);
INIT_WORK(&qca->ws_rx_vote_off, qca_wq_serial_rx_clock_vote_off);
INIT_WORK(&qca->ws_tx_vote_off, qca_wq_serial_tx_clock_vote_off);
INIT_WORK(&qca->ctrl_memdump_evt, qca_controller_memdump);
init_waitqueue_head(&qca->suspend_wait_q);
qca->hu = hu;
@ -519,23 +584,10 @@ static int qca_open(struct hci_uart *hu)
hu->priv = qca;
if (hu->serdev) {
qcadev = serdev_device_get_drvdata(hu->serdev);
if (!qca_is_wcn399x(qcadev->btsoc_type)) {
gpiod_set_value_cansleep(qcadev->bt_en, 1);
/* Controller needs time to bootup. */
msleep(150);
} else {
if (qca_is_wcn399x(qcadev->btsoc_type)) {
hu->init_speed = qcadev->init_speed;
hu->oper_speed = qcadev->oper_speed;
ret = qca_regulator_enable(qcadev);
if (ret) {
destroy_workqueue(qca->workqueue);
kfree_skb(qca->rx_skb);
hu->priv = NULL;
kfree(qca);
return ret;
}
}
}
@ -544,6 +596,7 @@ static int qca_open(struct hci_uart *hu)
timer_setup(&qca->tx_idle_timer, hci_ibs_tx_idle_timeout, 0);
qca->tx_idle_delay = IBS_HOST_TX_IDLE_TIMEOUT_MS;
timer_setup(&qca->memdump_timer, hci_memdump_timeout, 0);
BT_DBG("HCI_UART_QCA open, tx_idle_delay=%u, wake_retrans=%u",
qca->tx_idle_delay, qca->wake_retrans);
@ -613,7 +666,6 @@ static int qca_flush(struct hci_uart *hu)
/* Close protocol */
static int qca_close(struct hci_uart *hu)
{
struct qca_serdev *qcadev;
struct qca_data *qca = hu->priv;
BT_DBG("hu %p qca close", hu);
@ -622,19 +674,14 @@ static int qca_close(struct hci_uart *hu)
skb_queue_purge(&qca->tx_wait_q);
skb_queue_purge(&qca->txq);
skb_queue_purge(&qca->rx_memdump_q);
del_timer(&qca->tx_idle_timer);
del_timer(&qca->wake_retrans_timer);
del_timer(&qca->memdump_timer);
destroy_workqueue(qca->workqueue);
qca->hu = NULL;
if (hu->serdev) {
qcadev = serdev_device_get_drvdata(hu->serdev);
if (qca_is_wcn399x(qcadev->btsoc_type))
qca_power_shutdown(hu);
else
gpiod_set_value_cansleep(qcadev->bt_en, 0);
}
qca_power_shutdown(hu);
kfree_skb(qca->rx_skb);
@ -900,6 +947,125 @@ static int qca_recv_acl_data(struct hci_dev *hdev, struct sk_buff *skb)
return hci_recv_frame(hdev, skb);
}
static void qca_controller_memdump(struct work_struct *work)
{
struct qca_data *qca = container_of(work, struct qca_data,
ctrl_memdump_evt);
struct hci_uart *hu = qca->hu;
struct sk_buff *skb;
struct qca_memdump_event_hdr *cmd_hdr;
struct qca_memdump_data *qca_memdump = qca->qca_memdump;
struct qca_dump_size *dump;
char *memdump_buf;
char nullBuff[QCA_DUMP_PACKET_SIZE] = { 0 };
u16 seq_no;
u32 dump_size;
while ((skb = skb_dequeue(&qca->rx_memdump_q))) {
if (!qca_memdump) {
qca_memdump = kzalloc(sizeof(struct qca_memdump_data),
GFP_ATOMIC);
if (!qca_memdump)
return;
qca->qca_memdump = qca_memdump;
}
qca->memdump_state = QCA_MEMDUMP_COLLECTING;
cmd_hdr = (void *) skb->data;
seq_no = __le16_to_cpu(cmd_hdr->seq_no);
skb_pull(skb, sizeof(struct qca_memdump_event_hdr));
if (!seq_no) {
/* This is the first frame of memdump packet from
* the controller, Disable IBS to recevie dump
* with out any interruption, ideally time required for
* the controller to send the dump is 8 seconds. let us
* start timer to handle this asynchronous activity.
*/
clear_bit(QCA_IBS_ENABLED, &qca->flags);
set_bit(QCA_MEMDUMP_COLLECTION, &qca->flags);
dump = (void *) skb->data;
dump_size = __le32_to_cpu(dump->dump_size);
if (!(dump_size)) {
bt_dev_err(hu->hdev, "Rx invalid memdump size");
kfree_skb(skb);
return;
}
bt_dev_info(hu->hdev, "QCA collecting dump of size:%u",
dump_size);
mod_timer(&qca->memdump_timer, (jiffies +
msecs_to_jiffies(MEMDUMP_TIMEOUT_MS)));
skb_pull(skb, sizeof(dump_size));
memdump_buf = vmalloc(dump_size);
qca_memdump->memdump_buf_head = memdump_buf;
qca_memdump->memdump_buf_tail = memdump_buf;
}
memdump_buf = qca_memdump->memdump_buf_tail;
/* If sequence no 0 is missed then there is no point in
* accepting the other sequences.
*/
if (!memdump_buf) {
bt_dev_err(hu->hdev, "QCA: Discarding other packets");
kfree(qca_memdump);
kfree_skb(skb);
qca->qca_memdump = NULL;
return;
}
/* There could be chance of missing some packets from
* the controller. In such cases let us store the dummy
* packets in the buffer.
*/
while ((seq_no > qca_memdump->current_seq_no + 1) &&
seq_no != QCA_LAST_SEQUENCE_NUM) {
bt_dev_err(hu->hdev, "QCA controller missed packet:%d",
qca_memdump->current_seq_no);
memcpy(memdump_buf, nullBuff, QCA_DUMP_PACKET_SIZE);
memdump_buf = memdump_buf + QCA_DUMP_PACKET_SIZE;
qca_memdump->received_dump += QCA_DUMP_PACKET_SIZE;
qca_memdump->current_seq_no++;
}
memcpy(memdump_buf, (unsigned char *) skb->data, skb->len);
memdump_buf = memdump_buf + skb->len;
qca_memdump->memdump_buf_tail = memdump_buf;
qca_memdump->current_seq_no = seq_no + 1;
qca_memdump->received_dump += skb->len;
qca->qca_memdump = qca_memdump;
kfree_skb(skb);
if (seq_no == QCA_LAST_SEQUENCE_NUM) {
bt_dev_info(hu->hdev, "QCA writing crash dump of size %d bytes",
qca_memdump->received_dump);
memdump_buf = qca_memdump->memdump_buf_head;
dev_coredumpv(&hu->serdev->dev, memdump_buf,
qca_memdump->received_dump, GFP_KERNEL);
del_timer(&qca->memdump_timer);
kfree(qca->qca_memdump);
qca->qca_memdump = NULL;
qca->memdump_state = QCA_MEMDUMP_COLLECTED;
}
}
}
int qca_controller_memdump_event(struct hci_dev *hdev, struct sk_buff *skb)
{
struct hci_uart *hu = hci_get_drvdata(hdev);
struct qca_data *qca = hu->priv;
skb_queue_tail(&qca->rx_memdump_q, skb);
queue_work(qca->workqueue, &qca->ctrl_memdump_evt);
return 0;
}
static int qca_recv_event(struct hci_dev *hdev, struct sk_buff *skb)
{
struct hci_uart *hu = hci_get_drvdata(hdev);
@ -925,6 +1091,14 @@ static int qca_recv_event(struct hci_dev *hdev, struct sk_buff *skb)
return 0;
}
/* We receive chip memory dump as an event packet, With a dedicated
* handler followed by a hardware error event. When this event is
* received we store dump into a file before closing hci. This
* dump will help in triaging the issues.
*/
if ((skb->data[0] == HCI_VENDOR_PKT) &&
(get_unaligned_be16(skb->data + 2) == QCA_SSR_DUMP_HANDLE))
return qca_controller_memdump_event(hdev, skb);
return hci_recv_frame(hdev, skb);
}
@ -1203,6 +1377,91 @@ error:
return ret;
}
static int qca_send_crashbuffer(struct hci_uart *hu)
{
struct qca_data *qca = hu->priv;
struct sk_buff *skb;
skb = bt_skb_alloc(QCA_CRASHBYTE_PACKET_LEN, GFP_KERNEL);
if (!skb) {
bt_dev_err(hu->hdev, "Failed to allocate memory for skb packet");
return -ENOMEM;
}
/* We forcefully crash the controller, by sending 0xfb byte for
* 1024 times. We also might have chance of losing data, To be
* on safer side we send 1096 bytes to the SoC.
*/
memset(skb_put(skb, QCA_CRASHBYTE_PACKET_LEN), QCA_MEMDUMP_BYTE,
QCA_CRASHBYTE_PACKET_LEN);
hci_skb_pkt_type(skb) = HCI_COMMAND_PKT;
bt_dev_info(hu->hdev, "crash the soc to collect controller dump");
skb_queue_tail(&qca->txq, skb);
hci_uart_tx_wakeup(hu);
return 0;
}
static void qca_wait_for_dump_collection(struct hci_dev *hdev)
{
struct hci_uart *hu = hci_get_drvdata(hdev);
struct qca_data *qca = hu->priv;
struct qca_memdump_data *qca_memdump = qca->qca_memdump;
char *memdump_buf = NULL;
wait_on_bit_timeout(&qca->flags, QCA_MEMDUMP_COLLECTION,
TASK_UNINTERRUPTIBLE, MEMDUMP_TIMEOUT_MS);
clear_bit(QCA_MEMDUMP_COLLECTION, &qca->flags);
if (qca->memdump_state == QCA_MEMDUMP_IDLE) {
bt_dev_err(hu->hdev, "Clearing the buffers due to timeout");
if (qca_memdump)
memdump_buf = qca_memdump->memdump_buf_tail;
vfree(memdump_buf);
kfree(qca_memdump);
qca->memdump_state = QCA_MEMDUMP_TIMEOUT;
del_timer(&qca->memdump_timer);
cancel_work_sync(&qca->ctrl_memdump_evt);
}
}
static void qca_hw_error(struct hci_dev *hdev, u8 code)
{
struct hci_uart *hu = hci_get_drvdata(hdev);
struct qca_data *qca = hu->priv;
bt_dev_info(hdev, "mem_dump_status: %d", qca->memdump_state);
if (qca->memdump_state == QCA_MEMDUMP_IDLE) {
/* If hardware error event received for other than QCA
* soc memory dump event, then we need to crash the SOC
* and wait here for 8 seconds to get the dump packets.
* This will block main thread to be on hold until we
* collect dump.
*/
set_bit(QCA_MEMDUMP_COLLECTION, &qca->flags);
qca_send_crashbuffer(hu);
qca_wait_for_dump_collection(hdev);
} else if (qca->memdump_state == QCA_MEMDUMP_COLLECTING) {
/* Let us wait here until memory dump collected or
* memory dump timer expired.
*/
bt_dev_info(hdev, "waiting for dump to complete");
qca_wait_for_dump_collection(hdev);
}
}
static void qca_cmd_timeout(struct hci_dev *hdev)
{
struct hci_uart *hu = hci_get_drvdata(hdev);
struct qca_data *qca = hu->priv;
if (qca->memdump_state == QCA_MEMDUMP_IDLE)
qca_send_crashbuffer(hu);
else
bt_dev_info(hdev, "Dump collection is in process");
}
static int qca_wcn3990_init(struct hci_uart *hu)
{
struct qca_serdev *qcadev;
@ -1253,11 +1512,37 @@ static int qca_wcn3990_init(struct hci_uart *hu)
return 0;
}
static int qca_power_on(struct hci_dev *hdev)
{
struct hci_uart *hu = hci_get_drvdata(hdev);
enum qca_btsoc_type soc_type = qca_soc_type(hu);
struct qca_serdev *qcadev;
int ret = 0;
/* Non-serdev device usually is powered by external power
* and don't need additional action in driver for power on
*/
if (!hu->serdev)
return 0;
if (qca_is_wcn399x(soc_type)) {
ret = qca_wcn3990_init(hu);
} else {
qcadev = serdev_device_get_drvdata(hu->serdev);
gpiod_set_value_cansleep(qcadev->bt_en, 1);
/* Controller needs time to bootup. */
msleep(150);
}
return ret;
}
static int qca_setup(struct hci_uart *hu)
{
struct hci_dev *hdev = hu->hdev;
struct qca_data *qca = hu->priv;
unsigned int speed, qca_baudrate = QCA_BAUDRATE_115200;
unsigned int retries = 0;
enum qca_btsoc_type soc_type = qca_soc_type(hu);
const char *firmware_name = qca_get_firmware_name(hu);
int ret;
@ -1275,24 +1560,21 @@ static int qca_setup(struct hci_uart *hu)
*/
set_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, &hdev->quirks);
if (qca_is_wcn399x(soc_type)) {
bt_dev_info(hdev, "setting up wcn3990");
bt_dev_info(hdev, "setting up %s",
qca_is_wcn399x(soc_type) ? "wcn399x" : "ROME");
/* Enable NON_PERSISTENT_SETUP QUIRK to ensure to execute
* setup for every hci up.
*/
set_bit(HCI_QUIRK_NON_PERSISTENT_SETUP, &hdev->quirks);
retry:
ret = qca_power_on(hdev);
if (ret)
return ret;
if (qca_is_wcn399x(soc_type)) {
set_bit(HCI_QUIRK_USE_BDADDR_PROPERTY, &hdev->quirks);
hu->hdev->shutdown = qca_power_off;
ret = qca_wcn3990_init(hu);
if (ret)
return ret;
ret = qca_read_soc_version(hdev, &soc_ver, soc_type);
if (ret)
return ret;
} else {
bt_dev_info(hdev, "ROME setup");
qca_set_speed(hu, QCA_INIT_SPEED);
}
@ -1320,6 +1602,8 @@ static int qca_setup(struct hci_uart *hu)
if (!ret) {
set_bit(QCA_IBS_ENABLED, &qca->flags);
qca_debugfs_init(hdev);
hu->hdev->hw_error = qca_hw_error;
hu->hdev->cmd_timeout = qca_cmd_timeout;
} else if (ret == -ENOENT) {
/* No patch/nvm-config found, run with original fw/config */
ret = 0;
@ -1329,6 +1613,20 @@ static int qca_setup(struct hci_uart *hu)
* patch/nvm-config is found, so run with original fw/config.
*/
ret = 0;
} else {
if (retries < MAX_INIT_RETRIES) {
qca_power_shutdown(hu);
if (hu->serdev) {
serdev_device_close(hu->serdev);
ret = serdev_device_open(hu->serdev);
if (ret) {
bt_dev_err(hdev, "failed to open port");
return ret;
}
}
retries++;
goto retry;
}
}
/* Setup bdaddr */
@ -1393,6 +1691,7 @@ static void qca_power_shutdown(struct hci_uart *hu)
struct qca_serdev *qcadev;
struct qca_data *qca = hu->priv;
unsigned long flags;
enum qca_btsoc_type soc_type = qca_soc_type(hu);
qcadev = serdev_device_get_drvdata(hu->serdev);
@ -1405,20 +1704,36 @@ static void qca_power_shutdown(struct hci_uart *hu)
qca_flush(hu);
spin_unlock_irqrestore(&qca->hci_ibs_lock, flags);
host_set_baudrate(hu, 2400);
qca_send_power_pulse(hu, false);
qca_regulator_disable(qcadev);
hu->hdev->hw_error = NULL;
hu->hdev->cmd_timeout = NULL;
/* Non-serdev device usually is powered by external power
* and don't need additional action in driver for power down
*/
if (!hu->serdev)
return;
if (qca_is_wcn399x(soc_type)) {
host_set_baudrate(hu, 2400);
qca_send_power_pulse(hu, false);
qca_regulator_disable(qcadev);
} else {
gpiod_set_value_cansleep(qcadev->bt_en, 0);
}
}
static int qca_power_off(struct hci_dev *hdev)
{
struct hci_uart *hu = hci_get_drvdata(hdev);
struct qca_data *qca = hu->priv;
/* Perform pre shutdown command */
qca_send_pre_shutdown_cmd(hdev);
usleep_range(8000, 10000);
/* Stop sending shutdown command if soc crashes. */
if (qca->memdump_state == QCA_MEMDUMP_IDLE) {
qca_send_pre_shutdown_cmd(hdev);
usleep_range(8000, 10000);
}
qca->memdump_state = QCA_MEMDUMP_IDLE;
qca_power_shutdown(hu);
return 0;
}
@ -1493,6 +1808,7 @@ static int qca_init_regulators(struct qca_power *qca,
static int qca_serdev_probe(struct serdev_device *serdev)
{
struct qca_serdev *qcadev;
struct hci_dev *hdev;
const struct qca_vreg_data *data;
int err;
@ -1501,7 +1817,7 @@ static int qca_serdev_probe(struct serdev_device *serdev)
return -ENOMEM;
qcadev->serdev_hu.serdev = serdev;
data = of_device_get_match_data(&serdev->dev);
data = device_get_match_data(&serdev->dev);
serdev_device_set_drvdata(serdev, qcadev);
device_property_read_string(&serdev->dev, "firmware-name",
&qcadev->firmware_name);
@ -1518,7 +1834,7 @@ static int qca_serdev_probe(struct serdev_device *serdev)
data->num_vregs);
if (err) {
BT_ERR("Failed to init regulators:%d", err);
goto out;
return err;
}
qcadev->bt_power->vregs_on = false;
@ -1531,7 +1847,7 @@ static int qca_serdev_probe(struct serdev_device *serdev)
err = hci_uart_register_device(&qcadev->serdev_hu, &qca_proto);
if (err) {
BT_ERR("wcn3990 serdev registration failed");
goto out;
return err;
}
} else {
qcadev->btsoc_type = QCA_ROME;
@ -1557,12 +1873,18 @@ static int qca_serdev_probe(struct serdev_device *serdev)
return err;
err = hci_uart_register_device(&qcadev->serdev_hu, &qca_proto);
if (err)
if (err) {
BT_ERR("Rome serdev registration failed");
clk_disable_unprepare(qcadev->susclk);
return err;
}
}
out: return err;
hdev = qcadev->serdev_hu.hdev;
set_bit(HCI_QUIRK_NON_PERSISTENT_SETUP, &hdev->quirks);
hdev->shutdown = qca_power_off;
return 0;
}
static void qca_serdev_remove(struct serdev_device *serdev)

View File

@ -143,6 +143,13 @@ struct h4_recv_pkt {
.lsize = 1, \
.maxlen = HCI_MAX_EVENT_SIZE
#define H4_RECV_ISO \
.type = HCI_ISODATA_PKT, \
.hlen = HCI_ISO_HDR_SIZE, \
.loff = 2, \
.lsize = 2, \
.maxlen = HCI_MAX_FRAME_SIZE \
struct sk_buff *h4_recv_buf(struct hci_dev *hdev, struct sk_buff *skb,
const unsigned char *buffer, int count,
const struct h4_recv_pkt *pkts, int pkts_count);

View File

@ -178,6 +178,7 @@ static inline ssize_t vhci_get_user(struct vhci_data *data,
case HCI_EVENT_PKT:
case HCI_ACLDATA_PKT:
case HCI_SCODATA_PKT:
case HCI_ISODATA_PKT:
if (!data->hdev) {
kfree_skb(skb);
return -ENODEV;

View File

@ -4169,7 +4169,7 @@ static int hdlcdev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
*
* dev pointer to network device structure
*/
static void hdlcdev_tx_timeout(struct net_device *dev)
static void hdlcdev_tx_timeout(struct net_device *dev, unsigned int txqueue)
{
MGSLPC_INFO *info = dev_to_port(dev);
unsigned long flags;

View File

@ -1286,7 +1286,7 @@ static int chtls_pass_accept_req(struct chtls_dev *cdev, struct sk_buff *skb)
ctx = (struct listen_ctx *)data;
lsk = ctx->lsk;
if (unlikely(tid >= cdev->tids->ntids)) {
if (unlikely(tid_out_of_range(cdev->tids, tid))) {
pr_info("passive open TID %u too large\n", tid);
return 1;
}

View File

@ -181,15 +181,14 @@ EXPORT_SYMBOL(ib_umem_find_best_pgsz);
/**
* ib_umem_get - Pin and DMA map userspace memory.
*
* @udata: userspace context to pin memory for
* @device: IB device to connect UMEM
* @addr: userspace virtual address to start at
* @size: length of region to pin
* @access: IB_ACCESS_xxx flags for memory being pinned
*/
struct ib_umem *ib_umem_get(struct ib_udata *udata, unsigned long addr,
struct ib_umem *ib_umem_get(struct ib_device *device, unsigned long addr,
size_t size, int access)
{
struct ib_ucontext *context;
struct ib_umem *umem;
struct page **page_list;
unsigned long lock_limit;
@ -201,14 +200,6 @@ struct ib_umem *ib_umem_get(struct ib_udata *udata, unsigned long addr,
struct scatterlist *sg;
unsigned int gup_flags = FOLL_WRITE;
if (!udata)
return ERR_PTR(-EIO);
context = container_of(udata, struct uverbs_attr_bundle, driver_udata)
->context;
if (!context)
return ERR_PTR(-EIO);
/*
* If the combination of the addr and size requested for this memory
* region causes an integer overflow, return error.
@ -226,7 +217,7 @@ struct ib_umem *ib_umem_get(struct ib_udata *udata, unsigned long addr,
umem = kzalloc(sizeof(*umem), GFP_KERNEL);
if (!umem)
return ERR_PTR(-ENOMEM);
umem->ibdev = context->device;
umem->ibdev = device;
umem->length = size;
umem->address = addr;
umem->writable = ib_access_writable(access);
@ -281,7 +272,7 @@ struct ib_umem *ib_umem_get(struct ib_udata *udata, unsigned long addr,
npages -= ret;
sg = ib_umem_add_sg_table(sg, page_list, ret,
dma_get_max_seg_size(context->device->dma_device),
dma_get_max_seg_size(device->dma_device),
&umem->sg_nents);
up_read(&mm->mmap_sem);
@ -289,10 +280,10 @@ struct ib_umem *ib_umem_get(struct ib_udata *udata, unsigned long addr,
sg_mark_end(sg);
umem->nmap = ib_dma_map_sg(context->device,
umem->sg_head.sgl,
umem->sg_nents,
DMA_BIDIRECTIONAL);
umem->nmap = ib_dma_map_sg(device,
umem->sg_head.sgl,
umem->sg_nents,
DMA_BIDIRECTIONAL);
if (!umem->nmap) {
ret = -ENOMEM;
@ -303,7 +294,7 @@ struct ib_umem *ib_umem_get(struct ib_udata *udata, unsigned long addr,
goto out;
umem_release:
__ib_umem_release(context->device, umem, 0);
__ib_umem_release(device, umem, 0);
vma:
atomic64_sub(ib_umem_num_pages(umem), &mm->pinned_vm);
out:

View File

@ -110,15 +110,12 @@ out_page_list:
* They exist only to hold the per_mm reference to help the driver create
* children umems.
*
* @udata: udata from the syscall being used to create the umem
* @device: IB device to create UMEM
* @access: ib_reg_mr access flags
*/
struct ib_umem_odp *ib_umem_odp_alloc_implicit(struct ib_udata *udata,
struct ib_umem_odp *ib_umem_odp_alloc_implicit(struct ib_device *device,
int access)
{
struct ib_ucontext *context =
container_of(udata, struct uverbs_attr_bundle, driver_udata)
->context;
struct ib_umem *umem;
struct ib_umem_odp *umem_odp;
int ret;
@ -126,14 +123,11 @@ struct ib_umem_odp *ib_umem_odp_alloc_implicit(struct ib_udata *udata,
if (access & IB_ACCESS_HUGETLB)
return ERR_PTR(-EINVAL);
if (!context)
return ERR_PTR(-EIO);
umem_odp = kzalloc(sizeof(*umem_odp), GFP_KERNEL);
if (!umem_odp)
return ERR_PTR(-ENOMEM);
umem = &umem_odp->umem;
umem->ibdev = context->device;
umem->ibdev = device;
umem->writable = ib_access_writable(access);
umem->owning_mm = current->mm;
umem_odp->is_implicit_odp = 1;
@ -201,7 +195,7 @@ EXPORT_SYMBOL(ib_umem_odp_alloc_child);
/**
* ib_umem_odp_get - Create a umem_odp for a userspace va
*
* @udata: userspace context to pin memory for
* @device: IB device struct to get UMEM
* @addr: userspace virtual address to start at
* @size: length of region to pin
* @access: IB_ACCESS_xxx flags for memory being pinned
@ -210,23 +204,14 @@ EXPORT_SYMBOL(ib_umem_odp_alloc_child);
* pinning, instead, stores the mm for future page fault handling in
* conjunction with MMU notifiers.
*/
struct ib_umem_odp *ib_umem_odp_get(struct ib_udata *udata, unsigned long addr,
size_t size, int access,
struct ib_umem_odp *ib_umem_odp_get(struct ib_device *device,
unsigned long addr, size_t size, int access,
const struct mmu_interval_notifier_ops *ops)
{
struct ib_umem_odp *umem_odp;
struct ib_ucontext *context;
struct mm_struct *mm;
int ret;
if (!udata)
return ERR_PTR(-EIO);
context = container_of(udata, struct uverbs_attr_bundle, driver_udata)
->context;
if (!context)
return ERR_PTR(-EIO);
if (WARN_ON_ONCE(!(access & IB_ACCESS_ON_DEMAND)))
return ERR_PTR(-EINVAL);
@ -234,7 +219,7 @@ struct ib_umem_odp *ib_umem_odp_get(struct ib_udata *udata, unsigned long addr,
if (!umem_odp)
return ERR_PTR(-ENOMEM);
umem_odp->umem.ibdev = context->device;
umem_odp->umem.ibdev = device;
umem_odp->umem.length = size;
umem_odp->umem.address = addr;
umem_odp->umem.writable = ib_access_writable(access);

View File

@ -1990,6 +1990,47 @@ EXPORT_SYMBOL(ib_resize_cq);
/* Memory regions */
struct ib_mr *ib_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
u64 virt_addr, int access_flags)
{
struct ib_mr *mr;
if (access_flags & IB_ACCESS_ON_DEMAND) {
if (!(pd->device->attrs.device_cap_flags &
IB_DEVICE_ON_DEMAND_PAGING)) {
pr_debug("ODP support not available\n");
return ERR_PTR(-EINVAL);
}
}
mr = pd->device->ops.reg_user_mr(pd, start, length, virt_addr,
access_flags, NULL);
if (IS_ERR(mr))
return mr;
mr->device = pd->device;
mr->pd = pd;
mr->dm = NULL;
atomic_inc(&pd->usecnt);
mr->res.type = RDMA_RESTRACK_MR;
rdma_restrack_kadd(&mr->res);
return mr;
}
EXPORT_SYMBOL(ib_reg_user_mr);
int ib_advise_mr(struct ib_pd *pd, enum ib_uverbs_advise_mr_advice advice,
u32 flags, struct ib_sge *sg_list, u32 num_sge)
{
if (!pd->device->ops.advise_mr)
return -EOPNOTSUPP;
return pd->device->ops.advise_mr(pd, advice, flags, sg_list, num_sge,
NULL);
}
EXPORT_SYMBOL(ib_advise_mr);
int ib_dereg_mr_user(struct ib_mr *mr, struct ib_udata *udata)
{
struct ib_pd *pd = mr->pd;

View File

@ -837,7 +837,8 @@ static int bnxt_re_init_user_qp(struct bnxt_re_dev *rdev, struct bnxt_re_pd *pd,
bytes += (qplib_qp->sq.max_wqe * psn_sz);
}
bytes = PAGE_ALIGN(bytes);
umem = ib_umem_get(udata, ureq.qpsva, bytes, IB_ACCESS_LOCAL_WRITE);
umem = ib_umem_get(&rdev->ibdev, ureq.qpsva, bytes,
IB_ACCESS_LOCAL_WRITE);
if (IS_ERR(umem))
return PTR_ERR(umem);
@ -850,7 +851,7 @@ static int bnxt_re_init_user_qp(struct bnxt_re_dev *rdev, struct bnxt_re_pd *pd,
if (!qp->qplib_qp.srq) {
bytes = (qplib_qp->rq.max_wqe * BNXT_QPLIB_MAX_RQE_ENTRY_SIZE);
bytes = PAGE_ALIGN(bytes);
umem = ib_umem_get(udata, ureq.qprva, bytes,
umem = ib_umem_get(&rdev->ibdev, ureq.qprva, bytes,
IB_ACCESS_LOCAL_WRITE);
if (IS_ERR(umem))
goto rqfail;
@ -1304,7 +1305,8 @@ static int bnxt_re_init_user_srq(struct bnxt_re_dev *rdev,
bytes = (qplib_srq->max_wqe * BNXT_QPLIB_MAX_RQE_ENTRY_SIZE);
bytes = PAGE_ALIGN(bytes);
umem = ib_umem_get(udata, ureq.srqva, bytes, IB_ACCESS_LOCAL_WRITE);
umem = ib_umem_get(&rdev->ibdev, ureq.srqva, bytes,
IB_ACCESS_LOCAL_WRITE);
if (IS_ERR(umem))
return PTR_ERR(umem);
@ -2545,7 +2547,7 @@ int bnxt_re_create_cq(struct ib_cq *ibcq, const struct ib_cq_init_attr *attr,
goto fail;
}
cq->umem = ib_umem_get(udata, req.cq_va,
cq->umem = ib_umem_get(&rdev->ibdev, req.cq_va,
entries * sizeof(struct cq_base),
IB_ACCESS_LOCAL_WRITE);
if (IS_ERR(cq->umem)) {
@ -3514,7 +3516,7 @@ struct ib_mr *bnxt_re_reg_user_mr(struct ib_pd *ib_pd, u64 start, u64 length,
/* The fixed portion of the rkey is the same as the lkey */
mr->ib_mr.rkey = mr->qplib_mr.rkey;
umem = ib_umem_get(udata, start, length, mr_access_flags);
umem = ib_umem_get(&rdev->ibdev, start, length, mr_access_flags);
if (IS_ERR(umem)) {
dev_err(rdev_to_dev(rdev), "Failed to get umem");
rc = -EFAULT;

View File

@ -543,7 +543,7 @@ struct ib_mr *c4iw_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
mhp->rhp = rhp;
mhp->umem = ib_umem_get(udata, start, length, acc);
mhp->umem = ib_umem_get(pd->device, start, length, acc);
if (IS_ERR(mhp->umem))
goto err_free_skb;

View File

@ -1358,7 +1358,7 @@ struct ib_mr *efa_reg_mr(struct ib_pd *ibpd, u64 start, u64 length,
int inline_size;
int err;
if (udata->inlen &&
if (udata && udata->inlen &&
!ib_is_udata_cleared(udata, 0, sizeof(udata->inlen))) {
ibdev_dbg(&dev->ibdev,
"Incompatible ABI params, udata not cleared\n");
@ -1384,7 +1384,7 @@ struct ib_mr *efa_reg_mr(struct ib_pd *ibpd, u64 start, u64 length,
goto err_out;
}
mr->umem = ib_umem_get(udata, start, length, access_flags);
mr->umem = ib_umem_get(ibpd->device, start, length, access_flags);
if (IS_ERR(mr->umem)) {
err = PTR_ERR(mr->umem);
ibdev_dbg(&dev->ibdev,

View File

@ -163,7 +163,7 @@ static int get_cq_umem(struct hns_roce_dev *hr_dev, struct hns_roce_cq *hr_cq,
u32 npages;
int ret;
*umem = ib_umem_get(udata, ucmd.buf_addr, buf->size,
*umem = ib_umem_get(&hr_dev->ib_dev, ucmd.buf_addr, buf->size,
IB_ACCESS_LOCAL_WRITE);
if (IS_ERR(*umem))
return PTR_ERR(*umem);

View File

@ -31,7 +31,8 @@ int hns_roce_db_map_user(struct hns_roce_ucontext *context,
refcount_set(&page->refcount, 1);
page->user_virt = page_addr;
page->umem = ib_umem_get(udata, page_addr, PAGE_SIZE, 0);
page->umem = ib_umem_get(context->ibucontext.device, page_addr,
PAGE_SIZE, 0);
if (IS_ERR(page->umem)) {
ret = PTR_ERR(page->umem);
kfree(page);

View File

@ -1145,7 +1145,7 @@ struct ib_mr *hns_roce_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
if (!mr)
return ERR_PTR(-ENOMEM);
mr->umem = ib_umem_get(udata, start, length, access_flags);
mr->umem = ib_umem_get(pd->device, start, length, access_flags);
if (IS_ERR(mr->umem)) {
ret = PTR_ERR(mr->umem);
goto err_free;
@ -1230,7 +1230,7 @@ static int rereg_mr_trans(struct ib_mr *ibmr, int flags,
}
ib_umem_release(mr->umem);
mr->umem = ib_umem_get(udata, start, length, mr_access_flags);
mr->umem = ib_umem_get(ibmr->device, start, length, mr_access_flags);
if (IS_ERR(mr->umem)) {
ret = PTR_ERR(mr->umem);
mr->umem = NULL;

View File

@ -744,7 +744,7 @@ static int hns_roce_create_qp_common(struct hns_roce_dev *hr_dev,
goto err_alloc_rq_inline_buf;
}
hr_qp->umem = ib_umem_get(udata, ucmd.buf_addr,
hr_qp->umem = ib_umem_get(ib_pd->device, ucmd.buf_addr,
hr_qp->buff_size, 0);
if (IS_ERR(hr_qp->umem)) {
dev_err(dev, "ib_umem_get error for create qp\n");

View File

@ -186,7 +186,8 @@ static int create_user_srq(struct hns_roce_srq *srq, struct ib_udata *udata,
if (ib_copy_from_udata(&ucmd, udata, sizeof(ucmd)))
return -EFAULT;
srq->umem = ib_umem_get(udata, ucmd.buf_addr, srq_buf_size, 0);
srq->umem =
ib_umem_get(srq->ibsrq.device, ucmd.buf_addr, srq_buf_size, 0);
if (IS_ERR(srq->umem))
return PTR_ERR(srq->umem);
@ -205,7 +206,7 @@ static int create_user_srq(struct hns_roce_srq *srq, struct ib_udata *udata,
goto err_user_srq_mtt;
/* config index queue BA */
srq->idx_que.umem = ib_umem_get(udata, ucmd.que_addr,
srq->idx_que.umem = ib_umem_get(srq->ibsrq.device, ucmd.que_addr,
srq->idx_que.buf_size, 0);
if (IS_ERR(srq->idx_que.umem)) {
dev_err(hr_dev->dev, "ib_umem_get error for index queue\n");

View File

@ -1756,12 +1756,15 @@ static struct ib_mr *i40iw_reg_user_mr(struct ib_pd *pd,
int ret;
int pg_shift;
if (!udata)
return ERR_PTR(-EOPNOTSUPP);
if (iwdev->closing)
return ERR_PTR(-ENODEV);
if (length > I40IW_MAX_MR_SIZE)
return ERR_PTR(-EINVAL);
region = ib_umem_get(udata, start, length, acc);
region = ib_umem_get(pd->device, start, length, acc);
if (IS_ERR(region))
return (struct ib_mr *)region;

View File

@ -144,7 +144,7 @@ static int mlx4_ib_get_cq_umem(struct mlx4_ib_dev *dev, struct ib_udata *udata,
int shift;
int n;
*umem = ib_umem_get(udata, buf_addr, cqe * cqe_size,
*umem = ib_umem_get(&dev->ib_dev, buf_addr, cqe * cqe_size,
IB_ACCESS_LOCAL_WRITE);
if (IS_ERR(*umem))
return PTR_ERR(*umem);

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