From: notaz Date: Mon, 9 Feb 2015 01:54:24 +0000 (+0200) Subject: backport workqueue code from AOSP X-Git-Url: http://git.openpandora.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=213df0c14df14a5bfda939227441f45cd6516116;p=pandora-wifi.git backport workqueue code from AOSP --- diff --git a/sta_dk/common/inc/memMngrEx.h b/sta_dk/common/inc/memMngrEx.h index 196a780..1a191db 100644 --- a/sta_dk/common/inc/memMngrEx.h +++ b/sta_dk/common/inc/memMngrEx.h @@ -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 */ diff --git a/sta_dk/pform/linux/build/common.inc b/sta_dk/pform/linux/build/common.inc index 419af43..cf0d9db 100644 --- a/sta_dk/pform/linux/build/common.inc +++ b/sta_dk/pform/linux/build/common.inc @@ -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 diff --git a/sta_dk/pform/linux/inc/esta_drv.h b/sta_dk/pform/linux/inc/esta_drv.h index c2d7f7b..029b53c 100644 --- a/sta_dk/pform/linux/inc/esta_drv.h +++ b/sta_dk/pform/linux/inc/esta_drv.h @@ -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 */ diff --git a/sta_dk/pform/linux/src/esta_drv.c b/sta_dk/pform/linux/src/esta_drv.c index a77a3cb..14d6ec5 100644 --- a/sta_dk/pform/linux/src/esta_drv.c +++ b/sta_dk/pform/linux/src/esta_drv.c @@ -109,6 +109,9 @@ #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,2,0) #include #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); diff --git a/sta_dk/pform/linux/src/osapi.c b/sta_dk/pform/linux/src/osapi.c index 3253e10..b42d6a2 100644 --- a/sta_dk/pform/linux/src/osapi.c +++ b/sta_dk/pform/linux/src/osapi.c @@ -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 }