aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorEmil Tantilov <emil.s.tantilov@intel.com>2011-03-23 20:57:50 -0400
committerJeff Kirsher <jeffrey.t.kirsher@intel.com>2011-04-13 22:23:38 -0400
commiteb9c3e3ea2981e56c71e8f5477c51783856090b1 (patch)
treeff6ddad23c34e96de2083c46598f7aab0eb62425 /drivers
parent032b4325b61b03f87f0346d0e92e39f785e24105 (diff)
ixgbe: fix semaphores in eeprom routines for x540
HW can upload EEPROM content from flash while in a middle of checksum calculation. Take NVM ownership for the whole process of checksum update. Call ixgbe_read_eerd_generic() and ixgbe_write_eewr_generic() directly to avoid double take of semaphores which leads to long loading times. Signed-off-by: Emil Tantilov <emil.s.tantilov@intel.com> Tested-by: Stephen Ko <stephen.s.ko@intel.com> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/ixgbe/ixgbe_common.c44
-rw-r--r--drivers/net/ixgbe/ixgbe_common.h2
-rw-r--r--drivers/net/ixgbe/ixgbe_x540.c154
3 files changed, 153 insertions, 47 deletions
diff --git a/drivers/net/ixgbe/ixgbe_common.c b/drivers/net/ixgbe/ixgbe_common.c
index a67cba5149d1..fc31e0256c18 100644
--- a/drivers/net/ixgbe/ixgbe_common.c
+++ b/drivers/net/ixgbe/ixgbe_common.c
@@ -54,6 +54,7 @@ static s32 ixgbe_device_supports_autoneg_fc(struct ixgbe_hw *hw);
54static s32 ixgbe_negotiate_fc(struct ixgbe_hw *hw, u32 adv_reg, u32 lp_reg, 54static s32 ixgbe_negotiate_fc(struct ixgbe_hw *hw, u32 adv_reg, u32 lp_reg,
55 u32 adv_sym, u32 adv_asm, u32 lp_sym, u32 lp_asm); 55 u32 adv_sym, u32 adv_asm, u32 lp_sym, u32 lp_asm);
56static s32 ixgbe_setup_fc(struct ixgbe_hw *hw, s32 packetbuf_num); 56static s32 ixgbe_setup_fc(struct ixgbe_hw *hw, s32 packetbuf_num);
57static s32 ixgbe_poll_eerd_eewr_done(struct ixgbe_hw *hw, u32 ee_reg);
57 58
58/** 59/**
59 * ixgbe_start_hw_generic - Prepare hardware for Tx/Rx 60 * ixgbe_start_hw_generic - Prepare hardware for Tx/Rx
@@ -778,6 +779,47 @@ out:
778} 779}
779 780
780/** 781/**
782 * ixgbe_write_eewr_generic - Write EEPROM word using EEWR
783 * @hw: pointer to hardware structure
784 * @offset: offset of word in the EEPROM to write
785 * @data: word write to the EEPROM
786 *
787 * Write a 16 bit word to the EEPROM using the EEWR register.
788 **/
789s32 ixgbe_write_eewr_generic(struct ixgbe_hw *hw, u16 offset, u16 data)
790{
791 u32 eewr;
792 s32 status;
793
794 hw->eeprom.ops.init_params(hw);
795
796 if (offset >= hw->eeprom.word_size) {
797 status = IXGBE_ERR_EEPROM;
798 goto out;
799 }
800
801 eewr = (offset << IXGBE_EEPROM_RW_ADDR_SHIFT) |
802 (data << IXGBE_EEPROM_RW_REG_DATA) | IXGBE_EEPROM_RW_REG_START;
803
804 status = ixgbe_poll_eerd_eewr_done(hw, IXGBE_NVM_POLL_WRITE);
805 if (status != 0) {
806 hw_dbg(hw, "Eeprom write EEWR timed out\n");
807 goto out;
808 }
809
810 IXGBE_WRITE_REG(hw, IXGBE_EEWR, eewr);
811
812 status = ixgbe_poll_eerd_eewr_done(hw, IXGBE_NVM_POLL_WRITE);
813 if (status != 0) {
814 hw_dbg(hw, "Eeprom write EEWR timed out\n");
815 goto out;
816 }
817
818out:
819 return status;
820}
821
822/**
781 * ixgbe_poll_eerd_eewr_done - Poll EERD read or EEWR write status 823 * ixgbe_poll_eerd_eewr_done - Poll EERD read or EEWR write status
782 * @hw: pointer to hardware structure 824 * @hw: pointer to hardware structure
783 * @ee_reg: EEPROM flag for polling 825 * @ee_reg: EEPROM flag for polling
@@ -785,7 +827,7 @@ out:
785 * Polls the status bit (bit 1) of the EERD or EEWR to determine when the 827 * Polls the status bit (bit 1) of the EERD or EEWR to determine when the
786 * read or write is done respectively. 828 * read or write is done respectively.
787 **/ 829 **/
788s32 ixgbe_poll_eerd_eewr_done(struct ixgbe_hw *hw, u32 ee_reg) 830static s32 ixgbe_poll_eerd_eewr_done(struct ixgbe_hw *hw, u32 ee_reg)
789{ 831{
790 u32 i; 832 u32 i;
791 u32 reg; 833 u32 reg;
diff --git a/drivers/net/ixgbe/ixgbe_common.h b/drivers/net/ixgbe/ixgbe_common.h
index 2585bf38391d..e18dc136ad34 100644
--- a/drivers/net/ixgbe/ixgbe_common.h
+++ b/drivers/net/ixgbe/ixgbe_common.h
@@ -50,13 +50,13 @@ s32 ixgbe_led_off_generic(struct ixgbe_hw *hw, u32 index);
50s32 ixgbe_init_eeprom_params_generic(struct ixgbe_hw *hw); 50s32 ixgbe_init_eeprom_params_generic(struct ixgbe_hw *hw);
51s32 ixgbe_write_eeprom_generic(struct ixgbe_hw *hw, u16 offset, u16 data); 51s32 ixgbe_write_eeprom_generic(struct ixgbe_hw *hw, u16 offset, u16 data);
52s32 ixgbe_read_eerd_generic(struct ixgbe_hw *hw, u16 offset, u16 *data); 52s32 ixgbe_read_eerd_generic(struct ixgbe_hw *hw, u16 offset, u16 *data);
53s32 ixgbe_write_eewr_generic(struct ixgbe_hw *hw, u16 offset, u16 data);
53s32 ixgbe_read_eeprom_bit_bang_generic(struct ixgbe_hw *hw, u16 offset, 54s32 ixgbe_read_eeprom_bit_bang_generic(struct ixgbe_hw *hw, u16 offset,
54 u16 *data); 55 u16 *data);
55u16 ixgbe_calc_eeprom_checksum_generic(struct ixgbe_hw *hw); 56u16 ixgbe_calc_eeprom_checksum_generic(struct ixgbe_hw *hw);
56s32 ixgbe_validate_eeprom_checksum_generic(struct ixgbe_hw *hw, 57s32 ixgbe_validate_eeprom_checksum_generic(struct ixgbe_hw *hw,
57 u16 *checksum_val); 58 u16 *checksum_val);
58s32 ixgbe_update_eeprom_checksum_generic(struct ixgbe_hw *hw); 59s32 ixgbe_update_eeprom_checksum_generic(struct ixgbe_hw *hw);
59s32 ixgbe_poll_eerd_eewr_done(struct ixgbe_hw *hw, u32 ee_reg);
60 60
61s32 ixgbe_set_rar_generic(struct ixgbe_hw *hw, u32 index, u8 *addr, u32 vmdq, 61s32 ixgbe_set_rar_generic(struct ixgbe_hw *hw, u32 index, u8 *addr, u32 vmdq,
62 u32 enable_addr); 62 u32 enable_addr);
diff --git a/drivers/net/ixgbe/ixgbe_x540.c b/drivers/net/ixgbe/ixgbe_x540.c
index 8aa1dc1155a9..5433f15c1e1b 100644
--- a/drivers/net/ixgbe/ixgbe_x540.c
+++ b/drivers/net/ixgbe/ixgbe_x540.c
@@ -322,55 +322,33 @@ static s32 ixgbe_read_eerd_X540(struct ixgbe_hw *hw, u16 offset, u16 *data)
322} 322}
323 323
324/** 324/**
325 * ixgbe_write_eewr_X540 - Write EEPROM word using EEWR 325 * ixgbe_write_eewr_X540 - Write EEPROM word using EEWR
326 * @hw: pointer to hardware structure 326 * @hw: pointer to hardware structure
327 * @offset: offset of word in the EEPROM to write 327 * @offset: offset of word in the EEPROM to write
328 * @data: word write to the EEPROM 328 * @data: word write to the EEPROM
329 * 329 *
330 * Write a 16 bit word to the EEPROM using the EEWR register. 330 * Write a 16 bit word to the EEPROM using the EEWR register.
331 **/ 331 **/
332static s32 ixgbe_write_eewr_X540(struct ixgbe_hw *hw, u16 offset, u16 data) 332static s32 ixgbe_write_eewr_X540(struct ixgbe_hw *hw, u16 offset, u16 data)
333{ 333{
334 u32 eewr; 334 s32 status = 0;
335 s32 status;
336
337 hw->eeprom.ops.init_params(hw);
338
339 if (offset >= hw->eeprom.word_size) {
340 status = IXGBE_ERR_EEPROM;
341 goto out;
342 }
343
344 eewr = (offset << IXGBE_EEPROM_RW_ADDR_SHIFT) |
345 (data << IXGBE_EEPROM_RW_REG_DATA) |
346 IXGBE_EEPROM_RW_REG_START;
347
348 if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM) == 0) {
349 status = ixgbe_poll_eerd_eewr_done(hw, IXGBE_NVM_POLL_WRITE);
350 if (status != 0) {
351 hw_dbg(hw, "Eeprom write EEWR timed out\n");
352 goto out;
353 }
354
355 IXGBE_WRITE_REG(hw, IXGBE_EEWR, eewr);
356 335
357 status = ixgbe_poll_eerd_eewr_done(hw, IXGBE_NVM_POLL_WRITE); 336 if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM) == 0)
358 if (status != 0) { 337 status = ixgbe_write_eewr_generic(hw, offset, data);
359 hw_dbg(hw, "Eeprom write EEWR timed out\n"); 338 else
360 goto out;
361 }
362 } else {
363 status = IXGBE_ERR_SWFW_SYNC; 339 status = IXGBE_ERR_SWFW_SYNC;
364 }
365 340
366out: 341 hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM);
367 ixgbe_release_swfw_sync_X540(hw, IXGBE_GSSR_EEP_SM);
368 return status; 342 return status;
369} 343}
370 344
371/** 345/**
372 * ixgbe_calc_eeprom_checksum_X540 - Calculates and returns the checksum 346 * ixgbe_calc_eeprom_checksum_X540 - Calculates and returns the checksum
373 * @hw: pointer to hardware structure 347 *
348 * This function does not use synchronization for EERD and EEWR. It can
349 * be used internally by function which utilize ixgbe_acquire_swfw_sync_X540.
350 *
351 * @hw: pointer to hardware structure
374 **/ 352 **/
375static u16 ixgbe_calc_eeprom_checksum_X540(struct ixgbe_hw *hw) 353static u16 ixgbe_calc_eeprom_checksum_X540(struct ixgbe_hw *hw)
376{ 354{
@@ -381,9 +359,15 @@ static u16 ixgbe_calc_eeprom_checksum_X540(struct ixgbe_hw *hw)
381 u16 pointer = 0; 359 u16 pointer = 0;
382 u16 word = 0; 360 u16 word = 0;
383 361
362 /*
363 * Do not use hw->eeprom.ops.read because we do not want to take
364 * the synchronization semaphores here. Instead use
365 * ixgbe_read_eerd_generic
366 */
367
384 /* Include 0x0-0x3F in the checksum */ 368 /* Include 0x0-0x3F in the checksum */
385 for (i = 0; i < IXGBE_EEPROM_CHECKSUM; i++) { 369 for (i = 0; i < IXGBE_EEPROM_CHECKSUM; i++) {
386 if (hw->eeprom.ops.read(hw, i, &word) != 0) { 370 if (ixgbe_read_eerd_generic(hw, i, &word) != 0) {
387 hw_dbg(hw, "EEPROM read failed\n"); 371 hw_dbg(hw, "EEPROM read failed\n");
388 break; 372 break;
389 } 373 }
@@ -398,7 +382,7 @@ static u16 ixgbe_calc_eeprom_checksum_X540(struct ixgbe_hw *hw)
398 if (i == IXGBE_PHY_PTR || i == IXGBE_OPTION_ROM_PTR) 382 if (i == IXGBE_PHY_PTR || i == IXGBE_OPTION_ROM_PTR)
399 continue; 383 continue;
400 384
401 if (hw->eeprom.ops.read(hw, i, &pointer) != 0) { 385 if (ixgbe_read_eerd_generic(hw, i, &pointer) != 0) {
402 hw_dbg(hw, "EEPROM read failed\n"); 386 hw_dbg(hw, "EEPROM read failed\n");
403 break; 387 break;
404 } 388 }
@@ -408,7 +392,7 @@ static u16 ixgbe_calc_eeprom_checksum_X540(struct ixgbe_hw *hw)
408 pointer >= hw->eeprom.word_size) 392 pointer >= hw->eeprom.word_size)
409 continue; 393 continue;
410 394
411 if (hw->eeprom.ops.read(hw, pointer, &length) != 0) { 395 if (ixgbe_read_eerd_generic(hw, pointer, &length) != 0) {
412 hw_dbg(hw, "EEPROM read failed\n"); 396 hw_dbg(hw, "EEPROM read failed\n");
413 break; 397 break;
414 } 398 }
@@ -419,7 +403,7 @@ static u16 ixgbe_calc_eeprom_checksum_X540(struct ixgbe_hw *hw)
419 continue; 403 continue;
420 404
421 for (j = pointer+1; j <= pointer+length; j++) { 405 for (j = pointer+1; j <= pointer+length; j++) {
422 if (hw->eeprom.ops.read(hw, j, &word) != 0) { 406 if (ixgbe_read_eerd_generic(hw, j, &word) != 0) {
423 hw_dbg(hw, "EEPROM read failed\n"); 407 hw_dbg(hw, "EEPROM read failed\n");
424 break; 408 break;
425 } 409 }
@@ -433,6 +417,62 @@ static u16 ixgbe_calc_eeprom_checksum_X540(struct ixgbe_hw *hw)
433} 417}
434 418
435/** 419/**
420 * ixgbe_validate_eeprom_checksum_X540 - Validate EEPROM checksum
421 * @hw: pointer to hardware structure
422 * @checksum_val: calculated checksum
423 *
424 * Performs checksum calculation and validates the EEPROM checksum. If the
425 * caller does not need checksum_val, the value can be NULL.
426 **/
427static s32 ixgbe_validate_eeprom_checksum_X540(struct ixgbe_hw *hw,
428 u16 *checksum_val)
429{
430 s32 status;
431 u16 checksum;
432 u16 read_checksum = 0;
433
434 /*
435 * Read the first word from the EEPROM. If this times out or fails, do
436 * not continue or we could be in for a very long wait while every
437 * EEPROM read fails
438 */
439 status = hw->eeprom.ops.read(hw, 0, &checksum);
440
441 if (status != 0) {
442 hw_dbg(hw, "EEPROM read failed\n");
443 goto out;
444 }
445
446 if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM) == 0) {
447 checksum = hw->eeprom.ops.calc_checksum(hw);
448
449 /*
450 * Do not use hw->eeprom.ops.read because we do not want to take
451 * the synchronization semaphores twice here.
452 */
453 ixgbe_read_eerd_generic(hw, IXGBE_EEPROM_CHECKSUM,
454 &read_checksum);
455
456 /*
457 * Verify read checksum from EEPROM is the same as
458 * calculated checksum
459 */
460 if (read_checksum != checksum)
461 status = IXGBE_ERR_EEPROM_CHECKSUM;
462
463 /* If the user cares, return the calculated checksum */
464 if (checksum_val)
465 *checksum_val = checksum;
466 } else {
467 status = IXGBE_ERR_SWFW_SYNC;
468 }
469
470 hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM);
471out:
472 return status;
473}
474
475/**
436 * ixgbe_update_eeprom_checksum_X540 - Updates the EEPROM checksum and flash 476 * ixgbe_update_eeprom_checksum_X540 - Updates the EEPROM checksum and flash
437 * @hw: pointer to hardware structure 477 * @hw: pointer to hardware structure
438 * 478 *
@@ -443,11 +483,35 @@ static u16 ixgbe_calc_eeprom_checksum_X540(struct ixgbe_hw *hw)
443static s32 ixgbe_update_eeprom_checksum_X540(struct ixgbe_hw *hw) 483static s32 ixgbe_update_eeprom_checksum_X540(struct ixgbe_hw *hw)
444{ 484{
445 s32 status; 485 s32 status;
486 u16 checksum;
446 487
447 status = ixgbe_update_eeprom_checksum_generic(hw); 488 /*
489 * Read the first word from the EEPROM. If this times out or fails, do
490 * not continue or we could be in for a very long wait while every
491 * EEPROM read fails
492 */
493 status = hw->eeprom.ops.read(hw, 0, &checksum);
494
495 if (status != 0)
496 hw_dbg(hw, "EEPROM read failed\n");
497
498 if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM) == 0) {
499 checksum = hw->eeprom.ops.calc_checksum(hw);
448 500
449 if (status) 501 /*
502 * Do not use hw->eeprom.ops.write because we do not want to
503 * take the synchronization semaphores twice here.
504 */
505 status = ixgbe_write_eewr_generic(hw, IXGBE_EEPROM_CHECKSUM,
506 checksum);
507
508 if (status == 0)
450 status = ixgbe_update_flash_X540(hw); 509 status = ixgbe_update_flash_X540(hw);
510 else
511 status = IXGBE_ERR_SWFW_SYNC;
512 }
513
514 hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM);
451 515
452 return status; 516 return status;
453} 517}
@@ -728,7 +792,7 @@ static struct ixgbe_eeprom_operations eeprom_ops_X540 = {
728 .read = &ixgbe_read_eerd_X540, 792 .read = &ixgbe_read_eerd_X540,
729 .write = &ixgbe_write_eewr_X540, 793 .write = &ixgbe_write_eewr_X540,
730 .calc_checksum = &ixgbe_calc_eeprom_checksum_X540, 794 .calc_checksum = &ixgbe_calc_eeprom_checksum_X540,
731 .validate_checksum = &ixgbe_validate_eeprom_checksum_generic, 795 .validate_checksum = &ixgbe_validate_eeprom_checksum_X540,
732 .update_checksum = &ixgbe_update_eeprom_checksum_X540, 796 .update_checksum = &ixgbe_update_eeprom_checksum_X540,
733}; 797};
734 798