diff --git a/drivers/usb/gadget/udc/core.c b/drivers/usb/gadget/udc/core.c index 9061d5d07b36..9f8a008081a6 100644 --- a/drivers/usb/gadget/udc/core.c +++ b/drivers/usb/gadget/udc/core.c @@ -506,6 +506,22 @@ out: } EXPORT_SYMBOL_GPL(usb_gadget_wakeup); +/** + * usb_gsi_ep_op - performs operation on GSI accelerated EP based on EP op code + * + * Operations such as EP configuration, TRB allocation, StartXfer etc. + * See gsi_ep_op for more details. + */ +int usb_gsi_ep_op(struct usb_ep *ep, + struct usb_gsi_request *req, enum gsi_ep_op op) +{ + if (ep && ep->ops && ep->ops->gsi_ep_op) + return ep->ops->gsi_ep_op(ep, req, op); + + return -EOPNOTSUPP; +} +EXPORT_SYMBOL_GPL(usb_gsi_ep_op); + /** * usb_gadget_func_wakeup - send a function remote wakeup up notification * to the host connected to this gadget diff --git a/include/linux/usb/gadget.h b/include/linux/usb/gadget.h index 9627574e2450..264a69f9f952 100644 --- a/include/linux/usb/gadget.h +++ b/include/linux/usb/gadget.h @@ -73,6 +73,7 @@ struct usb_ep; * Note that for writes (IN transfers) some data bytes may still * reside in a device-side FIFO when the request is reported as * complete. + * @udc_priv: Vendor private data in usage by the UDC. * * These are allocated/freed through the endpoint they're used with. The * hardware's driver can add extra per-request data to the memory it returns, @@ -114,6 +115,52 @@ struct usb_request { int status; unsigned actual; + unsigned int udc_priv; +}; + +/* + * @buf_base_addr: Base pointer to buffer allocated for each GSI enabled EP. + * TRBs point to buffers that are split from this pool. The size of the + * buffer is num_bufs times buf_len. num_bufs and buf_len are determined + based on desired performance and aggregation size. + * @dma: DMA address corresponding to buf_base_addr. + * @num_bufs: Number of buffers associated with the GSI enabled EP. This + * corresponds to the number of non-zlp TRBs allocated for the EP. + * The value is determined based on desired performance for the EP. + * @buf_len: Size of each individual buffer is determined based on aggregation + * negotiated as per the protocol. In case of no aggregation supported by + * the protocol, we use default values. + * @db_reg_phs_addr_lsb: IPA channel doorbell register's physical address LSB + * @mapped_db_reg_phs_addr_lsb: doorbell LSB IOVA address mapped with IOMMU + * @db_reg_phs_addr_msb: IPA channel doorbell register's physical address MSB + */ +struct usb_gsi_request { + void *buf_base_addr; + dma_addr_t dma; + size_t num_bufs; + size_t buf_len; + u32 db_reg_phs_addr_lsb; + dma_addr_t mapped_db_reg_phs_addr_lsb; + u32 db_reg_phs_addr_msb; + struct sg_table sgt_trb_xfer_ring; + struct sg_table sgt_data_buff; +}; + +enum gsi_ep_op { + GSI_EP_OP_CONFIG = 0, + GSI_EP_OP_STARTXFER, + GSI_EP_OP_STORE_DBL_INFO, + GSI_EP_OP_ENABLE_GSI, + GSI_EP_OP_UPDATEXFER, + GSI_EP_OP_RING_DB, + GSI_EP_OP_ENDXFER, + GSI_EP_OP_GET_CH_INFO, + GSI_EP_OP_GET_XFER_IDX, + GSI_EP_OP_PREPARE_TRBS, + GSI_EP_OP_FREE_TRBS, + GSI_EP_OP_SET_CLR_BLOCK_DBL, + GSI_EP_OP_CHECK_FOR_SUSPEND, + GSI_EP_OP_DISABLE, }; /*-------------------------------------------------------------------------*/ @@ -144,6 +191,9 @@ struct usb_ep_ops { int (*fifo_status) (struct usb_ep *ep); void (*fifo_flush) (struct usb_ep *ep); + int (*gsi_ep_op) (struct usb_ep *ep, void *op_data, + enum gsi_ep_op op); + }; /** @@ -263,6 +313,8 @@ int usb_ep_clear_halt(struct usb_ep *ep); int usb_ep_set_wedge(struct usb_ep *ep); int usb_ep_fifo_status(struct usb_ep *ep); void usb_ep_fifo_flush(struct usb_ep *ep); +int usb_gsi_ep_op(struct usb_ep *ep, + struct usb_gsi_request *req, enum gsi_ep_op op); #else static inline void usb_ep_set_maxpacket_limit(struct usb_ep *ep, unsigned maxpacket_limit) @@ -292,6 +344,10 @@ static inline int usb_ep_fifo_status(struct usb_ep *ep) { return 0; } static inline void usb_ep_fifo_flush(struct usb_ep *ep) { } + +static int usb_gsi_ep_op(struct usb_ep *ep, + struct usb_gsi_request *req, enum gsi_ep_op op) +{ return 0; } #endif /* USB_GADGET */ /*-------------------------------------------------------------------------*/ @@ -329,6 +385,7 @@ struct usb_gadget_ops { struct usb_ep *(*match_ep)(struct usb_gadget *, struct usb_endpoint_descriptor *, struct usb_ss_ep_comp_descriptor *); + int (*restart)(struct usb_gadget *g); }; /** @@ -380,6 +437,8 @@ struct usb_gadget_ops { * @connected: True if gadget is connected. * @lpm_capable: If the gadget max_speed is FULL or HIGH, this flag * indicates that it supports LPM as per the LPM ECN & errata. + * @remote_wakeup: Indicates if the host has enabled the remote_wakeup + * feature. * * Gadgets have a mostly-portable "gadget driver" implementing device * functions, handling all usb configurations and interfaces. Gadget @@ -434,6 +493,7 @@ struct usb_gadget { unsigned deactivated:1; unsigned connected:1; unsigned lpm_capable:1; + unsigned remote_wakeup:1; }; #define work_to_gadget(w) (container_of((w), struct usb_gadget, work))