From 00b18e3de18aa97e5ebca7759db344663e899c66 Mon Sep 17 00:00:00 2001 From: Wang Xiao W Date: Thu, 10 Sep 2015 12:38:29 +0800 Subject: [PATCH] fm10k/base: fix mailbox phantom messages The phantom messages were a result of incorrectly forgetting to drop already transmitted messages. We would reset pulled, and tail_len but left the head/tail pointers alone. The correct fix is to loop through pulled and drop messages until we've dropped at least as many bytes as we pulled (possibly dropping a message we've only partially transmitted. However, we also have to account for tail_len variable and the 'ack' value as in mbx_pull_head. This means that we need to re-read the HEAD field of the mailbox header. Based on testing, this resolves the phantom messages issue, as well as correctly keeping messages which have yet to be transmitted at all in the Tx FIFO. Thus, we will begin re-transmission once we have re-connected. Signed-off-by: Wang Xiao W --- drivers/net/fm10k/base/fm10k_mbx.c | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/drivers/net/fm10k/base/fm10k_mbx.c b/drivers/net/fm10k/base/fm10k_mbx.c index ad9d81a103..0df588a0fa 100644 --- a/drivers/net/fm10k/base/fm10k_mbx.c +++ b/drivers/net/fm10k/base/fm10k_mbx.c @@ -142,8 +142,8 @@ STATIC u16 fm10k_fifo_head_drop(struct fm10k_mbx_fifo *fifo) * fm10k_fifo_drop_all - Drop all messages in FIFO * @fifo: pointer to FIFO * - * This function resets the head pointer to drop all messages in the FIFO, - * and ensure the FIFO is empty. + * This function resets the head pointer to drop all messages in the FIFO and + * ensure the FIFO is empty. **/ STATIC void fm10k_fifo_drop_all(struct fm10k_mbx_fifo *fifo) { @@ -1075,9 +1075,26 @@ STATIC s32 fm10k_mbx_create_reply(struct fm10k_hw *hw, **/ STATIC void fm10k_mbx_reset_work(struct fm10k_mbx_info *mbx) { + u16 len, head, ack; + /* reset our outgoing max size back to Rx limits */ mbx->max_size = mbx->rx.size - 1; + /* update mbx->pulled to account for tail_len and ack */ + head = FM10K_MSG_HDR_FIELD_GET(mbx->mbx_hdr, HEAD); + ack = fm10k_mbx_index_len(mbx, head, mbx->tail); + mbx->pulled += mbx->tail_len - ack; + + /* now drop any messages which have started or finished transmitting */ + while (fm10k_fifo_head_len(&mbx->tx) && mbx->pulled) { + len = fm10k_fifo_head_drop(&mbx->tx); + mbx->tx_dropped++; + if (mbx->pulled >= len) + mbx->pulled -= len; + else + mbx->pulled = 0; + } + /* just do a quick resysnc to start of message */ mbx->pushed = 0; mbx->pulled = 0; @@ -1774,7 +1791,7 @@ STATIC void fm10k_sm_mbx_disconnect(struct fm10k_hw *hw, mbx->state = FM10K_STATE_CLOSED; mbx->remote = 0; fm10k_mbx_reset_work(mbx); - fm10k_mbx_update_max_size(mbx, 0); + fm10k_fifo_drop_all(&mbx->tx); FM10K_WRITE_REG(hw, mbx->mbmem_reg, 0); } -- 2.20.1