Greg, is that patch on your list or did it get lost? * Sebastian Andrzej Siewior | 2011-02-08 21:07:40 [+0100]: >The document says: >|2.1 Problem description >| When at least two USB devices are simultaneously running, it is observed that >| sometimes the INT corresponding to one of the USB devices stops occurring. This may >| be observed sometimes with USB-to-serial or USB-to-network devices. >| The problem is not noticed when only USB mass storage devices are running. >|2.2 Implication >| This issue is because of the clearing of the respective Done Map bit on reading the ATL >| PTD Done Map register when an INT is generated by another PTD completion, but is not >| found set on that read access. In this situation, the respective Done Map bit will remain >| reset and no further INT will be asserted so the data transfer corresponding to that USB >| device will stop. >|2.3 Workaround >| An SOF INT can be used instead of an ATL INT with polling on Done bits. A time-out can >| be implemented and if a certain Done bit is never set, verification of the PTD completion >| can be done by reading PTD contents (valid bit). >| This is a proven workaround implemented in software. > >Russell King run into this with an USB-to-serial converter. This patch >implements his suggestion to enable the high frequent SOF interrupt only >at the time we have ATL packages queued. It goes even one step further >and enables the SOF interrupt only if we have more than one ATL packet >queued at the same time. > >Cc: <stable@xxxxxxxxxx> # [2.6.35.x, 2.6.36.x, 2.6.37.x] >Tested-by: Russell King <rmk+kernel@xxxxxxxxxxxxxxxx> >Signed-off-by: Sebastian Andrzej Siewior <bigeasy@xxxxxxxxxxxxx> >--- >v1..v2: use the register offset instead of the value. >v2..v3: change patch title > > drivers/usb/host/isp1760-hcd.c | 22 ++++++++++++++++------ > drivers/usb/host/isp1760-hcd.h | 1 + > 2 files changed, 17 insertions(+), 6 deletions(-) > >diff --git a/drivers/usb/host/isp1760-hcd.c b/drivers/usb/host/isp1760-hcd.c >index bdba8c5..c470cc8 100644 >--- a/drivers/usb/host/isp1760-hcd.c >+++ b/drivers/usb/host/isp1760-hcd.c >@@ -33,6 +33,7 @@ struct isp1760_hcd { > struct inter_packet_info atl_ints[32]; > struct inter_packet_info int_ints[32]; > struct memory_chunk memory_pool[BLOCKS]; >+ u32 atl_queued; > > /* periodic schedule support */ > #define DEFAULT_I_TDPS 1024 >@@ -850,6 +851,11 @@ static void enqueue_an_ATL_packet(struct usb_hcd *hcd, struct isp1760_qh *qh, > skip_map &= ~queue_entry; > isp1760_writel(skip_map, hcd->regs + HC_ATL_PTD_SKIPMAP_REG); > >+ priv->atl_queued++; >+ if (priv->atl_queued == 2) >+ isp1760_writel(INTERRUPT_ENABLE_SOT_MASK, >+ hcd->regs + HC_INTERRUPT_ENABLE); >+ > buffstatus = isp1760_readl(hcd->regs + HC_BUFFER_STATUS_REG); > buffstatus |= ATL_BUFFER; > isp1760_writel(buffstatus, hcd->regs + HC_BUFFER_STATUS_REG); >@@ -992,6 +998,7 @@ static void do_atl_int(struct usb_hcd *usb_hcd) > u32 dw3; > > status = 0; >+ priv->atl_queued--; > > queue_entry = __ffs(done_map); > done_map &= ~(1 << queue_entry); >@@ -1054,11 +1061,6 @@ static void do_atl_int(struct usb_hcd *usb_hcd) > * device is not able to send data fast enough. > * This happens mostly on slower hardware. > */ >- printk(KERN_NOTICE "Reloading ptd %p/%p... qh %p read: " >- "%d of %zu done: %08x cur: %08x\n", qtd, >- urb, qh, PTD_XFERRED_LENGTH(dw3), >- qtd->length, done_map, >- (1 << queue_entry)); > > /* RL counter = ERR counter */ > dw3 &= ~(0xf << 19); >@@ -1086,6 +1088,11 @@ static void do_atl_int(struct usb_hcd *usb_hcd) > priv_write_copy(priv, (u32 *)&ptd, usb_hcd->regs + > atl_regs, sizeof(ptd)); > >+ priv->atl_queued++; >+ if (priv->atl_queued == 2) >+ isp1760_writel(INTERRUPT_ENABLE_SOT_MASK, >+ usb_hcd->regs + HC_INTERRUPT_ENABLE); >+ > buffstatus = isp1760_readl(usb_hcd->regs + > HC_BUFFER_STATUS_REG); > buffstatus |= ATL_BUFFER; >@@ -1191,6 +1198,9 @@ static void do_atl_int(struct usb_hcd *usb_hcd) > skip_map = isp1760_readl(usb_hcd->regs + > HC_ATL_PTD_SKIPMAP_REG); > } >+ if (priv->atl_queued <= 1) >+ isp1760_writel(INTERRUPT_ENABLE_MASK, >+ usb_hcd->regs + HC_INTERRUPT_ENABLE); > } > > static void do_intl_int(struct usb_hcd *usb_hcd) >@@ -1770,7 +1780,7 @@ static irqreturn_t isp1760_irq(struct usb_hcd *usb_hcd) > goto leave; > > isp1760_writel(imask, usb_hcd->regs + HC_INTERRUPT_REG); >- if (imask & HC_ATL_INT) >+ if (imask & (HC_ATL_INT | HC_SOT_INT)) > do_atl_int(usb_hcd); > > if (imask & HC_INTL_INT) >diff --git a/drivers/usb/host/isp1760-hcd.h b/drivers/usb/host/isp1760-hcd.h >index 6931ef5..612bce5 100644 >--- a/drivers/usb/host/isp1760-hcd.h >+++ b/drivers/usb/host/isp1760-hcd.h >@@ -69,6 +69,7 @@ void deinit_kmem_cache(void); > > #define HC_INTERRUPT_ENABLE 0x314 > #define INTERRUPT_ENABLE_MASK (HC_INTL_INT | HC_ATL_INT | HC_EOT_INT) >+#define INTERRUPT_ENABLE_SOT_MASK (HC_INTL_INT | HC_SOT_INT | HC_EOT_INT) > > #define HC_ISO_INT (1 << 9) > #define HC_ATL_INT (1 << 8) >-- >1.7.3.2 Sebastian -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html