#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)
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
*/
* 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 */
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
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;
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);
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)
{
#endif/*FIRMWARE_DYNAMIC_LOAD*/
}
+#ifdef DM_USE_WORKQUEUE
+ destroy_workqueue(drv->tiwlan_wq);
+#endif
+
unregister_netdev(drv->netdev);
tiwlan_free_drv(drv);
}
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);