Merge bd2463ac7d ("Merge git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-next") into android-common
Baby steps in the 5.6-rc1 merge cycle to make things easier to review and debug. Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> Change-Id: I4c44b3c32065ea0ed8175b31665f2a4195a27300
This commit is contained in:
@@ -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.
|
||||
@@ -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];
|
||||
};
|
||||
};
|
||||
|
||||
@@ -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 = <ð1>;
|
||||
|
||||
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>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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>;
|
||||
};
|
||||
@@ -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>;
|
||||
};
|
||||
};
|
||||
};
|
||||
@@ -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.
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
@@ -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.
|
||||
@@ -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
|
||||
|
||||
@@ -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 | |
|
||||
| +----------------------------> |
|
||||
+--------+ +--------------------------+
|
||||
@@ -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.
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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.
|
||||
@@ -1,5 +0,0 @@
|
||||
fw_load_policy [DEVICE, GENERIC]
|
||||
Configuration mode: permanent
|
||||
|
||||
reset_dev_on_drv_probe [DEVICE, GENERIC]
|
||||
Configuration mode: permanent
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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, it’s 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 }
|
||||
}
|
||||
@@ -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 | |
|
||||
| +----------------------------> |
|
||||
+--------+ +--------------------------+
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
+20
-1
@@ -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
|
||||
=======
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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
|
||||
@@ -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.
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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.
|
||||
@@ -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
|
||||
@@ -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
|
||||
=================================== =====================================
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
===========================
|
||||
|
||||
@@ -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::
|
||||
|
||||
|
||||
+43
-4
@@ -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
|
||||
|
||||
@@ -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,
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
|
||||
@@ -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,
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -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,
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -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,
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -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,
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@@ -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,
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
+13
-17
@@ -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 */
|
||||
}
|
||||
|
||||
|
||||
@@ -72,6 +72,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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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 = <ð1>;
|
||||
|
||||
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 {
|
||||
|
||||
@@ -84,3 +84,16 @@
|
||||
ð1 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&switch_port1 {
|
||||
label = "lan0";
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&phy_port0 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&phy_port4 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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__ */
|
||||
+294
-239
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -95,6 +95,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
|
||||
|
||||
+157
-9
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
+18
-7
@@ -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);
|
||||
|
||||
+2
-5
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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, ¶ms);
|
||||
|
||||
memcpy(¶ms, bcm->dev->pcm_int_params, 5);
|
||||
btbcm_write_pcm_int_params(hu->hdev, ¶ms);
|
||||
}
|
||||
|
||||
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" },
|
||||
{ },
|
||||
};
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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;
|
||||
|
||||
+370
-48
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user