@@ -86,6 +86,22 @@ bool is_lmac_valid(struct cgx *cgx, int lmac_id)
8686 return test_bit (lmac_id , & cgx -> lmac_bmap );
8787}
8888
89+ /* Helper function to get sequential index
90+ * given the enabled LMAC of a CGX
91+ */
92+ static int get_sequence_id_of_lmac (struct cgx * cgx , int lmac_id )
93+ {
94+ int tmp , id = 0 ;
95+
96+ for_each_set_bit (tmp , & cgx -> lmac_bmap , MAX_LMAC_PER_CGX ) {
97+ if (tmp == lmac_id )
98+ break ;
99+ id ++ ;
100+ }
101+
102+ return id ;
103+ }
104+
89105struct mac_ops * get_mac_ops (void * cgxd )
90106{
91107 if (!cgxd )
@@ -211,37 +227,257 @@ static u64 mac2u64 (u8 *mac_addr)
211227 return mac ;
212228}
213229
230+ static void cfg2mac (u64 cfg , u8 * mac_addr )
231+ {
232+ int i , index = 0 ;
233+
234+ for (i = ETH_ALEN - 1 ; i >= 0 ; i -- , index ++ )
235+ mac_addr [i ] = (cfg >> (8 * index )) & 0xFF ;
236+ }
237+
214238int cgx_lmac_addr_set (u8 cgx_id , u8 lmac_id , u8 * mac_addr )
215239{
216240 struct cgx * cgx_dev = cgx_get_pdata (cgx_id );
241+ struct lmac * lmac = lmac_pdata (lmac_id , cgx_dev );
217242 struct mac_ops * mac_ops ;
243+ int index , id ;
218244 u64 cfg ;
219245
246+ /* access mac_ops to know csr_offset */
220247 mac_ops = cgx_dev -> mac_ops ;
248+
221249 /* copy 6bytes from macaddr */
222250 /* memcpy(&cfg, mac_addr, 6); */
223251
224252 cfg = mac2u64 (mac_addr );
225253
226- cgx_write (cgx_dev , 0 , (CGXX_CMRX_RX_DMAC_CAM0 + (lmac_id * 0x8 )),
254+ id = get_sequence_id_of_lmac (cgx_dev , lmac_id );
255+
256+ index = id * lmac -> mac_to_index_bmap .max ;
257+
258+ cgx_write (cgx_dev , 0 , (CGXX_CMRX_RX_DMAC_CAM0 + (index * 0x8 )),
227259 cfg | CGX_DMAC_CAM_ADDR_ENABLE | ((u64 )lmac_id << 49 ));
228260
229261 cfg = cgx_read (cgx_dev , lmac_id , CGXX_CMRX_RX_DMAC_CTL0 );
230- cfg |= CGX_DMAC_CTL0_CAM_ENABLE ;
262+ cfg |= (CGX_DMAC_CTL0_CAM_ENABLE | CGX_DMAC_BCAST_MODE |
263+ CGX_DMAC_MCAST_MODE );
231264 cgx_write (cgx_dev , lmac_id , CGXX_CMRX_RX_DMAC_CTL0 , cfg );
232265
233266 return 0 ;
234267}
235268
269+ u64 cgx_read_dmac_ctrl (void * cgxd , int lmac_id )
270+ {
271+ struct mac_ops * mac_ops ;
272+ struct cgx * cgx = cgxd ;
273+
274+ if (!cgxd || !is_lmac_valid (cgxd , lmac_id ))
275+ return 0 ;
276+
277+ cgx = cgxd ;
278+ /* Get mac_ops to know csr offset */
279+ mac_ops = cgx -> mac_ops ;
280+
281+ return cgx_read (cgxd , lmac_id , CGXX_CMRX_RX_DMAC_CTL0 );
282+ }
283+
284+ u64 cgx_read_dmac_entry (void * cgxd , int index )
285+ {
286+ struct mac_ops * mac_ops ;
287+ struct cgx * cgx ;
288+
289+ if (!cgxd )
290+ return 0 ;
291+
292+ cgx = cgxd ;
293+ mac_ops = cgx -> mac_ops ;
294+ return cgx_read (cgx , 0 , (CGXX_CMRX_RX_DMAC_CAM0 + (index * 8 )));
295+ }
296+
297+ int cgx_lmac_addr_add (u8 cgx_id , u8 lmac_id , u8 * mac_addr )
298+ {
299+ struct cgx * cgx_dev = cgx_get_pdata (cgx_id );
300+ struct lmac * lmac = lmac_pdata (lmac_id , cgx_dev );
301+ struct mac_ops * mac_ops ;
302+ int index , idx ;
303+ u64 cfg = 0 ;
304+ int id ;
305+
306+ if (!lmac )
307+ return - ENODEV ;
308+
309+ mac_ops = cgx_dev -> mac_ops ;
310+ /* Get available index where entry is to be installed */
311+ idx = rvu_alloc_rsrc (& lmac -> mac_to_index_bmap );
312+ if (idx < 0 )
313+ return idx ;
314+
315+ id = get_sequence_id_of_lmac (cgx_dev , lmac_id );
316+
317+ index = id * lmac -> mac_to_index_bmap .max + idx ;
318+
319+ cfg = mac2u64 (mac_addr );
320+ cfg |= CGX_DMAC_CAM_ADDR_ENABLE ;
321+ cfg |= ((u64 )lmac_id << 49 );
322+ cgx_write (cgx_dev , 0 , (CGXX_CMRX_RX_DMAC_CAM0 + (index * 0x8 )), cfg );
323+
324+ cfg = cgx_read (cgx_dev , lmac_id , CGXX_CMRX_RX_DMAC_CTL0 );
325+ cfg |= (CGX_DMAC_BCAST_MODE | CGX_DMAC_CAM_ACCEPT );
326+
327+ if (is_multicast_ether_addr (mac_addr )) {
328+ cfg &= ~GENMASK_ULL (2 , 1 );
329+ cfg |= CGX_DMAC_MCAST_MODE_CAM ;
330+ lmac -> mcast_filters_count ++ ;
331+ } else if (!lmac -> mcast_filters_count ) {
332+ cfg |= CGX_DMAC_MCAST_MODE ;
333+ }
334+
335+ cgx_write (cgx_dev , lmac_id , CGXX_CMRX_RX_DMAC_CTL0 , cfg );
336+
337+ return idx ;
338+ }
339+
340+ int cgx_lmac_addr_reset (u8 cgx_id , u8 lmac_id )
341+ {
342+ struct cgx * cgx_dev = cgx_get_pdata (cgx_id );
343+ struct lmac * lmac = lmac_pdata (lmac_id , cgx_dev );
344+ struct mac_ops * mac_ops ;
345+ u8 index = 0 , id ;
346+ u64 cfg ;
347+
348+ if (!lmac )
349+ return - ENODEV ;
350+
351+ mac_ops = cgx_dev -> mac_ops ;
352+ /* Restore index 0 to its default init value as done during
353+ * cgx_lmac_init
354+ */
355+ set_bit (0 , lmac -> mac_to_index_bmap .bmap );
356+
357+ id = get_sequence_id_of_lmac (cgx_dev , lmac_id );
358+
359+ index = id * lmac -> mac_to_index_bmap .max + index ;
360+ cgx_write (cgx_dev , 0 , (CGXX_CMRX_RX_DMAC_CAM0 + (index * 0x8 )), 0 );
361+
362+ /* Reset CGXX_CMRX_RX_DMAC_CTL0 register to default state */
363+ cfg = cgx_read (cgx_dev , lmac_id , CGXX_CMRX_RX_DMAC_CTL0 );
364+ cfg &= ~CGX_DMAC_CAM_ACCEPT ;
365+ cfg |= (CGX_DMAC_BCAST_MODE | CGX_DMAC_MCAST_MODE );
366+ cgx_write (cgx_dev , lmac_id , CGXX_CMRX_RX_DMAC_CTL0 , cfg );
367+
368+ return 0 ;
369+ }
370+
371+ /* Allows caller to change macaddress associated with index
372+ * in dmac filter table including index 0 reserved for
373+ * interface mac address
374+ */
375+ int cgx_lmac_addr_update (u8 cgx_id , u8 lmac_id , u8 * mac_addr , u8 index )
376+ {
377+ struct cgx * cgx_dev = cgx_get_pdata (cgx_id );
378+ struct mac_ops * mac_ops ;
379+ struct lmac * lmac ;
380+ u64 cfg ;
381+ int id ;
382+
383+ lmac = lmac_pdata (lmac_id , cgx_dev );
384+ if (!lmac )
385+ return - ENODEV ;
386+
387+ mac_ops = cgx_dev -> mac_ops ;
388+ /* Validate the index */
389+ if (index >= lmac -> mac_to_index_bmap .max )
390+ return - EINVAL ;
391+
392+ /* ensure index is already set */
393+ if (!test_bit (index , lmac -> mac_to_index_bmap .bmap ))
394+ return - EINVAL ;
395+
396+ id = get_sequence_id_of_lmac (cgx_dev , lmac_id );
397+
398+ index = id * lmac -> mac_to_index_bmap .max + index ;
399+
400+ cfg = cgx_read (cgx_dev , 0 , (CGXX_CMRX_RX_DMAC_CAM0 + (index * 0x8 )));
401+ cfg &= ~CGX_RX_DMAC_ADR_MASK ;
402+ cfg |= mac2u64 (mac_addr );
403+
404+ cgx_write (cgx_dev , 0 , (CGXX_CMRX_RX_DMAC_CAM0 + (index * 0x8 )), cfg );
405+ return 0 ;
406+ }
407+
408+ int cgx_lmac_addr_del (u8 cgx_id , u8 lmac_id , u8 index )
409+ {
410+ struct cgx * cgx_dev = cgx_get_pdata (cgx_id );
411+ struct lmac * lmac = lmac_pdata (lmac_id , cgx_dev );
412+ struct mac_ops * mac_ops ;
413+ u8 mac [ETH_ALEN ];
414+ u64 cfg ;
415+ int id ;
416+
417+ if (!lmac )
418+ return - ENODEV ;
419+
420+ mac_ops = cgx_dev -> mac_ops ;
421+ /* Validate the index */
422+ if (index >= lmac -> mac_to_index_bmap .max )
423+ return - EINVAL ;
424+
425+ /* Skip deletion for reserved index i.e. index 0 */
426+ if (index == 0 )
427+ return 0 ;
428+
429+ rvu_free_rsrc (& lmac -> mac_to_index_bmap , index );
430+
431+ id = get_sequence_id_of_lmac (cgx_dev , lmac_id );
432+
433+ index = id * lmac -> mac_to_index_bmap .max + index ;
434+
435+ /* Read MAC address to check whether it is ucast or mcast */
436+ cfg = cgx_read (cgx_dev , 0 , (CGXX_CMRX_RX_DMAC_CAM0 + (index * 0x8 )));
437+
438+ cfg2mac (cfg , mac );
439+ if (is_multicast_ether_addr (mac ))
440+ lmac -> mcast_filters_count -- ;
441+
442+ if (!lmac -> mcast_filters_count ) {
443+ cfg = cgx_read (cgx_dev , lmac_id , CGXX_CMRX_RX_DMAC_CTL0 );
444+ cfg &= ~GENMASK_ULL (2 , 1 );
445+ cfg |= CGX_DMAC_MCAST_MODE ;
446+ cgx_write (cgx_dev , lmac_id , CGXX_CMRX_RX_DMAC_CTL0 , cfg );
447+ }
448+
449+ cgx_write (cgx_dev , 0 , (CGXX_CMRX_RX_DMAC_CAM0 + (index * 0x8 )), 0 );
450+
451+ return 0 ;
452+ }
453+
454+ int cgx_lmac_addr_max_entries_get (u8 cgx_id , u8 lmac_id )
455+ {
456+ struct cgx * cgx_dev = cgx_get_pdata (cgx_id );
457+ struct lmac * lmac = lmac_pdata (lmac_id , cgx_dev );
458+
459+ if (lmac )
460+ return lmac -> mac_to_index_bmap .max ;
461+
462+ return 0 ;
463+ }
464+
236465u64 cgx_lmac_addr_get (u8 cgx_id , u8 lmac_id )
237466{
238467 struct cgx * cgx_dev = cgx_get_pdata (cgx_id );
468+ struct lmac * lmac = lmac_pdata (lmac_id , cgx_dev );
239469 struct mac_ops * mac_ops ;
470+ int index ;
240471 u64 cfg ;
472+ int id ;
241473
242474 mac_ops = cgx_dev -> mac_ops ;
243475
244- cfg = cgx_read (cgx_dev , 0 , CGXX_CMRX_RX_DMAC_CAM0 + lmac_id * 0x8 );
476+ id = get_sequence_id_of_lmac (cgx_dev , lmac_id );
477+
478+ index = id * lmac -> mac_to_index_bmap .max ;
479+
480+ cfg = cgx_read (cgx_dev , 0 , CGXX_CMRX_RX_DMAC_CAM0 + index * 0x8 );
245481 return cfg & CGX_RX_DMAC_ADR_MASK ;
246482}
247483
@@ -297,35 +533,51 @@ int cgx_lmac_internal_loopback(void *cgxd, int lmac_id, bool enable)
297533void cgx_lmac_promisc_config (int cgx_id , int lmac_id , bool enable )
298534{
299535 struct cgx * cgx = cgx_get_pdata (cgx_id );
536+ struct lmac * lmac = lmac_pdata (lmac_id , cgx );
537+ u16 max_dmac = lmac -> mac_to_index_bmap .max ;
300538 struct mac_ops * mac_ops ;
539+ int index , i ;
301540 u64 cfg = 0 ;
541+ int id ;
302542
303543 if (!cgx )
304544 return ;
305545
546+ id = get_sequence_id_of_lmac (cgx , lmac_id );
547+
306548 mac_ops = cgx -> mac_ops ;
307549 if (enable ) {
308550 /* Enable promiscuous mode on LMAC */
309551 cfg = cgx_read (cgx , lmac_id , CGXX_CMRX_RX_DMAC_CTL0 );
310- cfg &= ~( CGX_DMAC_CAM_ACCEPT | CGX_DMAC_MCAST_MODE ) ;
311- cfg |= CGX_DMAC_BCAST_MODE ;
552+ cfg &= ~CGX_DMAC_CAM_ACCEPT ;
553+ cfg |= ( CGX_DMAC_BCAST_MODE | CGX_DMAC_MCAST_MODE ) ;
312554 cgx_write (cgx , lmac_id , CGXX_CMRX_RX_DMAC_CTL0 , cfg );
313555
314- cfg = cgx_read (cgx , 0 ,
315- (CGXX_CMRX_RX_DMAC_CAM0 + lmac_id * 0x8 ));
316- cfg &= ~CGX_DMAC_CAM_ADDR_ENABLE ;
317- cgx_write (cgx , 0 ,
318- (CGXX_CMRX_RX_DMAC_CAM0 + lmac_id * 0x8 ), cfg );
556+ for (i = 0 ; i < max_dmac ; i ++ ) {
557+ index = id * max_dmac + i ;
558+ cfg = cgx_read (cgx , 0 ,
559+ (CGXX_CMRX_RX_DMAC_CAM0 + index * 0x8 ));
560+ cfg &= ~CGX_DMAC_CAM_ADDR_ENABLE ;
561+ cgx_write (cgx , 0 ,
562+ (CGXX_CMRX_RX_DMAC_CAM0 + index * 0x8 ), cfg );
563+ }
319564 } else {
320565 /* Disable promiscuous mode */
321566 cfg = cgx_read (cgx , lmac_id , CGXX_CMRX_RX_DMAC_CTL0 );
322567 cfg |= CGX_DMAC_CAM_ACCEPT | CGX_DMAC_MCAST_MODE ;
323568 cgx_write (cgx , lmac_id , CGXX_CMRX_RX_DMAC_CTL0 , cfg );
324- cfg = cgx_read (cgx , 0 ,
325- (CGXX_CMRX_RX_DMAC_CAM0 + lmac_id * 0x8 ));
326- cfg |= CGX_DMAC_CAM_ADDR_ENABLE ;
327- cgx_write (cgx , 0 ,
328- (CGXX_CMRX_RX_DMAC_CAM0 + lmac_id * 0x8 ), cfg );
569+ for (i = 0 ; i < max_dmac ; i ++ ) {
570+ index = id * max_dmac + i ;
571+ cfg = cgx_read (cgx , 0 ,
572+ (CGXX_CMRX_RX_DMAC_CAM0 + index * 0x8 ));
573+ if ((cfg & CGX_RX_DMAC_ADR_MASK ) != 0 ) {
574+ cfg |= CGX_DMAC_CAM_ADDR_ENABLE ;
575+ cgx_write (cgx , 0 ,
576+ (CGXX_CMRX_RX_DMAC_CAM0 +
577+ index * 0x8 ),
578+ cfg );
579+ }
580+ }
329581 }
330582}
331583
@@ -1234,6 +1486,15 @@ static int cgx_lmac_init(struct cgx *cgx)
12341486 }
12351487
12361488 lmac -> cgx = cgx ;
1489+ lmac -> mac_to_index_bmap .max =
1490+ MAX_DMAC_ENTRIES_PER_CGX / cgx -> lmac_count ;
1491+ err = rvu_alloc_bitmap (& lmac -> mac_to_index_bmap );
1492+ if (err )
1493+ return err ;
1494+
1495+ /* Reserve first entry for default MAC address */
1496+ set_bit (0 , lmac -> mac_to_index_bmap .bmap );
1497+
12371498 init_waitqueue_head (& lmac -> wq_cmd_cmplt );
12381499 mutex_init (& lmac -> cmd_lock );
12391500 spin_lock_init (& lmac -> event_cb_lock );
@@ -1274,6 +1535,7 @@ static int cgx_lmac_exit(struct cgx *cgx)
12741535 continue ;
12751536 cgx -> mac_ops -> mac_pause_frm_config (cgx , lmac -> lmac_id , false);
12761537 cgx_configure_interrupt (cgx , lmac , lmac -> lmac_id , true);
1538+ kfree (lmac -> mac_to_index_bmap .bmap );
12771539 kfree (lmac -> name );
12781540 kfree (lmac );
12791541 }
0 commit comments