1
0
Fork 0

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
  ...
alistair/sunxi64-5.4-dsi
Linus Torvalds 2019-09-18 12:34:53 -07:00
commit 81160dda9a
1711 changed files with 121345 additions and 35857 deletions

View File

@ -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>

View File

@ -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

View File

@ -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.

View File

@ -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
-------

View File

@ -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
========================

View File

@ -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

View File

@ -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;
};
};

View File

@ -17,6 +17,9 @@ properties:
compatible:
const: allwinner,sun7i-a20-gmac
reg:
maxItems: 1
interrupts:
maxItems: 1

View File

@ -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";
};

View File

@ -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>;
};
};

View File

@ -13,6 +13,7 @@ Required properties:
* "brcm,bcm20702a1"
* "brcm,bcm4330-bt"
* "brcm,bcm43438-bt"
* "brcm,bcm4345c5"
Optional properties:

View File

@ -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
};

View File

@ -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>;
};

View File

@ -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"

View File

@ -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",

View File

@ -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.
&eth {
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.
&eth {
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;
};
};
};
};
};
};

View File

@ -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.

View File

@ -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.

View File

@ -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";
};

View File

@ -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>;

View File

@ -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:

View File

@ -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

View File

@ -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

View File

@ -23,6 +23,7 @@ Contents:
intel/ice
google/gve
mellanox/mlx5
pensando/ionic
.. only:: subproject and html

View File

@ -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).

View File

@ -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

View File

@ -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.

View File

@ -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

View File

@ -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
=======

View File

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

View File

@ -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

View File

@ -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

View File

@ -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.

View File

@ -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
=====================================

View File

@ -14,7 +14,10 @@ Contents:
device_drivers/index
dsa/index
devlink-info-versions
devlink-trap
devlink-trap-netdevsim
ieee802154
j1939
kapi
z8530book
msg_zerocopy

View File

@ -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.

View File

@ -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));

View File

@ -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.

View File

@ -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

View File

@ -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 {

View File

@ -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>;

View File

@ -115,24 +115,34 @@
};
&eth {
pinctrl-names = "default";
pinctrl-0 = <&eth_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";
};
};
};

View File

@ -931,6 +931,5 @@
"syscon";
reg = <0 0x1b128000 0 0x3000>;
#clock-cells = <1>;
mediatek,physpeed = "2500";
};
};

View File

@ -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)

View File

@ -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:

View File

@ -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 */

View File

@ -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);
}

View File

@ -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);

View File

@ -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 *);

View File

@ -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 ?

View File

@ -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) {

View File

@ -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;
}

View File

@ -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);

View File

@ -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;

View File

@ -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;

View File

@ -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);
}

View File

@ -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)

View File

@ -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 */

View File

@ -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);

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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" },
{ },

View File

@ -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;
}

View File

@ -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);

View File

@ -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);
}

View File

@ -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");
}

View File

@ -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));
}
}

View File

@ -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;

View File

@ -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)] = {};

View File

@ -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 */

View File

@ -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;

View File

@ -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;

View File

@ -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);

View File

@ -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 {

View File

@ -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)

View File

@ -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;

View File

@ -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);

View File

@ -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);
}

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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
}
}

View File

@ -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

View File

@ -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

View File

@ -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;
}

View File

@ -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;

View File

@ -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);
}

View File

@ -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;

View File

@ -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);

View File

@ -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

View File

@ -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/

View File

@ -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;
}

View File

@ -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, &regs->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(&regs->ctrl);
reg |= FLEXCAN_CTRL_CLK_SRC;
if (priv->clk_src)
reg |= FLEXCAN_CTRL_CLK_SRC;
else
reg &= ~FLEXCAN_CTRL_CLK_SRC;
priv->write(reg, &regs->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)
};

View File

@ -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

View File

@ -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.

View File

@ -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

View File

@ -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