summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVivien Didelot <vivien.didelot@gmail.com>2019-08-25 13:25:15 -0400
committerDavid S. Miller <davem@davemloft.net>2019-08-27 23:17:27 -0400
commite65d45cc351ac5f1c11e6bac5669e536df753664 (patch)
treeb3dc9dd80c019aaa2b848ded18fc584f557953fc
parent68aaf4459556b1f9370c259fd486aecad2257552 (diff)
net: dsa: remove bitmap operations
The bitmap operations were introduced to simplify the switch drivers in the future, since most of them could implement the common VLAN and MDB operations (add, del, dump) with simple functions taking all target ports at once, and thus limiting the number of hardware accesses. Programming an MDB or VLAN this way in a single operation would clearly simplify the drivers a lot but would require a new get-set interface in DSA. The usage of such bitmap from the stack also raised concerned in the past, leading to the dynamic allocation of a new ds->_bitmap member in the dsa_switch structure. So let's get rid of them for now. This commit nicely wraps the ds->ops->port_{mdb,vlan}_{prepare,add} switch operations into new dsa_switch_{mdb,vlan}_{prepare,add} variants not using any bitmap argument anymore. New dsa_switch_{mdb,vlan}_match helpers have been introduced to make clear which local port of a switch must be programmed with the target object. While the targeted user port is an obvious candidate, the DSA links must also be programmed, as well as the CPU port for VLANs. While at it, also remove local variables that are only used once. Signed-off-by: Vivien Didelot <vivien.didelot@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--include/net/dsa.h3
-rw-r--r--net/dsa/dsa2.c14
-rw-r--r--net/dsa/switch.c132
3 files changed, 59 insertions, 90 deletions
diff --git a/include/net/dsa.h b/include/net/dsa.h
index 147b757ef8ea..96acb14ec1a8 100644
--- a/include/net/dsa.h
+++ b/include/net/dsa.h
@@ -275,9 +275,6 @@ struct dsa_switch {
275 */ 275 */
276 bool vlan_filtering; 276 bool vlan_filtering;
277 277
278 unsigned long *bitmap;
279 unsigned long _bitmap;
280
281 /* Dynamically allocated ports, keep last */ 278 /* Dynamically allocated ports, keep last */
282 size_t num_ports; 279 size_t num_ports;
283 struct dsa_port ports[]; 280 struct dsa_port ports[];
diff --git a/net/dsa/dsa2.c b/net/dsa/dsa2.c
index 8c4eccb0cfe6..f8445fa73448 100644
--- a/net/dsa/dsa2.c
+++ b/net/dsa/dsa2.c
@@ -834,20 +834,6 @@ struct dsa_switch *dsa_switch_alloc(struct device *dev, size_t n)
834 if (!ds) 834 if (!ds)
835 return NULL; 835 return NULL;
836 836
837 /* We avoid allocating memory outside dsa_switch
838 * if it is not needed.
839 */
840 if (n <= sizeof(ds->_bitmap) * 8) {
841 ds->bitmap = &ds->_bitmap;
842 } else {
843 ds->bitmap = devm_kcalloc(dev,
844 BITS_TO_LONGS(n),
845 sizeof(unsigned long),
846 GFP_KERNEL);
847 if (unlikely(!ds->bitmap))
848 return NULL;
849 }
850
851 ds->dev = dev; 837 ds->dev = dev;
852 ds->num_ports = n; 838 ds->num_ports = n;
853 839
diff --git a/net/dsa/switch.c b/net/dsa/switch.c
index 09d9286b27cc..489eb7b430a4 100644
--- a/net/dsa/switch.c
+++ b/net/dsa/switch.c
@@ -128,57 +128,51 @@ static int dsa_switch_fdb_del(struct dsa_switch *ds,
128 return ds->ops->port_fdb_del(ds, port, info->addr, info->vid); 128 return ds->ops->port_fdb_del(ds, port, info->addr, info->vid);
129} 129}
130 130
131static int 131static bool dsa_switch_mdb_match(struct dsa_switch *ds, int port,
132dsa_switch_mdb_prepare_bitmap(struct dsa_switch *ds, 132 struct dsa_notifier_mdb_info *info)
133 const struct switchdev_obj_port_mdb *mdb, 133{
134 const unsigned long *bitmap) 134 if (ds->index == info->sw_index && port == info->port)
135 return true;
136
137 if (dsa_is_dsa_port(ds, port))
138 return true;
139
140 return false;
141}
142
143static int dsa_switch_mdb_prepare(struct dsa_switch *ds,
144 struct dsa_notifier_mdb_info *info)
135{ 145{
136 int port, err; 146 int port, err;
137 147
138 if (!ds->ops->port_mdb_prepare || !ds->ops->port_mdb_add) 148 if (!ds->ops->port_mdb_prepare || !ds->ops->port_mdb_add)
139 return -EOPNOTSUPP; 149 return -EOPNOTSUPP;
140 150
141 for_each_set_bit(port, bitmap, ds->num_ports) { 151 for (port = 0; port < ds->num_ports; port++) {
142 err = ds->ops->port_mdb_prepare(ds, port, mdb); 152 if (dsa_switch_mdb_match(ds, port, info)) {
143 if (err) 153 err = ds->ops->port_mdb_prepare(ds, port, info->mdb);
144 return err; 154 if (err)
155 return err;
156 }
145 } 157 }
146 158
147 return 0; 159 return 0;
148} 160}
149 161
150static void dsa_switch_mdb_add_bitmap(struct dsa_switch *ds,
151 const struct switchdev_obj_port_mdb *mdb,
152 const unsigned long *bitmap)
153{
154 int port;
155
156 if (!ds->ops->port_mdb_add)
157 return;
158
159 for_each_set_bit(port, bitmap, ds->num_ports)
160 ds->ops->port_mdb_add(ds, port, mdb);
161}
162
163static int dsa_switch_mdb_add(struct dsa_switch *ds, 162static int dsa_switch_mdb_add(struct dsa_switch *ds,
164 struct dsa_notifier_mdb_info *info) 163 struct dsa_notifier_mdb_info *info)
165{ 164{
166 const struct switchdev_obj_port_mdb *mdb = info->mdb;
167 struct switchdev_trans *trans = info->trans;
168 int port; 165 int port;
169 166
170 /* Build a mask of Multicast group members */ 167 if (switchdev_trans_ph_prepare(info->trans))
171 bitmap_zero(ds->bitmap, ds->num_ports); 168 return dsa_switch_mdb_prepare(ds, info);
172 if (ds->index == info->sw_index)
173 set_bit(info->port, ds->bitmap);
174 for (port = 0; port < ds->num_ports; port++)
175 if (dsa_is_dsa_port(ds, port))
176 set_bit(port, ds->bitmap);
177 169
178 if (switchdev_trans_ph_prepare(trans)) 170 if (!ds->ops->port_mdb_add)
179 return dsa_switch_mdb_prepare_bitmap(ds, mdb, ds->bitmap); 171 return 0;
180 172
181 dsa_switch_mdb_add_bitmap(ds, mdb, ds->bitmap); 173 for (port = 0; port < ds->num_ports; port++)
174 if (dsa_switch_mdb_match(ds, port, info))
175 ds->ops->port_mdb_add(ds, port, info->mdb);
182 176
183 return 0; 177 return 0;
184} 178}
@@ -186,13 +180,11 @@ static int dsa_switch_mdb_add(struct dsa_switch *ds,
186static int dsa_switch_mdb_del(struct dsa_switch *ds, 180static int dsa_switch_mdb_del(struct dsa_switch *ds,
187 struct dsa_notifier_mdb_info *info) 181 struct dsa_notifier_mdb_info *info)
188{ 182{
189 const struct switchdev_obj_port_mdb *mdb = info->mdb;
190
191 if (!ds->ops->port_mdb_del) 183 if (!ds->ops->port_mdb_del)
192 return -EOPNOTSUPP; 184 return -EOPNOTSUPP;
193 185
194 if (ds->index == info->sw_index) 186 if (ds->index == info->sw_index)
195 return ds->ops->port_mdb_del(ds, info->port, mdb); 187 return ds->ops->port_mdb_del(ds, info->port, info->mdb);
196 188
197 return 0; 189 return 0;
198} 190}
@@ -234,59 +226,55 @@ static int dsa_port_vlan_check(struct dsa_switch *ds, int port,
234 (void *)vlan); 226 (void *)vlan);
235} 227}
236 228
237static int 229static bool dsa_switch_vlan_match(struct dsa_switch *ds, int port,
238dsa_switch_vlan_prepare_bitmap(struct dsa_switch *ds, 230 struct dsa_notifier_vlan_info *info)
239 const struct switchdev_obj_port_vlan *vlan, 231{
240 const unsigned long *bitmap) 232 if (ds->index == info->sw_index && port == info->port)
233 return true;
234
235 if (dsa_is_cpu_port(ds, port) || dsa_is_dsa_port(ds, port))
236 return true;
237
238 return false;
239}
240
241static int dsa_switch_vlan_prepare(struct dsa_switch *ds,
242 struct dsa_notifier_vlan_info *info)
241{ 243{
242 int port, err; 244 int port, err;
243 245
244 if (!ds->ops->port_vlan_prepare || !ds->ops->port_vlan_add) 246 if (!ds->ops->port_vlan_prepare || !ds->ops->port_vlan_add)
245 return -EOPNOTSUPP; 247 return -EOPNOTSUPP;
246 248
247 for_each_set_bit(port, bitmap, ds->num_ports) { 249 for (port = 0; port < ds->num_ports; port++) {
248 err = dsa_port_vlan_check(ds, port, vlan); 250 if (dsa_switch_vlan_match(ds, port, info)) {
249 if (err) 251 err = dsa_port_vlan_check(ds, port, info->vlan);
250 return err; 252 if (err)
253 return err;
251 254
252 err = ds->ops->port_vlan_prepare(ds, port, vlan); 255 err = ds->ops->port_vlan_prepare(ds, port, info->vlan);
253 if (err) 256 if (err)
254 return err; 257 return err;
258 }
255 } 259 }
256 260
257 return 0; 261 return 0;
258} 262}
259 263
260static void
261dsa_switch_vlan_add_bitmap(struct dsa_switch *ds,
262 const struct switchdev_obj_port_vlan *vlan,
263 const unsigned long *bitmap)
264{
265 int port;
266
267 for_each_set_bit(port, bitmap, ds->num_ports)
268 ds->ops->port_vlan_add(ds, port, vlan);
269}
270
271static int dsa_switch_vlan_add(struct dsa_switch *ds, 264static int dsa_switch_vlan_add(struct dsa_switch *ds,
272 struct dsa_notifier_vlan_info *info) 265 struct dsa_notifier_vlan_info *info)
273{ 266{
274 const struct switchdev_obj_port_vlan *vlan = info->vlan;
275 struct switchdev_trans *trans = info->trans;
276 int port; 267 int port;
277 268
278 /* Build a mask of VLAN members */ 269 if (switchdev_trans_ph_prepare(info->trans))
279 bitmap_zero(ds->bitmap, ds->num_ports); 270 return dsa_switch_vlan_prepare(ds, info);
280 if (ds->index == info->sw_index)
281 set_bit(info->port, ds->bitmap);
282 for (port = 0; port < ds->num_ports; port++)
283 if (dsa_is_cpu_port(ds, port) || dsa_is_dsa_port(ds, port))
284 set_bit(port, ds->bitmap);
285 271
286 if (switchdev_trans_ph_prepare(trans)) 272 if (!ds->ops->port_vlan_add)
287 return dsa_switch_vlan_prepare_bitmap(ds, vlan, ds->bitmap); 273 return 0;
288 274
289 dsa_switch_vlan_add_bitmap(ds, vlan, ds->bitmap); 275 for (port = 0; port < ds->num_ports; port++)
276 if (dsa_switch_vlan_match(ds, port, info))
277 ds->ops->port_vlan_add(ds, port, info->vlan);
290 278
291 return 0; 279 return 0;
292} 280}
@@ -294,13 +282,11 @@ static int dsa_switch_vlan_add(struct dsa_switch *ds,
294static int dsa_switch_vlan_del(struct dsa_switch *ds, 282static int dsa_switch_vlan_del(struct dsa_switch *ds,
295 struct dsa_notifier_vlan_info *info) 283 struct dsa_notifier_vlan_info *info)
296{ 284{
297 const struct switchdev_obj_port_vlan *vlan = info->vlan;
298
299 if (!ds->ops->port_vlan_del) 285 if (!ds->ops->port_vlan_del)
300 return -EOPNOTSUPP; 286 return -EOPNOTSUPP;
301 287
302 if (ds->index == info->sw_index) 288 if (ds->index == info->sw_index)
303 return ds->ops->port_vlan_del(ds, info->port, vlan); 289 return ds->ops->port_vlan_del(ds, info->port, info->vlan);
304 290
305 return 0; 291 return 0;
306} 292}