Merge tag 'renesas-boards-cleanups2-for-v3.19' of git://git.kernel.org/pub/scm/linux...
[firefly-linux-kernel-4.4.55.git] / drivers / net / wireless / mwifiex / 11n_rxreorder.c
index 40057079ffb9537eae9549518be3e5df29f1a16b..5ef5a0eeba50eb682d30e5879f565ac48ad217e4 100644 (file)
@@ -196,6 +196,7 @@ mwifiex_del_rx_reorder_entry(struct mwifiex_private *priv,
        mwifiex_11n_dispatch_pkt_until_start_win(priv, tbl, start_win);
 
        del_timer_sync(&tbl->timer_context.timer);
+       tbl->timer_context.timer_is_set = false;
 
        spin_lock_irqsave(&priv->rx_reorder_tbl_lock, flags);
        list_del(&tbl->list);
@@ -297,6 +298,7 @@ mwifiex_flush_data(unsigned long context)
                (struct reorder_tmr_cnxt *) context;
        int start_win, seq_num;
 
+       ctx->timer_is_set = false;
        seq_num = mwifiex_11n_find_last_seq_num(ctx);
 
        if (seq_num < 0)
@@ -385,6 +387,7 @@ mwifiex_11n_create_rx_reorder_tbl(struct mwifiex_private *priv, u8 *ta,
 
        new_node->timer_context.ptr = new_node;
        new_node->timer_context.priv = priv;
+       new_node->timer_context.timer_is_set = false;
 
        init_timer(&new_node->timer_context.timer);
        new_node->timer_context.timer.function = mwifiex_flush_data;
@@ -399,6 +402,22 @@ mwifiex_11n_create_rx_reorder_tbl(struct mwifiex_private *priv, u8 *ta,
        spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock, flags);
 }
 
+static void
+mwifiex_11n_rxreorder_timer_restart(struct mwifiex_rx_reorder_tbl *tbl)
+{
+       u32 min_flush_time;
+
+       if (tbl->win_size >= MWIFIEX_BA_WIN_SIZE_32)
+               min_flush_time = MIN_FLUSH_TIMER_15_MS;
+       else
+               min_flush_time = MIN_FLUSH_TIMER_MS;
+
+       mod_timer(&tbl->timer_context.timer,
+                 jiffies + msecs_to_jiffies(min_flush_time * tbl->win_size));
+
+       tbl->timer_context.timer_is_set = true;
+}
+
 /*
  * This function prepares command for adding a BA request.
  *
@@ -523,31 +542,31 @@ int mwifiex_11n_rx_reorder_pkt(struct mwifiex_private *priv,
                                u8 *ta, u8 pkt_type, void *payload)
 {
        struct mwifiex_rx_reorder_tbl *tbl;
-       int start_win, end_win, win_size;
+       int prev_start_win, start_win, end_win, win_size;
        u16 pkt_index;
        bool init_window_shift = false;
+       int ret = 0;
 
        tbl = mwifiex_11n_get_rx_reorder_tbl(priv, tid, ta);
        if (!tbl) {
                if (pkt_type != PKT_TYPE_BAR)
                        mwifiex_11n_dispatch_pkt(priv, payload);
-               return 0;
+               return ret;
        }
 
        if ((pkt_type == PKT_TYPE_AMSDU) && !tbl->amsdu) {
                mwifiex_11n_dispatch_pkt(priv, payload);
-               return 0;
+               return ret;
        }
 
        start_win = tbl->start_win;
+       prev_start_win = start_win;
        win_size = tbl->win_size;
        end_win = ((start_win + win_size) - 1) & (MAX_TID_VALUE - 1);
        if (tbl->flags & RXREOR_INIT_WINDOW_SHIFT) {
                init_window_shift = true;
                tbl->flags &= ~RXREOR_INIT_WINDOW_SHIFT;
        }
-       mod_timer(&tbl->timer_context.timer,
-                 jiffies + msecs_to_jiffies(MIN_FLUSH_TIMER_MS * win_size));
 
        if (tbl->flags & RXREOR_FORCE_NO_DROP) {
                dev_dbg(priv->adapter->dev,
@@ -568,11 +587,14 @@ int mwifiex_11n_rx_reorder_pkt(struct mwifiex_private *priv,
                if ((start_win + TWOPOW11) > (MAX_TID_VALUE - 1)) {
                        if (seq_num >= ((start_win + TWOPOW11) &
                                        (MAX_TID_VALUE - 1)) &&
-                           seq_num < start_win)
-                               return -1;
+                           seq_num < start_win) {
+                               ret = -1;
+                               goto done;
+                       }
                } else if ((seq_num < start_win) ||
-                          (seq_num > (start_win + TWOPOW11))) {
-                       return -1;
+                          (seq_num >= (start_win + TWOPOW11))) {
+                       ret = -1;
+                       goto done;
                }
        }
 
@@ -601,8 +623,10 @@ int mwifiex_11n_rx_reorder_pkt(struct mwifiex_private *priv,
                else
                        pkt_index = (seq_num+MAX_TID_VALUE) - start_win;
 
-               if (tbl->rx_reorder_ptr[pkt_index])
-                       return -1;
+               if (tbl->rx_reorder_ptr[pkt_index]) {
+                       ret = -1;
+                       goto done;
+               }
 
                tbl->rx_reorder_ptr[pkt_index] = payload;
        }
@@ -613,7 +637,11 @@ int mwifiex_11n_rx_reorder_pkt(struct mwifiex_private *priv,
         */
        mwifiex_11n_scan_and_dispatch(priv, tbl);
 
-       return 0;
+done:
+       if (!tbl->timer_context.timer_is_set ||
+           prev_start_win != tbl->start_win)
+               mwifiex_11n_rxreorder_timer_restart(tbl);
+       return ret;
 }
 
 /*