aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/host/uhci-hcd.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/host/uhci-hcd.c')
-rw-r--r--drivers/usb/host/uhci-hcd.c84
1 files changed, 48 insertions, 36 deletions
diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
index e87692c31be4..49b9d390b95f 100644
--- a/drivers/usb/host/uhci-hcd.c
+++ b/drivers/usb/host/uhci-hcd.c
@@ -60,6 +60,11 @@ Randy Dunlap, Georg Acher, Deti Fliegl, Thomas Sailer, Roman Weissgaerber, \
60Alan Stern" 60Alan Stern"
61#define DRIVER_DESC "USB Universal Host Controller Interface driver" 61#define DRIVER_DESC "USB Universal Host Controller Interface driver"
62 62
63/* for flakey hardware, ignore overcurrent indicators */
64static int ignore_oc;
65module_param(ignore_oc, bool, S_IRUGO);
66MODULE_PARM_DESC(ignore_oc, "ignore hardware overcurrent indications");
67
63/* 68/*
64 * debug = 0, no debugging messages 69 * debug = 0, no debugging messages
65 * debug = 1, dump failed URBs except for stalls 70 * debug = 1, dump failed URBs except for stalls
@@ -87,6 +92,34 @@ static void suspend_rh(struct uhci_hcd *uhci, enum uhci_rh_state new_state);
87static void wakeup_rh(struct uhci_hcd *uhci); 92static void wakeup_rh(struct uhci_hcd *uhci);
88static void uhci_get_current_frame_number(struct uhci_hcd *uhci); 93static void uhci_get_current_frame_number(struct uhci_hcd *uhci);
89 94
95/*
96 * Calculate the link pointer DMA value for the first Skeleton QH in a frame.
97 */
98static __le32 uhci_frame_skel_link(struct uhci_hcd *uhci, int frame)
99{
100 int skelnum;
101
102 /*
103 * The interrupt queues will be interleaved as evenly as possible.
104 * There's not much to be done about period-1 interrupts; they have
105 * to occur in every frame. But we can schedule period-2 interrupts
106 * in odd-numbered frames, period-4 interrupts in frames congruent
107 * to 2 (mod 4), and so on. This way each frame only has two
108 * interrupt QHs, which will help spread out bandwidth utilization.
109 *
110 * ffs (Find First bit Set) does exactly what we need:
111 * 1,3,5,... => ffs = 0 => use skel_int2_qh = skelqh[8],
112 * 2,6,10,... => ffs = 1 => use skel_int4_qh = skelqh[7], etc.
113 * ffs >= 7 => not on any high-period queue, so use
114 * skel_int1_qh = skelqh[9].
115 * Add in UHCI_NUMFRAMES to insure at least one bit is set.
116 */
117 skelnum = 8 - (int) __ffs(frame | UHCI_NUMFRAMES);
118 if (skelnum <= 1)
119 skelnum = 9;
120 return UHCI_PTR_QH | cpu_to_le32(uhci->skelqh[skelnum]->dma_handle);
121}
122
90#include "uhci-debug.c" 123#include "uhci-debug.c"
91#include "uhci-q.c" 124#include "uhci-q.c"
92#include "uhci-hub.c" 125#include "uhci-hub.c"
@@ -169,6 +202,11 @@ static int resume_detect_interrupts_are_broken(struct uhci_hcd *uhci)
169{ 202{
170 int port; 203 int port;
171 204
205 /* If we have to ignore overcurrent events then almost by definition
206 * we can't depend on resume-detect interrupts. */
207 if (ignore_oc)
208 return 1;
209
172 switch (to_pci_dev(uhci_dev(uhci))->vendor) { 210 switch (to_pci_dev(uhci_dev(uhci))->vendor) {
173 default: 211 default:
174 break; 212 break;
@@ -199,24 +237,16 @@ static int resume_detect_interrupts_are_broken(struct uhci_hcd *uhci)
199 237
200static int remote_wakeup_is_broken(struct uhci_hcd *uhci) 238static int remote_wakeup_is_broken(struct uhci_hcd *uhci)
201{ 239{
202 static struct dmi_system_id broken_wakeup_table[] = {
203 {
204 .ident = "Asus A7V8X",
205 .matches = {
206 DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK"),
207 DMI_MATCH(DMI_BOARD_NAME, "A7V8X"),
208 DMI_MATCH(DMI_BOARD_VERSION, "REV 1.xx"),
209 }
210 },
211 { }
212 };
213 int port; 240 int port;
241 char *sys_info;
242 static char bad_Asus_board[] = "A7V8X";
214 243
215 /* One of Asus's motherboards has a bug which causes it to 244 /* One of Asus's motherboards has a bug which causes it to
216 * wake up immediately from suspend-to-RAM if any of the ports 245 * wake up immediately from suspend-to-RAM if any of the ports
217 * are connected. In such cases we will not set EGSM. 246 * are connected. In such cases we will not set EGSM.
218 */ 247 */
219 if (dmi_check_system(broken_wakeup_table)) { 248 sys_info = dmi_get_system_info(DMI_BOARD_NAME);
249 if (sys_info && !strcmp(sys_info, bad_Asus_board)) {
220 for (port = 0; port < uhci->rh_numports; ++port) { 250 for (port = 0; port < uhci->rh_numports; ++port) {
221 if (inw(uhci->io_addr + USBPORTSC1 + port * 2) & 251 if (inw(uhci->io_addr + USBPORTSC1 + port * 2) &
222 USBPORTSC_CCS) 252 USBPORTSC_CCS)
@@ -255,7 +285,9 @@ __acquires(uhci->lock)
255 int_enable = USBINTR_RESUME; 285 int_enable = USBINTR_RESUME;
256 if (remote_wakeup_is_broken(uhci)) 286 if (remote_wakeup_is_broken(uhci))
257 egsm_enable = 0; 287 egsm_enable = 0;
258 if (resume_detect_interrupts_are_broken(uhci) || !egsm_enable) 288 if (resume_detect_interrupts_are_broken(uhci) || !egsm_enable ||
289 !device_may_wakeup(
290 &uhci_to_hcd(uhci)->self.root_hub->dev))
259 uhci->working_RD = int_enable = 0; 291 uhci->working_RD = int_enable = 0;
260 292
261 outw(int_enable, uhci->io_addr + USBINTR); 293 outw(int_enable, uhci->io_addr + USBINTR);
@@ -627,32 +659,11 @@ static int uhci_start(struct usb_hcd *hcd)
627 /* 659 /*
628 * Fill the frame list: make all entries point to the proper 660 * Fill the frame list: make all entries point to the proper
629 * interrupt queue. 661 * interrupt queue.
630 *
631 * The interrupt queues will be interleaved as evenly as possible.
632 * There's not much to be done about period-1 interrupts; they have
633 * to occur in every frame. But we can schedule period-2 interrupts
634 * in odd-numbered frames, period-4 interrupts in frames congruent
635 * to 2 (mod 4), and so on. This way each frame only has two
636 * interrupt QHs, which will help spread out bandwidth utilization.
637 */ 662 */
638 for (i = 0; i < UHCI_NUMFRAMES; i++) { 663 for (i = 0; i < UHCI_NUMFRAMES; i++) {
639 int irq;
640
641 /*
642 * ffs (Find First bit Set) does exactly what we need:
643 * 1,3,5,... => ffs = 0 => use skel_int2_qh = skelqh[8],
644 * 2,6,10,... => ffs = 1 => use skel_int4_qh = skelqh[7], etc.
645 * ffs >= 7 => not on any high-period queue, so use
646 * skel_int1_qh = skelqh[9].
647 * Add UHCI_NUMFRAMES to insure at least one bit is set.
648 */
649 irq = 8 - (int) __ffs(i + UHCI_NUMFRAMES);
650 if (irq <= 1)
651 irq = 9;
652 664
653 /* Only place we don't use the frame list routines */ 665 /* Only place we don't use the frame list routines */
654 uhci->frame[i] = UHCI_PTR_QH | 666 uhci->frame[i] = uhci_frame_skel_link(uhci, i);
655 cpu_to_le32(uhci->skelqh[irq]->dma_handle);
656 } 667 }
657 668
658 /* 669 /*
@@ -921,7 +932,8 @@ static int __init uhci_hcd_init(void)
921{ 932{
922 int retval = -ENOMEM; 933 int retval = -ENOMEM;
923 934
924 printk(KERN_INFO DRIVER_DESC " " DRIVER_VERSION "\n"); 935 printk(KERN_INFO DRIVER_DESC " " DRIVER_VERSION "%s\n",
936 ignore_oc ? ", overcurrent ignored" : "");
925 937
926 if (usb_disabled()) 938 if (usb_disabled())
927 return -ENODEV; 939 return -ENODEV;