Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 325979
b: refs/heads/master
c: 8e8a551
h: refs/heads/master
i:
  325977: e04c999
  325975: a937cd4
v: v3
  • Loading branch information
Virupax Sadashivpetimath authored and Felipe Balbi committed Aug 7, 2012
1 parent 12636b7 commit 8a2805e
Show file tree
Hide file tree
Showing 3 changed files with 97 additions and 6 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: decadacbd7259b1dce0aeb9cb4468432edf88fb4
refs/heads/master: 8e8a55165469c99af0c24a276d997f9473dc89ab
98 changes: 93 additions & 5 deletions trunk/drivers/usb/musb/musb_host.c
Original file line number Diff line number Diff line change
Expand Up @@ -823,9 +823,28 @@ static void musb_ep_program(struct musb *musb, u8 epnum,
if (load_count) {
/* PIO to load FIFO */
qh->segsize = load_count;
musb_write_fifo(hw_ep, load_count, buf);
if (!buf) {
sg_miter_start(&qh->sg_miter, urb->sg, 1,
SG_MITER_ATOMIC
| SG_MITER_FROM_SG);
if (!sg_miter_next(&qh->sg_miter)) {
dev_err(musb->controller,
"error: sg"
"list empty\n");
sg_miter_stop(&qh->sg_miter);
goto finish;
}
buf = qh->sg_miter.addr + urb->sg->offset +
urb->actual_length;
load_count = min_t(u32, load_count,
qh->sg_miter.length);
musb_write_fifo(hw_ep, load_count, buf);
qh->sg_miter.consumed = load_count;
sg_miter_stop(&qh->sg_miter);
} else
musb_write_fifo(hw_ep, load_count, buf);
}

finish:
/* re-enable interrupt */
musb_writew(mbase, MUSB_INTRTXE, int_txe);

Expand Down Expand Up @@ -1193,6 +1212,7 @@ void musb_host_tx(struct musb *musb, u8 epnum)
void __iomem *mbase = musb->mregs;
struct dma_channel *dma;
bool transfer_pending = false;
static bool use_sg;

musb_ep_select(mbase, epnum);
tx_csr = musb_readw(epio, MUSB_TXCSR);
Expand Down Expand Up @@ -1247,6 +1267,7 @@ void musb_host_tx(struct musb *musb, u8 epnum)
return;
}

done:
if (status) {
if (dma_channel_status(dma) == MUSB_DMA_STATUS_BUSY) {
dma->status = MUSB_DMA_STATUS_CORE_ABORT;
Expand Down Expand Up @@ -1416,9 +1437,38 @@ void musb_host_tx(struct musb *musb, u8 epnum)
length = qh->maxpacket;
/* Unmap the buffer so that CPU can use it */
usb_hcd_unmap_urb_for_dma(musb_to_hcd(musb), urb);
musb_write_fifo(hw_ep, length, urb->transfer_buffer + offset);

/*
* We need to map sg if the transfer_buffer is
* NULL.
*/
if (!urb->transfer_buffer)
use_sg = true;

if (use_sg) {
/* sg_miter_start is already done in musb_ep_program */
if (!sg_miter_next(&qh->sg_miter)) {
dev_err(musb->controller, "error: sg list empty\n");
sg_miter_stop(&qh->sg_miter);
status = -EINVAL;
goto done;
}
urb->transfer_buffer = qh->sg_miter.addr;
length = min_t(u32, length, qh->sg_miter.length);
musb_write_fifo(hw_ep, length, urb->transfer_buffer);
qh->sg_miter.consumed = length;
sg_miter_stop(&qh->sg_miter);
} else {
musb_write_fifo(hw_ep, length, urb->transfer_buffer + offset);
}

qh->segsize = length;

if (use_sg) {
if (offset + length >= urb->transfer_buffer_length)
use_sg = false;
}

musb_ep_select(mbase, epnum);
musb_writew(epio, MUSB_TXCSR,
MUSB_TXCSR_H_WZC_BITS | MUSB_TXCSR_TXPKTRDY);
Expand Down Expand Up @@ -1482,6 +1532,8 @@ void musb_host_rx(struct musb *musb, u8 epnum)
bool done = false;
u32 status;
struct dma_channel *dma;
static bool use_sg;
unsigned int sg_flags = SG_MITER_ATOMIC | SG_MITER_TO_SG;

musb_ep_select(mbase, epnum);

Expand Down Expand Up @@ -1796,10 +1848,43 @@ void musb_host_rx(struct musb *musb, u8 epnum)
#endif /* Mentor DMA */

if (!dma) {
unsigned int received_len;

/* Unmap the buffer so that CPU can use it */
usb_hcd_unmap_urb_for_dma(musb_to_hcd(musb), urb);
done = musb_host_packet_rx(musb, urb,
epnum, iso_err);

/*
* We need to map sg if the transfer_buffer is
* NULL.
*/
if (!urb->transfer_buffer) {
use_sg = true;
sg_miter_start(&qh->sg_miter, urb->sg, 1,
sg_flags);
}

if (use_sg) {
if (!sg_miter_next(&qh->sg_miter)) {
dev_err(musb->controller, "error: sg list empty\n");
sg_miter_stop(&qh->sg_miter);
status = -EINVAL;
done = true;
goto finish;
}
urb->transfer_buffer = qh->sg_miter.addr;
received_len = urb->actual_length;
qh->offset = 0x0;
done = musb_host_packet_rx(musb, urb, epnum,
iso_err);
/* Calculate the number of bytes received */
received_len = urb->actual_length -
received_len;
qh->sg_miter.consumed = received_len;
sg_miter_stop(&qh->sg_miter);
} else {
done = musb_host_packet_rx(musb, urb,
epnum, iso_err);
}
dev_dbg(musb->controller, "read %spacket\n", done ? "last " : "");
}
}
Expand All @@ -1808,6 +1893,9 @@ void musb_host_rx(struct musb *musb, u8 epnum)
urb->actual_length += xfer_len;
qh->offset += xfer_len;
if (done) {
if (use_sg)
use_sg = false;

if (urb->status == -EINPROGRESS)
urb->status = status;
musb_advance_schedule(musb, urb, hw_ep, USB_DIR_IN);
Expand Down
3 changes: 3 additions & 0 deletions trunk/drivers/usb/musb/musb_host.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@
#ifndef _MUSB_HOST_H
#define _MUSB_HOST_H

#include <linux/scatterlist.h>

static inline struct usb_hcd *musb_to_hcd(struct musb *musb)
{
return container_of((void *) musb, struct usb_hcd, hcd_priv);
Expand Down Expand Up @@ -71,6 +73,7 @@ struct musb_qh {
u16 maxpacket;
u16 frame; /* for periodic schedule */
unsigned iso_idx; /* in urb->iso_frame_desc[] */
struct sg_mapping_iter sg_miter; /* for highmem in PIO mode */
};

/* map from control or bulk queue head to the first qh on that ring */
Expand Down

0 comments on commit 8a2805e

Please sign in to comment.