]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
sif: sif_hwmon: add hwmon interface to export psif chip temperatures
authorFrancisco Triviño <francisco.trivino@oracle.com>
Tue, 2 Aug 2016 23:07:26 +0000 (01:07 +0200)
committerSantosh Shilimkar <santosh.shilimkar@oracle.com>
Fri, 12 Aug 2016 19:18:13 +0000 (12:18 -0700)
This commit adds support to export psif chip temperatures via hwmon
interface

Orabug: 24432362

Signed-off-by: Francisco Triviño <francisco.trivino@oracle.com>
Reviewed-by: Knut Omang <knut.omang@oracle.com>
drivers/infiniband/hw/sif/Makefile
drivers/infiniband/hw/sif/sif_dev.h
drivers/infiniband/hw/sif/sif_hwmon.c [new file with mode: 0644]
drivers/infiniband/hw/sif/sif_hwmon.h [new file with mode: 0644]
drivers/infiniband/hw/sif/sif_ireg.c

index b4e00159403b5d84380101124e99b01d473c7a67..825e82e32f6b6441c658656f7549e8c474bd4a0a 100644 (file)
@@ -5,7 +5,7 @@ obj-$(CONFIG_INFINIBAND_SIF) := sif.o
 
 sif-y := sif_main.o sif_mmu.o sif_dma.o sif_qp.o sif_sq.o \
    sif_cq.o sif_mr.o sif_mw.o sif_fmr.o sif_ah.o sif_pd.o sif_rq.o sif_srq.o \
-   sif_tqp.o sif_sndrcv.o sif_base.o sif_hwi.o sif_r3.o sif_vf.o sif_ireg.o sif_defs.o \
+   sif_tqp.o sif_sndrcv.o sif_base.o sif_hwi.o sif_r3.o sif_hwmon.o sif_vf.o sif_ireg.o sif_defs.o \
    sif_debug.o sif_epsc.o sif_eq.o sif_query.o sif_pqp.o \
    sif_verbs.o sif_fwa.o sif_checksum.o sif_spt.o sif_elog.o \
    sif_xmmu.o sif_xrc.o sif_mem.o sif_pt.o sif_idr.o version.o
index fb05b0222eff5c8a5a738c745971ad5bdd16bd43..59d9a2d3b8db27a8587048f4be453222803134be 100644 (file)
@@ -236,6 +236,7 @@ struct sif_compl; /* Declared in sif_cq.h */
 
 struct sif_dev {
        struct ib_device ib_dev;
+       struct device *hwmon_dev;
        struct sif_verbs sv;
        struct pci_dev *pdev;
        struct sif_dfs *dfs;    /* Optional debugfs info, if enabled in kernel */
diff --git a/drivers/infiniband/hw/sif/sif_hwmon.c b/drivers/infiniband/hw/sif/sif_hwmon.c
new file mode 100644 (file)
index 0000000..db3b4c0
--- /dev/null
@@ -0,0 +1,152 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ *    Author: Francisco Triviño <francisco.trivino@oracle.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * Driver for Oracle Scalable Infiniband Fabric (SIF) Host Channel Adapters
+ *
+ * sif_hwmon.c: SIF Hardware Monitoring
+ */
+
+#include "sif_dev.h"
+#include "sif_query.h"
+#include "sif_defs.h"
+#include "psif_hw_setget.h"
+#include "sif_hwmon.h"
+#include "psif_hw_data.h"
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+
+
+enum sif_hwmon_attr_type {
+       SIF_HWMON_ATTR_TEMP_MAX,
+       SIF_HWMON_ATTR_TEMP_MAIN,
+       SIF_HWMON_ATTR_TEMP_EPS,
+       SIF_HWMON_ATTR_TEMP_IBU,
+       SIF_HWMON_ATTR_TEMP_PEU,
+       SIF_HWMON_ATTR_TEMP_TSU,
+};
+
+static u64 sensor_show(const struct device *device,
+               struct device_attribute *attr,
+               char *buf,
+               int sif_hwmon_attr_temp)
+{
+        struct sif_dev *sdev = dev_get_drvdata(device);
+       struct psif_epsc_csr_req req;
+       struct psif_epsc_csr_rsp rsp;
+
+       /* EPSC supports the new requests starting from v.2.8 */
+       if (eps_version_ge(&sdev->es[sdev->mbox_epsc], 2, 8)) {
+               int ret = 0;
+
+               memset(&req, 0, sizeof(req));
+               memset(&rsp, 0, sizeof(rsp));
+               req.opcode = EPSC_QUERY;
+               req.u.query.data.op = EPSC_QUERY_ON_CHIP_TEMP;
+               ret = sif_epsc_wr(sdev, &req, &rsp);
+
+               if (!ret) {
+                       u16 t = 0;
+                       struct psif_epsc_query_on_chip_temp *temp =
+                               (struct psif_epsc_query_on_chip_temp *)&rsp.data;
+                       switch (sif_hwmon_attr_temp) {
+                       case SIF_HWMON_ATTR_TEMP_MAX:
+                               t = temp->max;
+                               break;
+                       case SIF_HWMON_ATTR_TEMP_MAIN:
+                               t = temp->main;
+                               break;
+                       case SIF_HWMON_ATTR_TEMP_EPS:
+                               t = temp->eps;
+                               break;
+                       case SIF_HWMON_ATTR_TEMP_IBU:
+                               t = temp->ibu;
+                               break;
+                       case SIF_HWMON_ATTR_TEMP_PEU:
+                               t = temp->peu;
+                               break;
+                       case SIF_HWMON_ATTR_TEMP_TSU:
+                               t = temp->tsu;
+                               break;
+                       default:
+                               WARN_ON(1);
+                       }
+                       sprintf(buf, "%u\n", t);
+               }
+               else
+                       sif_log(sdev, SIF_INFO, "Failed to query on chip temperature\n");
+       }
+       return strlen(buf);
+}
+
+/* hwmon-sysfs attributes */
+#define SENSOR_DEVICE_SHOW(field)                                      \
+static ssize_t show_sensor_##field(struct device *dev,                 \
+                               struct device_attribute *attr,          \
+                               char *buf)                              \
+{                                                                      \
+       return sensor_show(dev, attr, buf, SIF_HWMON_ATTR_TEMP_##field);\
+}
+
+SENSOR_DEVICE_SHOW(MAX);
+SENSOR_DEVICE_SHOW(MAIN);
+SENSOR_DEVICE_SHOW(EPS);
+SENSOR_DEVICE_SHOW(IBU);
+SENSOR_DEVICE_SHOW(PEU);
+SENSOR_DEVICE_SHOW(TSU);
+
+
+static SENSOR_DEVICE_ATTR(temp1_max, S_IRUGO, show_sensor_MAX, NULL, 1);
+static SENSOR_DEVICE_ATTR(temp1_main, S_IRUGO, show_sensor_MAIN, NULL, 1);
+static SENSOR_DEVICE_ATTR(temp1_eps, S_IRUGO, show_sensor_EPS, NULL, 1);
+static SENSOR_DEVICE_ATTR(temp1_ibu, S_IRUGO, show_sensor_IBU, NULL, 1);
+static SENSOR_DEVICE_ATTR(temp1_peu, S_IRUGO, show_sensor_PEU, NULL, 1);
+static SENSOR_DEVICE_ATTR(temp1_tsu, S_IRUGO, show_sensor_TSU, NULL, 1);
+
+
+static struct attribute *sif_hwmon_attrs[] = {
+       &sensor_dev_attr_temp1_max.dev_attr.attr,
+       &sensor_dev_attr_temp1_main.dev_attr.attr,
+       &sensor_dev_attr_temp1_eps.dev_attr.attr,
+       &sensor_dev_attr_temp1_ibu.dev_attr.attr,
+       &sensor_dev_attr_temp1_peu.dev_attr.attr,
+       &sensor_dev_attr_temp1_tsu.dev_attr.attr,
+       NULL,
+};
+
+ATTRIBUTE_GROUPS(sif_hwmon);
+
+void sif_register_hwmon_dev(struct sif_dev *sdev)
+{
+       struct device *dev = &sdev->pdev->dev;
+       struct device *hwmon_dev;
+
+       /* Skip hwmon registration for a VF device */
+       if (sdev->is_vf) {
+               sdev->hwmon_dev = NULL;
+               return;
+       }
+       hwmon_dev = hwmon_device_register_with_groups(dev, sdev->ib_dev.name,
+                                               sdev,
+                                               sif_hwmon_groups);
+       if (IS_ERR(hwmon_dev)) {
+               dev_err(dev, "Cannot register with hwmon, err=%ld\n",
+                       PTR_ERR(hwmon_dev));
+               hwmon_dev = NULL;
+       }
+       sdev->hwmon_dev = hwmon_dev;
+}
+
+void sif_unregister_hwmon_dev(struct sif_dev *sdev)
+{
+       struct device *hwmon_dev = sdev->hwmon_dev;
+       if (hwmon_dev) {
+               hwmon_device_unregister(hwmon_dev);
+               sdev->hwmon_dev = NULL;
+       }
+}
+
diff --git a/drivers/infiniband/hw/sif/sif_hwmon.h b/drivers/infiniband/hw/sif/sif_hwmon.h
new file mode 100644 (file)
index 0000000..e65c093
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ *    Author: Francisco Triviño <francisco.trivino@oracle.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * Driver for Oracle Scalable Infiniband Fabric (SIF) Host Channel Adapters
+ *
+ * sif_hwmon.h: SIF Hardware Monitoring
+ */
+
+#ifndef _SIF_HWMON_H
+#define _SIF_HWMON_H
+
+void sif_register_hwmon_dev(struct sif_dev *sdev);
+void sif_unregister_hwmon_dev(struct sif_dev *sdev);
+
+#endif
index 40e312c22c8f9f6cd26aa8efdcc47e93c111e813..762cf8d5bc8df7f564d4764e597c1a15a8cd6461 100644 (file)
@@ -36,6 +36,7 @@
 #include "sif_pd.h"
 #include "sif_base.h"
 #include "version.h"
+#include "sif_hwmon.h"
 
 
 static ssize_t show_rev(struct device *dev, struct device_attribute *attr,
@@ -899,6 +900,7 @@ int sif_register_ib_device(struct sif_dev *sdev)
                goto err_sysfsreg;
        }
 
+       sif_register_hwmon_dev(sdev);
        /* Populate the external kernel API (see sif_verbs.h): */
        sdev->sv.eps_wr = sif_eps_wr_ex;
        sdev->sv.create_cq = sif_create_cq;
@@ -920,6 +922,7 @@ void sif_unregister_ib_device(struct sif_dev *sdev)
 {
        struct ib_device *ibdev = &sdev->ib_dev;
 
+       sif_unregister_hwmon_dev(sdev);
        sdev->registered = false;
        ib_unregister_device(ibdev);
        sif_logi(ibdev, SIF_VERBS, "done unregistering device");