Loading drivers/usb/host/xhci-msm-hsic.c +116 −1 Original line number Diff line number Diff line Loading @@ -133,6 +133,9 @@ struct mxhci_hsic_hcd { uint32_t wakeup_int_cnt; uint32_t pwr_evt_irq_inlpm; struct pinctrl *hsic_pinctrl; struct tasklet_struct bh; unsigned handled_event_cnt; unsigned cpu_yield_cnt; }; #define SYNOPSIS_DWC3_VENDOR 0x5533 Loading Loading @@ -164,6 +167,9 @@ module_param_named(ep_addr_rxdbg_mask, module_param_named(ep_addr_txdbg_mask, dbg_hsic.outep_log_mask, uint, S_IRUGO | S_IWUSR); static int max_event_to_handle = 20; module_param(max_event_to_handle, uint, S_IRUGO | S_IWUSR); static int mxhci_hsic_data_events_show(struct seq_file *s, void *unused) { unsigned long flags; Loading Loading @@ -1076,6 +1082,66 @@ unlock: spin_unlock_irqrestore(&xhci->lock, flags); } static irqreturn_t mxhci_irq(struct usb_hcd *hcd) { struct mxhci_hsic_hcd *mxhci = hcd_to_hsic(hcd->primary_hcd); struct xhci_hcd *xhci = mxhci->xhci; u32 status; u64 temp_64; spin_lock(&xhci->lock); /* Check if the xHC generated the interrupt, or the irq is shared */ status = xhci_readl(xhci, &xhci->op_regs->status); if (status == 0xffffffff) { spin_unlock(&xhci->lock); return IRQ_HANDLED; } if (!(status & STS_EINT)) { spin_unlock(&xhci->lock); return IRQ_NONE; } if (status & STS_FATAL) { xhci_warn(xhci, "WARNING: Host System Error\n"); xhci_halt(xhci); spin_unlock(&xhci->lock); return IRQ_HANDLED; } /* * Clear the op reg interrupt status first, * so we can receive interrupts from other MSI-X interrupters. * Write 1 to clear the interrupt status. */ status |= STS_EINT; xhci_writel(xhci, status, &xhci->op_regs->status); if (hcd->irq) { u32 irq_pending; /* Acknowledge the PCI interrupt */ irq_pending = xhci_readl(xhci, &xhci->ir_set->irq_pending); irq_pending |= IMAN_IP; xhci_writel(xhci, irq_pending, &xhci->ir_set->irq_pending); } if (xhci->xhc_state & XHCI_STATE_DYING) { xhci_dbg(xhci, "xHCI dying, ignoring interrupt.\n"); /* Clear the event handler busy flag (RW1C); * the event ring should be empty. */ temp_64 = xhci_read_64(xhci, &xhci->ir_set->erst_dequeue); xhci_write_64(xhci, temp_64 | ERST_EHB, &xhci->ir_set->erst_dequeue); spin_unlock(&xhci->lock); return IRQ_HANDLED; } spin_unlock(&xhci->lock); tasklet_schedule(&mxhci->bh); return IRQ_HANDLED; } static struct hc_driver mxhci_hsic_hc_driver = { .description = "xhci-hcd", .product_desc = "Qualcomm xHCI Host Controller using HSIC", Loading @@ -1083,7 +1149,7 @@ static struct hc_driver mxhci_hsic_hc_driver = { /* * generic hardware linkage */ .irq = xhci_irq, .irq = mxhci_irq, .flags = HCD_MEMORY | HCD_USB3, /* Loading Loading @@ -1131,6 +1197,51 @@ static struct hc_driver mxhci_hsic_hc_driver = { .udev_enum_done = mxhci_hsic_udev_enum_done, }; static void mxhci_irq_bh(unsigned long param) { struct mxhci_hsic_hcd *mxhci = (struct mxhci_hsic_hcd *)param; struct xhci_hcd *xhci = mxhci->xhci; u64 temp_64; union xhci_trb *event_ring_deq; dma_addr_t deq; unsigned long flags; unsigned event_cnt = 0; int schedule_again = 0; spin_lock_irqsave(&xhci->lock, flags); event_ring_deq = xhci->event_ring->dequeue; while (event_cnt < max_event_to_handle) { schedule_again = xhci_handle_event(xhci); event_cnt++; } temp_64 = xhci_read_64(xhci, &xhci->ir_set->erst_dequeue); /* If necessary, update the HW's version of the event ring deq ptr. */ if (event_ring_deq != xhci->event_ring->dequeue) { deq = xhci_trb_virt_to_dma(xhci->event_ring->deq_seg, xhci->event_ring->dequeue); if (deq == 0) xhci_warn(xhci, "WARN wrong SW event ring dequeue ptr.\n"); /* Update HC event ring dequeue pointer */ temp_64 &= ERST_PTR_MASK; temp_64 |= ((u64) deq & (u64) ~ERST_PTR_MASK); } /* Clear the event handler busy flag to get irq ; reloads imod */ temp_64 |= ERST_EHB; xhci_write_64(xhci, temp_64, &xhci->ir_set->erst_dequeue); spin_unlock_irqrestore(&xhci->lock, flags); mxhci->handled_event_cnt += event_cnt - 1; mxhci->cpu_yield_cnt++; if ((schedule_again > 0) && !mxhci->xhci_remove_flag) tasklet_schedule(&mxhci->bh); } static ssize_t config_imod_store(struct device *pdev, struct device_attribute *attr, const char *buff, size_t size) { Loading Loading @@ -1292,6 +1403,8 @@ static int mxhci_hsic_probe(struct platform_device *pdev) mxhci->dev = &pdev->dev; mxhci->xhci_remove_flag = false; mxhci->xhci_shutdown_flag = false; mxhci->bh.func = mxhci_irq_bh; mxhci->bh.data = (unsigned long)mxhci; /* Get pinctrl if target uses pinctrl */ mxhci->hsic_pinctrl = devm_pinctrl_get(&pdev->dev); Loading Loading @@ -1589,6 +1702,8 @@ static int mxhci_hsic_remove(struct platform_device *pdev) pm_runtime_disable(&hcd->self.root_hub->dev); pm_runtime_barrier(&hcd->self.root_hub->dev); tasklet_kill(&mxhci->bh); usb_remove_hcd(xhci->shared_hcd); usb_put_hcd(xhci->shared_hcd); Loading drivers/usb/host/xhci-ring.c +1 −1 Original line number Diff line number Diff line Loading @@ -2685,7 +2685,7 @@ cleanup: * Returns >0 for "possibly more events to process" (caller should call again), * otherwise 0 if done. In future, <0 returns should indicate error code. */ static int xhci_handle_event(struct xhci_hcd *xhci) int xhci_handle_event(struct xhci_hcd *xhci) { union xhci_trb *event; int update_ptrs = 1; Loading drivers/usb/host/xhci.h +1 −0 Original line number Diff line number Diff line Loading @@ -1909,6 +1909,7 @@ int xhci_cancel_cmd(struct xhci_hcd *xhci, struct xhci_command *command, void xhci_ring_ep_doorbell(struct xhci_hcd *xhci, unsigned int slot_id, unsigned int ep_index, unsigned int stream_id); union xhci_trb *xhci_find_next_enqueue(struct xhci_ring *ring); int xhci_handle_event(struct xhci_hcd *xhci); /* xHCI roothub code */ void xhci_set_link_state(struct xhci_hcd *xhci, __le32 __iomem **port_array, Loading Loading
drivers/usb/host/xhci-msm-hsic.c +116 −1 Original line number Diff line number Diff line Loading @@ -133,6 +133,9 @@ struct mxhci_hsic_hcd { uint32_t wakeup_int_cnt; uint32_t pwr_evt_irq_inlpm; struct pinctrl *hsic_pinctrl; struct tasklet_struct bh; unsigned handled_event_cnt; unsigned cpu_yield_cnt; }; #define SYNOPSIS_DWC3_VENDOR 0x5533 Loading Loading @@ -164,6 +167,9 @@ module_param_named(ep_addr_rxdbg_mask, module_param_named(ep_addr_txdbg_mask, dbg_hsic.outep_log_mask, uint, S_IRUGO | S_IWUSR); static int max_event_to_handle = 20; module_param(max_event_to_handle, uint, S_IRUGO | S_IWUSR); static int mxhci_hsic_data_events_show(struct seq_file *s, void *unused) { unsigned long flags; Loading Loading @@ -1076,6 +1082,66 @@ unlock: spin_unlock_irqrestore(&xhci->lock, flags); } static irqreturn_t mxhci_irq(struct usb_hcd *hcd) { struct mxhci_hsic_hcd *mxhci = hcd_to_hsic(hcd->primary_hcd); struct xhci_hcd *xhci = mxhci->xhci; u32 status; u64 temp_64; spin_lock(&xhci->lock); /* Check if the xHC generated the interrupt, or the irq is shared */ status = xhci_readl(xhci, &xhci->op_regs->status); if (status == 0xffffffff) { spin_unlock(&xhci->lock); return IRQ_HANDLED; } if (!(status & STS_EINT)) { spin_unlock(&xhci->lock); return IRQ_NONE; } if (status & STS_FATAL) { xhci_warn(xhci, "WARNING: Host System Error\n"); xhci_halt(xhci); spin_unlock(&xhci->lock); return IRQ_HANDLED; } /* * Clear the op reg interrupt status first, * so we can receive interrupts from other MSI-X interrupters. * Write 1 to clear the interrupt status. */ status |= STS_EINT; xhci_writel(xhci, status, &xhci->op_regs->status); if (hcd->irq) { u32 irq_pending; /* Acknowledge the PCI interrupt */ irq_pending = xhci_readl(xhci, &xhci->ir_set->irq_pending); irq_pending |= IMAN_IP; xhci_writel(xhci, irq_pending, &xhci->ir_set->irq_pending); } if (xhci->xhc_state & XHCI_STATE_DYING) { xhci_dbg(xhci, "xHCI dying, ignoring interrupt.\n"); /* Clear the event handler busy flag (RW1C); * the event ring should be empty. */ temp_64 = xhci_read_64(xhci, &xhci->ir_set->erst_dequeue); xhci_write_64(xhci, temp_64 | ERST_EHB, &xhci->ir_set->erst_dequeue); spin_unlock(&xhci->lock); return IRQ_HANDLED; } spin_unlock(&xhci->lock); tasklet_schedule(&mxhci->bh); return IRQ_HANDLED; } static struct hc_driver mxhci_hsic_hc_driver = { .description = "xhci-hcd", .product_desc = "Qualcomm xHCI Host Controller using HSIC", Loading @@ -1083,7 +1149,7 @@ static struct hc_driver mxhci_hsic_hc_driver = { /* * generic hardware linkage */ .irq = xhci_irq, .irq = mxhci_irq, .flags = HCD_MEMORY | HCD_USB3, /* Loading Loading @@ -1131,6 +1197,51 @@ static struct hc_driver mxhci_hsic_hc_driver = { .udev_enum_done = mxhci_hsic_udev_enum_done, }; static void mxhci_irq_bh(unsigned long param) { struct mxhci_hsic_hcd *mxhci = (struct mxhci_hsic_hcd *)param; struct xhci_hcd *xhci = mxhci->xhci; u64 temp_64; union xhci_trb *event_ring_deq; dma_addr_t deq; unsigned long flags; unsigned event_cnt = 0; int schedule_again = 0; spin_lock_irqsave(&xhci->lock, flags); event_ring_deq = xhci->event_ring->dequeue; while (event_cnt < max_event_to_handle) { schedule_again = xhci_handle_event(xhci); event_cnt++; } temp_64 = xhci_read_64(xhci, &xhci->ir_set->erst_dequeue); /* If necessary, update the HW's version of the event ring deq ptr. */ if (event_ring_deq != xhci->event_ring->dequeue) { deq = xhci_trb_virt_to_dma(xhci->event_ring->deq_seg, xhci->event_ring->dequeue); if (deq == 0) xhci_warn(xhci, "WARN wrong SW event ring dequeue ptr.\n"); /* Update HC event ring dequeue pointer */ temp_64 &= ERST_PTR_MASK; temp_64 |= ((u64) deq & (u64) ~ERST_PTR_MASK); } /* Clear the event handler busy flag to get irq ; reloads imod */ temp_64 |= ERST_EHB; xhci_write_64(xhci, temp_64, &xhci->ir_set->erst_dequeue); spin_unlock_irqrestore(&xhci->lock, flags); mxhci->handled_event_cnt += event_cnt - 1; mxhci->cpu_yield_cnt++; if ((schedule_again > 0) && !mxhci->xhci_remove_flag) tasklet_schedule(&mxhci->bh); } static ssize_t config_imod_store(struct device *pdev, struct device_attribute *attr, const char *buff, size_t size) { Loading Loading @@ -1292,6 +1403,8 @@ static int mxhci_hsic_probe(struct platform_device *pdev) mxhci->dev = &pdev->dev; mxhci->xhci_remove_flag = false; mxhci->xhci_shutdown_flag = false; mxhci->bh.func = mxhci_irq_bh; mxhci->bh.data = (unsigned long)mxhci; /* Get pinctrl if target uses pinctrl */ mxhci->hsic_pinctrl = devm_pinctrl_get(&pdev->dev); Loading Loading @@ -1589,6 +1702,8 @@ static int mxhci_hsic_remove(struct platform_device *pdev) pm_runtime_disable(&hcd->self.root_hub->dev); pm_runtime_barrier(&hcd->self.root_hub->dev); tasklet_kill(&mxhci->bh); usb_remove_hcd(xhci->shared_hcd); usb_put_hcd(xhci->shared_hcd); Loading
drivers/usb/host/xhci-ring.c +1 −1 Original line number Diff line number Diff line Loading @@ -2685,7 +2685,7 @@ cleanup: * Returns >0 for "possibly more events to process" (caller should call again), * otherwise 0 if done. In future, <0 returns should indicate error code. */ static int xhci_handle_event(struct xhci_hcd *xhci) int xhci_handle_event(struct xhci_hcd *xhci) { union xhci_trb *event; int update_ptrs = 1; Loading
drivers/usb/host/xhci.h +1 −0 Original line number Diff line number Diff line Loading @@ -1909,6 +1909,7 @@ int xhci_cancel_cmd(struct xhci_hcd *xhci, struct xhci_command *command, void xhci_ring_ep_doorbell(struct xhci_hcd *xhci, unsigned int slot_id, unsigned int ep_index, unsigned int stream_id); union xhci_trb *xhci_find_next_enqueue(struct xhci_ring *ring); int xhci_handle_event(struct xhci_hcd *xhci); /* xHCI roothub code */ void xhci_set_link_state(struct xhci_hcd *xhci, __le32 __iomem **port_array, Loading