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

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
Loading
Loading
Loading
Loading
+30 −7
Original line number Diff line number Diff line
@@ -27,9 +27,8 @@ differences are:
3. Raw Gadget provides a way to select a UDC device/driver to bind to,
   while GadgetFS currently binds to the first available UDC.

4. Raw Gadget uses predictable endpoint names (handles) across different
   UDCs (as long as UDCs have enough endpoints of each required transfer
   type).
4. Raw Gadget explicitly exposes information about endpoints addresses and
   capabilities allowing a user to write UDC-agnostic gadgets.

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:
   Raw Gadget and react to those depending on what kind of USB device
   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
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

- Implement ioctl's for setting/clearing halt status on endpoints.

- Reporting more events (suspend, resume, etc.) through
  USB_RAW_IOCTL_EVENT_FETCH.
- Report more events (suspend, resume, etc.) through USB_RAW_IOCTL_EVENT_FETCH.

- 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).
+10 −10
Original line number Diff line number Diff line
@@ -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
 * @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;
	writel(mask, ptr);
@@ -137,7 +137,7 @@ struct usb_request *cdns3_next_request(struct list_head *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);
}
@@ -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
 */
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);
}
@@ -190,7 +190,7 @@ dma_addr_t cdns3_trb_virt_to_dma(struct cdns3_endpoint *priv_ep,
	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) {
	case USB_ENDPOINT_XFER_ISOC:
@@ -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);
}

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;
	int current_trb = priv_req->start_trb;
@@ -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_request *priv_req)
{
@@ -551,7 +551,7 @@ struct usb_request *cdns3_wa2_gadget_giveback(struct cdns3_device *priv_dev,
	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_request *priv_req)
{
@@ -836,7 +836,7 @@ void cdns3_gadget_giveback(struct cdns3_endpoint *priv_ep,
		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*/
	if (priv_ep->wa1_set) {
@@ -1904,7 +1904,7 @@ static int cdns3_ep_onchip_buffer_reserve(struct cdns3_device *priv_dev,
	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)
{
	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,
			       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_usb_regs __iomem *regs = priv_dev->regs;
+246 −61
Original line number Diff line number Diff line
@@ -7,6 +7,7 @@
 */

#include <linux/compiler.h>
#include <linux/ctype.h>
#include <linux/debugfs.h>
#include <linux/delay.h>
#include <linux/kref.h>
@@ -123,8 +124,6 @@ static void raw_event_queue_destroy(struct raw_event_queue *queue)

struct raw_dev;

#define USB_RAW_MAX_ENDPOINTS 32

enum ep_state {
	STATE_EP_DISABLED,
	STATE_EP_ENABLED,
@@ -134,6 +133,7 @@ struct raw_ep {
	struct raw_dev		*dev;
	enum ep_state		state;
	struct usb_ep		*ep;
	u8			addr;
	struct usb_request	*req;
	bool			urb_queued;
	bool			disabling;
@@ -168,7 +168,8 @@ struct raw_dev {
	bool				ep0_out_pending;
	bool				ep0_urb_queued;
	ssize_t				ep0_status;
	struct raw_ep			eps[USB_RAW_MAX_ENDPOINTS];
	struct raw_ep			eps[USB_RAW_EPS_NUM_MAX];
	int				eps_num;

	struct completion		ep0_done;
	struct raw_event_queue		queue;
@@ -202,8 +203,8 @@ static void dev_free(struct kref *kref)
		usb_ep_free_request(dev->gadget->ep0, dev->req);
	}
	raw_event_queue_destroy(&dev->queue);
	for (i = 0; i < USB_RAW_MAX_ENDPOINTS; i++) {
		if (dev->eps[i].state != STATE_EP_ENABLED)
	for (i = 0; i < dev->eps_num; i++) {
		if (dev->eps[i].state == STATE_EP_DISABLED)
			continue;
		usb_ep_disable(dev->eps[i].ep);
		usb_ep_free_request(dev->eps[i].ep, dev->eps[i].req);
@@ -249,12 +250,26 @@ static void gadget_ep0_complete(struct usb_ep *ep, struct usb_request *req)
	complete(&dev->ep0_done);
}

static u8 get_ep_addr(const char *name)
{
	/* If the endpoint has fixed function (named as e.g. "ep12out-bulk"),
	 * parse the endpoint address from its name. We deliberately use
	 * deprecated simple_strtoul() function here, as the number isn't
	 * followed by '\0' nor '\n'.
	 */
	if (isdigit(name[2]))
		return simple_strtoul(&name[2], NULL, 10);
	/* Otherwise the endpoint is configurable (named as e.g. "ep-a"). */
	return USB_RAW_EP_ADDR_ANY;
}

static int gadget_bind(struct usb_gadget *gadget,
			struct usb_gadget_driver *driver)
{
	int ret = 0;
	int ret = 0, i = 0;
	struct raw_dev *dev = container_of(driver, struct raw_dev, driver);
	struct usb_request *req;
	struct usb_ep *ep;
	unsigned long flags;

	if (strcmp(gadget->name, dev->udc_name) != 0)
@@ -273,6 +288,13 @@ static int gadget_bind(struct usb_gadget *gadget,
	dev->req->context = dev;
	dev->req->complete = gadget_ep0_complete;
	dev->gadget = gadget;
	gadget_for_each_ep(ep, dev->gadget) {
		dev->eps[i].ep = ep;
		dev->eps[i].addr = get_ep_addr(ep->name);
		dev->eps[i].state = STATE_EP_DISABLED;
		i++;
	}
	dev->eps_num = i;
	spin_unlock_irqrestore(&dev->lock, flags);

	/* Matches kref_put() in gadget_unbind(). */
@@ -555,7 +577,7 @@ static void *raw_alloc_io_data(struct usb_raw_ep_io *io, void __user *ptr,

	if (copy_from_user(io, ptr, sizeof(*io)))
		return ERR_PTR(-EFAULT);
	if (io->ep >= USB_RAW_MAX_ENDPOINTS)
	if (io->ep >= USB_RAW_EPS_NUM_MAX)
		return ERR_PTR(-EINVAL);
	if (!usb_raw_io_flags_valid(io->flags))
		return ERR_PTR(-EINVAL);
@@ -682,32 +704,48 @@ free:
	return ret;
}

static bool check_ep_caps(struct usb_ep *ep,
				struct usb_endpoint_descriptor *desc)
static int raw_ioctl_ep0_stall(struct raw_dev *dev, unsigned long value)
{
	switch (usb_endpoint_type(desc)) {
	case USB_ENDPOINT_XFER_ISOC:
		if (!ep->caps.type_iso)
			return false;
		break;
	case USB_ENDPOINT_XFER_BULK:
		if (!ep->caps.type_bulk)
			return false;
		break;
	case USB_ENDPOINT_XFER_INT:
		if (!ep->caps.type_int)
			return false;
		break;
	default:
		return false;
	int ret = 0;
	unsigned long flags;

	if (value)
		return -EINVAL;
	spin_lock_irqsave(&dev->lock, flags);
	if (dev->state != STATE_DEV_RUNNING) {
		dev_dbg(dev->dev, "fail, device is not running\n");
		ret = -EINVAL;
		goto out_unlock;
	}
	if (!dev->gadget) {
		dev_dbg(dev->dev, "fail, gadget is not bound\n");
		ret = -EBUSY;
		goto out_unlock;
	}
	if (dev->ep0_urb_queued) {
		dev_dbg(&dev->gadget->dev, "fail, urb already queued\n");
		ret = -EBUSY;
		goto out_unlock;
	}
	if (!dev->ep0_in_pending && !dev->ep0_out_pending) {
		dev_dbg(&dev->gadget->dev, "fail, no request pending\n");
		ret = -EBUSY;
		goto out_unlock;
	}

	if (usb_endpoint_dir_in(desc) && !ep->caps.dir_in)
		return false;
	if (usb_endpoint_dir_out(desc) && !ep->caps.dir_out)
		return false;
	ret = usb_ep_set_halt(dev->gadget->ep0);
	if (ret < 0)
		dev_err(&dev->gadget->dev,
				"fail, usb_ep_set_halt returned %d\n", ret);

	return true;
	if (dev->ep0_in_pending)
		dev->ep0_in_pending = false;
	else
		dev->ep0_out_pending = false;

out_unlock:
	spin_unlock_irqrestore(&dev->lock, flags);
	return ret;
}

static int raw_ioctl_ep_enable(struct raw_dev *dev, unsigned long value)
@@ -715,7 +753,7 @@ static int raw_ioctl_ep_enable(struct raw_dev *dev, unsigned long value)
	int ret = 0, i;
	unsigned long flags;
	struct usb_endpoint_descriptor *desc;
	struct usb_ep *ep = NULL;
	struct raw_ep *ep;

	desc = memdup_user((void __user *)value, sizeof(*desc));
	if (IS_ERR(desc))
@@ -743,41 +781,32 @@ static int raw_ioctl_ep_enable(struct raw_dev *dev, unsigned long value)
		goto out_free;
	}

	for (i = 0; i < USB_RAW_MAX_ENDPOINTS; i++) {
		if (dev->eps[i].state == STATE_EP_ENABLED)
	for (i = 0; i < dev->eps_num; i++) {
		ep = &dev->eps[i];
		if (ep->state != STATE_EP_DISABLED)
			continue;
		break;
	}
	if (i == USB_RAW_MAX_ENDPOINTS) {
		dev_dbg(&dev->gadget->dev,
				"fail, no device endpoints available\n");
		ret = -EBUSY;
		goto out_free;
	}

	gadget_for_each_ep(ep, dev->gadget) {
		if (ep->enabled)
		if (ep->addr != usb_endpoint_num(desc) &&
				ep->addr != USB_RAW_EP_ADDR_ANY)
			continue;
		if (!check_ep_caps(ep, desc))
		if (!usb_gadget_ep_match_desc(dev->gadget, ep->ep, desc, NULL))
			continue;
		ep->desc = desc;
		ret = usb_ep_enable(ep);
		ep->ep->desc = desc;
		ret = usb_ep_enable(ep->ep);
		if (ret < 0) {
			dev_err(&dev->gadget->dev,
				"fail, usb_ep_enable returned %d\n", ret);
			goto out_free;
		}
		dev->eps[i].req = usb_ep_alloc_request(ep, GFP_ATOMIC);
		if (!dev->eps[i].req) {
		ep->req = usb_ep_alloc_request(ep->ep, GFP_ATOMIC);
		if (!ep->req) {
			dev_err(&dev->gadget->dev,
				"fail, usb_ep_alloc_request failed\n");
			usb_ep_disable(ep);
			usb_ep_disable(ep->ep);
			ret = -ENOMEM;
			goto out_free;
		}
		dev->eps[i].ep = ep;
		dev->eps[i].state = STATE_EP_ENABLED;
		ep->driver_data = &dev->eps[i];
		ep->state = STATE_EP_ENABLED;
		ep->ep->driver_data = ep;
		ret = i;
		goto out_unlock;
	}
@@ -796,10 +825,6 @@ static int raw_ioctl_ep_disable(struct raw_dev *dev, unsigned long value)
{
	int ret = 0, i = value;
	unsigned long flags;
	const void *desc;

	if (i < 0 || i >= USB_RAW_MAX_ENDPOINTS)
		return -EINVAL;

	spin_lock_irqsave(&dev->lock, flags);
	if (dev->state != STATE_DEV_RUNNING) {
@@ -812,7 +837,12 @@ static int raw_ioctl_ep_disable(struct raw_dev *dev, unsigned long value)
		ret = -EBUSY;
		goto out_unlock;
	}
	if (dev->eps[i].state != STATE_EP_ENABLED) {
	if (i < 0 || i >= dev->eps_num) {
		dev_dbg(dev->dev, "fail, invalid endpoint\n");
		ret = -EBUSY;
		goto out_unlock;
	}
	if (dev->eps[i].state == STATE_EP_DISABLED) {
		dev_dbg(&dev->gadget->dev, "fail, endpoint is not enabled\n");
		ret = -EINVAL;
		goto out_unlock;
@@ -836,10 +866,8 @@ static int raw_ioctl_ep_disable(struct raw_dev *dev, unsigned long value)

	spin_lock_irqsave(&dev->lock, flags);
	usb_ep_free_request(dev->eps[i].ep, dev->eps[i].req);
	desc = dev->eps[i].ep->desc;
	dev->eps[i].ep = NULL;
	kfree(dev->eps[i].ep->desc);
	dev->eps[i].state = STATE_EP_DISABLED;
	kfree(desc);
	dev->eps[i].disabling = false;

out_unlock:
@@ -847,6 +875,74 @@ out_unlock:
	return ret;
}

static int raw_ioctl_ep_set_clear_halt_wedge(struct raw_dev *dev,
		unsigned long value, bool set, bool halt)
{
	int ret = 0, i = value;
	unsigned long flags;

	spin_lock_irqsave(&dev->lock, flags);
	if (dev->state != STATE_DEV_RUNNING) {
		dev_dbg(dev->dev, "fail, device is not running\n");
		ret = -EINVAL;
		goto out_unlock;
	}
	if (!dev->gadget) {
		dev_dbg(dev->dev, "fail, gadget is not bound\n");
		ret = -EBUSY;
		goto out_unlock;
	}
	if (i < 0 || i >= dev->eps_num) {
		dev_dbg(dev->dev, "fail, invalid endpoint\n");
		ret = -EBUSY;
		goto out_unlock;
	}
	if (dev->eps[i].state == STATE_EP_DISABLED) {
		dev_dbg(&dev->gadget->dev, "fail, endpoint is not enabled\n");
		ret = -EINVAL;
		goto out_unlock;
	}
	if (dev->eps[i].disabling) {
		dev_dbg(&dev->gadget->dev,
				"fail, disable is in progress\n");
		ret = -EINVAL;
		goto out_unlock;
	}
	if (dev->eps[i].urb_queued) {
		dev_dbg(&dev->gadget->dev,
				"fail, waiting for urb completion\n");
		ret = -EINVAL;
		goto out_unlock;
	}
	if (usb_endpoint_xfer_isoc(dev->eps[i].ep->desc)) {
		dev_dbg(&dev->gadget->dev,
				"fail, can't halt/wedge ISO endpoint\n");
		ret = -EINVAL;
		goto out_unlock;
	}

	if (set && halt) {
		ret = usb_ep_set_halt(dev->eps[i].ep);
		if (ret < 0)
			dev_err(&dev->gadget->dev,
				"fail, usb_ep_set_halt returned %d\n", ret);
	} else if (!set && halt) {
		ret = usb_ep_clear_halt(dev->eps[i].ep);
		if (ret < 0)
			dev_err(&dev->gadget->dev,
				"fail, usb_ep_clear_halt returned %d\n", ret);
	} else if (set && !halt) {
		ret = usb_ep_set_wedge(dev->eps[i].ep);
		if (ret < 0)
			dev_err(&dev->gadget->dev,
				"fail, usb_ep_set_wedge returned %d\n", ret);
	}

out_unlock:
	spin_unlock_irqrestore(&dev->lock, flags);
	return ret;
}

static void gadget_ep_complete(struct usb_ep *ep, struct usb_request *req)
{
	struct raw_ep *r_ep = (struct raw_ep *)ep->driver_data;
@@ -868,7 +964,7 @@ static int raw_process_ep_io(struct raw_dev *dev, struct usb_raw_ep_io *io,
{
	int ret = 0;
	unsigned long flags;
	struct raw_ep *ep = &dev->eps[io->ep];
	struct raw_ep *ep;
	DECLARE_COMPLETION_ONSTACK(done);

	spin_lock_irqsave(&dev->lock, flags);
@@ -882,6 +978,12 @@ static int raw_process_ep_io(struct raw_dev *dev, struct usb_raw_ep_io *io,
		ret = -EBUSY;
		goto out_unlock;
	}
	if (io->ep >= dev->eps_num) {
		dev_dbg(&dev->gadget->dev, "fail, invalid endpoint\n");
		ret = -EINVAL;
		goto out_unlock;
	}
	ep = &dev->eps[io->ep];
	if (ep->state != STATE_EP_ENABLED) {
		dev_dbg(&dev->gadget->dev, "fail, endpoint is not enabled\n");
		ret = -EBUSY;
@@ -1027,6 +1129,71 @@ out_unlock:
	return ret;
}

static void fill_ep_caps(struct usb_ep_caps *caps,
				struct usb_raw_ep_caps *raw_caps)
{
	raw_caps->type_control = caps->type_control;
	raw_caps->type_iso = caps->type_iso;
	raw_caps->type_bulk = caps->type_bulk;
	raw_caps->type_int = caps->type_int;
	raw_caps->dir_in = caps->dir_in;
	raw_caps->dir_out = caps->dir_out;
}

static void fill_ep_limits(struct usb_ep *ep, struct usb_raw_ep_limits *limits)
{
	limits->maxpacket_limit = ep->maxpacket_limit;
	limits->max_streams = ep->max_streams;
}

static int raw_ioctl_eps_info(struct raw_dev *dev, unsigned long value)
{
	int ret = 0, i;
	unsigned long flags;
	struct usb_raw_eps_info *info;
	struct raw_ep *ep;

	info = kmalloc(sizeof(*info), GFP_KERNEL);
	if (!info) {
		ret = -ENOMEM;
		goto out;
	}

	spin_lock_irqsave(&dev->lock, flags);
	if (dev->state != STATE_DEV_RUNNING) {
		dev_dbg(dev->dev, "fail, device is not running\n");
		ret = -EINVAL;
		spin_unlock_irqrestore(&dev->lock, flags);
		goto out_free;
	}
	if (!dev->gadget) {
		dev_dbg(dev->dev, "fail, gadget is not bound\n");
		ret = -EBUSY;
		spin_unlock_irqrestore(&dev->lock, flags);
		goto out_free;
	}

	memset(info, 0, sizeof(*info));
	for (i = 0; i < dev->eps_num; i++) {
		ep = &dev->eps[i];
		strscpy(&info->eps[i].name[0], ep->ep->name,
				USB_RAW_EP_NAME_MAX);
		info->eps[i].addr = ep->addr;
		fill_ep_caps(&ep->ep->caps, &info->eps[i].caps);
		fill_ep_limits(ep->ep, &info->eps[i].limits);
	}
	ret = dev->eps_num;
	spin_unlock_irqrestore(&dev->lock, flags);

	if (copy_to_user((void __user *)value, info, sizeof(*info)))
		ret = -EFAULT;

out_free:
	kfree(info);
out:
	return ret;
}

static long raw_ioctl(struct file *fd, unsigned int cmd, unsigned long value)
{
	struct raw_dev *dev = fd->private_data;
@@ -1069,6 +1236,24 @@ static long raw_ioctl(struct file *fd, unsigned int cmd, unsigned long value)
	case USB_RAW_IOCTL_VBUS_DRAW:
		ret = raw_ioctl_vbus_draw(dev, value);
		break;
	case USB_RAW_IOCTL_EPS_INFO:
		ret = raw_ioctl_eps_info(dev, value);
		break;
	case USB_RAW_IOCTL_EP0_STALL:
		ret = raw_ioctl_ep0_stall(dev, value);
		break;
	case USB_RAW_IOCTL_EP_SET_HALT:
		ret = raw_ioctl_ep_set_clear_halt_wedge(
					dev, value, true, true);
		break;
	case USB_RAW_IOCTL_EP_CLEAR_HALT:
		ret = raw_ioctl_ep_set_clear_halt_wedge(
					dev, value, false, true);
		break;
	case USB_RAW_IOCTL_EP_SET_WEDGE:
		ret = raw_ioctl_ep_set_clear_halt_wedge(
					dev, value, true, false);
		break;
	default:
		ret = -EINVAL;
	}
+2 −2
Original line number Diff line number Diff line
@@ -185,7 +185,7 @@ static int regs_dbg_release(struct inode *inode, struct file *file)
	return 0;
}

const struct file_operations queue_dbg_fops = {
static const struct file_operations queue_dbg_fops = {
	.owner		= THIS_MODULE,
	.open		= queue_dbg_open,
	.llseek		= no_llseek,
@@ -193,7 +193,7 @@ const struct file_operations queue_dbg_fops = {
	.release	= queue_dbg_release,
};

const struct file_operations regs_dbg_fops = {
static const struct file_operations regs_dbg_fops = {
	.owner		= THIS_MODULE,
	.open		= regs_dbg_open,
	.llseek		= generic_file_llseek,
+2 −2
Original line number Diff line number Diff line
@@ -276,7 +276,7 @@ static const struct file_operations mtu3_ep_fops = {
	.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("byte-sell", U3D_SSUSB_PRB_CTRL1),
	dump_prb_reg("byte-selh", U3D_SSUSB_PRB_CTRL2),
@@ -349,7 +349,7 @@ static const struct file_operations mtu3_probe_fops = {
static void mtu3_debugfs_create_prb_files(struct mtu3 *mtu)
{
	struct ssusb_mtk *ssusb = mtu->ssusb;
	struct debugfs_reg32 *regs;
	const struct debugfs_reg32 *regs;
	struct dentry *dir_prb;
	int i;

Loading