Commit a11fa2be authored by Michael Chan's avatar Michael Chan Committed by David S. Miller

bnxt_en: Improve the delay logic for firmware response.

The current code has 2 problems:

1. The maximum wait time is not long enough.  It is about 60% of the
duration specified by the firmware.  It is calling usleep_range(600, 800)
for every 1 msec we are supposed to wait.

2. The granularity of the delay is too coarse.  Many simple firmware
commands finish in 25 usec or less.

We fix these 2 issues by multiplying the original 1 msec loop counter by
40 and calling usleep_range(25, 40) for each iteration.

There is also a second delay loop to wait for the last DMA word to
complete.  This delay loop should be a very short 5 usec wait.

This change results in much faster bring-up/down time:

Before the patch:

time ip link set p4p1 up

real    0m0.120s
user    0m0.001s
sys     0m0.009s

After the patch:

time ip link set p4p1 up

real    0m0.030s
user    0m0.000s
sys     0m0.010s
Signed-off-by: default avatarMichael Chan <michael.chan@broadcom.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent d0a42d6f
...@@ -2780,7 +2780,7 @@ void bnxt_hwrm_cmd_hdr_init(struct bnxt *bp, void *request, u16 req_type, ...@@ -2780,7 +2780,7 @@ void bnxt_hwrm_cmd_hdr_init(struct bnxt *bp, void *request, u16 req_type,
static int bnxt_hwrm_do_send_msg(struct bnxt *bp, void *msg, u32 msg_len, static int bnxt_hwrm_do_send_msg(struct bnxt *bp, void *msg, u32 msg_len,
int timeout, bool silent) int timeout, bool silent)
{ {
int i, intr_process, rc; int i, intr_process, rc, tmo_count;
struct input *req = msg; struct input *req = msg;
u32 *data = msg; u32 *data = msg;
__le32 *resp_len, *valid; __le32 *resp_len, *valid;
...@@ -2809,11 +2809,12 @@ static int bnxt_hwrm_do_send_msg(struct bnxt *bp, void *msg, u32 msg_len, ...@@ -2809,11 +2809,12 @@ static int bnxt_hwrm_do_send_msg(struct bnxt *bp, void *msg, u32 msg_len,
timeout = DFLT_HWRM_CMD_TIMEOUT; timeout = DFLT_HWRM_CMD_TIMEOUT;
i = 0; i = 0;
tmo_count = timeout * 40;
if (intr_process) { if (intr_process) {
/* Wait until hwrm response cmpl interrupt is processed */ /* Wait until hwrm response cmpl interrupt is processed */
while (bp->hwrm_intr_seq_id != HWRM_SEQ_ID_INVALID && while (bp->hwrm_intr_seq_id != HWRM_SEQ_ID_INVALID &&
i++ < timeout) { i++ < tmo_count) {
usleep_range(600, 800); usleep_range(25, 40);
} }
if (bp->hwrm_intr_seq_id != HWRM_SEQ_ID_INVALID) { if (bp->hwrm_intr_seq_id != HWRM_SEQ_ID_INVALID) {
...@@ -2824,15 +2825,15 @@ static int bnxt_hwrm_do_send_msg(struct bnxt *bp, void *msg, u32 msg_len, ...@@ -2824,15 +2825,15 @@ static int bnxt_hwrm_do_send_msg(struct bnxt *bp, void *msg, u32 msg_len,
} else { } else {
/* Check if response len is updated */ /* Check if response len is updated */
resp_len = bp->hwrm_cmd_resp_addr + HWRM_RESP_LEN_OFFSET; resp_len = bp->hwrm_cmd_resp_addr + HWRM_RESP_LEN_OFFSET;
for (i = 0; i < timeout; i++) { for (i = 0; i < tmo_count; i++) {
len = (le32_to_cpu(*resp_len) & HWRM_RESP_LEN_MASK) >> len = (le32_to_cpu(*resp_len) & HWRM_RESP_LEN_MASK) >>
HWRM_RESP_LEN_SFT; HWRM_RESP_LEN_SFT;
if (len) if (len)
break; break;
usleep_range(600, 800); usleep_range(25, 40);
} }
if (i >= timeout) { if (i >= tmo_count) {
netdev_err(bp->dev, "Error (timeout: %d) msg {0x%x 0x%x} len:%d\n", netdev_err(bp->dev, "Error (timeout: %d) msg {0x%x 0x%x} len:%d\n",
timeout, le16_to_cpu(req->req_type), timeout, le16_to_cpu(req->req_type),
le16_to_cpu(req->seq_id), *resp_len); le16_to_cpu(req->seq_id), *resp_len);
...@@ -2841,13 +2842,13 @@ static int bnxt_hwrm_do_send_msg(struct bnxt *bp, void *msg, u32 msg_len, ...@@ -2841,13 +2842,13 @@ static int bnxt_hwrm_do_send_msg(struct bnxt *bp, void *msg, u32 msg_len,
/* Last word of resp contains valid bit */ /* Last word of resp contains valid bit */
valid = bp->hwrm_cmd_resp_addr + len - 4; valid = bp->hwrm_cmd_resp_addr + len - 4;
for (i = 0; i < timeout; i++) { for (i = 0; i < 5; i++) {
if (le32_to_cpu(*valid) & HWRM_RESP_VALID_MASK) if (le32_to_cpu(*valid) & HWRM_RESP_VALID_MASK)
break; break;
usleep_range(600, 800); udelay(1);
} }
if (i >= timeout) { if (i >= 5) {
netdev_err(bp->dev, "Error (timeout: %d) msg {0x%x 0x%x} len:%d v:%d\n", netdev_err(bp->dev, "Error (timeout: %d) msg {0x%x 0x%x} len:%d v:%d\n",
timeout, le16_to_cpu(req->req_type), timeout, le16_to_cpu(req->req_type),
le16_to_cpu(req->seq_id), len, *valid); le16_to_cpu(req->seq_id), len, *valid);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment