1 |
Author: mpagano |
2 |
Date: 2008-04-28 14:04:17 +0000 (Mon, 28 Apr 2008) |
3 |
New Revision: 1299 |
4 |
|
5 |
Added: |
6 |
genpatches-2.6/trunk/2.6.24/2300_delorme-cypress-m8-fix.patch |
7 |
Modified: |
8 |
genpatches-2.6/trunk/2.6.24/0000_README |
9 |
Log: |
10 |
Added Delorme patch for bug #219152 |
11 |
|
12 |
Modified: genpatches-2.6/trunk/2.6.24/0000_README |
13 |
=================================================================== |
14 |
--- genpatches-2.6/trunk/2.6.24/0000_README 2008-04-19 10:11:33 UTC (rev 1298) |
15 |
+++ genpatches-2.6/trunk/2.6.24/0000_README 2008-04-28 14:04:17 UTC (rev 1299) |
16 |
@@ -71,6 +71,10 @@ |
17 |
From: http://bugs.gentoo.org/196879 |
18 |
Desc: Fix TEST_UNIT_READY for medium detection |
19 |
|
20 |
+Patch: 2300_delorme-cypress-m8-fix.patch |
21 |
+From: http://bugs.gentoo.org/219152 |
22 |
+Desc: Fix for Delorme Earthmate LT-40 |
23 |
+ |
24 |
Patch: 2400_ipw2200-radiotap-addr.patch |
25 |
From: http://bugs.gentoo.org/215714 |
26 |
Desc: Fix IPW2200 radiotap interface |
27 |
|
28 |
Added: genpatches-2.6/trunk/2.6.24/2300_delorme-cypress-m8-fix.patch |
29 |
=================================================================== |
30 |
--- genpatches-2.6/trunk/2.6.24/2300_delorme-cypress-m8-fix.patch (rev 0) |
31 |
+++ genpatches-2.6/trunk/2.6.24/2300_delorme-cypress-m8-fix.patch 2008-04-28 14:04:17 UTC (rev 1299) |
32 |
@@ -0,0 +1,568 @@ |
33 |
+From: Mike Isely <isely@×××××.net> |
34 |
+Date: Mon, 11 Feb 2008 02:23:14 +0000 (-0600) |
35 |
+Subject: USB: cypress_m8: Feature buffer fixes |
36 |
+X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftorvalds%2Flinux-2.6.git;a=commitdiff_plain;h=93075544d6c6e9aaa14c44edb6eb3f71144bdeeb |
37 |
+ |
38 |
+USB: cypress_m8: Feature buffer fixes |
39 |
+ |
40 |
+cypress_m8: Feature buffer fixes |
41 |
+ |
42 |
+From: Mike Isely <isely@×××××.com> |
43 |
+ |
44 |
+Don't hardcode the feature buffer size; use sizeof() instead. That |
45 |
+way we can easily specify the size in a single spot. Speaking of the |
46 |
+feature buffer size, the Cypress app note (and further testing with a |
47 |
+DeLorme Earthmate) suggests that this size should be 5 not 8 bytes. |
48 |
+ |
49 |
+Signed-off-by: Mike Isely <isely@×××××.com> |
50 |
+Signed-off-by: Greg Kroah-Hartman <gregkh@××××.de> |
51 |
+--- |
52 |
+ |
53 |
+diff --git a/drivers/usb/serial/cypress_m8.c b/drivers/usb/serial/cypress_m8.c |
54 |
+index 779d078..155b82a 100644 |
55 |
+--- a/drivers/usb/serial/cypress_m8.c |
56 |
++++ b/drivers/usb/serial/cypress_m8.c |
57 |
+@@ -290,7 +290,7 @@ static int cypress_serial_control (struct usb_serial_port *port, unsigned baud_m |
58 |
+ { |
59 |
+ int new_baudrate = 0, retval = 0, tries = 0; |
60 |
+ struct cypress_private *priv; |
61 |
+- __u8 feature_buffer[8]; |
62 |
++ __u8 feature_buffer[5]; |
63 |
+ unsigned long flags; |
64 |
+ |
65 |
+ dbg("%s", __FUNCTION__); |
66 |
+@@ -353,7 +353,7 @@ static int cypress_serial_control (struct usb_serial_port *port, unsigned baud_m |
67 |
+ } |
68 |
+ dbg("%s - baud rate is being sent as %d", __FUNCTION__, new_baudrate); |
69 |
+ |
70 |
+- memset(feature_buffer, 0, 8); |
71 |
++ memset(feature_buffer, 0, sizeof(feature_buffer)); |
72 |
+ /* fill the feature_buffer with new configuration */ |
73 |
+ *((u_int32_t *)feature_buffer) = new_baudrate; |
74 |
+ |
75 |
+@@ -370,16 +370,20 @@ static int cypress_serial_control (struct usb_serial_port *port, unsigned baud_m |
76 |
+ feature_buffer[2], feature_buffer[3], feature_buffer[4]); |
77 |
+ |
78 |
+ do { |
79 |
+- retval = usb_control_msg (port->serial->dev, usb_sndctrlpipe(port->serial->dev, 0), |
80 |
+- HID_REQ_SET_REPORT, USB_DIR_OUT | USB_RECIP_INTERFACE | USB_TYPE_CLASS, |
81 |
+- 0x0300, 0, feature_buffer, 8, 500); |
82 |
++ retval = usb_control_msg(port->serial->dev, |
83 |
++ usb_sndctrlpipe(port->serial->dev, 0), |
84 |
++ HID_REQ_SET_REPORT, |
85 |
++ USB_DIR_OUT | USB_RECIP_INTERFACE | USB_TYPE_CLASS, |
86 |
++ 0x0300, 0, feature_buffer, |
87 |
++ sizeof(feature_buffer), 500); |
88 |
+ |
89 |
+ if (tries++ >= 3) |
90 |
+ break; |
91 |
+ |
92 |
+- } while (retval != 8 && retval != -ENODEV); |
93 |
++ } while (retval != sizeof(feature_buffer) && |
94 |
++ retval != -ENODEV); |
95 |
+ |
96 |
+- if (retval != 8) { |
97 |
++ if (retval != sizeof(feature_buffer)) { |
98 |
+ err("%s - failed sending serial line settings - %d", __FUNCTION__, retval); |
99 |
+ cypress_set_dead(port); |
100 |
+ } else { |
101 |
+@@ -393,19 +397,23 @@ static int cypress_serial_control (struct usb_serial_port *port, unsigned baud_m |
102 |
+ case CYPRESS_GET_CONFIG: |
103 |
+ dbg("%s - retreiving serial line settings", __FUNCTION__); |
104 |
+ /* set initial values in feature buffer */ |
105 |
+- memset(feature_buffer, 0, 8); |
106 |
++ memset(feature_buffer, 0, sizeof(feature_buffer)); |
107 |
+ |
108 |
+ do { |
109 |
+- retval = usb_control_msg (port->serial->dev, usb_rcvctrlpipe(port->serial->dev, 0), |
110 |
+- HID_REQ_GET_REPORT, USB_DIR_IN | USB_RECIP_INTERFACE | USB_TYPE_CLASS, |
111 |
+- 0x0300, 0, feature_buffer, 8, 500); |
112 |
+- |
113 |
++ retval = usb_control_msg(port->serial->dev, |
114 |
++ usb_rcvctrlpipe(port->serial->dev, 0), |
115 |
++ HID_REQ_GET_REPORT, |
116 |
++ USB_DIR_IN | USB_RECIP_INTERFACE | USB_TYPE_CLASS, |
117 |
++ 0x0300, 0, feature_buffer, |
118 |
++ sizeof(feature_buffer), 500); |
119 |
++ |
120 |
+ if (tries++ >= 3) |
121 |
+ break; |
122 |
+ |
123 |
+- } while (retval != 5 && retval != -ENODEV); |
124 |
++ } while (retval != sizeof(feature_buffer) && |
125 |
++ retval != -ENODEV); |
126 |
+ |
127 |
+- if (retval != 5) { |
128 |
++ if (retval != sizeof(feature_buffer)) { |
129 |
+ err("%s - failed to retrieve serial line settings - %d", __FUNCTION__, retval); |
130 |
+ cypress_set_dead(port); |
131 |
+ return retval; |
132 |
+ |
133 |
+From: Mike Isely <isely@×××××.com> |
134 |
+Date: Mon, 11 Feb 2008 02:23:19 +0000 (-0600) |
135 |
+Subject: USB: cypress_m8: Packet format is separate from characteristic size |
136 |
+X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftorvalds%2Flinux-2.6.git;a=commitdiff_plain;h=3416eaa1f8f8d516b77de514e14cf8da256d28fb |
137 |
+ |
138 |
+USB: cypress_m8: Packet format is separate from characteristic size |
139 |
+ |
140 |
+cypress_m8: Packet format is separate from characteristic size |
141 |
+ |
142 |
+The Cypress app note states that when using an 8 byte packet buffer |
143 |
+size that the packet format is modified (to be more compact). However |
144 |
+I have since discovered that newer DeLorme Earthmate LT-20 devices |
145 |
+(those that are low speed USB with 8 byte packet size) STILL use the |
146 |
+format that is really supposed to correspond to 32 byte packets. |
147 |
+Further confusing things is the subsequent discovery that there are |
148 |
+actually two different types of LT-20 - older LT-20's use 32 byte |
149 |
+packets which is probably why this issue wasn't originally |
150 |
+encountered. The solution here is to flag the packet format |
151 |
+separately from the buffer size. Then at initialization time, |
152 |
+identify the correct combination and set it up. This is a critical |
153 |
+fix for anyone with a newer LT-20. Older devices and non-Earthmate |
154 |
+devices should remain unaffected by this change. (If other devices |
155 |
+behave in this, uh, unexpected manner, it's now just a simple 1 line |
156 |
+change to fix them as well (change the pkt_fmt member for that |
157 |
+device). Default behavior with this patch is still to drive the |
158 |
+format as per the app-note; of course for Earthmate devices this is |
159 |
+overridden. |
160 |
+ |
161 |
+Signed-off-by: Mike Isely <isely@×××××.com> |
162 |
+Signed-off-by: Greg Kroah-Hartman <gregkh@××××.de> |
163 |
+--- |
164 |
+ |
165 |
+diff --git a/drivers/usb/serial/cypress_m8.c b/drivers/usb/serial/cypress_m8.c |
166 |
+index 155b82a..c42d3bd 100644 |
167 |
+--- a/drivers/usb/serial/cypress_m8.c |
168 |
++++ b/drivers/usb/serial/cypress_m8.c |
169 |
+@@ -122,6 +122,11 @@ static struct usb_driver cypress_driver = { |
170 |
+ .no_dynamic_id = 1, |
171 |
+ }; |
172 |
+ |
173 |
++enum packet_format { |
174 |
++ packet_format_1, /* b0:status, b1:payload count */ |
175 |
++ packet_format_2 /* b0[7:3]:status, b0[2:0]:payload count */ |
176 |
++}; |
177 |
++ |
178 |
+ struct cypress_private { |
179 |
+ spinlock_t lock; /* private lock */ |
180 |
+ int chiptype; /* identifier of device, for quirks/etc */ |
181 |
+@@ -139,6 +144,7 @@ struct cypress_private { |
182 |
+ __u8 current_status; /* received from last read - info on dsr,cts,cd,ri,etc */ |
183 |
+ __u8 current_config; /* stores the current configuration byte */ |
184 |
+ __u8 rx_flags; /* throttling - used from whiteheat/ftdi_sio */ |
185 |
++ enum packet_format pkt_fmt; /* format to use for packet send / receive */ |
186 |
+ int baud_rate; /* stores current baud rate in integer form */ |
187 |
+ int cbr_mask; /* stores current baud rate in masked form */ |
188 |
+ int isthrottled; /* if throttled, discard reads */ |
189 |
+@@ -532,6 +538,17 @@ static int generic_startup (struct usb_serial *serial) |
190 |
+ priv->termios_initialized = 0; |
191 |
+ priv->rx_flags = 0; |
192 |
+ priv->cbr_mask = B300; |
193 |
++ /* Default packet format setting is determined by packet size. |
194 |
++ Anything with a size larger then 9 must have a separate |
195 |
++ count field since the 3 bit count field is otherwise too |
196 |
++ small. Otherwise we can use the slightly more compact |
197 |
++ format. This is in accordance with the cypress_m8 serial |
198 |
++ converter app note. */ |
199 |
++ if (port->interrupt_out_size > 9) { |
200 |
++ priv->pkt_fmt = packet_format_1; |
201 |
++ } else { |
202 |
++ priv->pkt_fmt = packet_format_2; |
203 |
++ } |
204 |
+ if (interval > 0) { |
205 |
+ priv->write_urb_interval = interval; |
206 |
+ priv->read_urb_interval = interval; |
207 |
+@@ -564,6 +581,9 @@ static int cypress_earthmate_startup (struct usb_serial *serial) |
208 |
+ |
209 |
+ priv = usb_get_serial_port_data(serial->port[0]); |
210 |
+ priv->chiptype = CT_EARTHMATE; |
211 |
++ /* All Earthmate devices use the separated-count packet |
212 |
++ format! Idiotic. */ |
213 |
++ priv->pkt_fmt = packet_format_1; |
214 |
+ |
215 |
+ return 0; |
216 |
+ } /* cypress_earthmate_startup */ |
217 |
+@@ -811,21 +831,18 @@ static void cypress_send(struct usb_serial_port *port) |
218 |
+ memset(port->interrupt_out_urb->transfer_buffer, 0, port->interrupt_out_size); |
219 |
+ |
220 |
+ spin_lock_irqsave(&priv->lock, flags); |
221 |
+- switch (port->interrupt_out_size) { |
222 |
+- case 32: |
223 |
+- /* this is for the CY7C64013... */ |
224 |
+- offset = 2; |
225 |
+- port->interrupt_out_buffer[0] = priv->line_control; |
226 |
+- break; |
227 |
+- case 8: |
228 |
+- /* this is for the CY7C63743... */ |
229 |
+- offset = 1; |
230 |
+- port->interrupt_out_buffer[0] = priv->line_control; |
231 |
+- break; |
232 |
+- default: |
233 |
+- dbg("%s - wrong packet size", __FUNCTION__); |
234 |
+- spin_unlock_irqrestore(&priv->lock, flags); |
235 |
+- return; |
236 |
++ switch (priv->pkt_fmt) { |
237 |
++ default: |
238 |
++ case packet_format_1: |
239 |
++ /* this is for the CY7C64013... */ |
240 |
++ offset = 2; |
241 |
++ port->interrupt_out_buffer[0] = priv->line_control; |
242 |
++ break; |
243 |
++ case packet_format_2: |
244 |
++ /* this is for the CY7C63743... */ |
245 |
++ offset = 1; |
246 |
++ port->interrupt_out_buffer[0] = priv->line_control; |
247 |
++ break; |
248 |
+ } |
249 |
+ |
250 |
+ if (priv->line_control & CONTROL_RESET) |
251 |
+@@ -846,12 +863,13 @@ static void cypress_send(struct usb_serial_port *port) |
252 |
+ return; |
253 |
+ } |
254 |
+ |
255 |
+- switch (port->interrupt_out_size) { |
256 |
+- case 32: |
257 |
+- port->interrupt_out_buffer[1] = count; |
258 |
+- break; |
259 |
+- case 8: |
260 |
+- port->interrupt_out_buffer[0] |= count; |
261 |
++ switch (priv->pkt_fmt) { |
262 |
++ default: |
263 |
++ case packet_format_1: |
264 |
++ port->interrupt_out_buffer[1] = count; |
265 |
++ break; |
266 |
++ case packet_format_2: |
267 |
++ port->interrupt_out_buffer[0] |= count; |
268 |
+ } |
269 |
+ |
270 |
+ dbg("%s - count is %d", __FUNCTION__, count); |
271 |
+@@ -864,8 +882,9 @@ send: |
272 |
+ if (priv->cmd_ctrl) |
273 |
+ actual_size = 1; |
274 |
+ else |
275 |
+- actual_size = count + (port->interrupt_out_size == 32 ? 2 : 1); |
276 |
+- |
277 |
++ actual_size = count + |
278 |
++ (priv->pkt_fmt == packet_format_1 ? 2 : 1); |
279 |
++ |
280 |
+ usb_serial_debug_data(debug, &port->dev, __FUNCTION__, port->interrupt_out_size, |
281 |
+ port->interrupt_out_urb->transfer_buffer); |
282 |
+ |
283 |
+@@ -1331,30 +1350,32 @@ static void cypress_read_int_callback(struct urb *urb) |
284 |
+ } |
285 |
+ |
286 |
+ spin_lock_irqsave(&priv->lock, flags); |
287 |
+- switch(urb->actual_length) { |
288 |
+- case 32: |
289 |
+- /* This is for the CY7C64013... */ |
290 |
+- priv->current_status = data[0] & 0xF8; |
291 |
+- bytes = data[1] + 2; |
292 |
+- i = 2; |
293 |
+- if (bytes > 2) |
294 |
+- havedata = 1; |
295 |
+- break; |
296 |
+- case 8: |
297 |
+- /* This is for the CY7C63743... */ |
298 |
+- priv->current_status = data[0] & 0xF8; |
299 |
+- bytes = (data[0] & 0x07) + 1; |
300 |
+- i = 1; |
301 |
+- if (bytes > 1) |
302 |
+- havedata = 1; |
303 |
+- break; |
304 |
+- default: |
305 |
+- dbg("%s - wrong packet size - received %d bytes", |
306 |
+- __FUNCTION__, urb->actual_length); |
307 |
+- spin_unlock_irqrestore(&priv->lock, flags); |
308 |
+- goto continue_read; |
309 |
++ result = urb->actual_length; |
310 |
++ switch (priv->pkt_fmt) { |
311 |
++ default: |
312 |
++ case packet_format_1: |
313 |
++ /* This is for the CY7C64013... */ |
314 |
++ priv->current_status = data[0] & 0xF8; |
315 |
++ bytes = data[1] + 2; |
316 |
++ i = 2; |
317 |
++ if (bytes > 2) |
318 |
++ havedata = 1; |
319 |
++ break; |
320 |
++ case packet_format_2: |
321 |
++ /* This is for the CY7C63743... */ |
322 |
++ priv->current_status = data[0] & 0xF8; |
323 |
++ bytes = (data[0] & 0x07) + 1; |
324 |
++ i = 1; |
325 |
++ if (bytes > 1) |
326 |
++ havedata = 1; |
327 |
++ break; |
328 |
+ } |
329 |
+ spin_unlock_irqrestore(&priv->lock, flags); |
330 |
++ if (result < bytes) { |
331 |
++ dbg("%s - wrong packet size - received %d bytes but packet " |
332 |
++ "said %d bytes", __func__, result, bytes); |
333 |
++ goto continue_read; |
334 |
++ } |
335 |
+ |
336 |
+ usb_serial_debug_data (debug, &port->dev, __FUNCTION__, |
337 |
+ urb->actual_length, data); |
338 |
+ |
339 |
+From: Mike Isely <isely@×××××.com> |
340 |
+Date: Mon, 11 Feb 2008 02:23:24 +0000 (-0600) |
341 |
+Subject: USB: cypress_m8: Don't issue GET_CONFIG for certain devices |
342 |
+X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftorvalds%2Flinux-2.6.git;a=commitdiff_plain;h=3d6aa3206540e1e68bda9e8ea11ec71444f1ac71 |
343 |
+ |
344 |
+USB: cypress_m8: Don't issue GET_CONFIG for certain devices |
345 |
+ |
346 |
+Earthmate LT-20 devices (both "old" and "new" versions) can't tolerate |
347 |
+a GET_CONFIG command. The original Earthmate has no trouble with |
348 |
+this. Presumably other non-Earthmate devices are still OK as well. |
349 |
+This change disables the use of GET_CONFIG for cases where it is known |
350 |
+not to work. |
351 |
+ |
352 |
+Signed-off-by: Mike Isely <isely@×××××.com> |
353 |
+Signed-off-by: Greg Kroah-Hartman <gregkh@××××.de> |
354 |
+--- |
355 |
+ |
356 |
+diff --git a/drivers/usb/serial/cypress_m8.c b/drivers/usb/serial/cypress_m8.c |
357 |
+index c42d3bd..f0c5d2a 100644 |
358 |
+--- a/drivers/usb/serial/cypress_m8.c |
359 |
++++ b/drivers/usb/serial/cypress_m8.c |
360 |
+@@ -145,6 +145,7 @@ struct cypress_private { |
361 |
+ __u8 current_config; /* stores the current configuration byte */ |
362 |
+ __u8 rx_flags; /* throttling - used from whiteheat/ftdi_sio */ |
363 |
+ enum packet_format pkt_fmt; /* format to use for packet send / receive */ |
364 |
++ int get_cfg_unsafe; /* If true, the CYPRESS_GET_CONFIG is unsafe */ |
365 |
+ int baud_rate; /* stores current baud rate in integer form */ |
366 |
+ int cbr_mask; /* stores current baud rate in masked form */ |
367 |
+ int isthrottled; /* if throttled, discard reads */ |
368 |
+@@ -401,6 +402,12 @@ static int cypress_serial_control (struct usb_serial_port *port, unsigned baud_m |
369 |
+ } |
370 |
+ break; |
371 |
+ case CYPRESS_GET_CONFIG: |
372 |
++ if (priv->get_cfg_unsafe) { |
373 |
++ /* Not implemented for this device, |
374 |
++ and if we try to do it we're likely |
375 |
++ to crash the hardware. */ |
376 |
++ return -ENOTTY; |
377 |
++ } |
378 |
+ dbg("%s - retreiving serial line settings", __FUNCTION__); |
379 |
+ /* set initial values in feature buffer */ |
380 |
+ memset(feature_buffer, 0, sizeof(feature_buffer)); |
381 |
+@@ -570,20 +577,30 @@ static int generic_startup (struct usb_serial *serial) |
382 |
+ static int cypress_earthmate_startup (struct usb_serial *serial) |
383 |
+ { |
384 |
+ struct cypress_private *priv; |
385 |
++ struct usb_serial_port *port = serial->port[0]; |
386 |
+ |
387 |
+ dbg("%s", __FUNCTION__); |
388 |
+ |
389 |
+ if (generic_startup(serial)) { |
390 |
+ dbg("%s - Failed setting up port %d", __FUNCTION__, |
391 |
+- serial->port[0]->number); |
392 |
++ port->number); |
393 |
+ return 1; |
394 |
+ } |
395 |
+ |
396 |
+- priv = usb_get_serial_port_data(serial->port[0]); |
397 |
++ priv = usb_get_serial_port_data(port); |
398 |
+ priv->chiptype = CT_EARTHMATE; |
399 |
+ /* All Earthmate devices use the separated-count packet |
400 |
+ format! Idiotic. */ |
401 |
+ priv->pkt_fmt = packet_format_1; |
402 |
++ if (serial->dev->descriptor.idProduct != PRODUCT_ID_EARTHMATEUSB) { |
403 |
++ /* The old original USB Earthmate seemed able to |
404 |
++ handle GET_CONFIG requests; everything they've |
405 |
++ produced since that time crashes if this command is |
406 |
++ attempted :-( */ |
407 |
++ dbg("%s - Marking this device as unsafe for GET_CONFIG " |
408 |
++ "commands", __func__); |
409 |
++ priv->get_cfg_unsafe = !0; |
410 |
++ } |
411 |
+ |
412 |
+ return 0; |
413 |
+ } /* cypress_earthmate_startup */ |
414 |
+ |
415 |
+From: Mike Isely <isely@×××××.com> |
416 |
+Date: Mon, 11 Feb 2008 02:23:28 +0000 (-0600) |
417 |
+Subject: USB: cypress_m8: Get rid of pointless NULL check |
418 |
+X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftorvalds%2Flinux-2.6.git;a=commitdiff_plain;h=6768306c3d9568bc66dc22f8b863bfbda3e7c4d2 |
419 |
+ |
420 |
+USB: cypress_m8: Get rid of pointless NULL check |
421 |
+ |
422 |
+Remove a NULL check in cypress_m8; the check is useless in this |
423 |
+context because it is referenced earlier in the same code path thus |
424 |
+the kernel would be oops'ed before reaching this point anyway. (And |
425 |
+it's really pointless here anyway; if this pointer somehow is NULL the |
426 |
+driver is going to have serious problems in many other places.) |
427 |
+ |
428 |
+Signed-off-by: Mike Isely <isely@×××××.com> |
429 |
+Signed-off-by: Greg Kroah-Hartman <gregkh@××××.de> |
430 |
+--- |
431 |
+ |
432 |
+diff --git a/drivers/usb/serial/cypress_m8.c b/drivers/usb/serial/cypress_m8.c |
433 |
+index f0c5d2a..bdeda09 100644 |
434 |
+--- a/drivers/usb/serial/cypress_m8.c |
435 |
++++ b/drivers/usb/serial/cypress_m8.c |
436 |
+@@ -1399,13 +1399,11 @@ static void cypress_read_int_callback(struct urb *urb) |
437 |
+ |
438 |
+ spin_lock_irqsave(&priv->lock, flags); |
439 |
+ /* check to see if status has changed */ |
440 |
+- if (priv != NULL) { |
441 |
+- if (priv->current_status != priv->prev_status) { |
442 |
+- priv->diff_status |= priv->current_status ^ |
443 |
+- priv->prev_status; |
444 |
+- wake_up_interruptible(&priv->delta_msr_wait); |
445 |
+- priv->prev_status = priv->current_status; |
446 |
+- } |
447 |
++ if (priv->current_status != priv->prev_status) { |
448 |
++ priv->diff_status |= priv->current_status ^ |
449 |
++ priv->prev_status; |
450 |
++ wake_up_interruptible(&priv->delta_msr_wait); |
451 |
++ priv->prev_status = priv->current_status; |
452 |
+ } |
453 |
+ spin_unlock_irqrestore(&priv->lock, flags); |
454 |
+ |
455 |
+From: Mike Isely <isely@×××××.com> |
456 |
+Date: Mon, 11 Feb 2008 02:23:32 +0000 (-0600) |
457 |
+Subject: USB: cypress_m8: Limit baud rate to <=4800 for USB low speed devices |
458 |
+X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftorvalds%2Flinux-2.6.git;a=commitdiff_plain;h=92983c2121fb46f234add1c36b5e596779899d56 |
459 |
+ |
460 |
+USB: cypress_m8: Limit baud rate to <=4800 for USB low speed devices |
461 |
+ |
462 |
+The cypress app note for the M8 states that for the USB low speed |
463 |
+version of the part, throughput is effectively limited to 800 |
464 |
+bytes/sec. So if we were to try a faster baud rate in such cases then |
465 |
+we risk overrun errors on receive. Best to just identify this case |
466 |
+and limit the rate to 4800 baud or less (by ignoring any request to |
467 |
+set a faster rate). The old baud rate setting code was somewhat |
468 |
+fragile; this change also hopefully makes it easier in the future to |
469 |
+better checking / limiting. |
470 |
+ |
471 |
+Signed-off-by: Mike Isely <isely@×××××.com> |
472 |
+Signed-off-by: Greg Kroah-Hartman <gregkh@××××.de> |
473 |
+--- |
474 |
+ |
475 |
+diff --git a/drivers/usb/serial/cypress_m8.c b/drivers/usb/serial/cypress_m8.c |
476 |
+index bdeda09..4bf45c7 100644 |
477 |
+--- a/drivers/usb/serial/cypress_m8.c |
478 |
++++ b/drivers/usb/serial/cypress_m8.c |
479 |
+@@ -291,6 +291,59 @@ static struct usb_serial_driver cypress_ca42v2_device = { |
480 |
+ *****************************************************************************/ |
481 |
+ |
482 |
+ |
483 |
++static int analyze_baud_rate(struct usb_serial_port *port, unsigned baud_mask) |
484 |
++{ |
485 |
++ int new_rate; |
486 |
++ struct cypress_private *priv; |
487 |
++ priv = usb_get_serial_port_data(port); |
488 |
++ |
489 |
++ /* |
490 |
++ * The general purpose firmware for the Cypress M8 allows for |
491 |
++ * a maximum speed of 57600bps (I have no idea whether DeLorme |
492 |
++ * chose to use the general purpose firmware or not), if you |
493 |
++ * need to modify this speed setting for your own project |
494 |
++ * please add your own chiptype and modify the code likewise. |
495 |
++ * The Cypress HID->COM device will work successfully up to |
496 |
++ * 115200bps (but the actual throughput is around 3kBps). |
497 |
++ */ |
498 |
++ new_rate = mask_to_rate(baud_mask); |
499 |
++ if (new_rate < 0) { |
500 |
++ dbg("%s - failed setting baud rate, untranslatable speed", |
501 |
++ __func__); |
502 |
++ return -1; |
503 |
++ } |
504 |
++ if (port->serial->dev->speed == USB_SPEED_LOW) { |
505 |
++ /* |
506 |
++ * Mike Isely <isely@×××××.com> 2-Feb-2008: The |
507 |
++ * Cypress app note that describes this mechanism |
508 |
++ * states the the low-speed part can't handle more |
509 |
++ * than 800 bytes/sec, in which case 4800 baud is the |
510 |
++ * safest speed for a part like that. |
511 |
++ */ |
512 |
++ if (new_rate > 4800) { |
513 |
++ dbg("%s - failed setting baud rate, device incapable " |
514 |
++ "speed %d", __func__, new_rate); |
515 |
++ return -1; |
516 |
++ } |
517 |
++ } |
518 |
++ switch (priv->chiptype) { |
519 |
++ case CT_EARTHMATE: |
520 |
++ if (new_rate <= 600) { |
521 |
++ /* 300 and 600 baud rates are supported under |
522 |
++ * the generic firmware, but are not used with |
523 |
++ * NMEA and SiRF protocols */ |
524 |
++ dbg("%s - failed setting baud rate, unsupported speed " |
525 |
++ "of %d on Earthmate GPS", __func__, new_rate); |
526 |
++ return -1; |
527 |
++ } |
528 |
++ break; |
529 |
++ default: |
530 |
++ break; |
531 |
++ } |
532 |
++ return new_rate; |
533 |
++} |
534 |
++ |
535 |
++ |
536 |
+ /* This function can either set or retrieve the current serial line settings */ |
537 |
+ static int cypress_serial_control (struct usb_serial_port *port, unsigned baud_mask, int data_bits, int stop_bits, |
538 |
+ int parity_enable, int parity_type, int reset, int cypress_request_type) |
539 |
+@@ -309,54 +362,15 @@ static int cypress_serial_control (struct usb_serial_port *port, unsigned baud_m |
540 |
+ |
541 |
+ switch(cypress_request_type) { |
542 |
+ case CYPRESS_SET_CONFIG: |
543 |
+- |
544 |
+- /* |
545 |
+- * The general purpose firmware for the Cypress M8 allows for a maximum speed |
546 |
+- * of 57600bps (I have no idea whether DeLorme chose to use the general purpose |
547 |
+- * firmware or not), if you need to modify this speed setting for your own |
548 |
+- * project please add your own chiptype and modify the code likewise. The |
549 |
+- * Cypress HID->COM device will work successfully up to 115200bps (but the |
550 |
+- * actual throughput is around 3kBps). |
551 |
+- */ |
552 |
++ new_baudrate = priv->baud_rate; |
553 |
+ if (baud_mask != priv->cbr_mask) { |
554 |
+ dbg("%s - baud rate is changing", __FUNCTION__); |
555 |
+- if ( priv->chiptype == CT_EARTHMATE ) { |
556 |
+- /* 300 and 600 baud rates are supported under the generic firmware, |
557 |
+- * but are not used with NMEA and SiRF protocols */ |
558 |
+- |
559 |
+- if ( (baud_mask == B300) || (baud_mask == B600) ) { |
560 |
+- err("%s - failed setting baud rate, unsupported speed", |
561 |
+- __FUNCTION__); |
562 |
+- new_baudrate = priv->baud_rate; |
563 |
+- } else if ( (new_baudrate = mask_to_rate(baud_mask)) == -1) { |
564 |
+- err("%s - failed setting baud rate, unsupported speed", |
565 |
+- __FUNCTION__); |
566 |
+- new_baudrate = priv->baud_rate; |
567 |
+- } |
568 |
+- } else if (priv->chiptype == CT_CYPHIDCOM) { |
569 |
+- if ( (new_baudrate = mask_to_rate(baud_mask)) == -1) { |
570 |
+- err("%s - failed setting baud rate, unsupported speed", |
571 |
+- __FUNCTION__); |
572 |
+- new_baudrate = priv->baud_rate; |
573 |
+- } |
574 |
+- } else if (priv->chiptype == CT_CA42V2) { |
575 |
+- if ( (new_baudrate = mask_to_rate(baud_mask)) == -1) { |
576 |
+- err("%s - failed setting baud rate, unsupported speed", |
577 |
+- __FUNCTION__); |
578 |
+- new_baudrate = priv->baud_rate; |
579 |
+- } |
580 |
+- } else if (priv->chiptype == CT_GENERIC) { |
581 |
+- if ( (new_baudrate = mask_to_rate(baud_mask)) == -1) { |
582 |
+- err("%s - failed setting baud rate, unsupported speed", |
583 |
+- __FUNCTION__); |
584 |
+- new_baudrate = priv->baud_rate; |
585 |
+- } |
586 |
+- } else { |
587 |
+- info("%s - please define your chiptype", __FUNCTION__); |
588 |
+- new_baudrate = priv->baud_rate; |
589 |
++ retval = analyze_baud_rate(port, baud_mask); |
590 |
++ if (retval >= 0) { |
591 |
++ new_baudrate = retval; |
592 |
++ dbg("%s - New baud rate set to %d", |
593 |
++ __func__, new_baudrate); |
594 |
+ } |
595 |
+- } else { /* baud rate not changing, keep the old */ |
596 |
+- new_baudrate = priv->baud_rate; |
597 |
+ } |
598 |
+ dbg("%s - baud rate is being sent as %d", __FUNCTION__, new_baudrate); |
599 |
+ |
600 |
+ |
601 |
|
602 |
-- |
603 |
gentoo-commits@l.g.o mailing list |