fm10k/base: fix mailbox phantom messages
authorWang Xiao W <xiao.w.wang@intel.com>
Thu, 10 Sep 2015 04:38:29 +0000 (12:38 +0800)
committerThomas Monjalon <thomas.monjalon@6wind.com>
Wed, 7 Oct 2015 11:25:07 +0000 (13:25 +0200)
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 <xiao.w.wang@intel.com>
drivers/net/fm10k/base/fm10k_mbx.c

index ad9d81a..0df588a 100644 (file)
@@ -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);
 }