diff options
author | Huang, Xiong <xiong@qca.qualcomm.com> | 2012-04-18 18:01:22 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2012-04-19 20:14:19 -0400 |
commit | 969a7ee2a8398fb705f9836dc11d9e307d3ac89c (patch) | |
tree | 5925795988ab2a2b6ca05ecc2d26e4305b115b1a | |
parent | 9c5282180bab47991f45fe561d5340847fef2bd9 (diff) |
atl1c: add module parameter for l1c_wait_until_idle
l1c_wait_until_idle is called for serval modules (TXQ/RXQ/TXMAC/RXMAC).
specific moudle have specific idle/busy status in reg REG_IDLE_STATUS.
the previous code return wrongly if all modules are in idle status,
regardless the 'stop' action is applied on individual module.
Refine the reg REG_IDLE_STATUS definition as well.
Signed-off-by: xiong <xiong@qca.qualcomm.com>
Tested-by: Liu David <dwliu@qca.qualcomm.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | drivers/net/ethernet/atheros/atl1c/atl1c_hw.h | 28 | ||||
-rw-r--r-- | drivers/net/ethernet/atheros/atl1c/atl1c_main.c | 11 |
2 files changed, 24 insertions, 15 deletions
diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c_hw.h b/drivers/net/ethernet/atheros/atl1c/atl1c_hw.h index a37c82f14bb2..c1aa3ba7545b 100644 --- a/drivers/net/ethernet/atheros/atl1c/atl1c_hw.h +++ b/drivers/net/ethernet/atheros/atl1c/atl1c_hw.h | |||
@@ -227,17 +227,25 @@ int atl1c_phy_power_saving(struct atl1c_hw *hw); | |||
227 | GPHY_CTRL_HIB_PULSE |\ | 227 | GPHY_CTRL_HIB_PULSE |\ |
228 | GPHY_CTRL_PWDOWN_HW |\ | 228 | GPHY_CTRL_PWDOWN_HW |\ |
229 | GPHY_CTRL_PHY_IDDQ) | 229 | GPHY_CTRL_PHY_IDDQ) |
230 | |||
230 | /* Block IDLE Status Register */ | 231 | /* Block IDLE Status Register */ |
231 | #define REG_IDLE_STATUS 0x1410 | 232 | #define REG_IDLE_STATUS 0x1410 |
232 | #define IDLE_STATUS_MASK 0x00FF | 233 | #define IDLE_STATUS_SFORCE_MASK 0xFUL |
233 | #define IDLE_STATUS_RXMAC_NO_IDLE 0x1 | 234 | #define IDLE_STATUS_SFORCE_SHIFT 14 |
234 | #define IDLE_STATUS_TXMAC_NO_IDLE 0x2 | 235 | #define IDLE_STATUS_CALIB_DONE BIT(13) |
235 | #define IDLE_STATUS_RXQ_NO_IDLE 0x4 | 236 | #define IDLE_STATUS_CALIB_RES_MASK 0x1FUL |
236 | #define IDLE_STATUS_TXQ_NO_IDLE 0x8 | 237 | #define IDLE_STATUS_CALIB_RES_SHIFT 8 |
237 | #define IDLE_STATUS_DMAR_NO_IDLE 0x10 | 238 | #define IDLE_STATUS_CALIBERR_MASK 0xFUL |
238 | #define IDLE_STATUS_DMAW_NO_IDLE 0x20 | 239 | #define IDLE_STATUS_CALIBERR_SHIFT 4 |
239 | #define IDLE_STATUS_SMB_NO_IDLE 0x40 | 240 | #define IDLE_STATUS_TXQ_BUSY BIT(3) |
240 | #define IDLE_STATUS_CMB_NO_IDLE 0x80 | 241 | #define IDLE_STATUS_RXQ_BUSY BIT(2) |
242 | #define IDLE_STATUS_TXMAC_BUSY BIT(1) | ||
243 | #define IDLE_STATUS_RXMAC_BUSY BIT(0) | ||
244 | #define IDLE_STATUS_MASK (\ | ||
245 | IDLE_STATUS_TXQ_BUSY |\ | ||
246 | IDLE_STATUS_RXQ_BUSY |\ | ||
247 | IDLE_STATUS_TXMAC_BUSY |\ | ||
248 | IDLE_STATUS_RXMAC_BUSY) | ||
241 | 249 | ||
242 | /* MDIO Control Register */ | 250 | /* MDIO Control Register */ |
243 | #define REG_MDIO_CTRL 0x1414 | 251 | #define REG_MDIO_CTRL 0x1414 |
diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c index 2e1c9f39ff99..d2f89f026d70 100644 --- a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c +++ b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c | |||
@@ -185,14 +185,14 @@ static inline void atl1c_irq_reset(struct atl1c_adapter *adapter) | |||
185 | * atl1c_wait_until_idle - wait up to AT_HW_MAX_IDLE_DELAY reads | 185 | * atl1c_wait_until_idle - wait up to AT_HW_MAX_IDLE_DELAY reads |
186 | * of the idle status register until the device is actually idle | 186 | * of the idle status register until the device is actually idle |
187 | */ | 187 | */ |
188 | static u32 atl1c_wait_until_idle(struct atl1c_hw *hw) | 188 | static u32 atl1c_wait_until_idle(struct atl1c_hw *hw, u32 modu_ctrl) |
189 | { | 189 | { |
190 | int timeout; | 190 | int timeout; |
191 | u32 data; | 191 | u32 data; |
192 | 192 | ||
193 | for (timeout = 0; timeout < AT_HW_MAX_IDLE_DELAY; timeout++) { | 193 | for (timeout = 0; timeout < AT_HW_MAX_IDLE_DELAY; timeout++) { |
194 | AT_READ_REG(hw, REG_IDLE_STATUS, &data); | 194 | AT_READ_REG(hw, REG_IDLE_STATUS, &data); |
195 | if ((data & IDLE_STATUS_MASK) == 0) | 195 | if ((data & modu_ctrl) == 0) |
196 | return 0; | 196 | return 0; |
197 | msleep(1); | 197 | msleep(1); |
198 | } | 198 | } |
@@ -1119,13 +1119,14 @@ static int atl1c_stop_mac(struct atl1c_hw *hw) | |||
1119 | data &= ~TXQ_CTRL_EN; | 1119 | data &= ~TXQ_CTRL_EN; |
1120 | AT_WRITE_REG(hw, REG_TXQ_CTRL, data); | 1120 | AT_WRITE_REG(hw, REG_TXQ_CTRL, data); |
1121 | 1121 | ||
1122 | atl1c_wait_until_idle(hw); | 1122 | atl1c_wait_until_idle(hw, IDLE_STATUS_RXQ_BUSY | IDLE_STATUS_TXQ_BUSY); |
1123 | 1123 | ||
1124 | AT_READ_REG(hw, REG_MAC_CTRL, &data); | 1124 | AT_READ_REG(hw, REG_MAC_CTRL, &data); |
1125 | data &= ~(MAC_CTRL_TX_EN | MAC_CTRL_RX_EN); | 1125 | data &= ~(MAC_CTRL_TX_EN | MAC_CTRL_RX_EN); |
1126 | AT_WRITE_REG(hw, REG_MAC_CTRL, data); | 1126 | AT_WRITE_REG(hw, REG_MAC_CTRL, data); |
1127 | 1127 | ||
1128 | return (int)atl1c_wait_until_idle(hw); | 1128 | return (int)atl1c_wait_until_idle(hw, |
1129 | IDLE_STATUS_TXMAC_BUSY | IDLE_STATUS_RXMAC_BUSY); | ||
1129 | } | 1130 | } |
1130 | 1131 | ||
1131 | static void atl1c_enable_rx_ctrl(struct atl1c_hw *hw) | 1132 | static void atl1c_enable_rx_ctrl(struct atl1c_hw *hw) |
@@ -1176,7 +1177,7 @@ static int atl1c_reset_mac(struct atl1c_hw *hw) | |||
1176 | msleep(10); | 1177 | msleep(10); |
1177 | /* Wait at least 10ms for All module to be Idle */ | 1178 | /* Wait at least 10ms for All module to be Idle */ |
1178 | 1179 | ||
1179 | if (atl1c_wait_until_idle(hw)) { | 1180 | if (atl1c_wait_until_idle(hw, IDLE_STATUS_MASK)) { |
1180 | dev_err(&pdev->dev, | 1181 | dev_err(&pdev->dev, |
1181 | "MAC state machine can't be idle since" | 1182 | "MAC state machine can't be idle since" |
1182 | " disabled for 10ms second\n"); | 1183 | " disabled for 10ms second\n"); |