]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blame - releases/2.6.36.2/isdn-gigaset-fix-bas_gigaset-at-read-error-handling.patch
Remove duplicated commits
[thirdparty/kernel/stable-queue.git] / releases / 2.6.36.2 / isdn-gigaset-fix-bas_gigaset-at-read-error-handling.patch
CommitLineData
ad522180
GKH
1From c8701a08d6a4efeae45d84d0aa87172f23b14e3c Mon Sep 17 00:00:00 2001
2From: Tilman Schmidt <tilman@imap.cc>
3Date: Thu, 30 Sep 2010 13:34:40 +0000
4Subject: isdn/gigaset: fix bas_gigaset AT read error handling
5
6From: Tilman Schmidt <tilman@imap.cc>
7
8commit c8701a08d6a4efeae45d84d0aa87172f23b14e3c upstream.
9
10Rework the handling of USB errors in AT response reads
11to fix a possible infinite retry loop and a memory leak,
12and silence a few overly verbose kernel messages.
13
14Signed-off-by: Tilman Schmidt <tilman@imap.cc>
15Signed-off-by: David S. Miller <davem@davemloft.net>
16Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
17
18---
19 drivers/isdn/gigaset/bas-gigaset.c | 83 ++++++++++++++-----------------------
20 1 file changed, 33 insertions(+), 50 deletions(-)
21
22--- a/drivers/isdn/gigaset/bas-gigaset.c
23+++ b/drivers/isdn/gigaset/bas-gigaset.c
24@@ -438,23 +438,27 @@ static void cmd_in_timeout(unsigned long
25 return;
26 }
27
28- if (ucs->retry_cmd_in++ < BAS_RETRY) {
29- dev_notice(cs->dev, "control read: timeout, retry %d\n",
30- ucs->retry_cmd_in);
31- rc = atread_submit(cs, BAS_TIMEOUT);
32- if (rc >= 0 || rc == -ENODEV)
33- /* resubmitted or disconnected */
34- /* - bypass regular exit block */
35- return;
36- } else {
37+ if (ucs->retry_cmd_in++ >= BAS_RETRY) {
38 dev_err(cs->dev,
39 "control read: timeout, giving up after %d tries\n",
40 ucs->retry_cmd_in);
41+ kfree(ucs->rcvbuf);
42+ ucs->rcvbuf = NULL;
43+ ucs->rcvbuf_size = 0;
44+ error_reset(cs);
45+ return;
46+ }
47+
48+ gig_dbg(DEBUG_USBREQ, "%s: timeout, retry %d",
49+ __func__, ucs->retry_cmd_in);
50+ rc = atread_submit(cs, BAS_TIMEOUT);
51+ if (rc < 0) {
52+ kfree(ucs->rcvbuf);
53+ ucs->rcvbuf = NULL;
54+ ucs->rcvbuf_size = 0;
55+ if (rc != -ENODEV)
56+ error_reset(cs);
57 }
58- kfree(ucs->rcvbuf);
59- ucs->rcvbuf = NULL;
60- ucs->rcvbuf_size = 0;
61- error_reset(cs);
62 }
63
64 /* read_ctrl_callback
65@@ -470,18 +474,11 @@ static void read_ctrl_callback(struct ur
66 struct cardstate *cs = inbuf->cs;
67 struct bas_cardstate *ucs = cs->hw.bas;
68 int status = urb->status;
69- int have_data = 0;
70 unsigned numbytes;
71 int rc;
72
73 update_basstate(ucs, 0, BS_ATRDPEND);
74 wake_up(&ucs->waitqueue);
75-
76- if (!ucs->rcvbuf_size) {
77- dev_warn(cs->dev, "%s: no receive in progress\n", __func__);
78- return;
79- }
80-
81 del_timer(&ucs->timer_cmd_in);
82
83 switch (status) {
84@@ -495,19 +492,10 @@ static void read_ctrl_callback(struct ur
85 numbytes = ucs->rcvbuf_size;
86 }
87
88- /* copy received bytes to inbuf */
89- have_data = gigaset_fill_inbuf(inbuf, ucs->rcvbuf, numbytes);
90-
91- if (unlikely(numbytes < ucs->rcvbuf_size)) {
92- /* incomplete - resubmit for remaining bytes */
93- ucs->rcvbuf_size -= numbytes;
94- ucs->retry_cmd_in = 0;
95- rc = atread_submit(cs, BAS_TIMEOUT);
96- if (rc >= 0 || rc == -ENODEV)
97- /* resubmitted or disconnected */
98- /* - bypass regular exit block */
99- return;
100- error_reset(cs);
101+ /* copy received bytes to inbuf, notify event layer */
102+ if (gigaset_fill_inbuf(inbuf, ucs->rcvbuf, numbytes)) {
103+ gig_dbg(DEBUG_INTR, "%s-->BH", __func__);
104+ gigaset_schedule_event(cs);
105 }
106 break;
107
108@@ -516,37 +504,32 @@ static void read_ctrl_callback(struct ur
109 case -EINPROGRESS: /* pending */
110 case -ENODEV: /* device removed */
111 case -ESHUTDOWN: /* device shut down */
112- /* no action necessary */
113+ /* no further action necessary */
114 gig_dbg(DEBUG_USBREQ, "%s: %s",
115 __func__, get_usb_statmsg(status));
116 break;
117
118- default: /* severe trouble */
119- dev_warn(cs->dev, "control read: %s\n",
120- get_usb_statmsg(status));
121+ default: /* other errors: retry */
122 if (ucs->retry_cmd_in++ < BAS_RETRY) {
123- dev_notice(cs->dev, "control read: retry %d\n",
124- ucs->retry_cmd_in);
125+ gig_dbg(DEBUG_USBREQ, "%s: %s, retry %d", __func__,
126+ get_usb_statmsg(status), ucs->retry_cmd_in);
127 rc = atread_submit(cs, BAS_TIMEOUT);
128- if (rc >= 0 || rc == -ENODEV)
129- /* resubmitted or disconnected */
130- /* - bypass regular exit block */
131+ if (rc >= 0)
132+ /* successfully resubmitted, skip freeing */
133 return;
134- } else {
135- dev_err(cs->dev,
136- "control read: giving up after %d tries\n",
137- ucs->retry_cmd_in);
138+ if (rc == -ENODEV)
139+ /* disconnect, no further action necessary */
140+ break;
141 }
142+ dev_err(cs->dev, "control read: %s, giving up after %d tries\n",
143+ get_usb_statmsg(status), ucs->retry_cmd_in);
144 error_reset(cs);
145 }
146
147+ /* read finished, free buffer */
148 kfree(ucs->rcvbuf);
149 ucs->rcvbuf = NULL;
150 ucs->rcvbuf_size = 0;
151- if (have_data) {
152- gig_dbg(DEBUG_INTR, "%s-->BH", __func__);
153- gigaset_schedule_event(cs);
154- }
155 }
156
157 /* atread_submit