@@ -258,6 +258,150 @@ static void bgx_flush_dmac_cam_filter(struct bgx *bgx, int lmacid)
258
258
sizeof (u64 ), 0 );
259
259
}
260
260
261
+ static void bgx_lmac_remove_filters (struct lmac * lmac , u8 vf_id )
262
+ {
263
+ int i = 0 ;
264
+
265
+ if (!lmac )
266
+ return ;
267
+
268
+ /* We've got reset filters request from some of attached VF, while the
269
+ * others might want to keep their configuration. So in this case lets
270
+ * iterate over all of configured filters and decrease number of
271
+ * referencies. if some addresses get zero refs remove them from list
272
+ */
273
+ for (i = lmac -> dmacs_cfg - 1 ; i >= 0 ; i -- ) {
274
+ lmac -> dmacs [i ].vf_map &= ~BIT_ULL (vf_id );
275
+ if (!lmac -> dmacs [i ].vf_map ) {
276
+ lmac -> dmacs_cfg -- ;
277
+ lmac -> dmacs [i ].dmac = 0 ;
278
+ lmac -> dmacs [i ].vf_map = 0 ;
279
+ }
280
+ }
281
+ }
282
+
283
+ static int bgx_lmac_save_filter (struct lmac * lmac , u64 dmac , u8 vf_id )
284
+ {
285
+ u8 i = 0 ;
286
+
287
+ if (!lmac )
288
+ return -1 ;
289
+
290
+ /* At the same time we could have several VFs 'attached' to some
291
+ * particular LMAC, and each VF is represented as network interface
292
+ * for kernel. So from user perspective it should be possible to
293
+ * manipulate with its' (VF) receive modes. However from PF
294
+ * driver perspective we need to keep track of filter configurations
295
+ * for different VFs to prevent filter values dupes
296
+ */
297
+ for (i = 0 ; i < lmac -> dmacs_cfg ; i ++ ) {
298
+ if (lmac -> dmacs [i ].dmac == dmac ) {
299
+ lmac -> dmacs [i ].vf_map |= BIT_ULL (vf_id );
300
+ return -1 ;
301
+ }
302
+ }
303
+
304
+ if (!(lmac -> dmacs_cfg < lmac -> dmacs_count ))
305
+ return -1 ;
306
+
307
+ /* keep it for further tracking */
308
+ lmac -> dmacs [lmac -> dmacs_cfg ].dmac = dmac ;
309
+ lmac -> dmacs [lmac -> dmacs_cfg ].vf_map = BIT_ULL (vf_id );
310
+ lmac -> dmacs_cfg ++ ;
311
+ return 0 ;
312
+ }
313
+
314
+ static int bgx_set_dmac_cam_filter_mac (struct bgx * bgx , int lmacid ,
315
+ u64 cam_dmac , u8 idx )
316
+ {
317
+ struct lmac * lmac = NULL ;
318
+ u64 cfg = 0 ;
319
+
320
+ /* skip zero addresses as meaningless */
321
+ if (!cam_dmac || !bgx )
322
+ return -1 ;
323
+
324
+ lmac = & bgx -> lmac [lmacid ];
325
+
326
+ /* configure DCAM filtering for designated LMAC */
327
+ cfg = RX_DMACX_CAM_LMACID (lmacid & LMAC_ID_MASK ) |
328
+ RX_DMACX_CAM_EN | cam_dmac ;
329
+ bgx_reg_write (bgx , 0 , BGX_CMR_RX_DMACX_CAM +
330
+ ((lmacid * lmac -> dmacs_count ) + idx ) * sizeof (u64 ), cfg );
331
+ return 0 ;
332
+ }
333
+
334
+ void bgx_set_dmac_cam_filter (int node , int bgx_idx , int lmacid ,
335
+ u64 cam_dmac , u8 vf_id )
336
+ {
337
+ struct bgx * bgx = get_bgx (node , bgx_idx );
338
+ struct lmac * lmac = NULL ;
339
+
340
+ if (!bgx )
341
+ return ;
342
+
343
+ lmac = & bgx -> lmac [lmacid ];
344
+
345
+ if (!cam_dmac )
346
+ cam_dmac = ether_addr_to_u64 (lmac -> mac );
347
+
348
+ /* since we might have several VFs attached to particular LMAC
349
+ * and kernel could call mcast config for each of them with the
350
+ * same MAC, check if requested MAC is already in filtering list and
351
+ * updare/prepare list of MACs to be applied later to HW filters
352
+ */
353
+ bgx_lmac_save_filter (lmac , cam_dmac , vf_id );
354
+ }
355
+ EXPORT_SYMBOL (bgx_set_dmac_cam_filter );
356
+
357
+ void bgx_set_xcast_mode (int node , int bgx_idx , int lmacid , u8 mode )
358
+ {
359
+ struct bgx * bgx = get_bgx (node , bgx_idx );
360
+ struct lmac * lmac = NULL ;
361
+ u64 cfg = 0 ;
362
+ u8 i = 0 ;
363
+
364
+ if (!bgx )
365
+ return ;
366
+
367
+ lmac = & bgx -> lmac [lmacid ];
368
+
369
+ cfg = bgx_reg_read (bgx , lmacid , BGX_CMRX_RX_DMAC_CTL );
370
+ if (mode & BGX_XCAST_BCAST_ACCEPT )
371
+ cfg |= BCAST_ACCEPT ;
372
+ else
373
+ cfg &= ~BCAST_ACCEPT ;
374
+
375
+ /* disable all MCASTs and DMAC filtering */
376
+ cfg &= ~(CAM_ACCEPT | BGX_MCAST_MODE (MCAST_MODE_MASK ));
377
+
378
+ /* check requested bits and set filtergin mode appropriately */
379
+ if (mode & (BGX_XCAST_MCAST_ACCEPT )) {
380
+ cfg |= (BGX_MCAST_MODE (MCAST_MODE_ACCEPT ));
381
+ } else if (mode & BGX_XCAST_MCAST_FILTER ) {
382
+ cfg |= (BGX_MCAST_MODE (MCAST_MODE_CAM_FILTER ) | CAM_ACCEPT );
383
+ for (i = 0 ; i < lmac -> dmacs_cfg ; i ++ )
384
+ bgx_set_dmac_cam_filter_mac (bgx , lmacid ,
385
+ lmac -> dmacs [i ].dmac , i );
386
+ }
387
+ bgx_reg_write (bgx , lmacid , BGX_CMRX_RX_DMAC_CTL , cfg );
388
+ }
389
+ EXPORT_SYMBOL (bgx_set_xcast_mode );
390
+
391
+ void bgx_reset_xcast_mode (int node , int bgx_idx , int lmacid , u8 vf_id )
392
+ {
393
+ struct bgx * bgx = get_bgx (node , bgx_idx );
394
+
395
+ if (!bgx )
396
+ return ;
397
+
398
+ bgx_lmac_remove_filters (& bgx -> lmac [lmacid ], vf_id );
399
+ bgx_flush_dmac_cam_filter (bgx , lmacid );
400
+ bgx_set_xcast_mode (node , bgx_idx , lmacid ,
401
+ (BGX_XCAST_BCAST_ACCEPT | BGX_XCAST_MCAST_ACCEPT ));
402
+ }
403
+ EXPORT_SYMBOL (bgx_reset_xcast_mode );
404
+
261
405
void bgx_lmac_rx_tx_enable (int node , int bgx_idx , int lmacid , bool enable )
262
406
{
263
407
struct bgx * bgx = get_bgx (node , bgx_idx );
0 commit comments