diff options
Diffstat (limited to 'drivers/usb/gadget')
24 files changed, 629 insertions, 338 deletions
diff --git a/drivers/usb/gadget/config.c b/drivers/usb/gadget/config.c index 2d115353424c..8bb25773b61e 100644 --- a/drivers/usb/gadget/config.c +++ b/drivers/usb/gadget/config.c @@ -194,9 +194,13 @@ EXPORT_SYMBOL_GPL(usb_assign_descriptors); void usb_free_all_descriptors(struct usb_function *f) { usb_free_descriptors(f->fs_descriptors); + f->fs_descriptors = NULL; usb_free_descriptors(f->hs_descriptors); + f->hs_descriptors = NULL; usb_free_descriptors(f->ss_descriptors); + f->ss_descriptors = NULL; usb_free_descriptors(f->ssp_descriptors); + f->ssp_descriptors = NULL; } EXPORT_SYMBOL_GPL(usb_free_all_descriptors); diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c index 801a8b668a35..bf109191659a 100644 --- a/drivers/usb/gadget/function/f_fs.c +++ b/drivers/usb/gadget/function/f_fs.c @@ -2640,6 +2640,7 @@ static int __ffs_data_got_strings(struct ffs_data *ffs, do { /* lang_count > 0 so we can use do-while */ unsigned needed = needed_count; + u32 str_per_lang = str_count; if (len < 3) goto error_free; @@ -2675,7 +2676,7 @@ static int __ffs_data_got_strings(struct ffs_data *ffs, data += length + 1; len -= length + 1; - } while (--str_count); + } while (--str_per_lang); s->id = 0; /* terminator */ s->s = NULL; @@ -3826,14 +3827,9 @@ static char *ffs_prepare_buffer(const char __user *buf, size_t len) if (!len) return NULL; - data = kmalloc(len, GFP_KERNEL); - if (!data) - return ERR_PTR(-ENOMEM); - - if (copy_from_user(data, buf, len)) { - kfree(data); - return ERR_PTR(-EFAULT); - } + data = memdup_user(buf, len); + if (IS_ERR(data)) + return ERR_PTR(PTR_ERR(data)); pr_vdebug("Buffer from user space:\n"); ffs_dump_mem("", data, len); diff --git a/drivers/usb/gadget/function/f_mass_storage.c b/drivers/usb/gadget/function/f_mass_storage.c index 950c9435beec..4a4703634a2a 100644 --- a/drivers/usb/gadget/function/f_mass_storage.c +++ b/drivers/usb/gadget/function/f_mass_storage.c @@ -351,8 +351,6 @@ static inline struct fsg_dev *fsg_from_func(struct usb_function *f) return container_of(f, struct fsg_dev, function); } -typedef void (*fsg_routine_t)(struct fsg_dev *); - static int exception_in_progress(struct fsg_common *common) { return common->state > FSG_STATE_NORMAL; diff --git a/drivers/usb/gadget/function/f_printer.c b/drivers/usb/gadget/function/f_printer.c index 61ce8e68f7a3..f47fdc1fa7f1 100644 --- a/drivers/usb/gadget/function/f_printer.c +++ b/drivers/usb/gadget/function/f_printer.c @@ -825,7 +825,7 @@ set_printer_interface(struct printer_dev *dev) result = usb_ep_enable(dev->out_ep); if (result != 0) { - DBG(dev, "enable %s --> %d\n", dev->in_ep->name, result); + DBG(dev, "enable %s --> %d\n", dev->out_ep->name, result); goto done; } diff --git a/drivers/usb/gadget/function/f_tcm.c b/drivers/usb/gadget/function/f_tcm.c index 410fa89eae8f..7acb507946e6 100644 --- a/drivers/usb/gadget/function/f_tcm.c +++ b/drivers/usb/gadget/function/f_tcm.c @@ -1050,19 +1050,17 @@ static void usbg_cmd_work(struct work_struct *work) tv_nexus = tpg->tpg_nexus; dir = get_cmd_dir(cmd->cmd_buf); if (dir < 0) { - transport_init_se_cmd(se_cmd, - tv_nexus->tvn_se_sess->se_tpg->se_tpg_tfo, - tv_nexus->tvn_se_sess, cmd->data_len, DMA_NONE, - cmd->prio_attr, cmd->sense_iu.sense, - cmd->unpacked_lun); + __target_init_cmd(se_cmd, + tv_nexus->tvn_se_sess->se_tpg->se_tpg_tfo, + tv_nexus->tvn_se_sess, cmd->data_len, DMA_NONE, + cmd->prio_attr, cmd->sense_iu.sense, + cmd->unpacked_lun); goto out; } - if (target_submit_cmd(se_cmd, tv_nexus->tvn_se_sess, cmd->cmd_buf, - cmd->sense_iu.sense, cmd->unpacked_lun, 0, - cmd->prio_attr, dir, flags) < 0) - goto out; - + target_submit_cmd(se_cmd, tv_nexus->tvn_se_sess, cmd->cmd_buf, + cmd->sense_iu.sense, cmd->unpacked_lun, 0, + cmd->prio_attr, dir, flags); return; out: @@ -1181,19 +1179,17 @@ static void bot_cmd_work(struct work_struct *work) tv_nexus = tpg->tpg_nexus; dir = get_cmd_dir(cmd->cmd_buf); if (dir < 0) { - transport_init_se_cmd(se_cmd, - tv_nexus->tvn_se_sess->se_tpg->se_tpg_tfo, - tv_nexus->tvn_se_sess, cmd->data_len, DMA_NONE, - cmd->prio_attr, cmd->sense_iu.sense, - cmd->unpacked_lun); + __target_init_cmd(se_cmd, + tv_nexus->tvn_se_sess->se_tpg->se_tpg_tfo, + tv_nexus->tvn_se_sess, cmd->data_len, DMA_NONE, + cmd->prio_attr, cmd->sense_iu.sense, + cmd->unpacked_lun); goto out; } - if (target_submit_cmd(se_cmd, tv_nexus->tvn_se_sess, - cmd->cmd_buf, cmd->sense_iu.sense, cmd->unpacked_lun, - cmd->data_len, cmd->prio_attr, dir, 0) < 0) - goto out; - + target_submit_cmd(se_cmd, tv_nexus->tvn_se_sess, + cmd->cmd_buf, cmd->sense_iu.sense, cmd->unpacked_lun, + cmd->data_len, cmd->prio_attr, dir, 0); return; out: diff --git a/drivers/usb/gadget/function/f_uac1.c b/drivers/usb/gadget/function/f_uac1.c index 560382e0a8f3..d04707580068 100644 --- a/drivers/usb/gadget/function/f_uac1.c +++ b/drivers/usb/gadget/function/f_uac1.c @@ -19,6 +19,12 @@ #include "u_audio.h" #include "u_uac1.h" +/* UAC1 spec: 3.7.2.3 Audio Channel Cluster Format */ +#define UAC1_CHANNEL_MASK 0x0FFF + +#define EPIN_EN(_opts) ((_opts)->p_chmask != 0) +#define EPOUT_EN(_opts) ((_opts)->c_chmask != 0) + struct f_uac1 { struct g_audio g_audio; u8 ac_intf, as_in_intf, as_out_intf; @@ -30,6 +36,11 @@ static inline struct f_uac1 *func_to_uac1(struct usb_function *f) return container_of(f, struct f_uac1, g_audio.func); } +static inline struct f_uac1_opts *g_audio_to_uac1_opts(struct g_audio *audio) +{ + return container_of(audio->func.fi, struct f_uac1_opts, func_inst); +} + /* * DESCRIPTORS ... most are static, but strings and full * configuration descriptors are built on demand. @@ -42,11 +53,6 @@ static inline struct f_uac1 *func_to_uac1(struct usb_function *f) * USB-OUT -> IT_1 -> OT_2 -> ALSA_Capture * ALSA_Playback -> IT_3 -> OT_4 -> USB-IN */ -#define F_AUDIO_AC_INTERFACE 0 -#define F_AUDIO_AS_OUT_INTERFACE 1 -#define F_AUDIO_AS_IN_INTERFACE 2 -/* Number of streaming interfaces */ -#define F_AUDIO_NUM_INTERFACES 2 /* B.3.1 Standard AC Interface Descriptor */ static struct usb_interface_descriptor ac_interface_desc = { @@ -57,73 +63,47 @@ static struct usb_interface_descriptor ac_interface_desc = { .bInterfaceSubClass = USB_SUBCLASS_AUDIOCONTROL, }; -/* - * The number of AudioStreaming and MIDIStreaming interfaces - * in the Audio Interface Collection - */ -DECLARE_UAC_AC_HEADER_DESCRIPTOR(2); - -#define UAC_DT_AC_HEADER_LENGTH UAC_DT_AC_HEADER_SIZE(F_AUDIO_NUM_INTERFACES) -/* 2 input terminals and 2 output terminals */ -#define UAC_DT_TOTAL_LENGTH (UAC_DT_AC_HEADER_LENGTH \ - + 2*UAC_DT_INPUT_TERMINAL_SIZE + 2*UAC_DT_OUTPUT_TERMINAL_SIZE) /* B.3.2 Class-Specific AC Interface Descriptor */ -static struct uac1_ac_header_descriptor_2 ac_header_desc = { - .bLength = UAC_DT_AC_HEADER_LENGTH, - .bDescriptorType = USB_DT_CS_INTERFACE, - .bDescriptorSubtype = UAC_HEADER, - .bcdADC = cpu_to_le16(0x0100), - .wTotalLength = cpu_to_le16(UAC_DT_TOTAL_LENGTH), - .bInCollection = F_AUDIO_NUM_INTERFACES, - .baInterfaceNr = { - /* Interface number of the AudioStream interfaces */ - [0] = 1, - [1] = 2, - } -}; +static struct uac1_ac_header_descriptor *ac_header_desc; -#define USB_OUT_IT_ID 1 static struct uac_input_terminal_descriptor usb_out_it_desc = { .bLength = UAC_DT_INPUT_TERMINAL_SIZE, .bDescriptorType = USB_DT_CS_INTERFACE, .bDescriptorSubtype = UAC_INPUT_TERMINAL, - .bTerminalID = USB_OUT_IT_ID, + /* .bTerminalID = DYNAMIC */ .wTerminalType = cpu_to_le16(UAC_TERMINAL_STREAMING), .bAssocTerminal = 0, .wChannelConfig = cpu_to_le16(0x3), }; -#define IO_OUT_OT_ID 2 static struct uac1_output_terminal_descriptor io_out_ot_desc = { .bLength = UAC_DT_OUTPUT_TERMINAL_SIZE, .bDescriptorType = USB_DT_CS_INTERFACE, .bDescriptorSubtype = UAC_OUTPUT_TERMINAL, - .bTerminalID = IO_OUT_OT_ID, + /* .bTerminalID = DYNAMIC */ .wTerminalType = cpu_to_le16(UAC_OUTPUT_TERMINAL_SPEAKER), .bAssocTerminal = 0, - .bSourceID = USB_OUT_IT_ID, + /* .bSourceID = DYNAMIC */ }; -#define IO_IN_IT_ID 3 static struct uac_input_terminal_descriptor io_in_it_desc = { .bLength = UAC_DT_INPUT_TERMINAL_SIZE, .bDescriptorType = USB_DT_CS_INTERFACE, .bDescriptorSubtype = UAC_INPUT_TERMINAL, - .bTerminalID = IO_IN_IT_ID, + /* .bTerminalID = DYNAMIC */ .wTerminalType = cpu_to_le16(UAC_INPUT_TERMINAL_MICROPHONE), .bAssocTerminal = 0, .wChannelConfig = cpu_to_le16(0x3), }; -#define USB_IN_OT_ID 4 static struct uac1_output_terminal_descriptor usb_in_ot_desc = { .bLength = UAC_DT_OUTPUT_TERMINAL_SIZE, .bDescriptorType = USB_DT_CS_INTERFACE, .bDescriptorSubtype = UAC_OUTPUT_TERMINAL, - .bTerminalID = USB_IN_OT_ID, + /* .bTerminalID = DYNAMIC */ .wTerminalType = cpu_to_le16(UAC_TERMINAL_STREAMING), .bAssocTerminal = 0, - .bSourceID = IO_IN_IT_ID, + /* .bSourceID = DYNAMIC */ }; /* B.4.1 Standard AS Interface Descriptor */ @@ -168,7 +148,7 @@ static struct uac1_as_header_descriptor as_out_header_desc = { .bLength = UAC_DT_AS_HEADER_SIZE, .bDescriptorType = USB_DT_CS_INTERFACE, .bDescriptorSubtype = UAC_AS_GENERAL, - .bTerminalLink = USB_OUT_IT_ID, + /* .bTerminalLink = DYNAMIC */ .bDelay = 1, .wFormatTag = cpu_to_le16(UAC_FORMAT_TYPE_I_PCM), }; @@ -177,7 +157,7 @@ static struct uac1_as_header_descriptor as_in_header_desc = { .bLength = UAC_DT_AS_HEADER_SIZE, .bDescriptorType = USB_DT_CS_INTERFACE, .bDescriptorSubtype = UAC_AS_GENERAL, - .bTerminalLink = USB_IN_OT_ID, + /* .bTerminalLink = DYNAMIC */ .bDelay = 1, .wFormatTag = cpu_to_le16(UAC_FORMAT_TYPE_I_PCM), }; @@ -505,11 +485,144 @@ static void f_audio_disable(struct usb_function *f) /*-------------------------------------------------------------------------*/ +static struct +uac1_ac_header_descriptor *build_ac_header_desc(struct f_uac1_opts *opts) +{ + struct uac1_ac_header_descriptor *ac_desc; + int ac_header_desc_size; + int num_ifaces = 0; + + if (EPOUT_EN(opts)) + num_ifaces++; + if (EPIN_EN(opts)) + num_ifaces++; + + ac_header_desc_size = UAC_DT_AC_HEADER_SIZE(num_ifaces); + + ac_desc = kzalloc(ac_header_desc_size, GFP_KERNEL); + if (!ac_desc) + return NULL; + + ac_desc->bLength = ac_header_desc_size; + ac_desc->bDescriptorType = USB_DT_CS_INTERFACE; + ac_desc->bDescriptorSubtype = UAC_HEADER; + ac_desc->bcdADC = cpu_to_le16(0x0100); + ac_desc->bInCollection = num_ifaces; + + /* wTotalLength and baInterfaceNr will be defined later */ + + return ac_desc; +} + +/* Use macro to overcome line length limitation */ +#define USBDHDR(p) (struct usb_descriptor_header *)(p) + +static void setup_descriptor(struct f_uac1_opts *opts) +{ + /* patch descriptors */ + int i = 1; /* ID's start with 1 */ + + if (EPOUT_EN(opts)) + usb_out_it_desc.bTerminalID = i++; + if (EPIN_EN(opts)) + io_in_it_desc.bTerminalID = i++; + if (EPOUT_EN(opts)) + io_out_ot_desc.bTerminalID = i++; + if (EPIN_EN(opts)) + usb_in_ot_desc.bTerminalID = i++; + + usb_in_ot_desc.bSourceID = io_in_it_desc.bTerminalID; + io_out_ot_desc.bSourceID = usb_out_it_desc.bTerminalID; + + as_out_header_desc.bTerminalLink = usb_out_it_desc.bTerminalID; + as_in_header_desc.bTerminalLink = usb_in_ot_desc.bTerminalID; + + ac_header_desc->wTotalLength = cpu_to_le16(ac_header_desc->bLength); + + if (EPIN_EN(opts)) { + u16 len = le16_to_cpu(ac_header_desc->wTotalLength); + + len += sizeof(usb_in_ot_desc); + len += sizeof(io_in_it_desc); + ac_header_desc->wTotalLength = cpu_to_le16(len); + } + if (EPOUT_EN(opts)) { + u16 len = le16_to_cpu(ac_header_desc->wTotalLength); + + len += sizeof(usb_out_it_desc); + len += sizeof(io_out_ot_desc); + ac_header_desc->wTotalLength = cpu_to_le16(len); + } + + i = 0; + f_audio_desc[i++] = USBDHDR(&ac_interface_desc); + f_audio_desc[i++] = USBDHDR(ac_header_desc); + + if (EPOUT_EN(opts)) { + f_audio_desc[i++] = USBDHDR(&usb_out_it_desc); + f_audio_desc[i++] = USBDHDR(&io_out_ot_desc); + } + + if (EPIN_EN(opts)) { + f_audio_desc[i++] = USBDHDR(&io_in_it_desc); + f_audio_desc[i++] = USBDHDR(&usb_in_ot_desc); + } + + if (EPOUT_EN(opts)) { + f_audio_desc[i++] = USBDHDR(&as_out_interface_alt_0_desc); + f_audio_desc[i++] = USBDHDR(&as_out_interface_alt_1_desc); + f_audio_desc[i++] = USBDHDR(&as_out_header_desc); + f_audio_desc[i++] = USBDHDR(&as_out_type_i_desc); + f_audio_desc[i++] = USBDHDR(&as_out_ep_desc); + f_audio_desc[i++] = USBDHDR(&as_iso_out_desc); + } + if (EPIN_EN(opts)) { + f_audio_desc[i++] = USBDHDR(&as_in_interface_alt_0_desc); + f_audio_desc[i++] = USBDHDR(&as_in_interface_alt_1_desc); + f_audio_desc[i++] = USBDHDR(&as_in_header_desc); + f_audio_desc[i++] = USBDHDR(&as_in_type_i_desc); + f_audio_desc[i++] = USBDHDR(&as_in_ep_desc); + f_audio_desc[i++] = USBDHDR(&as_iso_in_desc); + } + f_audio_desc[i] = NULL; +} + +static int f_audio_validate_opts(struct g_audio *audio, struct device *dev) +{ + struct f_uac1_opts *opts = g_audio_to_uac1_opts(audio); + + if (!opts->p_chmask && !opts->c_chmask) { + dev_err(dev, "Error: no playback and capture channels\n"); + return -EINVAL; + } else if (opts->p_chmask & ~UAC1_CHANNEL_MASK) { + dev_err(dev, "Error: unsupported playback channels mask\n"); + return -EINVAL; + } else if (opts->c_chmask & ~UAC1_CHANNEL_MASK) { + dev_err(dev, "Error: unsupported capture channels mask\n"); + return -EINVAL; + } else if ((opts->p_ssize < 1) || (opts->p_ssize > 4)) { + dev_err(dev, "Error: incorrect playback sample size\n"); + return -EINVAL; + } else if ((opts->c_ssize < 1) || (opts->c_ssize > 4)) { + dev_err(dev, "Error: incorrect capture sample size\n"); + return -EINVAL; + } else if (!opts->p_srate) { + dev_err(dev, "Error: incorrect playback sampling rate\n"); + return -EINVAL; + } else if (!opts->c_srate) { + dev_err(dev, "Error: incorrect capture sampling rate\n"); + return -EINVAL; + } + + return 0; +} + /* audio function driver setup/binding */ static int f_audio_bind(struct usb_configuration *c, struct usb_function *f) { struct usb_composite_dev *cdev = c->cdev; struct usb_gadget *gadget = cdev->gadget; + struct device *dev = &gadget->dev; struct f_uac1 *uac1 = func_to_uac1(f); struct g_audio *audio = func_to_g_audio(f); struct f_uac1_opts *audio_opts; @@ -517,13 +630,23 @@ static int f_audio_bind(struct usb_configuration *c, struct usb_function *f) struct usb_string *us; u8 *sam_freq; int rate; + int ba_iface_id; int status; + status = f_audio_validate_opts(audio, dev); + if (status) + return status; + audio_opts = container_of(f->fi, struct f_uac1_opts, func_inst); us = usb_gstrings_attach(cdev, uac1_strings, ARRAY_SIZE(strings_uac1)); if (IS_ERR(us)) return PTR_ERR(us); + + ac_header_desc = build_ac_header_desc(audio_opts); + if (!ac_header_desc) + return -ENOMEM; + ac_interface_desc.iInterface = us[STR_AC_IF].id; usb_out_it_desc.iTerminal = us[STR_USB_OUT_IT].id; usb_out_it_desc.iChannelNames = us[STR_USB_OUT_IT_CH_NAMES].id; @@ -564,40 +687,52 @@ static int f_audio_bind(struct usb_configuration *c, struct usb_function *f) uac1->ac_intf = status; uac1->ac_alt = 0; - status = usb_interface_id(c, f); - if (status < 0) - goto fail; - as_out_interface_alt_0_desc.bInterfaceNumber = status; - as_out_interface_alt_1_desc.bInterfaceNumber = status; - ac_header_desc.baInterfaceNr[0] = status; - uac1->as_out_intf = status; - uac1->as_out_alt = 0; + ba_iface_id = 0; + + if (EPOUT_EN(audio_opts)) { + status = usb_interface_id(c, f); + if (status < 0) + goto fail; + as_out_interface_alt_0_desc.bInterfaceNumber = status; + as_out_interface_alt_1_desc.bInterfaceNumber = status; + ac_header_desc->baInterfaceNr[ba_iface_id++] = status; + uac1->as_out_intf = status; + uac1->as_out_alt = 0; + } - status = usb_interface_id(c, f); - if (status < 0) - goto fail; - as_in_interface_alt_0_desc.bInterfaceNumber = status; - as_in_interface_alt_1_desc.bInterfaceNumber = status; - ac_header_desc.baInterfaceNr[1] = status; - uac1->as_in_intf = status; - uac1->as_in_alt = 0; + if (EPIN_EN(audio_opts)) { + status = usb_interface_id(c, f); + if (status < 0) + goto fail; + as_in_interface_alt_0_desc.bInterfaceNumber = status; + as_in_interface_alt_1_desc.bInterfaceNumber = status; + ac_header_desc->baInterfaceNr[ba_iface_id++] = status; + uac1->as_in_intf = status; + uac1->as_in_alt = 0; + } audio->gadget = gadget; status = -ENODEV; /* allocate instance-specific endpoints */ - ep = usb_ep_autoconfig(cdev->gadget, &as_out_ep_desc); - if (!ep) - goto fail; - audio->out_ep = ep; - audio->out_ep->desc = &as_out_ep_desc; + if (EPOUT_EN(audio_opts)) { + ep = usb_ep_autoconfig(cdev->gadget, &as_out_ep_desc); + if (!ep) + goto fail; + audio->out_ep = ep; + audio->out_ep->desc = &as_out_ep_desc; + } - ep = usb_ep_autoconfig(cdev->gadget, &as_in_ep_desc); - if (!ep) - goto fail; - audio->in_ep = ep; - audio->in_ep->desc = &as_in_ep_desc; + if (EPIN_EN(audio_opts)) { + ep = usb_ep_autoconfig(cdev->gadget, &as_in_ep_desc); + if (!ep) + goto fail; + audio->in_ep = ep; + audio->in_ep->desc = &as_in_ep_desc; + } + + setup_descriptor(audio_opts); /* copy descriptors, and track endpoint copies */ status = usb_assign_descriptors(f, f_audio_desc, f_audio_desc, NULL, @@ -624,6 +759,8 @@ static int f_audio_bind(struct usb_configuration *c, struct usb_function *f) err_card_register: usb_free_all_descriptors(f); fail: + kfree(ac_header_desc); + ac_header_desc = NULL; return status; } @@ -766,6 +903,9 @@ static void f_audio_unbind(struct usb_configuration *c, struct usb_function *f) g_audio_cleanup(audio); usb_free_all_descriptors(f); + kfree(ac_header_desc); + ac_header_desc = NULL; + audio->gadget = NULL; } diff --git a/drivers/usb/gadget/function/f_uac2.c b/drivers/usb/gadget/function/f_uac2.c index 6f03e944e0e3..7aa4c8bc5a1a 100644 --- a/drivers/usb/gadget/function/f_uac2.c +++ b/drivers/usb/gadget/function/f_uac2.c @@ -14,6 +14,9 @@ #include "u_audio.h" #include "u_uac2.h" +/* UAC2 spec: 4.1 Audio Channel Cluster Descriptor */ +#define UAC2_CHANNEL_MASK 0x07FFFFFF + /* * The driver implements a simple UAC_2 topology. * USB-OUT -> IT_1 -> OT_3 -> ALSA_Capture @@ -284,6 +287,24 @@ static struct usb_endpoint_descriptor hs_epout_desc = { .bInterval = 4, }; +static struct usb_endpoint_descriptor ss_epout_desc = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + + .bEndpointAddress = USB_DIR_OUT, + .bmAttributes = USB_ENDPOINT_XFER_ISOC | USB_ENDPOINT_SYNC_ASYNC, + /* .wMaxPacketSize = DYNAMIC */ + .bInterval = 4, +}; + +static struct usb_ss_ep_comp_descriptor ss_epout_desc_comp = { + .bLength = sizeof(ss_epout_desc_comp), + .bDescriptorType = USB_DT_SS_ENDPOINT_COMP, + .bMaxBurst = 0, + .bmAttributes = 0, + /* wBytesPerInterval = DYNAMIC */ +}; + /* CS AS ISO OUT Endpoint */ static struct uac2_iso_endpoint_descriptor as_iso_out_desc = { .bLength = sizeof as_iso_out_desc, @@ -361,6 +382,24 @@ static struct usb_endpoint_descriptor hs_epin_desc = { .bInterval = 4, }; +static struct usb_endpoint_descriptor ss_epin_desc = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + + .bEndpointAddress = USB_DIR_IN, + .bmAttributes = USB_ENDPOINT_XFER_ISOC | USB_ENDPOINT_SYNC_ASYNC, + /* .wMaxPacketSize = DYNAMIC */ + .bInterval = 4, +}; + +static struct usb_ss_ep_comp_descriptor ss_epin_desc_comp = { + .bLength = sizeof(ss_epin_desc_comp), + .bDescriptorType = USB_DT_SS_ENDPOINT_COMP, + .bMaxBurst = 0, + .bmAttributes = 0, + /* wBytesPerInterval = DYNAMIC */ +}; + /* CS AS ISO IN Endpoint */ static struct uac2_iso_endpoint_descriptor as_iso_in_desc = { .bLength = sizeof as_iso_in_desc, @@ -433,6 +472,38 @@ static struct usb_descriptor_header *hs_audio_desc[] = { NULL, }; +static struct usb_descriptor_header *ss_audio_desc[] = { + (struct usb_descriptor_header *)&iad_desc, + (struct usb_descriptor_header *)&std_ac_if_desc, + + (struct usb_descriptor_header *)&ac_hdr_desc, + (struct usb_descriptor_header *)&in_clk_src_desc, + (struct usb_descriptor_header *)&out_clk_src_desc, + (struct usb_descriptor_header *)&usb_out_it_desc, + (struct usb_descriptor_header *)&io_in_it_desc, + (struct usb_descriptor_header *)&usb_in_ot_desc, + (struct usb_descriptor_header *)&io_out_ot_desc, + + (struct usb_descriptor_header *)&std_as_out_if0_desc, + (struct usb_descriptor_header *)&std_as_out_if1_desc, + + (struct usb_descriptor_header *)&as_out_hdr_desc, + (struct usb_descriptor_header *)&as_out_fmt1_desc, + (struct usb_descriptor_header *)&ss_epout_desc, + (struct usb_descriptor_header *)&ss_epout_desc_comp, + (struct usb_descriptor_header *)&as_iso_out_desc, + + (struct usb_descriptor_header *)&std_as_in_if0_desc, + (struct usb_descriptor_header *)&std_as_in_if1_desc, + + (struct usb_descriptor_header *)&as_in_hdr_desc, + (struct usb_descriptor_header *)&as_in_fmt1_desc, + (struct usb_descriptor_header *)&ss_epin_desc, + (struct usb_descriptor_header *)&ss_epin_desc_comp, + (struct usb_descriptor_header *)&as_iso_in_desc, + NULL, +}; + struct cntrl_cur_lay3 { __le32 dCUR; }; @@ -459,6 +530,7 @@ static int set_ep_max_packet_size(const struct f_uac2_opts *uac2_opts, break; case USB_SPEED_HIGH: + case USB_SPEED_SUPER: max_size_ep = 1024; factor = 8000; break; @@ -488,6 +560,72 @@ static int set_ep_max_packet_size(const struct f_uac2_opts *uac2_opts, /* Use macro to overcome line length limitation */ #define USBDHDR(p) (struct usb_descriptor_header *)(p) +static void setup_headers(struct f_uac2_opts *opts, + struct usb_descriptor_header **headers, + enum usb_device_speed speed) +{ + struct usb_ss_ep_comp_descriptor *epout_desc_comp = NULL; + struct usb_ss_ep_comp_descriptor *epin_desc_comp = NULL; + struct usb_endpoint_descriptor *epout_desc; + struct usb_endpoint_descriptor *epin_desc; + int i; + + switch (speed) { + case USB_SPEED_FULL: + epout_desc = &fs_epout_desc; + epin_desc = &fs_epin_desc; + break; + case USB_SPEED_HIGH: + epout_desc = &hs_epout_desc; + epin_desc = &hs_epin_desc; + break; + default: + epout_desc = &ss_epout_desc; + epin_desc = &ss_epin_desc; + epout_desc_comp = &ss_epout_desc_comp; + epin_desc_comp = &ss_epin_desc_comp; + } + + i = 0; + headers[i++] = USBDHDR(&iad_desc); + headers[i++] = USBDHDR(&std_ac_if_desc); + headers[i++] = USBDHDR(&ac_hdr_desc); + if (EPIN_EN(opts)) + headers[i++] = USBDHDR(&in_clk_src_desc); + if (EPOUT_EN(opts)) { + headers[i++] = USBDHDR(&out_clk_src_desc); + headers[i++] = USBDHDR(&usb_out_it_desc); + } + if (EPIN_EN(opts)) { + headers[i++] = USBDHDR(&io_in_it_desc); + headers[i++] = USBDHDR(&usb_in_ot_desc); + } + if (EPOUT_EN(opts)) { + headers[i++] = USBDHDR(&io_out_ot_desc); + headers[i++] = USBDHDR(&std_as_out_if0_desc); + headers[i++] = USBDHDR(&std_as_out_if1_desc); + headers[i++] = USBDHDR(&as_out_hdr_desc); + headers[i++] = USBDHDR(&as_out_fmt1_desc); + headers[i++] = USBDHDR(epout_desc); + if (epout_desc_comp) + headers[i++] = USBDHDR(epout_desc_comp); + + headers[i++] = USBDHDR(&as_iso_out_desc); + } + if (EPIN_EN(opts)) { + headers[i++] = USBDHDR(&std_as_in_if0_desc); + headers[i++] = USBDHDR(&std_as_in_if1_desc); + headers[i++] = USBDHDR(&as_in_hdr_desc); + headers[i++] = USBDHDR(&as_in_fmt1_desc); + headers[i++] = USBDHDR(epin_desc); + if (epin_desc_comp) + headers[i++] = USBDHDR(epin_desc_comp); + + headers[i++] = USBDHDR(&as_iso_in_desc); + } + headers[i] = NULL; +} + static void setup_descriptor(struct f_uac2_opts *opts) { /* patch descriptors */ @@ -537,71 +675,39 @@ static void setup_descriptor(struct f_uac2_opts *opts) iad_desc.bInterfaceCount++; } - i = 0; - fs_audio_desc[i++] = USBDHDR(&iad_desc); - fs_audio_desc[i++] = USBDHDR(&std_ac_if_desc); - fs_audio_desc[i++] = USBDHDR(&ac_hdr_desc); - if (EPIN_EN(opts)) - fs_audio_desc[i++] = USBDHDR(&in_clk_src_desc); - if (EPOUT_EN(opts)) { - fs_audio_desc[i++] = USBDHDR(&out_clk_src_desc); - fs_audio_desc[i++] = USBDHDR(&usb_out_it_desc); - } - if (EPIN_EN(opts)) { - fs_audio_desc[i++] = USBDHDR(&io_in_it_desc); - fs_audio_desc[i++] = USBDHDR(&usb_in_ot_desc); - } - if (EPOUT_EN(opts)) { - fs_audio_desc[i++] = USBDHDR(&io_out_ot_desc); - fs_audio_desc[i++] = USBDHDR(&std_as_out_if0_desc); - fs_audio_desc[i++] = USBDHDR(&std_as_out_if1_desc); - fs_audio_desc[i++] = USBDHDR(&as_out_hdr_desc); - fs_audio_desc[i++] = USBDHDR(&as_out_fmt1_desc); - fs_audio_desc[i++] = USBDHDR(&fs_epout_desc); - fs_audio_desc[i++] = USBDHDR(&as_iso_out_desc); - } - if (EPIN_EN(opts)) { - fs_audio_desc[i++] = USBDHDR(&std_as_in_if0_desc); - fs_audio_desc[i++] = USBDHDR(&std_as_in_if1_desc); - fs_audio_desc[i++] = USBDHDR(&as_in_hdr_desc); - fs_audio_desc[i++] = USBDHDR(&as_in_fmt1_desc); - fs_audio_desc[i++] = USBDHDR(&fs_epin_desc); - fs_audio_desc[i++] = USBDHDR(&as_iso_in_desc); - } - fs_audio_desc[i] = NULL; + setup_headers(opts, fs_audio_desc, USB_SPEED_FULL); + setup_headers(opts, hs_audio_desc, USB_SPEED_HIGH); + setup_headers(opts, ss_audio_desc, USB_SPEED_SUPER); +} - i = 0; - hs_audio_desc[i++] = USBDHDR(&iad_desc); - hs_audio_desc[i++] = USBDHDR(&std_ac_if_desc); - hs_audio_desc[i++] = USBDHDR(&ac_hdr_desc); - if (EPIN_EN(opts)) - hs_audio_desc[i++] = USBDHDR(&in_clk_src_desc); - if (EPOUT_EN(opts)) { - hs_audio_desc[i++] = USBDHDR(&out_clk_src_desc); - hs_audio_desc[i++] = USBDHDR(&usb_out_it_desc); - } - if (EPIN_EN(opts)) { - hs_audio_desc[i++] = USBDHDR(&io_in_it_desc); - hs_audio_desc[i++] = USBDHDR(&usb_in_ot_desc); - } - if (EPOUT_EN(opts)) { - hs_audio_desc[i++] = USBDHDR(&io_out_ot_desc); - hs_audio_desc[i++] = USBDHDR(&std_as_out_if0_desc); - hs_audio_desc[i++] = USBDHDR(&std_as_out_if1_desc); - hs_audio_desc[i++] = USBDHDR(&as_out_hdr_desc); - hs_audio_desc[i++] = USBDHDR(&as_out_fmt1_desc); - hs_audio_desc[i++] = USBDHDR(&hs_epout_desc); - hs_audio_desc[i++] = USBDHDR(&as_iso_out_desc); - } - if (EPIN_EN(opts)) { - hs_audio_desc[i++] = USBDHDR(&std_as_in_if0_desc); - hs_audio_desc[i++] = USBDHDR(&std_as_in_if1_desc); - hs_audio_desc[i++] = USBDHDR(&as_in_hdr_desc); - hs_audio_desc[i++] = USBDHDR(&as_in_fmt1_desc); - hs_audio_desc[i++] = USBDHDR(&hs_epin_desc); - hs_audio_desc[i++] = USBDHDR(&as_iso_in_desc); +static int afunc_validate_opts(struct g_audio *agdev, struct device *dev) +{ + struct f_uac2_opts *opts = g_audio_to_uac2_opts(agdev); + + if (!opts->p_chmask && !opts->c_chmask) { + dev_err(dev, "Error: no playback and capture channels\n"); + return -EINVAL; + } else if (opts->p_chmask & ~UAC2_CHANNEL_MASK) { + dev_err(dev, "Error: unsupported playback channels mask\n"); + return -EINVAL; + } else if (opts->c_chmask & ~UAC2_CHANNEL_MASK) { + dev_err(dev, "Error: unsupported capture channels mask\n"); + return -EINVAL; + } else if ((opts->p_ssize < 1) || (opts->p_ssize > 4)) { + dev_err(dev, "Error: incorrect playback sample size\n"); + return -EINVAL; + } else if ((opts->c_ssize < 1) || (opts->c_ssize > 4)) { + dev_err(dev, "Error: incorrect capture sample size\n"); + return -EINVAL; + } else if (!opts->p_srate) { + dev_err(dev, "Error: incorrect playback sampling rate\n"); + return -EINVAL; + } else if (!opts->c_srate) { + dev_err(dev, "Error: incorrect capture sampling rate\n"); + return -EINVAL; } - hs_audio_desc[i] = NULL; + + return 0; } static int @@ -612,11 +718,13 @@ afunc_bind(struct usb_configuration *cfg, struct usb_function *fn) struct usb_composite_dev *cdev = cfg->cdev; struct usb_gadget *gadget = cdev->gadget; struct device *dev = &gadget->dev; - struct f_uac2_opts *uac2_opts; + struct f_uac2_opts *uac2_opts = g_audio_to_uac2_opts(agdev); struct usb_string *us; int ret; - uac2_opts = container_of(fn->fi, struct f_uac2_opts, func_inst); + ret = afunc_validate_opts(agdev, dev); + if (ret) + return ret; us = usb_gstrings_attach(cdev, fn_strings, ARRAY_SIZE(strings_fn)); if (IS_ERR(us)) @@ -716,6 +824,20 @@ afunc_bind(struct usb_configuration *cfg, struct usb_function *fn) return ret; } + ret = set_ep_max_packet_size(uac2_opts, &ss_epin_desc, USB_SPEED_SUPER, + true); + if (ret < 0) { + dev_err(dev, "%s:%d Error!\n", __func__, __LINE__); + return ret; + } + + ret = set_ep_max_packet_size(uac2_opts, &ss_epout_desc, USB_SPEED_SUPER, + false); + if (ret < 0) { + dev_err(dev, "%s:%d Error!\n", __func__, __LINE__); + return ret; + } + if (EPOUT_EN(uac2_opts)) { agdev->out_ep = usb_ep_autoconfig(gadget, &fs_epout_desc); if (!agdev->out_ep) { @@ -739,13 +861,20 @@ afunc_bind(struct usb_configuration *cfg, struct usb_function *fn) le16_to_cpu(fs_epout_desc.wMaxPacketSize), le16_to_cpu(hs_epout_desc.wMaxPacketSize)); + agdev->in_ep_maxpsize = max_t(u16, agdev->in_ep_maxpsize, + le16_to_cpu(ss_epin_desc.wMaxPacketSize)); + agdev->out_ep_maxpsize = max_t(u16, agdev->out_ep_maxpsize, + le16_to_cpu(ss_epout_desc.wMaxPacketSize)); + hs_epout_desc.bEndpointAddress = fs_epout_desc.bEndpointAddress; hs_epin_desc.bEndpointAddress = fs_epin_desc.bEndpointAddress; + ss_epout_desc.bEndpointAddress = fs_epout_desc.bEndpointAddress; + ss_epin_desc.bEndpointAddress = fs_epin_desc.bEndpointAddress; setup_descriptor(uac2_opts); - ret = usb_assign_descriptors(fn, fs_audio_desc, hs_audio_desc, NULL, - NULL); + ret = usb_assign_descriptors(fn, fs_audio_desc, hs_audio_desc, ss_audio_desc, + ss_audio_desc); if (ret) return ret; diff --git a/drivers/usb/gadget/function/f_uvc.c b/drivers/usb/gadget/function/f_uvc.c index 44b4352a2676..f48a00e49794 100644 --- a/drivers/usb/gadget/function/f_uvc.c +++ b/drivers/usb/gadget/function/f_uvc.c @@ -633,7 +633,12 @@ uvc_function_bind(struct usb_configuration *c, struct usb_function *f) uvc_hs_streaming_ep.wMaxPacketSize = cpu_to_le16(max_packet_size | ((max_packet_mult - 1) << 11)); - uvc_hs_streaming_ep.bInterval = opts->streaming_interval; + + /* A high-bandwidth endpoint must specify a bInterval value of 1 */ + if (max_packet_mult > 1) + uvc_hs_streaming_ep.bInterval = 1; + else + uvc_hs_streaming_ep.bInterval = opts->streaming_interval; uvc_ss_streaming_ep.wMaxPacketSize = cpu_to_le16(max_packet_size); uvc_ss_streaming_ep.bInterval = opts->streaming_interval; @@ -817,6 +822,7 @@ static struct usb_function_instance *uvc_alloc_inst(void) pd->bmControls[0] = 1; pd->bmControls[1] = 0; pd->iProcessing = 0; + pd->bmVideoStandards = 0; od = &opts->uvc_output_terminal; od->bLength = UVC_DT_OUTPUT_TERMINAL_SIZE; diff --git a/drivers/usb/gadget/function/u_audio.c b/drivers/usb/gadget/function/u_audio.c index 265c4d805f81..5fbceee897a3 100644 --- a/drivers/usb/gadget/function/u_audio.c +++ b/drivers/usb/gadget/function/u_audio.c @@ -549,15 +549,15 @@ int g_audio_setup(struct g_audio *g_audio, const char *pcm_name, if (err < 0) goto snd_fail; - strlcpy(pcm->name, pcm_name, sizeof(pcm->name)); + strscpy(pcm->name, pcm_name, sizeof(pcm->name)); pcm->private_data = uac; uac->pcm = pcm; snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &uac_pcm_ops); snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &uac_pcm_ops); - strlcpy(card->driver, card_name, sizeof(card->driver)); - strlcpy(card->shortname, card_name, sizeof(card->shortname)); + strscpy(card->driver, card_name, sizeof(card->driver)); + strscpy(card->shortname, card_name, sizeof(card->shortname)); sprintf(card->longname, "%s %i", card_name, card->dev->id); snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_CONTINUOUS, diff --git a/drivers/usb/gadget/function/uvc_configfs.c b/drivers/usb/gadget/function/uvc_configfs.c index 00fb58e50a15..cd28dec837dd 100644 --- a/drivers/usb/gadget/function/uvc_configfs.c +++ b/drivers/usb/gadget/function/uvc_configfs.c @@ -231,7 +231,7 @@ static struct config_item *uvcg_control_header_make(struct config_group *group, h->desc.bLength = UVC_DT_HEADER_SIZE(1); h->desc.bDescriptorType = USB_DT_CS_INTERFACE; h->desc.bDescriptorSubType = UVC_VC_HEADER; - h->desc.bcdUVC = cpu_to_le16(0x0100); + h->desc.bcdUVC = cpu_to_le16(0x0110); h->desc.dwClockFrequency = cpu_to_le32(48000000); config_item_init_type_name(&h->item, name, &uvcg_control_header_type); diff --git a/drivers/usb/gadget/legacy/inode.c b/drivers/usb/gadget/legacy/inode.c index 71e7d10dd76b..cd8e2737947b 100644 --- a/drivers/usb/gadget/legacy/inode.c +++ b/drivers/usb/gadget/legacy/inode.c @@ -498,7 +498,8 @@ static void ep_aio_complete(struct usb_ep *ep, struct usb_request *req) iocb->private = NULL; /* aio_complete() reports bytes-transferred _and_ faults */ - iocb->ki_complete(iocb, req->actual ? req->actual : req->status, + iocb->ki_complete(iocb, + req->actual ? req->actual : (long)req->status, req->status); } else { /* ep_copy_to_user() won't report both; we hide some faults */ diff --git a/drivers/usb/gadget/legacy/mass_storage.c b/drivers/usb/gadget/legacy/mass_storage.c index 9ed22c5fb7fe..ac1741126619 100644 --- a/drivers/usb/gadget/legacy/mass_storage.c +++ b/drivers/usb/gadget/legacy/mass_storage.c @@ -175,8 +175,10 @@ static int msg_bind(struct usb_composite_dev *cdev) struct usb_descriptor_header *usb_desc; usb_desc = usb_otg_descriptor_alloc(cdev->gadget); - if (!usb_desc) + if (!usb_desc) { + status = -ENOMEM; goto fail_string_ids; + } usb_otg_descriptor_init(cdev->gadget, usb_desc); otg_desc[0] = usb_desc; otg_desc[1] = NULL; diff --git a/drivers/usb/gadget/legacy/multi.c b/drivers/usb/gadget/legacy/multi.c index ec9749845660..8db5c91ae47d 100644 --- a/drivers/usb/gadget/legacy/multi.c +++ b/drivers/usb/gadget/legacy/multi.c @@ -182,7 +182,7 @@ err_func_rndis: return ret; } -static __ref int rndis_config_register(struct usb_composite_dev *cdev) +static int rndis_config_register(struct usb_composite_dev *cdev) { static struct usb_configuration config = { .bConfigurationValue = MULTI_RNDIS_CONFIG_NUM, @@ -197,7 +197,7 @@ static __ref int rndis_config_register(struct usb_composite_dev *cdev) #else -static __ref int rndis_config_register(struct usb_composite_dev *cdev) +static int rndis_config_register(struct usb_composite_dev *cdev) { return 0; } @@ -265,7 +265,7 @@ err_func_ecm: return ret; } -static __ref int cdc_config_register(struct usb_composite_dev *cdev) +static int cdc_config_register(struct usb_composite_dev *cdev) { static struct usb_configuration config = { .bConfigurationValue = MULTI_CDC_CONFIG_NUM, @@ -280,7 +280,7 @@ static __ref int cdc_config_register(struct usb_composite_dev *cdev) #else -static __ref int cdc_config_register(struct usb_composite_dev *cdev) +static int cdc_config_register(struct usb_composite_dev *cdev) { return 0; } @@ -291,7 +291,7 @@ static __ref int cdc_config_register(struct usb_composite_dev *cdev) /****************************** Gadget Bind ******************************/ -static int __ref multi_bind(struct usb_composite_dev *cdev) +static int multi_bind(struct usb_composite_dev *cdev) { struct usb_gadget *gadget = cdev->gadget; #ifdef CONFIG_USB_G_MULTI_CDC @@ -399,8 +399,10 @@ static int __ref multi_bind(struct usb_composite_dev *cdev) struct usb_descriptor_header *usb_desc; usb_desc = usb_otg_descriptor_alloc(gadget); - if (!usb_desc) + if (!usb_desc) { + status = -ENOMEM; goto fail_string_ids; + } usb_otg_descriptor_init(gadget, usb_desc); otg_desc[0] = usb_desc; otg_desc[1] = NULL; diff --git a/drivers/usb/gadget/legacy/webcam.c b/drivers/usb/gadget/legacy/webcam.c index a9f8eb8e1c76..94e22867da1d 100644 --- a/drivers/usb/gadget/legacy/webcam.c +++ b/drivers/usb/gadget/legacy/webcam.c @@ -90,7 +90,7 @@ static const struct UVC_HEADER_DESCRIPTOR(1) uvc_control_header = { .bLength = UVC_DT_HEADER_SIZE(1), .bDescriptorType = USB_DT_CS_INTERFACE, .bDescriptorSubType = UVC_VC_HEADER, - .bcdUVC = cpu_to_le16(0x0100), + .bcdUVC = cpu_to_le16(0x0110), .wTotalLength = 0, /* dynamic */ .dwClockFrequency = cpu_to_le32(48000000), .bInCollection = 0, /* dynamic */ @@ -125,6 +125,7 @@ static const struct uvc_processing_unit_descriptor uvc_processing = { .bmControls[0] = 1, .bmControls[1] = 0, .iProcessing = 0, + .bmVideoStandards = 0, }; static const struct uvc_output_terminal_descriptor uvc_output_terminal = { diff --git a/drivers/usb/gadget/udc/aspeed-vhub/core.c b/drivers/usb/gadget/udc/aspeed-vhub/core.c index be7bb64e3594..d11d3d14313f 100644 --- a/drivers/usb/gadget/udc/aspeed-vhub/core.c +++ b/drivers/usb/gadget/udc/aspeed-vhub/core.c @@ -36,6 +36,7 @@ void ast_vhub_done(struct ast_vhub_ep *ep, struct ast_vhub_req *req, int status) { bool internal = req->internal; + struct ast_vhub *vhub = ep->vhub; EPVDBG(ep, "completing request @%p, status %d\n", req, status); @@ -46,7 +47,7 @@ void ast_vhub_done(struct ast_vhub_ep *ep, struct ast_vhub_req *req, if (req->req.dma) { if (!WARN_ON(!ep->dev)) - usb_gadget_unmap_request(&ep->dev->gadget, + usb_gadget_unmap_request_by_dev(&vhub->pdev->dev, &req->req, ep->epn.is_in); req->req.dma = 0; } diff --git a/drivers/usb/gadget/udc/aspeed-vhub/epn.c b/drivers/usb/gadget/udc/aspeed-vhub/epn.c index 02d8bfae58fb..cb164c615e6f 100644 --- a/drivers/usb/gadget/udc/aspeed-vhub/epn.c +++ b/drivers/usb/gadget/udc/aspeed-vhub/epn.c @@ -376,7 +376,7 @@ static int ast_vhub_epn_queue(struct usb_ep* u_ep, struct usb_request *u_req, if (ep->epn.desc_mode || ((((unsigned long)u_req->buf & 7) == 0) && (ep->epn.is_in || !(u_req->length & (u_ep->maxpacket - 1))))) { - rc = usb_gadget_map_request(&ep->dev->gadget, u_req, + rc = usb_gadget_map_request_by_dev(&vhub->pdev->dev, u_req, ep->epn.is_in); if (rc) { dev_warn(&vhub->pdev->dev, diff --git a/drivers/usb/gadget/udc/dummy_hcd.c b/drivers/usb/gadget/udc/dummy_hcd.c index 57067763b100..7db773c87379 100644 --- a/drivers/usb/gadget/udc/dummy_hcd.c +++ b/drivers/usb/gadget/udc/dummy_hcd.c @@ -903,6 +903,21 @@ static int dummy_pullup(struct usb_gadget *_gadget, int value) spin_lock_irqsave(&dum->lock, flags); dum->pullup = (value != 0); set_link_state(dum_hcd); + if (value == 0) { + /* + * Emulate synchronize_irq(): wait for callbacks to finish. + * This seems to be the best place to emulate the call to + * synchronize_irq() that's in usb_gadget_remove_driver(). + * Doing it in dummy_udc_stop() would be too late since it + * is called after the unbind callback and unbind shouldn't + * be invoked until all the other callbacks are finished. + */ + while (dum->callback_usage > 0) { + spin_unlock_irqrestore(&dum->lock, flags); + usleep_range(1000, 2000); + spin_lock_irqsave(&dum->lock, flags); + } + } spin_unlock_irqrestore(&dum->lock, flags); usb_hcd_poll_rh_status(dummy_hcd_to_hcd(dum_hcd)); @@ -1004,14 +1019,6 @@ static int dummy_udc_stop(struct usb_gadget *g) spin_lock_irq(&dum->lock); dum->ints_enabled = 0; stop_activity(dum); - - /* emulate synchronize_irq(): wait for callbacks to finish */ - while (dum->callback_usage > 0) { - spin_unlock_irq(&dum->lock); - usleep_range(1000, 2000); - spin_lock_irq(&dum->lock); - } - dum->driver = NULL; spin_unlock_irq(&dum->lock); @@ -1866,7 +1873,7 @@ restart: /* handle control requests */ if (ep == &dum->ep[0] && ep->setup_stage) { struct usb_ctrlrequest setup; - int value = 1; + int value; setup = *(struct usb_ctrlrequest *) urb->setup_packet; /* paranoia, in case of stale queued data */ diff --git a/drivers/usb/gadget/udc/fotg210-udc.c b/drivers/usb/gadget/udc/fotg210-udc.c index d6ca50f01985..fdca28e72a3b 100644 --- a/drivers/usb/gadget/udc/fotg210-udc.c +++ b/drivers/usb/gadget/udc/fotg210-udc.c @@ -338,15 +338,16 @@ static void fotg210_start_dma(struct fotg210_ep *ep, } else { buffer = req->req.buf + req->req.actual; length = ioread32(ep->fotg210->reg + - FOTG210_FIBCR(ep->epnum - 1)); - length &= FIBCR_BCFX; + FOTG210_FIBCR(ep->epnum - 1)) & FIBCR_BCFX; + if (length > req->req.length - req->req.actual) + length = req->req.length - req->req.actual; } } else { buffer = req->req.buf + req->req.actual; if (req->req.length - req->req.actual > ep->ep.maxpacket) length = ep->ep.maxpacket; else - length = req->req.length; + length = req->req.length - req->req.actual; } d = dma_map_single(dev, buffer, length, @@ -379,8 +380,7 @@ static void fotg210_ep0_queue(struct fotg210_ep *ep, } if (ep->dir_in) { /* if IN */ fotg210_start_dma(ep, req); - if ((req->req.length == req->req.actual) || - (req->req.actual < ep->ep.maxpacket)) + if (req->req.length == req->req.actual) fotg210_done(ep, req, 0); } else { /* OUT */ u32 value = ioread32(ep->fotg210->reg + FOTG210_DMISGR0); @@ -820,7 +820,7 @@ static void fotg210_ep0in(struct fotg210_udc *fotg210) if (req->req.length) fotg210_start_dma(ep, req); - if ((req->req.length - req->req.actual) < ep->ep.maxpacket) + if (req->req.actual == req->req.length) fotg210_done(ep, req, 0); } else { fotg210_set_cxdone(fotg210); @@ -849,12 +849,16 @@ static void fotg210_out_fifo_handler(struct fotg210_ep *ep) { struct fotg210_request *req = list_entry(ep->queue.next, struct fotg210_request, queue); + int disgr1 = ioread32(ep->fotg210->reg + FOTG210_DISGR1); fotg210_start_dma(ep, req); - /* finish out transfer */ + /* Complete the request when it's full or a short packet arrived. + * Like other drivers, short_not_ok isn't handled. + */ + if (req->req.length == req->req.actual || - req->req.actual < ep->ep.maxpacket) + (disgr1 & DISGR1_SPK_INT(ep->epnum - 1))) fotg210_done(ep, req, 0); } @@ -877,6 +881,8 @@ static irqreturn_t fotg210_irq(int irq, void *_fotg210) int_grp2 &= ~int_msk2; if (int_grp2 & DISGR2_USBRST_INT) { + usb_gadget_udc_reset(&fotg210->gadget, + fotg210->driver); value = ioread32(reg); value &= ~DISGR2_USBRST_INT; iowrite32(value, reg); @@ -1027,6 +1033,12 @@ static void fotg210_init(struct fotg210_udc *fotg210) value &= ~DMCR_GLINT_EN; iowrite32(value, fotg210->reg + FOTG210_DMCR); + /* enable only grp2 irqs we handle */ + iowrite32(~(DISGR2_DMA_ERROR | DISGR2_RX0BYTE_INT | DISGR2_TX0BYTE_INT + | DISGR2_ISO_SEQ_ABORT_INT | DISGR2_ISO_SEQ_ERR_INT + | DISGR2_RESM_INT | DISGR2_SUSP_INT | DISGR2_USBRST_INT), + fotg210->reg + FOTG210_DMISGR2); + /* disable all fifo interrupt */ iowrite32(~(u32)0, fotg210->reg + FOTG210_DMISGR1); diff --git a/drivers/usb/gadget/udc/net2272.c b/drivers/usb/gadget/udc/net2272.c index 23a735641c3d..89f479b78d80 100644 --- a/drivers/usb/gadget/udc/net2272.c +++ b/drivers/usb/gadget/udc/net2272.c @@ -539,7 +539,6 @@ net2272_read_fifo(struct net2272_ep *ep, struct net2272_request *req) int count; int tmp; int cleanup = 0; - int status = -1; dev_vdbg(ep->dev->dev, "read_fifo %s actual %d len %d\n", ep->ep.name, req->req.actual, req->req.length); @@ -591,6 +590,8 @@ net2272_read_fifo(struct net2272_ep *ep, struct net2272_request *req) } if (!list_empty(&ep->queue)) { + int status; + req = list_entry(ep->queue.next, struct net2272_request, queue); status = net2272_kick_dma(ep, req); diff --git a/drivers/usb/gadget/udc/pch_udc.c b/drivers/usb/gadget/udc/pch_udc.c index a3c1fc924268..9bb7a9d7a2fb 100644 --- a/drivers/usb/gadget/udc/pch_udc.c +++ b/drivers/usb/gadget/udc/pch_udc.c @@ -8,11 +8,12 @@ #include <linux/pci.h> #include <linux/delay.h> #include <linux/errno.h> +#include <linux/gpio/consumer.h> +#include <linux/gpio/machine.h> #include <linux/list.h> #include <linux/interrupt.h> #include <linux/usb/ch9.h> #include <linux/usb/gadget.h> -#include <linux/gpio/consumer.h> #include <linux/irq.h> #define PCH_VBUS_PERIOD 3000 /* VBUS polling period (msec) */ @@ -331,6 +332,7 @@ struct pch_vbus_gpio_data { * @dma_addr: DMA pool for received * @setup_data: Received setup data * @base_addr: for mapped device memory + * @bar: PCI BAR used for mapped device memory * @cfg_data: current cfg, intf, and alt in use * @vbus_gpio: GPIO informaton for detecting VBUS */ @@ -353,6 +355,7 @@ struct pch_udc_dev { dma_addr_t dma_addr; struct usb_ctrlrequest setup_data; void __iomem *base_addr; + unsigned short bar; struct pch_udc_cfg_data cfg_data; struct pch_vbus_gpio_data vbus_gpio; }; @@ -381,11 +384,8 @@ MODULE_PARM_DESC(speed_fs, "true for Full speed operation"); * @td_data_last: last dma desc. of chain * @queue: associated queue * @dma_going: DMA in progress for request - * @dma_mapped: DMA memory mapped for request * @dma_done: DMA completed for request * @chain_len: chain length - * @buf: Buffer memory for align adjustment - * @dma: DMA memory for align adjustment */ struct pch_udc_request { struct usb_request req; @@ -394,11 +394,8 @@ struct pch_udc_request { struct pch_udc_data_dma_desc *td_data_last; struct list_head queue; unsigned dma_going:1, - dma_mapped:1, dma_done:1; unsigned chain_len; - void *buf; - dma_addr_t dma; }; static inline u32 pch_udc_readl(struct pch_udc_dev *dev, unsigned long reg) @@ -563,12 +560,13 @@ static void pch_udc_clear_disconnect(struct pch_udc_dev *dev) pch_udc_bit_clr(dev, UDC_DEVCTL_ADDR, UDC_DEVCTL_RES); } +static void pch_udc_init(struct pch_udc_dev *dev); + /** * pch_udc_reconnect() - This API initializes usb device controller, * and clear the disconnect status. * @dev: Reference to pch_udc_regs structure */ -static void pch_udc_init(struct pch_udc_dev *dev); static void pch_udc_reconnect(struct pch_udc_dev *dev) { pch_udc_init(dev); @@ -596,18 +594,22 @@ static void pch_udc_reconnect(struct pch_udc_dev *dev) static inline void pch_udc_vbus_session(struct pch_udc_dev *dev, int is_active) { + unsigned long iflags; + + spin_lock_irqsave(&dev->lock, iflags); if (is_active) { pch_udc_reconnect(dev); dev->vbus_session = 1; } else { if (dev->driver && dev->driver->disconnect) { - spin_lock(&dev->lock); + spin_unlock_irqrestore(&dev->lock, iflags); dev->driver->disconnect(&dev->gadget); - spin_unlock(&dev->lock); + spin_lock_irqsave(&dev->lock, iflags); } pch_udc_set_disconnect(dev); dev->vbus_session = 0; } + spin_unlock_irqrestore(&dev->lock, iflags); } /** @@ -1166,20 +1168,25 @@ static int pch_udc_pcd_selfpowered(struct usb_gadget *gadget, int value) static int pch_udc_pcd_pullup(struct usb_gadget *gadget, int is_on) { struct pch_udc_dev *dev; + unsigned long iflags; if (!gadget) return -EINVAL; + dev = container_of(gadget, struct pch_udc_dev, gadget); + + spin_lock_irqsave(&dev->lock, iflags); if (is_on) { pch_udc_reconnect(dev); } else { if (dev->driver && dev->driver->disconnect) { - spin_lock(&dev->lock); + spin_unlock_irqrestore(&dev->lock, iflags); dev->driver->disconnect(&dev->gadget); - spin_unlock(&dev->lock); + spin_lock_irqsave(&dev->lock, iflags); } pch_udc_set_disconnect(dev); } + spin_unlock_irqrestore(&dev->lock, iflags); return 0; } @@ -1360,6 +1367,7 @@ static irqreturn_t pch_vbus_gpio_irq(int irq, void *data) */ static int pch_vbus_gpio_init(struct pch_udc_dev *dev) { + struct device *d = &dev->pdev->dev; int err; int irq_num = 0; struct gpio_desc *gpiod; @@ -1368,7 +1376,7 @@ static int pch_vbus_gpio_init(struct pch_udc_dev *dev) dev->vbus_gpio.intr = 0; /* Retrieve the GPIO line from the USB gadget device */ - gpiod = devm_gpiod_get(dev->gadget.dev.parent, NULL, GPIOD_IN); + gpiod = devm_gpiod_get_optional(d, NULL, GPIOD_IN); if (IS_ERR(gpiod)) return PTR_ERR(gpiod); gpiod_set_consumer_name(gpiod, "pch_vbus"); @@ -1428,33 +1436,7 @@ static void complete_req(struct pch_udc_ep *ep, struct pch_udc_request *req, status = req->req.status; dev = ep->dev; - if (req->dma_mapped) { - if (req->dma == DMA_ADDR_INVALID) { - if (ep->in) - dma_unmap_single(&dev->pdev->dev, req->req.dma, - req->req.length, - DMA_TO_DEVICE); - else - dma_unmap_single(&dev->pdev->dev, req->req.dma, - req->req.length, - DMA_FROM_DEVICE); - req->req.dma = DMA_ADDR_INVALID; - } else { - if (ep->in) - dma_unmap_single(&dev->pdev->dev, req->dma, - req->req.length, - DMA_TO_DEVICE); - else { - dma_unmap_single(&dev->pdev->dev, req->dma, - req->req.length, - DMA_FROM_DEVICE); - memcpy(req->req.buf, req->buf, req->req.length); - } - kfree(req->buf); - req->dma = DMA_ADDR_INVALID; - } - req->dma_mapped = 0; - } + usb_gadget_unmap_request(&dev->gadget, &req->req, ep->in); ep->halted = 1; spin_unlock(&dev->lock); if (!ep->in) @@ -1532,12 +1514,9 @@ static int pch_udc_create_dma_chain(struct pch_udc_ep *ep, if (req->chain_len > 1) pch_udc_free_dma_chain(ep->dev, req); - if (req->dma == DMA_ADDR_INVALID) - td->dataptr = req->req.dma; - else - td->dataptr = req->dma; - + td->dataptr = req->req.dma; td->status = PCH_UDC_BS_HST_BSY; + for (; ; bytes -= buf_len, ++len) { td->status = PCH_UDC_BS_HST_BSY | min(buf_len, bytes); if (bytes <= buf_len) @@ -1743,7 +1722,6 @@ static struct usb_request *pch_udc_alloc_request(struct usb_ep *usbep, if (!req) return NULL; req->req.dma = DMA_ADDR_INVALID; - req->dma = DMA_ADDR_INVALID; INIT_LIST_HEAD(&req->queue); if (!ep->dev->dma_addr) return &req->req; @@ -1756,7 +1734,7 @@ static struct usb_request *pch_udc_alloc_request(struct usb_ep *usbep, } /* prevent from using desc. - set HOST BUSY */ dma_desc->status |= PCH_UDC_BS_HST_BSY; - dma_desc->dataptr = cpu_to_le32(DMA_ADDR_INVALID); + dma_desc->dataptr = lower_32_bits(DMA_ADDR_INVALID); req->td_data = dma_desc; req->td_data_last = dma_desc; req->chain_len = 1; @@ -1826,39 +1804,9 @@ static int pch_udc_pcd_queue(struct usb_ep *usbep, struct usb_request *usbreq, return -ESHUTDOWN; spin_lock_irqsave(&dev->lock, iflags); /* map the buffer for dma */ - if (usbreq->length && - ((usbreq->dma == DMA_ADDR_INVALID) || !usbreq->dma)) { - if (!((unsigned long)(usbreq->buf) & 0x03)) { - if (ep->in) - usbreq->dma = dma_map_single(&dev->pdev->dev, - usbreq->buf, - usbreq->length, - DMA_TO_DEVICE); - else - usbreq->dma = dma_map_single(&dev->pdev->dev, - usbreq->buf, - usbreq->length, - DMA_FROM_DEVICE); - } else { - req->buf = kzalloc(usbreq->length, GFP_ATOMIC); - if (!req->buf) { - retval = -ENOMEM; - goto probe_end; - } - if (ep->in) { - memcpy(req->buf, usbreq->buf, usbreq->length); - req->dma = dma_map_single(&dev->pdev->dev, - req->buf, - usbreq->length, - DMA_TO_DEVICE); - } else - req->dma = dma_map_single(&dev->pdev->dev, - req->buf, - usbreq->length, - DMA_FROM_DEVICE); - } - req->dma_mapped = 1; - } + retval = usb_gadget_map_request(&dev->gadget, usbreq, ep->in); + if (retval) + goto probe_end; if (usbreq->length > 0) { retval = prepare_dma(ep, req, GFP_ATOMIC); if (retval) @@ -2298,6 +2246,21 @@ static void pch_udc_svc_data_out(struct pch_udc_dev *dev, int ep_num) pch_udc_set_dma(dev, DMA_DIR_RX); } +static int pch_udc_gadget_setup(struct pch_udc_dev *dev) + __must_hold(&dev->lock) +{ + int rc; + + /* In some cases we can get an interrupt before driver gets setup */ + if (!dev->driver) + return -ESHUTDOWN; + + spin_unlock(&dev->lock); + rc = dev->driver->setup(&dev->gadget, &dev->setup_data); + spin_lock(&dev->lock); + return rc; +} + /** * pch_udc_svc_control_in() - Handle Control IN endpoint interrupts * @dev: Reference to the device structure @@ -2369,15 +2332,12 @@ static void pch_udc_svc_control_out(struct pch_udc_dev *dev) dev->gadget.ep0 = &dev->ep[UDC_EP0IN_IDX].ep; else /* OUT */ dev->gadget.ep0 = &ep->ep; - spin_lock(&dev->lock); /* If Mass storage Reset */ if ((dev->setup_data.bRequestType == 0x21) && (dev->setup_data.bRequest == 0xFF)) dev->prot_stall = 0; /* call gadget with setup data received */ - setup_supported = dev->driver->setup(&dev->gadget, - &dev->setup_data); - spin_unlock(&dev->lock); + setup_supported = pch_udc_gadget_setup(dev); if (dev->setup_data.bRequestType & USB_DIR_IN) { ep->td_data->status = (ep->td_data->status & @@ -2625,9 +2585,7 @@ static void pch_udc_svc_intf_interrupt(struct pch_udc_dev *dev) dev->ep[i].halted = 0; } dev->stall = 0; - spin_unlock(&dev->lock); - dev->driver->setup(&dev->gadget, &dev->setup_data); - spin_lock(&dev->lock); + pch_udc_gadget_setup(dev); } /** @@ -2662,9 +2620,7 @@ static void pch_udc_svc_cfg_interrupt(struct pch_udc_dev *dev) dev->stall = 0; /* call gadget zero with setup data received */ - spin_unlock(&dev->lock); - dev->driver->setup(&dev->gadget, &dev->setup_data); - spin_lock(&dev->lock); + pch_udc_gadget_setup(dev); } /** @@ -2870,14 +2826,20 @@ static void pch_udc_pcd_reinit(struct pch_udc_dev *dev) * @dev: Reference to the driver structure * * Return codes: - * 0: Success + * 0: Success + * -ERRNO: All kind of errors when retrieving VBUS GPIO */ static int pch_udc_pcd_init(struct pch_udc_dev *dev) { + int ret; + pch_udc_init(dev); pch_udc_pcd_reinit(dev); - pch_vbus_gpio_init(dev); - return 0; + + ret = pch_vbus_gpio_init(dev); + if (ret) + pch_udc_exit(dev); + return ret; } /** @@ -2938,7 +2900,7 @@ static int init_dma_pools(struct pch_udc_dev *dev) dev->dma_addr = dma_map_single(&dev->pdev->dev, ep0out_buf, UDC_EP0OUT_BUFF_SIZE * 4, DMA_FROM_DEVICE); - return 0; + return dma_mapping_error(&dev->pdev->dev, dev->dma_addr); } static int pch_udc_start(struct usb_gadget *g, @@ -2976,6 +2938,38 @@ static int pch_udc_stop(struct usb_gadget *g) return 0; } +static void pch_vbus_gpio_remove_table(void *table) +{ + gpiod_remove_lookup_table(table); +} + +static int pch_vbus_gpio_add_table(struct device *d, void *table) +{ + gpiod_add_lookup_table(table); + return devm_add_action_or_reset(d, pch_vbus_gpio_remove_table, table); +} + +static struct gpiod_lookup_table pch_udc_minnow_vbus_gpio_table = { + .dev_id = "0000:02:02.4", + .table = { + GPIO_LOOKUP("sch_gpio.33158", 12, NULL, GPIO_ACTIVE_HIGH), + {} + }, +}; + +static int pch_udc_minnow_platform_init(struct device *d) +{ + return pch_vbus_gpio_add_table(d, &pch_udc_minnow_vbus_gpio_table); +} + +static int pch_udc_quark_platform_init(struct device *d) +{ + struct pch_udc_dev *dev = dev_get_drvdata(d); + + dev->bar = PCH_UDC_PCI_BAR_QUARK_X1000; + return 0; +} + static void pch_udc_shutdown(struct pci_dev *pdev) { struct pch_udc_dev *dev = pci_get_drvdata(pdev); @@ -3024,8 +3018,7 @@ static void pch_udc_remove(struct pci_dev *pdev) pch_udc_exit(dev); } -#ifdef CONFIG_PM_SLEEP -static int pch_udc_suspend(struct device *d) +static int __maybe_unused pch_udc_suspend(struct device *d) { struct pch_udc_dev *dev = dev_get_drvdata(d); @@ -3035,21 +3028,18 @@ static int pch_udc_suspend(struct device *d) return 0; } -static int pch_udc_resume(struct device *d) +static int __maybe_unused pch_udc_resume(struct device *d) { return 0; } static SIMPLE_DEV_PM_OPS(pch_udc_pm, pch_udc_suspend, pch_udc_resume); -#define PCH_UDC_PM_OPS (&pch_udc_pm) -#else -#define PCH_UDC_PM_OPS NULL -#endif /* CONFIG_PM_SLEEP */ -static int pch_udc_probe(struct pci_dev *pdev, - const struct pci_device_id *id) +typedef int (*platform_init_fn)(struct device *); + +static int pch_udc_probe(struct pci_dev *pdev, const struct pci_device_id *id) { - int bar; + platform_init_fn platform_init = (platform_init_fn)id->driver_data; int retval; struct pch_udc_dev *dev; @@ -3063,31 +3053,28 @@ static int pch_udc_probe(struct pci_dev *pdev, if (retval) return retval; + dev->bar = PCH_UDC_PCI_BAR; + dev->pdev = pdev; pci_set_drvdata(pdev, dev); - /* Determine BAR based on PCI ID */ - if (id->device == PCI_DEVICE_ID_INTEL_QUARK_X1000_UDC) - bar = PCH_UDC_PCI_BAR_QUARK_X1000; - else - bar = PCH_UDC_PCI_BAR; + /* Platform specific hook */ + if (platform_init) { + retval = platform_init(&pdev->dev); + if (retval) + return retval; + } /* PCI resource allocation */ - retval = pcim_iomap_regions(pdev, 1 << bar, pci_name(pdev)); + retval = pcim_iomap_regions(pdev, BIT(dev->bar), pci_name(pdev)); if (retval) return retval; - dev->base_addr = pcim_iomap_table(pdev)[bar]; - - /* - * FIXME: add a GPIO descriptor table to pdev.dev using - * gpiod_add_descriptor_table() from <linux/gpio/machine.h> based on - * the PCI subsystem ID. The system-dependent GPIO is necessary for - * VBUS operation. - */ + dev->base_addr = pcim_iomap_table(pdev)[dev->bar]; /* initialize the hardware */ - if (pch_udc_pcd_init(dev)) - return -ENODEV; + retval = pch_udc_pcd_init(dev); + if (retval) + return retval; pci_enable_msi(pdev); @@ -3104,7 +3091,6 @@ static int pch_udc_probe(struct pci_dev *pdev, /* device struct setup */ spin_lock_init(&dev->lock); - dev->pdev = pdev; dev->gadget.ops = &pch_udc_ops; retval = init_dma_pools(dev); @@ -3128,10 +3114,17 @@ finished: static const struct pci_device_id pch_udc_pcidev_id[] = { { - PCI_DEVICE(PCI_VENDOR_ID_INTEL, - PCI_DEVICE_ID_INTEL_QUARK_X1000_UDC), + PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_QUARK_X1000_UDC), + .class = PCI_CLASS_SERIAL_USB_DEVICE, + .class_mask = 0xffffffff, + .driver_data = (kernel_ulong_t)&pch_udc_quark_platform_init, + }, + { + PCI_DEVICE_SUB(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_EG20T_UDC, + PCI_VENDOR_ID_CIRCUITCO, PCI_SUBSYSTEM_ID_CIRCUITCO_MINNOWBOARD), .class = PCI_CLASS_SERIAL_USB_DEVICE, .class_mask = 0xffffffff, + .driver_data = (kernel_ulong_t)&pch_udc_minnow_platform_init, }, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_EG20T_UDC), @@ -3160,7 +3153,7 @@ static struct pci_driver pch_udc_driver = { .remove = pch_udc_remove, .shutdown = pch_udc_shutdown, .driver = { - .pm = PCH_UDC_PM_OPS, + .pm = &pch_udc_pm, }, }; diff --git a/drivers/usb/gadget/udc/r8a66597-udc.c b/drivers/usb/gadget/udc/r8a66597-udc.c index 896c1a016d55..65cae4883454 100644 --- a/drivers/usb/gadget/udc/r8a66597-udc.c +++ b/drivers/usb/gadget/udc/r8a66597-udc.c @@ -1849,6 +1849,8 @@ static int r8a66597_probe(struct platform_device *pdev) return PTR_ERR(reg); ires = platform_get_resource(pdev, IORESOURCE_IRQ, 0); + if (!ires) + return -EINVAL; irq = ires->start; irq_trigger = ires->flags & IRQF_TRIGGER_MASK; diff --git a/drivers/usb/gadget/udc/s3c2410_udc.c b/drivers/usb/gadget/udc/s3c2410_udc.c index 1d3ebb07ccd4..b154b62abefa 100644 --- a/drivers/usb/gadget/udc/s3c2410_udc.c +++ b/drivers/usb/gadget/udc/s3c2410_udc.c @@ -54,8 +54,6 @@ static struct clk *udc_clock; static struct clk *usb_bus_clock; static void __iomem *base_addr; static int irq_usbd; -static u64 rsrc_start; -static u64 rsrc_len; static struct dentry *s3c2410_udc_debugfs_root; static inline u32 udc_read(u32 reg) @@ -1752,7 +1750,8 @@ static int s3c2410_udc_probe(struct platform_device *pdev) udc_clock = clk_get(NULL, "usb-device"); if (IS_ERR(udc_clock)) { dev_err(dev, "failed to get udc clock source\n"); - return PTR_ERR(udc_clock); + retval = PTR_ERR(udc_clock); + goto err_usb_bus_clk; } clk_prepare_enable(udc_clock); @@ -1775,7 +1774,7 @@ static int s3c2410_udc_probe(struct platform_device *pdev) base_addr = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(base_addr)) { retval = PTR_ERR(base_addr); - goto err_mem; + goto err_udc_clk; } the_controller = udc; @@ -1793,7 +1792,7 @@ static int s3c2410_udc_probe(struct platform_device *pdev) if (retval != 0) { dev_err(dev, "cannot get irq %i, err %d\n", irq_usbd, retval); retval = -EBUSY; - goto err_map; + goto err_udc_clk; } dev_dbg(dev, "got irq %i\n", irq_usbd); @@ -1864,10 +1863,14 @@ err_gpio_claim: gpio_free(udc_info->vbus_pin); err_int: free_irq(irq_usbd, udc); -err_map: - iounmap(base_addr); -err_mem: - release_mem_region(rsrc_start, rsrc_len); +err_udc_clk: + clk_disable_unprepare(udc_clock); + clk_put(udc_clock); + udc_clock = NULL; +err_usb_bus_clk: + clk_disable_unprepare(usb_bus_clock); + clk_put(usb_bus_clock); + usb_bus_clock = NULL; return retval; } @@ -1899,9 +1902,6 @@ static int s3c2410_udc_remove(struct platform_device *pdev) free_irq(irq_usbd, udc); - iounmap(base_addr); - release_mem_region(rsrc_start, rsrc_len); - if (!IS_ERR(udc_clock) && udc_clock != NULL) { clk_disable_unprepare(udc_clock); clk_put(udc_clock); diff --git a/drivers/usb/gadget/udc/snps_udc_plat.c b/drivers/usb/gadget/udc/snps_udc_plat.c index 32f1d3e90c26..99805d60a7ab 100644 --- a/drivers/usb/gadget/udc/snps_udc_plat.c +++ b/drivers/usb/gadget/udc/snps_udc_plat.c @@ -114,8 +114,8 @@ static int udc_plat_probe(struct platform_device *pdev) res = platform_get_resource(pdev, IORESOURCE_MEM, 0); udc->virt_addr = devm_ioremap_resource(dev, res); - if (IS_ERR(udc->regs)) - return PTR_ERR(udc->regs); + if (IS_ERR(udc->virt_addr)) + return PTR_ERR(udc->virt_addr); /* udc csr registers base */ udc->csr = udc->virt_addr + UDC_CSR_ADDR; diff --git a/drivers/usb/gadget/udc/tegra-xudc.c b/drivers/usb/gadget/udc/tegra-xudc.c index 580bef8eb4cb..2319c9737c2b 100644 --- a/drivers/usb/gadget/udc/tegra-xudc.c +++ b/drivers/usb/gadget/udc/tegra-xudc.c @@ -3883,7 +3883,7 @@ static int tegra_xudc_remove(struct platform_device *pdev) pm_runtime_get_sync(xudc->dev); - cancel_delayed_work(&xudc->plc_reset_work); + cancel_delayed_work_sync(&xudc->plc_reset_work); cancel_work_sync(&xudc->usb_role_sw_work); usb_del_gadget_udc(&xudc->gadget); |