Loading drivers/usb/core/hcd.c +10 −0 Original line number Diff line number Diff line Loading @@ -2292,6 +2292,16 @@ usb_hcd_get_xfer_ring_dma_addr(struct usb_device *udev, return hcd->driver->get_xfer_ring_dma_addr(hcd, udev, ep); } int usb_hcd_get_controller_id(struct usb_device *udev) { struct usb_hcd *hcd = bus_to_hcd(udev->bus); if (!HCD_RH_RUNNING(hcd)) return -EINVAL; return hcd->driver->get_core_id(hcd); } #ifdef CONFIG_PM int hcd_bus_suspend(struct usb_device *rhdev, pm_message_t msg) Loading drivers/usb/core/usb.c +9 −0 Original line number Diff line number Diff line Loading @@ -876,6 +876,15 @@ dma_addr_t usb_get_xfer_ring_dma_addr(struct usb_device *dev, } EXPORT_SYMBOL(usb_get_xfer_ring_dma_addr); int usb_get_controller_id(struct usb_device *dev) { if (dev->state == USB_STATE_NOTATTACHED) return -EINVAL; return usb_hcd_get_controller_id(dev); } EXPORT_SYMBOL(usb_get_controller_id); /*-------------------------------------------------------------------*/ /* * __usb_get_extra_descriptor() finds a descriptor of specific type in the Loading drivers/usb/host/xhci-mem.c +79 −27 Original line number Diff line number Diff line Loading @@ -1831,27 +1831,17 @@ void xhci_free_erst(struct xhci_hcd *xhci, struct xhci_erst *erst) erst->entries = NULL; } int xhci_sec_event_ring_cleanup(struct usb_hcd *hcd, unsigned int intr_num) void xhci_handle_sec_intr_events(struct xhci_hcd *xhci, int intr_num) { int size; u32 iman_reg; union xhci_trb *erdp_trb, *current_trb; struct xhci_segment *seg; u64 erdp_reg; struct xhci_hcd *xhci = hcd_to_xhci(hcd); struct device *dev = xhci_to_hcd(xhci)->self.sysdev; u32 iman_reg; dma_addr_t deq; unsigned long segment_offset; if (intr_num > xhci->max_interrupters) { xhci_err(xhci, "invalid secondary interrupter num %d\n", intr_num); return -EINVAL; } /* disable irq, ack pending interrupt and ack all pending events */ size = sizeof(struct xhci_erst_entry)*(xhci->sec_erst[intr_num].num_entries); if (xhci->sec_erst[intr_num].entries) { /* * disable irq, ack pending interrupt and clear EHB for xHC to * generate interrupt again when new event ring is setup */ iman_reg = readl_relaxed(&xhci->sec_ir_set[intr_num]->irq_pending); iman_reg &= ~IMAN_IE; Loading @@ -1862,14 +1852,76 @@ int xhci_sec_event_ring_cleanup(struct usb_hcd *hcd, unsigned int intr_num) if (iman_reg & IMAN_IP) writel_relaxed(iman_reg, &xhci->sec_ir_set[intr_num]->irq_pending); /* make sure IP gets cleared before clearing EHB */ mb(); erdp_reg = xhci_read_64(xhci, &xhci->sec_ir_set[intr_num]->erst_dequeue); xhci_write_64(xhci, erdp_reg | ERST_EHB, /* last acked event trb is in erdp reg */ erdp_reg = xhci_read_64(xhci, &xhci->sec_ir_set[intr_num]->erst_dequeue); deq = (dma_addr_t)(erdp_reg & ~ERST_PTR_MASK); if (!deq) { pr_debug("%s: event ring handling not required\n", __func__); return; } seg = xhci->sec_event_ring[intr_num]->first_seg; segment_offset = deq - seg->dma; /* find out virtual address of the last acked event trb */ erdp_trb = current_trb = &seg->trbs[0] + (segment_offset/sizeof(*current_trb)); /* read cycle state of the last acked trb to find out CCS */ xhci->sec_event_ring[intr_num]->cycle_state = (current_trb->event_cmd.flags & TRB_CYCLE); while (1) { /* last trb of the event ring: toggle cycle state */ if (current_trb == &seg->trbs[TRBS_PER_SEGMENT - 1]) { xhci->sec_event_ring[intr_num]->cycle_state ^= 1; current_trb = &seg->trbs[0]; } else { current_trb++; } /* cycle state transition */ if ((le32_to_cpu(current_trb->event_cmd.flags) & TRB_CYCLE) != xhci->sec_event_ring[intr_num]->cycle_state) break; } if (erdp_trb != current_trb) { deq = xhci_trb_virt_to_dma(xhci->sec_event_ring[intr_num]->deq_seg, current_trb); if (deq == 0) xhci_warn(xhci, "WARN invalid SW event ring dequeue ptr.\n"); /* Update HC event ring dequeue pointer */ erdp_reg &= ERST_PTR_MASK; erdp_reg |= ((u64) deq & (u64) ~ERST_PTR_MASK); } /* Clear the event handler busy flag (RW1C); event ring is empty. */ erdp_reg |= ERST_EHB; xhci_write_64(xhci, erdp_reg, &xhci->sec_ir_set[intr_num]->erst_dequeue); } int xhci_sec_event_ring_cleanup(struct usb_hcd *hcd, unsigned int intr_num) { int size; struct xhci_hcd *xhci = hcd_to_xhci(hcd); struct device *dev = xhci_to_hcd(xhci)->self.sysdev; if (intr_num >= xhci->max_interrupters) { xhci_err(xhci, "invalid secondary interrupter num %d\n", intr_num); return -EINVAL; } size = sizeof(struct xhci_erst_entry)*(xhci->sec_erst[intr_num].num_entries); if (xhci->sec_erst[intr_num].entries) { xhci_handle_sec_intr_events(xhci, intr_num); dma_free_coherent(dev, size, xhci->sec_erst[intr_num].entries, xhci->sec_erst[intr_num].erst_dma_addr); xhci->sec_erst[intr_num].entries = NULL; Loading @@ -1891,7 +1943,7 @@ void xhci_event_ring_cleanup(struct xhci_hcd *xhci) unsigned int i; /* sec event ring clean up */ for (i = 1; i <= xhci->max_interrupters; i++) for (i = 1; i < xhci->max_interrupters; i++) xhci_sec_event_ring_cleanup(xhci_to_hcd(xhci), i); kfree(xhci->sec_ir_set); Loading Loading @@ -2483,7 +2535,7 @@ int xhci_sec_event_ring_setup(struct usb_hcd *hcd, unsigned int intr_num) if ((xhci->xhc_state & XHCI_STATE_HALTED) || !xhci->sec_ir_set || !xhci->sec_event_ring || !xhci->sec_erst || intr_num > xhci->max_interrupters) { intr_num >= xhci->max_interrupters) { xhci_err(xhci, "%s:state %x ir_set %pK evt_ring %pK erst %pK intr# %d\n", __func__, xhci->xhc_state, xhci->sec_ir_set, Loading drivers/usb/host/xhci.c +10 −2 Original line number Diff line number Diff line Loading @@ -5112,8 +5112,8 @@ dma_addr_t xhci_get_sec_event_ring_dma_addr(struct usb_hcd *hcd, { struct xhci_hcd *xhci = hcd_to_xhci(hcd); if (intr_num > xhci->max_interrupters) { xhci_err(xhci, "intr num %d > max intrs %d\n", intr_num, if (intr_num >= xhci->max_interrupters) { xhci_err(xhci, "intr num %d >= max intrs %d\n", intr_num, xhci->max_interrupters); return 0; } Loading Loading @@ -5162,6 +5162,13 @@ dma_addr_t xhci_get_xfer_ring_dma_addr(struct usb_hcd *hcd, return 0; } int xhci_get_core_id(struct usb_hcd *hcd) { struct xhci_hcd *xhci = hcd_to_xhci(hcd); return xhci->core_id; } static const struct hc_driver xhci_hc_driver = { .description = "xhci-hcd", .product_desc = "xHCI Host Controller", Loading Loading @@ -5227,6 +5234,7 @@ static const struct hc_driver xhci_hc_driver = { .get_sec_event_ring_dma_addr = xhci_get_sec_event_ring_dma_addr, .get_xfer_ring_dma_addr = xhci_get_xfer_ring_dma_addr, .get_dcba_dma_addr = xhci_get_dcba_dma_addr, .get_core_id = xhci_get_core_id, }; void xhci_init_driver(struct hc_driver *drv, Loading drivers/usb/host/xhci.h +1 −0 Original line number Diff line number Diff line Loading @@ -2121,6 +2121,7 @@ int xhci_find_raw_port_number(struct usb_hcd *hcd, int port1); struct xhci_hub *xhci_get_rhub(struct usb_hcd *hcd); void xhci_hc_died(struct xhci_hcd *xhci); int xhci_get_core_id(struct usb_hcd *hcd); #ifdef CONFIG_PM int xhci_bus_suspend(struct usb_hcd *hcd); Loading Loading
drivers/usb/core/hcd.c +10 −0 Original line number Diff line number Diff line Loading @@ -2292,6 +2292,16 @@ usb_hcd_get_xfer_ring_dma_addr(struct usb_device *udev, return hcd->driver->get_xfer_ring_dma_addr(hcd, udev, ep); } int usb_hcd_get_controller_id(struct usb_device *udev) { struct usb_hcd *hcd = bus_to_hcd(udev->bus); if (!HCD_RH_RUNNING(hcd)) return -EINVAL; return hcd->driver->get_core_id(hcd); } #ifdef CONFIG_PM int hcd_bus_suspend(struct usb_device *rhdev, pm_message_t msg) Loading
drivers/usb/core/usb.c +9 −0 Original line number Diff line number Diff line Loading @@ -876,6 +876,15 @@ dma_addr_t usb_get_xfer_ring_dma_addr(struct usb_device *dev, } EXPORT_SYMBOL(usb_get_xfer_ring_dma_addr); int usb_get_controller_id(struct usb_device *dev) { if (dev->state == USB_STATE_NOTATTACHED) return -EINVAL; return usb_hcd_get_controller_id(dev); } EXPORT_SYMBOL(usb_get_controller_id); /*-------------------------------------------------------------------*/ /* * __usb_get_extra_descriptor() finds a descriptor of specific type in the Loading
drivers/usb/host/xhci-mem.c +79 −27 Original line number Diff line number Diff line Loading @@ -1831,27 +1831,17 @@ void xhci_free_erst(struct xhci_hcd *xhci, struct xhci_erst *erst) erst->entries = NULL; } int xhci_sec_event_ring_cleanup(struct usb_hcd *hcd, unsigned int intr_num) void xhci_handle_sec_intr_events(struct xhci_hcd *xhci, int intr_num) { int size; u32 iman_reg; union xhci_trb *erdp_trb, *current_trb; struct xhci_segment *seg; u64 erdp_reg; struct xhci_hcd *xhci = hcd_to_xhci(hcd); struct device *dev = xhci_to_hcd(xhci)->self.sysdev; u32 iman_reg; dma_addr_t deq; unsigned long segment_offset; if (intr_num > xhci->max_interrupters) { xhci_err(xhci, "invalid secondary interrupter num %d\n", intr_num); return -EINVAL; } /* disable irq, ack pending interrupt and ack all pending events */ size = sizeof(struct xhci_erst_entry)*(xhci->sec_erst[intr_num].num_entries); if (xhci->sec_erst[intr_num].entries) { /* * disable irq, ack pending interrupt and clear EHB for xHC to * generate interrupt again when new event ring is setup */ iman_reg = readl_relaxed(&xhci->sec_ir_set[intr_num]->irq_pending); iman_reg &= ~IMAN_IE; Loading @@ -1862,14 +1852,76 @@ int xhci_sec_event_ring_cleanup(struct usb_hcd *hcd, unsigned int intr_num) if (iman_reg & IMAN_IP) writel_relaxed(iman_reg, &xhci->sec_ir_set[intr_num]->irq_pending); /* make sure IP gets cleared before clearing EHB */ mb(); erdp_reg = xhci_read_64(xhci, &xhci->sec_ir_set[intr_num]->erst_dequeue); xhci_write_64(xhci, erdp_reg | ERST_EHB, /* last acked event trb is in erdp reg */ erdp_reg = xhci_read_64(xhci, &xhci->sec_ir_set[intr_num]->erst_dequeue); deq = (dma_addr_t)(erdp_reg & ~ERST_PTR_MASK); if (!deq) { pr_debug("%s: event ring handling not required\n", __func__); return; } seg = xhci->sec_event_ring[intr_num]->first_seg; segment_offset = deq - seg->dma; /* find out virtual address of the last acked event trb */ erdp_trb = current_trb = &seg->trbs[0] + (segment_offset/sizeof(*current_trb)); /* read cycle state of the last acked trb to find out CCS */ xhci->sec_event_ring[intr_num]->cycle_state = (current_trb->event_cmd.flags & TRB_CYCLE); while (1) { /* last trb of the event ring: toggle cycle state */ if (current_trb == &seg->trbs[TRBS_PER_SEGMENT - 1]) { xhci->sec_event_ring[intr_num]->cycle_state ^= 1; current_trb = &seg->trbs[0]; } else { current_trb++; } /* cycle state transition */ if ((le32_to_cpu(current_trb->event_cmd.flags) & TRB_CYCLE) != xhci->sec_event_ring[intr_num]->cycle_state) break; } if (erdp_trb != current_trb) { deq = xhci_trb_virt_to_dma(xhci->sec_event_ring[intr_num]->deq_seg, current_trb); if (deq == 0) xhci_warn(xhci, "WARN invalid SW event ring dequeue ptr.\n"); /* Update HC event ring dequeue pointer */ erdp_reg &= ERST_PTR_MASK; erdp_reg |= ((u64) deq & (u64) ~ERST_PTR_MASK); } /* Clear the event handler busy flag (RW1C); event ring is empty. */ erdp_reg |= ERST_EHB; xhci_write_64(xhci, erdp_reg, &xhci->sec_ir_set[intr_num]->erst_dequeue); } int xhci_sec_event_ring_cleanup(struct usb_hcd *hcd, unsigned int intr_num) { int size; struct xhci_hcd *xhci = hcd_to_xhci(hcd); struct device *dev = xhci_to_hcd(xhci)->self.sysdev; if (intr_num >= xhci->max_interrupters) { xhci_err(xhci, "invalid secondary interrupter num %d\n", intr_num); return -EINVAL; } size = sizeof(struct xhci_erst_entry)*(xhci->sec_erst[intr_num].num_entries); if (xhci->sec_erst[intr_num].entries) { xhci_handle_sec_intr_events(xhci, intr_num); dma_free_coherent(dev, size, xhci->sec_erst[intr_num].entries, xhci->sec_erst[intr_num].erst_dma_addr); xhci->sec_erst[intr_num].entries = NULL; Loading @@ -1891,7 +1943,7 @@ void xhci_event_ring_cleanup(struct xhci_hcd *xhci) unsigned int i; /* sec event ring clean up */ for (i = 1; i <= xhci->max_interrupters; i++) for (i = 1; i < xhci->max_interrupters; i++) xhci_sec_event_ring_cleanup(xhci_to_hcd(xhci), i); kfree(xhci->sec_ir_set); Loading Loading @@ -2483,7 +2535,7 @@ int xhci_sec_event_ring_setup(struct usb_hcd *hcd, unsigned int intr_num) if ((xhci->xhc_state & XHCI_STATE_HALTED) || !xhci->sec_ir_set || !xhci->sec_event_ring || !xhci->sec_erst || intr_num > xhci->max_interrupters) { intr_num >= xhci->max_interrupters) { xhci_err(xhci, "%s:state %x ir_set %pK evt_ring %pK erst %pK intr# %d\n", __func__, xhci->xhc_state, xhci->sec_ir_set, Loading
drivers/usb/host/xhci.c +10 −2 Original line number Diff line number Diff line Loading @@ -5112,8 +5112,8 @@ dma_addr_t xhci_get_sec_event_ring_dma_addr(struct usb_hcd *hcd, { struct xhci_hcd *xhci = hcd_to_xhci(hcd); if (intr_num > xhci->max_interrupters) { xhci_err(xhci, "intr num %d > max intrs %d\n", intr_num, if (intr_num >= xhci->max_interrupters) { xhci_err(xhci, "intr num %d >= max intrs %d\n", intr_num, xhci->max_interrupters); return 0; } Loading Loading @@ -5162,6 +5162,13 @@ dma_addr_t xhci_get_xfer_ring_dma_addr(struct usb_hcd *hcd, return 0; } int xhci_get_core_id(struct usb_hcd *hcd) { struct xhci_hcd *xhci = hcd_to_xhci(hcd); return xhci->core_id; } static const struct hc_driver xhci_hc_driver = { .description = "xhci-hcd", .product_desc = "xHCI Host Controller", Loading Loading @@ -5227,6 +5234,7 @@ static const struct hc_driver xhci_hc_driver = { .get_sec_event_ring_dma_addr = xhci_get_sec_event_ring_dma_addr, .get_xfer_ring_dma_addr = xhci_get_xfer_ring_dma_addr, .get_dcba_dma_addr = xhci_get_dcba_dma_addr, .get_core_id = xhci_get_core_id, }; void xhci_init_driver(struct hc_driver *drv, Loading
drivers/usb/host/xhci.h +1 −0 Original line number Diff line number Diff line Loading @@ -2121,6 +2121,7 @@ int xhci_find_raw_port_number(struct usb_hcd *hcd, int port1); struct xhci_hub *xhci_get_rhub(struct usb_hcd *hcd); void xhci_hc_died(struct xhci_hcd *xhci); int xhci_get_core_id(struct usb_hcd *hcd); #ifdef CONFIG_PM int xhci_bus_suspend(struct usb_hcd *hcd); Loading