diff --git a/drivers/net/dsa/realtek/rtl8365mb.h b/drivers/net/dsa/realtek/rtl8365mb.h
index daa8f0b..cb8486a 100644
--- a/drivers/net/dsa/realtek/rtl8365mb.h
+++ b/drivers/net/dsa/realtek/rtl8365mb.h
@@ -10,12 +10,19 @@ enum rtl8365mb_family {
};
struct rtl8365mb_jam_tbl_entry;
+struct rtl8365mb_l2_uc;
+struct rtl8365mb_l2_mc;
struct rtl8365mb_family_info {
enum rtl8365mb_family family;
unsigned int num_ports;
const struct rtl8365mb_jam_tbl_entry *jam_table;
size_t jam_size;
+ size_t l2_entry_size;
+ void (*l2_data_to_uc)(const u16 *data, struct rtl8365mb_l2_uc *uc);
+ void (*l2_uc_to_data)(const struct rtl8365mb_l2_uc *uc, u16 *data);
+ void (*l2_data_to_mc)(const u16 *data, struct rtl8365mb_l2_mc *mc);
+ void (*l2_mc_to_data)(const struct rtl8365mb_l2_mc *mc, u16 *data);
};
const struct rtl8365mb_family_info *diff --git a/drivers/net/dsa/realtek/rtl8365mb_l2.c b/drivers/net/dsa/realtek/rtl8365mb_l2.c
index 0494d8a..cd5b333 100644
--- a/drivers/net/dsa/realtek/rtl8365mb_l2.c
+++ b/drivers/net/dsa/realtek/rtl8365mb_l2.c
@@ -6,18 +6,11 @@
#include <linux/etherdevice.h>
+#include "rtl8365mb.h"
#include "rtl8365mb_l2.h"
#include "rtl8365mb_table.h"
#include <linux/regmap.h>
-#define RTL8365MB_L2_ENTRY_SIZE 6
-
-#define RTL8365MB_L2_UC_D0_MAC5_MSK GENMASK(7, 0)
-#define RTL8365MB_L2_UC_D0_MAC4_MSK GENMASK(15, 8)
-#define RTL8365MB_L2_UC_D1_MAC3_MSK GENMASK(7, 0)
-#define RTL8365MB_L2_UC_D1_MAC2_MSK GENMASK(15, 8)
-#define RTL8365MB_L2_UC_D2_MAC1_MSK GENMASK(7, 0)
-#define RTL8365MB_L2_UC_D2_MAC0_MSK GENMASK(15, 8)
#define RTL8365MB_L2_UC_D3_VID_MSK GENMASK(11, 0)
#define RTL8365MB_L2_UC_D3_IVL_MSK GENMASK(13, 13)
#define RTL8365MB_L2_UC_D3_PORT_EXT_MSK GENMASK(15, 15)
@@ -36,12 +29,6 @@
#define RTL8365MB_L2_UC_D5_FWD_PRI_MSK GENMASK(4, 4)
#define RTL8365MB_L2_UC_D5_STATIC_MSK GENMASK(5, 5)
-#define RTL8365MB_L2_MC_D0_MAC5_MSK GENMASK(7, 0)
-#define RTL8365MB_L2_MC_D0_MAC4_MSK GENMASK(15, 8)
-#define RTL8365MB_L2_MC_D1_MAC3_MSK GENMASK(7, 0)
-#define RTL8365MB_L2_MC_D1_MAC2_MSK GENMASK(15, 8)
-#define RTL8365MB_L2_MC_D2_MAC1_MSK GENMASK(7, 0)
-#define RTL8365MB_L2_MC_D2_MAC0_MSK GENMASK(15, 8)
#define RTL8365MB_L2_MC_D3_VID_MSK GENMASK(11, 0)
#define RTL8365MB_L2_MC_D3_IVL_MSK GENMASK(13, 13)
#define RTL8365MB_L2_MC_D3_MBR_HI1_MSK GENMASK(15, 14)
@@ -131,16 +118,29 @@ struct rtl8365mb_l2_mc {
bool igmp_asic;
};
-static void rtl8365mb_l2_data_to_uc(const u16 *data, struct rtl8365mb_l2_uc *uc)
+static void rtl8365mb_l2_mac_to_data(const u8 *m, u16 *data)
+{
+ data[0] = (m[4] << 8) | m[5];
+ data[1] = (m[2] << 8) | m[3];
+ data[2] = (m[0] << 8) | m[1];
+}
+
+static void rtl8365mb_l2_data_to_mac(const u16 *data, u8 *m)
+{
+ m[5] = data[0] & 0xff;
+ m[4] = data[0] >> 8;
+ m[3] = data[1] & 0xff;
+ m[2] = data[1] >> 8;
+ m[1] = data[2] & 0xff;
+ m[0] = data[2] >> 8;
+}
+
+void rtl8365mb_c_l2_data_to_uc(const u16 *data,
+ struct rtl8365mb_l2_uc *uc)
{
u32 val;
- uc->key.mac_addr[5] = FIELD_GET(RTL8365MB_L2_UC_D0_MAC5_MSK, data[0]);
- uc->key.mac_addr[4] = FIELD_GET(RTL8365MB_L2_UC_D0_MAC4_MSK, data[0]);
- uc->key.mac_addr[3] = FIELD_GET(RTL8365MB_L2_UC_D1_MAC3_MSK, data[1]);
- uc->key.mac_addr[2] = FIELD_GET(RTL8365MB_L2_UC_D1_MAC2_MSK, data[1]);
- uc->key.mac_addr[1] = FIELD_GET(RTL8365MB_L2_UC_D2_MAC1_MSK, data[2]);
- uc->key.mac_addr[0] = FIELD_GET(RTL8365MB_L2_UC_D2_MAC0_MSK, data[2]);
+ rtl8365mb_l2_data_to_mac(data, uc->key.mac_addr);
uc->key.efid = FIELD_GET(RTL8365MB_L2_UC_D4_EFID_MSK, data[4]);
uc->key.vid = FIELD_GET(RTL8365MB_L2_UC_D3_VID_MSK, data[3]);
uc->key.ivl = FIELD_GET(RTL8365MB_L2_UC_D3_IVL_MSK, data[3]);@@ -161,23 +161,13 @@ static void rtl8365mb_l2_data_to_uc(const u16 *data, struct rtl8365mb_l2_uc *uc)
uc->is_static = FIELD_GET(RTL8365MB_L2_UC_D5_STATIC_MSK, data[5]);
}
-static void rtl8365mb_l2_uc_to_data(const struct rtl8365mb_l2_uc *uc, u16 *data)
+void rtl8365mb_c_l2_uc_to_data(const struct rtl8365mb_l2_uc *uc,
+ u16 *data)
{
u32 val;
- memset(data, 0, RTL8365MB_L2_ENTRY_SIZE * 2);
- data[0] |=
- FIELD_PREP(RTL8365MB_L2_UC_D0_MAC5_MSK, uc->key.mac_addr[5]);
- data[0] |=
- FIELD_PREP(RTL8365MB_L2_UC_D0_MAC4_MSK, uc->key.mac_addr[4]);
- data[1] |=
- FIELD_PREP(RTL8365MB_L2_UC_D1_MAC3_MSK, uc->key.mac_addr[3]);
- data[1] |=
- FIELD_PREP(RTL8365MB_L2_UC_D1_MAC2_MSK, uc->key.mac_addr[2]);
- data[2] |=
- FIELD_PREP(RTL8365MB_L2_UC_D2_MAC1_MSK, uc->key.mac_addr[1]);
- data[2] |=
- FIELD_PREP(RTL8365MB_L2_UC_D2_MAC0_MSK, uc->key.mac_addr[0]);
+ memset(data, 0, RTL8365MB_C_L2_ENTRY_SIZE * 2);
+ rtl8365mb_l2_mac_to_data(uc->key.mac_addr, data);
data[3] |= FIELD_PREP(RTL8365MB_L2_UC_D3_VID_MSK, uc->key.vid);
data[3] |= FIELD_PREP(RTL8365MB_L2_UC_D3_IVL_MSK, uc->key.ivl);
@@ -200,16 +190,12 @@ static void rtl8365mb_l2_uc_to_data(const struct rtl8365mb_l2_uc *uc, u16 *data)
data[5] |= FIELD_PREP(RTL8365MB_L2_UC_D5_STATIC_MSK, uc->is_static);
}
-static void rtl8365mb_l2_data_to_mc(const u16 *data, struct rtl8365mb_l2_mc *mc)
+void rtl8365mb_c_l2_data_to_mc(const u16 *data,
+ struct rtl8365mb_l2_mc *mc)
{
u32 val;
- mc->key.mac_addr[5] = FIELD_GET(RTL8365MB_L2_MC_D0_MAC5_MSK, data[0]);
- mc->key.mac_addr[4] = FIELD_GET(RTL8365MB_L2_MC_D0_MAC4_MSK, data[0]);
- mc->key.mac_addr[3] = FIELD_GET(RTL8365MB_L2_MC_D1_MAC3_MSK, data[1]);
- mc->key.mac_addr[2] = FIELD_GET(RTL8365MB_L2_MC_D1_MAC2_MSK, data[1]);
- mc->key.mac_addr[1] = FIELD_GET(RTL8365MB_L2_MC_D2_MAC1_MSK, data[2]);
- mc->key.mac_addr[0] = FIELD_GET(RTL8365MB_L2_MC_D2_MAC0_MSK, data[2]);
+ rtl8365mb_l2_data_to_mac(data, mc->key.mac_addr);
/* key.vid,key.fid shares the same memory space */
mc->key.vid = FIELD_GET(RTL8365MB_L2_MC_D3_VID_MSK, data[3]);
mc->key.ivl = FIELD_GET(RTL8365MB_L2_MC_D3_IVL_MSK, data[3]);@@ -228,17 +214,13 @@ static void rtl8365mb_l2_data_to_mc(const u16 *data, struct rtl8365mb_l2_mc *mc)
mc->igmp_asic = FIELD_GET(RTL8365MB_L2_MC_D5_IGMP_ASIC_MSK, data[5]);
}
-static void rtl8365mb_l2_mc_to_data(const struct rtl8365mb_l2_mc *mc, u16 *data)
+void rtl8365mb_c_l2_mc_to_data(const struct rtl8365mb_l2_mc *mc,
+ u16 *data)
{
u32 val;
- memset(data, 0, RTL8365MB_L2_ENTRY_SIZE * 2);
- data[0] |= FIELD_PREP(RTL8365MB_L2_MC_D0_MAC5_MSK, mc->key.mac_addr[5]);
- data[0] |= FIELD_PREP(RTL8365MB_L2_MC_D0_MAC4_MSK, mc->key.mac_addr[4]);
- data[1] |= FIELD_PREP(RTL8365MB_L2_MC_D1_MAC3_MSK, mc->key.mac_addr[3]);
- data[1] |= FIELD_PREP(RTL8365MB_L2_MC_D1_MAC2_MSK, mc->key.mac_addr[2]);
- data[2] |= FIELD_PREP(RTL8365MB_L2_MC_D2_MAC1_MSK, mc->key.mac_addr[1]);
- data[2] |= FIELD_PREP(RTL8365MB_L2_MC_D2_MAC0_MSK, mc->key.mac_addr[0]);
+ memset(data, 0, RTL8365MB_C_L2_ENTRY_SIZE * 2);
+ rtl8365mb_l2_mac_to_data(mc->key.mac_addr, data);
data[3] |= FIELD_PREP(RTL8365MB_L2_MC_D3_VID_MSK, mc->key.vid);
data[3] |= FIELD_PREP(RTL8365MB_L2_MC_D3_IVL_MSK, mc->key.ivl);
@@ -283,17 +265,20 @@ int rtl8365mb_l2_get_next_uc(struct realtek_priv *priv, u16 *addr, int port,
struct realtek_fdb_entry *entry)
{
u16 data[RTL8365MB_L2_ENTRY_SIZE] = { 0 };
+ const struct rtl8365mb_family_info *fi;
struct rtl8365mb_l2_uc uc;
int ret;
+ fi = rtl8365mb_get_family_info(priv);
+
ret = rtl8365mb_table_query(priv, RTL8365MB_TABLE_L2,
RTL8365MB_TABLE_OP_READ, addr,
RTL8365MB_TABLE_L2_METHOD_ADDR_NEXT_UC_PORT,
- port, data, RTL8365MB_L2_ENTRY_SIZE);
+ port, data, fi->l2_entry_size);
if (ret)
return ret;
- rtl8365mb_l2_data_to_uc(data, &uc);
+ fi->l2_data_to_uc(data, &uc);
ether_addr_copy(entry->mac_addr, uc.key.mac_addr);
entry->vid = uc.key.vid;@@ -307,6 +292,7 @@ int rtl8365mb_l2_add_uc(struct realtek_priv *priv, int port,
u16 efid, u16 vid)
{
u16 data[RTL8365MB_L2_ENTRY_SIZE] = { 0 };
+ const struct rtl8365mb_family_info *fi;
struct rtl8365mb_l2_uc uc = { 0 };
u16 addr;
int ret;@@ -326,13 +312,14 @@ int rtl8365mb_l2_add_uc(struct realtek_priv *priv, int port,
uc.is_static = true;
/* age greater than 0 adds/updates entries */
uc.age = 1;
- rtl8365mb_l2_uc_to_data(&uc, data);
+ fi = rtl8365mb_get_family_info(priv);
+ fi->l2_uc_to_data(&uc, data);
/* add the new entry or update an existing one */
ret = rtl8365mb_table_query(priv, RTL8365MB_TABLE_L2,
RTL8365MB_TABLE_OP_WRITE, &addr,
0, 0,
- data, RTL8365MB_L2_ENTRY_SIZE);
+ data, fi->l2_entry_size);
/* Assume the missing new entry as the table is full */
if (ret == -ENOENT)
@@ -347,6 +334,7 @@ int rtl8365mb_l2_del_uc(struct realtek_priv *priv, int port,
u16 efid, u16 vid)
{
u16 data[RTL8365MB_L2_ENTRY_SIZE] = { 0 };
+ const struct rtl8365mb_family_info *fi;
struct rtl8365mb_l2_uc uc = { 0 };
u16 addr;
int ret;@@ -358,7 +346,8 @@ int rtl8365mb_l2_del_uc(struct realtek_priv *priv, int port,
uc.key.vid = vid;
/* age 0 deletes the entry */
uc.age = 0;
- rtl8365mb_l2_uc_to_data(&uc, data);
+ fi = rtl8365mb_get_family_info(priv);
+ fi->l2_uc_to_data(&uc, data);
/* it looks like the switch will always add/update the entry,
* even when age is 0 or uc.key did not match an existing entry,
@@ -368,7 +357,7 @@ int rtl8365mb_l2_del_uc(struct realtek_priv *priv, int port,
ret = rtl8365mb_table_query(priv, RTL8365MB_TABLE_L2,
RTL8365MB_TABLE_OP_WRITE, &addr,
0, 0,
- data, RTL8365MB_L2_ENTRY_SIZE);
+ data, fi->l2_entry_size);
if (ret == -ENOENT) {
dev_dbg(priv->dev, "%s: %pM vid=%d efid=%d missing\n",@@ -451,6 +440,7 @@ int rtl8365mb_l2_add_mc(struct realtek_priv *priv, int port,
u16 vid)
{
u16 data[RTL8365MB_L2_ENTRY_SIZE] = { 0 };
+ const struct rtl8365mb_family_info *fi;
struct rtl8365mb_l2_mc mc = { 0 };
u16 addr;
int ret;@@ -463,16 +453,17 @@ int rtl8365mb_l2_add_mc(struct realtek_priv *priv, int port,
*/
mc.member |= BIT(port);
mc.is_static = 1;
- rtl8365mb_l2_mc_to_data(&mc, data);
+ fi = rtl8365mb_get_family_info(priv);
+ fi->l2_mc_to_data(&mc, data);
/* First look for an existing entry (to get existing port members) */
ret = rtl8365mb_table_query(priv, RTL8365MB_TABLE_L2,
RTL8365MB_TABLE_OP_READ, &addr,
RTL8365MB_TABLE_L2_METHOD_MAC, 0,
- data, RTL8365MB_L2_ENTRY_SIZE);
+ data, fi->l2_entry_size);
if (!ret) {
/* There is already an entry... */
- rtl8365mb_l2_data_to_mc(data, &mc);
+ fi->l2_data_to_mc(data, &mc);
dev_dbg(priv->dev,
"%s: found %pM addr=%d member=0x%x igmpidx=0x%x %s\n",
__func__, mac_addr, addr, mc.member, mc.igmpidx,@@ -487,7 +478,7 @@ int rtl8365mb_l2_add_mc(struct realtek_priv *priv, int port,
mc.is_static = 1;
}
- rtl8365mb_l2_mc_to_data(&mc, data);
+ fi->l2_mc_to_data(&mc, data);
} else if (ret == -ENOENT) {
/* New entry, no need to update data again as it already
* includes the member.@@ -508,7 +499,7 @@ int rtl8365mb_l2_add_mc(struct realtek_priv *priv, int port,
ret = rtl8365mb_table_query(priv, RTL8365MB_TABLE_L2,
RTL8365MB_TABLE_OP_WRITE, &addr,
0, 0,
- data, RTL8365MB_L2_ENTRY_SIZE);
+ data, fi->l2_entry_size);
/* Assume the missing new entry as the table is full */
if (ret == -ENOENT)
@@ -522,6 +513,7 @@ int rtl8365mb_l2_del_mc(struct realtek_priv *priv, int port,
u16 vid)
{
u16 data[RTL8365MB_L2_ENTRY_SIZE] = { 0 };
+ const struct rtl8365mb_family_info *fi;
struct rtl8365mb_l2_mc mc = { 0 };
u16 addr;
int ret;@@ -529,13 +521,14 @@ int rtl8365mb_l2_del_mc(struct realtek_priv *priv, int port,
memcpy(mc.key.mac_addr, mac_addr, ETH_ALEN);
mc.key.vid = vid;
mc.key.ivl = true;
- rtl8365mb_l2_mc_to_data(&mc, data);
+ fi = rtl8365mb_get_family_info(priv);
+ fi->l2_mc_to_data(&mc, data);
/* First look for an existing entry (to get existing port members) */
ret = rtl8365mb_table_query(priv, RTL8365MB_TABLE_L2,
RTL8365MB_TABLE_OP_READ, &addr,
RTL8365MB_TABLE_L2_METHOD_MAC, 0,
- data, RTL8365MB_L2_ENTRY_SIZE);
+ data, fi->l2_entry_size);
if (ret == -ENOENT) {
dev_dbg(priv->dev, "%s: %pM vid=%d missing\n",
__func__, mac_addr, vid);@@ -547,7 +540,7 @@ int rtl8365mb_l2_del_mc(struct realtek_priv *priv, int port,
/* Return on any other error */
return ret;
- rtl8365mb_l2_data_to_mc(data, &mc);
+ fi->l2_data_to_mc(data, &mc);
dev_dbg(priv->dev,
"%s: found %pM addr=%d member=0x%x igmpidx=0x%x %s\n",
__func__, mac_addr, addr, mc.member, mc.igmpidx,
@@ -565,12 +558,12 @@ int rtl8365mb_l2_del_mc(struct realtek_priv *priv, int port,
mc.fwd_pri = 0;
mc.igmp_asic = 0;
}
- rtl8365mb_l2_mc_to_data(&mc, data);
+ fi->l2_mc_to_data(&mc, data);
/* update the existing entry. */
ret = rtl8365mb_table_query(priv, RTL8365MB_TABLE_L2,
RTL8365MB_TABLE_OP_WRITE, &addr,
0, 0,
- data, RTL8365MB_L2_ENTRY_SIZE);
+ data, fi->l2_entry_size);
return ret;
}
diff --git a/drivers/net/dsa/realtek/rtl8365mb_l2.h b/drivers/net/dsa/realtek/rtl8365mb_l2.h
index 9470cf0..a9f9ae4 100644
--- a/drivers/net/dsa/realtek/rtl8365mb_l2.h
+++ b/drivers/net/dsa/realtek/rtl8365mb_l2.h
@@ -12,6 +12,18 @@
#include "realtek.h"
+#define RTL8365MB_C_L2_ENTRY_SIZE 6
+/* Highest L2 entry size of any supported chip, used for sizing */
+#define RTL8365MB_L2_ENTRY_SIZE RTL8365MB_C_L2_ENTRY_SIZE
+
+struct rtl8365mb_l2_uc;
+struct rtl8365mb_l2_mc;
+
+void rtl8365mb_c_l2_data_to_uc(const u16 *data, struct rtl8365mb_l2_uc *uc);
+void rtl8365mb_c_l2_uc_to_data(const struct rtl8365mb_l2_uc *uc, u16 *data);
+void rtl8365mb_c_l2_data_to_mc(const u16 *data, struct rtl8365mb_l2_mc *mc);
+void rtl8365mb_c_l2_mc_to_data(const struct rtl8365mb_l2_mc *mc, u16 *data);
+
int rtl8365mb_l2_get_next_uc(struct realtek_priv *priv, u16 *addr, int port,
struct realtek_fdb_entry *entry);
int rtl8365mb_l2_add_uc(struct realtek_priv *priv, int port,
diff --git a/drivers/net/dsa/realtek/rtl8365mb_main.c b/drivers/net/dsa/realtek/rtl8365mb_main.c
index 96b15dc..e9aac7e 100644
--- a/drivers/net/dsa/realtek/rtl8365mb_main.c
+++ b/drivers/net/dsa/realtek/rtl8365mb_main.c
@@ -811,6 +811,11 @@ static const struct rtl8365mb_family_info rtl8365mb_family_c = {
.num_ports = RTL8365MB_C_MAX_NUM_PORTS,
.jam_table = rtl8365mb_init_jam_8365mb_vc,
.jam_size = ARRAY_SIZE(rtl8365mb_init_jam_8365mb_vc),
+ .l2_entry_size = RTL8365MB_C_L2_ENTRY_SIZE,
+ .l2_data_to_uc = rtl8365mb_c_l2_data_to_uc,
+ .l2_uc_to_data = rtl8365mb_c_l2_uc_to_data,
+ .l2_data_to_mc = rtl8365mb_c_l2_data_to_mc,
+ .l2_mc_to_data = rtl8365mb_c_l2_mc_to_data,
};
/**--
2.53.0