Loading drivers/hwtracing/coresight/coresight-tmc-etf.c +9 −3 Original line number Diff line number Diff line Loading @@ -614,9 +614,12 @@ int tmc_read_prepare_etb(struct tmc_drvdata *drvdata) } /* Disable the TMC if need be */ if (drvdata->mode == CS_MODE_SYSFS) if (drvdata->mode == CS_MODE_SYSFS) { spin_unlock_irqrestore(&drvdata->spinlock, flags); coresight_disable_all_source_link(); spin_lock_irqsave(&drvdata->spinlock, flags); __tmc_etb_disable_hw(drvdata); } drvdata->reading = true; out: spin_unlock_irqrestore(&drvdata->spinlock, flags); Loading Loading @@ -646,6 +649,7 @@ int tmc_read_unprepare_etb(struct tmc_drvdata *drvdata) } } drvdata->reading = false; /* Re-enable the TMC if need be */ if (drvdata->mode == CS_MODE_SYSFS) { /* Loading @@ -658,6 +662,9 @@ int tmc_read_unprepare_etb(struct tmc_drvdata *drvdata) */ memset(drvdata->buf, 0, drvdata->size); __tmc_etb_enable_hw(drvdata); spin_unlock_irqrestore(&drvdata->spinlock, flags); coresight_enable_all_source_link(); spin_lock_irqsave(&drvdata->spinlock, flags); } else { /* * The ETB/ETF is not tracing and the buffer was just read. Loading @@ -667,7 +674,6 @@ int tmc_read_unprepare_etb(struct tmc_drvdata *drvdata) drvdata->buf = NULL; } drvdata->reading = false; spin_unlock_irqrestore(&drvdata->spinlock, flags); /* Loading drivers/hwtracing/coresight/coresight-tmc-etr.c +13 −5 Original line number Diff line number Diff line Loading @@ -2015,12 +2015,14 @@ int tmc_etr_switch_mode(struct tmc_drvdata *drvdata, const char *out_mode) return 0; } coresight_disable_all_source_link(); tmc_disable_etr_sink(drvdata->csdev); old_mode = drvdata->out_mode; drvdata->out_mode = new_mode; if (tmc_enable_etr_sink_sysfs(drvdata->csdev)) { drvdata->out_mode = old_mode; tmc_enable_etr_sink_sysfs(drvdata->csdev); coresight_enable_all_source_link(); dev_err(&drvdata->csdev->dev, "Switch to %s failed. Fall back to %s.\n", str_tmc_etr_out_mode[new_mode], Loading @@ -2028,7 +2030,7 @@ int tmc_etr_switch_mode(struct tmc_drvdata *drvdata, const char *out_mode) mutex_unlock(&drvdata->mem_lock); return -EINVAL; } coresight_enable_all_source_link(); mutex_unlock(&drvdata->mem_lock); return 0; } Loading Loading @@ -2081,9 +2083,12 @@ int tmc_read_prepare_etr(struct tmc_drvdata *drvdata) } /* Disable the TMC if we are trying to read from a running session. */ if (drvdata->mode == CS_MODE_SYSFS) if (drvdata->mode == CS_MODE_SYSFS) { spin_unlock_irqrestore(&drvdata->spinlock, flags); coresight_disable_all_source_link(); spin_lock_irqsave(&drvdata->spinlock, flags); __tmc_etr_disable_hw(drvdata); } drvdata->reading = true; out: spin_unlock_irqrestore(&drvdata->spinlock, flags); Loading @@ -2103,6 +2108,7 @@ int tmc_read_unprepare_etr(struct tmc_drvdata *drvdata) mutex_lock(&drvdata->mem_lock); spin_lock_irqsave(&drvdata->spinlock, flags); drvdata->reading = false; /* RE-enable the TMC if need be */ if (drvdata->mode == CS_MODE_SYSFS) { /* Loading @@ -2111,6 +2117,10 @@ int tmc_read_unprepare_etr(struct tmc_drvdata *drvdata) * be NULL. */ __tmc_etr_enable_hw(drvdata); spin_unlock_irqrestore(&drvdata->spinlock, flags); coresight_enable_all_source_link(); spin_lock_irqsave(&drvdata->spinlock, flags); } else { /* * The ETR is not tracing and the buffer was just read. Loading @@ -2120,14 +2130,12 @@ int tmc_read_unprepare_etr(struct tmc_drvdata *drvdata) drvdata->sysfs_buf = NULL; } drvdata->reading = false; spin_unlock_irqrestore(&drvdata->spinlock, flags); /* Free allocated memory out side of the spinlock */ if (sysfs_buf) tmc_etr_free_sysfs_buf(sysfs_buf); mutex_unlock(&drvdata->mem_lock); return 0; } drivers/hwtracing/coresight/coresight.c +141 −2 Original line number Diff line number Diff line Loading @@ -48,6 +48,8 @@ struct coresight_path { static LIST_HEAD(cs_active_paths); static struct coresight_device *activated_sink; /* * When losing synchronisation a new barrier packet needs to be inserted at the * beginning of the data collected in a buffer. That way the decoder knows that Loading Loading @@ -918,6 +920,129 @@ static int coresight_store_path(struct list_head *path) return 0; } static void coresight_enable_source_link(struct list_head *path) { u32 type; int ret; struct coresight_node *nd; struct coresight_device *csdev, *parent, *child; list_for_each_entry_reverse(nd, path, link) { csdev = nd->csdev; type = csdev->type; if (type == CORESIGHT_DEV_TYPE_LINKSINK) type = (csdev == coresight_get_sink(path)) ? CORESIGHT_DEV_TYPE_SINK : CORESIGHT_DEV_TYPE_LINK; switch (type) { case CORESIGHT_DEV_TYPE_SINK: break; case CORESIGHT_DEV_TYPE_SOURCE: if (source_ops(csdev)->enable) { ret = coresight_enable_reg_clk(csdev); if (ret) goto err; ret = source_ops(csdev)->enable(csdev, NULL, CS_MODE_SYSFS); if (ret) { coresight_disable_reg_clk(csdev); goto err; } } csdev->enable = true; break; case CORESIGHT_DEV_TYPE_LINK: parent = list_prev_entry(nd, link)->csdev; child = list_next_entry(nd, link)->csdev; ret = coresight_enable_link(csdev, parent, child, path); if (ret) goto err; break; default: break; } } return; err: coresight_disable_path_from(path, nd); coresight_release_path(path); } static void coresight_disable_source_link(struct list_head *path) { u32 type; struct coresight_node *nd; struct coresight_device *csdev, *parent, *child; list_for_each_entry(nd, path, link) { csdev = nd->csdev; type = csdev->type; if (type == CORESIGHT_DEV_TYPE_LINKSINK) type = (csdev == coresight_get_sink(path)) ? CORESIGHT_DEV_TYPE_SINK : CORESIGHT_DEV_TYPE_LINK; switch (type) { case CORESIGHT_DEV_TYPE_SINK: break; case CORESIGHT_DEV_TYPE_SOURCE: if (source_ops(csdev)->disable) { source_ops(csdev)->disable(csdev, NULL); coresight_disable_reg_clk(csdev); } csdev->enable = false; break; case CORESIGHT_DEV_TYPE_LINK: parent = list_prev_entry(nd, link)->csdev; child = list_next_entry(nd, link)->csdev; coresight_disable_link(csdev, parent, child, path); break; default: break; } } } void coresight_disable_all_source_link(void) { struct coresight_path *cspath = NULL; struct coresight_path *cspath_next = NULL; mutex_lock(&coresight_mutex); list_for_each_entry_safe(cspath, cspath_next, &cs_active_paths, link) { coresight_disable_source_link(cspath->path); } activated_sink = coresight_get_enabled_sink(false); if (activated_sink) activated_sink->activated = false; mutex_unlock(&coresight_mutex); } void coresight_enable_all_source_link(void) { struct coresight_path *cspath = NULL; struct coresight_path *cspath_next = NULL; mutex_lock(&coresight_mutex); list_for_each_entry_safe(cspath, cspath_next, &cs_active_paths, link) { coresight_enable_source_link(cspath->path); } if (activated_sink && activated_sink->enable) activated_sink->activated = true; activated_sink = NULL; mutex_unlock(&coresight_mutex); } int coresight_enable(struct coresight_device *csdev) { int ret = 0; Loading Loading @@ -1041,18 +1166,32 @@ static ssize_t enable_sink_store(struct device *dev, int ret; unsigned long val; struct coresight_device *csdev = to_coresight_device(dev); struct coresight_device *sink = NULL; ret = kstrtoul(buf, 10, &val); if (ret) return ret; mutex_lock(&coresight_mutex); if (val) if (val) { sink = activated_sink ? activated_sink : coresight_get_enabled_sink(false); if (sink && strcmp(dev_name(&sink->dev), dev_name(&csdev->dev))) goto err; csdev->activated = true; else } else { if (csdev->enable) goto err; csdev->activated = false; } mutex_unlock(&coresight_mutex); return size; err: mutex_unlock(&coresight_mutex); return -EINVAL; } static DEVICE_ATTR_RW(enable_sink); Loading include/linux/coresight.h +4 −0 Original line number Diff line number Diff line Loading @@ -313,6 +313,8 @@ extern const char *coresight_alloc_device_name(struct coresight_dev_list *devs, struct device *dev); extern void coresight_disable_reg_clk(struct coresight_device *csdev); extern int coresight_enable_reg_clk(struct coresight_device *csdev); extern void coresight_disable_all_source_link(void); extern void coresight_enable_all_source_link(void); #else static inline struct coresight_device * coresight_register(struct coresight_desc *desc) { return NULL; } Loading @@ -339,6 +341,8 @@ static inline int coresight_enable_reg_clk(struct coresight_device *csdev) { return -EINVAL; } static void coresight_disable_all_source_link(void) {}; static void coresight_enable_all_source_link(void) {}; #endif extern int coresight_get_cpu(struct device *dev); Loading Loading
drivers/hwtracing/coresight/coresight-tmc-etf.c +9 −3 Original line number Diff line number Diff line Loading @@ -614,9 +614,12 @@ int tmc_read_prepare_etb(struct tmc_drvdata *drvdata) } /* Disable the TMC if need be */ if (drvdata->mode == CS_MODE_SYSFS) if (drvdata->mode == CS_MODE_SYSFS) { spin_unlock_irqrestore(&drvdata->spinlock, flags); coresight_disable_all_source_link(); spin_lock_irqsave(&drvdata->spinlock, flags); __tmc_etb_disable_hw(drvdata); } drvdata->reading = true; out: spin_unlock_irqrestore(&drvdata->spinlock, flags); Loading Loading @@ -646,6 +649,7 @@ int tmc_read_unprepare_etb(struct tmc_drvdata *drvdata) } } drvdata->reading = false; /* Re-enable the TMC if need be */ if (drvdata->mode == CS_MODE_SYSFS) { /* Loading @@ -658,6 +662,9 @@ int tmc_read_unprepare_etb(struct tmc_drvdata *drvdata) */ memset(drvdata->buf, 0, drvdata->size); __tmc_etb_enable_hw(drvdata); spin_unlock_irqrestore(&drvdata->spinlock, flags); coresight_enable_all_source_link(); spin_lock_irqsave(&drvdata->spinlock, flags); } else { /* * The ETB/ETF is not tracing and the buffer was just read. Loading @@ -667,7 +674,6 @@ int tmc_read_unprepare_etb(struct tmc_drvdata *drvdata) drvdata->buf = NULL; } drvdata->reading = false; spin_unlock_irqrestore(&drvdata->spinlock, flags); /* Loading
drivers/hwtracing/coresight/coresight-tmc-etr.c +13 −5 Original line number Diff line number Diff line Loading @@ -2015,12 +2015,14 @@ int tmc_etr_switch_mode(struct tmc_drvdata *drvdata, const char *out_mode) return 0; } coresight_disable_all_source_link(); tmc_disable_etr_sink(drvdata->csdev); old_mode = drvdata->out_mode; drvdata->out_mode = new_mode; if (tmc_enable_etr_sink_sysfs(drvdata->csdev)) { drvdata->out_mode = old_mode; tmc_enable_etr_sink_sysfs(drvdata->csdev); coresight_enable_all_source_link(); dev_err(&drvdata->csdev->dev, "Switch to %s failed. Fall back to %s.\n", str_tmc_etr_out_mode[new_mode], Loading @@ -2028,7 +2030,7 @@ int tmc_etr_switch_mode(struct tmc_drvdata *drvdata, const char *out_mode) mutex_unlock(&drvdata->mem_lock); return -EINVAL; } coresight_enable_all_source_link(); mutex_unlock(&drvdata->mem_lock); return 0; } Loading Loading @@ -2081,9 +2083,12 @@ int tmc_read_prepare_etr(struct tmc_drvdata *drvdata) } /* Disable the TMC if we are trying to read from a running session. */ if (drvdata->mode == CS_MODE_SYSFS) if (drvdata->mode == CS_MODE_SYSFS) { spin_unlock_irqrestore(&drvdata->spinlock, flags); coresight_disable_all_source_link(); spin_lock_irqsave(&drvdata->spinlock, flags); __tmc_etr_disable_hw(drvdata); } drvdata->reading = true; out: spin_unlock_irqrestore(&drvdata->spinlock, flags); Loading @@ -2103,6 +2108,7 @@ int tmc_read_unprepare_etr(struct tmc_drvdata *drvdata) mutex_lock(&drvdata->mem_lock); spin_lock_irqsave(&drvdata->spinlock, flags); drvdata->reading = false; /* RE-enable the TMC if need be */ if (drvdata->mode == CS_MODE_SYSFS) { /* Loading @@ -2111,6 +2117,10 @@ int tmc_read_unprepare_etr(struct tmc_drvdata *drvdata) * be NULL. */ __tmc_etr_enable_hw(drvdata); spin_unlock_irqrestore(&drvdata->spinlock, flags); coresight_enable_all_source_link(); spin_lock_irqsave(&drvdata->spinlock, flags); } else { /* * The ETR is not tracing and the buffer was just read. Loading @@ -2120,14 +2130,12 @@ int tmc_read_unprepare_etr(struct tmc_drvdata *drvdata) drvdata->sysfs_buf = NULL; } drvdata->reading = false; spin_unlock_irqrestore(&drvdata->spinlock, flags); /* Free allocated memory out side of the spinlock */ if (sysfs_buf) tmc_etr_free_sysfs_buf(sysfs_buf); mutex_unlock(&drvdata->mem_lock); return 0; }
drivers/hwtracing/coresight/coresight.c +141 −2 Original line number Diff line number Diff line Loading @@ -48,6 +48,8 @@ struct coresight_path { static LIST_HEAD(cs_active_paths); static struct coresight_device *activated_sink; /* * When losing synchronisation a new barrier packet needs to be inserted at the * beginning of the data collected in a buffer. That way the decoder knows that Loading Loading @@ -918,6 +920,129 @@ static int coresight_store_path(struct list_head *path) return 0; } static void coresight_enable_source_link(struct list_head *path) { u32 type; int ret; struct coresight_node *nd; struct coresight_device *csdev, *parent, *child; list_for_each_entry_reverse(nd, path, link) { csdev = nd->csdev; type = csdev->type; if (type == CORESIGHT_DEV_TYPE_LINKSINK) type = (csdev == coresight_get_sink(path)) ? CORESIGHT_DEV_TYPE_SINK : CORESIGHT_DEV_TYPE_LINK; switch (type) { case CORESIGHT_DEV_TYPE_SINK: break; case CORESIGHT_DEV_TYPE_SOURCE: if (source_ops(csdev)->enable) { ret = coresight_enable_reg_clk(csdev); if (ret) goto err; ret = source_ops(csdev)->enable(csdev, NULL, CS_MODE_SYSFS); if (ret) { coresight_disable_reg_clk(csdev); goto err; } } csdev->enable = true; break; case CORESIGHT_DEV_TYPE_LINK: parent = list_prev_entry(nd, link)->csdev; child = list_next_entry(nd, link)->csdev; ret = coresight_enable_link(csdev, parent, child, path); if (ret) goto err; break; default: break; } } return; err: coresight_disable_path_from(path, nd); coresight_release_path(path); } static void coresight_disable_source_link(struct list_head *path) { u32 type; struct coresight_node *nd; struct coresight_device *csdev, *parent, *child; list_for_each_entry(nd, path, link) { csdev = nd->csdev; type = csdev->type; if (type == CORESIGHT_DEV_TYPE_LINKSINK) type = (csdev == coresight_get_sink(path)) ? CORESIGHT_DEV_TYPE_SINK : CORESIGHT_DEV_TYPE_LINK; switch (type) { case CORESIGHT_DEV_TYPE_SINK: break; case CORESIGHT_DEV_TYPE_SOURCE: if (source_ops(csdev)->disable) { source_ops(csdev)->disable(csdev, NULL); coresight_disable_reg_clk(csdev); } csdev->enable = false; break; case CORESIGHT_DEV_TYPE_LINK: parent = list_prev_entry(nd, link)->csdev; child = list_next_entry(nd, link)->csdev; coresight_disable_link(csdev, parent, child, path); break; default: break; } } } void coresight_disable_all_source_link(void) { struct coresight_path *cspath = NULL; struct coresight_path *cspath_next = NULL; mutex_lock(&coresight_mutex); list_for_each_entry_safe(cspath, cspath_next, &cs_active_paths, link) { coresight_disable_source_link(cspath->path); } activated_sink = coresight_get_enabled_sink(false); if (activated_sink) activated_sink->activated = false; mutex_unlock(&coresight_mutex); } void coresight_enable_all_source_link(void) { struct coresight_path *cspath = NULL; struct coresight_path *cspath_next = NULL; mutex_lock(&coresight_mutex); list_for_each_entry_safe(cspath, cspath_next, &cs_active_paths, link) { coresight_enable_source_link(cspath->path); } if (activated_sink && activated_sink->enable) activated_sink->activated = true; activated_sink = NULL; mutex_unlock(&coresight_mutex); } int coresight_enable(struct coresight_device *csdev) { int ret = 0; Loading Loading @@ -1041,18 +1166,32 @@ static ssize_t enable_sink_store(struct device *dev, int ret; unsigned long val; struct coresight_device *csdev = to_coresight_device(dev); struct coresight_device *sink = NULL; ret = kstrtoul(buf, 10, &val); if (ret) return ret; mutex_lock(&coresight_mutex); if (val) if (val) { sink = activated_sink ? activated_sink : coresight_get_enabled_sink(false); if (sink && strcmp(dev_name(&sink->dev), dev_name(&csdev->dev))) goto err; csdev->activated = true; else } else { if (csdev->enable) goto err; csdev->activated = false; } mutex_unlock(&coresight_mutex); return size; err: mutex_unlock(&coresight_mutex); return -EINVAL; } static DEVICE_ATTR_RW(enable_sink); Loading
include/linux/coresight.h +4 −0 Original line number Diff line number Diff line Loading @@ -313,6 +313,8 @@ extern const char *coresight_alloc_device_name(struct coresight_dev_list *devs, struct device *dev); extern void coresight_disable_reg_clk(struct coresight_device *csdev); extern int coresight_enable_reg_clk(struct coresight_device *csdev); extern void coresight_disable_all_source_link(void); extern void coresight_enable_all_source_link(void); #else static inline struct coresight_device * coresight_register(struct coresight_desc *desc) { return NULL; } Loading @@ -339,6 +341,8 @@ static inline int coresight_enable_reg_clk(struct coresight_device *csdev) { return -EINVAL; } static void coresight_disable_all_source_link(void) {}; static void coresight_enable_all_source_link(void) {}; #endif extern int coresight_get_cpu(struct device *dev); Loading