Merge Official Source
Signed-off-by: Tianling Shen <cnsztl@immortalwrt.org>
This commit is contained in:
commit
3ef187c32f
@ -49,6 +49,7 @@ zbtlink,zbt-wg2626|\
|
||||
zte,mf283plus)
|
||||
ubootenv_add_uci_config "/dev/mtd1" "0x0" "0x1000" "0x10000"
|
||||
;;
|
||||
asus,rt-ax53u|\
|
||||
belkin,rt1800|\
|
||||
h3c,tx1800-plus|\
|
||||
h3c,tx1801-plus|\
|
||||
|
||||
@ -8,12 +8,12 @@
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=linux-firmware
|
||||
PKG_VERSION:=20221109
|
||||
PKG_RELEASE:=5
|
||||
PKG_VERSION:=20221214
|
||||
PKG_RELEASE:=2
|
||||
|
||||
PKG_SOURCE_URL:=@KERNEL/linux/kernel/firmware
|
||||
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz
|
||||
PKG_HASH:=c0ddffbbcf30f2e015bddd5c6d3ce1f13976b906aceabda4a57e3c41a3190701
|
||||
PKG_HASH:=e793783e92acbde549965521462d1d1327827360664cf242dbda08f075654331
|
||||
|
||||
PKG_MAINTAINER:=Felix Fietkau <nbd@nbd.name>
|
||||
|
||||
|
||||
@ -19,5 +19,6 @@ define Package/ath11k-firmware-wcn6855/install
|
||||
$(INSTALL_DIR) $(1)/lib/firmware/ath11k/WCN6855/hw2.0
|
||||
$(INSTALL_DATA) \
|
||||
$(PKG_BUILD_DIR)/ath11k/WCN6855/hw2.0/* $(1)/lib/firmware/ath11k/WCN6855/hw2.0/
|
||||
$(LN) ./hw2.0 $(1)/lib/firmware/ath11k/WCN6855/hw2.1
|
||||
endef
|
||||
$(eval $(call BuildPackage,ath11k-firmware-wcn6855))
|
||||
|
||||
@ -0,0 +1,298 @@
|
||||
--- a/src/radius/radius_das.h
|
||||
+++ b/src/radius/radius_das.h
|
||||
@@ -44,6 +44,7 @@ struct radius_das_attrs {
|
||||
struct radius_das_conf {
|
||||
int port;
|
||||
const u8 *shared_secret;
|
||||
+ const u8 *nas_identifier;
|
||||
size_t shared_secret_len;
|
||||
const struct hostapd_ip_addr *client_addr;
|
||||
unsigned int time_window;
|
||||
--- a/src/ap/hostapd.c
|
||||
+++ b/src/ap/hostapd.c
|
||||
@@ -1367,6 +1367,7 @@ static int hostapd_setup_bss(struct host
|
||||
struct radius_das_conf das_conf;
|
||||
os_memset(&das_conf, 0, sizeof(das_conf));
|
||||
das_conf.port = conf->radius_das_port;
|
||||
+ das_conf.nas_identifier = conf->nas_identifier;
|
||||
das_conf.shared_secret = conf->radius_das_shared_secret;
|
||||
das_conf.shared_secret_len =
|
||||
conf->radius_das_shared_secret_len;
|
||||
--- a/src/radius/radius_das.c
|
||||
+++ b/src/radius/radius_das.c
|
||||
@@ -12,13 +12,26 @@
|
||||
#include "utils/common.h"
|
||||
#include "utils/eloop.h"
|
||||
#include "utils/ip_addr.h"
|
||||
+#include "utils/list.h"
|
||||
#include "radius.h"
|
||||
#include "radius_das.h"
|
||||
|
||||
|
||||
-struct radius_das_data {
|
||||
+static struct dl_list das_ports = DL_LIST_HEAD_INIT(das_ports);
|
||||
+
|
||||
+struct radius_das_port {
|
||||
+ struct dl_list list;
|
||||
+ struct dl_list das_data;
|
||||
+
|
||||
+ int port;
|
||||
int sock;
|
||||
+};
|
||||
+
|
||||
+struct radius_das_data {
|
||||
+ struct dl_list list;
|
||||
+ struct radius_das_port *port;
|
||||
u8 *shared_secret;
|
||||
+ u8 *nas_identifier;
|
||||
size_t shared_secret_len;
|
||||
struct hostapd_ip_addr client_addr;
|
||||
unsigned int time_window;
|
||||
@@ -378,56 +391,17 @@ fail:
|
||||
}
|
||||
|
||||
|
||||
-static void radius_das_receive(int sock, void *eloop_ctx, void *sock_ctx)
|
||||
+static void
|
||||
+radius_das_receive_msg(struct radius_das_data *das, struct radius_msg *msg,
|
||||
+ struct sockaddr *from, socklen_t fromlen,
|
||||
+ char *abuf, int from_port)
|
||||
{
|
||||
- struct radius_das_data *das = eloop_ctx;
|
||||
- u8 buf[1500];
|
||||
- union {
|
||||
- struct sockaddr_storage ss;
|
||||
- struct sockaddr_in sin;
|
||||
-#ifdef CONFIG_IPV6
|
||||
- struct sockaddr_in6 sin6;
|
||||
-#endif /* CONFIG_IPV6 */
|
||||
- } from;
|
||||
- char abuf[50];
|
||||
- int from_port = 0;
|
||||
- socklen_t fromlen;
|
||||
- int len;
|
||||
- struct radius_msg *msg, *reply = NULL;
|
||||
+ struct radius_msg *reply = NULL;
|
||||
struct radius_hdr *hdr;
|
||||
struct wpabuf *rbuf;
|
||||
+ struct os_time now;
|
||||
u32 val;
|
||||
int res;
|
||||
- struct os_time now;
|
||||
-
|
||||
- fromlen = sizeof(from);
|
||||
- len = recvfrom(sock, buf, sizeof(buf), 0,
|
||||
- (struct sockaddr *) &from.ss, &fromlen);
|
||||
- if (len < 0) {
|
||||
- wpa_printf(MSG_ERROR, "DAS: recvfrom: %s", strerror(errno));
|
||||
- return;
|
||||
- }
|
||||
-
|
||||
- os_strlcpy(abuf, inet_ntoa(from.sin.sin_addr), sizeof(abuf));
|
||||
- from_port = ntohs(from.sin.sin_port);
|
||||
-
|
||||
- wpa_printf(MSG_DEBUG, "DAS: Received %d bytes from %s:%d",
|
||||
- len, abuf, from_port);
|
||||
- if (das->client_addr.u.v4.s_addr &&
|
||||
- das->client_addr.u.v4.s_addr != from.sin.sin_addr.s_addr) {
|
||||
- wpa_printf(MSG_DEBUG, "DAS: Drop message from unknown client");
|
||||
- return;
|
||||
- }
|
||||
-
|
||||
- msg = radius_msg_parse(buf, len);
|
||||
- if (msg == NULL) {
|
||||
- wpa_printf(MSG_DEBUG, "DAS: Parsing incoming RADIUS packet "
|
||||
- "from %s:%d failed", abuf, from_port);
|
||||
- return;
|
||||
- }
|
||||
-
|
||||
- if (wpa_debug_level <= MSG_MSGDUMP)
|
||||
- radius_msg_dump(msg);
|
||||
|
||||
if (radius_msg_verify_das_req(msg, das->shared_secret,
|
||||
das->shared_secret_len,
|
||||
@@ -494,9 +468,8 @@ static void radius_das_receive(int sock,
|
||||
radius_msg_dump(reply);
|
||||
|
||||
rbuf = radius_msg_get_buf(reply);
|
||||
- res = sendto(das->sock, wpabuf_head(rbuf),
|
||||
- wpabuf_len(rbuf), 0,
|
||||
- (struct sockaddr *) &from.ss, fromlen);
|
||||
+ res = sendto(das->port->sock, wpabuf_head(rbuf),
|
||||
+ wpabuf_len(rbuf), 0, from, fromlen);
|
||||
if (res < 0) {
|
||||
wpa_printf(MSG_ERROR, "DAS: sendto(to %s:%d): %s",
|
||||
abuf, from_port, strerror(errno));
|
||||
@@ -508,6 +481,72 @@ fail:
|
||||
radius_msg_free(reply);
|
||||
}
|
||||
|
||||
+static void radius_das_receive(int sock, void *eloop_ctx, void *sock_ctx)
|
||||
+{
|
||||
+ struct radius_das_port *p = eloop_ctx;
|
||||
+ struct radius_das_data *das;
|
||||
+ u8 buf[1500];
|
||||
+ union {
|
||||
+ struct sockaddr_storage ss;
|
||||
+ struct sockaddr_in sin;
|
||||
+#ifdef CONFIG_IPV6
|
||||
+ struct sockaddr_in6 sin6;
|
||||
+#endif /* CONFIG_IPV6 */
|
||||
+ } from;
|
||||
+ struct radius_msg *msg;
|
||||
+ size_t nasid_len = 0;
|
||||
+ u8 *nasid_buf = NULL;
|
||||
+ char abuf[50];
|
||||
+ int from_port = 0;
|
||||
+ socklen_t fromlen;
|
||||
+ int found = 0;
|
||||
+ int len;
|
||||
+
|
||||
+ fromlen = sizeof(from);
|
||||
+ len = recvfrom(sock, buf, sizeof(buf), 0,
|
||||
+ (struct sockaddr *) &from.ss, &fromlen);
|
||||
+ if (len < 0) {
|
||||
+ wpa_printf(MSG_ERROR, "DAS: recvfrom: %s", strerror(errno));
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ os_strlcpy(abuf, inet_ntoa(from.sin.sin_addr), sizeof(abuf));
|
||||
+ from_port = ntohs(from.sin.sin_port);
|
||||
+
|
||||
+ msg = radius_msg_parse(buf, len);
|
||||
+ if (msg == NULL) {
|
||||
+ wpa_printf(MSG_DEBUG, "DAS: Parsing incoming RADIUS packet "
|
||||
+ "from %s:%d failed", abuf, from_port);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ wpa_printf(MSG_DEBUG, "DAS: Received %d bytes from %s:%d",
|
||||
+ len, abuf, from_port);
|
||||
+
|
||||
+ if (wpa_debug_level <= MSG_MSGDUMP)
|
||||
+ radius_msg_dump(msg);
|
||||
+
|
||||
+ radius_msg_get_attr_ptr(msg, RADIUS_ATTR_NAS_IDENTIFIER,
|
||||
+ &nasid_buf, &nasid_len, NULL);
|
||||
+ dl_list_for_each(das, &p->das_data, struct radius_das_data, list) {
|
||||
+ if (das->client_addr.u.v4.s_addr &&
|
||||
+ das->client_addr.u.v4.s_addr != from.sin.sin_addr.s_addr)
|
||||
+ continue;
|
||||
+
|
||||
+ if (das->nas_identifier && nasid_buf &&
|
||||
+ (nasid_len != os_strlen(das->nas_identifier) ||
|
||||
+ os_memcmp(das->nas_identifier, nasid_buf, nasid_len) != 0))
|
||||
+ continue;
|
||||
+
|
||||
+ found = 1;
|
||||
+ radius_das_receive_msg(das, msg, (struct sockaddr *)&from.ss,
|
||||
+ fromlen, abuf, from_port);
|
||||
+ }
|
||||
+
|
||||
+ if (!found)
|
||||
+ wpa_printf(MSG_DEBUG, "DAS: Drop message from unknown client");
|
||||
+}
|
||||
+
|
||||
|
||||
static int radius_das_open_socket(int port)
|
||||
{
|
||||
@@ -533,6 +572,49 @@ static int radius_das_open_socket(int po
|
||||
}
|
||||
|
||||
|
||||
+static struct radius_das_port *
|
||||
+radius_das_open_port(int port)
|
||||
+{
|
||||
+ struct radius_das_port *p;
|
||||
+
|
||||
+ dl_list_for_each(p, &das_ports, struct radius_das_port, list) {
|
||||
+ if (p->port == port)
|
||||
+ return p;
|
||||
+ }
|
||||
+
|
||||
+ p = os_zalloc(sizeof(*p));
|
||||
+ if (p == NULL)
|
||||
+ return NULL;
|
||||
+
|
||||
+ dl_list_init(&p->das_data);
|
||||
+ p->port = port;
|
||||
+ p->sock = radius_das_open_socket(port);
|
||||
+ if (p->sock < 0)
|
||||
+ goto free_port;
|
||||
+
|
||||
+ if (eloop_register_read_sock(p->sock, radius_das_receive, p, NULL))
|
||||
+ goto close_port;
|
||||
+
|
||||
+ dl_list_add(&das_ports, &p->list);
|
||||
+
|
||||
+ return p;
|
||||
+
|
||||
+close_port:
|
||||
+ close(p->sock);
|
||||
+free_port:
|
||||
+ os_free(p);
|
||||
+
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
+static void radius_das_close_port(struct radius_das_port *p)
|
||||
+{
|
||||
+ dl_list_del(&p->list);
|
||||
+ eloop_unregister_read_sock(p->sock);
|
||||
+ close(p->sock);
|
||||
+ free(p);
|
||||
+}
|
||||
+
|
||||
struct radius_das_data *
|
||||
radius_das_init(struct radius_das_conf *conf)
|
||||
{
|
||||
@@ -553,6 +635,8 @@ radius_das_init(struct radius_das_conf *
|
||||
das->ctx = conf->ctx;
|
||||
das->disconnect = conf->disconnect;
|
||||
das->coa = conf->coa;
|
||||
+ if (conf->nas_identifier)
|
||||
+ das->nas_identifier = os_strdup(conf->nas_identifier);
|
||||
|
||||
os_memcpy(&das->client_addr, conf->client_addr,
|
||||
sizeof(das->client_addr));
|
||||
@@ -565,19 +649,15 @@ radius_das_init(struct radius_das_conf *
|
||||
}
|
||||
das->shared_secret_len = conf->shared_secret_len;
|
||||
|
||||
- das->sock = radius_das_open_socket(conf->port);
|
||||
- if (das->sock < 0) {
|
||||
+ das->port = radius_das_open_port(conf->port);
|
||||
+ if (!das->port) {
|
||||
wpa_printf(MSG_ERROR, "Failed to open UDP socket for RADIUS "
|
||||
"DAS");
|
||||
radius_das_deinit(das);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
- if (eloop_register_read_sock(das->sock, radius_das_receive, das, NULL))
|
||||
- {
|
||||
- radius_das_deinit(das);
|
||||
- return NULL;
|
||||
- }
|
||||
+ dl_list_add(&das->port->das_data, &das->list);
|
||||
|
||||
return das;
|
||||
}
|
||||
@@ -588,11 +668,14 @@ void radius_das_deinit(struct radius_das
|
||||
if (das == NULL)
|
||||
return;
|
||||
|
||||
- if (das->sock >= 0) {
|
||||
- eloop_unregister_read_sock(das->sock);
|
||||
- close(das->sock);
|
||||
+ if (das->port) {
|
||||
+ dl_list_del(&das->list);
|
||||
+
|
||||
+ if (dl_list_empty(&das->port->das_data))
|
||||
+ radius_das_close_port(das->port);
|
||||
}
|
||||
|
||||
+ os_free(das->nas_identifier);
|
||||
os_free(das->shared_secret);
|
||||
os_free(das);
|
||||
}
|
||||
@ -86,7 +86,8 @@ case "$FIRMWARE" in
|
||||
avm,fritz300e)
|
||||
caldata_extract_reverse "urloader" 0x1541 0x440
|
||||
;;
|
||||
buffalo,wzr-hp-g450h)
|
||||
buffalo,wzr-hp-g450h|\
|
||||
pcs,cap324)
|
||||
caldata_extract "art" 0x1000 0x440
|
||||
;;
|
||||
dlink,dir-825-c1|\
|
||||
@ -103,9 +104,8 @@ case "$FIRMWARE" in
|
||||
;;
|
||||
netgear,wnr2200-8m|\
|
||||
netgear,wnr2200-16m|\
|
||||
pcs,cap324|\
|
||||
tplink,tl-wr842n-v1)
|
||||
caldata_extract "art" 0x1000 0x1000
|
||||
caldata_extract "art" 0x1000 0x3e0
|
||||
;;
|
||||
wd,mynet-n600|\
|
||||
wd,mynet-n750)
|
||||
@ -113,7 +113,7 @@ case "$FIRMWARE" in
|
||||
ath9k_patch_mac $(mtd_get_mac_ascii devdata "wlan5mac")
|
||||
;;
|
||||
wd,mynet-wifi-rangeextender)
|
||||
caldata_extract "art" 0x1000 0x1000
|
||||
caldata_extract "art" 0x1000 0x440
|
||||
ath9k_patch_mac $(nvram get wl0_hwaddr)
|
||||
;;
|
||||
*)
|
||||
|
||||
@ -0,0 +1,31 @@
|
||||
From 882882912cd25a637ba0cf09932ad248f584e680 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= <noltari@gmail.com>
|
||||
Date: Wed, 28 Dec 2022 13:19:49 +0100
|
||||
Subject: [PATCH 1/2] Revert "net: broadcom: Add PTP_1588_CLOCK_OPTIONAL
|
||||
dependency for BCMGENET under ARCH_BCM2835"
|
||||
|
||||
[ Upstream commit 421f8663b3a775c32f724f793264097c60028f2e ]
|
||||
|
||||
This reverts commit eb96fd3983b2cca1c90db45eaff1de67b94f9950.
|
||||
---
|
||||
drivers/net/ethernet/broadcom/Kconfig | 3 +--
|
||||
1 file changed, 1 insertion(+), 2 deletions(-)
|
||||
|
||||
--- a/drivers/net/ethernet/broadcom/Kconfig
|
||||
+++ b/drivers/net/ethernet/broadcom/Kconfig
|
||||
@@ -71,14 +71,13 @@ config BCM63XX_ENET
|
||||
config BCMGENET
|
||||
tristate "Broadcom GENET internal MAC support"
|
||||
depends on HAS_IOMEM
|
||||
- depends on PTP_1588_CLOCK_OPTIONAL || !ARCH_BCM2835
|
||||
select MII
|
||||
select PHYLIB
|
||||
select FIXED_PHY
|
||||
select BCM7XXX_PHY
|
||||
select MDIO_BCM_UNIMAC
|
||||
select DIMLIB
|
||||
- select BROADCOM_PHY if ARCH_BCM2835
|
||||
+ select BROADCOM_PHY if (ARCH_BCM2835 && PTP_1588_CLOCK_OPTIONAL)
|
||||
help
|
||||
This driver supports the built-in Ethernet MACs found in the
|
||||
Broadcom BCM7xxx Set Top Box family chipset.
|
||||
@ -0,0 +1,23 @@
|
||||
From f032f801658ce6b47498f3e140f7e4aef0645042 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= <noltari@gmail.com>
|
||||
Date: Wed, 28 Dec 2022 13:20:24 +0100
|
||||
Subject: [PATCH 2/2] Revert "net: broadcom: Fix BCMGENET Kconfig"
|
||||
|
||||
[ Upstream commit 8d820bc9d12b8beebca836cceaf2bbe68216c2f8 ]
|
||||
|
||||
This reverts commit 6a264203dbdb0d076891d83bf3bb274d6b3863f2.
|
||||
---
|
||||
drivers/net/ethernet/broadcom/Kconfig | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
--- a/drivers/net/ethernet/broadcom/Kconfig
|
||||
+++ b/drivers/net/ethernet/broadcom/Kconfig
|
||||
@@ -77,7 +77,7 @@ config BCMGENET
|
||||
select BCM7XXX_PHY
|
||||
select MDIO_BCM_UNIMAC
|
||||
select DIMLIB
|
||||
- select BROADCOM_PHY if (ARCH_BCM2835 && PTP_1588_CLOCK_OPTIONAL)
|
||||
+ select BROADCOM_PHY if ARCH_BCM2835
|
||||
help
|
||||
This driver supports the built-in Ethernet MACs found in the
|
||||
Broadcom BCM7xxx Set Top Box family chipset.
|
||||
@ -1,12 +1,15 @@
|
||||
From: Felix Fietkau <nbd@nbd.name>
|
||||
Date: Thu, 3 Nov 2022 12:38:49 +0100
|
||||
Subject: [PATCH] net: ethernet: mtk_eth_soc: work around issue with
|
||||
sending small fragments
|
||||
Subject: [PATCH] net: ethernet: mtk_eth_soc: work around issue with sending
|
||||
small fragments
|
||||
|
||||
When frames are sent with very small fragments, the DMA engine appears to
|
||||
lock up and transmit attempts time out. Fix this by detecting the presence
|
||||
of small fragments and use skb_gso_segment + skb_linearize to deal with
|
||||
them
|
||||
When lots of frames are sent with a number of very small fragments, an
|
||||
internal FIFO can overflow, causing the DMA engine to lock up lock up and
|
||||
transmit attempts time out.
|
||||
|
||||
Fix this on MT7986 by increasing the reserved FIFO space.
|
||||
Fix this on older chips by detecting the presence of small fragments and use
|
||||
skb_gso_segment + skb_linearize to deal with them.
|
||||
|
||||
Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
---
|
||||
@ -42,11 +45,12 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
bool gso = false;
|
||||
int tx_num;
|
||||
|
||||
@@ -1423,6 +1439,17 @@ static netdev_tx_t mtk_start_xmit(struct
|
||||
@@ -1423,6 +1439,18 @@ static netdev_tx_t mtk_start_xmit(struct
|
||||
return NETDEV_TX_BUSY;
|
||||
}
|
||||
|
||||
+ if (skb_is_gso(skb) && mtk_skb_has_small_frag(skb)) {
|
||||
+ if (!MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2) &&
|
||||
+ skb_is_gso(skb) && mtk_skb_has_small_frag(skb)) {
|
||||
+ segs = skb_gso_segment(skb, dev->features & ~NETIF_F_ALL_TSO);
|
||||
+ if (IS_ERR(segs))
|
||||
+ goto drop;
|
||||
@ -60,19 +64,31 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
/* TSO: fill MSS info in tcp checksum field */
|
||||
if (skb_is_gso(skb)) {
|
||||
if (skb_cow_head(skb, 0)) {
|
||||
@@ -1438,8 +1465,13 @@ static netdev_tx_t mtk_start_xmit(struct
|
||||
@@ -1438,8 +1466,14 @@ static netdev_tx_t mtk_start_xmit(struct
|
||||
}
|
||||
}
|
||||
|
||||
- if (mtk_tx_map(skb, dev, tx_num, ring, gso) < 0)
|
||||
- goto drop;
|
||||
+ skb_list_walk_safe(skb, skb, next) {
|
||||
+ if ((mtk_skb_has_small_frag(skb) && skb_linearize(skb)) ||
|
||||
+ if ((!MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2) &&
|
||||
+ mtk_skb_has_small_frag(skb) && skb_linearize(skb)) ||
|
||||
+ mtk_tx_map(skb, dev, tx_num, ring, gso) < 0) {
|
||||
+ stats->tx_dropped++;
|
||||
+ dev_kfree_skb_any(skb);
|
||||
+ stats->tx_dropped++;
|
||||
+ dev_kfree_skb_any(skb);
|
||||
+ }
|
||||
+ }
|
||||
|
||||
if (unlikely(atomic_read(&ring->free_count) <= ring->thresh))
|
||||
netif_tx_stop_all_queues(dev);
|
||||
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
|
||||
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
|
||||
@@ -246,7 +246,7 @@
|
||||
#define MTK_CHK_DDONE_EN BIT(28)
|
||||
#define MTK_DMAD_WR_WDONE BIT(26)
|
||||
#define MTK_WCOMP_EN BIT(24)
|
||||
-#define MTK_RESV_BUF (0x40 << 16)
|
||||
+#define MTK_RESV_BUF (0x80 << 16)
|
||||
#define MTK_MUTLI_CNT (0x4 << 12)
|
||||
#define MTK_LEAKY_BUCKET_EN BIT(11)
|
||||
|
||||
|
||||
@ -11,7 +11,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
|
||||
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
|
||||
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
|
||||
@@ -3531,9 +3531,12 @@ static int mtk_hw_init(struct mtk_eth *e
|
||||
@@ -3533,9 +3533,12 @@ static int mtk_hw_init(struct mtk_eth *e
|
||||
mtk_w32(eth, 0x21021000, MTK_FE_INT_GRP);
|
||||
|
||||
if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) {
|
||||
|
||||
@ -17,7 +17,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
|
||||
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
|
||||
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
|
||||
@@ -1993,29 +1993,16 @@ static int mtk_poll_rx(struct napi_struc
|
||||
@@ -1995,29 +1995,16 @@ static int mtk_poll_rx(struct napi_struc
|
||||
if (reason == MTK_PPE_CPU_REASON_HIT_UNBIND_RATE_REACHED)
|
||||
mtk_ppe_check_skb(eth->ppe[0], skb, hash);
|
||||
|
||||
@ -50,7 +50,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
}
|
||||
|
||||
skb_record_rx_queue(skb, 0);
|
||||
@@ -2832,29 +2819,11 @@ static netdev_features_t mtk_fix_feature
|
||||
@@ -2834,29 +2821,11 @@ static netdev_features_t mtk_fix_feature
|
||||
|
||||
static int mtk_set_features(struct net_device *dev, netdev_features_t features)
|
||||
{
|
||||
@ -80,7 +80,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -3153,30 +3122,6 @@ static int mtk_open(struct net_device *d
|
||||
@@ -3155,30 +3124,6 @@ static int mtk_open(struct net_device *d
|
||||
struct mtk_eth *eth = mac->hw;
|
||||
int i, err;
|
||||
|
||||
@ -111,7 +111,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
err = phylink_of_phy_connect(mac->phylink, mac->of_node, 0);
|
||||
if (err) {
|
||||
netdev_err(dev, "%s: could not attach PHY: %d\n", __func__,
|
||||
@@ -3217,6 +3162,35 @@ static int mtk_open(struct net_device *d
|
||||
@@ -3219,6 +3164,35 @@ static int mtk_open(struct net_device *d
|
||||
phylink_start(mac->phylink);
|
||||
netif_tx_start_all_queues(dev);
|
||||
|
||||
@ -147,7 +147,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -3510,10 +3484,9 @@ static int mtk_hw_init(struct mtk_eth *e
|
||||
@@ -3512,10 +3486,9 @@ static int mtk_hw_init(struct mtk_eth *e
|
||||
if (!MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) {
|
||||
val = mtk_r32(eth, MTK_CDMP_IG_CTRL);
|
||||
mtk_w32(eth, val | MTK_CDMP_STAG_EN, MTK_CDMP_IG_CTRL);
|
||||
@ -160,7 +160,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
|
||||
/* set interrupt delays based on current Net DIM sample */
|
||||
mtk_dim_rx(ð->rx_dim.work);
|
||||
@@ -4134,7 +4107,7 @@ static int mtk_add_mac(struct mtk_eth *e
|
||||
@@ -4136,7 +4109,7 @@ static int mtk_add_mac(struct mtk_eth *e
|
||||
eth->netdev[id]->hw_features |= NETIF_F_LRO;
|
||||
|
||||
eth->netdev[id]->vlan_features = eth->soc->hw_features &
|
||||
|
||||
@ -0,0 +1,55 @@
|
||||
From: Felix Fietkau <nbd@nbd.name>
|
||||
Date: Tue, 27 Dec 2022 15:02:51 +0100
|
||||
Subject: [PATCH] net: ethernet: mtk_eth_soc: ppe: fix L2 offloading with DSA
|
||||
untagging offload enabled
|
||||
|
||||
Check for skb metadata in order to detect the case where the DSA header is not
|
||||
present.
|
||||
|
||||
Fixes: 2d7605a72906 ("net: ethernet: mtk_eth_soc: enable hardware DSA untagging")
|
||||
Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
---
|
||||
|
||||
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
|
||||
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
|
||||
@@ -1992,9 +1992,6 @@ static int mtk_poll_rx(struct napi_struc
|
||||
skb_checksum_none_assert(skb);
|
||||
skb->protocol = eth_type_trans(skb, netdev);
|
||||
|
||||
- if (reason == MTK_PPE_CPU_REASON_HIT_UNBIND_RATE_REACHED)
|
||||
- mtk_ppe_check_skb(eth->ppe[0], skb, hash);
|
||||
-
|
||||
/* When using VLAN untagging in combination with DSA, the
|
||||
* hardware treats the MTK special tag as a VLAN and untags it.
|
||||
*/
|
||||
@@ -2007,6 +2004,9 @@ static int mtk_poll_rx(struct napi_struc
|
||||
skb_dst_set_noref(skb, ð->dsa_meta[port]->dst);
|
||||
}
|
||||
|
||||
+ if (reason == MTK_PPE_CPU_REASON_HIT_UNBIND_RATE_REACHED)
|
||||
+ mtk_ppe_check_skb(eth->ppe[0], skb, hash);
|
||||
+
|
||||
skb_record_rx_queue(skb, 0);
|
||||
napi_gro_receive(napi, skb);
|
||||
|
||||
--- a/drivers/net/ethernet/mediatek/mtk_ppe.c
|
||||
+++ b/drivers/net/ethernet/mediatek/mtk_ppe.c
|
||||
@@ -8,6 +8,7 @@
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/if_ether.h>
|
||||
#include <linux/if_vlan.h>
|
||||
+#include <net/dst_metadata.h>
|
||||
#include <net/dsa.h>
|
||||
#include "mtk_eth_soc.h"
|
||||
#include "mtk_ppe.h"
|
||||
@@ -756,7 +757,9 @@ void __mtk_ppe_check_skb(struct mtk_ppe
|
||||
skb->dev->dsa_ptr->tag_ops->proto != DSA_TAG_PROTO_MTK)
|
||||
goto out;
|
||||
|
||||
- tag += 4;
|
||||
+ if (!skb_metadata_dst(skb))
|
||||
+ tag += 4;
|
||||
+
|
||||
if (get_unaligned_be16(tag) != ETH_P_8021Q)
|
||||
break;
|
||||
|
||||
@ -60,12 +60,21 @@
|
||||
|
||||
partition@0 {
|
||||
label = "u-boot";
|
||||
reg = <0x0 0xe0000>;
|
||||
reg = <0x0 0x80000>;
|
||||
read-only;
|
||||
};
|
||||
|
||||
partition@e0000 {
|
||||
/*
|
||||
* u-boot gets split here while keeping u-boot read-only,
|
||||
* which allows safe usage of fw_setenv
|
||||
*/
|
||||
partition@80000 {
|
||||
label = "u-boot-env";
|
||||
reg = <0x80000 0x60000>;
|
||||
};
|
||||
|
||||
partition@e0000 {
|
||||
label = "nvram";
|
||||
reg = <0xe0000 0x100000>;
|
||||
read-only;
|
||||
};
|
||||
|
||||
@ -18,8 +18,17 @@ endef
|
||||
|
||||
include $(INCLUDE_DIR)/target.mk
|
||||
|
||||
DEFAULT_PACKAGES += uboot-envtools ethtool kmod-gpio-button-hotplug \
|
||||
firewall4 nftables kmod-nft-offload odhcp6c \
|
||||
ip-full ip-bridge tc-bpf
|
||||
DEFAULT_PACKAGES += \
|
||||
ethtool \
|
||||
firewall4 \
|
||||
ip-bridge \
|
||||
ip-full \
|
||||
kmod-gpio-button-hotplug \
|
||||
kmod-nft-offload \
|
||||
nftables \
|
||||
odhcp6c \
|
||||
tc-bpf \
|
||||
uboot-envtools \
|
||||
|
||||
|
||||
$(eval $(call BuildTarget))
|
||||
|
||||
@ -129,9 +129,9 @@
|
||||
label = "jffs2";
|
||||
reg = <0x160000 0x100000>;
|
||||
};
|
||||
partition@b260000 {
|
||||
partition@260000 {
|
||||
label = "firmware";
|
||||
reg = <0x260000 0xda0000>;
|
||||
reg = <0x260000 0x6d0000>;
|
||||
compatible = "openwrt,uimage", "denx,uimage";
|
||||
openwrt,ih-magic = <0x83800000>;
|
||||
};
|
||||
|
||||
@ -129,9 +129,9 @@
|
||||
label = "jffs2";
|
||||
reg = <0x160000 0x100000>;
|
||||
};
|
||||
partition@b260000 {
|
||||
partition@260000 {
|
||||
label = "firmware";
|
||||
reg = <0x260000 0xda0000>;
|
||||
reg = <0x260000 0x6d0000>;
|
||||
compatible = "openwrt,uimage", "denx,uimage";
|
||||
openwrt,ih-magic = <0x83800000>;
|
||||
};
|
||||
|
||||
@ -121,28 +121,45 @@ void rtl_table_release(struct table_reg *r)
|
||||
// pr_info("Unlock done\n");
|
||||
}
|
||||
|
||||
static int rtl_table_exec(struct table_reg *r, bool is_write, int idx)
|
||||
{
|
||||
int ret = 0;
|
||||
u32 cmd, val;
|
||||
|
||||
/* Read/write bit has inverted meaning on RTL838x */
|
||||
if (r->rmode)
|
||||
cmd = is_write ? 0 : BIT(r->c_bit);
|
||||
else
|
||||
cmd = is_write ? BIT(r->c_bit) : 0;
|
||||
|
||||
cmd |= BIT(r->c_bit + 1); /* Execute bit */
|
||||
cmd |= r->tbl << r->t_bit; /* Table type */
|
||||
cmd |= idx & (BIT(r->t_bit) - 1); /* Index */
|
||||
|
||||
sw_w32(cmd, r->addr);
|
||||
|
||||
ret = readx_poll_timeout(sw_r32, r->addr, val,
|
||||
!(val & BIT(r->c_bit + 1)), 20, 10000);
|
||||
if (ret)
|
||||
pr_err("%s: timeout\n", __func__);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Reads table index idx into the data registers of the table
|
||||
*/
|
||||
void rtl_table_read(struct table_reg *r, int idx)
|
||||
int rtl_table_read(struct table_reg *r, int idx)
|
||||
{
|
||||
u32 cmd = r->rmode ? BIT(r->c_bit) : 0;
|
||||
|
||||
cmd |= BIT(r->c_bit + 1) | (r->tbl << r->t_bit) | (idx & (BIT(r->t_bit) - 1));
|
||||
sw_w32(cmd, r->addr);
|
||||
do { } while (sw_r32(r->addr) & BIT(r->c_bit + 1));
|
||||
return rtl_table_exec(r, false, idx);
|
||||
}
|
||||
|
||||
/*
|
||||
* Writes the content of the table data registers into the table at index idx
|
||||
*/
|
||||
void rtl_table_write(struct table_reg *r, int idx)
|
||||
int rtl_table_write(struct table_reg *r, int idx)
|
||||
{
|
||||
u32 cmd = r->rmode ? 0 : BIT(r->c_bit);
|
||||
|
||||
cmd |= BIT(r->c_bit + 1) | (r->tbl << r->t_bit) | (idx & (BIT(r->t_bit) - 1));
|
||||
sw_w32(cmd, r->addr);
|
||||
do { } while (sw_r32(r->addr) & BIT(r->c_bit + 1));
|
||||
return rtl_table_exec(r, true, idx);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -323,7 +340,6 @@ static int __init rtl83xx_mdio_probe(struct rtl838x_switch_priv *priv)
|
||||
if (of_property_read_u32(dn, "reg", &pn))
|
||||
continue;
|
||||
|
||||
pr_info("%s found port %d\n", __func__, pn);
|
||||
phy_node = of_parse_phandle(dn, "phy-handle", 0);
|
||||
if (!phy_node) {
|
||||
if (pn != priv->cpu_port)
|
||||
@ -331,14 +347,9 @@ static int __init rtl83xx_mdio_probe(struct rtl838x_switch_priv *priv)
|
||||
continue;
|
||||
}
|
||||
|
||||
pr_info("%s port %d has phandle\n", __func__, pn);
|
||||
if (of_property_read_u32(phy_node, "sds", &priv->ports[pn].sds_num))
|
||||
priv->ports[pn].sds_num = -1;
|
||||
else {
|
||||
pr_info("%s sds port %d is %d\n", __func__, pn,
|
||||
priv->ports[pn].sds_num);
|
||||
}
|
||||
pr_info("%s port %d has SDS\n", __func__, priv->ports[pn].sds_num);
|
||||
pr_debug("%s port %d has SDS %d\n", __func__, pn, priv->ports[pn].sds_num);
|
||||
|
||||
if (of_get_phy_mode(dn, &interface))
|
||||
interface = PHY_INTERFACE_MODE_NA;
|
||||
|
||||
@ -343,6 +343,9 @@ static int l2_table_show(struct seq_file *m, void *v)
|
||||
|
||||
seq_printf(m, "Hash table bucket %d index %d ", bucket, index);
|
||||
l2_table_print_entry(m, priv, &e);
|
||||
|
||||
if (!((i + 1) % 64))
|
||||
cond_resched();
|
||||
}
|
||||
|
||||
for (i = 0; i < 64; i++) {
|
||||
|
||||
@ -1728,6 +1728,9 @@ static int rtl83xx_port_fdb_dump(struct dsa_switch *ds, int port,
|
||||
|
||||
if (e.port == port || e.port == RTL930X_PORT_IGNORE)
|
||||
cb(e.mac, e.vid, e.is_static, data);
|
||||
|
||||
if (!((i + 1) % 64))
|
||||
cond_resched();
|
||||
}
|
||||
|
||||
for (i = 0; i < 64; i++) {
|
||||
|
||||
@ -67,8 +67,8 @@ typedef enum {
|
||||
void rtl_table_init(void);
|
||||
struct table_reg *rtl_table_get(rtl838x_tbl_reg_t r, int t);
|
||||
void rtl_table_release(struct table_reg *r);
|
||||
void rtl_table_read(struct table_reg *r, int idx);
|
||||
void rtl_table_write(struct table_reg *r, int idx);
|
||||
int rtl_table_read(struct table_reg *r, int idx);
|
||||
int rtl_table_write(struct table_reg *r, int idx);
|
||||
inline u16 rtl_table_data(struct table_reg *r, int i);
|
||||
inline u32 rtl_table_data_r(struct table_reg *r, int i);
|
||||
inline void rtl_table_data_w(struct table_reg *r, u32 v, int i);
|
||||
|
||||
@ -96,7 +96,7 @@ struct notify_b {
|
||||
static void rtl838x_create_tx_header(struct p_hdr *h, unsigned int dest_port, int prio)
|
||||
{
|
||||
// cpu_tag[0] is reserved on the RTL83XX SoCs
|
||||
h->cpu_tag[1] = 0x0401; // BIT 10: RTL8380_CPU_TAG, BIT0: L2LEARNING on
|
||||
h->cpu_tag[1] = 0x0400; // BIT 10: RTL8380_CPU_TAG
|
||||
h->cpu_tag[2] = 0x0200; // Set only AS_DPM, to enable DPM settings below
|
||||
h->cpu_tag[3] = 0x0000;
|
||||
h->cpu_tag[4] = BIT(dest_port) >> 16;
|
||||
@ -111,7 +111,7 @@ static void rtl839x_create_tx_header(struct p_hdr *h, unsigned int dest_port, in
|
||||
{
|
||||
// cpu_tag[0] is reserved on the RTL83XX SoCs
|
||||
h->cpu_tag[1] = 0x0100; // RTL8390_CPU_TAG marker
|
||||
h->cpu_tag[2] = BIT(4) | BIT(7); /* AS_DPM (4) and L2LEARNING (7) flags */
|
||||
h->cpu_tag[2] = BIT(4); /* AS_DPM flag */
|
||||
h->cpu_tag[3] = h->cpu_tag[4] = h->cpu_tag[5] = 0;
|
||||
// h->cpu_tag[1] |= BIT(1) | BIT(0); // Bypass filter 1/2
|
||||
if (dest_port >= 32) {
|
||||
@ -682,7 +682,7 @@ static void rtl838x_hw_reset(struct rtl838x_eth_priv *priv)
|
||||
else
|
||||
reset_mask = 0xc;
|
||||
|
||||
sw_w32(reset_mask, priv->r->rst_glb_ctrl);
|
||||
sw_w32_mask(0, reset_mask, priv->r->rst_glb_ctrl);
|
||||
|
||||
do { /* Wait for reset of NIC and Queues done */
|
||||
udelay(20);
|
||||
|
||||
@ -17,7 +17,7 @@ description: |
|
||||
|
||||
RTL83XX: 0x3100, 0x3110, 0x3120, 0x3130, 0x3140
|
||||
RTL93XX: 0x3200, 0x3210, 0x3220, 0x3230, 0x3240
|
||||
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
items:
|
||||
|
||||
@ -350,9 +350,7 @@
|
||||
#define RTL931X_MAC_L2_GLOBAL_CTRL2 (0x1358)
|
||||
#define RTL931X_MAC_L2_GLOBAL_CTRL1 (0x5548)
|
||||
|
||||
/*
|
||||
* Switch interrupts
|
||||
*/
|
||||
/* Switch interrupts */
|
||||
#define RTL838X_IMR_GLB (0x1100)
|
||||
#define RTL838X_IMR_PORT_LINK_STS_CHG (0x1104)
|
||||
#define RTL838X_ISR_GLB_SRC (0x1148)
|
||||
@ -368,7 +366,7 @@
|
||||
#define RTL930X_ISR_GLB (0xC658)
|
||||
#define RTL930X_ISR_PORT_LINK_STS_CHG (0xC660)
|
||||
|
||||
// IMR_GLB does not exit on RTL931X
|
||||
/* IMR_GLB does not exit on RTL931X */
|
||||
#define RTL931X_IMR_PORT_LINK_STS_CHG (0x126C)
|
||||
#define RTL931X_ISR_GLB_SRC (0x12B4)
|
||||
#define RTL931X_ISR_PORT_LINK_STS_CHG (0x12B8)
|
||||
|
||||
@ -11,7 +11,7 @@
|
||||
|
||||
#include <mach-rtl83xx.h>
|
||||
|
||||
/*
|
||||
/*
|
||||
* Timer registers
|
||||
* the RTL9300/9310 SoCs have 6 timers, each register block 0x10 apart
|
||||
*/
|
||||
@ -24,11 +24,11 @@
|
||||
#define RTL9300_TC_INT_IP BIT(16)
|
||||
#define RTL9300_TC_INT_IE BIT(20)
|
||||
|
||||
// Timer modes
|
||||
/* Timer modes */
|
||||
#define TIMER_MODE_REPEAT 1
|
||||
#define TIMER_MODE_ONCE 0
|
||||
|
||||
// Minimum divider is 2
|
||||
/* Minimum divider is 2 */
|
||||
#define DIVISOR_RTL9300 2
|
||||
|
||||
#define N_BITS 28
|
||||
@ -54,11 +54,12 @@ static irqreturn_t rtl9300_timer_interrupt(int irq, void *dev_id)
|
||||
|
||||
u32 v = readl(rtl_clk->base + RTL9300_TC_INT);
|
||||
|
||||
// Acknowledge the IRQ
|
||||
/* Acknowledge the IRQ */
|
||||
v |= RTL9300_TC_INT_IP;
|
||||
writel(v, rtl_clk->base + RTL9300_TC_INT);
|
||||
|
||||
clk->event_handler(clk);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
@ -68,7 +69,7 @@ static void rtl9300_clock_stop(void __iomem *base)
|
||||
|
||||
writel(0, base + RTL9300_TC_CTRL);
|
||||
|
||||
// Acknowledge possibly pending IRQ
|
||||
/* Acknowledge possibly pending IRQ */
|
||||
v = readl(base + RTL9300_TC_INT);
|
||||
writel(v | RTL9300_TC_INT_IP, base + RTL9300_TC_INT);
|
||||
}
|
||||
@ -101,6 +102,7 @@ static int rtl9300_state_periodic(struct clock_event_device *clk)
|
||||
rtl9300_clock_stop(base);
|
||||
writel(RTL9300_CLOCK_RATE / HZ, base + RTL9300_TC_DATA);
|
||||
rtl9300_timer_start(base, TIMER_MODE_REPEAT);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -112,6 +114,7 @@ static int rtl9300_state_oneshot(struct clock_event_device *clk)
|
||||
rtl9300_clock_stop(base);
|
||||
writel(RTL9300_CLOCK_RATE / HZ, base + RTL9300_TC_DATA);
|
||||
rtl9300_timer_start(base, TIMER_MODE_ONCE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -121,6 +124,7 @@ static int rtl9300_shutdown(struct clock_event_device *clk)
|
||||
|
||||
pr_debug("------------- rtl9300_shutdown %08x\n", (u32)base);
|
||||
rtl9300_clock_stop(base);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -128,14 +132,14 @@ static void rtl9300_clock_setup(void __iomem *base)
|
||||
{
|
||||
u32 v;
|
||||
|
||||
// Disable timer
|
||||
/* Disable timer */
|
||||
writel(0, base + RTL9300_TC_CTRL);
|
||||
|
||||
// Acknowledge possibly pending IRQ
|
||||
/* Acknowledge possibly pending IRQ */
|
||||
v = readl(base + RTL9300_TC_INT);
|
||||
writel(v | RTL9300_TC_INT_IP, base + RTL9300_TC_INT);
|
||||
|
||||
// Setup maximum period (for use as clock-source)
|
||||
/* Setup maximum period (for use as clock-source) */
|
||||
writel(0x0fffffff, base + RTL9300_TC_DATA);
|
||||
}
|
||||
|
||||
|
||||
@ -147,4 +147,3 @@ wait_cpu:
|
||||
.globl rtcl_838x_dram_size
|
||||
rtcl_838x_dram_size:
|
||||
.word .-rtcl_838x_dram_start
|
||||
|
||||
|
||||
@ -139,4 +139,3 @@ wait_pllclock:
|
||||
.globl rtcl_839x_dram_size
|
||||
rtcl_839x_dram_size:
|
||||
.word .-rtcl_839x_dram_start
|
||||
|
||||
|
||||
@ -467,9 +467,9 @@ static long rtcl_round_rate(struct clk_hw *hw, unsigned long rate, unsigned long
|
||||
*/
|
||||
|
||||
#define RTCL_SRAM_FUNC(SOC, PBASE, FN) ({ \
|
||||
rtcl_##SOC##_sram_##FN = ((void *)&rtcl_##SOC##_dram_##FN \
|
||||
- (void *)&rtcl_##SOC##_dram_start) \
|
||||
+ (void *)PBASE; })
|
||||
rtcl_##SOC##_sram_##FN = ((void *)&rtcl_##SOC##_dram_##FN - \
|
||||
(void *)&rtcl_##SOC##_dram_start) + \
|
||||
(void *)PBASE; })
|
||||
|
||||
static const struct clk_ops rtcl_clk_ops = {
|
||||
.set_rate = rtcl_set_rate,
|
||||
@ -663,11 +663,10 @@ err_put_device:
|
||||
|
||||
void rtcl_ccu_log_early(void)
|
||||
{
|
||||
int clk_idx;
|
||||
char meminfo[80], clkinfo[255], msg[255] = "rtl83xx-clk: initialized";
|
||||
|
||||
sprintf(meminfo, " (%d Bit DDR%d)", rtcl_ccu->dram.buswidth, rtcl_ccu->dram.type);
|
||||
for (clk_idx = 0; clk_idx < CLK_COUNT; clk_idx++) {
|
||||
for (int clk_idx = 0; clk_idx < CLK_COUNT; clk_idx++) {
|
||||
sprintf(clkinfo, ", %s %lu MHz", rtcl_clk_info[clk_idx].display_name,
|
||||
rtcl_ccu->clks[clk_idx].startup / 1000000);
|
||||
if (clk_idx == CLK_MEM)
|
||||
@ -679,12 +678,11 @@ void rtcl_ccu_log_early(void)
|
||||
|
||||
void rtcl_ccu_log_late(void)
|
||||
{
|
||||
int clk_idx;
|
||||
struct rtcl_clk *rclk;
|
||||
bool overclock = false;
|
||||
char clkinfo[80], msg[255] = "rate setting enabled";
|
||||
|
||||
for (clk_idx = 0; clk_idx < CLK_COUNT; clk_idx++) {
|
||||
for (int clk_idx = 0; clk_idx < CLK_COUNT; clk_idx++) {
|
||||
rclk = &rtcl_ccu->clks[clk_idx];
|
||||
overclock |= rclk->max > rclk->startup;
|
||||
sprintf(clkinfo, ", %s %lu-%lu MHz", rtcl_clk_info[clk_idx].display_name,
|
||||
|
||||
@ -45,7 +45,7 @@ static u32 rtl8231_read(struct rtl8231_gpios *gpios, u32 reg)
|
||||
/* Set execution bit: cleared when operation completed */
|
||||
t |= 1;
|
||||
|
||||
// Start execution
|
||||
/* Start execution */
|
||||
sw_w32(t, gpios->ext_gpio_indrt_access);
|
||||
do {
|
||||
udelay(1);
|
||||
@ -55,7 +55,7 @@ static u32 rtl8231_read(struct rtl8231_gpios *gpios, u32 reg)
|
||||
|
||||
if (n >= USEC_TIMEOUT)
|
||||
return 0x80000000;
|
||||
|
||||
|
||||
pr_debug("%s: %x, %x, %x\n", __func__, gpios->smi_bus_id,
|
||||
reg, (t & 0xffff0000) >> 16);
|
||||
|
||||
@ -76,7 +76,7 @@ static int rtl8231_write(struct rtl8231_gpios *gpios, u32 reg, u32 data)
|
||||
/* Set execution bit: cleared when operation completed */
|
||||
t |= 1;
|
||||
|
||||
// Start execution
|
||||
/* Start execution */
|
||||
sw_w32(t, gpios->ext_gpio_indrt_access);
|
||||
do {
|
||||
udelay(1);
|
||||
@ -127,6 +127,7 @@ static int rtl8231_pin_dir(struct rtl8231_gpios *gpios, u32 gpio, u32 dir)
|
||||
rtl8231_write(gpios, pin_dir_addr, v);
|
||||
gpios->reg_shadow[pin_dir_addr] = v;
|
||||
gpios->reg_cached |= 1 << pin_dir_addr;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -150,6 +151,7 @@ static int rtl8231_pin_dir_get(struct rtl8231_gpios *gpios, u32 gpio, u32 *dir)
|
||||
*dir = 1;
|
||||
else
|
||||
*dir = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -166,6 +168,7 @@ static int rtl8231_pin_set(struct rtl8231_gpios *gpios, u32 gpio, u32 data)
|
||||
rtl8231_write(gpios, RTL8231_GPIO_DATA(gpio), v);
|
||||
gpios->reg_shadow[RTL8231_GPIO_DATA(gpio)] = v;
|
||||
gpios->reg_cached |= 1 << RTL8231_GPIO_DATA(gpio);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -179,6 +182,7 @@ static int rtl8231_pin_get(struct rtl8231_gpios *gpios, u32 gpio, u16 *state)
|
||||
}
|
||||
|
||||
*state = v & 0xffff;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -191,6 +195,7 @@ static int rtl8231_direction_input(struct gpio_chip *gc, unsigned int offset)
|
||||
mutex_lock(&miim_lock);
|
||||
err = rtl8231_pin_dir(gpios, offset, 1);
|
||||
mutex_unlock(&miim_lock);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
@ -203,8 +208,10 @@ static int rtl8231_direction_output(struct gpio_chip *gc, unsigned int offset, i
|
||||
mutex_lock(&miim_lock);
|
||||
err = rtl8231_pin_dir(gpios, offset, 0);
|
||||
mutex_unlock(&miim_lock);
|
||||
|
||||
if (!err)
|
||||
err = rtl8231_pin_set(gpios, offset, value);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
@ -217,6 +224,7 @@ static int rtl8231_get_direction(struct gpio_chip *gc, unsigned int offset)
|
||||
mutex_lock(&miim_lock);
|
||||
rtl8231_pin_dir_get(gpios, offset, &v);
|
||||
mutex_unlock(&miim_lock);
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
@ -228,8 +236,10 @@ static int rtl8231_gpio_get(struct gpio_chip *gc, unsigned int offset)
|
||||
mutex_lock(&miim_lock);
|
||||
rtl8231_pin_get(gpios, offset, &state);
|
||||
mutex_unlock(&miim_lock);
|
||||
|
||||
if (state & (1 << (offset % 16)))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -249,10 +259,10 @@ int rtl8231_init(struct rtl8231_gpios *gpios)
|
||||
gpios->reg_cached = 0;
|
||||
|
||||
if (soc_info.family == RTL8390_FAMILY_ID) {
|
||||
// RTL8390: Enable external gpio in global led control register
|
||||
/* RTL8390: Enable external gpio in global led control register */
|
||||
sw_w32_mask(0x7 << 18, 0x4 << 18, RTL839X_LED_GLB_CTRL);
|
||||
} else if (soc_info.family == RTL8380_FAMILY_ID) {
|
||||
// RTL8380: Enable RTL8231 indirect access mode
|
||||
/* RTL8380: Enable RTL8231 indirect access mode */
|
||||
sw_w32_mask(0, 1, RTL838X_EXTRA_GPIO_CTRL);
|
||||
sw_w32_mask(3, 1, RTL838X_DMY_REG5);
|
||||
}
|
||||
@ -337,8 +347,7 @@ static int rtl8231_gpio_probe(struct platform_device *pdev)
|
||||
gpios->gc.get = rtl8231_gpio_get;
|
||||
gpios->gc.get_direction = rtl8231_get_direction;
|
||||
|
||||
err = devm_gpiochip_add_data(dev, &gpios->gc, gpios);
|
||||
return err;
|
||||
return devm_gpiochip_add_data(dev, &gpios->gc, gpios);
|
||||
}
|
||||
|
||||
static struct platform_driver rtl8231_gpio_driver = {
|
||||
|
||||
@ -23,27 +23,27 @@ struct i2c_drv_data {
|
||||
void (*config_io)(struct rtl9300_i2c *i2c, int scl_num, int sda_num);
|
||||
u32 mst2_offset;
|
||||
};
|
||||
|
||||
|
||||
DEFINE_MUTEX(i2c_lock);
|
||||
|
||||
static void rtl9300_i2c_reg_addr_set(struct rtl9300_i2c *i2c, u32 reg, u16 len)
|
||||
{
|
||||
// Set register address width
|
||||
/* Set register address width */
|
||||
REG_MASK(i2c, 0x3 << RTL9300_I2C_CTRL2_MADDR_WIDTH, len << RTL9300_I2C_CTRL2_MADDR_WIDTH,
|
||||
RTL9300_I2C_CTRL2);
|
||||
|
||||
// Set register address
|
||||
/* Set register address */
|
||||
REG_MASK(i2c, 0xffffff << RTL9300_I2C_CTRL1_MEM_ADDR, reg << RTL9300_I2C_CTRL1_MEM_ADDR,
|
||||
RTL9300_I2C_CTRL1);
|
||||
}
|
||||
|
||||
static void rtl9310_i2c_reg_addr_set(struct rtl9300_i2c *i2c, u32 reg, u16 len)
|
||||
{
|
||||
// Set register address width
|
||||
/* Set register address width */
|
||||
REG_MASK(i2c, 0x3 << RTL9310_I2C_CTRL_MADDR_WIDTH, len << RTL9310_I2C_CTRL_MADDR_WIDTH,
|
||||
RTL9310_I2C_CTRL);
|
||||
|
||||
// Set register address
|
||||
/* Set register address */
|
||||
writel(reg, REG(i2c, RTL9310_I2C_MEMADDR));
|
||||
}
|
||||
|
||||
@ -51,14 +51,14 @@ static void rtl9300_i2c_config_io(struct rtl9300_i2c *i2c, int scl_num, int sda_
|
||||
{
|
||||
u32 v;
|
||||
|
||||
// Set SCL pin
|
||||
/* Set SCL pin */
|
||||
REG_MASK(i2c, 0, BIT(RTL9300_I2C_CTRL1_GPIO8_SCL_SEL), RTL9300_I2C_CTRL1);
|
||||
|
||||
// Set SDA pin
|
||||
/* Set SDA pin */
|
||||
REG_MASK(i2c, 0x7 << RTL9300_I2C_CTRL1_SDA_OUT_SEL,
|
||||
i2c->sda_num << RTL9300_I2C_CTRL1_SDA_OUT_SEL, RTL9300_I2C_CTRL1);
|
||||
|
||||
// Set SDA pin to I2C functionality
|
||||
/* Set SDA pin to I2C functionality */
|
||||
v = readl(i2c->base + RTL9300_I2C_MST_GLB_CTRL);
|
||||
v |= BIT(i2c->sda_num);
|
||||
writel(v, i2c->base + RTL9300_I2C_MST_GLB_CTRL);
|
||||
@ -68,14 +68,14 @@ static void rtl9310_i2c_config_io(struct rtl9300_i2c *i2c, int scl_num, int sda_
|
||||
{
|
||||
u32 v;
|
||||
|
||||
// Set SCL pin
|
||||
/* Set SCL pin */
|
||||
REG_MASK(i2c, 0, BIT(RTL9310_I2C_MST_IF_SEL_GPIO_SCL_SEL + scl_num), RTL9310_I2C_MST_IF_SEL);
|
||||
|
||||
// Set SDA pin
|
||||
/* Set SDA pin */
|
||||
REG_MASK(i2c, 0x7 << RTL9310_I2C_CTRL_SDA_OUT_SEL,
|
||||
i2c->sda_num << RTL9310_I2C_CTRL_SDA_OUT_SEL, RTL9310_I2C_CTRL);
|
||||
|
||||
// Set SDA pin to I2C functionality
|
||||
/* Set SDA pin to I2C functionality */
|
||||
v = readl(i2c->base + RTL9310_I2C_MST_IF_SEL);
|
||||
v |= BIT(i2c->sda_num);
|
||||
writel(v, i2c->base + RTL9310_I2C_MST_IF_SEL);
|
||||
@ -83,19 +83,19 @@ static void rtl9310_i2c_config_io(struct rtl9300_i2c *i2c, int scl_num, int sda_
|
||||
|
||||
static int rtl9300_i2c_config_xfer(struct rtl9300_i2c *i2c, u16 addr, u16 len)
|
||||
{
|
||||
// Set bus frequency
|
||||
/* Set bus frequency */
|
||||
REG_MASK(i2c, 0x3 << RTL9300_I2C_CTRL2_SCL_FREQ,
|
||||
i2c->bus_freq << RTL9300_I2C_CTRL2_SCL_FREQ, RTL9300_I2C_CTRL2);
|
||||
|
||||
// Set slave device address
|
||||
/* Set slave device address */
|
||||
REG_MASK(i2c, 0x7f << RTL9300_I2C_CTRL2_DEV_ADDR,
|
||||
addr << RTL9300_I2C_CTRL2_DEV_ADDR, RTL9300_I2C_CTRL2);
|
||||
|
||||
// Set data length
|
||||
/* Set data length */
|
||||
REG_MASK(i2c, 0xf << RTL9300_I2C_CTRL2_DATA_WIDTH,
|
||||
((len - 1) & 0xf) << RTL9300_I2C_CTRL2_DATA_WIDTH, RTL9300_I2C_CTRL2);
|
||||
|
||||
// Set read mode to random
|
||||
/* Set read mode to random */
|
||||
REG_MASK(i2c, 0x1 << RTL9300_I2C_CTRL2_READ_MODE, 0, RTL9300_I2C_CTRL2);
|
||||
|
||||
return 0;
|
||||
@ -103,19 +103,19 @@ static int rtl9300_i2c_config_xfer(struct rtl9300_i2c *i2c, u16 addr, u16 len)
|
||||
|
||||
static int rtl9310_i2c_config_xfer(struct rtl9300_i2c *i2c, u16 addr, u16 len)
|
||||
{
|
||||
// Set bus frequency
|
||||
/* Set bus frequency */
|
||||
REG_MASK(i2c, 0x3 << RTL9310_I2C_CTRL_SCL_FREQ,
|
||||
i2c->bus_freq << RTL9310_I2C_CTRL_SCL_FREQ, RTL9310_I2C_CTRL);
|
||||
|
||||
// Set slave device address
|
||||
/* Set slave device address */
|
||||
REG_MASK(i2c, 0x7f << RTL9310_I2C_CTRL_DEV_ADDR,
|
||||
addr << RTL9310_I2C_CTRL_DEV_ADDR, RTL9310_I2C_CTRL);
|
||||
|
||||
// Set data length
|
||||
/* Set data length */
|
||||
REG_MASK(i2c, 0xf << RTL9310_I2C_CTRL_DATA_WIDTH,
|
||||
((len - 1) & 0xf) << RTL9310_I2C_CTRL_DATA_WIDTH, RTL9310_I2C_CTRL);
|
||||
|
||||
// Set read mode to random
|
||||
/* Set read mode to random */
|
||||
REG_MASK(i2c, 0x1 << RTL9310_I2C_CTRL_READ_MODE, 0, RTL9310_I2C_CTRL);
|
||||
|
||||
return 0;
|
||||
@ -123,13 +123,12 @@ static int rtl9310_i2c_config_xfer(struct rtl9300_i2c *i2c, u16 addr, u16 len)
|
||||
|
||||
static int i2c_read(void __iomem *r0, u8 *buf, int len)
|
||||
{
|
||||
int i;
|
||||
u32 v;
|
||||
|
||||
if (len > 16)
|
||||
return -EIO;
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
for (int i = 0; i < len; i++) {
|
||||
u32 v;
|
||||
|
||||
if (i % 4 == 0)
|
||||
v = readl(r0 + i);
|
||||
buf[i] = v;
|
||||
@ -141,13 +140,12 @@ static int i2c_read(void __iomem *r0, u8 *buf, int len)
|
||||
|
||||
static int i2c_write(void __iomem *r0, u8 *buf, int len)
|
||||
{
|
||||
u32 v;
|
||||
int i;
|
||||
|
||||
if (len > 16)
|
||||
return -EIO;
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
for (int i = 0; i < len; i++) {
|
||||
u32 v;
|
||||
|
||||
if (! (i % 4))
|
||||
v = 0;
|
||||
v <<= 8;
|
||||
@ -347,7 +345,7 @@ static int rtl9300_i2c_probe(struct platform_device *pdev)
|
||||
int ret = 0;
|
||||
|
||||
pr_info("%s probing I2C adapter\n", __func__);
|
||||
|
||||
|
||||
if (!node) {
|
||||
dev_err(i2c->dev, "No DT found\n");
|
||||
return -EINVAL;
|
||||
@ -376,7 +374,7 @@ static int rtl9300_i2c_probe(struct platform_device *pdev)
|
||||
case I2C_MAX_STANDARD_MODE_FREQ:
|
||||
i2c->bus_freq = RTL9300_I2C_STD_FREQ;
|
||||
break;
|
||||
|
||||
|
||||
case I2C_MAX_FAST_MODE_FREQ:
|
||||
i2c->bus_freq = RTL9300_I2C_FAST_FREQ;
|
||||
break;
|
||||
@ -451,7 +449,7 @@ struct i2c_drv_data rtl9300_i2c_drv_data = {
|
||||
};
|
||||
|
||||
struct i2c_drv_data rtl9310_i2c_drv_data = {
|
||||
.scl0_pin = 13,
|
||||
.scl0_pin = 13,
|
||||
.scl1_pin = 14,
|
||||
.sda0_pin = 0,
|
||||
.read = rtl9310_i2c_read,
|
||||
|
||||
@ -55,8 +55,8 @@ struct rtl9300_i2c {
|
||||
struct device *dev;
|
||||
struct i2c_adapter adap;
|
||||
u8 bus_freq;
|
||||
u8 sda_num; // SDA channel number
|
||||
u8 scl_num; // SCL channel, mapping to master 1 or 2
|
||||
u8 sda_num; /* SDA channel number */
|
||||
u8 scl_num; /* SCL channel, mapping to master 1 or 2 */
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@ -48,11 +48,11 @@ static int rtl9300_i2c_mux_select(struct i2c_mux_core *muxc, u32 chan)
|
||||
{
|
||||
struct rtl9300_mux *mux = i2c_mux_priv(muxc);
|
||||
|
||||
// Set SCL pin
|
||||
/* Set SCL pin */
|
||||
REG_MASK(channels[chan].scl_num, 0,
|
||||
BIT(RTL9300_I2C_CTRL1_GPIO8_SCL_SEL), RTL9300_I2C_CTRL1);
|
||||
|
||||
// Set SDA pin
|
||||
/* Set SDA pin */
|
||||
REG_MASK(channels[chan].scl_num, 0x7 << RTL9300_I2C_CTRL1_SDA_OUT_SEL,
|
||||
channels[chan].sda_num << RTL9300_I2C_CTRL1_SDA_OUT_SEL, RTL9300_I2C_CTRL1);
|
||||
|
||||
@ -66,11 +66,11 @@ static int rtl9310_i2c_mux_select(struct i2c_mux_core *muxc, u32 chan)
|
||||
{
|
||||
struct rtl9300_mux *mux = i2c_mux_priv(muxc);
|
||||
|
||||
// Set SCL pin
|
||||
/* Set SCL pin */
|
||||
REG_MASK(0, 0, BIT(RTL9310_I2C_MST_IF_SEL_GPIO_SCL_SEL + channels[chan].scl_num),
|
||||
RTL9310_I2C_MST_IF_SEL);
|
||||
|
||||
// Set SDA pin
|
||||
/* Set SDA pin */
|
||||
REG_MASK(channels[chan].scl_num, 0xf << RTL9310_I2C_CTRL_SDA_OUT_SEL,
|
||||
channels[chan].sda_num << RTL9310_I2C_CTRL_SDA_OUT_SEL, RTL9310_I2C_CTRL);
|
||||
|
||||
@ -90,7 +90,7 @@ static void rtl9300_sda_sel(struct i2c_mux_core *muxc, int pin)
|
||||
struct rtl9300_mux *mux = i2c_mux_priv(muxc);
|
||||
u32 v;
|
||||
|
||||
// Set SDA pin to I2C functionality
|
||||
/* Set SDA pin to I2C functionality */
|
||||
v = readl(REG(0, RTL9300_I2C_MST_GLB_CTRL));
|
||||
v |= BIT(pin);
|
||||
writel(v, REG(0, RTL9300_I2C_MST_GLB_CTRL));
|
||||
@ -101,7 +101,7 @@ static void rtl9310_sda_sel(struct i2c_mux_core *muxc, int pin)
|
||||
struct rtl9300_mux *mux = i2c_mux_priv(muxc);
|
||||
u32 v;
|
||||
|
||||
// Set SDA pin to I2C functionality
|
||||
/* Set SDA pin to I2C functionality */
|
||||
v = readl(REG(0, RTL9310_I2C_MST_IF_SEL));
|
||||
v |= BIT(pin);
|
||||
writel(v, REG(0, RTL9310_I2C_MST_IF_SEL));
|
||||
@ -123,8 +123,8 @@ static struct device_node *mux_parent_adapter(struct device *dev, struct rtl9300
|
||||
if (!parent)
|
||||
return ERR_PTR(-EPROBE_DEFER);
|
||||
|
||||
if (!(of_device_is_compatible(parent_np, "realtek,rtl9300-i2c")
|
||||
|| of_device_is_compatible(parent_np, "realtek,rtl9310-i2c"))){
|
||||
if (!(of_device_is_compatible(parent_np, "realtek,rtl9300-i2c") ||
|
||||
of_device_is_compatible(parent_np, "realtek,rtl9310-i2c"))){
|
||||
dev_err(dev, "I2C parent not an RTL9300 I2C controller\n");
|
||||
return ERR_PTR(-ENODEV);
|
||||
}
|
||||
@ -147,7 +147,7 @@ struct i2c_mux_data rtl9300_i2c_mux_data = {
|
||||
};
|
||||
|
||||
struct i2c_mux_data rtl9310_i2c_mux_data = {
|
||||
.scl0_pin = 13,
|
||||
.scl0_pin = 13,
|
||||
.scl1_pin = 14,
|
||||
.sda0_pin = 0,
|
||||
.sda_pins = 16,
|
||||
@ -177,7 +177,7 @@ static int rtl9300_i2c_mux_probe(struct platform_device *pdev)
|
||||
int ret;
|
||||
|
||||
pr_info("%s probing I2C adapter\n", __func__);
|
||||
|
||||
|
||||
if (!node) {
|
||||
dev_err(dev, "No DT found\n");
|
||||
return -EINVAL;
|
||||
|
||||
@ -5,4 +5,3 @@ config NET_DSA_RTL83XX
|
||||
select NET_DSA_TAG_TRAILER
|
||||
help
|
||||
This driver adds support for Realtek RTL83xx series switching.
|
||||
|
||||
|
||||
@ -9,8 +9,8 @@
|
||||
#include <linux/inetdevice.h>
|
||||
#include <linux/rhashtable.h>
|
||||
#include <linux/of_net.h>
|
||||
|
||||
#include <asm/mach-rtl838x/mach-rtl83xx.h>
|
||||
|
||||
#include "rtl83xx.h"
|
||||
|
||||
extern struct rtl83xx_soc_info soc_info;
|
||||
@ -58,40 +58,37 @@ int rtl83xx_port_get_stp_state(struct rtl838x_switch_priv *priv, int port)
|
||||
}
|
||||
|
||||
static struct table_reg rtl838x_tbl_regs[] = {
|
||||
TBL_DESC(0x6900, 0x6908, 3, 15, 13, 1), // RTL8380_TBL_L2
|
||||
TBL_DESC(0x6914, 0x6918, 18, 14, 12, 1), // RTL8380_TBL_0
|
||||
TBL_DESC(0xA4C8, 0xA4CC, 6, 14, 12, 1), // RTL8380_TBL_1
|
||||
TBL_DESC(0x6900, 0x6908, 3, 15, 13, 1), /* RTL8380_TBL_L2 */
|
||||
TBL_DESC(0x6914, 0x6918, 18, 14, 12, 1), /* RTL8380_TBL_0 */
|
||||
TBL_DESC(0xA4C8, 0xA4CC, 6, 14, 12, 1), /* RTL8380_TBL_1 */
|
||||
|
||||
TBL_DESC(0x1180, 0x1184, 3, 16, 14, 0), // RTL8390_TBL_L2
|
||||
TBL_DESC(0x1190, 0x1194, 17, 15, 12, 0), // RTL8390_TBL_0
|
||||
TBL_DESC(0x6B80, 0x6B84, 4, 14, 12, 0), // RTL8390_TBL_1
|
||||
TBL_DESC(0x611C, 0x6120, 9, 8, 6, 0), // RTL8390_TBL_2
|
||||
TBL_DESC(0x1180, 0x1184, 3, 16, 14, 0), /* RTL8390_TBL_L2 */
|
||||
TBL_DESC(0x1190, 0x1194, 17, 15, 12, 0), /* RTL8390_TBL_0 */
|
||||
TBL_DESC(0x6B80, 0x6B84, 4, 14, 12, 0), /* RTL8390_TBL_1 */
|
||||
TBL_DESC(0x611C, 0x6120, 9, 8, 6, 0), /* RTL8390_TBL_2 */
|
||||
|
||||
TBL_DESC(0xB320, 0xB334, 3, 18, 16, 0), // RTL9300_TBL_L2
|
||||
TBL_DESC(0xB340, 0xB344, 19, 16, 12, 0), // RTL9300_TBL_0
|
||||
TBL_DESC(0xB3A0, 0xB3A4, 20, 16, 13, 0), // RTL9300_TBL_1
|
||||
TBL_DESC(0xCE04, 0xCE08, 6, 14, 12, 0), // RTL9300_TBL_2
|
||||
TBL_DESC(0xD600, 0xD604, 30, 7, 6, 0), // RTL9300_TBL_HSB
|
||||
TBL_DESC(0x7880, 0x7884, 22, 9, 8, 0), // RTL9300_TBL_HSA
|
||||
TBL_DESC(0xB320, 0xB334, 3, 18, 16, 0), /* RTL9300_TBL_L2 */
|
||||
TBL_DESC(0xB340, 0xB344, 19, 16, 12, 0), /* RTL9300_TBL_0 */
|
||||
TBL_DESC(0xB3A0, 0xB3A4, 20, 16, 13, 0), /* RTL9300_TBL_1 */
|
||||
TBL_DESC(0xCE04, 0xCE08, 6, 14, 12, 0), /* RTL9300_TBL_2 */
|
||||
TBL_DESC(0xD600, 0xD604, 30, 7, 6, 0), /* RTL9300_TBL_HSB */
|
||||
TBL_DESC(0x7880, 0x7884, 22, 9, 8, 0), /* RTL9300_TBL_HSA */
|
||||
|
||||
TBL_DESC(0x8500, 0x8508, 8, 19, 15, 0), // RTL9310_TBL_0
|
||||
TBL_DESC(0x40C0, 0x40C4, 22, 16, 14, 0), // RTL9310_TBL_1
|
||||
TBL_DESC(0x8528, 0x852C, 6, 18, 14, 0), // RTL9310_TBL_2
|
||||
TBL_DESC(0x0200, 0x0204, 9, 15, 12, 0), // RTL9310_TBL_3
|
||||
TBL_DESC(0x20dc, 0x20e0, 29, 7, 6, 0), // RTL9310_TBL_4
|
||||
TBL_DESC(0x7e1c, 0x7e20, 53, 8, 6, 0), // RTL9310_TBL_5
|
||||
TBL_DESC(0x8500, 0x8508, 8, 19, 15, 0), /* RTL9310_TBL_0 */
|
||||
TBL_DESC(0x40C0, 0x40C4, 22, 16, 14, 0), /* RTL9310_TBL_1 */
|
||||
TBL_DESC(0x8528, 0x852C, 6, 18, 14, 0), /* RTL9310_TBL_2 */
|
||||
TBL_DESC(0x0200, 0x0204, 9, 15, 12, 0), /* RTL9310_TBL_3 */
|
||||
TBL_DESC(0x20dc, 0x20e0, 29, 7, 6, 0), /* RTL9310_TBL_4 */
|
||||
TBL_DESC(0x7e1c, 0x7e20, 53, 8, 6, 0), /* RTL9310_TBL_5 */
|
||||
};
|
||||
|
||||
void rtl_table_init(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < RTL_TBL_END; i++)
|
||||
for (int i = 0; i < RTL_TBL_END; i++)
|
||||
mutex_init(&rtl838x_tbl_regs[i].lock);
|
||||
}
|
||||
|
||||
/*
|
||||
* Request access to table t in table access register r
|
||||
/* Request access to table t in table access register r
|
||||
* Returns a handle to a lock for that table
|
||||
*/
|
||||
struct table_reg *rtl_table_get(rtl838x_tbl_reg_t r, int t)
|
||||
@ -108,45 +105,55 @@ struct table_reg *rtl_table_get(rtl838x_tbl_reg_t r, int t)
|
||||
return &rtl838x_tbl_regs[r];
|
||||
}
|
||||
|
||||
/*
|
||||
* Release a table r, unlock the corresponding lock
|
||||
*/
|
||||
/* Release a table r, unlock the corresponding lock */
|
||||
void rtl_table_release(struct table_reg *r)
|
||||
{
|
||||
if (!r)
|
||||
return;
|
||||
|
||||
// pr_info("Unlocking %08x\n", (u32)r);
|
||||
/* pr_info("Unlocking %08x\n", (u32)r); */
|
||||
mutex_unlock(&r->lock);
|
||||
// pr_info("Unlock done\n");
|
||||
/* pr_info("Unlock done\n"); */
|
||||
}
|
||||
|
||||
/*
|
||||
* Reads table index idx into the data registers of the table
|
||||
*/
|
||||
void rtl_table_read(struct table_reg *r, int idx)
|
||||
static int rtl_table_exec(struct table_reg *r, bool is_write, int idx)
|
||||
{
|
||||
u32 cmd = r->rmode ? BIT(r->c_bit) : 0;
|
||||
int ret = 0;
|
||||
u32 cmd, val;
|
||||
|
||||
/* Read/write bit has inverted meaning on RTL838x */
|
||||
if (r->rmode)
|
||||
cmd = is_write ? 0 : BIT(r->c_bit);
|
||||
else
|
||||
cmd = is_write ? BIT(r->c_bit) : 0;
|
||||
|
||||
cmd |= BIT(r->c_bit + 1); /* Execute bit */
|
||||
cmd |= r->tbl << r->t_bit; /* Table type */
|
||||
cmd |= idx & (BIT(r->t_bit) - 1); /* Index */
|
||||
|
||||
cmd |= BIT(r->c_bit + 1) | (r->tbl << r->t_bit) | (idx & (BIT(r->t_bit) - 1));
|
||||
sw_w32(cmd, r->addr);
|
||||
do { } while (sw_r32(r->addr) & BIT(r->c_bit + 1));
|
||||
|
||||
ret = readx_poll_timeout(sw_r32, r->addr, val,
|
||||
!(val & BIT(r->c_bit + 1)), 20, 10000);
|
||||
if (ret)
|
||||
pr_err("%s: timeout\n", __func__);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Writes the content of the table data registers into the table at index idx
|
||||
*/
|
||||
void rtl_table_write(struct table_reg *r, int idx)
|
||||
/* Reads table index idx into the data registers of the table */
|
||||
int rtl_table_read(struct table_reg *r, int idx)
|
||||
{
|
||||
u32 cmd = r->rmode ? 0 : BIT(r->c_bit);
|
||||
|
||||
cmd |= BIT(r->c_bit + 1) | (r->tbl << r->t_bit) | (idx & (BIT(r->t_bit) - 1));
|
||||
sw_w32(cmd, r->addr);
|
||||
do { } while (sw_r32(r->addr) & BIT(r->c_bit + 1));
|
||||
return rtl_table_exec(r, false, idx);
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the address of the ith data register of table register r
|
||||
/* Writes the content of the table data registers into the table at index idx */
|
||||
int rtl_table_write(struct table_reg *r, int idx)
|
||||
{
|
||||
return rtl_table_exec(r, true, idx);
|
||||
}
|
||||
|
||||
/* Returns the address of the ith data register of table register r
|
||||
* the address is relative to the beginning of the Switch-IO block at 0xbb000000
|
||||
*/
|
||||
inline u16 rtl_table_data(struct table_reg *r, int i)
|
||||
@ -179,7 +186,7 @@ void rtl838x_set_port_reg(u64 set, int reg)
|
||||
|
||||
u64 rtl838x_get_port_reg(int reg)
|
||||
{
|
||||
return ((u64) sw_r32(reg));
|
||||
return ((u64)sw_r32(reg));
|
||||
}
|
||||
|
||||
/* Port register accessor functions for the RTL839x and RTL931X SoCs */
|
||||
@ -195,6 +202,7 @@ u64 rtl839x_get_port_reg_be(int reg)
|
||||
|
||||
v <<= 32;
|
||||
v |= sw_r32(reg + 4);
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
@ -222,6 +230,7 @@ u64 rtl839x_get_port_reg_le(int reg)
|
||||
|
||||
v <<= 32;
|
||||
v |= sw_r32(reg);
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
@ -237,6 +246,7 @@ int read_phy(u32 port, u32 page, u32 reg, u32 *val)
|
||||
case RTL9310_FAMILY_ID:
|
||||
return rtl931x_read_phy(port, page, reg, val);
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -252,6 +262,7 @@ int write_phy(u32 port, u32 page, u32 reg, u32 val)
|
||||
case RTL9310_FAMILY_ID:
|
||||
return rtl931x_write_phy(port, page, reg, val);
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -286,8 +297,7 @@ static int __init rtl83xx_mdio_probe(struct rtl838x_switch_priv *priv)
|
||||
|
||||
bus->name = "rtl838x slave mii";
|
||||
|
||||
/*
|
||||
* Since the NIC driver is loaded first, we can use the mdio rw functions
|
||||
/* Since the NIC driver is loaded first, we can use the mdio rw functions
|
||||
* assigned there.
|
||||
*/
|
||||
bus->read = priv->mii_bus->read;
|
||||
@ -323,7 +333,6 @@ static int __init rtl83xx_mdio_probe(struct rtl838x_switch_priv *priv)
|
||||
if (of_property_read_u32(dn, "reg", &pn))
|
||||
continue;
|
||||
|
||||
pr_info("%s found port %d\n", __func__, pn);
|
||||
phy_node = of_parse_phandle(dn, "phy-handle", 0);
|
||||
if (!phy_node) {
|
||||
if (pn != priv->cpu_port)
|
||||
@ -331,14 +340,9 @@ static int __init rtl83xx_mdio_probe(struct rtl838x_switch_priv *priv)
|
||||
continue;
|
||||
}
|
||||
|
||||
pr_info("%s port %d has phandle\n", __func__, pn);
|
||||
if (of_property_read_u32(phy_node, "sds", &priv->ports[pn].sds_num))
|
||||
priv->ports[pn].sds_num = -1;
|
||||
else {
|
||||
pr_info("%s sds port %d is %d\n", __func__, pn,
|
||||
priv->ports[pn].sds_num);
|
||||
}
|
||||
pr_info("%s port %d has SDS\n", __func__, priv->ports[pn].sds_num);
|
||||
pr_debug("%s port %d has SDS %d\n", __func__, pn, priv->ports[pn].sds_num);
|
||||
|
||||
if (of_get_phy_mode(dn, &interface))
|
||||
interface = PHY_INTERFACE_MODE_NA;
|
||||
@ -353,7 +357,7 @@ static int __init rtl83xx_mdio_probe(struct rtl838x_switch_priv *priv)
|
||||
led_set = 0;
|
||||
priv->ports[pn].led_set = led_set;
|
||||
|
||||
// Check for the integrated SerDes of the RTL8380M first
|
||||
/* Check for the integrated SerDes of the RTL8380M first */
|
||||
if (of_property_read_bool(phy_node, "phy-is-integrated")
|
||||
&& priv->id == 0x8380 && pn >= 24) {
|
||||
pr_debug("----> FÓUND A SERDES\n");
|
||||
@ -368,21 +372,21 @@ static int __init rtl83xx_mdio_probe(struct rtl838x_switch_priv *priv)
|
||||
priv->ports[pn].phy = PHY_RTL930X_SDS;
|
||||
}
|
||||
} else {
|
||||
if (of_property_read_bool(phy_node, "phy-is-integrated")
|
||||
&& !of_property_read_bool(phy_node, "sfp")) {
|
||||
if (of_property_read_bool(phy_node, "phy-is-integrated") &&
|
||||
!of_property_read_bool(phy_node, "sfp")) {
|
||||
priv->ports[pn].phy = PHY_RTL8218B_INT;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (!of_property_read_bool(phy_node, "phy-is-integrated")
|
||||
&& of_property_read_bool(phy_node, "sfp")) {
|
||||
if (!of_property_read_bool(phy_node, "phy-is-integrated") &&
|
||||
of_property_read_bool(phy_node, "sfp")) {
|
||||
priv->ports[pn].phy = PHY_RTL8214FC;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!of_property_read_bool(phy_node, "phy-is-integrated")
|
||||
&& !of_property_read_bool(phy_node, "sfp")) {
|
||||
if (!of_property_read_bool(phy_node, "phy-is-integrated") &&
|
||||
!of_property_read_bool(phy_node, "sfp")) {
|
||||
priv->ports[pn].phy = PHY_RTL8218B_EXT;
|
||||
continue;
|
||||
}
|
||||
@ -408,6 +412,7 @@ static int __init rtl83xx_mdio_probe(struct rtl838x_switch_priv *priv)
|
||||
}
|
||||
|
||||
pr_debug("%s done\n", __func__);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -424,6 +429,7 @@ static int __init rtl83xx_get_l2aging(struct rtl838x_switch_priv *priv)
|
||||
|
||||
pr_debug("L2 AGING time: %d sec\n", t);
|
||||
pr_debug("Dynamic aging for ports: %x\n", sw_r32(priv->r->l2_port_aging_out));
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
@ -458,6 +464,7 @@ int rtl83xx_lag_add(struct dsa_switch *ds, int group, int port, struct netdev_la
|
||||
pr_err("%s: Port %d already member of LAG %d.\n", __func__, port, i);
|
||||
return -ENOSPC;
|
||||
}
|
||||
|
||||
switch(info->hash_type) {
|
||||
case NETDEV_LAG_HASH_L2:
|
||||
algomsk |= TRUNK_DISTRIBUTION_ALGO_DMAC_BIT;
|
||||
@ -466,15 +473,15 @@ int rtl83xx_lag_add(struct dsa_switch *ds, int group, int port, struct netdev_la
|
||||
case NETDEV_LAG_HASH_L23:
|
||||
algomsk |= TRUNK_DISTRIBUTION_ALGO_DMAC_BIT;
|
||||
algomsk |= TRUNK_DISTRIBUTION_ALGO_SMAC_BIT;
|
||||
algomsk |= TRUNK_DISTRIBUTION_ALGO_SIP_BIT; //source ip
|
||||
algomsk |= TRUNK_DISTRIBUTION_ALGO_DIP_BIT; //dest ip
|
||||
algomsk |= TRUNK_DISTRIBUTION_ALGO_SIP_BIT; /* source ip */
|
||||
algomsk |= TRUNK_DISTRIBUTION_ALGO_DIP_BIT; /* dest ip */
|
||||
algoidx = 1;
|
||||
break;
|
||||
case NETDEV_LAG_HASH_L34:
|
||||
algomsk |= TRUNK_DISTRIBUTION_ALGO_SRC_L4PORT_BIT; //sport
|
||||
algomsk |= TRUNK_DISTRIBUTION_ALGO_DST_L4PORT_BIT; //dport
|
||||
algomsk |= TRUNK_DISTRIBUTION_ALGO_SIP_BIT; //source ip
|
||||
algomsk |= TRUNK_DISTRIBUTION_ALGO_DIP_BIT; //dest ip
|
||||
algomsk |= TRUNK_DISTRIBUTION_ALGO_SRC_L4PORT_BIT; /* sport */
|
||||
algomsk |= TRUNK_DISTRIBUTION_ALGO_DST_L4PORT_BIT; /* dport */
|
||||
algomsk |= TRUNK_DISTRIBUTION_ALGO_SIP_BIT; /* source ip */
|
||||
algomsk |= TRUNK_DISTRIBUTION_ALGO_DIP_BIT; /* dest ip */
|
||||
algoidx = 2;
|
||||
break;
|
||||
default:
|
||||
@ -486,6 +493,7 @@ int rtl83xx_lag_add(struct dsa_switch *ds, int group, int port, struct netdev_la
|
||||
|
||||
pr_info("%s: Added port %d to LAG %d. Members now %016llx.\n",
|
||||
__func__, port, group, priv->lags_port_members[group]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -509,18 +517,17 @@ int rtl83xx_lag_del(struct dsa_switch *ds, int group, int port)
|
||||
return -ENOSPC;
|
||||
}
|
||||
|
||||
// 0x7f algo mask all
|
||||
/* 0x7f algo mask all */
|
||||
priv->r->mask_port_reg_be(BIT_ULL(port), 0, priv->r->trk_mbr_ctr(group));
|
||||
priv->lags_port_members[group] &= ~BIT_ULL(port);
|
||||
|
||||
pr_info("%s: Removed port %d from LAG %d. Members now %016llx.\n",
|
||||
__func__, port, group, priv->lags_port_members[group]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate a 64 bit octet counter located in the LOG HW table
|
||||
*/
|
||||
/* Allocate a 64 bit octet counter located in the LOG HW table */
|
||||
static int rtl83xx_octet_cntr_alloc(struct rtl838x_switch_priv *priv)
|
||||
{
|
||||
int idx;
|
||||
@ -539,8 +546,7 @@ static int rtl83xx_octet_cntr_alloc(struct rtl838x_switch_priv *priv)
|
||||
return idx;
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate a 32-bit packet counter
|
||||
/* Allocate a 32-bit packet counter
|
||||
* 2 32-bit packet counters share the location of a 64-bit octet counter
|
||||
* Initially there are no free packet counters and 2 new ones need to be freed
|
||||
* by allocating the corresponding octet counter
|
||||
@ -574,8 +580,7 @@ int rtl83xx_packet_cntr_alloc(struct rtl838x_switch_priv *priv)
|
||||
return idx;
|
||||
}
|
||||
|
||||
/*
|
||||
* Add an L2 nexthop entry for the L3 routing system / PIE forwarding in the SoC
|
||||
/* Add an L2 nexthop entry for the L3 routing system / PIE forwarding in the SoC
|
||||
* Use VID and MAC in rtl838x_l2_entry to identify either a free slot in the L2 hash table
|
||||
* or mark an existing entry as a nexthop by setting it's nexthop bit
|
||||
* Called from the L3 layer
|
||||
@ -586,7 +591,7 @@ int rtl83xx_l2_nexthop_add(struct rtl838x_switch_priv *priv, struct rtl83xx_next
|
||||
struct rtl838x_l2_entry e;
|
||||
u64 seed = priv->r->l2_hash_seed(nh->mac, nh->rvid);
|
||||
u32 key = priv->r->l2_hash_key(priv, seed);
|
||||
int i, idx = -1;
|
||||
int idx = -1;
|
||||
u64 entry;
|
||||
|
||||
pr_debug("%s searching for %08llx vid %d with key %d, seed: %016llx\n",
|
||||
@ -596,8 +601,8 @@ int rtl83xx_l2_nexthop_add(struct rtl838x_switch_priv *priv, struct rtl83xx_next
|
||||
u64_to_ether_addr(nh->mac, &e.mac[0]);
|
||||
e.port = nh->port;
|
||||
|
||||
// Loop over all entries in the hash-bucket and over the second block on 93xx SoCs
|
||||
for (i = 0; i < priv->l2_bucket_size; i++) {
|
||||
/* Loop over all entries in the hash-bucket and over the second block on 93xx SoCs */
|
||||
for (int i = 0; i < priv->l2_bucket_size; i++) {
|
||||
entry = priv->r->read_l2_entry_using_hash(key, i, &e);
|
||||
|
||||
if (!e.valid || ((entry & 0x0fffffffffffffffULL) == seed)) {
|
||||
@ -612,14 +617,14 @@ int rtl83xx_l2_nexthop_add(struct rtl838x_switch_priv *priv, struct rtl83xx_next
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Found an existing (e->valid is true) or empty entry, make it a nexthop entry
|
||||
/* Found an existing (e->valid is true) or empty entry, make it a nexthop entry */
|
||||
nh->l2_id = idx;
|
||||
if (e.valid) {
|
||||
nh->port = e.port;
|
||||
nh->vid = e.vid; // Save VID
|
||||
nh->vid = e.vid; /* Save VID */
|
||||
nh->rvid = e.rvid;
|
||||
nh->dev_id = e.stack_dev;
|
||||
// If the entry is already a valid next hop entry, don't change it
|
||||
/* If the entry is already a valid next hop entry, don't change it */
|
||||
if (e.next_hop)
|
||||
return 0;
|
||||
} else {
|
||||
@ -631,12 +636,12 @@ int rtl83xx_l2_nexthop_add(struct rtl838x_switch_priv *priv, struct rtl83xx_next
|
||||
e.block_da = false;
|
||||
e.block_sa = false;
|
||||
e.suspended = false;
|
||||
e.age = 0; // With port-ignore
|
||||
e.age = 0; /* With port-ignore */
|
||||
e.port = priv->port_ignore;
|
||||
u64_to_ether_addr(nh->mac, &e.mac[0]);
|
||||
}
|
||||
e.next_hop = true;
|
||||
e.nh_route_id = nh->id; // NH route ID takes place of VID
|
||||
e.nh_route_id = nh->id; /* NH route ID takes place of VID */
|
||||
e.nh_vlan_target = false;
|
||||
|
||||
priv->r->write_l2_entry_using_hash(idx >> 2, idx & 0x3, &e);
|
||||
@ -644,8 +649,7 @@ int rtl83xx_l2_nexthop_add(struct rtl838x_switch_priv *priv, struct rtl83xx_next
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Removes a Layer 2 next hop entry in the forwarding database
|
||||
/* Removes a Layer 2 next hop entry in the forwarding database
|
||||
* If it was static, the entire entry is removed, otherwise the nexthop bit is cleared
|
||||
* and we wait until the entry ages out
|
||||
*/
|
||||
@ -665,7 +669,7 @@ int rtl83xx_l2_nexthop_rm(struct rtl838x_switch_priv *priv, struct rtl83xx_nexth
|
||||
if (e.is_static)
|
||||
e.valid = false;
|
||||
e.next_hop = false;
|
||||
e.vid = nh->vid; // Restore VID
|
||||
e.vid = nh->vid; /* Restore VID */
|
||||
e.rvid = nh->rvid;
|
||||
|
||||
priv->r->write_l2_entry_using_hash(key, i, &e);
|
||||
@ -722,30 +726,30 @@ static int rtl83xx_handle_changeupper(struct rtl838x_switch_priv *priv,
|
||||
|
||||
out:
|
||||
mutex_unlock(&priv->reg_mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Is the lower network device a DSA slave network device of our RTL930X-switch?
|
||||
/* Is the lower network device a DSA slave network device of our RTL930X-switch?
|
||||
* Unfortunately we cannot just follow dev->dsa_prt as this is only set for the
|
||||
* DSA master device.
|
||||
*/
|
||||
int rtl83xx_port_is_under(const struct net_device * dev, struct rtl838x_switch_priv *priv)
|
||||
{
|
||||
int i;
|
||||
/* TODO: On 5.12:
|
||||
* if(!dsa_slave_dev_check(dev)) {
|
||||
* netdev_info(dev, "%s: not a DSA device.\n", __func__);
|
||||
* return -EINVAL;
|
||||
* }
|
||||
*/
|
||||
|
||||
// TODO: On 5.12:
|
||||
// if(!dsa_slave_dev_check(dev)) {
|
||||
// netdev_info(dev, "%s: not a DSA device.\n", __func__);
|
||||
// return -EINVAL;
|
||||
// }
|
||||
|
||||
for (i = 0; i < priv->cpu_port; i++) {
|
||||
for (int i = 0; i < priv->cpu_port; i++) {
|
||||
if (!priv->ports[i].dp)
|
||||
continue;
|
||||
if (priv->ports[i].dp->slave == dev)
|
||||
return i;
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@ -780,9 +784,7 @@ const static struct rhashtable_params route_ht_params = {
|
||||
.head_offset = offsetof(struct rtl83xx_route, linkage),
|
||||
};
|
||||
|
||||
/*
|
||||
* Updates an L3 next hop entry in the ROUTING table
|
||||
*/
|
||||
/* Updates an L3 next hop entry in the ROUTING table */
|
||||
static int rtl83xx_l3_nexthop_update(struct rtl838x_switch_priv *priv, __be32 ip_addr, u64 mac)
|
||||
{
|
||||
struct rtl83xx_route *r;
|
||||
@ -799,7 +801,7 @@ static int rtl83xx_l3_nexthop_update(struct rtl838x_switch_priv *priv, __be32 i
|
||||
pr_info("%s: Setting up fwding: ip %pI4, GW mac %016llx\n",
|
||||
__func__, &ip_addr, mac);
|
||||
|
||||
// Reads the ROUTING table entry associated with the route
|
||||
/* Reads the ROUTING table entry associated with the route */
|
||||
priv->r->route_read(r->id, r);
|
||||
pr_info("Route with id %d to %pI4 / %d\n", r->id, &r->dst_ip, r->prefix_len);
|
||||
|
||||
@ -807,19 +809,19 @@ static int rtl83xx_l3_nexthop_update(struct rtl838x_switch_priv *priv, __be32 i
|
||||
r->nh.port = priv->port_ignore;
|
||||
r->nh.id = r->id;
|
||||
|
||||
// Do we need to explicitly add a DMAC entry with the route's nh index?
|
||||
/* Do we need to explicitly add a DMAC entry with the route's nh index? */
|
||||
if (priv->r->set_l3_egress_mac)
|
||||
priv->r->set_l3_egress_mac(r->id, mac);
|
||||
|
||||
// Update ROUTING table: map gateway-mac and switch-mac id to route id
|
||||
/* Update ROUTING table: map gateway-mac and switch-mac id to route id */
|
||||
rtl83xx_l2_nexthop_add(priv, &r->nh);
|
||||
|
||||
r->attr.valid = true;
|
||||
r->attr.action = ROUTE_ACT_FORWARD;
|
||||
r->attr.type = 0;
|
||||
r->attr.hit = false; // Reset route-used indicator
|
||||
r->attr.hit = false; /* Reset route-used indicator */
|
||||
|
||||
// Add PIE entry with dst_ip and prefix_len
|
||||
/* Add PIE entry with dst_ip and prefix_len */
|
||||
r->pr.dip = r->dst_ip;
|
||||
r->pr.dip_m = inet_make_mask(r->prefix_len);
|
||||
|
||||
@ -854,6 +856,7 @@ static int rtl83xx_l3_nexthop_update(struct rtl838x_switch_priv *priv, __be32 i
|
||||
}
|
||||
}
|
||||
rcu_read_unlock();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -884,6 +887,7 @@ static int rtl83xx_port_ipv4_resolve(struct rtl838x_switch_priv *priv,
|
||||
}
|
||||
|
||||
neigh_release(n);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
@ -941,7 +945,7 @@ static struct rtl83xx_route *rtl83xx_route_alloc(struct rtl838x_switch_priv *pri
|
||||
|
||||
r->id = idx;
|
||||
r->gw_ip = ip;
|
||||
r->pr.id = -1; // We still need to allocate a rule in HW
|
||||
r->pr.id = -1; /* We still need to allocate a rule in HW */
|
||||
r->is_host_route = false;
|
||||
|
||||
err = rhltable_insert(&priv->routes, &r->linkage, route_ht_params);
|
||||
@ -959,6 +963,7 @@ static struct rtl83xx_route *rtl83xx_route_alloc(struct rtl838x_switch_priv *pri
|
||||
|
||||
out_free:
|
||||
kfree(r);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -980,11 +985,12 @@ static struct rtl83xx_route *rtl83xx_host_route_alloc(struct rtl838x_switch_priv
|
||||
}
|
||||
|
||||
/* We require a unique route ID irrespective of whether it is a prefix or host
|
||||
* route (on RTL93xx) as we use this ID to associate a DMAC and next-hop entry */
|
||||
* route (on RTL93xx) as we use this ID to associate a DMAC and next-hop entry
|
||||
*/
|
||||
r->id = idx + MAX_ROUTES;
|
||||
|
||||
r->gw_ip = ip;
|
||||
r->pr.id = -1; // We still need to allocate a rule in HW
|
||||
r->pr.id = -1; /* We still need to allocate a rule in HW */
|
||||
r->is_host_route = true;
|
||||
|
||||
err = rhltable_insert(&priv->routes, &r->linkage, route_ht_params);
|
||||
@ -1002,6 +1008,7 @@ static struct rtl83xx_route *rtl83xx_host_route_alloc(struct rtl838x_switch_priv
|
||||
|
||||
out_free:
|
||||
kfree(r);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -1021,7 +1028,7 @@ static void rtl83xx_route_rm(struct rtl838x_switch_priv *priv, struct rtl83xx_ro
|
||||
priv->r->host_route_write(id, r);
|
||||
clear_bit(r->id - MAX_ROUTES, priv->host_route_use_bm);
|
||||
} else {
|
||||
// If there is a HW representation of the route, delete it
|
||||
/* If there is a HW representation of the route, delete it */
|
||||
if (priv->r->route_lookup_hw) {
|
||||
id = priv->r->route_lookup_hw(r);
|
||||
pr_info("%s: Got id for prefix route: %d\n", __func__, id);
|
||||
@ -1071,17 +1078,16 @@ static int rtl83xx_fib4_del(struct rtl838x_switch_priv *priv,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* On the RTL93xx, an L3 termination endpoint MAC address on which the router waits
|
||||
/* On the RTL93xx, an L3 termination endpoint MAC address on which the router waits
|
||||
* for packets to be routed needs to be allocated.
|
||||
*/
|
||||
static int rtl83xx_alloc_router_mac(struct rtl838x_switch_priv *priv, u64 mac)
|
||||
{
|
||||
int i, free_mac = -1;
|
||||
int free_mac = -1;
|
||||
struct rtl93xx_rt_mac m;
|
||||
|
||||
mutex_lock(&priv->reg_mutex);
|
||||
for (i = 0; i < MAX_ROUTER_MACS; i++) {
|
||||
for (int i = 0; i < MAX_ROUTER_MACS; i++) {
|
||||
priv->r->get_l3_router_mac(i, &m);
|
||||
if (free_mac < 0 && !m.valid) {
|
||||
free_mac = i;
|
||||
@ -1101,13 +1107,13 @@ static int rtl83xx_alloc_router_mac(struct rtl838x_switch_priv *priv, u64 mac)
|
||||
|
||||
m.valid = true;
|
||||
m.mac = mac;
|
||||
m.p_type = 0; // An individual port, not a trunk port
|
||||
m.p_id = 0x3f; // Listen on any port
|
||||
m.p_type = 0; /* An individual port, not a trunk port */
|
||||
m.p_id = 0x3f; /* Listen on any port */
|
||||
m.p_id_mask = 0;
|
||||
m.vid = 0; // Listen on any VLAN...
|
||||
m.vid_mask = 0; // ... so mask needs to be 0
|
||||
m.mac_mask = 0xffffffffffffULL; // We want an exact match of the interface MAC
|
||||
m.action = L3_FORWARD; // Route the packet
|
||||
m.vid = 0; /* Listen on any VLAN... */
|
||||
m.vid_mask = 0; /* ... so mask needs to be 0 */
|
||||
m.mac_mask = 0xffffffffffffULL; /* We want an exact match of the interface MAC */
|
||||
m.action = L3_FORWARD; /* Route the packet */
|
||||
priv->r->set_l3_router_mac(free_mac, &m);
|
||||
|
||||
mutex_unlock(&priv->reg_mutex);
|
||||
@ -1117,12 +1123,12 @@ static int rtl83xx_alloc_router_mac(struct rtl838x_switch_priv *priv, u64 mac)
|
||||
|
||||
static int rtl83xx_alloc_egress_intf(struct rtl838x_switch_priv *priv, u64 mac, int vlan)
|
||||
{
|
||||
int i, free_mac = -1;
|
||||
int free_mac = -1;
|
||||
struct rtl838x_l3_intf intf;
|
||||
u64 m;
|
||||
|
||||
mutex_lock(&priv->reg_mutex);
|
||||
for (i = 0; i < MAX_SMACS; i++) {
|
||||
for (int i = 0; i < MAX_SMACS; i++) {
|
||||
m = priv->r->get_l3_egress_mac(L3_EGRESS_DMACS + i);
|
||||
if (free_mac < 0 && !m) {
|
||||
free_mac = i;
|
||||
@ -1139,15 +1145,15 @@ static int rtl83xx_alloc_egress_intf(struct rtl838x_switch_priv *priv, u64 mac,
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Set up default egress interface 1
|
||||
/* Set up default egress interface 1 */
|
||||
intf.vid = vlan;
|
||||
intf.smac_idx = free_mac;
|
||||
intf.ip4_mtu_id = 1;
|
||||
intf.ip6_mtu_id = 1;
|
||||
intf.ttl_scope = 1; // TTL
|
||||
intf.hl_scope = 1; // Hop Limit
|
||||
intf.ip4_icmp_redirect = intf.ip6_icmp_redirect = 2; // FORWARD
|
||||
intf.ip4_pbr_icmp_redirect = intf.ip6_pbr_icmp_redirect = 2; // FORWARD;
|
||||
intf.ttl_scope = 1; /* TTL */
|
||||
intf.hl_scope = 1; /* Hop Limit */
|
||||
intf.ip4_icmp_redirect = intf.ip6_icmp_redirect = 2; /* FORWARD */
|
||||
intf.ip4_pbr_icmp_redirect = intf.ip6_pbr_icmp_redirect = 2; /* FORWARD; */
|
||||
priv->r->set_l3_egress_intf(free_mac, &intf);
|
||||
|
||||
priv->r->set_l3_egress_mac(L3_EGRESS_DMACS + free_mac, mac);
|
||||
@ -1181,22 +1187,22 @@ static int rtl83xx_fib4_add(struct rtl838x_switch_priv *priv,
|
||||
if (port < 0)
|
||||
return -1;
|
||||
|
||||
// For now we only work with routes that have a gateway and are not ourself
|
||||
// if ((!nh->fib_nh_gw4) && (info->dst_len != 32))
|
||||
// return 0;
|
||||
/* For now we only work with routes that have a gateway and are not ourself */
|
||||
/* if ((!nh->fib_nh_gw4) && (info->dst_len != 32)) */
|
||||
/* return 0; */
|
||||
|
||||
if ((info->dst & 0xff) == 0xff)
|
||||
return 0;
|
||||
|
||||
// Do not offload routes to 192.168.100.x
|
||||
/* Do not offload routes to 192.168.100.x */
|
||||
if ((info->dst & 0xffffff00) == 0xc0a86400)
|
||||
return 0;
|
||||
|
||||
// Do not offload routes to 127.x.x.x
|
||||
/* Do not offload routes to 127.x.x.x */
|
||||
if ((info->dst & 0xff000000) == 0x7f000000)
|
||||
return 0;
|
||||
|
||||
// Allocate route or host-route (entry if hardware supports this)
|
||||
/* Allocate route or host-route (entry if hardware supports this) */
|
||||
if (info->dst_len == 32 && priv->r->host_route_write)
|
||||
r = rtl83xx_host_route_alloc(priv, nh->fib_nh_gw4);
|
||||
else
|
||||
@ -1220,7 +1226,7 @@ static int rtl83xx_fib4_add(struct rtl838x_switch_priv *priv,
|
||||
if (rtl83xx_alloc_router_mac(priv, mac))
|
||||
goto out_free_rt;
|
||||
|
||||
// vid = 0: Do not care about VID
|
||||
/* vid = 0: Do not care about VID */
|
||||
r->nh.if_id = rtl83xx_alloc_egress_intf(priv, mac, vlan);
|
||||
if (r->nh.if_id < 0)
|
||||
goto out_free_rmac;
|
||||
@ -1240,7 +1246,7 @@ static int rtl83xx_fib4_add(struct rtl838x_switch_priv *priv,
|
||||
}
|
||||
}
|
||||
|
||||
// We need to resolve the mac address of the GW
|
||||
/* We need to resolve the mac address of the GW */
|
||||
if (!to_localhost)
|
||||
rtl83xx_port_ipv4_resolve(priv, dev, nh->fib_nh_gw4);
|
||||
|
||||
@ -1257,7 +1263,8 @@ static int rtl83xx_fib6_add(struct rtl838x_switch_priv *priv,
|
||||
struct fib6_entry_notifier_info *info)
|
||||
{
|
||||
pr_debug("In %s\n", __func__);
|
||||
// nh->fib_nh_flags |= RTNH_F_OFFLOAD;
|
||||
/* nh->fib_nh_flags |= RTNH_F_OFFLOAD; */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1441,7 +1448,7 @@ static int rtl83xx_fib_event(struct notifier_block *this, unsigned long event, v
|
||||
|
||||
static int __init rtl83xx_sw_probe(struct platform_device *pdev)
|
||||
{
|
||||
int err = 0, i;
|
||||
int err = 0;
|
||||
struct rtl838x_switch_priv *priv;
|
||||
struct device *dev = &pdev->dev;
|
||||
u64 bpdu_mask;
|
||||
@ -1452,7 +1459,7 @@ static int __init rtl83xx_sw_probe(struct platform_device *pdev)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
// Initialize access to RTL switch tables
|
||||
/* Initialize access to RTL switch tables */
|
||||
rtl_table_init();
|
||||
|
||||
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
|
||||
@ -1546,18 +1553,18 @@ static int __init rtl83xx_sw_probe(struct platform_device *pdev)
|
||||
*/
|
||||
return err;
|
||||
}
|
||||
|
||||
err = dsa_register_switch(priv->ds);
|
||||
if (err) {
|
||||
dev_err(dev, "Error registering switch: %d\n", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
/*
|
||||
* dsa_to_port returns dsa_port from the port list in
|
||||
/* dsa_to_port returns dsa_port from the port list in
|
||||
* dsa_switch_tree, the tree is built when the switch
|
||||
* is registered by dsa_register_switch
|
||||
*/
|
||||
for (i = 0; i <= priv->cpu_port; i++)
|
||||
for (int i = 0; i <= priv->cpu_port; i++)
|
||||
priv->ports[i].dp = dsa_to_port(priv->ds, i);
|
||||
|
||||
/* Enable link and media change interrupts. Are the SERDES masks needed? */
|
||||
@ -1571,19 +1578,19 @@ static int __init rtl83xx_sw_probe(struct platform_device *pdev)
|
||||
switch (priv->family_id) {
|
||||
case RTL8380_FAMILY_ID:
|
||||
err = request_irq(priv->link_state_irq, rtl838x_switch_irq,
|
||||
IRQF_SHARED, "rtl838x-link-state", priv->ds);
|
||||
IRQF_SHARED, "rtl838x-link-state", priv->ds);
|
||||
break;
|
||||
case RTL8390_FAMILY_ID:
|
||||
err = request_irq(priv->link_state_irq, rtl839x_switch_irq,
|
||||
IRQF_SHARED, "rtl839x-link-state", priv->ds);
|
||||
IRQF_SHARED, "rtl839x-link-state", priv->ds);
|
||||
break;
|
||||
case RTL9300_FAMILY_ID:
|
||||
err = request_irq(priv->link_state_irq, rtl930x_switch_irq,
|
||||
IRQF_SHARED, "rtl930x-link-state", priv->ds);
|
||||
IRQF_SHARED, "rtl930x-link-state", priv->ds);
|
||||
break;
|
||||
case RTL9310_FAMILY_ID:
|
||||
err = request_irq(priv->link_state_irq, rtl931x_switch_irq,
|
||||
IRQF_SHARED, "rtl931x-link-state", priv->ds);
|
||||
IRQF_SHARED, "rtl931x-link-state", priv->ds);
|
||||
break;
|
||||
}
|
||||
if (err) {
|
||||
@ -1602,12 +1609,10 @@ static int __init rtl83xx_sw_probe(struct platform_device *pdev)
|
||||
priv->r->l3_setup(priv);
|
||||
|
||||
/* Clear all destination ports for mirror groups */
|
||||
for (i = 0; i < 4; i++)
|
||||
for (int i = 0; i < 4; i++)
|
||||
priv->mirror_group_ports[i] = -1;
|
||||
|
||||
/*
|
||||
* Register netdevice event callback to catch changes in link aggregation groups
|
||||
*/
|
||||
/* Register netdevice event callback to catch changes in link aggregation groups */
|
||||
priv->nb.notifier_call = rtl83xx_netdevice_event;
|
||||
if (register_netdevice_notifier(&priv->nb)) {
|
||||
priv->nb.notifier_call = NULL;
|
||||
@ -1615,11 +1620,10 @@ static int __init rtl83xx_sw_probe(struct platform_device *pdev)
|
||||
goto err_register_nb;
|
||||
}
|
||||
|
||||
// Initialize hash table for L3 routing
|
||||
/* Initialize hash table for L3 routing */
|
||||
rhltable_init(&priv->routes, &route_ht_params);
|
||||
|
||||
/*
|
||||
* Register netevent notifier callback to catch notifications about neighboring
|
||||
/* Register netevent notifier callback to catch notifications about neighboring
|
||||
* changes to update nexthop entries for L3 routing.
|
||||
*/
|
||||
priv->ne_nb.notifier_call = rtl83xx_netevent_event;
|
||||
@ -1631,8 +1635,7 @@ static int __init rtl83xx_sw_probe(struct platform_device *pdev)
|
||||
|
||||
priv->fib_nb.notifier_call = rtl83xx_fib_event;
|
||||
|
||||
/*
|
||||
* Register Forwarding Information Base notifier to offload routes where
|
||||
/* Register Forwarding Information Base notifier to offload routes where
|
||||
* where possible
|
||||
* Only FIBs pointing to our own netdevs are programmed into
|
||||
* the device, so no need to pass a callback.
|
||||
@ -1641,13 +1644,13 @@ static int __init rtl83xx_sw_probe(struct platform_device *pdev)
|
||||
if (err)
|
||||
goto err_register_fib_nb;
|
||||
|
||||
// TODO: put this into l2_setup()
|
||||
// Flood BPDUs to all ports including cpu-port
|
||||
/* TODO: put this into l2_setup() */
|
||||
/* Flood BPDUs to all ports including cpu-port */
|
||||
if (soc_info.family != RTL9300_FAMILY_ID) {
|
||||
bpdu_mask = soc_info.family == RTL8380_FAMILY_ID ? 0x1FFFFFFF : 0x1FFFFFFFFFFFFF;
|
||||
priv->r->set_port_reg_be(bpdu_mask, priv->r->rma_bpdu_fld_pmask);
|
||||
|
||||
// TRAP 802.1X frames (EAPOL) to the CPU-Port, bypass STP and VLANs
|
||||
/* TRAP 802.1X frames (EAPOL) to the CPU-Port, bypass STP and VLANs */
|
||||
sw_w32(7, priv->r->spcl_trap_eapol_ctrl);
|
||||
|
||||
rtl838x_dbgfs_init(priv);
|
||||
@ -1667,8 +1670,9 @@ err_register_nb:
|
||||
|
||||
static int rtl83xx_sw_remove(struct platform_device *pdev)
|
||||
{
|
||||
// TODO:
|
||||
/* TODO: */
|
||||
pr_debug("Removing platform driver for rtl83xx-sw\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@ -2,8 +2,8 @@
|
||||
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/kernel.h>
|
||||
|
||||
#include <asm/mach-rtl838x/mach-rtl83xx.h>
|
||||
|
||||
#include "rtl83xx.h"
|
||||
|
||||
#define RTL838X_DRIVER_NAME "rtl838x"
|
||||
@ -109,21 +109,21 @@ const char *rtl930x_drop_cntr[] = {
|
||||
|
||||
const char *rtl931x_drop_cntr[] = {
|
||||
"ALE_RX_GOOD_PKTS", "RX_MAX_FRAME_SIZE", "MAC_RX_DROP", "OPENFLOW_IP_MPLS_TTL", "OPENFLOW_TBL_MISS",
|
||||
"IGR_BW", "SPECIAL_CONGEST", "EGR_QUEUE", "RESERVED", "EGR_LINK_STATUS", "STACK_UCAST_NONUCAST_TTL", // 10
|
||||
"IGR_BW", "SPECIAL_CONGEST", "EGR_QUEUE", "RESERVED", "EGR_LINK_STATUS", "STACK_UCAST_NONUCAST_TTL", /* 10 */
|
||||
"STACK_NONUC_BLOCKING_PMSK", "L2_CRC", "SRC_PORT_FILTER", "PARSER_PACKET_TOO_LONG", "PARSER_MALFORM_PACKET",
|
||||
"MPLS_OVER_2_LBL", "EACL_METER", "IACL_METER", "PROTO_STORM", "INVALID_CAPWAP_HEADER", // 20
|
||||
"MPLS_OVER_2_LBL", "EACL_METER", "IACL_METER", "PROTO_STORM", "INVALID_CAPWAP_HEADER", /* 20 */
|
||||
"MAC_IP_SUBNET_BASED_VLAN", "OAM_PARSER", "UC_MC_RPF", "IP_MAC_BINDING_MATCH_MISMATCH", "SA_BLOCK",
|
||||
"TUNNEL_IP_ADDRESS_CHECK", "EACL_DROP", "IACL_DROP", "ATTACK_PREVENT", "SYSTEM_PORT_LIMIT_LEARN", // 30,
|
||||
"TUNNEL_IP_ADDRESS_CHECK", "EACL_DROP", "IACL_DROP", "ATTACK_PREVENT", "SYSTEM_PORT_LIMIT_LEARN", /* 30 */
|
||||
"OAMPDU", "CCM_RX", "CFM_UNKNOWN_TYPE", "LBM_LBR_LTM_LTR", "Y_1731", "VLAN_LIMIT_LEARN",
|
||||
"VLAN_ACCEPT_FRAME_TYPE", "CFI_1", "STATIC_DYNAMIC_PORT_MOVING", "PORT_MOVE_FORBID", // 40
|
||||
"VLAN_ACCEPT_FRAME_TYPE", "CFI_1", "STATIC_DYNAMIC_PORT_MOVING", "PORT_MOVE_FORBID", /* 40 */
|
||||
"L3_CRC", "BPDU_PTP_LLDP_EAPOL_RMA", "MSTP_SRC_DROP_DISABLED_BLOCKING", "INVALID_SA", "NEW_SA",
|
||||
"VLAN_IGR_FILTER", "IGR_VLAN_CONVERT", "GRATUITOUS_ARP", "MSTP_SRC_DROP", "L2_HASH_FULL", // 50
|
||||
"VLAN_IGR_FILTER", "IGR_VLAN_CONVERT", "GRATUITOUS_ARP", "MSTP_SRC_DROP", "L2_HASH_FULL", /* 50 */
|
||||
"MPLS_UNKNOWN_LBL", "L3_IPUC_NON_IP", "TTL", "MTU", "ICMP_REDIRECT", "STORM_CONTROL", "L3_DIP_DMAC_MISMATCH",
|
||||
"IP4_IP_OPTION", "IP6_HBH_EXT_HEADER", "IP4_IP6_HEADER_ERROR", // 60
|
||||
"IP4_IP_OPTION", "IP6_HBH_EXT_HEADER", "IP4_IP6_HEADER_ERROR", /* 60 */
|
||||
"ROUTING_IP_ADDR_CHECK", "ROUTING_EXCEPTION", "DA_BLOCK", "OAM_MUX", "PORT_ISOLATION", "VLAN_EGR_FILTER",
|
||||
"MIRROR_ISOLATE", "MSTP_DESTINATION_DROP", "L2_MC_BRIDGE", "IP_UC_MC_ROUTING_LOOK_UP_MISS", // 70
|
||||
"MIRROR_ISOLATE", "MSTP_DESTINATION_DROP", "L2_MC_BRIDGE", "IP_UC_MC_ROUTING_LOOK_UP_MISS", /* 70 */
|
||||
"L2_UC", "L2_MC", "IP4_MC", "IP6_MC", "L3_UC_MC_ROUTE", "UNKNOWN_L2_UC_FLPM", "BC_FLPM",
|
||||
"VLAN_PRO_UNKNOWN_L2_MC_FLPM", "VLAN_PRO_UNKNOWN_IP4_MC_FLPM", "VLAN_PROFILE_UNKNOWN_IP6_MC_FLPM" // 80,
|
||||
"VLAN_PRO_UNKNOWN_L2_MC_FLPM", "VLAN_PRO_UNKNOWN_IP4_MC_FLPM", "VLAN_PROFILE_UNKNOWN_IP6_MC_FLPM", /* 80 */
|
||||
};
|
||||
|
||||
static ssize_t rtl838x_common_read(char __user *buffer, size_t count,
|
||||
@ -214,7 +214,6 @@ static ssize_t drop_counter_read(struct file *filp, char __user *buffer, size_t
|
||||
loff_t *ppos)
|
||||
{
|
||||
struct rtl838x_switch_priv *priv = filp->private_data;
|
||||
int i;
|
||||
const char **d;
|
||||
u32 v;
|
||||
char *buf;
|
||||
@ -248,7 +247,7 @@ static ssize_t drop_counter_read(struct file *filp, char __user *buffer, size_t
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
|
||||
for (i = 0; i < num; i++) {
|
||||
for (int i = 0; i < num; i++) {
|
||||
v = sw_r32(offset + (i << 2)) & 0xffff;
|
||||
n += sprintf(buf + n, "%s: %d\n", d[i], v);
|
||||
}
|
||||
@ -274,7 +273,6 @@ static void l2_table_print_entry(struct seq_file *m, struct rtl838x_switch_priv
|
||||
struct rtl838x_l2_entry *e)
|
||||
{
|
||||
u64 portmask;
|
||||
int i;
|
||||
|
||||
if (e->type == L2_UNICAST) {
|
||||
seq_puts(m, "L2_UNICAST\n");
|
||||
@ -315,7 +313,7 @@ static void l2_table_print_entry(struct seq_file *m, struct rtl838x_switch_priv
|
||||
|
||||
portmask = priv->r->read_mcast_pmask(e->mc_portmask_index);
|
||||
seq_printf(m, " index %u ports", e->mc_portmask_index);
|
||||
for (i = 0; i < 64; i++) {
|
||||
for (int i = 0; i < 64; i++) {
|
||||
if (portmask & BIT_ULL(i))
|
||||
seq_printf(m, " %d", i);
|
||||
}
|
||||
@ -329,11 +327,11 @@ static int l2_table_show(struct seq_file *m, void *v)
|
||||
{
|
||||
struct rtl838x_switch_priv *priv = m->private;
|
||||
struct rtl838x_l2_entry e;
|
||||
int i, bucket, index;
|
||||
int bucket, index;
|
||||
|
||||
mutex_lock(&priv->reg_mutex);
|
||||
|
||||
for (i = 0; i < priv->fib_entries; i++) {
|
||||
for (int i = 0; i < priv->fib_entries; i++) {
|
||||
bucket = i >> 2;
|
||||
index = i & 0x3;
|
||||
priv->r->read_l2_entry_using_hash(bucket, index, &e);
|
||||
@ -343,9 +341,12 @@ static int l2_table_show(struct seq_file *m, void *v)
|
||||
|
||||
seq_printf(m, "Hash table bucket %d index %d ", bucket, index);
|
||||
l2_table_print_entry(m, priv, &e);
|
||||
|
||||
if (!((i + 1) % 64))
|
||||
cond_resched();
|
||||
}
|
||||
|
||||
for (i = 0; i < 64; i++) {
|
||||
for (int i = 0; i < 64; i++) {
|
||||
priv->r->read_cam(i, &e);
|
||||
|
||||
if (!e.valid)
|
||||
@ -462,7 +463,7 @@ void rtl838x_dbgfs_cleanup(struct rtl838x_switch_priv *priv)
|
||||
{
|
||||
debugfs_remove_recursive(priv->dbgfs_dir);
|
||||
|
||||
// kfree(priv->dbgfs_entries);
|
||||
/* kfree(priv->dbgfs_entries); */
|
||||
}
|
||||
|
||||
static int rtl838x_dbgfs_port_init(struct dentry *parent, struct rtl838x_switch_priv *priv,
|
||||
@ -514,9 +515,6 @@ static int rtl838x_dbgfs_port_init(struct dentry *parent, struct rtl838x_switch_
|
||||
static int rtl838x_dbgfs_leds(struct dentry *parent, struct rtl838x_switch_priv *priv)
|
||||
{
|
||||
struct dentry *led_dir;
|
||||
int p;
|
||||
char led_sw_p_ctrl_name[20];
|
||||
char port_led_name[20];
|
||||
|
||||
led_dir = debugfs_create_dir("led", parent);
|
||||
|
||||
@ -537,20 +535,24 @@ static int rtl838x_dbgfs_leds(struct dentry *parent, struct rtl838x_switch_priv
|
||||
(u32 *)(RTL838X_SW_BASE + RTL8380_LED1_SW_P_EN_CTRL));
|
||||
debugfs_create_x32("led2_sw_p_en_ctrl", 0644, led_dir,
|
||||
(u32 *)(RTL838X_SW_BASE + RTL8380_LED2_SW_P_EN_CTRL));
|
||||
for (p = 0; p < 28; p++) {
|
||||
for (int p = 0; p < 28; p++) {
|
||||
char led_sw_p_ctrl_name[20];
|
||||
|
||||
snprintf(led_sw_p_ctrl_name, sizeof(led_sw_p_ctrl_name),
|
||||
"led_sw_p_ctrl.%02d", p);
|
||||
debugfs_create_x32(led_sw_p_ctrl_name, 0644, led_dir,
|
||||
(u32 *)(RTL838X_SW_BASE + RTL8380_LED_SW_P_CTRL(p)));
|
||||
}
|
||||
} else if (priv->family_id == RTL8390_FAMILY_ID) {
|
||||
char port_led_name[20];
|
||||
|
||||
debugfs_create_x32("led_glb_ctrl", 0644, led_dir,
|
||||
(u32 *)(RTL838X_SW_BASE + RTL8390_LED_GLB_CTRL));
|
||||
debugfs_create_x32("led_set_2_3", 0644, led_dir,
|
||||
(u32 *)(RTL838X_SW_BASE + RTL8390_LED_SET_2_3_CTRL));
|
||||
debugfs_create_x32("led_set_0_1", 0644, led_dir,
|
||||
(u32 *)(RTL838X_SW_BASE + RTL8390_LED_SET_0_1_CTRL));
|
||||
for (p = 0; p < 4; p++) {
|
||||
for (int p = 0; p < 4; p++) {
|
||||
snprintf(port_led_name, sizeof(port_led_name), "led_copr_set_sel.%1d", p);
|
||||
debugfs_create_x32(port_led_name, 0644, led_dir,
|
||||
(u32 *)(RTL838X_SW_BASE + RTL8390_LED_COPR_SET_SEL_CTRL(p << 4)));
|
||||
@ -572,12 +574,12 @@ static int rtl838x_dbgfs_leds(struct dentry *parent, struct rtl838x_switch_priv
|
||||
(u32 *)(RTL838X_SW_BASE + RTL8390_LED_COMBO_CTRL(32)));
|
||||
debugfs_create_x32("led_sw_ctrl", 0644, led_dir,
|
||||
(u32 *)(RTL838X_SW_BASE + RTL8390_LED_SW_CTRL));
|
||||
for (p = 0; p < 5; p++) {
|
||||
for (int p = 0; p < 5; p++) {
|
||||
snprintf(port_led_name, sizeof(port_led_name), "led_sw_p_en_ctrl.%1d", p);
|
||||
debugfs_create_x32(port_led_name, 0644, led_dir,
|
||||
(u32 *)(RTL838X_SW_BASE + RTL8390_LED_SW_P_EN_CTRL(p * 10)));
|
||||
}
|
||||
for (p = 0; p < 28; p++) {
|
||||
for (int p = 0; p < 28; p++) {
|
||||
snprintf(port_led_name, sizeof(port_led_name), "led_sw_p_ctrl.%02d", p);
|
||||
debugfs_create_x32(port_led_name, 0644, led_dir,
|
||||
(u32 *)(RTL838X_SW_BASE + RTL8390_LED_SW_P_CTRL(p)));
|
||||
@ -592,7 +594,7 @@ void rtl838x_dbgfs_init(struct rtl838x_switch_priv *priv)
|
||||
struct dentry *port_dir;
|
||||
struct dentry *mirror_dir;
|
||||
struct debugfs_regset32 *port_ctrl_regset;
|
||||
int ret, i;
|
||||
int ret;
|
||||
char lag_name[10];
|
||||
char mirror_name[10];
|
||||
|
||||
@ -607,7 +609,7 @@ void rtl838x_dbgfs_init(struct rtl838x_switch_priv *priv)
|
||||
(u32 *)(RTL838X_SW_BASE + RTL838X_MODEL_NAME_INFO));
|
||||
|
||||
/* Create one directory per port */
|
||||
for (i = 0; i < priv->cpu_port; i++) {
|
||||
for (int i = 0; i < priv->cpu_port; i++) {
|
||||
if (priv->ports[i].phy) {
|
||||
ret = rtl838x_dbgfs_port_init(rtl838x_dir, priv, i);
|
||||
if (ret)
|
||||
@ -630,7 +632,7 @@ void rtl838x_dbgfs_init(struct rtl838x_switch_priv *priv)
|
||||
debugfs_create_u8("id", 0444, port_dir, &priv->cpu_port);
|
||||
|
||||
/* Create entries for LAGs */
|
||||
for (i = 0; i < priv->n_lags; i++) {
|
||||
for (int i = 0; i < priv->n_lags; i++) {
|
||||
snprintf(lag_name, sizeof(lag_name), "lag.%02d", i);
|
||||
if (priv->family_id == RTL8380_FAMILY_ID)
|
||||
debugfs_create_x32(lag_name, 0644, rtl838x_dir,
|
||||
@ -641,7 +643,7 @@ void rtl838x_dbgfs_init(struct rtl838x_switch_priv *priv)
|
||||
}
|
||||
|
||||
/* Create directories for mirror groups */
|
||||
for (i = 0; i < 4; i++) {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
snprintf(mirror_name, sizeof(mirror_name), "mirror.%1d", i);
|
||||
mirror_dir = debugfs_create_dir(mirror_name, rtl838x_dir);
|
||||
if (priv->family_id == RTL8380_FAMILY_ID) {
|
||||
|
||||
@ -2,14 +2,12 @@
|
||||
|
||||
#include <net/dsa.h>
|
||||
#include <linux/if_bridge.h>
|
||||
|
||||
#include <asm/mach-rtl838x/mach-rtl83xx.h>
|
||||
|
||||
#include "rtl83xx.h"
|
||||
|
||||
|
||||
extern struct rtl83xx_soc_info soc_info;
|
||||
|
||||
|
||||
static void rtl83xx_init_stats(struct rtl838x_switch_priv *priv)
|
||||
{
|
||||
mutex_lock(&priv->reg_mutex);
|
||||
@ -28,12 +26,11 @@ static void rtl83xx_init_stats(struct rtl838x_switch_priv *priv)
|
||||
|
||||
static void rtl83xx_enable_phy_polling(struct rtl838x_switch_priv *priv)
|
||||
{
|
||||
int i;
|
||||
u64 v = 0;
|
||||
|
||||
msleep(1000);
|
||||
/* Enable all ports with a PHY, including the SFP-ports */
|
||||
for (i = 0; i < priv->cpu_port; i++) {
|
||||
for (int i = 0; i < priv->cpu_port; i++) {
|
||||
if (priv->ports[i].phy)
|
||||
v |= BIT_ULL(i);
|
||||
}
|
||||
@ -111,13 +108,10 @@ static enum dsa_tag_protocol rtl83xx_get_tag_protocol(struct dsa_switch *ds,
|
||||
return DSA_TAG_PROTO_TRAILER;
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize all VLANS
|
||||
*/
|
||||
/* Initialize all VLANS */
|
||||
static void rtl83xx_vlan_setup(struct rtl838x_switch_priv *priv)
|
||||
{
|
||||
struct rtl838x_vlan_info info;
|
||||
int i;
|
||||
|
||||
pr_info("In %s\n", __func__);
|
||||
|
||||
@ -126,39 +120,37 @@ static void rtl83xx_vlan_setup(struct rtl838x_switch_priv *priv)
|
||||
pr_info("UNKNOWN_MC_PMASK: %016llx\n", priv->r->read_mcast_pmask(UNKNOWN_MC_PMASK));
|
||||
priv->r->vlan_profile_dump(0);
|
||||
|
||||
info.fid = 0; // Default Forwarding ID / MSTI
|
||||
info.hash_uc_fid = false; // Do not build the L2 lookup hash with FID, but VID
|
||||
info.hash_mc_fid = false; // Do the same for Multicast packets
|
||||
info.profile_id = 0; // Use default Vlan Profile 0
|
||||
info.tagged_ports = 0; // Initially no port members
|
||||
info.fid = 0; /* Default Forwarding ID / MSTI */
|
||||
info.hash_uc_fid = false; /* Do not build the L2 lookup hash with FID, but VID */
|
||||
info.hash_mc_fid = false; /* Do the same for Multicast packets */
|
||||
info.profile_id = 0; /* Use default Vlan Profile 0 */
|
||||
info.tagged_ports = 0; /* Initially no port members */
|
||||
if (priv->family_id == RTL9310_FAMILY_ID) {
|
||||
info.if_id = 0;
|
||||
info.multicast_grp_mask = 0;
|
||||
info.l2_tunnel_list_id = -1;
|
||||
}
|
||||
|
||||
// Initialize all vlans 0-4095
|
||||
for (i = 0; i < MAX_VLANS; i ++)
|
||||
/* Initialize all vlans 0-4095 */
|
||||
for (int i = 0; i < MAX_VLANS; i ++)
|
||||
priv->r->vlan_set_tagged(i, &info);
|
||||
|
||||
// reset PVIDs; defaults to 1 on reset
|
||||
for (i = 0; i <= priv->ds->num_ports; i++) {
|
||||
/* reset PVIDs; defaults to 1 on reset */
|
||||
for (int i = 0; i <= priv->ds->num_ports; i++) {
|
||||
priv->r->vlan_port_pvid_set(i, PBVLAN_TYPE_INNER, 0);
|
||||
priv->r->vlan_port_pvid_set(i, PBVLAN_TYPE_OUTER, 0);
|
||||
priv->r->vlan_port_pvidmode_set(i, PBVLAN_TYPE_INNER, PBVLAN_MODE_UNTAG_AND_PRITAG);
|
||||
priv->r->vlan_port_pvidmode_set(i, PBVLAN_TYPE_OUTER, PBVLAN_MODE_UNTAG_AND_PRITAG);
|
||||
}
|
||||
|
||||
// Set forwarding action based on inner VLAN tag
|
||||
for (i = 0; i < priv->cpu_port; i++)
|
||||
/* Set forwarding action based on inner VLAN tag */
|
||||
for (int i = 0; i < priv->cpu_port; i++)
|
||||
priv->r->vlan_fwd_on_inner(i, true);
|
||||
}
|
||||
|
||||
static void rtl83xx_setup_bpdu_traps(struct rtl838x_switch_priv *priv)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < priv->cpu_port; i++)
|
||||
for (int i = 0; i < priv->cpu_port; i++)
|
||||
priv->r->set_receive_management_action(i, BPDU, COPY2CPU);
|
||||
}
|
||||
|
||||
@ -174,7 +166,6 @@ static void rtl83xx_port_set_salrn(struct rtl838x_switch_priv *priv,
|
||||
|
||||
static int rtl83xx_setup(struct dsa_switch *ds)
|
||||
{
|
||||
int i;
|
||||
struct rtl838x_switch_priv *priv = ds->priv;
|
||||
u64 port_bitmap = BIT_ULL(priv->cpu_port);
|
||||
|
||||
@ -183,7 +174,7 @@ static int rtl83xx_setup(struct dsa_switch *ds)
|
||||
/* Disable MAC polling the PHY so that we can start configuration */
|
||||
priv->r->set_port_reg_le(0ULL, priv->r->smi_poll_ctrl);
|
||||
|
||||
for (i = 0; i < ds->num_ports; i++)
|
||||
for (int i = 0; i < ds->num_ports; i++)
|
||||
priv->ports[i].enable = false;
|
||||
priv->ports[priv->cpu_port].enable = true;
|
||||
|
||||
@ -191,7 +182,7 @@ static int rtl83xx_setup(struct dsa_switch *ds)
|
||||
/* Setting bit j in register RTL838X_PORT_ISO_CTRL(i) allows
|
||||
* traffic from source port i to destination port j
|
||||
*/
|
||||
for (i = 0; i < priv->cpu_port; i++) {
|
||||
for (int i = 0; i < priv->cpu_port; i++) {
|
||||
if (priv->ports[i].phy) {
|
||||
priv->r->set_port_reg_be(BIT_ULL(priv->cpu_port) | BIT_ULL(i),
|
||||
priv->r->port_iso_ctrl(i));
|
||||
@ -218,8 +209,7 @@ static int rtl83xx_setup(struct dsa_switch *ds)
|
||||
rtl83xx_port_set_salrn(priv, priv->cpu_port, false);
|
||||
ds->assisted_learning_on_cpu_port = true;
|
||||
|
||||
/*
|
||||
* Make sure all frames sent to the switch's MAC are trapped to the CPU-port
|
||||
/* Make sure all frames sent to the switch's MAC are trapped to the CPU-port
|
||||
* 0: FWD, 1: DROP, 2: TRAP2CPU
|
||||
*/
|
||||
if (priv->family_id == RTL8380_FAMILY_ID)
|
||||
@ -238,7 +228,6 @@ static int rtl83xx_setup(struct dsa_switch *ds)
|
||||
|
||||
static int rtl93xx_setup(struct dsa_switch *ds)
|
||||
{
|
||||
int i;
|
||||
struct rtl838x_switch_priv *priv = ds->priv;
|
||||
u32 port_bitmap = BIT(priv->cpu_port);
|
||||
|
||||
@ -253,12 +242,12 @@ static int rtl93xx_setup(struct dsa_switch *ds)
|
||||
sw_w32(0, RTL931X_SMI_PORT_POLLING_CTRL + 4);
|
||||
}
|
||||
|
||||
// Disable all ports except CPU port
|
||||
for (i = 0; i < ds->num_ports; i++)
|
||||
/* Disable all ports except CPU port */
|
||||
for (int i = 0; i < ds->num_ports; i++)
|
||||
priv->ports[i].enable = false;
|
||||
priv->ports[priv->cpu_port].enable = true;
|
||||
|
||||
for (i = 0; i < priv->cpu_port; i++) {
|
||||
for (int i = 0; i < priv->cpu_port; i++) {
|
||||
if (priv->ports[i].phy) {
|
||||
priv->r->traffic_set(i, BIT_ULL(priv->cpu_port) | BIT_ULL(i));
|
||||
port_bitmap |= BIT_ULL(i);
|
||||
@ -268,7 +257,7 @@ static int rtl93xx_setup(struct dsa_switch *ds)
|
||||
|
||||
rtl930x_print_matrix();
|
||||
|
||||
// TODO: Initialize statistics
|
||||
/* TODO: Initialize statistics */
|
||||
|
||||
rtl83xx_vlan_setup(priv);
|
||||
|
||||
@ -413,9 +402,9 @@ static void rtl93xx_phylink_validate(struct dsa_switch *ds, int port,
|
||||
phylink_set(mask, 1000baseT_Half);
|
||||
}
|
||||
|
||||
// Internal phys of the RTL93xx family provide 10G
|
||||
if (priv->ports[port].phy_is_integrated
|
||||
&& state->interface == PHY_INTERFACE_MODE_1000BASEX) {
|
||||
/* Internal phys of the RTL93xx family provide 10G */
|
||||
if (priv->ports[port].phy_is_integrated &&
|
||||
state->interface == PHY_INTERFACE_MODE_1000BASEX) {
|
||||
phylink_set(mask, 1000baseX_Full);
|
||||
} else if (priv->ports[port].phy_is_integrated) {
|
||||
phylink_set(mask, 1000baseX_Full);
|
||||
@ -492,6 +481,7 @@ static int rtl83xx_phylink_mac_link_state(struct dsa_switch *ds, int port,
|
||||
state->pause |= MLO_PAUSE_RX;
|
||||
if (priv->r->get_port_reg_le(priv->r->mac_tx_pause_sts) & BIT_ULL(port))
|
||||
state->pause |= MLO_PAUSE_TX;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -506,8 +496,7 @@ static int rtl93xx_phylink_mac_link_state(struct dsa_switch *ds, int port,
|
||||
if (port < 0 || port > priv->cpu_port)
|
||||
return -EINVAL;
|
||||
|
||||
/*
|
||||
* On the RTL9300 for at least the RTL8226B PHY, the MAC-side link
|
||||
/* On the RTL9300 for at least the RTL8226B PHY, the MAC-side link
|
||||
* state needs to be read twice in order to read a correct result.
|
||||
* This would not be necessary for ports connected e.g. to RTL8218D
|
||||
* PHYs.
|
||||
@ -574,6 +563,7 @@ static int rtl93xx_phylink_mac_link_state(struct dsa_switch *ds, int port,
|
||||
state->pause |= MLO_PAUSE_RX;
|
||||
if (priv->r->get_port_reg_le(priv->r->mac_tx_pause_sts) & BIT_ULL(port))
|
||||
state->pause |= MLO_PAUSE_TX;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -683,7 +673,7 @@ static void rtl83xx_phylink_mac_config(struct dsa_switch *ds, int port,
|
||||
reg |= 1 << speed_bit;
|
||||
break;
|
||||
default:
|
||||
break; // Ignore, including 10MBit which has a speed value of 0
|
||||
break; /* Ignore, including 10MBit which has a speed value of 0 */
|
||||
}
|
||||
|
||||
if (priv->family_id == RTL8380_FAMILY_ID) {
|
||||
@ -700,7 +690,7 @@ static void rtl83xx_phylink_mac_config(struct dsa_switch *ds, int port,
|
||||
reg |= RTL839X_DUPLEX_MODE;
|
||||
}
|
||||
|
||||
// LAG members must use DUPLEX and we need to enable the link
|
||||
/* LAG members must use DUPLEX and we need to enable the link */
|
||||
if (priv->lagmembers & BIT_ULL(port)) {
|
||||
switch(priv->family_id) {
|
||||
case RTL8380_FAMILY_ID:
|
||||
@ -712,7 +702,7 @@ static void rtl83xx_phylink_mac_config(struct dsa_switch *ds, int port,
|
||||
}
|
||||
}
|
||||
|
||||
// Disable AN
|
||||
/* Disable AN */
|
||||
if (priv->family_id == RTL8380_FAMILY_ID)
|
||||
reg &= ~RTL838X_NWAY_EN;
|
||||
sw_w32(reg, priv->r->mac_force_mode_ctrl(port));
|
||||
@ -750,7 +740,7 @@ static void rtl931x_phylink_mac_config(struct dsa_switch *ds, int port,
|
||||
rtl931x_sds_init(sds_num, PHY_INTERFACE_MODE_10GBASER);
|
||||
break;
|
||||
case PHY_INTERFACE_MODE_USXGMII:
|
||||
// Translates to MII_USXGMII_10GSXGMII
|
||||
/* Translates to MII_USXGMII_10GSXGMII */
|
||||
band = rtl931x_sds_cmu_band_get(sds_num, PHY_INTERFACE_MODE_USXGMII);
|
||||
rtl931x_sds_init(sds_num, PHY_INTERFACE_MODE_USXGMII);
|
||||
break;
|
||||
@ -776,7 +766,7 @@ static void rtl931x_phylink_mac_config(struct dsa_switch *ds, int port,
|
||||
reg &= ~(RTL931X_DUPLEX_MODE | RTL931X_FORCE_EN | RTL931X_FORCE_LINK_EN);
|
||||
|
||||
reg &= ~(0xf << 12);
|
||||
reg |= 0x2 << 12; // Set SMI speed to 0x2
|
||||
reg |= 0x2 << 12; /* Set SMI speed to 0x2 */
|
||||
|
||||
reg |= RTL931X_TX_PAUSE_EN | RTL931X_RX_PAUSE_EN;
|
||||
|
||||
@ -801,7 +791,7 @@ static void rtl93xx_phylink_mac_config(struct dsa_switch *ds, int port,
|
||||
pr_info("%s port %d, mode %x, phy-mode: %s, speed %d, link %d\n", __func__,
|
||||
port, mode, phy_modes(state->interface), state->speed, state->link);
|
||||
|
||||
// Nothing to be done for the CPU-port
|
||||
/* Nothing to be done for the CPU-port */
|
||||
if (port == priv->cpu_port)
|
||||
return;
|
||||
|
||||
@ -823,7 +813,7 @@ static void rtl93xx_phylink_mac_config(struct dsa_switch *ds, int port,
|
||||
break;
|
||||
case PHY_INTERFACE_MODE_10GBASER:
|
||||
case PHY_INTERFACE_MODE_10GKR:
|
||||
sds_mode = 0x1b; // 10G 1000X Auto
|
||||
sds_mode = 0x1b; /* 10G 1000X Auto */
|
||||
break;
|
||||
case PHY_INTERFACE_MODE_USXGMII:
|
||||
sds_mode = 0x0d;
|
||||
@ -868,7 +858,7 @@ static void rtl93xx_phylink_mac_config(struct dsa_switch *ds, int port,
|
||||
reg |= RTL930X_DUPLEX_MODE;
|
||||
|
||||
if (priv->ports[port].phy_is_integrated)
|
||||
reg &= ~RTL930X_FORCE_EN; // Clear MAC_FORCE_EN to allow SDS-MAC link
|
||||
reg &= ~RTL930X_FORCE_EN; /* Clear MAC_FORCE_EN to allow SDS-MAC link */
|
||||
else
|
||||
reg |= RTL930X_FORCE_EN;
|
||||
|
||||
@ -884,7 +874,7 @@ static void rtl83xx_phylink_mac_link_down(struct dsa_switch *ds, int port,
|
||||
/* Stop TX/RX to port */
|
||||
sw_w32_mask(0x3, 0, priv->r->mac_port_ctrl(port));
|
||||
|
||||
// No longer force link
|
||||
/* No longer force link */
|
||||
sw_w32_mask(0x3, 0, priv->r->mac_force_mode_ctrl(port));
|
||||
}
|
||||
|
||||
@ -898,7 +888,7 @@ static void rtl93xx_phylink_mac_link_down(struct dsa_switch *ds, int port,
|
||||
/* Stop TX/RX to port */
|
||||
sw_w32_mask(0x3, 0, priv->r->mac_port_ctrl(port));
|
||||
|
||||
// No longer force link
|
||||
/* No longer force link */
|
||||
if (priv->family_id == RTL9300_FAMILY_ID)
|
||||
v = RTL930X_FORCE_EN | RTL930X_FORCE_LINK_EN;
|
||||
else if (priv->family_id == RTL9310_FAMILY_ID)
|
||||
@ -916,7 +906,7 @@ static void rtl83xx_phylink_mac_link_up(struct dsa_switch *ds, int port,
|
||||
struct rtl838x_switch_priv *priv = ds->priv;
|
||||
/* Restart TX/RX to port */
|
||||
sw_w32_mask(0, 0x3, priv->r->mac_port_ctrl(port));
|
||||
// TODO: Set speed/duplex/pauses
|
||||
/* TODO: Set speed/duplex/pauses */
|
||||
}
|
||||
|
||||
static void rtl93xx_phylink_mac_link_up(struct dsa_switch *ds, int port,
|
||||
@ -930,18 +920,16 @@ static void rtl93xx_phylink_mac_link_up(struct dsa_switch *ds, int port,
|
||||
|
||||
/* Restart TX/RX to port */
|
||||
sw_w32_mask(0, 0x3, priv->r->mac_port_ctrl(port));
|
||||
// TODO: Set speed/duplex/pauses
|
||||
/* TODO: Set speed/duplex/pauses */
|
||||
}
|
||||
|
||||
static void rtl83xx_get_strings(struct dsa_switch *ds,
|
||||
int port, u32 stringset, u8 *data)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (stringset != ETH_SS_STATS)
|
||||
return;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(rtl83xx_mib); i++)
|
||||
for (int i = 0; i < ARRAY_SIZE(rtl83xx_mib); i++)
|
||||
strncpy(data + i * ETH_GSTRING_LEN, rtl83xx_mib[i].name,
|
||||
ETH_GSTRING_LEN);
|
||||
}
|
||||
@ -951,10 +939,9 @@ static void rtl83xx_get_ethtool_stats(struct dsa_switch *ds, int port,
|
||||
{
|
||||
struct rtl838x_switch_priv *priv = ds->priv;
|
||||
const struct rtl83xx_mib_desc *mib;
|
||||
int i;
|
||||
u64 h;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(rtl83xx_mib); i++) {
|
||||
for (int i = 0; i < ARRAY_SIZE(rtl83xx_mib); i++) {
|
||||
mib = &rtl83xx_mib[i];
|
||||
|
||||
data[i] = sw_r32(priv->r->stat_port_std_mib + (port << 8) + 252 - mib->offset);
|
||||
@ -987,8 +974,8 @@ static int rtl83xx_mc_group_alloc(struct rtl838x_switch_priv *priv, int port)
|
||||
}
|
||||
|
||||
set_bit(mc_group, priv->mc_group_bm);
|
||||
mc_group++; // We cannot use group 0, as this is used for lookup miss flooding
|
||||
portmask = BIT_ULL(port) | BIT_ULL(priv->cpu_port);
|
||||
mc_group++; /* We cannot use group 0, as this is used for lookup miss flooding */
|
||||
portmask = BIT_ULL(port) | BIT_ULL(priv->cpu_port);
|
||||
priv->r->write_mcast_pmask(mc_group, portmask);
|
||||
|
||||
return mc_group;
|
||||
@ -1030,9 +1017,7 @@ static u64 rtl83xx_mc_group_del_port(struct rtl838x_switch_priv *priv, int mc_gr
|
||||
|
||||
static void store_mcgroups(struct rtl838x_switch_priv *priv, int port)
|
||||
{
|
||||
int mc_group;
|
||||
|
||||
for (mc_group = 0; mc_group < MAX_MC_GROUPS; mc_group++) {
|
||||
for (int mc_group = 0; mc_group < MAX_MC_GROUPS; mc_group++) {
|
||||
u64 portmask = priv->r->read_mcast_pmask(mc_group);
|
||||
if (portmask & BIT_ULL(port)) {
|
||||
priv->mc_group_saves[mc_group] = port;
|
||||
@ -1043,9 +1028,7 @@ static void store_mcgroups(struct rtl838x_switch_priv *priv, int port)
|
||||
|
||||
static void load_mcgroups(struct rtl838x_switch_priv *priv, int port)
|
||||
{
|
||||
int mc_group;
|
||||
|
||||
for (mc_group = 0; mc_group < MAX_MC_GROUPS; mc_group++) {
|
||||
for (int mc_group = 0; mc_group < MAX_MC_GROUPS; mc_group++) {
|
||||
if (priv->mc_group_saves[mc_group] == port) {
|
||||
rtl83xx_mc_group_add_port(priv, mc_group, port);
|
||||
priv->mc_group_saves[mc_group] = -1;
|
||||
@ -1083,7 +1066,7 @@ static int rtl83xx_port_enable(struct dsa_switch *ds, int port,
|
||||
v |= priv->ports[port].pm;
|
||||
priv->r->traffic_set(port, v);
|
||||
|
||||
// TODO: Figure out if this is necessary
|
||||
/* TODO: Figure out if this is necessary */
|
||||
if (priv->family_id == RTL9300_FAMILY_ID) {
|
||||
sw_w32_mask(0, BIT(port), RTL930X_L2_PORT_SABLK_CTRL);
|
||||
sw_w32_mask(0, BIT(port), RTL930X_L2_PORT_DABLK_CTRL);
|
||||
@ -1105,7 +1088,7 @@ static void rtl83xx_port_disable(struct dsa_switch *ds, int port)
|
||||
if (!dsa_is_user_port(ds, port))
|
||||
return;
|
||||
|
||||
// BUG: This does not work on RTL931X
|
||||
/* BUG: This does not work on RTL931X */
|
||||
/* remove port from switch mask of CPU_PORT */
|
||||
priv->r->traffic_disable(priv->cpu_port, port);
|
||||
store_mcgroups(priv, port);
|
||||
@ -1134,6 +1117,7 @@ static int rtl83xx_set_mac_eee(struct dsa_switch *ds, int port,
|
||||
pr_info("Enabled EEE for port %d\n", port);
|
||||
else
|
||||
pr_info("Disabled EEE for port %d\n", port);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1158,8 +1142,9 @@ static int rtl93xx_get_mac_eee(struct dsa_switch *ds, int port,
|
||||
{
|
||||
struct rtl838x_switch_priv *priv = ds->priv;
|
||||
|
||||
e->supported = SUPPORTED_100baseT_Full | SUPPORTED_1000baseT_Full
|
||||
| SUPPORTED_2500baseX_Full;
|
||||
e->supported = SUPPORTED_100baseT_Full |
|
||||
SUPPORTED_1000baseT_Full |
|
||||
SUPPORTED_2500baseX_Full;
|
||||
|
||||
priv->r->eee_port_ability(priv, e, port);
|
||||
|
||||
@ -1175,6 +1160,7 @@ static int rtl83xx_set_ageing_time(struct dsa_switch *ds, unsigned int msec)
|
||||
struct rtl838x_switch_priv *priv = ds->priv;
|
||||
|
||||
priv->r->set_ageing_time(msec);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1183,7 +1169,6 @@ static int rtl83xx_port_bridge_join(struct dsa_switch *ds, int port,
|
||||
{
|
||||
struct rtl838x_switch_priv *priv = ds->priv;
|
||||
u64 port_bitmap = BIT_ULL(priv->cpu_port), v;
|
||||
int i;
|
||||
|
||||
pr_debug("%s %x: %d %llx", __func__, (u32)priv, port, port_bitmap);
|
||||
|
||||
@ -1193,7 +1178,7 @@ static int rtl83xx_port_bridge_join(struct dsa_switch *ds, int port,
|
||||
}
|
||||
|
||||
mutex_lock(&priv->reg_mutex);
|
||||
for (i = 0; i < ds->num_ports; i++) {
|
||||
for (int i = 0; i < ds->num_ports; i++) {
|
||||
/* Add this port to the port matrix of the other ports in the
|
||||
* same bridge. If the port is disabled, port matrix is kept
|
||||
* and not being setup until the port becomes enabled.
|
||||
@ -1228,11 +1213,10 @@ static void rtl83xx_port_bridge_leave(struct dsa_switch *ds, int port,
|
||||
{
|
||||
struct rtl838x_switch_priv *priv = ds->priv;
|
||||
u64 port_bitmap = BIT_ULL(priv->cpu_port), v;
|
||||
int i;
|
||||
|
||||
pr_debug("%s %x: %d", __func__, (u32)priv, port);
|
||||
mutex_lock(&priv->reg_mutex);
|
||||
for (i = 0; i < ds->num_ports; i++) {
|
||||
for (int i = 0; i < ds->num_ports; i++) {
|
||||
/* Remove this port from the port matrix of the other ports
|
||||
* in the same bridge. If the port is disabled, port matrix
|
||||
* is kept and not being setup until the port becomes enabled.
|
||||
@ -1306,7 +1290,7 @@ void rtl83xx_port_stp_state_set(struct dsa_switch *ds, int port, u8 state)
|
||||
case BR_STATE_LEARNING: /* 2 */
|
||||
port_state[index] |= (2 << bit);
|
||||
break;
|
||||
case BR_STATE_FORWARDING: /* 3*/
|
||||
case BR_STATE_FORWARDING: /* 3 */
|
||||
port_state[index] |= (3 << bit);
|
||||
default:
|
||||
break;
|
||||
@ -1463,9 +1447,9 @@ static int rtl83xx_vlan_add(struct dsa_switch *ds, int port,
|
||||
priv->r->vlan_port_pvid_set(port, PBVLAN_TYPE_INNER, vlan->vid);
|
||||
priv->r->vlan_port_pvid_set(port, PBVLAN_TYPE_OUTER, vlan->vid);
|
||||
priv->r->vlan_port_pvidmode_set(port, PBVLAN_TYPE_INNER,
|
||||
PBVLAN_MODE_UNTAG_AND_PRITAG);
|
||||
PBVLAN_MODE_UNTAG_AND_PRITAG);
|
||||
priv->r->vlan_port_pvidmode_set(port, PBVLAN_TYPE_OUTER,
|
||||
PBVLAN_MODE_UNTAG_AND_PRITAG);
|
||||
PBVLAN_MODE_UNTAG_AND_PRITAG);
|
||||
|
||||
priv->ports[port].pvid = vlan->vid;
|
||||
}
|
||||
@ -1523,9 +1507,9 @@ static int rtl83xx_vlan_del(struct dsa_switch *ds, int port,
|
||||
priv->r->vlan_port_pvid_set(port, PBVLAN_TYPE_INNER, 0);
|
||||
priv->r->vlan_port_pvid_set(port, PBVLAN_TYPE_OUTER, 0);
|
||||
priv->r->vlan_port_pvidmode_set(port, PBVLAN_TYPE_INNER,
|
||||
PBVLAN_MODE_UNTAG_AND_PRITAG);
|
||||
PBVLAN_MODE_UNTAG_AND_PRITAG);
|
||||
priv->r->vlan_port_pvidmode_set(port, PBVLAN_TYPE_OUTER,
|
||||
PBVLAN_MODE_UNTAG_AND_PRITAG);
|
||||
PBVLAN_MODE_UNTAG_AND_PRITAG);
|
||||
}
|
||||
/* Get port memberships of this vlan */
|
||||
priv->r->vlan_tables_read(vlan->vid, &info);
|
||||
@ -1576,8 +1560,7 @@ static void rtl83xx_setup_l2_mc_entry(struct rtl838x_l2_entry *e, int vid, u64 m
|
||||
u64_to_ether_addr(mac, e->mac);
|
||||
}
|
||||
|
||||
/*
|
||||
* Uses the seed to identify a hash bucket in the L2 using the derived hash key and then loops
|
||||
/* Uses the seed to identify a hash bucket in the L2 using the derived hash key and then loops
|
||||
* over the entries in the bucket until either a matching entry is found or an empty slot
|
||||
* Returns the filled in rtl838x_l2_entry and the index in the bucket when an entry was found
|
||||
* when an empty slot was found and must exist is false, the index of the slot is returned
|
||||
@ -1586,13 +1569,13 @@ static void rtl83xx_setup_l2_mc_entry(struct rtl838x_l2_entry *e, int vid, u64 m
|
||||
static int rtl83xx_find_l2_hash_entry(struct rtl838x_switch_priv *priv, u64 seed,
|
||||
bool must_exist, struct rtl838x_l2_entry *e)
|
||||
{
|
||||
int i, idx = -1;
|
||||
int idx = -1;
|
||||
u32 key = priv->r->l2_hash_key(priv, seed);
|
||||
u64 entry;
|
||||
|
||||
pr_debug("%s: using key %x, for seed %016llx\n", __func__, key, seed);
|
||||
// Loop over all entries in the hash-bucket and over the second block on 93xx SoCs
|
||||
for (i = 0; i < priv->l2_bucket_size; i++) {
|
||||
/* Loop over all entries in the hash-bucket and over the second block on 93xx SoCs */
|
||||
for (int i = 0; i < priv->l2_bucket_size; i++) {
|
||||
entry = priv->r->read_l2_entry_using_hash(key, i, e);
|
||||
pr_debug("valid %d, mac %016llx\n", e->valid, ether_addr_to_u64(&e->mac[0]));
|
||||
if (must_exist && !e->valid)
|
||||
@ -1606,8 +1589,7 @@ static int rtl83xx_find_l2_hash_entry(struct rtl838x_switch_priv *priv, u64 seed
|
||||
return idx;
|
||||
}
|
||||
|
||||
/*
|
||||
* Uses the seed to identify an entry in the CAM by looping over all its entries
|
||||
/* Uses the seed to identify an entry in the CAM by looping over all its entries
|
||||
* Returns the filled in rtl838x_l2_entry and the index in the CAM when an entry was found
|
||||
* when an empty slot was found the index of the slot is returned
|
||||
* when no slots are available returns -1
|
||||
@ -1615,10 +1597,10 @@ static int rtl83xx_find_l2_hash_entry(struct rtl838x_switch_priv *priv, u64 seed
|
||||
static int rtl83xx_find_l2_cam_entry(struct rtl838x_switch_priv *priv, u64 seed,
|
||||
bool must_exist, struct rtl838x_l2_entry *e)
|
||||
{
|
||||
int i, idx = -1;
|
||||
int idx = -1;
|
||||
u64 entry;
|
||||
|
||||
for (i = 0; i < 64; i++) {
|
||||
for (int i = 0; i < 64; i++) {
|
||||
entry = priv->r->read_cam(i, e);
|
||||
if (!must_exist && !e->valid) {
|
||||
if (idx < 0) /* First empty entry? */
|
||||
@ -1630,6 +1612,7 @@ static int rtl83xx_find_l2_cam_entry(struct rtl838x_switch_priv *priv, u64 seed,
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return idx;
|
||||
}
|
||||
|
||||
@ -1651,14 +1634,14 @@ static int rtl83xx_port_fdb_add(struct dsa_switch *ds, int port,
|
||||
|
||||
idx = rtl83xx_find_l2_hash_entry(priv, seed, false, &e);
|
||||
|
||||
// Found an existing or empty entry
|
||||
/* Found an existing or empty entry */
|
||||
if (idx >= 0) {
|
||||
rtl83xx_setup_l2_uc_entry(&e, port, vid, mac);
|
||||
priv->r->write_l2_entry_using_hash(idx >> 2, idx & 0x3, &e);
|
||||
goto out;
|
||||
}
|
||||
|
||||
// Hash buckets full, try CAM
|
||||
/* Hash buckets full, try CAM */
|
||||
rtl83xx_find_l2_cam_entry(priv, seed, false, &e);
|
||||
|
||||
if (idx >= 0) {
|
||||
@ -1668,8 +1651,10 @@ static int rtl83xx_port_fdb_add(struct dsa_switch *ds, int port,
|
||||
}
|
||||
|
||||
err = -ENOTSUPP;
|
||||
|
||||
out:
|
||||
mutex_unlock(&priv->reg_mutex);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
@ -1703,8 +1688,10 @@ static int rtl83xx_port_fdb_del(struct dsa_switch *ds, int port,
|
||||
goto out;
|
||||
}
|
||||
err = -ENOENT;
|
||||
|
||||
out:
|
||||
mutex_unlock(&priv->reg_mutex);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
@ -1713,11 +1700,10 @@ static int rtl83xx_port_fdb_dump(struct dsa_switch *ds, int port,
|
||||
{
|
||||
struct rtl838x_l2_entry e;
|
||||
struct rtl838x_switch_priv *priv = ds->priv;
|
||||
int i;
|
||||
|
||||
mutex_lock(&priv->reg_mutex);
|
||||
|
||||
for (i = 0; i < priv->fib_entries; i++) {
|
||||
for (int i = 0; i < priv->fib_entries; i++) {
|
||||
priv->r->read_l2_entry_using_hash(i >> 2, i & 0x3, &e);
|
||||
|
||||
if (!e.valid)
|
||||
@ -1725,9 +1711,12 @@ static int rtl83xx_port_fdb_dump(struct dsa_switch *ds, int port,
|
||||
|
||||
if (e.port == port || e.port == RTL930X_PORT_IGNORE)
|
||||
cb(e.mac, e.vid, e.is_static, data);
|
||||
|
||||
if (!((i + 1) % 64))
|
||||
cond_resched();
|
||||
}
|
||||
|
||||
for (i = 0; i < 64; i++) {
|
||||
for (int i = 0; i < 64; i++) {
|
||||
priv->r->read_cam(i, &e);
|
||||
|
||||
if (!e.valid)
|
||||
@ -1738,6 +1727,7 @@ static int rtl83xx_port_fdb_dump(struct dsa_switch *ds, int port,
|
||||
}
|
||||
|
||||
mutex_unlock(&priv->reg_mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1766,7 +1756,7 @@ static int rtl83xx_port_mdb_add(struct dsa_switch *ds, int port,
|
||||
|
||||
idx = rtl83xx_find_l2_hash_entry(priv, seed, false, &e);
|
||||
|
||||
// Found an existing or empty entry
|
||||
/* Found an existing or empty entry */
|
||||
if (idx >= 0) {
|
||||
if (e.valid) {
|
||||
pr_debug("Found an existing entry %016llx, mc_group %d\n",
|
||||
@ -1785,7 +1775,7 @@ static int rtl83xx_port_mdb_add(struct dsa_switch *ds, int port,
|
||||
goto out;
|
||||
}
|
||||
|
||||
// Hash buckets full, try CAM
|
||||
/* Hash buckets full, try CAM */
|
||||
rtl83xx_find_l2_cam_entry(priv, seed, false, &e);
|
||||
|
||||
if (idx >= 0) {
|
||||
@ -1807,6 +1797,7 @@ static int rtl83xx_port_mdb_add(struct dsa_switch *ds, int port,
|
||||
}
|
||||
|
||||
err = -ENOTSUPP;
|
||||
|
||||
out:
|
||||
mutex_unlock(&priv->reg_mutex);
|
||||
if (err)
|
||||
@ -1858,9 +1849,11 @@ int rtl83xx_port_mdb_del(struct dsa_switch *ds, int port,
|
||||
}
|
||||
goto out;
|
||||
}
|
||||
// TODO: Re-enable with a newer kernel: err = -ENOENT;
|
||||
/* TODO: Re-enable with a newer kernel: err = -ENOENT; */
|
||||
|
||||
out:
|
||||
mutex_unlock(&priv->reg_mutex);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
@ -1871,7 +1864,7 @@ static int rtl83xx_port_mirror_add(struct dsa_switch *ds, int port,
|
||||
/* We support 4 mirror groups, one destination port per group */
|
||||
int group;
|
||||
struct rtl838x_switch_priv *priv = ds->priv;
|
||||
int ctrl_reg, dpm_reg, spm_reg;
|
||||
int ctrl_reg, dpm_reg, spm_reg;
|
||||
|
||||
pr_debug("In %s\n", __func__);
|
||||
|
||||
@ -1920,6 +1913,7 @@ static int rtl83xx_port_mirror_add(struct dsa_switch *ds, int port,
|
||||
|
||||
priv->mirror_group_ports[group] = mirror->to_local_port;
|
||||
mutex_unlock(&priv->reg_mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -2022,7 +2016,7 @@ static int rtl83xx_port_lag_change(struct dsa_switch *ds, int port)
|
||||
struct rtl838x_switch_priv *priv = ds->priv;
|
||||
|
||||
pr_debug("%s: %d\n", __func__, port);
|
||||
// Nothing to be done...
|
||||
/* Nothing to be done... */
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -2051,8 +2045,8 @@ static int rtl83xx_port_lag_join(struct dsa_switch *ds, int port,
|
||||
if (!priv->lag_devs[i])
|
||||
priv->lag_devs[i] = lag;
|
||||
|
||||
if (priv->lag_primary[i]==-1) {
|
||||
priv->lag_primary[i]=port;
|
||||
if (priv->lag_primary[i] == -1) {
|
||||
priv->lag_primary[i] = port;
|
||||
} else
|
||||
priv->is_lagmember[port] = 1;
|
||||
|
||||
@ -2067,8 +2061,8 @@ static int rtl83xx_port_lag_join(struct dsa_switch *ds, int port,
|
||||
|
||||
out:
|
||||
mutex_unlock(&priv->reg_mutex);
|
||||
return err;
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int rtl83xx_port_lag_leave(struct dsa_switch *ds, int port,
|
||||
@ -2078,7 +2072,7 @@ static int rtl83xx_port_lag_leave(struct dsa_switch *ds, int port,
|
||||
struct rtl838x_switch_priv *priv = ds->priv;
|
||||
|
||||
mutex_lock(&priv->reg_mutex);
|
||||
for (i=0;i<priv->n_lags;i++) {
|
||||
for (i = 0; i < priv->n_lags; i++) {
|
||||
if (priv->lags_port_members[i] & BIT_ULL(port)) {
|
||||
group = i;
|
||||
break;
|
||||
@ -2119,8 +2113,9 @@ int dsa_phy_read(struct dsa_switch *ds, int phy_addr, int phy_reg)
|
||||
u32 offset = 0;
|
||||
struct rtl838x_switch_priv *priv = ds->priv;
|
||||
|
||||
if (phy_addr >= 24 && phy_addr <= 27
|
||||
&& priv->ports[24].phy == PHY_RTL838X_SDS) {
|
||||
if ((phy_addr >= 24) &&
|
||||
(phy_addr <= 27) &&
|
||||
(priv->ports[24].phy == PHY_RTL838X_SDS)) {
|
||||
if (phy_addr == 26)
|
||||
offset = 0x100;
|
||||
val = sw_r32(RTL838X_SDS4_FIB_REG0 + offset + (phy_reg << 2)) & 0xffff;
|
||||
@ -2136,8 +2131,9 @@ int dsa_phy_write(struct dsa_switch *ds, int phy_addr, int phy_reg, u16 val)
|
||||
u32 offset = 0;
|
||||
struct rtl838x_switch_priv *priv = ds->priv;
|
||||
|
||||
if (phy_addr >= 24 && phy_addr <= 27
|
||||
&& priv->ports[24].phy == PHY_RTL838X_SDS) {
|
||||
if ((phy_addr >= 24) &&
|
||||
(phy_addr <= 27) &&
|
||||
(priv->ports[24].phy == PHY_RTL838X_SDS)) {
|
||||
if (phy_addr == 26)
|
||||
offset = 0x100;
|
||||
sw_w32(val, RTL838X_SDS4_FIB_REG0 + offset + (phy_reg << 2));
|
||||
|
||||
@ -2,8 +2,8 @@
|
||||
|
||||
#include <net/dsa.h>
|
||||
#include <linux/delay.h>
|
||||
|
||||
#include <asm/mach-rtl838x/mach-rtl83xx.h>
|
||||
|
||||
#include "rtl83xx.h"
|
||||
|
||||
static struct rtl838x_switch_priv *switch_priv;
|
||||
@ -20,34 +20,34 @@ int dot1p_priority_remapping[] = {0, 1, 2, 3, 4, 5, 6, 7};
|
||||
|
||||
static void rtl839x_read_scheduling_table(int port)
|
||||
{
|
||||
u32 cmd = 1 << 9 /* Execute cmd */
|
||||
| 0 << 8 /* Read */
|
||||
| 0 << 6 /* Table type 0b00 */
|
||||
| (port & 0x3f);
|
||||
u32 cmd = 1 << 9 | /* Execute cmd */
|
||||
0 << 8 | /* Read */
|
||||
0 << 6 | /* Table type 0b00 */
|
||||
(port & 0x3f);
|
||||
rtl839x_exec_tbl2_cmd(cmd);
|
||||
}
|
||||
|
||||
static void rtl839x_write_scheduling_table(int port)
|
||||
{
|
||||
u32 cmd = 1 << 9 /* Execute cmd */
|
||||
| 1 << 8 /* Write */
|
||||
| 0 << 6 /* Table type 0b00 */
|
||||
| (port & 0x3f);
|
||||
u32 cmd = 1 << 9 | /* Execute cmd */
|
||||
1 << 8 | /* Write */
|
||||
0 << 6 | /* Table type 0b00 */
|
||||
(port & 0x3f);
|
||||
rtl839x_exec_tbl2_cmd(cmd);
|
||||
}
|
||||
|
||||
static void rtl839x_read_out_q_table(int port)
|
||||
{
|
||||
u32 cmd = 1 << 9 /* Execute cmd */
|
||||
| 0 << 8 /* Read */
|
||||
| 2 << 6 /* Table type 0b10 */
|
||||
| (port & 0x3f);
|
||||
u32 cmd = 1 << 9 | /* Execute cmd */
|
||||
0 << 8 | /* Read */
|
||||
2 << 6 | /* Table type 0b10 */
|
||||
(port & 0x3f);
|
||||
rtl839x_exec_tbl2_cmd(cmd);
|
||||
}
|
||||
|
||||
static void rtl838x_storm_enable(struct rtl838x_switch_priv *priv, int port, bool enable)
|
||||
{
|
||||
// Enable Storm control for that port for UC, MC, and BC
|
||||
/* Enable Storm control for that port for UC, MC, and BC */
|
||||
if (enable)
|
||||
sw_w32(0x7, RTL838X_STORM_CTRL_LB_CTRL(port));
|
||||
else
|
||||
@ -56,12 +56,10 @@ static void rtl838x_storm_enable(struct rtl838x_switch_priv *priv, int port, boo
|
||||
|
||||
u32 rtl838x_get_egress_rate(struct rtl838x_switch_priv *priv, int port)
|
||||
{
|
||||
u32 rate;
|
||||
|
||||
if (port > priv->cpu_port)
|
||||
return 0;
|
||||
rate = sw_r32(RTL838X_SCHED_P_EGR_RATE_CTRL(port)) & 0x3fff;
|
||||
return rate;
|
||||
|
||||
return sw_r32(RTL838X_SCHED_P_EGR_RATE_CTRL(port)) & 0x3fff;
|
||||
}
|
||||
|
||||
/* Sets the rate limit, 10MBit/s is equal to a rate value of 625 */
|
||||
@ -86,40 +84,41 @@ void rtl838x_egress_rate_queue_limit(struct rtl838x_switch_priv *priv, int port,
|
||||
{
|
||||
if (port > priv->cpu_port)
|
||||
return;
|
||||
|
||||
if (queue > 7)
|
||||
return;
|
||||
|
||||
sw_w32(rate, RTL838X_SCHED_Q_EGR_RATE_CTRL(port, queue));
|
||||
}
|
||||
|
||||
static void rtl838x_rate_control_init(struct rtl838x_switch_priv *priv)
|
||||
{
|
||||
int i;
|
||||
|
||||
pr_info("Enabling Storm control\n");
|
||||
// TICK_PERIOD_PPS
|
||||
/* TICK_PERIOD_PPS */
|
||||
if (priv->id == 0x8380)
|
||||
sw_w32_mask(0x3ff << 20, 434 << 20, RTL838X_SCHED_LB_TICK_TKN_CTRL_0);
|
||||
|
||||
// Set burst rate
|
||||
sw_w32(0x00008000, RTL838X_STORM_CTRL_BURST_0); // UC
|
||||
sw_w32(0x80008000, RTL838X_STORM_CTRL_BURST_1); // MC and BC
|
||||
/* Set burst rate */
|
||||
sw_w32(0x00008000, RTL838X_STORM_CTRL_BURST_0); /* UC */
|
||||
sw_w32(0x80008000, RTL838X_STORM_CTRL_BURST_1); /* MC and BC */
|
||||
|
||||
// Set burst Packets per Second to 32
|
||||
sw_w32(0x00000020, RTL838X_STORM_CTRL_BURST_PPS_0); // UC
|
||||
sw_w32(0x00200020, RTL838X_STORM_CTRL_BURST_PPS_1); // MC and BC
|
||||
/* Set burst Packets per Second to 32 */
|
||||
sw_w32(0x00000020, RTL838X_STORM_CTRL_BURST_PPS_0); /* UC */
|
||||
sw_w32(0x00200020, RTL838X_STORM_CTRL_BURST_PPS_1); /* MC and BC */
|
||||
|
||||
// Include IFG in storm control, rate based on bytes/s (0 = packets)
|
||||
/* Include IFG in storm control, rate based on bytes/s (0 = packets) */
|
||||
sw_w32_mask(0, 1 << 6 | 1 << 5, RTL838X_STORM_CTRL);
|
||||
// Bandwidth control includes preamble and IFG (10 Bytes)
|
||||
/* Bandwidth control includes preamble and IFG (10 Bytes) */
|
||||
sw_w32_mask(0, 1, RTL838X_SCHED_CTRL);
|
||||
|
||||
// On SoCs except RTL8382M, set burst size of port egress
|
||||
/* On SoCs except RTL8382M, set burst size of port egress */
|
||||
if (priv->id != 0x8382)
|
||||
sw_w32_mask(0xffff, 0x800, RTL838X_SCHED_LB_THR);
|
||||
|
||||
/* Enable storm control on all ports with a PHY and limit rates,
|
||||
* for UC and MC for both known and unknown addresses */
|
||||
for (i = 0; i < priv->cpu_port; i++) {
|
||||
* for UC and MC for both known and unknown addresses
|
||||
*/
|
||||
for (int i = 0; i < priv->cpu_port; i++) {
|
||||
if (priv->ports[i].phy) {
|
||||
sw_w32((1 << 18) | 0x8000, RTL838X_STORM_CTRL_PORT_UC(i));
|
||||
sw_w32((1 << 18) | 0x8000, RTL838X_STORM_CTRL_PORT_MC(i));
|
||||
@ -128,14 +127,14 @@ static void rtl838x_rate_control_init(struct rtl838x_switch_priv *priv)
|
||||
}
|
||||
}
|
||||
|
||||
// Attack prevention, enable all attack prevention measures
|
||||
//sw_w32(0x1ffff, RTL838X_ATK_PRVNT_CTRL);
|
||||
/* Attack prevention, enable all attack prevention measures */
|
||||
/* sw_w32(0x1ffff, RTL838X_ATK_PRVNT_CTRL); */
|
||||
/* Attack prevention, drop (bit = 0) problematic packets on all ports.
|
||||
* Setting bit = 1 means: trap to CPU
|
||||
*/
|
||||
//sw_w32(0, RTL838X_ATK_PRVNT_ACT);
|
||||
// Enable attack prevention on all ports
|
||||
//sw_w32(0x0fffffff, RTL838X_ATK_PRVNT_PORT_EN);
|
||||
/* sw_w32(0, RTL838X_ATK_PRVNT_ACT); */
|
||||
/* Enable attack prevention on all ports */
|
||||
/* sw_w32(0x0fffffff, RTL838X_ATK_PRVNT_PORT_EN); */
|
||||
}
|
||||
|
||||
/* Sets the rate limit, 10MBit/s is equal to a rate value of 625 */
|
||||
@ -180,7 +179,7 @@ int rtl839x_set_egress_rate(struct rtl838x_switch_priv *priv, int port, u32 rate
|
||||
sw_w32_mask(0xfff << 20, rate << 20, RTL839X_TBL_ACCESS_DATA_2(8));
|
||||
|
||||
rtl839x_write_scheduling_table(port);
|
||||
|
||||
|
||||
mutex_unlock(&priv->reg_mutex);
|
||||
|
||||
return old_rate;
|
||||
@ -221,27 +220,25 @@ void rtl839x_egress_rate_queue_limit(struct rtl838x_switch_priv *priv, int port,
|
||||
|
||||
static void rtl839x_rate_control_init(struct rtl838x_switch_priv *priv)
|
||||
{
|
||||
int p, q;
|
||||
|
||||
pr_info("%s: enabling rate control\n", __func__);
|
||||
/* Tick length and token size settings for SoC with 250MHz,
|
||||
* RTL8350 family would use 50MHz
|
||||
*/
|
||||
// Set the special tick period
|
||||
/* Set the special tick period */
|
||||
sw_w32(976563, RTL839X_STORM_CTRL_SPCL_LB_TICK_TKN_CTRL);
|
||||
// Ingress tick period and token length 10G
|
||||
/* Ingress tick period and token length 10G */
|
||||
sw_w32(18 << 11 | 151, RTL839X_IGR_BWCTRL_LB_TICK_TKN_CTRL_0);
|
||||
// Ingress tick period and token length 1G
|
||||
/* Ingress tick period and token length 1G */
|
||||
sw_w32(245 << 11 | 129, RTL839X_IGR_BWCTRL_LB_TICK_TKN_CTRL_1);
|
||||
// Egress tick period 10G, bytes/token 10G and tick period 1G, bytes/token 1G
|
||||
/* Egress tick period 10G, bytes/token 10G and tick period 1G, bytes/token 1G */
|
||||
sw_w32(18 << 24 | 151 << 16 | 185 << 8 | 97, RTL839X_SCHED_LB_TICK_TKN_CTRL);
|
||||
// Set the tick period of the CPU and the Token Len
|
||||
/* Set the tick period of the CPU and the Token Len */
|
||||
sw_w32(3815 << 8 | 1, RTL839X_SCHED_LB_TICK_TKN_PPS_CTRL);
|
||||
|
||||
// Set the Weighted Fair Queueing burst size
|
||||
/* Set the Weighted Fair Queueing burst size */
|
||||
sw_w32_mask(0xffff, 4500, RTL839X_SCHED_LB_THR);
|
||||
|
||||
// Storm-rate calculation is based on bytes/sec (bit 5), include IFG (bit 6)
|
||||
/* Storm-rate calculation is based on bytes/sec (bit 5), include IFG (bit 6) */
|
||||
sw_w32_mask(0, 1 << 5 | 1 << 6, RTL839X_STORM_CTRL);
|
||||
|
||||
/* Based on the rate control mode being bytes/s
|
||||
@ -255,7 +252,7 @@ static void rtl839x_rate_control_init(struct rtl838x_switch_priv *priv)
|
||||
* for UC, MC and BC
|
||||
* For 1G port, the minimum burst rate is 1700, maximum 65535,
|
||||
* For 10G ports it is 2650 and 1048575 respectively */
|
||||
for (p = 0; p < priv->cpu_port; p++) {
|
||||
for (int p = 0; p < priv->cpu_port; p++) {
|
||||
if (priv->ports[p].phy && !priv->ports[p].is10G) {
|
||||
sw_w32_mask(0xffff, 0x8000, RTL839X_STORM_CTRL_PORT_UC_1(p));
|
||||
sw_w32_mask(0xffff, 0x8000, RTL839X_STORM_CTRL_PORT_MC_1(p));
|
||||
@ -264,29 +261,29 @@ static void rtl839x_rate_control_init(struct rtl838x_switch_priv *priv)
|
||||
}
|
||||
|
||||
/* Setup ingress/egress per-port rate control */
|
||||
for (p = 0; p < priv->cpu_port; p++) {
|
||||
for (int p = 0; p < priv->cpu_port; p++) {
|
||||
if (!priv->ports[p].phy)
|
||||
continue;
|
||||
|
||||
if (priv->ports[p].is10G)
|
||||
rtl839x_set_egress_rate(priv, p, 625000); // 10GB/s
|
||||
rtl839x_set_egress_rate(priv, p, 625000); /* 10GB/s */
|
||||
else
|
||||
rtl839x_set_egress_rate(priv, p, 62500); // 1GB/s
|
||||
rtl839x_set_egress_rate(priv, p, 62500); /* 1GB/s */
|
||||
|
||||
// Setup queues: all RTL83XX SoCs have 8 queues, maximum rate
|
||||
for (q = 0; q < 8; q++)
|
||||
/* Setup queues: all RTL83XX SoCs have 8 queues, maximum rate */
|
||||
for (int q = 0; q < 8; q++)
|
||||
rtl839x_egress_rate_queue_limit(priv, p, q, 0xfffff);
|
||||
|
||||
if (priv->ports[p].is10G) {
|
||||
// Set high threshold to maximum
|
||||
/* Set high threshold to maximum */
|
||||
sw_w32_mask(0xffff, 0xffff, RTL839X_IGR_BWCTRL_PORT_CTRL_10G_0(p));
|
||||
} else {
|
||||
// Set high threshold to maximum
|
||||
/* Set high threshold to maximum */
|
||||
sw_w32_mask(0xffff, 0xffff, RTL839X_IGR_BWCTRL_PORT_CTRL_1(p));
|
||||
}
|
||||
}
|
||||
|
||||
// Set global ingress low watermark rate
|
||||
/* Set global ingress low watermark rate */
|
||||
sw_w32(65532, RTL839X_IGR_BWCTRL_CTRL_LB_THR);
|
||||
}
|
||||
|
||||
@ -294,22 +291,19 @@ static void rtl839x_rate_control_init(struct rtl838x_switch_priv *priv)
|
||||
|
||||
void rtl838x_setup_prio2queue_matrix(int *min_queues)
|
||||
{
|
||||
int i;
|
||||
u32 v;
|
||||
|
||||
pr_info("Current Intprio2queue setting: %08x\n", sw_r32(RTL838X_QM_INTPRI2QID_CTRL));
|
||||
for (i = 0; i < MAX_PRIOS; i++)
|
||||
for (int i = 0; i < MAX_PRIOS; i++)
|
||||
v |= i << (min_queues[i] * 3);
|
||||
sw_w32(v, RTL838X_QM_INTPRI2QID_CTRL);
|
||||
}
|
||||
|
||||
void rtl839x_setup_prio2queue_matrix(int *min_queues)
|
||||
{
|
||||
int i, q;
|
||||
|
||||
pr_info("Current Intprio2queue setting: %08x\n", sw_r32(RTL839X_QM_INTPRI2QID_CTRL(0)));
|
||||
for (i = 0; i < MAX_PRIOS; i++) {
|
||||
q = min_queues[i];
|
||||
for (int i = 0; i < MAX_PRIOS; i++) {
|
||||
int q = min_queues[i];
|
||||
sw_w32(i << (q * 3), RTL839X_QM_INTPRI2QID_CTRL(q));
|
||||
}
|
||||
}
|
||||
@ -317,13 +311,12 @@ void rtl839x_setup_prio2queue_matrix(int *min_queues)
|
||||
/* Sets the CPU queue depending on the internal priority of a packet */
|
||||
void rtl83xx_setup_prio2queue_cpu_matrix(int *max_queues)
|
||||
{
|
||||
int reg = soc_info.family == RTL8380_FAMILY_ID ? RTL838X_QM_PKT2CPU_INTPRI_MAP
|
||||
int reg = soc_info.family == RTL8380_FAMILY_ID ? RTL838X_QM_PKT2CPU_INTPRI_MAP
|
||||
: RTL839X_QM_PKT2CPU_INTPRI_MAP;
|
||||
int i;
|
||||
u32 v;
|
||||
|
||||
pr_info("QM_PKT2CPU_INTPRI_MAP: %08x\n", sw_r32(reg));
|
||||
for (i = 0; i < MAX_PRIOS; i++)
|
||||
for (int i = 0; i < MAX_PRIOS; i++)
|
||||
v |= max_queues[i] << (i * 3);
|
||||
sw_w32(v, reg);
|
||||
}
|
||||
@ -351,7 +344,6 @@ void rtl83xx_set_ingress_priority(int port, int priority)
|
||||
sw_w32(priority << ((port % 10) *3), RTL838X_PRI_SEL_PORT_PRI(port));
|
||||
else
|
||||
sw_w32(priority << ((port % 10) *3), RTL839X_PRI_SEL_PORT_PRI(port));
|
||||
|
||||
}
|
||||
|
||||
int rtl839x_get_scheduling_algorithm(struct rtl838x_switch_priv *priv, int port)
|
||||
@ -367,6 +359,7 @@ int rtl839x_get_scheduling_algorithm(struct rtl838x_switch_priv *priv, int port)
|
||||
|
||||
if (v & BIT(19))
|
||||
return WEIGHTED_ROUND_ROBIN;
|
||||
|
||||
return WEIGHTED_FAIR_QUEUE;
|
||||
}
|
||||
|
||||
@ -381,24 +374,24 @@ void rtl839x_set_scheduling_algorithm(struct rtl838x_switch_priv *priv, int port
|
||||
mutex_lock(&priv->reg_mutex);
|
||||
/* Check whether we need to empty the egress queue of that port due to Errata E0014503 */
|
||||
if (sched == WEIGHTED_FAIR_QUEUE && t == WEIGHTED_ROUND_ROBIN && port != priv->cpu_port) {
|
||||
// Read Operations, Adminstatrion and Management control register
|
||||
/* Read Operations, Adminstatrion and Management control register */
|
||||
oam_state = sw_r32(RTL839X_OAM_CTRL);
|
||||
|
||||
// Get current OAM state
|
||||
/* Get current OAM state */
|
||||
oam_port_state = sw_r32(RTL839X_OAM_PORT_ACT_CTRL(port));
|
||||
|
||||
// Disable OAM to block traffice
|
||||
|
||||
/* Disable OAM to block traffice */
|
||||
v = sw_r32(RTL839X_OAM_CTRL);
|
||||
sw_w32_mask(0, 1, RTL839X_OAM_CTRL);
|
||||
v = sw_r32(RTL839X_OAM_CTRL);
|
||||
|
||||
// Set to trap action OAM forward (bits 1, 2) and OAM Mux Action Drop (bit 0)
|
||||
/* Set to trap action OAM forward (bits 1, 2) and OAM Mux Action Drop (bit 0) */
|
||||
sw_w32(0x2, RTL839X_OAM_PORT_ACT_CTRL(port));
|
||||
|
||||
// Set port egress rate to unlimited
|
||||
/* Set port egress rate to unlimited */
|
||||
egress_rate = rtl839x_set_egress_rate(priv, port, 0xFFFFF);
|
||||
|
||||
// Wait until the egress used page count of that port is 0
|
||||
|
||||
/* Wait until the egress used page count of that port is 0 */
|
||||
i = 0;
|
||||
do {
|
||||
usleep_range(100, 200);
|
||||
@ -409,19 +402,19 @@ void rtl839x_set_scheduling_algorithm(struct rtl838x_switch_priv *priv, int port
|
||||
} while (i < 3500 && count > 0);
|
||||
}
|
||||
|
||||
// Actually set the scheduling algorithm
|
||||
/* Actually set the scheduling algorithm */
|
||||
rtl839x_read_scheduling_table(port);
|
||||
sw_w32_mask(BIT(19), sched ? BIT(19) : 0, RTL839X_TBL_ACCESS_DATA_2(8));
|
||||
rtl839x_write_scheduling_table(port);
|
||||
|
||||
if (sched == WEIGHTED_FAIR_QUEUE && t == WEIGHTED_ROUND_ROBIN && port != priv->cpu_port) {
|
||||
// Restore OAM state to control register
|
||||
/* Restore OAM state to control register */
|
||||
sw_w32(oam_state, RTL839X_OAM_CTRL);
|
||||
|
||||
// Restore trap action state
|
||||
/* Restore trap action state */
|
||||
sw_w32(oam_port_state, RTL839X_OAM_PORT_ACT_CTRL(port));
|
||||
|
||||
// Restore port egress rate
|
||||
/* Restore port egress rate */
|
||||
rtl839x_set_egress_rate(priv, port, egress_rate);
|
||||
}
|
||||
|
||||
@ -431,17 +424,16 @@ void rtl839x_set_scheduling_algorithm(struct rtl838x_switch_priv *priv, int port
|
||||
void rtl839x_set_scheduling_queue_weights(struct rtl838x_switch_priv *priv, int port,
|
||||
int *queue_weights)
|
||||
{
|
||||
int i, lsb, low_byte, start_bit, high_mask;
|
||||
|
||||
mutex_lock(&priv->reg_mutex);
|
||||
|
||||
rtl839x_read_scheduling_table(port);
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
lsb = 48 + i * 8;
|
||||
low_byte = 8 - (lsb >> 5);
|
||||
start_bit = lsb - (low_byte << 5);
|
||||
high_mask = 0x3ff >> (32 - start_bit);
|
||||
for (int i = 0; i < 8; i++) {
|
||||
int lsb = 48 + i * 8;
|
||||
int low_byte = 8 - (lsb >> 5);
|
||||
int start_bit = lsb - (low_byte << 5);
|
||||
int high_mask = 0x3ff >> (32 - start_bit);
|
||||
|
||||
sw_w32_mask(0x3ff << start_bit, (queue_weights[i] & 0x3ff) << start_bit,
|
||||
RTL839X_TBL_ACCESS_DATA_2(low_byte));
|
||||
if (high_mask)
|
||||
@ -455,14 +447,13 @@ void rtl839x_set_scheduling_queue_weights(struct rtl838x_switch_priv *priv, int
|
||||
|
||||
void rtl838x_config_qos(void)
|
||||
{
|
||||
int i, p;
|
||||
u32 v;
|
||||
|
||||
pr_info("Setting up RTL838X QoS\n");
|
||||
pr_info("RTL838X_PRI_SEL_TBL_CTRL(i): %08x\n", sw_r32(RTL838X_PRI_SEL_TBL_CTRL(0)));
|
||||
rtl83xx_setup_default_prio2queue();
|
||||
|
||||
// Enable inner (bit 12) and outer (bit 13) priority remapping from DSCP
|
||||
/* Enable inner (bit 12) and outer (bit 13) priority remapping from DSCP */
|
||||
sw_w32_mask(0, BIT(12) | BIT(13), RTL838X_PRI_DSCP_INVLD_CTRL0);
|
||||
|
||||
/* Set default weight for calculating internal priority, in prio selection group 0
|
||||
@ -471,37 +462,36 @@ void rtl838x_config_qos(void)
|
||||
v = 3 | (4 << 3) | (5 << 6) | (6 << 9) | (7 << 12);
|
||||
sw_w32(v, RTL838X_PRI_SEL_TBL_CTRL(0));
|
||||
|
||||
// Set the inner and outer priority one-to-one to re-marked outer dot1p priority
|
||||
/* Set the inner and outer priority one-to-one to re-marked outer dot1p priority */
|
||||
v = 0;
|
||||
for (p = 0; p < 8; p++)
|
||||
for (int p = 0; p < 8; p++)
|
||||
v |= p << (3 * p);
|
||||
sw_w32(v, RTL838X_RMK_OPRI_CTRL);
|
||||
sw_w32(v, RTL838X_RMK_IPRI_CTRL);
|
||||
|
||||
v = 0;
|
||||
for (p = 0; p < 8; p++)
|
||||
for (int p = 0; p < 8; p++)
|
||||
v |= (dot1p_priority_remapping[p] & 0x7) << (p * 3);
|
||||
sw_w32(v, RTL838X_PRI_SEL_IPRI_REMAP);
|
||||
|
||||
// On all ports set scheduler type to WFQ
|
||||
for (i = 0; i <= soc_info.cpu_port; i++)
|
||||
/* On all ports set scheduler type to WFQ */
|
||||
for (int i = 0; i <= soc_info.cpu_port; i++)
|
||||
sw_w32(0, RTL838X_SCHED_P_TYPE_CTRL(i));
|
||||
|
||||
// Enable egress scheduler for CPU-Port
|
||||
/* Enable egress scheduler for CPU-Port */
|
||||
sw_w32_mask(0, BIT(8), RTL838X_SCHED_LB_CTRL(soc_info.cpu_port));
|
||||
|
||||
// Enable egress drop allways on
|
||||
/* Enable egress drop allways on */
|
||||
sw_w32_mask(0, BIT(11), RTL838X_FC_P_EGR_DROP_CTRL(soc_info.cpu_port));
|
||||
|
||||
// Give special trap frames priority 7 (BPDUs) and routing exceptions:
|
||||
/* Give special trap frames priority 7 (BPDUs) and routing exceptions: */
|
||||
sw_w32_mask(0, 7 << 3 | 7, RTL838X_QM_PKT2CPU_INTPRI_2);
|
||||
// Give RMA frames priority 7:
|
||||
/* Give RMA frames priority 7: */
|
||||
sw_w32_mask(0, 7, RTL838X_QM_PKT2CPU_INTPRI_1);
|
||||
}
|
||||
|
||||
void rtl839x_config_qos(void)
|
||||
{
|
||||
int port, p, q;
|
||||
u32 v;
|
||||
struct rtl838x_switch_priv *priv = switch_priv;
|
||||
|
||||
@ -509,26 +499,26 @@ void rtl839x_config_qos(void)
|
||||
pr_info("RTL839X_PRI_SEL_TBL_CTRL(i): %08x\n", sw_r32(RTL839X_PRI_SEL_TBL_CTRL(0)));
|
||||
rtl83xx_setup_default_prio2queue();
|
||||
|
||||
for (port = 0; port < soc_info.cpu_port; port++)
|
||||
for (int port = 0; port < soc_info.cpu_port; port++)
|
||||
sw_w32(7, RTL839X_QM_PORT_QNUM(port));
|
||||
|
||||
// CPU-port gets queue number 7
|
||||
/* CPU-port gets queue number 7 */
|
||||
sw_w32(7, RTL839X_QM_PORT_QNUM(soc_info.cpu_port));
|
||||
|
||||
for (port = 0; port <= soc_info.cpu_port; port++) {
|
||||
for (int port = 0; port <= soc_info.cpu_port; port++) {
|
||||
rtl83xx_set_ingress_priority(port, 0);
|
||||
rtl839x_set_scheduling_algorithm(priv, port, WEIGHTED_FAIR_QUEUE);
|
||||
rtl839x_set_scheduling_queue_weights(priv, port, default_queue_weights);
|
||||
// Do re-marking based on outer tag
|
||||
/* Do re-marking based on outer tag */
|
||||
sw_w32_mask(0, BIT(port % 32), RTL839X_RMK_PORT_DEI_TAG_CTRL(port));
|
||||
}
|
||||
|
||||
// Remap dot1p priorities to internal priority, for this the outer tag needs be re-marked
|
||||
/* Remap dot1p priorities to internal priority, for this the outer tag needs be re-marked */
|
||||
v = 0;
|
||||
for (p = 0; p < 8; p++)
|
||||
for (int p = 0; p < 8; p++)
|
||||
v |= (dot1p_priority_remapping[p] & 0x7) << (p * 3);
|
||||
sw_w32(v, RTL839X_PRI_SEL_IPRI_REMAP);
|
||||
|
||||
|
||||
/* Configure Drop Precedence for Drop Eligible Indicator (DEI)
|
||||
* Index 0: 0
|
||||
* Index 1: 2
|
||||
@ -536,7 +526,7 @@ void rtl839x_config_qos(void)
|
||||
*/
|
||||
sw_w32(2 << 2, RTL839X_PRI_SEL_DEI2DP_REMAP);
|
||||
|
||||
// Re-mark DEI: 4 bit-fields of 2 bits each, field 0 is bits 0-1, ...
|
||||
/* Re-mark DEI: 4 bit-fields of 2 bits each, field 0 is bits 0-1, ... */
|
||||
sw_w32((0x1 << 2) | (0x1 << 4), RTL839X_RMK_DEI_CTRL);
|
||||
|
||||
/* Set Congestion avoidance drop probability to 0 for drop precedences 0-2 (bits 24-31)
|
||||
@ -550,7 +540,7 @@ void rtl839x_config_qos(void)
|
||||
/* Set queue-based congestion avoidance properties, register fields are as
|
||||
* for forward RTL839X_WRED_PORT_THR_CTRL
|
||||
*/
|
||||
for (q = 0; q < 8; q++) {
|
||||
for (int q = 0; q < 8; q++) {
|
||||
sw_w32(255 << 24 | 78 << 12 | 68, RTL839X_WRED_QUEUE_THR_CTRL(q, 0));
|
||||
sw_w32(255 << 24 | 74 << 12 | 64, RTL839X_WRED_QUEUE_THR_CTRL(q, 0));
|
||||
sw_w32(255 << 24 | 70 << 12 | 60, RTL839X_WRED_QUEUE_THR_CTRL(q, 0));
|
||||
@ -572,5 +562,4 @@ void __init rtl83xx_setup_qos(struct rtl838x_switch_priv *priv)
|
||||
rtl838x_rate_control_init(priv);
|
||||
else if (priv->family_id == RTL8390_FAMILY_ID)
|
||||
rtl839x_rate_control_init(priv);
|
||||
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -5,9 +5,7 @@
|
||||
|
||||
#include <net/dsa.h>
|
||||
|
||||
/*
|
||||
* Register definition
|
||||
*/
|
||||
/* Register definition */
|
||||
#define RTL838X_MAC_PORT_CTRL(port) (0xd560 + (((port) << 7)))
|
||||
#define RTL839X_MAC_PORT_CTRL(port) (0x8004 + (((port) << 7)))
|
||||
#define RTL930X_MAC_PORT_CTRL(port) (0x3260 + (((port) << 6)))
|
||||
@ -398,17 +396,16 @@
|
||||
#define RTL839X_SPCL_TRAP_SWITCH_IPV4_ADDR_CTRL (0x106C)
|
||||
#define RTL839X_SPCL_TRAP_CRC_CTRL (0x1070)
|
||||
/* special port action controls */
|
||||
/*
|
||||
values:
|
||||
0 = FORWARD (default)
|
||||
1 = DROP
|
||||
2 = TRAP2CPU
|
||||
3 = FLOOD IN ALL PORT
|
||||
|
||||
Register encoding.
|
||||
offset = CTRL + (port >> 4) << 2
|
||||
value/mask = 3 << ((port&0xF) << 1)
|
||||
*/
|
||||
/* values:
|
||||
* 0 = FORWARD (default)
|
||||
* 1 = DROP
|
||||
* 2 = TRAP2CPU
|
||||
* 3 = FLOOD IN ALL PORT
|
||||
*
|
||||
* Register encoding.
|
||||
* offset = CTRL + (port >> 4) << 2
|
||||
* value/mask = 3 << ((port & 0xF) << 1)
|
||||
*/
|
||||
|
||||
typedef enum {
|
||||
BPDU = 0,
|
||||
@ -429,17 +426,17 @@ typedef enum {
|
||||
COPY2CPU,
|
||||
} action_type_t;
|
||||
|
||||
#define RTL838X_RMA_BPDU_CTRL (0x4330)
|
||||
#define RTL838X_RMA_BPDU_CTRL (0x4330)
|
||||
#define RTL839X_RMA_BPDU_CTRL (0x122C)
|
||||
#define RTL930X_RMA_BPDU_CTRL (0x9E7C)
|
||||
#define RTL931X_RMA_BPDU_CTRL (0x881C)
|
||||
|
||||
#define RTL838X_RMA_PTP_CTRL (0x4338)
|
||||
#define RTL838X_RMA_PTP_CTRL (0x4338)
|
||||
#define RTL839X_RMA_PTP_CTRL (0x123C)
|
||||
#define RTL930X_RMA_PTP_CTRL (0x9E88)
|
||||
#define RTL931X_RMA_PTP_CTRL (0x8834)
|
||||
|
||||
#define RTL838X_RMA_LLTP_CTRL (0x4340)
|
||||
#define RTL838X_RMA_LLTP_CTRL (0x4340)
|
||||
#define RTL839X_RMA_LLTP_CTRL (0x124C)
|
||||
#define RTL930X_RMA_LLTP_CTRL (0x9EFC)
|
||||
#define RTL931X_RMA_LLTP_CTRL (0x8918)
|
||||
@ -521,13 +518,13 @@ typedef enum {
|
||||
#define RTL930X_PIE_BLK_PHASE_CTRL (0xA5A4)
|
||||
#define RTL931X_PIE_BLK_PHASE_CTRL (0x4184)
|
||||
|
||||
// PIE actions
|
||||
/* PIE actions */
|
||||
#define PIE_ACT_COPY_TO_PORT 2
|
||||
#define PIE_ACT_REDIRECT_TO_PORT 4
|
||||
#define PIE_ACT_ROUTE_UC 6
|
||||
#define PIE_ACT_VID_ASSIGN 0
|
||||
|
||||
// L3 actions
|
||||
/* L3 actions */
|
||||
#define L3_FORWARD 0
|
||||
#define L3_DROP 1
|
||||
#define L3_TRAP2CPU 2
|
||||
@ -536,7 +533,7 @@ typedef enum {
|
||||
#define L3_COPY2MASTERCPU 5
|
||||
#define L3_HARDDROP 6
|
||||
|
||||
// Route actions
|
||||
/* Route actions */
|
||||
#define ROUTE_ACT_FORWARD 0
|
||||
#define ROUTE_ACT_TRAP2CPU 1
|
||||
#define ROUTE_ACT_COPY2CPU 2
|
||||
@ -634,10 +631,10 @@ struct rtl838x_vlan_info {
|
||||
u8 profile_id;
|
||||
bool hash_mc_fid;
|
||||
bool hash_uc_fid;
|
||||
u8 fid; // AKA MSTI
|
||||
u8 fid; /* AKA MSTI */
|
||||
|
||||
// The following fields are used only by the RTL931X
|
||||
int if_id; // Interface (index in L3_EGR_INTF_IDX)
|
||||
/* The following fields are used only by the RTL931X */
|
||||
int if_id; /* Interface (index in L3_EGR_INTF_IDX) */
|
||||
u16 multicast_grp_mask;
|
||||
int l2_tunnel_list_id;
|
||||
};
|
||||
@ -673,9 +670,9 @@ struct rtl838x_l2_entry {
|
||||
u32 mc_sip;
|
||||
u16 mc_mac_index;
|
||||
u16 nh_route_id;
|
||||
bool nh_vlan_target; // Only RTL83xx: VLAN used for next hop
|
||||
bool nh_vlan_target; /* Only RTL83xx: VLAN used for next hop */
|
||||
|
||||
// The following is only valid on RTL931x
|
||||
/* The following is only valid on RTL931x */
|
||||
bool is_open_flow;
|
||||
bool is_pe_forward;
|
||||
bool is_local_forward;
|
||||
@ -712,35 +709,35 @@ enum egr_filter {
|
||||
* to SoC family (e.g. because of different port ranges) */
|
||||
struct pie_rule {
|
||||
int id;
|
||||
enum pie_phase phase; // Phase in which this template is applied
|
||||
int packet_cntr; // ID of a packet counter assigned to this rule
|
||||
int octet_cntr; // ID of a byte counter assigned to this rule
|
||||
enum pie_phase phase; /* Phase in which this template is applied */
|
||||
int packet_cntr; /* ID of a packet counter assigned to this rule */
|
||||
int octet_cntr; /* ID of a byte counter assigned to this rule */
|
||||
u32 last_packet_cnt;
|
||||
u64 last_octet_cnt;
|
||||
|
||||
// The following are requirements for the pie template
|
||||
/* The following are requirements for the pie template */
|
||||
bool is_egress;
|
||||
bool is_ipv6; // This is a rule with IPv6 fields
|
||||
bool is_ipv6; /* This is a rule with IPv6 fields */
|
||||
|
||||
// Fixed fields that are always matched against on RTL8380
|
||||
/* Fixed fields that are always matched against on RTL8380 */
|
||||
u8 spmmask_fix;
|
||||
u8 spn; // Source port number
|
||||
bool stacking_port; // Source port is stacking port
|
||||
bool mgnt_vlan; // Packet arrived on management VLAN
|
||||
bool dmac_hit_sw; // The packet's destination MAC matches one of the device's
|
||||
bool content_too_deep; // The content of the packet cannot be parsed: too many layers
|
||||
bool not_first_frag; // Not the first IP fragment
|
||||
u8 frame_type_l4; // 0: UDP, 1: TCP, 2: ICMP/ICMPv6, 3: IGMP
|
||||
u8 frame_type; // 0: ARP, 1: L2 only, 2: IPv4, 3: IPv6
|
||||
bool otag_fmt; // 0: outer tag packet, 1: outer priority tag or untagged
|
||||
bool itag_fmt; // 0: inner tag packet, 1: inner priority tag or untagged
|
||||
bool otag_exist; // packet with outer tag
|
||||
bool itag_exist; // packet with inner tag
|
||||
bool frame_type_l2; // 0: Ethernet, 1: LLC_SNAP, 2: LLC_Other, 3: Reserved
|
||||
bool igr_normal_port; // Ingress port is not cpu or stacking port
|
||||
u8 tid; // The template ID defining the what the templated fields mean
|
||||
u8 spn; /* Source port number */
|
||||
bool stacking_port; /* Source port is stacking port */
|
||||
bool mgnt_vlan; /* Packet arrived on management VLAN */
|
||||
bool dmac_hit_sw; /* The packet's destination MAC matches one of the device's */
|
||||
bool content_too_deep; /* The content of the packet cannot be parsed: too many layers */
|
||||
bool not_first_frag; /* Not the first IP fragment */
|
||||
u8 frame_type_l4; /* 0: UDP, 1: TCP, 2: ICMP/ICMPv6, 3: IGMP */
|
||||
u8 frame_type; /* 0: ARP, 1: L2 only, 2: IPv4, 3: IPv6 */
|
||||
bool otag_fmt; /* 0: outer tag packet, 1: outer priority tag or untagged */
|
||||
bool itag_fmt; /* 0: inner tag packet, 1: inner priority tag or untagged */
|
||||
bool otag_exist; /* packet with outer tag */
|
||||
bool itag_exist; /* packet with inner tag */
|
||||
bool frame_type_l2; /* 0: Ethernet, 1: LLC_SNAP, 2: LLC_Other, 3: Reserved */
|
||||
bool igr_normal_port; /* Ingress port is not cpu or stacking port */
|
||||
u8 tid; /* The template ID defining the what the templated fields mean */
|
||||
|
||||
// Masks for the fields that are always matched against on RTL8380
|
||||
/* Masks for the fields that are always matched against on RTL8380 */
|
||||
u8 spmmask_fix_m;
|
||||
u8 spn_m;
|
||||
bool stacking_port_m;
|
||||
@ -758,52 +755,52 @@ struct pie_rule {
|
||||
bool igr_normal_port_m;
|
||||
u8 tid_m;
|
||||
|
||||
// Logical operations between rules, special rules for rule numbers apply
|
||||
/* Logical operations between rules, special rules for rule numbers apply */
|
||||
bool valid;
|
||||
bool cond_not; // Matches when conditions not match
|
||||
bool cond_and1; // And this rule 2n with the next rule 2n+1 in same block
|
||||
bool cond_and2; // And this rule m in block 2n with rule m in block 2n+1
|
||||
bool cond_not; /* Matches when conditions not match */
|
||||
bool cond_and1; /* And this rule 2n with the next rule 2n+1 in same block */
|
||||
bool cond_and2; /* And this rule m in block 2n with rule m in block 2n+1 */
|
||||
bool ivalid;
|
||||
|
||||
// Actions to be performed
|
||||
bool drop; // Drop the packet
|
||||
bool fwd_sel; // Forward packet: to port, portmask, dest route, next rule, drop
|
||||
bool ovid_sel; // So something to outer vlan-id: shift, re-assign
|
||||
bool ivid_sel; // Do something to inner vlan-id: shift, re-assign
|
||||
bool flt_sel; // Filter the packet when sending to certain ports
|
||||
bool log_sel; // Log the packet in one of the LOG-table counters
|
||||
bool rmk_sel; // Re-mark the packet, i.e. change the priority-tag
|
||||
bool meter_sel; // Meter the packet, i.e. limit rate of this type of packet
|
||||
bool tagst_sel; // Change the ergress tag
|
||||
bool mir_sel; // Mirror the packet to a Link Aggregation Group
|
||||
bool nopri_sel; // Change the normal priority
|
||||
bool cpupri_sel; // Change the CPU priority
|
||||
bool otpid_sel; // Change Outer Tag Protocol Identifier (802.1q)
|
||||
bool itpid_sel; // Change Inner Tag Protocol Identifier (802.1q)
|
||||
bool shaper_sel; // Apply traffic shaper
|
||||
bool mpls_sel; // MPLS actions
|
||||
bool bypass_sel; // Bypass actions
|
||||
bool fwd_sa_lrn; // Learn the source address when forwarding
|
||||
bool fwd_mod_to_cpu; // Forward the modified VLAN tag format to CPU-port
|
||||
/* Actions to be performed */
|
||||
bool drop; /* Drop the packet */
|
||||
bool fwd_sel; /* Forward packet: to port, portmask, dest route, next rule, drop */
|
||||
bool ovid_sel; /* So something to outer vlan-id: shift, re-assign */
|
||||
bool ivid_sel; /* Do something to inner vlan-id: shift, re-assign */
|
||||
bool flt_sel; /* Filter the packet when sending to certain ports */
|
||||
bool log_sel; /* Log the packet in one of the LOG-table counters */
|
||||
bool rmk_sel; /* Re-mark the packet, i.e. change the priority-tag */
|
||||
bool meter_sel; /* Meter the packet, i.e. limit rate of this type of packet */
|
||||
bool tagst_sel; /* Change the ergress tag */
|
||||
bool mir_sel; /* Mirror the packet to a Link Aggregation Group */
|
||||
bool nopri_sel; /* Change the normal priority */
|
||||
bool cpupri_sel; /* Change the CPU priority */
|
||||
bool otpid_sel; /* Change Outer Tag Protocol Identifier (802.1q) */
|
||||
bool itpid_sel; /* Change Inner Tag Protocol Identifier (802.1q) */
|
||||
bool shaper_sel; /* Apply traffic shaper */
|
||||
bool mpls_sel; /* MPLS actions */
|
||||
bool bypass_sel; /* Bypass actions */
|
||||
bool fwd_sa_lrn; /* Learn the source address when forwarding */
|
||||
bool fwd_mod_to_cpu; /* Forward the modified VLAN tag format to CPU-port */
|
||||
|
||||
// Fields used in predefined templates 0-2 on RTL8380 / 90 / 9300
|
||||
u64 spm; // Source Port Matrix
|
||||
u16 otag; // Outer VLAN-ID
|
||||
u8 smac[ETH_ALEN]; // Source MAC address
|
||||
u8 dmac[ETH_ALEN]; // Destination MAC address
|
||||
u16 ethertype; // Ethernet frame type field in ethernet header
|
||||
u16 itag; // Inner VLAN-ID
|
||||
/* Fields used in predefined templates 0-2 on RTL8380 / 90 / 9300 */
|
||||
u64 spm; /* Source Port Matrix */
|
||||
u16 otag; /* Outer VLAN-ID */
|
||||
u8 smac[ETH_ALEN]; /* Source MAC address */
|
||||
u8 dmac[ETH_ALEN]; /* Destination MAC address */
|
||||
u16 ethertype; /* Ethernet frame type field in ethernet header */
|
||||
u16 itag; /* Inner VLAN-ID */
|
||||
u16 field_range_check;
|
||||
u32 sip; // Source IP
|
||||
struct in6_addr sip6; // IPv6 Source IP
|
||||
u32 dip; // Destination IP
|
||||
struct in6_addr dip6; // IPv6 Destination IP
|
||||
u16 tos_proto; // IPv4: TOS + Protocol fields, IPv6: Traffic class + next header
|
||||
u16 sport; // TCP/UDP source port
|
||||
u16 dport; // TCP/UDP destination port
|
||||
u32 sip; /* Source IP */
|
||||
struct in6_addr sip6; /* IPv6 Source IP */
|
||||
u32 dip; /* Destination IP */
|
||||
struct in6_addr dip6; /* IPv6 Destination IP */
|
||||
u16 tos_proto; /* IPv4: TOS + Protocol fields, IPv6: Traffic class + next header */
|
||||
u16 sport; /* TCP/UDP source port */
|
||||
u16 dport; /* TCP/UDP destination port */
|
||||
u16 icmp_igmp;
|
||||
u16 tcp_info;
|
||||
u16 dsap_ssap; // Destination / Source Service Access Point bytes (802.3)
|
||||
u16 dsap_ssap; /* Destination / Source Service Access Point bytes (802.3) */
|
||||
|
||||
u64 spm_m;
|
||||
u16 otag_m;
|
||||
@ -813,9 +810,9 @@ struct pie_rule {
|
||||
u16 itag_m;
|
||||
u16 field_range_check_m;
|
||||
u32 sip_m;
|
||||
struct in6_addr sip6_m; // IPv6 Source IP mask
|
||||
struct in6_addr sip6_m; /* IPv6 Source IP mask */
|
||||
u32 dip_m;
|
||||
struct in6_addr dip6_m; // IPv6 Destination IP mask
|
||||
struct in6_addr dip6_m; /* IPv6 Destination IP mask */
|
||||
u16 tos_proto_m;
|
||||
u16 sport_m;
|
||||
u16 dport_m;
|
||||
@ -823,25 +820,25 @@ struct pie_rule {
|
||||
u16 tcp_info_m;
|
||||
u16 dsap_ssap_m;
|
||||
|
||||
// Data associated with actions
|
||||
u8 fwd_act; // Type of forwarding action
|
||||
// 0: permit, 1: drop, 2: copy to port id, 4: copy to portmask
|
||||
// 4: redirect to portid, 5: redirect to portmask
|
||||
// 6: route, 7: vlan leaky (only 8380)
|
||||
u16 fwd_data; // Additional data for forwarding action, e.g. destination port
|
||||
/* Data associated with actions */
|
||||
u8 fwd_act; /* Type of forwarding action */
|
||||
/* 0: permit, 1: drop, 2: copy to port id, 4: copy to portmask */
|
||||
/* 4: redirect to portid, 5: redirect to portmask */
|
||||
/* 6: route, 7: vlan leaky (only 8380) */
|
||||
u16 fwd_data; /* Additional data for forwarding action, e.g. destination port */
|
||||
u8 ovid_act;
|
||||
u16 ovid_data; // Outer VLAN ID
|
||||
u16 ovid_data; /* Outer VLAN ID */
|
||||
u8 ivid_act;
|
||||
u16 ivid_data; // Inner VLAN ID
|
||||
u16 flt_data; // Filtering data
|
||||
u16 log_data; // ID of packet or octet counter in LOG table, on RTL93xx
|
||||
// unnecessary since PIE-Rule-ID == LOG-counter-ID
|
||||
u16 ivid_data; /* Inner VLAN ID */
|
||||
u16 flt_data; /* Filtering data */
|
||||
u16 log_data; /* ID of packet or octet counter in LOG table, on RTL93xx */
|
||||
/* unnecessary since PIE-Rule-ID == LOG-counter-ID */
|
||||
bool log_octets;
|
||||
u8 mpls_act; // MPLS action type
|
||||
u16 mpls_lib_idx; // MPLS action data
|
||||
u8 mpls_act; /* MPLS action type */
|
||||
u16 mpls_lib_idx; /* MPLS action data */
|
||||
|
||||
u16 rmk_data; // Data for remarking
|
||||
u16 meter_data; // ID of meter for bandwidth control
|
||||
u16 rmk_data; /* Data for remarking */
|
||||
u16 meter_data; /* ID of meter for bandwidth control */
|
||||
u16 tagst_data;
|
||||
u16 mir_data;
|
||||
u16 nopri_data;
|
||||
@ -850,10 +847,10 @@ struct pie_rule {
|
||||
u16 itpid_data;
|
||||
u16 shaper_data;
|
||||
|
||||
// Bypass actions, ignored on RTL8380
|
||||
bool bypass_all; // Not clear
|
||||
bool bypass_igr_stp; // Bypass Ingress STP state
|
||||
bool bypass_ibc_sc; // Bypass Ingress Bandwidth Control and Storm Control
|
||||
/* Bypass actions, ignored on RTL8380 */
|
||||
bool bypass_all; /* Not clear */
|
||||
bool bypass_igr_stp; /* Bypass Ingress STP state */
|
||||
bool bypass_ibc_sc; /* Bypass Ingress Bandwidth Control and Storm Control */
|
||||
};
|
||||
|
||||
struct rtl838x_l3_intf {
|
||||
@ -871,37 +868,36 @@ struct rtl838x_l3_intf {
|
||||
u8 ip6_pbr_icmp_redirect;
|
||||
};
|
||||
|
||||
/*
|
||||
* An entry in the RTL93XX SoC's ROUTER_MAC tables setting up a termination point
|
||||
/* An entry in the RTL93XX SoC's ROUTER_MAC tables setting up a termination point
|
||||
* for the L3 routing system. Packets arriving and matching an entry in this table
|
||||
* will be considered for routing.
|
||||
* Mask fields state whether the corresponding data fields matter for matching
|
||||
*/
|
||||
struct rtl93xx_rt_mac {
|
||||
bool valid; // Valid or not
|
||||
bool p_type; // Individual (0) or trunk (1) port
|
||||
bool p_mask; // Whether the port type is used
|
||||
bool valid; /* Valid or not */
|
||||
bool p_type; /* Individual (0) or trunk (1) port */
|
||||
bool p_mask; /* Whether the port type is used */
|
||||
u8 p_id;
|
||||
u8 p_id_mask; // Mask for the port
|
||||
u8 action; // Routing action performed: 0: FORWARD, 1: DROP, 2: TRAP2CPU
|
||||
// 3: COPY2CPU, 4: TRAP2MASTERCPU, 5: COPY2MASTERCPU, 6: HARDDROP
|
||||
u8 p_id_mask; /* Mask for the port */
|
||||
u8 action; /* Routing action performed: 0: FORWARD, 1: DROP, 2: TRAP2CPU */
|
||||
/* 3: COPY2CPU, 4: TRAP2MASTERCPU, 5: COPY2MASTERCPU, 6: HARDDROP */
|
||||
u16 vid;
|
||||
u16 vid_mask;
|
||||
u64 mac; // MAC address used as source MAC in the routed packet
|
||||
u64 mac; /* MAC address used as source MAC in the routed packet */
|
||||
u64 mac_mask;
|
||||
};
|
||||
|
||||
struct rtl83xx_nexthop {
|
||||
u16 id; // ID: L3_NEXT_HOP table-index or route-index set in L2_NEXT_HOP
|
||||
u16 id; /* ID: L3_NEXT_HOP table-index or route-index set in L2_NEXT_HOP */
|
||||
u32 dev_id;
|
||||
u16 port;
|
||||
u16 vid; // VLAN-ID for L2 table entry (saved from L2-UC entry)
|
||||
u16 rvid; // Relay VID/FID for the L2 table entry
|
||||
u64 mac; // The MAC address of the entry in the L2_NEXT_HOP table
|
||||
u16 vid; /* VLAN-ID for L2 table entry (saved from L2-UC entry) */
|
||||
u16 rvid; /* Relay VID/FID for the L2 table entry */
|
||||
u64 mac; /* The MAC address of the entry in the L2_NEXT_HOP table */
|
||||
u16 mac_id;
|
||||
u16 l2_id; // Index of this next hop forwarding entry in L2 FIB table
|
||||
u64 gw; // The gateway MAC address packets are forwarded to
|
||||
int if_id; // Interface (into L3_EGR_INTF_IDX)
|
||||
u16 l2_id; /* Index of this next hop forwarding entry in L2 FIB table */
|
||||
u64 gw; /* The gateway MAC address packets are forwarded to */
|
||||
int if_id; /* Interface (into L3_EGR_INTF_IDX) */
|
||||
};
|
||||
|
||||
struct rtl838x_switch_priv;
|
||||
@ -928,14 +924,14 @@ struct rtl93xx_route_attr {
|
||||
};
|
||||
|
||||
struct rtl83xx_route {
|
||||
u32 gw_ip; // IP of the route's gateway
|
||||
u32 dst_ip; // IP of the destination net
|
||||
u32 gw_ip; /* IP of the route's gateway */
|
||||
u32 dst_ip; /* IP of the destination net */
|
||||
struct in6_addr dst_ip6;
|
||||
int prefix_len; // Network prefix len of the destination net
|
||||
int prefix_len; /* Network prefix len of the destination net */
|
||||
bool is_host_route;
|
||||
int id; // ID number of this route
|
||||
int id; /* ID number of this route */
|
||||
struct rhlist_head linkage;
|
||||
u16 switch_mac_id; // Index into switch's own MACs, RTL839X only
|
||||
u16 switch_mac_id; /* Index into switch's own MACs, RTL839X only */
|
||||
struct rtl83xx_nexthop nh;
|
||||
struct pie_rule pr;
|
||||
struct rtl93xx_route_attr attr;
|
||||
@ -1047,8 +1043,8 @@ struct rtl838x_switch_priv {
|
||||
u16 family_id;
|
||||
char version;
|
||||
struct rtl838x_port ports[57];
|
||||
struct mutex reg_mutex; // Mutex for individual register manipulations
|
||||
struct mutex pie_mutex; // Mutex for Packet Inspection Engine
|
||||
struct mutex reg_mutex; /* Mutex for individual register manipulations */
|
||||
struct mutex pie_mutex; /* Mutex for Packet Inspection Engine */
|
||||
int link_state_irq;
|
||||
int mirror_group_ports[4];
|
||||
struct mii_bus *mii_bus;
|
||||
@ -1067,7 +1063,7 @@ struct rtl838x_switch_priv {
|
||||
u32 lag_primary[MAX_LAGS];
|
||||
u32 is_lagmember[57];
|
||||
u64 lagmembers;
|
||||
struct notifier_block nb; // TODO: change to different name
|
||||
struct notifier_block nb; /* TODO: change to different name */
|
||||
struct notifier_block ne_nb;
|
||||
struct notifier_block fib_nb;
|
||||
bool eee_enabled;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -67,8 +67,8 @@ typedef enum {
|
||||
void rtl_table_init(void);
|
||||
struct table_reg *rtl_table_get(rtl838x_tbl_reg_t r, int t);
|
||||
void rtl_table_release(struct table_reg *r);
|
||||
void rtl_table_read(struct table_reg *r, int idx);
|
||||
void rtl_table_write(struct table_reg *r, int idx);
|
||||
int rtl_table_read(struct table_reg *r, int idx);
|
||||
int rtl_table_write(struct table_reg *r, int idx);
|
||||
inline u16 rtl_table_data(struct table_reg *r, int i);
|
||||
inline u32 rtl_table_data_r(struct table_reg *r, int i);
|
||||
inline void rtl_table_data_w(struct table_reg *r, u32 v, int i);
|
||||
@ -134,4 +134,3 @@ int rtl83xx_lag_add(struct dsa_switch *ds, int group, int port, struct netdev_la
|
||||
int rtl83xx_lag_del(struct dsa_switch *ds, int group, int port);
|
||||
|
||||
#endif /* _NET_DSA_RTL83XX_H */
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,6 +1,7 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
#include <asm/mach-rtl838x/mach-rtl83xx.h>
|
||||
|
||||
#include "rtl83xx.h"
|
||||
|
||||
#define RTL931X_VLAN_PORT_TAG_STS_INTERNAL 0x0
|
||||
@ -79,9 +80,9 @@ enum template_field_id {
|
||||
*/
|
||||
#define TEMPLATE_FIELD_VLAN TEMPLATE_FIELD_ITAG
|
||||
|
||||
// Number of fixed templates predefined in the RTL9300 SoC
|
||||
/* Number of fixed templates predefined in the RTL9300 SoC */
|
||||
#define N_FIXED_TEMPLATES 5
|
||||
// RTL931x specific predefined templates
|
||||
/* RTL931x specific predefined templates */
|
||||
static enum template_field_id fixed_templates[N_FIXED_TEMPLATES][N_FIXED_FIELDS_RTL931X] =
|
||||
{
|
||||
{
|
||||
@ -142,12 +143,12 @@ void rtl931x_vlan_profile_dump(int index)
|
||||
return;
|
||||
|
||||
profile[0] = sw_r32(RTL931X_VLAN_PROFILE_SET(index));
|
||||
profile[1] = (sw_r32(RTL931X_VLAN_PROFILE_SET(index) + 4) & 0x1FFFFFFFULL) << 32
|
||||
| (sw_r32(RTL931X_VLAN_PROFILE_SET(index) + 8) & 0xFFFFFFFF);
|
||||
profile[2] = (sw_r32(RTL931X_VLAN_PROFILE_SET(index) + 16) & 0x1FFFFFFFULL) << 32
|
||||
| (sw_r32(RTL931X_VLAN_PROFILE_SET(index) + 12) & 0xFFFFFFFF);
|
||||
profile[3] = (sw_r32(RTL931X_VLAN_PROFILE_SET(index) + 20) & 0x1FFFFFFFULL) << 32
|
||||
| (sw_r32(RTL931X_VLAN_PROFILE_SET(index) + 24) & 0xFFFFFFFF);
|
||||
profile[1] = (sw_r32(RTL931X_VLAN_PROFILE_SET(index) + 4) & 0x1FFFFFFFULL) << 32 |
|
||||
(sw_r32(RTL931X_VLAN_PROFILE_SET(index) + 8) & 0xFFFFFFFF);
|
||||
profile[2] = (sw_r32(RTL931X_VLAN_PROFILE_SET(index) + 16) & 0x1FFFFFFFULL) << 32 |
|
||||
(sw_r32(RTL931X_VLAN_PROFILE_SET(index) + 12) & 0xFFFFFFFF);
|
||||
profile[3] = (sw_r32(RTL931X_VLAN_PROFILE_SET(index) + 20) & 0x1FFFFFFFULL) << 32 |
|
||||
(sw_r32(RTL931X_VLAN_PROFILE_SET(index) + 24) & 0xFFFFFFFF);
|
||||
|
||||
pr_info("VLAN %d: L2 learning: %d, L2 Unknown MultiCast Field %llx, \
|
||||
IPv4 Unknown MultiCast Field %llx, IPv6 Unknown MultiCast Field: %llx",
|
||||
@ -156,25 +157,23 @@ void rtl931x_vlan_profile_dump(int index)
|
||||
|
||||
static void rtl931x_stp_get(struct rtl838x_switch_priv *priv, u16 msti, u32 port_state[])
|
||||
{
|
||||
int i;
|
||||
u32 cmd = 1 << 20 /* Execute cmd */
|
||||
| 0 << 19 /* Read */
|
||||
| 5 << 15 /* Table type 0b101 */
|
||||
| (msti & 0x3fff);
|
||||
u32 cmd = 1 << 20 | /* Execute cmd */
|
||||
0 << 19 | /* Read */
|
||||
5 << 15 | /* Table type 0b101 */
|
||||
(msti & 0x3fff);
|
||||
priv->r->exec_tbl0_cmd(cmd);
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
for (int i = 0; i < 4; i++)
|
||||
port_state[i] = sw_r32(priv->r->tbl_access_data_0(i));
|
||||
}
|
||||
|
||||
static void rtl931x_stp_set(struct rtl838x_switch_priv *priv, u16 msti, u32 port_state[])
|
||||
{
|
||||
int i;
|
||||
u32 cmd = 1 << 20 /* Execute cmd */
|
||||
| 1 << 19 /* Write */
|
||||
| 5 << 15 /* Table type 0b101 */
|
||||
| (msti & 0x3fff);
|
||||
for (i = 0; i < 4; i++)
|
||||
u32 cmd = 1 << 20 | /* Execute cmd */
|
||||
1 << 19 | /* Write */
|
||||
5 << 15 | /* Table type 0b101 */
|
||||
(msti & 0x3fff);
|
||||
for (int i = 0; i < 4; i++)
|
||||
sw_w32(port_state[i], priv->r->tbl_access_data_0(i));
|
||||
priv->r->exec_tbl0_cmd(cmd);
|
||||
}
|
||||
@ -187,7 +186,7 @@ inline static int rtl931x_trk_mbr_ctr(int group)
|
||||
static void rtl931x_vlan_tables_read(u32 vlan, struct rtl838x_vlan_info *info)
|
||||
{
|
||||
u32 v, w, x, y;
|
||||
// Read VLAN table (3) via register 0
|
||||
/* Read VLAN table (3) via register 0 */
|
||||
struct table_reg *r = rtl_table_get(RTL9310_TBL_0, 3);
|
||||
|
||||
rtl_table_read(r, vlan);
|
||||
@ -200,7 +199,7 @@ static void rtl931x_vlan_tables_read(u32 vlan, struct rtl838x_vlan_info *info)
|
||||
pr_debug("VLAN_READ %d: %08x %08x %08x %08x\n", vlan, v, w, x, y);
|
||||
info->tagged_ports = ((u64) v) << 25 | (w >> 7);
|
||||
info->profile_id = (x >> 16) & 0xf;
|
||||
info->fid = w & 0x7f; // AKA MSTI depending on context
|
||||
info->fid = w & 0x7f; /* AKA MSTI depending on context */
|
||||
info->hash_uc_fid = !!(x & BIT(31));
|
||||
info->hash_mc_fid = !!(x & BIT(30));
|
||||
info->if_id = (x >> 20) & 0x3ff;
|
||||
@ -214,7 +213,7 @@ static void rtl931x_vlan_tables_read(u32 vlan, struct rtl838x_vlan_info *info)
|
||||
info->tagged_ports, info->profile_id, info->hash_uc_fid, info->hash_mc_fid,
|
||||
info->if_id);
|
||||
|
||||
// Read UNTAG table via table register 3
|
||||
/* Read UNTAG table via table register 3 */
|
||||
r = rtl_table_get(RTL9310_TBL_3, 0);
|
||||
rtl_table_read(r, vlan);
|
||||
v = ((u64)sw_r32(rtl_table_data(r, 0))) << 25;
|
||||
@ -227,7 +226,7 @@ static void rtl931x_vlan_tables_read(u32 vlan, struct rtl838x_vlan_info *info)
|
||||
static void rtl931x_vlan_set_tagged(u32 vlan, struct rtl838x_vlan_info *info)
|
||||
{
|
||||
u32 v, w, x, y;
|
||||
// Access VLAN table (1) via register 0
|
||||
/* Access VLAN table (1) via register 0 */
|
||||
struct table_reg *r = rtl_table_get(RTL9310_TBL_0, 3);
|
||||
|
||||
v = info->tagged_ports >> 25;
|
||||
@ -294,18 +293,17 @@ irqreturn_t rtl931x_switch_irq(int irq, void *dev_id)
|
||||
u32 status = sw_r32(RTL931X_ISR_GLB_SRC);
|
||||
u64 ports = rtl839x_get_port_reg_le(RTL931X_ISR_PORT_LINK_STS_CHG);
|
||||
u64 link;
|
||||
int i;
|
||||
|
||||
/* Clear status */
|
||||
rtl839x_set_port_reg_le(ports, RTL931X_ISR_PORT_LINK_STS_CHG);
|
||||
pr_debug("RTL931X Link change: status: %x, ports %016llx\n", status, ports);
|
||||
|
||||
link = rtl839x_get_port_reg_le(RTL931X_MAC_LINK_STS);
|
||||
// Must re-read this to get correct status
|
||||
/* Must re-read this to get correct status */
|
||||
link = rtl839x_get_port_reg_le(RTL931X_MAC_LINK_STS);
|
||||
pr_debug("RTL931X Link change: status: %x, link status %016llx\n", status, link);
|
||||
|
||||
for (i = 0; i < 56; i++) {
|
||||
for (int i = 0; i < 56; i++) {
|
||||
if (ports & BIT_ULL(i)) {
|
||||
if (link & BIT_ULL(i)) {
|
||||
pr_info("%s port %d up\n", __func__, i);
|
||||
@ -316,6 +314,7 @@ irqreturn_t rtl931x_switch_irq(int irq, void *dev_id)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
@ -352,6 +351,7 @@ int rtl931x_write_phy(u32 port, u32 page, u32 reg, u32 val)
|
||||
err = -EIO;
|
||||
|
||||
mutex_unlock(&smi_lock);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
@ -380,12 +380,11 @@ int rtl931x_read_phy(u32 port, u32 page, u32 reg, u32 *val)
|
||||
__func__, port, page, reg, *val, v);
|
||||
|
||||
mutex_unlock(&smi_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read an mmd register of the PHY
|
||||
*/
|
||||
/* Read an mmd register of the PHY */
|
||||
int rtl931x_read_mmd_phy(u32 port, u32 devnum, u32 regnum, u32 *val)
|
||||
{
|
||||
int err = 0;
|
||||
@ -400,20 +399,20 @@ int rtl931x_read_mmd_phy(u32 port, u32 devnum, u32 regnum, u32 *val)
|
||||
|
||||
mutex_lock(&smi_lock);
|
||||
|
||||
// Set PHY to access via port-number
|
||||
/* Set PHY to access via port-number */
|
||||
sw_w32(port << 5, RTL931X_SMI_INDRT_ACCESS_BC_PHYID_CTRL);
|
||||
|
||||
// Set MMD device number and register to write to
|
||||
/* Set MMD device number and register to write to */
|
||||
sw_w32(devnum << 16 | mdiobus_c45_regad(regnum), RTL931X_SMI_INDRT_ACCESS_MMD_CTRL);
|
||||
|
||||
v = type << 2 | BIT(0); // MMD-access-type | EXEC
|
||||
v = type << 2 | BIT(0); /* MMD-access-type | EXEC */
|
||||
sw_w32(v, RTL931X_SMI_INDRT_ACCESS_CTRL_0);
|
||||
|
||||
do {
|
||||
v = sw_r32(RTL931X_SMI_INDRT_ACCESS_CTRL_0);
|
||||
} while (v & BIT(0));
|
||||
|
||||
// Check for error condition
|
||||
/* Check for error condition */
|
||||
if (v & BIT(1))
|
||||
err = -EIO;
|
||||
|
||||
@ -427,9 +426,7 @@ int rtl931x_read_mmd_phy(u32 port, u32 devnum, u32 regnum, u32 *val)
|
||||
return err;
|
||||
}
|
||||
|
||||
/*
|
||||
* Write to an mmd register of the PHY
|
||||
*/
|
||||
/* Write to an mmd register of the PHY */
|
||||
int rtl931x_write_mmd_phy(u32 port, u32 devnum, u32 regnum, u32 val)
|
||||
{
|
||||
int err = 0;
|
||||
@ -439,18 +436,18 @@ int rtl931x_write_mmd_phy(u32 port, u32 devnum, u32 regnum, u32 val)
|
||||
|
||||
mutex_lock(&smi_lock);
|
||||
|
||||
// Set PHY to access via port-mask
|
||||
/* Set PHY to access via port-mask */
|
||||
pm = (u64)1 << port;
|
||||
sw_w32((u32)pm, RTL931X_SMI_INDRT_ACCESS_CTRL_2);
|
||||
sw_w32((u32)(pm >> 32), RTL931X_SMI_INDRT_ACCESS_CTRL_2 + 4);
|
||||
|
||||
// Set data to write
|
||||
/* Set data to write */
|
||||
sw_w32_mask(0xffff, val, RTL931X_SMI_INDRT_ACCESS_CTRL_3);
|
||||
|
||||
// Set MMD device number and register to write to
|
||||
/* Set MMD device number and register to write to */
|
||||
sw_w32(devnum << 16 | mdiobus_c45_regad(regnum), RTL931X_SMI_INDRT_ACCESS_MMD_CTRL);
|
||||
|
||||
v = BIT(4) | type << 2 | BIT(0); // WRITE | MMD-access-type | EXEC
|
||||
v = BIT(4) | type << 2 | BIT(0); /* WRITE | MMD-access-type | EXEC */
|
||||
sw_w32(v, RTL931X_SMI_INDRT_ACCESS_CTRL_0);
|
||||
|
||||
do {
|
||||
@ -460,15 +457,15 @@ int rtl931x_write_mmd_phy(u32 port, u32 devnum, u32 regnum, u32 val)
|
||||
pr_debug("%s: port %d, dev: %x, regnum: %x, val: %x (err %d)\n", __func__,
|
||||
port, devnum, mdiobus_c45_regad(regnum), val, err);
|
||||
mutex_unlock(&smi_lock);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
void rtl931x_print_matrix(void)
|
||||
{
|
||||
volatile u64 *ptr = RTL838X_SW_BASE + RTL839X_PORT_ISO_CTRL(0);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 52; i += 4)
|
||||
for (int i = 0; i < 52; i += 4)
|
||||
pr_info("> %16llx %16llx %16llx %16llx\n",
|
||||
ptr[i + 0], ptr[i + 1], ptr[i + 2], ptr[i + 3]);
|
||||
pr_info("CPU_PORT> %16llx\n", ptr[52]);
|
||||
@ -507,9 +504,9 @@ void rtl931x_set_receive_management_action(int port, rma_ctrl_t type, action_typ
|
||||
sw_w32_mask(7 << ((port % 10) * 3), value << ((port % 10) * 3), RTL931X_RMA_BPDU_CTRL + ((port / 10) << 2));
|
||||
break;
|
||||
case PTP:
|
||||
//udp
|
||||
/* udp */
|
||||
sw_w32_mask(3 << 2, value << 2, RTL931X_RMA_PTP_CTRL + (port << 2));
|
||||
//eth2
|
||||
/* eth2 */
|
||||
sw_w32_mask(3, value, RTL931X_RMA_PTP_CTRL + (port << 2));
|
||||
break;
|
||||
case PTP_UDP:
|
||||
@ -538,12 +535,12 @@ u64 rtl931x_traffic_get(int source)
|
||||
rtl_table_read(r, source);
|
||||
v = sw_r32(rtl_table_data(r, 0));
|
||||
rtl_table_release(r);
|
||||
return v >> 3;
|
||||
v = v >> 3;
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
/*
|
||||
* Enable traffic between a source port and a destination port matrix
|
||||
*/
|
||||
/* Enable traffic between a source port and a destination port matrix */
|
||||
void rtl931x_traffic_set(int source, u64 dest_matrix)
|
||||
{
|
||||
struct table_reg *r = rtl_table_get(RTL9310_TBL_0, 6);
|
||||
@ -581,8 +578,7 @@ static u64 rtl931x_l2_hash_seed(u64 mac, u32 vid)
|
||||
return v;
|
||||
}
|
||||
|
||||
/*
|
||||
* Calculate both the block 0 and the block 1 hash by applyingthe same hash
|
||||
/* Calculate both the block 0 and the block 1 hash by applyingthe same hash
|
||||
* algorithm as the one used currently by the ASIC to the seed, and return
|
||||
* both hashes in the lower and higher word of the return value since only 12 bit of
|
||||
* the hash are significant.
|
||||
@ -609,7 +605,7 @@ static u32 rtl931x_l2_hash_key(struct rtl838x_switch_priv *priv, u64 seed)
|
||||
h4 = (seed >> 48) & 0xfff;
|
||||
k1 = h0 ^ h1 ^ h2 ^ h3 ^ h4;
|
||||
|
||||
// Algorithm choice for block 0
|
||||
/* Algorithm choice for block 0 */
|
||||
if (sw_r32(RTL931X_L2_CTRL) & BIT(0))
|
||||
h = k1;
|
||||
else
|
||||
@ -629,9 +625,7 @@ static u32 rtl931x_l2_hash_key(struct rtl838x_switch_priv *priv, u64 seed)
|
||||
return h;
|
||||
}
|
||||
|
||||
/*
|
||||
* Fills an L2 entry structure from the SoC registers
|
||||
*/
|
||||
/* Fills an L2 entry structure from the SoC registers */
|
||||
static void rtl931x_fill_l2_entry(u32 r[], struct rtl838x_l2_entry *e)
|
||||
{
|
||||
pr_debug("In %s valid?\n", __func__);
|
||||
@ -661,7 +655,7 @@ static void rtl931x_fill_l2_entry(u32 r[], struct rtl838x_l2_entry *e)
|
||||
e->is_l2_tunnel = !!(r[2] & BIT(31));
|
||||
e->is_static = !!(r[2] & BIT(13));
|
||||
e->port = (r[2] >> 19) & 0x3ff;
|
||||
// Check for trunk port
|
||||
/* Check for trunk port */
|
||||
if (r[2] & BIT(29)) {
|
||||
e->is_trunk = true;
|
||||
e->stack_dev = (e->port >> 9) & 1;
|
||||
@ -677,7 +671,7 @@ static void rtl931x_fill_l2_entry(u32 r[], struct rtl838x_l2_entry *e)
|
||||
e->suspended = !!(r[2] & BIT(12));
|
||||
e->age = (r[2] >> 16) & 3;
|
||||
|
||||
// the UC_VID field in hardware is used for the VID or for the route id
|
||||
/* the UC_VID field in hardware is used for the VID or for the route id */
|
||||
if (e->next_hop) {
|
||||
e->nh_route_id = r[2] & 0x7ff;
|
||||
e->vid = 0;
|
||||
@ -687,7 +681,7 @@ static void rtl931x_fill_l2_entry(u32 r[], struct rtl838x_l2_entry *e)
|
||||
}
|
||||
if (e->is_l2_tunnel)
|
||||
e->l2_tunnel_id = ((r[2] & 0xff) << 4) | (r[3] >> 28);
|
||||
// TODO: Implement VLAN conversion
|
||||
/* TODO: Implement VLAN conversion */
|
||||
} else {
|
||||
e->type = L2_MULTICAST;
|
||||
e->is_local_forward = !!(r[2] & BIT(31));
|
||||
@ -697,9 +691,7 @@ static void rtl931x_fill_l2_entry(u32 r[], struct rtl838x_l2_entry *e)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Fills the 3 SoC table registers r[] with the information of in the rtl838x_l2_entry
|
||||
*/
|
||||
/* Fills the 3 SoC table registers r[] with the information of in the rtl838x_l2_entry */
|
||||
static void rtl931x_fill_l2_row(u32 r[], struct rtl838x_l2_entry *e)
|
||||
{
|
||||
u32 port;
|
||||
@ -709,11 +701,14 @@ static void rtl931x_fill_l2_row(u32 r[], struct rtl838x_l2_entry *e)
|
||||
return;
|
||||
}
|
||||
|
||||
r[2] = BIT(31); // Set valid bit
|
||||
r[2] = BIT(31); /* Set valid bit */
|
||||
|
||||
r[0] = ((u32)e->mac[0]) << 24 | ((u32)e->mac[1]) << 16
|
||||
| ((u32)e->mac[2]) << 8 | ((u32)e->mac[3]);
|
||||
r[1] = ((u32)e->mac[4]) << 24 | ((u32)e->mac[5]) << 16;
|
||||
r[0] = ((u32)e->mac[0]) << 24 |
|
||||
((u32)e->mac[1]) << 16 |
|
||||
((u32)e->mac[2]) << 8 |
|
||||
((u32)e->mac[3]);
|
||||
r[1] = ((u32)e->mac[4]) << 24 |
|
||||
((u32)e->mac[5]) << 16;
|
||||
|
||||
r[2] |= e->next_hop ? BIT(12) : 0;
|
||||
|
||||
@ -733,19 +728,18 @@ static void rtl931x_fill_l2_row(u32 r[], struct rtl838x_l2_entry *e)
|
||||
r[2] |= e->block_sa ? BIT(17) : 0;
|
||||
r[2] |= e->suspended ? BIT(13) : 0;
|
||||
r[2] |= (e->age & 0x3) << 17;
|
||||
// the UC_VID field in hardware is used for the VID or for the route id
|
||||
/* the UC_VID field in hardware is used for the VID or for the route id */
|
||||
if (e->next_hop)
|
||||
r[2] |= e->nh_route_id & 0x7ff;
|
||||
else
|
||||
r[2] |= e->vid & 0xfff;
|
||||
} else { // L2_MULTICAST
|
||||
} else { /* L2_MULTICAST */
|
||||
r[2] |= (e->mc_portmask_index & 0x3ff) << 16;
|
||||
r[2] |= e->mc_mac_index & 0x7ff;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Read an L2 UC or MC entry out of a hash bucket of the L2 forwarding table
|
||||
/* Read an L2 UC or MC entry out of a hash bucket of the L2 forwarding table
|
||||
* hash is the id of the bucket and pos is the position of the entry in that bucket
|
||||
* The data read from the SoC is filled into rtl838x_l2_entry
|
||||
*/
|
||||
@ -754,7 +748,6 @@ static u64 rtl931x_read_l2_entry_using_hash(u32 hash, u32 pos, struct rtl838x_l2
|
||||
u32 r[4];
|
||||
struct table_reg *q = rtl_table_get(RTL9310_TBL_0, 0);
|
||||
u32 idx;
|
||||
int i;
|
||||
u64 mac;
|
||||
u64 seed;
|
||||
|
||||
@ -762,7 +755,8 @@ static u64 rtl931x_read_l2_entry_using_hash(u32 hash, u32 pos, struct rtl838x_l2
|
||||
|
||||
/* On the RTL93xx, 2 different hash algorithms are used making it a total of
|
||||
* 8 buckets that need to be searched, 4 for each hash-half
|
||||
* Use second hash space when bucket is between 4 and 8 */
|
||||
* Use second hash space when bucket is between 4 and 8
|
||||
*/
|
||||
if (pos >= 4) {
|
||||
pos -= 4;
|
||||
hash >>= 16;
|
||||
@ -770,11 +764,11 @@ static u64 rtl931x_read_l2_entry_using_hash(u32 hash, u32 pos, struct rtl838x_l2
|
||||
hash &= 0xffff;
|
||||
}
|
||||
|
||||
idx = (0 << 14) | (hash << 2) | pos; // Search SRAM, with hash and at pos in bucket
|
||||
idx = (0 << 14) | (hash << 2) | pos; /* Search SRAM, with hash and at pos in bucket */
|
||||
pr_debug("%s: NOW hash %08x, pos: %d\n", __func__, hash, pos);
|
||||
|
||||
rtl_table_read(q, idx);
|
||||
for (i = 0; i < 4; i++)
|
||||
for (int i = 0; i < 4; i++)
|
||||
r[i] = sw_r32(rtl_table_data(q, i));
|
||||
|
||||
rtl_table_release(q);
|
||||
@ -785,18 +779,23 @@ static u64 rtl931x_read_l2_entry_using_hash(u32 hash, u32 pos, struct rtl838x_l2
|
||||
if (!e->valid)
|
||||
return 0;
|
||||
|
||||
mac = ((u64)e->mac[0]) << 40 | ((u64)e->mac[1]) << 32 | ((u64)e->mac[2]) << 24
|
||||
| ((u64)e->mac[3]) << 16 | ((u64)e->mac[4]) << 8 | ((u64)e->mac[5]);
|
||||
mac = ((u64)e->mac[0]) << 40 |
|
||||
((u64)e->mac[1]) << 32 |
|
||||
((u64)e->mac[2]) << 24 |
|
||||
((u64)e->mac[3]) << 16 |
|
||||
((u64)e->mac[4]) << 8 |
|
||||
((u64)e->mac[5]);
|
||||
|
||||
seed = rtl931x_l2_hash_seed(mac, e->rvid);
|
||||
pr_debug("%s: mac %016llx, seed %016llx\n", __func__, mac, seed);
|
||||
// return vid with concatenated mac as unique id
|
||||
|
||||
/* return vid with concatenated mac as unique id */
|
||||
return seed;
|
||||
}
|
||||
|
||||
static u64 rtl931x_read_cam(int idx, struct rtl838x_l2_entry *e)
|
||||
{
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void rtl931x_write_cam(int idx, struct rtl838x_l2_entry *e)
|
||||
@ -807,8 +806,7 @@ static void rtl931x_write_l2_entry_using_hash(u32 hash, u32 pos, struct rtl838x_
|
||||
{
|
||||
u32 r[4];
|
||||
struct table_reg *q = rtl_table_get(RTL9310_TBL_0, 0);
|
||||
u32 idx = (0 << 14) | (hash << 2) | pos; // Access SRAM, with hash and at pos in bucket
|
||||
int i;
|
||||
u32 idx = (0 << 14) | (hash << 2) | pos; /* Access SRAM, with hash and at pos in bucket */
|
||||
|
||||
pr_info("%s: hash %d, pos %d\n", __func__, hash, pos);
|
||||
pr_info("%s: index %d -> mac %02x:%02x:%02x:%02x:%02x:%02x\n", __func__, idx,
|
||||
@ -817,17 +815,16 @@ static void rtl931x_write_l2_entry_using_hash(u32 hash, u32 pos, struct rtl838x_
|
||||
rtl931x_fill_l2_row(r, e);
|
||||
pr_info("%s: %d: %08x %08x %08x\n", __func__, idx, r[0], r[1], r[2]);
|
||||
|
||||
for (i= 0; i < 4; i++)
|
||||
for (int i = 0; i < 4; i++)
|
||||
sw_w32(r[i], rtl_table_data(q, i));
|
||||
|
||||
rtl_table_write(q, idx);
|
||||
rtl_table_release(q);
|
||||
|
||||
}
|
||||
|
||||
static void rtl931x_vlan_fwd_on_inner(int port, bool is_set)
|
||||
{
|
||||
// Always set all tag modes to fwd based on either inner or outer tag
|
||||
/* Always set all tag modes to fwd based on either inner or outer tag */
|
||||
if (is_set)
|
||||
sw_w32_mask(0, 0xf, RTL931X_VLAN_PORT_FWD + (port << 2));
|
||||
else
|
||||
@ -837,7 +834,6 @@ static void rtl931x_vlan_fwd_on_inner(int port, bool is_set)
|
||||
static void rtl931x_vlan_profile_setup(int profile)
|
||||
{
|
||||
u32 p[7];
|
||||
int i;
|
||||
|
||||
pr_info("In %s\n", __func__);
|
||||
|
||||
@ -846,38 +842,38 @@ static void rtl931x_vlan_profile_setup(int profile)
|
||||
|
||||
p[0] = sw_r32(RTL931X_VLAN_PROFILE_SET(profile));
|
||||
|
||||
// Enable routing of Ipv4/6 Unicast and IPv4/6 Multicast traffic
|
||||
//p[0] |= BIT(17) | BIT(16) | BIT(13) | BIT(12);
|
||||
p[0] |= 0x3 << 11; // COPY2CPU
|
||||
/* Enable routing of Ipv4/6 Unicast and IPv4/6 Multicast traffic */
|
||||
/* p[0] |= BIT(17) | BIT(16) | BIT(13) | BIT(12); */
|
||||
p[0] |= 0x3 << 11; /* COPY2CPU */
|
||||
|
||||
p[1] = 0x1FFFFFF; // L2 unknwon MC flooding portmask all ports, including the CPU-port
|
||||
p[1] = 0x1FFFFFF; /* L2 unknwon MC flooding portmask all ports, including the CPU-port */
|
||||
p[2] = 0xFFFFFFFF;
|
||||
p[3] = 0x1FFFFFF; // IPv4 unknwon MC flooding portmask
|
||||
p[3] = 0x1FFFFFF; /* IPv4 unknwon MC flooding portmask */
|
||||
p[4] = 0xFFFFFFFF;
|
||||
p[5] = 0x1FFFFFF; // IPv6 unknwon MC flooding portmask
|
||||
p[5] = 0x1FFFFFF; /* IPv6 unknwon MC flooding portmask */
|
||||
p[6] = 0xFFFFFFFF;
|
||||
|
||||
for (i = 0; i < 7; i++)
|
||||
for (int i = 0; i < 7; i++)
|
||||
sw_w32(p[i], RTL931X_VLAN_PROFILE_SET(profile) + i * 4);
|
||||
pr_info("Leaving %s\n", __func__);
|
||||
}
|
||||
|
||||
static void rtl931x_l2_learning_setup(void)
|
||||
{
|
||||
// Portmask for flooding broadcast traffic
|
||||
/* Portmask for flooding broadcast traffic */
|
||||
rtl839x_set_port_reg_be(0x1FFFFFFFFFFFFFF, RTL931X_L2_BC_FLD_PMSK);
|
||||
|
||||
// Portmask for flooding unicast traffic with unknown destination
|
||||
/* Portmask for flooding unicast traffic with unknown destination */
|
||||
rtl839x_set_port_reg_be(0x1FFFFFFFFFFFFFF, RTL931X_L2_UNKN_UC_FLD_PMSK);
|
||||
|
||||
// Limit learning to maximum: 64k entries, after that just flood (bits 0-2)
|
||||
/* Limit learning to maximum: 64k entries, after that just flood (bits 0-2) */
|
||||
sw_w32((0xffff << 3) | FORWARD, RTL931X_L2_LRN_CONSTRT_CTRL);
|
||||
}
|
||||
|
||||
static u64 rtl931x_read_mcast_pmask(int idx)
|
||||
{
|
||||
u64 portmask;
|
||||
// Read MC_PMSK (2) via register RTL9310_TBL_0
|
||||
/* Read MC_PMSK (2) via register RTL9310_TBL_0 */
|
||||
struct table_reg *q = rtl_table_get(RTL9310_TBL_0, 2);
|
||||
|
||||
rtl_table_read(q, idx);
|
||||
@ -888,6 +884,7 @@ static u64 rtl931x_read_mcast_pmask(int idx)
|
||||
rtl_table_release(q);
|
||||
|
||||
pr_debug("%s: Index idx %d has portmask %016llx\n", __func__, idx, portmask);
|
||||
|
||||
return portmask;
|
||||
}
|
||||
|
||||
@ -895,7 +892,7 @@ static void rtl931x_write_mcast_pmask(int idx, u64 portmask)
|
||||
{
|
||||
u64 pm = portmask;
|
||||
|
||||
// Access MC_PMSK (2) via register RTL9310_TBL_0
|
||||
/* Access MC_PMSK (2) via register RTL9310_TBL_0 */
|
||||
struct table_reg *q = rtl_table_get(RTL9310_TBL_0, 2);
|
||||
|
||||
pr_debug("%s: Index idx %d has portmask %016llx\n", __func__, idx, pm);
|
||||
@ -919,11 +916,12 @@ static int rtl931x_set_ageing_time(unsigned long msec)
|
||||
t = t > 0x1FFFFF ? 0x1FFFFF : t;
|
||||
sw_w32_mask(0x1FFFFF, t, RTL931X_L2_AGE_CTRL);
|
||||
pr_debug("Dynamic aging for ports: %x\n", sw_r32(RTL931X_L2_PORT_AGE_CTRL));
|
||||
|
||||
return 0;
|
||||
}
|
||||
void rtl931x_sw_init(struct rtl838x_switch_priv *priv)
|
||||
{
|
||||
// rtl931x_sds_init(priv);
|
||||
/* rtl931x_sds_init(priv); */
|
||||
}
|
||||
|
||||
static void rtl931x_pie_lookup_enable(struct rtl838x_switch_priv *priv, int index)
|
||||
@ -933,8 +931,7 @@ static void rtl931x_pie_lookup_enable(struct rtl838x_switch_priv *priv, int inde
|
||||
sw_w32_mask(0, BIT(block), RTL931X_PIE_BLK_LOOKUP_CTRL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Fills the data in the intermediate representation in the pie_rule structure
|
||||
/* Fills the data in the intermediate representation in the pie_rule structure
|
||||
* into a data field for a given template field field_type
|
||||
* TODO: This function looks very similar to the function of the rtl9300, but
|
||||
* since it uses the physical template_field_id, which are different for each
|
||||
@ -1031,7 +1028,6 @@ int rtl931x_pie_data_fill(enum template_field_id field_type, struct pie_rule *pr
|
||||
*data = pr->sip6.s6_addr16[5 - (field_type - TEMPLATE_FIELD_SIP2)];
|
||||
*data_m = pr->sip6_m.s6_addr16[5 - (field_type - TEMPLATE_FIELD_SIP2)];
|
||||
break;
|
||||
|
||||
case TEMPLATE_FIELD_DIP0:
|
||||
if (pr->is_ipv6) {
|
||||
*data = pr->dip6.s6_addr16[7];
|
||||
@ -1050,7 +1046,6 @@ int rtl931x_pie_data_fill(enum template_field_id field_type, struct pie_rule *pr
|
||||
*data_m = pr->dip_m >> 16;
|
||||
}
|
||||
break;
|
||||
|
||||
case TEMPLATE_FIELD_DIP2:
|
||||
case TEMPLATE_FIELD_DIP3:
|
||||
case TEMPLATE_FIELD_DIP4:
|
||||
@ -1060,7 +1055,6 @@ int rtl931x_pie_data_fill(enum template_field_id field_type, struct pie_rule *pr
|
||||
*data = pr->dip6.s6_addr16[5 - (field_type - TEMPLATE_FIELD_DIP2)];
|
||||
*data_m = pr->dip6_m.s6_addr16[5 - (field_type - TEMPLATE_FIELD_DIP2)];
|
||||
break;
|
||||
|
||||
case TEMPLATE_FIELD_IP_TOS_PROTO:
|
||||
*data = pr->tos_proto;
|
||||
*data_m = pr->tos_proto_m;
|
||||
@ -1092,8 +1086,7 @@ int rtl931x_pie_data_fill(enum template_field_id field_type, struct pie_rule *pr
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Reads the intermediate representation of the templated match-fields of the
|
||||
/* Reads the intermediate representation of the templated match-fields of the
|
||||
* PIE rule in the pie_rule structure and fills in the raw data fields in the
|
||||
* raw register space r[].
|
||||
* The register space configuration size is identical for the RTL8380/90 and RTL9300,
|
||||
@ -1103,13 +1096,12 @@ int rtl931x_pie_data_fill(enum template_field_id field_type, struct pie_rule *pr
|
||||
*/
|
||||
static void rtl931x_write_pie_templated(u32 r[], struct pie_rule *pr, enum template_field_id t[])
|
||||
{
|
||||
int i;
|
||||
u16 data, data_m;
|
||||
for (int i = 0; i < N_FIXED_FIELDS; i++) {
|
||||
u16 data, data_m;
|
||||
|
||||
for (i = 0; i < N_FIXED_FIELDS; i++) {
|
||||
rtl931x_pie_data_fill(t[i], pr, &data, &data_m);
|
||||
|
||||
// On the RTL9300, the mask fields are not word aligned!
|
||||
/* On the RTL9300, the mask fields are not word aligned! */
|
||||
if (!(i % 2)) {
|
||||
r[5 - i / 2] = data;
|
||||
r[12 - i / 2] |= ((u32)data_m << 8);
|
||||
@ -1126,7 +1118,7 @@ static void rtl931x_read_pie_fixed_fields(u32 r[], struct pie_rule *pr)
|
||||
pr->mgnt_vlan = r[7] & BIT(31);
|
||||
if (pr->phase == PHASE_IACL)
|
||||
pr->dmac_hit_sw = r[7] & BIT(30);
|
||||
else // TODO: EACL/VACL phase handling
|
||||
else /* TODO: EACL/VACL phase handling */
|
||||
pr->content_too_deep = r[7] & BIT(30);
|
||||
pr->not_first_frag = r[7] & BIT(29);
|
||||
pr->frame_type_l4 = (r[7] >> 26) & 7;
|
||||
@ -1203,15 +1195,15 @@ static void rtl931x_write_pie_fixed_fields(u32 r[], struct pie_rule *pr)
|
||||
|
||||
static void rtl931x_write_pie_action(u32 r[], struct pie_rule *pr)
|
||||
{
|
||||
// Either drop or forward
|
||||
/* Either drop or forward */
|
||||
if (pr->drop) {
|
||||
r[15] |= BIT(11) | BIT(12) | BIT(13); // Do Green, Yellow and Red drops
|
||||
// Actually DROP, not PERMIT in Green / Yellow / Red
|
||||
r[15] |= BIT(11) | BIT(12) | BIT(13); /* Do Green, Yellow and Red drops */
|
||||
/* Actually DROP, not PERMIT in Green / Yellow / Red */
|
||||
r[16] |= BIT(27) | BIT(28) | BIT(29);
|
||||
} else {
|
||||
r[15] |= pr->fwd_sel ? BIT(14) : 0;
|
||||
r[16] |= pr->fwd_act << 24;
|
||||
r[16] |= BIT(21); // We overwrite any drop
|
||||
r[16] |= BIT(21); /* We overwrite any drop */
|
||||
}
|
||||
if (pr->phase == PHASE_VACL)
|
||||
r[16] |= pr->fwd_sa_lrn ? BIT(22) : 0;
|
||||
@ -1225,7 +1217,7 @@ static void rtl931x_write_pie_action(u32 r[], struct pie_rule *pr)
|
||||
r[15] |= pr->log_sel ? BIT(26) : 0;
|
||||
|
||||
r[16] |= ((u32)(pr->fwd_data & 0xfff)) << 9;
|
||||
// r[15] |= pr->log_octets ? BIT(31) : 0;
|
||||
/* r[15] |= pr->log_octets ? BIT(31) : 0; */
|
||||
r[15] |= (u32)(pr->meter_data) >> 2;
|
||||
r[16] |= (((u32)(pr->meter_data) >> 7) & 0x3) << 29;
|
||||
|
||||
@ -1261,16 +1253,15 @@ void rtl931x_pie_rule_dump_raw(u32 r[])
|
||||
|
||||
static int rtl931x_pie_rule_write(struct rtl838x_switch_priv *priv, int idx, struct pie_rule *pr)
|
||||
{
|
||||
// Access IACL table (0) via register 1, the table size is 4096
|
||||
/* Access IACL table (0) via register 1, the table size is 4096 */
|
||||
struct table_reg *q = rtl_table_get(RTL9310_TBL_1, 0);
|
||||
u32 r[22];
|
||||
int i;
|
||||
int block = idx / PIE_BLOCK_SIZE;
|
||||
u32 t_select = sw_r32(RTL931X_PIE_BLK_TMPLTE_CTRL(block));
|
||||
|
||||
pr_info("%s: %d, t_select: %08x\n", __func__, idx, t_select);
|
||||
|
||||
for (i = 0; i < 22; i++)
|
||||
for (int i = 0; i < 22; i++)
|
||||
r[i] = 0;
|
||||
|
||||
if (!pr->valid) {
|
||||
@ -1287,7 +1278,7 @@ static int rtl931x_pie_rule_write(struct rtl838x_switch_priv *priv, int idx, str
|
||||
|
||||
rtl931x_pie_rule_dump_raw(r);
|
||||
|
||||
for (i = 0; i < 22; i++)
|
||||
for (int i = 0; i < 22; i++)
|
||||
sw_w32(r[i], rtl_table_data(q, i));
|
||||
|
||||
rtl_table_write(q, idx);
|
||||
@ -1298,11 +1289,8 @@ static int rtl931x_pie_rule_write(struct rtl838x_switch_priv *priv, int idx, str
|
||||
|
||||
static bool rtl931x_pie_templ_has(int t, enum template_field_id field_type)
|
||||
{
|
||||
int i;
|
||||
enum template_field_id ft;
|
||||
|
||||
for (i = 0; i < N_FIXED_FIELDS_RTL931X; i++) {
|
||||
ft = fixed_templates[t][i];
|
||||
for (int i = 0; i < N_FIXED_FIELDS_RTL931X; i++) {
|
||||
enum template_field_id ft = fixed_templates[t][i];
|
||||
if (field_type == ft)
|
||||
return true;
|
||||
}
|
||||
@ -1310,8 +1298,7 @@ static bool rtl931x_pie_templ_has(int t, enum template_field_id field_type)
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Verify that the rule pr is compatible with a given template t in block block
|
||||
/* Verify that the rule pr is compatible with a given template t in block block
|
||||
* Note that this function is SoC specific since the values of e.g. TEMPLATE_FIELD_SIP0
|
||||
* depend on the SoC
|
||||
*/
|
||||
@ -1327,13 +1314,17 @@ static int rtl931x_pie_verify_template(struct rtl838x_switch_priv *priv,
|
||||
return -1;
|
||||
|
||||
if (pr->is_ipv6) {
|
||||
if ((pr->sip6_m.s6_addr32[0] || pr->sip6_m.s6_addr32[1]
|
||||
|| pr->sip6_m.s6_addr32[2] || pr->sip6_m.s6_addr32[3])
|
||||
&& !rtl931x_pie_templ_has(t, TEMPLATE_FIELD_SIP2))
|
||||
if ((pr->sip6_m.s6_addr32[0] ||
|
||||
pr->sip6_m.s6_addr32[1] ||
|
||||
pr->sip6_m.s6_addr32[2] ||
|
||||
pr->sip6_m.s6_addr32[3]) &&
|
||||
!rtl931x_pie_templ_has(t, TEMPLATE_FIELD_SIP2))
|
||||
return -1;
|
||||
if ((pr->dip6_m.s6_addr32[0] || pr->dip6_m.s6_addr32[1]
|
||||
|| pr->dip6_m.s6_addr32[2] || pr->dip6_m.s6_addr32[3])
|
||||
&& !rtl931x_pie_templ_has(t, TEMPLATE_FIELD_DIP2))
|
||||
if ((pr->dip6_m.s6_addr32[0] ||
|
||||
pr->dip6_m.s6_addr32[1] ||
|
||||
pr->dip6_m.s6_addr32[2] ||
|
||||
pr->dip6_m.s6_addr32[3]) &&
|
||||
!rtl931x_pie_templ_has(t, TEMPLATE_FIELD_DIP2))
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -1343,7 +1334,7 @@ static int rtl931x_pie_verify_template(struct rtl838x_switch_priv *priv,
|
||||
if (ether_addr_to_u64(pr->dmac) && !rtl931x_pie_templ_has(t, TEMPLATE_FIELD_DMAC0))
|
||||
return -1;
|
||||
|
||||
// TODO: Check more
|
||||
/* TODO: Check more */
|
||||
|
||||
i = find_first_zero_bit(&priv->pie_use_bm[block * 4], PIE_BLOCK_SIZE);
|
||||
|
||||
@ -1355,7 +1346,7 @@ static int rtl931x_pie_verify_template(struct rtl838x_switch_priv *priv,
|
||||
|
||||
static int rtl931x_pie_rule_add(struct rtl838x_switch_priv *priv, struct pie_rule *pr)
|
||||
{
|
||||
int idx, block, j, t;
|
||||
int idx, block, j;
|
||||
int min_block = 0;
|
||||
int max_block = priv->n_pie_blocks / 2;
|
||||
|
||||
@ -1369,7 +1360,7 @@ static int rtl931x_pie_rule_add(struct rtl838x_switch_priv *priv, struct pie_rul
|
||||
|
||||
for (block = min_block; block < max_block; block++) {
|
||||
for (j = 0; j < 2; j++) {
|
||||
t = (sw_r32(RTL931X_PIE_BLK_TMPLTE_CTRL(block)) >> (j * 4)) & 0xf;
|
||||
int t = (sw_r32(RTL931X_PIE_BLK_TMPLTE_CTRL(block)) >> (j * 4)) & 0xf;
|
||||
pr_info("Testing block %d, template %d, template id %d\n", block, j, t);
|
||||
pr_info("%s: %08x\n",
|
||||
__func__, sw_r32(RTL931X_PIE_BLK_TMPLTE_CTRL(block)));
|
||||
@ -1390,7 +1381,7 @@ static int rtl931x_pie_rule_add(struct rtl838x_switch_priv *priv, struct pie_rul
|
||||
set_bit(idx, priv->pie_use_bm);
|
||||
|
||||
pr->valid = true;
|
||||
pr->tid = j; // Mapped to template number
|
||||
pr->tid = j; /* Mapped to template number */
|
||||
pr->tid_m = 0x1;
|
||||
pr->id = idx;
|
||||
|
||||
@ -1398,12 +1389,11 @@ static int rtl931x_pie_rule_add(struct rtl838x_switch_priv *priv, struct pie_rul
|
||||
rtl931x_pie_rule_write(priv, idx, pr);
|
||||
|
||||
mutex_unlock(&priv->pie_mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Delete a range of Packet Inspection Engine rules
|
||||
*/
|
||||
/* Delete a range of Packet Inspection Engine rules */
|
||||
static int rtl931x_pie_rule_del(struct rtl838x_switch_priv *priv, int index_from, int index_to)
|
||||
{
|
||||
u32 v = (index_from << 1)| (index_to << 13 ) | BIT(0);
|
||||
@ -1411,14 +1401,15 @@ static int rtl931x_pie_rule_del(struct rtl838x_switch_priv *priv, int index_from
|
||||
pr_info("%s: from %d to %d\n", __func__, index_from, index_to);
|
||||
mutex_lock(&priv->reg_mutex);
|
||||
|
||||
// Write from-to and execute bit into control register
|
||||
/* Write from-to and execute bit into control register */
|
||||
sw_w32(v, RTL931X_PIE_CLR_CTRL);
|
||||
|
||||
// Wait until command has completed
|
||||
/* Wait until command has completed */
|
||||
do {
|
||||
} while (sw_r32(RTL931X_PIE_CLR_CTRL) & BIT(0));
|
||||
|
||||
mutex_unlock(&priv->reg_mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1432,28 +1423,27 @@ static void rtl931x_pie_rule_rm(struct rtl838x_switch_priv *priv, struct pie_rul
|
||||
|
||||
static void rtl931x_pie_init(struct rtl838x_switch_priv *priv)
|
||||
{
|
||||
int i;
|
||||
u32 template_selectors;
|
||||
|
||||
mutex_init(&priv->pie_mutex);
|
||||
|
||||
pr_info("%s\n", __func__);
|
||||
// Enable ACL lookup on all ports, including CPU_PORT
|
||||
for (i = 0; i <= priv->cpu_port; i++)
|
||||
/* Enable ACL lookup on all ports, including CPU_PORT */
|
||||
for (int i = 0; i <= priv->cpu_port; i++)
|
||||
sw_w32(1, RTL931X_ACL_PORT_LOOKUP_CTRL(i));
|
||||
|
||||
// Include IPG in metering
|
||||
/* Include IPG in metering */
|
||||
sw_w32_mask(0, 1, RTL931X_METER_GLB_CTRL);
|
||||
|
||||
// Delete all present rules, block size is 128 on all SoC families
|
||||
/* Delete all present rules, block size is 128 on all SoC families */
|
||||
rtl931x_pie_rule_del(priv, 0, priv->n_pie_blocks * 128 - 1);
|
||||
|
||||
// Assign first half blocks 0-7 to VACL phase, second half to IACL
|
||||
// 3 bits are used for each block, values for PIE blocks are
|
||||
// 6: Disabled, 0: VACL, 1: IACL, 2: EACL
|
||||
// And for OpenFlow Flow blocks: 3: Ingress Flow table 0,
|
||||
// 4: Ingress Flow Table 3, 5: Egress flow table 0
|
||||
for (i = 0; i < priv->n_pie_blocks; i++) {
|
||||
/* Assign first half blocks 0-7 to VACL phase, second half to IACL */
|
||||
/* 3 bits are used for each block, values for PIE blocks are */
|
||||
/* 6: Disabled, 0: VACL, 1: IACL, 2: EACL */
|
||||
/* And for OpenFlow Flow blocks: 3: Ingress Flow table 0, */
|
||||
/* 4: Ingress Flow Table 3, 5: Egress flow table 0 */
|
||||
for (int i = 0; i < priv->n_pie_blocks; i++) {
|
||||
int pos = (i % 10) * 3;
|
||||
u32 r = RTL931X_PIE_BLK_PHASE_CTRL + 4 * (i / 10);
|
||||
|
||||
@ -1463,24 +1453,24 @@ static void rtl931x_pie_init(struct rtl838x_switch_priv *priv)
|
||||
sw_w32_mask(0x7 << pos, 1 << pos, r);
|
||||
}
|
||||
|
||||
// Enable predefined templates 0, 1 for first quarter of all blocks
|
||||
/* Enable predefined templates 0, 1 for first quarter of all blocks */
|
||||
template_selectors = 0 | (1 << 4);
|
||||
for (i = 0; i < priv->n_pie_blocks / 4; i++)
|
||||
for (int i = 0; i < priv->n_pie_blocks / 4; i++)
|
||||
sw_w32(template_selectors, RTL931X_PIE_BLK_TMPLTE_CTRL(i));
|
||||
|
||||
// Enable predefined templates 2, 3 for second quarter of all blocks
|
||||
/* Enable predefined templates 2, 3 for second quarter of all blocks */
|
||||
template_selectors = 2 | (3 << 4);
|
||||
for (i = priv->n_pie_blocks / 4; i < priv->n_pie_blocks / 2; i++)
|
||||
for (int i = priv->n_pie_blocks / 4; i < priv->n_pie_blocks / 2; i++)
|
||||
sw_w32(template_selectors, RTL931X_PIE_BLK_TMPLTE_CTRL(i));
|
||||
|
||||
// Enable predefined templates 0, 1 for third quater of all blocks
|
||||
/* Enable predefined templates 0, 1 for third quater of all blocks */
|
||||
template_selectors = 0 | (1 << 4);
|
||||
for (i = priv->n_pie_blocks / 2; i < priv->n_pie_blocks * 3 / 4; i++)
|
||||
for (int i = priv->n_pie_blocks / 2; i < priv->n_pie_blocks * 3 / 4; i++)
|
||||
sw_w32(template_selectors, RTL931X_PIE_BLK_TMPLTE_CTRL(i));
|
||||
|
||||
// Enable predefined templates 2, 3 for fourth quater of all blocks
|
||||
/* Enable predefined templates 2, 3 for fourth quater of all blocks */
|
||||
template_selectors = 2 | (3 << 4);
|
||||
for (i = priv->n_pie_blocks * 3 / 4; i < priv->n_pie_blocks; i++)
|
||||
for (int i = priv->n_pie_blocks * 3 / 4; i < priv->n_pie_blocks; i++)
|
||||
sw_w32(template_selectors, RTL931X_PIE_BLK_TMPLTE_CTRL(i));
|
||||
|
||||
}
|
||||
@ -1533,7 +1523,7 @@ void rtl931x_set_distribution_algorithm(int group, int algoidx, u32 algomsk)
|
||||
u32 newmask = 0;
|
||||
|
||||
/* TODO: for now we set algoidx to 0 */
|
||||
algoidx=0;
|
||||
algoidx = 0;
|
||||
|
||||
if (algomsk & TRUNK_DISTRIBUTION_ALGO_SIP_BIT) {
|
||||
l3shift = 4;
|
||||
@ -1569,12 +1559,7 @@ void rtl931x_set_distribution_algorithm(int group, int algoidx, u32 algomsk)
|
||||
|
||||
static void rtl931x_led_init(struct rtl838x_switch_priv *priv)
|
||||
{
|
||||
int i, pos;
|
||||
u32 v, set;
|
||||
u64 pm_copper = 0, pm_fiber = 0;
|
||||
u32 setlen;
|
||||
const __be32 *led_set;
|
||||
char set_name[9];
|
||||
struct device_node *node;
|
||||
|
||||
pr_info("%s called\n", __func__);
|
||||
@ -1584,15 +1569,18 @@ static void rtl931x_led_init(struct rtl838x_switch_priv *priv)
|
||||
return;
|
||||
}
|
||||
|
||||
for (i= 0; i < priv->cpu_port; i++) {
|
||||
pos = (i << 1) % 32;
|
||||
for (int i = 0; i < priv->cpu_port; i++) {
|
||||
int pos = (i << 1) % 32;
|
||||
u32 set;
|
||||
u32 v;
|
||||
|
||||
sw_w32_mask(0x3 << pos, 0, RTL931X_LED_PORT_FIB_SET_SEL_CTRL(i));
|
||||
sw_w32_mask(0x3 << pos, 0, RTL931X_LED_PORT_COPR_SET_SEL_CTRL(i));
|
||||
|
||||
if (!priv->ports[i].phy)
|
||||
continue;
|
||||
|
||||
v = 0x1; // Found on the EdgeCore, but we do not have any HW description
|
||||
v = 0x1; /* Found on the EdgeCore, but we do not have any HW description */
|
||||
sw_w32_mask(0x3 << pos, v << pos, RTL931X_LED_PORT_NUM_CTRL(i));
|
||||
|
||||
if (priv->ports[i].phy_is_integrated)
|
||||
@ -1605,7 +1593,12 @@ static void rtl931x_led_init(struct rtl838x_switch_priv *priv)
|
||||
sw_w32_mask(0, set << pos, RTL931X_LED_PORT_FIB_SET_SEL_CTRL(i));
|
||||
}
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
const __be32 *led_set;
|
||||
char set_name[9];
|
||||
u32 setlen;
|
||||
u32 v;
|
||||
|
||||
sprintf(set_name, "led_set%d", i);
|
||||
pr_info(">%s<\n", set_name);
|
||||
led_set = of_get_property(node, set_name, &setlen);
|
||||
@ -1617,16 +1610,15 @@ static void rtl931x_led_init(struct rtl838x_switch_priv *priv)
|
||||
sw_w32(v, RTL931X_LED_SET0_0_CTRL - i * 8);
|
||||
}
|
||||
|
||||
// Set LED mode to serial (0x1)
|
||||
/* Set LED mode to serial (0x1) */
|
||||
sw_w32_mask(0x3, 0x1, RTL931X_LED_GLB_CTRL);
|
||||
|
||||
rtl839x_set_port_reg_le(pm_copper, RTL931X_LED_PORT_COPR_MASK_CTRL);
|
||||
rtl839x_set_port_reg_le(pm_fiber, RTL931X_LED_PORT_FIB_MASK_CTRL);
|
||||
rtl839x_set_port_reg_le(pm_copper | pm_fiber, RTL931X_LED_PORT_COMBO_MASK_CTRL);
|
||||
|
||||
for (i = 0; i < 32; i++)
|
||||
for (int i = 0; i < 32; i++)
|
||||
pr_info("%s %08x: %08x\n",__func__, 0xbb000600 + i * 4, sw_r32(0x0600 + i * 4));
|
||||
|
||||
}
|
||||
|
||||
const struct rtl838x_reg rtl931x_reg = {
|
||||
@ -1638,7 +1630,7 @@ const struct rtl838x_reg rtl931x_reg = {
|
||||
.get_port_reg_le = rtl839x_get_port_reg_le,
|
||||
.stat_port_rst = RTL931X_STAT_PORT_RST,
|
||||
.stat_rst = RTL931X_STAT_RST,
|
||||
.stat_port_std_mib = 0, // Not defined
|
||||
.stat_port_std_mib = 0, /* Not defined */
|
||||
.traffic_enable = rtl931x_traffic_enable,
|
||||
.traffic_disable = rtl931x_traffic_disable,
|
||||
.traffic_get = rtl931x_traffic_get,
|
||||
@ -1647,7 +1639,7 @@ const struct rtl838x_reg rtl931x_reg = {
|
||||
.l2_ctrl_1 = RTL931X_L2_AGE_CTRL,
|
||||
.l2_port_aging_out = RTL931X_L2_PORT_AGE_CTRL,
|
||||
.set_ageing_time = rtl931x_set_ageing_time,
|
||||
// .smi_poll_ctrl does not exist
|
||||
/* .smi_poll_ctrl does not exist */
|
||||
.l2_tbl_flush_ctrl = RTL931X_L2_TBL_FLUSH_CTRL,
|
||||
.exec_tbl0_cmd = rtl931x_exec_tbl0_cmd,
|
||||
.exec_tbl1_cmd = rtl931x_exec_tbl1_cmd,
|
||||
@ -1655,7 +1647,7 @@ const struct rtl838x_reg rtl931x_reg = {
|
||||
.isr_glb_src = RTL931X_ISR_GLB_SRC,
|
||||
.isr_port_link_sts_chg = RTL931X_ISR_PORT_LINK_STS_CHG,
|
||||
.imr_port_link_sts_chg = RTL931X_IMR_PORT_LINK_STS_CHG,
|
||||
// imr_glb does not exist on RTL931X
|
||||
/* imr_glb does not exist on RTL931X */
|
||||
.vlan_tables_read = rtl931x_vlan_tables_read,
|
||||
.vlan_set_tagged = rtl931x_vlan_set_tagged,
|
||||
.vlan_set_untagged = rtl931x_vlan_set_untagged,
|
||||
@ -1698,4 +1690,3 @@ const struct rtl838x_reg rtl931x_reg = {
|
||||
.l3_setup = rtl931x_l3_setup,
|
||||
.led_init = rtl931x_led_init,
|
||||
};
|
||||
|
||||
|
||||
@ -5,14 +5,12 @@
|
||||
#include <linux/netdevice.h>
|
||||
#include <net/flow_offload.h>
|
||||
#include <linux/rhashtable.h>
|
||||
|
||||
#include <asm/mach-rtl838x/mach-rtl83xx.h>
|
||||
|
||||
#include "rtl83xx.h"
|
||||
#include "rtl838x.h"
|
||||
|
||||
/*
|
||||
* Parse the flow rule for the matching conditions
|
||||
*/
|
||||
/* Parse the flow rule for the matching conditions */
|
||||
static int rtl83xx_parse_flow_rule(struct rtl838x_switch_priv *priv,
|
||||
struct flow_rule *rule, struct rtl83xx_flow *flow)
|
||||
{
|
||||
@ -44,8 +42,7 @@ static int rtl83xx_parse_flow_rule(struct rtl838x_switch_priv *priv,
|
||||
flow->rule.frame_type_l4 = 0;
|
||||
if (match.key->ip_proto == IPPROTO_TCP)
|
||||
flow->rule.frame_type_l4 = 1;
|
||||
if (match.key->ip_proto == IPPROTO_ICMP
|
||||
|| match.key->ip_proto ==IPPROTO_ICMPV6)
|
||||
if (match.key->ip_proto == IPPROTO_ICMP || match.key->ip_proto == IPPROTO_ICMPV6)
|
||||
flow->rule.frame_type_l4 = 2;
|
||||
if (match.key->ip_proto == IPPROTO_TCP)
|
||||
flow->rule.frame_type_l4 = 3;
|
||||
@ -72,7 +69,7 @@ static int rtl83xx_parse_flow_rule(struct rtl838x_switch_priv *priv,
|
||||
flow_rule_match_vlan(rule, &match);
|
||||
flow->rule.itag = match.key->vlan_id;
|
||||
flow->rule.itag_m = match.mask->vlan_id;
|
||||
// TODO: What about match.key->vlan_priority ?
|
||||
/* TODO: What about match.key->vlan_priority? */
|
||||
}
|
||||
|
||||
if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_IPV4_ADDRS)) {
|
||||
@ -108,7 +105,7 @@ static int rtl83xx_parse_flow_rule(struct rtl838x_switch_priv *priv,
|
||||
flow->rule.sport_m = match.mask->src;
|
||||
}
|
||||
|
||||
// TODO: ICMP
|
||||
/* TODO: ICMP */
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -150,7 +147,7 @@ static int rtl83xx_add_flow(struct rtl838x_switch_priv *priv, struct flow_cls_of
|
||||
pr_debug("%s\n", __func__);
|
||||
|
||||
rtl83xx_parse_flow_rule(priv, rule, flow);
|
||||
|
||||
|
||||
flow_action_for_each(i, act, &rule->action) {
|
||||
switch (act->id) {
|
||||
case FLOW_ACTION_DROP:
|
||||
@ -176,7 +173,7 @@ static int rtl83xx_add_flow(struct rtl838x_switch_priv *priv, struct flow_cls_of
|
||||
|
||||
case FLOW_ACTION_VLAN_PUSH:
|
||||
pr_debug("%s: VLAN_PUSH\n", __func__);
|
||||
// TODO: act->vlan.proto
|
||||
/* TODO: act->vlan.proto */
|
||||
flow->rule.ivid_act = PIE_ACT_VID_ASSIGN;
|
||||
flow->rule.ivid_sel = true;
|
||||
flow->rule.ivid_data = htons(act->vlan.vid);
|
||||
@ -271,9 +268,9 @@ rcu_unlock:
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
rtl83xx_add_flow(priv, f, flow); // TODO: check error
|
||||
rtl83xx_add_flow(priv, f, flow); /* TODO: check error */
|
||||
|
||||
// Add log action to flow
|
||||
/* Add log action to flow */
|
||||
flow->rule.packet_cntr = rtl83xx_packet_cntr_alloc(priv);
|
||||
if (flow->rule.packet_cntr >= 0) {
|
||||
pr_debug("Using packet counter %d\n", flow->rule.packet_cntr);
|
||||
@ -288,6 +285,7 @@ out_free:
|
||||
kfree(flow);
|
||||
out:
|
||||
pr_err("%s: error %d\n", __func__, err);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
@ -311,6 +309,7 @@ static int rtl83xx_delete_flower(struct rtl838x_switch_priv *priv,
|
||||
kfree_rcu(flow, rcu_head);
|
||||
|
||||
rcu_read_unlock();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -333,9 +332,10 @@ static int rtl83xx_stats_flower(struct rtl838x_switch_priv *priv,
|
||||
flow->rule.last_packet_cnt = total_packets;
|
||||
}
|
||||
|
||||
// TODO: We need a second PIE rule to count the bytes
|
||||
/* TODO: We need a second PIE rule to count the bytes */
|
||||
flow_stats_update(&cls_flower->stats, 100 * new_packets, new_packets, 0, lastused,
|
||||
FLOW_ACTION_HW_STATS_IMMEDIATE);
|
||||
FLOW_ACTION_HW_STATS_IMMEDIATE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -3,9 +3,7 @@
|
||||
#ifndef _RTL838X_ETH_H
|
||||
#define _RTL838X_ETH_H
|
||||
|
||||
/*
|
||||
* Register definition
|
||||
*/
|
||||
/* Register definition */
|
||||
|
||||
/* Per port MAC control */
|
||||
#define RTL838X_MAC_PORT_CTRL (0xd560)
|
||||
@ -118,7 +116,7 @@
|
||||
#define RTL930X_MAC_LINK_DUP_STS (0xCB28)
|
||||
#define RTL931X_MAC_LINK_DUP_STS (0x0ef0)
|
||||
|
||||
// TODO: RTL8390_MAC_LINK_MEDIA_STS_ADDR ???
|
||||
/* TODO: RTL8390_MAC_LINK_MEDIA_STS_ADDR??? */
|
||||
|
||||
#define RTL838X_MAC_TX_PAUSE_STS (0xa1a0)
|
||||
#define RTL839X_MAC_TX_PAUSE_STS (0x03b8)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -18,7 +18,7 @@ struct __attribute__ ((__packed__)) fw_header {
|
||||
struct part parts[10];
|
||||
};
|
||||
|
||||
// TODO: fixed path?
|
||||
/* TODO: fixed path? */
|
||||
#define FIRMWARE_838X_8380_1 "rtl838x_phy/rtl838x_8380.fw"
|
||||
#define FIRMWARE_838X_8214FC_1 "rtl838x_phy/rtl838x_8214fc.fw"
|
||||
#define FIRMWARE_838X_8218b_1 "rtl838x_phy/rtl838x_8218b.fw"
|
||||
@ -35,7 +35,7 @@ struct __attribute__ ((__packed__)) fw_header {
|
||||
#define PHY_ID_RTL8393_I 0x001c8393
|
||||
#define PHY_ID_RTL9300_I 0x70d03106
|
||||
|
||||
// PHY MMD devices
|
||||
/* PHY MMD devices */
|
||||
#define MMD_AN 7
|
||||
#define MMD_VEND2 31
|
||||
|
||||
@ -60,7 +60,7 @@ struct __attribute__ ((__packed__)) fw_header {
|
||||
#define RTL930X_SDS_INDACS_DATA (0x03B4)
|
||||
#define RTL930X_MAC_FORCE_MODE_CTRL (0xCA1C)
|
||||
|
||||
/*Registers of the internal SerDes of the 9310 */
|
||||
/* Registers of the internal SerDes of the 9310 */
|
||||
#define RTL931X_SERDES_INDRT_ACCESS_CTRL (0x5638)
|
||||
#define RTL931X_SERDES_INDRT_DATA_CTRL (0x563C)
|
||||
#define RTL931X_SERDES_MODE_CTRL (0x13cc)
|
||||
|
||||
@ -6,9 +6,15 @@ include $(INCLUDE_DIR)/image.mk
|
||||
KERNEL_LOADADDR = 0x80000000
|
||||
KERNEL_ENTRY = 0x80000400
|
||||
|
||||
DEVICE_VARS += ZYXEL_VERS DLINK_KERNEL_PART_SIZE
|
||||
DEVICE_VARS += CAMEO_KERNEL_PART CAMEO_ROOTFS_PART CAMEO_CUSTOMER_SIGNATURE CAMEO_BOARD_VERSION
|
||||
DEVICE_VARS += H3C_PRODUCT_ID H3C_DEVICE_ID
|
||||
DEVICE_VARS += \
|
||||
CAMEO_BOARD_VERSION \
|
||||
CAMEO_CUSTOMER_SIGNATURE \
|
||||
CAMEO_KERNEL_PART \
|
||||
CAMEO_ROOTFS_PART \
|
||||
DLINK_KERNEL_PART_SIZE \
|
||||
H3C_DEVICE_ID \
|
||||
H3C_PRODUCT_ID \
|
||||
ZYXEL_VERS
|
||||
|
||||
define Build/zyxel-vers
|
||||
( echo VERS;\
|
||||
@ -81,13 +87,26 @@ endef
|
||||
|
||||
define Device/Default
|
||||
PROFILES = Default
|
||||
KERNEL := kernel-bin | append-dtb | gzip | uImage gzip
|
||||
KERNEL_INITRAMFS := kernel-bin | append-dtb | gzip | uImage gzip
|
||||
KERNEL := \
|
||||
kernel-bin | \
|
||||
append-dtb | \
|
||||
gzip | \
|
||||
uImage gzip
|
||||
KERNEL_INITRAMFS := \
|
||||
kernel-bin | \
|
||||
append-dtb | \
|
||||
gzip | \
|
||||
uImage gzip
|
||||
DEVICE_DTS_DIR := ../dts-$(KERNEL_PATCHVER)
|
||||
DEVICE_DTS = $$(SOC)_$(1)
|
||||
IMAGES := sysupgrade.bin
|
||||
IMAGE/sysupgrade.bin := append-kernel | pad-to 64k | append-rootfs | pad-rootfs | \
|
||||
check-size | append-metadata
|
||||
IMAGE/sysupgrade.bin := \
|
||||
append-kernel | \
|
||||
pad-to 64k | \
|
||||
append-rootfs | \
|
||||
pad-rootfs | \
|
||||
check-size | \
|
||||
append-metadata
|
||||
endef
|
||||
|
||||
include $(SUBTARGET).mk
|
||||
|
||||
@ -4,15 +4,26 @@ define Device/d-link_dgs-1210
|
||||
IMAGE_SIZE := 13824k
|
||||
DEVICE_VENDOR := D-Link
|
||||
DLINK_KERNEL_PART_SIZE := 1572864
|
||||
KERNEL := kernel-bin | append-dtb | gzip | uImage gzip | dlink-cameo
|
||||
KERNEL := \
|
||||
kernel-bin | \
|
||||
append-dtb | \
|
||||
gzip | \
|
||||
uImage gzip | \
|
||||
dlink-cameo
|
||||
CAMEO_KERNEL_PART := 2
|
||||
CAMEO_ROOTFS_PART := 3
|
||||
CAMEO_CUSTOMER_SIGNATURE := 2
|
||||
CAMEO_BOARD_VERSION := 32
|
||||
IMAGES += factory_image1.bin
|
||||
IMAGE/factory_image1.bin := append-kernel | pad-to 64k | \
|
||||
append-rootfs | pad-rootfs | pad-to 16 | check-size | \
|
||||
dlink-version | dlink-headers
|
||||
IMAGE/factory_image1.bin := \
|
||||
append-kernel | \
|
||||
pad-to 64k | \
|
||||
append-rootfs | \
|
||||
pad-rootfs | \
|
||||
pad-to 16 | \
|
||||
check-size | \
|
||||
dlink-version | \
|
||||
dlink-headers
|
||||
endef
|
||||
|
||||
define Device/hpe_1920
|
||||
@ -20,8 +31,36 @@ define Device/hpe_1920
|
||||
IMAGE_SIZE := 29632k
|
||||
BLOCKSIZE := 64k
|
||||
H3C_PRODUCT_ID := 0x3c010501
|
||||
KERNEL := kernel-bin | append-dtb | relocate-kernel | 7z | h3c-image | h3c-vfs
|
||||
KERNEL_INITRAMFS := kernel-bin | append-dtb | relocate-kernel | 7z | h3c-image
|
||||
IMAGE/sysupgrade.bin := append-kernel | pad-to $$$$(BLOCKSIZE) | append-rootfs | \
|
||||
pad-rootfs | check-size | append-metadata
|
||||
KERNEL := \
|
||||
kernel-bin | \
|
||||
append-dtb | \
|
||||
relocate-kernel | \
|
||||
7z | \
|
||||
h3c-image | \
|
||||
h3c-vfs
|
||||
KERNEL_INITRAMFS := \
|
||||
kernel-bin | \
|
||||
append-dtb | \
|
||||
relocate-kernel | \
|
||||
7z | \
|
||||
h3c-image
|
||||
IMAGE/sysupgrade.bin := \
|
||||
append-kernel | \
|
||||
pad-to $$$$(BLOCKSIZE) | \
|
||||
append-rootfs | \
|
||||
pad-rootfs | \
|
||||
check-size | \
|
||||
append-metadata
|
||||
endef
|
||||
|
||||
define Device/zyxel_gs1900
|
||||
DEVICE_VENDOR := ZyXEL
|
||||
IMAGE_SIZE := 6976k
|
||||
UIMAGE_MAGIC := 0x83800000
|
||||
KERNEL_INITRAMFS := \
|
||||
kernel-bin | \
|
||||
append-dtb | \
|
||||
gzip | \
|
||||
zyxel-vers | \
|
||||
uImage gzip
|
||||
endef
|
||||
|
||||
@ -67,7 +67,10 @@ define Device/engenius_ews2910p
|
||||
DEVICE_VENDOR := EnGenius
|
||||
DEVICE_MODEL := EWP2910P
|
||||
UIMAGE_MAGIC := 0x03802910
|
||||
KERNEL_INITRAMFS := kernel-bin | append-dtb | gzip | \
|
||||
KERNEL_INITRAMFS := \
|
||||
kernel-bin | \
|
||||
append-dtb | \
|
||||
gzip | \
|
||||
uImage gzip -n 'IMG-0.00.00-c0.0.00'
|
||||
endef
|
||||
TARGET_DEVICES += engenius_ews2910p
|
||||
@ -116,8 +119,16 @@ TARGET_DEVICES += iodata_bsh-g24mb
|
||||
|
||||
# "NGE" refers to the uImage magic
|
||||
define Device/netgear_nge
|
||||
KERNEL := kernel-bin | append-dtb | lzma | uImage lzma
|
||||
KERNEL_INITRAMFS := kernel-bin | append-dtb | lzma | uImage lzma
|
||||
KERNEL := \
|
||||
kernel-bin | \
|
||||
append-dtb | \
|
||||
lzma | \
|
||||
uImage lzma
|
||||
KERNEL_INITRAMFS := \
|
||||
kernel-bin | \
|
||||
append-dtb | \
|
||||
lzma | \
|
||||
uImage lzma
|
||||
SOC := rtl8380
|
||||
IMAGE_SIZE := 14848k
|
||||
UIMAGE_MAGIC := 0x4e474520
|
||||
@ -207,17 +218,9 @@ define Device/tplink_sg2210p-v3
|
||||
endef
|
||||
TARGET_DEVICES += tplink_sg2210p-v3
|
||||
|
||||
define Device/zyxel_gs1900
|
||||
SOC := rtl8380
|
||||
IMAGE_SIZE := 6976k
|
||||
DEVICE_VENDOR := ZyXEL
|
||||
UIMAGE_MAGIC := 0x83800000
|
||||
KERNEL_INITRAMFS := kernel-bin | append-dtb | gzip | zyxel-vers | \
|
||||
uImage gzip
|
||||
endef
|
||||
|
||||
define Device/zyxel_gs1900-10hp
|
||||
$(Device/zyxel_gs1900)
|
||||
SOC := rtl8380
|
||||
DEVICE_MODEL := GS1900-10HP
|
||||
ZYXEL_VERS := AAZI
|
||||
endef
|
||||
@ -233,6 +236,7 @@ TARGET_DEVICES += zyxel_gs1900-16
|
||||
|
||||
define Device/zyxel_gs1900-8
|
||||
$(Device/zyxel_gs1900)
|
||||
SOC := rtl8380
|
||||
DEVICE_MODEL := GS1900-8
|
||||
ZYXEL_VERS := AAHH
|
||||
endef
|
||||
@ -240,6 +244,7 @@ TARGET_DEVICES += zyxel_gs1900-8
|
||||
|
||||
define Device/zyxel_gs1900-8hp-v1
|
||||
$(Device/zyxel_gs1900)
|
||||
SOC := rtl8380
|
||||
DEVICE_MODEL := GS1900-8HP
|
||||
DEVICE_VARIANT := v1
|
||||
ZYXEL_VERS := AAHI
|
||||
@ -249,6 +254,7 @@ TARGET_DEVICES += zyxel_gs1900-8hp-v1
|
||||
|
||||
define Device/zyxel_gs1900-8hp-v2
|
||||
$(Device/zyxel_gs1900)
|
||||
SOC := rtl8380
|
||||
DEVICE_MODEL := GS1900-8HP
|
||||
DEVICE_VARIANT := v2
|
||||
ZYXEL_VERS := AAHI
|
||||
|
||||
@ -15,7 +15,10 @@ define Device/panasonic_m48eg-pn28480k
|
||||
DEVICE_VENDOR := Panasonic
|
||||
DEVICE_MODEL := Switch-M48eG
|
||||
DEVICE_VARIANT := PN28480K
|
||||
DEVICE_PACKAGES := kmod-hwmon-gpiofan kmod-hwmon-lm75 kmod-i2c-mux-pca954x \
|
||||
DEVICE_PACKAGES := \
|
||||
kmod-hwmon-gpiofan \
|
||||
kmod-hwmon-lm75 \
|
||||
kmod-i2c-mux-pca954x \
|
||||
kmod-thermal
|
||||
endef
|
||||
TARGET_DEVICES += panasonic_m48eg-pn28480k
|
||||
@ -27,18 +30,16 @@ define Device/tplink_sg2452p-v4
|
||||
DEVICE_VENDOR := TP-Link
|
||||
DEVICE_MODEL := SG2452P
|
||||
DEVICE_VARIANT := v4
|
||||
DEVICE_PACKAGES := kmod-hwmon-gpiofan kmod-hwmon-tps23861
|
||||
DEVICE_PACKAGES := \
|
||||
kmod-hwmon-gpiofan \
|
||||
kmod-hwmon-tps23861
|
||||
endef
|
||||
TARGET_DEVICES += tplink_sg2452p-v4
|
||||
|
||||
define Device/zyxel_gs1900-48
|
||||
$(Device/zyxel_gs1900)
|
||||
SOC := rtl8393
|
||||
IMAGE_SIZE := 13952k
|
||||
DEVICE_VENDOR := ZyXEL
|
||||
UIMAGE_MAGIC := 0x83800000
|
||||
ZYXEL_VERS := AAHO
|
||||
DEVICE_MODEL := GS1900-48
|
||||
KERNEL_INITRAMFS := kernel-bin | append-dtb | gzip | zyxel-vers $$$$(ZYXEL_VERS) | \
|
||||
uImage gzip
|
||||
ZYXEL_VERS := AAHN
|
||||
endef
|
||||
TARGET_DEVICES += zyxel_gs1900-48
|
||||
|
||||
@ -6,9 +6,12 @@ define Device/zyxel_xgs1250-12
|
||||
ZYXEL_VERS := ABWE
|
||||
DEVICE_VENDOR := Zyxel
|
||||
DEVICE_MODEL := XGS1250-12
|
||||
IMAGE_SIZE := 13312k
|
||||
KERNEL_INITRAMFS := kernel-bin | append-dtb | gzip | zyxel-vers $$$$(ZYXEL_VERS) | \
|
||||
IMAGE_SIZE := 13312k
|
||||
KERNEL_INITRAMFS := \
|
||||
kernel-bin | \
|
||||
append-dtb | \
|
||||
gzip | \
|
||||
zyxel-vers $$$$(ZYXEL_VERS) | \
|
||||
uImage gzip
|
||||
endef
|
||||
|
||||
TARGET_DEVICES += zyxel_xgs1250-12
|
||||
|
||||
@ -12,4 +12,3 @@ define Target/Description
|
||||
endef
|
||||
|
||||
FEATURES := $(filter-out mips16,$(FEATURES))
|
||||
|
||||
|
||||
@ -10,4 +10,3 @@ KERNEL_PATCHVER:=5.10
|
||||
define Target/Description
|
||||
Build firmware images for Realtek RTL839x based boards.
|
||||
endef
|
||||
|
||||
|
||||
@ -10,4 +10,3 @@ KERNEL_PATCHVER:=5.10
|
||||
define Target/Description
|
||||
Build firmware images for Realtek RTL930x based boards.
|
||||
endef
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user