aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/staging/otus/80211core/queue.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/staging/otus/80211core/queue.c')
-rw-r--r--drivers/staging/otus/80211core/queue.c303
1 files changed, 303 insertions, 0 deletions
diff --git a/drivers/staging/otus/80211core/queue.c b/drivers/staging/otus/80211core/queue.c
new file mode 100644
index 000000000000..d294831b5c36
--- /dev/null
+++ b/drivers/staging/otus/80211core/queue.c
@@ -0,0 +1,303 @@
+/*
+ * Copyright (c) 2007-2008 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+/* */
+/* Module Name : queue.c */
+/* */
+/* Abstract */
+/* This module contains queue management functions. */
+/* */
+/* NOTES */
+/* None */
+/* */
+/************************************************************************/
+#include "cprecomp.h"
+#include "queue.h"
+
+
+struct zsQueue* zfQueueCreate(zdev_t* dev, u16_t size)
+{
+ struct zsQueue* q;
+
+ if ((q = (struct zsQueue*)zfwMemAllocate(dev, sizeof(struct zsQueue)
+ + (sizeof(struct zsQueueCell)*(size-1)))) != NULL)
+ {
+ q->size = size;
+ q->sizeMask = size-1;
+ q->head = 0;
+ q->tail = 0;
+ }
+ return q;
+}
+
+void zfQueueDestroy(zdev_t* dev, struct zsQueue* q)
+{
+ u16_t size = sizeof(struct zsQueue) + (sizeof(struct zsQueueCell)*(q->size-1));
+
+ zfQueueFlush(dev, q);
+ zfwMemFree(dev, q, size);
+
+ return;
+}
+
+u16_t zfQueuePutNcs(zdev_t* dev, struct zsQueue* q, zbuf_t* buf, u32_t tick)
+{
+ u16_t ret = ZM_ERR_QUEUE_FULL;
+
+ zm_msg0_mm(ZM_LV_1, "zfQueuePutNcs()");
+
+ if (((q->tail+1)&q->sizeMask) != q->head)
+ {
+ q->cell[q->tail].buf = buf;
+ q->cell[q->tail].tick = tick;
+ q->tail = (q->tail+1) & q->sizeMask;
+ ret = ZM_SUCCESS;
+ }
+
+ return ret;
+}
+
+u16_t zfQueuePut(zdev_t* dev, struct zsQueue* q, zbuf_t* buf, u32_t tick)
+{
+ u16_t ret;
+ zmw_declare_for_critical_section();
+
+ zmw_enter_critical_section(dev);
+
+ ret = zfQueuePutNcs(dev, q, buf, tick);
+
+ zmw_leave_critical_section(dev);
+
+ return ret;
+}
+
+zbuf_t* zfQueueGet(zdev_t* dev, struct zsQueue* q)
+{
+ zbuf_t* buf = NULL;
+ zmw_declare_for_critical_section();
+
+ zmw_enter_critical_section(dev);
+
+ if (q->head != q->tail)
+ {
+ buf = q->cell[q->head].buf;
+ q->head = (q->head+1) & q->sizeMask;
+ }
+
+ zmw_leave_critical_section(dev);
+
+ return buf;
+}
+
+u16_t zfCompareDstwithBuf(zdev_t* dev, zbuf_t* buf, u8_t* addr)
+{
+ u16_t i;
+ u8_t dst[6];
+
+ for (i=0; i<6; i++)
+ {
+ dst[i] = zmw_buf_readb(dev, buf, i);
+ if (dst[i] != addr[i])
+ {
+ return 1+i;
+ }
+ }
+
+ return 0;
+}
+
+
+zbuf_t* zfQueueGetWithMac(zdev_t* dev, struct zsQueue* q, u8_t* addr, u8_t* mb)
+{
+ zbuf_t* buf;
+ zbuf_t* retBuf = NULL;
+ u16_t index, next;
+ zmw_declare_for_critical_section();
+
+ *mb = 0;
+
+ zmw_enter_critical_section(dev);
+
+ index = q->head;
+
+ while (1)
+ {
+ if (index != q->tail)
+ {
+ buf = q->cell[index].buf;
+
+ //if buf's detination address == input addr
+ if (zfCompareDstwithBuf(dev, buf, addr) == 0)
+ {
+ retBuf = buf;
+ //Get it, and trace the whole queue to calculate more bit
+ while ((next =((index+1)&q->sizeMask)) != q->tail)
+ {
+ q->cell[index].buf = q->cell[next].buf;
+ q->cell[index].tick = q->cell[next].tick;
+
+ if ((*mb == 0) && (zfCompareDstwithBuf(dev,
+ q->cell[next].buf, addr) == 0))
+ {
+ *mb = 1;
+ }
+
+ index = next;
+ }
+ q->tail = (q->tail-1) & q->sizeMask;
+
+ zmw_leave_critical_section(dev);
+ return retBuf;
+ }
+ index = (index + 1) & q->sizeMask;
+ } //if (index != q->tail)
+ else
+ {
+ break;
+ }
+ }
+
+ zmw_leave_critical_section(dev);
+
+ return retBuf;
+
+}
+
+void zfQueueFlush(zdev_t* dev, struct zsQueue* q)
+{
+ zbuf_t* buf;
+
+ while ((buf = zfQueueGet(dev, q)) != NULL)
+ {
+ zfwBufFree(dev, buf, 0);
+ }
+
+ return;
+}
+
+void zfQueueAge(zdev_t* dev, struct zsQueue* q, u32_t tick, u32_t msAge)
+{
+ zbuf_t* buf;
+ u32_t buftick;
+ zmw_declare_for_critical_section();
+
+ while (1)
+ {
+ buf = NULL;
+ zmw_enter_critical_section(dev);
+
+ if (q->head != q->tail)
+ {
+ buftick = q->cell[q->head].tick;
+ if (((tick - buftick)*ZM_MS_PER_TICK) > msAge)
+ {
+ buf = q->cell[q->head].buf;
+ q->head = (q->head+1) & q->sizeMask;
+ }
+ }
+
+ zmw_leave_critical_section(dev);
+
+ if (buf != NULL)
+ {
+ zm_msg0_mm(ZM_LV_0, "Age frame in queue!");
+ zfwBufFree(dev, buf, 0);
+ }
+ else
+ {
+ break;
+ }
+ }
+ return;
+}
+
+
+u8_t zfQueueRemovewithIndex(zdev_t* dev, struct zsQueue* q, u16_t index, u8_t* addr)
+{
+ u16_t next;
+ u8_t mb = 0;
+
+ //trace the whole queue to calculate more bit
+ while ((next =((index+1)&q->sizeMask)) != q->tail)
+ {
+ q->cell[index].buf = q->cell[next].buf;
+ q->cell[index].tick = q->cell[next].tick;
+
+ if ((mb == 0) && (zfCompareDstwithBuf(dev,
+ q->cell[next].buf, addr) == 0))
+ {
+ mb = 1;
+ }
+
+ index = next;
+ }
+ q->tail = (q->tail-1) & q->sizeMask;
+
+ return mb;
+
+}
+
+void zfQueueGenerateUapsdTim(zdev_t* dev, struct zsQueue* q,
+ u8_t* uniBitMap, u16_t* highestByte)
+{
+ zbuf_t* psBuf;
+ u8_t dst[6];
+ u16_t id, aid, index, i;
+ u16_t bitPosition;
+ u16_t bytePosition;
+ zmw_get_wlan_dev(dev);
+ zmw_declare_for_critical_section();
+
+ zmw_enter_critical_section(dev);
+
+ index = q->head;
+
+ while (index != q->tail)
+ {
+ psBuf = q->cell[index].buf;
+ for (i=0; i<6; i++)
+ {
+ dst[i] = zmw_buf_readb(dev, psBuf, i);
+ }
+ /* TODO : use u8_t* fot MAC address */
+ if (((id = zfApFindSta(dev, (u16_t*)dst)) != 0xffff)
+ && (wd->ap.staTable[id].psMode != 0))
+ {
+ /* Calculate PVB only when all AC are delivery-enabled */
+ if ((wd->ap.staTable[id].qosInfo & 0xf) == 0xf)
+ {
+ aid = id + 1;
+ bitPosition = (1 << (aid & 0x7));
+ bytePosition = (aid >> 3);
+ uniBitMap[bytePosition] |= bitPosition;
+
+ if (bytePosition>*highestByte)
+ {
+ *highestByte = bytePosition;
+ }
+ }
+ index = (index+1) & q->sizeMask;
+ }
+ else
+ {
+ /* Free garbage UAPSD frame */
+ zfQueueRemovewithIndex(dev, q, index, dst);
+ zfwBufFree(dev, psBuf, 0);
+ }
+ }
+ zmw_leave_critical_section(dev);
+
+ return;
+}