Path: blob/master/drivers/accel/habanalabs/common/sysfs.c
26436 views
// SPDX-License-Identifier: GPL-2.012/*3* Copyright 2016-2022 HabanaLabs, Ltd.4* All Rights Reserved.5*/67#include "habanalabs.h"89#include <linux/pci.h>10#include <linux/types.h>1112static ssize_t clk_max_freq_mhz_show(struct device *dev, struct device_attribute *attr, char *buf)13{14struct hl_device *hdev = dev_get_drvdata(dev);15long value;1617if (!hl_device_operational(hdev, NULL))18return -ENODEV;1920value = hl_fw_get_frequency(hdev, hdev->asic_prop.clk_pll_index, false);21if (value < 0)22return value;2324hdev->asic_prop.max_freq_value = value;2526return sprintf(buf, "%lu\n", (value / 1000 / 1000));27}2829static ssize_t clk_max_freq_mhz_store(struct device *dev, struct device_attribute *attr,30const char *buf, size_t count)31{32struct hl_device *hdev = dev_get_drvdata(dev);33int rc;34u64 value;3536if (!hl_device_operational(hdev, NULL)) {37count = -ENODEV;38goto fail;39}4041rc = kstrtoull(buf, 0, &value);42if (rc) {43count = -EINVAL;44goto fail;45}4647hdev->asic_prop.max_freq_value = value * 1000 * 1000;4849hl_fw_set_frequency(hdev, hdev->asic_prop.clk_pll_index, hdev->asic_prop.max_freq_value);5051fail:52return count;53}5455static ssize_t clk_cur_freq_mhz_show(struct device *dev, struct device_attribute *attr, char *buf)56{57struct hl_device *hdev = dev_get_drvdata(dev);58long value;5960if (!hl_device_operational(hdev, NULL))61return -ENODEV;6263value = hl_fw_get_frequency(hdev, hdev->asic_prop.clk_pll_index, true);64if (value < 0)65return value;6667return sprintf(buf, "%lu\n", (value / 1000 / 1000));68}6970static DEVICE_ATTR_RW(clk_max_freq_mhz);71static DEVICE_ATTR_RO(clk_cur_freq_mhz);7273static struct attribute *hl_dev_clk_attrs[] = {74&dev_attr_clk_max_freq_mhz.attr,75&dev_attr_clk_cur_freq_mhz.attr,76NULL,77};7879static ssize_t vrm_ver_show(struct device *dev, struct device_attribute *attr, char *buf)80{81struct hl_device *hdev = dev_get_drvdata(dev);82struct cpucp_info *cpucp_info;83u32 infineon_second_stage_version;84u32 infineon_second_stage_first_instance;85u32 infineon_second_stage_second_instance;86u32 infineon_second_stage_third_instance;87u32 mask = 0xff;8889cpucp_info = &hdev->asic_prop.cpucp_info;9091infineon_second_stage_version = le32_to_cpu(cpucp_info->infineon_second_stage_version);92infineon_second_stage_first_instance = infineon_second_stage_version & mask;93infineon_second_stage_second_instance =94(infineon_second_stage_version >> 8) & mask;95infineon_second_stage_third_instance =96(infineon_second_stage_version >> 16) & mask;9798if (cpucp_info->infineon_second_stage_version)99return sprintf(buf, "%#04x %#04x:%#04x:%#04x\n",100le32_to_cpu(cpucp_info->infineon_version),101infineon_second_stage_first_instance,102infineon_second_stage_second_instance,103infineon_second_stage_third_instance);104else105return sprintf(buf, "%#04x\n", le32_to_cpu(cpucp_info->infineon_version));106}107108static DEVICE_ATTR_RO(vrm_ver);109110static struct attribute *hl_dev_vrm_attrs[] = {111&dev_attr_vrm_ver.attr,112NULL,113};114115static ssize_t uboot_ver_show(struct device *dev, struct device_attribute *attr,116char *buf)117{118struct hl_device *hdev = dev_get_drvdata(dev);119120return sprintf(buf, "%s\n", hdev->asic_prop.uboot_ver);121}122123static ssize_t armcp_kernel_ver_show(struct device *dev,124struct device_attribute *attr, char *buf)125{126struct hl_device *hdev = dev_get_drvdata(dev);127128return sprintf(buf, "%s", hdev->asic_prop.cpucp_info.kernel_version);129}130131static ssize_t armcp_ver_show(struct device *dev, struct device_attribute *attr,132char *buf)133{134struct hl_device *hdev = dev_get_drvdata(dev);135136return sprintf(buf, "%s\n", hdev->asic_prop.cpucp_info.cpucp_version);137}138139static ssize_t cpld_ver_show(struct device *dev, struct device_attribute *attr,140char *buf)141{142struct hl_device *hdev = dev_get_drvdata(dev);143144return sprintf(buf, "0x%08x%08x\n",145le32_to_cpu(hdev->asic_prop.cpucp_info.cpld_timestamp),146le32_to_cpu(hdev->asic_prop.cpucp_info.cpld_version));147}148149static ssize_t cpucp_kernel_ver_show(struct device *dev,150struct device_attribute *attr, char *buf)151{152struct hl_device *hdev = dev_get_drvdata(dev);153154return sprintf(buf, "%s", hdev->asic_prop.cpucp_info.kernel_version);155}156157static ssize_t cpucp_ver_show(struct device *dev, struct device_attribute *attr,158char *buf)159{160struct hl_device *hdev = dev_get_drvdata(dev);161162return sprintf(buf, "%s\n", hdev->asic_prop.cpucp_info.cpucp_version);163}164165static ssize_t fuse_ver_show(struct device *dev, struct device_attribute *attr,166char *buf)167{168struct hl_device *hdev = dev_get_drvdata(dev);169170return sprintf(buf, "%s\n", hdev->asic_prop.cpucp_info.fuse_version);171}172173static ssize_t thermal_ver_show(struct device *dev,174struct device_attribute *attr, char *buf)175{176struct hl_device *hdev = dev_get_drvdata(dev);177178return sprintf(buf, "%s", hdev->asic_prop.cpucp_info.thermal_version);179}180181static ssize_t fw_os_ver_show(struct device *dev,182struct device_attribute *attr, char *buf)183{184struct hl_device *hdev = dev_get_drvdata(dev);185186return sprintf(buf, "%s", hdev->asic_prop.cpucp_info.fw_os_version);187}188189static ssize_t preboot_btl_ver_show(struct device *dev,190struct device_attribute *attr, char *buf)191{192struct hl_device *hdev = dev_get_drvdata(dev);193194return sprintf(buf, "%s\n", hdev->asic_prop.preboot_ver);195}196197static ssize_t soft_reset_store(struct device *dev,198struct device_attribute *attr, const char *buf,199size_t count)200{201struct hl_device *hdev = dev_get_drvdata(dev);202long value;203int rc;204205rc = kstrtoul(buf, 0, &value);206207if (rc) {208count = -EINVAL;209goto out;210}211212if (!hdev->asic_prop.allow_inference_soft_reset) {213dev_err(hdev->dev, "Device does not support inference soft-reset\n");214goto out;215}216217dev_warn(hdev->dev, "Inference Soft-Reset requested through sysfs\n");218219hl_device_reset(hdev, 0);220221out:222return count;223}224225static ssize_t hard_reset_store(struct device *dev,226struct device_attribute *attr,227const char *buf, size_t count)228{229struct hl_device *hdev = dev_get_drvdata(dev);230long value;231int rc;232233rc = kstrtoul(buf, 0, &value);234235if (rc) {236count = -EINVAL;237goto out;238}239240dev_warn(hdev->dev, "Hard-Reset requested through sysfs\n");241242hl_device_reset(hdev, HL_DRV_RESET_HARD);243244out:245return count;246}247248static ssize_t device_type_show(struct device *dev,249struct device_attribute *attr, char *buf)250{251struct hl_device *hdev = dev_get_drvdata(dev);252char *str;253254switch (hdev->asic_type) {255case ASIC_GOYA:256str = "GOYA";257break;258case ASIC_GAUDI:259str = "GAUDI";260break;261case ASIC_GAUDI_SEC:262str = "GAUDI SEC";263break;264case ASIC_GAUDI2:265str = "GAUDI2";266break;267case ASIC_GAUDI2B:268str = "GAUDI2B";269break;270case ASIC_GAUDI2C:271str = "GAUDI2C";272break;273case ASIC_GAUDI2D:274str = "GAUDI2D";275break;276default:277dev_err(hdev->dev, "Unrecognized ASIC type %d\n",278hdev->asic_type);279return -EINVAL;280}281282return sprintf(buf, "%s\n", str);283}284285static ssize_t pci_addr_show(struct device *dev, struct device_attribute *attr,286char *buf)287{288struct hl_device *hdev = dev_get_drvdata(dev);289290return sprintf(buf, "%04x:%02x:%02x.%x\n",291pci_domain_nr(hdev->pdev->bus),292hdev->pdev->bus->number,293PCI_SLOT(hdev->pdev->devfn),294PCI_FUNC(hdev->pdev->devfn));295}296297static ssize_t status_show(struct device *dev, struct device_attribute *attr,298char *buf)299{300struct hl_device *hdev = dev_get_drvdata(dev);301char str[HL_STR_MAX];302303strscpy(str, hdev->status[hl_device_status(hdev)], HL_STR_MAX);304305/* use uppercase for backward compatibility */306str[0] = 'A' + (str[0] - 'a');307308return sprintf(buf, "%s\n", str);309}310311static ssize_t soft_reset_cnt_show(struct device *dev,312struct device_attribute *attr, char *buf)313{314struct hl_device *hdev = dev_get_drvdata(dev);315316return sprintf(buf, "%d\n", hdev->reset_info.compute_reset_cnt);317}318319static ssize_t hard_reset_cnt_show(struct device *dev,320struct device_attribute *attr, char *buf)321{322struct hl_device *hdev = dev_get_drvdata(dev);323324return sprintf(buf, "%d\n", hdev->reset_info.hard_reset_cnt);325}326327static ssize_t max_power_show(struct device *dev, struct device_attribute *attr,328char *buf)329{330struct hl_device *hdev = dev_get_drvdata(dev);331long val;332333if (!hl_device_operational(hdev, NULL))334return -ENODEV;335336val = hl_fw_get_max_power(hdev);337if (val < 0)338return val;339340return sprintf(buf, "%lu\n", val);341}342343static ssize_t max_power_store(struct device *dev,344struct device_attribute *attr, const char *buf, size_t count)345{346struct hl_device *hdev = dev_get_drvdata(dev);347unsigned long value;348int rc;349350if (!hl_device_operational(hdev, NULL)) {351count = -ENODEV;352goto out;353}354355rc = kstrtoul(buf, 0, &value);356357if (rc) {358count = -EINVAL;359goto out;360}361362hdev->max_power = value;363hl_fw_set_max_power(hdev);364365out:366return count;367}368369static ssize_t eeprom_read_handler(struct file *filp, struct kobject *kobj,370const struct bin_attribute *attr, char *buf, loff_t offset,371size_t max_size)372{373struct device *dev = kobj_to_dev(kobj);374struct hl_device *hdev = dev_get_drvdata(dev);375char *data;376int rc;377378if (!hl_device_operational(hdev, NULL))379return -ENODEV;380381if (!max_size)382return -EINVAL;383384data = kzalloc(max_size, GFP_KERNEL);385if (!data)386return -ENOMEM;387388rc = hdev->asic_funcs->get_eeprom_data(hdev, data, max_size);389if (rc)390goto out;391392memcpy(buf, data, max_size);393394out:395kfree(data);396397return max_size;398}399400static ssize_t security_enabled_show(struct device *dev,401struct device_attribute *attr, char *buf)402{403struct hl_device *hdev = dev_get_drvdata(dev);404405return sprintf(buf, "%d\n", hdev->asic_prop.fw_security_enabled);406}407408static ssize_t module_id_show(struct device *dev,409struct device_attribute *attr, char *buf)410{411struct hl_device *hdev = dev_get_drvdata(dev);412413return sprintf(buf, "%u\n", le32_to_cpu(hdev->asic_prop.cpucp_info.card_location));414}415416static ssize_t parent_device_show(struct device *dev, struct device_attribute *attr, char *buf)417{418struct hl_device *hdev = dev_get_drvdata(dev);419420return sprintf(buf, "%s\n", HL_DEV_NAME(hdev));421}422423static DEVICE_ATTR_RO(armcp_kernel_ver);424static DEVICE_ATTR_RO(armcp_ver);425static DEVICE_ATTR_RO(cpld_ver);426static DEVICE_ATTR_RO(cpucp_kernel_ver);427static DEVICE_ATTR_RO(cpucp_ver);428static DEVICE_ATTR_RO(device_type);429static DEVICE_ATTR_RO(fuse_ver);430static DEVICE_ATTR_WO(hard_reset);431static DEVICE_ATTR_RO(hard_reset_cnt);432static DEVICE_ATTR_RW(max_power);433static DEVICE_ATTR_RO(pci_addr);434static DEVICE_ATTR_RO(preboot_btl_ver);435static DEVICE_ATTR_WO(soft_reset);436static DEVICE_ATTR_RO(soft_reset_cnt);437static DEVICE_ATTR_RO(status);438static DEVICE_ATTR_RO(thermal_ver);439static DEVICE_ATTR_RO(uboot_ver);440static DEVICE_ATTR_RO(fw_os_ver);441static DEVICE_ATTR_RO(security_enabled);442static DEVICE_ATTR_RO(module_id);443static DEVICE_ATTR_RO(parent_device);444445static const struct bin_attribute bin_attr_eeprom = {446.attr = {.name = "eeprom", .mode = (0444)},447.size = PAGE_SIZE,448.read = eeprom_read_handler449};450451static struct attribute *hl_dev_attrs[] = {452&dev_attr_armcp_kernel_ver.attr,453&dev_attr_armcp_ver.attr,454&dev_attr_cpld_ver.attr,455&dev_attr_cpucp_kernel_ver.attr,456&dev_attr_cpucp_ver.attr,457&dev_attr_device_type.attr,458&dev_attr_fuse_ver.attr,459&dev_attr_hard_reset.attr,460&dev_attr_hard_reset_cnt.attr,461&dev_attr_max_power.attr,462&dev_attr_pci_addr.attr,463&dev_attr_preboot_btl_ver.attr,464&dev_attr_status.attr,465&dev_attr_thermal_ver.attr,466&dev_attr_uboot_ver.attr,467&dev_attr_fw_os_ver.attr,468&dev_attr_security_enabled.attr,469&dev_attr_module_id.attr,470&dev_attr_parent_device.attr,471NULL,472};473474static const struct bin_attribute *const hl_dev_bin_attrs[] = {475&bin_attr_eeprom,476NULL477};478479static struct attribute_group hl_dev_attr_group = {480.attrs = hl_dev_attrs,481.bin_attrs = hl_dev_bin_attrs,482};483484static struct attribute_group hl_dev_clks_attr_group;485static struct attribute_group hl_dev_vrm_attr_group;486487static const struct attribute_group *hl_dev_attr_groups[] = {488&hl_dev_attr_group,489&hl_dev_clks_attr_group,490&hl_dev_vrm_attr_group,491NULL,492};493494static struct attribute *hl_dev_inference_attrs[] = {495&dev_attr_soft_reset.attr,496&dev_attr_soft_reset_cnt.attr,497NULL,498};499500static struct attribute_group hl_dev_inference_attr_group = {501.attrs = hl_dev_inference_attrs,502};503504static const struct attribute_group *hl_dev_inference_attr_groups[] = {505&hl_dev_inference_attr_group,506NULL,507};508509void hl_sysfs_add_dev_clk_attr(struct hl_device *hdev, struct attribute_group *dev_clk_attr_grp)510{511dev_clk_attr_grp->attrs = hl_dev_clk_attrs;512}513514void hl_sysfs_add_dev_vrm_attr(struct hl_device *hdev, struct attribute_group *dev_vrm_attr_grp)515{516dev_vrm_attr_grp->attrs = hl_dev_vrm_attrs;517}518519int hl_sysfs_init(struct hl_device *hdev)520{521int rc;522523hdev->max_power = hdev->asic_prop.max_power_default;524525hdev->asic_funcs->add_device_attr(hdev, &hl_dev_clks_attr_group, &hl_dev_vrm_attr_group);526527rc = device_add_groups(hdev->dev, hl_dev_attr_groups);528if (rc) {529dev_err(hdev->dev,530"Failed to add groups to device, error %d\n", rc);531return rc;532}533534if (!hdev->asic_prop.allow_inference_soft_reset)535return 0;536537rc = device_add_groups(hdev->dev, hl_dev_inference_attr_groups);538if (rc) {539dev_err(hdev->dev,540"Failed to add groups to device, error %d\n", rc);541goto remove_groups;542}543544return 0;545546remove_groups:547device_remove_groups(hdev->dev, hl_dev_attr_groups);548return rc;549}550551void hl_sysfs_fini(struct hl_device *hdev)552{553device_remove_groups(hdev->dev, hl_dev_attr_groups);554555if (!hdev->asic_prop.allow_inference_soft_reset)556return;557558device_remove_groups(hdev->dev, hl_dev_inference_attr_groups);559}560561562