mwifiex: enhance RX reordering to avoid packet drop during host sleep
authorAvinash Patil <patila@marvell.com>
Fri, 28 Sep 2012 02:00:10 +0000 (19:00 -0700)
committerJohn W. Linville <linville@tuxdriver.com>
Fri, 28 Sep 2012 17:54:10 +0000 (13:54 -0400)
Once hostsleep is activated, this patch takes care of not
dropping packets in RX reorder table.

Signed-off-by: Avinash Patil <patila@marvell.com>
Signed-off-by: Bing Zhao <bzhao@marvell.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
drivers/net/wireless/mwifiex/11n_rxreorder.c
drivers/net/wireless/mwifiex/11n_rxreorder.h
drivers/net/wireless/mwifiex/cmdevt.c
drivers/net/wireless/mwifiex/main.h

index 24e2582b467cd309f16b45a3b89d341eb959cd44..9402b93b9a363b350545fb24aad6f67f06afc172 100644 (file)
@@ -302,6 +302,7 @@ mwifiex_11n_create_rx_reorder_tbl(struct mwifiex_private *priv, u8 *ta,
                new_node->start_win = last_seq + 1;
 
        new_node->win_size = win_size;
+       new_node->flags = 0;
 
        new_node->rx_reorder_ptr = kzalloc(sizeof(void *) * win_size,
                                        GFP_KERNEL);
@@ -457,13 +458,20 @@ int mwifiex_11n_rx_reorder_pkt(struct mwifiex_private *priv,
         * If seq_num is less then starting win then ignore and drop the
         * packet
         */
-       if ((start_win + TWOPOW11) > (MAX_TID_VALUE - 1)) {/* Wrap */
-               if (seq_num >= ((start_win + TWOPOW11) &
-                               (MAX_TID_VALUE - 1)) && (seq_num < start_win))
+       if (tbl->flags & RXREOR_FORCE_NO_DROP) {
+               dev_dbg(priv->adapter->dev,
+                       "RXREOR_FORCE_NO_DROP when HS is activated\n");
+               tbl->flags &= ~RXREOR_FORCE_NO_DROP;
+       } else {
+               if ((start_win + TWOPOW11) > (MAX_TID_VALUE - 1)) {
+                       if (seq_num >= ((start_win + TWOPOW11) &
+                                       (MAX_TID_VALUE - 1)) &&
+                           seq_num < start_win)
+                               return -1;
+               } else if ((seq_num < start_win) ||
+                          (seq_num > (start_win + TWOPOW11))) {
                        return -1;
-       } else if ((seq_num < start_win) ||
-                  (seq_num > (start_win + TWOPOW11))) {
-               return -1;
+               }
        }
 
        /*
@@ -474,8 +482,7 @@ int mwifiex_11n_rx_reorder_pkt(struct mwifiex_private *priv,
                seq_num = ((seq_num + win_size) - 1) & (MAX_TID_VALUE - 1);
 
        if (((end_win < start_win) &&
-            (seq_num < (TWOPOW11 - (MAX_TID_VALUE - start_win))) &&
-            (seq_num > end_win)) ||
+            (seq_num < start_win) && (seq_num > end_win)) ||
            ((end_win > start_win) && ((seq_num > end_win) ||
                                       (seq_num < start_win)))) {
                end_win = seq_num;
@@ -637,3 +644,29 @@ void mwifiex_11n_cleanup_reorder_tbl(struct mwifiex_private *priv)
        INIT_LIST_HEAD(&priv->rx_reorder_tbl_ptr);
        mwifiex_reset_11n_rx_seq_num(priv);
 }
+
+/*
+ * This function updates all rx_reorder_tbl's flags.
+ */
+void mwifiex_update_rxreor_flags(struct mwifiex_adapter *adapter, u8 flags)
+{
+       struct mwifiex_private *priv;
+       struct mwifiex_rx_reorder_tbl *tbl;
+       unsigned long lock_flags;
+       int i;
+
+       for (i = 0; i < adapter->priv_num; i++) {
+               priv = adapter->priv[i];
+               if (!priv)
+                       continue;
+               if (list_empty(&priv->rx_reorder_tbl_ptr))
+                       continue;
+
+               spin_lock_irqsave(&priv->rx_reorder_tbl_lock, lock_flags);
+               list_for_each_entry(tbl, &priv->rx_reorder_tbl_ptr, list)
+                       tbl->flags = flags;
+               spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock, lock_flags);
+       }
+
+       return;
+}
index 72848591691a973ac83a5b6efd2481c79ae5354d..4064041ac852737602b8970eff8c40f4070c9117 100644 (file)
 #define BA_SETUP_MAX_PACKET_THRESHOLD  16
 #define BA_SETUP_PACKET_OFFSET         16
 
+enum mwifiex_rxreor_flags {
+       RXREOR_FORCE_NO_DROP    = 1<<0,
+};
+
 static inline void mwifiex_reset_11n_rx_seq_num(struct mwifiex_private *priv)
 {
        memset(priv->rx_seq, 0xff, sizeof(priv->rx_seq));
@@ -73,5 +77,6 @@ struct mwifiex_rx_reorder_tbl *mwifiex_11n_get_rxreorder_tbl(struct
 struct mwifiex_rx_reorder_tbl *
 mwifiex_11n_get_rx_reorder_tbl(struct mwifiex_private *priv, int tid, u8 *ta);
 void mwifiex_11n_del_rx_reorder_tbl_by_ta(struct mwifiex_private *priv, u8 *ta);
+void mwifiex_update_rxreor_flags(struct mwifiex_adapter *adapter, u8 flags);
 
 #endif /* _MWIFIEX_11N_RXREORDER_H_ */
index 225c1a4feeba8f7054f24d016f7380d442948f6a..8d465107f52b2c5073acad20d8d0acbe0485be5e 100644 (file)
@@ -1088,6 +1088,8 @@ mwifiex_hs_activated_event(struct mwifiex_private *priv, u8 activated)
        if (activated) {
                if (priv->adapter->is_hs_configured) {
                        priv->adapter->hs_activated = true;
+                       mwifiex_update_rxreor_flags(priv->adapter,
+                                                   RXREOR_FORCE_NO_DROP);
                        dev_dbg(priv->adapter->dev, "event: hs_activated\n");
                        priv->adapter->hs_activate_wait_q_woken = true;
                        wake_up_interruptible(
index 956312f45e60533495032370bc3840e0c5194ba3..bfb3fa69805c8d34d5d25586ec014c7d71728c9a 100644 (file)
@@ -535,6 +535,7 @@ struct mwifiex_rx_reorder_tbl {
        int win_size;
        void **rx_reorder_ptr;
        struct reorder_tmr_cnxt timer_context;
+       u8 flags;
 };
 
 struct mwifiex_bss_prio_node {