aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorOlav Kongas <ok@artecdesign.ee>2005-11-03 10:38:14 -0500
committerGreg Kroah-Hartman <gregkh@suse.de>2006-01-04 16:48:29 -0500
commit959eea2191e8d74b16ef019b0f4bf875c14f4547 (patch)
treec535857225eec2a52ce18c162ed94c5f18427dee /drivers
parent535488fcf1e4b2331e1c4a1eb67ca09468c13507 (diff)
[PATCH] USB: isp116x-hcd: cleanup
The attached patch makes a cleanup of isp116x-hcd. Most of the volume of the patch comes from 2 sources: moving the code around to get rid of a few function prototypes and reworking register dumping functions/macros. Among other things, switched over from using procfs to debugfs. Cleanup. The following changes were made: - Rework register dumping code so it can be used for dumping to both syslog and debugfs. - Switch from procfs to debugfs.. - Die gracefully on Unrecoverable Error interrupt. - Fix memory leak in isp116x_urb_enqueue(), if HC happens to die in a narrow time window. - Fix a 'sparce' warning (unnecessary cast). - Report Devices Removable for root hub ports by default (was Devices Permanently Attached). - Move bus suspend/resume functions down in code to get rid of a few function prototypes. - A number of one-line cleanups. - Add an entry to MAINTAINERS. Signed-off-by: Olav Kongas <ok@artecdesign.ee> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> MAINTAINERS | 6 drivers/usb/host/isp116x-hcd.c | 429 ++++++++++++++++------------------------- drivers/usb/host/isp116x.h | 83 +++++-- 3 files changed, 230 insertions(+), 288 deletions(-)
Diffstat (limited to 'drivers')
-rw-r--r--drivers/usb/host/isp116x-hcd.c429
-rw-r--r--drivers/usb/host/isp116x.h83
2 files changed, 224 insertions, 288 deletions
diff --git a/drivers/usb/host/isp116x-hcd.c b/drivers/usb/host/isp116x-hcd.c
index 5f56c4a42f52..342cfadc999a 100644
--- a/drivers/usb/host/isp116x-hcd.c
+++ b/drivers/usb/host/isp116x-hcd.c
@@ -55,19 +55,13 @@
55/* enqueuing/finishing log of urbs */ 55/* enqueuing/finishing log of urbs */
56//#define URB_TRACE 56//#define URB_TRACE
57 57
58#include <linux/config.h>
59#include <linux/module.h> 58#include <linux/module.h>
60#include <linux/moduleparam.h>
61#include <linux/kernel.h>
62#include <linux/delay.h> 59#include <linux/delay.h>
63#include <linux/ioport.h> 60#include <linux/debugfs.h>
64#include <linux/sched.h> 61#include <linux/seq_file.h>
65#include <linux/slab.h>
66#include <linux/smp_lock.h>
67#include <linux/errno.h> 62#include <linux/errno.h>
68#include <linux/init.h> 63#include <linux/init.h>
69#include <linux/list.h> 64#include <linux/list.h>
70#include <linux/interrupt.h>
71#include <linux/usb.h> 65#include <linux/usb.h>
72#include <linux/usb_isp116x.h> 66#include <linux/usb_isp116x.h>
73#include <linux/platform_device.h> 67#include <linux/platform_device.h>
@@ -77,14 +71,10 @@
77#include <asm/system.h> 71#include <asm/system.h>
78#include <asm/byteorder.h> 72#include <asm/byteorder.h>
79 73
80#ifndef DEBUG
81# define STUB_DEBUG_FILE
82#endif
83
84#include "../core/hcd.h" 74#include "../core/hcd.h"
85#include "isp116x.h" 75#include "isp116x.h"
86 76
87#define DRIVER_VERSION "05 Aug 2005" 77#define DRIVER_VERSION "03 Nov 2005"
88#define DRIVER_DESC "ISP116x USB Host Controller Driver" 78#define DRIVER_DESC "ISP116x USB Host Controller Driver"
89 79
90MODULE_DESCRIPTION(DRIVER_DESC); 80MODULE_DESCRIPTION(DRIVER_DESC);
@@ -305,9 +295,8 @@ static void postproc_atl_queue(struct isp116x *isp116x)
305 udev = urb->dev; 295 udev = urb->dev;
306 ptd = &ep->ptd; 296 ptd = &ep->ptd;
307 cc = PTD_GET_CC(ptd); 297 cc = PTD_GET_CC(ptd);
308
309 spin_lock(&urb->lock);
310 short_not_ok = 1; 298 short_not_ok = 1;
299 spin_lock(&urb->lock);
311 300
312 /* Data underrun is special. For allowed underrun 301 /* Data underrun is special. For allowed underrun
313 we clear the error and continue as normal. For 302 we clear the error and continue as normal. For
@@ -420,7 +409,7 @@ static void postproc_atl_queue(struct isp116x *isp116x)
420 ep->nextpid = 0; 409 ep->nextpid = 0;
421 break; 410 break;
422 default: 411 default:
423 BUG_ON(1); 412 BUG();
424 } 413 }
425 spin_unlock(&urb->lock); 414 spin_unlock(&urb->lock);
426 } 415 }
@@ -628,8 +617,12 @@ static irqreturn_t isp116x_irq(struct usb_hcd *hcd, struct pt_regs *regs)
628 u32 intstat = isp116x_read_reg32(isp116x, HCINTSTAT); 617 u32 intstat = isp116x_read_reg32(isp116x, HCINTSTAT);
629 isp116x_write_reg32(isp116x, HCINTSTAT, intstat); 618 isp116x_write_reg32(isp116x, HCINTSTAT, intstat);
630 if (intstat & HCINT_UE) { 619 if (intstat & HCINT_UE) {
631 ERR("Unrecoverable error\n"); 620 ERR("Unrecoverable error, HC is dead!\n");
632 /* What should we do here? Reset? */ 621 /* IRQ's are off, we do no DMA,
622 perfectly ready to die ... */
623 hcd->state = HC_STATE_HALT;
624 ret = IRQ_HANDLED;
625 goto done;
633 } 626 }
634 if (intstat & HCINT_RHSC) 627 if (intstat & HCINT_RHSC)
635 /* When root hub or any of its ports is going 628 /* When root hub or any of its ports is going
@@ -640,7 +633,6 @@ static irqreturn_t isp116x_irq(struct usb_hcd *hcd, struct pt_regs *regs)
640 if (intstat & HCINT_RD) { 633 if (intstat & HCINT_RD) {
641 DBG("---- remote wakeup\n"); 634 DBG("---- remote wakeup\n");
642 usb_hcd_resume_root_hub(hcd); 635 usb_hcd_resume_root_hub(hcd);
643 ret = IRQ_HANDLED;
644 } 636 }
645 irqstat &= ~HCuPINT_OPR; 637 irqstat &= ~HCuPINT_OPR;
646 ret = IRQ_HANDLED; 638 ret = IRQ_HANDLED;
@@ -651,6 +643,7 @@ static irqreturn_t isp116x_irq(struct usb_hcd *hcd, struct pt_regs *regs)
651 } 643 }
652 644
653 isp116x_write_reg16(isp116x, HCuPINTENB, isp116x->irqenb); 645 isp116x_write_reg16(isp116x, HCuPINTENB, isp116x->irqenb);
646 done:
654 spin_unlock(&isp116x->lock); 647 spin_unlock(&isp116x->lock);
655 return ret; 648 return ret;
656} 649}
@@ -724,6 +717,7 @@ static int isp116x_urb_enqueue(struct usb_hcd *hcd,
724 717
725 spin_lock_irqsave(&isp116x->lock, flags); 718 spin_lock_irqsave(&isp116x->lock, flags);
726 if (!HC_IS_RUNNING(hcd->state)) { 719 if (!HC_IS_RUNNING(hcd->state)) {
720 kfree(ep);
727 ret = -ENODEV; 721 ret = -ENODEV;
728 goto fail; 722 goto fail;
729 } 723 }
@@ -888,7 +882,7 @@ static void isp116x_endpoint_disable(struct usb_hcd *hcd,
888 struct usb_host_endpoint *hep) 882 struct usb_host_endpoint *hep)
889{ 883{
890 int i; 884 int i;
891 struct isp116x_ep *ep = hep->hcpriv;; 885 struct isp116x_ep *ep = hep->hcpriv;
892 886
893 if (!ep) 887 if (!ep)
894 return; 888 return;
@@ -916,8 +910,6 @@ static int isp116x_get_frame(struct usb_hcd *hcd)
916 return (int)fmnum; 910 return (int)fmnum;
917} 911}
918 912
919/*----------------------------------------------------------------*/
920
921/* 913/*
922 Adapted from ohci-hub.c. Currently we don't support autosuspend. 914 Adapted from ohci-hub.c. Currently we don't support autosuspend.
923*/ 915*/
@@ -968,11 +960,10 @@ static void isp116x_hub_descriptor(struct isp116x *isp116x,
968 desc->bHubContrCurrent = 0; 960 desc->bHubContrCurrent = 0;
969 desc->bNbrPorts = (u8) (reg & 0x3); 961 desc->bNbrPorts = (u8) (reg & 0x3);
970 /* Power switching, device type, overcurrent. */ 962 /* Power switching, device type, overcurrent. */
971 desc->wHubCharacteristics = 963 desc->wHubCharacteristics = cpu_to_le16((u16) ((reg >> 8) & 0x1f));
972 (__force __u16) cpu_to_le16((u16) ((reg >> 8) & 0x1f));
973 desc->bPwrOn2PwrGood = (u8) ((reg >> 24) & 0xff); 964 desc->bPwrOn2PwrGood = (u8) ((reg >> 24) & 0xff);
974 /* two bitmaps: ports removable, and legacy PortPwrCtrlMask */ 965 /* two bitmaps: ports removable, and legacy PortPwrCtrlMask */
975 desc->bitmap[0] = desc->bNbrPorts == 1 ? 1 << 1 : 3 << 1; 966 desc->bitmap[0] = 0;
976 desc->bitmap[1] = ~0; 967 desc->bitmap[1] = ~0;
977} 968}
978 969
@@ -1159,145 +1150,9 @@ static int isp116x_hub_control(struct usb_hcd *hcd,
1159 return ret; 1150 return ret;
1160} 1151}
1161 1152
1162#ifdef CONFIG_PM
1163
1164static int isp116x_bus_suspend(struct usb_hcd *hcd)
1165{
1166 struct isp116x *isp116x = hcd_to_isp116x(hcd);
1167 unsigned long flags;
1168 u32 val;
1169 int ret = 0;
1170
1171 spin_lock_irqsave(&isp116x->lock, flags);
1172
1173 val = isp116x_read_reg32(isp116x, HCCONTROL);
1174 switch (val & HCCONTROL_HCFS) {
1175 case HCCONTROL_USB_OPER:
1176 hcd->state = HC_STATE_QUIESCING;
1177 val &= (~HCCONTROL_HCFS & ~HCCONTROL_RWE);
1178 val |= HCCONTROL_USB_SUSPEND;
1179 if (hcd->remote_wakeup)
1180 val |= HCCONTROL_RWE;
1181 /* Wait for usb transfers to finish */
1182 mdelay(2);
1183 isp116x_write_reg32(isp116x, HCCONTROL, val);
1184 hcd->state = HC_STATE_SUSPENDED;
1185 /* Wait for devices to suspend */
1186 mdelay(5);
1187 case HCCONTROL_USB_SUSPEND:
1188 break;
1189 case HCCONTROL_USB_RESUME:
1190 isp116x_write_reg32(isp116x, HCCONTROL,
1191 (val & ~HCCONTROL_HCFS) |
1192 HCCONTROL_USB_RESET);
1193 case HCCONTROL_USB_RESET:
1194 ret = -EBUSY;
1195 break;
1196 default:
1197 ret = -EINVAL;
1198 }
1199
1200 spin_unlock_irqrestore(&isp116x->lock, flags);
1201 return ret;
1202}
1203
1204/* Get rid of these declarations later in cleanup */
1205static int isp116x_reset(struct usb_hcd *hcd);
1206static int isp116x_start(struct usb_hcd *hcd);
1207
1208static int isp116x_bus_resume(struct usb_hcd *hcd)
1209{
1210 struct isp116x *isp116x = hcd_to_isp116x(hcd);
1211 u32 val;
1212
1213 msleep(5);
1214 spin_lock_irq(&isp116x->lock);
1215
1216 val = isp116x_read_reg32(isp116x, HCCONTROL);
1217 switch (val & HCCONTROL_HCFS) {
1218 case HCCONTROL_USB_SUSPEND:
1219 val &= ~HCCONTROL_HCFS;
1220 val |= HCCONTROL_USB_RESUME;
1221 isp116x_write_reg32(isp116x, HCCONTROL, val);
1222 case HCCONTROL_USB_RESUME:
1223 break;
1224 case HCCONTROL_USB_OPER:
1225 spin_unlock_irq(&isp116x->lock);
1226 /* Without setting power_state here the
1227 SUSPENDED state won't be removed from
1228 sysfs/usbN/power.state as a response to remote
1229 wakeup. Maybe in the future. */
1230 hcd->self.root_hub->dev.power.power_state = PMSG_ON;
1231 return 0;
1232 default:
1233 /* HCCONTROL_USB_RESET: this may happen, when during
1234 suspension the HC lost power. Reinitialize completely */
1235 spin_unlock_irq(&isp116x->lock);
1236 DBG("Chip has been reset while suspended. Reinit from scratch.\n");
1237 isp116x_reset(hcd);
1238 isp116x_start(hcd);
1239 isp116x_hub_control(hcd, SetPortFeature,
1240 USB_PORT_FEAT_POWER, 1, NULL, 0);
1241 if ((isp116x->rhdesca & RH_A_NDP) == 2)
1242 isp116x_hub_control(hcd, SetPortFeature,
1243 USB_PORT_FEAT_POWER, 2, NULL, 0);
1244 hcd->self.root_hub->dev.power.power_state = PMSG_ON;
1245 return 0;
1246 }
1247
1248 val = isp116x->rhdesca & RH_A_NDP;
1249 while (val--) {
1250 u32 stat =
1251 isp116x_read_reg32(isp116x, val ? HCRHPORT2 : HCRHPORT1);
1252 /* force global, not selective, resume */
1253 if (!(stat & RH_PS_PSS))
1254 continue;
1255 DBG("%s: Resuming port %d\n", __func__, val);
1256 isp116x_write_reg32(isp116x, RH_PS_POCI, val
1257 ? HCRHPORT2 : HCRHPORT1);
1258 }
1259 spin_unlock_irq(&isp116x->lock);
1260
1261 hcd->state = HC_STATE_RESUMING;
1262 mdelay(20);
1263
1264 /* Go operational */
1265 spin_lock_irq(&isp116x->lock);
1266 val = isp116x_read_reg32(isp116x, HCCONTROL);
1267 isp116x_write_reg32(isp116x, HCCONTROL,
1268 (val & ~HCCONTROL_HCFS) | HCCONTROL_USB_OPER);
1269 spin_unlock_irq(&isp116x->lock);
1270 /* see analogous comment above */
1271 hcd->self.root_hub->dev.power.power_state = PMSG_ON;
1272 hcd->state = HC_STATE_RUNNING;
1273
1274 return 0;
1275}
1276
1277
1278#else
1279
1280#define isp116x_bus_suspend NULL
1281#define isp116x_bus_resume NULL
1282
1283#endif
1284
1285/*-----------------------------------------------------------------*/ 1153/*-----------------------------------------------------------------*/
1286 1154
1287#ifdef STUB_DEBUG_FILE 1155#ifdef CONFIG_DEBUG_FS
1288
1289static inline void create_debug_file(struct isp116x *isp116x)
1290{
1291}
1292
1293static inline void remove_debug_file(struct isp116x *isp116x)
1294{
1295}
1296
1297#else
1298
1299#include <linux/proc_fs.h>
1300#include <linux/seq_file.h>
1301 1156
1302static void dump_irq(struct seq_file *s, char *label, u16 mask) 1157static void dump_irq(struct seq_file *s, char *label, u16 mask)
1303{ 1158{
@@ -1321,13 +1176,9 @@ static void dump_int(struct seq_file *s, char *label, u32 mask)
1321 mask & HCINT_SF ? " sof" : "", mask & HCINT_SO ? " so" : ""); 1176 mask & HCINT_SF ? " sof" : "", mask & HCINT_SO ? " so" : "");
1322} 1177}
1323 1178
1324static int proc_isp116x_show(struct seq_file *s, void *unused) 1179static int isp116x_show_dbg(struct seq_file *s, void *unused)
1325{ 1180{
1326 struct isp116x *isp116x = s->private; 1181 struct isp116x *isp116x = s->private;
1327 struct isp116x_ep *ep;
1328 struct urb *urb;
1329 unsigned i;
1330 char *str;
1331 1182
1332 seq_printf(s, "%s\n%s version %s\n", 1183 seq_printf(s, "%s\n%s version %s\n",
1333 isp116x_to_hcd(isp116x)->product_desc, hcd_name, 1184 isp116x_to_hcd(isp116x)->product_desc, hcd_name,
@@ -1343,105 +1194,50 @@ static int proc_isp116x_show(struct seq_file *s, void *unused)
1343 } 1194 }
1344 1195
1345 spin_lock_irq(&isp116x->lock); 1196 spin_lock_irq(&isp116x->lock);
1346
1347 dump_irq(s, "hc_irq_enable", isp116x_read_reg16(isp116x, HCuPINTENB)); 1197 dump_irq(s, "hc_irq_enable", isp116x_read_reg16(isp116x, HCuPINTENB));
1348 dump_irq(s, "hc_irq_status", isp116x_read_reg16(isp116x, HCuPINT)); 1198 dump_irq(s, "hc_irq_status", isp116x_read_reg16(isp116x, HCuPINT));
1349 dump_int(s, "hc_int_enable", isp116x_read_reg32(isp116x, HCINTENB)); 1199 dump_int(s, "hc_int_enable", isp116x_read_reg32(isp116x, HCINTENB));
1350 dump_int(s, "hc_int_status", isp116x_read_reg32(isp116x, HCINTSTAT)); 1200 dump_int(s, "hc_int_status", isp116x_read_reg32(isp116x, HCINTSTAT));
1351 1201 isp116x_show_regs_seq(isp116x, s);
1352 list_for_each_entry(ep, &isp116x->async, schedule) {
1353
1354 switch (ep->nextpid) {
1355 case USB_PID_IN:
1356 str = "in";
1357 break;
1358 case USB_PID_OUT:
1359 str = "out";
1360 break;
1361 case USB_PID_SETUP:
1362 str = "setup";
1363 break;
1364 case USB_PID_ACK:
1365 str = "status";
1366 break;
1367 default:
1368 str = "?";
1369 break;
1370 };
1371 seq_printf(s, "%p, ep%d%s, maxpacket %d:\n", ep,
1372 ep->epnum, str, ep->maxpacket);
1373 list_for_each_entry(urb, &ep->hep->urb_list, urb_list) {
1374 seq_printf(s, " urb%p, %d/%d\n", urb,
1375 urb->actual_length,
1376 urb->transfer_buffer_length);
1377 }
1378 }
1379 if (!list_empty(&isp116x->async))
1380 seq_printf(s, "\n");
1381
1382 seq_printf(s, "periodic size= %d\n", PERIODIC_SIZE);
1383
1384 for (i = 0; i < PERIODIC_SIZE; i++) {
1385 ep = isp116x->periodic[i];
1386 if (!ep)
1387 continue;
1388 seq_printf(s, "%2d [%3d]:\n", i, isp116x->load[i]);
1389
1390 /* DUMB: prints shared entries multiple times */
1391 do {
1392 seq_printf(s, " %d/%p (%sdev%d ep%d%s max %d)\n",
1393 ep->period, ep,
1394 (ep->udev->speed ==
1395 USB_SPEED_FULL) ? "" : "ls ",
1396 ep->udev->devnum, ep->epnum,
1397 (ep->epnum ==
1398 0) ? "" : ((ep->nextpid ==
1399 USB_PID_IN) ? "in" : "out"),
1400 ep->maxpacket);
1401 ep = ep->next;
1402 } while (ep);
1403 }
1404 spin_unlock_irq(&isp116x->lock); 1202 spin_unlock_irq(&isp116x->lock);
1405 seq_printf(s, "\n"); 1203 seq_printf(s, "\n");
1406 1204
1407 return 0; 1205 return 0;
1408} 1206}
1409 1207
1410static int proc_isp116x_open(struct inode *inode, struct file *file) 1208static int isp116x_open_seq(struct inode *inode, struct file *file)
1411{ 1209{
1412 return single_open(file, proc_isp116x_show, PDE(inode)->data); 1210 return single_open(file, isp116x_show_dbg, inode->u.generic_ip);
1413} 1211}
1414 1212
1415static struct file_operations proc_ops = { 1213static struct file_operations isp116x_debug_fops = {
1416 .open = proc_isp116x_open, 1214 .open = isp116x_open_seq,
1417 .read = seq_read, 1215 .read = seq_read,
1418 .llseek = seq_lseek, 1216 .llseek = seq_lseek,
1419 .release = single_release, 1217 .release = single_release,
1420}; 1218};
1421 1219
1422/* expect just one isp116x per system */ 1220static int create_debug_file(struct isp116x *isp116x)
1423static const char proc_filename[] = "driver/isp116x";
1424
1425static void create_debug_file(struct isp116x *isp116x)
1426{ 1221{
1427 struct proc_dir_entry *pde; 1222 isp116x->dentry = debugfs_create_file(hcd_name,
1428 1223 S_IRUGO, NULL, isp116x,
1429 pde = create_proc_entry(proc_filename, 0, NULL); 1224 &isp116x_debug_fops);
1430 if (pde == NULL) 1225 if (!isp116x->dentry)
1431 return; 1226 return -ENOMEM;
1432 1227 return 0;
1433 pde->proc_fops = &proc_ops;
1434 pde->data = isp116x;
1435 isp116x->pde = pde;
1436} 1228}
1437 1229
1438static void remove_debug_file(struct isp116x *isp116x) 1230static void remove_debug_file(struct isp116x *isp116x)
1439{ 1231{
1440 if (isp116x->pde) 1232 debugfs_remove(isp116x->dentry);
1441 remove_proc_entry(proc_filename, NULL);
1442} 1233}
1443 1234
1444#endif 1235#else
1236
1237#define create_debug_file(d) 0
1238#define remove_debug_file(d) do{}while(0)
1239
1240#endif /* CONFIG_DEBUG_FS */
1445 1241
1446/*-----------------------------------------------------------------*/ 1242/*-----------------------------------------------------------------*/
1447 1243
@@ -1476,7 +1272,7 @@ static int isp116x_reset(struct usb_hcd *hcd)
1476 struct isp116x *isp116x = hcd_to_isp116x(hcd); 1272 struct isp116x *isp116x = hcd_to_isp116x(hcd);
1477 unsigned long t; 1273 unsigned long t;
1478 u16 clkrdy = 0; 1274 u16 clkrdy = 0;
1479 int ret = 0, timeout = 15 /* ms */ ; 1275 int ret, timeout = 15 /* ms */ ;
1480 1276
1481 ret = isp116x_sw_reset(isp116x); 1277 ret = isp116x_sw_reset(isp116x);
1482 if (ret) 1278 if (ret)
@@ -1492,7 +1288,7 @@ static int isp116x_reset(struct usb_hcd *hcd)
1492 break; 1288 break;
1493 } 1289 }
1494 if (!clkrdy) { 1290 if (!clkrdy) {
1495 ERR("Clock not ready after 20ms\n"); 1291 ERR("Clock not ready after %dms\n", timeout);
1496 /* After sw_reset the clock won't report to be ready, if 1292 /* After sw_reset the clock won't report to be ready, if
1497 H_WAKEUP pin is high. */ 1293 H_WAKEUP pin is high. */
1498 ERR("Please make sure that the H_WAKEUP pin is pulled low!\n"); 1294 ERR("Please make sure that the H_WAKEUP pin is pulled low!\n");
@@ -1610,12 +1406,128 @@ static int isp116x_start(struct usb_hcd *hcd)
1610 isp116x_write_reg32(isp116x, HCRHPORT1, RH_PS_CCS); 1406 isp116x_write_reg32(isp116x, HCRHPORT1, RH_PS_CCS);
1611 isp116x_write_reg32(isp116x, HCRHPORT2, RH_PS_CCS); 1407 isp116x_write_reg32(isp116x, HCRHPORT2, RH_PS_CCS);
1612 1408
1613 isp116x_show_regs(isp116x); 1409 isp116x_show_regs_log(isp116x);
1614 spin_unlock_irqrestore(&isp116x->lock, flags); 1410 spin_unlock_irqrestore(&isp116x->lock, flags);
1615 return 0; 1411 return 0;
1616} 1412}
1617 1413
1618/*-----------------------------------------------------------------*/ 1414#ifdef CONFIG_PM
1415
1416static int isp116x_bus_suspend(struct usb_hcd *hcd)
1417{
1418 struct isp116x *isp116x = hcd_to_isp116x(hcd);
1419 unsigned long flags;
1420 u32 val;
1421 int ret = 0;
1422
1423 spin_lock_irqsave(&isp116x->lock, flags);
1424
1425 val = isp116x_read_reg32(isp116x, HCCONTROL);
1426 switch (val & HCCONTROL_HCFS) {
1427 case HCCONTROL_USB_OPER:
1428 hcd->state = HC_STATE_QUIESCING;
1429 val &= (~HCCONTROL_HCFS & ~HCCONTROL_RWE);
1430 val |= HCCONTROL_USB_SUSPEND;
1431 if (hcd->remote_wakeup)
1432 val |= HCCONTROL_RWE;
1433 /* Wait for usb transfers to finish */
1434 mdelay(2);
1435 isp116x_write_reg32(isp116x, HCCONTROL, val);
1436 hcd->state = HC_STATE_SUSPENDED;
1437 /* Wait for devices to suspend */
1438 mdelay(5);
1439 case HCCONTROL_USB_SUSPEND:
1440 break;
1441 case HCCONTROL_USB_RESUME:
1442 isp116x_write_reg32(isp116x, HCCONTROL,
1443 (val & ~HCCONTROL_HCFS) |
1444 HCCONTROL_USB_RESET);
1445 case HCCONTROL_USB_RESET:
1446 ret = -EBUSY;
1447 break;
1448 default:
1449 ret = -EINVAL;
1450 }
1451
1452 spin_unlock_irqrestore(&isp116x->lock, flags);
1453 return ret;
1454}
1455
1456static int isp116x_bus_resume(struct usb_hcd *hcd)
1457{
1458 struct isp116x *isp116x = hcd_to_isp116x(hcd);
1459 u32 val;
1460
1461 msleep(5);
1462 spin_lock_irq(&isp116x->lock);
1463
1464 val = isp116x_read_reg32(isp116x, HCCONTROL);
1465 switch (val & HCCONTROL_HCFS) {
1466 case HCCONTROL_USB_SUSPEND:
1467 val &= ~HCCONTROL_HCFS;
1468 val |= HCCONTROL_USB_RESUME;
1469 isp116x_write_reg32(isp116x, HCCONTROL, val);
1470 case HCCONTROL_USB_RESUME:
1471 break;
1472 case HCCONTROL_USB_OPER:
1473 spin_unlock_irq(&isp116x->lock);
1474 /* Without setting power_state here the
1475 SUSPENDED state won't be removed from
1476 sysfs/usbN/power.state as a response to remote
1477 wakeup. Maybe in the future. */
1478 hcd->self.root_hub->dev.power.power_state = PMSG_ON;
1479 return 0;
1480 default:
1481 /* HCCONTROL_USB_RESET: this may happen, when during
1482 suspension the HC lost power. Reinitialize completely */
1483 spin_unlock_irq(&isp116x->lock);
1484 DBG("Chip has been reset while suspended. Reinit from scratch.\n");
1485 isp116x_reset(hcd);
1486 isp116x_start(hcd);
1487 isp116x_hub_control(hcd, SetPortFeature,
1488 USB_PORT_FEAT_POWER, 1, NULL, 0);
1489 if ((isp116x->rhdesca & RH_A_NDP) == 2)
1490 isp116x_hub_control(hcd, SetPortFeature,
1491 USB_PORT_FEAT_POWER, 2, NULL, 0);
1492 hcd->self.root_hub->dev.power.power_state = PMSG_ON;
1493 return 0;
1494 }
1495
1496 val = isp116x->rhdesca & RH_A_NDP;
1497 while (val--) {
1498 u32 stat =
1499 isp116x_read_reg32(isp116x, val ? HCRHPORT2 : HCRHPORT1);
1500 /* force global, not selective, resume */
1501 if (!(stat & RH_PS_PSS))
1502 continue;
1503 DBG("%s: Resuming port %d\n", __func__, val);
1504 isp116x_write_reg32(isp116x, RH_PS_POCI, val
1505 ? HCRHPORT2 : HCRHPORT1);
1506 }
1507 spin_unlock_irq(&isp116x->lock);
1508
1509 hcd->state = HC_STATE_RESUMING;
1510 msleep(20);
1511
1512 /* Go operational */
1513 spin_lock_irq(&isp116x->lock);
1514 val = isp116x_read_reg32(isp116x, HCCONTROL);
1515 isp116x_write_reg32(isp116x, HCCONTROL,
1516 (val & ~HCCONTROL_HCFS) | HCCONTROL_USB_OPER);
1517 spin_unlock_irq(&isp116x->lock);
1518 /* see analogous comment above */
1519 hcd->self.root_hub->dev.power.power_state = PMSG_ON;
1520 hcd->state = HC_STATE_RUNNING;
1521
1522 return 0;
1523}
1524
1525#else
1526
1527#define isp116x_bus_suspend NULL
1528#define isp116x_bus_resume NULL
1529
1530#endif
1619 1531
1620static struct hc_driver isp116x_hc_driver = { 1532static struct hc_driver isp116x_hc_driver = {
1621 .description = hcd_name, 1533 .description = hcd_name,
@@ -1745,12 +1657,19 @@ static int __init isp116x_probe(struct platform_device *pdev)
1745 } 1657 }
1746 1658
1747 ret = usb_add_hcd(hcd, irq, SA_INTERRUPT); 1659 ret = usb_add_hcd(hcd, irq, SA_INTERRUPT);
1748 if (ret != 0) 1660 if (ret)
1749 goto err6; 1661 goto err6;
1750 1662
1751 create_debug_file(isp116x); 1663 ret = create_debug_file(isp116x);
1664 if (ret) {
1665 ERR("Couldn't create debugfs entry\n");
1666 goto err7;
1667 }
1668
1752 return 0; 1669 return 0;
1753 1670
1671 err7:
1672 usb_remove_hcd(hcd);
1754 err6: 1673 err6:
1755 usb_put_hcd(hcd); 1674 usb_put_hcd(hcd);
1756 err5: 1675 err5:
@@ -1772,13 +1691,9 @@ static int __init isp116x_probe(struct platform_device *pdev)
1772*/ 1691*/
1773static int isp116x_suspend(struct platform_device *dev, pm_message_t state) 1692static int isp116x_suspend(struct platform_device *dev, pm_message_t state)
1774{ 1693{
1775 int ret = 0; 1694 VDBG("%s: state %x\n", __func__, state.event);
1776
1777 VDBG("%s: state %x\n", __func__, state);
1778
1779 dev->dev.power.power_state = state; 1695 dev->dev.power.power_state = state;
1780 1696 return 0;
1781 return ret;
1782} 1697}
1783 1698
1784/* 1699/*
@@ -1786,13 +1701,9 @@ static int isp116x_suspend(struct platform_device *dev, pm_message_t state)
1786*/ 1701*/
1787static int isp116x_resume(struct platform_device *dev) 1702static int isp116x_resume(struct platform_device *dev)
1788{ 1703{
1789 int ret = 0; 1704 VDBG("%s: state %x\n", __func__, dev->power.power_state.event);
1790
1791 VDBG("%s: state %x\n", __func__, dev->dev.power.power_state);
1792
1793 dev->dev.power.power_state = PMSG_ON; 1705 dev->dev.power.power_state = PMSG_ON;
1794 1706 return 0;
1795 return ret;
1796} 1707}
1797 1708
1798#else 1709#else
diff --git a/drivers/usb/host/isp116x.h b/drivers/usb/host/isp116x.h
index c6fec96785fe..a1b7c3813d3a 100644
--- a/drivers/usb/host/isp116x.h
+++ b/drivers/usb/host/isp116x.h
@@ -259,7 +259,7 @@ struct isp116x {
259 259
260 struct isp116x_platform_data *board; 260 struct isp116x_platform_data *board;
261 261
262 struct proc_dir_entry *pde; 262 struct dentry *dentry;
263 unsigned long stat1, stat2, stat4, stat8, stat16; 263 unsigned long stat1, stat2, stat4, stat8, stat16;
264 264
265 /* HC registers */ 265 /* HC registers */
@@ -450,7 +450,7 @@ static void isp116x_write_reg32(struct isp116x *isp116x, unsigned reg,
450 isp116x_write_data32(isp116x, (u32) val); 450 isp116x_write_data32(isp116x, (u32) val);
451} 451}
452 452
453#define isp116x_show_reg(d,r) { \ 453#define isp116x_show_reg_log(d,r,s) { \
454 if ((r) < 0x20) { \ 454 if ((r) < 0x20) { \
455 DBG("%-12s[%02x]: %08x\n", #r, \ 455 DBG("%-12s[%02x]: %08x\n", #r, \
456 r, isp116x_read_reg32(d, r)); \ 456 r, isp116x_read_reg32(d, r)); \
@@ -459,35 +459,60 @@ static void isp116x_write_reg32(struct isp116x *isp116x, unsigned reg,
459 r, isp116x_read_reg16(d, r)); \ 459 r, isp116x_read_reg16(d, r)); \
460 } \ 460 } \
461} 461}
462#define isp116x_show_reg_seq(d,r,s) { \
463 if ((r) < 0x20) { \
464 seq_printf(s, "%-12s[%02x]: %08x\n", #r, \
465 r, isp116x_read_reg32(d, r)); \
466 } else { \
467 seq_printf(s, "%-12s[%02x]: %04x\n", #r, \
468 r, isp116x_read_reg16(d, r)); \
469 } \
470}
462 471
463static inline void isp116x_show_regs(struct isp116x *isp116x) 472#define isp116x_show_regs(d,type,s) { \
473 isp116x_show_reg_##type(d, HCREVISION, s); \
474 isp116x_show_reg_##type(d, HCCONTROL, s); \
475 isp116x_show_reg_##type(d, HCCMDSTAT, s); \
476 isp116x_show_reg_##type(d, HCINTSTAT, s); \
477 isp116x_show_reg_##type(d, HCINTENB, s); \
478 isp116x_show_reg_##type(d, HCFMINTVL, s); \
479 isp116x_show_reg_##type(d, HCFMREM, s); \
480 isp116x_show_reg_##type(d, HCFMNUM, s); \
481 isp116x_show_reg_##type(d, HCLSTHRESH, s); \
482 isp116x_show_reg_##type(d, HCRHDESCA, s); \
483 isp116x_show_reg_##type(d, HCRHDESCB, s); \
484 isp116x_show_reg_##type(d, HCRHSTATUS, s); \
485 isp116x_show_reg_##type(d, HCRHPORT1, s); \
486 isp116x_show_reg_##type(d, HCRHPORT2, s); \
487 isp116x_show_reg_##type(d, HCHWCFG, s); \
488 isp116x_show_reg_##type(d, HCDMACFG, s); \
489 isp116x_show_reg_##type(d, HCXFERCTR, s); \
490 isp116x_show_reg_##type(d, HCuPINT, s); \
491 isp116x_show_reg_##type(d, HCuPINTENB, s); \
492 isp116x_show_reg_##type(d, HCCHIPID, s); \
493 isp116x_show_reg_##type(d, HCSCRATCH, s); \
494 isp116x_show_reg_##type(d, HCITLBUFLEN, s); \
495 isp116x_show_reg_##type(d, HCATLBUFLEN, s); \
496 isp116x_show_reg_##type(d, HCBUFSTAT, s); \
497 isp116x_show_reg_##type(d, HCRDITL0LEN, s); \
498 isp116x_show_reg_##type(d, HCRDITL1LEN, s); \
499}
500
501/*
502 Dump registers for debugfs.
503*/
504static inline void isp116x_show_regs_seq(struct isp116x *isp116x,
505 struct seq_file *s)
506{
507 isp116x_show_regs(isp116x, seq, s);
508}
509
510/*
511 Dump registers to syslog.
512*/
513static inline void isp116x_show_regs_log(struct isp116x *isp116x)
464{ 514{
465 isp116x_show_reg(isp116x, HCREVISION); 515 isp116x_show_regs(isp116x, log, NULL);
466 isp116x_show_reg(isp116x, HCCONTROL);
467 isp116x_show_reg(isp116x, HCCMDSTAT);
468 isp116x_show_reg(isp116x, HCINTSTAT);
469 isp116x_show_reg(isp116x, HCINTENB);
470 isp116x_show_reg(isp116x, HCFMINTVL);
471 isp116x_show_reg(isp116x, HCFMREM);
472 isp116x_show_reg(isp116x, HCFMNUM);
473 isp116x_show_reg(isp116x, HCLSTHRESH);
474 isp116x_show_reg(isp116x, HCRHDESCA);
475 isp116x_show_reg(isp116x, HCRHDESCB);
476 isp116x_show_reg(isp116x, HCRHSTATUS);
477 isp116x_show_reg(isp116x, HCRHPORT1);
478 isp116x_show_reg(isp116x, HCRHPORT2);
479 isp116x_show_reg(isp116x, HCHWCFG);
480 isp116x_show_reg(isp116x, HCDMACFG);
481 isp116x_show_reg(isp116x, HCXFERCTR);
482 isp116x_show_reg(isp116x, HCuPINT);
483 isp116x_show_reg(isp116x, HCuPINTENB);
484 isp116x_show_reg(isp116x, HCCHIPID);
485 isp116x_show_reg(isp116x, HCSCRATCH);
486 isp116x_show_reg(isp116x, HCITLBUFLEN);
487 isp116x_show_reg(isp116x, HCATLBUFLEN);
488 isp116x_show_reg(isp116x, HCBUFSTAT);
489 isp116x_show_reg(isp116x, HCRDITL0LEN);
490 isp116x_show_reg(isp116x, HCRDITL1LEN);
491} 516}
492 517
493#if defined(URB_TRACE) 518#if defined(URB_TRACE)