Skip to content

Commit

Permalink
Merge tag 'usb-4.18-rc3' 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 is a number of USB gadget and other driver fixes for 4.18-rc3.

  There's a bunch of them here, most of them being gadget driver and
  xhci host controller fixes for reported issues (as normal), but there
  are also some new device ids, and some fixes for the typec code.

  There is an acpi core patch in here that was acked by the acpi
  maintainer as it is needed for the typec fixes in order to properly
  solve a problem in that driver.

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

* tag 'usb-4.18-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb: (33 commits)
  usb: chipidea: host: fix disconnection detect issue
  usb: typec: tcpm: fix logbuffer index is wrong if _tcpm_log is re-entered
  typec: tcpm: Fix a msecs vs jiffies bug
  NFC: pn533: Fix wrong GFP flag usage
  usb: cdc_acm: Add quirk for Uniden UBC125 scanner
  staging/typec: fix tcpci_rt1711h build errors
  usb: typec: ucsi: Fix for incorrect status data issue
  usb: typec: ucsi: acpi: Workaround for cache mode issue
  acpi: Add helper for deactivating memory region
  usb: xhci: increase CRS timeout value
  usb: xhci: tegra: fix runtime PM error handling
  usb: xhci: remove the code build warning
  xhci: Fix kernel oops in trace_xhci_free_virt_device
  xhci: Fix perceived dead host due to runtime suspend race with event handler
  dwc2: gadget: Fix ISOC IN DDMA PID bitfield value calculation
  usb: gadget: dwc2: fix memory leak in gadget_init()
  usb: gadget: composite: fix delayed_status race condition when set_interface
  usb: dwc2: fix isoc split in transfer with no data
  usb: dwc2: alloc dma aligned buffer for isoc split in
  usb: dwc2: fix the incorrect bitmaps for the ports of multi_tt hub
  ...
  • Loading branch information
torvalds committed Jul 1, 2018
2 parents c350d6d + 226e2d2 commit c2aee37
Show file tree
Hide file tree
Showing 28 changed files with 373 additions and 66 deletions.
2 changes: 1 addition & 1 deletion Documentation/usb/gadget_configfs.txt
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,7 @@ $ rm configs/<config name>.<number>/<function>
where <config name>.<number> specify the configuration and <function> is
a symlink to a function being removed from the configuration, e.g.:

$ rm configfs/c.1/ncm.usb0
$ rm configs/c.1/ncm.usb0

...
...
Expand Down
72 changes: 72 additions & 0 deletions drivers/acpi/osl.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@
#include <linux/uaccess.h>
#include <linux/io-64-nonatomic-lo-hi.h>

#include "acpica/accommon.h"
#include "acpica/acnamesp.h"
#include "internal.h"

#define _COMPONENT ACPI_OS_SERVICES
Expand Down Expand Up @@ -1490,6 +1492,76 @@ int acpi_check_region(resource_size_t start, resource_size_t n,
}
EXPORT_SYMBOL(acpi_check_region);

static acpi_status acpi_deactivate_mem_region(acpi_handle handle, u32 level,
void *_res, void **return_value)
{
struct acpi_mem_space_context **mem_ctx;
union acpi_operand_object *handler_obj;
union acpi_operand_object *region_obj2;
union acpi_operand_object *region_obj;
struct resource *res = _res;
acpi_status status;

region_obj = acpi_ns_get_attached_object(handle);
if (!region_obj)
return AE_OK;

handler_obj = region_obj->region.handler;
if (!handler_obj)
return AE_OK;

if (region_obj->region.space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY)
return AE_OK;

if (!(region_obj->region.flags & AOPOBJ_SETUP_COMPLETE))
return AE_OK;

region_obj2 = acpi_ns_get_secondary_object(region_obj);
if (!region_obj2)
return AE_OK;

mem_ctx = (void *)&region_obj2->extra.region_context;

if (!(mem_ctx[0]->address >= res->start &&
mem_ctx[0]->address < res->end))
return AE_OK;

status = handler_obj->address_space.setup(region_obj,
ACPI_REGION_DEACTIVATE,
NULL, (void **)mem_ctx);
if (ACPI_SUCCESS(status))
region_obj->region.flags &= ~(AOPOBJ_SETUP_COMPLETE);

return status;
}

/**
* acpi_release_memory - Release any mappings done to a memory region
* @handle: Handle to namespace node
* @res: Memory resource
* @level: A level that terminates the search
*
* Walks through @handle and unmaps all SystemMemory Operation Regions that
* overlap with @res and that have already been activated (mapped).
*
* This is a helper that allows drivers to place special requirements on memory
* region that may overlap with operation regions, primarily allowing them to
* safely map the region as non-cached memory.
*
* The unmapped Operation Regions will be automatically remapped next time they
* are called, so the drivers do not need to do anything else.
*/
acpi_status acpi_release_memory(acpi_handle handle, struct resource *res,
u32 level)
{
if (!(res->flags & IORESOURCE_MEM))
return AE_TYPE;

return acpi_walk_namespace(ACPI_TYPE_REGION, handle, level,
acpi_deactivate_mem_region, NULL, res, NULL);
}
EXPORT_SYMBOL_GPL(acpi_release_memory);

/*
* Let drivers know whether the resource checks are effective
*/
Expand Down
4 changes: 2 additions & 2 deletions drivers/nfc/pn533/usb.c
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ static void pn533_recv_response(struct urb *urb)
struct sk_buff *skb = NULL;

if (!urb->status) {
skb = alloc_skb(urb->actual_length, GFP_KERNEL);
skb = alloc_skb(urb->actual_length, GFP_ATOMIC);
if (!skb) {
nfc_err(&phy->udev->dev, "failed to alloc memory\n");
} else {
Expand Down Expand Up @@ -186,7 +186,7 @@ static int pn533_usb_send_frame(struct pn533 *dev,

if (dev->protocol_type == PN533_PROTO_REQ_RESP) {
/* request for response for sent packet directly */
rc = pn533_submit_urb_for_response(phy, GFP_ATOMIC);
rc = pn533_submit_urb_for_response(phy, GFP_KERNEL);
if (rc)
goto error;
} else if (dev->protocol_type == PN533_PROTO_REQ_ACK_RESP) {
Expand Down
1 change: 1 addition & 0 deletions drivers/staging/typec/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ config TYPEC_TCPCI

config TYPEC_RT1711H
tristate "Richtek RT1711H Type-C chip driver"
depends on I2C
select TYPEC_TCPCI
help
Richtek RT1711H Type-C chip driver that works with
Expand Down
5 changes: 4 additions & 1 deletion drivers/usb/chipidea/host.c
Original file line number Diff line number Diff line change
Expand Up @@ -124,8 +124,11 @@ static int host_start(struct ci_hdrc *ci)

hcd->power_budget = ci->platdata->power_budget;
hcd->tpl_support = ci->platdata->tpl_support;
if (ci->phy || ci->usb_phy)
if (ci->phy || ci->usb_phy) {
hcd->skip_phy_initialization = 1;
if (ci->usb_phy)
hcd->usb_phy = ci->usb_phy;
}

ehci = hcd_to_ehci(hcd);
ehci->caps = ci->hw_bank.cap;
Expand Down
3 changes: 3 additions & 0 deletions drivers/usb/class/cdc-acm.c
Original file line number Diff line number Diff line change
Expand Up @@ -1758,6 +1758,9 @@ static const struct usb_device_id acm_ids[] = {
{ USB_DEVICE(0x11ca, 0x0201), /* VeriFone Mx870 Gadget Serial */
.driver_info = SINGLE_RX_URB,
},
{ USB_DEVICE(0x1965, 0x0018), /* Uniden UBC125XLT */
.driver_info = NO_UNION_NORMAL, /* has no union descriptor */
},
{ USB_DEVICE(0x22b8, 0x7000), /* Motorola Q Phone */
.driver_info = NO_UNION_NORMAL, /* has no union descriptor */
},
Expand Down
3 changes: 3 additions & 0 deletions drivers/usb/dwc2/core.h
Original file line number Diff line number Diff line change
Expand Up @@ -1004,6 +1004,7 @@ struct dwc2_hregs_backup {
* @frame_list_sz: Frame list size
* @desc_gen_cache: Kmem cache for generic descriptors
* @desc_hsisoc_cache: Kmem cache for hs isochronous descriptors
* @unaligned_cache: Kmem cache for DMA mode to handle non-aligned buf
*
* These are for peripheral mode:
*
Expand Down Expand Up @@ -1177,6 +1178,8 @@ struct dwc2_hsotg {
u32 frame_list_sz;
struct kmem_cache *desc_gen_cache;
struct kmem_cache *desc_hsisoc_cache;
struct kmem_cache *unaligned_cache;
#define DWC2_KMEM_UNALIGNED_BUF_SIZE 1024

#endif /* CONFIG_USB_DWC2_HOST || CONFIG_USB_DWC2_DUAL_ROLE */

Expand Down
20 changes: 12 additions & 8 deletions drivers/usb/dwc2/gadget.c
Original file line number Diff line number Diff line change
Expand Up @@ -812,6 +812,7 @@ static int dwc2_gadget_fill_isoc_desc(struct dwc2_hsotg_ep *hs_ep,
u32 index;
u32 maxsize = 0;
u32 mask = 0;
u8 pid = 0;

maxsize = dwc2_gadget_get_desc_params(hs_ep, &mask);

Expand Down Expand Up @@ -840,7 +841,11 @@ static int dwc2_gadget_fill_isoc_desc(struct dwc2_hsotg_ep *hs_ep,
((len << DEV_DMA_NBYTES_SHIFT) & mask));

if (hs_ep->dir_in) {
desc->status |= ((hs_ep->mc << DEV_DMA_ISOC_PID_SHIFT) &
if (len)
pid = DIV_ROUND_UP(len, hs_ep->ep.maxpacket);
else
pid = 1;
desc->status |= ((pid << DEV_DMA_ISOC_PID_SHIFT) &
DEV_DMA_ISOC_PID_MASK) |
((len % hs_ep->ep.maxpacket) ?
DEV_DMA_SHORT : 0) |
Expand Down Expand Up @@ -884,6 +889,7 @@ static void dwc2_gadget_start_isoc_ddma(struct dwc2_hsotg_ep *hs_ep)
struct dwc2_dma_desc *desc;

if (list_empty(&hs_ep->queue)) {
hs_ep->target_frame = TARGET_FRAME_INITIAL;
dev_dbg(hsotg->dev, "%s: No requests in queue\n", __func__);
return;
}
Expand Down Expand Up @@ -2755,8 +2761,6 @@ static void dwc2_gadget_handle_out_token_ep_disabled(struct dwc2_hsotg_ep *ep)
*/
tmp = dwc2_hsotg_read_frameno(hsotg);

dwc2_hsotg_complete_request(hsotg, ep, get_ep_head(ep), 0);

if (using_desc_dma(hsotg)) {
if (ep->target_frame == TARGET_FRAME_INITIAL) {
/* Start first ISO Out */
Expand Down Expand Up @@ -2817,9 +2821,6 @@ static void dwc2_gadget_handle_nak(struct dwc2_hsotg_ep *hs_ep)

tmp = dwc2_hsotg_read_frameno(hsotg);
if (using_desc_dma(hsotg)) {
dwc2_hsotg_complete_request(hsotg, hs_ep,
get_ep_head(hs_ep), 0);

hs_ep->target_frame = tmp;
dwc2_gadget_incr_frame_num(hs_ep);
dwc2_gadget_start_isoc_ddma(hs_ep);
Expand Down Expand Up @@ -4739,9 +4740,11 @@ int dwc2_gadget_init(struct dwc2_hsotg *hsotg)
}

ret = usb_add_gadget_udc(dev, &hsotg->gadget);
if (ret)
if (ret) {
dwc2_hsotg_ep_free_request(&hsotg->eps_out[0]->ep,
hsotg->ctrl_req);
return ret;

}
dwc2_hsotg_dump(hsotg);

return 0;
Expand All @@ -4755,6 +4758,7 @@ int dwc2_gadget_init(struct dwc2_hsotg *hsotg)
int dwc2_hsotg_remove(struct dwc2_hsotg *hsotg)
{
usb_del_gadget_udc(&hsotg->gadget);
dwc2_hsotg_ep_free_request(&hsotg->eps_out[0]->ep, hsotg->ctrl_req);

return 0;
}
Expand Down
93 changes: 87 additions & 6 deletions drivers/usb/dwc2/hcd.c
Original file line number Diff line number Diff line change
Expand Up @@ -1567,11 +1567,20 @@ static void dwc2_hc_start_transfer(struct dwc2_hsotg *hsotg,
}

if (hsotg->params.host_dma) {
dwc2_writel((u32)chan->xfer_dma,
hsotg->regs + HCDMA(chan->hc_num));
dma_addr_t dma_addr;

if (chan->align_buf) {
if (dbg_hc(chan))
dev_vdbg(hsotg->dev, "align_buf\n");
dma_addr = chan->align_buf;
} else {
dma_addr = chan->xfer_dma;
}
dwc2_writel((u32)dma_addr, hsotg->regs + HCDMA(chan->hc_num));

if (dbg_hc(chan))
dev_vdbg(hsotg->dev, "Wrote %08lx to HCDMA(%d)\n",
(unsigned long)chan->xfer_dma, chan->hc_num);
(unsigned long)dma_addr, chan->hc_num);
}

/* Start the split */
Expand Down Expand Up @@ -2625,6 +2634,35 @@ static void dwc2_hc_init_xfer(struct dwc2_hsotg *hsotg,
}
}

static int dwc2_alloc_split_dma_aligned_buf(struct dwc2_hsotg *hsotg,
struct dwc2_qh *qh,
struct dwc2_host_chan *chan)
{
if (!hsotg->unaligned_cache ||
chan->max_packet > DWC2_KMEM_UNALIGNED_BUF_SIZE)
return -ENOMEM;

if (!qh->dw_align_buf) {
qh->dw_align_buf = kmem_cache_alloc(hsotg->unaligned_cache,
GFP_ATOMIC | GFP_DMA);
if (!qh->dw_align_buf)
return -ENOMEM;
}

qh->dw_align_buf_dma = dma_map_single(hsotg->dev, qh->dw_align_buf,
DWC2_KMEM_UNALIGNED_BUF_SIZE,
DMA_FROM_DEVICE);

if (dma_mapping_error(hsotg->dev, qh->dw_align_buf_dma)) {
dev_err(hsotg->dev, "can't map align_buf\n");
chan->align_buf = 0;
return -EINVAL;
}

chan->align_buf = qh->dw_align_buf_dma;
return 0;
}

#define DWC2_USB_DMA_ALIGN 4

struct dma_aligned_buffer {
Expand Down Expand Up @@ -2802,6 +2840,32 @@ static int dwc2_assign_and_init_hc(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh)
/* Set the transfer attributes */
dwc2_hc_init_xfer(hsotg, chan, qtd);

/* For non-dword aligned buffers */
if (hsotg->params.host_dma && qh->do_split &&
chan->ep_is_in && (chan->xfer_dma & 0x3)) {
dev_vdbg(hsotg->dev, "Non-aligned buffer\n");
if (dwc2_alloc_split_dma_aligned_buf(hsotg, qh, chan)) {
dev_err(hsotg->dev,
"Failed to allocate memory to handle non-aligned buffer\n");
/* Add channel back to free list */
chan->align_buf = 0;
chan->multi_count = 0;
list_add_tail(&chan->hc_list_entry,
&hsotg->free_hc_list);
qtd->in_process = 0;
qh->channel = NULL;
return -ENOMEM;
}
} else {
/*
* We assume that DMA is always aligned in non-split
* case or split out case. Warn if not.
*/
WARN_ON_ONCE(hsotg->params.host_dma &&
(chan->xfer_dma & 0x3));
chan->align_buf = 0;
}

if (chan->ep_type == USB_ENDPOINT_XFER_INT ||
chan->ep_type == USB_ENDPOINT_XFER_ISOC)
/*
Expand Down Expand Up @@ -5246,6 +5310,19 @@ int dwc2_hcd_init(struct dwc2_hsotg *hsotg)
}
}

if (hsotg->params.host_dma) {
/*
* Create kmem caches to handle non-aligned buffer
* in Buffer DMA mode.
*/
hsotg->unaligned_cache = kmem_cache_create("dwc2-unaligned-dma",
DWC2_KMEM_UNALIGNED_BUF_SIZE, 4,
SLAB_CACHE_DMA, NULL);
if (!hsotg->unaligned_cache)
dev_err(hsotg->dev,
"unable to create dwc2 unaligned cache\n");
}

hsotg->otg_port = 1;
hsotg->frame_list = NULL;
hsotg->frame_list_dma = 0;
Expand Down Expand Up @@ -5280,8 +5357,9 @@ int dwc2_hcd_init(struct dwc2_hsotg *hsotg)
return 0;

error4:
kmem_cache_destroy(hsotg->desc_gen_cache);
kmem_cache_destroy(hsotg->unaligned_cache);
kmem_cache_destroy(hsotg->desc_hsisoc_cache);
kmem_cache_destroy(hsotg->desc_gen_cache);
error3:
dwc2_hcd_release(hsotg);
error2:
Expand Down Expand Up @@ -5322,8 +5400,9 @@ void dwc2_hcd_remove(struct dwc2_hsotg *hsotg)
usb_remove_hcd(hcd);
hsotg->priv = NULL;

kmem_cache_destroy(hsotg->desc_gen_cache);
kmem_cache_destroy(hsotg->unaligned_cache);
kmem_cache_destroy(hsotg->desc_hsisoc_cache);
kmem_cache_destroy(hsotg->desc_gen_cache);

dwc2_hcd_release(hsotg);
usb_put_hcd(hcd);
Expand Down Expand Up @@ -5435,7 +5514,7 @@ int dwc2_host_enter_hibernation(struct dwc2_hsotg *hsotg)
dwc2_writel(hprt0, hsotg->regs + HPRT0);

/* Wait for the HPRT0.PrtSusp register field to be set */
if (dwc2_hsotg_wait_bit_set(hsotg, HPRT0, HPRT0_SUSP, 300))
if (dwc2_hsotg_wait_bit_set(hsotg, HPRT0, HPRT0_SUSP, 3000))
dev_warn(hsotg->dev, "Suspend wasn't generated\n");

/*
Expand Down Expand Up @@ -5616,6 +5695,8 @@ int dwc2_host_exit_hibernation(struct dwc2_hsotg *hsotg, int rem_wakeup,
return ret;
}

dwc2_hcd_rem_wakeup(hsotg);

hsotg->hibernated = 0;
hsotg->bus_suspended = 0;
hsotg->lx_state = DWC2_L0;
Expand Down
Loading

0 comments on commit c2aee37

Please sign in to comment.