Loading drivers/hwtracing/coresight/coresight-byte-cntr.c +183 −5 Original line number Diff line number Diff line // SPDX-License-Identifier: GPL-2.0-only /* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. /* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. * * Description: CoreSight Trace Memory Controller driver */ Loading @@ -10,11 +10,15 @@ #include <linux/moduleparam.h> #include <linux/delay.h> #include <linux/uaccess.h> #include <linux/usb/usb_qdss.h> #include "coresight-byte-cntr.h" #include "coresight-priv.h" #include "coresight-tmc.h" #define USB_BLK_SIZE 65536 #define USB_BUF_NUM 255 static struct tmc_drvdata *tmcdrvdata; static void tmc_etr_read_bytes(struct byte_cntr *byte_cntr_data, loff_t *ppos, Loading @@ -39,10 +43,14 @@ static irqreturn_t etr_handler(int irq, void *data) { struct byte_cntr *byte_cntr_data = data; if (tmcdrvdata->out_mode == TMC_ETR_OUT_MODE_USB && byte_cntr_data->sw_usb) { atomic_inc(&byte_cntr_data->irq_cnt); wake_up(&byte_cntr_data->usb_wait_wq); } else if (tmcdrvdata->out_mode == TMC_ETR_OUT_MODE_MEM) { atomic_inc(&byte_cntr_data->irq_cnt); wake_up(&byte_cntr_data->wq); } return IRQ_HANDLED; } Loading Loading @@ -160,6 +168,45 @@ static int tmc_etr_byte_cntr_release(struct inode *in, struct file *fp) return 0; } int usb_bypass_start(struct byte_cntr *byte_cntr_data) { if (!byte_cntr_data) return -ENOMEM; mutex_lock(&byte_cntr_data->usb_bypass_lock); if (!tmcdrvdata->enable) { mutex_unlock(&byte_cntr_data->usb_bypass_lock); return -EINVAL; } atomic_set(&byte_cntr_data->usb_free_buf, USB_BUF_NUM); byte_cntr_data->offset = tmcdrvdata->etr_buf->offset; /* * IRQ is a '8- byte' counter and to observe interrupt at * 'block_size' bytes of data */ coresight_csr_set_byte_cntr(byte_cntr_data->csr, USB_BLK_SIZE / 8); atomic_set(&byte_cntr_data->irq_cnt, 0); mutex_unlock(&byte_cntr_data->usb_bypass_lock); return 0; } void usb_bypass_stop(struct byte_cntr *byte_cntr_data) { if (!byte_cntr_data) return; mutex_lock(&byte_cntr_data->usb_bypass_lock); wake_up(&byte_cntr_data->usb_wait_wq); coresight_csr_set_byte_cntr(byte_cntr_data->csr, 0); mutex_unlock(&byte_cntr_data->usb_bypass_lock); } EXPORT_SYMBOL(usb_bypass_stop); static int tmc_etr_byte_cntr_open(struct inode *in, struct file *fp) { struct byte_cntr *byte_cntr_data = Loading Loading @@ -244,6 +291,131 @@ static int byte_cntr_register_chardev(struct byte_cntr *byte_cntr_data) return ret; } static void usb_read_work_fn(struct work_struct *work) { int ret, seq = 0; struct qdss_request *usb_req = NULL; struct etr_buf *etr_buf = tmcdrvdata->etr_buf; size_t actual, req_size; 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, atomic_read(&drvdata->irq_cnt) > 0 || !tmcdrvdata->enable || tmcdrvdata->out_mode != TMC_ETR_OUT_MODE_USB); if (ret == -ERESTARTSYS || !tmcdrvdata->enable || tmcdrvdata->out_mode != TMC_ETR_OUT_MODE_USB) break; } req_size = USB_BLK_SIZE; while (req_size > 0) { seq++; usb_req = kzalloc(sizeof(*usb_req), GFP_KERNEL); if (!usb_req) return; actual = tmc_etr_buf_get_data(etr_buf, drvdata->offset, req_size, &usb_req->buf); if (actual <= 0) { kfree(usb_req); usb_req = NULL; dev_err(tmcdrvdata->dev, "No data in ETR\n"); break; } usb_req->length = actual; drvdata->usb_req = usb_req; req_size -= actual; if ((drvdata->offset + usb_req->length) >= tmcdrvdata->size) drvdata->offset = 0; else drvdata->offset += usb_req->length; if (atomic_read(&drvdata->usb_free_buf) > 0) { ret = usb_qdss_write(tmcdrvdata->usbch, drvdata->usb_req); if (ret) { kfree(usb_req); usb_req = NULL; drvdata->usb_req = NULL; dev_err(tmcdrvdata->dev, "Write data failed\n"); continue; } atomic_dec(&drvdata->usb_free_buf); } else { dev_dbg(tmcdrvdata->dev, "Drop data, offset = %d, seq = %d, irq = %d\n", drvdata->offset, seq, atomic_read(&drvdata->irq_cnt)); kfree(usb_req); drvdata->usb_req = NULL; } } if (atomic_read(&drvdata->irq_cnt) > 0) atomic_dec(&drvdata->irq_cnt); } dev_err(tmcdrvdata->dev, "TMC has been stopped.\n"); } static void usb_write_done(struct byte_cntr *drvdata, struct qdss_request *d_req) { atomic_inc(&drvdata->usb_free_buf); if (d_req->status) pr_err_ratelimited("USB write failed err:%d\n", d_req->status); kfree(d_req); } void usb_bypass_notifier(void *priv, unsigned int event, struct qdss_request *d_req, struct usb_qdss_ch *ch) { struct byte_cntr *drvdata = priv; if (!drvdata) return; switch (event) { case USB_QDSS_CONNECT: usb_qdss_alloc_req(ch, USB_BUF_NUM, 0); usb_bypass_start(drvdata); queue_work(drvdata->usb_wq, &(drvdata->read_work)); break; case USB_QDSS_DISCONNECT: usb_bypass_stop(drvdata); break; case USB_QDSS_DATA_WRITE_DONE: usb_write_done(drvdata, d_req); break; default: break; } } EXPORT_SYMBOL(usb_bypass_notifier); static int usb_bypass_init(struct byte_cntr *byte_cntr_data) { byte_cntr_data->usb_wq = create_singlethread_workqueue("byte-cntr"); if (!byte_cntr_data->usb_wq) return -ENOMEM; byte_cntr_data->offset = 0; mutex_init(&byte_cntr_data->usb_bypass_lock); init_waitqueue_head(&byte_cntr_data->usb_wait_wq); atomic_set(&byte_cntr_data->usb_free_buf, USB_BUF_NUM); INIT_WORK(&(byte_cntr_data->read_work), usb_read_work_fn); return 0; } struct byte_cntr *byte_cntr_init(struct amba_device *adev, struct tmc_drvdata *drvdata) { Loading @@ -261,6 +433,12 @@ struct byte_cntr *byte_cntr_init(struct amba_device *adev, if (!byte_cntr_data) return NULL; byte_cntr_data->sw_usb = of_property_read_bool(np, "qcom,sw-usb"); if (byte_cntr_data->sw_usb) { ret = usb_bypass_init(byte_cntr_data); if (ret) return NULL; } ret = devm_request_irq(dev, byte_cntr_irq, etr_handler, IRQF_TRIGGER_RISING | IRQF_SHARED, "tmc-etr", byte_cntr_data); Loading drivers/hwtracing/coresight/coresight-byte-cntr.h +14 −3 Original line number Diff line number Diff line /* SPDX-License-Identifier: GPL-2.0-only */ /* * Copyright (c) 2017, The Linux Foundation. All rights reserved. * Copyright (c) 2017, 2019 The Linux Foundation. All rights reserved. */ #ifndef _CORESIGHT_BYTE_CNTR_H #define _CORESIGHT_BYTE_CNTR_H Loading @@ -14,16 +14,27 @@ struct byte_cntr { struct class *driver_class; bool enable; bool read_active; bool sw_usb; uint32_t byte_cntr_value; uint32_t block_size; int byte_cntr_irq; atomic_t irq_cnt; atomic_t usb_free_buf; wait_queue_head_t wq; wait_queue_head_t usb_wait_wq; struct workqueue_struct *usb_wq; struct qdss_request *usb_req; struct work_struct read_work; struct mutex usb_bypass_lock; struct mutex byte_cntr_lock; struct coresight_csr *csr; unsigned long offset; }; extern void usb_bypass_notifier(void *priv, unsigned int event, struct qdss_request *d_req, struct usb_qdss_ch *ch); extern void tmc_etr_byte_cntr_start(struct byte_cntr *byte_cntr_data); extern void tmc_etr_byte_cntr_stop(struct byte_cntr *byte_cntr_data); extern void usb_bypass_stop(struct byte_cntr *byte_cntr_data); #endif drivers/hwtracing/coresight/coresight-tmc-etr.c +67 −10 Original line number Diff line number Diff line Loading @@ -343,10 +343,11 @@ void tmc_sg_table_sync_table(struct tmc_sg_table *sg_table) ssize_t tmc_sg_table_get_data(struct tmc_sg_table *sg_table, u64 offset, size_t len, char **bufpp) { size_t size; size_t size, tmp_len; int pg_idx = offset >> PAGE_SHIFT; int pg_offset = offset & (PAGE_SIZE - 1); struct tmc_pages *data_pages = &sg_table->data_pages; int i; size = tmc_sg_table_buf_size(sg_table); if (offset >= size) Loading @@ -355,7 +356,22 @@ ssize_t tmc_sg_table_get_data(struct tmc_sg_table *sg_table, /* Make sure we don't go beyond the end */ len = (len < (size - offset)) ? len : size - offset; /* Respect the page boundaries */ len = (len < (PAGE_SIZE - pg_offset)) ? len : (PAGE_SIZE - pg_offset); if (len > (PAGE_SIZE - pg_offset)) { tmp_len = PAGE_SIZE - pg_offset; for (i = 0; i < (data_pages->nr_pages - pg_idx); i++) { if (i < (data_pages->nr_pages - pg_idx - 1) && (page_address(data_pages->pages[pg_idx + i + 1]) - page_address(data_pages->pages[pg_idx + i])) == PAGE_SIZE) { if ((len - tmp_len) < PAGE_SIZE) break; tmp_len += PAGE_SIZE; } else { len = tmp_len; break; } } } if (len > 0) *bufpp = page_address(data_pages->pages[pg_idx]) + pg_offset; return len; Loading Loading @@ -1342,6 +1358,26 @@ static int tmc_enable_etr_sink_sysfs(struct coresight_device *csdev) } coresight_cti_map_trigout(drvdata->cti_flush, 3, 0); coresight_cti_map_trigin(drvdata->cti_reset, 2, 0); } else if (drvdata->byte_cntr->sw_usb) { if (!drvdata->etr_buf) { free_buf = new_buf = tmc_etr_setup_sysfs_buf(drvdata); if (IS_ERR(new_buf)) { mutex_unlock(&drvdata->mem_lock); return -ENOMEM; } } coresight_cti_map_trigout(drvdata->cti_flush, 3, 0); coresight_cti_map_trigin(drvdata->cti_reset, 2, 0); drvdata->usbch = usb_qdss_open("qdss_mdm", drvdata->byte_cntr, usb_bypass_notifier); if (IS_ERR_OR_NULL(drvdata->usbch)) { dev_err(drvdata->dev, "usb_qdss_open failed\n"); mutex_unlock(&drvdata->mem_lock); return -ENODEV; } } else { drvdata->usbch = usb_qdss_open("qdss", drvdata, usb_notifier); Loading Loading @@ -1379,7 +1415,9 @@ static int tmc_enable_etr_sink_sysfs(struct coresight_device *csdev) drvdata->mode = CS_MODE_SYSFS; if (drvdata->out_mode == TMC_ETR_OUT_MODE_MEM) if (drvdata->out_mode == TMC_ETR_OUT_MODE_MEM || (drvdata->out_mode == TMC_ETR_OUT_MODE_USB && drvdata->byte_cntr->sw_usb)) tmc_etr_enable_hw(drvdata); drvdata->enable = true; Loading Loading @@ -1435,12 +1473,18 @@ static void tmc_disable_etr_sink(struct coresight_device *csdev) /* Disable the TMC only if it needs to */ if (drvdata->mode != CS_MODE_DISABLED) { if (drvdata->out_mode == TMC_ETR_OUT_MODE_USB) { if (!drvdata->byte_cntr->sw_usb) { __tmc_etr_disable_to_bam(drvdata); spin_unlock_irqrestore(&drvdata->spinlock, flags); spin_unlock_irqrestore(&drvdata->spinlock, flags); tmc_etr_bam_disable(drvdata); usb_qdss_close(drvdata->usbch); drvdata->mode = CS_MODE_DISABLED; goto out; } else { usb_qdss_close(drvdata->usbch); tmc_etr_disable_hw(drvdata); } } else { tmc_etr_disable_hw(drvdata); } Loading @@ -1449,6 +1493,19 @@ static void tmc_disable_etr_sink(struct coresight_device *csdev) spin_unlock_irqrestore(&drvdata->spinlock, flags); if (drvdata->out_mode == TMC_ETR_OUT_MODE_USB && drvdata->byte_cntr->sw_usb) { usb_bypass_stop(drvdata->byte_cntr); flush_workqueue(drvdata->byte_cntr->usb_wq); coresight_cti_unmap_trigin(drvdata->cti_reset, 2, 0); coresight_cti_unmap_trigout(drvdata->cti_flush, 3, 0); /* Free memory outside the spinlock if need be */ if (drvdata->etr_buf) { tmc_etr_free_sysfs_buf(drvdata->etr_buf); drvdata->etr_buf = NULL; } } if (drvdata->out_mode == TMC_ETR_OUT_MODE_MEM) { tmc_etr_byte_cntr_stop(drvdata->byte_cntr); coresight_cti_unmap_trigin(drvdata->cti_reset, 2, 0); Loading Loading
drivers/hwtracing/coresight/coresight-byte-cntr.c +183 −5 Original line number Diff line number Diff line // SPDX-License-Identifier: GPL-2.0-only /* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. /* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. * * Description: CoreSight Trace Memory Controller driver */ Loading @@ -10,11 +10,15 @@ #include <linux/moduleparam.h> #include <linux/delay.h> #include <linux/uaccess.h> #include <linux/usb/usb_qdss.h> #include "coresight-byte-cntr.h" #include "coresight-priv.h" #include "coresight-tmc.h" #define USB_BLK_SIZE 65536 #define USB_BUF_NUM 255 static struct tmc_drvdata *tmcdrvdata; static void tmc_etr_read_bytes(struct byte_cntr *byte_cntr_data, loff_t *ppos, Loading @@ -39,10 +43,14 @@ static irqreturn_t etr_handler(int irq, void *data) { struct byte_cntr *byte_cntr_data = data; if (tmcdrvdata->out_mode == TMC_ETR_OUT_MODE_USB && byte_cntr_data->sw_usb) { atomic_inc(&byte_cntr_data->irq_cnt); wake_up(&byte_cntr_data->usb_wait_wq); } else if (tmcdrvdata->out_mode == TMC_ETR_OUT_MODE_MEM) { atomic_inc(&byte_cntr_data->irq_cnt); wake_up(&byte_cntr_data->wq); } return IRQ_HANDLED; } Loading Loading @@ -160,6 +168,45 @@ static int tmc_etr_byte_cntr_release(struct inode *in, struct file *fp) return 0; } int usb_bypass_start(struct byte_cntr *byte_cntr_data) { if (!byte_cntr_data) return -ENOMEM; mutex_lock(&byte_cntr_data->usb_bypass_lock); if (!tmcdrvdata->enable) { mutex_unlock(&byte_cntr_data->usb_bypass_lock); return -EINVAL; } atomic_set(&byte_cntr_data->usb_free_buf, USB_BUF_NUM); byte_cntr_data->offset = tmcdrvdata->etr_buf->offset; /* * IRQ is a '8- byte' counter and to observe interrupt at * 'block_size' bytes of data */ coresight_csr_set_byte_cntr(byte_cntr_data->csr, USB_BLK_SIZE / 8); atomic_set(&byte_cntr_data->irq_cnt, 0); mutex_unlock(&byte_cntr_data->usb_bypass_lock); return 0; } void usb_bypass_stop(struct byte_cntr *byte_cntr_data) { if (!byte_cntr_data) return; mutex_lock(&byte_cntr_data->usb_bypass_lock); wake_up(&byte_cntr_data->usb_wait_wq); coresight_csr_set_byte_cntr(byte_cntr_data->csr, 0); mutex_unlock(&byte_cntr_data->usb_bypass_lock); } EXPORT_SYMBOL(usb_bypass_stop); static int tmc_etr_byte_cntr_open(struct inode *in, struct file *fp) { struct byte_cntr *byte_cntr_data = Loading Loading @@ -244,6 +291,131 @@ static int byte_cntr_register_chardev(struct byte_cntr *byte_cntr_data) return ret; } static void usb_read_work_fn(struct work_struct *work) { int ret, seq = 0; struct qdss_request *usb_req = NULL; struct etr_buf *etr_buf = tmcdrvdata->etr_buf; size_t actual, req_size; 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, atomic_read(&drvdata->irq_cnt) > 0 || !tmcdrvdata->enable || tmcdrvdata->out_mode != TMC_ETR_OUT_MODE_USB); if (ret == -ERESTARTSYS || !tmcdrvdata->enable || tmcdrvdata->out_mode != TMC_ETR_OUT_MODE_USB) break; } req_size = USB_BLK_SIZE; while (req_size > 0) { seq++; usb_req = kzalloc(sizeof(*usb_req), GFP_KERNEL); if (!usb_req) return; actual = tmc_etr_buf_get_data(etr_buf, drvdata->offset, req_size, &usb_req->buf); if (actual <= 0) { kfree(usb_req); usb_req = NULL; dev_err(tmcdrvdata->dev, "No data in ETR\n"); break; } usb_req->length = actual; drvdata->usb_req = usb_req; req_size -= actual; if ((drvdata->offset + usb_req->length) >= tmcdrvdata->size) drvdata->offset = 0; else drvdata->offset += usb_req->length; if (atomic_read(&drvdata->usb_free_buf) > 0) { ret = usb_qdss_write(tmcdrvdata->usbch, drvdata->usb_req); if (ret) { kfree(usb_req); usb_req = NULL; drvdata->usb_req = NULL; dev_err(tmcdrvdata->dev, "Write data failed\n"); continue; } atomic_dec(&drvdata->usb_free_buf); } else { dev_dbg(tmcdrvdata->dev, "Drop data, offset = %d, seq = %d, irq = %d\n", drvdata->offset, seq, atomic_read(&drvdata->irq_cnt)); kfree(usb_req); drvdata->usb_req = NULL; } } if (atomic_read(&drvdata->irq_cnt) > 0) atomic_dec(&drvdata->irq_cnt); } dev_err(tmcdrvdata->dev, "TMC has been stopped.\n"); } static void usb_write_done(struct byte_cntr *drvdata, struct qdss_request *d_req) { atomic_inc(&drvdata->usb_free_buf); if (d_req->status) pr_err_ratelimited("USB write failed err:%d\n", d_req->status); kfree(d_req); } void usb_bypass_notifier(void *priv, unsigned int event, struct qdss_request *d_req, struct usb_qdss_ch *ch) { struct byte_cntr *drvdata = priv; if (!drvdata) return; switch (event) { case USB_QDSS_CONNECT: usb_qdss_alloc_req(ch, USB_BUF_NUM, 0); usb_bypass_start(drvdata); queue_work(drvdata->usb_wq, &(drvdata->read_work)); break; case USB_QDSS_DISCONNECT: usb_bypass_stop(drvdata); break; case USB_QDSS_DATA_WRITE_DONE: usb_write_done(drvdata, d_req); break; default: break; } } EXPORT_SYMBOL(usb_bypass_notifier); static int usb_bypass_init(struct byte_cntr *byte_cntr_data) { byte_cntr_data->usb_wq = create_singlethread_workqueue("byte-cntr"); if (!byte_cntr_data->usb_wq) return -ENOMEM; byte_cntr_data->offset = 0; mutex_init(&byte_cntr_data->usb_bypass_lock); init_waitqueue_head(&byte_cntr_data->usb_wait_wq); atomic_set(&byte_cntr_data->usb_free_buf, USB_BUF_NUM); INIT_WORK(&(byte_cntr_data->read_work), usb_read_work_fn); return 0; } struct byte_cntr *byte_cntr_init(struct amba_device *adev, struct tmc_drvdata *drvdata) { Loading @@ -261,6 +433,12 @@ struct byte_cntr *byte_cntr_init(struct amba_device *adev, if (!byte_cntr_data) return NULL; byte_cntr_data->sw_usb = of_property_read_bool(np, "qcom,sw-usb"); if (byte_cntr_data->sw_usb) { ret = usb_bypass_init(byte_cntr_data); if (ret) return NULL; } ret = devm_request_irq(dev, byte_cntr_irq, etr_handler, IRQF_TRIGGER_RISING | IRQF_SHARED, "tmc-etr", byte_cntr_data); Loading
drivers/hwtracing/coresight/coresight-byte-cntr.h +14 −3 Original line number Diff line number Diff line /* SPDX-License-Identifier: GPL-2.0-only */ /* * Copyright (c) 2017, The Linux Foundation. All rights reserved. * Copyright (c) 2017, 2019 The Linux Foundation. All rights reserved. */ #ifndef _CORESIGHT_BYTE_CNTR_H #define _CORESIGHT_BYTE_CNTR_H Loading @@ -14,16 +14,27 @@ struct byte_cntr { struct class *driver_class; bool enable; bool read_active; bool sw_usb; uint32_t byte_cntr_value; uint32_t block_size; int byte_cntr_irq; atomic_t irq_cnt; atomic_t usb_free_buf; wait_queue_head_t wq; wait_queue_head_t usb_wait_wq; struct workqueue_struct *usb_wq; struct qdss_request *usb_req; struct work_struct read_work; struct mutex usb_bypass_lock; struct mutex byte_cntr_lock; struct coresight_csr *csr; unsigned long offset; }; extern void usb_bypass_notifier(void *priv, unsigned int event, struct qdss_request *d_req, struct usb_qdss_ch *ch); extern void tmc_etr_byte_cntr_start(struct byte_cntr *byte_cntr_data); extern void tmc_etr_byte_cntr_stop(struct byte_cntr *byte_cntr_data); extern void usb_bypass_stop(struct byte_cntr *byte_cntr_data); #endif
drivers/hwtracing/coresight/coresight-tmc-etr.c +67 −10 Original line number Diff line number Diff line Loading @@ -343,10 +343,11 @@ void tmc_sg_table_sync_table(struct tmc_sg_table *sg_table) ssize_t tmc_sg_table_get_data(struct tmc_sg_table *sg_table, u64 offset, size_t len, char **bufpp) { size_t size; size_t size, tmp_len; int pg_idx = offset >> PAGE_SHIFT; int pg_offset = offset & (PAGE_SIZE - 1); struct tmc_pages *data_pages = &sg_table->data_pages; int i; size = tmc_sg_table_buf_size(sg_table); if (offset >= size) Loading @@ -355,7 +356,22 @@ ssize_t tmc_sg_table_get_data(struct tmc_sg_table *sg_table, /* Make sure we don't go beyond the end */ len = (len < (size - offset)) ? len : size - offset; /* Respect the page boundaries */ len = (len < (PAGE_SIZE - pg_offset)) ? len : (PAGE_SIZE - pg_offset); if (len > (PAGE_SIZE - pg_offset)) { tmp_len = PAGE_SIZE - pg_offset; for (i = 0; i < (data_pages->nr_pages - pg_idx); i++) { if (i < (data_pages->nr_pages - pg_idx - 1) && (page_address(data_pages->pages[pg_idx + i + 1]) - page_address(data_pages->pages[pg_idx + i])) == PAGE_SIZE) { if ((len - tmp_len) < PAGE_SIZE) break; tmp_len += PAGE_SIZE; } else { len = tmp_len; break; } } } if (len > 0) *bufpp = page_address(data_pages->pages[pg_idx]) + pg_offset; return len; Loading Loading @@ -1342,6 +1358,26 @@ static int tmc_enable_etr_sink_sysfs(struct coresight_device *csdev) } coresight_cti_map_trigout(drvdata->cti_flush, 3, 0); coresight_cti_map_trigin(drvdata->cti_reset, 2, 0); } else if (drvdata->byte_cntr->sw_usb) { if (!drvdata->etr_buf) { free_buf = new_buf = tmc_etr_setup_sysfs_buf(drvdata); if (IS_ERR(new_buf)) { mutex_unlock(&drvdata->mem_lock); return -ENOMEM; } } coresight_cti_map_trigout(drvdata->cti_flush, 3, 0); coresight_cti_map_trigin(drvdata->cti_reset, 2, 0); drvdata->usbch = usb_qdss_open("qdss_mdm", drvdata->byte_cntr, usb_bypass_notifier); if (IS_ERR_OR_NULL(drvdata->usbch)) { dev_err(drvdata->dev, "usb_qdss_open failed\n"); mutex_unlock(&drvdata->mem_lock); return -ENODEV; } } else { drvdata->usbch = usb_qdss_open("qdss", drvdata, usb_notifier); Loading Loading @@ -1379,7 +1415,9 @@ static int tmc_enable_etr_sink_sysfs(struct coresight_device *csdev) drvdata->mode = CS_MODE_SYSFS; if (drvdata->out_mode == TMC_ETR_OUT_MODE_MEM) if (drvdata->out_mode == TMC_ETR_OUT_MODE_MEM || (drvdata->out_mode == TMC_ETR_OUT_MODE_USB && drvdata->byte_cntr->sw_usb)) tmc_etr_enable_hw(drvdata); drvdata->enable = true; Loading Loading @@ -1435,12 +1473,18 @@ static void tmc_disable_etr_sink(struct coresight_device *csdev) /* Disable the TMC only if it needs to */ if (drvdata->mode != CS_MODE_DISABLED) { if (drvdata->out_mode == TMC_ETR_OUT_MODE_USB) { if (!drvdata->byte_cntr->sw_usb) { __tmc_etr_disable_to_bam(drvdata); spin_unlock_irqrestore(&drvdata->spinlock, flags); spin_unlock_irqrestore(&drvdata->spinlock, flags); tmc_etr_bam_disable(drvdata); usb_qdss_close(drvdata->usbch); drvdata->mode = CS_MODE_DISABLED; goto out; } else { usb_qdss_close(drvdata->usbch); tmc_etr_disable_hw(drvdata); } } else { tmc_etr_disable_hw(drvdata); } Loading @@ -1449,6 +1493,19 @@ static void tmc_disable_etr_sink(struct coresight_device *csdev) spin_unlock_irqrestore(&drvdata->spinlock, flags); if (drvdata->out_mode == TMC_ETR_OUT_MODE_USB && drvdata->byte_cntr->sw_usb) { usb_bypass_stop(drvdata->byte_cntr); flush_workqueue(drvdata->byte_cntr->usb_wq); coresight_cti_unmap_trigin(drvdata->cti_reset, 2, 0); coresight_cti_unmap_trigout(drvdata->cti_flush, 3, 0); /* Free memory outside the spinlock if need be */ if (drvdata->etr_buf) { tmc_etr_free_sysfs_buf(drvdata->etr_buf); drvdata->etr_buf = NULL; } } if (drvdata->out_mode == TMC_ETR_OUT_MODE_MEM) { tmc_etr_byte_cntr_stop(drvdata->byte_cntr); coresight_cti_unmap_trigin(drvdata->cti_reset, 2, 0); Loading