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>
28 #include <linux/usb/cdc-wdm.h>
64 /* CDC-WMC r1.1 requires wMaxCommand to be "at least 256 decimal (0x100)" */
71 /* --- method tables --- */
95 int count; member
120 if (desc->intf == intf) in wdm_find_device()
135 if (desc->intf->minor == minor) in wdm_find_device_by_minor()
144 /* --- callbacks --- */
150 desc = urb->context; in wdm_out_callback()
151 spin_lock_irqsave(&desc->iuspin, flags); in wdm_out_callback()
152 desc->werr = urb->status; in wdm_out_callback()
153 spin_unlock_irqrestore(&desc->iuspin, flags); in wdm_out_callback()
154 kfree(desc->outbuf); in wdm_out_callback()
155 desc->outbuf = NULL; in wdm_out_callback()
156 clear_bit(WDM_IN_USE, &desc->flags); in wdm_out_callback()
157 wake_up_all(&desc->wait); in wdm_out_callback()
163 struct wdm_device *desc = urb->context; in wdm_in_callback()
164 int status = urb->status; in wdm_in_callback()
165 int length = urb->actual_length; in wdm_in_callback()
167 spin_lock_irqsave(&desc->iuspin, flags); in wdm_in_callback()
168 clear_bit(WDM_RESPONDING, &desc->flags); in wdm_in_callback()
172 case -ENOENT: in wdm_in_callback()
173 dev_dbg(&desc->intf->dev, in wdm_in_callback()
174 "nonzero urb status received: -ENOENT\n"); in wdm_in_callback()
176 case -ECONNRESET: in wdm_in_callback()
177 dev_dbg(&desc->intf->dev, in wdm_in_callback()
178 "nonzero urb status received: -ECONNRESET\n"); in wdm_in_callback()
180 case -ESHUTDOWN: in wdm_in_callback()
181 dev_dbg(&desc->intf->dev, in wdm_in_callback()
182 "nonzero urb status received: -ESHUTDOWN\n"); in wdm_in_callback()
184 case -EPIPE: in wdm_in_callback()
185 dev_err(&desc->intf->dev, in wdm_in_callback()
186 "nonzero urb status received: -EPIPE\n"); in wdm_in_callback()
189 dev_err(&desc->intf->dev, in wdm_in_callback()
198 * Avoid propagating -EPIPE (stall) to userspace since it is in wdm_in_callback()
201 if (desc->rerr == 0 && status != -EPIPE) in wdm_in_callback()
202 desc->rerr = status; in wdm_in_callback()
204 if (length + desc->length > desc->wMaxCommand) { in wdm_in_callback()
206 set_bit(WDM_OVERFLOW, &desc->flags); in wdm_in_callback()
209 if (!test_bit(WDM_OVERFLOW, &desc->flags)) { in wdm_in_callback()
210 memmove(desc->ubuf + desc->length, desc->inbuf, length); in wdm_in_callback()
211 desc->length += length; in wdm_in_callback()
212 desc->reslength = length; in wdm_in_callback()
217 if (desc->rerr) { in wdm_in_callback()
220 * any data after poll'ing. in wdm_in_callback()
224 schedule_work(&desc->service_outs_intr); in wdm_in_callback()
226 set_bit(WDM_READ, &desc->flags); in wdm_in_callback()
227 wake_up(&desc->wait); in wdm_in_callback()
229 spin_unlock_irqrestore(&desc->iuspin, flags); in wdm_in_callback()
237 int status = urb->status; in wdm_int_callback()
241 desc = urb->context; in wdm_int_callback()
242 dr = (struct usb_cdc_notification *)desc->sbuf; in wdm_int_callback()
246 case -ESHUTDOWN: in wdm_int_callback()
247 case -ENOENT: in wdm_int_callback()
248 case -ECONNRESET: in wdm_int_callback()
250 case -EPIPE: in wdm_int_callback()
251 set_bit(WDM_INT_STALL, &desc->flags); in wdm_int_callback()
252 dev_err(&desc->intf->dev, "Stall on int endpoint\n"); in wdm_int_callback()
255 dev_err(&desc->intf->dev, in wdm_int_callback()
261 if (urb->actual_length < sizeof(struct usb_cdc_notification)) { in wdm_int_callback()
262 dev_err(&desc->intf->dev, "wdm_int_callback - %d bytes\n", in wdm_int_callback()
263 urb->actual_length); in wdm_int_callback()
267 switch (dr->bNotificationType) { in wdm_int_callback()
269 dev_dbg(&desc->intf->dev, in wdm_int_callback()
271 le16_to_cpu(dr->wIndex), le16_to_cpu(dr->wLength)); in wdm_int_callback()
276 dev_dbg(&desc->intf->dev, in wdm_int_callback()
278 dr->wValue ? "connected to" : "disconnected from"); in wdm_int_callback()
281 dev_dbg(&desc->intf->dev, "SPEED_CHANGE received (len %u)\n", in wdm_int_callback()
282 urb->actual_length); in wdm_int_callback()
285 clear_bit(WDM_POLL_RUNNING, &desc->flags); in wdm_int_callback()
286 dev_err(&desc->intf->dev, in wdm_int_callback()
288 dr->bNotificationType, in wdm_int_callback()
289 le16_to_cpu(dr->wIndex), in wdm_int_callback()
290 le16_to_cpu(dr->wLength)); in wdm_int_callback()
294 spin_lock_irqsave(&desc->iuspin, flags); in wdm_int_callback()
295 responding = test_and_set_bit(WDM_RESPONDING, &desc->flags); in wdm_int_callback()
296 if (!desc->resp_count++ && !responding in wdm_int_callback()
297 && !test_bit(WDM_DISCONNECTING, &desc->flags) in wdm_int_callback()
298 && !test_bit(WDM_SUSPENDING, &desc->flags)) { in wdm_int_callback()
299 rv = usb_submit_urb(desc->response, GFP_ATOMIC); in wdm_int_callback()
300 dev_dbg(&desc->intf->dev, "submit response URB %d\n", rv); in wdm_int_callback()
302 spin_unlock_irqrestore(&desc->iuspin, flags); in wdm_int_callback()
304 clear_bit(WDM_RESPONDING, &desc->flags); in wdm_int_callback()
305 if (rv == -EPERM) in wdm_int_callback()
307 if (rv == -ENOMEM) { in wdm_int_callback()
309 rv = schedule_work(&desc->rxwork); in wdm_int_callback()
311 dev_err(&desc->intf->dev, in wdm_int_callback()
318 dev_err(&desc->intf->dev, in wdm_int_callback()
319 "%s - usb_submit_urb failed with result %d\n", in wdm_int_callback()
327 usb_kill_urb(desc->command); in kill_urbs()
328 usb_kill_urb(desc->validity); in kill_urbs()
329 usb_kill_urb(desc->response); in kill_urbs()
334 usb_free_urb(desc->validity); in free_urbs()
335 usb_free_urb(desc->response); in free_urbs()
336 usb_free_urb(desc->command); in free_urbs()
341 kfree(desc->sbuf); in cleanup()
342 kfree(desc->inbuf); in cleanup()
343 kfree(desc->orq); in cleanup()
344 kfree(desc->irq); in cleanup()
345 kfree(desc->ubuf); in cleanup()
351 (struct file *file, const char __user *buffer, size_t count, loff_t *ppos) in wdm_write() argument
354 int rv = -EMSGSIZE, r, we; in wdm_write()
355 struct wdm_device *desc = file->private_data; in wdm_write()
358 if (count > desc->wMaxCommand) in wdm_write()
359 count = desc->wMaxCommand; in wdm_write()
361 spin_lock_irq(&desc->iuspin); in wdm_write()
362 we = desc->werr; in wdm_write()
363 desc->werr = 0; in wdm_write()
364 spin_unlock_irq(&desc->iuspin); in wdm_write()
368 buf = memdup_user(buffer, count); in wdm_write()
373 r = mutex_lock_interruptible(&desc->wlock); in wdm_write()
374 rv = -ERESTARTSYS; in wdm_write()
378 if (test_bit(WDM_DISCONNECTING, &desc->flags)) { in wdm_write()
379 rv = -ENODEV; in wdm_write()
383 r = usb_autopm_get_interface(desc->intf); in wdm_write()
389 if (!(file->f_flags & O_NONBLOCK)) in wdm_write()
390 r = wait_event_interruptible(desc->wait, !test_bit(WDM_IN_USE, in wdm_write()
391 &desc->flags)); in wdm_write()
393 if (test_bit(WDM_IN_USE, &desc->flags)) in wdm_write()
394 r = -EAGAIN; in wdm_write()
396 if (test_bit(WDM_RESETTING, &desc->flags)) in wdm_write()
397 r = -EIO; in wdm_write()
399 if (test_bit(WDM_DISCONNECTING, &desc->flags)) in wdm_write()
400 r = -ENODEV; in wdm_write()
407 req = desc->orq; in wdm_write()
409 desc->command, in wdm_write()
410 interface_to_usbdev(desc->intf), in wdm_write()
412 usb_sndctrlpipe(interface_to_usbdev(desc->intf), 0), in wdm_write()
415 count, in wdm_write()
420 req->bRequestType = (USB_DIR_OUT | USB_TYPE_CLASS | in wdm_write()
422 req->bRequest = USB_CDC_SEND_ENCAPSULATED_COMMAND; in wdm_write()
423 req->wValue = 0; in wdm_write()
424 req->wIndex = desc->inum; /* already converted */ in wdm_write()
425 req->wLength = cpu_to_le16(count); in wdm_write()
426 set_bit(WDM_IN_USE, &desc->flags); in wdm_write()
427 desc->outbuf = buf; in wdm_write()
429 rv = usb_submit_urb(desc->command, GFP_KERNEL); in wdm_write()
431 desc->outbuf = NULL; in wdm_write()
432 clear_bit(WDM_IN_USE, &desc->flags); in wdm_write()
433 wake_up_all(&desc->wait); /* for wdm_wait_for_response() */ in wdm_write()
434 dev_err(&desc->intf->dev, "Tx URB error: %d\n", rv); in wdm_write()
438 dev_dbg(&desc->intf->dev, "Tx URB has been submitted index=%d\n", in wdm_write()
439 le16_to_cpu(req->wIndex)); in wdm_write()
442 usb_autopm_put_interface(desc->intf); in wdm_write()
443 mutex_unlock(&desc->wlock); in wdm_write()
444 return count; in wdm_write()
447 usb_autopm_put_interface(desc->intf); in wdm_write()
449 mutex_unlock(&desc->wlock); in wdm_write()
456 * Submit the read urb if resp_count is non-zero.
458 * Called with desc->iuspin locked
465 if (!desc->resp_count || !--desc->resp_count) in service_outstanding_interrupt()
468 set_bit(WDM_RESPONDING, &desc->flags); in service_outstanding_interrupt()
469 spin_unlock_irq(&desc->iuspin); in service_outstanding_interrupt()
470 rv = usb_submit_urb(desc->response, GFP_KERNEL); in service_outstanding_interrupt()
471 spin_lock_irq(&desc->iuspin); in service_outstanding_interrupt()
473 dev_err(&desc->intf->dev, in service_outstanding_interrupt()
477 clear_bit(WDM_RESPONDING, &desc->flags); in service_outstanding_interrupt()
478 desc->resp_count = 0; in service_outstanding_interrupt()
485 (struct file *file, char __user *buffer, size_t count, loff_t *ppos) in wdm_read() argument
489 struct wdm_device *desc = file->private_data; in wdm_read()
492 rv = mutex_lock_interruptible(&desc->rlock); /*concurrent reads */ in wdm_read()
494 return -ERESTARTSYS; in wdm_read()
496 cntr = READ_ONCE(desc->length); in wdm_read()
498 desc->read = 0; in wdm_read()
499 retry: in wdm_read()
500 if (test_bit(WDM_DISCONNECTING, &desc->flags)) { in wdm_read()
501 rv = -ENODEV; in wdm_read()
504 if (test_bit(WDM_OVERFLOW, &desc->flags)) { in wdm_read()
505 clear_bit(WDM_OVERFLOW, &desc->flags); in wdm_read()
506 rv = -ENOBUFS; in wdm_read()
510 if (file->f_flags & O_NONBLOCK) { in wdm_read()
511 if (!test_bit(WDM_READ, &desc->flags)) { in wdm_read()
512 rv = -EAGAIN; in wdm_read()
517 rv = wait_event_interruptible(desc->wait, in wdm_read()
518 test_bit(WDM_READ, &desc->flags)); in wdm_read()
522 if (test_bit(WDM_DISCONNECTING, &desc->flags)) { in wdm_read()
523 rv = -ENODEV; in wdm_read()
526 if (test_bit(WDM_RESETTING, &desc->flags)) { in wdm_read()
527 rv = -EIO; in wdm_read()
530 usb_mark_last_busy(interface_to_usbdev(desc->intf)); in wdm_read()
532 rv = -ERESTARTSYS; in wdm_read()
536 spin_lock_irq(&desc->iuspin); in wdm_read()
538 if (desc->rerr) { /* read completed, error happened */ in wdm_read()
539 rv = usb_translate_errors(desc->rerr); in wdm_read()
540 desc->rerr = 0; in wdm_read()
541 spin_unlock_irq(&desc->iuspin); in wdm_read()
548 if (!test_bit(WDM_READ, &desc->flags)) { /* lost race */ in wdm_read()
549 spin_unlock_irq(&desc->iuspin); in wdm_read()
550 goto retry; in wdm_read()
553 if (!desc->reslength) { /* zero length read */ in wdm_read()
554 dev_dbg(&desc->intf->dev, "zero length - clearing WDM_READ\n"); in wdm_read()
555 clear_bit(WDM_READ, &desc->flags); in wdm_read()
557 spin_unlock_irq(&desc->iuspin); in wdm_read()
560 goto retry; in wdm_read()
562 cntr = desc->length; in wdm_read()
563 spin_unlock_irq(&desc->iuspin); in wdm_read()
566 if (cntr > count) in wdm_read()
567 cntr = count; in wdm_read()
568 rv = copy_to_user(buffer, desc->ubuf, cntr); in wdm_read()
570 rv = -EFAULT; in wdm_read()
574 spin_lock_irq(&desc->iuspin); in wdm_read()
576 for (i = 0; i < desc->length - cntr; i++) in wdm_read()
577 desc->ubuf[i] = desc->ubuf[i + cntr]; in wdm_read()
579 desc->length -= cntr; in wdm_read()
581 if (!desc->length) { in wdm_read()
582 clear_bit(WDM_READ, &desc->flags); in wdm_read()
585 spin_unlock_irq(&desc->iuspin); in wdm_read()
589 mutex_unlock(&desc->rlock); in wdm_read()
595 struct wdm_device *desc = file->private_data; in wdm_wait_for_response()
602 rv = wait_event_interruptible_timeout(desc->wait, in wdm_wait_for_response()
603 !test_bit(WDM_IN_USE, &desc->flags) || in wdm_wait_for_response()
604 test_bit(WDM_DISCONNECTING, &desc->flags), in wdm_wait_for_response()
611 if (test_bit(WDM_DISCONNECTING, &desc->flags)) in wdm_wait_for_response()
612 return -ENODEV; in wdm_wait_for_response()
614 return -EIO; in wdm_wait_for_response()
616 return -EINTR; in wdm_wait_for_response()
618 spin_lock_irq(&desc->iuspin); in wdm_wait_for_response()
619 rv = desc->werr; in wdm_wait_for_response()
620 desc->werr = 0; in wdm_wait_for_response()
621 spin_unlock_irq(&desc->iuspin); in wdm_wait_for_response()
629 * Also, don't abort when fsync() returned -EINVAL, for older kernels which do
630 * not implement wdm_flush() will return -EINVAL.
649 struct wdm_device *desc = file->private_data; in wdm_poll()
653 spin_lock_irqsave(&desc->iuspin, flags); in wdm_poll()
654 if (test_bit(WDM_DISCONNECTING, &desc->flags)) { in wdm_poll()
656 spin_unlock_irqrestore(&desc->iuspin, flags); in wdm_poll()
659 if (test_bit(WDM_READ, &desc->flags)) in wdm_poll()
661 if (desc->rerr || desc->werr) in wdm_poll()
663 if (!test_bit(WDM_IN_USE, &desc->flags)) in wdm_poll()
665 spin_unlock_irqrestore(&desc->iuspin, flags); in wdm_poll()
667 poll_wait(file, &desc->wait, wait); in wdm_poll()
676 int rv = -ENODEV; in wdm_open()
685 intf = desc->intf; in wdm_open()
686 if (test_bit(WDM_DISCONNECTING, &desc->flags)) in wdm_open()
688 file->private_data = desc; in wdm_open()
690 rv = usb_autopm_get_interface(desc->intf); in wdm_open()
692 dev_err(&desc->intf->dev, "Error autopm - %d\n", rv); in wdm_open()
696 /* using write lock to protect desc->count */ in wdm_open()
697 mutex_lock(&desc->wlock); in wdm_open()
698 if (!desc->count++) { in wdm_open()
699 desc->werr = 0; in wdm_open()
700 desc->rerr = 0; in wdm_open()
701 rv = usb_submit_urb(desc->validity, GFP_KERNEL); in wdm_open()
703 desc->count--; in wdm_open()
704 dev_err(&desc->intf->dev, in wdm_open()
705 "Error submitting int urb - %d\n", rv); in wdm_open()
711 mutex_unlock(&desc->wlock); in wdm_open()
712 if (desc->count == 1) in wdm_open()
713 desc->manage_power(intf, 1); in wdm_open()
714 usb_autopm_put_interface(desc->intf); in wdm_open()
722 struct wdm_device *desc = file->private_data; in wdm_release()
726 /* using write lock to protect desc->count */ in wdm_release()
727 mutex_lock(&desc->wlock); in wdm_release()
728 desc->count--; in wdm_release()
729 mutex_unlock(&desc->wlock); in wdm_release()
731 if (!desc->count) { in wdm_release()
732 if (!test_bit(WDM_DISCONNECTING, &desc->flags)) { in wdm_release()
733 dev_dbg(&desc->intf->dev, "wdm_release: cleanup\n"); in wdm_release()
735 spin_lock_irq(&desc->iuspin); in wdm_release()
736 desc->resp_count = 0; in wdm_release()
737 spin_unlock_irq(&desc->iuspin); in wdm_release()
738 desc->manage_power(desc->intf, 0); in wdm_release()
740 /* must avoid dev_printk here as desc->intf is invalid */ in wdm_release()
741 pr_debug(KBUILD_MODNAME " %s: device gone - cleaning up\n", __func__); in wdm_release()
751 struct wdm_device *desc = file->private_data; in wdm_ioctl()
756 if (copy_to_user((void __user *)arg, &desc->wMaxCommand, sizeof(desc->wMaxCommand))) in wdm_ioctl()
757 rv = -EFAULT; in wdm_ioctl()
760 rv = -ENOTTY; in wdm_ioctl()
773 .poll = wdm_poll,
780 .name = "cdc-wdm%d",
785 /* --- error handling --- */
793 spin_lock_irqsave(&desc->iuspin, flags); in wdm_rxwork()
794 if (test_bit(WDM_DISCONNECTING, &desc->flags)) { in wdm_rxwork()
795 spin_unlock_irqrestore(&desc->iuspin, flags); in wdm_rxwork()
797 responding = test_and_set_bit(WDM_RESPONDING, &desc->flags); in wdm_rxwork()
798 spin_unlock_irqrestore(&desc->iuspin, flags); in wdm_rxwork()
800 rv = usb_submit_urb(desc->response, GFP_KERNEL); in wdm_rxwork()
801 if (rv < 0 && rv != -EPERM) { in wdm_rxwork()
802 spin_lock_irqsave(&desc->iuspin, flags); in wdm_rxwork()
803 clear_bit(WDM_RESPONDING, &desc->flags); in wdm_rxwork()
804 if (!test_bit(WDM_DISCONNECTING, &desc->flags)) in wdm_rxwork()
805 schedule_work(&desc->rxwork); in wdm_rxwork()
806 spin_unlock_irqrestore(&desc->iuspin, flags); in wdm_rxwork()
817 spin_lock_irq(&desc->iuspin); in service_interrupt_work()
819 if (!desc->resp_count) { in service_interrupt_work()
820 set_bit(WDM_READ, &desc->flags); in service_interrupt_work()
821 wake_up(&desc->wait); in service_interrupt_work()
823 spin_unlock_irq(&desc->iuspin); in service_interrupt_work()
826 /* --- hotplug --- */
831 int rv = -ENOMEM; in wdm_create()
837 INIT_LIST_HEAD(&desc->device_list); in wdm_create()
838 mutex_init(&desc->rlock); in wdm_create()
839 mutex_init(&desc->wlock); in wdm_create()
840 spin_lock_init(&desc->iuspin); in wdm_create()
841 init_waitqueue_head(&desc->wait); in wdm_create()
842 desc->wMaxCommand = bufsize; in wdm_create()
844 desc->inum = cpu_to_le16((u16)intf->cur_altsetting->desc.bInterfaceNumber); in wdm_create()
845 desc->intf = intf; in wdm_create()
846 INIT_WORK(&desc->rxwork, wdm_rxwork); in wdm_create()
847 INIT_WORK(&desc->service_outs_intr, service_interrupt_work); in wdm_create()
849 rv = -EINVAL; in wdm_create()
853 desc->wMaxPacketSize = usb_endpoint_maxp(ep); in wdm_create()
855 desc->orq = kmalloc(sizeof(struct usb_ctrlrequest), GFP_KERNEL); in wdm_create()
856 if (!desc->orq) in wdm_create()
858 desc->irq = kmalloc(sizeof(struct usb_ctrlrequest), GFP_KERNEL); in wdm_create()
859 if (!desc->irq) in wdm_create()
862 desc->validity = usb_alloc_urb(0, GFP_KERNEL); in wdm_create()
863 if (!desc->validity) in wdm_create()
866 desc->response = usb_alloc_urb(0, GFP_KERNEL); in wdm_create()
867 if (!desc->response) in wdm_create()
870 desc->command = usb_alloc_urb(0, GFP_KERNEL); in wdm_create()
871 if (!desc->command) in wdm_create()
874 desc->ubuf = kmalloc(desc->wMaxCommand, GFP_KERNEL); in wdm_create()
875 if (!desc->ubuf) in wdm_create()
878 desc->sbuf = kmalloc(desc->wMaxPacketSize, GFP_KERNEL); in wdm_create()
879 if (!desc->sbuf) in wdm_create()
882 desc->inbuf = kmalloc(desc->wMaxCommand, GFP_KERNEL); in wdm_create()
883 if (!desc->inbuf) in wdm_create()
887 desc->validity, in wdm_create()
889 usb_rcvintpipe(interface_to_usbdev(intf), ep->bEndpointAddress), in wdm_create()
890 desc->sbuf, in wdm_create()
891 desc->wMaxPacketSize, in wdm_create()
894 ep->bInterval in wdm_create()
897 desc->irq->bRequestType = (USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE); in wdm_create()
898 desc->irq->bRequest = USB_CDC_GET_ENCAPSULATED_RESPONSE; in wdm_create()
899 desc->irq->wValue = 0; in wdm_create()
900 desc->irq->wIndex = desc->inum; /* already converted */ in wdm_create()
901 desc->irq->wLength = cpu_to_le16(desc->wMaxCommand); in wdm_create()
904 desc->response, in wdm_create()
907 usb_rcvctrlpipe(interface_to_usbdev(desc->intf), 0), in wdm_create()
908 (unsigned char *)desc->irq, in wdm_create()
909 desc->inbuf, in wdm_create()
910 desc->wMaxCommand, in wdm_create()
915 desc->manage_power = manage_power; in wdm_create()
918 list_add(&desc->device_list, &wdm_device_list); in wdm_create()
925 dev_info(&intf->dev, "%s: USB WDM device\n", dev_name(intf->usb_dev)); in wdm_create()
930 list_del(&desc->device_list); in wdm_create()
941 intf->needs_remote_wakeup = on; in wdm_manage_power()
949 int rv = -EINVAL; in wdm_probe()
953 u8 *buffer = intf->altsetting->extra; in wdm_probe()
954 int buflen = intf->altsetting->extralen; in wdm_probe()
963 maxcom = le16_to_cpu(hdr.usb_cdc_dmm_desc->wMaxCommand); in wdm_probe()
965 iface = intf->cur_altsetting; in wdm_probe()
966 if (iface->desc.bNumEndpoints != 1) in wdm_probe()
968 ep = &iface->endpoint[0].desc; in wdm_probe()
977 * usb_cdc_wdm_register - register a WDM subdriver
981 * @manage_power: call-back invoked during open and release to
1023 spin_lock_irqsave(&desc->iuspin, flags); in wdm_disconnect()
1024 set_bit(WDM_DISCONNECTING, &desc->flags); in wdm_disconnect()
1025 set_bit(WDM_READ, &desc->flags); in wdm_disconnect()
1026 spin_unlock_irqrestore(&desc->iuspin, flags); in wdm_disconnect()
1027 wake_up_all(&desc->wait); in wdm_disconnect()
1028 mutex_lock(&desc->rlock); in wdm_disconnect()
1029 mutex_lock(&desc->wlock); in wdm_disconnect()
1031 cancel_work_sync(&desc->rxwork); in wdm_disconnect()
1032 cancel_work_sync(&desc->service_outs_intr); in wdm_disconnect()
1033 mutex_unlock(&desc->wlock); in wdm_disconnect()
1034 mutex_unlock(&desc->rlock); in wdm_disconnect()
1036 /* the desc->intf pointer used as list key is now invalid */ in wdm_disconnect()
1038 list_del(&desc->device_list); in wdm_disconnect()
1041 if (!desc->count) in wdm_disconnect()
1044 dev_dbg(&intf->dev, "%d open files - postponing cleanup\n", desc->count); in wdm_disconnect()
1054 dev_dbg(&desc->intf->dev, "wdm%d_suspend\n", intf->minor); in wdm_suspend()
1058 mutex_lock(&desc->rlock); in wdm_suspend()
1059 mutex_lock(&desc->wlock); in wdm_suspend()
1061 spin_lock_irq(&desc->iuspin); in wdm_suspend()
1064 (test_bit(WDM_IN_USE, &desc->flags) in wdm_suspend()
1065 || test_bit(WDM_RESPONDING, &desc->flags))) { in wdm_suspend()
1066 spin_unlock_irq(&desc->iuspin); in wdm_suspend()
1067 rv = -EBUSY; in wdm_suspend()
1070 set_bit(WDM_SUSPENDING, &desc->flags); in wdm_suspend()
1071 spin_unlock_irq(&desc->iuspin); in wdm_suspend()
1072 /* callback submits work - order is essential */ in wdm_suspend()
1074 cancel_work_sync(&desc->rxwork); in wdm_suspend()
1075 cancel_work_sync(&desc->service_outs_intr); in wdm_suspend()
1078 mutex_unlock(&desc->wlock); in wdm_suspend()
1079 mutex_unlock(&desc->rlock); in wdm_suspend()
1090 if (desc->count) { in recover_from_urb_loss()
1091 rv = usb_submit_urb(desc->validity, GFP_NOIO); in recover_from_urb_loss()
1093 dev_err(&desc->intf->dev, in recover_from_urb_loss()
1094 "Error resume submitting int urb - %d\n", rv); in recover_from_urb_loss()
1105 dev_dbg(&desc->intf->dev, "wdm%d_resume\n", intf->minor); in wdm_resume()
1107 clear_bit(WDM_SUSPENDING, &desc->flags); in wdm_resume()
1119 * we notify everybody using poll of in wdm_pre_reset()
1124 spin_lock_irq(&desc->iuspin); in wdm_pre_reset()
1125 set_bit(WDM_RESETTING, &desc->flags); /* inform read/write */ in wdm_pre_reset()
1126 set_bit(WDM_READ, &desc->flags); /* unblock read */ in wdm_pre_reset()
1127 clear_bit(WDM_IN_USE, &desc->flags); /* unblock write */ in wdm_pre_reset()
1128 desc->rerr = -EINTR; in wdm_pre_reset()
1129 spin_unlock_irq(&desc->iuspin); in wdm_pre_reset()
1130 wake_up_all(&desc->wait); in wdm_pre_reset()
1131 mutex_lock(&desc->rlock); in wdm_pre_reset()
1132 mutex_lock(&desc->wlock); in wdm_pre_reset()
1134 cancel_work_sync(&desc->rxwork); in wdm_pre_reset()
1135 cancel_work_sync(&desc->service_outs_intr); in wdm_pre_reset()
1144 clear_bit(WDM_OVERFLOW, &desc->flags); in wdm_post_reset()
1145 clear_bit(WDM_RESETTING, &desc->flags); in wdm_post_reset()
1147 mutex_unlock(&desc->wlock); in wdm_post_reset()
1148 mutex_unlock(&desc->rlock); in wdm_post_reset()