#include <linux/poll.h>
 #include <linux/kernel.h>
 #include <linux/uuid.h>
+#include <linux/seq_file.h>
+#include <linux/slab.h>
 
-#include "periodic_work.h"
 #include "channel.h"
 
 struct visor_driver;
  * device:                     Device struct meant for use by the bus driver
  *                             only.
  * list_all:                   Used by the bus driver to enumerate devices.
- * periodic_work:              Device work queue. Private use by bus driver
- *                             only.
+ * timer:                      Timer fired periodically to do interrupt-type
+ *                             activity.
  * being_removed:              Indicates that the device is being removed from
  *                             the bus. Private bus driver use only.
  * visordriver_callback_lock:  Used by the bus driver to lock when handling
        /* These fields are for private use by the bus driver only. */
        struct device device;
        struct list_head list_all;
-       struct periodic_work *periodic_work;
+       struct timer_list timer;
+       bool timer_active;
        bool being_removed;
        struct semaphore visordriver_callback_lock;
        bool pausing;
 
 #include "visorbus.h"
 #include "visorbus_private.h"
 #include "version.h"
-#include "periodic_work.h"
 #include "vbuschannel.h"
 #include "guestlinuxdebug.h"
 #include "vmcallinterface.h"
        .bus_groups = visorbus_bus_groups,
 };
 
-static struct workqueue_struct *periodic_dev_workqueue;
 static long long bus_count;    /** number of bus instances */
                                        /** ever-increasing */
 
 {
        struct visor_device *dev = to_visor_device(xdev);
 
-       if (dev->periodic_work) {
-               visor_periodic_work_destroy(dev->periodic_work);
-               dev->periodic_work = NULL;
-       }
        if (dev->visorchannel) {
                visorchannel_destroy(dev->visorchannel);
                dev->visorchannel = NULL;
 }
 
 static void
-dev_periodic_work(void *xdev)
+dev_periodic_work(unsigned long __opaque)
 {
-       struct visor_device *dev = xdev;
+       struct visor_device *dev = (struct visor_device *)__opaque;
        struct visor_driver *drv = to_visor_driver(dev->device.driver);
 
-       down(&dev->visordriver_callback_lock);
        if (drv->channel_interrupt)
                drv->channel_interrupt(dev);
-       up(&dev->visordriver_callback_lock);
-       if (!visor_periodic_work_nextperiod(dev->periodic_work))
-               put_device(&dev->device);
+       mod_timer(&dev->timer, jiffies + POLLJIFFIES_NORMALCHANNEL);
 }
 
 static void
 dev_start_periodic_work(struct visor_device *dev)
 {
-       if (dev->being_removed)
+       if (dev->being_removed || dev->timer_active)
                return;
        /* now up by at least 2 */
        get_device(&dev->device);
-       if (!visor_periodic_work_start(dev->periodic_work))
-               put_device(&dev->device);
+       dev->timer.expires = jiffies + POLLJIFFIES_NORMALCHANNEL;
+       add_timer(&dev->timer);
+       dev->timer_active = true;
 }
 
 static void
 dev_stop_periodic_work(struct visor_device *dev)
 {
-       if (visor_periodic_work_stop(dev->periodic_work))
-               put_device(&dev->device);
+       if (!dev->timer_active)
+               return;
+       del_timer_sync(&dev->timer);
+       dev->timer_active = false;
+       put_device(&dev->device);
 }
 
 /** This is called automatically upon adding a visor_device (device_add), or
        dev->device.release = visorbus_release_device;
        /* keep a reference just for us (now 2) */
        get_device(&dev->device);
-       dev->periodic_work =
-               visor_periodic_work_create(POLLJIFFIES_NORMALCHANNEL,
-                                          periodic_dev_workqueue,
-                                          dev_periodic_work,
-                                          dev, dev_name(&dev->device));
-       if (!dev->periodic_work) {
-               POSTCODE_LINUX_3(DEVICE_CREATE_FAILURE_PC, chipset_dev_no,
-                                DIAG_SEVERITY_ERR);
-               err = -EINVAL;
-               goto err_put;
-       }
+       init_timer(&dev->timer);
+       dev->timer.data = (unsigned long)(dev);
+       dev->timer.function = dev_periodic_work;
 
        /* bus_id must be a unique name with respect to this bus TYPE
         * (NOT bus instance).  That's why we need to include the bus
                goto error;
        }
 
-       periodic_dev_workqueue = create_singlethread_workqueue("visorbus_dev");
-       if (!periodic_dev_workqueue) {
-               POSTCODE_LINUX_2(CREATE_WORKQUEUE_PC, DIAG_SEVERITY_ERR);
-               err = -ENOMEM;
-               goto error;
-       }
-
        /* This enables us to receive notifications when devices appear for
         * which this service partition is to be a server for.
         */
        visorchipset_register_busdev(NULL, NULL, NULL);
        remove_all_visor_devices();
 
-       flush_workqueue(periodic_dev_workqueue); /* better not be any work! */
-       destroy_workqueue(periodic_dev_workqueue);
-       periodic_dev_workqueue = NULL;
-
        list_for_each_safe(listentry, listtmp, &list_all_bus_instances) {
                struct visor_device *dev = list_entry(listentry,
                                                      struct visor_device,