Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

net: dsa: tag_ocelot: convert to tagger-owned data

The felix driver makes very light use of dp->priv, and the tagger is
effectively stateless. dp->priv is practically only needed to set up a
callback to perform deferred xmit of PTP and STP packets using the
ocelot-8021q tagging protocol (the main ocelot tagging protocol makes no
use of dp->priv, although this driver sets up dp->priv irrespective of
actual tagging protocol in use).

struct felix_port (what used to be pointed to by dp->priv) is removed
and replaced with a two-sided structure. The public side of this
structure, visible to the switch driver, is ocelot_8021q_tagger_data.
The private side is ocelot_8021q_tagger_private, and the latter
structure physically encapsulates the former. The public half of the
tagger data structure can be accessed through a helper of the same name
(ocelot_8021q_tagger_data) which also sanity-checks the protocol
currently in use by the switch. The public/private split was requested
by Andrew Lunn.

Suggested-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Vladimir Oltean and committed by
David S. Miller
35d97680 dc452a47

+94 -55
+14 -50
drivers/net/dsa/ocelot/felix.c
··· 1155 1155 kfree(xmit_work); 1156 1156 } 1157 1157 1158 - static int felix_port_setup_tagger_data(struct dsa_switch *ds, int port) 1158 + static int felix_connect_tag_protocol(struct dsa_switch *ds, 1159 + enum dsa_tag_protocol proto) 1159 1160 { 1160 - struct dsa_port *dp = dsa_to_port(ds, port); 1161 - struct ocelot *ocelot = ds->priv; 1162 - struct felix *felix = ocelot_to_felix(ocelot); 1163 - struct felix_port *felix_port; 1161 + struct ocelot_8021q_tagger_data *tagger_data; 1164 1162 1165 - if (!dsa_port_is_user(dp)) 1163 + switch (proto) { 1164 + case DSA_TAG_PROTO_OCELOT_8021Q: 1165 + tagger_data = ocelot_8021q_tagger_data(ds); 1166 + tagger_data->xmit_work_fn = felix_port_deferred_xmit; 1166 1167 return 0; 1167 - 1168 - felix_port = kzalloc(sizeof(*felix_port), GFP_KERNEL); 1169 - if (!felix_port) 1170 - return -ENOMEM; 1171 - 1172 - felix_port->xmit_worker = felix->xmit_worker; 1173 - felix_port->xmit_work_fn = felix_port_deferred_xmit; 1174 - 1175 - dp->priv = felix_port; 1176 - 1177 - return 0; 1178 - } 1179 - 1180 - static void felix_port_teardown_tagger_data(struct dsa_switch *ds, int port) 1181 - { 1182 - struct dsa_port *dp = dsa_to_port(ds, port); 1183 - struct felix_port *felix_port = dp->priv; 1184 - 1185 - if (!felix_port) 1186 - return; 1187 - 1188 - dp->priv = NULL; 1189 - kfree(felix_port); 1168 + case DSA_TAG_PROTO_OCELOT: 1169 + case DSA_TAG_PROTO_SEVILLE: 1170 + return 0; 1171 + default: 1172 + return -EPROTONOSUPPORT; 1173 + } 1190 1174 } 1191 1175 1192 1176 /* Hardware initialization done here so that we can allocate structures with ··· 1201 1217 } 1202 1218 } 1203 1219 1204 - felix->xmit_worker = kthread_create_worker(0, "felix_xmit"); 1205 - if (IS_ERR(felix->xmit_worker)) { 1206 - err = PTR_ERR(felix->xmit_worker); 1207 - goto out_deinit_timestamp; 1208 - } 1209 - 1210 1220 for (port = 0; port < ds->num_ports; port++) { 1211 1221 if (dsa_is_unused_port(ds, port)) 1212 1222 continue; ··· 1211 1233 * bits of vlan tag. 1212 1234 */ 1213 1235 felix_port_qos_map_init(ocelot, port); 1214 - 1215 - err = felix_port_setup_tagger_data(ds, port); 1216 - if (err) { 1217 - dev_err(ds->dev, 1218 - "port %d failed to set up tagger data: %pe\n", 1219 - port, ERR_PTR(err)); 1220 - goto out_deinit_ports; 1221 - } 1222 1236 } 1223 1237 1224 1238 err = ocelot_devlink_sb_register(ocelot); ··· 1238 1268 if (dsa_is_unused_port(ds, port)) 1239 1269 continue; 1240 1270 1241 - felix_port_teardown_tagger_data(ds, port); 1242 1271 ocelot_deinit_port(ocelot, port); 1243 1272 } 1244 1273 1245 - kthread_destroy_worker(felix->xmit_worker); 1246 - 1247 - out_deinit_timestamp: 1248 1274 ocelot_deinit_timestamp(ocelot); 1249 1275 ocelot_deinit(ocelot); 1250 1276 ··· 1269 1303 if (dsa_is_unused_port(ds, port)) 1270 1304 continue; 1271 1305 1272 - felix_port_teardown_tagger_data(ds, port); 1273 1306 ocelot_deinit_port(ocelot, port); 1274 1307 } 1275 - 1276 - kthread_destroy_worker(felix->xmit_worker); 1277 1308 1278 1309 ocelot_devlink_sb_unregister(ocelot); 1279 1310 ocelot_deinit_timestamp(ocelot); ··· 1611 1648 const struct dsa_switch_ops felix_switch_ops = { 1612 1649 .get_tag_protocol = felix_get_tag_protocol, 1613 1650 .change_tag_protocol = felix_change_tag_protocol, 1651 + .connect_tag_protocol = felix_connect_tag_protocol, 1614 1652 .setup = felix_setup, 1615 1653 .teardown = felix_teardown, 1616 1654 .set_ageing_time = felix_set_ageing_time,
+10 -2
include/linux/dsa/ocelot.h
··· 8 8 #include <linux/kthread.h> 9 9 #include <linux/packing.h> 10 10 #include <linux/skbuff.h> 11 + #include <net/dsa.h> 11 12 12 13 struct ocelot_skb_cb { 13 14 struct sk_buff *clone; ··· 169 168 struct kthread_work work; 170 169 }; 171 170 172 - struct felix_port { 171 + struct ocelot_8021q_tagger_data { 173 172 void (*xmit_work_fn)(struct kthread_work *work); 174 - struct kthread_worker *xmit_worker; 175 173 }; 174 + 175 + static inline struct ocelot_8021q_tagger_data * 176 + ocelot_8021q_tagger_data(struct dsa_switch *ds) 177 + { 178 + BUG_ON(ds->dst->tag_ops->proto != DSA_TAG_PROTO_OCELOT_8021Q); 179 + 180 + return ds->tagger_data; 181 + } 176 182 177 183 static inline void ocelot_xfh_get_rew_val(void *extraction, u64 *rew_val) 178 184 {
+70 -3
net/dsa/tag_ocelot_8021q.c
··· 12 12 #include <linux/dsa/ocelot.h> 13 13 #include "dsa_priv.h" 14 14 15 + struct ocelot_8021q_tagger_private { 16 + struct ocelot_8021q_tagger_data data; /* Must be first */ 17 + struct kthread_worker *xmit_worker; 18 + }; 19 + 15 20 static struct sk_buff *ocelot_defer_xmit(struct dsa_port *dp, 16 21 struct sk_buff *skb) 17 22 { 23 + struct ocelot_8021q_tagger_private *priv = dp->ds->tagger_data; 24 + struct ocelot_8021q_tagger_data *data = &priv->data; 25 + void (*xmit_work_fn)(struct kthread_work *work); 18 26 struct felix_deferred_xmit_work *xmit_work; 19 - struct felix_port *felix_port = dp->priv; 27 + struct kthread_worker *xmit_worker; 28 + 29 + xmit_work_fn = data->xmit_work_fn; 30 + xmit_worker = priv->xmit_worker; 31 + 32 + if (!xmit_work_fn || !xmit_worker) 33 + return NULL; 20 34 21 35 xmit_work = kzalloc(sizeof(*xmit_work), GFP_ATOMIC); 22 36 if (!xmit_work) 23 37 return NULL; 24 38 25 39 /* Calls felix_port_deferred_xmit in felix.c */ 26 - kthread_init_work(&xmit_work->work, felix_port->xmit_work_fn); 40 + kthread_init_work(&xmit_work->work, xmit_work_fn); 27 41 /* Increase refcount so the kfree_skb in dsa_slave_xmit 28 42 * won't really free the packet. 29 43 */ 30 44 xmit_work->dp = dp; 31 45 xmit_work->skb = skb_get(skb); 32 46 33 - kthread_queue_work(felix_port->xmit_worker, &xmit_work->work); 47 + kthread_queue_work(xmit_worker, &xmit_work->work); 34 48 35 49 return NULL; 36 50 } ··· 81 67 return skb; 82 68 } 83 69 70 + static void ocelot_disconnect(struct dsa_switch_tree *dst) 71 + { 72 + struct ocelot_8021q_tagger_private *priv; 73 + struct dsa_port *dp; 74 + 75 + list_for_each_entry(dp, &dst->ports, list) { 76 + priv = dp->ds->tagger_data; 77 + 78 + if (!priv) 79 + continue; 80 + 81 + if (priv->xmit_worker) 82 + kthread_destroy_worker(priv->xmit_worker); 83 + 84 + kfree(priv); 85 + dp->ds->tagger_data = NULL; 86 + } 87 + } 88 + 89 + static int ocelot_connect(struct dsa_switch_tree *dst) 90 + { 91 + struct ocelot_8021q_tagger_private *priv; 92 + struct dsa_port *dp; 93 + int err; 94 + 95 + list_for_each_entry(dp, &dst->ports, list) { 96 + if (dp->ds->tagger_data) 97 + continue; 98 + 99 + priv = kzalloc(sizeof(*priv), GFP_KERNEL); 100 + if (!priv) { 101 + err = -ENOMEM; 102 + goto out; 103 + } 104 + 105 + priv->xmit_worker = kthread_create_worker(0, "felix_xmit"); 106 + if (IS_ERR(priv->xmit_worker)) { 107 + err = PTR_ERR(priv->xmit_worker); 108 + goto out; 109 + } 110 + 111 + dp->ds->tagger_data = priv; 112 + } 113 + 114 + return 0; 115 + 116 + out: 117 + ocelot_disconnect(dst); 118 + return err; 119 + } 120 + 84 121 static const struct dsa_device_ops ocelot_8021q_netdev_ops = { 85 122 .name = "ocelot-8021q", 86 123 .proto = DSA_TAG_PROTO_OCELOT_8021Q, 87 124 .xmit = ocelot_xmit, 88 125 .rcv = ocelot_rcv, 126 + .connect = ocelot_connect, 127 + .disconnect = ocelot_disconnect, 89 128 .needed_headroom = VLAN_HLEN, 90 129 .promisc_on_master = true, 91 130 };