Loading drivers/usb/gadget/function/f_mtp.c +142 −1 Original line number Original line Diff line number Diff line Loading @@ -26,6 +26,8 @@ #include <linux/err.h> #include <linux/err.h> #include <linux/interrupt.h> #include <linux/interrupt.h> #include <linux/seq_file.h> #include <linux/debugfs.h> #include <linux/types.h> #include <linux/types.h> #include <linux/file.h> #include <linux/file.h> #include <linux/device.h> #include <linux/device.h> Loading Loading @@ -74,6 +76,8 @@ #define MTP_RESPONSE_DEVICE_BUSY 0x2019 #define MTP_RESPONSE_DEVICE_BUSY 0x2019 #define DRIVER_NAME "mtp" #define DRIVER_NAME "mtp" #define MAX_ITERATION 100 unsigned int mtp_rx_req_len = MTP_BULK_BUFFER_SIZE; unsigned int mtp_rx_req_len = MTP_BULK_BUFFER_SIZE; module_param(mtp_rx_req_len, uint, 0644); module_param(mtp_rx_req_len, uint, 0644); Loading Loading @@ -123,6 +127,14 @@ struct mtp_dev { uint16_t xfer_command; uint16_t xfer_command; uint32_t xfer_transaction_id; uint32_t xfer_transaction_id; int xfer_result; int xfer_result; struct { unsigned long vfs_rbytes; unsigned long vfs_wbytes; unsigned int vfs_rtime; unsigned int vfs_wtime; } perf[MAX_ITERATION]; unsigned int dbg_read_index; unsigned int dbg_write_index; }; }; static struct usb_interface_descriptor mtp_interface_desc = { static struct usb_interface_descriptor mtp_interface_desc = { Loading Loading @@ -784,6 +796,7 @@ static void send_file_work(struct work_struct *data) int xfer, ret, hdr_size; int xfer, ret, hdr_size; int r = 0; int r = 0; int sendZLP = 0; int sendZLP = 0; ktime_t start_time; /* read our parameters */ /* read our parameters */ smp_rmb(); smp_rmb(); Loading Loading @@ -844,14 +857,19 @@ static void send_file_work(struct work_struct *data) header->transaction_id = header->transaction_id = __cpu_to_le32(dev->xfer_transaction_id); __cpu_to_le32(dev->xfer_transaction_id); } } start_time = ktime_get(); ret = vfs_read(filp, req->buf + hdr_size, xfer - hdr_size, ret = vfs_read(filp, req->buf + hdr_size, xfer - hdr_size, &offset); &offset); if (ret < 0) { if (ret < 0) { r = ret; r = ret; break; break; } } xfer = ret + hdr_size; xfer = ret + hdr_size; dev->perf[dev->dbg_read_index].vfs_rtime = ktime_to_us(ktime_sub(ktime_get(), start_time)); dev->perf[dev->dbg_read_index].vfs_rbytes = xfer; dev->dbg_read_index = (dev->dbg_read_index + 1) % MAX_ITERATION; hdr_size = 0; hdr_size = 0; req->length = xfer; req->length = xfer; Loading Loading @@ -891,6 +909,7 @@ static void receive_file_work(struct work_struct *data) int64_t count; int64_t count; int ret, cur_buf = 0; int ret, cur_buf = 0; int r = 0; int r = 0; ktime_t start_time; /* read our parameters */ /* read our parameters */ smp_rmb(); smp_rmb(); Loading Loading @@ -924,6 +943,7 @@ static void receive_file_work(struct work_struct *data) if (write_req) { if (write_req) { DBG(cdev, "rx %p %d\n", write_req, write_req->actual); DBG(cdev, "rx %p %d\n", write_req, write_req->actual); start_time = ktime_get(); ret = vfs_write(filp, write_req->buf, write_req->actual, ret = vfs_write(filp, write_req->buf, write_req->actual, &offset); &offset); DBG(cdev, "vfs_write %d\n", ret); DBG(cdev, "vfs_write %d\n", ret); Loading @@ -933,6 +953,11 @@ static void receive_file_work(struct work_struct *data) dev->state = STATE_ERROR; dev->state = STATE_ERROR; break; break; } } dev->perf[dev->dbg_write_index].vfs_wtime = ktime_to_us(ktime_sub(ktime_get(), start_time)); dev->perf[dev->dbg_write_index].vfs_wbytes = ret; dev->dbg_write_index = (dev->dbg_write_index + 1) % MAX_ITERATION; write_req = NULL; write_req = NULL; } } Loading Loading @@ -1501,6 +1526,120 @@ static void mtp_function_disable(struct usb_function *f) VDBG(cdev, "%s disabled\n", dev->function.name); VDBG(cdev, "%s disabled\n", dev->function.name); } } static int debug_mtp_read_stats(struct seq_file *s, void *unused) { struct mtp_dev *dev = _mtp_dev; int i; unsigned long flags; unsigned int min, max = 0, sum = 0, iteration = 0; seq_puts(s, "\n=======================\n"); seq_puts(s, "MTP Write Stats:\n"); seq_puts(s, "\n=======================\n"); spin_lock_irqsave(&dev->lock, flags); min = dev->perf[0].vfs_wtime; for (i = 0; i < MAX_ITERATION; i++) { seq_printf(s, "vfs write: bytes:%ld\t\t time:%d\n", dev->perf[i].vfs_wbytes, dev->perf[i].vfs_wtime); if (dev->perf[i].vfs_wbytes == mtp_rx_req_len) { sum += dev->perf[i].vfs_wtime; if (min > dev->perf[i].vfs_wtime) min = dev->perf[i].vfs_wtime; if (max < dev->perf[i].vfs_wtime) max = dev->perf[i].vfs_wtime; iteration++; } } seq_printf(s, "vfs_write(time in usec) min:%d\t max:%d\t avg:%d\n", min, max, sum / iteration); min = max = sum = iteration = 0; seq_puts(s, "\n=======================\n"); seq_puts(s, "MTP Read Stats:\n"); seq_puts(s, "\n=======================\n"); min = dev->perf[0].vfs_rtime; for (i = 0; i < MAX_ITERATION; i++) { seq_printf(s, "vfs read: bytes:%ld\t\t time:%d\n", dev->perf[i].vfs_rbytes, dev->perf[i].vfs_rtime); if (dev->perf[i].vfs_rbytes == mtp_tx_req_len) { sum += dev->perf[i].vfs_rtime; if (min > dev->perf[i].vfs_rtime) min = dev->perf[i].vfs_rtime; if (max < dev->perf[i].vfs_rtime) max = dev->perf[i].vfs_rtime; iteration++; } } seq_printf(s, "vfs_read(time in usec) min:%d\t max:%d\t avg:%d\n", min, max, sum / iteration); spin_unlock_irqrestore(&dev->lock, flags); return 0; } static ssize_t debug_mtp_reset_stats(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { int clear_stats; unsigned long flags; struct mtp_dev *dev = _mtp_dev; if (buf == NULL) { pr_err("[%s] EINVAL\n", __func__); goto done; } if (kstrtoint(buf, 0, &clear_stats) || clear_stats != 0) { pr_err("Wrong value. To clear stats, enter value as 0.\n"); goto done; } spin_lock_irqsave(&dev->lock, flags); memset(&dev->perf[0], 0, MAX_ITERATION * sizeof(dev->perf[0])); dev->dbg_read_index = 0; dev->dbg_write_index = 0; spin_unlock_irqrestore(&dev->lock, flags); done: return count; } static int debug_mtp_open(struct inode *inode, struct file *file) { return single_open(file, debug_mtp_read_stats, inode->i_private); } static const struct file_operations debug_mtp_ops = { .open = debug_mtp_open, .read = seq_read, .write = debug_mtp_reset_stats, }; struct dentry *dent_mtp; static void mtp_debugfs_init(void) { struct dentry *dent_mtp_status; dent_mtp = debugfs_create_dir("usb_mtp", 0); if (!dent_mtp || IS_ERR(dent_mtp)) return; dent_mtp_status = debugfs_create_file("status", 0644, dent_mtp, 0, &debug_mtp_ops); if (!dent_mtp_status || IS_ERR(dent_mtp_status)) { debugfs_remove(dent_mtp); dent_mtp = NULL; return; } } static void mtp_debugfs_remove(void) { debugfs_remove_recursive(dent_mtp); } static int __mtp_setup(struct mtp_instance *fi_mtp) static int __mtp_setup(struct mtp_instance *fi_mtp) { { struct mtp_dev *dev; struct mtp_dev *dev; Loading Loading @@ -1537,6 +1676,7 @@ static int __mtp_setup(struct mtp_instance *fi_mtp) if (ret) if (ret) goto err2; goto err2; mtp_debugfs_init(); return 0; return 0; err2: err2: Loading @@ -1561,6 +1701,7 @@ static void mtp_cleanup(void) if (!dev) if (!dev) return; return; mtp_debugfs_remove(); misc_deregister(&mtp_device); misc_deregister(&mtp_device); destroy_workqueue(dev->wq); destroy_workqueue(dev->wq); _mtp_dev = NULL; _mtp_dev = NULL; Loading Loading
drivers/usb/gadget/function/f_mtp.c +142 −1 Original line number Original line Diff line number Diff line Loading @@ -26,6 +26,8 @@ #include <linux/err.h> #include <linux/err.h> #include <linux/interrupt.h> #include <linux/interrupt.h> #include <linux/seq_file.h> #include <linux/debugfs.h> #include <linux/types.h> #include <linux/types.h> #include <linux/file.h> #include <linux/file.h> #include <linux/device.h> #include <linux/device.h> Loading Loading @@ -74,6 +76,8 @@ #define MTP_RESPONSE_DEVICE_BUSY 0x2019 #define MTP_RESPONSE_DEVICE_BUSY 0x2019 #define DRIVER_NAME "mtp" #define DRIVER_NAME "mtp" #define MAX_ITERATION 100 unsigned int mtp_rx_req_len = MTP_BULK_BUFFER_SIZE; unsigned int mtp_rx_req_len = MTP_BULK_BUFFER_SIZE; module_param(mtp_rx_req_len, uint, 0644); module_param(mtp_rx_req_len, uint, 0644); Loading Loading @@ -123,6 +127,14 @@ struct mtp_dev { uint16_t xfer_command; uint16_t xfer_command; uint32_t xfer_transaction_id; uint32_t xfer_transaction_id; int xfer_result; int xfer_result; struct { unsigned long vfs_rbytes; unsigned long vfs_wbytes; unsigned int vfs_rtime; unsigned int vfs_wtime; } perf[MAX_ITERATION]; unsigned int dbg_read_index; unsigned int dbg_write_index; }; }; static struct usb_interface_descriptor mtp_interface_desc = { static struct usb_interface_descriptor mtp_interface_desc = { Loading Loading @@ -784,6 +796,7 @@ static void send_file_work(struct work_struct *data) int xfer, ret, hdr_size; int xfer, ret, hdr_size; int r = 0; int r = 0; int sendZLP = 0; int sendZLP = 0; ktime_t start_time; /* read our parameters */ /* read our parameters */ smp_rmb(); smp_rmb(); Loading Loading @@ -844,14 +857,19 @@ static void send_file_work(struct work_struct *data) header->transaction_id = header->transaction_id = __cpu_to_le32(dev->xfer_transaction_id); __cpu_to_le32(dev->xfer_transaction_id); } } start_time = ktime_get(); ret = vfs_read(filp, req->buf + hdr_size, xfer - hdr_size, ret = vfs_read(filp, req->buf + hdr_size, xfer - hdr_size, &offset); &offset); if (ret < 0) { if (ret < 0) { r = ret; r = ret; break; break; } } xfer = ret + hdr_size; xfer = ret + hdr_size; dev->perf[dev->dbg_read_index].vfs_rtime = ktime_to_us(ktime_sub(ktime_get(), start_time)); dev->perf[dev->dbg_read_index].vfs_rbytes = xfer; dev->dbg_read_index = (dev->dbg_read_index + 1) % MAX_ITERATION; hdr_size = 0; hdr_size = 0; req->length = xfer; req->length = xfer; Loading Loading @@ -891,6 +909,7 @@ static void receive_file_work(struct work_struct *data) int64_t count; int64_t count; int ret, cur_buf = 0; int ret, cur_buf = 0; int r = 0; int r = 0; ktime_t start_time; /* read our parameters */ /* read our parameters */ smp_rmb(); smp_rmb(); Loading Loading @@ -924,6 +943,7 @@ static void receive_file_work(struct work_struct *data) if (write_req) { if (write_req) { DBG(cdev, "rx %p %d\n", write_req, write_req->actual); DBG(cdev, "rx %p %d\n", write_req, write_req->actual); start_time = ktime_get(); ret = vfs_write(filp, write_req->buf, write_req->actual, ret = vfs_write(filp, write_req->buf, write_req->actual, &offset); &offset); DBG(cdev, "vfs_write %d\n", ret); DBG(cdev, "vfs_write %d\n", ret); Loading @@ -933,6 +953,11 @@ static void receive_file_work(struct work_struct *data) dev->state = STATE_ERROR; dev->state = STATE_ERROR; break; break; } } dev->perf[dev->dbg_write_index].vfs_wtime = ktime_to_us(ktime_sub(ktime_get(), start_time)); dev->perf[dev->dbg_write_index].vfs_wbytes = ret; dev->dbg_write_index = (dev->dbg_write_index + 1) % MAX_ITERATION; write_req = NULL; write_req = NULL; } } Loading Loading @@ -1501,6 +1526,120 @@ static void mtp_function_disable(struct usb_function *f) VDBG(cdev, "%s disabled\n", dev->function.name); VDBG(cdev, "%s disabled\n", dev->function.name); } } static int debug_mtp_read_stats(struct seq_file *s, void *unused) { struct mtp_dev *dev = _mtp_dev; int i; unsigned long flags; unsigned int min, max = 0, sum = 0, iteration = 0; seq_puts(s, "\n=======================\n"); seq_puts(s, "MTP Write Stats:\n"); seq_puts(s, "\n=======================\n"); spin_lock_irqsave(&dev->lock, flags); min = dev->perf[0].vfs_wtime; for (i = 0; i < MAX_ITERATION; i++) { seq_printf(s, "vfs write: bytes:%ld\t\t time:%d\n", dev->perf[i].vfs_wbytes, dev->perf[i].vfs_wtime); if (dev->perf[i].vfs_wbytes == mtp_rx_req_len) { sum += dev->perf[i].vfs_wtime; if (min > dev->perf[i].vfs_wtime) min = dev->perf[i].vfs_wtime; if (max < dev->perf[i].vfs_wtime) max = dev->perf[i].vfs_wtime; iteration++; } } seq_printf(s, "vfs_write(time in usec) min:%d\t max:%d\t avg:%d\n", min, max, sum / iteration); min = max = sum = iteration = 0; seq_puts(s, "\n=======================\n"); seq_puts(s, "MTP Read Stats:\n"); seq_puts(s, "\n=======================\n"); min = dev->perf[0].vfs_rtime; for (i = 0; i < MAX_ITERATION; i++) { seq_printf(s, "vfs read: bytes:%ld\t\t time:%d\n", dev->perf[i].vfs_rbytes, dev->perf[i].vfs_rtime); if (dev->perf[i].vfs_rbytes == mtp_tx_req_len) { sum += dev->perf[i].vfs_rtime; if (min > dev->perf[i].vfs_rtime) min = dev->perf[i].vfs_rtime; if (max < dev->perf[i].vfs_rtime) max = dev->perf[i].vfs_rtime; iteration++; } } seq_printf(s, "vfs_read(time in usec) min:%d\t max:%d\t avg:%d\n", min, max, sum / iteration); spin_unlock_irqrestore(&dev->lock, flags); return 0; } static ssize_t debug_mtp_reset_stats(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { int clear_stats; unsigned long flags; struct mtp_dev *dev = _mtp_dev; if (buf == NULL) { pr_err("[%s] EINVAL\n", __func__); goto done; } if (kstrtoint(buf, 0, &clear_stats) || clear_stats != 0) { pr_err("Wrong value. To clear stats, enter value as 0.\n"); goto done; } spin_lock_irqsave(&dev->lock, flags); memset(&dev->perf[0], 0, MAX_ITERATION * sizeof(dev->perf[0])); dev->dbg_read_index = 0; dev->dbg_write_index = 0; spin_unlock_irqrestore(&dev->lock, flags); done: return count; } static int debug_mtp_open(struct inode *inode, struct file *file) { return single_open(file, debug_mtp_read_stats, inode->i_private); } static const struct file_operations debug_mtp_ops = { .open = debug_mtp_open, .read = seq_read, .write = debug_mtp_reset_stats, }; struct dentry *dent_mtp; static void mtp_debugfs_init(void) { struct dentry *dent_mtp_status; dent_mtp = debugfs_create_dir("usb_mtp", 0); if (!dent_mtp || IS_ERR(dent_mtp)) return; dent_mtp_status = debugfs_create_file("status", 0644, dent_mtp, 0, &debug_mtp_ops); if (!dent_mtp_status || IS_ERR(dent_mtp_status)) { debugfs_remove(dent_mtp); dent_mtp = NULL; return; } } static void mtp_debugfs_remove(void) { debugfs_remove_recursive(dent_mtp); } static int __mtp_setup(struct mtp_instance *fi_mtp) static int __mtp_setup(struct mtp_instance *fi_mtp) { { struct mtp_dev *dev; struct mtp_dev *dev; Loading Loading @@ -1537,6 +1676,7 @@ static int __mtp_setup(struct mtp_instance *fi_mtp) if (ret) if (ret) goto err2; goto err2; mtp_debugfs_init(); return 0; return 0; err2: err2: Loading @@ -1561,6 +1701,7 @@ static void mtp_cleanup(void) if (!dev) if (!dev) return; return; mtp_debugfs_remove(); misc_deregister(&mtp_device); misc_deregister(&mtp_device); destroy_workqueue(dev->wq); destroy_workqueue(dev->wq); _mtp_dev = NULL; _mtp_dev = NULL; Loading