@@ -541,14 +541,93 @@ static inline int cpsw_get_slave_port(struct cpsw_priv *priv, u32 slave_num)
541541 return slave_num ;
542542}
543543
544+ static void cpsw_set_promiscious (struct net_device * ndev , bool enable )
545+ {
546+ struct cpsw_priv * priv = netdev_priv (ndev );
547+ struct cpsw_ale * ale = priv -> ale ;
548+ int i ;
549+
550+ if (priv -> data .dual_emac ) {
551+ bool flag = false;
552+
553+ /* Enabling promiscuous mode for one interface will be
554+ * common for both the interface as the interface shares
555+ * the same hardware resource.
556+ */
557+ for (i = 0 ; i <= priv -> data .slaves ; i ++ )
558+ if (priv -> slaves [i ].ndev -> flags & IFF_PROMISC )
559+ flag = true;
560+
561+ if (!enable && flag ) {
562+ enable = true;
563+ dev_err (& ndev -> dev , "promiscuity not disabled as the other interface is still in promiscuity mode\n" );
564+ }
565+
566+ if (enable ) {
567+ /* Enable Bypass */
568+ cpsw_ale_control_set (ale , 0 , ALE_BYPASS , 1 );
569+
570+ dev_dbg (& ndev -> dev , "promiscuity enabled\n" );
571+ } else {
572+ /* Disable Bypass */
573+ cpsw_ale_control_set (ale , 0 , ALE_BYPASS , 0 );
574+ dev_dbg (& ndev -> dev , "promiscuity disabled\n" );
575+ }
576+ } else {
577+ if (enable ) {
578+ unsigned long timeout = jiffies + HZ ;
579+
580+ /* Disable Learn for all ports */
581+ for (i = 0 ; i <= priv -> data .slaves ; i ++ ) {
582+ cpsw_ale_control_set (ale , i ,
583+ ALE_PORT_NOLEARN , 1 );
584+ cpsw_ale_control_set (ale , i ,
585+ ALE_PORT_NO_SA_UPDATE , 1 );
586+ }
587+
588+ /* Clear All Untouched entries */
589+ cpsw_ale_control_set (ale , 0 , ALE_AGEOUT , 1 );
590+ do {
591+ cpu_relax ();
592+ if (cpsw_ale_control_get (ale , 0 , ALE_AGEOUT ))
593+ break ;
594+ } while (time_after (timeout , jiffies ));
595+ cpsw_ale_control_set (ale , 0 , ALE_AGEOUT , 1 );
596+
597+ /* Clear all mcast from ALE */
598+ cpsw_ale_flush_multicast (ale , ALE_ALL_PORTS <<
599+ priv -> host_port );
600+
601+ /* Flood All Unicast Packets to Host port */
602+ cpsw_ale_control_set (ale , 0 , ALE_P0_UNI_FLOOD , 1 );
603+ dev_dbg (& ndev -> dev , "promiscuity enabled\n" );
604+ } else {
605+ /* Flood All Unicast Packets to Host port */
606+ cpsw_ale_control_set (ale , 0 , ALE_P0_UNI_FLOOD , 0 );
607+
608+ /* Enable Learn for all ports */
609+ for (i = 0 ; i <= priv -> data .slaves ; i ++ ) {
610+ cpsw_ale_control_set (ale , i ,
611+ ALE_PORT_NOLEARN , 0 );
612+ cpsw_ale_control_set (ale , i ,
613+ ALE_PORT_NO_SA_UPDATE , 0 );
614+ }
615+ dev_dbg (& ndev -> dev , "promiscuity disabled\n" );
616+ }
617+ }
618+ }
619+
544620static void cpsw_ndo_set_rx_mode (struct net_device * ndev )
545621{
546622 struct cpsw_priv * priv = netdev_priv (ndev );
547623
548624 if (ndev -> flags & IFF_PROMISC ) {
549625 /* Enable promiscuous mode */
550- dev_err ( priv -> dev , "Ignoring Promiscuous mode\n" );
626+ cpsw_set_promiscious ( ndev , true );
551627 return ;
628+ } else {
629+ /* Disable promiscuous mode */
630+ cpsw_set_promiscious (ndev , false);
552631 }
553632
554633 /* Clear all mcast from ALE */
@@ -1257,29 +1336,6 @@ static netdev_tx_t cpsw_ndo_start_xmit(struct sk_buff *skb,
12571336 return NETDEV_TX_BUSY ;
12581337}
12591338
1260- static void cpsw_ndo_change_rx_flags (struct net_device * ndev , int flags )
1261- {
1262- /*
1263- * The switch cannot operate in promiscuous mode without substantial
1264- * headache. For promiscuous mode to work, we would need to put the
1265- * ALE in bypass mode and route all traffic to the host port.
1266- * Subsequently, the host will need to operate as a "bridge", learn,
1267- * and flood as needed. For now, we simply complain here and
1268- * do nothing about it :-)
1269- */
1270- if ((flags & IFF_PROMISC ) && (ndev -> flags & IFF_PROMISC ))
1271- dev_err (& ndev -> dev , "promiscuity ignored!\n" );
1272-
1273- /*
1274- * The switch cannot filter multicast traffic unless it is configured
1275- * in "VLAN Aware" mode. Unfortunately, VLAN awareness requires a
1276- * whole bunch of additional logic that this driver does not implement
1277- * at present.
1278- */
1279- if ((flags & IFF_ALLMULTI ) && !(ndev -> flags & IFF_ALLMULTI ))
1280- dev_err (& ndev -> dev , "multicast traffic cannot be filtered!\n" );
1281- }
1282-
12831339#ifdef CONFIG_TI_CPTS
12841340
12851341static void cpsw_hwtstamp_v1 (struct cpsw_priv * priv )
@@ -1575,7 +1631,6 @@ static const struct net_device_ops cpsw_netdev_ops = {
15751631 .ndo_open = cpsw_ndo_open ,
15761632 .ndo_stop = cpsw_ndo_stop ,
15771633 .ndo_start_xmit = cpsw_ndo_start_xmit ,
1578- .ndo_change_rx_flags = cpsw_ndo_change_rx_flags ,
15791634 .ndo_set_mac_address = cpsw_ndo_set_mac_address ,
15801635 .ndo_do_ioctl = cpsw_ndo_ioctl ,
15811636 .ndo_validate_addr = eth_validate_addr ,
0 commit comments