Merge git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-next
Pull networking updates from David Miller: 1) Add WireGuard 2) Add HE and TWT support to ath11k driver, from John Crispin. 3) Add ESP in TCP encapsulation support, from Sabrina Dubroca. 4) Add variable window congestion control to TIPC, from Jon Maloy. 5) Add BCM84881 PHY driver, from Russell King. 6) Start adding netlink support for ethtool operations, from Michal Kubecek. 7) Add XDP drop and TX action support to ena driver, from Sameeh Jubran. 8) Add new ipv4 route notifications so that mlxsw driver does not have to handle identical routes itself. From Ido Schimmel. 9) Add BPF dynamic program extensions, from Alexei Starovoitov. 10) Support RX and TX timestamping in igc, from Vinicius Costa Gomes. 11) Add support for macsec HW offloading, from Antoine Tenart. 12) Add initial support for MPTCP protocol, from Christoph Paasch, Matthieu Baerts, Florian Westphal, Peter Krystad, and many others. 13) Add Octeontx2 PF support, from Sunil Goutham, Geetha sowjanya, Linu Cherian, and others. * git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-next: (1469 commits) net: phy: add default ARCH_BCM_IPROC for MDIO_BCM_IPROC udp: segment looped gso packets correctly netem: change mailing list qed: FW 8.42.2.0 debug features qed: rt init valid initialization changed qed: Debug feature: ilt and mdump qed: FW 8.42.2.0 Add fw overlay feature qed: FW 8.42.2.0 HSI changes qed: FW 8.42.2.0 iscsi/fcoe changes qed: Add abstraction for different hsi values per chip qed: FW 8.42.2.0 Additional ll2 type qed: Use dmae to write to widebus registers in fw_funcs qed: FW 8.42.2.0 Parser offsets modified qed: FW 8.42.2.0 Queue Manager changes qed: FW 8.42.2.0 Expose new registers and change windows qed: FW 8.42.2.0 Internal ram offsets modifications MAINTAINERS: Add entry for Marvell OcteonTX2 Physical Function driver Documentation: net: octeontx2: Add RVU HW and drivers overview octeontx2-pf: ethtool RSS config support octeontx2-pf: Add basic ethtool support ...
This commit is contained in:
commit
bd2463ac7d
63
Documentation/ABI/testing/sysfs-bus-mdio
Normal file
63
Documentation/ABI/testing/sysfs-bus-mdio
Normal file
|
@ -0,0 +1,63 @@
|
|||
What: /sys/bus/mdio_bus/devices/.../statistics/
|
||||
Date: January 2020
|
||||
KernelVersion: 5.6
|
||||
Contact: netdev@vger.kernel.org
|
||||
Description:
|
||||
This folder contains statistics about global and per
|
||||
MDIO bus address statistics.
|
||||
|
||||
What: /sys/bus/mdio_bus/devices/.../statistics/transfers
|
||||
Date: January 2020
|
||||
KernelVersion: 5.6
|
||||
Contact: netdev@vger.kernel.org
|
||||
Description:
|
||||
Total number of transfers for this MDIO bus.
|
||||
|
||||
What: /sys/bus/mdio_bus/devices/.../statistics/errors
|
||||
Date: January 2020
|
||||
KernelVersion: 5.6
|
||||
Contact: netdev@vger.kernel.org
|
||||
Description:
|
||||
Total number of transfer errors for this MDIO bus.
|
||||
|
||||
What: /sys/bus/mdio_bus/devices/.../statistics/writes
|
||||
Date: January 2020
|
||||
KernelVersion: 5.6
|
||||
Contact: netdev@vger.kernel.org
|
||||
Description:
|
||||
Total number of write transactions for this MDIO bus.
|
||||
|
||||
What: /sys/bus/mdio_bus/devices/.../statistics/reads
|
||||
Date: January 2020
|
||||
KernelVersion: 5.6
|
||||
Contact: netdev@vger.kernel.org
|
||||
Description:
|
||||
Total number of read transactions for this MDIO bus.
|
||||
|
||||
What: /sys/bus/mdio_bus/devices/.../statistics/transfers_<addr>
|
||||
Date: January 2020
|
||||
KernelVersion: 5.6
|
||||
Contact: netdev@vger.kernel.org
|
||||
Description:
|
||||
Total number of transfers for this MDIO bus address.
|
||||
|
||||
What: /sys/bus/mdio_bus/devices/.../statistics/errors_<addr>
|
||||
Date: January 2020
|
||||
KernelVersion: 5.6
|
||||
Contact: netdev@vger.kernel.org
|
||||
Description:
|
||||
Total number of transfer errors for this MDIO bus address.
|
||||
|
||||
What: /sys/bus/mdio_bus/devices/.../statistics/writes_<addr>
|
||||
Date: January 2020
|
||||
KernelVersion: 5.6
|
||||
Contact: netdev@vger.kernel.org
|
||||
Description:
|
||||
Total number of write transactions for this MDIO bus address.
|
||||
|
||||
What: /sys/bus/mdio_bus/devices/.../statistics/reads_<addr>
|
||||
Date: January 2020
|
||||
KernelVersion: 5.6
|
||||
Contact: netdev@vger.kernel.org
|
||||
Description:
|
||||
Total number of read transactions for this MDIO bus address.
|
|
@ -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];
|
||||
};
|
||||
};
|
||||
|
|
148
Documentation/devicetree/bindings/net/dsa/ar9331.txt
Normal file
148
Documentation/devicetree/bindings/net/dsa/ar9331.txt
Normal file
|
@ -0,0 +1,148 @@
|
|||
Atheros AR9331 built-in switch
|
||||
=============================
|
||||
|
||||
It is a switch built-in to Atheros AR9331 WiSoC and addressable over internal
|
||||
MDIO bus. All PHYs are built-in as well.
|
||||
|
||||
Required properties:
|
||||
|
||||
- compatible: should be: "qca,ar9331-switch"
|
||||
- reg: Address on the MII bus for the switch.
|
||||
- resets : Must contain an entry for each entry in reset-names.
|
||||
- reset-names : Must include the following entries: "switch"
|
||||
- interrupt-parent: Phandle to the parent interrupt controller
|
||||
- interrupts: IRQ line for the switch
|
||||
- interrupt-controller: Indicates the switch is itself an interrupt
|
||||
controller. This is used for the PHY interrupts.
|
||||
- #interrupt-cells: must be 1
|
||||
- mdio: Container of PHY and devices on the switches MDIO bus.
|
||||
|
||||
See Documentation/devicetree/bindings/net/dsa/dsa.txt for a list of additional
|
||||
required and optional properties.
|
||||
Examples:
|
||||
|
||||
eth0: ethernet@19000000 {
|
||||
compatible = "qca,ar9330-eth";
|
||||
reg = <0x19000000 0x200>;
|
||||
interrupts = <4>;
|
||||
|
||||
resets = <&rst 9>, <&rst 22>;
|
||||
reset-names = "mac", "mdio";
|
||||
clocks = <&pll ATH79_CLK_AHB>, <&pll ATH79_CLK_AHB>;
|
||||
clock-names = "eth", "mdio";
|
||||
|
||||
phy-mode = "mii";
|
||||
phy-handle = <&phy_port4>;
|
||||
};
|
||||
|
||||
eth1: ethernet@1a000000 {
|
||||
compatible = "qca,ar9330-eth";
|
||||
reg = <0x1a000000 0x200>;
|
||||
interrupts = <5>;
|
||||
resets = <&rst 13>, <&rst 23>;
|
||||
reset-names = "mac", "mdio";
|
||||
clocks = <&pll ATH79_CLK_AHB>, <&pll ATH79_CLK_AHB>;
|
||||
clock-names = "eth", "mdio";
|
||||
|
||||
phy-mode = "gmii";
|
||||
|
||||
fixed-link {
|
||||
speed = <1000>;
|
||||
full-duplex;
|
||||
};
|
||||
|
||||
mdio {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
switch10: switch@10 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
compatible = "qca,ar9331-switch";
|
||||
reg = <0x10>;
|
||||
resets = <&rst 8>;
|
||||
reset-names = "switch";
|
||||
|
||||
interrupt-parent = <&miscintc>;
|
||||
interrupts = <12>;
|
||||
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <1>;
|
||||
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
switch_port0: port@0 {
|
||||
reg = <0x0>;
|
||||
label = "cpu";
|
||||
ethernet = <ð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;
|
||||
};
|
||||
|
|
273
Documentation/devicetree/bindings/net/wireless/qcom,ath11k.yaml
Normal file
273
Documentation/devicetree/bindings/net/wireless/qcom,ath11k.yaml
Normal file
|
@ -0,0 +1,273 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
# Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
|
||||
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/net/wireless/qcom,ath11k.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Qualcomm Technologies ath11k wireless devices Generic Binding
|
||||
|
||||
maintainers:
|
||||
- Kalle Valo <kvalo@codeaurora.org>
|
||||
|
||||
description: |
|
||||
These are dt entries for Qualcomm Technologies, Inc. IEEE 802.11ax
|
||||
devices, for example like AHB based IPQ8074.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: qcom,ipq8074-wifi
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
items:
|
||||
- description: misc-pulse1 interrupt events
|
||||
- description: misc-latch interrupt events
|
||||
- description: sw exception interrupt events
|
||||
- description: watchdog interrupt events
|
||||
- description: interrupt event for ring CE0
|
||||
- description: interrupt event for ring CE1
|
||||
- description: interrupt event for ring CE2
|
||||
- description: interrupt event for ring CE3
|
||||
- description: interrupt event for ring CE4
|
||||
- description: interrupt event for ring CE5
|
||||
- description: interrupt event for ring CE6
|
||||
- description: interrupt event for ring CE7
|
||||
- description: interrupt event for ring CE8
|
||||
- description: interrupt event for ring CE9
|
||||
- description: interrupt event for ring CE10
|
||||
- description: interrupt event for ring CE11
|
||||
- description: interrupt event for ring host2wbm-desc-feed
|
||||
- description: interrupt event for ring host2reo-re-injection
|
||||
- description: interrupt event for ring host2reo-command
|
||||
- description: interrupt event for ring host2rxdma-monitor-ring3
|
||||
- description: interrupt event for ring host2rxdma-monitor-ring2
|
||||
- description: interrupt event for ring host2rxdma-monitor-ring1
|
||||
- description: interrupt event for ring reo2ost-exception
|
||||
- description: interrupt event for ring wbm2host-rx-release
|
||||
- description: interrupt event for ring reo2host-status
|
||||
- description: interrupt event for ring reo2host-destination-ring4
|
||||
- description: interrupt event for ring reo2host-destination-ring3
|
||||
- description: interrupt event for ring reo2host-destination-ring2
|
||||
- description: interrupt event for ring reo2host-destination-ring1
|
||||
- description: interrupt event for ring rxdma2host-monitor-destination-mac3
|
||||
- description: interrupt event for ring rxdma2host-monitor-destination-mac2
|
||||
- description: interrupt event for ring rxdma2host-monitor-destination-mac1
|
||||
- description: interrupt event for ring ppdu-end-interrupts-mac3
|
||||
- description: interrupt event for ring ppdu-end-interrupts-mac2
|
||||
- description: interrupt event for ring ppdu-end-interrupts-mac1
|
||||
- description: interrupt event for ring rxdma2host-monitor-status-ring-mac3
|
||||
- description: interrupt event for ring rxdma2host-monitor-status-ring-mac2
|
||||
- description: interrupt event for ring rxdma2host-monitor-status-ring-mac1
|
||||
- description: interrupt event for ring host2rxdma-host-buf-ring-mac3
|
||||
- description: interrupt event for ring host2rxdma-host-buf-ring-mac2
|
||||
- description: interrupt event for ring host2rxdma-host-buf-ring-mac1
|
||||
- description: interrupt event for ring rxdma2host-destination-ring-mac3
|
||||
- description: interrupt event for ring rxdma2host-destination-ring-mac2
|
||||
- description: interrupt event for ring rxdma2host-destination-ring-mac1
|
||||
- description: interrupt event for ring host2tcl-input-ring4
|
||||
- description: interrupt event for ring host2tcl-input-ring3
|
||||
- description: interrupt event for ring host2tcl-input-ring2
|
||||
- description: interrupt event for ring host2tcl-input-ring1
|
||||
- description: interrupt event for ring wbm2host-tx-completions-ring3
|
||||
- description: interrupt event for ring wbm2host-tx-completions-ring2
|
||||
- description: interrupt event for ring wbm2host-tx-completions-ring1
|
||||
- description: interrupt event for ring tcl2host-status-ring
|
||||
|
||||
|
||||
interrupt-names:
|
||||
items:
|
||||
- const: misc-pulse1
|
||||
- const: misc-latch
|
||||
- const: sw-exception
|
||||
- const: watchdog
|
||||
- const: ce0
|
||||
- const: ce1
|
||||
- const: ce2
|
||||
- const: ce3
|
||||
- const: ce4
|
||||
- const: ce5
|
||||
- const: ce6
|
||||
- const: ce7
|
||||
- const: ce8
|
||||
- const: ce9
|
||||
- const: ce10
|
||||
- const: ce11
|
||||
- const: host2wbm-desc-feed
|
||||
- const: host2reo-re-injection
|
||||
- const: host2reo-command
|
||||
- const: host2rxdma-monitor-ring3
|
||||
- const: host2rxdma-monitor-ring2
|
||||
- const: host2rxdma-monitor-ring1
|
||||
- const: reo2ost-exception
|
||||
- const: wbm2host-rx-release
|
||||
- const: reo2host-status
|
||||
- const: reo2host-destination-ring4
|
||||
- const: reo2host-destination-ring3
|
||||
- const: reo2host-destination-ring2
|
||||
- const: reo2host-destination-ring1
|
||||
- const: rxdma2host-monitor-destination-mac3
|
||||
- const: rxdma2host-monitor-destination-mac2
|
||||
- const: rxdma2host-monitor-destination-mac1
|
||||
- const: ppdu-end-interrupts-mac3
|
||||
- const: ppdu-end-interrupts-mac2
|
||||
- const: ppdu-end-interrupts-mac1
|
||||
- const: rxdma2host-monitor-status-ring-mac3
|
||||
- const: rxdma2host-monitor-status-ring-mac2
|
||||
- const: rxdma2host-monitor-status-ring-mac1
|
||||
- const: host2rxdma-host-buf-ring-mac3
|
||||
- const: host2rxdma-host-buf-ring-mac2
|
||||
- const: host2rxdma-host-buf-ring-mac1
|
||||
- const: rxdma2host-destination-ring-mac3
|
||||
- const: rxdma2host-destination-ring-mac2
|
||||
- const: rxdma2host-destination-ring-mac1
|
||||
- const: host2tcl-input-ring4
|
||||
- const: host2tcl-input-ring3
|
||||
- const: host2tcl-input-ring2
|
||||
- const: host2tcl-input-ring1
|
||||
- const: wbm2host-tx-completions-ring3
|
||||
- const: wbm2host-tx-completions-ring2
|
||||
- const: wbm2host-tx-completions-ring1
|
||||
- const: tcl2host-status-ring
|
||||
|
||||
qcom,rproc:
|
||||
$ref: /schemas/types.yaml#definitions/phandle
|
||||
description:
|
||||
DT entry of q6v5-wcss remoteproc driver.
|
||||
Phandle to a node that can contain the following properties
|
||||
* compatible
|
||||
* reg
|
||||
* reg-names
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- interrupts
|
||||
- interrupt-names
|
||||
- qcom,rproc
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
|
||||
q6v5_wcss: q6v5_wcss@CD00000 {
|
||||
compatible = "qcom,ipq8074-wcss-pil";
|
||||
reg = <0xCD00000 0x4040>,
|
||||
<0x4AB000 0x20>;
|
||||
reg-names = "qdsp6",
|
||||
"rmb";
|
||||
};
|
||||
|
||||
wifi0: wifi@c000000 {
|
||||
compatible = "qcom,ipq8074-wifi";
|
||||
reg = <0xc000000 0x2000000>;
|
||||
interrupts = <0 320 1>,
|
||||
<0 319 1>,
|
||||
<0 318 1>,
|
||||
<0 317 1>,
|
||||
<0 316 1>,
|
||||
<0 315 1>,
|
||||
<0 314 1>,
|
||||
<0 311 1>,
|
||||
<0 310 1>,
|
||||
<0 411 1>,
|
||||
<0 410 1>,
|
||||
<0 40 1>,
|
||||
<0 39 1>,
|
||||
<0 302 1>,
|
||||
<0 301 1>,
|
||||
<0 37 1>,
|
||||
<0 36 1>,
|
||||
<0 296 1>,
|
||||
<0 295 1>,
|
||||
<0 294 1>,
|
||||
<0 293 1>,
|
||||
<0 292 1>,
|
||||
<0 291 1>,
|
||||
<0 290 1>,
|
||||
<0 289 1>,
|
||||
<0 288 1>,
|
||||
<0 239 1>,
|
||||
<0 236 1>,
|
||||
<0 235 1>,
|
||||
<0 234 1>,
|
||||
<0 233 1>,
|
||||
<0 232 1>,
|
||||
<0 231 1>,
|
||||
<0 230 1>,
|
||||
<0 229 1>,
|
||||
<0 228 1>,
|
||||
<0 224 1>,
|
||||
<0 223 1>,
|
||||
<0 203 1>,
|
||||
<0 183 1>,
|
||||
<0 180 1>,
|
||||
<0 179 1>,
|
||||
<0 178 1>,
|
||||
<0 177 1>,
|
||||
<0 176 1>,
|
||||
<0 163 1>,
|
||||
<0 162 1>,
|
||||
<0 160 1>,
|
||||
<0 159 1>,
|
||||
<0 158 1>,
|
||||
<0 157 1>,
|
||||
<0 156 1>;
|
||||
interrupt-names = "misc-pulse1",
|
||||
"misc-latch",
|
||||
"sw-exception",
|
||||
"watchdog",
|
||||
"ce0",
|
||||
"ce1",
|
||||
"ce2",
|
||||
"ce3",
|
||||
"ce4",
|
||||
"ce5",
|
||||
"ce6",
|
||||
"ce7",
|
||||
"ce8",
|
||||
"ce9",
|
||||
"ce10",
|
||||
"ce11",
|
||||
"host2wbm-desc-feed",
|
||||
"host2reo-re-injection",
|
||||
"host2reo-command",
|
||||
"host2rxdma-monitor-ring3",
|
||||
"host2rxdma-monitor-ring2",
|
||||
"host2rxdma-monitor-ring1",
|
||||
"reo2ost-exception",
|
||||
"wbm2host-rx-release",
|
||||
"reo2host-status",
|
||||
"reo2host-destination-ring4",
|
||||
"reo2host-destination-ring3",
|
||||
"reo2host-destination-ring2",
|
||||
"reo2host-destination-ring1",
|
||||
"rxdma2host-monitor-destination-mac3",
|
||||
"rxdma2host-monitor-destination-mac2",
|
||||
"rxdma2host-monitor-destination-mac1",
|
||||
"ppdu-end-interrupts-mac3",
|
||||
"ppdu-end-interrupts-mac2",
|
||||
"ppdu-end-interrupts-mac1",
|
||||
"rxdma2host-monitor-status-ring-mac3",
|
||||
"rxdma2host-monitor-status-ring-mac2",
|
||||
"rxdma2host-monitor-status-ring-mac1",
|
||||
"host2rxdma-host-buf-ring-mac3",
|
||||
"host2rxdma-host-buf-ring-mac2",
|
||||
"host2rxdma-host-buf-ring-mac1",
|
||||
"rxdma2host-destination-ring-mac3",
|
||||
"rxdma2host-destination-ring-mac2",
|
||||
"rxdma2host-destination-ring-mac1",
|
||||
"host2tcl-input-ring4",
|
||||
"host2tcl-input-ring3",
|
||||
"host2tcl-input-ring2",
|
||||
"host2tcl-input-ring1",
|
||||
"wbm2host-tx-completions-ring3",
|
||||
"wbm2host-tx-completions-ring2",
|
||||
"wbm2host-tx-completions-ring1",
|
||||
"tcl2host-status-ring";
|
||||
qcom,rproc = <&q6v5_wcss>;
|
||||
};
|
35
Documentation/devicetree/bindings/ptp/ptp-ines.txt
Normal file
35
Documentation/devicetree/bindings/ptp/ptp-ines.txt
Normal file
|
@ -0,0 +1,35 @@
|
|||
ZHAW InES PTP time stamping IP core
|
||||
|
||||
The IP core needs two different kinds of nodes. The control node
|
||||
lives somewhere in the memory map and specifies the address of the
|
||||
control registers. There can be up to three port handles placed as
|
||||
attributes of PHY nodes. These associate a particular MII bus with a
|
||||
port index within the IP core.
|
||||
|
||||
Required properties of the control node:
|
||||
|
||||
- compatible: "ines,ptp-ctrl"
|
||||
- reg: physical address and size of the register bank
|
||||
|
||||
Required format of the port handle within the PHY node:
|
||||
|
||||
- timestamper: provides control node reference and
|
||||
the port channel within the IP core
|
||||
|
||||
Example:
|
||||
|
||||
tstamper: timestamper@60000000 {
|
||||
compatible = "ines,ptp-ctrl";
|
||||
reg = <0x60000000 0x80>;
|
||||
};
|
||||
|
||||
ethernet@80000000 {
|
||||
...
|
||||
mdio {
|
||||
...
|
||||
ethernet-phy@3 {
|
||||
...
|
||||
timestamper = <&tstamper 0>;
|
||||
};
|
||||
};
|
||||
};
|
42
Documentation/devicetree/bindings/ptp/timestamper.txt
Normal file
42
Documentation/devicetree/bindings/ptp/timestamper.txt
Normal file
|
@ -0,0 +1,42 @@
|
|||
Time stamps from MII bus snooping devices
|
||||
|
||||
This binding supports non-PHY devices that snoop the MII bus and
|
||||
provide time stamps. In contrast to PHY time stamping drivers (which
|
||||
can simply attach their interface directly to the PHY instance), stand
|
||||
alone MII time stamping drivers use this binding to specify the
|
||||
connection between the snooping device and a given network interface.
|
||||
|
||||
Non-PHY MII time stamping drivers typically talk to the control
|
||||
interface over another bus like I2C, SPI, UART, or via a memory mapped
|
||||
peripheral. This controller device is associated with one or more
|
||||
time stamping channels, each of which snoops on a MII bus.
|
||||
|
||||
The "timestamper" property lives in a phy node and links a time
|
||||
stamping channel from the controller device to that phy's MII bus.
|
||||
|
||||
Example:
|
||||
|
||||
tstamper: timestamper@10000000 {
|
||||
compatible = "ines,ptp-ctrl";
|
||||
reg = <0x10000000 0x80>;
|
||||
};
|
||||
|
||||
ethernet@20000000 {
|
||||
mdio {
|
||||
ethernet-phy@1 {
|
||||
timestamper = <&tstamper 0>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
ethernet@30000000 {
|
||||
mdio {
|
||||
ethernet-phy@2 {
|
||||
timestamper = <&tstamper 1>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
In this example, time stamps from the MII bus attached to phy@1 will
|
||||
appear on time stamp channel 0 (zero), and those from phy@2 appear on
|
||||
channel 1.
|
|
@ -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
|
||||
|
||||
|
|
159
Documentation/networking/device_drivers/marvell/octeontx2.rst
Normal file
159
Documentation/networking/device_drivers/marvell/octeontx2.rst
Normal file
|
@ -0,0 +1,159 @@
|
|||
.. SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
|
||||
====================================
|
||||
Marvell OcteonTx2 RVU Kernel Drivers
|
||||
====================================
|
||||
|
||||
Copyright (c) 2020 Marvell International Ltd.
|
||||
|
||||
Contents
|
||||
========
|
||||
|
||||
- `Overview`_
|
||||
- `Drivers`_
|
||||
- `Basic packet flow`_
|
||||
|
||||
Overview
|
||||
========
|
||||
|
||||
Resource virtualization unit (RVU) on Marvell's OcteonTX2 SOC maps HW
|
||||
resources from the network, crypto and other functional blocks into
|
||||
PCI-compatible physical and virtual functions. Each functional block
|
||||
again has multiple local functions (LFs) for provisioning to PCI devices.
|
||||
RVU supports multiple PCIe SRIOV physical functions (PFs) and virtual
|
||||
functions (VFs). PF0 is called the administrative / admin function (AF)
|
||||
and has privileges to provision RVU functional block's LFs to each of the
|
||||
PF/VF.
|
||||
|
||||
RVU managed networking functional blocks
|
||||
- Network pool or buffer allocator (NPA)
|
||||
- Network interface controller (NIX)
|
||||
- Network parser CAM (NPC)
|
||||
- Schedule/Synchronize/Order unit (SSO)
|
||||
- Loopback interface (LBK)
|
||||
|
||||
RVU managed non-networking functional blocks
|
||||
- Crypto accelerator (CPT)
|
||||
- Scheduled timers unit (TIM)
|
||||
- Schedule/Synchronize/Order unit (SSO)
|
||||
Used for both networking and non networking usecases
|
||||
|
||||
Resource provisioning examples
|
||||
- A PF/VF with NIX-LF & NPA-LF resources works as a pure network device
|
||||
- A PF/VF with CPT-LF resource works as a pure crypto offload device.
|
||||
|
||||
RVU functional blocks are highly configurable as per software requirements.
|
||||
|
||||
Firmware setups following stuff before kernel boots
|
||||
- Enables required number of RVU PFs based on number of physical links.
|
||||
- Number of VFs per PF are either static or configurable at compile time.
|
||||
Based on config, firmware assigns VFs to each of the PFs.
|
||||
- Also assigns MSIX vectors to each of PF and VFs.
|
||||
- These are not changed after kernel boot.
|
||||
|
||||
Drivers
|
||||
=======
|
||||
|
||||
Linux kernel will have multiple drivers registering to different PF and VFs
|
||||
of RVU. Wrt networking there will be 3 flavours of drivers.
|
||||
|
||||
Admin Function driver
|
||||
---------------------
|
||||
|
||||
As mentioned above RVU PF0 is called the admin function (AF), this driver
|
||||
supports resource provisioning and configuration of functional blocks.
|
||||
Doesn't handle any I/O. It sets up few basic stuff but most of the
|
||||
funcionality is achieved via configuration requests from PFs and VFs.
|
||||
|
||||
PF/VFs communicates with AF via a shared memory region (mailbox). Upon
|
||||
receiving requests AF does resource provisioning and other HW configuration.
|
||||
AF is always attached to host kernel, but PFs and their VFs may be used by host
|
||||
kernel itself, or attached to VMs or to userspace applications like
|
||||
DPDK etc. So AF has to handle provisioning/configuration requests sent
|
||||
by any device from any domain.
|
||||
|
||||
AF driver also interacts with underlying firmware to
|
||||
- Manage physical ethernet links ie CGX LMACs.
|
||||
- Retrieve information like speed, duplex, autoneg etc
|
||||
- Retrieve PHY EEPROM and stats.
|
||||
- Configure FEC, PAM modes
|
||||
- etc
|
||||
|
||||
From pure networking side AF driver supports following functionality.
|
||||
- Map a physical link to a RVU PF to which a netdev is registered.
|
||||
- Attach NIX and NPA block LFs to RVU PF/VF which provide buffer pools, RQs, SQs
|
||||
for regular networking functionality.
|
||||
- Flow control (pause frames) enable/disable/config.
|
||||
- HW PTP timestamping related config.
|
||||
- NPC parser profile config, basically how to parse pkt and what info to extract.
|
||||
- NPC extract profile config, what to extract from the pkt to match data in MCAM entries.
|
||||
- Manage NPC MCAM entries, upon request can frame and install requested packet forwarding rules.
|
||||
- Defines receive side scaling (RSS) algorithms.
|
||||
- Defines segmentation offload algorithms (eg TSO)
|
||||
- VLAN stripping, capture and insertion config.
|
||||
- SSO and TIM blocks config which provide packet scheduling support.
|
||||
- Debugfs support, to check current resource provising, current status of
|
||||
NPA pools, NIX RQ, SQ and CQs, various stats etc which helps in debugging issues.
|
||||
- And many more.
|
||||
|
||||
Physical Function driver
|
||||
------------------------
|
||||
|
||||
This RVU PF handles IO, is mapped to a physical ethernet link and this
|
||||
driver registers a netdev. This supports SR-IOV. As said above this driver
|
||||
communicates with AF with a mailbox. To retrieve information from physical
|
||||
links this driver talks to AF and AF gets that info from firmware and responds
|
||||
back ie cannot talk to firmware directly.
|
||||
|
||||
Supports ethtool for configuring links, RSS, queue count, queue size,
|
||||
flow control, ntuple filters, dump PHY EEPROM, config FEC etc.
|
||||
|
||||
Virtual Function driver
|
||||
-----------------------
|
||||
|
||||
There are two types VFs, VFs that share the physical link with their parent
|
||||
SR-IOV PF and the VFs which work in pairs using internal HW loopback channels (LBK).
|
||||
|
||||
Type1:
|
||||
- These VFs and their parent PF share a physical link and used for outside communication.
|
||||
- VFs cannot communicate with AF directly, they send mbox message to PF and PF
|
||||
forwards that to AF. AF after processing, responds back to PF and PF forwards
|
||||
the reply to VF.
|
||||
- From functionality point of view there is no difference between PF and VF as same type
|
||||
HW resources are attached to both. But user would be able to configure few stuff only
|
||||
from PF as PF is treated as owner/admin of the link.
|
||||
|
||||
Type2:
|
||||
- RVU PF0 ie admin function creates these VFs and maps them to loopback block's channels.
|
||||
- A set of two VFs (VF0 & VF1, VF2 & VF3 .. so on) works as a pair ie pkts sent out of
|
||||
VF0 will be received by VF1 and viceversa.
|
||||
- These VFs can be used by applications or virtual machines to communicate between them
|
||||
without sending traffic outside. There is no switch present in HW, hence the support
|
||||
for loopback VFs.
|
||||
- These communicate directly with AF (PF0) via mbox.
|
||||
|
||||
Except for the IO channels or links used for packet reception and transmission there is
|
||||
no other difference between these VF types. AF driver takes care of IO channel mapping,
|
||||
hence same VF driver works for both types of devices.
|
||||
|
||||
Basic packet flow
|
||||
=================
|
||||
|
||||
Ingress
|
||||
-------
|
||||
|
||||
1. CGX LMAC receives packet.
|
||||
2. Forwards the packet to the NIX block.
|
||||
3. Then submitted to NPC block for parsing and then MCAM lookup to get the destination RVU device.
|
||||
4. NIX LF attached to the destination RVU device allocates a buffer from RQ mapped buffer pool of NPA block LF.
|
||||
5. RQ may be selected by RSS or by configuring MCAM rule with a RQ number.
|
||||
6. Packet is DMA'ed and driver is notified.
|
||||
|
||||
Egress
|
||||
------
|
||||
|
||||
1. Driver prepares a send descriptor and submits to SQ for transmission.
|
||||
2. The SQ is already configured (by AF) to transmit on a specific link/channel.
|
||||
3. The SQ descriptor ring is maintained in buffers allocated from SQ mapped pool of NPA block LF.
|
||||
4. NIX block transmits the pkt on the designated channel.
|
||||
5. NPC MCAM entries can be installed to divert pkt onto a different channel.
|
|
@ -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.
|
||||
|
|
697
Documentation/networking/device_drivers/stmicro/stmmac.rst
Normal file
697
Documentation/networking/device_drivers/stmicro/stmmac.rst
Normal file
|
@ -0,0 +1,697 @@
|
|||
.. SPDX-License-Identifier: GPL-2.0+
|
||||
|
||||
==============================================================
|
||||
Linux Driver for the Synopsys(R) Ethernet Controllers "stmmac"
|
||||
==============================================================
|
||||
|
||||
Authors: Giuseppe Cavallaro <peppe.cavallaro@st.com>,
|
||||
Alexandre Torgue <alexandre.torgue@st.com>, Jose Abreu <joabreu@synopsys.com>
|
||||
|
||||
Contents
|
||||
========
|
||||
|
||||
- In This Release
|
||||
- Feature List
|
||||
- Kernel Configuration
|
||||
- Command Line Parameters
|
||||
- Driver Information and Notes
|
||||
- Debug Information
|
||||
- Support
|
||||
|
||||
In This Release
|
||||
===============
|
||||
|
||||
This file describes the stmmac Linux Driver for all the Synopsys(R) Ethernet
|
||||
Controllers.
|
||||
|
||||
Currently, this network device driver is for all STi embedded MAC/GMAC
|
||||
(i.e. 7xxx/5xxx SoCs), SPEAr (arm), Loongson1B (mips) and XILINX XC2V3000
|
||||
FF1152AMT0221 D1215994A VIRTEX FPGA board. The Synopsys Ethernet QoS 5.0 IPK
|
||||
is also supported.
|
||||
|
||||
DesignWare(R) Cores Ethernet MAC 10/100/1000 Universal version 3.70a
|
||||
(and older) and DesignWare(R) Cores Ethernet Quality-of-Service version 4.0
|
||||
(and upper) have been used for developing this driver as well as
|
||||
DesignWare(R) Cores XGMAC - 10G Ethernet MAC.
|
||||
|
||||
This driver supports both the platform bus and PCI.
|
||||
|
||||
This driver includes support for the following Synopsys(R) DesignWare(R)
|
||||
Cores Ethernet Controllers and corresponding minimum and maximum versions:
|
||||
|
||||
+-------------------------------+--------------+--------------+--------------+
|
||||
| Controller Name | Min. Version | Max. Version | Abbrev. Name |
|
||||
+===============================+==============+==============+==============+
|
||||
| Ethernet MAC Universal | N/A | 3.73a | GMAC |
|
||||
+-------------------------------+--------------+--------------+--------------+
|
||||
| Ethernet Quality-of-Service | 4.00a | N/A | GMAC4+ |
|
||||
+-------------------------------+--------------+--------------+--------------+
|
||||
| XGMAC - 10G Ethernet MAC | 2.10a | N/A | XGMAC2+ |
|
||||
+-------------------------------+--------------+--------------+--------------+
|
||||
|
||||
For questions related to hardware requirements, refer to the documentation
|
||||
supplied with your Ethernet adapter. All hardware requirements listed apply
|
||||
to use with Linux.
|
||||
|
||||
Feature List
|
||||
============
|
||||
|
||||
The following features are available in this driver:
|
||||
- GMII/MII/RGMII/SGMII/RMII/XGMII Interface
|
||||
- Half-Duplex / Full-Duplex Operation
|
||||
- Energy Efficient Ethernet (EEE)
|
||||
- IEEE 802.3x PAUSE Packets (Flow Control)
|
||||
- RMON/MIB Counters
|
||||
- IEEE 1588 Timestamping (PTP)
|
||||
- Pulse-Per-Second Output (PPS)
|
||||
- MDIO Clause 22 / Clause 45 Interface
|
||||
- MAC Loopback
|
||||
- ARP Offloading
|
||||
- Automatic CRC / PAD Insertion and Checking
|
||||
- Checksum Offload for Received and Transmitted Packets
|
||||
- Standard or Jumbo Ethernet Packets
|
||||
- Source Address Insertion / Replacement
|
||||
- VLAN TAG Insertion / Replacement / Deletion / Filtering (HASH and PERFECT)
|
||||
- Programmable TX and RX Watchdog and Coalesce Settings
|
||||
- Destination Address Filtering (PERFECT)
|
||||
- HASH Filtering (Multicast)
|
||||
- Layer 3 / Layer 4 Filtering
|
||||
- Remote Wake-Up Detection
|
||||
- Receive Side Scaling (RSS)
|
||||
- Frame Preemption for TX and RX
|
||||
- Programmable Burst Length, Threshold, Queue Size
|
||||
- Multiple Queues (up to 8)
|
||||
- Multiple Scheduling Algorithms (TX: WRR, DWRR, WFQ, SP, CBS, EST, TBS;
|
||||
RX: WRR, SP)
|
||||
- Flexible RX Parser
|
||||
- TCP / UDP Segmentation Offload (TSO, USO)
|
||||
- Split Header (SPH)
|
||||
- Safety Features (ECC Protection, Data Parity Protection)
|
||||
- Selftests using Ethtool
|
||||
|
||||
Kernel Configuration
|
||||
====================
|
||||
|
||||
The kernel configuration option is ``CONFIG_STMMAC_ETH``:
|
||||
- ``CONFIG_STMMAC_PLATFORM``: is to enable the platform driver.
|
||||
- ``CONFIG_STMMAC_PCI``: is to enable the pci driver.
|
||||
|
||||
Command Line Parameters
|
||||
=======================
|
||||
|
||||
If the driver is built as a module the following optional parameters are used
|
||||
by entering them on the command line with the modprobe command using this
|
||||
syntax (e.g. for PCI module)::
|
||||
|
||||
modprobe stmmac_pci [<option>=<VAL1>,<VAL2>,...]
|
||||
|
||||
Driver parameters can be also passed in command line by using::
|
||||
|
||||
stmmaceth=watchdog:100,chain_mode=1
|
||||
|
||||
The default value for each parameter is generally the recommended setting,
|
||||
unless otherwise noted.
|
||||
|
||||
watchdog
|
||||
--------
|
||||
:Valid Range: 5000-None
|
||||
:Default Value: 5000
|
||||
|
||||
This parameter overrides the transmit timeout in milliseconds.
|
||||
|
||||
debug
|
||||
-----
|
||||
:Valid Range: 0-16 (0=none,...,16=all)
|
||||
:Default Value: 0
|
||||
|
||||
This parameter adjusts the level of debug messages displayed in the system
|
||||
logs.
|
||||
|
||||
phyaddr
|
||||
-------
|
||||
:Valid Range: 0-31
|
||||
:Default Value: -1
|
||||
|
||||
This parameter overrides the physical address of the PHY device.
|
||||
|
||||
flow_ctrl
|
||||
---------
|
||||
:Valid Range: 0-3 (0=off,1=rx,2=tx,3=rx/tx)
|
||||
:Default Value: 3
|
||||
|
||||
This parameter changes the default Flow Control ability.
|
||||
|
||||
pause
|
||||
-----
|
||||
:Valid Range: 0-65535
|
||||
:Default Value: 65535
|
||||
|
||||
This parameter changes the default Flow Control Pause time.
|
||||
|
||||
tc
|
||||
--
|
||||
:Valid Range: 64-256
|
||||
:Default Value: 64
|
||||
|
||||
This parameter changes the default HW FIFO Threshold control value.
|
||||
|
||||
buf_sz
|
||||
------
|
||||
:Valid Range: 1536-16384
|
||||
:Default Value: 1536
|
||||
|
||||
This parameter changes the default RX DMA packet buffer size.
|
||||
|
||||
eee_timer
|
||||
---------
|
||||
:Valid Range: 0-None
|
||||
:Default Value: 1000
|
||||
|
||||
This parameter changes the default LPI TX Expiration time in milliseconds.
|
||||
|
||||
chain_mode
|
||||
----------
|
||||
:Valid Range: 0-1 (0=off,1=on)
|
||||
:Default Value: 0
|
||||
|
||||
This parameter changes the default mode of operation from Ring Mode to
|
||||
Chain Mode.
|
||||
|
||||
Driver Information and Notes
|
||||
============================
|
||||
|
||||
Transmit Process
|
||||
----------------
|
||||
|
||||
The xmit method is invoked when the kernel needs to transmit a packet; it sets
|
||||
the descriptors in the ring and informs the DMA engine that there is a packet
|
||||
ready to be transmitted.
|
||||
|
||||
By default, the driver sets the ``NETIF_F_SG`` bit in the features field of
|
||||
the ``net_device`` structure, enabling the scatter-gather feature. This is
|
||||
true on chips and configurations where the checksum can be done in hardware.
|
||||
|
||||
Once the controller has finished transmitting the packet, timer will be
|
||||
scheduled to release the transmit resources.
|
||||
|
||||
Receive Process
|
||||
---------------
|
||||
|
||||
When one or more packets are received, an interrupt happens. The interrupts
|
||||
are not queued, so the driver has to scan all the descriptors in the ring
|
||||
during the receive process.
|
||||
|
||||
This is based on NAPI, so the interrupt handler signals only if there is work
|
||||
to be done, and it exits. Then the poll method will be scheduled at some
|
||||
future point.
|
||||
|
||||
The incoming packets are stored, by the DMA, in a list of pre-allocated socket
|
||||
buffers in order to avoid the memcpy (zero-copy).
|
||||
|
||||
Interrupt Mitigation
|
||||
--------------------
|
||||
|
||||
The driver is able to mitigate the number of its DMA interrupts using NAPI for
|
||||
the reception on chips older than the 3.50. New chips have an HW RX Watchdog
|
||||
used for this mitigation.
|
||||
|
||||
Mitigation parameters can be tuned by ethtool.
|
||||
|
||||
WoL
|
||||
---
|
||||
|
||||
Wake up on Lan feature through Magic and Unicast frames are supported for the
|
||||
GMAC, GMAC4/5 and XGMAC core.
|
||||
|
||||
DMA Descriptors
|
||||
---------------
|
||||
|
||||
Driver handles both normal and alternate descriptors. The latter has been only
|
||||
tested on DesignWare(R) Cores Ethernet MAC Universal version 3.41a and later.
|
||||
|
||||
stmmac supports DMA descriptor to operate both in dual buffer (RING) and
|
||||
linked-list(CHAINED) mode. In RING each descriptor points to two data buffer
|
||||
pointers whereas in CHAINED mode they point to only one data buffer pointer.
|
||||
RING mode is the default.
|
||||
|
||||
In CHAINED mode each descriptor will have pointer to next descriptor in the
|
||||
list, hence creating the explicit chaining in the descriptor itself, whereas
|
||||
such explicit chaining is not possible in RING mode.
|
||||
|
||||
Extended Descriptors
|
||||
--------------------
|
||||
|
||||
The extended descriptors give us information about the Ethernet payload when
|
||||
it is carrying PTP packets or TCP/UDP/ICMP over IP. These are not available on
|
||||
GMAC Synopsys(R) chips older than the 3.50. At probe time the driver will
|
||||
decide if these can be actually used. This support also is mandatory for PTPv2
|
||||
because the extra descriptors are used for saving the hardware timestamps and
|
||||
Extended Status.
|
||||
|
||||
Ethtool Support
|
||||
---------------
|
||||
|
||||
Ethtool is supported. For example, driver statistics (including RMON),
|
||||
internal errors can be taken using::
|
||||
|
||||
ethtool -S ethX
|
||||
|
||||
Ethtool selftests are also supported. This allows to do some early sanity
|
||||
checks to the HW using MAC and PHY loopback mechanisms::
|
||||
|
||||
ethtool -t ethX
|
||||
|
||||
Jumbo and Segmentation Offloading
|
||||
---------------------------------
|
||||
|
||||
Jumbo frames are supported and tested for the GMAC. The GSO has been also
|
||||
added but it's performed in software. LRO is not supported.
|
||||
|
||||
TSO Support
|
||||
-----------
|
||||
|
||||
TSO (TCP Segmentation Offload) feature is supported by GMAC > 4.x and XGMAC
|
||||
chip family. When a packet is sent through TCP protocol, the TCP stack ensures
|
||||
that the SKB provided to the low level driver (stmmac in our case) matches
|
||||
with the maximum frame len (IP header + TCP header + payload <= 1500 bytes
|
||||
(for MTU set to 1500)). It means that if an application using TCP want to send
|
||||
a packet which will have a length (after adding headers) > 1514 the packet
|
||||
will be split in several TCP packets: The data payload is split and headers
|
||||
(TCP/IP ..) are added. It is done by software.
|
||||
|
||||
When TSO is enabled, the TCP stack doesn't care about the maximum frame length
|
||||
and provide SKB packet to stmmac as it is. The GMAC IP will have to perform
|
||||
the segmentation by it self to match with maximum frame length.
|
||||
|
||||
This feature can be enabled in device tree through ``snps,tso`` entry.
|
||||
|
||||
Energy Efficient Ethernet
|
||||
-------------------------
|
||||
|
||||
Energy Efficient Ethernet (EEE) enables IEEE 802.3 MAC sublayer along with a
|
||||
family of Physical layer to operate in the Low Power Idle (LPI) mode. The EEE
|
||||
mode supports the IEEE 802.3 MAC operation at 100Mbps, 1000Mbps and 1Gbps.
|
||||
|
||||
The LPI mode allows power saving by switching off parts of the communication
|
||||
device functionality when there is no data to be transmitted & received.
|
||||
The system on both the side of the link can disable some functionalities and
|
||||
save power during the period of low-link utilization. The MAC controls whether
|
||||
the system should enter or exit the LPI mode and communicate this to PHY.
|
||||
|
||||
As soon as the interface is opened, the driver verifies if the EEE can be
|
||||
supported. This is done by looking at both the DMA HW capability register and
|
||||
the PHY devices MCD registers.
|
||||
|
||||
To enter in TX LPI mode the driver needs to have a software timer that enable
|
||||
and disable the LPI mode when there is nothing to be transmitted.
|
||||
|
||||
Precision Time Protocol (PTP)
|
||||
-----------------------------
|
||||
|
||||
The driver supports the IEEE 1588-2002, Precision Time Protocol (PTP), which
|
||||
enables precise synchronization of clocks in measurement and control systems
|
||||
implemented with technologies such as network communication.
|
||||
|
||||
In addition to the basic timestamp features mentioned in IEEE 1588-2002
|
||||
Timestamps, new GMAC cores support the advanced timestamp features.
|
||||
IEEE 1588-2008 can be enabled when configuring the Kernel.
|
||||
|
||||
SGMII/RGMII Support
|
||||
-------------------
|
||||
|
||||
New GMAC devices provide own way to manage RGMII/SGMII. This information is
|
||||
available at run-time by looking at the HW capability register. This means
|
||||
that the stmmac can manage auto-negotiation and link status w/o using the
|
||||
PHYLIB stuff. In fact, the HW provides a subset of extended registers to
|
||||
restart the ANE, verify Full/Half duplex mode and Speed. Thanks to these
|
||||
registers, it is possible to look at the Auto-negotiated Link Parter Ability.
|
||||
|
||||
Physical
|
||||
--------
|
||||
|
||||
The driver is compatible with Physical Abstraction Layer to be connected with
|
||||
PHY and GPHY devices.
|
||||
|
||||
Platform Information
|
||||
--------------------
|
||||
|
||||
Several information can be passed through the platform and device-tree.
|
||||
|
||||
::
|
||||
|
||||
struct plat_stmmacenet_data {
|
||||
|
||||
1) Bus identifier::
|
||||
|
||||
int bus_id;
|
||||
|
||||
2) PHY Physical Address. If set to -1 the driver will pick the first PHY it
|
||||
finds::
|
||||
|
||||
int phy_addr;
|
||||
|
||||
3) PHY Device Interface::
|
||||
|
||||
int interface;
|
||||
|
||||
4) Specific platform fields for the MDIO bus::
|
||||
|
||||
struct stmmac_mdio_bus_data *mdio_bus_data;
|
||||
|
||||
5) Internal DMA parameters::
|
||||
|
||||
struct stmmac_dma_cfg *dma_cfg;
|
||||
|
||||
6) Fixed CSR Clock Range selection::
|
||||
|
||||
int clk_csr;
|
||||
|
||||
7) HW uses the GMAC core::
|
||||
|
||||
int has_gmac;
|
||||
|
||||
8) If set the MAC will use Enhanced Descriptors::
|
||||
|
||||
int enh_desc;
|
||||
|
||||
9) Core is able to perform TX Checksum and/or RX Checksum in HW::
|
||||
|
||||
int tx_coe;
|
||||
int rx_coe;
|
||||
|
||||
11) Some HWs are not able to perform the csum in HW for over-sized frames due
|
||||
to limited buffer sizes. Setting this flag the csum will be done in SW on
|
||||
JUMBO frames::
|
||||
|
||||
int bugged_jumbo;
|
||||
|
||||
12) Core has the embedded power module::
|
||||
|
||||
int pmt;
|
||||
|
||||
13) Force DMA to use the Store and Forward mode or Threshold mode::
|
||||
|
||||
int force_sf_dma_mode;
|
||||
int force_thresh_dma_mode;
|
||||
|
||||
15) Force to disable the RX Watchdog feature and switch to NAPI mode::
|
||||
|
||||
int riwt_off;
|
||||
|
||||
16) Limit the maximum operating speed and MTU::
|
||||
|
||||
int max_speed;
|
||||
int maxmtu;
|
||||
|
||||
18) Number of Multicast/Unicast filters::
|
||||
|
||||
int multicast_filter_bins;
|
||||
int unicast_filter_entries;
|
||||
|
||||
20) Limit the maximum TX and RX FIFO size::
|
||||
|
||||
int tx_fifo_size;
|
||||
int rx_fifo_size;
|
||||
|
||||
21) Use the specified number of TX and RX Queues::
|
||||
|
||||
u32 rx_queues_to_use;
|
||||
u32 tx_queues_to_use;
|
||||
|
||||
22) Use the specified TX and RX scheduling algorithm::
|
||||
|
||||
u8 rx_sched_algorithm;
|
||||
u8 tx_sched_algorithm;
|
||||
|
||||
23) Internal TX and RX Queue parameters::
|
||||
|
||||
struct stmmac_rxq_cfg rx_queues_cfg[MTL_MAX_RX_QUEUES];
|
||||
struct stmmac_txq_cfg tx_queues_cfg[MTL_MAX_TX_QUEUES];
|
||||
|
||||
24) This callback is used for modifying some syscfg registers (on ST SoCs)
|
||||
according to the link speed negotiated by the physical layer::
|
||||
|
||||
void (*fix_mac_speed)(void *priv, unsigned int speed);
|
||||
|
||||
25) Callbacks used for calling a custom initialization; This is sometimes
|
||||
necessary on some platforms (e.g. ST boxes) where the HW needs to have set
|
||||
some PIO lines or system cfg registers. init/exit callbacks should not use
|
||||
or modify platform data::
|
||||
|
||||
int (*init)(struct platform_device *pdev, void *priv);
|
||||
void (*exit)(struct platform_device *pdev, void *priv);
|
||||
|
||||
26) Perform HW setup of the bus. For example, on some ST platforms this field
|
||||
is used to configure the AMBA bridge to generate more efficient STBus traffic::
|
||||
|
||||
struct mac_device_info *(*setup)(void *priv);
|
||||
void *bsp_priv;
|
||||
|
||||
27) Internal clocks and rates::
|
||||
|
||||
struct clk *stmmac_clk;
|
||||
struct clk *pclk;
|
||||
struct clk *clk_ptp_ref;
|
||||
unsigned int clk_ptp_rate;
|
||||
unsigned int clk_ref_rate;
|
||||
s32 ptp_max_adj;
|
||||
|
||||
28) Main reset::
|
||||
|
||||
struct reset_control *stmmac_rst;
|
||||
|
||||
29) AXI Internal Parameters::
|
||||
|
||||
struct stmmac_axi *axi;
|
||||
|
||||
30) HW uses GMAC>4 cores::
|
||||
|
||||
int has_gmac4;
|
||||
|
||||
31) HW is sun8i based::
|
||||
|
||||
bool has_sun8i;
|
||||
|
||||
32) Enables TSO feature::
|
||||
|
||||
bool tso_en;
|
||||
|
||||
33) Enables Receive Side Scaling (RSS) feature::
|
||||
|
||||
int rss_en;
|
||||
|
||||
34) MAC Port selection::
|
||||
|
||||
int mac_port_sel_speed;
|
||||
|
||||
35) Enables TX LPI Clock Gating::
|
||||
|
||||
bool en_tx_lpi_clockgating;
|
||||
|
||||
36) HW uses XGMAC>2.10 cores::
|
||||
|
||||
int has_xgmac;
|
||||
|
||||
::
|
||||
|
||||
}
|
||||
|
||||
For MDIO bus data, we have:
|
||||
|
||||
::
|
||||
|
||||
struct stmmac_mdio_bus_data {
|
||||
|
||||
1) PHY mask passed when MDIO bus is registered::
|
||||
|
||||
unsigned int phy_mask;
|
||||
|
||||
2) List of IRQs, one per PHY::
|
||||
|
||||
int *irqs;
|
||||
|
||||
3) If IRQs is NULL, use this for probed PHY::
|
||||
|
||||
int probed_phy_irq;
|
||||
|
||||
4) Set to true if PHY needs reset::
|
||||
|
||||
bool needs_reset;
|
||||
|
||||
::
|
||||
|
||||
}
|
||||
|
||||
For DMA engine configuration, we have:
|
||||
|
||||
::
|
||||
|
||||
struct stmmac_dma_cfg {
|
||||
|
||||
1) Programmable Burst Length (TX and RX)::
|
||||
|
||||
int pbl;
|
||||
|
||||
2) If set, DMA TX / RX will use this value rather than pbl::
|
||||
|
||||
int txpbl;
|
||||
int rxpbl;
|
||||
|
||||
3) Enable 8xPBL::
|
||||
|
||||
bool pblx8;
|
||||
|
||||
4) Enable Fixed or Mixed burst::
|
||||
|
||||
int fixed_burst;
|
||||
int mixed_burst;
|
||||
|
||||
5) Enable Address Aligned Beats::
|
||||
|
||||
bool aal;
|
||||
|
||||
6) Enable Enhanced Addressing (> 32 bits)::
|
||||
|
||||
bool eame;
|
||||
|
||||
::
|
||||
|
||||
}
|
||||
|
||||
For DMA AXI parameters, we have:
|
||||
|
||||
::
|
||||
|
||||
struct stmmac_axi {
|
||||
|
||||
1) Enable AXI LPI::
|
||||
|
||||
bool axi_lpi_en;
|
||||
bool axi_xit_frm;
|
||||
|
||||
2) Set AXI Write / Read maximum outstanding requests::
|
||||
|
||||
u32 axi_wr_osr_lmt;
|
||||
u32 axi_rd_osr_lmt;
|
||||
|
||||
3) Set AXI 4KB bursts::
|
||||
|
||||
bool axi_kbbe;
|
||||
|
||||
4) Set AXI maximum burst length map::
|
||||
|
||||
u32 axi_blen[AXI_BLEN];
|
||||
|
||||
5) Set AXI Fixed burst / mixed burst::
|
||||
|
||||
bool axi_fb;
|
||||
bool axi_mb;
|
||||
|
||||
6) Set AXI rebuild incrx mode::
|
||||
|
||||
bool axi_rb;
|
||||
|
||||
::
|
||||
|
||||
}
|
||||
|
||||
For the RX Queues configuration, we have:
|
||||
|
||||
::
|
||||
|
||||
struct stmmac_rxq_cfg {
|
||||
|
||||
1) Mode to use (DCB or AVB)::
|
||||
|
||||
u8 mode_to_use;
|
||||
|
||||
2) DMA channel to use::
|
||||
|
||||
u32 chan;
|
||||
|
||||
3) Packet routing, if applicable::
|
||||
|
||||
u8 pkt_route;
|
||||
|
||||
4) Use priority routing, and priority to route::
|
||||
|
||||
bool use_prio;
|
||||
u32 prio;
|
||||
|
||||
::
|
||||
|
||||
}
|
||||
|
||||
For the TX Queues configuration, we have:
|
||||
|
||||
::
|
||||
|
||||
struct stmmac_txq_cfg {
|
||||
|
||||
1) Queue weight in scheduler::
|
||||
|
||||
u32 weight;
|
||||
|
||||
2) Mode to use (DCB or AVB)::
|
||||
|
||||
u8 mode_to_use;
|
||||
|
||||
3) Credit Base Shaper Parameters::
|
||||
|
||||
u32 send_slope;
|
||||
u32 idle_slope;
|
||||
u32 high_credit;
|
||||
u32 low_credit;
|
||||
|
||||
4) Use priority scheduling, and priority::
|
||||
|
||||
bool use_prio;
|
||||
u32 prio;
|
||||
|
||||
::
|
||||
|
||||
}
|
||||
|
||||
Device Tree Information
|
||||
-----------------------
|
||||
|
||||
Please refer to the following document:
|
||||
Documentation/devicetree/bindings/net/snps,dwmac.yaml
|
||||
|
||||
HW Capabilities
|
||||
---------------
|
||||
|
||||
Note that, starting from new chips, where it is available the HW capability
|
||||
register, many configurations are discovered at run-time for example to
|
||||
understand if EEE, HW csum, PTP, enhanced descriptor etc are actually
|
||||
available. As strategy adopted in this driver, the information from the HW
|
||||
capability register can replace what has been passed from the platform.
|
||||
|
||||
Debug Information
|
||||
=================
|
||||
|
||||
The driver exports many information i.e. internal statistics, debug
|
||||
information, MAC and DMA registers etc.
|
||||
|
||||
These can be read in several ways depending on the type of the information
|
||||
actually needed.
|
||||
|
||||
For example a user can be use the ethtool support to get statistics: e.g.
|
||||
using: ``ethtool -S ethX`` (that shows the Management counters (MMC) if
|
||||
supported) or sees the MAC/DMA registers: e.g. using: ``ethtool -d ethX``
|
||||
|
||||
Compiling the Kernel with ``CONFIG_DEBUG_FS`` the driver will export the
|
||||
following debugfs entries:
|
||||
|
||||
- ``descriptors_status``: To show the DMA TX/RX descriptor rings
|
||||
- ``dma_cap``: To show the HW Capabilities
|
||||
|
||||
Developer can also use the ``debug`` module parameter to get further debug
|
||||
information (please see: NETIF Msg Level).
|
||||
|
||||
Support
|
||||
=======
|
||||
|
||||
If an issue is identified with the released source code on a supported kernel
|
||||
with a supported adapter, email the specific information related to the
|
||||
issue to netdev@vger.kernel.org
|
|
@ -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
|
74
Documentation/networking/devlink/bnxt.rst
Normal file
74
Documentation/networking/devlink/bnxt.rst
Normal file
|
@ -0,0 +1,74 @@
|
|||
.. SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
====================
|
||||
bnxt devlink support
|
||||
====================
|
||||
|
||||
This document describes the devlink features implemented by the ``bnxt``
|
||||
device driver.
|
||||
|
||||
Parameters
|
||||
==========
|
||||
|
||||
.. list-table:: Generic parameters implemented
|
||||
|
||||
* - Name
|
||||
- Mode
|
||||
* - ``enable_sriov``
|
||||
- Permanent
|
||||
* - ``ignore_ari``
|
||||
- Permanent
|
||||
* - ``msix_vec_per_pf_max``
|
||||
- Permanent
|
||||
* - ``msix_vec_per_pf_min``
|
||||
- Permanent
|
||||
|
||||
The ``bnxt`` driver also implements the following driver-specific
|
||||
parameters.
|
||||
|
||||
.. list-table:: Driver-specific parameters implemented
|
||||
:widths: 5 5 5 85
|
||||
|
||||
* - Name
|
||||
- Type
|
||||
- Mode
|
||||
- Description
|
||||
* - ``gre_ver_check``
|
||||
- Boolean
|
||||
- Permanent
|
||||
- Generic Routing Encapsulation (GRE) version check will be enabled in
|
||||
the device. If disabled, the device will skip the version check for
|
||||
incoming packets.
|
||||
|
||||
Info versions
|
||||
=============
|
||||
|
||||
The ``bnxt_en`` driver reports the following versions
|
||||
|
||||
.. list-table:: devlink info versions implemented
|
||||
:widths: 5 5 90
|
||||
|
||||
* - Name
|
||||
- Type
|
||||
- Description
|
||||
* - ``asic.id``
|
||||
- fixed
|
||||
- ASIC design identifier
|
||||
* - ``asic.rev``
|
||||
- fixed
|
||||
- ASIC design revision
|
||||
* - ``fw.psid``
|
||||
- stored, running
|
||||
- Firmware parameter set version of the board
|
||||
* - ``fw``
|
||||
- stored, running
|
||||
- Overall board firmware version
|
||||
* - ``fw.app``
|
||||
- stored, running
|
||||
- Data path firmware version
|
||||
* - ``fw.mgmt``
|
||||
- stored, running
|
||||
- Management firmware version
|
||||
* - ``fw.roce``
|
||||
- stored, running
|
||||
- RoCE management firmware version
|
252
Documentation/networking/devlink/devlink-dpipe.rst
Normal file
252
Documentation/networking/devlink/devlink-dpipe.rst
Normal file
|
@ -0,0 +1,252 @@
|
|||
.. SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
=============
|
||||
Devlink DPIPE
|
||||
=============
|
||||
|
||||
Background
|
||||
==========
|
||||
|
||||
While performing the hardware offloading process, much of the hardware
|
||||
specifics cannot be presented. These details are useful for debugging, and
|
||||
``devlink-dpipe`` provides a standardized way to provide visibility into the
|
||||
offloading process.
|
||||
|
||||
For example, the routing longest prefix match (LPM) algorithm used by the
|
||||
Linux kernel may differ from the hardware implementation. The pipeline debug
|
||||
API (DPIPE) is aimed at providing the user visibility into the ASIC's
|
||||
pipeline in a generic way.
|
||||
|
||||
The hardware offload process is expected to be done in a way that the user
|
||||
should not be able to distinguish between the hardware vs. software
|
||||
implementation. In this process, hardware specifics are neglected. In
|
||||
reality those details can have lots of meaning and should be exposed in some
|
||||
standard way.
|
||||
|
||||
This problem is made even more complex when one wishes to offload the
|
||||
control path of the whole networking stack to a switch ASIC. Due to
|
||||
differences in the hardware and software models some processes cannot be
|
||||
represented correctly.
|
||||
|
||||
One example is the kernel's LPM algorithm which in many cases differs
|
||||
greatly to the hardware implementation. The configuration API is the same,
|
||||
but one cannot rely on the Forward Information Base (FIB) to look like the
|
||||
Level Path Compression trie (LPC-trie) in hardware.
|
||||
|
||||
In many situations trying to analyze systems failure solely based on the
|
||||
kernel's dump may not be enough. By combining this data with complementary
|
||||
information about the underlying hardware, this debugging can be made
|
||||
easier; additionally, the information can be useful when debugging
|
||||
performance issues.
|
||||
|
||||
Overview
|
||||
========
|
||||
|
||||
The ``devlink-dpipe`` interface closes this gap. The hardware's pipeline is
|
||||
modeled as a graph of match/action tables. Each table represents a specific
|
||||
hardware block. This model is not new, first being used by the P4 language.
|
||||
|
||||
Traditionally it has been used as an alternative model for hardware
|
||||
configuration, but the ``devlink-dpipe`` interface uses it for visibility
|
||||
purposes as a standard complementary tool. The system's view from
|
||||
``devlink-dpipe`` should change according to the changes done by the
|
||||
standard configuration tools.
|
||||
|
||||
For example, 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 }
|
||||
}
|
114
Documentation/networking/devlink/devlink-health.rst
Normal file
114
Documentation/networking/devlink/devlink-health.rst
Normal file
|
@ -0,0 +1,114 @@
|
|||
.. SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
==============
|
||||
Devlink Health
|
||||
==============
|
||||
|
||||
Background
|
||||
==========
|
||||
|
||||
The ``devlink`` health mechanism is targeted for Real Time Alerting, in
|
||||
order to know when something bad happened to a PCI device.
|
||||
|
||||
* Provide alert debug information.
|
||||
* Self healing.
|
||||
* If problem needs vendor support, provide a way to gather all needed
|
||||
debugging information.
|
||||
|
||||
Overview
|
||||
========
|
||||
|
||||
The main idea is to unify and centralize driver health reports in the
|
||||
generic ``devlink`` instance and allow the user to set different
|
||||
attributes of the health reporting and recovery procedures.
|
||||
|
||||
The ``devlink`` health reporter:
|
||||
Device driver creates a "health reporter" per each error/health type.
|
||||
Error/Health type can be a known/generic (eg pci error, fw error, rx/tx error)
|
||||
or unknown (driver specific).
|
||||
For each registered health reporter a driver can issue error/health reports
|
||||
asynchronously. All health reports handling is done by ``devlink``.
|
||||
Device driver can provide specific callbacks for each "health reporter", e.g.:
|
||||
|
||||
* Recovery procedures
|
||||
* Diagnostics procedures
|
||||
* Object dump procedures
|
||||
* OOB initial parameters
|
||||
|
||||
Different parts of the driver can register different types of health reporters
|
||||
with different handlers.
|
||||
|
||||
Actions
|
||||
=======
|
||||
|
||||
Once an error is reported, devlink health will perform the following actions:
|
||||
|
||||
* A log is being send to the kernel trace events buffer
|
||||
* Health status and statistics are being updated for the reporter instance
|
||||
* Object dump is being taken and saved at the reporter instance (as long as
|
||||
there is no other dump which is already stored)
|
||||
* Auto recovery attempt is being done. Depends on:
|
||||
- Auto-recovery configuration
|
||||
- Grace period vs. time passed since last recover
|
||||
|
||||
User Interface
|
||||
==============
|
||||
|
||||
User can access/change each reporter's parameters and driver specific callbacks
|
||||
via ``devlink``, e.g per error type (per health reporter):
|
||||
|
||||
* Configure reporter's generic parameters (like: disable/enable auto recovery)
|
||||
* Invoke recovery procedure
|
||||
* Run diagnostics
|
||||
* Object dump
|
||||
|
||||
.. list-table:: List of devlink health interfaces
|
||||
:widths: 10 90
|
||||
|
||||
* - Name
|
||||
- Description
|
||||
* - ``DEVLINK_CMD_HEALTH_REPORTER_GET``
|
||||
- Retrieves status and configuration info per DEV and reporter.
|
||||
* - ``DEVLINK_CMD_HEALTH_REPORTER_SET``
|
||||
- Allows reporter-related configuration setting.
|
||||
* - ``DEVLINK_CMD_HEALTH_REPORTER_RECOVER``
|
||||
- Triggers a reporter's recovery procedure.
|
||||
* - ``DEVLINK_CMD_HEALTH_REPORTER_DIAGNOSE``
|
||||
- Retrieves diagnostics data from a reporter on a device.
|
||||
* - ``DEVLINK_CMD_HEALTH_REPORTER_DUMP_GET``
|
||||
- Retrieves the last stored dump. Devlink health
|
||||
saves a single dump. If an dump is not already stored by the devlink
|
||||
for this reporter, devlink generates a new dump.
|
||||
dump output is defined by the reporter.
|
||||
* - ``DEVLINK_CMD_HEALTH_REPORTER_DUMP_CLEAR``
|
||||
- Clears the last saved dump file for the specified reporter.
|
||||
|
||||
The following diagram provides a general overview of ``devlink-health``::
|
||||
|
||||
netlink
|
||||
+--------------------------+
|
||||
| |
|
||||
| + |
|
||||
| | |
|
||||
+--------------------------+
|
||||
|request for ops
|
||||
|(diagnose,
|
||||
mlx5_core devlink |recover,
|
||||
|dump)
|
||||
+--------+ +--------------------------+
|
||||
| | | reporter| |
|
||||
| | | +---------v----------+ |
|
||||
| | ops execution | | | |
|
||||
| <----------------------------------+ | |
|
||||
| | | | | |
|
||||
| | | + ^------------------+ |
|
||||
| | | | request for ops |
|
||||
| | | | (recover, dump) |
|
||||
| | | | |
|
||||
| | | +-+------------------+ |
|
||||
| | health report | | health handler | |
|
||||
| +-------------------------------> | |
|
||||
| | | +--------------------+ |
|
||||
| | health reporter create | |
|
||||
| +----------------------------> |
|
||||
+--------+ +--------------------------+
|
100
Documentation/networking/devlink/devlink-info.rst
Normal file
100
Documentation/networking/devlink/devlink-info.rst
Normal file
|
@ -0,0 +1,100 @@
|
|||
.. SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
|
||||
============
|
||||
Devlink Info
|
||||
============
|
||||
|
||||
The ``devlink-info`` mechanism enables device drivers to report device
|
||||
information in a generic fashion. It is extensible, and enables exporting
|
||||
even device or driver specific information.
|
||||
|
||||
devlink supports representing the following types of versions
|
||||
|
||||
.. list-table:: List of version types
|
||||
:widths: 5 95
|
||||
|
||||
* - Type
|
||||
- Description
|
||||
* - ``fixed``
|
||||
- Represents fixed versions, which cannot change. For example,
|
||||
component identifiers or the board version reported in the PCI VPD.
|
||||
* - ``running``
|
||||
- Represents the version of the currently running component. For
|
||||
example the running version of firmware. These versions generally
|
||||
only update after a reboot.
|
||||
* - ``stored``
|
||||
- Represents the version of a component as stored, such as after a
|
||||
flash update. Stored values should update to reflect changes in the
|
||||
flash even if a reboot has not yet occurred.
|
||||
|
||||
Generic Versions
|
||||
================
|
||||
|
||||
It is expected that drivers use the following generic names for exporting
|
||||
version information. Other information may be exposed using driver-specific
|
||||
names, but these should be documented in the driver-specific file.
|
||||
|
||||
board.id
|
||||
--------
|
||||
|
||||
Unique identifier of the board design.
|
||||
|
||||
board.rev
|
||||
---------
|
||||
|
||||
Board design revision.
|
||||
|
||||
asic.id
|
||||
-------
|
||||
|
||||
ASIC design identifier.
|
||||
|
||||
asic.rev
|
||||
--------
|
||||
|
||||
ASIC design revision.
|
||||
|
||||
board.manufacture
|
||||
-----------------
|
||||
|
||||
An identifier of the company or the facility which produced the part.
|
||||
|
||||
fw
|
||||
--
|
||||
|
||||
Overall firmware version, often representing the collection of
|
||||
fw.mgmt, fw.app, etc.
|
||||
|
||||
fw.mgmt
|
||||
-------
|
||||
|
||||
Control unit firmware version. This firmware is responsible for house
|
||||
keeping tasks, PHY control etc. but not the packet-by-packet data path
|
||||
operation.
|
||||
|
||||
fw.app
|
||||
------
|
||||
|
||||
Data path microcode controlling high-speed packet processing.
|
||||
|
||||
fw.undi
|
||||
-------
|
||||
|
||||
UNDI software, may include the UEFI driver, firmware or both.
|
||||
|
||||
fw.ncsi
|
||||
-------
|
||||
|
||||
Version of the software responsible for supporting/handling the
|
||||
Network Controller Sideband Interface.
|
||||
|
||||
fw.psid
|
||||
-------
|
||||
|
||||
Unique identifier of the firmware parameter set.
|
||||
|
||||
fw.roce
|
||||
-------
|
||||
|
||||
RoCE firmware version which is responsible for handling roce
|
||||
management.
|
108
Documentation/networking/devlink/devlink-params.rst
Normal file
108
Documentation/networking/devlink/devlink-params.rst
Normal file
|
@ -0,0 +1,108 @@
|
|||
.. SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
==============
|
||||
Devlink Params
|
||||
==============
|
||||
|
||||
``devlink`` provides capability for a driver to expose device parameters for low
|
||||
level device functionality. Since devlink can operate at the device-wide
|
||||
level, it can be used to provide configuration that may affect multiple
|
||||
ports on a single device.
|
||||
|
||||
This document describes a number of generic parameters that are supported
|
||||
across multiple drivers. Each driver is also free to add their own
|
||||
parameters. Each driver must document the specific parameters they support,
|
||||
whether generic or not.
|
||||
|
||||
Configuration modes
|
||||
===================
|
||||
|
||||
Parameters may be set in different configuration modes.
|
||||
|
||||
.. list-table:: Possible configuration modes
|
||||
:widths: 5 90
|
||||
|
||||
* - Name
|
||||
- Description
|
||||
* - ``runtime``
|
||||
- set while the driver is running, and takes effect immediately. No
|
||||
reset is required.
|
||||
* - ``driverinit``
|
||||
- applied while the driver initializes. Requires the user to restart
|
||||
the driver using the ``devlink`` reload command.
|
||||
* - ``permanent``
|
||||
- written to the device's non-volatile memory. A hard reset is required
|
||||
for it to take effect.
|
||||
|
||||
Reloading
|
||||
---------
|
||||
|
||||
In order for ``driverinit`` parameters to take effect, the driver must
|
||||
support reloading via the ``devlink-reload`` command. This command will
|
||||
request a reload of the device driver.
|
||||
|
||||
Generic configuration parameters
|
||||
================================
|
||||
The following is a list of generic configuration parameters that drivers may
|
||||
add. Use of generic parameters is preferred over each driver creating their
|
||||
own name.
|
||||
|
||||
.. list-table:: List of generic parameters
|
||||
:widths: 5 5 90
|
||||
|
||||
* - Name
|
||||
- Type
|
||||
- Description
|
||||
* - ``enable_sriov``
|
||||
- Boolean
|
||||
- Enable Single Root I/O Virtualization (SRIOV) in the device.
|
||||
* - ``ignore_ari``
|
||||
- Boolean
|
||||
- Ignore Alternative Routing-ID Interpretation (ARI) capability. If
|
||||
enabled, the adapter will ignore ARI capability even when the
|
||||
platform has support enabled. The device will create the same number
|
||||
of partitions as when the platform does not support ARI.
|
||||
* - ``msix_vec_per_pf_max``
|
||||
- u32
|
||||
- Provides the maximum number of MSI-X interrupts that a device can
|
||||
create. Value is the same across all physical functions (PFs) in the
|
||||
device.
|
||||
* - ``msix_vec_per_pf_min``
|
||||
- u32
|
||||
- Provides the minimum number of MSI-X interrupts required for the
|
||||
device to initialize. Value is the same across all physical functions
|
||||
(PFs) in the device.
|
||||
* - ``fw_load_policy``
|
||||
- u8
|
||||
- Control the device's firmware loading policy.
|
||||
- ``DEVLINK_PARAM_FW_LOAD_POLICY_VALUE_DRIVER`` (0)
|
||||
Load firmware version preferred by the driver.
|
||||
- ``DEVLINK_PARAM_FW_LOAD_POLICY_VALUE_FLASH`` (1)
|
||||
Load firmware currently stored in flash.
|
||||
- ``DEVLINK_PARAM_FW_LOAD_POLICY_VALUE_DISK`` (2)
|
||||
Load firmware currently available on host's disk.
|
||||
* - ``reset_dev_on_drv_probe``
|
||||
- u8
|
||||
- Controls the device's reset policy on driver probe.
|
||||
- ``DEVLINK_PARAM_RESET_DEV_ON_DRV_PROBE_VALUE_UNKNOWN`` (0)
|
||||
Unknown or invalid value.
|
||||
- ``DEVLINK_PARAM_RESET_DEV_ON_DRV_PROBE_VALUE_ALWAYS`` (1)
|
||||
Always reset device on driver probe.
|
||||
- ``DEVLINK_PARAM_RESET_DEV_ON_DRV_PROBE_VALUE_NEVER`` (2)
|
||||
Never reset device on driver probe.
|
||||
- ``DEVLINK_PARAM_RESET_DEV_ON_DRV_PROBE_VALUE_DISK`` (3)
|
||||
Reset the device only if firmware can be found in the filesystem.
|
||||
* - ``enable_roce``
|
||||
- Boolean
|
||||
- Enable handling of RoCE traffic in the device.
|
||||
* - ``internal_err_reset``
|
||||
- Boolean
|
||||
- When enabled, the device driver will reset the device on internal
|
||||
errors.
|
||||
* - ``max_macs``
|
||||
- u32
|
||||
- Specifies the maximum number of MAC addresses per ethernet port of
|
||||
this device.
|
||||
* - ``region_snapshot_enable``
|
||||
- Boolean
|
||||
- Enable capture of ``devlink-region`` snapshots.
|
60
Documentation/networking/devlink/devlink-region.rst
Normal file
60
Documentation/networking/devlink/devlink-region.rst
Normal file
|
@ -0,0 +1,60 @@
|
|||
.. SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
==============
|
||||
Devlink Region
|
||||
==============
|
||||
|
||||
``devlink`` regions enable access to driver defined address regions using
|
||||
devlink.
|
||||
|
||||
Each device can create and register its own supported address regions. The
|
||||
region can then be accessed via the devlink region interface.
|
||||
|
||||
Region snapshots are collected by the driver, and can be accessed via read
|
||||
or dump commands. This allows future analysis on the created snapshots.
|
||||
Regions may optionally support triggering snapshots on demand.
|
||||
|
||||
The major benefit to creating a region is to provide access to internal
|
||||
address regions that are otherwise inaccessible to the user.
|
||||
|
||||
Regions may also be used to provide an additional way to debug complex error
|
||||
states, but see also :doc:`devlink-health`
|
||||
|
||||
example usage
|
||||
-------------
|
||||
|
||||
.. code:: shell
|
||||
|
||||
$ devlink region help
|
||||
$ devlink region show [ DEV/REGION ]
|
||||
$ devlink region del DEV/REGION snapshot SNAPSHOT_ID
|
||||
$ devlink region dump DEV/REGION [ snapshot SNAPSHOT_ID ]
|
||||
$ devlink region read DEV/REGION [ snapshot SNAPSHOT_ID ]
|
||||
address ADDRESS length length
|
||||
|
||||
# Show all of the exposed regions with region sizes:
|
||||
$ devlink region show
|
||||
pci/0000:00:05.0/cr-space: size 1048576 snapshot [1 2]
|
||||
pci/0000:00:05.0/fw-health: size 64 snapshot [1 2]
|
||||
|
||||
# Delete a snapshot using:
|
||||
$ devlink region del pci/0000:00:05.0/cr-space snapshot 1
|
||||
|
||||
# Trigger (request) a snapshot be taken:
|
||||
$ devlink region trigger pci/0000:00:05.0/cr-space
|
||||
|
||||
# Dump a snapshot:
|
||||
$ devlink region dump pci/0000:00:05.0/fw-health snapshot 1
|
||||
0000000000000000 0014 95dc 0014 9514 0035 1670 0034 db30
|
||||
0000000000000010 0000 0000 ffff ff04 0029 8c00 0028 8cc8
|
||||
0000000000000020 0016 0bb8 0016 1720 0000 0000 c00f 3ffc
|
||||
0000000000000030 bada cce5 bada cce5 bada cce5 bada cce5
|
||||
|
||||
# Read a specific part of a snapshot:
|
||||
$ devlink region read pci/0000:00:05.0/fw-health snapshot 1 address 0
|
||||
length 16
|
||||
0000000000000000 0014 95dc 0014 9514 0035 1670 0034 db30
|
||||
|
||||
As regions are likely very device or driver specific, no generic regions are
|
||||
defined. See the driver-specific documentation files for information on the
|
||||
specific regions a driver supports.
|
62
Documentation/networking/devlink/devlink-resource.rst
Normal file
62
Documentation/networking/devlink/devlink-resource.rst
Normal file
|
@ -0,0 +1,62 @@
|
|||
.. SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
================
|
||||
Devlink Resource
|
||||
================
|
||||
|
||||
``devlink`` provides the ability for drivers to register resources, which
|
||||
can allow administrators to see the device restrictions for a given
|
||||
resource, as well as how much of the given resource is currently
|
||||
in use. Additionally, these resources can optionally have configurable size.
|
||||
This could enable the administrator to limit the number of resources that
|
||||
are used.
|
||||
|
||||
For example, the ``netdevsim`` driver enables ``/IPv4/fib`` and
|
||||
``/IPv4/fib-rules`` as resources to limit the number of IPv4 FIB entries and
|
||||
rules for a given device.
|
||||
|
||||
Resource Ids
|
||||
============
|
||||
|
||||
Each resource is represented by an id, and contains information about its
|
||||
current size and related sub resources. To access a sub resource, you
|
||||
specify the path of the resource. For example ``/IPv4/fib`` is the id for
|
||||
the ``fib`` sub-resource under the ``IPv4`` resource.
|
||||
|
||||
example usage
|
||||
-------------
|
||||
|
||||
The resources exposed by the driver can be observed, for example:
|
||||
|
||||
.. code:: shell
|
||||
|
||||
$devlink resource show pci/0000:03:00.0
|
||||
pci/0000:03:00.0:
|
||||
name kvd size 245760 unit entry
|
||||
resources:
|
||||
name linear size 98304 occ 0 unit entry size_min 0 size_max 147456 size_gran 128
|
||||
name hash_double size 60416 unit entry size_min 32768 size_max 180224 size_gran 128
|
||||
name hash_single size 87040 unit entry size_min 65536 size_max 212992 size_gran 128
|
||||
|
||||
Some resource's size can be changed. Examples:
|
||||
|
||||
.. code:: shell
|
||||
|
||||
$devlink resource set pci/0000:03:00.0 path /kvd/hash_single size 73088
|
||||
$devlink resource set pci/0000:03:00.0 path /kvd/hash_double size 74368
|
||||
|
||||
The changes do not apply immediately, this can be validated by the 'size_new'
|
||||
attribute, which represents the pending change in size. For example:
|
||||
|
||||
.. code:: shell
|
||||
|
||||
$devlink resource show pci/0000:03:00.0
|
||||
pci/0000:03:00.0:
|
||||
name kvd size 245760 unit entry size_valid false
|
||||
resources:
|
||||
name linear size 98304 size_new 147456 occ 0 unit entry size_min 0 size_max 147456 size_gran 128
|
||||
name hash_double size 60416 unit entry size_min 32768 size_max 180224 size_gran 128
|
||||
name hash_single size 87040 unit entry size_min 65536 size_max 212992 size_gran 128
|
||||
|
||||
Note that changes in resource size may require a device reload to properly
|
||||
take effect.
|
|
@ -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
|
||||
=======
|
42
Documentation/networking/devlink/index.rst
Normal file
42
Documentation/networking/devlink/index.rst
Normal file
|
@ -0,0 +1,42 @@
|
|||
Linux Devlink Documentation
|
||||
===========================
|
||||
|
||||
devlink is an API to expose device information and resources not directly
|
||||
related to any device class, such as chip-wide/switch-ASIC-wide configuration.
|
||||
|
||||
Interface documentation
|
||||
-----------------------
|
||||
|
||||
The following pages describe various interfaces available through devlink in
|
||||
general.
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
devlink-dpipe
|
||||
devlink-health
|
||||
devlink-info
|
||||
devlink-params
|
||||
devlink-region
|
||||
devlink-resource
|
||||
devlink-trap
|
||||
|
||||
Driver-specific documentation
|
||||
-----------------------------
|
||||
|
||||
Each driver that implements ``devlink`` is expected to document what
|
||||
parameters, info versions, and other features it supports.
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
bnxt
|
||||
ionic
|
||||
mlx4
|
||||
mlx5
|
||||
mlxsw
|
||||
mv88e6xxx
|
||||
netdevsim
|
||||
nfp
|
||||
qed
|
||||
ti-cpsw-switch
|
29
Documentation/networking/devlink/ionic.rst
Normal file
29
Documentation/networking/devlink/ionic.rst
Normal file
|
@ -0,0 +1,29 @@
|
|||
.. SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
=====================
|
||||
ionic devlink support
|
||||
=====================
|
||||
|
||||
This document describes the devlink features implemented by the ``ionic``
|
||||
device driver.
|
||||
|
||||
Info versions
|
||||
=============
|
||||
|
||||
The ``ionic`` driver reports the following versions
|
||||
|
||||
.. list-table:: devlink info versions implemented
|
||||
:widths: 5 5 90
|
||||
|
||||
* - Name
|
||||
- Type
|
||||
- Description
|
||||
* - ``fw``
|
||||
- running
|
||||
- Version of firmware running on the device
|
||||
* - ``asic.id``
|
||||
- fixed
|
||||
- The ASIC type for this device
|
||||
* - ``asic.rev``
|
||||
- fixed
|
||||
- The revision of the ASIC for this device
|
56
Documentation/networking/devlink/mlx4.rst
Normal file
56
Documentation/networking/devlink/mlx4.rst
Normal file
|
@ -0,0 +1,56 @@
|
|||
.. SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
====================
|
||||
mlx4 devlink support
|
||||
====================
|
||||
|
||||
This document describes the devlink features implemented by the ``mlx4``
|
||||
device driver.
|
||||
|
||||
Parameters
|
||||
==========
|
||||
|
||||
.. list-table:: Generic parameters implemented
|
||||
|
||||
* - Name
|
||||
- Mode
|
||||
* - ``internal_err_reset``
|
||||
- driverinit, runtime
|
||||
* - ``max_macs``
|
||||
- driverinit
|
||||
* - ``region_snapshot_enable``
|
||||
- driverinit, runtime
|
||||
|
||||
The ``mlx4`` driver also implements the following driver-specific
|
||||
parameters.
|
||||
|
||||
.. list-table:: Driver-specific parameters implemented
|
||||
:widths: 5 5 5 85
|
||||
|
||||
* - Name
|
||||
- Type
|
||||
- Mode
|
||||
- Description
|
||||
* - ``enable_64b_cqe_eqe``
|
||||
- Boolean
|
||||
- driverinit
|
||||
- Enable 64 byte CQEs/EQEs, if the FW supports it.
|
||||
* - ``enable_4k_uar``
|
||||
- Boolean
|
||||
- driverinit
|
||||
- Enable using the 4k UAR.
|
||||
|
||||
The ``mlx4`` driver supports reloading via ``DEVLINK_CMD_RELOAD``
|
||||
|
||||
Regions
|
||||
=======
|
||||
|
||||
The ``mlx4`` driver supports dumping the firmware PCI crspace and health
|
||||
buffer during a critical firmware issue.
|
||||
|
||||
In case a firmware command times out, firmware getting stuck, or a non zero
|
||||
value on the catastrophic buffer, a snapshot will be taken by the driver.
|
||||
|
||||
The ``cr-space`` region will contain the firmware PCI crspace contents. The
|
||||
``fw-health`` region will contain the device firmware's health buffer.
|
||||
Snapshots for both of these regions are taken on the same event triggers.
|
59
Documentation/networking/devlink/mlx5.rst
Normal file
59
Documentation/networking/devlink/mlx5.rst
Normal file
|
@ -0,0 +1,59 @@
|
|||
.. SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
====================
|
||||
mlx5 devlink support
|
||||
====================
|
||||
|
||||
This document describes the devlink features implemented by the ``mlx5``
|
||||
device driver.
|
||||
|
||||
Parameters
|
||||
==========
|
||||
|
||||
.. list-table:: Generic parameters implemented
|
||||
|
||||
* - Name
|
||||
- Mode
|
||||
* - ``enable_roce``
|
||||
- driverinit
|
||||
|
||||
The ``mlx5`` driver also implements the following driver-specific
|
||||
parameters.
|
||||
|
||||
.. list-table:: Driver-specific parameters implemented
|
||||
:widths: 5 5 5 85
|
||||
|
||||
* - Name
|
||||
- Type
|
||||
- Mode
|
||||
- Description
|
||||
* - ``flow_steering_mode``
|
||||
- string
|
||||
- runtime
|
||||
- Controls the flow steering mode of the driver
|
||||
|
||||
* ``dmfs`` Device managed flow steering. In DMFS mode, the HW
|
||||
steering entities are created and managed through firmware.
|
||||
* ``smfs`` Software managed flow steering. In SMFS mode, the HW
|
||||
steering entities are created and manage through the driver without
|
||||
firmware intervention.
|
||||
|
||||
The ``mlx5`` driver supports reloading via ``DEVLINK_CMD_RELOAD``
|
||||
|
||||
Info versions
|
||||
=============
|
||||
|
||||
The ``mlx5`` driver reports the following versions
|
||||
|
||||
.. list-table:: devlink info versions implemented
|
||||
:widths: 5 5 90
|
||||
|
||||
* - Name
|
||||
- Type
|
||||
- Description
|
||||
* - ``fw.psid``
|
||||
- fixed
|
||||
- Used to represent the board id of the device.
|
||||
* - ``fw.version``
|
||||
- stored, running
|
||||
- Three digit major.minor.subminor firmware version number.
|
81
Documentation/networking/devlink/mlxsw.rst
Normal file
81
Documentation/networking/devlink/mlxsw.rst
Normal file
|
@ -0,0 +1,81 @@
|
|||
.. SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
=====================
|
||||
mlxsw devlink support
|
||||
=====================
|
||||
|
||||
This document describes the devlink features implemented by the ``mlxsw``
|
||||
device driver.
|
||||
|
||||
Parameters
|
||||
==========
|
||||
|
||||
.. list-table:: Generic parameters implemented
|
||||
|
||||
* - Name
|
||||
- Mode
|
||||
* - ``fw_load_policy``
|
||||
- driverinit
|
||||
|
||||
The ``mlxsw`` driver also implements the following driver-specific
|
||||
parameters.
|
||||
|
||||
.. list-table:: Driver-specific parameters implemented
|
||||
:widths: 5 5 5 85
|
||||
|
||||
* - Name
|
||||
- Type
|
||||
- Mode
|
||||
- Description
|
||||
* - ``acl_region_rehash_interval``
|
||||
- u32
|
||||
- runtime
|
||||
- Sets an interval for periodic ACL region rehashes. The value is
|
||||
specified in milliseconds, with a minimum of ``3000``. The value of
|
||||
``0`` disables periodic work entirely. The first rehash will be run
|
||||
immediately after the value is set.
|
||||
|
||||
The ``mlxsw`` driver supports reloading via ``DEVLINK_CMD_RELOAD``
|
||||
|
||||
Info versions
|
||||
=============
|
||||
|
||||
The ``mlxsw`` driver reports the following versions
|
||||
|
||||
.. list-table:: devlink info versions implemented
|
||||
:widths: 5 5 90
|
||||
|
||||
* - Name
|
||||
- Type
|
||||
- Description
|
||||
* - ``hw.revision``
|
||||
- fixed
|
||||
- The hardware revision for this board
|
||||
* - ``fw.psid``
|
||||
- fixed
|
||||
- Firmware PSID
|
||||
* - ``fw.version``
|
||||
- running
|
||||
- Three digit firmware version
|
||||
|
||||
Driver-specific Traps
|
||||
=====================
|
||||
|
||||
.. list-table:: List of Driver-specific Traps Registered by ``mlxsw``
|
||||
:widths: 5 5 90
|
||||
|
||||
* - Name
|
||||
- Type
|
||||
- Description
|
||||
* - ``irif_disabled``
|
||||
- ``drop``
|
||||
- Traps packets that the device decided to drop because they need to be
|
||||
routed from a disabled router interface (RIF). This can happen during
|
||||
RIF dismantle, when the RIF is first disabled before being removed
|
||||
completely
|
||||
* - ``erif_disabled``
|
||||
- ``drop``
|
||||
- Traps packets that the device decided to drop because they need to be
|
||||
routed through a disabled router interface (RIF). This can happen during
|
||||
RIF dismantle, when the RIF is first disabled before being removed
|
||||
completely
|
28
Documentation/networking/devlink/mv88e6xxx.rst
Normal file
28
Documentation/networking/devlink/mv88e6xxx.rst
Normal file
|
@ -0,0 +1,28 @@
|
|||
.. SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
=========================
|
||||
mv88e6xxx devlink support
|
||||
=========================
|
||||
|
||||
This document describes the devlink features implemented by the ``mv88e6xxx``
|
||||
device driver.
|
||||
|
||||
Parameters
|
||||
==========
|
||||
|
||||
The ``mv88e6xxx`` driver implements the following driver-specific parameters.
|
||||
|
||||
.. list-table:: Driver-specific parameters implemented
|
||||
:widths: 5 5 5 85
|
||||
|
||||
* - Name
|
||||
- Type
|
||||
- Mode
|
||||
- Description
|
||||
* - ``ATU_hash``
|
||||
- u8
|
||||
- runtime
|
||||
- Select one of four possible hashing algorithms for MAC addresses in
|
||||
the Address Translation Unit. A value of 3 may work better than the
|
||||
default of 1 when many MAC addresses have the same OUI. Only the
|
||||
values 0 to 3 are valid for this parameter.
|
72
Documentation/networking/devlink/netdevsim.rst
Normal file
72
Documentation/networking/devlink/netdevsim.rst
Normal file
|
@ -0,0 +1,72 @@
|
|||
.. SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
=========================
|
||||
netdevsim devlink support
|
||||
=========================
|
||||
|
||||
This document describes the ``devlink`` features supported by the
|
||||
``netdevsim`` device driver.
|
||||
|
||||
Parameters
|
||||
==========
|
||||
|
||||
.. list-table:: Generic parameters implemented
|
||||
|
||||
* - Name
|
||||
- Mode
|
||||
* - ``max_macs``
|
||||
- driverinit
|
||||
|
||||
The ``netdevsim`` driver also implements the following driver-specific
|
||||
parameters.
|
||||
|
||||
.. list-table:: Driver-specific parameters implemented
|
||||
:widths: 5 5 5 85
|
||||
|
||||
* - Name
|
||||
- Type
|
||||
- Mode
|
||||
- Description
|
||||
* - ``test1``
|
||||
- Boolean
|
||||
- driverinit
|
||||
- Test parameter used to show how a driver-specific devlink parameter
|
||||
can be implemented.
|
||||
|
||||
The ``netdevsim`` driver supports reloading via ``DEVLINK_CMD_RELOAD``
|
||||
|
||||
Regions
|
||||
=======
|
||||
|
||||
The ``netdevsim`` driver exposes a ``dummy`` region as an example of how the
|
||||
devlink-region interfaces work. A snapshot is taken whenever the
|
||||
``take_snapshot`` debugfs file is written to.
|
||||
|
||||
Resources
|
||||
=========
|
||||
|
||||
The ``netdevsim`` driver exposes resources to control the number of FIB
|
||||
entries and FIB rule entries that the driver will allow.
|
||||
|
||||
.. code:: shell
|
||||
|
||||
$ devlink resource set netdevsim/netdevsim0 path /IPv4/fib size 96
|
||||
$ devlink resource set netdevsim/netdevsim0 path /IPv4/fib-rules size 16
|
||||
$ devlink resource set netdevsim/netdevsim0 path /IPv6/fib size 64
|
||||
$ devlink resource set netdevsim/netdevsim0 path /IPv6/fib-rules size 16
|
||||
$ devlink dev reload netdevsim/netdevsim0
|
||||
|
||||
Driver-specific Traps
|
||||
=====================
|
||||
|
||||
.. list-table:: List of Driver-specific Traps Registered by ``netdevsim``
|
||||
:widths: 5 5 90
|
||||
|
||||
* - Name
|
||||
- Type
|
||||
- Description
|
||||
* - ``fid_miss``
|
||||
- ``exception``
|
||||
- When a packet enters the device it is classified to a filtering
|
||||
indentifier (FID) based on the ingress port and VLAN. This trap is used
|
||||
to trap packets for which a FID could not be found
|
65
Documentation/networking/devlink/nfp.rst
Normal file
65
Documentation/networking/devlink/nfp.rst
Normal file
|
@ -0,0 +1,65 @@
|
|||
.. SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
===================
|
||||
nfp devlink support
|
||||
===================
|
||||
|
||||
This document describes the devlink features implemented by the ``nfp``
|
||||
device driver.
|
||||
|
||||
Parameters
|
||||
==========
|
||||
|
||||
.. list-table:: Generic parameters implemented
|
||||
|
||||
* - Name
|
||||
- Mode
|
||||
* - ``fw_load_policy``
|
||||
- permanent
|
||||
* - ``reset_dev_on_drv_probe``
|
||||
- permanent
|
||||
|
||||
Info versions
|
||||
=============
|
||||
|
||||
The ``nfp`` driver reports the following versions
|
||||
|
||||
.. list-table:: devlink info versions implemented
|
||||
:widths: 5 5 90
|
||||
|
||||
* - Name
|
||||
- Type
|
||||
- Description
|
||||
* - ``board.id``
|
||||
- fixed
|
||||
- Part number identifying the board design
|
||||
* - ``board.rev``
|
||||
- fixed
|
||||
- Revision of the board design
|
||||
* - ``board.manufacture``
|
||||
- fixed
|
||||
- Vendor of the board design
|
||||
* - ``board.model``
|
||||
- fixed
|
||||
- Model name of the board design
|
||||
* - ``fw.bundle_id``
|
||||
- stored, running
|
||||
- Firmware bundle id
|
||||
* - ``fw.mgmt``
|
||||
- stored, running
|
||||
- Version of the management firmware
|
||||
* - ``fw.cpld``
|
||||
- stored, running
|
||||
- The CPLD firmware component version
|
||||
* - ``fw.app``
|
||||
- stored, running
|
||||
- The APP firmware component version
|
||||
* - ``fw.undi``
|
||||
- stored, running
|
||||
- The UNDI firmware component version
|
||||
* - ``fw.ncsi``
|
||||
- stored, running
|
||||
- The NSCI firmware component version
|
||||
* - ``chip.init``
|
||||
- stored, running
|
||||
- The CFGR firmware component version
|
26
Documentation/networking/devlink/qed.rst
Normal file
26
Documentation/networking/devlink/qed.rst
Normal file
|
@ -0,0 +1,26 @@
|
|||
.. SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
===================
|
||||
qed devlink support
|
||||
===================
|
||||
|
||||
This document describes the devlink features implemented by the ``qed`` core
|
||||
device driver.
|
||||
|
||||
Parameters
|
||||
==========
|
||||
|
||||
The ``qed`` driver implements the following driver-specific parameters.
|
||||
|
||||
.. list-table:: Driver-specific parameters implemented
|
||||
:widths: 5 5 5 85
|
||||
|
||||
* - Name
|
||||
- Type
|
||||
- Mode
|
||||
- Description
|
||||
* - ``iwarp_cmt``
|
||||
- Boolean
|
||||
- runtime
|
||||
- Enable iWARP functionality for 100g devices. Note that this impacts
|
||||
L2 performance, and is therefore not enabled by default.
|
31
Documentation/networking/devlink/ti-cpsw-switch.rst
Normal file
31
Documentation/networking/devlink/ti-cpsw-switch.rst
Normal file
|
@ -0,0 +1,31 @@
|
|||
.. SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
==============================
|
||||
ti-cpsw-switch devlink support
|
||||
==============================
|
||||
|
||||
This document describes the devlink features implemented by the ``ti-cpsw-switch``
|
||||
device driver.
|
||||
|
||||
Parameters
|
||||
==========
|
||||
|
||||
The ``ti-cpsw-switch`` driver implements the following driver-specific
|
||||
parameters.
|
||||
|
||||
.. list-table:: Driver-specific parameters implemented
|
||||
:widths: 5 5 5 85
|
||||
|
||||
* - Name
|
||||
- Type
|
||||
- Mode
|
||||
- Description
|
||||
* - ``ale_bypass``
|
||||
- Boolean
|
||||
- runtime
|
||||
- Enables ALE_CONTROL(4).BYPASS mode for debugging purposes. In this
|
||||
mode, all packets will be sent to the host port only.
|
||||
* - ``switch_mode``
|
||||
- Boolean
|
||||
- runtime
|
||||
- Enable switch mode
|
618
Documentation/networking/ethtool-netlink.rst
Normal file
618
Documentation/networking/ethtool-netlink.rst
Normal file
|
@ -0,0 +1,618 @@
|
|||
=============================
|
||||
Netlink interface for ethtool
|
||||
=============================
|
||||
|
||||
|
||||
Basic information
|
||||
=================
|
||||
|
||||
Netlink interface for ethtool uses generic netlink family ``ethtool``
|
||||
(userspace application should use macros ``ETHTOOL_GENL_NAME`` and
|
||||
``ETHTOOL_GENL_VERSION`` defined in ``<linux/ethtool_netlink.h>`` uapi
|
||||
header). This family does not use a specific header, all information in
|
||||
requests and replies is passed using netlink attributes.
|
||||
|
||||
The ethtool netlink interface uses extended ACK for error and warning
|
||||
reporting, userspace application developers are encouraged to make these
|
||||
messages available to user in a suitable way.
|
||||
|
||||
Requests can be divided into three categories: "get" (retrieving information),
|
||||
"set" (setting parameters) and "action" (invoking an action).
|
||||
|
||||
All "set" and "action" type requests require admin privileges
|
||||
(``CAP_NET_ADMIN`` in the namespace). Most "get" type requests are allowed for
|
||||
anyone but there are exceptions (where the response contains sensitive
|
||||
information). In some cases, the request as such is allowed for anyone but
|
||||
unprivileged users have attributes with sensitive information (e.g.
|
||||
wake-on-lan password) omitted.
|
||||
|
||||
|
||||
Conventions
|
||||
===========
|
||||
|
||||
Attributes which represent a boolean value usually use NLA_U8 type so that we
|
||||
can distinguish three states: "on", "off" and "not present" (meaning the
|
||||
information is not available in "get" requests or value is not to be changed
|
||||
in "set" requests). For these attributes, the "true" value should be passed as
|
||||
number 1 but any non-zero value should be understood as "true" by recipient.
|
||||
In the tables below, "bool" denotes NLA_U8 attributes interpreted in this way.
|
||||
|
||||
In the message structure descriptions below, if an attribute name is suffixed
|
||||
with "+", parent nest can contain multiple attributes of the same type. This
|
||||
implements an array of entries.
|
||||
|
||||
|
||||
Request header
|
||||
==============
|
||||
|
||||
Each request or reply message contains a nested attribute with common header.
|
||||
Structure of this header is
|
||||
|
||||
============================== ====== =============================
|
||||
``ETHTOOL_A_HEADER_DEV_INDEX`` u32 device ifindex
|
||||
``ETHTOOL_A_HEADER_DEV_NAME`` string device name
|
||||
``ETHTOOL_A_HEADER_FLAGS`` u32 flags common for all requests
|
||||
============================== ====== =============================
|
||||
|
||||
``ETHTOOL_A_HEADER_DEV_INDEX`` and ``ETHTOOL_A_HEADER_DEV_NAME`` identify the
|
||||
device message relates to. One of them is sufficient in requests, if both are
|
||||
used, they must identify the same device. Some requests, e.g. global string
|
||||
sets, do not require device identification. Most ``GET`` requests also allow
|
||||
dump requests without device identification to query the same information for
|
||||
all devices providing it (each device in a separate message).
|
||||
|
||||
``ETHTOOL_A_HEADER_FLAGS`` is a bitmap of request flags common for all request
|
||||
types. The interpretation of these flags is the same for all request types but
|
||||
the flags may not apply to requests. Recognized flags are:
|
||||
|
||||
================================= ===================================
|
||||
``ETHTOOL_FLAG_COMPACT_BITSETS`` use compact format bitsets in reply
|
||||
``ETHTOOL_FLAG_OMIT_REPLY`` omit optional reply (_SET and _ACT)
|
||||
================================= ===================================
|
||||
|
||||
New request flags should follow the general idea that if the flag is not set,
|
||||
the behaviour is backward compatible, i.e. requests from old clients not aware
|
||||
of the flag should be interpreted the way the client expects. A client must
|
||||
not set flags it does not understand.
|
||||
|
||||
|
||||
Bit sets
|
||||
========
|
||||
|
||||
For short bitmaps of (reasonably) fixed length, standard ``NLA_BITFIELD32``
|
||||
type is used. For arbitrary length bitmaps, ethtool netlink uses a nested
|
||||
attribute with contents of one of two forms: compact (two binary bitmaps
|
||||
representing bit values and mask of affected bits) and bit-by-bit (list of
|
||||
bits identified by either index or name).
|
||||
|
||||
Verbose (bit-by-bit) bitsets allow sending symbolic names for bits together
|
||||
with their values which saves a round trip (when the bitset is passed in a
|
||||
request) or at least a second request (when the bitset is in a reply). This is
|
||||
useful for one shot applications like traditional ethtool command. On the
|
||||
other hand, long running applications like ethtool monitor (displaying
|
||||
notifications) or network management daemons may prefer fetching the names
|
||||
only once and using compact form to save message size. Notifications from
|
||||
ethtool netlink interface always use compact form for bitsets.
|
||||
|
||||
A bitset can represent either a value/mask pair (``ETHTOOL_A_BITSET_NOMASK``
|
||||
not set) or a single bitmap (``ETHTOOL_A_BITSET_NOMASK`` set). In requests
|
||||
modifying a bitmap, the former changes the bit set in mask to values set in
|
||||
value and preserves the rest; the latter sets the bits set in the bitmap and
|
||||
clears the rest.
|
||||
|
||||
Compact form: nested (bitset) atrribute contents:
|
||||
|
||||
============================ ====== ============================
|
||||
``ETHTOOL_A_BITSET_NOMASK`` flag no mask, only a list
|
||||
``ETHTOOL_A_BITSET_SIZE`` u32 number of significant bits
|
||||
``ETHTOOL_A_BITSET_VALUE`` binary bitmap of bit values
|
||||
``ETHTOOL_A_BITSET_MASK`` binary bitmap of valid bits
|
||||
============================ ====== ============================
|
||||
|
||||
Value and mask must have length at least ``ETHTOOL_A_BITSET_SIZE`` bits
|
||||
rounded up to a multiple of 32 bits. They consist of 32-bit words in host byte
|
||||
order, words ordered from least significant to most significant (i.e. the same
|
||||
way as bitmaps are passed with ioctl interface).
|
||||
|
||||
For compact form, ``ETHTOOL_A_BITSET_SIZE`` and ``ETHTOOL_A_BITSET_VALUE`` are
|
||||
mandatory. ``ETHTOOL_A_BITSET_MASK`` attribute is mandatory if
|
||||
``ETHTOOL_A_BITSET_NOMASK`` is not set (bitset represents a value/mask pair);
|
||||
if ``ETHTOOL_A_BITSET_NOMASK`` is not set, ``ETHTOOL_A_BITSET_MASK`` is not
|
||||
allowed (bitset represents a single bitmap.
|
||||
|
||||
Kernel bit set length may differ from userspace length if older application is
|
||||
used on newer kernel or vice versa. If userspace bitmap is longer, an error is
|
||||
issued only if the request actually tries to set values of some bits not
|
||||
recognized by kernel.
|
||||
|
||||
Bit-by-bit form: nested (bitset) attribute contents:
|
||||
|
||||
+------------------------------------+--------+-----------------------------+
|
||||
| ``ETHTOOL_A_BITSET_NOMASK`` | flag | no mask, only a list |
|
||||
+------------------------------------+--------+-----------------------------+
|
||||
| ``ETHTOOL_A_BITSET_SIZE`` | u32 | number of significant bits |
|
||||
+------------------------------------+--------+-----------------------------+
|
||||
| ``ETHTOOL_A_BITSET_BITS`` | nested | array of bits |
|
||||
+-+----------------------------------+--------+-----------------------------+
|
||||
| | ``ETHTOOL_A_BITSET_BITS_BIT+`` | nested | one bit |
|
||||
+-+-+--------------------------------+--------+-----------------------------+
|
||||
| | | ``ETHTOOL_A_BITSET_BIT_INDEX`` | u32 | bit index (0 for LSB) |
|
||||
+-+-+--------------------------------+--------+-----------------------------+
|
||||
| | | ``ETHTOOL_A_BITSET_BIT_NAME`` | string | bit name |
|
||||
+-+-+--------------------------------+--------+-----------------------------+
|
||||
| | | ``ETHTOOL_A_BITSET_BIT_VALUE`` | flag | present if bit is set |
|
||||
+-+-+--------------------------------+--------+-----------------------------+
|
||||
|
||||
Bit size is optional for bit-by-bit form. ``ETHTOOL_A_BITSET_BITS`` nest can
|
||||
only contain ``ETHTOOL_A_BITSET_BITS_BIT`` attributes but there can be an
|
||||
arbitrary number of them. A bit may be identified by its index or by its
|
||||
name. When used in requests, listed bits are set to 0 or 1 according to
|
||||
``ETHTOOL_A_BITSET_BIT_VALUE``, the rest is preserved. A request fails if
|
||||
index exceeds kernel bit length or if name is not recognized.
|
||||
|
||||
When ``ETHTOOL_A_BITSET_NOMASK`` flag is present, bitset is interpreted as
|
||||
a simple bitmap. ``ETHTOOL_A_BITSET_BIT_VALUE`` attributes are not used in
|
||||
such case. Such bitset represents a bitmap with listed bits set and the rest
|
||||
zero.
|
||||
|
||||
In requests, application can use either form. Form used by kernel in reply is
|
||||
determined by ``ETHTOOL_FLAG_COMPACT_BITSETS`` flag in flags field of request
|
||||
header. Semantics of value and mask depends on the attribute.
|
||||
|
||||
|
||||
List of message types
|
||||
=====================
|
||||
|
||||
All constants identifying message types use ``ETHTOOL_CMD_`` prefix and suffix
|
||||
according to message purpose:
|
||||
|
||||
============== ======================================
|
||||
``_GET`` userspace request to retrieve data
|
||||
``_SET`` userspace request to set data
|
||||
``_ACT`` userspace request to perform an action
|
||||
``_GET_REPLY`` kernel reply to a ``GET`` request
|
||||
``_SET_REPLY`` kernel reply to a ``SET`` request
|
||||
``_ACT_REPLY`` kernel reply to an ``ACT`` request
|
||||
``_NTF`` kernel notification
|
||||
============== ======================================
|
||||
|
||||
Userspace to kernel:
|
||||
|
||||
===================================== ================================
|
||||
``ETHTOOL_MSG_STRSET_GET`` get string set
|
||||
``ETHTOOL_MSG_LINKINFO_GET`` get link settings
|
||||
``ETHTOOL_MSG_LINKINFO_SET`` set link settings
|
||||
``ETHTOOL_MSG_LINKMODES_GET`` get link modes info
|
||||
``ETHTOOL_MSG_LINKMODES_SET`` set link modes info
|
||||
``ETHTOOL_MSG_LINKSTATE_GET`` get link state
|
||||
``ETHTOOL_MSG_DEBUG_GET`` get debugging settings
|
||||
``ETHTOOL_MSG_DEBUG_SET`` set debugging settings
|
||||
``ETHTOOL_MSG_WOL_GET`` get wake-on-lan settings
|
||||
``ETHTOOL_MSG_WOL_SET`` set wake-on-lan settings
|
||||
===================================== ================================
|
||||
|
||||
Kernel to userspace:
|
||||
|
||||
===================================== =================================
|
||||
``ETHTOOL_MSG_STRSET_GET_REPLY`` string set contents
|
||||
``ETHTOOL_MSG_LINKINFO_GET_REPLY`` link settings
|
||||
``ETHTOOL_MSG_LINKINFO_NTF`` link settings notification
|
||||
``ETHTOOL_MSG_LINKMODES_GET_REPLY`` link modes info
|
||||
``ETHTOOL_MSG_LINKMODES_NTF`` link modes notification
|
||||
``ETHTOOL_MSG_LINKSTATE_GET_REPLY`` link state info
|
||||
``ETHTOOL_MSG_DEBUG_GET_REPLY`` debugging settings
|
||||
``ETHTOOL_MSG_DEBUG_NTF`` debugging settings notification
|
||||
``ETHTOOL_MSG_WOL_GET_REPLY`` wake-on-lan settings
|
||||
``ETHTOOL_MSG_WOL_NTF`` wake-on-lan settings notification
|
||||
===================================== =================================
|
||||
|
||||
``GET`` requests are sent by userspace applications to retrieve device
|
||||
information. They usually do not contain any message specific attributes.
|
||||
Kernel replies with corresponding "GET_REPLY" message. For most types, ``GET``
|
||||
request with ``NLM_F_DUMP`` and no device identification can be used to query
|
||||
the information for all devices supporting the request.
|
||||
|
||||
If the data can be also modified, corresponding ``SET`` message with the same
|
||||
layout as corresponding ``GET_REPLY`` is used to request changes. Only
|
||||
attributes where a change is requested are included in such request (also, not
|
||||
all attributes may be changed). Replies to most ``SET`` request consist only
|
||||
of error code and extack; if kernel provides additional data, it is sent in
|
||||
the form of corresponding ``SET_REPLY`` message which can be suppressed by
|
||||
setting ``ETHTOOL_FLAG_OMIT_REPLY`` flag in request header.
|
||||
|
||||
Data modification also triggers sending a ``NTF`` message with a notification.
|
||||
These usually bear only a subset of attributes which was affected by the
|
||||
change. The same notification is issued if the data is modified using other
|
||||
means (mostly ioctl ethtool interface). Unlike notifications from ethtool
|
||||
netlink code which are only sent if something actually changed, notifications
|
||||
triggered by ioctl interface may be sent even if the request did not actually
|
||||
change any data.
|
||||
|
||||
``ACT`` messages request kernel (driver) to perform a specific action. If some
|
||||
information is reported by kernel (which can be suppressed by setting
|
||||
``ETHTOOL_FLAG_OMIT_REPLY`` flag in request header), the reply takes form of
|
||||
an ``ACT_REPLY`` message. Performing an action also triggers a notification
|
||||
(``NTF`` message).
|
||||
|
||||
Later sections describe the format and semantics of these messages.
|
||||
|
||||
|
||||
STRSET_GET
|
||||
==========
|
||||
|
||||
Requests contents of a string set as provided by ioctl commands
|
||||
``ETHTOOL_GSSET_INFO`` and ``ETHTOOL_GSTRINGS.`` String sets are not user
|
||||
writeable so that the corresponding ``STRSET_SET`` message is only used in
|
||||
kernel replies. There are two types of string sets: global (independent of
|
||||
a device, e.g. device feature names) and device specific (e.g. device private
|
||||
flags).
|
||||
|
||||
Request contents:
|
||||
|
||||
+---------------------------------------+--------+------------------------+
|
||||
| ``ETHTOOL_A_STRSET_HEADER`` | nested | request header |
|
||||
+---------------------------------------+--------+------------------------+
|
||||
| ``ETHTOOL_A_STRSET_STRINGSETS`` | nested | string set to request |
|
||||
+-+-------------------------------------+--------+------------------------+
|
||||
| | ``ETHTOOL_A_STRINGSETS_STRINGSET+`` | nested | one string set |
|
||||
+-+-+-----------------------------------+--------+------------------------+
|
||||
| | | ``ETHTOOL_A_STRINGSET_ID`` | u32 | set id |
|
||||
+-+-+-----------------------------------+--------+------------------------+
|
||||
|
||||
Kernel response contents:
|
||||
|
||||
+---------------------------------------+--------+-----------------------+
|
||||
| ``ETHTOOL_A_STRSET_HEADER`` | nested | reply header |
|
||||
+---------------------------------------+--------+-----------------------+
|
||||
| ``ETHTOOL_A_STRSET_STRINGSETS`` | nested | array of string sets |
|
||||
+-+-------------------------------------+--------+-----------------------+
|
||||
| | ``ETHTOOL_A_STRINGSETS_STRINGSET+`` | nested | one string set |
|
||||
+-+-+-----------------------------------+--------+-----------------------+
|
||||
| | | ``ETHTOOL_A_STRINGSET_ID`` | u32 | set id |
|
||||
+-+-+-----------------------------------+--------+-----------------------+
|
||||
| | | ``ETHTOOL_A_STRINGSET_COUNT`` | u32 | number of strings |
|
||||
+-+-+-----------------------------------+--------+-----------------------+
|
||||
| | | ``ETHTOOL_A_STRINGSET_STRINGS`` | nested | array of strings |
|
||||
+-+-+-+---------------------------------+--------+-----------------------+
|
||||
| | | | ``ETHTOOL_A_STRINGS_STRING+`` | nested | one string |
|
||||
+-+-+-+-+-------------------------------+--------+-----------------------+
|
||||
| | | | | ``ETHTOOL_A_STRING_INDEX`` | u32 | string index |
|
||||
+-+-+-+-+-------------------------------+--------+-----------------------+
|
||||
| | | | | ``ETHTOOL_A_STRING_VALUE`` | string | string value |
|
||||
+-+-+-+-+-------------------------------+--------+-----------------------+
|
||||
| ``ETHTOOL_A_STRSET_COUNTS_ONLY`` | flag | return only counts |
|
||||
+---------------------------------------+--------+-----------------------+
|
||||
|
||||
Device identification in request header is optional. Depending on its presence
|
||||
a and ``NLM_F_DUMP`` flag, there are three type of ``STRSET_GET`` requests:
|
||||
|
||||
- no ``NLM_F_DUMP,`` no device: get "global" stringsets
|
||||
- no ``NLM_F_DUMP``, with device: get string sets related to the device
|
||||
- ``NLM_F_DUMP``, no device: get device related string sets for all devices
|
||||
|
||||
If there is no ``ETHTOOL_A_STRSET_STRINGSETS`` array, all string sets of
|
||||
requested type are returned, otherwise only those specified in the request.
|
||||
Flag ``ETHTOOL_A_STRSET_COUNTS_ONLY`` tells kernel to only return string
|
||||
counts of the sets, not the actual strings.
|
||||
|
||||
|
||||
LINKINFO_GET
|
||||
============
|
||||
|
||||
Requests link settings as provided by ``ETHTOOL_GLINKSETTINGS`` except for
|
||||
link modes and autonegotiation related information. The request does not use
|
||||
any attributes.
|
||||
|
||||
Request contents:
|
||||
|
||||
==================================== ====== ==========================
|
||||
``ETHTOOL_A_LINKINFO_HEADER`` nested request header
|
||||
==================================== ====== ==========================
|
||||
|
||||
Kernel response contents:
|
||||
|
||||
==================================== ====== ==========================
|
||||
``ETHTOOL_A_LINKINFO_HEADER`` nested reply header
|
||||
``ETHTOOL_A_LINKINFO_PORT`` u8 physical port
|
||||
``ETHTOOL_A_LINKINFO_PHYADDR`` u8 phy MDIO address
|
||||
``ETHTOOL_A_LINKINFO_TP_MDIX`` u8 MDI(-X) status
|
||||
``ETHTOOL_A_LINKINFO_TP_MDIX_CTRL`` u8 MDI(-X) control
|
||||
``ETHTOOL_A_LINKINFO_TRANSCEIVER`` u8 transceiver
|
||||
==================================== ====== ==========================
|
||||
|
||||
Attributes and their values have the same meaning as matching members of the
|
||||
corresponding ioctl structures.
|
||||
|
||||
``LINKINFO_GET`` allows dump requests (kernel returns reply message for all
|
||||
devices supporting the request).
|
||||
|
||||
|
||||
LINKINFO_SET
|
||||
============
|
||||
|
||||
``LINKINFO_SET`` request allows setting some of the attributes reported by
|
||||
``LINKINFO_GET``.
|
||||
|
||||
Request contents:
|
||||
|
||||
==================================== ====== ==========================
|
||||
``ETHTOOL_A_LINKINFO_HEADER`` nested request header
|
||||
``ETHTOOL_A_LINKINFO_PORT`` u8 physical port
|
||||
``ETHTOOL_A_LINKINFO_PHYADDR`` u8 phy MDIO address
|
||||
``ETHTOOL_A_LINKINFO_TP_MDIX_CTRL`` u8 MDI(-X) control
|
||||
==================================== ====== ==========================
|
||||
|
||||
MDI(-X) status and transceiver cannot be set, request with the corresponding
|
||||
attributes is rejected.
|
||||
|
||||
|
||||
LINKMODES_GET
|
||||
=============
|
||||
|
||||
Requests link modes (supported, advertised and peer advertised) and related
|
||||
information (autonegotiation status, link speed and duplex) as provided by
|
||||
``ETHTOOL_GLINKSETTINGS``. The request does not use any attributes.
|
||||
|
||||
Request contents:
|
||||
|
||||
==================================== ====== ==========================
|
||||
``ETHTOOL_A_LINKMODES_HEADER`` nested request header
|
||||
==================================== ====== ==========================
|
||||
|
||||
Kernel response contents:
|
||||
|
||||
==================================== ====== ==========================
|
||||
``ETHTOOL_A_LINKMODES_HEADER`` nested reply header
|
||||
``ETHTOOL_A_LINKMODES_AUTONEG`` u8 autonegotiation status
|
||||
``ETHTOOL_A_LINKMODES_OURS`` bitset advertised link modes
|
||||
``ETHTOOL_A_LINKMODES_PEER`` bitset partner link modes
|
||||
``ETHTOOL_A_LINKMODES_SPEED`` u32 link speed (Mb/s)
|
||||
``ETHTOOL_A_LINKMODES_DUPLEX`` u8 duplex mode
|
||||
==================================== ====== ==========================
|
||||
|
||||
For ``ETHTOOL_A_LINKMODES_OURS``, value represents advertised modes and mask
|
||||
represents supported modes. ``ETHTOOL_A_LINKMODES_PEER`` in the reply is a bit
|
||||
list.
|
||||
|
||||
``LINKMODES_GET`` allows dump requests (kernel returns reply messages for all
|
||||
devices supporting the request).
|
||||
|
||||
|
||||
LINKMODES_SET
|
||||
=============
|
||||
|
||||
Request contents:
|
||||
|
||||
==================================== ====== ==========================
|
||||
``ETHTOOL_A_LINKMODES_HEADER`` nested request header
|
||||
``ETHTOOL_A_LINKMODES_AUTONEG`` u8 autonegotiation status
|
||||
``ETHTOOL_A_LINKMODES_OURS`` bitset advertised link modes
|
||||
``ETHTOOL_A_LINKMODES_PEER`` bitset partner link modes
|
||||
``ETHTOOL_A_LINKMODES_SPEED`` u32 link speed (Mb/s)
|
||||
``ETHTOOL_A_LINKMODES_DUPLEX`` u8 duplex mode
|
||||
==================================== ====== ==========================
|
||||
|
||||
``ETHTOOL_A_LINKMODES_OURS`` bit set allows setting advertised link modes. If
|
||||
autonegotiation is on (either set now or kept from before), advertised modes
|
||||
are not changed (no ``ETHTOOL_A_LINKMODES_OURS`` attribute) and at least one
|
||||
of speed and duplex is specified, kernel adjusts advertised modes to all
|
||||
supported modes matching speed, duplex or both (whatever is specified). This
|
||||
autoselection is done on ethtool side with ioctl interface, netlink interface
|
||||
is supposed to allow requesting changes without knowing what exactly kernel
|
||||
supports.
|
||||
|
||||
|
||||
LINKSTATE_GET
|
||||
=============
|
||||
|
||||
Requests link state information. At the moment, only link up/down flag (as
|
||||
provided by ``ETHTOOL_GLINK`` ioctl command) is provided but some future
|
||||
extensions are planned (e.g. link down reason). This request does not have any
|
||||
attributes.
|
||||
|
||||
Request contents:
|
||||
|
||||
==================================== ====== ==========================
|
||||
``ETHTOOL_A_LINKSTATE_HEADER`` nested request header
|
||||
==================================== ====== ==========================
|
||||
|
||||
Kernel response contents:
|
||||
|
||||
==================================== ====== ==========================
|
||||
``ETHTOOL_A_LINKSTATE_HEADER`` nested reply header
|
||||
``ETHTOOL_A_LINKSTATE_LINK`` bool link state (up/down)
|
||||
==================================== ====== ==========================
|
||||
|
||||
For most NIC drivers, the value of ``ETHTOOL_A_LINKSTATE_LINK`` returns
|
||||
carrier flag provided by ``netif_carrier_ok()`` but there are drivers which
|
||||
define their own handler.
|
||||
|
||||
``LINKSTATE_GET`` allows dump requests (kernel returns reply messages for all
|
||||
devices supporting the request).
|
||||
|
||||
|
||||
DEBUG_GET
|
||||
=========
|
||||
|
||||
Requests debugging settings of a device. At the moment, only message mask is
|
||||
provided.
|
||||
|
||||
Request contents:
|
||||
|
||||
==================================== ====== ==========================
|
||||
``ETHTOOL_A_DEBUG_HEADER`` nested request header
|
||||
==================================== ====== ==========================
|
||||
|
||||
Kernel response contents:
|
||||
|
||||
==================================== ====== ==========================
|
||||
``ETHTOOL_A_DEBUG_HEADER`` nested reply header
|
||||
``ETHTOOL_A_DEBUG_MSGMASK`` bitset message mask
|
||||
==================================== ====== ==========================
|
||||
|
||||
The message mask (``ETHTOOL_A_DEBUG_MSGMASK``) is equal to message level as
|
||||
provided by ``ETHTOOL_GMSGLVL`` and set by ``ETHTOOL_SMSGLVL`` in ioctl
|
||||
interface. While it is called message level there for historical reasons, most
|
||||
drivers and almost all newer drivers use it as a mask of enabled message
|
||||
classes (represented by ``NETIF_MSG_*`` constants); therefore netlink
|
||||
interface follows its actual use in practice.
|
||||
|
||||
``DEBUG_GET`` allows dump requests (kernel returns reply messages for all
|
||||
devices supporting the request).
|
||||
|
||||
|
||||
DEBUG_SET
|
||||
=========
|
||||
|
||||
Set or update debugging settings of a device. At the moment, only message mask
|
||||
is supported.
|
||||
|
||||
Request contents:
|
||||
|
||||
==================================== ====== ==========================
|
||||
``ETHTOOL_A_DEBUG_HEADER`` nested request header
|
||||
``ETHTOOL_A_DEBUG_MSGMASK`` bitset message mask
|
||||
==================================== ====== ==========================
|
||||
|
||||
``ETHTOOL_A_DEBUG_MSGMASK`` bit set allows setting or modifying mask of
|
||||
enabled debugging message types for the device.
|
||||
|
||||
|
||||
WOL_GET
|
||||
=======
|
||||
|
||||
Query device wake-on-lan settings. Unlike most "GET" type requests,
|
||||
``ETHTOOL_MSG_WOL_GET`` requires (netns) ``CAP_NET_ADMIN`` privileges as it
|
||||
(potentially) provides SecureOn(tm) password which is confidential.
|
||||
|
||||
Request contents:
|
||||
|
||||
==================================== ====== ==========================
|
||||
``ETHTOOL_A_WOL_HEADER`` nested request header
|
||||
==================================== ====== ==========================
|
||||
|
||||
Kernel response contents:
|
||||
|
||||
==================================== ====== ==========================
|
||||
``ETHTOOL_A_WOL_HEADER`` nested reply header
|
||||
``ETHTOOL_A_WOL_MODES`` bitset mask of enabled WoL modes
|
||||
``ETHTOOL_A_WOL_SOPASS`` binary SecureOn(tm) password
|
||||
==================================== ====== ==========================
|
||||
|
||||
In reply, ``ETHTOOL_A_WOL_MODES`` mask consists of modes supported by the
|
||||
device, value of modes which are enabled. ``ETHTOOL_A_WOL_SOPASS`` is only
|
||||
included in reply if ``WAKE_MAGICSECURE`` mode is supported.
|
||||
|
||||
|
||||
WOL_SET
|
||||
=======
|
||||
|
||||
Set or update wake-on-lan settings.
|
||||
|
||||
Request contents:
|
||||
|
||||
==================================== ====== ==========================
|
||||
``ETHTOOL_A_WOL_HEADER`` nested request header
|
||||
``ETHTOOL_A_WOL_MODES`` bitset enabled WoL modes
|
||||
``ETHTOOL_A_WOL_SOPASS`` binary SecureOn(tm) password
|
||||
==================================== ====== ==========================
|
||||
|
||||
``ETHTOOL_A_WOL_SOPASS`` is only allowed for devices supporting
|
||||
``WAKE_MAGICSECURE`` mode.
|
||||
|
||||
|
||||
Request translation
|
||||
===================
|
||||
|
||||
The following table maps ioctl commands to netlink commands providing their
|
||||
functionality. Entries with "n/a" in right column are commands which do not
|
||||
have their netlink replacement yet.
|
||||
|
||||
=================================== =====================================
|
||||
ioctl command netlink command
|
||||
=================================== =====================================
|
||||
``ETHTOOL_GSET`` ``ETHTOOL_MSG_LINKINFO_GET``
|
||||
``ETHTOOL_MSG_LINKMODES_GET``
|
||||
``ETHTOOL_SSET`` ``ETHTOOL_MSG_LINKINFO_SET``
|
||||
``ETHTOOL_MSG_LINKMODES_SET``
|
||||
``ETHTOOL_GDRVINFO`` n/a
|
||||
``ETHTOOL_GREGS`` n/a
|
||||
``ETHTOOL_GWOL`` ``ETHTOOL_MSG_WOL_GET``
|
||||
``ETHTOOL_SWOL`` ``ETHTOOL_MSG_WOL_SET``
|
||||
``ETHTOOL_GMSGLVL`` ``ETHTOOL_MSG_DEBUG_GET``
|
||||
``ETHTOOL_SMSGLVL`` ``ETHTOOL_MSG_DEBUG_SET``
|
||||
``ETHTOOL_NWAY_RST`` n/a
|
||||
``ETHTOOL_GLINK`` ``ETHTOOL_MSG_LINKSTATE_GET``
|
||||
``ETHTOOL_GEEPROM`` n/a
|
||||
``ETHTOOL_SEEPROM`` n/a
|
||||
``ETHTOOL_GCOALESCE`` n/a
|
||||
``ETHTOOL_SCOALESCE`` n/a
|
||||
``ETHTOOL_GRINGPARAM`` n/a
|
||||
``ETHTOOL_SRINGPARAM`` n/a
|
||||
``ETHTOOL_GPAUSEPARAM`` n/a
|
||||
``ETHTOOL_SPAUSEPARAM`` n/a
|
||||
``ETHTOOL_GRXCSUM`` n/a
|
||||
``ETHTOOL_SRXCSUM`` n/a
|
||||
``ETHTOOL_GTXCSUM`` n/a
|
||||
``ETHTOOL_STXCSUM`` n/a
|
||||
``ETHTOOL_GSG`` n/a
|
||||
``ETHTOOL_SSG`` n/a
|
||||
``ETHTOOL_TEST`` n/a
|
||||
``ETHTOOL_GSTRINGS`` ``ETHTOOL_MSG_STRSET_GET``
|
||||
``ETHTOOL_PHYS_ID`` n/a
|
||||
``ETHTOOL_GSTATS`` n/a
|
||||
``ETHTOOL_GTSO`` n/a
|
||||
``ETHTOOL_STSO`` n/a
|
||||
``ETHTOOL_GPERMADDR`` rtnetlink ``RTM_GETLINK``
|
||||
``ETHTOOL_GUFO`` n/a
|
||||
``ETHTOOL_SUFO`` n/a
|
||||
``ETHTOOL_GGSO`` n/a
|
||||
``ETHTOOL_SGSO`` n/a
|
||||
``ETHTOOL_GFLAGS`` n/a
|
||||
``ETHTOOL_SFLAGS`` n/a
|
||||
``ETHTOOL_GPFLAGS`` n/a
|
||||
``ETHTOOL_SPFLAGS`` n/a
|
||||
``ETHTOOL_GRXFH`` n/a
|
||||
``ETHTOOL_SRXFH`` n/a
|
||||
``ETHTOOL_GGRO`` n/a
|
||||
``ETHTOOL_SGRO`` n/a
|
||||
``ETHTOOL_GRXRINGS`` n/a
|
||||
``ETHTOOL_GRXCLSRLCNT`` n/a
|
||||
``ETHTOOL_GRXCLSRULE`` n/a
|
||||
``ETHTOOL_GRXCLSRLALL`` n/a
|
||||
``ETHTOOL_SRXCLSRLDEL`` n/a
|
||||
``ETHTOOL_SRXCLSRLINS`` n/a
|
||||
``ETHTOOL_FLASHDEV`` n/a
|
||||
``ETHTOOL_RESET`` n/a
|
||||
``ETHTOOL_SRXNTUPLE`` n/a
|
||||
``ETHTOOL_GRXNTUPLE`` n/a
|
||||
``ETHTOOL_GSSET_INFO`` ``ETHTOOL_MSG_STRSET_GET``
|
||||
``ETHTOOL_GRXFHINDIR`` n/a
|
||||
``ETHTOOL_SRXFHINDIR`` n/a
|
||||
``ETHTOOL_GFEATURES`` n/a
|
||||
``ETHTOOL_SFEATURES`` n/a
|
||||
``ETHTOOL_GCHANNELS`` n/a
|
||||
``ETHTOOL_SCHANNELS`` n/a
|
||||
``ETHTOOL_SET_DUMP`` n/a
|
||||
``ETHTOOL_GET_DUMP_FLAG`` n/a
|
||||
``ETHTOOL_GET_DUMP_DATA`` n/a
|
||||
``ETHTOOL_GET_TS_INFO`` n/a
|
||||
``ETHTOOL_GMODULEINFO`` n/a
|
||||
``ETHTOOL_GMODULEEEPROM`` n/a
|
||||
``ETHTOOL_GEEE`` n/a
|
||||
``ETHTOOL_SEEE`` n/a
|
||||
``ETHTOOL_GRSSH`` n/a
|
||||
``ETHTOOL_SRSSH`` n/a
|
||||
``ETHTOOL_GTUNABLE`` n/a
|
||||
``ETHTOOL_STUNABLE`` n/a
|
||||
``ETHTOOL_GPHYSTATS`` n/a
|
||||
``ETHTOOL_PERQUEUE`` n/a
|
||||
``ETHTOOL_GLINKSETTINGS`` ``ETHTOOL_MSG_LINKINFO_GET``
|
||||
``ETHTOOL_MSG_LINKMODES_GET``
|
||||
``ETHTOOL_SLINKSETTINGS`` ``ETHTOOL_MSG_LINKINFO_SET``
|
||||
``ETHTOOL_MSG_LINKMODES_SET``
|
||||
``ETHTOOL_PHY_GTUNABLE`` n/a
|
||||
``ETHTOOL_PHY_STUNABLE`` n/a
|
||||
``ETHTOOL_GFECPARAM`` n/a
|
||||
``ETHTOOL_SFECPARAM`` n/a
|
||||
=================================== =====================================
|
|
@ -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::
|
||||
|
||||
|
|
47
MAINTAINERS
47
MAINTAINERS
|
@ -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,
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
@ -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 */
|
||||
}
|
||||
|
||||
|
|
|
@ -69,6 +69,7 @@ config ARM64
|
|||
select ARCH_SUPPORTS_INT128 if CC_HAS_INT128 && (GCC_VERSION >= 50000 || CC_IS_CLANG)
|
||||
select ARCH_SUPPORTS_NUMA_BALANCING
|
||||
select ARCH_WANT_COMPAT_IPC_PARSE_VERSION if COMPAT
|
||||
select ARCH_WANT_DEFAULT_BPF_JIT
|
||||
select ARCH_WANT_DEFAULT_TOPDOWN_MMAP_LAYOUT
|
||||
select ARCH_WANT_FRAME_POINTERS
|
||||
select ARCH_WANT_HUGE_PMD_SHARE if ARM64_4K_PAGES || (ARM64_16K_PAGES && !ARM64_VA_BITS_36)
|
||||
|
|
|
@ -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
|
||||
|
|
9
arch/riscv/include/uapi/asm/bpf_perf_event.h
Normal file
9
arch/riscv/include/uapi/asm/bpf_perf_event.h
Normal file
|
@ -0,0 +1,9 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
|
||||
#ifndef _UAPI__ASM_BPF_PERF_EVENT_H__
|
||||
#define _UAPI__ASM_BPF_PERF_EVENT_H__
|
||||
|
||||
#include <asm/ptrace.h>
|
||||
|
||||
typedef struct user_regs_struct bpf_user_pt_regs_t;
|
||||
|
||||
#endif /* _UAPI__ASM_BPF_PERF_EVENT_H__ */
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -93,6 +93,7 @@ config X86
|
|||
select ARCH_USE_QUEUED_RWLOCKS
|
||||
select ARCH_USE_QUEUED_SPINLOCKS
|
||||
select ARCH_WANT_BATCHED_UNMAP_TLB_FLUSH
|
||||
select ARCH_WANT_DEFAULT_BPF_JIT if X86_64
|
||||
select ARCH_WANTS_DYNAMIC_TASK_STRUCT
|
||||
select ARCH_WANT_HUGE_PMD_SHARE
|
||||
select ARCH_WANTS_THP_SWAP if X86_64
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
Loading…
Reference in a new issue