Merge git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-next
Pull networking updates from David Miller: 1) Support IPV6 RA Captive Portal Identifier, from Maciej Żenczykowski. 2) Use bio_vec in the networking instead of custom skb_frag_t, from Matthew Wilcox. 3) Make use of xmit_more in r8169 driver, from Heiner Kallweit. 4) Add devmap_hash to xdp, from Toke Høiland-Jørgensen. 5) Support all variants of 5750X bnxt_en chips, from Michael Chan. 6) More RTNL avoidance work in the core and mlx5 driver, from Vlad Buslov. 7) Add TCP syn cookies bpf helper, from Petar Penkov. 8) Add 'nettest' to selftests and use it, from David Ahern. 9) Add extack support to drop_monitor, add packet alert mode and support for HW drops, from Ido Schimmel. 10) Add VLAN offload to stmmac, from Jose Abreu. 11) Lots of devm_platform_ioremap_resource() conversions, from YueHaibing. 12) Add IONIC driver, from Shannon Nelson. 13) Several kTLS cleanups, from Jakub Kicinski. * git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-next: (1930 commits) mlxsw: spectrum_buffers: Add the ability to query the CPU port's shared buffer mlxsw: spectrum: Register CPU port with devlink mlxsw: spectrum_buffers: Prevent changing CPU port's configuration net: ena: fix incorrect update of intr_delay_resolution net: ena: fix retrieval of nonadaptive interrupt moderation intervals net: ena: fix update of interrupt moderation register net: ena: remove all old adaptive rx interrupt moderation code from ena_com net: ena: remove ena_restore_ethtool_params() and relevant fields net: ena: remove old adaptive interrupt moderation code from ena_netdev net: ena: remove code duplication in ena_com_update_nonadaptive_moderation_interval _*() net: ena: enable the interrupt_moderation in driver_supported_features net: ena: reimplement set/get_coalesce() net: ena: switch to dim algorithm for rx adaptive interrupt moderation net: ena: add intr_moder_rx_interval to struct ena_com_dev and use it net: phy: adin: implement Energy Detect Powerdown mode via phy-tunable ethtool: implement Energy Detect Powerdown support via phy-tunable xen-netfront: do not assume sk_buff_head list is empty in error handling s390/ctcm: Delete unnecessary checks before the macro call “dev_kfree_skb” net: ena: don't wake up tx queue when down drop_monitor: Better sanitize notified packets ...
This commit is contained in:
commit
81160dda9a
1
.mailmap
1
.mailmap
|
@ -65,6 +65,7 @@ Dengcheng Zhu <dzhu@wavecomp.com> <dengcheng.zhu@mips.com>
|
|||
Dengcheng Zhu <dzhu@wavecomp.com> <dengcheng.zhu@imgtec.com>
|
||||
Dengcheng Zhu <dzhu@wavecomp.com> <dczhu@mips.com>
|
||||
Dengcheng Zhu <dzhu@wavecomp.com> <dengcheng.zhu@gmail.com>
|
||||
<dev.kurt@vandijck-laurijssen.be> <kurt.van.dijck@eia.be>
|
||||
Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
|
||||
Dmitry Safonov <0x7f454c46@gmail.com> <dsafonov@virtuozzo.com>
|
||||
Dmitry Safonov <0x7f454c46@gmail.com> <d.safonov@partner.samsung.com>
|
||||
|
|
2
CREDITS
2
CREDITS
|
@ -751,7 +751,7 @@ S: Santa Cruz, California
|
|||
S: USA
|
||||
|
||||
N: Luis Correia
|
||||
E: lfcorreia@users.sf.net
|
||||
E: luisfcorreia@gmail.com
|
||||
D: Ralink rt2x00 WLAN driver
|
||||
S: Belas, Portugal
|
||||
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
What: /sys/kernel/btf
|
||||
Date: Aug 2019
|
||||
KernelVersion: 5.5
|
||||
Contact: bpf@vger.kernel.org
|
||||
Description:
|
||||
Contains BTF type information and related data for kernel and
|
||||
kernel modules.
|
||||
|
||||
What: /sys/kernel/btf/vmlinux
|
||||
Date: Aug 2019
|
||||
KernelVersion: 5.5
|
||||
Contact: bpf@vger.kernel.org
|
||||
Description:
|
||||
Read-only binary attribute exposing kernel's own BTF type
|
||||
information with description of all internal kernel types. See
|
||||
Documentation/bpf/btf.rst for detailed description of format
|
||||
itself.
|
|
@ -421,7 +421,6 @@ That is, the recovery API only requires that:
|
|||
- drivers/net/ixgbe
|
||||
- drivers/net/cxgb3
|
||||
- drivers/net/s2io.c
|
||||
- drivers/net/qlge
|
||||
|
||||
The End
|
||||
-------
|
||||
|
|
|
@ -26,6 +26,7 @@ The inputs are:
|
|||
* ``nhoff`` - initial offset of the networking header
|
||||
* ``thoff`` - initial offset of the transport header, initialized to nhoff
|
||||
* ``n_proto`` - L3 protocol type, parsed out of L2 header
|
||||
* ``flags`` - optional flags
|
||||
|
||||
Flow dissector BPF program should fill out the rest of the ``struct
|
||||
bpf_flow_keys`` fields. Input arguments ``nhoff/thoff/n_proto`` should be
|
||||
|
@ -101,6 +102,23 @@ can be called for both cases and would have to be written carefully to
|
|||
handle both cases.
|
||||
|
||||
|
||||
Flags
|
||||
=====
|
||||
|
||||
``flow_keys->flags`` might contain optional input flags that work as follows:
|
||||
|
||||
* ``BPF_FLOW_DISSECTOR_F_PARSE_1ST_FRAG`` - tells BPF flow dissector to
|
||||
continue parsing first fragment; the default expected behavior is that
|
||||
flow dissector returns as soon as it finds out that the packet is fragmented;
|
||||
used by ``eth_get_headlen`` to estimate length of all headers for GRO.
|
||||
* ``BPF_FLOW_DISSECTOR_F_STOP_AT_FLOW_LABEL`` - tells BPF flow dissector to
|
||||
stop parsing as soon as it reaches IPv6 flow label; used by
|
||||
``___skb_get_hash`` and ``__skb_get_hash_symmetric`` to get flow hash.
|
||||
* ``BPF_FLOW_DISSECTOR_F_STOP_AT_ENCAP`` - tells BPF flow dissector to stop
|
||||
parsing as soon as it reaches encapsulated headers; used by routing
|
||||
infrastructure.
|
||||
|
||||
|
||||
Reference Implementation
|
||||
========================
|
||||
|
||||
|
|
|
@ -9,8 +9,6 @@ Required Properties:
|
|||
- "mediatek,mt7622-sgmiisys", "syscon"
|
||||
- "mediatek,mt7629-sgmiisys", "syscon"
|
||||
- #clock-cells: Must be 1
|
||||
- mediatek,physpeed: Should be one of "auto", "1000" or "2500" to match up
|
||||
the capability of the target PHY.
|
||||
|
||||
The SGMIISYS controller uses the common clk binding from
|
||||
Documentation/devicetree/bindings/clock/clock-bindings.txt
|
||||
|
|
|
@ -0,0 +1,73 @@
|
|||
# SPDX-License-Identifier: GPL-2.0+
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/net/adi,adin.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Analog Devices ADIN1200/ADIN1300 PHY
|
||||
|
||||
maintainers:
|
||||
- Alexandru Ardelean <alexandru.ardelean@analog.com>
|
||||
|
||||
description: |
|
||||
Bindings for Analog Devices Industrial Ethernet PHYs
|
||||
|
||||
allOf:
|
||||
- $ref: ethernet-phy.yaml#
|
||||
|
||||
properties:
|
||||
adi,rx-internal-delay-ps:
|
||||
description: |
|
||||
RGMII RX Clock Delay used only when PHY operates in RGMII mode with
|
||||
internal delay (phy-mode is 'rgmii-id' or 'rgmii-rxid') in pico-seconds.
|
||||
enum: [ 1600, 1800, 2000, 2200, 2400 ]
|
||||
default: 2000
|
||||
|
||||
adi,tx-internal-delay-ps:
|
||||
description: |
|
||||
RGMII TX Clock Delay used only when PHY operates in RGMII mode with
|
||||
internal delay (phy-mode is 'rgmii-id' or 'rgmii-txid') in pico-seconds.
|
||||
enum: [ 1600, 1800, 2000, 2200, 2400 ]
|
||||
default: 2000
|
||||
|
||||
adi,fifo-depth-bits:
|
||||
description: |
|
||||
When operating in RMII mode, this option configures the FIFO depth.
|
||||
enum: [ 4, 8, 12, 16, 20, 24 ]
|
||||
default: 8
|
||||
|
||||
adi,disable-energy-detect:
|
||||
description: |
|
||||
Disables Energy Detect Powerdown Mode (default disabled, i.e energy detect
|
||||
is enabled if this property is unspecified)
|
||||
type: boolean
|
||||
|
||||
examples:
|
||||
- |
|
||||
ethernet {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
phy-mode = "rgmii-id";
|
||||
|
||||
ethernet-phy@0 {
|
||||
reg = <0>;
|
||||
|
||||
adi,rx-internal-delay-ps = <1800>;
|
||||
adi,tx-internal-delay-ps = <2200>;
|
||||
};
|
||||
};
|
||||
- |
|
||||
ethernet {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
phy-mode = "rmii";
|
||||
|
||||
ethernet-phy@1 {
|
||||
reg = <1>;
|
||||
|
||||
adi,fifo-depth-bits = <16>;
|
||||
adi,disable-energy-detect;
|
||||
};
|
||||
};
|
|
@ -17,6 +17,9 @@ properties:
|
|||
compatible:
|
||||
const: allwinner,sun7i-a20-gmac
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
|
|
|
@ -0,0 +1,113 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
|
||||
# Copyright 2019 BayLibre, SAS
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: "http://devicetree.org/schemas/net/amlogic,meson-dwmac.yaml#"
|
||||
$schema: "http://devicetree.org/meta-schemas/core.yaml#"
|
||||
|
||||
title: Amlogic Meson DWMAC Ethernet controller
|
||||
|
||||
maintainers:
|
||||
- Neil Armstrong <narmstrong@baylibre.com>
|
||||
- Martin Blumenstingl <martin.blumenstingl@googlemail.com>
|
||||
|
||||
# We need a select here so we don't match all nodes with 'snps,dwmac'
|
||||
select:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- amlogic,meson6-dwmac
|
||||
- amlogic,meson8b-dwmac
|
||||
- amlogic,meson8m2-dwmac
|
||||
- amlogic,meson-gxbb-dwmac
|
||||
- amlogic,meson-axg-dwmac
|
||||
required:
|
||||
- compatible
|
||||
|
||||
allOf:
|
||||
- $ref: "snps,dwmac.yaml#"
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- amlogic,meson8b-dwmac
|
||||
- amlogic,meson8m2-dwmac
|
||||
- amlogic,meson-gxbb-dwmac
|
||||
- amlogic,meson-axg-dwmac
|
||||
|
||||
then:
|
||||
properties:
|
||||
clocks:
|
||||
items:
|
||||
- description: GMAC main clock
|
||||
- description: First parent clock of the internal mux
|
||||
- description: Second parent clock of the internal mux
|
||||
|
||||
clock-names:
|
||||
minItems: 3
|
||||
maxItems: 3
|
||||
items:
|
||||
- const: stmmaceth
|
||||
- const: clkin0
|
||||
- const: clkin1
|
||||
|
||||
amlogic,tx-delay-ns:
|
||||
$ref: /schemas/types.yaml#definitions/uint32
|
||||
description:
|
||||
The internal RGMII TX clock delay (provided by this driver) in
|
||||
nanoseconds. Allowed values are 0ns, 2ns, 4ns, 6ns.
|
||||
When phy-mode is set to "rgmii" then the TX delay should be
|
||||
explicitly configured. When not configured a fallback of 2ns is
|
||||
used. When the phy-mode is set to either "rgmii-id" or "rgmii-txid"
|
||||
the TX clock delay is already provided by the PHY. In that case
|
||||
this property should be set to 0ns (which disables the TX clock
|
||||
delay in the MAC to prevent the clock from going off because both
|
||||
PHY and MAC are adding a delay).
|
||||
Any configuration is ignored when the phy-mode is set to "rmii".
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
additionalItems: true
|
||||
maxItems: 3
|
||||
items:
|
||||
- enum:
|
||||
- amlogic,meson6-dwmac
|
||||
- amlogic,meson8b-dwmac
|
||||
- amlogic,meson8m2-dwmac
|
||||
- amlogic,meson-gxbb-dwmac
|
||||
- amlogic,meson-axg-dwmac
|
||||
contains:
|
||||
enum:
|
||||
- snps,dwmac-3.70a
|
||||
- snps,dwmac
|
||||
|
||||
reg:
|
||||
items:
|
||||
- description:
|
||||
The first register range should be the one of the DWMAC controller
|
||||
- description:
|
||||
The second range is is for the Amlogic specific configuration
|
||||
(for example the PRG_ETHERNET register range on Meson8b and newer)
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- interrupts
|
||||
- interrupt-names
|
||||
- clocks
|
||||
- clock-names
|
||||
- phy-mode
|
||||
|
||||
examples:
|
||||
- |
|
||||
ethmac: ethernet@c9410000 {
|
||||
compatible = "amlogic,meson-gxbb-dwmac", "snps,dwmac";
|
||||
reg = <0xc9410000 0x10000>, <0xc8834540 0x8>;
|
||||
interrupts = <8>;
|
||||
interrupt-names = "macirq";
|
||||
clocks = <&clk_eth>, <&clkc_fclk_div2>, <&clk_mpll2>;
|
||||
clock-names = "stmmaceth", "clkin0", "clkin1";
|
||||
phy-mode = "rgmii";
|
||||
};
|
|
@ -0,0 +1,45 @@
|
|||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/net/aspeed,ast2600-mdio.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: ASPEED AST2600 MDIO Controller
|
||||
|
||||
maintainers:
|
||||
- Andrew Jeffery <andrew@aj.id.au>
|
||||
|
||||
description: |+
|
||||
The ASPEED AST2600 MDIO controller is the third iteration of ASPEED's MDIO
|
||||
bus register interface, this time also separating out the controller from the
|
||||
MAC.
|
||||
|
||||
allOf:
|
||||
- $ref: "mdio.yaml#"
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: aspeed,ast2600-mdio
|
||||
reg:
|
||||
maxItems: 1
|
||||
description: The register range of the MDIO controller instance
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- "#address-cells"
|
||||
- "#size-cells"
|
||||
|
||||
examples:
|
||||
- |
|
||||
mdio0: mdio@1e650000 {
|
||||
compatible = "aspeed,ast2600-mdio";
|
||||
reg = <0x1e650000 0x8>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
ethphy0: ethernet-phy@0 {
|
||||
compatible = "ethernet-phy-ieee802.3-c22";
|
||||
reg = <0>;
|
||||
};
|
||||
};
|
|
@ -13,6 +13,7 @@ Required properties:
|
|||
* "brcm,bcm20702a1"
|
||||
* "brcm,bcm4330-bt"
|
||||
* "brcm,bcm43438-bt"
|
||||
* "brcm,bcm4345c5"
|
||||
|
||||
Optional properties:
|
||||
|
||||
|
|
|
@ -32,6 +32,15 @@ Optional properties:
|
|||
ack_gpr is the gpr register offset of CAN stop acknowledge.
|
||||
ack_bit is the bit offset of CAN stop acknowledge.
|
||||
|
||||
- fsl,clk-source: Select the clock source to the CAN Protocol Engine (PE).
|
||||
It's SoC Implementation dependent. Refer to RM for detailed
|
||||
definition. If this property is not set in device tree node
|
||||
then driver selects clock source 1 by default.
|
||||
0: clock source 0 (oscillator clock)
|
||||
1: clock source 1 (peripheral clock)
|
||||
|
||||
- wakeup-source: enable CAN remote wakeup
|
||||
|
||||
Example:
|
||||
|
||||
can@1c000 {
|
||||
|
@ -40,4 +49,5 @@ Example:
|
|||
interrupts = <48 0x2>;
|
||||
interrupt-parent = <&mpic>;
|
||||
clock-frequency = <200000000>; // filled in by bootloader
|
||||
fsl,clk-source = <0>; // select clock source 0 for PE
|
||||
};
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
Texas Instruments TCAN4x5x CAN Controller
|
||||
================================================
|
||||
|
||||
This file provides device node information for the TCAN4x5x interface contains.
|
||||
|
||||
Required properties:
|
||||
- compatible: "ti,tcan4x5x"
|
||||
- reg: 0
|
||||
- #address-cells: 1
|
||||
- #size-cells: 0
|
||||
- spi-max-frequency: Maximum frequency of the SPI bus the chip can
|
||||
operate at should be less than or equal to 18 MHz.
|
||||
- device-wake-gpios: Wake up GPIO to wake up the TCAN device.
|
||||
- interrupt-parent: the phandle to the interrupt controller which provides
|
||||
the interrupt.
|
||||
- interrupts: interrupt specification for data-ready.
|
||||
|
||||
See Documentation/devicetree/bindings/net/can/m_can.txt for additional
|
||||
required property details.
|
||||
|
||||
Optional properties:
|
||||
- reset-gpios: Hardwired output GPIO. If not defined then software
|
||||
reset.
|
||||
- device-state-gpios: Input GPIO that indicates if the device is in
|
||||
a sleep state or if the device is active.
|
||||
|
||||
Example:
|
||||
tcan4x5x: tcan4x5x@0 {
|
||||
compatible = "ti,tcan4x5x";
|
||||
reg = <0>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
spi-max-frequency = <10000000>;
|
||||
bosch,mram-cfg = <0x0 0 0 32 0 0 1 1>;
|
||||
interrupt-parent = <&gpio1>;
|
||||
interrupts = <14 GPIO_ACTIVE_LOW>;
|
||||
device-state-gpios = <&gpio3 21 GPIO_ACTIVE_HIGH>;
|
||||
device-wake-gpios = <&gpio1 15 GPIO_ACTIVE_HIGH>;
|
||||
reset-gpios = <&gpio1 27 GPIO_ACTIVE_LOW>;
|
||||
};
|
|
@ -5,6 +5,9 @@ Required properties:
|
|||
|
||||
- compatible: For external switch chips, compatible string must be exactly one
|
||||
of the following:
|
||||
- "microchip,ksz8765"
|
||||
- "microchip,ksz8794"
|
||||
- "microchip,ksz8795"
|
||||
- "microchip,ksz9477"
|
||||
- "microchip,ksz9897"
|
||||
- "microchip,ksz9896"
|
||||
|
|
|
@ -22,7 +22,7 @@ which is at a different MDIO base address in different switch families.
|
|||
- "marvell,mv88e6190" : Switch has base address 0x00. Use with models:
|
||||
6190, 6190X, 6191, 6290, 6390, 6390X
|
||||
- "marvell,mv88e6250" : Switch has base address 0x08 or 0x18. Use with model:
|
||||
6250
|
||||
6220, 6250
|
||||
|
||||
Required properties:
|
||||
- compatible : Should be one of "marvell,mv88e6085",
|
||||
|
|
|
@ -35,6 +35,42 @@ Required properties for the child nodes within ports container:
|
|||
- phy-mode: String, must be either "trgmii" or "rgmii" for port labeled
|
||||
"cpu".
|
||||
|
||||
Port 5 of the switch is muxed between:
|
||||
1. GMAC5: GMAC5 can interface with another external MAC or PHY.
|
||||
2. PHY of port 0 or port 4: PHY interfaces with an external MAC like 2nd GMAC
|
||||
of the SOC. Used in many setups where port 0/4 becomes the WAN port.
|
||||
Note: On a MT7621 SOC with integrated switch: 2nd GMAC can only connected to
|
||||
GMAC5 when the gpios for RGMII2 (GPIO 22-33) are not used and not
|
||||
connected to external component!
|
||||
|
||||
Port 5 modes/configurations:
|
||||
1. Port 5 is disabled and isolated: An external phy can interface to the 2nd
|
||||
GMAC of the SOC.
|
||||
In the case of a build-in MT7530 switch, port 5 shares the RGMII bus with 2nd
|
||||
GMAC and an optional external phy. Mind the GPIO/pinctl settings of the SOC!
|
||||
2. Port 5 is muxed to PHY of port 0/4: Port 0/4 interfaces with 2nd GMAC.
|
||||
It is a simple MAC to PHY interface, port 5 needs to be setup for xMII mode
|
||||
and RGMII delay.
|
||||
3. Port 5 is muxed to GMAC5 and can interface to an external phy.
|
||||
Port 5 becomes an extra switch port.
|
||||
Only works on platform where external phy TX<->RX lines are swapped.
|
||||
Like in the Ubiquiti ER-X-SFP.
|
||||
4. Port 5 is muxed to GMAC5 and interfaces with the 2nd GAMC as 2nd CPU port.
|
||||
Currently a 2nd CPU port is not supported by DSA code.
|
||||
|
||||
Depending on how the external PHY is wired:
|
||||
1. normal: The PHY can only connect to 2nd GMAC but not to the switch
|
||||
2. swapped: RGMII TX, RX are swapped; external phy interface with the switch as
|
||||
a ethernet port. But can't interface to the 2nd GMAC.
|
||||
|
||||
Based on the DT the port 5 mode is configured.
|
||||
|
||||
Driver tries to lookup the phy-handle of the 2nd GMAC of the master device.
|
||||
When phy-handle matches PHY of port 0 or 4 then port 5 set-up as mode 2.
|
||||
phy-mode must be set, see also example 2 below!
|
||||
* mt7621: phy-mode = "rgmii-txid";
|
||||
* mt7623: phy-mode = "rgmii";
|
||||
|
||||
See Documentation/devicetree/bindings/net/dsa/dsa.txt for a list of additional
|
||||
required, optional properties and how the integrated switch subnodes must
|
||||
be specified.
|
||||
|
@ -94,3 +130,181 @@ Example:
|
|||
};
|
||||
};
|
||||
};
|
||||
|
||||
Example 2: MT7621: Port 4 is WAN port: 2nd GMAC -> Port 5 -> PHY port 4.
|
||||
|
||||
ð {
|
||||
gmac0: mac@0 {
|
||||
compatible = "mediatek,eth-mac";
|
||||
reg = <0>;
|
||||
phy-mode = "rgmii";
|
||||
|
||||
fixed-link {
|
||||
speed = <1000>;
|
||||
full-duplex;
|
||||
pause;
|
||||
};
|
||||
};
|
||||
|
||||
gmac1: mac@1 {
|
||||
compatible = "mediatek,eth-mac";
|
||||
reg = <1>;
|
||||
phy-mode = "rgmii-txid";
|
||||
phy-handle = <&phy4>;
|
||||
};
|
||||
|
||||
mdio: mdio-bus {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
/* Internal phy */
|
||||
phy4: ethernet-phy@4 {
|
||||
reg = <4>;
|
||||
};
|
||||
|
||||
mt7530: switch@1f {
|
||||
compatible = "mediatek,mt7621";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
reg = <0x1f>;
|
||||
pinctrl-names = "default";
|
||||
mediatek,mcm;
|
||||
|
||||
resets = <&rstctrl 2>;
|
||||
reset-names = "mcm";
|
||||
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
port@0 {
|
||||
reg = <0>;
|
||||
label = "lan0";
|
||||
};
|
||||
|
||||
port@1 {
|
||||
reg = <1>;
|
||||
label = "lan1";
|
||||
};
|
||||
|
||||
port@2 {
|
||||
reg = <2>;
|
||||
label = "lan2";
|
||||
};
|
||||
|
||||
port@3 {
|
||||
reg = <3>;
|
||||
label = "lan3";
|
||||
};
|
||||
|
||||
/* Commented out. Port 4 is handled by 2nd GMAC.
|
||||
port@4 {
|
||||
reg = <4>;
|
||||
label = "lan4";
|
||||
};
|
||||
*/
|
||||
|
||||
cpu_port0: port@6 {
|
||||
reg = <6>;
|
||||
label = "cpu";
|
||||
ethernet = <&gmac0>;
|
||||
phy-mode = "rgmii";
|
||||
|
||||
fixed-link {
|
||||
speed = <1000>;
|
||||
full-duplex;
|
||||
pause;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
Example 3: MT7621: Port 5 is connected to external PHY: Port 5 -> external PHY.
|
||||
|
||||
ð {
|
||||
gmac0: mac@0 {
|
||||
compatible = "mediatek,eth-mac";
|
||||
reg = <0>;
|
||||
phy-mode = "rgmii";
|
||||
|
||||
fixed-link {
|
||||
speed = <1000>;
|
||||
full-duplex;
|
||||
pause;
|
||||
};
|
||||
};
|
||||
|
||||
mdio: mdio-bus {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
/* External phy */
|
||||
ephy5: ethernet-phy@7 {
|
||||
reg = <7>;
|
||||
};
|
||||
|
||||
mt7530: switch@1f {
|
||||
compatible = "mediatek,mt7621";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
reg = <0x1f>;
|
||||
pinctrl-names = "default";
|
||||
mediatek,mcm;
|
||||
|
||||
resets = <&rstctrl 2>;
|
||||
reset-names = "mcm";
|
||||
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
port@0 {
|
||||
reg = <0>;
|
||||
label = "lan0";
|
||||
};
|
||||
|
||||
port@1 {
|
||||
reg = <1>;
|
||||
label = "lan1";
|
||||
};
|
||||
|
||||
port@2 {
|
||||
reg = <2>;
|
||||
label = "lan2";
|
||||
};
|
||||
|
||||
port@3 {
|
||||
reg = <3>;
|
||||
label = "lan3";
|
||||
};
|
||||
|
||||
port@4 {
|
||||
reg = <4>;
|
||||
label = "lan4";
|
||||
};
|
||||
|
||||
port@5 {
|
||||
reg = <5>;
|
||||
label = "lan5";
|
||||
phy-mode = "rgmii";
|
||||
phy-handle = <&ephy5>;
|
||||
};
|
||||
|
||||
cpu_port0: port@6 {
|
||||
reg = <6>;
|
||||
label = "cpu";
|
||||
ethernet = <&gmac0>;
|
||||
phy-mode = "rgmii";
|
||||
|
||||
fixed-link {
|
||||
speed = <1000>;
|
||||
full-duplex;
|
||||
pause;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
|
@ -11,7 +11,9 @@ Required properties:
|
|||
to parent node bindings.
|
||||
- compatible : Should be "fsl,enetc".
|
||||
|
||||
1) The ENETC external port is connected to a MDIO configurable phy:
|
||||
1. The ENETC external port is connected to a MDIO configurable phy
|
||||
|
||||
1.1. Using the local ENETC Port MDIO interface
|
||||
|
||||
In this case, the ENETC node should include a "mdio" sub-node
|
||||
that in turn should contain the "ethernet-phy" node describing the
|
||||
|
@ -47,8 +49,42 @@ Example:
|
|||
};
|
||||
};
|
||||
|
||||
2) The ENETC port is an internal port or has a fixed-link external
|
||||
connection:
|
||||
1.2. Using the central MDIO PCIe endpoint device
|
||||
|
||||
In this case, the mdio node should be defined as another PCIe
|
||||
endpoint node, at the same level with the ENETC port nodes.
|
||||
|
||||
Required properties:
|
||||
|
||||
- reg : Specifies PCIe Device Number and Function
|
||||
Number of the ENETC endpoint device, according
|
||||
to parent node bindings.
|
||||
- compatible : Should be "fsl,enetc-mdio".
|
||||
|
||||
The remaining required mdio bus properties are standard, their bindings
|
||||
already defined in Documentation/devicetree/bindings/net/mdio.txt.
|
||||
|
||||
Example:
|
||||
|
||||
ethernet@0,0 {
|
||||
compatible = "fsl,enetc";
|
||||
reg = <0x000000 0 0 0 0>;
|
||||
phy-handle = <&sgmii_phy0>;
|
||||
phy-connection-type = "sgmii";
|
||||
};
|
||||
|
||||
mdio@0,3 {
|
||||
compatible = "fsl,enetc-mdio";
|
||||
reg = <0x000300 0 0 0 0>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
sgmii_phy0: ethernet-phy@2 {
|
||||
reg = <0x2>;
|
||||
};
|
||||
};
|
||||
|
||||
2. The ENETC port is an internal port or has a fixed-link external
|
||||
connection
|
||||
|
||||
In this case, the ENETC port node defines a fixed link connection,
|
||||
as specified by Documentation/devicetree/bindings/net/fixed-link.txt.
|
||||
|
|
|
@ -12,6 +12,7 @@ Required properties:
|
|||
"mediatek,mt7623-eth", "mediatek,mt2701-eth": for MT7623 SoC
|
||||
"mediatek,mt7622-eth": for MT7622 SoC
|
||||
"mediatek,mt7629-eth": for MT7629 SoC
|
||||
"ralink,rt5350-eth": for Ralink Rt5350F and MT7628/88 SoC
|
||||
- reg: Address and length of the register set for the device
|
||||
- interrupts: Should contain the three frame engines interrupts in numeric
|
||||
order. These are fe_int0, fe_int1 and fe_int2.
|
||||
|
|
|
@ -1,71 +0,0 @@
|
|||
* Amlogic Meson DWMAC Ethernet controller
|
||||
|
||||
The device inherits all the properties of the dwmac/stmmac devices
|
||||
described in the file stmmac.txt in the current directory with the
|
||||
following changes.
|
||||
|
||||
Required properties on all platforms:
|
||||
|
||||
- compatible: Depending on the platform this should be one of:
|
||||
- "amlogic,meson6-dwmac"
|
||||
- "amlogic,meson8b-dwmac"
|
||||
- "amlogic,meson8m2-dwmac"
|
||||
- "amlogic,meson-gxbb-dwmac"
|
||||
- "amlogic,meson-axg-dwmac"
|
||||
Additionally "snps,dwmac" and any applicable more
|
||||
detailed version number described in net/stmmac.txt
|
||||
should be used.
|
||||
|
||||
- reg: The first register range should be the one of the DWMAC
|
||||
controller. The second range is is for the Amlogic specific
|
||||
configuration (for example the PRG_ETHERNET register range
|
||||
on Meson8b and newer)
|
||||
|
||||
Required properties on Meson8b, Meson8m2, GXBB and newer:
|
||||
- clock-names: Should contain the following:
|
||||
- "stmmaceth" - see stmmac.txt
|
||||
- "clkin0" - first parent clock of the internal mux
|
||||
- "clkin1" - second parent clock of the internal mux
|
||||
|
||||
Optional properties on Meson8b, Meson8m2, GXBB and newer:
|
||||
- amlogic,tx-delay-ns: The internal RGMII TX clock delay (provided
|
||||
by this driver) in nanoseconds. Allowed values
|
||||
are: 0ns, 2ns, 4ns, 6ns.
|
||||
When phy-mode is set to "rgmii" then the TX
|
||||
delay should be explicitly configured. When
|
||||
not configured a fallback of 2ns is used.
|
||||
When the phy-mode is set to either "rgmii-id"
|
||||
or "rgmii-txid" the TX clock delay is already
|
||||
provided by the PHY. In that case this
|
||||
property should be set to 0ns (which disables
|
||||
the TX clock delay in the MAC to prevent the
|
||||
clock from going off because both PHY and MAC
|
||||
are adding a delay).
|
||||
Any configuration is ignored when the phy-mode
|
||||
is set to "rmii".
|
||||
|
||||
Example for Meson6:
|
||||
|
||||
ethmac: ethernet@c9410000 {
|
||||
compatible = "amlogic,meson6-dwmac", "snps,dwmac";
|
||||
reg = <0xc9410000 0x10000
|
||||
0xc1108108 0x4>;
|
||||
interrupts = <0 8 1>;
|
||||
interrupt-names = "macirq";
|
||||
clocks = <&clk81>;
|
||||
clock-names = "stmmaceth";
|
||||
}
|
||||
|
||||
Example for GXBB:
|
||||
ethmac: ethernet@c9410000 {
|
||||
compatible = "amlogic,meson-gxbb-dwmac", "snps,dwmac";
|
||||
reg = <0x0 0xc9410000 0x0 0x10000>,
|
||||
<0x0 0xc8834540 0x0 0x8>;
|
||||
interrupts = <0 8 1>;
|
||||
interrupt-names = "macirq";
|
||||
clocks = <&clkc CLKID_ETH>,
|
||||
<&clkc CLKID_FCLK_DIV2>,
|
||||
<&clkc CLKID_MPLL2>;
|
||||
clock-names = "stmmaceth", "clkin0", "clkin1";
|
||||
phy-mode = "rgmii";
|
||||
};
|
|
@ -12,13 +12,15 @@ Required properties:
|
|||
- "sys"
|
||||
- "rew"
|
||||
- "qs"
|
||||
- "ptp" (optional due to backward compatibility)
|
||||
- "qsys"
|
||||
- "ana"
|
||||
- "portX" with X from 0 to the number of last port index available on that
|
||||
switch
|
||||
- interrupts: Should contain the switch interrupts for frame extraction and
|
||||
frame injection
|
||||
- interrupt-names: should contain the interrupt names: "xtr", "inj"
|
||||
- interrupts: Should contain the switch interrupts for frame extraction,
|
||||
frame injection and PTP ready.
|
||||
- interrupt-names: should contain the interrupt names: "xtr", "inj". Can contain
|
||||
"ptp_rdy" which is optional due to backward compatibility.
|
||||
- ethernet-ports: A container for child nodes representing switch ports.
|
||||
|
||||
The ethernet-ports container has the following properties
|
||||
|
@ -44,6 +46,7 @@ Example:
|
|||
reg = <0x1010000 0x10000>,
|
||||
<0x1030000 0x10000>,
|
||||
<0x1080000 0x100>,
|
||||
<0x10e0000 0x10000>,
|
||||
<0x11e0000 0x100>,
|
||||
<0x11f0000 0x100>,
|
||||
<0x1200000 0x100>,
|
||||
|
@ -57,11 +60,12 @@ Example:
|
|||
<0x1280000 0x100>,
|
||||
<0x1800000 0x80000>,
|
||||
<0x1880000 0x10000>;
|
||||
reg-names = "sys", "rew", "qs", "port0", "port1", "port2",
|
||||
"port3", "port4", "port5", "port6", "port7",
|
||||
"port8", "port9", "port10", "qsys", "ana";
|
||||
interrupts = <21 22>;
|
||||
interrupt-names = "xtr", "inj";
|
||||
reg-names = "sys", "rew", "qs", "ptp", "port0", "port1",
|
||||
"port2", "port3", "port4", "port5", "port6",
|
||||
"port7", "port8", "port9", "port10", "qsys",
|
||||
"ana";
|
||||
interrupts = <18 21 22>;
|
||||
interrupt-names = "ptp_rdy", "xtr", "inj";
|
||||
|
||||
ethernet-ports {
|
||||
#address-cells = <1>;
|
||||
|
|
|
@ -50,6 +50,11 @@ properties:
|
|||
- allwinner,sun8i-r40-emac
|
||||
- allwinner,sun8i-v3s-emac
|
||||
- allwinner,sun50i-a64-emac
|
||||
- amlogic,meson6-dwmac
|
||||
- amlogic,meson8b-dwmac
|
||||
- amlogic,meson8m2-dwmac
|
||||
- amlogic,meson-gxbb-dwmac
|
||||
- amlogic,meson-axg-dwmac
|
||||
- snps,dwmac
|
||||
- snps,dwmac-3.50a
|
||||
- snps,dwmac-3.610
|
||||
|
@ -61,7 +66,8 @@ properties:
|
|||
- snps,dwxgmac-2.10
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
minItems: 1
|
||||
maxItems: 2
|
||||
|
||||
interrupts:
|
||||
minItems: 1
|
||||
|
@ -106,6 +112,14 @@ properties:
|
|||
reset-names:
|
||||
const: stmmaceth
|
||||
|
||||
mac-mode:
|
||||
maxItems: 1
|
||||
description:
|
||||
The property is identical to 'phy-mode', and assumes that there is mode
|
||||
converter in-between the MAC & PHY (e.g. GMII-to-RGMII). This converter
|
||||
can be passive (no SW requirement), and requires that the MAC operate
|
||||
in a different mode than the PHY in order to function.
|
||||
|
||||
snps,axi-config:
|
||||
$ref: /schemas/types.yaml#definitions/phandle
|
||||
description:
|
||||
|
|
|
@ -37,6 +37,10 @@ Optional property:
|
|||
for applicable values. The CLK_OUT pin can also
|
||||
be disabled by this property. When omitted, the
|
||||
PHY's default will be left as is.
|
||||
- ti,sgmii-ref-clock-output-enable - This denotes which
|
||||
SGMII configuration is used (4 or 6-wire modes).
|
||||
Some MACs work with differential SGMII clock.
|
||||
See data manual for details.
|
||||
|
||||
Note: ti,min-output-impedance and ti,max-output-impedance are mutually
|
||||
exclusive. When both properties are present ti,max-output-impedance
|
||||
|
|
|
@ -153,10 +153,12 @@ an example, if the UMEM is 64k and each chunk is 4k, then the UMEM has
|
|||
|
||||
Frames passed to the kernel are used for the ingress path (RX rings).
|
||||
|
||||
The user application produces UMEM addrs to this ring. Note that the
|
||||
kernel will mask the incoming addr. E.g. for a chunk size of 2k, the
|
||||
log2(2048) LSB of the addr will be masked off, meaning that 2048, 2050
|
||||
and 3000 refers to the same chunk.
|
||||
The user application produces UMEM addrs to this ring. Note that, if
|
||||
running the application with aligned chunk mode, the kernel will mask
|
||||
the incoming addr. E.g. for a chunk size of 2k, the log2(2048) LSB of
|
||||
the addr will be masked off, meaning that 2048, 2050 and 3000 refers
|
||||
to the same chunk. If the user application is run in the unaligned
|
||||
chunks mode, then the incoming addr will be left untouched.
|
||||
|
||||
|
||||
UMEM Completion Ring
|
||||
|
|
|
@ -23,6 +23,7 @@ Contents:
|
|||
intel/ice
|
||||
google/gve
|
||||
mellanox/mlx5
|
||||
pensando/ionic
|
||||
|
||||
.. only:: subproject and html
|
||||
|
||||
|
|
|
@ -10,11 +10,15 @@ Copyright(c) 2013-2018 Intel Corporation.
|
|||
Contents
|
||||
========
|
||||
|
||||
- Overview
|
||||
- Identifying Your Adapter
|
||||
- Additional Configurations
|
||||
- Known Issues/Troubleshooting
|
||||
- Support
|
||||
|
||||
Overview
|
||||
========
|
||||
|
||||
This file describes the iavf Linux* Base Driver. This driver was formerly
|
||||
called i40evf.
|
||||
|
||||
|
@ -27,6 +31,7 @@ The guest OS loading the iavf driver must support MSI-X interrupts.
|
|||
|
||||
Identifying Your Adapter
|
||||
========================
|
||||
|
||||
The driver in this kernel is compatible with devices based on the following:
|
||||
* Intel(R) XL710 X710 Virtual Function
|
||||
* Intel(R) X722 Virtual Function
|
||||
|
@ -50,9 +55,10 @@ Link messages will not be displayed to the console if the distribution is
|
|||
restricting system messages. In order to see network driver link messages on
|
||||
your console, set dmesg to eight by entering the following::
|
||||
|
||||
dmesg -n 8
|
||||
# dmesg -n 8
|
||||
|
||||
NOTE: This setting is not saved across reboots.
|
||||
NOTE:
|
||||
This setting is not saved across reboots.
|
||||
|
||||
ethtool
|
||||
-------
|
||||
|
@ -72,11 +78,11 @@ then requests from that VF to set VLAN tag stripping will be ignored.
|
|||
To enable/disable VLAN tag stripping for a VF, issue the following command
|
||||
from inside the VM in which you are running the VF::
|
||||
|
||||
ethtool -K <if_name> rxvlan on/off
|
||||
# ethtool -K <if_name> rxvlan on/off
|
||||
|
||||
or alternatively::
|
||||
|
||||
ethtool --offload <if_name> rxvlan on/off
|
||||
# ethtool --offload <if_name> rxvlan on/off
|
||||
|
||||
Adaptive Virtual Function
|
||||
-------------------------
|
||||
|
@ -91,21 +97,21 @@ additional features depending on what features are available in the PF with
|
|||
which the AVF is associated. The following are base mode features:
|
||||
|
||||
- 4 Queue Pairs (QP) and associated Configuration Status Registers (CSRs)
|
||||
for Tx/Rx.
|
||||
- i40e descriptors and ring format.
|
||||
- Descriptor write-back completion.
|
||||
- 1 control queue, with i40e descriptors, CSRs and ring format.
|
||||
- 5 MSI-X interrupt vectors and corresponding i40e CSRs.
|
||||
- 1 Interrupt Throttle Rate (ITR) index.
|
||||
- 1 Virtual Station Interface (VSI) per VF.
|
||||
for Tx/Rx
|
||||
- i40e descriptors and ring format
|
||||
- Descriptor write-back completion
|
||||
- 1 control queue, with i40e descriptors, CSRs and ring format
|
||||
- 5 MSI-X interrupt vectors and corresponding i40e CSRs
|
||||
- 1 Interrupt Throttle Rate (ITR) index
|
||||
- 1 Virtual Station Interface (VSI) per VF
|
||||
- 1 Traffic Class (TC), TC0
|
||||
- Receive Side Scaling (RSS) with 64 entry indirection table and key,
|
||||
configured through the PF.
|
||||
- 1 unicast MAC address reserved per VF.
|
||||
- 16 MAC address filters for each VF.
|
||||
- Stateless offloads - non-tunneled checksums.
|
||||
- AVF device ID.
|
||||
- HW mailbox is used for VF to PF communications (including on Windows).
|
||||
configured through the PF
|
||||
- 1 unicast MAC address reserved per VF
|
||||
- 16 MAC address filters for each VF
|
||||
- Stateless offloads - non-tunneled checksums
|
||||
- AVF device ID
|
||||
- HW mailbox is used for VF to PF communications (including on Windows)
|
||||
|
||||
IEEE 802.1ad (QinQ) Support
|
||||
---------------------------
|
||||
|
@ -117,8 +123,8 @@ VLAN ID, among other uses.
|
|||
|
||||
The following are examples of how to configure 802.1ad (QinQ)::
|
||||
|
||||
ip link add link eth0 eth0.24 type vlan proto 802.1ad id 24
|
||||
ip link add link eth0.24 eth0.24.371 type vlan proto 802.1Q id 371
|
||||
# ip link add link eth0 eth0.24 type vlan proto 802.1ad id 24
|
||||
# ip link add link eth0.24 eth0.24.371 type vlan proto 802.1Q id 371
|
||||
|
||||
Where "24" and "371" are example VLAN IDs.
|
||||
|
||||
|
@ -133,6 +139,19 @@ specific application. This can reduce latency for the specified application,
|
|||
and allow Tx traffic to be rate limited per application. Follow the steps below
|
||||
to set ADq.
|
||||
|
||||
Requirements:
|
||||
|
||||
- The sch_mqprio, act_mirred and cls_flower modules must be loaded
|
||||
- The latest version of iproute2
|
||||
- If another driver (for example, DPDK) has set cloud filters, you cannot
|
||||
enable ADQ
|
||||
- Depending on the underlying PF device, ADQ cannot be enabled when the
|
||||
following features are enabled:
|
||||
|
||||
+ Data Center Bridging (DCB)
|
||||
+ Multiple Functions per Port (MFP)
|
||||
+ Sideband Filters
|
||||
|
||||
1. Create traffic classes (TCs). Maximum of 8 TCs can be created per interface.
|
||||
The shaper bw_rlimit parameter is optional.
|
||||
|
||||
|
@ -141,9 +160,9 @@ to 1Gbit for tc0 and 3Gbit for tc1.
|
|||
|
||||
::
|
||||
|
||||
# tc qdisc add dev <interface> root mqprio num_tc 2 map 0 0 0 0 1 1 1 1
|
||||
queues 16@0 16@16 hw 1 mode channel shaper bw_rlimit min_rate 1Gbit 2Gbit
|
||||
max_rate 1Gbit 3Gbit
|
||||
tc qdisc add dev <interface> root mqprio num_tc 2 map 0 0 0 0 1 1 1 1
|
||||
queues 16@0 16@16 hw 1 mode channel shaper bw_rlimit min_rate 1Gbit 2Gbit
|
||||
max_rate 1Gbit 3Gbit
|
||||
|
||||
map: priority mapping for up to 16 priorities to tcs (e.g. map 0 0 0 0 1 1 1 1
|
||||
sets priorities 0-3 to use tc0 and 4-7 to use tc1)
|
||||
|
@ -162,6 +181,10 @@ Totals must be equal or less than port speed.
|
|||
For example: min_rate 1Gbit 3Gbit: Verify bandwidth limit using network
|
||||
monitoring tools such as ifstat or sar –n DEV [interval] [number of samples]
|
||||
|
||||
NOTE:
|
||||
Setting up channels via ethtool (ethtool -L) is not supported when the
|
||||
TCs are configured using mqprio.
|
||||
|
||||
2. Enable HW TC offload on interface::
|
||||
|
||||
# ethtool -K <interface> hw-tc-offload on
|
||||
|
@ -171,16 +194,16 @@ monitoring tools such as ifstat or sar –n DEV [interval] [number of samples]
|
|||
# tc qdisc add dev <interface> ingress
|
||||
|
||||
NOTES:
|
||||
- Run all tc commands from the iproute2 <pathtoiproute2>/tc/ directory.
|
||||
- ADq is not compatible with cloud filters.
|
||||
- Run all tc commands from the iproute2 <pathtoiproute2>/tc/ directory
|
||||
- ADq is not compatible with cloud filters
|
||||
- Setting up channels via ethtool (ethtool -L) is not supported when the TCs
|
||||
are configured using mqprio.
|
||||
are configured using mqprio
|
||||
- You must have iproute2 latest version
|
||||
- NVM version 6.01 or later is required.
|
||||
- NVM version 6.01 or later is required
|
||||
- ADq cannot be enabled when any the following features are enabled: Data
|
||||
Center Bridging (DCB), Multiple Functions per Port (MFP), or Sideband Filters.
|
||||
Center Bridging (DCB), Multiple Functions per Port (MFP), or Sideband Filters
|
||||
- If another driver (for example, DPDK) has set cloud filters, you cannot
|
||||
enable ADq.
|
||||
enable ADq
|
||||
- Tunnel filters are not supported in ADq. If encapsulated packets do arrive
|
||||
in non-tunnel mode, filtering will be done on the inner headers. For example,
|
||||
for VXLAN traffic in non-tunnel mode, PCTYPE is identified as a VXLAN
|
||||
|
@ -198,6 +221,16 @@ NOTES:
|
|||
Known Issues/Troubleshooting
|
||||
============================
|
||||
|
||||
Bonding fails with VFs bound to an Intel(R) Ethernet Controller 700 series device
|
||||
---------------------------------------------------------------------------------
|
||||
If you bind Virtual Functions (VFs) to an Intel(R) Ethernet Controller 700
|
||||
series based device, the VF slaves may fail when they become the active slave.
|
||||
If the MAC address of the VF is set by the PF (Physical Function) of the
|
||||
device, when you add a slave, or change the active-backup slave, Linux bonding
|
||||
tries to sync the backup slave's MAC address to the same MAC address as the
|
||||
active slave. Linux bonding will fail at this point. This issue will not occur
|
||||
if the VF's MAC address is not set by the PF.
|
||||
|
||||
Traffic Is Not Being Passed Between VM and Client
|
||||
-------------------------------------------------
|
||||
You may not be able to pass traffic between a client system and a
|
||||
|
@ -215,13 +248,28 @@ Do not unload a port's driver if a Virtual Function (VF) with an active Virtual
|
|||
Machine (VM) is bound to it. Doing so will cause the port to appear to hang.
|
||||
Once the VM shuts down, or otherwise releases the VF, the command will complete.
|
||||
|
||||
Using four traffic classes fails
|
||||
--------------------------------
|
||||
Do not try to reserve more than three traffic classes in the iavf driver. Doing
|
||||
so will fail to set any traffic classes and will cause the driver to write
|
||||
errors to stdout. Use a maximum of three queues to avoid this issue.
|
||||
|
||||
Multiple log error messages on iavf driver removal
|
||||
--------------------------------------------------
|
||||
If you have several VFs and you remove the iavf driver, several instances of
|
||||
the following log errors are written to the log::
|
||||
|
||||
Unable to send opcode 2 to PF, err I40E_ERR_QUEUE_EMPTY, aq_err ok
|
||||
Unable to send the message to VF 2 aq_err 12
|
||||
ARQ Overflow Error detected
|
||||
|
||||
Virtual machine does not get link
|
||||
---------------------------------
|
||||
If the virtual machine has more than one virtual port assigned to it, and those
|
||||
virtual ports are bound to different physical ports, you may not get link on
|
||||
all of the virtual ports. The following command may work around the issue::
|
||||
|
||||
ethtool -r <PF>
|
||||
# ethtool -r <PF>
|
||||
|
||||
Where <PF> is the PF interface in the host, for example: p5p1. You may need to
|
||||
run the command more than once to get link on all virtual ports.
|
||||
|
@ -251,12 +299,13 @@ traffic.
|
|||
If you have multiple interfaces in a server, either turn on ARP filtering by
|
||||
entering::
|
||||
|
||||
echo 1 > /proc/sys/net/ipv4/conf/all/arp_filter
|
||||
# echo 1 > /proc/sys/net/ipv4/conf/all/arp_filter
|
||||
|
||||
NOTE: This setting is not saved across reboots. The configuration change can be
|
||||
made permanent by adding the following line to the file /etc/sysctl.conf::
|
||||
NOTE:
|
||||
This setting is not saved across reboots. The configuration change can be
|
||||
made permanent by adding the following line to the file /etc/sysctl.conf::
|
||||
|
||||
net.ipv4.conf.all.arp_filter = 1
|
||||
net.ipv4.conf.all.arp_filter = 1
|
||||
|
||||
Another alternative is to install the interfaces in separate broadcast domains
|
||||
(either in different switches or in a switch partitioned to VLANs).
|
||||
|
|
|
@ -11,7 +11,9 @@ Contents
|
|||
|
||||
- `Enabling the driver and kconfig options`_
|
||||
- `Devlink info`_
|
||||
- `Devlink parameters`_
|
||||
- `Devlink health reporters`_
|
||||
- `mlx5 tracepoints`_
|
||||
|
||||
Enabling the driver and kconfig options
|
||||
================================================
|
||||
|
@ -121,12 +123,44 @@ User command example::
|
|||
stored:
|
||||
fw.version 16.26.0100
|
||||
|
||||
Devlink parameters
|
||||
==================
|
||||
|
||||
flow_steering_mode: Device flow steering mode
|
||||
---------------------------------------------
|
||||
The flow steering mode parameter 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.
|
||||
|
||||
SMFS mode is faster and provides better rule inserstion rate compared to default DMFS mode.
|
||||
|
||||
User command examples:
|
||||
|
||||
- Set SMFS flow steering mode::
|
||||
|
||||
$ devlink dev param set pci/0000:06:00.0 name flow_steering_mode value "smfs" cmode runtime
|
||||
|
||||
- Read device flow steering mode::
|
||||
|
||||
$ devlink dev param show pci/0000:06:00.0 name flow_steering_mode
|
||||
pci/0000:06:00.0:
|
||||
name flow_steering_mode type driver-specific
|
||||
values:
|
||||
cmode runtime value smfs
|
||||
|
||||
|
||||
Devlink health reporters
|
||||
========================
|
||||
|
||||
tx reporter
|
||||
-----------
|
||||
The tx reporter is responsible of two error scenarios:
|
||||
The tx reporter is responsible for reporting and recovering of the following two error scenarios:
|
||||
|
||||
- TX timeout
|
||||
Report on kernel tx timeout detection.
|
||||
|
@ -135,7 +169,7 @@ The tx reporter is responsible of two error scenarios:
|
|||
Report on error tx completion.
|
||||
Recover by flushing the TX queue and reset it.
|
||||
|
||||
TX reporter also support Diagnose callback, on which it provides
|
||||
TX reporter also support on demand diagnose callback, on which it provides
|
||||
real time information of its send queues status.
|
||||
|
||||
User commands examples:
|
||||
|
@ -144,11 +178,40 @@ User commands examples:
|
|||
|
||||
$ devlink health diagnose pci/0000:82:00.0 reporter tx
|
||||
|
||||
NOTE: This command has valid output only when interface is up, otherwise the command has empty output.
|
||||
|
||||
- Show number of tx errors indicated, number of recover flows ended successfully,
|
||||
is autorecover enabled and graceful period from last recover::
|
||||
|
||||
$ devlink health show pci/0000:82:00.0 reporter tx
|
||||
|
||||
rx reporter
|
||||
-----------
|
||||
The rx reporter is responsible for reporting and recovering of the following two error scenarios:
|
||||
|
||||
- RX queues initialization (population) timeout
|
||||
RX queues descriptors population on ring initialization is done in
|
||||
napi context via triggering an irq, in case of a failure to get
|
||||
the minimum amount of descriptors, a timeout would occur and it
|
||||
could be recoverable by polling the EQ (Event Queue).
|
||||
- RX completions with errors (reported by HW on interrupt context)
|
||||
Report on rx completion error.
|
||||
Recover (if needed) by flushing the related queue and reset it.
|
||||
|
||||
RX reporter also supports on demand diagnose callback, on which it
|
||||
provides real time information of its receive queues status.
|
||||
|
||||
- Diagnose rx queues status, and corresponding completion queue::
|
||||
|
||||
$ devlink health diagnose pci/0000:82:00.0 reporter rx
|
||||
|
||||
NOTE: This command has valid output only when interface is up, otherwise the command has empty output.
|
||||
|
||||
- Show number of rx errors indicated, number of recover flows ended successfully,
|
||||
is autorecover enabled and graceful period from last recover::
|
||||
|
||||
$ devlink health show pci/0000:82:00.0 reporter rx
|
||||
|
||||
fw reporter
|
||||
-----------
|
||||
The fw reporter implements diagnose and dump callbacks.
|
||||
|
@ -190,3 +253,48 @@ User commands examples:
|
|||
$ devlink health dump show pci/0000:82:00.1 reporter fw_fatal
|
||||
|
||||
NOTE: This command can run only on PF.
|
||||
|
||||
mlx5 tracepoints
|
||||
================
|
||||
|
||||
mlx5 driver provides internal trace points for tracking and debugging using
|
||||
kernel tracepoints interfaces (refer to Documentation/trace/ftrase.rst).
|
||||
|
||||
For the list of support mlx5 events check /sys/kernel/debug/tracing/events/mlx5/
|
||||
|
||||
tc and eswitch offloads tracepoints:
|
||||
|
||||
- mlx5e_configure_flower: trace flower filter actions and cookies offloaded to mlx5::
|
||||
|
||||
$ echo mlx5:mlx5e_configure_flower >> /sys/kernel/debug/tracing/set_event
|
||||
$ cat /sys/kernel/debug/tracing/trace
|
||||
...
|
||||
tc-6535 [019] ...1 2672.404466: mlx5e_configure_flower: cookie=0000000067874a55 actions= REDIRECT
|
||||
|
||||
- mlx5e_delete_flower: trace flower filter actions and cookies deleted from mlx5::
|
||||
|
||||
$ echo mlx5:mlx5e_delete_flower >> /sys/kernel/debug/tracing/set_event
|
||||
$ cat /sys/kernel/debug/tracing/trace
|
||||
...
|
||||
tc-6569 [010] .N.1 2686.379075: mlx5e_delete_flower: cookie=0000000067874a55 actions= NULL
|
||||
|
||||
- mlx5e_stats_flower: trace flower stats request::
|
||||
|
||||
$ echo mlx5:mlx5e_stats_flower >> /sys/kernel/debug/tracing/set_event
|
||||
$ cat /sys/kernel/debug/tracing/trace
|
||||
...
|
||||
tc-6546 [010] ...1 2679.704889: mlx5e_stats_flower: cookie=0000000060eb3d6a bytes=0 packets=0 lastused=4295560217
|
||||
|
||||
- mlx5e_tc_update_neigh_used_value: trace tunnel rule neigh update value offloaded to mlx5::
|
||||
|
||||
$ echo mlx5:mlx5e_tc_update_neigh_used_value >> /sys/kernel/debug/tracing/set_event
|
||||
$ cat /sys/kernel/debug/tracing/trace
|
||||
...
|
||||
kworker/u48:4-8806 [009] ...1 55117.882428: mlx5e_tc_update_neigh_used_value: netdev: ens1f0 IPv4: 1.1.1.10 IPv6: ::ffff:1.1.1.10 neigh_used=1
|
||||
|
||||
- mlx5e_rep_neigh_update: trace neigh update tasks scheduled due to neigh state change events::
|
||||
|
||||
$ echo mlx5:mlx5e_rep_neigh_update >> /sys/kernel/debug/tracing/set_event
|
||||
$ cat /sys/kernel/debug/tracing/trace
|
||||
...
|
||||
kworker/u48:7-2221 [009] ...1 1475.387435: mlx5e_rep_neigh_update: netdev: ens1f0 MAC: 24:8a:07:9a:17:9a IPv4: 1.1.1.10 IPv6: ::ffff:1.1.1.10 neigh_connected=1
|
||||
|
|
|
@ -0,0 +1,133 @@
|
|||
.. SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
|
||||
=============================================
|
||||
Netronome Flow Processor (NFP) Kernel Drivers
|
||||
=============================================
|
||||
|
||||
Copyright (c) 2019, Netronome Systems, Inc.
|
||||
|
||||
Contents
|
||||
========
|
||||
|
||||
- `Overview`_
|
||||
- `Acquiring Firmware`_
|
||||
|
||||
Overview
|
||||
========
|
||||
|
||||
This driver supports Netronome's line of Flow Processor devices,
|
||||
including the NFP4000, NFP5000, and NFP6000 models, which are also
|
||||
incorporated in the company's family of Agilio SmartNICs. The SR-IOV
|
||||
physical and virtual functions for these devices are supported by
|
||||
the driver.
|
||||
|
||||
Acquiring Firmware
|
||||
==================
|
||||
|
||||
The NFP4000 and NFP6000 devices require application specific firmware
|
||||
to function. Application firmware can be located either on the host file system
|
||||
or in the device flash (if supported by management firmware).
|
||||
|
||||
Firmware files on the host filesystem contain card type (`AMDA-*` string), media
|
||||
config etc. They should be placed in `/lib/firmware/netronome` directory to
|
||||
load firmware from the host file system.
|
||||
|
||||
Firmware for basic NIC operation is available in the upstream
|
||||
`linux-firmware.git` repository.
|
||||
|
||||
Firmware in NVRAM
|
||||
-----------------
|
||||
|
||||
Recent versions of management firmware supports loading application
|
||||
firmware from flash when the host driver gets probed. The firmware loading
|
||||
policy configuration may be used to configure this feature appropriately.
|
||||
|
||||
Devlink or ethtool can be used to update the application firmware on the device
|
||||
flash by providing the appropriate `nic_AMDA*.nffw` file to the respective
|
||||
command. Users need to take care to write the correct firmware image for the
|
||||
card and media configuration to flash.
|
||||
|
||||
Available storage space in flash depends on the card being used.
|
||||
|
||||
Dealing with multiple projects
|
||||
------------------------------
|
||||
|
||||
NFP hardware is fully programmable therefore there can be different
|
||||
firmware images targeting different applications.
|
||||
|
||||
When using application firmware from host, we recommend placing
|
||||
actual firmware files in application-named subdirectories in
|
||||
`/lib/firmware/netronome` and linking the desired files, e.g.::
|
||||
|
||||
$ tree /lib/firmware/netronome/
|
||||
/lib/firmware/netronome/
|
||||
├── bpf
|
||||
│ ├── nic_AMDA0081-0001_1x40.nffw
|
||||
│ └── nic_AMDA0081-0001_4x10.nffw
|
||||
├── flower
|
||||
│ ├── nic_AMDA0081-0001_1x40.nffw
|
||||
│ └── nic_AMDA0081-0001_4x10.nffw
|
||||
├── nic
|
||||
│ ├── nic_AMDA0081-0001_1x40.nffw
|
||||
│ └── nic_AMDA0081-0001_4x10.nffw
|
||||
├── nic_AMDA0081-0001_1x40.nffw -> bpf/nic_AMDA0081-0001_1x40.nffw
|
||||
└── nic_AMDA0081-0001_4x10.nffw -> bpf/nic_AMDA0081-0001_4x10.nffw
|
||||
|
||||
3 directories, 8 files
|
||||
|
||||
You may need to use hard instead of symbolic links on distributions
|
||||
which use old `mkinitrd` command instead of `dracut` (e.g. Ubuntu).
|
||||
|
||||
After changing firmware files you may need to regenerate the initramfs
|
||||
image. Initramfs contains drivers and firmware files your system may
|
||||
need to boot. Refer to the documentation of your distribution to find
|
||||
out how to update initramfs. Good indication of stale initramfs
|
||||
is system loading wrong driver or firmware on boot, but when driver is
|
||||
later reloaded manually everything works correctly.
|
||||
|
||||
Selecting firmware per device
|
||||
-----------------------------
|
||||
|
||||
Most commonly all cards on the system use the same type of firmware.
|
||||
If you want to load specific firmware image for a specific card, you
|
||||
can use either the PCI bus address or serial number. Driver will print
|
||||
which files it's looking for when it recognizes a NFP device::
|
||||
|
||||
nfp: Looking for firmware file in order of priority:
|
||||
nfp: netronome/serial-00-12-34-aa-bb-cc-10-ff.nffw: not found
|
||||
nfp: netronome/pci-0000:02:00.0.nffw: not found
|
||||
nfp: netronome/nic_AMDA0081-0001_1x40.nffw: found, loading...
|
||||
|
||||
In this case if file (or link) called *serial-00-12-34-aa-bb-5d-10-ff.nffw*
|
||||
or *pci-0000:02:00.0.nffw* is present in `/lib/firmware/netronome` this
|
||||
firmware file will take precedence over `nic_AMDA*` files.
|
||||
|
||||
Note that `serial-*` and `pci-*` files are **not** automatically included
|
||||
in initramfs, you will have to refer to documentation of appropriate tools
|
||||
to find out how to include them.
|
||||
|
||||
Firmware loading policy
|
||||
-----------------------
|
||||
|
||||
Firmware loading policy is controlled via three HWinfo parameters
|
||||
stored as key value pairs in the device flash:
|
||||
|
||||
app_fw_from_flash
|
||||
Defines which firmware should take precedence, 'Disk' (0), 'Flash' (1) or
|
||||
the 'Preferred' (2) firmware. When 'Preferred' is selected, the management
|
||||
firmware makes the decision over which firmware will be loaded by comparing
|
||||
versions of the flash firmware and the host supplied firmware.
|
||||
This variable is configurable using the 'fw_load_policy'
|
||||
devlink parameter.
|
||||
|
||||
abi_drv_reset
|
||||
Defines if the driver should reset the firmware when
|
||||
the driver is probed, either 'Disk' (0) if firmware was found on disk,
|
||||
'Always' (1) reset or 'Never' (2) reset. Note that the device is always
|
||||
reset on driver unload if firmware was loaded when the driver was probed.
|
||||
This variable is configurable using the 'reset_dev_on_drv_probe'
|
||||
devlink parameter.
|
||||
|
||||
abi_drv_load_ifc
|
||||
Defines a list of PF devices allowed to load FW on the device.
|
||||
This variable is not currently user configurable.
|
|
@ -0,0 +1,43 @@
|
|||
.. SPDX-License-Identifier: GPL-2.0+
|
||||
|
||||
==========================================================
|
||||
Linux* Driver for the Pensando(R) Ethernet adapter family
|
||||
==========================================================
|
||||
|
||||
Pensando Linux Ethernet driver.
|
||||
Copyright(c) 2019 Pensando Systems, Inc
|
||||
|
||||
Contents
|
||||
========
|
||||
|
||||
- Identifying the Adapter
|
||||
- Support
|
||||
|
||||
Identifying the Adapter
|
||||
=======================
|
||||
|
||||
To find if one or more Pensando PCI Ethernet devices are installed on the
|
||||
host, check for the PCI devices::
|
||||
|
||||
$ lspci -d 1dd8:
|
||||
b5:00.0 Ethernet controller: Device 1dd8:1002
|
||||
b6:00.0 Ethernet controller: Device 1dd8:1002
|
||||
|
||||
If such devices are listed as above, then the ionic.ko driver should find
|
||||
and configure them for use. There should be log entries in the kernel
|
||||
messages such as these::
|
||||
|
||||
$ dmesg | grep ionic
|
||||
ionic Pensando Ethernet NIC Driver, ver 0.15.0-k
|
||||
ionic 0000:b5:00.0 enp181s0: renamed from eth0
|
||||
ionic 0000:b6:00.0 enp182s0: renamed from eth0
|
||||
|
||||
Support
|
||||
=======
|
||||
For general Linux networking support, please use the netdev mailing
|
||||
list, which is monitored by Pensando personnel::
|
||||
netdev@vger.kernel.org
|
||||
|
||||
For more specific support needs, please use the Pensando driver support
|
||||
email::
|
||||
drivers@pensando.io
|
|
@ -14,11 +14,27 @@ 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
|
||||
=======
|
||||
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
fw_load_policy [DEVICE, GENERIC]
|
||||
Configuration mode: permanent
|
||||
|
||||
reset_dev_on_drv_probe [DEVICE, GENERIC]
|
||||
Configuration mode: permanent
|
|
@ -48,4 +48,20 @@ fw_load_policy [DEVICE, GENERIC]
|
|||
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
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
.. SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
======================
|
||||
Devlink Trap netdevsim
|
||||
======================
|
||||
|
||||
Driver-specific Traps
|
||||
=====================
|
||||
|
||||
.. list-table:: List of Driver-specific Traps Registered by ``netdevsim``
|
||||
:widths: 5 5 90
|
||||
|
||||
* - Name
|
||||
- Type
|
||||
- Description
|
||||
* - ``fid_miss``
|
||||
- ``exception``
|
||||
- When a packet enters the device it is classified to a filtering
|
||||
indentifier (FID) based on the ingress port and VLAN. This trap is used
|
||||
to trap packets for which a FID could not be found
|
|
@ -0,0 +1,208 @@
|
|||
.. SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
============
|
||||
Devlink Trap
|
||||
============
|
||||
|
||||
Background
|
||||
==========
|
||||
|
||||
Devices capable of offloading the kernel's datapath and perform functions such
|
||||
as bridging and routing must also be able to send specific packets to the
|
||||
kernel (i.e., the CPU) for processing.
|
||||
|
||||
For example, a device acting as a multicast-aware bridge must be able to send
|
||||
IGMP membership reports to the kernel for processing by the bridge module.
|
||||
Without processing such packets, the bridge module could never populate its
|
||||
MDB.
|
||||
|
||||
As another example, consider a device acting as router which has received an IP
|
||||
packet with a TTL of 1. Upon routing the packet the device must send it to the
|
||||
kernel so that it will route it as well and generate an ICMP Time Exceeded
|
||||
error datagram. Without letting the kernel route such packets itself, utilities
|
||||
such as ``traceroute`` could never work.
|
||||
|
||||
The fundamental ability of sending certain packets to the kernel for processing
|
||||
is called "packet trapping".
|
||||
|
||||
Overview
|
||||
========
|
||||
|
||||
The ``devlink-trap`` mechanism allows capable device drivers to register their
|
||||
supported packet traps with ``devlink`` and report trapped packets to
|
||||
``devlink`` for further analysis.
|
||||
|
||||
Upon receiving trapped packets, ``devlink`` will perform a per-trap packets and
|
||||
bytes accounting and potentially report the packet to user space via a netlink
|
||||
event along with all the provided metadata (e.g., trap reason, timestamp, input
|
||||
port). This is especially useful for drop traps (see :ref:`Trap-Types`)
|
||||
as it allows users to obtain further visibility into packet drops that would
|
||||
otherwise be invisible.
|
||||
|
||||
The following diagram provides a general overview of ``devlink-trap``::
|
||||
|
||||
Netlink event: Packet w/ metadata
|
||||
Or a summary of recent drops
|
||||
^
|
||||
|
|
||||
Userspace |
|
||||
+---------------------------------------------------+
|
||||
Kernel |
|
||||
|
|
||||
+-------+--------+
|
||||
| |
|
||||
| drop_monitor |
|
||||
| |
|
||||
+-------^--------+
|
||||
|
|
||||
|
|
||||
|
|
||||
+----+----+
|
||||
| | Kernel's Rx path
|
||||
| devlink | (non-drop traps)
|
||||
| |
|
||||
+----^----+ ^
|
||||
| |
|
||||
+-----------+
|
||||
|
|
||||
+-------+-------+
|
||||
| |
|
||||
| Device driver |
|
||||
| |
|
||||
+-------^-------+
|
||||
Kernel |
|
||||
+---------------------------------------------------+
|
||||
Hardware |
|
||||
| Trapped packet
|
||||
|
|
||||
+--+---+
|
||||
| |
|
||||
| ASIC |
|
||||
| |
|
||||
+------+
|
||||
|
||||
.. _Trap-Types:
|
||||
|
||||
Trap Types
|
||||
==========
|
||||
|
||||
The ``devlink-trap`` mechanism supports the following packet trap types:
|
||||
|
||||
* ``drop``: Trapped packets were dropped by the underlying device. Packets
|
||||
are only processed by ``devlink`` and not injected to the kernel's Rx path.
|
||||
The trap action (see :ref:`Trap-Actions`) can be changed.
|
||||
* ``exception``: Trapped packets were not forwarded as intended by the
|
||||
underlying device due to an exception (e.g., TTL error, missing neighbour
|
||||
entry) and trapped to the control plane for resolution. Packets are
|
||||
processed by ``devlink`` and injected to the kernel's Rx path. Changing the
|
||||
action of such traps is not allowed, as it can easily break the control
|
||||
plane.
|
||||
|
||||
.. _Trap-Actions:
|
||||
|
||||
Trap Actions
|
||||
============
|
||||
|
||||
The ``devlink-trap`` mechanism supports the following packet trap actions:
|
||||
|
||||
* ``trap``: The sole copy of the packet is sent to the CPU.
|
||||
* ``drop``: The packet is dropped by the underlying device and a copy is not
|
||||
sent to the CPU.
|
||||
|
||||
Generic Packet Traps
|
||||
====================
|
||||
|
||||
Generic packet traps are used to describe traps that trap well-defined packets
|
||||
or packets that are trapped due to well-defined conditions (e.g., TTL error).
|
||||
Such traps can be shared by multiple device drivers and their description must
|
||||
be added to the following table:
|
||||
|
||||
.. list-table:: List of Generic Packet Traps
|
||||
:widths: 5 5 90
|
||||
|
||||
* - Name
|
||||
- Type
|
||||
- Description
|
||||
* - ``source_mac_is_multicast``
|
||||
- ``drop``
|
||||
- Traps incoming packets that the device decided to drop because of a
|
||||
multicast source MAC
|
||||
* - ``vlan_tag_mismatch``
|
||||
- ``drop``
|
||||
- Traps incoming packets that the device decided to drop in case of VLAN
|
||||
tag mismatch: The ingress bridge port is not configured with a PVID and
|
||||
the packet is untagged or prio-tagged
|
||||
* - ``ingress_vlan_filter``
|
||||
- ``drop``
|
||||
- Traps incoming packets that the device decided to drop in case they are
|
||||
tagged with a VLAN that is not configured on the ingress bridge port
|
||||
* - ``ingress_spanning_tree_filter``
|
||||
- ``drop``
|
||||
- Traps incoming packets that the device decided to drop in case the STP
|
||||
state of the ingress bridge port is not "forwarding"
|
||||
* - ``port_list_is_empty``
|
||||
- ``drop``
|
||||
- Traps packets that the device decided to drop in case they need to be
|
||||
flooded and the flood list is empty
|
||||
* - ``port_loopback_filter``
|
||||
- ``drop``
|
||||
- Traps packets that the device decided to drop in case after layer 2
|
||||
forwarding the only port from which they should be transmitted through
|
||||
is the port from which they were received
|
||||
* - ``blackhole_route``
|
||||
- ``drop``
|
||||
- Traps packets that the device decided to drop in case they hit a
|
||||
blackhole route
|
||||
* - ``ttl_value_is_too_small``
|
||||
- ``exception``
|
||||
- Traps unicast packets that should be forwarded by the device whose TTL
|
||||
was decremented to 0 or less
|
||||
* - ``tail_drop``
|
||||
- ``drop``
|
||||
- Traps packets that the device decided to drop because they could not be
|
||||
enqueued to a transmission queue which is full
|
||||
|
||||
Driver-specific Packet Traps
|
||||
============================
|
||||
|
||||
Device drivers can register driver-specific packet traps, but these must be
|
||||
clearly documented. Such traps can correspond to device-specific exceptions and
|
||||
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`
|
||||
|
||||
Generic Packet Trap Groups
|
||||
==========================
|
||||
|
||||
Generic packet trap groups are used to aggregate logically related packet
|
||||
traps. These groups allow the user to batch operations such as setting the trap
|
||||
action of all member traps. In addition, ``devlink-trap`` can report aggregated
|
||||
per-group packets and bytes statistics, in case per-trap statistics are too
|
||||
narrow. The description of these groups must be added to the following table:
|
||||
|
||||
.. list-table:: List of Generic Packet Trap Groups
|
||||
:widths: 10 90
|
||||
|
||||
* - Name
|
||||
- Description
|
||||
* - ``l2_drops``
|
||||
- Contains packet traps for packets that were dropped by the device during
|
||||
layer 2 forwarding (i.e., bridge)
|
||||
* - ``l3_drops``
|
||||
- Contains packet traps for packets that were dropped by the device or hit
|
||||
an exception (e.g., TTL error) during layer 3 forwarding
|
||||
* - ``buffer_drops``
|
||||
- Contains packet traps for packets that were dropped by the device due to
|
||||
an enqueue decision
|
||||
|
||||
Testing
|
||||
=======
|
||||
|
||||
See ``tools/testing/selftests/drivers/net/netdevsim/devlink_trap.sh`` for a
|
||||
test covering the core infrastructure. Test cases should be added for any new
|
||||
functionality.
|
||||
|
||||
Device drivers should focus their tests on device-specific functionality, such
|
||||
as the triggering of supported packet traps.
|
|
@ -146,6 +146,96 @@ enslaves eth0 and eth1 (the DSA master of the switch ports). This is because in
|
|||
this mode, the switch ports beneath br0 are not capable of regular traffic, and
|
||||
are only used as a conduit for switchdev operations.
|
||||
|
||||
Offloads
|
||||
========
|
||||
|
||||
Time-aware scheduling
|
||||
---------------------
|
||||
|
||||
The switch supports a variation of the enhancements for scheduled traffic
|
||||
specified in IEEE 802.1Q-2018 (formerly 802.1Qbv). This means it can be used to
|
||||
ensure deterministic latency for priority traffic that is sent in-band with its
|
||||
gate-open event in the network schedule.
|
||||
|
||||
This capability can be managed through the tc-taprio offload ('flags 2'). The
|
||||
difference compared to the software implementation of taprio is that the latter
|
||||
would only be able to shape traffic originated from the CPU, but not
|
||||
autonomously forwarded flows.
|
||||
|
||||
The device has 8 traffic classes, and maps incoming frames to one of them based
|
||||
on the VLAN PCP bits (if no VLAN is present, the port-based default is used).
|
||||
As described in the previous sections, depending on the value of
|
||||
``vlan_filtering``, the EtherType recognized by the switch as being VLAN can
|
||||
either be the typical 0x8100 or a custom value used internally by the driver
|
||||
for tagging. Therefore, the switch ignores the VLAN PCP if used in standalone
|
||||
or bridge mode with ``vlan_filtering=0``, as it will not recognize the 0x8100
|
||||
EtherType. In these modes, injecting into a particular TX queue can only be
|
||||
done by the DSA net devices, which populate the PCP field of the tagging header
|
||||
on egress. Using ``vlan_filtering=1``, the behavior is the other way around:
|
||||
offloaded flows can be steered to TX queues based on the VLAN PCP, but the DSA
|
||||
net devices are no longer able to do that. To inject frames into a hardware TX
|
||||
queue with VLAN awareness active, it is necessary to create a VLAN
|
||||
sub-interface on the DSA master port, and send normal (0x8100) VLAN-tagged
|
||||
towards the switch, with the VLAN PCP bits set appropriately.
|
||||
|
||||
Management traffic (having DMAC 01-80-C2-xx-xx-xx or 01-19-1B-xx-xx-xx) is the
|
||||
notable exception: the switch always treats it with a fixed priority and
|
||||
disregards any VLAN PCP bits even if present. The traffic class for management
|
||||
traffic has a value of 7 (highest priority) at the moment, which is not
|
||||
configurable in the driver.
|
||||
|
||||
Below is an example of configuring a 500 us cyclic schedule on egress port
|
||||
``swp5``. The traffic class gate for management traffic (7) is open for 100 us,
|
||||
and the gates for all other traffic classes are open for 400 us::
|
||||
|
||||
#!/bin/bash
|
||||
|
||||
set -e -u -o pipefail
|
||||
|
||||
NSEC_PER_SEC="1000000000"
|
||||
|
||||
gatemask() {
|
||||
local tc_list="$1"
|
||||
local mask=0
|
||||
|
||||
for tc in ${tc_list}; do
|
||||
mask=$((${mask} | (1 << ${tc})))
|
||||
done
|
||||
|
||||
printf "%02x" ${mask}
|
||||
}
|
||||
|
||||
if ! systemctl is-active --quiet ptp4l; then
|
||||
echo "Please start the ptp4l service"
|
||||
exit
|
||||
fi
|
||||
|
||||
now=$(phc_ctl /dev/ptp1 get | gawk '/clock time is/ { print $5; }')
|
||||
# Phase-align the base time to the start of the next second.
|
||||
sec=$(echo "${now}" | gawk -F. '{ print $1; }')
|
||||
base_time="$(((${sec} + 1) * ${NSEC_PER_SEC}))"
|
||||
|
||||
tc qdisc add dev swp5 parent root handle 100 taprio \
|
||||
num_tc 8 \
|
||||
map 0 1 2 3 5 6 7 \
|
||||
queues 1@0 1@1 1@2 1@3 1@4 1@5 1@6 1@7 \
|
||||
base-time ${base_time} \
|
||||
sched-entry S $(gatemask 7) 100000 \
|
||||
sched-entry S $(gatemask "0 1 2 3 4 5 6") 400000 \
|
||||
flags 2
|
||||
|
||||
It is possible to apply the tc-taprio offload on multiple egress ports. There
|
||||
are hardware restrictions related to the fact that no gate event may trigger
|
||||
simultaneously on two ports. The driver checks the consistency of the schedules
|
||||
against this restriction and errors out when appropriate. Schedule analysis is
|
||||
needed to avoid this, which is outside the scope of the document.
|
||||
|
||||
At the moment, the time-aware scheduler can only be triggered based on a
|
||||
standalone clock and not based on PTP time. This means the base-time argument
|
||||
from tc-taprio is ignored and the schedule starts right away. It also means it
|
||||
is more difficult to phase-align the scheduler with the other devices in the
|
||||
network.
|
||||
|
||||
Device Tree bindings and board design
|
||||
=====================================
|
||||
|
||||
|
|
|
@ -14,7 +14,10 @@ Contents:
|
|||
device_drivers/index
|
||||
dsa/index
|
||||
devlink-info-versions
|
||||
devlink-trap
|
||||
devlink-trap-netdevsim
|
||||
ieee802154
|
||||
j1939
|
||||
kapi
|
||||
z8530book
|
||||
msg_zerocopy
|
||||
|
|
|
@ -256,6 +256,12 @@ tcp_base_mss - INTEGER
|
|||
Path MTU discovery (MTU probing). If MTU probing is enabled,
|
||||
this is the initial MSS used by the connection.
|
||||
|
||||
tcp_mtu_probe_floor - INTEGER
|
||||
If MTU probing is enabled this caps the minimum MSS used for search_low
|
||||
for the connection.
|
||||
|
||||
Default : 48
|
||||
|
||||
tcp_min_snd_mss - INTEGER
|
||||
TCP SYN and SYNACK messages usually advertise an ADVMSS option,
|
||||
as described in RFC 1122 and RFC 6691.
|
||||
|
|
|
@ -0,0 +1,422 @@
|
|||
.. SPDX-License-Identifier: (GPL-2.0 OR MIT)
|
||||
|
||||
===================
|
||||
J1939 Documentation
|
||||
===================
|
||||
|
||||
Overview / What Is J1939
|
||||
========================
|
||||
|
||||
SAE J1939 defines a higher layer protocol on CAN. It implements a more
|
||||
sophisticated addressing scheme and extends the maximum packet size above 8
|
||||
bytes. Several derived specifications exist, which differ from the original
|
||||
J1939 on the application level, like MilCAN A, NMEA2000 and especially
|
||||
ISO-11783 (ISOBUS). This last one specifies the so-called ETP (Extended
|
||||
Transport Protocol) which is has been included in this implementation. This
|
||||
results in a maximum packet size of ((2 ^ 24) - 1) * 7 bytes == 111 MiB.
|
||||
|
||||
Specifications used
|
||||
-------------------
|
||||
|
||||
* SAE J1939-21 : data link layer
|
||||
* SAE J1939-81 : network management
|
||||
* ISO 11783-6 : Virtual Terminal (Extended Transport Protocol)
|
||||
|
||||
.. _j1939-motivation:
|
||||
|
||||
Motivation
|
||||
==========
|
||||
|
||||
Given the fact there's something like SocketCAN with an API similar to BSD
|
||||
sockets, we found some reasons to justify a kernel implementation for the
|
||||
addressing and transport methods used by J1939.
|
||||
|
||||
* **Addressing:** when a process on an ECU communicates via J1939, it should
|
||||
not necessarily know its source address. Although at least one process per
|
||||
ECU should know the source address. Other processes should be able to reuse
|
||||
that address. This way, address parameters for different processes
|
||||
cooperating for the same ECU, are not duplicated. This way of working is
|
||||
closely related to the UNIX concept where programs do just one thing, and do
|
||||
it well.
|
||||
|
||||
* **Dynamic addressing:** Address Claiming in J1939 is time critical.
|
||||
Furthermore data transport should be handled properly during the address
|
||||
negotiation. Putting this functionality in the kernel eliminates it as a
|
||||
requirement for _every_ user space process that communicates via J1939. This
|
||||
results in a consistent J1939 bus with proper addressing.
|
||||
|
||||
* **Transport:** both TP & ETP reuse some PGNs to relay big packets over them.
|
||||
Different processes may thus use the same TP & ETP PGNs without actually
|
||||
knowing it. The individual TP & ETP sessions _must_ be serialized
|
||||
(synchronized) between different processes. The kernel solves this problem
|
||||
properly and eliminates the serialization (synchronization) as a requirement
|
||||
for _every_ user space process that communicates via J1939.
|
||||
|
||||
J1939 defines some other features (relaying, gateway, fast packet transport,
|
||||
...). In-kernel code for these would not contribute to protocol stability.
|
||||
Therefore, these parts are left to user space.
|
||||
|
||||
The J1939 sockets operate on CAN network devices (see SocketCAN). Any J1939
|
||||
user space library operating on CAN raw sockets will still operate properly.
|
||||
Since such library does not communicate with the in-kernel implementation, care
|
||||
must be taken that these two do not interfere. In practice, this means they
|
||||
cannot share ECU addresses. A single ECU (or virtual ECU) address is used by
|
||||
the library exclusively, or by the in-kernel system exclusively.
|
||||
|
||||
J1939 concepts
|
||||
==============
|
||||
|
||||
PGN
|
||||
---
|
||||
|
||||
The PGN (Parameter Group Number) is a number to identify a packet. The PGN
|
||||
is composed as follows:
|
||||
1 bit : Reserved Bit
|
||||
1 bit : Data Page
|
||||
8 bits : PF (PDU Format)
|
||||
8 bits : PS (PDU Specific)
|
||||
|
||||
In J1939-21 distinction is made between PDU1 format (where PF < 240) and PDU2
|
||||
format (where PF >= 240). Furthermore, when using PDU2 format, the PS-field
|
||||
contains a so-called Group Extension, which is part of the PGN. When using PDU2
|
||||
format, the Group Extension is set in the PS-field.
|
||||
|
||||
On the other hand, when using PDU1 format, the PS-field contains a so-called
|
||||
Destination Address, which is _not_ part of the PGN. When communicating a PGN
|
||||
from user space to kernel (or visa versa) and PDU2 format is used, the PS-field
|
||||
of the PGN shall be set to zero. The Destination Address shall be set
|
||||
elsewhere.
|
||||
|
||||
Regarding PGN mapping to 29-bit CAN identifier, the Destination Address shall
|
||||
be get/set from/to the appropriate bits of the identifier by the kernel.
|
||||
|
||||
|
||||
Addressing
|
||||
----------
|
||||
|
||||
Both static and dynamic addressing methods can be used.
|
||||
|
||||
For static addresses, no extra checks are made by the kernel, and provided
|
||||
addresses are considered right. This responsibility is for the OEM or system
|
||||
integrator.
|
||||
|
||||
For dynamic addressing, so-called Address Claiming, extra support is foreseen
|
||||
in the kernel. In J1939 any ECU is known by it's 64-bit NAME. At the moment of
|
||||
a successful address claim, the kernel keeps track of both NAME and source
|
||||
address being claimed. This serves as a base for filter schemes. By default,
|
||||
packets with a destination that is not locally, will be rejected.
|
||||
|
||||
Mixed mode packets (from a static to a dynamic address or vice versa) are
|
||||
allowed. The BSD sockets define separate API calls for getting/setting the
|
||||
local & remote address and are applicable for J1939 sockets.
|
||||
|
||||
Filtering
|
||||
---------
|
||||
|
||||
J1939 defines white list filters per socket that a user can set in order to
|
||||
receive a subset of the J1939 traffic. Filtering can be based on:
|
||||
|
||||
* SA
|
||||
* SOURCE_NAME
|
||||
* PGN
|
||||
|
||||
When multiple filters are in place for a single socket, and a packet comes in
|
||||
that matches several of those filters, the packet is only received once for
|
||||
that socket.
|
||||
|
||||
How to Use J1939
|
||||
================
|
||||
|
||||
API Calls
|
||||
---------
|
||||
|
||||
On CAN, you first need to open a socket for communicating over a CAN network.
|
||||
To use J1939, #include <linux/can/j1939.h>. From there, <linux/can.h> will be
|
||||
included too. To open a socket, use:
|
||||
|
||||
.. code-block:: C
|
||||
|
||||
s = socket(PF_CAN, SOCK_DGRAM, CAN_J1939);
|
||||
|
||||
J1939 does use SOCK_DGRAM sockets. In the J1939 specification, connections are
|
||||
mentioned in the context of transport protocol sessions. These still deliver
|
||||
packets to the other end (using several CAN packets). SOCK_STREAM is not
|
||||
supported.
|
||||
|
||||
After the successful creation of the socket, you would normally use the bind(2)
|
||||
and/or connect(2) system call to bind the socket to a CAN interface. After
|
||||
binding and/or connecting the socket, you can read(2) and write(2) from/to the
|
||||
socket or use send(2), sendto(2), sendmsg(2) and the recv*() counterpart
|
||||
operations on the socket as usual. There are also J1939 specific socket options
|
||||
described below.
|
||||
|
||||
In order to send data, a bind(2) must have been successful. bind(2) assigns a
|
||||
local address to a socket.
|
||||
|
||||
Different from CAN is that the payload data is just the data that get send,
|
||||
without it's header info. The header info is derived from the sockaddr supplied
|
||||
to bind(2), connect(2), sendto(2) and recvfrom(2). A write(2) with size 4 will
|
||||
result in a packet with 4 bytes.
|
||||
|
||||
The sockaddr structure has extensions for use with J1939 as specified below:
|
||||
|
||||
.. code-block:: C
|
||||
|
||||
struct sockaddr_can {
|
||||
sa_family_t can_family;
|
||||
int can_ifindex;
|
||||
union {
|
||||
struct {
|
||||
__u64 name;
|
||||
/* pgn:
|
||||
* 8 bit: PS in PDU2 case, else 0
|
||||
* 8 bit: PF
|
||||
* 1 bit: DP
|
||||
* 1 bit: reserved
|
||||
*/
|
||||
__u32 pgn;
|
||||
__u8 addr;
|
||||
} j1939;
|
||||
} can_addr;
|
||||
}
|
||||
|
||||
can_family & can_ifindex serve the same purpose as for other SocketCAN sockets.
|
||||
|
||||
can_addr.j1939.pgn specifies the PGN (max 0x3ffff). Individual bits are
|
||||
specified above.
|
||||
|
||||
can_addr.j1939.name contains the 64-bit J1939 NAME.
|
||||
|
||||
can_addr.j1939.addr contains the address.
|
||||
|
||||
The bind(2) system call assigns the local address, i.e. the source address when
|
||||
sending packages. If a PGN during bind(2) is set, it's used as a RX filter.
|
||||
I.e. only packets with a matching PGN are received. If an ADDR or NAME is set
|
||||
it is used as a receive filter, too. It will match the destination NAME or ADDR
|
||||
of the incoming packet. The NAME filter will work only if appropriate Address
|
||||
Claiming for this name was done on the CAN bus and registered/cached by the
|
||||
kernel.
|
||||
|
||||
On the other hand connect(2) assigns the remote address, i.e. the destination
|
||||
address. The PGN from connect(2) is used as the default PGN when sending
|
||||
packets. If ADDR or NAME is set it will be used as the default destination ADDR
|
||||
or NAME. Further a set ADDR or NAME during connect(2) is used as a receive
|
||||
filter. It will match the source NAME or ADDR of the incoming packet.
|
||||
|
||||
Both write(2) and send(2) will send a packet with local address from bind(2) and
|
||||
the remote address from connect(2). Use sendto(2) to overwrite the destination
|
||||
address.
|
||||
|
||||
If can_addr.j1939.name is set (!= 0) the NAME is looked up by the kernel and
|
||||
the corresponding ADDR is used. If can_addr.j1939.name is not set (== 0),
|
||||
can_addr.j1939.addr is used.
|
||||
|
||||
When creating a socket, reasonable defaults are set. Some options can be
|
||||
modified with setsockopt(2) & getsockopt(2).
|
||||
|
||||
RX path related options:
|
||||
|
||||
- SO_J1939_FILTER - configure array of filters
|
||||
- SO_J1939_PROMISC - disable filters set by bind(2) and connect(2)
|
||||
|
||||
By default no broadcast packets can be send or received. To enable sending or
|
||||
receiving broadcast packets use the socket option SO_BROADCAST:
|
||||
|
||||
.. code-block:: C
|
||||
|
||||
int value = 1;
|
||||
setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &value, sizeof(value));
|
||||
|
||||
The following diagram illustrates the RX path:
|
||||
|
||||
.. code::
|
||||
|
||||
+--------------------+
|
||||
| incoming packet |
|
||||
+--------------------+
|
||||
|
|
||||
V
|
||||
+--------------------+
|
||||
| SO_J1939_PROMISC? |
|
||||
+--------------------+
|
||||
| |
|
||||
no | | yes
|
||||
| |
|
||||
.---------' `---------.
|
||||
| |
|
||||
+---------------------------+ |
|
||||
| bind() + connect() + | |
|
||||
| SOCK_BROADCAST filter | |
|
||||
+---------------------------+ |
|
||||
| |
|
||||
|<---------------------'
|
||||
V
|
||||
+---------------------------+
|
||||
| SO_J1939_FILTER |
|
||||
+---------------------------+
|
||||
|
|
||||
V
|
||||
+---------------------------+
|
||||
| socket recv() |
|
||||
+---------------------------+
|
||||
|
||||
TX path related options:
|
||||
SO_J1939_SEND_PRIO - change default send priority for the socket
|
||||
|
||||
Message Flags during send() and Related System Calls
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
send(2), sendto(2) and sendmsg(2) take a 'flags' argument. Currently
|
||||
supported flags are:
|
||||
|
||||
* MSG_DONTWAIT, i.e. non-blocking operation.
|
||||
|
||||
recvmsg(2)
|
||||
^^^^^^^^^
|
||||
|
||||
In most cases recvmsg(2) is needed if you want to extract more information than
|
||||
recvfrom(2) can provide. For example package priority and timestamp. The
|
||||
Destination Address, name and packet priority (if applicable) are attached to
|
||||
the msghdr in the recvmsg(2) call. They can be extracted using cmsg(3) macros,
|
||||
with cmsg_level == SOL_J1939 && cmsg_type == SCM_J1939_DEST_ADDR,
|
||||
SCM_J1939_DEST_NAME or SCM_J1939_PRIO. The returned data is a uint8_t for
|
||||
priority and dst_addr, and uint64_t for dst_name.
|
||||
|
||||
.. code-block:: C
|
||||
|
||||
uint8_t priority, dst_addr;
|
||||
uint64_t dst_name;
|
||||
|
||||
for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
|
||||
switch (cmsg->cmsg_level) {
|
||||
case SOL_CAN_J1939:
|
||||
if (cmsg->cmsg_type == SCM_J1939_DEST_ADDR)
|
||||
dst_addr = *CMSG_DATA(cmsg);
|
||||
else if (cmsg->cmsg_type == SCM_J1939_DEST_NAME)
|
||||
memcpy(&dst_name, CMSG_DATA(cmsg), cmsg->cmsg_len - CMSG_LEN(0));
|
||||
else if (cmsg->cmsg_type == SCM_J1939_PRIO)
|
||||
priority = *CMSG_DATA(cmsg);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Dynamic Addressing
|
||||
------------------
|
||||
|
||||
Distinction has to be made between using the claimed address and doing an
|
||||
address claim. To use an already claimed address, one has to fill in the
|
||||
j1939.name member and provide it to bind(2). If the name had claimed an address
|
||||
earlier, all further messages being sent will use that address. And the
|
||||
j1939.addr member will be ignored.
|
||||
|
||||
An exception on this is PGN 0x0ee00. This is the "Address Claim/Cannot Claim
|
||||
Address" message and the kernel will use the j1939.addr member for that PGN if
|
||||
necessary.
|
||||
|
||||
To claim an address following code example can be used:
|
||||
|
||||
.. code-block:: C
|
||||
|
||||
struct sockaddr_can baddr = {
|
||||
.can_family = AF_CAN,
|
||||
.can_addr.j1939 = {
|
||||
.name = name,
|
||||
.addr = J1939_IDLE_ADDR,
|
||||
.pgn = J1939_NO_PGN, /* to disable bind() rx filter for PGN */
|
||||
},
|
||||
.can_ifindex = if_nametoindex("can0"),
|
||||
};
|
||||
|
||||
bind(sock, (struct sockaddr *)&baddr, sizeof(baddr));
|
||||
|
||||
/* for Address Claiming broadcast must be allowed */
|
||||
int value = 1;
|
||||
setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &value, sizeof(value));
|
||||
|
||||
/* configured advanced RX filter with PGN needed for Address Claiming */
|
||||
const struct j1939_filter filt[] = {
|
||||
{
|
||||
.pgn = J1939_PGN_ADDRESS_CLAIMED,
|
||||
.pgn_mask = J1939_PGN_PDU1_MAX,
|
||||
}, {
|
||||
.pgn = J1939_PGN_ADDRESS_REQUEST,
|
||||
.pgn_mask = J1939_PGN_PDU1_MAX,
|
||||
}, {
|
||||
.pgn = J1939_PGN_ADDRESS_COMMANDED,
|
||||
.pgn_mask = J1939_PGN_MAX,
|
||||
},
|
||||
};
|
||||
|
||||
setsockopt(sock, SOL_CAN_J1939, SO_J1939_FILTER, &filt, sizeof(filt));
|
||||
|
||||
uint64_t dat = htole64(name);
|
||||
const struct sockaddr_can saddr = {
|
||||
.can_family = AF_CAN,
|
||||
.can_addr.j1939 = {
|
||||
.pgn = J1939_PGN_ADDRESS_CLAIMED,
|
||||
.addr = J1939_NO_ADDR,
|
||||
},
|
||||
};
|
||||
|
||||
/* Afterwards do a sendto(2) with data set to the NAME (Little Endian). If the
|
||||
* NAME provided, does not match the j1939.name provided to bind(2), EPROTO
|
||||
* will be returned.
|
||||
*/
|
||||
sendto(sock, dat, sizeof(dat), 0, (const struct sockaddr *)&saddr, sizeof(saddr));
|
||||
|
||||
If no-one else contests the address claim within 250ms after transmission, the
|
||||
kernel marks the NAME-SA assignment as valid. The valid assignment will be kept
|
||||
among other valid NAME-SA assignments. From that point, any socket bound to the
|
||||
NAME can send packets.
|
||||
|
||||
If another ECU claims the address, the kernel will mark the NAME-SA expired.
|
||||
No socket bound to the NAME can send packets (other than address claims). To
|
||||
claim another address, some socket bound to NAME, must bind(2) again, but with
|
||||
only j1939.addr changed to the new SA, and must then send a valid address claim
|
||||
packet. This restarts the state machine in the kernel (and any other
|
||||
participant on the bus) for this NAME.
|
||||
|
||||
can-utils also include the jacd tool, so it can be used as code example or as
|
||||
default Address Claiming daemon.
|
||||
|
||||
Send Examples
|
||||
-------------
|
||||
|
||||
Static Addressing
|
||||
^^^^^^^^^^^^^^^^^
|
||||
|
||||
This example will send a PGN (0x12300) from SA 0x20 to DA 0x30.
|
||||
|
||||
Bind:
|
||||
|
||||
.. code-block:: C
|
||||
|
||||
struct sockaddr_can baddr = {
|
||||
.can_family = AF_CAN,
|
||||
.can_addr.j1939 = {
|
||||
.name = J1939_NO_NAME,
|
||||
.addr = 0x20,
|
||||
.pgn = J1939_NO_PGN,
|
||||
},
|
||||
.can_ifindex = if_nametoindex("can0"),
|
||||
};
|
||||
|
||||
bind(sock, (struct sockaddr *)&baddr, sizeof(baddr));
|
||||
|
||||
Now, the socket 'sock' is bound to the SA 0x20. Since no connect(2) was called,
|
||||
at this point we can use only sendto(2) or sendmsg(2).
|
||||
|
||||
Send:
|
||||
|
||||
.. code-block:: C
|
||||
|
||||
const struct sockaddr_can saddr = {
|
||||
.can_family = AF_CAN,
|
||||
.can_addr.j1939 = {
|
||||
.name = J1939_NO_NAME;
|
||||
.pgn = 0x30,
|
||||
.addr = 0x12300,
|
||||
},
|
||||
};
|
||||
|
||||
sendto(sock, dat, sizeof(dat), 0, (const struct sockaddr *)&saddr, sizeof(saddr));
|
|
@ -8,7 +8,8 @@ Overview
|
|||
========
|
||||
|
||||
phylink is a mechanism to support hot-pluggable networking modules
|
||||
without needing to re-initialise the adapter on hot-plug events.
|
||||
directly connected to a MAC without needing to re-initialise the
|
||||
adapter on hot-plug events.
|
||||
|
||||
phylink supports conventional phylib-based setups, fixed link setups
|
||||
and SFP (Small Formfactor Pluggable) modules at present.
|
||||
|
|
51
MAINTAINERS
51
MAINTAINERS
|
@ -641,6 +641,12 @@ M: Lino Sanfilippo <LinoSanfilippo@gmx.de>
|
|||
S: Maintained
|
||||
F: drivers/net/ethernet/alacritech/*
|
||||
|
||||
FORCEDETH GIGABIT ETHERNET DRIVER
|
||||
M: Rain River <rain.1986.08.12@gmail.com>
|
||||
L: netdev@vger.kernel.org
|
||||
S: Maintained
|
||||
F: drivers/net/ethernet/nvidia/*
|
||||
|
||||
ALCATEL SPEEDTOUCH USB DRIVER
|
||||
M: Duncan Sands <duncan.sands@free.fr>
|
||||
L: linux-usb@vger.kernel.org
|
||||
|
@ -938,6 +944,14 @@ S: Supported
|
|||
F: drivers/mux/adgs1408.c
|
||||
F: Documentation/devicetree/bindings/mux/adi,adgs1408.txt
|
||||
|
||||
ANALOG DEVICES INC ADIN DRIVER
|
||||
M: Alexandru Ardelean <alexaundru.ardelean@analog.com>
|
||||
L: netdev@vger.kernel.org
|
||||
W: http://ez.analog.com/community/linux-device-drivers
|
||||
S: Supported
|
||||
F: drivers/net/phy/adin.c
|
||||
F: Documentation/devicetree/bindings/net/adi,adin.yaml
|
||||
|
||||
ANALOG DEVICES INC ADIS DRIVER LIBRARY
|
||||
M: Alexandru Ardelean <alexandru.ardelean@analog.com>
|
||||
S: Supported
|
||||
|
@ -2917,6 +2931,7 @@ BATMAN ADVANCED
|
|||
M: Marek Lindner <mareklindner@neomailbox.ch>
|
||||
M: Simon Wunderlich <sw@simonwunderlich.de>
|
||||
M: Antonio Quartulli <a@unstable.cc>
|
||||
M: Sven Eckelmann <sven@narfation.org>
|
||||
L: b.a.t.m.a.n@lists.open-mesh.org (moderated for non-subscribers)
|
||||
W: https://www.open-mesh.org/
|
||||
B: https://www.open-mesh.org/projects/batman-adv/issues
|
||||
|
@ -3637,9 +3652,12 @@ S: Maintained
|
|||
F: Documentation/devicetree/bindings/net/can/
|
||||
F: drivers/net/can/
|
||||
F: include/linux/can/dev.h
|
||||
F: include/linux/can/led.h
|
||||
F: include/linux/can/rx-offload.h
|
||||
F: include/linux/can/platform/
|
||||
F: include/uapi/linux/can/error.h
|
||||
F: include/uapi/linux/can/netlink.h
|
||||
F: include/uapi/linux/can/vxcan.h
|
||||
|
||||
CAN NETWORK LAYER
|
||||
M: Oliver Hartkopp <socketcan@hartkopp.net>
|
||||
|
@ -3652,11 +3670,23 @@ S: Maintained
|
|||
F: Documentation/networking/can.rst
|
||||
F: net/can/
|
||||
F: include/linux/can/core.h
|
||||
F: include/linux/can/skb.h
|
||||
F: include/net/netns/can.h
|
||||
F: include/uapi/linux/can.h
|
||||
F: include/uapi/linux/can/bcm.h
|
||||
F: include/uapi/linux/can/raw.h
|
||||
F: include/uapi/linux/can/gw.h
|
||||
|
||||
CAN-J1939 NETWORK LAYER
|
||||
M: Robin van der Gracht <robin@protonic.nl>
|
||||
M: Oleksij Rempel <o.rempel@pengutronix.de>
|
||||
R: Pengutronix Kernel Team <kernel@pengutronix.de>
|
||||
L: linux-can@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/networking/j1939.txt
|
||||
F: net/can/j1939/
|
||||
F: include/uapi/linux/can/j1939.h
|
||||
|
||||
CAPABILITIES
|
||||
M: Serge Hallyn <serge@hallyn.com>
|
||||
L: linux-security-module@vger.kernel.org
|
||||
|
@ -5573,12 +5603,6 @@ T: git git://linuxtv.org/media_tree.git
|
|||
S: Maintained
|
||||
F: drivers/media/radio/dsbr100.c
|
||||
|
||||
DSCC4 DRIVER
|
||||
M: Francois Romieu <romieu@fr.zoreil.com>
|
||||
L: netdev@vger.kernel.org
|
||||
S: Maintained
|
||||
F: drivers/net/wan/dscc4.c
|
||||
|
||||
DT3155 MEDIA DRIVER
|
||||
M: Hans Verkuil <hverkuil@xs4all.nl>
|
||||
L: linux-media@vger.kernel.org
|
||||
|
@ -7504,6 +7528,7 @@ F: drivers/hid/hid-hyperv.c
|
|||
F: drivers/hv/
|
||||
F: drivers/input/serio/hyperv-keyboard.c
|
||||
F: drivers/pci/controller/pci-hyperv.c
|
||||
F: drivers/pci/controller/pci-hyperv-intf.c
|
||||
F: drivers/net/hyperv/
|
||||
F: drivers/scsi/storvsc_drv.c
|
||||
F: drivers/uio/uio_hv_generic.c
|
||||
|
@ -11201,6 +11226,7 @@ S: Maintained
|
|||
W: https://fedorahosted.org/dropwatch/
|
||||
F: net/core/drop_monitor.c
|
||||
F: include/uapi/linux/net_dropmon.h
|
||||
F: include/net/drop_monitor.h
|
||||
|
||||
NETWORKING DRIVERS
|
||||
M: "David S. Miller" <davem@davemloft.net>
|
||||
|
@ -11380,7 +11406,6 @@ F: include/net/nfc/
|
|||
F: include/uapi/linux/nfc.h
|
||||
F: drivers/nfc/
|
||||
F: include/linux/platform_data/nfcmrvl.h
|
||||
F: include/linux/platform_data/nxp-nci.h
|
||||
F: Documentation/devicetree/bindings/net/nfc/
|
||||
|
||||
NFS, SUNRPC, AND LOCKD CLIENTS
|
||||
|
@ -12643,6 +12668,14 @@ L: platform-driver-x86@vger.kernel.org
|
|||
S: Maintained
|
||||
F: drivers/platform/x86/peaq-wmi.c
|
||||
|
||||
PENSANDO ETHERNET DRIVERS
|
||||
M: Shannon Nelson <snelson@pensando.io>
|
||||
M: Pensando Drivers <drivers@pensando.io>
|
||||
L: netdev@vger.kernel.org
|
||||
S: Supported
|
||||
F: Documentation/networking/device_drivers/pensando/ionic.rst
|
||||
F: drivers/net/ethernet/pensando/
|
||||
|
||||
PER-CPU MEMORY ALLOCATOR
|
||||
M: Dennis Zhou <dennis@kernel.org>
|
||||
M: Tejun Heo <tj@kernel.org>
|
||||
|
@ -13298,7 +13331,7 @@ M: Manish Chopra <manishc@marvell.com>
|
|||
M: GR-Linux-NIC-Dev@marvell.com
|
||||
L: netdev@vger.kernel.org
|
||||
S: Supported
|
||||
F: drivers/net/ethernet/qlogic/qlge/
|
||||
F: drivers/staging/qlge/
|
||||
|
||||
QM1D1B0004 MEDIA DRIVER
|
||||
M: Akihiro Tsukada <tskd08@gmail.com>
|
||||
|
@ -17710,7 +17743,7 @@ F: Documentation/ABI/testing/sysfs-hypervisor-xen
|
|||
|
||||
XEN NETWORK BACKEND DRIVER
|
||||
M: Wei Liu <wei.liu@kernel.org>
|
||||
M: Paul Durrant <paul.durrant@citrix.com>
|
||||
M: Paul Durrant <paul@xen.org>
|
||||
L: xen-devel@lists.xenproject.org (moderated for non-subscribers)
|
||||
L: netdev@vger.kernel.org
|
||||
S: Supported
|
||||
|
|
|
@ -85,6 +85,26 @@
|
|||
system-clock-frequency = <25000000>;
|
||||
};
|
||||
};
|
||||
|
||||
mdio-mux {
|
||||
compatible = "mdio-mux-multiplexer";
|
||||
mux-controls = <&mux 0>;
|
||||
mdio-parent-bus = <&enetc_mdio_pf3>;
|
||||
#address-cells=<1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
/* on-board RGMII PHY */
|
||||
mdio@0 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
reg = <0>;
|
||||
|
||||
qds_phy1: ethernet-phy@5 {
|
||||
/* Atheros 8035 */
|
||||
reg = <5>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&duart0 {
|
||||
|
@ -172,6 +192,26 @@
|
|||
};
|
||||
};
|
||||
};
|
||||
|
||||
fpga@66 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
compatible = "fsl,ls1028aqds-fpga", "fsl,fpga-qixis-i2c",
|
||||
"simple-mfd";
|
||||
reg = <0x66>;
|
||||
|
||||
mux: mux-controller {
|
||||
compatible = "reg-mux";
|
||||
#mux-control-cells = <1>;
|
||||
mux-reg-masks = <0x54 0xf0>; /* 0: reg 0x54, bits 7:4 */
|
||||
};
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
&enetc_port1 {
|
||||
phy-handle = <&qds_phy1>;
|
||||
phy-connection-type = "rgmii-id";
|
||||
};
|
||||
|
||||
&sai1 {
|
||||
|
|
|
@ -658,6 +658,12 @@
|
|||
compatible = "fsl,enetc";
|
||||
reg = <0x000100 0 0 0 0>;
|
||||
};
|
||||
enetc_mdio_pf3: mdio@0,3 {
|
||||
compatible = "fsl,enetc-mdio";
|
||||
reg = <0x000300 0 0 0 0>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
};
|
||||
ethernet@0,4 {
|
||||
compatible = "fsl,enetc-ptp";
|
||||
reg = <0x000400 0 0 0 0>;
|
||||
|
|
|
@ -115,24 +115,34 @@
|
|||
};
|
||||
|
||||
ð {
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <ð_pins>;
|
||||
status = "okay";
|
||||
gmac0: mac@0 {
|
||||
compatible = "mediatek,eth-mac";
|
||||
reg = <0>;
|
||||
phy-mode = "2500base-x";
|
||||
|
||||
fixed-link {
|
||||
speed = <2500>;
|
||||
full-duplex;
|
||||
pause;
|
||||
};
|
||||
};
|
||||
|
||||
gmac1: mac@1 {
|
||||
compatible = "mediatek,eth-mac";
|
||||
reg = <1>;
|
||||
phy-handle = <&phy5>;
|
||||
phy-mode = "rgmii";
|
||||
|
||||
fixed-link {
|
||||
speed = <1000>;
|
||||
full-duplex;
|
||||
pause;
|
||||
};
|
||||
};
|
||||
|
||||
mdio-bus {
|
||||
mdio: mdio-bus {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
phy5: ethernet-phy@5 {
|
||||
reg = <5>;
|
||||
phy-mode = "sgmii";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -931,6 +931,5 @@
|
|||
"syscon";
|
||||
reg = <0 0x1b128000 0 0x3000>;
|
||||
#clock-cells = <1>;
|
||||
mediatek,physpeed = "2500";
|
||||
};
|
||||
};
|
||||
|
|
|
@ -171,6 +171,9 @@
|
|||
/* Rd = Ra + Rn * Rm */
|
||||
#define A64_MADD(sf, Rd, Ra, Rn, Rm) aarch64_insn_gen_data3(Rd, Ra, Rn, Rm, \
|
||||
A64_VARIANT(sf), AARCH64_INSN_DATA3_MADD)
|
||||
/* Rd = Ra - Rn * Rm */
|
||||
#define A64_MSUB(sf, Rd, Ra, Rn, Rm) aarch64_insn_gen_data3(Rd, Ra, Rn, Rm, \
|
||||
A64_VARIANT(sf), AARCH64_INSN_DATA3_MSUB)
|
||||
/* Rd = Rn * Rm */
|
||||
#define A64_MUL(sf, Rd, Rn, Rm) A64_MADD(sf, Rd, A64_ZR, Rn, Rm)
|
||||
|
||||
|
|
|
@ -409,8 +409,7 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx,
|
|||
break;
|
||||
case BPF_MOD:
|
||||
emit(A64_UDIV(is64, tmp, dst, src), ctx);
|
||||
emit(A64_MUL(is64, tmp, tmp, src), ctx);
|
||||
emit(A64_SUB(is64, dst, dst, tmp), ctx);
|
||||
emit(A64_MSUB(is64, dst, dst, tmp, src), ctx);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
@ -516,8 +515,7 @@ emit_bswap_uxt:
|
|||
case BPF_ALU64 | BPF_MOD | BPF_K:
|
||||
emit_a64_mov_i(is64, tmp2, imm, ctx);
|
||||
emit(A64_UDIV(is64, tmp, dst, tmp2), ctx);
|
||||
emit(A64_MUL(is64, tmp, tmp, tmp2), ctx);
|
||||
emit(A64_SUB(is64, dst, dst, tmp), ctx);
|
||||
emit(A64_MSUB(is64, dst, dst, tmp, tmp2), ctx);
|
||||
break;
|
||||
case BPF_ALU | BPF_LSH | BPF_K:
|
||||
case BPF_ALU64 | BPF_LSH | BPF_K:
|
||||
|
|
|
@ -3,169 +3,161 @@
|
|||
* Copyright (C) 1999, 2000 Ralf Baechle
|
||||
* Copyright (C) 1999, 2000 Silicon Graphics, Inc.
|
||||
*/
|
||||
#ifndef _IOC3_H
|
||||
#define _IOC3_H
|
||||
#ifndef MIPS_SN_IOC3_H
|
||||
#define MIPS_SN_IOC3_H
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
/* SUPERIO uart register map */
|
||||
typedef volatile struct ioc3_uartregs {
|
||||
union {
|
||||
volatile u8 rbr; /* read only, DLAB == 0 */
|
||||
volatile u8 thr; /* write only, DLAB == 0 */
|
||||
volatile u8 dll; /* DLAB == 1 */
|
||||
} u1;
|
||||
union {
|
||||
volatile u8 ier; /* DLAB == 0 */
|
||||
volatile u8 dlm; /* DLAB == 1 */
|
||||
} u2;
|
||||
union {
|
||||
volatile u8 iir; /* read only */
|
||||
volatile u8 fcr; /* write only */
|
||||
} u3;
|
||||
volatile u8 iu_lcr;
|
||||
volatile u8 iu_mcr;
|
||||
volatile u8 iu_lsr;
|
||||
volatile u8 iu_msr;
|
||||
volatile u8 iu_scr;
|
||||
} ioc3_uregs_t;
|
||||
/* serial port register map */
|
||||
struct ioc3_serialregs {
|
||||
u32 sscr;
|
||||
u32 stpir;
|
||||
u32 stcir;
|
||||
u32 srpir;
|
||||
u32 srcir;
|
||||
u32 srtr;
|
||||
u32 shadow;
|
||||
};
|
||||
|
||||
#define iu_rbr u1.rbr
|
||||
#define iu_thr u1.thr
|
||||
#define iu_dll u1.dll
|
||||
#define iu_ier u2.ier
|
||||
#define iu_dlm u2.dlm
|
||||
#define iu_iir u3.iir
|
||||
#define iu_fcr u3.fcr
|
||||
/* SUPERIO uart register map */
|
||||
struct ioc3_uartregs {
|
||||
union {
|
||||
u8 iu_rbr; /* read only, DLAB == 0 */
|
||||
u8 iu_thr; /* write only, DLAB == 0 */
|
||||
u8 iu_dll; /* DLAB == 1 */
|
||||
};
|
||||
union {
|
||||
u8 iu_ier; /* DLAB == 0 */
|
||||
u8 iu_dlm; /* DLAB == 1 */
|
||||
};
|
||||
union {
|
||||
u8 iu_iir; /* read only */
|
||||
u8 iu_fcr; /* write only */
|
||||
};
|
||||
u8 iu_lcr;
|
||||
u8 iu_mcr;
|
||||
u8 iu_lsr;
|
||||
u8 iu_msr;
|
||||
u8 iu_scr;
|
||||
};
|
||||
|
||||
struct ioc3_sioregs {
|
||||
volatile u8 fill[0x141]; /* starts at 0x141 */
|
||||
u8 fill[0x141]; /* starts at 0x141 */
|
||||
|
||||
volatile u8 uartc;
|
||||
volatile u8 kbdcg;
|
||||
u8 uartc;
|
||||
u8 kbdcg;
|
||||
|
||||
volatile u8 fill0[0x150 - 0x142 - 1];
|
||||
u8 fill0[0x150 - 0x142 - 1];
|
||||
|
||||
volatile u8 pp_data;
|
||||
volatile u8 pp_dsr;
|
||||
volatile u8 pp_dcr;
|
||||
u8 pp_data;
|
||||
u8 pp_dsr;
|
||||
u8 pp_dcr;
|
||||
|
||||
volatile u8 fill1[0x158 - 0x152 - 1];
|
||||
u8 fill1[0x158 - 0x152 - 1];
|
||||
|
||||
volatile u8 pp_fifa;
|
||||
volatile u8 pp_cfgb;
|
||||
volatile u8 pp_ecr;
|
||||
u8 pp_fifa;
|
||||
u8 pp_cfgb;
|
||||
u8 pp_ecr;
|
||||
|
||||
volatile u8 fill2[0x168 - 0x15a - 1];
|
||||
u8 fill2[0x168 - 0x15a - 1];
|
||||
|
||||
volatile u8 rtcad;
|
||||
volatile u8 rtcdat;
|
||||
u8 rtcad;
|
||||
u8 rtcdat;
|
||||
|
||||
volatile u8 fill3[0x170 - 0x169 - 1];
|
||||
u8 fill3[0x170 - 0x169 - 1];
|
||||
|
||||
struct ioc3_uartregs uartb; /* 0x20170 */
|
||||
struct ioc3_uartregs uarta; /* 0x20178 */
|
||||
};
|
||||
|
||||
struct ioc3_ethregs {
|
||||
u32 emcr; /* 0x000f0 */
|
||||
u32 eisr; /* 0x000f4 */
|
||||
u32 eier; /* 0x000f8 */
|
||||
u32 ercsr; /* 0x000fc */
|
||||
u32 erbr_h; /* 0x00100 */
|
||||
u32 erbr_l; /* 0x00104 */
|
||||
u32 erbar; /* 0x00108 */
|
||||
u32 ercir; /* 0x0010c */
|
||||
u32 erpir; /* 0x00110 */
|
||||
u32 ertr; /* 0x00114 */
|
||||
u32 etcsr; /* 0x00118 */
|
||||
u32 ersr; /* 0x0011c */
|
||||
u32 etcdc; /* 0x00120 */
|
||||
u32 ebir; /* 0x00124 */
|
||||
u32 etbr_h; /* 0x00128 */
|
||||
u32 etbr_l; /* 0x0012c */
|
||||
u32 etcir; /* 0x00130 */
|
||||
u32 etpir; /* 0x00134 */
|
||||
u32 emar_h; /* 0x00138 */
|
||||
u32 emar_l; /* 0x0013c */
|
||||
u32 ehar_h; /* 0x00140 */
|
||||
u32 ehar_l; /* 0x00144 */
|
||||
u32 micr; /* 0x00148 */
|
||||
u32 midr_r; /* 0x0014c */
|
||||
u32 midr_w; /* 0x00150 */
|
||||
};
|
||||
|
||||
struct ioc3_serioregs {
|
||||
u32 km_csr; /* 0x0009c */
|
||||
u32 k_rd; /* 0x000a0 */
|
||||
u32 m_rd; /* 0x000a4 */
|
||||
u32 k_wd; /* 0x000a8 */
|
||||
u32 m_wd; /* 0x000ac */
|
||||
};
|
||||
|
||||
/* Register layout of IOC3 in configuration space. */
|
||||
struct ioc3 {
|
||||
volatile u32 pad0[7]; /* 0x00000 */
|
||||
volatile u32 sio_ir; /* 0x0001c */
|
||||
volatile u32 sio_ies; /* 0x00020 */
|
||||
volatile u32 sio_iec; /* 0x00024 */
|
||||
volatile u32 sio_cr; /* 0x00028 */
|
||||
volatile u32 int_out; /* 0x0002c */
|
||||
volatile u32 mcr; /* 0x00030 */
|
||||
/* PCI Config Space registers */
|
||||
u32 pci_id; /* 0x00000 */
|
||||
u32 pci_scr; /* 0x00004 */
|
||||
u32 pci_rev; /* 0x00008 */
|
||||
u32 pci_lat; /* 0x0000c */
|
||||
u32 pci_addr; /* 0x00010 */
|
||||
u32 pci_err_addr_l; /* 0x00014 */
|
||||
u32 pci_err_addr_h; /* 0x00018 */
|
||||
|
||||
u32 sio_ir; /* 0x0001c */
|
||||
u32 sio_ies; /* 0x00020 */
|
||||
u32 sio_iec; /* 0x00024 */
|
||||
u32 sio_cr; /* 0x00028 */
|
||||
u32 int_out; /* 0x0002c */
|
||||
u32 mcr; /* 0x00030 */
|
||||
|
||||
/* General Purpose I/O registers */
|
||||
volatile u32 gpcr_s; /* 0x00034 */
|
||||
volatile u32 gpcr_c; /* 0x00038 */
|
||||
volatile u32 gpdr; /* 0x0003c */
|
||||
volatile u32 gppr_0; /* 0x00040 */
|
||||
volatile u32 gppr_1; /* 0x00044 */
|
||||
volatile u32 gppr_2; /* 0x00048 */
|
||||
volatile u32 gppr_3; /* 0x0004c */
|
||||
volatile u32 gppr_4; /* 0x00050 */
|
||||
volatile u32 gppr_5; /* 0x00054 */
|
||||
volatile u32 gppr_6; /* 0x00058 */
|
||||
volatile u32 gppr_7; /* 0x0005c */
|
||||
volatile u32 gppr_8; /* 0x00060 */
|
||||
volatile u32 gppr_9; /* 0x00064 */
|
||||
volatile u32 gppr_10; /* 0x00068 */
|
||||
volatile u32 gppr_11; /* 0x0006c */
|
||||
volatile u32 gppr_12; /* 0x00070 */
|
||||
volatile u32 gppr_13; /* 0x00074 */
|
||||
volatile u32 gppr_14; /* 0x00078 */
|
||||
volatile u32 gppr_15; /* 0x0007c */
|
||||
u32 gpcr_s; /* 0x00034 */
|
||||
u32 gpcr_c; /* 0x00038 */
|
||||
u32 gpdr; /* 0x0003c */
|
||||
u32 gppr[16]; /* 0x00040 */
|
||||
|
||||
/* Parallel Port Registers */
|
||||
volatile u32 ppbr_h_a; /* 0x00080 */
|
||||
volatile u32 ppbr_l_a; /* 0x00084 */
|
||||
volatile u32 ppcr_a; /* 0x00088 */
|
||||
volatile u32 ppcr; /* 0x0008c */
|
||||
volatile u32 ppbr_h_b; /* 0x00090 */
|
||||
volatile u32 ppbr_l_b; /* 0x00094 */
|
||||
volatile u32 ppcr_b; /* 0x00098 */
|
||||
u32 ppbr_h_a; /* 0x00080 */
|
||||
u32 ppbr_l_a; /* 0x00084 */
|
||||
u32 ppcr_a; /* 0x00088 */
|
||||
u32 ppcr; /* 0x0008c */
|
||||
u32 ppbr_h_b; /* 0x00090 */
|
||||
u32 ppbr_l_b; /* 0x00094 */
|
||||
u32 ppcr_b; /* 0x00098 */
|
||||
|
||||
/* Keyboard and Mouse Registers */
|
||||
volatile u32 km_csr; /* 0x0009c */
|
||||
volatile u32 k_rd; /* 0x000a0 */
|
||||
volatile u32 m_rd; /* 0x000a4 */
|
||||
volatile u32 k_wd; /* 0x000a8 */
|
||||
volatile u32 m_wd; /* 0x000ac */
|
||||
struct ioc3_serioregs serio;
|
||||
|
||||
/* Serial Port Registers */
|
||||
volatile u32 sbbr_h; /* 0x000b0 */
|
||||
volatile u32 sbbr_l; /* 0x000b4 */
|
||||
volatile u32 sscr_a; /* 0x000b8 */
|
||||
volatile u32 stpir_a; /* 0x000bc */
|
||||
volatile u32 stcir_a; /* 0x000c0 */
|
||||
volatile u32 srpir_a; /* 0x000c4 */
|
||||
volatile u32 srcir_a; /* 0x000c8 */
|
||||
volatile u32 srtr_a; /* 0x000cc */
|
||||
volatile u32 shadow_a; /* 0x000d0 */
|
||||
volatile u32 sscr_b; /* 0x000d4 */
|
||||
volatile u32 stpir_b; /* 0x000d8 */
|
||||
volatile u32 stcir_b; /* 0x000dc */
|
||||
volatile u32 srpir_b; /* 0x000e0 */
|
||||
volatile u32 srcir_b; /* 0x000e4 */
|
||||
volatile u32 srtr_b; /* 0x000e8 */
|
||||
volatile u32 shadow_b; /* 0x000ec */
|
||||
u32 sbbr_h; /* 0x000b0 */
|
||||
u32 sbbr_l; /* 0x000b4 */
|
||||
struct ioc3_serialregs port_a;
|
||||
struct ioc3_serialregs port_b;
|
||||
|
||||
/* Ethernet Registers */
|
||||
volatile u32 emcr; /* 0x000f0 */
|
||||
volatile u32 eisr; /* 0x000f4 */
|
||||
volatile u32 eier; /* 0x000f8 */
|
||||
volatile u32 ercsr; /* 0x000fc */
|
||||
volatile u32 erbr_h; /* 0x00100 */
|
||||
volatile u32 erbr_l; /* 0x00104 */
|
||||
volatile u32 erbar; /* 0x00108 */
|
||||
volatile u32 ercir; /* 0x0010c */
|
||||
volatile u32 erpir; /* 0x00110 */
|
||||
volatile u32 ertr; /* 0x00114 */
|
||||
volatile u32 etcsr; /* 0x00118 */
|
||||
volatile u32 ersr; /* 0x0011c */
|
||||
volatile u32 etcdc; /* 0x00120 */
|
||||
volatile u32 ebir; /* 0x00124 */
|
||||
volatile u32 etbr_h; /* 0x00128 */
|
||||
volatile u32 etbr_l; /* 0x0012c */
|
||||
volatile u32 etcir; /* 0x00130 */
|
||||
volatile u32 etpir; /* 0x00134 */
|
||||
volatile u32 emar_h; /* 0x00138 */
|
||||
volatile u32 emar_l; /* 0x0013c */
|
||||
volatile u32 ehar_h; /* 0x00140 */
|
||||
volatile u32 ehar_l; /* 0x00144 */
|
||||
volatile u32 micr; /* 0x00148 */
|
||||
volatile u32 midr_r; /* 0x0014c */
|
||||
volatile u32 midr_w; /* 0x00150 */
|
||||
volatile u32 pad1[(0x20000 - 0x00154) / 4];
|
||||
/* Ethernet Registers */
|
||||
struct ioc3_ethregs eth;
|
||||
u32 pad1[(0x20000 - 0x00154) / 4];
|
||||
|
||||
/* SuperIO Registers XXX */
|
||||
struct ioc3_sioregs sregs; /* 0x20000 */
|
||||
volatile u32 pad2[(0x40000 - 0x20180) / 4];
|
||||
u32 pad2[(0x40000 - 0x20180) / 4];
|
||||
|
||||
/* SSRAM Diagnostic Access */
|
||||
volatile u32 ssram[(0x80000 - 0x40000) / 4];
|
||||
u32 ssram[(0x80000 - 0x40000) / 4];
|
||||
|
||||
/* Bytebus device offsets
|
||||
0x80000 - Access to the generic devices selected with DEV0
|
||||
|
@ -178,6 +170,20 @@ struct ioc3 {
|
|||
0xFFFFF bytebus DEV_SEL_3 */
|
||||
};
|
||||
|
||||
|
||||
#define PCI_LAT 0xc /* Latency Timer */
|
||||
#define PCI_SCR_DROP_MODE_EN 0x00008000 /* drop pios on parity err */
|
||||
#define UARTA_BASE 0x178
|
||||
#define UARTB_BASE 0x170
|
||||
|
||||
/*
|
||||
* Bytebus device space
|
||||
*/
|
||||
#define IOC3_BYTEBUS_DEV0 0x80000L
|
||||
#define IOC3_BYTEBUS_DEV1 0xa0000L
|
||||
#define IOC3_BYTEBUS_DEV2 0xc0000L
|
||||
#define IOC3_BYTEBUS_DEV3 0xe0000L
|
||||
|
||||
/*
|
||||
* Ethernet RX Buffer
|
||||
*/
|
||||
|
@ -233,28 +239,20 @@ struct ioc3_etxd {
|
|||
#define ETXD_B2CNT_MASK 0x7ff00000
|
||||
#define ETXD_B2CNT_SHIFT 20
|
||||
|
||||
/*
|
||||
* Bytebus device space
|
||||
*/
|
||||
#define IOC3_BYTEBUS_DEV0 0x80000L
|
||||
#define IOC3_BYTEBUS_DEV1 0xa0000L
|
||||
#define IOC3_BYTEBUS_DEV2 0xc0000L
|
||||
#define IOC3_BYTEBUS_DEV3 0xe0000L
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
/* Superio Registers (PIO Access) */
|
||||
#define IOC3_SIO_BASE 0x20000
|
||||
#define IOC3_SIO_UARTC (IOC3_SIO_BASE+0x141) /* UART Config */
|
||||
#define IOC3_SIO_KBDCG (IOC3_SIO_BASE+0x142) /* KBD Config */
|
||||
#define IOC3_SIO_PP_BASE (IOC3_SIO_BASE+PP_BASE) /* Parallel Port */
|
||||
#define IOC3_SIO_PP_BASE (IOC3_SIO_BASE+PP_BASE) /* Parallel Port */
|
||||
#define IOC3_SIO_RTC_BASE (IOC3_SIO_BASE+0x168) /* Real Time Clock */
|
||||
#define IOC3_SIO_UB_BASE (IOC3_SIO_BASE+UARTB_BASE) /* UART B */
|
||||
#define IOC3_SIO_UA_BASE (IOC3_SIO_BASE+UARTA_BASE) /* UART A */
|
||||
|
||||
/* SSRAM Diagnostic Access */
|
||||
#define IOC3_SSRAM IOC3_RAM_OFF /* base of SSRAM diagnostic access */
|
||||
#define IOC3_SSRAM_LEN 0x40000 /* 256kb (address space size, may not be fully populated) */
|
||||
#define IOC3_SSRAM_LEN 0x40000 /* 256kb (addrspc sz, may not be populated) */
|
||||
#define IOC3_SSRAM_DM 0x0000ffff /* data mask */
|
||||
#define IOC3_SSRAM_PM 0x00010000 /* parity mask */
|
||||
|
||||
|
@ -294,10 +292,10 @@ struct ioc3_etxd {
|
|||
SIO_IR to assert */
|
||||
#define KM_CSR_M_TO_EN 0x00080000 /* KM_CSR_M_TO + KM_CSR_M_TO_EN = cause
|
||||
SIO_IR to assert */
|
||||
#define KM_CSR_K_CLAMP_ONE 0x00100000 /* Pull K_CLK low after rec. one char */
|
||||
#define KM_CSR_M_CLAMP_ONE 0x00200000 /* Pull M_CLK low after rec. one char */
|
||||
#define KM_CSR_K_CLAMP_THREE 0x00400000 /* Pull K_CLK low after rec. three chars */
|
||||
#define KM_CSR_M_CLAMP_THREE 0x00800000 /* Pull M_CLK low after rec. three char */
|
||||
#define KM_CSR_K_CLAMP_1 0x00100000 /* Pull K_CLK low aft recv 1 char */
|
||||
#define KM_CSR_M_CLAMP_1 0x00200000 /* Pull M_CLK low aft recv 1 char */
|
||||
#define KM_CSR_K_CLAMP_3 0x00400000 /* Pull K_CLK low aft recv 3 chars */
|
||||
#define KM_CSR_M_CLAMP_3 0x00800000 /* Pull M_CLK low aft recv 3 chars */
|
||||
|
||||
/* bitmasks for IOC3_K_RD and IOC3_M_RD */
|
||||
#define KM_RD_DATA_2 0x000000ff /* 3rd char recvd since last read */
|
||||
|
@ -440,10 +438,6 @@ struct ioc3_etxd {
|
|||
SIO_IR_PP_INTB | SIO_IR_PP_MEMERR)
|
||||
#define SIO_IR_RT (SIO_IR_RT_INT | SIO_IR_GEN_INT1)
|
||||
|
||||
/* macro to load pending interrupts */
|
||||
#define IOC3_PENDING_INTRS(mem) (PCI_INW(&((mem)->sio_ir)) & \
|
||||
PCI_INW(&((mem)->sio_ies_ro)))
|
||||
|
||||
/* bitmasks for SIO_CR */
|
||||
#define SIO_CR_SIO_RESET 0x00000001 /* reset the SIO */
|
||||
#define SIO_CR_SER_A_BASE 0x000000fe /* DMA poll addr port A */
|
||||
|
@ -500,10 +494,11 @@ struct ioc3_etxd {
|
|||
#define GPCR_UARTB_MODESEL 0x40 /* pin is output to port B mode sel */
|
||||
#define GPCR_UARTA_MODESEL 0x80 /* pin is output to port A mode sel */
|
||||
|
||||
#define GPPR_PHY_RESET_PIN 5 /* GIO pin controlling phy reset */
|
||||
#define GPPR_UARTB_MODESEL_PIN 6 /* GIO pin controlling uart b mode select */
|
||||
#define GPPR_UARTA_MODESEL_PIN 7 /* GIO pin controlling uart a mode select */
|
||||
#define GPPR_PHY_RESET_PIN 5 /* GIO pin cntrlling phy reset */
|
||||
#define GPPR_UARTB_MODESEL_PIN 6 /* GIO pin cntrlling uart b mode sel */
|
||||
#define GPPR_UARTA_MODESEL_PIN 7 /* GIO pin cntrlling uart a mode sel */
|
||||
|
||||
/* ethernet */
|
||||
#define EMCR_DUPLEX 0x00000001
|
||||
#define EMCR_PROMISC 0x00000002
|
||||
#define EMCR_PADEN 0x00000004
|
||||
|
@ -595,70 +590,4 @@ struct ioc3_etxd {
|
|||
|
||||
#define MIDR_DATA_MASK 0x0000ffff
|
||||
|
||||
#define ERXBUF_IPCKSUM_MASK 0x0000ffff
|
||||
#define ERXBUF_BYTECNT_MASK 0x07ff0000
|
||||
#define ERXBUF_BYTECNT_SHIFT 16
|
||||
#define ERXBUF_V 0x80000000
|
||||
|
||||
#define ERXBUF_CRCERR 0x00000001 /* aka RSV15 */
|
||||
#define ERXBUF_FRAMERR 0x00000002 /* aka RSV14 */
|
||||
#define ERXBUF_CODERR 0x00000004 /* aka RSV13 */
|
||||
#define ERXBUF_INVPREAMB 0x00000008 /* aka RSV18 */
|
||||
#define ERXBUF_LOLEN 0x00007000 /* aka RSV2_0 */
|
||||
#define ERXBUF_HILEN 0x03ff0000 /* aka RSV12_3 */
|
||||
#define ERXBUF_MULTICAST 0x04000000 /* aka RSV16 */
|
||||
#define ERXBUF_BROADCAST 0x08000000 /* aka RSV17 */
|
||||
#define ERXBUF_LONGEVENT 0x10000000 /* aka RSV19 */
|
||||
#define ERXBUF_BADPKT 0x20000000 /* aka RSV20 */
|
||||
#define ERXBUF_GOODPKT 0x40000000 /* aka RSV21 */
|
||||
#define ERXBUF_CARRIER 0x80000000 /* aka RSV22 */
|
||||
|
||||
#define ETXD_BYTECNT_MASK 0x000007ff /* total byte count */
|
||||
#define ETXD_INTWHENDONE 0x00001000 /* intr when done */
|
||||
#define ETXD_D0V 0x00010000 /* data 0 valid */
|
||||
#define ETXD_B1V 0x00020000 /* buf 1 valid */
|
||||
#define ETXD_B2V 0x00040000 /* buf 2 valid */
|
||||
#define ETXD_DOCHECKSUM 0x00080000 /* insert ip cksum */
|
||||
#define ETXD_CHKOFF_MASK 0x07f00000 /* cksum byte offset */
|
||||
#define ETXD_CHKOFF_SHIFT 20
|
||||
|
||||
#define ETXD_D0CNT_MASK 0x0000007f
|
||||
#define ETXD_B1CNT_MASK 0x0007ff00
|
||||
#define ETXD_B1CNT_SHIFT 8
|
||||
#define ETXD_B2CNT_MASK 0x7ff00000
|
||||
#define ETXD_B2CNT_SHIFT 20
|
||||
|
||||
typedef enum ioc3_subdevs_e {
|
||||
ioc3_subdev_ether,
|
||||
ioc3_subdev_generic,
|
||||
ioc3_subdev_nic,
|
||||
ioc3_subdev_kbms,
|
||||
ioc3_subdev_ttya,
|
||||
ioc3_subdev_ttyb,
|
||||
ioc3_subdev_ecpp,
|
||||
ioc3_subdev_rt,
|
||||
ioc3_nsubdevs
|
||||
} ioc3_subdev_t;
|
||||
|
||||
/* subdevice disable bits,
|
||||
* from the standard INFO_LBL_SUBDEVS
|
||||
*/
|
||||
#define IOC3_SDB_ETHER (1<<ioc3_subdev_ether)
|
||||
#define IOC3_SDB_GENERIC (1<<ioc3_subdev_generic)
|
||||
#define IOC3_SDB_NIC (1<<ioc3_subdev_nic)
|
||||
#define IOC3_SDB_KBMS (1<<ioc3_subdev_kbms)
|
||||
#define IOC3_SDB_TTYA (1<<ioc3_subdev_ttya)
|
||||
#define IOC3_SDB_TTYB (1<<ioc3_subdev_ttyb)
|
||||
#define IOC3_SDB_ECPP (1<<ioc3_subdev_ecpp)
|
||||
#define IOC3_SDB_RT (1<<ioc3_subdev_rt)
|
||||
|
||||
#define IOC3_ALL_SUBDEVS ((1<<ioc3_nsubdevs)-1)
|
||||
|
||||
#define IOC3_SDB_SERIAL (IOC3_SDB_TTYA|IOC3_SDB_TTYB)
|
||||
|
||||
#define IOC3_STD_SUBDEVS IOC3_ALL_SUBDEVS
|
||||
|
||||
#define IOC3_INTA_SUBDEVS IOC3_SDB_ETHER
|
||||
#define IOC3_INTB_SUBDEVS (IOC3_SDB_GENERIC|IOC3_SDB_KBMS|IOC3_SDB_SERIAL|IOC3_SDB_ECPP|IOC3_SDB_RT)
|
||||
|
||||
#endif /* _IOC3_H */
|
||||
#endif /* MIPS_SN_IOC3_H */
|
||||
|
|
|
@ -35,6 +35,7 @@ void prom_putchar(char c)
|
|||
{
|
||||
struct ioc3_uartregs *uart = console_uart();
|
||||
|
||||
while ((uart->iu_lsr & 0x20) == 0);
|
||||
uart->iu_thr = c;
|
||||
while ((readb(&uart->iu_lsr) & 0x20) == 0)
|
||||
;
|
||||
writeb(c, &uart->iu_thr);
|
||||
}
|
||||
|
|
|
@ -130,17 +130,6 @@ cnodeid_t get_compact_nodeid(void)
|
|||
return NASID_TO_COMPACT_NODEID(get_nasid());
|
||||
}
|
||||
|
||||
static inline void ioc3_eth_init(void)
|
||||
{
|
||||
struct ioc3 *ioc3;
|
||||
nasid_t nid;
|
||||
|
||||
nid = get_nasid();
|
||||
ioc3 = (struct ioc3 *) KL_CONFIG_CH_CONS_INFO(nid)->memory_base;
|
||||
|
||||
ioc3->eier = 0;
|
||||
}
|
||||
|
||||
extern void ip27_reboot_setup(void);
|
||||
|
||||
void __init plat_mem_setup(void)
|
||||
|
@ -182,8 +171,6 @@ void __init plat_mem_setup(void)
|
|||
panic("Kernel compiled for N mode.");
|
||||
#endif
|
||||
|
||||
ioc3_eth_init();
|
||||
|
||||
ioport_resource.start = 0;
|
||||
ioport_resource.end = ~0UL;
|
||||
set_io_port_base(IO_BASE);
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#define QDIO_MAX_QUEUES_PER_IRQ 4
|
||||
#define QDIO_MAX_BUFFERS_PER_Q 128
|
||||
#define QDIO_MAX_BUFFERS_MASK (QDIO_MAX_BUFFERS_PER_Q - 1)
|
||||
#define QDIO_BUFNR(num) ((num) & QDIO_MAX_BUFFERS_MASK)
|
||||
#define QDIO_MAX_ELEMENTS_PER_BUFFER 16
|
||||
#define QDIO_SBAL_SIZE 256
|
||||
|
||||
|
@ -359,7 +360,7 @@ struct qdio_initialize {
|
|||
qdio_handler_t *output_handler;
|
||||
void (**queue_start_poll_array) (struct ccw_device *, int,
|
||||
unsigned long);
|
||||
int scan_threshold;
|
||||
unsigned int scan_threshold;
|
||||
unsigned long int_parm;
|
||||
struct qdio_buffer **input_sbal_addr_array;
|
||||
struct qdio_buffer **output_sbal_addr_array;
|
||||
|
@ -416,6 +417,9 @@ extern int do_QDIO(struct ccw_device *, unsigned int, int, unsigned int,
|
|||
extern int qdio_start_irq(struct ccw_device *, int);
|
||||
extern int qdio_stop_irq(struct ccw_device *, int);
|
||||
extern int qdio_get_next_buffers(struct ccw_device *, int, int *, int *);
|
||||
extern int qdio_inspect_queue(struct ccw_device *cdev, unsigned int nr,
|
||||
bool is_input, unsigned int *bufnr,
|
||||
unsigned int *error);
|
||||
extern int qdio_shutdown(struct ccw_device *, int);
|
||||
extern int qdio_free(struct ccw_device *);
|
||||
extern int qdio_get_ssqd_desc(struct ccw_device *, struct qdio_ssqd_desc *);
|
||||
|
|
|
@ -502,7 +502,8 @@ static void bpf_jit_epilogue(struct bpf_jit *jit, u32 stack_depth)
|
|||
* NOTE: Use noinline because for gcov (-fprofile-arcs) gcc allocates a lot of
|
||||
* stack space for the large switch statement.
|
||||
*/
|
||||
static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp, int i)
|
||||
static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp,
|
||||
int i, bool extra_pass)
|
||||
{
|
||||
struct bpf_insn *insn = &fp->insnsi[i];
|
||||
int jmp_off, last, insn_count = 1;
|
||||
|
@ -1011,10 +1012,14 @@ static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp, int i
|
|||
*/
|
||||
case BPF_JMP | BPF_CALL:
|
||||
{
|
||||
/*
|
||||
* b0 = (__bpf_call_base + imm)(b1, b2, b3, b4, b5)
|
||||
*/
|
||||
const u64 func = (u64)__bpf_call_base + imm;
|
||||
u64 func;
|
||||
bool func_addr_fixed;
|
||||
int ret;
|
||||
|
||||
ret = bpf_jit_get_func_addr(fp, insn, extra_pass,
|
||||
&func, &func_addr_fixed);
|
||||
if (ret < 0)
|
||||
return -1;
|
||||
|
||||
REG_SET_SEEN(BPF_REG_5);
|
||||
jit->seen |= SEEN_FUNC;
|
||||
|
@ -1283,7 +1288,8 @@ branch_oc:
|
|||
/*
|
||||
* Compile eBPF program into s390x code
|
||||
*/
|
||||
static int bpf_jit_prog(struct bpf_jit *jit, struct bpf_prog *fp)
|
||||
static int bpf_jit_prog(struct bpf_jit *jit, struct bpf_prog *fp,
|
||||
bool extra_pass)
|
||||
{
|
||||
int i, insn_count;
|
||||
|
||||
|
@ -1292,7 +1298,7 @@ static int bpf_jit_prog(struct bpf_jit *jit, struct bpf_prog *fp)
|
|||
|
||||
bpf_jit_prologue(jit, fp->aux->stack_depth);
|
||||
for (i = 0; i < fp->len; i += insn_count) {
|
||||
insn_count = bpf_jit_insn(jit, fp, i);
|
||||
insn_count = bpf_jit_insn(jit, fp, i, extra_pass);
|
||||
if (insn_count < 0)
|
||||
return -1;
|
||||
/* Next instruction address */
|
||||
|
@ -1311,6 +1317,12 @@ bool bpf_jit_needs_zext(void)
|
|||
return true;
|
||||
}
|
||||
|
||||
struct s390_jit_data {
|
||||
struct bpf_binary_header *header;
|
||||
struct bpf_jit ctx;
|
||||
int pass;
|
||||
};
|
||||
|
||||
/*
|
||||
* Compile eBPF program "fp"
|
||||
*/
|
||||
|
@ -1318,7 +1330,9 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *fp)
|
|||
{
|
||||
struct bpf_prog *tmp, *orig_fp = fp;
|
||||
struct bpf_binary_header *header;
|
||||
struct s390_jit_data *jit_data;
|
||||
bool tmp_blinded = false;
|
||||
bool extra_pass = false;
|
||||
struct bpf_jit jit;
|
||||
int pass;
|
||||
|
||||
|
@ -1337,6 +1351,23 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *fp)
|
|||
fp = tmp;
|
||||
}
|
||||
|
||||
jit_data = fp->aux->jit_data;
|
||||
if (!jit_data) {
|
||||
jit_data = kzalloc(sizeof(*jit_data), GFP_KERNEL);
|
||||
if (!jit_data) {
|
||||
fp = orig_fp;
|
||||
goto out;
|
||||
}
|
||||
fp->aux->jit_data = jit_data;
|
||||
}
|
||||
if (jit_data->ctx.addrs) {
|
||||
jit = jit_data->ctx;
|
||||
header = jit_data->header;
|
||||
extra_pass = true;
|
||||
pass = jit_data->pass + 1;
|
||||
goto skip_init_ctx;
|
||||
}
|
||||
|
||||
memset(&jit, 0, sizeof(jit));
|
||||
jit.addrs = kcalloc(fp->len + 1, sizeof(*jit.addrs), GFP_KERNEL);
|
||||
if (jit.addrs == NULL) {
|
||||
|
@ -1349,7 +1380,7 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *fp)
|
|||
* - 3: Calculate program size and addrs arrray
|
||||
*/
|
||||
for (pass = 1; pass <= 3; pass++) {
|
||||
if (bpf_jit_prog(&jit, fp)) {
|
||||
if (bpf_jit_prog(&jit, fp, extra_pass)) {
|
||||
fp = orig_fp;
|
||||
goto free_addrs;
|
||||
}
|
||||
|
@ -1361,12 +1392,14 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *fp)
|
|||
fp = orig_fp;
|
||||
goto free_addrs;
|
||||
}
|
||||
|
||||
header = bpf_jit_binary_alloc(jit.size, &jit.prg_buf, 2, jit_fill_hole);
|
||||
if (!header) {
|
||||
fp = orig_fp;
|
||||
goto free_addrs;
|
||||
}
|
||||
if (bpf_jit_prog(&jit, fp)) {
|
||||
skip_init_ctx:
|
||||
if (bpf_jit_prog(&jit, fp, extra_pass)) {
|
||||
bpf_jit_binary_free(header);
|
||||
fp = orig_fp;
|
||||
goto free_addrs;
|
||||
|
@ -1375,12 +1408,24 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *fp)
|
|||
bpf_jit_dump(fp->len, jit.size, pass, jit.prg_buf);
|
||||
print_fn_code(jit.prg_buf, jit.size_prg);
|
||||
}
|
||||
bpf_jit_binary_lock_ro(header);
|
||||
if (!fp->is_func || extra_pass) {
|
||||
bpf_jit_binary_lock_ro(header);
|
||||
} else {
|
||||
jit_data->header = header;
|
||||
jit_data->ctx = jit;
|
||||
jit_data->pass = pass;
|
||||
}
|
||||
fp->bpf_func = (void *) jit.prg_buf;
|
||||
fp->jited = 1;
|
||||
fp->jited_len = jit.size;
|
||||
|
||||
if (!fp->is_func || extra_pass) {
|
||||
bpf_prog_fill_jited_linfo(fp, jit.addrs + 1);
|
||||
free_addrs:
|
||||
kfree(jit.addrs);
|
||||
kfree(jit.addrs);
|
||||
kfree(jit_data);
|
||||
fp->aux->jit_data = NULL;
|
||||
}
|
||||
out:
|
||||
if (tmp_blinded)
|
||||
bpf_jit_prog_release_other(fp, fp == orig_fp ?
|
||||
|
|
|
@ -1136,7 +1136,7 @@ DPRINTK("doing direct send\n"); /* @@@ well, this doesn't work anyway */
|
|||
else
|
||||
put_dma(tx->index,eni_dev->dma,&j,(unsigned long)
|
||||
skb_frag_page(&skb_shinfo(skb)->frags[i]) +
|
||||
skb_shinfo(skb)->frags[i].page_offset,
|
||||
skb_frag_off(&skb_shinfo(skb)->frags[i]),
|
||||
skb_frag_size(&skb_shinfo(skb)->frags[i]));
|
||||
}
|
||||
if (skb->len & 3) {
|
||||
|
|
|
@ -2580,10 +2580,9 @@ he_send(struct atm_vcc *vcc, struct sk_buff *skb)
|
|||
slot = 0;
|
||||
}
|
||||
|
||||
tpd->iovec[slot].addr = dma_map_single(&he_dev->pci_dev->dev,
|
||||
(void *) page_address(frag->page) + frag->page_offset,
|
||||
frag->size, DMA_TO_DEVICE);
|
||||
tpd->iovec[slot].len = frag->size;
|
||||
tpd->iovec[slot].addr = skb_frag_dma_map(&he_dev->pci_dev->dev,
|
||||
frag, 0, skb_frag_size(frag), DMA_TO_DEVICE);
|
||||
tpd->iovec[slot].len = skb_frag_size(frag);
|
||||
++slot;
|
||||
|
||||
}
|
||||
|
|
|
@ -516,9 +516,8 @@ struct geos_gpio_attr {
|
|||
static ssize_t geos_gpio_store(struct device *dev, struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct pci_dev *pdev = to_pci_dev(dev);
|
||||
struct geos_gpio_attr *gattr = container_of(attr, struct geos_gpio_attr, attr);
|
||||
struct solos_card *card = pci_get_drvdata(pdev);
|
||||
struct solos_card *card = dev_get_drvdata(dev);
|
||||
uint32_t data32;
|
||||
|
||||
if (count != 1 && (count != 2 || buf[1] != '\n'))
|
||||
|
@ -542,9 +541,8 @@ static ssize_t geos_gpio_store(struct device *dev, struct device_attribute *attr
|
|||
static ssize_t geos_gpio_show(struct device *dev, struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct pci_dev *pdev = to_pci_dev(dev);
|
||||
struct geos_gpio_attr *gattr = container_of(attr, struct geos_gpio_attr, attr);
|
||||
struct solos_card *card = pci_get_drvdata(pdev);
|
||||
struct solos_card *card = dev_get_drvdata(dev);
|
||||
uint32_t data32;
|
||||
|
||||
data32 = ioread32(card->config_regs + GPIO_STATUS);
|
||||
|
@ -556,9 +554,8 @@ static ssize_t geos_gpio_show(struct device *dev, struct device_attribute *attr,
|
|||
static ssize_t hardware_show(struct device *dev, struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct pci_dev *pdev = to_pci_dev(dev);
|
||||
struct geos_gpio_attr *gattr = container_of(attr, struct geos_gpio_attr, attr);
|
||||
struct solos_card *card = pci_get_drvdata(pdev);
|
||||
struct solos_card *card = dev_get_drvdata(dev);
|
||||
uint32_t data32;
|
||||
|
||||
data32 = ioread32(card->config_regs + GPIO_STATUS);
|
||||
|
|
|
@ -59,22 +59,6 @@ static inline void mips_write32(struct bcma_drv_mips *mcore,
|
|||
bcma_write32(mcore->core, offset, value);
|
||||
}
|
||||
|
||||
static const u32 ipsflag_irq_mask[] = {
|
||||
0,
|
||||
BCMA_MIPS_IPSFLAG_IRQ1,
|
||||
BCMA_MIPS_IPSFLAG_IRQ2,
|
||||
BCMA_MIPS_IPSFLAG_IRQ3,
|
||||
BCMA_MIPS_IPSFLAG_IRQ4,
|
||||
};
|
||||
|
||||
static const u32 ipsflag_irq_shift[] = {
|
||||
0,
|
||||
BCMA_MIPS_IPSFLAG_IRQ1_SHIFT,
|
||||
BCMA_MIPS_IPSFLAG_IRQ2_SHIFT,
|
||||
BCMA_MIPS_IPSFLAG_IRQ3_SHIFT,
|
||||
BCMA_MIPS_IPSFLAG_IRQ4_SHIFT,
|
||||
};
|
||||
|
||||
static u32 bcma_core_mips_irqflag(struct bcma_device *dev)
|
||||
{
|
||||
u32 flag;
|
||||
|
|
|
@ -78,7 +78,7 @@ static u16 bcma_pcie_mdio_read(struct bcma_drv_pci *pc, u16 device, u8 address)
|
|||
v |= (address << BCMA_CORE_PCI_MDIODATA_REGADDR_SHF_OLD);
|
||||
}
|
||||
|
||||
v = BCMA_CORE_PCI_MDIODATA_START;
|
||||
v |= BCMA_CORE_PCI_MDIODATA_START;
|
||||
v |= BCMA_CORE_PCI_MDIODATA_READ;
|
||||
v |= BCMA_CORE_PCI_MDIODATA_TA;
|
||||
|
||||
|
@ -121,7 +121,7 @@ static void bcma_pcie_mdio_write(struct bcma_drv_pci *pc, u16 device,
|
|||
v |= (address << BCMA_CORE_PCI_MDIODATA_REGADDR_SHF_OLD);
|
||||
}
|
||||
|
||||
v = BCMA_CORE_PCI_MDIODATA_START;
|
||||
v |= BCMA_CORE_PCI_MDIODATA_START;
|
||||
v |= BCMA_CORE_PCI_MDIODATA_WRITE;
|
||||
v |= BCMA_CORE_PCI_MDIODATA_TA;
|
||||
v |= data;
|
||||
|
|
|
@ -260,8 +260,7 @@ static void bcma_host_pci_remove(struct pci_dev *dev)
|
|||
#ifdef CONFIG_PM_SLEEP
|
||||
static int bcma_host_pci_suspend(struct device *dev)
|
||||
{
|
||||
struct pci_dev *pdev = to_pci_dev(dev);
|
||||
struct bcma_bus *bus = pci_get_drvdata(pdev);
|
||||
struct bcma_bus *bus = dev_get_drvdata(dev);
|
||||
|
||||
bus->mapped_core = NULL;
|
||||
|
||||
|
@ -270,8 +269,7 @@ static int bcma_host_pci_suspend(struct device *dev)
|
|||
|
||||
static int bcma_host_pci_resume(struct device *dev)
|
||||
{
|
||||
struct pci_dev *pdev = to_pci_dev(dev);
|
||||
struct bcma_bus *bus = pci_get_drvdata(pdev);
|
||||
struct bcma_bus *bus = dev_get_drvdata(dev);
|
||||
|
||||
return bcma_bus_resume(bus);
|
||||
}
|
||||
|
|
|
@ -222,7 +222,7 @@ static void bcma_sprom_extract_r8(struct bcma_bus *bus, const u16 *sprom)
|
|||
{
|
||||
u16 v, o;
|
||||
int i;
|
||||
u16 pwr_info_offset[] = {
|
||||
static const u16 pwr_info_offset[] = {
|
||||
SSB_SROM8_PWR_INFO_CORE0, SSB_SROM8_PWR_INFO_CORE1,
|
||||
SSB_SROM8_PWR_INFO_CORE2, SSB_SROM8_PWR_INFO_CORE3
|
||||
};
|
||||
|
@ -578,9 +578,11 @@ int bcma_sprom_get(struct bcma_bus *bus)
|
|||
{
|
||||
u16 offset = BCMA_CC_SPROM;
|
||||
u16 *sprom;
|
||||
size_t sprom_sizes[] = { SSB_SPROMSIZE_WORDS_R4,
|
||||
SSB_SPROMSIZE_WORDS_R10,
|
||||
SSB_SPROMSIZE_WORDS_R11, };
|
||||
static const size_t sprom_sizes[] = {
|
||||
SSB_SPROMSIZE_WORDS_R4,
|
||||
SSB_SPROMSIZE_WORDS_R10,
|
||||
SSB_SPROMSIZE_WORDS_R11,
|
||||
};
|
||||
int i, err = 0;
|
||||
|
||||
if (!bus->drv_cc.core)
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#define BDADDR_BCM43430A0 (&(bdaddr_t) {{0xac, 0x1f, 0x12, 0xa0, 0x43, 0x43}})
|
||||
#define BDADDR_BCM4324B3 (&(bdaddr_t) {{0x00, 0x00, 0x00, 0xb3, 0x24, 0x43}})
|
||||
#define BDADDR_BCM4330B1 (&(bdaddr_t) {{0x00, 0x00, 0x00, 0xb1, 0x30, 0x43}})
|
||||
#define BDADDR_BCM4345C5 (&(bdaddr_t) {{0xac, 0x1f, 0x00, 0xc5, 0x45, 0x43}})
|
||||
#define BDADDR_BCM43341B (&(bdaddr_t) {{0xac, 0x1f, 0x00, 0x1b, 0x34, 0x43}})
|
||||
|
||||
int btbcm_check_bdaddr(struct hci_dev *hdev)
|
||||
|
@ -73,6 +74,7 @@ int btbcm_check_bdaddr(struct hci_dev *hdev)
|
|||
!bacmp(&bda->bdaddr, BDADDR_BCM2076B1) ||
|
||||
!bacmp(&bda->bdaddr, BDADDR_BCM4324B3) ||
|
||||
!bacmp(&bda->bdaddr, BDADDR_BCM4330B1) ||
|
||||
!bacmp(&bda->bdaddr, BDADDR_BCM4345C5) ||
|
||||
!bacmp(&bda->bdaddr, BDADDR_BCM43430A0) ||
|
||||
!bacmp(&bda->bdaddr, BDADDR_BCM43341B)) {
|
||||
bt_dev_info(hdev, "BCM: Using default device address (%pMR)",
|
||||
|
@ -332,6 +334,7 @@ static const struct bcm_subver_table bcm_uart_subver_table[] = {
|
|||
{ 0x2122, "BCM4343A0" }, /* 001.001.034 */
|
||||
{ 0x2209, "BCM43430A1" }, /* 001.002.009 */
|
||||
{ 0x6119, "BCM4345C0" }, /* 003.001.025 */
|
||||
{ 0x6606, "BCM4345C5" }, /* 003.006.006 */
|
||||
{ 0x230f, "BCM4356A2" }, /* 001.003.015 */
|
||||
{ 0x220e, "BCM20702A1" }, /* 001.002.014 */
|
||||
{ 0x4217, "BCM4329B1" }, /* 002.002.023 */
|
||||
|
|
|
@ -106,8 +106,9 @@ int qca_send_pre_shutdown_cmd(struct hci_dev *hdev)
|
|||
|
||||
bt_dev_dbg(hdev, "QCA pre shutdown cmd");
|
||||
|
||||
skb = __hci_cmd_sync(hdev, QCA_PRE_SHUTDOWN_CMD, 0,
|
||||
NULL, HCI_INIT_TIMEOUT);
|
||||
skb = __hci_cmd_sync_ev(hdev, QCA_PRE_SHUTDOWN_CMD, 0,
|
||||
NULL, HCI_EV_CMD_COMPLETE, HCI_INIT_TIMEOUT);
|
||||
|
||||
if (IS_ERR(skb)) {
|
||||
err = PTR_ERR(skb);
|
||||
bt_dev_err(hdev, "QCA preshutdown_cmd failed (%d)", err);
|
||||
|
|
|
@ -178,6 +178,27 @@ static const struct id_table *btrtl_match_ic(u16 lmp_subver, u16 hci_rev,
|
|||
return &ic_id_table[i];
|
||||
}
|
||||
|
||||
static struct sk_buff *btrtl_read_local_version(struct hci_dev *hdev)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
|
||||
skb = __hci_cmd_sync(hdev, HCI_OP_READ_LOCAL_VERSION, 0, NULL,
|
||||
HCI_INIT_TIMEOUT);
|
||||
if (IS_ERR(skb)) {
|
||||
rtl_dev_err(hdev, "HCI_OP_READ_LOCAL_VERSION failed (%ld)",
|
||||
PTR_ERR(skb));
|
||||
return skb;
|
||||
}
|
||||
|
||||
if (skb->len != sizeof(struct hci_rp_read_local_version)) {
|
||||
rtl_dev_err(hdev, "HCI_OP_READ_LOCAL_VERSION event length mismatch");
|
||||
kfree_skb(skb);
|
||||
return ERR_PTR(-EIO);
|
||||
}
|
||||
|
||||
return skb;
|
||||
}
|
||||
|
||||
static int rtl_read_rom_version(struct hci_dev *hdev, u8 *version)
|
||||
{
|
||||
struct rtl_rom_version_evt *rom_version;
|
||||
|
@ -186,19 +207,19 @@ static int rtl_read_rom_version(struct hci_dev *hdev, u8 *version)
|
|||
/* Read RTL ROM version command */
|
||||
skb = __hci_cmd_sync(hdev, 0xfc6d, 0, NULL, HCI_INIT_TIMEOUT);
|
||||
if (IS_ERR(skb)) {
|
||||
rtl_dev_err(hdev, "Read ROM version failed (%ld)\n",
|
||||
rtl_dev_err(hdev, "Read ROM version failed (%ld)",
|
||||
PTR_ERR(skb));
|
||||
return PTR_ERR(skb);
|
||||
}
|
||||
|
||||
if (skb->len != sizeof(*rom_version)) {
|
||||
rtl_dev_err(hdev, "RTL version event length mismatch\n");
|
||||
rtl_dev_err(hdev, "version event length mismatch");
|
||||
kfree_skb(skb);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
rom_version = (struct rtl_rom_version_evt *)skb->data;
|
||||
rtl_dev_info(hdev, "rom_version status=%x version=%x\n",
|
||||
rtl_dev_info(hdev, "rom_version status=%x version=%x",
|
||||
rom_version->status, rom_version->version);
|
||||
|
||||
*version = rom_version->version;
|
||||
|
@ -242,7 +263,7 @@ static int rtlbt_parse_firmware(struct hci_dev *hdev,
|
|||
|
||||
fwptr = btrtl_dev->fw_data + btrtl_dev->fw_len - sizeof(extension_sig);
|
||||
if (memcmp(fwptr, extension_sig, sizeof(extension_sig)) != 0) {
|
||||
rtl_dev_err(hdev, "extension section signature mismatch\n");
|
||||
rtl_dev_err(hdev, "extension section signature mismatch");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
@ -263,7 +284,7 @@ static int rtlbt_parse_firmware(struct hci_dev *hdev,
|
|||
break;
|
||||
|
||||
if (length == 0) {
|
||||
rtl_dev_err(hdev, "found instruction with length 0\n");
|
||||
rtl_dev_err(hdev, "found instruction with length 0");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
@ -276,7 +297,7 @@ static int rtlbt_parse_firmware(struct hci_dev *hdev,
|
|||
}
|
||||
|
||||
if (project_id < 0) {
|
||||
rtl_dev_err(hdev, "failed to find version instruction\n");
|
||||
rtl_dev_err(hdev, "failed to find version instruction");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
@ -287,13 +308,13 @@ static int rtlbt_parse_firmware(struct hci_dev *hdev,
|
|||
}
|
||||
|
||||
if (i >= ARRAY_SIZE(project_id_to_lmp_subver)) {
|
||||
rtl_dev_err(hdev, "unknown project id %d\n", project_id);
|
||||
rtl_dev_err(hdev, "unknown project id %d", project_id);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (btrtl_dev->ic_info->lmp_subver !=
|
||||
project_id_to_lmp_subver[i].lmp_subver) {
|
||||
rtl_dev_err(hdev, "firmware is for %x but this is a %x\n",
|
||||
rtl_dev_err(hdev, "firmware is for %x but this is a %x",
|
||||
project_id_to_lmp_subver[i].lmp_subver,
|
||||
btrtl_dev->ic_info->lmp_subver);
|
||||
return -EINVAL;
|
||||
|
@ -301,7 +322,7 @@ static int rtlbt_parse_firmware(struct hci_dev *hdev,
|
|||
|
||||
epatch_info = (struct rtl_epatch_header *)btrtl_dev->fw_data;
|
||||
if (memcmp(epatch_info->signature, RTL_EPATCH_SIGNATURE, 8) != 0) {
|
||||
rtl_dev_err(hdev, "bad EPATCH signature\n");
|
||||
rtl_dev_err(hdev, "bad EPATCH signature");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
@ -368,6 +389,8 @@ static int rtl_download_firmware(struct hci_dev *hdev,
|
|||
int frag_len = RTL_FRAG_LEN;
|
||||
int ret = 0;
|
||||
int i;
|
||||
struct sk_buff *skb;
|
||||
struct hci_rp_read_local_version *rp;
|
||||
|
||||
dl_cmd = kmalloc(sizeof(struct rtl_download_cmd), GFP_KERNEL);
|
||||
if (!dl_cmd)
|
||||
|
@ -378,7 +401,11 @@ static int rtl_download_firmware(struct hci_dev *hdev,
|
|||
|
||||
BT_DBG("download fw (%d/%d)", i, frag_num);
|
||||
|
||||
dl_cmd->index = i;
|
||||
if (i > 0x7f)
|
||||
dl_cmd->index = (i & 0x7f) + 1;
|
||||
else
|
||||
dl_cmd->index = i;
|
||||
|
||||
if (i == (frag_num - 1)) {
|
||||
dl_cmd->index |= 0x80; /* data end */
|
||||
frag_len = fw_len % RTL_FRAG_LEN;
|
||||
|
@ -389,14 +416,14 @@ static int rtl_download_firmware(struct hci_dev *hdev,
|
|||
skb = __hci_cmd_sync(hdev, 0xfc20, frag_len + 1, dl_cmd,
|
||||
HCI_INIT_TIMEOUT);
|
||||
if (IS_ERR(skb)) {
|
||||
rtl_dev_err(hdev, "download fw command failed (%ld)\n",
|
||||
rtl_dev_err(hdev, "download fw command failed (%ld)",
|
||||
PTR_ERR(skb));
|
||||
ret = -PTR_ERR(skb);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (skb->len != sizeof(struct rtl_download_response)) {
|
||||
rtl_dev_err(hdev, "download fw event length mismatch\n");
|
||||
rtl_dev_err(hdev, "download fw event length mismatch");
|
||||
kfree_skb(skb);
|
||||
ret = -EIO;
|
||||
goto out;
|
||||
|
@ -406,6 +433,18 @@ static int rtl_download_firmware(struct hci_dev *hdev,
|
|||
data += RTL_FRAG_LEN;
|
||||
}
|
||||
|
||||
skb = btrtl_read_local_version(hdev);
|
||||
if (IS_ERR(skb)) {
|
||||
ret = PTR_ERR(skb);
|
||||
rtl_dev_err(hdev, "read local version failed");
|
||||
goto out;
|
||||
}
|
||||
|
||||
rp = (struct hci_rp_read_local_version *)skb->data;
|
||||
rtl_dev_info(hdev, "fw version 0x%04x%04x",
|
||||
__le16_to_cpu(rp->hci_rev), __le16_to_cpu(rp->lmp_subver));
|
||||
kfree_skb(skb);
|
||||
|
||||
out:
|
||||
kfree(dl_cmd);
|
||||
return ret;
|
||||
|
@ -416,7 +455,7 @@ static int rtl_load_file(struct hci_dev *hdev, const char *name, u8 **buff)
|
|||
const struct firmware *fw;
|
||||
int ret;
|
||||
|
||||
rtl_dev_info(hdev, "rtl: loading %s\n", name);
|
||||
rtl_dev_info(hdev, "loading %s", name);
|
||||
ret = request_firmware(&fw, name, &hdev->dev);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
@ -440,7 +479,7 @@ static int btrtl_setup_rtl8723a(struct hci_dev *hdev,
|
|||
* (which is only for RTL8723B and newer).
|
||||
*/
|
||||
if (!memcmp(btrtl_dev->fw_data, RTL_EPATCH_SIGNATURE, 8)) {
|
||||
rtl_dev_err(hdev, "unexpected EPATCH signature!\n");
|
||||
rtl_dev_err(hdev, "unexpected EPATCH signature!");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
@ -475,7 +514,7 @@ static int btrtl_setup_rtl8723b(struct hci_dev *hdev,
|
|||
fw_data = tbuff;
|
||||
}
|
||||
|
||||
rtl_dev_info(hdev, "cfg_sz %d, total sz %d\n", btrtl_dev->cfg_len, ret);
|
||||
rtl_dev_info(hdev, "cfg_sz %d, total sz %d", btrtl_dev->cfg_len, ret);
|
||||
|
||||
ret = rtl_download_firmware(hdev, fw_data, ret);
|
||||
|
||||
|
@ -484,27 +523,6 @@ out:
|
|||
return ret;
|
||||
}
|
||||
|
||||
static struct sk_buff *btrtl_read_local_version(struct hci_dev *hdev)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
|
||||
skb = __hci_cmd_sync(hdev, HCI_OP_READ_LOCAL_VERSION, 0, NULL,
|
||||
HCI_INIT_TIMEOUT);
|
||||
if (IS_ERR(skb)) {
|
||||
rtl_dev_err(hdev, "HCI_OP_READ_LOCAL_VERSION failed (%ld)\n",
|
||||
PTR_ERR(skb));
|
||||
return skb;
|
||||
}
|
||||
|
||||
if (skb->len != sizeof(struct hci_rp_read_local_version)) {
|
||||
rtl_dev_err(hdev, "HCI_OP_READ_LOCAL_VERSION event length mismatch\n");
|
||||
kfree_skb(skb);
|
||||
return ERR_PTR(-EIO);
|
||||
}
|
||||
|
||||
return skb;
|
||||
}
|
||||
|
||||
void btrtl_free(struct btrtl_device_info *btrtl_dev)
|
||||
{
|
||||
kfree(btrtl_dev->fw_data);
|
||||
|
@ -537,7 +555,7 @@ struct btrtl_device_info *btrtl_initialize(struct hci_dev *hdev,
|
|||
}
|
||||
|
||||
resp = (struct hci_rp_read_local_version *)skb->data;
|
||||
rtl_dev_info(hdev, "rtl: examining hci_ver=%02x hci_rev=%04x lmp_ver=%02x lmp_subver=%04x\n",
|
||||
rtl_dev_info(hdev, "examining hci_ver=%02x hci_rev=%04x lmp_ver=%02x lmp_subver=%04x",
|
||||
resp->hci_ver, resp->hci_rev,
|
||||
resp->lmp_ver, resp->lmp_subver);
|
||||
|
||||
|
@ -550,7 +568,7 @@ struct btrtl_device_info *btrtl_initialize(struct hci_dev *hdev,
|
|||
hdev->bus);
|
||||
|
||||
if (!btrtl_dev->ic_info) {
|
||||
rtl_dev_info(hdev, "rtl: unknown IC info, lmp subver %04x, hci rev %04x, hci ver %04x",
|
||||
rtl_dev_info(hdev, "unknown IC info, lmp subver %04x, hci rev %04x, hci ver %04x",
|
||||
lmp_subver, hci_rev, hci_ver);
|
||||
return btrtl_dev;
|
||||
}
|
||||
|
@ -564,7 +582,7 @@ struct btrtl_device_info *btrtl_initialize(struct hci_dev *hdev,
|
|||
btrtl_dev->fw_len = rtl_load_file(hdev, btrtl_dev->ic_info->fw_name,
|
||||
&btrtl_dev->fw_data);
|
||||
if (btrtl_dev->fw_len < 0) {
|
||||
rtl_dev_err(hdev, "firmware file %s not found\n",
|
||||
rtl_dev_err(hdev, "firmware file %s not found",
|
||||
btrtl_dev->ic_info->fw_name);
|
||||
ret = btrtl_dev->fw_len;
|
||||
goto err_free;
|
||||
|
@ -582,7 +600,7 @@ struct btrtl_device_info *btrtl_initialize(struct hci_dev *hdev,
|
|||
&btrtl_dev->cfg_data);
|
||||
if (btrtl_dev->ic_info->config_needed &&
|
||||
btrtl_dev->cfg_len <= 0) {
|
||||
rtl_dev_err(hdev, "mandatory config file %s not found\n",
|
||||
rtl_dev_err(hdev, "mandatory config file %s not found",
|
||||
btrtl_dev->ic_info->cfg_name);
|
||||
ret = btrtl_dev->cfg_len;
|
||||
goto err_free;
|
||||
|
@ -608,7 +626,7 @@ int btrtl_download_firmware(struct hci_dev *hdev,
|
|||
* to a different value.
|
||||
*/
|
||||
if (!btrtl_dev->ic_info) {
|
||||
rtl_dev_info(hdev, "rtl: assuming no firmware upload needed\n");
|
||||
rtl_dev_info(hdev, "assuming no firmware upload needed");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -622,7 +640,7 @@ int btrtl_download_firmware(struct hci_dev *hdev,
|
|||
case RTL_ROM_LMP_8822B:
|
||||
return btrtl_setup_rtl8723b(hdev, btrtl_dev);
|
||||
default:
|
||||
rtl_dev_info(hdev, "rtl: assuming no firmware upload needed\n");
|
||||
rtl_dev_info(hdev, "assuming no firmware upload needed");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
@ -641,6 +659,11 @@ int btrtl_setup_realtek(struct hci_dev *hdev)
|
|||
|
||||
btrtl_free(btrtl_dev);
|
||||
|
||||
/* Enable controller to do both LE scan and BR/EDR inquiry
|
||||
* simultaneously.
|
||||
*/
|
||||
set_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, &hdev->quirks);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(btrtl_setup_realtek);
|
||||
|
@ -714,18 +737,18 @@ int btrtl_get_uart_settings(struct hci_dev *hdev,
|
|||
|
||||
total_data_len = btrtl_dev->cfg_len - sizeof(*config);
|
||||
if (total_data_len <= 0) {
|
||||
rtl_dev_warn(hdev, "no config loaded\n");
|
||||
rtl_dev_warn(hdev, "no config loaded");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
config = (struct rtl_vendor_config *)btrtl_dev->cfg_data;
|
||||
if (le32_to_cpu(config->signature) != RTL_CONFIG_MAGIC) {
|
||||
rtl_dev_err(hdev, "invalid config magic\n");
|
||||
rtl_dev_err(hdev, "invalid config magic");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (total_data_len < le16_to_cpu(config->total_len)) {
|
||||
rtl_dev_err(hdev, "config is too short\n");
|
||||
rtl_dev_err(hdev, "config is too short");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
@ -735,7 +758,7 @@ int btrtl_get_uart_settings(struct hci_dev *hdev,
|
|||
switch (le16_to_cpu(entry->offset)) {
|
||||
case 0xc:
|
||||
if (entry->len < sizeof(*device_baudrate)) {
|
||||
rtl_dev_err(hdev, "invalid UART config entry\n");
|
||||
rtl_dev_err(hdev, "invalid UART config entry");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
@ -752,7 +775,7 @@ int btrtl_get_uart_settings(struct hci_dev *hdev,
|
|||
break;
|
||||
|
||||
default:
|
||||
rtl_dev_dbg(hdev, "skipping config entry 0x%x (len %u)\n",
|
||||
rtl_dev_dbg(hdev, "skipping config entry 0x%x (len %u)",
|
||||
le16_to_cpu(entry->offset), entry->len);
|
||||
break;
|
||||
};
|
||||
|
@ -761,13 +784,13 @@ int btrtl_get_uart_settings(struct hci_dev *hdev,
|
|||
}
|
||||
|
||||
if (!found) {
|
||||
rtl_dev_err(hdev, "no UART config entry found\n");
|
||||
rtl_dev_err(hdev, "no UART config entry found");
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
rtl_dev_dbg(hdev, "device baudrate = 0x%08x\n", *device_baudrate);
|
||||
rtl_dev_dbg(hdev, "controller baudrate = %u\n", *controller_baudrate);
|
||||
rtl_dev_dbg(hdev, "flow control %d\n", *flow_control);
|
||||
rtl_dev_dbg(hdev, "device baudrate = 0x%08x", *device_baudrate);
|
||||
rtl_dev_dbg(hdev, "controller baudrate = %u", *controller_baudrate);
|
||||
rtl_dev_dbg(hdev, "flow control %d", *flow_control);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -438,6 +438,7 @@ static const struct dmi_system_id btusb_needs_reset_resume_table[] = {
|
|||
#define BTUSB_OOB_WAKE_ENABLED 11
|
||||
#define BTUSB_HW_RESET_ACTIVE 12
|
||||
#define BTUSB_TX_WAIT_VND_EVT 13
|
||||
#define BTUSB_WAKEUP_DISABLE 14
|
||||
|
||||
struct btusb_data {
|
||||
struct hci_dev *hdev;
|
||||
|
@ -526,6 +527,36 @@ static void btusb_intel_cmd_timeout(struct hci_dev *hdev)
|
|||
gpiod_set_value_cansleep(reset_gpio, 0);
|
||||
}
|
||||
|
||||
static void btusb_rtl_cmd_timeout(struct hci_dev *hdev)
|
||||
{
|
||||
struct btusb_data *data = hci_get_drvdata(hdev);
|
||||
struct gpio_desc *reset_gpio = data->reset_gpio;
|
||||
|
||||
if (++data->cmd_timeout_cnt < 5)
|
||||
return;
|
||||
|
||||
if (!reset_gpio) {
|
||||
bt_dev_err(hdev, "No gpio to reset Realtek device, ignoring");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Toggle the hard reset line. The Realtek device is going to
|
||||
* yank itself off the USB and then replug. The cleanup is handled
|
||||
* correctly on the way out (standard USB disconnect), and the new
|
||||
* device is detected cleanly and bound to the driver again like
|
||||
* it should be.
|
||||
*/
|
||||
if (test_and_set_bit(BTUSB_HW_RESET_ACTIVE, &data->flags)) {
|
||||
bt_dev_err(hdev, "last reset failed? Not resetting again");
|
||||
return;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
static inline void btusb_free_frags(struct btusb_data *data)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
@ -1174,6 +1205,13 @@ static int btusb_open(struct hci_dev *hdev)
|
|||
|
||||
data->intf->needs_remote_wakeup = 1;
|
||||
|
||||
/* Disable device remote wakeup when host is suspended
|
||||
* For Realtek chips, global suspend without
|
||||
* SET_FEATURE (DEVICE_REMOTE_WAKEUP) can save more power in device.
|
||||
*/
|
||||
if (test_bit(BTUSB_WAKEUP_DISABLE, &data->flags))
|
||||
device_wakeup_disable(&data->udev->dev);
|
||||
|
||||
if (test_and_set_bit(BTUSB_INTR_RUNNING, &data->flags))
|
||||
goto done;
|
||||
|
||||
|
@ -1237,6 +1275,11 @@ static int btusb_close(struct hci_dev *hdev)
|
|||
goto failed;
|
||||
|
||||
data->intf->needs_remote_wakeup = 0;
|
||||
|
||||
/* Enable remote wake up for auto-suspend */
|
||||
if (test_bit(BTUSB_WAKEUP_DISABLE, &data->flags))
|
||||
data->intf->needs_remote_wakeup = 1;
|
||||
|
||||
usb_autopm_put_interface(data->intf);
|
||||
|
||||
failed:
|
||||
|
@ -3768,12 +3811,13 @@ static int btusb_probe(struct usb_interface *intf,
|
|||
if (id->driver_info & BTUSB_REALTEK) {
|
||||
hdev->setup = btrtl_setup_realtek;
|
||||
hdev->shutdown = btrtl_shutdown_realtek;
|
||||
hdev->cmd_timeout = btusb_rtl_cmd_timeout;
|
||||
|
||||
/* Realtek devices lose their updated firmware over suspend,
|
||||
* but the USB hub doesn't notice any status change.
|
||||
* Explicitly request a device reset on resume.
|
||||
/* Realtek devices lose their updated firmware over global
|
||||
* suspend that means host doesn't send SET_FEATURE
|
||||
* (DEVICE_REMOTE_WAKEUP)
|
||||
*/
|
||||
interface_to_usbdev(intf)->quirks |= USB_QUIRK_RESET_RESUME;
|
||||
set_bit(BTUSB_WAKEUP_DISABLE, &data->flags);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -3947,6 +3991,19 @@ static int btusb_suspend(struct usb_interface *intf, pm_message_t message)
|
|||
enable_irq(data->oob_wake_irq);
|
||||
}
|
||||
|
||||
/* For global suspend, Realtek devices lose the loaded fw
|
||||
* in them. But for autosuspend, firmware should remain.
|
||||
* Actually, it depends on whether the usb host sends
|
||||
* set feature (enable wakeup) or not.
|
||||
*/
|
||||
if (test_bit(BTUSB_WAKEUP_DISABLE, &data->flags)) {
|
||||
if (PMSG_IS_AUTO(message) &&
|
||||
device_can_wakeup(&data->udev->dev))
|
||||
data->udev->do_remote_wakeup = 1;
|
||||
else if (!PMSG_IS_AUTO(message))
|
||||
data->udev->reset_resume = 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -260,7 +260,7 @@ static int bcm_gpio_set_power(struct bcm_device *dev, bool powered)
|
|||
}
|
||||
|
||||
/* wait for device to power on and come out of reset */
|
||||
usleep_range(10000, 20000);
|
||||
usleep_range(100000, 120000);
|
||||
|
||||
dev->res_enabled = powered;
|
||||
|
||||
|
@ -824,6 +824,21 @@ unlock:
|
|||
}
|
||||
#endif
|
||||
|
||||
/* Some firmware reports an IRQ which does not work (wrong pin in fw table?) */
|
||||
static const struct dmi_system_id bcm_broken_irq_dmi_table[] = {
|
||||
{
|
||||
.ident = "Meegopad T08",
|
||||
.matches = {
|
||||
DMI_EXACT_MATCH(DMI_BOARD_VENDOR,
|
||||
"To be filled by OEM."),
|
||||
DMI_EXACT_MATCH(DMI_BOARD_NAME, "T3 MRD"),
|
||||
DMI_EXACT_MATCH(DMI_BOARD_VERSION, "V1.1"),
|
||||
},
|
||||
},
|
||||
{ }
|
||||
};
|
||||
|
||||
#ifdef CONFIG_ACPI
|
||||
static const struct acpi_gpio_params first_gpio = { 0, 0, false };
|
||||
static const struct acpi_gpio_params second_gpio = { 1, 0, false };
|
||||
static const struct acpi_gpio_params third_gpio = { 2, 0, false };
|
||||
|
@ -842,21 +857,6 @@ static const struct acpi_gpio_mapping acpi_bcm_int_first_gpios[] = {
|
|||
{ },
|
||||
};
|
||||
|
||||
/* Some firmware reports an IRQ which does not work (wrong pin in fw table?) */
|
||||
static const struct dmi_system_id bcm_broken_irq_dmi_table[] = {
|
||||
{
|
||||
.ident = "Meegopad T08",
|
||||
.matches = {
|
||||
DMI_EXACT_MATCH(DMI_BOARD_VENDOR,
|
||||
"To be filled by OEM."),
|
||||
DMI_EXACT_MATCH(DMI_BOARD_NAME, "T3 MRD"),
|
||||
DMI_EXACT_MATCH(DMI_BOARD_VERSION, "V1.1"),
|
||||
},
|
||||
},
|
||||
{ }
|
||||
};
|
||||
|
||||
#ifdef CONFIG_ACPI
|
||||
static int bcm_resource(struct acpi_resource *ares, void *data)
|
||||
{
|
||||
struct bcm_device *dev = data;
|
||||
|
@ -1419,6 +1419,7 @@ static void bcm_serdev_remove(struct serdev_device *serdev)
|
|||
#ifdef CONFIG_OF
|
||||
static const struct of_device_id bcm_bluetooth_of_match[] = {
|
||||
{ .compatible = "brcm,bcm20702a1" },
|
||||
{ .compatible = "brcm,bcm4345c5" },
|
||||
{ .compatible = "brcm,bcm4330-bt" },
|
||||
{ .compatible = "brcm,bcm43438-bt" },
|
||||
{ },
|
||||
|
|
|
@ -504,26 +504,7 @@ static int qca_open(struct hci_uart *hu)
|
|||
qca->tx_ibs_state = HCI_IBS_TX_ASLEEP;
|
||||
qca->rx_ibs_state = HCI_IBS_RX_ASLEEP;
|
||||
|
||||
/* clocks actually on, but we start votes off */
|
||||
qca->tx_vote = false;
|
||||
qca->rx_vote = false;
|
||||
qca->flags = 0;
|
||||
|
||||
qca->ibs_sent_wacks = 0;
|
||||
qca->ibs_sent_slps = 0;
|
||||
qca->ibs_sent_wakes = 0;
|
||||
qca->ibs_recv_wacks = 0;
|
||||
qca->ibs_recv_slps = 0;
|
||||
qca->ibs_recv_wakes = 0;
|
||||
qca->vote_last_jif = jiffies;
|
||||
qca->vote_on_ms = 0;
|
||||
qca->vote_off_ms = 0;
|
||||
qca->votes_on = 0;
|
||||
qca->votes_off = 0;
|
||||
qca->tx_votes_on = 0;
|
||||
qca->tx_votes_off = 0;
|
||||
qca->rx_votes_on = 0;
|
||||
qca->rx_votes_off = 0;
|
||||
|
||||
hu->priv = qca;
|
||||
|
||||
|
@ -1263,6 +1244,11 @@ static int qca_setup(struct hci_uart *hu)
|
|||
/* Patch downloading has to be done without IBS mode */
|
||||
clear_bit(QCA_IBS_ENABLED, &qca->flags);
|
||||
|
||||
/* Enable controller to do both LE scan and BR/EDR inquiry
|
||||
* simultaneously.
|
||||
*/
|
||||
set_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, &hdev->quirks);
|
||||
|
||||
if (qca_is_wcn399x(soc_type)) {
|
||||
bt_dev_info(hdev, "setting up wcn3990");
|
||||
|
||||
|
@ -1328,7 +1314,7 @@ static int qca_setup(struct hci_uart *hu)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static struct hci_uart_proto qca_proto = {
|
||||
static const struct hci_uart_proto qca_proto = {
|
||||
.id = HCI_UART_QCA,
|
||||
.name = "QCA",
|
||||
.manufacturer = 29,
|
||||
|
@ -1391,6 +1377,8 @@ static int qca_power_off(struct hci_dev *hdev)
|
|||
/* Perform pre shutdown command */
|
||||
qca_send_pre_shutdown_cmd(hdev);
|
||||
|
||||
usleep_range(8000, 10000);
|
||||
|
||||
qca_power_shutdown(hu);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -1134,7 +1134,9 @@ copy:
|
|||
}
|
||||
/* Update the skb. */
|
||||
if (merge) {
|
||||
skb_shinfo(skb)->frags[i - 1].size += copy;
|
||||
skb_frag_size_add(
|
||||
&skb_shinfo(skb)->frags[i - 1],
|
||||
copy);
|
||||
} else {
|
||||
skb_fill_page_desc(skb, i, page, off, copy);
|
||||
if (off + copy < pg_size) {
|
||||
|
@ -1247,7 +1249,7 @@ new_buf:
|
|||
|
||||
i = skb_shinfo(skb)->nr_frags;
|
||||
if (skb_can_coalesce(skb, i, page, offset)) {
|
||||
skb_shinfo(skb)->frags[i - 1].size += copy;
|
||||
skb_frag_size_add(&skb_shinfo(skb)->frags[i - 1], copy);
|
||||
} else if (i < MAX_SKB_FRAGS) {
|
||||
get_page(page);
|
||||
skb_fill_page_desc(skb, i, page, offset, copy);
|
||||
|
|
|
@ -474,7 +474,8 @@ static int chtls_getsockopt(struct sock *sk, int level, int optname,
|
|||
struct tls_context *ctx = tls_get_ctx(sk);
|
||||
|
||||
if (level != SOL_TLS)
|
||||
return ctx->getsockopt(sk, level, optname, optval, optlen);
|
||||
return ctx->sk_proto->getsockopt(sk, level,
|
||||
optname, optval, optlen);
|
||||
|
||||
return do_chtls_getsockopt(sk, optval, optlen);
|
||||
}
|
||||
|
@ -541,7 +542,8 @@ static int chtls_setsockopt(struct sock *sk, int level, int optname,
|
|||
struct tls_context *ctx = tls_get_ctx(sk);
|
||||
|
||||
if (level != SOL_TLS)
|
||||
return ctx->setsockopt(sk, level, optname, optval, optlen);
|
||||
return ctx->sk_proto->setsockopt(sk, level,
|
||||
optname, optval, optlen);
|
||||
|
||||
return do_chtls_setsockopt(sk, optname, optval, optlen);
|
||||
}
|
||||
|
|
|
@ -303,7 +303,7 @@ static void ms_ff_worker(struct work_struct *work)
|
|||
r->magnitude[MAGNITUDE_WEAK] = ms->weak; /* right actuator */
|
||||
|
||||
ret = hid_hw_output_report(hdev, (__u8 *)r, sizeof(*r));
|
||||
if (ret)
|
||||
if (ret < 0)
|
||||
hid_warn(hdev, "failed to send FF report\n");
|
||||
}
|
||||
|
||||
|
|
|
@ -181,7 +181,8 @@ static void ssip_skb_to_msg(struct sk_buff *skb, struct hsi_msg *msg)
|
|||
sg = sg_next(sg);
|
||||
BUG_ON(!sg);
|
||||
frag = &skb_shinfo(skb)->frags[i];
|
||||
sg_set_page(sg, frag->page.p, frag->size, frag->page_offset);
|
||||
sg_set_page(sg, skb_frag_page(frag), skb_frag_size(frag),
|
||||
skb_frag_off(frag));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -102,13 +102,13 @@ static noinline int build_vnic_ulp_payload(struct sdma_engine *sde,
|
|||
goto bail_txadd;
|
||||
|
||||
for (i = 0; i < skb_shinfo(tx->skb)->nr_frags; i++) {
|
||||
struct skb_frag_struct *frag = &skb_shinfo(tx->skb)->frags[i];
|
||||
skb_frag_t *frag = &skb_shinfo(tx->skb)->frags[i];
|
||||
|
||||
/* combine physically continuous fragments later? */
|
||||
ret = sdma_txadd_page(sde->dd,
|
||||
&tx->txreq,
|
||||
skb_frag_page(frag),
|
||||
frag->page_offset,
|
||||
skb_frag_off(frag),
|
||||
skb_frag_size(frag));
|
||||
if (unlikely(ret))
|
||||
goto bail_txadd;
|
||||
|
|
|
@ -186,136 +186,6 @@ int mlx5_cmd_dealloc_memic(struct mlx5_dm *dm, phys_addr_t addr, u64 length)
|
|||
return err;
|
||||
}
|
||||
|
||||
int mlx5_cmd_alloc_sw_icm(struct mlx5_dm *dm, int type, u64 length,
|
||||
u16 uid, phys_addr_t *addr, u32 *obj_id)
|
||||
{
|
||||
struct mlx5_core_dev *dev = dm->dev;
|
||||
u32 out[MLX5_ST_SZ_DW(general_obj_out_cmd_hdr)] = {};
|
||||
u32 in[MLX5_ST_SZ_DW(create_sw_icm_in)] = {};
|
||||
unsigned long *block_map;
|
||||
u64 icm_start_addr;
|
||||
u32 log_icm_size;
|
||||
u32 num_blocks;
|
||||
u32 max_blocks;
|
||||
u64 block_idx;
|
||||
void *sw_icm;
|
||||
int ret;
|
||||
|
||||
MLX5_SET(general_obj_in_cmd_hdr, in, opcode,
|
||||
MLX5_CMD_OP_CREATE_GENERAL_OBJECT);
|
||||
MLX5_SET(general_obj_in_cmd_hdr, in, obj_type, MLX5_OBJ_TYPE_SW_ICM);
|
||||
MLX5_SET(general_obj_in_cmd_hdr, in, uid, uid);
|
||||
|
||||
switch (type) {
|
||||
case MLX5_IB_UAPI_DM_TYPE_STEERING_SW_ICM:
|
||||
icm_start_addr = MLX5_CAP64_DEV_MEM(dev,
|
||||
steering_sw_icm_start_address);
|
||||
log_icm_size = MLX5_CAP_DEV_MEM(dev, log_steering_sw_icm_size);
|
||||
block_map = dm->steering_sw_icm_alloc_blocks;
|
||||
break;
|
||||
case MLX5_IB_UAPI_DM_TYPE_HEADER_MODIFY_SW_ICM:
|
||||
icm_start_addr = MLX5_CAP64_DEV_MEM(dev,
|
||||
header_modify_sw_icm_start_address);
|
||||
log_icm_size = MLX5_CAP_DEV_MEM(dev,
|
||||
log_header_modify_sw_icm_size);
|
||||
block_map = dm->header_modify_sw_icm_alloc_blocks;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
num_blocks = (length + MLX5_SW_ICM_BLOCK_SIZE(dev) - 1) >>
|
||||
MLX5_LOG_SW_ICM_BLOCK_SIZE(dev);
|
||||
max_blocks = BIT(log_icm_size - MLX5_LOG_SW_ICM_BLOCK_SIZE(dev));
|
||||
spin_lock(&dm->lock);
|
||||
block_idx = bitmap_find_next_zero_area(block_map,
|
||||
max_blocks,
|
||||
0,
|
||||
num_blocks, 0);
|
||||
|
||||
if (block_idx < max_blocks)
|
||||
bitmap_set(block_map,
|
||||
block_idx, num_blocks);
|
||||
|
||||
spin_unlock(&dm->lock);
|
||||
|
||||
if (block_idx >= max_blocks)
|
||||
return -ENOMEM;
|
||||
|
||||
sw_icm = MLX5_ADDR_OF(create_sw_icm_in, in, sw_icm);
|
||||
icm_start_addr += block_idx << MLX5_LOG_SW_ICM_BLOCK_SIZE(dev);
|
||||
MLX5_SET64(sw_icm, sw_icm, sw_icm_start_addr,
|
||||
icm_start_addr);
|
||||
MLX5_SET(sw_icm, sw_icm, log_sw_icm_size, ilog2(length));
|
||||
|
||||
ret = mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out));
|
||||
if (ret) {
|
||||
spin_lock(&dm->lock);
|
||||
bitmap_clear(block_map,
|
||||
block_idx, num_blocks);
|
||||
spin_unlock(&dm->lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
*addr = icm_start_addr;
|
||||
*obj_id = MLX5_GET(general_obj_out_cmd_hdr, out, obj_id);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mlx5_cmd_dealloc_sw_icm(struct mlx5_dm *dm, int type, u64 length,
|
||||
u16 uid, phys_addr_t addr, u32 obj_id)
|
||||
{
|
||||
struct mlx5_core_dev *dev = dm->dev;
|
||||
u32 out[MLX5_ST_SZ_DW(general_obj_out_cmd_hdr)] = {};
|
||||
u32 in[MLX5_ST_SZ_DW(general_obj_in_cmd_hdr)] = {};
|
||||
unsigned long *block_map;
|
||||
u32 num_blocks;
|
||||
u64 start_idx;
|
||||
int err;
|
||||
|
||||
num_blocks = (length + MLX5_SW_ICM_BLOCK_SIZE(dev) - 1) >>
|
||||
MLX5_LOG_SW_ICM_BLOCK_SIZE(dev);
|
||||
|
||||
switch (type) {
|
||||
case MLX5_IB_UAPI_DM_TYPE_STEERING_SW_ICM:
|
||||
start_idx =
|
||||
(addr - MLX5_CAP64_DEV_MEM(
|
||||
dev, steering_sw_icm_start_address)) >>
|
||||
MLX5_LOG_SW_ICM_BLOCK_SIZE(dev);
|
||||
block_map = dm->steering_sw_icm_alloc_blocks;
|
||||
break;
|
||||
case MLX5_IB_UAPI_DM_TYPE_HEADER_MODIFY_SW_ICM:
|
||||
start_idx =
|
||||
(addr -
|
||||
MLX5_CAP64_DEV_MEM(
|
||||
dev, header_modify_sw_icm_start_address)) >>
|
||||
MLX5_LOG_SW_ICM_BLOCK_SIZE(dev);
|
||||
block_map = dm->header_modify_sw_icm_alloc_blocks;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
MLX5_SET(general_obj_in_cmd_hdr, in, opcode,
|
||||
MLX5_CMD_OP_DESTROY_GENERAL_OBJECT);
|
||||
MLX5_SET(general_obj_in_cmd_hdr, in, obj_type, MLX5_OBJ_TYPE_SW_ICM);
|
||||
MLX5_SET(general_obj_in_cmd_hdr, in, obj_id, obj_id);
|
||||
MLX5_SET(general_obj_in_cmd_hdr, in, uid, uid);
|
||||
|
||||
err = mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out));
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
spin_lock(&dm->lock);
|
||||
bitmap_clear(block_map,
|
||||
start_idx, num_blocks);
|
||||
spin_unlock(&dm->lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mlx5_cmd_query_ext_ppcnt_counters(struct mlx5_core_dev *dev, void *out)
|
||||
{
|
||||
u32 in[MLX5_ST_SZ_DW(ppcnt_reg)] = {};
|
||||
|
|
|
@ -65,8 +65,4 @@ int mlx5_cmd_alloc_q_counter(struct mlx5_core_dev *dev, u16 *counter_id,
|
|||
u16 uid);
|
||||
int mlx5_cmd_mad_ifc(struct mlx5_core_dev *dev, const void *inb, void *outb,
|
||||
u16 opmod, u8 port);
|
||||
int mlx5_cmd_alloc_sw_icm(struct mlx5_dm *dm, int type, u64 length,
|
||||
u16 uid, phys_addr_t *addr, u32 *obj_id);
|
||||
int mlx5_cmd_dealloc_sw_icm(struct mlx5_dm *dm, int type, u64 length,
|
||||
u16 uid, phys_addr_t addr, u32 obj_id);
|
||||
#endif /* MLX5_IB_CMD_H */
|
||||
|
|
|
@ -922,6 +922,7 @@ static bool devx_is_general_cmd(void *in, struct mlx5_ib_dev *dev)
|
|||
case MLX5_CMD_OP_QUERY_CONG_STATUS:
|
||||
case MLX5_CMD_OP_QUERY_CONG_PARAMS:
|
||||
case MLX5_CMD_OP_QUERY_CONG_STATISTICS:
|
||||
case MLX5_CMD_OP_QUERY_LAG:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
|
|
|
@ -322,11 +322,11 @@ void mlx5_ib_destroy_flow_action_raw(struct mlx5_ib_flow_action *maction)
|
|||
switch (maction->flow_action_raw.sub_type) {
|
||||
case MLX5_IB_FLOW_ACTION_MODIFY_HEADER:
|
||||
mlx5_modify_header_dealloc(maction->flow_action_raw.dev->mdev,
|
||||
maction->flow_action_raw.action_id);
|
||||
maction->flow_action_raw.modify_hdr);
|
||||
break;
|
||||
case MLX5_IB_FLOW_ACTION_PACKET_REFORMAT:
|
||||
mlx5_packet_reformat_dealloc(maction->flow_action_raw.dev->mdev,
|
||||
maction->flow_action_raw.action_id);
|
||||
maction->flow_action_raw.pkt_reformat);
|
||||
break;
|
||||
case MLX5_IB_FLOW_ACTION_DECAP:
|
||||
break;
|
||||
|
@ -352,10 +352,11 @@ mlx5_ib_create_modify_header(struct mlx5_ib_dev *dev,
|
|||
if (!maction)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
ret = mlx5_modify_header_alloc(dev->mdev, namespace, num_actions, in,
|
||||
&maction->flow_action_raw.action_id);
|
||||
maction->flow_action_raw.modify_hdr =
|
||||
mlx5_modify_header_alloc(dev->mdev, namespace, num_actions, in);
|
||||
|
||||
if (ret) {
|
||||
if (IS_ERR(maction->flow_action_raw.modify_hdr)) {
|
||||
ret = PTR_ERR(maction->flow_action_raw.modify_hdr);
|
||||
kfree(maction);
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
|
@ -479,11 +480,13 @@ static int mlx5_ib_flow_action_create_packet_reformat_ctx(
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = mlx5_packet_reformat_alloc(dev->mdev, prm_prt, len,
|
||||
in, namespace,
|
||||
&maction->flow_action_raw.action_id);
|
||||
if (ret)
|
||||
maction->flow_action_raw.pkt_reformat =
|
||||
mlx5_packet_reformat_alloc(dev->mdev, prm_prt, len,
|
||||
in, namespace);
|
||||
if (IS_ERR(maction->flow_action_raw.pkt_reformat)) {
|
||||
ret = PTR_ERR(maction->flow_action_raw.pkt_reformat);
|
||||
return ret;
|
||||
}
|
||||
|
||||
maction->flow_action_raw.sub_type =
|
||||
MLX5_IB_FLOW_ACTION_PACKET_REFORMAT;
|
||||
|
|
|
@ -2280,6 +2280,7 @@ static inline int check_dm_type_support(struct mlx5_ib_dev *dev,
|
|||
return -EOPNOTSUPP;
|
||||
break;
|
||||
case MLX5_IB_UAPI_DM_TYPE_STEERING_SW_ICM:
|
||||
case MLX5_IB_UAPI_DM_TYPE_HEADER_MODIFY_SW_ICM:
|
||||
if (!capable(CAP_SYS_RAWIO) ||
|
||||
!capable(CAP_NET_RAW))
|
||||
return -EPERM;
|
||||
|
@ -2344,20 +2345,20 @@ static int handle_alloc_dm_sw_icm(struct ib_ucontext *ctx,
|
|||
struct uverbs_attr_bundle *attrs,
|
||||
int type)
|
||||
{
|
||||
struct mlx5_dm *dm_db = &to_mdev(ctx->device)->dm;
|
||||
struct mlx5_core_dev *dev = to_mdev(ctx->device)->mdev;
|
||||
u64 act_size;
|
||||
int err;
|
||||
|
||||
/* Allocation size must a multiple of the basic block size
|
||||
* and a power of 2.
|
||||
*/
|
||||
act_size = round_up(attr->length, MLX5_SW_ICM_BLOCK_SIZE(dm_db->dev));
|
||||
act_size = round_up(attr->length, MLX5_SW_ICM_BLOCK_SIZE(dev));
|
||||
act_size = roundup_pow_of_two(act_size);
|
||||
|
||||
dm->size = act_size;
|
||||
err = mlx5_cmd_alloc_sw_icm(dm_db, type, act_size,
|
||||
to_mucontext(ctx)->devx_uid, &dm->dev_addr,
|
||||
&dm->icm_dm.obj_id);
|
||||
err = mlx5_dm_sw_icm_alloc(dev, type, act_size,
|
||||
to_mucontext(ctx)->devx_uid, &dm->dev_addr,
|
||||
&dm->icm_dm.obj_id);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
|
@ -2365,9 +2366,9 @@ static int handle_alloc_dm_sw_icm(struct ib_ucontext *ctx,
|
|||
MLX5_IB_ATTR_ALLOC_DM_RESP_START_OFFSET,
|
||||
&dm->dev_addr, sizeof(dm->dev_addr));
|
||||
if (err)
|
||||
mlx5_cmd_dealloc_sw_icm(dm_db, type, dm->size,
|
||||
to_mucontext(ctx)->devx_uid,
|
||||
dm->dev_addr, dm->icm_dm.obj_id);
|
||||
mlx5_dm_sw_icm_dealloc(dev, type, dm->size,
|
||||
to_mucontext(ctx)->devx_uid, dm->dev_addr,
|
||||
dm->icm_dm.obj_id);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
@ -2407,8 +2408,14 @@ struct ib_dm *mlx5_ib_alloc_dm(struct ib_device *ibdev,
|
|||
attrs);
|
||||
break;
|
||||
case MLX5_IB_UAPI_DM_TYPE_STEERING_SW_ICM:
|
||||
err = handle_alloc_dm_sw_icm(context, dm,
|
||||
attr, attrs,
|
||||
MLX5_SW_ICM_TYPE_STEERING);
|
||||
break;
|
||||
case MLX5_IB_UAPI_DM_TYPE_HEADER_MODIFY_SW_ICM:
|
||||
err = handle_alloc_dm_sw_icm(context, dm, attr, attrs, type);
|
||||
err = handle_alloc_dm_sw_icm(context, dm,
|
||||
attr, attrs,
|
||||
MLX5_SW_ICM_TYPE_HEADER_MODIFY);
|
||||
break;
|
||||
default:
|
||||
err = -EOPNOTSUPP;
|
||||
|
@ -2428,6 +2435,7 @@ int mlx5_ib_dealloc_dm(struct ib_dm *ibdm, struct uverbs_attr_bundle *attrs)
|
|||
{
|
||||
struct mlx5_ib_ucontext *ctx = rdma_udata_to_drv_context(
|
||||
&attrs->driver_udata, struct mlx5_ib_ucontext, ibucontext);
|
||||
struct mlx5_core_dev *dev = to_mdev(ibdm->device)->mdev;
|
||||
struct mlx5_dm *dm_db = &to_mdev(ibdm->device)->dm;
|
||||
struct mlx5_ib_dm *dm = to_mdm(ibdm);
|
||||
u32 page_idx;
|
||||
|
@ -2439,19 +2447,23 @@ int mlx5_ib_dealloc_dm(struct ib_dm *ibdm, struct uverbs_attr_bundle *attrs)
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
page_idx = (dm->dev_addr -
|
||||
pci_resource_start(dm_db->dev->pdev, 0) -
|
||||
MLX5_CAP64_DEV_MEM(dm_db->dev,
|
||||
memic_bar_start_addr)) >>
|
||||
PAGE_SHIFT;
|
||||
page_idx = (dm->dev_addr - pci_resource_start(dev->pdev, 0) -
|
||||
MLX5_CAP64_DEV_MEM(dev, memic_bar_start_addr)) >>
|
||||
PAGE_SHIFT;
|
||||
bitmap_clear(ctx->dm_pages, page_idx,
|
||||
DIV_ROUND_UP(dm->size, PAGE_SIZE));
|
||||
break;
|
||||
case MLX5_IB_UAPI_DM_TYPE_STEERING_SW_ICM:
|
||||
ret = mlx5_dm_sw_icm_dealloc(dev, MLX5_SW_ICM_TYPE_STEERING,
|
||||
dm->size, ctx->devx_uid, dm->dev_addr,
|
||||
dm->icm_dm.obj_id);
|
||||
if (ret)
|
||||
return ret;
|
||||
break;
|
||||
case MLX5_IB_UAPI_DM_TYPE_HEADER_MODIFY_SW_ICM:
|
||||
ret = mlx5_cmd_dealloc_sw_icm(dm_db, dm->type, dm->size,
|
||||
ctx->devx_uid, dm->dev_addr,
|
||||
dm->icm_dm.obj_id);
|
||||
ret = mlx5_dm_sw_icm_dealloc(dev, MLX5_SW_ICM_TYPE_HEADER_MODIFY,
|
||||
dm->size, ctx->devx_uid, dm->dev_addr,
|
||||
dm->icm_dm.obj_id);
|
||||
if (ret)
|
||||
return ret;
|
||||
break;
|
||||
|
@ -2646,7 +2658,8 @@ int parse_flow_flow_action(struct mlx5_ib_flow_action *maction,
|
|||
if (action->action & MLX5_FLOW_CONTEXT_ACTION_MOD_HDR)
|
||||
return -EINVAL;
|
||||
action->action |= MLX5_FLOW_CONTEXT_ACTION_MOD_HDR;
|
||||
action->modify_id = maction->flow_action_raw.action_id;
|
||||
action->modify_hdr =
|
||||
maction->flow_action_raw.modify_hdr;
|
||||
return 0;
|
||||
}
|
||||
if (maction->flow_action_raw.sub_type ==
|
||||
|
@ -2663,8 +2676,8 @@ int parse_flow_flow_action(struct mlx5_ib_flow_action *maction,
|
|||
return -EINVAL;
|
||||
action->action |=
|
||||
MLX5_FLOW_CONTEXT_ACTION_PACKET_REFORMAT;
|
||||
action->reformat_id =
|
||||
maction->flow_action_raw.action_id;
|
||||
action->pkt_reformat =
|
||||
maction->flow_action_raw.pkt_reformat;
|
||||
return 0;
|
||||
}
|
||||
/* fall through */
|
||||
|
@ -6096,8 +6109,6 @@ static struct ib_counters *mlx5_ib_create_counters(struct ib_device *device,
|
|||
|
||||
static void mlx5_ib_stage_init_cleanup(struct mlx5_ib_dev *dev)
|
||||
{
|
||||
struct mlx5_core_dev *mdev = dev->mdev;
|
||||
|
||||
mlx5_ib_cleanup_multiport_master(dev);
|
||||
if (IS_ENABLED(CONFIG_INFINIBAND_ON_DEMAND_PAGING)) {
|
||||
srcu_barrier(&dev->mr_srcu);
|
||||
|
@ -6105,29 +6116,11 @@ static void mlx5_ib_stage_init_cleanup(struct mlx5_ib_dev *dev)
|
|||
}
|
||||
|
||||
WARN_ON(!bitmap_empty(dev->dm.memic_alloc_pages, MLX5_MAX_MEMIC_PAGES));
|
||||
|
||||
WARN_ON(dev->dm.steering_sw_icm_alloc_blocks &&
|
||||
!bitmap_empty(
|
||||
dev->dm.steering_sw_icm_alloc_blocks,
|
||||
BIT(MLX5_CAP_DEV_MEM(mdev, log_steering_sw_icm_size) -
|
||||
MLX5_LOG_SW_ICM_BLOCK_SIZE(mdev))));
|
||||
|
||||
kfree(dev->dm.steering_sw_icm_alloc_blocks);
|
||||
|
||||
WARN_ON(dev->dm.header_modify_sw_icm_alloc_blocks &&
|
||||
!bitmap_empty(dev->dm.header_modify_sw_icm_alloc_blocks,
|
||||
BIT(MLX5_CAP_DEV_MEM(
|
||||
mdev, log_header_modify_sw_icm_size) -
|
||||
MLX5_LOG_SW_ICM_BLOCK_SIZE(mdev))));
|
||||
|
||||
kfree(dev->dm.header_modify_sw_icm_alloc_blocks);
|
||||
}
|
||||
|
||||
static int mlx5_ib_stage_init_init(struct mlx5_ib_dev *dev)
|
||||
{
|
||||
struct mlx5_core_dev *mdev = dev->mdev;
|
||||
u64 header_modify_icm_blocks = 0;
|
||||
u64 steering_icm_blocks = 0;
|
||||
int err;
|
||||
int i;
|
||||
|
||||
|
@ -6174,51 +6167,17 @@ static int mlx5_ib_stage_init_init(struct mlx5_ib_dev *dev)
|
|||
INIT_LIST_HEAD(&dev->qp_list);
|
||||
spin_lock_init(&dev->reset_flow_resource_lock);
|
||||
|
||||
if (MLX5_CAP_GEN_64(mdev, general_obj_types) &
|
||||
MLX5_GENERAL_OBJ_TYPES_CAP_SW_ICM) {
|
||||
if (MLX5_CAP64_DEV_MEM(mdev, steering_sw_icm_start_address)) {
|
||||
steering_icm_blocks =
|
||||
BIT(MLX5_CAP_DEV_MEM(mdev,
|
||||
log_steering_sw_icm_size) -
|
||||
MLX5_LOG_SW_ICM_BLOCK_SIZE(mdev));
|
||||
|
||||
dev->dm.steering_sw_icm_alloc_blocks =
|
||||
kcalloc(BITS_TO_LONGS(steering_icm_blocks),
|
||||
sizeof(unsigned long), GFP_KERNEL);
|
||||
if (!dev->dm.steering_sw_icm_alloc_blocks)
|
||||
goto err_mp;
|
||||
}
|
||||
|
||||
if (MLX5_CAP64_DEV_MEM(mdev,
|
||||
header_modify_sw_icm_start_address)) {
|
||||
header_modify_icm_blocks = BIT(
|
||||
MLX5_CAP_DEV_MEM(
|
||||
mdev, log_header_modify_sw_icm_size) -
|
||||
MLX5_LOG_SW_ICM_BLOCK_SIZE(mdev));
|
||||
|
||||
dev->dm.header_modify_sw_icm_alloc_blocks =
|
||||
kcalloc(BITS_TO_LONGS(header_modify_icm_blocks),
|
||||
sizeof(unsigned long), GFP_KERNEL);
|
||||
if (!dev->dm.header_modify_sw_icm_alloc_blocks)
|
||||
goto err_dm;
|
||||
}
|
||||
}
|
||||
|
||||
spin_lock_init(&dev->dm.lock);
|
||||
dev->dm.dev = mdev;
|
||||
|
||||
if (IS_ENABLED(CONFIG_INFINIBAND_ON_DEMAND_PAGING)) {
|
||||
err = init_srcu_struct(&dev->mr_srcu);
|
||||
if (err)
|
||||
goto err_dm;
|
||||
goto err_mp;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err_dm:
|
||||
kfree(dev->dm.steering_sw_icm_alloc_blocks);
|
||||
kfree(dev->dm.header_modify_sw_icm_alloc_blocks);
|
||||
|
||||
err_mp:
|
||||
mlx5_ib_cleanup_multiport_master(dev);
|
||||
|
||||
|
|
|
@ -868,7 +868,10 @@ struct mlx5_ib_flow_action {
|
|||
struct {
|
||||
struct mlx5_ib_dev *dev;
|
||||
u32 sub_type;
|
||||
u32 action_id;
|
||||
union {
|
||||
struct mlx5_modify_hdr *modify_hdr;
|
||||
struct mlx5_pkt_reformat *pkt_reformat;
|
||||
};
|
||||
} flow_action_raw;
|
||||
};
|
||||
};
|
||||
|
@ -881,8 +884,6 @@ struct mlx5_dm {
|
|||
*/
|
||||
spinlock_t lock;
|
||||
DECLARE_BITMAP(memic_alloc_pages, MLX5_MAX_MEMIC_PAGES);
|
||||
unsigned long *steering_sw_icm_alloc_blocks;
|
||||
unsigned long *header_modify_sw_icm_alloc_blocks;
|
||||
};
|
||||
|
||||
struct mlx5_read_counters_attr {
|
||||
|
|
|
@ -86,7 +86,7 @@ struct mlx5_core_srq *mlx5_cmd_get_srq(struct mlx5_ib_dev *dev, u32 srqn)
|
|||
xa_lock(&table->array);
|
||||
srq = xa_load(&table->array, srqn);
|
||||
if (srq)
|
||||
atomic_inc(&srq->common.refcount);
|
||||
refcount_inc(&srq->common.refcount);
|
||||
xa_unlock(&table->array);
|
||||
|
||||
return srq;
|
||||
|
@ -592,7 +592,7 @@ int mlx5_cmd_create_srq(struct mlx5_ib_dev *dev, struct mlx5_core_srq *srq,
|
|||
if (err)
|
||||
return err;
|
||||
|
||||
atomic_set(&srq->common.refcount, 1);
|
||||
refcount_set(&srq->common.refcount, 1);
|
||||
init_completion(&srq->common.free);
|
||||
|
||||
err = xa_err(xa_store_irq(&table->array, srq->srqn, srq, GFP_KERNEL));
|
||||
|
@ -675,7 +675,7 @@ static int srq_event_notifier(struct notifier_block *nb,
|
|||
xa_lock(&table->array);
|
||||
srq = xa_load(&table->array, srqn);
|
||||
if (srq)
|
||||
atomic_inc(&srq->common.refcount);
|
||||
refcount_inc(&srq->common.refcount);
|
||||
xa_unlock(&table->array);
|
||||
|
||||
if (!srq)
|
||||
|
|
|
@ -293,7 +293,8 @@ int ipoib_dma_map_tx(struct ib_device *ca, struct ipoib_tx_buf *tx_req)
|
|||
const skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
|
||||
mapping[i + off] = ib_dma_map_page(ca,
|
||||
skb_frag_page(frag),
|
||||
frag->page_offset, skb_frag_size(frag),
|
||||
skb_frag_off(frag),
|
||||
skb_frag_size(frag),
|
||||
DMA_TO_DEVICE);
|
||||
if (unlikely(ib_dma_mapping_error(ca, mapping[i + off])))
|
||||
goto partial_error;
|
||||
|
|
|
@ -509,8 +509,7 @@ HDLC_irq_xpr(struct bchannel *bch)
|
|||
if (bch->tx_skb && bch->tx_idx < bch->tx_skb->len) {
|
||||
hdlc_fill_fifo(bch);
|
||||
} else {
|
||||
if (bch->tx_skb)
|
||||
dev_kfree_skb(bch->tx_skb);
|
||||
dev_kfree_skb(bch->tx_skb);
|
||||
if (get_next_bframe(bch)) {
|
||||
hdlc_fill_fifo(bch);
|
||||
test_and_clear_bit(FLG_TX_EMPTY, &bch->Flags);
|
||||
|
|
|
@ -1119,8 +1119,7 @@ tx_birq(struct bchannel *bch)
|
|||
if (bch->tx_skb && bch->tx_idx < bch->tx_skb->len)
|
||||
hfcpci_fill_fifo(bch);
|
||||
else {
|
||||
if (bch->tx_skb)
|
||||
dev_kfree_skb(bch->tx_skb);
|
||||
dev_kfree_skb(bch->tx_skb);
|
||||
if (get_next_bframe(bch))
|
||||
hfcpci_fill_fifo(bch);
|
||||
}
|
||||
|
@ -1132,8 +1131,7 @@ tx_dirq(struct dchannel *dch)
|
|||
if (dch->tx_skb && dch->tx_idx < dch->tx_skb->len)
|
||||
hfcpci_fill_dfifo(dch->hw);
|
||||
else {
|
||||
if (dch->tx_skb)
|
||||
dev_kfree_skb(dch->tx_skb);
|
||||
dev_kfree_skb(dch->tx_skb);
|
||||
if (get_next_dframe(dch))
|
||||
hfcpci_fill_dfifo(dch->hw);
|
||||
}
|
||||
|
|
|
@ -190,8 +190,7 @@ isac_rme_irq(struct isac_hw *isac)
|
|||
#endif
|
||||
}
|
||||
WriteISAC(isac, ISAC_CMDR, 0x80);
|
||||
if (isac->dch.rx_skb)
|
||||
dev_kfree_skb(isac->dch.rx_skb);
|
||||
dev_kfree_skb(isac->dch.rx_skb);
|
||||
isac->dch.rx_skb = NULL;
|
||||
} else {
|
||||
count = ReadISAC(isac, ISAC_RBCL) & 0x1f;
|
||||
|
@ -210,8 +209,7 @@ isac_xpr_irq(struct isac_hw *isac)
|
|||
if (isac->dch.tx_skb && isac->dch.tx_idx < isac->dch.tx_skb->len) {
|
||||
isac_fill_fifo(isac);
|
||||
} else {
|
||||
if (isac->dch.tx_skb)
|
||||
dev_kfree_skb(isac->dch.tx_skb);
|
||||
dev_kfree_skb(isac->dch.tx_skb);
|
||||
if (get_next_dframe(&isac->dch))
|
||||
isac_fill_fifo(isac);
|
||||
}
|
||||
|
@ -464,8 +462,7 @@ isacsx_rme_irq(struct isac_hw *isac)
|
|||
isac->dch.err_crc++;
|
||||
#endif
|
||||
WriteISAC(isac, ISACX_CMDRD, ISACX_CMDRD_RMC);
|
||||
if (isac->dch.rx_skb)
|
||||
dev_kfree_skb(isac->dch.rx_skb);
|
||||
dev_kfree_skb(isac->dch.rx_skb);
|
||||
isac->dch.rx_skb = NULL;
|
||||
} else {
|
||||
count = ReadISAC(isac, ISACX_RBCLD) & 0x1f;
|
||||
|
@ -1012,8 +1009,7 @@ hscx_xpr(struct hscx_hw *hx)
|
|||
if (hx->bch.tx_skb && hx->bch.tx_idx < hx->bch.tx_skb->len) {
|
||||
hscx_fill_fifo(hx);
|
||||
} else {
|
||||
if (hx->bch.tx_skb)
|
||||
dev_kfree_skb(hx->bch.tx_skb);
|
||||
dev_kfree_skb(hx->bch.tx_skb);
|
||||
if (get_next_bframe(&hx->bch)) {
|
||||
hscx_fill_fifo(hx);
|
||||
test_and_clear_bit(FLG_TX_EMPTY, &hx->bch.Flags);
|
||||
|
|
|
@ -690,8 +690,7 @@ send_next(struct isar_ch *ch)
|
|||
}
|
||||
}
|
||||
}
|
||||
if (ch->bch.tx_skb)
|
||||
dev_kfree_skb(ch->bch.tx_skb);
|
||||
dev_kfree_skb(ch->bch.tx_skb);
|
||||
if (get_next_bframe(&ch->bch)) {
|
||||
isar_fill_fifo(ch);
|
||||
test_and_clear_bit(FLG_TX_EMPTY, &ch->bch.Flags);
|
||||
|
|
|
@ -605,8 +605,7 @@ bc_next_frame(struct tiger_ch *bc)
|
|||
if (bc->bch.tx_skb && bc->bch.tx_idx < bc->bch.tx_skb->len) {
|
||||
fill_dma(bc);
|
||||
} else {
|
||||
if (bc->bch.tx_skb)
|
||||
dev_kfree_skb(bc->bch.tx_skb);
|
||||
dev_kfree_skb(bc->bch.tx_skb);
|
||||
if (get_next_bframe(&bc->bch)) {
|
||||
fill_dma(bc);
|
||||
test_and_clear_bit(FLG_TX_EMPTY, &bc->bch.Flags);
|
||||
|
|
|
@ -356,8 +356,7 @@ handle_rxD(struct w6692_hw *card) {
|
|||
card->dch.err_rx++;
|
||||
#endif
|
||||
}
|
||||
if (card->dch.rx_skb)
|
||||
dev_kfree_skb(card->dch.rx_skb);
|
||||
dev_kfree_skb(card->dch.rx_skb);
|
||||
card->dch.rx_skb = NULL;
|
||||
WriteW6692(card, W_D_CMDR, W_D_CMDR_RACK | W_D_CMDR_RRST);
|
||||
} else {
|
||||
|
@ -376,8 +375,7 @@ handle_txD(struct w6692_hw *card) {
|
|||
if (card->dch.tx_skb && card->dch.tx_idx < card->dch.tx_skb->len) {
|
||||
W6692_fill_Dfifo(card);
|
||||
} else {
|
||||
if (card->dch.tx_skb)
|
||||
dev_kfree_skb(card->dch.tx_skb);
|
||||
dev_kfree_skb(card->dch.tx_skb);
|
||||
if (get_next_dframe(&card->dch))
|
||||
W6692_fill_Dfifo(card);
|
||||
}
|
||||
|
@ -636,8 +634,7 @@ send_next(struct w6692_ch *wch)
|
|||
if (wch->bch.tx_skb && wch->bch.tx_idx < wch->bch.tx_skb->len) {
|
||||
W6692_fill_Bfifo(wch);
|
||||
} else {
|
||||
if (wch->bch.tx_skb)
|
||||
dev_kfree_skb(wch->bch.tx_skb);
|
||||
dev_kfree_skb(wch->bch.tx_skb);
|
||||
if (get_next_bframe(&wch->bch)) {
|
||||
W6692_fill_Bfifo(wch);
|
||||
test_and_clear_bit(FLG_TX_EMPTY, &wch->bch.Flags);
|
||||
|
|
|
@ -1254,8 +1254,7 @@ release_card(struct l1oip *hc)
|
|||
mISDN_freebchannel(hc->chan[ch].bch);
|
||||
kfree(hc->chan[ch].bch);
|
||||
#ifdef REORDER_DEBUG
|
||||
if (hc->chan[ch].disorder_skb)
|
||||
dev_kfree_skb(hc->chan[ch].disorder_skb);
|
||||
dev_kfree_skb(hc->chan[ch].disorder_skb);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
|
|
@ -900,8 +900,7 @@ l2_disconnect(struct FsmInst *fi, int event, void *arg)
|
|||
send_uframe(l2, NULL, DISC | 0x10, CMD);
|
||||
mISDN_FsmDelTimer(&l2->t203, 1);
|
||||
restart_t200(l2, 2);
|
||||
if (skb)
|
||||
dev_kfree_skb(skb);
|
||||
dev_kfree_skb(skb);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -1722,8 +1721,7 @@ l2_set_own_busy(struct FsmInst *fi, int event, void *arg)
|
|||
enquiry_cr(l2, RNR, RSP, 0);
|
||||
test_and_clear_bit(FLG_ACK_PEND, &l2->flag);
|
||||
}
|
||||
if (skb)
|
||||
dev_kfree_skb(skb);
|
||||
dev_kfree_skb(skb);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -1736,8 +1734,7 @@ l2_clear_own_busy(struct FsmInst *fi, int event, void *arg)
|
|||
enquiry_cr(l2, RR, RSP, 0);
|
||||
test_and_clear_bit(FLG_ACK_PEND, &l2->flag);
|
||||
}
|
||||
if (skb)
|
||||
dev_kfree_skb(skb);
|
||||
dev_kfree_skb(skb);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
@ -75,8 +75,7 @@ send_socklist(struct mISDN_sock_list *sl, struct sk_buff *skb)
|
|||
cskb = NULL;
|
||||
}
|
||||
read_unlock(&sl->lock);
|
||||
if (cskb)
|
||||
dev_kfree_skb(cskb);
|
||||
dev_kfree_skb(cskb);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -134,8 +133,7 @@ send_layer2(struct mISDNstack *st, struct sk_buff *skb)
|
|||
}
|
||||
out:
|
||||
mutex_unlock(&st->lmutex);
|
||||
if (skb)
|
||||
dev_kfree_skb(skb);
|
||||
dev_kfree_skb(skb);
|
||||
}
|
||||
|
||||
static inline int
|
||||
|
|
|
@ -1328,10 +1328,8 @@ mgr_bcast(struct mISDNchannel *ch, struct sk_buff *skb)
|
|||
}
|
||||
out:
|
||||
read_unlock_irqrestore(&mgr->lock, flags);
|
||||
if (cskb)
|
||||
dev_kfree_skb(cskb);
|
||||
if (skb)
|
||||
dev_kfree_skb(skb);
|
||||
dev_kfree_skb(cskb);
|
||||
dev_kfree_skb(skb);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -44,7 +44,7 @@ static void rx(struct net_device *dev, int bufnum,
|
|||
{
|
||||
struct arcnet_local *lp = netdev_priv(dev);
|
||||
struct sk_buff *skb;
|
||||
struct archdr *pkt = pkthdr;
|
||||
struct archdr *pkt;
|
||||
char *pktbuf, *pkthdrbuf;
|
||||
int ofs;
|
||||
|
||||
|
|
|
@ -55,11 +55,6 @@ void bond_debug_register(struct bonding *bond)
|
|||
bond->debug_dir =
|
||||
debugfs_create_dir(bond->dev->name, bonding_debug_root);
|
||||
|
||||
if (!bond->debug_dir) {
|
||||
netdev_warn(bond->dev, "failed to register to debugfs\n");
|
||||
return;
|
||||
}
|
||||
|
||||
debugfs_create_file("rlb_hash_table", 0400, bond->debug_dir,
|
||||
bond, &bond_debug_rlb_hash_fops);
|
||||
}
|
||||
|
|
|
@ -94,26 +94,20 @@ static inline void update_tty_status(struct ser_device *ser)
|
|||
}
|
||||
static inline void debugfs_init(struct ser_device *ser, struct tty_struct *tty)
|
||||
{
|
||||
ser->debugfs_tty_dir =
|
||||
debugfs_create_dir(tty->name, debugfsdir);
|
||||
if (!IS_ERR(ser->debugfs_tty_dir)) {
|
||||
debugfs_create_blob("last_tx_msg", 0400,
|
||||
ser->debugfs_tty_dir,
|
||||
&ser->tx_blob);
|
||||
ser->debugfs_tty_dir = debugfs_create_dir(tty->name, debugfsdir);
|
||||
|
||||
debugfs_create_blob("last_rx_msg", 0400,
|
||||
ser->debugfs_tty_dir,
|
||||
&ser->rx_blob);
|
||||
debugfs_create_blob("last_tx_msg", 0400, ser->debugfs_tty_dir,
|
||||
&ser->tx_blob);
|
||||
|
||||
debugfs_create_x32("ser_state", 0400,
|
||||
ser->debugfs_tty_dir,
|
||||
(u32 *)&ser->state);
|
||||
debugfs_create_blob("last_rx_msg", 0400, ser->debugfs_tty_dir,
|
||||
&ser->rx_blob);
|
||||
|
||||
debugfs_create_x8("tty_status", 0400,
|
||||
ser->debugfs_tty_dir,
|
||||
&ser->tty_status);
|
||||
debugfs_create_x32("ser_state", 0400, ser->debugfs_tty_dir,
|
||||
(u32 *)&ser->state);
|
||||
|
||||
debugfs_create_x8("tty_status", 0400, ser->debugfs_tty_dir,
|
||||
&ser->tty_status);
|
||||
|
||||
}
|
||||
ser->tx_blob.data = ser->tx_data;
|
||||
ser->tx_blob.size = 0;
|
||||
ser->rx_blob.data = ser->rx_data;
|
||||
|
|
|
@ -623,11 +623,7 @@ static void cfv_netdev_setup(struct net_device *netdev)
|
|||
/* Create debugfs counters for the device */
|
||||
static inline void debugfs_init(struct cfv_info *cfv)
|
||||
{
|
||||
cfv->debugfs =
|
||||
debugfs_create_dir(netdev_name(cfv->ndev), NULL);
|
||||
|
||||
if (IS_ERR(cfv->debugfs))
|
||||
return;
|
||||
cfv->debugfs = debugfs_create_dir(netdev_name(cfv->ndev), NULL);
|
||||
|
||||
debugfs_create_u32("rx-napi-complete", 0400, cfv->debugfs,
|
||||
&cfv->stats.rx_napi_complete);
|
||||
|
|
|
@ -120,6 +120,19 @@ config CAN_JANZ_ICAN3
|
|||
This driver can also be built as a module. If so, the module will be
|
||||
called janz-ican3.ko.
|
||||
|
||||
config CAN_KVASER_PCIEFD
|
||||
depends on PCI
|
||||
tristate "Kvaser PCIe FD cards"
|
||||
help
|
||||
This is a driver for the Kvaser PCI Express CAN FD family.
|
||||
|
||||
Supported devices:
|
||||
Kvaser PCIEcan 4xHS
|
||||
Kvaser PCIEcan 2xHS v2
|
||||
Kvaser PCIEcan HS v2
|
||||
Kvaser Mini PCI Express HS v2
|
||||
Kvaser Mini PCI Express 2xHS v2
|
||||
|
||||
config CAN_SUN4I
|
||||
tristate "Allwinner A10 CAN controller"
|
||||
depends on MACH_SUN4I || MACH_SUN7I || COMPILE_TEST
|
||||
|
|
|
@ -25,6 +25,7 @@ obj-$(CONFIG_CAN_FLEXCAN) += flexcan.o
|
|||
obj-$(CONFIG_CAN_GRCAN) += grcan.o
|
||||
obj-$(CONFIG_CAN_IFI_CANFD) += ifi_canfd/
|
||||
obj-$(CONFIG_CAN_JANZ_ICAN3) += janz-ican3.o
|
||||
obj-$(CONFIG_CAN_KVASER_PCIEFD) += kvaser_pciefd.o
|
||||
obj-$(CONFIG_CAN_MSCAN) += mscan/
|
||||
obj-$(CONFIG_CAN_M_CAN) += m_can/
|
||||
obj-$(CONFIG_CAN_PEAK_PCIEFD) += peak_canfd/
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (C) 2005 Marc Kleine-Budde, Pengutronix
|
||||
/* Copyright (C) 2005 Marc Kleine-Budde, Pengutronix
|
||||
* Copyright (C) 2006 Andrey Volkov, Varma Electronics
|
||||
* Copyright (C) 2008-2009 Wolfgang Grandegger <wg@grandegger.com>
|
||||
*/
|
||||
|
@ -12,6 +11,7 @@
|
|||
#include <linux/if_arp.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/can.h>
|
||||
#include <linux/can/can-ml.h>
|
||||
#include <linux/can/dev.h>
|
||||
#include <linux/can/skb.h>
|
||||
#include <linux/can/netlink.h>
|
||||
|
@ -62,8 +62,7 @@ EXPORT_SYMBOL_GPL(can_len2dlc);
|
|||
#define CAN_CALC_MAX_ERROR 50 /* in one-tenth of a percent */
|
||||
#define CAN_CALC_SYNC_SEG 1
|
||||
|
||||
/*
|
||||
* Bit-timing calculation derived from:
|
||||
/* Bit-timing calculation derived from:
|
||||
*
|
||||
* Code based on LinCAN sources and H8S2638 project
|
||||
* Copyright 2004-2006 Pavel Pisa - DCE FELK CVUT cz
|
||||
|
@ -75,10 +74,11 @@ EXPORT_SYMBOL_GPL(can_len2dlc);
|
|||
* registers of the CAN controller. You can find more information
|
||||
* in the header file linux/can/netlink.h.
|
||||
*/
|
||||
static int can_update_sample_point(const struct can_bittiming_const *btc,
|
||||
unsigned int sample_point_nominal, unsigned int tseg,
|
||||
unsigned int *tseg1_ptr, unsigned int *tseg2_ptr,
|
||||
unsigned int *sample_point_error_ptr)
|
||||
static int
|
||||
can_update_sample_point(const struct can_bittiming_const *btc,
|
||||
unsigned int sample_point_nominal, unsigned int tseg,
|
||||
unsigned int *tseg1_ptr, unsigned int *tseg2_ptr,
|
||||
unsigned int *sample_point_error_ptr)
|
||||
{
|
||||
unsigned int sample_point_error, best_sample_point_error = UINT_MAX;
|
||||
unsigned int sample_point, best_sample_point = 0;
|
||||
|
@ -86,7 +86,9 @@ static int can_update_sample_point(const struct can_bittiming_const *btc,
|
|||
int i;
|
||||
|
||||
for (i = 0; i <= 1; i++) {
|
||||
tseg2 = tseg + CAN_CALC_SYNC_SEG - (sample_point_nominal * (tseg + CAN_CALC_SYNC_SEG)) / 1000 - i;
|
||||
tseg2 = tseg + CAN_CALC_SYNC_SEG -
|
||||
(sample_point_nominal * (tseg + CAN_CALC_SYNC_SEG)) /
|
||||
1000 - i;
|
||||
tseg2 = clamp(tseg2, btc->tseg2_min, btc->tseg2_max);
|
||||
tseg1 = tseg - tseg2;
|
||||
if (tseg1 > btc->tseg1_max) {
|
||||
|
@ -94,10 +96,12 @@ static int can_update_sample_point(const struct can_bittiming_const *btc,
|
|||
tseg2 = tseg - tseg1;
|
||||
}
|
||||
|
||||
sample_point = 1000 * (tseg + CAN_CALC_SYNC_SEG - tseg2) / (tseg + CAN_CALC_SYNC_SEG);
|
||||
sample_point = 1000 * (tseg + CAN_CALC_SYNC_SEG - tseg2) /
|
||||
(tseg + CAN_CALC_SYNC_SEG);
|
||||
sample_point_error = abs(sample_point_nominal - sample_point);
|
||||
|
||||
if ((sample_point <= sample_point_nominal) && (sample_point_error < best_sample_point_error)) {
|
||||
if (sample_point <= sample_point_nominal &&
|
||||
sample_point_error < best_sample_point_error) {
|
||||
best_sample_point = sample_point;
|
||||
best_sample_point_error = sample_point_error;
|
||||
*tseg1_ptr = tseg1;
|
||||
|
@ -148,7 +152,7 @@ static int can_calc_bittiming(struct net_device *dev, struct can_bittiming *bt,
|
|||
|
||||
/* choose brp step which is possible in system */
|
||||
brp = (brp / btc->brp_inc) * btc->brp_inc;
|
||||
if ((brp < btc->brp_min) || (brp > btc->brp_max))
|
||||
if (brp < btc->brp_min || brp > btc->brp_max)
|
||||
continue;
|
||||
|
||||
bitrate = priv->clock.freq / (brp * tsegall);
|
||||
|
@ -162,7 +166,8 @@ static int can_calc_bittiming(struct net_device *dev, struct can_bittiming *bt,
|
|||
if (bitrate_error < best_bitrate_error)
|
||||
best_sample_point_error = UINT_MAX;
|
||||
|
||||
can_update_sample_point(btc, sample_point_nominal, tseg / 2, &tseg1, &tseg2, &sample_point_error);
|
||||
can_update_sample_point(btc, sample_point_nominal, tseg / 2,
|
||||
&tseg1, &tseg2, &sample_point_error);
|
||||
if (sample_point_error > best_sample_point_error)
|
||||
continue;
|
||||
|
||||
|
@ -191,8 +196,9 @@ static int can_calc_bittiming(struct net_device *dev, struct can_bittiming *bt,
|
|||
}
|
||||
|
||||
/* real sample point */
|
||||
bt->sample_point = can_update_sample_point(btc, sample_point_nominal, best_tseg,
|
||||
&tseg1, &tseg2, NULL);
|
||||
bt->sample_point = can_update_sample_point(btc, sample_point_nominal,
|
||||
best_tseg, &tseg1, &tseg2,
|
||||
NULL);
|
||||
|
||||
v64 = (u64)best_brp * 1000 * 1000 * 1000;
|
||||
do_div(v64, priv->clock.freq);
|
||||
|
@ -216,7 +222,8 @@ static int can_calc_bittiming(struct net_device *dev, struct can_bittiming *bt,
|
|||
bt->brp = best_brp;
|
||||
|
||||
/* real bitrate */
|
||||
bt->bitrate = priv->clock.freq / (bt->brp * (CAN_CALC_SYNC_SEG + tseg1 + tseg2));
|
||||
bt->bitrate = priv->clock.freq /
|
||||
(bt->brp * (CAN_CALC_SYNC_SEG + tseg1 + tseg2));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -229,8 +236,7 @@ static int can_calc_bittiming(struct net_device *dev, struct can_bittiming *bt,
|
|||
}
|
||||
#endif /* CONFIG_CAN_CALC_BITTIMING */
|
||||
|
||||
/*
|
||||
* Checks the validity of the specified bit-timing parameters prop_seg,
|
||||
/* Checks the validity of the specified bit-timing parameters prop_seg,
|
||||
* phase_seg1, phase_seg2 and sjw and tries to determine the bitrate
|
||||
* prescaler value brp. You can find more information in the header
|
||||
* file linux/can/netlink.h.
|
||||
|
@ -270,9 +276,10 @@ static int can_fixup_bittiming(struct net_device *dev, struct can_bittiming *bt,
|
|||
}
|
||||
|
||||
/* Checks the validity of predefined bitrate settings */
|
||||
static int can_validate_bitrate(struct net_device *dev, struct can_bittiming *bt,
|
||||
const u32 *bitrate_const,
|
||||
const unsigned int bitrate_const_cnt)
|
||||
static int
|
||||
can_validate_bitrate(struct net_device *dev, struct can_bittiming *bt,
|
||||
const u32 *bitrate_const,
|
||||
const unsigned int bitrate_const_cnt)
|
||||
{
|
||||
struct can_priv *priv = netdev_priv(dev);
|
||||
unsigned int i;
|
||||
|
@ -295,8 +302,7 @@ static int can_get_bittiming(struct net_device *dev, struct can_bittiming *bt,
|
|||
{
|
||||
int err;
|
||||
|
||||
/*
|
||||
* Depending on the given can_bittiming parameter structure the CAN
|
||||
/* Depending on the given can_bittiming parameter structure the CAN
|
||||
* timing parameters are calculated based on the provided bitrate OR
|
||||
* alternatively the CAN timing parameters (tq, prop_seg, etc.) are
|
||||
* provided directly which are then checked and fixed up.
|
||||
|
@ -397,8 +403,7 @@ void can_change_state(struct net_device *dev, struct can_frame *cf,
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(can_change_state);
|
||||
|
||||
/*
|
||||
* Local echo of CAN messages
|
||||
/* Local echo of CAN messages
|
||||
*
|
||||
* CAN network devices *should* support a local echo functionality
|
||||
* (see Documentation/networking/can.rst). To test the handling of CAN
|
||||
|
@ -423,8 +428,7 @@ static void can_flush_echo_skb(struct net_device *dev)
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Put the skb on the stack to be looped backed locally lateron
|
||||
/* Put the skb on the stack to be looped backed locally lateron
|
||||
*
|
||||
* The function is typically called in the start_xmit function
|
||||
* of the device driver. The driver must protect access to
|
||||
|
@ -446,7 +450,6 @@ void can_put_echo_skb(struct sk_buff *skb, struct net_device *dev,
|
|||
}
|
||||
|
||||
if (!priv->echo_skb[idx]) {
|
||||
|
||||
skb = can_create_echo_skb(skb);
|
||||
if (!skb)
|
||||
return;
|
||||
|
@ -466,7 +469,8 @@ void can_put_echo_skb(struct sk_buff *skb, struct net_device *dev,
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(can_put_echo_skb);
|
||||
|
||||
struct sk_buff *__can_get_echo_skb(struct net_device *dev, unsigned int idx, u8 *len_ptr)
|
||||
struct sk_buff *
|
||||
__can_get_echo_skb(struct net_device *dev, unsigned int idx, u8 *len_ptr)
|
||||
{
|
||||
struct can_priv *priv = netdev_priv(dev);
|
||||
|
||||
|
@ -493,8 +497,7 @@ struct sk_buff *__can_get_echo_skb(struct net_device *dev, unsigned int idx, u8
|
|||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the skb from the stack and loop it back locally
|
||||
/* Get the skb from the stack and loop it back locally
|
||||
*
|
||||
* The function is typically called when the TX done interrupt
|
||||
* is handled in the device driver. The driver must protect
|
||||
|
@ -515,11 +518,10 @@ unsigned int can_get_echo_skb(struct net_device *dev, unsigned int idx)
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(can_get_echo_skb);
|
||||
|
||||
/*
|
||||
* Remove the skb from the stack and free it.
|
||||
*
|
||||
* The function is typically called when TX failed.
|
||||
*/
|
||||
/* Remove the skb from the stack and free it.
|
||||
*
|
||||
* The function is typically called when TX failed.
|
||||
*/
|
||||
void can_free_echo_skb(struct net_device *dev, unsigned int idx)
|
||||
{
|
||||
struct can_priv *priv = netdev_priv(dev);
|
||||
|
@ -533,9 +535,7 @@ void can_free_echo_skb(struct net_device *dev, unsigned int idx)
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(can_free_echo_skb);
|
||||
|
||||
/*
|
||||
* CAN device restart for bus-off recovery
|
||||
*/
|
||||
/* CAN device restart for bus-off recovery */
|
||||
static void can_restart(struct net_device *dev)
|
||||
{
|
||||
struct can_priv *priv = netdev_priv(dev);
|
||||
|
@ -546,15 +546,14 @@ static void can_restart(struct net_device *dev)
|
|||
|
||||
BUG_ON(netif_carrier_ok(dev));
|
||||
|
||||
/*
|
||||
* No synchronization needed because the device is bus-off and
|
||||
/* No synchronization needed because the device is bus-off and
|
||||
* no messages can come in or go out.
|
||||
*/
|
||||
can_flush_echo_skb(dev);
|
||||
|
||||
/* send restart message upstream */
|
||||
skb = alloc_can_err_skb(dev, &cf);
|
||||
if (skb == NULL) {
|
||||
if (!skb) {
|
||||
err = -ENOMEM;
|
||||
goto restart;
|
||||
}
|
||||
|
@ -580,7 +579,8 @@ restart:
|
|||
static void can_restart_work(struct work_struct *work)
|
||||
{
|
||||
struct delayed_work *dwork = to_delayed_work(work);
|
||||
struct can_priv *priv = container_of(dwork, struct can_priv, restart_work);
|
||||
struct can_priv *priv = container_of(dwork, struct can_priv,
|
||||
restart_work);
|
||||
|
||||
can_restart(priv->dev);
|
||||
}
|
||||
|
@ -589,8 +589,7 @@ int can_restart_now(struct net_device *dev)
|
|||
{
|
||||
struct can_priv *priv = netdev_priv(dev);
|
||||
|
||||
/*
|
||||
* A manual restart is only permitted if automatic restart is
|
||||
/* A manual restart is only permitted if automatic restart is
|
||||
* disabled and the device is in the bus-off state
|
||||
*/
|
||||
if (priv->restart_ms)
|
||||
|
@ -604,8 +603,7 @@ int can_restart_now(struct net_device *dev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* CAN bus-off
|
||||
/* CAN bus-off
|
||||
*
|
||||
* This functions should be called when the device goes bus-off to
|
||||
* tell the netif layer that no more packets can be sent or received.
|
||||
|
@ -708,9 +706,7 @@ struct sk_buff *alloc_can_err_skb(struct net_device *dev, struct can_frame **cf)
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(alloc_can_err_skb);
|
||||
|
||||
/*
|
||||
* Allocate and setup space for the CAN network device
|
||||
*/
|
||||
/* Allocate and setup space for the CAN network device */
|
||||
struct net_device *alloc_candev_mqs(int sizeof_priv, unsigned int echo_skb_max,
|
||||
unsigned int txqs, unsigned int rxqs)
|
||||
{
|
||||
|
@ -718,11 +714,24 @@ struct net_device *alloc_candev_mqs(int sizeof_priv, unsigned int echo_skb_max,
|
|||
struct can_priv *priv;
|
||||
int size;
|
||||
|
||||
/* We put the driver's priv, the CAN mid layer priv and the
|
||||
* echo skb into the netdevice's priv. The memory layout for
|
||||
* the netdev_priv is like this:
|
||||
*
|
||||
* +-------------------------+
|
||||
* | driver's priv |
|
||||
* +-------------------------+
|
||||
* | struct can_ml_priv |
|
||||
* +-------------------------+
|
||||
* | array of struct sk_buff |
|
||||
* +-------------------------+
|
||||
*/
|
||||
|
||||
size = ALIGN(sizeof_priv, NETDEV_ALIGN) + sizeof(struct can_ml_priv);
|
||||
|
||||
if (echo_skb_max)
|
||||
size = ALIGN(sizeof_priv, sizeof(struct sk_buff *)) +
|
||||
size = ALIGN(size, sizeof(struct sk_buff *)) +
|
||||
echo_skb_max * sizeof(struct sk_buff *);
|
||||
else
|
||||
size = sizeof_priv;
|
||||
|
||||
dev = alloc_netdev_mqs(size, "can%d", NET_NAME_UNKNOWN, can_setup,
|
||||
txqs, rxqs);
|
||||
|
@ -732,10 +741,12 @@ struct net_device *alloc_candev_mqs(int sizeof_priv, unsigned int echo_skb_max,
|
|||
priv = netdev_priv(dev);
|
||||
priv->dev = dev;
|
||||
|
||||
dev->ml_priv = (void *)priv + ALIGN(sizeof_priv, NETDEV_ALIGN);
|
||||
|
||||
if (echo_skb_max) {
|
||||
priv->echo_skb_max = echo_skb_max;
|
||||
priv->echo_skb = (void *)priv +
|
||||
ALIGN(sizeof_priv, sizeof(struct sk_buff *));
|
||||
(size - echo_skb_max * sizeof(struct sk_buff *));
|
||||
}
|
||||
|
||||
priv->state = CAN_STATE_STOPPED;
|
||||
|
@ -746,18 +757,14 @@ struct net_device *alloc_candev_mqs(int sizeof_priv, unsigned int echo_skb_max,
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(alloc_candev_mqs);
|
||||
|
||||
/*
|
||||
* Free space of the CAN network device
|
||||
*/
|
||||
/* Free space of the CAN network device */
|
||||
void free_candev(struct net_device *dev)
|
||||
{
|
||||
free_netdev(dev);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(free_candev);
|
||||
|
||||
/*
|
||||
* changing MTU and control mode for CAN/CANFD devices
|
||||
*/
|
||||
/* changing MTU and control mode for CAN/CANFD devices */
|
||||
int can_change_mtu(struct net_device *dev, int new_mtu)
|
||||
{
|
||||
struct can_priv *priv = netdev_priv(dev);
|
||||
|
@ -794,8 +801,7 @@ int can_change_mtu(struct net_device *dev, int new_mtu)
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(can_change_mtu);
|
||||
|
||||
/*
|
||||
* Common open function when the device gets opened.
|
||||
/* Common open function when the device gets opened.
|
||||
*
|
||||
* This function should be called in the open function of the device
|
||||
* driver.
|
||||
|
@ -812,7 +818,7 @@ int open_candev(struct net_device *dev)
|
|||
/* For CAN FD the data bitrate has to be >= the arbitration bitrate */
|
||||
if ((priv->ctrlmode & CAN_CTRLMODE_FD) &&
|
||||
(!priv->data_bittiming.bitrate ||
|
||||
(priv->data_bittiming.bitrate < priv->bittiming.bitrate))) {
|
||||
priv->data_bittiming.bitrate < priv->bittiming.bitrate)) {
|
||||
netdev_err(dev, "incorrect/missing data bit-timing\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
@ -848,8 +854,7 @@ void of_can_transceiver(struct net_device *dev)
|
|||
EXPORT_SYMBOL_GPL(of_can_transceiver);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Common close function for cleanup before the device gets closed.
|
||||
/* Common close function for cleanup before the device gets closed.
|
||||
*
|
||||
* This function should be called in the close function of the device
|
||||
* driver.
|
||||
|
@ -863,9 +868,7 @@ void close_candev(struct net_device *dev)
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(close_candev);
|
||||
|
||||
/*
|
||||
* CAN netlink interface
|
||||
*/
|
||||
/* CAN netlink interface */
|
||||
static const struct nla_policy can_policy[IFLA_CAN_MAX + 1] = {
|
||||
[IFLA_CAN_STATE] = { .type = NLA_U32 },
|
||||
[IFLA_CAN_CTRLMODE] = { .len = sizeof(struct can_ctrlmode) },
|
||||
|
@ -1209,7 +1212,6 @@ static int can_newlink(struct net *src_net, struct net_device *dev,
|
|||
|
||||
static void can_dellink(struct net_device *dev, struct list_head *head)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static struct rtnl_link_ops can_link_ops __read_mostly = {
|
||||
|
@ -1227,9 +1229,7 @@ static struct rtnl_link_ops can_link_ops __read_mostly = {
|
|||
.fill_xstats = can_fill_xstats,
|
||||
};
|
||||
|
||||
/*
|
||||
* Register the CAN network device
|
||||
*/
|
||||
/* Register the CAN network device */
|
||||
int register_candev(struct net_device *dev)
|
||||
{
|
||||
struct can_priv *priv = netdev_priv(dev);
|
||||
|
@ -1255,22 +1255,19 @@ int register_candev(struct net_device *dev)
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(register_candev);
|
||||
|
||||
/*
|
||||
* Unregister the CAN network device
|
||||
*/
|
||||
/* Unregister the CAN network device */
|
||||
void unregister_candev(struct net_device *dev)
|
||||
{
|
||||
unregister_netdev(dev);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(unregister_candev);
|
||||
|
||||
/*
|
||||
* Test if a network device is a candev based device
|
||||
/* Test if a network device is a candev based device
|
||||
* and return the can_priv* if so.
|
||||
*/
|
||||
struct can_priv *safe_candev_priv(struct net_device *dev)
|
||||
{
|
||||
if ((dev->type != ARPHRD_CAN) || (dev->rtnl_link_ops != &can_link_ops))
|
||||
if (dev->type != ARPHRD_CAN || dev->rtnl_link_ops != &can_link_ops)
|
||||
return NULL;
|
||||
|
||||
return netdev_priv(dev);
|
||||
|
@ -1285,7 +1282,7 @@ static __init int can_dev_init(void)
|
|||
|
||||
err = rtnl_link_register(&can_link_ops);
|
||||
if (!err)
|
||||
printk(KERN_INFO MOD_DESC "\n");
|
||||
pr_info(MOD_DESC "\n");
|
||||
|
||||
return err;
|
||||
}
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <linux/regmap.h>
|
||||
|
||||
|
@ -266,6 +267,7 @@ struct flexcan_stop_mode {
|
|||
struct flexcan_priv {
|
||||
struct can_priv can;
|
||||
struct can_rx_offload offload;
|
||||
struct device *dev;
|
||||
|
||||
struct flexcan_regs __iomem *regs;
|
||||
struct flexcan_mb __iomem *tx_mb;
|
||||
|
@ -273,6 +275,8 @@ struct flexcan_priv {
|
|||
u8 tx_mb_idx;
|
||||
u8 mb_count;
|
||||
u8 mb_size;
|
||||
u8 clk_src; /* clock source of CAN Protocol Engine */
|
||||
|
||||
u32 reg_ctrl_default;
|
||||
u32 reg_imask1_default;
|
||||
u32 reg_imask2_default;
|
||||
|
@ -462,6 +466,27 @@ static inline void flexcan_error_irq_disable(const struct flexcan_priv *priv)
|
|||
priv->write(reg_ctrl, ®s->ctrl);
|
||||
}
|
||||
|
||||
static int flexcan_clks_enable(const struct flexcan_priv *priv)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = clk_prepare_enable(priv->clk_ipg);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = clk_prepare_enable(priv->clk_per);
|
||||
if (err)
|
||||
clk_disable_unprepare(priv->clk_ipg);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static void flexcan_clks_disable(const struct flexcan_priv *priv)
|
||||
{
|
||||
clk_disable_unprepare(priv->clk_per);
|
||||
clk_disable_unprepare(priv->clk_ipg);
|
||||
}
|
||||
|
||||
static inline int flexcan_transceiver_enable(const struct flexcan_priv *priv)
|
||||
{
|
||||
if (!priv->reg_xceiver)
|
||||
|
@ -588,19 +613,13 @@ static int flexcan_get_berr_counter(const struct net_device *dev,
|
|||
const struct flexcan_priv *priv = netdev_priv(dev);
|
||||
int err;
|
||||
|
||||
err = clk_prepare_enable(priv->clk_ipg);
|
||||
if (err)
|
||||
err = pm_runtime_get_sync(priv->dev);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
err = clk_prepare_enable(priv->clk_per);
|
||||
if (err)
|
||||
goto out_disable_ipg;
|
||||
|
||||
err = __flexcan_get_berr_counter(dev, bec);
|
||||
|
||||
clk_disable_unprepare(priv->clk_per);
|
||||
out_disable_ipg:
|
||||
clk_disable_unprepare(priv->clk_ipg);
|
||||
pm_runtime_put(priv->dev);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
@ -1233,17 +1252,13 @@ static int flexcan_open(struct net_device *dev)
|
|||
struct flexcan_priv *priv = netdev_priv(dev);
|
||||
int err;
|
||||
|
||||
err = clk_prepare_enable(priv->clk_ipg);
|
||||
if (err)
|
||||
err = pm_runtime_get_sync(priv->dev);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
err = clk_prepare_enable(priv->clk_per);
|
||||
if (err)
|
||||
goto out_disable_ipg;
|
||||
|
||||
err = open_candev(dev);
|
||||
if (err)
|
||||
goto out_disable_per;
|
||||
goto out_runtime_put;
|
||||
|
||||
err = request_irq(dev->irq, flexcan_irq, IRQF_SHARED, dev->name, dev);
|
||||
if (err)
|
||||
|
@ -1306,10 +1321,8 @@ static int flexcan_open(struct net_device *dev)
|
|||
free_irq(dev->irq, dev);
|
||||
out_close:
|
||||
close_candev(dev);
|
||||
out_disable_per:
|
||||
clk_disable_unprepare(priv->clk_per);
|
||||
out_disable_ipg:
|
||||
clk_disable_unprepare(priv->clk_ipg);
|
||||
out_runtime_put:
|
||||
pm_runtime_put(priv->dev);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
@ -1324,10 +1337,9 @@ static int flexcan_close(struct net_device *dev)
|
|||
|
||||
can_rx_offload_del(&priv->offload);
|
||||
free_irq(dev->irq, dev);
|
||||
clk_disable_unprepare(priv->clk_per);
|
||||
clk_disable_unprepare(priv->clk_ipg);
|
||||
|
||||
close_candev(dev);
|
||||
pm_runtime_put(priv->dev);
|
||||
|
||||
can_led_event(dev, CAN_LED_EVENT_STOP);
|
||||
|
||||
|
@ -1367,20 +1379,20 @@ static int register_flexcandev(struct net_device *dev)
|
|||
struct flexcan_regs __iomem *regs = priv->regs;
|
||||
u32 reg, err;
|
||||
|
||||
err = clk_prepare_enable(priv->clk_ipg);
|
||||
err = flexcan_clks_enable(priv);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = clk_prepare_enable(priv->clk_per);
|
||||
if (err)
|
||||
goto out_disable_ipg;
|
||||
|
||||
/* select "bus clock", chip must be disabled */
|
||||
err = flexcan_chip_disable(priv);
|
||||
if (err)
|
||||
goto out_disable_per;
|
||||
goto out_clks_disable;
|
||||
|
||||
reg = priv->read(®s->ctrl);
|
||||
reg |= FLEXCAN_CTRL_CLK_SRC;
|
||||
if (priv->clk_src)
|
||||
reg |= FLEXCAN_CTRL_CLK_SRC;
|
||||
else
|
||||
reg &= ~FLEXCAN_CTRL_CLK_SRC;
|
||||
priv->write(reg, ®s->ctrl);
|
||||
|
||||
err = flexcan_chip_enable(priv);
|
||||
|
@ -1406,15 +1418,21 @@ static int register_flexcandev(struct net_device *dev)
|
|||
}
|
||||
|
||||
err = register_candev(dev);
|
||||
if (err)
|
||||
goto out_chip_disable;
|
||||
|
||||
/* Disable core and let pm_runtime_put() disable the clocks.
|
||||
* If CONFIG_PM is not enabled, the clocks will stay powered.
|
||||
*/
|
||||
flexcan_chip_disable(priv);
|
||||
pm_runtime_put(priv->dev);
|
||||
|
||||
return 0;
|
||||
|
||||
/* disable core and turn off clocks */
|
||||
out_chip_disable:
|
||||
flexcan_chip_disable(priv);
|
||||
out_disable_per:
|
||||
clk_disable_unprepare(priv->clk_per);
|
||||
out_disable_ipg:
|
||||
clk_disable_unprepare(priv->clk_ipg);
|
||||
|
||||
out_clks_disable:
|
||||
flexcan_clks_disable(priv);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
@ -1473,6 +1491,11 @@ static int flexcan_setup_stop_mode(struct platform_device *pdev)
|
|||
|
||||
device_set_wakeup_capable(&pdev->dev, true);
|
||||
|
||||
if (of_property_read_bool(np, "wakeup-source"))
|
||||
device_set_wakeup_enable(&pdev->dev, true);
|
||||
|
||||
return 0;
|
||||
|
||||
out_put_node:
|
||||
of_node_put(gpr_np);
|
||||
return ret;
|
||||
|
@ -1508,6 +1531,7 @@ static int flexcan_probe(struct platform_device *pdev)
|
|||
struct clk *clk_ipg = NULL, *clk_per = NULL;
|
||||
struct flexcan_regs __iomem *regs;
|
||||
int err, irq;
|
||||
u8 clk_src = 1;
|
||||
u32 clock_freq = 0;
|
||||
|
||||
reg_xceiver = devm_regulator_get(&pdev->dev, "xceiver");
|
||||
|
@ -1516,9 +1540,12 @@ static int flexcan_probe(struct platform_device *pdev)
|
|||
else if (IS_ERR(reg_xceiver))
|
||||
reg_xceiver = NULL;
|
||||
|
||||
if (pdev->dev.of_node)
|
||||
if (pdev->dev.of_node) {
|
||||
of_property_read_u32(pdev->dev.of_node,
|
||||
"clock-frequency", &clock_freq);
|
||||
of_property_read_u8(pdev->dev.of_node,
|
||||
"fsl,clk-source", &clk_src);
|
||||
}
|
||||
|
||||
if (!clock_freq) {
|
||||
clk_ipg = devm_clk_get(&pdev->dev, "ipg");
|
||||
|
@ -1576,6 +1603,7 @@ static int flexcan_probe(struct platform_device *pdev)
|
|||
priv->write = flexcan_write_le;
|
||||
}
|
||||
|
||||
priv->dev = &pdev->dev;
|
||||
priv->can.clock.freq = clock_freq;
|
||||
priv->can.bittiming_const = &flexcan_bittiming_const;
|
||||
priv->can.do_set_mode = flexcan_set_mode;
|
||||
|
@ -1586,9 +1614,14 @@ static int flexcan_probe(struct platform_device *pdev)
|
|||
priv->regs = regs;
|
||||
priv->clk_ipg = clk_ipg;
|
||||
priv->clk_per = clk_per;
|
||||
priv->clk_src = clk_src;
|
||||
priv->devtype_data = devtype_data;
|
||||
priv->reg_xceiver = reg_xceiver;
|
||||
|
||||
pm_runtime_get_noresume(&pdev->dev);
|
||||
pm_runtime_set_active(&pdev->dev);
|
||||
pm_runtime_enable(&pdev->dev);
|
||||
|
||||
err = register_flexcandev(dev);
|
||||
if (err) {
|
||||
dev_err(&pdev->dev, "registering netdev failed\n");
|
||||
|
@ -1615,6 +1648,7 @@ static int flexcan_remove(struct platform_device *pdev)
|
|||
struct net_device *dev = platform_get_drvdata(pdev);
|
||||
|
||||
unregister_flexcandev(dev);
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
free_candev(dev);
|
||||
|
||||
return 0;
|
||||
|
@ -1624,7 +1658,7 @@ static int __maybe_unused flexcan_suspend(struct device *device)
|
|||
{
|
||||
struct net_device *dev = dev_get_drvdata(device);
|
||||
struct flexcan_priv *priv = netdev_priv(dev);
|
||||
int err;
|
||||
int err = 0;
|
||||
|
||||
if (netif_running(dev)) {
|
||||
/* if wakeup is enabled, enter stop mode
|
||||
|
@ -1639,20 +1673,22 @@ static int __maybe_unused flexcan_suspend(struct device *device)
|
|||
err = flexcan_chip_disable(priv);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = pm_runtime_force_suspend(device);
|
||||
}
|
||||
netif_stop_queue(dev);
|
||||
netif_device_detach(dev);
|
||||
}
|
||||
priv->can.state = CAN_STATE_SLEEPING;
|
||||
|
||||
return 0;
|
||||
return err;
|
||||
}
|
||||
|
||||
static int __maybe_unused flexcan_resume(struct device *device)
|
||||
{
|
||||
struct net_device *dev = dev_get_drvdata(device);
|
||||
struct flexcan_priv *priv = netdev_priv(dev);
|
||||
int err;
|
||||
int err = 0;
|
||||
|
||||
priv->can.state = CAN_STATE_ERROR_ACTIVE;
|
||||
if (netif_running(dev)) {
|
||||
|
@ -1661,14 +1697,35 @@ static int __maybe_unused flexcan_resume(struct device *device)
|
|||
if (device_may_wakeup(device)) {
|
||||
disable_irq_wake(dev->irq);
|
||||
} else {
|
||||
err = flexcan_chip_enable(priv);
|
||||
err = pm_runtime_force_resume(device);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = flexcan_chip_enable(priv);
|
||||
}
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int __maybe_unused flexcan_runtime_suspend(struct device *device)
|
||||
{
|
||||
struct net_device *dev = dev_get_drvdata(device);
|
||||
struct flexcan_priv *priv = netdev_priv(dev);
|
||||
|
||||
flexcan_clks_disable(priv);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __maybe_unused flexcan_runtime_resume(struct device *device)
|
||||
{
|
||||
struct net_device *dev = dev_get_drvdata(device);
|
||||
struct flexcan_priv *priv = netdev_priv(dev);
|
||||
|
||||
return flexcan_clks_enable(priv);
|
||||
}
|
||||
|
||||
static int __maybe_unused flexcan_noirq_suspend(struct device *device)
|
||||
{
|
||||
struct net_device *dev = dev_get_drvdata(device);
|
||||
|
@ -1698,6 +1755,7 @@ static int __maybe_unused flexcan_noirq_resume(struct device *device)
|
|||
|
||||
static const struct dev_pm_ops flexcan_pm_ops = {
|
||||
SET_SYSTEM_SLEEP_PM_OPS(flexcan_suspend, flexcan_resume)
|
||||
SET_RUNTIME_PM_OPS(flexcan_runtime_suspend, flexcan_runtime_resume, NULL)
|
||||
SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(flexcan_noirq_suspend, flexcan_noirq_resume)
|
||||
};
|
||||
|
||||
|
|
|
@ -1936,7 +1936,6 @@ static int ican3_probe(struct platform_device *pdev)
|
|||
/* find our IRQ number */
|
||||
mod->irq = platform_get_irq(pdev, 0);
|
||||
if (mod->irq < 0) {
|
||||
dev_err(dev, "IRQ line not found\n");
|
||||
ret = -ENODEV;
|
||||
goto out_free_ndev;
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,6 +1,24 @@
|
|||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
config CAN_M_CAN
|
||||
depends on HAS_IOMEM
|
||||
tristate "Bosch M_CAN devices"
|
||||
tristate "Bosch M_CAN support"
|
||||
---help---
|
||||
Say Y here if you want to support for Bosch M_CAN controller.
|
||||
Say Y here if you want support for Bosch M_CAN controller framework.
|
||||
This is common support for devices that embed the Bosch M_CAN IP.
|
||||
|
||||
config CAN_M_CAN_PLATFORM
|
||||
tristate "Bosch M_CAN support for io-mapped devices"
|
||||
depends on HAS_IOMEM
|
||||
depends on CAN_M_CAN
|
||||
---help---
|
||||
Say Y here if you want support for IO Mapped Bosch M_CAN controller.
|
||||
This support is for devices that have the Bosch M_CAN controller
|
||||
IP embedded into the device and the IP is IO Mapped to the processor.
|
||||
|
||||
config CAN_M_CAN_TCAN4X5X
|
||||
depends on CAN_M_CAN
|
||||
depends on REGMAP_SPI
|
||||
tristate "TCAN4X5X M_CAN device"
|
||||
---help---
|
||||
Say Y here if you want support for Texas Instruments TCAN4x5x
|
||||
M_CAN controller. This device is a peripherial device that uses the
|
||||
SPI bus for communication.
|
||||
|
|
|
@ -4,3 +4,5 @@
|
|||
#
|
||||
|
||||
obj-$(CONFIG_CAN_M_CAN) += m_can.o
|
||||
obj-$(CONFIG_CAN_M_CAN_PLATFORM) += m_can_platform.o
|
||||
obj-$(CONFIG_CAN_M_CAN_TCAN4X5X) += tcan4x5x.o
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,110 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/* CAN bus driver for Bosch M_CAN controller
|
||||
* Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/
|
||||
*/
|
||||
|
||||
#ifndef _CAN_M_CAN_H_
|
||||
#define _CAN_M_CAN_H_
|
||||
|
||||
#include <linux/can/core.h>
|
||||
#include <linux/can/led.h>
|
||||
#include <linux/completion.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/freezer.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/iopoll.h>
|
||||
#include <linux/can/dev.h>
|
||||
#include <linux/pinctrl/consumer.h>
|
||||
|
||||
/* m_can lec values */
|
||||
enum m_can_lec_type {
|
||||
LEC_NO_ERROR = 0,
|
||||
LEC_STUFF_ERROR,
|
||||
LEC_FORM_ERROR,
|
||||
LEC_ACK_ERROR,
|
||||
LEC_BIT1_ERROR,
|
||||
LEC_BIT0_ERROR,
|
||||
LEC_CRC_ERROR,
|
||||
LEC_UNUSED,
|
||||
};
|
||||
|
||||
enum m_can_mram_cfg {
|
||||
MRAM_SIDF = 0,
|
||||
MRAM_XIDF,
|
||||
MRAM_RXF0,
|
||||
MRAM_RXF1,
|
||||
MRAM_RXB,
|
||||
MRAM_TXE,
|
||||
MRAM_TXB,
|
||||
MRAM_CFG_NUM,
|
||||
};
|
||||
|
||||
/* address offset and element number for each FIFO/Buffer in the Message RAM */
|
||||
struct mram_cfg {
|
||||
u16 off;
|
||||
u8 num;
|
||||
};
|
||||
|
||||
struct m_can_classdev;
|
||||
struct m_can_ops {
|
||||
/* Device specific call backs */
|
||||
int (*clear_interrupts)(struct m_can_classdev *cdev);
|
||||
u32 (*read_reg)(struct m_can_classdev *cdev, int reg);
|
||||
int (*write_reg)(struct m_can_classdev *cdev, int reg, int val);
|
||||
u32 (*read_fifo)(struct m_can_classdev *cdev, int addr_offset);
|
||||
int (*write_fifo)(struct m_can_classdev *cdev, int addr_offset,
|
||||
int val);
|
||||
int (*init)(struct m_can_classdev *cdev);
|
||||
};
|
||||
|
||||
struct m_can_classdev {
|
||||
struct can_priv can;
|
||||
struct napi_struct napi;
|
||||
struct net_device *net;
|
||||
struct device *dev;
|
||||
struct clk *hclk;
|
||||
struct clk *cclk;
|
||||
|
||||
struct workqueue_struct *tx_wq;
|
||||
struct work_struct tx_work;
|
||||
struct sk_buff *tx_skb;
|
||||
|
||||
struct can_bittiming_const *bit_timing;
|
||||
struct can_bittiming_const *data_timing;
|
||||
|
||||
struct m_can_ops *ops;
|
||||
|
||||
void *device_data;
|
||||
|
||||
int version;
|
||||
int freq;
|
||||
u32 irqstatus;
|
||||
|
||||
int pm_clock_support;
|
||||
int is_peripheral;
|
||||
|
||||
struct mram_cfg mcfg[MRAM_CFG_NUM];
|
||||
};
|
||||
|
||||
struct m_can_classdev *m_can_class_allocate_dev(struct device *dev);
|
||||
int m_can_class_register(struct m_can_classdev *cdev);
|
||||
void m_can_class_unregister(struct m_can_classdev *cdev);
|
||||
int m_can_class_get_clocks(struct m_can_classdev *cdev);
|
||||
void m_can_init_ram(struct m_can_classdev *priv);
|
||||
void m_can_config_endisable(struct m_can_classdev *priv, bool enable);
|
||||
|
||||
int m_can_class_suspend(struct device *dev);
|
||||
int m_can_class_resume(struct device *dev);
|
||||
#endif /* _CAN_M_H_ */
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue