static int msm72k_queue(struct usb_ep *_ep, struct usb_request *req, gfp_t gfp_flags) { struct msm_endpoint *ep = to_msm_endpoint(_ep); struct usb_info *ui = ep->ui; if (ep == &ui->ep0in) { struct msm_request *r = to_msm_request(req); if (!req->length) goto ep_queue_done; else { if (ui->ep0_dir == USB_DIR_OUT) { ep = &ui->ep0out; ep->ep.driver_data = ui->ep0in.ep.driver_data; } /* ep0_queue_ack_complete queue a receive for ACK before ** calling req->complete */ r->gadget_complete = req->complete; req->complete = ep0_queue_ack_complete; } } ep_queue_done: return usb_ept_queue_xfer(ep, req); }
static int msm72k_queue(struct usb_ep *_ep, struct usb_request *req, gfp_t gfp_flags) { struct msm_endpoint *ep = to_msm_endpoint(_ep); struct usb_info *ui = ep->ui; int ret; if (ep == &ui->ep0in) { struct msm_request *r = to_msm_request(req); if (!req->length) goto ep_queue_done; r->gadget_complete = req->complete; /* ep0_queue_ack_complete queue a receive for ACK before ** calling req->complete */ req->complete = ep0_queue_ack_complete; if (ui->ep0_dir == USB_DIR_OUT) ep = &ui->ep0out; goto ep_queue_done; } if (ui->usb_state == USB_STATE_SUSPENDED) { ret = msm72k_wakeup(&ui->gadget); if (ret) return ret; } ep_queue_done: return usb_ept_queue_xfer(ep, req); }
static void ep0_setup_send(struct usb_info *ui, unsigned length) { struct usb_request *req = ui->setup_req; struct msm_request *r = to_msm_request(req); struct msm_endpoint *ept = &ui->ep0in; req->length = length; req->complete = ep0_queue_ack_complete; r->gadget_complete = NULL; usb_ept_queue_xfer(ept, req); }
static void ep0_complete(struct usb_ep *ep, struct usb_request *req) { struct msm_request *r = to_msm_request(req); struct msm_endpoint *ept = to_msm_endpoint(ep); struct usb_info *ui = ept->ui; req->complete = r->gadget_complete; r->gadget_complete = NULL; if (req->complete) req->complete(&ui->ep0in.ep, req); }
static void msm72k_free_request(struct usb_ep *_ep, struct usb_request *_req) { struct msm_request *req = to_msm_request(_req); struct msm_endpoint *ept = to_msm_endpoint(_ep); struct usb_info *ui = ept->ui; /* request should not be busy */ BUG_ON(req->busy); if (req->alloced) kfree(req->req.buf); dma_pool_free(ui->pool, req->item, req->item_dma); kfree(req); }
static int msm72k_dequeue(struct usb_ep *_ep, struct usb_request *_req) { struct msm_endpoint *ep = to_msm_endpoint(_ep); struct msm_request *req = to_msm_request(_req); struct usb_info *ui = ep->ui; struct msm_request *cur, *prev; unsigned long flags; if (!_ep || !_req) return -EINVAL; spin_lock_irqsave(&ui->lock, flags); cur = ep->req; prev = NULL; while (cur != 0) { if (cur == req) { req->busy = 0; req->live = 0; req->req.status = -ECONNRESET; req->req.actual = 0; if (req->req.complete) { spin_unlock_irqrestore(&ui->lock, flags); req->req.complete(&ep->ep, &req->req); spin_lock_irqsave(&ui->lock, flags); } /* remove from linked list */ if (prev) prev->next = cur->next; else ep->req = cur->next; if (ep->last == cur) ep->last = prev; /* break from loop */ cur = NULL; } else { prev = cur; cur = cur->next; } } spin_unlock_irqrestore(&ui->lock, flags); return 0; }
static void msm72k_free_request(struct usb_ep *_ep, struct usb_request *_req) { struct msm_request *req = to_msm_request(_req); struct msm_endpoint *ept = to_msm_endpoint(_ep); struct usb_info *ui = ept->ui; unsigned long flags; int dead = 0; spin_lock_irqsave(&ui->lock, flags); /* defer freeing resources if request is still busy */ if (req->busy) dead = req->dead = 1; spin_unlock_irqrestore(&ui->lock, flags); /* if req->dead, then we will clean up when the request finishes */ if (!dead) do_free_req(ui, req); }
static void ep0_queue_ack_complete(struct usb_ep *ep, struct usb_request *req) { struct msm_endpoint *ept = to_msm_endpoint(ep); struct msm_request *r = to_msm_request(req); completion_func gadget_complete = r->gadget_complete; if (gadget_complete) { r->gadget_complete = NULL; gadget_complete(ep, req); } /* queue up the receive of the ACK response from the host */ if (req->status == 0) { struct usb_info *ui = ept->ui; req->length = 0; req->complete = ep0_complete; if (ui->ep0_dir == USB_DIR_IN) usb_ept_queue_xfer(&ui->ep0out, req); else usb_ept_queue_xfer(&ui->ep0in, req); } else ep0_complete(ep, req); }
int usb_ept_queue_xfer(struct msm_endpoint *ept, struct usb_request *_req) { unsigned long flags; struct msm_request *req = to_msm_request(_req); struct msm_request *last; struct usb_info *ui = ept->ui; struct ept_queue_item *item = req->item; unsigned length = req->req.length; if (length > 0x4000) return -EMSGSIZE; spin_lock_irqsave(&ui->lock, flags); if (req->busy) { req->req.status = -EBUSY; spin_unlock_irqrestore(&ui->lock, flags); INFO("usb_ept_queue_xfer() tried to queue busy request\n"); return -EBUSY; } if (!ui->online && (ept->num != 0)) { req->req.status = -ESHUTDOWN; spin_unlock_irqrestore(&ui->lock, flags); INFO("usb_ept_queue_xfer() called while offline\n"); return -ESHUTDOWN; } req->busy = 1; req->live = 0; req->next = 0; req->req.status = -EBUSY; req->dma = dma_map_single(NULL, req->req.buf, length, (ept->flags & EPT_FLAG_IN) ? DMA_TO_DEVICE : DMA_FROM_DEVICE); /* prepare the transaction descriptor item for the hardware */ item->next = TERMINATE; item->info = INFO_BYTES(length) | INFO_IOC | INFO_ACTIVE; item->page0 = req->dma; item->page1 = (req->dma + 0x1000) & 0xfffff000; item->page2 = (req->dma + 0x2000) & 0xfffff000; item->page3 = (req->dma + 0x3000) & 0xfffff000; /* Add the new request to the end of the queue */ last = ept->last; if (last) { /* Already requests in the queue. add us to the * end, but let the completion interrupt actually * start things going, to avoid hw issues */ last->next = req; /* only modify the hw transaction next pointer if * that request is not live */ if (!last->live) last->item->next = req->item_dma; } else { /* queue was empty -- kick the hardware */ ept->req = req; usb_ept_start(ept); } ept->last = req; spin_unlock_irqrestore(&ui->lock, flags); return 0; }