aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/host/ehci-hub.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/host/ehci-hub.c')
-rw-r--r--drivers/usb/host/ehci-hub.c98
1 files changed, 61 insertions, 37 deletions
diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
index 735db4aec831..40e8240b7851 100644
--- a/drivers/usb/host/ehci-hub.c
+++ b/drivers/usb/host/ehci-hub.c
@@ -123,6 +123,8 @@ static int ehci_bus_suspend (struct usb_hcd *hcd)
123 123
124 if (time_before (jiffies, ehci->next_statechange)) 124 if (time_before (jiffies, ehci->next_statechange))
125 msleep(5); 125 msleep(5);
126 del_timer_sync(&ehci->watchdog);
127 del_timer_sync(&ehci->iaa_watchdog);
126 128
127 port = HCS_N_PORTS (ehci->hcs_params); 129 port = HCS_N_PORTS (ehci->hcs_params);
128 spin_lock_irq (&ehci->lock); 130 spin_lock_irq (&ehci->lock);
@@ -134,7 +136,7 @@ static int ehci_bus_suspend (struct usb_hcd *hcd)
134 } 136 }
135 ehci->command = ehci_readl(ehci, &ehci->regs->command); 137 ehci->command = ehci_readl(ehci, &ehci->regs->command);
136 if (ehci->reclaim) 138 if (ehci->reclaim)
137 ehci->reclaim_ready = 1; 139 end_unlink_async(ehci);
138 ehci_work(ehci); 140 ehci_work(ehci);
139 141
140 /* Unlike other USB host controller types, EHCI doesn't have 142 /* Unlike other USB host controller types, EHCI doesn't have
@@ -170,8 +172,11 @@ static int ehci_bus_suspend (struct usb_hcd *hcd)
170 } 172 }
171 } 173 }
172 174
175 /* Apparently some devices need a >= 1-uframe delay here */
176 if (ehci->bus_suspended)
177 udelay(150);
178
173 /* turn off now-idle HC */ 179 /* turn off now-idle HC */
174 del_timer_sync (&ehci->watchdog);
175 ehci_halt (ehci); 180 ehci_halt (ehci);
176 hcd->state = HC_STATE_SUSPENDED; 181 hcd->state = HC_STATE_SUSPENDED;
177 182
@@ -291,14 +296,16 @@ static int ehci_bus_resume (struct usb_hcd *hcd)
291/*-------------------------------------------------------------------------*/ 296/*-------------------------------------------------------------------------*/
292 297
293/* Display the ports dedicated to the companion controller */ 298/* Display the ports dedicated to the companion controller */
294static ssize_t show_companion(struct class_device *class_dev, char *buf) 299static ssize_t show_companion(struct device *dev,
300 struct device_attribute *attr,
301 char *buf)
295{ 302{
296 struct ehci_hcd *ehci; 303 struct ehci_hcd *ehci;
297 int nports, index, n; 304 int nports, index, n;
298 int count = PAGE_SIZE; 305 int count = PAGE_SIZE;
299 char *ptr = buf; 306 char *ptr = buf;
300 307
301 ehci = hcd_to_ehci(bus_to_hcd(class_get_devdata(class_dev))); 308 ehci = hcd_to_ehci(bus_to_hcd(dev_get_drvdata(dev)));
302 nports = HCS_N_PORTS(ehci->hcs_params); 309 nports = HCS_N_PORTS(ehci->hcs_params);
303 310
304 for (index = 0; index < nports; ++index) { 311 for (index = 0; index < nports; ++index) {
@@ -312,40 +319,21 @@ static ssize_t show_companion(struct class_device *class_dev, char *buf)
312} 319}
313 320
314/* 321/*
315 * Dedicate or undedicate a port to the companion controller. 322 * Sets the owner of a port
316 * Syntax is "[-]portnum", where a leading '-' sign means
317 * return control of the port to the EHCI controller.
318 */ 323 */
319static ssize_t store_companion(struct class_device *class_dev, 324static void set_owner(struct ehci_hcd *ehci, int portnum, int new_owner)
320 const char *buf, size_t count)
321{ 325{
322 struct ehci_hcd *ehci;
323 int portnum, new_owner, try;
324 u32 __iomem *status_reg; 326 u32 __iomem *status_reg;
325 u32 port_status; 327 u32 port_status;
328 int try;
326 329
327 ehci = hcd_to_ehci(bus_to_hcd(class_get_devdata(class_dev))); 330 status_reg = &ehci->regs->port_status[portnum];
328 new_owner = PORT_OWNER; /* Owned by companion */
329 if (sscanf(buf, "%d", &portnum) != 1)
330 return -EINVAL;
331 if (portnum < 0) {
332 portnum = - portnum;
333 new_owner = 0; /* Owned by EHCI */
334 }
335 if (portnum <= 0 || portnum > HCS_N_PORTS(ehci->hcs_params))
336 return -ENOENT;
337 status_reg = &ehci->regs->port_status[--portnum];
338 if (new_owner)
339 set_bit(portnum, &ehci->companion_ports);
340 else
341 clear_bit(portnum, &ehci->companion_ports);
342 331
343 /* 332 /*
344 * The controller won't set the OWNER bit if the port is 333 * The controller won't set the OWNER bit if the port is
345 * enabled, so this loop will sometimes require at least two 334 * enabled, so this loop will sometimes require at least two
346 * iterations: one to disable the port and one to set OWNER. 335 * iterations: one to disable the port and one to set OWNER.
347 */ 336 */
348
349 for (try = 4; try > 0; --try) { 337 for (try = 4; try > 0; --try) {
350 spin_lock_irq(&ehci->lock); 338 spin_lock_irq(&ehci->lock);
351 port_status = ehci_readl(ehci, status_reg); 339 port_status = ehci_readl(ehci, status_reg);
@@ -362,9 +350,39 @@ static ssize_t store_companion(struct class_device *class_dev,
362 if (try > 1) 350 if (try > 1)
363 msleep(5); 351 msleep(5);
364 } 352 }
353}
354
355/*
356 * Dedicate or undedicate a port to the companion controller.
357 * Syntax is "[-]portnum", where a leading '-' sign means
358 * return control of the port to the EHCI controller.
359 */
360static ssize_t store_companion(struct device *dev,
361 struct device_attribute *attr,
362 const char *buf, size_t count)
363{
364 struct ehci_hcd *ehci;
365 int portnum, new_owner;
366
367 ehci = hcd_to_ehci(bus_to_hcd(dev_get_drvdata(dev)));
368 new_owner = PORT_OWNER; /* Owned by companion */
369 if (sscanf(buf, "%d", &portnum) != 1)
370 return -EINVAL;
371 if (portnum < 0) {
372 portnum = - portnum;
373 new_owner = 0; /* Owned by EHCI */
374 }
375 if (portnum <= 0 || portnum > HCS_N_PORTS(ehci->hcs_params))
376 return -ENOENT;
377 portnum--;
378 if (new_owner)
379 set_bit(portnum, &ehci->companion_ports);
380 else
381 clear_bit(portnum, &ehci->companion_ports);
382 set_owner(ehci, portnum, new_owner);
365 return count; 383 return count;
366} 384}
367static CLASS_DEVICE_ATTR(companion, 0644, show_companion, store_companion); 385static DEVICE_ATTR(companion, 0644, show_companion, store_companion);
368 386
369static inline void create_companion_file(struct ehci_hcd *ehci) 387static inline void create_companion_file(struct ehci_hcd *ehci)
370{ 388{
@@ -372,16 +390,16 @@ static inline void create_companion_file(struct ehci_hcd *ehci)
372 390
373 /* with integrated TT there is no companion! */ 391 /* with integrated TT there is no companion! */
374 if (!ehci_is_TDI(ehci)) 392 if (!ehci_is_TDI(ehci))
375 i = class_device_create_file(ehci_to_hcd(ehci)->self.class_dev, 393 i = device_create_file(ehci_to_hcd(ehci)->self.dev,
376 &class_device_attr_companion); 394 &dev_attr_companion);
377} 395}
378 396
379static inline void remove_companion_file(struct ehci_hcd *ehci) 397static inline void remove_companion_file(struct ehci_hcd *ehci)
380{ 398{
381 /* with integrated TT there is no companion! */ 399 /* with integrated TT there is no companion! */
382 if (!ehci_is_TDI(ehci)) 400 if (!ehci_is_TDI(ehci))
383 class_device_remove_file(ehci_to_hcd(ehci)->self.class_dev, 401 device_remove_file(ehci_to_hcd(ehci)->self.dev,
384 &class_device_attr_companion); 402 &dev_attr_companion);
385} 403}
386 404
387 405
@@ -393,10 +411,8 @@ static int check_reset_complete (
393 u32 __iomem *status_reg, 411 u32 __iomem *status_reg,
394 int port_status 412 int port_status
395) { 413) {
396 if (!(port_status & PORT_CONNECT)) { 414 if (!(port_status & PORT_CONNECT))
397 ehci->reset_done [index] = 0;
398 return port_status; 415 return port_status;
399 }
400 416
401 /* if reset finished and it's still not enabled -- handoff */ 417 /* if reset finished and it's still not enabled -- handoff */
402 if (!(port_status & PORT_PE)) { 418 if (!(port_status & PORT_PE)) {
@@ -475,8 +491,6 @@ ehci_hub_status_data (struct usb_hcd *hcd, char *buf)
475 * controller by the user. 491 * controller by the user.
476 */ 492 */
477 493
478 if (!(temp & PORT_CONNECT))
479 ehci->reset_done [i] = 0;
480 if ((temp & mask) != 0 494 if ((temp & mask) != 0
481 || ((temp & PORT_RESUME) != 0 495 || ((temp & PORT_RESUME) != 0
482 && time_after_eq(jiffies, 496 && time_after_eq(jiffies,
@@ -864,3 +878,13 @@ error:
864 spin_unlock_irqrestore (&ehci->lock, flags); 878 spin_unlock_irqrestore (&ehci->lock, flags);
865 return retval; 879 return retval;
866} 880}
881
882static void ehci_relinquish_port(struct usb_hcd *hcd, int portnum)
883{
884 struct ehci_hcd *ehci = hcd_to_ehci(hcd);
885
886 if (ehci_is_TDI(ehci))
887 return;
888 set_owner(ehci, --portnum, PORT_OWNER);
889}
890