sonic-buildimage/platform/mellanox/non-upstream-patches/patches/0218-UBUNTU-SAUCE-platform-mellanox-Add-mlx-trio-driver.patch
Kebo Liu e286869b24
[Mellanox] Update HW-MGMT package to new version V.7.0030.1011 (#16239)
- Why I did it
1. Update Mellanox HW-MGMT package to newer version V.7.0030.1011
2. Replace the SONiC PMON Thermal control algorithm with the one inside the HW-MGMT package on all Nvidia platforms
3. Support Spectrum-4 systems

- How I did it
1. Update the HW-MGMT package version number and submodule pointer
2. Remove the thermal control algorithm implementation from Mellanox platform API
3. Revise the patch to HW-MGMT package which will disable HW-MGMT from running on SIMX
4. Update the downstream kernel patch list

Signed-off-by: Kebo Liu <kebol@nvidia.com>
2023-09-06 11:32:08 +03:00

956 lines
27 KiB
Diff

From 15bbb9ee03e015587b9bd704f36c85177fba563a Mon Sep 17 00:00:00 2001
From: Shravan Kumar Ramani <shravankr@nvidia.com>
Date: Tue, 5 Jul 2022 11:11:45 -0400
Subject: [PATCH backport 5.10 19/63] UBUNTU: SAUCE: platform/mellanox: Add
mlx-trio driver
BugLink: https://bugs.launchpad.net/bugs/1980754
The mlx-trio driver allows users to configure the TRIO PCIe root
complex of Mellanox BlueField SoCs to select an L3 cache profile.
It also handles TRIO IRQs and prints debug info.
Signed-off-by: Shravan Kumar Ramani <shravankr@nvidia.com>
Signed-off-by: Ike Panhc <ike.pan@canonical.com>
---
drivers/platform/mellanox/Kconfig | 7 +
drivers/platform/mellanox/Makefile | 1 +
drivers/platform/mellanox/mlx-trio.c | 651 ++++++++++++++++++++++++++
drivers/platform/mellanox/trio_regs.h | 236 ++++++++++
4 files changed, 895 insertions(+)
create mode 100644 drivers/platform/mellanox/mlx-trio.c
create mode 100644 drivers/platform/mellanox/trio_regs.h
diff --git a/drivers/platform/mellanox/Kconfig b/drivers/platform/mellanox/Kconfig
index b0d2c3343..5d329350a 100644
--- a/drivers/platform/mellanox/Kconfig
+++ b/drivers/platform/mellanox/Kconfig
@@ -90,6 +90,13 @@ config MLXBF_PMC
to performance monitoring counters within various blocks in the
Mellanox BlueField SoC via a sysfs interface.
+config MLXBF_TRIO
+ tristate "Mellanox TRIO driver"
+ depends on ARM64
+ help
+ This driver supports the TRIO PCIe root complex interface on
+ Mellanox BlueField SoCs.
+
config NVSW_SN2201
tristate "Nvidia SN2201 platform driver support"
depends on REGMAP
diff --git a/drivers/platform/mellanox/Makefile b/drivers/platform/mellanox/Makefile
index ba56485cb..161fad566 100644
--- a/drivers/platform/mellanox/Makefile
+++ b/drivers/platform/mellanox/Makefile
@@ -7,6 +7,7 @@ obj-$(CONFIG_MLX_PLATFORM) += mlx-platform.o
obj-$(CONFIG_MLXBF_BOOTCTL) += mlxbf-bootctl.o
obj-$(CONFIG_MLXBF_PMC) += mlxbf-pmc.o
obj-$(CONFIG_MLXBF_TMFIFO) += mlxbf-tmfifo.o
+obj-$(CONFIG_MLXBF_TRIO) += mlx-trio.o
obj-$(CONFIG_MLXREG_HOTPLUG) += mlxreg-hotplug.o
obj-$(CONFIG_MLXREG_IO) += mlxreg-io.o
obj-$(CONFIG_MLXREG_LC) += mlxreg-lc.o
diff --git a/drivers/platform/mellanox/mlx-trio.c b/drivers/platform/mellanox/mlx-trio.c
new file mode 100644
index 000000000..849006e9c
--- /dev/null
+++ b/drivers/platform/mellanox/mlx-trio.c
@@ -0,0 +1,651 @@
+// SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause
+/*
+ * TRIO driver for Mellanox BlueField SoC
+ *
+ * Copyright (c) 2018, Mellanox Technologies. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/acpi.h>
+#include <linux/arm-smccc.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/kmod.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/platform_device.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/sysfs.h>
+
+#include <uapi/linux/psci.h>
+
+#include "trio_regs.h"
+
+#define DRIVER_NAME "mlx-trio"
+#define DRIVER_VERSION "0.4"
+#define DRIVER_DESCRIPTION "Mellanox TRIO PCIe host controller driver"
+
+/* SMC return codes */
+#define SMCCC_ACCESS_VIOLATION (-4)
+
+/* SMC function identifiers */
+#define MLNX_WRITE_REG_64 (0x8200000B)
+#define MLNX_READ_REG_64 (0x8200000C)
+#define MLNX_SIP_SVC_UID (0x8200ff01)
+#define MLNX_SIP_SVC_VERSION (0x8200ff03)
+
+#define MLNX_TRIO_SVC_REQ_MAJOR 0
+#define MLNX_TRIO_SVC_MIN_MINOR 4
+
+#define TRIO_NUM_IRQS 17
+#define L3_PROFILE_NUM (L3C_PROF_RD_MISS__LENGTH / L3C_PROF_RD_MISS__STRIDE)
+
+/* The PUSH_DMA_EVT_CTR wrapped. */
+#define TRIO_PUSH_DMA_EVT_CTR_INT_BIT 10
+
+/* The MAP_EVT_CTR wrapped. */
+#define TRIO_MAP_EVT_CTR_INT_BIT 11
+
+enum trio_int_events {
+ TRIO_MAC_INT = 0,
+ TRIO_RSH_FULL_ERR_INT,
+ TRIO_MSG_Q_FULL_ERR_INT,
+ TRIO_MSG_Q_ARRIVED_INT,
+ TRIO_MMIO_ERR_INT,
+ TRIO_MAP_UNCLAIMED_INT,
+ TRIO_RSH_SIZE_ERR_INT,
+ TRIO_PIO_ECAM_ERR_INT,
+ TRIO_PIO_CPL_ERR_INT,
+ TRIO_MMIO_PROT_ERR_INT,
+ TRIO_PUSH_DMA_EVT_CTR_INT,
+ TRIO_MAP_EVT_CTR_INT,
+ TRIO_PIO_DISABLED_INT,
+ TRIO_REM_MMIO_ERR_INT,
+ TRIO_ERR_MSG_COR_INT,
+ TRIO_ERR_MSG_NONFATAL_INT,
+ TRIO_ERR_MSG_FATAL_INT,
+};
+
+struct trio_event_info {
+ const char *name;
+ int additional_info;
+};
+
+static const struct trio_event_info trio_events[TRIO_NUM_IRQS] = {
+ [TRIO_MAC_INT] = {
+ .name = "MAC Interrupt",
+ .additional_info = -1,
+ },
+ [TRIO_RSH_FULL_ERR_INT] = {
+ .name = "RShim Full Error",
+ .additional_info = -1,
+ },
+ [TRIO_MSG_Q_FULL_ERR_INT] = {
+ .name = "Msg Queue Full Error",
+ .additional_info = -1,
+ },
+ [TRIO_MSG_Q_ARRIVED_INT] = {
+ .name = "Msg Arrived Interrupt",
+ .additional_info = -1,
+ },
+ [TRIO_MMIO_ERR_INT] = {
+ .name = "MMIO Error",
+ .additional_info = TRIO_MMIO_ERROR_INFO,
+ },
+ [TRIO_MAP_UNCLAIMED_INT] = {
+ .name = "Packet Unclaimed Error",
+ .additional_info = TRIO_MAP_ERR_STS,
+ },
+ [TRIO_RSH_SIZE_ERR_INT] = {
+ .name = "RShim Size Error",
+ .additional_info = -1,
+ },
+ [TRIO_PIO_ECAM_ERR_INT] = {
+ .name = "PIO ECAM Error",
+ .additional_info = -1,
+ },
+ [TRIO_PIO_CPL_ERR_INT] = {
+ .name = "PIO Completion Error",
+ .additional_info = TRIO_TILE_PIO_CPL_ERR_STS,
+ },
+ [TRIO_MMIO_PROT_ERR_INT] = {
+ .name = "MMIO Protection level Violation",
+ .additional_info = -1,
+ },
+ [TRIO_PUSH_DMA_EVT_CTR_INT] = {
+ .name = "PUSH_DMA_CTR wrapped",
+ .additional_info = -1,
+ },
+ [TRIO_MAP_EVT_CTR_INT] = {
+ .name = "MAP_EVT_CTR wrapped",
+ .additional_info = -1,
+ },
+ [TRIO_PIO_DISABLED_INT] = {
+ .name = "Access to disabled PIO region",
+ .additional_info = -1,
+ },
+ [TRIO_REM_MMIO_ERR_INT] = {
+ .name = "Remote Buffer MMIO Error",
+ .additional_info = -1,
+ },
+ [TRIO_ERR_MSG_COR_INT] = {
+ .name = "Correctable error message received",
+ .additional_info = -1,
+ },
+ [TRIO_ERR_MSG_NONFATAL_INT] = {
+ .name = "Nonfatal error message received",
+ .additional_info = -1,
+ },
+ [TRIO_ERR_MSG_FATAL_INT] = {
+ .name = "Fatal error message received",
+ .additional_info = -1,
+ },
+};
+
+enum l3_profile_type {
+ LRU_PROFILE = 0, /* 0 is the default behavior. */
+ NVME_PROFILE,
+ L3_PROFILE_TYPE_NUM,
+};
+
+static const char *l3_profiles[L3_PROFILE_TYPE_NUM] = {
+ [LRU_PROFILE] = "Strict_LRU",
+ [NVME_PROFILE] = "NVMeOF_suitable"
+};
+
+/*
+ * The default profile each L3 profile would get.
+ * The current setting would make profile 1 the NVMe suitable profile
+ * and the rest of the profiles LRU profile.
+ * Note that profile 0 should be configured as LRU as this is the
+ * default profile.
+ */
+static const enum l3_profile_type default_profile[L3_PROFILE_NUM] = {
+ [1] = NVME_PROFILE,
+};
+
+struct event_context {
+ int event_num;
+ int irq;
+ struct trio_context *trio;
+};
+
+struct trio_context {
+ /* The kernel structure representing the device. */
+ struct platform_device *pdev;
+
+ /* Argument to be passed back to the IRQ handler */
+ struct event_context *events;
+
+ /*
+ * Reg base addr, will be memmapped if sreg_use_smcs is false.
+ * Otherwise, this is a physical address.
+ */
+ void __iomem *mmio_base;
+
+ int trio_index;
+
+ /* Name of the bus this TRIO corresponds to */
+ const char *bus;
+
+ /* The PCI device this TRIO corresponds to */
+ struct pci_dev *trio_pci;
+
+ /* Number of platform_irqs for this device */
+ uint32_t num_irqs;
+
+ /* Access regs with smcs if true */
+ bool sreg_use_smcs;
+
+ /* verification table for trio */
+ uint32_t sreg_trio_tbl;
+};
+
+static int secure_writeq(struct trio_context *trio, uint64_t value,
+ void __iomem *addr)
+{
+ struct arm_smccc_res res;
+ int status;
+
+ arm_smccc_smc(MLNX_WRITE_REG_64, trio->sreg_trio_tbl, value,
+ (uintptr_t) addr, 0, 0, 0, 0, &res);
+
+ status = res.a0;
+
+ switch (status) {
+ /*
+ * Note: PSCI_RET_NOT_SUPPORTED is used here to maintain compatibility
+ * with older kernels that do not have SMCCC_RET_NOT_SUPPORTED
+ */
+ case PSCI_RET_NOT_SUPPORTED:
+ dev_err(&trio->pdev->dev,
+ "%s: required SMC unsupported\n",
+ __func__);
+ return -1;
+ case SMCCC_ACCESS_VIOLATION:
+ dev_err(&trio->pdev->dev,
+ "%s: could not access register at %px\n",
+ __func__,
+ addr);
+ return -1;
+ default:
+ return 0;
+ }
+}
+
+static int trio_writeq(struct trio_context *trio, uint64_t value,
+ void __iomem *addr)
+{
+ if (trio->sreg_use_smcs)
+ return secure_writeq(trio, value, addr);
+ else {
+ writeq(value, addr);
+ return 0;
+ }
+}
+
+static int secure_readq(struct trio_context *trio, void __iomem *addr,
+ uint64_t *result)
+{
+ struct arm_smccc_res res;
+ int status;
+
+ arm_smccc_smc(MLNX_READ_REG_64, trio->sreg_trio_tbl, (uintptr_t) addr,
+ 0, 0, 0, 0, 0, &res);
+
+ status = res.a0;
+
+ switch (status) {
+ /*
+ * Note: PSCI_RET_NOT_SUPPORTED is used here to maintain compatibility
+ * with older kernels that do not have SMCCC_RET_NOT_SUPPORTED
+ */
+ case PSCI_RET_NOT_SUPPORTED:
+ dev_err(&trio->pdev->dev,
+ "%s: required SMC unsupported\n", __func__);
+ return -1;
+ case SMCCC_ACCESS_VIOLATION:
+ dev_err(&trio->pdev->dev,
+ "%s: could not read register %px\n",
+ __func__,
+ addr);
+ return -1;
+ default:
+ *result = (uint64_t)res.a1;
+ return 0;
+ }
+}
+
+static int trio_readq(struct trio_context *trio, void __iomem *addr,
+ uint64_t *result)
+{
+ if (trio->sreg_use_smcs)
+ return secure_readq(trio, addr, result);
+ else {
+ *result = readq(addr);
+ return 0;
+ }
+}
+
+static irqreturn_t trio_irq_handler(int irq, void *arg)
+{
+ struct event_context *ctx = (struct event_context *)arg;
+ struct trio_context *trio = ctx->trio;
+
+ pr_debug("mlx_trio: TRIO %d received IRQ %d event %d (%s)\n",
+ trio->trio_index, irq, ctx->event_num,
+ trio_events[ctx->event_num].name);
+
+ if (trio_events[ctx->event_num].additional_info != -1) {
+ uint64_t info;
+ trio_readq(trio, trio->mmio_base +
+ trio_events[ctx->event_num].additional_info,
+ &info);
+ pr_debug("mlx_trio: Addition IRQ info: %llx\n", info);
+ }
+
+ return IRQ_HANDLED;
+}
+
+static ssize_t current_profile_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ int profile_num;
+ struct trio_context *trio;
+ struct platform_device *pdev;
+
+ TRIO_DEV_CTL_t tdc;
+
+ pdev = to_platform_device(dev);
+ trio = platform_get_drvdata(pdev);
+
+ if (trio_readq(trio, trio->mmio_base + TRIO_DEV_CTL, &tdc.word)) {
+ return -EIO;
+ }
+
+ if (tdc.l3_profile_ovd == 0)
+ profile_num = -1;
+ else
+ profile_num = tdc.l3_profile_val;
+
+ return sprintf(buf, "%d\n", profile_num);
+}
+
+static int set_l3cache_profile(struct trio_context *trio, long profile_num)
+{
+ TRIO_DEV_CTL_t tdc;
+
+ if (trio_readq(trio, trio->mmio_base + TRIO_DEV_CTL, &tdc.word)) {
+ return -EIO;
+ }
+
+ if (profile_num == -1) {
+ dev_info(&trio->pdev->dev, "Unlink %s profile\n", trio->bus);
+
+ tdc.l3_profile_ovd = 0;
+ } else if (profile_num < L3_PROFILE_NUM && profile_num >= 0) {
+ dev_info(&trio->pdev->dev, "Change %s to profile %ld\n",
+ trio->bus, profile_num);
+
+ tdc.l3_profile_ovd = 1;
+ tdc.l3_profile_val = profile_num;
+ } else {
+ dev_err(&trio->pdev->dev, "Profile number out of range.");
+ return -EINVAL;
+ }
+
+ if (trio_writeq(trio, tdc.word, trio->mmio_base + TRIO_DEV_CTL)) {
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static ssize_t current_profile_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ int err;
+ long profile_num;
+ struct trio_context *trio;
+ struct platform_device *pdev;
+
+ pdev = container_of(dev, struct platform_device, dev);
+ trio = platform_get_drvdata(pdev);
+
+ err = kstrtol(buf, 10, &profile_num);
+ if (err)
+ return err;
+
+ err = set_l3cache_profile(trio, profile_num);
+ if (err)
+ return err;
+
+ return count;
+}
+
+static DEVICE_ATTR_RW(current_profile);
+
+static ssize_t available_profiles_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ int i;
+ ssize_t line_size;
+ ssize_t len = 0;
+
+ for (i = 0; i < L3_PROFILE_NUM; i++) {
+ line_size = sprintf(buf, "%d %s\n", i,
+ l3_profiles[default_profile[i]]);
+ buf += line_size;
+ len += line_size;
+ }
+ return len;
+}
+
+static DEVICE_ATTR_RO(available_profiles);
+
+static int trio_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct trio_context *trio;
+ int i, j, ret, irq;
+ int trio_bus, trio_device, trio_function;
+ struct resource *res;
+ struct arm_smccc_res smc_res;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+ dev_warn(dev, "%s: failed to find reg resource 0\n", __func__);
+ return -ENODEV;
+ }
+
+ trio = kzalloc(sizeof(struct trio_context), GFP_KERNEL);
+ if (!trio)
+ return -ENOMEM;
+
+ platform_set_drvdata(pdev, trio);
+ trio->pdev = pdev;
+
+ /* Determine whether to use SMCs or not. */
+ if (device_property_read_u32(&pdev->dev, "sec_reg_block",
+ &trio->sreg_trio_tbl)) {
+ trio->sreg_use_smcs = false;
+ } else {
+ /*
+ * Ensure we have the UUID we expect for the Mellanox service.
+ */
+ arm_smccc_smc(MLNX_SIP_SVC_UID, 0, 0, 0, 0, 0, 0, 0, &smc_res);
+ if (smc_res.a0 != 0x89c036b4 || smc_res.a1 != 0x11e6e7d7 ||
+ smc_res.a2 != 0x1a009787 || smc_res.a3 != 0xc4bf00ca) {
+ dev_err(&pdev->dev,
+ "Mellanox SMC service not available\n");
+ return -EINVAL;
+ }
+
+ /*
+ * Check service version to see if we actually do support the
+ * needed SMCs. If we have the calls we need, mark support for
+ * them in the trio struct.
+ */
+ arm_smccc_smc(MLNX_SIP_SVC_VERSION, 0, 0, 0, 0, 0, 0, 0,
+ &smc_res);
+ if (smc_res.a0 == MLNX_TRIO_SVC_REQ_MAJOR &&
+ smc_res.a1 >= MLNX_TRIO_SVC_MIN_MINOR) {
+ trio->sreg_use_smcs = true;
+ } else {
+ dev_err(&pdev->dev,
+ "Required SMCs are not supported.\n");
+
+ return -EINVAL;
+ }
+ }
+
+ if (device_property_read_string(dev, "bus_number", &trio->bus)) {
+ dev_warn(dev, "%s: failed to retrieve Trio bus name\n",
+ __func__);
+ ret = -ENODEV;
+ goto err;
+ }
+
+ if (device_property_read_u32(dev, "num_irqs", &trio->num_irqs))
+ trio->num_irqs = TRIO_NUM_IRQS;
+ trio->events = kzalloc(sizeof(struct event_context) * trio->num_irqs,
+ GFP_KERNEL);
+ if (!trio->events) {
+ ret = -ENOMEM;
+ goto err;
+ }
+
+ /* Map registers */
+ if (!trio->sreg_use_smcs) {
+ trio->mmio_base = devm_ioremap_resource(&pdev->dev, res);
+
+ if (IS_ERR(trio->mmio_base)) {
+ dev_warn(dev, "%s: ioremap failed for mmio_base %llx err %p\n",
+ __func__, res->start, trio->mmio_base);
+ ret = PTR_ERR(trio->mmio_base);
+ goto err;
+ }
+ } else
+ trio->mmio_base = (void __iomem *) res->start;
+
+ for (i = 0; i < trio->num_irqs; ++i) {
+ struct event_context *ctx = &trio->events[i];
+ int dri_ret;
+
+ switch (i) {
+ case TRIO_PUSH_DMA_EVT_CTR_INT_BIT:
+ case TRIO_MAP_EVT_CTR_INT_BIT:
+ /*
+ * These events are not errors, they just indicate
+ * that a performance counter wrapped. We may want
+ * the performance counter driver to register for them.
+ */
+ continue;
+ default:
+ break;
+ }
+
+ irq = platform_get_irq(pdev, i);
+ if (irq < 0) {
+ dev_warn(dev, "%s: failed to get plat irq %d ret %d\n",
+ __func__, i, irq);
+ for (j = i - 1; j >= 0; j--) {
+ ctx = &trio->events[j];
+ devm_free_irq(&pdev->dev, ctx->irq, ctx);
+ }
+ ret = -ENXIO;
+ goto err;
+ }
+ ctx->event_num = i;
+ ctx->trio = trio;
+ ctx->irq = irq;
+ dri_ret = devm_request_irq(&pdev->dev, irq, trio_irq_handler, 0,
+ dev_name(dev), ctx);
+
+ dev_dbg(dev, "%s: request_irq returns %d %d->%d\n", __func__,
+ dri_ret, i, irq);
+ }
+
+ /* Create the L3 cache profile on this device */
+ device_create_file(dev, &dev_attr_current_profile);
+ device_create_file(dev, &dev_attr_available_profiles);
+
+ /*
+ * Get the corresponding PCI device this trio maps to.
+ * If the bus number can't be read properly, no symlinks are created.
+ */
+ if (sscanf(trio->bus, "%d:%d.%d", &trio_bus, &trio_device,
+ &trio_function) != 3) {
+ dev_warn(dev, "Device [%s] not valid\n", trio->bus);
+ return 0;
+ }
+
+ /* trio_device is also the index of the TRIO */
+ trio->trio_index = trio_device;
+
+ /* The PCI domain/segment would always be 0 here. */
+ trio->trio_pci =
+ pci_get_domain_bus_and_slot(0, trio_bus,
+ (trio_device << 3) + trio_function);
+
+ /* Add the symlink from the TRIO to the PCI device */
+ if (trio->trio_pci != NULL) {
+ if (sysfs_create_link(&dev->kobj, &trio->trio_pci->dev.kobj,
+ "pcie_slot")) {
+ pci_dev_put(trio->trio_pci);
+ trio->trio_pci = NULL;
+ dev_warn(dev, "Failed to create symblink for %s\n",
+ trio->bus);
+ }
+ } else
+ dev_warn(dev, "Device %s not found\n", trio->bus);
+
+ dev_info(dev, "v" DRIVER_VERSION " probed\n");
+ return 0;
+err:
+ dev_warn(dev, "Error probing trio\n");
+ if (trio->events)
+ kfree(trio->events);
+ kfree(trio);
+ platform_set_drvdata(pdev, NULL);
+ return ret;
+}
+
+static int trio_remove(struct platform_device *pdev)
+{
+ struct trio_context *trio = platform_get_drvdata(pdev);
+ struct device *dev = &pdev->dev;
+ int i;
+
+ for (i = 0; i < trio->num_irqs; ++i) {
+ struct event_context *ctx = &trio->events[i];
+
+ if (ctx->irq)
+ devm_free_irq(&pdev->dev, ctx->irq, ctx);
+ }
+ device_remove_file(dev, &dev_attr_current_profile);
+ device_remove_file(dev, &dev_attr_available_profiles);
+
+ /* Delete the symlink and decrement the reference count. */
+ if (trio->trio_pci != NULL) {
+ sysfs_remove_link(&dev->kobj, "pcie_slot");
+ pci_dev_put(trio->trio_pci);
+ }
+ platform_set_drvdata(pdev, NULL);
+ kfree(trio->events);
+ kfree(trio);
+
+ return 0;
+}
+
+static const struct acpi_device_id trio_acpi_ids[] = {
+ {"MLNXBF06", 0},
+ {},
+};
+
+MODULE_DEVICE_TABLE(acpi, trio_acpi_ids);
+static struct platform_driver mlx_trio_driver = {
+ .driver = {
+ .name = DRIVER_NAME,
+ .acpi_match_table = ACPI_PTR(trio_acpi_ids),
+ },
+ .probe = trio_probe,
+ .remove = trio_remove,
+};
+
+static int __init trio_init(void)
+{
+ int ret;
+
+ ret = platform_driver_register(&mlx_trio_driver);
+ if (ret)
+ pr_err("Failed to register trio driver.\n");
+
+ return ret;
+}
+
+static void __exit trio_exit(void)
+{
+ platform_driver_unregister(&mlx_trio_driver);
+}
+
+module_init(trio_init);
+module_exit(trio_exit);
+
+MODULE_DESCRIPTION(DRIVER_DESCRIPTION);
+MODULE_AUTHOR("Shravan Kumar Ramani <shravankr@nvidia.com>");
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_VERSION(DRIVER_VERSION);
diff --git a/drivers/platform/mellanox/trio_regs.h b/drivers/platform/mellanox/trio_regs.h
new file mode 100644
index 000000000..cc2f2003d
--- /dev/null
+++ b/drivers/platform/mellanox/trio_regs.h
@@ -0,0 +1,236 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2019, Mellanox Technologies. All rights reserved.
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+#ifndef __TRIO_REGS_H__
+#define __TRIO_REGS_H__
+
+#ifdef __ASSEMBLER__
+#define _64bit(x) x
+#else /* __ASSEMBLER__ */
+#define _64bit(x) x ## ULL
+#endif /* __ASSEMBLER */
+
+#include <linux/types.h>
+
+#define L3C_PROF_RD_MISS__FIRST_WORD 0x0600
+#define L3C_PROF_RD_MISS__LAST_WORD 0x063c
+#define L3C_PROF_RD_MISS__LENGTH 0x0040
+#define L3C_PROF_RD_MISS__STRIDE 0x0004
+
+#define L3C_PROF_RD_MISS__LOW_ORDER_SHIFT 0
+#define L3C_PROF_RD_MISS__LOW_ORDER_WIDTH 5
+#define L3C_PROF_RD_MISS__LOW_ORDER_RESET_VAL 11
+#define L3C_PROF_RD_MISS__LOW_ORDER_RMASK 0x1f
+#define L3C_PROF_RD_MISS__LOW_ORDER_MASK 0x1f
+
+#define L3C_PROF_RD_MISS__HIGH_ORDER_SHIFT 5
+#define L3C_PROF_RD_MISS__HIGH_ORDER_WIDTH 5
+#define L3C_PROF_RD_MISS__HIGH_ORDER_RESET_VAL 0
+#define L3C_PROF_RD_MISS__HIGH_ORDER_RMASK 0x1f
+#define L3C_PROF_RD_MISS__HIGH_ORDER_MASK 0x3e0
+
+#define L3C_PROF_RD_MISS__ALLOC_STATE_SHIFT 12
+#define L3C_PROF_RD_MISS__ALLOC_STATE_WIDTH 1
+#define L3C_PROF_RD_MISS__ALLOC_STATE_RESET_VAL 0
+#define L3C_PROF_RD_MISS__ALLOC_STATE_RMASK 0x1
+#define L3C_PROF_RD_MISS__ALLOC_STATE_MASK 0x1000
+
+#define L3C_PROF_RD_MISS__LOW_STATE_BLK_ALLOC_SHIFT 13
+#define L3C_PROF_RD_MISS__LOW_STATE_BLK_ALLOC_WIDTH 1
+#define L3C_PROF_RD_MISS__LOW_STATE_BLK_ALLOC_RESET_VAL 0
+#define L3C_PROF_RD_MISS__LOW_STATE_BLK_ALLOC_RMASK 0x1
+#define L3C_PROF_RD_MISS__LOW_STATE_BLK_ALLOC_MASK 0x2000
+
+#define L3C_PROF_RD_MISS__HIGH_STATE_BLK_ALLOC_SHIFT 14
+#define L3C_PROF_RD_MISS__HIGH_STATE_BLK_ALLOC_WIDTH 1
+#define L3C_PROF_RD_MISS__HIGH_STATE_BLK_ALLOC_RESET_VAL 0
+#define L3C_PROF_RD_MISS__HIGH_STATE_BLK_ALLOC_RMASK 0x1
+#define L3C_PROF_RD_MISS__HIGH_STATE_BLK_ALLOC_MASK 0x4000
+
+#define L3C_PROF_RD_MISS__PROB_SHIFT 16
+#define L3C_PROF_RD_MISS__PROB_WIDTH 16
+#define L3C_PROF_RD_MISS__PROB_RESET_VAL 0
+#define L3C_PROF_RD_MISS__PROB_RMASK 0xffff
+#define L3C_PROF_RD_MISS__PROB_MASK 0xffff0000
+
+#define TRIO_DEV_CTL 0x0008
+#define TRIO_DEV_CTL__LENGTH 0x0001
+
+#define TRIO_DEV_CTL__NDN_ROUTE_ORDER_SHIFT 0
+#define TRIO_DEV_CTL__NDN_ROUTE_ORDER_WIDTH 1
+#define TRIO_DEV_CTL__NDN_ROUTE_ORDER_RESET_VAL 0
+#define TRIO_DEV_CTL__NDN_ROUTE_ORDER_RMASK 0x1
+#define TRIO_DEV_CTL__NDN_ROUTE_ORDER_MASK 0x1
+
+#define TRIO_DEV_CTL__CDN_ROUTE_ORDER_SHIFT 1
+#define TRIO_DEV_CTL__CDN_ROUTE_ORDER_WIDTH 1
+#define TRIO_DEV_CTL__CDN_ROUTE_ORDER_RESET_VAL 1
+#define TRIO_DEV_CTL__CDN_ROUTE_ORDER_RMASK 0x1
+#define TRIO_DEV_CTL__CDN_ROUTE_ORDER_MASK 0x2
+
+#define TRIO_DEV_CTL__DDN_ROUTE_ORDER_SHIFT 2
+#define TRIO_DEV_CTL__DDN_ROUTE_ORDER_WIDTH 1
+#define TRIO_DEV_CTL__DDN_ROUTE_ORDER_RESET_VAL 1
+#define TRIO_DEV_CTL__DDN_ROUTE_ORDER_RMASK 0x1
+#define TRIO_DEV_CTL__DDN_ROUTE_ORDER_MASK 0x4
+
+#define TRIO_DEV_CTL__DMA_RD_CA_ENA_SHIFT 3
+#define TRIO_DEV_CTL__DMA_RD_CA_ENA_WIDTH 1
+#define TRIO_DEV_CTL__DMA_RD_CA_ENA_RESET_VAL 1
+#define TRIO_DEV_CTL__DMA_RD_CA_ENA_RMASK 0x1
+#define TRIO_DEV_CTL__DMA_RD_CA_ENA_MASK 0x8
+
+#define TRIO_DEV_CTL__L3_PROFILE_OVD_SHIFT 4
+#define TRIO_DEV_CTL__L3_PROFILE_OVD_WIDTH 1
+#define TRIO_DEV_CTL__L3_PROFILE_OVD_RESET_VAL 0
+#define TRIO_DEV_CTL__L3_PROFILE_OVD_RMASK 0x1
+#define TRIO_DEV_CTL__L3_PROFILE_OVD_MASK 0x10
+
+#define TRIO_DEV_CTL__L3_PROFILE_VAL_SHIFT 5
+#define TRIO_DEV_CTL__L3_PROFILE_VAL_WIDTH 4
+#define TRIO_DEV_CTL__L3_PROFILE_VAL_RESET_VAL 0
+#define TRIO_DEV_CTL__L3_PROFILE_VAL_RMASK 0xf
+#define TRIO_DEV_CTL__L3_PROFILE_VAL_MASK 0x1e0
+
+#define TRIO_DEV_CTL__WR_SLVERR_MAP_SHIFT 9
+#define TRIO_DEV_CTL__WR_SLVERR_MAP_WIDTH 2
+#define TRIO_DEV_CTL__WR_SLVERR_MAP_RESET_VAL 2
+#define TRIO_DEV_CTL__WR_SLVERR_MAP_RMASK 0x3
+#define TRIO_DEV_CTL__WR_SLVERR_MAP_MASK 0x600
+#define TRIO_DEV_CTL__WR_SLVERR_MAP_VAL_OKAY 0x0
+#define TRIO_DEV_CTL__WR_SLVERR_MAP_VAL_DATAERROR 0x2
+#define TRIO_DEV_CTL__WR_SLVERR_MAP_VAL_NONDATAERROR 0x3
+
+#define TRIO_DEV_CTL__WR_DECERR_MAP_SHIFT 11
+#define TRIO_DEV_CTL__WR_DECERR_MAP_WIDTH 2
+#define TRIO_DEV_CTL__WR_DECERR_MAP_RESET_VAL 3
+#define TRIO_DEV_CTL__WR_DECERR_MAP_RMASK 0x3
+#define TRIO_DEV_CTL__WR_DECERR_MAP_MASK 0x1800
+#define TRIO_DEV_CTL__WR_DECERR_MAP_VAL_OKAY 0x0
+#define TRIO_DEV_CTL__WR_DECERR_MAP_VAL_DATAERROR 0x2
+#define TRIO_DEV_CTL__WR_DECERR_MAP_VAL_NONDATAERROR 0x3
+
+#define TRIO_DEV_CTL__RD_SLVERR_MAP_SHIFT 13
+#define TRIO_DEV_CTL__RD_SLVERR_MAP_WIDTH 2
+#define TRIO_DEV_CTL__RD_SLVERR_MAP_RESET_VAL 2
+#define TRIO_DEV_CTL__RD_SLVERR_MAP_RMASK 0x3
+#define TRIO_DEV_CTL__RD_SLVERR_MAP_MASK 0x6000
+#define TRIO_DEV_CTL__RD_SLVERR_MAP_VAL_OKAY 0x0
+#define TRIO_DEV_CTL__RD_SLVERR_MAP_VAL_DATAERROR 0x2
+#define TRIO_DEV_CTL__RD_SLVERR_MAP_VAL_NONDATAERROR 0x3
+
+#define TRIO_DEV_CTL__RD_DECERR_MAP_SHIFT 15
+#define TRIO_DEV_CTL__RD_DECERR_MAP_WIDTH 2
+#define TRIO_DEV_CTL__RD_DECERR_MAP_RESET_VAL 3
+#define TRIO_DEV_CTL__RD_DECERR_MAP_RMASK 0x3
+#define TRIO_DEV_CTL__RD_DECERR_MAP_MASK 0x18000
+#define TRIO_DEV_CTL__RD_DECERR_MAP_VAL_OKAY 0x0
+#define TRIO_DEV_CTL__RD_DECERR_MAP_VAL_DATAERROR 0x2
+#define TRIO_DEV_CTL__RD_DECERR_MAP_VAL_NONDATAERROR 0x3
+
+#define TRIO_DEV_CTL__CDN_REQ_BUF_ENA_SHIFT 17
+#define TRIO_DEV_CTL__CDN_REQ_BUF_ENA_WIDTH 1
+#define TRIO_DEV_CTL__CDN_REQ_BUF_ENA_RESET_VAL 1
+#define TRIO_DEV_CTL__CDN_REQ_BUF_ENA_RMASK 0x1
+#define TRIO_DEV_CTL__CDN_REQ_BUF_ENA_MASK 0x20000
+
+#define TRIO_DEV_CTL__DMA_WRQ_HWM_SHIFT 20
+#define TRIO_DEV_CTL__DMA_WRQ_HWM_WIDTH 8
+#define TRIO_DEV_CTL__DMA_WRQ_HWM_RESET_VAL 255
+#define TRIO_DEV_CTL__DMA_WRQ_HWM_RMASK 0xff
+#define TRIO_DEV_CTL__DMA_WRQ_HWM_MASK 0xff00000
+
+#define TRIO_DEV_CTL__GTHR_DELAY_ADJ_SHIFT 28
+#define TRIO_DEV_CTL__GTHR_DELAY_ADJ_WIDTH 4
+#define TRIO_DEV_CTL__GTHR_DELAY_ADJ_RESET_VAL 0
+#define TRIO_DEV_CTL__GTHR_DELAY_ADJ_RMASK 0xf
+#define TRIO_DEV_CTL__GTHR_DELAY_ADJ_MASK 0xf0000000
+
+#ifndef __ASSEMBLER__
+__extension__
+typedef union {
+ struct {
+ /*
+ * When 1, packets sent on the NDN will be routed x-first.
+ * When 0, packets will be routed y-first. This setting must
+ * match the setting in the Tiles. Devices may have
+ * additional interfaces with customized route-order settings
+ * used in addition to or instead of this field.
+ */
+ u64 ndn_route_order : 1;
+ /*
+ * When 1, packets sent on the CDN will be routed x-first.
+ * When 0, packets will be routed y-first. This setting must
+ * match the setting in the Tiles. Devices may have
+ * additional interfaces with customized route-order settings
+ * used in addition to or instead of this field.
+ */
+ u64 cdn_route_order : 1;
+ /*
+ * When 1, packets sent on the DDN will be routed x-first.
+ * When 0, packets will be routed y-first. This setting must
+ * match the setting in the Tiles. Devices may have
+ * additional interfaces with customized route-order settings
+ * used in addition to or instead of this field.
+ */
+ u64 ddn_route_order : 1;
+ /*
+ * When 1, the ExpCompAck flow will be used on DMA reads
+ * which allows read-data-bypass for lower latency. Must only
+ * be changed if no DMA read traffic is inflight.
+ */
+ u64 dma_rd_ca_ena : 1;
+ /*
+ * For devices with DMA. When 1, the L3 cache profile will be
+ * forced to L3_PROFILE_VAL. When 0, the L3 profile is
+ * selected by the device.
+ */
+ u64 l3_profile_ovd : 1;
+ /*
+ * For devices with DMA. L3 cache profile to be used when
+ * L3_PROFILE_OVD is 1.
+ */
+ u64 l3_profile_val : 4;
+ /* Write response mapping for MMIO slave errors */
+ u64 wr_slverr_map : 2;
+ /* Write response mapping for MMIO decode errors */
+ u64 wr_decerr_map : 2;
+ /* Read response mapping for MMIO slave errors */
+ u64 rd_slverr_map : 2;
+ /* Read response mapping for MMIO decode errors */
+ u64 rd_decerr_map : 2;
+ /*
+ * When 1, the CDN sync FIFO is allowed to back pressure
+ * until full to avoid retries and improve performance
+ */
+ u64 cdn_req_buf_ena : 1;
+ /* Reserved. */
+ u64 __reserved_0 : 2;
+ /*
+ * For diagnostics only. Block new traffic when WRQ_INFL
+ * count exceeds this threshold. This register field does not
+ * exist in the PKA or Tile or MSS.
+ */
+ u64 dma_wrq_hwm : 8;
+ /* For diagnostics only. Adjust packet gather delay on RNF */
+ u64 gthr_delay_adj : 4;
+ /* Reserved. */
+ u64 __reserved_1 : 32;
+ };
+
+ u64 word;
+} TRIO_DEV_CTL_t;
+#endif /* !defined(__ASSEMBLER__) */
+
+#define TRIO_MMIO_ERROR_INFO 0x0608
+
+#define TRIO_MAP_ERR_STS 0x0810
+
+#define TRIO_TILE_PIO_CPL_ERR_STS 0x09f0
+
+#endif /* !defined(__TRIO_REGS_H__) */
--
2.20.1