aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet
diff options
context:
space:
mode:
authorAriel Elior <ariele@broadcom.com>2012-01-26 01:01:52 -0500
committerDavid S. Miller <davem@davemloft.net>2012-01-26 13:39:52 -0500
commit95c6c6165eaf5a031bcf31606e081c72e4acdeb8 (patch)
tree70af0b9194397ac380e735bb3d0f13f46946c292 /drivers/net/ethernet
parent889b9af34f986138eebebfe781567cb950b3a22b (diff)
bnx2x: Recovery flow bug fixes
1. Sample mcp pulse and mcp sequence in nic load instead of in init_one as they may change by the time we want to use them. 2. Allow cnic to access device during nic load (by adding a new "LOADING" state to recovery flow). This prevents the unnecessary cnic timeout which resulted by cnic attempting to access because nic is loading, but being blocked because of the Recovery state. 3. Issue 'fake' driver load command to mcp when last driver unloads to prevent mcp from taking ownership. When recovery is complete unload fake driver to allow mcp to initialize the hardware before first driver loads. Signed-off-by: Ariel Elior <ariele@broadcom.com> Signed-off-by: Eilon Greenstein <eilong@broadcom.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ethernet')
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x.h3
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c18
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c102
3 files changed, 75 insertions, 48 deletions
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
index 8c73d34b2ff1..06bbef742fa3 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
@@ -1088,7 +1088,8 @@ enum bnx2x_recovery_state {
1088 BNX2X_RECOVERY_DONE, 1088 BNX2X_RECOVERY_DONE,
1089 BNX2X_RECOVERY_INIT, 1089 BNX2X_RECOVERY_INIT,
1090 BNX2X_RECOVERY_WAIT, 1090 BNX2X_RECOVERY_WAIT,
1091 BNX2X_RECOVERY_FAILED 1091 BNX2X_RECOVERY_FAILED,
1092 BNX2X_RECOVERY_NIC_LOADING
1092}; 1093};
1093 1094
1094/* 1095/*
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
index 15db2d679a14..8fdd71b7bef0 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
@@ -1776,6 +1776,18 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
1776 * common blocks should be initialized, otherwise - not 1776 * common blocks should be initialized, otherwise - not
1777 */ 1777 */
1778 if (!BP_NOMCP(bp)) { 1778 if (!BP_NOMCP(bp)) {
1779 /* init fw_seq */
1780 bp->fw_seq =
1781 (SHMEM_RD(bp, func_mb[BP_FW_MB_IDX(bp)].drv_mb_header) &
1782 DRV_MSG_SEQ_NUMBER_MASK);
1783 BNX2X_DEV_INFO("fw_seq 0x%08x\n", bp->fw_seq);
1784
1785 /* Get current FW pulse sequence */
1786 bp->fw_drv_pulse_wr_seq =
1787 (SHMEM_RD(bp, func_mb[BP_FW_MB_IDX(bp)].drv_pulse_mb) &
1788 DRV_PULSE_SEQ_MASK);
1789 BNX2X_DEV_INFO("drv_pulse 0x%x\n", bp->fw_drv_pulse_wr_seq);
1790
1779 load_code = bnx2x_fw_command(bp, DRV_MSG_CODE_LOAD_REQ, 0); 1791 load_code = bnx2x_fw_command(bp, DRV_MSG_CODE_LOAD_REQ, 0);
1780 if (!load_code) { 1792 if (!load_code) {
1781 BNX2X_ERR("MCP response failure, aborting\n"); 1793 BNX2X_ERR("MCP response failure, aborting\n");
@@ -3442,7 +3454,7 @@ int bnx2x_change_mtu(struct net_device *dev, int new_mtu)
3442 struct bnx2x *bp = netdev_priv(dev); 3454 struct bnx2x *bp = netdev_priv(dev);
3443 3455
3444 if (bp->recovery_state != BNX2X_RECOVERY_DONE) { 3456 if (bp->recovery_state != BNX2X_RECOVERY_DONE) {
3445 pr_err("Handling parity error recovery. Try again later\n"); 3457 netdev_err(dev, "Handling parity error recovery. Try again later\n");
3446 return -EAGAIN; 3458 return -EAGAIN;
3447 } 3459 }
3448 3460
@@ -3569,7 +3581,7 @@ int bnx2x_resume(struct pci_dev *pdev)
3569 bp = netdev_priv(dev); 3581 bp = netdev_priv(dev);
3570 3582
3571 if (bp->recovery_state != BNX2X_RECOVERY_DONE) { 3583 if (bp->recovery_state != BNX2X_RECOVERY_DONE) {
3572 pr_err("Handling parity error recovery. Try again later\n"); 3584 netdev_err(dev, "Handling parity error recovery. Try again later\n");
3573 return -EAGAIN; 3585 return -EAGAIN;
3574 } 3586 }
3575 3587
@@ -3585,8 +3597,6 @@ int bnx2x_resume(struct pci_dev *pdev)
3585 bnx2x_set_power_state(bp, PCI_D0); 3597 bnx2x_set_power_state(bp, PCI_D0);
3586 netif_device_attach(dev); 3598 netif_device_attach(dev);
3587 3599
3588 /* Since the chip was reset, clear the FW sequence number */
3589 bp->fw_seq = 0;
3590 rc = bnx2x_nic_load(bp, LOAD_OPEN); 3600 rc = bnx2x_nic_load(bp, LOAD_OPEN);
3591 3601
3592 rtnl_unlock(); 3602 rtnl_unlock();
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
index f7f167a0f85a..c945df061618 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
@@ -468,7 +468,9 @@ static int bnx2x_issue_dmae_with_comp(struct bnx2x *bp,
468 while ((*wb_comp & ~DMAE_PCI_ERR_FLAG) != DMAE_COMP_VAL) { 468 while ((*wb_comp & ~DMAE_PCI_ERR_FLAG) != DMAE_COMP_VAL) {
469 DP(BNX2X_MSG_OFF, "wb_comp 0x%08x\n", *wb_comp); 469 DP(BNX2X_MSG_OFF, "wb_comp 0x%08x\n", *wb_comp);
470 470
471 if (!cnt) { 471 if (!cnt ||
472 (bp->recovery_state != BNX2X_RECOVERY_DONE &&
473 bp->recovery_state != BNX2X_RECOVERY_NIC_LOADING)) {
472 BNX2X_ERR("DMAE timeout!\n"); 474 BNX2X_ERR("DMAE timeout!\n");
473 rc = DMAE_TIMEOUT; 475 rc = DMAE_TIMEOUT;
474 goto unlock; 476 goto unlock;
@@ -8477,13 +8479,38 @@ int bnx2x_leader_reset(struct bnx2x *bp)
8477{ 8479{
8478 int rc = 0; 8480 int rc = 0;
8479 bool global = bnx2x_reset_is_global(bp); 8481 bool global = bnx2x_reset_is_global(bp);
8482 u32 load_code;
8483
8484 /* if not going to reset MCP - load "fake" driver to reset HW while
8485 * driver is owner of the HW
8486 */
8487 if (!global && !BP_NOMCP(bp)) {
8488 load_code = bnx2x_fw_command(bp, DRV_MSG_CODE_LOAD_REQ, 0);
8489 if (!load_code) {
8490 BNX2X_ERR("MCP response failure, aborting\n");
8491 rc = -EAGAIN;
8492 goto exit_leader_reset;
8493 }
8494 if ((load_code != FW_MSG_CODE_DRV_LOAD_COMMON_CHIP) &&
8495 (load_code != FW_MSG_CODE_DRV_LOAD_COMMON)) {
8496 BNX2X_ERR("MCP unexpected resp, aborting\n");
8497 rc = -EAGAIN;
8498 goto exit_leader_reset2;
8499 }
8500 load_code = bnx2x_fw_command(bp, DRV_MSG_CODE_LOAD_DONE, 0);
8501 if (!load_code) {
8502 BNX2X_ERR("MCP response failure, aborting\n");
8503 rc = -EAGAIN;
8504 goto exit_leader_reset2;
8505 }
8506 }
8480 8507
8481 /* Try to recover after the failure */ 8508 /* Try to recover after the failure */
8482 if (bnx2x_process_kill(bp, global)) { 8509 if (bnx2x_process_kill(bp, global)) {
8483 netdev_err(bp->dev, "Something bad had happen on engine %d! " 8510 netdev_err(bp->dev, "Something bad had happen on engine %d! "
8484 "Aii!\n", BP_PATH(bp)); 8511 "Aii!\n", BP_PATH(bp));
8485 rc = -EAGAIN; 8512 rc = -EAGAIN;
8486 goto exit_leader_reset; 8513 goto exit_leader_reset2;
8487 } 8514 }
8488 8515
8489 /* 8516 /*
@@ -8494,6 +8521,12 @@ int bnx2x_leader_reset(struct bnx2x *bp)
8494 if (global) 8521 if (global)
8495 bnx2x_clear_reset_global(bp); 8522 bnx2x_clear_reset_global(bp);
8496 8523
8524exit_leader_reset2:
8525 /* unload "fake driver" if it was loaded */
8526 if (!global && !BP_NOMCP(bp)) {
8527 bnx2x_fw_command(bp, DRV_MSG_CODE_UNLOAD_REQ_WOL_MCP, 0);
8528 bnx2x_fw_command(bp, DRV_MSG_CODE_UNLOAD_DONE, 0);
8529 }
8497exit_leader_reset: 8530exit_leader_reset:
8498 bp->is_leader = 0; 8531 bp->is_leader = 0;
8499 bnx2x_release_leader_lock(bp); 8532 bnx2x_release_leader_lock(bp);
@@ -8530,13 +8563,15 @@ static inline void bnx2x_recovery_failed(struct bnx2x *bp)
8530static void bnx2x_parity_recover(struct bnx2x *bp) 8563static void bnx2x_parity_recover(struct bnx2x *bp)
8531{ 8564{
8532 bool global = false; 8565 bool global = false;
8566 bool is_parity;
8533 8567
8534 DP(NETIF_MSG_HW, "Handling parity\n"); 8568 DP(NETIF_MSG_HW, "Handling parity\n");
8535 while (1) { 8569 while (1) {
8536 switch (bp->recovery_state) { 8570 switch (bp->recovery_state) {
8537 case BNX2X_RECOVERY_INIT: 8571 case BNX2X_RECOVERY_INIT:
8538 DP(NETIF_MSG_HW, "State is BNX2X_RECOVERY_INIT\n"); 8572 DP(NETIF_MSG_HW, "State is BNX2X_RECOVERY_INIT\n");
8539 bnx2x_chk_parity_attn(bp, &global, false); 8573 is_parity = bnx2x_chk_parity_attn(bp, &global, false);
8574 WARN_ON(!is_parity);
8540 8575
8541 /* Try to get a LEADER_LOCK HW lock */ 8576 /* Try to get a LEADER_LOCK HW lock */
8542 if (bnx2x_trylock_leader_lock(bp)) { 8577 if (bnx2x_trylock_leader_lock(bp)) {
@@ -8560,15 +8595,6 @@ static void bnx2x_parity_recover(struct bnx2x *bp)
8560 8595
8561 bp->recovery_state = BNX2X_RECOVERY_WAIT; 8596 bp->recovery_state = BNX2X_RECOVERY_WAIT;
8562 8597
8563 /*
8564 * Reset MCP command sequence number and MCP mail box
8565 * sequence as we are going to reset the MCP.
8566 */
8567 if (global) {
8568 bp->fw_seq = 0;
8569 bp->fw_drv_pulse_wr_seq = 0;
8570 }
8571
8572 /* Ensure "is_leader", MCP command sequence and 8598 /* Ensure "is_leader", MCP command sequence and
8573 * "recovery_state" update values are seen on other 8599 * "recovery_state" update values are seen on other
8574 * CPUs. 8600 * CPUs.
@@ -8652,9 +8678,20 @@ static void bnx2x_parity_recover(struct bnx2x *bp)
8652 return; 8678 return;
8653 } 8679 }
8654 8680
8655 if (bnx2x_nic_load(bp, LOAD_NORMAL)) 8681 bp->recovery_state =
8656 bnx2x_recovery_failed(bp); 8682 BNX2X_RECOVERY_NIC_LOADING;
8657 else { 8683 if (bnx2x_nic_load(bp, LOAD_NORMAL)) {
8684 netdev_err(bp->dev,
8685 "Recovery failed. "
8686 "Power cycle "
8687 "needed\n");
8688 /* Disconnect this device */
8689 netif_device_detach(bp->dev);
8690 /* Shut down the power */
8691 bnx2x_set_power_state(
8692 bp, PCI_D3hot);
8693 smp_mb();
8694 } else {
8658 bp->recovery_state = 8695 bp->recovery_state =
8659 BNX2X_RECOVERY_DONE; 8696 BNX2X_RECOVERY_DONE;
8660 smp_mb(); 8697 smp_mb();
@@ -8908,9 +8945,6 @@ static void __devinit bnx2x_undi_unload(struct bnx2x *bp)
8908 8945
8909 /* restore our func and fw_seq */ 8946 /* restore our func and fw_seq */
8910 bp->pf_num = orig_pf_num; 8947 bp->pf_num = orig_pf_num;
8911 bp->fw_seq =
8912 (SHMEM_RD(bp, func_mb[bp->pf_num].drv_mb_header) &
8913 DRV_MSG_SEQ_NUMBER_MASK);
8914 } 8948 }
8915 } 8949 }
8916 8950
@@ -9936,16 +9970,6 @@ static int __devinit bnx2x_get_hwinfo(struct bnx2x *bp)
9936 9970
9937 bnx2x_get_cnic_info(bp); 9971 bnx2x_get_cnic_info(bp);
9938 9972
9939 /* Get current FW pulse sequence */
9940 if (!BP_NOMCP(bp)) {
9941 int mb_idx = BP_FW_MB_IDX(bp);
9942
9943 bp->fw_drv_pulse_wr_seq =
9944 (SHMEM_RD(bp, func_mb[mb_idx].drv_pulse_mb) &
9945 DRV_PULSE_SEQ_MASK);
9946 BNX2X_DEV_INFO("drv_pulse 0x%x\n", bp->fw_drv_pulse_wr_seq);
9947 }
9948
9949 return rc; 9973 return rc;
9950} 9974}
9951 9975
@@ -10115,14 +10139,6 @@ static int __devinit bnx2x_init_bp(struct bnx2x *bp)
10115 if (!BP_NOMCP(bp)) 10139 if (!BP_NOMCP(bp))
10116 bnx2x_undi_unload(bp); 10140 bnx2x_undi_unload(bp);
10117 10141
10118 /* init fw_seq after undi_unload! */
10119 if (!BP_NOMCP(bp)) {
10120 bp->fw_seq =
10121 (SHMEM_RD(bp, func_mb[BP_FW_MB_IDX(bp)].drv_mb_header) &
10122 DRV_MSG_SEQ_NUMBER_MASK);
10123 BNX2X_DEV_INFO("fw_seq 0x%08x\n", bp->fw_seq);
10124 }
10125
10126 if (CHIP_REV_IS_FPGA(bp)) 10142 if (CHIP_REV_IS_FPGA(bp))
10127 dev_err(&bp->pdev->dev, "FPGA detected\n"); 10143 dev_err(&bp->pdev->dev, "FPGA detected\n");
10128 10144
@@ -11331,13 +11347,6 @@ static void bnx2x_eeh_recover(struct bnx2x *bp)
11331 if ((val & (SHR_MEM_VALIDITY_DEV_INFO | SHR_MEM_VALIDITY_MB)) 11347 if ((val & (SHR_MEM_VALIDITY_DEV_INFO | SHR_MEM_VALIDITY_MB))
11332 != (SHR_MEM_VALIDITY_DEV_INFO | SHR_MEM_VALIDITY_MB)) 11348 != (SHR_MEM_VALIDITY_DEV_INFO | SHR_MEM_VALIDITY_MB))
11333 BNX2X_ERR("BAD MCP validity signature\n"); 11349 BNX2X_ERR("BAD MCP validity signature\n");
11334
11335 if (!BP_NOMCP(bp)) {
11336 bp->fw_seq =
11337 (SHMEM_RD(bp, func_mb[BP_FW_MB_IDX(bp)].drv_mb_header) &
11338 DRV_MSG_SEQ_NUMBER_MASK);
11339 BNX2X_DEV_INFO("fw_seq 0x%08x\n", bp->fw_seq);
11340 }
11341} 11350}
11342 11351
11343/** 11352/**
@@ -11593,6 +11602,13 @@ static int bnx2x_cnic_sp_queue(struct net_device *dev,
11593 return -EIO; 11602 return -EIO;
11594#endif 11603#endif
11595 11604
11605 if ((bp->recovery_state != BNX2X_RECOVERY_DONE) &&
11606 (bp->recovery_state != BNX2X_RECOVERY_NIC_LOADING)) {
11607 netdev_err(dev, "Handling parity error recovery. Try again "
11608 "later\n");
11609 return -EAGAIN;
11610 }
11611
11596 spin_lock_bh(&bp->spq_lock); 11612 spin_lock_bh(&bp->spq_lock);
11597 11613
11598 for (i = 0; i < count; i++) { 11614 for (i = 0; i < count; i++) {