Skip to content

Commit

Permalink
Merge tag 'usb-5.7-rc6' of git://git.kernel.org/pub/scm/linux/kernel/…
Browse files Browse the repository at this point in the history
…git/gregkh/usb

Pull USB fixes from Greg KH:
 "Here are a number of USB fixes for 5.7-rc6

  The "largest" in here is a bunch of raw-gadget fixes and api changes
  as the driver just showed up in -rc1 and work has been done to fix up
  some uapi issues found with the original submission, before it shows
  up in a -final release.

  Other than that, a bunch of other small USB gadget fixes, xhci fixes,
  some quirks, andother tiny fixes for reported issues.

  All of these have been in linux-next with no reported issues"

* tag 'usb-5.7-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb: (26 commits)
  USB: gadget: fix illegal array access in binding with UDC
  usb: core: hub: limit HUB_QUIRK_DISABLE_AUTOSUSPEND to USB5534B
  USB: usbfs: fix mmap dma mismatch
  usb: host: xhci-plat: keep runtime active when removing host
  usb: xhci: Fix NULL pointer dereference when enqueuing trbs from urb sg list
  usb: cdns3: gadget: make a bunch of functions static
  usb: mtu3: constify struct debugfs_reg32
  usb: gadget: udc: atmel: Make some symbols static
  usb: raw-gadget: fix null-ptr-deref when reenabling endpoints
  usb: raw-gadget: documentation updates
  usb: raw-gadget: support stalling/halting/wedging endpoints
  usb: raw-gadget: fix gadget endpoint selection
  usb: raw-gadget: improve uapi headers comments
  usb: typec: mux: intel: Fix DP_HPD_LVL bit field
  usb: raw-gadget: fix return value of ep read ioctls
  usb: dwc3: select USB_ROLE_SWITCH
  usb: gadget: legacy: fix error return code in gncm_bind()
  usb: gadget: legacy: fix error return code in cdc_bind()
  usb: gadget: legacy: fix redundant initialization warnings
  usb: gadget: tegra-xudc: Fix idle suspend/resume
  ...
  • Loading branch information
Linus Torvalds committed May 17, 2020
2 parents b48397c + 1575358 commit fb27bc0
Show file tree
Hide file tree
Showing 22 changed files with 448 additions and 123 deletions.
37 changes: 30 additions & 7 deletions Documentation/usb/raw-gadget.rst
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,8 @@ differences are:
3. Raw Gadget provides a way to select a UDC device/driver to bind to,
while GadgetFS currently binds to the first available UDC.

4. Raw Gadget uses predictable endpoint names (handles) across different
UDCs (as long as UDCs have enough endpoints of each required transfer
type).
4. Raw Gadget explicitly exposes information about endpoints addresses and
capabilities allowing a user to write UDC-agnostic gadgets.

5. Raw Gadget has ioctl-based interface instead of a filesystem-based one.

Expand All @@ -50,12 +49,36 @@ The typical usage of Raw Gadget looks like:
Raw Gadget and react to those depending on what kind of USB device
needs to be emulated.

Note, that some UDC drivers have fixed addresses assigned to endpoints, and
therefore arbitrary endpoint addresses can't be used in the descriptors.
Nevertheles, Raw Gadget provides a UDC-agnostic way to write USB gadgets.
Once a USB_RAW_EVENT_CONNECT event is received via USB_RAW_IOCTL_EVENT_FETCH,
the USB_RAW_IOCTL_EPS_INFO ioctl can be used to find out information about
endpoints that the UDC driver has. Based on that information, the user must
chose UDC endpoints that will be used for the gadget being emulated, and
properly assign addresses in endpoint descriptors.

You can find usage examples (along with a test suite) here:

https://github.com/xairy/raw-gadget

Internal details
~~~~~~~~~~~~~~~~

Currently every endpoint read/write ioctl submits a USB request and waits until
its completion. This is the desired mode for coverage-guided fuzzing (as we'd
like all USB request processing happen during the lifetime of a syscall),
and must be kept in the implementation. (This might be slow for real world
applications, thus the O_NONBLOCK improvement suggestion below.)

Potential future improvements
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

- Implement ioctl's for setting/clearing halt status on endpoints.

- Reporting more events (suspend, resume, etc.) through
USB_RAW_IOCTL_EVENT_FETCH.
- Report more events (suspend, resume, etc.) through USB_RAW_IOCTL_EVENT_FETCH.

- Support O_NONBLOCK I/O.

- Support USB 3 features (accept SS endpoint companion descriptor when
enabling endpoints; allow providing stream_id for bulk transfers).

- Support ISO transfer features (expose frame_number for completed requests).
22 changes: 11 additions & 11 deletions drivers/usb/cdns3/gadget.c
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ static int cdns3_ep_run_stream_transfer(struct cdns3_endpoint *priv_ep,
* @ptr: address of device controller register to be read and changed
* @mask: bits requested to clar
*/
void cdns3_clear_register_bit(void __iomem *ptr, u32 mask)
static void cdns3_clear_register_bit(void __iomem *ptr, u32 mask)
{
mask = readl(ptr) & ~mask;
writel(mask, ptr);
Expand Down Expand Up @@ -137,7 +137,7 @@ struct usb_request *cdns3_next_request(struct list_head *list)
*
* Returns buffer or NULL if no buffers in list
*/
struct cdns3_aligned_buf *cdns3_next_align_buf(struct list_head *list)
static struct cdns3_aligned_buf *cdns3_next_align_buf(struct list_head *list)
{
return list_first_entry_or_null(list, struct cdns3_aligned_buf, list);
}
Expand All @@ -148,7 +148,7 @@ struct cdns3_aligned_buf *cdns3_next_align_buf(struct list_head *list)
*
* Returns request or NULL if no requests in list
*/
struct cdns3_request *cdns3_next_priv_request(struct list_head *list)
static struct cdns3_request *cdns3_next_priv_request(struct list_head *list)
{
return list_first_entry_or_null(list, struct cdns3_request, list);
}
Expand Down Expand Up @@ -190,7 +190,7 @@ dma_addr_t cdns3_trb_virt_to_dma(struct cdns3_endpoint *priv_ep,
return priv_ep->trb_pool_dma + offset;
}

int cdns3_ring_size(struct cdns3_endpoint *priv_ep)
static int cdns3_ring_size(struct cdns3_endpoint *priv_ep)
{
switch (priv_ep->type) {
case USB_ENDPOINT_XFER_ISOC:
Expand Down Expand Up @@ -345,7 +345,7 @@ static void cdns3_ep_inc_deq(struct cdns3_endpoint *priv_ep)
cdns3_ep_inc_trb(&priv_ep->dequeue, &priv_ep->ccs, priv_ep->num_trbs);
}

void cdns3_move_deq_to_next_trb(struct cdns3_request *priv_req)
static void cdns3_move_deq_to_next_trb(struct cdns3_request *priv_req)
{
struct cdns3_endpoint *priv_ep = priv_req->priv_ep;
int current_trb = priv_req->start_trb;
Expand Down Expand Up @@ -511,7 +511,7 @@ static void cdns3_wa2_descmiss_copy_data(struct cdns3_endpoint *priv_ep,
}
}

struct usb_request *cdns3_wa2_gadget_giveback(struct cdns3_device *priv_dev,
static struct usb_request *cdns3_wa2_gadget_giveback(struct cdns3_device *priv_dev,
struct cdns3_endpoint *priv_ep,
struct cdns3_request *priv_req)
{
Expand Down Expand Up @@ -551,7 +551,7 @@ struct usb_request *cdns3_wa2_gadget_giveback(struct cdns3_device *priv_dev,
return &priv_req->request;
}

int cdns3_wa2_gadget_ep_queue(struct cdns3_device *priv_dev,
static int cdns3_wa2_gadget_ep_queue(struct cdns3_device *priv_dev,
struct cdns3_endpoint *priv_ep,
struct cdns3_request *priv_req)
{
Expand Down Expand Up @@ -836,7 +836,7 @@ void cdns3_gadget_giveback(struct cdns3_endpoint *priv_ep,
cdns3_gadget_ep_free_request(&priv_ep->endpoint, request);
}

void cdns3_wa1_restore_cycle_bit(struct cdns3_endpoint *priv_ep)
static void cdns3_wa1_restore_cycle_bit(struct cdns3_endpoint *priv_ep)
{
/* Work around for stale data address in TRB*/
if (priv_ep->wa1_set) {
Expand Down Expand Up @@ -1904,7 +1904,7 @@ static int cdns3_ep_onchip_buffer_reserve(struct cdns3_device *priv_dev,
return 0;
}

void cdns3_stream_ep_reconfig(struct cdns3_device *priv_dev,
static void cdns3_stream_ep_reconfig(struct cdns3_device *priv_dev,
struct cdns3_endpoint *priv_ep)
{
if (!priv_ep->use_streams || priv_dev->gadget.speed < USB_SPEED_SUPER)
Expand All @@ -1925,7 +1925,7 @@ void cdns3_stream_ep_reconfig(struct cdns3_device *priv_dev,
EP_CFG_TDL_CHK | EP_CFG_SID_CHK);
}

void cdns3_configure_dmult(struct cdns3_device *priv_dev,
static void cdns3_configure_dmult(struct cdns3_device *priv_dev,
struct cdns3_endpoint *priv_ep)
{
struct cdns3_usb_regs __iomem *regs = priv_dev->regs;
Expand Down Expand Up @@ -2548,7 +2548,7 @@ int cdns3_gadget_ep_dequeue(struct usb_ep *ep,
link_trb = priv_req->trb;

/* Update ring only if removed request is on pending_req_list list */
if (req_on_hw_ring) {
if (req_on_hw_ring && link_trb) {
link_trb->buffer = TRB_BUFFER(priv_ep->trb_pool_dma +
((priv_req->end_trb + 1) * TRB_SIZE));
link_trb->control = (link_trb->control & TRB_CYCLE) |
Expand Down
16 changes: 13 additions & 3 deletions drivers/usb/core/devio.c
Original file line number Diff line number Diff line change
Expand Up @@ -251,9 +251,19 @@ static int usbdev_mmap(struct file *file, struct vm_area_struct *vma)
usbm->vma_use_count = 1;
INIT_LIST_HEAD(&usbm->memlist);

if (dma_mmap_coherent(hcd->self.sysdev, vma, mem, dma_handle, size)) {
dec_usb_memory_use_count(usbm, &usbm->vma_use_count);
return -EAGAIN;
if (hcd->localmem_pool || !hcd_uses_dma(hcd)) {
if (remap_pfn_range(vma, vma->vm_start,
virt_to_phys(usbm->mem) >> PAGE_SHIFT,
size, vma->vm_page_prot) < 0) {
dec_usb_memory_use_count(usbm, &usbm->vma_use_count);
return -EAGAIN;
}
} else {
if (dma_mmap_coherent(hcd->self.sysdev, vma, mem, dma_handle,
size)) {
dec_usb_memory_use_count(usbm, &usbm->vma_use_count);
return -EAGAIN;
}
}

vma->vm_flags |= VM_IO;
Expand Down
6 changes: 5 additions & 1 deletion drivers/usb/core/hub.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@

#define USB_VENDOR_GENESYS_LOGIC 0x05e3
#define USB_VENDOR_SMSC 0x0424
#define USB_PRODUCT_USB5534B 0x5534
#define HUB_QUIRK_CHECK_PORT_AUTOSUSPEND 0x01
#define HUB_QUIRK_DISABLE_AUTOSUSPEND 0x02

Expand Down Expand Up @@ -5621,8 +5622,11 @@ static void hub_event(struct work_struct *work)
}

static const struct usb_device_id hub_id_table[] = {
{ .match_flags = USB_DEVICE_ID_MATCH_VENDOR | USB_DEVICE_ID_MATCH_INT_CLASS,
{ .match_flags = USB_DEVICE_ID_MATCH_VENDOR
| USB_DEVICE_ID_MATCH_PRODUCT
| USB_DEVICE_ID_MATCH_INT_CLASS,
.idVendor = USB_VENDOR_SMSC,
.idProduct = USB_PRODUCT_USB5534B,
.bInterfaceClass = USB_CLASS_HUB,
.driver_info = HUB_QUIRK_DISABLE_AUTOSUSPEND},
{ .match_flags = USB_DEVICE_ID_MATCH_VENDOR
Expand Down
1 change: 1 addition & 0 deletions drivers/usb/dwc3/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ config USB_DWC3
tristate "DesignWare USB3 DRD Core Support"
depends on (USB || USB_GADGET) && HAS_DMA
select USB_XHCI_PLATFORM if USB_XHCI_HCD
select USB_ROLE_SWITCH if USB_DWC3_DUAL_ROLE
help
Say Y or M here if your system has a Dual Role SuperSpeed
USB controller based on the DesignWare USB3 IP Core.
Expand Down
1 change: 1 addition & 0 deletions drivers/usb/dwc3/dwc3-pci.c
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ static const struct property_entry dwc3_pci_intel_properties[] = {

static const struct property_entry dwc3_pci_mrfld_properties[] = {
PROPERTY_ENTRY_STRING("dr_mode", "otg"),
PROPERTY_ENTRY_STRING("linux,extcon-name", "mrfld_bcove_pwrsrc"),
PROPERTY_ENTRY_BOOL("linux,sysdev_is_parent"),
{}
};
Expand Down
3 changes: 0 additions & 3 deletions drivers/usb/dwc3/gadget.c
Original file line number Diff line number Diff line change
Expand Up @@ -2483,9 +2483,6 @@ static int dwc3_gadget_ep_reclaim_trb_sg(struct dwc3_ep *dep,
for_each_sg(sg, s, pending, i) {
trb = &dep->trb_pool[dep->trb_dequeue];

if (trb->ctrl & DWC3_TRB_CTRL_HWO)
break;

req->sg = sg_next(s);
req->num_pending_sgs--;

Expand Down
3 changes: 3 additions & 0 deletions drivers/usb/gadget/configfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,9 @@ static ssize_t gadget_dev_desc_UDC_store(struct config_item *item,
char *name;
int ret;

if (strlen(page) < len)
return -EOVERFLOW;

name = kstrdup(page, GFP_KERNEL);
if (!name)
return -ENOMEM;
Expand Down
4 changes: 3 additions & 1 deletion drivers/usb/gadget/legacy/audio.c
Original file line number Diff line number Diff line change
Expand Up @@ -300,8 +300,10 @@ static int audio_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;
}
usb_otg_descriptor_init(cdev->gadget, usb_desc);
otg_desc[0] = usb_desc;
otg_desc[1] = NULL;
Expand Down
4 changes: 3 additions & 1 deletion drivers/usb/gadget/legacy/cdc2.c
Original file line number Diff line number Diff line change
Expand Up @@ -179,8 +179,10 @@ static int cdc_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 fail1;
}
usb_otg_descriptor_init(gadget, usb_desc);
otg_desc[0] = usb_desc;
otg_desc[1] = NULL;
Expand Down
3 changes: 1 addition & 2 deletions drivers/usb/gadget/legacy/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -1361,7 +1361,6 @@ gadgetfs_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)

req->buf = dev->rbuf;
req->context = NULL;
value = -EOPNOTSUPP;
switch (ctrl->bRequest) {

case USB_REQ_GET_DESCRIPTOR:
Expand Down Expand Up @@ -1784,7 +1783,7 @@ static ssize_t
dev_config (struct file *fd, const char __user *buf, size_t len, loff_t *ptr)
{
struct dev_data *dev = fd->private_data;
ssize_t value = len, length = len;
ssize_t value, length = len;
unsigned total;
u32 tag;
char *kbuf;
Expand Down
4 changes: 3 additions & 1 deletion drivers/usb/gadget/legacy/ncm.c
Original file line number Diff line number Diff line change
Expand Up @@ -156,8 +156,10 @@ static int gncm_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;
}
usb_otg_descriptor_init(gadget, usb_desc);
otg_desc[0] = usb_desc;
otg_desc[1] = NULL;
Expand Down
Loading

0 comments on commit fb27bc0

Please sign in to comment.