Merge branch 'main' of git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-next.git

This commit is contained in:
Stephen Rothwell 2025-01-14 11:54:20 +11:00
commit 9e4691b393
883 changed files with 41444 additions and 11599 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

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

View File

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

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

View File

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

View File

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

View File

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

View File

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

View File

@ -90,4 +90,3 @@ examples:
marvell,wakeup-pin = <3>;
};
};

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -86,6 +86,7 @@ Contents:
netdevices
netfilter-sysctl
netif-msg
netmem
nexthop-group-resilient
nf_conntrack-sysctl
nf_flowtable

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -148,6 +148,8 @@
#define SCM_TS_OPT_ID 81
#define SO_RCVPRIORITY 82
#if !defined(__KERNEL__)
#if __BITS_PER_LONG == 64

View File

@ -159,6 +159,8 @@
#define SCM_TS_OPT_ID 81
#define SO_RCVPRIORITY 82
#if !defined(__KERNEL__)
#if __BITS_PER_LONG == 64

View File

@ -140,6 +140,8 @@
#define SCM_TS_OPT_ID 0x404C
#define SO_RCVPRIORITY 0x404D
#if !defined(__KERNEL__)
#if __BITS_PER_LONG == 64

View File

@ -141,6 +141,8 @@
#define SCM_TS_OPT_ID 0x005a
#define SO_RCVPRIORITY 0x005b
#if !defined(__KERNEL__)

View File

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

View File

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

View File

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

View File

@ -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[],

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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