]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
Merge tag 'driver-core-6.13-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git...
authorLinus Torvalds <torvalds@linux-foundation.org>
Fri, 29 Nov 2024 19:43:29 +0000 (11:43 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Fri, 29 Nov 2024 19:43:29 +0000 (11:43 -0800)
Pull driver core updates from Greg KH:
 "Here is a small set of driver core changes for 6.13-rc1.

  Nothing major for this merge cycle, except for the two simple merge
  conflicts are here just to make life interesting.

  Included in here are:

   - sysfs core changes and preparations for more sysfs api cleanups
     that can come through all driver trees after -rc1 is out

   - fw_devlink fixes based on many reports and debugging sessions

   - list_for_each_reverse() removal, no one was using it!

   - last-minute seq_printf() format string bug found and fixed in many
     drivers all at once.

   - minor bugfixes and changes full details in the shortlog"

* tag 'driver-core-6.13-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core: (35 commits)
  Fix a potential abuse of seq_printf() format string in drivers
  cpu: Remove spurious NULL in attribute_group definition
  s390/con3215: Remove spurious NULL in attribute_group definition
  perf: arm-ni: Remove spurious NULL in attribute_group definition
  driver core: Constify bin_attribute definitions
  sysfs: attribute_group: allow registration of const bin_attribute
  firmware_loader: Fix possible resource leak in fw_log_firmware_info()
  drivers: core: fw_devlink: Fix excess parameter description in docstring
  driver core: class: Correct WARN() message in APIs class_(for_each|find)_device()
  cacheinfo: Use of_property_present() for non-boolean properties
  cdx: Fix cdx_mmap_resource() after constifying attr in ->mmap()
  drivers: core: fw_devlink: Make the error message a bit more useful
  phy: tegra: xusb: Set fwnode for xusb port devices
  drm: display: Set fwnode for aux bus devices
  driver core: fw_devlink: Stop trying to optimize cycle detection logic
  driver core: Constify attribute arguments of binary attributes
  sysfs: bin_attribute: add const read/write callback variants
  sysfs: implement all BIN_ATTR_* macros in terms of __BIN_ATTR()
  sysfs: treewide: constify attribute callback of bin_attribute::llseek()
  sysfs: treewide: constify attribute callback of bin_attribute::mmap()
  ...

14 files changed:
1  2 
drivers/base/core.c
drivers/gpio/gpio-aspeed.c
drivers/gpio/gpio-omap.c
drivers/gpio/gpio-xgs-iproc.c
drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c
drivers/pci/pci-sysfs.c
drivers/phy/tegra/xusb.c
drivers/pinctrl/pinctrl-stmfx.c
drivers/pinctrl/pinctrl-sx150x.c
drivers/pinctrl/renesas/pinctrl-rzg2l.c
drivers/platform/x86/amd/hsmp/acpi.c
drivers/platform/x86/amd/hsmp/plat.c
drivers/platform/x86/intel/pmt/class.c
kernel/cpu.c

Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
index 4aa4d66f491af4e0075d25bd35b583881d57718d,0000000000000000000000000000000000000000..dd5b5773328a9aff376a389cbd0109cb8cf0e385
mode 100644,000000..100644
--- /dev/null
@@@ -1,378 -1,0 +1,378 @@@
-                                        struct bin_attribute *battr, int id)
 +// SPDX-License-Identifier: GPL-2.0
 +/*
 + * AMD HSMP Platform Driver
 + * Copyright (c) 2024, AMD.
 + * All Rights Reserved.
 + *
 + * This file provides an ACPI based driver implementation for HSMP interface.
 + */
 +
 +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 +
 +#include <asm/amd_hsmp.h>
 +#include <asm/amd_nb.h>
 +
 +#include <linux/acpi.h>
 +#include <linux/device.h>
 +#include <linux/dev_printk.h>
 +#include <linux/ioport.h>
 +#include <linux/kstrtox.h>
 +#include <linux/module.h>
 +#include <linux/platform_device.h>
 +#include <linux/sysfs.h>
 +#include <linux/uuid.h>
 +
 +#include <uapi/asm-generic/errno-base.h>
 +
 +#include "hsmp.h"
 +
 +#define DRIVER_NAME           "amd_hsmp"
 +#define DRIVER_VERSION                "2.3"
 +#define ACPI_HSMP_DEVICE_HID  "AMDI0097"
 +
 +/* These are the strings specified in ACPI table */
 +#define MSG_IDOFF_STR         "MsgIdOffset"
 +#define MSG_ARGOFF_STR                "MsgArgOffset"
 +#define MSG_RESPOFF_STR               "MsgRspOffset"
 +
 +static struct hsmp_plat_device *hsmp_pdev;
 +
 +static int amd_hsmp_acpi_rdwr(struct hsmp_socket *sock, u32 offset,
 +                            u32 *value, bool write)
 +{
 +      if (write)
 +              iowrite32(*value, sock->virt_base_addr + offset);
 +      else
 +              *value = ioread32(sock->virt_base_addr + offset);
 +
 +      return 0;
 +}
 +
 +/* This is the UUID used for HSMP */
 +static const guid_t acpi_hsmp_uuid = GUID_INIT(0xb74d619d, 0x5707, 0x48bd,
 +                                              0xa6, 0x9f, 0x4e, 0xa2,
 +                                              0x87, 0x1f, 0xc2, 0xf6);
 +
 +static inline bool is_acpi_hsmp_uuid(union acpi_object *obj)
 +{
 +      if (obj->type == ACPI_TYPE_BUFFER && obj->buffer.length == UUID_SIZE)
 +              return guid_equal((guid_t *)obj->buffer.pointer, &acpi_hsmp_uuid);
 +
 +      return false;
 +}
 +
 +static inline int hsmp_get_uid(struct device *dev, u16 *sock_ind)
 +{
 +      char *uid;
 +
 +      /*
 +       * UID (ID00, ID01..IDXX) is used for differentiating sockets,
 +       * read it and strip the "ID" part of it and convert the remaining
 +       * bytes to integer.
 +       */
 +      uid = acpi_device_uid(ACPI_COMPANION(dev));
 +
 +      return kstrtou16(uid + 2, 10, sock_ind);
 +}
 +
 +static acpi_status hsmp_resource(struct acpi_resource *res, void *data)
 +{
 +      struct hsmp_socket *sock = data;
 +      struct resource r;
 +
 +      switch (res->type) {
 +      case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
 +              if (!acpi_dev_resource_memory(res, &r))
 +                      return AE_ERROR;
 +              if (!r.start || r.end < r.start || !(r.flags & IORESOURCE_MEM_WRITEABLE))
 +                      return AE_ERROR;
 +              sock->mbinfo.base_addr = r.start;
 +              sock->mbinfo.size = resource_size(&r);
 +              break;
 +      case ACPI_RESOURCE_TYPE_END_TAG:
 +              break;
 +      default:
 +              return AE_ERROR;
 +      }
 +
 +      return AE_OK;
 +}
 +
 +static int hsmp_read_acpi_dsd(struct hsmp_socket *sock)
 +{
 +      struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER, NULL };
 +      union acpi_object *guid, *mailbox_package;
 +      union acpi_object *dsd;
 +      acpi_status status;
 +      int ret = 0;
 +      int j;
 +
 +      status = acpi_evaluate_object_typed(ACPI_HANDLE(sock->dev), "_DSD", NULL,
 +                                          &buf, ACPI_TYPE_PACKAGE);
 +      if (ACPI_FAILURE(status)) {
 +              dev_err(sock->dev, "Failed to read mailbox reg offsets from DSD table, err: %s\n",
 +                      acpi_format_exception(status));
 +              return -ENODEV;
 +      }
 +
 +      dsd = buf.pointer;
 +
 +      /* HSMP _DSD property should contain 2 objects.
 +       * 1. guid which is an acpi object of type ACPI_TYPE_BUFFER
 +       * 2. mailbox which is an acpi object of type ACPI_TYPE_PACKAGE
 +       *    This mailbox object contains 3 more acpi objects of type
 +       *    ACPI_TYPE_PACKAGE for holding msgid, msgresp, msgarg offsets
 +       *    these packages inturn contain 2 acpi objects of type
 +       *    ACPI_TYPE_STRING and ACPI_TYPE_INTEGER
 +       */
 +      if (!dsd || dsd->type != ACPI_TYPE_PACKAGE || dsd->package.count != 2) {
 +              ret = -EINVAL;
 +              goto free_buf;
 +      }
 +
 +      guid = &dsd->package.elements[0];
 +      mailbox_package = &dsd->package.elements[1];
 +      if (!is_acpi_hsmp_uuid(guid) || mailbox_package->type != ACPI_TYPE_PACKAGE) {
 +              dev_err(sock->dev, "Invalid hsmp _DSD table data\n");
 +              ret = -EINVAL;
 +              goto free_buf;
 +      }
 +
 +      for (j = 0; j < mailbox_package->package.count; j++) {
 +              union acpi_object *msgobj, *msgstr, *msgint;
 +
 +              msgobj  = &mailbox_package->package.elements[j];
 +              msgstr  = &msgobj->package.elements[0];
 +              msgint  = &msgobj->package.elements[1];
 +
 +              /* package should have 1 string and 1 integer object */
 +              if (msgobj->type != ACPI_TYPE_PACKAGE ||
 +                  msgstr->type != ACPI_TYPE_STRING ||
 +                  msgint->type != ACPI_TYPE_INTEGER) {
 +                      ret = -EINVAL;
 +                      goto free_buf;
 +              }
 +
 +              if (!strncmp(msgstr->string.pointer, MSG_IDOFF_STR,
 +                           msgstr->string.length)) {
 +                      sock->mbinfo.msg_id_off = msgint->integer.value;
 +              } else if (!strncmp(msgstr->string.pointer, MSG_RESPOFF_STR,
 +                                  msgstr->string.length)) {
 +                      sock->mbinfo.msg_resp_off =  msgint->integer.value;
 +              } else if (!strncmp(msgstr->string.pointer, MSG_ARGOFF_STR,
 +                                  msgstr->string.length)) {
 +                      sock->mbinfo.msg_arg_off = msgint->integer.value;
 +              } else {
 +                      ret = -ENOENT;
 +                      goto free_buf;
 +              }
 +      }
 +
 +      if (!sock->mbinfo.msg_id_off || !sock->mbinfo.msg_resp_off ||
 +          !sock->mbinfo.msg_arg_off)
 +              ret = -EINVAL;
 +
 +free_buf:
 +      ACPI_FREE(buf.pointer);
 +      return ret;
 +}
 +
 +static int hsmp_read_acpi_crs(struct hsmp_socket *sock)
 +{
 +      acpi_status status;
 +
 +      status = acpi_walk_resources(ACPI_HANDLE(sock->dev), METHOD_NAME__CRS,
 +                                   hsmp_resource, sock);
 +      if (ACPI_FAILURE(status)) {
 +              dev_err(sock->dev, "Failed to look up MP1 base address from CRS method, err: %s\n",
 +                      acpi_format_exception(status));
 +              return -EINVAL;
 +      }
 +      if (!sock->mbinfo.base_addr || !sock->mbinfo.size)
 +              return -EINVAL;
 +
 +      /* The mapped region should be un-cached */
 +      sock->virt_base_addr = devm_ioremap_uc(sock->dev, sock->mbinfo.base_addr,
 +                                             sock->mbinfo.size);
 +      if (!sock->virt_base_addr) {
 +              dev_err(sock->dev, "Failed to ioremap MP1 base address\n");
 +              return -ENOMEM;
 +      }
 +
 +      return 0;
 +}
 +
 +/* Parse the ACPI table to read the data */
 +static int hsmp_parse_acpi_table(struct device *dev, u16 sock_ind)
 +{
 +      struct hsmp_socket *sock = &hsmp_pdev->sock[sock_ind];
 +      int ret;
 +
 +      sock->sock_ind          = sock_ind;
 +      sock->dev               = dev;
 +      sock->amd_hsmp_rdwr     = amd_hsmp_acpi_rdwr;
 +
 +      sema_init(&sock->hsmp_sem, 1);
 +
 +      dev_set_drvdata(dev, sock);
 +
 +      /* Read MP1 base address from CRS method */
 +      ret = hsmp_read_acpi_crs(sock);
 +      if (ret)
 +              return ret;
 +
 +      /* Read mailbox offsets from DSD table */
 +      return hsmp_read_acpi_dsd(sock);
 +}
 +
 +static ssize_t hsmp_metric_tbl_acpi_read(struct file *filp, struct kobject *kobj,
 +                                       struct bin_attribute *bin_attr, char *buf,
 +                                       loff_t off, size_t count)
 +{
 +      struct device *dev = container_of(kobj, struct device, kobj);
 +      struct hsmp_socket *sock = dev_get_drvdata(dev);
 +
 +      return hsmp_metric_tbl_read(sock, buf, count);
 +}
 +
 +static umode_t hsmp_is_sock_attr_visible(struct kobject *kobj,
++                                       const struct bin_attribute *battr, int id)
 +{
 +      if (hsmp_pdev->proto_ver == HSMP_PROTO_VER6)
 +              return battr->attr.mode;
 +
 +      return 0;
 +}
 +
 +static int init_acpi(struct device *dev)
 +{
 +      u16 sock_ind;
 +      int ret;
 +
 +      ret = hsmp_get_uid(dev, &sock_ind);
 +      if (ret)
 +              return ret;
 +      if (sock_ind >= hsmp_pdev->num_sockets)
 +              return -EINVAL;
 +
 +      ret = hsmp_parse_acpi_table(dev, sock_ind);
 +      if (ret) {
 +              dev_err(dev, "Failed to parse ACPI table\n");
 +              return ret;
 +      }
 +
 +      /* Test the hsmp interface */
 +      ret = hsmp_test(sock_ind, 0xDEADBEEF);
 +      if (ret) {
 +              dev_err(dev, "HSMP test message failed on Fam:%x model:%x\n",
 +                      boot_cpu_data.x86, boot_cpu_data.x86_model);
 +              dev_err(dev, "Is HSMP disabled in BIOS ?\n");
 +              return ret;
 +      }
 +
 +      ret = hsmp_cache_proto_ver(sock_ind);
 +      if (ret) {
 +              dev_err(dev, "Failed to read HSMP protocol version\n");
 +              return ret;
 +      }
 +
 +      if (hsmp_pdev->proto_ver == HSMP_PROTO_VER6) {
 +              ret = hsmp_get_tbl_dram_base(sock_ind);
 +              if (ret)
 +                      dev_err(dev, "Failed to init metric table\n");
 +      }
 +
 +      return ret;
 +}
 +
 +static struct bin_attribute  hsmp_metric_tbl_attr = {
 +      .attr = { .name = HSMP_METRICS_TABLE_NAME, .mode = 0444},
 +      .read = hsmp_metric_tbl_acpi_read,
 +      .size = sizeof(struct hsmp_metric_table),
 +};
 +
 +static struct bin_attribute *hsmp_attr_list[] = {
 +      &hsmp_metric_tbl_attr,
 +      NULL
 +};
 +
 +static struct attribute_group hsmp_attr_grp = {
 +      .bin_attrs = hsmp_attr_list,
 +      .is_bin_visible = hsmp_is_sock_attr_visible,
 +};
 +
 +static const struct attribute_group *hsmp_groups[] = {
 +      &hsmp_attr_grp,
 +      NULL
 +};
 +
 +static const struct acpi_device_id amd_hsmp_acpi_ids[] = {
 +      {ACPI_HSMP_DEVICE_HID, 0},
 +      {}
 +};
 +MODULE_DEVICE_TABLE(acpi, amd_hsmp_acpi_ids);
 +
 +static int hsmp_acpi_probe(struct platform_device *pdev)
 +{
 +      int ret;
 +
 +      hsmp_pdev = get_hsmp_pdev();
 +      if (!hsmp_pdev)
 +              return -ENOMEM;
 +
 +      if (!hsmp_pdev->is_probed) {
 +              hsmp_pdev->num_sockets = amd_nb_num();
 +              if (hsmp_pdev->num_sockets == 0 || hsmp_pdev->num_sockets > MAX_AMD_SOCKETS)
 +                      return -ENODEV;
 +
 +              hsmp_pdev->sock = devm_kcalloc(&pdev->dev, hsmp_pdev->num_sockets,
 +                                             sizeof(*hsmp_pdev->sock),
 +                                             GFP_KERNEL);
 +              if (!hsmp_pdev->sock)
 +                      return -ENOMEM;
 +      }
 +
 +      ret = init_acpi(&pdev->dev);
 +      if (ret) {
 +              dev_err(&pdev->dev, "Failed to initialize HSMP interface.\n");
 +              return ret;
 +      }
 +
 +      if (!hsmp_pdev->is_probed) {
 +              ret = hsmp_misc_register(&pdev->dev);
 +              if (ret)
 +                      return ret;
 +              hsmp_pdev->is_probed = true;
 +      }
 +
 +      return 0;
 +}
 +
 +static void hsmp_acpi_remove(struct platform_device *pdev)
 +{
 +      /*
 +       * We register only one misc_device even on multi-socket system.
 +       * So, deregister should happen only once.
 +       */
 +      if (hsmp_pdev->is_probed) {
 +              hsmp_misc_deregister();
 +              hsmp_pdev->is_probed = false;
 +      }
 +}
 +
 +static struct platform_driver amd_hsmp_driver = {
 +      .probe          = hsmp_acpi_probe,
 +      .remove         = hsmp_acpi_remove,
 +      .driver         = {
 +              .name   = DRIVER_NAME,
 +              .acpi_match_table = amd_hsmp_acpi_ids,
 +              .dev_groups = hsmp_groups,
 +      },
 +};
 +
 +module_platform_driver(amd_hsmp_driver);
 +
 +MODULE_IMPORT_NS(AMD_HSMP);
 +MODULE_DESCRIPTION("AMD HSMP Platform Interface Driver");
 +MODULE_VERSION(DRIVER_VERSION);
 +MODULE_LICENSE("GPL");
index f8e74c0392ba0e2b8334f1c3d1e9b95de14fa98e,0000000000000000000000000000000000000000..748bbc35648474370275a80daf2c26e5d732f6ad
mode 100644,000000..100644
--- /dev/null
@@@ -1,338 -1,0 +1,338 @@@
-                                        struct bin_attribute *battr, int id)
 +// SPDX-License-Identifier: GPL-2.0
 +/*
 + * AMD HSMP Platform Driver
 + * Copyright (c) 2024, AMD.
 + * All Rights Reserved.
 + *
 + * This file provides platform device implementations.
 + */
 +
 +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 +
 +#include <asm/amd_hsmp.h>
 +#include <asm/amd_nb.h>
 +
 +#include <linux/device.h>
 +#include <linux/module.h>
 +#include <linux/pci.h>
 +#include <linux/platform_device.h>
 +#include <linux/sysfs.h>
 +
 +#include "hsmp.h"
 +
 +#define DRIVER_NAME           "amd_hsmp"
 +#define DRIVER_VERSION                "2.3"
 +
 +/*
 + * To access specific HSMP mailbox register, s/w writes the SMN address of HSMP mailbox
 + * register into the SMN_INDEX register, and reads/writes the SMN_DATA reg.
 + * Below are required SMN address for HSMP Mailbox register offsets in SMU address space
 + */
 +#define SMN_HSMP_BASE         0x3B00000
 +#define SMN_HSMP_MSG_ID               0x0010534
 +#define SMN_HSMP_MSG_ID_F1A_M0H       0x0010934
 +#define SMN_HSMP_MSG_RESP     0x0010980
 +#define SMN_HSMP_MSG_DATA     0x00109E0
 +
 +#define HSMP_INDEX_REG                0xc4
 +#define HSMP_DATA_REG         0xc8
 +
 +static struct hsmp_plat_device *hsmp_pdev;
 +
 +static int amd_hsmp_pci_rdwr(struct hsmp_socket *sock, u32 offset,
 +                           u32 *value, bool write)
 +{
 +      int ret;
 +
 +      if (!sock->root)
 +              return -ENODEV;
 +
 +      ret = pci_write_config_dword(sock->root, HSMP_INDEX_REG,
 +                                   sock->mbinfo.base_addr + offset);
 +      if (ret)
 +              return ret;
 +
 +      ret = (write ? pci_write_config_dword(sock->root, HSMP_DATA_REG, *value)
 +                   : pci_read_config_dword(sock->root, HSMP_DATA_REG, value));
 +
 +      return ret;
 +}
 +
 +static ssize_t hsmp_metric_tbl_plat_read(struct file *filp, struct kobject *kobj,
 +                                       struct bin_attribute *bin_attr, char *buf,
 +                                       loff_t off, size_t count)
 +{
 +      struct hsmp_socket *sock;
 +      u16 sock_ind;
 +
 +      sock_ind = (uintptr_t)bin_attr->private;
 +      if (sock_ind >= hsmp_pdev->num_sockets)
 +              return -EINVAL;
 +
 +      sock = &hsmp_pdev->sock[sock_ind];
 +
 +      return hsmp_metric_tbl_read(sock, buf, count);
 +}
 +
 +static umode_t hsmp_is_sock_attr_visible(struct kobject *kobj,
++                                       const struct bin_attribute *battr, int id)
 +{
 +      u16 sock_ind;
 +
 +      sock_ind = (uintptr_t)battr->private;
 +
 +      if (id == 0 && sock_ind >= hsmp_pdev->num_sockets)
 +              return SYSFS_GROUP_INVISIBLE;
 +
 +      if (hsmp_pdev->proto_ver == HSMP_PROTO_VER6)
 +              return battr->attr.mode;
 +
 +      return 0;
 +}
 +
 +/*
 + * AMD supports maximum of 8 sockets in a system.
 + * Static array of 8 + 1(for NULL) elements is created below
 + * to create sysfs groups for sockets.
 + * is_bin_visible function is used to show / hide the necessary groups.
 + */
 +#define HSMP_BIN_ATTR(index, _list)                                   \
 +static struct bin_attribute attr##index = {                           \
 +      .attr = { .name = HSMP_METRICS_TABLE_NAME, .mode = 0444},       \
 +      .private = (void *)index,                                       \
 +      .read = hsmp_metric_tbl_plat_read,                                      \
 +      .size = sizeof(struct hsmp_metric_table),                       \
 +};                                                                    \
 +static struct bin_attribute _list[] = {                                       \
 +      &attr##index,                                                   \
 +      NULL                                                            \
 +}
 +
 +HSMP_BIN_ATTR(0, *sock0_attr_list);
 +HSMP_BIN_ATTR(1, *sock1_attr_list);
 +HSMP_BIN_ATTR(2, *sock2_attr_list);
 +HSMP_BIN_ATTR(3, *sock3_attr_list);
 +HSMP_BIN_ATTR(4, *sock4_attr_list);
 +HSMP_BIN_ATTR(5, *sock5_attr_list);
 +HSMP_BIN_ATTR(6, *sock6_attr_list);
 +HSMP_BIN_ATTR(7, *sock7_attr_list);
 +
 +#define HSMP_BIN_ATTR_GRP(index, _list, _name)                        \
 +static struct attribute_group sock##index##_attr_grp = {      \
 +      .bin_attrs = _list,                                     \
 +      .is_bin_visible = hsmp_is_sock_attr_visible,            \
 +      .name = #_name,                                         \
 +}
 +
 +HSMP_BIN_ATTR_GRP(0, sock0_attr_list, socket0);
 +HSMP_BIN_ATTR_GRP(1, sock1_attr_list, socket1);
 +HSMP_BIN_ATTR_GRP(2, sock2_attr_list, socket2);
 +HSMP_BIN_ATTR_GRP(3, sock3_attr_list, socket3);
 +HSMP_BIN_ATTR_GRP(4, sock4_attr_list, socket4);
 +HSMP_BIN_ATTR_GRP(5, sock5_attr_list, socket5);
 +HSMP_BIN_ATTR_GRP(6, sock6_attr_list, socket6);
 +HSMP_BIN_ATTR_GRP(7, sock7_attr_list, socket7);
 +
 +static const struct attribute_group *hsmp_groups[] = {
 +      &sock0_attr_grp,
 +      &sock1_attr_grp,
 +      &sock2_attr_grp,
 +      &sock3_attr_grp,
 +      &sock4_attr_grp,
 +      &sock5_attr_grp,
 +      &sock6_attr_grp,
 +      &sock7_attr_grp,
 +      NULL
 +};
 +
 +static inline bool is_f1a_m0h(void)
 +{
 +      if (boot_cpu_data.x86 == 0x1A && boot_cpu_data.x86_model <= 0x0F)
 +              return true;
 +
 +      return false;
 +}
 +
 +static int init_platform_device(struct device *dev)
 +{
 +      struct hsmp_socket *sock;
 +      int ret, i;
 +
 +      for (i = 0; i < hsmp_pdev->num_sockets; i++) {
 +              if (!node_to_amd_nb(i))
 +                      return -ENODEV;
 +              sock = &hsmp_pdev->sock[i];
 +              sock->root                      = node_to_amd_nb(i)->root;
 +              sock->sock_ind                  = i;
 +              sock->dev                       = dev;
 +              sock->mbinfo.base_addr          = SMN_HSMP_BASE;
 +              sock->amd_hsmp_rdwr             = amd_hsmp_pci_rdwr;
 +
 +              /*
 +               * This is a transitional change from non-ACPI to ACPI, only
 +               * family 0x1A, model 0x00 platform is supported for both ACPI and non-ACPI.
 +               */
 +              if (is_f1a_m0h())
 +                      sock->mbinfo.msg_id_off = SMN_HSMP_MSG_ID_F1A_M0H;
 +              else
 +                      sock->mbinfo.msg_id_off = SMN_HSMP_MSG_ID;
 +
 +              sock->mbinfo.msg_resp_off       = SMN_HSMP_MSG_RESP;
 +              sock->mbinfo.msg_arg_off        = SMN_HSMP_MSG_DATA;
 +              sema_init(&sock->hsmp_sem, 1);
 +
 +              /* Test the hsmp interface on each socket */
 +              ret = hsmp_test(i, 0xDEADBEEF);
 +              if (ret) {
 +                      dev_err(dev, "HSMP test message failed on Fam:%x model:%x\n",
 +                              boot_cpu_data.x86, boot_cpu_data.x86_model);
 +                      dev_err(dev, "Is HSMP disabled in BIOS ?\n");
 +                      return ret;
 +              }
 +
 +              ret = hsmp_cache_proto_ver(i);
 +              if (ret) {
 +                      dev_err(dev, "Failed to read HSMP protocol version\n");
 +                      return ret;
 +              }
 +
 +              if (hsmp_pdev->proto_ver == HSMP_PROTO_VER6) {
 +                      ret = hsmp_get_tbl_dram_base(i);
 +                      if (ret)
 +                              dev_err(dev, "Failed to init metric table\n");
 +              }
 +      }
 +
 +      return 0;
 +}
 +
 +static int hsmp_pltdrv_probe(struct platform_device *pdev)
 +{
 +      int ret;
 +
 +      hsmp_pdev->sock = devm_kcalloc(&pdev->dev, hsmp_pdev->num_sockets,
 +                                     sizeof(*hsmp_pdev->sock),
 +                                     GFP_KERNEL);
 +      if (!hsmp_pdev->sock)
 +              return -ENOMEM;
 +
 +      ret = init_platform_device(&pdev->dev);
 +      if (ret) {
 +              dev_err(&pdev->dev, "Failed to init HSMP mailbox\n");
 +              return ret;
 +      }
 +
 +      return hsmp_misc_register(&pdev->dev);
 +}
 +
 +static void hsmp_pltdrv_remove(struct platform_device *pdev)
 +{
 +      hsmp_misc_deregister();
 +}
 +
 +static struct platform_driver amd_hsmp_driver = {
 +      .probe          = hsmp_pltdrv_probe,
 +      .remove         = hsmp_pltdrv_remove,
 +      .driver         = {
 +              .name   = DRIVER_NAME,
 +              .dev_groups = hsmp_groups,
 +      },
 +};
 +
 +static struct platform_device *amd_hsmp_platdev;
 +
 +static int hsmp_plat_dev_register(void)
 +{
 +      int ret;
 +
 +      amd_hsmp_platdev = platform_device_alloc(DRIVER_NAME, PLATFORM_DEVID_NONE);
 +      if (!amd_hsmp_platdev)
 +              return -ENOMEM;
 +
 +      ret = platform_device_add(amd_hsmp_platdev);
 +      if (ret)
 +              platform_device_put(amd_hsmp_platdev);
 +
 +      return ret;
 +}
 +
 +/*
 + * This check is only needed for backward compatibility of previous platforms.
 + * All new platforms are expected to support ACPI based probing.
 + */
 +static bool legacy_hsmp_support(void)
 +{
 +      if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD)
 +              return false;
 +
 +      switch (boot_cpu_data.x86) {
 +      case 0x19:
 +              switch (boot_cpu_data.x86_model) {
 +              case 0x00 ... 0x1F:
 +              case 0x30 ... 0x3F:
 +              case 0x90 ... 0x9F:
 +              case 0xA0 ... 0xAF:
 +                      return true;
 +              default:
 +                      return false;
 +              }
 +      case 0x1A:
 +              switch (boot_cpu_data.x86_model) {
 +              case 0x00 ... 0x1F:
 +                      return true;
 +              default:
 +                      return false;
 +              }
 +      default:
 +              return false;
 +      }
 +
 +      return false;
 +}
 +
 +static int __init hsmp_plt_init(void)
 +{
 +      int ret = -ENODEV;
 +
 +      if (!legacy_hsmp_support()) {
 +              pr_info("HSMP is not supported on Family:%x model:%x\n",
 +                      boot_cpu_data.x86, boot_cpu_data.x86_model);
 +              return ret;
 +      }
 +
 +      hsmp_pdev = get_hsmp_pdev();
 +      if (!hsmp_pdev)
 +              return -ENOMEM;
 +
 +      /*
 +       * amd_nb_num() returns number of SMN/DF interfaces present in the system
 +       * if we have N SMN/DF interfaces that ideally means N sockets
 +       */
 +      hsmp_pdev->num_sockets = amd_nb_num();
 +      if (hsmp_pdev->num_sockets == 0 || hsmp_pdev->num_sockets > MAX_AMD_SOCKETS)
 +              return ret;
 +
 +      ret = platform_driver_register(&amd_hsmp_driver);
 +      if (ret)
 +              return ret;
 +
 +      ret = hsmp_plat_dev_register();
 +      if (ret)
 +              platform_driver_unregister(&amd_hsmp_driver);
 +
 +      return ret;
 +}
 +
 +static void __exit hsmp_plt_exit(void)
 +{
 +      platform_device_unregister(amd_hsmp_platdev);
 +      platform_driver_unregister(&amd_hsmp_driver);
 +}
 +
 +device_initcall(hsmp_plt_init);
 +module_exit(hsmp_plt_exit);
 +
 +MODULE_IMPORT_NS(AMD_HSMP);
 +MODULE_DESCRIPTION("AMD HSMP Platform Interface Driver");
 +MODULE_VERSION(DRIVER_VERSION);
 +MODULE_LICENSE("GPL");
diff --cc kernel/cpu.c
Simple merge