Commit 2eb3e621 authored by Stephen Hemminger's avatar Stephen Hemminger Committed by Jeff Garzik

skge: set mac address bonding fix

When bonding does fail over it calls set_mac_address.  When this happens
as the result of another port going down, the phy_mutex that is common to
both ports is held, so it deadlocks. Setting the address doesn't need to do
anything that needs the phy_mutex, it already has the RTNL to protect against
other admin actions.

This change just disables the receiver to avoid any hardware confusion
while address is changing.
Signed-off-by: default avatarStephen Hemminger <shemminger@linux-foundation.org>
Signed-off-by: default avatarJeff Garzik <jeff@garzik.org>
parent 8ce5e3e4
...@@ -3275,24 +3275,30 @@ static int skge_set_mac_address(struct net_device *dev, void *p) ...@@ -3275,24 +3275,30 @@ static int skge_set_mac_address(struct net_device *dev, void *p)
struct skge_hw *hw = skge->hw; struct skge_hw *hw = skge->hw;
unsigned port = skge->port; unsigned port = skge->port;
const struct sockaddr *addr = p; const struct sockaddr *addr = p;
u16 ctrl;
if (!is_valid_ether_addr(addr->sa_data)) if (!is_valid_ether_addr(addr->sa_data))
return -EADDRNOTAVAIL; return -EADDRNOTAVAIL;
mutex_lock(&hw->phy_mutex);
memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN); memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN);
memcpy_toio(hw->regs + B2_MAC_1 + port*8,
dev->dev_addr, ETH_ALEN);
memcpy_toio(hw->regs + B2_MAC_2 + port*8,
dev->dev_addr, ETH_ALEN);
if (hw->chip_id == CHIP_ID_GENESIS) /* disable Rx */
xm_outaddr(hw, port, XM_SA, dev->dev_addr); ctrl = gma_read16(hw, port, GM_GP_CTRL);
else { gma_write16(hw, port, GM_GP_CTRL, ctrl & ~GM_GPCR_RX_ENA);
gma_set_addr(hw, port, GM_SRC_ADDR_1L, dev->dev_addr);
gma_set_addr(hw, port, GM_SRC_ADDR_2L, dev->dev_addr); memcpy_toio(hw->regs + B2_MAC_1 + port*8, dev->dev_addr, ETH_ALEN);
memcpy_toio(hw->regs + B2_MAC_2 + port*8, dev->dev_addr, ETH_ALEN);
if (netif_running(dev)) {
if (hw->chip_id == CHIP_ID_GENESIS)
xm_outaddr(hw, port, XM_SA, dev->dev_addr);
else {
gma_set_addr(hw, port, GM_SRC_ADDR_1L, dev->dev_addr);
gma_set_addr(hw, port, GM_SRC_ADDR_2L, dev->dev_addr);
}
} }
mutex_unlock(&hw->phy_mutex);
gma_write16(hw, port, GM_GP_CTRL, ctrl);
return 0; return 0;
} }
......
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