mirror of
https://github.com/torvalds/linux.git
synced 2024-11-10 06:01:57 +00:00
USB fixes for 5.4-rc6
The USB sub-maintainers woke up this past week and sent a bunch of tiny fixes. Here are a lot of small patches that that resolve a bunch of reported issues in the USB core, drivers, serial drivers, gadget drivers, and of course, xhci :) All of these have been in linux-next with no reported issues. Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> -----BEGIN PGP SIGNATURE----- iG0EABECAC0WIQT0tgzFv3jCIUoxPcsxR9QN2y37KQUCXb7SXg8cZ3JlZ0Brcm9h aC5jb20ACgkQMUfUDdst+ylCyQCgleuRSWwpH3QVRvCXpT/kxqXPkEQAn0ct2ZOi oInjMIDpRJ+EuEithFOI =P61y -----END PGP SIGNATURE----- Merge tag 'usb-5.4-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb Pull USB fixes from Greg KH: "The USB sub-maintainers woke up this past week and sent a bunch of tiny fixes. Here are a lot of small patches that that resolve a bunch of reported issues in the USB core, drivers, serial drivers, gadget drivers, and of course, xhci :) All of these have been in linux-next with no reported issues" * tag 'usb-5.4-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb: (31 commits) usb: dwc3: gadget: fix race when disabling ep with cancelled xfers usb: cdns3: gadget: Fix g_audio use case when connected to Super-Speed host usb: cdns3: gadget: reset EP_CLAIMED flag while unloading USB: serial: whiteheat: fix line-speed endianness USB: serial: whiteheat: fix potential slab corruption USB: gadget: Reject endpoints with 0 maxpacket value UAS: Revert commit3ae62a4209
("UAS: fix alignment of scatter/gather segments") usb-storage: Revert commit747668dbc0
("usb-storage: Set virt_boundary_mask to avoid SG overflows") usbip: Fix free of unallocated memory in vhci tx usbip: tools: Fix read_usb_vudc_device() error path handling usb: xhci: fix __le32/__le64 accessors in debugfs code usb: xhci: fix Immediate Data Transfer endianness xhci: Fix use-after-free regression in xhci clear hub TT implementation USB: ldusb: fix control-message timeout USB: ldusb: use unsigned size format specifiers USB: ldusb: fix ring-buffer locking USB: Skip endpoints with 0 maxpacket length usb: cdns3: gadget: Don't manage pullups usb: dwc3: remove the call trace of USBx_GFLADJ usb: gadget: configfs: fix concurrent issue between composite APIs ...
This commit is contained in:
commit
3a69c9e522
@ -2329,8 +2329,6 @@ static void cdns3_gadget_config(struct cdns3_device *priv_dev)
|
||||
writel(USB_CONF_CLK2OFFDS | USB_CONF_L1DS, ®s->usb_conf);
|
||||
|
||||
cdns3_configure_dmult(priv_dev, NULL);
|
||||
|
||||
cdns3_gadget_pullup(&priv_dev->gadget, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2345,9 +2343,35 @@ static int cdns3_gadget_udc_start(struct usb_gadget *gadget,
|
||||
{
|
||||
struct cdns3_device *priv_dev = gadget_to_cdns3_device(gadget);
|
||||
unsigned long flags;
|
||||
enum usb_device_speed max_speed = driver->max_speed;
|
||||
|
||||
spin_lock_irqsave(&priv_dev->lock, flags);
|
||||
priv_dev->gadget_driver = driver;
|
||||
|
||||
/* limit speed if necessary */
|
||||
max_speed = min(driver->max_speed, gadget->max_speed);
|
||||
|
||||
switch (max_speed) {
|
||||
case USB_SPEED_FULL:
|
||||
writel(USB_CONF_SFORCE_FS, &priv_dev->regs->usb_conf);
|
||||
writel(USB_CONF_USB3DIS, &priv_dev->regs->usb_conf);
|
||||
break;
|
||||
case USB_SPEED_HIGH:
|
||||
writel(USB_CONF_USB3DIS, &priv_dev->regs->usb_conf);
|
||||
break;
|
||||
case USB_SPEED_SUPER:
|
||||
break;
|
||||
default:
|
||||
dev_err(priv_dev->dev,
|
||||
"invalid maximum_speed parameter %d\n",
|
||||
max_speed);
|
||||
/* fall through */
|
||||
case USB_SPEED_UNKNOWN:
|
||||
/* default to superspeed */
|
||||
max_speed = USB_SPEED_SUPER;
|
||||
break;
|
||||
}
|
||||
|
||||
cdns3_gadget_config(priv_dev);
|
||||
spin_unlock_irqrestore(&priv_dev->lock, flags);
|
||||
return 0;
|
||||
@ -2381,6 +2405,8 @@ static int cdns3_gadget_udc_stop(struct usb_gadget *gadget)
|
||||
writel(EP_CMD_EPRST, &priv_dev->regs->ep_cmd);
|
||||
readl_poll_timeout_atomic(&priv_dev->regs->ep_cmd, val,
|
||||
!(val & EP_CMD_EPRST), 1, 100);
|
||||
|
||||
priv_ep->flags &= ~EP_CLAIMED;
|
||||
}
|
||||
|
||||
/* disable interrupt for device */
|
||||
@ -2575,12 +2601,7 @@ static int cdns3_gadget_start(struct cdns3 *cdns)
|
||||
/* Check the maximum_speed parameter */
|
||||
switch (max_speed) {
|
||||
case USB_SPEED_FULL:
|
||||
writel(USB_CONF_SFORCE_FS, &priv_dev->regs->usb_conf);
|
||||
writel(USB_CONF_USB3DIS, &priv_dev->regs->usb_conf);
|
||||
break;
|
||||
case USB_SPEED_HIGH:
|
||||
writel(USB_CONF_USB3DIS, &priv_dev->regs->usb_conf);
|
||||
break;
|
||||
case USB_SPEED_SUPER:
|
||||
break;
|
||||
default:
|
||||
@ -2713,8 +2734,6 @@ static int cdns3_gadget_suspend(struct cdns3 *cdns, bool do_wakeup)
|
||||
/* disable interrupt for device */
|
||||
writel(0, &priv_dev->regs->usb_ien);
|
||||
|
||||
cdns3_gadget_pullup(&priv_dev->gadget, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -12,7 +12,6 @@
|
||||
#ifdef CONFIG_USB_CDNS3_HOST
|
||||
|
||||
int cdns3_host_init(struct cdns3 *cdns);
|
||||
void cdns3_host_exit(struct cdns3 *cdns);
|
||||
|
||||
#else
|
||||
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include <linux/platform_device.h>
|
||||
#include "core.h"
|
||||
#include "drd.h"
|
||||
#include "host-export.h"
|
||||
|
||||
static int __cdns3_host_init(struct cdns3 *cdns)
|
||||
{
|
||||
|
@ -348,6 +348,11 @@ static int usb_parse_endpoint(struct device *ddev, int cfgno, int inum,
|
||||
|
||||
/* Validate the wMaxPacketSize field */
|
||||
maxp = usb_endpoint_maxp(&endpoint->desc);
|
||||
if (maxp == 0) {
|
||||
dev_warn(ddev, "config %d interface %d altsetting %d endpoint 0x%X has wMaxPacketSize 0, skipping\n",
|
||||
cfgno, inum, asnum, d->bEndpointAddress);
|
||||
goto skip_to_next_endpoint_or_interface_descriptor;
|
||||
}
|
||||
|
||||
/* Find the highest legal maxpacket size for this endpoint */
|
||||
i = 0; /* additional transactions per microframe */
|
||||
|
@ -102,6 +102,7 @@ config USB_DWC3_MESON_G12A
|
||||
depends on ARCH_MESON || COMPILE_TEST
|
||||
default USB_DWC3
|
||||
select USB_ROLE_SWITCH
|
||||
select REGMAP_MMIO
|
||||
help
|
||||
Support USB2/3 functionality in Amlogic G12A platforms.
|
||||
Say 'Y' or 'M' if you have one such device.
|
||||
|
@ -312,8 +312,7 @@ static void dwc3_frame_length_adjustment(struct dwc3 *dwc)
|
||||
|
||||
reg = dwc3_readl(dwc->regs, DWC3_GFLADJ);
|
||||
dft = reg & DWC3_GFLADJ_30MHZ_MASK;
|
||||
if (!dev_WARN_ONCE(dwc->dev, dft == dwc->fladj,
|
||||
"request value same as default, ignoring\n")) {
|
||||
if (dft != dwc->fladj) {
|
||||
reg &= ~DWC3_GFLADJ_30MHZ_MASK;
|
||||
reg |= DWC3_GFLADJ_30MHZ_SDBND_SEL | dwc->fladj;
|
||||
dwc3_writel(dwc->regs, DWC3_GFLADJ, reg);
|
||||
|
@ -258,7 +258,7 @@ static int dwc3_pci_probe(struct pci_dev *pci, const struct pci_device_id *id)
|
||||
|
||||
ret = platform_device_add_properties(dwc->dwc3, p);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
goto err;
|
||||
|
||||
ret = dwc3_pci_quirks(dwc);
|
||||
if (ret)
|
||||
|
@ -707,6 +707,12 @@ static void dwc3_remove_requests(struct dwc3 *dwc, struct dwc3_ep *dep)
|
||||
|
||||
dwc3_gadget_giveback(dep, req, -ESHUTDOWN);
|
||||
}
|
||||
|
||||
while (!list_empty(&dep->cancelled_list)) {
|
||||
req = next_request(&dep->cancelled_list);
|
||||
|
||||
dwc3_gadget_giveback(dep, req, -ESHUTDOWN);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -2170,14 +2170,18 @@ void composite_dev_cleanup(struct usb_composite_dev *cdev)
|
||||
usb_ep_dequeue(cdev->gadget->ep0, cdev->os_desc_req);
|
||||
|
||||
kfree(cdev->os_desc_req->buf);
|
||||
cdev->os_desc_req->buf = NULL;
|
||||
usb_ep_free_request(cdev->gadget->ep0, cdev->os_desc_req);
|
||||
cdev->os_desc_req = NULL;
|
||||
}
|
||||
if (cdev->req) {
|
||||
if (cdev->setup_pending)
|
||||
usb_ep_dequeue(cdev->gadget->ep0, cdev->req);
|
||||
|
||||
kfree(cdev->req->buf);
|
||||
cdev->req->buf = NULL;
|
||||
usb_ep_free_request(cdev->gadget->ep0, cdev->req);
|
||||
cdev->req = NULL;
|
||||
}
|
||||
cdev->next_string_id = 0;
|
||||
device_remove_file(&cdev->gadget->dev, &dev_attr_suspended);
|
||||
|
@ -61,6 +61,8 @@ struct gadget_info {
|
||||
bool use_os_desc;
|
||||
char b_vendor_code;
|
||||
char qw_sign[OS_STRING_QW_SIGN_LEN];
|
||||
spinlock_t spinlock;
|
||||
bool unbind;
|
||||
};
|
||||
|
||||
static inline struct gadget_info *to_gadget_info(struct config_item *item)
|
||||
@ -1244,6 +1246,7 @@ static int configfs_composite_bind(struct usb_gadget *gadget,
|
||||
int ret;
|
||||
|
||||
/* the gi->lock is hold by the caller */
|
||||
gi->unbind = 0;
|
||||
cdev->gadget = gadget;
|
||||
set_gadget_data(gadget, cdev);
|
||||
ret = composite_dev_prepare(composite, cdev);
|
||||
@ -1376,31 +1379,128 @@ static void configfs_composite_unbind(struct usb_gadget *gadget)
|
||||
{
|
||||
struct usb_composite_dev *cdev;
|
||||
struct gadget_info *gi;
|
||||
unsigned long flags;
|
||||
|
||||
/* the gi->lock is hold by the caller */
|
||||
|
||||
cdev = get_gadget_data(gadget);
|
||||
gi = container_of(cdev, struct gadget_info, cdev);
|
||||
spin_lock_irqsave(&gi->spinlock, flags);
|
||||
gi->unbind = 1;
|
||||
spin_unlock_irqrestore(&gi->spinlock, flags);
|
||||
|
||||
kfree(otg_desc[0]);
|
||||
otg_desc[0] = NULL;
|
||||
purge_configs_funcs(gi);
|
||||
composite_dev_cleanup(cdev);
|
||||
usb_ep_autoconfig_reset(cdev->gadget);
|
||||
spin_lock_irqsave(&gi->spinlock, flags);
|
||||
cdev->gadget = NULL;
|
||||
set_gadget_data(gadget, NULL);
|
||||
spin_unlock_irqrestore(&gi->spinlock, flags);
|
||||
}
|
||||
|
||||
static int configfs_composite_setup(struct usb_gadget *gadget,
|
||||
const struct usb_ctrlrequest *ctrl)
|
||||
{
|
||||
struct usb_composite_dev *cdev;
|
||||
struct gadget_info *gi;
|
||||
unsigned long flags;
|
||||
int ret;
|
||||
|
||||
cdev = get_gadget_data(gadget);
|
||||
if (!cdev)
|
||||
return 0;
|
||||
|
||||
gi = container_of(cdev, struct gadget_info, cdev);
|
||||
spin_lock_irqsave(&gi->spinlock, flags);
|
||||
cdev = get_gadget_data(gadget);
|
||||
if (!cdev || gi->unbind) {
|
||||
spin_unlock_irqrestore(&gi->spinlock, flags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = composite_setup(gadget, ctrl);
|
||||
spin_unlock_irqrestore(&gi->spinlock, flags);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void configfs_composite_disconnect(struct usb_gadget *gadget)
|
||||
{
|
||||
struct usb_composite_dev *cdev;
|
||||
struct gadget_info *gi;
|
||||
unsigned long flags;
|
||||
|
||||
cdev = get_gadget_data(gadget);
|
||||
if (!cdev)
|
||||
return;
|
||||
|
||||
gi = container_of(cdev, struct gadget_info, cdev);
|
||||
spin_lock_irqsave(&gi->spinlock, flags);
|
||||
cdev = get_gadget_data(gadget);
|
||||
if (!cdev || gi->unbind) {
|
||||
spin_unlock_irqrestore(&gi->spinlock, flags);
|
||||
return;
|
||||
}
|
||||
|
||||
composite_disconnect(gadget);
|
||||
spin_unlock_irqrestore(&gi->spinlock, flags);
|
||||
}
|
||||
|
||||
static void configfs_composite_suspend(struct usb_gadget *gadget)
|
||||
{
|
||||
struct usb_composite_dev *cdev;
|
||||
struct gadget_info *gi;
|
||||
unsigned long flags;
|
||||
|
||||
cdev = get_gadget_data(gadget);
|
||||
if (!cdev)
|
||||
return;
|
||||
|
||||
gi = container_of(cdev, struct gadget_info, cdev);
|
||||
spin_lock_irqsave(&gi->spinlock, flags);
|
||||
cdev = get_gadget_data(gadget);
|
||||
if (!cdev || gi->unbind) {
|
||||
spin_unlock_irqrestore(&gi->spinlock, flags);
|
||||
return;
|
||||
}
|
||||
|
||||
composite_suspend(gadget);
|
||||
spin_unlock_irqrestore(&gi->spinlock, flags);
|
||||
}
|
||||
|
||||
static void configfs_composite_resume(struct usb_gadget *gadget)
|
||||
{
|
||||
struct usb_composite_dev *cdev;
|
||||
struct gadget_info *gi;
|
||||
unsigned long flags;
|
||||
|
||||
cdev = get_gadget_data(gadget);
|
||||
if (!cdev)
|
||||
return;
|
||||
|
||||
gi = container_of(cdev, struct gadget_info, cdev);
|
||||
spin_lock_irqsave(&gi->spinlock, flags);
|
||||
cdev = get_gadget_data(gadget);
|
||||
if (!cdev || gi->unbind) {
|
||||
spin_unlock_irqrestore(&gi->spinlock, flags);
|
||||
return;
|
||||
}
|
||||
|
||||
composite_resume(gadget);
|
||||
spin_unlock_irqrestore(&gi->spinlock, flags);
|
||||
}
|
||||
|
||||
static const struct usb_gadget_driver configfs_driver_template = {
|
||||
.bind = configfs_composite_bind,
|
||||
.unbind = configfs_composite_unbind,
|
||||
|
||||
.setup = composite_setup,
|
||||
.reset = composite_disconnect,
|
||||
.disconnect = composite_disconnect,
|
||||
.setup = configfs_composite_setup,
|
||||
.reset = configfs_composite_disconnect,
|
||||
.disconnect = configfs_composite_disconnect,
|
||||
|
||||
.suspend = composite_suspend,
|
||||
.resume = composite_resume,
|
||||
.suspend = configfs_composite_suspend,
|
||||
.resume = configfs_composite_resume,
|
||||
|
||||
.max_speed = USB_SPEED_SUPER,
|
||||
.driver = {
|
||||
|
@ -449,9 +449,11 @@ static void submit_request(struct usba_ep *ep, struct usba_request *req)
|
||||
next_fifo_transaction(ep, req);
|
||||
if (req->last_transaction) {
|
||||
usba_ep_writel(ep, CTL_DIS, USBA_TX_PK_RDY);
|
||||
usba_ep_writel(ep, CTL_ENB, USBA_TX_COMPLETE);
|
||||
if (ep_is_control(ep))
|
||||
usba_ep_writel(ep, CTL_ENB, USBA_TX_COMPLETE);
|
||||
} else {
|
||||
usba_ep_writel(ep, CTL_DIS, USBA_TX_COMPLETE);
|
||||
if (ep_is_control(ep))
|
||||
usba_ep_writel(ep, CTL_DIS, USBA_TX_COMPLETE);
|
||||
usba_ep_writel(ep, CTL_ENB, USBA_TX_PK_RDY);
|
||||
}
|
||||
}
|
||||
|
@ -98,6 +98,17 @@ int usb_ep_enable(struct usb_ep *ep)
|
||||
if (ep->enabled)
|
||||
goto out;
|
||||
|
||||
/* UDC drivers can't handle endpoints with maxpacket size 0 */
|
||||
if (usb_endpoint_maxp(ep->desc) == 0) {
|
||||
/*
|
||||
* We should log an error message here, but we can't call
|
||||
* dev_err() because there's no way to find the gadget
|
||||
* given only ep.
|
||||
*/
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = ep->ops->enable(ep, ep->desc);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
@ -2576,7 +2576,7 @@ static int fsl_udc_remove(struct platform_device *pdev)
|
||||
dma_pool_destroy(udc_controller->td_pool);
|
||||
free_irq(udc_controller->irq, udc_controller);
|
||||
iounmap(dr_regs);
|
||||
if (pdata->operating_mode == FSL_USB2_DR_DEVICE)
|
||||
if (res && (pdata->operating_mode == FSL_USB2_DR_DEVICE))
|
||||
release_mem_region(res->start, resource_size(res));
|
||||
|
||||
/* free udc --wait for the release() finished */
|
||||
|
@ -1544,10 +1544,10 @@ static void usb3_set_device_address(struct renesas_usb3 *usb3, u16 addr)
|
||||
static bool usb3_std_req_set_address(struct renesas_usb3 *usb3,
|
||||
struct usb_ctrlrequest *ctrl)
|
||||
{
|
||||
if (ctrl->wValue >= 128)
|
||||
if (le16_to_cpu(ctrl->wValue) >= 128)
|
||||
return true; /* stall */
|
||||
|
||||
usb3_set_device_address(usb3, ctrl->wValue);
|
||||
usb3_set_device_address(usb3, le16_to_cpu(ctrl->wValue));
|
||||
usb3_set_p0_con_for_no_data(usb3);
|
||||
|
||||
return false;
|
||||
@ -1582,6 +1582,7 @@ static bool usb3_std_req_get_status(struct renesas_usb3 *usb3,
|
||||
struct renesas_usb3_ep *usb3_ep;
|
||||
int num;
|
||||
u16 status = 0;
|
||||
__le16 tx_data;
|
||||
|
||||
switch (ctrl->bRequestType & USB_RECIP_MASK) {
|
||||
case USB_RECIP_DEVICE:
|
||||
@ -1604,10 +1605,10 @@ static bool usb3_std_req_get_status(struct renesas_usb3 *usb3,
|
||||
}
|
||||
|
||||
if (!stall) {
|
||||
status = cpu_to_le16(status);
|
||||
tx_data = cpu_to_le16(status);
|
||||
dev_dbg(usb3_to_dev(usb3), "get_status: req = %p\n",
|
||||
usb_req_to_usb3_req(usb3->ep0_req));
|
||||
usb3_pipe0_internal_xfer(usb3, &status, sizeof(status),
|
||||
usb3_pipe0_internal_xfer(usb3, &tx_data, sizeof(tx_data),
|
||||
usb3_pipe0_get_status_completion);
|
||||
}
|
||||
|
||||
@ -1772,7 +1773,7 @@ static bool usb3_std_req_set_sel(struct renesas_usb3 *usb3,
|
||||
static bool usb3_std_req_set_configuration(struct renesas_usb3 *usb3,
|
||||
struct usb_ctrlrequest *ctrl)
|
||||
{
|
||||
if (ctrl->wValue > 0)
|
||||
if (le16_to_cpu(ctrl->wValue) > 0)
|
||||
usb3_set_bit(usb3, USB_COM_CON_CONF, USB3_USB_COM_CON);
|
||||
else
|
||||
usb3_clear_bit(usb3, USB_COM_CON_CONF, USB3_USB_COM_CON);
|
||||
|
@ -202,10 +202,10 @@ static void xhci_ring_dump_segment(struct seq_file *s,
|
||||
trb = &seg->trbs[i];
|
||||
dma = seg->dma + i * sizeof(*trb);
|
||||
seq_printf(s, "%pad: %s\n", &dma,
|
||||
xhci_decode_trb(trb->generic.field[0],
|
||||
trb->generic.field[1],
|
||||
trb->generic.field[2],
|
||||
trb->generic.field[3]));
|
||||
xhci_decode_trb(le32_to_cpu(trb->generic.field[0]),
|
||||
le32_to_cpu(trb->generic.field[1]),
|
||||
le32_to_cpu(trb->generic.field[2]),
|
||||
le32_to_cpu(trb->generic.field[3])));
|
||||
}
|
||||
}
|
||||
|
||||
@ -263,10 +263,10 @@ static int xhci_slot_context_show(struct seq_file *s, void *unused)
|
||||
xhci = hcd_to_xhci(bus_to_hcd(dev->udev->bus));
|
||||
slot_ctx = xhci_get_slot_ctx(xhci, dev->out_ctx);
|
||||
seq_printf(s, "%pad: %s\n", &dev->out_ctx->dma,
|
||||
xhci_decode_slot_context(slot_ctx->dev_info,
|
||||
slot_ctx->dev_info2,
|
||||
slot_ctx->tt_info,
|
||||
slot_ctx->dev_state));
|
||||
xhci_decode_slot_context(le32_to_cpu(slot_ctx->dev_info),
|
||||
le32_to_cpu(slot_ctx->dev_info2),
|
||||
le32_to_cpu(slot_ctx->tt_info),
|
||||
le32_to_cpu(slot_ctx->dev_state)));
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -286,10 +286,10 @@ static int xhci_endpoint_context_show(struct seq_file *s, void *unused)
|
||||
ep_ctx = xhci_get_ep_ctx(xhci, dev->out_ctx, dci);
|
||||
dma = dev->out_ctx->dma + dci * CTX_SIZE(xhci->hcc_params);
|
||||
seq_printf(s, "%pad: %s\n", &dma,
|
||||
xhci_decode_ep_context(ep_ctx->ep_info,
|
||||
ep_ctx->ep_info2,
|
||||
ep_ctx->deq,
|
||||
ep_ctx->tx_info));
|
||||
xhci_decode_ep_context(le32_to_cpu(ep_ctx->ep_info),
|
||||
le32_to_cpu(ep_ctx->ep_info2),
|
||||
le64_to_cpu(ep_ctx->deq),
|
||||
le32_to_cpu(ep_ctx->tx_info)));
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -3330,6 +3330,7 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
|
||||
if (xhci_urb_suitable_for_idt(urb)) {
|
||||
memcpy(&send_addr, urb->transfer_buffer,
|
||||
trb_buff_len);
|
||||
le64_to_cpus(&send_addr);
|
||||
field |= TRB_IDT;
|
||||
}
|
||||
}
|
||||
@ -3475,6 +3476,7 @@ int xhci_queue_ctrl_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
|
||||
if (xhci_urb_suitable_for_idt(urb)) {
|
||||
memcpy(&addr, urb->transfer_buffer,
|
||||
urb->transfer_buffer_length);
|
||||
le64_to_cpus(&addr);
|
||||
field |= TRB_IDT;
|
||||
} else {
|
||||
addr = (u64) urb->transfer_dma;
|
||||
|
@ -3071,6 +3071,48 @@ void xhci_cleanup_stalled_ring(struct xhci_hcd *xhci, unsigned int ep_index,
|
||||
}
|
||||
}
|
||||
|
||||
static void xhci_endpoint_disable(struct usb_hcd *hcd,
|
||||
struct usb_host_endpoint *host_ep)
|
||||
{
|
||||
struct xhci_hcd *xhci;
|
||||
struct xhci_virt_device *vdev;
|
||||
struct xhci_virt_ep *ep;
|
||||
struct usb_device *udev;
|
||||
unsigned long flags;
|
||||
unsigned int ep_index;
|
||||
|
||||
xhci = hcd_to_xhci(hcd);
|
||||
rescan:
|
||||
spin_lock_irqsave(&xhci->lock, flags);
|
||||
|
||||
udev = (struct usb_device *)host_ep->hcpriv;
|
||||
if (!udev || !udev->slot_id)
|
||||
goto done;
|
||||
|
||||
vdev = xhci->devs[udev->slot_id];
|
||||
if (!vdev)
|
||||
goto done;
|
||||
|
||||
ep_index = xhci_get_endpoint_index(&host_ep->desc);
|
||||
ep = &vdev->eps[ep_index];
|
||||
if (!ep)
|
||||
goto done;
|
||||
|
||||
/* wait for hub_tt_work to finish clearing hub TT */
|
||||
if (ep->ep_state & EP_CLEARING_TT) {
|
||||
spin_unlock_irqrestore(&xhci->lock, flags);
|
||||
schedule_timeout_uninterruptible(1);
|
||||
goto rescan;
|
||||
}
|
||||
|
||||
if (ep->ep_state)
|
||||
xhci_dbg(xhci, "endpoint disable with ep_state 0x%x\n",
|
||||
ep->ep_state);
|
||||
done:
|
||||
host_ep->hcpriv = NULL;
|
||||
spin_unlock_irqrestore(&xhci->lock, flags);
|
||||
}
|
||||
|
||||
/*
|
||||
* Called after usb core issues a clear halt control message.
|
||||
* The host side of the halt should already be cleared by a reset endpoint
|
||||
@ -5238,20 +5280,13 @@ static void xhci_clear_tt_buffer_complete(struct usb_hcd *hcd,
|
||||
unsigned int ep_index;
|
||||
unsigned long flags;
|
||||
|
||||
/*
|
||||
* udev might be NULL if tt buffer is cleared during a failed device
|
||||
* enumeration due to a halted control endpoint. Usb core might
|
||||
* have allocated a new udev for the next enumeration attempt.
|
||||
*/
|
||||
|
||||
xhci = hcd_to_xhci(hcd);
|
||||
|
||||
spin_lock_irqsave(&xhci->lock, flags);
|
||||
udev = (struct usb_device *)ep->hcpriv;
|
||||
if (!udev)
|
||||
return;
|
||||
slot_id = udev->slot_id;
|
||||
ep_index = xhci_get_endpoint_index(&ep->desc);
|
||||
|
||||
spin_lock_irqsave(&xhci->lock, flags);
|
||||
xhci->devs[slot_id]->eps[ep_index].ep_state &= ~EP_CLEARING_TT;
|
||||
xhci_ring_doorbell_for_active_rings(xhci, slot_id, ep_index);
|
||||
spin_unlock_irqrestore(&xhci->lock, flags);
|
||||
@ -5288,6 +5323,7 @@ static const struct hc_driver xhci_hc_driver = {
|
||||
.free_streams = xhci_free_streams,
|
||||
.add_endpoint = xhci_add_endpoint,
|
||||
.drop_endpoint = xhci_drop_endpoint,
|
||||
.endpoint_disable = xhci_endpoint_disable,
|
||||
.endpoint_reset = xhci_endpoint_reset,
|
||||
.check_bandwidth = xhci_check_bandwidth,
|
||||
.reset_bandwidth = xhci_reset_bandwidth,
|
||||
|
@ -487,7 +487,7 @@ static ssize_t ld_usb_read(struct file *file, char __user *buffer, size_t count,
|
||||
}
|
||||
bytes_to_read = min(count, *actual_buffer);
|
||||
if (bytes_to_read < *actual_buffer)
|
||||
dev_warn(&dev->intf->dev, "Read buffer overflow, %zd bytes dropped\n",
|
||||
dev_warn(&dev->intf->dev, "Read buffer overflow, %zu bytes dropped\n",
|
||||
*actual_buffer-bytes_to_read);
|
||||
|
||||
/* copy one interrupt_in_buffer from ring_buffer into userspace */
|
||||
@ -495,11 +495,11 @@ static ssize_t ld_usb_read(struct file *file, char __user *buffer, size_t count,
|
||||
retval = -EFAULT;
|
||||
goto unlock_exit;
|
||||
}
|
||||
dev->ring_tail = (dev->ring_tail+1) % ring_buffer_size;
|
||||
|
||||
retval = bytes_to_read;
|
||||
|
||||
spin_lock_irq(&dev->rbsl);
|
||||
dev->ring_tail = (dev->ring_tail + 1) % ring_buffer_size;
|
||||
|
||||
if (dev->buffer_overflow) {
|
||||
dev->buffer_overflow = 0;
|
||||
spin_unlock_irq(&dev->rbsl);
|
||||
@ -562,8 +562,9 @@ static ssize_t ld_usb_write(struct file *file, const char __user *buffer,
|
||||
/* write the data into interrupt_out_buffer from userspace */
|
||||
bytes_to_write = min(count, write_buffer_size*dev->interrupt_out_endpoint_size);
|
||||
if (bytes_to_write < count)
|
||||
dev_warn(&dev->intf->dev, "Write buffer overflow, %zd bytes dropped\n", count-bytes_to_write);
|
||||
dev_dbg(&dev->intf->dev, "%s: count = %zd, bytes_to_write = %zd\n",
|
||||
dev_warn(&dev->intf->dev, "Write buffer overflow, %zu bytes dropped\n",
|
||||
count - bytes_to_write);
|
||||
dev_dbg(&dev->intf->dev, "%s: count = %zu, bytes_to_write = %zu\n",
|
||||
__func__, count, bytes_to_write);
|
||||
|
||||
if (copy_from_user(dev->interrupt_out_buffer, buffer, bytes_to_write)) {
|
||||
@ -580,7 +581,7 @@ static ssize_t ld_usb_write(struct file *file, const char __user *buffer,
|
||||
1 << 8, 0,
|
||||
dev->interrupt_out_buffer,
|
||||
bytes_to_write,
|
||||
USB_CTRL_SET_TIMEOUT * HZ);
|
||||
USB_CTRL_SET_TIMEOUT);
|
||||
if (retval < 0)
|
||||
dev_err(&dev->intf->dev,
|
||||
"Couldn't submit HID_REQ_SET_REPORT %d\n",
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#include "mtu3.h"
|
||||
#include "mtu3_dr.h"
|
||||
#include "mtu3_debug.h"
|
||||
#include "mtu3_trace.h"
|
||||
|
||||
|
@ -162,17 +162,17 @@ void usbhs_usbreq_get_val(struct usbhs_priv *priv, struct usb_ctrlrequest *req)
|
||||
req->bRequest = (val >> 8) & 0xFF;
|
||||
req->bRequestType = (val >> 0) & 0xFF;
|
||||
|
||||
req->wValue = usbhs_read(priv, USBVAL);
|
||||
req->wIndex = usbhs_read(priv, USBINDX);
|
||||
req->wLength = usbhs_read(priv, USBLENG);
|
||||
req->wValue = cpu_to_le16(usbhs_read(priv, USBVAL));
|
||||
req->wIndex = cpu_to_le16(usbhs_read(priv, USBINDX));
|
||||
req->wLength = cpu_to_le16(usbhs_read(priv, USBLENG));
|
||||
}
|
||||
|
||||
void usbhs_usbreq_set_val(struct usbhs_priv *priv, struct usb_ctrlrequest *req)
|
||||
{
|
||||
usbhs_write(priv, USBREQ, (req->bRequest << 8) | req->bRequestType);
|
||||
usbhs_write(priv, USBVAL, req->wValue);
|
||||
usbhs_write(priv, USBINDX, req->wIndex);
|
||||
usbhs_write(priv, USBLENG, req->wLength);
|
||||
usbhs_write(priv, USBVAL, le16_to_cpu(req->wValue));
|
||||
usbhs_write(priv, USBINDX, le16_to_cpu(req->wIndex));
|
||||
usbhs_write(priv, USBLENG, le16_to_cpu(req->wLength));
|
||||
|
||||
usbhs_bset(priv, DCPCTR, SUREQ, SUREQ);
|
||||
}
|
||||
|
@ -265,7 +265,7 @@ static int usbhsg_recip_handler_std_set_device(struct usbhs_priv *priv,
|
||||
case USB_DEVICE_TEST_MODE:
|
||||
usbhsg_recip_handler_std_control_done(priv, uep, ctrl);
|
||||
udelay(100);
|
||||
usbhs_sys_set_test_mode(priv, le16_to_cpu(ctrl->wIndex >> 8));
|
||||
usbhs_sys_set_test_mode(priv, le16_to_cpu(ctrl->wIndex) >> 8);
|
||||
break;
|
||||
default:
|
||||
usbhsg_recip_handler_std_control_done(priv, uep, ctrl);
|
||||
@ -315,7 +315,7 @@ static void __usbhsg_recip_send_status(struct usbhsg_gpriv *gpriv,
|
||||
struct usbhs_pipe *pipe = usbhsg_uep_to_pipe(dcp);
|
||||
struct device *dev = usbhsg_gpriv_to_dev(gpriv);
|
||||
struct usb_request *req;
|
||||
unsigned short *buf;
|
||||
__le16 *buf;
|
||||
|
||||
/* alloc new usb_request for recip */
|
||||
req = usb_ep_alloc_request(&dcp->ep, GFP_ATOMIC);
|
||||
|
@ -559,6 +559,10 @@ static int firm_send_command(struct usb_serial_port *port, __u8 command,
|
||||
|
||||
command_port = port->serial->port[COMMAND_PORT];
|
||||
command_info = usb_get_serial_port_data(command_port);
|
||||
|
||||
if (command_port->bulk_out_size < datasize + 1)
|
||||
return -EIO;
|
||||
|
||||
mutex_lock(&command_info->mutex);
|
||||
command_info->command_finished = false;
|
||||
|
||||
@ -632,6 +636,7 @@ static void firm_setup_port(struct tty_struct *tty)
|
||||
struct device *dev = &port->dev;
|
||||
struct whiteheat_port_settings port_settings;
|
||||
unsigned int cflag = tty->termios.c_cflag;
|
||||
speed_t baud;
|
||||
|
||||
port_settings.port = port->port_number + 1;
|
||||
|
||||
@ -692,11 +697,13 @@ static void firm_setup_port(struct tty_struct *tty)
|
||||
dev_dbg(dev, "%s - XON = %2x, XOFF = %2x\n", __func__, port_settings.xon, port_settings.xoff);
|
||||
|
||||
/* get the baud rate wanted */
|
||||
port_settings.baud = tty_get_baud_rate(tty);
|
||||
dev_dbg(dev, "%s - baud rate = %d\n", __func__, port_settings.baud);
|
||||
baud = tty_get_baud_rate(tty);
|
||||
port_settings.baud = cpu_to_le32(baud);
|
||||
dev_dbg(dev, "%s - baud rate = %u\n", __func__, baud);
|
||||
|
||||
/* fixme: should set validated settings */
|
||||
tty_encode_baud_rate(tty, port_settings.baud, port_settings.baud);
|
||||
tty_encode_baud_rate(tty, baud, baud);
|
||||
|
||||
/* handle any settings that aren't specified in the tty structure */
|
||||
port_settings.lloop = 0;
|
||||
|
||||
|
@ -87,7 +87,7 @@ struct whiteheat_simple {
|
||||
|
||||
struct whiteheat_port_settings {
|
||||
__u8 port; /* port number (1 to N) */
|
||||
__u32 baud; /* any value 7 - 460800, firmware calculates
|
||||
__le32 baud; /* any value 7 - 460800, firmware calculates
|
||||
best fit; arrives little endian */
|
||||
__u8 bits; /* 5, 6, 7, or 8 */
|
||||
__u8 stop; /* 1 or 2, default 1 (2 = 1.5 if bits = 5) */
|
||||
|
@ -68,7 +68,6 @@ static const char* host_info(struct Scsi_Host *host)
|
||||
static int slave_alloc (struct scsi_device *sdev)
|
||||
{
|
||||
struct us_data *us = host_to_us(sdev->host);
|
||||
int maxp;
|
||||
|
||||
/*
|
||||
* Set the INQUIRY transfer length to 36. We don't use any of
|
||||
@ -77,15 +76,6 @@ static int slave_alloc (struct scsi_device *sdev)
|
||||
*/
|
||||
sdev->inquiry_len = 36;
|
||||
|
||||
/*
|
||||
* USB has unusual scatter-gather requirements: the length of each
|
||||
* scatterlist element except the last must be divisible by the
|
||||
* Bulk maxpacket value. Fortunately this value is always a
|
||||
* power of 2. Inform the block layer about this requirement.
|
||||
*/
|
||||
maxp = usb_maxpacket(us->pusb_dev, us->recv_bulk_pipe, 0);
|
||||
blk_queue_virt_boundary(sdev->request_queue, maxp - 1);
|
||||
|
||||
/*
|
||||
* Some host controllers may have alignment requirements.
|
||||
* We'll play it safe by requiring 512-byte alignment always.
|
||||
|
@ -789,29 +789,9 @@ static int uas_slave_alloc(struct scsi_device *sdev)
|
||||
{
|
||||
struct uas_dev_info *devinfo =
|
||||
(struct uas_dev_info *)sdev->host->hostdata;
|
||||
int maxp;
|
||||
|
||||
sdev->hostdata = devinfo;
|
||||
|
||||
/*
|
||||
* We have two requirements here. We must satisfy the requirements
|
||||
* of the physical HC and the demands of the protocol, as we
|
||||
* definitely want no additional memory allocation in this path
|
||||
* ruling out using bounce buffers.
|
||||
*
|
||||
* For a transmission on USB to continue we must never send
|
||||
* a package that is smaller than maxpacket. Hence the length of each
|
||||
* scatterlist element except the last must be divisible by the
|
||||
* Bulk maxpacket value.
|
||||
* If the HC does not ensure that through SG,
|
||||
* the upper layer must do that. We must assume nothing
|
||||
* about the capabilities off the HC, so we use the most
|
||||
* pessimistic requirement.
|
||||
*/
|
||||
|
||||
maxp = usb_maxpacket(devinfo->udev, devinfo->data_in_pipe, 0);
|
||||
blk_queue_virt_boundary(sdev->request_queue, maxp - 1);
|
||||
|
||||
/*
|
||||
* The protocol has no requirements on alignment in the strict sense.
|
||||
* Controllers may or may not have alignment restrictions.
|
||||
|
@ -147,7 +147,10 @@ static int vhci_send_cmd_submit(struct vhci_device *vdev)
|
||||
}
|
||||
|
||||
kfree(iov);
|
||||
/* This is only for isochronous case */
|
||||
kfree(iso_buffer);
|
||||
iso_buffer = NULL;
|
||||
|
||||
usbip_dbg_vhci_tx("send txdata\n");
|
||||
|
||||
total_size += txsize;
|
||||
|
@ -69,7 +69,7 @@ int read_usb_vudc_device(struct udev_device *sdev, struct usbip_usb_device *dev)
|
||||
FILE *fd = NULL;
|
||||
struct udev_device *plat;
|
||||
const char *speed;
|
||||
int ret = 0;
|
||||
size_t ret;
|
||||
|
||||
plat = udev_device_get_parent(sdev);
|
||||
path = udev_device_get_syspath(plat);
|
||||
@ -79,8 +79,10 @@ int read_usb_vudc_device(struct udev_device *sdev, struct usbip_usb_device *dev)
|
||||
if (!fd)
|
||||
return -1;
|
||||
ret = fread((char *) &descr, sizeof(descr), 1, fd);
|
||||
if (ret < 0)
|
||||
if (ret != 1) {
|
||||
err("Cannot read vudc device descr file: %s", strerror(errno));
|
||||
goto err;
|
||||
}
|
||||
fclose(fd);
|
||||
|
||||
copy_descr_attr(dev, &descr, bDeviceClass);
|
||||
|
Loading…
Reference in New Issue
Block a user