diff options
Diffstat (limited to 'drivers/usb/host')
-rw-r--r-- | drivers/usb/host/ehci-pci.c | 2 | ||||
-rw-r--r-- | drivers/usb/host/ohci-at91.c | 35 | ||||
-rw-r--r-- | drivers/usb/host/ohci-hcd.c | 2 | ||||
-rw-r--r-- | drivers/usb/host/ohci-pci.c | 2 | ||||
-rw-r--r-- | drivers/usb/host/ohci-s3c2410.c | 41 | ||||
-rw-r--r-- | drivers/usb/host/pci-quirks.c | 1 | ||||
-rw-r--r-- | drivers/usb/host/pci-quirks.h | 7 | ||||
-rw-r--r-- | drivers/usb/host/uhci-hcd.c | 9 | ||||
-rw-r--r-- | drivers/usb/host/uhci-hcd.h | 1 | ||||
-rw-r--r-- | drivers/usb/host/uhci-hub.c | 18 |
10 files changed, 69 insertions, 49 deletions
diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c index 1e03f1a5a5fd..a1bd2bea6deb 100644 --- a/drivers/usb/host/ehci-pci.c +++ b/drivers/usb/host/ehci-pci.c | |||
@@ -350,7 +350,7 @@ static const struct hc_driver ehci_pci_hc_driver = { | |||
350 | /* PCI driver selection metadata; PCI hotplugging uses this */ | 350 | /* PCI driver selection metadata; PCI hotplugging uses this */ |
351 | static const struct pci_device_id pci_ids [] = { { | 351 | static const struct pci_device_id pci_ids [] = { { |
352 | /* handle any USB 2.0 EHCI controller */ | 352 | /* handle any USB 2.0 EHCI controller */ |
353 | PCI_DEVICE_CLASS(((PCI_CLASS_SERIAL_USB << 8) | 0x20), ~0), | 353 | PCI_DEVICE_CLASS(PCI_CLASS_SERIAL_USB_EHCI, ~0), |
354 | .driver_data = (unsigned long) &ehci_pci_hc_driver, | 354 | .driver_data = (unsigned long) &ehci_pci_hc_driver, |
355 | }, | 355 | }, |
356 | { /* end: all zeroes */ } | 356 | { /* end: all zeroes */ } |
diff --git a/drivers/usb/host/ohci-at91.c b/drivers/usb/host/ohci-at91.c index 980030d684d5..6b7350b52419 100644 --- a/drivers/usb/host/ohci-at91.c +++ b/drivers/usb/host/ohci-at91.c | |||
@@ -20,7 +20,7 @@ | |||
20 | #include <asm/arch/board.h> | 20 | #include <asm/arch/board.h> |
21 | 21 | ||
22 | #ifndef CONFIG_ARCH_AT91RM9200 | 22 | #ifndef CONFIG_ARCH_AT91RM9200 |
23 | #error "This file is AT91RM9200 bus glue. CONFIG_ARCH_AT91RM9200 must be defined." | 23 | #error "CONFIG_ARCH_AT91RM9200 must be defined." |
24 | #endif | 24 | #endif |
25 | 25 | ||
26 | /* interface and function clocks */ | 26 | /* interface and function clocks */ |
@@ -84,8 +84,6 @@ static int usb_hcd_at91_remove (struct usb_hcd *, struct platform_device *); | |||
84 | * Allocates basic resources for this USB host controller, and | 84 | * Allocates basic resources for this USB host controller, and |
85 | * then invokes the start() method for the HCD associated with it | 85 | * then invokes the start() method for the HCD associated with it |
86 | * through the hotplug entry's driver_data. | 86 | * through the hotplug entry's driver_data. |
87 | * | ||
88 | * Store this function in the HCD's struct pci_driver as probe(). | ||
89 | */ | 87 | */ |
90 | int usb_hcd_at91_probe (const struct hc_driver *driver, struct platform_device *pdev) | 88 | int usb_hcd_at91_probe (const struct hc_driver *driver, struct platform_device *pdev) |
91 | { | 89 | { |
@@ -148,7 +146,6 @@ int usb_hcd_at91_probe (const struct hc_driver *driver, struct platform_device * | |||
148 | } | 146 | } |
149 | 147 | ||
150 | 148 | ||
151 | /* may be called without controller electrically present */ | ||
152 | /* may be called with controller, bus, and devices active */ | 149 | /* may be called with controller, bus, and devices active */ |
153 | 150 | ||
154 | /** | 151 | /** |
@@ -166,11 +163,11 @@ static int usb_hcd_at91_remove (struct usb_hcd *hcd, struct platform_device *pde | |||
166 | usb_remove_hcd(hcd); | 163 | usb_remove_hcd(hcd); |
167 | at91_stop_hc(pdev); | 164 | at91_stop_hc(pdev); |
168 | iounmap(hcd->regs); | 165 | iounmap(hcd->regs); |
169 | release_mem_region(hcd->rsrc_start, hcd->rsrc_len); | 166 | release_mem_region(hcd->rsrc_start, hcd->rsrc_len); |
170 | 167 | ||
171 | clk_put(fclk); | 168 | clk_put(fclk); |
172 | clk_put(iclk); | 169 | clk_put(iclk); |
173 | fclk = iclk = NULL; | 170 | fclk = iclk = NULL; |
174 | 171 | ||
175 | dev_set_drvdata(&pdev->dev, NULL); | 172 | dev_set_drvdata(&pdev->dev, NULL); |
176 | return 0; | 173 | return 0; |
@@ -235,8 +232,8 @@ static const struct hc_driver ohci_at91_hc_driver = { | |||
235 | .hub_control = ohci_hub_control, | 232 | .hub_control = ohci_hub_control, |
236 | 233 | ||
237 | #ifdef CONFIG_PM | 234 | #ifdef CONFIG_PM |
238 | .hub_suspend = ohci_hub_suspend, | 235 | .bus_suspend = ohci_bus_suspend, |
239 | .hub_resume = ohci_hub_resume, | 236 | .bus_resume = ohci_bus_resume, |
240 | #endif | 237 | #endif |
241 | .start_port_reset = ohci_start_port_reset, | 238 | .start_port_reset = ohci_start_port_reset, |
242 | }; | 239 | }; |
@@ -254,21 +251,21 @@ static int ohci_hcd_at91_drv_remove(struct platform_device *dev) | |||
254 | } | 251 | } |
255 | 252 | ||
256 | #ifdef CONFIG_PM | 253 | #ifdef CONFIG_PM |
257 | static int ohci_hcd_at91_drv_suspend(struct platform_device *dev, u32 state, u32 level) | ||
258 | { | ||
259 | printk("%s(%s:%d): not implemented yet\n", | ||
260 | __func__, __FILE__, __LINE__); | ||
261 | 254 | ||
255 | /* REVISIT suspend/resume look "too" simple here */ | ||
256 | |||
257 | static int | ||
258 | ohci_hcd_at91_drv_suspend(struct platform_device *dev, pm_message_t mesg) | ||
259 | { | ||
262 | clk_disable(fclk); | 260 | clk_disable(fclk); |
261 | clk_disable(iclk); | ||
263 | 262 | ||
264 | return 0; | 263 | return 0; |
265 | } | 264 | } |
266 | 265 | ||
267 | static int ohci_hcd_at91_drv_resume(struct platform_device *dev, u32 state) | 266 | static int ohci_hcd_at91_drv_resume(struct platform_device *dev) |
268 | { | 267 | { |
269 | printk("%s(%s:%d): not implemented yet\n", | 268 | clk_enable(iclk); |
270 | __func__, __FILE__, __LINE__); | ||
271 | |||
272 | clk_enable(fclk); | 269 | clk_enable(fclk); |
273 | 270 | ||
274 | return 0; | 271 | return 0; |
@@ -278,6 +275,8 @@ static int ohci_hcd_at91_drv_resume(struct platform_device *dev, u32 state) | |||
278 | #define ohci_hcd_at91_drv_resume NULL | 275 | #define ohci_hcd_at91_drv_resume NULL |
279 | #endif | 276 | #endif |
280 | 277 | ||
278 | MODULE_ALIAS("at91rm9200-ohci"); | ||
279 | |||
281 | static struct platform_driver ohci_hcd_at91_driver = { | 280 | static struct platform_driver ohci_hcd_at91_driver = { |
282 | .probe = ohci_hcd_at91_drv_probe, | 281 | .probe = ohci_hcd_at91_drv_probe, |
283 | .remove = ohci_hcd_at91_drv_remove, | 282 | .remove = ohci_hcd_at91_drv_remove, |
diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c index 544f7589912f..73f5a379d9b3 100644 --- a/drivers/usb/host/ohci-hcd.c +++ b/drivers/usb/host/ohci-hcd.c | |||
@@ -863,7 +863,7 @@ static int ohci_restart (struct ohci_hcd *ohci) | |||
863 | i = ohci->num_ports; | 863 | i = ohci->num_ports; |
864 | while (i--) | 864 | while (i--) |
865 | ohci_writel (ohci, RH_PS_PSS, | 865 | ohci_writel (ohci, RH_PS_PSS, |
866 | &ohci->regs->roothub.portstatus [temp]); | 866 | &ohci->regs->roothub.portstatus [i]); |
867 | ohci_dbg (ohci, "restart complete\n"); | 867 | ohci_dbg (ohci, "restart complete\n"); |
868 | } | 868 | } |
869 | return 0; | 869 | return 0; |
diff --git a/drivers/usb/host/ohci-pci.c b/drivers/usb/host/ohci-pci.c index 1bfe96f4d045..b268537e389e 100644 --- a/drivers/usb/host/ohci-pci.c +++ b/drivers/usb/host/ohci-pci.c | |||
@@ -206,7 +206,7 @@ static const struct hc_driver ohci_pci_hc_driver = { | |||
206 | 206 | ||
207 | static const struct pci_device_id pci_ids [] = { { | 207 | static const struct pci_device_id pci_ids [] = { { |
208 | /* handle any USB OHCI controller */ | 208 | /* handle any USB OHCI controller */ |
209 | PCI_DEVICE_CLASS((PCI_CLASS_SERIAL_USB << 8) | 0x10, ~0), | 209 | PCI_DEVICE_CLASS(PCI_CLASS_SERIAL_USB_OHCI, ~0), |
210 | .driver_data = (unsigned long) &ohci_pci_hc_driver, | 210 | .driver_data = (unsigned long) &ohci_pci_hc_driver, |
211 | }, { /* end: all zeroes */ } | 211 | }, { /* end: all zeroes */ } |
212 | }; | 212 | }; |
diff --git a/drivers/usb/host/ohci-s3c2410.c b/drivers/usb/host/ohci-s3c2410.c index 682bf2215660..1da5de573a6f 100644 --- a/drivers/usb/host/ohci-s3c2410.c +++ b/drivers/usb/host/ohci-s3c2410.c | |||
@@ -30,6 +30,7 @@ | |||
30 | /* clock device associated with the hcd */ | 30 | /* clock device associated with the hcd */ |
31 | 31 | ||
32 | static struct clk *clk; | 32 | static struct clk *clk; |
33 | static struct clk *usb_clk; | ||
33 | 34 | ||
34 | /* forward definitions */ | 35 | /* forward definitions */ |
35 | 36 | ||
@@ -37,7 +38,7 @@ static void s3c2410_hcd_oc(struct s3c2410_hcd_info *info, int port_oc); | |||
37 | 38 | ||
38 | /* conversion functions */ | 39 | /* conversion functions */ |
39 | 40 | ||
40 | struct s3c2410_hcd_info *to_s3c2410_info(struct usb_hcd *hcd) | 41 | static struct s3c2410_hcd_info *to_s3c2410_info(struct usb_hcd *hcd) |
41 | { | 42 | { |
42 | return hcd->self.controller->platform_data; | 43 | return hcd->self.controller->platform_data; |
43 | } | 44 | } |
@@ -47,6 +48,10 @@ static void s3c2410_start_hc(struct platform_device *dev, struct usb_hcd *hcd) | |||
47 | struct s3c2410_hcd_info *info = dev->dev.platform_data; | 48 | struct s3c2410_hcd_info *info = dev->dev.platform_data; |
48 | 49 | ||
49 | dev_dbg(&dev->dev, "s3c2410_start_hc:\n"); | 50 | dev_dbg(&dev->dev, "s3c2410_start_hc:\n"); |
51 | |||
52 | clk_enable(usb_clk); | ||
53 | mdelay(2); /* let the bus clock stabilise */ | ||
54 | |||
50 | clk_enable(clk); | 55 | clk_enable(clk); |
51 | 56 | ||
52 | if (info != NULL) { | 57 | if (info != NULL) { |
@@ -75,6 +80,7 @@ static void s3c2410_stop_hc(struct platform_device *dev) | |||
75 | } | 80 | } |
76 | 81 | ||
77 | clk_disable(clk); | 82 | clk_disable(clk); |
83 | clk_disable(usb_clk); | ||
78 | } | 84 | } |
79 | 85 | ||
80 | /* ohci_s3c2410_hub_status_data | 86 | /* ohci_s3c2410_hub_status_data |
@@ -316,7 +322,8 @@ static void s3c2410_hcd_oc(struct s3c2410_hcd_info *info, int port_oc) | |||
316 | * | 322 | * |
317 | */ | 323 | */ |
318 | 324 | ||
319 | void usb_hcd_s3c2410_remove (struct usb_hcd *hcd, struct platform_device *dev) | 325 | static void |
326 | usb_hcd_s3c2410_remove (struct usb_hcd *hcd, struct platform_device *dev) | ||
320 | { | 327 | { |
321 | usb_remove_hcd(hcd); | 328 | usb_remove_hcd(hcd); |
322 | s3c2410_stop_hc(dev); | 329 | s3c2410_stop_hc(dev); |
@@ -334,8 +341,8 @@ void usb_hcd_s3c2410_remove (struct usb_hcd *hcd, struct platform_device *dev) | |||
334 | * through the hotplug entry's driver_data. | 341 | * through the hotplug entry's driver_data. |
335 | * | 342 | * |
336 | */ | 343 | */ |
337 | int usb_hcd_s3c2410_probe (const struct hc_driver *driver, | 344 | static int usb_hcd_s3c2410_probe (const struct hc_driver *driver, |
338 | struct platform_device *dev) | 345 | struct platform_device *dev) |
339 | { | 346 | { |
340 | struct usb_hcd *hcd = NULL; | 347 | struct usb_hcd *hcd = NULL; |
341 | int retval; | 348 | int retval; |
@@ -353,14 +360,21 @@ int usb_hcd_s3c2410_probe (const struct hc_driver *driver, | |||
353 | if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) { | 360 | if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) { |
354 | dev_err(&dev->dev, "request_mem_region failed"); | 361 | dev_err(&dev->dev, "request_mem_region failed"); |
355 | retval = -EBUSY; | 362 | retval = -EBUSY; |
356 | goto err0; | 363 | goto err_put; |
357 | } | 364 | } |
358 | 365 | ||
359 | clk = clk_get(NULL, "usb-host"); | 366 | clk = clk_get(&dev->dev, "usb-host"); |
360 | if (IS_ERR(clk)) { | 367 | if (IS_ERR(clk)) { |
361 | dev_err(&dev->dev, "cannot get usb-host clock\n"); | 368 | dev_err(&dev->dev, "cannot get usb-host clock\n"); |
362 | retval = -ENOENT; | 369 | retval = -ENOENT; |
363 | goto err1; | 370 | goto err_mem; |
371 | } | ||
372 | |||
373 | usb_clk = clk_get(&dev->dev, "upll"); | ||
374 | if (IS_ERR(usb_clk)) { | ||
375 | dev_err(&dev->dev, "cannot get usb-host clock\n"); | ||
376 | retval = -ENOENT; | ||
377 | goto err_clk; | ||
364 | } | 378 | } |
365 | 379 | ||
366 | s3c2410_start_hc(dev, hcd); | 380 | s3c2410_start_hc(dev, hcd); |
@@ -369,26 +383,29 @@ int usb_hcd_s3c2410_probe (const struct hc_driver *driver, | |||
369 | if (!hcd->regs) { | 383 | if (!hcd->regs) { |
370 | dev_err(&dev->dev, "ioremap failed\n"); | 384 | dev_err(&dev->dev, "ioremap failed\n"); |
371 | retval = -ENOMEM; | 385 | retval = -ENOMEM; |
372 | goto err2; | 386 | goto err_ioremap; |
373 | } | 387 | } |
374 | 388 | ||
375 | ohci_hcd_init(hcd_to_ohci(hcd)); | 389 | ohci_hcd_init(hcd_to_ohci(hcd)); |
376 | 390 | ||
377 | retval = usb_add_hcd(hcd, dev->resource[1].start, SA_INTERRUPT); | 391 | retval = usb_add_hcd(hcd, dev->resource[1].start, SA_INTERRUPT); |
378 | if (retval != 0) | 392 | if (retval != 0) |
379 | goto err2; | 393 | goto err_ioremap; |
380 | 394 | ||
381 | return 0; | 395 | return 0; |
382 | 396 | ||
383 | err2: | 397 | err_ioremap: |
384 | s3c2410_stop_hc(dev); | 398 | s3c2410_stop_hc(dev); |
385 | iounmap(hcd->regs); | 399 | iounmap(hcd->regs); |
400 | clk_put(usb_clk); | ||
401 | |||
402 | err_clk: | ||
386 | clk_put(clk); | 403 | clk_put(clk); |
387 | 404 | ||
388 | err1: | 405 | err_mem: |
389 | release_mem_region(hcd->rsrc_start, hcd->rsrc_len); | 406 | release_mem_region(hcd->rsrc_start, hcd->rsrc_len); |
390 | 407 | ||
391 | err0: | 408 | err_put: |
392 | usb_put_hcd(hcd); | 409 | usb_put_hcd(hcd); |
393 | return retval; | 410 | return retval; |
394 | } | 411 | } |
diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c index 9e81c26313f9..1045f846fbe2 100644 --- a/drivers/usb/host/pci-quirks.c +++ b/drivers/usb/host/pci-quirks.c | |||
@@ -15,6 +15,7 @@ | |||
15 | #include <linux/init.h> | 15 | #include <linux/init.h> |
16 | #include <linux/delay.h> | 16 | #include <linux/delay.h> |
17 | #include <linux/acpi.h> | 17 | #include <linux/acpi.h> |
18 | #include "pci-quirks.h" | ||
18 | 19 | ||
19 | 20 | ||
20 | #define UHCI_USBLEGSUP 0xc0 /* legacy support */ | 21 | #define UHCI_USBLEGSUP 0xc0 /* legacy support */ |
diff --git a/drivers/usb/host/pci-quirks.h b/drivers/usb/host/pci-quirks.h new file mode 100644 index 000000000000..1564edfff6fe --- /dev/null +++ b/drivers/usb/host/pci-quirks.h | |||
@@ -0,0 +1,7 @@ | |||
1 | #ifndef __LINUX_USB_PCI_QUIRKS_H | ||
2 | #define __LINUX_USB_PCI_QUIRKS_H | ||
3 | |||
4 | void uhci_reset_hc(struct pci_dev *pdev, unsigned long base); | ||
5 | int uhci_check_and_reset_hc(struct pci_dev *pdev, unsigned long base); | ||
6 | |||
7 | #endif /* __LINUX_USB_PCI_QUIRKS_H */ | ||
diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c index 4edb8330c440..d225e11f4055 100644 --- a/drivers/usb/host/uhci-hcd.c +++ b/drivers/usb/host/uhci-hcd.c | |||
@@ -50,6 +50,7 @@ | |||
50 | 50 | ||
51 | #include "../core/hcd.h" | 51 | #include "../core/hcd.h" |
52 | #include "uhci-hcd.h" | 52 | #include "uhci-hcd.h" |
53 | #include "pci-quirks.h" | ||
53 | 54 | ||
54 | /* | 55 | /* |
55 | * Version Information | 56 | * Version Information |
@@ -100,9 +101,6 @@ static void uhci_get_current_frame_number(struct uhci_hcd *uhci); | |||
100 | #include "uhci-q.c" | 101 | #include "uhci-q.c" |
101 | #include "uhci-hub.c" | 102 | #include "uhci-hub.c" |
102 | 103 | ||
103 | extern void uhci_reset_hc(struct pci_dev *pdev, unsigned long base); | ||
104 | extern int uhci_check_and_reset_hc(struct pci_dev *pdev, unsigned long base); | ||
105 | |||
106 | /* | 104 | /* |
107 | * Finish up a host controller reset and update the recorded state. | 105 | * Finish up a host controller reset and update the recorded state. |
108 | */ | 106 | */ |
@@ -117,8 +115,7 @@ static void finish_reset(struct uhci_hcd *uhci) | |||
117 | for (port = 0; port < uhci->rh_numports; ++port) | 115 | for (port = 0; port < uhci->rh_numports; ++port) |
118 | outw(0, uhci->io_addr + USBPORTSC1 + (port * 2)); | 116 | outw(0, uhci->io_addr + USBPORTSC1 + (port * 2)); |
119 | 117 | ||
120 | uhci->port_c_suspend = uhci->suspended_ports = | 118 | uhci->port_c_suspend = uhci->resuming_ports = 0; |
121 | uhci->resuming_ports = 0; | ||
122 | uhci->rh_state = UHCI_RH_RESET; | 119 | uhci->rh_state = UHCI_RH_RESET; |
123 | uhci->is_stopped = UHCI_IS_STOPPED; | 120 | uhci->is_stopped = UHCI_IS_STOPPED; |
124 | uhci_to_hcd(uhci)->state = HC_STATE_HALT; | 121 | uhci_to_hcd(uhci)->state = HC_STATE_HALT; |
@@ -861,7 +858,7 @@ static const struct hc_driver uhci_driver = { | |||
861 | 858 | ||
862 | static const struct pci_device_id uhci_pci_ids[] = { { | 859 | static const struct pci_device_id uhci_pci_ids[] = { { |
863 | /* handle any USB UHCI controller */ | 860 | /* handle any USB UHCI controller */ |
864 | PCI_DEVICE_CLASS(((PCI_CLASS_SERIAL_USB << 8) | 0x00), ~0), | 861 | PCI_DEVICE_CLASS(PCI_CLASS_SERIAL_USB_UHCI, ~0), |
865 | .driver_data = (unsigned long) &uhci_driver, | 862 | .driver_data = (unsigned long) &uhci_driver, |
866 | }, { /* end: all zeroes */ } | 863 | }, { /* end: all zeroes */ } |
867 | }; | 864 | }; |
diff --git a/drivers/usb/host/uhci-hcd.h b/drivers/usb/host/uhci-hcd.h index 4a69c7eb09bd..d5c8f4d92823 100644 --- a/drivers/usb/host/uhci-hcd.h +++ b/drivers/usb/host/uhci-hcd.h | |||
@@ -415,7 +415,6 @@ struct uhci_hcd { | |||
415 | 415 | ||
416 | /* Support for port suspend/resume/reset */ | 416 | /* Support for port suspend/resume/reset */ |
417 | unsigned long port_c_suspend; /* Bit-arrays of ports */ | 417 | unsigned long port_c_suspend; /* Bit-arrays of ports */ |
418 | unsigned long suspended_ports; | ||
419 | unsigned long resuming_ports; | 418 | unsigned long resuming_ports; |
420 | unsigned long ports_timeout; /* Time to stop signalling */ | 419 | unsigned long ports_timeout; /* Time to stop signalling */ |
421 | 420 | ||
diff --git a/drivers/usb/host/uhci-hub.c b/drivers/usb/host/uhci-hub.c index 152971d16769..c8451d9578f1 100644 --- a/drivers/usb/host/uhci-hub.c +++ b/drivers/usb/host/uhci-hub.c | |||
@@ -85,11 +85,10 @@ static void uhci_finish_suspend(struct uhci_hcd *uhci, int port, | |||
85 | { | 85 | { |
86 | int status; | 86 | int status; |
87 | 87 | ||
88 | if (test_bit(port, &uhci->suspended_ports)) { | 88 | if (inw(port_addr) & (USBPORTSC_SUSP | USBPORTSC_RD)) { |
89 | CLR_RH_PORTSTAT(USBPORTSC_SUSP | USBPORTSC_RD); | 89 | CLR_RH_PORTSTAT(USBPORTSC_SUSP | USBPORTSC_RD); |
90 | clear_bit(port, &uhci->suspended_ports); | 90 | if (test_bit(port, &uhci->resuming_ports)) |
91 | clear_bit(port, &uhci->resuming_ports); | 91 | set_bit(port, &uhci->port_c_suspend); |
92 | set_bit(port, &uhci->port_c_suspend); | ||
93 | 92 | ||
94 | /* The controller won't actually turn off the RD bit until | 93 | /* The controller won't actually turn off the RD bit until |
95 | * it has had a chance to send a low-speed EOP sequence, | 94 | * it has had a chance to send a low-speed EOP sequence, |
@@ -97,6 +96,7 @@ static void uhci_finish_suspend(struct uhci_hcd *uhci, int port, | |||
97 | * slightly longer for good luck. */ | 96 | * slightly longer for good luck. */ |
98 | udelay(4); | 97 | udelay(4); |
99 | } | 98 | } |
99 | clear_bit(port, &uhci->resuming_ports); | ||
100 | } | 100 | } |
101 | 101 | ||
102 | /* Wait for the UHCI controller in HP's iLO2 server management chip. | 102 | /* Wait for the UHCI controller in HP's iLO2 server management chip. |
@@ -265,8 +265,6 @@ static int uhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, | |||
265 | wPortChange |= USB_PORT_STAT_C_SUSPEND; | 265 | wPortChange |= USB_PORT_STAT_C_SUSPEND; |
266 | lstatus |= 1; | 266 | lstatus |= 1; |
267 | } | 267 | } |
268 | if (test_bit(port, &uhci->suspended_ports)) | ||
269 | lstatus |= 2; | ||
270 | if (test_bit(port, &uhci->resuming_ports)) | 268 | if (test_bit(port, &uhci->resuming_ports)) |
271 | lstatus |= 4; | 269 | lstatus |= 4; |
272 | 270 | ||
@@ -309,7 +307,6 @@ static int uhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, | |||
309 | 307 | ||
310 | switch (wValue) { | 308 | switch (wValue) { |
311 | case USB_PORT_FEAT_SUSPEND: | 309 | case USB_PORT_FEAT_SUSPEND: |
312 | set_bit(port, &uhci->suspended_ports); | ||
313 | SET_RH_PORTSTAT(USBPORTSC_SUSP); | 310 | SET_RH_PORTSTAT(USBPORTSC_SUSP); |
314 | OK(0); | 311 | OK(0); |
315 | case USB_PORT_FEAT_RESET: | 312 | case USB_PORT_FEAT_RESET: |
@@ -343,8 +340,11 @@ static int uhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, | |||
343 | CLR_RH_PORTSTAT(USBPORTSC_PEC); | 340 | CLR_RH_PORTSTAT(USBPORTSC_PEC); |
344 | OK(0); | 341 | OK(0); |
345 | case USB_PORT_FEAT_SUSPEND: | 342 | case USB_PORT_FEAT_SUSPEND: |
346 | if (test_bit(port, &uhci->suspended_ports) && | 343 | if (!(inw(port_addr) & USBPORTSC_SUSP)) { |
347 | !test_and_set_bit(port, | 344 | |
345 | /* Make certain the port isn't suspended */ | ||
346 | uhci_finish_suspend(uhci, port, port_addr); | ||
347 | } else if (!test_and_set_bit(port, | ||
348 | &uhci->resuming_ports)) { | 348 | &uhci->resuming_ports)) { |
349 | SET_RH_PORTSTAT(USBPORTSC_RD); | 349 | SET_RH_PORTSTAT(USBPORTSC_RD); |
350 | 350 | ||