aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/skge.c
diff options
context:
space:
mode:
authorStephen Hemminger <shemminger@linux-foundation.org>2007-03-12 18:16:26 -0400
committerJeff Garzik <jeff@garzik.org>2007-03-15 10:44:32 -0400
commit2eb3e621c4e07e9e7200dbb66f0433b4caafb8e7 (patch)
tree076526c36ade3c7c8a5e118c5210e14db96f22de /drivers/net/skge.c
parent8ce5e3e45e01ffab38a9f03900181132b9068543 (diff)
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: Stephen Hemminger <shemminger@linux-foundation.org> Signed-off-by: Jeff Garzik <jeff@garzik.org>
Diffstat (limited to 'drivers/net/skge.c')
-rw-r--r--drivers/net/skge.c28
1 files changed, 17 insertions, 11 deletions
diff --git a/drivers/net/skge.c b/drivers/net/skge.c
index eea75a401b0c..8fecf1b817f7 100644
--- a/drivers/net/skge.c
+++ b/drivers/net/skge.c
@@ -3275,24 +3275,30 @@ static int skge_set_mac_address(struct net_device *dev, void *p)
3275 struct skge_hw *hw = skge->hw; 3275 struct skge_hw *hw = skge->hw;
3276 unsigned port = skge->port; 3276 unsigned port = skge->port;
3277 const struct sockaddr *addr = p; 3277 const struct sockaddr *addr = p;
3278 u16 ctrl;
3278 3279
3279 if (!is_valid_ether_addr(addr->sa_data)) 3280 if (!is_valid_ether_addr(addr->sa_data))
3280 return -EADDRNOTAVAIL; 3281 return -EADDRNOTAVAIL;
3281 3282
3282 mutex_lock(&hw->phy_mutex);
3283 memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN); 3283 memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN);
3284 memcpy_toio(hw->regs + B2_MAC_1 + port*8,
3285 dev->dev_addr, ETH_ALEN);
3286 memcpy_toio(hw->regs + B2_MAC_2 + port*8,
3287 dev->dev_addr, ETH_ALEN);
3288 3284
3289 if (hw->chip_id == CHIP_ID_GENESIS) 3285 /* disable Rx */
3290 xm_outaddr(hw, port, XM_SA, dev->dev_addr); 3286 ctrl = gma_read16(hw, port, GM_GP_CTRL);
3291 else { 3287 gma_write16(hw, port, GM_GP_CTRL, ctrl & ~GM_GPCR_RX_ENA);
3292 gma_set_addr(hw, port, GM_SRC_ADDR_1L, dev->dev_addr); 3288
3293 gma_set_addr(hw, port, GM_SRC_ADDR_2L, dev->dev_addr); 3289 memcpy_toio(hw->regs + B2_MAC_1 + port*8, dev->dev_addr, ETH_ALEN);
3290 memcpy_toio(hw->regs + B2_MAC_2 + port*8, dev->dev_addr, ETH_ALEN);
3291
3292 if (netif_running(dev)) {
3293 if (hw->chip_id == CHIP_ID_GENESIS)
3294 xm_outaddr(hw, port, XM_SA, dev->dev_addr);
3295 else {
3296 gma_set_addr(hw, port, GM_SRC_ADDR_1L, dev->dev_addr);
3297 gma_set_addr(hw, port, GM_SRC_ADDR_2L, dev->dev_addr);
3298 }
3294 } 3299 }
3295 mutex_unlock(&hw->phy_mutex); 3300
3301 gma_write16(hw, port, GM_GP_CTRL, ctrl);
3296 3302
3297 return 0; 3303 return 0;
3298} 3304}