diff options
author | Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> | 2011-10-31 03:48:00 -0400 |
---|---|---|
committer | Felipe Balbi <balbi@ti.com> | 2011-12-12 04:45:07 -0500 |
commit | ab14230854aba9d0c99b3cd0e4bb1ef430973d84 (patch) | |
tree | f4c598256c6b61404883bfeda2aa5c66ff76866b /drivers/usb/renesas_usbhs/mod_host.c | |
parent | c5b963f809f378d4fedd6f2f09b36f50c5a37bd5 (diff) |
usb: gadget: renesas_usbhs: check device0 status when alloc
device0 was treated without checking in usbhsh_device_alloc().
but "udev->usbv" and "dev_set_drvdata()" will be overwritten
if device0 was multi-allocated.
This patch fixes this issue.
Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Signed-off-by: Felipe Balbi <balbi@ti.com>
Diffstat (limited to 'drivers/usb/renesas_usbhs/mod_host.c')
-rw-r--r-- | drivers/usb/renesas_usbhs/mod_host.c | 36 |
1 files changed, 22 insertions, 14 deletions
diff --git a/drivers/usb/renesas_usbhs/mod_host.c b/drivers/usb/renesas_usbhs/mod_host.c index 3f1eaf15e0ba..e6fd044adfa3 100644 --- a/drivers/usb/renesas_usbhs/mod_host.c +++ b/drivers/usb/renesas_usbhs/mod_host.c | |||
@@ -153,6 +153,7 @@ static const char usbhsh_hcd_name[] = "renesas_usbhs host"; | |||
153 | #define usbhsh_usbv_to_udev(d) dev_get_drvdata(&(d)->dev) | 153 | #define usbhsh_usbv_to_udev(d) dev_get_drvdata(&(d)->dev) |
154 | 154 | ||
155 | #define usbhsh_udev_to_usbv(h) ((h)->usbv) | 155 | #define usbhsh_udev_to_usbv(h) ((h)->usbv) |
156 | #define usbhsh_udev_is_used(h) usbhsh_udev_to_usbv(h) | ||
156 | 157 | ||
157 | #define usbhsh_pipe_info(p) ((p)->mod_private) | 158 | #define usbhsh_pipe_info(p) ((p)->mod_private) |
158 | 159 | ||
@@ -231,27 +232,34 @@ static struct usbhsh_device *usbhsh_device_alloc(struct usbhsh_hpriv *hpriv, | |||
231 | int i; | 232 | int i; |
232 | 233 | ||
233 | /* | 234 | /* |
234 | * device 0 | 235 | * find device |
235 | */ | 236 | */ |
236 | if (0 == usb_pipedevice(urb->pipe)) { | 237 | if (0 == usb_pipedevice(urb->pipe)) { |
238 | /* | ||
239 | * device0 is special case | ||
240 | */ | ||
237 | udev = usbhsh_device0(hpriv); | 241 | udev = usbhsh_device0(hpriv); |
238 | goto usbhsh_device_find; | 242 | if (usbhsh_udev_is_used(udev)) |
239 | } | 243 | udev = NULL; |
244 | } else { | ||
245 | struct usbhsh_device *pos; | ||
240 | 246 | ||
241 | /* | 247 | /* |
242 | * find unused device | 248 | * find unused device |
243 | */ | 249 | */ |
244 | usbhsh_for_each_udev(udev, hpriv, i) { | 250 | usbhsh_for_each_udev(pos, hpriv, i) { |
245 | if (usbhsh_udev_to_usbv(udev)) | 251 | if (usbhsh_udev_is_used(pos)) |
246 | continue; | 252 | continue; |
247 | goto usbhsh_device_find; | 253 | udev = pos; |
254 | break; | ||
255 | } | ||
248 | } | 256 | } |
249 | 257 | ||
250 | dev_err(dev, "no free usbhsh_device\n"); | 258 | if (!udev) { |
251 | 259 | dev_err(dev, "no free usbhsh_device\n"); | |
252 | return NULL; | 260 | return NULL; |
261 | } | ||
253 | 262 | ||
254 | usbhsh_device_find: | ||
255 | if (usbhsh_device_has_endpoint(udev)) | 263 | if (usbhsh_device_has_endpoint(udev)) |
256 | dev_warn(dev, "udev have old endpoint\n"); | 264 | dev_warn(dev, "udev have old endpoint\n"); |
257 | 265 | ||