mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
synced 2025-01-15 02:05:33 +00:00
Merge branch 'main' of git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-next.git
This commit is contained in:
commit
9e4691b393
2
.mailmap
2
.mailmap
@ -535,6 +535,8 @@ Oleksij Rempel <linux@rempel-privat.de> <external.Oleksij.Rempel@de.bosch.com>
|
||||
Oleksij Rempel <linux@rempel-privat.de> <fixed-term.Oleksij.Rempel@de.bosch.com>
|
||||
Oleksij Rempel <o.rempel@pengutronix.de>
|
||||
Oleksij Rempel <o.rempel@pengutronix.de> <ore@pengutronix.de>
|
||||
Oliver Hartkopp <socketcan@hartkopp.net> <oliver.hartkopp@volkswagen.de>
|
||||
Oliver Hartkopp <socketcan@hartkopp.net> <oliver@hartkopp.net>
|
||||
Oliver Upton <oliver.upton@linux.dev> <oupton@google.com>
|
||||
Ondřej Jirman <megi@xff.cz> <megous@megous.com>
|
||||
Oza Pawandeep <quic_poza@quicinc.com> <poza@codeaurora.org>
|
||||
|
@ -104,7 +104,7 @@ quiet_cmd_sphinx = SPHINX $@ --> file://$(abspath $(BUILDDIR)/$3/$4)
|
||||
YNL_INDEX:=$(srctree)/Documentation/networking/netlink_spec/index.rst
|
||||
YNL_RST_DIR:=$(srctree)/Documentation/networking/netlink_spec
|
||||
YNL_YAML_DIR:=$(srctree)/Documentation/netlink/specs
|
||||
YNL_TOOL:=$(srctree)/tools/net/ynl/ynl-gen-rst.py
|
||||
YNL_TOOL:=$(srctree)/tools/net/ynl/pyynl/ynl_gen_rst.py
|
||||
|
||||
YNL_RST_FILES_TMP := $(patsubst %.yaml,%.rst,$(wildcard $(YNL_YAML_DIR)/*.yaml))
|
||||
YNL_RST_FILES := $(patsubst $(YNL_YAML_DIR)%,$(YNL_RST_DIR)%, $(YNL_RST_FILES_TMP))
|
||||
|
@ -227,11 +227,119 @@ Intended use
|
||||
|
||||
Drivers that opt to use this API first need to identify which of the above 3
|
||||
quirk combinations (for a total of 8) match what the hardware documentation
|
||||
describes. Then they should wrap the packing() function, creating a new
|
||||
xxx_packing() that calls it using the proper QUIRK_* one-hot bits set.
|
||||
describes.
|
||||
|
||||
There are 3 supported usage patterns, detailed below.
|
||||
|
||||
packing()
|
||||
^^^^^^^^^
|
||||
|
||||
This API function is deprecated.
|
||||
|
||||
The packing() function returns an int-encoded error code, which protects the
|
||||
programmer against incorrect API use. The errors are not expected to occur
|
||||
during runtime, therefore it is reasonable for xxx_packing() to return void
|
||||
and simply swallow those errors. Optionally it can dump stack or print the
|
||||
error description.
|
||||
during runtime, therefore it is reasonable to wrap packing() into a custom
|
||||
function which returns void and swallows those errors. Optionally it can
|
||||
dump stack or print the error description.
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
void my_packing(void *buf, u64 *val, int startbit, int endbit,
|
||||
size_t len, enum packing_op op)
|
||||
{
|
||||
int err;
|
||||
|
||||
/* Adjust quirks accordingly */
|
||||
err = packing(buf, val, startbit, endbit, len, op, QUIRK_LSW32_IS_FIRST);
|
||||
if (likely(!err))
|
||||
return;
|
||||
|
||||
if (err == -EINVAL) {
|
||||
pr_err("Start bit (%d) expected to be larger than end (%d)\n",
|
||||
startbit, endbit);
|
||||
} else if (err == -ERANGE) {
|
||||
if ((startbit - endbit + 1) > 64)
|
||||
pr_err("Field %d-%d too large for 64 bits!\n",
|
||||
startbit, endbit);
|
||||
else
|
||||
pr_err("Cannot store %llx inside bits %d-%d (would truncate)\n",
|
||||
*val, startbit, endbit);
|
||||
}
|
||||
dump_stack();
|
||||
}
|
||||
|
||||
pack() and unpack()
|
||||
^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
These are const-correct variants of packing(), and eliminate the last "enum
|
||||
packing_op op" argument.
|
||||
|
||||
Calling pack(...) is equivalent, and preferred, to calling packing(..., PACK).
|
||||
|
||||
Calling unpack(...) is equivalent, and preferred, to calling packing(..., UNPACK).
|
||||
|
||||
pack_fields() and unpack_fields()
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
The library exposes optimized functions for the scenario where there are many
|
||||
fields represented in a buffer, and it encourages consumer drivers to avoid
|
||||
repetitive calls to pack() and unpack() for each field, but instead use
|
||||
pack_fields() and unpack_fields(), which reduces the code footprint.
|
||||
|
||||
These APIs use field definitions in arrays of ``struct packed_field_u8`` or
|
||||
``struct packed_field_u16``, allowing consumer drivers to minimize the size
|
||||
of these arrays according to their custom requirements.
|
||||
|
||||
The pack_fields() and unpack_fields() API functions are actually macros which
|
||||
automatically select the appropriate function at compile time, based on the
|
||||
type of the fields array passed in.
|
||||
|
||||
An additional benefit over pack() and unpack() is that sanity checks on the
|
||||
field definitions are handled at compile time with ``BUILD_BUG_ON`` rather
|
||||
than only when the offending code is executed. These functions return void and
|
||||
wrapping them to handle unexpected errors is not necessary.
|
||||
|
||||
It is recommended, but not required, that you wrap your packed buffer into a
|
||||
structured type with a fixed size. This generally makes it easier for the
|
||||
compiler to enforce that the correct size buffer is used.
|
||||
|
||||
Here is an example of how to use the fields APIs:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
/* Ordering inside the unpacked structure is flexible and can be different
|
||||
* from the packed buffer. Here, it is optimized to reduce padding.
|
||||
*/
|
||||
struct data {
|
||||
u64 field3;
|
||||
u32 field4;
|
||||
u16 field1;
|
||||
u8 field2;
|
||||
};
|
||||
|
||||
#define SIZE 13
|
||||
|
||||
typdef struct __packed { u8 buf[SIZE]; } packed_buf_t;
|
||||
|
||||
static const struct packed_field_u8 fields[] = {
|
||||
PACKED_FIELD(100, 90, struct data, field1),
|
||||
PACKED_FIELD(90, 87, struct data, field2),
|
||||
PACKED_FIELD(86, 30, struct data, field3),
|
||||
PACKED_FIELD(29, 0, struct data, field4),
|
||||
};
|
||||
|
||||
void unpack_your_data(const packed_buf_t *buf, struct data *unpacked)
|
||||
{
|
||||
BUILD_BUG_ON(sizeof(*buf) != SIZE;
|
||||
|
||||
unpack_fields(buf, sizeof(*buf), unpacked, fields,
|
||||
QUIRK_LITTLE_ENDIAN);
|
||||
}
|
||||
|
||||
void pack_your_data(const struct data *unpacked, packed_buf_t *buf)
|
||||
{
|
||||
BUILD_BUG_ON(sizeof(*buf) != SIZE;
|
||||
|
||||
pack_fields(buf, sizeof(*buf), unpacked, fields,
|
||||
QUIRK_LITTLE_ENDIAN);
|
||||
}
|
||||
|
@ -38,7 +38,7 @@ unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
mdio_mux_iproc: mdio-mux@66020000 {
|
||||
mdio-mux@66020000 {
|
||||
compatible = "brcm,mdio-mux-iproc";
|
||||
reg = <0x66020000 0x250>;
|
||||
#address-cells = <1>;
|
||||
@ -49,7 +49,7 @@ examples:
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
pci_phy0: pci-phy@0 {
|
||||
pci-phy@0 {
|
||||
compatible = "brcm,ns2-pcie-phy";
|
||||
reg = <0x0>;
|
||||
#phy-cells = <0>;
|
||||
@ -61,7 +61,7 @@ examples:
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
pci_phy1: pci-phy@0 {
|
||||
pci-phy@0 {
|
||||
compatible = "brcm,ns2-pcie-phy";
|
||||
reg = <0x0>;
|
||||
#phy-cells = <0>;
|
||||
@ -73,7 +73,7 @@ examples:
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
gphy0: eth-phy@10 {
|
||||
eth-phy@10 {
|
||||
reg = <0x10>;
|
||||
};
|
||||
};
|
||||
|
@ -0,0 +1,58 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/net/can/atmel,at91sam9263-can.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Microchip AT91 CAN Controller
|
||||
|
||||
maintainers:
|
||||
- Nicolas Ferre <nicolas.ferre@microchip.com>
|
||||
|
||||
allOf:
|
||||
- $ref: can-controller.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
oneOf:
|
||||
- enum:
|
||||
- atmel,at91sam9263-can
|
||||
- atmel,at91sam9x5-can
|
||||
- items:
|
||||
- enum:
|
||||
- microchip,sam9x60-can
|
||||
- const: atmel,at91sam9x5-can
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
maxItems: 1
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: can_clk
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- interrupts
|
||||
- clocks
|
||||
- clock-names
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
#include <dt-bindings/clock/at91.h>
|
||||
can@f000c000 {
|
||||
compatible = "atmel,at91sam9263-can";
|
||||
reg = <0xf000c000 0x300>;
|
||||
interrupts = <30 IRQ_TYPE_LEVEL_HIGH 3>;
|
||||
clocks = <&pmc PMC_TYPE_PERIPHERAL 12>;
|
||||
clock-names = "can_clk";
|
||||
};
|
@ -1,15 +0,0 @@
|
||||
* AT91 CAN *
|
||||
|
||||
Required properties:
|
||||
- compatible: Should be "atmel,at91sam9263-can", "atmel,at91sam9x5-can" or
|
||||
"microchip,sam9x60-can"
|
||||
- reg: Should contain CAN controller registers location and length
|
||||
- interrupts: Should contain IRQ line for the CAN controller
|
||||
|
||||
Example:
|
||||
|
||||
can0: can@f000c000 {
|
||||
compatible = "atmel,at91sam9x5-can";
|
||||
reg = <0xf000c000 0x300>;
|
||||
interrupts = <40 4 5>
|
||||
};
|
@ -15,7 +15,11 @@ allOf:
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: microchip,mpfs-can
|
||||
oneOf:
|
||||
- items:
|
||||
- const: microchip,pic64gx-can
|
||||
- const: microchip,mpfs-can
|
||||
- const: microchip,mpfs-can
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
@ -63,7 +63,7 @@ properties:
|
||||
maxItems: 1
|
||||
|
||||
st,gcan:
|
||||
$ref: /schemas/types.yaml#/definitions/phandle-array
|
||||
$ref: /schemas/types.yaml#/definitions/phandle
|
||||
description:
|
||||
The phandle to the gcan node which allows to access the 512-bytes
|
||||
SRAM memory shared by the two bxCAN cells (CAN1 primary and CAN2
|
||||
|
@ -1,48 +0,0 @@
|
||||
Texas Instruments TCAN4x5x CAN Controller
|
||||
================================================
|
||||
|
||||
This file provides device node information for the TCAN4x5x interface contains.
|
||||
|
||||
Required properties:
|
||||
- compatible:
|
||||
"ti,tcan4552", "ti,tcan4x5x"
|
||||
"ti,tcan4553", "ti,tcan4x5x" or
|
||||
"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.
|
||||
- interrupt-parent: the phandle to the interrupt controller which provides
|
||||
the interrupt.
|
||||
- interrupts: interrupt specification for data-ready.
|
||||
|
||||
See Documentation/devicetree/bindings/net/can/bosch,m_can.yaml 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. Not
|
||||
available with tcan4552/4553.
|
||||
- device-wake-gpios: Wake up GPIO to wake up the TCAN device. Not
|
||||
available with tcan4552/4553.
|
||||
- wakeup-source: Leave the chip running when suspended, and configure
|
||||
the RX interrupt to wake up the device.
|
||||
|
||||
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 16 0 0 1 1>;
|
||||
interrupt-parent = <&gpio1>;
|
||||
interrupts = <14 IRQ_TYPE_LEVEL_LOW>;
|
||||
device-state-gpios = <&gpio3 21 GPIO_ACTIVE_HIGH>;
|
||||
device-wake-gpios = <&gpio1 15 GPIO_ACTIVE_HIGH>;
|
||||
reset-gpios = <&gpio1 27 GPIO_ACTIVE_HIGH>;
|
||||
wakeup-source;
|
||||
};
|
199
Documentation/devicetree/bindings/net/can/ti,tcan4x5x.yaml
Normal file
199
Documentation/devicetree/bindings/net/can/ti,tcan4x5x.yaml
Normal file
@ -0,0 +1,199 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/net/can/ti,tcan4x5x.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Texas Instruments TCAN4x5x CAN Controller
|
||||
|
||||
maintainers:
|
||||
- Marc Kleine-Budde <mkl@pengutronix.de>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
oneOf:
|
||||
- items:
|
||||
- enum:
|
||||
- ti,tcan4552
|
||||
- ti,tcan4553
|
||||
- const: ti,tcan4x5x
|
||||
- const: ti,tcan4x5x
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
description: The GPIO parent interrupt.
|
||||
|
||||
clocks:
|
||||
maxItems: 1
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: cclk
|
||||
|
||||
reset-gpios:
|
||||
description: Hardwired output GPIO. If not defined then software reset.
|
||||
maxItems: 1
|
||||
|
||||
device-state-gpios:
|
||||
description:
|
||||
Input GPIO that indicates if the device is in a sleep state or if the
|
||||
device is active. Not available with tcan4552/4553.
|
||||
maxItems: 1
|
||||
|
||||
device-wake-gpios:
|
||||
description:
|
||||
Wake up GPIO to wake up the TCAN device.
|
||||
Not available with tcan4552/4553.
|
||||
maxItems: 1
|
||||
|
||||
bosch,mram-cfg:
|
||||
description: |
|
||||
Message RAM configuration data.
|
||||
Multiple M_CAN instances can share the same Message RAM
|
||||
and each element(e.g Rx FIFO or Tx Buffer and etc) number
|
||||
in Message RAM is also configurable, so this property is
|
||||
telling driver how the shared or private Message RAM are
|
||||
used by this M_CAN controller.
|
||||
|
||||
The format should be as follows:
|
||||
<offset sidf_elems xidf_elems rxf0_elems rxf1_elems rxb_elems txe_elems txb_elems>
|
||||
The 'offset' is an address offset of the Message RAM where
|
||||
the following elements start from. This is usually set to
|
||||
0x0 if you're using a private Message RAM. The remain cells
|
||||
are used to specify how many elements are used for each FIFO/Buffer.
|
||||
|
||||
M_CAN includes the following elements according to user manual:
|
||||
11-bit Filter 0-128 elements / 0-128 words
|
||||
29-bit Filter 0-64 elements / 0-128 words
|
||||
Rx FIFO 0 0-64 elements / 0-1152 words
|
||||
Rx FIFO 1 0-64 elements / 0-1152 words
|
||||
Rx Buffers 0-64 elements / 0-1152 words
|
||||
Tx Event FIFO 0-32 elements / 0-64 words
|
||||
Tx Buffers 0-32 elements / 0-576 words
|
||||
|
||||
Please refer to 2.4.1 Message RAM Configuration in Bosch
|
||||
M_CAN user manual for details.
|
||||
$ref: /schemas/types.yaml#/definitions/int32-array
|
||||
items:
|
||||
- description: The 'offset' is an address offset of the Message RAM where
|
||||
the following elements start from. This is usually set to 0x0 if
|
||||
you're using a private Message RAM.
|
||||
default: 0
|
||||
- description: 11-bit Filter 0-128 elements / 0-128 words
|
||||
minimum: 0
|
||||
maximum: 128
|
||||
- description: 29-bit Filter 0-64 elements / 0-128 words
|
||||
minimum: 0
|
||||
maximum: 64
|
||||
- description: Rx FIFO 0 0-64 elements / 0-1152 words
|
||||
minimum: 0
|
||||
maximum: 64
|
||||
- description: Rx FIFO 1 0-64 elements / 0-1152 words
|
||||
minimum: 0
|
||||
maximum: 64
|
||||
- description: Rx Buffers 0-64 elements / 0-1152 words
|
||||
minimum: 0
|
||||
maximum: 64
|
||||
- description: Tx Event FIFO 0-32 elements / 0-64 words
|
||||
minimum: 0
|
||||
maximum: 32
|
||||
- description: Tx Buffers 0-32 elements / 0-576 words
|
||||
minimum: 0
|
||||
maximum: 32
|
||||
minItems: 1
|
||||
|
||||
spi-max-frequency:
|
||||
description:
|
||||
Must be half or less of "clocks" frequency.
|
||||
maximum: 18000000
|
||||
|
||||
ti,nwkrq-voltage-vio:
|
||||
type: boolean
|
||||
description:
|
||||
nWKRQ Pin GPO buffer voltage configuration.
|
||||
Set nWKRQ to use VIO voltage rail.
|
||||
When not set nWKRQ will use internal voltage rail.
|
||||
|
||||
wakeup-source:
|
||||
$ref: /schemas/types.yaml#/definitions/flag
|
||||
description:
|
||||
Enable CAN remote wakeup.
|
||||
|
||||
allOf:
|
||||
- $ref: can-controller.yaml#
|
||||
- $ref: /schemas/spi/spi-peripheral-props.yaml#
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- ti,tcan4552
|
||||
- ti,tcan4553
|
||||
then:
|
||||
properties:
|
||||
device-state-gpios: false
|
||||
device-wake-gpios: false
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- interrupts
|
||||
- clocks
|
||||
- clock-names
|
||||
- bosch,mram-cfg
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
|
||||
spi {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
can@0 {
|
||||
compatible = "ti,tcan4x5x";
|
||||
reg = <0>;
|
||||
clocks = <&can0_osc>;
|
||||
clock-names = "cclk";
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&can0_pins>;
|
||||
spi-max-frequency = <10000000>;
|
||||
bosch,mram-cfg = <0x0 0 0 16 0 0 1 1>;
|
||||
interrupt-parent = <&gpio1>;
|
||||
interrupts = <14 IRQ_TYPE_LEVEL_LOW>;
|
||||
device-state-gpios = <&gpio3 21 GPIO_ACTIVE_HIGH>;
|
||||
device-wake-gpios = <&gpio1 15 GPIO_ACTIVE_HIGH>;
|
||||
reset-gpios = <&gpio1 27 GPIO_ACTIVE_HIGH>;
|
||||
ti,nwkrq-voltage-vio;
|
||||
wakeup-source;
|
||||
};
|
||||
};
|
||||
- |
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
|
||||
spi {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
can@0 {
|
||||
compatible = "ti,tcan4552", "ti,tcan4x5x";
|
||||
reg = <0>;
|
||||
clocks = <&can0_osc>;
|
||||
clock-names = "cclk";
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&can0_pins>;
|
||||
spi-max-frequency = <10000000>;
|
||||
bosch,mram-cfg = <0x0 0 0 16 0 0 1 1>;
|
||||
interrupt-parent = <&gpio1>;
|
||||
interrupts = <14 IRQ_TYPE_LEVEL_LOW>;
|
||||
reset-gpios = <&gpio1 27 GPIO_ACTIVE_HIGH>;
|
||||
wakeup-source;
|
||||
};
|
||||
};
|
@ -129,6 +129,24 @@ properties:
|
||||
minimum: 0
|
||||
maximum: 383
|
||||
|
||||
rx-internal-delay-ps:
|
||||
description:
|
||||
RGMII Receive Clock Delay defined in pico seconds, used to select
|
||||
the DLL phase shift between 1000 ps (45 degree shift at 1Gbps) and
|
||||
3300 ps (147 degree shift at 1Gbps). A value of 0 ps will disable
|
||||
any delay. The Default is no delay.
|
||||
enum: [0, 1000, 1700, 2000, 2500, 3000, 3300]
|
||||
default: 0
|
||||
|
||||
tx-internal-delay-ps:
|
||||
description:
|
||||
RGMII Transmit Clock Delay defined in pico seconds, used to select
|
||||
the DLL phase shift between 1000 ps (45 degree shift at 1Gbps) and
|
||||
3300 ps (147 degree shift at 1Gbps). A value of 0 ps will disable
|
||||
any delay. The Default is no delay.
|
||||
enum: [0, 1000, 1700, 2000, 2500, 3000, 3300]
|
||||
default: 0
|
||||
|
||||
required:
|
||||
- reg
|
||||
- phys
|
||||
|
105
Documentation/devicetree/bindings/net/nxp,s32-dwmac.yaml
Normal file
105
Documentation/devicetree/bindings/net/nxp,s32-dwmac.yaml
Normal file
@ -0,0 +1,105 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
# Copyright 2021-2024 NXP
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/net/nxp,s32-dwmac.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: NXP S32G2xx/S32G3xx/S32R45 GMAC ethernet controller
|
||||
|
||||
maintainers:
|
||||
- Jan Petrous (OSS) <jan.petrous@oss.nxp.com>
|
||||
|
||||
description:
|
||||
This device is a Synopsys DWC IP, integrated on NXP S32G/R SoCs.
|
||||
The SoC series S32G2xx and S32G3xx feature one DWMAC instance,
|
||||
the SoC S32R45 has two instances. The devices can use RGMII/RMII/MII
|
||||
interface over Pinctrl device or the output can be routed
|
||||
to the embedded SerDes for SGMII connectivity.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
oneOf:
|
||||
- const: nxp,s32g2-dwmac
|
||||
- items:
|
||||
- enum:
|
||||
- nxp,s32g3-dwmac
|
||||
- nxp,s32r45-dwmac
|
||||
- const: nxp,s32g2-dwmac
|
||||
|
||||
reg:
|
||||
items:
|
||||
- description: Main GMAC registers
|
||||
- description: GMAC PHY mode control register
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
interrupt-names:
|
||||
const: macirq
|
||||
|
||||
clocks:
|
||||
items:
|
||||
- description: Main GMAC clock
|
||||
- description: Transmit clock
|
||||
- description: Receive clock
|
||||
- description: PTP reference clock
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: stmmaceth
|
||||
- const: tx
|
||||
- const: rx
|
||||
- const: ptp_ref
|
||||
|
||||
required:
|
||||
- clocks
|
||||
- clock-names
|
||||
|
||||
allOf:
|
||||
- $ref: snps,dwmac.yaml#
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
#include <dt-bindings/phy/phy.h>
|
||||
bus {
|
||||
#address-cells = <2>;
|
||||
#size-cells = <2>;
|
||||
|
||||
ethernet@4033c000 {
|
||||
compatible = "nxp,s32g2-dwmac";
|
||||
reg = <0x0 0x4033c000 0x0 0x2000>, /* gmac IP */
|
||||
<0x0 0x4007c004 0x0 0x4>; /* GMAC_0_CTRL_STS */
|
||||
interrupt-parent = <&gic>;
|
||||
interrupts = <GIC_SPI 57 IRQ_TYPE_LEVEL_HIGH>;
|
||||
interrupt-names = "macirq";
|
||||
snps,mtl-rx-config = <&mtl_rx_setup>;
|
||||
snps,mtl-tx-config = <&mtl_tx_setup>;
|
||||
clocks = <&clks 24>, <&clks 17>, <&clks 16>, <&clks 15>;
|
||||
clock-names = "stmmaceth", "tx", "rx", "ptp_ref";
|
||||
phy-mode = "rgmii-id";
|
||||
phy-handle = <&phy0>;
|
||||
|
||||
mtl_rx_setup: rx-queues-config {
|
||||
snps,rx-queues-to-use = <5>;
|
||||
};
|
||||
|
||||
mtl_tx_setup: tx-queues-config {
|
||||
snps,tx-queues-to-use = <5>;
|
||||
};
|
||||
|
||||
mdio {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
compatible = "snps,dwmac-mdio";
|
||||
|
||||
phy0: ethernet-phy@0 {
|
||||
reg = <0>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
@ -239,7 +239,7 @@ examples:
|
||||
|
||||
qcom,gsi-loader = "self";
|
||||
memory-region = <&ipa_fw_mem>;
|
||||
firmware-name = "qcom/sc7180-trogdor/modem/modem.mdt";
|
||||
firmware-name = "qcom/sc7180-trogdor/modem/modem.mbn";
|
||||
|
||||
iommus = <&apps_smmu 0x440 0x0>,
|
||||
<&apps_smmu 0x442 0x0>;
|
||||
|
@ -67,6 +67,7 @@ properties:
|
||||
- ingenic,x2000-mac
|
||||
- loongson,ls2k-dwmac
|
||||
- loongson,ls7a-dwmac
|
||||
- nxp,s32g2-dwmac
|
||||
- qcom,qcs404-ethqos
|
||||
- qcom,sa8775p-ethqos
|
||||
- qcom,sc8280xp-ethqos
|
||||
|
@ -96,6 +96,32 @@ properties:
|
||||
- master
|
||||
- slave
|
||||
|
||||
ti,gpio2-clk-out:
|
||||
description: |
|
||||
DP83822 PHY only.
|
||||
The GPIO2 pin on the DP83822 can be configured as clock output. When
|
||||
omitted, the PHY's default will be left as is.
|
||||
|
||||
- 'mac-if': In MII mode the clock frequency is 25-MHz, in RMII Mode the
|
||||
clock frequency is 50-MHz and in RGMII Mode the clock frequency is
|
||||
25-MHz.
|
||||
- 'xi': XI clock(pass-through clock from XI pin).
|
||||
- 'int-ref': Internal reference clock 25-MHz.
|
||||
- 'rmii-master-mode-ref': RMII master mode reference clock 50-MHz. RMII
|
||||
master mode reference clock is identical to MAC IF clock in RMII master
|
||||
mode.
|
||||
- 'free-running': Free running clock 125-MHz.
|
||||
- 'recovered': Recovered clock is a 125-MHz recovered clock from a
|
||||
connected link partner.
|
||||
$ref: /schemas/types.yaml#/definitions/string
|
||||
enum:
|
||||
- mac-if
|
||||
- xi
|
||||
- int-ref
|
||||
- rmii-master-mode-ref
|
||||
- free-running
|
||||
- recovered
|
||||
|
||||
required:
|
||||
- reg
|
||||
|
||||
@ -110,6 +136,7 @@ examples:
|
||||
reg = <0>;
|
||||
rx-internal-delay-ps = <1>;
|
||||
tx-internal-delay-ps = <1>;
|
||||
ti,gpio2-clk-out = "xi";
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -302,7 +302,6 @@ examples:
|
||||
ti,fifo-depth = <DP83867_PHYCR_FIFO_DEPTH_4_B_NIB>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
cpts@3d000 {
|
||||
compatible = "ti,am65-cpts";
|
||||
@ -315,3 +314,4 @@ examples:
|
||||
ti,cpts-periodic-outputs = <2>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
@ -90,4 +90,3 @@ examples:
|
||||
marvell,wakeup-pin = <3>;
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -106,6 +106,9 @@ properties:
|
||||
name-prefix:
|
||||
description: For enum the prefix of the values, optional.
|
||||
type: string
|
||||
enum-cnt-name:
|
||||
description: Name of the render-max counter enum entry.
|
||||
type: string
|
||||
# End genetlink-c
|
||||
|
||||
attribute-sets:
|
||||
|
@ -117,6 +117,9 @@ properties:
|
||||
name-prefix:
|
||||
description: For enum the prefix of the values, optional.
|
||||
type: string
|
||||
enum-cnt-name:
|
||||
description: Name of the render-max counter enum entry.
|
||||
type: string
|
||||
# End genetlink-c
|
||||
# Start genetlink-legacy
|
||||
members:
|
||||
|
@ -221,7 +221,7 @@ properties:
|
||||
type: &attr-type
|
||||
description: The netlink attribute type
|
||||
enum: [ unused, pad, flag, binary, bitfield32,
|
||||
u8, u16, u32, u64, s8, s16, s32, s64,
|
||||
uint, sint, u8, u16, u32, u64, s8, s16, s32, s64,
|
||||
string, nest, indexed-array, nest-type-value,
|
||||
sub-message ]
|
||||
doc:
|
||||
|
@ -5,6 +5,7 @@ name: ethtool
|
||||
protocol: genetlink-legacy
|
||||
|
||||
doc: Partial family for Ethtool Netlink.
|
||||
uapi-header: linux/ethtool_netlink_generated.h
|
||||
|
||||
definitions:
|
||||
-
|
||||
@ -12,43 +13,99 @@ definitions:
|
||||
enum-name:
|
||||
type: enum
|
||||
entries: [ vxlan, geneve, vxlan-gpe ]
|
||||
enum-cnt-name: __ethtool-udp-tunnel-type-cnt
|
||||
render-max: true
|
||||
-
|
||||
name: stringset
|
||||
type: enum
|
||||
entries: []
|
||||
header: linux/ethtool.h # skip rendering, no actual definition
|
||||
-
|
||||
name: header-flags
|
||||
type: flags
|
||||
entries: [ compact-bitsets, omit-reply, stats ]
|
||||
name-prefix: ethtool-flag-
|
||||
doc: common ethtool header flags
|
||||
entries:
|
||||
-
|
||||
name: compact-bitsets
|
||||
doc: use compact bitsets in reply
|
||||
-
|
||||
name: omit-reply
|
||||
doc: provide optional reply for SET or ACT requests
|
||||
-
|
||||
name: stats
|
||||
doc: request statistics, if supported by the driver
|
||||
-
|
||||
name: module-fw-flash-status
|
||||
type: enum
|
||||
entries: [ started, in_progress, completed, error ]
|
||||
doc: plug-in module firmware flashing status
|
||||
header: linux/ethtool.h
|
||||
entries:
|
||||
-
|
||||
name: started
|
||||
doc: The firmware flashing process has started.
|
||||
-
|
||||
name: in_progress
|
||||
doc: The firmware flashing process is in progress.
|
||||
-
|
||||
name: completed
|
||||
doc: The firmware flashing process was completed successfully.
|
||||
-
|
||||
name: error
|
||||
doc: The firmware flashing process was stopped due to an error.
|
||||
-
|
||||
name: c33-pse-ext-state
|
||||
enum-name:
|
||||
doc: "groups of PSE extended states functions. IEEE 802.3-2022 33.2.4.4 Variables"
|
||||
type: enum
|
||||
name-prefix: ethtool-c33-pse-ext-state-
|
||||
header: linux/ethtool.h
|
||||
entries:
|
||||
- none
|
||||
- error-condition
|
||||
- mr-mps-valid
|
||||
- mr-pse-enable
|
||||
- option-detect-ted
|
||||
- option-vport-lim
|
||||
- ovld-detected
|
||||
- power-not-available
|
||||
- short-detected
|
||||
-
|
||||
name: none
|
||||
doc: none
|
||||
-
|
||||
name: error-condition
|
||||
doc: Group of error_condition states
|
||||
-
|
||||
name: mr-mps-valid
|
||||
doc: Group of mr_mps_valid states
|
||||
-
|
||||
name: mr-pse-enable
|
||||
doc: Group of mr_pse_enable states
|
||||
-
|
||||
name: option-detect-ted
|
||||
doc: Group of option_detect_ted states
|
||||
-
|
||||
name: option-vport-lim
|
||||
doc: Group of option_vport_lim states
|
||||
-
|
||||
name: ovld-detected
|
||||
doc: Group of ovld_detected states
|
||||
-
|
||||
name: power-not-available
|
||||
doc: Group of power_not_available states
|
||||
-
|
||||
name: short-detected
|
||||
doc: Group of short_detected states
|
||||
-
|
||||
name: phy-upstream-type
|
||||
enum-name:
|
||||
type: enum
|
||||
entries: [ mac, phy ]
|
||||
-
|
||||
name: tcp-data-split
|
||||
type: enum
|
||||
entries: [ unknown, disabled, enabled ]
|
||||
|
||||
attribute-sets:
|
||||
-
|
||||
name: header
|
||||
attr-cnt-name: __ethtool-a-header-cnt
|
||||
attributes:
|
||||
-
|
||||
name: unspec
|
||||
type: unused
|
||||
value: 0
|
||||
-
|
||||
name: dev-index
|
||||
type: u32
|
||||
@ -65,7 +122,12 @@ attribute-sets:
|
||||
|
||||
-
|
||||
name: bitset-bit
|
||||
attr-cnt-name: __ethtool-a-bitset-bit-cnt
|
||||
attributes:
|
||||
-
|
||||
name: unspec
|
||||
type: unused
|
||||
value: 0
|
||||
-
|
||||
name: index
|
||||
type: u32
|
||||
@ -77,7 +139,12 @@ attribute-sets:
|
||||
type: flag
|
||||
-
|
||||
name: bitset-bits
|
||||
attr-cnt-name: __ethtool-a-bitset-bits-cnt
|
||||
attributes:
|
||||
-
|
||||
name: unspec
|
||||
type: unused
|
||||
value: 0
|
||||
-
|
||||
name: bit
|
||||
type: nest
|
||||
@ -85,7 +152,12 @@ attribute-sets:
|
||||
nested-attributes: bitset-bit
|
||||
-
|
||||
name: bitset
|
||||
attr-cnt-name: __ethtool-a-bitset-cnt
|
||||
attributes:
|
||||
-
|
||||
name: unspec
|
||||
type: unused
|
||||
value: 0
|
||||
-
|
||||
name: nomask
|
||||
type: flag
|
||||
@ -104,7 +176,12 @@ attribute-sets:
|
||||
type: binary
|
||||
-
|
||||
name: string
|
||||
attr-cnt-name: __ethtool-a-string-cnt
|
||||
attributes:
|
||||
-
|
||||
name: unspec
|
||||
type: unused
|
||||
value: 0
|
||||
-
|
||||
name: index
|
||||
type: u32
|
||||
@ -113,7 +190,16 @@ attribute-sets:
|
||||
type: string
|
||||
-
|
||||
name: strings
|
||||
attr-cnt-name: __ethtool-a-strings-cnt
|
||||
attributes:
|
||||
-
|
||||
name: unspec
|
||||
type: unused
|
||||
value: 0
|
||||
-
|
||||
name: unspec
|
||||
type: unused
|
||||
value: 0
|
||||
-
|
||||
name: string
|
||||
type: nest
|
||||
@ -121,7 +207,12 @@ attribute-sets:
|
||||
nested-attributes: string
|
||||
-
|
||||
name: stringset
|
||||
attr-cnt-name: __ethtool-a-stringset-cnt
|
||||
attributes:
|
||||
-
|
||||
name: unspec
|
||||
type: unused
|
||||
value: 0
|
||||
-
|
||||
name: id
|
||||
type: u32
|
||||
@ -135,7 +226,12 @@ attribute-sets:
|
||||
nested-attributes: strings
|
||||
-
|
||||
name: stringsets
|
||||
attr-cnt-name: __ethtool-a-stringsets-cnt
|
||||
attributes:
|
||||
-
|
||||
name: unspec
|
||||
type: unused
|
||||
value: 0
|
||||
-
|
||||
name: stringset
|
||||
type: nest
|
||||
@ -143,7 +239,12 @@ attribute-sets:
|
||||
nested-attributes: stringset
|
||||
-
|
||||
name: strset
|
||||
attr-cnt-name: __ethtool-a-strset-cnt
|
||||
attributes:
|
||||
-
|
||||
name: unspec
|
||||
type: unused
|
||||
value: 0
|
||||
-
|
||||
name: header
|
||||
type: nest
|
||||
@ -158,7 +259,12 @@ attribute-sets:
|
||||
|
||||
-
|
||||
name: privflags
|
||||
attr-cnt-name: __ethtool-a-privflags-cnt
|
||||
attributes:
|
||||
-
|
||||
name: unspec
|
||||
type: unused
|
||||
value: 0
|
||||
-
|
||||
name: header
|
||||
type: nest
|
||||
@ -170,7 +276,12 @@ attribute-sets:
|
||||
|
||||
-
|
||||
name: rings
|
||||
attr-cnt-name: __ethtool-a-rings-cnt
|
||||
attributes:
|
||||
-
|
||||
name: unspec
|
||||
type: unused
|
||||
value: 0
|
||||
-
|
||||
name: header
|
||||
type: nest
|
||||
@ -205,6 +316,7 @@ attribute-sets:
|
||||
-
|
||||
name: tcp-data-split
|
||||
type: u8
|
||||
enum: tcp-data-split
|
||||
-
|
||||
name: cqe-size
|
||||
type: u32
|
||||
@ -223,31 +335,48 @@ attribute-sets:
|
||||
|
||||
-
|
||||
name: mm-stat
|
||||
attr-cnt-name: __ethtool-a-mm-stat-cnt
|
||||
doc: MAC Merge (802.3)
|
||||
attributes:
|
||||
-
|
||||
name: unspec
|
||||
type: unused
|
||||
value: 0
|
||||
-
|
||||
name: pad
|
||||
type: pad
|
||||
-
|
||||
name: reassembly-errors
|
||||
doc: aMACMergeFrameAssErrorCount
|
||||
type: u64
|
||||
-
|
||||
name: smd-errors
|
||||
doc: aMACMergeFrameSmdErrorCount
|
||||
type: u64
|
||||
-
|
||||
name: reassembly-ok
|
||||
doc: aMACMergeFrameAssOkCount
|
||||
type: u64
|
||||
-
|
||||
name: rx-frag-count
|
||||
doc: aMACMergeFragCountRx
|
||||
type: u64
|
||||
-
|
||||
name: tx-frag-count
|
||||
doc: aMACMergeFragCountTx
|
||||
type: u64
|
||||
-
|
||||
name: hold-count
|
||||
doc: aMACMergeHoldCount
|
||||
type: u64
|
||||
-
|
||||
name: mm
|
||||
attr-cnt-name: __ethtool-a-mm-cnt
|
||||
attributes:
|
||||
-
|
||||
name: unspec
|
||||
type: unused
|
||||
value: 0
|
||||
-
|
||||
name: header
|
||||
type: nest
|
||||
@ -285,7 +414,12 @@ attribute-sets:
|
||||
nested-attributes: mm-stat
|
||||
-
|
||||
name: linkinfo
|
||||
attr-cnt-name: __ethtool-a-linkinfo-cnt
|
||||
attributes:
|
||||
-
|
||||
name: unspec
|
||||
type: unused
|
||||
value: 0
|
||||
-
|
||||
name: header
|
||||
type: nest
|
||||
@ -307,7 +441,12 @@ attribute-sets:
|
||||
type: u8
|
||||
-
|
||||
name: linkmodes
|
||||
attr-cnt-name: __ethtool-a-linkmodes-cnt
|
||||
attributes:
|
||||
-
|
||||
name: unspec
|
||||
type: unused
|
||||
value: 0
|
||||
-
|
||||
name: header
|
||||
type: nest
|
||||
@ -343,7 +482,12 @@ attribute-sets:
|
||||
type: u8
|
||||
-
|
||||
name: linkstate
|
||||
attr-cnt-name: __ethtool-a-linkstate-cnt
|
||||
attributes:
|
||||
-
|
||||
name: unspec
|
||||
type: unused
|
||||
value: 0
|
||||
-
|
||||
name: header
|
||||
type: nest
|
||||
@ -368,7 +512,12 @@ attribute-sets:
|
||||
type: u32
|
||||
-
|
||||
name: debug
|
||||
attr-cnt-name: __ethtool-a-debug-cnt
|
||||
attributes:
|
||||
-
|
||||
name: unspec
|
||||
type: unused
|
||||
value: 0
|
||||
-
|
||||
name: header
|
||||
type: nest
|
||||
@ -379,7 +528,12 @@ attribute-sets:
|
||||
nested-attributes: bitset
|
||||
-
|
||||
name: wol
|
||||
attr-cnt-name: __ethtool-a-wol-cnt
|
||||
attributes:
|
||||
-
|
||||
name: unspec
|
||||
type: unused
|
||||
value: 0
|
||||
-
|
||||
name: header
|
||||
type: nest
|
||||
@ -393,7 +547,12 @@ attribute-sets:
|
||||
type: binary
|
||||
-
|
||||
name: features
|
||||
attr-cnt-name: __ethtool-a-features-cnt
|
||||
attributes:
|
||||
-
|
||||
name: unspec
|
||||
type: unused
|
||||
value: 0
|
||||
-
|
||||
name: header
|
||||
type: nest
|
||||
@ -416,7 +575,12 @@ attribute-sets:
|
||||
nested-attributes: bitset
|
||||
-
|
||||
name: channels
|
||||
attr-cnt-name: __ethtool-a-channels-cnt
|
||||
attributes:
|
||||
-
|
||||
name: unspec
|
||||
type: unused
|
||||
value: 0
|
||||
-
|
||||
name: header
|
||||
type: nest
|
||||
@ -448,7 +612,12 @@ attribute-sets:
|
||||
|
||||
-
|
||||
name: irq-moderation
|
||||
attr-cnt-name: __ethtool-a-irq-moderation-cnt
|
||||
attributes:
|
||||
-
|
||||
name: unspec
|
||||
type: unused
|
||||
value: 0
|
||||
-
|
||||
name: usec
|
||||
type: u32
|
||||
@ -460,7 +629,12 @@ attribute-sets:
|
||||
type: u32
|
||||
-
|
||||
name: profile
|
||||
attr-cnt-name: __ethtool-a-profile-cnt
|
||||
attributes:
|
||||
-
|
||||
name: unspec
|
||||
type: unused
|
||||
value: 0
|
||||
-
|
||||
name: irq-moderation
|
||||
type: nest
|
||||
@ -468,7 +642,12 @@ attribute-sets:
|
||||
nested-attributes: irq-moderation
|
||||
-
|
||||
name: coalesce
|
||||
attr-cnt-name: __ethtool-a-coalesce-cnt
|
||||
attributes:
|
||||
-
|
||||
name: unspec
|
||||
type: unused
|
||||
value: 0
|
||||
-
|
||||
name: header
|
||||
type: nest
|
||||
@ -565,7 +744,12 @@ attribute-sets:
|
||||
|
||||
-
|
||||
name: pause-stat
|
||||
attr-cnt-name: __ethtool-a-pause-stat-cnt
|
||||
attributes:
|
||||
-
|
||||
name: unspec
|
||||
type: unused
|
||||
value: 0
|
||||
-
|
||||
name: pad
|
||||
type: pad
|
||||
@ -577,7 +761,12 @@ attribute-sets:
|
||||
type: u64
|
||||
-
|
||||
name: pause
|
||||
attr-cnt-name: __ethtool-a-pause-cnt
|
||||
attributes:
|
||||
-
|
||||
name: unspec
|
||||
type: unused
|
||||
value: 0
|
||||
-
|
||||
name: header
|
||||
type: nest
|
||||
@ -600,7 +789,12 @@ attribute-sets:
|
||||
type: u32
|
||||
-
|
||||
name: eee
|
||||
attr-cnt-name: __ethtool-a-eee-cnt
|
||||
attributes:
|
||||
-
|
||||
name: unspec
|
||||
type: unused
|
||||
value: 0
|
||||
-
|
||||
name: header
|
||||
type: nest
|
||||
@ -627,7 +821,12 @@ attribute-sets:
|
||||
type: u32
|
||||
-
|
||||
name: ts-stat
|
||||
attr-cnt-name: __ethtool-a-ts-stat-cnt
|
||||
attributes:
|
||||
-
|
||||
name: unspec
|
||||
type: unused
|
||||
value: 0
|
||||
-
|
||||
name: tx-pkts
|
||||
type: uint
|
||||
@ -638,8 +837,27 @@ attribute-sets:
|
||||
name: tx-err
|
||||
type: uint
|
||||
-
|
||||
name: tsinfo
|
||||
name: ts-hwtstamp-provider
|
||||
attr-cnt-name: __ethtool-a-ts-hwtstamp-provider-cnt
|
||||
attributes:
|
||||
-
|
||||
name: unspec
|
||||
type: unused
|
||||
value: 0
|
||||
-
|
||||
name: index
|
||||
type: u32
|
||||
-
|
||||
name: qualifier
|
||||
type: u32
|
||||
-
|
||||
name: tsinfo
|
||||
attr-cnt-name: __ethtool-a-tsinfo-cnt
|
||||
attributes:
|
||||
-
|
||||
name: unspec
|
||||
type: unused
|
||||
value: 0
|
||||
-
|
||||
name: header
|
||||
type: nest
|
||||
@ -663,21 +881,38 @@ attribute-sets:
|
||||
name: stats
|
||||
type: nest
|
||||
nested-attributes: ts-stat
|
||||
-
|
||||
name: hwtstamp-provider
|
||||
type: nest
|
||||
nested-attributes: ts-hwtstamp-provider
|
||||
-
|
||||
name: cable-result
|
||||
attr-cnt-name: __ethtool-a-cable-result-cnt
|
||||
attributes:
|
||||
-
|
||||
name: unspec
|
||||
type: unused
|
||||
value: 0
|
||||
-
|
||||
name: pair
|
||||
doc: ETHTOOL_A_CABLE_PAIR
|
||||
type: u8
|
||||
-
|
||||
name: code
|
||||
doc: ETHTOOL_A_CABLE_RESULT_CODE
|
||||
type: u8
|
||||
-
|
||||
name: src
|
||||
doc: ETHTOOL_A_CABLE_INF_SRC
|
||||
type: u32
|
||||
-
|
||||
name: cable-fault-length
|
||||
attr-cnt-name: __ethtool-a-cable-fault-length-cnt
|
||||
attributes:
|
||||
-
|
||||
name: unspec
|
||||
type: unused
|
||||
value: 0
|
||||
-
|
||||
name: pair
|
||||
type: u8
|
||||
@ -689,7 +924,12 @@ attribute-sets:
|
||||
type: u32
|
||||
-
|
||||
name: cable-nest
|
||||
attr-cnt-name: __ethtool-a-cable-nest-cnt
|
||||
attributes:
|
||||
-
|
||||
name: unspec
|
||||
type: unused
|
||||
value: 0
|
||||
-
|
||||
name: result
|
||||
type: nest
|
||||
@ -700,20 +940,31 @@ attribute-sets:
|
||||
nested-attributes: cable-fault-length
|
||||
-
|
||||
name: cable-test
|
||||
attr-cnt-name: __ethtool-a-cable-test-cnt
|
||||
attributes:
|
||||
-
|
||||
name: unspec
|
||||
type: unused
|
||||
value: 0
|
||||
-
|
||||
name: header
|
||||
type: nest
|
||||
nested-attributes: header
|
||||
-
|
||||
name: cable-test-ntf
|
||||
attr-cnt-name: __ethtool-a-cable-test-ntf-cnt
|
||||
attributes:
|
||||
-
|
||||
name: unspec
|
||||
type: unused
|
||||
value: 0
|
||||
-
|
||||
name: header
|
||||
type: nest
|
||||
nested-attributes: header
|
||||
-
|
||||
name: status
|
||||
doc: _STARTED/_COMPLETE
|
||||
type: u8
|
||||
-
|
||||
name: nest
|
||||
@ -721,7 +972,12 @@ attribute-sets:
|
||||
nested-attributes: cable-nest
|
||||
-
|
||||
name: cable-test-tdr-cfg
|
||||
attr-cnt-name: __ethtool-a-cable-test-tdr-cfg-cnt
|
||||
attributes:
|
||||
-
|
||||
name: unspec
|
||||
type: unused
|
||||
value: 0
|
||||
-
|
||||
name: first
|
||||
type: u32
|
||||
@ -736,7 +992,12 @@ attribute-sets:
|
||||
type: u8
|
||||
-
|
||||
name: cable-test-tdr-ntf
|
||||
attr-cnt-name: __ethtool-a-cable-test-tdr-ntf-cnt
|
||||
attributes:
|
||||
-
|
||||
name: unspec
|
||||
type: unused
|
||||
value: 0
|
||||
-
|
||||
name: header
|
||||
type: nest
|
||||
@ -750,7 +1011,12 @@ attribute-sets:
|
||||
nested-attributes: cable-nest
|
||||
-
|
||||
name: cable-test-tdr
|
||||
attr-cnt-name: __ethtool-a-cable-test-tdr-cnt
|
||||
attributes:
|
||||
-
|
||||
name: unspec
|
||||
type: unused
|
||||
value: 0
|
||||
-
|
||||
name: header
|
||||
type: nest
|
||||
@ -761,7 +1027,12 @@ attribute-sets:
|
||||
nested-attributes: cable-test-tdr-cfg
|
||||
-
|
||||
name: tunnel-udp-entry
|
||||
attr-cnt-name: __ethtool-a-tunnel-udp-entry-cnt
|
||||
attributes:
|
||||
-
|
||||
name: unspec
|
||||
type: unused
|
||||
value: 0
|
||||
-
|
||||
name: port
|
||||
type: u16
|
||||
@ -772,7 +1043,12 @@ attribute-sets:
|
||||
enum: udp-tunnel-type
|
||||
-
|
||||
name: tunnel-udp-table
|
||||
attr-cnt-name: __ethtool-a-tunnel-udp-table-cnt
|
||||
attributes:
|
||||
-
|
||||
name: unspec
|
||||
type: unused
|
||||
value: 0
|
||||
-
|
||||
name: size
|
||||
type: u32
|
||||
@ -787,14 +1063,24 @@ attribute-sets:
|
||||
nested-attributes: tunnel-udp-entry
|
||||
-
|
||||
name: tunnel-udp
|
||||
attr-cnt-name: __ethtool-a-tunnel-udp-cnt
|
||||
attributes:
|
||||
-
|
||||
name: unspec
|
||||
type: unused
|
||||
value: 0
|
||||
-
|
||||
name: table
|
||||
type: nest
|
||||
nested-attributes: tunnel-udp-table
|
||||
-
|
||||
name: tunnel-info
|
||||
attr-cnt-name: __ethtool-a-tunnel-info-cnt
|
||||
attributes:
|
||||
-
|
||||
name: unspec
|
||||
type: unused
|
||||
value: 0
|
||||
-
|
||||
name: header
|
||||
type: nest
|
||||
@ -805,7 +1091,12 @@ attribute-sets:
|
||||
nested-attributes: tunnel-udp
|
||||
-
|
||||
name: fec-stat
|
||||
attr-cnt-name: __ethtool-a-fec-stat-cnt
|
||||
attributes:
|
||||
-
|
||||
name: unspec
|
||||
type: unused
|
||||
value: 0
|
||||
-
|
||||
name: pad
|
||||
type: pad
|
||||
@ -823,7 +1114,12 @@ attribute-sets:
|
||||
sub-type: u64
|
||||
-
|
||||
name: fec
|
||||
attr-cnt-name: __ethtool-a-fec-cnt
|
||||
attributes:
|
||||
-
|
||||
name: unspec
|
||||
type: unused
|
||||
value: 0
|
||||
-
|
||||
name: header
|
||||
type: nest
|
||||
@ -844,7 +1140,12 @@ attribute-sets:
|
||||
nested-attributes: fec-stat
|
||||
-
|
||||
name: module-eeprom
|
||||
attr-cnt-name: __ethtool-a-module-eeprom-cnt
|
||||
attributes:
|
||||
-
|
||||
name: unspec
|
||||
type: unused
|
||||
value: 0
|
||||
-
|
||||
name: header
|
||||
type: nest
|
||||
@ -869,7 +1170,12 @@ attribute-sets:
|
||||
type: binary
|
||||
-
|
||||
name: stats-grp
|
||||
attr-cnt-name: __ethtool-a-stats-grp-cnt
|
||||
attributes:
|
||||
-
|
||||
name: unspec
|
||||
type: unused
|
||||
value: 0
|
||||
-
|
||||
name: pad
|
||||
type: pad
|
||||
@ -912,7 +1218,12 @@ attribute-sets:
|
||||
name: hist-val
|
||||
-
|
||||
name: stats
|
||||
attr-cnt-name: __ethtool-a-stats-cnt
|
||||
attributes:
|
||||
-
|
||||
name: unspec
|
||||
type: unused
|
||||
value: 0
|
||||
-
|
||||
name: pad
|
||||
type: pad
|
||||
@ -933,7 +1244,12 @@ attribute-sets:
|
||||
type: u32
|
||||
-
|
||||
name: phc-vclocks
|
||||
attr-cnt-name: __ethtool-a-phc-vclocks-cnt
|
||||
attributes:
|
||||
-
|
||||
name: unspec
|
||||
type: unused
|
||||
value: 0
|
||||
-
|
||||
name: header
|
||||
type: nest
|
||||
@ -947,7 +1263,12 @@ attribute-sets:
|
||||
sub-type: s32
|
||||
-
|
||||
name: module
|
||||
attr-cnt-name: __ethtool-a-module-cnt
|
||||
attributes:
|
||||
-
|
||||
name: unspec
|
||||
type: unused
|
||||
value: 0
|
||||
-
|
||||
name: header
|
||||
type: nest
|
||||
@ -960,7 +1281,13 @@ attribute-sets:
|
||||
type: u8
|
||||
-
|
||||
name: c33-pse-pw-limit
|
||||
attr-cnt-name: __ethtool-a-c33-pse-pw-limit-cnt
|
||||
attr-max-name: __ethtool-a-c33-pse-pw-limit-max
|
||||
attributes:
|
||||
-
|
||||
name: unspec
|
||||
type: unused
|
||||
value: 0
|
||||
-
|
||||
name: min
|
||||
type: u32
|
||||
@ -969,7 +1296,12 @@ attribute-sets:
|
||||
type: u32
|
||||
-
|
||||
name: pse
|
||||
attr-cnt-name: __ethtool-a-pse-cnt
|
||||
attributes:
|
||||
-
|
||||
name: unspec
|
||||
type: unused
|
||||
value: 0
|
||||
-
|
||||
name: header
|
||||
type: nest
|
||||
@ -1027,7 +1359,12 @@ attribute-sets:
|
||||
nested-attributes: c33-pse-pw-limit
|
||||
-
|
||||
name: rss
|
||||
attr-cnt-name: __ethtool-a-rss-cnt
|
||||
attributes:
|
||||
-
|
||||
name: unspec
|
||||
type: unused
|
||||
value: 0
|
||||
-
|
||||
name: header
|
||||
type: nest
|
||||
@ -1053,7 +1390,12 @@ attribute-sets:
|
||||
type: u32
|
||||
-
|
||||
name: plca
|
||||
attr-cnt-name: __ethtool-a-plca-cnt
|
||||
attributes:
|
||||
-
|
||||
name: unspec
|
||||
type: unused
|
||||
value: 0
|
||||
-
|
||||
name: header
|
||||
type: nest
|
||||
@ -1084,7 +1426,12 @@ attribute-sets:
|
||||
type: u32
|
||||
-
|
||||
name: module-fw-flash
|
||||
attr-cnt-name: __ethtool-a-module-fw-flash-cnt
|
||||
attributes:
|
||||
-
|
||||
name: unspec
|
||||
type: unused
|
||||
value: 0
|
||||
-
|
||||
name: header
|
||||
type: nest
|
||||
@ -1110,7 +1457,12 @@ attribute-sets:
|
||||
type: uint
|
||||
-
|
||||
name: phy
|
||||
attr-cnt-name: __ethtool-a-phy-cnt
|
||||
attributes:
|
||||
-
|
||||
name: unspec
|
||||
type: unused
|
||||
value: 0
|
||||
-
|
||||
name: header
|
||||
type: nest
|
||||
@ -1137,6 +1489,33 @@ attribute-sets:
|
||||
-
|
||||
name: downstream-sfp-name
|
||||
type: string
|
||||
-
|
||||
name: tsconfig
|
||||
attr-cnt-name: __ethtool-a-tsconfig-cnt
|
||||
attributes:
|
||||
-
|
||||
name: unspec
|
||||
type: unused
|
||||
value: 0
|
||||
-
|
||||
name: header
|
||||
type: nest
|
||||
nested-attributes: header
|
||||
-
|
||||
name: hwtstamp-provider
|
||||
type: nest
|
||||
nested-attributes: ts-hwtstamp-provider
|
||||
-
|
||||
name: tx-types
|
||||
type: nest
|
||||
nested-attributes: bitset
|
||||
-
|
||||
name: rx-filters
|
||||
type: nest
|
||||
nested-attributes: bitset
|
||||
-
|
||||
name: hwtstamp-flags
|
||||
type: u32
|
||||
|
||||
operations:
|
||||
enum-model: directional
|
||||
@ -1578,6 +1957,7 @@ operations:
|
||||
request:
|
||||
attributes:
|
||||
- header
|
||||
- hwtstamp-provider
|
||||
reply:
|
||||
attributes:
|
||||
- header
|
||||
@ -1586,6 +1966,7 @@ operations:
|
||||
- rx-filters
|
||||
- phc-index
|
||||
- stats
|
||||
- hwtstamp-provider
|
||||
dump: *tsinfo-get-op
|
||||
-
|
||||
name: cable-test-act
|
||||
@ -1960,3 +2341,32 @@ operations:
|
||||
name: phy-ntf
|
||||
doc: Notification for change in PHY devices.
|
||||
notify: phy-get
|
||||
-
|
||||
name: tsconfig-get
|
||||
doc: Get hwtstamp config.
|
||||
|
||||
attribute-set: tsconfig
|
||||
|
||||
do: &tsconfig-get-op
|
||||
request:
|
||||
attributes:
|
||||
- header
|
||||
reply:
|
||||
attributes: &tsconfig
|
||||
- header
|
||||
- hwtstamp-provider
|
||||
- tx-types
|
||||
- rx-filters
|
||||
- hwtstamp-flags
|
||||
dump: *tsconfig-get-op
|
||||
-
|
||||
name: tsconfig-set
|
||||
doc: Set hwtstamp config.
|
||||
|
||||
attribute-set: tsconfig
|
||||
|
||||
do:
|
||||
request:
|
||||
attributes: *tsconfig
|
||||
reply:
|
||||
attributes: *tsconfig
|
||||
|
@ -1825,6 +1825,48 @@ attribute-sets:
|
||||
-
|
||||
name: erspan-hwid
|
||||
type: u16
|
||||
-
|
||||
name: linkinfo-vti-attrs
|
||||
name-prefix: ifla-vti-
|
||||
attributes:
|
||||
-
|
||||
name: link
|
||||
type: u32
|
||||
-
|
||||
name: ikey
|
||||
type: u32
|
||||
-
|
||||
name: okey
|
||||
type: u32
|
||||
-
|
||||
name: local
|
||||
type: binary
|
||||
display-hint: ipv4
|
||||
-
|
||||
name: remote
|
||||
type: binary
|
||||
display-hint: ipv4
|
||||
-
|
||||
name: fwmark
|
||||
type: u32
|
||||
-
|
||||
name: linkinfo-vti6-attrs
|
||||
subset-of: linkinfo-vti-attrs
|
||||
attributes:
|
||||
-
|
||||
name: link
|
||||
-
|
||||
name: ikey
|
||||
-
|
||||
name: okey
|
||||
-
|
||||
name: local
|
||||
display-hint: ipv6
|
||||
-
|
||||
name: remote
|
||||
display-hint: ipv6
|
||||
-
|
||||
name: fwmark
|
||||
-
|
||||
name: linkinfo-geneve-attrs
|
||||
name-prefix: ifla-geneve-
|
||||
@ -1941,6 +1983,42 @@ attribute-sets:
|
||||
-
|
||||
name: fwmark
|
||||
type: u32
|
||||
-
|
||||
name: linkinfo-ip6tnl-attrs
|
||||
subset-of: linkinfo-iptun-attrs
|
||||
attributes:
|
||||
-
|
||||
name: link
|
||||
-
|
||||
name: local
|
||||
display-hint: ipv6
|
||||
-
|
||||
name: remote
|
||||
display-hint: ipv6
|
||||
-
|
||||
name: ttl
|
||||
-
|
||||
name: encap-limit
|
||||
-
|
||||
name: flowinfo
|
||||
-
|
||||
name: flags
|
||||
# ip6tnl unlike ipip and sit has 32b flags
|
||||
type: u32
|
||||
-
|
||||
name: proto
|
||||
-
|
||||
name: encap-type
|
||||
-
|
||||
name: encap-flags
|
||||
-
|
||||
name: encap-sport
|
||||
-
|
||||
name: encap-dport
|
||||
-
|
||||
name: collect-metadata
|
||||
-
|
||||
name: fwmark
|
||||
-
|
||||
name: linkinfo-tun-attrs
|
||||
name-prefix: ifla-tun-
|
||||
@ -2086,6 +2164,9 @@ attribute-sets:
|
||||
-
|
||||
name: mctp-net
|
||||
type: u32
|
||||
-
|
||||
name: phys-binding
|
||||
type: u8
|
||||
-
|
||||
name: stats-attrs
|
||||
name-prefix: ifla-stats-
|
||||
@ -2166,6 +2247,12 @@ attribute-sets:
|
||||
name: peer-scrub
|
||||
type: u32
|
||||
enum: netkit-scrub
|
||||
-
|
||||
name: headroom
|
||||
type: u16
|
||||
-
|
||||
name: tailroom
|
||||
type: u16
|
||||
|
||||
sub-messages:
|
||||
-
|
||||
@ -2192,6 +2279,9 @@ sub-messages:
|
||||
-
|
||||
value: ipip
|
||||
attribute-set: linkinfo-iptun-attrs
|
||||
-
|
||||
value: ip6tnl
|
||||
attribute-set: linkinfo-ip6tnl-attrs
|
||||
-
|
||||
value: sit
|
||||
attribute-set: linkinfo-iptun-attrs
|
||||
@ -2204,6 +2294,12 @@ sub-messages:
|
||||
-
|
||||
value: vrf
|
||||
attribute-set: linkinfo-vrf-attrs
|
||||
-
|
||||
value: vti
|
||||
attribute-set: linkinfo-vti-attrs
|
||||
-
|
||||
value: vti6
|
||||
attribute-set: linkinfo-vti6-attrs
|
||||
-
|
||||
value: netkit
|
||||
attribute-set: linkinfo-netkit-attrs
|
||||
|
@ -177,6 +177,11 @@ attribute-sets:
|
||||
-
|
||||
name: rta-nh-id
|
||||
type: u32
|
||||
-
|
||||
name: rta-flowlabel
|
||||
type: u32
|
||||
byte-order: big-endian
|
||||
display-hint: hex
|
||||
-
|
||||
name: rta-metrics
|
||||
attributes:
|
||||
@ -260,6 +265,7 @@ operations:
|
||||
- rta-dport
|
||||
- rta-mark
|
||||
- rta-uid
|
||||
- rta-flowlabel
|
||||
reply:
|
||||
value: 24
|
||||
attributes: &all-route-attrs
|
||||
@ -299,6 +305,7 @@ operations:
|
||||
- rta-sport
|
||||
- rta-dport
|
||||
- rta-nh-id
|
||||
- rta-flowlabel
|
||||
dump:
|
||||
request:
|
||||
value: 26
|
||||
|
@ -172,6 +172,16 @@ attribute-sets:
|
||||
-
|
||||
name: dscp
|
||||
type: u8
|
||||
-
|
||||
name: flowlabel
|
||||
type: u32
|
||||
byte-order: big-endian
|
||||
display-hint: hex
|
||||
-
|
||||
name: flowlabel-mask
|
||||
type: u32
|
||||
byte-order: big-endian
|
||||
display-hint: hex
|
||||
|
||||
operations:
|
||||
enum-model: directional
|
||||
@ -203,6 +213,8 @@ operations:
|
||||
- sport-range
|
||||
- dport-range
|
||||
- dscp
|
||||
- flowlabel
|
||||
- flowlabel-mask
|
||||
-
|
||||
name: newrule-ntf
|
||||
doc: Notify a rule creation
|
||||
|
@ -1963,7 +1963,7 @@ obtain its hardware address from the first slave, which might not
|
||||
match the hardware address of the VLAN interfaces (which was
|
||||
ultimately copied from an earlier slave).
|
||||
|
||||
There are two methods to insure that the VLAN device operates
|
||||
There are two methods to ensure that the VLAN device operates
|
||||
with the correct hardware address if all slaves are removed from a
|
||||
bond interface:
|
||||
|
||||
@ -2078,7 +2078,7 @@ as an unsolicited ARP reply (because ARP matches replies on an
|
||||
interface basis), and is discarded. The MII monitor is not affected
|
||||
by the state of the routing table.
|
||||
|
||||
The solution here is simply to insure that slaves do not have
|
||||
The solution here is simply to ensure that slaves do not have
|
||||
routes of their own, and if for some reason they must, those routes do
|
||||
not supersede routes of their master. This should generally be the
|
||||
case, but unusual configurations or errant manual or automatic static
|
||||
@ -2295,7 +2295,7 @@ active-backup:
|
||||
the switches have an ISL and play together well. If the
|
||||
network configuration is such that one switch is specifically
|
||||
a backup switch (e.g., has lower capacity, higher cost, etc),
|
||||
then the primary option can be used to insure that the
|
||||
then the primary option can be used to ensure that the
|
||||
preferred link is always used when it is available.
|
||||
|
||||
broadcast:
|
||||
@ -2322,7 +2322,7 @@ monitor can provide a higher level of reliability in detecting end to
|
||||
end connectivity failures (which may be caused by the failure of any
|
||||
individual component to pass traffic for any reason). Additionally,
|
||||
the ARP monitor should be configured with multiple targets (at least
|
||||
one for each switch in the network). This will insure that,
|
||||
one for each switch in the network). This will ensure that,
|
||||
regardless of which switch is active, the ARP monitor has a suitable
|
||||
target to query.
|
||||
|
||||
|
@ -299,6 +299,18 @@ Use ethtool to view and set link-down-on-close, as follows::
|
||||
ethtool --show-priv-flags ethX
|
||||
ethtool --set-priv-flags ethX link-down-on-close [on|off]
|
||||
|
||||
Setting the mdd-auto-reset-vf Private Flag
|
||||
------------------------------------------
|
||||
|
||||
When the mdd-auto-reset-vf private flag is set to "on", the problematic VF will
|
||||
be automatically reset if a malformed descriptor is detected. If the flag is
|
||||
set to "off", the problematic VF will be disabled.
|
||||
|
||||
Use ethtool to view and set mdd-auto-reset-vf, as follows::
|
||||
|
||||
ethtool --show-priv-flags ethX
|
||||
ethtool --set-priv-flags ethX mdd-auto-reset-vf [on|off]
|
||||
|
||||
Viewing Link Messages
|
||||
---------------------
|
||||
Link messages will not be displayed to the console if the distribution is
|
||||
|
@ -237,6 +237,8 @@ Userspace to kernel:
|
||||
``ETHTOOL_MSG_MM_SET`` set MAC merge layer parameters
|
||||
``ETHTOOL_MSG_MODULE_FW_FLASH_ACT`` flash transceiver module firmware
|
||||
``ETHTOOL_MSG_PHY_GET`` get Ethernet PHY information
|
||||
``ETHTOOL_MSG_TSCONFIG_GET`` get hw timestamping configuration
|
||||
``ETHTOOL_MSG_TSCONFIG_SET`` set hw timestamping configuration
|
||||
===================================== =================================
|
||||
|
||||
Kernel to userspace:
|
||||
@ -286,6 +288,8 @@ Kernel to userspace:
|
||||
``ETHTOOL_MSG_MODULE_FW_FLASH_NTF`` transceiver module flash updates
|
||||
``ETHTOOL_MSG_PHY_GET_REPLY`` Ethernet PHY information
|
||||
``ETHTOOL_MSG_PHY_NTF`` Ethernet PHY information change
|
||||
``ETHTOOL_MSG_TSCONFIG_GET_REPLY`` hw timestamping configuration
|
||||
``ETHTOOL_MSG_TSCONFIG_SET_REPLY`` new hw timestamping configuration
|
||||
======================================== =================================
|
||||
|
||||
``GET`` requests are sent by userspace applications to retrieve device
|
||||
@ -1245,9 +1249,10 @@ Gets timestamping information like ``ETHTOOL_GET_TS_INFO`` ioctl request.
|
||||
|
||||
Request contents:
|
||||
|
||||
===================================== ====== ==========================
|
||||
======================================== ====== ============================
|
||||
``ETHTOOL_A_TSINFO_HEADER`` nested request header
|
||||
===================================== ====== ==========================
|
||||
``ETHTOOL_A_TSINFO_HWTSTAMP_PROVIDER`` nested PTP hw clock provider
|
||||
======================================== ====== ============================
|
||||
|
||||
Kernel response contents:
|
||||
|
||||
@ -2243,6 +2248,75 @@ Kernel response contents:
|
||||
When ``ETHTOOL_A_PHY_UPSTREAM_TYPE`` is PHY_UPSTREAM_PHY, the PHY's parent is
|
||||
another PHY.
|
||||
|
||||
TSCONFIG_GET
|
||||
============
|
||||
|
||||
Retrieves the information about the current hardware timestamping source and
|
||||
configuration.
|
||||
|
||||
It is similar to the deprecated ``SIOCGHWTSTAMP`` ioctl request.
|
||||
|
||||
Request contents:
|
||||
|
||||
==================================== ====== ==========================
|
||||
``ETHTOOL_A_TSCONFIG_HEADER`` nested request header
|
||||
==================================== ====== ==========================
|
||||
|
||||
Kernel response contents:
|
||||
|
||||
======================================== ====== ============================
|
||||
``ETHTOOL_A_TSCONFIG_HEADER`` nested request header
|
||||
``ETHTOOL_A_TSCONFIG_HWTSTAMP_PROVIDER`` nested PTP hw clock provider
|
||||
``ETHTOOL_A_TSCONFIG_TX_TYPES`` bitset hwtstamp Tx type
|
||||
``ETHTOOL_A_TSCONFIG_RX_FILTERS`` bitset hwtstamp Rx filter
|
||||
``ETHTOOL_A_TSCONFIG_HWTSTAMP_FLAGS`` u32 hwtstamp flags
|
||||
======================================== ====== ============================
|
||||
|
||||
When set the ``ETHTOOL_A_TSCONFIG_HWTSTAMP_PROVIDER`` attribute identifies the
|
||||
source of the hw timestamping provider. It is composed by
|
||||
``ETHTOOL_A_TS_HWTSTAMP_PROVIDER_INDEX`` attribute which describe the index of
|
||||
the PTP device and ``ETHTOOL_A_TS_HWTSTAMP_PROVIDER_QUALIFIER`` which describe
|
||||
the qualifier of the timestamp.
|
||||
|
||||
When set the ``ETHTOOL_A_TSCONFIG_TX_TYPES``, ``ETHTOOL_A_TSCONFIG_RX_FILTERS``
|
||||
and the ``ETHTOOL_A_TSCONFIG_HWTSTAMP_FLAGS`` attributes identify the Tx
|
||||
type, the Rx filter and the flags configured for the current hw timestamping
|
||||
provider. The attributes are propagated to the driver through the following
|
||||
structure:
|
||||
|
||||
.. kernel-doc:: include/linux/net_tstamp.h
|
||||
:identifiers: kernel_hwtstamp_config
|
||||
|
||||
TSCONFIG_SET
|
||||
============
|
||||
|
||||
Set the information about the current hardware timestamping source and
|
||||
configuration.
|
||||
|
||||
It is similar to the deprecated ``SIOCSHWTSTAMP`` ioctl request.
|
||||
|
||||
Request contents:
|
||||
|
||||
======================================== ====== ============================
|
||||
``ETHTOOL_A_TSCONFIG_HEADER`` nested request header
|
||||
``ETHTOOL_A_TSCONFIG_HWTSTAMP_PROVIDER`` nested PTP hw clock provider
|
||||
``ETHTOOL_A_TSCONFIG_TX_TYPES`` bitset hwtstamp Tx type
|
||||
``ETHTOOL_A_TSCONFIG_RX_FILTERS`` bitset hwtstamp Rx filter
|
||||
``ETHTOOL_A_TSCONFIG_HWTSTAMP_FLAGS`` u32 hwtstamp flags
|
||||
======================================== ====== ============================
|
||||
|
||||
Kernel response contents:
|
||||
|
||||
======================================== ====== ============================
|
||||
``ETHTOOL_A_TSCONFIG_HEADER`` nested request header
|
||||
``ETHTOOL_A_TSCONFIG_HWTSTAMP_PROVIDER`` nested PTP hw clock provider
|
||||
``ETHTOOL_A_TSCONFIG_TX_TYPES`` bitset hwtstamp Tx type
|
||||
``ETHTOOL_A_TSCONFIG_RX_FILTERS`` bitset hwtstamp Rx filter
|
||||
``ETHTOOL_A_TSCONFIG_HWTSTAMP_FLAGS`` u32 hwtstamp flags
|
||||
======================================== ====== ============================
|
||||
|
||||
For a description of each attribute, see ``TSCONFIG_GET``.
|
||||
|
||||
Request translation
|
||||
===================
|
||||
|
||||
@ -2351,4 +2425,6 @@ are netlink only.
|
||||
n/a ``ETHTOOL_MSG_MM_SET``
|
||||
n/a ``ETHTOOL_MSG_MODULE_FW_FLASH_ACT``
|
||||
n/a ``ETHTOOL_MSG_PHY_GET``
|
||||
``SIOCGHWTSTAMP`` ``ETHTOOL_MSG_TSCONFIG_GET``
|
||||
``SIOCSHWTSTAMP`` ``ETHTOOL_MSG_TSCONFIG_SET``
|
||||
=================================== =====================================
|
||||
|
@ -72,7 +72,8 @@ exports a management (e.g. MLME) and data API.
|
||||
possibly with some kinds of acceleration like automatic CRC computation and
|
||||
comparison, automagic ACK handling, address matching, etc.
|
||||
|
||||
Those types of devices require different approach to be hooked into Linux kernel.
|
||||
Each type of device requires a different approach to be hooked into the Linux
|
||||
kernel.
|
||||
|
||||
HardMAC
|
||||
-------
|
||||
@ -81,10 +82,10 @@ See the header include/net/ieee802154_netdev.h. You have to implement Linux
|
||||
net_device, with .type = ARPHRD_IEEE802154. Data is exchanged with socket family
|
||||
code via plain sk_buffs. On skb reception skb->cb must contain additional
|
||||
info as described in the struct ieee802154_mac_cb. During packet transmission
|
||||
the skb->cb is used to provide additional data to device's header_ops->create
|
||||
function. Be aware that this data can be overridden later (when socket code
|
||||
submits skb to qdisc), so if you need something from that cb later, you should
|
||||
store info in the skb->data on your own.
|
||||
the skb->cb is used to provide additional data to the device's
|
||||
header_ops->create function. Be aware that this data can be overridden later
|
||||
(when socket code submits skb to qdisc), so if you need something from that cb
|
||||
later, you should store info in the skb->data on your own.
|
||||
|
||||
To hook the MLME interface you have to populate the ml_priv field of your
|
||||
net_device with a pointer to struct ieee802154_mlme_ops instance. The fields
|
||||
@ -94,8 +95,9 @@ All other fields are required.
|
||||
SoftMAC
|
||||
-------
|
||||
|
||||
The MAC is the middle layer in the IEEE 802.15.4 Linux stack. This moment it
|
||||
provides interface for drivers registration and management of slave interfaces.
|
||||
The MAC is the middle layer in the IEEE 802.15.4 Linux stack. At the moment, it
|
||||
provides an interface for driver registration and management of slave
|
||||
interfaces.
|
||||
|
||||
NOTE: Currently the only monitor device type is supported - it's IEEE 802.15.4
|
||||
stack interface for network sniffers (e.g. WireShark).
|
||||
|
@ -86,6 +86,7 @@ Contents:
|
||||
netdevices
|
||||
netfilter-sysctl
|
||||
netif-msg
|
||||
netmem
|
||||
nexthop-group-resilient
|
||||
nf_conntrack-sysctl
|
||||
nf_flowtable
|
||||
|
@ -1000,6 +1000,20 @@ tcp_tw_reuse - INTEGER
|
||||
|
||||
Default: 2
|
||||
|
||||
tcp_tw_reuse_delay - UNSIGNED INTEGER
|
||||
The delay in milliseconds before a TIME-WAIT socket can be reused by a
|
||||
new connection, if TIME-WAIT socket reuse is enabled. The actual reuse
|
||||
threshold is within [N, N+1] range, where N is the requested delay in
|
||||
milliseconds, to ensure the delay interval is never shorter than the
|
||||
configured value.
|
||||
|
||||
This setting contains an assumption about the other TCP timestamp clock
|
||||
tick interval. It should not be set to a value lower than the peer's
|
||||
clock tick for PAWS (Protection Against Wrapped Sequence numbers)
|
||||
mechanism work correctly for the reused connection.
|
||||
|
||||
Default: 1000 (milliseconds)
|
||||
|
||||
tcp_window_scaling - BOOLEAN
|
||||
Enable window scaling as defined in RFC1323.
|
||||
|
||||
|
@ -89,7 +89,7 @@ Observability
|
||||
=============
|
||||
The relation between PF, irq, napi, and queue can be observed via netlink spec::
|
||||
|
||||
$ ./tools/net/ynl/cli.py --spec Documentation/netlink/specs/netdev.yaml --dump queue-get --json='{"ifindex": 13}'
|
||||
$ ./tools/net/ynl/pyynl/cli.py --spec Documentation/netlink/specs/netdev.yaml --dump queue-get --json='{"ifindex": 13}'
|
||||
[{'id': 0, 'ifindex': 13, 'napi-id': 539, 'type': 'rx'},
|
||||
{'id': 1, 'ifindex': 13, 'napi-id': 540, 'type': 'rx'},
|
||||
{'id': 2, 'ifindex': 13, 'napi-id': 541, 'type': 'rx'},
|
||||
@ -101,7 +101,7 @@ The relation between PF, irq, napi, and queue can be observed via netlink spec::
|
||||
{'id': 3, 'ifindex': 13, 'napi-id': 542, 'type': 'tx'},
|
||||
{'id': 4, 'ifindex': 13, 'napi-id': 543, 'type': 'tx'}]
|
||||
|
||||
$ ./tools/net/ynl/cli.py --spec Documentation/netlink/specs/netdev.yaml --dump napi-get --json='{"ifindex": 13}'
|
||||
$ ./tools/net/ynl/pyynl/cli.py --spec Documentation/netlink/specs/netdev.yaml --dump napi-get --json='{"ifindex": 13}'
|
||||
[{'id': 543, 'ifindex': 13, 'irq': 42},
|
||||
{'id': 542, 'ifindex': 13, 'irq': 41},
|
||||
{'id': 541, 'ifindex': 13, 'irq': 40},
|
||||
|
@ -199,13 +199,13 @@ parameters mentioned above use hyphens instead of underscores:
|
||||
|
||||
Per-NAPI configuration can be done programmatically in a user application
|
||||
or by using a script included in the kernel source tree:
|
||||
``tools/net/ynl/cli.py``.
|
||||
``tools/net/ynl/pyynl/cli.py``.
|
||||
|
||||
For example, using the script:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ kernel-source/tools/net/ynl/cli.py \
|
||||
$ kernel-source/tools/net/ynl/pyynl/cli.py \
|
||||
--spec Documentation/netlink/specs/netdev.yaml \
|
||||
--do napi-set \
|
||||
--json='{"id": 345,
|
||||
|
@ -79,6 +79,7 @@ u8 sysctl_tcp_retries1
|
||||
u8 sysctl_tcp_retries2
|
||||
u8 sysctl_tcp_orphan_retries
|
||||
u8 sysctl_tcp_tw_reuse timewait_sock_ops
|
||||
unsigned_int sysctl_tcp_tw_reuse_delay timewait_sock_ops
|
||||
int sysctl_tcp_fin_timeout TCP_LAST_ACK/tcp_rcv_state_process
|
||||
unsigned_int sysctl_tcp_notsent_lowat read_mostly tcp_notsent_lowat/tcp_stream_memory_free
|
||||
u8 sysctl_tcp_sack tcp_syn_options
|
||||
|
@ -124,7 +124,7 @@ To remove a target::
|
||||
|
||||
The interface exposes these parameters of a netconsole target to userspace:
|
||||
|
||||
============== ================================= ============
|
||||
=============== ================================= ============
|
||||
enabled Is this target currently enabled? (read-write)
|
||||
extended Extended mode enabled (read-write)
|
||||
release Prepend kernel release to message (read-write)
|
||||
@ -135,7 +135,8 @@ The interface exposes these parameters of a netconsole target to userspace:
|
||||
remote_ip Remote agent's IP address (read-write)
|
||||
local_mac Local interface's MAC address (read-only)
|
||||
remote_mac Remote agent's MAC address (read-write)
|
||||
============== ================================= ============
|
||||
transmit_errors Number of packet send errors (read-only)
|
||||
=============== ================================= ============
|
||||
|
||||
The "enabled" attribute is also used to control whether the parameters of
|
||||
a target can be updated or not -- you can modify the parameters of only
|
||||
|
@ -297,3 +297,13 @@ napi->poll:
|
||||
Context:
|
||||
softirq
|
||||
will be called with interrupts disabled by netconsole.
|
||||
|
||||
NETDEV_INTERNAL symbol namespace
|
||||
================================
|
||||
|
||||
Symbols exported as NETDEV_INTERNAL can only be used in networking
|
||||
core and drivers which exclusively flow via the main networking list and trees.
|
||||
Note that the inverse is not true, most symbols outside of NETDEV_INTERNAL
|
||||
are not expected to be used by random code outside netdev either.
|
||||
Symbols may lack the designation because they predate the namespaces,
|
||||
or simply due to an oversight.
|
||||
|
@ -1,4 +1,4 @@
|
||||
SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
This file is populated during the build of the documentation (htmldocs) by the
|
||||
tools/net/ynl/ynl-gen-rst.py script.
|
||||
tools/net/ynl/pyynl/ynl_gen_rst.py script.
|
||||
|
79
Documentation/networking/netmem.rst
Normal file
79
Documentation/networking/netmem.rst
Normal file
@ -0,0 +1,79 @@
|
||||
.. SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
==================================
|
||||
Netmem Support for Network Drivers
|
||||
==================================
|
||||
|
||||
This document outlines the requirements for network drivers to support netmem,
|
||||
an abstract memory type that enables features like device memory TCP. By
|
||||
supporting netmem, drivers can work with various underlying memory types
|
||||
with little to no modification.
|
||||
|
||||
Benefits of Netmem :
|
||||
|
||||
* Flexibility: Netmem can be backed by different memory types (e.g., struct
|
||||
page, DMA-buf), allowing drivers to support various use cases such as device
|
||||
memory TCP.
|
||||
* Future-proof: Drivers with netmem support are ready for upcoming
|
||||
features that rely on it.
|
||||
* Simplified Development: Drivers interact with a consistent API,
|
||||
regardless of the underlying memory implementation.
|
||||
|
||||
Driver Requirements
|
||||
===================
|
||||
|
||||
1. The driver must support page_pool.
|
||||
|
||||
2. The driver must support the tcp-data-split ethtool option.
|
||||
|
||||
3. The driver must use the page_pool netmem APIs for payload memory. The netmem
|
||||
APIs currently 1-to-1 correspond with page APIs. Conversion to netmem should
|
||||
be achievable by switching the page APIs to netmem APIs and tracking memory
|
||||
via netmem_refs in the driver rather than struct page * :
|
||||
|
||||
- page_pool_alloc -> page_pool_alloc_netmem
|
||||
- page_pool_get_dma_addr -> page_pool_get_dma_addr_netmem
|
||||
- page_pool_put_page -> page_pool_put_netmem
|
||||
|
||||
Not all page APIs have netmem equivalents at the moment. If your driver
|
||||
relies on a missing netmem API, feel free to add and propose to netdev@, or
|
||||
reach out to the maintainers and/or almasrymina@google.com for help adding
|
||||
the netmem API.
|
||||
|
||||
4. The driver must use the following PP_FLAGS:
|
||||
|
||||
- PP_FLAG_DMA_MAP: netmem is not dma-mappable by the driver. The driver
|
||||
must delegate the dma mapping to the page_pool, which knows when
|
||||
dma-mapping is (or is not) appropriate.
|
||||
- PP_FLAG_DMA_SYNC_DEV: netmem dma addr is not necessarily dma-syncable
|
||||
by the driver. The driver must delegate the dma syncing to the page_pool,
|
||||
which knows when dma-syncing is (or is not) appropriate.
|
||||
- PP_FLAG_ALLOW_UNREADABLE_NETMEM. The driver must specify this flag iff
|
||||
tcp-data-split is enabled.
|
||||
|
||||
5. The driver must not assume the netmem is readable and/or backed by pages.
|
||||
The netmem returned by the page_pool may be unreadable, in which case
|
||||
netmem_address() will return NULL. The driver must correctly handle
|
||||
unreadable netmem, i.e. don't attempt to handle its contents when
|
||||
netmem_address() is NULL.
|
||||
|
||||
Ideally, drivers should not have to check the underlying netmem type via
|
||||
helpers like netmem_is_net_iov() or convert the netmem to any of its
|
||||
underlying types via netmem_to_page() or netmem_to_net_iov(). In most cases,
|
||||
netmem or page_pool helpers that abstract this complexity are provided
|
||||
(and more can be added).
|
||||
|
||||
6. The driver must use page_pool_dma_sync_netmem_for_cpu() in lieu of
|
||||
dma_sync_single_range_for_cpu(). For some memory providers, dma_syncing for
|
||||
CPU will be done by the page_pool, for others (particularly dmabuf memory
|
||||
provider), dma syncing for CPU is the responsibility of the userspace using
|
||||
dmabuf APIs. The driver must delegate the entire dma-syncing operation to
|
||||
the page_pool which will do it correctly.
|
||||
|
||||
7. Avoid implementing driver-specific recycling on top of the page_pool. Drivers
|
||||
cannot hold onto a struct page to do their own recycling as the netmem may
|
||||
not be backed by a struct page. However, you may hold onto a page_pool
|
||||
reference with page_pool_fragment_netmem() or page_pool_ref_netmem() for
|
||||
that purpose, but be mindful that some netmem types might have longer
|
||||
circulation times, such as when userspace holds a reference in zerocopy
|
||||
scenarios.
|
@ -525,8 +525,8 @@ implicitly defined. ts[0] holds a software timestamp if set, ts[1]
|
||||
is again deprecated and ts[2] holds a hardware timestamp if set.
|
||||
|
||||
|
||||
3. Hardware Timestamping configuration: SIOCSHWTSTAMP and SIOCGHWTSTAMP
|
||||
=======================================================================
|
||||
3. Hardware Timestamping configuration: ETHTOOL_MSG_TSCONFIG_SET/GET
|
||||
====================================================================
|
||||
|
||||
Hardware time stamping must also be initialized for each device driver
|
||||
that is expected to do hardware time stamping. The parameter is defined in
|
||||
@ -539,12 +539,14 @@ include/uapi/linux/net_tstamp.h as::
|
||||
};
|
||||
|
||||
Desired behavior is passed into the kernel and to a specific device by
|
||||
calling ioctl(SIOCSHWTSTAMP) with a pointer to a struct ifreq whose
|
||||
ifr_data points to a struct hwtstamp_config. The tx_type and
|
||||
rx_filter are hints to the driver what it is expected to do. If
|
||||
the requested fine-grained filtering for incoming packets is not
|
||||
supported, the driver may time stamp more than just the requested types
|
||||
of packets.
|
||||
calling the tsconfig netlink socket ``ETHTOOL_MSG_TSCONFIG_SET``.
|
||||
The ``ETHTOOL_A_TSCONFIG_TX_TYPES``, ``ETHTOOL_A_TSCONFIG_RX_FILTERS`` and
|
||||
``ETHTOOL_A_TSCONFIG_HWTSTAMP_FLAGS`` netlink attributes are then used to set
|
||||
the struct hwtstamp_config accordingly.
|
||||
|
||||
The ``ETHTOOL_A_TSCONFIG_HWTSTAMP_PROVIDER`` netlink nested attribute is used
|
||||
to select the source of the hardware time stamping. It is composed of an index
|
||||
for the device source and a qualifier for the type of time stamping.
|
||||
|
||||
Drivers are free to use a more permissive configuration than the requested
|
||||
configuration. It is expected that drivers should only implement directly the
|
||||
@ -563,9 +565,16 @@ Only a processes with admin rights may change the configuration. User
|
||||
space is responsible to ensure that multiple processes don't interfere
|
||||
with each other and that the settings are reset.
|
||||
|
||||
Any process can read the actual configuration by passing this
|
||||
structure to ioctl(SIOCGHWTSTAMP) in the same way. However, this has
|
||||
not been implemented in all drivers.
|
||||
Any process can read the actual configuration by requesting tsconfig netlink
|
||||
socket ``ETHTOOL_MSG_TSCONFIG_GET``.
|
||||
|
||||
The legacy configuration is the use of the ioctl(SIOCSHWTSTAMP) with a pointer
|
||||
to a struct ifreq whose ifr_data points to a struct hwtstamp_config.
|
||||
The tx_type and rx_filter are hints to the driver what it is expected to do.
|
||||
If the requested fine-grained filtering for incoming packets is not
|
||||
supported, the driver may time stamp more than just the requested types
|
||||
of packets. ioctl(SIOCGHWTSTAMP) is used in the same way as the
|
||||
ioctl(SIOCSHWTSTAMP). However, this has not been implemented in all drivers.
|
||||
|
||||
::
|
||||
|
||||
@ -610,9 +619,10 @@ not been implemented in all drivers.
|
||||
--------------------------------------------------------
|
||||
|
||||
A driver which supports hardware time stamping must support the
|
||||
SIOCSHWTSTAMP ioctl and update the supplied struct hwtstamp_config with
|
||||
the actual values as described in the section on SIOCSHWTSTAMP. It
|
||||
should also support SIOCGHWTSTAMP.
|
||||
ndo_hwtstamp_set NDO or the legacy SIOCSHWTSTAMP ioctl and update the
|
||||
supplied struct hwtstamp_config with the actual values as described in
|
||||
the section on SIOCSHWTSTAMP. It should also support ndo_hwtstamp_get or
|
||||
the legacy SIOCGHWTSTAMP.
|
||||
|
||||
Time stamps for received packets must be stored in the skb. To get a pointer
|
||||
to the shared time stamp structure of the skb call skb_hwtstamps(). Then
|
||||
|
@ -200,6 +200,32 @@ received without a cmsg buffer set.
|
||||
|
||||
recv will never return data from mixed types of TLS records.
|
||||
|
||||
TLS 1.3 Key Updates
|
||||
-------------------
|
||||
|
||||
In TLS 1.3, KeyUpdate handshake messages signal that the sender is
|
||||
updating its TX key. Any message sent after a KeyUpdate will be
|
||||
encrypted using the new key. The userspace library can pass the new
|
||||
key to the kernel using the TLS_TX and TLS_RX socket options, as for
|
||||
the initial keys. TLS version and cipher cannot be changed.
|
||||
|
||||
To prevent attempting to decrypt incoming records using the wrong key,
|
||||
decryption will be paused when a KeyUpdate message is received by the
|
||||
kernel, until the new key has been provided using the TLS_RX socket
|
||||
option. Any read occurring after the KeyUpdate has been read and
|
||||
before the new key is provided will fail with EKEYEXPIRED. poll() will
|
||||
not report any read events from the socket until the new key is
|
||||
provided. There is no pausing on the transmit side.
|
||||
|
||||
Userspace should make sure that the crypto_info provided has been set
|
||||
properly. In particular, the kernel will not check for key/nonce
|
||||
reuse.
|
||||
|
||||
The number of successful and failed key updates is tracked in the
|
||||
``TlsTxRekeyOk``, ``TlsRxRekeyOk``, ``TlsTxRekeyError``,
|
||||
``TlsRxRekeyError`` statistics. The ``TlsRxRekeyReceived`` statistic
|
||||
counts KeyUpdate handshake messages that have been received.
|
||||
|
||||
Integrating in to userspace TLS library
|
||||
---------------------------------------
|
||||
|
||||
@ -286,3 +312,13 @@ TLS implementation exposes the following per-namespace statistics
|
||||
- ``TlsRxNoPadViolation`` -
|
||||
number of data RX records which had to be re-decrypted due to
|
||||
``TLS_RX_EXPECT_NO_PAD`` mis-prediction.
|
||||
|
||||
- ``TlsTxRekeyOk``, ``TlsRxRekeyOk`` -
|
||||
number of successful rekeys on existing sessions for TX and RX
|
||||
|
||||
- ``TlsTxRekeyError``, ``TlsRxRekeyError`` -
|
||||
number of failed rekeys on existing sessions for TX and RX
|
||||
|
||||
- ``TlsRxRekeyReceived`` -
|
||||
number of received KeyUpdate handshake messages, requiring userspace
|
||||
to provide a new RX key
|
||||
|
@ -169,7 +169,8 @@ the stack in xfrm_input().
|
||||
|
||||
hand the packet to napi_gro_receive() as usual
|
||||
|
||||
In ESN mode, xdo_dev_state_advance_esn() is called from xfrm_replay_advance_esn().
|
||||
In ESN mode, xdo_dev_state_advance_esn() is called from
|
||||
xfrm_replay_advance_esn() for RX, and xfrm_replay_overflow_offload_esn for TX.
|
||||
Driver will check packet seq number and update HW ESN state machine if needed.
|
||||
|
||||
Packet offload mode:
|
||||
|
@ -56,7 +56,9 @@ If ``name-prefix`` is specified it replaces the ``$family-$enum``
|
||||
portion of the entry name.
|
||||
|
||||
Boolean ``render-max`` controls creation of the max values
|
||||
(which are enabled by default for attribute enums).
|
||||
(which are enabled by default for attribute enums). These max
|
||||
values are named ``__$pfx-MAX`` and ``$pfx-MAX``. The name
|
||||
of the first value can be overridden via ``enum-cnt-name`` property.
|
||||
|
||||
Attributes
|
||||
==========
|
||||
|
@ -15,7 +15,7 @@ developing Netlink related code. The tool is implemented in Python
|
||||
and can use a YAML specification to issue Netlink requests
|
||||
to the kernel. Only Generic Netlink is supported.
|
||||
|
||||
The tool is located at ``tools/net/ynl/cli.py``. It accepts
|
||||
The tool is located at ``tools/net/ynl/pyynl/cli.py``. It accepts
|
||||
a handul of arguments, the most important ones are:
|
||||
|
||||
- ``--spec`` - point to the spec file
|
||||
@ -27,7 +27,7 @@ YAML specs can be found under ``Documentation/netlink/specs/``.
|
||||
|
||||
Example use::
|
||||
|
||||
$ ./tools/net/ynl/cli.py --spec Documentation/netlink/specs/ethtool.yaml \
|
||||
$ ./tools/net/ynl/pyynl/cli.py --spec Documentation/netlink/specs/ethtool.yaml \
|
||||
--do rings-get \
|
||||
--json '{"header":{"dev-index": 18}}'
|
||||
{'header': {'dev-index': 18, 'dev-name': 'eni1np1'},
|
||||
@ -75,7 +75,7 @@ the two marker lines like above to a file, add that file to git,
|
||||
and run the regeneration tool. Grep the tree for ``YNL-GEN``
|
||||
to see other examples.
|
||||
|
||||
The code generation itself is performed by ``tools/net/ynl/ynl-gen-c.py``
|
||||
The code generation itself is performed by ``tools/net/ynl/pyynl/ynl_gen_c.py``
|
||||
but it takes a few arguments so calling it directly for each file
|
||||
quickly becomes tedious.
|
||||
|
||||
@ -84,7 +84,7 @@ YNL lib
|
||||
|
||||
``tools/net/ynl/lib/`` contains an implementation of a C library
|
||||
(based on libmnl) which integrates with code generated by
|
||||
``tools/net/ynl/ynl-gen-c.py`` to create easy to use netlink wrappers.
|
||||
``tools/net/ynl/pyynl/ynl_gen_c.py`` to create easy to use netlink wrappers.
|
||||
|
||||
YNL basics
|
||||
----------
|
||||
|
17
MAINTAINERS
17
MAINTAINERS
@ -2843,6 +2843,13 @@ S: Maintained
|
||||
F: arch/arm64/boot/dts/freescale/s32g*.dts*
|
||||
F: drivers/pinctrl/nxp/
|
||||
|
||||
ARM/NXP S32G/S32R DWMAC ETHERNET DRIVER
|
||||
M: Jan Petrous <jan.petrous@oss.nxp.com>
|
||||
L: NXP S32 Linux Team <s32@nxp.com>
|
||||
S: Maintained
|
||||
F: Documentation/devicetree/bindings/net/nxp,s32-dwmac.yaml
|
||||
F: drivers/net/ethernet/stmicro/stmmac/dwmac-s32.c
|
||||
|
||||
ARM/Orion SoC/Technologic Systems TS-78xx platform support
|
||||
M: Alexander Clouter <alex@digriz.org.uk>
|
||||
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
|
||||
@ -4610,6 +4617,7 @@ F: drivers/net/ethernet/broadcom/bnx2x/
|
||||
|
||||
BROADCOM BNXT_EN 50 GIGABIT ETHERNET DRIVER
|
||||
M: Michael Chan <michael.chan@broadcom.com>
|
||||
M: Pavan Chebbi <pavan.chebbi@broadcom.com>
|
||||
L: netdev@vger.kernel.org
|
||||
S: Supported
|
||||
F: drivers/firmware/broadcom/tee_bnxt_fw.c
|
||||
@ -5117,6 +5125,7 @@ F: include/uapi/linux/can/gw.h
|
||||
F: include/uapi/linux/can/isotp.h
|
||||
F: include/uapi/linux/can/raw.h
|
||||
F: net/can/
|
||||
F: net/sched/em_canid.c
|
||||
|
||||
CAN-J1939 NETWORK LAYER
|
||||
M: Robin van der Gracht <robin@protonic.nl>
|
||||
@ -10302,7 +10311,6 @@ F: drivers/input/touchscreen/himax_hx83112b.c
|
||||
|
||||
HIPPI
|
||||
M: Jes Sorensen <jes@trained-monkey.org>
|
||||
L: linux-hippi@sunsite.dk
|
||||
S: Maintained
|
||||
F: drivers/net/hippi/
|
||||
F: include/linux/hippidevice.h
|
||||
@ -13979,6 +13987,7 @@ M: Sunil Goutham <sgoutham@marvell.com>
|
||||
M: Geetha sowjanya <gakula@marvell.com>
|
||||
M: Subbaraya Sundeep <sbhatta@marvell.com>
|
||||
M: hariprasad <hkelam@marvell.com>
|
||||
M: Bharat Bhushan <bbhushan2@marvell.com>
|
||||
L: netdev@vger.kernel.org
|
||||
S: Supported
|
||||
F: drivers/net/ethernet/marvell/octeontx2/nic/
|
||||
@ -16216,7 +16225,8 @@ M: Breno Leitao <leitao@debian.org>
|
||||
S: Maintained
|
||||
F: Documentation/networking/netconsole.rst
|
||||
F: drivers/net/netconsole.c
|
||||
F: tools/testing/selftests/drivers/net/netcons_basic.sh
|
||||
F: tools/testing/selftests/drivers/net/lib/sh/lib_netcons.sh
|
||||
F: tools/testing/selftests/drivers/net/netcons\*
|
||||
|
||||
NETDEVSIM
|
||||
M: Jakub Kicinski <kuba@kernel.org>
|
||||
@ -16332,7 +16342,7 @@ F: include/linux/inetdevice.h
|
||||
F: include/linux/netdev*
|
||||
F: include/linux/platform_data/wiznet.h
|
||||
F: include/uapi/linux/cn_proc.h
|
||||
F: include/uapi/linux/ethtool_netlink.h
|
||||
F: include/uapi/linux/ethtool_netlink*
|
||||
F: include/uapi/linux/if_*
|
||||
F: include/uapi/linux/net_shaper.h
|
||||
F: include/uapi/linux/netdev*
|
||||
@ -17690,6 +17700,7 @@ F: Documentation/core-api/packing.rst
|
||||
F: include/linux/packing.h
|
||||
F: lib/packing.c
|
||||
F: lib/packing_test.c
|
||||
F: scripts/gen_packed_field_checks.c
|
||||
|
||||
PADATA PARALLEL EXECUTION MECHANISM
|
||||
M: Steffen Klassert <steffen.klassert@secunet.com>
|
||||
|
4
Makefile
4
Makefile
@ -1367,6 +1367,10 @@ PHONY += scripts_unifdef
|
||||
scripts_unifdef: scripts_basic
|
||||
$(Q)$(MAKE) $(build)=scripts scripts/unifdef
|
||||
|
||||
PHONY += scripts_gen_packed_field_checks
|
||||
scripts_gen_packed_field_checks: scripts_basic
|
||||
$(Q)$(MAKE) $(build)=scripts scripts/gen_packed_field_checks
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Install
|
||||
|
||||
|
@ -148,6 +148,8 @@
|
||||
|
||||
#define SCM_TS_OPT_ID 81
|
||||
|
||||
#define SO_RCVPRIORITY 82
|
||||
|
||||
#if !defined(__KERNEL__)
|
||||
|
||||
#if __BITS_PER_LONG == 64
|
||||
|
@ -159,6 +159,8 @@
|
||||
|
||||
#define SCM_TS_OPT_ID 81
|
||||
|
||||
#define SO_RCVPRIORITY 82
|
||||
|
||||
#if !defined(__KERNEL__)
|
||||
|
||||
#if __BITS_PER_LONG == 64
|
||||
|
@ -140,6 +140,8 @@
|
||||
|
||||
#define SCM_TS_OPT_ID 0x404C
|
||||
|
||||
#define SO_RCVPRIORITY 0x404D
|
||||
|
||||
#if !defined(__KERNEL__)
|
||||
|
||||
#if __BITS_PER_LONG == 64
|
||||
|
@ -141,6 +141,8 @@
|
||||
|
||||
#define SCM_TS_OPT_ID 0x005a
|
||||
|
||||
#define SO_RCVPRIORITY 0x005b
|
||||
|
||||
#if !defined(__KERNEL__)
|
||||
|
||||
|
||||
|
@ -943,7 +943,7 @@ int mlx5_ib_fs_add_op_fc(struct mlx5_ib_dev *dev, u32 port_num,
|
||||
}
|
||||
|
||||
dst.type = MLX5_FLOW_DESTINATION_TYPE_COUNTER;
|
||||
dst.counter_id = mlx5_fc_id(opfc->fc);
|
||||
dst.counter = opfc->fc;
|
||||
|
||||
flow_act.action =
|
||||
MLX5_FLOW_CONTEXT_ACTION_COUNT | MLX5_FLOW_CONTEXT_ACTION_ALLOW;
|
||||
@ -1113,8 +1113,8 @@ static struct mlx5_ib_flow_handler *_create_flow_rule(struct mlx5_ib_dev *dev,
|
||||
handler->ibcounters = flow_act.counters;
|
||||
dest_arr[dest_num].type =
|
||||
MLX5_FLOW_DESTINATION_TYPE_COUNTER;
|
||||
dest_arr[dest_num].counter_id =
|
||||
mlx5_fc_id(mcounters->hw_cntrs_hndl);
|
||||
dest_arr[dest_num].counter =
|
||||
mcounters->hw_cntrs_hndl;
|
||||
dest_num++;
|
||||
}
|
||||
|
||||
@ -1603,7 +1603,7 @@ static bool raw_fs_is_multicast(struct mlx5_ib_flow_matcher *fs_matcher,
|
||||
static struct mlx5_ib_flow_handler *raw_fs_rule_add(
|
||||
struct mlx5_ib_dev *dev, struct mlx5_ib_flow_matcher *fs_matcher,
|
||||
struct mlx5_flow_context *flow_context, struct mlx5_flow_act *flow_act,
|
||||
u32 counter_id, void *cmd_in, int inlen, int dest_id, int dest_type)
|
||||
struct mlx5_fc *counter, void *cmd_in, int inlen, int dest_id, int dest_type)
|
||||
{
|
||||
struct mlx5_flow_destination *dst;
|
||||
struct mlx5_ib_flow_prio *ft_prio;
|
||||
@ -1652,8 +1652,12 @@ static struct mlx5_ib_flow_handler *raw_fs_rule_add(
|
||||
}
|
||||
|
||||
if (flow_act->action & MLX5_FLOW_CONTEXT_ACTION_COUNT) {
|
||||
if (WARN_ON(!counter)) {
|
||||
err = -EINVAL;
|
||||
goto unlock;
|
||||
}
|
||||
dst[dst_num].type = MLX5_FLOW_DESTINATION_TYPE_COUNTER;
|
||||
dst[dst_num].counter_id = counter_id;
|
||||
dst[dst_num].counter = counter;
|
||||
dst_num++;
|
||||
}
|
||||
|
||||
@ -1878,7 +1882,8 @@ static int get_dests(struct uverbs_attr_bundle *attrs,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool is_flow_counter(void *obj, u32 offset, u32 *counter_id)
|
||||
static bool
|
||||
is_flow_counter(void *obj, u32 offset, u32 *counter_id, u32 *fc_bulk_size)
|
||||
{
|
||||
struct devx_obj *devx_obj = obj;
|
||||
u16 opcode = MLX5_GET(general_obj_in_cmd_hdr, devx_obj->dinbox, opcode);
|
||||
@ -1888,6 +1893,7 @@ static bool is_flow_counter(void *obj, u32 offset, u32 *counter_id)
|
||||
if (offset && offset >= devx_obj->flow_counter_bulk_size)
|
||||
return false;
|
||||
|
||||
*fc_bulk_size = devx_obj->flow_counter_bulk_size;
|
||||
*counter_id = MLX5_GET(dealloc_flow_counter_in,
|
||||
devx_obj->dinbox,
|
||||
flow_counter_id);
|
||||
@ -1904,13 +1910,13 @@ static int UVERBS_HANDLER(MLX5_IB_METHOD_CREATE_FLOW)(
|
||||
{
|
||||
struct mlx5_flow_context flow_context = {.flow_tag =
|
||||
MLX5_FS_DEFAULT_FLOW_TAG};
|
||||
u32 *offset_attr, offset = 0, counter_id = 0;
|
||||
int dest_id, dest_type = -1, inlen, len, ret, i;
|
||||
struct mlx5_ib_flow_handler *flow_handler;
|
||||
struct mlx5_ib_flow_matcher *fs_matcher;
|
||||
struct ib_uobject **arr_flow_actions;
|
||||
struct ib_uflow_resources *uflow_res;
|
||||
struct mlx5_flow_act flow_act = {};
|
||||
struct mlx5_fc *counter = NULL;
|
||||
struct ib_qp *qp = NULL;
|
||||
void *devx_obj, *cmd_in;
|
||||
struct ib_uobject *uobj;
|
||||
@ -1937,6 +1943,7 @@ static int UVERBS_HANDLER(MLX5_IB_METHOD_CREATE_FLOW)(
|
||||
len = uverbs_attr_get_uobjs_arr(attrs,
|
||||
MLX5_IB_ATTR_CREATE_FLOW_ARR_COUNTERS_DEVX, &arr_flow_actions);
|
||||
if (len) {
|
||||
u32 *offset_attr, fc_bulk_size, offset = 0, counter_id = 0;
|
||||
devx_obj = arr_flow_actions[0]->object;
|
||||
|
||||
if (uverbs_attr_is_valid(attrs,
|
||||
@ -1956,8 +1963,11 @@ static int UVERBS_HANDLER(MLX5_IB_METHOD_CREATE_FLOW)(
|
||||
offset = *offset_attr;
|
||||
}
|
||||
|
||||
if (!is_flow_counter(devx_obj, offset, &counter_id))
|
||||
if (!is_flow_counter(devx_obj, offset, &counter_id, &fc_bulk_size))
|
||||
return -EINVAL;
|
||||
counter = mlx5_fc_local_create(counter_id, offset, fc_bulk_size);
|
||||
if (IS_ERR(counter))
|
||||
return PTR_ERR(counter);
|
||||
|
||||
flow_act.action |= MLX5_FLOW_CONTEXT_ACTION_COUNT;
|
||||
}
|
||||
@ -1968,8 +1978,10 @@ static int UVERBS_HANDLER(MLX5_IB_METHOD_CREATE_FLOW)(
|
||||
MLX5_IB_ATTR_CREATE_FLOW_MATCH_VALUE);
|
||||
|
||||
uflow_res = flow_resources_alloc(MLX5_IB_CREATE_FLOW_MAX_FLOW_ACTIONS);
|
||||
if (!uflow_res)
|
||||
return -ENOMEM;
|
||||
if (!uflow_res) {
|
||||
ret = -ENOMEM;
|
||||
goto destroy_counter;
|
||||
}
|
||||
|
||||
len = uverbs_attr_get_uobjs_arr(attrs,
|
||||
MLX5_IB_ATTR_CREATE_FLOW_ARR_FLOW_ACTIONS, &arr_flow_actions);
|
||||
@ -1996,7 +2008,7 @@ static int UVERBS_HANDLER(MLX5_IB_METHOD_CREATE_FLOW)(
|
||||
|
||||
flow_handler =
|
||||
raw_fs_rule_add(dev, fs_matcher, &flow_context, &flow_act,
|
||||
counter_id, cmd_in, inlen, dest_id, dest_type);
|
||||
counter, cmd_in, inlen, dest_id, dest_type);
|
||||
if (IS_ERR(flow_handler)) {
|
||||
ret = PTR_ERR(flow_handler);
|
||||
goto err_out;
|
||||
@ -2007,6 +2019,9 @@ static int UVERBS_HANDLER(MLX5_IB_METHOD_CREATE_FLOW)(
|
||||
return 0;
|
||||
err_out:
|
||||
ib_uverbs_flow_resources_free(uflow_res);
|
||||
destroy_counter:
|
||||
if (counter)
|
||||
mlx5_fc_local_destroy(counter);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -294,20 +294,6 @@ get_Bprotocol4mask(u_int m)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct Bprotocol *
|
||||
get_Bprotocol4id(u_int id)
|
||||
{
|
||||
u_int m;
|
||||
|
||||
if (id < ISDN_P_B_START || id > 63) {
|
||||
printk(KERN_WARNING "%s id not in range %d\n",
|
||||
__func__, id);
|
||||
return NULL;
|
||||
}
|
||||
m = 1 << (id & ISDN_P_B_MASK);
|
||||
return get_Bprotocol4mask(m);
|
||||
}
|
||||
|
||||
int
|
||||
mISDN_register_Bprotocol(struct Bprotocol *bp)
|
||||
{
|
||||
|
@ -55,7 +55,6 @@ extern void __add_layer2(struct mISDNchannel *, struct mISDNstack *);
|
||||
|
||||
extern u_int get_all_Bprotocols(void);
|
||||
struct Bprotocol *get_Bprotocol4mask(u_int);
|
||||
struct Bprotocol *get_Bprotocol4id(u_int);
|
||||
|
||||
extern int mISDN_inittimer(u_int *);
|
||||
extern void mISDN_timer_cleanup(void);
|
||||
|
@ -84,7 +84,7 @@ static int bareudp_udp_encap_recv(struct sock *sk, struct sk_buff *skb)
|
||||
|
||||
if (skb_copy_bits(skb, BAREUDP_BASE_HLEN, &ipversion,
|
||||
sizeof(ipversion))) {
|
||||
dev_core_stats_rx_dropped_inc(bareudp->dev);
|
||||
dev_dstats_rx_dropped(bareudp->dev);
|
||||
goto drop;
|
||||
}
|
||||
ipversion >>= 4;
|
||||
@ -94,7 +94,7 @@ static int bareudp_udp_encap_recv(struct sock *sk, struct sk_buff *skb)
|
||||
} else if (ipversion == 6 && bareudp->multi_proto_mode) {
|
||||
proto = htons(ETH_P_IPV6);
|
||||
} else {
|
||||
dev_core_stats_rx_dropped_inc(bareudp->dev);
|
||||
dev_dstats_rx_dropped(bareudp->dev);
|
||||
goto drop;
|
||||
}
|
||||
} else if (bareudp->ethertype == htons(ETH_P_MPLS_UC)) {
|
||||
@ -108,7 +108,7 @@ static int bareudp_udp_encap_recv(struct sock *sk, struct sk_buff *skb)
|
||||
ipv4_is_multicast(tunnel_hdr->daddr)) {
|
||||
proto = htons(ETH_P_MPLS_MC);
|
||||
} else {
|
||||
dev_core_stats_rx_dropped_inc(bareudp->dev);
|
||||
dev_dstats_rx_dropped(bareudp->dev);
|
||||
goto drop;
|
||||
}
|
||||
} else {
|
||||
@ -124,7 +124,7 @@ static int bareudp_udp_encap_recv(struct sock *sk, struct sk_buff *skb)
|
||||
(addr_type & IPV6_ADDR_MULTICAST)) {
|
||||
proto = htons(ETH_P_MPLS_MC);
|
||||
} else {
|
||||
dev_core_stats_rx_dropped_inc(bareudp->dev);
|
||||
dev_dstats_rx_dropped(bareudp->dev);
|
||||
goto drop;
|
||||
}
|
||||
}
|
||||
@ -136,7 +136,7 @@ static int bareudp_udp_encap_recv(struct sock *sk, struct sk_buff *skb)
|
||||
proto,
|
||||
!net_eq(bareudp->net,
|
||||
dev_net(bareudp->dev)))) {
|
||||
dev_core_stats_rx_dropped_inc(bareudp->dev);
|
||||
dev_dstats_rx_dropped(bareudp->dev);
|
||||
goto drop;
|
||||
}
|
||||
|
||||
@ -144,7 +144,7 @@ static int bareudp_udp_encap_recv(struct sock *sk, struct sk_buff *skb)
|
||||
|
||||
tun_dst = udp_tun_rx_dst(skb, family, key, 0, 0);
|
||||
if (!tun_dst) {
|
||||
dev_core_stats_rx_dropped_inc(bareudp->dev);
|
||||
dev_dstats_rx_dropped(bareudp->dev);
|
||||
goto drop;
|
||||
}
|
||||
skb_dst_set(skb, &tun_dst->dst);
|
||||
@ -194,7 +194,7 @@ static int bareudp_udp_encap_recv(struct sock *sk, struct sk_buff *skb)
|
||||
len = skb->len;
|
||||
err = gro_cells_receive(&bareudp->gro_cells, skb);
|
||||
if (likely(err == NET_RX_SUCCESS))
|
||||
dev_sw_netstats_rx_add(bareudp->dev, len);
|
||||
dev_dstats_rx_add(bareudp->dev, len);
|
||||
|
||||
return 0;
|
||||
drop:
|
||||
@ -589,7 +589,7 @@ static void bareudp_setup(struct net_device *dev)
|
||||
dev->priv_flags |= IFF_NO_QUEUE;
|
||||
dev->lltx = true;
|
||||
dev->flags = IFF_POINTOPOINT | IFF_NOARP | IFF_MULTICAST;
|
||||
dev->pcpu_stat_type = NETDEV_PCPU_STAT_TSTATS;
|
||||
dev->pcpu_stat_type = NETDEV_PCPU_STAT_DSTATS;
|
||||
}
|
||||
|
||||
static int bareudp_validate(struct nlattr *tb[], struct nlattr *data[],
|
||||
|
@ -85,8 +85,6 @@ const char *can_get_state_str(const enum can_state state)
|
||||
default:
|
||||
return "<unknown>";
|
||||
}
|
||||
|
||||
return "<unknown>";
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(can_get_state_str);
|
||||
|
||||
|
@ -999,7 +999,8 @@ static int kvaser_pciefd_setup_can_ctrls(struct kvaser_pciefd *pcie)
|
||||
can->can.ctrlmode_supported = CAN_CTRLMODE_LISTENONLY |
|
||||
CAN_CTRLMODE_FD |
|
||||
CAN_CTRLMODE_FD_NON_ISO |
|
||||
CAN_CTRLMODE_CC_LEN8_DLC;
|
||||
CAN_CTRLMODE_CC_LEN8_DLC |
|
||||
CAN_CTRLMODE_BERR_REPORTING;
|
||||
|
||||
status = ioread32(can->reg_base + KVASER_PCIEFD_KCAN_STAT_REG);
|
||||
if (!(status & KVASER_PCIEFD_KCAN_STAT_FD)) {
|
||||
@ -1234,11 +1235,15 @@ static int kvaser_pciefd_handle_data_packet(struct kvaser_pciefd *pcie,
|
||||
}
|
||||
|
||||
static void kvaser_pciefd_change_state(struct kvaser_pciefd_can *can,
|
||||
const struct can_berr_counter *bec,
|
||||
struct can_frame *cf,
|
||||
enum can_state new_state,
|
||||
enum can_state tx_state,
|
||||
enum can_state rx_state)
|
||||
{
|
||||
enum can_state old_state;
|
||||
|
||||
old_state = can->can.state;
|
||||
can_change_state(can->can.dev, cf, tx_state, rx_state);
|
||||
|
||||
if (new_state == CAN_STATE_BUS_OFF) {
|
||||
@ -1254,6 +1259,18 @@ static void kvaser_pciefd_change_state(struct kvaser_pciefd_can *can,
|
||||
can_bus_off(ndev);
|
||||
}
|
||||
}
|
||||
if (old_state == CAN_STATE_BUS_OFF &&
|
||||
new_state == CAN_STATE_ERROR_ACTIVE &&
|
||||
can->can.restart_ms) {
|
||||
can->can.can_stats.restarts++;
|
||||
if (cf)
|
||||
cf->can_id |= CAN_ERR_RESTARTED;
|
||||
}
|
||||
if (cf && new_state != CAN_STATE_BUS_OFF) {
|
||||
cf->can_id |= CAN_ERR_CNT;
|
||||
cf->data[6] = bec->txerr;
|
||||
cf->data[7] = bec->rxerr;
|
||||
}
|
||||
}
|
||||
|
||||
static void kvaser_pciefd_packet_to_state(struct kvaser_pciefd_rx_packet *p,
|
||||
@ -1288,7 +1305,7 @@ static int kvaser_pciefd_rx_error_frame(struct kvaser_pciefd_can *can,
|
||||
struct can_berr_counter bec;
|
||||
enum can_state old_state, new_state, tx_state, rx_state;
|
||||
struct net_device *ndev = can->can.dev;
|
||||
struct sk_buff *skb;
|
||||
struct sk_buff *skb = NULL;
|
||||
struct can_frame *cf = NULL;
|
||||
|
||||
old_state = can->can.state;
|
||||
@ -1297,16 +1314,10 @@ static int kvaser_pciefd_rx_error_frame(struct kvaser_pciefd_can *can,
|
||||
bec.rxerr = FIELD_GET(KVASER_PCIEFD_SPACK_RXERR_MASK, p->header[0]);
|
||||
|
||||
kvaser_pciefd_packet_to_state(p, &bec, &new_state, &tx_state, &rx_state);
|
||||
if (can->can.ctrlmode & CAN_CTRLMODE_BERR_REPORTING)
|
||||
skb = alloc_can_err_skb(ndev, &cf);
|
||||
if (new_state != old_state) {
|
||||
kvaser_pciefd_change_state(can, cf, new_state, tx_state, rx_state);
|
||||
if (old_state == CAN_STATE_BUS_OFF &&
|
||||
new_state == CAN_STATE_ERROR_ACTIVE &&
|
||||
can->can.restart_ms) {
|
||||
can->can.can_stats.restarts++;
|
||||
if (skb)
|
||||
cf->can_id |= CAN_ERR_RESTARTED;
|
||||
}
|
||||
kvaser_pciefd_change_state(can, &bec, cf, new_state, tx_state, rx_state);
|
||||
}
|
||||
|
||||
can->err_rep_cnt++;
|
||||
@ -1319,17 +1330,18 @@ static int kvaser_pciefd_rx_error_frame(struct kvaser_pciefd_can *can,
|
||||
can->bec.txerr = bec.txerr;
|
||||
can->bec.rxerr = bec.rxerr;
|
||||
|
||||
if (can->can.ctrlmode & CAN_CTRLMODE_BERR_REPORTING) {
|
||||
if (!skb) {
|
||||
netdev_warn(ndev, "No memory left for err_skb\n");
|
||||
ndev->stats.rx_dropped++;
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
kvaser_pciefd_set_skb_timestamp(can->kv_pcie, skb, p->timestamp);
|
||||
cf->can_id |= CAN_ERR_BUSERROR | CAN_ERR_CNT;
|
||||
cf->data[6] = bec.txerr;
|
||||
cf->data[7] = bec.rxerr;
|
||||
|
||||
netif_rx(skb);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -1359,6 +1371,7 @@ static int kvaser_pciefd_handle_status_resp(struct kvaser_pciefd_can *can,
|
||||
{
|
||||
struct can_berr_counter bec;
|
||||
enum can_state old_state, new_state, tx_state, rx_state;
|
||||
int ret = 0;
|
||||
|
||||
old_state = can->can.state;
|
||||
|
||||
@ -1372,25 +1385,15 @@ static int kvaser_pciefd_handle_status_resp(struct kvaser_pciefd_can *can,
|
||||
struct can_frame *cf;
|
||||
|
||||
skb = alloc_can_err_skb(ndev, &cf);
|
||||
if (!skb) {
|
||||
ndev->stats.rx_dropped++;
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
kvaser_pciefd_change_state(can, cf, new_state, tx_state, rx_state);
|
||||
if (old_state == CAN_STATE_BUS_OFF &&
|
||||
new_state == CAN_STATE_ERROR_ACTIVE &&
|
||||
can->can.restart_ms) {
|
||||
can->can.can_stats.restarts++;
|
||||
cf->can_id |= CAN_ERR_RESTARTED;
|
||||
}
|
||||
|
||||
kvaser_pciefd_change_state(can, &bec, cf, new_state, tx_state, rx_state);
|
||||
if (skb) {
|
||||
kvaser_pciefd_set_skb_timestamp(can->kv_pcie, skb, p->timestamp);
|
||||
|
||||
cf->data[6] = bec.txerr;
|
||||
cf->data[7] = bec.rxerr;
|
||||
|
||||
netif_rx(skb);
|
||||
} else {
|
||||
ndev->stats.rx_dropped++;
|
||||
netdev_warn(ndev, "No memory left for err_skb\n");
|
||||
ret = -ENOMEM;
|
||||
}
|
||||
}
|
||||
can->bec.txerr = bec.txerr;
|
||||
can->bec.rxerr = bec.rxerr;
|
||||
@ -1398,7 +1401,7 @@ static int kvaser_pciefd_handle_status_resp(struct kvaser_pciefd_can *can,
|
||||
if (bec.txerr || bec.rxerr)
|
||||
mod_timer(&can->bec_poll_timer, KVASER_PCIEFD_BEC_POLL_FREQ);
|
||||
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int kvaser_pciefd_handle_status_packet(struct kvaser_pciefd *pcie,
|
||||
|
@ -1785,6 +1785,13 @@ static void m_can_stop(struct net_device *dev)
|
||||
|
||||
/* set the state as STOPPED */
|
||||
cdev->can.state = CAN_STATE_STOPPED;
|
||||
|
||||
if (cdev->ops->deinit) {
|
||||
ret = cdev->ops->deinit(cdev);
|
||||
if (ret)
|
||||
netdev_err(dev, "failed to deinitialize: %pe\n",
|
||||
ERR_PTR(ret));
|
||||
}
|
||||
}
|
||||
|
||||
static int m_can_close(struct net_device *dev)
|
||||
@ -2466,6 +2473,7 @@ int m_can_class_suspend(struct device *dev)
|
||||
{
|
||||
struct m_can_classdev *cdev = dev_get_drvdata(dev);
|
||||
struct net_device *ndev = cdev->net;
|
||||
int ret = 0;
|
||||
|
||||
if (netif_running(ndev)) {
|
||||
netif_stop_queue(ndev);
|
||||
@ -2478,6 +2486,9 @@ int m_can_class_suspend(struct device *dev)
|
||||
if (cdev->pm_wake_source) {
|
||||
hrtimer_cancel(&cdev->hrtimer);
|
||||
m_can_write(cdev, M_CAN_IE, IR_RF0N);
|
||||
|
||||
if (cdev->ops->deinit)
|
||||
ret = cdev->ops->deinit(cdev);
|
||||
} else {
|
||||
m_can_stop(ndev);
|
||||
}
|
||||
@ -2489,7 +2500,7 @@ int m_can_class_suspend(struct device *dev)
|
||||
|
||||
cdev->can.state = CAN_STATE_SLEEPING;
|
||||
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(m_can_class_suspend);
|
||||
|
||||
@ -2497,14 +2508,13 @@ int m_can_class_resume(struct device *dev)
|
||||
{
|
||||
struct m_can_classdev *cdev = dev_get_drvdata(dev);
|
||||
struct net_device *ndev = cdev->net;
|
||||
int ret = 0;
|
||||
|
||||
pinctrl_pm_select_default_state(dev);
|
||||
|
||||
cdev->can.state = CAN_STATE_ERROR_ACTIVE;
|
||||
|
||||
if (netif_running(ndev)) {
|
||||
int ret;
|
||||
|
||||
ret = m_can_clk_start(cdev);
|
||||
if (ret)
|
||||
return ret;
|
||||
@ -2517,6 +2527,10 @@ int m_can_class_resume(struct device *dev)
|
||||
* again.
|
||||
*/
|
||||
cdev->active_interrupts |= IR_RF0N | IR_TEFN;
|
||||
|
||||
if (cdev->ops->init)
|
||||
ret = cdev->ops->init(cdev);
|
||||
|
||||
m_can_write(cdev, M_CAN_IE, cdev->active_interrupts);
|
||||
} else {
|
||||
ret = m_can_start(ndev);
|
||||
@ -2530,7 +2544,7 @@ int m_can_class_resume(struct device *dev)
|
||||
netif_start_queue(ndev);
|
||||
}
|
||||
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(m_can_class_resume);
|
||||
|
||||
|
@ -68,6 +68,7 @@ struct m_can_ops {
|
||||
int (*write_fifo)(struct m_can_classdev *cdev, int addr_offset,
|
||||
const void *val, size_t val_count);
|
||||
int (*init)(struct m_can_classdev *cdev);
|
||||
int (*deinit)(struct m_can_classdev *cdev);
|
||||
};
|
||||
|
||||
struct m_can_tx_op {
|
||||
|
@ -92,6 +92,8 @@
|
||||
#define TCAN4X5X_MODE_STANDBY BIT(6)
|
||||
#define TCAN4X5X_MODE_NORMAL BIT(7)
|
||||
|
||||
#define TCAN4X5X_NWKRQ_VOLTAGE_VIO BIT(19)
|
||||
|
||||
#define TCAN4X5X_DISABLE_WAKE_MSK (BIT(31) | BIT(30))
|
||||
#define TCAN4X5X_DISABLE_INH_MSK BIT(9)
|
||||
|
||||
@ -267,9 +269,24 @@ static int tcan4x5x_init(struct m_can_classdev *cdev)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (tcan4x5x->nwkrq_voltage_vio) {
|
||||
ret = regmap_set_bits(tcan4x5x->regmap, TCAN4X5X_CONFIG,
|
||||
TCAN4X5X_NWKRQ_VOLTAGE_VIO);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int tcan4x5x_deinit(struct m_can_classdev *cdev)
|
||||
{
|
||||
struct tcan4x5x_priv *tcan4x5x = cdev_to_priv(cdev);
|
||||
|
||||
return regmap_update_bits(tcan4x5x->regmap, TCAN4X5X_CONFIG,
|
||||
TCAN4X5X_MODE_SEL_MASK, TCAN4X5X_MODE_STANDBY);
|
||||
};
|
||||
|
||||
static int tcan4x5x_disable_wake(struct m_can_classdev *cdev)
|
||||
{
|
||||
struct tcan4x5x_priv *tcan4x5x = cdev_to_priv(cdev);
|
||||
@ -318,6 +335,14 @@ static const struct tcan4x5x_version_info
|
||||
return &tcan4x5x_versions[TCAN4X5X];
|
||||
}
|
||||
|
||||
static void tcan4x5x_get_dt_data(struct m_can_classdev *cdev)
|
||||
{
|
||||
struct tcan4x5x_priv *tcan4x5x = cdev_to_priv(cdev);
|
||||
|
||||
tcan4x5x->nwkrq_voltage_vio =
|
||||
of_property_read_bool(cdev->dev->of_node, "ti,nwkrq-voltage-vio");
|
||||
}
|
||||
|
||||
static int tcan4x5x_get_gpios(struct m_can_classdev *cdev,
|
||||
const struct tcan4x5x_version_info *version_info)
|
||||
{
|
||||
@ -359,6 +384,7 @@ static int tcan4x5x_get_gpios(struct m_can_classdev *cdev,
|
||||
|
||||
static const struct m_can_ops tcan4x5x_ops = {
|
||||
.init = tcan4x5x_init,
|
||||
.deinit = tcan4x5x_deinit,
|
||||
.read_reg = tcan4x5x_read_reg,
|
||||
.write_reg = tcan4x5x_write_reg,
|
||||
.write_fifo = tcan4x5x_write_fifo,
|
||||
@ -392,7 +418,7 @@ static int tcan4x5x_can_probe(struct spi_device *spi)
|
||||
priv->power = NULL;
|
||||
}
|
||||
|
||||
m_can_class_get_clocks(mcan_class);
|
||||
mcan_class->cclk = devm_clk_get(mcan_class->dev, "cclk");
|
||||
if (IS_ERR(mcan_class->cclk)) {
|
||||
dev_err(&spi->dev, "no CAN clock source defined\n");
|
||||
freq = TCAN4X5X_EXT_CLK_DEF;
|
||||
@ -453,6 +479,8 @@ static int tcan4x5x_can_probe(struct spi_device *spi)
|
||||
goto out_power;
|
||||
}
|
||||
|
||||
tcan4x5x_get_dt_data(mcan_class);
|
||||
|
||||
tcan4x5x_check_wake(priv);
|
||||
|
||||
ret = tcan4x5x_write_tcan_reg(mcan_class, TCAN4X5X_INT_EN, 0);
|
||||
|
@ -42,6 +42,8 @@ struct tcan4x5x_priv {
|
||||
|
||||
struct tcan4x5x_map_buf map_buf_rx;
|
||||
struct tcan4x5x_map_buf map_buf_tx;
|
||||
|
||||
bool nwkrq_voltage_vio;
|
||||
};
|
||||
|
||||
static inline void
|
||||
|
@ -230,18 +230,9 @@ static int sp_probe(struct platform_device *pdev)
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
if (!res_mem)
|
||||
return -ENODEV;
|
||||
|
||||
if (!devm_request_mem_region(&pdev->dev, res_mem->start,
|
||||
resource_size(res_mem), DRV_NAME))
|
||||
return -EBUSY;
|
||||
|
||||
addr = devm_ioremap(&pdev->dev, res_mem->start,
|
||||
resource_size(res_mem));
|
||||
if (!addr)
|
||||
return -ENOMEM;
|
||||
addr = devm_platform_get_and_ioremap_resource(pdev, 0, &res_mem);
|
||||
if (IS_ERR(addr))
|
||||
return PTR_ERR(addr);
|
||||
|
||||
if (of) {
|
||||
irq = platform_get_irq(pdev, 0);
|
||||
|
@ -570,7 +570,7 @@ static int sun4i_can_err(struct net_device *dev, u8 isrc, u8 status)
|
||||
else
|
||||
state = CAN_STATE_ERROR_ACTIVE;
|
||||
}
|
||||
if (skb && state != CAN_STATE_BUS_OFF) {
|
||||
if (likely(skb) && state != CAN_STATE_BUS_OFF) {
|
||||
cf->can_id |= CAN_ERR_CNT;
|
||||
cf->data[6] = txerr;
|
||||
cf->data[7] = rxerr;
|
||||
|
@ -818,7 +818,8 @@ static int kvaser_usb_init_one(struct kvaser_usb *dev, int channel)
|
||||
init_completion(&priv->stop_comp);
|
||||
init_completion(&priv->flush_comp);
|
||||
init_completion(&priv->get_busparams_comp);
|
||||
priv->can.ctrlmode_supported = CAN_CTRLMODE_CC_LEN8_DLC;
|
||||
priv->can.ctrlmode_supported = CAN_CTRLMODE_CC_LEN8_DLC |
|
||||
CAN_CTRLMODE_BERR_REPORTING;
|
||||
|
||||
priv->dev = dev;
|
||||
priv->netdev = netdev;
|
||||
|
@ -926,6 +926,42 @@ kvaser_usb_hydra_bus_status_to_can_state(const struct kvaser_usb_net_priv *priv,
|
||||
}
|
||||
}
|
||||
|
||||
static void kvaser_usb_hydra_change_state(struct kvaser_usb_net_priv *priv,
|
||||
const struct can_berr_counter *bec,
|
||||
struct can_frame *cf,
|
||||
enum can_state new_state)
|
||||
{
|
||||
struct net_device *netdev = priv->netdev;
|
||||
enum can_state old_state = priv->can.state;
|
||||
enum can_state tx_state, rx_state;
|
||||
|
||||
tx_state = (bec->txerr >= bec->rxerr) ?
|
||||
new_state : CAN_STATE_ERROR_ACTIVE;
|
||||
rx_state = (bec->txerr <= bec->rxerr) ?
|
||||
new_state : CAN_STATE_ERROR_ACTIVE;
|
||||
can_change_state(netdev, cf, tx_state, rx_state);
|
||||
|
||||
if (new_state == CAN_STATE_BUS_OFF && old_state < CAN_STATE_BUS_OFF) {
|
||||
if (priv->can.restart_ms == 0)
|
||||
kvaser_usb_hydra_send_simple_cmd_async(priv, CMD_STOP_CHIP_REQ);
|
||||
|
||||
can_bus_off(netdev);
|
||||
}
|
||||
|
||||
if (priv->can.restart_ms &&
|
||||
old_state >= CAN_STATE_BUS_OFF &&
|
||||
new_state < CAN_STATE_BUS_OFF) {
|
||||
priv->can.can_stats.restarts++;
|
||||
if (cf)
|
||||
cf->can_id |= CAN_ERR_RESTARTED;
|
||||
}
|
||||
if (cf && new_state != CAN_STATE_BUS_OFF) {
|
||||
cf->can_id |= CAN_ERR_CNT;
|
||||
cf->data[6] = bec->txerr;
|
||||
cf->data[7] = bec->rxerr;
|
||||
}
|
||||
}
|
||||
|
||||
static void kvaser_usb_hydra_update_state(struct kvaser_usb_net_priv *priv,
|
||||
u8 bus_status,
|
||||
const struct can_berr_counter *bec)
|
||||
@ -951,41 +987,11 @@ static void kvaser_usb_hydra_update_state(struct kvaser_usb_net_priv *priv,
|
||||
return;
|
||||
|
||||
skb = alloc_can_err_skb(netdev, &cf);
|
||||
if (skb) {
|
||||
enum can_state tx_state, rx_state;
|
||||
|
||||
tx_state = (bec->txerr >= bec->rxerr) ?
|
||||
new_state : CAN_STATE_ERROR_ACTIVE;
|
||||
rx_state = (bec->txerr <= bec->rxerr) ?
|
||||
new_state : CAN_STATE_ERROR_ACTIVE;
|
||||
can_change_state(netdev, cf, tx_state, rx_state);
|
||||
}
|
||||
|
||||
if (new_state == CAN_STATE_BUS_OFF && old_state < CAN_STATE_BUS_OFF) {
|
||||
if (!priv->can.restart_ms)
|
||||
kvaser_usb_hydra_send_simple_cmd_async
|
||||
(priv, CMD_STOP_CHIP_REQ);
|
||||
|
||||
can_bus_off(netdev);
|
||||
}
|
||||
|
||||
if (!skb) {
|
||||
netdev_warn(netdev, "No memory left for err_skb\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (priv->can.restart_ms &&
|
||||
old_state >= CAN_STATE_BUS_OFF &&
|
||||
new_state < CAN_STATE_BUS_OFF)
|
||||
priv->can.can_stats.restarts++;
|
||||
|
||||
if (new_state != CAN_STATE_BUS_OFF) {
|
||||
cf->can_id |= CAN_ERR_CNT;
|
||||
cf->data[6] = bec->txerr;
|
||||
cf->data[7] = bec->rxerr;
|
||||
}
|
||||
|
||||
kvaser_usb_hydra_change_state(priv, bec, cf, new_state);
|
||||
if (skb)
|
||||
netif_rx(skb);
|
||||
else
|
||||
netdev_warn(netdev, "No memory left for err_skb\n");
|
||||
}
|
||||
|
||||
static void kvaser_usb_hydra_state_event(const struct kvaser_usb *dev,
|
||||
@ -1078,9 +1084,8 @@ kvaser_usb_hydra_error_frame(struct kvaser_usb_net_priv *priv,
|
||||
{
|
||||
struct net_device *netdev = priv->netdev;
|
||||
struct net_device_stats *stats = &netdev->stats;
|
||||
struct can_frame *cf;
|
||||
struct sk_buff *skb;
|
||||
struct skb_shared_hwtstamps *shhwtstamps;
|
||||
struct can_frame *cf = NULL;
|
||||
struct sk_buff *skb = NULL;
|
||||
struct can_berr_counter bec;
|
||||
enum can_state new_state, old_state;
|
||||
u8 bus_status;
|
||||
@ -1096,51 +1101,25 @@ kvaser_usb_hydra_error_frame(struct kvaser_usb_net_priv *priv,
|
||||
kvaser_usb_hydra_bus_status_to_can_state(priv, bus_status, &bec,
|
||||
&new_state);
|
||||
|
||||
if (priv->can.ctrlmode & CAN_CTRLMODE_BERR_REPORTING)
|
||||
skb = alloc_can_err_skb(netdev, &cf);
|
||||
if (new_state != old_state)
|
||||
kvaser_usb_hydra_change_state(priv, &bec, cf, new_state);
|
||||
|
||||
if (new_state != old_state) {
|
||||
if (priv->can.ctrlmode & CAN_CTRLMODE_BERR_REPORTING) {
|
||||
if (skb) {
|
||||
enum can_state tx_state, rx_state;
|
||||
struct skb_shared_hwtstamps *shhwtstamps = skb_hwtstamps(skb);
|
||||
|
||||
tx_state = (bec.txerr >= bec.rxerr) ?
|
||||
new_state : CAN_STATE_ERROR_ACTIVE;
|
||||
rx_state = (bec.txerr <= bec.rxerr) ?
|
||||
new_state : CAN_STATE_ERROR_ACTIVE;
|
||||
|
||||
can_change_state(netdev, cf, tx_state, rx_state);
|
||||
|
||||
if (priv->can.restart_ms &&
|
||||
old_state >= CAN_STATE_BUS_OFF &&
|
||||
new_state < CAN_STATE_BUS_OFF)
|
||||
cf->can_id |= CAN_ERR_RESTARTED;
|
||||
}
|
||||
|
||||
if (new_state == CAN_STATE_BUS_OFF) {
|
||||
if (!priv->can.restart_ms)
|
||||
kvaser_usb_hydra_send_simple_cmd_async
|
||||
(priv, CMD_STOP_CHIP_REQ);
|
||||
|
||||
can_bus_off(netdev);
|
||||
}
|
||||
}
|
||||
|
||||
if (!skb) {
|
||||
stats->rx_dropped++;
|
||||
netdev_warn(netdev, "No memory left for err_skb\n");
|
||||
return;
|
||||
}
|
||||
|
||||
shhwtstamps = skb_hwtstamps(skb);
|
||||
shhwtstamps->hwtstamp = hwtstamp;
|
||||
|
||||
cf->can_id |= CAN_ERR_BUSERROR;
|
||||
if (new_state != CAN_STATE_BUS_OFF) {
|
||||
cf->can_id |= CAN_ERR_CNT;
|
||||
cf->can_id |= CAN_ERR_BUSERROR | CAN_ERR_CNT;
|
||||
cf->data[6] = bec.txerr;
|
||||
cf->data[7] = bec.rxerr;
|
||||
}
|
||||
|
||||
netif_rx(skb);
|
||||
} else {
|
||||
stats->rx_dropped++;
|
||||
netdev_warn(netdev, "No memory left for err_skb\n");
|
||||
}
|
||||
}
|
||||
|
||||
priv->bec.txerr = bec.txerr;
|
||||
priv->bec.rxerr = bec.rxerr;
|
||||
|
@ -1120,10 +1120,8 @@ kvaser_usb_leaf_rx_error_update_can_state(struct kvaser_usb_net_priv *priv,
|
||||
static void kvaser_usb_leaf_rx_error(const struct kvaser_usb *dev,
|
||||
const struct kvaser_usb_err_summary *es)
|
||||
{
|
||||
struct can_frame *cf;
|
||||
struct can_frame tmp_cf = { .can_id = CAN_ERR_FLAG,
|
||||
.len = CAN_ERR_DLC };
|
||||
struct sk_buff *skb;
|
||||
struct can_frame *cf = NULL;
|
||||
struct sk_buff *skb = NULL;
|
||||
struct net_device_stats *stats;
|
||||
struct kvaser_usb_net_priv *priv;
|
||||
struct kvaser_usb_net_leaf_priv *leaf;
|
||||
@ -1143,18 +1141,10 @@ static void kvaser_usb_leaf_rx_error(const struct kvaser_usb *dev,
|
||||
if (!netif_running(priv->netdev))
|
||||
return;
|
||||
|
||||
/* Update all of the CAN interface's state and error counters before
|
||||
* trying any memory allocation that can actually fail with -ENOMEM.
|
||||
*
|
||||
* We send a temporary stack-allocated error CAN frame to
|
||||
* can_change_state() for the very same reason.
|
||||
*
|
||||
* TODO: Split can_change_state() responsibility between updating the
|
||||
* CAN interface's state and counters, and the setting up of CAN error
|
||||
* frame ID and data to userspace. Remove stack allocation afterwards.
|
||||
*/
|
||||
old_state = priv->can.state;
|
||||
kvaser_usb_leaf_rx_error_update_can_state(priv, es, &tmp_cf);
|
||||
if (priv->can.ctrlmode & CAN_CTRLMODE_BERR_REPORTING)
|
||||
skb = alloc_can_err_skb(priv->netdev, &cf);
|
||||
kvaser_usb_leaf_rx_error_update_can_state(priv, es, cf);
|
||||
new_state = priv->can.state;
|
||||
|
||||
/* If there are errors, request status updates periodically as we do
|
||||
@ -1168,13 +1158,6 @@ static void kvaser_usb_leaf_rx_error(const struct kvaser_usb *dev,
|
||||
schedule_delayed_work(&leaf->chip_state_req_work,
|
||||
msecs_to_jiffies(500));
|
||||
|
||||
skb = alloc_can_err_skb(priv->netdev, &cf);
|
||||
if (!skb) {
|
||||
stats->rx_dropped++;
|
||||
return;
|
||||
}
|
||||
memcpy(cf, &tmp_cf, sizeof(*cf));
|
||||
|
||||
if (new_state != old_state) {
|
||||
if (es->status &
|
||||
(M16C_STATE_BUS_OFF | M16C_STATE_BUS_RESET)) {
|
||||
@ -1187,11 +1170,20 @@ static void kvaser_usb_leaf_rx_error(const struct kvaser_usb *dev,
|
||||
if (priv->can.restart_ms &&
|
||||
old_state == CAN_STATE_BUS_OFF &&
|
||||
new_state < CAN_STATE_BUS_OFF) {
|
||||
if (cf)
|
||||
cf->can_id |= CAN_ERR_RESTARTED;
|
||||
netif_carrier_on(priv->netdev);
|
||||
}
|
||||
}
|
||||
|
||||
if (!skb) {
|
||||
if (priv->can.ctrlmode & CAN_CTRLMODE_BERR_REPORTING) {
|
||||
stats->rx_dropped++;
|
||||
netdev_warn(priv->netdev, "No memory left for err_skb\n");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
switch (dev->driver_info->family) {
|
||||
case KVASER_LEAF:
|
||||
if (es->leaf.error_factor) {
|
||||
|
@ -2224,25 +2224,19 @@ int b53_eee_init(struct dsa_switch *ds, int port, struct phy_device *phy)
|
||||
}
|
||||
EXPORT_SYMBOL(b53_eee_init);
|
||||
|
||||
int b53_get_mac_eee(struct dsa_switch *ds, int port, struct ethtool_keee *e)
|
||||
bool b53_support_eee(struct dsa_switch *ds, int port)
|
||||
{
|
||||
struct b53_device *dev = ds->priv;
|
||||
|
||||
if (is5325(dev) || is5365(dev))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
return 0;
|
||||
return !is5325(dev) && !is5365(dev);
|
||||
}
|
||||
EXPORT_SYMBOL(b53_get_mac_eee);
|
||||
EXPORT_SYMBOL(b53_support_eee);
|
||||
|
||||
int b53_set_mac_eee(struct dsa_switch *ds, int port, struct ethtool_keee *e)
|
||||
{
|
||||
struct b53_device *dev = ds->priv;
|
||||
struct ethtool_keee *p = &dev->ports[port].eee;
|
||||
|
||||
if (is5325(dev) || is5365(dev))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
p->eee_enabled = e->eee_enabled;
|
||||
b53_eee_enable_set(ds, port, e->eee_enabled);
|
||||
|
||||
@ -2298,7 +2292,7 @@ static const struct dsa_switch_ops b53_switch_ops = {
|
||||
.phylink_get_caps = b53_phylink_get_caps,
|
||||
.port_enable = b53_enable_port,
|
||||
.port_disable = b53_disable_port,
|
||||
.get_mac_eee = b53_get_mac_eee,
|
||||
.support_eee = b53_support_eee,
|
||||
.set_mac_eee = b53_set_mac_eee,
|
||||
.port_bridge_join = b53_br_join,
|
||||
.port_bridge_leave = b53_br_leave,
|
||||
|
@ -384,7 +384,7 @@ int b53_enable_port(struct dsa_switch *ds, int port, struct phy_device *phy);
|
||||
void b53_disable_port(struct dsa_switch *ds, int port);
|
||||
void b53_brcm_hdr_setup(struct dsa_switch *ds, int port);
|
||||
int b53_eee_init(struct dsa_switch *ds, int port, struct phy_device *phy);
|
||||
int b53_get_mac_eee(struct dsa_switch *ds, int port, struct ethtool_keee *e);
|
||||
bool b53_support_eee(struct dsa_switch *ds, int port);
|
||||
int b53_set_mac_eee(struct dsa_switch *ds, int port, struct ethtool_keee *e);
|
||||
|
||||
#endif
|
||||
|
@ -1232,7 +1232,7 @@ static const struct dsa_switch_ops bcm_sf2_ops = {
|
||||
.set_wol = bcm_sf2_sw_set_wol,
|
||||
.port_enable = bcm_sf2_port_setup,
|
||||
.port_disable = bcm_sf2_port_disable,
|
||||
.get_mac_eee = b53_get_mac_eee,
|
||||
.support_eee = b53_support_eee,
|
||||
.set_mac_eee = b53_set_mac_eee,
|
||||
.port_bridge_join = b53_br_join,
|
||||
.port_bridge_leave = b53_br_leave,
|
||||
|
@ -127,10 +127,14 @@ static const struct of_device_id ksz9477_dt_ids[] = {
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, ksz9477_dt_ids);
|
||||
|
||||
static DEFINE_SIMPLE_DEV_PM_OPS(ksz_i2c_pm_ops,
|
||||
ksz_switch_suspend, ksz_switch_resume);
|
||||
|
||||
static struct i2c_driver ksz9477_i2c_driver = {
|
||||
.driver = {
|
||||
.name = "ksz9477-switch",
|
||||
.of_match_table = ksz9477_dt_ids,
|
||||
.pm = &ksz_i2c_pm_ops,
|
||||
},
|
||||
.probe = ksz9477_i2c_probe,
|
||||
.remove = ksz9477_i2c_remove,
|
||||
|
@ -1339,6 +1339,7 @@ const struct ksz_chip_data ksz_switch_chips[] = {
|
||||
.supports_rgmii = {false, false, true},
|
||||
.internal_phy = {true, true, false},
|
||||
.gbit_capable = {false, false, true},
|
||||
.ptp_capable = true,
|
||||
.wr_table = &ksz8563_register_set,
|
||||
.rd_table = &ksz8563_register_set,
|
||||
},
|
||||
@ -1550,6 +1551,7 @@ const struct ksz_chip_data ksz_switch_chips[] = {
|
||||
.internal_phy = {true, true, true, true,
|
||||
true, false, false},
|
||||
.gbit_capable = {true, true, true, true, true, true, true},
|
||||
.ptp_capable = true,
|
||||
.wr_table = &ksz9477_register_set,
|
||||
.rd_table = &ksz9477_register_set,
|
||||
},
|
||||
@ -1677,6 +1679,7 @@ const struct ksz_chip_data ksz_switch_chips[] = {
|
||||
.supports_rgmii = {false, false, true},
|
||||
.internal_phy = {true, true, false},
|
||||
.gbit_capable = {true, true, true},
|
||||
.ptp_capable = true,
|
||||
},
|
||||
|
||||
[KSZ8567] = {
|
||||
@ -1712,6 +1715,7 @@ const struct ksz_chip_data ksz_switch_chips[] = {
|
||||
true, false, false},
|
||||
.gbit_capable = {false, false, false, false, false,
|
||||
true, true},
|
||||
.ptp_capable = true,
|
||||
},
|
||||
|
||||
[KSZ9567] = {
|
||||
@ -1744,6 +1748,7 @@ const struct ksz_chip_data ksz_switch_chips[] = {
|
||||
.internal_phy = {true, true, true, true,
|
||||
true, false, false},
|
||||
.gbit_capable = {true, true, true, true, true, true, true},
|
||||
.ptp_capable = true,
|
||||
},
|
||||
|
||||
[LAN9370] = {
|
||||
@ -1773,6 +1778,7 @@ const struct ksz_chip_data ksz_switch_chips[] = {
|
||||
.supports_rmii = {false, false, false, false, true},
|
||||
.supports_rgmii = {false, false, false, false, true},
|
||||
.internal_phy = {true, true, true, true, false},
|
||||
.ptp_capable = true,
|
||||
},
|
||||
|
||||
[LAN9371] = {
|
||||
@ -1802,6 +1808,7 @@ const struct ksz_chip_data ksz_switch_chips[] = {
|
||||
.supports_rmii = {false, false, false, false, true, true},
|
||||
.supports_rgmii = {false, false, false, false, true, true},
|
||||
.internal_phy = {true, true, true, true, false, false},
|
||||
.ptp_capable = true,
|
||||
},
|
||||
|
||||
[LAN9372] = {
|
||||
@ -1835,6 +1842,7 @@ const struct ksz_chip_data ksz_switch_chips[] = {
|
||||
true, true, false, false},
|
||||
.internal_phy = {true, true, true, true,
|
||||
false, false, true, true},
|
||||
.ptp_capable = true,
|
||||
},
|
||||
|
||||
[LAN9373] = {
|
||||
@ -1868,6 +1876,7 @@ const struct ksz_chip_data ksz_switch_chips[] = {
|
||||
true, true, false, false},
|
||||
.internal_phy = {true, true, true, false,
|
||||
false, false, true, true},
|
||||
.ptp_capable = true,
|
||||
},
|
||||
|
||||
[LAN9374] = {
|
||||
@ -1901,6 +1910,7 @@ const struct ksz_chip_data ksz_switch_chips[] = {
|
||||
true, true, false, false},
|
||||
.internal_phy = {true, true, true, true,
|
||||
false, false, true, true},
|
||||
.ptp_capable = true,
|
||||
},
|
||||
|
||||
[LAN9646] = {
|
||||
@ -2544,8 +2554,12 @@ static int ksz_mdio_register(struct ksz_device *dev)
|
||||
bus->read = ksz_sw_mdio_read;
|
||||
bus->write = ksz_sw_mdio_write;
|
||||
bus->name = "ksz user smi";
|
||||
if (ds->dst->index != 0) {
|
||||
snprintf(bus->id, MII_BUS_ID_SIZE, "SMI-%d-%d", ds->dst->index, ds->index);
|
||||
} else {
|
||||
snprintf(bus->id, MII_BUS_ID_SIZE, "SMI-%d", ds->index);
|
||||
}
|
||||
}
|
||||
|
||||
ret = ksz_parse_dt_phy_config(dev, bus, mdio_np);
|
||||
if (ret)
|
||||
@ -2805,17 +2819,22 @@ static int ksz_setup(struct dsa_switch *ds)
|
||||
if (ret)
|
||||
goto out_girq;
|
||||
|
||||
if (dev->info->ptp_capable) {
|
||||
ret = ksz_ptp_irq_setup(ds, dp->index);
|
||||
if (ret)
|
||||
goto out_pirq;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (dev->info->ptp_capable) {
|
||||
ret = ksz_ptp_clock_register(ds);
|
||||
if (ret) {
|
||||
dev_err(dev->dev, "Failed to register PTP clock: %d\n", ret);
|
||||
dev_err(dev->dev, "Failed to register PTP clock: %d\n",
|
||||
ret);
|
||||
goto out_ptpirq;
|
||||
}
|
||||
}
|
||||
|
||||
ret = ksz_mdio_register(dev);
|
||||
if (ret < 0) {
|
||||
@ -2834,9 +2853,10 @@ static int ksz_setup(struct dsa_switch *ds)
|
||||
return 0;
|
||||
|
||||
out_ptp_clock_unregister:
|
||||
if (dev->info->ptp_capable)
|
||||
ksz_ptp_clock_unregister(ds);
|
||||
out_ptpirq:
|
||||
if (dev->irq > 0)
|
||||
if (dev->irq > 0 && dev->info->ptp_capable)
|
||||
dsa_switch_for_each_user_port(dp, dev->ds)
|
||||
ksz_ptp_irq_free(ds, dp->index);
|
||||
out_pirq:
|
||||
@ -2855,10 +2875,12 @@ static void ksz_teardown(struct dsa_switch *ds)
|
||||
struct ksz_device *dev = ds->priv;
|
||||
struct dsa_port *dp;
|
||||
|
||||
if (dev->info->ptp_capable)
|
||||
ksz_ptp_clock_unregister(ds);
|
||||
|
||||
if (dev->irq > 0) {
|
||||
dsa_switch_for_each_user_port(dp, dev->ds) {
|
||||
if (dev->info->ptp_capable)
|
||||
ksz_ptp_irq_free(ds, dp->index);
|
||||
|
||||
ksz_irq_free(&dev->ports[dp->index].pirq);
|
||||
@ -3444,12 +3466,12 @@ static int ksz_max_mtu(struct dsa_switch *ds, int port)
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static int ksz_validate_eee(struct dsa_switch *ds, int port)
|
||||
static bool ksz_support_eee(struct dsa_switch *ds, int port)
|
||||
{
|
||||
struct ksz_device *dev = ds->priv;
|
||||
|
||||
if (!dev->info->internal_phy[port])
|
||||
return -EOPNOTSUPP;
|
||||
return false;
|
||||
|
||||
switch (dev->chip_id) {
|
||||
case KSZ8563_CHIP_ID:
|
||||
@ -3461,41 +3483,16 @@ static int ksz_validate_eee(struct dsa_switch *ds, int port)
|
||||
case KSZ9896_CHIP_ID:
|
||||
case KSZ9897_CHIP_ID:
|
||||
case LAN9646_CHIP_ID:
|
||||
return 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static int ksz_get_mac_eee(struct dsa_switch *ds, int port,
|
||||
struct ethtool_keee *e)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = ksz_validate_eee(ds, port);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* There is no documented control of Tx LPI configuration. */
|
||||
e->tx_lpi_enabled = true;
|
||||
|
||||
/* There is no documented control of Tx LPI timer. According to tests
|
||||
* Tx LPI timer seems to be set by default to minimal value.
|
||||
*/
|
||||
e->tx_lpi_timer = 0;
|
||||
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
static int ksz_set_mac_eee(struct dsa_switch *ds, int port,
|
||||
struct ethtool_keee *e)
|
||||
{
|
||||
struct ksz_device *dev = ds->priv;
|
||||
int ret;
|
||||
|
||||
ret = ksz_validate_eee(ds, port);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (!e->tx_lpi_enabled) {
|
||||
dev_err(dev->dev, "Disabling EEE Tx LPI is not supported\n");
|
||||
@ -4593,6 +4590,23 @@ static int ksz_hsr_leave(struct dsa_switch *ds, int port,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ksz_suspend(struct dsa_switch *ds)
|
||||
{
|
||||
struct ksz_device *dev = ds->priv;
|
||||
|
||||
cancel_delayed_work_sync(&dev->mib_read);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ksz_resume(struct dsa_switch *ds)
|
||||
{
|
||||
struct ksz_device *dev = ds->priv;
|
||||
|
||||
if (dev->mib_read_interval)
|
||||
schedule_delayed_work(&dev->mib_read, dev->mib_read_interval);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct dsa_switch_ops ksz_switch_ops = {
|
||||
.get_tag_protocol = ksz_get_tag_protocol,
|
||||
.connect_tag_protocol = ksz_connect_tag_protocol,
|
||||
@ -4633,6 +4647,8 @@ static const struct dsa_switch_ops ksz_switch_ops = {
|
||||
.port_max_mtu = ksz_max_mtu,
|
||||
.get_wol = ksz_get_wol,
|
||||
.set_wol = ksz_set_wol,
|
||||
.suspend = ksz_suspend,
|
||||
.resume = ksz_resume,
|
||||
.get_ts_info = ksz_get_ts_info,
|
||||
.port_hwtstamp_get = ksz_hwtstamp_get,
|
||||
.port_hwtstamp_set = ksz_hwtstamp_set,
|
||||
@ -4641,7 +4657,7 @@ static const struct dsa_switch_ops ksz_switch_ops = {
|
||||
.cls_flower_add = ksz_cls_flower_add,
|
||||
.cls_flower_del = ksz_cls_flower_del,
|
||||
.port_setup_tc = ksz_setup_tc,
|
||||
.get_mac_eee = ksz_get_mac_eee,
|
||||
.support_eee = ksz_support_eee,
|
||||
.set_mac_eee = ksz_set_mac_eee,
|
||||
.port_get_default_prio = ksz_port_get_default_prio,
|
||||
.port_set_default_prio = ksz_port_set_default_prio,
|
||||
@ -5132,6 +5148,24 @@ void ksz_switch_remove(struct ksz_device *dev)
|
||||
}
|
||||
EXPORT_SYMBOL(ksz_switch_remove);
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
int ksz_switch_suspend(struct device *dev)
|
||||
{
|
||||
struct ksz_device *priv = dev_get_drvdata(dev);
|
||||
|
||||
return dsa_switch_suspend(priv->ds);
|
||||
}
|
||||
EXPORT_SYMBOL(ksz_switch_suspend);
|
||||
|
||||
int ksz_switch_resume(struct device *dev)
|
||||
{
|
||||
struct ksz_device *priv = dev_get_drvdata(dev);
|
||||
|
||||
return dsa_switch_resume(priv->ds);
|
||||
}
|
||||
EXPORT_SYMBOL(ksz_switch_resume);
|
||||
#endif
|
||||
|
||||
MODULE_AUTHOR("Woojung Huh <Woojung.Huh@microchip.com>");
|
||||
MODULE_DESCRIPTION("Microchip KSZ Series Switch DSA Driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
@ -92,6 +92,7 @@ struct ksz_chip_data {
|
||||
bool supports_rgmii[KSZ_MAX_NUM_PORTS];
|
||||
bool internal_phy[KSZ_MAX_NUM_PORTS];
|
||||
bool gbit_capable[KSZ_MAX_NUM_PORTS];
|
||||
bool ptp_capable;
|
||||
const struct regmap_access_table *wr_table;
|
||||
const struct regmap_access_table *rd_table;
|
||||
};
|
||||
@ -444,6 +445,8 @@ struct ksz_dev_ops {
|
||||
struct ksz_device *ksz_switch_alloc(struct device *base, void *priv);
|
||||
int ksz_switch_register(struct ksz_device *dev);
|
||||
void ksz_switch_remove(struct ksz_device *dev);
|
||||
int ksz_switch_suspend(struct device *dev);
|
||||
int ksz_switch_resume(struct device *dev);
|
||||
|
||||
void ksz_init_mib_timer(struct ksz_device *dev);
|
||||
bool ksz_is_port_mac_global_usable(struct dsa_switch *ds, int port);
|
||||
|
@ -239,10 +239,14 @@ static const struct spi_device_id ksz_spi_ids[] = {
|
||||
};
|
||||
MODULE_DEVICE_TABLE(spi, ksz_spi_ids);
|
||||
|
||||
static DEFINE_SIMPLE_DEV_PM_OPS(ksz_spi_pm_ops,
|
||||
ksz_switch_suspend, ksz_switch_resume);
|
||||
|
||||
static struct spi_driver ksz_spi_driver = {
|
||||
.driver = {
|
||||
.name = "ksz-switch",
|
||||
.of_match_table = ksz_dt_ids,
|
||||
.pm = &ksz_spi_pm_ops,
|
||||
},
|
||||
.id_table = ksz_spi_ids,
|
||||
.probe = ksz_spi_probe,
|
||||
|
@ -3085,18 +3085,6 @@ mt753x_setup(struct dsa_switch *ds)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int mt753x_get_mac_eee(struct dsa_switch *ds, int port,
|
||||
struct ethtool_keee *e)
|
||||
{
|
||||
struct mt7530_priv *priv = ds->priv;
|
||||
u32 eeecr = mt7530_read(priv, MT753X_PMEEECR_P(port));
|
||||
|
||||
e->tx_lpi_enabled = !(eeecr & LPI_MODE_EN);
|
||||
e->tx_lpi_timer = LPI_THRESH_GET(eeecr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mt753x_set_mac_eee(struct dsa_switch *ds, int port,
|
||||
struct ethtool_keee *e)
|
||||
{
|
||||
@ -3238,7 +3226,7 @@ const struct dsa_switch_ops mt7530_switch_ops = {
|
||||
.port_mirror_add = mt753x_port_mirror_add,
|
||||
.port_mirror_del = mt753x_port_mirror_del,
|
||||
.phylink_get_caps = mt753x_phylink_get_caps,
|
||||
.get_mac_eee = mt753x_get_mac_eee,
|
||||
.support_eee = dsa_supports_eee,
|
||||
.set_mac_eee = mt753x_set_mac_eee,
|
||||
.conduit_state_change = mt753x_conduit_state_change,
|
||||
.port_setup_tc = mt753x_setup_tc,
|
||||
|
@ -1289,9 +1289,6 @@ static size_t mv88e6095_stats_get_stat(struct mv88e6xxx_chip *chip, int port,
|
||||
const struct mv88e6xxx_hw_stat *stat,
|
||||
uint64_t *data)
|
||||
{
|
||||
if (!(stat->type & (STATS_TYPE_BANK0 | STATS_TYPE_PORT)))
|
||||
return 0;
|
||||
|
||||
*data = _mv88e6xxx_get_ethtool_stat(chip, stat, port, 0,
|
||||
MV88E6XXX_G1_STATS_OP_HIST_RX);
|
||||
return 1;
|
||||
@ -1301,9 +1298,6 @@ static size_t mv88e6250_stats_get_stat(struct mv88e6xxx_chip *chip, int port,
|
||||
const struct mv88e6xxx_hw_stat *stat,
|
||||
uint64_t *data)
|
||||
{
|
||||
if (!(stat->type & STATS_TYPE_BANK0))
|
||||
return 0;
|
||||
|
||||
*data = _mv88e6xxx_get_ethtool_stat(chip, stat, port, 0,
|
||||
MV88E6XXX_G1_STATS_OP_HIST_RX);
|
||||
return 1;
|
||||
@ -1313,9 +1307,6 @@ static size_t mv88e6320_stats_get_stat(struct mv88e6xxx_chip *chip, int port,
|
||||
const struct mv88e6xxx_hw_stat *stat,
|
||||
uint64_t *data)
|
||||
{
|
||||
if (!(stat->type & (STATS_TYPE_BANK0 | STATS_TYPE_BANK1)))
|
||||
return 0;
|
||||
|
||||
*data = _mv88e6xxx_get_ethtool_stat(chip, stat, port,
|
||||
MV88E6XXX_G1_STATS_OP_BANK_1_BIT_9,
|
||||
MV88E6XXX_G1_STATS_OP_HIST_RX);
|
||||
@ -1326,9 +1317,6 @@ static size_t mv88e6390_stats_get_stat(struct mv88e6xxx_chip *chip, int port,
|
||||
const struct mv88e6xxx_hw_stat *stat,
|
||||
uint64_t *data)
|
||||
{
|
||||
if (!(stat->type & (STATS_TYPE_BANK0 | STATS_TYPE_BANK1)))
|
||||
return 0;
|
||||
|
||||
*data = _mv88e6xxx_get_ethtool_stat(chip, stat, port,
|
||||
MV88E6XXX_G1_STATS_OP_BANK_1_BIT_10,
|
||||
0);
|
||||
@ -1341,6 +1329,9 @@ static size_t mv88e6xxx_stats_get_stat(struct mv88e6xxx_chip *chip, int port,
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (!(stat->type & chip->info->stats_type))
|
||||
return 0;
|
||||
|
||||
if (chip->info->ops->stats_get_stat) {
|
||||
mv88e6xxx_reg_lock(chip);
|
||||
ret = chip->info->ops->stats_get_stat(chip, port, stat, data);
|
||||
@ -1522,13 +1513,6 @@ static void mv88e6xxx_get_regs(struct dsa_switch *ds, int port,
|
||||
mv88e6xxx_reg_unlock(chip);
|
||||
}
|
||||
|
||||
static int mv88e6xxx_get_mac_eee(struct dsa_switch *ds, int port,
|
||||
struct ethtool_keee *e)
|
||||
{
|
||||
/* Nothing to do on the port's MAC */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mv88e6xxx_set_mac_eee(struct dsa_switch *ds, int port,
|
||||
struct ethtool_keee *e)
|
||||
{
|
||||
@ -5645,6 +5629,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
|
||||
.age_time_coeff = 15000,
|
||||
.g1_irqs = 9,
|
||||
.g2_irqs = 5,
|
||||
.stats_type = STATS_TYPE_BANK0,
|
||||
.atu_move_port_mask = 0xf,
|
||||
.dual_chip = true,
|
||||
.ops = &mv88e6250_ops,
|
||||
@ -5665,6 +5650,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
|
||||
.age_time_coeff = 15000,
|
||||
.g1_irqs = 9,
|
||||
.g2_irqs = 5,
|
||||
.stats_type = STATS_TYPE_BANK0,
|
||||
.atu_move_port_mask = 0xf,
|
||||
.dual_chip = true,
|
||||
.ops = &mv88e6250_ops,
|
||||
@ -5687,6 +5673,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
|
||||
.age_time_coeff = 15000,
|
||||
.g1_irqs = 8,
|
||||
.g2_irqs = 10,
|
||||
.stats_type = STATS_TYPE_BANK0 | STATS_TYPE_PORT,
|
||||
.atu_move_port_mask = 0xf,
|
||||
.pvt = true,
|
||||
.multi_chip = true,
|
||||
@ -5708,6 +5695,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
|
||||
.global2_addr = 0x1c,
|
||||
.age_time_coeff = 15000,
|
||||
.g1_irqs = 8,
|
||||
.stats_type = STATS_TYPE_BANK0 | STATS_TYPE_PORT,
|
||||
.atu_move_port_mask = 0xf,
|
||||
.multi_chip = true,
|
||||
.ops = &mv88e6095_ops,
|
||||
@ -5730,6 +5718,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
|
||||
.age_time_coeff = 15000,
|
||||
.g1_irqs = 8,
|
||||
.g2_irqs = 10,
|
||||
.stats_type = STATS_TYPE_BANK0 | STATS_TYPE_PORT,
|
||||
.atu_move_port_mask = 0xf,
|
||||
.pvt = true,
|
||||
.multi_chip = true,
|
||||
@ -5754,6 +5743,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
|
||||
.age_time_coeff = 15000,
|
||||
.g1_irqs = 9,
|
||||
.g2_irqs = 10,
|
||||
.stats_type = STATS_TYPE_BANK0 | STATS_TYPE_PORT,
|
||||
.atu_move_port_mask = 0xf,
|
||||
.pvt = true,
|
||||
.multi_chip = true,
|
||||
@ -5776,6 +5766,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
|
||||
.global2_addr = 0x1c,
|
||||
.age_time_coeff = 15000,
|
||||
.g1_irqs = 9,
|
||||
.stats_type = STATS_TYPE_BANK0 | STATS_TYPE_PORT,
|
||||
.atu_move_port_mask = 0xf,
|
||||
.multi_chip = true,
|
||||
.ops = &mv88e6131_ops,
|
||||
@ -5800,6 +5791,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
|
||||
.atu_move_port_mask = 0x1f,
|
||||
.g1_irqs = 9,
|
||||
.g2_irqs = 10,
|
||||
.stats_type = STATS_TYPE_BANK0 | STATS_TYPE_BANK1,
|
||||
.pvt = true,
|
||||
.multi_chip = true,
|
||||
.edsa_support = MV88E6XXX_EDSA_SUPPORTED,
|
||||
@ -5823,6 +5815,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
|
||||
.age_time_coeff = 15000,
|
||||
.g1_irqs = 9,
|
||||
.g2_irqs = 10,
|
||||
.stats_type = STATS_TYPE_BANK0 | STATS_TYPE_PORT,
|
||||
.atu_move_port_mask = 0xf,
|
||||
.pvt = true,
|
||||
.multi_chip = true,
|
||||
@ -5848,6 +5841,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
|
||||
.age_time_coeff = 15000,
|
||||
.g1_irqs = 9,
|
||||
.g2_irqs = 10,
|
||||
.stats_type = STATS_TYPE_BANK0 | STATS_TYPE_PORT,
|
||||
.atu_move_port_mask = 0xf,
|
||||
.pvt = true,
|
||||
.multi_chip = true,
|
||||
@ -5872,6 +5866,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
|
||||
.age_time_coeff = 15000,
|
||||
.g1_irqs = 9,
|
||||
.g2_irqs = 10,
|
||||
.stats_type = STATS_TYPE_BANK0 | STATS_TYPE_BANK1,
|
||||
.atu_move_port_mask = 0xf,
|
||||
.pvt = true,
|
||||
.multi_chip = true,
|
||||
@ -5897,6 +5892,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
|
||||
.age_time_coeff = 15000,
|
||||
.g1_irqs = 9,
|
||||
.g2_irqs = 10,
|
||||
.stats_type = STATS_TYPE_BANK0 | STATS_TYPE_PORT,
|
||||
.atu_move_port_mask = 0xf,
|
||||
.pvt = true,
|
||||
.multi_chip = true,
|
||||
@ -5921,6 +5917,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
|
||||
.age_time_coeff = 15000,
|
||||
.g1_irqs = 9,
|
||||
.g2_irqs = 10,
|
||||
.stats_type = STATS_TYPE_BANK0 | STATS_TYPE_PORT,
|
||||
.atu_move_port_mask = 0xf,
|
||||
.pvt = true,
|
||||
.multi_chip = true,
|
||||
@ -5946,6 +5943,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
|
||||
.age_time_coeff = 15000,
|
||||
.g1_irqs = 9,
|
||||
.g2_irqs = 10,
|
||||
.stats_type = STATS_TYPE_BANK0 | STATS_TYPE_PORT,
|
||||
.atu_move_port_mask = 0xf,
|
||||
.pvt = true,
|
||||
.multi_chip = true,
|
||||
@ -5968,6 +5966,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
|
||||
.global2_addr = 0x1c,
|
||||
.age_time_coeff = 15000,
|
||||
.g1_irqs = 8,
|
||||
.stats_type = STATS_TYPE_BANK0 | STATS_TYPE_PORT,
|
||||
.atu_move_port_mask = 0xf,
|
||||
.multi_chip = true,
|
||||
.edsa_support = MV88E6XXX_EDSA_SUPPORTED,
|
||||
@ -5992,6 +5991,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
|
||||
.age_time_coeff = 3750,
|
||||
.g1_irqs = 9,
|
||||
.g2_irqs = 14,
|
||||
.stats_type = STATS_TYPE_BANK0 | STATS_TYPE_BANK1,
|
||||
.pvt = true,
|
||||
.multi_chip = true,
|
||||
.atu_move_port_mask = 0x1f,
|
||||
@ -6016,6 +6016,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
|
||||
.age_time_coeff = 3750,
|
||||
.g1_irqs = 9,
|
||||
.g2_irqs = 14,
|
||||
.stats_type = STATS_TYPE_BANK0 | STATS_TYPE_BANK1,
|
||||
.atu_move_port_mask = 0x1f,
|
||||
.pvt = true,
|
||||
.multi_chip = true,
|
||||
@ -6039,6 +6040,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
|
||||
.age_time_coeff = 3750,
|
||||
.g1_irqs = 9,
|
||||
.g2_irqs = 14,
|
||||
.stats_type = STATS_TYPE_BANK0 | STATS_TYPE_BANK1,
|
||||
.atu_move_port_mask = 0x1f,
|
||||
.pvt = true,
|
||||
.multi_chip = true,
|
||||
@ -6063,6 +6065,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
|
||||
.age_time_coeff = 3750,
|
||||
.g1_irqs = 10,
|
||||
.g2_irqs = 14,
|
||||
.stats_type = STATS_TYPE_BANK0 | STATS_TYPE_BANK1,
|
||||
.atu_move_port_mask = 0x1f,
|
||||
.pvt = true,
|
||||
.multi_chip = true,
|
||||
@ -6087,6 +6090,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
|
||||
.age_time_coeff = 3750,
|
||||
.g1_irqs = 10,
|
||||
.g2_irqs = 14,
|
||||
.stats_type = STATS_TYPE_BANK0 | STATS_TYPE_BANK1,
|
||||
.atu_move_port_mask = 0x1f,
|
||||
.pvt = true,
|
||||
.multi_chip = true,
|
||||
@ -6114,6 +6118,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
|
||||
.age_time_coeff = 15000,
|
||||
.g1_irqs = 9,
|
||||
.g2_irqs = 10,
|
||||
.stats_type = STATS_TYPE_BANK0,
|
||||
.atu_move_port_mask = 0xf,
|
||||
.dual_chip = true,
|
||||
.ptp_support = true,
|
||||
@ -6138,6 +6143,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
|
||||
.age_time_coeff = 15000,
|
||||
.g1_irqs = 9,
|
||||
.g2_irqs = 10,
|
||||
.stats_type = STATS_TYPE_BANK0 | STATS_TYPE_PORT,
|
||||
.atu_move_port_mask = 0xf,
|
||||
.pvt = true,
|
||||
.multi_chip = true,
|
||||
@ -6161,6 +6167,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
|
||||
.age_time_coeff = 15000,
|
||||
.g1_irqs = 9,
|
||||
.g2_irqs = 10,
|
||||
.stats_type = STATS_TYPE_BANK0,
|
||||
.atu_move_port_mask = 0xf,
|
||||
.dual_chip = true,
|
||||
.ptp_support = true,
|
||||
@ -6184,6 +6191,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
|
||||
.age_time_coeff = 3750,
|
||||
.g1_irqs = 9,
|
||||
.g2_irqs = 14,
|
||||
.stats_type = STATS_TYPE_BANK0 | STATS_TYPE_BANK1,
|
||||
.atu_move_port_mask = 0x1f,
|
||||
.pvt = true,
|
||||
.multi_chip = true,
|
||||
@ -6208,6 +6216,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
|
||||
.age_time_coeff = 15000,
|
||||
.g1_irqs = 8,
|
||||
.g2_irqs = 10,
|
||||
.stats_type = STATS_TYPE_BANK0 | STATS_TYPE_BANK1,
|
||||
.atu_move_port_mask = 0xf,
|
||||
.pvt = true,
|
||||
.multi_chip = true,
|
||||
@ -6233,6 +6242,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
|
||||
.age_time_coeff = 15000,
|
||||
.g1_irqs = 8,
|
||||
.g2_irqs = 10,
|
||||
.stats_type = STATS_TYPE_BANK0 | STATS_TYPE_BANK1,
|
||||
.atu_move_port_mask = 0xf,
|
||||
.multi_chip = true,
|
||||
.edsa_support = MV88E6XXX_EDSA_SUPPORTED,
|
||||
@ -6259,6 +6269,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
|
||||
.atu_move_port_mask = 0x1f,
|
||||
.g1_irqs = 9,
|
||||
.g2_irqs = 10,
|
||||
.stats_type = STATS_TYPE_BANK0 | STATS_TYPE_BANK1,
|
||||
.pvt = true,
|
||||
.multi_chip = true,
|
||||
.edsa_support = MV88E6XXX_EDSA_SUPPORTED,
|
||||
@ -6283,6 +6294,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
|
||||
.age_time_coeff = 15000,
|
||||
.g1_irqs = 9,
|
||||
.g2_irqs = 10,
|
||||
.stats_type = STATS_TYPE_BANK0 | STATS_TYPE_PORT,
|
||||
.atu_move_port_mask = 0xf,
|
||||
.pvt = true,
|
||||
.multi_chip = true,
|
||||
@ -6307,6 +6319,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
|
||||
.age_time_coeff = 15000,
|
||||
.g1_irqs = 9,
|
||||
.g2_irqs = 10,
|
||||
.stats_type = STATS_TYPE_BANK0 | STATS_TYPE_PORT,
|
||||
.atu_move_port_mask = 0xf,
|
||||
.pvt = true,
|
||||
.multi_chip = true,
|
||||
@ -6332,6 +6345,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
|
||||
.age_time_coeff = 15000,
|
||||
.g1_irqs = 9,
|
||||
.g2_irqs = 10,
|
||||
.stats_type = STATS_TYPE_BANK0 | STATS_TYPE_PORT,
|
||||
.atu_move_port_mask = 0xf,
|
||||
.pvt = true,
|
||||
.multi_chip = true,
|
||||
@ -6359,6 +6373,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
|
||||
.age_time_coeff = 3750,
|
||||
.g1_irqs = 10,
|
||||
.g2_irqs = 14,
|
||||
.stats_type = STATS_TYPE_BANK0 | STATS_TYPE_BANK1,
|
||||
.atu_move_port_mask = 0x1f,
|
||||
.pvt = true,
|
||||
.multi_chip = true,
|
||||
@ -6383,6 +6398,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
|
||||
.age_time_coeff = 3750,
|
||||
.g1_irqs = 9,
|
||||
.g2_irqs = 14,
|
||||
.stats_type = STATS_TYPE_BANK0 | STATS_TYPE_BANK1,
|
||||
.atu_move_port_mask = 0x1f,
|
||||
.pvt = true,
|
||||
.multi_chip = true,
|
||||
@ -6408,6 +6424,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
|
||||
.age_time_coeff = 3750,
|
||||
.g1_irqs = 9,
|
||||
.g2_irqs = 14,
|
||||
.stats_type = STATS_TYPE_BANK0 | STATS_TYPE_BANK1,
|
||||
.atu_move_port_mask = 0x1f,
|
||||
.pvt = true,
|
||||
.multi_chip = true,
|
||||
@ -6433,6 +6450,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
|
||||
.age_time_coeff = 3750,
|
||||
.g1_irqs = 10,
|
||||
.g2_irqs = 14,
|
||||
.stats_type = STATS_TYPE_BANK0 | STATS_TYPE_BANK1,
|
||||
.atu_move_port_mask = 0x1f,
|
||||
.pvt = true,
|
||||
.multi_chip = true,
|
||||
@ -7074,7 +7092,7 @@ static const struct dsa_switch_ops mv88e6xxx_switch_ops = {
|
||||
.get_sset_count = mv88e6xxx_get_sset_count,
|
||||
.port_max_mtu = mv88e6xxx_get_max_mtu,
|
||||
.port_change_mtu = mv88e6xxx_change_mtu,
|
||||
.get_mac_eee = mv88e6xxx_get_mac_eee,
|
||||
.support_eee = dsa_supports_eee,
|
||||
.set_mac_eee = mv88e6xxx_set_mac_eee,
|
||||
.get_eeprom_len = mv88e6xxx_get_eeprom_len,
|
||||
.get_eeprom = mv88e6xxx_get_eeprom,
|
||||
|
@ -144,6 +144,7 @@ struct mv88e6xxx_info {
|
||||
unsigned int age_time_coeff;
|
||||
unsigned int g1_irqs;
|
||||
unsigned int g2_irqs;
|
||||
int stats_type;
|
||||
bool pvt;
|
||||
|
||||
/* Mark certain ports as invalid. This is required for example for the
|
||||
|
@ -342,7 +342,7 @@ static int qca8k_read_eth(struct qca8k_priv *priv, u32 reg, u32 *val, int len)
|
||||
dev_queue_xmit(skb);
|
||||
|
||||
ret = wait_for_completion_timeout(&mgmt_eth_data->rw_done,
|
||||
msecs_to_jiffies(QCA8K_ETHERNET_TIMEOUT));
|
||||
QCA8K_ETHERNET_TIMEOUT);
|
||||
|
||||
*val = mgmt_eth_data->data[0];
|
||||
if (len > QCA_HDR_MGMT_DATA1_LEN)
|
||||
@ -394,7 +394,7 @@ static int qca8k_write_eth(struct qca8k_priv *priv, u32 reg, u32 *val, int len)
|
||||
dev_queue_xmit(skb);
|
||||
|
||||
ret = wait_for_completion_timeout(&mgmt_eth_data->rw_done,
|
||||
msecs_to_jiffies(QCA8K_ETHERNET_TIMEOUT));
|
||||
QCA8K_ETHERNET_TIMEOUT);
|
||||
|
||||
ack = mgmt_eth_data->ack;
|
||||
|
||||
@ -1019,7 +1019,7 @@ qca8k_setup_mdio_bus(struct qca8k_priv *priv)
|
||||
|
||||
of_get_phy_mode(port, &mode);
|
||||
|
||||
if (of_property_read_bool(port, "phy-handle") &&
|
||||
if (of_property_present(port, "phy-handle") &&
|
||||
mode != PHY_INTERFACE_MODE_INTERNAL)
|
||||
external_mdio_mask |= BIT(reg);
|
||||
else
|
||||
@ -2016,7 +2016,7 @@ static const struct dsa_switch_ops qca8k_switch_ops = {
|
||||
.get_ethtool_stats = qca8k_get_ethtool_stats,
|
||||
.get_sset_count = qca8k_get_sset_count,
|
||||
.set_ageing_time = qca8k_set_ageing_time,
|
||||
.get_mac_eee = qca8k_get_mac_eee,
|
||||
.support_eee = dsa_supports_eee,
|
||||
.set_mac_eee = qca8k_set_mac_eee,
|
||||
.port_enable = qca8k_port_enable,
|
||||
.port_disable = qca8k_port_disable,
|
||||
|
@ -557,13 +557,6 @@ exit:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int qca8k_get_mac_eee(struct dsa_switch *ds, int port,
|
||||
struct ethtool_keee *e)
|
||||
{
|
||||
/* Nothing to do on the port's MAC */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int qca8k_port_configure_learning(struct dsa_switch *ds, int port,
|
||||
bool learning)
|
||||
{
|
||||
|
@ -16,7 +16,7 @@
|
||||
|
||||
#define QCA8K_ETHERNET_MDIO_PRIORITY 7
|
||||
#define QCA8K_ETHERNET_PHY_PRIORITY 6
|
||||
#define QCA8K_ETHERNET_TIMEOUT 5
|
||||
#define QCA8K_ETHERNET_TIMEOUT msecs_to_jiffies(5)
|
||||
|
||||
#define QCA8K_NUM_PORTS 7
|
||||
#define QCA8K_NUM_CPU_PORTS 2
|
||||
@ -520,7 +520,6 @@ int qca8k_get_sset_count(struct dsa_switch *ds, int port, int sset);
|
||||
|
||||
/* Common eee function */
|
||||
int qca8k_set_mac_eee(struct dsa_switch *ds, int port, struct ethtool_keee *eee);
|
||||
int qca8k_get_mac_eee(struct dsa_switch *ds, int port, struct ethtool_keee *e);
|
||||
|
||||
/* Common bridge function */
|
||||
void qca8k_port_stp_state_set(struct dsa_switch *ds, int port, u8 state);
|
||||
|
@ -26,12 +26,8 @@ void sja1105_pack(void *buf, const u64 *val, int start, int end, size_t len)
|
||||
pr_err("Start bit (%d) expected to be larger than end (%d)\n",
|
||||
start, end);
|
||||
} else if (rc == -ERANGE) {
|
||||
if ((start - end + 1) > 64)
|
||||
pr_err("Field %d-%d too large for 64 bits!\n",
|
||||
start, end);
|
||||
else
|
||||
pr_err("Cannot store %llx inside bits %d-%d (would truncate)\n",
|
||||
*val, start, end);
|
||||
}
|
||||
dump_stack();
|
||||
}
|
||||
|
@ -159,7 +159,7 @@ config ETHOC
|
||||
Say Y here if you want to use the OpenCores 10/100 Mbps Ethernet MAC.
|
||||
|
||||
config OA_TC6
|
||||
tristate "OPEN Alliance TC6 10BASE-T1x MAC-PHY support"
|
||||
tristate "OPEN Alliance TC6 10BASE-T1x MAC-PHY support" if COMPILE_TEST
|
||||
depends on SPI
|
||||
select PHYLIB
|
||||
help
|
||||
|
@ -421,18 +421,12 @@ static void xgene_enet_configure_clock(struct xgene_enet_pdata *pdata)
|
||||
|
||||
if (dev->of_node) {
|
||||
struct clk *parent = clk_get_parent(pdata->clk);
|
||||
long rate = rgmii_clock(pdata->phy_speed);
|
||||
|
||||
switch (pdata->phy_speed) {
|
||||
case SPEED_10:
|
||||
clk_set_rate(parent, 2500000);
|
||||
break;
|
||||
case SPEED_100:
|
||||
clk_set_rate(parent, 25000000);
|
||||
break;
|
||||
default:
|
||||
clk_set_rate(parent, 125000000);
|
||||
break;
|
||||
}
|
||||
if (rate < 0)
|
||||
rate = 125000000;
|
||||
|
||||
clk_set_rate(parent, rate);
|
||||
}
|
||||
#ifdef CONFIG_ACPI
|
||||
else {
|
||||
|
@ -8322,16 +8322,20 @@ static int bnxt_hwrm_func_qcfg(struct bnxt *bp)
|
||||
if (rc)
|
||||
goto func_qcfg_exit;
|
||||
|
||||
flags = le16_to_cpu(resp->flags);
|
||||
#ifdef CONFIG_BNXT_SRIOV
|
||||
if (BNXT_VF(bp)) {
|
||||
struct bnxt_vf_info *vf = &bp->vf;
|
||||
|
||||
vf->vlan = le16_to_cpu(resp->vlan) & VLAN_VID_MASK;
|
||||
if (flags & FUNC_QCFG_RESP_FLAGS_TRUSTED_VF)
|
||||
vf->flags |= BNXT_VF_TRUST;
|
||||
else
|
||||
vf->flags &= ~BNXT_VF_TRUST;
|
||||
} else {
|
||||
bp->pf.registered_vfs = le16_to_cpu(resp->registered_vfs);
|
||||
}
|
||||
#endif
|
||||
flags = le16_to_cpu(resp->flags);
|
||||
if (flags & (FUNC_QCFG_RESP_FLAGS_FW_DCBX_AGENT_ENABLED |
|
||||
FUNC_QCFG_RESP_FLAGS_FW_LLDP_AGENT_ENABLED)) {
|
||||
bp->fw_cap |= BNXT_FW_CAP_LLDP_AGENT;
|
||||
@ -9160,10 +9164,18 @@ static int bnxt_alloc_ctx_mem(struct bnxt *bp)
|
||||
ena = 0;
|
||||
if ((bp->flags & BNXT_FLAG_ROCE_CAP) && !is_kdump_kernel()) {
|
||||
pg_lvl = 2;
|
||||
extra_qps = min_t(u32, 65536, max_qps - l2_qps - qp1_qps);
|
||||
/* allocate extra qps if fw supports RoCE fast qp destroy feature */
|
||||
if (BNXT_SW_RES_LMT(bp)) {
|
||||
extra_qps = max_qps - l2_qps - qp1_qps;
|
||||
extra_srqs = max_srqs - srqs;
|
||||
} else {
|
||||
extra_qps = min_t(u32, 65536,
|
||||
max_qps - l2_qps - qp1_qps);
|
||||
/* allocate extra qps if fw supports RoCE fast qp
|
||||
* destroy feature
|
||||
*/
|
||||
extra_qps += fast_qpmd_qps;
|
||||
extra_srqs = min_t(u32, 8192, max_srqs - srqs);
|
||||
}
|
||||
if (fast_qpmd_qps)
|
||||
ena |= FUNC_BACKING_STORE_CFG_REQ_ENABLES_QP_FAST_QPMD;
|
||||
}
|
||||
@ -9199,6 +9211,11 @@ static int bnxt_alloc_ctx_mem(struct bnxt *bp)
|
||||
goto skip_rdma;
|
||||
|
||||
ctxm = &ctx->ctx_arr[BNXT_CTX_MRAV];
|
||||
if (BNXT_SW_RES_LMT(bp) &&
|
||||
ctxm->split_entry_cnt == BNXT_CTX_MRAV_AV_SPLIT_ENTRY + 1) {
|
||||
num_ah = ctxm->mrav_av_entries;
|
||||
num_mr = ctxm->max_entries - num_ah;
|
||||
} else {
|
||||
/* 128K extra is needed to accommodate static AH context
|
||||
* allocation by f/w.
|
||||
*/
|
||||
@ -9207,6 +9224,7 @@ static int bnxt_alloc_ctx_mem(struct bnxt *bp)
|
||||
ctxm->split_entry_cnt = BNXT_CTX_MRAV_AV_SPLIT_ENTRY + 1;
|
||||
if (!ctxm->mrav_av_entries || ctxm->mrav_av_entries > num_ah)
|
||||
ctxm->mrav_av_entries = num_ah;
|
||||
}
|
||||
|
||||
rc = bnxt_setup_ctxm_pg_tbls(bp, ctxm, num_mr + num_ah, 2);
|
||||
if (rc)
|
||||
@ -9513,6 +9531,9 @@ static int __bnxt_hwrm_func_qcaps(struct bnxt *bp)
|
||||
bp->flags |= BNXT_FLAG_UDP_GSO_CAP;
|
||||
if (flags_ext2 & FUNC_QCAPS_RESP_FLAGS_EXT2_TX_PKT_TS_CMPL_SUPPORTED)
|
||||
bp->fw_cap |= BNXT_FW_CAP_TX_TS_CMP;
|
||||
if (flags_ext2 &
|
||||
FUNC_QCAPS_RESP_FLAGS_EXT2_SW_MAX_RESOURCE_LIMITS_SUPPORTED)
|
||||
bp->fw_cap |= BNXT_FW_CAP_SW_MAX_RESOURCE_LIMITS;
|
||||
if (BNXT_PF(bp) &&
|
||||
(flags_ext2 & FUNC_QCAPS_RESP_FLAGS_EXT2_ROCE_VF_RESOURCE_MGMT_SUPPORTED))
|
||||
bp->fw_cap |= BNXT_FW_CAP_ROCE_VF_RESC_MGMT_SUPPORTED;
|
||||
@ -11571,6 +11592,26 @@ hwrm_phy_qcaps_exit:
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void bnxt_hwrm_mac_qcaps(struct bnxt *bp)
|
||||
{
|
||||
struct hwrm_port_mac_qcaps_output *resp;
|
||||
struct hwrm_port_mac_qcaps_input *req;
|
||||
int rc;
|
||||
|
||||
if (bp->hwrm_spec_code < 0x10a03)
|
||||
return;
|
||||
|
||||
rc = hwrm_req_init(bp, req, HWRM_PORT_MAC_QCAPS);
|
||||
if (rc)
|
||||
return;
|
||||
|
||||
resp = hwrm_req_hold(bp, req);
|
||||
rc = hwrm_req_send_silent(bp, req);
|
||||
if (!rc)
|
||||
bp->mac_flags = resp->flags;
|
||||
hwrm_req_drop(bp, req);
|
||||
}
|
||||
|
||||
static bool bnxt_support_dropped(u16 advertising, u16 supported)
|
||||
{
|
||||
u16 diff = advertising ^ supported;
|
||||
@ -15701,6 +15742,10 @@ static int bnxt_probe_phy(struct bnxt *bp, bool fw_dflt)
|
||||
bp->dev->priv_flags |= IFF_SUPP_NOFCS;
|
||||
else
|
||||
bp->dev->priv_flags &= ~IFF_SUPP_NOFCS;
|
||||
|
||||
bp->mac_flags = 0;
|
||||
bnxt_hwrm_mac_qcaps(bp);
|
||||
|
||||
if (!fw_dflt)
|
||||
return 0;
|
||||
|
||||
|
@ -2270,6 +2270,11 @@ struct bnxt {
|
||||
|
||||
#define BNXT_PF(bp) (!((bp)->flags & BNXT_FLAG_VF))
|
||||
#define BNXT_VF(bp) ((bp)->flags & BNXT_FLAG_VF)
|
||||
#ifdef CONFIG_BNXT_SRIOV
|
||||
#define BNXT_VF_IS_TRUSTED(bp) ((bp)->vf.flags & BNXT_VF_TRUST)
|
||||
#else
|
||||
#define BNXT_VF_IS_TRUSTED(bp) 0
|
||||
#endif
|
||||
#define BNXT_NPAR(bp) ((bp)->port_partition_type)
|
||||
#define BNXT_MH(bp) ((bp)->flags & BNXT_FLAG_MULTI_HOST)
|
||||
#define BNXT_SINGLE_PF(bp) (BNXT_PF(bp) && !BNXT_NPAR(bp) && !BNXT_MH(bp))
|
||||
@ -2482,6 +2487,7 @@ struct bnxt {
|
||||
#define BNXT_FW_CAP_CFA_NTUPLE_RX_EXT_IP_PROTO BIT_ULL(38)
|
||||
#define BNXT_FW_CAP_CFA_RFS_RING_TBL_IDX_V3 BIT_ULL(39)
|
||||
#define BNXT_FW_CAP_VNIC_RE_FLUSH BIT_ULL(40)
|
||||
#define BNXT_FW_CAP_SW_MAX_RESOURCE_LIMITS BIT_ULL(41)
|
||||
|
||||
u32 fw_dbg_cap;
|
||||
|
||||
@ -2501,6 +2507,8 @@ struct bnxt {
|
||||
((bp)->fw_cap & BNXT_FW_CAP_ENABLE_RDMA_SRIOV)
|
||||
#define BNXT_ROCE_VF_RESC_CAP(bp) \
|
||||
((bp)->fw_cap & BNXT_FW_CAP_ROCE_VF_RESC_MGMT_SUPPORTED)
|
||||
#define BNXT_SW_RES_LMT(bp) \
|
||||
((bp)->fw_cap & BNXT_FW_CAP_SW_MAX_RESOURCE_LIMITS)
|
||||
|
||||
u32 hwrm_spec_code;
|
||||
u16 hwrm_cmd_seq;
|
||||
@ -2660,6 +2668,11 @@ struct bnxt {
|
||||
#define BNXT_PHY_FL_BANK_SEL (PORT_PHY_QCAPS_RESP_FLAGS2_BANK_ADDR_SUPPORTED << 8)
|
||||
#define BNXT_PHY_FL_SPEEDS2 (PORT_PHY_QCAPS_RESP_FLAGS2_SPEEDS2_SUPPORTED << 8)
|
||||
|
||||
/* copied from flags in hwrm_port_mac_qcaps_output */
|
||||
u8 mac_flags;
|
||||
#define BNXT_MAC_FL_NO_MAC_LPBK \
|
||||
PORT_MAC_QCAPS_RESP_FLAGS_LOCAL_LPBK_NOT_SUPPORTED
|
||||
|
||||
u8 num_tests;
|
||||
struct bnxt_test_info *test_info;
|
||||
|
||||
|
@ -2050,6 +2050,7 @@ static void bnxt_get_regs(struct net_device *dev, struct ethtool_regs *regs,
|
||||
int rc;
|
||||
|
||||
regs->version = 0;
|
||||
if (!(bp->fw_dbg_cap & DBG_QCAPS_RESP_FLAGS_REG_ACCESS_RESTRICTED))
|
||||
bnxt_dbg_hwrm_rd_reg(bp, 0, BNXT_PXP_REG_LEN / 4, _p);
|
||||
|
||||
if (!(bp->fw_cap & BNXT_FW_CAP_PCIE_STATS_SUPPORTED))
|
||||
@ -4375,6 +4376,9 @@ static int bnxt_get_module_info(struct net_device *dev,
|
||||
struct bnxt *bp = netdev_priv(dev);
|
||||
int rc;
|
||||
|
||||
if (BNXT_VF(bp) && !BNXT_VF_IS_TRUSTED(bp))
|
||||
return -EPERM;
|
||||
|
||||
/* No point in going further if phy status indicates
|
||||
* module is not inserted or if it is powered down or
|
||||
* if it is of type 10GBase-T
|
||||
@ -4426,6 +4430,9 @@ static int bnxt_get_module_eeprom(struct net_device *dev,
|
||||
u16 start = eeprom->offset, length = eeprom->len;
|
||||
int rc = 0;
|
||||
|
||||
if (BNXT_VF(bp) && !BNXT_VF_IS_TRUSTED(bp))
|
||||
return -EPERM;
|
||||
|
||||
memset(data, 0, eeprom->len);
|
||||
|
||||
/* Read A0 portion of the EEPROM */
|
||||
@ -4480,6 +4487,12 @@ static int bnxt_get_module_eeprom_by_page(struct net_device *dev,
|
||||
struct bnxt *bp = netdev_priv(dev);
|
||||
int rc;
|
||||
|
||||
if (BNXT_VF(bp) && !BNXT_VF_IS_TRUSTED(bp)) {
|
||||
NL_SET_ERR_MSG_MOD(extack,
|
||||
"Module read not permitted on untrusted VF");
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
rc = bnxt_get_module_status(bp, extack);
|
||||
if (rc)
|
||||
return rc;
|
||||
@ -4887,35 +4900,44 @@ static void bnxt_self_test(struct net_device *dev, struct ethtool_test *etest,
|
||||
bnxt_close_nic(bp, true, false);
|
||||
bnxt_run_fw_tests(bp, test_mask, &test_results);
|
||||
|
||||
buf[BNXT_MACLPBK_TEST_IDX] = 1;
|
||||
bnxt_hwrm_mac_loopback(bp, true);
|
||||
msleep(250);
|
||||
rc = bnxt_half_open_nic(bp);
|
||||
if (rc) {
|
||||
bnxt_hwrm_mac_loopback(bp, false);
|
||||
etest->flags |= ETH_TEST_FL_FAILED;
|
||||
return;
|
||||
}
|
||||
buf[BNXT_MACLPBK_TEST_IDX] = 1;
|
||||
if (bp->mac_flags & BNXT_MAC_FL_NO_MAC_LPBK)
|
||||
goto skip_mac_loopback;
|
||||
|
||||
bnxt_hwrm_mac_loopback(bp, true);
|
||||
msleep(250);
|
||||
if (bnxt_run_loopback(bp))
|
||||
etest->flags |= ETH_TEST_FL_FAILED;
|
||||
else
|
||||
buf[BNXT_MACLPBK_TEST_IDX] = 0;
|
||||
|
||||
bnxt_hwrm_mac_loopback(bp, false);
|
||||
skip_mac_loopback:
|
||||
buf[BNXT_PHYLPBK_TEST_IDX] = 1;
|
||||
if (bp->phy_flags & BNXT_PHY_FL_NO_PHY_LPBK)
|
||||
goto skip_phy_loopback;
|
||||
|
||||
bnxt_hwrm_phy_loopback(bp, true, false);
|
||||
msleep(1000);
|
||||
if (bnxt_run_loopback(bp)) {
|
||||
buf[BNXT_PHYLPBK_TEST_IDX] = 1;
|
||||
if (bnxt_run_loopback(bp))
|
||||
etest->flags |= ETH_TEST_FL_FAILED;
|
||||
}
|
||||
else
|
||||
buf[BNXT_PHYLPBK_TEST_IDX] = 0;
|
||||
skip_phy_loopback:
|
||||
buf[BNXT_EXTLPBK_TEST_IDX] = 1;
|
||||
if (do_ext_lpbk) {
|
||||
etest->flags |= ETH_TEST_FL_EXTERNAL_LB_DONE;
|
||||
bnxt_hwrm_phy_loopback(bp, true, true);
|
||||
msleep(1000);
|
||||
if (bnxt_run_loopback(bp)) {
|
||||
buf[BNXT_EXTLPBK_TEST_IDX] = 1;
|
||||
if (bnxt_run_loopback(bp))
|
||||
etest->flags |= ETH_TEST_FL_FAILED;
|
||||
}
|
||||
else
|
||||
buf[BNXT_EXTLPBK_TEST_IDX] = 0;
|
||||
}
|
||||
bnxt_hwrm_phy_loopback(bp, false, false);
|
||||
bnxt_half_close_nic(bp);
|
||||
|
@ -417,6 +417,8 @@ static void bnxt_set_edev_info(struct bnxt_en_dev *edev, struct bnxt *bp)
|
||||
edev->flags |= BNXT_EN_FLAG_VF;
|
||||
if (BNXT_ROCE_VF_RESC_CAP(bp))
|
||||
edev->flags |= BNXT_EN_FLAG_ROCE_VF_RES_MGMT;
|
||||
if (BNXT_SW_RES_LMT(bp))
|
||||
edev->flags |= BNXT_EN_FLAG_SW_RES_LMT;
|
||||
|
||||
edev->chip_num = bp->chip_num;
|
||||
edev->hw_ring_stats_size = bp->hw_ring_stats_size;
|
||||
|
@ -65,6 +65,8 @@ struct bnxt_en_dev {
|
||||
#define BNXT_EN_FLAG_VF 0x10
|
||||
#define BNXT_EN_VF(edev) ((edev)->flags & BNXT_EN_FLAG_VF)
|
||||
#define BNXT_EN_FLAG_ROCE_VF_RES_MGMT 0x20
|
||||
#define BNXT_EN_FLAG_SW_RES_LMT 0x40
|
||||
#define BNXT_EN_SW_RES_LMT(edev) ((edev)->flags & BNXT_EN_FLAG_SW_RES_LMT)
|
||||
|
||||
struct bnxt_ulp *ulp_tbl;
|
||||
int l2_db_size; /* Doorbell BAR size in
|
||||
|
@ -530,19 +530,9 @@ static void macb_set_tx_clk(struct macb *bp, int speed)
|
||||
if (bp->phy_interface == PHY_INTERFACE_MODE_MII)
|
||||
return;
|
||||
|
||||
switch (speed) {
|
||||
case SPEED_10:
|
||||
rate = 2500000;
|
||||
break;
|
||||
case SPEED_100:
|
||||
rate = 25000000;
|
||||
break;
|
||||
case SPEED_1000:
|
||||
rate = 125000000;
|
||||
break;
|
||||
default:
|
||||
rate = rgmii_clock(speed);
|
||||
if (rate < 0)
|
||||
return;
|
||||
}
|
||||
|
||||
rate_rounded = clk_round_rate(bp->tx_clk, rate);
|
||||
if (rate_rounded < 0)
|
||||
|
@ -6562,6 +6562,9 @@ static void cxgb4_advance_esn_state(struct xfrm_state *x)
|
||||
{
|
||||
struct adapter *adap = netdev2adap(x->xso.dev);
|
||||
|
||||
if (x->xso.dir != XFRM_DEV_OFFLOAD_IN)
|
||||
return;
|
||||
|
||||
if (!mutex_trylock(&uld_mutex)) {
|
||||
dev_dbg(adap->pdev_dev,
|
||||
"crypto uld critical resource is under use\n");
|
||||
|
@ -109,7 +109,7 @@ static struct enic_intr_mod_table mod_table[ENIC_MAX_COALESCE_TIMERS + 1] = {
|
||||
static struct enic_intr_mod_range mod_range[ENIC_MAX_LINK_SPEEDS] = {
|
||||
{0, 0}, /* 0 - 4 Gbps */
|
||||
{0, 3}, /* 4 - 10 Gbps */
|
||||
{3, 6}, /* 10 - 40 Gbps */
|
||||
{3, 6}, /* 10+ Gbps */
|
||||
};
|
||||
|
||||
static void enic_init_affinity_hint(struct enic *enic)
|
||||
@ -428,6 +428,36 @@ static void enic_mtu_check(struct enic *enic)
|
||||
}
|
||||
}
|
||||
|
||||
static void enic_set_rx_coal_setting(struct enic *enic)
|
||||
{
|
||||
unsigned int speed;
|
||||
int index = -1;
|
||||
struct enic_rx_coal *rx_coal = &enic->rx_coalesce_setting;
|
||||
|
||||
/* 1. Read the link speed from fw
|
||||
* 2. Pick the default range for the speed
|
||||
* 3. Update it in enic->rx_coalesce_setting
|
||||
*/
|
||||
speed = vnic_dev_port_speed(enic->vdev);
|
||||
if (speed > ENIC_LINK_SPEED_10G)
|
||||
index = ENIC_LINK_40G_INDEX;
|
||||
else if (speed > ENIC_LINK_SPEED_4G)
|
||||
index = ENIC_LINK_10G_INDEX;
|
||||
else
|
||||
index = ENIC_LINK_4G_INDEX;
|
||||
|
||||
rx_coal->small_pkt_range_start = mod_range[index].small_pkt_range_start;
|
||||
rx_coal->large_pkt_range_start = mod_range[index].large_pkt_range_start;
|
||||
rx_coal->range_end = ENIC_RX_COALESCE_RANGE_END;
|
||||
|
||||
/* Start with the value provided by UCSM */
|
||||
for (index = 0; index < enic->rq_count; index++)
|
||||
enic->cq[index].cur_rx_coal_timeval =
|
||||
enic->config.intr_timer_usec;
|
||||
|
||||
rx_coal->use_adaptive_rx_coalesce = 1;
|
||||
}
|
||||
|
||||
static void enic_link_check(struct enic *enic)
|
||||
{
|
||||
int link_status = vnic_dev_link_status(enic->vdev);
|
||||
@ -436,6 +466,7 @@ static void enic_link_check(struct enic *enic)
|
||||
if (link_status && !carrier_ok) {
|
||||
netdev_info(enic->netdev, "Link UP\n");
|
||||
netif_carrier_on(enic->netdev);
|
||||
enic_set_rx_coal_setting(enic);
|
||||
} else if (!link_status && carrier_ok) {
|
||||
netdev_info(enic->netdev, "Link DOWN\n");
|
||||
netif_carrier_off(enic->netdev);
|
||||
@ -1901,36 +1932,6 @@ static void enic_synchronize_irqs(struct enic *enic)
|
||||
}
|
||||
}
|
||||
|
||||
static void enic_set_rx_coal_setting(struct enic *enic)
|
||||
{
|
||||
unsigned int speed;
|
||||
int index = -1;
|
||||
struct enic_rx_coal *rx_coal = &enic->rx_coalesce_setting;
|
||||
|
||||
/* 1. Read the link speed from fw
|
||||
* 2. Pick the default range for the speed
|
||||
* 3. Update it in enic->rx_coalesce_setting
|
||||
*/
|
||||
speed = vnic_dev_port_speed(enic->vdev);
|
||||
if (ENIC_LINK_SPEED_10G < speed)
|
||||
index = ENIC_LINK_40G_INDEX;
|
||||
else if (ENIC_LINK_SPEED_4G < speed)
|
||||
index = ENIC_LINK_10G_INDEX;
|
||||
else
|
||||
index = ENIC_LINK_4G_INDEX;
|
||||
|
||||
rx_coal->small_pkt_range_start = mod_range[index].small_pkt_range_start;
|
||||
rx_coal->large_pkt_range_start = mod_range[index].large_pkt_range_start;
|
||||
rx_coal->range_end = ENIC_RX_COALESCE_RANGE_END;
|
||||
|
||||
/* Start with the value provided by UCSM */
|
||||
for (index = 0; index < enic->rq_count; index++)
|
||||
enic->cq[index].cur_rx_coal_timeval =
|
||||
enic->config.intr_timer_usec;
|
||||
|
||||
rx_coal->use_adaptive_rx_coalesce = 1;
|
||||
}
|
||||
|
||||
static int enic_dev_notify_set(struct enic *enic)
|
||||
{
|
||||
int err;
|
||||
@ -3063,7 +3064,6 @@ static int enic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
timer_setup(&enic->notify_timer, enic_notify_timer, 0);
|
||||
|
||||
enic_rfs_flw_tbl_init(enic);
|
||||
enic_set_rx_coal_setting(enic);
|
||||
INIT_WORK(&enic->reset, enic_reset);
|
||||
INIT_WORK(&enic->tx_hang_reset, enic_tx_hang_reset);
|
||||
INIT_WORK(&enic->change_mtu_work, enic_change_mtu_work);
|
||||
|
@ -81,8 +81,7 @@ config UCC_GETH
|
||||
tristate "Freescale QE Gigabit Ethernet"
|
||||
depends on QUICC_ENGINE && PPC32
|
||||
select FSL_PQ_MDIO
|
||||
select PHYLIB
|
||||
select FIXED_PHY
|
||||
select PHYLINK
|
||||
help
|
||||
This driver supports the Gigabit Ethernet mode of the QUICC Engine,
|
||||
which is available on some Freescale SOCs.
|
||||
|
@ -2281,7 +2281,7 @@ static int dpaa_a050385_wa_xdpf(struct dpaa_priv *priv,
|
||||
new_xdpf->len = xdpf->len;
|
||||
new_xdpf->headroom = priv->tx_headroom;
|
||||
new_xdpf->frame_sz = DPAA_BP_RAW_SIZE;
|
||||
new_xdpf->mem.type = MEM_TYPE_PAGE_ORDER0;
|
||||
new_xdpf->mem_type = MEM_TYPE_PAGE_ORDER0;
|
||||
|
||||
/* Release the initial buffer */
|
||||
xdp_return_frame_rx_napi(xdpf);
|
||||
|
@ -780,13 +780,14 @@ struct ethsw_dump_ctx {
|
||||
static int dpaa2_switch_fdb_dump_nl(struct fdb_dump_entry *entry,
|
||||
struct ethsw_dump_ctx *dump)
|
||||
{
|
||||
struct ndo_fdb_dump_context *ctx = (void *)dump->cb->ctx;
|
||||
int is_dynamic = entry->type & DPSW_FDB_ENTRY_DINAMIC;
|
||||
u32 portid = NETLINK_CB(dump->cb->skb).portid;
|
||||
u32 seq = dump->cb->nlh->nlmsg_seq;
|
||||
struct nlmsghdr *nlh;
|
||||
struct ndmsg *ndm;
|
||||
|
||||
if (dump->idx < dump->cb->args[2])
|
||||
if (dump->idx < ctx->fdb_idx)
|
||||
goto skip;
|
||||
|
||||
nlh = nlmsg_put(dump->skb, portid, seq, RTM_NEWNEIGH,
|
||||
|
@ -146,6 +146,27 @@ static int enetc_ptp_parse(struct sk_buff *skb, u8 *udp,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool enetc_tx_csum_offload_check(struct sk_buff *skb)
|
||||
{
|
||||
switch (skb->csum_offset) {
|
||||
case offsetof(struct tcphdr, check):
|
||||
case offsetof(struct udphdr, check):
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static bool enetc_skb_is_ipv6(struct sk_buff *skb)
|
||||
{
|
||||
return vlan_get_protocol(skb) == htons(ETH_P_IPV6);
|
||||
}
|
||||
|
||||
static bool enetc_skb_is_tcp(struct sk_buff *skb)
|
||||
{
|
||||
return skb->csum_offset == offsetof(struct tcphdr, check);
|
||||
}
|
||||
|
||||
static int enetc_map_tx_buffs(struct enetc_bdr *tx_ring, struct sk_buff *skb)
|
||||
{
|
||||
bool do_vlan, do_onestep_tstamp = false, do_twostep_tstamp = false;
|
||||
@ -163,6 +184,29 @@ static int enetc_map_tx_buffs(struct enetc_bdr *tx_ring, struct sk_buff *skb)
|
||||
dma_addr_t dma;
|
||||
u8 flags = 0;
|
||||
|
||||
enetc_clear_tx_bd(&temp_bd);
|
||||
if (skb->ip_summed == CHECKSUM_PARTIAL) {
|
||||
/* Can not support TSD and checksum offload at the same time */
|
||||
if (priv->active_offloads & ENETC_F_TXCSUM &&
|
||||
enetc_tx_csum_offload_check(skb) && !tx_ring->tsd_enable) {
|
||||
temp_bd.l3_aux0 = FIELD_PREP(ENETC_TX_BD_L3_START,
|
||||
skb_network_offset(skb));
|
||||
temp_bd.l3_aux1 = FIELD_PREP(ENETC_TX_BD_L3_HDR_LEN,
|
||||
skb_network_header_len(skb) / 4);
|
||||
temp_bd.l3_aux1 |= FIELD_PREP(ENETC_TX_BD_L3T,
|
||||
enetc_skb_is_ipv6(skb));
|
||||
if (enetc_skb_is_tcp(skb))
|
||||
temp_bd.l4_aux = FIELD_PREP(ENETC_TX_BD_L4T,
|
||||
ENETC_TXBD_L4T_TCP);
|
||||
else
|
||||
temp_bd.l4_aux = FIELD_PREP(ENETC_TX_BD_L4T,
|
||||
ENETC_TXBD_L4T_UDP);
|
||||
flags |= ENETC_TXBD_FLAGS_CSUM_LSO | ENETC_TXBD_FLAGS_L4CS;
|
||||
} else if (skb_checksum_help(skb)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
i = tx_ring->next_to_use;
|
||||
txbd = ENETC_TXBD(*tx_ring, i);
|
||||
prefetchw(txbd);
|
||||
@ -173,7 +217,6 @@ static int enetc_map_tx_buffs(struct enetc_bdr *tx_ring, struct sk_buff *skb)
|
||||
|
||||
temp_bd.addr = cpu_to_le64(dma);
|
||||
temp_bd.buf_len = cpu_to_le16(len);
|
||||
temp_bd.lstatus = 0;
|
||||
|
||||
tx_swbd = &tx_ring->tx_swbd[i];
|
||||
tx_swbd->dma = dma;
|
||||
@ -489,8 +532,233 @@ static void enetc_tso_complete_csum(struct enetc_bdr *tx_ring, struct tso_t *tso
|
||||
}
|
||||
}
|
||||
|
||||
static int enetc_lso_count_descs(const struct sk_buff *skb)
|
||||
{
|
||||
/* 4 BDs: 1 BD for LSO header + 1 BD for extended BD + 1 BD
|
||||
* for linear area data but not include LSO header, namely
|
||||
* skb_headlen(skb) - lso_hdr_len (it may be 0, but that's
|
||||
* okay, we only need to consider the worst case). And 1 BD
|
||||
* for gap.
|
||||
*/
|
||||
return skb_shinfo(skb)->nr_frags + 4;
|
||||
}
|
||||
|
||||
static int enetc_lso_get_hdr_len(const struct sk_buff *skb)
|
||||
{
|
||||
int hdr_len, tlen;
|
||||
|
||||
tlen = skb_is_gso_tcp(skb) ? tcp_hdrlen(skb) : sizeof(struct udphdr);
|
||||
hdr_len = skb_transport_offset(skb) + tlen;
|
||||
|
||||
return hdr_len;
|
||||
}
|
||||
|
||||
static void enetc_lso_start(struct sk_buff *skb, struct enetc_lso_t *lso)
|
||||
{
|
||||
lso->lso_seg_size = skb_shinfo(skb)->gso_size;
|
||||
lso->ipv6 = enetc_skb_is_ipv6(skb);
|
||||
lso->tcp = skb_is_gso_tcp(skb);
|
||||
lso->l3_hdr_len = skb_network_header_len(skb);
|
||||
lso->l3_start = skb_network_offset(skb);
|
||||
lso->hdr_len = enetc_lso_get_hdr_len(skb);
|
||||
lso->total_len = skb->len - lso->hdr_len;
|
||||
}
|
||||
|
||||
static void enetc_lso_map_hdr(struct enetc_bdr *tx_ring, struct sk_buff *skb,
|
||||
int *i, struct enetc_lso_t *lso)
|
||||
{
|
||||
union enetc_tx_bd txbd_tmp, *txbd;
|
||||
struct enetc_tx_swbd *tx_swbd;
|
||||
u16 frm_len, frm_len_ext;
|
||||
u8 flags, e_flags = 0;
|
||||
dma_addr_t addr;
|
||||
char *hdr;
|
||||
|
||||
/* Get the first BD of the LSO BDs chain */
|
||||
txbd = ENETC_TXBD(*tx_ring, *i);
|
||||
tx_swbd = &tx_ring->tx_swbd[*i];
|
||||
prefetchw(txbd);
|
||||
|
||||
/* Prepare LSO header: MAC + IP + TCP/UDP */
|
||||
hdr = tx_ring->tso_headers + *i * TSO_HEADER_SIZE;
|
||||
memcpy(hdr, skb->data, lso->hdr_len);
|
||||
addr = tx_ring->tso_headers_dma + *i * TSO_HEADER_SIZE;
|
||||
|
||||
/* {frm_len_ext, frm_len} indicates the total length of
|
||||
* large transmit data unit. frm_len contains the 16 least
|
||||
* significant bits and frm_len_ext contains the 4 most
|
||||
* significant bits.
|
||||
*/
|
||||
frm_len = lso->total_len & 0xffff;
|
||||
frm_len_ext = (lso->total_len >> 16) & 0xf;
|
||||
|
||||
/* Set the flags of the first BD */
|
||||
flags = ENETC_TXBD_FLAGS_EX | ENETC_TXBD_FLAGS_CSUM_LSO |
|
||||
ENETC_TXBD_FLAGS_LSO | ENETC_TXBD_FLAGS_L4CS;
|
||||
|
||||
enetc_clear_tx_bd(&txbd_tmp);
|
||||
txbd_tmp.addr = cpu_to_le64(addr);
|
||||
txbd_tmp.hdr_len = cpu_to_le16(lso->hdr_len);
|
||||
|
||||
/* first BD needs frm_len and offload flags set */
|
||||
txbd_tmp.frm_len = cpu_to_le16(frm_len);
|
||||
txbd_tmp.flags = flags;
|
||||
|
||||
txbd_tmp.l3_aux0 = FIELD_PREP(ENETC_TX_BD_L3_START, lso->l3_start);
|
||||
/* l3_hdr_size in 32-bits (4 bytes) */
|
||||
txbd_tmp.l3_aux1 = FIELD_PREP(ENETC_TX_BD_L3_HDR_LEN,
|
||||
lso->l3_hdr_len / 4);
|
||||
if (lso->ipv6)
|
||||
txbd_tmp.l3_aux1 |= ENETC_TX_BD_L3T;
|
||||
else
|
||||
txbd_tmp.l3_aux0 |= ENETC_TX_BD_IPCS;
|
||||
|
||||
txbd_tmp.l4_aux = FIELD_PREP(ENETC_TX_BD_L4T, lso->tcp ?
|
||||
ENETC_TXBD_L4T_TCP : ENETC_TXBD_L4T_UDP);
|
||||
|
||||
/* For the LSO header we do not set the dma address since
|
||||
* we do not want it unmapped when we do cleanup. We still
|
||||
* set len so that we count the bytes sent.
|
||||
*/
|
||||
tx_swbd->len = lso->hdr_len;
|
||||
tx_swbd->do_twostep_tstamp = false;
|
||||
tx_swbd->check_wb = false;
|
||||
|
||||
/* Actually write the header in the BD */
|
||||
*txbd = txbd_tmp;
|
||||
|
||||
/* Get the next BD, and the next BD is extended BD */
|
||||
enetc_bdr_idx_inc(tx_ring, i);
|
||||
txbd = ENETC_TXBD(*tx_ring, *i);
|
||||
tx_swbd = &tx_ring->tx_swbd[*i];
|
||||
prefetchw(txbd);
|
||||
|
||||
enetc_clear_tx_bd(&txbd_tmp);
|
||||
if (skb_vlan_tag_present(skb)) {
|
||||
/* Setup the VLAN fields */
|
||||
txbd_tmp.ext.vid = cpu_to_le16(skb_vlan_tag_get(skb));
|
||||
txbd_tmp.ext.tpid = ENETC_TPID_8021Q;
|
||||
e_flags = ENETC_TXBD_E_FLAGS_VLAN_INS;
|
||||
}
|
||||
|
||||
/* Write the BD */
|
||||
txbd_tmp.ext.e_flags = e_flags;
|
||||
txbd_tmp.ext.lso_sg_size = cpu_to_le16(lso->lso_seg_size);
|
||||
txbd_tmp.ext.frm_len_ext = cpu_to_le16(frm_len_ext);
|
||||
*txbd = txbd_tmp;
|
||||
}
|
||||
|
||||
static int enetc_lso_map_data(struct enetc_bdr *tx_ring, struct sk_buff *skb,
|
||||
int *i, struct enetc_lso_t *lso, int *count)
|
||||
{
|
||||
union enetc_tx_bd txbd_tmp, *txbd = NULL;
|
||||
struct enetc_tx_swbd *tx_swbd;
|
||||
skb_frag_t *frag;
|
||||
dma_addr_t dma;
|
||||
u8 flags = 0;
|
||||
int len, f;
|
||||
|
||||
len = skb_headlen(skb) - lso->hdr_len;
|
||||
if (len > 0) {
|
||||
dma = dma_map_single(tx_ring->dev, skb->data + lso->hdr_len,
|
||||
len, DMA_TO_DEVICE);
|
||||
if (dma_mapping_error(tx_ring->dev, dma))
|
||||
return -ENOMEM;
|
||||
|
||||
enetc_bdr_idx_inc(tx_ring, i);
|
||||
txbd = ENETC_TXBD(*tx_ring, *i);
|
||||
tx_swbd = &tx_ring->tx_swbd[*i];
|
||||
prefetchw(txbd);
|
||||
*count += 1;
|
||||
|
||||
enetc_clear_tx_bd(&txbd_tmp);
|
||||
txbd_tmp.addr = cpu_to_le64(dma);
|
||||
txbd_tmp.buf_len = cpu_to_le16(len);
|
||||
|
||||
tx_swbd->dma = dma;
|
||||
tx_swbd->len = len;
|
||||
tx_swbd->is_dma_page = 0;
|
||||
tx_swbd->dir = DMA_TO_DEVICE;
|
||||
}
|
||||
|
||||
frag = &skb_shinfo(skb)->frags[0];
|
||||
for (f = 0; f < skb_shinfo(skb)->nr_frags; f++, frag++) {
|
||||
if (txbd)
|
||||
*txbd = txbd_tmp;
|
||||
|
||||
len = skb_frag_size(frag);
|
||||
dma = skb_frag_dma_map(tx_ring->dev, frag);
|
||||
if (dma_mapping_error(tx_ring->dev, dma))
|
||||
return -ENOMEM;
|
||||
|
||||
/* Get the next BD */
|
||||
enetc_bdr_idx_inc(tx_ring, i);
|
||||
txbd = ENETC_TXBD(*tx_ring, *i);
|
||||
tx_swbd = &tx_ring->tx_swbd[*i];
|
||||
prefetchw(txbd);
|
||||
*count += 1;
|
||||
|
||||
enetc_clear_tx_bd(&txbd_tmp);
|
||||
txbd_tmp.addr = cpu_to_le64(dma);
|
||||
txbd_tmp.buf_len = cpu_to_le16(len);
|
||||
|
||||
tx_swbd->dma = dma;
|
||||
tx_swbd->len = len;
|
||||
tx_swbd->is_dma_page = 1;
|
||||
tx_swbd->dir = DMA_TO_DEVICE;
|
||||
}
|
||||
|
||||
/* Last BD needs 'F' bit set */
|
||||
flags |= ENETC_TXBD_FLAGS_F;
|
||||
txbd_tmp.flags = flags;
|
||||
*txbd = txbd_tmp;
|
||||
|
||||
tx_swbd->is_eof = 1;
|
||||
tx_swbd->skb = skb;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int enetc_lso_hw_offload(struct enetc_bdr *tx_ring, struct sk_buff *skb)
|
||||
{
|
||||
struct enetc_tx_swbd *tx_swbd;
|
||||
struct enetc_lso_t lso = {0};
|
||||
int err, i, count = 0;
|
||||
|
||||
/* Initialize the LSO handler */
|
||||
enetc_lso_start(skb, &lso);
|
||||
i = tx_ring->next_to_use;
|
||||
|
||||
enetc_lso_map_hdr(tx_ring, skb, &i, &lso);
|
||||
/* First BD and an extend BD */
|
||||
count += 2;
|
||||
|
||||
err = enetc_lso_map_data(tx_ring, skb, &i, &lso, &count);
|
||||
if (err)
|
||||
goto dma_err;
|
||||
|
||||
/* Go to the next BD */
|
||||
enetc_bdr_idx_inc(tx_ring, &i);
|
||||
tx_ring->next_to_use = i;
|
||||
enetc_update_tx_ring_tail(tx_ring);
|
||||
|
||||
return count;
|
||||
|
||||
dma_err:
|
||||
do {
|
||||
tx_swbd = &tx_ring->tx_swbd[i];
|
||||
enetc_free_tx_frame(tx_ring, tx_swbd);
|
||||
if (i == 0)
|
||||
i = tx_ring->bd_count;
|
||||
i--;
|
||||
} while (--count);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int enetc_map_tx_tso_buffs(struct enetc_bdr *tx_ring, struct sk_buff *skb)
|
||||
{
|
||||
struct enetc_ndev_priv *priv = netdev_priv(tx_ring->ndev);
|
||||
int hdr_len, total_len, data_len;
|
||||
struct enetc_tx_swbd *tx_swbd;
|
||||
union enetc_tx_bd *txbd;
|
||||
@ -556,7 +824,7 @@ static int enetc_map_tx_tso_buffs(struct enetc_bdr *tx_ring, struct sk_buff *skb
|
||||
bd_data_num++;
|
||||
tso_build_data(skb, &tso, size);
|
||||
|
||||
if (unlikely(bd_data_num >= ENETC_MAX_SKB_FRAGS && data_len))
|
||||
if (unlikely(bd_data_num >= priv->max_frags && data_len))
|
||||
goto err_chained_bd;
|
||||
}
|
||||
|
||||
@ -594,7 +862,7 @@ static netdev_tx_t enetc_start_xmit(struct sk_buff *skb,
|
||||
{
|
||||
struct enetc_ndev_priv *priv = netdev_priv(ndev);
|
||||
struct enetc_bdr *tx_ring;
|
||||
int count, err;
|
||||
int count;
|
||||
|
||||
/* Queue one-step Sync packet if already locked */
|
||||
if (skb->cb[0] & ENETC_F_TX_ONESTEP_SYNC_TSTAMP) {
|
||||
@ -608,6 +876,17 @@ static netdev_tx_t enetc_start_xmit(struct sk_buff *skb,
|
||||
tx_ring = priv->tx_ring[skb->queue_mapping];
|
||||
|
||||
if (skb_is_gso(skb)) {
|
||||
/* LSO data unit lengths of up to 256KB are supported */
|
||||
if (priv->active_offloads & ENETC_F_LSO &&
|
||||
(skb->len - enetc_lso_get_hdr_len(skb)) <=
|
||||
ENETC_LSO_MAX_DATA_LEN) {
|
||||
if (enetc_bd_unused(tx_ring) < enetc_lso_count_descs(skb)) {
|
||||
netif_stop_subqueue(ndev, tx_ring->index);
|
||||
return NETDEV_TX_BUSY;
|
||||
}
|
||||
|
||||
count = enetc_lso_hw_offload(tx_ring, skb);
|
||||
} else {
|
||||
if (enetc_bd_unused(tx_ring) < tso_count_descs(skb)) {
|
||||
netif_stop_subqueue(ndev, tx_ring->index);
|
||||
return NETDEV_TX_BUSY;
|
||||
@ -616,8 +895,9 @@ static netdev_tx_t enetc_start_xmit(struct sk_buff *skb,
|
||||
enetc_lock_mdio();
|
||||
count = enetc_map_tx_tso_buffs(tx_ring, skb);
|
||||
enetc_unlock_mdio();
|
||||
}
|
||||
} else {
|
||||
if (unlikely(skb_shinfo(skb)->nr_frags > ENETC_MAX_SKB_FRAGS))
|
||||
if (unlikely(skb_shinfo(skb)->nr_frags > priv->max_frags))
|
||||
if (unlikely(skb_linearize(skb)))
|
||||
goto drop_packet_err;
|
||||
|
||||
@ -627,11 +907,6 @@ static netdev_tx_t enetc_start_xmit(struct sk_buff *skb,
|
||||
return NETDEV_TX_BUSY;
|
||||
}
|
||||
|
||||
if (skb->ip_summed == CHECKSUM_PARTIAL) {
|
||||
err = skb_checksum_help(skb);
|
||||
if (err)
|
||||
goto drop_packet_err;
|
||||
}
|
||||
enetc_lock_mdio();
|
||||
count = enetc_map_tx_buffs(tx_ring, skb);
|
||||
enetc_unlock_mdio();
|
||||
@ -640,7 +915,7 @@ static netdev_tx_t enetc_start_xmit(struct sk_buff *skb,
|
||||
if (unlikely(!count))
|
||||
goto drop_packet_err;
|
||||
|
||||
if (enetc_bd_unused(tx_ring) < ENETC_TXBDS_MAX_NEEDED)
|
||||
if (enetc_bd_unused(tx_ring) < ENETC_TXBDS_MAX_NEEDED(priv->max_frags))
|
||||
netif_stop_subqueue(ndev, tx_ring->index);
|
||||
|
||||
return NETDEV_TX_OK;
|
||||
@ -908,7 +1183,8 @@ static bool enetc_clean_tx_ring(struct enetc_bdr *tx_ring, int napi_budget)
|
||||
if (unlikely(tx_frm_cnt && netif_carrier_ok(ndev) &&
|
||||
__netif_subqueue_stopped(ndev, tx_ring->index) &&
|
||||
!test_bit(ENETC_TX_DOWN, &priv->flags) &&
|
||||
(enetc_bd_unused(tx_ring) >= ENETC_TXBDS_MAX_NEEDED))) {
|
||||
(enetc_bd_unused(tx_ring) >=
|
||||
ENETC_TXBDS_MAX_NEEDED(priv->max_frags)))) {
|
||||
netif_wake_subqueue(ndev, tx_ring->index);
|
||||
}
|
||||
|
||||
@ -1759,6 +2035,9 @@ void enetc_get_si_caps(struct enetc_si *si)
|
||||
rss = enetc_rd(hw, ENETC_SIRSSCAPR);
|
||||
si->num_rss = ENETC_SIRSSCAPR_GET_NUM_RSS(rss);
|
||||
}
|
||||
|
||||
if (val & ENETC_SIPCAPR0_LSO)
|
||||
si->hw_features |= ENETC_SI_F_LSO;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(enetc_get_si_caps);
|
||||
|
||||
@ -2055,6 +2334,14 @@ static int enetc_setup_default_rss_table(struct enetc_si *si, int num_groups)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void enetc_set_lso_flags_mask(struct enetc_hw *hw)
|
||||
{
|
||||
enetc_wr(hw, ENETC4_SILSOSFMR0,
|
||||
SILSOSFMR0_VAL_SET(ENETC4_TCP_NL_SEG_FLAGS_DMASK,
|
||||
ENETC4_TCP_NL_SEG_FLAGS_DMASK));
|
||||
enetc_wr(hw, ENETC4_SILSOSFMR1, 0);
|
||||
}
|
||||
|
||||
int enetc_configure_si(struct enetc_ndev_priv *priv)
|
||||
{
|
||||
struct enetc_si *si = priv->si;
|
||||
@ -2068,6 +2355,9 @@ int enetc_configure_si(struct enetc_ndev_priv *priv)
|
||||
/* enable SI */
|
||||
enetc_wr(hw, ENETC_SIMR, ENETC_SIMR_EN);
|
||||
|
||||
if (si->hw_features & ENETC_SI_F_LSO)
|
||||
enetc_set_lso_flags_mask(hw);
|
||||
|
||||
/* TODO: RSS support for i.MX95 will be supported later, and the
|
||||
* is_enetc_rev1() condition will be removed
|
||||
*/
|
||||
@ -3269,17 +3559,21 @@ EXPORT_SYMBOL_GPL(enetc_pci_remove);
|
||||
static const struct enetc_drvdata enetc_pf_data = {
|
||||
.sysclk_freq = ENETC_CLK_400M,
|
||||
.pmac_offset = ENETC_PMAC_OFFSET,
|
||||
.max_frags = ENETC_MAX_SKB_FRAGS,
|
||||
.eth_ops = &enetc_pf_ethtool_ops,
|
||||
};
|
||||
|
||||
static const struct enetc_drvdata enetc4_pf_data = {
|
||||
.sysclk_freq = ENETC_CLK_333M,
|
||||
.tx_csum = true,
|
||||
.max_frags = ENETC4_MAX_SKB_FRAGS,
|
||||
.pmac_offset = ENETC4_PMAC_OFFSET,
|
||||
.eth_ops = &enetc4_pf_ethtool_ops,
|
||||
};
|
||||
|
||||
static const struct enetc_drvdata enetc_vf_data = {
|
||||
.sysclk_freq = ENETC_CLK_400M,
|
||||
.max_frags = ENETC_MAX_SKB_FRAGS,
|
||||
.eth_ops = &enetc_vf_ethtool_ops,
|
||||
};
|
||||
|
||||
|
@ -41,6 +41,18 @@ struct enetc_tx_swbd {
|
||||
u8 qbv_en:1;
|
||||
};
|
||||
|
||||
struct enetc_lso_t {
|
||||
bool ipv6;
|
||||
bool tcp;
|
||||
u8 l3_hdr_len;
|
||||
u8 hdr_len; /* LSO header length */
|
||||
u8 l3_start;
|
||||
u16 lso_seg_size;
|
||||
int total_len; /* total data length, not include LSO header */
|
||||
};
|
||||
|
||||
#define ENETC_LSO_MAX_DATA_LEN SZ_256K
|
||||
|
||||
#define ENETC_RX_MAXFRM_SIZE ENETC_MAC_MAXFRM_SIZE
|
||||
#define ENETC_RXB_TRUESIZE 2048 /* PAGE_SIZE >> 1 */
|
||||
#define ENETC_RXB_PAD NET_SKB_PAD /* add extra space if needed */
|
||||
@ -59,9 +71,16 @@ struct enetc_rx_swbd {
|
||||
|
||||
/* ENETC overhead: optional extension BD + 1 BD gap */
|
||||
#define ENETC_TXBDS_NEEDED(val) ((val) + 2)
|
||||
/* max # of chained Tx BDs is 15, including head and extension BD */
|
||||
/* For LS1028A, max # of chained Tx BDs is 15, including head and
|
||||
* extension BD.
|
||||
*/
|
||||
#define ENETC_MAX_SKB_FRAGS 13
|
||||
#define ENETC_TXBDS_MAX_NEEDED ENETC_TXBDS_NEEDED(ENETC_MAX_SKB_FRAGS + 1)
|
||||
/* For ENETC v4 and later versions, max # of chained Tx BDs is 63,
|
||||
* including head and extension BD, but the range of MAX_SKB_FRAGS
|
||||
* is 17 ~ 45, so set ENETC4_MAX_SKB_FRAGS to MAX_SKB_FRAGS.
|
||||
*/
|
||||
#define ENETC4_MAX_SKB_FRAGS MAX_SKB_FRAGS
|
||||
#define ENETC_TXBDS_MAX_NEEDED(x) ENETC_TXBDS_NEEDED((x) + 1)
|
||||
|
||||
struct enetc_ring_stats {
|
||||
unsigned int packets;
|
||||
@ -231,9 +250,12 @@ enum enetc_errata {
|
||||
#define ENETC_SI_F_PSFP BIT(0)
|
||||
#define ENETC_SI_F_QBV BIT(1)
|
||||
#define ENETC_SI_F_QBU BIT(2)
|
||||
#define ENETC_SI_F_LSO BIT(3)
|
||||
|
||||
struct enetc_drvdata {
|
||||
u32 pmac_offset; /* Only valid for PSI which supports 802.1Qbu */
|
||||
u8 tx_csum:1;
|
||||
u8 max_frags;
|
||||
u64 sysclk_freq;
|
||||
const struct ethtool_ops *eth_ops;
|
||||
};
|
||||
@ -341,6 +363,8 @@ enum enetc_active_offloads {
|
||||
ENETC_F_QBV = BIT(9),
|
||||
ENETC_F_QCI = BIT(10),
|
||||
ENETC_F_QBU = BIT(11),
|
||||
ENETC_F_TXCSUM = BIT(12),
|
||||
ENETC_F_LSO = BIT(13),
|
||||
};
|
||||
|
||||
enum enetc_flags_bit {
|
||||
@ -375,6 +399,7 @@ struct enetc_ndev_priv {
|
||||
u16 msg_enable;
|
||||
|
||||
u8 preemptible_tcs;
|
||||
u8 max_frags; /* The maximum number of BDs for fragments */
|
||||
|
||||
enum enetc_active_offloads active_offloads;
|
||||
|
||||
|
@ -12,6 +12,29 @@
|
||||
#define NXP_ENETC_VENDOR_ID 0x1131
|
||||
#define NXP_ENETC_PF_DEV_ID 0xe101
|
||||
|
||||
/**********************Station interface registers************************/
|
||||
/* Station interface LSO segmentation flag mask register 0/1 */
|
||||
#define ENETC4_SILSOSFMR0 0x1300
|
||||
#define SILSOSFMR0_TCP_MID_SEG GENMASK(27, 16)
|
||||
#define SILSOSFMR0_TCP_1ST_SEG GENMASK(11, 0)
|
||||
#define SILSOSFMR0_VAL_SET(first, mid) (FIELD_PREP(SILSOSFMR0_TCP_MID_SEG, mid) | \
|
||||
FIELD_PREP(SILSOSFMR0_TCP_1ST_SEG, first))
|
||||
|
||||
#define ENETC4_SILSOSFMR1 0x1304
|
||||
#define SILSOSFMR1_TCP_LAST_SEG GENMASK(11, 0)
|
||||
#define ENETC4_TCP_FLAGS_FIN BIT(0)
|
||||
#define ENETC4_TCP_FLAGS_SYN BIT(1)
|
||||
#define ENETC4_TCP_FLAGS_RST BIT(2)
|
||||
#define ENETC4_TCP_FLAGS_PSH BIT(3)
|
||||
#define ENETC4_TCP_FLAGS_ACK BIT(4)
|
||||
#define ENETC4_TCP_FLAGS_URG BIT(5)
|
||||
#define ENETC4_TCP_FLAGS_ECE BIT(6)
|
||||
#define ENETC4_TCP_FLAGS_CWR BIT(7)
|
||||
#define ENETC4_TCP_FLAGS_NS BIT(8)
|
||||
/* According to tso_build_hdr(), clear all special flags for not last packet. */
|
||||
#define ENETC4_TCP_NL_SEG_FLAGS_DMASK (ENETC4_TCP_FLAGS_FIN | \
|
||||
ENETC4_TCP_FLAGS_RST | ENETC4_TCP_FLAGS_PSH)
|
||||
|
||||
/***************************ENETC port registers**************************/
|
||||
#define ENETC4_ECAPR0 0x0
|
||||
#define ECAPR0_RFS BIT(2)
|
||||
|
@ -25,6 +25,7 @@
|
||||
#define ENETC_SIPCAPR0 0x20
|
||||
#define ENETC_SIPCAPR0_RSS BIT(8)
|
||||
#define ENETC_SIPCAPR0_RFS BIT(2)
|
||||
#define ENETC_SIPCAPR0_LSO BIT(1)
|
||||
#define ENETC_SIPCAPR1 0x24
|
||||
#define ENETC_SITGTGR 0x30
|
||||
#define ENETC_SIRBGCR 0x38
|
||||
@ -554,11 +555,23 @@ static inline u64 _enetc_rd_reg64_wa(void __iomem *reg)
|
||||
union enetc_tx_bd {
|
||||
struct {
|
||||
__le64 addr;
|
||||
union {
|
||||
__le16 buf_len;
|
||||
__le16 hdr_len; /* For LSO, ENETC 4.1 and later */
|
||||
};
|
||||
__le16 frm_len;
|
||||
union {
|
||||
struct {
|
||||
u8 reserved[3];
|
||||
u8 l3_aux0;
|
||||
#define ENETC_TX_BD_L3_START GENMASK(6, 0)
|
||||
#define ENETC_TX_BD_IPCS BIT(7)
|
||||
u8 l3_aux1;
|
||||
#define ENETC_TX_BD_L3_HDR_LEN GENMASK(6, 0)
|
||||
#define ENETC_TX_BD_L3T BIT(7)
|
||||
u8 l4_aux;
|
||||
#define ENETC_TX_BD_L4T GENMASK(7, 5)
|
||||
#define ENETC_TXBD_L4T_UDP 1
|
||||
#define ENETC_TXBD_L4T_TCP 2
|
||||
u8 flags;
|
||||
}; /* default layout */
|
||||
__le32 txstart;
|
||||
@ -569,23 +582,27 @@ union enetc_tx_bd {
|
||||
__le32 tstamp;
|
||||
__le16 tpid;
|
||||
__le16 vid;
|
||||
u8 reserved[6];
|
||||
__le16 lso_sg_size; /* For ENETC 4.1 and later */
|
||||
__le16 frm_len_ext; /* For ENETC 4.1 and later */
|
||||
u8 reserved[2];
|
||||
u8 e_flags;
|
||||
u8 flags;
|
||||
} ext; /* Tx BD extension */
|
||||
struct {
|
||||
__le32 tstamp;
|
||||
u8 reserved[10];
|
||||
u8 reserved[8];
|
||||
__le16 lso_err_count; /* For ENETC 4.1 and later */
|
||||
u8 status;
|
||||
u8 flags;
|
||||
} wb; /* writeback descriptor */
|
||||
};
|
||||
|
||||
enum enetc_txbd_flags {
|
||||
ENETC_TXBD_FLAGS_RES0 = BIT(0), /* reserved */
|
||||
ENETC_TXBD_FLAGS_L4CS = BIT(0), /* For ENETC 4.1 and later */
|
||||
ENETC_TXBD_FLAGS_TSE = BIT(1),
|
||||
ENETC_TXBD_FLAGS_LSO = BIT(1), /* For ENETC 4.1 and later */
|
||||
ENETC_TXBD_FLAGS_W = BIT(2),
|
||||
ENETC_TXBD_FLAGS_RES3 = BIT(3), /* reserved */
|
||||
ENETC_TXBD_FLAGS_CSUM_LSO = BIT(3), /* For ENETC 4.1 and later */
|
||||
ENETC_TXBD_FLAGS_TXSTART = BIT(4),
|
||||
ENETC_TXBD_FLAGS_EX = BIT(6),
|
||||
ENETC_TXBD_FLAGS_F = BIT(7)
|
||||
@ -654,6 +671,8 @@ union enetc_rx_bd {
|
||||
#define ENETC_CBD_FLAGS_SF BIT(7) /* short format */
|
||||
#define ENETC_CBD_STATUS_MASK 0xf
|
||||
|
||||
#define ENETC_TPID_8021Q 0
|
||||
|
||||
struct enetc_cmd_rfse {
|
||||
u8 smac_h[6];
|
||||
u8 smac_m[6];
|
||||
|
@ -101,6 +101,7 @@ void enetc_pf_netdev_setup(struct enetc_si *si, struct net_device *ndev,
|
||||
|
||||
priv->msg_enable = (NETIF_MSG_WOL << 1) - 1;
|
||||
priv->sysclk_freq = si->drvdata->sysclk_freq;
|
||||
priv->max_frags = si->drvdata->max_frags;
|
||||
ndev->netdev_ops = ndev_ops;
|
||||
enetc_set_ethtool_ops(ndev);
|
||||
ndev->watchdog_timeo = 5 * HZ;
|
||||
@ -109,16 +110,24 @@ void enetc_pf_netdev_setup(struct enetc_si *si, struct net_device *ndev,
|
||||
ndev->hw_features = NETIF_F_SG | NETIF_F_RXCSUM |
|
||||
NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX |
|
||||
NETIF_F_HW_VLAN_CTAG_FILTER | NETIF_F_LOOPBACK |
|
||||
NETIF_F_HW_CSUM | NETIF_F_TSO | NETIF_F_TSO6;
|
||||
NETIF_F_HW_CSUM | NETIF_F_TSO | NETIF_F_TSO6 |
|
||||
NETIF_F_GSO_UDP_L4;
|
||||
ndev->features = NETIF_F_HIGHDMA | NETIF_F_SG | NETIF_F_RXCSUM |
|
||||
NETIF_F_HW_VLAN_CTAG_TX |
|
||||
NETIF_F_HW_VLAN_CTAG_RX |
|
||||
NETIF_F_HW_CSUM | NETIF_F_TSO | NETIF_F_TSO6;
|
||||
NETIF_F_HW_CSUM | NETIF_F_TSO | NETIF_F_TSO6 |
|
||||
NETIF_F_GSO_UDP_L4;
|
||||
ndev->vlan_features = NETIF_F_SG | NETIF_F_HW_CSUM |
|
||||
NETIF_F_TSO | NETIF_F_TSO6;
|
||||
|
||||
ndev->priv_flags |= IFF_UNICAST_FLT;
|
||||
|
||||
if (si->drvdata->tx_csum)
|
||||
priv->active_offloads |= ENETC_F_TXCSUM;
|
||||
|
||||
if (si->hw_features & ENETC_SI_F_LSO)
|
||||
priv->active_offloads |= ENETC_F_LSO;
|
||||
|
||||
/* TODO: currently, i.MX95 ENETC driver does not support advanced features */
|
||||
if (!is_enetc_rev1(si)) {
|
||||
ndev->hw_features &= ~(NETIF_F_HW_VLAN_CTAG_FILTER | NETIF_F_LOOPBACK);
|
||||
|
@ -136,6 +136,7 @@ static void enetc_vf_netdev_setup(struct enetc_si *si, struct net_device *ndev,
|
||||
|
||||
priv->msg_enable = (NETIF_MSG_IFUP << 1) - 1;
|
||||
priv->sysclk_freq = si->drvdata->sysclk_freq;
|
||||
priv->max_frags = si->drvdata->max_frags;
|
||||
ndev->netdev_ops = ndev_ops;
|
||||
enetc_set_ethtool_ops(ndev);
|
||||
ndev->watchdog_timeo = 5 * HZ;
|
||||
@ -144,11 +145,13 @@ static void enetc_vf_netdev_setup(struct enetc_si *si, struct net_device *ndev,
|
||||
ndev->hw_features = NETIF_F_SG | NETIF_F_RXCSUM |
|
||||
NETIF_F_HW_VLAN_CTAG_TX |
|
||||
NETIF_F_HW_VLAN_CTAG_RX |
|
||||
NETIF_F_HW_CSUM | NETIF_F_TSO | NETIF_F_TSO6;
|
||||
NETIF_F_HW_CSUM | NETIF_F_TSO | NETIF_F_TSO6 |
|
||||
NETIF_F_GSO_UDP_L4;
|
||||
ndev->features = NETIF_F_HIGHDMA | NETIF_F_SG | NETIF_F_RXCSUM |
|
||||
NETIF_F_HW_VLAN_CTAG_TX |
|
||||
NETIF_F_HW_VLAN_CTAG_RX |
|
||||
NETIF_F_HW_CSUM | NETIF_F_TSO | NETIF_F_TSO6;
|
||||
NETIF_F_HW_CSUM | NETIF_F_TSO | NETIF_F_TSO6 |
|
||||
NETIF_F_GSO_UDP_L4;
|
||||
ndev->vlan_features = NETIF_F_SG | NETIF_F_HW_CSUM |
|
||||
NETIF_F_TSO | NETIF_F_TSO6;
|
||||
|
||||
|
@ -671,8 +671,6 @@ struct fec_enet_private {
|
||||
unsigned int tx_time_itr;
|
||||
unsigned int itr_clk_rate;
|
||||
|
||||
/* tx lpi eee mode */
|
||||
struct ethtool_keee eee;
|
||||
unsigned int clk_ref_rate;
|
||||
|
||||
/* ptp clock period in ns*/
|
||||
|
@ -2045,14 +2045,14 @@ static int fec_enet_us_to_tx_cycle(struct net_device *ndev, int us)
|
||||
return us * (fep->clk_ref_rate / 1000) / 1000;
|
||||
}
|
||||
|
||||
static int fec_enet_eee_mode_set(struct net_device *ndev, bool enable)
|
||||
static int fec_enet_eee_mode_set(struct net_device *ndev, u32 lpi_timer,
|
||||
bool enable)
|
||||
{
|
||||
struct fec_enet_private *fep = netdev_priv(ndev);
|
||||
struct ethtool_keee *p = &fep->eee;
|
||||
unsigned int sleep_cycle, wake_cycle;
|
||||
|
||||
if (enable) {
|
||||
sleep_cycle = fec_enet_us_to_tx_cycle(ndev, p->tx_lpi_timer);
|
||||
sleep_cycle = fec_enet_us_to_tx_cycle(ndev, lpi_timer);
|
||||
wake_cycle = sleep_cycle;
|
||||
} else {
|
||||
sleep_cycle = 0;
|
||||
@ -2105,7 +2105,9 @@ static void fec_enet_adjust_link(struct net_device *ndev)
|
||||
napi_enable(&fep->napi);
|
||||
}
|
||||
if (fep->quirks & FEC_QUIRK_HAS_EEE)
|
||||
fec_enet_eee_mode_set(ndev, phy_dev->enable_tx_lpi);
|
||||
fec_enet_eee_mode_set(ndev,
|
||||
phy_dev->eee_cfg.tx_lpi_timer,
|
||||
phy_dev->enable_tx_lpi);
|
||||
} else {
|
||||
if (fep->link) {
|
||||
netif_stop_queue(ndev);
|
||||
@ -3181,7 +3183,6 @@ static int
|
||||
fec_enet_get_eee(struct net_device *ndev, struct ethtool_keee *edata)
|
||||
{
|
||||
struct fec_enet_private *fep = netdev_priv(ndev);
|
||||
struct ethtool_keee *p = &fep->eee;
|
||||
|
||||
if (!(fep->quirks & FEC_QUIRK_HAS_EEE))
|
||||
return -EOPNOTSUPP;
|
||||
@ -3189,8 +3190,6 @@ fec_enet_get_eee(struct net_device *ndev, struct ethtool_keee *edata)
|
||||
if (!netif_running(ndev))
|
||||
return -ENETDOWN;
|
||||
|
||||
edata->tx_lpi_timer = p->tx_lpi_timer;
|
||||
|
||||
return phy_ethtool_get_eee(ndev->phydev, edata);
|
||||
}
|
||||
|
||||
@ -3198,7 +3197,6 @@ static int
|
||||
fec_enet_set_eee(struct net_device *ndev, struct ethtool_keee *edata)
|
||||
{
|
||||
struct fec_enet_private *fep = netdev_priv(ndev);
|
||||
struct ethtool_keee *p = &fep->eee;
|
||||
|
||||
if (!(fep->quirks & FEC_QUIRK_HAS_EEE))
|
||||
return -EOPNOTSUPP;
|
||||
@ -3206,8 +3204,6 @@ fec_enet_set_eee(struct net_device *ndev, struct ethtool_keee *edata)
|
||||
if (!netif_running(ndev))
|
||||
return -ENETDOWN;
|
||||
|
||||
p->tx_lpi_timer = edata->tx_lpi_timer;
|
||||
|
||||
return phy_ethtool_set_eee(ndev->phydev, edata);
|
||||
}
|
||||
|
||||
|
@ -2690,13 +2690,12 @@ static struct fman *read_dts_node(struct platform_device *of_dev)
|
||||
{
|
||||
struct fman *fman;
|
||||
struct device_node *fm_node, *muram_node;
|
||||
void __iomem *base_addr;
|
||||
struct resource *res;
|
||||
u32 val, range[2];
|
||||
int err, irq;
|
||||
struct clk *clk;
|
||||
u32 clk_rate;
|
||||
phys_addr_t phys_base_addr;
|
||||
resource_size_t mem_size;
|
||||
|
||||
fman = kzalloc(sizeof(*fman), GFP_KERNEL);
|
||||
if (!fman)
|
||||
@ -2724,18 +2723,6 @@ static struct fman *read_dts_node(struct platform_device *of_dev)
|
||||
goto fman_node_put;
|
||||
fman->dts_params.err_irq = err;
|
||||
|
||||
/* Get the FM address */
|
||||
res = platform_get_resource(of_dev, IORESOURCE_MEM, 0);
|
||||
if (!res) {
|
||||
err = -EINVAL;
|
||||
dev_err(&of_dev->dev, "%s: Can't get FMan memory resource\n",
|
||||
__func__);
|
||||
goto fman_node_put;
|
||||
}
|
||||
|
||||
phys_base_addr = res->start;
|
||||
mem_size = resource_size(res);
|
||||
|
||||
clk = of_clk_get(fm_node, 0);
|
||||
if (IS_ERR(clk)) {
|
||||
err = PTR_ERR(clk);
|
||||
@ -2803,24 +2790,16 @@ static struct fman *read_dts_node(struct platform_device *of_dev)
|
||||
}
|
||||
}
|
||||
|
||||
fman->dts_params.res =
|
||||
devm_request_mem_region(&of_dev->dev, phys_base_addr,
|
||||
mem_size, "fman");
|
||||
if (!fman->dts_params.res) {
|
||||
err = -EBUSY;
|
||||
dev_err(&of_dev->dev, "%s: request_mem_region() failed\n",
|
||||
__func__);
|
||||
goto fman_free;
|
||||
}
|
||||
|
||||
fman->dts_params.base_addr =
|
||||
devm_ioremap(&of_dev->dev, phys_base_addr, mem_size);
|
||||
if (!fman->dts_params.base_addr) {
|
||||
err = -ENOMEM;
|
||||
base_addr = devm_platform_get_and_ioremap_resource(of_dev, 0, &res);
|
||||
if (IS_ERR(base_addr)) {
|
||||
err = PTR_ERR(base_addr);
|
||||
dev_err(&of_dev->dev, "%s: devm_ioremap() failed\n", __func__);
|
||||
goto fman_free;
|
||||
}
|
||||
|
||||
fman->dts_params.base_addr = base_addr;
|
||||
fman->dts_params.res = res;
|
||||
|
||||
fman->dev = &of_dev->dev;
|
||||
|
||||
err = of_platform_populate(fm_node, NULL, NULL, &of_dev->dev);
|
||||
|
@ -26,7 +26,7 @@
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/mii.h>
|
||||
#include <linux/phy.h>
|
||||
#include <linux/phy_fixed.h>
|
||||
#include <linux/phylink.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
@ -34,6 +34,7 @@
|
||||
#include <linux/of_mdio.h>
|
||||
#include <linux/of_net.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/rtnetlink.h>
|
||||
|
||||
#include <linux/uaccess.h>
|
||||
#include <asm/irq.h>
|
||||
@ -132,7 +133,6 @@ static const struct ucc_geth_info ugeth_primary_info = {
|
||||
.transmitFlowControl = 1,
|
||||
.maxGroupAddrInHash = 4,
|
||||
.maxIndAddrInHash = 4,
|
||||
.prel = 7,
|
||||
.maxFrameLength = 1518+16, /* Add extra bytes for VLANs etc. */
|
||||
.minFrameLength = 64,
|
||||
.maxD1Length = 1520+16, /* Add extra bytes for VLANs etc. */
|
||||
@ -1205,34 +1205,6 @@ static int init_mac_station_addr_regs(u8 address_byte_0,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int init_check_frame_length_mode(int length_check,
|
||||
u32 __iomem *maccfg2_register)
|
||||
{
|
||||
u32 value = 0;
|
||||
|
||||
value = in_be32(maccfg2_register);
|
||||
|
||||
if (length_check)
|
||||
value |= MACCFG2_LC;
|
||||
else
|
||||
value &= ~MACCFG2_LC;
|
||||
|
||||
out_be32(maccfg2_register, value);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int init_preamble_length(u8 preamble_length,
|
||||
u32 __iomem *maccfg2_register)
|
||||
{
|
||||
if ((preamble_length < 3) || (preamble_length > 7))
|
||||
return -EINVAL;
|
||||
|
||||
clrsetbits_be32(maccfg2_register, MACCFG2_PREL_MASK,
|
||||
preamble_length << MACCFG2_PREL_SHIFT);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int init_rx_parameters(int reject_broadcast,
|
||||
int receive_short_frames,
|
||||
int promiscuous, u32 __iomem *upsmr_register)
|
||||
@ -1287,94 +1259,11 @@ static int init_min_frame_len(u16 min_frame_length,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int adjust_enet_interface(struct ucc_geth_private *ugeth)
|
||||
static bool phy_interface_mode_is_reduced(phy_interface_t interface)
|
||||
{
|
||||
struct ucc_geth_info *ug_info;
|
||||
struct ucc_geth __iomem *ug_regs;
|
||||
struct ucc_fast __iomem *uf_regs;
|
||||
int ret_val;
|
||||
u32 upsmr, maccfg2;
|
||||
u16 value;
|
||||
|
||||
ugeth_vdbg("%s: IN", __func__);
|
||||
|
||||
ug_info = ugeth->ug_info;
|
||||
ug_regs = ugeth->ug_regs;
|
||||
uf_regs = ugeth->uccf->uf_regs;
|
||||
|
||||
/* Set MACCFG2 */
|
||||
maccfg2 = in_be32(&ug_regs->maccfg2);
|
||||
maccfg2 &= ~MACCFG2_INTERFACE_MODE_MASK;
|
||||
if ((ugeth->max_speed == SPEED_10) ||
|
||||
(ugeth->max_speed == SPEED_100))
|
||||
maccfg2 |= MACCFG2_INTERFACE_MODE_NIBBLE;
|
||||
else if (ugeth->max_speed == SPEED_1000)
|
||||
maccfg2 |= MACCFG2_INTERFACE_MODE_BYTE;
|
||||
maccfg2 |= ug_info->padAndCrc;
|
||||
out_be32(&ug_regs->maccfg2, maccfg2);
|
||||
|
||||
/* Set UPSMR */
|
||||
upsmr = in_be32(&uf_regs->upsmr);
|
||||
upsmr &= ~(UCC_GETH_UPSMR_RPM | UCC_GETH_UPSMR_R10M |
|
||||
UCC_GETH_UPSMR_TBIM | UCC_GETH_UPSMR_RMM);
|
||||
if ((ugeth->phy_interface == PHY_INTERFACE_MODE_RMII) ||
|
||||
(ugeth->phy_interface == PHY_INTERFACE_MODE_RGMII) ||
|
||||
(ugeth->phy_interface == PHY_INTERFACE_MODE_RGMII_ID) ||
|
||||
(ugeth->phy_interface == PHY_INTERFACE_MODE_RGMII_RXID) ||
|
||||
(ugeth->phy_interface == PHY_INTERFACE_MODE_RGMII_TXID) ||
|
||||
(ugeth->phy_interface == PHY_INTERFACE_MODE_RTBI)) {
|
||||
if (ugeth->phy_interface != PHY_INTERFACE_MODE_RMII)
|
||||
upsmr |= UCC_GETH_UPSMR_RPM;
|
||||
switch (ugeth->max_speed) {
|
||||
case SPEED_10:
|
||||
upsmr |= UCC_GETH_UPSMR_R10M;
|
||||
fallthrough;
|
||||
case SPEED_100:
|
||||
if (ugeth->phy_interface != PHY_INTERFACE_MODE_RTBI)
|
||||
upsmr |= UCC_GETH_UPSMR_RMM;
|
||||
}
|
||||
}
|
||||
if ((ugeth->phy_interface == PHY_INTERFACE_MODE_TBI) ||
|
||||
(ugeth->phy_interface == PHY_INTERFACE_MODE_RTBI)) {
|
||||
upsmr |= UCC_GETH_UPSMR_TBIM;
|
||||
}
|
||||
if (ugeth->phy_interface == PHY_INTERFACE_MODE_SGMII)
|
||||
upsmr |= UCC_GETH_UPSMR_SGMM;
|
||||
|
||||
out_be32(&uf_regs->upsmr, upsmr);
|
||||
|
||||
/* Disable autonegotiation in tbi mode, because by default it
|
||||
comes up in autonegotiation mode. */
|
||||
/* Note that this depends on proper setting in utbipar register. */
|
||||
if ((ugeth->phy_interface == PHY_INTERFACE_MODE_TBI) ||
|
||||
(ugeth->phy_interface == PHY_INTERFACE_MODE_RTBI)) {
|
||||
struct ucc_geth_info *ug_info = ugeth->ug_info;
|
||||
struct phy_device *tbiphy;
|
||||
|
||||
if (!ug_info->tbi_node)
|
||||
pr_warn("TBI mode requires that the device tree specify a tbi-handle\n");
|
||||
|
||||
tbiphy = of_phy_find_device(ug_info->tbi_node);
|
||||
if (!tbiphy)
|
||||
pr_warn("Could not get TBI device\n");
|
||||
|
||||
value = phy_read(tbiphy, ENET_TBI_MII_CR);
|
||||
value &= ~0x1000; /* Turn off autonegotiation */
|
||||
phy_write(tbiphy, ENET_TBI_MII_CR, value);
|
||||
|
||||
put_device(&tbiphy->mdio.dev);
|
||||
}
|
||||
|
||||
init_check_frame_length_mode(ug_info->lengthCheckRx, &ug_regs->maccfg2);
|
||||
|
||||
ret_val = init_preamble_length(ug_info->prel, &ug_regs->maccfg2);
|
||||
if (ret_val != 0) {
|
||||
if (netif_msg_probe(ugeth))
|
||||
pr_err("Preamble length must be between 3 and 7 inclusive\n");
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return phy_interface_mode_is_rgmii(interface) ||
|
||||
interface == PHY_INTERFACE_MODE_RMII ||
|
||||
interface == PHY_INTERFACE_MODE_RTBI;
|
||||
}
|
||||
|
||||
static int ugeth_graceful_stop_tx(struct ucc_geth_private *ugeth)
|
||||
@ -1545,108 +1434,7 @@ static void ugeth_activate(struct ucc_geth_private *ugeth)
|
||||
|
||||
/* allow to xmit again */
|
||||
netif_tx_wake_all_queues(ugeth->ndev);
|
||||
__netdev_watchdog_up(ugeth->ndev);
|
||||
}
|
||||
|
||||
/* Called every time the controller might need to be made
|
||||
* aware of new link state. The PHY code conveys this
|
||||
* information through variables in the ugeth structure, and this
|
||||
* function converts those variables into the appropriate
|
||||
* register values, and can bring down the device if needed.
|
||||
*/
|
||||
|
||||
static void adjust_link(struct net_device *dev)
|
||||
{
|
||||
struct ucc_geth_private *ugeth = netdev_priv(dev);
|
||||
struct ucc_geth __iomem *ug_regs;
|
||||
struct ucc_fast __iomem *uf_regs;
|
||||
struct phy_device *phydev = ugeth->phydev;
|
||||
int new_state = 0;
|
||||
|
||||
ug_regs = ugeth->ug_regs;
|
||||
uf_regs = ugeth->uccf->uf_regs;
|
||||
|
||||
if (phydev->link) {
|
||||
u32 tempval = in_be32(&ug_regs->maccfg2);
|
||||
u32 upsmr = in_be32(&uf_regs->upsmr);
|
||||
/* Now we make sure that we can be in full duplex mode.
|
||||
* If not, we operate in half-duplex mode. */
|
||||
if (phydev->duplex != ugeth->oldduplex) {
|
||||
new_state = 1;
|
||||
if (!(phydev->duplex))
|
||||
tempval &= ~(MACCFG2_FDX);
|
||||
else
|
||||
tempval |= MACCFG2_FDX;
|
||||
ugeth->oldduplex = phydev->duplex;
|
||||
}
|
||||
|
||||
if (phydev->speed != ugeth->oldspeed) {
|
||||
new_state = 1;
|
||||
switch (phydev->speed) {
|
||||
case SPEED_1000:
|
||||
tempval = ((tempval &
|
||||
~(MACCFG2_INTERFACE_MODE_MASK)) |
|
||||
MACCFG2_INTERFACE_MODE_BYTE);
|
||||
break;
|
||||
case SPEED_100:
|
||||
case SPEED_10:
|
||||
tempval = ((tempval &
|
||||
~(MACCFG2_INTERFACE_MODE_MASK)) |
|
||||
MACCFG2_INTERFACE_MODE_NIBBLE);
|
||||
/* if reduced mode, re-set UPSMR.R10M */
|
||||
if ((ugeth->phy_interface == PHY_INTERFACE_MODE_RMII) ||
|
||||
(ugeth->phy_interface == PHY_INTERFACE_MODE_RGMII) ||
|
||||
(ugeth->phy_interface == PHY_INTERFACE_MODE_RGMII_ID) ||
|
||||
(ugeth->phy_interface == PHY_INTERFACE_MODE_RGMII_RXID) ||
|
||||
(ugeth->phy_interface == PHY_INTERFACE_MODE_RGMII_TXID) ||
|
||||
(ugeth->phy_interface == PHY_INTERFACE_MODE_RTBI)) {
|
||||
if (phydev->speed == SPEED_10)
|
||||
upsmr |= UCC_GETH_UPSMR_R10M;
|
||||
else
|
||||
upsmr &= ~UCC_GETH_UPSMR_R10M;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (netif_msg_link(ugeth))
|
||||
pr_warn(
|
||||
"%s: Ack! Speed (%d) is not 10/100/1000!",
|
||||
dev->name, phydev->speed);
|
||||
break;
|
||||
}
|
||||
ugeth->oldspeed = phydev->speed;
|
||||
}
|
||||
|
||||
if (!ugeth->oldlink) {
|
||||
new_state = 1;
|
||||
ugeth->oldlink = 1;
|
||||
}
|
||||
|
||||
if (new_state) {
|
||||
/*
|
||||
* To change the MAC configuration we need to disable
|
||||
* the controller. To do so, we have to either grab
|
||||
* ugeth->lock, which is a bad idea since 'graceful
|
||||
* stop' commands might take quite a while, or we can
|
||||
* quiesce driver's activity.
|
||||
*/
|
||||
ugeth_quiesce(ugeth);
|
||||
ugeth_disable(ugeth, COMM_DIR_RX_AND_TX);
|
||||
|
||||
out_be32(&ug_regs->maccfg2, tempval);
|
||||
out_be32(&uf_regs->upsmr, upsmr);
|
||||
|
||||
ugeth_enable(ugeth, COMM_DIR_RX_AND_TX);
|
||||
ugeth_activate(ugeth);
|
||||
}
|
||||
} else if (ugeth->oldlink) {
|
||||
new_state = 1;
|
||||
ugeth->oldlink = 0;
|
||||
ugeth->oldspeed = 0;
|
||||
ugeth->oldduplex = -1;
|
||||
}
|
||||
|
||||
if (new_state && netif_msg_link(ugeth))
|
||||
phy_print_status(phydev);
|
||||
netdev_watchdog_up(ugeth->ndev);
|
||||
}
|
||||
|
||||
/* Initialize TBI PHY interface for communicating with the
|
||||
@ -1664,8 +1452,7 @@ static void uec_configure_serdes(struct net_device *dev)
|
||||
struct phy_device *tbiphy;
|
||||
|
||||
if (!ug_info->tbi_node) {
|
||||
dev_warn(&dev->dev, "SGMII mode requires that the device "
|
||||
"tree specify a tbi-handle\n");
|
||||
dev_warn(&dev->dev, "SGMII mode requires that the device tree specify a tbi-handle\n");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1696,34 +1483,145 @@ static void uec_configure_serdes(struct net_device *dev)
|
||||
put_device(&tbiphy->mdio.dev);
|
||||
}
|
||||
|
||||
/* Configure the PHY for dev.
|
||||
* returns 0 if success. -1 if failure
|
||||
*/
|
||||
static int init_phy(struct net_device *dev)
|
||||
static void ugeth_mac_link_up(struct phylink_config *config, struct phy_device *phy,
|
||||
unsigned int mode, phy_interface_t interface,
|
||||
int speed, int duplex, bool tx_pause, bool rx_pause)
|
||||
{
|
||||
struct ucc_geth_private *priv = netdev_priv(dev);
|
||||
struct ucc_geth_info *ug_info = priv->ug_info;
|
||||
struct phy_device *phydev;
|
||||
struct net_device *ndev = to_net_dev(config->dev);
|
||||
struct ucc_geth_private *ugeth = netdev_priv(ndev);
|
||||
struct ucc_geth_info *ug_info = ugeth->ug_info;
|
||||
struct ucc_geth __iomem *ug_regs = ugeth->ug_regs;
|
||||
struct ucc_fast __iomem *uf_regs = ugeth->uccf->uf_regs;
|
||||
u32 old_maccfg2, maccfg2 = in_be32(&ug_regs->maccfg2);
|
||||
u32 old_upsmr, upsmr = in_be32(&uf_regs->upsmr);
|
||||
|
||||
priv->oldlink = 0;
|
||||
priv->oldspeed = 0;
|
||||
priv->oldduplex = -1;
|
||||
old_maccfg2 = maccfg2;
|
||||
old_upsmr = upsmr;
|
||||
|
||||
phydev = of_phy_connect(dev, ug_info->phy_node, &adjust_link, 0,
|
||||
priv->phy_interface);
|
||||
if (!phydev) {
|
||||
dev_err(&dev->dev, "Could not attach to PHY\n");
|
||||
return -ENODEV;
|
||||
/* No length check */
|
||||
maccfg2 &= ~MACCFG2_LC;
|
||||
maccfg2 &= ~MACCFG2_INTERFACE_MODE_MASK;
|
||||
upsmr &= ~(UCC_GETH_UPSMR_RPM | UCC_GETH_UPSMR_R10M |
|
||||
UCC_GETH_UPSMR_TBIM | UCC_GETH_UPSMR_RMM);
|
||||
|
||||
if (speed == SPEED_10 || speed == SPEED_100)
|
||||
maccfg2 |= MACCFG2_INTERFACE_MODE_NIBBLE;
|
||||
else if (speed == SPEED_1000)
|
||||
maccfg2 |= MACCFG2_INTERFACE_MODE_BYTE;
|
||||
|
||||
maccfg2 |= ug_info->padAndCrc;
|
||||
|
||||
if (phy_interface_mode_is_reduced(interface)) {
|
||||
|
||||
if (interface != PHY_INTERFACE_MODE_RMII)
|
||||
upsmr |= UCC_GETH_UPSMR_RPM;
|
||||
|
||||
switch (speed) {
|
||||
case SPEED_10:
|
||||
upsmr |= UCC_GETH_UPSMR_R10M;
|
||||
fallthrough;
|
||||
case SPEED_100:
|
||||
if (interface != PHY_INTERFACE_MODE_RTBI)
|
||||
upsmr |= UCC_GETH_UPSMR_RMM;
|
||||
}
|
||||
}
|
||||
|
||||
if (priv->phy_interface == PHY_INTERFACE_MODE_SGMII)
|
||||
uec_configure_serdes(dev);
|
||||
if (interface == PHY_INTERFACE_MODE_TBI ||
|
||||
interface == PHY_INTERFACE_MODE_RTBI)
|
||||
upsmr |= UCC_GETH_UPSMR_TBIM;
|
||||
|
||||
phy_set_max_speed(phydev, priv->max_speed);
|
||||
if (interface == PHY_INTERFACE_MODE_SGMII)
|
||||
upsmr |= UCC_GETH_UPSMR_SGMM;
|
||||
|
||||
priv->phydev = phydev;
|
||||
if (duplex == DUPLEX_HALF)
|
||||
maccfg2 &= ~(MACCFG2_FDX);
|
||||
else
|
||||
maccfg2 |= MACCFG2_FDX;
|
||||
|
||||
return 0;
|
||||
if (maccfg2 != old_maccfg2 || upsmr != old_upsmr) {
|
||||
/*
|
||||
* To change the MAC configuration we need to disable
|
||||
* the controller. To do so, we have to either grab
|
||||
* ugeth->lock, which is a bad idea since 'graceful
|
||||
* stop' commands might take quite a while, or we can
|
||||
* quiesce driver's activity.
|
||||
*/
|
||||
ugeth_quiesce(ugeth);
|
||||
ugeth_disable(ugeth, COMM_DIR_RX_AND_TX);
|
||||
|
||||
out_be32(&ug_regs->maccfg2, maccfg2);
|
||||
out_be32(&uf_regs->upsmr, upsmr);
|
||||
|
||||
ugeth_enable(ugeth, COMM_DIR_RX_AND_TX);
|
||||
ugeth_activate(ugeth);
|
||||
}
|
||||
|
||||
if (interface == PHY_INTERFACE_MODE_SGMII)
|
||||
uec_configure_serdes(ndev);
|
||||
|
||||
if (!phylink_autoneg_inband(mode)) {
|
||||
ug_info->aufc = 0;
|
||||
ug_info->receiveFlowControl = rx_pause;
|
||||
ug_info->transmitFlowControl = tx_pause;
|
||||
|
||||
init_flow_control_params(ug_info->aufc,
|
||||
ug_info->receiveFlowControl,
|
||||
ug_info->transmitFlowControl,
|
||||
ug_info->pausePeriod,
|
||||
ug_info->extensionField,
|
||||
&ugeth->uccf->uf_regs->upsmr,
|
||||
&ugeth->ug_regs->uempr,
|
||||
&ugeth->ug_regs->maccfg1);
|
||||
}
|
||||
|
||||
ugeth_enable(ugeth, COMM_DIR_RX_AND_TX);
|
||||
}
|
||||
|
||||
static void ugeth_mac_link_down(struct phylink_config *config,
|
||||
unsigned int mode, phy_interface_t interface)
|
||||
{
|
||||
struct net_device *ndev = to_net_dev(config->dev);
|
||||
struct ucc_geth_private *ugeth = netdev_priv(ndev);
|
||||
|
||||
ugeth_disable(ugeth, COMM_DIR_RX_AND_TX);
|
||||
}
|
||||
|
||||
static void ugeth_mac_config(struct phylink_config *config, unsigned int mode,
|
||||
const struct phylink_link_state *state)
|
||||
{
|
||||
struct net_device *ndev = to_net_dev(config->dev);
|
||||
struct ucc_geth_private *ugeth = netdev_priv(ndev);
|
||||
struct ucc_geth_info *ug_info = ugeth->ug_info;
|
||||
u16 value;
|
||||
|
||||
if (state->interface == PHY_INTERFACE_MODE_TBI ||
|
||||
state->interface == PHY_INTERFACE_MODE_RTBI) {
|
||||
struct phy_device *tbiphy;
|
||||
|
||||
if (!ug_info->tbi_node)
|
||||
pr_warn("TBI mode requires that the device tree specify a tbi-handle\n");
|
||||
|
||||
tbiphy = of_phy_find_device(ug_info->tbi_node);
|
||||
if (!tbiphy)
|
||||
pr_warn("Could not get TBI device\n");
|
||||
|
||||
value = phy_read(tbiphy, ENET_TBI_MII_CR);
|
||||
value &= ~0x1000; /* Turn off autonegotiation */
|
||||
phy_write(tbiphy, ENET_TBI_MII_CR, value);
|
||||
|
||||
put_device(&tbiphy->mdio.dev);
|
||||
}
|
||||
|
||||
if (phylink_autoneg_inband(mode)) {
|
||||
ug_info->aufc = 1;
|
||||
|
||||
init_flow_control_params(ug_info->aufc, 1, 1,
|
||||
ug_info->pausePeriod,
|
||||
ug_info->extensionField,
|
||||
&ugeth->uccf->uf_regs->upsmr,
|
||||
&ugeth->ug_regs->uempr,
|
||||
&ugeth->ug_regs->maccfg1);
|
||||
}
|
||||
}
|
||||
|
||||
static void ugeth_dump_regs(struct ucc_geth_private *ugeth)
|
||||
@ -1995,7 +1893,6 @@ static void ucc_geth_set_multi(struct net_device *dev)
|
||||
static void ucc_geth_stop(struct ucc_geth_private *ugeth)
|
||||
{
|
||||
struct ucc_geth __iomem *ug_regs = ugeth->ug_regs;
|
||||
struct phy_device *phydev = ugeth->phydev;
|
||||
|
||||
ugeth_vdbg("%s: IN", __func__);
|
||||
|
||||
@ -2004,7 +1901,7 @@ static void ucc_geth_stop(struct ucc_geth_private *ugeth)
|
||||
* Must be done before disabling the controller
|
||||
* or deadlock may happen.
|
||||
*/
|
||||
phy_stop(phydev);
|
||||
phylink_stop(ugeth->phylink);
|
||||
|
||||
/* Disable the controller */
|
||||
ugeth_disable(ugeth, COMM_DIR_RX_AND_TX);
|
||||
@ -3246,12 +3143,6 @@ static int ucc_geth_init_mac(struct ucc_geth_private *ugeth)
|
||||
goto err;
|
||||
}
|
||||
|
||||
err = adjust_enet_interface(ugeth);
|
||||
if (err) {
|
||||
netif_err(ugeth, ifup, dev, "Cannot configure net device, aborting\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Set MACSTNADDR1, MACSTNADDR2 */
|
||||
/* For more details see the hardware spec. */
|
||||
init_mac_station_addr_regs(dev->dev_addr[0],
|
||||
@ -3263,12 +3154,6 @@ static int ucc_geth_init_mac(struct ucc_geth_private *ugeth)
|
||||
&ugeth->ug_regs->macstnaddr1,
|
||||
&ugeth->ug_regs->macstnaddr2);
|
||||
|
||||
err = ugeth_enable(ugeth, COMM_DIR_RX_AND_TX);
|
||||
if (err) {
|
||||
netif_err(ugeth, ifup, dev, "Cannot enable net device, aborting\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
err:
|
||||
ucc_geth_stop(ugeth);
|
||||
@ -3291,10 +3176,10 @@ static int ucc_geth_open(struct net_device *dev)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
err = init_phy(dev);
|
||||
err = phylink_of_phy_connect(ugeth->phylink, ugeth->dev->of_node, 0);
|
||||
if (err) {
|
||||
netif_err(ugeth, ifup, dev, "Cannot initialize PHY, aborting\n");
|
||||
return err;
|
||||
dev_err(&dev->dev, "Could not attach to PHY\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
err = ucc_geth_init_mac(ugeth);
|
||||
@ -3310,13 +3195,13 @@ static int ucc_geth_open(struct net_device *dev)
|
||||
goto err;
|
||||
}
|
||||
|
||||
phy_start(ugeth->phydev);
|
||||
phylink_start(ugeth->phylink);
|
||||
napi_enable(&ugeth->napi);
|
||||
netdev_reset_queue(dev);
|
||||
netif_start_queue(dev);
|
||||
|
||||
device_set_wakeup_capable(&dev->dev,
|
||||
qe_alive_during_sleep() || ugeth->phydev->irq);
|
||||
qe_alive_during_sleep() || dev->phydev->irq);
|
||||
device_set_wakeup_enable(&dev->dev, ugeth->wol_en);
|
||||
|
||||
return err;
|
||||
@ -3337,8 +3222,7 @@ static int ucc_geth_close(struct net_device *dev)
|
||||
|
||||
cancel_work_sync(&ugeth->timeout_work);
|
||||
ucc_geth_stop(ugeth);
|
||||
phy_disconnect(ugeth->phydev);
|
||||
ugeth->phydev = NULL;
|
||||
phylink_disconnect_phy(ugeth->phylink);
|
||||
|
||||
free_irq(ugeth->ug_info->uf_info.irq, ugeth->ndev);
|
||||
|
||||
@ -3372,7 +3256,7 @@ static void ucc_geth_timeout_work(struct work_struct *work)
|
||||
ucc_geth_stop(ugeth);
|
||||
ucc_geth_init_mac(ugeth);
|
||||
/* Must start PHY here */
|
||||
phy_start(ugeth->phydev);
|
||||
phylink_start(ugeth->phylink);
|
||||
netif_tx_start_all_queues(dev);
|
||||
}
|
||||
|
||||
@ -3397,6 +3281,7 @@ static int ucc_geth_suspend(struct platform_device *ofdev, pm_message_t state)
|
||||
{
|
||||
struct net_device *ndev = platform_get_drvdata(ofdev);
|
||||
struct ucc_geth_private *ugeth = netdev_priv(ndev);
|
||||
bool mac_wol = false;
|
||||
|
||||
if (!netif_running(ndev))
|
||||
return 0;
|
||||
@ -3410,14 +3295,17 @@ static int ucc_geth_suspend(struct platform_device *ofdev, pm_message_t state)
|
||||
*/
|
||||
ugeth_disable(ugeth, COMM_DIR_RX_AND_TX);
|
||||
|
||||
if (ugeth->wol_en & WAKE_MAGIC) {
|
||||
if (ugeth->wol_en & WAKE_MAGIC && !ugeth->phy_wol_en) {
|
||||
setbits32(ugeth->uccf->p_uccm, UCC_GETH_UCCE_MPD);
|
||||
setbits32(&ugeth->ug_regs->maccfg2, MACCFG2_MPE);
|
||||
ucc_fast_enable(ugeth->uccf, COMM_DIR_RX_AND_TX);
|
||||
} else if (!(ugeth->wol_en & WAKE_PHY)) {
|
||||
phy_stop(ugeth->phydev);
|
||||
mac_wol = true;
|
||||
}
|
||||
|
||||
rtnl_lock();
|
||||
phylink_suspend(ugeth->phylink, mac_wol);
|
||||
rtnl_unlock();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -3451,12 +3339,9 @@ static int ucc_geth_resume(struct platform_device *ofdev)
|
||||
}
|
||||
}
|
||||
|
||||
ugeth->oldlink = 0;
|
||||
ugeth->oldspeed = 0;
|
||||
ugeth->oldduplex = -1;
|
||||
|
||||
phy_stop(ugeth->phydev);
|
||||
phy_start(ugeth->phydev);
|
||||
rtnl_lock();
|
||||
phylink_resume(ugeth->phylink);
|
||||
rtnl_unlock();
|
||||
|
||||
napi_enable(&ugeth->napi);
|
||||
netif_device_attach(ndev);
|
||||
@ -3469,32 +3354,6 @@ static int ucc_geth_resume(struct platform_device *ofdev)
|
||||
#define ucc_geth_resume NULL
|
||||
#endif
|
||||
|
||||
static phy_interface_t to_phy_interface(const char *phy_connection_type)
|
||||
{
|
||||
if (strcasecmp(phy_connection_type, "mii") == 0)
|
||||
return PHY_INTERFACE_MODE_MII;
|
||||
if (strcasecmp(phy_connection_type, "gmii") == 0)
|
||||
return PHY_INTERFACE_MODE_GMII;
|
||||
if (strcasecmp(phy_connection_type, "tbi") == 0)
|
||||
return PHY_INTERFACE_MODE_TBI;
|
||||
if (strcasecmp(phy_connection_type, "rmii") == 0)
|
||||
return PHY_INTERFACE_MODE_RMII;
|
||||
if (strcasecmp(phy_connection_type, "rgmii") == 0)
|
||||
return PHY_INTERFACE_MODE_RGMII;
|
||||
if (strcasecmp(phy_connection_type, "rgmii-id") == 0)
|
||||
return PHY_INTERFACE_MODE_RGMII_ID;
|
||||
if (strcasecmp(phy_connection_type, "rgmii-txid") == 0)
|
||||
return PHY_INTERFACE_MODE_RGMII_TXID;
|
||||
if (strcasecmp(phy_connection_type, "rgmii-rxid") == 0)
|
||||
return PHY_INTERFACE_MODE_RGMII_RXID;
|
||||
if (strcasecmp(phy_connection_type, "rtbi") == 0)
|
||||
return PHY_INTERFACE_MODE_RTBI;
|
||||
if (strcasecmp(phy_connection_type, "sgmii") == 0)
|
||||
return PHY_INTERFACE_MODE_SGMII;
|
||||
|
||||
return PHY_INTERFACE_MODE_MII;
|
||||
}
|
||||
|
||||
static int ucc_geth_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
|
||||
{
|
||||
struct ucc_geth_private *ugeth = netdev_priv(dev);
|
||||
@ -3502,10 +3361,7 @@ static int ucc_geth_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
|
||||
if (!netif_running(dev))
|
||||
return -EINVAL;
|
||||
|
||||
if (!ugeth->phydev)
|
||||
return -ENODEV;
|
||||
|
||||
return phy_mii_ioctl(ugeth->phydev, rq, cmd);
|
||||
return phylink_mii_ioctl(ugeth->phylink, rq, cmd);
|
||||
}
|
||||
|
||||
static const struct net_device_ops ucc_geth_netdev_ops = {
|
||||
@ -3513,7 +3369,6 @@ static const struct net_device_ops ucc_geth_netdev_ops = {
|
||||
.ndo_stop = ucc_geth_close,
|
||||
.ndo_start_xmit = ucc_geth_start_xmit,
|
||||
.ndo_validate_addr = eth_validate_addr,
|
||||
.ndo_change_carrier = fixed_phy_change_carrier,
|
||||
.ndo_set_mac_address = ucc_geth_set_mac_addr,
|
||||
.ndo_set_rx_mode = ucc_geth_set_multi,
|
||||
.ndo_tx_timeout = ucc_geth_timeout,
|
||||
@ -3553,6 +3408,12 @@ static int ucc_geth_parse_clock(struct device_node *np, const char *which,
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct phylink_mac_ops ugeth_mac_ops = {
|
||||
.mac_link_up = ugeth_mac_link_up,
|
||||
.mac_link_down = ugeth_mac_link_down,
|
||||
.mac_config = ugeth_mac_config,
|
||||
};
|
||||
|
||||
static int ucc_geth_probe(struct platform_device* ofdev)
|
||||
{
|
||||
struct device *device = &ofdev->dev;
|
||||
@ -3560,23 +3421,12 @@ static int ucc_geth_probe(struct platform_device* ofdev)
|
||||
struct net_device *dev = NULL;
|
||||
struct ucc_geth_private *ugeth = NULL;
|
||||
struct ucc_geth_info *ug_info;
|
||||
struct device_node *phy_node;
|
||||
struct phylink *phylink;
|
||||
struct resource res;
|
||||
int err, ucc_num, max_speed = 0;
|
||||
int err, ucc_num;
|
||||
const unsigned int *prop;
|
||||
phy_interface_t phy_interface;
|
||||
static const int enet_to_speed[] = {
|
||||
SPEED_10, SPEED_10, SPEED_10,
|
||||
SPEED_100, SPEED_100, SPEED_100,
|
||||
SPEED_1000, SPEED_1000, SPEED_1000, SPEED_1000,
|
||||
};
|
||||
static const phy_interface_t enet_to_phy_interface[] = {
|
||||
PHY_INTERFACE_MODE_MII, PHY_INTERFACE_MODE_RMII,
|
||||
PHY_INTERFACE_MODE_RGMII, PHY_INTERFACE_MODE_MII,
|
||||
PHY_INTERFACE_MODE_RMII, PHY_INTERFACE_MODE_RGMII,
|
||||
PHY_INTERFACE_MODE_GMII, PHY_INTERFACE_MODE_RGMII,
|
||||
PHY_INTERFACE_MODE_TBI, PHY_INTERFACE_MODE_RTBI,
|
||||
PHY_INTERFACE_MODE_SGMII,
|
||||
};
|
||||
|
||||
ugeth_vdbg("%s: IN", __func__);
|
||||
|
||||
@ -3612,57 +3462,35 @@ static int ucc_geth_probe(struct platform_device* ofdev)
|
||||
ug_info->uf_info.regs = res.start;
|
||||
ug_info->uf_info.irq = irq_of_parse_and_map(np, 0);
|
||||
|
||||
ug_info->phy_node = of_parse_phandle(np, "phy-handle", 0);
|
||||
if (!ug_info->phy_node && of_phy_is_fixed_link(np)) {
|
||||
/*
|
||||
* In the case of a fixed PHY, the DT node associated
|
||||
* to the PHY is the Ethernet MAC DT node.
|
||||
*/
|
||||
err = of_phy_register_fixed_link(np);
|
||||
if (err)
|
||||
return err;
|
||||
ug_info->phy_node = of_node_get(np);
|
||||
}
|
||||
|
||||
/* Find the TBI PHY node. If it's not there, we don't support SGMII */
|
||||
ug_info->tbi_node = of_parse_phandle(np, "tbi-handle", 0);
|
||||
|
||||
/* get the phy interface type, or default to MII */
|
||||
prop = of_get_property(np, "phy-connection-type", NULL);
|
||||
if (!prop) {
|
||||
/* handle interface property present in old trees */
|
||||
prop = of_get_property(ug_info->phy_node, "interface", NULL);
|
||||
if (prop != NULL) {
|
||||
phy_interface = enet_to_phy_interface[*prop];
|
||||
max_speed = enet_to_speed[*prop];
|
||||
} else
|
||||
phy_interface = PHY_INTERFACE_MODE_MII;
|
||||
} else {
|
||||
phy_interface = to_phy_interface((const char *)prop);
|
||||
phy_node = of_parse_phandle(np, "phy-handle", 0);
|
||||
if (phy_node) {
|
||||
prop = of_get_property(phy_node, "interface", NULL);
|
||||
if (prop) {
|
||||
dev_err(&ofdev->dev,
|
||||
"Device-tree property 'interface' is no longer supported. Please use 'phy-connection-type' instead.");
|
||||
of_node_put(phy_node);
|
||||
err = -EINVAL;
|
||||
goto err_put_tbi;
|
||||
}
|
||||
of_node_put(phy_node);
|
||||
}
|
||||
|
||||
/* get speed, or derive from PHY interface */
|
||||
if (max_speed == 0)
|
||||
switch (phy_interface) {
|
||||
case PHY_INTERFACE_MODE_GMII:
|
||||
case PHY_INTERFACE_MODE_RGMII:
|
||||
case PHY_INTERFACE_MODE_RGMII_ID:
|
||||
case PHY_INTERFACE_MODE_RGMII_RXID:
|
||||
case PHY_INTERFACE_MODE_RGMII_TXID:
|
||||
case PHY_INTERFACE_MODE_TBI:
|
||||
case PHY_INTERFACE_MODE_RTBI:
|
||||
case PHY_INTERFACE_MODE_SGMII:
|
||||
max_speed = SPEED_1000;
|
||||
break;
|
||||
default:
|
||||
max_speed = SPEED_100;
|
||||
break;
|
||||
err = of_get_phy_mode(np, &phy_interface);
|
||||
if (err) {
|
||||
dev_err(&ofdev->dev, "Invalid phy-connection-type");
|
||||
goto err_put_tbi;
|
||||
}
|
||||
|
||||
if (max_speed == SPEED_1000) {
|
||||
if (phy_interface == PHY_INTERFACE_MODE_GMII ||
|
||||
phy_interface_mode_is_rgmii(phy_interface) ||
|
||||
phy_interface == PHY_INTERFACE_MODE_TBI ||
|
||||
phy_interface == PHY_INTERFACE_MODE_RTBI ||
|
||||
phy_interface == PHY_INTERFACE_MODE_SGMII) {
|
||||
unsigned int snums = qe_get_num_of_snums();
|
||||
|
||||
/* configure muram FIFOs for gigabit operation */
|
||||
ug_info->uf_info.urfs = UCC_GETH_URFS_GIGA_INIT;
|
||||
ug_info->uf_info.urfet = UCC_GETH_URFET_GIGA_INIT;
|
||||
ug_info->uf_info.urfset = UCC_GETH_URFSET_GIGA_INIT;
|
||||
@ -3691,7 +3519,7 @@ static int ucc_geth_probe(struct platform_device* ofdev)
|
||||
dev = devm_alloc_etherdev(&ofdev->dev, sizeof(*ugeth));
|
||||
if (!dev) {
|
||||
err = -ENOMEM;
|
||||
goto err_deregister_fixed_link;
|
||||
goto err_put_tbi;
|
||||
}
|
||||
|
||||
ugeth = netdev_priv(dev);
|
||||
@ -3718,23 +3546,50 @@ static int ucc_geth_probe(struct platform_device* ofdev)
|
||||
dev->max_mtu = 1518;
|
||||
|
||||
ugeth->msg_enable = netif_msg_init(debug.msg_enable, UGETH_MSG_DEFAULT);
|
||||
ugeth->phy_interface = phy_interface;
|
||||
ugeth->max_speed = max_speed;
|
||||
|
||||
/* Carrier starts down, phylib will bring it up */
|
||||
netif_carrier_off(dev);
|
||||
ugeth->phylink_config.dev = &dev->dev;
|
||||
ugeth->phylink_config.type = PHYLINK_NETDEV;
|
||||
|
||||
ugeth->phylink_config.mac_capabilities =
|
||||
MAC_SYM_PAUSE | MAC_10 | MAC_100 | MAC_1000FD;
|
||||
|
||||
__set_bit(PHY_INTERFACE_MODE_MII,
|
||||
ugeth->phylink_config.supported_interfaces);
|
||||
__set_bit(PHY_INTERFACE_MODE_RMII,
|
||||
ugeth->phylink_config.supported_interfaces);
|
||||
__set_bit(PHY_INTERFACE_MODE_GMII,
|
||||
ugeth->phylink_config.supported_interfaces);
|
||||
phy_interface_set_rgmii(ugeth->phylink_config.supported_interfaces);
|
||||
|
||||
if (ug_info->tbi_node) {
|
||||
__set_bit(PHY_INTERFACE_MODE_SGMII,
|
||||
ugeth->phylink_config.supported_interfaces);
|
||||
__set_bit(PHY_INTERFACE_MODE_TBI,
|
||||
ugeth->phylink_config.supported_interfaces);
|
||||
__set_bit(PHY_INTERFACE_MODE_RTBI,
|
||||
ugeth->phylink_config.supported_interfaces);
|
||||
}
|
||||
|
||||
phylink = phylink_create(&ugeth->phylink_config, dev_fwnode(&dev->dev),
|
||||
phy_interface, &ugeth_mac_ops);
|
||||
if (IS_ERR(phylink)) {
|
||||
err = PTR_ERR(phylink);
|
||||
goto err_put_tbi;
|
||||
}
|
||||
|
||||
ugeth->phylink = phylink;
|
||||
|
||||
err = devm_register_netdev(&ofdev->dev, dev);
|
||||
if (err) {
|
||||
if (netif_msg_probe(ugeth))
|
||||
pr_err("%s: Cannot register net device, aborting\n",
|
||||
dev->name);
|
||||
goto err_deregister_fixed_link;
|
||||
goto err_destroy_phylink;
|
||||
}
|
||||
|
||||
err = of_get_ethdev_address(np, dev);
|
||||
if (err == -EPROBE_DEFER)
|
||||
goto err_deregister_fixed_link;
|
||||
goto err_destroy_phylink;
|
||||
|
||||
ugeth->ug_info = ug_info;
|
||||
ugeth->dev = device;
|
||||
@ -3743,11 +3598,11 @@ static int ucc_geth_probe(struct platform_device* ofdev)
|
||||
|
||||
return 0;
|
||||
|
||||
err_deregister_fixed_link:
|
||||
if (of_phy_is_fixed_link(np))
|
||||
of_phy_deregister_fixed_link(np);
|
||||
err_destroy_phylink:
|
||||
phylink_destroy(phylink);
|
||||
err_put_tbi:
|
||||
of_node_put(ug_info->tbi_node);
|
||||
of_node_put(ug_info->phy_node);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
@ -3755,13 +3610,10 @@ static void ucc_geth_remove(struct platform_device* ofdev)
|
||||
{
|
||||
struct net_device *dev = platform_get_drvdata(ofdev);
|
||||
struct ucc_geth_private *ugeth = netdev_priv(dev);
|
||||
struct device_node *np = ofdev->dev.of_node;
|
||||
|
||||
ucc_geth_memclean(ugeth);
|
||||
if (of_phy_is_fixed_link(np))
|
||||
of_phy_deregister_fixed_link(np);
|
||||
phylink_destroy(ugeth->phylink);
|
||||
of_node_put(ugeth->ug_info->tbi_node);
|
||||
of_node_put(ugeth->ug_info->phy_node);
|
||||
}
|
||||
|
||||
static const struct of_device_id ucc_geth_match[] = {
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user