diff options
author | Michael Chan <mchan@broadcom.com> | 2006-01-23 19:07:10 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2006-01-23 19:07:10 -0500 |
commit | b090ae2b59f3db57732340c6af3beceec8d6c148 (patch) | |
tree | d776af0e28bdbce20be5589c26ceab644778e368 /drivers/net/bnx2.c | |
parent | e29054f92d7d575631691865c1b95bee5bc974cc (diff) |
[BNX2]: Improve handshake with firmware
Improve handshake with bootcode with the following changes:
1. Increase timeout to 100msec and use msleep instead of udelay.
2. Add more error checking for timeouts and errors.
Signed-off-by: Michael Chan <mchan@broadcom.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/bnx2.c')
-rw-r--r-- | drivers/net/bnx2.c | 44 |
1 files changed, 23 insertions, 21 deletions
diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c index 790dc926acae..3486324b6919 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c | |||
@@ -1327,43 +1327,45 @@ bnx2_set_mac_loopback(struct bnx2 *bp) | |||
1327 | } | 1327 | } |
1328 | 1328 | ||
1329 | static int | 1329 | static int |
1330 | bnx2_fw_sync(struct bnx2 *bp, u32 msg_data) | 1330 | bnx2_fw_sync(struct bnx2 *bp, u32 msg_data, int silent) |
1331 | { | 1331 | { |
1332 | int i; | 1332 | int i; |
1333 | u32 val; | 1333 | u32 val; |
1334 | 1334 | ||
1335 | if (bp->fw_timed_out) | ||
1336 | return -EBUSY; | ||
1337 | |||
1338 | bp->fw_wr_seq++; | 1335 | bp->fw_wr_seq++; |
1339 | msg_data |= bp->fw_wr_seq; | 1336 | msg_data |= bp->fw_wr_seq; |
1340 | 1337 | ||
1341 | REG_WR_IND(bp, bp->shmem_base + BNX2_DRV_MB, msg_data); | 1338 | REG_WR_IND(bp, bp->shmem_base + BNX2_DRV_MB, msg_data); |
1342 | 1339 | ||
1343 | /* wait for an acknowledgement. */ | 1340 | /* wait for an acknowledgement. */ |
1344 | for (i = 0; i < (FW_ACK_TIME_OUT_MS * 1000)/5; i++) { | 1341 | for (i = 0; i < (FW_ACK_TIME_OUT_MS / 10); i++) { |
1345 | udelay(5); | 1342 | msleep(10); |
1346 | 1343 | ||
1347 | val = REG_RD_IND(bp, bp->shmem_base + BNX2_FW_MB); | 1344 | val = REG_RD_IND(bp, bp->shmem_base + BNX2_FW_MB); |
1348 | 1345 | ||
1349 | if ((val & BNX2_FW_MSG_ACK) == (msg_data & BNX2_DRV_MSG_SEQ)) | 1346 | if ((val & BNX2_FW_MSG_ACK) == (msg_data & BNX2_DRV_MSG_SEQ)) |
1350 | break; | 1347 | break; |
1351 | } | 1348 | } |
1349 | if ((msg_data & BNX2_DRV_MSG_DATA) == BNX2_DRV_MSG_DATA_WAIT0) | ||
1350 | return 0; | ||
1352 | 1351 | ||
1353 | /* If we timed out, inform the firmware that this is the case. */ | 1352 | /* If we timed out, inform the firmware that this is the case. */ |
1354 | if (((val & BNX2_FW_MSG_ACK) != (msg_data & BNX2_DRV_MSG_SEQ)) && | 1353 | if ((val & BNX2_FW_MSG_ACK) != (msg_data & BNX2_DRV_MSG_SEQ)) { |
1355 | ((msg_data & BNX2_DRV_MSG_DATA) != BNX2_DRV_MSG_DATA_WAIT0)) { | 1354 | if (!silent) |
1355 | printk(KERN_ERR PFX "fw sync timeout, reset code = " | ||
1356 | "%x\n", msg_data); | ||
1356 | 1357 | ||
1357 | msg_data &= ~BNX2_DRV_MSG_CODE; | 1358 | msg_data &= ~BNX2_DRV_MSG_CODE; |
1358 | msg_data |= BNX2_DRV_MSG_CODE_FW_TIMEOUT; | 1359 | msg_data |= BNX2_DRV_MSG_CODE_FW_TIMEOUT; |
1359 | 1360 | ||
1360 | REG_WR_IND(bp, bp->shmem_base + BNX2_DRV_MB, msg_data); | 1361 | REG_WR_IND(bp, bp->shmem_base + BNX2_DRV_MB, msg_data); |
1361 | 1362 | ||
1362 | bp->fw_timed_out = 1; | ||
1363 | |||
1364 | return -EBUSY; | 1363 | return -EBUSY; |
1365 | } | 1364 | } |
1366 | 1365 | ||
1366 | if ((val & BNX2_FW_MSG_STATUS_MASK) != BNX2_FW_MSG_STATUS_OK) | ||
1367 | return -EIO; | ||
1368 | |||
1367 | return 0; | 1369 | return 0; |
1368 | } | 1370 | } |
1369 | 1371 | ||
@@ -2374,7 +2376,7 @@ bnx2_set_power_state(struct bnx2 *bp, pci_power_t state) | |||
2374 | wol_msg = BNX2_DRV_MSG_CODE_SUSPEND_NO_WOL; | 2376 | wol_msg = BNX2_DRV_MSG_CODE_SUSPEND_NO_WOL; |
2375 | } | 2377 | } |
2376 | 2378 | ||
2377 | bnx2_fw_sync(bp, BNX2_DRV_MSG_DATA_WAIT3 | wol_msg); | 2379 | bnx2_fw_sync(bp, BNX2_DRV_MSG_DATA_WAIT3 | wol_msg, 0); |
2378 | 2380 | ||
2379 | pmcsr &= ~PCI_PM_CTRL_STATE_MASK; | 2381 | pmcsr &= ~PCI_PM_CTRL_STATE_MASK; |
2380 | if ((CHIP_ID(bp) == CHIP_ID_5706_A0) || | 2382 | if ((CHIP_ID(bp) == CHIP_ID_5706_A0) || |
@@ -3014,16 +3016,14 @@ bnx2_reset_chip(struct bnx2 *bp, u32 reset_code) | |||
3014 | val = REG_RD(bp, BNX2_MISC_ENABLE_CLR_BITS); | 3016 | val = REG_RD(bp, BNX2_MISC_ENABLE_CLR_BITS); |
3015 | udelay(5); | 3017 | udelay(5); |
3016 | 3018 | ||
3019 | /* Wait for the firmware to tell us it is ok to issue a reset. */ | ||
3020 | bnx2_fw_sync(bp, BNX2_DRV_MSG_DATA_WAIT0 | reset_code, 1); | ||
3021 | |||
3017 | /* Deposit a driver reset signature so the firmware knows that | 3022 | /* Deposit a driver reset signature so the firmware knows that |
3018 | * this is a soft reset. */ | 3023 | * this is a soft reset. */ |
3019 | REG_WR_IND(bp, bp->shmem_base + BNX2_DRV_RESET_SIGNATURE, | 3024 | REG_WR_IND(bp, bp->shmem_base + BNX2_DRV_RESET_SIGNATURE, |
3020 | BNX2_DRV_RESET_SIGNATURE_MAGIC); | 3025 | BNX2_DRV_RESET_SIGNATURE_MAGIC); |
3021 | 3026 | ||
3022 | bp->fw_timed_out = 0; | ||
3023 | |||
3024 | /* Wait for the firmware to tell us it is ok to issue a reset. */ | ||
3025 | bnx2_fw_sync(bp, BNX2_DRV_MSG_DATA_WAIT0 | reset_code); | ||
3026 | |||
3027 | /* Do a dummy read to force the chip to complete all current transaction | 3027 | /* Do a dummy read to force the chip to complete all current transaction |
3028 | * before we issue a reset. */ | 3028 | * before we issue a reset. */ |
3029 | val = REG_RD(bp, BNX2_MISC_ID); | 3029 | val = REG_RD(bp, BNX2_MISC_ID); |
@@ -3062,10 +3062,10 @@ bnx2_reset_chip(struct bnx2 *bp, u32 reset_code) | |||
3062 | return -ENODEV; | 3062 | return -ENODEV; |
3063 | } | 3063 | } |
3064 | 3064 | ||
3065 | bp->fw_timed_out = 0; | ||
3066 | |||
3067 | /* Wait for the firmware to finish its initialization. */ | 3065 | /* Wait for the firmware to finish its initialization. */ |
3068 | bnx2_fw_sync(bp, BNX2_DRV_MSG_DATA_WAIT1 | reset_code); | 3066 | rc = bnx2_fw_sync(bp, BNX2_DRV_MSG_DATA_WAIT1 | reset_code, 0); |
3067 | if (rc) | ||
3068 | return rc; | ||
3069 | 3069 | ||
3070 | if (CHIP_ID(bp) == CHIP_ID_5706_A0) { | 3070 | if (CHIP_ID(bp) == CHIP_ID_5706_A0) { |
3071 | /* Adjust the voltage regular to two steps lower. The default | 3071 | /* Adjust the voltage regular to two steps lower. The default |
@@ -3083,6 +3083,7 @@ static int | |||
3083 | bnx2_init_chip(struct bnx2 *bp) | 3083 | bnx2_init_chip(struct bnx2 *bp) |
3084 | { | 3084 | { |
3085 | u32 val; | 3085 | u32 val; |
3086 | int rc; | ||
3086 | 3087 | ||
3087 | /* Make sure the interrupt is not active. */ | 3088 | /* Make sure the interrupt is not active. */ |
3088 | REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD, BNX2_PCICFG_INT_ACK_CMD_MASK_INT); | 3089 | REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD, BNX2_PCICFG_INT_ACK_CMD_MASK_INT); |
@@ -3225,14 +3226,15 @@ bnx2_init_chip(struct bnx2 *bp) | |||
3225 | /* Initialize the receive filter. */ | 3226 | /* Initialize the receive filter. */ |
3226 | bnx2_set_rx_mode(bp->dev); | 3227 | bnx2_set_rx_mode(bp->dev); |
3227 | 3228 | ||
3228 | bnx2_fw_sync(bp, BNX2_DRV_MSG_DATA_WAIT2 | BNX2_DRV_MSG_CODE_RESET); | 3229 | rc = bnx2_fw_sync(bp, BNX2_DRV_MSG_DATA_WAIT2 | BNX2_DRV_MSG_CODE_RESET, |
3230 | 0); | ||
3229 | 3231 | ||
3230 | REG_WR(bp, BNX2_MISC_ENABLE_SET_BITS, 0x5ffffff); | 3232 | REG_WR(bp, BNX2_MISC_ENABLE_SET_BITS, 0x5ffffff); |
3231 | REG_RD(bp, BNX2_MISC_ENABLE_SET_BITS); | 3233 | REG_RD(bp, BNX2_MISC_ENABLE_SET_BITS); |
3232 | 3234 | ||
3233 | udelay(20); | 3235 | udelay(20); |
3234 | 3236 | ||
3235 | return 0; | 3237 | return rc; |
3236 | } | 3238 | } |
3237 | 3239 | ||
3238 | 3240 | ||