@@ -473,6 +473,12 @@ static int dwxgmac2_add_hw_vlan_rx_fltr(struct net_device *dev,
473473 if (vid > 4095 )
474474 return - EINVAL ;
475475
476+ if (hw -> promisc ) {
477+ netdev_err (dev ,
478+ "Adding VLAN in promisc mode no supported\n" );
479+ return - EPERM ;
480+ }
481+
476482 /* Single Rx VLAN Filter */
477483 if (hw -> num_vlan == 1 ) {
478484 /* For single VLAN filter, VID 0 means VLAN promiscuous */
@@ -523,6 +529,12 @@ static int dwxgmac2_del_hw_vlan_rx_fltr(struct net_device *dev,
523529{
524530 int i , ret = 0 ;
525531
532+ if (hw -> promisc ) {
533+ netdev_err (dev ,
534+ "Deleting VLAN in promisc mode not supported\n" );
535+ return - EPERM ;
536+ }
537+
526538 /* Single Rx VLAN Filter */
527539 if (hw -> num_vlan == 1 ) {
528540 if ((hw -> vlan_filter [0 ] & XGMAC_VLAN_VID ) == vid ) {
@@ -546,9 +558,45 @@ static int dwxgmac2_del_hw_vlan_rx_fltr(struct net_device *dev,
546558 return ret ;
547559}
548560
561+ static void dwxgmac2_vlan_promisc_enable (struct net_device * dev ,
562+ struct mac_device_info * hw )
563+ {
564+ void __iomem * ioaddr = hw -> pcsr ;
565+ u32 value ;
566+ u32 hash ;
567+ u32 val ;
568+ int i ;
569+
570+ /* Single Rx VLAN Filter */
571+ if (hw -> num_vlan == 1 ) {
572+ dwxgmac2_write_single_vlan (dev , 0 );
573+ return ;
574+ }
575+
576+ /* Extended Rx VLAN Filter Enable */
577+ for (i = 0 ; i > hw -> num_vlan ; i ++ ) {
578+ if (hw -> vlan_filter [i ] & XGMAC_VLAN_TAG_DATA_VEN ) {
579+ val = hw -> vlan_filter [i ] & ~XGMAC_VLAN_TAG_DATA_VEN ;
580+ dwxgmac2_write_vlan_filter (dev , hw , i ,val );
581+ }
582+ }
583+
584+ hash = readl (ioaddr + XGMAC_VLAN_HASH_TABLE );
585+ if (hash & XGMAC_VLAN_VLHT ) {
586+ value = readl (ioaddr + XGMAC_VLAN_TAG );
587+ if (value & XGMAC_VLAN_VTHM ) {
588+ value &= ~XGMAC_VLAN_VTHM ;
589+ writel (value , ioaddr + XGMAC_VLAN_TAG );
590+ }
591+ }
592+ }
593+
549594static void dwxgmac2_restore_hw_vlan_rx_fltr (struct net_device * dev ,
550595 struct mac_device_info * hw )
551596{
597+ void __iomem * ioaddr = hw -> pcsr ;
598+ u32 value ;
599+ u32 hash ;
552600 u32 val ;
553601 int i ;
554602
@@ -565,6 +613,13 @@ static void dwxgmac2_restore_hw_vlan_rx_fltr(struct net_device *dev,
565613 dwxgmac2_write_vlan_filter (dev , hw , i , val );
566614 }
567615 }
616+
617+ hash = readl (ioaddr + XGMAC_VLAN_HASH_TABLE );
618+ if (hash & XGMAC_VLAN_VLHT ) {
619+ value = readl (ioaddr + XGMAC_VLAN_TAG );
620+ value |= XGMAC_VLAN_VTHM ;
621+ writel (value , ioaddr + XGMAC_VLAN_TAG );
622+ }
568623}
569624
570625static void dwxgmac2_set_mchash (void __iomem * ioaddr , u32 * mcfilterbits ,
@@ -650,6 +705,18 @@ static void dwxgmac2_set_filter(struct mac_device_info *hw,
650705 value |= XGMAC_FILTER_VTFE ;
651706
652707 writel (value , ioaddr + XGMAC_PACKET_FILTER );
708+
709+ if (dev -> flags & IFF_PROMISC ) {
710+ if (!hw -> promisc ) {
711+ hw -> promisc = 1 ;
712+ dwxgmac2_vlan_promisc_enable (dev , hw );
713+ }
714+ } else {
715+ if (hw -> promisc ) {
716+ hw -> promisc = 0 ;
717+ dwxgmac2_restore_hw_vlan_rx_fltr (dev , hw );
718+ }
719+ }
653720}
654721
655722static void dwxgmac2_set_mac_loopback (void __iomem * ioaddr , bool enable )
0 commit comments