diff options
author | Alexander Duyck <alexander.h.duyck@intel.com> | 2009-10-05 02:32:27 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-10-06 17:59:18 -0400 |
commit | bf6f7a928d313ddecb0a16ea60fa6b45ac1414a7 (patch) | |
tree | e26e506f81bb02deab334b600930dd86b337fabc /drivers/net/igb/e1000_82575.c | |
parent | 008c3422d48b217792789bdea822dbc2efe2165c (diff) |
igb: add locking to reads of the i2c interface
The current implementation of sgmii support isn't correctly locking the
interfaces for reads/writes. This change pulls the read/write
functionality out of 82575.c and moves it to phy.c. In addition it
replaces the implementation in 82575.c with one that uses locking around
the relocated i2c interface calls.
Signed-off-by: Alexander Duyck <alexander.h.duyck@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/igb/e1000_82575.c')
-rw-r--r-- | drivers/net/igb/e1000_82575.c | 85 |
1 files changed, 20 insertions, 65 deletions
diff --git a/drivers/net/igb/e1000_82575.c b/drivers/net/igb/e1000_82575.c index 65b900028bca..78971815bbce 100644 --- a/drivers/net/igb/e1000_82575.c +++ b/drivers/net/igb/e1000_82575.c | |||
@@ -277,45 +277,23 @@ static void igb_release_phy_82575(struct e1000_hw *hw) | |||
277 | static s32 igb_read_phy_reg_sgmii_82575(struct e1000_hw *hw, u32 offset, | 277 | static s32 igb_read_phy_reg_sgmii_82575(struct e1000_hw *hw, u32 offset, |
278 | u16 *data) | 278 | u16 *data) |
279 | { | 279 | { |
280 | struct e1000_phy_info *phy = &hw->phy; | 280 | s32 ret_val = -E1000_ERR_PARAM; |
281 | u32 i, i2ccmd = 0; | ||
282 | 281 | ||
283 | if (offset > E1000_MAX_SGMII_PHY_REG_ADDR) { | 282 | if (offset > E1000_MAX_SGMII_PHY_REG_ADDR) { |
284 | hw_dbg("PHY Address %u is out of range\n", offset); | 283 | hw_dbg("PHY Address %u is out of range\n", offset); |
285 | return -E1000_ERR_PARAM; | 284 | goto out; |
286 | } | 285 | } |
287 | 286 | ||
288 | /* | 287 | ret_val = hw->phy.ops.acquire(hw); |
289 | * Set up Op-code, Phy Address, and register address in the I2CCMD | 288 | if (ret_val) |
290 | * register. The MAC will take care of interfacing with the | 289 | goto out; |
291 | * PHY to retrieve the desired data. | ||
292 | */ | ||
293 | i2ccmd = ((offset << E1000_I2CCMD_REG_ADDR_SHIFT) | | ||
294 | (phy->addr << E1000_I2CCMD_PHY_ADDR_SHIFT) | | ||
295 | (E1000_I2CCMD_OPCODE_READ)); | ||
296 | 290 | ||
297 | wr32(E1000_I2CCMD, i2ccmd); | 291 | ret_val = igb_read_phy_reg_i2c(hw, offset, data); |
298 | 292 | ||
299 | /* Poll the ready bit to see if the I2C read completed */ | 293 | hw->phy.ops.release(hw); |
300 | for (i = 0; i < E1000_I2CCMD_PHY_TIMEOUT; i++) { | ||
301 | udelay(50); | ||
302 | i2ccmd = rd32(E1000_I2CCMD); | ||
303 | if (i2ccmd & E1000_I2CCMD_READY) | ||
304 | break; | ||
305 | } | ||
306 | if (!(i2ccmd & E1000_I2CCMD_READY)) { | ||
307 | hw_dbg("I2CCMD Read did not complete\n"); | ||
308 | return -E1000_ERR_PHY; | ||
309 | } | ||
310 | if (i2ccmd & E1000_I2CCMD_ERROR) { | ||
311 | hw_dbg("I2CCMD Error bit set\n"); | ||
312 | return -E1000_ERR_PHY; | ||
313 | } | ||
314 | |||
315 | /* Need to byte-swap the 16-bit value. */ | ||
316 | *data = ((i2ccmd >> 8) & 0x00FF) | ((i2ccmd << 8) & 0xFF00); | ||
317 | 294 | ||
318 | return 0; | 295 | out: |
296 | return ret_val; | ||
319 | } | 297 | } |
320 | 298 | ||
321 | /** | 299 | /** |
@@ -330,47 +308,24 @@ static s32 igb_read_phy_reg_sgmii_82575(struct e1000_hw *hw, u32 offset, | |||
330 | static s32 igb_write_phy_reg_sgmii_82575(struct e1000_hw *hw, u32 offset, | 308 | static s32 igb_write_phy_reg_sgmii_82575(struct e1000_hw *hw, u32 offset, |
331 | u16 data) | 309 | u16 data) |
332 | { | 310 | { |
333 | struct e1000_phy_info *phy = &hw->phy; | 311 | s32 ret_val = -E1000_ERR_PARAM; |
334 | u32 i, i2ccmd = 0; | 312 | |
335 | u16 phy_data_swapped; | ||
336 | 313 | ||
337 | if (offset > E1000_MAX_SGMII_PHY_REG_ADDR) { | 314 | if (offset > E1000_MAX_SGMII_PHY_REG_ADDR) { |
338 | hw_dbg("PHY Address %d is out of range\n", offset); | 315 | hw_dbg("PHY Address %d is out of range\n", offset); |
339 | return -E1000_ERR_PARAM; | 316 | goto out; |
340 | } | 317 | } |
341 | 318 | ||
342 | /* Swap the data bytes for the I2C interface */ | 319 | ret_val = hw->phy.ops.acquire(hw); |
343 | phy_data_swapped = ((data >> 8) & 0x00FF) | ((data << 8) & 0xFF00); | 320 | if (ret_val) |
321 | goto out; | ||
344 | 322 | ||
345 | /* | 323 | ret_val = igb_write_phy_reg_i2c(hw, offset, data); |
346 | * Set up Op-code, Phy Address, and register address in the I2CCMD | ||
347 | * register. The MAC will take care of interfacing with the | ||
348 | * PHY to retrieve the desired data. | ||
349 | */ | ||
350 | i2ccmd = ((offset << E1000_I2CCMD_REG_ADDR_SHIFT) | | ||
351 | (phy->addr << E1000_I2CCMD_PHY_ADDR_SHIFT) | | ||
352 | E1000_I2CCMD_OPCODE_WRITE | | ||
353 | phy_data_swapped); | ||
354 | |||
355 | wr32(E1000_I2CCMD, i2ccmd); | ||
356 | |||
357 | /* Poll the ready bit to see if the I2C read completed */ | ||
358 | for (i = 0; i < E1000_I2CCMD_PHY_TIMEOUT; i++) { | ||
359 | udelay(50); | ||
360 | i2ccmd = rd32(E1000_I2CCMD); | ||
361 | if (i2ccmd & E1000_I2CCMD_READY) | ||
362 | break; | ||
363 | } | ||
364 | if (!(i2ccmd & E1000_I2CCMD_READY)) { | ||
365 | hw_dbg("I2CCMD Write did not complete\n"); | ||
366 | return -E1000_ERR_PHY; | ||
367 | } | ||
368 | if (i2ccmd & E1000_I2CCMD_ERROR) { | ||
369 | hw_dbg("I2CCMD Error bit set\n"); | ||
370 | return -E1000_ERR_PHY; | ||
371 | } | ||
372 | 324 | ||
373 | return 0; | 325 | hw->phy.ops.release(hw); |
326 | |||
327 | out: | ||
328 | return ret_val; | ||
374 | } | 329 | } |
375 | 330 | ||
376 | /** | 331 | /** |