Merge branch 'for-usb-next' of git+ssh://master.kernel.org/pub/scm/linux/kernel/git/sarah/xhci into usb-next
* 'for-usb-next' of git+ssh://master.kernel.org/pub/scm/linux/kernel/git/sarah/xhci: xhci 1.0: Set transfer burst last packet count field. xhci 1.0: Set transfer burst count field. xhci 1.0: Update TD size field format. xhci 1.0: Only interrupt on short packet for IN EPs. xhci: Remove sparse warning about cmd_status. usbcore: warm reset USB3 port in SS.Inactive state usbcore: Refine USB3.0 device suspend and resume xHCI: report USB3.0 portstatus comply with USB3.0 specification xHCI: Set link state support xHCI: Clear link state change support xHCI: warm reset support usb/ch9: use proper endianess for wBytesPerInterval xhci: Remove recursive call to xhci_handle_event xhci: Add an assertion to check for virt_dev=0 bug. xhci: Add rmb() between reading event validity & event data access. xhci: Make xHCI driver endian-safe
This commit is contained in:
commit
dbc265465a
9 changed files with 763 additions and 449 deletions
|
@ -129,7 +129,7 @@ static void usb_parse_ss_endpoint_companion(struct device *ddev, int cfgno,
|
|||
max_tx = ep->desc.wMaxPacketSize * (desc->bMaxBurst + 1);
|
||||
else
|
||||
max_tx = 999999;
|
||||
if (desc->wBytesPerInterval > max_tx) {
|
||||
if (le16_to_cpu(desc->wBytesPerInterval) > max_tx) {
|
||||
dev_warn(ddev, "%s endpoint with wBytesPerInterval of %d in "
|
||||
"config %d interface %d altsetting %d ep %d: "
|
||||
"setting to %d\n",
|
||||
|
|
|
@ -379,15 +379,6 @@ static int hub_port_status(struct usb_hub *hub, int port1,
|
|||
*status = le16_to_cpu(hub->status->port.wPortStatus);
|
||||
*change = le16_to_cpu(hub->status->port.wPortChange);
|
||||
|
||||
if ((hub->hdev->parent != NULL) &&
|
||||
hub_is_superspeed(hub->hdev)) {
|
||||
/* Translate the USB 3 port status */
|
||||
u16 tmp = *status & USB_SS_PORT_STAT_MASK;
|
||||
if (*status & USB_SS_PORT_STAT_POWER)
|
||||
tmp |= USB_PORT_STAT_POWER;
|
||||
*status = tmp;
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
}
|
||||
mutex_unlock(&hub->status_mutex);
|
||||
|
@ -2160,11 +2151,76 @@ static int hub_port_reset(struct usb_hub *hub, int port1,
|
|||
return status;
|
||||
}
|
||||
|
||||
/* Warm reset a USB3 protocol port */
|
||||
static int hub_port_warm_reset(struct usb_hub *hub, int port)
|
||||
{
|
||||
int ret;
|
||||
u16 portstatus, portchange;
|
||||
|
||||
if (!hub_is_superspeed(hub->hdev)) {
|
||||
dev_err(hub->intfdev, "only USB3 hub support warm reset\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Warm reset the port */
|
||||
ret = set_port_feature(hub->hdev,
|
||||
port, USB_PORT_FEAT_BH_PORT_RESET);
|
||||
if (ret) {
|
||||
dev_err(hub->intfdev, "cannot warm reset port %d\n", port);
|
||||
return ret;
|
||||
}
|
||||
|
||||
msleep(20);
|
||||
ret = hub_port_status(hub, port, &portstatus, &portchange);
|
||||
|
||||
if (portchange & USB_PORT_STAT_C_RESET)
|
||||
clear_port_feature(hub->hdev, port, USB_PORT_FEAT_C_RESET);
|
||||
|
||||
if (portchange & USB_PORT_STAT_C_BH_RESET)
|
||||
clear_port_feature(hub->hdev, port,
|
||||
USB_PORT_FEAT_C_BH_PORT_RESET);
|
||||
|
||||
if (portchange & USB_PORT_STAT_C_LINK_STATE)
|
||||
clear_port_feature(hub->hdev, port,
|
||||
USB_PORT_FEAT_C_PORT_LINK_STATE);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Check if a port is power on */
|
||||
static int port_is_power_on(struct usb_hub *hub, unsigned portstatus)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (hub_is_superspeed(hub->hdev)) {
|
||||
if (portstatus & USB_SS_PORT_STAT_POWER)
|
||||
ret = 1;
|
||||
} else {
|
||||
if (portstatus & USB_PORT_STAT_POWER)
|
||||
ret = 1;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
|
||||
#define MASK_BITS (USB_PORT_STAT_POWER | USB_PORT_STAT_CONNECTION | \
|
||||
USB_PORT_STAT_SUSPEND)
|
||||
#define WANT_BITS (USB_PORT_STAT_POWER | USB_PORT_STAT_CONNECTION)
|
||||
/* Check if a port is suspended(USB2.0 port) or in U3 state(USB3.0 port) */
|
||||
static int port_is_suspended(struct usb_hub *hub, unsigned portstatus)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (hub_is_superspeed(hub->hdev)) {
|
||||
if ((portstatus & USB_PORT_STAT_LINK_STATE)
|
||||
== USB_SS_PORT_LS_U3)
|
||||
ret = 1;
|
||||
} else {
|
||||
if (portstatus & USB_PORT_STAT_SUSPEND)
|
||||
ret = 1;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Determine whether the device on a port is ready for a normal resume,
|
||||
* is ready for a reset-resume, or should be disconnected.
|
||||
|
@ -2174,7 +2230,9 @@ static int check_port_resume_type(struct usb_device *udev,
|
|||
int status, unsigned portchange, unsigned portstatus)
|
||||
{
|
||||
/* Is the device still present? */
|
||||
if (status || (portstatus & MASK_BITS) != WANT_BITS) {
|
||||
if (status || port_is_suspended(hub, portstatus) ||
|
||||
!port_is_power_on(hub, portstatus) ||
|
||||
!(portstatus & USB_PORT_STAT_CONNECTION)) {
|
||||
if (status >= 0)
|
||||
status = -ENODEV;
|
||||
}
|
||||
|
@ -2285,14 +2343,10 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg)
|
|||
}
|
||||
|
||||
/* see 7.1.7.6 */
|
||||
/* Clear PORT_POWER if it's a USB3.0 device connected to USB 3.0
|
||||
* external hub.
|
||||
* FIXME: this is a temporary workaround to make the system able
|
||||
* to suspend/resume.
|
||||
*/
|
||||
if ((hub->hdev->parent != NULL) && hub_is_superspeed(hub->hdev))
|
||||
status = clear_port_feature(hub->hdev, port1,
|
||||
USB_PORT_FEAT_POWER);
|
||||
if (hub_is_superspeed(hub->hdev))
|
||||
status = set_port_feature(hub->hdev,
|
||||
port1 | (USB_SS_PORT_LS_U3 << 3),
|
||||
USB_PORT_FEAT_LINK_STATE);
|
||||
else
|
||||
status = set_port_feature(hub->hdev, port1,
|
||||
USB_PORT_FEAT_SUSPEND);
|
||||
|
@ -2439,7 +2493,7 @@ int usb_port_resume(struct usb_device *udev, pm_message_t msg)
|
|||
|
||||
/* Skip the initial Clear-Suspend step for a remote wakeup */
|
||||
status = hub_port_status(hub, port1, &portstatus, &portchange);
|
||||
if (status == 0 && !(portstatus & USB_PORT_STAT_SUSPEND))
|
||||
if (status == 0 && !port_is_suspended(hub, portstatus))
|
||||
goto SuspendCleared;
|
||||
|
||||
// dev_dbg(hub->intfdev, "resume port %d\n", port1);
|
||||
|
@ -2447,8 +2501,13 @@ int usb_port_resume(struct usb_device *udev, pm_message_t msg)
|
|||
set_bit(port1, hub->busy_bits);
|
||||
|
||||
/* see 7.1.7.7; affects power usage, but not budgeting */
|
||||
status = clear_port_feature(hub->hdev,
|
||||
port1, USB_PORT_FEAT_SUSPEND);
|
||||
if (hub_is_superspeed(hub->hdev))
|
||||
status = set_port_feature(hub->hdev,
|
||||
port1 | (USB_SS_PORT_LS_U0 << 3),
|
||||
USB_PORT_FEAT_LINK_STATE);
|
||||
else
|
||||
status = clear_port_feature(hub->hdev,
|
||||
port1, USB_PORT_FEAT_SUSPEND);
|
||||
if (status) {
|
||||
dev_dbg(hub->intfdev, "can't resume port %d, status %d\n",
|
||||
port1, status);
|
||||
|
@ -2470,9 +2529,15 @@ int usb_port_resume(struct usb_device *udev, pm_message_t msg)
|
|||
|
||||
SuspendCleared:
|
||||
if (status == 0) {
|
||||
if (portchange & USB_PORT_STAT_C_SUSPEND)
|
||||
clear_port_feature(hub->hdev, port1,
|
||||
USB_PORT_FEAT_C_SUSPEND);
|
||||
if (hub_is_superspeed(hub->hdev)) {
|
||||
if (portchange & USB_PORT_STAT_C_LINK_STATE)
|
||||
clear_port_feature(hub->hdev, port1,
|
||||
USB_PORT_FEAT_C_PORT_LINK_STATE);
|
||||
} else {
|
||||
if (portchange & USB_PORT_STAT_C_SUSPEND)
|
||||
clear_port_feature(hub->hdev, port1,
|
||||
USB_PORT_FEAT_C_SUSPEND);
|
||||
}
|
||||
}
|
||||
|
||||
clear_bit(port1, hub->busy_bits);
|
||||
|
@ -3147,7 +3212,7 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
|
|||
|
||||
/* maybe switch power back on (e.g. root hub was reset) */
|
||||
if ((wHubCharacteristics & HUB_CHAR_LPSM) < 2
|
||||
&& !(portstatus & USB_PORT_STAT_POWER))
|
||||
&& !port_is_power_on(hub, portstatus))
|
||||
set_port_feature(hdev, port1, USB_PORT_FEAT_POWER);
|
||||
|
||||
if (portstatus & USB_PORT_STAT_ENABLE)
|
||||
|
@ -3490,6 +3555,16 @@ static void hub_events(void)
|
|||
USB_PORT_FEAT_C_PORT_CONFIG_ERROR);
|
||||
}
|
||||
|
||||
/* Warm reset a USB3 protocol port if it's in
|
||||
* SS.Inactive state.
|
||||
*/
|
||||
if (hub_is_superspeed(hub->hdev) &&
|
||||
(portstatus & USB_PORT_STAT_LINK_STATE)
|
||||
== USB_SS_PORT_LS_SS_INACTIVE) {
|
||||
dev_dbg(hub_dev, "warm reset port %d\n", i);
|
||||
hub_port_warm_reset(hub, i);
|
||||
}
|
||||
|
||||
if (connect_change)
|
||||
hub_port_connect_change(hub, i,
|
||||
portstatus, portchange);
|
||||
|
|
|
@ -147,7 +147,7 @@ static void xhci_print_op_regs(struct xhci_hcd *xhci)
|
|||
|
||||
static void xhci_print_ports(struct xhci_hcd *xhci)
|
||||
{
|
||||
u32 __iomem *addr;
|
||||
__le32 __iomem *addr;
|
||||
int i, j;
|
||||
int ports;
|
||||
char *names[NUM_PORT_REGS] = {
|
||||
|
@ -253,27 +253,27 @@ void xhci_print_trb_offsets(struct xhci_hcd *xhci, union xhci_trb *trb)
|
|||
void xhci_debug_trb(struct xhci_hcd *xhci, union xhci_trb *trb)
|
||||
{
|
||||
u64 address;
|
||||
u32 type = xhci_readl(xhci, &trb->link.control) & TRB_TYPE_BITMASK;
|
||||
u32 type = le32_to_cpu(trb->link.control) & TRB_TYPE_BITMASK;
|
||||
|
||||
switch (type) {
|
||||
case TRB_TYPE(TRB_LINK):
|
||||
xhci_dbg(xhci, "Link TRB:\n");
|
||||
xhci_print_trb_offsets(xhci, trb);
|
||||
|
||||
address = trb->link.segment_ptr;
|
||||
address = le64_to_cpu(trb->link.segment_ptr);
|
||||
xhci_dbg(xhci, "Next ring segment DMA address = 0x%llx\n", address);
|
||||
|
||||
xhci_dbg(xhci, "Interrupter target = 0x%x\n",
|
||||
GET_INTR_TARGET(trb->link.intr_target));
|
||||
GET_INTR_TARGET(le32_to_cpu(trb->link.intr_target)));
|
||||
xhci_dbg(xhci, "Cycle bit = %u\n",
|
||||
(unsigned int) (trb->link.control & TRB_CYCLE));
|
||||
(unsigned int) (le32_to_cpu(trb->link.control) & TRB_CYCLE));
|
||||
xhci_dbg(xhci, "Toggle cycle bit = %u\n",
|
||||
(unsigned int) (trb->link.control & LINK_TOGGLE));
|
||||
(unsigned int) (le32_to_cpu(trb->link.control) & LINK_TOGGLE));
|
||||
xhci_dbg(xhci, "No Snoop bit = %u\n",
|
||||
(unsigned int) (trb->link.control & TRB_NO_SNOOP));
|
||||
(unsigned int) (le32_to_cpu(trb->link.control) & TRB_NO_SNOOP));
|
||||
break;
|
||||
case TRB_TYPE(TRB_TRANSFER):
|
||||
address = trb->trans_event.buffer;
|
||||
address = le64_to_cpu(trb->trans_event.buffer);
|
||||
/*
|
||||
* FIXME: look at flags to figure out if it's an address or if
|
||||
* the data is directly in the buffer field.
|
||||
|
@ -281,11 +281,12 @@ void xhci_debug_trb(struct xhci_hcd *xhci, union xhci_trb *trb)
|
|||
xhci_dbg(xhci, "DMA address or buffer contents= %llu\n", address);
|
||||
break;
|
||||
case TRB_TYPE(TRB_COMPLETION):
|
||||
address = trb->event_cmd.cmd_trb;
|
||||
address = le64_to_cpu(trb->event_cmd.cmd_trb);
|
||||
xhci_dbg(xhci, "Command TRB pointer = %llu\n", address);
|
||||
xhci_dbg(xhci, "Completion status = %u\n",
|
||||
(unsigned int) GET_COMP_CODE(trb->event_cmd.status));
|
||||
xhci_dbg(xhci, "Flags = 0x%x\n", (unsigned int) trb->event_cmd.flags);
|
||||
(unsigned int) GET_COMP_CODE(le32_to_cpu(trb->event_cmd.status)));
|
||||
xhci_dbg(xhci, "Flags = 0x%x\n",
|
||||
(unsigned int) le32_to_cpu(trb->event_cmd.flags));
|
||||
break;
|
||||
default:
|
||||
xhci_dbg(xhci, "Unknown TRB with TRB type ID %u\n",
|
||||
|
@ -311,16 +312,16 @@ void xhci_debug_trb(struct xhci_hcd *xhci, union xhci_trb *trb)
|
|||
void xhci_debug_segment(struct xhci_hcd *xhci, struct xhci_segment *seg)
|
||||
{
|
||||
int i;
|
||||
u32 addr = (u32) seg->dma;
|
||||
u64 addr = seg->dma;
|
||||
union xhci_trb *trb = seg->trbs;
|
||||
|
||||
for (i = 0; i < TRBS_PER_SEGMENT; ++i) {
|
||||
trb = &seg->trbs[i];
|
||||
xhci_dbg(xhci, "@%08x %08x %08x %08x %08x\n", addr,
|
||||
lower_32_bits(trb->link.segment_ptr),
|
||||
upper_32_bits(trb->link.segment_ptr),
|
||||
(unsigned int) trb->link.intr_target,
|
||||
(unsigned int) trb->link.control);
|
||||
xhci_dbg(xhci, "@%016llx %08x %08x %08x %08x\n", addr,
|
||||
(u32)lower_32_bits(le64_to_cpu(trb->link.segment_ptr)),
|
||||
(u32)upper_32_bits(le64_to_cpu(trb->link.segment_ptr)),
|
||||
(unsigned int) le32_to_cpu(trb->link.intr_target),
|
||||
(unsigned int) le32_to_cpu(trb->link.control));
|
||||
addr += sizeof(*trb);
|
||||
}
|
||||
}
|
||||
|
@ -391,18 +392,18 @@ void xhci_dbg_ep_rings(struct xhci_hcd *xhci,
|
|||
|
||||
void xhci_dbg_erst(struct xhci_hcd *xhci, struct xhci_erst *erst)
|
||||
{
|
||||
u32 addr = (u32) erst->erst_dma_addr;
|
||||
u64 addr = erst->erst_dma_addr;
|
||||
int i;
|
||||
struct xhci_erst_entry *entry;
|
||||
|
||||
for (i = 0; i < erst->num_entries; ++i) {
|
||||
entry = &erst->entries[i];
|
||||
xhci_dbg(xhci, "@%08x %08x %08x %08x %08x\n",
|
||||
(unsigned int) addr,
|
||||
lower_32_bits(entry->seg_addr),
|
||||
upper_32_bits(entry->seg_addr),
|
||||
(unsigned int) entry->seg_size,
|
||||
(unsigned int) entry->rsvd);
|
||||
xhci_dbg(xhci, "@%016llx %08x %08x %08x %08x\n",
|
||||
addr,
|
||||
lower_32_bits(le64_to_cpu(entry->seg_addr)),
|
||||
upper_32_bits(le64_to_cpu(entry->seg_addr)),
|
||||
(unsigned int) le32_to_cpu(entry->seg_size),
|
||||
(unsigned int) le32_to_cpu(entry->rsvd));
|
||||
addr += sizeof(*entry);
|
||||
}
|
||||
}
|
||||
|
@ -436,7 +437,7 @@ char *xhci_get_slot_state(struct xhci_hcd *xhci,
|
|||
{
|
||||
struct xhci_slot_ctx *slot_ctx = xhci_get_slot_ctx(xhci, ctx);
|
||||
|
||||
switch (GET_SLOT_STATE(slot_ctx->dev_state)) {
|
||||
switch (GET_SLOT_STATE(le32_to_cpu(slot_ctx->dev_state))) {
|
||||
case 0:
|
||||
return "enabled/disabled";
|
||||
case 1:
|
||||
|
|
|
@ -50,7 +50,7 @@ static void xhci_common_hub_descriptor(struct xhci_hcd *xhci,
|
|||
temp |= 0x0008;
|
||||
/* Bits 6:5 - no TTs in root ports */
|
||||
/* Bit 7 - no port indicators */
|
||||
desc->wHubCharacteristics = (__force __u16) cpu_to_le16(temp);
|
||||
desc->wHubCharacteristics = cpu_to_le16(temp);
|
||||
}
|
||||
|
||||
/* Fill in the USB 2.0 roothub descriptor */
|
||||
|
@ -314,7 +314,7 @@ void xhci_ring_device(struct xhci_hcd *xhci, int slot_id)
|
|||
}
|
||||
|
||||
static void xhci_disable_port(struct usb_hcd *hcd, struct xhci_hcd *xhci,
|
||||
u16 wIndex, u32 __iomem *addr, u32 port_status)
|
||||
u16 wIndex, __le32 __iomem *addr, u32 port_status)
|
||||
{
|
||||
/* Don't allow the USB core to disable SuperSpeed ports. */
|
||||
if (hcd->speed == HCD_USB3) {
|
||||
|
@ -331,7 +331,7 @@ static void xhci_disable_port(struct usb_hcd *hcd, struct xhci_hcd *xhci,
|
|||
}
|
||||
|
||||
static void xhci_clear_port_change_bit(struct xhci_hcd *xhci, u16 wValue,
|
||||
u16 wIndex, u32 __iomem *addr, u32 port_status)
|
||||
u16 wIndex, __le32 __iomem *addr, u32 port_status)
|
||||
{
|
||||
char *port_change_bit;
|
||||
u32 status;
|
||||
|
@ -341,6 +341,10 @@ static void xhci_clear_port_change_bit(struct xhci_hcd *xhci, u16 wValue,
|
|||
status = PORT_RC;
|
||||
port_change_bit = "reset";
|
||||
break;
|
||||
case USB_PORT_FEAT_C_BH_PORT_RESET:
|
||||
status = PORT_WRC;
|
||||
port_change_bit = "warm(BH) reset";
|
||||
break;
|
||||
case USB_PORT_FEAT_C_CONNECTION:
|
||||
status = PORT_CSC;
|
||||
port_change_bit = "connect";
|
||||
|
@ -357,6 +361,10 @@ static void xhci_clear_port_change_bit(struct xhci_hcd *xhci, u16 wValue,
|
|||
status = PORT_PLC;
|
||||
port_change_bit = "suspend/resume";
|
||||
break;
|
||||
case USB_PORT_FEAT_C_PORT_LINK_STATE:
|
||||
status = PORT_PLC;
|
||||
port_change_bit = "link state";
|
||||
break;
|
||||
default:
|
||||
/* Should never happen */
|
||||
return;
|
||||
|
@ -376,9 +384,10 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
|
|||
unsigned long flags;
|
||||
u32 temp, temp1, status;
|
||||
int retval = 0;
|
||||
u32 __iomem **port_array;
|
||||
__le32 __iomem **port_array;
|
||||
int slot_id;
|
||||
struct xhci_bus_state *bus_state;
|
||||
u16 link_state = 0;
|
||||
|
||||
if (hcd->speed == HCD_USB3) {
|
||||
ports = xhci->num_usb3_ports;
|
||||
|
@ -422,9 +431,6 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
|
|||
}
|
||||
xhci_dbg(xhci, "get port status, actual port %d status = 0x%x\n", wIndex, temp);
|
||||
|
||||
/* FIXME - should we return a port status value like the USB
|
||||
* 3.0 external hubs do?
|
||||
*/
|
||||
/* wPortChange bits */
|
||||
if (temp & PORT_CSC)
|
||||
status |= USB_PORT_STAT_C_CONNECTION << 16;
|
||||
|
@ -432,13 +438,21 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
|
|||
status |= USB_PORT_STAT_C_ENABLE << 16;
|
||||
if ((temp & PORT_OCC))
|
||||
status |= USB_PORT_STAT_C_OVERCURRENT << 16;
|
||||
/*
|
||||
* FIXME ignoring reset and USB 2.1/3.0 specific
|
||||
* changes
|
||||
*/
|
||||
if ((temp & PORT_PLS_MASK) == XDEV_U3
|
||||
&& (temp & PORT_POWER))
|
||||
status |= 1 << USB_PORT_FEAT_SUSPEND;
|
||||
if ((temp & PORT_RC))
|
||||
status |= USB_PORT_STAT_C_RESET << 16;
|
||||
/* USB3.0 only */
|
||||
if (hcd->speed == HCD_USB3) {
|
||||
if ((temp & PORT_PLC))
|
||||
status |= USB_PORT_STAT_C_LINK_STATE << 16;
|
||||
if ((temp & PORT_WRC))
|
||||
status |= USB_PORT_STAT_C_BH_RESET << 16;
|
||||
}
|
||||
|
||||
if (hcd->speed != HCD_USB3) {
|
||||
if ((temp & PORT_PLS_MASK) == XDEV_U3
|
||||
&& (temp & PORT_POWER))
|
||||
status |= USB_PORT_STAT_SUSPEND;
|
||||
}
|
||||
if ((temp & PORT_PLS_MASK) == XDEV_RESUME) {
|
||||
if ((temp & PORT_RESET) || !(temp & PORT_PE))
|
||||
goto error;
|
||||
|
@ -469,7 +483,8 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
|
|||
&& (temp & PORT_POWER)
|
||||
&& (bus_state->suspended_ports & (1 << wIndex))) {
|
||||
bus_state->suspended_ports &= ~(1 << wIndex);
|
||||
bus_state->port_c_suspend |= 1 << wIndex;
|
||||
if (hcd->speed != HCD_USB3)
|
||||
bus_state->port_c_suspend |= 1 << wIndex;
|
||||
}
|
||||
if (temp & PORT_CONNECT) {
|
||||
status |= USB_PORT_STAT_CONNECTION;
|
||||
|
@ -481,14 +496,28 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
|
|||
status |= USB_PORT_STAT_OVERCURRENT;
|
||||
if (temp & PORT_RESET)
|
||||
status |= USB_PORT_STAT_RESET;
|
||||
if (temp & PORT_POWER)
|
||||
status |= USB_PORT_STAT_POWER;
|
||||
if (temp & PORT_POWER) {
|
||||
if (hcd->speed == HCD_USB3)
|
||||
status |= USB_SS_PORT_STAT_POWER;
|
||||
else
|
||||
status |= USB_PORT_STAT_POWER;
|
||||
}
|
||||
/* Port Link State */
|
||||
if (hcd->speed == HCD_USB3) {
|
||||
/* resume state is a xHCI internal state.
|
||||
* Do not report it to usb core.
|
||||
*/
|
||||
if ((temp & PORT_PLS_MASK) != XDEV_RESUME)
|
||||
status |= (temp & PORT_PLS_MASK);
|
||||
}
|
||||
if (bus_state->port_c_suspend & (1 << wIndex))
|
||||
status |= 1 << USB_PORT_FEAT_C_SUSPEND;
|
||||
xhci_dbg(xhci, "Get port status returned 0x%x\n", status);
|
||||
put_unaligned(cpu_to_le32(status), (__le32 *) buf);
|
||||
break;
|
||||
case SetPortFeature:
|
||||
if (wValue == USB_PORT_FEAT_LINK_STATE)
|
||||
link_state = (wIndex & 0xff00) >> 3;
|
||||
wIndex &= 0xff;
|
||||
if (!wIndex || wIndex > ports)
|
||||
goto error;
|
||||
|
@ -537,6 +566,44 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
|
|||
temp = xhci_readl(xhci, port_array[wIndex]);
|
||||
bus_state->suspended_ports |= 1 << wIndex;
|
||||
break;
|
||||
case USB_PORT_FEAT_LINK_STATE:
|
||||
temp = xhci_readl(xhci, port_array[wIndex]);
|
||||
/* Software should not attempt to set
|
||||
* port link state above '5' (Rx.Detect) and the port
|
||||
* must be enabled.
|
||||
*/
|
||||
if ((temp & PORT_PE) == 0 ||
|
||||
(link_state > USB_SS_PORT_LS_RX_DETECT)) {
|
||||
xhci_warn(xhci, "Cannot set link state.\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (link_state == USB_SS_PORT_LS_U3) {
|
||||
slot_id = xhci_find_slot_id_by_port(hcd, xhci,
|
||||
wIndex + 1);
|
||||
if (slot_id) {
|
||||
/* unlock to execute stop endpoint
|
||||
* commands */
|
||||
spin_unlock_irqrestore(&xhci->lock,
|
||||
flags);
|
||||
xhci_stop_device(xhci, slot_id, 1);
|
||||
spin_lock_irqsave(&xhci->lock, flags);
|
||||
}
|
||||
}
|
||||
|
||||
temp = xhci_port_state_to_neutral(temp);
|
||||
temp &= ~PORT_PLS_MASK;
|
||||
temp |= PORT_LINK_STROBE | link_state;
|
||||
xhci_writel(xhci, temp, port_array[wIndex]);
|
||||
|
||||
spin_unlock_irqrestore(&xhci->lock, flags);
|
||||
msleep(20); /* wait device to enter */
|
||||
spin_lock_irqsave(&xhci->lock, flags);
|
||||
|
||||
temp = xhci_readl(xhci, port_array[wIndex]);
|
||||
if (link_state == USB_SS_PORT_LS_U3)
|
||||
bus_state->suspended_ports |= 1 << wIndex;
|
||||
break;
|
||||
case USB_PORT_FEAT_POWER:
|
||||
/*
|
||||
* Turn on ports, even if there isn't per-port switching.
|
||||
|
@ -557,6 +624,12 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
|
|||
temp = xhci_readl(xhci, port_array[wIndex]);
|
||||
xhci_dbg(xhci, "set port reset, actual port %d status = 0x%x\n", wIndex, temp);
|
||||
break;
|
||||
case USB_PORT_FEAT_BH_PORT_RESET:
|
||||
temp |= PORT_WR;
|
||||
xhci_writel(xhci, temp, port_array[wIndex]);
|
||||
|
||||
temp = xhci_readl(xhci, port_array[wIndex]);
|
||||
break;
|
||||
default:
|
||||
goto error;
|
||||
}
|
||||
|
@ -584,35 +657,27 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
|
|||
if (temp & XDEV_U3) {
|
||||
if ((temp & PORT_PE) == 0)
|
||||
goto error;
|
||||
if (DEV_SUPERSPEED(temp)) {
|
||||
temp = xhci_port_state_to_neutral(temp);
|
||||
temp &= ~PORT_PLS_MASK;
|
||||
temp |= PORT_LINK_STROBE | XDEV_U0;
|
||||
xhci_writel(xhci, temp,
|
||||
port_array[wIndex]);
|
||||
xhci_readl(xhci, port_array[wIndex]);
|
||||
} else {
|
||||
temp = xhci_port_state_to_neutral(temp);
|
||||
temp &= ~PORT_PLS_MASK;
|
||||
temp |= PORT_LINK_STROBE | XDEV_RESUME;
|
||||
xhci_writel(xhci, temp,
|
||||
port_array[wIndex]);
|
||||
|
||||
spin_unlock_irqrestore(&xhci->lock,
|
||||
flags);
|
||||
msleep(20);
|
||||
spin_lock_irqsave(&xhci->lock, flags);
|
||||
temp = xhci_port_state_to_neutral(temp);
|
||||
temp &= ~PORT_PLS_MASK;
|
||||
temp |= PORT_LINK_STROBE | XDEV_RESUME;
|
||||
xhci_writel(xhci, temp,
|
||||
port_array[wIndex]);
|
||||
|
||||
temp = xhci_readl(xhci,
|
||||
port_array[wIndex]);
|
||||
temp = xhci_port_state_to_neutral(temp);
|
||||
temp &= ~PORT_PLS_MASK;
|
||||
temp |= PORT_LINK_STROBE | XDEV_U0;
|
||||
xhci_writel(xhci, temp,
|
||||
port_array[wIndex]);
|
||||
}
|
||||
bus_state->port_c_suspend |= 1 << wIndex;
|
||||
spin_unlock_irqrestore(&xhci->lock,
|
||||
flags);
|
||||
msleep(20);
|
||||
spin_lock_irqsave(&xhci->lock, flags);
|
||||
|
||||
temp = xhci_readl(xhci,
|
||||
port_array[wIndex]);
|
||||
temp = xhci_port_state_to_neutral(temp);
|
||||
temp &= ~PORT_PLS_MASK;
|
||||
temp |= PORT_LINK_STROBE | XDEV_U0;
|
||||
xhci_writel(xhci, temp,
|
||||
port_array[wIndex]);
|
||||
}
|
||||
bus_state->port_c_suspend |= 1 << wIndex;
|
||||
|
||||
slot_id = xhci_find_slot_id_by_port(hcd, xhci,
|
||||
wIndex + 1);
|
||||
|
@ -625,9 +690,11 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
|
|||
case USB_PORT_FEAT_C_SUSPEND:
|
||||
bus_state->port_c_suspend &= ~(1 << wIndex);
|
||||
case USB_PORT_FEAT_C_RESET:
|
||||
case USB_PORT_FEAT_C_BH_PORT_RESET:
|
||||
case USB_PORT_FEAT_C_CONNECTION:
|
||||
case USB_PORT_FEAT_C_OVER_CURRENT:
|
||||
case USB_PORT_FEAT_C_ENABLE:
|
||||
case USB_PORT_FEAT_C_PORT_LINK_STATE:
|
||||
xhci_clear_port_change_bit(xhci, wValue, wIndex,
|
||||
port_array[wIndex], temp);
|
||||
break;
|
||||
|
@ -664,7 +731,7 @@ int xhci_hub_status_data(struct usb_hcd *hcd, char *buf)
|
|||
int i, retval;
|
||||
struct xhci_hcd *xhci = hcd_to_xhci(hcd);
|
||||
int ports;
|
||||
u32 __iomem **port_array;
|
||||
__le32 __iomem **port_array;
|
||||
struct xhci_bus_state *bus_state;
|
||||
|
||||
if (hcd->speed == HCD_USB3) {
|
||||
|
@ -681,7 +748,7 @@ int xhci_hub_status_data(struct usb_hcd *hcd, char *buf)
|
|||
memset(buf, 0, retval);
|
||||
status = 0;
|
||||
|
||||
mask = PORT_CSC | PORT_PEC | PORT_OCC;
|
||||
mask = PORT_CSC | PORT_PEC | PORT_OCC | PORT_PLC;
|
||||
|
||||
spin_lock_irqsave(&xhci->lock, flags);
|
||||
/* For each port, did anything change? If so, set that bit in buf. */
|
||||
|
@ -709,7 +776,7 @@ int xhci_bus_suspend(struct usb_hcd *hcd)
|
|||
{
|
||||
struct xhci_hcd *xhci = hcd_to_xhci(hcd);
|
||||
int max_ports, port_index;
|
||||
u32 __iomem **port_array;
|
||||
__le32 __iomem **port_array;
|
||||
struct xhci_bus_state *bus_state;
|
||||
unsigned long flags;
|
||||
|
||||
|
@ -779,7 +846,7 @@ int xhci_bus_suspend(struct usb_hcd *hcd)
|
|||
|
||||
if (DEV_HIGHSPEED(t1)) {
|
||||
/* enable remote wake up for USB 2.0 */
|
||||
u32 __iomem *addr;
|
||||
__le32 __iomem *addr;
|
||||
u32 tmp;
|
||||
|
||||
/* Add one to the port status register address to get
|
||||
|
@ -801,7 +868,7 @@ int xhci_bus_resume(struct usb_hcd *hcd)
|
|||
{
|
||||
struct xhci_hcd *xhci = hcd_to_xhci(hcd);
|
||||
int max_ports, port_index;
|
||||
u32 __iomem **port_array;
|
||||
__le32 __iomem **port_array;
|
||||
struct xhci_bus_state *bus_state;
|
||||
u32 temp;
|
||||
unsigned long flags;
|
||||
|
@ -875,7 +942,7 @@ int xhci_bus_resume(struct usb_hcd *hcd)
|
|||
|
||||
if (DEV_HIGHSPEED(temp)) {
|
||||
/* disable remote wake up for USB 2.0 */
|
||||
u32 __iomem *addr;
|
||||
__le32 __iomem *addr;
|
||||
u32 tmp;
|
||||
|
||||
/* Add one to the port status register address to get
|
||||
|
|
|
@ -89,16 +89,17 @@ static void xhci_link_segments(struct xhci_hcd *xhci, struct xhci_segment *prev,
|
|||
return;
|
||||
prev->next = next;
|
||||
if (link_trbs) {
|
||||
prev->trbs[TRBS_PER_SEGMENT-1].link.segment_ptr = next->dma;
|
||||
prev->trbs[TRBS_PER_SEGMENT-1].link.
|
||||
segment_ptr = cpu_to_le64(next->dma);
|
||||
|
||||
/* Set the last TRB in the segment to have a TRB type ID of Link TRB */
|
||||
val = prev->trbs[TRBS_PER_SEGMENT-1].link.control;
|
||||
val = le32_to_cpu(prev->trbs[TRBS_PER_SEGMENT-1].link.control);
|
||||
val &= ~TRB_TYPE_BITMASK;
|
||||
val |= TRB_TYPE(TRB_LINK);
|
||||
/* Always set the chain bit with 0.95 hardware */
|
||||
if (xhci_link_trb_quirk(xhci))
|
||||
val |= TRB_CHAIN;
|
||||
prev->trbs[TRBS_PER_SEGMENT-1].link.control = val;
|
||||
prev->trbs[TRBS_PER_SEGMENT-1].link.control = cpu_to_le32(val);
|
||||
}
|
||||
xhci_dbg(xhci, "Linking segment 0x%llx to segment 0x%llx (DMA)\n",
|
||||
(unsigned long long)prev->dma,
|
||||
|
@ -186,7 +187,8 @@ static struct xhci_ring *xhci_ring_alloc(struct xhci_hcd *xhci,
|
|||
|
||||
if (link_trbs) {
|
||||
/* See section 4.9.2.1 and 6.4.4.1 */
|
||||
prev->trbs[TRBS_PER_SEGMENT-1].link.control |= (LINK_TOGGLE);
|
||||
prev->trbs[TRBS_PER_SEGMENT-1].link.
|
||||
control |= cpu_to_le32(LINK_TOGGLE);
|
||||
xhci_dbg(xhci, "Wrote link toggle flag to"
|
||||
" segment %p (virtual), 0x%llx (DMA)\n",
|
||||
prev, (unsigned long long)prev->dma);
|
||||
|
@ -548,7 +550,8 @@ struct xhci_stream_info *xhci_alloc_stream_info(struct xhci_hcd *xhci,
|
|||
addr = cur_ring->first_seg->dma |
|
||||
SCT_FOR_CTX(SCT_PRI_TR) |
|
||||
cur_ring->cycle_state;
|
||||
stream_info->stream_ctx_array[cur_stream].stream_ring = addr;
|
||||
stream_info->stream_ctx_array[cur_stream].
|
||||
stream_ring = cpu_to_le64(addr);
|
||||
xhci_dbg(xhci, "Setting stream %d ring ptr to 0x%08llx\n",
|
||||
cur_stream, (unsigned long long) addr);
|
||||
|
||||
|
@ -614,10 +617,10 @@ void xhci_setup_streams_ep_input_ctx(struct xhci_hcd *xhci,
|
|||
max_primary_streams = fls(stream_info->num_stream_ctxs) - 2;
|
||||
xhci_dbg(xhci, "Setting number of stream ctx array entries to %u\n",
|
||||
1 << (max_primary_streams + 1));
|
||||
ep_ctx->ep_info &= ~EP_MAXPSTREAMS_MASK;
|
||||
ep_ctx->ep_info |= EP_MAXPSTREAMS(max_primary_streams);
|
||||
ep_ctx->ep_info |= EP_HAS_LSA;
|
||||
ep_ctx->deq = stream_info->ctx_array_dma;
|
||||
ep_ctx->ep_info &= cpu_to_le32(~EP_MAXPSTREAMS_MASK);
|
||||
ep_ctx->ep_info |= cpu_to_le32(EP_MAXPSTREAMS(max_primary_streams)
|
||||
| EP_HAS_LSA);
|
||||
ep_ctx->deq = cpu_to_le64(stream_info->ctx_array_dma);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -630,10 +633,9 @@ void xhci_setup_no_streams_ep_input_ctx(struct xhci_hcd *xhci,
|
|||
struct xhci_virt_ep *ep)
|
||||
{
|
||||
dma_addr_t addr;
|
||||
ep_ctx->ep_info &= ~EP_MAXPSTREAMS_MASK;
|
||||
ep_ctx->ep_info &= ~EP_HAS_LSA;
|
||||
ep_ctx->ep_info &= cpu_to_le32(~(EP_MAXPSTREAMS_MASK | EP_HAS_LSA));
|
||||
addr = xhci_trb_virt_to_dma(ep->ring->deq_seg, ep->ring->dequeue);
|
||||
ep_ctx->deq = addr | ep->ring->cycle_state;
|
||||
ep_ctx->deq = cpu_to_le64(addr | ep->ring->cycle_state);
|
||||
}
|
||||
|
||||
/* Frees all stream contexts associated with the endpoint,
|
||||
|
@ -781,11 +783,11 @@ int xhci_alloc_virt_device(struct xhci_hcd *xhci, int slot_id,
|
|||
dev->udev = udev;
|
||||
|
||||
/* Point to output device context in dcbaa. */
|
||||
xhci->dcbaa->dev_context_ptrs[slot_id] = dev->out_ctx->dma;
|
||||
xhci->dcbaa->dev_context_ptrs[slot_id] = cpu_to_le64(dev->out_ctx->dma);
|
||||
xhci_dbg(xhci, "Set slot id %d dcbaa entry %p to 0x%llx\n",
|
||||
slot_id,
|
||||
&xhci->dcbaa->dev_context_ptrs[slot_id],
|
||||
(unsigned long long) xhci->dcbaa->dev_context_ptrs[slot_id]);
|
||||
slot_id,
|
||||
&xhci->dcbaa->dev_context_ptrs[slot_id],
|
||||
(unsigned long long) le64_to_cpu(xhci->dcbaa->dev_context_ptrs[slot_id]));
|
||||
|
||||
return 1;
|
||||
fail:
|
||||
|
@ -810,8 +812,9 @@ void xhci_copy_ep0_dequeue_into_input_ctx(struct xhci_hcd *xhci,
|
|||
* configured device has reset, so all control transfers should have
|
||||
* been completed or cancelled before the reset.
|
||||
*/
|
||||
ep0_ctx->deq = xhci_trb_virt_to_dma(ep_ring->enq_seg, ep_ring->enqueue);
|
||||
ep0_ctx->deq |= ep_ring->cycle_state;
|
||||
ep0_ctx->deq = cpu_to_le64(xhci_trb_virt_to_dma(ep_ring->enq_seg,
|
||||
ep_ring->enqueue)
|
||||
| ep_ring->cycle_state);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -885,24 +888,22 @@ int xhci_setup_addressable_virt_dev(struct xhci_hcd *xhci, struct usb_device *ud
|
|||
slot_ctx = xhci_get_slot_ctx(xhci, dev->in_ctx);
|
||||
|
||||
/* 2) New slot context and endpoint 0 context are valid*/
|
||||
ctrl_ctx->add_flags = SLOT_FLAG | EP0_FLAG;
|
||||
ctrl_ctx->add_flags = cpu_to_le32(SLOT_FLAG | EP0_FLAG);
|
||||
|
||||
/* 3) Only the control endpoint is valid - one endpoint context */
|
||||
slot_ctx->dev_info |= LAST_CTX(1);
|
||||
|
||||
slot_ctx->dev_info |= (u32) udev->route;
|
||||
slot_ctx->dev_info |= cpu_to_le32(LAST_CTX(1) | (u32) udev->route);
|
||||
switch (udev->speed) {
|
||||
case USB_SPEED_SUPER:
|
||||
slot_ctx->dev_info |= (u32) SLOT_SPEED_SS;
|
||||
slot_ctx->dev_info |= cpu_to_le32((u32) SLOT_SPEED_SS);
|
||||
break;
|
||||
case USB_SPEED_HIGH:
|
||||
slot_ctx->dev_info |= (u32) SLOT_SPEED_HS;
|
||||
slot_ctx->dev_info |= cpu_to_le32((u32) SLOT_SPEED_HS);
|
||||
break;
|
||||
case USB_SPEED_FULL:
|
||||
slot_ctx->dev_info |= (u32) SLOT_SPEED_FS;
|
||||
slot_ctx->dev_info |= cpu_to_le32((u32) SLOT_SPEED_FS);
|
||||
break;
|
||||
case USB_SPEED_LOW:
|
||||
slot_ctx->dev_info |= (u32) SLOT_SPEED_LS;
|
||||
slot_ctx->dev_info |= cpu_to_le32((u32) SLOT_SPEED_LS);
|
||||
break;
|
||||
case USB_SPEED_WIRELESS:
|
||||
xhci_dbg(xhci, "FIXME xHCI doesn't support wireless speeds\n");
|
||||
|
@ -916,7 +917,7 @@ int xhci_setup_addressable_virt_dev(struct xhci_hcd *xhci, struct usb_device *ud
|
|||
port_num = xhci_find_real_port_number(xhci, udev);
|
||||
if (!port_num)
|
||||
return -EINVAL;
|
||||
slot_ctx->dev_info2 |= (u32) ROOT_HUB_PORT(port_num);
|
||||
slot_ctx->dev_info2 |= cpu_to_le32((u32) ROOT_HUB_PORT(port_num));
|
||||
/* Set the port number in the virtual_device to the faked port number */
|
||||
for (top_dev = udev; top_dev->parent && top_dev->parent->parent;
|
||||
top_dev = top_dev->parent)
|
||||
|
@ -927,31 +928,31 @@ int xhci_setup_addressable_virt_dev(struct xhci_hcd *xhci, struct usb_device *ud
|
|||
|
||||
/* Is this a LS/FS device under an external HS hub? */
|
||||
if (udev->tt && udev->tt->hub->parent) {
|
||||
slot_ctx->tt_info = udev->tt->hub->slot_id;
|
||||
slot_ctx->tt_info |= udev->ttport << 8;
|
||||
slot_ctx->tt_info = cpu_to_le32(udev->tt->hub->slot_id |
|
||||
(udev->ttport << 8));
|
||||
if (udev->tt->multi)
|
||||
slot_ctx->dev_info |= DEV_MTT;
|
||||
slot_ctx->dev_info |= cpu_to_le32(DEV_MTT);
|
||||
}
|
||||
xhci_dbg(xhci, "udev->tt = %p\n", udev->tt);
|
||||
xhci_dbg(xhci, "udev->ttport = 0x%x\n", udev->ttport);
|
||||
|
||||
/* Step 4 - ring already allocated */
|
||||
/* Step 5 */
|
||||
ep0_ctx->ep_info2 = EP_TYPE(CTRL_EP);
|
||||
ep0_ctx->ep_info2 = cpu_to_le32(EP_TYPE(CTRL_EP));
|
||||
/*
|
||||
* XXX: Not sure about wireless USB devices.
|
||||
*/
|
||||
switch (udev->speed) {
|
||||
case USB_SPEED_SUPER:
|
||||
ep0_ctx->ep_info2 |= MAX_PACKET(512);
|
||||
ep0_ctx->ep_info2 |= cpu_to_le32(MAX_PACKET(512));
|
||||
break;
|
||||
case USB_SPEED_HIGH:
|
||||
/* USB core guesses at a 64-byte max packet first for FS devices */
|
||||
case USB_SPEED_FULL:
|
||||
ep0_ctx->ep_info2 |= MAX_PACKET(64);
|
||||
ep0_ctx->ep_info2 |= cpu_to_le32(MAX_PACKET(64));
|
||||
break;
|
||||
case USB_SPEED_LOW:
|
||||
ep0_ctx->ep_info2 |= MAX_PACKET(8);
|
||||
ep0_ctx->ep_info2 |= cpu_to_le32(MAX_PACKET(8));
|
||||
break;
|
||||
case USB_SPEED_WIRELESS:
|
||||
xhci_dbg(xhci, "FIXME xHCI doesn't support wireless speeds\n");
|
||||
|
@ -962,12 +963,10 @@ int xhci_setup_addressable_virt_dev(struct xhci_hcd *xhci, struct usb_device *ud
|
|||
BUG();
|
||||
}
|
||||
/* EP 0 can handle "burst" sizes of 1, so Max Burst Size field is 0 */
|
||||
ep0_ctx->ep_info2 |= MAX_BURST(0);
|
||||
ep0_ctx->ep_info2 |= ERROR_COUNT(3);
|
||||
ep0_ctx->ep_info2 |= cpu_to_le32(MAX_BURST(0) | ERROR_COUNT(3));
|
||||
|
||||
ep0_ctx->deq =
|
||||
dev->eps[0].ring->first_seg->dma;
|
||||
ep0_ctx->deq |= dev->eps[0].ring->cycle_state;
|
||||
ep0_ctx->deq = cpu_to_le64(dev->eps[0].ring->first_seg->dma |
|
||||
dev->eps[0].ring->cycle_state);
|
||||
|
||||
/* Steps 7 and 8 were done in xhci_alloc_virt_device() */
|
||||
|
||||
|
@ -1131,10 +1130,10 @@ static u32 xhci_get_max_esit_payload(struct xhci_hcd *xhci,
|
|||
return 0;
|
||||
|
||||
if (udev->speed == USB_SPEED_SUPER)
|
||||
return ep->ss_ep_comp.wBytesPerInterval;
|
||||
return le16_to_cpu(ep->ss_ep_comp.wBytesPerInterval);
|
||||
|
||||
max_packet = GET_MAX_PACKET(ep->desc.wMaxPacketSize);
|
||||
max_burst = (ep->desc.wMaxPacketSize & 0x1800) >> 11;
|
||||
max_packet = GET_MAX_PACKET(le16_to_cpu(ep->desc.wMaxPacketSize));
|
||||
max_burst = (le16_to_cpu(ep->desc.wMaxPacketSize) & 0x1800) >> 11;
|
||||
/* A 0 in max burst means 1 transfer per ESIT */
|
||||
return max_packet * (max_burst + 1);
|
||||
}
|
||||
|
@ -1183,10 +1182,10 @@ int xhci_endpoint_init(struct xhci_hcd *xhci,
|
|||
}
|
||||
virt_dev->eps[ep_index].skip = false;
|
||||
ep_ring = virt_dev->eps[ep_index].new_ring;
|
||||
ep_ctx->deq = ep_ring->first_seg->dma | ep_ring->cycle_state;
|
||||
ep_ctx->deq = cpu_to_le64(ep_ring->first_seg->dma | ep_ring->cycle_state);
|
||||
|
||||
ep_ctx->ep_info = xhci_get_endpoint_interval(udev, ep);
|
||||
ep_ctx->ep_info |= EP_MULT(xhci_get_endpoint_mult(udev, ep));
|
||||
ep_ctx->ep_info = cpu_to_le32(xhci_get_endpoint_interval(udev, ep)
|
||||
| EP_MULT(xhci_get_endpoint_mult(udev, ep)));
|
||||
|
||||
/* FIXME dig Mult and streams info out of ep companion desc */
|
||||
|
||||
|
@ -1194,22 +1193,22 @@ int xhci_endpoint_init(struct xhci_hcd *xhci,
|
|||
* error count = 0 means infinite retries.
|
||||
*/
|
||||
if (!usb_endpoint_xfer_isoc(&ep->desc))
|
||||
ep_ctx->ep_info2 = ERROR_COUNT(3);
|
||||
ep_ctx->ep_info2 = cpu_to_le32(ERROR_COUNT(3));
|
||||
else
|
||||
ep_ctx->ep_info2 = ERROR_COUNT(1);
|
||||
ep_ctx->ep_info2 = cpu_to_le32(ERROR_COUNT(1));
|
||||
|
||||
ep_ctx->ep_info2 |= xhci_get_endpoint_type(udev, ep);
|
||||
ep_ctx->ep_info2 |= cpu_to_le32(xhci_get_endpoint_type(udev, ep));
|
||||
|
||||
/* Set the max packet size and max burst */
|
||||
switch (udev->speed) {
|
||||
case USB_SPEED_SUPER:
|
||||
max_packet = ep->desc.wMaxPacketSize;
|
||||
ep_ctx->ep_info2 |= MAX_PACKET(max_packet);
|
||||
max_packet = le16_to_cpu(ep->desc.wMaxPacketSize);
|
||||
ep_ctx->ep_info2 |= cpu_to_le32(MAX_PACKET(max_packet));
|
||||
/* dig out max burst from ep companion desc */
|
||||
max_packet = ep->ss_ep_comp.bMaxBurst;
|
||||
if (!max_packet)
|
||||
xhci_warn(xhci, "WARN no SS endpoint bMaxBurst\n");
|
||||
ep_ctx->ep_info2 |= MAX_BURST(max_packet);
|
||||
ep_ctx->ep_info2 |= cpu_to_le32(MAX_BURST(max_packet));
|
||||
break;
|
||||
case USB_SPEED_HIGH:
|
||||
/* bits 11:12 specify the number of additional transaction
|
||||
|
@ -1217,20 +1216,21 @@ int xhci_endpoint_init(struct xhci_hcd *xhci,
|
|||
*/
|
||||
if (usb_endpoint_xfer_isoc(&ep->desc) ||
|
||||
usb_endpoint_xfer_int(&ep->desc)) {
|
||||
max_burst = (ep->desc.wMaxPacketSize & 0x1800) >> 11;
|
||||
ep_ctx->ep_info2 |= MAX_BURST(max_burst);
|
||||
max_burst = (le16_to_cpu(ep->desc.wMaxPacketSize)
|
||||
& 0x1800) >> 11;
|
||||
ep_ctx->ep_info2 |= cpu_to_le32(MAX_BURST(max_burst));
|
||||
}
|
||||
/* Fall through */
|
||||
case USB_SPEED_FULL:
|
||||
case USB_SPEED_LOW:
|
||||
max_packet = GET_MAX_PACKET(ep->desc.wMaxPacketSize);
|
||||
ep_ctx->ep_info2 |= MAX_PACKET(max_packet);
|
||||
max_packet = GET_MAX_PACKET(le16_to_cpu(ep->desc.wMaxPacketSize));
|
||||
ep_ctx->ep_info2 |= cpu_to_le32(MAX_PACKET(max_packet));
|
||||
break;
|
||||
default:
|
||||
BUG();
|
||||
}
|
||||
max_esit_payload = xhci_get_max_esit_payload(xhci, udev, ep);
|
||||
ep_ctx->tx_info = MAX_ESIT_PAYLOAD_FOR_EP(max_esit_payload);
|
||||
ep_ctx->tx_info = cpu_to_le32(MAX_ESIT_PAYLOAD_FOR_EP(max_esit_payload));
|
||||
|
||||
/*
|
||||
* XXX no idea how to calculate the average TRB buffer length for bulk
|
||||
|
@ -1247,7 +1247,7 @@ int xhci_endpoint_init(struct xhci_hcd *xhci,
|
|||
* use Event Data TRBs, and we don't chain in a link TRB on short
|
||||
* transfers, we're basically dividing by 1.
|
||||
*/
|
||||
ep_ctx->tx_info |= AVG_TRB_LENGTH_FOR_EP(max_esit_payload);
|
||||
ep_ctx->tx_info |= cpu_to_le32(AVG_TRB_LENGTH_FOR_EP(max_esit_payload));
|
||||
|
||||
/* FIXME Debug endpoint context */
|
||||
return 0;
|
||||
|
@ -1347,7 +1347,7 @@ static int scratchpad_alloc(struct xhci_hcd *xhci, gfp_t flags)
|
|||
if (!xhci->scratchpad->sp_dma_buffers)
|
||||
goto fail_sp4;
|
||||
|
||||
xhci->dcbaa->dev_context_ptrs[0] = xhci->scratchpad->sp_dma;
|
||||
xhci->dcbaa->dev_context_ptrs[0] = cpu_to_le64(xhci->scratchpad->sp_dma);
|
||||
for (i = 0; i < num_sp; i++) {
|
||||
dma_addr_t dma;
|
||||
void *buf = pci_alloc_consistent(to_pci_dev(dev),
|
||||
|
@ -1724,7 +1724,7 @@ static void xhci_set_hc_event_deq(struct xhci_hcd *xhci)
|
|||
}
|
||||
|
||||
static void xhci_add_in_port(struct xhci_hcd *xhci, unsigned int num_ports,
|
||||
u32 __iomem *addr, u8 major_revision)
|
||||
__le32 __iomem *addr, u8 major_revision)
|
||||
{
|
||||
u32 temp, port_offset, port_count;
|
||||
int i;
|
||||
|
@ -1789,7 +1789,7 @@ static void xhci_add_in_port(struct xhci_hcd *xhci, unsigned int num_ports,
|
|||
*/
|
||||
static int xhci_setup_port_arrays(struct xhci_hcd *xhci, gfp_t flags)
|
||||
{
|
||||
u32 __iomem *addr;
|
||||
__le32 __iomem *addr;
|
||||
u32 offset;
|
||||
unsigned int num_ports;
|
||||
int i, port_index;
|
||||
|
@ -2042,8 +2042,8 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
|
|||
/* set ring base address and size for each segment table entry */
|
||||
for (val = 0, seg = xhci->event_ring->first_seg; val < ERST_NUM_SEGS; val++) {
|
||||
struct xhci_erst_entry *entry = &xhci->erst.entries[val];
|
||||
entry->seg_addr = seg->dma;
|
||||
entry->seg_size = TRBS_PER_SEGMENT;
|
||||
entry->seg_addr = cpu_to_le64(seg->dma);
|
||||
entry->seg_size = cpu_to_le32(TRBS_PER_SEGMENT);
|
||||
entry->rsvd = 0;
|
||||
seg = seg->next;
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -973,8 +973,8 @@ static int xhci_check_maxpacket(struct xhci_hcd *xhci, unsigned int slot_id,
|
|||
|
||||
out_ctx = xhci->devs[slot_id]->out_ctx;
|
||||
ep_ctx = xhci_get_ep_ctx(xhci, out_ctx, ep_index);
|
||||
hw_max_packet_size = MAX_PACKET_DECODED(ep_ctx->ep_info2);
|
||||
max_packet_size = urb->dev->ep0.desc.wMaxPacketSize;
|
||||
hw_max_packet_size = MAX_PACKET_DECODED(le32_to_cpu(ep_ctx->ep_info2));
|
||||
max_packet_size = le16_to_cpu(urb->dev->ep0.desc.wMaxPacketSize);
|
||||
if (hw_max_packet_size != max_packet_size) {
|
||||
xhci_dbg(xhci, "Max Packet Size for ep 0 changed.\n");
|
||||
xhci_dbg(xhci, "Max packet size in usb_device = %d\n",
|
||||
|
@ -988,15 +988,15 @@ static int xhci_check_maxpacket(struct xhci_hcd *xhci, unsigned int slot_id,
|
|||
xhci->devs[slot_id]->out_ctx, ep_index);
|
||||
in_ctx = xhci->devs[slot_id]->in_ctx;
|
||||
ep_ctx = xhci_get_ep_ctx(xhci, in_ctx, ep_index);
|
||||
ep_ctx->ep_info2 &= ~MAX_PACKET_MASK;
|
||||
ep_ctx->ep_info2 |= MAX_PACKET(max_packet_size);
|
||||
ep_ctx->ep_info2 &= cpu_to_le32(~MAX_PACKET_MASK);
|
||||
ep_ctx->ep_info2 |= cpu_to_le32(MAX_PACKET(max_packet_size));
|
||||
|
||||
/* Set up the input context flags for the command */
|
||||
/* FIXME: This won't work if a non-default control endpoint
|
||||
* changes max packet sizes.
|
||||
*/
|
||||
ctrl_ctx = xhci_get_input_control_ctx(xhci, in_ctx);
|
||||
ctrl_ctx->add_flags = EP0_FLAG;
|
||||
ctrl_ctx->add_flags = cpu_to_le32(EP0_FLAG);
|
||||
ctrl_ctx->drop_flags = 0;
|
||||
|
||||
xhci_dbg(xhci, "Slot %d input context\n", slot_id);
|
||||
|
@ -1010,7 +1010,7 @@ static int xhci_check_maxpacket(struct xhci_hcd *xhci, unsigned int slot_id,
|
|||
/* Clean up the input context for later use by bandwidth
|
||||
* functions.
|
||||
*/
|
||||
ctrl_ctx->add_flags = SLOT_FLAG;
|
||||
ctrl_ctx->add_flags = cpu_to_le32(SLOT_FLAG);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
@ -1331,27 +1331,30 @@ int xhci_drop_endpoint(struct usb_hcd *hcd, struct usb_device *udev,
|
|||
/* If the HC already knows the endpoint is disabled,
|
||||
* or the HCD has noted it is disabled, ignore this request
|
||||
*/
|
||||
if ((ep_ctx->ep_info & EP_STATE_MASK) == EP_STATE_DISABLED ||
|
||||
ctrl_ctx->drop_flags & xhci_get_endpoint_flag(&ep->desc)) {
|
||||
if ((le32_to_cpu(ep_ctx->ep_info) & EP_STATE_MASK) ==
|
||||
EP_STATE_DISABLED ||
|
||||
le32_to_cpu(ctrl_ctx->drop_flags) &
|
||||
xhci_get_endpoint_flag(&ep->desc)) {
|
||||
xhci_warn(xhci, "xHCI %s called with disabled ep %p\n",
|
||||
__func__, ep);
|
||||
return 0;
|
||||
}
|
||||
|
||||
ctrl_ctx->drop_flags |= drop_flag;
|
||||
new_drop_flags = ctrl_ctx->drop_flags;
|
||||
ctrl_ctx->drop_flags |= cpu_to_le32(drop_flag);
|
||||
new_drop_flags = le32_to_cpu(ctrl_ctx->drop_flags);
|
||||
|
||||
ctrl_ctx->add_flags &= ~drop_flag;
|
||||
new_add_flags = ctrl_ctx->add_flags;
|
||||
ctrl_ctx->add_flags &= cpu_to_le32(~drop_flag);
|
||||
new_add_flags = le32_to_cpu(ctrl_ctx->add_flags);
|
||||
|
||||
last_ctx = xhci_last_valid_endpoint(ctrl_ctx->add_flags);
|
||||
last_ctx = xhci_last_valid_endpoint(le32_to_cpu(ctrl_ctx->add_flags));
|
||||
slot_ctx = xhci_get_slot_ctx(xhci, in_ctx);
|
||||
/* Update the last valid endpoint context, if we deleted the last one */
|
||||
if ((slot_ctx->dev_info & LAST_CTX_MASK) > LAST_CTX(last_ctx)) {
|
||||
slot_ctx->dev_info &= ~LAST_CTX_MASK;
|
||||
slot_ctx->dev_info |= LAST_CTX(last_ctx);
|
||||
if ((le32_to_cpu(slot_ctx->dev_info) & LAST_CTX_MASK) >
|
||||
LAST_CTX(last_ctx)) {
|
||||
slot_ctx->dev_info &= cpu_to_le32(~LAST_CTX_MASK);
|
||||
slot_ctx->dev_info |= cpu_to_le32(LAST_CTX(last_ctx));
|
||||
}
|
||||
new_slot_info = slot_ctx->dev_info;
|
||||
new_slot_info = le32_to_cpu(slot_ctx->dev_info);
|
||||
|
||||
xhci_endpoint_zero(xhci, xhci->devs[udev->slot_id], ep);
|
||||
|
||||
|
@ -1419,7 +1422,8 @@ int xhci_add_endpoint(struct usb_hcd *hcd, struct usb_device *udev,
|
|||
/* If the HCD has already noted the endpoint is enabled,
|
||||
* ignore this request.
|
||||
*/
|
||||
if (ctrl_ctx->add_flags & xhci_get_endpoint_flag(&ep->desc)) {
|
||||
if (le32_to_cpu(ctrl_ctx->add_flags) &
|
||||
xhci_get_endpoint_flag(&ep->desc)) {
|
||||
xhci_warn(xhci, "xHCI %s called with enabled ep %p\n",
|
||||
__func__, ep);
|
||||
return 0;
|
||||
|
@ -1437,8 +1441,8 @@ int xhci_add_endpoint(struct usb_hcd *hcd, struct usb_device *udev,
|
|||
return -ENOMEM;
|
||||
}
|
||||
|
||||
ctrl_ctx->add_flags |= added_ctxs;
|
||||
new_add_flags = ctrl_ctx->add_flags;
|
||||
ctrl_ctx->add_flags |= cpu_to_le32(added_ctxs);
|
||||
new_add_flags = le32_to_cpu(ctrl_ctx->add_flags);
|
||||
|
||||
/* If xhci_endpoint_disable() was called for this endpoint, but the
|
||||
* xHC hasn't been notified yet through the check_bandwidth() call,
|
||||
|
@ -1446,15 +1450,16 @@ int xhci_add_endpoint(struct usb_hcd *hcd, struct usb_device *udev,
|
|||
* descriptors. We must drop and re-add this endpoint, so we leave the
|
||||
* drop flags alone.
|
||||
*/
|
||||
new_drop_flags = ctrl_ctx->drop_flags;
|
||||
new_drop_flags = le32_to_cpu(ctrl_ctx->drop_flags);
|
||||
|
||||
slot_ctx = xhci_get_slot_ctx(xhci, in_ctx);
|
||||
/* Update the last valid endpoint context, if we just added one past */
|
||||
if ((slot_ctx->dev_info & LAST_CTX_MASK) < LAST_CTX(last_ctx)) {
|
||||
slot_ctx->dev_info &= ~LAST_CTX_MASK;
|
||||
slot_ctx->dev_info |= LAST_CTX(last_ctx);
|
||||
if ((le32_to_cpu(slot_ctx->dev_info) & LAST_CTX_MASK) <
|
||||
LAST_CTX(last_ctx)) {
|
||||
slot_ctx->dev_info &= cpu_to_le32(~LAST_CTX_MASK);
|
||||
slot_ctx->dev_info |= cpu_to_le32(LAST_CTX(last_ctx));
|
||||
}
|
||||
new_slot_info = slot_ctx->dev_info;
|
||||
new_slot_info = le32_to_cpu(slot_ctx->dev_info);
|
||||
|
||||
/* Store the usb_device pointer for later use */
|
||||
ep->hcpriv = udev;
|
||||
|
@ -1484,9 +1489,9 @@ static void xhci_zero_in_ctx(struct xhci_hcd *xhci, struct xhci_virt_device *vir
|
|||
ctrl_ctx->drop_flags = 0;
|
||||
ctrl_ctx->add_flags = 0;
|
||||
slot_ctx = xhci_get_slot_ctx(xhci, virt_dev->in_ctx);
|
||||
slot_ctx->dev_info &= ~LAST_CTX_MASK;
|
||||
slot_ctx->dev_info &= cpu_to_le32(~LAST_CTX_MASK);
|
||||
/* Endpoint 0 is always valid */
|
||||
slot_ctx->dev_info |= LAST_CTX(1);
|
||||
slot_ctx->dev_info |= cpu_to_le32(LAST_CTX(1));
|
||||
for (i = 1; i < 31; ++i) {
|
||||
ep_ctx = xhci_get_ep_ctx(xhci, virt_dev->in_ctx, i);
|
||||
ep_ctx->ep_info = 0;
|
||||
|
@ -1497,7 +1502,7 @@ static void xhci_zero_in_ctx(struct xhci_hcd *xhci, struct xhci_virt_device *vir
|
|||
}
|
||||
|
||||
static int xhci_configure_endpoint_result(struct xhci_hcd *xhci,
|
||||
struct usb_device *udev, int *cmd_status)
|
||||
struct usb_device *udev, u32 *cmd_status)
|
||||
{
|
||||
int ret;
|
||||
|
||||
|
@ -1535,7 +1540,7 @@ static int xhci_configure_endpoint_result(struct xhci_hcd *xhci,
|
|||
}
|
||||
|
||||
static int xhci_evaluate_context_result(struct xhci_hcd *xhci,
|
||||
struct usb_device *udev, int *cmd_status)
|
||||
struct usb_device *udev, u32 *cmd_status)
|
||||
{
|
||||
int ret;
|
||||
struct xhci_virt_device *virt_dev = xhci->devs[udev->slot_id];
|
||||
|
@ -1581,7 +1586,7 @@ static int xhci_configure_endpoint(struct xhci_hcd *xhci,
|
|||
unsigned long flags;
|
||||
struct xhci_container_ctx *in_ctx;
|
||||
struct completion *cmd_completion;
|
||||
int *cmd_status;
|
||||
u32 *cmd_status;
|
||||
struct xhci_virt_device *virt_dev;
|
||||
|
||||
spin_lock_irqsave(&xhci->lock, flags);
|
||||
|
@ -1595,8 +1600,8 @@ static int xhci_configure_endpoint(struct xhci_hcd *xhci,
|
|||
/* Enqueue pointer can be left pointing to the link TRB,
|
||||
* we must handle that
|
||||
*/
|
||||
if ((command->command_trb->link.control & TRB_TYPE_BITMASK)
|
||||
== TRB_TYPE(TRB_LINK))
|
||||
if ((le32_to_cpu(command->command_trb->link.control)
|
||||
& TRB_TYPE_BITMASK) == TRB_TYPE(TRB_LINK))
|
||||
command->command_trb =
|
||||
xhci->cmd_ring->enq_seg->next->trbs;
|
||||
|
||||
|
@ -1672,14 +1677,13 @@ int xhci_check_bandwidth(struct usb_hcd *hcd, struct usb_device *udev)
|
|||
|
||||
/* See section 4.6.6 - A0 = 1; A1 = D0 = D1 = 0 */
|
||||
ctrl_ctx = xhci_get_input_control_ctx(xhci, virt_dev->in_ctx);
|
||||
ctrl_ctx->add_flags |= SLOT_FLAG;
|
||||
ctrl_ctx->add_flags &= ~EP0_FLAG;
|
||||
ctrl_ctx->drop_flags &= ~SLOT_FLAG;
|
||||
ctrl_ctx->drop_flags &= ~EP0_FLAG;
|
||||
ctrl_ctx->add_flags |= cpu_to_le32(SLOT_FLAG);
|
||||
ctrl_ctx->add_flags &= cpu_to_le32(~EP0_FLAG);
|
||||
ctrl_ctx->drop_flags &= cpu_to_le32(~(SLOT_FLAG | EP0_FLAG));
|
||||
xhci_dbg(xhci, "New Input Control Context:\n");
|
||||
slot_ctx = xhci_get_slot_ctx(xhci, virt_dev->in_ctx);
|
||||
xhci_dbg_ctx(xhci, virt_dev->in_ctx,
|
||||
LAST_CTX_TO_EP_NUM(slot_ctx->dev_info));
|
||||
LAST_CTX_TO_EP_NUM(le32_to_cpu(slot_ctx->dev_info)));
|
||||
|
||||
ret = xhci_configure_endpoint(xhci, udev, NULL,
|
||||
false, false);
|
||||
|
@ -1690,7 +1694,7 @@ int xhci_check_bandwidth(struct usb_hcd *hcd, struct usb_device *udev)
|
|||
|
||||
xhci_dbg(xhci, "Output context after successful config ep cmd:\n");
|
||||
xhci_dbg_ctx(xhci, virt_dev->out_ctx,
|
||||
LAST_CTX_TO_EP_NUM(slot_ctx->dev_info));
|
||||
LAST_CTX_TO_EP_NUM(le32_to_cpu(slot_ctx->dev_info)));
|
||||
|
||||
xhci_zero_in_ctx(xhci, virt_dev);
|
||||
/* Install new rings and free or cache any old rings */
|
||||
|
@ -1740,10 +1744,10 @@ static void xhci_setup_input_ctx_for_config_ep(struct xhci_hcd *xhci,
|
|||
{
|
||||
struct xhci_input_control_ctx *ctrl_ctx;
|
||||
ctrl_ctx = xhci_get_input_control_ctx(xhci, in_ctx);
|
||||
ctrl_ctx->add_flags = add_flags;
|
||||
ctrl_ctx->drop_flags = drop_flags;
|
||||
ctrl_ctx->add_flags = cpu_to_le32(add_flags);
|
||||
ctrl_ctx->drop_flags = cpu_to_le32(drop_flags);
|
||||
xhci_slot_copy(xhci, in_ctx, out_ctx);
|
||||
ctrl_ctx->add_flags |= SLOT_FLAG;
|
||||
ctrl_ctx->add_flags |= cpu_to_le32(SLOT_FLAG);
|
||||
|
||||
xhci_dbg(xhci, "Input Context:\n");
|
||||
xhci_dbg_ctx(xhci, in_ctx, xhci_last_valid_endpoint(add_flags));
|
||||
|
@ -1772,7 +1776,7 @@ static void xhci_setup_input_ctx_for_quirk(struct xhci_hcd *xhci,
|
|||
deq_state->new_deq_ptr);
|
||||
return;
|
||||
}
|
||||
ep_ctx->deq = addr | deq_state->new_cycle_state;
|
||||
ep_ctx->deq = cpu_to_le64(addr | deq_state->new_cycle_state);
|
||||
|
||||
added_ctxs = xhci_get_endpoint_flag_from_index(ep_index);
|
||||
xhci_setup_input_ctx_for_config_ep(xhci, xhci->devs[slot_id]->in_ctx,
|
||||
|
@ -2327,8 +2331,8 @@ int xhci_discover_or_reset_device(struct usb_hcd *hcd, struct usb_device *udev)
|
|||
/* Enqueue pointer can be left pointing to the link TRB,
|
||||
* we must handle that
|
||||
*/
|
||||
if ((reset_device_cmd->command_trb->link.control & TRB_TYPE_BITMASK)
|
||||
== TRB_TYPE(TRB_LINK))
|
||||
if ((le32_to_cpu(reset_device_cmd->command_trb->link.control)
|
||||
& TRB_TYPE_BITMASK) == TRB_TYPE(TRB_LINK))
|
||||
reset_device_cmd->command_trb =
|
||||
xhci->cmd_ring->enq_seg->next->trbs;
|
||||
|
||||
|
@ -2542,6 +2546,17 @@ int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev)
|
|||
|
||||
virt_dev = xhci->devs[udev->slot_id];
|
||||
|
||||
if (WARN_ON(!virt_dev)) {
|
||||
/*
|
||||
* In plug/unplug torture test with an NEC controller,
|
||||
* a zero-dereference was observed once due to virt_dev = 0.
|
||||
* Print useful debug rather than crash if it is observed again!
|
||||
*/
|
||||
xhci_warn(xhci, "Virt dev invalid for slot_id 0x%x!\n",
|
||||
udev->slot_id);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
slot_ctx = xhci_get_slot_ctx(xhci, virt_dev->in_ctx);
|
||||
/*
|
||||
* If this is the first Set Address since device plug-in or
|
||||
|
@ -2609,10 +2624,10 @@ int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev)
|
|||
temp_64 = xhci_read_64(xhci, &xhci->op_regs->dcbaa_ptr);
|
||||
xhci_dbg(xhci, "Op regs DCBAA ptr = %#016llx\n", temp_64);
|
||||
xhci_dbg(xhci, "Slot ID %d dcbaa entry @%p = %#016llx\n",
|
||||
udev->slot_id,
|
||||
&xhci->dcbaa->dev_context_ptrs[udev->slot_id],
|
||||
(unsigned long long)
|
||||
xhci->dcbaa->dev_context_ptrs[udev->slot_id]);
|
||||
udev->slot_id,
|
||||
&xhci->dcbaa->dev_context_ptrs[udev->slot_id],
|
||||
(unsigned long long)
|
||||
le64_to_cpu(xhci->dcbaa->dev_context_ptrs[udev->slot_id]));
|
||||
xhci_dbg(xhci, "Output Context DMA address = %#08llx\n",
|
||||
(unsigned long long)virt_dev->out_ctx->dma);
|
||||
xhci_dbg(xhci, "Slot ID %d Input Context:\n", udev->slot_id);
|
||||
|
@ -2626,7 +2641,8 @@ int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev)
|
|||
slot_ctx = xhci_get_slot_ctx(xhci, virt_dev->out_ctx);
|
||||
/* Use kernel assigned address for devices; store xHC assigned
|
||||
* address locally. */
|
||||
virt_dev->address = (slot_ctx->dev_state & DEV_ADDR_MASK) + 1;
|
||||
virt_dev->address = (le32_to_cpu(slot_ctx->dev_state) & DEV_ADDR_MASK)
|
||||
+ 1;
|
||||
/* Zero the input context control for later use */
|
||||
ctrl_ctx = xhci_get_input_control_ctx(xhci, virt_dev->in_ctx);
|
||||
ctrl_ctx->add_flags = 0;
|
||||
|
@ -2670,16 +2686,16 @@ int xhci_update_hub_device(struct usb_hcd *hcd, struct usb_device *hdev,
|
|||
spin_lock_irqsave(&xhci->lock, flags);
|
||||
xhci_slot_copy(xhci, config_cmd->in_ctx, vdev->out_ctx);
|
||||
ctrl_ctx = xhci_get_input_control_ctx(xhci, config_cmd->in_ctx);
|
||||
ctrl_ctx->add_flags |= SLOT_FLAG;
|
||||
ctrl_ctx->add_flags |= cpu_to_le32(SLOT_FLAG);
|
||||
slot_ctx = xhci_get_slot_ctx(xhci, config_cmd->in_ctx);
|
||||
slot_ctx->dev_info |= DEV_HUB;
|
||||
slot_ctx->dev_info |= cpu_to_le32(DEV_HUB);
|
||||
if (tt->multi)
|
||||
slot_ctx->dev_info |= DEV_MTT;
|
||||
slot_ctx->dev_info |= cpu_to_le32(DEV_MTT);
|
||||
if (xhci->hci_version > 0x95) {
|
||||
xhci_dbg(xhci, "xHCI version %x needs hub "
|
||||
"TT think time and number of ports\n",
|
||||
(unsigned int) xhci->hci_version);
|
||||
slot_ctx->dev_info2 |= XHCI_MAX_PORTS(hdev->maxchild);
|
||||
slot_ctx->dev_info2 |= cpu_to_le32(XHCI_MAX_PORTS(hdev->maxchild));
|
||||
/* Set TT think time - convert from ns to FS bit times.
|
||||
* 0 = 8 FS bit times, 1 = 16 FS bit times,
|
||||
* 2 = 24 FS bit times, 3 = 32 FS bit times.
|
||||
|
@ -2687,7 +2703,7 @@ int xhci_update_hub_device(struct usb_hcd *hcd, struct usb_device *hdev,
|
|||
think_time = tt->think_time;
|
||||
if (think_time != 0)
|
||||
think_time = (think_time / 666) - 1;
|
||||
slot_ctx->tt_info |= TT_THINK_TIME(think_time);
|
||||
slot_ctx->tt_info |= cpu_to_le32(TT_THINK_TIME(think_time));
|
||||
} else {
|
||||
xhci_dbg(xhci, "xHCI version %x doesn't need hub "
|
||||
"TT think time or number of ports\n",
|
||||
|
|
|
@ -57,13 +57,13 @@
|
|||
* @run_regs_off: RTSOFF - Runtime register space offset
|
||||
*/
|
||||
struct xhci_cap_regs {
|
||||
u32 hc_capbase;
|
||||
u32 hcs_params1;
|
||||
u32 hcs_params2;
|
||||
u32 hcs_params3;
|
||||
u32 hcc_params;
|
||||
u32 db_off;
|
||||
u32 run_regs_off;
|
||||
__le32 hc_capbase;
|
||||
__le32 hcs_params1;
|
||||
__le32 hcs_params2;
|
||||
__le32 hcs_params3;
|
||||
__le32 hcc_params;
|
||||
__le32 db_off;
|
||||
__le32 run_regs_off;
|
||||
/* Reserved up to (CAPLENGTH - 0x1C) */
|
||||
};
|
||||
|
||||
|
@ -155,26 +155,26 @@ struct xhci_cap_regs {
|
|||
* devices.
|
||||
*/
|
||||
struct xhci_op_regs {
|
||||
u32 command;
|
||||
u32 status;
|
||||
u32 page_size;
|
||||
u32 reserved1;
|
||||
u32 reserved2;
|
||||
u32 dev_notification;
|
||||
u64 cmd_ring;
|
||||
__le32 command;
|
||||
__le32 status;
|
||||
__le32 page_size;
|
||||
__le32 reserved1;
|
||||
__le32 reserved2;
|
||||
__le32 dev_notification;
|
||||
__le64 cmd_ring;
|
||||
/* rsvd: offset 0x20-2F */
|
||||
u32 reserved3[4];
|
||||
u64 dcbaa_ptr;
|
||||
u32 config_reg;
|
||||
__le32 reserved3[4];
|
||||
__le64 dcbaa_ptr;
|
||||
__le32 config_reg;
|
||||
/* rsvd: offset 0x3C-3FF */
|
||||
u32 reserved4[241];
|
||||
__le32 reserved4[241];
|
||||
/* port 1 registers, which serve as a base address for other ports */
|
||||
u32 port_status_base;
|
||||
u32 port_power_base;
|
||||
u32 port_link_base;
|
||||
u32 reserved5;
|
||||
__le32 port_status_base;
|
||||
__le32 port_power_base;
|
||||
__le32 port_link_base;
|
||||
__le32 reserved5;
|
||||
/* registers for ports 2-255 */
|
||||
u32 reserved6[NUM_PORT_REGS*254];
|
||||
__le32 reserved6[NUM_PORT_REGS*254];
|
||||
};
|
||||
|
||||
/* USBCMD - USB command - command bitmasks */
|
||||
|
@ -382,12 +382,12 @@ struct xhci_op_regs {
|
|||
* updates the dequeue pointer.
|
||||
*/
|
||||
struct xhci_intr_reg {
|
||||
u32 irq_pending;
|
||||
u32 irq_control;
|
||||
u32 erst_size;
|
||||
u32 rsvd;
|
||||
u64 erst_base;
|
||||
u64 erst_dequeue;
|
||||
__le32 irq_pending;
|
||||
__le32 irq_control;
|
||||
__le32 erst_size;
|
||||
__le32 rsvd;
|
||||
__le64 erst_base;
|
||||
__le64 erst_dequeue;
|
||||
};
|
||||
|
||||
/* irq_pending bitmasks */
|
||||
|
@ -432,8 +432,8 @@ struct xhci_intr_reg {
|
|||
* or larger accesses"
|
||||
*/
|
||||
struct xhci_run_regs {
|
||||
u32 microframe_index;
|
||||
u32 rsvd[7];
|
||||
__le32 microframe_index;
|
||||
__le32 rsvd[7];
|
||||
struct xhci_intr_reg ir_set[128];
|
||||
};
|
||||
|
||||
|
@ -447,7 +447,7 @@ struct xhci_run_regs {
|
|||
* Section 5.6
|
||||
*/
|
||||
struct xhci_doorbell_array {
|
||||
u32 doorbell[256];
|
||||
__le32 doorbell[256];
|
||||
};
|
||||
|
||||
#define DB_VALUE(ep, stream) ((((ep) + 1) & 0xff) | ((stream) << 16))
|
||||
|
@ -504,12 +504,12 @@ struct xhci_container_ctx {
|
|||
* reserved at the end of the slot context for HC internal use.
|
||||
*/
|
||||
struct xhci_slot_ctx {
|
||||
u32 dev_info;
|
||||
u32 dev_info2;
|
||||
u32 tt_info;
|
||||
u32 dev_state;
|
||||
__le32 dev_info;
|
||||
__le32 dev_info2;
|
||||
__le32 tt_info;
|
||||
__le32 dev_state;
|
||||
/* offset 0x10 to 0x1f reserved for HC internal use */
|
||||
u32 reserved[4];
|
||||
__le32 reserved[4];
|
||||
};
|
||||
|
||||
/* dev_info bitmasks */
|
||||
|
@ -580,12 +580,12 @@ struct xhci_slot_ctx {
|
|||
* reserved at the end of the endpoint context for HC internal use.
|
||||
*/
|
||||
struct xhci_ep_ctx {
|
||||
u32 ep_info;
|
||||
u32 ep_info2;
|
||||
u64 deq;
|
||||
u32 tx_info;
|
||||
__le32 ep_info;
|
||||
__le32 ep_info2;
|
||||
__le64 deq;
|
||||
__le32 tx_info;
|
||||
/* offset 0x14 - 0x1f reserved for HC internal use */
|
||||
u32 reserved[3];
|
||||
__le32 reserved[3];
|
||||
};
|
||||
|
||||
/* ep_info bitmasks */
|
||||
|
@ -660,9 +660,9 @@ struct xhci_ep_ctx {
|
|||
* @add_context: set the bit of the endpoint context you want to enable
|
||||
*/
|
||||
struct xhci_input_control_ctx {
|
||||
u32 drop_flags;
|
||||
u32 add_flags;
|
||||
u32 rsvd2[6];
|
||||
__le32 drop_flags;
|
||||
__le32 add_flags;
|
||||
__le32 rsvd2[6];
|
||||
};
|
||||
|
||||
/* Represents everything that is needed to issue a command on the command ring.
|
||||
|
@ -688,9 +688,9 @@ struct xhci_command {
|
|||
|
||||
struct xhci_stream_ctx {
|
||||
/* 64-bit stream ring address, cycle state, and stream type */
|
||||
u64 stream_ring;
|
||||
__le64 stream_ring;
|
||||
/* offset 0x14 - 0x1f reserved for HC internal use */
|
||||
u32 reserved[2];
|
||||
__le32 reserved[2];
|
||||
};
|
||||
|
||||
/* Stream Context Types (section 6.4.1) - bits 3:1 of stream ctx deq ptr */
|
||||
|
@ -803,7 +803,7 @@ struct xhci_virt_device {
|
|||
*/
|
||||
struct xhci_device_context_array {
|
||||
/* 64-bit device addresses; we only write 32-bit addresses */
|
||||
u64 dev_context_ptrs[MAX_HC_SLOTS];
|
||||
__le64 dev_context_ptrs[MAX_HC_SLOTS];
|
||||
/* private xHCD pointers */
|
||||
dma_addr_t dma;
|
||||
};
|
||||
|
@ -816,10 +816,10 @@ struct xhci_device_context_array {
|
|||
|
||||
struct xhci_transfer_event {
|
||||
/* 64-bit buffer address, or immediate data */
|
||||
u64 buffer;
|
||||
u32 transfer_len;
|
||||
__le64 buffer;
|
||||
__le32 transfer_len;
|
||||
/* This field is interpreted differently based on the type of TRB */
|
||||
u32 flags;
|
||||
__le32 flags;
|
||||
};
|
||||
|
||||
/** Transfer Event bit fields **/
|
||||
|
@ -898,9 +898,9 @@ struct xhci_transfer_event {
|
|||
|
||||
struct xhci_link_trb {
|
||||
/* 64-bit segment pointer*/
|
||||
u64 segment_ptr;
|
||||
u32 intr_target;
|
||||
u32 control;
|
||||
__le64 segment_ptr;
|
||||
__le32 intr_target;
|
||||
__le32 control;
|
||||
};
|
||||
|
||||
/* control bitfields */
|
||||
|
@ -909,9 +909,9 @@ struct xhci_link_trb {
|
|||
/* Command completion event TRB */
|
||||
struct xhci_event_cmd {
|
||||
/* Pointer to command TRB, or the value passed by the event data trb */
|
||||
u64 cmd_trb;
|
||||
u32 status;
|
||||
u32 flags;
|
||||
__le64 cmd_trb;
|
||||
__le32 status;
|
||||
__le32 flags;
|
||||
};
|
||||
|
||||
/* flags bitmasks */
|
||||
|
@ -943,6 +943,8 @@ struct xhci_event_cmd {
|
|||
/* Interrupter Target - which MSI-X vector to target the completion event at */
|
||||
#define TRB_INTR_TARGET(p) (((p) & 0x3ff) << 22)
|
||||
#define GET_INTR_TARGET(p) (((p) >> 22) & 0x3ff)
|
||||
#define TRB_TBC(p) (((p) & 0x3) << 7)
|
||||
#define TRB_TLBPC(p) (((p) & 0xf) << 16)
|
||||
|
||||
/* Cycle bit - indicates TRB ownership by HC or HCD */
|
||||
#define TRB_CYCLE (1<<0)
|
||||
|
@ -970,7 +972,7 @@ struct xhci_event_cmd {
|
|||
#define TRB_SIA (1<<31)
|
||||
|
||||
struct xhci_generic_trb {
|
||||
u32 field[4];
|
||||
__le32 field[4];
|
||||
};
|
||||
|
||||
union xhci_trb {
|
||||
|
@ -1118,10 +1120,10 @@ struct xhci_ring {
|
|||
|
||||
struct xhci_erst_entry {
|
||||
/* 64-bit event ring segment address */
|
||||
u64 seg_addr;
|
||||
u32 seg_size;
|
||||
__le64 seg_addr;
|
||||
__le32 seg_size;
|
||||
/* Set to zero */
|
||||
u32 rsvd;
|
||||
__le32 rsvd;
|
||||
};
|
||||
|
||||
struct xhci_erst {
|
||||
|
@ -1286,10 +1288,10 @@ struct xhci_hcd {
|
|||
/* Is each xHCI roothub port a USB 3.0, USB 2.0, or USB 1.1 port? */
|
||||
u8 *port_array;
|
||||
/* Array of pointers to USB 3.0 PORTSC registers */
|
||||
u32 __iomem **usb3_ports;
|
||||
__le32 __iomem **usb3_ports;
|
||||
unsigned int num_usb3_ports;
|
||||
/* Array of pointers to USB 2.0 PORTSC registers */
|
||||
u32 __iomem **usb2_ports;
|
||||
__le32 __iomem **usb2_ports;
|
||||
unsigned int num_usb2_ports;
|
||||
};
|
||||
|
||||
|
@ -1322,12 +1324,12 @@ static inline struct usb_hcd *xhci_to_hcd(struct xhci_hcd *xhci)
|
|||
/* TODO: copied from ehci.h - can be refactored? */
|
||||
/* xHCI spec says all registers are little endian */
|
||||
static inline unsigned int xhci_readl(const struct xhci_hcd *xhci,
|
||||
__u32 __iomem *regs)
|
||||
__le32 __iomem *regs)
|
||||
{
|
||||
return readl(regs);
|
||||
}
|
||||
static inline void xhci_writel(struct xhci_hcd *xhci,
|
||||
const unsigned int val, __u32 __iomem *regs)
|
||||
const unsigned int val, __le32 __iomem *regs)
|
||||
{
|
||||
xhci_dbg(xhci,
|
||||
"`MEM_WRITE_DWORD(3'b000, 32'h%p, 32'h%0x, 4'hf);\n",
|
||||
|
@ -1345,7 +1347,7 @@ static inline void xhci_writel(struct xhci_hcd *xhci,
|
|||
* the high dword, and write order is irrelevant.
|
||||
*/
|
||||
static inline u64 xhci_read_64(const struct xhci_hcd *xhci,
|
||||
__u64 __iomem *regs)
|
||||
__le64 __iomem *regs)
|
||||
{
|
||||
__u32 __iomem *ptr = (__u32 __iomem *) regs;
|
||||
u64 val_lo = readl(ptr);
|
||||
|
@ -1353,7 +1355,7 @@ static inline u64 xhci_read_64(const struct xhci_hcd *xhci,
|
|||
return val_lo + (val_hi << 32);
|
||||
}
|
||||
static inline void xhci_write_64(struct xhci_hcd *xhci,
|
||||
const u64 val, __u64 __iomem *regs)
|
||||
const u64 val, __le64 __iomem *regs)
|
||||
{
|
||||
__u32 __iomem *ptr = (__u32 __iomem *) regs;
|
||||
u32 val_lo = lower_32_bits(val);
|
||||
|
|
|
@ -579,7 +579,7 @@ struct usb_ss_ep_comp_descriptor {
|
|||
|
||||
__u8 bMaxBurst;
|
||||
__u8 bmAttributes;
|
||||
__u16 wBytesPerInterval;
|
||||
__le16 wBytesPerInterval;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
#define USB_DT_SS_EP_COMP_SIZE 6
|
||||
|
|
Loading…
Reference in a new issue