aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHuang, Xiong <xiong@qca.qualcomm.com>2012-04-18 18:01:22 -0400
committerDavid S. Miller <davem@davemloft.net>2012-04-19 20:14:19 -0400
commit969a7ee2a8398fb705f9836dc11d9e307d3ac89c (patch)
tree5925795988ab2a2b6ca05ecc2d26e4305b115b1a
parent9c5282180bab47991f45fe561d5340847fef2bd9 (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.h28
-rw-r--r--drivers/net/ethernet/atheros/atl1c/atl1c_main.c11
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 */
188static u32 atl1c_wait_until_idle(struct atl1c_hw *hw) 188static 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
1131static void atl1c_enable_rx_ctrl(struct atl1c_hw *hw) 1132static 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");