Merge branch 'rtl8365mb-vc-support'
Alvin Šipraga says: ==================== net: dsa: add support for RTL8365MB-VC This series adds support for Realtek's RTL8365MB-VC, a 4+1 port 10/100/1000M Ethernet switch. The driver - rtl8365mb - was developed by Michael Ramussen and myself. This version of the driver is relatively slim, implementing only the standalone port functionality and no offload capabilities. It is based on a previous RFC series [1] from August, and the main difference is the removal of some spurious VLAN operations. Otherwise I have simply addressed most of the feedback. Please see the respective patches for more detail. In parallel I am working on offloading the bridge layer capabilities, but I would like to get the basic stuff upstreamed as soon as possible. v3 -> v4: - get irq before setting virq parents (fixes kernel test robot warning) - remove pad-to-72-bytes logic in tagger xmit (fixes DENG Qingfang's suggestion); no longer needed as we set CPU minimum RX size to 64 bytes - use mutex to protect MIB counter access instead of a spinlock (fixes Jakub's feedback on v3 statistics refactoring) v2 -> v3: - move IRQ setup earlier in probe per Florian's suggestion - fix compilation error on some archs due to FIELD_PREP use in v1 - follow Jakub's suggestion and use the standard ethtool stats API; NOTE: new patch in the series for relevant DSA plumbing - following the stats change, it became apparent that the rtl8366 helper library is no longer that helpful; scrap it and implement the ethtool ops specifically for this chip v1 -> v2: - drop DSA port type checks during MAC configuration - use OF properties to configure RGMII TX/RX delay - don't set default fwd_offload_mark if packet is trapped to CPU - remove port mapping macros - update device tree bindings documentation with an example - cosmetic changes to the tagging driver using FIELD_* macros [1] https://lore.kernel.org/netdev/20210822193145.1312668-1-alvin@pqrs.dk/ ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
c87350ced1
@ -9,6 +9,7 @@ SMI-based Realtek devices.
|
||||
Required properties:
|
||||
|
||||
- compatible: must be exactly one of:
|
||||
"realtek,rtl8365mb" (4+1 ports)
|
||||
"realtek,rtl8366"
|
||||
"realtek,rtl8366rb" (4+1 ports)
|
||||
"realtek,rtl8366s" (4+1 ports)
|
||||
@ -62,6 +63,8 @@ and subnodes of DSA switches.
|
||||
|
||||
Examples:
|
||||
|
||||
An example for the RTL8366RB:
|
||||
|
||||
switch {
|
||||
compatible = "realtek,rtl8366rb";
|
||||
/* 22 = MDIO (has input reads), 21 = MDC (clock, output only) */
|
||||
@ -151,3 +154,87 @@ switch {
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
An example for the RTL8365MB-VC:
|
||||
|
||||
switch {
|
||||
compatible = "realtek,rtl8365mb";
|
||||
mdc-gpios = <&gpio1 16 GPIO_ACTIVE_HIGH>;
|
||||
mdio-gpios = <&gpio1 17 GPIO_ACTIVE_HIGH>;
|
||||
reset-gpios = <&gpio5 0 GPIO_ACTIVE_LOW>;
|
||||
|
||||
switch_intc: interrupt-controller {
|
||||
interrupt-parent = <&gpio5>;
|
||||
interrupts = <1 IRQ_TYPE_LEVEL_LOW>;
|
||||
interrupt-controller;
|
||||
#address-cells = <0>;
|
||||
#interrupt-cells = <1>;
|
||||
};
|
||||
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
reg = <0>;
|
||||
port@0 {
|
||||
reg = <0>;
|
||||
label = "swp0";
|
||||
phy-handle = <ðphy0>;
|
||||
};
|
||||
port@1 {
|
||||
reg = <1>;
|
||||
label = "swp1";
|
||||
phy-handle = <ðphy1>;
|
||||
};
|
||||
port@2 {
|
||||
reg = <2>;
|
||||
label = "swp2";
|
||||
phy-handle = <ðphy2>;
|
||||
};
|
||||
port@3 {
|
||||
reg = <3>;
|
||||
label = "swp3";
|
||||
phy-handle = <ðphy3>;
|
||||
};
|
||||
port@6 {
|
||||
reg = <6>;
|
||||
label = "cpu";
|
||||
ethernet = <&fec1>;
|
||||
phy-mode = "rgmii";
|
||||
tx-internal-delay-ps = <2000>;
|
||||
rx-internal-delay-ps = <2000>;
|
||||
|
||||
fixed-link {
|
||||
speed = <1000>;
|
||||
full-duplex;
|
||||
pause;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
mdio {
|
||||
compatible = "realtek,smi-mdio";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
ethphy0: phy@0 {
|
||||
reg = <0>;
|
||||
interrupt-parent = <&switch_intc>;
|
||||
interrupts = <0>;
|
||||
};
|
||||
ethphy1: phy@1 {
|
||||
reg = <1>;
|
||||
interrupt-parent = <&switch_intc>;
|
||||
interrupts = <1>;
|
||||
};
|
||||
ethphy2: phy@2 {
|
||||
reg = <2>;
|
||||
interrupt-parent = <&switch_intc>;
|
||||
interrupts = <2>;
|
||||
};
|
||||
ethphy3: phy@3 {
|
||||
reg = <3>;
|
||||
interrupt-parent = <&switch_intc>;
|
||||
interrupts = <3>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
@ -70,6 +70,7 @@ config NET_DSA_QCA8K
|
||||
config NET_DSA_REALTEK_SMI
|
||||
tristate "Realtek SMI Ethernet switch family support"
|
||||
select NET_DSA_TAG_RTL4_A
|
||||
select NET_DSA_TAG_RTL8_4
|
||||
select FIXED_PHY
|
||||
select IRQ_DOMAIN
|
||||
select REALTEK_PHY
|
||||
|
@ -10,7 +10,7 @@ obj-$(CONFIG_NET_DSA_MT7530) += mt7530.o
|
||||
obj-$(CONFIG_NET_DSA_MV88E6060) += mv88e6060.o
|
||||
obj-$(CONFIG_NET_DSA_QCA8K) += qca8k.o
|
||||
obj-$(CONFIG_NET_DSA_REALTEK_SMI) += realtek-smi.o
|
||||
realtek-smi-objs := realtek-smi-core.o rtl8366.o rtl8366rb.o
|
||||
realtek-smi-objs := realtek-smi-core.o rtl8366.o rtl8366rb.o rtl8365mb.o
|
||||
obj-$(CONFIG_NET_DSA_SMSC_LAN9303) += lan9303-core.o
|
||||
obj-$(CONFIG_NET_DSA_SMSC_LAN9303_I2C) += lan9303_i2c.o
|
||||
obj-$(CONFIG_NET_DSA_SMSC_LAN9303_MDIO) += lan9303_mdio.o
|
||||
|
@ -501,6 +501,10 @@ static const struct of_device_id realtek_smi_of_match[] = {
|
||||
.compatible = "realtek,rtl8366s",
|
||||
.data = NULL,
|
||||
},
|
||||
{
|
||||
.compatible = "realtek,rtl8365mb",
|
||||
.data = &rtl8365mb_variant,
|
||||
},
|
||||
{ /* sentinel */ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, realtek_smi_of_match);
|
||||
|
@ -140,5 +140,6 @@ int rtl8366_get_sset_count(struct dsa_switch *ds, int port, int sset);
|
||||
void rtl8366_get_ethtool_stats(struct dsa_switch *ds, int port, uint64_t *data);
|
||||
|
||||
extern const struct realtek_smi_variant rtl8366rb_variant;
|
||||
extern const struct realtek_smi_variant rtl8365mb_variant;
|
||||
|
||||
#endif /* _REALTEK_SMI_H */
|
||||
|
1982
drivers/net/dsa/rtl8365mb.c
Normal file
1982
drivers/net/dsa/rtl8365mb.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -1023,6 +1023,14 @@ static struct phy_driver realtek_drvs[] = {
|
||||
.resume = genphy_resume,
|
||||
.read_page = rtl821x_read_page,
|
||||
.write_page = rtl821x_write_page,
|
||||
}, {
|
||||
PHY_ID_MATCH_EXACT(0x001cc942),
|
||||
.name = "RTL8365MB-VC Gigabit Ethernet",
|
||||
/* Interrupt handling analogous to RTL8366RB */
|
||||
.config_intr = genphy_no_config_intr,
|
||||
.handle_interrupt = genphy_handle_interrupt_no_ack,
|
||||
.suspend = genphy_suspend,
|
||||
.resume = genphy_resume,
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -51,6 +51,7 @@ struct phylink_link_state;
|
||||
#define DSA_TAG_PROTO_SEVILLE_VALUE 21
|
||||
#define DSA_TAG_PROTO_BRCM_LEGACY_VALUE 22
|
||||
#define DSA_TAG_PROTO_SJA1110_VALUE 23
|
||||
#define DSA_TAG_PROTO_RTL8_4_VALUE 24
|
||||
|
||||
enum dsa_tag_protocol {
|
||||
DSA_TAG_PROTO_NONE = DSA_TAG_PROTO_NONE_VALUE,
|
||||
@ -77,6 +78,7 @@ enum dsa_tag_protocol {
|
||||
DSA_TAG_PROTO_OCELOT_8021Q = DSA_TAG_PROTO_OCELOT_8021Q_VALUE,
|
||||
DSA_TAG_PROTO_SEVILLE = DSA_TAG_PROTO_SEVILLE_VALUE,
|
||||
DSA_TAG_PROTO_SJA1110 = DSA_TAG_PROTO_SJA1110_VALUE,
|
||||
DSA_TAG_PROTO_RTL8_4 = DSA_TAG_PROTO_RTL8_4_VALUE,
|
||||
};
|
||||
|
||||
struct dsa_switch;
|
||||
@ -645,6 +647,12 @@ struct dsa_switch_ops {
|
||||
int (*get_sset_count)(struct dsa_switch *ds, int port, int sset);
|
||||
void (*get_ethtool_phy_stats)(struct dsa_switch *ds,
|
||||
int port, uint64_t *data);
|
||||
void (*get_eth_phy_stats)(struct dsa_switch *ds, int port,
|
||||
struct ethtool_eth_phy_stats *phy_stats);
|
||||
void (*get_eth_mac_stats)(struct dsa_switch *ds, int port,
|
||||
struct ethtool_eth_mac_stats *mac_stats);
|
||||
void (*get_eth_ctrl_stats)(struct dsa_switch *ds, int port,
|
||||
struct ethtool_eth_ctrl_stats *ctrl_stats);
|
||||
void (*get_stats64)(struct dsa_switch *ds, int port,
|
||||
struct rtnl_link_stats64 *s);
|
||||
void (*self_test)(struct dsa_switch *ds, int port,
|
||||
|
@ -86,6 +86,7 @@
|
||||
* over Ethernet
|
||||
*/
|
||||
#define ETH_P_PAE 0x888E /* Port Access Entity (IEEE 802.1X) */
|
||||
#define ETH_P_REALTEK 0x8899 /* Multiple proprietary protocols */
|
||||
#define ETH_P_AOE 0x88A2 /* ATA over Ethernet */
|
||||
#define ETH_P_8021AD 0x88A8 /* 802.1ad Service VLAN */
|
||||
#define ETH_P_802_EX1 0x88B5 /* 802.1 Local Experimental 1. */
|
||||
|
@ -92,13 +92,6 @@ config NET_DSA_TAG_KSZ
|
||||
Say Y if you want to enable support for tagging frames for the
|
||||
Microchip 8795/9477/9893 families of switches.
|
||||
|
||||
config NET_DSA_TAG_RTL4_A
|
||||
tristate "Tag driver for Realtek 4 byte protocol A tags"
|
||||
help
|
||||
Say Y or M if you want to enable support for tagging frames for the
|
||||
Realtek switches with 4 byte protocol A tags, sich as found in
|
||||
the Realtek RTL8366RB.
|
||||
|
||||
config NET_DSA_TAG_OCELOT
|
||||
tristate "Tag driver for Ocelot family of switches, using NPI port"
|
||||
select PACKING
|
||||
@ -126,6 +119,19 @@ config NET_DSA_TAG_QCA
|
||||
Say Y or M if you want to enable support for tagging frames for
|
||||
the Qualcomm Atheros QCA8K switches.
|
||||
|
||||
config NET_DSA_TAG_RTL4_A
|
||||
tristate "Tag driver for Realtek 4 byte protocol A tags"
|
||||
help
|
||||
Say Y or M if you want to enable support for tagging frames for the
|
||||
Realtek switches with 4 byte protocol A tags, sich as found in
|
||||
the Realtek RTL8366RB.
|
||||
|
||||
config NET_DSA_TAG_RTL8_4
|
||||
tristate "Tag driver for Realtek 8 byte protocol 4 tags"
|
||||
help
|
||||
Say Y or M if you want to enable support for tagging frames for Realtek
|
||||
switches with 8 byte protocol 4 tags, such as the Realtek RTL8365MB-VC.
|
||||
|
||||
config NET_DSA_TAG_LAN9303
|
||||
tristate "Tag driver for SMSC/Microchip LAN9303 family of switches"
|
||||
help
|
||||
|
@ -10,12 +10,13 @@ obj-$(CONFIG_NET_DSA_TAG_DSA_COMMON) += tag_dsa.o
|
||||
obj-$(CONFIG_NET_DSA_TAG_GSWIP) += tag_gswip.o
|
||||
obj-$(CONFIG_NET_DSA_TAG_HELLCREEK) += tag_hellcreek.o
|
||||
obj-$(CONFIG_NET_DSA_TAG_KSZ) += tag_ksz.o
|
||||
obj-$(CONFIG_NET_DSA_TAG_RTL4_A) += tag_rtl4_a.o
|
||||
obj-$(CONFIG_NET_DSA_TAG_LAN9303) += tag_lan9303.o
|
||||
obj-$(CONFIG_NET_DSA_TAG_MTK) += tag_mtk.o
|
||||
obj-$(CONFIG_NET_DSA_TAG_OCELOT) += tag_ocelot.o
|
||||
obj-$(CONFIG_NET_DSA_TAG_OCELOT_8021Q) += tag_ocelot_8021q.o
|
||||
obj-$(CONFIG_NET_DSA_TAG_QCA) += tag_qca.o
|
||||
obj-$(CONFIG_NET_DSA_TAG_RTL4_A) += tag_rtl4_a.o
|
||||
obj-$(CONFIG_NET_DSA_TAG_RTL8_4) += tag_rtl8_4.o
|
||||
obj-$(CONFIG_NET_DSA_TAG_SJA1105) += tag_sja1105.o
|
||||
obj-$(CONFIG_NET_DSA_TAG_TRAILER) += tag_trailer.o
|
||||
obj-$(CONFIG_NET_DSA_TAG_XRS700X) += tag_xrs700x.o
|
||||
|
@ -789,6 +789,37 @@ static int dsa_slave_get_sset_count(struct net_device *dev, int sset)
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static void dsa_slave_get_eth_phy_stats(struct net_device *dev,
|
||||
struct ethtool_eth_phy_stats *phy_stats)
|
||||
{
|
||||
struct dsa_port *dp = dsa_slave_to_port(dev);
|
||||
struct dsa_switch *ds = dp->ds;
|
||||
|
||||
if (ds->ops->get_eth_phy_stats)
|
||||
ds->ops->get_eth_phy_stats(ds, dp->index, phy_stats);
|
||||
}
|
||||
|
||||
static void dsa_slave_get_eth_mac_stats(struct net_device *dev,
|
||||
struct ethtool_eth_mac_stats *mac_stats)
|
||||
{
|
||||
struct dsa_port *dp = dsa_slave_to_port(dev);
|
||||
struct dsa_switch *ds = dp->ds;
|
||||
|
||||
if (ds->ops->get_eth_mac_stats)
|
||||
ds->ops->get_eth_mac_stats(ds, dp->index, mac_stats);
|
||||
}
|
||||
|
||||
static void
|
||||
dsa_slave_get_eth_ctrl_stats(struct net_device *dev,
|
||||
struct ethtool_eth_ctrl_stats *ctrl_stats)
|
||||
{
|
||||
struct dsa_port *dp = dsa_slave_to_port(dev);
|
||||
struct dsa_switch *ds = dp->ds;
|
||||
|
||||
if (ds->ops->get_eth_ctrl_stats)
|
||||
ds->ops->get_eth_ctrl_stats(ds, dp->index, ctrl_stats);
|
||||
}
|
||||
|
||||
static void dsa_slave_net_selftest(struct net_device *ndev,
|
||||
struct ethtool_test *etest, u64 *buf)
|
||||
{
|
||||
@ -1695,6 +1726,9 @@ static const struct ethtool_ops dsa_slave_ethtool_ops = {
|
||||
.get_strings = dsa_slave_get_strings,
|
||||
.get_ethtool_stats = dsa_slave_get_ethtool_stats,
|
||||
.get_sset_count = dsa_slave_get_sset_count,
|
||||
.get_eth_phy_stats = dsa_slave_get_eth_phy_stats,
|
||||
.get_eth_mac_stats = dsa_slave_get_eth_mac_stats,
|
||||
.get_eth_ctrl_stats = dsa_slave_get_eth_ctrl_stats,
|
||||
.set_wol = dsa_slave_set_wol,
|
||||
.get_wol = dsa_slave_get_wol,
|
||||
.set_eee = dsa_slave_set_eee,
|
||||
|
178
net/dsa/tag_rtl8_4.c
Normal file
178
net/dsa/tag_rtl8_4.c
Normal file
@ -0,0 +1,178 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Handler for Realtek 8 byte switch tags
|
||||
*
|
||||
* Copyright (C) 2021 Alvin Šipraga <alsi@bang-olufsen.dk>
|
||||
*
|
||||
* NOTE: Currently only supports protocol "4" found in the RTL8365MB, hence
|
||||
* named tag_rtl8_4.
|
||||
*
|
||||
* This tag header has the following format:
|
||||
*
|
||||
* -------------------------------------------
|
||||
* | MAC DA | MAC SA | 8 byte tag | Type | ...
|
||||
* -------------------------------------------
|
||||
* _______________/ \______________________________________
|
||||
* / \
|
||||
* 0 7|8 15
|
||||
* |-----------------------------------+-----------------------------------|---
|
||||
* | (16-bit) | ^
|
||||
* | Realtek EtherType [0x8899] | |
|
||||
* |-----------------------------------+-----------------------------------| 8
|
||||
* | (8-bit) | (8-bit) |
|
||||
* | Protocol [0x04] | REASON | b
|
||||
* |-----------------------------------+-----------------------------------| y
|
||||
* | (1) | (1) | (2) | (1) | (3) | (1) | (1) | (1) | (5) | t
|
||||
* | FID_EN | X | FID | PRI_EN | PRI | KEEP | X | LEARN_DIS | X | e
|
||||
* |-----------------------------------+-----------------------------------| s
|
||||
* | (1) | (15-bit) | |
|
||||
* | ALLOW | TX/RX | v
|
||||
* |-----------------------------------+-----------------------------------|---
|
||||
*
|
||||
* With the following field descriptions:
|
||||
*
|
||||
* field | description
|
||||
* ------------+-------------
|
||||
* Realtek | 0x8899: indicates that this is a proprietary Realtek tag;
|
||||
* EtherType | note that Realtek uses the same EtherType for
|
||||
* | other incompatible tag formats (e.g. tag_rtl4_a.c)
|
||||
* Protocol | 0x04: indicates that this tag conforms to this format
|
||||
* X | reserved
|
||||
* ------------+-------------
|
||||
* REASON | reason for forwarding packet to CPU
|
||||
* | 0: packet was forwarded or flooded to CPU
|
||||
* | 80: packet was trapped to CPU
|
||||
* FID_EN | 1: packet has an FID
|
||||
* | 0: no FID
|
||||
* FID | FID of packet (if FID_EN=1)
|
||||
* PRI_EN | 1: force priority of packet
|
||||
* | 0: don't force priority
|
||||
* PRI | priority of packet (if PRI_EN=1)
|
||||
* KEEP | preserve packet VLAN tag format
|
||||
* LEARN_DIS | don't learn the source MAC address of the packet
|
||||
* ALLOW | 1: treat TX/RX field as an allowance port mask, meaning the
|
||||
* | packet may only be forwarded to ports specified in the
|
||||
* | mask
|
||||
* | 0: no allowance port mask, TX/RX field is the forwarding
|
||||
* | port mask
|
||||
* TX/RX | TX (switch->CPU): port number the packet was received on
|
||||
* | RX (CPU->switch): forwarding port mask (if ALLOW=0)
|
||||
* | allowance port mask (if ALLOW=1)
|
||||
*/
|
||||
|
||||
#include <linux/bitfield.h>
|
||||
#include <linux/bits.h>
|
||||
#include <linux/etherdevice.h>
|
||||
|
||||
#include "dsa_priv.h"
|
||||
|
||||
/* Protocols supported:
|
||||
*
|
||||
* 0x04 = RTL8365MB DSA protocol
|
||||
*/
|
||||
|
||||
#define RTL8_4_TAG_LEN 8
|
||||
|
||||
#define RTL8_4_PROTOCOL GENMASK(15, 8)
|
||||
#define RTL8_4_PROTOCOL_RTL8365MB 0x04
|
||||
#define RTL8_4_REASON GENMASK(7, 0)
|
||||
#define RTL8_4_REASON_FORWARD 0
|
||||
#define RTL8_4_REASON_TRAP 80
|
||||
|
||||
#define RTL8_4_LEARN_DIS BIT(5)
|
||||
|
||||
#define RTL8_4_TX GENMASK(3, 0)
|
||||
#define RTL8_4_RX GENMASK(10, 0)
|
||||
|
||||
static struct sk_buff *rtl8_4_tag_xmit(struct sk_buff *skb,
|
||||
struct net_device *dev)
|
||||
{
|
||||
struct dsa_port *dp = dsa_slave_to_port(dev);
|
||||
__be16 *tag;
|
||||
|
||||
skb_push(skb, RTL8_4_TAG_LEN);
|
||||
|
||||
dsa_alloc_etype_header(skb, RTL8_4_TAG_LEN);
|
||||
tag = dsa_etype_header_pos_tx(skb);
|
||||
|
||||
/* Set Realtek EtherType */
|
||||
tag[0] = htons(ETH_P_REALTEK);
|
||||
|
||||
/* Set Protocol; zero REASON */
|
||||
tag[1] = htons(FIELD_PREP(RTL8_4_PROTOCOL, RTL8_4_PROTOCOL_RTL8365MB));
|
||||
|
||||
/* Zero FID_EN, FID, PRI_EN, PRI, KEEP; set LEARN_DIS */
|
||||
tag[2] = htons(FIELD_PREP(RTL8_4_LEARN_DIS, 1));
|
||||
|
||||
/* Zero ALLOW; set RX (CPU->switch) forwarding port mask */
|
||||
tag[3] = htons(FIELD_PREP(RTL8_4_RX, BIT(dp->index)));
|
||||
|
||||
return skb;
|
||||
}
|
||||
|
||||
static struct sk_buff *rtl8_4_tag_rcv(struct sk_buff *skb,
|
||||
struct net_device *dev)
|
||||
{
|
||||
__be16 *tag;
|
||||
u16 etype;
|
||||
u8 reason;
|
||||
u8 proto;
|
||||
u8 port;
|
||||
|
||||
if (unlikely(!pskb_may_pull(skb, RTL8_4_TAG_LEN)))
|
||||
return NULL;
|
||||
|
||||
tag = dsa_etype_header_pos_rx(skb);
|
||||
|
||||
/* Parse Realtek EtherType */
|
||||
etype = ntohs(tag[0]);
|
||||
if (unlikely(etype != ETH_P_REALTEK)) {
|
||||
dev_warn_ratelimited(&dev->dev,
|
||||
"non-realtek ethertype 0x%04x\n", etype);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Parse Protocol */
|
||||
proto = FIELD_GET(RTL8_4_PROTOCOL, ntohs(tag[1]));
|
||||
if (unlikely(proto != RTL8_4_PROTOCOL_RTL8365MB)) {
|
||||
dev_warn_ratelimited(&dev->dev,
|
||||
"unknown realtek protocol 0x%02x\n",
|
||||
proto);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Parse REASON */
|
||||
reason = FIELD_GET(RTL8_4_REASON, ntohs(tag[1]));
|
||||
|
||||
/* Parse TX (switch->CPU) */
|
||||
port = FIELD_GET(RTL8_4_TX, ntohs(tag[3]));
|
||||
skb->dev = dsa_master_find_slave(dev, 0, port);
|
||||
if (!skb->dev) {
|
||||
dev_warn_ratelimited(&dev->dev,
|
||||
"could not find slave for port %d\n",
|
||||
port);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Remove tag and recalculate checksum */
|
||||
skb_pull_rcsum(skb, RTL8_4_TAG_LEN);
|
||||
|
||||
dsa_strip_etype_header(skb, RTL8_4_TAG_LEN);
|
||||
|
||||
if (reason != RTL8_4_REASON_TRAP)
|
||||
dsa_default_offload_fwd_mark(skb);
|
||||
|
||||
return skb;
|
||||
}
|
||||
|
||||
static const struct dsa_device_ops rtl8_4_netdev_ops = {
|
||||
.name = "rtl8_4",
|
||||
.proto = DSA_TAG_PROTO_RTL8_4,
|
||||
.xmit = rtl8_4_tag_xmit,
|
||||
.rcv = rtl8_4_tag_rcv,
|
||||
.needed_headroom = RTL8_4_TAG_LEN,
|
||||
};
|
||||
module_dsa_tag_driver(rtl8_4_netdev_ops);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_ALIAS_DSA_TAG_DRIVER(DSA_TAG_PROTO_RTL8_4);
|
Loading…
Reference in New Issue
Block a user