aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorDave Graham <david.graham@intel.com>2009-06-08 10:28:17 -0400
committerDavid S. Miller <davem@davemloft.net>2009-06-09 08:25:35 -0400
commit23a2d1b233f535fc74f8dca66e488980b4db041b (patch)
tree7c0102dfbfa8b789a4385d08151268a6fa3f8a3f /drivers
parent8459464f07cf67cab07b17d5736d75fb86adab22 (diff)
e1000e: Fixes possible phy corrupton on 82571 designs.
Phy corruption has been observed on 2-port 82571 adapters, and is root-caused to lack of synchronization between the 2 driver instances, which conflict when attempting to access the phy via the single MDIC register. A semaphore exists for this purpose, and is now used on these designs. Because PXE &/or EFI boot code (which we cannot expect to be built with this fix) may leave the inter-instance semaphore in an invalid initial state when the driver first loads, this fix also includes a one-time (per driver load) fix-up of the semaphore initial state. Signed-off-by: dave graham <david.graham@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')
-rw-r--r--drivers/net/e1000e/82571.c86
-rw-r--r--drivers/net/e1000e/defines.h2
-rw-r--r--drivers/net/e1000e/hw.h2
3 files changed, 83 insertions, 7 deletions
diff --git a/drivers/net/e1000e/82571.c b/drivers/net/e1000e/82571.c
index c4b3f4fe91ae..b53b40ba88a8 100644
--- a/drivers/net/e1000e/82571.c
+++ b/drivers/net/e1000e/82571.c
@@ -71,6 +71,7 @@ static s32 e1000_setup_link_82571(struct e1000_hw *hw);
71static void e1000_clear_hw_cntrs_82571(struct e1000_hw *hw); 71static void e1000_clear_hw_cntrs_82571(struct e1000_hw *hw);
72static bool e1000_check_mng_mode_82574(struct e1000_hw *hw); 72static bool e1000_check_mng_mode_82574(struct e1000_hw *hw);
73static s32 e1000_led_on_82574(struct e1000_hw *hw); 73static s32 e1000_led_on_82574(struct e1000_hw *hw);
74static void e1000_put_hw_semaphore_82571(struct e1000_hw *hw);
74 75
75/** 76/**
76 * e1000_init_phy_params_82571 - Init PHY func ptrs. 77 * e1000_init_phy_params_82571 - Init PHY func ptrs.
@@ -212,6 +213,9 @@ static s32 e1000_init_mac_params_82571(struct e1000_adapter *adapter)
212 struct e1000_hw *hw = &adapter->hw; 213 struct e1000_hw *hw = &adapter->hw;
213 struct e1000_mac_info *mac = &hw->mac; 214 struct e1000_mac_info *mac = &hw->mac;
214 struct e1000_mac_operations *func = &mac->ops; 215 struct e1000_mac_operations *func = &mac->ops;
216 u32 swsm = 0;
217 u32 swsm2 = 0;
218 bool force_clear_smbi = false;
215 219
216 /* Set media type */ 220 /* Set media type */
217 switch (adapter->pdev->device) { 221 switch (adapter->pdev->device) {
@@ -276,6 +280,50 @@ static s32 e1000_init_mac_params_82571(struct e1000_adapter *adapter)
276 break; 280 break;
277 } 281 }
278 282
283 /*
284 * Ensure that the inter-port SWSM.SMBI lock bit is clear before
285 * first NVM or PHY acess. This should be done for single-port
286 * devices, and for one port only on dual-port devices so that
287 * for those devices we can still use the SMBI lock to synchronize
288 * inter-port accesses to the PHY & NVM.
289 */
290 switch (hw->mac.type) {
291 case e1000_82571:
292 case e1000_82572:
293 swsm2 = er32(SWSM2);
294
295 if (!(swsm2 & E1000_SWSM2_LOCK)) {
296 /* Only do this for the first interface on this card */
297 ew32(SWSM2,
298 swsm2 | E1000_SWSM2_LOCK);
299 force_clear_smbi = true;
300 } else
301 force_clear_smbi = false;
302 break;
303 default:
304 force_clear_smbi = true;
305 break;
306 }
307
308 if (force_clear_smbi) {
309 /* Make sure SWSM.SMBI is clear */
310 swsm = er32(SWSM);
311 if (swsm & E1000_SWSM_SMBI) {
312 /* This bit should not be set on a first interface, and
313 * indicates that the bootagent or EFI code has
314 * improperly left this bit enabled
315 */
316 hw_dbg(hw, "Please update your 82571 Bootagent\n");
317 }
318 ew32(SWSM, swsm & ~E1000_SWSM_SMBI);
319 }
320
321 /*
322 * Initialze device specific counter of SMBI acquisition
323 * timeouts.
324 */
325 hw->dev_spec.e82571.smb_counter = 0;
326
279 return 0; 327 return 0;
280} 328}
281 329
@@ -413,11 +461,37 @@ static s32 e1000_get_phy_id_82571(struct e1000_hw *hw)
413static s32 e1000_get_hw_semaphore_82571(struct e1000_hw *hw) 461static s32 e1000_get_hw_semaphore_82571(struct e1000_hw *hw)
414{ 462{
415 u32 swsm; 463 u32 swsm;
416 s32 timeout = hw->nvm.word_size + 1; 464 s32 sw_timeout = hw->nvm.word_size + 1;
465 s32 fw_timeout = hw->nvm.word_size + 1;
417 s32 i = 0; 466 s32 i = 0;
418 467
468 /*
469 * If we have timedout 3 times on trying to acquire
470 * the inter-port SMBI semaphore, there is old code
471 * operating on the other port, and it is not
472 * releasing SMBI. Modify the number of times that
473 * we try for the semaphore to interwork with this
474 * older code.
475 */
476 if (hw->dev_spec.e82571.smb_counter > 2)
477 sw_timeout = 1;
478
479 /* Get the SW semaphore */
480 while (i < sw_timeout) {
481 swsm = er32(SWSM);
482 if (!(swsm & E1000_SWSM_SMBI))
483 break;
484
485 udelay(50);
486 i++;
487 }
488
489 if (i == sw_timeout) {
490 hw_dbg(hw, "Driver can't access device - SMBI bit is set.\n");
491 hw->dev_spec.e82571.smb_counter++;
492 }
419 /* Get the FW semaphore. */ 493 /* Get the FW semaphore. */
420 for (i = 0; i < timeout; i++) { 494 for (i = 0; i < fw_timeout; i++) {
421 swsm = er32(SWSM); 495 swsm = er32(SWSM);
422 ew32(SWSM, swsm | E1000_SWSM_SWESMBI); 496 ew32(SWSM, swsm | E1000_SWSM_SWESMBI);
423 497
@@ -428,9 +502,9 @@ static s32 e1000_get_hw_semaphore_82571(struct e1000_hw *hw)
428 udelay(50); 502 udelay(50);
429 } 503 }
430 504
431 if (i == timeout) { 505 if (i == fw_timeout) {
432 /* Release semaphores */ 506 /* Release semaphores */
433 e1000e_put_hw_semaphore(hw); 507 e1000_put_hw_semaphore_82571(hw);
434 hw_dbg(hw, "Driver can't access the NVM\n"); 508 hw_dbg(hw, "Driver can't access the NVM\n");
435 return -E1000_ERR_NVM; 509 return -E1000_ERR_NVM;
436 } 510 }
@@ -449,9 +523,7 @@ static void e1000_put_hw_semaphore_82571(struct e1000_hw *hw)
449 u32 swsm; 523 u32 swsm;
450 524
451 swsm = er32(SWSM); 525 swsm = er32(SWSM);
452 526 swsm &= ~(E1000_SWSM_SMBI | E1000_SWSM_SWESMBI);
453 swsm &= ~E1000_SWSM_SWESMBI;
454
455 ew32(SWSM, swsm); 527 ew32(SWSM, swsm);
456} 528}
457 529
diff --git a/drivers/net/e1000e/defines.h b/drivers/net/e1000e/defines.h
index 674a47e43034..8890c97e1120 100644
--- a/drivers/net/e1000e/defines.h
+++ b/drivers/net/e1000e/defines.h
@@ -376,6 +376,8 @@
376#define E1000_SWSM_SWESMBI 0x00000002 /* FW Semaphore bit */ 376#define E1000_SWSM_SWESMBI 0x00000002 /* FW Semaphore bit */
377#define E1000_SWSM_DRV_LOAD 0x00000008 /* Driver Loaded Bit */ 377#define E1000_SWSM_DRV_LOAD 0x00000008 /* Driver Loaded Bit */
378 378
379#define E1000_SWSM2_LOCK 0x00000002 /* Secondary driver semaphore bit */
380
379/* Interrupt Cause Read */ 381/* Interrupt Cause Read */
380#define E1000_ICR_TXDW 0x00000001 /* Transmit desc written back */ 382#define E1000_ICR_TXDW 0x00000001 /* Transmit desc written back */
381#define E1000_ICR_LSC 0x00000004 /* Link Status Change */ 383#define E1000_ICR_LSC 0x00000004 /* Link Status Change */
diff --git a/drivers/net/e1000e/hw.h b/drivers/net/e1000e/hw.h
index fce3f0529e4c..163c1c0cfee7 100644
--- a/drivers/net/e1000e/hw.h
+++ b/drivers/net/e1000e/hw.h
@@ -214,6 +214,7 @@ enum e1e_registers {
214 E1000_FACTPS = 0x05B30, /* Function Active and Power State to MNG */ 214 E1000_FACTPS = 0x05B30, /* Function Active and Power State to MNG */
215 E1000_SWSM = 0x05B50, /* SW Semaphore */ 215 E1000_SWSM = 0x05B50, /* SW Semaphore */
216 E1000_FWSM = 0x05B54, /* FW Semaphore */ 216 E1000_FWSM = 0x05B54, /* FW Semaphore */
217 E1000_SWSM2 = 0x05B58, /* Driver-only SW semaphore */
217 E1000_HICR = 0x08F00, /* Host Interface Control */ 218 E1000_HICR = 0x08F00, /* Host Interface Control */
218}; 219};
219 220
@@ -883,6 +884,7 @@ struct e1000_fc_info {
883struct e1000_dev_spec_82571 { 884struct e1000_dev_spec_82571 {
884 bool laa_is_present; 885 bool laa_is_present;
885 bool alt_mac_addr_is_present; 886 bool alt_mac_addr_is_present;
887 u32 smb_counter;
886}; 888};
887 889
888struct e1000_shadow_ram { 890struct e1000_shadow_ram {