Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

platform/mellanox: mlxbf-pmc: Add support for monitoring cycle count

Add support for programming any counter to monitor the cycle count.
This will allow the user to repurpose and dedicate any of the counters
in the block to counting cycles.

Signed-off-by: Shravan Kumar Ramani <shravankr@nvidia.com>
Reviewed-by: David Thompson <davthompson@nvidia.com>
Reviewed-by: Vadim Pasternak <vadimp@nvidia.com>
Link: https://lore.kernel.org/r/bd7747897cf1ce77e2e39e271cac21684830f7e7.1736413033.git.shravankr@nvidia.com
Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>

authored by

Shravan Kumar Ramani and committed by
Ilpo Järvinen
5efc8009 1b32401b

+61
+61
drivers/platform/mellanox/mlxbf-pmc.c
··· 88 88 #define MLXBF_PMC_CRSPACE_PERFMON_CTL(n) (n * MLXBF_PMC_CRSPACE_PERFMON_REG0_SZ) 89 89 #define MLXBF_PMC_CRSPACE_PERFMON_EN BIT(30) 90 90 #define MLXBF_PMC_CRSPACE_PERFMON_CLR BIT(28) 91 + #define MLXBF_PMC_CRSPACE_PERFMON_COUNT_CLOCK(n) (MLXBF_PMC_CRSPACE_PERFMON_CTL(n) + 0x4) 91 92 #define MLXBF_PMC_CRSPACE_PERFMON_VAL0(n) (MLXBF_PMC_CRSPACE_PERFMON_CTL(n) + 0xc) 92 93 93 94 /** ··· 115 114 * @attr_event: Attributes for "event" sysfs files 116 115 * @attr_event_list: Attributes for "event_list" sysfs files 117 116 * @attr_enable: Attributes for "enable" sysfs files 117 + * @attr_count_clock: Attributes for "count_clock" sysfs files 118 118 * @block_attr: All attributes needed for the block 119 119 * @block_attr_grp: Attribute group for the block 120 120 */ ··· 128 126 struct mlxbf_pmc_attribute *attr_event; 129 127 struct mlxbf_pmc_attribute attr_event_list; 130 128 struct mlxbf_pmc_attribute attr_enable; 129 + struct mlxbf_pmc_attribute attr_count_clock; 131 130 struct attribute *block_attr[MLXBF_PMC_MAX_ATTRS]; 132 131 struct attribute_group block_attr_grp; 133 132 }; ··· 1766 1763 return count; 1767 1764 } 1768 1765 1766 + /* Show function for "count_clock" sysfs files - only for crspace */ 1767 + static ssize_t mlxbf_pmc_count_clock_show(struct device *dev, 1768 + struct device_attribute *attr, char *buf) 1769 + { 1770 + struct mlxbf_pmc_attribute *attr_count_clock = container_of( 1771 + attr, struct mlxbf_pmc_attribute, dev_attr); 1772 + unsigned int blk_num; 1773 + u32 reg; 1774 + 1775 + blk_num = attr_count_clock->nr; 1776 + 1777 + if (mlxbf_pmc_readl(pmc->block[blk_num].mmio_base + 1778 + MLXBF_PMC_CRSPACE_PERFMON_COUNT_CLOCK(pmc->block[blk_num].counters), 1779 + &reg)) 1780 + return -EINVAL; 1781 + 1782 + return sysfs_emit(buf, "%u\n", reg); 1783 + } 1784 + 1785 + /* Store function for "count_clock" sysfs files - only for crspace */ 1786 + static ssize_t mlxbf_pmc_count_clock_store(struct device *dev, 1787 + struct device_attribute *attr, 1788 + const char *buf, size_t count) 1789 + { 1790 + struct mlxbf_pmc_attribute *attr_count_clock = container_of( 1791 + attr, struct mlxbf_pmc_attribute, dev_attr); 1792 + unsigned int blk_num; 1793 + u32 reg; 1794 + int err; 1795 + 1796 + blk_num = attr_count_clock->nr; 1797 + 1798 + err = kstrtouint(buf, 0, &reg); 1799 + if (err < 0) 1800 + return err; 1801 + 1802 + mlxbf_pmc_write(pmc->block[blk_num].mmio_base + 1803 + MLXBF_PMC_CRSPACE_PERFMON_COUNT_CLOCK(pmc->block[blk_num].counters), 1804 + MLXBF_PMC_WRITE_REG_32, reg); 1805 + 1806 + return count; 1807 + } 1808 + 1769 1809 /* Populate attributes for blocks with counters to monitor performance */ 1770 1810 static int mlxbf_pmc_init_perftype_counter(struct device *dev, unsigned int blk_num) 1771 1811 { ··· 1841 1795 attr->nr = blk_num; 1842 1796 attr->dev_attr.attr.name = devm_kasprintf(dev, GFP_KERNEL, 1843 1797 "enable"); 1798 + if (!attr->dev_attr.attr.name) 1799 + return -ENOMEM; 1800 + pmc->block[blk_num].block_attr[++i] = &attr->dev_attr.attr; 1801 + attr = NULL; 1802 + } 1803 + 1804 + if (pmc->block[blk_num].type == MLXBF_PMC_TYPE_CRSPACE) { 1805 + /* Program crspace counters to count clock cycles using "count_clock" sysfs */ 1806 + attr = &pmc->block[blk_num].attr_count_clock; 1807 + attr->dev_attr.attr.mode = 0644; 1808 + attr->dev_attr.show = mlxbf_pmc_count_clock_show; 1809 + attr->dev_attr.store = mlxbf_pmc_count_clock_store; 1810 + attr->nr = blk_num; 1811 + attr->dev_attr.attr.name = devm_kasprintf(dev, GFP_KERNEL, 1812 + "count_clock"); 1844 1813 if (!attr->dev_attr.attr.name) 1845 1814 return -ENOMEM; 1846 1815 pmc->block[blk_num].block_attr[++i] = &attr->dev_attr.attr;