lkml.org 
[lkml]   [2018]   [Jul]   [12]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 28/31] usb: usbssp: implemented usbssp_gadget_ep_disable function.
    Date
    Patch implements function responsible for disabling
    USB endpoint. This function is called
    from USB core gadget during handling SET_CONFIGURATION or
    SET_INTERFACE request, or after such events as USB_RESET or detaching
    device from host.

    Signed-off-by: Pawel Laszczak <pawell@cadence.com>
    ---
    drivers/usb/usbssp/gadget-if.c | 44 +++++++++++++++++--
    drivers/usb/usbssp/gadget-mem.c | 18 ++++++++
    drivers/usb/usbssp/gadget.c | 75 +++++++++++++++++++++++++++++++++
    drivers/usb/usbssp/gadget.h | 2 +
    4 files changed, 135 insertions(+), 4 deletions(-)

    diff --git a/drivers/usb/usbssp/gadget-if.c b/drivers/usb/usbssp/gadget-if.c
    index 2fecc934cbce..75444eaaf699 100644
    --- a/drivers/usb/usbssp/gadget-if.c
    +++ b/drivers/usb/usbssp/gadget-if.c
    @@ -86,13 +86,49 @@ static int usbssp_gadget_ep_enable(struct usb_ep *ep,

    int usbssp_gadget_ep_disable(struct usb_ep *ep)
    {
    - struct usbssp_ep *ep_priv = to_usbssp_ep(ep);
    - int ret = 0;
    + struct usbssp_ep *ep_priv;
    + struct usbssp_udc *usbssp_data;
    + int ep_index = 0;
    + int ret;
    + int irq_disabled_locally = 0;
    + unsigned long flags = 0;
    + struct usbssp_request *req_priv;

    - if (!ep_priv)
    + ep_priv = to_usbssp_ep(ep);
    + usbssp_data = ep_priv->usbssp_data;
    + ep_index = usbssp_get_endpoint_index(ep_priv->endpoint.desc);
    +
    + if (!(ep_priv->ep_state & USBSSP_EP_ENABLED)) {
    + usbssp_dbg(usbssp_data, "%s is already disabled\n",
    + ep_priv->name);
    return -EINVAL;
    + }
    +
    + usbssp_g_lock(irq_disabled_locally, flags);

    - /*TODO: implements this function*/
    + ep_priv->ep_state |= USBSSP_EP_DISABLE_PENDING;
    +
    + /*dequeue all USB request from endpoint*/
    + list_for_each_entry(req_priv, &ep_priv->pending_list, list) {
    + usbssp_dequeue(ep_priv, req_priv);
    + }
    +
    + ret = usbssp_drop_endpoint(usbssp_data, &usbssp_data->gadget, ep_priv);
    + if (ret)
    + goto finish;
    +
    + ret = usbssp_check_bandwidth(usbssp_data, &usbssp_data->gadget);
    + if (ret)
    + goto finish;
    +
    + ep_priv->ep_state &= ~USBSSP_EP_ENABLED;
    +
    +finish:
    + ep_priv->ep_state &= ~USBSSP_EP_DISABLE_PENDING;
    + usbssp_dbg(usbssp_data, "%s disable endpoint %s\n", ep_priv->name,
    + (ret == 0) ? "success" : "failed");
    +
    + usbssp_g_unlock(irq_disabled_locally, flags);
    return ret;
    }

    diff --git a/drivers/usb/usbssp/gadget-mem.c b/drivers/usb/usbssp/gadget-mem.c
    index 303dc8fab8ad..772a43f24ca9 100644
    --- a/drivers/usb/usbssp/gadget-mem.c
    +++ b/drivers/usb/usbssp/gadget-mem.c
    @@ -1103,6 +1103,24 @@ int usbssp_endpoint_init(struct usbssp_udc *usbssp_data,
    return 0;
    }

    +void usbssp_endpoint_zero(struct usbssp_udc *usbssp_data,
    + struct usbssp_device *dev_priv,
    + struct usbssp_ep *ep)
    +{
    + unsigned int ep_index;
    + struct usbssp_ep_ctx *ep_ctx;
    +
    + ep_index = usbssp_get_endpoint_index(ep->endpoint.desc);
    + ep_ctx = usbssp_get_ep_ctx(usbssp_data, dev_priv->in_ctx, ep_index);
    +
    + ep_ctx->ep_info = 0;
    + ep_ctx->ep_info2 = 0;
    + ep_ctx->deq = 0;
    + ep_ctx->tx_info = 0;
    + /* Don't free the endpoint ring until the set interface or configuration
    + * request succeeds.
    + */
    +}
    struct usbssp_command *usbssp_alloc_command(struct usbssp_udc *usbssp_data,
    bool allocate_completion,
    gfp_t mem_flags)
    diff --git a/drivers/usb/usbssp/gadget.c b/drivers/usb/usbssp/gadget.c
    index 833647600485..bf6a147e2a16 100644
    --- a/drivers/usb/usbssp/gadget.c
    +++ b/drivers/usb/usbssp/gadget.c
    @@ -723,6 +723,81 @@ int usbssp_dequeue(struct usbssp_ep *ep_priv, struct usbssp_request *req_priv)
    return ret;
    }

    +/* Drop an endpoint from a new bandwidth configuration for this device.
    + * Only one call to this function is allowed per endpoint before
    + * check_bandwidth() or reset_bandwidth() must be called.
    + * A call to usbssp_drop_endpoint() followed by a call to usbssp_add_endpoint()
    + * will add the endpoint to the schedule with possibly new parameters
    + * denoted by a different endpoint descriptor in usbssp_ep.
    + * A call to usbssp_add_endpoint() followed by a call to
    + * usbsssp_drop_endpoint() is not allowed.
    + */
    +int usbssp_drop_endpoint(struct usbssp_udc *usbssp_data, struct usb_gadget *g,
    + struct usbssp_ep *dep)
    +{
    + struct usbssp_container_ctx *in_ctx, *out_ctx;
    + struct usbssp_input_control_ctx *ctrl_ctx;
    + unsigned int ep_index;
    + struct usbssp_ep_ctx *ep_ctx;
    + u32 drop_flag;
    + u32 new_add_flags, new_drop_flags;
    + int ret;
    +
    + ret = usbssp_check_args(usbssp_data, dep, 1, true, __func__);
    + if (ret <= 0)
    + return ret;
    +
    + if (usbssp_data->usbssp_state & USBSSP_STATE_DYING)
    + return -ENODEV;
    +
    + drop_flag = usbssp_get_endpoint_flag(dep->endpoint.desc);
    + if (drop_flag == SLOT_FLAG || drop_flag == EP0_FLAG) {
    + usbssp_dbg(usbssp_data, "USBSSP %s - can't drop slot or ep 0 %#x\n",
    + __func__, drop_flag);
    + return 0;
    + }
    +
    + in_ctx = usbssp_data->devs.in_ctx;
    + out_ctx = usbssp_data->devs.out_ctx;
    + ctrl_ctx = usbssp_get_input_control_ctx(in_ctx);
    + if (!ctrl_ctx) {
    + usbssp_warn(usbssp_data, "%s: Could not get input context, bad type.\n",
    + __func__);
    + return 0;
    + }
    +
    + ep_index = usbssp_get_endpoint_index(dep->endpoint.desc);
    + ep_ctx = usbssp_get_ep_ctx(usbssp_data, out_ctx, ep_index);
    + /* If the controller already knows the endpoint is disabled,
    + * or the USBSSP driver has noted it is disabled, ignore this request
    + */
    + if ((GET_EP_CTX_STATE(ep_ctx) == EP_STATE_DISABLED) ||
    + le32_to_cpu(ctrl_ctx->drop_flags) &
    + usbssp_get_endpoint_flag(dep->endpoint.desc)) {
    + /* Do not warn when called after a usb_device_reset */
    + if (usbssp_data->devs.eps[ep_index].ring != NULL)
    + usbssp_warn(usbssp_data, "USBSSP %s called with disabled ep %p\n",
    + __func__, dep);
    + return 0;
    + }
    +
    + ctrl_ctx->drop_flags |= cpu_to_le32(drop_flag);
    + new_drop_flags = le32_to_cpu(ctrl_ctx->drop_flags);
    +
    + ctrl_ctx->add_flags &= cpu_to_le32(~drop_flag);
    + new_add_flags = le32_to_cpu(ctrl_ctx->add_flags);
    +
    +// usbssp_debugfs_remove_endpoint(usbssp_data, &usbssp_data->devs,
    +// ep_index);
    +
    + usbssp_endpoint_zero(usbssp_data, &usbssp_data->devs, dep);
    +
    + usbssp_dbg(usbssp_data, "drop ep 0x%x, new drop flags = %#x, new add flags = %#x\n",
    + (unsigned int) dep->endpoint.desc->bEndpointAddress,
    + (unsigned int) new_drop_flags,
    + (unsigned int) new_add_flags);
    + return 0;
    +}

    /* Add an endpoint to a new possible bandwidth configuration for this device.
    * Only one call to this function is allowed per endpoint before
    diff --git a/drivers/usb/usbssp/gadget.h b/drivers/usb/usbssp/gadget.h
    index a3288cd16c4a..cc826255593f 100644
    --- a/drivers/usb/usbssp/gadget.h
    +++ b/drivers/usb/usbssp/gadget.h
    @@ -1688,6 +1688,8 @@ void usbssp_copy_ep0_dequeue_into_input_ctx(struct usbssp_udc *usbssp_data);
    unsigned int usbssp_get_endpoint_index(const struct usb_endpoint_descriptor *desc);
    unsigned int usbssp_get_endpoint_address(unsigned int ep_index);
    unsigned int usbssp_last_valid_endpoint(u32 added_ctxs);
    +void usbssp_endpoint_zero(struct usbssp_udc *usbssp_data,
    + struct usbssp_device *dev_priv, struct usbssp_ep *ep);
    int usbssp_endpoint_init(struct usbssp_udc *usbssp_data,
    struct usbssp_device *dev_priv,
    struct usbssp_ep *dep,
    --
    2.17.1
    \
     
     \ /
      Last update: 2018-07-15 22:05    [W:4.340 / U:0.028 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site