*   published by the Free Software Foundation.
  */
 
+#include <linux/circ_buf.h>
 #include <linux/firmware.h>
 #include <linux/mmc/card.h>
 #include <linux/mmc/sdio_func.h>
        priv->tx_dev.qtail = (priv->tx_dev.qtail + 1) % TX_DEVICE_BUFF_SIZE;
 }
 
-static inline unsigned int cnt_txqbody(struct ks_wlan_private *priv)
+static inline bool txq_has_space(struct ks_wlan_private *priv)
 {
-       unsigned int tx_cnt = priv->tx_dev.qtail - priv->tx_dev.qhead;
-
-       return (tx_cnt + TX_DEVICE_BUFF_SIZE) % TX_DEVICE_BUFF_SIZE;
+       return (CIRC_SPACE(priv->tx_dev.qhead, priv->tx_dev.qtail,
+                          TX_DEVICE_BUFF_SIZE) > 0);
 }
 
 static inline void inc_rxqhead(struct ks_wlan_private *priv)
        priv->rx_dev.qtail = (priv->rx_dev.qtail + 1) % RX_DEVICE_BUFF_SIZE;
 }
 
-static inline unsigned int cnt_rxqbody(struct ks_wlan_private *priv)
+static inline bool rxq_has_space(struct ks_wlan_private *priv)
+{
+       return (CIRC_SPACE(priv->rx_dev.qhead, priv->rx_dev.qtail,
+                          RX_DEVICE_BUFF_SIZE) > 0);
+}
+
+static inline unsigned int txq_count(struct ks_wlan_private *priv)
 {
-       unsigned int rx_cnt = priv->rx_dev.qtail - priv->rx_dev.qhead;
+       return CIRC_CNT_TO_END(priv->tx_dev.qhead, priv->tx_dev.qtail,
+                              TX_DEVICE_BUFF_SIZE);
+}
 
-       return (rx_cnt + RX_DEVICE_BUFF_SIZE) % RX_DEVICE_BUFF_SIZE;
+static inline unsigned int rxq_count(struct ks_wlan_private *priv)
+{
+       return CIRC_CNT_TO_END(priv->rx_dev.qhead, priv->rx_dev.qtail,
+                              RX_DEVICE_BUFF_SIZE);
 }
 
 /* Read single byte from device address into byte (CMD52) */
                   atomic_read(&priv->psstatus.status),
                   atomic_read(&priv->psstatus.confirm_wait),
                   atomic_read(&priv->psstatus.snooze_guard),
-                  cnt_txqbody(priv));
+                  txq_count(priv));
 
        if (atomic_read(&priv->psstatus.confirm_wait) ||
            atomic_read(&priv->psstatus.snooze_guard) ||
-           cnt_txqbody(priv)) {
+           txq_has_space(priv)) {
                queue_delayed_work(priv->wq, &priv->rw_dwork, 0);
                return;
        }
                goto err_complete;
        }
 
-       if ((TX_DEVICE_BUFF_SIZE - 1) <= cnt_txqbody(priv)) {
+       if ((TX_DEVICE_BUFF_SIZE - 1) <= txq_count(priv)) {
                netdev_err(priv->net_dev, "tx buffer overflow\n");
                ret = -EOVERFLOW;
                goto err_complete;
        struct tx_device_buffer *sp;
        int ret;
 
-       if (cnt_txqbody(priv) <= 0 ||
+       if (!txq_has_space(priv) ||
            atomic_read(&priv->psstatus.status) == PS_SNOOZE)
                return;
 
                (*sp->complete_handler)(priv, sp->skb);
        inc_txqhead(priv);
 
-       if (cnt_txqbody(priv) > 0)
+       if (txq_has_space(priv))
                queue_delayed_work(priv->wq, &priv->rw_dwork, 0);
 }
 
        result = enqueue_txdev(priv, p, size, complete_handler, skb);
        spin_unlock(&priv->tx_dev.tx_dev_lock);
 
-       if (cnt_txqbody(priv) > 0)
+       if (txq_has_space(priv))
                queue_delayed_work(priv->wq, &priv->rw_dwork, 0);
 
        return result;
        struct ks_wlan_private *priv = (struct ks_wlan_private *)dev;
        struct rx_device_buffer *rp;
 
-       if (cnt_rxqbody(priv) > 0 && priv->dev_state >= DEVICE_STATE_BOOT) {
+       if (rxq_has_space(priv) && priv->dev_state >= DEVICE_STATE_BOOT) {
                rp = &priv->rx_dev.rx_dev_buff[priv->rx_dev.qhead];
                hostif_receive(priv, rp->data, rp->size);
                inc_rxqhead(priv);
 
-               if (cnt_rxqbody(priv) > 0)
+               if (rxq_has_space(priv))
                        tasklet_schedule(&priv->rx_bh_task);
        }
 }
        unsigned short event = 0;
 
        /* receive data */
-       if (cnt_rxqbody(priv) >= (RX_DEVICE_BUFF_SIZE - 1)) {
+       if (rxq_count(priv) >= (RX_DEVICE_BUFF_SIZE - 1)) {
                netdev_err(priv->net_dev, "rx buffer overflow\n");
                return;
        }
 
        /* power save wakeup */
        if (atomic_read(&priv->psstatus.status) == PS_SNOOZE) {
-               if (cnt_txqbody(priv) > 0) {
+               if (txq_has_space(priv)) {
                        ks_wlan_hw_wakeup_request(priv);
                        queue_delayed_work(priv->wq, &priv->rw_dwork, 1);
                }
 
                if (byte & WSTATUS_MASK) {
                        if (atomic_read(&priv->psstatus.status) == PS_SNOOZE) {
-                               if (cnt_txqbody(priv)) {
+                               if (txq_has_space(priv)) {
                                        ks_wlan_hw_wakeup_request(priv);
                                        queue_delayed_work(priv->wq,
                                                           &priv->rw_dwork, 1);
        struct tx_device_buffer *sp;
 
        /* tx buffer clear */
-       while (cnt_txqbody(priv) > 0) {
+       while (txq_has_space(priv)) {
                sp = &priv->tx_dev.tx_dev_buff[priv->tx_dev.qhead];
                kfree(sp->sendp);
                if (sp->complete_handler)       /* TX Complete */