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 | |
| 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>
| -rw-r--r-- | drivers/net/bnx2.c | 44 | ||||
| -rw-r--r-- | drivers/net/bnx2.h | 4 |
2 files changed, 25 insertions, 23 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 | ||
diff --git a/drivers/net/bnx2.h b/drivers/net/bnx2.h index 8a70311d781f..a99b04143f69 100644 --- a/drivers/net/bnx2.h +++ b/drivers/net/bnx2.h | |||
| @@ -3999,7 +3999,7 @@ struct bnx2 { | |||
| 3999 | u16 bus_speed_mhz; | 3999 | u16 bus_speed_mhz; |
| 4000 | u8 wol; | 4000 | u8 wol; |
| 4001 | 4001 | ||
| 4002 | u8 fw_timed_out; | 4002 | u8 pad; |
| 4003 | 4003 | ||
| 4004 | u16 fw_wr_seq; | 4004 | u16 fw_wr_seq; |
| 4005 | u16 fw_drv_pulse_wr_seq; | 4005 | u16 fw_drv_pulse_wr_seq; |
| @@ -4173,7 +4173,7 @@ struct fw_info { | |||
| 4173 | * the firmware has timed out, the driver will assume there is no firmware | 4173 | * the firmware has timed out, the driver will assume there is no firmware |
| 4174 | * running and there won't be any firmware-driver synchronization during a | 4174 | * running and there won't be any firmware-driver synchronization during a |
| 4175 | * driver reset. */ | 4175 | * driver reset. */ |
| 4176 | #define FW_ACK_TIME_OUT_MS 50 | 4176 | #define FW_ACK_TIME_OUT_MS 100 |
| 4177 | 4177 | ||
| 4178 | 4178 | ||
| 4179 | #define BNX2_DRV_RESET_SIGNATURE 0x00000000 | 4179 | #define BNX2_DRV_RESET_SIGNATURE 0x00000000 |
