diff options
author | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2020-08-31 08:11:45 +0300 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2020-08-31 08:11:45 +0300 |
commit | 5fedf0d295d3ef69fd85fdee4cb68fd3756b54c2 (patch) | |
tree | 777c39ad4586149de154be3c4c102f751336a37b /drivers/usb | |
parent | 3ed8e1c2ac9914a2fcb08ec13476b85319536cea (diff) | |
parent | f75aef392f869018f78cfedf3c320a6b3fcfda6b (diff) | |
download | linux-5fedf0d295d3ef69fd85fdee4cb68fd3756b54c2.tar.xz |
Merge 5.9-rc3 into usb-next
We want the USB fixes in here as well.
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/usb')
47 files changed, 417 insertions, 203 deletions
diff --git a/drivers/usb/c67x00/c67x00-sched.c b/drivers/usb/c67x00/c67x00-sched.c index 6275cb77a15b..e65f1a0ae80b 100644 --- a/drivers/usb/c67x00/c67x00-sched.c +++ b/drivers/usb/c67x00/c67x00-sched.c @@ -710,7 +710,8 @@ static int c67x00_add_ctrl_urb(struct c67x00_hcd *c67x00, struct urb *urb) if (ret) return ret; break; - } /* else fallthrough */ + } + fallthrough; case STATUS_STAGE: pid = !usb_pipeout(urb->pipe) ? USB_PID_OUT : USB_PID_IN; ret = c67x00_create_td(c67x00, urb, NULL, 0, pid, 1, diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index 991786876dbb..7f6f3ab5b8a6 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -378,21 +378,19 @@ static void acm_ctrl_irq(struct urb *urb) if (current_size < expected_size) { /* notification is transmitted fragmented, reassemble */ if (acm->nb_size < expected_size) { - if (acm->nb_size) { - kfree(acm->notification_buffer); - acm->nb_size = 0; - } + u8 *new_buffer; alloc_size = roundup_pow_of_two(expected_size); - /* - * kmalloc ensures a valid notification_buffer after a - * use of kfree in case the previous allocation was too - * small. Final freeing is done on disconnect. - */ - acm->notification_buffer = - kmalloc(alloc_size, GFP_ATOMIC); - if (!acm->notification_buffer) + /* Final freeing is done on disconnect. */ + new_buffer = krealloc(acm->notification_buffer, + alloc_size, GFP_ATOMIC); + if (!new_buffer) { + acm->nb_index = 0; goto exit; + } + + acm->notification_buffer = new_buffer; acm->nb_size = alloc_size; + dr = (struct usb_cdc_notification *)acm->notification_buffer; } copy_size = min(current_size, diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c index f81606c6a35b..7e73e989645b 100644 --- a/drivers/usb/core/driver.c +++ b/drivers/usb/core/driver.c @@ -905,6 +905,35 @@ static int usb_uevent(struct device *dev, struct kobj_uevent_env *env) return 0; } +static bool is_dev_usb_generic_driver(struct device *dev) +{ + struct usb_device_driver *udd = dev->driver ? + to_usb_device_driver(dev->driver) : NULL; + + return udd == &usb_generic_driver; +} + +static int __usb_bus_reprobe_drivers(struct device *dev, void *data) +{ + struct usb_device_driver *new_udriver = data; + struct usb_device *udev; + int ret; + + if (!is_dev_usb_generic_driver(dev)) + return 0; + + udev = to_usb_device(dev); + if (usb_device_match_id(udev, new_udriver->id_table) == NULL && + (!new_udriver->match || new_udriver->match(udev) != 0)) + return 0; + + ret = device_reprobe(dev); + if (ret && ret != -EPROBE_DEFER) + dev_err(dev, "Failed to reprobe device (error %d)\n", ret); + + return 0; +} + /** * usb_register_device_driver - register a USB device (not interface) driver * @new_udriver: USB operations for the device driver @@ -934,13 +963,20 @@ int usb_register_device_driver(struct usb_device_driver *new_udriver, retval = driver_register(&new_udriver->drvwrap.driver); - if (!retval) + if (!retval) { pr_info("%s: registered new device driver %s\n", usbcore_name, new_udriver->name); - else + /* + * Check whether any device could be better served with + * this new driver + */ + bus_for_each_dev(&usb_bus_type, NULL, new_udriver, + __usb_bus_reprobe_drivers); + } else { printk(KERN_ERR "%s: error %d registering device " " driver %s\n", usbcore_name, retval, new_udriver->name); + } return retval; } diff --git a/drivers/usb/core/generic.c b/drivers/usb/core/generic.c index d27ac8e78b2e..22c887f5c497 100644 --- a/drivers/usb/core/generic.c +++ b/drivers/usb/core/generic.c @@ -205,8 +205,9 @@ static int __check_for_non_generic_match(struct device_driver *drv, void *data) udrv = to_usb_device_driver(drv); if (udrv == &usb_generic_driver) return 0; - - return usb_device_match_id(udev, udrv->id_table) != NULL; + if (usb_device_match_id(udev, udrv->id_table) != NULL) + return 1; + return (udrv->match && udrv->match(udev)); } static bool usb_generic_driver_match(struct usb_device *udev) diff --git a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c index 4dc443aaef5c..ec0d6c50610c 100644 --- a/drivers/usb/core/hcd-pci.c +++ b/drivers/usb/core/hcd-pci.c @@ -315,11 +315,14 @@ EXPORT_SYMBOL_GPL(usb_hcd_pci_probe); void usb_hcd_pci_remove(struct pci_dev *dev) { struct usb_hcd *hcd; + int hcd_driver_flags; hcd = pci_get_drvdata(dev); if (!hcd) return; + hcd_driver_flags = hcd->driver->flags; + if (pci_dev_run_wake(dev)) pm_runtime_get_noresume(&dev->dev); @@ -347,7 +350,7 @@ void usb_hcd_pci_remove(struct pci_dev *dev) up_read(&companions_rwsem); } usb_put_hcd(hcd); - if ((hcd->driver->flags & HCD_MASK) < HCD_USB3) + if ((hcd_driver_flags & HCD_MASK) < HCD_USB3) pci_free_irq_vectors(dev); pci_disable_device(dev); } diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 052d5accfe9b..5b768b80d1ee 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -727,7 +727,7 @@ static void hub_irq(struct urb *urb) if ((++hub->nerrors < 10) || hub->error) goto resubmit; hub->error = status; - /* FALL THROUGH */ + fallthrough; /* let hub_wq handle things */ case 0: /* we got data: port status changed */ diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c index 7c1198f80c23..f232914de5fd 100644 --- a/drivers/usb/core/quirks.c +++ b/drivers/usb/core/quirks.c @@ -370,6 +370,10 @@ static const struct usb_device_id usb_quirk_list[] = { { USB_DEVICE(0x0926, 0x0202), .driver_info = USB_QUIRK_ENDPOINT_IGNORE }, + /* Sound Devices MixPre-D */ + { USB_DEVICE(0x0926, 0x0208), .driver_info = + USB_QUIRK_ENDPOINT_IGNORE }, + /* Keytouch QWERTY Panel keyboard */ { USB_DEVICE(0x0926, 0x3333), .driver_info = USB_QUIRK_CONFIG_INTF_STRINGS }, @@ -465,6 +469,8 @@ static const struct usb_device_id usb_quirk_list[] = { { USB_DEVICE(0x2386, 0x3119), .driver_info = USB_QUIRK_NO_LPM }, + { USB_DEVICE(0x2386, 0x350e), .driver_info = USB_QUIRK_NO_LPM }, + /* DJI CineSSD */ { USB_DEVICE(0x2ca3, 0x0031), .driver_info = USB_QUIRK_NO_LPM }, @@ -509,6 +515,7 @@ static const struct usb_device_id usb_amd_resume_quirk_list[] = { */ static const struct usb_device_id usb_endpoint_ignore[] = { { USB_DEVICE_INTERFACE_NUMBER(0x0926, 0x0202, 1), .driver_info = 0x85 }, + { USB_DEVICE_INTERFACE_NUMBER(0x0926, 0x0208, 1), .driver_info = 0x85 }, { } }; diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index 422aea24afcd..2eb34c8b4065 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -646,9 +646,8 @@ static int dwc3_phy_setup(struct dwc3 *dwc) if (!(reg & DWC3_GUSB2PHYCFG_ULPI_UTMI)) break; } - /* FALLTHROUGH */ + fallthrough; case DWC3_GHWPARAMS3_HSPHY_IFC_ULPI: - /* FALLTHROUGH */ default: break; } @@ -1411,7 +1410,7 @@ static void dwc3_check_params(struct dwc3 *dwc) default: dev_err(dev, "invalid maximum_speed parameter %d\n", dwc->maximum_speed); - /* fall through */ + fallthrough; case USB_SPEED_UNKNOWN: /* default to superspeed */ dwc->maximum_speed = USB_SPEED_SUPER; diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index e44bfc3b5096..c2a0f64f8d1e 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -1054,27 +1054,25 @@ static void __dwc3_prepare_one_trb(struct dwc3_ep *dep, struct dwc3_trb *trb, * dwc3_prepare_one_trb - setup one TRB from one request * @dep: endpoint for which this request is prepared * @req: dwc3_request pointer + * @trb_length: buffer size of the TRB * @chain: should this TRB be chained to the next? * @node: only for isochronous endpoints. First TRB needs different type. */ static void dwc3_prepare_one_trb(struct dwc3_ep *dep, - struct dwc3_request *req, unsigned chain, unsigned node) + struct dwc3_request *req, unsigned int trb_length, + unsigned chain, unsigned node) { struct dwc3_trb *trb; - unsigned int length; dma_addr_t dma; unsigned stream_id = req->request.stream_id; unsigned short_not_ok = req->request.short_not_ok; unsigned no_interrupt = req->request.no_interrupt; unsigned is_last = req->request.is_last; - if (req->request.num_sgs > 0) { - length = sg_dma_len(req->start_sg); + if (req->request.num_sgs > 0) dma = sg_dma_address(req->start_sg); - } else { - length = req->request.length; + else dma = req->request.dma; - } trb = &dep->trb_pool[dep->trb_enqueue]; @@ -1086,7 +1084,7 @@ static void dwc3_prepare_one_trb(struct dwc3_ep *dep, req->num_trbs++; - __dwc3_prepare_one_trb(dep, trb, dma, length, chain, node, + __dwc3_prepare_one_trb(dep, trb, dma, trb_length, chain, node, stream_id, short_not_ok, no_interrupt, is_last); } @@ -1096,16 +1094,27 @@ static void dwc3_prepare_one_trb_sg(struct dwc3_ep *dep, struct scatterlist *sg = req->start_sg; struct scatterlist *s; int i; - + unsigned int length = req->request.length; unsigned int remaining = req->request.num_mapped_sgs - req->num_queued_sgs; + /* + * If we resume preparing the request, then get the remaining length of + * the request and resume where we left off. + */ + for_each_sg(req->request.sg, s, req->num_queued_sgs, i) + length -= sg_dma_len(s); + for_each_sg(sg, s, remaining, i) { - unsigned int length = req->request.length; unsigned int maxp = usb_endpoint_maxp(dep->endpoint.desc); unsigned int rem = length % maxp; + unsigned int trb_length; unsigned chain = true; + trb_length = min_t(unsigned int, length, sg_dma_len(s)); + + length -= trb_length; + /* * IOMMU driver is coalescing the list of sgs which shares a * page boundary into one and giving it to USB driver. With @@ -1113,7 +1122,7 @@ static void dwc3_prepare_one_trb_sg(struct dwc3_ep *dep, * sgs passed. So mark the chain bit to false if it isthe last * mapped sg. */ - if (i == remaining - 1) + if ((i == remaining - 1) || !length) chain = false; if (rem && usb_endpoint_dir_out(dep->endpoint.desc) && !chain) { @@ -1123,7 +1132,7 @@ static void dwc3_prepare_one_trb_sg(struct dwc3_ep *dep, req->needs_extra_trb = true; /* prepare normal TRB */ - dwc3_prepare_one_trb(dep, req, true, i); + dwc3_prepare_one_trb(dep, req, trb_length, true, i); /* Now prepare one extra TRB to align transfer size */ trb = &dep->trb_pool[dep->trb_enqueue]; @@ -1134,8 +1143,39 @@ static void dwc3_prepare_one_trb_sg(struct dwc3_ep *dep, req->request.short_not_ok, req->request.no_interrupt, req->request.is_last); + } else if (req->request.zero && req->request.length && + !usb_endpoint_xfer_isoc(dep->endpoint.desc) && + !rem && !chain) { + struct dwc3 *dwc = dep->dwc; + struct dwc3_trb *trb; + + req->needs_extra_trb = true; + + /* Prepare normal TRB */ + dwc3_prepare_one_trb(dep, req, trb_length, true, i); + + /* Prepare one extra TRB to handle ZLP */ + trb = &dep->trb_pool[dep->trb_enqueue]; + req->num_trbs++; + __dwc3_prepare_one_trb(dep, trb, dwc->bounce_addr, 0, + !req->direction, 1, + req->request.stream_id, + req->request.short_not_ok, + req->request.no_interrupt, + req->request.is_last); + + /* Prepare one more TRB to handle MPS alignment */ + if (!req->direction) { + trb = &dep->trb_pool[dep->trb_enqueue]; + req->num_trbs++; + __dwc3_prepare_one_trb(dep, trb, dwc->bounce_addr, maxp, + false, 1, req->request.stream_id, + req->request.short_not_ok, + req->request.no_interrupt, + req->request.is_last); + } } else { - dwc3_prepare_one_trb(dep, req, chain, i); + dwc3_prepare_one_trb(dep, req, trb_length, chain, i); } /* @@ -1150,6 +1190,16 @@ static void dwc3_prepare_one_trb_sg(struct dwc3_ep *dep, req->num_queued_sgs++; + /* + * The number of pending SG entries may not correspond to the + * number of mapped SG entries. If all the data are queued, then + * don't include unused SG entries. + */ + if (length == 0) { + req->num_pending_sgs -= req->request.num_mapped_sgs - req->num_queued_sgs; + break; + } + if (!dwc3_calc_trbs_left(dep)) break; } @@ -1169,7 +1219,7 @@ static void dwc3_prepare_one_trb_linear(struct dwc3_ep *dep, req->needs_extra_trb = true; /* prepare normal TRB */ - dwc3_prepare_one_trb(dep, req, true, 0); + dwc3_prepare_one_trb(dep, req, length, true, 0); /* Now prepare one extra TRB to align transfer size */ trb = &dep->trb_pool[dep->trb_enqueue]; @@ -1180,6 +1230,7 @@ static void dwc3_prepare_one_trb_linear(struct dwc3_ep *dep, req->request.no_interrupt, req->request.is_last); } else if (req->request.zero && req->request.length && + !usb_endpoint_xfer_isoc(dep->endpoint.desc) && (IS_ALIGNED(req->request.length, maxp))) { struct dwc3 *dwc = dep->dwc; struct dwc3_trb *trb; @@ -1187,18 +1238,29 @@ static void dwc3_prepare_one_trb_linear(struct dwc3_ep *dep, req->needs_extra_trb = true; /* prepare normal TRB */ - dwc3_prepare_one_trb(dep, req, true, 0); + dwc3_prepare_one_trb(dep, req, length, true, 0); - /* Now prepare one extra TRB to handle ZLP */ + /* Prepare one extra TRB to handle ZLP */ trb = &dep->trb_pool[dep->trb_enqueue]; req->num_trbs++; __dwc3_prepare_one_trb(dep, trb, dwc->bounce_addr, 0, - false, 1, req->request.stream_id, + !req->direction, 1, req->request.stream_id, req->request.short_not_ok, req->request.no_interrupt, req->request.is_last); + + /* Prepare one more TRB to handle MPS alignment for OUT */ + if (!req->direction) { + trb = &dep->trb_pool[dep->trb_enqueue]; + req->num_trbs++; + __dwc3_prepare_one_trb(dep, trb, dwc->bounce_addr, maxp, + false, 1, req->request.stream_id, + req->request.short_not_ok, + req->request.no_interrupt, + req->request.is_last); + } } else { - dwc3_prepare_one_trb(dep, req, false, 0); + dwc3_prepare_one_trb(dep, req, length, false, 0); } } @@ -2671,8 +2733,17 @@ static int dwc3_gadget_ep_cleanup_completed_request(struct dwc3_ep *dep, status); if (req->needs_extra_trb) { + unsigned int maxp = usb_endpoint_maxp(dep->endpoint.desc); + ret = dwc3_gadget_ep_reclaim_trb_linear(dep, req, event, status); + + /* Reclaim MPS padding TRB for ZLP */ + if (!req->direction && req->request.zero && req->request.length && + !usb_endpoint_xfer_isoc(dep->endpoint.desc) && + (IS_ALIGNED(req->request.length, maxp))) + ret = dwc3_gadget_ep_reclaim_trb_linear(dep, req, event, status); + req->needs_extra_trb = false; } diff --git a/drivers/usb/gadget/function/f_mass_storage.c b/drivers/usb/gadget/function/f_mass_storage.c index 331c951d72dc..950c9435beec 100644 --- a/drivers/usb/gadget/function/f_mass_storage.c +++ b/drivers/usb/gadget/function/f_mass_storage.c @@ -2039,7 +2039,6 @@ static int do_scsi_command(struct fsg_common *common) case RELEASE: case RESERVE: case SEND_DIAGNOSTIC: - fallthrough; default: unknown_cmnd: diff --git a/drivers/usb/gadget/function/f_ncm.c b/drivers/usb/gadget/function/f_ncm.c index 1d900081b1f0..b4206b0dede5 100644 --- a/drivers/usb/gadget/function/f_ncm.c +++ b/drivers/usb/gadget/function/f_ncm.c @@ -1181,12 +1181,15 @@ static int ncm_unwrap_ntb(struct gether *port, int ndp_index; unsigned dg_len, dg_len2; unsigned ndp_len; + unsigned block_len; struct sk_buff *skb2; int ret = -EINVAL; - unsigned max_size = le32_to_cpu(ntb_parameters.dwNtbOutMaxSize); + unsigned ntb_max = le32_to_cpu(ntb_parameters.dwNtbOutMaxSize); + unsigned frame_max = le16_to_cpu(ecm_desc.wMaxSegmentSize); const struct ndp_parser_opts *opts = ncm->parser_opts; unsigned crc_len = ncm->is_crc ? sizeof(uint32_t) : 0; int dgram_counter; + bool ndp_after_header; /* dwSignature */ if (get_unaligned_le32(tmp) != opts->nth_sign) { @@ -1205,25 +1208,37 @@ static int ncm_unwrap_ntb(struct gether *port, } tmp++; /* skip wSequence */ + block_len = get_ncm(&tmp, opts->block_length); /* (d)wBlockLength */ - if (get_ncm(&tmp, opts->block_length) > max_size) { + if (block_len > ntb_max) { INFO(port->func.config->cdev, "OUT size exceeded\n"); goto err; } ndp_index = get_ncm(&tmp, opts->ndp_index); + ndp_after_header = false; /* Run through all the NDP's in the NTB */ do { - /* NCM 3.2 */ - if (((ndp_index % 4) != 0) && - (ndp_index < opts->nth_size)) { + /* + * NCM 3.2 + * dwNdpIndex + */ + if (((ndp_index % 4) != 0) || + (ndp_index < opts->nth_size) || + (ndp_index > (block_len - + opts->ndp_size))) { INFO(port->func.config->cdev, "Bad index: %#X\n", ndp_index); goto err; } + if (ndp_index == opts->nth_size) + ndp_after_header = true; - /* walk through NDP */ + /* + * walk through NDP + * dwSignature + */ tmp = (void *)(skb->data + ndp_index); if (get_unaligned_le32(tmp) != ncm->ndp_sign) { INFO(port->func.config->cdev, "Wrong NDP SIGN\n"); @@ -1234,14 +1249,15 @@ static int ncm_unwrap_ntb(struct gether *port, ndp_len = get_unaligned_le16(tmp++); /* * NCM 3.3.1 + * wLength * entry is 2 items * item size is 16/32 bits, opts->dgram_item_len * 2 bytes * minimal: struct usb_cdc_ncm_ndpX + normal entry + zero entry * Each entry is a dgram index and a dgram length. */ if ((ndp_len < opts->ndp_size - + 2 * 2 * (opts->dgram_item_len * 2)) - || (ndp_len % opts->ndplen_align != 0)) { + + 2 * 2 * (opts->dgram_item_len * 2)) || + (ndp_len % opts->ndplen_align != 0)) { INFO(port->func.config->cdev, "Bad NDP length: %#X\n", ndp_len); goto err; @@ -1258,8 +1274,21 @@ static int ncm_unwrap_ntb(struct gether *port, do { index = index2; + /* wDatagramIndex[0] */ + if ((index < opts->nth_size) || + (index > block_len - opts->dpe_size)) { + INFO(port->func.config->cdev, + "Bad index: %#X\n", index); + goto err; + } + dg_len = dg_len2; - if (dg_len < 14 + crc_len) { /* ethernet hdr + crc */ + /* + * wDatagramLength[0] + * ethernet hdr + crc or larger than max frame size + */ + if ((dg_len < 14 + crc_len) || + (dg_len > frame_max)) { INFO(port->func.config->cdev, "Bad dgram length: %#X\n", dg_len); goto err; @@ -1283,6 +1312,37 @@ static int ncm_unwrap_ntb(struct gether *port, index2 = get_ncm(&tmp, opts->dgram_item_len); dg_len2 = get_ncm(&tmp, opts->dgram_item_len); + if (index2 == 0 || dg_len2 == 0) + break; + + /* wDatagramIndex[1] */ + if (ndp_after_header) { + if (index2 < opts->nth_size + opts->ndp_size) { + INFO(port->func.config->cdev, + "Bad index: %#X\n", index2); + goto err; + } + } else { + if (index2 < opts->nth_size + opts->dpe_size) { + INFO(port->func.config->cdev, + "Bad index: %#X\n", index2); + goto err; + } + } + if (index2 > block_len - opts->dpe_size) { + INFO(port->func.config->cdev, + "Bad index: %#X\n", index2); + goto err; + } + + /* wDatagramLength[1] */ + if ((dg_len2 < 14 + crc_len) || + (dg_len2 > frame_max)) { + INFO(port->func.config->cdev, + "Bad dgram length: %#X\n", dg_len); + goto err; + } + /* * Copy the data into a new skb. * This ensures the truesize is correct @@ -1299,9 +1359,6 @@ static int ncm_unwrap_ntb(struct gether *port, ndp_len -= 2 * (opts->dgram_item_len * 2); dgram_counter++; - - if (index2 == 0 || dg_len2 == 0) - break; } while (ndp_len > 2 * (opts->dgram_item_len * 2)); } while (ndp_index); diff --git a/drivers/usb/gadget/function/f_tcm.c b/drivers/usb/gadget/function/f_tcm.c index d94b814328c8..184165e27908 100644 --- a/drivers/usb/gadget/function/f_tcm.c +++ b/drivers/usb/gadget/function/f_tcm.c @@ -753,12 +753,13 @@ static int uasp_alloc_stream_res(struct f_uas *fu, struct uas_stream *stream) goto err_sts; return 0; + err_sts: - usb_ep_free_request(fu->ep_status, stream->req_status); - stream->req_status = NULL; -err_out: usb_ep_free_request(fu->ep_out, stream->req_out); stream->req_out = NULL; +err_out: + usb_ep_free_request(fu->ep_in, stream->req_in); + stream->req_in = NULL; out: return -ENOMEM; } diff --git a/drivers/usb/gadget/u_f.h b/drivers/usb/gadget/u_f.h index eaa13fd3dc7f..e313c3b8dcb1 100644 --- a/drivers/usb/gadget/u_f.h +++ b/drivers/usb/gadget/u_f.h @@ -14,6 +14,7 @@ #define __U_F_H__ #include <linux/usb/gadget.h> +#include <linux/overflow.h> /* Variable Length Array Macros **********************************************/ #define vla_group(groupname) size_t groupname##__next = 0 @@ -21,21 +22,36 @@ #define vla_item(groupname, type, name, n) \ size_t groupname##_##name##__offset = ({ \ - size_t align_mask = __alignof__(type) - 1; \ - size_t offset = (groupname##__next + align_mask) & ~align_mask;\ - size_t size = (n) * sizeof(type); \ - groupname##__next = offset + size; \ + size_t offset = 0; \ + if (groupname##__next != SIZE_MAX) { \ + size_t align_mask = __alignof__(type) - 1; \ + size_t size = array_size(n, sizeof(type)); \ + offset = (groupname##__next + align_mask) & \ + ~align_mask; \ + if (check_add_overflow(offset, size, \ + &groupname##__next)) { \ + groupname##__next = SIZE_MAX; \ + offset = 0; \ + } \ + } \ offset; \ }) #define vla_item_with_sz(groupname, type, name, n) \ - size_t groupname##_##name##__sz = (n) * sizeof(type); \ - size_t groupname##_##name##__offset = ({ \ - size_t align_mask = __alignof__(type) - 1; \ - size_t offset = (groupname##__next + align_mask) & ~align_mask;\ - size_t size = groupname##_##name##__sz; \ - groupname##__next = offset + size; \ - offset; \ + size_t groupname##_##name##__sz = array_size(n, sizeof(type)); \ + size_t groupname##_##name##__offset = ({ \ + size_t offset = 0; \ + if (groupname##__next != SIZE_MAX) { \ + size_t align_mask = __alignof__(type) - 1; \ + offset = (groupname##__next + align_mask) & \ + ~align_mask; \ + if (check_add_overflow(offset, groupname##_##name##__sz,\ + &groupname##__next)) { \ + groupname##__next = SIZE_MAX; \ + offset = 0; \ + } \ + } \ + offset; \ }) #define vla_ptr(ptr, groupname, name) \ diff --git a/drivers/usb/gadget/udc/atmel_usba_udc.c b/drivers/usb/gadget/udc/atmel_usba_udc.c index fa6793065c7c..a6426dd1cfef 100644 --- a/drivers/usb/gadget/udc/atmel_usba_udc.c +++ b/drivers/usb/gadget/udc/atmel_usba_udc.c @@ -328,7 +328,7 @@ static int usba_config_fifo_table(struct usba_udc *udc) switch (fifo_mode) { default: fifo_mode = 0; - /* fall through */ + fallthrough; case 0: udc->fifo_cfg = NULL; n = 0; diff --git a/drivers/usb/gadget/udc/fsl_udc_core.c b/drivers/usb/gadget/udc/fsl_udc_core.c index b2638e83bb49..a6f7b2594c09 100644 --- a/drivers/usb/gadget/udc/fsl_udc_core.c +++ b/drivers/usb/gadget/udc/fsl_udc_core.c @@ -250,7 +250,7 @@ static int dr_controller_setup(struct fsl_udc *udc) break; case FSL_USB2_PHY_UTMI_WIDE: portctrl |= PORTSCX_PTW_16BIT; - /* fall through */ + fallthrough; case FSL_USB2_PHY_UTMI: case FSL_USB2_PHY_UTMI_DUAL: if (udc->pdata->have_sysif_regs) { diff --git a/drivers/usb/gadget/udc/pxa25x_udc.c b/drivers/usb/gadget/udc/pxa25x_udc.c index cfafdd92c2a8..10324a7334fe 100644 --- a/drivers/usb/gadget/udc/pxa25x_udc.c +++ b/drivers/usb/gadget/udc/pxa25x_udc.c @@ -2340,12 +2340,12 @@ static int pxa25x_udc_probe(struct platform_device *pdev) case PXA250_A0: case PXA250_A1: /* A0/A1 "not released"; ep 13, 15 unusable */ - /* fall through */ + fallthrough; case PXA250_B2: case PXA210_B2: case PXA250_B1: case PXA210_B1: case PXA250_B0: case PXA210_B0: /* OUT-DMA is broken ... */ - /* fall through */ + fallthrough; case PXA250_C0: case PXA210_C0: break; #elif defined(CONFIG_ARCH_IXP4XX) diff --git a/drivers/usb/host/isp116x-hcd.c b/drivers/usb/host/isp116x-hcd.c index a87c0b26279e..3055d9abfec3 100644 --- a/drivers/usb/host/isp116x-hcd.c +++ b/drivers/usb/host/isp116x-hcd.c @@ -1019,7 +1019,7 @@ static int isp116x_hub_control(struct usb_hcd *hcd, spin_lock_irqsave(&isp116x->lock, flags); isp116x_write_reg32(isp116x, HCRHSTATUS, RH_HS_OCIC); spin_unlock_irqrestore(&isp116x->lock, flags); - /* fall through */ + fallthrough; case C_HUB_LOCAL_POWER: DBG("C_HUB_LOCAL_POWER\n"); break; @@ -1421,10 +1421,10 @@ static int isp116x_bus_suspend(struct usb_hcd *hcd) isp116x_write_reg32(isp116x, HCCONTROL, (val & ~HCCONTROL_HCFS) | HCCONTROL_USB_RESET); - /* fall through */ + fallthrough; case HCCONTROL_USB_RESET: ret = -EBUSY; - /* fall through */ + fallthrough; default: /* HCCONTROL_USB_SUSPEND */ spin_unlock_irqrestore(&isp116x->lock, flags); break; diff --git a/drivers/usb/host/ohci-exynos.c b/drivers/usb/host/ohci-exynos.c index bd40e597f256..5f5e8a64c8e2 100644 --- a/drivers/usb/host/ohci-exynos.c +++ b/drivers/usb/host/ohci-exynos.c @@ -171,9 +171,8 @@ static int exynos_ohci_probe(struct platform_device *pdev) hcd->rsrc_len = resource_size(res); irq = platform_get_irq(pdev, 0); - if (!irq) { - dev_err(&pdev->dev, "Failed to get IRQ\n"); - err = -ENODEV; + if (irq < 0) { + err = irq; goto fail_io; } diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c index ce32ef864d6a..c32b544c043a 100644 --- a/drivers/usb/host/pci-quirks.c +++ b/drivers/usb/host/pci-quirks.c @@ -956,7 +956,8 @@ static void quirk_usb_disable_ehci(struct pci_dev *pdev) ehci_bios_handoff(pdev, op_reg_base, cap, offset); break; case 0: /* Illegal reserved cap, set cap=0 so we exit */ - cap = 0; /* fall through */ + cap = 0; + fallthrough; default: dev_warn(&pdev->dev, "EHCI: unrecognized capability %02x\n", diff --git a/drivers/usb/host/xhci-dbgcap.c b/drivers/usb/host/xhci-dbgcap.c index fcc5ac5ce8b1..ccb0156fcebe 100644 --- a/drivers/usb/host/xhci-dbgcap.c +++ b/drivers/usb/host/xhci-dbgcap.c @@ -699,7 +699,7 @@ static void dbc_handle_xfer_event(struct xhci_dbc *dbc, union xhci_trb *event) switch (comp_code) { case COMP_SUCCESS: remain_length = 0; - /* FALLTHROUGH */ + fallthrough; case COMP_SHORT_PACKET: status = 0; break; diff --git a/drivers/usb/host/xhci-debugfs.c b/drivers/usb/host/xhci-debugfs.c index 92e25a62fdb5..c88bffd68742 100644 --- a/drivers/usb/host/xhci-debugfs.c +++ b/drivers/usb/host/xhci-debugfs.c @@ -274,7 +274,7 @@ static int xhci_slot_context_show(struct seq_file *s, void *unused) static int xhci_endpoint_context_show(struct seq_file *s, void *unused) { - int dci; + int ep_index; dma_addr_t dma; struct xhci_hcd *xhci; struct xhci_ep_ctx *ep_ctx; @@ -283,9 +283,9 @@ static int xhci_endpoint_context_show(struct seq_file *s, void *unused) xhci = hcd_to_xhci(bus_to_hcd(dev->udev->bus)); - for (dci = 1; dci < 32; dci++) { - ep_ctx = xhci_get_ep_ctx(xhci, dev->out_ctx, dci); - dma = dev->out_ctx->dma + dci * CTX_SIZE(xhci->hcc_params); + for (ep_index = 0; ep_index < 31; ep_index++) { + ep_ctx = xhci_get_ep_ctx(xhci, dev->out_ctx, ep_index); + dma = dev->out_ctx->dma + (ep_index + 1) * CTX_SIZE(xhci->hcc_params); seq_printf(s, "%pad: %s\n", &dma, xhci_decode_ep_context(le32_to_cpu(ep_ctx->ep_info), le32_to_cpu(ep_ctx->ep_info2), diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c index c3554e37e09f..c799ca5361d4 100644 --- a/drivers/usb/host/xhci-hub.c +++ b/drivers/usb/host/xhci-hub.c @@ -740,15 +740,6 @@ static void xhci_hub_report_usb3_link_state(struct xhci_hcd *xhci, { u32 pls = status_reg & PORT_PLS_MASK; - /* resume state is a xHCI internal state. - * Do not report it to usb core, instead, pretend to be U3, - * thus usb core knows it's not ready for transfer - */ - if (pls == XDEV_RESUME) { - *status |= USB_SS_PORT_LS_U3; - return; - } - /* When the CAS bit is set then warm reset * should be performed on port */ @@ -771,6 +762,16 @@ static void xhci_hub_report_usb3_link_state(struct xhci_hcd *xhci, pls |= USB_PORT_STAT_CONNECTION; } else { /* + * Resume state is an xHCI internal state. Do not report it to + * usb core, instead, pretend to be U3, thus usb core knows + * it's not ready for transfer. + */ + if (pls == XDEV_RESUME) { + *status |= USB_SS_PORT_LS_U3; + return; + } + + /* * If CAS bit isn't set but the Port is already at * Compliance Mode, fake a connection so the USB core * notices the Compliance state and resets the port. @@ -1483,7 +1484,7 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, break; case USB_PORT_FEAT_C_SUSPEND: bus_state->port_c_suspend &= ~(1 << wIndex); - /* fall through */ + fallthrough; case USB_PORT_FEAT_C_RESET: case USB_PORT_FEAT_C_BH_PORT_RESET: case USB_PORT_FEAT_C_CONNECTION: diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index 696fad50b478..fe405cd38dbc 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -1311,7 +1311,7 @@ static unsigned int xhci_get_endpoint_interval(struct usb_device *udev, interval = xhci_parse_microframe_interval(udev, ep); break; } - /* Fall through - SS and HS isoc/int have same decoding */ + fallthrough; /* SS and HS isoc/int have same decoding */ case USB_SPEED_SUPER_PLUS: case USB_SPEED_SUPER: @@ -1331,7 +1331,7 @@ static unsigned int xhci_get_endpoint_interval(struct usb_device *udev, * since it uses the same rules as low speed interrupt * endpoints. */ - /* fall through */ + fallthrough; case USB_SPEED_LOW: if (usb_endpoint_xfer_int(&ep->desc) || diff --git a/drivers/usb/host/xhci-pci-renesas.c b/drivers/usb/host/xhci-pci-renesas.c index 59b1965ad0a3..f97ac9f52bf4 100644 --- a/drivers/usb/host/xhci-pci-renesas.c +++ b/drivers/usb/host/xhci-pci-renesas.c @@ -50,20 +50,6 @@ #define RENESAS_RETRY 10000 #define RENESAS_DELAY 10 -#define ROM_VALID_01 0x2013 -#define ROM_VALID_02 0x2026 - -static int renesas_verify_fw_version(struct pci_dev *pdev, u32 version) -{ - switch (version) { - case ROM_VALID_01: - case ROM_VALID_02: - return 0; - } - dev_err(&pdev->dev, "FW has invalid version :%d\n", version); - return -EINVAL; -} - static int renesas_fw_download_image(struct pci_dev *dev, const u32 *fw, size_t step, bool rom) { @@ -202,10 +188,7 @@ static int renesas_check_rom_state(struct pci_dev *pdev) version &= RENESAS_FW_VERSION_FIELD; version = version >> RENESAS_FW_VERSION_OFFSET; - - err = renesas_verify_fw_version(pdev, version); - if (err) - return err; + dev_dbg(&pdev->dev, "Found ROM version: %x\n", version); /* * Test if ROM is present and loaded, if so we can skip everything diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 2c255d0620b0..a741a38a4c69 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -2103,7 +2103,7 @@ static int process_ctrl_td(struct xhci_hcd *xhci, struct xhci_td *td, break; xhci_dbg(xhci, "TRB error %u, halted endpoint index = %u\n", trb_comp_code, ep_index); - /* else fall through */ + fallthrough; case COMP_STALL_ERROR: /* Did we transfer part of the data (middle) phase? */ if (trb_type == TRB_DATA || trb_type == TRB_NORMAL) diff --git a/drivers/usb/host/xhci-tegra.c b/drivers/usb/host/xhci-tegra.c index 0672edcba8f1..934be1686352 100644 --- a/drivers/usb/host/xhci-tegra.c +++ b/drivers/usb/host/xhci-tegra.c @@ -1136,7 +1136,7 @@ static struct phy *tegra_xusb_get_phy(struct tegra_xusb *tegra, char *name, unsigned int i, phy_count = 0; for (i = 0; i < tegra->soc->num_types; i++) { - if (!strncmp(tegra->soc->phy_types[i].name, "usb2", + if (!strncmp(tegra->soc->phy_types[i].name, name, strlen(name))) return tegra->phys[phy_count+port]; @@ -1258,6 +1258,8 @@ static int tegra_xusb_init_usb_phy(struct tegra_xusb *tegra) INIT_WORK(&tegra->id_work, tegra_xhci_id_work); tegra->id_nb.notifier_call = tegra_xhci_id_notify; + tegra->otg_usb2_port = -EINVAL; + tegra->otg_usb3_port = -EINVAL; for (i = 0; i < tegra->num_usb_phys; i++) { struct phy *phy = tegra_xusb_get_phy(tegra, "usb2", i); diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 3c41b14ecce7..f4cedcaee14b 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -3236,10 +3236,11 @@ static void xhci_endpoint_reset(struct usb_hcd *hcd, wait_for_completion(cfg_cmd->completion); - ep->ep_state &= ~EP_SOFT_CLEAR_TOGGLE; xhci_free_command(xhci, cfg_cmd); cleanup: xhci_free_command(xhci, stop_cmd); + if (ep->ep_state & EP_SOFT_CLEAR_TOGGLE) + ep->ep_state &= ~EP_SOFT_CLEAR_TOGGLE; } static int xhci_check_streams_endpoint(struct xhci_hcd *xhci, @@ -4618,7 +4619,7 @@ static unsigned long long xhci_calculate_intel_u1_timeout( break; } /* Otherwise the calculation is the same as isoc eps */ - /* fall through */ + fallthrough; case USB_ENDPOINT_XFER_ISOC: timeout_ns = xhci_service_interval_to_ns(desc); timeout_ns = DIV_ROUND_UP_ULL(timeout_ns * 105, 100); diff --git a/drivers/usb/misc/lvstest.c b/drivers/usb/misc/lvstest.c index 407fe7570f3b..f8686139d6f3 100644 --- a/drivers/usb/misc/lvstest.c +++ b/drivers/usb/misc/lvstest.c @@ -426,7 +426,7 @@ static int lvs_rh_probe(struct usb_interface *intf, USB_DT_SS_HUB_SIZE, USB_CTRL_GET_TIMEOUT); if (ret < (USB_DT_HUB_NONVAR_SIZE + 2)) { dev_err(&hdev->dev, "wrong root hub descriptor read %d\n", ret); - return ret; + return ret < 0 ? ret : -EINVAL; } /* submit urb to poll interrupt endpoint */ diff --git a/drivers/usb/misc/yurex.c b/drivers/usb/misc/yurex.c index 2063ef071393..e3165d79b5f6 100644 --- a/drivers/usb/misc/yurex.c +++ b/drivers/usb/misc/yurex.c @@ -490,7 +490,7 @@ static ssize_t yurex_write(struct file *file, const char __user *user_buffer, prepare_to_wait(&dev->waitq, &wait, TASK_INTERRUPTIBLE); dev_dbg(&dev->interface->dev, "%s - submit %c\n", __func__, dev->cntl_buffer[0]); - retval = usb_submit_urb(dev->cntl_urb, GFP_KERNEL); + retval = usb_submit_urb(dev->cntl_urb, GFP_ATOMIC); if (retval >= 0) timeout = schedule_timeout(YUREX_WRITE_TIMEOUT); finish_wait(&dev->waitq, &wait); diff --git a/drivers/usb/musb/cppi_dma.c b/drivers/usb/musb/cppi_dma.c index c545b27ea568..edb5b63d7063 100644 --- a/drivers/usb/musb/cppi_dma.c +++ b/drivers/usb/musb/cppi_dma.c @@ -975,7 +975,7 @@ static int cppi_channel_program(struct dma_channel *ch, musb_dbg(musb, "%cX DMA%d not allocated!", cppi_ch->transmit ? 'T' : 'R', cppi_ch->index); - /* FALLTHROUGH */ + fallthrough; case MUSB_DMA_STATUS_FREE: break; } diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index 5a56a03996b1..849e0b770130 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -852,7 +852,7 @@ static void musb_handle_intr_suspend(struct musb *musb, u8 devctl) case OTG_STATE_B_IDLE: if (!musb->is_active) break; - /* fall through */ + fallthrough; case OTG_STATE_B_PERIPHERAL: musb_g_suspend(musb); musb->is_active = musb->g.b_hnp_enable; @@ -972,9 +972,8 @@ static void musb_handle_intr_disconnect(struct musb *musb, u8 devctl) case OTG_STATE_A_PERIPHERAL: musb_hnp_stop(musb); musb_root_disconnect(musb); - /* FALLTHROUGH */ + fallthrough; case OTG_STATE_B_WAIT_ACON: - /* FALLTHROUGH */ case OTG_STATE_B_PERIPHERAL: case OTG_STATE_B_IDLE: musb_g_disconnect(musb); @@ -1009,7 +1008,7 @@ static void musb_handle_intr_reset(struct musb *musb) switch (musb->xceiv->otg->state) { case OTG_STATE_A_SUSPEND: musb_g_reset(musb); - /* FALLTHROUGH */ + fallthrough; case OTG_STATE_A_WAIT_BCON: /* OPT TD.4.7-900ms */ /* never use invalid T(a_wait_bcon) */ musb_dbg(musb, "HNP: in %s, %d msec timeout", @@ -1030,7 +1029,7 @@ static void musb_handle_intr_reset(struct musb *musb) break; case OTG_STATE_B_IDLE: musb->xceiv->otg->state = OTG_STATE_B_PERIPHERAL; - /* FALLTHROUGH */ + fallthrough; case OTG_STATE_B_PERIPHERAL: musb_g_reset(musb); break; @@ -1471,7 +1470,7 @@ static int ep_config_from_table(struct musb *musb) switch (fifo_mode) { default: fifo_mode = 0; - /* FALLTHROUGH */ + fallthrough; case 0: cfg = mode_0_cfg; n = ARRAY_SIZE(mode_0_cfg); @@ -2018,7 +2017,7 @@ static void musb_pm_runtime_check_session(struct musb *musb) musb->quirk_retries--; return; } - /* fall through */ + fallthrough; case MUSB_QUIRK_A_DISCONNECT_19: if (musb->quirk_retries && !musb->flush_irq_work) { musb_dbg(musb, diff --git a/drivers/usb/musb/musb_dsps.c b/drivers/usb/musb/musb_dsps.c index 19556c1a8ae8..30085b2be7b9 100644 --- a/drivers/usb/musb/musb_dsps.c +++ b/drivers/usb/musb/musb_dsps.c @@ -232,7 +232,7 @@ static int dsps_check_status(struct musb *musb, void *unused) dsps_mod_timer_optional(glue); break; } - /* fall through */ + fallthrough; case OTG_STATE_A_WAIT_BCON: /* keep VBUS on for host-only mode */ @@ -242,7 +242,7 @@ static int dsps_check_status(struct musb *musb, void *unused) } musb_writeb(musb->mregs, MUSB_DEVCTL, 0); skip_session = 1; - /* fall through */ + fallthrough; case OTG_STATE_A_IDLE: case OTG_STATE_B_IDLE: @@ -793,7 +793,7 @@ static int dsps_create_musb_pdev(struct dsps_glue *glue, case USB_SPEED_SUPER: dev_warn(dev, "ignore incorrect maximum_speed " "(super-speed) setting in dts"); - /* fall through */ + fallthrough; default: config->maximum_speed = USB_SPEED_HIGH; } diff --git a/drivers/usb/musb/musb_gadget_ep0.c b/drivers/usb/musb/musb_gadget_ep0.c index 0ae3e0be043e..44d3cb02fa76 100644 --- a/drivers/usb/musb/musb_gadget_ep0.c +++ b/drivers/usb/musb/musb_gadget_ep0.c @@ -735,7 +735,7 @@ irqreturn_t musb_g_ep0_irq(struct musb *musb) musb_writeb(mbase, MUSB_TESTMODE, musb->test_mode_nr); } - /* FALLTHROUGH */ + fallthrough; case MUSB_EP0_STAGE_STATUSOUT: /* end of sequence #1: write to host (TX state) */ @@ -767,7 +767,7 @@ irqreturn_t musb_g_ep0_irq(struct musb *musb) */ retval = IRQ_HANDLED; musb->ep0_state = MUSB_EP0_STAGE_SETUP; - /* FALLTHROUGH */ + fallthrough; case MUSB_EP0_STAGE_SETUP: setup: diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c index 8b7d22a0c0fb..30c5e7de0761 100644 --- a/drivers/usb/musb/musb_host.c +++ b/drivers/usb/musb/musb_host.c @@ -360,7 +360,7 @@ static void musb_advance_schedule(struct musb *musb, struct urb *urb, qh = first_qh(head); break; } - /* fall through */ + fallthrough; case USB_ENDPOINT_XFER_ISOC: case USB_ENDPOINT_XFER_INT: @@ -1019,7 +1019,7 @@ static bool musb_h_ep0_continue(struct musb *musb, u16 len, struct urb *urb) musb->ep0_stage = MUSB_EP0_OUT; more = true; } - /* FALLTHROUGH */ + fallthrough; case MUSB_EP0_OUT: fifo_count = min_t(size_t, qh->maxpacket, urb->transfer_buffer_length - @@ -2222,7 +2222,7 @@ static int musb_urb_enqueue( interval = max_t(u8, epd->bInterval, 1); break; } - /* FALLTHROUGH */ + fallthrough; case USB_ENDPOINT_XFER_ISOC: /* ISO always uses logarithmic encoding */ interval = min_t(u8, epd->bInterval, 16); diff --git a/drivers/usb/musb/musb_virthub.c b/drivers/usb/musb/musb_virthub.c index cb7ae297a3af..cafc69536e1d 100644 --- a/drivers/usb/musb/musb_virthub.c +++ b/drivers/usb/musb/musb_virthub.c @@ -211,7 +211,7 @@ void musb_root_disconnect(struct musb *musb) musb->g.is_a_peripheral = 1; break; } - /* FALLTHROUGH */ + fallthrough; case OTG_STATE_A_HOST: musb->xceiv->otg->state = OTG_STATE_A_WAIT_BCON; musb->is_active = 0; diff --git a/drivers/usb/musb/omap2430.c b/drivers/usb/musb/omap2430.c index d62c78b97cad..4232f1ce3fbf 100644 --- a/drivers/usb/musb/omap2430.c +++ b/drivers/usb/musb/omap2430.c @@ -104,7 +104,7 @@ static void omap_musb_set_mailbox(struct omap2430_glue *glue) if (error) break; musb->xceiv->otg->state = OTG_STATE_A_WAIT_VRISE; - /* Fall through */ + fallthrough; case OTG_STATE_A_WAIT_VRISE: case OTG_STATE_A_WAIT_BCON: case OTG_STATE_A_HOST: diff --git a/drivers/usb/musb/tusb6010.c b/drivers/usb/musb/tusb6010.c index 99890d1bbfcb..c26683a2702b 100644 --- a/drivers/usb/musb/tusb6010.c +++ b/drivers/usb/musb/tusb6010.c @@ -464,7 +464,7 @@ static void musb_do_idle(struct timer_list *t) dev_dbg(musb->controller, "Nothing connected %s, turning off VBUS\n", usb_otg_state_string(musb->xceiv->otg->state)); } - /* FALLTHROUGH */ + fallthrough; case OTG_STATE_A_IDLE: tusb_musb_set_vbus(musb, 0); default: diff --git a/drivers/usb/phy/phy-jz4770.c b/drivers/usb/phy/phy-jz4770.c index d4ee3cb721ea..f6d3731581eb 100644 --- a/drivers/usb/phy/phy-jz4770.c +++ b/drivers/usb/phy/phy-jz4770.c @@ -176,6 +176,7 @@ static int ingenic_usb_phy_init(struct usb_phy *phy) /* Wait for PHY to reset */ usleep_range(30, 300); + reg = readl(priv->base + REG_USBPCR_OFFSET); writel(reg & ~USBPCR_POR, priv->base + REG_USBPCR_OFFSET); usleep_range(300, 1000); diff --git a/drivers/usb/storage/sddr55.c b/drivers/usb/storage/sddr55.c index c8a988d2cfdd..15dc25801cdc 100644 --- a/drivers/usb/storage/sddr55.c +++ b/drivers/usb/storage/sddr55.c @@ -592,7 +592,7 @@ static unsigned long sddr55_get_capacity(struct us_data *us) { case 0x64: info->pageshift = 8; info->smallpageshift = 1; - /* fall through */ + fallthrough; case 0x5d: // 5d is a ROM card with pagesize 512. return 0x00200000; diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c index d592071119ba..08f9296431e9 100644 --- a/drivers/usb/storage/uas.c +++ b/drivers/usb/storage/uas.c @@ -688,7 +688,7 @@ static int uas_queuecommand_lck(struct scsi_cmnd *cmnd, break; case DMA_BIDIRECTIONAL: cmdinfo->state |= ALLOC_DATA_IN_URB | SUBMIT_DATA_IN_URB; - /* fall through */ + fallthrough; case DMA_TO_DEVICE: cmdinfo->state |= ALLOC_DATA_OUT_URB | SUBMIT_DATA_OUT_URB; case DMA_NONE: diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index 220ae2c356ee..5732e9691f08 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -2328,7 +2328,7 @@ UNUSUAL_DEV( 0x357d, 0x7788, 0x0114, 0x0114, "JMicron", "USB to ATA/ATAPI Bridge", USB_SC_DEVICE, USB_PR_DEVICE, NULL, - US_FL_BROKEN_FUA ), + US_FL_BROKEN_FUA | US_FL_IGNORE_UAS ), /* Reported by Andrey Rahmatullin <wrar@altlinux.org> */ UNUSUAL_DEV( 0x4102, 0x1020, 0x0100, 0x0100, diff --git a/drivers/usb/storage/unusual_uas.h b/drivers/usb/storage/unusual_uas.h index 162b09d69f62..711ab240058c 100644 --- a/drivers/usb/storage/unusual_uas.h +++ b/drivers/usb/storage/unusual_uas.h @@ -28,6 +28,13 @@ * and don't forget to CC: the USB development list <linux-usb@vger.kernel.org> */ +/* Reported-by: Till Dörges <doerges@pre-sense.de> */ +UNUSUAL_DEV(0x054c, 0x087d, 0x0000, 0x9999, + "Sony", + "PSZ-HA*", + USB_SC_DEVICE, USB_PR_DEVICE, NULL, + US_FL_NO_REPORT_OPCODES), + /* Reported-by: Julian Groß <julian.g@posteo.de> */ UNUSUAL_DEV(0x059f, 0x105f, 0x0000, 0x9999, "LaCie", @@ -80,6 +87,13 @@ UNUSUAL_DEV(0x152d, 0x0578, 0x0000, 0x9999, USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_BROKEN_FUA), +/* Reported-by: Thinh Nguyen <thinhn@synopsys.com> */ +UNUSUAL_DEV(0x154b, 0xf00d, 0x0000, 0x9999, + "PNY", + "Pro Elite SSD", + USB_SC_DEVICE, USB_PR_DEVICE, NULL, + US_FL_NO_ATA_1X), + /* Reported-by: Hans de Goede <hdegoede@redhat.com> */ UNUSUAL_DEV(0x2109, 0x0711, 0x0000, 0x9999, "VIA", diff --git a/drivers/usb/typec/tcpm/tcpci.c b/drivers/usb/typec/tcpm/tcpci.c index f57d91fd0e09..bd80e03b2b6f 100644 --- a/drivers/usb/typec/tcpm/tcpci.c +++ b/drivers/usb/typec/tcpm/tcpci.c @@ -157,7 +157,7 @@ static enum typec_cc_status tcpci_to_typec_cc(unsigned int cc, bool sink) case 0x3: if (sink) return TYPEC_CC_RP_3_0; - /* fall through */ + fallthrough; case 0x0: default: return TYPEC_CC_OPEN; diff --git a/drivers/usb/typec/tcpm/tcpm.c b/drivers/usb/typec/tcpm/tcpm.c index 85184ffac48e..92806547f485 100644 --- a/drivers/usb/typec/tcpm/tcpm.c +++ b/drivers/usb/typec/tcpm/tcpm.c @@ -3394,13 +3394,31 @@ static void run_state_machine(struct tcpm_port *port) tcpm_set_state(port, SNK_HARD_RESET_SINK_OFF, 0); break; case SRC_HARD_RESET_VBUS_OFF: - tcpm_set_vconn(port, true); + /* + * 7.1.5 Response to Hard Resets + * Hard Reset Signaling indicates a communication failure has occurred and the + * Source Shall stop driving VCONN, Shall remove Rp from the VCONN pin and Shall + * drive VBUS to vSafe0V as shown in Figure 7-9. + */ + tcpm_set_vconn(port, false); tcpm_set_vbus(port, false); tcpm_set_roles(port, port->self_powered, TYPEC_SOURCE, tcpm_data_role_for_source(port)); - tcpm_set_state(port, SRC_HARD_RESET_VBUS_ON, PD_T_SRC_RECOVER); + /* + * If tcpc fails to notify vbus off, TCPM will wait for PD_T_SAFE_0V + + * PD_T_SRC_RECOVER before turning vbus back on. + * From Table 7-12 Sequence Description for a Source Initiated Hard Reset: + * 4. Policy Engine waits tPSHardReset after sending Hard Reset Signaling and then + * tells the Device Policy Manager to instruct the power supply to perform a + * Hard Reset. The transition to vSafe0V Shall occur within tSafe0V (t2). + * 5. After tSrcRecover the Source applies power to VBUS in an attempt to + * re-establish communication with the Sink and resume USB Default Operation. + * The transition to vSafe5V Shall occur within tSrcTurnOn(t4). + */ + tcpm_set_state(port, SRC_HARD_RESET_VBUS_ON, PD_T_SAFE_0V + PD_T_SRC_RECOVER); break; case SRC_HARD_RESET_VBUS_ON: + tcpm_set_vconn(port, true); tcpm_set_vbus(port, true); port->tcpc->set_pd_rx(port->tcpc, true); tcpm_set_attached_state(port, true); @@ -3965,7 +3983,11 @@ static void _tcpm_pd_vbus_off(struct tcpm_port *port) tcpm_set_state(port, SNK_HARD_RESET_WAIT_VBUS, 0); break; case SRC_HARD_RESET_VBUS_OFF: - tcpm_set_state(port, SRC_HARD_RESET_VBUS_ON, 0); + /* + * After establishing the vSafe0V voltage condition on VBUS, the Source Shall wait + * tSrcRecover before re-applying VCONN and restoring VBUS to vSafe5V. + */ + tcpm_set_state(port, SRC_HARD_RESET_VBUS_ON, PD_T_SRC_RECOVER); break; case HARD_RESET_SEND: break; diff --git a/drivers/usb/typec/ucsi/displayport.c b/drivers/usb/typec/ucsi/displayport.c index 048381c058a5..261131c9e37c 100644 --- a/drivers/usb/typec/ucsi/displayport.c +++ b/drivers/usb/typec/ucsi/displayport.c @@ -288,8 +288,6 @@ struct typec_altmode *ucsi_register_displayport(struct ucsi_connector *con, struct typec_altmode *alt; struct ucsi_dp *dp; - mutex_lock(&con->lock); - /* We can't rely on the firmware with the capabilities. */ desc->vdo |= DP_CAP_DP_SIGNALING | DP_CAP_RECEPTACLE; @@ -298,15 +296,12 @@ struct typec_altmode *ucsi_register_displayport(struct ucsi_connector *con, desc->vdo |= all_assignments << 16; alt = typec_port_register_altmode(con->port, desc); - if (IS_ERR(alt)) { - mutex_unlock(&con->lock); + if (IS_ERR(alt)) return alt; - } dp = devm_kzalloc(&alt->dev, sizeof(*dp), GFP_KERNEL); if (!dp) { typec_unregister_altmode(alt); - mutex_unlock(&con->lock); return ERR_PTR(-ENOMEM); } @@ -319,7 +314,5 @@ struct typec_altmode *ucsi_register_displayport(struct ucsi_connector *con, alt->ops = &ucsi_displayport_ops; typec_altmode_set_drvdata(alt, dp); - mutex_unlock(&con->lock); - return alt; } diff --git a/drivers/usb/typec/ucsi/ucsi.c b/drivers/usb/typec/ucsi/ucsi.c index affd024190c9..e680fcfdee60 100644 --- a/drivers/usb/typec/ucsi/ucsi.c +++ b/drivers/usb/typec/ucsi/ucsi.c @@ -146,40 +146,33 @@ static int ucsi_exec_command(struct ucsi *ucsi, u64 cmd) return UCSI_CCI_LENGTH(cci); } -static int ucsi_run_command(struct ucsi *ucsi, u64 command, - void *data, size_t size) +int ucsi_send_command(struct ucsi *ucsi, u64 command, + void *data, size_t size) { u8 length; int ret; + mutex_lock(&ucsi->ppm_lock); + ret = ucsi_exec_command(ucsi, command); if (ret < 0) - return ret; + goto out; length = ret; if (data) { ret = ucsi->ops->read(ucsi, UCSI_MESSAGE_IN, data, size); if (ret) - return ret; + goto out; } ret = ucsi_acknowledge_command(ucsi); if (ret) - return ret; - - return length; -} - -int ucsi_send_command(struct ucsi *ucsi, u64 command, - void *retval, size_t size) -{ - int ret; + goto out; - mutex_lock(&ucsi->ppm_lock); - ret = ucsi_run_command(ucsi, command, retval, size); + ret = length; +out: mutex_unlock(&ucsi->ppm_lock); - return ret; } EXPORT_SYMBOL_GPL(ucsi_send_command); @@ -205,7 +198,7 @@ void ucsi_altmode_update_active(struct ucsi_connector *con) int i; command = UCSI_GET_CURRENT_CAM | UCSI_CONNECTOR_NUMBER(con->num); - ret = ucsi_run_command(con->ucsi, command, &cur, sizeof(cur)); + ret = ucsi_send_command(con->ucsi, command, &cur, sizeof(cur)); if (ret < 0) { if (con->ucsi->version > 0x0100) { dev_err(con->ucsi->dev, @@ -354,7 +347,7 @@ ucsi_register_altmodes_nvidia(struct ucsi_connector *con, u8 recipient) command |= UCSI_GET_ALTMODE_RECIPIENT(recipient); command |= UCSI_GET_ALTMODE_CONNECTOR_NUMBER(con->num); command |= UCSI_GET_ALTMODE_OFFSET(i); - len = ucsi_run_command(con->ucsi, command, &alt, sizeof(alt)); + len = ucsi_send_command(con->ucsi, command, &alt, sizeof(alt)); /* * We are collecting all altmodes first and then registering. * Some type-C device will return zero length data beyond last @@ -431,7 +424,7 @@ static int ucsi_register_altmodes(struct ucsi_connector *con, u8 recipient) command |= UCSI_GET_ALTMODE_RECIPIENT(recipient); command |= UCSI_GET_ALTMODE_CONNECTOR_NUMBER(con->num); command |= UCSI_GET_ALTMODE_OFFSET(i); - len = ucsi_run_command(con->ucsi, command, alt, sizeof(alt)); + len = ucsi_send_command(con->ucsi, command, alt, sizeof(alt)); if (len <= 0) return len; @@ -502,7 +495,7 @@ static void ucsi_get_pdos(struct ucsi_connector *con, int is_partner) command |= UCSI_GET_PDOS_PARTNER_PDO(is_partner); command |= UCSI_GET_PDOS_NUM_PDOS(UCSI_MAX_PDOS - 1); command |= UCSI_GET_PDOS_SRC_PDOS; - ret = ucsi_run_command(ucsi, command, con->src_pdos, + ret = ucsi_send_command(ucsi, command, con->src_pdos, sizeof(con->src_pdos)); if (ret < 0) { dev_err(ucsi->dev, "UCSI_GET_PDOS failed (%d)\n", ret); @@ -681,7 +674,7 @@ static void ucsi_handle_connector_change(struct work_struct *work) */ command = UCSI_GET_CAM_SUPPORTED; command |= UCSI_CONNECTOR_NUMBER(con->num); - ucsi_run_command(con->ucsi, command, NULL, 0); + ucsi_send_command(con->ucsi, command, NULL, 0); } if (con->status.change & UCSI_CONSTAT_PARTNER_CHANGE) @@ -736,20 +729,24 @@ static int ucsi_reset_ppm(struct ucsi *ucsi) u32 cci; int ret; + mutex_lock(&ucsi->ppm_lock); + ret = ucsi->ops->async_write(ucsi, UCSI_CONTROL, &command, sizeof(command)); if (ret < 0) - return ret; + goto out; tmo = jiffies + msecs_to_jiffies(UCSI_TIMEOUT_MS); do { - if (time_is_before_jiffies(tmo)) - return -ETIMEDOUT; + if (time_is_before_jiffies(tmo)) { + ret = -ETIMEDOUT; + goto out; + } ret = ucsi->ops->read(ucsi, UCSI_CCI, &cci, sizeof(cci)); if (ret) - return ret; + goto out; /* If the PPM is still doing something else, reset it again. */ if (cci & ~UCSI_CCI_RESET_COMPLETE) { @@ -757,13 +754,15 @@ static int ucsi_reset_ppm(struct ucsi *ucsi) &command, sizeof(command)); if (ret < 0) - return ret; + goto out; } msleep(20); } while (!(cci & UCSI_CCI_RESET_COMPLETE)); - return 0; +out: + mutex_unlock(&ucsi->ppm_lock); + return ret; } static int ucsi_role_cmd(struct ucsi_connector *con, u64 command) @@ -775,9 +774,7 @@ static int ucsi_role_cmd(struct ucsi_connector *con, u64 command) u64 c; /* PPM most likely stopped responding. Resetting everything. */ - mutex_lock(&con->ucsi->ppm_lock); ucsi_reset_ppm(con->ucsi); - mutex_unlock(&con->ucsi->ppm_lock); c = UCSI_SET_NOTIFICATION_ENABLE | con->ucsi->ntfy; ucsi_send_command(con->ucsi, c, NULL, 0); @@ -901,12 +898,15 @@ static int ucsi_register_port(struct ucsi *ucsi, int index) con->num = index + 1; con->ucsi = ucsi; + /* Delay other interactions with the con until registration is complete */ + mutex_lock(&con->lock); + /* Get connector capability */ command = UCSI_GET_CONNECTOR_CAPABILITY; command |= UCSI_CONNECTOR_NUMBER(con->num); - ret = ucsi_run_command(ucsi, command, &con->cap, sizeof(con->cap)); + ret = ucsi_send_command(ucsi, command, &con->cap, sizeof(con->cap)); if (ret < 0) - return ret; + goto out; if (con->cap.op_mode & UCSI_CONCAP_OPMODE_DRP) cap->data = TYPEC_PORT_DRD; @@ -938,27 +938,32 @@ static int ucsi_register_port(struct ucsi *ucsi, int index) ret = ucsi_register_port_psy(con); if (ret) - return ret; + goto out; /* Register the connector */ con->port = typec_register_port(ucsi->dev, cap); - if (IS_ERR(con->port)) - return PTR_ERR(con->port); + if (IS_ERR(con->port)) { + ret = PTR_ERR(con->port); + goto out; + } /* Alternate modes */ ret = ucsi_register_altmodes(con, UCSI_RECIPIENT_CON); - if (ret) + if (ret) { dev_err(ucsi->dev, "con%d: failed to register alt modes\n", con->num); + goto out; + } /* Get the status */ command = UCSI_GET_CONNECTOR_STATUS | UCSI_CONNECTOR_NUMBER(con->num); - ret = ucsi_run_command(ucsi, command, &con->status, - sizeof(con->status)); + ret = ucsi_send_command(ucsi, command, &con->status, sizeof(con->status)); if (ret < 0) { dev_err(ucsi->dev, "con%d: failed to get status\n", con->num); - return 0; + ret = 0; + goto out; } + ret = 0; /* ucsi_send_command() returns length on success */ switch (UCSI_CONSTAT_PARTNER_TYPE(con->status.flags)) { case UCSI_CONSTAT_PARTNER_TYPE_UFP: @@ -983,17 +988,21 @@ static int ucsi_register_port(struct ucsi *ucsi, int index) if (con->partner) { ret = ucsi_register_altmodes(con, UCSI_RECIPIENT_SOP); - if (ret) + if (ret) { dev_err(ucsi->dev, "con%d: failed to register alternate modes\n", con->num); - else + ret = 0; + } else { ucsi_altmode_update_active(con); + } } trace_ucsi_register_port(con->num, &con->status); - return 0; +out: + mutex_unlock(&con->lock); + return ret; } /** @@ -1009,8 +1018,6 @@ static int ucsi_init(struct ucsi *ucsi) int ret; int i; - mutex_lock(&ucsi->ppm_lock); - /* Reset the PPM */ ret = ucsi_reset_ppm(ucsi); if (ret) { @@ -1021,13 +1028,13 @@ static int ucsi_init(struct ucsi *ucsi) /* Enable basic notifications */ ucsi->ntfy = UCSI_ENABLE_NTFY_CMD_COMPLETE | UCSI_ENABLE_NTFY_ERROR; command = UCSI_SET_NOTIFICATION_ENABLE | ucsi->ntfy; - ret = ucsi_run_command(ucsi, command, NULL, 0); + ret = ucsi_send_command(ucsi, command, NULL, 0); if (ret < 0) goto err_reset; /* Get PPM capabilities */ command = UCSI_GET_CAPABILITY; - ret = ucsi_run_command(ucsi, command, &ucsi->cap, sizeof(ucsi->cap)); + ret = ucsi_send_command(ucsi, command, &ucsi->cap, sizeof(ucsi->cap)); if (ret < 0) goto err_reset; @@ -1054,12 +1061,10 @@ static int ucsi_init(struct ucsi *ucsi) /* Enable all notifications */ ucsi->ntfy = UCSI_ENABLE_NTFY_ALL; command = UCSI_SET_NOTIFICATION_ENABLE | ucsi->ntfy; - ret = ucsi_run_command(ucsi, command, NULL, 0); + ret = ucsi_send_command(ucsi, command, NULL, 0); if (ret < 0) goto err_unregister; - mutex_unlock(&ucsi->ppm_lock); - return 0; err_unregister: @@ -1074,8 +1079,6 @@ err_unregister: err_reset: ucsi_reset_ppm(ucsi); err: - mutex_unlock(&ucsi->ppm_lock); - return ret; } diff --git a/drivers/usb/usbip/stub_dev.c b/drivers/usb/usbip/stub_dev.c index 2305d425e6c9..9d7d642022d1 100644 --- a/drivers/usb/usbip/stub_dev.c +++ b/drivers/usb/usbip/stub_dev.c @@ -461,6 +461,11 @@ static void stub_disconnect(struct usb_device *udev) return; } +static bool usbip_match(struct usb_device *udev) +{ + return true; +} + #ifdef CONFIG_PM /* These functions need usb_port_suspend and usb_port_resume, @@ -486,6 +491,7 @@ struct usb_device_driver stub_driver = { .name = "usbip-host", .probe = stub_probe, .disconnect = stub_disconnect, + .match = usbip_match, #ifdef CONFIG_PM .suspend = stub_suspend, .resume = stub_resume, |