Skip to content

Commit c4f3341

Browse files
committed
Merge branch 'DSA-tag_8021q-cleanup'
Vladimir Oltean says: ==================== DSA tag_8021q cleanup This small series tries to consolidate the VLAN handling in DSA a little bit. It reworks tag_8021q to be minimally invasive to the dsa_switch_ops structure. This makes the rest of the code a bit easier to follow. ==================== Signed-off-by: David S. Miller <[email protected]>
2 parents a8c16e8 + 8823659 commit c4f3341

File tree

7 files changed

+265
-220
lines changed

7 files changed

+265
-220
lines changed

drivers/net/dsa/sja1105/sja1105.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -210,14 +210,13 @@ struct sja1105_private {
210210
struct dsa_switch *ds;
211211
struct list_head dsa_8021q_vlans;
212212
struct list_head bridge_vlans;
213-
struct list_head crosschip_links;
214213
struct sja1105_flow_block flow_block;
215214
struct sja1105_port ports[SJA1105_NUM_PORTS];
216215
/* Serializes transmission of management frames so that
217216
* the switch doesn't confuse them with one another.
218217
*/
219218
struct mutex mgmt_lock;
220-
bool expect_dsa_8021q;
219+
struct dsa_8021q_context *dsa_8021q_ctx;
221220
enum sja1105_vlan_state vlan_state;
222221
struct sja1105_cbs_entry *cbs;
223222
struct sja1105_tagger_data tagger_data;

drivers/net/dsa/sja1105/sja1105_main.c

Lines changed: 128 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -1880,19 +1880,17 @@ static int sja1105_crosschip_bridge_join(struct dsa_switch *ds,
18801880
if (dsa_to_port(ds, port)->bridge_dev != br)
18811881
continue;
18821882

1883-
other_priv->expect_dsa_8021q = true;
1884-
rc = dsa_8021q_crosschip_bridge_join(ds, port, other_ds,
1885-
other_port,
1886-
&priv->crosschip_links);
1887-
other_priv->expect_dsa_8021q = false;
1883+
rc = dsa_8021q_crosschip_bridge_join(priv->dsa_8021q_ctx,
1884+
port,
1885+
other_priv->dsa_8021q_ctx,
1886+
other_port);
18881887
if (rc)
18891888
return rc;
18901889

1891-
priv->expect_dsa_8021q = true;
1892-
rc = dsa_8021q_crosschip_bridge_join(other_ds, other_port, ds,
1893-
port,
1894-
&other_priv->crosschip_links);
1895-
priv->expect_dsa_8021q = false;
1890+
rc = dsa_8021q_crosschip_bridge_join(other_priv->dsa_8021q_ctx,
1891+
other_port,
1892+
priv->dsa_8021q_ctx,
1893+
port);
18961894
if (rc)
18971895
return rc;
18981896
}
@@ -1919,33 +1917,24 @@ static void sja1105_crosschip_bridge_leave(struct dsa_switch *ds,
19191917
if (dsa_to_port(ds, port)->bridge_dev != br)
19201918
continue;
19211919

1922-
other_priv->expect_dsa_8021q = true;
1923-
dsa_8021q_crosschip_bridge_leave(ds, port, other_ds, other_port,
1924-
&priv->crosschip_links);
1925-
other_priv->expect_dsa_8021q = false;
1920+
dsa_8021q_crosschip_bridge_leave(priv->dsa_8021q_ctx, port,
1921+
other_priv->dsa_8021q_ctx,
1922+
other_port);
19261923

1927-
priv->expect_dsa_8021q = true;
1928-
dsa_8021q_crosschip_bridge_leave(other_ds, other_port, ds, port,
1929-
&other_priv->crosschip_links);
1930-
priv->expect_dsa_8021q = false;
1924+
dsa_8021q_crosschip_bridge_leave(other_priv->dsa_8021q_ctx,
1925+
other_port,
1926+
priv->dsa_8021q_ctx, port);
19311927
}
19321928
}
19331929

19341930
static int sja1105_setup_8021q_tagging(struct dsa_switch *ds, bool enabled)
19351931
{
19361932
struct sja1105_private *priv = ds->priv;
1937-
int rc, i;
1933+
int rc;
19381934

1939-
for (i = 0; i < SJA1105_NUM_PORTS; i++) {
1940-
priv->expect_dsa_8021q = true;
1941-
rc = dsa_port_setup_8021q_tagging(ds, i, enabled);
1942-
priv->expect_dsa_8021q = false;
1943-
if (rc < 0) {
1944-
dev_err(ds->dev, "Failed to setup VLAN tagging for port %d: %d\n",
1945-
i, rc);
1946-
return rc;
1947-
}
1948-
}
1935+
rc = dsa_8021q_setup(priv->dsa_8021q_ctx, enabled);
1936+
if (rc)
1937+
return rc;
19491938

19501939
dev_info(ds->dev, "%s switch tagging\n",
19511940
enabled ? "Enabled" : "Disabled");
@@ -2149,12 +2138,12 @@ struct sja1105_crosschip_vlan {
21492138
bool untagged;
21502139
int port;
21512140
int other_port;
2152-
struct dsa_switch *other_ds;
2141+
struct dsa_8021q_context *other_ctx;
21532142
};
21542143

21552144
struct sja1105_crosschip_switch {
21562145
struct list_head list;
2157-
struct dsa_switch *other_ds;
2146+
struct dsa_8021q_context *other_ctx;
21582147
};
21592148

21602149
static int sja1105_commit_pvid(struct sja1105_private *priv)
@@ -2330,8 +2319,8 @@ sja1105_build_crosschip_subvlans(struct sja1105_private *priv,
23302319

23312320
INIT_LIST_HEAD(&crosschip_vlans);
23322321

2333-
list_for_each_entry(c, &priv->crosschip_links, list) {
2334-
struct sja1105_private *other_priv = c->other_ds->priv;
2322+
list_for_each_entry(c, &priv->dsa_8021q_ctx->crosschip_links, list) {
2323+
struct sja1105_private *other_priv = c->other_ctx->ds->priv;
23352324

23362325
if (other_priv->vlan_state == SJA1105_VLAN_FILTERING_FULL)
23372326
continue;
@@ -2341,7 +2330,7 @@ sja1105_build_crosschip_subvlans(struct sja1105_private *priv,
23412330
*/
23422331
if (!dsa_is_user_port(priv->ds, c->port))
23432332
continue;
2344-
if (!dsa_is_user_port(c->other_ds, c->other_port))
2333+
if (!dsa_is_user_port(c->other_ctx->ds, c->other_port))
23452334
continue;
23462335

23472336
/* Search for VLANs on the remote port */
@@ -2376,7 +2365,7 @@ sja1105_build_crosschip_subvlans(struct sja1105_private *priv,
23762365
tmp->untagged == v->untagged &&
23772366
tmp->port == c->port &&
23782367
tmp->other_port == v->port &&
2379-
tmp->other_ds == c->other_ds) {
2368+
tmp->other_ctx == c->other_ctx) {
23802369
already_added = true;
23812370
break;
23822371
}
@@ -2394,14 +2383,14 @@ sja1105_build_crosschip_subvlans(struct sja1105_private *priv,
23942383
tmp->vid = v->vid;
23952384
tmp->port = c->port;
23962385
tmp->other_port = v->port;
2397-
tmp->other_ds = c->other_ds;
2386+
tmp->other_ctx = c->other_ctx;
23982387
tmp->untagged = v->untagged;
23992388
list_add(&tmp->list, &crosschip_vlans);
24002389
}
24012390
}
24022391

24032392
list_for_each_entry(tmp, &crosschip_vlans, list) {
2404-
struct sja1105_private *other_priv = tmp->other_ds->priv;
2393+
struct sja1105_private *other_priv = tmp->other_ctx->ds->priv;
24052394
int upstream = dsa_upstream_port(priv->ds, tmp->port);
24062395
int match, subvlan;
24072396
u16 rx_vid;
@@ -2418,7 +2407,7 @@ sja1105_build_crosschip_subvlans(struct sja1105_private *priv,
24182407
goto out;
24192408
}
24202409

2421-
rx_vid = dsa_8021q_rx_vid_subvlan(tmp->other_ds,
2410+
rx_vid = dsa_8021q_rx_vid_subvlan(tmp->other_ctx->ds,
24222411
tmp->other_port,
24232412
subvlan);
24242413

@@ -2493,11 +2482,11 @@ static int sja1105_notify_crosschip_switches(struct sja1105_private *priv)
24932482

24942483
INIT_LIST_HEAD(&crosschip_switches);
24952484

2496-
list_for_each_entry(c, &priv->crosschip_links, list) {
2485+
list_for_each_entry(c, &priv->dsa_8021q_ctx->crosschip_links, list) {
24972486
bool already_added = false;
24982487

24992488
list_for_each_entry(s, &crosschip_switches, list) {
2500-
if (s->other_ds == c->other_ds) {
2489+
if (s->other_ctx == c->other_ctx) {
25012490
already_added = true;
25022491
break;
25032492
}
@@ -2512,12 +2501,12 @@ static int sja1105_notify_crosschip_switches(struct sja1105_private *priv)
25122501
rc = -ENOMEM;
25132502
goto out;
25142503
}
2515-
s->other_ds = c->other_ds;
2504+
s->other_ctx = c->other_ctx;
25162505
list_add(&s->list, &crosschip_switches);
25172506
}
25182507

25192508
list_for_each_entry(s, &crosschip_switches, list) {
2520-
struct sja1105_private *other_priv = s->other_ds->priv;
2509+
struct sja1105_private *other_priv = s->other_ctx->ds->priv;
25212510

25222511
rc = sja1105_build_vlan_table(other_priv, false);
25232512
if (rc)
@@ -2618,16 +2607,6 @@ static int sja1105_build_vlan_table(struct sja1105_private *priv, bool notify)
26182607
return rc;
26192608
}
26202609

2621-
/* Select the list to which we should add this VLAN. */
2622-
static struct list_head *sja1105_classify_vlan(struct sja1105_private *priv,
2623-
u16 vid)
2624-
{
2625-
if (priv->expect_dsa_8021q)
2626-
return &priv->dsa_8021q_vlans;
2627-
2628-
return &priv->bridge_vlans;
2629-
}
2630-
26312610
static int sja1105_vlan_prepare(struct dsa_switch *ds, int port,
26322611
const struct switchdev_obj_port_vlan *vlan)
26332612
{
@@ -2642,7 +2621,7 @@ static int sja1105_vlan_prepare(struct dsa_switch *ds, int port,
26422621
* configuration done by dsa_8021q.
26432622
*/
26442623
for (vid = vlan->vid_begin; vid <= vlan->vid_end; vid++) {
2645-
if (!priv->expect_dsa_8021q && vid_is_dsa_8021q(vid)) {
2624+
if (vid_is_dsa_8021q(vid)) {
26462625
dev_err(ds->dev, "Range 1024-3071 reserved for dsa_8021q operation\n");
26472626
return -EBUSY;
26482627
}
@@ -2762,6 +2741,54 @@ static int sja1105_vlan_filtering(struct dsa_switch *ds, int port, bool enabled)
27622741
return sja1105_setup_8021q_tagging(ds, want_tagging);
27632742
}
27642743

2744+
/* Returns number of VLANs added (0 or 1) on success,
2745+
* or a negative error code.
2746+
*/
2747+
static int sja1105_vlan_add_one(struct dsa_switch *ds, int port, u16 vid,
2748+
u16 flags, struct list_head *vlan_list)
2749+
{
2750+
bool untagged = flags & BRIDGE_VLAN_INFO_UNTAGGED;
2751+
bool pvid = flags & BRIDGE_VLAN_INFO_PVID;
2752+
struct sja1105_bridge_vlan *v;
2753+
2754+
list_for_each_entry(v, vlan_list, list)
2755+
if (v->port == port && v->vid == vid &&
2756+
v->untagged == untagged && v->pvid == pvid)
2757+
/* Already added */
2758+
return 0;
2759+
2760+
v = kzalloc(sizeof(*v), GFP_KERNEL);
2761+
if (!v) {
2762+
dev_err(ds->dev, "Out of memory while storing VLAN\n");
2763+
return -ENOMEM;
2764+
}
2765+
2766+
v->port = port;
2767+
v->vid = vid;
2768+
v->untagged = untagged;
2769+
v->pvid = pvid;
2770+
list_add(&v->list, vlan_list);
2771+
2772+
return 1;
2773+
}
2774+
2775+
/* Returns number of VLANs deleted (0 or 1) */
2776+
static int sja1105_vlan_del_one(struct dsa_switch *ds, int port, u16 vid,
2777+
struct list_head *vlan_list)
2778+
{
2779+
struct sja1105_bridge_vlan *v, *n;
2780+
2781+
list_for_each_entry_safe(v, n, vlan_list, list) {
2782+
if (v->port == port && v->vid == vid) {
2783+
list_del(&v->list);
2784+
kfree(v);
2785+
return 1;
2786+
}
2787+
}
2788+
2789+
return 0;
2790+
}
2791+
27652792
static void sja1105_vlan_add(struct dsa_switch *ds, int port,
27662793
const struct switchdev_obj_port_vlan *vlan)
27672794
{
@@ -2771,38 +2798,12 @@ static void sja1105_vlan_add(struct dsa_switch *ds, int port,
27712798
int rc;
27722799

27732800
for (vid = vlan->vid_begin; vid <= vlan->vid_end; vid++) {
2774-
bool untagged = vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED;
2775-
bool pvid = vlan->flags & BRIDGE_VLAN_INFO_PVID;
2776-
struct sja1105_bridge_vlan *v;
2777-
struct list_head *vlan_list;
2778-
bool already_added = false;
2779-
2780-
vlan_list = sja1105_classify_vlan(priv, vid);
2781-
2782-
list_for_each_entry(v, vlan_list, list) {
2783-
if (v->port == port && v->vid == vid &&
2784-
v->untagged == untagged && v->pvid == pvid) {
2785-
already_added = true;
2786-
break;
2787-
}
2788-
}
2789-
2790-
if (already_added)
2791-
continue;
2792-
2793-
v = kzalloc(sizeof(*v), GFP_KERNEL);
2794-
if (!v) {
2795-
dev_err(ds->dev, "Out of memory while storing VLAN\n");
2801+
rc = sja1105_vlan_add_one(ds, port, vid, vlan->flags,
2802+
&priv->bridge_vlans);
2803+
if (rc < 0)
27962804
return;
2797-
}
2798-
2799-
v->port = port;
2800-
v->vid = vid;
2801-
v->untagged = untagged;
2802-
v->pvid = pvid;
2803-
list_add(&v->list, vlan_list);
2804-
2805-
vlan_table_changed = true;
2805+
if (rc > 0)
2806+
vlan_table_changed = true;
28062807
}
28072808

28082809
if (!vlan_table_changed)
@@ -2819,21 +2820,12 @@ static int sja1105_vlan_del(struct dsa_switch *ds, int port,
28192820
struct sja1105_private *priv = ds->priv;
28202821
bool vlan_table_changed = false;
28212822
u16 vid;
2823+
int rc;
28222824

28232825
for (vid = vlan->vid_begin; vid <= vlan->vid_end; vid++) {
2824-
struct sja1105_bridge_vlan *v, *n;
2825-
struct list_head *vlan_list;
2826-
2827-
vlan_list = sja1105_classify_vlan(priv, vid);
2828-
2829-
list_for_each_entry_safe(v, n, vlan_list, list) {
2830-
if (v->port == port && v->vid == vid) {
2831-
list_del(&v->list);
2832-
kfree(v);
2833-
vlan_table_changed = true;
2834-
break;
2835-
}
2836-
}
2826+
rc = sja1105_vlan_del_one(ds, port, vid, &priv->bridge_vlans);
2827+
if (rc > 0)
2828+
vlan_table_changed = true;
28372829
}
28382830

28392831
if (!vlan_table_changed)
@@ -2842,6 +2834,36 @@ static int sja1105_vlan_del(struct dsa_switch *ds, int port,
28422834
return sja1105_build_vlan_table(priv, true);
28432835
}
28442836

2837+
static int sja1105_dsa_8021q_vlan_add(struct dsa_switch *ds, int port, u16 vid,
2838+
u16 flags)
2839+
{
2840+
struct sja1105_private *priv = ds->priv;
2841+
int rc;
2842+
2843+
rc = sja1105_vlan_add_one(ds, port, vid, flags, &priv->dsa_8021q_vlans);
2844+
if (rc <= 0)
2845+
return rc;
2846+
2847+
return sja1105_build_vlan_table(priv, true);
2848+
}
2849+
2850+
static int sja1105_dsa_8021q_vlan_del(struct dsa_switch *ds, int port, u16 vid)
2851+
{
2852+
struct sja1105_private *priv = ds->priv;
2853+
int rc;
2854+
2855+
rc = sja1105_vlan_del_one(ds, port, vid, &priv->dsa_8021q_vlans);
2856+
if (!rc)
2857+
return 0;
2858+
2859+
return sja1105_build_vlan_table(priv, true);
2860+
}
2861+
2862+
static const struct dsa_8021q_ops sja1105_dsa_8021q_ops = {
2863+
.vlan_add = sja1105_dsa_8021q_vlan_add,
2864+
.vlan_del = sja1105_dsa_8021q_vlan_del,
2865+
};
2866+
28452867
static int sja1105_best_effort_vlan_filtering_get(struct sja1105_private *priv,
28462868
bool *be_vlan)
28472869
{
@@ -3504,7 +3526,15 @@ static int sja1105_probe(struct spi_device *spi)
35043526
mutex_init(&priv->ptp_data.lock);
35053527
mutex_init(&priv->mgmt_lock);
35063528

3507-
INIT_LIST_HEAD(&priv->crosschip_links);
3529+
priv->dsa_8021q_ctx = devm_kzalloc(dev, sizeof(*priv->dsa_8021q_ctx),
3530+
GFP_KERNEL);
3531+
if (!priv->dsa_8021q_ctx)
3532+
return -ENOMEM;
3533+
3534+
priv->dsa_8021q_ctx->ops = &sja1105_dsa_8021q_ops;
3535+
priv->dsa_8021q_ctx->ds = ds;
3536+
3537+
INIT_LIST_HEAD(&priv->dsa_8021q_ctx->crosschip_links);
35083538
INIT_LIST_HEAD(&priv->bridge_vlans);
35093539
INIT_LIST_HEAD(&priv->dsa_8021q_vlans);
35103540

0 commit comments

Comments
 (0)