sir_kthread.c pretty much duplicates the workqueue functionality. Switch it to use a workqueue instead. It could probably use schedule_work/schedule_delayed_work instead of having it's own waitqueue, but I'd rather leave that to the maintainer. The file should probably get a name that still makes sense or merged into sir-dev.c now, but again that's up to the maintainer.
Note: I don't have the hardware so this is just compile-tested. Signed-off-by: Christoph Hellwig <[EMAIL PROTECTED]> Index: linux-2.6/drivers/net/irda/sir-dev.h =================================================================== --- linux-2.6.orig/drivers/net/irda/sir-dev.h 2006-01-31 12:23:36.000000000 +0100 +++ linux-2.6/drivers/net/irda/sir-dev.h 2006-04-14 15:08:14.000000000 +0200 @@ -15,23 +15,15 @@ #define IRDA_SIR_H #include <linux/netdevice.h> +#include <linux/workqueue.h> #include <net/irda/irda.h> #include <net/irda/irda_device.h> // iobuff_t -/* FIXME: unify irda_request with sir_fsm! */ - -struct irda_request { - struct list_head lh_request; - unsigned long pending; - void (*func)(void *); - void *data; - struct timer_list timer; -}; struct sir_fsm { struct semaphore sem; - struct irda_request rq; + struct work_struct work; unsigned state, substate; int param; int result; Index: linux-2.6/drivers/net/irda/sir_dev.c =================================================================== --- linux-2.6.orig/drivers/net/irda/sir_dev.c 2006-04-14 15:02:46.000000000 +0200 +++ linux-2.6/drivers/net/irda/sir_dev.c 2006-04-14 15:03:15.000000000 +0200 @@ -619,10 +619,6 @@ spin_lock_init(&dev->tx_lock); init_MUTEX(&dev->fsm.sem); - INIT_LIST_HEAD(&dev->fsm.rq.lh_request); - dev->fsm.rq.pending = 0; - init_timer(&dev->fsm.rq.timer); - dev->drv = drv; dev->netdev = ndev; Index: linux-2.6/drivers/net/irda/sir_kthread.c =================================================================== --- linux-2.6.orig/drivers/net/irda/sir_kthread.c 2006-04-14 14:54:08.000000000 +0200 +++ linux-2.6/drivers/net/irda/sir_kthread.c 2006-04-14 15:10:56.000000000 +0200 @@ -14,159 +14,14 @@ #include <linux/module.h> #include <linux/kernel.h> -#include <linux/version.h> #include <linux/init.h> -#include <linux/smp_lock.h> -#include <linux/completion.h> #include <linux/delay.h> - #include <net/irda/irda.h> #include "sir-dev.h" -/************************************************************************** - * - * kIrDAd kernel thread and config state machine - * - */ - -struct irda_request_queue { - struct list_head request_list; - spinlock_t lock; - task_t *thread; - struct completion exit; - wait_queue_head_t kick, done; - atomic_t num_pending; -}; - -static struct irda_request_queue irda_rq_queue; - -static int irda_queue_request(struct irda_request *rq) -{ - int ret = 0; - unsigned long flags; - - if (!test_and_set_bit(0, &rq->pending)) { - spin_lock_irqsave(&irda_rq_queue.lock, flags); - list_add_tail(&rq->lh_request, &irda_rq_queue.request_list); - wake_up(&irda_rq_queue.kick); - atomic_inc(&irda_rq_queue.num_pending); - spin_unlock_irqrestore(&irda_rq_queue.lock, flags); - ret = 1; - } - return ret; -} - -static void irda_request_timer(unsigned long data) -{ - struct irda_request *rq = (struct irda_request *)data; - unsigned long flags; - - spin_lock_irqsave(&irda_rq_queue.lock, flags); - list_add_tail(&rq->lh_request, &irda_rq_queue.request_list); - wake_up(&irda_rq_queue.kick); - spin_unlock_irqrestore(&irda_rq_queue.lock, flags); -} - -static int irda_queue_delayed_request(struct irda_request *rq, unsigned long delay) -{ - int ret = 0; - struct timer_list *timer = &rq->timer; - if (!test_and_set_bit(0, &rq->pending)) { - timer->expires = jiffies + delay; - timer->function = irda_request_timer; - timer->data = (unsigned long)rq; - atomic_inc(&irda_rq_queue.num_pending); - add_timer(timer); - ret = 1; - } - return ret; -} - -static void run_irda_queue(void) -{ - unsigned long flags; - struct list_head *entry, *tmp; - struct irda_request *rq; - - spin_lock_irqsave(&irda_rq_queue.lock, flags); - list_for_each_safe(entry, tmp, &irda_rq_queue.request_list) { - rq = list_entry(entry, struct irda_request, lh_request); - list_del_init(entry); - spin_unlock_irqrestore(&irda_rq_queue.lock, flags); - - clear_bit(0, &rq->pending); - rq->func(rq->data); - - if (atomic_dec_and_test(&irda_rq_queue.num_pending)) - wake_up(&irda_rq_queue.done); - - spin_lock_irqsave(&irda_rq_queue.lock, flags); - } - spin_unlock_irqrestore(&irda_rq_queue.lock, flags); -} - -static int irda_thread(void *startup) -{ - DECLARE_WAITQUEUE(wait, current); - - daemonize("kIrDAd"); - - irda_rq_queue.thread = current; - - complete((struct completion *)startup); - - while (irda_rq_queue.thread != NULL) { - - /* We use TASK_INTERRUPTIBLE, rather than - * TASK_UNINTERRUPTIBLE. Andrew Morton made this - * change ; he told me that it is safe, because "signal - * blocking is now handled in daemonize()", he added - * that the problem is that "uninterruptible sleep - * contributes to load average", making user worry. - * Jean II */ - set_task_state(current, TASK_INTERRUPTIBLE); - add_wait_queue(&irda_rq_queue.kick, &wait); - if (list_empty(&irda_rq_queue.request_list)) - schedule(); - else - __set_task_state(current, TASK_RUNNING); - remove_wait_queue(&irda_rq_queue.kick, &wait); - - /* make swsusp happy with our thread */ - try_to_freeze(); - - run_irda_queue(); - } - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,35) - reparent_to_init(); -#endif - complete_and_exit(&irda_rq_queue.exit, 0); - /* never reached */ - return 0; -} - - -static void flush_irda_queue(void) -{ - if (atomic_read(&irda_rq_queue.num_pending)) { - - DECLARE_WAITQUEUE(wait, current); - - if (!list_empty(&irda_rq_queue.request_list)) - run_irda_queue(); - - set_task_state(current, TASK_UNINTERRUPTIBLE); - add_wait_queue(&irda_rq_queue.done, &wait); - if (atomic_read(&irda_rq_queue.num_pending)) - schedule(); - else - __set_task_state(current, TASK_RUNNING); - remove_wait_queue(&irda_rq_queue.done, &wait); - } -} +static struct workqueue_struct *irda_wq; /* substate handler of the config-fsm to handle the cases where we want * to wait for transmit completion before changing the port configuration @@ -413,7 +268,7 @@ fsm->state = next_state; } while(!delay); - irda_queue_delayed_request(&fsm->rq, msecs_to_jiffies(delay)); + queue_delayed_work(irda_wq, &fsm->work, msecs_to_jiffies(delay)); } /* schedule some device configuration task for execution by kIrDAd @@ -424,7 +279,6 @@ int sirdev_schedule_request(struct sir_dev *dev, int initial_state, unsigned param) { struct sir_fsm *fsm = &dev->fsm; - int xmit_was_down; IRDA_DEBUG(2, "%s - state=0x%04x / param=%u\n", __FUNCTION__, initial_state, param); @@ -443,7 +297,6 @@ return -ESTALE; /* or better EPIPE? */ } - xmit_was_down = netif_queue_stopped(dev->netdev); netif_stop_queue(dev->netdev); atomic_set(&dev->enable_rx, 0); @@ -451,58 +304,27 @@ fsm->param = param; fsm->result = 0; - INIT_LIST_HEAD(&fsm->rq.lh_request); - fsm->rq.pending = 0; - fsm->rq.func = irda_config_fsm; - fsm->rq.data = dev; - - if (!irda_queue_request(&fsm->rq)) { /* returns 0 on error! */ - atomic_set(&dev->enable_rx, 1); - if (!xmit_was_down) - netif_wake_queue(dev->netdev); - up(&fsm->sem); - return -EAGAIN; - } + INIT_WORK(&fsm->work, irda_config_fsm, dev); + queue_work(irda_wq, &fsm->work); return 0; } -static int __init irda_thread_create(void) +static int __init irda_thread_init(void) { - struct completion startup; - int pid; - - spin_lock_init(&irda_rq_queue.lock); - irda_rq_queue.thread = NULL; - INIT_LIST_HEAD(&irda_rq_queue.request_list); - init_waitqueue_head(&irda_rq_queue.kick); - init_waitqueue_head(&irda_rq_queue.done); - atomic_set(&irda_rq_queue.num_pending, 0); - - init_completion(&startup); - pid = kernel_thread(irda_thread, &startup, CLONE_FS|CLONE_FILES); - if (pid <= 0) - return -EAGAIN; - else - wait_for_completion(&startup); - + irda_wq = create_singlethread_workqueue("irda_wq"); + if (!irda_wq) + return -ENOMEM; return 0; } -static void __exit irda_thread_join(void) +static void __exit irda_thread_exit(void) { - if (irda_rq_queue.thread) { - flush_irda_queue(); - init_completion(&irda_rq_queue.exit); - irda_rq_queue.thread = NULL; - wake_up(&irda_rq_queue.kick); - wait_for_completion(&irda_rq_queue.exit); - } + destroy_workqueue(irda_wq); } -module_init(irda_thread_create); -module_exit(irda_thread_join); +module_init(irda_thread_init); +module_exit(irda_thread_exit); MODULE_AUTHOR("Martin Diehl <[EMAIL PROTECTED]>"); MODULE_DESCRIPTION("IrDA SIR core"); MODULE_LICENSE("GPL"); - - To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html