usb: renesas_usbhs: divide data transfer functions
authorKuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Mon, 6 Jun 2011 05:18:07 +0000 (14:18 +0900)
committerGreg Kroah-Hartman <gregkh@suse.de>
Tue, 7 Jun 2011 16:10:07 +0000 (09:10 -0700)
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>
drivers/usb/renesas_usbhs/common.h
drivers/usb/renesas_usbhs/fifo.c
drivers/usb/renesas_usbhs/fifo.h
drivers/usb/renesas_usbhs/mod_gadget.c
drivers/usb/renesas_usbhs/pipe.c
drivers/usb/renesas_usbhs/pipe.h

index 24f756024bed83d3cf44ed63b80fdd154270096e..0aadcb4027648a45455b633e21c9de9b78203fe4 100644 (file)
@@ -24,7 +24,6 @@ struct usbhs_priv;
 
 #include "./mod.h"
 #include "./pipe.h"
-#include "./fifo.h"
 
 /*
  *
index 3fd3adf90541bf457ef00cbb4b5f5d15b9874240..098388489813c9a10d3766854af69a922d5e0200 100644 (file)
 #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
  */
@@ -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)
@@ -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;
 
        /*
@@ -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)
@@ -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);
@@ -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;
 
        /*
@@ -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;
 }
index 75a7c1577ad3f34f7101688771fccd3abc74af78..758d85dd31ddba3a7af1616272841ed2ae52a5ce 100644 (file)
 #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 */
index 128c8da8db851a9066e0ea5e4f7a6af9b3c94bc3..4a1d1fcc90fd3cdd6136ecc002acdba3ee80203f 100644 (file)
@@ -27,6 +27,7 @@
 struct usbhsg_request {
        struct usb_request      req;
        struct list_head        node;
+       struct usbhs_pkt        pkt;
 };
 
 #define EP_NAME_SIZE 8
@@ -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 */
@@ -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)
@@ -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 ?
         */
@@ -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;
 }
@@ -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;
@@ -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,
@@ -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);
 
index 75e9e3cbc0e54f65ad3ec2dd98b1839eaffd0f60..7a11616d6e28cf88591be164894b7c1d650c8264 100644 (file)
@@ -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;
@@ -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,
@@ -639,7 +644,6 @@ void usbhs_dcp_control_transfer_done(struct usbhs_pipe *pipe)
        usbhsp_pipectrl_set(pipe, CCPL, CCPL);
 }
 
-
 /*
  *             pipe module function
  */
index 2fb69df932ed65131587937fda54cda50f12895b..1f871b0c4971e1c803512b9ad0d665ba488b5258 100644 (file)
@@ -18,6 +18,7 @@
 #define RENESAS_USB_PIPE_H
 
 #include "./common.h"
+#include "./fifo.h"
 
 /*
  *     struct
@@ -39,6 +40,9 @@ struct usbhs_pipe_info {
        struct usbhs_pipe *pipe;
        int size;       /* array size of "pipe" */
        int bufnmb_last;        /* FIXME : driver needs good allocator */
+
+       void (*tx_done)(struct usbhs_pkt *pkt);
+       void (*rx_done)(struct usbhs_pkt *pkt);
 };
 
 /*
@@ -76,7 +80,9 @@ int usbhs_pipe_probe(struct usbhs_priv *priv);
 void usbhs_pipe_remove(struct usbhs_priv *priv);
 int usbhs_pipe_is_dir_in(struct usbhs_pipe *pipe);
 int usbhs_pipe_is_dir_host(struct usbhs_pipe *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));
 int usbhs_pipe_get_maxpacket(struct usbhs_pipe *pipe);
 void usbhs_pipe_clear_sequence(struct usbhs_pipe *pipe);
 int usbhs_pipe_is_accessible(struct usbhs_pipe *pipe);