Merge Official Source

Signed-off-by: Tianling Shen <cnsztl@immortalwrt.org>
This commit is contained in:
Tianling Shen 2023-05-08 18:25:15 +08:00
commit 6ac5642117
No known key found for this signature in database
GPG Key ID: 6850B6345C862176
8 changed files with 193 additions and 175 deletions

View File

@ -176,7 +176,6 @@ 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);
pr_debug("%s called\n", __func__);
@ -187,18 +186,24 @@ static int rtl83xx_setup(struct dsa_switch *ds)
priv->ports[i].enable = false;
priv->ports[priv->cpu_port].enable = true;
/* Isolate ports from each other: traffic only CPU <-> port */
/* Setting bit j in register RTL838X_PORT_ISO_CTRL(i) allows
* traffic from source port i to destination port j
/* Configure ports so they are disabled by default, but once enabled
* they will work in isolated mode (only traffic between port and CPU).
*/
for (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));
port_bitmap |= BIT_ULL(i);
priv->ports[i].pm = BIT_ULL(priv->cpu_port);
priv->r->traffic_set(i, BIT_ULL(i));
}
}
priv->r->set_port_reg_be(port_bitmap, priv->r->port_iso_ctrl(priv->cpu_port));
priv->r->traffic_set(priv->cpu_port, BIT_ULL(priv->cpu_port));
/* For standalone ports, forward packets even if a static fdb
* entry for the source address exists on another port.
*/
if (priv->r->set_static_move_action) {
for (i = 0; i <= priv->cpu_port; i++)
priv->r->set_static_move_action(i, true);
}
if (priv->family_id == RTL8380_FAMILY_ID)
rtl838x_print_matrix();
@ -240,7 +245,6 @@ static int rtl93xx_setup(struct dsa_switch *ds)
{
int i;
struct rtl838x_switch_priv *priv = ds->priv;
u32 port_bitmap = BIT(priv->cpu_port);
pr_info("%s called\n", __func__);
@ -258,13 +262,16 @@ static int rtl93xx_setup(struct dsa_switch *ds)
priv->ports[i].enable = false;
priv->ports[priv->cpu_port].enable = true;
/* Configure ports so they are disabled by default, but once enabled
* they will work in isolated mode (only traffic between port and CPU).
*/
for (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);
priv->ports[i].pm = BIT_ULL(priv->cpu_port);
priv->r->traffic_set(i, BIT_ULL(i));
}
}
priv->r->traffic_set(priv->cpu_port, port_bitmap);
priv->r->traffic_set(priv->cpu_port, BIT_ULL(priv->cpu_port));
rtl930x_print_matrix();
@ -981,14 +988,8 @@ static int rtl83xx_mc_group_alloc(struct rtl838x_switch_priv *priv, int port)
if (mc_group >= MAX_MC_GROUPS - 1)
return -1;
if (priv->is_lagmember[port]) {
pr_info("%s: %d is lag slave. ignore\n", __func__, port);
return 0;
}
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);
portmask = BIT_ULL(port);
priv->r->write_mcast_pmask(mc_group, portmask);
return mc_group;
@ -999,10 +1000,7 @@ static u64 rtl83xx_mc_group_add_port(struct rtl838x_switch_priv *priv, int mc_gr
u64 portmask = priv->r->read_mcast_pmask(mc_group);
pr_debug("%s: %d\n", __func__, port);
if (priv->is_lagmember[port]) {
pr_info("%s: %d is lag slave. ignore\n", __func__, port);
return portmask;
}
portmask |= BIT_ULL(port);
priv->r->write_mcast_pmask(mc_group, portmask);
@ -1014,45 +1012,15 @@ static u64 rtl83xx_mc_group_del_port(struct rtl838x_switch_priv *priv, int mc_gr
u64 portmask = priv->r->read_mcast_pmask(mc_group);
pr_debug("%s: %d\n", __func__, port);
if (priv->is_lagmember[port]) {
pr_info("%s: %d is lag slave. ignore\n", __func__, port);
return portmask;
}
portmask &= ~BIT_ULL(port);
priv->r->write_mcast_pmask(mc_group, portmask);
if (portmask == BIT_ULL(priv->cpu_port)) {
portmask &= ~BIT_ULL(priv->cpu_port);
priv->r->write_mcast_pmask(mc_group, portmask);
if (!portmask)
clear_bit(mc_group, priv->mc_group_bm);
}
return portmask;
}
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++) {
u64 portmask = priv->r->read_mcast_pmask(mc_group);
if (portmask & BIT_ULL(port)) {
priv->mc_group_saves[mc_group] = port;
rtl83xx_mc_group_del_port(priv, mc_group, 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++) {
if (priv->mc_group_saves[mc_group] == port) {
rtl83xx_mc_group_add_port(priv, mc_group, port);
priv->mc_group_saves[mc_group] = -1;
}
}
}
static int rtl83xx_port_enable(struct dsa_switch *ds, int port,
struct phy_device *phydev)
{
@ -1071,8 +1039,6 @@ static int rtl83xx_port_enable(struct dsa_switch *ds, int port,
/* add port to switch mask of CPU_PORT */
priv->r->traffic_enable(priv->cpu_port, port);
load_mcgroups(priv, port);
if (priv->is_lagmember[port]) {
pr_debug("%s: %d is lag slave. ignore\n", __func__, port);
return 0;
@ -1108,7 +1074,6 @@ static void rtl83xx_port_disable(struct dsa_switch *ds, int port)
// 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);
/* remove all other ports in the same bridge from switch mask of port */
v = priv->r->traffic_get(port);
@ -1208,7 +1173,6 @@ static int rtl83xx_port_bridge_join(struct dsa_switch *ds, int port,
port_bitmap |= BIT_ULL(i);
}
}
load_mcgroups(priv, port);
/* Add all other ports to this port matrix. */
if (priv->ports[port].enable) {
@ -1218,6 +1182,10 @@ static int rtl83xx_port_bridge_join(struct dsa_switch *ds, int port,
priv->r->traffic_set(port, v);
}
priv->ports[port].pm |= port_bitmap;
if (priv->r->set_static_move_action)
priv->r->set_static_move_action(port, false);
mutex_unlock(&priv->reg_mutex);
return 0;
@ -1227,7 +1195,7 @@ static void rtl83xx_port_bridge_leave(struct dsa_switch *ds, int port,
struct net_device *bridge)
{
struct rtl838x_switch_priv *priv = ds->priv;
u64 port_bitmap = BIT_ULL(priv->cpu_port), v;
u64 port_bitmap = 0, v;
int i;
pr_debug("%s %x: %d", __func__, (u32)priv, port);
@ -1245,20 +1213,22 @@ static void rtl83xx_port_bridge_leave(struct dsa_switch *ds, int port,
if (priv->ports[i].enable)
priv->r->traffic_disable(i, port);
priv->ports[i].pm |= BIT_ULL(port);
port_bitmap &= ~BIT_ULL(i);
priv->ports[i].pm &= ~BIT_ULL(port);
port_bitmap |= BIT_ULL(i);
}
}
store_mcgroups(priv, port);
/* Add all other ports to this port matrix. */
/* Remove all other ports from this port matrix. */
if (priv->ports[port].enable) {
v = priv->r->traffic_get(port);
v |= port_bitmap;
v &= ~port_bitmap;
priv->r->traffic_set(port, v);
}
priv->ports[port].pm &= ~port_bitmap;
if (priv->r->set_static_move_action)
priv->r->set_static_move_action(port, true);
mutex_unlock(&priv->reg_mutex);
}
@ -1436,6 +1406,20 @@ static int rtl83xx_vlan_prepare(struct dsa_switch *ds, int port,
return 0;
}
static void rtl83xx_vlan_set_pvid(struct rtl838x_switch_priv *priv,
int port, int pvid)
{
/* Set both inner and outer PVID of the port */
priv->r->vlan_port_pvid_set(port, PBVLAN_TYPE_INNER, pvid);
priv->r->vlan_port_pvid_set(port, PBVLAN_TYPE_OUTER, pvid);
priv->r->vlan_port_pvidmode_set(port, PBVLAN_TYPE_INNER,
PBVLAN_MODE_UNTAG_AND_PRITAG);
priv->r->vlan_port_pvidmode_set(port, PBVLAN_TYPE_OUTER,
PBVLAN_MODE_UNTAG_AND_PRITAG);
priv->ports[port].pvid = pvid;
}
static void rtl83xx_vlan_add(struct dsa_switch *ds, int port,
const struct switchdev_obj_port_vlan *vlan)
{
@ -1454,20 +1438,11 @@ static void rtl83xx_vlan_add(struct dsa_switch *ds, int port,
mutex_lock(&priv->reg_mutex);
if (vlan->flags & BRIDGE_VLAN_INFO_PVID) {
for (v = vlan->vid_begin; v <= vlan->vid_end; v++) {
if (!v)
continue;
/* Set both inner and outer PVID of the port */
priv->r->vlan_port_pvid_set(port, PBVLAN_TYPE_INNER, v);
priv->r->vlan_port_pvid_set(port, PBVLAN_TYPE_OUTER, v);
priv->r->vlan_port_pvidmode_set(port, PBVLAN_TYPE_INNER,
PBVLAN_MODE_UNTAG_AND_PRITAG);
priv->r->vlan_port_pvidmode_set(port, PBVLAN_TYPE_OUTER,
PBVLAN_MODE_UNTAG_AND_PRITAG);
priv->ports[port].pvid = vlan->vid_end;
}
for (v = vlan->vid_begin; v <= vlan->vid_end; v++) {
if (vlan->flags & BRIDGE_VLAN_INFO_PVID)
rtl83xx_vlan_set_pvid(priv, port, v);
else if (priv->ports[port].pvid == v)
rtl83xx_vlan_set_pvid(priv, port, 0);
}
for (v = vlan->vid_begin; v <= vlan->vid_end; v++) {
@ -1489,6 +1464,8 @@ static void rtl83xx_vlan_add(struct dsa_switch *ds, int port,
info.tagged_ports |= BIT_ULL(port);
if (vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED)
info.untagged_ports |= BIT_ULL(port);
else
info.untagged_ports &= ~BIT_ULL(port);
priv->r->vlan_set_untagged(v, info.untagged_ports);
pr_debug("Untagged ports, VLAN %d: %llx\n", v, info.untagged_ports);
@ -1523,12 +1500,7 @@ static int rtl83xx_vlan_del(struct dsa_switch *ds, int port,
for (v = vlan->vid_begin; v <= vlan->vid_end; v++) {
/* Reset to default if removing the current PVID */
if (v == pvid) {
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);
priv->r->vlan_port_pvidmode_set(port, PBVLAN_TYPE_OUTER,
PBVLAN_MODE_UNTAG_AND_PRITAG);
rtl83xx_vlan_set_pvid(priv, port, 0);
}
/* Get port memberships of this vlan */
priv->r->vlan_tables_read(v, &info);
@ -1662,7 +1634,7 @@ static int rtl83xx_port_fdb_add(struct dsa_switch *ds, int port,
}
// Hash buckets full, try CAM
rtl83xx_find_l2_cam_entry(priv, seed, false, &e);
idx = rtl83xx_find_l2_cam_entry(priv, seed, false, &e);
if (idx >= 0) {
rtl83xx_setup_l2_uc_entry(&e, port, vid, mac);
@ -1698,7 +1670,7 @@ static int rtl83xx_port_fdb_del(struct dsa_switch *ds, int port,
}
/* Check CAM for spillover from hash buckets */
rtl83xx_find_l2_cam_entry(priv, seed, true, &e);
idx = rtl83xx_find_l2_cam_entry(priv, seed, true, &e);
if (idx >= 0) {
e.valid = false;
@ -1800,7 +1772,7 @@ static void rtl83xx_port_mdb_add(struct dsa_switch *ds, int port,
}
// Hash buckets full, try CAM
rtl83xx_find_l2_cam_entry(priv, seed, false, &e);
idx = rtl83xx_find_l2_cam_entry(priv, seed, false, &e);
if (idx >= 0) {
if (e.valid) {
@ -1860,7 +1832,7 @@ int rtl83xx_port_mdb_del(struct dsa_switch *ds, int port,
}
/* Check CAM for spillover from hash buckets */
rtl83xx_find_l2_cam_entry(priv, seed, true, &e);
idx = rtl83xx_find_l2_cam_entry(priv, seed, true, &e);
if (idx >= 0) {
portmask = rtl83xx_mc_group_del_port(priv, e.mc_portmask_index, port);

View File

@ -559,6 +559,15 @@ static void rtl838x_enable_bcast_flood(int port, bool enable)
}
static void rtl838x_set_static_move_action(int port, bool forward)
{
int shift = MV_ACT_PORT_SHIFT(port);
u32 val = forward ? MV_ACT_FORWARD : MV_ACT_DROP;
sw_w32_mask(MV_ACT_MASK << shift, val << shift,
RTL838X_L2_PORT_STATIC_MV_ACT(port));
}
static void rtl838x_stp_get(struct rtl838x_switch_priv *priv, u16 msti, u32 port_state[])
{
int i;
@ -1750,6 +1759,7 @@ const struct rtl838x_reg rtl838x_reg = {
.enable_flood = rtl838x_enable_flood,
.enable_mcast_flood = rtl838x_enable_mcast_flood,
.enable_bcast_flood = rtl838x_enable_bcast_flood,
.set_static_move_action = rtl838x_set_static_move_action,
.stp_get = rtl838x_stp_get,
.stp_set = rtl838x_stp_set,
.mac_port_ctrl = rtl838x_mac_port_ctrl,

View File

@ -251,6 +251,19 @@
#define RTL930X_L2_PORT_NEW_SA_FWD(p) (0x8FF4 + (((p / 10) << 2)))
#define RTL931X_L2_PORT_NEW_SA_FWD(p) (0xC830 + (((p / 10) << 2)))
#define RTL838X_L2_PORT_MV_ACT(p) (0x335c + (((p >> 4) << 2)))
#define RTL839X_L2_PORT_MV_ACT(p) (0x3b80 + (((p >> 4) << 2)))
#define RTL838X_L2_PORT_STATIC_MV_ACT(p) (0x327c + (((p >> 4) << 2)))
#define RTL839X_L2_PORT_STATIC_MV_ACT(p) (0x38dc + (((p >> 4) << 2)))
#define MV_ACT_PORT_SHIFT(p) ((p % 16) * 2)
#define MV_ACT_MASK 0x3
#define MV_ACT_FORWARD 0
#define MV_ACT_DROP 1
#define MV_ACT_TRAP2CPU 2
#define MV_ACT_COPY2CPU 3
#define RTL930X_ST_CTRL (0x8798)
#define RTL930X_L2_PORT_SABLK_CTRL (0x905c)
@ -982,6 +995,7 @@ struct rtl838x_reg {
void (*enable_flood)(int port, bool enable);
void (*enable_mcast_flood)(int port, bool enable);
void (*enable_bcast_flood)(int port, bool enable);
void (*set_static_move_action)(int port, bool forward);
void (*stp_get)(struct rtl838x_switch_priv *priv, u16 msti, u32 port_state[]);
void (*stp_set)(struct rtl838x_switch_priv *priv, u16 msti, u32 port_state[]);
int (*mac_force_mode_ctrl)(int port);
@ -1072,7 +1086,6 @@ struct rtl838x_switch_priv {
struct notifier_block fib_nb;
bool eee_enabled;
unsigned long int mc_group_bm[MAX_MC_GROUPS >> 5];
int mc_group_saves[MAX_MC_GROUPS];
int n_pie_blocks;
struct rhashtable tc_ht;
unsigned long int pie_use_bm[MAX_PIE_ENTRIES >> 5];

View File

@ -602,6 +602,16 @@ static void rtl839x_enable_bcast_flood(int port, bool enable)
{
}
static void rtl839x_set_static_move_action(int port, bool forward)
{
int shift = MV_ACT_PORT_SHIFT(port);
u32 val = forward ? MV_ACT_FORWARD : MV_ACT_DROP;
sw_w32_mask(MV_ACT_MASK << shift, val << shift,
RTL839X_L2_PORT_STATIC_MV_ACT(port));
}
irqreturn_t rtl839x_switch_irq(int irq, void *dev_id)
{
struct dsa_switch *ds = dev_id;
@ -1893,6 +1903,7 @@ const struct rtl838x_reg rtl839x_reg = {
.enable_flood = rtl839x_enable_flood,
.enable_mcast_flood = rtl839x_enable_mcast_flood,
.enable_bcast_flood = rtl839x_enable_bcast_flood,
.set_static_move_action = rtl839x_set_static_move_action,
.stp_get = rtl839x_stp_get,
.stp_set = rtl839x_stp_set,
.mac_force_mode_ctrl = rtl839x_mac_force_mode_ctrl,

View File

@ -167,7 +167,6 @@ static void rtl83xx_port_set_salrn(struct rtl838x_switch_priv *priv,
static int rtl83xx_setup(struct dsa_switch *ds)
{
struct rtl838x_switch_priv *priv = ds->priv;
u64 port_bitmap = BIT_ULL(priv->cpu_port);
pr_debug("%s called\n", __func__);
@ -178,18 +177,24 @@ static int rtl83xx_setup(struct dsa_switch *ds)
priv->ports[i].enable = false;
priv->ports[priv->cpu_port].enable = true;
/* Isolate ports from each other: traffic only CPU <-> port */
/* Setting bit j in register RTL838X_PORT_ISO_CTRL(i) allows
* traffic from source port i to destination port j
/* Configure ports so they are disabled by default, but once enabled
* they will work in isolated mode (only traffic between port and CPU).
*/
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));
port_bitmap |= BIT_ULL(i);
priv->ports[i].pm = BIT_ULL(priv->cpu_port);
priv->r->traffic_set(i, BIT_ULL(i));
}
}
priv->r->set_port_reg_be(port_bitmap, priv->r->port_iso_ctrl(priv->cpu_port));
priv->r->traffic_set(priv->cpu_port, BIT_ULL(priv->cpu_port));
/* For standalone ports, forward packets even if a static fdb
* entry for the source address exists on another port.
*/
if (priv->r->set_static_move_action) {
for (int i = 0; i <= priv->cpu_port; i++)
priv->r->set_static_move_action(i, true);
}
if (priv->family_id == RTL8380_FAMILY_ID)
rtl838x_print_matrix();
@ -229,7 +234,6 @@ static int rtl83xx_setup(struct dsa_switch *ds)
static int rtl93xx_setup(struct dsa_switch *ds)
{
struct rtl838x_switch_priv *priv = ds->priv;
u32 port_bitmap = BIT(priv->cpu_port);
pr_info("%s called\n", __func__);
@ -247,13 +251,16 @@ static int rtl93xx_setup(struct dsa_switch *ds)
priv->ports[i].enable = false;
priv->ports[priv->cpu_port].enable = true;
/* Configure ports so they are disabled by default, but once enabled
* they will work in isolated mode (only traffic between port and CPU).
*/
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);
priv->ports[i].pm = BIT_ULL(priv->cpu_port);
priv->r->traffic_set(i, BIT_ULL(i));
}
}
priv->r->traffic_set(priv->cpu_port, port_bitmap);
priv->r->traffic_set(priv->cpu_port, BIT_ULL(priv->cpu_port));
rtl930x_print_matrix();
@ -968,14 +975,8 @@ static int rtl83xx_mc_group_alloc(struct rtl838x_switch_priv *priv, int port)
if (mc_group >= MAX_MC_GROUPS - 1)
return -1;
if (priv->is_lagmember[port]) {
pr_info("%s: %d is lag slave. ignore\n", __func__, port);
return 0;
}
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);
portmask = BIT_ULL(port);
priv->r->write_mcast_pmask(mc_group, portmask);
return mc_group;
@ -986,10 +987,7 @@ static u64 rtl83xx_mc_group_add_port(struct rtl838x_switch_priv *priv, int mc_gr
u64 portmask = priv->r->read_mcast_pmask(mc_group);
pr_debug("%s: %d\n", __func__, port);
if (priv->is_lagmember[port]) {
pr_info("%s: %d is lag slave. ignore\n", __func__, port);
return portmask;
}
portmask |= BIT_ULL(port);
priv->r->write_mcast_pmask(mc_group, portmask);
@ -1001,41 +999,15 @@ static u64 rtl83xx_mc_group_del_port(struct rtl838x_switch_priv *priv, int mc_gr
u64 portmask = priv->r->read_mcast_pmask(mc_group);
pr_debug("%s: %d\n", __func__, port);
if (priv->is_lagmember[port]) {
pr_info("%s: %d is lag slave. ignore\n", __func__, port);
return portmask;
}
portmask &= ~BIT_ULL(port);
priv->r->write_mcast_pmask(mc_group, portmask);
if (portmask == BIT_ULL(priv->cpu_port)) {
portmask &= ~BIT_ULL(priv->cpu_port);
priv->r->write_mcast_pmask(mc_group, portmask);
if (!portmask)
clear_bit(mc_group, priv->mc_group_bm);
}
return portmask;
}
static void store_mcgroups(struct rtl838x_switch_priv *priv, int port)
{
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;
rtl83xx_mc_group_del_port(priv, mc_group, port);
}
}
}
static void load_mcgroups(struct rtl838x_switch_priv *priv, int port)
{
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;
}
}
}
static int rtl83xx_port_enable(struct dsa_switch *ds, int port,
struct phy_device *phydev)
{
@ -1054,8 +1026,6 @@ static int rtl83xx_port_enable(struct dsa_switch *ds, int port,
/* add port to switch mask of CPU_PORT */
priv->r->traffic_enable(priv->cpu_port, port);
load_mcgroups(priv, port);
if (priv->is_lagmember[port]) {
pr_debug("%s: %d is lag slave. ignore\n", __func__, port);
return 0;
@ -1091,7 +1061,6 @@ static void rtl83xx_port_disable(struct dsa_switch *ds, int port)
/* 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);
/* remove all other ports in the same bridge from switch mask of port */
v = priv->r->traffic_get(port);
@ -1193,7 +1162,6 @@ static int rtl83xx_port_bridge_join(struct dsa_switch *ds, int port,
port_bitmap |= BIT_ULL(i);
}
}
load_mcgroups(priv, port);
/* Add all other ports to this port matrix. */
if (priv->ports[port].enable) {
@ -1203,6 +1171,10 @@ static int rtl83xx_port_bridge_join(struct dsa_switch *ds, int port,
priv->r->traffic_set(port, v);
}
priv->ports[port].pm |= port_bitmap;
if (priv->r->set_static_move_action)
priv->r->set_static_move_action(port, false);
mutex_unlock(&priv->reg_mutex);
return 0;
@ -1212,7 +1184,7 @@ static void rtl83xx_port_bridge_leave(struct dsa_switch *ds, int port,
struct net_device *bridge)
{
struct rtl838x_switch_priv *priv = ds->priv;
u64 port_bitmap = BIT_ULL(priv->cpu_port), v;
u64 port_bitmap = 0, v;
pr_debug("%s %x: %d", __func__, (u32)priv, port);
mutex_lock(&priv->reg_mutex);
@ -1229,20 +1201,22 @@ static void rtl83xx_port_bridge_leave(struct dsa_switch *ds, int port,
if (priv->ports[i].enable)
priv->r->traffic_disable(i, port);
priv->ports[i].pm |= BIT_ULL(port);
port_bitmap &= ~BIT_ULL(i);
priv->ports[i].pm &= ~BIT_ULL(port);
port_bitmap |= BIT_ULL(i);
}
}
store_mcgroups(priv, port);
/* Add all other ports to this port matrix. */
/* Remove all other ports from this port matrix. */
if (priv->ports[port].enable) {
v = priv->r->traffic_get(port);
v |= port_bitmap;
v &= ~port_bitmap;
priv->r->traffic_set(port, v);
}
priv->ports[port].pm &= ~port_bitmap;
if (priv->r->set_static_move_action)
priv->r->set_static_move_action(port, true);
mutex_unlock(&priv->reg_mutex);
}
@ -1420,6 +1394,20 @@ static int rtl83xx_vlan_prepare(struct dsa_switch *ds, int port,
return 0;
}
static void rtl83xx_vlan_set_pvid(struct rtl838x_switch_priv *priv,
int port, int pvid)
{
/* Set both inner and outer PVID of the port */
priv->r->vlan_port_pvid_set(port, PBVLAN_TYPE_INNER, pvid);
priv->r->vlan_port_pvid_set(port, PBVLAN_TYPE_OUTER, pvid);
priv->r->vlan_port_pvidmode_set(port, PBVLAN_TYPE_INNER,
PBVLAN_MODE_UNTAG_AND_PRITAG);
priv->r->vlan_port_pvidmode_set(port, PBVLAN_TYPE_OUTER,
PBVLAN_MODE_UNTAG_AND_PRITAG);
priv->ports[port].pvid = pvid;
}
static int rtl83xx_vlan_add(struct dsa_switch *ds, int port,
const struct switchdev_obj_port_vlan *vlan,
struct netlink_ext_ack *extack)
@ -1442,17 +1430,10 @@ static int rtl83xx_vlan_add(struct dsa_switch *ds, int port,
mutex_lock(&priv->reg_mutex);
if (vlan->flags & BRIDGE_VLAN_INFO_PVID && vlan->vid) {
/* Set both inner and outer PVID of the 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);
priv->r->vlan_port_pvidmode_set(port, PBVLAN_TYPE_OUTER,
PBVLAN_MODE_UNTAG_AND_PRITAG);
priv->ports[port].pvid = vlan->vid;
}
if (vlan->flags & BRIDGE_VLAN_INFO_PVID)
rtl83xx_vlan_set_pvid(priv, port, vlan->vid);
else if (priv->ports[port].pvid == vlan->vid)
rtl83xx_vlan_set_pvid(priv, port, 0);
/* Get port memberships of this vlan */
priv->r->vlan_tables_read(vlan->vid, &info);
@ -1472,6 +1453,8 @@ static int rtl83xx_vlan_add(struct dsa_switch *ds, int port,
info.tagged_ports |= BIT_ULL(port);
if (vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED)
info.untagged_ports |= BIT_ULL(port);
else
info.untagged_ports &= ~BIT_ULL(port);
priv->r->vlan_set_untagged(vlan->vid, info.untagged_ports);
pr_debug("Untagged ports, VLAN %d: %llx\n", vlan->vid, info.untagged_ports);
@ -1504,12 +1487,7 @@ static int rtl83xx_vlan_del(struct dsa_switch *ds, int port,
/* Reset to default if removing the current PVID */
if (vlan->vid == pvid) {
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);
priv->r->vlan_port_pvidmode_set(port, PBVLAN_TYPE_OUTER,
PBVLAN_MODE_UNTAG_AND_PRITAG);
rtl83xx_vlan_set_pvid(priv, port, 0);
}
/* Get port memberships of this vlan */
priv->r->vlan_tables_read(vlan->vid, &info);
@ -1642,7 +1620,7 @@ static int rtl83xx_port_fdb_add(struct dsa_switch *ds, int port,
}
/* Hash buckets full, try CAM */
rtl83xx_find_l2_cam_entry(priv, seed, false, &e);
idx = rtl83xx_find_l2_cam_entry(priv, seed, false, &e);
if (idx >= 0) {
rtl83xx_setup_l2_uc_entry(&e, port, vid, mac);
@ -1680,7 +1658,7 @@ static int rtl83xx_port_fdb_del(struct dsa_switch *ds, int port,
}
/* Check CAM for spillover from hash buckets */
rtl83xx_find_l2_cam_entry(priv, seed, true, &e);
idx = rtl83xx_find_l2_cam_entry(priv, seed, true, &e);
if (idx >= 0) {
e.valid = false;
@ -1776,7 +1754,7 @@ static int rtl83xx_port_mdb_add(struct dsa_switch *ds, int port,
}
/* Hash buckets full, try CAM */
rtl83xx_find_l2_cam_entry(priv, seed, false, &e);
idx = rtl83xx_find_l2_cam_entry(priv, seed, false, &e);
if (idx >= 0) {
if (e.valid) {
@ -1839,7 +1817,7 @@ int rtl83xx_port_mdb_del(struct dsa_switch *ds, int port,
}
/* Check CAM for spillover from hash buckets */
rtl83xx_find_l2_cam_entry(priv, seed, true, &e);
idx = rtl83xx_find_l2_cam_entry(priv, seed, true, &e);
if (idx >= 0) {
portmask = rtl83xx_mc_group_del_port(priv, e.mc_portmask_index, port);

View File

@ -543,6 +543,15 @@ static void rtl838x_enable_bcast_flood(int port, bool enable)
}
static void rtl838x_set_static_move_action(int port, bool forward)
{
int shift = MV_ACT_PORT_SHIFT(port);
u32 val = forward ? MV_ACT_FORWARD : MV_ACT_DROP;
sw_w32_mask(MV_ACT_MASK << shift, val << shift,
RTL838X_L2_PORT_STATIC_MV_ACT(port));
}
static void rtl838x_stp_get(struct rtl838x_switch_priv *priv, u16 msti, u32 port_state[])
{
u32 cmd = 1 << 15 | /* Execute cmd */
@ -1717,6 +1726,7 @@ const struct rtl838x_reg rtl838x_reg = {
.enable_flood = rtl838x_enable_flood,
.enable_mcast_flood = rtl838x_enable_mcast_flood,
.enable_bcast_flood = rtl838x_enable_bcast_flood,
.set_static_move_action = rtl838x_set_static_move_action,
.stp_get = rtl838x_stp_get,
.stp_set = rtl838x_stp_set,
.mac_port_ctrl = rtl838x_mac_port_ctrl,

View File

@ -249,6 +249,19 @@
#define RTL930X_L2_PORT_NEW_SA_FWD(p) (0x8FF4 + (((p / 10) << 2)))
#define RTL931X_L2_PORT_NEW_SA_FWD(p) (0xC830 + (((p / 10) << 2)))
#define RTL838X_L2_PORT_MV_ACT(p) (0x335c + (((p >> 4) << 2)))
#define RTL839X_L2_PORT_MV_ACT(p) (0x3b80 + (((p >> 4) << 2)))
#define RTL838X_L2_PORT_STATIC_MV_ACT(p) (0x327c + (((p >> 4) << 2)))
#define RTL839X_L2_PORT_STATIC_MV_ACT(p) (0x38dc + (((p >> 4) << 2)))
#define MV_ACT_PORT_SHIFT(p) ((p % 16) * 2)
#define MV_ACT_MASK 0x3
#define MV_ACT_FORWARD 0
#define MV_ACT_DROP 1
#define MV_ACT_TRAP2CPU 2
#define MV_ACT_COPY2CPU 3
#define RTL930X_ST_CTRL (0x8798)
#define RTL930X_L2_PORT_SABLK_CTRL (0x905c)
@ -978,6 +991,7 @@ struct rtl838x_reg {
void (*enable_flood)(int port, bool enable);
void (*enable_mcast_flood)(int port, bool enable);
void (*enable_bcast_flood)(int port, bool enable);
void (*set_static_move_action)(int port, bool forward);
void (*stp_get)(struct rtl838x_switch_priv *priv, u16 msti, u32 port_state[]);
void (*stp_set)(struct rtl838x_switch_priv *priv, u16 msti, u32 port_state[]);
int (*mac_force_mode_ctrl)(int port);
@ -1068,7 +1082,6 @@ struct rtl838x_switch_priv {
struct notifier_block fib_nb;
bool eee_enabled;
unsigned long int mc_group_bm[MAX_MC_GROUPS >> 5];
int mc_group_saves[MAX_MC_GROUPS];
int n_pie_blocks;
struct rhashtable tc_ht;
unsigned long int pie_use_bm[MAX_PIE_ENTRIES >> 5];

View File

@ -590,6 +590,16 @@ static void rtl839x_enable_bcast_flood(int port, bool enable)
{
}
static void rtl839x_set_static_move_action(int port, bool forward)
{
int shift = MV_ACT_PORT_SHIFT(port);
u32 val = forward ? MV_ACT_FORWARD : MV_ACT_DROP;
sw_w32_mask(MV_ACT_MASK << shift, val << shift,
RTL839X_L2_PORT_STATIC_MV_ACT(port));
}
irqreturn_t rtl839x_switch_irq(int irq, void *dev_id)
{
struct dsa_switch *ds = dev_id;
@ -1855,6 +1865,7 @@ const struct rtl838x_reg rtl839x_reg = {
.enable_flood = rtl839x_enable_flood,
.enable_mcast_flood = rtl839x_enable_mcast_flood,
.enable_bcast_flood = rtl839x_enable_bcast_flood,
.set_static_move_action = rtl839x_set_static_move_action,
.stp_get = rtl839x_stp_get,
.stp_set = rtl839x_stp_set,
.mac_force_mode_ctrl = rtl839x_mac_force_mode_ctrl,