@@ -415,6 +415,158 @@ static void dwxgmac2_set_eee_timer(struct mac_device_info *hw, int ls, int tw)
415415 writel (value , ioaddr + XGMAC_LPI_TIMER_CTRL );
416416}
417417
418+ static void dwxgmac2_write_single_vlan (struct net_device * dev , u16 vid )
419+ {
420+ void __iomem * ioaddr = (void __iomem * )dev -> base_addr ;
421+ u32 val ;
422+
423+ val = readl (ioaddr + XGMAC_VLAN_TAG );
424+ val &= ~XGMAC_VLAN_VID ;
425+ val |= XGMAC_VLAN_ETV | vid ;
426+
427+ writel (val , ioaddr + XGMAC_VLAN_TAG );
428+ }
429+
430+ static int dwxgmac2_write_vlan_filter (struct net_device * dev ,
431+ struct mac_device_info * hw ,
432+ u8 index , u32 data )
433+ {
434+ void __iomem * ioaddr = (void __iomem * )dev -> base_addr ;
435+ int i , timeout = 10 ;
436+ u32 val ;
437+
438+ if (index >= hw -> num_vlan )
439+ return - EINVAL ;
440+
441+ writel (data , ioaddr + XGMAC_VLAN_TAG_DATA );
442+
443+ val = readl (ioaddr + XGMAC_VLAN_TAG );
444+ val &= ~(XGMAC_VLAN_TAG_CTRL_OFS_MASK |
445+ XGMAC_VLAN_CT |
446+ XGMAC_VLAN_OB );
447+
448+ val |= (index << XGMAC_VLAN_OFS_SHIFT | XGMAC_VLAN_OB );
449+
450+ writel (val , ioaddr + XGMAC_VLAN_TAG );
451+
452+ for (i = 0 ; i < timeout ; i ++ ) {
453+ val = readl (ioaddr + XGMAC_VLAN_TAG );
454+ if (!(val & XGMAC_VLAN_OB ))
455+ return 0 ;
456+ udelay (1 );
457+
458+ }
459+
460+ netdev_err (dev , "Timeout accesing MAC_VLAN_TAG_FILTER\n" );
461+
462+ return - EBUSY ;
463+ }
464+
465+ static int dwxgmac2_add_hw_vlan_rx_fltr (struct net_device * dev ,
466+ struct mac_device_info * hw ,
467+ __be16 proto , u16 vid )
468+ {
469+ int index = -1 ;
470+ u32 val = 0 ;
471+ int i , ret ;
472+
473+ if (vid > 4095 )
474+ return - EINVAL ;
475+
476+ /* Single Rx VLAN Filter */
477+ if (hw -> num_vlan == 1 ) {
478+ /* For single VLAN filter, VID 0 means VLAN promiscuous */
479+ if (vid == 0 ) {
480+ netdev_warn (dev , "Adding VLAN ID 0 is not supported\n" );
481+ return - EPERM ;
482+ }
483+
484+ if (hw -> vlan_filter [0 ] & XGMAC_VLAN_VID ) {
485+ netdev_err (dev , "Only single VLAN ID supported\n" );
486+ return - EPERM ;
487+ }
488+
489+ hw -> vlan_filter [0 ] = vid ;
490+ dwxgmac2_write_single_vlan (dev , vid );
491+
492+ return 0 ;
493+ }
494+
495+ /* Extended Rx VLAN Filter Enable */
496+ val |= XGMAC_VLAN_TAG_DATA_ETV | XGMAC_VLAN_TAG_DATA_VEN | vid ;
497+
498+ for (i = 0 ; i < hw -> num_vlan ; i ++ ) {
499+ if (hw -> vlan_filter [i ] == val )
500+ return 0 ;
501+
502+ else if (!(hw -> vlan_filter [i ] & XGMAC_VLAN_TAG_DATA_VEN ))
503+ index = i ;
504+ }
505+
506+ if (index == -1 ){
507+ netdev_err (dev , "MAC_VLAN_TAG_FILTER full (size: %0u)\n" ,
508+ hw -> num_vlan );
509+ return - EPERM ;
510+ }
511+
512+ ret = dwxgmac2_write_vlan_filter (dev , hw , index , val );
513+
514+ if (!ret )
515+ hw -> vlan_filter [index ] = val ;
516+
517+ return ret ;
518+ }
519+
520+ static int dwxgmac2_del_hw_vlan_rx_fltr (struct net_device * dev ,
521+ struct mac_device_info * hw ,
522+ __be16 proto , u16 vid )
523+ {
524+ int i , ret = 0 ;
525+
526+ /* Single Rx VLAN Filter */
527+ if (hw -> num_vlan == 1 ) {
528+ if ((hw -> vlan_filter [0 ] & XGMAC_VLAN_VID ) == vid ) {
529+ hw -> vlan_filter [0 ] = 0 ;
530+ dwxgmac2_write_single_vlan (dev , 0 );
531+ }
532+ return 0 ;
533+ }
534+
535+ /* Extended Rx VLAN Filter Enable */
536+ for (i = 0 ; i < hw -> num_vlan ; i ++ ) {
537+ if ((hw -> vlan_filter [i ] & XGMAC_VLAN_TAG_DATA_VID ) == vid ) {
538+ ret = dwxgmac2_write_vlan_filter (dev , hw , i , 0 );
539+
540+ if (!ret )
541+ hw -> vlan_filter [i ] = 0 ;
542+ else
543+ return ret ;
544+ }
545+ }
546+ return ret ;
547+ }
548+
549+ static void dwxgmac2_restore_hw_vlan_rx_fltr (struct net_device * dev ,
550+ struct mac_device_info * hw )
551+ {
552+ u32 val ;
553+ int i ;
554+
555+ /* Single Rx VLAN Filter */
556+ if (hw -> num_vlan == 1 ) {
557+ dwxgmac2_write_single_vlan (dev , hw -> vlan_filter [0 ]);
558+ return ;
559+ }
560+
561+ /* Extended Rx VLAN Filter Enable */
562+ for (i = 0 ; i < hw -> num_vlan ; i ++ ) {
563+ if (hw -> vlan_filter [i ] & XGMAC_VLAN_TAG_DATA_VEN ) {
564+ val = hw -> vlan_filter [i ];
565+ dwxgmac2_write_vlan_filter (dev , hw , i , val );
566+ }
567+ }
568+ }
569+
418570static void dwxgmac2_set_mchash (void __iomem * ioaddr , u32 * mcfilterbits ,
419571 int mcbitslog2 )
420572{
@@ -493,6 +645,10 @@ static void dwxgmac2_set_filter(struct mac_device_info *hw,
493645 }
494646 }
495647
648+ /* VLAN Filtering */
649+ if (dev -> features & NETIF_F_HW_VLAN_CTAG_FILTER )
650+ value |= XGMAC_FILTER_VTFE ;
651+
496652 writel (value , ioaddr + XGMAC_PACKET_FILTER );
497653}
498654
@@ -1528,6 +1684,9 @@ const struct stmmac_ops dwxgmac210_ops = {
15281684 .enable_vlan = dwxgmac2_enable_vlan ,
15291685 .config_l3_filter = dwxgmac2_config_l3_filter ,
15301686 .config_l4_filter = dwxgmac2_config_l4_filter ,
1687+ .add_hw_vlan_rx_fltr = dwxgmac2_add_hw_vlan_rx_fltr ,
1688+ .del_hw_vlan_rx_fltr = dwxgmac2_del_hw_vlan_rx_fltr ,
1689+ .restore_hw_vlan_rx_fltr = dwxgmac2_restore_hw_vlan_rx_fltr ,
15311690 .set_arp_offload = dwxgmac2_set_arp_offload ,
15321691 .est_configure = dwxgmac3_est_configure ,
15331692 .fpe_configure = dwxgmac3_fpe_configure ,
@@ -1598,6 +1757,37 @@ const struct stmmac_ops dwxlgmac2_ops = {
15981757 .set_hw_vlan_mode = dwxgmac2_set_hw_vlan_mode ,
15991758};
16001759
1760+ static u32 dwxgmac2_get_num_vlan (void __iomem * ioaddr )
1761+ {
1762+ u32 val , num_vlan ;
1763+
1764+ val = readl (ioaddr + XGMAC_HW_FEATURE3 );
1765+ switch (val & XGMAC_HWFEAT_NRVF ) {
1766+ case 0 :
1767+ num_vlan = 1 ;
1768+ break ;
1769+ case 1 :
1770+ num_vlan = 4 ;
1771+ break ;
1772+ case 2 :
1773+ num_vlan = 8 ;
1774+ break ;
1775+ case 3 :
1776+ num_vlan = 16 ;
1777+ break ;
1778+ case 4 :
1779+ num_vlan = 24 ;
1780+ break ;
1781+ case 5 :
1782+ num_vlan = 32 ;
1783+ break ;
1784+ default :
1785+ num_vlan = 1 ;
1786+ }
1787+
1788+ return num_vlan ;
1789+ }
1790+
16011791int dwxgmac2_setup (struct stmmac_priv * priv )
16021792{
16031793 struct mac_device_info * mac = priv -> hw ;
@@ -1631,7 +1821,7 @@ int dwxgmac2_setup(struct stmmac_priv *priv)
16311821 mac -> mii .reg_mask = GENMASK (15 , 0 );
16321822 mac -> mii .clk_csr_shift = 19 ;
16331823 mac -> mii .clk_csr_mask = GENMASK (21 , 19 );
1634-
1824+ mac -> num_vlan = dwxgmac2_get_num_vlan ( priv -> ioaddr );
16351825 return 0 ;
16361826}
16371827
0 commit comments