diff options
author | anirban ray <aray@nvidia.com> | 2016-04-05 14:10:23 -0400 |
---|---|---|
committer | Sumeet Gupta <sumeetg@nvidia.com> | 2016-05-02 14:43:59 -0400 |
commit | fb9d5a99c17e17ef84dee85f529e3800a98ee796 (patch) | |
tree | e1f2ac344b512d01adb9b80c224306492080eb3f /drivers/net | |
parent | dca9a6d0f095cd526fc8bb8ca080acc51403c013 (diff) |
net:eqos: Check power state in thermal and PHY API
Bug 200186948
Change-Id: I5912c22d449f47c709da82b540471b88dc2be487
Signed-off-by: anirban ray <aray@nvidia.com>
Reviewed-on: http://git-master/r/1120502
Reviewed-by: Automatic_Commit_Validation_User
Reviewed-by: David Lim <dlim@nvidia.com>
GVS: Gerrit_Virtual_Submit
Reviewed-by: Sumeet Gupta <sumeetg@nvidia.com>
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/ethernet/nvidia/eqos/init.c | 61 | ||||
-rw-r--r-- | drivers/net/ethernet/nvidia/eqos/mdio.c | 49 |
2 files changed, 79 insertions, 31 deletions
diff --git a/drivers/net/ethernet/nvidia/eqos/init.c b/drivers/net/ethernet/nvidia/eqos/init.c index 4867dd4aa..86fb73c95 100644 --- a/drivers/net/ethernet/nvidia/eqos/init.c +++ b/drivers/net/ethernet/nvidia/eqos/init.c | |||
@@ -581,7 +581,11 @@ static int tegra_eqos_max_state(struct thermal_cooling_device *tcd, | |||
581 | unsigned long *state) | 581 | unsigned long *state) |
582 | { | 582 | { |
583 | struct eqos_prv_data *pdata = tcd->devdata; | 583 | struct eqos_prv_data *pdata = tcd->devdata; |
584 | 584 | /* | |
585 | * NOTE: There is no locking here. Therefore any HW manipulation code | ||
586 | * added in the future will need to employ concurrency control just | ||
587 | * like tegra_eqos_set_state() | ||
588 | */ | ||
585 | pr_info("%s state=%d\n", __func__, pdata->therm_state.counter); | 589 | pr_info("%s state=%d\n", __func__, pdata->therm_state.counter); |
586 | *state = TEGRA_EQOS_THERM_MAX_STATE; | 590 | *state = TEGRA_EQOS_THERM_MAX_STATE; |
587 | 591 | ||
@@ -593,6 +597,11 @@ static int tegra_eqos_cur_state(struct thermal_cooling_device *tcd, | |||
593 | { | 597 | { |
594 | struct eqos_prv_data *pdata = tcd->devdata; | 598 | struct eqos_prv_data *pdata = tcd->devdata; |
595 | 599 | ||
600 | /* | ||
601 | * NOTE: There is no locking here. Therefore any HW manipulation code | ||
602 | * added in the future will need to employ concurrency control just | ||
603 | * like tegra_eqos_set_state() | ||
604 | */ | ||
596 | pr_info("%s state=%d\n", __func__, pdata->therm_state.counter); | 605 | pr_info("%s state=%d\n", __func__, pdata->therm_state.counter); |
597 | *state = (unsigned long)atomic_read(&pdata->therm_state); | 606 | *state = (unsigned long)atomic_read(&pdata->therm_state); |
598 | 607 | ||
@@ -604,6 +613,17 @@ static int tegra_eqos_set_state(struct thermal_cooling_device *tcd, | |||
604 | { | 613 | { |
605 | struct eqos_prv_data *pdata = tcd->devdata; | 614 | struct eqos_prv_data *pdata = tcd->devdata; |
606 | struct hw_if_struct *hw_if = &(pdata->hw_if); | 615 | struct hw_if_struct *hw_if = &(pdata->hw_if); |
616 | int hw_chg_count; | ||
617 | |||
618 | hw_chg_count = EQOS_HW_CHG_MAX_COUNT; | ||
619 | while (test_and_set_bit(HW_CHANGING, &pdata->hw_state_flgs) && | ||
620 | hw_chg_count--) | ||
621 | usleep_range(20000, 40000); | ||
622 | |||
623 | if (pdata->suspended || hw_chg_count == 0) { | ||
624 | clear_bit(HW_CHANGING, &pdata->hw_state_flgs); | ||
625 | return -ENODEV; | ||
626 | } | ||
607 | 627 | ||
608 | pr_info("%s cur state=%d new state=%ld, recalibrating eqos pads\n", | 628 | pr_info("%s cur state=%d new state=%ld, recalibrating eqos pads\n", |
609 | __func__, pdata->therm_state.counter, state); | 629 | __func__, pdata->therm_state.counter, state); |
@@ -621,6 +641,8 @@ static int tegra_eqos_set_state(struct thermal_cooling_device *tcd, | |||
621 | /* read-to-clear error counters */ | 641 | /* read-to-clear error counters */ |
622 | hw_if->read_err_counter(pdata, false); | 642 | hw_if->read_err_counter(pdata, false); |
623 | 643 | ||
644 | clear_bit(HW_CHANGING, &pdata->hw_state_flgs); | ||
645 | |||
624 | return 0; | 646 | return 0; |
625 | } | 647 | } |
626 | 648 | ||
@@ -1247,27 +1269,6 @@ static void eqos_shutdown(struct platform_device *pdev) | |||
1247 | return; | 1269 | return; |
1248 | } | 1270 | } |
1249 | 1271 | ||
1250 | #if 0 | ||
1251 | static INT eqos_suspend_late(struct platform_device *pdev, pm_message_t state) | ||
1252 | { | ||
1253 | pr_err("-->eqos_suspend_late\n"); | ||
1254 | pr_err("Handle the suspend_late\n"); | ||
1255 | pr_err("<--eqos_suspend_late\n"); | ||
1256 | |||
1257 | return 0; | ||
1258 | } | ||
1259 | |||
1260 | static INT eqos_resume_early(struct platform_device *pdev) | ||
1261 | { | ||
1262 | pr_err("-->eqos_resume_early\n"); | ||
1263 | pr_err("Handle the resume_early\n"); | ||
1264 | pr_err("<--eqos_resume_early\n"); | ||
1265 | |||
1266 | return 0; | ||
1267 | } | ||
1268 | |||
1269 | #endif | ||
1270 | |||
1271 | #ifdef CONFIG_PM | 1272 | #ifdef CONFIG_PM |
1272 | 1273 | ||
1273 | /*! | 1274 | /*! |
@@ -1289,18 +1290,19 @@ static INT eqos_suspend(struct platform_device *pdev, pm_message_t state) | |||
1289 | struct net_device *dev = platform_get_drvdata(pdev); | 1290 | struct net_device *dev = platform_get_drvdata(pdev); |
1290 | struct eqos_prv_data *pdata = netdev_priv(dev); | 1291 | struct eqos_prv_data *pdata = netdev_priv(dev); |
1291 | 1292 | ||
1293 | while (test_and_set_bit(HW_CHANGING, &pdata->hw_state_flgs)) | ||
1294 | usleep_range(1000, 2000); | ||
1295 | |||
1292 | if (pdata->suspended) { | 1296 | if (pdata->suspended) { |
1297 | clear_bit(HW_CHANGING, &pdata->hw_state_flgs); | ||
1293 | pr_err("eqos already suspended\n"); | 1298 | pr_err("eqos already suspended\n"); |
1294 | return -EINVAL; | 1299 | return -EINVAL; |
1295 | } | 1300 | } |
1296 | pdata->suspended = 1; | ||
1297 | 1301 | ||
1302 | pdata->suspended = 1; | ||
1298 | if (netif_running(dev)) { | 1303 | if (netif_running(dev)) { |
1299 | while (test_and_set_bit(HW_CHANGING, &pdata->hw_state_flgs)) | ||
1300 | usleep_range(1000, 2000); | ||
1301 | eqos_stop_dev(pdata); | 1304 | eqos_stop_dev(pdata); |
1302 | pdata->hw_state_flgs |= (1 << HW_STOPPED); | 1305 | pdata->hw_state_flgs |= (1 << HW_STOPPED); |
1303 | clear_bit(HW_CHANGING, &pdata->hw_state_flgs); | ||
1304 | } | 1306 | } |
1305 | 1307 | ||
1306 | /* disable clocks */ | 1308 | /* disable clocks */ |
@@ -1308,6 +1310,8 @@ static INT eqos_suspend(struct platform_device *pdev, pm_message_t state) | |||
1308 | /* disable regulators */ | 1310 | /* disable regulators */ |
1309 | eqos_regulator_deinit(pdata); | 1311 | eqos_regulator_deinit(pdata); |
1310 | 1312 | ||
1313 | clear_bit(HW_CHANGING, &pdata->hw_state_flgs); | ||
1314 | |||
1311 | return 0; | 1315 | return 0; |
1312 | } | 1316 | } |
1313 | 1317 | ||
@@ -1330,7 +1334,10 @@ static INT eqos_resume(struct platform_device *pdev) | |||
1330 | struct net_device *dev = platform_get_drvdata(pdev); | 1334 | struct net_device *dev = platform_get_drvdata(pdev); |
1331 | struct eqos_prv_data *pdata = netdev_priv(dev); | 1335 | struct eqos_prv_data *pdata = netdev_priv(dev); |
1332 | 1336 | ||
1337 | while (test_and_set_bit(HW_CHANGING, &pdata->hw_state_flgs)) | ||
1338 | usleep_range(1000, 2000); | ||
1333 | if (!pdata->suspended) { | 1339 | if (!pdata->suspended) { |
1340 | clear_bit(HW_CHANGING, &pdata->hw_state_flgs); | ||
1334 | pr_err("eqos already resumed\n"); | 1341 | pr_err("eqos already resumed\n"); |
1335 | return -EINVAL; | 1342 | return -EINVAL; |
1336 | } | 1343 | } |
@@ -1346,6 +1353,8 @@ static INT eqos_resume(struct platform_device *pdev) | |||
1346 | pdata->suspended = 0; | 1353 | pdata->suspended = 0; |
1347 | pdata->hw_state_flgs &= ~(1 << HW_STOPPED); | 1354 | pdata->hw_state_flgs &= ~(1 << HW_STOPPED); |
1348 | 1355 | ||
1356 | clear_bit(HW_CHANGING, &pdata->hw_state_flgs); | ||
1357 | |||
1349 | return 0; | 1358 | return 0; |
1350 | } | 1359 | } |
1351 | 1360 | ||
diff --git a/drivers/net/ethernet/nvidia/eqos/mdio.c b/drivers/net/ethernet/nvidia/eqos/mdio.c index 3312c6fa7..16835db20 100644 --- a/drivers/net/ethernet/nvidia/eqos/mdio.c +++ b/drivers/net/ethernet/nvidia/eqos/mdio.c | |||
@@ -30,7 +30,7 @@ | |||
30 | * ========================================================================= | 30 | * ========================================================================= |
31 | */ | 31 | */ |
32 | /* | 32 | /* |
33 | * Copyright (c) 2015, NVIDIA CORPORATION. All rights reserved. | 33 | * Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved. |
34 | * | 34 | * |
35 | * This program is free software; you can redistribute it and/or modify it | 35 | * This program is free software; you can redistribute it and/or modify it |
36 | * under the terms and conditions of the GNU General Public License, | 36 | * under the terms and conditions of the GNU General Public License, |
@@ -70,10 +70,19 @@ INT eqos_mdio_read_direct(struct eqos_prv_data *pdata, | |||
70 | { | 70 | { |
71 | struct hw_if_struct *hw_if = &(pdata->hw_if); | 71 | struct hw_if_struct *hw_if = &(pdata->hw_if); |
72 | int phy_reg_read_status; | 72 | int phy_reg_read_status; |
73 | int hw_chg_count; | ||
73 | 74 | ||
74 | DBGPR_MDIO("--> eqos_mdio_read_direct\n"); | 75 | DBGPR_MDIO("--> eqos_mdio_read_direct\n"); |
75 | if (pdata->suspended) | 76 | |
77 | hw_chg_count = EQOS_HW_CHG_MAX_COUNT; | ||
78 | while (test_and_set_bit(HW_CHANGING, &pdata->hw_state_flgs) && | ||
79 | hw_chg_count--) | ||
80 | usleep_range(20000, 40000); | ||
81 | |||
82 | if (pdata->suspended || hw_chg_count == 0) { | ||
83 | clear_bit(HW_CHANGING, &pdata->hw_state_flgs); | ||
76 | return -ENODEV; | 84 | return -ENODEV; |
85 | } | ||
77 | 86 | ||
78 | if (hw_if->read_phy_regs) { | 87 | if (hw_if->read_phy_regs) { |
79 | phy_reg_read_status = | 88 | phy_reg_read_status = |
@@ -83,8 +92,8 @@ INT eqos_mdio_read_direct(struct eqos_prv_data *pdata, | |||
83 | pr_err("%s: hw_if->read_phy_regs not defined", DEV_NAME); | 92 | pr_err("%s: hw_if->read_phy_regs not defined", DEV_NAME); |
84 | } | 93 | } |
85 | 94 | ||
95 | clear_bit(HW_CHANGING, &pdata->hw_state_flgs); | ||
86 | DBGPR_MDIO("<-- eqos_mdio_read_direct\n"); | 96 | DBGPR_MDIO("<-- eqos_mdio_read_direct\n"); |
87 | |||
88 | return phy_reg_read_status; | 97 | return phy_reg_read_status; |
89 | } | 98 | } |
90 | 99 | ||
@@ -111,9 +120,17 @@ INT eqos_mdio_write_direct(struct eqos_prv_data *pdata, | |||
111 | { | 120 | { |
112 | struct hw_if_struct *hw_if = &(pdata->hw_if); | 121 | struct hw_if_struct *hw_if = &(pdata->hw_if); |
113 | int phy_reg_write_status; | 122 | int phy_reg_write_status; |
123 | int hw_chg_count; | ||
114 | 124 | ||
115 | if (pdata->suspended) | 125 | hw_chg_count = EQOS_HW_CHG_MAX_COUNT; |
126 | while (test_and_set_bit(HW_CHANGING, &pdata->hw_state_flgs) && | ||
127 | hw_chg_count--) | ||
128 | usleep_range(20000, 40000); | ||
129 | |||
130 | if (pdata->suspended || hw_chg_count == 0) { | ||
131 | clear_bit(HW_CHANGING, &pdata->hw_state_flgs); | ||
116 | return -ENODEV; | 132 | return -ENODEV; |
133 | } | ||
117 | 134 | ||
118 | DBGPR_MDIO("--> eqos_mdio_write_direct\n"); | 135 | DBGPR_MDIO("--> eqos_mdio_write_direct\n"); |
119 | 136 | ||
@@ -125,8 +142,8 @@ INT eqos_mdio_write_direct(struct eqos_prv_data *pdata, | |||
125 | pr_err("%s: hw_if->write_phy_regs not defined", DEV_NAME); | 142 | pr_err("%s: hw_if->write_phy_regs not defined", DEV_NAME); |
126 | } | 143 | } |
127 | 144 | ||
145 | clear_bit(HW_CHANGING, &pdata->hw_state_flgs); | ||
128 | DBGPR_MDIO("<-- eqos_mdio_write_direct\n"); | 146 | DBGPR_MDIO("<-- eqos_mdio_write_direct\n"); |
129 | |||
130 | return phy_reg_write_status; | 147 | return phy_reg_write_status; |
131 | } | 148 | } |
132 | 149 | ||
@@ -151,10 +168,20 @@ static INT eqos_mdio_read(struct mii_bus *bus, int phyaddr, int phyreg) | |||
151 | struct eqos_prv_data *pdata = netdev_priv(dev); | 168 | struct eqos_prv_data *pdata = netdev_priv(dev); |
152 | struct hw_if_struct *hw_if = &(pdata->hw_if); | 169 | struct hw_if_struct *hw_if = &(pdata->hw_if); |
153 | int phydata = 0; | 170 | int phydata = 0; |
171 | int hw_chg_count; | ||
154 | 172 | ||
155 | DBGPR_MDIO("--> eqos_mdio_read: phyaddr = %d, phyreg = %d\n", | 173 | DBGPR_MDIO("--> eqos_mdio_read: phyaddr = %d, phyreg = %d\n", |
156 | phyaddr, phyreg); | 174 | phyaddr, phyreg); |
157 | 175 | ||
176 | hw_chg_count = EQOS_HW_CHG_MAX_COUNT; | ||
177 | if (test_and_set_bit(HW_CHANGING, &pdata->hw_state_flgs)) | ||
178 | return -ENODEV; | ||
179 | |||
180 | if (pdata->suspended) { | ||
181 | clear_bit(HW_CHANGING, &pdata->hw_state_flgs); | ||
182 | return -ENODEV; | ||
183 | } | ||
184 | |||
158 | if (hw_if->read_phy_regs) | 185 | if (hw_if->read_phy_regs) |
159 | hw_if->read_phy_regs(phyaddr, phyreg, &phydata); | 186 | hw_if->read_phy_regs(phyaddr, phyreg, &phydata); |
160 | else | 187 | else |
@@ -162,6 +189,7 @@ static INT eqos_mdio_read(struct mii_bus *bus, int phyaddr, int phyreg) | |||
162 | 189 | ||
163 | DBGPR_MDIO("<-- eqos_mdio_read: phydata = %#x\n", phydata); | 190 | DBGPR_MDIO("<-- eqos_mdio_read: phydata = %#x\n", phydata); |
164 | 191 | ||
192 | clear_bit(HW_CHANGING, &pdata->hw_state_flgs); | ||
165 | return phydata; | 193 | return phydata; |
166 | } | 194 | } |
167 | 195 | ||
@@ -187,8 +215,18 @@ static INT eqos_mdio_write(struct mii_bus *bus, int phyaddr, int phyreg, | |||
187 | struct eqos_prv_data *pdata = netdev_priv(dev); | 215 | struct eqos_prv_data *pdata = netdev_priv(dev); |
188 | struct hw_if_struct *hw_if = &(pdata->hw_if); | 216 | struct hw_if_struct *hw_if = &(pdata->hw_if); |
189 | INT ret = Y_SUCCESS; | 217 | INT ret = Y_SUCCESS; |
218 | int hw_chg_count; | ||
190 | 219 | ||
191 | DBGPR_MDIO("--> eqos_mdio_write\n"); | 220 | DBGPR_MDIO("--> eqos_mdio_write\n"); |
221 | hw_chg_count = EQOS_HW_CHG_MAX_COUNT; | ||
222 | while (test_and_set_bit(HW_CHANGING, &pdata->hw_state_flgs) && | ||
223 | hw_chg_count--) | ||
224 | usleep_range(20000, 40000); | ||
225 | |||
226 | if (pdata->suspended || hw_chg_count == 0) { | ||
227 | clear_bit(HW_CHANGING, &pdata->hw_state_flgs); | ||
228 | return -ENODEV; | ||
229 | } | ||
192 | 230 | ||
193 | if (hw_if->write_phy_regs) { | 231 | if (hw_if->write_phy_regs) { |
194 | hw_if->write_phy_regs(phyaddr, phyreg, phydata); | 232 | hw_if->write_phy_regs(phyaddr, phyreg, phydata); |
@@ -199,6 +237,7 @@ static INT eqos_mdio_write(struct mii_bus *bus, int phyaddr, int phyreg, | |||
199 | 237 | ||
200 | DBGPR_MDIO("<-- eqos_mdio_write\n"); | 238 | DBGPR_MDIO("<-- eqos_mdio_write\n"); |
201 | 239 | ||
240 | clear_bit(HW_CHANGING, &pdata->hw_state_flgs); | ||
202 | return ret; | 241 | return ret; |
203 | } | 242 | } |
204 | 243 | ||