Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 232628
b: refs/heads/master
c: abab0c6
h: refs/heads/master
v: v3
  • Loading branch information
Toshiharu Okada authored and Greg Kroah-Hartman committed Jan 23, 2011
1 parent f68ba54 commit 2118486
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 51 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 956227120f2e8eed8ca459879d7eafee78591cc1
refs/heads/master: abab0c67c061612cf559ab27ce1340774d7c292d
117 changes: 67 additions & 50 deletions trunk/drivers/usb/gadget/pch_udc.c
Original file line number Diff line number Diff line change
Expand Up @@ -198,10 +198,10 @@
#define PCH_UDC_BRLEN 0x0F /* Burst length */
#define PCH_UDC_THLEN 0x1F /* Threshold length */
/* Value of EP Buffer Size */
#define UDC_EP0IN_BUFF_SIZE 64
#define UDC_EPIN_BUFF_SIZE 512
#define UDC_EP0OUT_BUFF_SIZE 64
#define UDC_EPOUT_BUFF_SIZE 512
#define UDC_EP0IN_BUFF_SIZE 16
#define UDC_EPIN_BUFF_SIZE 256
#define UDC_EP0OUT_BUFF_SIZE 16
#define UDC_EPOUT_BUFF_SIZE 256
/* Value of EP maximum packet size */
#define UDC_EP0IN_MAX_PKT_SIZE 64
#define UDC_EP0OUT_MAX_PKT_SIZE 64
Expand Down Expand Up @@ -351,7 +351,7 @@ struct pch_udc_dev {
struct pci_pool *data_requests;
struct pci_pool *stp_requests;
dma_addr_t dma_addr;
unsigned long ep0out_buf[64];
void *ep0out_buf;
struct usb_ctrlrequest setup_data;
unsigned long phys_addr;
void __iomem *base_addr;
Expand Down Expand Up @@ -1219,11 +1219,11 @@ static void complete_req(struct pch_udc_ep *ep, struct pch_udc_request *req,
dev = ep->dev;
if (req->dma_mapped) {
if (ep->in)
pci_unmap_single(dev->pdev, req->req.dma,
req->req.length, PCI_DMA_TODEVICE);
dma_unmap_single(&dev->pdev->dev, req->req.dma,
req->req.length, DMA_TO_DEVICE);
else
pci_unmap_single(dev->pdev, req->req.dma,
req->req.length, PCI_DMA_FROMDEVICE);
dma_unmap_single(&dev->pdev->dev, req->req.dma,
req->req.length, DMA_FROM_DEVICE);
req->dma_mapped = 0;
req->req.dma = DMA_ADDR_INVALID;
}
Expand Down Expand Up @@ -1414,7 +1414,6 @@ static void pch_udc_start_rxrequest(struct pch_udc_ep *ep,

pch_udc_clear_dma(ep->dev, DMA_DIR_RX);
td_data = req->td_data;
ep->td_data = req->td_data;
/* Set the status bits for all descriptors */
while (1) {
td_data->status = (td_data->status & ~PCH_UDC_BUFF_STS) |
Expand Down Expand Up @@ -1613,15 +1612,19 @@ static int pch_udc_pcd_queue(struct usb_ep *usbep, struct usb_request *usbreq,
if (usbreq->length &&
((usbreq->dma == DMA_ADDR_INVALID) || !usbreq->dma)) {
if (ep->in)
usbreq->dma = pci_map_single(dev->pdev, usbreq->buf,
usbreq->length, PCI_DMA_TODEVICE);
usbreq->dma = dma_map_single(&dev->pdev->dev,
usbreq->buf,
usbreq->length,
DMA_TO_DEVICE);
else
usbreq->dma = pci_map_single(dev->pdev, usbreq->buf,
usbreq->length, PCI_DMA_FROMDEVICE);
usbreq->dma = dma_map_single(&dev->pdev->dev,
usbreq->buf,
usbreq->length,
DMA_FROM_DEVICE);
req->dma_mapped = 1;
}
if (usbreq->length > 0) {
retval = prepare_dma(ep, req, gfp);
retval = prepare_dma(ep, req, GFP_ATOMIC);
if (retval)
goto probe_end;
}
Expand All @@ -1646,7 +1649,6 @@ static int pch_udc_pcd_queue(struct usb_ep *usbep, struct usb_request *usbreq,
pch_udc_wait_ep_stall(ep);
pch_udc_ep_clear_nak(ep);
pch_udc_enable_ep_interrupts(ep->dev, (1 << ep->num));
pch_udc_set_dma(dev, DMA_DIR_TX);
}
}
/* Now add this request to the ep's pending requests */
Expand Down Expand Up @@ -1926,6 +1928,7 @@ static void pch_udc_complete_receiver(struct pch_udc_ep *ep)
PCH_UDC_BS_DMA_DONE)
return;
pch_udc_clear_dma(ep->dev, DMA_DIR_RX);
pch_udc_ep_set_ddptr(ep, 0);
if ((req->td_data_last->status & PCH_UDC_RXTX_STS) !=
PCH_UDC_RTS_SUCC) {
dev_err(&dev->pdev->dev, "Invalid RXTX status (0x%08x) "
Expand Down Expand Up @@ -1963,7 +1966,7 @@ static void pch_udc_svc_data_in(struct pch_udc_dev *dev, int ep_num)
u32 epsts;
struct pch_udc_ep *ep;

ep = &dev->ep[2*ep_num];
ep = &dev->ep[UDC_EPIN_IDX(ep_num)];
epsts = ep->epsts;
ep->epsts = 0;

Expand Down Expand Up @@ -2008,7 +2011,7 @@ static void pch_udc_svc_data_out(struct pch_udc_dev *dev, int ep_num)
struct pch_udc_ep *ep;
struct pch_udc_request *req = NULL;

ep = &dev->ep[2*ep_num + 1];
ep = &dev->ep[UDC_EPOUT_IDX(ep_num)];
epsts = ep->epsts;
ep->epsts = 0;

Expand All @@ -2025,10 +2028,11 @@ static void pch_udc_svc_data_out(struct pch_udc_dev *dev, int ep_num)
}
if (epsts & UDC_EPSTS_HE)
return;
if (epsts & UDC_EPSTS_RSS)
if (epsts & UDC_EPSTS_RSS) {
pch_udc_ep_set_stall(ep);
pch_udc_enable_ep_interrupts(ep->dev,
PCH_UDC_EPINT(ep->in, ep->num));
}
if (epsts & UDC_EPSTS_RCS) {
if (!dev->prot_stall) {
pch_udc_ep_clear_stall(ep);
Expand Down Expand Up @@ -2060,8 +2064,10 @@ static void pch_udc_svc_control_in(struct pch_udc_dev *dev)
{
u32 epsts;
struct pch_udc_ep *ep;
struct pch_udc_ep *ep_out;

ep = &dev->ep[UDC_EP0IN_IDX];
ep_out = &dev->ep[UDC_EP0OUT_IDX];
epsts = ep->epsts;
ep->epsts = 0;

Expand All @@ -2073,8 +2079,16 @@ static void pch_udc_svc_control_in(struct pch_udc_dev *dev)
return;
if (epsts & UDC_EPSTS_HE)
return;
if ((epsts & UDC_EPSTS_TDC) && (!dev->stall))
if ((epsts & UDC_EPSTS_TDC) && (!dev->stall)) {
pch_udc_complete_transfer(ep);
pch_udc_clear_dma(dev, DMA_DIR_RX);
ep_out->td_data->status = (ep_out->td_data->status &
~PCH_UDC_BUFF_STS) |
PCH_UDC_BS_HST_RDY;
pch_udc_ep_clear_nak(ep_out);
pch_udc_set_dma(dev, DMA_DIR_RX);
pch_udc_ep_set_rrdy(ep_out);
}
/* On IN interrupt, provide data if we have any */
if ((epsts & UDC_EPSTS_IN) && !(epsts & UDC_EPSTS_TDC) &&
!(epsts & UDC_EPSTS_TXEMPTY))
Expand Down Expand Up @@ -2102,11 +2116,9 @@ static void pch_udc_svc_control_out(struct pch_udc_dev *dev)
dev->stall = 0;
dev->ep[UDC_EP0IN_IDX].halted = 0;
dev->ep[UDC_EP0OUT_IDX].halted = 0;
/* In data not ready */
pch_udc_ep_set_nak(&(dev->ep[UDC_EP0IN_IDX]));
dev->setup_data = ep->td_stp->request;
pch_udc_init_setup_buff(ep->td_stp);
pch_udc_clear_dma(dev, DMA_DIR_TX);
pch_udc_clear_dma(dev, DMA_DIR_RX);
pch_udc_ep_fifo_flush(&(dev->ep[UDC_EP0IN_IDX]),
dev->ep[UDC_EP0IN_IDX].in);
if ((dev->setup_data.bRequestType & USB_DIR_IN))
Expand All @@ -2122,14 +2134,23 @@ static void pch_udc_svc_control_out(struct pch_udc_dev *dev)
setup_supported = dev->driver->setup(&dev->gadget,
&dev->setup_data);
spin_lock(&dev->lock);

if (dev->setup_data.bRequestType & USB_DIR_IN) {
ep->td_data->status = (ep->td_data->status &
~PCH_UDC_BUFF_STS) |
PCH_UDC_BS_HST_RDY;
pch_udc_ep_set_ddptr(ep, ep->td_data_phys);
}
/* ep0 in returns data on IN phase */
if (setup_supported >= 0 && setup_supported <
UDC_EP0IN_MAX_PKT_SIZE) {
pch_udc_ep_clear_nak(&(dev->ep[UDC_EP0IN_IDX]));
/* Gadget would have queued a request when
* we called the setup */
pch_udc_set_dma(dev, DMA_DIR_RX);
pch_udc_ep_clear_nak(ep);
if (!(dev->setup_data.bRequestType & USB_DIR_IN)) {
pch_udc_set_dma(dev, DMA_DIR_RX);
pch_udc_ep_clear_nak(ep);
}
} else if (setup_supported < 0) {
/* if unsupported request, then stall */
pch_udc_ep_set_stall(&(dev->ep[UDC_EP0IN_IDX]));
Expand All @@ -2142,22 +2163,13 @@ static void pch_udc_svc_control_out(struct pch_udc_dev *dev)
}
} else if ((((stat & UDC_EPSTS_OUT_MASK) >> UDC_EPSTS_OUT_SHIFT) ==
UDC_EPSTS_OUT_DATA) && !dev->stall) {
if (list_empty(&ep->queue)) {
dev_err(&dev->pdev->dev, "%s: No request\n", __func__);
ep->td_data->status = (ep->td_data->status &
~PCH_UDC_BUFF_STS) |
PCH_UDC_BS_HST_RDY;
pch_udc_set_dma(dev, DMA_DIR_RX);
} else {
/* control write */
/* next function will pickuo an clear the status */
pch_udc_clear_dma(dev, DMA_DIR_RX);
pch_udc_ep_set_ddptr(ep, 0);
if (!list_empty(&ep->queue)) {
ep->epsts = stat;

pch_udc_svc_data_out(dev, 0);
/* re-program desc. pointer for possible ZLPs */
pch_udc_ep_set_ddptr(ep, ep->td_data_phys);
pch_udc_set_dma(dev, DMA_DIR_RX);
pch_udc_svc_data_out(dev, PCH_UDC_EP0);
}
pch_udc_set_dma(dev, DMA_DIR_RX);
}
pch_udc_ep_set_rrdy(ep);
}
Expand All @@ -2174,7 +2186,7 @@ static void pch_udc_postsvc_epinters(struct pch_udc_dev *dev, int ep_num)
struct pch_udc_ep *ep;
struct pch_udc_request *req;

ep = &dev->ep[2*ep_num];
ep = &dev->ep[UDC_EPIN_IDX(ep_num)];
if (!list_empty(&ep->queue)) {
req = list_entry(ep->queue.next, struct pch_udc_request, queue);
pch_udc_enable_ep_interrupts(ep->dev,
Expand All @@ -2196,13 +2208,13 @@ static void pch_udc_read_all_epstatus(struct pch_udc_dev *dev, u32 ep_intr)
for (i = 0; i < PCH_UDC_USED_EP_NUM; i++) {
/* IN */
if (ep_intr & (0x1 << i)) {
ep = &dev->ep[2*i];
ep = &dev->ep[UDC_EPIN_IDX(i)];
ep->epsts = pch_udc_read_ep_status(ep);
pch_udc_clear_ep_status(ep, ep->epsts);
}
/* OUT */
if (ep_intr & (0x10000 << i)) {
ep = &dev->ep[2*i+1];
ep = &dev->ep[UDC_EPOUT_IDX(i)];
ep->epsts = pch_udc_read_ep_status(ep);
pch_udc_clear_ep_status(ep, ep->epsts);
}
Expand Down Expand Up @@ -2563,9 +2575,6 @@ static void pch_udc_pcd_reinit(struct pch_udc_dev *dev)
dev->ep[UDC_EP0IN_IDX].ep.maxpacket = UDC_EP0IN_MAX_PKT_SIZE;
dev->ep[UDC_EP0OUT_IDX].ep.maxpacket = UDC_EP0OUT_MAX_PKT_SIZE;

dev->dma_addr = pci_map_single(dev->pdev, dev->ep0out_buf, 256,
PCI_DMA_FROMDEVICE);

/* remove ep0 in and out from the list. They have own pointer */
list_del_init(&dev->ep[UDC_EP0IN_IDX].ep.ep_list);
list_del_init(&dev->ep[UDC_EP0OUT_IDX].ep.ep_list);
Expand Down Expand Up @@ -2637,6 +2646,13 @@ static int init_dma_pools(struct pch_udc_dev *dev)
dev->ep[UDC_EP0IN_IDX].td_stp_phys = 0;
dev->ep[UDC_EP0IN_IDX].td_data = NULL;
dev->ep[UDC_EP0IN_IDX].td_data_phys = 0;

dev->ep0out_buf = kzalloc(UDC_EP0OUT_BUFF_SIZE * 4, GFP_KERNEL);
if (!dev->ep0out_buf)
return -ENOMEM;
dev->dma_addr = dma_map_single(&dev->pdev->dev, dev->ep0out_buf,
UDC_EP0OUT_BUFF_SIZE * 4,
DMA_FROM_DEVICE);
return 0;
}

Expand Down Expand Up @@ -2750,6 +2766,11 @@ static void pch_udc_remove(struct pci_dev *pdev)
pci_pool_destroy(dev->stp_requests);
}

if (dev->dma_addr)
dma_unmap_single(&dev->pdev->dev, dev->dma_addr,
UDC_EP0OUT_BUFF_SIZE * 4, DMA_FROM_DEVICE);
kfree(dev->ep0out_buf);

pch_udc_exit(dev);

if (dev->irq_registered)
Expand Down Expand Up @@ -2792,11 +2813,7 @@ static int pch_udc_resume(struct pci_dev *pdev)
int ret;

pci_set_power_state(pdev, PCI_D0);
ret = pci_restore_state(pdev);
if (ret) {
dev_err(&pdev->dev, "%s: pci_restore_state failed\n", __func__);
return ret;
}
pci_restore_state(pdev);
ret = pci_enable_device(pdev);
if (ret) {
dev_err(&pdev->dev, "%s: pci_enable_device failed\n", __func__);
Expand Down

0 comments on commit 2118486

Please sign in to comment.