Lines Matching +full:poll +full:- +full:retry +full:- +full:count
1 // SPDX-License-Identifier: GPL-2.0
3 * cdc-wdm.c
7 * Copyright (c) 2007-2009 Oliver Neukum
9 * Some code taken from cdc-acm.c
23 #include <linux/poll.h>
30 #include <linux/usb/cdc-wdm.h>
67 /* CDC-WMC r1.1 requires wMaxCommand to be "at least 256 decimal (0x100)" */
74 /* --- method tables --- */
98 int count; member
126 if (desc->intf == intf) in wdm_find_device()
141 if (desc->intf->minor == minor) in wdm_find_device_by_minor()
150 /* --- callbacks --- */
156 desc = urb->context; in wdm_out_callback()
157 spin_lock_irqsave(&desc->iuspin, flags); in wdm_out_callback()
158 desc->werr = urb->status; in wdm_out_callback()
159 spin_unlock_irqrestore(&desc->iuspin, flags); in wdm_out_callback()
160 kfree(desc->outbuf); in wdm_out_callback()
161 desc->outbuf = NULL; in wdm_out_callback()
162 clear_bit(WDM_IN_USE, &desc->flags); in wdm_out_callback()
163 wake_up_all(&desc->wait); in wdm_out_callback()
171 struct wdm_device *desc = urb->context; in wdm_in_callback()
172 int status = urb->status; in wdm_in_callback()
173 int length = urb->actual_length; in wdm_in_callback()
175 spin_lock_irqsave(&desc->iuspin, flags); in wdm_in_callback()
176 clear_bit(WDM_RESPONDING, &desc->flags); in wdm_in_callback()
180 case -ENOENT: in wdm_in_callback()
181 dev_dbg(&desc->intf->dev, in wdm_in_callback()
182 "nonzero urb status received: -ENOENT\n"); in wdm_in_callback()
184 case -ECONNRESET: in wdm_in_callback()
185 dev_dbg(&desc->intf->dev, in wdm_in_callback()
186 "nonzero urb status received: -ECONNRESET\n"); in wdm_in_callback()
188 case -ESHUTDOWN: in wdm_in_callback()
189 dev_dbg(&desc->intf->dev, in wdm_in_callback()
190 "nonzero urb status received: -ESHUTDOWN\n"); in wdm_in_callback()
192 case -EPIPE: in wdm_in_callback()
193 dev_err(&desc->intf->dev, in wdm_in_callback()
194 "nonzero urb status received: -EPIPE\n"); in wdm_in_callback()
197 dev_err(&desc->intf->dev, in wdm_in_callback()
203 if (test_bit(WDM_WWAN_IN_USE, &desc->flags)) { in wdm_in_callback()
211 * Avoid propagating -EPIPE (stall) to userspace since it is in wdm_in_callback()
214 if (desc->rerr == 0 && status != -EPIPE) in wdm_in_callback()
215 desc->rerr = status; in wdm_in_callback()
217 if (length + desc->length > desc->wMaxCommand) { in wdm_in_callback()
219 set_bit(WDM_OVERFLOW, &desc->flags); in wdm_in_callback()
222 if (!test_bit(WDM_OVERFLOW, &desc->flags)) { in wdm_in_callback()
223 memmove(desc->ubuf + desc->length, desc->inbuf, length); in wdm_in_callback()
224 desc->length += length; in wdm_in_callback()
225 desc->reslength = length; in wdm_in_callback()
230 if (desc->rerr) { in wdm_in_callback()
233 * any data after poll'ing. in wdm_in_callback()
237 schedule_work(&desc->service_outs_intr); in wdm_in_callback()
239 set_bit(WDM_READ, &desc->flags); in wdm_in_callback()
240 wake_up(&desc->wait); in wdm_in_callback()
243 spin_unlock_irqrestore(&desc->iuspin, flags); in wdm_in_callback()
251 int status = urb->status; in wdm_int_callback()
255 desc = urb->context; in wdm_int_callback()
256 dr = (struct usb_cdc_notification *)desc->sbuf; in wdm_int_callback()
260 case -ESHUTDOWN: in wdm_int_callback()
261 case -ENOENT: in wdm_int_callback()
262 case -ECONNRESET: in wdm_int_callback()
264 case -EPIPE: in wdm_int_callback()
265 set_bit(WDM_INT_STALL, &desc->flags); in wdm_int_callback()
266 dev_err(&desc->intf->dev, "Stall on int endpoint\n"); in wdm_int_callback()
269 dev_err_ratelimited(&desc->intf->dev, in wdm_int_callback()
275 if (urb->actual_length < sizeof(struct usb_cdc_notification)) { in wdm_int_callback()
276 dev_err_ratelimited(&desc->intf->dev, "wdm_int_callback - %d bytes\n", in wdm_int_callback()
277 urb->actual_length); in wdm_int_callback()
281 switch (dr->bNotificationType) { in wdm_int_callback()
283 dev_dbg(&desc->intf->dev, in wdm_int_callback()
285 le16_to_cpu(dr->wIndex), le16_to_cpu(dr->wLength)); in wdm_int_callback()
290 dev_dbg(&desc->intf->dev, in wdm_int_callback()
292 dr->wValue ? "connected to" : "disconnected from"); in wdm_int_callback()
295 dev_dbg(&desc->intf->dev, "SPEED_CHANGE received (len %u)\n", in wdm_int_callback()
296 urb->actual_length); in wdm_int_callback()
299 clear_bit(WDM_POLL_RUNNING, &desc->flags); in wdm_int_callback()
300 dev_err(&desc->intf->dev, in wdm_int_callback()
302 dr->bNotificationType, in wdm_int_callback()
303 le16_to_cpu(dr->wIndex), in wdm_int_callback()
304 le16_to_cpu(dr->wLength)); in wdm_int_callback()
308 spin_lock_irqsave(&desc->iuspin, flags); in wdm_int_callback()
309 responding = test_and_set_bit(WDM_RESPONDING, &desc->flags); in wdm_int_callback()
310 if (!desc->resp_count++ && !responding in wdm_int_callback()
311 && !test_bit(WDM_DISCONNECTING, &desc->flags) in wdm_int_callback()
312 && !test_bit(WDM_SUSPENDING, &desc->flags)) { in wdm_int_callback()
313 rv = usb_submit_urb(desc->response, GFP_ATOMIC); in wdm_int_callback()
314 dev_dbg(&desc->intf->dev, "submit response URB %d\n", rv); in wdm_int_callback()
316 spin_unlock_irqrestore(&desc->iuspin, flags); in wdm_int_callback()
318 clear_bit(WDM_RESPONDING, &desc->flags); in wdm_int_callback()
319 if (rv == -EPERM) in wdm_int_callback()
321 if (rv == -ENOMEM) { in wdm_int_callback()
323 rv = schedule_work(&desc->rxwork); in wdm_int_callback()
325 dev_err(&desc->intf->dev, in wdm_int_callback()
332 dev_err(&desc->intf->dev, in wdm_int_callback()
333 "%s - usb_submit_urb failed with result %d\n", in wdm_int_callback()
341 usb_poison_urb(desc->command); in poison_urbs()
342 usb_poison_urb(desc->validity); in poison_urbs()
343 usb_poison_urb(desc->response); in poison_urbs()
352 usb_unpoison_urb(desc->response); in unpoison_urbs()
353 usb_unpoison_urb(desc->validity); in unpoison_urbs()
354 usb_unpoison_urb(desc->command); in unpoison_urbs()
359 usb_free_urb(desc->validity); in free_urbs()
360 usb_free_urb(desc->response); in free_urbs()
361 usb_free_urb(desc->command); in free_urbs()
366 kfree(desc->sbuf); in cleanup()
367 kfree(desc->inbuf); in cleanup()
368 kfree(desc->orq); in cleanup()
369 kfree(desc->irq); in cleanup()
370 kfree(desc->ubuf); in cleanup()
376 (struct file *file, const char __user *buffer, size_t count, loff_t *ppos) in wdm_write() argument
379 int rv = -EMSGSIZE, r, we; in wdm_write()
380 struct wdm_device *desc = file->private_data; in wdm_write()
383 if (count > desc->wMaxCommand) in wdm_write()
384 count = desc->wMaxCommand; in wdm_write()
386 spin_lock_irq(&desc->iuspin); in wdm_write()
387 we = desc->werr; in wdm_write()
388 desc->werr = 0; in wdm_write()
389 spin_unlock_irq(&desc->iuspin); in wdm_write()
393 buf = memdup_user(buffer, count); in wdm_write()
398 r = mutex_lock_interruptible(&desc->wlock); in wdm_write()
399 rv = -ERESTARTSYS; in wdm_write()
403 if (test_bit(WDM_DISCONNECTING, &desc->flags)) { in wdm_write()
404 rv = -ENODEV; in wdm_write()
408 r = usb_autopm_get_interface(desc->intf); in wdm_write()
414 if (!(file->f_flags & O_NONBLOCK)) in wdm_write()
415 r = wait_event_interruptible(desc->wait, !test_bit(WDM_IN_USE, in wdm_write()
416 &desc->flags)); in wdm_write()
418 if (test_bit(WDM_IN_USE, &desc->flags)) in wdm_write()
419 r = -EAGAIN; in wdm_write()
421 if (test_bit(WDM_RESETTING, &desc->flags)) in wdm_write()
422 r = -EIO; in wdm_write()
424 if (test_bit(WDM_DISCONNECTING, &desc->flags)) in wdm_write()
425 r = -ENODEV; in wdm_write()
432 req = desc->orq; in wdm_write()
434 desc->command, in wdm_write()
435 interface_to_usbdev(desc->intf), in wdm_write()
437 usb_sndctrlpipe(interface_to_usbdev(desc->intf), 0), in wdm_write()
440 count, in wdm_write()
445 req->bRequestType = (USB_DIR_OUT | USB_TYPE_CLASS | in wdm_write()
447 req->bRequest = USB_CDC_SEND_ENCAPSULATED_COMMAND; in wdm_write()
448 req->wValue = 0; in wdm_write()
449 req->wIndex = desc->inum; /* already converted */ in wdm_write()
450 req->wLength = cpu_to_le16(count); in wdm_write()
451 set_bit(WDM_IN_USE, &desc->flags); in wdm_write()
452 desc->outbuf = buf; in wdm_write()
454 rv = usb_submit_urb(desc->command, GFP_KERNEL); in wdm_write()
456 desc->outbuf = NULL; in wdm_write()
457 clear_bit(WDM_IN_USE, &desc->flags); in wdm_write()
458 wake_up_all(&desc->wait); /* for wdm_wait_for_response() */ in wdm_write()
459 dev_err(&desc->intf->dev, "Tx URB error: %d\n", rv); in wdm_write()
463 dev_dbg(&desc->intf->dev, "Tx URB has been submitted index=%d\n", in wdm_write()
464 le16_to_cpu(req->wIndex)); in wdm_write()
467 usb_autopm_put_interface(desc->intf); in wdm_write()
468 mutex_unlock(&desc->wlock); in wdm_write()
469 return count; in wdm_write()
472 usb_autopm_put_interface(desc->intf); in wdm_write()
474 mutex_unlock(&desc->wlock); in wdm_write()
481 * Submit the read urb if resp_count is non-zero.
483 * Called with desc->iuspin locked
490 if (!desc->resp_count || !--desc->resp_count) in service_outstanding_interrupt()
493 if (test_bit(WDM_DISCONNECTING, &desc->flags)) { in service_outstanding_interrupt()
494 rv = -ENODEV; in service_outstanding_interrupt()
497 if (test_bit(WDM_RESETTING, &desc->flags)) { in service_outstanding_interrupt()
498 rv = -EIO; in service_outstanding_interrupt()
502 set_bit(WDM_RESPONDING, &desc->flags); in service_outstanding_interrupt()
503 spin_unlock_irq(&desc->iuspin); in service_outstanding_interrupt()
504 rv = usb_submit_urb(desc->response, GFP_KERNEL); in service_outstanding_interrupt()
505 spin_lock_irq(&desc->iuspin); in service_outstanding_interrupt()
507 if (!test_bit(WDM_DISCONNECTING, &desc->flags)) in service_outstanding_interrupt()
508 dev_err(&desc->intf->dev, in service_outstanding_interrupt()
512 clear_bit(WDM_RESPONDING, &desc->flags); in service_outstanding_interrupt()
513 desc->resp_count = 0; in service_outstanding_interrupt()
520 (struct file *file, char __user *buffer, size_t count, loff_t *ppos) in wdm_read() argument
524 struct wdm_device *desc = file->private_data; in wdm_read()
527 rv = mutex_lock_interruptible(&desc->rlock); /*concurrent reads */ in wdm_read()
529 return -ERESTARTSYS; in wdm_read()
531 cntr = READ_ONCE(desc->length); in wdm_read()
533 desc->read = 0; in wdm_read()
534 retry: in wdm_read()
535 if (test_bit(WDM_DISCONNECTING, &desc->flags)) { in wdm_read()
536 rv = -ENODEV; in wdm_read()
539 if (test_bit(WDM_OVERFLOW, &desc->flags)) { in wdm_read()
540 clear_bit(WDM_OVERFLOW, &desc->flags); in wdm_read()
541 rv = -ENOBUFS; in wdm_read()
545 if (file->f_flags & O_NONBLOCK) { in wdm_read()
546 if (!test_bit(WDM_READ, &desc->flags)) { in wdm_read()
547 rv = -EAGAIN; in wdm_read()
552 rv = wait_event_interruptible(desc->wait, in wdm_read()
553 test_bit(WDM_READ, &desc->flags)); in wdm_read()
557 if (test_bit(WDM_DISCONNECTING, &desc->flags)) { in wdm_read()
558 rv = -ENODEV; in wdm_read()
561 if (test_bit(WDM_RESETTING, &desc->flags)) { in wdm_read()
562 rv = -EIO; in wdm_read()
565 usb_mark_last_busy(interface_to_usbdev(desc->intf)); in wdm_read()
567 rv = -ERESTARTSYS; in wdm_read()
571 spin_lock_irq(&desc->iuspin); in wdm_read()
573 if (desc->rerr) { /* read completed, error happened */ in wdm_read()
574 rv = usb_translate_errors(desc->rerr); in wdm_read()
575 desc->rerr = 0; in wdm_read()
576 spin_unlock_irq(&desc->iuspin); in wdm_read()
583 if (!test_bit(WDM_READ, &desc->flags)) { /* lost race */ in wdm_read()
584 spin_unlock_irq(&desc->iuspin); in wdm_read()
585 goto retry; in wdm_read()
588 if (!desc->reslength) { /* zero length read */ in wdm_read()
589 dev_dbg(&desc->intf->dev, "zero length - clearing WDM_READ\n"); in wdm_read()
590 clear_bit(WDM_READ, &desc->flags); in wdm_read()
592 spin_unlock_irq(&desc->iuspin); in wdm_read()
595 goto retry; in wdm_read()
597 cntr = desc->length; in wdm_read()
598 spin_unlock_irq(&desc->iuspin); in wdm_read()
601 if (cntr > count) in wdm_read()
602 cntr = count; in wdm_read()
603 rv = copy_to_user(buffer, desc->ubuf, cntr); in wdm_read()
605 rv = -EFAULT; in wdm_read()
609 spin_lock_irq(&desc->iuspin); in wdm_read()
611 for (i = 0; i < desc->length - cntr; i++) in wdm_read()
612 desc->ubuf[i] = desc->ubuf[i + cntr]; in wdm_read()
614 desc->length -= cntr; in wdm_read()
616 if (!desc->length) { in wdm_read()
617 clear_bit(WDM_READ, &desc->flags); in wdm_read()
620 spin_unlock_irq(&desc->iuspin); in wdm_read()
624 mutex_unlock(&desc->rlock); in wdm_read()
630 struct wdm_device *desc = file->private_data; in wdm_wait_for_response()
637 rv = wait_event_interruptible_timeout(desc->wait, in wdm_wait_for_response()
638 !test_bit(WDM_IN_USE, &desc->flags) || in wdm_wait_for_response()
639 test_bit(WDM_DISCONNECTING, &desc->flags), in wdm_wait_for_response()
646 if (test_bit(WDM_DISCONNECTING, &desc->flags)) in wdm_wait_for_response()
647 return -ENODEV; in wdm_wait_for_response()
649 return -EIO; in wdm_wait_for_response()
651 return -EINTR; in wdm_wait_for_response()
653 spin_lock_irq(&desc->iuspin); in wdm_wait_for_response()
654 rv = desc->werr; in wdm_wait_for_response()
655 desc->werr = 0; in wdm_wait_for_response()
656 spin_unlock_irq(&desc->iuspin); in wdm_wait_for_response()
664 * Also, don't abort when fsync() returned -EINVAL, for older kernels which do
665 * not implement wdm_flush() will return -EINVAL.
684 struct wdm_device *desc = file->private_data; in wdm_poll()
688 spin_lock_irqsave(&desc->iuspin, flags); in wdm_poll()
689 if (test_bit(WDM_DISCONNECTING, &desc->flags)) { in wdm_poll()
691 spin_unlock_irqrestore(&desc->iuspin, flags); in wdm_poll()
694 if (test_bit(WDM_READ, &desc->flags)) in wdm_poll()
696 if (desc->rerr || desc->werr) in wdm_poll()
698 if (!test_bit(WDM_IN_USE, &desc->flags)) in wdm_poll()
700 spin_unlock_irqrestore(&desc->iuspin, flags); in wdm_poll()
702 poll_wait(file, &desc->wait, wait); in wdm_poll()
711 int rv = -ENODEV; in wdm_open()
720 intf = desc->intf; in wdm_open()
721 if (test_bit(WDM_DISCONNECTING, &desc->flags)) in wdm_open()
723 file->private_data = desc; in wdm_open()
725 if (test_bit(WDM_WWAN_IN_USE, &desc->flags)) { in wdm_open()
726 rv = -EBUSY; in wdm_open()
730 rv = usb_autopm_get_interface(desc->intf); in wdm_open()
732 dev_err(&desc->intf->dev, "Error autopm - %d\n", rv); in wdm_open()
736 /* using write lock to protect desc->count */ in wdm_open()
737 mutex_lock(&desc->wlock); in wdm_open()
738 if (!desc->count++) { in wdm_open()
739 desc->werr = 0; in wdm_open()
740 desc->rerr = 0; in wdm_open()
741 rv = usb_submit_urb(desc->validity, GFP_KERNEL); in wdm_open()
743 desc->count--; in wdm_open()
744 dev_err(&desc->intf->dev, in wdm_open()
745 "Error submitting int urb - %d\n", rv); in wdm_open()
751 mutex_unlock(&desc->wlock); in wdm_open()
752 if (desc->count == 1) in wdm_open()
753 desc->manage_power(intf, 1); in wdm_open()
754 usb_autopm_put_interface(desc->intf); in wdm_open()
762 struct wdm_device *desc = file->private_data; in wdm_release()
766 /* using write lock to protect desc->count */ in wdm_release()
767 mutex_lock(&desc->wlock); in wdm_release()
768 desc->count--; in wdm_release()
769 mutex_unlock(&desc->wlock); in wdm_release()
771 if (!desc->count) { in wdm_release()
772 if (!test_bit(WDM_DISCONNECTING, &desc->flags)) { in wdm_release()
773 dev_dbg(&desc->intf->dev, "wdm_release: cleanup\n"); in wdm_release()
775 spin_lock_irq(&desc->iuspin); in wdm_release()
776 desc->resp_count = 0; in wdm_release()
777 clear_bit(WDM_RESPONDING, &desc->flags); in wdm_release()
778 spin_unlock_irq(&desc->iuspin); in wdm_release()
779 desc->manage_power(desc->intf, 0); in wdm_release()
782 /* must avoid dev_printk here as desc->intf is invalid */ in wdm_release()
783 pr_debug(KBUILD_MODNAME " %s: device gone - cleaning up\n", __func__); in wdm_release()
793 struct wdm_device *desc = file->private_data; in wdm_ioctl()
798 if (copy_to_user((void __user *)arg, &desc->wMaxCommand, sizeof(desc->wMaxCommand))) in wdm_ioctl()
799 rv = -EFAULT; in wdm_ioctl()
802 rv = -ENOTTY; in wdm_ioctl()
815 .poll = wdm_poll,
822 .name = "cdc-wdm%d",
827 /* --- WWAN framework integration --- */
838 if (desc->count) { in wdm_wwan_port_start()
840 return -EBUSY; in wdm_wwan_port_start()
842 set_bit(WDM_WWAN_IN_USE, &desc->flags); in wdm_wwan_port_start()
845 desc->manage_power(desc->intf, 1); in wdm_wwan_port_start()
851 return usb_submit_urb(desc->validity, GFP_KERNEL); in wdm_wwan_port_start()
860 desc->manage_power(desc->intf, 0); in wdm_wwan_port_stop()
861 clear_bit(WDM_READ, &desc->flags); in wdm_wwan_port_stop()
862 clear_bit(WDM_WWAN_IN_USE, &desc->flags); in wdm_wwan_port_stop()
868 struct sk_buff *skb = urb->context; in wdm_wwan_port_tx_complete()
869 struct wdm_device *desc = skb_shinfo(skb)->destructor_arg; in wdm_wwan_port_tx_complete()
871 usb_autopm_put_interface(desc->intf); in wdm_wwan_port_tx_complete()
872 wwan_port_txon(desc->wwanp); in wdm_wwan_port_tx_complete()
879 struct usb_interface *intf = desc->intf; in wdm_wwan_port_tx()
880 struct usb_ctrlrequest *req = desc->orq; in wdm_wwan_port_tx()
888 desc->command, in wdm_wwan_port_tx()
892 skb->data, in wdm_wwan_port_tx()
893 skb->len, in wdm_wwan_port_tx()
898 req->bRequestType = (USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE); in wdm_wwan_port_tx()
899 req->bRequest = USB_CDC_SEND_ENCAPSULATED_COMMAND; in wdm_wwan_port_tx()
900 req->wValue = 0; in wdm_wwan_port_tx()
901 req->wIndex = desc->inum; in wdm_wwan_port_tx()
902 req->wLength = cpu_to_le16(skb->len); in wdm_wwan_port_tx()
904 skb_shinfo(skb)->destructor_arg = desc; in wdm_wwan_port_tx()
906 rv = usb_submit_urb(desc->command, GFP_KERNEL); in wdm_wwan_port_tx()
923 struct usb_interface *intf = desc->intf; in wdm_wwan_init()
927 if (desc->wwanp_type == WWAN_PORT_UNKNOWN) { in wdm_wwan_init()
928 dev_info(&intf->dev, "Unknown control protocol\n"); in wdm_wwan_init()
932 port = wwan_create_port(&intf->dev, desc->wwanp_type, &wdm_wwan_port_ops, in wdm_wwan_init()
935 dev_err(&intf->dev, "%s: Unable to create WWAN port\n", in wdm_wwan_init()
936 dev_name(intf->usb_dev)); in wdm_wwan_init()
940 desc->wwanp = port; in wdm_wwan_init()
945 if (!desc->wwanp) in wdm_wwan_deinit()
948 wwan_remove_port(desc->wwanp); in wdm_wwan_deinit()
949 desc->wwanp = NULL; in wdm_wwan_deinit()
954 struct wwan_port *port = desc->wwanp; in wdm_wwan_rx()
962 skb_put_data(skb, desc->inbuf, length); in wdm_wwan_rx()
966 schedule_work(&desc->service_outs_intr); in wdm_wwan_rx()
974 /* --- error handling --- */
982 spin_lock_irqsave(&desc->iuspin, flags); in wdm_rxwork()
983 if (test_bit(WDM_DISCONNECTING, &desc->flags)) { in wdm_rxwork()
984 spin_unlock_irqrestore(&desc->iuspin, flags); in wdm_rxwork()
986 responding = test_and_set_bit(WDM_RESPONDING, &desc->flags); in wdm_rxwork()
987 spin_unlock_irqrestore(&desc->iuspin, flags); in wdm_rxwork()
989 rv = usb_submit_urb(desc->response, GFP_KERNEL); in wdm_rxwork()
990 if (rv < 0 && rv != -EPERM) { in wdm_rxwork()
991 spin_lock_irqsave(&desc->iuspin, flags); in wdm_rxwork()
992 clear_bit(WDM_RESPONDING, &desc->flags); in wdm_rxwork()
993 if (!test_bit(WDM_DISCONNECTING, &desc->flags)) in wdm_rxwork()
994 schedule_work(&desc->rxwork); in wdm_rxwork()
995 spin_unlock_irqrestore(&desc->iuspin, flags); in wdm_rxwork()
1006 spin_lock_irq(&desc->iuspin); in service_interrupt_work()
1008 if (!desc->resp_count) { in service_interrupt_work()
1009 set_bit(WDM_READ, &desc->flags); in service_interrupt_work()
1010 wake_up(&desc->wait); in service_interrupt_work()
1012 spin_unlock_irq(&desc->iuspin); in service_interrupt_work()
1015 /* --- hotplug --- */
1021 int rv = -ENOMEM; in wdm_create()
1027 INIT_LIST_HEAD(&desc->device_list); in wdm_create()
1028 mutex_init(&desc->rlock); in wdm_create()
1029 mutex_init(&desc->wlock); in wdm_create()
1030 spin_lock_init(&desc->iuspin); in wdm_create()
1031 init_waitqueue_head(&desc->wait); in wdm_create()
1032 desc->wMaxCommand = bufsize; in wdm_create()
1034 desc->inum = cpu_to_le16((u16)intf->cur_altsetting->desc.bInterfaceNumber); in wdm_create()
1035 desc->intf = intf; in wdm_create()
1036 desc->wwanp_type = type; in wdm_create()
1037 INIT_WORK(&desc->rxwork, wdm_rxwork); in wdm_create()
1038 INIT_WORK(&desc->service_outs_intr, service_interrupt_work); in wdm_create()
1041 rv = -EINVAL; in wdm_create()
1045 desc->wMaxPacketSize = usb_endpoint_maxp(ep); in wdm_create()
1047 desc->orq = kmalloc(sizeof(struct usb_ctrlrequest), GFP_KERNEL); in wdm_create()
1048 if (!desc->orq) in wdm_create()
1050 desc->irq = kmalloc(sizeof(struct usb_ctrlrequest), GFP_KERNEL); in wdm_create()
1051 if (!desc->irq) in wdm_create()
1054 desc->validity = usb_alloc_urb(0, GFP_KERNEL); in wdm_create()
1055 if (!desc->validity) in wdm_create()
1058 desc->response = usb_alloc_urb(0, GFP_KERNEL); in wdm_create()
1059 if (!desc->response) in wdm_create()
1062 desc->command = usb_alloc_urb(0, GFP_KERNEL); in wdm_create()
1063 if (!desc->command) in wdm_create()
1066 desc->ubuf = kmalloc(desc->wMaxCommand, GFP_KERNEL); in wdm_create()
1067 if (!desc->ubuf) in wdm_create()
1070 desc->sbuf = kmalloc(desc->wMaxPacketSize, GFP_KERNEL); in wdm_create()
1071 if (!desc->sbuf) in wdm_create()
1074 desc->inbuf = kmalloc(desc->wMaxCommand, GFP_KERNEL); in wdm_create()
1075 if (!desc->inbuf) in wdm_create()
1079 desc->validity, in wdm_create()
1081 usb_rcvintpipe(interface_to_usbdev(intf), ep->bEndpointAddress), in wdm_create()
1082 desc->sbuf, in wdm_create()
1083 desc->wMaxPacketSize, in wdm_create()
1086 ep->bInterval in wdm_create()
1089 desc->irq->bRequestType = (USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE); in wdm_create()
1090 desc->irq->bRequest = USB_CDC_GET_ENCAPSULATED_RESPONSE; in wdm_create()
1091 desc->irq->wValue = 0; in wdm_create()
1092 desc->irq->wIndex = desc->inum; /* already converted */ in wdm_create()
1093 desc->irq->wLength = cpu_to_le16(desc->wMaxCommand); in wdm_create()
1096 desc->response, in wdm_create()
1099 usb_rcvctrlpipe(interface_to_usbdev(desc->intf), 0), in wdm_create()
1100 (unsigned char *)desc->irq, in wdm_create()
1101 desc->inbuf, in wdm_create()
1102 desc->wMaxCommand, in wdm_create()
1107 desc->manage_power = manage_power; in wdm_create()
1110 list_add(&desc->device_list, &wdm_device_list); in wdm_create()
1117 dev_info(&intf->dev, "%s: USB WDM device\n", dev_name(intf->usb_dev)); in wdm_create()
1125 list_del(&desc->device_list); in wdm_create()
1136 intf->needs_remote_wakeup = on; in wdm_manage_power()
1144 int rv = -EINVAL; in wdm_probe()
1148 u8 *buffer = intf->altsetting->extra; in wdm_probe()
1149 int buflen = intf->altsetting->extralen; in wdm_probe()
1158 maxcom = le16_to_cpu(hdr.usb_cdc_dmm_desc->wMaxCommand); in wdm_probe()
1160 iface = intf->cur_altsetting; in wdm_probe()
1161 if (iface->desc.bNumEndpoints != 1) in wdm_probe()
1163 ep = &iface->endpoint[0].desc; in wdm_probe()
1172 * usb_cdc_wdm_register - register a WDM subdriver
1177 * @manage_power: call-back invoked during open and release to
1221 spin_lock_irqsave(&desc->iuspin, flags); in wdm_disconnect()
1222 set_bit(WDM_DISCONNECTING, &desc->flags); in wdm_disconnect()
1223 set_bit(WDM_READ, &desc->flags); in wdm_disconnect()
1224 spin_unlock_irqrestore(&desc->iuspin, flags); in wdm_disconnect()
1225 wake_up_all(&desc->wait); in wdm_disconnect()
1226 mutex_lock(&desc->rlock); in wdm_disconnect()
1227 mutex_lock(&desc->wlock); in wdm_disconnect()
1229 cancel_work_sync(&desc->rxwork); in wdm_disconnect()
1230 cancel_work_sync(&desc->service_outs_intr); in wdm_disconnect()
1231 mutex_unlock(&desc->wlock); in wdm_disconnect()
1232 mutex_unlock(&desc->rlock); in wdm_disconnect()
1234 /* the desc->intf pointer used as list key is now invalid */ in wdm_disconnect()
1236 list_del(&desc->device_list); in wdm_disconnect()
1239 if (!desc->count) in wdm_disconnect()
1242 dev_dbg(&intf->dev, "%d open files - postponing cleanup\n", desc->count); in wdm_disconnect()
1252 dev_dbg(&desc->intf->dev, "wdm%d_suspend\n", intf->minor); in wdm_suspend()
1256 mutex_lock(&desc->rlock); in wdm_suspend()
1257 mutex_lock(&desc->wlock); in wdm_suspend()
1259 spin_lock_irq(&desc->iuspin); in wdm_suspend()
1262 (test_bit(WDM_IN_USE, &desc->flags) in wdm_suspend()
1263 || test_bit(WDM_RESPONDING, &desc->flags))) { in wdm_suspend()
1264 spin_unlock_irq(&desc->iuspin); in wdm_suspend()
1265 rv = -EBUSY; in wdm_suspend()
1268 set_bit(WDM_SUSPENDING, &desc->flags); in wdm_suspend()
1269 spin_unlock_irq(&desc->iuspin); in wdm_suspend()
1270 /* callback submits work - order is essential */ in wdm_suspend()
1272 cancel_work_sync(&desc->rxwork); in wdm_suspend()
1273 cancel_work_sync(&desc->service_outs_intr); in wdm_suspend()
1277 mutex_unlock(&desc->wlock); in wdm_suspend()
1278 mutex_unlock(&desc->rlock); in wdm_suspend()
1289 if (desc->count) { in recover_from_urb_loss()
1290 rv = usb_submit_urb(desc->validity, GFP_NOIO); in recover_from_urb_loss()
1292 dev_err(&desc->intf->dev, in recover_from_urb_loss()
1293 "Error resume submitting int urb - %d\n", rv); in recover_from_urb_loss()
1304 dev_dbg(&desc->intf->dev, "wdm%d_resume\n", intf->minor); in wdm_resume()
1306 clear_bit(WDM_SUSPENDING, &desc->flags); in wdm_resume()
1318 * we notify everybody using poll of in wdm_pre_reset()
1323 spin_lock_irq(&desc->iuspin); in wdm_pre_reset()
1324 set_bit(WDM_RESETTING, &desc->flags); /* inform read/write */ in wdm_pre_reset()
1325 set_bit(WDM_READ, &desc->flags); /* unblock read */ in wdm_pre_reset()
1326 clear_bit(WDM_IN_USE, &desc->flags); /* unblock write */ in wdm_pre_reset()
1327 desc->rerr = -EINTR; in wdm_pre_reset()
1328 spin_unlock_irq(&desc->iuspin); in wdm_pre_reset()
1329 wake_up_all(&desc->wait); in wdm_pre_reset()
1330 mutex_lock(&desc->rlock); in wdm_pre_reset()
1331 mutex_lock(&desc->wlock); in wdm_pre_reset()
1333 cancel_work_sync(&desc->rxwork); in wdm_pre_reset()
1334 cancel_work_sync(&desc->service_outs_intr); in wdm_pre_reset()
1344 clear_bit(WDM_OVERFLOW, &desc->flags); in wdm_post_reset()
1345 clear_bit(WDM_RESETTING, &desc->flags); in wdm_post_reset()
1347 mutex_unlock(&desc->wlock); in wdm_post_reset()
1348 mutex_unlock(&desc->rlock); in wdm_post_reset()