static void usbhsh_pipe_detach(struct usbhsh_hpriv *hpriv, struct usbhsh_ep *uep) { struct usbhs_priv *priv = usbhsh_hpriv_to_priv(hpriv); struct usbhs_pipe *pipe; struct device *dev = usbhs_priv_to_dev(priv); unsigned long flags; /******************** spin lock ********************/ usbhs_lock(priv, flags); pipe = usbhsh_uep_to_pipe(uep); if (unlikely(!pipe)) { dev_err(dev, "uep doens't have pipe\n"); } else { struct usb_host_endpoint *ep = usbhsh_uep_to_ep(uep); struct usbhsh_device *udev = usbhsh_uep_to_udev(uep); /* detach pipe from uep */ usbhsh_uep_to_pipe(uep) = NULL; usbhsh_pipe_to_uep(pipe) = NULL; dev_dbg(dev, "%s [%d-%d(%s)]\n", __func__, usbhsh_device_number(hpriv, udev), usb_endpoint_num(&ep->desc), usbhs_pipe_name(pipe)); } usbhs_unlock(priv, flags); /******************** spin unlock ******************/ }
static void usbhsh_endpoint_detach(struct usbhsh_hpriv *hpriv, struct usb_host_endpoint *ep) { struct usbhs_priv *priv = usbhsh_hpriv_to_priv(hpriv); struct device *dev = usbhs_priv_to_dev(priv); struct usbhsh_ep *uep = usbhsh_ep_to_uep(ep); unsigned long flags; if (!uep) return; dev_dbg(dev, "%s [%d-%d]\n", __func__, usbhsh_device_number(hpriv, usbhsh_uep_to_udev(uep)), usb_endpoint_num(&ep->desc)); if (usbhsh_uep_to_pipe(uep)) usbhsh_pipe_detach(hpriv, uep); /******************** spin lock ********************/ usbhs_lock(priv, flags); /* remove this endpoint from udev */ list_del_init(&uep->ep_list); usbhsh_uep_to_udev(uep) = NULL; usbhsh_uep_to_ep(uep) = NULL; usbhsh_ep_to_uep(ep) = NULL; usbhs_unlock(priv, flags); /******************** spin unlock ******************/ kfree(uep); }
static int usbhsh_dcp_queue_push(struct usb_hcd *hcd, struct urb *urb, gfp_t mflags) { struct usbhsh_hpriv *hpriv = usbhsh_hcd_to_hpriv(hcd); struct usbhsh_ep *uep = usbhsh_ep_to_uep(urb->ep); struct usbhs_pipe *pipe = usbhsh_uep_to_pipe(uep); struct device *dev = usbhsh_hcd_to_dev(hcd); int ret; dev_dbg(dev, "%s\n", __func__); /* * setup stage * * usbhsh_send_setup_stage_packet() wait SACK/SIGN */ usbhsh_setup_stage_packet_push(hpriv, urb, pipe); /* * data stage * * It is pushed only when urb has buffer. */ if (urb->transfer_buffer_length) { ret = usbhsh_data_stage_packet_push(hpriv, urb, pipe, mflags); if (ret < 0) { dev_err(dev, "data stage failed\n"); return ret; } } /* * status stage */ ret = usbhsh_status_stage_packet_push(hpriv, urb, pipe, mflags); if (ret < 0) { dev_err(dev, "status stage failed\n"); return ret; } /* * start pushed packets */ usbhs_pkt_start(pipe); return 0; }
static int usbhsh_queue_push(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flags) { struct usbhsh_hpriv *hpriv = usbhsh_hcd_to_hpriv(hcd); struct usbhsh_ep *uep = usbhsh_ep_to_uep(urb->ep); struct usbhs_pipe *pipe = usbhsh_uep_to_pipe(uep); struct device *dev = usbhsh_hcd_to_dev(hcd); struct usbhsh_request *ureq; void *buf; int len, sequence; if (usb_pipeisoc(urb->pipe)) { dev_err(dev, "pipe iso is not supported now\n"); return -EIO; } /* this ureq will be freed on usbhsh_queue_done() */ ureq = usbhsh_ureq_alloc(hpriv, urb, mem_flags); if (unlikely(!ureq)) { dev_err(dev, "ureq alloc fail\n"); return -ENOMEM; } if (usb_pipein(urb->pipe)) pipe->handler = &usbhs_fifo_dma_pop_handler; else pipe->handler = &usbhs_fifo_dma_push_handler; buf = (void *)(urb->transfer_buffer + urb->actual_length); len = urb->transfer_buffer_length - urb->actual_length; sequence = usb_gettoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe)); dev_dbg(dev, "%s\n", __func__); usbhs_pkt_push(pipe, &ureq->pkt, usbhsh_queue_done, buf, len, (urb->transfer_flags & URB_ZERO_PACKET), sequence); usbhs_pkt_start(pipe); return 0; }
static int usbhsh_pipe_attach(struct usbhsh_hpriv *hpriv, struct urb *urb) { struct usbhs_priv *priv = usbhsh_hpriv_to_priv(hpriv); struct usbhsh_ep *uep = usbhsh_ep_to_uep(urb->ep); struct usbhsh_device *udev = usbhsh_device_get(hpriv, urb); struct usbhs_pipe *pipe; struct usb_endpoint_descriptor *desc = &urb->ep->desc; struct device *dev = usbhs_priv_to_dev(priv); unsigned long flags; int dir_in_req = !!usb_pipein(urb->pipe); int is_dcp = usb_endpoint_xfer_control(desc); int i, dir_in; int ret = -EBUSY; /******************** spin lock ********************/ usbhs_lock(priv, flags); /* * if uep has been attached to pipe, * reuse it */ if (usbhsh_uep_to_pipe(uep)) { ret = 0; goto usbhsh_pipe_attach_done; } usbhs_for_each_pipe_with_dcp(pipe, priv, i) { /* check pipe type */ if (!usbhs_pipe_type_is(pipe, usb_endpoint_type(desc))) continue; /* check pipe direction if normal pipe */ if (!is_dcp) { dir_in = !!usbhs_pipe_is_dir_in(pipe); if (0 != (dir_in - dir_in_req)) continue; } /* check pipe is free */ if (usbhsh_pipe_to_uep(pipe)) continue; /* * attach pipe to uep * * usbhs_pipe_config_update() should be called after * usbhs_set_device_config() * see * DCPMAXP/PIPEMAXP */ usbhsh_uep_to_pipe(uep) = pipe; usbhsh_pipe_to_uep(pipe) = uep; usbhs_pipe_config_update(pipe, usbhsh_device_number(hpriv, udev), usb_endpoint_num(desc), usb_endpoint_maxp(desc)); dev_dbg(dev, "%s [%d-%d(%s:%s)]\n", __func__, usbhsh_device_number(hpriv, udev), usb_endpoint_num(desc), usbhs_pipe_name(pipe), dir_in_req ? "in" : "out"); ret = 0; break; } usbhsh_pipe_attach_done: if (0 == ret) uep->counter++; usbhs_unlock(priv, flags); /******************** spin unlock ******************/ return ret; }