tg3: Request APE_LOCK_PHY before PHY access
authorMichael Chan <mchan@broadcom.com>
Sun, 29 Jul 2012 19:15:41 +0000 (19:15 +0000)
committerDavid S. Miller <davem@davemloft.net>
Mon, 30 Jul 2012 06:18:31 +0000 (23:18 -0700)
to prevent PHY access conflict with APE firmware.

Signed-off-by: Michael Chan <mchan@broadcom.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/broadcom/tg3.c
drivers/net/ethernet/broadcom/tg3.h

index 9a009fd6ea1b716418d3ad85fd72b4c72254be2e..a528f9a6a8932778320a7ab5561d4f67ba3626a1 100644 (file)
@@ -672,6 +672,12 @@ static int tg3_ape_lock(struct tg3 *tp, int locknum)
                else
                        bit = 1 << tp->pci_fn;
                break;
+       case TG3_APE_LOCK_PHY0:
+       case TG3_APE_LOCK_PHY1:
+       case TG3_APE_LOCK_PHY2:
+       case TG3_APE_LOCK_PHY3:
+               bit = APE_LOCK_REQ_DRIVER;
+               break;
        default:
                return -EINVAL;
        }
@@ -723,6 +729,12 @@ static void tg3_ape_unlock(struct tg3 *tp, int locknum)
                else
                        bit = 1 << tp->pci_fn;
                break;
+       case TG3_APE_LOCK_PHY0:
+       case TG3_APE_LOCK_PHY1:
+       case TG3_APE_LOCK_PHY2:
+       case TG3_APE_LOCK_PHY3:
+               bit = APE_LOCK_GRANT_DRIVER;
+               break;
        default:
                return;
        }
@@ -1052,6 +1064,8 @@ static int tg3_readphy(struct tg3 *tp, int reg, u32 *val)
                udelay(80);
        }
 
+       tg3_ape_lock(tp, tp->phy_ape_lock);
+
        *val = 0x0;
 
        frame_val  = ((tp->phy_addr << MI_COM_PHY_ADDR_SHIFT) &
@@ -1086,6 +1100,8 @@ static int tg3_readphy(struct tg3 *tp, int reg, u32 *val)
                udelay(80);
        }
 
+       tg3_ape_unlock(tp, tp->phy_ape_lock);
+
        return ret;
 }
 
@@ -1105,6 +1121,8 @@ static int tg3_writephy(struct tg3 *tp, int reg, u32 val)
                udelay(80);
        }
 
+       tg3_ape_lock(tp, tp->phy_ape_lock);
+
        frame_val  = ((tp->phy_addr << MI_COM_PHY_ADDR_SHIFT) &
                      MI_COM_PHY_ADDR_MASK);
        frame_val |= ((reg << MI_COM_REG_ADDR_SHIFT) &
@@ -1135,6 +1153,8 @@ static int tg3_writephy(struct tg3 *tp, int reg, u32 val)
                udelay(80);
        }
 
+       tg3_ape_unlock(tp, tp->phy_ape_lock);
+
        return ret;
 }
 
@@ -13648,6 +13668,23 @@ static int __devinit tg3_phy_probe(struct tg3 *tp)
        tg3_flag_set(tp, PAUSE_AUTONEG);
        tp->link_config.flowctrl = FLOW_CTRL_TX | FLOW_CTRL_RX;
 
+       if (tg3_flag(tp, ENABLE_APE)) {
+               switch (tp->pci_fn) {
+               case 0:
+                       tp->phy_ape_lock = TG3_APE_LOCK_PHY0;
+                       break;
+               case 1:
+                       tp->phy_ape_lock = TG3_APE_LOCK_PHY1;
+                       break;
+               case 2:
+                       tp->phy_ape_lock = TG3_APE_LOCK_PHY2;
+                       break;
+               case 3:
+                       tp->phy_ape_lock = TG3_APE_LOCK_PHY3;
+                       break;
+               }
+       }
+
        if (tg3_flag(tp, USE_PHYLIB))
                return tg3_phy_init(tp);
 
index a1b75cd67b9d715859460bfcfdcd64afa9d8b8b0..6fb45a5000328d8edef2b0c36b1ed5d9be593637 100644 (file)
@@ -3107,6 +3107,7 @@ struct tg3 {
        int                             old_link;
 
        u8                              phy_addr;
+       u8                              phy_ape_lock;
 
        /* PHY info */
        u32                             phy_id;