LWN.net Logo

Workqueue Abstraction, 2.5.40-H7

From:  Ingo Molnar <mingo@elte.hu>
To:  Linus Torvalds <torvalds@transmeta.com>
Subject:  [patch] Workqueue Abstraction, 2.5.40-H7
Date:  Tue, 1 Oct 2002 18:24:50 +0200 (CEST)
Cc:  linux-kernel@vger.kernel.org

the attached (compressed) patch is the next iteration of the workqueue
abstraction. There are two major categories of changes:

  - a much improved (i hope) core framework

  - (almost) complete conversion of existing drivers to the new framework.

1) The framework improvements include:

 - per-CPU queueing support.

on SMP there is a per-CPU worker thread (bound to its CPU) and per-CPU
work queues - this feature is completely transparent to workqueue-users.  
keventd automatically uses this feature. XFS can now update to work-queues
and have the same per-CPU performance as it had with its per-CPU worker
threads.

 - delayed work submission

there's a new queue_delayed_work(wq, work, delay) function and a new
schedule_delayed_work(work, delay) function. The later one is used to
correctly fix former tq_timer users. I've reverted those changes in 2.5.40
that changed tq_timer uses to schedule_work() - eg. in the case of
random.c or the tty flip queue it was definitely the wrong thing to do.

delayed work means a timer embedded in work_t. I considered using split
work_t and delayed_work_t types, but lots of code actively uses
task-queues in both delayed and non-delayed mode, so i went for the more
generic approach that allows both methods of work submission. Delayed
timers do not cause any other overhead in the normal submission path
otherwise.

 - multithreaded run_workqueue() implementation

the run_workqueue() function can now be called from multiple contexts, and
a worker thread will only use up a single entryy - this property is used
by the flushing code, and can potentially be used in the future to extend
the number of per-CPU worker threads.

 - more reliable flushing

there's now a 'pending work' counter, which is used to accurately detect
when the last work-function has finished execution. It's also used to
correctly flush against timed requests. I'm not convinced whether the old
keventd implementation got this detail right.

 - i switched the arguments of the queueing function(s) per Jeff's
   suggestion, it's more straightforward this way.


2) driver fixes.

i have converted almost every affected driver to the new framework. This
cleaned up tons of code. I also fixed a number of drivers that were still
using BHs (these drivers did not compile in 2.5.40).

while this means lots of changes, it might ease the QA decision whether to
put this patch into 2.5.

The pach converts roughly 80% of all tqueue-using code to workqueues - and
all the places that are not converted to workqueues yet are places that do
not compile in vanilla 2.5.40 anyway, due to unrelated changes. I've
converted a fair number of drivers that do not compile in 2.5.40, and i
think i've managed to convert every driver that compiles under 2.5.40.

i've tested the patch on 2.5.40, UP and SMP x86, boots & works just fine.

I've also attached maxi-config, which is a pretty large .config - this
config file compiles the kernel just fine. (it's too large to be booted
though.) No workqueue/taskqueue related warning messages or compile
errors.

	Ingo

--- linux/drivers/hotplug/cpqphp.h.orig	Tue Oct  1 14:01:22 2002
+++ linux/drivers/hotplug/cpqphp.h	Tue Oct  1 14:02:04 2002
@@ -317,7 +317,7 @@
 	u16 vendor_id;
 	char proc_name[20];
 	char proc_name2[20];
-	struct tq_struct int_task_event;
+	work_t int_task_event;
 	wait_queue_head_t queue;	/* sleep & wake process */
 };
 
--- linux/drivers/hotplug/cpqphp_core.c.orig	Tue Oct  1 15:52:29 2002
+++ linux/drivers/hotplug/cpqphp_core.c	Tue Oct  1 17:14:39 2002
@@ -33,7 +33,7 @@
 #include <linux/proc_fs.h>
 #include <linux/miscdevice.h>
 #include <linux/slab.h>
-#include <linux/tqueue.h>
+#include <linux/workqueue.h>
 #include <linux/pci.h>
 #include <linux/init.h>
 #include <asm/uaccess.h>
--- linux/drivers/hotplug/cpqphp_ctrl.c.orig	Tue Oct  1 15:52:29 2002
+++ linux/drivers/hotplug/cpqphp_ctrl.c	Tue Oct  1 17:14:59 2002
@@ -31,7 +31,7 @@
 #include <linux/kernel.h>
 #include <linux/types.h>
 #include <linux/slab.h>
-#include <linux/tqueue.h>
+#include <linux/workqueue.h>
 #include <linux/interrupt.h>
 #include <linux/delay.h>
 #include <linux/wait.h>
@@ -971,7 +971,6 @@
 	if (schedule_flag) {
 		up(&event_semaphore);
 		dbg("Signal event_semaphore\n");
-		mark_bh(IMMEDIATE_BH);
 	}
 
 }
--- linux/drivers/hotplug/cpqphp_nvram.c.orig	Tue Oct  1 15:52:29 2002
+++ linux/drivers/hotplug/cpqphp_nvram.c	Tue Oct  1 17:15:19 2002
@@ -33,7 +33,7 @@
 #include <linux/proc_fs.h>
 #include <linux/miscdevice.h>
 #include <linux/slab.h>
-#include <linux/tqueue.h>
+#include <linux/workqueue.h>
 #include <linux/pci.h>
 #include <linux/init.h>
 #include <asm/uaccess.h>
--- linux/drivers/hotplug/cpqphp_pci.c.orig	Tue Oct  1 15:52:29 2002
+++ linux/drivers/hotplug/cpqphp_pci.c	Tue Oct  1 17:13:49 2002
@@ -31,7 +31,7 @@
 #include <linux/kernel.h>
 #include <linux/types.h>
 #include <linux/slab.h>
-#include <linux/tqueue.h>
+#include <linux/workqueue.h>
 #include <linux/proc_fs.h>
 #include <linux/pci.h>
 #include "cpqphp.h"
--- linux/drivers/hotplug/cpqphp_proc.c.orig	Tue Oct  1 15:52:29 2002
+++ linux/drivers/hotplug/cpqphp_proc.c	Tue Oct  1 17:15:23 2002
@@ -31,7 +31,7 @@
 #include <linux/kernel.h>
 #include <linux/types.h>
 #include <linux/proc_fs.h>
-#include <linux/tqueue.h>
+#include <linux/workqueue.h>
 #include <linux/pci.h>
 #include "cpqphp.h"
 
--- linux/drivers/net/hamradio/dmascc.c.orig	Tue Oct  1 14:01:22 2002
+++ linux/drivers/net/hamradio/dmascc.c	Tue Oct  1 14:04:44 2002
@@ -36,7 +36,7 @@
 #include <linux/netdevice.h>
 #include <linux/rtnetlink.h>
 #include <linux/sockios.h>
-#include <linux/tqueue.h>
+#include <linux/workqueue.h>
 #include <linux/version.h>
 #include <asm/atomic.h>
 #include <asm/bitops.h>
@@ -225,7 +225,7 @@
   char rx_buf[NUM_RX_BUF][BUF_SIZE];
   int rx_len[NUM_RX_BUF];
   int rx_ptr;
-  struct tq_struct rx_task;
+  work_t rx_work;
   int rx_head, rx_tail, rx_count;
   int rx_over;
   char tx_buf[NUM_TX_BUF][BUF_SIZE];
@@ -569,8 +569,7 @@
     priv->param.clocks = TCTRxCP | RCRTxCP;
     priv->param.persist = 256;
     priv->param.dma = -1;
-    priv->rx_task.routine = rx_bh;
-    priv->rx_task.data = priv;
+    INIT_WORK(&priv->rx_work, rx_bh, priv);
     dev->priv = priv;
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
     if (sizeof(dev->name) == sizeof(char *)) dev->name = priv->name;
@@ -1072,9 +1071,7 @@
 	  priv->rx_len[priv->rx_head] = cb;
 	  priv->rx_head = (priv->rx_head + 1) % NUM_RX_BUF;
 	  priv->rx_count++;
-	  /* Mark bottom half handler */
-	  queue_task(&priv->rx_task, &tq_immediate);
-	  mark_bh(IMMEDIATE_BH);
+	  schedule_work(&priv->rx_work);
 	} else {
 	  priv->stats.rx_errors++;
 	  priv->stats.rx_over_errors++;
--- linux/drivers/net/hamradio/baycom_epp.c.orig	Tue Oct  1 14:01:22 2002
+++ linux/drivers/net/hamradio/baycom_epp.c	Tue Oct  1 14:13:05 2002
@@ -45,7 +45,7 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/string.h>
-#include <linux/tqueue.h>
+#include <linux/workqueue.h>
 #include <linux/fs.h>
 #include <linux/parport.h>
 #include <linux/smp_lock.h>
@@ -194,8 +194,8 @@
 	int magic;
 
         struct pardevice *pdev;
-	unsigned int bh_running;
-	struct tq_struct run_bh;
+	unsigned int work_running;
+	work_t run_work;
 	unsigned int modem;
 	unsigned int bitrate;
 	unsigned char stat;
@@ -829,7 +829,7 @@
 	
 	baycom_paranoia_check_void(dev, "epp_bh");
 	bc = (struct baycom_state *)dev->priv;
-	if (!bc->bh_running)
+	if (!bc->work_running)
 		return;
 	baycom_int_freq(bc);
 	pp = bc->pdev->port;
@@ -928,7 +928,7 @@
 	bc->debug_vals.mod_cycles = time2 - time1;
 	bc->debug_vals.demod_cycles = time3 - time2;
 #endif /* BAYCOM_DEBUG */
-	queue_task(&bc->run_bh, &tq_timer);
+	schedule_delayed_work(&bc->run_work, 1);
 	if (!bc->skb)
 		netif_wake_queue(dev);
 	return;
@@ -1019,10 +1019,6 @@
 {
 	struct baycom_state *bc;
         struct parport *pp;
-	const struct tq_struct run_bh = {
-		.routine = (void *)(void *)epp_bh,
-		.data = dev
-	};
 	unsigned int i, j;
 	unsigned char tmp[128];
 	unsigned char stat;
@@ -1060,8 +1056,8 @@
                 return -EBUSY;
         }
         dev->irq = /*pp->irq*/ 0;
-	bc->run_bh = run_bh;
-	bc->bh_running = 1;
+	INIT_WORK(&bc->run_work, (void *)(void *)epp_bh, dev);
+	bc->work_running = 1;
 	bc->modem = EPP_CONVENTIONAL;
 	if (eppconfig(bc))
 		printk(KERN_INFO "%s: no FPGA detected, assuming conventional EPP modem\n", bc_drvname);
@@ -1121,7 +1117,7 @@
 	bc->hdlctx.slotcnt = bc->ch_params.slottime;
 	bc->hdlctx.calibrate = 0;
 	/* start the bottom half stuff */
-	queue_task(&bc->run_bh, &tq_timer);
+	schedule_delayed_work(&bc->run_work, 1);
 	netif_start_queue(dev);
 	MOD_INC_USE_COUNT;
 	return 0;
@@ -1145,8 +1141,8 @@
 	baycom_paranoia_check(dev, "epp_close", -EINVAL);
 	bc = (struct baycom_state *)dev->priv;
 	pp = bc->pdev->port;
-	bc->bh_running = 0;
-	run_task_queue(&tq_timer);  /* dequeue bottom half */
+	bc->work_running = 0;
+	flush_scheduled_work();
 	bc->stat = EPP_DCDBIT;
 	tmp[0] = 0;
 	pp->ops->epp_write_addr(pp, tmp, 1, 0);
--- linux/drivers/net/wan/lmc/lmc_proto.c.orig	Tue Oct  1 15:33:32 2002
+++ linux/drivers/net/wan/lmc/lmc_proto.c	Tue Oct  1 15:33:36 2002
@@ -44,7 +44,7 @@
 #include <linux/skbuff.h>
 #include <net/syncppp.h>
 #include <linux/inet.h>
-#include <linux/tqueue.h>
+#include <linux/workqueue.h>
 #include <linux/proc_fs.h>
 
 #include "lmc_ver.h"
--- linux/drivers/net/wan/sdla_ppp.c.orig	Tue Oct  1 14:01:22 2002
+++ linux/drivers/net/wan/sdla_ppp.c	Tue Oct  1 14:20:32 2002
@@ -220,10 +220,10 @@
 
 	unsigned long router_up_time; 
 
-	/* Polling task queue. Each interface
-         * has its own task queue, which is used
+	/* Polling work queue entry. Each interface
+         * has its own work queue entry, which is used
          * to defer events from the interrupt */
-	struct tq_struct poll_task;
+	work_t poll_work;
 	struct timer_list poll_delay_timer;
 
 	u8 gateway;
@@ -631,13 +631,8 @@
 	dev->priv = ppp_priv_area;
 	dev->mtu = min_t(unsigned int, dev->mtu, card->wandev.mtu);
 
-	/* Initialize the polling task routine */
-#ifndef LINUX_2_4
-	ppp_priv_area->poll_task.next = NULL;
-#endif
-	ppp_priv_area->poll_task.sync=0;
-	ppp_priv_area->poll_task.routine = (void*)(void*)ppp_poll;
-	ppp_priv_area->poll_task.data = dev;
+	/* Initialize the polling work routine */
+	INIT_WORK(&ppp_priv_area->poll_work, (void*)(void*)ppp_poll, dev);
 
 	/* Initialize the polling delay timer */
 	init_timer(&ppp_priv_area->poll_delay_timer);
@@ -3667,11 +3662,7 @@
 			return;
 		}
 
-#ifdef LINUX_2_4
-		schedule_task(&ppp_priv_area->poll_task);
-#else
-		queue_task(&ppp_priv_area->poll_task, &tq_scheduler);
-#endif
+		schedule_work(&ppp_priv_area->poll_work);
 	}
 	return;
 }
--- linux/drivers/net/wan/pc300_tty.c.orig	Tue Oct  1 14:01:22 2002
+++ linux/drivers/net/wan/pc300_tty.c	Tue Oct  1 14:23:15 2002
@@ -106,8 +106,8 @@
 	pc300dev_t*	pc300dev;	/* ptr. to info struct in PC300 driver */
 	unsigned char	name[20];	/* interf. name + "-tty" */
 	struct tty_struct *tty;		
-	struct tq_struct tty_tx_task_queue; /* tx task - tx interrupt */
-	struct tq_struct tty_rx_task_queue; /* rx task - rx interrupt */
+	work_t tty_tx_work; /* tx work - tx interrupt */
+	work_t tty_rx_work; /* rx work - rx interrupt */
 	} st_cpc_tty_area;
 
 /* TTY data structures */
@@ -134,8 +134,8 @@
 				unsigned int cmd, unsigned long arg);
 static void cpc_tty_flush_buffer(struct tty_struct *tty);
 static void cpc_tty_hangup(struct tty_struct *tty);
-static void cpc_tty_rx_task(void *data);
-static void cpc_tty_tx_task(void *data);
+static void cpc_tty_rx_work(void *data);
+static void cpc_tty_tx_work(void *data);
 static int cpc_tty_send_to_card(pc300dev_t *dev,void *buf, int len);
 static void cpc_tty_trace(pc300dev_t *dev, char* buf, int len, char rxtx);
 static void cpc_tty_dtr_off(pc300dev_t *pc300dev);
@@ -288,12 +288,9 @@
 	cpc_tty->num_open= 0;
 	cpc_tty->tty_minor = port + CPC_TTY_MINOR_START;
 	cpc_tty->pc300dev = pc300dev; 
-	
-	cpc_tty->tty_tx_task_queue.routine = cpc_tty_tx_task; 
-	cpc_tty->tty_tx_task_queue.data = (void *)cpc_tty; 
-	
-	cpc_tty->tty_rx_task_queue.routine = cpc_tty_rx_task; 
-	cpc_tty->tty_rx_task_queue.data = (void *) port; 
+
+	INIT_WORK(&cpc_tty->tty_tx_work, cpc_tty_tx_work, (void *)cpc_tty);
+	INIT_WORK(&cpc_tty->tty_rx_work, cpc_tty_rx_work, (void *)port);
 	
 	cpc_tty->buf_rx.first = cpc_tty->buf_rx.last = 0;
 
@@ -706,13 +703,13 @@
 }
 
 /*
- * PC300 TTY RX task routine
- * This routine treats RX task
+ * PC300 TTY RX work routine
+ * This routine treats RX work
  * o verify read buffer
  * o call the line disc. read
  * o free memory
  */
-static void cpc_tty_rx_task(void * data)
+static void cpc_tty_rx_work(void * data)
 {
 	int port, i, j;
 	st_cpc_tty_area *cpc_tty; 
@@ -745,7 +742,7 @@
 } 
 
 /*
- * PC300 TTY RX task routine
+ * PC300 TTY RX work routine
  *
  * This routine treats RX interrupt. 
  * o read all frames in card
@@ -912,25 +909,25 @@
 				cpc_tty->buf_rx.last->next = new;
 				cpc_tty->buf_rx.last = new;
 			}
-			schedule_task(&(cpc_tty->tty_rx_task_queue));
+			schedule_work(&(cpc_tty->tty_rx_work));
 			stats->rx_packets++;
 		}
 	} 
 } 
 
 /*
- * PC300 TTY TX task routine
+ * PC300 TTY TX work routine
  * 
  * This routine treats TX interrupt. 
  * o if need call line discipline wakeup
  * o call wake_up_interruptible
  */
-static void cpc_tty_tx_task(void *data)
+static void cpc_tty_tx_work(void *data)
 {
 	st_cpc_tty_area *cpc_tty = (st_cpc_tty_area *) data; 
 	struct tty_struct *tty; 
 
-	CPC_TTY_DBG("%s: cpc_tty_tx_task init\n",cpc_tty->name);
+	CPC_TTY_DBG("%s: cpc_tty_tx_work init\n",cpc_tty->name);
 	
 	if ((tty = cpc_tty->tty) == 0) { 
 		CPC_TTY_DBG("%s: the interface is not opened\n",cpc_tty->name);
@@ -1124,7 +1121,7 @@
 	if (!cpc_tty) {
 		return;
 	}
-	schedule_task(&(cpc_tty->tty_tx_task_queue)); 
+	schedule_work(&(cpc_tty->tty_tx_work)); 
 } 
 
 /*
--- linux/drivers/net/wan/sdla_chdlc.c.orig	Tue Oct  1 14:01:22 2002
+++ linux/drivers/net/wan/sdla_chdlc.c	Tue Oct  1 14:28:40 2002
@@ -163,10 +163,10 @@
 	
 	unsigned char interface_down;
 
-	/* Polling task queue. Each interface
-         * has its own task queue, which is used
+	/* Polling work queue entry. Each interface
+         * has its own work queue entry, which is used
          * to defer events from the interrupt */
-	struct tq_struct poll_task;
+	work_t poll_work;
 	struct timer_list poll_delay_timer;
 
 	u8 gateway;
@@ -262,8 +262,8 @@
 
 #if defined(LINUX_2_1) || defined(LINUX_2_4)
   /* Bottom half handlers */
-  static void chdlc_bh (netdevice_t *);
-  static int chdlc_bh_cleanup (netdevice_t *);
+  static void chdlc_work (netdevice_t *);
+  static int chdlc_work_cleanup (netdevice_t *);
   static int bh_enqueue (netdevice_t *, struct sk_buff *);
 #endif
 
@@ -930,13 +930,8 @@
 	dev->init = &if_init;
 	dev->priv = chdlc_priv_area;
 
-	/* Initialize the polling task routine */
-#ifndef LINUX_2_4
-	chdlc_priv_area->poll_task.next = NULL;
-#endif
-	chdlc_priv_area->poll_task.sync=0;
-	chdlc_priv_area->poll_task.routine = (void*)(void*)chdlc_poll;
-	chdlc_priv_area->poll_task.data = dev;
+	/* Initialize the polling work routine */
+	INIT_WORK(&chdlc_priv_area->poll_work, (void*)(void*)chdlc_poll, dev);
 
 	/* Initialize the polling delay timer */
 	init_timer(&chdlc_priv_area->poll_delay_timer);
@@ -1052,15 +1047,11 @@
 		return -EBUSY;
 
 #if defined(LINUX_2_1) || defined(LINUX_2_4)
-	/* Initialize the task queue */
+	/* Initialize the work queue entry */
 	chdlc_priv_area->tq_working=0;
 
-#ifndef LINUX_2_4
-	chdlc_priv_area->common.wanpipe_task.next = NULL;
-#endif
-	chdlc_priv_area->common.wanpipe_task.sync = 0;
-	chdlc_priv_area->common.wanpipe_task.routine = (void *)(void *)chdlc_bh;
-	chdlc_priv_area->common.wanpipe_task.data = dev;
+	INIT_WORK(&chdlc_priv_area->common.wanpipe_work,
+			(void *)(void *)chdlc_work, dev);
 
 	/* Allocate and initialize BH circular buffer */
 	/* Add 1 to MAX_BH_BUFF so we don't have test with (MAX_BH_BUFF-1) */
@@ -1863,7 +1854,7 @@
  *       PREPROCESSOR STATEMENT ABOVE, UNLESS YOU KNOW WHAT YOU ARE
  *       DOING */
 
-static void chdlc_bh (netdevice_t * dev)
+static void chdlc_work (netdevice_t * dev)
 {
 	chdlc_private_area_t* chan = dev->priv;
 	sdla_t *card = chan->card;
@@ -1883,7 +1874,7 @@
 			if (chan->common.sk == NULL || chan->common.func == NULL){
 				++card->wandev.stats.rx_dropped;
 				wan_dev_kfree_skb(skb, FREE_READ);
-				chdlc_bh_cleanup(dev);
+				chdlc_work_cleanup(dev);
 				continue;
 			}
 
@@ -1893,10 +1884,10 @@
 				atomic_set(&chan->common.receive_block,1);
 				return;
 			}else{
-				chdlc_bh_cleanup(dev);
+				chdlc_work_cleanup(dev);
 			}
 		}else{
-			chdlc_bh_cleanup(dev);
+			chdlc_work_cleanup(dev);
 		}
 	}	
 	clear_bit(0, &chan->tq_working);
@@ -1904,7 +1895,7 @@
 	return;
 }
 
-static int chdlc_bh_cleanup (netdevice_t *dev)
+static int chdlc_work_cleanup (netdevice_t *dev)
 {
 	chdlc_private_area_t* chan = dev->priv;
 
@@ -2214,10 +2205,8 @@
 
 		bh_enqueue(dev, skb);
 
-		if (!test_and_set_bit(0,&chdlc_priv_area->tq_working)){
-			wanpipe_queue_tq(&chdlc_priv_area->common.wanpipe_task);
-		        wanpipe_mark_bh();
-		}
+		if (!test_and_set_bit(0,&chdlc_priv_area->tq_working))
+			wanpipe_queue_work(&chdlc_priv_area->common.wanpipe_work);
 #endif
 	}else{
 		/* FIXME: we should check to see if the received packet is a 
@@ -3776,7 +3765,7 @@
  * trigger_chdlc_poll
  *
  * Description:
- * 	Add a chdlc_poll() task into a tq_scheduler bh handler
+ * 	Add a chdlc_poll() work entry into the keventd work queue
  *      for a specific dlci/interface.  This will kick
  *      the fr_poll() routine at a later time. 
  *
@@ -3804,12 +3793,7 @@
 	if (test_bit(PERI_CRIT,&card->wandev.critical)){
 		return; 
 	}
-#ifdef LINUX_2_4
-	schedule_task(&chdlc_priv_area->poll_task);
-#else
-	queue_task(&chdlc_priv_area->poll_task, &tq_scheduler);
-#endif
-	return;
+	schedule_work(&chdlc_priv_area->poll_work);
 }
 
 
@@ -3856,14 +3840,10 @@
 
 static void wanpipe_tty_trigger_poll(sdla_t *card)
 {
-#ifdef LINUX_2_4
-	schedule_task(&card->tty_task_queue);
-#else
-	queue_task(&card->tty_task_queue, &tq_scheduler);
-#endif
+	schedule_work(&card->tty_work);
 }
 
-static void tty_poll_task (void* data)
+static void tty_poll_work (void* data)
 {
 	sdla_t *card = (sdla_t*)data;
 	struct tty_struct *tty;
@@ -4736,8 +4716,7 @@
 	state->icount.overrun = state->icount.brk = 0;
 	state->irq = card->wandev.irq; 
 
-	card->tty_task_queue.routine = tty_poll_task;
-	card->tty_task_queue.data = (void*)card;
+	INIT_WORK(&card->tty_work, tty_poll_work, (void*)card);
 	return 0;
 }
 
--- linux/drivers/net/e1000/e1000.h.orig	Tue Oct  1 14:01:22 2002
+++ linux/drivers/net/e1000/e1000.h	Tue Oct  1 14:34:13 2002
@@ -64,7 +64,7 @@
 #include <linux/list.h>
 #include <linux/reboot.h>
 #include <net/checksum.h>
-#include <linux/tqueue.h>
+#include <linux/workqueue.h>
 #include <linux/ethtool.h>
 #include <linux/if_vlan.h>
 
@@ -160,7 +160,7 @@
 	uint16_t link_duplex;
 	spinlock_t stats_lock;
 	atomic_t irq_sem;
-	struct tq_struct tx_timeout_task;
+	work_t tx_timeout_task;
 
 	struct timer_list blink_timer;
 	unsigned long led_status;
--- linux/drivers/net/e1000/e1000_main.c.orig	Tue Oct  1 14:34:51 2002
+++ linux/drivers/net/e1000/e1000_main.c	Tue Oct  1 14:35:15 2002
@@ -470,7 +470,7 @@
 	adapter->phy_info_timer.function = &e1000_update_phy_info;
 	adapter->phy_info_timer.data = (unsigned long) adapter;
 
-	INIT_TQUEUE(&adapter->tx_timeout_task, 
+	INIT_WORK(&adapter->tx_timeout_task, 
 		(void (*)(void *))e1000_tx_timeout_task, netdev);
 
 	register_netdev(netdev);
@@ -1542,7 +1542,7 @@
 	struct e1000_adapter *adapter = netdev->priv;
 
 	/* Do the reset outside of interrupt context */
-	schedule_task(&adapter->tx_timeout_task);
+	schedule_work(&adapter->tx_timeout_task);
 }
 
 static void
--- linux/drivers/net/wireless/airo.c.orig	Tue Oct  1 14:01:22 2002
+++ linux/drivers/net/wireless/airo.c	Tue Oct  1 14:36:54 2002
@@ -32,7 +32,7 @@
 #include <linux/timer.h>
 #include <linux/interrupt.h>
 #include <linux/in.h>
-#include <linux/tqueue.h>
+#include <linux/workqueue.h>
 #include <asm/io.h>
 #include <asm/system.h>
 #include <asm/bitops.h>
@@ -999,17 +999,17 @@
 	tdsRssiEntry *rssi;
 	struct semaphore sem;
 	struct task_struct *task;
-	struct tq_struct promisc_task;
+	work_t promisc_task;
 	struct {
 		struct sk_buff *skb;
 		int fid;
-		struct tq_struct task;
+		work_t task;
 	} xmit, xmit11;
 	struct net_device *wifidev;
 #ifdef WIRELESS_EXT
 	struct iw_statistics	wstats;		// wireless stats
 	unsigned long		scan_timestamp;	/* Time started to scan */
-	struct tq_struct	event_task;
+	work_t	event_task;
 #ifdef WIRELESS_SPY
 	int			spy_number;
 	u_char			spy_address[IW_MAX_SPY][ETH_ALEN];
@@ -1019,7 +1019,7 @@
 	/* MIC stuff */
 	mic_module		mod[2];
 	mic_statistics		micstats;
-	struct tq_struct 	mic_task;
+	work_t 	mic_task;
 };
 
 static inline int bap_read(struct airo_info *ai, u16 *pu16Dst, int bytelen,
@@ -1318,7 +1318,7 @@
 		netif_stop_queue(dev);
 		priv->xmit.task.routine = (void (*)(void *))airo_do_xmit;
 		priv->xmit.task.data = (void *)dev;
-		schedule_task(&priv->xmit.task);
+		schedule_work(&priv->xmit.task);
 		return;
 	}
 	status = transmit_802_3_packet (priv, fids[fid], skb->data);
@@ -1380,7 +1380,7 @@
 		netif_stop_queue(dev);
 		priv->xmit11.task.routine = (void (*)(void *))airo_do_xmit11;
 		priv->xmit11.task.data = (void *)dev;
-		schedule_task(&priv->xmit11.task);
+		schedule_work(&priv->xmit11.task);
 		return;
 	}
 	status = transmit_802_11_packet (priv, fids[fid], skb->data);
@@ -1466,7 +1466,7 @@
 	} else {
 		ai->promisc_task.routine = (void (*)(void *))airo_end_promisc;
 		ai->promisc_task.data = (void *)ai;
-		schedule_task(&ai->promisc_task);
+		schedule_work(&ai->promisc_task);
 	}
 }
 
@@ -1482,7 +1482,7 @@
 	} else {
 		ai->promisc_task.routine = (void (*)(void *))airo_set_promisc;
 		ai->promisc_task.data = (void *)ai;
-		schedule_task(&ai->promisc_task);
+		schedule_work(&ai->promisc_task);
 	}
 }
 
@@ -1550,7 +1550,7 @@
 void stop_airo_card( struct net_device *dev, int freeres )
 {
 	struct airo_info *ai = dev->priv;
-	flush_scheduled_tasks();
+	flush_scheduled_work();
 	if (ai->flash)
 		kfree(ai->flash);
 	if (ai->rssi)
@@ -1814,7 +1814,7 @@
 	} else {
 		ai->event_task.routine = (void (*)(void *))airo_send_event;
 		ai->event_task.data = (void *)dev;
-		schedule_task(&ai->event_task);
+		schedule_work(&ai->event_task);
 	}
 }
 #endif
@@ -1833,7 +1833,7 @@
 	} else {
 		ai->mic_task.routine = (void (*)(void *))airo_read_mic;
 		ai->mic_task.data = (void *)ai;
-		schedule_task(&ai->mic_task);
+		schedule_work(&ai->mic_task);
 	}
 }
 
--- linux/drivers/net/wireless/orinoco.h.orig	Tue Oct  1 14:01:22 2002
+++ linux/drivers/net/wireless/orinoco.h	Tue Oct  1 14:37:40 2002
@@ -11,7 +11,7 @@
 #include <linux/spinlock.h>
 #include <linux/netdevice.h>
 #include <linux/wireless.h>
-#include <linux/tqueue.h>
+#include <linux/workqueue.h>
 #include "hermes.h"
 
 /* To enable debug messages */
@@ -42,7 +42,7 @@
 	/* Synchronisation stuff */
 	spinlock_t lock;
 	int hw_unavailable;
-	struct tq_struct timeout_task;
+	work_t timeout_task;
 
 	int open;
 
--- linux/drivers/net/wireless/orinoco.c.orig	Tue Oct  1 14:37:32 2002
+++ linux/drivers/net/wireless/orinoco.c	Tue Oct  1 14:38:09 2002
@@ -323,7 +323,7 @@
  *	  the card from hard sleep.
  *
  * v0.13beta1 -> v0.13 - 27 Sep 2002 - David Gibson
- *	o Re-introduced full resets (via schedule_task()) on Tx
+ *	o Re-introduced full resets (via schedule_work()) on Tx
  *	  timeout.
  *
  * v0.13 -> v0.13a - 30 Sep 2002 - David Gibson
@@ -378,7 +378,7 @@
 #include <linux/if_arp.h>
 #include <linux/etherdevice.h>
 #include <linux/wireless.h>
-#include <linux/tqueue.h>
+#include <linux/workqueue.h>
 
 #include "hermes.h"
 #include "hermes_rid.h"
@@ -889,7 +889,7 @@
 }
 
 /* This must be called from user context, without locks held - use
- * schedule_task() */
+ * schedule_work() */
 static void orinoco_reset(struct net_device *dev)
 {
 	struct orinoco_private *priv = dev->priv;
@@ -2317,7 +2317,7 @@
 
 	stats->tx_errors++;
 
-	schedule_task(&priv->timeout_task);
+	schedule_work(&priv->timeout_task);
 }
 
 static int
@@ -3708,7 +3708,7 @@
 		
 		printk(KERN_DEBUG "%s: Force scheduling reset!\n", dev->name);
 
-		schedule_task(&priv->timeout_task);
+		schedule_work(&priv->timeout_task);
 		break;
 
 	case SIOCIWFIRSTPRIV + 0x2: /* set_port3 */
@@ -4241,7 +4241,7 @@
 	priv->hw_unavailable = 1; /* orinoco_init() must clear this
 				   * before anything else touches the
 				   * hardware */
-	INIT_TQUEUE(&priv->timeout_task, (void (*)(void *))orinoco_reset, dev);
+	INIT_WORK(&priv->timeout_task, (void (*)(void *))orinoco_reset, dev);
 
 	return dev;
 
--- linux/drivers/net/aironet4500.h.orig	Tue Oct  1 14:01:22 2002
+++ linux/drivers/net/aironet4500.h	Tue Oct  1 14:16:17 2002
@@ -1478,8 +1478,8 @@
 	u8			link_status_changed;
 	
 	volatile int		ejected;
-	volatile int		bh_running;
-	volatile int		bh_active;
+	volatile int		work_running;
+	volatile int		work_active;
 	volatile long		tx_chain_active;
 	volatile u16		enabled_interrupts;
 	volatile u16		waiting_interrupts;
@@ -1499,7 +1499,7 @@
         struct awc_command	cmd;
         long long		async_command_start;
         volatile int		command_semaphore_on;
-        struct tq_struct 	immediate_bh;
+        work_t			work;
 	volatile int		process_tx_results;
 
 	u8			p2p[6];
@@ -1559,7 +1559,7 @@
 extern int	awc_transmit_packet(struct net_device * dev, struct awc_fid * tx_buff) ;
 extern int	awc_tx_complete_check(struct net_device * dev);
 extern int	awc_interrupt_process(struct net_device * dev);
-extern void 	awc_bh(struct net_device *dev);
+extern void 	awc_work(struct net_device *dev);
 extern int 	awc_802_11_find_copy_path(struct net_device * dev, struct awc_fid * rx_buff);
 extern void 	awc_802_11_router_rx(struct net_device * dev,struct awc_fid * rx_buff);
 extern int 	awc_802_11_tx_find_path_and_post(struct net_device * dev, struct sk_buff * skb);
--- linux/drivers/net/sungem.h.orig	Tue Oct  1 14:01:22 2002
+++ linux/drivers/net/sungem.h	Tue Oct  1 14:39:58 2002
@@ -967,7 +967,7 @@
 	int hw_running;
 	int opened;
 	struct semaphore pm_sem;
-	struct tq_struct pm_task;
+	work_t pm_task;
 	struct timer_list pm_timer;
 
 	struct gem_init_block *init_block;
@@ -999,7 +999,7 @@
 	struct timer_list	link_timer;
 	int			timer_ticks;
 	int			wake_on_lan;
-	struct tq_struct	reset_task;
+	work_t			reset_task;
 	volatile int		reset_task_pending;
 	
 	/* Diagnostic counters and state. */
--- linux/drivers/net/tlan.h.orig	Tue Oct  1 14:01:22 2002
+++ linux/drivers/net/tlan.h	Tue Oct  1 14:41:20 2002
@@ -208,7 +208,7 @@
 	spinlock_t		lock;
 	u8			link;
 	u8			is_eisa;
-	struct tq_struct	tlan_tqueue;
+	work_t			tlan_tqueue;
 	u8			neg_be_verbose;
 } TLanPrivateInfo;
 
--- linux/drivers/net/ns83820.c.orig	Tue Oct  1 14:01:22 2002
+++ linux/drivers/net/ns83820.c	Tue Oct  1 14:42:27 2002
@@ -93,7 +93,7 @@
 #include <linux/etherdevice.h>
 #include <linux/delay.h>
 #include <linux/smp_lock.h>
-#include <linux/tqueue.h>
+#include <linux/workqueue.h>
 #include <linux/init.h>
 #include <linux/ip.h>	/* for iph */
 #include <linux/in.h>	/* for IPPROTO_... */
@@ -411,7 +411,7 @@
 	struct tasklet_struct	rx_tasklet;
 
 	unsigned		ihr;
-	struct tq_struct	tq_refill;
+	work_t	tq_refill;
 
 	/* protects everything below.  irqsave when using. */
 	spinlock_t		misc_lock;
@@ -784,7 +784,7 @@
 	}
 
 	if (dev->rx_info.up && nr_rx_empty(dev) > NR_RX_DESC*3/4)
-		schedule_task(&dev->tq_refill);
+		schedule_work(&dev->tq_refill);
 	else
 		kick_rx(dev);
 	if (dev->rx_info.idle)
@@ -1438,7 +1438,7 @@
 	dev->ee.lock = &dev->misc_lock;
 	dev->net_dev.owner = THIS_MODULE;
 
-	PREPARE_TQUEUE(&dev->tq_refill, queue_refill, dev);
+	INIT_WORK(&dev->tq_refill, queue_refill, dev);
 	tasklet_init(&dev->rx_tasklet, rx_action, (unsigned long)dev);
 
 	err = pci_enable_device(pci_dev);
--- linux/drivers/net/plip.c.orig	Tue Oct  1 14:01:22 2002
+++ linux/drivers/net/plip.c	Tue Oct  1 14:46:28 2002
@@ -110,7 +110,7 @@
 #include <linux/if_plip.h>
 #include <net/neighbour.h>
 
-#include <linux/tqueue.h>
+#include <linux/workqueue.h>
 #include <linux/ioport.h>
 #include <linux/spinlock.h>
 #include <asm/bitops.h>
@@ -211,9 +211,9 @@
 
 struct net_local {
 	struct net_device_stats enet_stats;
-	struct tq_struct immediate;
-	struct tq_struct deferred;
-	struct tq_struct timer;
+	work_t immediate;
+	work_t deferred;
+	work_t timer;
 	struct plip_local snd_data;
 	struct plip_local rcv_data;
 	struct pardevice *pardev;
@@ -348,22 +348,11 @@
 	nl->nibble	= PLIP_NIBBLE_WAIT;
 
 	/* Initialize task queue structures */
-	INIT_LIST_HEAD(&nl->immediate.list);
-	nl->immediate.sync = 0;
-	nl->immediate.routine = (void (*)(void *))plip_bh;
-	nl->immediate.data = dev;
-
-	INIT_LIST_HEAD(&nl->deferred.list);
-	nl->deferred.sync = 0;
-	nl->deferred.routine = (void (*)(void *))plip_kick_bh;
-	nl->deferred.data = dev;
-
-	if (dev->irq == -1) {
-		INIT_LIST_HEAD(&nl->timer.list);
-		nl->timer.sync = 0;
-		nl->timer.routine = (void (*)(void *))plip_timer_bh;
-		nl->timer.data = dev;
-	}
+	INIT_WORK(&nl->immediate, (void (*)(void *))plip_bh, dev);
+	INIT_WORK(&nl->deferred, (void (*)(void *))plip_kick_bh, dev);
+
+	if (dev->irq == -1)
+		INIT_WORK(&nl->timer, (void (*)(void *))plip_timer_bh, dev);
 
 	spin_lock_init(&nl->lock);
 
@@ -378,10 +367,8 @@
 {
 	struct net_local *nl = (struct net_local *)dev->priv;
 
-	if (nl->is_deferred) {
-		queue_task(&nl->immediate, &tq_immediate);
-		mark_bh(IMMEDIATE_BH);
-	}
+	if (nl->is_deferred)
+		schedule_work(&nl->immediate);
 }
 
 /* Forward declarations of internal routines */
@@ -432,7 +419,7 @@
 	if ((r = (*f)(dev, nl, snd, rcv)) != OK
 	    && (r = plip_bh_timeout_error(dev, nl, snd, rcv, r)) != OK) {
 		nl->is_deferred = 1;
-		queue_task(&nl->deferred, &tq_timer);
+		schedule_delayed_work(&nl->deferred, 1);
 	}
 }
 
@@ -444,7 +431,7 @@
 	if (!(atomic_read (&nl->kill_timer))) {
 		plip_interrupt (-1, dev, NULL);
 
-		queue_task (&nl->timer, &tq_timer);
+		schedule_delayed_work(&nl->timer, 1);
 	}
 	else {
 		up (&nl->killed_timer_sem);
@@ -665,7 +652,7 @@
 				rcv->state = PLIP_PK_DONE;
 				nl->is_deferred = 1;
 				nl->connection = PLIP_CN_SEND;
-				queue_task(&nl->deferred, &tq_timer);
+				schedule_delayed_work(&nl->deferred, 1);
 				enable_parport_interrupts (dev);
 				ENABLE(dev->irq);
 				return OK;
@@ -740,8 +727,7 @@
 		if (snd->state != PLIP_PK_DONE) {
 			nl->connection = PLIP_CN_SEND;
 			spin_unlock_irq(&nl->lock);
-			queue_task(&nl->immediate, &tq_immediate);
-			mark_bh(IMMEDIATE_BH);
+			schedule_work(&nl->immediate);
 			enable_parport_interrupts (dev);
 			ENABLE(dev->irq);
 			return OK;
@@ -909,7 +895,7 @@
 			printk(KERN_DEBUG "%s: send end\n", dev->name);
 		nl->connection = PLIP_CN_CLOSING;
 		nl->is_deferred = 1;
-		queue_task(&nl->deferred, &tq_timer);
+		schedule_delayed_work(&nl->deferred, 1);
 		enable_parport_interrupts (dev);
 		ENABLE(dev->irq);
 		return OK;
@@ -953,7 +939,7 @@
 		netif_wake_queue (dev);
 	} else {
 		nl->is_deferred = 1;
-		queue_task(&nl->deferred, &tq_timer);
+		schedule_delayed_work(&nl->deferred, 1);
 	}
 
 	return OK;
@@ -997,8 +983,7 @@
 		rcv->state = PLIP_PK_TRIGGER;
 		nl->connection = PLIP_CN_RECEIVE;
 		nl->timeout_count = 0;
-		queue_task(&nl->immediate, &tq_immediate);
-		mark_bh(IMMEDIATE_BH);
+		schedule_work(&nl->immediate);
 		break;
 
 	case PLIP_CN_RECEIVE:
@@ -1051,8 +1036,7 @@
 		nl->connection = PLIP_CN_SEND;
 		nl->timeout_count = 0;
 	}
-	queue_task(&nl->immediate, &tq_immediate);
-	mark_bh(IMMEDIATE_BH);
+	schedule_work(&nl->immediate);
 	spin_unlock_irq(&nl->lock);
 	
 	return 0;
@@ -1131,7 +1115,7 @@
 	if (dev->irq == -1)
 	{
 		atomic_set (&nl->kill_timer, 0);
-		queue_task (&nl->timer, &tq_timer);
+		schedule_delayed_work(&nl->timer, 1);
 	}
 
 	/* Initialize the state machine. */
--- linux/drivers/net/aironet4500_core.c.orig	Tue Oct  1 14:14:03 2002
+++ linux/drivers/net/aironet4500_core.c	Tue Oct  1 14:17:00 2002
@@ -22,7 +22,7 @@
 #include <linux/init.h>
 #include <linux/config.h>
 #include <linux/kernel.h>
-#include <linux/tqueue.h>
+#include <linux/workqueue.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
@@ -2202,10 +2202,9 @@
 
 
 #define AWC_QUEUE_BH {\
-	if (!priv->bh_active && !priv->bh_running){\
-		priv->bh_active = 1;\
-		queue_task(&priv->immediate_bh, &tq_immediate);\
-		mark_bh(IMMEDIATE_BH);\
+	if (!priv->work_active && !priv->work_running){\
+		priv->work_active = 1;\
+		schedule_work(&priv->work); \
 	}\
 	}
 
@@ -2223,7 +2222,7 @@
 
 	DEBUG(8, "awc_bh awoken on jiffie %ld \n",jiffies);
 
-	priv->bh_running = 1;
+	priv->work_running = 1;
 	
 	active_interrupts = awc_event_status(dev->base_addr);
 	
@@ -2233,7 +2232,7 @@
 
         if (test_and_set_bit( 0, (void *) &priv->tx_chain_active) ) {
 //		printk(KERN_ERR "tx chain active in bh \n");
-//		queue_task(&priv->immediate_bh, &tq_immediate);
+//		schedule_work(&priv->work);
 		goto bad_end;
 	}
 start:
@@ -2281,8 +2280,8 @@
 				goto start;
 			}
 		};
-		priv->bh_active  = 0;
-		priv->bh_running = 0;
+		priv->work_active  = 0;
+		priv->work_running = 0;
 
         priv->tx_chain_active = 0;
 
@@ -2292,8 +2291,8 @@
 //	if (!priv->tx_chain_active) 
 //		wake_up(&priv->tx_chain_wait_queue);
   
-  	priv->bh_running = 0;
-	priv->bh_active = 0;
+  	priv->work_running = 0;
+	priv->work_active = 0;
 	return ;
 };
 
@@ -2366,7 +2365,7 @@
 		//priv->
 		netif_device_detach (dev);
 		priv->ejected = 1;
-		if (priv->bh_active || priv->bh_running){
+		if (priv->work_active || priv->work_running){
 			priv->interrupt_count--;
 			goto bad_end;
 		} else if (priv->command_semaphore_on){
@@ -2498,8 +2497,8 @@
 	active_interrupts = awc_event_status(dev->base_addr);
 
 	if ((active_interrupts & 0x7) && 
-	     !priv->bh_active && 
-	     !priv->bh_running ){
+	     !priv->work_active && 
+	     !priv->work_running ){
 		if (multi_ints++ < 5)
 			goto start;
         }
@@ -2874,12 +2873,9 @@
 	
 	priv->command_semaphore_on = 0;
 	priv->unlock_command_postponed = 0;
-	INIT_LIST_HEAD(&priv->immediate_bh.list);
-	priv->immediate_bh.sync 	= 0;
-	priv->immediate_bh.routine 	= (void *)(void *)awc_bh;
-	priv->immediate_bh.data 	= dev;
-	priv->bh_running	= 0;
-	priv->bh_active		= 0;
+	INIT_WORK(&priv->work, (void *)(void *)awc_work, dev);
+	priv->work_running	= 0;
+	priv->work_active	= 0;
 	priv->tx_chain_active	= 0;
 	priv->enabled_interrupts= 0x00;
 	priv->waiting_interrupts= 0x00;
--- linux/drivers/net/sungem.c.orig	Tue Oct  1 14:39:32 2002
+++ linux/drivers/net/sungem.c	Tue Oct  1 14:40:00 2002
@@ -40,7 +40,7 @@
 #include <linux/ethtool.h>
 #include <linux/crc32.h>
 #include <linux/random.h>
-#include <linux/tqueue.h>
+#include <linux/workqueue.h>
 
 #include <asm/system.h>
 #include <asm/bitops.h>
@@ -584,7 +584,7 @@
 
 do_reset:
 	gp->reset_task_pending = 2;
-	schedule_task(&gp->reset_task);
+	schedule_work(&gp->reset_task);
 
 	return 1;
 }
@@ -821,7 +821,7 @@
 	spin_lock_irq(&gp->lock);
 
 	gp->reset_task_pending = 2;
-	schedule_task(&gp->reset_task);
+	schedule_work(&gp->reset_task);
 
 	spin_unlock_irq(&gp->lock);
 }
@@ -975,10 +975,10 @@
 	spin_lock_irq(&gp->lock);
 	dev->mtu = new_mtu;
 	gp->reset_task_pending = 1;
-	schedule_task(&gp->reset_task);
+	schedule_work(&gp->reset_task);
 	spin_unlock_irq(&gp->lock);
 
-	flush_scheduled_tasks();
+	flush_scheduled_work();
 
 	return 0;
 }
@@ -1384,7 +1384,7 @@
 					printk(KERN_INFO "%s: Link down\n",
 						gp->dev->name);
 				gp->reset_task_pending = 2;
-				schedule_task(&gp->reset_task);
+				schedule_work(&gp->reset_task);
 				restart = 1;
 			} else if (++gp->timer_ticks > 10)
 				restart = gem_mdio_link_not_up(gp);
@@ -2299,7 +2299,7 @@
 {
 	struct gem *gp = (struct gem *) data;
 
-	schedule_task(&gp->pm_task);
+	schedule_work(&gp->pm_task);
 }
 
 static int gem_open(struct net_device *dev)
@@ -2313,7 +2313,7 @@
 
 	/* Stop the PM timer/task */
 	del_timer(&gp->pm_timer);
-	flush_scheduled_tasks();
+	flush_scheduled_work();
 
 	/* The power-management semaphore protects the hw_running
 	 * etc. state so it is safe to do this bit without gp->lock
@@ -2445,7 +2445,7 @@
 	if (gp->hw_running) {
 		/* Kill PM timer if any */
 		del_timer_sync(&gp->pm_timer);
-		flush_scheduled_tasks();
+		flush_scheduled_work();
 
 		gem_shutdown(gp);
 	}
@@ -2955,8 +2955,8 @@
 	gp->pm_timer.function = gem_pm_timer;
 	gp->pm_timer.data = (unsigned long) gp;
 
-	INIT_TQUEUE(&gp->pm_task, gem_pm_task, gp);
-	INIT_TQUEUE(&gp->reset_task, gem_reset_task, gp);
+	INIT_WORK(&gp->pm_task, gem_pm_task, gp);
+	INIT_WORK(&gp->reset_task, gem_reset_task, gp);
 	
 	/* Default link parameters */
 	if (link_mode >= 0 && link_mode <= 6)
@@ -3061,7 +3061,7 @@
 	down(&gp->pm_sem);
 	/* Stop the PM timer & task */
 	del_timer_sync(&gp->pm_timer);
-	flush_scheduled_tasks();
+	flush_scheduled_work();
 	if (gp->hw_running)
 		gem_shutdown(gp);
 	up(&gp->pm_sem);
@@ -3090,7 +3090,7 @@
 		down(&gp->pm_sem);
 		/* Stop the PM timer & task */
 		del_timer_sync(&gp->pm_timer);
-		flush_scheduled_tasks();
+		flush_scheduled_work();
 		if (gp->hw_running)
 			gem_shutdown(gp);
 		up(&gp->pm_sem);
--- linux/drivers/net/tlan.c.orig	Tue Oct  1 14:40:29 2002
+++ linux/drivers/net/tlan.c	Tue Oct  1 14:41:21 2002
@@ -174,7 +174,7 @@
 #include <linux/etherdevice.h>
 #include <linux/delay.h>
 #include <linux/spinlock.h>
-#include <linux/tqueue.h>
+#include <linux/workqueue.h>
 #include <linux/mii.h>
 
 #include "tlan.h"
@@ -600,10 +600,7 @@
 	
 	/* This will be used when we get an adapter error from
 	 * within our irq handler */
-	INIT_LIST_HEAD(&priv->tlan_tqueue.list);
-	priv->tlan_tqueue.sync = 0;
-	priv->tlan_tqueue.routine = (void *)(void*)TLan_tx_timeout;
-	priv->tlan_tqueue.data = dev;
+	INIT_WORK(&priv->tlan_tqueue, (void *)(void*)TLan_tx_timeout, dev);
 
 	spin_lock_init(&priv->lock);
 	
@@ -1708,7 +1705,7 @@
 		TLan_ReadAndClearStats( dev, TLAN_RECORD );
 		outl( TLAN_HC_AD_RST, dev->base_addr + TLAN_HOST_CMD );
 
-		schedule_task(&priv->tlan_tqueue);
+		schedule_work(&priv->tlan_tqueue);
 
 		netif_wake_queue(dev);
 		ack = 0;
--- linux/drivers/isdn/eicon/eicon.h.orig	Tue Oct  1 14:01:22 2002
+++ linux/drivers/isdn/eicon/eicon.h	Tue Oct  1 14:47:23 2002
@@ -117,7 +117,7 @@
 #include <linux/config.h>
 #include <linux/sched.h>
 #include <linux/string.h>
-#include <linux/tqueue.h>
+#include <linux/workqueue.h>
 #include <linux/interrupt.h>
 #include <linux/skbuff.h>
 #include <linux/errno.h>
@@ -321,9 +321,9 @@
 	struct sk_buff_head sackq;       /* Data-Ack-Message queue           */
 	struct sk_buff_head statq;       /* Status-Message queue             */
 	int statq_entries;
-	struct tq_struct snd_tq;         /* Task struct for xmit bh          */
-	struct tq_struct rcv_tq;         /* Task struct for rcv bh           */
-	struct tq_struct ack_tq;         /* Task struct for ack bh           */
+	work_t snd_tq;         /* Task struct for xmit bh          */
+	work_t rcv_tq;         /* Task struct for rcv bh           */
+	work_t ack_tq;         /* Task struct for ack bh           */
 	eicon_chan*	IdTable[256];	 /* Table to find entity   */
 	__u16  ref_in;
 	__u16  ref_out;
@@ -349,20 +349,17 @@
 
 extern __inline__ void eicon_schedule_tx(eicon_card *card)
 {
-        queue_task(&card->snd_tq, &tq_immediate);
-        mark_bh(IMMEDIATE_BH);
+        schedule_work(&card->snd_tq);
 }
 
 extern __inline__ void eicon_schedule_rx(eicon_card *card)
 {
-        queue_task(&card->rcv_tq, &tq_immediate);
-        mark_bh(IMMEDIATE_BH);
+        schedule_work(&card->rcv_tq);
 }
 
 extern __inline__ void eicon_schedule_ack(eicon_card *card)
 {
-        queue_task(&card->ack_tq, &tq_immediate);
-        mark_bh(IMMEDIATE_BH);
+        schedule_work(&card->ack_tq);
 }
 
 extern int eicon_addcard(int, int, int, char *, int);
--- linux/drivers/isdn/eicon/linsys.c.orig	Tue Oct  1 14:01:22 2002
+++ linux/drivers/isdn/eicon/linsys.c	Tue Oct  1 14:49:12 2002
@@ -10,7 +10,7 @@
 
 #include <linux/sched.h>
 #undef N_DATA
-#include <linux/tqueue.h>
+#include <linux/workqueue.h>
 
 #include <linux/smp.h>
 struct pt_regs;
@@ -79,26 +79,20 @@
 
 int	DivasDpcSchedule(void)
 {
-	static	struct tq_struct DivasTask;
+	static	work_t DivasTask;
 
-	DivasTask.routine = DivasDoDpc;
-	DivasTask.data = (void *) 0;
-
-	queue_task(&DivasTask, &tq_immediate);
-	mark_bh(IMMEDIATE_BH);
+	INIT_WORK(&DivasTask, DivasDoDpc, NULL);
+	schedule_work(&DivasTask);
 
 	return 0;
 }
 
 int	DivasScheduleRequestDpc(void)
 {
-	static	struct tq_struct DivasTask;
-
-	DivasTask.routine = DivasDoRequestDpc;
-	DivasTask.data = (void *) 0;
+	static	work_t DivasTask;
 
-	queue_task(&DivasTask, &tq_immediate);
-	mark_bh(IMMEDIATE_BH);
+	INIT_WORK(&DivasTask, DivasDoRequestDpc, NULL);
+	schedule_work(&DivasTask);
 
 	return 0;
 }
--- linux/drivers/isdn/i4l/isdn_tty.c.orig	Tue Oct  1 15:52:29 2002
+++ linux/drivers/isdn/i4l/isdn_tty.c	Tue Oct  1 15:58:55 2002
@@ -101,7 +101,7 @@
 #endif
 					if (info->emu.mdmreg[REG_CPPP] & BIT_CPPP)
 						tty->flip.flag_buf_ptr[len - 1] = 0xff;
-					queue_task(&tty->flip.tqueue, &tq_timer);
+					schedule_delayed_work(&tty->flip.work, 1);
 					kfree_skb(skb);
 					return 1;
 				}
@@ -153,7 +153,7 @@
 							tty->flip.flag_buf_ptr += r;
 							tty->flip.char_buf_ptr += r;
 							if (r)
-								queue_task(&tty->flip.tqueue, &tq_timer);
+								schedule_delayed_work(&tty->flip.work, 1);
 							restore_flags(flags);
 						}
 					} else
@@ -2498,7 +2498,7 @@
 
 	} else {
 		restore_flags(flags);
-		queue_task(&tty->flip.tqueue, &tq_timer);
+		schedule_delayed_work(&tty->flip.work, 1);
 	}
 }
 
--- linux/drivers/isdn/i4l/isdn_net.c.orig	Tue Oct  1 15:52:29 2002
+++ linux/drivers/isdn/i4l/isdn_net.c	Tue Oct  1 16:00:32 2002
@@ -161,8 +161,7 @@
 
 	if (!(isdn_net_device_busy(lp))) {
 		if (!skb_queue_empty(&lp->super_tx_queue)) {
-			queue_task(&lp->tqueue, &tq_immediate);
-			mark_bh(IMMEDIATE_BH);
+			schedule_work(&lp->tqueue);
 		} else {
 			isdn_net_device_wake_queue(lp);
 		}
@@ -852,8 +851,7 @@
 		// we can't grab the lock from irq context, 
 		// so we just queue the packet
 		skb_queue_tail(&lp->super_tx_queue, skb); 
-		queue_task(&lp->tqueue, &tq_immediate);
-		mark_bh(IMMEDIATE_BH);
+		schedule_work(&lp->tqueue);
 		return;
 	}
 
@@ -1595,9 +1593,7 @@
 	netdev->local.netdev = netdev;
 	netdev->local.next = &netdev->local;
 
-	netdev->local.tqueue.sync = 0;
-	netdev->local.tqueue.routine = isdn_net_softint;
-	netdev->local.tqueue.data = &netdev->local;
+	INIT_WORK(&netdev->local.tqueue, isdn_net_softint, &netdev->local);
 	spin_lock_init(&netdev->local.xmit_lock);
 
 	netdev->isdn_slot = -1;
--- linux/drivers/isdn/hysdn/hysdn_defs.h.orig	Tue Oct  1 14:01:22 2002
+++ linux/drivers/isdn/hysdn/hysdn_defs.h	Tue Oct  1 14:49:28 2002
@@ -17,7 +17,7 @@
 #include <linux/config.h>
 #include <linux/hysdn_if.h>
 #include <linux/interrupt.h>
-#include <linux/tqueue.h>
+#include <linux/workqueue.h>
 #include <linux/skbuff.h>
 
 /****************************/
@@ -173,7 +173,7 @@
 	void (*set_errlog_state) (struct HYSDN_CARD *, int);
 
 	/* interrupt handler + interrupt synchronisation */
-	struct tq_struct irq_queue;	/* interrupt task queue */
+	work_t irq_queue;	/* interrupt task queue */
 	uchar volatile irq_enabled;	/* interrupt enabled if != 0 */
 	uchar volatile hw_lock;	/* hardware is currently locked -> no access */
 
--- linux/drivers/isdn/hysdn/hysdn_net.c.orig	Tue Oct  1 15:53:24 2002
+++ linux/drivers/isdn/hysdn/hysdn_net.c	Tue Oct  1 16:00:44 2002
@@ -169,8 +169,7 @@
 	spin_unlock_irq(&lp->lock);
 
 	if (lp->sk_count <= 3) {
-		queue_task(&((hysdn_card *) dev->priv)->irq_queue, &tq_immediate);
-		mark_bh(IMMEDIATE_BH);
+		schedule_work(&((hysdn_card *) dev->priv)->irq_queue);
 	}
 	return (0);		/* success */
 }				/* net_send_packet */
--- linux/drivers/isdn/hysdn/boardergo.c.orig	Tue Oct  1 14:50:37 2002
+++ linux/drivers/isdn/hysdn/boardergo.c	Tue Oct  1 16:01:14 2002
@@ -59,10 +59,8 @@
 	b |= dpr->ToHyInt;	/* and for champ */
 
 	/* start kernel task immediately after leaving all interrupts */
-	if (!card->hw_lock) {
-		queue_task(&card->irq_queue, &tq_immediate);
-		mark_bh(IMMEDIATE_BH);
-	}
+	if (!card->hw_lock)
+		schedule_work(&card->irq_queue);
 	restore_flags(flags);
 }				/* ergo_interrupt */
 
@@ -177,8 +175,7 @@
 		card->err_log_state = ERRLOG_STATE_STOP;	/* request stop */
 
 	restore_flags(flags);
-	queue_task(&card->irq_queue, &tq_immediate);
-	mark_bh(IMMEDIATE_BH);
+	schedule_work(&card->irq_queue);
 }				/* ergo_set_errlog_state */
 
 /******************************************/
@@ -450,9 +447,7 @@
 	card->writebootseq = ergo_writebootseq;
 	card->waitpofready = ergo_waitpofready;
 	card->set_errlog_state = ergo_set_errlog_state;
-	card->irq_queue.sync = 0;
-	card->irq_queue.data = card;	/* init task queue for interrupt */
-	card->irq_queue.routine = (void *) (void *) ergo_irq_bh;
+	INIT_WORK(&card->irq_queue, (void *) (void *) ergo_irq_bh, card);
 
 	return (0);
 }				/* ergo_inithardware */
--- linux/drivers/isdn/hysdn/hycapi.c.orig	Tue Oct  1 15:53:24 2002
+++ linux/drivers/isdn/hysdn/hycapi.c	Tue Oct  1 16:01:07 2002
@@ -131,8 +131,7 @@
 	}
 	cinfo->tx_skb = skb;
 	spin_unlock_irq(&cinfo->lock);
-	queue_task(&card->irq_queue, &tq_immediate);
-	mark_bh(IMMEDIATE_BH);
+	schedule_work(&card->irq_queue);
 }
 
 /***********************************************************
--- linux/drivers/isdn/hysdn/hysdn_sched.c.orig	Tue Oct  1 14:49:59 2002
+++ linux/drivers/isdn/hysdn/hysdn_sched.c	Tue Oct  1 14:50:21 2002
@@ -175,8 +175,7 @@
 	card->async_busy = 1;	/* request transfer */
 
 	/* now queue the task */
-	queue_task(&card->irq_queue, &tq_immediate);
-	mark_bh(IMMEDIATE_BH);
+	schedule_work(&card->irq_queue);
 	sti();
 
 	if (card->debug_flags & LOG_SCHED_ASYN)
--- linux/drivers/isdn/hisax/amd7930.c.orig	Tue Oct  1 14:01:22 2002
+++ linux/drivers/isdn/hisax/amd7930.c	Tue Oct  1 16:05:17 2002
@@ -120,16 +120,14 @@
 	} else {
 		clear_bit(BC_FLG_BUSY, &bcs->Flag);
 		bcs->event |= 1 << B_XMTBUFREADY;
-		queue_task(&bcs->tqueue, &tq_immediate);
-		mark_bh(IMMEDIATE_BH);
+		schedule_work(&bcs->tqueue);
 	}
 }
 
 static void
 Bchan_xmit_callback(struct BCState *bcs)
 {
-	queue_task(&bcs->hw.amd7930.tq_xmt, &tq_immediate);
-	mark_bh(IMMEDIATE_BH);
+	schedule_work(&bcs->hw.amd7930.tq_xmt);
 }
 
 /* B channel transmission: two modes (three, if you count L1_MODE_NULL)
@@ -261,8 +259,7 @@
 			      (void *) &Bchan_recv_callback, (void *) bcs);
 	}
 
-	queue_task(&hw->tq_rcv, &tq_immediate);
-	mark_bh(IMMEDIATE_BH);
+	schedule_work(&hw->tq_rcv);
 }
 
 static void
@@ -308,7 +305,7 @@
 						skb_queue_tail(&bcs->rqueue, hw->rv_skb);
 						hw->rv_skb = skb;
 						bcs->event |= 1 << B_RCVBUFREADY;
-						queue_task(&bcs->tqueue, &tq_immediate);
+						schedule_work(&bcs->tqueue);
 					}
 				} else if (len > 0) {
 					/* Small packet received */
@@ -319,8 +316,7 @@
 						memcpy(skb_put(skb, len), hw->rv_skb->tail, len);
 						skb_queue_tail(&bcs->rqueue, skb);
 						bcs->event |= 1 << B_RCVBUFREADY;
-						queue_task(&bcs->tqueue, &tq_immediate);
-						mark_bh(IMMEDIATE_BH);
+						schedule_work(&bcs->tqueue);
 					}
 				} else {
 					/* Reception Error */
@@ -336,8 +332,7 @@
 				       RCV_BUFSIZE/RCV_BUFBLKS);
 				skb_queue_tail(&bcs->rqueue, skb);
 				bcs->event |= 1 << B_RCVBUFREADY;
-				queue_task(&bcs->tqueue, &tq_immediate);
-				mark_bh(IMMEDIATE_BH);
+				schedule_work(&bcs->tqueue);
 			}
 		}
 
@@ -422,12 +417,11 @@
 	}
 
 	bcs->hw.amd7930.tq_rcv.sync = 0;
-	bcs->hw.amd7930.tq_rcv.routine = (void (*)(void *)) &Bchan_rcv_bh;
-	bcs->hw.amd7930.tq_rcv.data = (void *) bcs;
+	INIT_WORK(&bcs->hw.amd7930.tq_rcv, (void (*)(void *)) &Bchan_rcv_bh,
+			(void *) bcs);
 
-	bcs->hw.amd7930.tq_xmt.sync = 0;
-	bcs->hw.amd7930.tq_xmt.routine = (void (*)(void *)) &Bchan_xmt_bh;
-	bcs->hw.amd7930.tq_xmt.data = (void *) bcs;
+	INIT_WORK(&bcs->hw.amd7930.tq_xmt, (void (*)(void *)) &Bchan_xmt_bh,
+			(void *) bcs);
 }
 
 static void
@@ -466,7 +460,7 @@
 amd7930_drecv_callback(void *arg, int error, unsigned int count)
 {
 	struct IsdnCardState *cs = (struct IsdnCardState *) arg;
-	static struct tq_struct task;
+	static work_t task;
 	struct sk_buff *skb;
 
         /* NOTE: This function is called directly from an interrupt handler */
@@ -479,10 +473,8 @@
 			skb_queue_tail(&cs->rq, skb);
 		}
 
-		task.routine = (void *) DChannel_proc_rcv;
-		task.data = (void *) cs;
-		queue_task(&task, &tq_immediate);
-		mark_bh(IMMEDIATE_BH);
+		INIT_WORK(&task, (void *) DChannel_proc_rcv, (void *) cs);
+		schedule_work(&task);
 	}
 
 	if (cs->debug & L1_DEB_ISAC_FIFO) {
@@ -503,7 +495,7 @@
 amd7930_dxmit_callback(void *arg, int error)
 {
 	struct IsdnCardState *cs = (struct IsdnCardState *) arg;
-	static struct tq_struct task;
+	static work_t task;
 
         /* NOTE: This function is called directly from an interrupt handler */
 
@@ -521,10 +513,8 @@
 
 	cs->tx_skb = NULL;
 
-	task.routine = (void *) DChannel_proc_xmt;
-	task.data = (void *) cs;
-	queue_task(&task, &tq_immediate);
-	mark_bh(IMMEDIATE_BH);
+	INIT_WORK(&task, (void *) DChannel_proc_xmt, (void *) cs);
+	schedule_work(&task);
 }
 
 static void
@@ -643,7 +633,7 @@
 static void
 amd7930_liu_callback(struct IsdnCardState *cs)
 {
-	static struct tq_struct task;
+	static work_t task;
 
 	if (!cs)
 		return;
@@ -654,11 +644,8 @@
 		debugl1(cs, tmp);
 	}
 
-	task.sync = 0;
-	task.routine = (void *) &amd7930_new_ph;
-	task.data = (void *) cs;
-	queue_task(&task, &tq_immediate);
-	mark_bh(IMMEDIATE_BH);
+	INIT_WORK(&task, (void *) &amd7930_new_ph, (void *) cs);
+	schedule_work(&task);
 }
 
 void
--- linux/drivers/isdn/hisax/hisax.h.orig	Tue Oct  1 14:01:22 2002
+++ linux/drivers/isdn/hisax/hisax.h	Tue Oct  1 14:55:24 2002
@@ -453,8 +453,8 @@
 	int rv_buff_out;
 	struct sk_buff *rv_skb;
 	struct hdlc_state *hdlc_state;
-	struct tq_struct tq_rcv;
-	struct tq_struct tq_xmt;
+	work_t tq_rcv;
+	work_t tq_xmt;
 };
 
 #define BC_FLG_INIT	1
@@ -495,7 +495,7 @@
 	u_char *blog;
 	u_char *conmsg;
 	struct timer_list transbusy;
-	struct tq_struct tqueue;
+	work_t tqueue;
 	unsigned long event;
 	int  (*BC_SetStack) (struct PStack *, struct BCState *);
 	void (*BC_Close) (struct BCState *);
@@ -954,7 +954,7 @@
 	struct sk_buff *tx_skb;
 	int tx_cnt;
 	long event;
-	struct tq_struct tqueue;
+	work_t tqueue;
 	struct timer_list dbusytimer;
 #ifdef ERROR_STATISTIC
 	int err_crc;
--- linux/drivers/isdn/hisax/hscx.c.orig	Tue Oct  1 15:52:29 2002
+++ linux/drivers/isdn/hisax/hscx.c	Tue Oct  1 16:01:22 2002
@@ -95,8 +95,7 @@
 hscx_sched_event(struct BCState *bcs, int event)
 {
 	bcs->event |= 1 << event;
-	queue_task(&bcs->tqueue, &tq_immediate);
-	mark_bh(IMMEDIATE_BH);
+	schedule_work(&bcs->tqueue);
 }
 
 void
--- linux/drivers/isdn/hisax/icc.c.orig	Tue Oct  1 15:52:29 2002
+++ linux/drivers/isdn/hisax/icc.c	Tue Oct  1 16:02:02 2002
@@ -191,8 +191,7 @@
 icc_sched_event(struct IsdnCardState *cs, int event)
 {
 	test_and_set_bit(event, &cs->event);
-	queue_task(&cs->tqueue, &tq_immediate);
-	mark_bh(IMMEDIATE_BH);
+	schedule_work(&cs->tqueue);
 }
 
 void
@@ -625,7 +624,7 @@
 void __init
 initicc(struct IsdnCardState *cs)
 {
-	cs->tqueue.routine = (void *) (void *) icc_bh;
+	INIT_WORK(&cs->tqueue, (void *) (void *) icc_bh, NULL);
 	cs->setstack_d = setstack_icc;
 	cs->DC_Close = DC_Close_icc;
 	cs->dc.icc.mon_tx = NULL;
--- linux/drivers/isdn/hisax/hfc_2bds0.c.orig	Tue Oct  1 15:52:29 2002
+++ linux/drivers/isdn/hisax/hfc_2bds0.c	Tue Oct  1 16:02:26 2002
@@ -202,8 +202,7 @@
 hfc_sched_event(struct BCState *bcs, int event)
 {
 	bcs->event |= 1 << event;
-	queue_task(&bcs->tqueue, &tq_immediate);
-	mark_bh(IMMEDIATE_BH);
+	schedule_work(&bcs->tqueue);
 }
 
 static struct sk_buff
@@ -646,8 +645,7 @@
 sched_event_D(struct IsdnCardState *cs, int event)
 {
 	test_and_set_bit(event, &cs->event);
-	queue_task(&cs->tqueue, &tq_immediate);
-	mark_bh(IMMEDIATE_BH);
+	schedule_work(&cs->tqueue);
 }
 
 static
@@ -1129,7 +1127,7 @@
 	cs->dbusytimer.function = (void *) hfc_dbusy_timer;
 	cs->dbusytimer.data = (long) cs;
 	init_timer(&cs->dbusytimer);
-	cs->tqueue.routine = (void *) (void *) hfcd_bh;
+	INIT_WORK(&cs->tqueue, (void *) (void *) hfcd_bh, NULL);
 	if (!cs->hw.hfcD.send)
 		cs->hw.hfcD.send = init_send_hfcd(16);
 	if (!cs->bcs[0].hw.hfc.send)
--- linux/drivers/isdn/hisax/hfc_sx.c.orig	Tue Oct  1 15:52:29 2002
+++ linux/drivers/isdn/hisax/hfc_sx.c	Tue Oct  1 16:02:52 2002
@@ -464,8 +464,7 @@
 sched_event_D_sx(struct IsdnCardState *cs, int event)
 {
 	test_and_set_bit(event, &cs->event);
-	queue_task(&cs->tqueue, &tq_immediate);
-	mark_bh(IMMEDIATE_BH);
+	schedule_work(&cs->tqueue);
 }
 
 /*********************************/
@@ -475,8 +474,7 @@
 hfcsx_sched_event(struct BCState *bcs, int event)
 {
 	bcs->event |= 1 << event;
-	queue_task(&bcs->tqueue, &tq_immediate);
-	mark_bh(IMMEDIATE_BH);
+	schedule_work(&bcs->tqueue);
 }
 
 /************************************************/
@@ -1412,7 +1410,7 @@
 	cs->dbusytimer.function = (void *) hfcsx_dbusy_timer;
 	cs->dbusytimer.data = (long) cs;
 	init_timer(&cs->dbusytimer);
-	cs->tqueue.routine = (void *) (void *) hfcsx_bh;
+	INIT_WORK(&cs->tqueue, (void *) (void *) hfcsx_bh, NULL);
 	cs->BC_Send_Data = &hfcsx_send_data;
 	cs->bcs[0].BC_SetStack = setstack_2b;
 	cs->bcs[1].BC_SetStack = setstack_2b;
--- linux/drivers/isdn/hisax/hfc_2bs0.c.orig	Tue Oct  1 15:52:29 2002
+++ linux/drivers/isdn/hisax/hfc_2bs0.c	Tue Oct  1 16:03:10 2002
@@ -86,8 +86,7 @@
 hfc_sched_event(struct BCState *bcs, int event)
 {
 	bcs->event |= 1 << event;
-	queue_task(&bcs->tqueue, &tq_immediate);
-	mark_bh(IMMEDIATE_BH);
+	schedule_work(&bcs->tqueue);
 }
 
 static void
--- linux/drivers/isdn/hisax/isac.c.orig	Tue Oct  1 15:52:29 2002
+++ linux/drivers/isdn/hisax/isac.c	Tue Oct  1 16:03:34 2002
@@ -195,8 +195,7 @@
 isac_sched_event(struct IsdnCardState *cs, int event)
 {
 	test_and_set_bit(event, &cs->event);
-	queue_task(&cs->tqueue, &tq_immediate);
-	mark_bh(IMMEDIATE_BH);
+	schedule_work(&cs->tqueue);
 }
 
 void
@@ -627,7 +626,7 @@
 void __devinit
 initisac(struct IsdnCardState *cs)
 {
-	cs->tqueue.routine = (void *) (void *) isac_bh;
+	INIT_WORK(&cs->tqueue, (void *) (void *) isac_bh, NULL);
 	cs->setstack_d = setstack_isac;
 	cs->DC_Close = DC_Close_isac;
 	cs->dc.isac.mon_tx = NULL;
--- linux/drivers/isdn/hisax/netjet.c.orig	Tue Oct  1 15:52:29 2002
+++ linux/drivers/isdn/hisax/netjet.c	Tue Oct  1 16:03:46 2002
@@ -434,8 +434,7 @@
 		skb_queue_tail(&bcs->rqueue, skb);
 	}
 	bcs->event |= 1 << B_RCVBUFREADY;
-	queue_task(&bcs->tqueue, &tq_immediate);
-	mark_bh(IMMEDIATE_BH);
+	schedule_work(&bcs->tqueue);
 	
 	if (bcs->cs->debug & L1_DEB_RECEIVE_FRAME)
 		printframe(bcs->cs, bcs->hw.tiger.rcvbuf, count, "rec");
@@ -791,8 +790,7 @@
 							cnt - s_cnt);
 				}
 				bcs->event |= 1 << B_XMTBUFREADY;
-				queue_task(&bcs->tqueue, &tq_immediate);
-				mark_bh(IMMEDIATE_BH);
+				schedule_work(&bcs->tqueue);
 			}
 		}
 	} else if (test_and_clear_bit(BC_FLG_NOFRAME, &bcs->Flag)) {
--- linux/drivers/isdn/hisax/isdnl1.c.orig	Tue Oct  1 15:52:29 2002
+++ linux/drivers/isdn/hisax/isdnl1.c	Tue Oct  1 16:04:12 2002
@@ -345,9 +345,7 @@
 
 	bcs->cs = cs;
 	bcs->channel = bc;
-	bcs->tqueue.sync = 0;
-	bcs->tqueue.routine = (void *) (void *) BChannel_bh;
-	bcs->tqueue.data = bcs;
+	INIT_WORK(&bcs->tqueue, (void *) (void *) BChannel_bh, bcs);
 	bcs->BC_SetStack = NULL;
 	bcs->BC_Close = NULL;
 	bcs->Flag = 0;
--- linux/drivers/isdn/hisax/jade.c.orig	Tue Oct  1 15:52:29 2002
+++ linux/drivers/isdn/hisax/jade.c	Tue Oct  1 16:04:23 2002
@@ -138,8 +138,7 @@
 jade_sched_event(struct BCState *bcs, int event)
 {
     bcs->event |= 1 << event;
-    queue_task(&bcs->tqueue, &tq_immediate);
-    mark_bh(IMMEDIATE_BH);
+    schedule_work(&bcs->tqueue);
 }
 
 static void
--- linux/drivers/isdn/hisax/avm_pci.c.orig	Tue Oct  1 15:52:29 2002
+++ linux/drivers/isdn/hisax/avm_pci.c	Tue Oct  1 16:04:28 2002
@@ -200,8 +200,7 @@
 hdlc_sched_event(struct BCState *bcs, int event)
 {
 	bcs->event |= 1 << event;
-	queue_task(&bcs->tqueue, &tq_immediate);
-	mark_bh(IMMEDIATE_BH);
+	schedule_work(&bcs->tqueue);
 }
 
 void
--- linux/drivers/isdn/hisax/hfc_pci.c.orig	Tue Oct  1 15:52:29 2002
+++ linux/drivers/isdn/hisax/hfc_pci.c	Tue Oct  1 16:05:43 2002
@@ -194,8 +194,7 @@
 sched_event_D_pci(struct IsdnCardState *cs, int event)
 {
 	test_and_set_bit(event, &cs->event);
-	queue_task(&cs->tqueue, &tq_immediate);
-	mark_bh(IMMEDIATE_BH);
+	schedule_work(&cs->tqueue);
 }
 
 /*********************************/
@@ -205,8 +204,7 @@
 hfcpci_sched_event(struct BCState *bcs, int event)
 {
 	bcs->event |= 1 << event;
-	queue_task(&bcs->tqueue, &tq_immediate);
-	mark_bh(IMMEDIATE_BH);
+	schedule_work(&bcs->tqueue);
 }
 
 /************************************************/
@@ -1624,7 +1622,7 @@
 	cs->dbusytimer.function = (void *) hfcpci_dbusy_timer;
 	cs->dbusytimer.data = (long) cs;
 	init_timer(&cs->dbusytimer);
-	cs->tqueue.routine = (void *) (void *) hfcpci_bh;
+	INIT_WORK(&cs->tqueue, (void *) (void *) hfcpci_bh, NULL);
 	cs->BC_Send_Data = &hfcpci_send_data;
 	cs->bcs[0].BC_SetStack = setstack_2b;
 	cs->bcs[1].BC_SetStack = setstack_2b;
--- linux/drivers/isdn/hisax/isar.c.orig	Tue Oct  1 15:52:29 2002
+++ linux/drivers/isdn/hisax/isar.c	Tue Oct  1 16:06:03 2002
@@ -447,8 +447,7 @@
 isar_sched_event(struct BCState *bcs, int event)
 {
 	bcs->event |= 1 << event;
-	queue_task(&bcs->tqueue, &tq_immediate);
-	mark_bh(IMMEDIATE_BH);
+	schedule_work(&bcs->tqueue);
 }
 
 static inline void
@@ -1561,7 +1560,7 @@
 		cs->bcs[i].mode = 0;
 		cs->bcs[i].hw.isar.dpath = i + 1;
 		modeisar(&cs->bcs[i], 0, 0);
-		cs->bcs[i].tqueue.routine = (void *) (void *) isar_bh;
+		INIT_WORK(&cs->bcs[i].tqueue, (void *) (void *) isar_bh, NULL);
 	}
 }
 
--- linux/drivers/isdn/hisax/ipacx.c.orig	Tue Oct  1 15:52:29 2002
+++ linux/drivers/isdn/hisax/ipacx.c	Tue Oct  1 16:06:31 2002
@@ -304,8 +304,7 @@
 dch_sched_event(struct IsdnCardState *cs, int event)
 {
 	set_bit(event, &cs->event);
-	queue_task(&cs->tqueue, &tq_immediate);
-	mark_bh(IMMEDIATE_BH);
+	schedule_work(&cs->tqueue);
 }
 
 //----------------------------------------------------------
@@ -510,7 +509,7 @@
 {
 	printk(KERN_INFO "HiSax: IPACX ISDN driver v0.1.0\n");
 
-	cs->tqueue.routine  = (void *)(void *) dch_bh;
+	INIT_WORK(&cs->tqueue, (void *)(void *) dch_bh);
 	cs->setstack_d      = dch_setstack;
   
 	cs->dbusytimer.function = (void *) dbusy_timer_handler;
@@ -593,8 +592,7 @@
 bch_sched_event(struct BCState *bcs, int event)
 {
 	bcs->event |= 1 << event;
-	queue_task(&bcs->tqueue, &tq_immediate);
-	mark_bh(IMMEDIATE_BH);
+	schedule_work(&bcs->tqueue);
 }
 
 //----------------------------------------------------------
--- linux/drivers/isdn/hisax/amd7930_fn.c.orig	Tue Oct  1 15:52:29 2002
+++ linux/drivers/isdn/hisax/amd7930_fn.c	Tue Oct  1 16:06:57 2002
@@ -277,8 +277,7 @@
         }
 
         test_and_set_bit(event, &cs->event);
-	queue_task(&cs->tqueue, &tq_immediate);
-	mark_bh(IMMEDIATE_BH);
+	schedule_work(&cs->tqueue);
 }
 
 static void
@@ -791,7 +790,7 @@
         cs->dc.amd7930.old_state = 0;
         cs->dc.amd7930.lmr1 = 0x40;
         cs->dc.amd7930.ph_command = Amd7930_ph_command;
-        cs->tqueue.routine = (void *) (void *) Amd7930_bh;
+	INIT_WORK(&cs->tqueue, (void *) (void *) Amd7930_bh, NULL);
 	cs->setstack_d = setstack_Amd7930;
 	cs->DC_Close = DC_Close_Amd7930;
 	cs->dbusytimer.function = (void *) dbusy_timer_handler;
--- linux/drivers/isdn/hisax/config.c.orig	Tue Oct  1 15:52:29 2002
+++ linux/drivers/isdn/hisax/config.c	Tue Oct  1 16:07:26 2002
@@ -22,7 +22,7 @@
 #include "hisax.h"
 #include <linux/module.h>
 #include <linux/kernel_stat.h>
-#include <linux/tqueue.h>
+#include <linux/workqueue.h>
 #include <linux/interrupt.h>
 #define HISAX_STATUS_BUFSIZE 4096
 #define INCLUDE_INLINE_FUNCS
@@ -1789,7 +1789,7 @@
 	hisax_d_if->cs = cs;
 	cs->hw.hisax_d_if = hisax_d_if;
 	cs->cardmsg = hisax_cardmsg;
-	cs->tqueue.routine = (void *) (void *) hisax_bh;
+	INIT_WORK(&cs->tqueue, (void *) (void *) hisax_bh, NULL);
 	cs->channel[0].d_st->l1.l2l1 = hisax_d_l2l1;
 	for (i = 0; i < 2; i++) {
 		cs->bcs[i].BC_SetStack = hisax_bc_setstack;
@@ -1818,8 +1818,7 @@
 static void hisax_sched_event(struct IsdnCardState *cs, int event)
 {
 	cs->event |= 1 << event;
-	queue_task(&cs->tqueue, &tq_immediate);
-	mark_bh(IMMEDIATE_BH);
+	schedule_work(&cs->tqueue);
 }
 
 static void hisax_bh(struct IsdnCardState *cs)
@@ -1845,8 +1844,7 @@
 static void hisax_b_sched_event(struct BCState *bcs, int event)
 {
 	bcs->event |= 1 << event;
-	queue_task(&bcs->tqueue, &tq_immediate);
-	mark_bh(IMMEDIATE_BH);
+	schedule_work(&bcs->tqueue);
 }
 
 static inline void D_L2L1(struct hisax_d_if *d_if, int pr, void *arg)
--- linux/drivers/isdn/hisax/w6692.c.orig	Tue Oct  1 15:52:29 2002
+++ linux/drivers/isdn/hisax/w6692.c	Tue Oct  1 16:07:49 2002
@@ -135,16 +135,14 @@
 W6692_sched_event(struct IsdnCardState *cs, int event)
 {
 	test_and_set_bit(event, &cs->event);
-	queue_task(&cs->tqueue, &tq_immediate);
-	mark_bh(IMMEDIATE_BH);
+	schedule_work(&cs->tqueue);
 }
 
 static void
 W6692B_sched_event(struct BCState *bcs, int event)
 {
 	bcs->event |= 1 << event;
-	queue_task(&bcs->tqueue, &tq_immediate);
-	mark_bh(IMMEDIATE_BH);
+	schedule_work(&bcs->tqueue);
 }
 
 static void
@@ -889,7 +887,7 @@
 void __init initW6692(struct IsdnCardState *cs, int part)
 {
 	if (part & 1) {
-		cs->tqueue.routine = (void *) (void *) W6692_bh;
+		INIT_WORK(&cs->tqueue, (void *) (void *) W6692_bh, NULL);
 		cs->setstack_d = setstack_W6692;
 		cs->DC_Close = DC_Close_W6692;
 		cs->dbusytimer.function = (void *) dbusy_timer_handler;
--- linux/drivers/isdn/pcbit/pcbit.h.orig	Tue Oct  1 14:01:22 2002
+++ linux/drivers/isdn/pcbit/pcbit.h	Tue Oct  1 14:56:05 2002
@@ -12,7 +12,7 @@
 #ifndef PCBIT_H
 #define PCBIT_H
 
-#include <linux/tqueue.h>
+#include <linux/workqueue.h>
 
 #define MAX_PCBIT_CARDS 4
 
@@ -74,7 +74,7 @@
 
 	struct timer_list error_recover_timer;
 
-	struct tq_struct qdelivery;
+	work_t qdelivery;
 
 	u_char w_busy;
 	u_char r_busy;
--- linux/drivers/isdn/pcbit/drv.c.orig	Tue Oct  1 14:56:33 2002
+++ linux/drivers/isdn/pcbit/drv.c	Tue Oct  1 14:56:58 2002
@@ -130,9 +130,7 @@
 	memset(dev->b2, 0, sizeof(struct pcbit_chan));
 	dev->b2->id = 1;
 
-	dev->qdelivery.sync = 0;
-	dev->qdelivery.routine = pcbit_deliver;
-	dev->qdelivery.data = dev;
+	INIT_WORK(&dev->qdelivery, pcbit_deliver, dev);
 
 	/*
 	 *  interrupts
--- linux/drivers/isdn/pcbit/layer2.c.orig	Tue Oct  1 15:52:29 2002
+++ linux/drivers/isdn/pcbit/layer2.c	Tue Oct  1 16:08:02 2002
@@ -30,7 +30,7 @@
 #include <linux/types.h>
 #include <linux/slab.h>
 #include <linux/interrupt.h>
-#include <linux/tqueue.h>
+#include <linux/workqueue.h>
 #include <linux/mm.h>
 #include <linux/skbuff.h>
 
@@ -81,8 +81,7 @@
 static __inline__ void
 pcbit_sched_delivery(struct pcbit_dev *dev)
 {
-	queue_task(&dev->qdelivery, &tq_immediate);
-	mark_bh(IMMEDIATE_BH);
+	schedule_work(&dev->qdelivery);
 }
 
 
--- linux/drivers/isdn/tpam/tpam.h.orig	Tue Oct  1 14:01:22 2002
+++ linux/drivers/isdn/tpam/tpam.h	Tue Oct  1 14:57:26 2002
@@ -16,7 +16,7 @@
 
 #include <linux/isdnif.h>
 #include <linux/init.h>
-#include <linux/tqueue.h>
+#include <linux/workqueue.h>
 
 /* Maximum number of channels for this board */
 #define TPAM_NBCHANNEL		30
@@ -86,8 +86,8 @@
 	int roundrobin;			/* round robin between channels */
 	struct sk_buff_head sendq;	/* send queue */
 	struct sk_buff_head recvq;	/* receive queue */
-	struct tq_struct send_tq;	/* send task queue */
-	struct tq_struct recv_tq;	/* receive task queue */
+	work_t send_tq;	/* send task queue */
+	work_t recv_tq;	/* receive task queue */
 	spinlock_t lock;		/* lock for the card */
 } tpam_card;
 
--- linux/drivers/isdn/tpam/tpam_main.c.orig	Tue Oct  1 15:52:29 2002
+++ linux/drivers/isdn/tpam/tpam_main.c	Tue Oct  1 16:08:40 2002
@@ -176,10 +176,8 @@
 	card->loopmode = 0;
 	skb_queue_head_init(&card->sendq);
 	skb_queue_head_init(&card->recvq);
-	card->recv_tq.routine = (void *) (void *) tpam_recv_tq;
-	card->recv_tq.data = card;
-	card->send_tq.routine = (void *) (void *) tpam_send_tq;
-	card->send_tq.data = card;
+	INIT_WORK(&card->recv_tq, (void *) (void *) tpam_recv_tq, card);
+	INIT_WORK(&card->send_tq, (void *) (void *) tpam_send_tq, card);
 
 	/* add the board at the end of the list of boards */
 	card->next = NULL;
--- linux/drivers/isdn/tpam/tpam_queues.c.orig	Tue Oct  1 14:58:17 2002
+++ linux/drivers/isdn/tpam/tpam_queues.c	Tue Oct  1 15:15:11 2002
@@ -13,7 +13,7 @@
 
 #include <linux/pci.h>
 #include <linux/sched.h>
-#include <linux/tqueue.h>
+#include <linux/workqueue.h>
 #include <linux/interrupt.h>
 #include <asm/io.h>
 
@@ -36,8 +36,7 @@
 	skb_queue_tail(&card->sendq, skb);
 
 	/* queue the board's send task struct for immediate treatment */
-	queue_task(&card->send_tq, &tq_immediate);
-	mark_bh(IMMEDIATE_BH);
+	schedule_work(&card->send_tq);
 }
 
 /*
@@ -58,8 +57,7 @@
 		skb_queue_tail(&channel->sendq, skb);
 
 	/* queue the channel's send task struct for immediate treatment */
-	queue_task(&channel->card->send_tq, &tq_immediate);
-	mark_bh(IMMEDIATE_BH);
+	schedule_work(&channel->card->send_tq);
 }
 
 /*
@@ -169,8 +167,7 @@
 		else {
 			/* put the message in the receive queue */
 			skb_queue_tail(&card->recvq, skb);
-			queue_task(&card->recv_tq, &tq_immediate);
-			mark_bh(IMMEDIATE_BH);
+			schedule_work(&card->recv_tq);
 		}
 		return;
 	}
@@ -187,8 +184,7 @@
 		spin_unlock(&card->lock);
 
 		/* schedule the send queue for execution */
-		queue_task(&card->send_tq, &tq_immediate);
-		mark_bh(IMMEDIATE_BH);
+		schedule_work(&card->send_tq);
 		return;
 	}
 
--- linux/drivers/isdn/capi/kcapi.c.orig	Tue Oct  1 14:01:22 2002
+++ linux/drivers/isdn/capi/kcapi.c	Tue Oct  1 15:17:45 2002
@@ -20,7 +20,7 @@
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
 #include <linux/skbuff.h>
-#include <linux/tqueue.h>
+#include <linux/workqueue.h>
 #include <linux/capi.h>
 #include <linux/kernelcapi.h>
 #include <linux/init.h>
@@ -69,8 +69,8 @@
 static int ncards;
 static struct sk_buff_head recv_queue;
 
-static struct tq_struct tq_state_notify;
-static struct tq_struct tq_recv_notify;
+static work_t tq_state_notify;
+static work_t tq_recv_notify;
 
 /* -------- ref counting -------------------------------------- */
 
@@ -234,7 +234,7 @@
 	 * user process, not in bh.
 	 */
 	MOD_INC_USE_COUNT;
-	if (schedule_task(&tq_state_notify) == 0)
+	if (schedule_work(&tq_state_notify) == 0)
 		MOD_DEC_USE_COUNT;
 	return 0;
 }
@@ -359,8 +359,7 @@
 
 	}
 	skb_queue_tail(&recv_queue, skb);
-	queue_task(&tq_recv_notify, &tq_immediate);
-	mark_bh(IMMEDIATE_BH);
+	schedule_work(&tq_recv_notify);
 	return;
 
 error:
@@ -875,11 +874,8 @@
 
 	skb_queue_head_init(&recv_queue);
 
-	tq_state_notify.routine = notify_handler;
-	tq_state_notify.data = 0;
-
-	tq_recv_notify.routine = recv_handler;
-	tq_recv_notify.data = 0;
+	INIT_WORK(&tq_state_notify, notify_handler, NULL);
+	INIT_WORK(&tq_recv_notify, recv_handler, NULL);
 
         kcapi_proc_init();
 
--- linux/drivers/isdn/act2000/act2000.h.orig	Tue Oct  1 14:01:22 2002
+++ linux/drivers/isdn/act2000/act2000.h	Tue Oct  1 15:23:28 2002
@@ -62,7 +62,7 @@
 
 #include <linux/sched.h>
 #include <linux/string.h>
-#include <linux/tqueue.h>
+#include <linux/workqueue.h>
 #include <linux/interrupt.h>
 #include <linux/skbuff.h>
 #include <linux/errno.h>
@@ -162,9 +162,9 @@
 	__u16 need_b3ack;                /* Flag: Need ACK for current skb   */
 	struct sk_buff *sbuf;            /* skb which is currently sent      */
 	struct timer_list ptimer;        /* Poll timer                       */
-	struct tq_struct snd_tq;         /* Task struct for xmit bh          */
-	struct tq_struct rcv_tq;         /* Task struct for rcv bh           */
-	struct tq_struct poll_tq;        /* Task struct for polled rcv bh    */
+	work_t snd_tq;         /* Task struct for xmit bh          */
+	work_t rcv_tq;         /* Task struct for rcv bh           */
+	work_t poll_tq;        /* Task struct for polled rcv bh    */
 	msn_entry *msn_list;
 	unsigned short msgnum;           /* Message number fur sending       */
 	act2000_chan bch[ACT2000_BCH];   /* B-Channel status/control         */
@@ -179,20 +179,17 @@
 
 extern __inline__ void act2000_schedule_tx(act2000_card *card)
 {
-        queue_task(&card->snd_tq, &tq_immediate);
-        mark_bh(IMMEDIATE_BH);
+        schedule_work(&card->snd_tq);
 }
 
 extern __inline__ void act2000_schedule_rx(act2000_card *card)
 {
-        queue_task(&card->rcv_tq, &tq_immediate);
-        mark_bh(IMMEDIATE_BH);
+        schedule_work(&card->rcv_tq);
 }
 
 extern __inline__ void act2000_schedule_poll(act2000_card *card)
 {
-        queue_task(&card->poll_tq, &tq_immediate);
-        mark_bh(IMMEDIATE_BH);
+        schedule_work(&card->poll_tq);
 }
 
 extern char *act2000_find_eaz(act2000_card *, char);
--- linux/drivers/isdn/act2000/module.c.orig	Tue Oct  1 15:19:58 2002
+++ linux/drivers/isdn/act2000/module.c	Tue Oct  1 15:22:57 2002
@@ -616,12 +616,9 @@
 	skb_queue_head_init(&card->sndq);
 	skb_queue_head_init(&card->rcvq);
 	skb_queue_head_init(&card->ackq);
-	card->snd_tq.routine = (void *) (void *) act2000_transmit;
-	card->snd_tq.data = card;
-	card->rcv_tq.routine = (void *) (void *) actcapi_dispatch;
-	card->rcv_tq.data = card;
-	card->poll_tq.routine = (void *) (void *) act2000_receive;
-	card->poll_tq.data = card;
+	INIT_WORK(&card->snd_tq, (void *) (void *) act2000_transmit, card);
+	INIT_WORK(&card->rcv_tq, (void *) (void *) actcapi_dispatch, card);
+	INIT_WORK(&card->poll_tq, (void *) (void *) act2000_receive, card);
 	init_timer(&card->ptimer);
         card->interface.channels = ACT2000_BCH;
         card->interface.maxbufsize = 4000;
--- linux/drivers/acpi/osl.c.orig	Tue Oct  1 14:01:22 2002
+++ linux/drivers/acpi/osl.c	Tue Oct  1 15:24:31 2002
@@ -33,7 +33,7 @@
 #include <linux/interrupt.h>
 #include <linux/kmod.h>
 #include <linux/delay.h>
-#include <linux/tqueue.h>
+#include <linux/workqueue.h>
 #include <asm/io.h>
 #include "acpi.h"
 
@@ -586,8 +586,8 @@
 	 * Queue via DPC:
 	 * --------------
 	 * Note that we have to use two different processes for queuing DPCs:
-	 *	 Interrupt-Level: Use schedule_task; can't spawn a new thread.
-	 *	    Kernel-Level: Spawn a new kernel thread, as schedule_task has
+	 *	 Interrupt-Level: Use schedule_work; can't spawn a new thread.
+	 *	    Kernel-Level: Spawn a new kernel thread, as schedule_work has
 	 *			  its limitations (e.g. single-threaded model), and
 	 *			  all other task queues run at interrupt-level.
 	 */
@@ -605,9 +605,9 @@
 		 * We can save time and code by allocating the DPC and tq_structs
 		 * from the same memory.
 		 */
-		struct tq_struct *task;
+		work_t *task;
 
-		dpc = kmalloc(sizeof(ACPI_OS_DPC)+sizeof(struct tq_struct), GFP_ATOMIC);
+		dpc = kmalloc(sizeof(ACPI_OS_DPC)+sizeof(work_t), GFP_ATOMIC);
 		if (!dpc)
 			return_ACPI_STATUS (AE_NO_MEMORY);
 
@@ -615,10 +615,10 @@
 		dpc->context = context;
 
 		task = (void *)(dpc+1);
-		INIT_TQUEUE(task, acpi_os_schedule_exec, (void*)dpc);
+		INIT_WORK(task, acpi_os_schedule_exec, (void*)dpc);
 
-		if (schedule_task(task) < 0) {
-			ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Call to schedule_task() failed.\n"));
+		if (schedule_work(task) < 0) {
+			ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Call to schedule_work() failed.\n"));
 			kfree(dpc);
 			status = AE_ERROR;
 		}
--- linux/drivers/media/video/cpia_pp.c.orig	Tue Oct  1 14:01:22 2002
+++ linux/drivers/media/video/cpia_pp.c	Tue Oct  1 15:25:28 2002
@@ -32,7 +32,7 @@
 #include <linux/parport.h>
 #include <linux/interrupt.h>
 #include <linux/delay.h>
-#include <linux/tqueue.h>
+#include <linux/workqueue.h>
 #include <linux/smp_lock.h>
 
 #include <linux/kmod.h>
@@ -137,7 +137,7 @@
 struct pp_cam_entry {
 	struct pardevice *pdev;
 	struct parport *port;
-	struct tq_struct cb_task;
+	work_t cb_task;
 	int open_count;
 	wait_queue_head_t wq_stream;
 	/* image state flags */
@@ -518,8 +518,7 @@
 	int retval = 0;
 	
 	if(cam->port->irq != PARPORT_IRQ_NONE) {
-		cam->cb_task.routine = cb;
-		cam->cb_task.data = cbdata;
+		INIT_WORK(&cam->cb_task, cb, cbdata);
 	} else {
 		retval = -1;
 	}
--- linux/drivers/video/sa1100fb.h.orig	Tue Oct  1 14:01:22 2002
+++ linux/drivers/video/sa1100fb.h	Tue Oct  1 15:25:51 2002
@@ -101,7 +101,7 @@
 	volatile u_char		task_state;
 	struct semaphore	ctrlr_sem;
 	wait_queue_head_t	ctrlr_wait;
-	struct tq_struct	task;
+	work_t	task;
 
 #ifdef CONFIG_PM
 	struct pm_dev		*pm;
--- linux/drivers/video/sa1100fb.c.orig	Tue Oct  1 15:26:07 2002
+++ linux/drivers/video/sa1100fb.c	Tue Oct  1 15:26:58 2002
@@ -767,7 +767,7 @@
 static int sa1100fb_activate_var(struct fb_var_screeninfo *var, struct sa1100fb_info *);
 static void set_ctrlr_state(struct sa1100fb_info *fbi, u_int state);
 
-static inline void sa1100fb_schedule_task(struct sa1100fb_info *fbi, u_int state)
+static inline void sa1100fb_schedule_work(struct sa1100fb_info *fbi, u_int state)
 {
 	unsigned long flags;
 
@@ -787,7 +787,7 @@
 
 	if (state != (u_int)-1) {
 		fbi->task_state = state;
-		schedule_task(&fbi->task);
+		schedule_work(&fbi->task);
 	}
 	local_irq_restore(flags);
 }
@@ -1140,14 +1140,14 @@
 		    fbi->fb.fix.visual == FB_VISUAL_STATIC_PSEUDOCOLOR)
 			for (i = 0; i < fbi->palette_size; i++)
 				sa1100fb_setpalettereg(i, 0, 0, 0, 0, info);
-		sa1100fb_schedule_task(fbi, C_DISABLE);
+		sa1100fb_schedule_work(fbi, C_DISABLE);
 		break;
 
 	case VESA_NO_BLANKING:
 		if (fbi->fb.fix.visual == FB_VISUAL_PSEUDOCOLOR ||
 		    fbi->fb.fix.visual == FB_VISUAL_STATIC_PSEUDOCOLOR)
 			fb_set_cmap(&fbi->fb.cmap, 1, info);
-		sa1100fb_schedule_task(fbi, C_ENABLE);
+		sa1100fb_schedule_work(fbi, C_ENABLE);
 	}
 	return 0;
 }
@@ -1285,7 +1285,7 @@
 	if ((LCCR0 != fbi->reg_lccr0)       || (LCCR1 != fbi->reg_lccr1) ||
 	    (LCCR2 != fbi->reg_lccr2)       || (LCCR3 != fbi->reg_lccr3) ||
 	    (DBAR1 != fbi->dbar1) || (DBAR2 != fbi->dbar2))
-		sa1100fb_schedule_task(fbi, C_REENABLE);
+		sa1100fb_schedule_work(fbi, C_REENABLE);
 
 	return 0;
 }
@@ -1778,7 +1778,7 @@
 	fbi->fb.disp->inverse		= inf->cmap_inverse;
 
 	init_waitqueue_head(&fbi->ctrlr_wait);
-	INIT_TQUEUE(&fbi->task, sa1100fb_task, fbi);
+	INIT_WORK(&fbi->task, sa1100fb_task, fbi);
 	init_MUTEX(&fbi->ctrlr_sem);
 
 	return fbi;
--- linux/drivers/serial/8250.c.orig	Fri Sep 20 17:20:15 2002
+++ linux/drivers/serial/8250.c	Tue Oct  1 16:58:11 2002
@@ -735,7 +735,7 @@
 
 	do {
 		if (unlikely(tty->flip.count >= TTY_FLIPBUF_SIZE)) {
-			tty->flip.tqueue.routine((void *)tty);
+			tty->flip.work.func((void *)tty);
 			if (tty->flip.count >= TTY_FLIPBUF_SIZE)
 				return; // if TTY_DONT_FLIP is set
 		}
--- linux/drivers/serial/8250_cs.c.orig	Tue Oct  1 14:01:22 2002
+++ linux/drivers/serial/8250_cs.c	Tue Oct  1 15:27:39 2002
@@ -42,7 +42,7 @@
 #include <linux/tty.h>
 #include <linux/serial.h>
 #include <linux/major.h>
-#include <linux/tqueue.h>
+#include <linux/workqueue.h>
 #include <asm/io.h>
 #include <asm/system.h>
 
@@ -107,7 +107,7 @@
 	int			manfid;
 	dev_node_t		node[4];
 	int			line[4];
-	struct tq_struct	remove;
+	work_t	remove;
 } serial_info_t;
 
 static void serial_config(dev_link_t * link);
@@ -182,7 +182,7 @@
 	 */
 
 	if (link->state & DEV_CONFIG)
-		schedule_task(&info->remove);
+		schedule_work(&info->remove);
 }
 
 /*======================================================================
@@ -210,7 +210,7 @@
 	link = &info->link;
 	link->priv = info;
 
-	INIT_TQUEUE(&info->remove, do_serial_release, info);
+	INIT_WORK(&info->remove, do_serial_release, info);
 
 	link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
 	link->io.NumPorts1 = 8;
@@ -278,7 +278,7 @@
 	/*
 	 * Ensure any outstanding scheduled tasks are completed.
 	 */
-	flush_scheduled_tasks();
+	flush_scheduled_work();
 
 	/*
 	 * Ensure that the ports have been released.
--- linux/drivers/serial/amba.c.orig	Tue Oct  1 15:52:29 2002
+++ linux/drivers/serial/amba.c	Tue Oct  1 16:09:03 2002
@@ -152,7 +152,7 @@
 	status = UART_GET_FR(port);
 	while (UART_RX_DATA(status) && max_count--) {
 		if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
-			tty->flip.tqueue.routine((void *)tty);
+			tty->flip.work.func((void *)tty);
 			if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
 				printk(KERN_WARNING "TTY_DONT_FLIP set\n");
 				return;
--- linux/drivers/serial/sunsu.c.orig	Tue Oct  1 15:52:29 2002
+++ linux/drivers/serial/sunsu.c	Tue Oct  1 16:09:12 2002
@@ -323,7 +323,7 @@
 
 	do {
 		if (unlikely(tty->flip.count >= TTY_FLIPBUF_SIZE)) {
-			tty->flip.tqueue.routine((void *)tty);
+			tty->flip.work.func((void *)tty);
 			if (tty->flip.count >= TTY_FLIPBUF_SIZE)
 				return; // if TTY_DONT_FLIP is set
 		}
--- linux/drivers/serial/21285.c.orig	Tue Oct  1 15:52:29 2002
+++ linux/drivers/serial/21285.c	Tue Oct  1 16:09:21 2002
@@ -94,7 +94,7 @@
 	status = *CSR_UARTFLG;
 	while (!(status & 0x10) && max_count--) {
 		if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
-			tty->flip.tqueue.routine((void *)tty);
+			tty->flip.work.func((void *)tty);
 			if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
 				printk(KERN_WARNING "TTY_DONT_FLIP set\n");
 				return;
--- linux/drivers/serial/sunsab.c.orig	Tue Oct  1 15:52:29 2002
+++ linux/drivers/serial/sunsab.c	Tue Oct  1 16:09:32 2002
@@ -138,7 +138,7 @@
 		unsigned char ch = buf[i];
 
 		if (unlikely(tty->flip.count >= TTY_FLIPBUF_SIZE)) {
-			tty->flip.tqueue.routine((void *)tty);
+			tty->flip.work.func((void *)tty);
 			if (tty->flip.count >= TTY_FLIPBUF_SIZE)
 				return; // if TTY_DONT_FLIP is set
 		}
--- linux/drivers/serial/sunzilog.c.orig	Tue Oct  1 15:52:29 2002
+++ linux/drivers/serial/sunzilog.c	Tue Oct  1 16:09:40 2002
@@ -338,7 +338,7 @@
 		unsigned char ch, r1;
 
 		if (unlikely(tty->flip.count >= TTY_FLIPBUF_SIZE)) {
-			tty->flip.tqueue.routine((void *)tty);
+			tty->flip.work.func((void *)tty);
 			if (tty->flip.count >= TTY_FLIPBUF_SIZE)
 				return;
 		}
--- linux/drivers/char/ip2/i2ellis.h.orig	Tue Oct  1 14:01:22 2002
+++ linux/drivers/char/ip2/i2ellis.h	Tue Oct  1 15:28:30 2002
@@ -401,7 +401,7 @@
 	rwlock_t	write_fifo_spinlock;
 
 //	For queuing interupt bottom half handlers.	/\/\|=mhw=|\/\/
-	struct tq_struct	tqueue_interrupt;
+	work_t	tqueue_interrupt;
 
 	struct timer_list  SendPendingTimer;   // Used by iiSendPending
 	unsigned int	SendPendingRetry;
--- linux/drivers/char/ip2/i2lib.h.orig	Tue Oct  1 14:01:22 2002
+++ linux/drivers/char/ip2/i2lib.h	Tue Oct  1 15:35:18 2002
@@ -27,6 +27,7 @@
 #include "i2ellis.h"
 #include "i2pack.h"
 #include "i2cmd.h"
+#include <linux/workqueue.h>
 
 //------------------------------------------------------------------------------
 // i2ChanStr -- Channel Structure:
@@ -224,9 +225,9 @@
 	/*
 	 *	Task queues for processing input packets from the board.
 	 */
-	struct tq_struct	tqueue_input;
-	struct tq_struct	tqueue_status;
-	struct tq_struct	tqueue_hangup;
+	work_t	tqueue_input;
+	work_t	tqueue_status;
+	work_t	tqueue_hangup;
 
 	rwlock_t Ibuf_spinlock;
 	rwlock_t Obuf_spinlock;
--- linux/drivers/char/ip2/i2lib.c.orig	Tue Oct  1 15:29:50 2002
+++ linux/drivers/char/ip2/i2lib.c	Tue Oct  1 15:29:55 2002
@@ -1582,8 +1582,7 @@
 			WRITE_UNLOCK_IRQRESTORE(&pB->read_fifo_spinlock,bflags);
 
 #ifdef USE_IQ
-			queue_task(&pCh->tqueue_input, &tq_immediate);
-			mark_bh(IMMEDIATE_BH);
+			schedule_work(&pCh->tqueue_input);
 #else
 			do_input(pCh);
 #endif
@@ -1820,8 +1819,7 @@
 					}  /* End of switch on status type */
 					if (dss_change) {
 #ifdef USE_IQ
-						queue_task(&pCh->tqueue_status, &tq_immediate);
-						mark_bh(IMMEDIATE_BH);
+						schedule_work(&pCh->tqueue_status);
 #else
 						do_status(pCh);
 #endif
--- linux/drivers/char/drm/radeon_irq.c.orig	Tue Oct  1 08:54:36 2002
+++ linux/drivers/char/drm/radeon_irq.c	Tue Oct  1 08:54:49 2002
@@ -69,7 +69,7 @@
 
 	atomic_inc(&dev_priv->irq_received);
 #ifdef __linux__
-	schedule_task(&dev->tq);
+	schedule_work(&dev->work);
 #endif /* __linux__ */
 #ifdef __FreeBSD__
 	taskqueue_enqueue(taskqueue_swi, &dev->task);
--- linux/drivers/char/drm/drmP.h.orig	Tue Oct  1 08:54:19 2002
+++ linux/drivers/char/drm/drmP.h	Tue Oct  1 08:54:49 2002
@@ -66,7 +66,7 @@
 #include <linux/types.h>
 #include <linux/agp_backend.h>
 #endif
-#include <linux/tqueue.h>
+#include <linux/workqueue.h>
 #include <linux/poll.h>
 #include <asm/pgalloc.h>
 #include "drm.h"
@@ -575,7 +575,7 @@
 	int		  last_checked;	/* Last context checked for DMA	   */
 	int		  last_context;	/* Last current context		   */
 	unsigned long	  last_switch;	/* jiffies at last context switch  */
-	struct tq_struct  tq;
+	work_t		  work;
 	cycles_t	  ctx_start;
 	cycles_t	  lck_start;
 #if __HAVE_DMA_HISTOGRAM
--- linux/drivers/char/drm/drm_dma.h.orig	Fri Sep 20 17:20:31 2002
+++ linux/drivers/char/drm/drm_dma.h	Tue Oct  1 08:54:49 2002
@@ -532,10 +532,7 @@
 	dev->dma->this_buffer = NULL;
 
 #if __HAVE_DMA_IRQ_BH
-	INIT_LIST_HEAD( &dev->tq.list );
-	dev->tq.sync = 0;
-	dev->tq.routine = DRM(dma_immediate_bh);
-	dev->tq.data = dev;
+	INIT_WORK(&dev->work, DRM(dma_immediate_bh), dev);
 #endif
 
 				/* Before installing handler */
--- linux/drivers/char/drm/gamma_dma.c.orig	Tue Oct  1 15:53:24 2002
+++ linux/drivers/char/drm/gamma_dma.c	Tue Oct  1 16:09:50 2002
@@ -128,8 +128,7 @@
 		clear_bit(0, &dev->dma_flag);
 
 				/* Dispatch new buffer */
-		queue_task(&dev->tq, &tq_immediate);
-		mark_bh(IMMEDIATE_BH);
+		schedule_work(&dev->tq);
 	}
 }
 
--- linux/drivers/char/pcmcia/synclink_cs.c.orig	Tue Oct  1 14:01:22 2002
+++ linux/drivers/char/pcmcia/synclink_cs.c	Tue Oct  1 15:46:33 2002
@@ -68,7 +68,7 @@
 #include <asm/bitops.h>
 #include <asm/types.h>
 #include <linux/termios.h>
-#include <linux/tqueue.h>
+#include <linux/workqueue.h>
 
 #include <pcmcia/version.h>
 #include <pcmcia/cs_types.h>
@@ -195,7 +195,7 @@
 	unsigned char  pim_value;
 
 	spinlock_t lock;
-	struct tq_struct task;		/* task structure for scheduling bh */
+	work_t task;		/* task structure for scheduling bh */
 
 	u32 max_frame_size;
 
@@ -562,9 +562,7 @@
 
     memset(info, 0, sizeof(MGSLPC_INFO));
     info->magic = MGSLPC_MAGIC;
-    info->task.sync = 0;
-    info->task.routine = bh_handler;
-    info->task.data    = info;
+    INIT_WORK(&info->task, bh_handler, info);
     info->max_frame_size = 4096;
     info->close_delay = 5*HZ/10;
     info->closing_wait = 30*HZ;
@@ -1460,8 +1458,7 @@
 		if ( debug_level >= DEBUG_LEVEL_ISR )	
 			printk("%s(%d):%s queueing bh task.\n",
 				__FILE__,__LINE__,info->device_name);
-		queue_task(&info->task, &tq_immediate);
-		mark_bh(IMMEDIATE_BH);
+		schedule_work(&info->task);
 		info->bh_requested = 1;
 	}
 
--- linux/drivers/char/tty_io.c.orig	Tue Oct  1 08:54:36 2002
+++ linux/drivers/char/tty_io.c	Tue Oct  1 11:22:33 2002
@@ -538,7 +538,7 @@
 	
 	printk(KERN_DEBUG "%s hangup...\n", tty_name(tty, buf));
 #endif
-	schedule_task(&tty->tq_hangup);
+	schedule_work(&tty->hangup_work);
 }
 
 void tty_vhangup(struct tty_struct * tty)
@@ -1265,7 +1265,7 @@
 	/*
 	 * Make sure that the tty's task queue isn't activated. 
 	 */
-	flush_scheduled_tasks();
+	flush_scheduled_work();
 
 	/* 
 	 * The release_mem function takes care of the details of clearing
@@ -1874,8 +1874,8 @@
 }
 
 /*
- * The tq handling here is a little racy - tty->SAK_tq may already be queued.
- * Fortunately we don't need to worry, because if ->SAK_tq is already queued,
+ * The tq handling here is a little racy - tty->SAK_work may already be queued.
+ * Fortunately we don't need to worry, because if ->SAK_work is already queued,
  * the values which we write to it will be identical to the values which it
  * already has. --akpm
  */
@@ -1883,8 +1883,8 @@
 {
 	if (!tty)
 		return;
-	PREPARE_TQUEUE(&tty->SAK_tq, __do_SAK, tty);
-	schedule_task(&tty->SAK_tq);
+	PREPARE_WORK(&tty->SAK_work, __do_SAK, tty);
+	schedule_work(&tty->SAK_work);
 }
 
 /*
@@ -1900,7 +1900,10 @@
 	unsigned long flags;
 
 	if (test_bit(TTY_DONT_FLIP, &tty->flags)) {
-		schedule_task(&tty->flip.tqueue);
+		/*
+		 * Do it after the next timer tick:
+		 */
+		schedule_delayed_work(&tty->flip.work, 1);
 		return;
 	}
 	if (tty->flip.buf_num) {
@@ -1977,7 +1980,7 @@
 	if (tty->low_latency)
 		flush_to_ldisc((void *) tty);
 	else
-		schedule_task(&tty->flip.tqueue);
+		schedule_delayed_work(&tty->flip.work, 1);
 }
 
 /*
@@ -1991,18 +1994,16 @@
 	tty->pgrp = -1;
 	tty->flip.char_buf_ptr = tty->flip.char_buf;
 	tty->flip.flag_buf_ptr = tty->flip.flag_buf;
-	tty->flip.tqueue.routine = flush_to_ldisc;
-	tty->flip.tqueue.data = tty;
+	INIT_WORK(&tty->flip.work, flush_to_ldisc, tty);
 	init_MUTEX(&tty->flip.pty_sem);
 	init_waitqueue_head(&tty->write_wait);
 	init_waitqueue_head(&tty->read_wait);
-	tty->tq_hangup.routine = do_tty_hangup;
-	tty->tq_hangup.data = tty;
+	INIT_WORK(&tty->hangup_work, do_tty_hangup, tty);
 	sema_init(&tty->atomic_read, 1);
 	sema_init(&tty->atomic_write, 1);
 	spin_lock_init(&tty->read_lock);
 	INIT_LIST_HEAD(&tty->tty_files);
-	INIT_TQUEUE(&tty->SAK_tq, 0, 0);
+	INIT_WORK(&tty->SAK_work, NULL, NULL);
 }
 
 /*
--- linux/drivers/char/vt.c.orig	Fri Sep 20 17:20:34 2002
+++ linux/drivers/char/vt.c	Tue Oct  1 16:56:05 2002
@@ -97,7 +97,7 @@
 #include <linux/interrupt.h>
 #include <linux/config.h>
 #include <linux/version.h>
-#include <linux/tqueue.h>
+#include <linux/workqueue.h>
 #include <linux/bootmem.h>
 #include <linux/pm.h>
 
@@ -161,9 +161,7 @@
 static int blankinterval = 10*60*HZ;
 static int vesa_off_interval;
 
-static struct tq_struct console_callback_tq = {
-	routine: console_callback,
-};
+static DECLARE_WORK(console_work, console_callback, NULL);
 
 /*
  * fg_console is the current virtual console,
@@ -241,7 +239,7 @@
 
 void schedule_console_callback(void)
 {
-	schedule_task(&console_callback_tq);
+	schedule_work(&console_work);
 }
 
 static void scrup(int currcons, unsigned int t, unsigned int b, int nr)
--- linux/drivers/char/random.c.orig	Tue Oct  1 08:54:36 2002
+++ linux/drivers/char/random.c	Tue Oct  1 11:11:11 2002
@@ -252,7 +252,7 @@
 #include <linux/poll.h>
 #include <linux/init.h>
 #include <linux/fs.h>
-#include <linux/tqueue.h>
+#include <linux/workqueue.h>
 
 #include <asm/processor.h>
 #include <asm/uaccess.h>
@@ -624,8 +624,8 @@
 static int	*batch_entropy_credit;
 static int	batch_max;
 static int	batch_head, batch_tail;
-static struct tq_struct	batch_tqueue;
 static void batch_entropy_process(void *private_);
+static DECLARE_WORK(batch_work, batch_entropy_process, NULL);
 
 /* note: the size must be a power of 2 */
 static int __init batch_entropy_init(int size, struct entropy_store *r)
@@ -640,8 +640,7 @@
 	}
 	batch_head = batch_tail = 0;
 	batch_max = size;
-	batch_tqueue.routine = batch_entropy_process;
-	batch_tqueue.data = r;
+	batch_work.data = r;
 	return 0;
 }
 
@@ -664,8 +663,10 @@
 
 	new = (batch_head+1) & (batch_max-1);
 	if (new != batch_tail) {
-		// FIXME: is this correct?
-		schedule_task(&batch_tqueue);
+		/*
+		 * Schedule it for the next timer tick:
+		 */
+		schedule_delayed_work(&batch_work, 1);
 		batch_head = new;
 	} else {
 		DEBUG_ENT("batch entropy buffer full\n");
@@ -1749,7 +1750,7 @@
 
 	sysctl_init_random(new_store);
 	old_store = random_state;
-	random_state = batch_tqueue.data = new_store;
+	random_state = batch_work.data = new_store;
 	free_entropy_store(old_store);
 	return 0;
 }
--- linux/drivers/char/rocket_int.h.orig	Tue Oct  1 14:01:22 2002
+++ linux/drivers/char/rocket_int.h	Tue Oct  1 15:37:06 2002
@@ -1143,7 +1143,6 @@
 	int			cps;
 	struct termios		normal_termios;
 	struct termios		callout_termios;
-	struct tq_struct	tqueue;
 	wait_queue_head_t	open_wait;
 	wait_queue_head_t	close_wait;
 };
--- linux/drivers/char/sx.h.orig	Tue Oct  1 14:01:22 2002
+++ linux/drivers/char/sx.h	Tue Oct  1 15:38:21 2002
@@ -22,10 +22,6 @@
 
 struct sx_port {
   struct gs_port          gs;
-  /*
-  struct tq_struct        tqueue;
-  struct tq_struct        tqueue_hangup;
-  */
   struct wait_queue       *shutdown_wait;
   int                     ch_base;
   int                     c_dcd;
--- linux/drivers/char/synclinkmp.c.orig	Tue Oct  1 14:01:22 2002
+++ linux/drivers/char/synclinkmp.c	Tue Oct  1 15:39:15 2002
@@ -67,7 +67,7 @@
 #include <asm/bitops.h>
 #include <asm/types.h>
 #include <linux/termios.h>
-#include <linux/tqueue.h>
+#include <linux/workqueue.h>
 
 #ifdef CONFIG_SYNCLINK_SYNCPPP_MODULE
 #define CONFIG_SYNCLINK_SYNCPPP 1
@@ -194,7 +194,7 @@
 	struct timer_list	status_timer;	/* input signal status check timer */
 
 	spinlock_t lock;		/* spinlock for synchronizing with ISR */
-	struct tq_struct task;	 		/* task structure for scheduling bh */
+	work_t task;	 		/* task structure for scheduling bh */
 
 	u32 max_frame_size;			/* as set by device config */
 
@@ -2572,8 +2572,7 @@
 			if ( debug_level >= DEBUG_LEVEL_ISR )
 				printk("%s(%d):%s queueing bh task.\n",
 					__FILE__,__LINE__,port->device_name);
-			queue_task(&port->task, &tq_immediate);
-			mark_bh(IMMEDIATE_BH);
+			schedule_work(&port->task);
 			port->bh_requested = 1;
 		}
 	}
@@ -3736,9 +3735,7 @@
 	} else {
 		memset(info, 0, sizeof(SLMP_INFO));
 		info->magic = MGSL_MAGIC;
-		info->task.sync = 0;
-		info->task.routine = bh_handler;
-		info->task.data    = info;
+		INIT_WORK(&info->task, bh_handler, info);
 		info->max_frame_size = 4096;
 		info->close_delay = 5*HZ/10;
 		info->closing_wait = 30*HZ;
--- linux/drivers/char/cyclades.c.orig	Tue Oct  1 14:01:22 2002
+++ linux/drivers/char/cyclades.c	Tue Oct  1 15:44:01 2002
@@ -712,8 +712,6 @@
 
 #define	JIFFIES_DIFF(n, j)	((j) - (n))
 
-static DECLARE_TASK_QUEUE(tq_cyclades);
-
 static struct tty_driver cy_serial_driver, cy_callout_driver;
 static int serial_refcount;
 
@@ -934,8 +932,7 @@
 cy_sched_event(struct cyclades_port *info, int event)
 {
     info->event |= 1 << event; /* remember what kind of event and who */
-    queue_task(&info->tqueue, &tq_cyclades); /* it belongs to */
-    mark_bh(CYCLADES_BH);                       /* then trigger event */
+    schedule_work(&info->tqueue);
 } /* cy_sched_event */
 
 
@@ -951,9 +948,7 @@
  * This is done through one level of indirection--the task queue.
  * When a hardware interrupt service routine wants service by the
  * driver's bottom half, it enqueues the appropriate tq_struct (one
- * per port) to the tq_cyclades work queue and sets a request flag
- * via mark_bh for processing that queue.  When the time is right,
- * do_cyclades_bh is called (because of the mark_bh) and it requests
+ * per port) to the keventd work queue and sets a request flag
  * that the work queue be processed.
  *
  * Although this may seem unwieldy, it gives the system a way to
@@ -962,12 +957,6 @@
  * had to poll every port to see if that port needed servicing.
  */
 static void
-do_cyclades_bh(void)
-{
-    run_task_queue(&tq_cyclades);
-} /* do_cyclades_bh */
-
-static void
 do_softint(void *private_)
 {
   struct cyclades_port *info = (struct cyclades_port *) private_;
@@ -1291,7 +1280,7 @@
 #endif
                             }
                         }
-                        queue_task(&tty->flip.tqueue, &tq_timer);
+                        schedule_delayed_work(&tty->flip.work, 1);
                     }
                     /* end of service */
                     cy_writeb((u_long)base_addr+(CyRIR<<index), (save_xir & 0x3f));
@@ -1673,7 +1662,7 @@
 	    }
 #endif
 	    info->idle_stats.recv_idle = jiffies;
-	    queue_task(&tty->flip.tqueue, &tq_timer);
+	    schedule_delayed_work(&tty->flip.work, 1);
 	}
 	/* Update rx_get */
 	cy_writel(&buf_ctrl->rx_get, new_rx_get);
@@ -1888,7 +1877,7 @@
 	if(delta_count)
 	    cy_sched_event(info, Cy_EVENT_DELTA_WAKEUP);
 	if(special_count)
-	    queue_task(&tty->flip.tqueue, &tq_timer);
+	    schedule_delayed_work(&tty->flip.work, 1);
     }
 }
 
@@ -5513,8 +5502,6 @@
   unsigned short chip_number;
   int nports;
 
-    init_bh(CYCLADES_BH, do_cyclades_bh);
-
     show_version();
 
     /* Initialize the tty_driver structure */
@@ -5661,8 +5648,7 @@
                     info->blocked_open = 0;
                     info->default_threshold = 0;
                     info->default_timeout = 0;
-                    info->tqueue.routine = do_softint;
-                    info->tqueue.data = info;
+		    INIT_WORK(&info->tqueue, do_softint, info);
                     info->callout_termios =
 		                cy_callout_driver.init_termios;
                     info->normal_termios =
@@ -5740,8 +5726,7 @@
                     info->blocked_open = 0;
                     info->default_threshold = 0;
                     info->default_timeout = 0;
-                    info->tqueue.routine = do_softint;
-                    info->tqueue.data = info;
+		    INIT_WORK(&info->tqueue, do_softint, info);
                     info->callout_termios =
 		               cy_callout_driver.init_termios;
                     info->normal_termios =
@@ -5791,7 +5776,6 @@
 #endif /* CONFIG_CYZ_INTR */
 
     save_flags(flags); cli();
-    remove_bh(CYCLADES_BH);
 
     if ((e1 = tty_unregister_driver(&cy_serial_driver)))
             printk("cyc: failed to unregister Cyclades serial driver(%d)\n",
--- linux/drivers/char/synclink.c.orig	Tue Oct  1 14:01:22 2002
+++ linux/drivers/char/synclink.c	Tue Oct  1 15:48:26 2002
@@ -100,7 +100,7 @@
 #include <asm/bitops.h>
 #include <asm/types.h>
 #include <linux/termios.h>
-#include <linux/tqueue.h>
+#include <linux/workqueue.h>
 
 #ifdef CONFIG_SYNCLINK_SYNCPPP_MODULE
 #define CONFIG_SYNCLINK_SYNCPPP 1
@@ -223,7 +223,7 @@
 	struct mgsl_struct	*next_device;	/* device list link */
 	
 	spinlock_t irq_spinlock;		/* spinlock for synchronizing with ISR */
-	struct tq_struct task;		/* task structure for scheduling bh */
+	work_t task;		/* task structure for scheduling bh */
 
 	u32 EventMask;			/* event trigger mask */
 	u32 RecordedEvents;		/* pending events */
@@ -1757,8 +1757,7 @@
 		if ( debug_level >= DEBUG_LEVEL_ISR )	
 			printk("%s(%d):%s queueing bh task.\n",
 				__FILE__,__LINE__,info->device_name);
-		queue_task(&info->task, &tq_immediate);
-		mark_bh(IMMEDIATE_BH);
+		schedule_work(&info->task);
 		info->bh_requested = 1;
 	}
 
@@ -4543,9 +4542,7 @@
 	} else {
 		memset(info, 0, sizeof(struct mgsl_struct));
 		info->magic = MGSL_MAGIC;
-		info->task.sync = 0;
-		info->task.routine = mgsl_bh_handler;
-		info->task.data    = info;
+		INIT_WORK(&info->task, mgsl_bh_handler, info);
 		info->max_frame_size = 4096;
 		info->close_delay = 5*HZ/10;
 		info->closing_wait = 30*HZ;
--- linux/drivers/char/epca.h.orig	Tue Oct  1 14:01:22 2002
+++ linux/drivers/char/epca.h	Tue Oct  1 15:49:32 2002
@@ -142,7 +142,7 @@
 	struct termios              callout_termios;
 	wait_queue_head_t           open_wait;
 	wait_queue_head_t           close_wait;
-	struct tq_struct            tqueue;
+	work_t            tqueue;
 	volatile struct global_data *mailbox;
 };
 
--- linux/drivers/char/sh-sci.h.orig	Tue Oct  1 14:01:22 2002
+++ linux/drivers/char/sh-sci.h	Tue Oct  1 16:11:30 2002
@@ -200,7 +200,7 @@
 	void (*init_pins)(struct sci_port* port, unsigned int cflag);
 	unsigned int old_cflag;
 	struct async_icount icount;
-	struct tq_struct tqueue;
+	work_t tqueue;
 	unsigned long event;
 };
 
--- linux/drivers/char/mxser.c.orig	Tue Oct  1 14:01:22 2002
+++ linux/drivers/char/mxser.c	Tue Oct  1 16:12:01 2002
@@ -262,7 +262,7 @@
 	int xmit_head;
 	int xmit_tail;
 	int xmit_cnt;
-	struct tq_struct tqueue;
+	work_t tqueue;
 	struct termios normal_termios;
 	struct termios callout_termios;
 	wait_queue_head_t open_wait;
@@ -449,8 +449,7 @@
 		info->custom_divisor = hwconf->baud_base[i] * 16;
 		info->close_delay = 5 * HZ / 10;
 		info->closing_wait = 30 * HZ;
-		info->tqueue.routine = mxser_do_softint;
-		info->tqueue.data = info;
+		INIT_WORK(&info->tqueue, mxser_do_softint, info);
 		info->callout_termios = mxvar_cdriver.init_termios;
 		info->normal_termios = mxvar_sdriver.init_termios;
 		init_waitqueue_head(&info->open_wait);
@@ -1480,7 +1479,7 @@
 		*status = inb(info->base + UART_LSR) & info->read_status_mask;
 	} while (*status & UART_LSR_DR);
 	mxvar_log.rxcnt[info->port] += cnt;
-	queue_task(&tty->flip.tqueue, &tq_timer);
+	schedule_delayed_work(&tty->flip.work, 1);
 
 }
 
@@ -1513,7 +1512,7 @@
 	if (info->xmit_cnt < WAKEUP_CHARS) {
 		set_bit(MXSER_EVENT_TXLOW, &info->event);
 		MOD_INC_USE_COUNT;
-		if (schedule_task(&info->tqueue) == 0)
+		if (schedule_work(&info->tqueue) == 0)
 		    MOD_DEC_USE_COUNT;
 	}
 	if (info->xmit_cnt <= 0) {
@@ -1544,7 +1543,7 @@
 			   (info->flags & ASYNC_CALLOUT_NOHUP)))
 			set_bit(MXSER_EVENT_HANGUP, &info->event);
 		MOD_INC_USE_COUNT;
-		if (schedule_task(&info->tqueue) == 0)
+		if (schedule_work(&info->tqueue) == 0)
 		    MOD_DEC_USE_COUNT;
 	}
 	if (info->flags & ASYNC_CTS_FLOW) {
@@ -1556,7 +1555,7 @@
 
 				set_bit(MXSER_EVENT_TXLOW, &info->event);
 				MOD_INC_USE_COUNT;
-				if (schedule_task(&info->tqueue) == 0)
+				if (schedule_work(&info->tqueue) == 0)
 					MOD_DEC_USE_COUNT;
 			}
 		} else {
--- linux/drivers/char/genrtc.c.orig	Tue Oct  1 14:01:22 2002
+++ linux/drivers/char/genrtc.c	Tue Oct  1 16:12:40 2002
@@ -48,7 +48,7 @@
 #include <linux/init.h>
 #include <linux/poll.h>
 #include <linux/proc_fs.h>
-#include <linux/tqueue.h>
+#include <linux/workqueue.h>
 
 #include <asm/uaccess.h>
 #include <asm/system.h>
@@ -82,7 +82,7 @@
 static int irq_active;
 
 #ifdef CONFIG_GEN_RTC_X
-struct tq_struct genrtc_task;
+work_t genrtc_task;
 static struct timer_list timer_task;
 
 static unsigned int oldsecs;
@@ -91,7 +91,7 @@
 
 void gen_rtc_timer(unsigned long data);
 
-static volatile int stask_active;              /* schedule_task */
+static volatile int stask_active;              /* schedule_work */
 static volatile int ttask_active;              /* timer_task */
 static int stop_rtc_timers;                    /* don't requeue tasks */
 static spinlock_t gen_rtc_lock = SPIN_LOCK_UNLOCKED;
@@ -120,7 +120,7 @@
 		add_timer(&timer_task);
 
 		gen_rtc_interrupt(0);
-	} else if (schedule_task(&genrtc_task) == 0)
+	} else if (schedule_work(&genrtc_task) == 0)
 		stask_active = 0;
 }
 
@@ -134,7 +134,7 @@
 		       jiffies-tt_exp);
 	ttask_active=0;
 	stask_active=1;
-	if ((schedule_task(&genrtc_task) == 0))
+	if ((schedule_work(&genrtc_task) == 0))
 		stask_active = 0;
 }
 
@@ -253,12 +253,12 @@
 		irq_active = 1;
 		stop_rtc_timers = 0;
 		lostint = 0;
-		genrtc_task.routine = genrtc_troutine;
+		INIT_WORK(&genrtc_task, genrtc_troutine, NULL);
 		oldsecs = get_rtc_ss();
 		init_timer(&timer_task);
 
 		stask_active = 1;
-		if (schedule_task(&genrtc_task) == 0){
+		if (schedule_work(&genrtc_task) == 0){
 			stask_active = 0;
 		}
 	}
--- linux/drivers/char/moxa.c.orig	Tue Oct  1 14:01:22 2002
+++ linux/drivers/char/moxa.c	Tue Oct  1 16:13:14 2002
@@ -159,7 +159,7 @@
 	struct termios callout_termios;
 	wait_queue_head_t open_wait;
 	wait_queue_head_t close_wait;
-	struct tq_struct tqueue;
+	work_t tqueue;
 };
 
 struct mxser_mstatus {
@@ -384,8 +384,7 @@
 	for (i = 0, ch = moxaChannels; i < MAX_PORTS; i++, ch++) {
 		ch->type = PORT_16550A;
 		ch->port = i;
-		ch->tqueue.routine = do_moxa_softint;
-		ch->tqueue.data = ch;
+		INIT_WORK(&ch->tqueue, do_moxa_softint, ch);
 		ch->tty = 0;
 		ch->close_delay = 5 * HZ / 10;
 		ch->closing_wait = 30 * HZ;
@@ -1026,7 +1025,7 @@
 					else {
 						set_bit(MOXA_EVENT_HANGUP, &ch->event);
 						MOD_DEC_USE_COUNT;
-						if (schedule_task(&ch->tqueue) == 0)
+						if (schedule_work(&ch->tqueue) == 0)
 							MOD_INC_USE_COUNT;
 					}
 				}
--- linux/drivers/char/sx.c.orig	Tue Oct  1 15:38:10 2002
+++ linux/drivers/char/sx.c	Tue Oct  1 15:38:14 2002
@@ -220,7 +220,6 @@
 #include <linux/fcntl.h>
 #include <linux/major.h>
 #include <linux/delay.h>
-#include <linux/tqueue.h>
 #include <linux/version.h>
 #include <linux/pci.h>
 #include <linux/slab.h>
--- linux/drivers/char/epca.c.orig	Tue Oct  1 15:49:43 2002
+++ linux/drivers/char/epca.c	Tue Oct  1 15:50:10 2002
@@ -488,7 +488,7 @@
 
 	ch->event |= 1 << event;
 	MOD_INC_USE_COUNT;
-	if (schedule_task(&ch->tqueue) == 0)
+	if (schedule_work(&ch->tqueue) == 0)
 		MOD_DEC_USE_COUNT;
 
 
@@ -2039,8 +2039,7 @@
 
 		ch->brdchan        = bc;
 		ch->mailbox        = gd; 
-		ch->tqueue.routine = do_softint;
-		ch->tqueue.data    = ch;
+		INIT_WORK(&ch->tqueue, do_softint, ch);
 		ch->board          = &boards[crd];
 
 		switch (bd->type)
--- linux/drivers/char/sh-sci.c.orig	Tue Oct  1 15:50:49 2002
+++ linux/drivers/char/sh-sci.c	Tue Oct  1 16:10:55 2002
@@ -431,8 +431,7 @@
 static inline void sci_sched_event(struct sci_port *port, int event)
 {
 	port->event |= 1 << event;
-	queue_task(&port->tqueue, &tq_immediate);
-	mark_bh(IMMEDIATE_BH);
+	schedule_work(&port->tqueue);
 }
 
 static void sci_transmit_chars(struct sci_port *port)
@@ -825,8 +824,7 @@
 	port->gs.count++;
 
 	port->event = 0;
-	port->tqueue.routine = do_softint;
-	port->tqueue.data = port;
+	INIT_WORK(&port->tqueue, do_softint, port);
 
 	/*
 	 * Start up serial port
--- linux/drivers/char/ip2main.c.orig	Tue Oct  1 15:53:24 2002
+++ linux/drivers/char/ip2main.c	Tue Oct  1 16:14:05 2002
@@ -1097,8 +1097,7 @@
 		pCh++;
 	}
 ex_exit:
-	pB->tqueue_interrupt.routine = (void(*)(void*)) ip2_interrupt_bh;
-	pB->tqueue_interrupt.data = pB;
+	INIT_WORK(&pB->tqueue_interrupt, (void(*)(void*)) ip2_interrupt_bh, pB);
 	return;
 
 err_release_region:
@@ -1376,10 +1375,9 @@
 			iiDisableMailIrq(pB);
 
 //			Park the board on the immediate queue for processing.
-			queue_task(&pB->tqueue_interrupt, &tq_immediate);
+			schedule_work(&pB->tqueue_interrupt);
 
 //			Make sure the immediate queue is flagged to fire.
-			mark_bh(IMMEDIATE_BH);
 		    }
 #else
 //		We are using immediate servicing here.  This sucks and can
--- linux/drivers/acorn/block/fd1772.c.orig	Tue Oct  1 14:01:22 2002
+++ linux/drivers/acorn/block/fd1772.c	Tue Oct  1 16:15:03 2002
@@ -131,7 +131,7 @@
 #include <linux/kernel.h>
 #include <linux/interrupt.h>
 #include <linux/timer.h>
-#include <linux/tqueue.h>
+#include <linux/workqueue.h>
 #include <linux/fd.h>
 #include <linux/fd1772.h>
 #include <linux/errno.h>
@@ -324,8 +324,7 @@
 
 static void fd1772_checkint(void);
 
-struct tq_struct fd1772_tq = 
-{ 0,0, (void *)fd1772_checkint, 0 };
+DECLARE_WORK(fd1772_tq, (void *)fd1772_checkint, NULL);
 /*
  * The driver is trying to determine the correct media format
  * while Probing is set. fd_rwsec_done() clears it after a
@@ -1288,8 +1287,7 @@
 		floppy_irqconsequencehandler();
 	if ((MultReadInProgress) && (fdc1772_bytestogo==0)) fd_readtrack_check(0);
 	if (fdc_busy) {
-		queue_task(&fd1772_tq,&tq_immediate);
-		mark_bh(IMMEDIATE_BH);
+		schedule_work(&fd1772_tq);
 	}
 }
 
@@ -1311,8 +1309,7 @@
 
 	redo_fd_request();
 
-	queue_task(&fd1772_tq,&tq_immediate);
-	mark_bh(IMMEDIATE_BH);
+	schedule_work(&fd1772_tq);
 }
 
 
--- linux/drivers/s390/char/con3215.c.orig	Tue Oct  1 14:01:22 2002
+++ linux/drivers/s390/char/con3215.c	Tue Oct  1 16:16:54 2002
@@ -89,7 +89,7 @@
         int written;                  /* number of bytes in write requests */
 	devstat_t devstat;	      /* device status structure for do_IO */
 	struct tty_struct *tty;	      /* pointer to tty structure if present */
-	struct tq_struct tqueue;      /* task queue to bottom half */
+	work_t tqueue;      /* task queue to bottom half */
 	raw3215_req *queued_read;     /* pointer to queued read requests */
 	raw3215_req *queued_write;    /* pointer to queued write requests */
 	wait_queue_head_t empty_wait; /* wait queue for flushing */
@@ -379,10 +379,8 @@
         raw->flags |= RAW3215_BH_PENDING;
 	INIT_LIST_HEAD(&raw->tqueue.list);
 	raw->tqueue.sync = 0;
-        raw->tqueue.routine = raw3215_softint;
-        raw->tqueue.data = raw;
-        queue_task(&raw->tqueue, &tq_immediate);
-        mark_bh(IMMEDIATE_BH);
+	INIT_WORK(&raw->tqueue, raw3215_softint, raw);
+        schedule_work(&raw->tqueue);
 }
 
 /*
@@ -867,8 +865,7 @@
 			kfree(raw);
 			return -ENOMEM;
 		}
-		raw->tqueue.routine = raw3215_softint;
-		raw->tqueue.data = raw;
+		INIT_WORK(&raw->tqueue, raw3215_softint, raw);
                 init_waitqueue_head(&raw->empty_wait);
 		raw3215[line] = raw;
 	}
@@ -1097,8 +1094,7 @@
 	/* Find the first console */
 	raw->irq = raw3215_find_dev(0);
 	raw->flags |= RAW3215_FIXED;
-	raw->tqueue.routine = raw3215_softint;
-	raw->tqueue.data = raw;
+	INIT_WORK(&raw->tqueue, raw3215_softint, raw);
         init_waitqueue_head(&raw->empty_wait);
 
 	/* Request the console irq */
--- linux/drivers/s390/char/tubfs.c.orig	Tue Oct  1 15:52:29 2002
+++ linux/drivers/s390/char/tubfs.c	Tue Oct  1 16:17:28 2002
@@ -265,10 +265,8 @@
 	if (tubp->flags & TUB_BHPENDING)
 		return;
 	tubp->flags |= TUB_BHPENDING;
-	tubp->tqueue.routine = fs3270_bh;
-	tubp->tqueue.data = tubp;
-	queue_task(&tubp->tqueue, &tq_immediate);
-	mark_bh(IMMEDIATE_BH);
+	INIT_WORK(&tubp->tqueue, fs3270_bh, tubp);
+	schedule_work(&tubp->tqueue);
 }
 
 /*
--- linux/drivers/scsi/ppa.c.orig	Tue Oct  1 14:01:22 2002
+++ linux/drivers/scsi/ppa.c	Tue Oct  1 16:18:07 2002
@@ -29,7 +29,7 @@
     int mode;			/* Transfer mode                */
     int host;			/* Host number (for proc)       */
     Scsi_Cmnd *cur_cmd;		/* Current queued command       */
-    struct tq_struct ppa_tq;	/* Polling interrupt stuff       */
+    work_t ppa_tq;	/* Polling interrupt stuff       */
     unsigned long jstart;	/* Jiffies at start             */
     unsigned long recon_tmo;    /* How many usecs to wait for reconnection (6th bit) */
     unsigned int failed:1;	/* Failure flag                 */
@@ -801,7 +801,7 @@
     if (ppa_engine(tmp, cmd)) {
 	tmp->ppa_tq.data = (void *) tmp;
 	tmp->ppa_tq.sync = 0;
-	queue_task(&tmp->ppa_tq, &tq_timer);
+	schedule_delayed_work(&tmp->ppa_tq, 1);
 	return;
     }
     /* Command must of completed hence it is safe to let go... */
@@ -986,8 +986,7 @@
 
     ppa_hosts[host_no].ppa_tq.data = ppa_hosts + host_no;
     ppa_hosts[host_no].ppa_tq.sync = 0;
-    queue_task(&ppa_hosts[host_no].ppa_tq, &tq_immediate);
-    mark_bh(IMMEDIATE_BH);
+    schedule_work(&ppa_hosts[host_no].ppa_tq);
 
     return 0;
 }
--- linux/drivers/scsi/oktagon_esp.c.orig	Tue Oct  1 14:01:22 2002
+++ linux/drivers/scsi/oktagon_esp.c	Tue Oct  1 16:18:48 2002
@@ -40,7 +40,7 @@
 #include <asm/amigahw.h>
 
 #ifdef USE_BOTTOM_HALF
-#include <linux/tqueue.h>
+#include <linux/workqueue.h>
 #include <linux/interrupt.h>
 #endif
 
@@ -77,9 +77,7 @@
 long oktag_to_io(long *paddr, long *addr, long len);
 long oktag_from_io(long *addr, long *paddr, long len);
 
-static struct tq_struct tq_fake_dma = {
-    routine:	dma_commit,
-};
+static DECLARE_WORK(tq_fake_dma, dma_commit, NULL);
 
 #define DMA_MAXTRANSFER 0x8000
 
@@ -515,9 +513,7 @@
 #ifdef USE_BOTTOM_HALF
 	if(dma_on)
 	 {
-	  tq_fake_dma.sync = 0;
-	  queue_task(&tq_fake_dma,&tq_immediate);
-	  mark_bh(IMMEDIATE_BH);
+	  schedule_work(&tq_fake_dma);
 	 }
 #else
 	while(len && !dma_irq_p(esp))
--- linux/drivers/scsi/aha152x.c.orig	Tue Oct  1 14:01:22 2002
+++ linux/drivers/scsi/aha152x.c	Tue Oct  1 16:19:12 2002
@@ -1893,7 +1893,7 @@
 		printk(KERN_ERR "aha152x: done() called outside of command\n");
 }
 
-static struct tq_struct aha152x_tq;
+static work_t aha152x_tq;
 
 /*
  * Run service completions on the card with interrupts enabled.
@@ -1940,9 +1940,8 @@
 	
 	/* Poke the BH handler */
 	HOSTDATA(shpnt)->service++;
-	aha152x_tq.routine = (void *) run;
-	queue_task(&aha152x_tq, &tq_immediate);
-	mark_bh(IMMEDIATE_BH);
+	INIT_WORK(&aha152x_tq, (void *) run, NULL);
+	schedule_work(&aha152x_tq);
 }
 
 /*
--- linux/drivers/scsi/sun3_NCR5380.c.orig	Tue Oct  1 14:01:22 2002
+++ linux/drivers/scsi/sun3_NCR5380.c	Tue Oct  1 16:19:38 2002
@@ -642,16 +642,11 @@
  * interrupt or bottom half.
  */
 
-#include <linux/tqueue.h>
+#include <linux/workqueue.h>
 #include <linux/interrupt.h>
 
 static volatile int main_running = 0;
-static struct tq_struct NCR5380_tqueue = {
-//    NULL,		/* next */
-    sync: 0,			/* sync */
-    routine: (void (*)(void*))NCR5380_main,  /* routine, must have (void *) arg... */
-    data: NULL		/* data */
-};
+static DECLARE_WORK(NCR5380_tqueue, (void (*)(void*))NCR5380_main, NULL);
 
 static __inline__ void queue_main(void)
 {
@@ -660,8 +655,7 @@
 	   queue it on the 'immediate' task queue, to be processed
 	   immediately after the current interrupt processing has
 	   finished. */
-	queue_task(&NCR5380_tqueue, &tq_immediate);
-	mark_bh(IMMEDIATE_BH);
+	schedule_work(&NCR5380_tqueue);
     }
     /* else: nothing to do: the running NCR5380_main() will pick up
        any newly queued command. */
--- linux/drivers/scsi/atari_NCR5380.c.orig	Tue Oct  1 14:01:22 2002
+++ linux/drivers/scsi/atari_NCR5380.c	Tue Oct  1 16:20:11 2002
@@ -640,13 +640,11 @@
  * interrupt or bottom half.
  */
 
-#include <linux/tqueue.h>
+#include <linux/workqueue.h>
 #include <linux/interrupt.h>
 
 static volatile int main_running = 0;
-static struct tq_struct NCR5380_tqueue = {
-    routine:	(void (*)(void*))NCR5380_main	/* must have (void *) arg... */
-};
+static DECLARE_WORK(NCR5380_tqueue, (void (*)(void*))NCR5380_main, NULL);
 
 static __inline__ void queue_main(void)
 {
@@ -655,8 +653,7 @@
 	   queue it on the 'immediate' task queue, to be processed
 	   immediately after the current interrupt processing has
 	   finished. */
-	queue_task(&NCR5380_tqueue, &tq_immediate);
-	mark_bh(IMMEDIATE_BH);
+	schedule_work(&NCR5380_tqueue);
     }
     /* else: nothing to do: the running NCR5380_main() will pick up
        any newly queued command. */
--- linux/drivers/scsi/mac_NCR5380.c.orig	Tue Oct  1 14:01:22 2002
+++ linux/drivers/scsi/mac_NCR5380.c	Tue Oct  1 16:20:34 2002
@@ -657,13 +657,11 @@
  * interrupt or bottom half.
  */
 
-#include <linux/tqueue.h>
+#include <linux/workqueue.h>
 #include <linux/interrupt.h>
 
 static volatile int main_running = 0;
-static struct tq_struct NCR5380_tqueue = {
-    routine:	(void (*)(void*))NCR5380_main	/* must have (void *) arg... */
-};
+static DECLARE_WORK(NCR5380_tqueue, (void (*)(void*))NCR5380_main, NULL);
 
 static __inline__ void queue_main(void)
 {
@@ -672,8 +670,7 @@
 	   queue it on the 'immediate' task queue, to be processed
 	   immediately after the current interrupt processing has
 	   finished. */
-	queue_task(&NCR5380_tqueue, &tq_immediate);
-	mark_bh(IMMEDIATE_BH);
+	schedule_work(&NCR5380_tqueue);
     }
     /* else: nothing to do: the running NCR5380_main() will pick up
        any newly queued command. */
--- linux/drivers/scsi/imm.c.orig	Tue Oct  1 14:01:22 2002
+++ linux/drivers/scsi/imm.c	Tue Oct  1 16:22:25 2002
@@ -36,7 +36,7 @@
     int mode;			/* Transfer mode                */
     int host;			/* Host number (for proc)       */
     Scsi_Cmnd *cur_cmd;		/* Current queued command       */
-    struct tq_struct imm_tq;	/* Polling interrupt stuff       */
+    work_t imm_tq;		/* Polling interrupt stuff       */
     unsigned long jstart;	/* Jiffies at start             */
     unsigned failed:1;		/* Failure flag                 */
     unsigned dp:1;		/* Data phase present           */
@@ -51,7 +51,6 @@
 	mode:		IMM_AUTODETECT,	\
 	host:		-1,		\
 	cur_cmd:	NULL,		\
-	imm_tq:		{ routine: imm_interrupt },    \
 	jstart:		0,		\
 	failed:		0,		\
 	dp:		0,		\
@@ -896,9 +895,8 @@
 	return;
     }
     if (imm_engine(tmp, cmd)) {
-	tmp->imm_tq.data = (void *) tmp;
-	tmp->imm_tq.sync = 0;
-	queue_task(&tmp->imm_tq, &tq_timer);
+	INIT_WORK(&tmp->imm_tq, imm_interrupt, (void *)tmp);
+	schedule_delayed_work(&tmp->imm_tq, 1);
 	return;
     }
     /* Command must of completed hence it is safe to let go... */
@@ -1103,10 +1101,8 @@
 
     imm_pb_claim(host_no);
 
-    imm_hosts[host_no].imm_tq.data = imm_hosts + host_no;
-    imm_hosts[host_no].imm_tq.sync = 0;
-    queue_task(&imm_hosts[host_no].imm_tq, &tq_immediate);
-    mark_bh(IMMEDIATE_BH);
+    INIT_WORK(&imm_hosts[host_no].imm_tq, imm_interrupt, imm_hosts + host_no);
+    schedule_work(&imm_hosts[host_no].imm_tq);
 
     return 0;
 }
--- linux/drivers/scsi/qla1280.h.orig	Tue Oct  1 14:01:22 2002
+++ linux/drivers/scsi/qla1280.h	Tue Oct  1 16:23:28 2002
@@ -1234,7 +1234,7 @@
 	struct scsi_lu *dev[MAX_EQ];	/* Logical unit queues */
 
 	/* bottom half run queue */
-	struct tq_struct run_qla_bh;
+	work_t run_qla_bh;
 
 	/* Received ISP mailbox data. */
 	volatile uint16_t mailbox_out[MAILBOX_REGISTER_COUNT];
--- linux/drivers/scsi/megaraid.c.orig	Tue Oct  1 15:52:29 2002
+++ linux/drivers/scsi/megaraid.c	Tue Oct  1 17:43:01 2002
@@ -491,7 +491,7 @@
 #include <linux/proc_fs.h>
 #include <linux/blk.h>
 #include <linux/wait.h>
-#include <linux/tqueue.h>
+#include <linux/workqueue.h>
 #include <linux/interrupt.h>
 #include <linux/mm.h>
 #include <asm/pgtable.h>
--- linux/drivers/scsi/qla1280.c.orig	Tue Oct  1 15:52:29 2002
+++ linux/drivers/scsi/qla1280.c	Tue Oct  1 16:23:23 2002
@@ -131,14 +131,14 @@
         - Added check of device_id when handling non
           QLA12160s during detect().
     Rev  3.22 Beta January 5, 2001 BN Qlogic
-        - Changed queue_task() to schedule_task()
+        - Changed queue_task() to schedule_work()
           for kernels 2.4.0 and higher.
           Note: 2.4.0-testxx kernels released prior to
                 the actual 2.4.0 kernel release on January 2001
-                will get compile/link errors with schedule_task().
+                will get compile/link errors with schedule_work().
                 Please update your kernel to released 2.4.0 level,
                 or comment lines in this file flagged with  3.22
-                to resolve compile/link error of schedule_task().
+                to resolve compile/link error of schedule_work().
         - Added -DCONFIG_SMP in addition to -D__SMP__
           in Makefile for 2.4.0 builds of driver as module.
     Rev  3.21 Beta January 4, 2001 BN Qlogic
@@ -253,7 +253,7 @@
 #include <linux/pci.h>
 #include <linux/proc_fs.h>
 #include <linux/blk.h>
-#include <linux/tqueue.h>
+#include <linux/workqueue.h>
 #include <linux/stat.h>
 #include <linux/slab.h>
 
@@ -1190,9 +1190,9 @@
 					   &ha->done_q_last);
 /* 3.22 */
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)	/* 3.22 */
-			queue_task(&ha->run_qla_bh, &tq_scheduler);
+			schedule_work(&ha->run_qla_bh);
 #else				/* 3.22 */
-			schedule_task(&ha->run_qla_bh);	/* 3.22 */
+			schedule_work(&ha->run_qla_bh);	/* 3.22 */
 #endif				/* 3.22 */
 			return 0;
 		}
--- linux/drivers/usb/serial/digi_acceleport.c.orig	Tue Oct  1 11:29:51 2002
+++ linux/drivers/usb/serial/digi_acceleport.c	Tue Oct  1 11:32:28 2002
@@ -243,7 +243,7 @@
 #include <linux/tty_flip.h>
 #include <linux/module.h>
 #include <linux/spinlock.h>
-#include <linux/tqueue.h>
+#include <linux/workqueue.h>
 #include <asm/uaccess.h>
 #include <linux/usb.h>
 
@@ -437,7 +437,7 @@
 	wait_queue_head_t dp_flush_wait;
 	int dp_in_close;			/* close in progress */
 	wait_queue_head_t dp_close_wait;	/* wait queue for close */
-	struct tq_struct dp_wakeup_task;
+	work_t dp_wakeup_work;
 };
 
 
@@ -1416,7 +1416,7 @@
 
 	/* also queue up a wakeup at scheduler time, in case we */
 	/* lost the race in write_chan(). */
-	schedule_task(&priv->dp_wakeup_task);
+	schedule_work(&priv->dp_wakeup_work);
 
 	spin_unlock( &priv->dp_port_lock );
 
@@ -1714,10 +1714,8 @@
 		init_waitqueue_head( &priv->dp_flush_wait );
 		priv->dp_in_close = 0;
 		init_waitqueue_head( &priv->dp_close_wait );
-		INIT_LIST_HEAD(&priv->dp_wakeup_task.list);
-		priv->dp_wakeup_task.sync = 0;
-		priv->dp_wakeup_task.routine = (void *)digi_wakeup_write_lock;
-		priv->dp_wakeup_task.data = (void *)(&serial->port[i]);
+		INIT_WORK(&priv->dp_wakeup_work, (void *)digi_wakeup_write_lock,
+				(void *)(&serial->port[i]));
 
 		/* initialize write wait queue for this port */
 		init_waitqueue_head( &serial->port[i].write_wait );
--- linux/drivers/usb/serial/usb-serial.h.orig	Tue Oct  1 11:31:31 2002
+++ linux/drivers/usb/serial/usb-serial.h	Tue Oct  1 11:31:51 2002
@@ -87,7 +87,7 @@
  * @bulk_out_endpointAddress: endpoint address for the bulk out pipe for this
  *	port.
  * @write_wait: a wait_queue_head_t used by the port.
- * @tqueue: task queue for the line discipline waking up.
+ * @work: work queue entry for the line discipline waking up.
  * @open_count: number of times this port has been opened.
  * @sem: struct semaphore used to lock this structure.
  * @private: place to put any driver specific information that is needed.  The
@@ -117,7 +117,7 @@
 	__u8			bulk_out_endpointAddress;
 
 	wait_queue_head_t	write_wait;
-	struct tq_struct	tqueue;
+	work_t			work;
 	int			open_count;
 	struct semaphore	sem;
 	void *			private;
--- linux/drivers/usb/serial/visor.c.orig	Tue Oct  1 11:37:36 2002
+++ linux/drivers/usb/serial/visor.c	Tue Oct  1 11:37:51 2002
@@ -460,7 +460,7 @@
 	/* free up the transfer buffer, as usb_free_urb() does not do this */
 	kfree (urb->transfer_buffer);
 
-	schedule_task(&port->tqueue);
+	schedule_work(&port->work);
 }
 
 
--- linux/drivers/usb/serial/ipaq.c.orig	Tue Oct  1 11:38:12 2002
+++ linux/drivers/usb/serial/ipaq.c	Tue Oct  1 11:38:26 2002
@@ -466,7 +466,7 @@
 		spin_unlock_irqrestore(&write_list_lock, flags);
 	}
 
-	schedule_task(&port->tqueue);
+	schedule_work(&port->work);
 }
 
 static int ipaq_write_room(struct usb_serial_port *port)
--- linux/drivers/usb/serial/keyspan_pda.c.orig	Tue Oct  1 11:34:18 2002
+++ linux/drivers/usb/serial/keyspan_pda.c	Tue Oct  1 11:37:17 2002
@@ -76,7 +76,7 @@
 #include <linux/tty_flip.h>
 #include <linux/module.h>
 #include <linux/spinlock.h>
-#include <linux/tqueue.h>
+#include <linux/workqueue.h>
 #include <asm/uaccess.h>
 #include <linux/usb.h>
 
@@ -125,8 +125,8 @@
 struct keyspan_pda_private {
 	int			tx_room;
 	int			tx_throttled;
-	struct tq_struct	wakeup_task;
-	struct tq_struct	unthrottle_task;
+	work_t			wakeup_work;
+	work_t			unthrottle_work;
 };
 
 
@@ -267,7 +267,7 @@
 			tty = serial->port[0].tty;
 			priv->tx_throttled = 0;
 			/* queue up a wakeup at scheduler time */
-			schedule_task(&priv->wakeup_task);
+			schedule_work(&priv->wakeup_work);
 			break;
 		default:
 			break;
@@ -611,7 +611,7 @@
 
 	if (request_unthrottle) {
 		priv->tx_throttled = 1; /* block writers */
-		schedule_task(&priv->unthrottle_task);
+		schedule_work(&priv->unthrottle_work);
 	}
 
 	rc = count;
@@ -638,7 +638,7 @@
 	}
 	
 	/* queue up a wakeup at scheduler time */
-	schedule_task(&priv->wakeup_task);
+	schedule_work(&priv->wakeup_work);
 }
 
 
@@ -791,14 +791,11 @@
 	if (!priv)
 		return (1); /* error */
 	init_waitqueue_head(&serial->port[0].write_wait);
-	INIT_LIST_HEAD(&priv->wakeup_task.list);
-	priv->wakeup_task.sync = 0;
-	priv->wakeup_task.routine = (void *)keyspan_pda_wakeup_write;
-	priv->wakeup_task.data = (void *)(&serial->port[0]);
-	INIT_LIST_HEAD(&priv->unthrottle_task.list);
-	priv->unthrottle_task.sync = 0;
-	priv->unthrottle_task.routine = (void *)keyspan_pda_request_unthrottle;
-