diff options
| author | Tejun Heo <tj@kernel.org> | 2014-11-22 09:32:08 -0500 |
|---|---|---|
| committer | Tejun Heo <tj@kernel.org> | 2014-11-22 09:32:08 -0500 |
| commit | cceb9bd63373061ad7b75c321808a2fb11c86545 (patch) | |
| tree | a70d939eabed2e19538707402441644dfc26990e /drivers/usb/gadget/function/f_loopback.c | |
| parent | 56e4dea81a55c338eede625f715c7fa21f1a28c4 (diff) | |
| parent | 8a84e01e147f44111988f9d8ccd2eaa30215a0f2 (diff) | |
Merge branch 'master' into for-3.19
Pull in to receive 54ef6df3f3f1 ("rcu: Provide counterpart to
rcu_dereference() for non-RCU situations").
Signed-off-by: Tejun Heo <tj@kernel.org>
Diffstat (limited to 'drivers/usb/gadget/function/f_loopback.c')
| -rw-r--r-- | drivers/usb/gadget/function/f_loopback.c | 87 |
1 files changed, 42 insertions, 45 deletions
diff --git a/drivers/usb/gadget/function/f_loopback.c b/drivers/usb/gadget/function/f_loopback.c index bf04389137e6..298b46112b1a 100644 --- a/drivers/usb/gadget/function/f_loopback.c +++ b/drivers/usb/gadget/function/f_loopback.c | |||
| @@ -253,22 +253,13 @@ static void loopback_complete(struct usb_ep *ep, struct usb_request *req) | |||
| 253 | 253 | ||
| 254 | case 0: /* normal completion? */ | 254 | case 0: /* normal completion? */ |
| 255 | if (ep == loop->out_ep) { | 255 | if (ep == loop->out_ep) { |
| 256 | /* loop this OUT packet back IN to the host */ | ||
| 257 | req->zero = (req->actual < req->length); | 256 | req->zero = (req->actual < req->length); |
| 258 | req->length = req->actual; | 257 | req->length = req->actual; |
| 259 | status = usb_ep_queue(loop->in_ep, req, GFP_ATOMIC); | ||
| 260 | if (status == 0) | ||
| 261 | return; | ||
| 262 | |||
| 263 | /* "should never get here" */ | ||
| 264 | ERROR(cdev, "can't loop %s to %s: %d\n", | ||
| 265 | ep->name, loop->in_ep->name, | ||
| 266 | status); | ||
| 267 | } | 258 | } |
| 268 | 259 | ||
| 269 | /* queue the buffer for some later OUT packet */ | 260 | /* queue the buffer for some later OUT packet */ |
| 270 | req->length = buflen; | 261 | req->length = buflen; |
| 271 | status = usb_ep_queue(loop->out_ep, req, GFP_ATOMIC); | 262 | status = usb_ep_queue(ep, req, GFP_ATOMIC); |
| 272 | if (status == 0) | 263 | if (status == 0) |
| 273 | return; | 264 | return; |
| 274 | 265 | ||
| @@ -308,60 +299,66 @@ static inline struct usb_request *lb_alloc_ep_req(struct usb_ep *ep, int len) | |||
| 308 | return alloc_ep_req(ep, len, buflen); | 299 | return alloc_ep_req(ep, len, buflen); |
| 309 | } | 300 | } |
| 310 | 301 | ||
| 311 | static int | 302 | static int enable_endpoint(struct usb_composite_dev *cdev, struct f_loopback *loop, |
| 312 | enable_loopback(struct usb_composite_dev *cdev, struct f_loopback *loop) | 303 | struct usb_ep *ep) |
| 313 | { | 304 | { |
| 314 | int result = 0; | ||
| 315 | struct usb_ep *ep; | ||
| 316 | struct usb_request *req; | 305 | struct usb_request *req; |
| 317 | unsigned i; | 306 | unsigned i; |
| 307 | int result; | ||
| 318 | 308 | ||
| 319 | /* one endpoint writes data back IN to the host */ | 309 | /* |
| 320 | ep = loop->in_ep; | 310 | * one endpoint writes data back IN to the host while another endpoint |
| 311 | * just reads OUT packets | ||
| 312 | */ | ||
| 321 | result = config_ep_by_speed(cdev->gadget, &(loop->function), ep); | 313 | result = config_ep_by_speed(cdev->gadget, &(loop->function), ep); |
| 322 | if (result) | 314 | if (result) |
| 323 | return result; | 315 | goto fail0; |
| 324 | result = usb_ep_enable(ep); | 316 | result = usb_ep_enable(ep); |
| 325 | if (result < 0) | 317 | if (result < 0) |
| 326 | return result; | ||
| 327 | ep->driver_data = loop; | ||
| 328 | |||
| 329 | /* one endpoint just reads OUT packets */ | ||
| 330 | ep = loop->out_ep; | ||
| 331 | result = config_ep_by_speed(cdev->gadget, &(loop->function), ep); | ||
| 332 | if (result) | ||
| 333 | goto fail0; | 318 | goto fail0; |
| 334 | |||
| 335 | result = usb_ep_enable(ep); | ||
| 336 | if (result < 0) { | ||
| 337 | fail0: | ||
| 338 | ep = loop->in_ep; | ||
| 339 | usb_ep_disable(ep); | ||
| 340 | ep->driver_data = NULL; | ||
| 341 | return result; | ||
| 342 | } | ||
| 343 | ep->driver_data = loop; | 319 | ep->driver_data = loop; |
| 344 | 320 | ||
| 345 | /* allocate a bunch of read buffers and queue them all at once. | 321 | /* |
| 322 | * allocate a bunch of read buffers and queue them all at once. | ||
| 346 | * we buffer at most 'qlen' transfers; fewer if any need more | 323 | * we buffer at most 'qlen' transfers; fewer if any need more |
| 347 | * than 'buflen' bytes each. | 324 | * than 'buflen' bytes each. |
| 348 | */ | 325 | */ |
| 349 | for (i = 0; i < qlen && result == 0; i++) { | 326 | for (i = 0; i < qlen && result == 0; i++) { |
| 350 | req = lb_alloc_ep_req(ep, 0); | 327 | req = lb_alloc_ep_req(ep, 0); |
| 351 | if (req) { | 328 | if (!req) |
| 352 | req->complete = loopback_complete; | 329 | goto fail1; |
| 353 | result = usb_ep_queue(ep, req, GFP_ATOMIC); | 330 | |
| 354 | if (result) | 331 | req->complete = loopback_complete; |
| 355 | ERROR(cdev, "%s queue req --> %d\n", | 332 | result = usb_ep_queue(ep, req, GFP_ATOMIC); |
| 356 | ep->name, result); | 333 | if (result) { |
| 357 | } else { | 334 | ERROR(cdev, "%s queue req --> %d\n", |
| 358 | usb_ep_disable(ep); | 335 | ep->name, result); |
| 359 | ep->driver_data = NULL; | 336 | goto fail1; |
| 360 | result = -ENOMEM; | ||
| 361 | goto fail0; | ||
| 362 | } | 337 | } |
| 363 | } | 338 | } |
| 364 | 339 | ||
| 340 | return 0; | ||
| 341 | |||
| 342 | fail1: | ||
| 343 | usb_ep_disable(ep); | ||
| 344 | |||
| 345 | fail0: | ||
| 346 | return result; | ||
| 347 | } | ||
| 348 | |||
| 349 | static int | ||
| 350 | enable_loopback(struct usb_composite_dev *cdev, struct f_loopback *loop) | ||
| 351 | { | ||
| 352 | int result = 0; | ||
| 353 | |||
| 354 | result = enable_endpoint(cdev, loop, loop->in_ep); | ||
| 355 | if (result) | ||
| 356 | return result; | ||
| 357 | |||
| 358 | result = enable_endpoint(cdev, loop, loop->out_ep); | ||
| 359 | if (result) | ||
| 360 | return result; | ||
| 361 | |||
| 365 | DBG(cdev, "%s enabled\n", loop->function.name); | 362 | DBG(cdev, "%s enabled\n", loop->function.name); |
| 366 | return result; | 363 | return result; |
| 367 | } | 364 | } |
