Commit cec9ae50 authored by Marc Zyngier's avatar Marc Zyngier Committed by David S. Miller

net: sun4i-emac: add promiscuous support

The sun4i-emac driver is rather primitive, and doesn't support
promiscuous mode. This makes usage such as bridging impossible,
which is a shame on virtualization capable HW such as the
Allwinner A20.

The fix is fairly simple: move the RX setup code to the ndo_set_rx_mode
vector, and add the required HW configuration when IFF_PROMISC is passed
by the core code.

This has been tested on a generic A20 box running a few virtual
machines hanging off a bridge with the EMAC chip as the link to the
outside world.

Cc: Stefan Roese <sr@denx.de>
Cc: Maxime Ripard <maxime.ripard@free-electrons.com>
Signed-off-by: default avatarMarc Zyngier <marc.zyngier@arm.com>
Acked-by: default avatarStefan Roese <sr@denx.de>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 0af764e3
...@@ -268,15 +268,6 @@ static unsigned int emac_setup(struct net_device *ndev) ...@@ -268,15 +268,6 @@ static unsigned int emac_setup(struct net_device *ndev)
writel(reg_val | EMAC_TX_MODE_ABORTED_FRAME_EN, writel(reg_val | EMAC_TX_MODE_ABORTED_FRAME_EN,
db->membase + EMAC_TX_MODE_REG); db->membase + EMAC_TX_MODE_REG);
/* set up RX */
reg_val = readl(db->membase + EMAC_RX_CTL_REG);
writel(reg_val | EMAC_RX_CTL_PASS_LEN_OOR_EN |
EMAC_RX_CTL_ACCEPT_UNICAST_EN | EMAC_RX_CTL_DA_FILTER_EN |
EMAC_RX_CTL_ACCEPT_MULTICAST_EN |
EMAC_RX_CTL_ACCEPT_BROADCAST_EN,
db->membase + EMAC_RX_CTL_REG);
/* set MAC */ /* set MAC */
/* set MAC CTL0 */ /* set MAC CTL0 */
reg_val = readl(db->membase + EMAC_MAC_CTL0_REG); reg_val = readl(db->membase + EMAC_MAC_CTL0_REG);
...@@ -309,6 +300,26 @@ static unsigned int emac_setup(struct net_device *ndev) ...@@ -309,6 +300,26 @@ static unsigned int emac_setup(struct net_device *ndev)
return 0; return 0;
} }
static void emac_set_rx_mode(struct net_device *ndev)
{
struct emac_board_info *db = netdev_priv(ndev);
unsigned int reg_val;
/* set up RX */
reg_val = readl(db->membase + EMAC_RX_CTL_REG);
if (ndev->flags & IFF_PROMISC)
reg_val |= EMAC_RX_CTL_PASS_ALL_EN;
else
reg_val &= ~EMAC_RX_CTL_PASS_ALL_EN;
writel(reg_val | EMAC_RX_CTL_PASS_LEN_OOR_EN |
EMAC_RX_CTL_ACCEPT_UNICAST_EN | EMAC_RX_CTL_DA_FILTER_EN |
EMAC_RX_CTL_ACCEPT_MULTICAST_EN |
EMAC_RX_CTL_ACCEPT_BROADCAST_EN,
db->membase + EMAC_RX_CTL_REG);
}
static unsigned int emac_powerup(struct net_device *ndev) static unsigned int emac_powerup(struct net_device *ndev)
{ {
struct emac_board_info *db = netdev_priv(ndev); struct emac_board_info *db = netdev_priv(ndev);
...@@ -782,6 +793,7 @@ static const struct net_device_ops emac_netdev_ops = { ...@@ -782,6 +793,7 @@ static const struct net_device_ops emac_netdev_ops = {
.ndo_stop = emac_stop, .ndo_stop = emac_stop,
.ndo_start_xmit = emac_start_xmit, .ndo_start_xmit = emac_start_xmit,
.ndo_tx_timeout = emac_timeout, .ndo_tx_timeout = emac_timeout,
.ndo_set_rx_mode = emac_set_rx_mode,
.ndo_do_ioctl = emac_ioctl, .ndo_do_ioctl = emac_ioctl,
.ndo_change_mtu = eth_change_mtu, .ndo_change_mtu = eth_change_mtu,
.ndo_validate_addr = eth_validate_addr, .ndo_validate_addr = eth_validate_addr,
......
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