Merge branch 'for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/hch/hfsplus
[pandora-kernel.git] / drivers / connector / cn_queue.c
index 210338e..81270d2 100644 (file)
 #include <linux/connector.h>
 #include <linux/delay.h>
 
-
-/*
- * This job is sent to the kevent workqueue.
- * While no event is once sent to any callback, the connector workqueue
- * is not created to avoid a useless waiting kernel task.
- * Once the first event is received, we create this dedicated workqueue which
- * is necessary because the flow of data can be high and we don't want
- * to encumber keventd with that.
- */
-static void cn_queue_create(struct work_struct *work)
-{
-       struct cn_queue_dev *dev;
-
-       dev = container_of(work, struct cn_queue_dev, wq_creation);
-
-       dev->cn_queue = create_singlethread_workqueue(dev->name);
-       /* If we fail, we will use keventd for all following connector jobs */
-       WARN_ON(!dev->cn_queue);
-}
-
-/*
- * Queue a data sent to a callback.
- * If the connector workqueue is already created, we queue the job on it.
- * Otherwise, we queue the job to kevent and queue the connector workqueue
- * creation too.
- */
-int queue_cn_work(struct cn_callback_entry *cbq, struct work_struct *work)
-{
-       struct cn_queue_dev *pdev = cbq->pdev;
-
-       if (likely(pdev->cn_queue))
-               return queue_work(pdev->cn_queue, work);
-
-       /* Don't create the connector workqueue twice */
-       if (atomic_inc_return(&pdev->wq_requested) == 1)
-               schedule_work(&pdev->wq_creation);
-       else
-               atomic_dec(&pdev->wq_requested);
-
-       return schedule_work(work);
-}
-
 void cn_queue_wrapper(struct work_struct *work)
 {
        struct cn_callback_entry *cbq =
@@ -111,11 +69,7 @@ cn_queue_alloc_callback_entry(char *name, struct cb_id *id,
 
 static void cn_queue_free_callback(struct cn_callback_entry *cbq)
 {
-       /* The first jobs have been sent to kevent, flush them too */
-       flush_scheduled_work();
-       if (cbq->pdev->cn_queue)
-               flush_workqueue(cbq->pdev->cn_queue);
-
+       flush_workqueue(cbq->pdev->cn_queue);
        kfree(cbq);
 }
 
@@ -193,11 +147,14 @@ struct cn_queue_dev *cn_queue_alloc_dev(char *name, struct sock *nls)
        atomic_set(&dev->refcnt, 0);
        INIT_LIST_HEAD(&dev->queue_list);
        spin_lock_init(&dev->queue_lock);
-       init_waitqueue_head(&dev->wq_created);
 
        dev->nls = nls;
 
-       INIT_WORK(&dev->wq_creation, cn_queue_create);
+       dev->cn_queue = alloc_ordered_workqueue(dev->name, 0);
+       if (!dev->cn_queue) {
+               kfree(dev);
+               return NULL;
+       }
 
        return dev;
 }
@@ -205,25 +162,9 @@ struct cn_queue_dev *cn_queue_alloc_dev(char *name, struct sock *nls)
 void cn_queue_free_dev(struct cn_queue_dev *dev)
 {
        struct cn_callback_entry *cbq, *n;
-       long timeout;
-       DEFINE_WAIT(wait);
-
-       /* Flush the first pending jobs queued on kevent */
-       flush_scheduled_work();
-
-       /* If the connector workqueue creation is still pending, wait for it */
-       prepare_to_wait(&dev->wq_created, &wait, TASK_UNINTERRUPTIBLE);
-       if (atomic_read(&dev->wq_requested) && !dev->cn_queue) {
-               timeout = schedule_timeout(HZ * 2);
-               if (!timeout && !dev->cn_queue)
-                       WARN_ON(1);
-       }
-       finish_wait(&dev->wq_created, &wait);
 
-       if (dev->cn_queue) {
-               flush_workqueue(dev->cn_queue);
-               destroy_workqueue(dev->cn_queue);
-       }
+       flush_workqueue(dev->cn_queue);
+       destroy_workqueue(dev->cn_queue);
 
        spin_lock_bh(&dev->queue_lock);
        list_for_each_entry_safe(cbq, n, &dev->queue_list, callback_entry)