diff options
author | Arvid Brodin <arvid.brodin@enea.com> | 2011-08-21 02:29:28 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2011-08-22 18:32:46 -0400 |
commit | 6477acc0814fc7aadfe3d723d2596fb4eb6d1732 (patch) | |
tree | 58246dfcdaf790e3f29c99f95a38faa0639a2bfd /drivers/usb/host/isp1760-hcd.c | |
parent | 38679b720014d89b192c38d4c604f5a718b9788d (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.c | 38 |
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 |
1271 | static struct timer_list errata2_timer; | 1272 | static 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 | ||