aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/host/isp1760-hcd.c
diff options
context:
space:
mode:
authorArvid Brodin <arvid.brodin@enea.com>2011-08-21 02:29:28 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2011-08-22 18:32:46 -0400
commit6477acc0814fc7aadfe3d723d2596fb4eb6d1732 (patch)
tree58246dfcdaf790e3f29c99f95a38faa0639a2bfd /drivers/usb/host/isp1760-hcd.c
parent38679b720014d89b192c38d4c604f5a718b9788d (diff)
usb/isp1760: Fix problems that trigger WARNING at line 1136.
1) A bug in the usage of time_after() in errata2_function(). 2) Clear done_maps just prior to starting a new transfer in start_bus_transfer(), instead of just after, when done_map bits might have been validly set by the started transfer. Signed-off-by: Arvid Brodin <arvid.brodin@enea.com> Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/host/isp1760-hcd.c')
-rw-r--r--drivers/usb/host/isp1760-hcd.c38
1 files changed, 20 insertions, 18 deletions
diff --git a/drivers/usb/host/isp1760-hcd.c b/drivers/usb/host/isp1760-hcd.c
index 1eb69e050941..11367b45d511 100644
--- a/drivers/usb/host/isp1760-hcd.c
+++ b/drivers/usb/host/isp1760-hcd.c
@@ -732,28 +732,29 @@ static void start_bus_transfer(struct usb_hcd *hcd, u32 ptd_offset, int slot,
732 WARN_ON(slots[slot].qh); 732 WARN_ON(slots[slot].qh);
733 WARN_ON(qtd->status != QTD_PAYLOAD_ALLOC); 733 WARN_ON(qtd->status != QTD_PAYLOAD_ALLOC);
734 734
735 slots[slot].qtd = qtd;
736 slots[slot].qh = qh;
737 qh->slot = slot;
738 qtd->status = QTD_XFER_STARTED; /* Set this before writing ptd, since
739 interrupt routine may preempt and expects this value. */
740 slots[slot].timestamp = jiffies;
741 ptd_write(hcd->regs, ptd_offset, slot, ptd);
742
743 /* Make sure done map has not triggered from some unlinked transfer */ 735 /* Make sure done map has not triggered from some unlinked transfer */
744 if (ptd_offset == ATL_PTD_OFFSET) { 736 if (ptd_offset == ATL_PTD_OFFSET) {
745 priv->atl_done_map |= reg_read32(hcd->regs, 737 priv->atl_done_map |= reg_read32(hcd->regs,
746 HC_ATL_PTD_DONEMAP_REG); 738 HC_ATL_PTD_DONEMAP_REG);
747 priv->atl_done_map &= ~(1 << qh->slot); 739 priv->atl_done_map &= ~(1 << slot);
740 } else {
741 priv->int_done_map |= reg_read32(hcd->regs,
742 HC_INT_PTD_DONEMAP_REG);
743 priv->int_done_map &= ~(1 << slot);
744 }
748 745
746 qh->slot = slot;
747 qtd->status = QTD_XFER_STARTED;
748 slots[slot].timestamp = jiffies;
749 slots[slot].qtd = qtd;
750 slots[slot].qh = qh;
751 ptd_write(hcd->regs, ptd_offset, slot, ptd);
752
753 if (ptd_offset == ATL_PTD_OFFSET) {
749 skip_map = reg_read32(hcd->regs, HC_ATL_PTD_SKIPMAP_REG); 754 skip_map = reg_read32(hcd->regs, HC_ATL_PTD_SKIPMAP_REG);
750 skip_map &= ~(1 << qh->slot); 755 skip_map &= ~(1 << qh->slot);
751 reg_write32(hcd->regs, HC_ATL_PTD_SKIPMAP_REG, skip_map); 756 reg_write32(hcd->regs, HC_ATL_PTD_SKIPMAP_REG, skip_map);
752 } else { 757 } else {
753 priv->int_done_map |= reg_read32(hcd->regs,
754 HC_INT_PTD_DONEMAP_REG);
755 priv->int_done_map &= ~(1 << qh->slot);
756
757 skip_map = reg_read32(hcd->regs, HC_INT_PTD_SKIPMAP_REG); 758 skip_map = reg_read32(hcd->regs, HC_INT_PTD_SKIPMAP_REG);
758 skip_map &= ~(1 << qh->slot); 759 skip_map &= ~(1 << qh->slot);
759 reg_write32(hcd->regs, HC_INT_PTD_SKIPMAP_REG, skip_map); 760 reg_write32(hcd->regs, HC_INT_PTD_SKIPMAP_REG, skip_map);
@@ -1266,7 +1267,7 @@ leave:
1266 * not to cause too much lag when this HW bug occurs, while still hopefully 1267 * not to cause too much lag when this HW bug occurs, while still hopefully
1267 * ensuring that the check does not falsely trigger. 1268 * ensuring that the check does not falsely trigger.
1268 */ 1269 */
1269#define SLOT_TIMEOUT 180 1270#define SLOT_TIMEOUT 300
1270#define SLOT_CHECK_PERIOD 200 1271#define SLOT_CHECK_PERIOD 200
1271static struct timer_list errata2_timer; 1272static struct timer_list errata2_timer;
1272 1273
@@ -1281,16 +1282,17 @@ void errata2_function(unsigned long data)
1281 spin_lock_irqsave(&priv->lock, spinflags); 1282 spin_lock_irqsave(&priv->lock, spinflags);
1282 1283
1283 for (slot = 0; slot < 32; slot++) 1284 for (slot = 0; slot < 32; slot++)
1284 if ((priv->atl_slots[slot].qh || priv->atl_slots[slot].qtd) && 1285 if (priv->atl_slots[slot].qh && time_after(jiffies,
1285 time_after(jiffies + SLOT_TIMEOUT * HZ / 1000, 1286 priv->atl_slots[slot].timestamp +
1286 priv->atl_slots[slot].timestamp)) { 1287 SLOT_TIMEOUT * HZ / 1000)) {
1287 ptd_read(hcd->regs, ATL_PTD_OFFSET, slot, &ptd); 1288 ptd_read(hcd->regs, ATL_PTD_OFFSET, slot, &ptd);
1288 if (!FROM_DW0_VALID(ptd.dw0) && 1289 if (!FROM_DW0_VALID(ptd.dw0) &&
1289 !FROM_DW3_ACTIVE(ptd.dw3)) 1290 !FROM_DW3_ACTIVE(ptd.dw3))
1290 priv->atl_done_map |= 1 << slot; 1291 priv->atl_done_map |= 1 << slot;
1291 } 1292 }
1292 1293
1293 handle_done_ptds(hcd); 1294 if (priv->atl_done_map)
1295 handle_done_ptds(hcd);
1294 1296
1295 spin_unlock_irqrestore(&priv->lock, spinflags); 1297 spin_unlock_irqrestore(&priv->lock, spinflags);
1296 1298