* Re: [PATCH] mm: thp: remove use_zero_page sysfs knob
From: Yang Shi @ 2018-07-23 21:49 UTC (permalink / raw)
To: David Rientjes, Matthew Wilcox
Cc: Andrew Morton, kirill, hughd, aaron.lu, linux-mm, linux-kernel
In-Reply-To: <alpine.DEB.2.21.1807231427550.103523@chino.kir.corp.google.com>
On 7/23/18 2:33 PM, David Rientjes wrote:
> On Mon, 23 Jul 2018, David Rientjes wrote:
>
>>>> The huge zero page can be reclaimed under memory pressure and, if it is,
>>>> it is attempted to be allocted again with gfp flags that attempt memory
>>>> compaction that can become expensive. If we are constantly under memory
>>>> pressure, it gets freed and reallocated millions of times always trying to
>>>> compact memory both directly and by kicking kcompactd in the background.
>>>>
>>>> It likely should also be per node.
>>> Have you benchmarked making the non-huge zero page per-node?
>>>
>> Not since we disable it :) I will, though. The more concerning issue for
>> us, modulo CVE-2017-1000405, is the cpu cost of constantly directly
>> compacting memory for allocating the hzp in real time after it has been
>> reclaimed. We've observed this happening tens or hundreds of thousands
>> of times on some systems. It will be 2MB per node on x86 if the data
>> suggests we should make it NUMA aware, I don't think the cost is too high
>> to leave it persistently available even under memory pressure if
>> use_zero_page is enabled.
>>
> Measuring access latency to 4GB of memory on Naples I observe ~6.7%
> slower access latency intrasocket and ~14% slower intersocket.
>
> use_zero_page is currently a simple thp flag, meaning it rejects writes
> where val != !!val, so perhaps it would be best to overload it with
> additional options? I can imagine 0x2 defining persistent allocation so
> that the hzp is not freed when the refcount goes to 0 and 0x4 defining if
> the hzp should be per node. Implementing persistent allocation fixes our
> concern with it, so I'd like to start there. Comments?
Sounds worth trying to me :-)A It might be worth making it persistent by
default. Keeping 2MB memory unreclaimable sounds not harmful for the use
case which prefer to use THP.
^ permalink raw reply
* [PATCH v7 01/12] dt-bindings: Add a document of PECI subsystem
From: Jae Hyun Yoo @ 2018-07-23 21:47 UTC (permalink / raw)
To: Jean Delvare, Guenter Roeck, Rob Herring, Mark Rutland, Lee Jones,
Joel Stanley, Andrew Jeffery, Jonathan Corbet, Greg Kroah-Hartman,
Gustavo Pimentel, Kishon Vijay Abraham I, Lorenzo Pieralisi,
Darrick J . Wong, Eric Sandeen, Arnd Bergmann, Wu Hao,
Tomohiro Kusumi, Bryant G . Ly, Frederic Barrat, David S . Miller,
Mauro Carvalho Chehab, Andrew Morton, Randy Dunlap,
Philippe Ombredanne, Vinod Koul, Stephen Boyd, David Kershner,
Uwe Kleine-Konig, Sagar Dharia, Johan Hovold, Thomas Gleixner,
Juergen Gross, Cyrille Pitchen
Cc: linux-hwmon, devicetree, linux-kernel, linux-arm-kernel,
linux-aspeed, linux-doc, openbmc, Jae Hyun Yoo
In-Reply-To: <20180723214751.1733-1-jae.hyun.yoo@linux.intel.com>
This commit adds a document of generic PECI bus, adapter and client
driver.
Signed-off-by: Jae Hyun Yoo <jae.hyun.yoo@linux.intel.com>
Reviewed-by: Haiyue Wang <haiyue.wang@linux.intel.com>
Reviewed-by: James Feist <james.feist@linux.intel.com>
Reviewed-by: Vernon Mauery <vernon.mauery@linux.intel.com>
Cc: Rob Herring <robh+dt@kernel.org>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Andrew Jeffery <andrew@aj.id.au>
Cc: Joel Stanley <joel@jms.id.au>
---
.../devicetree/bindings/peci/peci.txt | 43 +++++++++++++++++++
1 file changed, 43 insertions(+)
create mode 100644 Documentation/devicetree/bindings/peci/peci.txt
diff --git a/Documentation/devicetree/bindings/peci/peci.txt b/Documentation/devicetree/bindings/peci/peci.txt
new file mode 100644
index 000000000000..864b7ab4e9fa
--- /dev/null
+++ b/Documentation/devicetree/bindings/peci/peci.txt
@@ -0,0 +1,43 @@
+Generic device tree configuration for PECI adapters
+===================================================
+
+Required properties:
+- #address-cells : Should be <1>. Read more about client addresses below.
+- #size-cells : Should be <0>. Read more about client addresses below.
+
+The cells properties above define that an address of CPU clients of a PECI bus
+are described by a single value.
+
+Example:
+ peci0: peci-bus@0 {
+ compatible = "vendor,soc-peci";
+ reg = <0x0 0x1000>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
+Generic device tree configuration for PECI clients
+==================================================
+
+Required properties:
+- compatible : Should contain name of PECI client.
+- reg : Should contain address of a client CPU. Address range of CPU
+ clients starts from 0x30 based on PECI specification.
+
+Example:
+ peci-bus@0 {
+ compatible = "vendor,soc-peci";
+ reg = <0x0 0x1000>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ peci-client@30 {
+ compatible = "intel,peci-client";
+ reg = <0x30>;
+ };
+
+ peci-client@31 {
+ compatible = "intel,peci-client";
+ reg = <0x31>;
+ };
+ };
--
2.18.0
--
To unsubscribe from this list: send the line "unsubscribe linux-doc" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* [PATCH v7 03/12] peci: Add support for PECI bus driver core
From: Jae Hyun Yoo @ 2018-07-23 21:47 UTC (permalink / raw)
To: Jean Delvare, Guenter Roeck, Rob Herring, Mark Rutland, Lee Jones,
Joel Stanley, Andrew Jeffery, Jonathan Corbet, Greg Kroah-Hartman,
Gustavo Pimentel, Kishon Vijay Abraham I, Lorenzo Pieralisi,
Darrick J . Wong, Eric Sandeen, Arnd Bergmann, Wu Hao,
Tomohiro Kusumi, Bryant G . Ly, Frederic Barrat, David S . Miller,
Mauro Carvalho Chehab, Andrew Morton, Randy Dunlap,
Philippe Ombredanne, Vinod Koul, Stephen Boyd, David Kershner,
Uwe Kleine-Konig, Sagar Dharia, Johan Hovold, Thomas Gleixner,
Juergen Gross, Cyrille Pitchen
Cc: linux-hwmon, devicetree, linux-kernel, linux-arm-kernel,
linux-aspeed, linux-doc, openbmc, Jae Hyun Yoo, Fengguang Wu,
Gavin Schenk, Viresh Kumar, Cyrille Pitchen, Alan Cox,
Andrew Lunn, Andy Shevchenko, Benjamin Herrenschmidt,
Jason M Biils, Julia Cartwright
In-Reply-To: <20180723214751.1733-1-jae.hyun.yoo@linux.intel.com>
This commit adds driver implementation for PECI bus core into linux
driver framework.
Signed-off-by: Jae Hyun Yoo <jae.hyun.yoo@linux.intel.com>
Signed-off-by: Fengguang Wu <fengguang.wu@intel.com>
Reviewed-by: Haiyue Wang <haiyue.wang@linux.intel.com>
Reviewed-by: James Feist <james.feist@linux.intel.com>
Reviewed-by: Vernon Mauery <vernon.mauery@linux.intel.com>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Philippe Ombredanne <pombredanne@nexb.com>
Cc: Gavin Schenk <g.schenk@eckelmann.de>
Cc: Vinod Koul <vkoul@kernel.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Sagar Dharia <sdharia@codeaurora.org>
Cc: David Kershner <david.kershner@unisys.com>
Cc: Johan Hovold <johan@kernel.org>
Cc: Uwe Kleine-Konig <u.kleine-koenig@pengutronix.de>
Cc: Viresh Kumar <viresh.kumar@linaro.org>
Cc: Randy Dunlap <rdunlap@infradead.org>
Cc: Cyrille Pitchen <cyrille.pitchen@free-electrons.com>
Cc: Juergen Gross <jgross@suse.com>
Cc: Alan Cox <alan@linux.intel.com>
Cc: Andrew Lunn <andrew@lunn.ch>
Cc: Andy Shevchenko <andriy.shevchenko@intel.com>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Fengguang Wu <fengguang.wu@intel.com>
Cc: Jason M Biils <jason.m.bills@linux.intel.com>
Cc: Julia Cartwright <juliac@eso.teric.us>
---
drivers/Kconfig | 2 +
drivers/Makefile | 1 +
drivers/peci/Kconfig | 12 +
drivers/peci/Makefile | 6 +
drivers/peci/peci-core.c | 1438 +++++++++++++++++++++++++++++++
include/linux/peci.h | 104 +++
include/uapi/linux/peci-ioctl.h | 265 ++++++
7 files changed, 1828 insertions(+)
create mode 100644 drivers/peci/Kconfig
create mode 100644 drivers/peci/Makefile
create mode 100644 drivers/peci/peci-core.c
create mode 100644 include/linux/peci.h
create mode 100644 include/uapi/linux/peci-ioctl.h
diff --git a/drivers/Kconfig b/drivers/Kconfig
index ab4d43923c4d..c633db2b41fb 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -219,4 +219,6 @@ source "drivers/siox/Kconfig"
source "drivers/slimbus/Kconfig"
+source "drivers/peci/Kconfig"
+
endmenu
diff --git a/drivers/Makefile b/drivers/Makefile
index cc9a7c5f7d2c..32e879ce3f8e 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -186,3 +186,4 @@ obj-$(CONFIG_MULTIPLEXER) += mux/
obj-$(CONFIG_UNISYS_VISORBUS) += visorbus/
obj-$(CONFIG_SIOX) += siox/
obj-$(CONFIG_GNSS) += gnss/
+obj-$(CONFIG_PECI) += peci/
diff --git a/drivers/peci/Kconfig b/drivers/peci/Kconfig
new file mode 100644
index 000000000000..4ccacb22a356
--- /dev/null
+++ b/drivers/peci/Kconfig
@@ -0,0 +1,12 @@
+#
+# Platform Environment Control Interface (PECI) subsystem configuration
+#
+
+config PECI
+ bool "PECI support"
+ select RT_MUTEXES
+ select CRC8
+ help
+ The Platform Environment Control Interface (PECI) is a one-wire bus
+ interface that provides a communication channel from Intel processors
+ and chipset components to external monitoring or control devices.
diff --git a/drivers/peci/Makefile b/drivers/peci/Makefile
new file mode 100644
index 000000000000..9e8615e0d3ff
--- /dev/null
+++ b/drivers/peci/Makefile
@@ -0,0 +1,6 @@
+#
+# Makefile for the PECI core and bus drivers.
+#
+
+# Core functionality
+obj-$(CONFIG_PECI) += peci-core.o
diff --git a/drivers/peci/peci-core.c b/drivers/peci/peci-core.c
new file mode 100644
index 000000000000..4aaf537cc9de
--- /dev/null
+++ b/drivers/peci/peci-core.c
@@ -0,0 +1,1438 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (c) 2018 Intel Corporation
+
+#include <linux/bitfield.h>
+#include <linux/crc8.h>
+#include <linux/delay.h>
+#include <linux/fs.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/peci.h>
+#include <linux/pm_domain.h>
+#include <linux/pm_runtime.h>
+#include <linux/slab.h>
+#include <linux/uaccess.h>
+
+/* Mask for getting minor revision number from DIB */
+#define MINOR_REV_NUM_MASK GENMASK(11, 8)
+
+/* CRC8 table for Assure Write Frame Check */
+#define PECI_CRC8_POLYNOMIAL 0x07
+DECLARE_CRC8_TABLE(peci_crc8_table);
+
+static struct device_type peci_adapter_type;
+static struct device_type peci_client_type;
+
+/* Max number of peci cdev */
+#define PECI_CDEV_MAX 16
+
+static dev_t peci_devt;
+static bool is_registered;
+
+static DEFINE_MUTEX(core_lock);
+static DEFINE_IDR(peci_adapter_idr);
+
+static struct peci_adapter *peci_get_adapter(int nr)
+{
+ struct peci_adapter *adapter;
+
+ mutex_lock(&core_lock);
+ adapter = idr_find(&peci_adapter_idr, nr);
+ if (!adapter)
+ goto out_unlock;
+
+ if (try_module_get(adapter->owner))
+ get_device(&adapter->dev);
+ else
+ adapter = NULL;
+
+out_unlock:
+ mutex_unlock(&core_lock);
+ return adapter;
+}
+
+static void peci_put_adapter(struct peci_adapter *adapter)
+{
+ if (!adapter)
+ return;
+
+ put_device(&adapter->dev);
+ module_put(adapter->owner);
+}
+
+static ssize_t name_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ return sprintf(buf, "%s\n", dev->type == &peci_client_type ?
+ to_peci_client(dev)->name : to_peci_adapter(dev)->name);
+}
+static DEVICE_ATTR_RO(name);
+
+static void peci_client_dev_release(struct device *dev)
+{
+ struct peci_client *client = to_peci_client(dev);
+
+ dev_dbg(dev, "%s: %s\n", __func__, client->name);
+ peci_put_adapter(client->adapter);
+ kfree(client);
+}
+
+static struct attribute *peci_device_attrs[] = {
+ &dev_attr_name.attr,
+ NULL
+};
+ATTRIBUTE_GROUPS(peci_device);
+
+static struct device_type peci_client_type = {
+ .groups = peci_device_groups,
+ .release = peci_client_dev_release,
+};
+
+struct peci_client *peci_verify_client(struct device *dev)
+{
+ return (dev->type == &peci_client_type)
+ ? to_peci_client(dev)
+ : NULL;
+}
+EXPORT_SYMBOL_GPL(peci_verify_client);
+
+static u8 peci_aw_fcs(u8 *data, int len)
+{
+ return crc8(peci_crc8_table, data, (size_t)len, 0);
+}
+
+static int __peci_xfer(struct peci_adapter *adapter, struct peci_xfer_msg *msg,
+ bool do_retry, bool has_aw_fcs)
+{
+ ktime_t start, end;
+ s64 elapsed_ms;
+ int rc = 0;
+
+ /**
+ * For some commands, the PECI originator may need to retry a command if
+ * the processor PECI client responds with a 0x8x completion code. In
+ * each instance, the processor PECI client may have started the
+ * operation but not completed it yet. When the 'retry' bit is set, the
+ * PECI client will ignore a new request if it exactly matches a
+ * previous valid request.
+ */
+
+ if (do_retry)
+ start = ktime_get();
+
+ do {
+ rc = adapter->xfer(adapter, msg);
+
+ if (!do_retry || rc)
+ break;
+
+ if (msg->rx_buf[0] == DEV_PECI_CC_SUCCESS)
+ break;
+
+ /* Retry is needed when completion code is 0x8x */
+ if ((msg->rx_buf[0] & DEV_PECI_CC_RETRY_CHECK_MASK) !=
+ DEV_PECI_CC_NEED_RETRY) {
+ rc = -EIO;
+ break;
+ }
+
+ /* Set the retry bit to indicate a retry attempt */
+ msg->tx_buf[1] |= DEV_PECI_RETRY_BIT;
+
+ /* Recalculate the AW FCS if it has one */
+ if (has_aw_fcs)
+ msg->tx_buf[msg->tx_len - 1] = 0x80 ^
+ peci_aw_fcs((u8 *)msg,
+ 2 + msg->tx_len);
+
+ /**
+ * Retry for at least 250ms before returning an error.
+ * Retry interval guideline:
+ * No minimum < Retry Interval < No maximum
+ * (recommend 10ms)
+ */
+ end = ktime_get();
+ elapsed_ms = ktime_to_ms(ktime_sub(end, start));
+ if (elapsed_ms >= DEV_PECI_RETRY_TIME_MS) {
+ dev_dbg(&adapter->dev, "Timeout retrying xfer!\n");
+ rc = -ETIMEDOUT;
+ break;
+ }
+
+ usleep_range((DEV_PECI_RETRY_INTERVAL_USEC >> 2) + 1,
+ DEV_PECI_RETRY_INTERVAL_USEC);
+ } while (true);
+
+ if (rc)
+ dev_dbg(&adapter->dev, "xfer error, rc: %d\n", rc);
+
+ return rc;
+}
+
+static int peci_xfer(struct peci_adapter *adapter, struct peci_xfer_msg *msg)
+{
+ return __peci_xfer(adapter, msg, false, false);
+}
+
+static int peci_xfer_with_retries(struct peci_adapter *adapter,
+ struct peci_xfer_msg *msg,
+ bool has_aw_fcs)
+{
+ return __peci_xfer(adapter, msg, true, has_aw_fcs);
+}
+
+static int peci_scan_cmd_mask(struct peci_adapter *adapter)
+{
+ struct peci_xfer_msg msg;
+ int rc = 0;
+ u32 dib;
+
+ /* Update command mask just once */
+ if (adapter->cmd_mask & BIT(PECI_CMD_XFER))
+ return 0;
+
+ msg.addr = PECI_BASE_ADDR;
+ msg.tx_len = GET_DIB_WR_LEN;
+ msg.rx_len = GET_DIB_RD_LEN;
+ msg.tx_buf[0] = GET_DIB_PECI_CMD;
+
+ rc = peci_xfer(adapter, &msg);
+ if (rc)
+ return rc;
+
+ dib = le32_to_cpup((__le32 *)msg.rx_buf);
+
+ /* Check special case for Get DIB command */
+ if (dib == 0x00) {
+ dev_dbg(&adapter->dev, "DIB read as 0x00\n");
+ return -EIO;
+ }
+
+ /**
+ * Setting up the supporting commands based on minor revision number.
+ * See PECI Spec Table 3-1.
+ */
+ switch (FIELD_GET(MINOR_REV_NUM_MASK, dib)) {
+ case 6:
+ adapter->cmd_mask |= BIT(PECI_CMD_WR_IA_MSR);
+ /* fallthrough */
+ case 5:
+ adapter->cmd_mask |= BIT(PECI_CMD_WR_PCI_CFG);
+ /* fallthrough */
+ case 4:
+ adapter->cmd_mask |= BIT(PECI_CMD_RD_PCI_CFG);
+ /* fallthrough */
+ case 3:
+ adapter->cmd_mask |= BIT(PECI_CMD_RD_PCI_CFG_LOCAL);
+ adapter->cmd_mask |= BIT(PECI_CMD_WR_PCI_CFG_LOCAL);
+ /* fallthrough */
+ case 2:
+ adapter->cmd_mask |= BIT(PECI_CMD_RD_IA_MSR);
+ /* fallthrough */
+ case 1:
+ adapter->cmd_mask |= BIT(PECI_CMD_RD_PKG_CFG);
+ adapter->cmd_mask |= BIT(PECI_CMD_WR_PKG_CFG);
+ }
+
+ adapter->cmd_mask |= BIT(PECI_CMD_XFER);
+ adapter->cmd_mask |= BIT(PECI_CMD_GET_TEMP);
+ adapter->cmd_mask |= BIT(PECI_CMD_GET_DIB);
+ adapter->cmd_mask |= BIT(PECI_CMD_PING);
+
+ return rc;
+}
+
+static int peci_cmd_support(struct peci_adapter *adapter, enum peci_cmd cmd)
+{
+ if (!(adapter->cmd_mask & BIT(PECI_CMD_PING)) &&
+ peci_scan_cmd_mask(adapter) < 0) {
+ dev_dbg(&adapter->dev, "Failed to scan command mask\n");
+ return -EIO;
+ }
+
+ if (!(adapter->cmd_mask & BIT(cmd))) {
+ dev_dbg(&adapter->dev, "Command %d is not supported\n", cmd);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int peci_ioctl_xfer(struct peci_adapter *adapter, void *vmsg)
+{
+ struct peci_xfer_msg *msg = vmsg;
+
+ return peci_xfer(adapter, msg);
+}
+
+static int peci_ioctl_ping(struct peci_adapter *adapter, void *vmsg)
+{
+ struct peci_ping_msg *umsg = vmsg;
+ struct peci_xfer_msg msg;
+
+ msg.addr = umsg->addr;
+ msg.tx_len = 0;
+ msg.rx_len = 0;
+
+ return peci_xfer(adapter, &msg);
+}
+
+static int peci_ioctl_get_dib(struct peci_adapter *adapter, void *vmsg)
+{
+ struct peci_get_dib_msg *umsg = vmsg;
+ struct peci_xfer_msg msg;
+ int rc;
+
+ msg.addr = umsg->addr;
+ msg.tx_len = GET_DIB_WR_LEN;
+ msg.rx_len = GET_DIB_RD_LEN;
+ msg.tx_buf[0] = GET_DIB_PECI_CMD;
+
+ rc = peci_xfer(adapter, &msg);
+ if (rc)
+ return rc;
+
+ umsg->dib = le32_to_cpup((__le32 *)msg.rx_buf);
+
+ return 0;
+}
+
+static int peci_ioctl_get_temp(struct peci_adapter *adapter, void *vmsg)
+{
+ struct peci_get_temp_msg *umsg = vmsg;
+ struct peci_xfer_msg msg;
+ int rc;
+
+ msg.addr = umsg->addr;
+ msg.tx_len = GET_TEMP_WR_LEN;
+ msg.rx_len = GET_TEMP_RD_LEN;
+ msg.tx_buf[0] = GET_TEMP_PECI_CMD;
+
+ rc = peci_xfer(adapter, &msg);
+ if (rc)
+ return rc;
+
+ umsg->temp_raw = le16_to_cpup((__le16 *)msg.rx_buf);
+
+ return 0;
+}
+
+static int peci_ioctl_rd_pkg_cfg(struct peci_adapter *adapter, void *vmsg)
+{
+ struct peci_rd_pkg_cfg_msg *umsg = vmsg;
+ struct peci_xfer_msg msg;
+ int rc = 0;
+
+ /* Per the PECI spec, the read length must be a byte, word, or dword */
+ if (umsg->rx_len != 1 && umsg->rx_len != 2 && umsg->rx_len != 4) {
+ dev_dbg(&adapter->dev, "Invalid read length, rx_len: %d\n",
+ umsg->rx_len);
+ return -EINVAL;
+ }
+
+ msg.addr = umsg->addr;
+ msg.tx_len = RDPKGCFG_WRITE_LEN;
+ /* read lengths of 1 and 2 result in an error, so only use 4 for now */
+ msg.rx_len = RDPKGCFG_READ_LEN_BASE + umsg->rx_len;
+ msg.tx_buf[0] = RDPKGCFG_PECI_CMD;
+ msg.tx_buf[1] = 0x00; /* request byte for Host ID | Retry bit */
+ /* Host ID is 0 for PECI 3.0 */
+ msg.tx_buf[2] = umsg->index; /* RdPkgConfig index */
+ msg.tx_buf[3] = (u8)umsg->param; /* LSB - Config parameter */
+ msg.tx_buf[4] = (u8)(umsg->param >> 8); /* MSB - Config parameter */
+
+ rc = peci_xfer_with_retries(adapter, &msg, false);
+ if (!rc)
+ memcpy(umsg->pkg_config, &msg.rx_buf[1], umsg->rx_len);
+
+ return rc;
+}
+
+static int peci_ioctl_wr_pkg_cfg(struct peci_adapter *adapter, void *vmsg)
+{
+ struct peci_wr_pkg_cfg_msg *umsg = vmsg;
+ struct peci_xfer_msg msg;
+ int rc = 0, i;
+
+ /* Per the PECI spec, the write length must be a dword */
+ if (umsg->tx_len != 4) {
+ dev_dbg(&adapter->dev, "Invalid write length, tx_len: %d\n",
+ umsg->tx_len);
+ return -EINVAL;
+ }
+
+ msg.addr = umsg->addr;
+ msg.tx_len = WRPKGCFG_WRITE_LEN_BASE + umsg->tx_len;
+ /* read lengths of 1 and 2 result in an error, so only use 4 for now */
+ msg.rx_len = WRPKGCFG_READ_LEN;
+ msg.tx_buf[0] = WRPKGCFG_PECI_CMD;
+ msg.tx_buf[1] = 0x00; /* request byte for Host ID | Retry bit */
+ /* Host ID is 0 for PECI 3.0 */
+ msg.tx_buf[2] = umsg->index; /* RdPkgConfig index */
+ msg.tx_buf[3] = (u8)umsg->param; /* LSB - Config parameter */
+ msg.tx_buf[4] = (u8)(umsg->param >> 8); /* MSB - Config parameter */
+ for (i = 0; i < umsg->tx_len; i++)
+ msg.tx_buf[5 + i] = (u8)(umsg->value >> (i << 3));
+
+ /* Add an Assure Write Frame Check Sequence byte */
+ msg.tx_buf[5 + i] = 0x80 ^
+ peci_aw_fcs((u8 *)&msg, 8 + umsg->tx_len);
+
+ rc = peci_xfer_with_retries(adapter, &msg, true);
+
+ return rc;
+}
+
+static int peci_ioctl_rd_ia_msr(struct peci_adapter *adapter, void *vmsg)
+{
+ struct peci_rd_ia_msr_msg *umsg = vmsg;
+ struct peci_xfer_msg msg;
+ int rc = 0;
+
+ msg.addr = umsg->addr;
+ msg.tx_len = RDIAMSR_WRITE_LEN;
+ msg.rx_len = RDIAMSR_READ_LEN;
+ msg.tx_buf[0] = RDIAMSR_PECI_CMD;
+ msg.tx_buf[1] = 0x00;
+ msg.tx_buf[2] = umsg->thread_id;
+ msg.tx_buf[3] = (u8)umsg->address;
+ msg.tx_buf[4] = (u8)(umsg->address >> 8);
+
+ rc = peci_xfer_with_retries(adapter, &msg, false);
+ if (!rc)
+ memcpy(&umsg->value, &msg.rx_buf[1], sizeof(uint64_t));
+
+ return rc;
+}
+
+static int peci_ioctl_rd_pci_cfg(struct peci_adapter *adapter, void *vmsg)
+{
+ struct peci_rd_pci_cfg_msg *umsg = vmsg;
+ struct peci_xfer_msg msg;
+ u32 address;
+ int rc = 0;
+
+ address = umsg->reg; /* [11:0] - Register */
+ address |= (u32)umsg->function << 12; /* [14:12] - Function */
+ address |= (u32)umsg->device << 15; /* [19:15] - Device */
+ address |= (u32)umsg->bus << 20; /* [27:20] - Bus */
+ /* [31:28] - Reserved */
+ msg.addr = umsg->addr;
+ msg.tx_len = RDPCICFG_WRITE_LEN;
+ msg.rx_len = RDPCICFG_READ_LEN;
+ msg.tx_buf[0] = RDPCICFG_PECI_CMD;
+ msg.tx_buf[1] = 0x00; /* request byte for Host ID | Retry bit */
+ /* Host ID is 0 for PECI 3.0 */
+ msg.tx_buf[2] = (u8)address; /* LSB - PCI Config Address */
+ msg.tx_buf[3] = (u8)(address >> 8); /* PCI Config Address */
+ msg.tx_buf[4] = (u8)(address >> 16); /* PCI Config Address */
+ msg.tx_buf[5] = (u8)(address >> 24); /* MSB - PCI Config Address */
+
+ rc = peci_xfer_with_retries(adapter, &msg, false);
+ if (!rc)
+ memcpy(umsg->pci_config, &msg.rx_buf[1], 4);
+
+ return rc;
+}
+
+static int peci_ioctl_rd_pci_cfg_local(struct peci_adapter *adapter, void *vmsg)
+{
+ struct peci_rd_pci_cfg_local_msg *umsg = vmsg;
+ struct peci_xfer_msg msg;
+ u32 address;
+ int rc = 0;
+
+ /* Per the PECI spec, the read length must be a byte, word, or dword */
+ if (umsg->rx_len != 1 && umsg->rx_len != 2 && umsg->rx_len != 4) {
+ dev_dbg(&adapter->dev, "Invalid read length, rx_len: %d\n",
+ umsg->rx_len);
+ return -EINVAL;
+ }
+
+ address = umsg->reg; /* [11:0] - Register */
+ address |= (u32)umsg->function << 12; /* [14:12] - Function */
+ address |= (u32)umsg->device << 15; /* [19:15] - Device */
+ address |= (u32)umsg->bus << 20; /* [23:20] - Bus */
+
+ msg.addr = umsg->addr;
+ msg.tx_len = RDPCICFGLOCAL_WRITE_LEN;
+ msg.rx_len = RDPCICFGLOCAL_READ_LEN_BASE + umsg->rx_len;
+ msg.tx_buf[0] = RDPCICFGLOCAL_PECI_CMD;
+ msg.tx_buf[1] = 0x00; /* request byte for Host ID | Retry bit */
+ /* Host ID is 0 for PECI 3.0 */
+ msg.tx_buf[2] = (u8)address; /* LSB - PCI Configuration Address */
+ msg.tx_buf[3] = (u8)(address >> 8); /* PCI Configuration Address */
+ msg.tx_buf[4] = (u8)(address >> 16); /* PCI Configuration Address */
+
+ rc = peci_xfer_with_retries(adapter, &msg, false);
+ if (!rc)
+ memcpy(umsg->pci_config, &msg.rx_buf[1], umsg->rx_len);
+
+ return rc;
+}
+
+static int peci_ioctl_wr_pci_cfg_local(struct peci_adapter *adapter, void *vmsg)
+{
+ struct peci_wr_pci_cfg_local_msg *umsg = vmsg;
+ struct peci_xfer_msg msg;
+ int rc = 0, i;
+ u32 address;
+
+ /* Per the PECI spec, the write length must be a byte, word, or dword */
+ if (umsg->tx_len != 1 && umsg->tx_len != 2 && umsg->tx_len != 4) {
+ dev_dbg(&adapter->dev, "Invalid write length, tx_len: %d\n",
+ umsg->tx_len);
+ return -EINVAL;
+ }
+
+ address = umsg->reg; /* [11:0] - Register */
+ address |= (u32)umsg->function << 12; /* [14:12] - Function */
+ address |= (u32)umsg->device << 15; /* [19:15] - Device */
+ address |= (u32)umsg->bus << 20; /* [23:20] - Bus */
+
+ msg.addr = umsg->addr;
+ msg.tx_len = WRPCICFGLOCAL_WRITE_LEN_BASE + umsg->tx_len;
+ msg.rx_len = WRPCICFGLOCAL_READ_LEN;
+ msg.tx_buf[0] = WRPCICFGLOCAL_PECI_CMD;
+ msg.tx_buf[1] = 0x00; /* request byte for Host ID | Retry bit */
+ /* Host ID is 0 for PECI 3.0 */
+ msg.tx_buf[2] = (u8)address; /* LSB - PCI Configuration Address */
+ msg.tx_buf[3] = (u8)(address >> 8); /* PCI Configuration Address */
+ msg.tx_buf[4] = (u8)(address >> 16); /* PCI Configuration Address */
+ for (i = 0; i < umsg->tx_len; i++)
+ msg.tx_buf[5 + i] = (u8)(umsg->value >> (i << 3));
+
+ /* Add an Assure Write Frame Check Sequence byte */
+ msg.tx_buf[5 + i] = 0x80 ^
+ peci_aw_fcs((u8 *)&msg, 8 + umsg->tx_len);
+
+ rc = peci_xfer_with_retries(adapter, &msg, true);
+
+ return rc;
+}
+
+typedef int (*peci_ioctl_fn_type)(struct peci_adapter *, void *);
+
+static const peci_ioctl_fn_type peci_ioctl_fn[PECI_CMD_MAX] = {
+ peci_ioctl_xfer,
+ peci_ioctl_ping,
+ peci_ioctl_get_dib,
+ peci_ioctl_get_temp,
+ peci_ioctl_rd_pkg_cfg,
+ peci_ioctl_wr_pkg_cfg,
+ peci_ioctl_rd_ia_msr,
+ NULL, /* Reserved */
+ peci_ioctl_rd_pci_cfg,
+ NULL, /* Reserved */
+ peci_ioctl_rd_pci_cfg_local,
+ peci_ioctl_wr_pci_cfg_local,
+};
+
+int peci_command(struct peci_adapter *adapter, enum peci_cmd cmd, void *vmsg)
+{
+ int rc = 0;
+
+ if (cmd >= PECI_CMD_MAX || cmd < PECI_CMD_XFER)
+ return -EINVAL;
+
+ dev_dbg(&adapter->dev, "%s, cmd=0x%02x\n", __func__, cmd);
+
+ if (!peci_ioctl_fn[cmd])
+ return -EINVAL;
+
+ rt_mutex_lock(&adapter->bus_lock);
+
+ rc = peci_cmd_support(adapter, cmd);
+ if (!rc)
+ rc = peci_ioctl_fn[cmd](adapter, vmsg);
+
+ rt_mutex_unlock(&adapter->bus_lock);
+
+ return rc;
+}
+EXPORT_SYMBOL_GPL(peci_command);
+
+static long peci_ioctl(struct file *file, unsigned int iocmd, unsigned long arg)
+{
+ struct peci_adapter *adapter = file->private_data;
+ void __user *argp = (void __user *)arg;
+ unsigned int msg_len;
+ enum peci_cmd cmd;
+ int rc = 0;
+ u8 *msg;
+
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+
+ dev_dbg(&adapter->dev, "ioctl, cmd=0x%x, arg=0x%lx\n", iocmd, arg);
+
+ switch (iocmd) {
+ case PECI_IOC_XFER:
+ case PECI_IOC_PING:
+ case PECI_IOC_GET_DIB:
+ case PECI_IOC_GET_TEMP:
+ case PECI_IOC_RD_PKG_CFG:
+ case PECI_IOC_WR_PKG_CFG:
+ case PECI_IOC_RD_IA_MSR:
+ case PECI_IOC_RD_PCI_CFG:
+ case PECI_IOC_RD_PCI_CFG_LOCAL:
+ case PECI_IOC_WR_PCI_CFG_LOCAL:
+ cmd = _IOC_NR(iocmd);
+ msg_len = _IOC_SIZE(iocmd);
+ break;
+
+ default:
+ dev_dbg(&adapter->dev, "Invalid ioctl cmd : 0x%x\n", iocmd);
+ return -ENOTTY;
+ }
+
+ msg = memdup_user(argp, msg_len);
+ if (IS_ERR(msg))
+ return PTR_ERR(msg);
+
+ rc = peci_command(adapter, cmd, msg);
+
+ if (!rc && copy_to_user(argp, msg, msg_len))
+ rc = -EFAULT;
+
+ kfree(msg);
+ return (long)rc;
+}
+
+static int peci_open(struct inode *inode, struct file *file)
+{
+ unsigned int minor = iminor(inode);
+ struct peci_adapter *adapter;
+
+ adapter = peci_get_adapter(minor);
+ if (!adapter)
+ return -ENODEV;
+
+ file->private_data = adapter;
+
+ return 0;
+}
+
+static int peci_release(struct inode *inode, struct file *file)
+{
+ struct peci_adapter *adapter = file->private_data;
+
+ peci_put_adapter(adapter);
+ file->private_data = NULL;
+
+ return 0;
+}
+
+static const struct file_operations peci_fops = {
+ .owner = THIS_MODULE,
+ .unlocked_ioctl = peci_ioctl,
+ .open = peci_open,
+ .release = peci_release,
+};
+
+static int peci_detect(struct peci_adapter *adapter, u8 addr)
+{
+ struct peci_ping_msg msg;
+
+ msg.addr = addr;
+
+ return peci_command(adapter, PECI_CMD_PING, &msg);
+}
+
+static const struct of_device_id *
+peci_of_match_device(const struct of_device_id *matches,
+ struct peci_client *client)
+{
+#if IS_ENABLED(CONFIG_OF)
+ if (!(client && matches))
+ return NULL;
+
+ return of_match_device(matches, &client->dev);
+#else
+ return NULL;
+#endif
+}
+
+static const struct peci_device_id *
+peci_match_id(const struct peci_device_id *id, struct peci_client *client)
+{
+ if (!(id && client))
+ return NULL;
+
+ while (id->name[0]) {
+ if (!strncmp(client->name, id->name, PECI_NAME_SIZE))
+ return id;
+ id++;
+ }
+
+ return NULL;
+}
+
+static int peci_device_match(struct device *dev, struct device_driver *drv)
+{
+ struct peci_client *client = peci_verify_client(dev);
+ struct peci_driver *driver;
+
+ /* Attempt an OF style match */
+ if (peci_of_match_device(drv->of_match_table, client))
+ return 1;
+
+ driver = to_peci_driver(drv);
+
+ /* Finally an ID match */
+ if (peci_match_id(driver->id_table, client))
+ return 1;
+
+ return 0;
+}
+
+static int peci_device_probe(struct device *dev)
+{
+ struct peci_client *client = peci_verify_client(dev);
+ struct peci_driver *driver;
+ int status = -EINVAL;
+
+ if (!client)
+ return 0;
+
+ driver = to_peci_driver(dev->driver);
+
+ if (!driver->id_table &&
+ !peci_of_match_device(dev->driver->of_match_table, client))
+ return -ENODEV;
+
+ dev_dbg(dev, "%s: name:%s\n", __func__, client->name);
+
+ status = dev_pm_domain_attach(&client->dev, true);
+ if (status == -EPROBE_DEFER)
+ return status;
+
+ if (driver->probe)
+ status = driver->probe(client);
+ else
+ status = -EINVAL;
+
+ if (status)
+ goto err_detach_pm_domain;
+
+ return 0;
+
+err_detach_pm_domain:
+ dev_pm_domain_detach(&client->dev, true);
+ return status;
+}
+
+static int peci_device_remove(struct device *dev)
+{
+ struct peci_client *client = peci_verify_client(dev);
+ struct peci_driver *driver;
+ int status = 0;
+
+ if (!client || !dev->driver)
+ return 0;
+
+ driver = to_peci_driver(dev->driver);
+ if (driver->remove) {
+ dev_dbg(dev, "%s: name:%s\n", __func__, client->name);
+ status = driver->remove(client);
+ }
+
+ dev_pm_domain_detach(&client->dev, true);
+
+ return status;
+}
+
+static void peci_device_shutdown(struct device *dev)
+{
+ struct peci_client *client = peci_verify_client(dev);
+ struct peci_driver *driver;
+
+ if (!client || !dev->driver)
+ return;
+
+ dev_dbg(dev, "%s: name:%s\n", __func__, client->name);
+
+ driver = to_peci_driver(dev->driver);
+ if (driver->shutdown)
+ driver->shutdown(client);
+}
+
+static struct bus_type peci_bus_type = {
+ .name = "peci",
+ .match = peci_device_match,
+ .probe = peci_device_probe,
+ .remove = peci_device_remove,
+ .shutdown = peci_device_shutdown,
+};
+
+static int peci_check_addr_validity(u8 addr)
+{
+ if (addr < PECI_BASE_ADDR && addr > PECI_BASE_ADDR + PECI_OFFSET_MAX)
+ return -EINVAL;
+
+ return 0;
+}
+
+static int peci_check_client_busy(struct device *dev, void *client_new_p)
+{
+ struct peci_client *client = peci_verify_client(dev);
+ struct peci_client *client_new = client_new_p;
+
+ if (client && client->addr == client_new->addr)
+ return -EBUSY;
+
+ return 0;
+}
+
+int peci_get_cpu_id(struct peci_adapter *adapter, u8 addr, u32 *cpu_id)
+{
+ struct peci_rd_pkg_cfg_msg msg;
+ int rc;
+
+ msg.addr = addr;
+ msg.index = MBX_INDEX_CPU_ID;
+ msg.param = PKG_ID_CPU_ID;
+ msg.rx_len = 4;
+
+ rc = peci_command(adapter, PECI_CMD_RD_PKG_CFG, &msg);
+ if (!rc)
+ *cpu_id = le32_to_cpup((__le32 *)msg.pkg_config);
+
+ return rc;
+}
+EXPORT_SYMBOL_GPL(peci_get_cpu_id);
+
+static struct peci_client *peci_new_device(struct peci_adapter *adapter,
+ struct peci_board_info const *info)
+{
+ struct peci_client *client;
+ int rc;
+
+ /* Increase reference count for the adapter assigned */
+ if (!peci_get_adapter(adapter->nr))
+ return NULL;
+
+ client = kzalloc(sizeof(*client), GFP_KERNEL);
+ if (!client)
+ goto err_put_adapter;
+
+ client->adapter = adapter;
+ client->addr = info->addr;
+ strlcpy(client->name, info->type, sizeof(client->name));
+
+ rc = peci_check_addr_validity(client->addr);
+ if (rc) {
+ dev_err(&adapter->dev, "Invalid PECI CPU address 0x%02hx\n",
+ client->addr);
+ goto err_free_client_silent;
+ }
+
+ /* Check online status of client */
+ rc = peci_detect(adapter, client->addr);
+ if (rc)
+ goto err_free_client;
+
+ rc = device_for_each_child(&adapter->dev, client,
+ peci_check_client_busy);
+ if (rc)
+ goto err_free_client;
+
+ client->dev.parent = &client->adapter->dev;
+ client->dev.bus = &peci_bus_type;
+ client->dev.type = &peci_client_type;
+ client->dev.of_node = info->of_node;
+ dev_set_name(&client->dev, "%d-%02x", adapter->nr, client->addr);
+
+ rc = device_register(&client->dev);
+ if (rc)
+ goto err_free_client;
+
+ dev_dbg(&adapter->dev, "client [%s] registered with bus id %s\n",
+ client->name, dev_name(&client->dev));
+
+ return client;
+
+err_free_client:
+ dev_err(&adapter->dev,
+ "Failed to register peci client %s at 0x%02x (%d)\n",
+ client->name, client->addr, rc);
+err_free_client_silent:
+ kfree(client);
+err_put_adapter:
+ peci_put_adapter(adapter);
+ return NULL;
+}
+
+static void peci_unregister_device(struct peci_client *client)
+{
+ if (client->dev.of_node)
+ of_node_clear_flag(client->dev.of_node, OF_POPULATED);
+
+ device_unregister(&client->dev);
+}
+
+static int peci_unregister_client(struct device *dev, void *dummy)
+{
+ struct peci_client *client = peci_verify_client(dev);
+
+ if (client)
+ peci_unregister_device(client);
+
+ return 0;
+}
+
+static void peci_adapter_dev_release(struct device *dev)
+{
+ struct peci_adapter *adapter = to_peci_adapter(dev);
+
+ dev_dbg(dev, "%s: %s\n", __func__, adapter->name);
+ mutex_destroy(&adapter->userspace_clients_lock);
+ rt_mutex_destroy(&adapter->bus_lock);
+ kfree(adapter);
+}
+
+static ssize_t peci_sysfs_new_device(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct peci_adapter *adapter = to_peci_adapter(dev);
+ struct peci_board_info info = {};
+ struct peci_client *client;
+ char *blank, end;
+ int rc;
+
+ /* Parse device type */
+ blank = strchr(buf, ' ');
+ if (!blank) {
+ dev_err(dev, "%s: Missing parameters\n", "new_device");
+ return -EINVAL;
+ }
+ if (blank - buf > PECI_NAME_SIZE - 1) {
+ dev_err(dev, "%s: Invalid device type\n", "new_device");
+ return -EINVAL;
+ }
+ memcpy(info.type, buf, blank - buf);
+
+ /* Parse remaining parameters, reject extra parameters */
+ rc = sscanf(++blank, "%hi%c", &info.addr, &end);
+ if (rc < 1) {
+ dev_err(dev, "%s: Can't parse client address\n", "new_device");
+ return -EINVAL;
+ }
+ if (rc > 1 && end != '\n') {
+ dev_err(dev, "%s: Extra parameters\n", "new_device");
+ return -EINVAL;
+ }
+
+ client = peci_new_device(adapter, &info);
+ if (!client)
+ return -EINVAL;
+
+ /* Keep track of the added device */
+ mutex_lock(&adapter->userspace_clients_lock);
+ list_add_tail(&client->detected, &adapter->userspace_clients);
+ mutex_unlock(&adapter->userspace_clients_lock);
+ dev_info(dev, "%s: Instantiated device %s at 0x%02hx\n", "new_device",
+ info.type, info.addr);
+
+ return count;
+}
+static DEVICE_ATTR(new_device, 0200, NULL, peci_sysfs_new_device);
+
+static ssize_t peci_sysfs_delete_device(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct peci_adapter *adapter = to_peci_adapter(dev);
+ struct peci_client *client, *next;
+ struct peci_board_info info = {};
+ struct peci_driver *driver;
+ char *blank, end;
+ int rc;
+
+ /* Parse device type */
+ blank = strchr(buf, ' ');
+ if (!blank) {
+ dev_err(dev, "%s: Missing parameters\n", "delete_device");
+ return -EINVAL;
+ }
+ if (blank - buf > PECI_NAME_SIZE - 1) {
+ dev_err(dev, "%s: Invalid device type\n", "delete_device");
+ return -EINVAL;
+ }
+ memcpy(info.type, buf, blank - buf);
+
+ /* Parse remaining parameters, reject extra parameters */
+ rc = sscanf(++blank, "%hi%c", &info.addr, &end);
+ if (rc < 1) {
+ dev_err(dev, "%s: Can't parse client address\n",
+ "delete_device");
+ return -EINVAL;
+ }
+ if (rc > 1 && end != '\n') {
+ dev_err(dev, "%s: Extra parameters\n", "delete_device");
+ return -EINVAL;
+ }
+
+ /* Make sure the device was added through sysfs */
+ rc = -ENOENT;
+ mutex_lock(&adapter->userspace_clients_lock);
+ list_for_each_entry_safe(client, next, &adapter->userspace_clients,
+ detected) {
+ driver = to_peci_driver(client->dev.driver);
+
+ if (client->addr == info.addr &&
+ !strncmp(client->name, info.type, PECI_NAME_SIZE)) {
+ dev_info(dev, "%s: Deleting device %s at 0x%02hx\n",
+ "delete_device", client->name, client->addr);
+ list_del(&client->detected);
+ peci_unregister_device(client);
+ rc = count;
+ break;
+ }
+ }
+ mutex_unlock(&adapter->userspace_clients_lock);
+
+ if (rc < 0)
+ dev_err(dev, "%s: Can't find device in list\n",
+ "delete_device");
+
+ return rc;
+}
+static DEVICE_ATTR_IGNORE_LOCKDEP(delete_device, 0200, NULL,
+ peci_sysfs_delete_device);
+
+static struct attribute *peci_adapter_attrs[] = {
+ &dev_attr_name.attr,
+ &dev_attr_new_device.attr,
+ &dev_attr_delete_device.attr,
+ NULL
+};
+ATTRIBUTE_GROUPS(peci_adapter);
+
+static struct device_type peci_adapter_type = {
+ .groups = peci_adapter_groups,
+ .release = peci_adapter_dev_release,
+};
+
+struct peci_adapter *peci_verify_adapter(struct device *dev)
+{
+ return (dev->type == &peci_adapter_type)
+ ? to_peci_adapter(dev)
+ : NULL;
+}
+EXPORT_SYMBOL_GPL(peci_verify_adapter);
+
+#if IS_ENABLED(CONFIG_OF)
+static struct peci_client *peci_of_register_device(struct peci_adapter *adapter,
+ struct device_node *node)
+{
+ struct peci_board_info info = {};
+ struct peci_client *result;
+ const __be32 *addr_be;
+ int len;
+
+ dev_dbg(&adapter->dev, "register %s\n", node->full_name);
+
+ if (of_modalias_node(node, info.type, sizeof(info.type)) < 0) {
+ dev_err(&adapter->dev, "modalias failure on %s\n",
+ node->full_name);
+ return ERR_PTR(-EINVAL);
+ }
+
+ addr_be = of_get_property(node, "reg", &len);
+ if (!addr_be || len < sizeof(*addr_be)) {
+ dev_err(&adapter->dev, "invalid reg on %s\n",
+ node->full_name);
+ return ERR_PTR(-EINVAL);
+ }
+
+ info.addr = be32_to_cpup(addr_be);
+ info.of_node = of_node_get(node);
+
+ result = peci_new_device(adapter, &info);
+ if (!result)
+ result = ERR_PTR(-EINVAL);
+
+ of_node_put(node);
+ return result;
+}
+
+static void peci_of_register_devices(struct peci_adapter *adapter)
+{
+ struct device_node *bus, *node;
+ struct peci_client *client;
+
+ /* Only register child devices if the adapter has a node pointer set */
+ if (!adapter->dev.of_node)
+ return;
+
+ bus = of_get_child_by_name(adapter->dev.of_node, "peci-bus");
+ if (!bus)
+ bus = of_node_get(adapter->dev.of_node);
+
+ for_each_available_child_of_node(bus, node) {
+ if (of_node_test_and_set_flag(node, OF_POPULATED))
+ continue;
+
+ client = peci_of_register_device(adapter, node);
+ if (IS_ERR(client)) {
+ dev_warn(&adapter->dev,
+ "Failed to create PECI device for %s\n",
+ node->full_name);
+ of_node_clear_flag(node, OF_POPULATED);
+ }
+ }
+
+ of_node_put(bus);
+}
+#else
+static void peci_of_register_devices(struct peci_adapter *adapter) { }
+#endif /* CONFIG_OF */
+
+#if IS_ENABLED(CONFIG_OF_DYNAMIC)
+static int peci_of_match_node(struct device *dev, void *data)
+{
+ return dev->of_node == data;
+}
+
+/* must call put_device() when done with returned peci_client device */
+static struct peci_client *peci_of_find_device(struct device_node *node)
+{
+ struct peci_client *client;
+ struct device *dev;
+
+ dev = bus_find_device(&peci_bus_type, NULL, node, peci_of_match_node);
+ if (!dev)
+ return NULL;
+
+ client = peci_verify_client(dev);
+ if (!client)
+ put_device(dev);
+
+ return client;
+}
+
+/* must call put_device() when done with returned peci_adapter device */
+static struct peci_adapter *peci_of_find_adapter(struct device_node *node)
+{
+ struct peci_adapter *adapter;
+ struct device *dev;
+
+ dev = bus_find_device(&peci_bus_type, NULL, node, peci_of_match_node);
+ if (!dev)
+ return NULL;
+
+ adapter = peci_verify_adapter(dev);
+ if (!adapter)
+ put_device(dev);
+
+ return adapter;
+}
+
+static int peci_of_notify(struct notifier_block *nb,
+ unsigned long action,
+ void *arg)
+{
+ struct of_reconfig_data *rd = arg;
+ struct peci_adapter *adapter;
+ struct peci_client *client;
+
+ switch (of_reconfig_get_state_change(action, rd)) {
+ case OF_RECONFIG_CHANGE_ADD:
+ adapter = peci_of_find_adapter(rd->dn->parent);
+ if (!adapter)
+ return NOTIFY_OK; /* not for us */
+
+ if (of_node_test_and_set_flag(rd->dn, OF_POPULATED)) {
+ put_device(&adapter->dev);
+ return NOTIFY_OK;
+ }
+
+ client = peci_of_register_device(adapter, rd->dn);
+ put_device(&adapter->dev);
+
+ if (IS_ERR(client)) {
+ dev_err(&adapter->dev,
+ "failed to create client for '%s'\n",
+ rd->dn->full_name);
+ of_node_clear_flag(rd->dn, OF_POPULATED);
+ return notifier_from_errno(PTR_ERR(client));
+ }
+ break;
+ case OF_RECONFIG_CHANGE_REMOVE:
+ /* already depopulated? */
+ if (!of_node_check_flag(rd->dn, OF_POPULATED))
+ return NOTIFY_OK;
+
+ /* find our device by node */
+ client = peci_of_find_device(rd->dn);
+ if (!client)
+ return NOTIFY_OK; /* no? not meant for us */
+
+ /* unregister takes one ref away */
+ peci_unregister_device(client);
+
+ /* and put the reference of the find */
+ put_device(&client->dev);
+ break;
+ }
+
+ return NOTIFY_OK;
+}
+
+static struct notifier_block peci_of_notifier = {
+ .notifier_call = peci_of_notify,
+};
+#else
+extern struct notifier_block peci_of_notifier;
+#endif /* CONFIG_OF_DYNAMIC */
+
+struct peci_adapter *peci_alloc_adapter(struct device *dev, unsigned int size)
+{
+ struct peci_adapter *adapter;
+
+ if (!dev)
+ return NULL;
+
+ adapter = kzalloc(size + sizeof(*adapter), GFP_KERNEL);
+ if (!adapter)
+ return NULL;
+
+ device_initialize(&adapter->dev);
+ adapter->dev.parent = dev;
+ adapter->dev.bus = &peci_bus_type;
+ adapter->dev.type = &peci_adapter_type;
+ peci_set_adapdata(adapter, &adapter[1]);
+
+ return adapter;
+}
+EXPORT_SYMBOL_GPL(peci_alloc_adapter);
+
+static int peci_register_adapter(struct peci_adapter *adapter)
+{
+ int rc = -EINVAL;
+
+ /* Can't register until after driver model init */
+ if (WARN_ON(!is_registered))
+ goto err_free_idr;
+
+ if (WARN(!adapter->name[0], "peci adapter has no name"))
+ goto err_free_idr;
+
+ if (WARN(!adapter->xfer, "peci adapter has no xfer function\n"))
+ goto err_free_idr;
+
+ rt_mutex_init(&adapter->bus_lock);
+ mutex_init(&adapter->userspace_clients_lock);
+ INIT_LIST_HEAD(&adapter->userspace_clients);
+
+ dev_set_name(&adapter->dev, "peci%d", adapter->nr);
+
+ /* cdev */
+ cdev_init(&adapter->cdev, &peci_fops);
+ adapter->cdev.owner = THIS_MODULE;
+ adapter->dev.devt = MKDEV(MAJOR(peci_devt), adapter->nr);
+ rc = cdev_add(&adapter->cdev, adapter->dev.devt, 1);
+ if (rc) {
+ pr_err("adapter '%s': can't add cdev (%d)\n",
+ adapter->name, rc);
+ goto err_free_idr;
+ }
+ rc = device_add(&adapter->dev);
+ if (rc) {
+ pr_err("adapter '%s': can't add device (%d)\n",
+ adapter->name, rc);
+ goto err_del_cdev;
+ }
+
+ dev_dbg(&adapter->dev, "adapter [%s] registered\n", adapter->name);
+
+ pm_runtime_no_callbacks(&adapter->dev);
+ pm_suspend_ignore_children(&adapter->dev, true);
+ pm_runtime_enable(&adapter->dev);
+
+ /* create pre-declared device nodes */
+ peci_of_register_devices(adapter);
+
+ return 0;
+
+err_del_cdev:
+ cdev_del(&adapter->cdev);
+err_free_idr:
+ mutex_lock(&core_lock);
+ idr_remove(&peci_adapter_idr, adapter->nr);
+ mutex_unlock(&core_lock);
+ return rc;
+}
+
+static int peci_add_numbered_adapter(struct peci_adapter *adapter)
+{
+ int id;
+
+ mutex_lock(&core_lock);
+ id = idr_alloc(&peci_adapter_idr, adapter,
+ adapter->nr, adapter->nr + 1, GFP_KERNEL);
+ mutex_unlock(&core_lock);
+ if (WARN(id < 0, "couldn't get idr"))
+ return id == -ENOSPC ? -EBUSY : id;
+
+ return peci_register_adapter(adapter);
+}
+
+int peci_add_adapter(struct peci_adapter *adapter)
+{
+ struct device *dev = &adapter->dev;
+ int id;
+
+ if (dev->of_node) {
+ id = of_alias_get_id(dev->of_node, "peci");
+ if (id >= 0) {
+ adapter->nr = id;
+ return peci_add_numbered_adapter(adapter);
+ }
+ }
+
+ mutex_lock(&core_lock);
+ id = idr_alloc(&peci_adapter_idr, adapter, 0, 0, GFP_KERNEL);
+ mutex_unlock(&core_lock);
+ if (WARN(id < 0, "couldn't get idr"))
+ return id;
+
+ adapter->nr = id;
+
+ return peci_register_adapter(adapter);
+}
+EXPORT_SYMBOL_GPL(peci_add_adapter);
+
+void peci_del_adapter(struct peci_adapter *adapter)
+{
+ struct peci_client *client, *next;
+ struct peci_adapter *found;
+ int nr;
+
+ /* First make sure that this adapter was ever added */
+ mutex_lock(&core_lock);
+ found = idr_find(&peci_adapter_idr, adapter->nr);
+ mutex_unlock(&core_lock);
+
+ if (found != adapter)
+ return;
+
+ /* Remove devices instantiated from sysfs */
+ mutex_lock(&adapter->userspace_clients_lock);
+ list_for_each_entry_safe(client, next, &adapter->userspace_clients,
+ detected) {
+ dev_dbg(&adapter->dev, "Removing %s at 0x%x\n", client->name,
+ client->addr);
+ list_del(&client->detected);
+ peci_unregister_device(client);
+ }
+ mutex_unlock(&adapter->userspace_clients_lock);
+
+ /**
+ * Detach any active clients. This can't fail, thus we do not
+ * check the returned value.
+ */
+ device_for_each_child(&adapter->dev, NULL, peci_unregister_client);
+
+ /* device name is gone after device_unregister */
+ dev_dbg(&adapter->dev, "adapter [%s] unregistered\n", adapter->name);
+
+ /* free cdev */
+ cdev_del(&adapter->cdev);
+
+ pm_runtime_disable(&adapter->dev);
+
+ nr = adapter->nr;
+
+ device_unregister(&adapter->dev);
+
+ /* free bus id */
+ mutex_lock(&core_lock);
+ idr_remove(&peci_adapter_idr, nr);
+ mutex_unlock(&core_lock);
+}
+EXPORT_SYMBOL_GPL(peci_del_adapter);
+
+/**
+ * A peci_driver is used with one or more peci_client (device) nodes to access
+ * peci clients, on a bus instance associated with some peci_adapter.
+ */
+int peci_register_driver(struct module *owner, struct peci_driver *driver)
+{
+ int rc;
+
+ /* Can't register until after driver model init */
+ if (WARN_ON(!is_registered))
+ return -EAGAIN;
+
+ /* add the driver to the list of peci drivers in the driver core */
+ driver->driver.owner = owner;
+ driver->driver.bus = &peci_bus_type;
+
+ /**
+ * When registration returns, the driver core
+ * will have called probe() for all matching-but-unbound devices.
+ */
+ rc = driver_register(&driver->driver);
+ if (rc)
+ return rc;
+
+ pr_debug("driver [%s] registered\n", driver->driver.name);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(peci_register_driver);
+
+void peci_del_driver(struct peci_driver *driver)
+{
+ driver_unregister(&driver->driver);
+ pr_debug("driver [%s] unregistered\n", driver->driver.name);
+}
+EXPORT_SYMBOL_GPL(peci_del_driver);
+
+static int __init peci_init(void)
+{
+ int ret;
+
+ ret = bus_register(&peci_bus_type);
+ if (ret < 0) {
+ pr_err("peci: Failed to register PECI bus type!\n");
+ return ret;
+ }
+
+ ret = alloc_chrdev_region(&peci_devt, 0, PECI_CDEV_MAX, "peci");
+ if (ret < 0) {
+ pr_err("peci: Failed to allocate chr dev region!\n");
+ bus_unregister(&peci_bus_type);
+ return ret;
+ }
+
+ crc8_populate_msb(peci_crc8_table, PECI_CRC8_POLYNOMIAL);
+
+ if (IS_ENABLED(CONFIG_OF_DYNAMIC))
+ WARN_ON(of_reconfig_notifier_register(&peci_of_notifier));
+
+ is_registered = true;
+
+ return 0;
+}
+
+static void __exit peci_exit(void)
+{
+ if (IS_ENABLED(CONFIG_OF_DYNAMIC))
+ WARN_ON(of_reconfig_notifier_unregister(&peci_of_notifier));
+
+ unregister_chrdev_region(peci_devt, PECI_CDEV_MAX);
+ bus_unregister(&peci_bus_type);
+}
+
+postcore_initcall(peci_init);
+module_exit(peci_exit);
+
+MODULE_AUTHOR("Jason M Biils <jason.m.bills@linux.intel.com>");
+MODULE_AUTHOR("Jae Hyun Yoo <jae.hyun.yoo@linux.intel.com>");
+MODULE_DESCRIPTION("PECI bus core module");
+MODULE_LICENSE("GPL v2");
diff --git a/include/linux/peci.h b/include/linux/peci.h
new file mode 100644
index 000000000000..425c9cdab6dc
--- /dev/null
+++ b/include/linux/peci.h
@@ -0,0 +1,104 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright (c) 2018 Intel Corporation */
+
+#ifndef __LINUX_PECI_H
+#define __LINUX_PECI_H
+
+#include <linux/cdev.h>
+#include <linux/device.h>
+#include <linux/peci-ioctl.h>
+#include <linux/rtmutex.h>
+
+#define PECI_NAME_SIZE 32
+
+struct peci_board_info {
+ char type[PECI_NAME_SIZE];
+ unsigned short addr; /* CPU client address */
+ struct device_node *of_node;
+};
+
+struct peci_adapter {
+ struct module *owner;
+ struct rt_mutex bus_lock;
+ struct device dev;
+ struct cdev cdev;
+ int nr;
+ char name[PECI_NAME_SIZE];
+ struct mutex userspace_clients_lock; /* clients list mutex */
+ struct list_head userspace_clients;
+ int (*xfer)(struct peci_adapter *adapter,
+ struct peci_xfer_msg *msg);
+ uint cmd_mask;
+};
+
+static inline struct peci_adapter *to_peci_adapter(void *d)
+{
+ return container_of(d, struct peci_adapter, dev);
+}
+
+static inline void *peci_get_adapdata(const struct peci_adapter *adapter)
+{
+ return dev_get_drvdata(&adapter->dev);
+}
+
+static inline void peci_set_adapdata(struct peci_adapter *adapter, void *data)
+{
+ dev_set_drvdata(&adapter->dev, data);
+}
+
+struct peci_client {
+ struct device dev; /* the device structure */
+ struct peci_adapter *adapter; /* the adapter we sit on */
+ u8 addr; /* CPU client address */
+ char name[PECI_NAME_SIZE];
+ struct list_head detected;
+};
+
+static inline struct peci_client *to_peci_client(void *d)
+{
+ return container_of(d, struct peci_client, dev);
+}
+
+struct peci_device_id {
+ char name[PECI_NAME_SIZE];
+ unsigned long driver_data; /* Data private to the driver */
+};
+
+struct peci_driver {
+ int (*probe)(struct peci_client *client);
+ int (*remove)(struct peci_client *client);
+ void (*shutdown)(struct peci_client *client);
+ struct device_driver driver;
+ const struct peci_device_id *id_table;
+};
+
+static inline struct peci_driver *to_peci_driver(void *d)
+{
+ return container_of(d, struct peci_driver, driver);
+}
+
+/**
+ * module_peci_driver() - Helper macro for registering a modular PECI driver
+ * @__peci_driver: peci_driver struct
+ *
+ * Helper macro for PECI drivers which do not do anything special in module
+ * init/exit. This eliminates a lot of boilerplate. Each module may only
+ * use this macro once, and calling it replaces module_init() and module_exit()
+ */
+#define module_peci_driver(__peci_driver) \
+ module_driver(__peci_driver, peci_add_driver, peci_del_driver)
+
+/* use a define to avoid include chaining to get THIS_MODULE */
+#define peci_add_driver(driver) peci_register_driver(THIS_MODULE, driver)
+
+int peci_register_driver(struct module *owner, struct peci_driver *drv);
+void peci_del_driver(struct peci_driver *driver);
+struct peci_client *peci_verify_client(struct device *dev);
+struct peci_adapter *peci_alloc_adapter(struct device *dev, unsigned int size);
+int peci_add_adapter(struct peci_adapter *adapter);
+void peci_del_adapter(struct peci_adapter *adapter);
+struct peci_adapter *peci_verify_adapter(struct device *dev);
+int peci_command(struct peci_adapter *adpater, enum peci_cmd cmd, void *vmsg);
+int peci_get_cpu_id(struct peci_adapter *adapter, u8 addr, u32 *cpu_id);
+
+#endif /* __LINUX_PECI_H */
diff --git a/include/uapi/linux/peci-ioctl.h b/include/uapi/linux/peci-ioctl.h
new file mode 100644
index 000000000000..b30d797c3b6e
--- /dev/null
+++ b/include/uapi/linux/peci-ioctl.h
@@ -0,0 +1,265 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright (c) 2018 Intel Corporation */
+
+#ifndef __PECI_IOCTL_H
+#define __PECI_IOCTL_H
+
+#include <linux/ioctl.h>
+#include <linux/types.h>
+
+/* Base Address of 48d */
+#define PECI_BASE_ADDR 0x30 /* The PECI client's default address of 0x30 */
+#define PECI_OFFSET_MAX 8 /* Max numver of CPU clients */
+
+/* PCI Access */
+#define MAX_PCI_READ_LEN 24 /* Number of bytes of the PCI Space read */
+
+#define PCI_BUS0_CPU0 0x00
+#define PCI_BUS0_CPU1 0x80
+#define PCI_CPUBUSNO_BUS 0x00
+#define PCI_CPUBUSNO_DEV 0x08
+#define PCI_CPUBUSNO_FUNC 0x02
+#define PCI_CPUBUSNO 0xcc
+#define PCI_CPUBUSNO_1 0xd0
+#define PCI_CPUBUSNO_VALID 0xd4
+
+/* Package Identifier Read Parameter Value */
+#define PKG_ID_CPU_ID 0x0000 /* CPUID Info */
+#define PKG_ID_PLATFORM_ID 0x0001 /* Platform ID */
+#define PKG_ID_UNCORE_ID 0x0002 /* Uncore Device ID */
+#define PKG_ID_MAX_THREAD_ID 0x0003 /* Max Thread ID */
+#define PKG_ID_MICROCODE_REV 0x0004 /* CPU Microcode Update Revision */
+#define PKG_ID_MACHINE_CHECK_STATUS 0x0005 /* Machine Check Status */
+
+/* RdPkgConfig Index */
+#define MBX_INDEX_CPU_ID 0 /* Package Identifier Read */
+#define MBX_INDEX_VR_DEBUG 1 /* VR Debug */
+#define MBX_INDEX_PKG_TEMP_READ 2 /* Package Temperature Read */
+#define MBX_INDEX_ENERGY_COUNTER 3 /* Energy counter */
+#define MBX_INDEX_ENERGY_STATUS 4 /* DDR Energy Status */
+#define MBX_INDEX_WAKE_MODE_BIT 5 /* "Wake on PECI" Mode bit */
+#define MBX_INDEX_EPI 6 /* Efficient Performance Indication */
+#define MBX_INDEX_PKG_RAPL_PERF 8 /* Pkg RAPL Performance Status Read */
+#define MBX_INDEX_PER_CORE_DTS_TEMP 9 /* Per Core DTS Temperature Read */
+#define MBX_INDEX_DTS_MARGIN 10 /* DTS thermal margin */
+#define MBX_INDEX_SKT_PWR_THRTL_DUR 11 /* Socket Power Throttled Duration */
+#define MBX_INDEX_CFG_TDP_CONTROL 12 /* TDP Config Control */
+#define MBX_INDEX_CFG_TDP_LEVELS 13 /* TDP Config Levels */
+#define MBX_INDEX_DDR_DIMM_TEMP 14 /* DDR DIMM Temperature */
+#define MBX_INDEX_CFG_ICCMAX 15 /* Configurable ICCMAX */
+#define MBX_INDEX_TEMP_TARGET 16 /* Temperature Target Read */
+#define MBX_INDEX_CURR_CFG_LIMIT 17 /* Current Config Limit */
+#define MBX_INDEX_DIMM_TEMP_READ 20 /* Package Thermal Status Read */
+#define MBX_INDEX_DRAM_IMC_TMP_READ 22 /* DRAM IMC Temperature Read */
+#define MBX_INDEX_DDR_CH_THERM_STAT 23 /* DDR Channel Thermal Status */
+#define MBX_INDEX_PKG_POWER_LIMIT1 26 /* Package Power Limit1 */
+#define MBX_INDEX_PKG_POWER_LIMIT2 27 /* Package Power Limit2 */
+#define MBX_INDEX_TDP 28 /* Thermal design power minimum */
+#define MBX_INDEX_TDP_HIGH 29 /* Thermal design power maximum */
+#define MBX_INDEX_TDP_UNITS 30 /* Units for power/energy registers */
+#define MBX_INDEX_RUN_TIME 31 /* Accumulated Run Time */
+#define MBX_INDEX_CONSTRAINED_TIME 32 /* Thermally Constrained Time Read */
+#define MBX_INDEX_TURBO_RATIO 33 /* Turbo Activation Ratio */
+#define MBX_INDEX_DDR_RAPL_PL1 34 /* DDR RAPL PL1 */
+#define MBX_INDEX_DDR_PWR_INFO_HIGH 35 /* DRAM Power Info Read (high) */
+#define MBX_INDEX_DDR_PWR_INFO_LOW 36 /* DRAM Power Info Read (low) */
+#define MBX_INDEX_DDR_RAPL_PL2 37 /* DDR RAPL PL2 */
+#define MBX_INDEX_DDR_RAPL_STATUS 38 /* DDR RAPL Performance Status */
+#define MBX_INDEX_DDR_HOT_ABSOLUTE 43 /* DDR Hottest Dimm Absolute Temp */
+#define MBX_INDEX_DDR_HOT_RELATIVE 44 /* DDR Hottest Dimm Relative Temp */
+#define MBX_INDEX_DDR_THROTTLE_TIME 45 /* DDR Throttle Time */
+#define MBX_INDEX_DDR_THERM_STATUS 46 /* DDR Thermal Status */
+#define MBX_INDEX_TIME_AVG_TEMP 47 /* Package time-averaged temperature */
+#define MBX_INDEX_TURBO_RATIO_LIMIT 49 /* Turbo Ratio Limit Read */
+#define MBX_INDEX_HWP_AUTO_OOB 53 /* HWP Autonomous Out-of-band */
+#define MBX_INDEX_DDR_WARM_BUDGET 55 /* DDR Warm Power Budget */
+#define MBX_INDEX_DDR_HOT_BUDGET 56 /* DDR Hot Power Budget */
+#define MBX_INDEX_PKG_PSYS_PWR_LIM3 57 /* Package/Psys Power Limit3 */
+#define MBX_INDEX_PKG_PSYS_PWR_LIM1 58 /* Package/Psys Power Limit1 */
+#define MBX_INDEX_PKG_PSYS_PWR_LIM2 59 /* Package/Psys Power Limit2 */
+#define MBX_INDEX_PKG_PSYS_PWR_LIM4 60 /* Package/Psys Power Limit4 */
+#define MBX_INDEX_PERF_LIMIT_REASON 65 /* Performance Limit Reasons */
+
+/* WrPkgConfig Index */
+#define MBX_INDEX_DIMM_AMBIENT 19
+#define MBX_INDEX_DIMM_TEMP 24
+
+/* Device Specific Completion Code (CC) Definition */
+#define DEV_PECI_CC_SUCCESS 0x40
+#define DEV_PECI_CC_TIMEOUT 0x80
+#define DEV_PECI_CC_OUT_OF_RESOURCE 0x81
+#define DEV_PECI_CC_UNAVAIL_RESOURCE 0x82
+#define DEV_PECI_CC_INVALID_REQ 0x90
+
+/* Completion Code mask to check retry needs */
+#define DEV_PECI_CC_RETRY_CHECK_MASK 0xf0
+#define DEV_PECI_CC_NEED_RETRY 0x80
+
+/* Skylake EDS says to retry for 250ms */
+#define DEV_PECI_RETRY_TIME_MS 250
+#define DEV_PECI_RETRY_INTERVAL_USEC 10000
+#define DEV_PECI_RETRY_BIT 0x01
+
+#define GET_TEMP_WR_LEN 1
+#define GET_TEMP_RD_LEN 2
+#define GET_TEMP_PECI_CMD 0x01
+
+#define GET_DIB_WR_LEN 1
+#define GET_DIB_RD_LEN 8
+#define GET_DIB_PECI_CMD 0xf7
+
+#define RDPKGCFG_WRITE_LEN 5
+#define RDPKGCFG_READ_LEN_BASE 1
+#define RDPKGCFG_PECI_CMD 0xa1
+
+#define WRPKGCFG_WRITE_LEN_BASE 6
+#define WRPKGCFG_READ_LEN 1
+#define WRPKGCFG_PECI_CMD 0xa5
+
+#define RDIAMSR_WRITE_LEN 5
+#define RDIAMSR_READ_LEN 9
+#define RDIAMSR_PECI_CMD 0xb1
+
+#define WRIAMSR_PECI_CMD 0xb5
+
+#define RDPCICFG_WRITE_LEN 6
+#define RDPCICFG_READ_LEN 5
+#define RDPCICFG_PECI_CMD 0x61
+
+#define WRPCICFG_PECI_CMD 0x65
+
+#define RDPCICFGLOCAL_WRITE_LEN 5
+#define RDPCICFGLOCAL_READ_LEN_BASE 1
+#define RDPCICFGLOCAL_PECI_CMD 0xe1
+
+#define WRPCICFGLOCAL_WRITE_LEN_BASE 6
+#define WRPCICFGLOCAL_READ_LEN 1
+#define WRPCICFGLOCAL_PECI_CMD 0xe5
+
+#define PECI_BUFFER_SIZE 32
+
+enum peci_cmd {
+ PECI_CMD_XFER = 0,
+ PECI_CMD_PING,
+ PECI_CMD_GET_DIB,
+ PECI_CMD_GET_TEMP,
+ PECI_CMD_RD_PKG_CFG,
+ PECI_CMD_WR_PKG_CFG,
+ PECI_CMD_RD_IA_MSR,
+ PECI_CMD_WR_IA_MSR,
+ PECI_CMD_RD_PCI_CFG,
+ PECI_CMD_WR_PCI_CFG,
+ PECI_CMD_RD_PCI_CFG_LOCAL,
+ PECI_CMD_WR_PCI_CFG_LOCAL,
+ PECI_CMD_MAX
+};
+
+struct peci_xfer_msg {
+ __u8 addr;
+ __u8 tx_len;
+ __u8 rx_len;
+ __u8 tx_buf[PECI_BUFFER_SIZE];
+ __u8 rx_buf[PECI_BUFFER_SIZE];
+} __attribute__((__packed__));
+
+struct peci_ping_msg {
+ __u8 addr;
+} __attribute__((__packed__));
+
+struct peci_get_dib_msg {
+ __u8 addr;
+ __u32 dib;
+} __attribute__((__packed__));
+
+struct peci_get_temp_msg {
+ __u8 addr;
+ __s16 temp_raw;
+} __attribute__((__packed__));
+
+struct peci_rd_pkg_cfg_msg {
+ __u8 addr;
+ __u8 index;
+ __u16 param;
+ __u8 rx_len;
+ __u8 pkg_config[4];
+} __attribute__((__packed__));
+
+struct peci_wr_pkg_cfg_msg {
+ __u8 addr;
+ __u8 index;
+ __u16 param;
+ __u8 tx_len;
+ __u32 value;
+} __attribute__((__packed__));
+
+struct peci_rd_ia_msr_msg {
+ __u8 addr;
+ __u8 thread_id;
+ __u16 address;
+ __u64 value;
+} __attribute__((__packed__));
+
+struct peci_rd_pci_cfg_msg {
+ __u8 addr;
+ __u8 bus;
+ __u8 device;
+ __u8 function;
+ __u16 reg;
+ __u8 pci_config[4];
+} __attribute__((__packed__));
+
+struct peci_rd_pci_cfg_local_msg {
+ __u8 addr;
+ __u8 bus;
+ __u8 device;
+ __u8 function;
+ __u16 reg;
+ __u8 rx_len;
+ __u8 pci_config[4];
+} __attribute__((__packed__));
+
+struct peci_wr_pci_cfg_local_msg {
+ __u8 addr;
+ __u8 bus;
+ __u8 device;
+ __u8 function;
+ __u16 reg;
+ __u8 tx_len;
+ __u32 value;
+} __attribute__((__packed__));
+
+#define PECI_IOC_BASE 0xb7
+
+#define PECI_IOC_XFER \
+ _IOWR(PECI_IOC_BASE, PECI_CMD_XFER, struct peci_xfer_msg)
+
+#define PECI_IOC_PING \
+ _IOWR(PECI_IOC_BASE, PECI_CMD_PING, struct peci_ping_msg)
+
+#define PECI_IOC_GET_DIB \
+ _IOWR(PECI_IOC_BASE, PECI_CMD_GET_DIB, struct peci_get_dib_msg)
+
+#define PECI_IOC_GET_TEMP \
+ _IOWR(PECI_IOC_BASE, PECI_CMD_GET_TEMP, struct peci_get_temp_msg)
+
+#define PECI_IOC_RD_PKG_CFG \
+ _IOWR(PECI_IOC_BASE, PECI_CMD_RD_PKG_CFG, struct peci_rd_pkg_cfg_msg)
+
+#define PECI_IOC_WR_PKG_CFG \
+ _IOWR(PECI_IOC_BASE, PECI_CMD_WR_PKG_CFG, struct peci_wr_pkg_cfg_msg)
+
+#define PECI_IOC_RD_IA_MSR \
+ _IOWR(PECI_IOC_BASE, PECI_CMD_RD_IA_MSR, struct peci_rd_ia_msr_msg)
+
+#define PECI_IOC_RD_PCI_CFG \
+ _IOWR(PECI_IOC_BASE, PECI_CMD_RD_PCI_CFG, struct peci_rd_pci_cfg_msg)
+
+#define PECI_IOC_RD_PCI_CFG_LOCAL \
+ _IOWR(PECI_IOC_BASE, PECI_CMD_RD_PCI_CFG_LOCAL, \
+ struct peci_rd_pci_cfg_local_msg)
+
+#define PECI_IOC_WR_PCI_CFG_LOCAL \
+ _IOWR(PECI_IOC_BASE, PECI_CMD_WR_PCI_CFG_LOCAL, \
+ struct peci_wr_pci_cfg_local_msg)
+
+#endif /* __PECI_IOCTL_H */
--
2.18.0
--
To unsubscribe from this list: send the line "unsubscribe linux-doc" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* Re: [PATCH v5 net-next] net/sched: add skbprio scheduler
From: Cong Wang @ 2018-07-23 20:47 UTC (permalink / raw)
To: Nishanth Devarajan
Cc: Jamal Hadi Salim, Jiri Pirko, David Miller,
Linux Kernel Network Developers, Cody Doucette, Michel Machado
In-Reply-To: <20180723140735.GA6935@gmail.com>
On Mon, Jul 23, 2018 at 7:07 AM Nishanth Devarajan <ndev2021@gmail.com> wrote:
>
> net/sched: add skbprio scheduler
>
> Skbprio (SKB Priority Queue) is a queueing discipline that prioritizes packets
> according to their skb->priority field. Under congestion, already-enqueued lower
> priority packets will be dropped to make space available for higher priority
> packets. Skbprio was conceived as a solution for denial-of-service defenses that
> need to route packets with different priorities as a means to overcome DoS
> attacks.
>
> v5
> *Do not reference qdisc_dev(sch)->tx_queue_len for setting limit. Instead set
> default sch->limit to 64.
Overall, it looks much better now!
Acked-by: Cong Wang <xiyou.wangcong@gmail.com>
Thanks the update!
^ permalink raw reply
* Re: [PATCH 0/3] PTI for x86-32 Fixes and Updates
From: Andy Lutomirski @ 2018-07-23 21:50 UTC (permalink / raw)
To: Pavel Machek
Cc: Linus Torvalds, Joerg Roedel, Thomas Gleixner, Ingo Molnar,
Peter Anvin, the arch/x86 maintainers, Linux Kernel Mailing List,
linux-mm, Andrew Lutomirski, Dave Hansen, Josh Poimboeuf,
Jürgen Groß, Peter Zijlstra, Borislav Petkov,
Jiri Kosina, Boris Ostrovsky, Brian Gerst, David Laight,
Denys Vlasenko, Eduardo Valentin, Greg Kroah-Hartman, Will Deacon,
Liguori, Anthony, Daniel Gruss, Hugh Dickins, Kees Cook,
Andrea Arcangeli, Waiman Long, David H . Gutteridge, Joerg Roedel,
Arnaldo Carvalho de Melo, Alexander Shishkin, Jiri Olsa,
Namhyung Kim
In-Reply-To: <20180723213830.GA4632@amd>
> On Jul 23, 2018, at 2:38 PM, Pavel Machek <pavel@ucw.cz> wrote:
>
>> On Mon 2018-07-23 12:00:08, Linus Torvalds wrote:
>>> On Mon, Jul 23, 2018 at 7:09 AM Pavel Machek <pavel@ucw.cz> wrote:
>>>
>>> Meanwhile... it looks like gcc is not slowed down significantly, but
>>> other stuff sees 30% .. 40% slowdowns... which is rather
>>> significant.
>>
>> That is more or less expected.
>>
>> Gcc spends about 90+% of its time in user space, and the system calls
>> it *does* do tend to be "real work" (open/read/etc). And modern gcc's
>> no longer have the pipe between cpp and cc1, so they don't have that
>> issue either (which would have sjhown the PTI slowdown a lot more)
>>
>> Some other loads will do a lot more time traversing the user/kernel
>> boundary, and in 32-bit mode you won't be able to take advantage of
>> the address space ID's, so you really get the full effect.
>
> Understood. Just -- bzip2 should include quite a lot of time in
> userspace, too.
>
>>> Would it be possible to have per-process control of kpti? I have
>>> some processes where trading of speed for security would make sense.
>>
>> That was pretty extensively discussed, and no sane model for it was
>> ever agreed upon. Some people wanted it per-thread, others per-mm,
>> and it wasn't clear how to set it either and how it should inherit
>> across fork/exec, and what the namespace rules etc should be.
>>
>> You absolutely need to inherit it (so that you can say "I trust this
>> session" or whatever), but at the same time you *don't* want to
>> inherit if you have a server you trust that then spawns user processes
>> (think "I want systemd to not have the overhead, but the user
>> processes it spawns obviously do need protection").
>>
>> It was just a morass. Nothing came out of it. I guess people can
>> discuss it again, but it's not simple.
>
> I agree it is not easy. OTOH -- 30% of user-visible performance is a
> _lot_. That is worth spending man-years on... Ok, problem is not as
> severe on modern CPUs with address space ID's, but...
>
> What I want is "if A can ptrace B, and B has pti disabled, A can have
> pti disabled as well". Now.. I see someone may want to have it
> per-thread, because for stuff like javascript JIT, thread may have
> rights to call ptrace, but is unable to call ptrace because JIT
> removed that ability... hmm...
No, you don’t want that. The problem is that Meltdown isn’t a problem that exists in isolation. It’s very plausible that JavaScript code could trigger a speculation attack that, with PTI off, could read kernel memory.
^ permalink raw reply
* Re: [PATCH v2 07/15] xfs: pack holes in xfs_defer_ops and xfs_trans
From: Bill O'Donnell @ 2018-07-23 20:48 UTC (permalink / raw)
To: Brian Foster; +Cc: linux-xfs
In-Reply-To: <20180723130414.47980-8-bfoster@redhat.com>
On Mon, Jul 23, 2018 at 09:04:06AM -0400, Brian Foster wrote:
> Both structures have holes due to member alignment. Move dop_low to
> the end of xfs_defer ops to sanitize the cache line alignment and
> move t_flags to save 8 bytes in xfs_trans.
>
> Signed-off-by: Brian Foster <bfoster@redhat.com>
> Reviewed-by: Christoph Hellwig <hch@lst.de>
Looks good.
Reviewed-by: Bill O'Donnell <billodo@redhat.com>
> ---
> fs/xfs/libxfs/xfs_defer.h | 3 ++-
> fs/xfs/xfs_trans.h | 2 +-
> 2 files changed, 3 insertions(+), 2 deletions(-)
>
> diff --git a/fs/xfs/libxfs/xfs_defer.h b/fs/xfs/libxfs/xfs_defer.h
> index 58c979c9f3fa..8f58f217fdff 100644
> --- a/fs/xfs/libxfs/xfs_defer.h
> +++ b/fs/xfs/libxfs/xfs_defer.h
> @@ -49,13 +49,14 @@ enum xfs_defer_ops_type {
> #define XFS_DEFER_OPS_NR_BUFS 2 /* join up to two buffers */
>
> struct xfs_defer_ops {
> - bool dop_low; /* alloc in low mode */
> struct list_head dop_intake; /* unlogged pending work */
> struct list_head dop_pending; /* logged pending work */
>
> /* relog these with each roll */
> struct xfs_inode *dop_inodes[XFS_DEFER_OPS_NR_INODES];
> struct xfs_buf *dop_bufs[XFS_DEFER_OPS_NR_BUFS];
> +
> + bool dop_low; /* alloc in low mode */
> };
>
> void xfs_defer_add(struct xfs_defer_ops *dop, enum xfs_defer_ops_type type,
> diff --git a/fs/xfs/xfs_trans.h b/fs/xfs/xfs_trans.h
> index 37fdacc690c7..6f857af61455 100644
> --- a/fs/xfs/xfs_trans.h
> +++ b/fs/xfs/xfs_trans.h
> @@ -102,12 +102,12 @@ typedef struct xfs_trans {
> unsigned int t_blk_res_used; /* # of resvd blocks used */
> unsigned int t_rtx_res; /* # of rt extents resvd */
> unsigned int t_rtx_res_used; /* # of resvd rt extents used */
> + unsigned int t_flags; /* misc flags */
> xfs_fsblock_t t_firstblock; /* first block allocated */
> struct xlog_ticket *t_ticket; /* log mgr ticket */
> struct xfs_mount *t_mountp; /* ptr to fs mount struct */
> struct xfs_dquot_acct *t_dqinfo; /* acctg info for dquots */
> struct xfs_defer_ops *t_dfops; /* dfops reference */
> - unsigned int t_flags; /* misc flags */
> int64_t t_icount_delta; /* superblock icount change */
> int64_t t_ifree_delta; /* superblock ifree change */
> int64_t t_fdblocks_delta; /* superblock fdblocks chg */
> --
> 2.17.1
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-xfs" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH 2/5] rhashtable: don't hold lock on first table throughout insertion.
From: NeilBrown @ 2018-07-23 21:52 UTC (permalink / raw)
To: paulmck; +Cc: Herbert Xu, Thomas Graf, netdev, linux-kernel
In-Reply-To: <20180723205625.GZ12945@linux.vnet.ibm.com>
[-- Attachment #1: Type: text/plain, Size: 1524 bytes --]
On Mon, Jul 23 2018, Paul E. McKenney wrote:
> On Mon, Jul 23, 2018 at 09:13:43AM +1000, NeilBrown wrote:
>> On Sun, Jul 22 2018, Paul E. McKenney wrote:
>> >
>> > One issue is that the ->func pointer can legitimately be NULL while on
>> > RCU's callback lists. This happens when someone invokes kfree_rcu()
>> > with the rcu_head structure at the beginning of the enclosing structure.
>> > I could add an offset to avoid this, or perhaps the kmalloc() folks
>> > could be persuaded Rao Shoaib's patch moving kfree_rcu() handling to
>> > the slab allocators, so that RCU only ever sees function pointers in
>> > the ->func field.
>> >
>> > Either way, this should be hidden behind an API to allow adjustments
>> > to be made if needed. Maybe something like is_after_call_rcu()?
>> > This would (for example) allow debug-object checks to be used to catch
>> > check-after-free bugs.
>> >
>> > Would something of that sort work for you?
>>
>> Yes, if you could provide an is_after_call_rcu() API, that would
>> perfectly suit my use-case.
>
> After beating my head against the object-debug code a bit, I have to ask
> if it would be OK for you if the is_after_call_rcu() API also takes the
> function that was passed to RCU.
Sure. It feels a bit clumsy, but I can see it could be easier to make
robust.
So yes: I'm fine with pass the same function and rcu_head to both
call_rcu() and is_after_call_rcu(). Actually, when I say it like that,
it seems less clumsy :-)
Thanks,
NeilBrown
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 832 bytes --]
^ permalink raw reply
* Re: [PATCH v4] selftests: add headers_install to lib.mk
From: Anders Roxell @ 2018-07-23 20:49 UTC (permalink / raw)
To: Masahiro Yamada, Michal Marek, Shuah Khan, Bamvor Zhang, brgl,
Paolo Bonzini, Andrew Morton, Mike Rapoport, aarcange
Cc: linux-kbuild, Linux Kernel Mailing List,
open list:KERNEL SELFTEST FRAMEWORK, Networking
In-Reply-To: <20180607110911.12252-1-anders.roxell@linaro.org>
On Thu, 7 Jun 2018 at 13:09, Anders Roxell <anders.roxell@linaro.org> wrote:
>
> If the kernel headers aren't installed we can't build all the tests.
> Add a new make target rule 'khdr' in the file lib.mk to generate the
> kernel headers and that gets include for every test-dir Makefile that
> includes lib.mk If the testdir in turn have its own sub-dirs the
> top_srcdir needs to be set to the linux-rootdir to be able to generate
> the kernel headers.
>
> Signed-off-by: Anders Roxell <anders.roxell@linaro.org>
> Reviewed-by: Fathi Boudra <fathi.boudra@linaro.org>
> ---
> Makefile | 14 +-------------
> scripts/subarch.include | 13 +++++++++++++
> tools/testing/selftests/android/Makefile | 2 +-
> tools/testing/selftests/android/ion/Makefile | 2 ++
> tools/testing/selftests/futex/functional/Makefile | 1 +
> tools/testing/selftests/gpio/Makefile | 7 ++-----
> tools/testing/selftests/kvm/Makefile | 7 ++-----
> tools/testing/selftests/lib.mk | 12 ++++++++++++
> tools/testing/selftests/net/Makefile | 1 +
> .../selftests/networking/timestamping/Makefile | 1 +
> tools/testing/selftests/vm/Makefile | 4 ----
> 11 files changed, 36 insertions(+), 28 deletions(-)
> create mode 100644 scripts/subarch.include
>
> diff --git a/Makefile b/Makefile
> index 6b9aea95ae3a..8050072300fa 100644
> --- a/Makefile
> +++ b/Makefile
> @@ -286,19 +286,7 @@ KERNELRELEASE = $(shell cat include/config/kernel.release 2> /dev/null)
> KERNELVERSION = $(VERSION)$(if $(PATCHLEVEL),.$(PATCHLEVEL)$(if $(SUBLEVEL),.$(SUBLEVEL)))$(EXTRAVERSION)
> export VERSION PATCHLEVEL SUBLEVEL KERNELRELEASE KERNELVERSION
>
> -# SUBARCH tells the usermode build what the underlying arch is. That is set
> -# first, and if a usermode build is happening, the "ARCH=um" on the command
> -# line overrides the setting of ARCH below. If a native build is happening,
> -# then ARCH is assigned, getting whatever value it gets normally, and
> -# SUBARCH is subsequently ignored.
> -
> -SUBARCH := $(shell uname -m | sed -e s/i.86/x86/ -e s/x86_64/x86/ \
> - -e s/sun4u/sparc64/ \
> - -e s/arm.*/arm/ -e s/sa110/arm/ \
> - -e s/s390x/s390/ -e s/parisc64/parisc/ \
> - -e s/ppc.*/powerpc/ -e s/mips.*/mips/ \
> - -e s/sh[234].*/sh/ -e s/aarch64.*/arm64/ \
> - -e s/riscv.*/riscv/)
> +include scripts/subarch.include
>
> # Cross compiling and selecting different set of gcc/bin-utils
> # ---------------------------------------------------------------------------
> diff --git a/scripts/subarch.include b/scripts/subarch.include
> new file mode 100644
> index 000000000000..650682821126
> --- /dev/null
> +++ b/scripts/subarch.include
> @@ -0,0 +1,13 @@
> +# SUBARCH tells the usermode build what the underlying arch is. That is set
> +# first, and if a usermode build is happening, the "ARCH=um" on the command
> +# line overrides the setting of ARCH below. If a native build is happening,
> +# then ARCH is assigned, getting whatever value it gets normally, and
> +# SUBARCH is subsequently ignored.
> +
> +SUBARCH := $(shell uname -m | sed -e s/i.86/x86/ -e s/x86_64/x86/ \
> + -e s/sun4u/sparc64/ \
> + -e s/arm.*/arm/ -e s/sa110/arm/ \
> + -e s/s390x/s390/ -e s/parisc64/parisc/ \
> + -e s/ppc.*/powerpc/ -e s/mips.*/mips/ \
> + -e s/sh[234].*/sh/ -e s/aarch64.*/arm64/ \
> + -e s/riscv.*/riscv/)
> diff --git a/tools/testing/selftests/android/Makefile b/tools/testing/selftests/android/Makefile
> index 72c25a3cb658..d9a725478375 100644
> --- a/tools/testing/selftests/android/Makefile
> +++ b/tools/testing/selftests/android/Makefile
> @@ -6,7 +6,7 @@ TEST_PROGS := run.sh
>
> include ../lib.mk
>
> -all:
> +all: khdr
> @for DIR in $(SUBDIRS); do \
> BUILD_TARGET=$(OUTPUT)/$$DIR; \
> mkdir $$BUILD_TARGET -p; \
> diff --git a/tools/testing/selftests/android/ion/Makefile b/tools/testing/selftests/android/ion/Makefile
> index e03695287f76..88cfe88e466f 100644
> --- a/tools/testing/selftests/android/ion/Makefile
> +++ b/tools/testing/selftests/android/ion/Makefile
> @@ -10,6 +10,8 @@ $(TEST_GEN_FILES): ipcsocket.c ionutils.c
>
> TEST_PROGS := ion_test.sh
>
> +KSFT_KHDR_INSTALL := 1
> +top_srcdir = ../../../../..
> include ../../lib.mk
>
> $(OUTPUT)/ionapp_export: ionapp_export.c ipcsocket.c ionutils.c
> diff --git a/tools/testing/selftests/futex/functional/Makefile b/tools/testing/selftests/futex/functional/Makefile
> index ff8feca49746..ad1eeb14fda7 100644
> --- a/tools/testing/selftests/futex/functional/Makefile
> +++ b/tools/testing/selftests/futex/functional/Makefile
> @@ -18,6 +18,7 @@ TEST_GEN_FILES := \
>
> TEST_PROGS := run.sh
>
> +top_srcdir = ../../../../..
> include ../../lib.mk
>
> $(TEST_GEN_FILES): $(HEADERS)
> diff --git a/tools/testing/selftests/gpio/Makefile b/tools/testing/selftests/gpio/Makefile
> index 1bbb47565c55..4665cdbf1a8d 100644
> --- a/tools/testing/selftests/gpio/Makefile
> +++ b/tools/testing/selftests/gpio/Makefile
> @@ -21,11 +21,8 @@ endef
> CFLAGS += -O2 -g -std=gnu99 -Wall -I../../../../usr/include/
> LDLIBS += -lmount -I/usr/include/libmount
>
> -$(BINARIES): ../../../gpio/gpio-utils.o ../../../../usr/include/linux/gpio.h
> +$(BINARIES):| khdr
> +$(BINARIES): ../../../gpio/gpio-utils.o
>
> ../../../gpio/gpio-utils.o:
> make ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) -C ../../../gpio
> -
> -../../../../usr/include/linux/gpio.h:
> - make -C ../../../.. headers_install INSTALL_HDR_PATH=$(shell pwd)/../../../../usr/
> -
> diff --git a/tools/testing/selftests/kvm/Makefile b/tools/testing/selftests/kvm/Makefile
> index d9d00319b07c..bcb69380bbab 100644
> --- a/tools/testing/selftests/kvm/Makefile
> +++ b/tools/testing/selftests/kvm/Makefile
> @@ -32,9 +32,6 @@ $(LIBKVM_OBJ): $(OUTPUT)/%.o: %.c
> $(OUTPUT)/libkvm.a: $(LIBKVM_OBJ)
> $(AR) crs $@ $^
>
> -$(LINUX_HDR_PATH):
> - make -C $(top_srcdir) headers_install
> -
> -all: $(STATIC_LIBS) $(LINUX_HDR_PATH)
> +all: $(STATIC_LIBS)
> $(TEST_GEN_PROGS): $(STATIC_LIBS)
> -$(TEST_GEN_PROGS) $(LIBKVM_OBJ): | $(LINUX_HDR_PATH)
> +$(STATIC_LIBS):| khdr
> diff --git a/tools/testing/selftests/lib.mk b/tools/testing/selftests/lib.mk
> index 17ab36605a8e..0a8e75886224 100644
> --- a/tools/testing/selftests/lib.mk
> +++ b/tools/testing/selftests/lib.mk
> @@ -16,8 +16,20 @@ TEST_GEN_PROGS := $(patsubst %,$(OUTPUT)/%,$(TEST_GEN_PROGS))
> TEST_GEN_PROGS_EXTENDED := $(patsubst %,$(OUTPUT)/%,$(TEST_GEN_PROGS_EXTENDED))
> TEST_GEN_FILES := $(patsubst %,$(OUTPUT)/%,$(TEST_GEN_FILES))
>
> +top_srcdir ?= ../../../..
> +include $(top_srcdir)/scripts/subarch.include
> +ARCH ?= $(SUBARCH)
> +
> all: $(TEST_GEN_PROGS) $(TEST_GEN_PROGS_EXTENDED) $(TEST_GEN_FILES)
>
> +.PHONY: khdr
> +khdr:
> + make ARCH=$(ARCH) -C $(top_srcdir) headers_install
> +
> +ifdef KSFT_KHDR_INSTALL
> +$(TEST_GEN_PROGS) $(TEST_GEN_PROGS_EXTENDED) $(TEST_GEN_FILES):| khdr
> +endif
> +
> .ONESHELL:
> define RUN_TEST_PRINT_RESULT
> TEST_HDR_MSG="selftests: "`basename $$PWD`:" $$BASENAME_TEST"; \
> diff --git a/tools/testing/selftests/net/Makefile b/tools/testing/selftests/net/Makefile
> index 663e11e85727..d515dabc6b0d 100644
> --- a/tools/testing/selftests/net/Makefile
> +++ b/tools/testing/selftests/net/Makefile
> @@ -15,6 +15,7 @@ TEST_GEN_FILES += udpgso udpgso_bench_tx udpgso_bench_rx
> TEST_GEN_PROGS = reuseport_bpf reuseport_bpf_cpu reuseport_bpf_numa
> TEST_GEN_PROGS += reuseport_dualstack reuseaddr_conflict
>
> +KSFT_KHDR_INSTALL := 1
> include ../lib.mk
>
> $(OUTPUT)/reuseport_bpf_numa: LDFLAGS += -lnuma
> diff --git a/tools/testing/selftests/networking/timestamping/Makefile b/tools/testing/selftests/networking/timestamping/Makefile
> index a728040edbe1..14cfcf006936 100644
> --- a/tools/testing/selftests/networking/timestamping/Makefile
> +++ b/tools/testing/selftests/networking/timestamping/Makefile
> @@ -5,6 +5,7 @@ TEST_PROGS := hwtstamp_config rxtimestamp timestamping txtimestamp
>
> all: $(TEST_PROGS)
>
> +top_srcdir = ../../../../..
> include ../../lib.mk
>
> clean:
> diff --git a/tools/testing/selftests/vm/Makefile b/tools/testing/selftests/vm/Makefile
> index fdefa2295ddc..58759454b1d0 100644
> --- a/tools/testing/selftests/vm/Makefile
> +++ b/tools/testing/selftests/vm/Makefile
> @@ -25,10 +25,6 @@ TEST_PROGS := run_vmtests
>
> include ../lib.mk
>
> -$(OUTPUT)/userfaultfd: ../../../../usr/include/linux/kernel.h
> $(OUTPUT)/userfaultfd: LDLIBS += -lpthread
>
> $(OUTPUT)/mlock-random-test: LDLIBS += -lcap
> -
> -../../../../usr/include/linux/kernel.h:
> - make -C ../../../.. headers_install
> --
> 2.17.1
>
Ping.
^ permalink raw reply
* Re: [PATCH v5] PCI: Check for PCIe downtraining conditions
From: Tal Gilboa @ 2018-07-23 21:52 UTC (permalink / raw)
To: Jakub Kicinski, Alexandru Gagniuc
Cc: linux-pci@vger.kernel.org, bhelgaas@google.com,
keith.busch@intel.com, alex_gagniuc@dellteam.com,
austin_bolen@dell.com, shyam_iyer@dell.com,
jeffrey.t.kirsher@intel.com, ariel.elior@cavium.com,
michael.chan@broadcom.com, ganeshgr@chelsio.com, Tariq Toukan,
airlied@gmail.com, alexander.deucher@amd.com,
mike.marciniszyn@intel.com, linux-kernel@vger.kernel.org
In-Reply-To: <20180723140143.1a46902f@cakuba.netronome.com>
On 7/24/2018 12:01 AM, Jakub Kicinski wrote:
> On Mon, 23 Jul 2018 15:03:38 -0500, Alexandru Gagniuc wrote:
>> PCIe downtraining happens when both the device and PCIe port are
>> capable of a larger bus width or higher speed than negotiated.
>> Downtraining might be indicative of other problems in the system, and
>> identifying this from userspace is neither intuitive, nor
>> straightforward.
>>
>> The easiest way to detect this is with pcie_print_link_status(),
>> since the bottleneck is usually the link that is downtrained. It's not
>> a perfect solution, but it works extremely well in most cases.
>>
>> Signed-off-by: Alexandru Gagniuc <mr.nuke.me@gmail.com>
>> ---
>>
>> For the sake of review, I've created a __pcie_print_link_status() which
>> takes a 'verbose' argument. If we agree want to go this route, and update
>> the users of pcie_print_link_status(), I can split this up in two patches.
>> I prefer just printing this information in the core functions, and letting
>> drivers not have to worry about this. Though there seems to be strong for
>> not going that route, so here it goes:
>
> FWIW the networking drivers print PCIe BW because sometimes the network
> bandwidth is simply over-provisioned on multi port cards, e.g. 80Gbps
> card on a x8 link.
>
> Sorry to bike shed, but currently the networking cards print the info
> during probe. Would it make sense to move your message closer to probe
> time? Rather than when device is added. If driver structure is
> available, we could also consider adding a boolean to struct pci_driver
> to indicate if driver wants the verbose message? This way we avoid
> duplicated prints.
>
> I have no objection to current patch, it LGTM. Just a thought.
I don't see the reason for having two functions. What's the problem with
adding the verbose argument to the original function?
>
>> drivers/pci/pci.c | 22 ++++++++++++++++++----
>> drivers/pci/probe.c | 21 +++++++++++++++++++++
>> include/linux/pci.h | 1 +
>> 3 files changed, 40 insertions(+), 4 deletions(-) >>
>> diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
>> index 316496e99da9..414ad7b3abdb 100644
>> --- a/drivers/pci/pci.c
>> +++ b/drivers/pci/pci.c
>> @@ -5302,14 +5302,15 @@ u32 pcie_bandwidth_capable(struct pci_dev *dev, enum pci_bus_speed *speed,
>> }
>>
>> /**
>> - * pcie_print_link_status - Report the PCI device's link speed and width
>> + * __pcie_print_link_status - Report the PCI device's link speed and width
>> * @dev: PCI device to query
>> + * @verbose: Be verbose -- print info even when enough bandwidth is available.
>> *
>> * Report the available bandwidth at the device. If this is less than the
>> * device is capable of, report the device's maximum possible bandwidth and
>> * the upstream link that limits its performance to less than that.
>> */
>> -void pcie_print_link_status(struct pci_dev *dev)
>> +void __pcie_print_link_status(struct pci_dev *dev, bool verbose)
>> {
>> enum pcie_link_width width, width_cap;
>> enum pci_bus_speed speed, speed_cap;
>> @@ -5319,11 +5320,11 @@ void pcie_print_link_status(struct pci_dev *dev)
>> bw_cap = pcie_bandwidth_capable(dev, &speed_cap, &width_cap);
>> bw_avail = pcie_bandwidth_available(dev, &limiting_dev, &speed, &width);
>>
>> - if (bw_avail >= bw_cap)
>> + if (bw_avail >= bw_cap && verbose)
>> pci_info(dev, "%u.%03u Gb/s available PCIe bandwidth (%s x%d link)\n",
>> bw_cap / 1000, bw_cap % 1000,
>> PCIE_SPEED2STR(speed_cap), width_cap);
>> - else
>> + else if (bw_avail < bw_cap)
>> pci_info(dev, "%u.%03u Gb/s available PCIe bandwidth, limited by %s x%d link at %s (capable of %u.%03u Gb/s with %s x%d link)\n",
>> bw_avail / 1000, bw_avail % 1000,
>> PCIE_SPEED2STR(speed), width,
>> @@ -5331,6 +5332,19 @@ void pcie_print_link_status(struct pci_dev *dev)
>> bw_cap / 1000, bw_cap % 1000,
>> PCIE_SPEED2STR(speed_cap), width_cap);
>> }
>> +
>> +/**
>> + * pcie_print_link_status - Report the PCI device's link speed and width
>> + * @dev: PCI device to query
>> + *
>> + * Report the available bandwidth at the device. If this is less than the
>> + * device is capable of, report the device's maximum possible bandwidth and
>> + * the upstream link that limits its performance to less than that.
>> + */
>> +void pcie_print_link_status(struct pci_dev *dev)
>> +{
>> + __pcie_print_link_status(dev, true);
>> +}
>> EXPORT_SYMBOL(pcie_print_link_status);
>>
>> /**
>> diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
>> index ac876e32de4b..1f7336377c3b 100644
>> --- a/drivers/pci/probe.c
>> +++ b/drivers/pci/probe.c
>> @@ -2205,6 +2205,24 @@ static struct pci_dev *pci_scan_device(struct pci_bus *bus, int devfn)
>> return dev;
>> }
>>
>> +static void pcie_check_upstream_link(struct pci_dev *dev)
>> +{
>> + if (!pci_is_pcie(dev))
>> + return;
>> +
>> + /* Look from the device up to avoid downstream ports with no devices. */
>> + if ((pci_pcie_type(dev) != PCI_EXP_TYPE_ENDPOINT) &&
>> + (pci_pcie_type(dev) != PCI_EXP_TYPE_LEG_END) &&
>> + (pci_pcie_type(dev) != PCI_EXP_TYPE_UPSTREAM))
>> + return;
>> +
>> + /* Multi-function PCIe share the same link/status. */
>> + if (PCI_FUNC(dev->devfn) != 0 || dev->is_virtfn)
>> + return;
>> +
>> + __pcie_print_link_status(dev, false);
>> +}
>> +
>> static void pci_init_capabilities(struct pci_dev *dev)
>> {
>> /* Enhanced Allocation */
>> @@ -2240,6 +2258,9 @@ static void pci_init_capabilities(struct pci_dev *dev)
>> /* Advanced Error Reporting */
>> pci_aer_init(dev);
>>
>> + /* Check link and detect downtrain errors */
>> + pcie_check_upstream_link(dev);
This is called for every PCIe device right? Won't there be a duplicated
print in case a device loads with lower PCIe bandwidth than needed?
>> +
>> if (pci_probe_reset_function(dev) == 0)
>> dev->reset_fn = 1;
>> }
>> diff --git a/include/linux/pci.h b/include/linux/pci.h
>> index abd5d5e17aee..15bfab8f7a1b 100644
>> --- a/include/linux/pci.h
>> +++ b/include/linux/pci.h
>> @@ -1088,6 +1088,7 @@ int pcie_set_mps(struct pci_dev *dev, int mps);
>> u32 pcie_bandwidth_available(struct pci_dev *dev, struct pci_dev **limiting_dev,
>> enum pci_bus_speed *speed,
>> enum pcie_link_width *width);
>> +void __pcie_print_link_status(struct pci_dev *dev, bool verbose);
>> void pcie_print_link_status(struct pci_dev *dev);
>> int pcie_flr(struct pci_dev *dev);
>> int __pci_reset_function_locked(struct pci_dev *dev);
>
^ permalink raw reply
* Re: [PATCH v2 09/15] xfs: use internal dfops in cow blocks cancel
From: Bill O'Donnell @ 2018-07-23 20:49 UTC (permalink / raw)
To: Brian Foster; +Cc: linux-xfs
In-Reply-To: <20180723130414.47980-10-bfoster@redhat.com>
On Mon, Jul 23, 2018 at 09:04:08AM -0400, Brian Foster wrote:
> All callers either explicitly initialize a dfops or pass a
> transaction with an internal dfops. Drop the hacky old dfops
> replacement logic and use the one associated with the transaction.
>
> Signed-off-by: Brian Foster <bfoster@redhat.com>
Looks good.
Reviewed-by: Bill O'Donnell <billodo@redhat.com>
> ---
> fs/xfs/xfs_reflink.c | 6 ++----
> 1 file changed, 2 insertions(+), 4 deletions(-)
>
> diff --git a/fs/xfs/xfs_reflink.c b/fs/xfs/xfs_reflink.c
> index 3143889097f1..c3f2a0d3e6f5 100644
> --- a/fs/xfs/xfs_reflink.c
> +++ b/fs/xfs/xfs_reflink.c
> @@ -483,8 +483,6 @@ xfs_reflink_cancel_cow_blocks(
> struct xfs_ifork *ifp = XFS_IFORK_PTR(ip, XFS_COW_FORK);
> struct xfs_bmbt_irec got, del;
> struct xfs_iext_cursor icur;
> - struct xfs_defer_ops dfops;
> - struct xfs_defer_ops *odfops = (*tpp)->t_dfops;
> int error = 0;
>
> if (!xfs_is_reflink_inode(ip))
> @@ -511,7 +509,8 @@ xfs_reflink_cancel_cow_blocks(
> if (error)
> break;
> } else if (del.br_state == XFS_EXT_UNWRITTEN || cancel_real) {
> - xfs_defer_init(*tpp, &dfops);
> + ASSERT((*tpp)->t_dfops);
> + ASSERT((*tpp)->t_firstblock == NULLFSBLOCK);
>
> /* Free the CoW orphan record. */
> error = xfs_refcount_free_cow_extent(ip->i_mount,
> @@ -553,7 +552,6 @@ xfs_reflink_cancel_cow_blocks(
> /* clear tag if cow fork is emptied */
> if (!ifp->if_bytes)
> xfs_inode_clear_cowblocks_tag(ip);
> - (*tpp)->t_dfops = odfops;
> return error;
> }
>
> --
> 2.17.1
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-xfs" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* [PATCH] drm/amdgpu: implement harvesting support for UVD 7.2 (v2)
From: Alex Deucher @ 2018-07-23 21:53 UTC (permalink / raw)
To: amd-gfx-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW; +Cc: Alex Deucher
Properly handle cases where one or more instance of the IP
block may be harvested.
v2: make sure ip_num_rings is initialized amdgpu_queue_mgr.c
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
---
drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c | 10 ++++-
drivers/gpu/drm/amd/amdgpu/amdgpu_queue_mgr.c | 13 +++++--
drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c | 11 +++++-
drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.h | 5 +++
drivers/gpu/drm/amd/amdgpu/uvd_v7_0.c | 56 +++++++++++++++++++++++++--
5 files changed, 86 insertions(+), 9 deletions(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
index 258b6f73cbdf..f4d379cd4e47 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
@@ -348,8 +348,11 @@ static int amdgpu_info_ioctl(struct drm_device *dev, void *data, struct drm_file
break;
case AMDGPU_HW_IP_UVD:
type = AMD_IP_BLOCK_TYPE_UVD;
- for (i = 0; i < adev->uvd.num_uvd_inst; i++)
+ for (i = 0; i < adev->uvd.num_uvd_inst; i++) {
+ if (adev->uvd.harvest_config & (1 << i))
+ continue;
ring_mask |= ((adev->uvd.inst[i].ring.ready ? 1 : 0) << i);
+ }
ib_start_alignment = 64;
ib_size_alignment = 64;
break;
@@ -362,11 +365,14 @@ static int amdgpu_info_ioctl(struct drm_device *dev, void *data, struct drm_file
break;
case AMDGPU_HW_IP_UVD_ENC:
type = AMD_IP_BLOCK_TYPE_UVD;
- for (i = 0; i < adev->uvd.num_uvd_inst; i++)
+ for (i = 0; i < adev->uvd.num_uvd_inst; i++) {
+ if (adev->uvd.harvest_config & (1 << i))
+ continue;
for (j = 0; j < adev->uvd.num_enc_rings; j++)
ring_mask |=
((adev->uvd.inst[i].ring_enc[j].ready ? 1 : 0) <<
(j + i * adev->uvd.num_enc_rings));
+ }
ib_start_alignment = 64;
ib_size_alignment = 64;
break;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_queue_mgr.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_queue_mgr.c
index ea9850c9224d..c59d3a2af388 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_queue_mgr.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_queue_mgr.c
@@ -219,7 +219,7 @@ int amdgpu_queue_mgr_map(struct amdgpu_device *adev,
u32 hw_ip, u32 instance, u32 ring,
struct amdgpu_ring **out_ring)
{
- int r, ip_num_rings;
+ int i, r, ip_num_rings = 0;
struct amdgpu_queue_mapper *mapper = &mgr->mapper[hw_ip];
if (!adev || !mgr || !out_ring)
@@ -248,14 +248,21 @@ int amdgpu_queue_mgr_map(struct amdgpu_device *adev,
ip_num_rings = adev->sdma.num_instances;
break;
case AMDGPU_HW_IP_UVD:
- ip_num_rings = adev->uvd.num_uvd_inst;
+ for (i = 0; i < adev->uvd.num_uvd_inst; i++) {
+ if (!(adev->uvd.harvest_config & (1 << i)))
+ ip_num_rings++;
+ }
break;
case AMDGPU_HW_IP_VCE:
ip_num_rings = adev->vce.num_rings;
break;
case AMDGPU_HW_IP_UVD_ENC:
+ for (i = 0; i < adev->uvd.num_uvd_inst; i++) {
+ if (!(adev->uvd.harvest_config & (1 << i)))
+ ip_num_rings++;
+ }
ip_num_rings =
- adev->uvd.num_enc_rings * adev->uvd.num_uvd_inst;
+ adev->uvd.num_enc_rings * ip_num_rings;
break;
case AMDGPU_HW_IP_VCN_DEC:
ip_num_rings = 1;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c
index 80b5c453f8c1..a07548c99ab8 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c
@@ -255,7 +255,8 @@ int amdgpu_uvd_sw_init(struct amdgpu_device *adev)
bo_size += AMDGPU_GPU_PAGE_ALIGN(le32_to_cpu(hdr->ucode_size_bytes) + 8);
for (j = 0; j < adev->uvd.num_uvd_inst; j++) {
-
+ if (adev->uvd.harvest_config & (1 << j))
+ continue;
r = amdgpu_bo_create_kernel(adev, bo_size, PAGE_SIZE,
AMDGPU_GEM_DOMAIN_VRAM, &adev->uvd.inst[j].vcpu_bo,
&adev->uvd.inst[j].gpu_addr, &adev->uvd.inst[j].cpu_addr);
@@ -309,6 +310,8 @@ int amdgpu_uvd_sw_fini(struct amdgpu_device *adev)
&adev->uvd.entity);
for (j = 0; j < adev->uvd.num_uvd_inst; ++j) {
+ if (adev->uvd.harvest_config & (1 << j))
+ continue;
kfree(adev->uvd.inst[j].saved_bo);
amdgpu_bo_free_kernel(&adev->uvd.inst[j].vcpu_bo,
@@ -344,6 +347,8 @@ int amdgpu_uvd_suspend(struct amdgpu_device *adev)
}
for (j = 0; j < adev->uvd.num_uvd_inst; ++j) {
+ if (adev->uvd.harvest_config & (1 << j))
+ continue;
if (adev->uvd.inst[j].vcpu_bo == NULL)
continue;
@@ -366,6 +371,8 @@ int amdgpu_uvd_resume(struct amdgpu_device *adev)
int i;
for (i = 0; i < adev->uvd.num_uvd_inst; i++) {
+ if (adev->uvd.harvest_config & (1 << i))
+ continue;
if (adev->uvd.inst[i].vcpu_bo == NULL)
return -EINVAL;
@@ -1160,6 +1167,8 @@ static void amdgpu_uvd_idle_work_handler(struct work_struct *work)
unsigned fences = 0, i, j;
for (i = 0; i < adev->uvd.num_uvd_inst; ++i) {
+ if (adev->uvd.harvest_config & (1 << i))
+ continue;
fences += amdgpu_fence_count_emitted(&adev->uvd.inst[i].ring);
for (j = 0; j < adev->uvd.num_enc_rings; ++j) {
fences += amdgpu_fence_count_emitted(&adev->uvd.inst[i].ring_enc[j]);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.h
index 66872286ab12..9cf42454ba81 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.h
@@ -46,8 +46,12 @@ struct amdgpu_uvd_inst {
struct amdgpu_ring ring_enc[AMDGPU_MAX_UVD_ENC_RINGS];
struct amdgpu_irq_src irq;
uint32_t srbm_soft_reset;
+ uint32_t instance;
};
+#define AMDGPU_UVD_HARVEST_UVD0 (1 << 0)
+#define AMDGPU_UVD_HARVEST_UVD1 (1 << 1)
+
struct amdgpu_uvd {
const struct firmware *fw; /* UVD firmware */
unsigned fw_version;
@@ -61,6 +65,7 @@ struct amdgpu_uvd {
atomic_t handles[AMDGPU_MAX_UVD_HANDLES];
struct drm_sched_entity entity;
struct delayed_work idle_work;
+ unsigned harvest_config;
};
int amdgpu_uvd_sw_init(struct amdgpu_device *adev);
diff --git a/drivers/gpu/drm/amd/amdgpu/uvd_v7_0.c b/drivers/gpu/drm/amd/amdgpu/uvd_v7_0.c
index db5f3d78ab12..8179317be750 100644
--- a/drivers/gpu/drm/amd/amdgpu/uvd_v7_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/uvd_v7_0.c
@@ -41,6 +41,12 @@
#include "mmhub/mmhub_1_0_sh_mask.h"
#include "ivsrcid/uvd/irqsrcs_uvd_7_0.h"
+#define mmUVD_PG0_CC_UVD_HARVESTING 0x00c7
+#define mmUVD_PG0_CC_UVD_HARVESTING_BASE_IDX 1
+//UVD_PG0_CC_UVD_HARVESTING
+#define UVD_PG0_CC_UVD_HARVESTING__UVD_DISABLE__SHIFT 0x1
+#define UVD_PG0_CC_UVD_HARVESTING__UVD_DISABLE_MASK 0x00000002L
+
#define UVD7_MAX_HW_INSTANCES_VEGA20 2
static void uvd_v7_0_set_ring_funcs(struct amdgpu_device *adev);
@@ -370,10 +376,25 @@ static int uvd_v7_0_enc_ring_test_ib(struct amdgpu_ring *ring, long timeout)
static int uvd_v7_0_early_init(void *handle)
{
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
- if (adev->asic_type == CHIP_VEGA20)
+
+ if (adev->asic_type == CHIP_VEGA20) {
+ u32 harvest;
+ int i;
+
adev->uvd.num_uvd_inst = UVD7_MAX_HW_INSTANCES_VEGA20;
- else
+ for (i = 0; i < adev->uvd.num_uvd_inst; i++) {
+ harvest = RREG32_SOC15(UVD, i, mmUVD_PG0_CC_UVD_HARVESTING);
+ if (harvest & UVD_PG0_CC_UVD_HARVESTING__UVD_DISABLE_MASK) {
+ adev->uvd.harvest_config |= 1 << i;
+ }
+ }
+ if (adev->uvd.harvest_config == (AMDGPU_UVD_HARVEST_UVD0 |
+ AMDGPU_UVD_HARVEST_UVD1))
+ /* both instances are harvested, disable the block */
+ return -ENOENT;
+ } else {
adev->uvd.num_uvd_inst = 1;
+ }
if (amdgpu_sriov_vf(adev))
adev->uvd.num_enc_rings = 1;
@@ -393,6 +414,8 @@ static int uvd_v7_0_sw_init(void *handle)
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
for (j = 0; j < adev->uvd.num_uvd_inst; j++) {
+ if (adev->uvd.harvest_config & (1 << j))
+ continue;
/* UVD TRAP */
r = amdgpu_irq_add_id(adev, amdgpu_ih_clientid_uvds[j], UVD_7_0__SRCID__UVD_SYSTEM_MESSAGE_INTERRUPT, &adev->uvd.inst[j].irq);
if (r)
@@ -425,6 +448,8 @@ static int uvd_v7_0_sw_init(void *handle)
return r;
for (j = 0; j < adev->uvd.num_uvd_inst; j++) {
+ if (adev->uvd.harvest_config & (1 << j))
+ continue;
if (!amdgpu_sriov_vf(adev)) {
ring = &adev->uvd.inst[j].ring;
sprintf(ring->name, "uvd<%d>", j);
@@ -472,6 +497,8 @@ static int uvd_v7_0_sw_fini(void *handle)
return r;
for (j = 0; j < adev->uvd.num_uvd_inst; ++j) {
+ if (adev->uvd.harvest_config & (1 << j))
+ continue;
for (i = 0; i < adev->uvd.num_enc_rings; ++i)
amdgpu_ring_fini(&adev->uvd.inst[j].ring_enc[i]);
}
@@ -500,6 +527,8 @@ static int uvd_v7_0_hw_init(void *handle)
goto done;
for (j = 0; j < adev->uvd.num_uvd_inst; ++j) {
+ if (adev->uvd.harvest_config & (1 << j))
+ continue;
ring = &adev->uvd.inst[j].ring;
if (!amdgpu_sriov_vf(adev)) {
@@ -579,8 +608,11 @@ static int uvd_v7_0_hw_fini(void *handle)
DRM_DEBUG("For SRIOV client, shouldn't do anything.\n");
}
- for (i = 0; i < adev->uvd.num_uvd_inst; ++i)
+ for (i = 0; i < adev->uvd.num_uvd_inst; ++i) {
+ if (adev->uvd.harvest_config & (1 << i))
+ continue;
adev->uvd.inst[i].ring.ready = false;
+ }
return 0;
}
@@ -623,6 +655,8 @@ static void uvd_v7_0_mc_resume(struct amdgpu_device *adev)
int i;
for (i = 0; i < adev->uvd.num_uvd_inst; ++i) {
+ if (adev->uvd.harvest_config & (1 << i))
+ continue;
if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) {
WREG32_SOC15(UVD, i, mmUVD_LMI_VCPU_CACHE_64BIT_BAR_LOW,
lower_32_bits(adev->firmware.ucode[AMDGPU_UCODE_ID_UVD].mc_addr));
@@ -695,6 +729,8 @@ static int uvd_v7_0_mmsch_start(struct amdgpu_device *adev,
WREG32_SOC15(VCE, 0, mmVCE_MMSCH_VF_MAILBOX_RESP, 0);
for (i = 0; i < adev->uvd.num_uvd_inst; ++i) {
+ if (adev->uvd.harvest_config & (1 << i))
+ continue;
WDOORBELL32(adev->uvd.inst[i].ring_enc[0].doorbell_index, 0);
adev->wb.wb[adev->uvd.inst[i].ring_enc[0].wptr_offs] = 0;
adev->uvd.inst[i].ring_enc[0].wptr = 0;
@@ -751,6 +787,8 @@ static int uvd_v7_0_sriov_start(struct amdgpu_device *adev)
init_table += header->uvd_table_offset;
for (i = 0; i < adev->uvd.num_uvd_inst; ++i) {
+ if (adev->uvd.harvest_config & (1 << i))
+ continue;
ring = &adev->uvd.inst[i].ring;
ring->wptr = 0;
size = AMDGPU_GPU_PAGE_ALIGN(adev->uvd.fw->size + 4);
@@ -890,6 +928,8 @@ static int uvd_v7_0_start(struct amdgpu_device *adev)
int i, j, k, r;
for (k = 0; k < adev->uvd.num_uvd_inst; ++k) {
+ if (adev->uvd.harvest_config & (1 << k))
+ continue;
/* disable DPG */
WREG32_P(SOC15_REG_OFFSET(UVD, k, mmUVD_POWER_STATUS), 0,
~UVD_POWER_STATUS__UVD_PG_MODE_MASK);
@@ -902,6 +942,8 @@ static int uvd_v7_0_start(struct amdgpu_device *adev)
uvd_v7_0_mc_resume(adev);
for (k = 0; k < adev->uvd.num_uvd_inst; ++k) {
+ if (adev->uvd.harvest_config & (1 << k))
+ continue;
ring = &adev->uvd.inst[k].ring;
/* disable clock gating */
WREG32_P(SOC15_REG_OFFSET(UVD, k, mmUVD_CGC_CTRL), 0,
@@ -1069,6 +1111,8 @@ static void uvd_v7_0_stop(struct amdgpu_device *adev)
uint8_t i = 0;
for (i = 0; i < adev->uvd.num_uvd_inst; ++i) {
+ if (adev->uvd.harvest_config & (1 << i))
+ continue;
/* force RBC into idle state */
WREG32_SOC15(UVD, i, mmUVD_RBC_RB_CNTL, 0x11010101);
@@ -1756,6 +1800,8 @@ static void uvd_v7_0_set_ring_funcs(struct amdgpu_device *adev)
int i;
for (i = 0; i < adev->uvd.num_uvd_inst; i++) {
+ if (adev->uvd.harvest_config & (1 << i))
+ continue;
adev->uvd.inst[i].ring.funcs = &uvd_v7_0_ring_vm_funcs;
adev->uvd.inst[i].ring.me = i;
DRM_INFO("UVD(%d) is enabled in VM mode\n", i);
@@ -1767,6 +1813,8 @@ static void uvd_v7_0_set_enc_ring_funcs(struct amdgpu_device *adev)
int i, j;
for (j = 0; j < adev->uvd.num_uvd_inst; j++) {
+ if (adev->uvd.harvest_config & (1 << j))
+ continue;
for (i = 0; i < adev->uvd.num_enc_rings; ++i) {
adev->uvd.inst[j].ring_enc[i].funcs = &uvd_v7_0_enc_ring_vm_funcs;
adev->uvd.inst[j].ring_enc[i].me = j;
@@ -1786,6 +1834,8 @@ static void uvd_v7_0_set_irq_funcs(struct amdgpu_device *adev)
int i;
for (i = 0; i < adev->uvd.num_uvd_inst; i++) {
+ if (adev->uvd.harvest_config & (1 << i))
+ continue;
adev->uvd.inst[i].irq.num_types = adev->uvd.num_enc_rings + 1;
adev->uvd.inst[i].irq.funcs = &uvd_v7_0_irq_funcs;
}
--
2.13.6
_______________________________________________
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx
^ permalink raw reply related
* Re: [PATCH] mm: thp: remove use_zero_page sysfs knob
From: Yang Shi @ 2018-07-23 21:52 UTC (permalink / raw)
To: David Rientjes
Cc: Kirill A. Shutemov, hughd, aaron.lu, akpm, linux-mm, linux-kernel
In-Reply-To: <alpine.DEB.2.21.1807231329080.105582@chino.kir.corp.google.com>
On 7/23/18 1:31 PM, David Rientjes wrote:
> On Fri, 20 Jul 2018, Yang Shi wrote:
>
>> I agree to keep it for a while to let that security bug cool down, however, if
>> there is no user anymore, it sounds pointless to still keep a dead knob.
>>
> It's not a dead knob. We use it, and for reasons other than
> CVE-2017-1000405. To mitigate the cost of constantly compacting memory to
> allocate it after it has been freed due to memry pressure, we can either
> continue to disable it, allow it to be persistently available, or use a
> new value for use_zero_page to specify it should be persistently
> available.
My understanding is the cost of memory compaction is *not* unique for
huge zero page, right? It is expected when memory pressure is met, even
though huge zero page is disabled.
^ permalink raw reply
* Re: Documentation update wrt pci_release_regions()?
From: Bjorn Helgaas @ 2018-07-23 20:50 UTC (permalink / raw)
To: Andy Shevchenko; +Cc: Bjorn Helgaas, linux-pci
In-Reply-To: <e024134239091caf9684073887466df073ab1363.camel@linux.intel.com>
On Mon, Jul 23, 2018 at 01:36:43PM +0300, Andy Shevchenko wrote:
> Hi!
>
> At some point I have stumbled over [1] which has a rightful confusion.
> I tried to go through documentation we have and have no idea is that
> behaviour have been fixed or not and if yes, in which kernel version.
>
> Can we submit a patch against documentation to clarify the status of it?
> Followup would be fix of hfi1 driver to drop confusion.
>
> [1]: https://stackoverflow.com/questions/51163832/linux-pci-driver-setup
> -and-teardown
I would love it if somebody posted a patch to clarify this. I don't
have time to research and formulate a patch right now, but if you want
to propose something, or open a bugzilla so we don't forget, that
would be great.
The first fix would be to change the reference to
pci_request_regions(), which doesn't exist.
^ permalink raw reply
* [PATCH v2 0/2] clk: qcom: Quad SPI (qspi) clock support for sdm845
From: Douglas Anderson @ 2018-07-23 21:54 UTC (permalink / raw)
To: sboyd, andy.gross
Cc: tdas, grahamr, girishm, anischal, bjorn.andersson,
Douglas Anderson, devicetree, Michael Turquette, linux-arm-msm,
linux-kernel, David Brown, Rob Herring, Mark Rutland, linux-soc,
linux-clk
This two-series patch adds the needed clock bits to use the Quad SPI
(qspi) part on sdm845. It's expected that the bindings part of this
patch could land in the clock tree with an immutable git hash and then
be pulled into the Qualcomm tree so it could be used by dts files.
>From the reply to my v1, the clock plan for this clock is:
- MinSVS@19.2
- LowSVS@75
- SVS@150
- Nominal@300
...and intermediate frequencies can be used at frequences less than
300. I didn't see a need for 75 MHz and it was unclear from previous
replies if this should come from MAIN or EVEN so I left it out. I
have added 100 MHz here since it is useful (/ 4 = 25 MHz is a useful
clock for SPI flash)
OTHER NOTES:
- From probing lines, it appears that the Quad SPI block has a divide
by 4 somewhere inside it (probably so it can oversample the lines,
or possibly so it can generate phase-offset clocks). Thus we need
the core to go 4 times faster than we'd expect to run the SPI bus.
- SPI devices usually specify the MAX frequency they should be clocked
at, so it's important that we use the clk_rcg2_floor_ops here rather
than the clk_rcg2_ops
Changes in v2:
- Only 19.2, 100, 150, and 300 MHz now.
- All clocks come from MAIN rather than EVEN.
- Use parent map 0 instead of new parent map 9.
Douglas Anderson (2):
clk: qcom: Add qspi (Quad SPI) clock defines for sdm845 to header
clk: qcom: Add qspi (Quad SPI) clocks for sdm845
drivers/clk/qcom/gcc-sdm845.c | 63 +++++++++++++++++++++
include/dt-bindings/clock/qcom,gcc-sdm845.h | 3 +
2 files changed, 66 insertions(+)
--
2.18.0.233.g985f88cf7e-goog
^ permalink raw reply
* [PATCH v2 1/2] clk: qcom: Add qspi (Quad SPI) clock defines for sdm845 to header
From: Douglas Anderson @ 2018-07-23 21:54 UTC (permalink / raw)
To: sboyd, andy.gross
Cc: tdas, grahamr, girishm, anischal, bjorn.andersson,
Douglas Anderson, devicetree, linux-kernel, Rob Herring,
Mark Rutland
In-Reply-To: <20180723215404.74296-1-dianders@chromium.org>
These clocks will need to be defined in the clock driver and
referenced in device tree files.
Signed-off-by: Douglas Anderson <dianders@chromium.org>
---
Changes in v2: None
include/dt-bindings/clock/qcom,gcc-sdm845.h | 3 +++
1 file changed, 3 insertions(+)
diff --git a/include/dt-bindings/clock/qcom,gcc-sdm845.h b/include/dt-bindings/clock/qcom,gcc-sdm845.h
index f96fc2dbf60e..b8eae5a76503 100644
--- a/include/dt-bindings/clock/qcom,gcc-sdm845.h
+++ b/include/dt-bindings/clock/qcom,gcc-sdm845.h
@@ -194,6 +194,9 @@
#define GPLL4 184
#define GCC_CPUSS_DVM_BUS_CLK 185
#define GCC_CPUSS_GNOC_CLK 186
+#define GCC_QSPI_CORE_CLK_SRC 187
+#define GCC_QSPI_CORE_CLK 188
+#define GCC_QSPI_CNOC_PERIPH_AHB_CLK 189
/* GCC Resets */
#define GCC_MMSS_BCR 0
--
2.18.0.233.g985f88cf7e-goog
^ permalink raw reply related
* [PATCH v2 2/2] clk: qcom: Add qspi (Quad SPI) clocks for sdm845
From: Douglas Anderson @ 2018-07-23 21:54 UTC (permalink / raw)
To: sboyd, andy.gross
Cc: tdas, grahamr, girishm, anischal, bjorn.andersson,
Douglas Anderson, Michael Turquette, linux-arm-msm, linux-kernel,
David Brown, linux-soc, linux-clk
In-Reply-To: <20180723215404.74296-1-dianders@chromium.org>
Add both the interface and core clock.
Signed-off-by: Douglas Anderson <dianders@chromium.org>
---
Changes in v2:
- Only 19.2, 100, 150, and 300 MHz now.
- All clocks come from MAIN rather than EVEN.
- Use parent map 0 instead of new parent map 9.
drivers/clk/qcom/gcc-sdm845.c | 63 +++++++++++++++++++++++++++++++++++
1 file changed, 63 insertions(+)
diff --git a/drivers/clk/qcom/gcc-sdm845.c b/drivers/clk/qcom/gcc-sdm845.c
index 0f694ed4238a..5bca634e277a 100644
--- a/drivers/clk/qcom/gcc-sdm845.c
+++ b/drivers/clk/qcom/gcc-sdm845.c
@@ -162,6 +162,13 @@ static const char * const gcc_parent_names_10[] = {
"core_bi_pll_test_se",
};
+static const char * const gcc_parent_names_9[] = {
+ "bi_tcxo",
+ "gpll0",
+ "gpll0_out_even",
+ "core_pi_sleep_clk",
+};
+
static struct clk_alpha_pll gpll0 = {
.offset = 0x0,
.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_FABIA],
@@ -358,6 +365,28 @@ static struct clk_rcg2 gcc_pcie_phy_refgen_clk_src = {
},
};
+static const struct freq_tbl ftbl_gcc_qspi_core_clk_src[] = {
+ F(19200000, P_BI_TCXO, 1, 0, 0),
+ F(100000000, P_GPLL0_OUT_MAIN, 6, 0, 0),
+ F(150000000, P_GPLL0_OUT_MAIN, 4, 0, 0),
+ F(300000000, P_GPLL0_OUT_MAIN, 2, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 gcc_qspi_core_clk_src = {
+ .cmd_rcgr = 0x4b008,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_0,
+ .freq_tbl = ftbl_gcc_qspi_core_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "gcc_qspi_core_clk_src",
+ .parent_names = gcc_parent_names_9,
+ .num_parents = 4,
+ .ops = &clk_rcg2_floor_ops,
+ },
+};
+
static const struct freq_tbl ftbl_gcc_pdm2_clk_src[] = {
F(9600000, P_BI_TCXO, 2, 0, 0),
F(19200000, P_BI_TCXO, 1, 0, 0),
@@ -1935,6 +1964,37 @@ static struct clk_branch gcc_qmip_video_ahb_clk = {
},
};
+static struct clk_branch gcc_qspi_cnoc_periph_ahb_clk = {
+ .halt_reg = 0x4b000,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x4b000,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_qspi_cnoc_periph_ahb_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qspi_core_clk = {
+ .halt_reg = 0x4b004,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x4b004,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_qspi_core_clk",
+ .parent_names = (const char *[]){
+ "gcc_qspi_core_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
static struct clk_branch gcc_qupv3_wrap0_s0_clk = {
.halt_reg = 0x17030,
.halt_check = BRANCH_HALT_VOTED,
@@ -3383,6 +3443,9 @@ static struct clk_regmap *gcc_sdm845_clocks[] = {
[GPLL4] = &gpll4.clkr,
[GCC_CPUSS_DVM_BUS_CLK] = &gcc_cpuss_dvm_bus_clk.clkr,
[GCC_CPUSS_GNOC_CLK] = &gcc_cpuss_gnoc_clk.clkr,
+ [GCC_QSPI_CORE_CLK_SRC] = &gcc_qspi_core_clk_src.clkr,
+ [GCC_QSPI_CORE_CLK] = &gcc_qspi_core_clk.clkr,
+ [GCC_QSPI_CNOC_PERIPH_AHB_CLK] = &gcc_qspi_cnoc_periph_ahb_clk.clkr,
};
static const struct qcom_reset_map gcc_sdm845_resets[] = {
--
2.18.0.233.g985f88cf7e-goog
^ permalink raw reply related
* [PATCH v2 0/2] clk: qcom: Quad SPI (qspi) clock support for sdm845
From: Douglas Anderson @ 2018-07-23 21:54 UTC (permalink / raw)
To: sboyd, andy.gross
Cc: tdas, grahamr, girishm, anischal, bjorn.andersson,
Douglas Anderson, devicetree, Michael Turquette, linux-arm-msm,
linux-kernel, David Brown, Rob Herring, Mark Rutland, linux-soc,
linux-clk
This two-series patch adds the needed clock bits to use the Quad SPI
(qspi) part on sdm845. It's expected that the bindings part of this
patch could land in the clock tree with an immutable git hash and then
be pulled into the Qualcomm tree so it could be used by dts files.
From the reply to my v1, the clock plan for this clock is:
- MinSVS@19.2
- LowSVS@75
- SVS@150
- Nominal@300
...and intermediate frequencies can be used at frequences less than
300. I didn't see a need for 75 MHz and it was unclear from previous
replies if this should come from MAIN or EVEN so I left it out. I
have added 100 MHz here since it is useful (/ 4 = 25 MHz is a useful
clock for SPI flash)
OTHER NOTES:
- From probing lines, it appears that the Quad SPI block has a divide
by 4 somewhere inside it (probably so it can oversample the lines,
or possibly so it can generate phase-offset clocks). Thus we need
the core to go 4 times faster than we'd expect to run the SPI bus.
- SPI devices usually specify the MAX frequency they should be clocked
at, so it's important that we use the clk_rcg2_floor_ops here rather
than the clk_rcg2_ops
Changes in v2:
- Only 19.2, 100, 150, and 300 MHz now.
- All clocks come from MAIN rather than EVEN.
- Use parent map 0 instead of new parent map 9.
Douglas Anderson (2):
clk: qcom: Add qspi (Quad SPI) clock defines for sdm845 to header
clk: qcom: Add qspi (Quad SPI) clocks for sdm845
drivers/clk/qcom/gcc-sdm845.c | 63 +++++++++++++++++++++
include/dt-bindings/clock/qcom,gcc-sdm845.h | 3 +
2 files changed, 66 insertions(+)
--
2.18.0.233.g985f88cf7e-goog
^ permalink raw reply
* Re: [PATCH iproute2] devlink: CTRL_ATTR_FAMILY_ID is a u16
From: Stephen Hemminger @ 2018-07-23 20:51 UTC (permalink / raw)
To: dsahern; +Cc: netdev, jiri, David Ahern
In-Reply-To: <20180720163526.756-1-dsahern@kernel.org>
On Fri, 20 Jul 2018 09:35:26 -0700
dsahern@kernel.org wrote:
> From: David Ahern <dsahern@gmail.com>
>
> CTRL_ATTR_FAMILY_ID is a u16, not a u32. Update devlink accordingly.
>
> Fixes: a3c4b484a1edd ("add devlink tool")
> Signed-off-by: David Ahern <dsahern@gmail.com>
Applied
^ permalink raw reply
* Re: [PATCH v2 10/15] xfs: use internal dfops in attr code
From: Bill O'Donnell @ 2018-07-23 20:51 UTC (permalink / raw)
To: Brian Foster; +Cc: linux-xfs
In-Reply-To: <20180723130414.47980-11-bfoster@redhat.com>
On Mon, Jul 23, 2018 at 09:04:09AM -0400, Brian Foster wrote:
> Remove the unnecessary on-stack dfops structure and use the internal
> transaction dfops instead. The lower level xattr code already
> appropriately accesses ->t_dfops throughout.
>
> Signed-off-by: Brian Foster <bfoster@redhat.com>
Looks good.
Reviewed-by: Bill O'Donnell <billodo@redhat.com>
> ---
> fs/xfs/libxfs/xfs_attr.c | 16 +++++-----------
> 1 file changed, 5 insertions(+), 11 deletions(-)
>
> diff --git a/fs/xfs/libxfs/xfs_attr.c b/fs/xfs/libxfs/xfs_attr.c
> index 927d4c968f9a..66a22c80a0db 100644
> --- a/fs/xfs/libxfs/xfs_attr.c
> +++ b/fs/xfs/libxfs/xfs_attr.c
> @@ -202,7 +202,6 @@ xfs_attr_set(
> struct xfs_mount *mp = dp->i_mount;
> struct xfs_buf *leaf_bp = NULL;
> struct xfs_da_args args;
> - struct xfs_defer_ops dfops;
> struct xfs_trans_res tres;
> int rsvd = (flags & ATTR_ROOT) != 0;
> int error, err2, local;
> @@ -251,7 +250,6 @@ xfs_attr_set(
> rsvd ? XFS_TRANS_RESERVE : 0, &args.trans);
> if (error)
> return error;
> - xfs_defer_init(args.trans, &dfops);
>
> xfs_ilock(dp, XFS_ILOCK_EXCL);
> error = xfs_trans_reserve_quota_nblks(args.trans, dp, args.total, 0,
> @@ -315,18 +313,18 @@ xfs_attr_set(
> */
> error = xfs_attr_shortform_to_leaf(&args, &leaf_bp);
> if (error)
> - goto out_defer_cancel;
> + goto out;
> /*
> * Prevent the leaf buffer from being unlocked so that a
> * concurrent AIL push cannot grab the half-baked leaf
> * buffer and run into problems with the write verifier.
> */
> xfs_trans_bhold(args.trans, leaf_bp);
> - xfs_defer_bjoin(&dfops, leaf_bp);
> - xfs_defer_ijoin(&dfops, dp);
> - error = xfs_defer_finish(&args.trans, &dfops);
> + xfs_defer_bjoin(args.trans->t_dfops, leaf_bp);
> + xfs_defer_ijoin(args.trans->t_dfops, dp);
> + error = xfs_defer_finish(&args.trans, args.trans->t_dfops);
> if (error)
> - goto out_defer_cancel;
> + goto out;
>
> /*
> * Commit the leaf transformation. We'll need another (linked)
> @@ -366,8 +364,6 @@ xfs_attr_set(
>
> return error;
>
> -out_defer_cancel:
> - xfs_defer_cancel(&dfops);
> out:
> if (leaf_bp)
> xfs_trans_brelse(args.trans, leaf_bp);
> @@ -389,7 +385,6 @@ xfs_attr_remove(
> {
> struct xfs_mount *mp = dp->i_mount;
> struct xfs_da_args args;
> - struct xfs_defer_ops dfops;
> int error;
>
> XFS_STATS_INC(mp, xs_attr_remove);
> @@ -422,7 +417,6 @@ xfs_attr_remove(
> &args.trans);
> if (error)
> return error;
> - xfs_defer_init(args.trans, &dfops);
>
> xfs_ilock(dp, XFS_ILOCK_EXCL);
> /*
> --
> 2.17.1
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-xfs" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH] Drivers: Xen: xlate_mmu.c: Fixed comment layout
From: Randy Dunlap @ 2018-07-23 21:55 UTC (permalink / raw)
To: Mark Railton; +Cc: jgross, xen-devel, boris.ostrovsky, linux-kernel
In-Reply-To: <20180723214804.GA21761@ZeroCool>
On 07/23/2018 02:48 PM, Mark Railton wrote:
> On Mon, Jul 23, 2018 at 02:44:28PM -0700, Randy Dunlap wrote:
>> On 07/23/2018 02:40 PM, Mark Railton wrote:
>>> On Mon, Jul 23, 2018 at 02:38:20PM -0700, Randy Dunlap wrote:
>>>> On 07/23/2018 02:34 PM, Mark Railton wrote:
>>>>> Fixed issue with multi line comment
>>>>
>>>> Fix [not Fixed]
>>>>
>>>>>
>>>>> Signed-off-by: Mark Railton <mark@markrailton.com>
>>>>> ---
>>>>> drivers/xen/xlate_mmu.c | 5 +++--
>>>>> 1 file changed, 3 insertions(+), 2 deletions(-)
>>>>>
>>>>> diff --git a/drivers/xen/xlate_mmu.c b/drivers/xen/xlate_mmu.c
>>>>> index 23f1387b3ef7..3b03bc1641ed 100644
>>>>> --- a/drivers/xen/xlate_mmu.c
>>>>> +++ b/drivers/xen/xlate_mmu.c
>>>>> @@ -151,8 +151,9 @@ int xen_xlate_remap_gfn_array(struct vm_area_struct *vma,
>>>>> struct remap_data data;
>>>>> unsigned long range = DIV_ROUND_UP(nr, XEN_PFN_PER_PAGE) << PAGE_SHIFT;
>>>>>
>>>>> - /* Kept here for the purpose of making sure code doesn't break
>>>>> - x86 PVOPS */
>>>>> + /* Kept here for the purpose of making sure code doesn't
>>>>> + * break x86 PVOPS
>>>>> + */
>>>>
>>>> That is still not the preferred kernel multi-line comment style.
>>>> Documentation/process/coding-style.rst says:
>>>>
>>>> /*
>>>> * This is the preferred style for multi-line
>>>> * comments in the Linux kernel source code.
>>>> * Please use it consistently.
>>>> *
>>>> * Description: A column of asterisks on the left side,
>>>> * with beginning and ending almost-blank lines.
>>>> */
>>>>
>>>> although Networking code has a slightly different preferred style (as in
>>>> your patch).
>>>>
>>>>> BUG_ON(!((vma->vm_flags & (VM_PFNMAP | VM_IO)) == (VM_PFNMAP | VM_IO)));
>>>>>
>>>>> data.fgfn = gfn;
>>>>>
>>>>
>>>>
>>>> --
>>>> ~Randy
>>>
>>> Thank's for the feedback, I'll get that updated now.
>>>
>>> I'm still kinda new to this, I assume I need to send the new patch via
>>> git send-email?
>>
>> That is one option. Use whatever works for you.
>>
>> There are several email clients that also work well.
>> See Documentation/process/email-clients.rst.
>>
>>
>> --
>> ~Randy
>
> From 57c8104d2a30020005be16df2ca69ed66f6c4ae9 Mon Sep 17 00:00:00 2001
> From: Mark Railton <mark@markrailton.com>
> Date: Mon, 23 Jul 2018 22:28:53 +0100
> Subject: [PATCH] Drivers: Xen: xlate_mmu.c: Fixed comment layout
>
> Fixed issue with multi line comment
>
> Signed-off-by: Mark Railton <mark@markrailton.com>
> ---
> drivers/xen/xlate_mmu.c | 6 ++++--
> 1 file changed, 4 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/xen/xlate_mmu.c b/drivers/xen/xlate_mmu.c
> index 23f1387b3ef7..2b77c79f8ce7 100644
> --- a/drivers/xen/xlate_mmu.c
> +++ b/drivers/xen/xlate_mmu.c
> @@ -151,8 +151,10 @@ int xen_xlate_remap_gfn_array(struct vm_area_struct *vma,
> struct remap_data data;
> unsigned long range = DIV_ROUND_UP(nr, XEN_PFN_PER_PAGE) << PAGE_SHIFT;
>
> - /* Kept here for the purpose of making sure code doesn't break
> - x86 PVOPS */
> + /*
> + * Kept here for the purpose of making sure code doesn't
> + * break x86 PVOPS
> + */
> BUG_ON(!((vma->vm_flags & (VM_PFNMAP | VM_IO)) == (VM_PFNMAP | VM_IO)));
>
> data.fgfn = gfn;
> --
> 2.17.1
Hi,
a. The subject and the patch description should be in present tense, i.e.,
Fix instead of Fixed.
b. Ideally you start a new email thread for new versions of a patch (but Cc:
the interested parties).
For the patch itself:
Acked-by: Randy Dunlap <rdunlap@infradead.org>
Thanks.
--
~Randy
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel
^ permalink raw reply
* Re: [PATCH] Drivers: Xen: xlate_mmu.c: Fixed comment layout
From: Randy Dunlap @ 2018-07-23 21:55 UTC (permalink / raw)
To: Mark Railton; +Cc: boris.ostrovsky, jgross, xen-devel, linux-kernel
In-Reply-To: <20180723214804.GA21761@ZeroCool>
On 07/23/2018 02:48 PM, Mark Railton wrote:
> On Mon, Jul 23, 2018 at 02:44:28PM -0700, Randy Dunlap wrote:
>> On 07/23/2018 02:40 PM, Mark Railton wrote:
>>> On Mon, Jul 23, 2018 at 02:38:20PM -0700, Randy Dunlap wrote:
>>>> On 07/23/2018 02:34 PM, Mark Railton wrote:
>>>>> Fixed issue with multi line comment
>>>>
>>>> Fix [not Fixed]
>>>>
>>>>>
>>>>> Signed-off-by: Mark Railton <mark@markrailton.com>
>>>>> ---
>>>>> drivers/xen/xlate_mmu.c | 5 +++--
>>>>> 1 file changed, 3 insertions(+), 2 deletions(-)
>>>>>
>>>>> diff --git a/drivers/xen/xlate_mmu.c b/drivers/xen/xlate_mmu.c
>>>>> index 23f1387b3ef7..3b03bc1641ed 100644
>>>>> --- a/drivers/xen/xlate_mmu.c
>>>>> +++ b/drivers/xen/xlate_mmu.c
>>>>> @@ -151,8 +151,9 @@ int xen_xlate_remap_gfn_array(struct vm_area_struct *vma,
>>>>> struct remap_data data;
>>>>> unsigned long range = DIV_ROUND_UP(nr, XEN_PFN_PER_PAGE) << PAGE_SHIFT;
>>>>>
>>>>> - /* Kept here for the purpose of making sure code doesn't break
>>>>> - x86 PVOPS */
>>>>> + /* Kept here for the purpose of making sure code doesn't
>>>>> + * break x86 PVOPS
>>>>> + */
>>>>
>>>> That is still not the preferred kernel multi-line comment style.
>>>> Documentation/process/coding-style.rst says:
>>>>
>>>> /*
>>>> * This is the preferred style for multi-line
>>>> * comments in the Linux kernel source code.
>>>> * Please use it consistently.
>>>> *
>>>> * Description: A column of asterisks on the left side,
>>>> * with beginning and ending almost-blank lines.
>>>> */
>>>>
>>>> although Networking code has a slightly different preferred style (as in
>>>> your patch).
>>>>
>>>>> BUG_ON(!((vma->vm_flags & (VM_PFNMAP | VM_IO)) == (VM_PFNMAP | VM_IO)));
>>>>>
>>>>> data.fgfn = gfn;
>>>>>
>>>>
>>>>
>>>> --
>>>> ~Randy
>>>
>>> Thank's for the feedback, I'll get that updated now.
>>>
>>> I'm still kinda new to this, I assume I need to send the new patch via
>>> git send-email?
>>
>> That is one option. Use whatever works for you.
>>
>> There are several email clients that also work well.
>> See Documentation/process/email-clients.rst.
>>
>>
>> --
>> ~Randy
>
> From 57c8104d2a30020005be16df2ca69ed66f6c4ae9 Mon Sep 17 00:00:00 2001
> From: Mark Railton <mark@markrailton.com>
> Date: Mon, 23 Jul 2018 22:28:53 +0100
> Subject: [PATCH] Drivers: Xen: xlate_mmu.c: Fixed comment layout
>
> Fixed issue with multi line comment
>
> Signed-off-by: Mark Railton <mark@markrailton.com>
> ---
> drivers/xen/xlate_mmu.c | 6 ++++--
> 1 file changed, 4 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/xen/xlate_mmu.c b/drivers/xen/xlate_mmu.c
> index 23f1387b3ef7..2b77c79f8ce7 100644
> --- a/drivers/xen/xlate_mmu.c
> +++ b/drivers/xen/xlate_mmu.c
> @@ -151,8 +151,10 @@ int xen_xlate_remap_gfn_array(struct vm_area_struct *vma,
> struct remap_data data;
> unsigned long range = DIV_ROUND_UP(nr, XEN_PFN_PER_PAGE) << PAGE_SHIFT;
>
> - /* Kept here for the purpose of making sure code doesn't break
> - x86 PVOPS */
> + /*
> + * Kept here for the purpose of making sure code doesn't
> + * break x86 PVOPS
> + */
> BUG_ON(!((vma->vm_flags & (VM_PFNMAP | VM_IO)) == (VM_PFNMAP | VM_IO)));
>
> data.fgfn = gfn;
> --
> 2.17.1
Hi,
a. The subject and the patch description should be in present tense, i.e.,
Fix instead of Fixed.
b. Ideally you start a new email thread for new versions of a patch (but Cc:
the interested parties).
For the patch itself:
Acked-by: Randy Dunlap <rdunlap@infradead.org>
Thanks.
--
~Randy
^ permalink raw reply
* Re: [PATCH RFC] debugobjects: Make stack check warning more informative
From: Yang Shi @ 2018-07-23 21:54 UTC (permalink / raw)
To: Joel Fernandes, linux-kernel
Cc: kernel-team, Thomas Gleixner, Waiman Long, Arnd Bergmann,
astrachan
In-Reply-To: <20180723212531.202328-1-joel@joelfernandes.org>
On 7/23/18 2:25 PM, Joel Fernandes wrote:
> From: "Joel Fernandes (Google)" <joel@joelfernandes.org>
>
> Recently we debugged an issue where debugobject tracking was telling
> us of an annotation issue. Turns out the issue was due to the object in
> concern being on a different stack which was due to another issue.
>
> Discussing with tglx, he suggested printing the pointers and the
> location of the stack for the currently running task. This helped find
> the object was on the wrong stack. I turned the resulting patch into
> something upstreamable, so that the error message is more informative
> and can help in debugging for similar issues in the future.
Acked-by: Yang Shi <yang.shi@linux.alibaba.com>
>
> Signed-off-by: Joel Fernandes (Google) <joel@joelfernandes.org>
> ---
> lib/debugobjects.c | 7 +++++--
> 1 file changed, 5 insertions(+), 2 deletions(-)
>
> diff --git a/lib/debugobjects.c b/lib/debugobjects.c
> index 994be4805cec..24c1df0d7466 100644
> --- a/lib/debugobjects.c
> +++ b/lib/debugobjects.c
> @@ -360,9 +360,12 @@ static void debug_object_is_on_stack(void *addr, int onstack)
>
> limit++;
> if (is_on_stack)
> - pr_warn("object is on stack, but not annotated\n");
> + pr_warn("object %p is on stack %p, but NOT annotated.\n", addr,
> + task_stack_page(current));
> else
> - pr_warn("object is not on stack, but annotated\n");
> + pr_warn("object %p is NOT on stack %p, but annotated.\n", addr,
> + task_stack_page(current));
> +
> WARN_ON(1);
> }
>
^ permalink raw reply
* Re: [EXTERNAL] [rocko/master][PATCHv2] tidl-utils: SRCREV bump
From: Jacob Stiffler @ 2018-07-23 21:55 UTC (permalink / raw)
To: Djordje Senicic, meta-arago; +Cc: d-senicic1
In-Reply-To: <1532375688-4054-1-git-send-email-x0157990@ti.com>
Denys,
Can you please apply this to the ti2018.01 branch?
Thank you,
Jake
On 7/23/2018 3:54 PM, Djordje Senicic wrote:
> * Get new version of tidl-utils configuration files with fixed path
> * RDEPENDS is not needed for x86 target, as executables are statically linked
>
> Signed-off-by: Djordje Senicic <x0157990@ti.com>
> ---
> meta-arago-extras/recipes-ti/tidl-utils/tidl-utils.bb | 4 ++--
> 1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/meta-arago-extras/recipes-ti/tidl-utils/tidl-utils.bb b/meta-arago-extras/recipes-ti/tidl-utils/tidl-utils.bb
> index 264b030..569de5a 100644
> --- a/meta-arago-extras/recipes-ti/tidl-utils/tidl-utils.bb
> +++ b/meta-arago-extras/recipes-ti/tidl-utils/tidl-utils.bb
> @@ -8,10 +8,10 @@ INC_PR = "r0"
>
> LIC_FILES_CHKSUM = "file://docs/LICENSE.txt;md5=a93aa5af7a3bbbb6fb34c8df59efaa5c"
>
> -RDEPENDS_${PN} += " tidl-api tidl-examples "
> +RDEPENDS_${PN}_class-target += " tidl-api tidl-examples "
>
> SRC_URI = "git://git.ti.com/tidl/tidl-utils.git;protocol=git;branch=master"
> -SRCREV = "93f66d2c53960b13b7e7f20208ee205f727aaf28"
> +SRCREV = "994d90ae583610673d9d39086ca5e84027a9c56e"
>
> PR = "${INC_PR}.0"
>
^ permalink raw reply
* Re: HID: intel_ish-hid: tx_buf memory leak on probe/remove
From: Srinivas Pandruvada @ 2018-07-23 21:55 UTC (permalink / raw)
To: Anton Vasilyev
Cc: Jiri Kosina, Benjamin Tissoires, Even Xu, linux-input,
linux-kernel, ldv-project
In-Reply-To: <a0faf8a7-17ea-0ed3-5bb5-f1e8fb5debf6@ispras.ru>
On Mon, 2018-07-23 at 20:56 +0300, Anton Vasilyev wrote:
> ish_dev_init() allocates 512*176 bytes memory for tx_buf and stores
> it at
> &dev->wr_free_list_head.link list on ish_probe().
> But there is no deallocation of this memory in ish_remove() and in
> ish_probe()
> error path.
> So current intel-ish-ipc provides 88 KB memory leak for each
> probe/release.
>
> I have two ideas 1) to replace kzalloc allocation by devm_kzalloc,
Thanks for finding this. We can replace both alloc in this function
with devm_ calls. Once you have a patch I can test.
Thanks,
Srinivas
> or 2) release memory stored at &dev->wr_free_list_head.link list
> (and
> may be at
> &dev->wr_processing_list_head.link) in all driver exits.
>
> But I do not know which way is preferable for this case.
>
> Found by Linux Driver Verification project (linuxtesting.org).
>
> --
> Anton Vasilyev
> Linux Verification Center, ISPRAS
> web: http://linuxtesting.org
> e-mail: vasilyev@ispras.ru
^ permalink raw reply
* Re: [PATCH 0/3] PTI for x86-32 Fixes and Updates
From: Pavel Machek @ 2018-07-23 21:55 UTC (permalink / raw)
To: Andy Lutomirski
Cc: Linus Torvalds, Joerg Roedel, Thomas Gleixner, Ingo Molnar,
Peter Anvin, the arch/x86 maintainers, Linux Kernel Mailing List,
linux-mm, Andrew Lutomirski, Dave Hansen, Josh Poimboeuf,
Jürgen Groß, Peter Zijlstra, Borislav Petkov,
Jiri Kosina, Boris Ostrovsky, Brian Gerst, David Laight,
Denys Vlasenko, Eduardo Valentin, Greg Kroah-Hartman, Will Deacon,
Liguori, Anthony, Daniel Gruss, Hugh Dickins, Kees Cook,
Andrea Arcangeli, Waiman Long, David H . Gutteridge, Joerg Roedel,
Arnaldo Carvalho de Melo, Alexander Shishkin, Jiri Olsa,
Namhyung Kim
In-Reply-To: <39A1C149-DA03-46D1-801F-0205DCD69A36@amacapital.net>
[-- Attachment #1: Type: text/plain, Size: 1112 bytes --]
Hi!
> > What I want is "if A can ptrace B, and B has pti disabled, A can have
> > pti disabled as well". Now.. I see someone may want to have it
> > per-thread, because for stuff like javascript JIT, thread may have
> > rights to call ptrace, but is unable to call ptrace because JIT
> > removed that ability... hmm...
>
> No, you don’t want that. The problem is that Meltdown isn’t a problem that exists in isolation. It’s very plausible that JavaScript code could trigger a speculation attack that, with PTI off, could read kernel memory.
Yeah, the web browser threads that run javascript code should have PTI
on. But maybe I want the rest of web browser with PTI off.
So... yes, I see why someone may want it per-thread (and not
per-process).
I guess per-process would be good enough for me. Actually, maybe even
per-uid. I don't have any fancy security here, so anything running uid
0 and 1000 is close enough to trusted.
Pavel
--
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 181 bytes --]
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.