aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Chan <mchan@broadcom.com>2006-01-23 19:07:10 -0500
committerDavid S. Miller <davem@davemloft.net>2006-01-23 19:07:10 -0500
commitb090ae2b59f3db57732340c6af3beceec8d6c148 (patch)
treed776af0e28bdbce20be5589c26ceab644778e368
parente29054f92d7d575631691865c1b95bee5bc974cc (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.c44
-rw-r--r--drivers/net/bnx2.h4
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
1329static int 1329static int
1330bnx2_fw_sync(struct bnx2 *bp, u32 msg_data) 1330bnx2_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
3083bnx2_init_chip(struct bnx2 *bp) 3083bnx2_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