diff options
author | Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> | 2012-11-06 03:11:53 -0500 |
---|---|---|
committer | Felipe Balbi <balbi@ti.com> | 2012-11-06 08:04:28 -0500 |
commit | 7b332e5fef480ee14d133d9b83af22d03819368e (patch) | |
tree | d9720f428f53b4038de082815e0089f7e0c250a2 /drivers/usb | |
parent | 24e4c1c30da3926db547aab4ec873afdc60bd3ee (diff) |
usb: renesas_usbhs: host: add endpoint user counter
renesas_usbhs attaches pipe to endpoint when urb was queued, and it will be
detached when transfer was done. Multi device controlling was enabled by this
behavior.
Now renesas_usbhs driver tried to wait until detaching if urb was queued to
endpoint which already has been attached to pipe, and it created strange driver
behavior.
But it can re-use this attached pipe if multi urb was queued. This patch
implements it.
Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Signed-off-by: Felipe Balbi <balbi@ti.com>
Diffstat (limited to 'drivers/usb')
-rw-r--r-- | drivers/usb/renesas_usbhs/mod_host.c | 24 |
1 files changed, 13 insertions, 11 deletions
diff --git a/drivers/usb/renesas_usbhs/mod_host.c b/drivers/usb/renesas_usbhs/mod_host.c index 33f706387237..73c5039f7670 100644 --- a/drivers/usb/renesas_usbhs/mod_host.c +++ b/drivers/usb/renesas_usbhs/mod_host.c | |||
@@ -85,6 +85,7 @@ struct usbhsh_ep { | |||
85 | struct usbhsh_device *udev; /* attached udev */ | 85 | struct usbhsh_device *udev; /* attached udev */ |
86 | struct usb_host_endpoint *ep; | 86 | struct usb_host_endpoint *ep; |
87 | struct list_head ep_list; /* list to usbhsh_device */ | 87 | struct list_head ep_list; /* list to usbhsh_device */ |
88 | unsigned int counter; /* pipe attach counter */ | ||
88 | }; | 89 | }; |
89 | 90 | ||
90 | #define USBHSH_DEVICE_MAX 10 /* see DEVADDn / DCPMAXP / PIPEMAXP */ | 91 | #define USBHSH_DEVICE_MAX 10 /* see DEVADDn / DCPMAXP / PIPEMAXP */ |
@@ -271,8 +272,12 @@ static int usbhsh_pipe_attach(struct usbhsh_hpriv *hpriv, | |||
271 | /******************** spin lock ********************/ | 272 | /******************** spin lock ********************/ |
272 | usbhs_lock(priv, flags); | 273 | usbhs_lock(priv, flags); |
273 | 274 | ||
274 | if (unlikely(usbhsh_uep_to_pipe(uep))) { | 275 | /* |
275 | dev_err(dev, "uep already has pipe\n"); | 276 | * if uep has been attached to pipe, |
277 | * reuse it | ||
278 | */ | ||
279 | if (usbhsh_uep_to_pipe(uep)) { | ||
280 | ret = 0; | ||
276 | goto usbhsh_pipe_attach_done; | 281 | goto usbhsh_pipe_attach_done; |
277 | } | 282 | } |
278 | 283 | ||
@@ -320,6 +325,9 @@ static int usbhsh_pipe_attach(struct usbhsh_hpriv *hpriv, | |||
320 | } | 325 | } |
321 | 326 | ||
322 | usbhsh_pipe_attach_done: | 327 | usbhsh_pipe_attach_done: |
328 | if (0 == ret) | ||
329 | uep->counter++; | ||
330 | |||
323 | usbhs_unlock(priv, flags); | 331 | usbhs_unlock(priv, flags); |
324 | /******************** spin unlock ******************/ | 332 | /******************** spin unlock ******************/ |
325 | 333 | ||
@@ -341,7 +349,7 @@ static void usbhsh_pipe_detach(struct usbhsh_hpriv *hpriv, | |||
341 | 349 | ||
342 | if (unlikely(!pipe)) { | 350 | if (unlikely(!pipe)) { |
343 | dev_err(dev, "uep doens't have pipe\n"); | 351 | dev_err(dev, "uep doens't have pipe\n"); |
344 | } else { | 352 | } else if (1 == uep->counter--) { /* last user */ |
345 | struct usb_host_endpoint *ep = usbhsh_uep_to_ep(uep); | 353 | struct usb_host_endpoint *ep = usbhsh_uep_to_ep(uep); |
346 | struct usbhsh_device *udev = usbhsh_uep_to_udev(uep); | 354 | struct usbhsh_device *udev = usbhsh_uep_to_udev(uep); |
347 | 355 | ||
@@ -386,6 +394,7 @@ static int usbhsh_endpoint_attach(struct usbhsh_hpriv *hpriv, | |||
386 | /* | 394 | /* |
387 | * init endpoint | 395 | * init endpoint |
388 | */ | 396 | */ |
397 | uep->counter = 0; | ||
389 | INIT_LIST_HEAD(&uep->ep_list); | 398 | INIT_LIST_HEAD(&uep->ep_list); |
390 | list_add_tail(&uep->ep_list, &udev->ep_list_head); | 399 | list_add_tail(&uep->ep_list, &udev->ep_list_head); |
391 | 400 | ||
@@ -954,7 +963,6 @@ static int usbhsh_urb_enqueue(struct usb_hcd *hcd, | |||
954 | struct usb_host_endpoint *ep = urb->ep; | 963 | struct usb_host_endpoint *ep = urb->ep; |
955 | struct usbhsh_device *new_udev = NULL; | 964 | struct usbhsh_device *new_udev = NULL; |
956 | int is_dir_in = usb_pipein(urb->pipe); | 965 | int is_dir_in = usb_pipein(urb->pipe); |
957 | int i; | ||
958 | int ret; | 966 | int ret; |
959 | 967 | ||
960 | dev_dbg(dev, "%s (%s)\n", __func__, is_dir_in ? "in" : "out"); | 968 | dev_dbg(dev, "%s (%s)\n", __func__, is_dir_in ? "in" : "out"); |
@@ -1000,13 +1008,7 @@ static int usbhsh_urb_enqueue(struct usb_hcd *hcd, | |||
1000 | * attach pipe to endpoint | 1008 | * attach pipe to endpoint |
1001 | * see [image of mod_host] | 1009 | * see [image of mod_host] |
1002 | */ | 1010 | */ |
1003 | for (i = 0; i < 1024; i++) { | 1011 | ret = usbhsh_pipe_attach(hpriv, urb); |
1004 | ret = usbhsh_pipe_attach(hpriv, urb); | ||
1005 | if (ret < 0) | ||
1006 | msleep(100); | ||
1007 | else | ||
1008 | break; | ||
1009 | } | ||
1010 | if (ret < 0) { | 1012 | if (ret < 0) { |
1011 | dev_err(dev, "pipe attach failed\n"); | 1013 | dev_err(dev, "pipe attach failed\n"); |
1012 | goto usbhsh_urb_enqueue_error_free_endpoint; | 1014 | goto usbhsh_urb_enqueue_error_free_endpoint; |