aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/host/isp1760-hcd.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/host/isp1760-hcd.c')
-rw-r--r--drivers/usb/host/isp1760-hcd.c138
1 files changed, 94 insertions, 44 deletions
diff --git a/drivers/usb/host/isp1760-hcd.c b/drivers/usb/host/isp1760-hcd.c
index e399e235f656..14c9238a5017 100644
--- a/drivers/usb/host/isp1760-hcd.c
+++ b/drivers/usb/host/isp1760-hcd.c
@@ -21,6 +21,7 @@
21#include <linux/uaccess.h> 21#include <linux/uaccess.h>
22#include <linux/io.h> 22#include <linux/io.h>
23#include <linux/mm.h> 23#include <linux/mm.h>
24#include <linux/timer.h>
24#include <asm/unaligned.h> 25#include <asm/unaligned.h>
25#include <asm/cacheflush.h> 26#include <asm/cacheflush.h>
26 27
@@ -39,7 +40,6 @@ struct isp1760_hcd {
39 int int_done_map; 40 int int_done_map;
40 struct memory_chunk memory_pool[BLOCKS]; 41 struct memory_chunk memory_pool[BLOCKS];
41 struct list_head controlqhs, bulkqhs, interruptqhs; 42 struct list_head controlqhs, bulkqhs, interruptqhs;
42 int active_ptds;
43 43
44 /* periodic schedule support */ 44 /* periodic schedule support */
45#define DEFAULT_I_TDPS 1024 45#define DEFAULT_I_TDPS 1024
@@ -489,10 +489,6 @@ static int isp1760_hc_setup(struct usb_hcd *hcd)
489 16 : 32, (priv->devflags & ISP1760_FLAG_ANALOG_OC) ? 489 16 : 32, (priv->devflags & ISP1760_FLAG_ANALOG_OC) ?
490 "analog" : "digital"); 490 "analog" : "digital");
491 491
492 /* This is weird: at the first plug-in of a device there seems to be
493 one packet queued that never gets returned? */
494 priv->active_ptds = -1;
495
496 /* ATL reset */ 492 /* ATL reset */
497 reg_write32(hcd->regs, HC_HW_MODE_CTRL, hwmode | ALL_ATX_RESET); 493 reg_write32(hcd->regs, HC_HW_MODE_CTRL, hwmode | ALL_ATX_RESET);
498 mdelay(10); 494 mdelay(10);
@@ -741,8 +737,8 @@ static void start_bus_transfer(struct usb_hcd *hcd, u32 ptd_offset, int slot,
741 qh->slot = slot; 737 qh->slot = slot;
742 qtd->status = QTD_XFER_STARTED; /* Set this before writing ptd, since 738 qtd->status = QTD_XFER_STARTED; /* Set this before writing ptd, since
743 interrupt routine may preempt and expects this value. */ 739 interrupt routine may preempt and expects this value. */
740 slots[slot].timestamp = jiffies;
744 ptd_write(hcd->regs, ptd_offset, slot, ptd); 741 ptd_write(hcd->regs, ptd_offset, slot, ptd);
745 priv->active_ptds++;
746 742
747 /* Make sure done map has not triggered from some unlinked transfer */ 743 /* Make sure done map has not triggered from some unlinked transfer */
748 if (ptd_offset == ATL_PTD_OFFSET) { 744 if (ptd_offset == ATL_PTD_OFFSET) {
@@ -1091,11 +1087,9 @@ static int check_atl_transfer(struct usb_hcd *hcd, struct ptd *ptd,
1091 return PTD_STATE_QTD_DONE; 1087 return PTD_STATE_QTD_DONE;
1092} 1088}
1093 1089
1094static irqreturn_t isp1760_irq(struct usb_hcd *hcd) 1090static void handle_done_ptds(struct usb_hcd *hcd)
1095{ 1091{
1096 struct isp1760_hcd *priv = hcd_to_priv(hcd); 1092 struct isp1760_hcd *priv = hcd_to_priv(hcd);
1097 u32 imask;
1098 irqreturn_t irqret = IRQ_NONE;
1099 struct ptd ptd; 1093 struct ptd ptd;
1100 struct isp1760_qh *qh; 1094 struct isp1760_qh *qh;
1101 int slot; 1095 int slot;
@@ -1104,27 +1098,14 @@ static irqreturn_t isp1760_irq(struct usb_hcd *hcd)
1104 u32 ptd_offset; 1098 u32 ptd_offset;
1105 struct isp1760_qtd *qtd; 1099 struct isp1760_qtd *qtd;
1106 int modified; 1100 int modified;
1107 static int last_active_ptds; 1101 int skip_map;
1108 int int_skip_map, atl_skip_map;
1109
1110 spin_lock(&priv->lock);
1111
1112 if (!(hcd->state & HC_STATE_RUNNING))
1113 goto leave;
1114
1115 imask = reg_read32(hcd->regs, HC_INTERRUPT_REG);
1116 if (unlikely(!imask))
1117 goto leave;
1118 reg_write32(hcd->regs, HC_INTERRUPT_REG, imask); /* Clear */
1119 1102
1120 int_skip_map = reg_read32(hcd->regs, HC_INT_PTD_SKIPMAP_REG); 1103 skip_map = reg_read32(hcd->regs, HC_INT_PTD_SKIPMAP_REG);
1121 atl_skip_map = reg_read32(hcd->regs, HC_ATL_PTD_SKIPMAP_REG); 1104 priv->int_done_map &= ~skip_map;
1122 priv->int_done_map |= reg_read32(hcd->regs, HC_INT_PTD_DONEMAP_REG); 1105 skip_map = reg_read32(hcd->regs, HC_ATL_PTD_SKIPMAP_REG);
1123 priv->atl_done_map |= reg_read32(hcd->regs, HC_ATL_PTD_DONEMAP_REG); 1106 priv->atl_done_map &= ~skip_map;
1124 priv->int_done_map &= ~int_skip_map;
1125 priv->atl_done_map &= ~atl_skip_map;
1126 1107
1127 modified = priv->int_done_map | priv->atl_done_map; 1108 modified = priv->int_done_map || priv->atl_done_map;
1128 1109
1129 while (priv->int_done_map || priv->atl_done_map) { 1110 while (priv->int_done_map || priv->atl_done_map) {
1130 if (priv->int_done_map) { 1111 if (priv->int_done_map) {
@@ -1163,7 +1144,6 @@ static irqreturn_t isp1760_irq(struct usb_hcd *hcd)
1163 slots[slot].qtd = NULL; 1144 slots[slot].qtd = NULL;
1164 qh = slots[slot].qh; 1145 qh = slots[slot].qh;
1165 slots[slot].qh = NULL; 1146 slots[slot].qh = NULL;
1166 priv->active_ptds--;
1167 qh->slot = -1; 1147 qh->slot = -1;
1168 1148
1169 WARN_ON(qtd->status != QTD_XFER_STARTED); 1149 WARN_ON(qtd->status != QTD_XFER_STARTED);
@@ -1234,22 +1214,28 @@ static irqreturn_t isp1760_irq(struct usb_hcd *hcd)
1234 1214
1235 if (modified) 1215 if (modified)
1236 schedule_ptds(hcd); 1216 schedule_ptds(hcd);
1217}
1237 1218
1238 /* ISP1760 Errata 2 explains that interrupts may be missed (or not 1219static irqreturn_t isp1760_irq(struct usb_hcd *hcd)
1239 happen?) if two USB devices are running simultaneously. Perhaps 1220{
1240 this happens when a PTD is finished during interrupt handling; 1221 struct isp1760_hcd *priv = hcd_to_priv(hcd);
1241 enable SOF interrupts if PTDs are still scheduled when exiting this 1222 u32 imask;
1242 interrupt handler, just to be safe. */ 1223 irqreturn_t irqret = IRQ_NONE;
1243 1224
1244 if (priv->active_ptds != last_active_ptds) { 1225 spin_lock(&priv->lock);
1245 if (priv->active_ptds > 0) 1226
1246 reg_write32(hcd->regs, HC_INTERRUPT_ENABLE, 1227 if (!(hcd->state & HC_STATE_RUNNING))
1247 INTERRUPT_ENABLE_SOT_MASK); 1228 goto leave;
1248 else 1229
1249 reg_write32(hcd->regs, HC_INTERRUPT_ENABLE, 1230 imask = reg_read32(hcd->regs, HC_INTERRUPT_REG);
1250 INTERRUPT_ENABLE_MASK); 1231 if (unlikely(!imask))
1251 last_active_ptds = priv->active_ptds; 1232 goto leave;
1252 } 1233 reg_write32(hcd->regs, HC_INTERRUPT_REG, imask); /* Clear */
1234
1235 priv->int_done_map |= reg_read32(hcd->regs, HC_INT_PTD_DONEMAP_REG);
1236 priv->atl_done_map |= reg_read32(hcd->regs, HC_ATL_PTD_DONEMAP_REG);
1237
1238 handle_done_ptds(hcd);
1253 1239
1254 irqret = IRQ_HANDLED; 1240 irqret = IRQ_HANDLED;
1255leave: 1241leave:
@@ -1258,6 +1244,63 @@ leave:
1258 return irqret; 1244 return irqret;
1259} 1245}
1260 1246
1247/*
1248 * Workaround for problem described in chip errata 2:
1249 *
1250 * Sometimes interrupts are not generated when ATL (not INT?) completion occurs.
1251 * One solution suggested in the errata is to use SOF interrupts _instead_of_
1252 * ATL done interrupts (the "instead of" might be important since it seems
1253 * enabling ATL interrupts also causes the chip to sometimes - rarely - "forget"
1254 * to set the PTD's done bit in addition to not generating an interrupt!).
1255 *
1256 * So if we use SOF + ATL interrupts, we sometimes get stale PTDs since their
1257 * done bit is not being set. This is bad - it blocks the endpoint until reboot.
1258 *
1259 * If we use SOF interrupts only, we get latency between ptd completion and the
1260 * actual handling. This is very noticeable in testusb runs which takes several
1261 * minutes longer without ATL interrupts.
1262 *
1263 * A better solution is to run the code below every SLOT_CHECK_PERIOD ms. If it
1264 * finds active ATL slots which are older than SLOT_TIMEOUT ms, it checks the
1265 * slot's ACTIVE and VALID bits. If these are not set, the ptd is considered
1266 * completed and its done map bit is set.
1267 *
1268 * The values of SLOT_TIMEOUT and SLOT_CHECK_PERIOD have been arbitrarily chosen
1269 * not to cause too much lag when this HW bug occurs, while still hopefully
1270 * ensuring that the check does not falsely trigger.
1271 */
1272#define SLOT_TIMEOUT 180
1273#define SLOT_CHECK_PERIOD 200
1274static struct timer_list errata2_timer;
1275
1276void errata2_function(unsigned long data)
1277{
1278 struct usb_hcd *hcd = (struct usb_hcd *) data;
1279 struct isp1760_hcd *priv = hcd_to_priv(hcd);
1280 int slot;
1281 struct ptd ptd;
1282 unsigned long spinflags;
1283
1284 spin_lock_irqsave(&priv->lock, spinflags);
1285
1286 for (slot = 0; slot < 32; slot++)
1287 if ((priv->atl_slots[slot].qh || priv->atl_slots[slot].qtd) &&
1288 time_after(jiffies + SLOT_TIMEOUT * HZ / 1000,
1289 priv->atl_slots[slot].timestamp)) {
1290 ptd_read(hcd->regs, ATL_PTD_OFFSET, slot, &ptd);
1291 if (!FROM_DW0_VALID(ptd.dw0) &&
1292 !FROM_DW3_ACTIVE(ptd.dw3))
1293 priv->atl_done_map |= 1 << slot;
1294 }
1295
1296 handle_done_ptds(hcd);
1297
1298 spin_unlock_irqrestore(&priv->lock, spinflags);
1299
1300 errata2_timer.expires = jiffies + SLOT_CHECK_PERIOD * HZ / 1000;
1301 add_timer(&errata2_timer);
1302}
1303
1261static int isp1760_run(struct usb_hcd *hcd) 1304static int isp1760_run(struct usb_hcd *hcd)
1262{ 1305{
1263 int retval; 1306 int retval;
@@ -1303,6 +1346,12 @@ static int isp1760_run(struct usb_hcd *hcd)
1303 if (retval) 1346 if (retval)
1304 return retval; 1347 return retval;
1305 1348
1349 init_timer(&errata2_timer);
1350 errata2_timer.function = errata2_function;
1351 errata2_timer.data = (unsigned long) hcd;
1352 errata2_timer.expires = jiffies + SLOT_CHECK_PERIOD * HZ / 1000;
1353 add_timer(&errata2_timer);
1354
1306 chipid = reg_read32(hcd->regs, HC_CHIP_ID_REG); 1355 chipid = reg_read32(hcd->regs, HC_CHIP_ID_REG);
1307 dev_info(hcd->self.controller, "USB ISP %04x HW rev. %d started\n", 1356 dev_info(hcd->self.controller, "USB ISP %04x HW rev. %d started\n",
1308 chipid & 0xffff, chipid >> 16); 1357 chipid & 0xffff, chipid >> 16);
@@ -1561,7 +1610,6 @@ static void kill_transfer(struct usb_hcd *hcd, struct urb *urb,
1561 } 1610 }
1562 1611
1563 qh->slot = -1; 1612 qh->slot = -1;
1564 priv->active_ptds--;
1565} 1613}
1566 1614
1567static int isp1760_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, 1615static int isp1760_urb_dequeue(struct usb_hcd *hcd, struct urb *urb,
@@ -2012,6 +2060,8 @@ static void isp1760_stop(struct usb_hcd *hcd)
2012 struct isp1760_hcd *priv = hcd_to_priv(hcd); 2060 struct isp1760_hcd *priv = hcd_to_priv(hcd);
2013 u32 temp; 2061 u32 temp;
2014 2062
2063 del_timer(&errata2_timer);
2064
2015 isp1760_hub_control(hcd, ClearPortFeature, USB_PORT_FEAT_POWER, 1, 2065 isp1760_hub_control(hcd, ClearPortFeature, USB_PORT_FEAT_POWER, 1,
2016 NULL, 0); 2066 NULL, 0);
2017 mdelay(20); 2067 mdelay(20);