diff options
Diffstat (limited to 'drivers/usb/host/r8a66597-hcd.c')
-rw-r--r-- | drivers/usb/host/r8a66597-hcd.c | 81 |
1 files changed, 58 insertions, 23 deletions
diff --git a/drivers/usb/host/r8a66597-hcd.c b/drivers/usb/host/r8a66597-hcd.c index e33d36256350..d478ffad59b4 100644 --- a/drivers/usb/host/r8a66597-hcd.c +++ b/drivers/usb/host/r8a66597-hcd.c | |||
@@ -35,7 +35,10 @@ | |||
35 | #include <linux/usb.h> | 35 | #include <linux/usb.h> |
36 | #include <linux/platform_device.h> | 36 | #include <linux/platform_device.h> |
37 | #include <linux/io.h> | 37 | #include <linux/io.h> |
38 | #include <linux/mm.h> | ||
38 | #include <linux/irq.h> | 39 | #include <linux/irq.h> |
40 | #include <linux/slab.h> | ||
41 | #include <asm/cacheflush.h> | ||
39 | 42 | ||
40 | #include "../core/hcd.h" | 43 | #include "../core/hcd.h" |
41 | #include "r8a66597.h" | 44 | #include "r8a66597.h" |
@@ -216,8 +219,17 @@ static void disable_controller(struct r8a66597 *r8a66597) | |||
216 | { | 219 | { |
217 | int port; | 220 | int port; |
218 | 221 | ||
222 | /* disable interrupts */ | ||
219 | r8a66597_write(r8a66597, 0, INTENB0); | 223 | r8a66597_write(r8a66597, 0, INTENB0); |
220 | r8a66597_write(r8a66597, 0, INTSTS0); | 224 | r8a66597_write(r8a66597, 0, INTENB1); |
225 | r8a66597_write(r8a66597, 0, BRDYENB); | ||
226 | r8a66597_write(r8a66597, 0, BEMPENB); | ||
227 | r8a66597_write(r8a66597, 0, NRDYENB); | ||
228 | |||
229 | /* clear status */ | ||
230 | r8a66597_write(r8a66597, 0, BRDYSTS); | ||
231 | r8a66597_write(r8a66597, 0, NRDYSTS); | ||
232 | r8a66597_write(r8a66597, 0, BEMPSTS); | ||
221 | 233 | ||
222 | for (port = 0; port < r8a66597->max_root_hub; port++) | 234 | for (port = 0; port < r8a66597->max_root_hub; port++) |
223 | r8a66597_disable_port(r8a66597, port); | 235 | r8a66597_disable_port(r8a66597, port); |
@@ -407,7 +419,7 @@ static u8 alloc_usb_address(struct r8a66597 *r8a66597, struct urb *urb) | |||
407 | 419 | ||
408 | /* this function must be called with interrupt disabled */ | 420 | /* this function must be called with interrupt disabled */ |
409 | static void free_usb_address(struct r8a66597 *r8a66597, | 421 | static void free_usb_address(struct r8a66597 *r8a66597, |
410 | struct r8a66597_device *dev) | 422 | struct r8a66597_device *dev, int reset) |
411 | { | 423 | { |
412 | int port; | 424 | int port; |
413 | 425 | ||
@@ -419,7 +431,13 @@ static void free_usb_address(struct r8a66597 *r8a66597, | |||
419 | dev->state = USB_STATE_DEFAULT; | 431 | dev->state = USB_STATE_DEFAULT; |
420 | r8a66597->address_map &= ~(1 << dev->address); | 432 | r8a66597->address_map &= ~(1 << dev->address); |
421 | dev->address = 0; | 433 | dev->address = 0; |
422 | dev_set_drvdata(&dev->udev->dev, NULL); | 434 | /* |
435 | * Only when resetting USB, it is necessary to erase drvdata. When | ||
436 | * a usb device with usb hub is disconnect, "dev->udev" is already | ||
437 | * freed on usb_desconnect(). So we cannot access the data. | ||
438 | */ | ||
439 | if (reset) | ||
440 | dev_set_drvdata(&dev->udev->dev, NULL); | ||
423 | list_del(&dev->device_list); | 441 | list_del(&dev->device_list); |
424 | kfree(dev); | 442 | kfree(dev); |
425 | 443 | ||
@@ -811,6 +829,26 @@ static void enable_r8a66597_pipe(struct r8a66597 *r8a66597, struct urb *urb, | |||
811 | enable_r8a66597_pipe_dma(r8a66597, dev, pipe, urb); | 829 | enable_r8a66597_pipe_dma(r8a66597, dev, pipe, urb); |
812 | } | 830 | } |
813 | 831 | ||
832 | static void r8a66597_urb_done(struct r8a66597 *r8a66597, struct urb *urb, | ||
833 | int status) | ||
834 | __releases(r8a66597->lock) | ||
835 | __acquires(r8a66597->lock) | ||
836 | { | ||
837 | if (usb_pipein(urb->pipe) && usb_pipetype(urb->pipe) != PIPE_CONTROL) { | ||
838 | void *ptr; | ||
839 | |||
840 | for (ptr = urb->transfer_buffer; | ||
841 | ptr < urb->transfer_buffer + urb->transfer_buffer_length; | ||
842 | ptr += PAGE_SIZE) | ||
843 | flush_dcache_page(virt_to_page(ptr)); | ||
844 | } | ||
845 | |||
846 | usb_hcd_unlink_urb_from_ep(r8a66597_to_hcd(r8a66597), urb); | ||
847 | spin_unlock(&r8a66597->lock); | ||
848 | usb_hcd_giveback_urb(r8a66597_to_hcd(r8a66597), urb, status); | ||
849 | spin_lock(&r8a66597->lock); | ||
850 | } | ||
851 | |||
814 | /* this function must be called with interrupt disabled */ | 852 | /* this function must be called with interrupt disabled */ |
815 | static void force_dequeue(struct r8a66597 *r8a66597, u16 pipenum, u16 address) | 853 | static void force_dequeue(struct r8a66597 *r8a66597, u16 pipenum, u16 address) |
816 | { | 854 | { |
@@ -822,8 +860,6 @@ static void force_dequeue(struct r8a66597 *r8a66597, u16 pipenum, u16 address) | |||
822 | return; | 860 | return; |
823 | 861 | ||
824 | list_for_each_entry_safe(td, next, list, queue) { | 862 | list_for_each_entry_safe(td, next, list, queue) { |
825 | if (!td) | ||
826 | continue; | ||
827 | if (td->address != address) | 863 | if (td->address != address) |
828 | continue; | 864 | continue; |
829 | 865 | ||
@@ -831,15 +867,9 @@ static void force_dequeue(struct r8a66597 *r8a66597, u16 pipenum, u16 address) | |||
831 | list_del(&td->queue); | 867 | list_del(&td->queue); |
832 | kfree(td); | 868 | kfree(td); |
833 | 869 | ||
834 | if (urb) { | 870 | if (urb) |
835 | usb_hcd_unlink_urb_from_ep(r8a66597_to_hcd(r8a66597), | 871 | r8a66597_urb_done(r8a66597, urb, -ENODEV); |
836 | urb); | ||
837 | 872 | ||
838 | spin_unlock(&r8a66597->lock); | ||
839 | usb_hcd_giveback_urb(r8a66597_to_hcd(r8a66597), urb, | ||
840 | -ENODEV); | ||
841 | spin_lock(&r8a66597->lock); | ||
842 | } | ||
843 | break; | 873 | break; |
844 | } | 874 | } |
845 | } | 875 | } |
@@ -999,6 +1029,8 @@ static void start_root_hub_sampling(struct r8a66597 *r8a66597, int port, | |||
999 | /* this function must be called with interrupt disabled */ | 1029 | /* this function must be called with interrupt disabled */ |
1000 | static void r8a66597_check_syssts(struct r8a66597 *r8a66597, int port, | 1030 | static void r8a66597_check_syssts(struct r8a66597 *r8a66597, int port, |
1001 | u16 syssts) | 1031 | u16 syssts) |
1032 | __releases(r8a66597->lock) | ||
1033 | __acquires(r8a66597->lock) | ||
1002 | { | 1034 | { |
1003 | if (syssts == SE0) { | 1035 | if (syssts == SE0) { |
1004 | r8a66597_write(r8a66597, ~ATTCH, get_intsts_reg(port)); | 1036 | r8a66597_write(r8a66597, ~ATTCH, get_intsts_reg(port)); |
@@ -1016,7 +1048,9 @@ static void r8a66597_check_syssts(struct r8a66597 *r8a66597, int port, | |||
1016 | usb_hcd_resume_root_hub(r8a66597_to_hcd(r8a66597)); | 1048 | usb_hcd_resume_root_hub(r8a66597_to_hcd(r8a66597)); |
1017 | } | 1049 | } |
1018 | 1050 | ||
1051 | spin_unlock(&r8a66597->lock); | ||
1019 | usb_hcd_poll_rh_status(r8a66597_to_hcd(r8a66597)); | 1052 | usb_hcd_poll_rh_status(r8a66597_to_hcd(r8a66597)); |
1053 | spin_lock(&r8a66597->lock); | ||
1020 | } | 1054 | } |
1021 | 1055 | ||
1022 | /* this function must be called with interrupt disabled */ | 1056 | /* this function must be called with interrupt disabled */ |
@@ -1042,7 +1076,7 @@ static void r8a66597_usb_disconnect(struct r8a66597 *r8a66597, int port) | |||
1042 | struct r8a66597_device *dev = r8a66597->root_hub[port].dev; | 1076 | struct r8a66597_device *dev = r8a66597->root_hub[port].dev; |
1043 | 1077 | ||
1044 | disable_r8a66597_pipe_all(r8a66597, dev); | 1078 | disable_r8a66597_pipe_all(r8a66597, dev); |
1045 | free_usb_address(r8a66597, dev); | 1079 | free_usb_address(r8a66597, dev, 0); |
1046 | 1080 | ||
1047 | start_root_hub_sampling(r8a66597, port, 0); | 1081 | start_root_hub_sampling(r8a66597, port, 0); |
1048 | } | 1082 | } |
@@ -1276,10 +1310,7 @@ __releases(r8a66597->lock) __acquires(r8a66597->lock) | |||
1276 | if (usb_pipeisoc(urb->pipe)) | 1310 | if (usb_pipeisoc(urb->pipe)) |
1277 | urb->start_frame = r8a66597_get_frame(hcd); | 1311 | urb->start_frame = r8a66597_get_frame(hcd); |
1278 | 1312 | ||
1279 | usb_hcd_unlink_urb_from_ep(r8a66597_to_hcd(r8a66597), urb); | 1313 | r8a66597_urb_done(r8a66597, urb, status); |
1280 | spin_unlock(&r8a66597->lock); | ||
1281 | usb_hcd_giveback_urb(hcd, urb, status); | ||
1282 | spin_lock(&r8a66597->lock); | ||
1283 | } | 1314 | } |
1284 | 1315 | ||
1285 | if (restart) { | 1316 | if (restart) { |
@@ -2025,8 +2056,6 @@ static struct r8a66597_device *get_r8a66597_device(struct r8a66597 *r8a66597, | |||
2025 | struct list_head *list = &r8a66597->child_device; | 2056 | struct list_head *list = &r8a66597->child_device; |
2026 | 2057 | ||
2027 | list_for_each_entry(dev, list, device_list) { | 2058 | list_for_each_entry(dev, list, device_list) { |
2028 | if (!dev) | ||
2029 | continue; | ||
2030 | if (dev->usb_address != addr) | 2059 | if (dev->usb_address != addr) |
2031 | continue; | 2060 | continue; |
2032 | 2061 | ||
@@ -2063,7 +2092,7 @@ static void update_usb_address_map(struct r8a66597 *r8a66597, | |||
2063 | spin_lock_irqsave(&r8a66597->lock, flags); | 2092 | spin_lock_irqsave(&r8a66597->lock, flags); |
2064 | dev = get_r8a66597_device(r8a66597, addr); | 2093 | dev = get_r8a66597_device(r8a66597, addr); |
2065 | disable_r8a66597_pipe_all(r8a66597, dev); | 2094 | disable_r8a66597_pipe_all(r8a66597, dev); |
2066 | free_usb_address(r8a66597, dev); | 2095 | free_usb_address(r8a66597, dev, 0); |
2067 | put_child_connect_map(r8a66597, addr); | 2096 | put_child_connect_map(r8a66597, addr); |
2068 | spin_unlock_irqrestore(&r8a66597->lock, flags); | 2097 | spin_unlock_irqrestore(&r8a66597->lock, flags); |
2069 | } | 2098 | } |
@@ -2206,7 +2235,7 @@ static int r8a66597_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, | |||
2206 | rh->port |= (1 << USB_PORT_FEAT_RESET); | 2235 | rh->port |= (1 << USB_PORT_FEAT_RESET); |
2207 | 2236 | ||
2208 | disable_r8a66597_pipe_all(r8a66597, dev); | 2237 | disable_r8a66597_pipe_all(r8a66597, dev); |
2209 | free_usb_address(r8a66597, dev); | 2238 | free_usb_address(r8a66597, dev, 1); |
2210 | 2239 | ||
2211 | r8a66597_mdfy(r8a66597, USBRST, USBRST | UACT, | 2240 | r8a66597_mdfy(r8a66597, USBRST, USBRST | UACT, |
2212 | get_dvstctr_reg(port)); | 2241 | get_dvstctr_reg(port)); |
@@ -2357,7 +2386,7 @@ static int r8a66597_resume(struct device *dev) | |||
2357 | return 0; | 2386 | return 0; |
2358 | } | 2387 | } |
2359 | 2388 | ||
2360 | static struct dev_pm_ops r8a66597_dev_pm_ops = { | 2389 | static const struct dev_pm_ops r8a66597_dev_pm_ops = { |
2361 | .suspend = r8a66597_suspend, | 2390 | .suspend = r8a66597_suspend, |
2362 | .resume = r8a66597_resume, | 2391 | .resume = r8a66597_resume, |
2363 | .poweroff = r8a66597_suspend, | 2392 | .poweroff = r8a66597_suspend, |
@@ -2470,6 +2499,12 @@ static int __devinit r8a66597_probe(struct platform_device *pdev) | |||
2470 | r8a66597->rh_timer.data = (unsigned long)r8a66597; | 2499 | r8a66597->rh_timer.data = (unsigned long)r8a66597; |
2471 | r8a66597->reg = (unsigned long)reg; | 2500 | r8a66597->reg = (unsigned long)reg; |
2472 | 2501 | ||
2502 | /* make sure no interrupts are pending */ | ||
2503 | ret = r8a66597_clock_enable(r8a66597); | ||
2504 | if (ret < 0) | ||
2505 | goto clean_up3; | ||
2506 | disable_controller(r8a66597); | ||
2507 | |||
2473 | for (i = 0; i < R8A66597_MAX_NUM_PIPE; i++) { | 2508 | for (i = 0; i < R8A66597_MAX_NUM_PIPE; i++) { |
2474 | INIT_LIST_HEAD(&r8a66597->pipe_queue[i]); | 2509 | INIT_LIST_HEAD(&r8a66597->pipe_queue[i]); |
2475 | init_timer(&r8a66597->td_timer[i]); | 2510 | init_timer(&r8a66597->td_timer[i]); |