diff options
Diffstat (limited to 'drivers/usb')
-rw-r--r-- | drivers/usb/Kconfig | 2 | ||||
-rw-r--r-- | drivers/usb/atm/ueagle-atm.c | 38 | ||||
-rw-r--r-- | drivers/usb/gadget/Kconfig | 4 | ||||
-rw-r--r-- | drivers/usb/host/ehci-hcd.c | 19 | ||||
-rw-r--r-- | drivers/usb/host/ehci-hub.c | 78 | ||||
-rw-r--r-- | drivers/usb/host/ehci-msm.c | 20 | ||||
-rw-r--r-- | drivers/usb/host/ehci-q.c | 82 | ||||
-rw-r--r-- | drivers/usb/host/ehci-sched.c | 17 | ||||
-rw-r--r-- | drivers/usb/host/ehci-sysfs.c | 190 | ||||
-rw-r--r-- | drivers/usb/host/ehci.h | 5 | ||||
-rw-r--r-- | drivers/usb/host/ohci-sh.c | 2 | ||||
-rw-r--r-- | drivers/usb/host/pci-quirks.c | 28 | ||||
-rw-r--r-- | drivers/usb/host/r8a66597-hcd.c | 6 | ||||
-rw-r--r-- | drivers/usb/host/r8a66597.h | 38 | ||||
-rw-r--r-- | drivers/usb/mon/mon_text.c | 9 | ||||
-rw-r--r-- | drivers/usb/renesas_usbhs/Kconfig | 15 | ||||
-rw-r--r-- | drivers/usb/renesas_usbhs/common.c | 23 | ||||
-rw-r--r-- | drivers/usb/renesas_usbhs/fifo.c | 41 | ||||
-rw-r--r-- | drivers/usb/renesas_usbhs/mod_gadget.c | 65 | ||||
-rw-r--r-- | drivers/usb/serial/pl2303.c | 26 |
20 files changed, 473 insertions, 235 deletions
diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig index 8cd999a217b6..48f1781352f1 100644 --- a/drivers/usb/Kconfig +++ b/drivers/usb/Kconfig | |||
@@ -118,6 +118,8 @@ source "drivers/usb/host/Kconfig" | |||
118 | 118 | ||
119 | source "drivers/usb/musb/Kconfig" | 119 | source "drivers/usb/musb/Kconfig" |
120 | 120 | ||
121 | source "drivers/usb/renesas_usbhs/Kconfig" | ||
122 | |||
121 | source "drivers/usb/class/Kconfig" | 123 | source "drivers/usb/class/Kconfig" |
122 | 124 | ||
123 | source "drivers/usb/storage/Kconfig" | 125 | source "drivers/usb/storage/Kconfig" |
diff --git a/drivers/usb/atm/ueagle-atm.c b/drivers/usb/atm/ueagle-atm.c index e71521ce3010..428f36801e06 100644 --- a/drivers/usb/atm/ueagle-atm.c +++ b/drivers/usb/atm/ueagle-atm.c | |||
@@ -116,14 +116,14 @@ struct uea_cmvs_v1 { | |||
116 | u32 address; | 116 | u32 address; |
117 | u16 offset; | 117 | u16 offset; |
118 | u32 data; | 118 | u32 data; |
119 | } __attribute__ ((packed)); | 119 | } __packed; |
120 | 120 | ||
121 | struct uea_cmvs_v2 { | 121 | struct uea_cmvs_v2 { |
122 | u32 group; | 122 | u32 group; |
123 | u32 address; | 123 | u32 address; |
124 | u32 offset; | 124 | u32 offset; |
125 | u32 data; | 125 | u32 data; |
126 | } __attribute__ ((packed)); | 126 | } __packed; |
127 | 127 | ||
128 | /* information about currently processed cmv */ | 128 | /* information about currently processed cmv */ |
129 | struct cmv_dsc_e1 { | 129 | struct cmv_dsc_e1 { |
@@ -352,7 +352,7 @@ struct block_index { | |||
352 | __le32 PageAddress; | 352 | __le32 PageAddress; |
353 | __le16 dummy1; | 353 | __le16 dummy1; |
354 | __le16 PageNumber; | 354 | __le16 PageNumber; |
355 | } __attribute__ ((packed)); | 355 | } __packed; |
356 | 356 | ||
357 | #define E4_IS_BOOT_PAGE(PageSize) ((le32_to_cpu(PageSize)) & 0x80000000) | 357 | #define E4_IS_BOOT_PAGE(PageSize) ((le32_to_cpu(PageSize)) & 0x80000000) |
358 | #define E4_PAGE_BYTES(PageSize) ((le32_to_cpu(PageSize) & 0x7fffffff) * 4) | 358 | #define E4_PAGE_BYTES(PageSize) ((le32_to_cpu(PageSize) & 0x7fffffff) * 4) |
@@ -367,7 +367,7 @@ struct l1_code { | |||
367 | u8 page_number_to_block_index[E4_MAX_PAGE_NUMBER]; | 367 | u8 page_number_to_block_index[E4_MAX_PAGE_NUMBER]; |
368 | struct block_index page_header[E4_NO_SWAPPAGE_HEADERS]; | 368 | struct block_index page_header[E4_NO_SWAPPAGE_HEADERS]; |
369 | u8 code[0]; | 369 | u8 code[0]; |
370 | } __attribute__ ((packed)); | 370 | } __packed; |
371 | 371 | ||
372 | /* structures describing a block within a DSP page */ | 372 | /* structures describing a block within a DSP page */ |
373 | struct block_info_e1 { | 373 | struct block_info_e1 { |
@@ -377,7 +377,7 @@ struct block_info_e1 { | |||
377 | __le16 wOvlOffset; | 377 | __le16 wOvlOffset; |
378 | __le16 wOvl; /* overlay */ | 378 | __le16 wOvl; /* overlay */ |
379 | __le16 wLast; | 379 | __le16 wLast; |
380 | } __attribute__ ((packed)); | 380 | } __packed; |
381 | #define E1_BLOCK_INFO_SIZE 12 | 381 | #define E1_BLOCK_INFO_SIZE 12 |
382 | 382 | ||
383 | struct block_info_e4 { | 383 | struct block_info_e4 { |
@@ -387,7 +387,7 @@ struct block_info_e4 { | |||
387 | __be32 dwSize; | 387 | __be32 dwSize; |
388 | __be32 dwAddress; | 388 | __be32 dwAddress; |
389 | __be16 wReserved; | 389 | __be16 wReserved; |
390 | } __attribute__ ((packed)); | 390 | } __packed; |
391 | #define E4_BLOCK_INFO_SIZE 14 | 391 | #define E4_BLOCK_INFO_SIZE 14 |
392 | 392 | ||
393 | #define UEA_BIHDR 0xabcd | 393 | #define UEA_BIHDR 0xabcd |
@@ -467,7 +467,7 @@ struct cmv_e1 { | |||
467 | __le32 dwSymbolicAddress; | 467 | __le32 dwSymbolicAddress; |
468 | __le16 wOffsetAddress; | 468 | __le16 wOffsetAddress; |
469 | __le32 dwData; | 469 | __le32 dwData; |
470 | } __attribute__ ((packed)); | 470 | } __packed; |
471 | 471 | ||
472 | struct cmv_e4 { | 472 | struct cmv_e4 { |
473 | __be16 wGroup; | 473 | __be16 wGroup; |
@@ -475,17 +475,17 @@ struct cmv_e4 { | |||
475 | __be16 wOffset; | 475 | __be16 wOffset; |
476 | __be16 wAddress; | 476 | __be16 wAddress; |
477 | __be32 dwData[6]; | 477 | __be32 dwData[6]; |
478 | } __attribute__ ((packed)); | 478 | } __packed; |
479 | 479 | ||
480 | /* structures representing swap information */ | 480 | /* structures representing swap information */ |
481 | struct swap_info_e1 { | 481 | struct swap_info_e1 { |
482 | __u8 bSwapPageNo; | 482 | __u8 bSwapPageNo; |
483 | __u8 bOvl; /* overlay */ | 483 | __u8 bOvl; /* overlay */ |
484 | } __attribute__ ((packed)); | 484 | } __packed; |
485 | 485 | ||
486 | struct swap_info_e4 { | 486 | struct swap_info_e4 { |
487 | __u8 bSwapPageNo; | 487 | __u8 bSwapPageNo; |
488 | } __attribute__ ((packed)); | 488 | } __packed; |
489 | 489 | ||
490 | /* structures representing interrupt data */ | 490 | /* structures representing interrupt data */ |
491 | #define e1_bSwapPageNo u.e1.s1.swapinfo.bSwapPageNo | 491 | #define e1_bSwapPageNo u.e1.s1.swapinfo.bSwapPageNo |
@@ -499,23 +499,23 @@ union intr_data_e1 { | |||
499 | struct { | 499 | struct { |
500 | struct swap_info_e1 swapinfo; | 500 | struct swap_info_e1 swapinfo; |
501 | __le16 wDataSize; | 501 | __le16 wDataSize; |
502 | } __attribute__ ((packed)) s1; | 502 | } __packed s1; |
503 | struct { | 503 | struct { |
504 | struct cmv_e1 cmv; | 504 | struct cmv_e1 cmv; |
505 | __le16 wDataSize; | 505 | __le16 wDataSize; |
506 | } __attribute__ ((packed)) s2; | 506 | } __packed s2; |
507 | } __attribute__ ((packed)); | 507 | } __packed; |
508 | 508 | ||
509 | union intr_data_e4 { | 509 | union intr_data_e4 { |
510 | struct { | 510 | struct { |
511 | struct swap_info_e4 swapinfo; | 511 | struct swap_info_e4 swapinfo; |
512 | __le16 wDataSize; | 512 | __le16 wDataSize; |
513 | } __attribute__ ((packed)) s1; | 513 | } __packed s1; |
514 | struct { | 514 | struct { |
515 | struct cmv_e4 cmv; | 515 | struct cmv_e4 cmv; |
516 | __le16 wDataSize; | 516 | __le16 wDataSize; |
517 | } __attribute__ ((packed)) s2; | 517 | } __packed s2; |
518 | } __attribute__ ((packed)); | 518 | } __packed; |
519 | 519 | ||
520 | struct intr_pkt { | 520 | struct intr_pkt { |
521 | __u8 bType; | 521 | __u8 bType; |
@@ -528,15 +528,15 @@ struct intr_pkt { | |||
528 | union intr_data_e1 e1; | 528 | union intr_data_e1 e1; |
529 | union intr_data_e4 e4; | 529 | union intr_data_e4 e4; |
530 | } u; | 530 | } u; |
531 | } __attribute__ ((packed)); | 531 | } __packed; |
532 | 532 | ||
533 | #define E1_INTR_PKT_SIZE 28 | 533 | #define E1_INTR_PKT_SIZE 28 |
534 | #define E4_INTR_PKT_SIZE 64 | 534 | #define E4_INTR_PKT_SIZE 64 |
535 | 535 | ||
536 | static struct usb_driver uea_driver; | 536 | static struct usb_driver uea_driver; |
537 | static DEFINE_MUTEX(uea_mutex); | 537 | static DEFINE_MUTEX(uea_mutex); |
538 | static const char *chip_name[] = {"ADI930", "Eagle I", "Eagle II", "Eagle III", | 538 | static const char * const chip_name[] = { |
539 | "Eagle IV"}; | 539 | "ADI930", "Eagle I", "Eagle II", "Eagle III", "Eagle IV"}; |
540 | 540 | ||
541 | static int modem_index; | 541 | static int modem_index; |
542 | static unsigned int debug; | 542 | static unsigned int debug; |
diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig index b0594d907549..44b6b40aafb4 100644 --- a/drivers/usb/gadget/Kconfig +++ b/drivers/usb/gadget/Kconfig | |||
@@ -216,9 +216,11 @@ config USB_R8A66597 | |||
216 | dynamically linked module called "r8a66597_udc" and force all | 216 | dynamically linked module called "r8a66597_udc" and force all |
217 | gadget drivers to also be dynamically linked. | 217 | gadget drivers to also be dynamically linked. |
218 | 218 | ||
219 | config USB_RENESAS_USBHS | 219 | config USB_RENESAS_USBHS_UDC |
220 | tristate 'Renesas USBHS controller' | 220 | tristate 'Renesas USBHS controller' |
221 | depends on SUPERH || ARCH_SHMOBILE | 221 | depends on SUPERH || ARCH_SHMOBILE |
222 | depends on USB_RENESAS_USBHS | ||
223 | select USB_GADGET_DUALSPEED | ||
222 | help | 224 | help |
223 | Renesas USBHS is a discrete USB host and peripheral controller chip | 225 | Renesas USBHS is a discrete USB host and peripheral controller chip |
224 | that supports both full and high speed USB 2.0 data transfers. | 226 | that supports both full and high speed USB 2.0 data transfers. |
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index e18862c5b059..2902199fa8ff 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c | |||
@@ -90,7 +90,8 @@ static const char hcd_name [] = "ehci_hcd"; | |||
90 | #define EHCI_IAA_MSECS 10 /* arbitrary */ | 90 | #define EHCI_IAA_MSECS 10 /* arbitrary */ |
91 | #define EHCI_IO_JIFFIES (HZ/10) /* io watchdog > irq_thresh */ | 91 | #define EHCI_IO_JIFFIES (HZ/10) /* io watchdog > irq_thresh */ |
92 | #define EHCI_ASYNC_JIFFIES (HZ/20) /* async idle timeout */ | 92 | #define EHCI_ASYNC_JIFFIES (HZ/20) /* async idle timeout */ |
93 | #define EHCI_SHRINK_FRAMES 5 /* async qh unlink delay */ | 93 | #define EHCI_SHRINK_JIFFIES (DIV_ROUND_UP(HZ, 200) + 1) |
94 | /* 200-ms async qh unlink delay */ | ||
94 | 95 | ||
95 | /* Initial IRQ latency: faster than hw default */ | 96 | /* Initial IRQ latency: faster than hw default */ |
96 | static int log2_irq_thresh = 0; // 0 to 6 | 97 | static int log2_irq_thresh = 0; // 0 to 6 |
@@ -148,10 +149,7 @@ timer_action(struct ehci_hcd *ehci, enum ehci_timer_action action) | |||
148 | break; | 149 | break; |
149 | /* case TIMER_ASYNC_SHRINK: */ | 150 | /* case TIMER_ASYNC_SHRINK: */ |
150 | default: | 151 | default: |
151 | /* add a jiffie since we synch against the | 152 | t = EHCI_SHRINK_JIFFIES; |
152 | * 8 KHz uframe counter. | ||
153 | */ | ||
154 | t = DIV_ROUND_UP(EHCI_SHRINK_FRAMES * HZ, 1000) + 1; | ||
155 | break; | 153 | break; |
156 | } | 154 | } |
157 | mod_timer(&ehci->watchdog, t + jiffies); | 155 | mod_timer(&ehci->watchdog, t + jiffies); |
@@ -336,6 +334,7 @@ static void ehci_work(struct ehci_hcd *ehci); | |||
336 | #include "ehci-mem.c" | 334 | #include "ehci-mem.c" |
337 | #include "ehci-q.c" | 335 | #include "ehci-q.c" |
338 | #include "ehci-sched.c" | 336 | #include "ehci-sched.c" |
337 | #include "ehci-sysfs.c" | ||
339 | 338 | ||
340 | /*-------------------------------------------------------------------------*/ | 339 | /*-------------------------------------------------------------------------*/ |
341 | 340 | ||
@@ -520,7 +519,7 @@ static void ehci_stop (struct usb_hcd *hcd) | |||
520 | ehci_reset (ehci); | 519 | ehci_reset (ehci); |
521 | spin_unlock_irq(&ehci->lock); | 520 | spin_unlock_irq(&ehci->lock); |
522 | 521 | ||
523 | remove_companion_file(ehci); | 522 | remove_sysfs_files(ehci); |
524 | remove_debug_files (ehci); | 523 | remove_debug_files (ehci); |
525 | 524 | ||
526 | /* root hub is shut down separately (first, when possible) */ | 525 | /* root hub is shut down separately (first, when possible) */ |
@@ -571,6 +570,12 @@ static int ehci_init(struct usb_hcd *hcd) | |||
571 | hcc_params = ehci_readl(ehci, &ehci->caps->hcc_params); | 570 | hcc_params = ehci_readl(ehci, &ehci->caps->hcc_params); |
572 | 571 | ||
573 | /* | 572 | /* |
573 | * by default set standard 80% (== 100 usec/uframe) max periodic | ||
574 | * bandwidth as required by USB 2.0 | ||
575 | */ | ||
576 | ehci->uframe_periodic_max = 100; | ||
577 | |||
578 | /* | ||
574 | * hw default: 1K periodic list heads, one per frame. | 579 | * hw default: 1K periodic list heads, one per frame. |
575 | * periodic_size can shrink by USBCMD update if hcc_params allows. | 580 | * periodic_size can shrink by USBCMD update if hcc_params allows. |
576 | */ | 581 | */ |
@@ -754,7 +759,7 @@ static int ehci_run (struct usb_hcd *hcd) | |||
754 | * since the class device isn't created that early. | 759 | * since the class device isn't created that early. |
755 | */ | 760 | */ |
756 | create_debug_files(ehci); | 761 | create_debug_files(ehci); |
757 | create_companion_file(ehci); | 762 | create_sysfs_files(ehci); |
758 | 763 | ||
759 | return 0; | 764 | return 0; |
760 | } | 765 | } |
diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c index ea6184bf48d0..bf2c8f65e1ae 100644 --- a/drivers/usb/host/ehci-hub.c +++ b/drivers/usb/host/ehci-hub.c | |||
@@ -471,29 +471,6 @@ static int ehci_bus_resume (struct usb_hcd *hcd) | |||
471 | 471 | ||
472 | /*-------------------------------------------------------------------------*/ | 472 | /*-------------------------------------------------------------------------*/ |
473 | 473 | ||
474 | /* Display the ports dedicated to the companion controller */ | ||
475 | static ssize_t show_companion(struct device *dev, | ||
476 | struct device_attribute *attr, | ||
477 | char *buf) | ||
478 | { | ||
479 | struct ehci_hcd *ehci; | ||
480 | int nports, index, n; | ||
481 | int count = PAGE_SIZE; | ||
482 | char *ptr = buf; | ||
483 | |||
484 | ehci = hcd_to_ehci(bus_to_hcd(dev_get_drvdata(dev))); | ||
485 | nports = HCS_N_PORTS(ehci->hcs_params); | ||
486 | |||
487 | for (index = 0; index < nports; ++index) { | ||
488 | if (test_bit(index, &ehci->companion_ports)) { | ||
489 | n = scnprintf(ptr, count, "%d\n", index + 1); | ||
490 | ptr += n; | ||
491 | count -= n; | ||
492 | } | ||
493 | } | ||
494 | return ptr - buf; | ||
495 | } | ||
496 | |||
497 | /* | 474 | /* |
498 | * Sets the owner of a port | 475 | * Sets the owner of a port |
499 | */ | 476 | */ |
@@ -528,58 +505,6 @@ static void set_owner(struct ehci_hcd *ehci, int portnum, int new_owner) | |||
528 | } | 505 | } |
529 | } | 506 | } |
530 | 507 | ||
531 | /* | ||
532 | * Dedicate or undedicate a port to the companion controller. | ||
533 | * Syntax is "[-]portnum", where a leading '-' sign means | ||
534 | * return control of the port to the EHCI controller. | ||
535 | */ | ||
536 | static ssize_t store_companion(struct device *dev, | ||
537 | struct device_attribute *attr, | ||
538 | const char *buf, size_t count) | ||
539 | { | ||
540 | struct ehci_hcd *ehci; | ||
541 | int portnum, new_owner; | ||
542 | |||
543 | ehci = hcd_to_ehci(bus_to_hcd(dev_get_drvdata(dev))); | ||
544 | new_owner = PORT_OWNER; /* Owned by companion */ | ||
545 | if (sscanf(buf, "%d", &portnum) != 1) | ||
546 | return -EINVAL; | ||
547 | if (portnum < 0) { | ||
548 | portnum = - portnum; | ||
549 | new_owner = 0; /* Owned by EHCI */ | ||
550 | } | ||
551 | if (portnum <= 0 || portnum > HCS_N_PORTS(ehci->hcs_params)) | ||
552 | return -ENOENT; | ||
553 | portnum--; | ||
554 | if (new_owner) | ||
555 | set_bit(portnum, &ehci->companion_ports); | ||
556 | else | ||
557 | clear_bit(portnum, &ehci->companion_ports); | ||
558 | set_owner(ehci, portnum, new_owner); | ||
559 | return count; | ||
560 | } | ||
561 | static DEVICE_ATTR(companion, 0644, show_companion, store_companion); | ||
562 | |||
563 | static inline int create_companion_file(struct ehci_hcd *ehci) | ||
564 | { | ||
565 | int i = 0; | ||
566 | |||
567 | /* with integrated TT there is no companion! */ | ||
568 | if (!ehci_is_TDI(ehci)) | ||
569 | i = device_create_file(ehci_to_hcd(ehci)->self.controller, | ||
570 | &dev_attr_companion); | ||
571 | return i; | ||
572 | } | ||
573 | |||
574 | static inline void remove_companion_file(struct ehci_hcd *ehci) | ||
575 | { | ||
576 | /* with integrated TT there is no companion! */ | ||
577 | if (!ehci_is_TDI(ehci)) | ||
578 | device_remove_file(ehci_to_hcd(ehci)->self.controller, | ||
579 | &dev_attr_companion); | ||
580 | } | ||
581 | |||
582 | |||
583 | /*-------------------------------------------------------------------------*/ | 508 | /*-------------------------------------------------------------------------*/ |
584 | 509 | ||
585 | static int check_reset_complete ( | 510 | static int check_reset_complete ( |
@@ -891,10 +816,11 @@ static int ehci_hub_control ( | |||
891 | * power switching; they're allowed to just limit the | 816 | * power switching; they're allowed to just limit the |
892 | * current. khubd will turn the power back on. | 817 | * current. khubd will turn the power back on. |
893 | */ | 818 | */ |
894 | if (HCS_PPC (ehci->hcs_params)){ | 819 | if ((temp & PORT_OC) && HCS_PPC(ehci->hcs_params)) { |
895 | ehci_writel(ehci, | 820 | ehci_writel(ehci, |
896 | temp & ~(PORT_RWC_BITS | PORT_POWER), | 821 | temp & ~(PORT_RWC_BITS | PORT_POWER), |
897 | status_reg); | 822 | status_reg); |
823 | temp = ehci_readl(ehci, status_reg); | ||
898 | } | 824 | } |
899 | } | 825 | } |
900 | 826 | ||
diff --git a/drivers/usb/host/ehci-msm.c b/drivers/usb/host/ehci-msm.c index b5a0bf649c95..592d5f76803e 100644 --- a/drivers/usb/host/ehci-msm.c +++ b/drivers/usb/host/ehci-msm.c | |||
@@ -40,27 +40,9 @@ static int ehci_msm_reset(struct usb_hcd *hcd) | |||
40 | int retval; | 40 | int retval; |
41 | 41 | ||
42 | ehci->caps = USB_CAPLENGTH; | 42 | ehci->caps = USB_CAPLENGTH; |
43 | ehci->regs = USB_CAPLENGTH + | ||
44 | HC_LENGTH(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase)); | ||
45 | dbg_hcs_params(ehci, "reset"); | ||
46 | dbg_hcc_params(ehci, "reset"); | ||
47 | |||
48 | /* cache the data to minimize the chip reads*/ | ||
49 | ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params); | ||
50 | |||
51 | hcd->has_tt = 1; | 43 | hcd->has_tt = 1; |
52 | ehci->sbrn = HCD_USB2; | ||
53 | |||
54 | retval = ehci_halt(ehci); | ||
55 | if (retval) | ||
56 | return retval; | ||
57 | |||
58 | /* data structure init */ | ||
59 | retval = ehci_init(hcd); | ||
60 | if (retval) | ||
61 | return retval; | ||
62 | 44 | ||
63 | retval = ehci_reset(ehci); | 45 | retval = ehci_setup(hcd); |
64 | if (retval) | 46 | if (retval) |
65 | return retval; | 47 | return retval; |
66 | 48 | ||
diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c index 5d6bc624c961..9bf3c0d983c4 100644 --- a/drivers/usb/host/ehci-q.c +++ b/drivers/usb/host/ehci-q.c | |||
@@ -1231,6 +1231,8 @@ static void start_unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh) | |||
1231 | 1231 | ||
1232 | prev->hw->hw_next = qh->hw->hw_next; | 1232 | prev->hw->hw_next = qh->hw->hw_next; |
1233 | prev->qh_next = qh->qh_next; | 1233 | prev->qh_next = qh->qh_next; |
1234 | if (ehci->qh_scan_next == qh) | ||
1235 | ehci->qh_scan_next = qh->qh_next.qh; | ||
1234 | wmb (); | 1236 | wmb (); |
1235 | 1237 | ||
1236 | /* If the controller isn't running, we don't have to wait for it */ | 1238 | /* If the controller isn't running, we don't have to wait for it */ |
@@ -1256,53 +1258,49 @@ static void scan_async (struct ehci_hcd *ehci) | |||
1256 | struct ehci_qh *qh; | 1258 | struct ehci_qh *qh; |
1257 | enum ehci_timer_action action = TIMER_IO_WATCHDOG; | 1259 | enum ehci_timer_action action = TIMER_IO_WATCHDOG; |
1258 | 1260 | ||
1259 | ehci->stamp = ehci_readl(ehci, &ehci->regs->frame_index); | ||
1260 | timer_action_done (ehci, TIMER_ASYNC_SHRINK); | 1261 | timer_action_done (ehci, TIMER_ASYNC_SHRINK); |
1261 | rescan: | ||
1262 | stopped = !HC_IS_RUNNING(ehci_to_hcd(ehci)->state); | 1262 | stopped = !HC_IS_RUNNING(ehci_to_hcd(ehci)->state); |
1263 | qh = ehci->async->qh_next.qh; | ||
1264 | if (likely (qh != NULL)) { | ||
1265 | do { | ||
1266 | /* clean any finished work for this qh */ | ||
1267 | if (!list_empty(&qh->qtd_list) && (stopped || | ||
1268 | qh->stamp != ehci->stamp)) { | ||
1269 | int temp; | ||
1270 | |||
1271 | /* unlinks could happen here; completion | ||
1272 | * reporting drops the lock. rescan using | ||
1273 | * the latest schedule, but don't rescan | ||
1274 | * qhs we already finished (no looping) | ||
1275 | * unless the controller is stopped. | ||
1276 | */ | ||
1277 | qh = qh_get (qh); | ||
1278 | qh->stamp = ehci->stamp; | ||
1279 | temp = qh_completions (ehci, qh); | ||
1280 | if (qh->needs_rescan) | ||
1281 | unlink_async(ehci, qh); | ||
1282 | qh_put (qh); | ||
1283 | if (temp != 0) { | ||
1284 | goto rescan; | ||
1285 | } | ||
1286 | } | ||
1287 | 1263 | ||
1288 | /* unlink idle entries, reducing DMA usage as well | 1264 | ehci->qh_scan_next = ehci->async->qh_next.qh; |
1289 | * as HCD schedule-scanning costs. delay for any qh | 1265 | while (ehci->qh_scan_next) { |
1290 | * we just scanned, there's a not-unusual case that it | 1266 | qh = ehci->qh_scan_next; |
1291 | * doesn't stay idle for long. | 1267 | ehci->qh_scan_next = qh->qh_next.qh; |
1292 | * (plus, avoids some kind of re-activation race.) | 1268 | rescan: |
1269 | /* clean any finished work for this qh */ | ||
1270 | if (!list_empty(&qh->qtd_list)) { | ||
1271 | int temp; | ||
1272 | |||
1273 | /* | ||
1274 | * Unlinks could happen here; completion reporting | ||
1275 | * drops the lock. That's why ehci->qh_scan_next | ||
1276 | * always holds the next qh to scan; if the next qh | ||
1277 | * gets unlinked then ehci->qh_scan_next is adjusted | ||
1278 | * in start_unlink_async(). | ||
1293 | */ | 1279 | */ |
1294 | if (list_empty(&qh->qtd_list) | 1280 | qh = qh_get(qh); |
1295 | && qh->qh_state == QH_STATE_LINKED) { | 1281 | temp = qh_completions(ehci, qh); |
1296 | if (!ehci->reclaim && (stopped || | 1282 | if (qh->needs_rescan) |
1297 | ((ehci->stamp - qh->stamp) & 0x1fff) | 1283 | unlink_async(ehci, qh); |
1298 | >= EHCI_SHRINK_FRAMES * 8)) | 1284 | qh->unlink_time = jiffies + EHCI_SHRINK_JIFFIES; |
1299 | start_unlink_async(ehci, qh); | 1285 | qh_put(qh); |
1300 | else | 1286 | if (temp != 0) |
1301 | action = TIMER_ASYNC_SHRINK; | 1287 | goto rescan; |
1302 | } | 1288 | } |
1303 | 1289 | ||
1304 | qh = qh->qh_next.qh; | 1290 | /* unlink idle entries, reducing DMA usage as well |
1305 | } while (qh); | 1291 | * as HCD schedule-scanning costs. delay for any qh |
1292 | * we just scanned, there's a not-unusual case that it | ||
1293 | * doesn't stay idle for long. | ||
1294 | * (plus, avoids some kind of re-activation race.) | ||
1295 | */ | ||
1296 | if (list_empty(&qh->qtd_list) | ||
1297 | && qh->qh_state == QH_STATE_LINKED) { | ||
1298 | if (!ehci->reclaim && (stopped || | ||
1299 | time_after_eq(jiffies, qh->unlink_time))) | ||
1300 | start_unlink_async(ehci, qh); | ||
1301 | else | ||
1302 | action = TIMER_ASYNC_SHRINK; | ||
1303 | } | ||
1306 | } | 1304 | } |
1307 | if (action == TIMER_ASYNC_SHRINK) | 1305 | if (action == TIMER_ASYNC_SHRINK) |
1308 | timer_action (ehci, TIMER_ASYNC_SHRINK); | 1306 | timer_action (ehci, TIMER_ASYNC_SHRINK); |
diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c index 6c9fbe352f73..2abf8543f083 100644 --- a/drivers/usb/host/ehci-sched.c +++ b/drivers/usb/host/ehci-sched.c | |||
@@ -172,7 +172,7 @@ periodic_usecs (struct ehci_hcd *ehci, unsigned frame, unsigned uframe) | |||
172 | } | 172 | } |
173 | } | 173 | } |
174 | #ifdef DEBUG | 174 | #ifdef DEBUG |
175 | if (usecs > 100) | 175 | if (usecs > ehci->uframe_periodic_max) |
176 | ehci_err (ehci, "uframe %d sched overrun: %d usecs\n", | 176 | ehci_err (ehci, "uframe %d sched overrun: %d usecs\n", |
177 | frame * 8 + uframe, usecs); | 177 | frame * 8 + uframe, usecs); |
178 | #endif | 178 | #endif |
@@ -709,11 +709,8 @@ static int check_period ( | |||
709 | if (uframe >= 8) | 709 | if (uframe >= 8) |
710 | return 0; | 710 | return 0; |
711 | 711 | ||
712 | /* | 712 | /* convert "usecs we need" to "max already claimed" */ |
713 | * 80% periodic == 100 usec/uframe available | 713 | usecs = ehci->uframe_periodic_max - usecs; |
714 | * convert "usecs we need" to "max already claimed" | ||
715 | */ | ||
716 | usecs = 100 - usecs; | ||
717 | 714 | ||
718 | /* we "know" 2 and 4 uframe intervals were rejected; so | 715 | /* we "know" 2 and 4 uframe intervals were rejected; so |
719 | * for period 0, check _every_ microframe in the schedule. | 716 | * for period 0, check _every_ microframe in the schedule. |
@@ -1286,9 +1283,9 @@ itd_slot_ok ( | |||
1286 | { | 1283 | { |
1287 | uframe %= period; | 1284 | uframe %= period; |
1288 | do { | 1285 | do { |
1289 | /* can't commit more than 80% periodic == 100 usec */ | 1286 | /* can't commit more than uframe_periodic_max usec */ |
1290 | if (periodic_usecs (ehci, uframe >> 3, uframe & 0x7) | 1287 | if (periodic_usecs (ehci, uframe >> 3, uframe & 0x7) |
1291 | > (100 - usecs)) | 1288 | > (ehci->uframe_periodic_max - usecs)) |
1292 | return 0; | 1289 | return 0; |
1293 | 1290 | ||
1294 | /* we know urb->interval is 2^N uframes */ | 1291 | /* we know urb->interval is 2^N uframes */ |
@@ -1345,7 +1342,7 @@ sitd_slot_ok ( | |||
1345 | #endif | 1342 | #endif |
1346 | 1343 | ||
1347 | /* check starts (OUT uses more than one) */ | 1344 | /* check starts (OUT uses more than one) */ |
1348 | max_used = 100 - stream->usecs; | 1345 | max_used = ehci->uframe_periodic_max - stream->usecs; |
1349 | for (tmp = stream->raw_mask & 0xff; tmp; tmp >>= 1, uf++) { | 1346 | for (tmp = stream->raw_mask & 0xff; tmp; tmp >>= 1, uf++) { |
1350 | if (periodic_usecs (ehci, frame, uf) > max_used) | 1347 | if (periodic_usecs (ehci, frame, uf) > max_used) |
1351 | return 0; | 1348 | return 0; |
@@ -1354,7 +1351,7 @@ sitd_slot_ok ( | |||
1354 | /* for IN, check CSPLIT */ | 1351 | /* for IN, check CSPLIT */ |
1355 | if (stream->c_usecs) { | 1352 | if (stream->c_usecs) { |
1356 | uf = uframe & 7; | 1353 | uf = uframe & 7; |
1357 | max_used = 100 - stream->c_usecs; | 1354 | max_used = ehci->uframe_periodic_max - stream->c_usecs; |
1358 | do { | 1355 | do { |
1359 | tmp = 1 << uf; | 1356 | tmp = 1 << uf; |
1360 | tmp <<= 8; | 1357 | tmp <<= 8; |
diff --git a/drivers/usb/host/ehci-sysfs.c b/drivers/usb/host/ehci-sysfs.c new file mode 100644 index 000000000000..14ced00ba220 --- /dev/null +++ b/drivers/usb/host/ehci-sysfs.c | |||
@@ -0,0 +1,190 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2007 by Alan Stern | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify it | ||
5 | * under the terms of the GNU General Public License as published by the | ||
6 | * Free Software Foundation; either version 2 of the License, or (at your | ||
7 | * option) any later version. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, but | ||
10 | * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY | ||
11 | * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | ||
12 | * for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, write to the Free Software Foundation, | ||
16 | * Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
17 | */ | ||
18 | |||
19 | /* this file is part of ehci-hcd.c */ | ||
20 | |||
21 | |||
22 | /* Display the ports dedicated to the companion controller */ | ||
23 | static ssize_t show_companion(struct device *dev, | ||
24 | struct device_attribute *attr, | ||
25 | char *buf) | ||
26 | { | ||
27 | struct ehci_hcd *ehci; | ||
28 | int nports, index, n; | ||
29 | int count = PAGE_SIZE; | ||
30 | char *ptr = buf; | ||
31 | |||
32 | ehci = hcd_to_ehci(bus_to_hcd(dev_get_drvdata(dev))); | ||
33 | nports = HCS_N_PORTS(ehci->hcs_params); | ||
34 | |||
35 | for (index = 0; index < nports; ++index) { | ||
36 | if (test_bit(index, &ehci->companion_ports)) { | ||
37 | n = scnprintf(ptr, count, "%d\n", index + 1); | ||
38 | ptr += n; | ||
39 | count -= n; | ||
40 | } | ||
41 | } | ||
42 | return ptr - buf; | ||
43 | } | ||
44 | |||
45 | /* | ||
46 | * Dedicate or undedicate a port to the companion controller. | ||
47 | * Syntax is "[-]portnum", where a leading '-' sign means | ||
48 | * return control of the port to the EHCI controller. | ||
49 | */ | ||
50 | static ssize_t store_companion(struct device *dev, | ||
51 | struct device_attribute *attr, | ||
52 | const char *buf, size_t count) | ||
53 | { | ||
54 | struct ehci_hcd *ehci; | ||
55 | int portnum, new_owner; | ||
56 | |||
57 | ehci = hcd_to_ehci(bus_to_hcd(dev_get_drvdata(dev))); | ||
58 | new_owner = PORT_OWNER; /* Owned by companion */ | ||
59 | if (sscanf(buf, "%d", &portnum) != 1) | ||
60 | return -EINVAL; | ||
61 | if (portnum < 0) { | ||
62 | portnum = - portnum; | ||
63 | new_owner = 0; /* Owned by EHCI */ | ||
64 | } | ||
65 | if (portnum <= 0 || portnum > HCS_N_PORTS(ehci->hcs_params)) | ||
66 | return -ENOENT; | ||
67 | portnum--; | ||
68 | if (new_owner) | ||
69 | set_bit(portnum, &ehci->companion_ports); | ||
70 | else | ||
71 | clear_bit(portnum, &ehci->companion_ports); | ||
72 | set_owner(ehci, portnum, new_owner); | ||
73 | return count; | ||
74 | } | ||
75 | static DEVICE_ATTR(companion, 0644, show_companion, store_companion); | ||
76 | |||
77 | |||
78 | /* | ||
79 | * Display / Set uframe_periodic_max | ||
80 | */ | ||
81 | static ssize_t show_uframe_periodic_max(struct device *dev, | ||
82 | struct device_attribute *attr, | ||
83 | char *buf) | ||
84 | { | ||
85 | struct ehci_hcd *ehci; | ||
86 | int n; | ||
87 | |||
88 | ehci = hcd_to_ehci(bus_to_hcd(dev_get_drvdata(dev))); | ||
89 | n = scnprintf(buf, PAGE_SIZE, "%d\n", ehci->uframe_periodic_max); | ||
90 | return n; | ||
91 | } | ||
92 | |||
93 | |||
94 | static ssize_t store_uframe_periodic_max(struct device *dev, | ||
95 | struct device_attribute *attr, | ||
96 | const char *buf, size_t count) | ||
97 | { | ||
98 | struct ehci_hcd *ehci; | ||
99 | unsigned uframe_periodic_max; | ||
100 | unsigned frame, uframe; | ||
101 | unsigned short allocated_max; | ||
102 | unsigned long flags; | ||
103 | ssize_t ret; | ||
104 | |||
105 | ehci = hcd_to_ehci(bus_to_hcd(dev_get_drvdata(dev))); | ||
106 | if (kstrtouint(buf, 0, &uframe_periodic_max) < 0) | ||
107 | return -EINVAL; | ||
108 | |||
109 | if (uframe_periodic_max < 100 || uframe_periodic_max >= 125) { | ||
110 | ehci_info(ehci, "rejecting invalid request for " | ||
111 | "uframe_periodic_max=%u\n", uframe_periodic_max); | ||
112 | return -EINVAL; | ||
113 | } | ||
114 | |||
115 | ret = -EINVAL; | ||
116 | |||
117 | /* | ||
118 | * lock, so that our checking does not race with possible periodic | ||
119 | * bandwidth allocation through submitting new urbs. | ||
120 | */ | ||
121 | spin_lock_irqsave (&ehci->lock, flags); | ||
122 | |||
123 | /* | ||
124 | * for request to decrease max periodic bandwidth, we have to check | ||
125 | * every microframe in the schedule to see whether the decrease is | ||
126 | * possible. | ||
127 | */ | ||
128 | if (uframe_periodic_max < ehci->uframe_periodic_max) { | ||
129 | allocated_max = 0; | ||
130 | |||
131 | for (frame = 0; frame < ehci->periodic_size; ++frame) | ||
132 | for (uframe = 0; uframe < 7; ++uframe) | ||
133 | allocated_max = max(allocated_max, | ||
134 | periodic_usecs (ehci, frame, uframe)); | ||
135 | |||
136 | if (allocated_max > uframe_periodic_max) { | ||
137 | ehci_info(ehci, | ||
138 | "cannot decrease uframe_periodic_max becase " | ||
139 | "periodic bandwidth is already allocated " | ||
140 | "(%u > %u)\n", | ||
141 | allocated_max, uframe_periodic_max); | ||
142 | goto out_unlock; | ||
143 | } | ||
144 | } | ||
145 | |||
146 | /* increasing is always ok */ | ||
147 | |||
148 | ehci_info(ehci, "setting max periodic bandwidth to %u%% " | ||
149 | "(== %u usec/uframe)\n", | ||
150 | 100*uframe_periodic_max/125, uframe_periodic_max); | ||
151 | |||
152 | if (uframe_periodic_max != 100) | ||
153 | ehci_warn(ehci, "max periodic bandwidth set is non-standard\n"); | ||
154 | |||
155 | ehci->uframe_periodic_max = uframe_periodic_max; | ||
156 | ret = count; | ||
157 | |||
158 | out_unlock: | ||
159 | spin_unlock_irqrestore (&ehci->lock, flags); | ||
160 | return ret; | ||
161 | } | ||
162 | static DEVICE_ATTR(uframe_periodic_max, 0644, show_uframe_periodic_max, store_uframe_periodic_max); | ||
163 | |||
164 | |||
165 | static inline int create_sysfs_files(struct ehci_hcd *ehci) | ||
166 | { | ||
167 | struct device *controller = ehci_to_hcd(ehci)->self.controller; | ||
168 | int i = 0; | ||
169 | |||
170 | /* with integrated TT there is no companion! */ | ||
171 | if (!ehci_is_TDI(ehci)) | ||
172 | i = device_create_file(controller, &dev_attr_companion); | ||
173 | if (i) | ||
174 | goto out; | ||
175 | |||
176 | i = device_create_file(controller, &dev_attr_uframe_periodic_max); | ||
177 | out: | ||
178 | return i; | ||
179 | } | ||
180 | |||
181 | static inline void remove_sysfs_files(struct ehci_hcd *ehci) | ||
182 | { | ||
183 | struct device *controller = ehci_to_hcd(ehci)->self.controller; | ||
184 | |||
185 | /* with integrated TT there is no companion! */ | ||
186 | if (!ehci_is_TDI(ehci)) | ||
187 | device_remove_file(controller, &dev_attr_companion); | ||
188 | |||
189 | device_remove_file(controller, &dev_attr_uframe_periodic_max); | ||
190 | } | ||
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h index bd6ff489baf9..e4feec3457fb 100644 --- a/drivers/usb/host/ehci.h +++ b/drivers/usb/host/ehci.h | |||
@@ -75,6 +75,7 @@ struct ehci_hcd { /* one per controller */ | |||
75 | struct ehci_qh *async; | 75 | struct ehci_qh *async; |
76 | struct ehci_qh *dummy; /* For AMD quirk use */ | 76 | struct ehci_qh *dummy; /* For AMD quirk use */ |
77 | struct ehci_qh *reclaim; | 77 | struct ehci_qh *reclaim; |
78 | struct ehci_qh *qh_scan_next; | ||
78 | unsigned scanning : 1; | 79 | unsigned scanning : 1; |
79 | 80 | ||
80 | /* periodic schedule support */ | 81 | /* periodic schedule support */ |
@@ -87,6 +88,8 @@ struct ehci_hcd { /* one per controller */ | |||
87 | union ehci_shadow *pshadow; /* mirror hw periodic table */ | 88 | union ehci_shadow *pshadow; /* mirror hw periodic table */ |
88 | int next_uframe; /* scan periodic, start here */ | 89 | int next_uframe; /* scan periodic, start here */ |
89 | unsigned periodic_sched; /* periodic activity count */ | 90 | unsigned periodic_sched; /* periodic activity count */ |
91 | unsigned uframe_periodic_max; /* max periodic time per uframe */ | ||
92 | |||
90 | 93 | ||
91 | /* list of itds & sitds completed while clock_frame was still active */ | 94 | /* list of itds & sitds completed while clock_frame was still active */ |
92 | struct list_head cached_itd_list; | 95 | struct list_head cached_itd_list; |
@@ -117,7 +120,6 @@ struct ehci_hcd { /* one per controller */ | |||
117 | struct timer_list iaa_watchdog; | 120 | struct timer_list iaa_watchdog; |
118 | struct timer_list watchdog; | 121 | struct timer_list watchdog; |
119 | unsigned long actions; | 122 | unsigned long actions; |
120 | unsigned stamp; | ||
121 | unsigned periodic_stamp; | 123 | unsigned periodic_stamp; |
122 | unsigned random_frame; | 124 | unsigned random_frame; |
123 | unsigned long next_statechange; | 125 | unsigned long next_statechange; |
@@ -343,6 +345,7 @@ struct ehci_qh { | |||
343 | struct ehci_qh *reclaim; /* next to reclaim */ | 345 | struct ehci_qh *reclaim; /* next to reclaim */ |
344 | 346 | ||
345 | struct ehci_hcd *ehci; | 347 | struct ehci_hcd *ehci; |
348 | unsigned long unlink_time; | ||
346 | 349 | ||
347 | /* | 350 | /* |
348 | * Do NOT use atomic operations for QH refcounting. On some CPUs | 351 | * Do NOT use atomic operations for QH refcounting. On some CPUs |
diff --git a/drivers/usb/host/ohci-sh.c b/drivers/usb/host/ohci-sh.c index f47867ff78c7..14cecb52a9fe 100644 --- a/drivers/usb/host/ohci-sh.c +++ b/drivers/usb/host/ohci-sh.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * Copyright (C) 2008 Renesas Solutions Corp. | 4 | * Copyright (C) 2008 Renesas Solutions Corp. |
5 | * | 5 | * |
6 | * Author : Yoshihiro Shimoda <shimoda.yoshihiro@renesas.com> | 6 | * Author : Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com> |
7 | * | 7 | * |
8 | * This program is free software; you can redistribute it and/or modify | 8 | * This program is free software; you can redistribute it and/or modify |
9 | * it under the terms of the GNU General Public License as published by | 9 | * it under the terms of the GNU General Public License as published by |
diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c index fd930618c28f..b5a7304fcbef 100644 --- a/drivers/usb/host/pci-quirks.c +++ b/drivers/usb/host/pci-quirks.c | |||
@@ -507,20 +507,34 @@ static void __devinit quirk_usb_handoff_ohci(struct pci_dev *pdev) | |||
507 | iounmap(base); | 507 | iounmap(base); |
508 | } | 508 | } |
509 | 509 | ||
510 | static const struct dmi_system_id __initconst ehci_dmi_nohandoff_table[] = { | ||
511 | { | ||
512 | /* Pegatron Lucid (ExoPC) */ | ||
513 | .matches = { | ||
514 | DMI_MATCH(DMI_BOARD_NAME, "EXOPG06411"), | ||
515 | DMI_MATCH(DMI_BIOS_VERSION, "Lucid-CE-133"), | ||
516 | }, | ||
517 | }, | ||
518 | { | ||
519 | /* Pegatron Lucid (Ordissimo AIRIS) */ | ||
520 | .matches = { | ||
521 | DMI_MATCH(DMI_BOARD_NAME, "M11JB"), | ||
522 | DMI_MATCH(DMI_BIOS_VERSION, "Lucid-GE-133"), | ||
523 | }, | ||
524 | }, | ||
525 | { } | ||
526 | }; | ||
527 | |||
510 | static void __devinit ehci_bios_handoff(struct pci_dev *pdev, | 528 | static void __devinit ehci_bios_handoff(struct pci_dev *pdev, |
511 | void __iomem *op_reg_base, | 529 | void __iomem *op_reg_base, |
512 | u32 cap, u8 offset) | 530 | u32 cap, u8 offset) |
513 | { | 531 | { |
514 | int try_handoff = 1, tried_handoff = 0; | 532 | int try_handoff = 1, tried_handoff = 0; |
515 | 533 | ||
516 | /* The Pegatron Lucid (ExoPC) tablet sporadically waits for 90 | 534 | /* The Pegatron Lucid tablet sporadically waits for 98 seconds trying |
517 | * seconds trying the handoff on its unused controller. Skip | 535 | * the handoff on its unused controller. Skip it. */ |
518 | * it. */ | ||
519 | if (pdev->vendor == 0x8086 && pdev->device == 0x283a) { | 536 | if (pdev->vendor == 0x8086 && pdev->device == 0x283a) { |
520 | const char *dmi_bn = dmi_get_system_info(DMI_BOARD_NAME); | 537 | if (dmi_check_system(ehci_dmi_nohandoff_table)) |
521 | const char *dmi_bv = dmi_get_system_info(DMI_BIOS_VERSION); | ||
522 | if (dmi_bn && !strcmp(dmi_bn, "EXOPG06411") && | ||
523 | dmi_bv && !strcmp(dmi_bv, "Lucid-CE-133")) | ||
524 | try_handoff = 0; | 538 | try_handoff = 0; |
525 | } | 539 | } |
526 | 540 | ||
diff --git a/drivers/usb/host/r8a66597-hcd.c b/drivers/usb/host/r8a66597-hcd.c index db6f8b9c19b6..fd35901861c3 100644 --- a/drivers/usb/host/r8a66597-hcd.c +++ b/drivers/usb/host/r8a66597-hcd.c | |||
@@ -6,7 +6,7 @@ | |||
6 | * Portions Copyright (C) 2004-2005 David Brownell | 6 | * Portions Copyright (C) 2004-2005 David Brownell |
7 | * Portions Copyright (C) 1999 Roman Weissgaerber | 7 | * Portions Copyright (C) 1999 Roman Weissgaerber |
8 | * | 8 | * |
9 | * Author : Yoshihiro Shimoda <shimoda.yoshihiro@renesas.com> | 9 | * Author : Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com> |
10 | * | 10 | * |
11 | * This program is free software; you can redistribute it and/or modify | 11 | * This program is free software; you can redistribute it and/or modify |
12 | * it under the terms of the GNU General Public License as published by | 12 | * it under the terms of the GNU General Public License as published by |
@@ -1438,7 +1438,7 @@ static void packet_write(struct r8a66597 *r8a66597, u16 pipenum) | |||
1438 | if (pipenum > 0) | 1438 | if (pipenum > 0) |
1439 | r8a66597_write(r8a66597, ~(1 << pipenum), BEMPSTS); | 1439 | r8a66597_write(r8a66597, ~(1 << pipenum), BEMPSTS); |
1440 | if (urb->transfer_buffer) { | 1440 | if (urb->transfer_buffer) { |
1441 | r8a66597_write_fifo(r8a66597, td->pipe->fifoaddr, buf, size); | 1441 | r8a66597_write_fifo(r8a66597, td->pipe, buf, size); |
1442 | if (!usb_pipebulk(urb->pipe) || td->maxpacket != size) | 1442 | if (!usb_pipebulk(urb->pipe) || td->maxpacket != size) |
1443 | r8a66597_write(r8a66597, BVAL, td->pipe->fifoctr); | 1443 | r8a66597_write(r8a66597, BVAL, td->pipe->fifoctr); |
1444 | } | 1444 | } |
@@ -2306,7 +2306,7 @@ static int r8a66597_bus_resume(struct usb_hcd *hcd) | |||
2306 | 2306 | ||
2307 | dbg("resume port = %d", port); | 2307 | dbg("resume port = %d", port); |
2308 | rh->port &= ~USB_PORT_STAT_SUSPEND; | 2308 | rh->port &= ~USB_PORT_STAT_SUSPEND; |
2309 | rh->port |= USB_PORT_STAT_C_SUSPEND < 16; | 2309 | rh->port |= USB_PORT_STAT_C_SUSPEND << 16; |
2310 | r8a66597_mdfy(r8a66597, RESUME, RESUME | UACT, dvstctr_reg); | 2310 | r8a66597_mdfy(r8a66597, RESUME, RESUME | UACT, dvstctr_reg); |
2311 | msleep(50); | 2311 | msleep(50); |
2312 | r8a66597_mdfy(r8a66597, UACT, RESUME | UACT, dvstctr_reg); | 2312 | r8a66597_mdfy(r8a66597, UACT, RESUME | UACT, dvstctr_reg); |
diff --git a/drivers/usb/host/r8a66597.h b/drivers/usb/host/r8a66597.h index 25563e9a90bc..f28782d20eef 100644 --- a/drivers/usb/host/r8a66597.h +++ b/drivers/usb/host/r8a66597.h | |||
@@ -201,11 +201,26 @@ static inline void r8a66597_write(struct r8a66597 *r8a66597, u16 val, | |||
201 | iowrite16(val, r8a66597->reg + offset); | 201 | iowrite16(val, r8a66597->reg + offset); |
202 | } | 202 | } |
203 | 203 | ||
204 | static inline void r8a66597_mdfy(struct r8a66597 *r8a66597, | ||
205 | u16 val, u16 pat, unsigned long offset) | ||
206 | { | ||
207 | u16 tmp; | ||
208 | tmp = r8a66597_read(r8a66597, offset); | ||
209 | tmp = tmp & (~pat); | ||
210 | tmp = tmp | val; | ||
211 | r8a66597_write(r8a66597, tmp, offset); | ||
212 | } | ||
213 | |||
214 | #define r8a66597_bclr(r8a66597, val, offset) \ | ||
215 | r8a66597_mdfy(r8a66597, 0, val, offset) | ||
216 | #define r8a66597_bset(r8a66597, val, offset) \ | ||
217 | r8a66597_mdfy(r8a66597, val, 0, offset) | ||
218 | |||
204 | static inline void r8a66597_write_fifo(struct r8a66597 *r8a66597, | 219 | static inline void r8a66597_write_fifo(struct r8a66597 *r8a66597, |
205 | unsigned long offset, u16 *buf, | 220 | struct r8a66597_pipe *pipe, u16 *buf, |
206 | int len) | 221 | int len) |
207 | { | 222 | { |
208 | void __iomem *fifoaddr = r8a66597->reg + offset; | 223 | void __iomem *fifoaddr = r8a66597->reg + pipe->fifoaddr; |
209 | unsigned long count; | 224 | unsigned long count; |
210 | unsigned char *pb; | 225 | unsigned char *pb; |
211 | int i; | 226 | int i; |
@@ -230,26 +245,15 @@ static inline void r8a66597_write_fifo(struct r8a66597 *r8a66597, | |||
230 | iowrite16_rep(fifoaddr, buf, len); | 245 | iowrite16_rep(fifoaddr, buf, len); |
231 | if (unlikely(odd)) { | 246 | if (unlikely(odd)) { |
232 | buf = &buf[len]; | 247 | buf = &buf[len]; |
248 | if (r8a66597->pdata->wr0_shorted_to_wr1) | ||
249 | r8a66597_bclr(r8a66597, MBW_16, pipe->fifosel); | ||
233 | iowrite8((unsigned char)*buf, fifoaddr); | 250 | iowrite8((unsigned char)*buf, fifoaddr); |
251 | if (r8a66597->pdata->wr0_shorted_to_wr1) | ||
252 | r8a66597_bset(r8a66597, MBW_16, pipe->fifosel); | ||
234 | } | 253 | } |
235 | } | 254 | } |
236 | } | 255 | } |
237 | 256 | ||
238 | static inline void r8a66597_mdfy(struct r8a66597 *r8a66597, | ||
239 | u16 val, u16 pat, unsigned long offset) | ||
240 | { | ||
241 | u16 tmp; | ||
242 | tmp = r8a66597_read(r8a66597, offset); | ||
243 | tmp = tmp & (~pat); | ||
244 | tmp = tmp | val; | ||
245 | r8a66597_write(r8a66597, tmp, offset); | ||
246 | } | ||
247 | |||
248 | #define r8a66597_bclr(r8a66597, val, offset) \ | ||
249 | r8a66597_mdfy(r8a66597, 0, val, offset) | ||
250 | #define r8a66597_bset(r8a66597, val, offset) \ | ||
251 | r8a66597_mdfy(r8a66597, val, 0, offset) | ||
252 | |||
253 | static inline unsigned long get_syscfg_reg(int port) | 257 | static inline unsigned long get_syscfg_reg(int port) |
254 | { | 258 | { |
255 | return port == 0 ? SYSCFG0 : SYSCFG1; | 259 | return port == 0 ? SYSCFG0 : SYSCFG1; |
diff --git a/drivers/usb/mon/mon_text.c b/drivers/usb/mon/mon_text.c index c302e1983c70..1c3afcc11bd9 100644 --- a/drivers/usb/mon/mon_text.c +++ b/drivers/usb/mon/mon_text.c | |||
@@ -670,6 +670,9 @@ int mon_text_add(struct mon_bus *mbus, const struct usb_bus *ubus) | |||
670 | int busnum = ubus? ubus->busnum: 0; | 670 | int busnum = ubus? ubus->busnum: 0; |
671 | int rc; | 671 | int rc; |
672 | 672 | ||
673 | if (mon_dir == NULL) | ||
674 | return 0; | ||
675 | |||
673 | if (ubus != NULL) { | 676 | if (ubus != NULL) { |
674 | rc = snprintf(name, NAMESZ, "%dt", busnum); | 677 | rc = snprintf(name, NAMESZ, "%dt", busnum); |
675 | if (rc <= 0 || rc >= NAMESZ) | 678 | if (rc <= 0 || rc >= NAMESZ) |
@@ -740,12 +743,12 @@ int __init mon_text_init(void) | |||
740 | 743 | ||
741 | mondir = debugfs_create_dir("usbmon", usb_debug_root); | 744 | mondir = debugfs_create_dir("usbmon", usb_debug_root); |
742 | if (IS_ERR(mondir)) { | 745 | if (IS_ERR(mondir)) { |
743 | printk(KERN_NOTICE TAG ": debugfs is not available\n"); | 746 | /* debugfs not available, but we can use usbmon without it */ |
744 | return -ENODEV; | 747 | return 0; |
745 | } | 748 | } |
746 | if (mondir == NULL) { | 749 | if (mondir == NULL) { |
747 | printk(KERN_NOTICE TAG ": unable to create usbmon directory\n"); | 750 | printk(KERN_NOTICE TAG ": unable to create usbmon directory\n"); |
748 | return -ENODEV; | 751 | return -ENOMEM; |
749 | } | 752 | } |
750 | mon_dir = mondir; | 753 | mon_dir = mondir; |
751 | return 0; | 754 | return 0; |
diff --git a/drivers/usb/renesas_usbhs/Kconfig b/drivers/usb/renesas_usbhs/Kconfig new file mode 100644 index 000000000000..286cbf1ca7de --- /dev/null +++ b/drivers/usb/renesas_usbhs/Kconfig | |||
@@ -0,0 +1,15 @@ | |||
1 | # | ||
2 | # Renesas USBHS Controller Drivers | ||
3 | # | ||
4 | |||
5 | config USB_RENESAS_USBHS | ||
6 | tristate 'Renesas USBHS controller' | ||
7 | depends on SUPERH || ARCH_SHMOBILE | ||
8 | default n | ||
9 | help | ||
10 | Renesas USBHS is a discrete USB host and peripheral controller chip | ||
11 | that supports both full and high speed USB 2.0 data transfers. | ||
12 | It has nine or more configurable endpoints, and endpoint zero. | ||
13 | |||
14 | Say "y" to link the driver statically, or "m" to build a | ||
15 | dynamically linked module called "renesas_usbhs" | ||
diff --git a/drivers/usb/renesas_usbhs/common.c b/drivers/usb/renesas_usbhs/common.c index 665259aec871..d8239e5efa66 100644 --- a/drivers/usb/renesas_usbhs/common.c +++ b/drivers/usb/renesas_usbhs/common.c | |||
@@ -21,6 +21,29 @@ | |||
21 | #include <linux/sysfs.h> | 21 | #include <linux/sysfs.h> |
22 | #include "./common.h" | 22 | #include "./common.h" |
23 | 23 | ||
24 | /* | ||
25 | * image of renesas_usbhs | ||
26 | * | ||
27 | * ex) gadget case | ||
28 | |||
29 | * mod.c | ||
30 | * mod_gadget.c | ||
31 | * mod_host.c pipe.c fifo.c | ||
32 | * | ||
33 | * +-------+ +-----------+ | ||
34 | * | pipe0 |------>| fifo pio | | ||
35 | * +------------+ +-------+ +-----------+ | ||
36 | * | mod_gadget |=====> | pipe1 |--+ | ||
37 | * +------------+ +-------+ | +-----------+ | ||
38 | * | pipe2 | | +-| fifo dma0 | | ||
39 | * +------------+ +-------+ | | +-----------+ | ||
40 | * | mod_host | | pipe3 |<-|--+ | ||
41 | * +------------+ +-------+ | +-----------+ | ||
42 | * | .... | +--->| fifo dma1 | | ||
43 | * | .... | +-----------+ | ||
44 | */ | ||
45 | |||
46 | |||
24 | #define USBHSF_RUNTIME_PWCTRL (1 << 0) | 47 | #define USBHSF_RUNTIME_PWCTRL (1 << 0) |
25 | 48 | ||
26 | /* status */ | 49 | /* status */ |
diff --git a/drivers/usb/renesas_usbhs/fifo.c b/drivers/usb/renesas_usbhs/fifo.c index 021695de1e9e..406893e4422b 100644 --- a/drivers/usb/renesas_usbhs/fifo.c +++ b/drivers/usb/renesas_usbhs/fifo.c | |||
@@ -26,7 +26,16 @@ | |||
26 | #define usbhsf_fifo_is_busy(f) ((f)->pipe) /* see usbhs_pipe_select_fifo */ | 26 | #define usbhsf_fifo_is_busy(f) ((f)->pipe) /* see usbhs_pipe_select_fifo */ |
27 | 27 | ||
28 | /* | 28 | /* |
29 | * packet info function | 29 | * packet initialize |
30 | */ | ||
31 | void usbhs_pkt_init(struct usbhs_pkt *pkt) | ||
32 | { | ||
33 | pkt->dma = DMA_ADDR_INVALID; | ||
34 | INIT_LIST_HEAD(&pkt->node); | ||
35 | } | ||
36 | |||
37 | /* | ||
38 | * packet control function | ||
30 | */ | 39 | */ |
31 | static int usbhsf_null_handle(struct usbhs_pkt *pkt, int *is_done) | 40 | static int usbhsf_null_handle(struct usbhs_pkt *pkt, int *is_done) |
32 | { | 41 | { |
@@ -43,12 +52,6 @@ static struct usbhs_pkt_handle usbhsf_null_handler = { | |||
43 | .try_run = usbhsf_null_handle, | 52 | .try_run = usbhsf_null_handle, |
44 | }; | 53 | }; |
45 | 54 | ||
46 | void usbhs_pkt_init(struct usbhs_pkt *pkt) | ||
47 | { | ||
48 | pkt->dma = DMA_ADDR_INVALID; | ||
49 | INIT_LIST_HEAD(&pkt->node); | ||
50 | } | ||
51 | |||
52 | void usbhs_pkt_push(struct usbhs_pipe *pipe, struct usbhs_pkt *pkt, | 55 | void usbhs_pkt_push(struct usbhs_pipe *pipe, struct usbhs_pkt *pkt, |
53 | struct usbhs_pkt_handle *handler, | 56 | struct usbhs_pkt_handle *handler, |
54 | void *buf, int len, int zero) | 57 | void *buf, int len, int zero) |
@@ -293,7 +296,7 @@ static int usbhsf_fifo_select(struct usbhs_pipe *pipe, | |||
293 | } | 296 | } |
294 | 297 | ||
295 | /* | 298 | /* |
296 | * PIO fifo functions | 299 | * PIO push handler |
297 | */ | 300 | */ |
298 | static int usbhsf_pio_try_push(struct usbhs_pkt *pkt, int *is_done) | 301 | static int usbhsf_pio_try_push(struct usbhs_pkt *pkt, int *is_done) |
299 | { | 302 | { |
@@ -313,8 +316,11 @@ static int usbhsf_pio_try_push(struct usbhs_pkt *pkt, int *is_done) | |||
313 | return 0; | 316 | return 0; |
314 | 317 | ||
315 | ret = usbhs_pipe_is_accessible(pipe); | 318 | ret = usbhs_pipe_is_accessible(pipe); |
316 | if (ret < 0) | 319 | if (ret < 0) { |
320 | /* inaccessible pipe is not an error */ | ||
321 | ret = 0; | ||
317 | goto usbhs_fifo_write_busy; | 322 | goto usbhs_fifo_write_busy; |
323 | } | ||
318 | 324 | ||
319 | ret = usbhsf_fifo_barrier(priv, fifo); | 325 | ret = usbhsf_fifo_barrier(priv, fifo); |
320 | if (ret < 0) | 326 | if (ret < 0) |
@@ -395,6 +401,9 @@ struct usbhs_pkt_handle usbhs_fifo_pio_push_handler = { | |||
395 | .try_run = usbhsf_pio_try_push, | 401 | .try_run = usbhsf_pio_try_push, |
396 | }; | 402 | }; |
397 | 403 | ||
404 | /* | ||
405 | * PIO pop handler | ||
406 | */ | ||
398 | static int usbhsf_prepare_pop(struct usbhs_pkt *pkt, int *is_done) | 407 | static int usbhsf_prepare_pop(struct usbhs_pkt *pkt, int *is_done) |
399 | { | 408 | { |
400 | struct usbhs_pipe *pipe = pkt->pipe; | 409 | struct usbhs_pipe *pipe = pkt->pipe; |
@@ -497,7 +506,7 @@ struct usbhs_pkt_handle usbhs_fifo_pio_pop_handler = { | |||
497 | }; | 506 | }; |
498 | 507 | ||
499 | /* | 508 | /* |
500 | * handler function | 509 | * DCP ctrol statge handler |
501 | */ | 510 | */ |
502 | static int usbhsf_ctrl_stage_end(struct usbhs_pkt *pkt, int *is_done) | 511 | static int usbhsf_ctrl_stage_end(struct usbhs_pkt *pkt, int *is_done) |
503 | { | 512 | { |
@@ -614,6 +623,9 @@ static void usbhsf_dma_prepare_tasklet(unsigned long data) | |||
614 | dma_async_issue_pending(chan); | 623 | dma_async_issue_pending(chan); |
615 | } | 624 | } |
616 | 625 | ||
626 | /* | ||
627 | * DMA push handler | ||
628 | */ | ||
617 | static int usbhsf_dma_prepare_push(struct usbhs_pkt *pkt, int *is_done) | 629 | static int usbhsf_dma_prepare_push(struct usbhs_pkt *pkt, int *is_done) |
618 | { | 630 | { |
619 | struct usbhs_pipe *pipe = pkt->pipe; | 631 | struct usbhs_pipe *pipe = pkt->pipe; |
@@ -633,6 +645,9 @@ static int usbhsf_dma_prepare_push(struct usbhs_pkt *pkt, int *is_done) | |||
633 | if (len % 4) /* 32bit alignment */ | 645 | if (len % 4) /* 32bit alignment */ |
634 | goto usbhsf_pio_prepare_push; | 646 | goto usbhsf_pio_prepare_push; |
635 | 647 | ||
648 | if (((u32)pkt->buf + pkt->actual) & 0x7) /* 8byte alignment */ | ||
649 | goto usbhsf_pio_prepare_push; | ||
650 | |||
636 | /* get enable DMA fifo */ | 651 | /* get enable DMA fifo */ |
637 | fifo = usbhsf_get_dma_fifo(priv, pkt); | 652 | fifo = usbhsf_get_dma_fifo(priv, pkt); |
638 | if (!fifo) | 653 | if (!fifo) |
@@ -686,6 +701,9 @@ struct usbhs_pkt_handle usbhs_fifo_dma_push_handler = { | |||
686 | .dma_done = usbhsf_dma_push_done, | 701 | .dma_done = usbhsf_dma_push_done, |
687 | }; | 702 | }; |
688 | 703 | ||
704 | /* | ||
705 | * DMA pop handler | ||
706 | */ | ||
689 | static int usbhsf_dma_try_pop(struct usbhs_pkt *pkt, int *is_done) | 707 | static int usbhsf_dma_try_pop(struct usbhs_pkt *pkt, int *is_done) |
690 | { | 708 | { |
691 | struct usbhs_pipe *pipe = pkt->pipe; | 709 | struct usbhs_pipe *pipe = pkt->pipe; |
@@ -704,6 +722,9 @@ static int usbhsf_dma_try_pop(struct usbhs_pkt *pkt, int *is_done) | |||
704 | if (!fifo) | 722 | if (!fifo) |
705 | goto usbhsf_pio_prepare_pop; | 723 | goto usbhsf_pio_prepare_pop; |
706 | 724 | ||
725 | if (((u32)pkt->buf + pkt->actual) & 0x7) /* 8byte alignment */ | ||
726 | goto usbhsf_pio_prepare_pop; | ||
727 | |||
707 | ret = usbhsf_fifo_select(pipe, fifo, 0); | 728 | ret = usbhsf_fifo_select(pipe, fifo, 0); |
708 | if (ret < 0) | 729 | if (ret < 0) |
709 | goto usbhsf_pio_prepare_pop; | 730 | goto usbhsf_pio_prepare_pop; |
diff --git a/drivers/usb/renesas_usbhs/mod_gadget.c b/drivers/usb/renesas_usbhs/mod_gadget.c index 9a8e2e9141b2..ba79dbf5adbc 100644 --- a/drivers/usb/renesas_usbhs/mod_gadget.c +++ b/drivers/usb/renesas_usbhs/mod_gadget.c | |||
@@ -44,6 +44,7 @@ struct usbhsg_uep { | |||
44 | struct usbhsg_gpriv { | 44 | struct usbhsg_gpriv { |
45 | struct usb_gadget gadget; | 45 | struct usb_gadget gadget; |
46 | struct usbhs_mod mod; | 46 | struct usbhs_mod mod; |
47 | struct list_head link; | ||
47 | 48 | ||
48 | struct usbhsg_uep *uep; | 49 | struct usbhsg_uep *uep; |
49 | int uep_size; | 50 | int uep_size; |
@@ -113,8 +114,18 @@ struct usbhsg_recip_handle { | |||
113 | #define usbhsg_status_clr(gp, b) (gp->status &= ~b) | 114 | #define usbhsg_status_clr(gp, b) (gp->status &= ~b) |
114 | #define usbhsg_status_has(gp, b) (gp->status & b) | 115 | #define usbhsg_status_has(gp, b) (gp->status & b) |
115 | 116 | ||
117 | /* controller */ | ||
118 | LIST_HEAD(the_controller_link); | ||
119 | |||
120 | #define usbhsg_for_each_controller(gpriv)\ | ||
121 | list_for_each_entry(gpriv, &the_controller_link, link) | ||
122 | #define usbhsg_controller_register(gpriv)\ | ||
123 | list_add_tail(&(gpriv)->link, &the_controller_link) | ||
124 | #define usbhsg_controller_unregister(gpriv)\ | ||
125 | list_del_init(&(gpriv)->link) | ||
126 | |||
116 | /* | 127 | /* |
117 | * list push/pop | 128 | * queue push/pop |
118 | */ | 129 | */ |
119 | static void usbhsg_queue_push(struct usbhsg_uep *uep, | 130 | static void usbhsg_queue_push(struct usbhsg_uep *uep, |
120 | struct usbhsg_request *ureq) | 131 | struct usbhsg_request *ureq) |
@@ -160,6 +171,9 @@ static void usbhsg_queue_done(struct usbhs_pkt *pkt) | |||
160 | usbhsg_queue_pop(uep, ureq, 0); | 171 | usbhsg_queue_pop(uep, ureq, 0); |
161 | } | 172 | } |
162 | 173 | ||
174 | /* | ||
175 | * dma map/unmap | ||
176 | */ | ||
163 | static int usbhsg_dma_map(struct device *dev, | 177 | static int usbhsg_dma_map(struct device *dev, |
164 | struct usbhs_pkt *pkt, | 178 | struct usbhs_pkt *pkt, |
165 | enum dma_data_direction dir) | 179 | enum dma_data_direction dir) |
@@ -473,6 +487,11 @@ static int usbhsg_ep_enable(struct usb_ep *ep, | |||
473 | uep->pipe = pipe; | 487 | uep->pipe = pipe; |
474 | pipe->mod_private = uep; | 488 | pipe->mod_private = uep; |
475 | 489 | ||
490 | /* | ||
491 | * usbhs_fifo_dma_push/pop_handler try to | ||
492 | * use dmaengine if possible. | ||
493 | * It will use pio handler if impossible. | ||
494 | */ | ||
476 | if (usb_endpoint_dir_in(desc)) | 495 | if (usb_endpoint_dir_in(desc)) |
477 | uep->handler = &usbhs_fifo_dma_push_handler; | 496 | uep->handler = &usbhs_fifo_dma_push_handler; |
478 | else | 497 | else |
@@ -724,11 +743,10 @@ static int usbhsg_try_stop(struct usbhs_priv *priv, u32 status) | |||
724 | * linux usb function | 743 | * linux usb function |
725 | * | 744 | * |
726 | */ | 745 | */ |
727 | struct usbhsg_gpriv *the_controller; | ||
728 | static int usbhsg_gadget_start(struct usb_gadget_driver *driver, | 746 | static int usbhsg_gadget_start(struct usb_gadget_driver *driver, |
729 | int (*bind)(struct usb_gadget *)) | 747 | int (*bind)(struct usb_gadget *)) |
730 | { | 748 | { |
731 | struct usbhsg_gpriv *gpriv = the_controller; | 749 | struct usbhsg_gpriv *gpriv; |
732 | struct usbhs_priv *priv; | 750 | struct usbhs_priv *priv; |
733 | struct device *dev; | 751 | struct device *dev; |
734 | int ret; | 752 | int ret; |
@@ -738,10 +756,17 @@ static int usbhsg_gadget_start(struct usb_gadget_driver *driver, | |||
738 | !driver->setup || | 756 | !driver->setup || |
739 | driver->speed != USB_SPEED_HIGH) | 757 | driver->speed != USB_SPEED_HIGH) |
740 | return -EINVAL; | 758 | return -EINVAL; |
741 | if (!gpriv) | 759 | |
742 | return -ENODEV; | 760 | /* |
743 | if (gpriv->driver) | 761 | * find unused controller |
744 | return -EBUSY; | 762 | */ |
763 | usbhsg_for_each_controller(gpriv) { | ||
764 | if (!gpriv->driver) | ||
765 | goto find_unused_controller; | ||
766 | } | ||
767 | return -ENODEV; | ||
768 | |||
769 | find_unused_controller: | ||
745 | 770 | ||
746 | dev = usbhsg_gpriv_to_dev(gpriv); | 771 | dev = usbhsg_gpriv_to_dev(gpriv); |
747 | priv = usbhsg_gpriv_to_priv(gpriv); | 772 | priv = usbhsg_gpriv_to_priv(gpriv); |
@@ -778,18 +803,25 @@ add_fail: | |||
778 | 803 | ||
779 | static int usbhsg_gadget_stop(struct usb_gadget_driver *driver) | 804 | static int usbhsg_gadget_stop(struct usb_gadget_driver *driver) |
780 | { | 805 | { |
781 | struct usbhsg_gpriv *gpriv = the_controller; | 806 | struct usbhsg_gpriv *gpriv; |
782 | struct usbhs_priv *priv; | 807 | struct usbhs_priv *priv; |
783 | struct device *dev = usbhsg_gpriv_to_dev(gpriv); | 808 | struct device *dev; |
784 | |||
785 | if (!gpriv) | ||
786 | return -ENODEV; | ||
787 | 809 | ||
788 | if (!driver || | 810 | if (!driver || |
789 | !driver->unbind || | 811 | !driver->unbind) |
790 | driver != gpriv->driver) | ||
791 | return -EINVAL; | 812 | return -EINVAL; |
792 | 813 | ||
814 | /* | ||
815 | * find controller | ||
816 | */ | ||
817 | usbhsg_for_each_controller(gpriv) { | ||
818 | if (gpriv->driver == driver) | ||
819 | goto find_matching_controller; | ||
820 | } | ||
821 | return -ENODEV; | ||
822 | |||
823 | find_matching_controller: | ||
824 | |||
793 | dev = usbhsg_gpriv_to_dev(gpriv); | 825 | dev = usbhsg_gpriv_to_dev(gpriv); |
794 | priv = usbhsg_gpriv_to_priv(gpriv); | 826 | priv = usbhsg_gpriv_to_priv(gpriv); |
795 | 827 | ||
@@ -911,7 +943,7 @@ int __devinit usbhs_mod_gadget_probe(struct usbhs_priv *priv) | |||
911 | } | 943 | } |
912 | } | 944 | } |
913 | 945 | ||
914 | the_controller = gpriv; | 946 | usbhsg_controller_register(gpriv); |
915 | 947 | ||
916 | ret = usb_add_gadget_udc(dev, &gpriv->gadget); | 948 | ret = usb_add_gadget_udc(dev, &gpriv->gadget); |
917 | if (ret) | 949 | if (ret) |
@@ -935,6 +967,9 @@ void __devexit usbhs_mod_gadget_remove(struct usbhs_priv *priv) | |||
935 | struct usbhsg_gpriv *gpriv = usbhsg_priv_to_gpriv(priv); | 967 | struct usbhsg_gpriv *gpriv = usbhsg_priv_to_gpriv(priv); |
936 | 968 | ||
937 | usb_del_gadget_udc(&gpriv->gadget); | 969 | usb_del_gadget_udc(&gpriv->gadget); |
970 | |||
971 | usbhsg_controller_unregister(gpriv); | ||
972 | |||
938 | kfree(gpriv->uep); | 973 | kfree(gpriv->uep); |
939 | kfree(gpriv); | 974 | kfree(gpriv); |
940 | } | 975 | } |
diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c index 30461fcc2206..ee28115aa9b4 100644 --- a/drivers/usb/serial/pl2303.c +++ b/drivers/usb/serial/pl2303.c | |||
@@ -342,10 +342,28 @@ static void pl2303_set_termios(struct tty_struct *tty, | |||
342 | baud = 6000000; | 342 | baud = 6000000; |
343 | } | 343 | } |
344 | dbg("%s - baud set = %d", __func__, baud); | 344 | dbg("%s - baud set = %d", __func__, baud); |
345 | buf[0] = baud & 0xff; | 345 | if (baud <= 115200) { |
346 | buf[1] = (baud >> 8) & 0xff; | 346 | buf[0] = baud & 0xff; |
347 | buf[2] = (baud >> 16) & 0xff; | 347 | buf[1] = (baud >> 8) & 0xff; |
348 | buf[3] = (baud >> 24) & 0xff; | 348 | buf[2] = (baud >> 16) & 0xff; |
349 | buf[3] = (baud >> 24) & 0xff; | ||
350 | } else { | ||
351 | /* apparently the formula for higher speeds is: | ||
352 | * baudrate = 12M * 32 / (2^buf[1]) / buf[0] | ||
353 | */ | ||
354 | unsigned tmp = 12*1000*1000*32 / baud; | ||
355 | buf[3] = 0x80; | ||
356 | buf[2] = 0; | ||
357 | buf[1] = (tmp >= 256); | ||
358 | while (tmp >= 256) { | ||
359 | tmp >>= 2; | ||
360 | buf[1] <<= 1; | ||
361 | } | ||
362 | if (tmp > 256) { | ||
363 | tmp %= 256; | ||
364 | } | ||
365 | buf[0] = tmp; | ||
366 | } | ||
349 | } | 367 | } |
350 | 368 | ||
351 | /* For reference buf[4]=0 is 1 stop bits */ | 369 | /* For reference buf[4]=0 is 1 stop bits */ |