From dc50eab76b709d68175a358d6e23a5a3890764d3 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sat, 18 May 2024 19:39:57 +0200 Subject: Merging upstream version 6.7.7. Signed-off-by: Daniel Baumann --- drivers/usb/gadget/function/f_fs.c | 6 +++--- drivers/usb/gadget/function/f_mass_storage.c | 20 ++++++++++++++++++-- drivers/usb/gadget/function/f_midi.c | 4 ++-- drivers/usb/gadget/function/f_ncm.c | 10 +++++++++- drivers/usb/gadget/function/f_tcm.c | 3 +++ drivers/usb/gadget/function/f_uac2.c | 16 ++++++++++++++-- drivers/usb/gadget/function/f_uvc.c | 14 ++++++++++++-- drivers/usb/gadget/function/u_ether.c | 4 +++- drivers/usb/gadget/function/u_uac2.h | 8 ++++++++ 9 files changed, 72 insertions(+), 13 deletions(-) (limited to 'drivers/usb/gadget/function') diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c index 6e9ef35a43..efe3e3b857 100644 --- a/drivers/usb/gadget/function/f_fs.c +++ b/drivers/usb/gadget/function/f_fs.c @@ -202,7 +202,7 @@ struct ffs_epfile { struct ffs_buffer { size_t length; char *data; - char storage[]; + char storage[] __counted_by(length); }; /* ffs_io_data structure ***************************************************/ @@ -1383,8 +1383,8 @@ ffs_sb_make_inode(struct super_block *sb, void *data, inode->i_mode = perms->mode; inode->i_uid = perms->uid; inode->i_gid = perms->gid; - inode->i_atime = ts; - inode->i_mtime = ts; + inode_set_atime_to_ts(inode, ts); + inode_set_mtime_to_ts(inode, ts); inode->i_private = data; if (fops) inode->i_fop = fops; diff --git a/drivers/usb/gadget/function/f_mass_storage.c b/drivers/usb/gadget/function/f_mass_storage.c index 722a3ab2b3..c265a1f62f 100644 --- a/drivers/usb/gadget/function/f_mass_storage.c +++ b/drivers/usb/gadget/function/f_mass_storage.c @@ -545,21 +545,37 @@ static int start_transfer(struct fsg_dev *fsg, struct usb_ep *ep, static bool start_in_transfer(struct fsg_common *common, struct fsg_buffhd *bh) { + int rc; + if (!fsg_is_set(common)) return false; bh->state = BUF_STATE_SENDING; - if (start_transfer(common->fsg, common->fsg->bulk_in, bh->inreq)) + rc = start_transfer(common->fsg, common->fsg->bulk_in, bh->inreq); + if (rc) { bh->state = BUF_STATE_EMPTY; + if (rc == -ESHUTDOWN) { + common->running = 0; + return false; + } + } return true; } static bool start_out_transfer(struct fsg_common *common, struct fsg_buffhd *bh) { + int rc; + if (!fsg_is_set(common)) return false; bh->state = BUF_STATE_RECEIVING; - if (start_transfer(common->fsg, common->fsg->bulk_out, bh->outreq)) + rc = start_transfer(common->fsg, common->fsg->bulk_out, bh->outreq); + if (rc) { bh->state = BUF_STATE_FULL; + if (rc == -ESHUTDOWN) { + common->running = 0; + return false; + } + } return true; } diff --git a/drivers/usb/gadget/function/f_midi.c b/drivers/usb/gadget/function/f_midi.c index 2d02f25f95..5335845d69 100644 --- a/drivers/usb/gadget/function/f_midi.c +++ b/drivers/usb/gadget/function/f_midi.c @@ -99,7 +99,7 @@ struct f_midi { unsigned int in_last_port; unsigned char free_ref; - struct gmidi_in_port in_ports_array[/* in_ports */]; + struct gmidi_in_port in_ports_array[] __counted_by(in_ports); }; static inline struct f_midi *func_to_midi(struct usb_function *f) @@ -1349,6 +1349,7 @@ static struct usb_function *f_midi_alloc(struct usb_function_instance *fi) status = -ENOMEM; goto setup_fail; } + midi->in_ports = opts->in_ports; for (i = 0; i < opts->in_ports; i++) midi->in_ports_array[i].cable = i; @@ -1359,7 +1360,6 @@ static struct usb_function *f_midi_alloc(struct usb_function_instance *fi) status = -ENOMEM; goto midi_free; } - midi->in_ports = opts->in_ports; midi->out_ports = opts->out_ports; midi->index = opts->index; midi->buflen = opts->buflen; diff --git a/drivers/usb/gadget/function/f_ncm.c b/drivers/usb/gadget/function/f_ncm.c index cc0ed29a4a..5712883a75 100644 --- a/drivers/usb/gadget/function/f_ncm.c +++ b/drivers/usb/gadget/function/f_ncm.c @@ -1325,7 +1325,15 @@ parse_ntb: "Parsed NTB with %d frames\n", dgram_counter); to_process -= block_len; - if (to_process != 0) { + + /* + * Windows NCM driver avoids USB ZLPs by adding a 1-byte + * zero pad as needed. + */ + if (to_process == 1 && + (*(unsigned char *)(ntb_ptr + block_len) == 0x00)) { + to_process--; + } else if (to_process > 0) { ntb_ptr = (unsigned char *)(ntb_ptr + block_len); goto parse_ntb; } diff --git a/drivers/usb/gadget/function/f_tcm.c b/drivers/usb/gadget/function/f_tcm.c index 79ed2e6e57..ff33f31bcd 100644 --- a/drivers/usb/gadget/function/f_tcm.c +++ b/drivers/usb/gadget/function/f_tcm.c @@ -1687,6 +1687,9 @@ static const struct target_core_fabric_ops usbg_ops = { .tfc_wwn_attrs = usbg_wwn_attrs, .tfc_tpg_base_attrs = usbg_base_attrs, + + .default_submit_type = TARGET_DIRECT_SUBMIT, + .direct_submit_supp = 1, }; /* Start gadget.c code */ diff --git a/drivers/usb/gadget/function/f_uac2.c b/drivers/usb/gadget/function/f_uac2.c index 0219cd7949..f9a0f07a74 100644 --- a/drivers/usb/gadget/function/f_uac2.c +++ b/drivers/usb/gadget/function/f_uac2.c @@ -212,7 +212,7 @@ static struct uac2_input_terminal_descriptor io_in_it_desc = { .bDescriptorSubtype = UAC_INPUT_TERMINAL, /* .bTerminalID = DYNAMIC */ - .wTerminalType = cpu_to_le16(UAC_INPUT_TERMINAL_MICROPHONE), + /* .wTerminalType = DYNAMIC */ .bAssocTerminal = 0, /* .bCSourceID = DYNAMIC */ .iChannelNames = 0, @@ -240,7 +240,7 @@ static struct uac2_output_terminal_descriptor io_out_ot_desc = { .bDescriptorSubtype = UAC_OUTPUT_TERMINAL, /* .bTerminalID = DYNAMIC */ - .wTerminalType = cpu_to_le16(UAC_OUTPUT_TERMINAL_SPEAKER), + /* .wTerminalType = DYNAMIC */ .bAssocTerminal = 0, /* .bSourceID = DYNAMIC */ /* .bCSourceID = DYNAMIC */ @@ -977,6 +977,9 @@ static void setup_descriptor(struct f_uac2_opts *opts) iad_desc.bInterfaceCount++; } + io_in_it_desc.wTerminalType = cpu_to_le16(opts->c_terminal_type); + io_out_ot_desc.wTerminalType = cpu_to_le16(opts->p_terminal_type); + 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); @@ -2095,6 +2098,9 @@ UAC2_ATTRIBUTE(s16, c_volume_res); UAC2_ATTRIBUTE(u32, fb_max); UAC2_ATTRIBUTE_STRING(function_name); +UAC2_ATTRIBUTE(s16, p_terminal_type); +UAC2_ATTRIBUTE(s16, c_terminal_type); + static struct configfs_attribute *f_uac2_attrs[] = { &f_uac2_opts_attr_p_chmask, &f_uac2_opts_attr_p_srate, @@ -2122,6 +2128,9 @@ static struct configfs_attribute *f_uac2_attrs[] = { &f_uac2_opts_attr_function_name, + &f_uac2_opts_attr_p_terminal_type, + &f_uac2_opts_attr_c_terminal_type, + NULL, }; @@ -2180,6 +2189,9 @@ static struct usb_function_instance *afunc_alloc_inst(void) snprintf(opts->function_name, sizeof(opts->function_name), "Source/Sink"); + opts->p_terminal_type = UAC2_DEF_P_TERM_TYPE; + opts->c_terminal_type = UAC2_DEF_C_TERM_TYPE; + return &opts->func_inst; } diff --git a/drivers/usb/gadget/function/f_uvc.c b/drivers/usb/gadget/function/f_uvc.c index 2e6bafb2a5..c6965e3894 100644 --- a/drivers/usb/gadget/function/f_uvc.c +++ b/drivers/usb/gadget/function/f_uvc.c @@ -516,6 +516,7 @@ uvc_copy_descriptors(struct uvc_device *uvc, enum usb_device_speed speed) void *mem; switch (speed) { + case USB_SPEED_SUPER_PLUS: case USB_SPEED_SUPER: uvc_control_desc = uvc->desc.ss_control; uvc_streaming_cls = uvc->desc.ss_streaming; @@ -564,7 +565,8 @@ uvc_copy_descriptors(struct uvc_device *uvc, enum usb_device_speed speed) bytes += uvc_interrupt_ep.bLength + uvc_interrupt_cs_ep.bLength; n_desc += 2; - if (speed == USB_SPEED_SUPER) { + if (speed == USB_SPEED_SUPER || + speed == USB_SPEED_SUPER_PLUS) { bytes += uvc_ss_interrupt_comp.bLength; n_desc += 1; } @@ -619,7 +621,8 @@ uvc_copy_descriptors(struct uvc_device *uvc, enum usb_device_speed speed) if (uvc->enable_interrupt_ep) { UVC_COPY_DESCRIPTOR(mem, dst, &uvc_interrupt_ep); - if (speed == USB_SPEED_SUPER) + if (speed == USB_SPEED_SUPER || + speed == USB_SPEED_SUPER_PLUS) UVC_COPY_DESCRIPTOR(mem, dst, &uvc_ss_interrupt_comp); UVC_COPY_DESCRIPTOR(mem, dst, &uvc_interrupt_cs_ep); @@ -811,6 +814,13 @@ uvc_function_bind(struct usb_configuration *c, struct usb_function *f) goto error; } + f->ssp_descriptors = uvc_copy_descriptors(uvc, USB_SPEED_SUPER_PLUS); + if (IS_ERR(f->ssp_descriptors)) { + ret = PTR_ERR(f->ssp_descriptors); + f->ssp_descriptors = NULL; + goto error; + } + /* Preallocate control endpoint request. */ uvc->control_req = usb_ep_alloc_request(cdev->gadget->ep0, GFP_KERNEL); uvc->control_buf = kmalloc(UVC_MAX_REQUEST_SIZE, GFP_KERNEL); diff --git a/drivers/usb/gadget/function/u_ether.c b/drivers/usb/gadget/function/u_ether.c index 4bb0553da6..3c5a6f6ac3 100644 --- a/drivers/usb/gadget/function/u_ether.c +++ b/drivers/usb/gadget/function/u_ether.c @@ -1163,6 +1163,8 @@ struct net_device *gether_connect(struct gether *link) if (netif_running(dev->net)) eth_start(dev, GFP_ATOMIC); + netif_device_attach(dev->net); + /* on error, disable any endpoints */ } else { (void) usb_ep_disable(link->out_ep); @@ -1200,7 +1202,7 @@ void gether_disconnect(struct gether *link) DBG(dev, "%s\n", __func__); - netif_stop_queue(dev->net); + netif_device_detach(dev->net); netif_carrier_off(dev->net); /* disable endpoints, forcing (synchronous) completion diff --git a/drivers/usb/gadget/function/u_uac2.h b/drivers/usb/gadget/function/u_uac2.h index 0510c9bad5..5e81bdd6c5 100644 --- a/drivers/usb/gadget/function/u_uac2.h +++ b/drivers/usb/gadget/function/u_uac2.h @@ -35,6 +35,11 @@ #define UAC2_DEF_REQ_NUM 2 #define UAC2_DEF_INT_REQ_NUM 10 +#define UAC2_DEF_P_TERM_TYPE 0x301 + /* UAC_OUTPUT_TERMINAL_SPEAKER */ +#define UAC2_DEF_C_TERM_TYPE 0x201 + /* UAC_INPUT_TERMINAL_MICROPHONE*/ + struct f_uac2_opts { struct usb_function_instance func_inst; int p_chmask; @@ -65,6 +70,9 @@ struct f_uac2_opts { char function_name[32]; + s16 p_terminal_type; + s16 c_terminal_type; + struct mutex lock; int refcnt; }; -- cgit v1.2.3