X-Git-Url: https://git.openpandora.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;ds=sidebyside;f=drivers%2Fusb%2Frenesas_usbhs%2Fmod_gadget.c;h=a3818773dec113c9cd3f3d0ff6a636c363e0d7e2;hb=6acb95d4e0709a582023e87f9b3537fb4d837fd0;hp=206cfabc92863e0d409e8c76a32bf3129883eeda;hpb=434d42cfd05a7cc452457a81d2029540cba12150;p=pandora-kernel.git diff --git a/drivers/usb/renesas_usbhs/mod_gadget.c b/drivers/usb/renesas_usbhs/mod_gadget.c index 206cfabc9286..a3818773dec1 100644 --- a/drivers/usb/renesas_usbhs/mod_gadget.c +++ b/drivers/usb/renesas_usbhs/mod_gadget.c @@ -26,7 +26,7 @@ */ struct usbhsg_request { struct usb_request req; - struct list_head node; + struct usbhs_pkt pkt; }; #define EP_NAME_SIZE 8 @@ -35,7 +35,6 @@ struct usbhsg_pipe_handle; struct usbhsg_uep { struct usb_ep ep; struct usbhs_pipe *pipe; - struct list_head list; char ep_name[EP_NAME_SIZE]; @@ -110,6 +109,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 */ @@ -156,12 +159,12 @@ static void usbhsg_queue_push(struct usbhsg_uep *uep, struct usbhsg_gpriv *gpriv = usbhsg_uep_to_gpriv(uep); struct device *dev = usbhsg_gpriv_to_dev(gpriv); struct usbhs_pipe *pipe = usbhsg_uep_to_pipe(uep); + struct usbhs_pkt *pkt = usbhsg_ureq_to_pkt(ureq); /* ********* assume under spin lock ********* */ - list_del_init(&ureq->node); - list_add_tail(&ureq->node, &uep->list); + usbhs_pkt_push(pipe, pkt); ureq->req.actual = 0; ureq->req.status = -EINPROGRESS; @@ -172,13 +175,16 @@ static void usbhsg_queue_push(struct usbhsg_uep *uep, static struct usbhsg_request *usbhsg_queue_get(struct usbhsg_uep *uep) { + struct usbhs_pipe *pipe = usbhsg_uep_to_pipe(uep); + struct usbhs_pkt *pkt = usbhs_pkt_get(pipe); + /* ********* assume under spin lock ********* */ - if (list_empty(&uep->list)) - return NULL; + if (!pkt) + return 0; - return list_entry(uep->list.next, struct usbhsg_request, node); + return usbhsg_pkt_to_ureq(pkt); } #define usbhsg_queue_prepare(uep) __usbhsg_queue_handler(uep, 1); @@ -238,6 +244,7 @@ static void usbhsg_queue_pop(struct usbhsg_uep *uep, struct usbhsg_gpriv *gpriv = usbhsg_uep_to_gpriv(uep); struct usbhs_pipe *pipe = usbhsg_uep_to_pipe(uep); struct device *dev = usbhsg_gpriv_to_dev(gpriv); + struct usbhs_pkt *pkt = usbhsg_ureq_to_pkt(ureq); /* ********* assume under spin lock ********* @@ -263,7 +270,7 @@ static void usbhsg_queue_pop(struct usbhsg_uep *uep, dev_dbg(dev, "pipe %d : queue pop\n", usbhs_pipe_number(pipe)); - list_del_init(&ureq->node); + usbhs_pkt_pop(pkt); ureq->req.status = status; ureq->req.complete(&uep->ep, &ureq->req); @@ -319,38 +326,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 +372,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_fifo_enable(pipe); - /* * all data were sent ? */ @@ -389,6 +383,29 @@ 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 usb_request *req = &ureq->req; + struct usbhs_pkt *pkt = usbhsg_ureq_to_pkt(ureq); + int ret; + + /* + ********* assume under spin lock ********* + */ + + usbhs_pkt_update(pkt, + 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 +425,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; @@ -454,11 +466,26 @@ static int usbhsg_try_run_receive_packet(struct usbhsg_uep *uep, int disable = 0; uep->handler->irq_mask(uep, disable); - usbhs_fifo_disable(pipe); + 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 usb_request *req = &ureq->req; + struct usbhs_pkt *pkt = usbhsg_ureq_to_pkt(ureq); + + /* + ********* assume under spin lock ********* + */ + + usbhs_pkt_update(pkt, + req->buf + req->actual, + req->length - req->actual); + + return usbhs_fifo_read(pkt); } static int usbhsg_prepare_receive_packet(struct usbhsg_uep *uep, @@ -546,9 +573,9 @@ static int usbhsg_recip_handler_std_clear_endpoint(struct usbhs_priv *priv, struct usbhs_pipe *pipe = usbhsg_uep_to_pipe(uep); if (!usbhsg_status_has(gpriv, USBHSG_STATUS_WEDGE)) { - usbhs_fifo_disable(pipe); + usbhs_pipe_disable(pipe); usbhs_pipe_clear_sequence(pipe); - usbhs_fifo_enable(pipe); + usbhs_pipe_enable(pipe); } usbhsg_recip_handler_std_control_done(priv, uep, ctrl); @@ -695,7 +722,7 @@ static int usbhsg_irq_ctrl_stage(struct usbhs_priv *priv, ret = gpriv->driver->setup(&gpriv->gadget, &ctrl); if (ret < 0) - usbhs_fifo_stall(pipe); + usbhs_pipe_stall(pipe); return ret; } @@ -787,7 +814,6 @@ static int usbhsg_dcp_enable(struct usbhsg_uep *uep) uep->pipe = pipe; uep->pipe->mod_private = uep; - INIT_LIST_HEAD(&uep->list); return 0; } @@ -803,7 +829,7 @@ static int usbhsg_pipe_disable(struct usbhsg_uep *uep) ********* assume under spin lock ********* */ - usbhs_fifo_disable(pipe); + usbhs_pipe_disable(pipe); /* * disable pipe irq @@ -861,7 +887,6 @@ static int usbhsg_ep_enable(struct usb_ep *ep, if (pipe) { uep->pipe = pipe; pipe->mod_private = uep; - INIT_LIST_HEAD(&uep->list); if (usb_endpoint_dir_in(desc)) uep->handler = &usbhsg_handler_send_packet; @@ -905,7 +930,8 @@ static struct usb_request *usbhsg_ep_alloc_request(struct usb_ep *ep, if (!ureq) return NULL; - INIT_LIST_HEAD(&ureq->node); + usbhs_pkt_init(usbhsg_ureq_to_pkt(ureq)); + return &ureq->req; } @@ -914,7 +940,7 @@ static void usbhsg_ep_free_request(struct usb_ep *ep, { struct usbhsg_request *ureq = usbhsg_req_to_ureq(req); - WARN_ON(!list_empty(&ureq->node)); + WARN_ON(!list_empty(&ureq->pkt.node)); kfree(ureq); } @@ -1016,9 +1042,9 @@ static int __usbhsg_ep_set_halt_wedge(struct usb_ep *ep, int halt, int wedge) halt, usbhs_pipe_number(pipe)); if (halt) - usbhs_fifo_stall(pipe); + usbhs_pipe_stall(pipe); else - usbhs_fifo_disable(pipe); + usbhs_pipe_disable(pipe); if (halt && wedge) usbhsg_status_set(gpriv, USBHSG_STATUS_WEDGE); @@ -1086,7 +1112,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); @@ -1350,7 +1378,6 @@ int __devinit usbhs_mod_gadget_probe(struct usbhs_priv *priv) uep->ep.name = uep->ep_name; uep->ep.ops = &usbhsg_ep_ops; INIT_LIST_HEAD(&uep->ep.ep_list); - INIT_LIST_HEAD(&uep->list); /* init DCP */ if (usbhsg_is_dcp(uep)) {