static int xudc_write_fifo(struct xusb_ep *ep, struct xusb_req *req)
{
	u32 max;
	u32 length;
	int ret;
	int retval = -EAGAIN;
	struct xusb_udc *udc = ep->udc;
	int is_last, is_short = 0;
	u8 *buf;

	max = le16_to_cpu(ep->desc->wMaxPacketSize);
	buf = req->usb_req.buf + req->usb_req.actual;
	prefetch(buf);
	length = req->usb_req.length - req->usb_req.actual;
	length = min(length, max);

	ret = xudc_eptxrx(ep, req, buf, length);
	switch (ret) {
	case 0:
		req->usb_req.actual += length;
		if (unlikely(length != max)) {
			is_last = is_short = 1;
		} else {
			if (likely(req->usb_req.length !=
				   req->usb_req.actual) || req->usb_req.zero)
				is_last = 0;
			else
				is_last = 1;
		}
		dev_dbg(udc->dev, "%s: wrote %s %d bytes%s%s %d left %p\n",
			__func__, ep->ep_usb.name, length, is_last ? "/L" : "",
			is_short ? "/S" : "",
			req->usb_req.length - req->usb_req.actual, req);
		/* completion */
		if (is_last) {
			xudc_done(ep, req, 0);
			retval = 0;
		}
		break;
	case -EAGAIN:
		dev_dbg(udc->dev, "Send busy\n");
		break;
	case -EINVAL:
	case -ETIMEDOUT:
		/* DMA error, dequeue the request */
		xudc_done(ep, req, -ECONNRESET);
		retval = 0;
		break;
	}

	return retval;
}
static int xudc_write_fifo(struct xusb_ep *ep, struct xusb_req *req)
{
	u32 max;
	u32 length;
	int ret;
	int retval = -EAGAIN;
	struct xusb_udc *udc = ep->udc;
	int is_last, is_short = 0;
	u8 *buf;

	max = le16_to_cpu(ep->desc->wMaxPacketSize);
	buf = req->usb_req.buf + req->usb_req.actual;
	prefetch(buf);
	length = req->usb_req.length - req->usb_req.actual;
	length = min(length, max);

	ret = xudc_eptxrx(ep, req, buf, length);
	switch (ret) {
	case 0:
		req->usb_req.actual += length;
		if (unlikely(length != max)) {
			is_last = is_short = 1;
		} else {
			if (likely(req->usb_req.length !=
				   req->usb_req.actual) || req->usb_req.zero)
				is_last = 0;
			else
				is_last = 1;
		}
		dev_dbg(udc->dev, "%s: wrote %s %d bytes%s%s %d left %p\n",
			__func__, ep->ep_usb.name, length, is_last ? "/L" : "",
			is_short ? "/S" : "",
			req->usb_req.length - req->usb_req.actual, req);
		 
		if (is_last) {
			xudc_done(ep, req, 0);
			retval = 0;
		}
		break;
	case -EAGAIN:
		dev_dbg(udc->dev, "Send busy\n");
		break;
	case -EINVAL:
	case -ETIMEDOUT:
		 
		xudc_done(ep, req, -ECONNRESET);
		retval = 0;
		break;
	}

	return retval;
}