Commit 86e1cf7d authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman

Merge tag 'fixes-for-v5.7-rc6' of...

Merge tag 'fixes-for-v5.7-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb into usb-linus

Felipe writes:

USB: fixes for v5.7-rc6

The main part here are the important fixes for the raw-gadget before it
becomes an ABI. We're adding support for stall/halt/wedge which is
actually pretty important in many situations. There's also a NULL
pointer deref fix.

Apart from raw-gadget, I've included some recent sparse fixes to a few
drivers.
Signed-off-by: default avatarFelipe Balbi <balbi@kernel.org>

* tag 'fixes-for-v5.7-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb:
  usb: cdns3: gadget: make a bunch of functions static
  usb: mtu3: constify struct debugfs_reg32
  usb: gadget: udc: atmel: Make some symbols static
  usb: raw-gadget: fix null-ptr-deref when reenabling endpoints
  usb: raw-gadget: documentation updates
  usb: raw-gadget: support stalling/halting/wedging endpoints
  usb: raw-gadget: fix gadget endpoint selection
  usb: raw-gadget: improve uapi headers comments
parents a0e710a7 172b14b4
...@@ -27,9 +27,8 @@ differences are: ...@@ -27,9 +27,8 @@ differences are:
3. Raw Gadget provides a way to select a UDC device/driver to bind to, 3. Raw Gadget provides a way to select a UDC device/driver to bind to,
while GadgetFS currently binds to the first available UDC. while GadgetFS currently binds to the first available UDC.
4. Raw Gadget uses predictable endpoint names (handles) across different 4. Raw Gadget explicitly exposes information about endpoints addresses and
UDCs (as long as UDCs have enough endpoints of each required transfer capabilities allowing a user to write UDC-agnostic gadgets.
type).
5. Raw Gadget has ioctl-based interface instead of a filesystem-based one. 5. Raw Gadget has ioctl-based interface instead of a filesystem-based one.
...@@ -50,12 +49,36 @@ The typical usage of Raw Gadget looks like: ...@@ -50,12 +49,36 @@ The typical usage of Raw Gadget looks like:
Raw Gadget and react to those depending on what kind of USB device Raw Gadget and react to those depending on what kind of USB device
needs to be emulated. needs to be emulated.
Note, that some UDC drivers have fixed addresses assigned to endpoints, and
therefore arbitrary endpoint addresses can't be used in the descriptors.
Nevertheles, Raw Gadget provides a UDC-agnostic way to write USB gadgets.
Once a USB_RAW_EVENT_CONNECT event is received via USB_RAW_IOCTL_EVENT_FETCH,
the USB_RAW_IOCTL_EPS_INFO ioctl can be used to find out information about
endpoints that the UDC driver has. Based on that information, the user must
chose UDC endpoints that will be used for the gadget being emulated, and
properly assign addresses in endpoint descriptors.
You can find usage examples (along with a test suite) here:
https://github.com/xairy/raw-gadget
Internal details
~~~~~~~~~~~~~~~~
Currently every endpoint read/write ioctl submits a USB request and waits until
its completion. This is the desired mode for coverage-guided fuzzing (as we'd
like all USB request processing happen during the lifetime of a syscall),
and must be kept in the implementation. (This might be slow for real world
applications, thus the O_NONBLOCK improvement suggestion below.)
Potential future improvements Potential future improvements
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- Implement ioctl's for setting/clearing halt status on endpoints. - Report more events (suspend, resume, etc.) through USB_RAW_IOCTL_EVENT_FETCH.
- Reporting more events (suspend, resume, etc.) through
USB_RAW_IOCTL_EVENT_FETCH.
- Support O_NONBLOCK I/O. - Support O_NONBLOCK I/O.
- Support USB 3 features (accept SS endpoint companion descriptor when
enabling endpoints; allow providing stream_id for bulk transfers).
- Support ISO transfer features (expose frame_number for completed requests).
...@@ -82,7 +82,7 @@ static int cdns3_ep_run_stream_transfer(struct cdns3_endpoint *priv_ep, ...@@ -82,7 +82,7 @@ static int cdns3_ep_run_stream_transfer(struct cdns3_endpoint *priv_ep,
* @ptr: address of device controller register to be read and changed * @ptr: address of device controller register to be read and changed
* @mask: bits requested to clar * @mask: bits requested to clar
*/ */
void cdns3_clear_register_bit(void __iomem *ptr, u32 mask) static void cdns3_clear_register_bit(void __iomem *ptr, u32 mask)
{ {
mask = readl(ptr) & ~mask; mask = readl(ptr) & ~mask;
writel(mask, ptr); writel(mask, ptr);
...@@ -137,7 +137,7 @@ struct usb_request *cdns3_next_request(struct list_head *list) ...@@ -137,7 +137,7 @@ struct usb_request *cdns3_next_request(struct list_head *list)
* *
* Returns buffer or NULL if no buffers in list * Returns buffer or NULL if no buffers in list
*/ */
struct cdns3_aligned_buf *cdns3_next_align_buf(struct list_head *list) static struct cdns3_aligned_buf *cdns3_next_align_buf(struct list_head *list)
{ {
return list_first_entry_or_null(list, struct cdns3_aligned_buf, list); return list_first_entry_or_null(list, struct cdns3_aligned_buf, list);
} }
...@@ -148,7 +148,7 @@ struct cdns3_aligned_buf *cdns3_next_align_buf(struct list_head *list) ...@@ -148,7 +148,7 @@ struct cdns3_aligned_buf *cdns3_next_align_buf(struct list_head *list)
* *
* Returns request or NULL if no requests in list * Returns request or NULL if no requests in list
*/ */
struct cdns3_request *cdns3_next_priv_request(struct list_head *list) static struct cdns3_request *cdns3_next_priv_request(struct list_head *list)
{ {
return list_first_entry_or_null(list, struct cdns3_request, list); return list_first_entry_or_null(list, struct cdns3_request, list);
} }
...@@ -190,7 +190,7 @@ dma_addr_t cdns3_trb_virt_to_dma(struct cdns3_endpoint *priv_ep, ...@@ -190,7 +190,7 @@ dma_addr_t cdns3_trb_virt_to_dma(struct cdns3_endpoint *priv_ep,
return priv_ep->trb_pool_dma + offset; return priv_ep->trb_pool_dma + offset;
} }
int cdns3_ring_size(struct cdns3_endpoint *priv_ep) static int cdns3_ring_size(struct cdns3_endpoint *priv_ep)
{ {
switch (priv_ep->type) { switch (priv_ep->type) {
case USB_ENDPOINT_XFER_ISOC: case USB_ENDPOINT_XFER_ISOC:
...@@ -345,7 +345,7 @@ static void cdns3_ep_inc_deq(struct cdns3_endpoint *priv_ep) ...@@ -345,7 +345,7 @@ static void cdns3_ep_inc_deq(struct cdns3_endpoint *priv_ep)
cdns3_ep_inc_trb(&priv_ep->dequeue, &priv_ep->ccs, priv_ep->num_trbs); cdns3_ep_inc_trb(&priv_ep->dequeue, &priv_ep->ccs, priv_ep->num_trbs);
} }
void cdns3_move_deq_to_next_trb(struct cdns3_request *priv_req) static void cdns3_move_deq_to_next_trb(struct cdns3_request *priv_req)
{ {
struct cdns3_endpoint *priv_ep = priv_req->priv_ep; struct cdns3_endpoint *priv_ep = priv_req->priv_ep;
int current_trb = priv_req->start_trb; int current_trb = priv_req->start_trb;
...@@ -511,7 +511,7 @@ static void cdns3_wa2_descmiss_copy_data(struct cdns3_endpoint *priv_ep, ...@@ -511,7 +511,7 @@ static void cdns3_wa2_descmiss_copy_data(struct cdns3_endpoint *priv_ep,
} }
} }
struct usb_request *cdns3_wa2_gadget_giveback(struct cdns3_device *priv_dev, static struct usb_request *cdns3_wa2_gadget_giveback(struct cdns3_device *priv_dev,
struct cdns3_endpoint *priv_ep, struct cdns3_endpoint *priv_ep,
struct cdns3_request *priv_req) struct cdns3_request *priv_req)
{ {
...@@ -551,7 +551,7 @@ struct usb_request *cdns3_wa2_gadget_giveback(struct cdns3_device *priv_dev, ...@@ -551,7 +551,7 @@ struct usb_request *cdns3_wa2_gadget_giveback(struct cdns3_device *priv_dev,
return &priv_req->request; return &priv_req->request;
} }
int cdns3_wa2_gadget_ep_queue(struct cdns3_device *priv_dev, static int cdns3_wa2_gadget_ep_queue(struct cdns3_device *priv_dev,
struct cdns3_endpoint *priv_ep, struct cdns3_endpoint *priv_ep,
struct cdns3_request *priv_req) struct cdns3_request *priv_req)
{ {
...@@ -836,7 +836,7 @@ void cdns3_gadget_giveback(struct cdns3_endpoint *priv_ep, ...@@ -836,7 +836,7 @@ void cdns3_gadget_giveback(struct cdns3_endpoint *priv_ep,
cdns3_gadget_ep_free_request(&priv_ep->endpoint, request); cdns3_gadget_ep_free_request(&priv_ep->endpoint, request);
} }
void cdns3_wa1_restore_cycle_bit(struct cdns3_endpoint *priv_ep) static void cdns3_wa1_restore_cycle_bit(struct cdns3_endpoint *priv_ep)
{ {
/* Work around for stale data address in TRB*/ /* Work around for stale data address in TRB*/
if (priv_ep->wa1_set) { if (priv_ep->wa1_set) {
...@@ -1904,7 +1904,7 @@ static int cdns3_ep_onchip_buffer_reserve(struct cdns3_device *priv_dev, ...@@ -1904,7 +1904,7 @@ static int cdns3_ep_onchip_buffer_reserve(struct cdns3_device *priv_dev,
return 0; return 0;
} }
void cdns3_stream_ep_reconfig(struct cdns3_device *priv_dev, static void cdns3_stream_ep_reconfig(struct cdns3_device *priv_dev,
struct cdns3_endpoint *priv_ep) struct cdns3_endpoint *priv_ep)
{ {
if (!priv_ep->use_streams || priv_dev->gadget.speed < USB_SPEED_SUPER) if (!priv_ep->use_streams || priv_dev->gadget.speed < USB_SPEED_SUPER)
...@@ -1925,7 +1925,7 @@ void cdns3_stream_ep_reconfig(struct cdns3_device *priv_dev, ...@@ -1925,7 +1925,7 @@ void cdns3_stream_ep_reconfig(struct cdns3_device *priv_dev,
EP_CFG_TDL_CHK | EP_CFG_SID_CHK); EP_CFG_TDL_CHK | EP_CFG_SID_CHK);
} }
void cdns3_configure_dmult(struct cdns3_device *priv_dev, static void cdns3_configure_dmult(struct cdns3_device *priv_dev,
struct cdns3_endpoint *priv_ep) struct cdns3_endpoint *priv_ep)
{ {
struct cdns3_usb_regs __iomem *regs = priv_dev->regs; struct cdns3_usb_regs __iomem *regs = priv_dev->regs;
......
This diff is collapsed.
...@@ -185,7 +185,7 @@ static int regs_dbg_release(struct inode *inode, struct file *file) ...@@ -185,7 +185,7 @@ static int regs_dbg_release(struct inode *inode, struct file *file)
return 0; return 0;
} }
const struct file_operations queue_dbg_fops = { static const struct file_operations queue_dbg_fops = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.open = queue_dbg_open, .open = queue_dbg_open,
.llseek = no_llseek, .llseek = no_llseek,
...@@ -193,7 +193,7 @@ const struct file_operations queue_dbg_fops = { ...@@ -193,7 +193,7 @@ const struct file_operations queue_dbg_fops = {
.release = queue_dbg_release, .release = queue_dbg_release,
}; };
const struct file_operations regs_dbg_fops = { static const struct file_operations regs_dbg_fops = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.open = regs_dbg_open, .open = regs_dbg_open,
.llseek = generic_file_llseek, .llseek = generic_file_llseek,
......
...@@ -276,7 +276,7 @@ static const struct file_operations mtu3_ep_fops = { ...@@ -276,7 +276,7 @@ static const struct file_operations mtu3_ep_fops = {
.release = single_release, .release = single_release,
}; };
static struct debugfs_reg32 mtu3_prb_regs[] = { static const struct debugfs_reg32 mtu3_prb_regs[] = {
dump_prb_reg("enable", U3D_SSUSB_PRB_CTRL0), dump_prb_reg("enable", U3D_SSUSB_PRB_CTRL0),
dump_prb_reg("byte-sell", U3D_SSUSB_PRB_CTRL1), dump_prb_reg("byte-sell", U3D_SSUSB_PRB_CTRL1),
dump_prb_reg("byte-selh", U3D_SSUSB_PRB_CTRL2), dump_prb_reg("byte-selh", U3D_SSUSB_PRB_CTRL2),
...@@ -349,7 +349,7 @@ static const struct file_operations mtu3_probe_fops = { ...@@ -349,7 +349,7 @@ static const struct file_operations mtu3_probe_fops = {
static void mtu3_debugfs_create_prb_files(struct mtu3 *mtu) static void mtu3_debugfs_create_prb_files(struct mtu3 *mtu)
{ {
struct ssusb_mtk *ssusb = mtu->ssusb; struct ssusb_mtk *ssusb = mtu->ssusb;
struct debugfs_reg32 *regs; const struct debugfs_reg32 *regs;
struct dentry *dir_prb; struct dentry *dir_prb;
int i; int i;
......
...@@ -93,6 +93,64 @@ struct usb_raw_ep_io { ...@@ -93,6 +93,64 @@ struct usb_raw_ep_io {
__u8 data[0]; __u8 data[0];
}; };
/* Maximum number of non-control endpoints in struct usb_raw_eps_info. */
#define USB_RAW_EPS_NUM_MAX 30
/* Maximum length of UDC endpoint name in struct usb_raw_ep_info. */
#define USB_RAW_EP_NAME_MAX 16
/* Used as addr in struct usb_raw_ep_info if endpoint accepts any address. */
#define USB_RAW_EP_ADDR_ANY 0xff
/*
* struct usb_raw_ep_caps - exposes endpoint capabilities from struct usb_ep
* (technically from its member struct usb_ep_caps).
*/
struct usb_raw_ep_caps {
__u32 type_control : 1;
__u32 type_iso : 1;
__u32 type_bulk : 1;
__u32 type_int : 1;
__u32 dir_in : 1;
__u32 dir_out : 1;
};
/*
* struct usb_raw_ep_limits - exposes endpoint limits from struct usb_ep.
* @maxpacket_limit: Maximum packet size value supported by this endpoint.
* @max_streams: maximum number of streams supported by this endpoint
* (actual number is 2^n).
* @reserved: Empty, reserved for potential future extensions.
*/
struct usb_raw_ep_limits {
__u16 maxpacket_limit;
__u16 max_streams;
__u32 reserved;
};
/*
* struct usb_raw_ep_info - stores information about a gadget endpoint.
* @name: Name of the endpoint as it is defined in the UDC driver.
* @addr: Address of the endpoint that must be specified in the endpoint
* descriptor passed to USB_RAW_IOCTL_EP_ENABLE ioctl.
* @caps: Endpoint capabilities.
* @limits: Endpoint limits.
*/
struct usb_raw_ep_info {
__u8 name[USB_RAW_EP_NAME_MAX];
__u32 addr;
struct usb_raw_ep_caps caps;
struct usb_raw_ep_limits limits;
};
/*
* struct usb_raw_eps_info - argument for USB_RAW_IOCTL_EPS_INFO ioctl.
* eps: Structures that store information about non-control endpoints.
*/
struct usb_raw_eps_info {
struct usb_raw_ep_info eps[USB_RAW_EPS_NUM_MAX];
};
/* /*
* Initializes a Raw Gadget instance. * Initializes a Raw Gadget instance.
* Accepts a pointer to the usb_raw_init struct as an argument. * Accepts a pointer to the usb_raw_init struct as an argument.
...@@ -115,37 +173,38 @@ struct usb_raw_ep_io { ...@@ -115,37 +173,38 @@ struct usb_raw_ep_io {
#define USB_RAW_IOCTL_EVENT_FETCH _IOR('U', 2, struct usb_raw_event) #define USB_RAW_IOCTL_EVENT_FETCH _IOR('U', 2, struct usb_raw_event)
/* /*
* Queues an IN (OUT for READ) urb as a response to the last control request * Queues an IN (OUT for READ) request as a response to the last setup request
* received on endpoint 0, provided that was an IN (OUT for READ) request and * received on endpoint 0 (provided that was an IN (OUT for READ) request), and
* waits until the urb is completed. Copies received data to user for READ. * waits until the request is completed. Copies received data to user for READ.
* Accepts a pointer to the usb_raw_ep_io struct as an argument. * Accepts a pointer to the usb_raw_ep_io struct as an argument.
* Returns length of trasferred data on success or negative error code on * Returns length of transferred data on success or negative error code on
* failure. * failure.
*/ */
#define USB_RAW_IOCTL_EP0_WRITE _IOW('U', 3, struct usb_raw_ep_io) #define USB_RAW_IOCTL_EP0_WRITE _IOW('U', 3, struct usb_raw_ep_io)
#define USB_RAW_IOCTL_EP0_READ _IOWR('U', 4, struct usb_raw_ep_io) #define USB_RAW_IOCTL_EP0_READ _IOWR('U', 4, struct usb_raw_ep_io)
/* /*
* Finds an endpoint that supports the transfer type specified in the * Finds an endpoint that satisfies the parameters specified in the provided
* descriptor and enables it. * descriptors (address, transfer type, etc.) and enables it.
* Accepts a pointer to the usb_endpoint_descriptor struct as an argument. * Accepts a pointer to the usb_raw_ep_descs struct as an argument.
* Returns enabled endpoint handle on success or negative error code on failure. * Returns enabled endpoint handle on success or negative error code on failure.
*/ */
#define USB_RAW_IOCTL_EP_ENABLE _IOW('U', 5, struct usb_endpoint_descriptor) #define USB_RAW_IOCTL_EP_ENABLE _IOW('U', 5, struct usb_endpoint_descriptor)
/* Disables specified endpoint. /*
* Disables specified endpoint.
* Accepts endpoint handle as an argument. * Accepts endpoint handle as an argument.
* Returns 0 on success or negative error code on failure. * Returns 0 on success or negative error code on failure.
*/ */
#define USB_RAW_IOCTL_EP_DISABLE _IOW('U', 6, __u32) #define USB_RAW_IOCTL_EP_DISABLE _IOW('U', 6, __u32)
/* /*
* Queues an IN (OUT for READ) urb as a response to the last control request * Queues an IN (OUT for READ) request as a response to the last setup request
* received on endpoint usb_raw_ep_io.ep, provided that was an IN (OUT for READ) * received on endpoint usb_raw_ep_io.ep (provided that was an IN (OUT for READ)
* request and waits until the urb is completed. Copies received data to user * request), and waits until the request is completed. Copies received data to
* for READ. * user for READ.
* Accepts a pointer to the usb_raw_ep_io struct as an argument. * Accepts a pointer to the usb_raw_ep_io struct as an argument.
* Returns length of trasferred data on success or negative error code on * Returns length of transferred data on success or negative error code on
* failure. * failure.
*/ */
#define USB_RAW_IOCTL_EP_WRITE _IOW('U', 7, struct usb_raw_ep_io) #define USB_RAW_IOCTL_EP_WRITE _IOW('U', 7, struct usb_raw_ep_io)
...@@ -164,4 +223,27 @@ struct usb_raw_ep_io { ...@@ -164,4 +223,27 @@ struct usb_raw_ep_io {
*/ */
#define USB_RAW_IOCTL_VBUS_DRAW _IOW('U', 10, __u32) #define USB_RAW_IOCTL_VBUS_DRAW _IOW('U', 10, __u32)
/*
* Fills in the usb_raw_eps_info structure with information about non-control
* endpoints available for the currently connected UDC.
* Returns the number of available endpoints on success or negative error code
* on failure.
*/
#define USB_RAW_IOCTL_EPS_INFO _IOR('U', 11, struct usb_raw_eps_info)
/*
* Stalls a pending control request on endpoint 0.
* Returns 0 on success or negative error code on failure.
*/
#define USB_RAW_IOCTL_EP0_STALL _IO('U', 12)
/*
* Sets or clears halt or wedge status of the endpoint.
* Accepts endpoint handle as an argument.
* Returns 0 on success or negative error code on failure.
*/
#define USB_RAW_IOCTL_EP_SET_HALT _IOW('U', 13, __u32)
#define USB_RAW_IOCTL_EP_CLEAR_HALT _IOW('U', 14, __u32)
#define USB_RAW_IOCTL_EP_SET_WEDGE _IOW('U', 15, __u32)
#endif /* _UAPI__LINUX_USB_RAW_GADGET_H */ #endif /* _UAPI__LINUX_USB_RAW_GADGET_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment