compat: backport system_nrt_wq
[~emulex/for-vlad/old/compat.git] / compat / compat-2.6.36.c
1 /*
2  * Copyright 2010    Hauke Mehrtens <hauke@hauke-m.de>
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License version 2 as
6  * published by the Free Software Foundation.
7  *
8  * Compatibility file for Linux wireless for kernels 2.6.36.
9  */
10
11 #include <linux/compat.h>
12 #include <linux/usb.h>
13
14 #ifdef CONFIG_COMPAT_USB_URB_THREAD_FIX
15 /* Callers must hold anchor->lock */
16 static void __usb_unanchor_urb(struct urb *urb, struct usb_anchor *anchor)
17 {
18         urb->anchor = NULL;
19         list_del(&urb->anchor_list);
20         usb_put_urb(urb);
21         if (list_empty(&anchor->urb_list))
22                 wake_up(&anchor->wait);
23 }
24
25 /**
26  * usb_unlink_anchored_urbs - asynchronously cancel transfer requests en masse
27  * @anchor: anchor the requests are bound to
28  *
29  * this allows all outstanding URBs to be unlinked starting
30  * from the back of the queue. This function is asynchronous.
31  * The unlinking is just tiggered. It may happen after this
32  * function has returned.
33  *
34  * This routine should not be called by a driver after its disconnect
35  * method has returned.
36  */
37 void compat_usb_unlink_anchored_urbs(struct usb_anchor *anchor)
38 {
39         struct urb *victim;
40
41         while ((victim = usb_get_from_anchor(anchor)) != NULL) {
42                 usb_unlink_urb(victim);
43                 usb_put_urb(victim);
44         }
45 }
46 EXPORT_SYMBOL_GPL(compat_usb_unlink_anchored_urbs);
47
48 /**
49  * usb_get_from_anchor - get an anchor's oldest urb
50  * @anchor: the anchor whose urb you want
51  *
52  * this will take the oldest urb from an anchor,
53  * unanchor and return it
54  */
55 struct urb *compat_usb_get_from_anchor(struct usb_anchor *anchor)
56 {
57         struct urb *victim;
58         unsigned long flags;
59
60         spin_lock_irqsave(&anchor->lock, flags);
61         if (!list_empty(&anchor->urb_list)) {
62                 victim = list_entry(anchor->urb_list.next, struct urb,
63                                     anchor_list);
64                 usb_get_urb(victim);
65                 __usb_unanchor_urb(victim, anchor);
66         } else {
67                 victim = NULL;
68         }
69         spin_unlock_irqrestore(&anchor->lock, flags);
70
71         return victim;
72 }
73 EXPORT_SYMBOL_GPL(compat_usb_get_from_anchor);
74
75 /**
76  * usb_scuttle_anchored_urbs - unanchor all an anchor's urbs
77  * @anchor: the anchor whose urbs you want to unanchor
78  *
79  * use this to get rid of all an anchor's urbs
80  */
81 void compat_usb_scuttle_anchored_urbs(struct usb_anchor *anchor)
82 {
83         struct urb *victim;
84         unsigned long flags;
85
86         spin_lock_irqsave(&anchor->lock, flags);
87         while (!list_empty(&anchor->urb_list)) {
88                 victim = list_entry(anchor->urb_list.prev, struct urb,
89                                     anchor_list);
90                 __usb_unanchor_urb(victim, anchor);
91         }
92         spin_unlock_irqrestore(&anchor->lock, flags);
93 }
94 EXPORT_SYMBOL_GPL(compat_usb_scuttle_anchored_urbs);
95
96 struct workqueue_struct *system_nrt_wq __read_mostly;
97 EXPORT_SYMBOL_GPL(system_nrt_wq);
98
99 void compat_system_workqueue_create()
100 {
101         system_nrt_wq = create_singlethread_workqueue("events_nrt");
102         WARN_ON(system_nrt_wq);
103 }
104
105 void compat_system_workqueue_destroy()
106 {
107         destroy_workqueue(system_nrt_wq);
108 }
109
110 #endif /* CONFIG_COMPAT_USB_URB_THREAD_FIX */
111