Re: [PATCH] usb/isp1760: Implement Errata 2

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hello.

On 07-02-2011 17:46, Sebastian Andrzej Siewior wrote:

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>
[...]

diff --git a/drivers/usb/host/isp1760-hcd.c b/drivers/usb/host/isp1760-hcd.c
index bdba8c5..07761f7 100644
--- a/drivers/usb/host/isp1760-hcd.c
+++ b/drivers/usb/host/isp1760-hcd.c
[...]
@@ -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_MASK,
+				hcd->regs + INTERRUPT_ENABLE_SOT_MASK);

   Perhaps it's:

		isp1760_writel(INTERRUPT_ENABLE_[SOT_]MASK,
				hcd->regs + HC_INTERRUPT_ENABLE);

   Othrwise it doesn't make much sense...

@@ -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_MASK,
+				    usb_hcd->regs + INTERRUPT_ENABLE_SOT_MASK);

   Same here...

@@ -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);

   Here it seems correct.

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)

WBR, Sergei
--
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


[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux