diff options
Diffstat (limited to 'drivers/usb/serial/sierra.c')
-rw-r--r-- | drivers/usb/serial/sierra.c | 371 |
1 files changed, 159 insertions, 212 deletions
diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c index ac1829c6e8f0..e7db20343d1a 100644 --- a/drivers/usb/serial/sierra.c +++ b/drivers/usb/serial/sierra.c | |||
@@ -86,15 +86,14 @@ static int debug; | |||
86 | #define N_IN_URB 4 | 86 | #define N_IN_URB 4 |
87 | #define N_OUT_URB 4 | 87 | #define N_OUT_URB 4 |
88 | #define IN_BUFLEN 4096 | 88 | #define IN_BUFLEN 4096 |
89 | #define OUT_BUFLEN 128 | ||
90 | 89 | ||
91 | struct sierra_port_private { | 90 | struct sierra_port_private { |
91 | spinlock_t lock; /* lock the structure */ | ||
92 | int outstanding_urbs; /* number of out urbs in flight */ | ||
93 | |||
92 | /* Input endpoints and buffer for this port */ | 94 | /* Input endpoints and buffer for this port */ |
93 | struct urb *in_urbs[N_IN_URB]; | 95 | struct urb *in_urbs[N_IN_URB]; |
94 | char in_buffer[N_IN_URB][IN_BUFLEN]; | 96 | char in_buffer[N_IN_URB][IN_BUFLEN]; |
95 | /* Output endpoints and buffer for this port */ | ||
96 | struct urb *out_urbs[N_OUT_URB]; | ||
97 | char out_buffer[N_OUT_URB][OUT_BUFLEN]; | ||
98 | 97 | ||
99 | /* Settings for the port */ | 98 | /* Settings for the port */ |
100 | int rts_state; /* Handshaking pins (outputs) */ | 99 | int rts_state; /* Handshaking pins (outputs) */ |
@@ -103,8 +102,6 @@ struct sierra_port_private { | |||
103 | int dsr_state; | 102 | int dsr_state; |
104 | int dcd_state; | 103 | int dcd_state; |
105 | int ri_state; | 104 | int ri_state; |
106 | |||
107 | unsigned long tx_start_time[N_OUT_URB]; | ||
108 | }; | 105 | }; |
109 | 106 | ||
110 | static int sierra_send_setup(struct usb_serial_port *port) | 107 | static int sierra_send_setup(struct usb_serial_port *port) |
@@ -197,61 +194,98 @@ static int sierra_ioctl(struct usb_serial_port *port, struct file *file, | |||
197 | return -ENOIOCTLCMD; | 194 | return -ENOIOCTLCMD; |
198 | } | 195 | } |
199 | 196 | ||
197 | static void sierra_outdat_callback(struct urb *urb) | ||
198 | { | ||
199 | struct usb_serial_port *port = urb->context; | ||
200 | struct sierra_port_private *portdata = usb_get_serial_port_data(port); | ||
201 | int status = urb->status; | ||
202 | unsigned long flags; | ||
203 | |||
204 | dbg("%s - port %d", __FUNCTION__, port->number); | ||
205 | |||
206 | /* free up the transfer buffer, as usb_free_urb() does not do this */ | ||
207 | kfree(urb->transfer_buffer); | ||
208 | |||
209 | if (status) | ||
210 | dbg("%s - nonzero write bulk status received: %d", | ||
211 | __FUNCTION__, status); | ||
212 | |||
213 | spin_lock_irqsave(&portdata->lock, flags); | ||
214 | --portdata->outstanding_urbs; | ||
215 | spin_unlock_irqrestore(&portdata->lock, flags); | ||
216 | |||
217 | usb_serial_port_softint(port); | ||
218 | } | ||
219 | |||
200 | /* Write */ | 220 | /* Write */ |
201 | static int sierra_write(struct usb_serial_port *port, | 221 | static int sierra_write(struct usb_serial_port *port, |
202 | const unsigned char *buf, int count) | 222 | const unsigned char *buf, int count) |
203 | { | 223 | { |
204 | struct sierra_port_private *portdata; | 224 | struct sierra_port_private *portdata = usb_get_serial_port_data(port); |
205 | int i; | 225 | struct usb_serial *serial = port->serial; |
206 | int left, todo; | 226 | unsigned long flags; |
207 | struct urb *this_urb = NULL; /* spurious */ | 227 | unsigned char *buffer; |
208 | int err; | 228 | struct urb *urb; |
229 | int status; | ||
209 | 230 | ||
210 | portdata = usb_get_serial_port_data(port); | 231 | portdata = usb_get_serial_port_data(port); |
211 | 232 | ||
212 | dbg("%s: write (%d chars)", __FUNCTION__, count); | 233 | dbg("%s: write (%d chars)", __FUNCTION__, count); |
213 | 234 | ||
214 | i = 0; | 235 | spin_lock_irqsave(&portdata->lock, flags); |
215 | left = count; | 236 | if (portdata->outstanding_urbs > N_OUT_URB) { |
216 | for (i=0; left > 0 && i < N_OUT_URB; i++) { | 237 | spin_unlock_irqrestore(&portdata->lock, flags); |
217 | todo = left; | 238 | dbg("%s - write limit hit\n", __FUNCTION__); |
218 | if (todo > OUT_BUFLEN) | 239 | return 0; |
219 | todo = OUT_BUFLEN; | 240 | } |
220 | 241 | portdata->outstanding_urbs++; | |
221 | this_urb = portdata->out_urbs[i]; | 242 | spin_unlock_irqrestore(&portdata->lock, flags); |
222 | if (this_urb->status == -EINPROGRESS) { | 243 | |
223 | if (time_before(jiffies, | 244 | buffer = kmalloc(count, GFP_ATOMIC); |
224 | portdata->tx_start_time[i] + 10 * HZ)) | 245 | if (!buffer) { |
225 | continue; | 246 | dev_err(&port->dev, "out of memory\n"); |
226 | usb_unlink_urb(this_urb); | 247 | count = -ENOMEM; |
227 | continue; | 248 | goto error_no_buffer; |
228 | } | 249 | } |
229 | if (this_urb->status != 0) | 250 | |
230 | dbg("usb_write %p failed (err=%d)", | 251 | urb = usb_alloc_urb(0, GFP_ATOMIC); |
231 | this_urb, this_urb->status); | 252 | if (!urb) { |
232 | 253 | dev_err(&port->dev, "no more free urbs\n"); | |
233 | dbg("%s: endpoint %d buf %d", __FUNCTION__, | 254 | count = -ENOMEM; |
234 | usb_pipeendpoint(this_urb->pipe), i); | 255 | goto error_no_urb; |
235 | 256 | } | |
236 | /* send the data */ | 257 | |
237 | memcpy (this_urb->transfer_buffer, buf, todo); | 258 | memcpy(buffer, buf, count); |
238 | this_urb->transfer_buffer_length = todo; | 259 | |
239 | 260 | usb_serial_debug_data(debug, &port->dev, __FUNCTION__, count, buffer); | |
240 | this_urb->dev = port->serial->dev; | 261 | |
241 | err = usb_submit_urb(this_urb, GFP_ATOMIC); | 262 | usb_fill_bulk_urb(urb, serial->dev, |
242 | if (err) { | 263 | usb_sndbulkpipe(serial->dev, |
243 | dbg("usb_submit_urb %p (write bulk) failed " | 264 | port->bulk_out_endpointAddress), |
244 | "(%d, has %d)", this_urb, | 265 | buffer, count, sierra_outdat_callback, port); |
245 | err, this_urb->status); | 266 | |
246 | continue; | 267 | /* send it down the pipe */ |
247 | } | 268 | status = usb_submit_urb(urb, GFP_ATOMIC); |
248 | portdata->tx_start_time[i] = jiffies; | 269 | if (status) { |
249 | buf += todo; | 270 | dev_err(&port->dev, "%s - usb_submit_urb(write bulk) failed " |
250 | left -= todo; | 271 | "with status = %d\n", __FUNCTION__, status); |
272 | count = status; | ||
273 | goto error; | ||
251 | } | 274 | } |
252 | 275 | ||
253 | count -= left; | 276 | /* we are done with this urb, so let the host driver |
254 | dbg("%s: wrote (did %d)", __FUNCTION__, count); | 277 | * really free it when it is finished with it */ |
278 | usb_free_urb(urb); | ||
279 | |||
280 | return count; | ||
281 | error: | ||
282 | usb_free_urb(urb); | ||
283 | error_no_urb: | ||
284 | kfree(buffer); | ||
285 | error_no_buffer: | ||
286 | spin_lock_irqsave(&portdata->lock, flags); | ||
287 | --portdata->outstanding_urbs; | ||
288 | spin_unlock_irqrestore(&portdata->lock, flags); | ||
255 | return count; | 289 | return count; |
256 | } | 290 | } |
257 | 291 | ||
@@ -262,15 +296,16 @@ static void sierra_indat_callback(struct urb *urb) | |||
262 | struct usb_serial_port *port; | 296 | struct usb_serial_port *port; |
263 | struct tty_struct *tty; | 297 | struct tty_struct *tty; |
264 | unsigned char *data = urb->transfer_buffer; | 298 | unsigned char *data = urb->transfer_buffer; |
299 | int status = urb->status; | ||
265 | 300 | ||
266 | dbg("%s: %p", __FUNCTION__, urb); | 301 | dbg("%s: %p", __FUNCTION__, urb); |
267 | 302 | ||
268 | endpoint = usb_pipeendpoint(urb->pipe); | 303 | endpoint = usb_pipeendpoint(urb->pipe); |
269 | port = (struct usb_serial_port *) urb->context; | 304 | port = (struct usb_serial_port *) urb->context; |
270 | 305 | ||
271 | if (urb->status) { | 306 | if (status) { |
272 | dbg("%s: nonzero status: %d on endpoint %02x.", | 307 | dbg("%s: nonzero status: %d on endpoint %02x.", |
273 | __FUNCTION__, urb->status, endpoint); | 308 | __FUNCTION__, status, endpoint); |
274 | } else { | 309 | } else { |
275 | tty = port->tty; | 310 | tty = port->tty; |
276 | if (urb->actual_length) { | 311 | if (urb->actual_length) { |
@@ -282,30 +317,20 @@ static void sierra_indat_callback(struct urb *urb) | |||
282 | } | 317 | } |
283 | 318 | ||
284 | /* Resubmit urb so we continue receiving */ | 319 | /* Resubmit urb so we continue receiving */ |
285 | if (port->open_count && urb->status != -ESHUTDOWN) { | 320 | if (port->open_count && status != -ESHUTDOWN) { |
286 | err = usb_submit_urb(urb, GFP_ATOMIC); | 321 | err = usb_submit_urb(urb, GFP_ATOMIC); |
287 | if (err) | 322 | if (err) |
288 | printk(KERN_ERR "%s: resubmit read urb failed. " | 323 | dev_err(&port->dev, "resubmit read urb failed." |
289 | "(%d)", __FUNCTION__, err); | 324 | "(%d)", err); |
290 | } | 325 | } |
291 | } | 326 | } |
292 | return; | 327 | return; |
293 | } | 328 | } |
294 | 329 | ||
295 | static void sierra_outdat_callback(struct urb *urb) | ||
296 | { | ||
297 | struct usb_serial_port *port; | ||
298 | |||
299 | dbg("%s", __FUNCTION__); | ||
300 | |||
301 | port = (struct usb_serial_port *) urb->context; | ||
302 | |||
303 | usb_serial_port_softint(port); | ||
304 | } | ||
305 | |||
306 | static void sierra_instat_callback(struct urb *urb) | 330 | static void sierra_instat_callback(struct urb *urb) |
307 | { | 331 | { |
308 | int err; | 332 | int err; |
333 | int status = urb->status; | ||
309 | struct usb_serial_port *port = (struct usb_serial_port *) urb->context; | 334 | struct usb_serial_port *port = (struct usb_serial_port *) urb->context; |
310 | struct sierra_port_private *portdata = usb_get_serial_port_data(port); | 335 | struct sierra_port_private *portdata = usb_get_serial_port_data(port); |
311 | struct usb_serial *serial = port->serial; | 336 | struct usb_serial *serial = port->serial; |
@@ -313,7 +338,7 @@ static void sierra_instat_callback(struct urb *urb) | |||
313 | dbg("%s", __FUNCTION__); | 338 | dbg("%s", __FUNCTION__); |
314 | dbg("%s: urb %p port %p has data %p", __FUNCTION__,urb,port,portdata); | 339 | dbg("%s: urb %p port %p has data %p", __FUNCTION__,urb,port,portdata); |
315 | 340 | ||
316 | if (urb->status == 0) { | 341 | if (status == 0) { |
317 | struct usb_ctrlrequest *req_pkt = | 342 | struct usb_ctrlrequest *req_pkt = |
318 | (struct usb_ctrlrequest *)urb->transfer_buffer; | 343 | (struct usb_ctrlrequest *)urb->transfer_buffer; |
319 | 344 | ||
@@ -344,10 +369,10 @@ static void sierra_instat_callback(struct urb *urb) | |||
344 | req_pkt->bRequestType,req_pkt->bRequest); | 369 | req_pkt->bRequestType,req_pkt->bRequest); |
345 | } | 370 | } |
346 | } else | 371 | } else |
347 | dbg("%s: error %d", __FUNCTION__, urb->status); | 372 | dbg("%s: error %d", __FUNCTION__, status); |
348 | 373 | ||
349 | /* Resubmit urb so we continue receiving IRQ data */ | 374 | /* Resubmit urb so we continue receiving IRQ data */ |
350 | if (urb->status != -ESHUTDOWN) { | 375 | if (status != -ESHUTDOWN) { |
351 | urb->dev = serial->dev; | 376 | urb->dev = serial->dev; |
352 | err = usb_submit_urb(urb, GFP_ATOMIC); | 377 | err = usb_submit_urb(urb, GFP_ATOMIC); |
353 | if (err) | 378 | if (err) |
@@ -358,46 +383,42 @@ static void sierra_instat_callback(struct urb *urb) | |||
358 | 383 | ||
359 | static int sierra_write_room(struct usb_serial_port *port) | 384 | static int sierra_write_room(struct usb_serial_port *port) |
360 | { | 385 | { |
361 | struct sierra_port_private *portdata; | 386 | struct sierra_port_private *portdata = usb_get_serial_port_data(port); |
362 | int i; | 387 | unsigned long flags; |
363 | int data_len = 0; | ||
364 | struct urb *this_urb; | ||
365 | 388 | ||
366 | portdata = usb_get_serial_port_data(port); | 389 | dbg("%s - port %d", __FUNCTION__, port->number); |
367 | 390 | ||
368 | for (i=0; i < N_OUT_URB; i++) { | 391 | /* try to give a good number back based on if we have any free urbs at |
369 | this_urb = portdata->out_urbs[i]; | 392 | * this point in time */ |
370 | if (this_urb && this_urb->status != -EINPROGRESS) | 393 | spin_lock_irqsave(&portdata->lock, flags); |
371 | data_len += OUT_BUFLEN; | 394 | if (portdata->outstanding_urbs > N_OUT_URB * 2 / 3) { |
395 | spin_unlock_irqrestore(&portdata->lock, flags); | ||
396 | dbg("%s - write limit hit\n", __FUNCTION__); | ||
397 | return 0; | ||
372 | } | 398 | } |
399 | spin_unlock_irqrestore(&portdata->lock, flags); | ||
373 | 400 | ||
374 | dbg("%s: %d", __FUNCTION__, data_len); | 401 | return 2048; |
375 | return data_len; | ||
376 | } | 402 | } |
377 | 403 | ||
378 | static int sierra_chars_in_buffer(struct usb_serial_port *port) | 404 | static int sierra_chars_in_buffer(struct usb_serial_port *port) |
379 | { | 405 | { |
380 | struct sierra_port_private *portdata; | 406 | dbg("%s - port %d", __FUNCTION__, port->number); |
381 | int i; | 407 | |
382 | int data_len = 0; | 408 | /* |
383 | struct urb *this_urb; | 409 | * We can't really account for how much data we |
384 | 410 | * have sent out, but hasn't made it through to the | |
385 | portdata = usb_get_serial_port_data(port); | 411 | * device as we can't see the backend here, so just |
386 | 412 | * tell the tty layer that everything is flushed. | |
387 | for (i=0; i < N_OUT_URB; i++) { | 413 | */ |
388 | this_urb = portdata->out_urbs[i]; | 414 | return 0; |
389 | if (this_urb && this_urb->status == -EINPROGRESS) | ||
390 | data_len += this_urb->transfer_buffer_length; | ||
391 | } | ||
392 | dbg("%s: %d", __FUNCTION__, data_len); | ||
393 | return data_len; | ||
394 | } | 415 | } |
395 | 416 | ||
396 | static int sierra_open(struct usb_serial_port *port, struct file *filp) | 417 | static int sierra_open(struct usb_serial_port *port, struct file *filp) |
397 | { | 418 | { |
398 | struct sierra_port_private *portdata; | 419 | struct sierra_port_private *portdata; |
399 | struct usb_serial *serial = port->serial; | 420 | struct usb_serial *serial = port->serial; |
400 | int i, err; | 421 | int i; |
401 | struct urb *urb; | 422 | struct urb *urb; |
402 | int result; | 423 | int result; |
403 | __u16 set_mode_dzero = 0x0000; | 424 | __u16 set_mode_dzero = 0x0000; |
@@ -413,7 +434,7 @@ static int sierra_open(struct usb_serial_port *port, struct file *filp) | |||
413 | /* Reset low level data toggle and start reading from endpoints */ | 434 | /* Reset low level data toggle and start reading from endpoints */ |
414 | for (i = 0; i < N_IN_URB; i++) { | 435 | for (i = 0; i < N_IN_URB; i++) { |
415 | urb = portdata->in_urbs[i]; | 436 | urb = portdata->in_urbs[i]; |
416 | if (! urb) | 437 | if (!urb) |
417 | continue; | 438 | continue; |
418 | if (urb->dev != serial->dev) { | 439 | if (urb->dev != serial->dev) { |
419 | dbg("%s: dev %p != %p", __FUNCTION__, | 440 | dbg("%s: dev %p != %p", __FUNCTION__, |
@@ -427,24 +448,13 @@ static int sierra_open(struct usb_serial_port *port, struct file *filp) | |||
427 | */ | 448 | */ |
428 | usb_clear_halt(urb->dev, urb->pipe); | 449 | usb_clear_halt(urb->dev, urb->pipe); |
429 | 450 | ||
430 | err = usb_submit_urb(urb, GFP_KERNEL); | 451 | result = usb_submit_urb(urb, GFP_KERNEL); |
431 | if (err) { | 452 | if (result) { |
432 | dbg("%s: submit urb %d failed (%d) %d", | 453 | dev_err(&port->dev, "submit urb %d failed (%d) %d", |
433 | __FUNCTION__, i, err, | 454 | i, result, urb->transfer_buffer_length); |
434 | urb->transfer_buffer_length); | ||
435 | } | 455 | } |
436 | } | 456 | } |
437 | 457 | ||
438 | /* Reset low level data toggle on out endpoints */ | ||
439 | for (i = 0; i < N_OUT_URB; i++) { | ||
440 | urb = portdata->out_urbs[i]; | ||
441 | if (! urb) | ||
442 | continue; | ||
443 | urb->dev = serial->dev; | ||
444 | /* usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe), | ||
445 | usb_pipeout(urb->pipe), 0); */ | ||
446 | } | ||
447 | |||
448 | port->tty->low_latency = 1; | 458 | port->tty->low_latency = 1; |
449 | 459 | ||
450 | /* set mode to D0 */ | 460 | /* set mode to D0 */ |
@@ -455,7 +465,14 @@ static int sierra_open(struct usb_serial_port *port, struct file *filp) | |||
455 | 465 | ||
456 | sierra_send_setup(port); | 466 | sierra_send_setup(port); |
457 | 467 | ||
458 | return (0); | 468 | /* start up the interrupt endpoint if we have one */ |
469 | if (port->interrupt_in_urb) { | ||
470 | result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL); | ||
471 | if (result) | ||
472 | dev_err(&port->dev, "submit irq_in urb failed %d", | ||
473 | result); | ||
474 | } | ||
475 | return 0; | ||
459 | } | 476 | } |
460 | 477 | ||
461 | static void sierra_close(struct usb_serial_port *port, struct file *filp) | 478 | static void sierra_close(struct usb_serial_port *port, struct file *filp) |
@@ -475,71 +492,21 @@ static void sierra_close(struct usb_serial_port *port, struct file *filp) | |||
475 | 492 | ||
476 | /* Stop reading/writing urbs */ | 493 | /* Stop reading/writing urbs */ |
477 | for (i = 0; i < N_IN_URB; i++) | 494 | for (i = 0; i < N_IN_URB; i++) |
478 | usb_unlink_urb(portdata->in_urbs[i]); | 495 | usb_kill_urb(portdata->in_urbs[i]); |
479 | for (i = 0; i < N_OUT_URB; i++) | ||
480 | usb_unlink_urb(portdata->out_urbs[i]); | ||
481 | } | 496 | } |
482 | port->tty = NULL; | ||
483 | } | ||
484 | |||
485 | /* Helper functions used by sierra_setup_urbs */ | ||
486 | static struct urb *sierra_setup_urb(struct usb_serial *serial, int endpoint, | ||
487 | int dir, void *ctx, char *buf, int len, | ||
488 | usb_complete_t callback) | ||
489 | { | ||
490 | struct urb *urb; | ||
491 | |||
492 | if (endpoint == -1) | ||
493 | return NULL; /* endpoint not needed */ | ||
494 | |||
495 | urb = usb_alloc_urb(0, GFP_KERNEL); /* No ISO */ | ||
496 | if (urb == NULL) { | ||
497 | dbg("%s: alloc for endpoint %d failed.", __FUNCTION__, endpoint); | ||
498 | return NULL; | ||
499 | } | ||
500 | |||
501 | /* Fill URB using supplied data. */ | ||
502 | usb_fill_bulk_urb(urb, serial->dev, | ||
503 | usb_sndbulkpipe(serial->dev, endpoint) | dir, | ||
504 | buf, len, callback, ctx); | ||
505 | |||
506 | return urb; | ||
507 | } | ||
508 | 497 | ||
509 | /* Setup urbs */ | 498 | usb_kill_urb(port->interrupt_in_urb); |
510 | static void sierra_setup_urbs(struct usb_serial *serial) | ||
511 | { | ||
512 | int i,j; | ||
513 | struct usb_serial_port *port; | ||
514 | struct sierra_port_private *portdata; | ||
515 | |||
516 | dbg("%s", __FUNCTION__); | ||
517 | 499 | ||
518 | for (i = 0; i < serial->num_ports; i++) { | 500 | port->tty = NULL; |
519 | port = serial->port[i]; | ||
520 | portdata = usb_get_serial_port_data(port); | ||
521 | |||
522 | /* Do indat endpoints first */ | ||
523 | for (j = 0; j < N_IN_URB; ++j) { | ||
524 | portdata->in_urbs[j] = sierra_setup_urb (serial, | ||
525 | port->bulk_in_endpointAddress, USB_DIR_IN, port, | ||
526 | portdata->in_buffer[j], IN_BUFLEN, sierra_indat_callback); | ||
527 | } | ||
528 | |||
529 | /* outdat endpoints */ | ||
530 | for (j = 0; j < N_OUT_URB; ++j) { | ||
531 | portdata->out_urbs[j] = sierra_setup_urb (serial, | ||
532 | port->bulk_out_endpointAddress, USB_DIR_OUT, port, | ||
533 | portdata->out_buffer[j], OUT_BUFLEN, sierra_outdat_callback); | ||
534 | } | ||
535 | } | ||
536 | } | 501 | } |
537 | 502 | ||
538 | static int sierra_startup(struct usb_serial *serial) | 503 | static int sierra_startup(struct usb_serial *serial) |
539 | { | 504 | { |
540 | int i, err; | ||
541 | struct usb_serial_port *port; | 505 | struct usb_serial_port *port; |
542 | struct sierra_port_private *portdata; | 506 | struct sierra_port_private *portdata; |
507 | struct urb *urb; | ||
508 | int i; | ||
509 | int j; | ||
543 | 510 | ||
544 | dbg("%s", __FUNCTION__); | 511 | dbg("%s", __FUNCTION__); |
545 | 512 | ||
@@ -550,22 +517,31 @@ static int sierra_startup(struct usb_serial *serial) | |||
550 | if (!portdata) { | 517 | if (!portdata) { |
551 | dbg("%s: kmalloc for sierra_port_private (%d) failed!.", | 518 | dbg("%s: kmalloc for sierra_port_private (%d) failed!.", |
552 | __FUNCTION__, i); | 519 | __FUNCTION__, i); |
553 | return (1); | 520 | return -ENOMEM; |
554 | } | 521 | } |
522 | spin_lock_init(&portdata->lock); | ||
555 | 523 | ||
556 | usb_set_serial_port_data(port, portdata); | 524 | usb_set_serial_port_data(port, portdata); |
557 | 525 | ||
558 | if (! port->interrupt_in_urb) | 526 | /* initialize the in urbs */ |
559 | continue; | 527 | for (j = 0; j < N_IN_URB; ++j) { |
560 | err = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL); | 528 | urb = usb_alloc_urb(0, GFP_KERNEL); |
561 | if (err) | 529 | if (urb == NULL) { |
562 | dbg("%s: submit irq_in urb failed %d", | 530 | dbg("%s: alloc for in port failed.", |
563 | __FUNCTION__, err); | 531 | __FUNCTION__); |
532 | continue; | ||
533 | } | ||
534 | /* Fill URB using supplied data. */ | ||
535 | usb_fill_bulk_urb(urb, serial->dev, | ||
536 | usb_rcvbulkpipe(serial->dev, | ||
537 | port->bulk_in_endpointAddress), | ||
538 | portdata->in_buffer[j], IN_BUFLEN, | ||
539 | sierra_indat_callback, port); | ||
540 | portdata->in_urbs[j] = urb; | ||
541 | } | ||
564 | } | 542 | } |
565 | 543 | ||
566 | sierra_setup_urbs(serial); | 544 | return 0; |
567 | |||
568 | return (0); | ||
569 | } | 545 | } |
570 | 546 | ||
571 | static void sierra_shutdown(struct usb_serial *serial) | 547 | static void sierra_shutdown(struct usb_serial *serial) |
@@ -576,22 +552,6 @@ static void sierra_shutdown(struct usb_serial *serial) | |||
576 | 552 | ||
577 | dbg("%s", __FUNCTION__); | 553 | dbg("%s", __FUNCTION__); |
578 | 554 | ||
579 | /* Stop reading/writing urbs */ | ||
580 | for (i = 0; i < serial->num_ports; ++i) { | ||
581 | port = serial->port[i]; | ||
582 | if (!port) | ||
583 | continue; | ||
584 | portdata = usb_get_serial_port_data(port); | ||
585 | if (!portdata) | ||
586 | continue; | ||
587 | |||
588 | for (j = 0; j < N_IN_URB; j++) | ||
589 | usb_unlink_urb(portdata->in_urbs[j]); | ||
590 | for (j = 0; j < N_OUT_URB; j++) | ||
591 | usb_unlink_urb(portdata->out_urbs[j]); | ||
592 | } | ||
593 | |||
594 | /* Now free them */ | ||
595 | for (i = 0; i < serial->num_ports; ++i) { | 555 | for (i = 0; i < serial->num_ports; ++i) { |
596 | port = serial->port[i]; | 556 | port = serial->port[i]; |
597 | if (!port) | 557 | if (!port) |
@@ -601,25 +561,12 @@ static void sierra_shutdown(struct usb_serial *serial) | |||
601 | continue; | 561 | continue; |
602 | 562 | ||
603 | for (j = 0; j < N_IN_URB; j++) { | 563 | for (j = 0; j < N_IN_URB; j++) { |
604 | if (portdata->in_urbs[j]) { | 564 | usb_kill_urb(portdata->in_urbs[j]); |
605 | usb_free_urb(portdata->in_urbs[j]); | 565 | usb_free_urb(portdata->in_urbs[j]); |
606 | portdata->in_urbs[j] = NULL; | 566 | portdata->in_urbs[j] = NULL; |
607 | } | ||
608 | } | 567 | } |
609 | for (j = 0; j < N_OUT_URB; j++) { | 568 | kfree(portdata); |
610 | if (portdata->out_urbs[j]) { | 569 | usb_set_serial_port_data(port, NULL); |
611 | usb_free_urb(portdata->out_urbs[j]); | ||
612 | portdata->out_urbs[j] = NULL; | ||
613 | } | ||
614 | } | ||
615 | } | ||
616 | |||
617 | /* Now free per port private data */ | ||
618 | for (i = 0; i < serial->num_ports; i++) { | ||
619 | port = serial->port[i]; | ||
620 | if (!port) | ||
621 | continue; | ||
622 | kfree(usb_get_serial_port_data(port)); | ||
623 | } | 570 | } |
624 | } | 571 | } |
625 | 572 | ||