Merge tag 'usb-5.2-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb

Pull USB/PHY updates from Greg KH:
 "Here is the big set of USB and PHY driver patches for 5.2-rc1

  There is the usual set of:

   - USB gadget updates

   - PHY driver updates and additions

   - USB serial driver updates and fixes

   - typec updates and new chips supported

   - mtu3 driver updates

   - xhci driver updates

   - other tiny driver updates

  Nothing really interesting, just constant forward progress.

  All of these have been in linux-next for a while with no reported
  issues. The usb-gadget and usb-serial trees were merged a bit "late",
  but both of them had been in linux-next before they got merged here
  last Friday"

* tag 'usb-5.2-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb: (206 commits)
  USB: serial: f81232: implement break control
  USB: serial: f81232: add high baud rate support
  USB: serial: f81232: clear overrun flag
  USB: serial: f81232: fix interrupt worker not stop
  usb: dwc3: Rename DWC3_DCTL_LPM_ERRATA
  usb: dwc3: Fix default lpm_nyet_threshold value
  usb: dwc3: debug: Print GET_STATUS(device) tracepoint
  usb: dwc3: Do core validation early on probe
  usb: dwc3: gadget: Set lpm_capable
  usb: gadget: atmel: tie wake lock to running clock
  usb: gadget: atmel: support USB suspend
  usb: gadget: atmel_usba_udc: simplify setting of interrupt-enabled mask
  dwc2: gadget: Fix completed transfer size calculation in DDMA
  usb: dwc2: Set lpm mode parameters depend on HW configuration
  usb: dwc2: Fix channel disable flow
  usb: dwc2: Set actual frame number for completed ISOC transfer
  usb: gadget: do not use __constant_cpu_to_le16
  usb: dwc2: gadget: Increase descriptors count for ISOC's
  usb: introduce usb_ep_type_string() function
  usb: dwc3: move synchronize_irq() out of the spinlock protected block
  ...
This commit is contained in:
Linus Torvalds
2019-05-08 10:03:52 -07:00
206 changed files with 12173 additions and 3318 deletions

View File

@@ -727,8 +727,7 @@ void fhci_queue_urb(struct fhci_hcd *fhci, struct urb *urb)
}
ed->speed = (urb->dev->speed == USB_SPEED_LOW) ?
FHCI_LOW_SPEED : FHCI_FULL_SPEED;
ed->max_pkt_size = usb_maxpacket(urb->dev,
urb->pipe, usb_pipeout(urb->pipe));
ed->max_pkt_size = usb_endpoint_maxp(&urb->ep->desc);
urb->ep->hcpriv = ed;
fhci_dbg(fhci, "new ep speed=%d max_pkt_size=%d\n",
ed->speed, ed->max_pkt_size);
@@ -768,8 +767,7 @@ void fhci_queue_urb(struct fhci_hcd *fhci, struct urb *urb)
if (urb->transfer_flags & URB_ZERO_PACKET &&
urb->transfer_buffer_length > 0 &&
((urb->transfer_buffer_length %
usb_maxpacket(urb->dev, urb->pipe,
usb_pipeout(urb->pipe))) == 0))
usb_endpoint_maxp(&urb->ep->desc)) == 0))
urb_state = US_BULK0;
while (data_len > 4096) {
td = fhci_td_fill(fhci, urb, urb_priv, ed, cnt,
@@ -807,8 +805,8 @@ void fhci_queue_urb(struct fhci_hcd *fhci, struct urb *urb)
break;
case FHCI_TF_CTRL:
ed->dev_addr = usb_pipedevice(urb->pipe);
ed->max_pkt_size = usb_maxpacket(urb->dev, urb->pipe,
usb_pipeout(urb->pipe));
ed->max_pkt_size = usb_endpoint_maxp(&urb->ep->desc);
/* setup stage */
td = fhci_td_fill(fhci, urb, urb_priv, ed, cnt++, FHCI_TA_SETUP,
USB_TD_TOGGLE_DATA0, urb->setup_packet, 8, 0, 0, true);

View File

@@ -3203,6 +3203,8 @@ static int __init u132_hcd_init(void)
return -ENODEV;
printk(KERN_INFO "driver %s\n", hcd_name);
workqueue = create_singlethread_workqueue("u132");
if (!workqueue)
return -ENOMEM;
retval = platform_driver_register(&u132_platform_driver);
if (retval)
destroy_workqueue(workqueue);

View File

@@ -487,8 +487,8 @@ static void xhci_disable_port(struct usb_hcd *hcd, struct xhci_hcd *xhci,
/* Write 1 to disable the port */
writel(port_status | PORT_PE, addr);
port_status = readl(addr);
xhci_dbg(xhci, "disable port, actual port %d status = 0x%x\n",
wIndex, port_status);
xhci_dbg(xhci, "disable port %d-%d, portsc: 0x%x\n",
hcd->self.busnum, wIndex + 1, port_status);
}
static void xhci_clear_port_change_bit(struct xhci_hcd *xhci, u16 wValue,
@@ -537,8 +537,9 @@ static void xhci_clear_port_change_bit(struct xhci_hcd *xhci, u16 wValue,
/* Change bits are all write 1 to clear */
writel(port_status | status, addr);
port_status = readl(addr);
xhci_dbg(xhci, "clear port %s change, actual port %d status = 0x%x\n",
port_change_bit, wIndex, port_status);
xhci_dbg(xhci, "clear port%d %s change, portsc: 0x%x\n",
wIndex + 1, port_change_bit, port_status);
}
struct xhci_hub *xhci_get_rhub(struct usb_hcd *hcd)
@@ -565,13 +566,16 @@ static void xhci_set_port_power(struct xhci_hcd *xhci, struct usb_hcd *hcd,
rhub = xhci_get_rhub(hcd);
port = rhub->ports[index];
temp = readl(port->addr);
xhci_dbg(xhci, "set port power %d-%d %s, portsc: 0x%x\n",
hcd->self.busnum, index + 1, on ? "ON" : "OFF", temp);
temp = xhci_port_state_to_neutral(temp);
if (on) {
/* Power on */
writel(temp | PORT_POWER, port->addr);
temp = readl(port->addr);
xhci_dbg(xhci, "set port power, actual port %d status = 0x%x\n",
index, temp);
readl(port->addr);
} else {
/* Power off */
writel(temp & ~PORT_POWER, port->addr);
@@ -666,12 +670,17 @@ void xhci_set_link_state(struct xhci_hcd *xhci, struct xhci_port *port,
u32 link_state)
{
u32 temp;
u32 portsc;
temp = readl(port->addr);
temp = xhci_port_state_to_neutral(temp);
portsc = readl(port->addr);
temp = xhci_port_state_to_neutral(portsc);
temp &= ~PORT_PLS_MASK;
temp |= PORT_LINK_STROBE | link_state;
writel(temp, port->addr);
xhci_dbg(xhci, "Set port %d-%d link state, portsc: 0x%x, write 0x%x",
port->rhub->hcd->self.busnum, port->hcd_portnum + 1,
portsc, temp);
}
static void xhci_set_remote_wake_mask(struct xhci_hcd *xhci,
@@ -840,7 +849,9 @@ static int xhci_handle_usb2_port_link_resume(struct xhci_port *port,
} else if (time_after_eq(jiffies, bus_state->resume_done[wIndex])) {
int time_left;
xhci_dbg(xhci, "Resume USB2 port %d\n", wIndex + 1);
xhci_dbg(xhci, "resume USB2 port %d-%d\n",
hcd->self.busnum, wIndex + 1);
bus_state->resume_done[wIndex] = 0;
clear_bit(wIndex, &bus_state->resuming_ports);
@@ -867,9 +878,8 @@ static int xhci_handle_usb2_port_link_resume(struct xhci_port *port,
} else {
int port_status = readl(port->addr);
xhci_warn(xhci, "Port resume %i msec timed out, portsc = 0x%x\n",
XHCI_MAX_REXIT_TIMEOUT_MS,
port_status);
xhci_warn(xhci, "Port resume timed out, port %d-%d: 0x%x\n",
hcd->self.busnum, wIndex + 1, port_status);
*status |= USB_PORT_STAT_SUSPEND;
clear_bit(wIndex, &bus_state->rexit_ports);
}
@@ -1124,9 +1134,8 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
if (status == 0xffffffff)
goto error;
xhci_dbg(xhci, "get port status, actual port %d status = 0x%x\n",
wIndex, temp);
xhci_dbg(xhci, "Get port status returned 0x%x\n", status);
xhci_dbg(xhci, "Get port status %d-%d read: 0x%x, return 0x%x",
hcd->self.busnum, wIndex + 1, temp, status);
put_unaligned(cpu_to_le32(status), (__le32 *) buf);
/* if USB 3.1 extended port status return additional 4 bytes */
@@ -1182,7 +1191,8 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
temp = readl(ports[wIndex]->addr);
if ((temp & PORT_PE) == 0 || (temp & PORT_RESET)
|| (temp & PORT_PLS_MASK) >= XDEV_U3) {
xhci_warn(xhci, "USB core suspending device not in U0/U1/U2.\n");
xhci_warn(xhci, "USB core suspending port %d-%d not in U0/U1/U2\n",
hcd->self.busnum, wIndex + 1);
goto error;
}

View File

@@ -206,19 +206,6 @@ static int xhci_mtk_ssusb_config(struct xhci_hcd_mtk *mtk)
return xhci_mtk_host_enable(mtk);
}
/* ignore the error if the clock does not exist */
static struct clk *optional_clk_get(struct device *dev, const char *id)
{
struct clk *opt_clk;
opt_clk = devm_clk_get(dev, id);
/* ignore error number except EPROBE_DEFER */
if (IS_ERR(opt_clk) && (PTR_ERR(opt_clk) != -EPROBE_DEFER))
opt_clk = NULL;
return opt_clk;
}
static int xhci_mtk_clks_get(struct xhci_hcd_mtk *mtk)
{
struct device *dev = mtk->dev;
@@ -229,15 +216,15 @@ static int xhci_mtk_clks_get(struct xhci_hcd_mtk *mtk)
return PTR_ERR(mtk->sys_clk);
}
mtk->ref_clk = optional_clk_get(dev, "ref_ck");
mtk->ref_clk = devm_clk_get_optional(dev, "ref_ck");
if (IS_ERR(mtk->ref_clk))
return PTR_ERR(mtk->ref_clk);
mtk->mcu_clk = optional_clk_get(dev, "mcu_ck");
mtk->mcu_clk = devm_clk_get_optional(dev, "mcu_ck");
if (IS_ERR(mtk->mcu_clk))
return PTR_ERR(mtk->mcu_clk);
mtk->dma_clk = optional_clk_get(dev, "dma_ck");
mtk->dma_clk = devm_clk_get_optional(dev, "dma_ck");
return PTR_ERR_OR_ZERO(mtk->dma_clk);
}

View File

@@ -165,8 +165,6 @@ static int xhci_plat_probe(struct platform_device *pdev)
struct xhci_hcd *xhci;
struct resource *res;
struct usb_hcd *hcd;
struct clk *clk;
struct clk *reg_clk;
int ret;
int irq;
@@ -235,31 +233,32 @@ static int xhci_plat_probe(struct platform_device *pdev)
hcd->rsrc_start = res->start;
hcd->rsrc_len = resource_size(res);
xhci = hcd_to_xhci(hcd);
/*
* Not all platforms have clks so it is not an error if the
* clock do not exist.
*/
reg_clk = devm_clk_get(&pdev->dev, "reg");
if (!IS_ERR(reg_clk)) {
ret = clk_prepare_enable(reg_clk);
if (ret)
goto put_hcd;
} else if (PTR_ERR(reg_clk) == -EPROBE_DEFER) {
ret = -EPROBE_DEFER;
xhci->reg_clk = devm_clk_get_optional(&pdev->dev, "reg");
if (IS_ERR(xhci->reg_clk)) {
ret = PTR_ERR(xhci->reg_clk);
goto put_hcd;
}
clk = devm_clk_get(&pdev->dev, NULL);
if (!IS_ERR(clk)) {
ret = clk_prepare_enable(clk);
if (ret)
goto disable_reg_clk;
} else if (PTR_ERR(clk) == -EPROBE_DEFER) {
ret = -EPROBE_DEFER;
ret = clk_prepare_enable(xhci->reg_clk);
if (ret)
goto put_hcd;
xhci->clk = devm_clk_get_optional(&pdev->dev, NULL);
if (IS_ERR(xhci->clk)) {
ret = PTR_ERR(xhci->clk);
goto disable_reg_clk;
}
xhci = hcd_to_xhci(hcd);
ret = clk_prepare_enable(xhci->clk);
if (ret)
goto disable_reg_clk;
priv_match = of_device_get_match_data(&pdev->dev);
if (priv_match) {
struct xhci_plat_priv *priv = hcd_to_xhci_priv(hcd);
@@ -271,8 +270,6 @@ static int xhci_plat_probe(struct platform_device *pdev)
device_wakeup_enable(hcd->self.controller);
xhci->clk = clk;
xhci->reg_clk = reg_clk;
xhci->main_hcd = hcd;
xhci->shared_hcd = __usb_create_hcd(driver, sysdev, &pdev->dev,
dev_name(&pdev->dev), hcd);
@@ -348,10 +345,10 @@ put_usb3_hcd:
usb_put_hcd(xhci->shared_hcd);
disable_clk:
clk_disable_unprepare(clk);
clk_disable_unprepare(xhci->clk);
disable_reg_clk:
clk_disable_unprepare(reg_clk);
clk_disable_unprepare(xhci->reg_clk);
put_hcd:
usb_put_hcd(hcd);

View File

@@ -1569,18 +1569,19 @@ static void handle_port_status(struct xhci_hcd *xhci,
"WARN: xHC returned failed port status event\n");
port_id = GET_PORT_ID(le32_to_cpu(event->generic.field[0]));
xhci_dbg(xhci, "Port Status Change Event for port %d\n", port_id);
max_ports = HCS_MAX_PORTS(xhci->hcs_params1);
if ((port_id <= 0) || (port_id > max_ports)) {
xhci_warn(xhci, "Invalid port id %d\n", port_id);
xhci_warn(xhci, "Port change event with invalid port ID %d\n",
port_id);
inc_deq(xhci, xhci->event_ring);
return;
}
port = &xhci->hw_ports[port_id - 1];
if (!port || !port->rhub || port->hcd_portnum == DUPLICATE_ENTRY) {
xhci_warn(xhci, "Event for invalid port %u\n", port_id);
xhci_warn(xhci, "Port change event, no port for port ID %u\n",
port_id);
bogus_port_status = true;
goto cleanup;
}
@@ -1597,6 +1598,9 @@ static void handle_port_status(struct xhci_hcd *xhci,
hcd_portnum = port->hcd_portnum;
portsc = readl(port->addr);
xhci_dbg(xhci, "Port change event, %d-%d, id %d, portsc: 0x%x\n",
hcd->self.busnum, hcd_portnum + 1, port_id, portsc);
trace_xhci_handle_port_status(hcd_portnum, portsc);
if (hcd->state == HC_STATE_SUSPENDED) {
@@ -3275,6 +3279,12 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
field |= TRB_IOC;
more_trbs_coming = false;
td->last_trb = ring->enqueue;
if (xhci_urb_suitable_for_idt(urb)) {
memcpy(&send_addr, urb->transfer_buffer,
trb_buff_len);
field |= TRB_IDT;
}
}
/* Only set interrupt on short packet for IN endpoints */
@@ -3414,6 +3424,12 @@ int xhci_queue_ctrl_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
if (urb->transfer_buffer_length > 0) {
u32 length_field, remainder;
if (xhci_urb_suitable_for_idt(urb)) {
memcpy(&urb->transfer_dma, urb->transfer_buffer,
urb->transfer_buffer_length);
field |= TRB_IDT;
}
remainder = xhci_td_remainder(xhci, 0,
urb->transfer_buffer_length,
urb->transfer_buffer_length,

View File

@@ -161,6 +161,7 @@ struct tegra_xusb_soc {
} ports;
bool scale_ss_clock;
bool has_ipfs;
};
struct tegra_xusb {
@@ -637,16 +638,18 @@ static irqreturn_t tegra_xusb_mbox_thread(int irq, void *data)
return IRQ_HANDLED;
}
static void tegra_xusb_ipfs_config(struct tegra_xusb *tegra,
struct resource *regs)
static void tegra_xusb_config(struct tegra_xusb *tegra,
struct resource *regs)
{
u32 value;
value = ipfs_readl(tegra, IPFS_XUSB_HOST_CONFIGURATION_0);
value |= IPFS_EN_FPCI;
ipfs_writel(tegra, value, IPFS_XUSB_HOST_CONFIGURATION_0);
if (tegra->soc->has_ipfs) {
value = ipfs_readl(tegra, IPFS_XUSB_HOST_CONFIGURATION_0);
value |= IPFS_EN_FPCI;
ipfs_writel(tegra, value, IPFS_XUSB_HOST_CONFIGURATION_0);
usleep_range(10, 20);
usleep_range(10, 20);
}
/* Program BAR0 space */
value = fpci_readl(tegra, XUSB_CFG_4);
@@ -661,13 +664,15 @@ static void tegra_xusb_ipfs_config(struct tegra_xusb *tegra,
value |= XUSB_IO_SPACE_EN | XUSB_MEM_SPACE_EN | XUSB_BUS_MASTER_EN;
fpci_writel(tegra, value, XUSB_CFG_1);
/* Enable interrupt assertion */
value = ipfs_readl(tegra, IPFS_XUSB_HOST_INTR_MASK_0);
value |= IPFS_IP_INT_MASK;
ipfs_writel(tegra, value, IPFS_XUSB_HOST_INTR_MASK_0);
if (tegra->soc->has_ipfs) {
/* Enable interrupt assertion */
value = ipfs_readl(tegra, IPFS_XUSB_HOST_INTR_MASK_0);
value |= IPFS_IP_INT_MASK;
ipfs_writel(tegra, value, IPFS_XUSB_HOST_INTR_MASK_0);
/* Set hysteresis */
ipfs_writel(tegra, 0x80, IPFS_XUSB_HOST_CLKGATE_HYSTERESIS_0);
/* Set hysteresis */
ipfs_writel(tegra, 0x80, IPFS_XUSB_HOST_CLKGATE_HYSTERESIS_0);
}
}
static int tegra_xusb_clk_enable(struct tegra_xusb *tegra)
@@ -1015,10 +1020,12 @@ static int tegra_xusb_probe(struct platform_device *pdev)
if (IS_ERR(tegra->fpci_base))
return PTR_ERR(tegra->fpci_base);
res = platform_get_resource(pdev, IORESOURCE_MEM, 2);
tegra->ipfs_base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(tegra->ipfs_base))
return PTR_ERR(tegra->ipfs_base);
if (tegra->soc->has_ipfs) {
res = platform_get_resource(pdev, IORESOURCE_MEM, 2);
tegra->ipfs_base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(tegra->ipfs_base))
return PTR_ERR(tegra->ipfs_base);
}
tegra->xhci_irq = platform_get_irq(pdev, 0);
if (tegra->xhci_irq < 0)
@@ -1208,7 +1215,7 @@ static int tegra_xusb_probe(struct platform_device *pdev)
goto disable_rpm;
}
tegra_xusb_ipfs_config(tegra, regs);
tegra_xusb_config(tegra, regs);
err = tegra_xusb_load_firmware(tegra);
if (err < 0) {
@@ -1380,6 +1387,7 @@ static const struct tegra_xusb_soc tegra124_soc = {
.usb3 = { .offset = 0, .count = 2, },
},
.scale_ss_clock = true,
.has_ipfs = true,
};
MODULE_FIRMWARE("nvidia/tegra124/xusb.bin");
@@ -1411,12 +1419,38 @@ static const struct tegra_xusb_soc tegra210_soc = {
.usb3 = { .offset = 0, .count = 4, },
},
.scale_ss_clock = false,
.has_ipfs = true,
};
MODULE_FIRMWARE("nvidia/tegra210/xusb.bin");
static const char * const tegra186_supply_names[] = {
};
static const struct tegra_xusb_phy_type tegra186_phy_types[] = {
{ .name = "usb3", .num = 3, },
{ .name = "usb2", .num = 3, },
{ .name = "hsic", .num = 1, },
};
static const struct tegra_xusb_soc tegra186_soc = {
.firmware = "nvidia/tegra186/xusb.bin",
.supply_names = tegra186_supply_names,
.num_supplies = ARRAY_SIZE(tegra186_supply_names),
.phy_types = tegra186_phy_types,
.num_types = ARRAY_SIZE(tegra186_phy_types),
.ports = {
.usb3 = { .offset = 0, .count = 3, },
.usb2 = { .offset = 3, .count = 3, },
.hsic = { .offset = 6, .count = 1, },
},
.scale_ss_clock = false,
.has_ipfs = false,
};
static const struct of_device_id tegra_xusb_of_match[] = {
{ .compatible = "nvidia,tegra124-xusb", .data = &tegra124_soc },
{ .compatible = "nvidia,tegra210-xusb", .data = &tegra210_soc },
{ .compatible = "nvidia,tegra186-xusb", .data = &tegra186_soc },
{ },
};
MODULE_DEVICE_TABLE(of, tegra_xusb_of_match);

View File

@@ -366,6 +366,11 @@ DEFINE_EVENT(xhci_log_ep_ctx, xhci_handle_cmd_config_ep,
TP_ARGS(ctx)
);
DEFINE_EVENT(xhci_log_ep_ctx, xhci_add_endpoint,
TP_PROTO(struct xhci_ep_ctx *ctx),
TP_ARGS(ctx)
);
DECLARE_EVENT_CLASS(xhci_log_slot_ctx,
TP_PROTO(struct xhci_slot_ctx *ctx),
TP_ARGS(ctx),
@@ -432,6 +437,31 @@ DEFINE_EVENT(xhci_log_slot_ctx, xhci_configure_endpoint,
TP_ARGS(ctx)
);
DECLARE_EVENT_CLASS(xhci_log_ctrl_ctx,
TP_PROTO(struct xhci_input_control_ctx *ctrl_ctx),
TP_ARGS(ctrl_ctx),
TP_STRUCT__entry(
__field(u32, drop)
__field(u32, add)
),
TP_fast_assign(
__entry->drop = le32_to_cpu(ctrl_ctx->drop_flags);
__entry->add = le32_to_cpu(ctrl_ctx->add_flags);
),
TP_printk("%s", xhci_decode_ctrl_ctx(__entry->drop, __entry->add)
)
);
DEFINE_EVENT(xhci_log_ctrl_ctx, xhci_address_ctrl_ctx,
TP_PROTO(struct xhci_input_control_ctx *ctrl_ctx),
TP_ARGS(ctrl_ctx)
);
DEFINE_EVENT(xhci_log_ctrl_ctx, xhci_configure_endpoint_ctrl_ctx,
TP_PROTO(struct xhci_input_control_ctx *ctrl_ctx),
TP_ARGS(ctrl_ctx)
);
DECLARE_EVENT_CLASS(xhci_log_ring,
TP_PROTO(struct xhci_ring *ring),
TP_ARGS(ring),

View File

@@ -893,7 +893,7 @@ static void xhci_disable_port_wake_on_bits(struct xhci_hcd *xhci)
struct xhci_port **ports;
int port_index;
unsigned long flags;
u32 t1, t2;
u32 t1, t2, portsc;
spin_lock_irqsave(&xhci->lock, flags);
@@ -902,10 +902,15 @@ static void xhci_disable_port_wake_on_bits(struct xhci_hcd *xhci)
ports = xhci->usb3_rhub.ports;
while (port_index--) {
t1 = readl(ports[port_index]->addr);
portsc = t1;
t1 = xhci_port_state_to_neutral(t1);
t2 = t1 & ~PORT_WAKE_BITS;
if (t1 != t2)
if (t1 != t2) {
writel(t2, ports[port_index]->addr);
xhci_dbg(xhci, "disable wake bits port %d-%d, portsc: 0x%x, write: 0x%x\n",
xhci->usb3_rhub.hcd->self.busnum,
port_index + 1, portsc, t2);
}
}
/* disable usb2 ports Wake bits */
@@ -913,12 +918,16 @@ static void xhci_disable_port_wake_on_bits(struct xhci_hcd *xhci)
ports = xhci->usb2_rhub.ports;
while (port_index--) {
t1 = readl(ports[port_index]->addr);
portsc = t1;
t1 = xhci_port_state_to_neutral(t1);
t2 = t1 & ~PORT_WAKE_BITS;
if (t1 != t2)
if (t1 != t2) {
writel(t2, ports[port_index]->addr);
xhci_dbg(xhci, "disable wake bits port %d-%d, portsc: 0x%x, write: 0x%x\n",
xhci->usb2_rhub.hcd->self.busnum,
port_index + 1, portsc, t2);
}
}
spin_unlock_irqrestore(&xhci->lock, flags);
}
@@ -1238,6 +1247,21 @@ EXPORT_SYMBOL_GPL(xhci_resume);
/*-------------------------------------------------------------------------*/
/*
* Bypass the DMA mapping if URB is suitable for Immediate Transfer (IDT),
* we'll copy the actual data into the TRB address register. This is limited to
* transfers up to 8 bytes on output endpoints of any kind with wMaxPacketSize
* >= 8 bytes. If suitable for IDT only one Transfer TRB per TD is allowed.
*/
static int xhci_map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb,
gfp_t mem_flags)
{
if (xhci_urb_suitable_for_idt(urb))
return 0;
return usb_hcd_map_urb_for_dma(hcd, urb, mem_flags);
}
/**
* xhci_get_endpoint_index - Used for passing endpoint bitmasks between the core and
* HCDs. Find the index for an endpoint given its descriptor. Use the return
@@ -1783,6 +1807,7 @@ static int xhci_add_endpoint(struct usb_hcd *hcd, struct usb_device *udev,
struct xhci_container_ctx *in_ctx;
unsigned int ep_index;
struct xhci_input_control_ctx *ctrl_ctx;
struct xhci_ep_ctx *ep_ctx;
u32 added_ctxs;
u32 new_add_flags, new_drop_flags;
struct xhci_virt_device *virt_dev;
@@ -1873,6 +1898,9 @@ static int xhci_add_endpoint(struct usb_hcd *hcd, struct usb_device *udev,
/* Store the usb_device pointer for later use */
ep->hcpriv = udev;
ep_ctx = xhci_get_ep_ctx(xhci, virt_dev->in_ctx, ep_index);
trace_xhci_add_endpoint(ep_ctx);
xhci_debugfs_create_endpoint(xhci, virt_dev, ep_index);
xhci_dbg(xhci, "add ep 0x%x, slot id %d, new drop flags = %#x, new add flags = %#x\n",
@@ -2747,6 +2775,8 @@ static int xhci_configure_endpoint(struct xhci_hcd *xhci,
}
slot_ctx = xhci_get_slot_ctx(xhci, command->in_ctx);
trace_xhci_configure_endpoint_ctrl_ctx(ctrl_ctx);
trace_xhci_configure_endpoint(slot_ctx);
if (!ctx_change)
@@ -4012,6 +4042,7 @@ static int xhci_setup_device(struct usb_hcd *hcd, struct usb_device *udev,
trace_xhci_address_ctx(xhci, virt_dev->in_ctx,
le32_to_cpu(slot_ctx->dev_info) >> 27);
trace_xhci_address_ctrl_ctx(ctrl_ctx);
spin_lock_irqsave(&xhci->lock, flags);
trace_xhci_setup_device(virt_dev);
ret = xhci_queue_address_device(xhci, command, virt_dev->in_ctx->dma,
@@ -5154,6 +5185,7 @@ static const struct hc_driver xhci_hc_driver = {
/*
* managing i/o requests and associated device resources
*/
.map_urb_for_dma = xhci_map_urb_for_dma,
.urb_enqueue = xhci_urb_enqueue,
.urb_dequeue = xhci_urb_dequeue,
.alloc_dev = xhci_alloc_dev,

View File

@@ -1303,6 +1303,8 @@ enum xhci_setup_dev {
#define TRB_IOC (1<<5)
/* The buffer pointer contains immediate data */
#define TRB_IDT (1<<6)
/* TDs smaller than this might use IDT */
#define TRB_IDT_MAX_SIZE 8
/* Block Event Interrupt */
#define TRB_BEI (1<<9)
@@ -2149,6 +2151,21 @@ static inline struct xhci_ring *xhci_urb_to_transfer_ring(struct xhci_hcd *xhci,
urb->stream_id);
}
/*
* TODO: As per spec Isochronous IDT transmissions are supported. We bypass
* them anyways as we where unable to find a device that matches the
* constraints.
*/
static inline bool xhci_urb_suitable_for_idt(struct urb *urb)
{
if (!usb_endpoint_xfer_isoc(&urb->ep->desc) && usb_urb_dir_out(urb) &&
usb_endpoint_maxp(&urb->ep->desc) >= TRB_IDT_MAX_SIZE &&
urb->transfer_buffer_length <= TRB_IDT_MAX_SIZE)
return true;
return false;
}
static inline char *xhci_slot_state_string(u32 state)
{
switch (state) {
@@ -2384,6 +2401,35 @@ static inline const char *xhci_decode_trb(u32 field0, u32 field1, u32 field2,
return str;
}
static inline const char *xhci_decode_ctrl_ctx(unsigned long drop,
unsigned long add)
{
static char str[1024];
unsigned int bit;
int ret = 0;
if (drop) {
ret = sprintf(str, "Drop:");
for_each_set_bit(bit, &drop, 32)
ret += sprintf(str + ret, " %d%s",
bit / 2,
bit % 2 ? "in":"out");
ret += sprintf(str + ret, ", ");
}
if (add) {
ret += sprintf(str + ret, "Add:%s%s",
(add & SLOT_FLAG) ? " slot":"",
(add & EP0_FLAG) ? " ep0":"");
add &= ~(SLOT_FLAG | EP0_FLAG);
for_each_set_bit(bit, &add, 32)
ret += sprintf(str + ret, " %d%s",
bit / 2,
bit % 2 ? "in":"out");
}
return str;
}
static inline const char *xhci_decode_slot_context(u32 info, u32 info2,
u32 tt_info, u32 state)
{