backport workqueue code from AOSP jorjin
authornotaz <notasas@gmail.com>
Mon, 9 Feb 2015 01:54:24 +0000 (03:54 +0200)
committernotaz <notasas@gmail.com>
Mon, 9 Feb 2015 01:58:30 +0000 (03:58 +0200)
sta_dk/common/inc/memMngrEx.h
sta_dk/pform/linux/build/common.inc
sta_dk/pform/linux/inc/esta_drv.h
sta_dk/pform/linux/src/esta_drv.c
sta_dk/pform/linux/src/osapi.c

index 196a780..1a191db 100644 (file)
@@ -218,6 +218,9 @@ struct mem_MSDU_T {
        UINT8                           txCompleteFlags;                /* Tx complete flags */
        UINT32              insertionTime;  /* time of msdu insersion to driver. */
        UINT8               qosTag;         /* 802.11d qos tag */
+#ifdef DM_USE_WORKQUEUE
+    mem_MSDU_T *        msdu_next;      /* Used for Workqueue list */
+#endif /* DM_USE_WORKQUEUE */
   #ifdef TI_DBG
     UINT32              timeStamp [MAX_NUM_OF_TIME_STAMPS];   
                                         /* array of time stamps */ 
index 419af43..cf0d9db 100644 (file)
@@ -51,6 +51,11 @@ WSPI ?= n
 #
 INTR ?= y
 
+#
+# Use work queues
+#
+WORKQUEUE ?= y
+
 #
 # Enable or disable debugging
 #
@@ -93,6 +98,10 @@ ifeq ($(INTR),n)
     DK_DEFINES += -D PRIODIC_INTERRUPT
 endif    
 
+ifeq ($(WORKQUEUE),y)
+    DK_DEFINES += -D DM_USE_WORKQUEUE
+endif
+
 ifeq ($(DEBUG),y)
     DK_DEFINES += -D TI_DBG
     DK_DEFINES += -D REPORT_LOG
index c2d7f7b..029b53c 100644 (file)
@@ -186,7 +186,16 @@ struct tiwlan_net_dev {
       tiwlan_region_t eeprom_image;
       tiwlan_region_t firmware_image;
       int irq;
+#ifdef DM_USE_WORKQUEUE
+      struct workqueue_struct *tiwlan_wq; /* Work Queue */
+//      struct work_struct tirq;         /* Work Task for interrupt */
+      struct work_struct tw;           /* Work Task for other stuff */
+      mem_MSDU_T *txmit_msdu_next;
+      mem_MSDU_T *txmit_msdu_last;
+      struct work_struct txmit;        /* Work Task for transmit */
+#else
       struct tasklet_struct tl;        /* Control tasklet */
+#endif
       int interrupt_pending;           /* 1=tasklet has to handle interrupts when awakes */
       int dma_done;
       struct list_head request_q;      /* Requests queue: -> tasklet */
index a77a3cb..14d6ec5 100644 (file)
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,2,0)
 #include <linux/wl12xx.h>
 #endif
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,39)
+#define create_freezable_workqueue create_freezeable_workqueue
+#endif
 
 #if 0
 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,28)
@@ -566,6 +569,52 @@ void sendFreeFunc(TI_HANDLE pSkb, TI_HANDLE dummy1, TI_STATUS status)
     dev_kfree_skb(skb);
 }
 
+#ifdef DM_USE_WORKQUEUE
+void tiwlan_add_msdu(tiwlan_net_dev_t *drv, mem_MSDU_T *pMsdu)
+{
+    if( pMsdu == NULL )
+        return;
+    pMsdu->msdu_next = NULL;
+    if( drv->txmit_msdu_next != NULL ) {
+        drv->txmit_msdu_last->msdu_next = pMsdu;
+    }
+    else {
+        drv->txmit_msdu_next = pMsdu;
+    }
+    drv->txmit_msdu_last = pMsdu;
+}
+
+mem_MSDU_T *tiwlan_del_msdu(tiwlan_net_dev_t *drv)
+{
+    mem_MSDU_T *pMsdu = NULL;
+
+    if( drv->txmit_msdu_next != NULL ) {
+        pMsdu = drv->txmit_msdu_next;
+        drv->txmit_msdu_next = pMsdu->msdu_next;
+        if( drv->txmit_msdu_next == NULL ) { /* Last MSDU */
+            drv->txmit_msdu_last = NULL;
+        }
+    }
+    return( pMsdu );
+}
+
+static void tiwlan_xmit_handler( struct work_struct *work )
+{
+    tiwlan_net_dev_t *drv = (tiwlan_net_dev_t *)container_of( work, struct tiwlan_net_dev, txmit );
+    mem_MSDU_T *pMsdu;
+    unsigned long flags;
+
+    /* printk("TI: %s:\t%lu\n", __FUNCTION__, jiffies); */
+    do {
+        spin_lock_irqsave(&drv->lock, flags);
+        pMsdu = tiwlan_del_msdu(drv);
+        spin_unlock_irqrestore(&drv->lock, flags);
+        if( pMsdu ) {
+            configMgr_sendMsdu(drv->adapter.CoreHalCtx, pMsdu, 0);
+        }
+    } while( pMsdu != NULL );
+}
+#endif
 
 /* send packet from Linux TCP/IP stack to WLAN
  */
@@ -680,8 +729,18 @@ static int tiwlan_drv_net_xmit(struct sk_buff *skb, struct net_device *dev)
     * Set DTag to zero 
     * (note that classification is further handled in the Core)
     */
-    if (status == OK)
+   if (status == OK) {
+#ifdef DM_USE_WORKQUEUE
+      unsigned long flags;
+
+      spin_lock_irqsave(&drv->lock, flags);
+      tiwlan_add_msdu(drv, pMsdu);
+      spin_unlock_irqrestore(&drv->lock, flags);
+      queue_work( drv->tiwlan_wq, &drv->txmit );
+#else
       status = configMgr_sendMsdu(drv->adapter.CoreHalCtx, pMsdu, 0);
+#endif
+   }
    else
       configMgr_memMngrFreeMSDU (drv->adapter.CoreHalCtx, (UINT32) pMsdu); /* If status != OK , we won't send the MSDU, so we need to free it */
 
@@ -818,9 +877,13 @@ static irqreturn_t tiwlan_interrupt (int irq, void *netdrv, struct pt_regs *cpu_
        tiwlan_net_dev_t *drv = (tiwlan_net_dev_t *)netdrv;
 
        drv->interrupt_pending = 1;
+#ifdef DM_USE_WORKQUEUE
+       queue_work( drv->tiwlan_wq, &drv->tw );
+#else
        tasklet_schedule (&drv->tl);
+#endif
 
-    return IRQ_HANDLED;
+       return IRQ_HANDLED;
 }
 #endif
 
@@ -839,9 +902,17 @@ static void tiwlan_poll_irq_handler(unsigned long parm)
    WLAN protocol tasklet. Most of work happens in the
    context of this tasklet.
 */
+#ifdef DM_USE_WORKQUEUE
+static void tiwlan_work_handler( struct work_struct *work )
+#else
 static void tiwlan_tasklet_handler(unsigned long netdrv)
+#endif
 {
+#ifdef DM_USE_WORKQUEUE
+    tiwlan_net_dev_t *drv = (tiwlan_net_dev_t *)container_of( work, struct tiwlan_net_dev, tw );
+#else
     tiwlan_net_dev_t *drv = (tiwlan_net_dev_t *)netdrv;
+#endif
 
   #ifdef STACK_PROFILE
     unsigned int curr1,base1;
@@ -992,7 +1063,11 @@ int tiwlan_send_wait_reply(tiwlan_net_dev_t *drv,
    list_add_tail(&req.list, &drv->request_q);
    spin_unlock_irqrestore(&drv->lock, flags);
 
+#ifdef DM_USE_WORKQUEUE
+   queue_work( drv->tiwlan_wq, &drv->tw );
+#else
    tasklet_schedule(&drv->tl);
+#endif
 
    wait_for_completion(&req.u.req.comp);
 
@@ -1336,6 +1411,9 @@ static void tiwlan_destroy_drv(tiwlan_net_dev_t *drv)
 
    tiwlan_stop_and_destroy_drv(drv);
    list_del(&drv->list);
+#ifdef DM_USE_WORKQUEUE
+   while( tiwlan_del_msdu(drv) != NULL );
+#endif
 
    if (drv->adapter.CoreHalCtx)
    {
@@ -1386,6 +1464,10 @@ static void tiwlan_destroy_drv(tiwlan_net_dev_t *drv)
 
 #endif/*FIRMWARE_DYNAMIC_LOAD*/
    }
+#ifdef DM_USE_WORKQUEUE
+   destroy_workqueue(drv->tiwlan_wq);
+#endif
+
    unregister_netdev(drv->netdev);
    tiwlan_free_drv(drv);
 }
@@ -1416,7 +1498,20 @@ tiwlan_create_drv(unsigned long reg_start, unsigned long reg_size,
       return -ENODEV;
    }
 
+#ifdef DM_USE_WORKQUEUE
+   drv->tiwlan_wq = create_freezable_workqueue("tiwlan_wifi_wq");
+   if( !(drv->tiwlan_wq) ) {
+       tiwlan_free_drv(drv);
+       printk(KERN_ERR "Failed to create workqueue\n");
+       return -EINVAL;
+   }
+   INIT_WORK( &drv->tw, tiwlan_work_handler );
+   INIT_WORK( &drv->txmit, tiwlan_xmit_handler );
+   //INIT_WORK( &drv->tirq, tiwlan_irq_handler );
+   drv->txmit_msdu_next = drv->txmit_msdu_last = NULL;
+#else
    tasklet_init(&drv->tl, tiwlan_tasklet_handler, (unsigned long)drv);
+#endif
    spin_lock_init(&drv->lock);
    INIT_LIST_HEAD(&drv->request_q);
    init_timer(&drv->poll_timer);
index 3253e10..b42d6a2 100644 (file)
@@ -265,7 +265,11 @@ void os_TNETWIF_BusTxn_Complete(TI_HANDLE OsContext,int status)
        tiwlan_net_dev_t *drv = (tiwlan_net_dev_t *)OsContext;
 
        drv->dma_done = 1;
+#ifdef DM_USE_WORKQUEUE
+       queue_work( drv->tiwlan_wq, &drv->tw );
+#else
        tasklet_schedule(&drv->tl);
+#endif
 }
 
 /****************************************************************************************
@@ -1476,7 +1480,11 @@ static void os_timerHandlr(unsigned long parm)
    list_del(&tmr->req.list);
    list_add_tail(&tmr->req.list, &drv->request_q);
    spin_unlock_irqrestore(&drv->lock, flags);
+#ifdef DM_USE_WORKQUEUE
+   queue_work( drv->tiwlan_wq, &drv->tw );
+#else
    tasklet_schedule(&drv->tl);
+#endif
 }