Loading drivers/hwtracing/coresight/coresight-tmc-etr.c +13 −11 Original line number Diff line number Diff line Loading @@ -13,13 +13,6 @@ #include "coresight-priv.h" #include "coresight-tmc.h" struct etr_flat_buf { struct device *dev; dma_addr_t daddr; void *vaddr; size_t size; }; /* * The TMC ETR SG has a page size of 4K. The SG table contains pointers * to 4KB buffers. However, the OS may use a PAGE_SIZE different from Loading Loading @@ -895,7 +888,7 @@ static void tmc_sync_etr_buf(struct tmc_drvdata *drvdata) tmc_etr_buf_insert_barrier_packet(etr_buf, etr_buf->offset); } static void tmc_etr_enable_hw(struct tmc_drvdata *drvdata) void tmc_etr_enable_hw(struct tmc_drvdata *drvdata) { u32 axictl, sts; struct etr_buf *etr_buf = drvdata->etr_buf; Loading Loading @@ -1007,7 +1000,7 @@ static void tmc_etr_sync_sysfs_buf(struct tmc_drvdata *drvdata) tmc_sync_etr_buf(drvdata); } static void tmc_etr_disable_hw(struct tmc_drvdata *drvdata) void tmc_etr_disable_hw(struct tmc_drvdata *drvdata) { CS_UNLOCK(drvdata->base); Loading Loading @@ -1081,7 +1074,10 @@ 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) tmc_etr_enable_hw(drvdata); drvdata->enable = true; out: spin_unlock_irqrestore(&drvdata->spinlock, flags); Loading Loading @@ -1132,7 +1128,9 @@ 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) tmc_etr_disable_hw(drvdata); drvdata->mode = CS_MODE_DISABLED; } Loading Loading @@ -1166,6 +1164,10 @@ int tmc_read_prepare_etr(struct tmc_drvdata *drvdata) goto out; } if (drvdata->out_mode == TMC_ETR_OUT_MODE_USB) { ret = -EINVAL; goto out; } /* Don't interfere if operated from Perf */ if (drvdata->mode == CS_MODE_PERF) { ret = -EINVAL; Loading drivers/hwtracing/coresight/coresight-tmc.c +109 −6 Original line number Diff line number Diff line Loading @@ -320,14 +320,108 @@ static ssize_t buffer_size_store(struct device *dev, static DEVICE_ATTR_RW(buffer_size); static struct attribute *coresight_tmc_attrs[] = { static ssize_t out_mode_show(struct device *dev, struct device_attribute *attr, char *buf) { struct tmc_drvdata *drvdata = dev_get_drvdata(dev->parent); return scnprintf(buf, PAGE_SIZE, "%s\n", str_tmc_etr_out_mode[drvdata->out_mode]); } static ssize_t out_mode_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) { struct tmc_drvdata *drvdata = dev_get_drvdata(dev->parent); char str[10] = ""; unsigned long flags; int ret; if (strlen(buf) >= 10) return -EINVAL; if (sscanf(buf, "%10s", str) != 1) return -EINVAL; mutex_lock(&drvdata->mem_lock); if (!strcmp(str, str_tmc_etr_out_mode[TMC_ETR_OUT_MODE_MEM])) { if (drvdata->out_mode == TMC_ETR_OUT_MODE_MEM) goto out; spin_lock_irqsave(&drvdata->spinlock, flags); if (!drvdata->enable) { drvdata->out_mode = TMC_ETR_OUT_MODE_MEM; spin_unlock_irqrestore(&drvdata->spinlock, flags); goto out; } tmc_etr_enable_hw(drvdata); drvdata->out_mode = TMC_ETR_OUT_MODE_MEM; spin_unlock_irqrestore(&drvdata->spinlock, flags); } else if (!strcmp(str, str_tmc_etr_out_mode[TMC_ETR_OUT_MODE_USB])) { if (drvdata->out_mode == TMC_ETR_OUT_MODE_USB) goto out; spin_lock_irqsave(&drvdata->spinlock, flags); if (!drvdata->enable) { drvdata->out_mode = TMC_ETR_OUT_MODE_USB; spin_unlock_irqrestore(&drvdata->spinlock, flags); goto out; } if (drvdata->reading) { ret = -EBUSY; goto err1; } tmc_etr_disable_hw(drvdata); drvdata->out_mode = TMC_ETR_OUT_MODE_USB; spin_unlock_irqrestore(&drvdata->spinlock, flags); } out: mutex_unlock(&drvdata->mem_lock); return size; err1: spin_unlock_irqrestore(&drvdata->spinlock, flags); mutex_unlock(&drvdata->mem_lock); return ret; } static DEVICE_ATTR_RW(out_mode); static ssize_t available_out_modes_show(struct device *dev, struct device_attribute *attr, char *buf) { ssize_t len = 0; int i; for (i = 0; i < ARRAY_SIZE(str_tmc_etr_out_mode); i++) len += scnprintf(buf + len, PAGE_SIZE - len, "%s ", str_tmc_etr_out_mode[i]); len += scnprintf(buf + len, PAGE_SIZE - len, "\n"); return len; } static DEVICE_ATTR_RO(available_out_modes); static struct attribute *coresight_tmc_etf_attrs[] = { &dev_attr_trigger_cntr.attr, &dev_attr_buffer_size.attr, NULL, }; static struct attribute *coresight_tmc_etr_attrs[] = { &dev_attr_trigger_cntr.attr, &dev_attr_buffer_size.attr, &dev_attr_out_mode.attr, &dev_attr_available_out_modes.attr, NULL, }; static const struct attribute_group coresight_tmc_group = { .attrs = coresight_tmc_attrs, static const struct attribute_group coresight_tmc_etf_group = { .attrs = coresight_tmc_etf_attrs, }; static const struct attribute_group coresight_tmc_etr_group = { .attrs = coresight_tmc_etr_attrs, }; static const struct attribute_group coresight_tmc_mgmt_group = { Loading @@ -335,8 +429,14 @@ static const struct attribute_group coresight_tmc_mgmt_group = { .name = "mgmt", }; const struct attribute_group *coresight_tmc_groups[] = { &coresight_tmc_group, const struct attribute_group *coresight_tmc_etf_groups[] = { &coresight_tmc_etf_group, &coresight_tmc_mgmt_group, NULL, }; const struct attribute_group *coresight_tmc_etr_groups[] = { &coresight_tmc_etr_group, &coresight_tmc_mgmt_group, NULL, }; Loading Loading @@ -392,16 +492,19 @@ static int tmc_config_desc(struct tmc_drvdata *drvdata, case TMC_CONFIG_TYPE_ETB: desc->type = CORESIGHT_DEV_TYPE_SINK; desc->subtype.sink_subtype = CORESIGHT_DEV_SUBTYPE_SINK_BUFFER; desc->groups = coresight_tmc_etf_groups; desc->ops = &tmc_etb_cs_ops; break; case TMC_CONFIG_TYPE_ETR: desc->type = CORESIGHT_DEV_TYPE_SINK; desc->subtype.sink_subtype = CORESIGHT_DEV_SUBTYPE_SINK_BUFFER; desc->groups = coresight_tmc_etr_groups; desc->ops = &tmc_etr_cs_ops; break; case TMC_CONFIG_TYPE_ETF: desc->type = CORESIGHT_DEV_TYPE_LINKSINK; desc->subtype.link_subtype = CORESIGHT_DEV_SUBTYPE_LINK_FIFO; desc->groups = coresight_tmc_etf_groups; desc->ops = &tmc_etf_cs_ops; break; default: Loading Loading @@ -455,6 +558,7 @@ static int tmc_probe(struct amba_device *adev, const struct amba_id *id) drvdata->memwidth = tmc_get_memwidth(devid); if (drvdata->config_type == TMC_CONFIG_TYPE_ETR) { drvdata->out_mode = TMC_ETR_OUT_MODE_MEM; ret = of_property_read_u32(np, "arm,buffer-size", &drvdata->size); if (ret) Loading @@ -478,7 +582,6 @@ static int tmc_probe(struct amba_device *adev, const struct amba_id *id) desc.pdata = pdata; desc.dev = dev; desc.groups = coresight_tmc_groups; ret = tmc_config_desc(drvdata, &desc); if (ret) goto out; Loading drivers/hwtracing/coresight/coresight-tmc.h +26 −0 Original line number Diff line number Diff line Loading @@ -9,6 +9,10 @@ #include <linux/dma-mapping.h> #include <linux/miscdevice.h> #include <linux/delay.h> #include <asm/cacheflush.h> #include <linux/of_address.h> #include <linux/amba/bus.h> #define TMC_RSZ 0x004 #define TMC_STS 0x00c Loading Loading @@ -133,8 +137,27 @@ enum etr_mode { ETR_MODE_CATU, /* Use SG mechanism in CATU */ }; enum tmc_etr_out_mode { TMC_ETR_OUT_MODE_NONE, TMC_ETR_OUT_MODE_MEM, TMC_ETR_OUT_MODE_USB, }; static const char * const str_tmc_etr_out_mode[] = { [TMC_ETR_OUT_MODE_NONE] = "none", [TMC_ETR_OUT_MODE_MEM] = "mem", [TMC_ETR_OUT_MODE_USB] = "usb", }; struct etr_buf_operations; struct etr_flat_buf { struct device *dev; dma_addr_t daddr; void *vaddr; size_t size; }; /** * struct etr_buf - Details of the buffer used by ETR * @mode : Mode of the ETR buffer, contiguous, Scatter Gather etc. Loading Loading @@ -197,6 +220,7 @@ struct tmc_drvdata { struct coresight_csr *csr; const char *csr_name; bool enable; enum tmc_etr_out_mode out_mode; }; struct etr_buf_operations { Loading Loading @@ -257,6 +281,8 @@ ssize_t tmc_etb_get_sysfs_trace(struct tmc_drvdata *drvdata, /* ETR functions */ int tmc_read_prepare_etr(struct tmc_drvdata *drvdata); int tmc_read_unprepare_etr(struct tmc_drvdata *drvdata); void tmc_etr_enable_hw(struct tmc_drvdata *drvdata); void tmc_etr_disable_hw(struct tmc_drvdata *drvdata); extern const struct coresight_ops tmc_etr_cs_ops; ssize_t tmc_etr_get_sysfs_trace(struct tmc_drvdata *drvdata, loff_t pos, size_t len, char **bufpp); Loading Loading
drivers/hwtracing/coresight/coresight-tmc-etr.c +13 −11 Original line number Diff line number Diff line Loading @@ -13,13 +13,6 @@ #include "coresight-priv.h" #include "coresight-tmc.h" struct etr_flat_buf { struct device *dev; dma_addr_t daddr; void *vaddr; size_t size; }; /* * The TMC ETR SG has a page size of 4K. The SG table contains pointers * to 4KB buffers. However, the OS may use a PAGE_SIZE different from Loading Loading @@ -895,7 +888,7 @@ static void tmc_sync_etr_buf(struct tmc_drvdata *drvdata) tmc_etr_buf_insert_barrier_packet(etr_buf, etr_buf->offset); } static void tmc_etr_enable_hw(struct tmc_drvdata *drvdata) void tmc_etr_enable_hw(struct tmc_drvdata *drvdata) { u32 axictl, sts; struct etr_buf *etr_buf = drvdata->etr_buf; Loading Loading @@ -1007,7 +1000,7 @@ static void tmc_etr_sync_sysfs_buf(struct tmc_drvdata *drvdata) tmc_sync_etr_buf(drvdata); } static void tmc_etr_disable_hw(struct tmc_drvdata *drvdata) void tmc_etr_disable_hw(struct tmc_drvdata *drvdata) { CS_UNLOCK(drvdata->base); Loading Loading @@ -1081,7 +1074,10 @@ 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) tmc_etr_enable_hw(drvdata); drvdata->enable = true; out: spin_unlock_irqrestore(&drvdata->spinlock, flags); Loading Loading @@ -1132,7 +1128,9 @@ 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) tmc_etr_disable_hw(drvdata); drvdata->mode = CS_MODE_DISABLED; } Loading Loading @@ -1166,6 +1164,10 @@ int tmc_read_prepare_etr(struct tmc_drvdata *drvdata) goto out; } if (drvdata->out_mode == TMC_ETR_OUT_MODE_USB) { ret = -EINVAL; goto out; } /* Don't interfere if operated from Perf */ if (drvdata->mode == CS_MODE_PERF) { ret = -EINVAL; Loading
drivers/hwtracing/coresight/coresight-tmc.c +109 −6 Original line number Diff line number Diff line Loading @@ -320,14 +320,108 @@ static ssize_t buffer_size_store(struct device *dev, static DEVICE_ATTR_RW(buffer_size); static struct attribute *coresight_tmc_attrs[] = { static ssize_t out_mode_show(struct device *dev, struct device_attribute *attr, char *buf) { struct tmc_drvdata *drvdata = dev_get_drvdata(dev->parent); return scnprintf(buf, PAGE_SIZE, "%s\n", str_tmc_etr_out_mode[drvdata->out_mode]); } static ssize_t out_mode_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) { struct tmc_drvdata *drvdata = dev_get_drvdata(dev->parent); char str[10] = ""; unsigned long flags; int ret; if (strlen(buf) >= 10) return -EINVAL; if (sscanf(buf, "%10s", str) != 1) return -EINVAL; mutex_lock(&drvdata->mem_lock); if (!strcmp(str, str_tmc_etr_out_mode[TMC_ETR_OUT_MODE_MEM])) { if (drvdata->out_mode == TMC_ETR_OUT_MODE_MEM) goto out; spin_lock_irqsave(&drvdata->spinlock, flags); if (!drvdata->enable) { drvdata->out_mode = TMC_ETR_OUT_MODE_MEM; spin_unlock_irqrestore(&drvdata->spinlock, flags); goto out; } tmc_etr_enable_hw(drvdata); drvdata->out_mode = TMC_ETR_OUT_MODE_MEM; spin_unlock_irqrestore(&drvdata->spinlock, flags); } else if (!strcmp(str, str_tmc_etr_out_mode[TMC_ETR_OUT_MODE_USB])) { if (drvdata->out_mode == TMC_ETR_OUT_MODE_USB) goto out; spin_lock_irqsave(&drvdata->spinlock, flags); if (!drvdata->enable) { drvdata->out_mode = TMC_ETR_OUT_MODE_USB; spin_unlock_irqrestore(&drvdata->spinlock, flags); goto out; } if (drvdata->reading) { ret = -EBUSY; goto err1; } tmc_etr_disable_hw(drvdata); drvdata->out_mode = TMC_ETR_OUT_MODE_USB; spin_unlock_irqrestore(&drvdata->spinlock, flags); } out: mutex_unlock(&drvdata->mem_lock); return size; err1: spin_unlock_irqrestore(&drvdata->spinlock, flags); mutex_unlock(&drvdata->mem_lock); return ret; } static DEVICE_ATTR_RW(out_mode); static ssize_t available_out_modes_show(struct device *dev, struct device_attribute *attr, char *buf) { ssize_t len = 0; int i; for (i = 0; i < ARRAY_SIZE(str_tmc_etr_out_mode); i++) len += scnprintf(buf + len, PAGE_SIZE - len, "%s ", str_tmc_etr_out_mode[i]); len += scnprintf(buf + len, PAGE_SIZE - len, "\n"); return len; } static DEVICE_ATTR_RO(available_out_modes); static struct attribute *coresight_tmc_etf_attrs[] = { &dev_attr_trigger_cntr.attr, &dev_attr_buffer_size.attr, NULL, }; static struct attribute *coresight_tmc_etr_attrs[] = { &dev_attr_trigger_cntr.attr, &dev_attr_buffer_size.attr, &dev_attr_out_mode.attr, &dev_attr_available_out_modes.attr, NULL, }; static const struct attribute_group coresight_tmc_group = { .attrs = coresight_tmc_attrs, static const struct attribute_group coresight_tmc_etf_group = { .attrs = coresight_tmc_etf_attrs, }; static const struct attribute_group coresight_tmc_etr_group = { .attrs = coresight_tmc_etr_attrs, }; static const struct attribute_group coresight_tmc_mgmt_group = { Loading @@ -335,8 +429,14 @@ static const struct attribute_group coresight_tmc_mgmt_group = { .name = "mgmt", }; const struct attribute_group *coresight_tmc_groups[] = { &coresight_tmc_group, const struct attribute_group *coresight_tmc_etf_groups[] = { &coresight_tmc_etf_group, &coresight_tmc_mgmt_group, NULL, }; const struct attribute_group *coresight_tmc_etr_groups[] = { &coresight_tmc_etr_group, &coresight_tmc_mgmt_group, NULL, }; Loading Loading @@ -392,16 +492,19 @@ static int tmc_config_desc(struct tmc_drvdata *drvdata, case TMC_CONFIG_TYPE_ETB: desc->type = CORESIGHT_DEV_TYPE_SINK; desc->subtype.sink_subtype = CORESIGHT_DEV_SUBTYPE_SINK_BUFFER; desc->groups = coresight_tmc_etf_groups; desc->ops = &tmc_etb_cs_ops; break; case TMC_CONFIG_TYPE_ETR: desc->type = CORESIGHT_DEV_TYPE_SINK; desc->subtype.sink_subtype = CORESIGHT_DEV_SUBTYPE_SINK_BUFFER; desc->groups = coresight_tmc_etr_groups; desc->ops = &tmc_etr_cs_ops; break; case TMC_CONFIG_TYPE_ETF: desc->type = CORESIGHT_DEV_TYPE_LINKSINK; desc->subtype.link_subtype = CORESIGHT_DEV_SUBTYPE_LINK_FIFO; desc->groups = coresight_tmc_etf_groups; desc->ops = &tmc_etf_cs_ops; break; default: Loading Loading @@ -455,6 +558,7 @@ static int tmc_probe(struct amba_device *adev, const struct amba_id *id) drvdata->memwidth = tmc_get_memwidth(devid); if (drvdata->config_type == TMC_CONFIG_TYPE_ETR) { drvdata->out_mode = TMC_ETR_OUT_MODE_MEM; ret = of_property_read_u32(np, "arm,buffer-size", &drvdata->size); if (ret) Loading @@ -478,7 +582,6 @@ static int tmc_probe(struct amba_device *adev, const struct amba_id *id) desc.pdata = pdata; desc.dev = dev; desc.groups = coresight_tmc_groups; ret = tmc_config_desc(drvdata, &desc); if (ret) goto out; Loading
drivers/hwtracing/coresight/coresight-tmc.h +26 −0 Original line number Diff line number Diff line Loading @@ -9,6 +9,10 @@ #include <linux/dma-mapping.h> #include <linux/miscdevice.h> #include <linux/delay.h> #include <asm/cacheflush.h> #include <linux/of_address.h> #include <linux/amba/bus.h> #define TMC_RSZ 0x004 #define TMC_STS 0x00c Loading Loading @@ -133,8 +137,27 @@ enum etr_mode { ETR_MODE_CATU, /* Use SG mechanism in CATU */ }; enum tmc_etr_out_mode { TMC_ETR_OUT_MODE_NONE, TMC_ETR_OUT_MODE_MEM, TMC_ETR_OUT_MODE_USB, }; static const char * const str_tmc_etr_out_mode[] = { [TMC_ETR_OUT_MODE_NONE] = "none", [TMC_ETR_OUT_MODE_MEM] = "mem", [TMC_ETR_OUT_MODE_USB] = "usb", }; struct etr_buf_operations; struct etr_flat_buf { struct device *dev; dma_addr_t daddr; void *vaddr; size_t size; }; /** * struct etr_buf - Details of the buffer used by ETR * @mode : Mode of the ETR buffer, contiguous, Scatter Gather etc. Loading Loading @@ -197,6 +220,7 @@ struct tmc_drvdata { struct coresight_csr *csr; const char *csr_name; bool enable; enum tmc_etr_out_mode out_mode; }; struct etr_buf_operations { Loading Loading @@ -257,6 +281,8 @@ ssize_t tmc_etb_get_sysfs_trace(struct tmc_drvdata *drvdata, /* ETR functions */ int tmc_read_prepare_etr(struct tmc_drvdata *drvdata); int tmc_read_unprepare_etr(struct tmc_drvdata *drvdata); void tmc_etr_enable_hw(struct tmc_drvdata *drvdata); void tmc_etr_disable_hw(struct tmc_drvdata *drvdata); extern const struct coresight_ops tmc_etr_cs_ops; ssize_t tmc_etr_get_sysfs_trace(struct tmc_drvdata *drvdata, loff_t pos, size_t len, char **bufpp); Loading