示例#1
0
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);
}
示例#2
0
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);
}
示例#3
0
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);
}
示例#4
0
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);
}
示例#5
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;

	/* 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);
}
示例#6
0
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;
}
示例#7
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);
}
示例#8
0
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);
}
示例#9
0
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;
}