iwlwifi: pcie: Refactor iwl_queue_space
authorIdo Yariv <ido@wizery.com>
Mon, 15 Jul 2013 15:51:48 +0000 (11:51 -0400)
committerJohannes Berg <johannes.berg@intel.com>
Fri, 9 Aug 2013 12:38:01 +0000 (14:38 +0200)
Reduce the ambiguity spares to a single element if the window size is not
smaller than the queue size. If smaller, no spares are required at all.

Signed-off-by: Ido Yariv <ido@wizery.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
drivers/net/wireless/iwlwifi/pcie/tx.c

index 011167c22da859e627b39263f0aeae708d9a11f6..12c9c0030da667b7b8334bcd77b8eee16ebfd888 100644 (file)
  ***************************************************/
 static int iwl_queue_space(const struct iwl_queue *q)
 {
-       int s = q->read_ptr - q->write_ptr;
-
-       if (q->read_ptr > q->write_ptr)
-               s -= q->n_bd;
-
-       if (s <= 0)
-               s += q->n_window;
-       /* keep some reserve to not confuse empty and full situations */
-       s -= 2;
-       if (s < 0)
-               s = 0;
-       return s;
+       unsigned int max;
+       unsigned int used;
+
+       /*
+        * To avoid ambiguity between empty and completely full queues, there
+        * should always be less than q->n_bd elements in the queue.
+        * If q->n_window is smaller than q->n_bd, there is no need to reserve
+        * any queue entries for this purpose.
+        */
+       if (q->n_window < q->n_bd)
+               max = q->n_window;
+       else
+               max = q->n_bd - 1;
+
+       /*
+        * q->n_bd is a power of 2, so the following is equivalent to modulo by
+        * q->n_bd and is well defined for negative dividends.
+        */
+       used = (q->write_ptr - q->read_ptr) & (q->n_bd - 1);
+
+       if (WARN_ON(used > max))
+               return 0;
+
+       return max - used;
 }
 
 /*