Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 02765034 authored by qctecmdr's avatar qctecmdr Committed by Gerrit - the friendly Code Review server
Browse files

Merge "usb: gadget: f_mtp: Add ipc logging for mtp driver"

parents 30109ba5 4a6e5835
Loading
Loading
Loading
Loading
+80 −51
Original line number Diff line number Diff line
@@ -32,6 +32,7 @@
#include <linux/file.h>
#include <linux/device.h>
#include <linux/miscdevice.h>
#include <linux/ipc_logging.h>

#include <linux/usb.h>
#include <linux/usb_usual.h>
@@ -42,6 +43,18 @@

#include "configfs.h"

#define NUM_PAGES	10 /* # of pages for ipc logging */

#ifdef CONFIG_DYNAMIC_DEBUG
#define mtp_log(fmt, ...) do { \
	ipc_log_string(_mtp_ipc_log, "%s: " fmt,  __func__, ##__VA_ARGS__); \
	dynamic_pr_debug("%s: " fmt, __func__, ##__VA_ARGS__); \
} while (0)
#else
#define mtp_log(fmt, ...) \
	ipc_log_string(_mtp_ipc_log, "%s: " fmt,  __func__, ##__VA_ARGS__)
#endif

#define MTP_RX_BUFFER_INIT_SIZE    1048576
#define MTP_TX_BUFFER_INIT_SIZE    1048576
#define MTP_BULK_BUFFER_SIZE       16384
@@ -140,6 +153,8 @@ struct mtp_dev {
	struct mutex  read_mutex;
};

static void *_mtp_ipc_log;

static struct usb_interface_descriptor mtp_interface_desc = {
	.bLength                = USB_DT_INTERFACE_SIZE,
	.bDescriptorType        = USB_DT_INTERFACE,
@@ -499,32 +514,32 @@ static int mtp_create_bulk_endpoints(struct mtp_dev *dev,
	struct usb_ep *ep;
	int i;

	DBG(cdev, "create_bulk_endpoints dev: %pK\n", dev);
	mtp_log("dev: %pK\n", dev);

	ep = usb_ep_autoconfig(cdev->gadget, in_desc);
	if (!ep) {
		DBG(cdev, "usb_ep_autoconfig for ep_in failed\n");
		mtp_log("usb_ep_autoconfig for ep_in failed\n");
		return -ENODEV;
	}
	DBG(cdev, "usb_ep_autoconfig for ep_in got %s\n", ep->name);
	mtp_log("usb_ep_autoconfig for ep_in got %s\n", ep->name);
	ep->driver_data = dev;		/* claim the endpoint */
	dev->ep_in = ep;

	ep = usb_ep_autoconfig(cdev->gadget, out_desc);
	if (!ep) {
		DBG(cdev, "usb_ep_autoconfig for ep_out failed\n");
		mtp_log("usb_ep_autoconfig for ep_out failed\n");
		return -ENODEV;
	}
	DBG(cdev, "usb_ep_autoconfig for mtp ep_out got %s\n", ep->name);
	mtp_log("usb_ep_autoconfig for mtp ep_out got %s\n", ep->name);
	ep->driver_data = dev;		/* claim the endpoint */
	dev->ep_out = ep;

	ep = usb_ep_autoconfig(cdev->gadget, intr_desc);
	if (!ep) {
		DBG(cdev, "usb_ep_autoconfig for ep_intr failed\n");
		mtp_log("usb_ep_autoconfig for ep_intr failed\n");
		return -ENODEV;
	}
	DBG(cdev, "usb_ep_autoconfig for mtp ep_intr got %s\n", ep->name);
	mtp_log("usb_ep_autoconfig for mtp ep_intr got %s\n", ep->name);
	ep->driver_data = dev;		/* claim the endpoint */
	dev->ep_intr = ep;

@@ -592,10 +607,10 @@ static ssize_t mtp_read(struct file *fp, char __user *buf,
	ssize_t r = count, xfer, len;
	int ret = 0;

	DBG(cdev, "%s(%zu) state:%d\n", __func__, count, dev->state);
	mtp_log("(%zu) state:%d\n", count, dev->state);

	/* we will block until we're online */
	DBG(cdev, "mtp_read: waiting for online state\n");
	mtp_log("waiting for online state\n");
	ret = wait_event_interruptible(dev->read_wq,
		dev->state != STATE_OFFLINE);
	if (ret < 0) {
@@ -652,7 +667,7 @@ static ssize_t mtp_read(struct file *fp, char __user *buf,
		r = -EIO;
		goto done;
	} else {
		DBG(cdev, "rx %pK queue\n", req);
		mtp_log("rx %pK queue\n", req);
	}

	/* wait for a request to complete */
@@ -678,7 +693,7 @@ static ssize_t mtp_read(struct file *fp, char __user *buf,
		if (req->actual == 0)
			goto requeue_req;

		DBG(cdev, "rx %pK %d\n", req, req->actual);
		mtp_log("rx %pK %d\n", req, req->actual);
		xfer = (req->actual < count) ? req->actual : count;
		r = xfer;
		if (copy_to_user(buf, req->buf, xfer))
@@ -695,7 +710,7 @@ static ssize_t mtp_read(struct file *fp, char __user *buf,
		dev->state = STATE_READY;
	spin_unlock_irq(&dev->lock);

	DBG(cdev, "%s returning %zd state:%d\n", __func__, r, dev->state);
	mtp_log("returning %zd state:%d\n", r, dev->state);
	return r;
}

@@ -703,14 +718,13 @@ static ssize_t mtp_write(struct file *fp, const char __user *buf,
	size_t count, loff_t *pos)
{
	struct mtp_dev *dev = fp->private_data;
	struct usb_composite_dev *cdev = dev->cdev;
	struct usb_request *req = 0;
	ssize_t r = count;
	unsigned xfer;
	int sendZLP = 0;
	int ret;

	DBG(cdev, "%s(%zu) state:%d\n", __func__, count, dev->state);
	mtp_log("(%zu) state:%d\n", count, dev->state);

	spin_lock_irq(&dev->lock);
	if (dev->state == STATE_CANCELED) {
@@ -738,7 +752,7 @@ static ssize_t mtp_write(struct file *fp, const char __user *buf,
			sendZLP = 0;

		if (dev->state != STATE_BUSY) {
			DBG(cdev, "mtp_write dev->error\n");
			mtp_log("dev->error\n");
			r = -EIO;
			break;
		}
@@ -749,8 +763,8 @@ static ssize_t mtp_write(struct file *fp, const char __user *buf,
			((req = mtp_req_get(dev, &dev->tx_idle))
				|| dev->state != STATE_BUSY));
		if (!req) {
			DBG(cdev, "%s request NULL ret:%d state:%d\n",
				__func__, ret, dev->state);
			mtp_log("request NULL ret:%d state:%d\n",
				ret, dev->state);
			r = ret;
			break;
		}
@@ -767,7 +781,7 @@ static ssize_t mtp_write(struct file *fp, const char __user *buf,
		req->length = xfer;
		ret = usb_ep_queue(dev->ep_in, req, GFP_KERNEL);
		if (ret < 0) {
			DBG(cdev, "mtp_write: xfer error %d\n", ret);
			mtp_log("xfer error %d\n", ret);
			r = -EIO;
			break;
		}
@@ -789,7 +803,7 @@ static ssize_t mtp_write(struct file *fp, const char __user *buf,
		dev->state = STATE_READY;
	spin_unlock_irq(&dev->lock);

	DBG(cdev, "%s returning %zd state:%d\n", __func__, r, dev->state);
	mtp_log("returning %zd state:%d\n", r, dev->state);
	return r;
}

@@ -798,7 +812,6 @@ static void send_file_work(struct work_struct *data)
{
	struct mtp_dev *dev = container_of(data, struct mtp_dev,
						send_file_work);
	struct usb_composite_dev *cdev = dev->cdev;
	struct usb_request *req = 0;
	struct mtp_data_header *header;
	struct file *filp;
@@ -815,7 +828,7 @@ static void send_file_work(struct work_struct *data)
	offset = dev->xfer_file_offset;
	count = dev->xfer_file_length;

	DBG(cdev, "send_file_work(%lld %lld)\n", offset, count);
	mtp_log("(%lld %lld)\n", offset, count);

	if (dev->xfer_send_header) {
		hdr_size = sizeof(struct mtp_data_header);
@@ -845,8 +858,7 @@ static void send_file_work(struct work_struct *data)
			break;
		}
		if (!req) {
			DBG(cdev,
				"%s request NULL ret:%d state:%d\n", __func__,
			mtp_log("request NULL ret:%d state:%d\n",
				ret, dev->state);
			r = ret;
			break;
@@ -889,7 +901,7 @@ static void send_file_work(struct work_struct *data)
		req->length = xfer;
		ret = usb_ep_queue(dev->ep_in, req, GFP_KERNEL);
		if (ret < 0) {
			DBG(cdev, "send_file_work: xfer error %d\n", ret);
			mtp_log("xfer error %d\n", ret);
			if (dev->state != STATE_OFFLINE)
				dev->state = STATE_ERROR;
			r = -EIO;
@@ -905,7 +917,7 @@ static void send_file_work(struct work_struct *data)
	if (req)
		mtp_req_put(dev, &dev->tx_idle, req);

	DBG(cdev, "%s returning %d state:%d\n", __func__, r, dev->state);
	mtp_log("returning %d state:%d\n", r, dev->state);
	/* write the result */
	dev->xfer_result = r;
	smp_wmb();
@@ -916,7 +928,6 @@ static void receive_file_work(struct work_struct *data)
{
	struct mtp_dev *dev = container_of(data, struct mtp_dev,
						receive_file_work);
	struct usb_composite_dev *cdev = dev->cdev;
	struct usb_request *read_req = NULL, *write_req = NULL;
	struct file *filp;
	loff_t offset;
@@ -931,9 +942,9 @@ static void receive_file_work(struct work_struct *data)
	offset = dev->xfer_file_offset;
	count = dev->xfer_file_length;

	DBG(cdev, "receive_file_work(%lld)\n", count);
	mtp_log("(%lld)\n", count);
	if (!IS_ALIGNED(count, dev->ep_out->maxpacket))
		DBG(cdev, "%s- count(%lld) not multiple of mtu(%d)\n", __func__,
		mtp_log("- count(%lld) not multiple of mtu(%d)\n",
						count, dev->ep_out->maxpacket);

	while (count > 0 || write_req) {
@@ -963,7 +974,7 @@ static void receive_file_work(struct work_struct *data)
		}

		if (write_req) {
			DBG(cdev, "rx %pK %d\n", write_req, write_req->actual);
			mtp_log("rx %pK %d\n", write_req, write_req->actual);
			start_time = ktime_get();
			mutex_lock(&dev->read_mutex);
			if (dev->state == STATE_OFFLINE) {
@@ -973,7 +984,7 @@ static void receive_file_work(struct work_struct *data)
			}
			ret = vfs_write(filp, write_req->buf, write_req->actual,
				&offset);
			DBG(cdev, "vfs_write %d\n", ret);
			mtp_log("vfs_write %d\n", ret);
			if (ret != write_req->actual) {
				r = -EIO;
				mutex_unlock(&dev->read_mutex);
@@ -1031,7 +1042,7 @@ static void receive_file_work(struct work_struct *data)
				 * short packet is used to signal EOF for
				 * sizes > 4 gig
				 */
				DBG(cdev, "got short packet\n");
				mtp_log("got short packet\n");
				count = 0;
			}

@@ -1041,7 +1052,7 @@ static void receive_file_work(struct work_struct *data)
		}
	}

	DBG(cdev, "receive_file_work returning %d\n", r);
	mtp_log("returning %d\n", r);
	/* write the result */
	dev->xfer_result = r;
	smp_wmb();
@@ -1053,7 +1064,7 @@ static int mtp_send_event(struct mtp_dev *dev, struct mtp_event *event)
	int ret;
	int length = event->length;

	DBG(dev->cdev, "mtp_send_event(%zu)\n", event->length);
	mtp_log("(%zu)\n", event->length);

	if (length < 0 || length > INTR_BUFFER_SIZE)
		return -EINVAL;
@@ -1087,7 +1098,7 @@ static long mtp_send_receive_ioctl(struct file *fp, unsigned int code,
	int ret = -EINVAL;

	if (mtp_lock(&dev->ioctl_excl)) {
		DBG(dev->cdev, "ioctl returning EBUSY state:%d\n", dev->state);
		mtp_log("ioctl returning EBUSY state:%d\n", dev->state);
		return -EBUSY;
	}

@@ -1155,7 +1166,7 @@ static long mtp_send_receive_ioctl(struct file *fp, unsigned int code,
	spin_unlock_irq(&dev->lock);
out:
	mtp_unlock(&dev->ioctl_excl);
	DBG(dev->cdev, "ioctl returning %d\n", ret);
	mtp_log("ioctl returning %d\n", ret);
	return ret;
}

@@ -1189,7 +1200,7 @@ static long mtp_ioctl(struct file *fp, unsigned int code, unsigned long value)
		mtp_unlock(&dev->ioctl_excl);
	break;
	default:
		DBG(dev->cdev, "unknown ioctl code: %d\n", code);
		mtp_log("unknown ioctl code: %d\n", code);
	}
fail:
	return ret;
@@ -1229,7 +1240,7 @@ static long compat_mtp_ioctl(struct file *fp, unsigned int code,
		cmd = MTP_SEND_EVENT;
		break;
	default:
		DBG(dev->cdev, "unknown compat_ioctl code: %d\n", code);
		mtp_log("unknown compat_ioctl code: %d\n", code);
		ret = -ENOIOCTLCMD;
		goto fail;
	}
@@ -1319,8 +1330,7 @@ static int mtp_ctrlrequest(struct usb_composite_dev *cdev,
	u16	w_length = le16_to_cpu(ctrl->wLength);
	unsigned long	flags;

	VDBG(cdev, "mtp_ctrlrequest "
			"%02x.%02x v%04x i%04x l%u\n",
	mtp_log("%02x.%02x v%04x i%04x l%u\n",
			ctrl->bRequestType, ctrl->bRequest,
			w_value, w_index, w_length);

@@ -1335,7 +1345,7 @@ static int mtp_ctrlrequest(struct usb_composite_dev *cdev,
		memcpy(cdev->req->buf, mtp_os_string, value);
	} else if ((ctrl->bRequestType & USB_TYPE_MASK) == USB_TYPE_VENDOR) {
		/* Handle MTP OS descriptor */
		DBG(cdev, "vendor request: %d index: %d value: %d length: %d\n",
		mtp_log("vendor request: %d index: %d value: %d length: %d\n",
			ctrl->bRequest, w_index, w_value, w_length);

		if (ctrl->bRequest == 1
@@ -1353,12 +1363,12 @@ static int mtp_ctrlrequest(struct usb_composite_dev *cdev,
			}
		}
	} else if ((ctrl->bRequestType & USB_TYPE_MASK) == USB_TYPE_CLASS) {
		DBG(cdev, "class request: %d index: %d value: %d length: %d\n",
		mtp_log("class request: %d index: %d value: %d length: %d\n",
			ctrl->bRequest, w_index, w_value, w_length);

		if (ctrl->bRequest == MTP_REQ_CANCEL && w_index == 0
				&& w_value == 0) {
			DBG(cdev, "MTP_REQ_CANCEL\n");
			mtp_log("MTP_REQ_CANCEL\n");

			spin_lock_irqsave(&dev->lock, flags);
			if (dev->state == STATE_BUSY) {
@@ -1380,7 +1390,7 @@ static int mtp_ctrlrequest(struct usb_composite_dev *cdev,
			status->wLength =
				__constant_cpu_to_le16(sizeof(*status));

			DBG(cdev, "MTP_REQ_GET_DEVICE_STATUS\n");
			mtp_log("MTP_REQ_GET_DEVICE_STATUS\n");
			spin_lock_irqsave(&dev->lock, flags);
			/* device status is "busy" until we report
			 * the cancelation to userspace
@@ -1404,7 +1414,7 @@ static int mtp_ctrlrequest(struct usb_composite_dev *cdev,
		cdev->req->length = value;
		rc = usb_ep_queue(cdev->gadget->ep0, cdev->req, GFP_ATOMIC);
		if (rc < 0)
			ERROR(cdev, "%s: response queue error\n", __func__);
			pr_err("%s: response queue error\n", __func__);
	}
	return value;
}
@@ -1419,7 +1429,7 @@ mtp_function_bind(struct usb_configuration *c, struct usb_function *f)
	struct mtp_instance *fi_mtp;

	dev->cdev = cdev;
	DBG(cdev, "%s dev: %pK\n", __func__, dev);
	mtp_log("dev: %pK\n", dev);

	/* allocate interface ID(s) */
	id = usb_interface_id(c, f);
@@ -1474,7 +1484,7 @@ mtp_function_bind(struct usb_configuration *c, struct usb_function *f)
	}

	fi_mtp->func_inst.f = &dev->function;
	DBG(cdev, "%s speed %s: IN/%s, OUT/%s\n",
	mtp_log("%s speed %s: IN/%s, OUT/%s\n",
		gadget_is_superspeed(c->cdev->gadget) ? "super" :
		(gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full"),
		f->name, dev->ep_in->name, dev->ep_out->name);
@@ -1490,6 +1500,7 @@ mtp_function_unbind(struct usb_configuration *c, struct usb_function *f)
	int i;
	fi_mtp = container_of(f->fi, struct mtp_instance, func_inst);
	mtp_string_defs[INTERFACE_STRING_INDEX].id = 0;
	mtp_log("dev: %pK\n", dev);
	mutex_lock(&dev->read_mutex);
	while ((req = mtp_req_get(dev, &dev->tx_idle)))
		mtp_request_free(req, dev->ep_in);
@@ -1514,7 +1525,7 @@ static int mtp_function_set_alt(struct usb_function *f,
	struct usb_composite_dev *cdev = f->config->cdev;
	int ret;

	DBG(cdev, "mtp_function_set_alt intf: %d alt: %d\n", intf, alt);
	mtp_log("%d alt: %d\n", intf, alt);

	ret = config_ep_by_speed(cdev->gadget, f, dev->ep_in);
	if (ret)
@@ -1554,9 +1565,8 @@ static int mtp_function_set_alt(struct usb_function *f,
static void mtp_function_disable(struct usb_function *f)
{
	struct mtp_dev	*dev = func_to_mtp(f);
	struct usb_composite_dev	*cdev = dev->cdev;

	DBG(cdev, "mtp_function_disable\n");
	mtp_log("\n");
	spin_lock_irq(&dev->lock);
	dev->state = STATE_OFFLINE;
	spin_unlock_irq(&dev->lock);
@@ -1567,7 +1577,7 @@ static void mtp_function_disable(struct usb_function *f)
	/* readers may be blocked waiting for us to go online */
	wake_up(&dev->read_wq);

	VDBG(cdev, "%s disabled\n", dev->function.name);
	mtp_log("%s disabled\n", dev->function.name);
}

static int debug_mtp_read_stats(struct seq_file *s, void *unused)
@@ -1917,5 +1927,24 @@ static struct usb_function *mtp_alloc(struct usb_function_instance *fi)
	return function_alloc_mtp_ptp(fi, true);
}

DECLARE_USB_FUNCTION_INIT(mtp, mtp_alloc_inst, mtp_alloc);
DECLARE_USB_FUNCTION(mtp, mtp_alloc_inst, mtp_alloc);

static int mtp_init(void)
{
	_mtp_ipc_log = ipc_log_context_create(NUM_PAGES, "usb_mtp", 0);
	if (IS_ERR_OR_NULL(_mtp_ipc_log))
		_mtp_ipc_log =  NULL;

	return usb_function_register(&mtpusb_func);
}
module_init(mtp_init);

static void __exit mtp_exit(void)
{
	ipc_log_context_destroy(_mtp_ipc_log);
	usb_function_unregister(&mtpusb_func);
}
module_exit(mtp_exit);

MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("MTP function driver");