Commit b37feed7 authored by Ben Hutchings's avatar Ben Hutchings Committed by David S. Miller

sh_eth: Fix promiscuous mode on chips without TSU

Currently net_device_ops::set_rx_mode is only implemented for
chips with a TSU (multiple address table).  However we do need
to turn the PRM (promiscuous) flag on and off for other chips.

- Remove the unlikely() from the TSU functions that we may safely
  call for chips without a TSU
- Make setting of the MCT flag conditional on the tsu capability flag
- Rename sh_eth_set_multicast_list() to sh_eth_set_rx_mode() and plumb
  it into both net_device_ops structures
- Remove the previously-unreachable branch in sh_eth_rx_mode() that
  would otherwise reset the flags to defaults for non-TSU chips
Signed-off-by: default avatarBen Hutchings <ben.hutchings@codethink.co.uk>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 9d289715
...@@ -2417,7 +2417,7 @@ static int sh_eth_tsu_purge_all(struct net_device *ndev) ...@@ -2417,7 +2417,7 @@ static int sh_eth_tsu_purge_all(struct net_device *ndev)
struct sh_eth_private *mdp = netdev_priv(ndev); struct sh_eth_private *mdp = netdev_priv(ndev);
int i, ret; int i, ret;
if (unlikely(!mdp->cd->tsu)) if (!mdp->cd->tsu)
return 0; return 0;
for (i = 0; i < SH_ETH_TSU_CAM_ENTRIES; i++) { for (i = 0; i < SH_ETH_TSU_CAM_ENTRIES; i++) {
...@@ -2440,7 +2440,7 @@ static void sh_eth_tsu_purge_mcast(struct net_device *ndev) ...@@ -2440,7 +2440,7 @@ static void sh_eth_tsu_purge_mcast(struct net_device *ndev)
void *reg_offset = sh_eth_tsu_get_offset(mdp, TSU_ADRH0); void *reg_offset = sh_eth_tsu_get_offset(mdp, TSU_ADRH0);
int i; int i;
if (unlikely(!mdp->cd->tsu)) if (!mdp->cd->tsu)
return; return;
for (i = 0; i < SH_ETH_TSU_CAM_ENTRIES; i++, reg_offset += 8) { for (i = 0; i < SH_ETH_TSU_CAM_ENTRIES; i++, reg_offset += 8) {
...@@ -2450,8 +2450,8 @@ static void sh_eth_tsu_purge_mcast(struct net_device *ndev) ...@@ -2450,8 +2450,8 @@ static void sh_eth_tsu_purge_mcast(struct net_device *ndev)
} }
} }
/* Multicast reception directions set */ /* Update promiscuous flag and multicast filter */
static void sh_eth_set_multicast_list(struct net_device *ndev) static void sh_eth_set_rx_mode(struct net_device *ndev)
{ {
struct sh_eth_private *mdp = netdev_priv(ndev); struct sh_eth_private *mdp = netdev_priv(ndev);
u32 ecmr_bits; u32 ecmr_bits;
...@@ -2462,7 +2462,9 @@ static void sh_eth_set_multicast_list(struct net_device *ndev) ...@@ -2462,7 +2462,9 @@ static void sh_eth_set_multicast_list(struct net_device *ndev)
/* Initial condition is MCT = 1, PRM = 0. /* Initial condition is MCT = 1, PRM = 0.
* Depending on ndev->flags, set PRM or clear MCT * Depending on ndev->flags, set PRM or clear MCT
*/ */
ecmr_bits = (sh_eth_read(ndev, ECMR) & ~ECMR_PRM) | ECMR_MCT; ecmr_bits = sh_eth_read(ndev, ECMR) & ~ECMR_PRM;
if (mdp->cd->tsu)
ecmr_bits |= ECMR_MCT;
if (!(ndev->flags & IFF_MULTICAST)) { if (!(ndev->flags & IFF_MULTICAST)) {
sh_eth_tsu_purge_mcast(ndev); sh_eth_tsu_purge_mcast(ndev);
...@@ -2491,9 +2493,6 @@ static void sh_eth_set_multicast_list(struct net_device *ndev) ...@@ -2491,9 +2493,6 @@ static void sh_eth_set_multicast_list(struct net_device *ndev)
} }
} }
} }
} else {
/* Normal, unicast/broadcast-only mode. */
ecmr_bits = (ecmr_bits & ~ECMR_PRM) | ECMR_MCT;
} }
/* update the ethernet mode */ /* update the ethernet mode */
...@@ -2701,6 +2700,7 @@ static const struct net_device_ops sh_eth_netdev_ops = { ...@@ -2701,6 +2700,7 @@ static const struct net_device_ops sh_eth_netdev_ops = {
.ndo_stop = sh_eth_close, .ndo_stop = sh_eth_close,
.ndo_start_xmit = sh_eth_start_xmit, .ndo_start_xmit = sh_eth_start_xmit,
.ndo_get_stats = sh_eth_get_stats, .ndo_get_stats = sh_eth_get_stats,
.ndo_set_rx_mode = sh_eth_set_rx_mode,
.ndo_tx_timeout = sh_eth_tx_timeout, .ndo_tx_timeout = sh_eth_tx_timeout,
.ndo_do_ioctl = sh_eth_do_ioctl, .ndo_do_ioctl = sh_eth_do_ioctl,
.ndo_validate_addr = eth_validate_addr, .ndo_validate_addr = eth_validate_addr,
...@@ -2713,7 +2713,7 @@ static const struct net_device_ops sh_eth_netdev_ops_tsu = { ...@@ -2713,7 +2713,7 @@ static const struct net_device_ops sh_eth_netdev_ops_tsu = {
.ndo_stop = sh_eth_close, .ndo_stop = sh_eth_close,
.ndo_start_xmit = sh_eth_start_xmit, .ndo_start_xmit = sh_eth_start_xmit,
.ndo_get_stats = sh_eth_get_stats, .ndo_get_stats = sh_eth_get_stats,
.ndo_set_rx_mode = sh_eth_set_multicast_list, .ndo_set_rx_mode = sh_eth_set_rx_mode,
.ndo_vlan_rx_add_vid = sh_eth_vlan_rx_add_vid, .ndo_vlan_rx_add_vid = sh_eth_vlan_rx_add_vid,
.ndo_vlan_rx_kill_vid = sh_eth_vlan_rx_kill_vid, .ndo_vlan_rx_kill_vid = sh_eth_vlan_rx_kill_vid,
.ndo_tx_timeout = sh_eth_tx_timeout, .ndo_tx_timeout = sh_eth_tx_timeout,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment