sysfs.c (11603B)
1// SPDX-License-Identifier: GPL-2.0 2 3/* 4 * Copyright 2016-2022 HabanaLabs, Ltd. 5 * All Rights Reserved. 6 */ 7 8#include "habanalabs.h" 9 10#include <linux/pci.h> 11 12static ssize_t clk_max_freq_mhz_show(struct device *dev, struct device_attribute *attr, char *buf) 13{ 14 struct hl_device *hdev = dev_get_drvdata(dev); 15 long value; 16 17 if (!hl_device_operational(hdev, NULL)) 18 return -ENODEV; 19 20 value = hl_fw_get_frequency(hdev, hdev->asic_prop.clk_pll_index, false); 21 if (value < 0) 22 return value; 23 24 hdev->asic_prop.max_freq_value = value; 25 26 return sprintf(buf, "%lu\n", (value / 1000 / 1000)); 27} 28 29static ssize_t clk_max_freq_mhz_store(struct device *dev, struct device_attribute *attr, 30 const char *buf, size_t count) 31{ 32 struct hl_device *hdev = dev_get_drvdata(dev); 33 int rc; 34 u64 value; 35 36 if (!hl_device_operational(hdev, NULL)) { 37 count = -ENODEV; 38 goto fail; 39 } 40 41 rc = kstrtoull(buf, 0, &value); 42 if (rc) { 43 count = -EINVAL; 44 goto fail; 45 } 46 47 hdev->asic_prop.max_freq_value = value * 1000 * 1000; 48 49 hl_fw_set_frequency(hdev, hdev->asic_prop.clk_pll_index, hdev->asic_prop.max_freq_value); 50 51fail: 52 return count; 53} 54 55static ssize_t clk_cur_freq_mhz_show(struct device *dev, struct device_attribute *attr, char *buf) 56{ 57 struct hl_device *hdev = dev_get_drvdata(dev); 58 long value; 59 60 if (!hl_device_operational(hdev, NULL)) 61 return -ENODEV; 62 63 value = hl_fw_get_frequency(hdev, hdev->asic_prop.clk_pll_index, true); 64 if (value < 0) 65 return value; 66 67 return sprintf(buf, "%lu\n", (value / 1000 / 1000)); 68} 69 70static DEVICE_ATTR_RW(clk_max_freq_mhz); 71static DEVICE_ATTR_RO(clk_cur_freq_mhz); 72 73static struct attribute *hl_dev_clk_attrs[] = { 74 &dev_attr_clk_max_freq_mhz.attr, 75 &dev_attr_clk_cur_freq_mhz.attr, 76}; 77 78static ssize_t vrm_ver_show(struct device *dev, struct device_attribute *attr, char *buf) 79{ 80 struct hl_device *hdev = dev_get_drvdata(dev); 81 struct cpucp_info *cpucp_info; 82 83 cpucp_info = &hdev->asic_prop.cpucp_info; 84 85 if (cpucp_info->infineon_second_stage_version) 86 return sprintf(buf, "%#04x %#04x\n", le32_to_cpu(cpucp_info->infineon_version), 87 le32_to_cpu(cpucp_info->infineon_second_stage_version)); 88 else 89 return sprintf(buf, "%#04x\n", le32_to_cpu(cpucp_info->infineon_version)); 90} 91 92static DEVICE_ATTR_RO(vrm_ver); 93 94static struct attribute *hl_dev_vrm_attrs[] = { 95 &dev_attr_vrm_ver.attr, 96}; 97 98static ssize_t uboot_ver_show(struct device *dev, struct device_attribute *attr, 99 char *buf) 100{ 101 struct hl_device *hdev = dev_get_drvdata(dev); 102 103 return sprintf(buf, "%s\n", hdev->asic_prop.uboot_ver); 104} 105 106static ssize_t armcp_kernel_ver_show(struct device *dev, 107 struct device_attribute *attr, char *buf) 108{ 109 struct hl_device *hdev = dev_get_drvdata(dev); 110 111 return sprintf(buf, "%s", hdev->asic_prop.cpucp_info.kernel_version); 112} 113 114static ssize_t armcp_ver_show(struct device *dev, struct device_attribute *attr, 115 char *buf) 116{ 117 struct hl_device *hdev = dev_get_drvdata(dev); 118 119 return sprintf(buf, "%s\n", hdev->asic_prop.cpucp_info.cpucp_version); 120} 121 122static ssize_t cpld_ver_show(struct device *dev, struct device_attribute *attr, 123 char *buf) 124{ 125 struct hl_device *hdev = dev_get_drvdata(dev); 126 127 return sprintf(buf, "0x%08x\n", 128 le32_to_cpu(hdev->asic_prop.cpucp_info.cpld_version)); 129} 130 131static ssize_t cpucp_kernel_ver_show(struct device *dev, 132 struct device_attribute *attr, char *buf) 133{ 134 struct hl_device *hdev = dev_get_drvdata(dev); 135 136 return sprintf(buf, "%s", hdev->asic_prop.cpucp_info.kernel_version); 137} 138 139static ssize_t cpucp_ver_show(struct device *dev, struct device_attribute *attr, 140 char *buf) 141{ 142 struct hl_device *hdev = dev_get_drvdata(dev); 143 144 return sprintf(buf, "%s\n", hdev->asic_prop.cpucp_info.cpucp_version); 145} 146 147static ssize_t fuse_ver_show(struct device *dev, struct device_attribute *attr, 148 char *buf) 149{ 150 struct hl_device *hdev = dev_get_drvdata(dev); 151 152 return sprintf(buf, "%s\n", hdev->asic_prop.cpucp_info.fuse_version); 153} 154 155static ssize_t thermal_ver_show(struct device *dev, 156 struct device_attribute *attr, char *buf) 157{ 158 struct hl_device *hdev = dev_get_drvdata(dev); 159 160 return sprintf(buf, "%s", hdev->asic_prop.cpucp_info.thermal_version); 161} 162 163static ssize_t fw_os_ver_show(struct device *dev, 164 struct device_attribute *attr, char *buf) 165{ 166 struct hl_device *hdev = dev_get_drvdata(dev); 167 168 return sprintf(buf, "%s", hdev->asic_prop.cpucp_info.fw_os_version); 169} 170 171static ssize_t preboot_btl_ver_show(struct device *dev, 172 struct device_attribute *attr, char *buf) 173{ 174 struct hl_device *hdev = dev_get_drvdata(dev); 175 176 return sprintf(buf, "%s\n", hdev->asic_prop.preboot_ver); 177} 178 179static ssize_t soft_reset_store(struct device *dev, 180 struct device_attribute *attr, const char *buf, 181 size_t count) 182{ 183 struct hl_device *hdev = dev_get_drvdata(dev); 184 long value; 185 int rc; 186 187 rc = kstrtoul(buf, 0, &value); 188 189 if (rc) { 190 count = -EINVAL; 191 goto out; 192 } 193 194 if (!hdev->asic_prop.allow_inference_soft_reset) { 195 dev_err(hdev->dev, "Device does not support inference soft-reset\n"); 196 goto out; 197 } 198 199 dev_warn(hdev->dev, "Inference Soft-Reset requested through sysfs\n"); 200 201 hl_device_reset(hdev, 0); 202 203out: 204 return count; 205} 206 207static ssize_t hard_reset_store(struct device *dev, 208 struct device_attribute *attr, 209 const char *buf, size_t count) 210{ 211 struct hl_device *hdev = dev_get_drvdata(dev); 212 long value; 213 int rc; 214 215 rc = kstrtoul(buf, 0, &value); 216 217 if (rc) { 218 count = -EINVAL; 219 goto out; 220 } 221 222 dev_warn(hdev->dev, "Hard-Reset requested through sysfs\n"); 223 224 hl_device_reset(hdev, HL_DRV_RESET_HARD); 225 226out: 227 return count; 228} 229 230static ssize_t device_type_show(struct device *dev, 231 struct device_attribute *attr, char *buf) 232{ 233 struct hl_device *hdev = dev_get_drvdata(dev); 234 char *str; 235 236 switch (hdev->asic_type) { 237 case ASIC_GOYA: 238 str = "GOYA"; 239 break; 240 case ASIC_GAUDI: 241 str = "GAUDI"; 242 break; 243 case ASIC_GAUDI_SEC: 244 str = "GAUDI SEC"; 245 break; 246 default: 247 dev_err(hdev->dev, "Unrecognized ASIC type %d\n", 248 hdev->asic_type); 249 return -EINVAL; 250 } 251 252 return sprintf(buf, "%s\n", str); 253} 254 255static ssize_t pci_addr_show(struct device *dev, struct device_attribute *attr, 256 char *buf) 257{ 258 struct hl_device *hdev = dev_get_drvdata(dev); 259 260 return sprintf(buf, "%04x:%02x:%02x.%x\n", 261 pci_domain_nr(hdev->pdev->bus), 262 hdev->pdev->bus->number, 263 PCI_SLOT(hdev->pdev->devfn), 264 PCI_FUNC(hdev->pdev->devfn)); 265} 266 267static ssize_t status_show(struct device *dev, struct device_attribute *attr, 268 char *buf) 269{ 270 struct hl_device *hdev = dev_get_drvdata(dev); 271 char str[HL_STR_MAX]; 272 273 strscpy(str, hdev->status[hl_device_status(hdev)], HL_STR_MAX); 274 275 /* use uppercase for backward compatibility */ 276 str[0] = 'A' + (str[0] - 'a'); 277 278 return sprintf(buf, "%s\n", str); 279} 280 281static ssize_t soft_reset_cnt_show(struct device *dev, 282 struct device_attribute *attr, char *buf) 283{ 284 struct hl_device *hdev = dev_get_drvdata(dev); 285 286 return sprintf(buf, "%d\n", hdev->reset_info.soft_reset_cnt); 287} 288 289static ssize_t hard_reset_cnt_show(struct device *dev, 290 struct device_attribute *attr, char *buf) 291{ 292 struct hl_device *hdev = dev_get_drvdata(dev); 293 294 return sprintf(buf, "%d\n", hdev->reset_info.hard_reset_cnt); 295} 296 297static ssize_t max_power_show(struct device *dev, struct device_attribute *attr, 298 char *buf) 299{ 300 struct hl_device *hdev = dev_get_drvdata(dev); 301 long val; 302 303 if (!hl_device_operational(hdev, NULL)) 304 return -ENODEV; 305 306 val = hl_fw_get_max_power(hdev); 307 if (val < 0) 308 return val; 309 310 return sprintf(buf, "%lu\n", val); 311} 312 313static ssize_t max_power_store(struct device *dev, 314 struct device_attribute *attr, const char *buf, size_t count) 315{ 316 struct hl_device *hdev = dev_get_drvdata(dev); 317 unsigned long value; 318 int rc; 319 320 if (!hl_device_operational(hdev, NULL)) { 321 count = -ENODEV; 322 goto out; 323 } 324 325 rc = kstrtoul(buf, 0, &value); 326 327 if (rc) { 328 count = -EINVAL; 329 goto out; 330 } 331 332 hdev->max_power = value; 333 hl_fw_set_max_power(hdev); 334 335out: 336 return count; 337} 338 339static ssize_t eeprom_read_handler(struct file *filp, struct kobject *kobj, 340 struct bin_attribute *attr, char *buf, loff_t offset, 341 size_t max_size) 342{ 343 struct device *dev = kobj_to_dev(kobj); 344 struct hl_device *hdev = dev_get_drvdata(dev); 345 char *data; 346 int rc; 347 348 if (!hl_device_operational(hdev, NULL)) 349 return -ENODEV; 350 351 if (!max_size) 352 return -EINVAL; 353 354 data = kzalloc(max_size, GFP_KERNEL); 355 if (!data) 356 return -ENOMEM; 357 358 rc = hdev->asic_funcs->get_eeprom_data(hdev, data, max_size); 359 if (rc) 360 goto out; 361 362 memcpy(buf, data, max_size); 363 364out: 365 kfree(data); 366 367 return max_size; 368} 369 370static DEVICE_ATTR_RO(armcp_kernel_ver); 371static DEVICE_ATTR_RO(armcp_ver); 372static DEVICE_ATTR_RO(cpld_ver); 373static DEVICE_ATTR_RO(cpucp_kernel_ver); 374static DEVICE_ATTR_RO(cpucp_ver); 375static DEVICE_ATTR_RO(device_type); 376static DEVICE_ATTR_RO(fuse_ver); 377static DEVICE_ATTR_WO(hard_reset); 378static DEVICE_ATTR_RO(hard_reset_cnt); 379static DEVICE_ATTR_RW(max_power); 380static DEVICE_ATTR_RO(pci_addr); 381static DEVICE_ATTR_RO(preboot_btl_ver); 382static DEVICE_ATTR_WO(soft_reset); 383static DEVICE_ATTR_RO(soft_reset_cnt); 384static DEVICE_ATTR_RO(status); 385static DEVICE_ATTR_RO(thermal_ver); 386static DEVICE_ATTR_RO(uboot_ver); 387static DEVICE_ATTR_RO(fw_os_ver); 388 389static struct bin_attribute bin_attr_eeprom = { 390 .attr = {.name = "eeprom", .mode = (0444)}, 391 .size = PAGE_SIZE, 392 .read = eeprom_read_handler 393}; 394 395static struct attribute *hl_dev_attrs[] = { 396 &dev_attr_armcp_kernel_ver.attr, 397 &dev_attr_armcp_ver.attr, 398 &dev_attr_cpld_ver.attr, 399 &dev_attr_cpucp_kernel_ver.attr, 400 &dev_attr_cpucp_ver.attr, 401 &dev_attr_device_type.attr, 402 &dev_attr_fuse_ver.attr, 403 &dev_attr_hard_reset.attr, 404 &dev_attr_hard_reset_cnt.attr, 405 &dev_attr_max_power.attr, 406 &dev_attr_pci_addr.attr, 407 &dev_attr_preboot_btl_ver.attr, 408 &dev_attr_status.attr, 409 &dev_attr_thermal_ver.attr, 410 &dev_attr_uboot_ver.attr, 411 &dev_attr_fw_os_ver.attr, 412 NULL, 413}; 414 415static struct bin_attribute *hl_dev_bin_attrs[] = { 416 &bin_attr_eeprom, 417 NULL 418}; 419 420static struct attribute_group hl_dev_attr_group = { 421 .attrs = hl_dev_attrs, 422 .bin_attrs = hl_dev_bin_attrs, 423}; 424 425static struct attribute_group hl_dev_clks_attr_group; 426static struct attribute_group hl_dev_vrm_attr_group; 427 428static const struct attribute_group *hl_dev_attr_groups[] = { 429 &hl_dev_attr_group, 430 &hl_dev_clks_attr_group, 431 &hl_dev_vrm_attr_group, 432 NULL, 433}; 434 435static struct attribute *hl_dev_inference_attrs[] = { 436 &dev_attr_soft_reset.attr, 437 &dev_attr_soft_reset_cnt.attr, 438 NULL, 439}; 440 441static struct attribute_group hl_dev_inference_attr_group = { 442 .attrs = hl_dev_inference_attrs, 443}; 444 445static const struct attribute_group *hl_dev_inference_attr_groups[] = { 446 &hl_dev_inference_attr_group, 447 NULL, 448}; 449 450void hl_sysfs_add_dev_clk_attr(struct hl_device *hdev, struct attribute_group *dev_clk_attr_grp) 451{ 452 dev_clk_attr_grp->attrs = hl_dev_clk_attrs; 453} 454 455void hl_sysfs_add_dev_vrm_attr(struct hl_device *hdev, struct attribute_group *dev_vrm_attr_grp) 456{ 457 dev_vrm_attr_grp->attrs = hl_dev_vrm_attrs; 458} 459 460int hl_sysfs_init(struct hl_device *hdev) 461{ 462 int rc; 463 464 hdev->max_power = hdev->asic_prop.max_power_default; 465 466 hdev->asic_funcs->add_device_attr(hdev, &hl_dev_clks_attr_group, &hl_dev_vrm_attr_group); 467 468 rc = device_add_groups(hdev->dev, hl_dev_attr_groups); 469 if (rc) { 470 dev_err(hdev->dev, 471 "Failed to add groups to device, error %d\n", rc); 472 return rc; 473 } 474 475 if (!hdev->asic_prop.allow_inference_soft_reset) 476 return 0; 477 478 rc = device_add_groups(hdev->dev, hl_dev_inference_attr_groups); 479 if (rc) { 480 dev_err(hdev->dev, 481 "Failed to add groups to device, error %d\n", rc); 482 return rc; 483 } 484 485 return 0; 486} 487 488void hl_sysfs_fini(struct hl_device *hdev) 489{ 490 device_remove_groups(hdev->dev, hl_dev_attr_groups); 491 492 if (!hdev->asic_prop.allow_inference_soft_reset) 493 return; 494 495 device_remove_groups(hdev->dev, hl_dev_inference_attr_groups); 496}