cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

goya_hwmgr.c (8675B)


      1// SPDX-License-Identifier: GPL-2.0
      2
      3/*
      4 * Copyright 2016-2022 HabanaLabs, Ltd.
      5 * All Rights Reserved.
      6 */
      7
      8#include "goyaP.h"
      9
     10void goya_set_pll_profile(struct hl_device *hdev, enum hl_pll_frequency freq)
     11{
     12	struct goya_device *goya = hdev->asic_specific;
     13
     14	if (!hdev->pdev)
     15		return;
     16
     17	switch (freq) {
     18	case PLL_HIGH:
     19		hl_fw_set_frequency(hdev, HL_GOYA_MME_PLL, hdev->high_pll);
     20		hl_fw_set_frequency(hdev, HL_GOYA_TPC_PLL, hdev->high_pll);
     21		hl_fw_set_frequency(hdev, HL_GOYA_IC_PLL, hdev->high_pll);
     22		break;
     23	case PLL_LOW:
     24		hl_fw_set_frequency(hdev, HL_GOYA_MME_PLL, GOYA_PLL_FREQ_LOW);
     25		hl_fw_set_frequency(hdev, HL_GOYA_TPC_PLL, GOYA_PLL_FREQ_LOW);
     26		hl_fw_set_frequency(hdev, HL_GOYA_IC_PLL, GOYA_PLL_FREQ_LOW);
     27		break;
     28	case PLL_LAST:
     29		hl_fw_set_frequency(hdev, HL_GOYA_MME_PLL, goya->mme_clk);
     30		hl_fw_set_frequency(hdev, HL_GOYA_TPC_PLL, goya->tpc_clk);
     31		hl_fw_set_frequency(hdev, HL_GOYA_IC_PLL, goya->ic_clk);
     32		break;
     33	default:
     34		dev_err(hdev->dev, "unknown frequency setting\n");
     35	}
     36}
     37
     38static ssize_t mme_clk_show(struct device *dev, struct device_attribute *attr,
     39				char *buf)
     40{
     41	struct hl_device *hdev = dev_get_drvdata(dev);
     42	long value;
     43
     44	if (!hl_device_operational(hdev, NULL))
     45		return -ENODEV;
     46
     47	value = hl_fw_get_frequency(hdev, HL_GOYA_MME_PLL, false);
     48
     49	if (value < 0)
     50		return value;
     51
     52	return sprintf(buf, "%lu\n", value);
     53}
     54
     55static ssize_t mme_clk_store(struct device *dev, struct device_attribute *attr,
     56				const char *buf, size_t count)
     57{
     58	struct hl_device *hdev = dev_get_drvdata(dev);
     59	struct goya_device *goya = hdev->asic_specific;
     60	int rc;
     61	long value;
     62
     63	if (!hl_device_operational(hdev, NULL)) {
     64		count = -ENODEV;
     65		goto fail;
     66	}
     67
     68	if (goya->pm_mng_profile == PM_AUTO) {
     69		count = -EPERM;
     70		goto fail;
     71	}
     72
     73	rc = kstrtoul(buf, 0, &value);
     74
     75	if (rc) {
     76		count = -EINVAL;
     77		goto fail;
     78	}
     79
     80	hl_fw_set_frequency(hdev, HL_GOYA_MME_PLL, value);
     81	goya->mme_clk = value;
     82
     83fail:
     84	return count;
     85}
     86
     87static ssize_t tpc_clk_show(struct device *dev, struct device_attribute *attr,
     88				char *buf)
     89{
     90	struct hl_device *hdev = dev_get_drvdata(dev);
     91	long value;
     92
     93	if (!hl_device_operational(hdev, NULL))
     94		return -ENODEV;
     95
     96	value = hl_fw_get_frequency(hdev, HL_GOYA_TPC_PLL, false);
     97
     98	if (value < 0)
     99		return value;
    100
    101	return sprintf(buf, "%lu\n", value);
    102}
    103
    104static ssize_t tpc_clk_store(struct device *dev, struct device_attribute *attr,
    105				const char *buf, size_t count)
    106{
    107	struct hl_device *hdev = dev_get_drvdata(dev);
    108	struct goya_device *goya = hdev->asic_specific;
    109	int rc;
    110	long value;
    111
    112	if (!hl_device_operational(hdev, NULL)) {
    113		count = -ENODEV;
    114		goto fail;
    115	}
    116
    117	if (goya->pm_mng_profile == PM_AUTO) {
    118		count = -EPERM;
    119		goto fail;
    120	}
    121
    122	rc = kstrtoul(buf, 0, &value);
    123
    124	if (rc) {
    125		count = -EINVAL;
    126		goto fail;
    127	}
    128
    129	hl_fw_set_frequency(hdev, HL_GOYA_TPC_PLL, value);
    130	goya->tpc_clk = value;
    131
    132fail:
    133	return count;
    134}
    135
    136static ssize_t ic_clk_show(struct device *dev, struct device_attribute *attr,
    137				char *buf)
    138{
    139	struct hl_device *hdev = dev_get_drvdata(dev);
    140	long value;
    141
    142	if (!hl_device_operational(hdev, NULL))
    143		return -ENODEV;
    144
    145	value = hl_fw_get_frequency(hdev, HL_GOYA_IC_PLL, false);
    146
    147	if (value < 0)
    148		return value;
    149
    150	return sprintf(buf, "%lu\n", value);
    151}
    152
    153static ssize_t ic_clk_store(struct device *dev, struct device_attribute *attr,
    154				const char *buf, size_t count)
    155{
    156	struct hl_device *hdev = dev_get_drvdata(dev);
    157	struct goya_device *goya = hdev->asic_specific;
    158	int rc;
    159	long value;
    160
    161	if (!hl_device_operational(hdev, NULL)) {
    162		count = -ENODEV;
    163		goto fail;
    164	}
    165
    166	if (goya->pm_mng_profile == PM_AUTO) {
    167		count = -EPERM;
    168		goto fail;
    169	}
    170
    171	rc = kstrtoul(buf, 0, &value);
    172
    173	if (rc) {
    174		count = -EINVAL;
    175		goto fail;
    176	}
    177
    178	hl_fw_set_frequency(hdev, HL_GOYA_IC_PLL, value);
    179	goya->ic_clk = value;
    180
    181fail:
    182	return count;
    183}
    184
    185static ssize_t mme_clk_curr_show(struct device *dev,
    186				struct device_attribute *attr, char *buf)
    187{
    188	struct hl_device *hdev = dev_get_drvdata(dev);
    189	long value;
    190
    191	if (!hl_device_operational(hdev, NULL))
    192		return -ENODEV;
    193
    194	value = hl_fw_get_frequency(hdev, HL_GOYA_MME_PLL, true);
    195
    196	if (value < 0)
    197		return value;
    198
    199	return sprintf(buf, "%lu\n", value);
    200}
    201
    202static ssize_t tpc_clk_curr_show(struct device *dev,
    203				struct device_attribute *attr, char *buf)
    204{
    205	struct hl_device *hdev = dev_get_drvdata(dev);
    206	long value;
    207
    208	if (!hl_device_operational(hdev, NULL))
    209		return -ENODEV;
    210
    211	value = hl_fw_get_frequency(hdev, HL_GOYA_TPC_PLL, true);
    212
    213	if (value < 0)
    214		return value;
    215
    216	return sprintf(buf, "%lu\n", value);
    217}
    218
    219static ssize_t ic_clk_curr_show(struct device *dev,
    220				struct device_attribute *attr, char *buf)
    221{
    222	struct hl_device *hdev = dev_get_drvdata(dev);
    223	long value;
    224
    225	if (!hl_device_operational(hdev, NULL))
    226		return -ENODEV;
    227
    228	value = hl_fw_get_frequency(hdev, HL_GOYA_IC_PLL, true);
    229
    230	if (value < 0)
    231		return value;
    232
    233	return sprintf(buf, "%lu\n", value);
    234}
    235
    236static ssize_t pm_mng_profile_show(struct device *dev,
    237				struct device_attribute *attr, char *buf)
    238{
    239	struct hl_device *hdev = dev_get_drvdata(dev);
    240	struct goya_device *goya = hdev->asic_specific;
    241
    242	if (!hl_device_operational(hdev, NULL))
    243		return -ENODEV;
    244
    245	return sprintf(buf, "%s\n",
    246			(goya->pm_mng_profile == PM_AUTO) ? "auto" :
    247			(goya->pm_mng_profile == PM_MANUAL) ? "manual" :
    248			"unknown");
    249}
    250
    251static ssize_t pm_mng_profile_store(struct device *dev,
    252		struct device_attribute *attr, const char *buf, size_t count)
    253{
    254	struct hl_device *hdev = dev_get_drvdata(dev);
    255	struct goya_device *goya = hdev->asic_specific;
    256
    257	if (!hl_device_operational(hdev, NULL)) {
    258		count = -ENODEV;
    259		goto out;
    260	}
    261
    262	mutex_lock(&hdev->fpriv_list_lock);
    263
    264	if (hdev->is_compute_ctx_active) {
    265		dev_err(hdev->dev,
    266			"Can't change PM profile while compute context is opened on the device\n");
    267		count = -EPERM;
    268		goto unlock_mutex;
    269	}
    270
    271	if (strncmp("auto", buf, strlen("auto")) == 0) {
    272		/* Make sure we are in LOW PLL when changing modes */
    273		if (goya->pm_mng_profile == PM_MANUAL) {
    274			goya->curr_pll_profile = PLL_HIGH;
    275			goya->pm_mng_profile = PM_AUTO;
    276			goya_set_frequency(hdev, PLL_LOW);
    277		}
    278	} else if (strncmp("manual", buf, strlen("manual")) == 0) {
    279		if (goya->pm_mng_profile == PM_AUTO) {
    280			/* Must release the lock because the work thread also
    281			 * takes this lock. But before we release it, set
    282			 * the mode to manual so nothing will change if a user
    283			 * suddenly opens the device
    284			 */
    285			goya->pm_mng_profile = PM_MANUAL;
    286
    287			mutex_unlock(&hdev->fpriv_list_lock);
    288
    289			/* Flush the current work so we can return to the user
    290			 * knowing that he is the only one changing frequencies
    291			 */
    292			if (goya->goya_work)
    293				flush_delayed_work(&goya->goya_work->work_freq);
    294
    295			return count;
    296		}
    297	} else {
    298		dev_err(hdev->dev, "value should be auto or manual\n");
    299		count = -EINVAL;
    300	}
    301
    302unlock_mutex:
    303	mutex_unlock(&hdev->fpriv_list_lock);
    304out:
    305	return count;
    306}
    307
    308static ssize_t high_pll_show(struct device *dev, struct device_attribute *attr,
    309				char *buf)
    310{
    311	struct hl_device *hdev = dev_get_drvdata(dev);
    312
    313	if (!hl_device_operational(hdev, NULL))
    314		return -ENODEV;
    315
    316	return sprintf(buf, "%u\n", hdev->high_pll);
    317}
    318
    319static ssize_t high_pll_store(struct device *dev, struct device_attribute *attr,
    320				const char *buf, size_t count)
    321{
    322	struct hl_device *hdev = dev_get_drvdata(dev);
    323	long value;
    324	int rc;
    325
    326	if (!hl_device_operational(hdev, NULL)) {
    327		count = -ENODEV;
    328		goto out;
    329	}
    330
    331	rc = kstrtoul(buf, 0, &value);
    332
    333	if (rc) {
    334		count = -EINVAL;
    335		goto out;
    336	}
    337
    338	hdev->high_pll = value;
    339
    340out:
    341	return count;
    342}
    343
    344static DEVICE_ATTR_RW(high_pll);
    345static DEVICE_ATTR_RW(ic_clk);
    346static DEVICE_ATTR_RO(ic_clk_curr);
    347static DEVICE_ATTR_RW(mme_clk);
    348static DEVICE_ATTR_RO(mme_clk_curr);
    349static DEVICE_ATTR_RW(pm_mng_profile);
    350static DEVICE_ATTR_RW(tpc_clk);
    351static DEVICE_ATTR_RO(tpc_clk_curr);
    352
    353static struct attribute *goya_clk_dev_attrs[] = {
    354	&dev_attr_high_pll.attr,
    355	&dev_attr_ic_clk.attr,
    356	&dev_attr_ic_clk_curr.attr,
    357	&dev_attr_mme_clk.attr,
    358	&dev_attr_mme_clk_curr.attr,
    359	&dev_attr_pm_mng_profile.attr,
    360	&dev_attr_tpc_clk.attr,
    361	&dev_attr_tpc_clk_curr.attr,
    362};
    363
    364static ssize_t infineon_ver_show(struct device *dev, struct device_attribute *attr, char *buf)
    365{
    366	struct hl_device *hdev = dev_get_drvdata(dev);
    367	struct cpucp_info *cpucp_info;
    368
    369	cpucp_info = &hdev->asic_prop.cpucp_info;
    370
    371	return sprintf(buf, "%#04x\n", le32_to_cpu(cpucp_info->infineon_version));
    372}
    373
    374static DEVICE_ATTR_RO(infineon_ver);
    375
    376static struct attribute *goya_vrm_dev_attrs[] = {
    377	&dev_attr_infineon_ver.attr,
    378};
    379
    380void goya_add_device_attr(struct hl_device *hdev, struct attribute_group *dev_clk_attr_grp,
    381				struct attribute_group *dev_vrm_attr_grp)
    382{
    383	dev_clk_attr_grp->attrs = goya_clk_dev_attrs;
    384	dev_vrm_attr_grp->attrs = goya_vrm_dev_attrs;
    385}