Loading drivers/hwtracing/coresight/coresight-byte-cntr.c +147 −55 Original line number Diff line number Diff line Loading @@ -11,6 +11,7 @@ #include <linux/delay.h> #include <linux/uaccess.h> #include <linux/usb/usb_qdss.h> #include <linux/time.h> #include "coresight-byte-cntr.h" #include "coresight-priv.h" Loading @@ -19,6 +20,7 @@ #define USB_BLK_SIZE 65536 #define USB_SG_NUM (USB_BLK_SIZE / PAGE_SIZE) #define USB_BUF_NUM 255 #define USB_TIME_OUT (5 * HZ) static struct tmc_drvdata *tmcdrvdata; Loading Loading @@ -315,71 +317,158 @@ static int byte_cntr_register_chardev(struct byte_cntr *byte_cntr_data) return ret; } static int usb_transfer_small_packet(struct qdss_request *usb_req, struct byte_cntr *drvdata, size_t *small_size) { int ret = 0; struct etr_buf *etr_buf = tmcdrvdata->etr_buf; size_t req_size, actual; long w_offset; w_offset = tmc_sg_get_rwp_offset(tmcdrvdata); req_size = ((w_offset < drvdata->offset) ? etr_buf->size : 0) + w_offset - drvdata->offset; req_size = (req_size < USB_BLK_SIZE) ? req_size : USB_BLK_SIZE; while (req_size > 0) { usb_req = devm_kzalloc(tmcdrvdata->dev, sizeof(*usb_req), GFP_KERNEL); if (!usb_req) { ret = -EFAULT; goto out; } actual = tmc_etr_buf_get_data(etr_buf, drvdata->offset, req_size, &usb_req->buf); usb_req->length = actual; drvdata->usb_req = usb_req; req_size -= actual; if ((drvdata->offset + actual) >= tmcdrvdata->size) drvdata->offset = 0; else drvdata->offset += actual; *small_size += actual; if (atomic_read(&drvdata->usb_free_buf) > 0) { ret = usb_qdss_write(tmcdrvdata->usbch, usb_req); if (ret) { devm_kfree(tmcdrvdata->dev, usb_req); usb_req = NULL; drvdata->usb_req = NULL; dev_err(tmcdrvdata->dev, "Write data failed:%d\n", ret); goto out; } atomic_dec(&drvdata->usb_free_buf); } else { dev_dbg(tmcdrvdata->dev, "Drop data, offset = %d, len = %d\n", drvdata->offset, req_size); devm_kfree(tmcdrvdata->dev, usb_req); drvdata->usb_req = NULL; } } out: return ret; } static void usb_read_work_fn(struct work_struct *work) { int ret, i, seq = 0; struct qdss_request *usb_req = NULL; struct etr_buf *etr_buf = tmcdrvdata->etr_buf; size_t actual, req_size; size_t actual, req_size, req_sg_num, small_size = 0; char *buf; struct byte_cntr *drvdata = container_of(work, struct byte_cntr, read_work); while (tmcdrvdata->enable && tmcdrvdata->out_mode == TMC_ETR_OUT_MODE_USB) { if (!atomic_read(&drvdata->irq_cnt)) { ret = wait_event_interruptible(drvdata->usb_wait_wq, ret = wait_event_interruptible_timeout( drvdata->usb_wait_wq, atomic_read(&drvdata->irq_cnt) > 0 || !tmcdrvdata->enable || tmcdrvdata->out_mode != TMC_ETR_OUT_MODE_USB || !drvdata->read_active); || !drvdata->read_active, USB_TIME_OUT); if (ret == -ERESTARTSYS || !tmcdrvdata->enable || tmcdrvdata->out_mode != TMC_ETR_OUT_MODE_USB || !drvdata->read_active) break; if (ret == 0) { ret = usb_transfer_small_packet(usb_req, drvdata, &small_size); if (ret && ret != -EAGAIN) return; continue; } } req_size = USB_BLK_SIZE; req_size = USB_BLK_SIZE - small_size; small_size = 0; if (req_size > 0) { seq++; usb_req = devm_kzalloc(tmcdrvdata->dev, sizeof(*usb_req), GFP_KERNEL); req_sg_num = (req_size - 1) / PAGE_SIZE + 1; usb_req = devm_kzalloc(tmcdrvdata->dev, sizeof(*usb_req), GFP_KERNEL); if (!usb_req) return; usb_req->sg = devm_kzalloc(tmcdrvdata->dev, sizeof(*(usb_req->sg)) * USB_SG_NUM, GFP_KERNEL); sizeof(*(usb_req->sg)) * req_sg_num, GFP_KERNEL); if (!usb_req->sg) { devm_kfree(tmcdrvdata->dev, usb_req->sg); devm_kfree(tmcdrvdata->dev, usb_req); usb_req = NULL; return; } usb_req->length = USB_BLK_SIZE; drvdata->usb_req = usb_req; for (i = 0; i < USB_SG_NUM; i++) { actual = tmc_etr_buf_get_data(etr_buf, drvdata->offset, for (i = 0; i < req_sg_num; i++) { actual = tmc_etr_buf_get_data(etr_buf, drvdata->offset, PAGE_SIZE, &buf); if (actual <= 0) { devm_kfree(tmcdrvdata->dev, usb_req->sg); devm_kfree(tmcdrvdata->dev, usb_req->sg); devm_kfree(tmcdrvdata->dev, usb_req); usb_req = NULL; dev_err(tmcdrvdata->dev, "No data in ETR\n"); return; } sg_set_buf(&usb_req->sg[i], buf, actual); if (i == 0) usb_req->buf = buf; req_size -= actual; if ((drvdata->offset + actual) >= tmcdrvdata->size) if (i == req_sg_num - 1) sg_mark_end(&usb_req->sg[i]); if ((drvdata->offset + actual) >= tmcdrvdata->size) drvdata->offset = 0; else drvdata->offset += actual; if (i == USB_SG_NUM - 1) sg_mark_end(&usb_req->sg[i]); } usb_req->length = req_size; drvdata->usb_req = usb_req; usb_req->num_sgs = i; if (atomic_read(&drvdata->usb_free_buf) > 0) { ret = usb_qdss_write(tmcdrvdata->usbch, drvdata->usb_req); if (ret) { devm_kfree(tmcdrvdata->dev, usb_req->sg); devm_kfree(tmcdrvdata->dev, usb_req->sg); devm_kfree(tmcdrvdata->dev, usb_req); usb_req = NULL; drvdata->usb_req = NULL; Loading @@ -400,6 +489,8 @@ static void usb_read_work_fn(struct work_struct *work) devm_kfree(tmcdrvdata->dev, usb_req); drvdata->usb_req = NULL; } } if (atomic_read(&drvdata->irq_cnt) > 0) atomic_dec(&drvdata->irq_cnt); } Loading @@ -412,6 +503,7 @@ static void usb_write_done(struct byte_cntr *drvdata, atomic_inc(&drvdata->usb_free_buf); if (d_req->status) pr_err_ratelimited("USB write failed err:%d\n", d_req->status); if (d_req->sg) devm_kfree(tmcdrvdata->dev, d_req->sg); devm_kfree(tmcdrvdata->dev, d_req); } Loading drivers/hwtracing/coresight/coresight-tmc-etr.c +14 −0 Original line number Diff line number Diff line Loading @@ -215,6 +215,20 @@ void tmc_free_sg_table(struct tmc_sg_table *sg_table) tmc_free_data_pages(sg_table); } long tmc_sg_get_rwp_offset(struct tmc_drvdata *drvdata) { struct etr_buf *etr_buf = drvdata->etr_buf; struct etr_sg_table *etr_table = etr_buf->private; struct tmc_sg_table *table = etr_table->sg_table; u64 rwp; long w_offset; rwp = tmc_read_rwp(drvdata); w_offset = tmc_sg_get_data_page_offset(table, rwp); return w_offset; } /* * Alloc pages for the table. Since this will be used by the device, * allocate the pages closer to the device (i.e, dev_to_node(dev) Loading drivers/hwtracing/coresight/coresight-tmc.h +1 −1 Original line number Diff line number Diff line Loading @@ -325,7 +325,7 @@ ssize_t tmc_etr_get_sysfs_trace(struct tmc_drvdata *drvdata, ssize_t tmc_etr_buf_get_data(struct etr_buf *etr_buf, u64 offset, size_t len, char **bufpp); int tmc_etr_switch_mode(struct tmc_drvdata *drvdata, const char *out_mode); long tmc_sg_get_rwp_offset(struct tmc_drvdata *drvdata); #define TMC_REG_PAIR(name, lo_off, hi_off) \ static inline u64 \ Loading Loading
drivers/hwtracing/coresight/coresight-byte-cntr.c +147 −55 Original line number Diff line number Diff line Loading @@ -11,6 +11,7 @@ #include <linux/delay.h> #include <linux/uaccess.h> #include <linux/usb/usb_qdss.h> #include <linux/time.h> #include "coresight-byte-cntr.h" #include "coresight-priv.h" Loading @@ -19,6 +20,7 @@ #define USB_BLK_SIZE 65536 #define USB_SG_NUM (USB_BLK_SIZE / PAGE_SIZE) #define USB_BUF_NUM 255 #define USB_TIME_OUT (5 * HZ) static struct tmc_drvdata *tmcdrvdata; Loading Loading @@ -315,71 +317,158 @@ static int byte_cntr_register_chardev(struct byte_cntr *byte_cntr_data) return ret; } static int usb_transfer_small_packet(struct qdss_request *usb_req, struct byte_cntr *drvdata, size_t *small_size) { int ret = 0; struct etr_buf *etr_buf = tmcdrvdata->etr_buf; size_t req_size, actual; long w_offset; w_offset = tmc_sg_get_rwp_offset(tmcdrvdata); req_size = ((w_offset < drvdata->offset) ? etr_buf->size : 0) + w_offset - drvdata->offset; req_size = (req_size < USB_BLK_SIZE) ? req_size : USB_BLK_SIZE; while (req_size > 0) { usb_req = devm_kzalloc(tmcdrvdata->dev, sizeof(*usb_req), GFP_KERNEL); if (!usb_req) { ret = -EFAULT; goto out; } actual = tmc_etr_buf_get_data(etr_buf, drvdata->offset, req_size, &usb_req->buf); usb_req->length = actual; drvdata->usb_req = usb_req; req_size -= actual; if ((drvdata->offset + actual) >= tmcdrvdata->size) drvdata->offset = 0; else drvdata->offset += actual; *small_size += actual; if (atomic_read(&drvdata->usb_free_buf) > 0) { ret = usb_qdss_write(tmcdrvdata->usbch, usb_req); if (ret) { devm_kfree(tmcdrvdata->dev, usb_req); usb_req = NULL; drvdata->usb_req = NULL; dev_err(tmcdrvdata->dev, "Write data failed:%d\n", ret); goto out; } atomic_dec(&drvdata->usb_free_buf); } else { dev_dbg(tmcdrvdata->dev, "Drop data, offset = %d, len = %d\n", drvdata->offset, req_size); devm_kfree(tmcdrvdata->dev, usb_req); drvdata->usb_req = NULL; } } out: return ret; } static void usb_read_work_fn(struct work_struct *work) { int ret, i, seq = 0; struct qdss_request *usb_req = NULL; struct etr_buf *etr_buf = tmcdrvdata->etr_buf; size_t actual, req_size; size_t actual, req_size, req_sg_num, small_size = 0; char *buf; struct byte_cntr *drvdata = container_of(work, struct byte_cntr, read_work); while (tmcdrvdata->enable && tmcdrvdata->out_mode == TMC_ETR_OUT_MODE_USB) { if (!atomic_read(&drvdata->irq_cnt)) { ret = wait_event_interruptible(drvdata->usb_wait_wq, ret = wait_event_interruptible_timeout( drvdata->usb_wait_wq, atomic_read(&drvdata->irq_cnt) > 0 || !tmcdrvdata->enable || tmcdrvdata->out_mode != TMC_ETR_OUT_MODE_USB || !drvdata->read_active); || !drvdata->read_active, USB_TIME_OUT); if (ret == -ERESTARTSYS || !tmcdrvdata->enable || tmcdrvdata->out_mode != TMC_ETR_OUT_MODE_USB || !drvdata->read_active) break; if (ret == 0) { ret = usb_transfer_small_packet(usb_req, drvdata, &small_size); if (ret && ret != -EAGAIN) return; continue; } } req_size = USB_BLK_SIZE; req_size = USB_BLK_SIZE - small_size; small_size = 0; if (req_size > 0) { seq++; usb_req = devm_kzalloc(tmcdrvdata->dev, sizeof(*usb_req), GFP_KERNEL); req_sg_num = (req_size - 1) / PAGE_SIZE + 1; usb_req = devm_kzalloc(tmcdrvdata->dev, sizeof(*usb_req), GFP_KERNEL); if (!usb_req) return; usb_req->sg = devm_kzalloc(tmcdrvdata->dev, sizeof(*(usb_req->sg)) * USB_SG_NUM, GFP_KERNEL); sizeof(*(usb_req->sg)) * req_sg_num, GFP_KERNEL); if (!usb_req->sg) { devm_kfree(tmcdrvdata->dev, usb_req->sg); devm_kfree(tmcdrvdata->dev, usb_req); usb_req = NULL; return; } usb_req->length = USB_BLK_SIZE; drvdata->usb_req = usb_req; for (i = 0; i < USB_SG_NUM; i++) { actual = tmc_etr_buf_get_data(etr_buf, drvdata->offset, for (i = 0; i < req_sg_num; i++) { actual = tmc_etr_buf_get_data(etr_buf, drvdata->offset, PAGE_SIZE, &buf); if (actual <= 0) { devm_kfree(tmcdrvdata->dev, usb_req->sg); devm_kfree(tmcdrvdata->dev, usb_req->sg); devm_kfree(tmcdrvdata->dev, usb_req); usb_req = NULL; dev_err(tmcdrvdata->dev, "No data in ETR\n"); return; } sg_set_buf(&usb_req->sg[i], buf, actual); if (i == 0) usb_req->buf = buf; req_size -= actual; if ((drvdata->offset + actual) >= tmcdrvdata->size) if (i == req_sg_num - 1) sg_mark_end(&usb_req->sg[i]); if ((drvdata->offset + actual) >= tmcdrvdata->size) drvdata->offset = 0; else drvdata->offset += actual; if (i == USB_SG_NUM - 1) sg_mark_end(&usb_req->sg[i]); } usb_req->length = req_size; drvdata->usb_req = usb_req; usb_req->num_sgs = i; if (atomic_read(&drvdata->usb_free_buf) > 0) { ret = usb_qdss_write(tmcdrvdata->usbch, drvdata->usb_req); if (ret) { devm_kfree(tmcdrvdata->dev, usb_req->sg); devm_kfree(tmcdrvdata->dev, usb_req->sg); devm_kfree(tmcdrvdata->dev, usb_req); usb_req = NULL; drvdata->usb_req = NULL; Loading @@ -400,6 +489,8 @@ static void usb_read_work_fn(struct work_struct *work) devm_kfree(tmcdrvdata->dev, usb_req); drvdata->usb_req = NULL; } } if (atomic_read(&drvdata->irq_cnt) > 0) atomic_dec(&drvdata->irq_cnt); } Loading @@ -412,6 +503,7 @@ static void usb_write_done(struct byte_cntr *drvdata, atomic_inc(&drvdata->usb_free_buf); if (d_req->status) pr_err_ratelimited("USB write failed err:%d\n", d_req->status); if (d_req->sg) devm_kfree(tmcdrvdata->dev, d_req->sg); devm_kfree(tmcdrvdata->dev, d_req); } Loading
drivers/hwtracing/coresight/coresight-tmc-etr.c +14 −0 Original line number Diff line number Diff line Loading @@ -215,6 +215,20 @@ void tmc_free_sg_table(struct tmc_sg_table *sg_table) tmc_free_data_pages(sg_table); } long tmc_sg_get_rwp_offset(struct tmc_drvdata *drvdata) { struct etr_buf *etr_buf = drvdata->etr_buf; struct etr_sg_table *etr_table = etr_buf->private; struct tmc_sg_table *table = etr_table->sg_table; u64 rwp; long w_offset; rwp = tmc_read_rwp(drvdata); w_offset = tmc_sg_get_data_page_offset(table, rwp); return w_offset; } /* * Alloc pages for the table. Since this will be used by the device, * allocate the pages closer to the device (i.e, dev_to_node(dev) Loading
drivers/hwtracing/coresight/coresight-tmc.h +1 −1 Original line number Diff line number Diff line Loading @@ -325,7 +325,7 @@ ssize_t tmc_etr_get_sysfs_trace(struct tmc_drvdata *drvdata, ssize_t tmc_etr_buf_get_data(struct etr_buf *etr_buf, u64 offset, size_t len, char **bufpp); int tmc_etr_switch_mode(struct tmc_drvdata *drvdata, const char *out_mode); long tmc_sg_get_rwp_offset(struct tmc_drvdata *drvdata); #define TMC_REG_PAIR(name, lo_off, hi_off) \ static inline u64 \ Loading