]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blob - releases/2.6.32.12/usb-cdc-acm-update-to-new-autopm-api.patch
Remove duplicated commits
[thirdparty/kernel/stable-queue.git] / releases / 2.6.32.12 / usb-cdc-acm-update-to-new-autopm-api.patch
1 From 97d35f95552c9a0ee4777a7f04431a9fd1260478 Mon Sep 17 00:00:00 2001
2 From: Oliver Neukum <oliver@neukum.org>
3 Date: Wed, 16 Dec 2009 17:05:57 +0100
4 Subject: USB: cdc-acm: Update to new autopm API
5
6 From: Oliver Neukum <oliver@neukum.org>
7
8 commit 97d35f95552c9a0ee4777a7f04431a9fd1260478 upstream.
9
10 Update cdc-acm to the async methods eliminating the workqueue
11
12 [This fixes a reported lockup for the cdc-acm driver - gregkh]
13
14 Signed-off-by: Oliver Neukum <oliver@neukum.org>
15 Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
16
17 ---
18 drivers/usb/class/cdc-acm.c | 43 ++++++++++++++++++++++---------------------
19 drivers/usb/class/cdc-acm.h | 1 -
20 2 files changed, 22 insertions(+), 22 deletions(-)
21
22 --- a/drivers/usb/class/cdc-acm.c
23 +++ b/drivers/usb/class/cdc-acm.c
24 @@ -170,6 +170,7 @@ static void acm_write_done(struct acm *a
25 {
26 wb->use = 0;
27 acm->transmitting--;
28 + usb_autopm_put_interface_async(acm->control);
29 }
30
31 /*
32 @@ -211,9 +212,12 @@ static int acm_write_start(struct acm *a
33 }
34
35 dbg("%s susp_count: %d", __func__, acm->susp_count);
36 + usb_autopm_get_interface_async(acm->control);
37 if (acm->susp_count) {
38 - acm->delayed_wb = wb;
39 - schedule_work(&acm->waker);
40 + if (!acm->delayed_wb)
41 + acm->delayed_wb = wb;
42 + else
43 + usb_autopm_put_interface_async(acm->control);
44 spin_unlock_irqrestore(&acm->write_lock, flags);
45 return 0; /* A white lie */
46 }
47 @@ -534,23 +538,6 @@ static void acm_softint(struct work_stru
48 tty_kref_put(tty);
49 }
50
51 -static void acm_waker(struct work_struct *waker)
52 -{
53 - struct acm *acm = container_of(waker, struct acm, waker);
54 - int rv;
55 -
56 - rv = usb_autopm_get_interface(acm->control);
57 - if (rv < 0) {
58 - dev_err(&acm->dev->dev, "Autopm failure in %s\n", __func__);
59 - return;
60 - }
61 - if (acm->delayed_wb) {
62 - acm_start_wb(acm, acm->delayed_wb);
63 - acm->delayed_wb = NULL;
64 - }
65 - usb_autopm_put_interface(acm->control);
66 -}
67 -
68 /*
69 * TTY handlers
70 */
71 @@ -1178,7 +1165,6 @@ made_compressed_probe:
72 acm->urb_task.func = acm_rx_tasklet;
73 acm->urb_task.data = (unsigned long) acm;
74 INIT_WORK(&acm->work, acm_softint);
75 - INIT_WORK(&acm->waker, acm_waker);
76 init_waitqueue_head(&acm->drain_wait);
77 spin_lock_init(&acm->throttle_lock);
78 spin_lock_init(&acm->write_lock);
79 @@ -1343,7 +1329,6 @@ static void stop_data_traffic(struct acm
80 tasklet_enable(&acm->urb_task);
81
82 cancel_work_sync(&acm->work);
83 - cancel_work_sync(&acm->waker);
84 }
85
86 static void acm_disconnect(struct usb_interface *intf)
87 @@ -1435,6 +1420,7 @@ static int acm_suspend(struct usb_interf
88 static int acm_resume(struct usb_interface *intf)
89 {
90 struct acm *acm = usb_get_intfdata(intf);
91 + struct acm_wb *wb;
92 int rv = 0;
93 int cnt;
94
95 @@ -1449,6 +1435,21 @@ static int acm_resume(struct usb_interfa
96 mutex_lock(&acm->mutex);
97 if (acm->port.count) {
98 rv = usb_submit_urb(acm->ctrlurb, GFP_NOIO);
99 +
100 + spin_lock_irq(&acm->write_lock);
101 + if (acm->delayed_wb) {
102 + wb = acm->delayed_wb;
103 + acm->delayed_wb = NULL;
104 + spin_unlock_irq(&acm->write_lock);
105 + acm_start_wb(acm, acm->delayed_wb);
106 + } else {
107 + spin_unlock_irq(&acm->write_lock);
108 + }
109 +
110 + /*
111 + * delayed error checking because we must
112 + * do the write path at all cost
113 + */
114 if (rv < 0)
115 goto err_out;
116
117 --- a/drivers/usb/class/cdc-acm.h
118 +++ b/drivers/usb/class/cdc-acm.h
119 @@ -112,7 +112,6 @@ struct acm {
120 struct mutex mutex;
121 struct usb_cdc_line_coding line; /* bits, stop, parity */
122 struct work_struct work; /* work queue entry for line discipline waking up */
123 - struct work_struct waker;
124 wait_queue_head_t drain_wait; /* close processing */
125 struct tasklet_struct urb_task; /* rx processing */
126 spinlock_t throttle_lock; /* synchronize throtteling and read callback */