Skip to content

Commit

Permalink
usb: renesas_usbhs: divide data transfer functions
Browse files Browse the repository at this point in the history
DMAEngine will be supported to this driver in the future.
Then, both PIO and DMA data transfer method should be supported.
But, the transfer function can returns the result immediately
in PIO version, but it can't in DMA version.
This patch divides data transfer functions into top/bottom half
in preparation for DMAEngine support.

Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
  • Loading branch information
Kuninori Morimoto authored and Greg Kroah-Hartman committed Jun 7, 2011
1 parent e8d548d commit 4bd0481
Show file tree
Hide file tree
Showing 6 changed files with 150 additions and 60 deletions.
1 change: 0 additions & 1 deletion drivers/usb/renesas_usbhs/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ struct usbhs_priv;

#include "./mod.h"
#include "./pipe.h"
#include "./fifo.h"

/*
*
Expand Down
57 changes: 47 additions & 10 deletions drivers/usb/renesas_usbhs/fifo.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,20 @@
#include "./common.h"
#include "./pipe.h"

/*
* packet info function
*/
void usbhs_pkt_update(struct usbhs_pkt *pkt,
struct usbhs_pipe *pipe,
void *buf, int len)
{
pkt->pipe = pipe;
pkt->buf = buf;
pkt->length = len;
pkt->actual = 0;
pkt->maxp = 0;
}

/*
* FIFO ctrl
*/
Expand Down Expand Up @@ -93,13 +107,16 @@ int usbhs_fifo_prepare_write(struct usbhs_pipe *pipe)
return usbhsf_fifo_select(pipe, 1);
}

int usbhs_fifo_write(struct usbhs_pipe *pipe, u8 *buf, int len)
int usbhs_fifo_write(struct usbhs_pkt *pkt)
{
struct usbhs_pipe *pipe = pkt->pipe;
struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe);
struct usbhs_pipe_info *info = usbhs_priv_to_pipeinfo(priv);
void __iomem *addr = priv->base + CFIFO;
int maxp = usbhs_pipe_get_maxpacket(pipe);
int total_len;
int i, ret;
u8 *buf = pkt->buf;
int i, ret, len;

ret = usbhs_pipe_is_accessible(pipe);
if (ret < 0)
Expand All @@ -113,7 +130,7 @@ int usbhs_fifo_write(struct usbhs_pipe *pipe, u8 *buf, int len)
if (ret < 0)
return ret;

len = min(len, maxp);
len = min(pkt->length, maxp);
total_len = len;

/*
Expand All @@ -135,7 +152,16 @@ int usbhs_fifo_write(struct usbhs_pipe *pipe, u8 *buf, int len)
if (total_len < maxp)
usbhsf_send_terminator(pipe);

return total_len;
usbhs_pipe_enable(pipe);

/* update pkt */
if (info->tx_done) {
pkt->actual = total_len;
pkt->maxp = maxp;
info->tx_done(pkt);
}

return 0;
}

int usbhs_fifo_prepare_read(struct usbhs_pipe *pipe)
Expand All @@ -154,13 +180,16 @@ int usbhs_fifo_prepare_read(struct usbhs_pipe *pipe)
return ret;
}

int usbhs_fifo_read(struct usbhs_pipe *pipe, u8 *buf, int len)
int usbhs_fifo_read(struct usbhs_pkt *pkt)
{
struct usbhs_pipe *pipe = pkt->pipe;
struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe);
struct usbhs_pipe_info *info = usbhs_priv_to_pipeinfo(priv);
void __iomem *addr = priv->base + CFIFO;
int rcv_len;
u8 *buf = pkt->buf;
int rcv_len, len;
int i, ret;
int total_len;
int total_len = 0;
u32 data = 0;

ret = usbhsf_fifo_select(pipe, 0);
Expand All @@ -181,10 +210,10 @@ int usbhs_fifo_read(struct usbhs_pipe *pipe, u8 *buf, int len)
*/
if (0 == rcv_len) {
usbhsf_fifo_clear(pipe);
return 0;
goto usbhs_fifo_read_end;
}

len = min(rcv_len, len);
len = min(rcv_len, pkt->length);
total_len = len;

/*
Expand All @@ -207,5 +236,13 @@ int usbhs_fifo_read(struct usbhs_pipe *pipe, u8 *buf, int len)
buf[i] = (data >> ((i & 0x03) * 8)) & 0xff;
}

return total_len;
usbhs_fifo_read_end:
if (info->rx_done) {
/* update pkt */
pkt->actual = total_len;
pkt->maxp = usbhs_pipe_get_maxpacket(pipe);
info->rx_done(pkt);
}

return 0;
}
21 changes: 18 additions & 3 deletions drivers/usb/renesas_usbhs/fifo.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,29 @@
#ifndef RENESAS_USB_FIFO_H
#define RENESAS_USB_FIFO_H

#include "common.h"
#include "pipe.h"

struct usbhs_pkt {
struct usbhs_pipe *pipe;
int maxp;
void *buf;
int length;
int actual;
};

/*
* fifo
*/
int usbhs_fifo_write(struct usbhs_pipe *pipe, u8 *buf, int len);
int usbhs_fifo_read(struct usbhs_pipe *pipe, u8 *buf, int len);
int usbhs_fifo_write(struct usbhs_pkt *pkt);
int usbhs_fifo_read(struct usbhs_pkt *pkt);
int usbhs_fifo_prepare_write(struct usbhs_pipe *pipe);
int usbhs_fifo_prepare_read(struct usbhs_pipe *pipe);

/*
* packet info
*/
void usbhs_pkt_update(struct usbhs_pkt *pkt,
struct usbhs_pipe *pipe,
void *buf, int len);

#endif /* RENESAS_USB_FIFO_H */
115 changes: 72 additions & 43 deletions drivers/usb/renesas_usbhs/mod_gadget.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
struct usbhsg_request {
struct usb_request req;
struct list_head node;
struct usbhs_pkt pkt;
};

#define EP_NAME_SIZE 8
Expand Down Expand Up @@ -110,6 +111,10 @@ struct usbhsg_recip_handle {
#define usbhsg_pipe_to_uep(p) ((p)->mod_private)
#define usbhsg_is_dcp(u) ((u) == usbhsg_gpriv_to_dcp((u)->gpriv))

#define usbhsg_ureq_to_pkt(u) (&(u)->pkt)
#define usbhsg_pkt_to_ureq(i) \
container_of(i, struct usbhsg_request, pkt)

#define usbhsg_is_not_connected(gp) ((gp)->gadget.speed == USB_SPEED_UNKNOWN)

/* status */
Expand Down Expand Up @@ -319,38 +324,32 @@ static int usbhsg_try_run_ctrl_stage_end(struct usbhsg_uep *uep,
return 0;
}

static int usbhsg_try_run_send_packet(struct usbhsg_uep *uep,
struct usbhsg_request *ureq)
/*
* packet send hander
*/
static void usbhsg_try_run_send_packet_bh(struct usbhs_pkt *pkt)
{
struct usbhs_pipe *pipe = usbhsg_uep_to_pipe(uep);
struct usbhs_pipe *pipe = pkt->pipe;
struct usbhsg_uep *uep = usbhsg_pipe_to_uep(pipe);
struct usbhsg_request *ureq = usbhsg_pkt_to_ureq(pkt);
struct usb_request *req = &ureq->req;
struct usbhsg_gpriv *gpriv = usbhsg_uep_to_gpriv(uep);
struct device *dev = usbhsg_gpriv_to_dev(gpriv);
void *buf;
int remainder, send;
int remainder, send, maxp;
int is_done = 0;
int enable;
int maxp;

/*
********* assume under spin lock *********
*/

maxp = usbhs_pipe_get_maxpacket(pipe);
buf = req->buf + req->actual;
remainder = req->length - req->actual;

send = usbhs_fifo_write(pipe, buf, remainder);
maxp = pkt->maxp;
send = pkt->actual;
remainder = pkt->length;

/*
* send < 0 : pipe busy
* send = 0 : send zero packet
* send > 0 : send data
*
* send <= max_packet
*/
if (send > 0)
req->actual += send;
req->actual += send;

/* send all packet ? */
if (send < remainder)
Expand All @@ -371,13 +370,6 @@ static int usbhsg_try_run_send_packet(struct usbhsg_uep *uep,
enable = !is_done;
uep->handler->irq_mask(uep, enable);

/*
* usbhs_fifo_enable execute
* - after callback_update,
* - before queue_pop / stage_end
*/
usbhs_pipe_enable(pipe);

/*
* all data were sent ?
*/
Expand All @@ -389,6 +381,30 @@ static int usbhsg_try_run_send_packet(struct usbhsg_uep *uep,

usbhsg_queue_pop(uep, ureq, 0);
}
}

static int usbhsg_try_run_send_packet(struct usbhsg_uep *uep,
struct usbhsg_request *ureq)
{
struct usbhs_pipe *pipe = usbhsg_uep_to_pipe(uep);
struct usb_request *req = &ureq->req;
struct usbhs_pkt *pkt = usbhsg_ureq_to_pkt(ureq);
int ret;

/*
********* assume under spin lock *********
*/

usbhs_pkt_update(pkt, pipe,
req->buf + req->actual,
req->length - req->actual);

ret = usbhs_fifo_write(pkt);
if (ret < 0) {
/* pipe is busy.
* retry in interrupt */
uep->handler->irq_mask(uep, 1);
}

return 0;
}
Expand All @@ -408,35 +424,30 @@ static int usbhsg_prepare_send_packet(struct usbhsg_uep *uep,
return 0;
}

static int usbhsg_try_run_receive_packet(struct usbhsg_uep *uep,
struct usbhsg_request *ureq)
/*
* packet recv hander
*/
static void usbhsg_try_run_receive_packet_bh(struct usbhs_pkt *pkt)
{
struct usbhs_pipe *pipe = usbhsg_uep_to_pipe(uep);
struct usbhs_pipe *pipe = pkt->pipe;
struct usbhsg_uep *uep = usbhsg_pipe_to_uep(pipe);
struct usbhsg_request *ureq = usbhsg_pkt_to_ureq(pkt);
struct usb_request *req = &ureq->req;
struct usbhsg_gpriv *gpriv = usbhsg_uep_to_gpriv(uep);
struct device *dev = usbhsg_gpriv_to_dev(gpriv);
void *buf;
int maxp;
int remainder, recv;
int remainder, recv, maxp;
int is_done = 0;

/*
********* assume under spin lock *********
*/

maxp = usbhs_pipe_get_maxpacket(pipe);
buf = req->buf + req->actual;
remainder = req->length - req->actual;
maxp = pkt->maxp;
remainder = pkt->length;
recv = pkt->actual;

recv = usbhs_fifo_read(pipe, buf, remainder);
/*
* recv < 0 : pipe busy
* recv >= 0 : receive data
*
* recv <= max_packet
*/
if (recv < 0)
return -EBUSY;

/* update parameters */
req->actual += recv;
Expand All @@ -457,8 +468,24 @@ static int usbhsg_try_run_receive_packet(struct usbhsg_uep *uep,
usbhs_pipe_disable(pipe);
usbhsg_queue_pop(uep, ureq, 0);
}
}

return 0;
static int usbhsg_try_run_receive_packet(struct usbhsg_uep *uep,
struct usbhsg_request *ureq)
{
struct usbhs_pipe *pipe = usbhsg_uep_to_pipe(uep);
struct usb_request *req = &ureq->req;
struct usbhs_pkt *pkt = usbhsg_ureq_to_pkt(ureq);

/*
********* assume under spin lock *********
*/

usbhs_pkt_update(pkt, pipe,
req->buf + req->actual,
req->length - req->actual);

return usbhs_fifo_read(pkt);
}

static int usbhsg_prepare_receive_packet(struct usbhsg_uep *uep,
Expand Down Expand Up @@ -1086,7 +1113,9 @@ static int usbhsg_try_start(struct usbhs_priv *priv, u32 status)
/*
* pipe initialize and enable DCP
*/
usbhs_pipe_init(priv);
usbhs_pipe_init(priv,
usbhsg_try_run_send_packet_bh,
usbhsg_try_run_receive_packet_bh);
usbhsg_uep_init(gpriv);
usbhsg_dcp_enable(dcp);

Expand Down
8 changes: 6 additions & 2 deletions drivers/usb/renesas_usbhs/pipe.c
Original file line number Diff line number Diff line change
Expand Up @@ -531,7 +531,9 @@ static struct usbhs_pipe *usbhsp_get_pipe(struct usbhs_priv *priv, u32 type)
return pipe;
}

void usbhs_pipe_init(struct usbhs_priv *priv)
void usbhs_pipe_init(struct usbhs_priv *priv,
void (*tx_done)(struct usbhs_pkt *pkt),
void (*rx_done)(struct usbhs_pkt *pkt))
{
struct usbhs_pipe_info *info = usbhs_priv_to_pipeinfo(priv);
struct usbhs_pipe *pipe;
Expand Down Expand Up @@ -561,6 +563,9 @@ void usbhs_pipe_init(struct usbhs_priv *priv)
usbhsp_pipectrl_set(pipe, ACLRM, ACLRM);
usbhsp_pipectrl_set(pipe, ACLRM, 0);
}

info->tx_done = tx_done;
info->rx_done = rx_done;
}

struct usbhs_pipe *usbhs_pipe_malloc(struct usbhs_priv *priv,
Expand Down Expand Up @@ -639,7 +644,6 @@ void usbhs_dcp_control_transfer_done(struct usbhs_pipe *pipe)
usbhsp_pipectrl_set(pipe, CCPL, CCPL);
}


/*
* pipe module function
*/
Expand Down
Loading

0 comments on commit 4bd0481

Please sign in to comment.