[PATCH 14/133] [Jaunty SRU] ARM.imx51 Freescale:ENGR00107483 Revert [MX37] failed to test our MSC driver with USBCV 1.3."
Brad Figg
brad.figg at canonical.com
Thu Jul 9 16:48:04 UTC 2009
From: Lily Zhang <r58066 at freescale.com>
This reverts commit 648bc6939d98667791010759987fe26f5c479e59.
Signed-off-by: Lily Zhang <r58066 at freescale.com>
Signed-off-by: Brad Figg <brad.figg at canonical.com>
---
drivers/usb/gadget/arcotg_udc.c | 99 +++++++++++++++++++++++++++---------
drivers/usb/gadget/arcotg_udc.h | 2 +-
drivers/usb/gadget/file_storage.c | 2 +
3 files changed, 77 insertions(+), 26 deletions(-)
diff --git a/drivers/usb/gadget/arcotg_udc.c b/drivers/usb/gadget/arcotg_udc.c
index bb8f761..2a5d78f 100644
--- a/drivers/usb/gadget/arcotg_udc.c
+++ b/drivers/usb/gadget/arcotg_udc.c
@@ -908,8 +908,8 @@ fsl_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
int is_iso = 0;
/* catch various bogus parameters */
- if (!_req || !req->req.buf || (ep_index(ep)
- && !list_empty(&req->queue))) {
+ if (!_req || !req->req.complete || !req->req.buf
+ || !list_empty(&req->queue)) {
VDBG("%s, bad params\n", __func__);
return -EINVAL;
}
@@ -964,6 +964,10 @@ fsl_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
return -ENOMEM;
}
+ /* Update ep0 state */
+ if ((ep_index(ep) == 0))
+ udc->ep0_state = DATA_STATE_XMIT;
+
/* irq handler advances the queue */
if (req != NULL)
list_add_tail(&req->queue, &ep->queue);
@@ -1093,6 +1097,7 @@ static int fsl_ep_set_halt(struct usb_ep *_ep, int value)
spin_unlock_irqrestore(&ep->udc->lock, flags);
if (ep_index(ep) == 0) {
+ udc->ep0_state = WAIT_FOR_SETUP;
udc->ep0_dir = 0;
}
out:
@@ -1304,6 +1309,7 @@ static void ep0stall(struct fsl_udc *udc)
tmp = fsl_readl(&dr_regs->endptctrl[0]);
tmp |= EPCTRL_TX_EP_STALL | EPCTRL_RX_EP_STALL;
fsl_writel(tmp, &dr_regs->endptctrl[0]);
+ udc->ep0_state = WAIT_FOR_SETUP;
udc->ep0_dir = 0;
}
@@ -1318,10 +1324,26 @@ static int ep0_prime_status(struct fsl_udc *udc, int direction)
udc->ep0_dir = USB_DIR_IN;
else
udc->ep0_dir = USB_DIR_OUT;
+
ep = &udc->eps[0];
+ udc->ep0_state = WAIT_FOR_OUT_STATUS;
+
req->ep = ep;
req->req.length = 0;
- status = fsl_ep_queue(&ep->ep, &req->req, GFP_ATOMIC);
+ req->req.status = -EINPROGRESS;
+ req->req.actual = 0;
+ req->req.complete = NULL;
+ req->dtd_count = 0;
+
+ if (fsl_req_to_dtd(req) == 0)
+ status = fsl_queue_td(ep, req);
+ else
+ return -ENOMEM;
+
+ if (status)
+ ERR("Can't queue ep0 status request \n");
+ list_add_tail(&req->queue, &ep->queue);
+
return status;
}
@@ -1387,20 +1409,29 @@ static void ch9getstatus(struct fsl_udc *udc, u8 request_type, u16 value,
}
udc->ep0_dir = USB_DIR_IN;
- /* Borrow the per device data_req */
- /* status_req had been used to prime status */
- req = udc->data_req;
+ /* Borrow the per device status_req */
+ req = udc->status_req;
/* Fill in the reqest structure */
*((u16 *) req->req.buf) = cpu_to_le16(tmp);
req->ep = ep;
req->req.length = 2;
+ req->req.status = -EINPROGRESS;
+ req->req.actual = 0;
+ req->req.complete = NULL;
+ req->dtd_count = 0;
+
+ /* prime the data phase */
+ if ((fsl_req_to_dtd(req) == 0))
+ status = fsl_queue_td(ep, req);
+ else /* no mem */
+ goto stall;
- status = fsl_ep_queue(&ep->ep, &req->req, GFP_ATOMIC);
if (status) {
- udc_reset_ep_queue(udc, 0);
ERR("Can't respond to getstatus request \n");
goto stall;
}
+ list_add_tail(&req->queue, &ep->queue);
+ udc->ep0_state = DATA_STATE_XMIT;
return;
stall:
ep0stall(udc);
@@ -1414,10 +1445,7 @@ static void setup_received_irq(struct fsl_udc *udc,
u16 wLength = le16_to_cpu(setup->wLength);
udc_reset_ep_queue(udc, 0);
- if (setup->bRequestType & USB_DIR_IN) {
- if (ep0_prime_status(udc, EP_DIR_OUT))
- ep0stall(udc);
- }
+
/* We process some stardard setup requests here */
switch (setup->bRequest) {
case USB_REQ_GET_STATUS:
@@ -1508,11 +1536,11 @@ static void setup_received_irq(struct fsl_udc *udc,
? USB_DIR_IN : USB_DIR_OUT;
spin_unlock(&udc->lock);
if (udc->driver->setup(&udc->gadget,
- &udc->local_setup_buff) < 0) {
- /* cancel status phase */
- udc_reset_ep_queue(udc, 0);
+ &udc->local_setup_buff) < 0)
ep0stall(udc);
- }
+ spin_lock(&udc->lock);
+ udc->ep0_state = (setup->bRequestType & USB_DIR_IN)
+ ? DATA_STATE_XMIT : DATA_STATE_RECV;
} else {
/* No data phase, IN status from gadget */
udc->ep0_dir = USB_DIR_IN;
@@ -1520,8 +1548,9 @@ static void setup_received_irq(struct fsl_udc *udc,
if (udc->driver->setup(&udc->gadget,
&udc->local_setup_buff) < 0)
ep0stall(udc);
+ spin_lock(&udc->lock);
+ udc->ep0_state = WAIT_FOR_OUT_STATUS;
}
- spin_lock(&udc->lock);
}
/* Process request for Data or Status phase of ep0
@@ -1535,7 +1564,30 @@ static void ep0_req_complete(struct fsl_udc *udc, struct fsl_ep *ep0,
fsl_writel(new_address << USB_DEVICE_ADDRESS_BIT_POS,
&dr_regs->deviceaddr);
}
+
done(ep0, req, 0);
+
+ switch (udc->ep0_state) {
+ case DATA_STATE_XMIT:
+ /* receive status phase */
+ if (ep0_prime_status(udc, EP_DIR_OUT))
+ ep0stall(udc);
+ break;
+ case DATA_STATE_RECV:
+ /* send status phase */
+ if (ep0_prime_status(udc, EP_DIR_IN))
+ ep0stall(udc);
+ break;
+ case WAIT_FOR_OUT_STATUS:
+ udc->ep0_state = WAIT_FOR_SETUP;
+ break;
+ case WAIT_FOR_SETUP:
+ ERR("Unexpect ep0 packets \n");
+ break;
+ default:
+ ep0stall(udc);
+ break;
+ }
}
/* Tripwire mechanism to ensure a setup packet payload is extracted without
@@ -1873,6 +1925,7 @@ static void reset_irq(struct fsl_udc *udc)
/* Clear usb state */
udc->resume_state = 0;
udc->ep0_dir = 0;
+ udc->ep0_state = WAIT_FOR_SETUP;
udc->remote_wakeup = 0; /* default to 0 on reset */
udc->gadget.b_hnp_enable = 0;
udc->gadget.a_hnp_support = 0;
@@ -2053,6 +2106,7 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver)
/* Enable DR IRQ reg and Set usbcmd reg Run bit */
dr_controller_run(udc_controller);
udc_controller->usb_state = USB_STATE_ATTACHED;
+ udc_controller->ep0_state = WAIT_FOR_SETUP;
udc_controller->ep0_dir = 0;
}
printk(KERN_INFO "%s: bind to driver %s \n",
@@ -2085,6 +2139,7 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
/* in fact, no needed */
udc_controller->usb_state = USB_STATE_ATTACHED;
+ udc_controller->ep0_state = WAIT_FOR_SETUP;
udc_controller->ep0_dir = 0;
/* stand operation */
@@ -2434,14 +2489,9 @@ static int __init struct_udc_setup(struct fsl_udc *udc,
/* FIXME: fsl_alloc_request() ignores ep argument */
udc->status_req = container_of(fsl_alloc_request(NULL, GFP_KERNEL),
struct fsl_req, req);
- /* for future use */
+ /* allocate a small amount of memory to get valid address */
udc->status_req->req.buf = kmalloc(8, GFP_KERNEL);
udc->status_req->req.dma = virt_to_phys(udc->status_req->req.buf);
- /* Initialize ep0 data request structure */
- udc->data_req = container_of(fsl_alloc_request(NULL, GFP_KERNEL),
- struct fsl_req, req);
- udc->data_req->req.buf = kmalloc(8, GFP_KERNEL);
- udc->data_req->req.dma = virt_to_phys(udc->data_req->req.buf);
udc->resume_state = USB_STATE_NOTATTACHED;
udc->usb_state = USB_STATE_POWERED;
@@ -2699,8 +2749,6 @@ static int __exit fsl_udc_remove(struct platform_device *pdev)
/* Free allocated memory */
kfree(udc_controller->status_req->req.buf);
kfree(udc_controller->status_req);
- kfree(udc_controller->data_req->req.buf);
- kfree(udc_controller->data_req);
kfree(udc_controller->eps);
dma_pool_destroy(udc_controller->td_pool);
@@ -2795,6 +2843,7 @@ static int fsl_udc_resume(struct platform_device *pdev)
dr_controller_run(udc_controller);
}
udc_controller->usb_state = USB_STATE_ATTACHED;
+ udc_controller->ep0_state = WAIT_FOR_SETUP;
udc_controller->ep0_dir = 0;
printk(KERN_INFO "USB Gadget resumed\n");
diff --git a/drivers/usb/gadget/arcotg_udc.h b/drivers/usb/gadget/arcotg_udc.h
index aa5e6e7..aa57bd8 100644
--- a/drivers/usb/gadget/arcotg_udc.h
+++ b/drivers/usb/gadget/arcotg_udc.h
@@ -560,7 +560,6 @@ struct fsl_udc {
struct ep_queue_head *ep_qh; /* Endpoints Queue-Head */
struct fsl_req *status_req; /* ep0 status request */
- struct fsl_req *data_req; /* ep0 data request */
struct dma_pool *td_pool; /* dma pool for DTD */
enum fsl_usb2_phy_modes phy_mode;
@@ -573,6 +572,7 @@ struct fsl_udc {
u32 resume_state; /* USB state to resume */
u32 usb_state; /* USB current state */
u32 usb_next_state; /* USB next state */
+ u32 ep0_state; /* Endpoint zero state */
u32 ep0_dir; /* Endpoint zero direction: can be
USB_DIR_IN or USB_DIR_OUT */
u32 usb_sof_count; /* SOF count */
diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c
index c4e62a6..d77ad4a 100644
--- a/drivers/usb/gadget/file_storage.c
+++ b/drivers/usb/gadget/file_storage.c
@@ -712,6 +712,8 @@ static void set_bulk_out_req_length(struct fsg_dev *fsg,
if (rem > 0)
length += fsg->bulk_out_maxpacket - rem;
bh->outreq->length = length;
+ if (bh->bulk_out_intended_length == 31)
+ bh->outreq->length = 31;
}
static struct fsg_dev *the_fsg;
--
1.6.0.4
More information about the kernel-team
mailing list