linux/drivers/misc/habanalabs/common/sysfs.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2
   3/*
   4 * Copyright 2016-2019 HabanaLabs, Ltd.
   5 * All Rights Reserved.
   6 */
   7
   8#include "habanalabs.h"
   9
  10#include <linux/pci.h>
  11
  12long hl_get_frequency(struct hl_device *hdev, u32 pll_index, bool curr)
  13{
  14        struct armcp_packet pkt;
  15        long result;
  16        int rc;
  17
  18        memset(&pkt, 0, sizeof(pkt));
  19
  20        if (curr)
  21                pkt.ctl = cpu_to_le32(ARMCP_PACKET_FREQUENCY_CURR_GET <<
  22                                                ARMCP_PKT_CTL_OPCODE_SHIFT);
  23        else
  24                pkt.ctl = cpu_to_le32(ARMCP_PACKET_FREQUENCY_GET <<
  25                                                ARMCP_PKT_CTL_OPCODE_SHIFT);
  26        pkt.pll_index = cpu_to_le32(pll_index);
  27
  28        rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt),
  29                                                0, &result);
  30
  31        if (rc) {
  32                dev_err(hdev->dev,
  33                        "Failed to get frequency of PLL %d, error %d\n",
  34                        pll_index, rc);
  35                result = rc;
  36        }
  37
  38        return result;
  39}
  40
  41void hl_set_frequency(struct hl_device *hdev, u32 pll_index, u64 freq)
  42{
  43        struct armcp_packet pkt;
  44        int rc;
  45
  46        memset(&pkt, 0, sizeof(pkt));
  47
  48        pkt.ctl = cpu_to_le32(ARMCP_PACKET_FREQUENCY_SET <<
  49                                        ARMCP_PKT_CTL_OPCODE_SHIFT);
  50        pkt.pll_index = cpu_to_le32(pll_index);
  51        pkt.value = cpu_to_le64(freq);
  52
  53        rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt),
  54                                                0, NULL);
  55
  56        if (rc)
  57                dev_err(hdev->dev,
  58                        "Failed to set frequency to PLL %d, error %d\n",
  59                        pll_index, rc);
  60}
  61
  62u64 hl_get_max_power(struct hl_device *hdev)
  63{
  64        struct armcp_packet pkt;
  65        long result;
  66        int rc;
  67
  68        memset(&pkt, 0, sizeof(pkt));
  69
  70        pkt.ctl = cpu_to_le32(ARMCP_PACKET_MAX_POWER_GET <<
  71                                ARMCP_PKT_CTL_OPCODE_SHIFT);
  72
  73        rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt),
  74                                                0, &result);
  75
  76        if (rc) {
  77                dev_err(hdev->dev, "Failed to get max power, error %d\n", rc);
  78                result = rc;
  79        }
  80
  81        return result;
  82}
  83
  84void hl_set_max_power(struct hl_device *hdev)
  85{
  86        struct armcp_packet pkt;
  87        int rc;
  88
  89        memset(&pkt, 0, sizeof(pkt));
  90
  91        pkt.ctl = cpu_to_le32(ARMCP_PACKET_MAX_POWER_SET <<
  92                                ARMCP_PKT_CTL_OPCODE_SHIFT);
  93        pkt.value = cpu_to_le64(hdev->max_power);
  94
  95        rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt),
  96                                                0, NULL);
  97
  98        if (rc)
  99                dev_err(hdev->dev, "Failed to set max power, error %d\n", rc);
 100}
 101
 102static ssize_t uboot_ver_show(struct device *dev, struct device_attribute *attr,
 103                                char *buf)
 104{
 105        struct hl_device *hdev = dev_get_drvdata(dev);
 106
 107        return sprintf(buf, "%s\n", hdev->asic_prop.uboot_ver);
 108}
 109
 110static ssize_t armcp_kernel_ver_show(struct device *dev,
 111                                struct device_attribute *attr, char *buf)
 112{
 113        struct hl_device *hdev = dev_get_drvdata(dev);
 114
 115        return sprintf(buf, "%s", hdev->asic_prop.armcp_info.kernel_version);
 116}
 117
 118static ssize_t armcp_ver_show(struct device *dev, struct device_attribute *attr,
 119                                char *buf)
 120{
 121        struct hl_device *hdev = dev_get_drvdata(dev);
 122
 123        return sprintf(buf, "%s\n", hdev->asic_prop.armcp_info.armcp_version);
 124}
 125
 126static ssize_t cpld_ver_show(struct device *dev, struct device_attribute *attr,
 127                                char *buf)
 128{
 129        struct hl_device *hdev = dev_get_drvdata(dev);
 130
 131        return sprintf(buf, "0x%08x\n",
 132                        hdev->asic_prop.armcp_info.cpld_version);
 133}
 134
 135static ssize_t infineon_ver_show(struct device *dev,
 136                                struct device_attribute *attr, char *buf)
 137{
 138        struct hl_device *hdev = dev_get_drvdata(dev);
 139
 140        return sprintf(buf, "0x%04x\n",
 141                        hdev->asic_prop.armcp_info.infineon_version);
 142}
 143
 144static ssize_t fuse_ver_show(struct device *dev, struct device_attribute *attr,
 145                                char *buf)
 146{
 147        struct hl_device *hdev = dev_get_drvdata(dev);
 148
 149        return sprintf(buf, "%s\n", hdev->asic_prop.armcp_info.fuse_version);
 150}
 151
 152static ssize_t thermal_ver_show(struct device *dev,
 153                                struct device_attribute *attr, char *buf)
 154{
 155        struct hl_device *hdev = dev_get_drvdata(dev);
 156
 157        return sprintf(buf, "%s", hdev->asic_prop.armcp_info.thermal_version);
 158}
 159
 160static ssize_t preboot_btl_ver_show(struct device *dev,
 161                                struct device_attribute *attr, char *buf)
 162{
 163        struct hl_device *hdev = dev_get_drvdata(dev);
 164
 165        return sprintf(buf, "%s\n", hdev->asic_prop.preboot_ver);
 166}
 167
 168static ssize_t soft_reset_store(struct device *dev,
 169                                struct device_attribute *attr, const char *buf,
 170                                size_t count)
 171{
 172        struct hl_device *hdev = dev_get_drvdata(dev);
 173        long value;
 174        int rc;
 175
 176        rc = kstrtoul(buf, 0, &value);
 177
 178        if (rc) {
 179                count = -EINVAL;
 180                goto out;
 181        }
 182
 183        if (!hdev->supports_soft_reset) {
 184                dev_err(hdev->dev, "Device does not support soft-reset\n");
 185                goto out;
 186        }
 187
 188        dev_warn(hdev->dev, "Soft-Reset requested through sysfs\n");
 189
 190        hl_device_reset(hdev, false, false);
 191
 192out:
 193        return count;
 194}
 195
 196static ssize_t hard_reset_store(struct device *dev,
 197                                struct device_attribute *attr,
 198                                const char *buf, size_t count)
 199{
 200        struct hl_device *hdev = dev_get_drvdata(dev);
 201        long value;
 202        int rc;
 203
 204        rc = kstrtoul(buf, 0, &value);
 205
 206        if (rc) {
 207                count = -EINVAL;
 208                goto out;
 209        }
 210
 211        dev_warn(hdev->dev, "Hard-Reset requested through sysfs\n");
 212
 213        hl_device_reset(hdev, true, false);
 214
 215out:
 216        return count;
 217}
 218
 219static ssize_t device_type_show(struct device *dev,
 220                struct device_attribute *attr, char *buf)
 221{
 222        struct hl_device *hdev = dev_get_drvdata(dev);
 223        char *str;
 224
 225        switch (hdev->asic_type) {
 226        case ASIC_GOYA:
 227                str = "GOYA";
 228                break;
 229        case ASIC_GAUDI:
 230                str = "GAUDI";
 231                break;
 232        default:
 233                dev_err(hdev->dev, "Unrecognized ASIC type %d\n",
 234                                hdev->asic_type);
 235                return -EINVAL;
 236        }
 237
 238        return sprintf(buf, "%s\n", str);
 239}
 240
 241static ssize_t pci_addr_show(struct device *dev, struct device_attribute *attr,
 242                                char *buf)
 243{
 244        struct hl_device *hdev = dev_get_drvdata(dev);
 245
 246        return sprintf(buf, "%04x:%02x:%02x.%x\n",
 247                        pci_domain_nr(hdev->pdev->bus),
 248                        hdev->pdev->bus->number,
 249                        PCI_SLOT(hdev->pdev->devfn),
 250                        PCI_FUNC(hdev->pdev->devfn));
 251}
 252
 253static ssize_t status_show(struct device *dev, struct device_attribute *attr,
 254                                char *buf)
 255{
 256        struct hl_device *hdev = dev_get_drvdata(dev);
 257        char *str;
 258
 259        if (atomic_read(&hdev->in_reset))
 260                str = "In reset";
 261        else if (hdev->disabled)
 262                str = "Malfunction";
 263        else
 264                str = "Operational";
 265
 266        return sprintf(buf, "%s\n", str);
 267}
 268
 269static ssize_t soft_reset_cnt_show(struct device *dev,
 270                struct device_attribute *attr, char *buf)
 271{
 272        struct hl_device *hdev = dev_get_drvdata(dev);
 273
 274        return sprintf(buf, "%d\n", hdev->soft_reset_cnt);
 275}
 276
 277static ssize_t hard_reset_cnt_show(struct device *dev,
 278                struct device_attribute *attr, char *buf)
 279{
 280        struct hl_device *hdev = dev_get_drvdata(dev);
 281
 282        return sprintf(buf, "%d\n", hdev->hard_reset_cnt);
 283}
 284
 285static ssize_t max_power_show(struct device *dev, struct device_attribute *attr,
 286                                char *buf)
 287{
 288        struct hl_device *hdev = dev_get_drvdata(dev);
 289        long val;
 290
 291        if (hl_device_disabled_or_in_reset(hdev))
 292                return -ENODEV;
 293
 294        val = hl_get_max_power(hdev);
 295
 296        return sprintf(buf, "%lu\n", val);
 297}
 298
 299static ssize_t max_power_store(struct device *dev,
 300                struct device_attribute *attr, const char *buf, size_t count)
 301{
 302        struct hl_device *hdev = dev_get_drvdata(dev);
 303        unsigned long value;
 304        int rc;
 305
 306        if (hl_device_disabled_or_in_reset(hdev)) {
 307                count = -ENODEV;
 308                goto out;
 309        }
 310
 311        rc = kstrtoul(buf, 0, &value);
 312
 313        if (rc) {
 314                count = -EINVAL;
 315                goto out;
 316        }
 317
 318        hdev->max_power = value;
 319        hl_set_max_power(hdev);
 320
 321out:
 322        return count;
 323}
 324
 325static ssize_t eeprom_read_handler(struct file *filp, struct kobject *kobj,
 326                        struct bin_attribute *attr, char *buf, loff_t offset,
 327                        size_t max_size)
 328{
 329        struct device *dev = container_of(kobj, struct device, kobj);
 330        struct hl_device *hdev = dev_get_drvdata(dev);
 331        char *data;
 332        int rc;
 333
 334        if (hl_device_disabled_or_in_reset(hdev))
 335                return -ENODEV;
 336
 337        if (!max_size)
 338                return -EINVAL;
 339
 340        data = kzalloc(max_size, GFP_KERNEL);
 341        if (!data)
 342                return -ENOMEM;
 343
 344        rc = hdev->asic_funcs->get_eeprom_data(hdev, data, max_size);
 345        if (rc)
 346                goto out;
 347
 348        memcpy(buf, data, max_size);
 349
 350out:
 351        kfree(data);
 352
 353        return max_size;
 354}
 355
 356static DEVICE_ATTR_RO(armcp_kernel_ver);
 357static DEVICE_ATTR_RO(armcp_ver);
 358static DEVICE_ATTR_RO(cpld_ver);
 359static DEVICE_ATTR_RO(device_type);
 360static DEVICE_ATTR_RO(fuse_ver);
 361static DEVICE_ATTR_WO(hard_reset);
 362static DEVICE_ATTR_RO(hard_reset_cnt);
 363static DEVICE_ATTR_RO(infineon_ver);
 364static DEVICE_ATTR_RW(max_power);
 365static DEVICE_ATTR_RO(pci_addr);
 366static DEVICE_ATTR_RO(preboot_btl_ver);
 367static DEVICE_ATTR_WO(soft_reset);
 368static DEVICE_ATTR_RO(soft_reset_cnt);
 369static DEVICE_ATTR_RO(status);
 370static DEVICE_ATTR_RO(thermal_ver);
 371static DEVICE_ATTR_RO(uboot_ver);
 372
 373static struct bin_attribute bin_attr_eeprom = {
 374        .attr = {.name = "eeprom", .mode = (0444)},
 375        .size = PAGE_SIZE,
 376        .read = eeprom_read_handler
 377};
 378
 379static struct attribute *hl_dev_attrs[] = {
 380        &dev_attr_armcp_kernel_ver.attr,
 381        &dev_attr_armcp_ver.attr,
 382        &dev_attr_cpld_ver.attr,
 383        &dev_attr_device_type.attr,
 384        &dev_attr_fuse_ver.attr,
 385        &dev_attr_hard_reset.attr,
 386        &dev_attr_hard_reset_cnt.attr,
 387        &dev_attr_infineon_ver.attr,
 388        &dev_attr_max_power.attr,
 389        &dev_attr_pci_addr.attr,
 390        &dev_attr_preboot_btl_ver.attr,
 391        &dev_attr_soft_reset.attr,
 392        &dev_attr_soft_reset_cnt.attr,
 393        &dev_attr_status.attr,
 394        &dev_attr_thermal_ver.attr,
 395        &dev_attr_uboot_ver.attr,
 396        NULL,
 397};
 398
 399static struct bin_attribute *hl_dev_bin_attrs[] = {
 400        &bin_attr_eeprom,
 401        NULL
 402};
 403
 404static struct attribute_group hl_dev_attr_group = {
 405        .attrs = hl_dev_attrs,
 406        .bin_attrs = hl_dev_bin_attrs,
 407};
 408
 409static struct attribute_group hl_dev_clks_attr_group;
 410
 411static const struct attribute_group *hl_dev_attr_groups[] = {
 412        &hl_dev_attr_group,
 413        &hl_dev_clks_attr_group,
 414        NULL,
 415};
 416
 417int hl_sysfs_init(struct hl_device *hdev)
 418{
 419        int rc;
 420
 421        if (hdev->asic_type == ASIC_GOYA)
 422                hdev->pm_mng_profile = PM_AUTO;
 423        else
 424                hdev->pm_mng_profile = PM_MANUAL;
 425
 426        hdev->max_power = hdev->asic_prop.max_power_default;
 427
 428        hdev->asic_funcs->add_device_attr(hdev, &hl_dev_clks_attr_group);
 429
 430        rc = device_add_groups(hdev->dev, hl_dev_attr_groups);
 431        if (rc) {
 432                dev_err(hdev->dev,
 433                        "Failed to add groups to device, error %d\n", rc);
 434                return rc;
 435        }
 436
 437        return 0;
 438}
 439
 440void hl_sysfs_fini(struct hl_device *hdev)
 441{
 442        device_remove_groups(hdev->dev, hl_dev_attr_groups);
 443}
 444