diff options
author | Stephen Hemminger <shemminger@linux-foundation.org> | 2007-03-12 18:16:26 -0400 |
---|---|---|
committer | Jeff Garzik <jeff@garzik.org> | 2007-03-15 10:44:32 -0400 |
commit | 2eb3e621c4e07e9e7200dbb66f0433b4caafb8e7 (patch) | |
tree | 076526c36ade3c7c8a5e118c5210e14db96f22de /drivers/net/skge.c | |
parent | 8ce5e3e45e01ffab38a9f03900181132b9068543 (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.c | 28 |
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 | } |