aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOliver Neukum <oneukum@suse.de>2011-03-11 08:51:12 -0500
committerTakashi Iwai <tiwai@suse.de>2011-03-11 08:59:29 -0500
commit88a8516a2128a6d078a106ead48092240e8a138f (patch)
treedc839c85a9b2fc2e17759c5a42368cb8300e42bc
parentedf7de31c25ce72f163bf7d1fc0d2711869d073c (diff)
ALSA: usbaudio: implement USB autosuspend
Devices are autosuspended if no pcm nor midi channel is open Mixer devices may be opened. This way they are active when in use to play or record sound, but can be suspended while users have a mixer application running. [Small clean-ups using static inline by tiwai] Signed-off-by: Oliver Neukum <oneukum@suse.de> Signed-off-by: Takashi Iwai <tiwai@suse.de>
-rw-r--r--sound/usb/card.c66
-rw-r--r--sound/usb/midi.c8
-rw-r--r--sound/usb/mixer.c23
-rw-r--r--sound/usb/pcm.c20
-rw-r--r--sound/usb/power.h17
-rw-r--r--sound/usb/usbaudio.h6
6 files changed, 118 insertions, 22 deletions
diff --git a/sound/usb/card.c b/sound/usb/card.c
index 7fa53d91e73b..40722f8711ad 100644
--- a/sound/usb/card.c
+++ b/sound/usb/card.c
@@ -65,6 +65,7 @@
65#include "pcm.h" 65#include "pcm.h"
66#include "urb.h" 66#include "urb.h"
67#include "format.h" 67#include "format.h"
68#include "power.h"
68 69
69MODULE_AUTHOR("Takashi Iwai <tiwai@suse.de>"); 70MODULE_AUTHOR("Takashi Iwai <tiwai@suse.de>");
70MODULE_DESCRIPTION("USB Audio"); 71MODULE_DESCRIPTION("USB Audio");
@@ -330,6 +331,7 @@ static int snd_usb_audio_create(struct usb_device *dev, int idx,
330 chip->setup = device_setup[idx]; 331 chip->setup = device_setup[idx];
331 chip->nrpacks = nrpacks; 332 chip->nrpacks = nrpacks;
332 chip->async_unlink = async_unlink; 333 chip->async_unlink = async_unlink;
334 chip->probing = 1;
333 335
334 chip->usb_id = USB_ID(le16_to_cpu(dev->descriptor.idVendor), 336 chip->usb_id = USB_ID(le16_to_cpu(dev->descriptor.idVendor),
335 le16_to_cpu(dev->descriptor.idProduct)); 337 le16_to_cpu(dev->descriptor.idProduct));
@@ -451,6 +453,7 @@ static void *snd_usb_audio_probe(struct usb_device *dev,
451 goto __error; 453 goto __error;
452 } 454 }
453 chip = usb_chip[i]; 455 chip = usb_chip[i];
456 chip->probing = 1;
454 break; 457 break;
455 } 458 }
456 } 459 }
@@ -466,6 +469,7 @@ static void *snd_usb_audio_probe(struct usb_device *dev,
466 goto __error; 469 goto __error;
467 } 470 }
468 snd_card_set_dev(chip->card, &intf->dev); 471 snd_card_set_dev(chip->card, &intf->dev);
472 chip->pm_intf = intf;
469 break; 473 break;
470 } 474 }
471 if (!chip) { 475 if (!chip) {
@@ -505,6 +509,7 @@ static void *snd_usb_audio_probe(struct usb_device *dev,
505 509
506 usb_chip[chip->index] = chip; 510 usb_chip[chip->index] = chip;
507 chip->num_interfaces++; 511 chip->num_interfaces++;
512 chip->probing = 0;
508 mutex_unlock(&register_mutex); 513 mutex_unlock(&register_mutex);
509 return chip; 514 return chip;
510 515
@@ -581,6 +586,23 @@ static void usb_audio_disconnect(struct usb_interface *intf)
581} 586}
582 587
583#ifdef CONFIG_PM 588#ifdef CONFIG_PM
589
590int snd_usb_autoresume(struct snd_usb_audio *chip)
591{
592 int err = -ENODEV;
593
594 if (!chip->shutdown && !chip->probing)
595 err = usb_autopm_get_interface(chip->pm_intf);
596
597 return err;
598}
599
600void snd_usb_autosuspend(struct snd_usb_audio *chip)
601{
602 if (!chip->shutdown && !chip->probing)
603 usb_autopm_put_interface(chip->pm_intf);
604}
605
584static int usb_audio_suspend(struct usb_interface *intf, pm_message_t message) 606static int usb_audio_suspend(struct usb_interface *intf, pm_message_t message)
585{ 607{
586 struct snd_usb_audio *chip = usb_get_intfdata(intf); 608 struct snd_usb_audio *chip = usb_get_intfdata(intf);
@@ -591,18 +613,26 @@ static int usb_audio_suspend(struct usb_interface *intf, pm_message_t message)
591 if (chip == (void *)-1L) 613 if (chip == (void *)-1L)
592 return 0; 614 return 0;
593 615
594 snd_power_change_state(chip->card, SNDRV_CTL_POWER_D3hot); 616 if (!(message.event & PM_EVENT_AUTO)) {
595 if (!chip->num_suspended_intf++) { 617 snd_power_change_state(chip->card, SNDRV_CTL_POWER_D3hot);
596 list_for_each(p, &chip->pcm_list) { 618 if (!chip->num_suspended_intf++) {
597 as = list_entry(p, struct snd_usb_stream, list); 619 list_for_each(p, &chip->pcm_list) {
598 snd_pcm_suspend_all(as->pcm); 620 as = list_entry(p, struct snd_usb_stream, list);
599 } 621 snd_pcm_suspend_all(as->pcm);
600 622 }
601 list_for_each_entry(mixer, &chip->mixer_list, list) { 623 }
602 snd_usb_mixer_inactivate(mixer); 624 } else {
603 } 625 /*
626 * otherwise we keep the rest of the system in the dark
627 * to keep this transparent
628 */
629 if (!chip->num_suspended_intf++)
630 chip->autosuspended = 1;
604 } 631 }
605 632
633 list_for_each_entry(mixer, &chip->mixer_list, list)
634 snd_usb_mixer_inactivate(mixer);
635
606 return 0; 636 return 0;
607} 637}
608 638
@@ -610,6 +640,7 @@ static int usb_audio_resume(struct usb_interface *intf)
610{ 640{
611 struct snd_usb_audio *chip = usb_get_intfdata(intf); 641 struct snd_usb_audio *chip = usb_get_intfdata(intf);
612 struct usb_mixer_interface *mixer; 642 struct usb_mixer_interface *mixer;
643 int err = 0;
613 644
614 if (chip == (void *)-1L) 645 if (chip == (void *)-1L)
615 return 0; 646 return 0;
@@ -619,12 +650,18 @@ static int usb_audio_resume(struct usb_interface *intf)
619 * ALSA leaves material resumption to user space 650 * ALSA leaves material resumption to user space
620 * we just notify and restart the mixers 651 * we just notify and restart the mixers
621 */ 652 */
622 list_for_each_entry(mixer, &chip->mixer_list, list) 653 list_for_each_entry(mixer, &chip->mixer_list, list) {
623 snd_usb_mixer_activate(mixer); 654 err = snd_usb_mixer_activate(mixer);
655 if (err < 0)
656 goto err_out;
657 }
624 658
625 snd_power_change_state(chip->card, SNDRV_CTL_POWER_D0); 659 if (!chip->autosuspended)
660 snd_power_change_state(chip->card, SNDRV_CTL_POWER_D0);
661 chip->autosuspended = 0;
626 662
627 return 0; 663err_out:
664 return err;
628} 665}
629#else 666#else
630#define usb_audio_suspend NULL 667#define usb_audio_suspend NULL
@@ -652,6 +689,7 @@ static struct usb_driver usb_audio_driver = {
652 .suspend = usb_audio_suspend, 689 .suspend = usb_audio_suspend,
653 .resume = usb_audio_resume, 690 .resume = usb_audio_resume,
654 .id_table = usb_audio_ids, 691 .id_table = usb_audio_ids,
692 .supports_autosuspend = 1,
655}; 693};
656 694
657static int __init snd_usb_audio_init(void) 695static int __init snd_usb_audio_init(void)
diff --git a/sound/usb/midi.c b/sound/usb/midi.c
index db2dc5ffe6dd..b4b39c0b6c9e 100644
--- a/sound/usb/midi.c
+++ b/sound/usb/midi.c
@@ -54,6 +54,7 @@
54#include <sound/asequencer.h> 54#include <sound/asequencer.h>
55#include "usbaudio.h" 55#include "usbaudio.h"
56#include "midi.h" 56#include "midi.h"
57#include "power.h"
57#include "helper.h" 58#include "helper.h"
58 59
59/* 60/*
@@ -1044,6 +1045,7 @@ static int snd_usbmidi_output_open(struct snd_rawmidi_substream *substream)
1044 struct snd_usb_midi* umidi = substream->rmidi->private_data; 1045 struct snd_usb_midi* umidi = substream->rmidi->private_data;
1045 struct usbmidi_out_port* port = NULL; 1046 struct usbmidi_out_port* port = NULL;
1046 int i, j; 1047 int i, j;
1048 int err;
1047 1049
1048 for (i = 0; i < MIDI_MAX_ENDPOINTS; ++i) 1050 for (i = 0; i < MIDI_MAX_ENDPOINTS; ++i)
1049 if (umidi->endpoints[i].out) 1051 if (umidi->endpoints[i].out)
@@ -1056,6 +1058,9 @@ static int snd_usbmidi_output_open(struct snd_rawmidi_substream *substream)
1056 snd_BUG(); 1058 snd_BUG();
1057 return -ENXIO; 1059 return -ENXIO;
1058 } 1060 }
1061 err = usb_autopm_get_interface(umidi->iface);
1062 if (err < 0)
1063 return -EIO;
1059 substream->runtime->private_data = port; 1064 substream->runtime->private_data = port;
1060 port->state = STATE_UNKNOWN; 1065 port->state = STATE_UNKNOWN;
1061 substream_open(substream, 1); 1066 substream_open(substream, 1);
@@ -1064,7 +1069,10 @@ static int snd_usbmidi_output_open(struct snd_rawmidi_substream *substream)
1064 1069
1065static int snd_usbmidi_output_close(struct snd_rawmidi_substream *substream) 1070static int snd_usbmidi_output_close(struct snd_rawmidi_substream *substream)
1066{ 1071{
1072 struct snd_usb_midi* umidi = substream->rmidi->private_data;
1073
1067 substream_open(substream, 0); 1074 substream_open(substream, 0);
1075 usb_autopm_put_interface(umidi->iface);
1068 return 0; 1076 return 0;
1069} 1077}
1070 1078
diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c
index 09e59345bb6d..5e4775716607 100644
--- a/sound/usb/mixer.c
+++ b/sound/usb/mixer.c
@@ -61,6 +61,7 @@
61#include "mixer.h" 61#include "mixer.h"
62#include "helper.h" 62#include "helper.h"
63#include "mixer_quirks.h" 63#include "mixer_quirks.h"
64#include "power.h"
64 65
65#define MAX_ID_ELEMS 256 66#define MAX_ID_ELEMS 256
66 67
@@ -295,16 +296,22 @@ static int get_ctl_value_v1(struct usb_mixer_elem_info *cval, int request, int v
295 unsigned char buf[2]; 296 unsigned char buf[2];
296 int val_len = cval->val_type >= USB_MIXER_S16 ? 2 : 1; 297 int val_len = cval->val_type >= USB_MIXER_S16 ? 2 : 1;
297 int timeout = 10; 298 int timeout = 10;
299 int err;
298 300
301 err = snd_usb_autoresume(cval->mixer->chip);
302 if (err < 0)
303 return -EIO;
299 while (timeout-- > 0) { 304 while (timeout-- > 0) {
300 if (snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0), request, 305 if (snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0), request,
301 USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, 306 USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
302 validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), 307 validx, snd_usb_ctrl_intf(chip) | (cval->id << 8),
303 buf, val_len, 100) >= val_len) { 308 buf, val_len, 100) >= val_len) {
304 *value_ret = convert_signed_value(cval, snd_usb_combine_bytes(buf, val_len)); 309 *value_ret = convert_signed_value(cval, snd_usb_combine_bytes(buf, val_len));
310 snd_usb_autosuspend(cval->mixer->chip);
305 return 0; 311 return 0;
306 } 312 }
307 } 313 }
314 snd_usb_autosuspend(cval->mixer->chip);
308 snd_printdd(KERN_ERR "cannot get ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d\n", 315 snd_printdd(KERN_ERR "cannot get ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d\n",
309 request, validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), cval->val_type); 316 request, validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), cval->val_type);
310 return -EINVAL; 317 return -EINVAL;
@@ -328,12 +335,18 @@ static int get_ctl_value_v2(struct usb_mixer_elem_info *cval, int request, int v
328 335
329 memset(buf, 0, sizeof(buf)); 336 memset(buf, 0, sizeof(buf));
330 337
338 ret = snd_usb_autoresume(chip) ? -EIO : 0;
339 if (ret)
340 goto error;
341
331 ret = snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0), bRequest, 342 ret = snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0), bRequest,
332 USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, 343 USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
333 validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), 344 validx, snd_usb_ctrl_intf(chip) | (cval->id << 8),
334 buf, size, 1000); 345 buf, size, 1000);
346 snd_usb_autosuspend(chip);
335 347
336 if (ret < 0) { 348 if (ret < 0) {
349error:
337 snd_printk(KERN_ERR "cannot get ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d\n", 350 snd_printk(KERN_ERR "cannot get ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d\n",
338 request, validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), cval->val_type); 351 request, validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), cval->val_type);
339 return ret; 352 return ret;
@@ -413,7 +426,7 @@ int snd_usb_mixer_set_ctl_value(struct usb_mixer_elem_info *cval,
413{ 426{
414 struct snd_usb_audio *chip = cval->mixer->chip; 427 struct snd_usb_audio *chip = cval->mixer->chip;
415 unsigned char buf[2]; 428 unsigned char buf[2];
416 int val_len, timeout = 10; 429 int val_len, err, timeout = 10;
417 430
418 if (cval->mixer->protocol == UAC_VERSION_1) { 431 if (cval->mixer->protocol == UAC_VERSION_1) {
419 val_len = cval->val_type >= USB_MIXER_S16 ? 2 : 1; 432 val_len = cval->val_type >= USB_MIXER_S16 ? 2 : 1;
@@ -433,13 +446,19 @@ int snd_usb_mixer_set_ctl_value(struct usb_mixer_elem_info *cval,
433 value_set = convert_bytes_value(cval, value_set); 446 value_set = convert_bytes_value(cval, value_set);
434 buf[0] = value_set & 0xff; 447 buf[0] = value_set & 0xff;
435 buf[1] = (value_set >> 8) & 0xff; 448 buf[1] = (value_set >> 8) & 0xff;
449 err = snd_usb_autoresume(chip);
450 if (err < 0)
451 return -EIO;
436 while (timeout-- > 0) 452 while (timeout-- > 0)
437 if (snd_usb_ctl_msg(chip->dev, 453 if (snd_usb_ctl_msg(chip->dev,
438 usb_sndctrlpipe(chip->dev, 0), request, 454 usb_sndctrlpipe(chip->dev, 0), request,
439 USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT, 455 USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT,
440 validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), 456 validx, snd_usb_ctrl_intf(chip) | (cval->id << 8),
441 buf, val_len, 100) >= 0) 457 buf, val_len, 100) >= 0) {
458 snd_usb_autosuspend(chip);
442 return 0; 459 return 0;
460 }
461 snd_usb_autosuspend(chip);
443 snd_printdd(KERN_ERR "cannot set ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d, data = %#x/%#x\n", 462 snd_printdd(KERN_ERR "cannot set ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d, data = %#x/%#x\n",
444 request, validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), cval->val_type, buf[0], buf[1]); 463 request, validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), cval->val_type, buf[0], buf[1]);
445 return -EINVAL; 464 return -EINVAL;
diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c
index e3f680526cb5..b8dcbf407bbb 100644
--- a/sound/usb/pcm.c
+++ b/sound/usb/pcm.c
@@ -32,6 +32,7 @@
32#include "helper.h" 32#include "helper.h"
33#include "pcm.h" 33#include "pcm.h"
34#include "clock.h" 34#include "clock.h"
35#include "power.h"
35 36
36/* 37/*
37 * return the current pcm pointer. just based on the hwptr_done value. 38 * return the current pcm pointer. just based on the hwptr_done value.
@@ -739,6 +740,9 @@ static int setup_hw_info(struct snd_pcm_runtime *runtime, struct snd_usb_substre
739 pt = 125 * (1 << fp->datainterval); 740 pt = 125 * (1 << fp->datainterval);
740 ptmin = min(ptmin, pt); 741 ptmin = min(ptmin, pt);
741 } 742 }
743 err = snd_usb_autoresume(subs->stream->chip);
744 if (err < 0)
745 return err;
742 746
743 param_period_time_if_needed = SNDRV_PCM_HW_PARAM_PERIOD_TIME; 747 param_period_time_if_needed = SNDRV_PCM_HW_PARAM_PERIOD_TIME;
744 if (snd_usb_get_speed(subs->dev) == USB_SPEED_FULL) 748 if (snd_usb_get_speed(subs->dev) == USB_SPEED_FULL)
@@ -756,21 +760,21 @@ static int setup_hw_info(struct snd_pcm_runtime *runtime, struct snd_usb_substre
756 SNDRV_PCM_HW_PARAM_CHANNELS, 760 SNDRV_PCM_HW_PARAM_CHANNELS,
757 param_period_time_if_needed, 761 param_period_time_if_needed,
758 -1)) < 0) 762 -1)) < 0)
759 return err; 763 goto rep_err;
760 if ((err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, 764 if ((err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
761 hw_rule_channels, subs, 765 hw_rule_channels, subs,
762 SNDRV_PCM_HW_PARAM_FORMAT, 766 SNDRV_PCM_HW_PARAM_FORMAT,
763 SNDRV_PCM_HW_PARAM_RATE, 767 SNDRV_PCM_HW_PARAM_RATE,
764 param_period_time_if_needed, 768 param_period_time_if_needed,
765 -1)) < 0) 769 -1)) < 0)
766 return err; 770 goto rep_err;
767 if ((err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_FORMAT, 771 if ((err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_FORMAT,
768 hw_rule_format, subs, 772 hw_rule_format, subs,
769 SNDRV_PCM_HW_PARAM_RATE, 773 SNDRV_PCM_HW_PARAM_RATE,
770 SNDRV_PCM_HW_PARAM_CHANNELS, 774 SNDRV_PCM_HW_PARAM_CHANNELS,
771 param_period_time_if_needed, 775 param_period_time_if_needed,
772 -1)) < 0) 776 -1)) < 0)
773 return err; 777 goto rep_err;
774 if (param_period_time_if_needed >= 0) { 778 if (param_period_time_if_needed >= 0) {
775 err = snd_pcm_hw_rule_add(runtime, 0, 779 err = snd_pcm_hw_rule_add(runtime, 0,
776 SNDRV_PCM_HW_PARAM_PERIOD_TIME, 780 SNDRV_PCM_HW_PARAM_PERIOD_TIME,
@@ -780,11 +784,15 @@ static int setup_hw_info(struct snd_pcm_runtime *runtime, struct snd_usb_substre
780 SNDRV_PCM_HW_PARAM_RATE, 784 SNDRV_PCM_HW_PARAM_RATE,
781 -1); 785 -1);
782 if (err < 0) 786 if (err < 0)
783 return err; 787 goto rep_err;
784 } 788 }
785 if ((err = snd_usb_pcm_check_knot(runtime, subs)) < 0) 789 if ((err = snd_usb_pcm_check_knot(runtime, subs)) < 0)
786 return err; 790 goto rep_err;
787 return 0; 791 return 0;
792
793rep_err:
794 snd_usb_autosuspend(subs->stream->chip);
795 return err;
788} 796}
789 797
790static int snd_usb_pcm_open(struct snd_pcm_substream *substream, int direction) 798static int snd_usb_pcm_open(struct snd_pcm_substream *substream, int direction)
@@ -798,6 +806,7 @@ static int snd_usb_pcm_open(struct snd_pcm_substream *substream, int direction)
798 runtime->hw = snd_usb_hardware; 806 runtime->hw = snd_usb_hardware;
799 runtime->private_data = subs; 807 runtime->private_data = subs;
800 subs->pcm_substream = substream; 808 subs->pcm_substream = substream;
809 /* runtime PM is also done there */
801 return setup_hw_info(runtime, subs); 810 return setup_hw_info(runtime, subs);
802} 811}
803 812
@@ -811,6 +820,7 @@ static int snd_usb_pcm_close(struct snd_pcm_substream *substream, int direction)
811 subs->interface = -1; 820 subs->interface = -1;
812 } 821 }
813 subs->pcm_substream = NULL; 822 subs->pcm_substream = NULL;
823 snd_usb_autosuspend(subs->stream->chip);
814 return 0; 824 return 0;
815} 825}
816 826
diff --git a/sound/usb/power.h b/sound/usb/power.h
new file mode 100644
index 000000000000..48ee51dcb71e
--- /dev/null
+++ b/sound/usb/power.h
@@ -0,0 +1,17 @@
1#ifndef __USBAUDIO_POWER_H
2#define __USBAUDIO_POWER_H
3
4#ifdef CONFIG_PM
5int snd_usb_autoresume(struct snd_usb_audio *chip);
6void snd_usb_autosuspend(struct snd_usb_audio *chip);
7#else
8static inline int snd_usb_autoresume(struct snd_usb_audio *chip)
9{
10 return 0;
11}
12static inline void snd_usb_autosuspend(struct snd_usb_audio *chip)
13{
14}
15#endif
16
17#endif /* __USBAUDIO_POWER_H */
diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h
index 6e66fffe87f5..32f2a97f2f14 100644
--- a/sound/usb/usbaudio.h
+++ b/sound/usb/usbaudio.h
@@ -34,10 +34,14 @@ struct snd_usb_audio {
34 int index; 34 int index;
35 struct usb_device *dev; 35 struct usb_device *dev;
36 struct snd_card *card; 36 struct snd_card *card;
37 struct usb_interface *pm_intf;
37 u32 usb_id; 38 u32 usb_id;
38 int shutdown;
39 struct mutex shutdown_mutex; 39 struct mutex shutdown_mutex;
40 unsigned int shutdown:1;
41 unsigned int probing:1;
42 unsigned int autosuspended:1;
40 unsigned int txfr_quirk:1; /* Subframe boundaries on transfers */ 43 unsigned int txfr_quirk:1; /* Subframe boundaries on transfers */
44
41 int num_interfaces; 45 int num_interfaces;
42 int num_suspended_intf; 46 int num_suspended_intf;
43 47