Merge Official Source
Signed-off-by: Tianling Shen <cnsztl@immortalwrt.org>
This commit is contained in:
commit
6ac5642117
@ -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);
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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];
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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];
|
||||
|
||||
@ -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,
|
||||
|
||||
Loading…
Reference in New Issue
Block a user