All the mail mirrored from lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 0/2] i2c_imc: New driver, at long last
@ 2015-03-09 20:55 ` Andy Lutomirski
  0 siblings, 0 replies; 10+ messages in thread
From: Andy Lutomirski @ 2015-03-09 20:55 UTC (permalink / raw)
  To: Wolfram Sang, linux-i2c, Jean Delvare, Guenter Roeck,
	linux-kernel
  Cc: Mauro Carvalho Chehab, Rui Wang, Tony Luck, One Thousand Gnomes,
	Alun Evans, Robert Elliott, Boaz Harrosh, Paul Bolle,
	Andy Lutomirski

This adds i2c_imc, a driver for the SMBUS lines on DIMM slots on modern
Intel server chips.  Conceptually, I like it a lot -- it's a driver for
a bus for which we know the exact topology a priori.  That means that we
can actually enumerate the things on the bus reasonably cleanly.

This driver is weird, but I don't think that merging it will cause
problems, and I believe that there are Real Users (tm) of this driver.

It has two caveats.

Big caveat: Lots of things like to touch this bus, such as a BMC, the
memory controller power management stuff, and maybe even SMM code.
Intel forgot to define a way to arbitrate between them, nor are the
SMBUS master regs designed to be poked by multiple things at once.  The
upshot is that loading this driver is generally unsafe.  The driver
takes some measures to detect contention for the registers and shut
itself down, but no one should rely on that.

My understanding is that there's work in ACPI land to define an
arbitration mechanism.  Once this happens, we can support it in this
driver.  In the mean time, this driver has actual users, and there are
motherboards specifically designed to be used with a driver like this.
(I have such a board, and you can even buy them on regular online
shopping sutes.)

Therefore, I added a module parameter called allow_unsafe_access.  If
unset, the driver will refuse to load with an informative message.  If
set, the driver will pr_warn and load.

Little caveat: This submission only supposts Sandy Bridge.  I'd rather
get it merged without Ivy Bridge and Haswell support and add them later
(should be easy) rather than trying to make the driver support all
possible hardware before merging it.

Changes from v1:
 - Fix checkpatch license nits.
 - Fix MODULE_LICENSE.
 - Add missing parentheses to macros.
 - Tidy up imc_wait_not_busy.
 - Clean up post-transaction-completion handling code.
 - Downgrade a bunch of message severities.
 - Misc checkpatch stuff.
 - Move select I2C_DIMM_BUS where it belongs.
 - Improve comments.

Changes from last year:
 - This is an updated resubmission after about a year of thumb
   twiddling.

Andy Lutomirski (2):
  i2c_imc: New driver for Intel's iMC, found on LGA2011 chips
  i2c, i2c_imc: Add DIMM bus code

 drivers/i2c/busses/Kconfig    |  22 ++
 drivers/i2c/busses/Makefile   |   5 +
 drivers/i2c/busses/dimm-bus.c | 107 ++++++++
 drivers/i2c/busses/i2c-imc.c  | 570 ++++++++++++++++++++++++++++++++++++++++++
 include/linux/i2c/dimm-bus.h  |  20 ++
 5 files changed, 724 insertions(+)
 create mode 100644 drivers/i2c/busses/dimm-bus.c
 create mode 100644 drivers/i2c/busses/i2c-imc.c
 create mode 100644 include/linux/i2c/dimm-bus.h

-- 
2.3.0


^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH v2 0/2] i2c_imc: New driver, at long last
@ 2015-03-09 20:55 ` Andy Lutomirski
  0 siblings, 0 replies; 10+ messages in thread
From: Andy Lutomirski @ 2015-03-09 20:55 UTC (permalink / raw)
  To: Wolfram Sang, linux-i2c-u79uwXL29TY76Z2rM5mHXA, Jean Delvare,
	Guenter Roeck, linux-kernel-u79uwXL29TY76Z2rM5mHXA
  Cc: Mauro Carvalho Chehab, Rui Wang, Tony Luck, One Thousand Gnomes,
	Alun Evans, Robert Elliott, Boaz Harrosh, Paul Bolle,
	Andy Lutomirski

This adds i2c_imc, a driver for the SMBUS lines on DIMM slots on modern
Intel server chips.  Conceptually, I like it a lot -- it's a driver for
a bus for which we know the exact topology a priori.  That means that we
can actually enumerate the things on the bus reasonably cleanly.

This driver is weird, but I don't think that merging it will cause
problems, and I believe that there are Real Users (tm) of this driver.

It has two caveats.

Big caveat: Lots of things like to touch this bus, such as a BMC, the
memory controller power management stuff, and maybe even SMM code.
Intel forgot to define a way to arbitrate between them, nor are the
SMBUS master regs designed to be poked by multiple things at once.  The
upshot is that loading this driver is generally unsafe.  The driver
takes some measures to detect contention for the registers and shut
itself down, but no one should rely on that.

My understanding is that there's work in ACPI land to define an
arbitration mechanism.  Once this happens, we can support it in this
driver.  In the mean time, this driver has actual users, and there are
motherboards specifically designed to be used with a driver like this.
(I have such a board, and you can even buy them on regular online
shopping sutes.)

Therefore, I added a module parameter called allow_unsafe_access.  If
unset, the driver will refuse to load with an informative message.  If
set, the driver will pr_warn and load.

Little caveat: This submission only supposts Sandy Bridge.  I'd rather
get it merged without Ivy Bridge and Haswell support and add them later
(should be easy) rather than trying to make the driver support all
possible hardware before merging it.

Changes from v1:
 - Fix checkpatch license nits.
 - Fix MODULE_LICENSE.
 - Add missing parentheses to macros.
 - Tidy up imc_wait_not_busy.
 - Clean up post-transaction-completion handling code.
 - Downgrade a bunch of message severities.
 - Misc checkpatch stuff.
 - Move select I2C_DIMM_BUS where it belongs.
 - Improve comments.

Changes from last year:
 - This is an updated resubmission after about a year of thumb
   twiddling.

Andy Lutomirski (2):
  i2c_imc: New driver for Intel's iMC, found on LGA2011 chips
  i2c, i2c_imc: Add DIMM bus code

 drivers/i2c/busses/Kconfig    |  22 ++
 drivers/i2c/busses/Makefile   |   5 +
 drivers/i2c/busses/dimm-bus.c | 107 ++++++++
 drivers/i2c/busses/i2c-imc.c  | 570 ++++++++++++++++++++++++++++++++++++++++++
 include/linux/i2c/dimm-bus.h  |  20 ++
 5 files changed, 724 insertions(+)
 create mode 100644 drivers/i2c/busses/dimm-bus.c
 create mode 100644 drivers/i2c/busses/i2c-imc.c
 create mode 100644 include/linux/i2c/dimm-bus.h

-- 
2.3.0

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH v2 1/2] i2c_imc: New driver for Intel's iMC, found on LGA2011 chips
  2015-03-09 20:55 ` Andy Lutomirski
  (?)
@ 2015-03-09 20:55 ` Andy Lutomirski
  2015-03-14  4:14   ` Guenter Roeck
  -1 siblings, 1 reply; 10+ messages in thread
From: Andy Lutomirski @ 2015-03-09 20:55 UTC (permalink / raw)
  To: Wolfram Sang, linux-i2c, Jean Delvare, Guenter Roeck,
	linux-kernel
  Cc: Mauro Carvalho Chehab, Rui Wang, Tony Luck, One Thousand Gnomes,
	Alun Evans, Robert Elliott, Boaz Harrosh, Paul Bolle,
	Andy Lutomirski

Sandy Bridge Xeon and Extreme chips have integrated memory
controllers with (rather limited) onboard SMBUS masters.  This
driver gives access to the bus.

There are various groups working on standardizing a way to arbitrate
access to the bus between the OS, SMM firmware, a BMC, hardware
thermal control, etc.  In the mean time, running this driver is
unsafe except under special circumstances.  Nonetheless, this driver
has real users.

As a compromise, the driver will refuse to load unless
i2c_imc.allow_unsafe_access=Y.  When safe access becomes available,
we can leave this option as a way for legacy users to run the
driver, and we'll allow the driver to load by default if safe bus
access is available.

Signed-off-by: Andy Lutomirski <luto@amacapital.net>
---
 drivers/i2c/busses/Kconfig   |  17 ++
 drivers/i2c/busses/Makefile  |   1 +
 drivers/i2c/busses/i2c-imc.c | 567 +++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 585 insertions(+)
 create mode 100644 drivers/i2c/busses/i2c-imc.c

diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
index ab838d9e28b6..50e3d79122dd 100644
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -149,6 +149,23 @@ config I2C_ISMT
 	  This driver can also be built as a module.  If so, the module will be
 	  called i2c-ismt.
 
+config I2C_IMC
+	tristate "Intel iMC (LGA 2011) SMBus Controller"
+	depends on PCI && X86
+	help
+	  If you say yes to this option, support will be included for the Intel
+	  Integrated Memory Controller SMBus host controller interface.  This
+	  controller is found on LGA 2011 Xeons and Core i7 Extremes.
+
+	  There are currently no systems on which the kernel knows that it can
+	  safely enable this driver.  For now, you need to pass this driver a
+	  scary module parameter, and you should only pass that parameter if you
+	  have a special motherboard and know exactly what you are doing.
+	  Special motherboards include the Supermicro X9DRH-iF-NV.
+
+	  This driver can also be built as a module.  If so, the module will be
+	  called i2c-imc.
+
 config I2C_PIIX4
 	tristate "Intel PIIX4 and compatible (ATI/AMD/Serverworks/Broadcom/SMSC)"
 	depends on PCI
diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
index 56388f658d2f..4287c891e782 100644
--- a/drivers/i2c/busses/Makefile
+++ b/drivers/i2c/busses/Makefile
@@ -15,6 +15,7 @@ obj-$(CONFIG_I2C_AMD8111)	+= i2c-amd8111.o
 obj-$(CONFIG_I2C_I801)		+= i2c-i801.o
 obj-$(CONFIG_I2C_ISCH)		+= i2c-isch.o
 obj-$(CONFIG_I2C_ISMT)		+= i2c-ismt.o
+obj-$(CONFIG_I2C_IMC)		+= i2c-imc.o
 obj-$(CONFIG_I2C_NFORCE2)	+= i2c-nforce2.o
 obj-$(CONFIG_I2C_NFORCE2_S4985)	+= i2c-nforce2-s4985.o
 obj-$(CONFIG_I2C_PIIX4)		+= i2c-piix4.o
diff --git a/drivers/i2c/busses/i2c-imc.c b/drivers/i2c/busses/i2c-imc.c
new file mode 100644
index 000000000000..455d9243f10b
--- /dev/null
+++ b/drivers/i2c/busses/i2c-imc.c
@@ -0,0 +1,567 @@
+/*
+ * Copyright (c) 2013-2015 Andrew Lutomirski <luto@amacapital.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/pci.h>
+#include <linux/ratelimit.h>
+#include <linux/i2c.h>
+
+/*
+ * The datasheet can be found here, for example:
+ * http://www.intel.com/content/dam/www/public/us/en/documents/datasheets/xeon-e5-1600-2600-vol-2-datasheet.pdf
+ *
+ * There seem to be quite a few bugs or spec errors, though:
+ *
+ *  - A successful transaction sets WOD and RDO.
+ *
+ *  - The docs for TSOD_POLL_EN make no sense (see imc_channel_claim).
+ *
+ *  - Erratum BT109, which says:
+ *
+ *      The processor may not complete SMBus (System Management Bus)
+ *      transactions targeting the TSOD (Temperature Sensor On DIMM)
+ *      when Package C-States are enabled. Due to this erratum, if the
+ *      processor transitions into a Package C-State while an SMBus
+ *      transaction with the TSOD is in process, the processor will
+ *      suspend receipt of the transaction. The transaction completes
+ *      while the processor is in a Package C-State.  Upon exiting
+ *      Package C-State, the processor will attempt to resume the
+ *      SMBus transaction, detect a protocol violation, and log an
+ *      error.
+ *
+ *   The description notwithstanding, I've seen difficult-to-reproduce
+ *   issues when the system goes completely idle (so package C-states can
+ *   be entered) while software-initiated SMBUS transactions are in
+ *   progress.
+ */
+
+/* Register offsets (in PCI configuration space) */
+#define SMBSTAT(i)			(0x180 + 0x10*(i))
+#define SMBCMD(i)			(0x184 + 0x10*(i))
+#define SMBCNTL(i)			(0x188 + 0x10*(i))
+#define SMB_TSOD_POLL_RATE_CNTR(i)	(0x18C + 0x10*(i))
+#define SMB_TSOD_POLL_RATE		(0x1A8)
+
+/* SMBSTAT fields */
+#define SMBSTAT_RDO		(1U << 31)	/* Read Data Valid */
+#define SMBSTAT_WOD		(1U << 30)	/* Write Operation Done */
+#define SMBSTAT_SBE		(1U << 29)	/* SMBus Error */
+#define SMBSTAT_SMB_BUSY	(1U << 28)	/* SMBus Busy State */
+/* 26:24 is the last automatically polled TSOD address */
+#define SMBSTAT_RDATA_MASK	0xffff		/* result of a read */
+
+/* SMBCMD fields */
+#define SMBCMD_TRIGGER		(1U << 31)	/* CMD Trigger */
+#define SMBCMD_PNTR_SEL		(1U << 30)	/* HW polls TSOD with pointer */
+#define SMBCMD_WORD_ACCESS	(1U << 29)	/* word (vs byte) access */
+#define SMBCMD_TYPE_MASK	(3U << 27)	/* Mask for access type */
+#define  SMBCMD_TYPE_READ	(0U << 27)	/* Read */
+#define  SMBCMD_TYPE_WRITE	(1U << 27)	/* Write */
+#define  SMBCMD_TYPE_PNTR_WRITE	(3U << 27)	/* Write to pointer */
+#define SMBCMD_SA_MASK		(7U << 24)	/* Slave Address high bits */
+#define SMBCMD_SA_SHIFT		24
+#define SMBCMD_BA_MASK		0xff0000	/* Bus Txn address */
+#define SMBCMD_BA_SHIFT		16
+#define SMBCMD_WDATA_MASK	0xffff		/* data to write */
+
+/* SMBCNTL fields */
+#define SMBCNTL_DTI_MASK	0xf0000000	/* Slave Address low bits */
+#define SMBCNTL_DTI_SHIFT	28		/* Slave Address low bits */
+#define SMBCNTL_CKOVRD		(1U << 27)	/* # Clock Override */
+#define SMBCNTL_DIS_WRT		(1U << 26)	/* Disable Write (sadly) */
+#define SMBCNTL_SOFT_RST	(1U << 10)	/* Soft Reset */
+#define SMBCNTL_TSOD_POLL_EN	(1U << 8)	/* TSOD Polling Enable */
+/* Bits 0-3 and 4-6 indicate TSOD presence in various slots */
+
+/* Bits that might randomly change if we race with something. */
+#define SMBCMD_OUR_BITS		(~(u32)SMBCMD_TRIGGER)
+#define SMBCNTL_OUR_BITS	(SMBCNTL_DTI_MASK | SMBCNTL_TSOD_POLL_EN)
+
+/* System Address Controller, PCI dev 13 fn 6, 8086.3cf5 */
+#define SAD_CONTROL 0xf4
+
+#define PCI_DEVICE_ID_INTEL_SBRIDGE_BR          0x3cf5  /* 13.6 */
+#define PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TA      0x3ca8  /* 15.0 */
+
+static atomic_t imc_raced;  /* Set permanently to 1 if we screw up. */
+
+static bool allow_unsafe_access;
+
+struct imc_channel {
+	struct i2c_adapter adapter;
+	struct mutex mutex;  /* protects access to regs and prev_tsod_poll */
+	bool can_write, suspended;
+	bool prev_tsod_poll;
+};
+
+struct imc_priv {
+	struct pci_dev *pci_dev;
+	struct imc_channel channels[2];
+};
+
+static bool imc_wait_not_busy(struct imc_priv *priv, int chan, u32 *stat)
+{
+	/*
+	 * The clock is around 100kHz, and transactions are nine cycles
+	 * per byte plus a few start/stop cycles, plus whatever clock
+	 * streching is involved.  This means that polling every 70us
+	 * or so will give decent performance.
+	 *
+	 * Ideally we would calculate a good estimate for the
+	 * transaction time and sleep, but busy-waiting is an effective
+	 * workaround for an apparent Sandy Bridge bug that causes bogus
+	 * output if the system enters a package C-state.  (NB: these
+	 * states are systemwide -- we don't need be running on the
+	 * right package for this to work.)
+	 *
+	 * When Ivy Bridge and Haswell support are added, we could
+	 * consider making the busy-wait depend on the platform.
+	 */
+
+	int i;
+
+	for (i = 0; i < 50; i++) {
+		pci_read_config_dword(priv->pci_dev, SMBSTAT(chan), stat);
+		if (!(*stat & SMBSTAT_SMB_BUSY))
+			return true;
+		udelay(70);  /* see comment above -- we need to busy-wait */
+	}
+
+	return false;
+}
+
+static void imc_channel_release(struct imc_priv *priv, int chan)
+{
+	/* Return to HW control. */
+	if (priv->channels[chan].prev_tsod_poll) {
+		u32 cntl;
+
+		pci_read_config_dword(priv->pci_dev, SMBCNTL(chan), &cntl);
+		cntl |= SMBCNTL_TSOD_POLL_EN;
+		pci_write_config_dword(priv->pci_dev, SMBCNTL(chan), cntl);
+	}
+}
+
+static int imc_channel_claim(struct imc_priv *priv, int chan)
+{
+	/*
+	 * The docs are a bit confused here.  We're supposed to disable TSOD
+	 * polling, then wait for busy to be cleared, then set
+	 * SMBCNTL_TSOD_POLL_EN to zero to switch to software control.  But
+	 * SMBCNTL_TSOD_POLL_EN is the only documented way to turn off polling.
+	 */
+
+	u32 cntl, stat;
+
+	if (priv->channels[chan].suspended)
+		return -EIO;
+
+	pci_read_config_dword(priv->pci_dev, SMBCNTL(chan), &cntl);
+	priv->channels[chan].prev_tsod_poll = !!(cntl & SMBCNTL_TSOD_POLL_EN);
+	cntl &= ~SMBCNTL_TSOD_POLL_EN;
+	pci_write_config_dword(priv->pci_dev, SMBCNTL(chan), cntl);
+
+	/* Sometimes the hardware won't let go. */
+	pci_read_config_dword(priv->pci_dev, SMBCNTL(chan), &cntl);
+	if (cntl & SMBCNTL_TSOD_POLL_EN)
+		return -EBUSY;
+
+	if (!imc_wait_not_busy(priv, chan, &stat)) {
+		imc_channel_release(priv, chan);
+		return -EBUSY;  /* Someone else is controlling the bus. */
+	}
+
+	return 0;  /* The channel is ours. */
+}
+
+static bool imc_channel_can_claim(struct imc_priv *priv, int chan)
+{
+	u32 orig_cntl, cntl;
+
+	/* See if we can turn off TSOD_POLL_EN. */
+
+	pci_read_config_dword(priv->pci_dev, SMBCNTL(chan), &orig_cntl);
+	pci_write_config_dword(priv->pci_dev, SMBCNTL(chan),
+			       orig_cntl & ~SMBCNTL_TSOD_POLL_EN);
+
+	pci_read_config_dword(priv->pci_dev, SMBCNTL(chan), &cntl);
+	if (cntl & SMBCNTL_TSOD_POLL_EN)
+		return false;  /* Failed. */
+
+	pci_write_config_dword(priv->pci_dev, SMBCNTL(chan), orig_cntl);
+	return true;
+}
+
+/*
+ * The iMC supports five access types.  The terminology is rather
+ * inconsistent.  These are the types:
+ *
+ * "Write to pointer register SMBus": I2C_SMBUS_WRITE, I2C_SMBUS_BYTE
+ *
+ * Read byte/word: I2C_SMBUS_READ, I2C_SMBUS_{BYTE|WORD}_DATA
+ *
+ * Write byte/word: I2C_SMBUS_WRITE, I2C_SMBUS_{BYTE|WORD}_DATA
+ *
+ * The pointer write operations is AFAICT completely useless for
+ * software control, for two reasons.  First, HW periodically polls any
+ * TSODs on the bus, so it will corrupt the pointer in between SW
+ * transactions.  More importantly, the matching "read byte"/"receive
+ * byte" (the address-less single-byte read) is not available for SW
+ * control.  Therefore, this driver doesn't implement pointer writes
+ *
+ * There is no PEC support.
+ */
+
+static u32 imc_func(struct i2c_adapter *adapter)
+{
+	int chan;
+	struct imc_channel *ch;
+	struct imc_priv *priv = i2c_get_adapdata(adapter);
+
+	chan = (adapter == &priv->channels[0].adapter ? 0 : 1);
+	ch = &priv->channels[chan];
+
+	if (ch->can_write)
+		return I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA;
+	else
+		return I2C_FUNC_SMBUS_READ_BYTE_DATA |
+			I2C_FUNC_SMBUS_READ_WORD_DATA;
+}
+
+static s32 imc_smbus_xfer(struct i2c_adapter *adap, u16 addr,
+			  unsigned short flags, char read_write, u8 command,
+			  int size, union i2c_smbus_data *data)
+{
+	int ret, chan;
+	u32 cmd = 0, cntl, final_cmd, final_cntl, stat;
+	struct imc_channel *ch;
+	struct imc_priv *priv = i2c_get_adapdata(adap);
+
+	if (atomic_read(&imc_raced))
+		return -EIO;  /* Minimize damage. */
+
+	chan = (adap == &priv->channels[0].adapter ? 0 : 1);
+	ch = &priv->channels[chan];
+
+	/* Encode CMD part of addresses and access size */
+	cmd |= ((u32)addr & 0x7) << SMBCMD_SA_SHIFT;
+	cmd |= ((u32)command) << SMBCMD_BA_SHIFT;
+	if (size == I2C_SMBUS_WORD_DATA)
+		cmd |= SMBCMD_WORD_ACCESS;
+
+	/* Encode read/write and data to write */
+	if (read_write == I2C_SMBUS_READ) {
+		cmd |= SMBCMD_TYPE_READ;
+	} else {
+		cmd |= SMBCMD_TYPE_WRITE;
+		cmd |= (size == I2C_SMBUS_WORD_DATA
+			    ? swab16(data->word)
+			    : data->byte);
+	}
+
+	mutex_lock(&ch->mutex);
+
+	ret = imc_channel_claim(priv, chan);
+	if (ret)
+		goto out_unlock;
+
+	pci_read_config_dword(priv->pci_dev, SMBCNTL(chan), &cntl);
+	cntl &= ~SMBCNTL_DTI_MASK;
+	cntl |= ((u32)addr >> 3) << SMBCNTL_DTI_SHIFT;
+	pci_write_config_dword(priv->pci_dev, SMBCNTL(chan), cntl);
+
+	/*
+	 * This clears SMBCMD_PNTR_SEL.  We leave it cleared so that we don't
+	 * need to think about keeping the TSOD pointer state consistent with
+	 * the hardware's expectation.  This probably has some miniscule
+	 * power cost, as TSOD polls will take 9 extra cycles.
+	 */
+	cmd |= SMBCMD_TRIGGER;
+	pci_write_config_dword(priv->pci_dev, SMBCMD(chan), cmd);
+
+	if (!imc_wait_not_busy(priv, chan, &stat)) {
+		/* Timeout.  TODO: Reset the controller? */
+		ret = -ETIMEDOUT;
+		dev_dbg(&priv->pci_dev->dev, "controller is wedged\n");
+		goto out_release;
+	}
+
+	/*
+	 * Be paranoid: try to detect races.  This will only detect races
+	 * against BIOS, not against hardware.  (I've never seen this happen.)
+	 */
+	pci_read_config_dword(priv->pci_dev, SMBCMD(chan), &final_cmd);
+	pci_read_config_dword(priv->pci_dev, SMBCNTL(chan), &final_cntl);
+	if (((cmd ^ final_cmd) & SMBCMD_OUR_BITS) ||
+	    ((cntl ^ final_cntl) & SMBCNTL_OUR_BITS)) {
+		WARN(1, "iMC SMBUS raced against firmware");
+		dev_err(&priv->pci_dev->dev,
+			"Access to channel %d raced: cmd 0x%08X->0x%08X, cntl 0x%08X->0x%08X\n",
+			chan, cmd, final_cmd, cntl, final_cntl);
+		atomic_set(&imc_raced, 1);
+		ret = -EIO;
+		goto out_release;
+	}
+
+	if (stat & SMBSTAT_SBE) {
+		/*
+		 * Clear the error to re-enable TSOD polling.  The docs say
+		 * that, as long as SBE is set, TSOD polling won't happen.
+		 * The docs also say that writing zero to this bit (which is
+		 * the only writable bit in the whole register) will clear
+		 * the error.  Empirically, writing 0 does not clear SBE, but
+		 * it's probably still good to do the write in compliance with
+		 * the spec.  (TSOD polling still happens and seems to
+		 * clear SBE on its own.)
+		 */
+		pci_write_config_dword(priv->pci_dev, SMBSTAT(chan), 0);
+		ret = -ENXIO;
+		goto out_release;
+	}
+
+	if (read_write == I2C_SMBUS_READ) {
+		if (!(stat & SMBSTAT_RDO)) {
+			dev_dbg(&priv->pci_dev->dev,
+				"Unexpected read status 0x%08X\n", stat);
+			ret = -EIO;
+			goto out_release;
+		}
+
+		/*
+		 * The iMC SMBUS controller thinks of SMBUS words as
+		 * being big-endian (MSB first).  Linux treats them as
+		 * little-endian, so we need to swap them.
+		 *
+		 * Note: the controller will often (always?) set WOD
+		 * here.  This is probably a hardware bug.
+		 */
+		if (size == I2C_SMBUS_WORD_DATA)
+			data->word = swab16(stat & SMBSTAT_RDATA_MASK);
+		else
+			data->byte = stat & 0xFF;
+	} else {
+		/*
+		 * Note: the controller will often (always?) set RDO here.
+		 * This is probably a hardware bug.
+		 */
+		if (!(stat & SMBSTAT_WOD)) {
+			dev_dbg(&priv->pci_dev->dev,
+				"Unexpected write status 0x%08X\n", stat);
+			ret = -EIO;
+		}
+	}
+
+out_release:
+	imc_channel_release(priv, chan);
+
+out_unlock:
+	mutex_unlock(&ch->mutex);
+
+	return ret;
+}
+
+static const struct i2c_algorithm imc_smbus_algorithm = {
+	.smbus_xfer	= imc_smbus_xfer,
+	.functionality	= imc_func,
+};
+
+static int imc_init_channel(struct imc_priv *priv, int i, int socket)
+{
+	int err;
+	u32 val;
+	struct imc_channel *ch = &priv->channels[i];
+
+	/*
+	 * With CLTT enabled, the hardware won't let us turn
+	 * off TSOD polling.  The device is completely useless
+	 * when this happens (at least without help from Intel),
+	 * but we can at least minimize confusion.
+	 */
+	if (!imc_channel_can_claim(priv, i)) {
+		dev_warn(&priv->pci_dev->dev,
+			 "iMC channel %d: we cannot control the HW.  Is CLTT on?\n",
+			 i);
+		return -EBUSY;
+	}
+
+	i2c_set_adapdata(&ch->adapter, priv);
+	ch->adapter.owner = THIS_MODULE;
+	ch->adapter.algo = &imc_smbus_algorithm;
+	ch->adapter.dev.parent = &priv->pci_dev->dev;
+
+	pci_read_config_dword(priv->pci_dev, SMBCNTL(i), &val);
+	ch->can_write = !(val & SMBCNTL_DIS_WRT);
+
+	mutex_init(&ch->mutex);
+
+	snprintf(ch->adapter.name, sizeof(ch->adapter.name),
+		 "iMC socket %d channel %d", socket, i);
+	err = i2c_add_adapter(&ch->adapter);
+	if (err) {
+		mutex_destroy(&ch->mutex);
+		return err;
+	}
+
+	return 0;
+}
+
+static void imc_free_channel(struct imc_priv *priv, int i)
+{
+	struct imc_channel *ch = &priv->channels[i];
+
+	i2c_del_adapter(&ch->adapter);
+	mutex_destroy(&ch->mutex);
+}
+
+static struct pci_dev *imc_get_related_device(struct pci_bus *bus,
+					      unsigned int devfn, u16 devid)
+{
+	struct pci_dev *dev = pci_get_slot(bus, devfn);
+
+	if (!dev)
+		return NULL;
+	if (dev->vendor != PCI_VENDOR_ID_INTEL || dev->device != devid) {
+		pci_dev_put(dev);
+		return NULL;
+	}
+	return dev;
+}
+
+static int imc_probe(struct pci_dev *dev, const struct pci_device_id *id)
+{
+	int i, j, err;
+	struct imc_priv *priv;
+	struct pci_dev *sad;  /* System Address Decoder */
+	u32 sad_control;
+
+	/* Paranoia: the datasheet says this is always at 15.0 */
+	if (dev->devfn != PCI_DEVFN(15, 0))
+		return -ENODEV;
+
+	/*
+	 * The socket number is hidden away on a different PCI device.
+	 * There's another copy at devfn 11.0 offset 0x40, and an even
+	 * less convincing copy at 5.0 0x140.  The actual APICID register
+	 * is "not used ... and is still implemented in hardware because
+	 * of FUD".
+	 *
+	 * In principle we could double-check that the socket matches
+	 * the numa_node from SRAT, but this is probably not worth it.
+	 */
+	sad = imc_get_related_device(dev->bus, PCI_DEVFN(13, 6),
+				     PCI_DEVICE_ID_INTEL_SBRIDGE_BR);
+	if (!sad)
+		return -ENODEV;
+	pci_read_config_dword(sad, SAD_CONTROL, &sad_control);
+	pci_dev_put(sad);
+
+	priv = devm_kzalloc(&dev->dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+	priv->pci_dev = dev;
+
+	pci_set_drvdata(dev, priv);
+
+	for (i = 0; i < 2; i++) {
+		err = imc_init_channel(priv, i, sad_control & 0x7);
+		if (err)
+			goto exit_free_channels;
+	}
+
+	return 0;
+
+exit_free_channels:
+	for (j = 0; j < i; j++)
+		imc_free_channel(priv, j);
+	return err;
+}
+
+static void imc_remove(struct pci_dev *dev)
+{
+	int i;
+	struct imc_priv *priv = pci_get_drvdata(dev);
+
+	for (i = 0; i < 2; i++)
+		imc_free_channel(priv, i);
+}
+
+static int imc_suspend(struct pci_dev *dev, pm_message_t mesg)
+{
+	int i;
+	struct imc_priv *priv = pci_get_drvdata(dev);
+
+	/* BIOS is in charge.  We should finish any pending transaction */
+	for (i = 0; i < 2; i++) {
+		mutex_lock(&priv->channels[i].mutex);
+		priv->channels[i].suspended = true;
+		mutex_unlock(&priv->channels[i].mutex);
+	}
+
+	return 0;
+}
+
+static int imc_resume(struct pci_dev *dev)
+{
+	int i;
+	struct imc_priv *priv = pci_get_drvdata(dev);
+
+	for (i = 0; i < 2; i++) {
+		mutex_lock(&priv->channels[i].mutex);
+		priv->channels[i].suspended = false;
+		mutex_unlock(&priv->channels[i].mutex);
+	}
+
+	return 0;
+}
+
+static const struct pci_device_id imc_ids[] = {
+	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TA) },
+	{ 0, }
+};
+MODULE_DEVICE_TABLE(pci, imc_ids);
+
+static struct pci_driver imc_pci_driver = {
+	.name		= "imc_smbus",
+	.id_table	= imc_ids,
+	.probe		= imc_probe,
+	.remove		= imc_remove,
+	.suspend	= imc_suspend,
+	.resume		= imc_resume,
+};
+
+static int __init i2c_imc_init(void)
+{
+	if (!allow_unsafe_access)
+		return -ENODEV;
+
+	pr_warn("using this driver is dangerous unless your firmware is specifically designed for it; use at your own risk\n");
+	return pci_register_driver(&imc_pci_driver);
+}
+module_init(i2c_imc_init);
+
+static void __exit i2c_imc_exit(void)
+{
+	pci_unregister_driver(&imc_pci_driver);
+}
+module_exit(i2c_imc_exit);
+
+module_param(allow_unsafe_access, bool, 0400);
+MODULE_PARM_DESC(allow_unsafe_access, "enable i2c_imc despite potential races against BIOS/hardware bus access");
+
+MODULE_AUTHOR("Andrew Lutomirski <luto@amacapital.net>");
+MODULE_DESCRIPTION("iMC SMBus driver");
+MODULE_LICENSE("GPL v2");
-- 
2.3.0


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH v2 2/2] i2c, i2c_imc: Add DIMM bus code
  2015-03-09 20:55 ` Andy Lutomirski
  (?)
  (?)
@ 2015-03-09 20:55 ` Andy Lutomirski
  -1 siblings, 0 replies; 10+ messages in thread
From: Andy Lutomirski @ 2015-03-09 20:55 UTC (permalink / raw)
  To: Wolfram Sang, linux-i2c, Jean Delvare, Guenter Roeck,
	linux-kernel
  Cc: Mauro Carvalho Chehab, Rui Wang, Tony Luck, One Thousand Gnomes,
	Alun Evans, Robert Elliott, Boaz Harrosh, Paul Bolle,
	Andy Lutomirski

Add i2c_scan_dimm_bus to declare that a particular i2c_adapter
contains DIMMs.  This will probe (and autoload modules!) for useful
SMBUS devices that live on DIMMs.  i2c_imc calls it.

As more SMBUS-addressable DIMM components become supported, this
code can be extended to probe for them.

Signed-off-by: Andy Lutomirski <luto@amacapital.net>
---
 drivers/i2c/busses/Kconfig    |   5 ++
 drivers/i2c/busses/Makefile   |   4 ++
 drivers/i2c/busses/dimm-bus.c | 107 ++++++++++++++++++++++++++++++++++++++++++
 drivers/i2c/busses/i2c-imc.c  |   3 ++
 include/linux/i2c/dimm-bus.h  |  20 ++++++++
 5 files changed, 139 insertions(+)
 create mode 100644 drivers/i2c/busses/dimm-bus.c
 create mode 100644 include/linux/i2c/dimm-bus.h

diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
index 50e3d79122dd..2ea6648492eb 100644
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -149,9 +149,14 @@ config I2C_ISMT
 	  This driver can also be built as a module.  If so, the module will be
 	  called i2c-ismt.
 
+config I2C_DIMM_BUS
+       tristate
+       default n
+
 config I2C_IMC
 	tristate "Intel iMC (LGA 2011) SMBus Controller"
 	depends on PCI && X86
+	select I2C_DIMM_BUS
 	help
 	  If you say yes to this option, support will be included for the Intel
 	  Integrated Memory Controller SMBus host controller interface.  This
diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
index 4287c891e782..a01bdcc0e239 100644
--- a/drivers/i2c/busses/Makefile
+++ b/drivers/i2c/busses/Makefile
@@ -25,6 +25,10 @@ obj-$(CONFIG_I2C_SIS96X)	+= i2c-sis96x.o
 obj-$(CONFIG_I2C_VIA)		+= i2c-via.o
 obj-$(CONFIG_I2C_VIAPRO)	+= i2c-viapro.o
 
+# DIMM busses
+obj-$(CONFIG_I2C_DIMM_BUS)	+= dimm-bus.o
+obj-$(CONFIG_I2C_IMC)		+= i2c-imc.o
+
 # Mac SMBus host controller drivers
 obj-$(CONFIG_I2C_HYDRA)		+= i2c-hydra.o
 obj-$(CONFIG_I2C_POWERMAC)	+= i2c-powermac.o
diff --git a/drivers/i2c/busses/dimm-bus.c b/drivers/i2c/busses/dimm-bus.c
new file mode 100644
index 000000000000..3760663d21c8
--- /dev/null
+++ b/drivers/i2c/busses/dimm-bus.c
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2013-2015 Andrew Lutomirski <luto@amacapital.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/i2c.h>
+#include <linux/bug.h>
+#include <linux/module.h>
+#include <linux/i2c/dimm-bus.h>
+
+static bool probe_addr(struct i2c_adapter *adapter, int addr)
+{
+	/*
+	 * So far, all known devices that live on DIMMs can be safely
+	 * and reliably detected by trying to read a byte at address
+	 * zero.  (The exception is the SPD write protection control,
+	 * which can't be probed and requires special hardware and/or
+	 * quick writes to access, and has no driver.)
+	 */
+	union i2c_smbus_data dummy;
+
+	return i2c_smbus_xfer(adapter, addr, 0, I2C_SMBUS_READ, 0,
+			      I2C_SMBUS_BYTE_DATA, &dummy) >= 0;
+}
+
+/**
+ * i2c_scan_dimm_bus() - Scans an SMBUS segment known to contain DIMMs
+ * @adapter: The SMBUS adapter to scan
+ *
+ * This function tells the DIMM-bus code that the adapter is known to
+ * contain DIMMs.  i2c_scan_dimm_bus will probe for devices known to
+ * live on DIMMs.
+ *
+ * Do NOT call this function on general-purpose system SMBUS segments
+ * unless you know that the only things on the bus are DIMMs.
+ * Otherwise is it very likely to mis-identify other things on the
+ * bus.
+ *
+ * Callers are advised not to set adapter->class = I2C_CLASS_SPD to
+ * avoid having two separate mechanisms trying to automatically claim
+ * devices on the bus.
+ */
+void i2c_scan_dimm_bus(struct i2c_adapter *adapter)
+{
+	struct i2c_board_info info = {};
+	int slot;
+
+	/*
+	 * We probe with "read byte data".  If any DIMM SMBUS driver can't
+	 * support that access type, this function should be updated.
+	 */
+	if (WARN_ON(!i2c_check_functionality(adapter,
+					     I2C_FUNC_SMBUS_READ_BYTE_DATA)))
+		return;
+
+	/*
+	 * Addresses on DIMMs use the three low bits to identify the slot
+	 * and the four high bits to identify the device type.  Known
+	 * devices are:
+	 *
+	 *  - 0x50 - 0x57: SPD (Serial Presence Detect) EEPROM
+	 *  - 0x30 - 0x37: SPD WP control -- not easy to probe
+	 *  - 0x18 - 0x1f: TSOD (Temperature Sensor on DIMM)
+	 *
+	 * There's no point in trying to probe the SPD WP control: we'd
+	 * want to probe using quick reads, which i2c-imc doesn't
+	 * support, we don't have a driver for it, we can't really use
+	 * it without special hardware (it's not a normal i2c slave --
+	 * see the JEDEC docs), and using it risks bricking the DIMM
+	 * it's on anyway.
+	 *
+	 * NB: There's no need to save the return value from
+	 * i2c_new_device, as the core code will unregister it for us
+	 * when the adapter is removed.  If users want to bind a
+	 * different driver, nothing stops them from unbinding the
+	 * drivers we request here.
+	 */
+	for (slot = 0; slot < 8; slot++) {
+		/* If there's no SPD, then assume there's no DIMM here. */
+		if (!probe_addr(adapter, 0x50 | slot))
+			continue;
+
+		strcpy(info.type, "spd");
+		info.addr = 0x50 | slot;
+		i2c_new_device(adapter, &info);
+
+		if (probe_addr(adapter, 0x18 | slot)) {
+			/* This is a temperature sensor. */
+			strcpy(info.type, "jc42");
+			info.addr = 0x18 | slot;
+			i2c_new_device(adapter, &info);
+		}
+	}
+}
+EXPORT_SYMBOL(i2c_scan_dimm_bus);
+
+MODULE_AUTHOR("Andrew Lutomirski <luto@amacapital.net>");
+MODULE_DESCRIPTION("i2c DIMM bus support");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/i2c/busses/i2c-imc.c b/drivers/i2c/busses/i2c-imc.c
index 455d9243f10b..2a0fd60a509e 100644
--- a/drivers/i2c/busses/i2c-imc.c
+++ b/drivers/i2c/busses/i2c-imc.c
@@ -19,6 +19,7 @@
 #include <linux/pci.h>
 #include <linux/ratelimit.h>
 #include <linux/i2c.h>
+#include <linux/i2c/dimm-bus.h>
 
 /*
  * The datasheet can be found here, for example:
@@ -416,6 +417,8 @@ static int imc_init_channel(struct imc_priv *priv, int i, int socket)
 		return err;
 	}
 
+	i2c_scan_dimm_bus(&ch->adapter);
+
 	return 0;
 }
 
diff --git a/include/linux/i2c/dimm-bus.h b/include/linux/i2c/dimm-bus.h
new file mode 100644
index 000000000000..62dbaac4be23
--- /dev/null
+++ b/include/linux/i2c/dimm-bus.h
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2013 Andrew Lutomirski <luto@amacapital.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _I2C_DIMM_BUS
+#define _I2C_DIMM_BUS
+
+struct i2c_adapter;
+void i2c_scan_dimm_bus(struct i2c_adapter *adapter);
+
+#endif /* _I2C_DIMM_BUS */
-- 
2.3.0


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* Re: [PATCH v2 1/2] i2c_imc: New driver for Intel's iMC, found on LGA2011 chips
  2015-03-09 20:55 ` [PATCH v2 1/2] i2c_imc: New driver for Intel's iMC, found on LGA2011 chips Andy Lutomirski
@ 2015-03-14  4:14   ` Guenter Roeck
  2015-03-17 20:14       ` Andy Lutomirski
  0 siblings, 1 reply; 10+ messages in thread
From: Guenter Roeck @ 2015-03-14  4:14 UTC (permalink / raw)
  To: Andy Lutomirski, Wolfram Sang, linux-i2c, Jean Delvare,
	linux-kernel
  Cc: Mauro Carvalho Chehab, Rui Wang, Tony Luck, One Thousand Gnomes,
	Alun Evans, Robert Elliott, Boaz Harrosh, Paul Bolle

On 03/09/2015 01:55 PM, Andy Lutomirski wrote:
> Sandy Bridge Xeon and Extreme chips have integrated memory
> controllers with (rather limited) onboard SMBUS masters.  This
> driver gives access to the bus.
>
> There are various groups working on standardizing a way to arbitrate
> access to the bus between the OS, SMM firmware, a BMC, hardware
> thermal control, etc.  In the mean time, running this driver is
> unsafe except under special circumstances.  Nonetheless, this driver
> has real users.
>
> As a compromise, the driver will refuse to load unless
> i2c_imc.allow_unsafe_access=Y.  When safe access becomes available,
> we can leave this option as a way for legacy users to run the
> driver, and we'll allow the driver to load by default if safe bus
> access is available.
>
> Signed-off-by: Andy Lutomirski <luto@amacapital.net>
> ---
>   drivers/i2c/busses/Kconfig   |  17 ++
>   drivers/i2c/busses/Makefile  |   1 +
>   drivers/i2c/busses/i2c-imc.c | 567 +++++++++++++++++++++++++++++++++++++++++++
>   3 files changed, 585 insertions(+)
>   create mode 100644 drivers/i2c/busses/i2c-imc.c
>
> diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
> index ab838d9e28b6..50e3d79122dd 100644
> --- a/drivers/i2c/busses/Kconfig
> +++ b/drivers/i2c/busses/Kconfig
> @@ -149,6 +149,23 @@ config I2C_ISMT
>   	  This driver can also be built as a module.  If so, the module will be
>   	  called i2c-ismt.
>
> +config I2C_IMC
> +	tristate "Intel iMC (LGA 2011) SMBus Controller"
> +	depends on PCI && X86
> +	help
> +	  If you say yes to this option, support will be included for the Intel
> +	  Integrated Memory Controller SMBus host controller interface.  This
> +	  controller is found on LGA 2011 Xeons and Core i7 Extremes.
> +
> +	  There are currently no systems on which the kernel knows that it can
> +	  safely enable this driver.  For now, you need to pass this driver a
> +	  scary module parameter, and you should only pass that parameter if you
> +	  have a special motherboard and know exactly what you are doing.
> +	  Special motherboards include the Supermicro X9DRH-iF-NV.
> +
I think the current approach of issuing warnings here and in the driver on load
is the wrong one. For the most part, users will just run with distributions.
If a distribution enables the driver, it will end up being used, warning or not.

A much better approach, in my opinion, would be to only enable the driver for
systems where it is known (or presumed) to be good, such as the Supermicro board
mentioned above. This can be done with DMI data.

For other boards, a 'force' module parameter can be added. This would ensure
that the user _has_ to do something manually to load the driver. The warning
on load would then only be displayed if the force module parameter is set.

Having said that, I am still not convinced that the driver should be in the kernel
to start with. Browsing through Intel's datasheets, the registers are supported
in E5-2600 v1, v2, and v3. However, in v3 Intel added a note saying that the registers
should not be accessed by the OS directly, but only through the bios. Given that,
and if that is possible, it might make more sense to rely on ACPI. It would then
be up to the board and/or BIOS vendor to decide if the information should be available
to the OS or not.

Thanks,
Guenter


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH v2 1/2] i2c_imc: New driver for Intel's iMC, found on LGA2011 chips
@ 2015-03-17 20:14       ` Andy Lutomirski
  0 siblings, 0 replies; 10+ messages in thread
From: Andy Lutomirski @ 2015-03-17 20:14 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: Boaz Harrosh, One Thousand Gnomes, Rui Wang, Jean Delvare,
	Alun Evans, Robert Elliott, linux-i2c@vger.kernel.org,
	Wolfram Sang, Mauro Carvalho Chehab, Paul Bolle, Tony Luck,
	linux-kernel@vger.kernel.org

On Mar 13, 2015 9:15 PM, "Guenter Roeck" <linux@roeck-us.net> wrote:
>
> On 03/09/2015 01:55 PM, Andy Lutomirski wrote:
>>
>> Sandy Bridge Xeon and Extreme chips have integrated memory
>> controllers with (rather limited) onboard SMBUS masters.  This
>> driver gives access to the bus.
>>
>> There are various groups working on standardizing a way to arbitrate
>> access to the bus between the OS, SMM firmware, a BMC, hardware
>> thermal control, etc.  In the mean time, running this driver is
>> unsafe except under special circumstances.  Nonetheless, this driver
>> has real users.
>>
>> As a compromise, the driver will refuse to load unless
>> i2c_imc.allow_unsafe_access=Y.  When safe access becomes available,
>> we can leave this option as a way for legacy users to run the
>> driver, and we'll allow the driver to load by default if safe bus
>> access is available.
>>
>> Signed-off-by: Andy Lutomirski <luto@amacapital.net>
>> ---
>>   drivers/i2c/busses/Kconfig   |  17 ++
>>   drivers/i2c/busses/Makefile  |   1 +
>>   drivers/i2c/busses/i2c-imc.c | 567 +++++++++++++++++++++++++++++++++++++++++++
>>   3 files changed, 585 insertions(+)
>>   create mode 100644 drivers/i2c/busses/i2c-imc.c
>>
>> diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
>> index ab838d9e28b6..50e3d79122dd 100644
>> --- a/drivers/i2c/busses/Kconfig
>> +++ b/drivers/i2c/busses/Kconfig
>> @@ -149,6 +149,23 @@ config I2C_ISMT
>>           This driver can also be built as a module.  If so, the module will be
>>           called i2c-ismt.
>>
>> +config I2C_IMC
>> +       tristate "Intel iMC (LGA 2011) SMBus Controller"
>> +       depends on PCI && X86
>> +       help
>> +         If you say yes to this option, support will be included for the Intel
>> +         Integrated Memory Controller SMBus host controller interface.  This
>> +         controller is found on LGA 2011 Xeons and Core i7 Extremes.
>> +
>> +         There are currently no systems on which the kernel knows that it can
>> +         safely enable this driver.  For now, you need to pass this driver a
>> +         scary module parameter, and you should only pass that parameter if you
>> +         have a special motherboard and know exactly what you are doing.
>> +         Special motherboards include the Supermicro X9DRH-iF-NV.
>> +
>
> I think the current approach of issuing warnings here and in the driver on load
> is the wrong one. For the most part, users will just run with distributions.
> If a distribution enables the driver, it will end up being used, warning or not.
>
> A much better approach, in my opinion, would be to only enable the driver for
> systems where it is known (or presumed) to be good, such as the Supermicro board
> mentioned above. This can be done with DMI data.
>
> For other boards, a 'force' module parameter can be added. This would ensure
> that the user _has_ to do something manually to load the driver. The warning
> on load would then only be displayed if the force module parameter is set.
>

This driver already has that: that's what "allow_unsafe_access" does.

I wouldn't be opposed to adding a DMI whitelist, although I really
don't want DMI entries to proliferate.

> Having said that, I am still not convinced that the driver should be in the kernel
> to start with. Browsing through Intel's datasheets, the registers are supported
> in E5-2600 v1, v2, and v3. However, in v3 Intel added a note saying that the registers
> should not be accessed by the OS directly, but only through the bios. Given that,
> and if that is possible, it might make more sense to rely on ACPI. It would then
> be up to the board and/or BIOS vendor to decide if the information should be available
> to the OS or not.

I think the plan is to add something to ACPI to tell us when we can
use these registers.  Unfortunately I'm not privy to whatever the ACPI
committee is doing.


--Andy

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH v2 1/2] i2c_imc: New driver for Intel's iMC, found on LGA2011 chips
@ 2015-03-17 20:14       ` Andy Lutomirski
  0 siblings, 0 replies; 10+ messages in thread
From: Andy Lutomirski @ 2015-03-17 20:14 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: Boaz Harrosh, One Thousand Gnomes, Rui Wang, Jean Delvare,
	Alun Evans, Robert Elliott,
	linux-i2c-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, Wolfram Sang,
	Mauro Carvalho Chehab, Paul Bolle, Tony Luck,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org

On Mar 13, 2015 9:15 PM, "Guenter Roeck" <linux-0h96xk9xTtrk1uMJSBkQmQ@public.gmane.org> wrote:
>
> On 03/09/2015 01:55 PM, Andy Lutomirski wrote:
>>
>> Sandy Bridge Xeon and Extreme chips have integrated memory
>> controllers with (rather limited) onboard SMBUS masters.  This
>> driver gives access to the bus.
>>
>> There are various groups working on standardizing a way to arbitrate
>> access to the bus between the OS, SMM firmware, a BMC, hardware
>> thermal control, etc.  In the mean time, running this driver is
>> unsafe except under special circumstances.  Nonetheless, this driver
>> has real users.
>>
>> As a compromise, the driver will refuse to load unless
>> i2c_imc.allow_unsafe_access=Y.  When safe access becomes available,
>> we can leave this option as a way for legacy users to run the
>> driver, and we'll allow the driver to load by default if safe bus
>> access is available.
>>
>> Signed-off-by: Andy Lutomirski <luto-kltTT9wpgjJwATOyAt5JVQ@public.gmane.org>
>> ---
>>   drivers/i2c/busses/Kconfig   |  17 ++
>>   drivers/i2c/busses/Makefile  |   1 +
>>   drivers/i2c/busses/i2c-imc.c | 567 +++++++++++++++++++++++++++++++++++++++++++
>>   3 files changed, 585 insertions(+)
>>   create mode 100644 drivers/i2c/busses/i2c-imc.c
>>
>> diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
>> index ab838d9e28b6..50e3d79122dd 100644
>> --- a/drivers/i2c/busses/Kconfig
>> +++ b/drivers/i2c/busses/Kconfig
>> @@ -149,6 +149,23 @@ config I2C_ISMT
>>           This driver can also be built as a module.  If so, the module will be
>>           called i2c-ismt.
>>
>> +config I2C_IMC
>> +       tristate "Intel iMC (LGA 2011) SMBus Controller"
>> +       depends on PCI && X86
>> +       help
>> +         If you say yes to this option, support will be included for the Intel
>> +         Integrated Memory Controller SMBus host controller interface.  This
>> +         controller is found on LGA 2011 Xeons and Core i7 Extremes.
>> +
>> +         There are currently no systems on which the kernel knows that it can
>> +         safely enable this driver.  For now, you need to pass this driver a
>> +         scary module parameter, and you should only pass that parameter if you
>> +         have a special motherboard and know exactly what you are doing.
>> +         Special motherboards include the Supermicro X9DRH-iF-NV.
>> +
>
> I think the current approach of issuing warnings here and in the driver on load
> is the wrong one. For the most part, users will just run with distributions.
> If a distribution enables the driver, it will end up being used, warning or not.
>
> A much better approach, in my opinion, would be to only enable the driver for
> systems where it is known (or presumed) to be good, such as the Supermicro board
> mentioned above. This can be done with DMI data.
>
> For other boards, a 'force' module parameter can be added. This would ensure
> that the user _has_ to do something manually to load the driver. The warning
> on load would then only be displayed if the force module parameter is set.
>

This driver already has that: that's what "allow_unsafe_access" does.

I wouldn't be opposed to adding a DMI whitelist, although I really
don't want DMI entries to proliferate.

> Having said that, I am still not convinced that the driver should be in the kernel
> to start with. Browsing through Intel's datasheets, the registers are supported
> in E5-2600 v1, v2, and v3. However, in v3 Intel added a note saying that the registers
> should not be accessed by the OS directly, but only through the bios. Given that,
> and if that is possible, it might make more sense to rely on ACPI. It would then
> be up to the board and/or BIOS vendor to decide if the information should be available
> to the OS or not.

I think the plan is to add something to ACPI to tell us when we can
use these registers.  Unfortunately I'm not privy to whatever the ACPI
committee is doing.


--Andy

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH v2 1/2] i2c_imc: New driver for Intel's iMC, found on LGA2011 chips
  2015-03-17 20:14       ` Andy Lutomirski
  (?)
@ 2015-06-17 13:18       ` Wolfram Sang
  2015-06-17 15:12           ` Guenter Roeck
  -1 siblings, 1 reply; 10+ messages in thread
From: Wolfram Sang @ 2015-06-17 13:18 UTC (permalink / raw)
  To: Andy Lutomirski
  Cc: Guenter Roeck, Boaz Harrosh, One Thousand Gnomes, Rui Wang,
	Jean Delvare, Alun Evans, Robert Elliott,
	linux-i2c@vger.kernel.org, Mauro Carvalho Chehab, Paul Bolle,
	Tony Luck, linux-kernel@vger.kernel.org

[-- Attachment #1: Type: text/plain, Size: 1037 bytes --]


> > Having said that, I am still not convinced that the driver should be in the kernel
> > to start with. Browsing through Intel's datasheets, the registers are supported
> > in E5-2600 v1, v2, and v3. However, in v3 Intel added a note saying that the registers
> > should not be accessed by the OS directly, but only through the bios. Given that,
> > and if that is possible, it might make more sense to rely on ACPI. It would then
> > be up to the board and/or BIOS vendor to decide if the information should be available
> > to the OS or not.
> 
> I think the plan is to add something to ACPI to tell us when we can
> use these registers.  Unfortunately I'm not privy to whatever the ACPI
> committee is doing.

Coming from the embedded world and not knowing much about this, I tend
to wait until the above issue is clear, meaning when and how this driver
is safe to be used. I hope you don't mind. Keeping your code up to date
and sharing it is much appreciated, though! As well as Guenter's comments.

Thanks!


[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH v2 1/2] i2c_imc: New driver for Intel's iMC, found on LGA2011 chips
  2015-06-17 13:18       ` Wolfram Sang
@ 2015-06-17 15:12           ` Guenter Roeck
  0 siblings, 0 replies; 10+ messages in thread
From: Guenter Roeck @ 2015-06-17 15:12 UTC (permalink / raw)
  To: Wolfram Sang
  Cc: Andy Lutomirski, Boaz Harrosh, One Thousand Gnomes, Rui Wang,
	Jean Delvare, Alun Evans, Robert Elliott,
	linux-i2c@vger.kernel.org, Mauro Carvalho Chehab, Paul Bolle,
	Tony Luck, linux-kernel@vger.kernel.org

On Wed, Jun 17, 2015 at 03:18:42PM +0200, Wolfram Sang wrote:
> 
> > > Having said that, I am still not convinced that the driver should be in the kernel
> > > to start with. Browsing through Intel's datasheets, the registers are supported
> > > in E5-2600 v1, v2, and v3. However, in v3 Intel added a note saying that the registers
> > > should not be accessed by the OS directly, but only through the bios. Given that,
> > > and if that is possible, it might make more sense to rely on ACPI. It would then
> > > be up to the board and/or BIOS vendor to decide if the information should be available
> > > to the OS or not.
> > 
> > I think the plan is to add something to ACPI to tell us when we can
> > use these registers.  Unfortunately I'm not privy to whatever the ACPI
> > committee is doing.
> 
> Coming from the embedded world and not knowing much about this, I tend
> to wait until the above issue is clear, meaning when and how this driver
> is safe to be used. I hope you don't mind. Keeping your code up to date
> and sharing it is much appreciated, though! As well as Guenter's comments.
> 
When I suggested that we should rely on ACPI, I meant through ACPI SMBus CMI
(i2c-scmi), not through some ACPI properties which would permit direct access.

Thanks,
Guenter

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH v2 1/2] i2c_imc: New driver for Intel's iMC, found on LGA2011 chips
@ 2015-06-17 15:12           ` Guenter Roeck
  0 siblings, 0 replies; 10+ messages in thread
From: Guenter Roeck @ 2015-06-17 15:12 UTC (permalink / raw)
  To: Wolfram Sang
  Cc: Andy Lutomirski, Boaz Harrosh, One Thousand Gnomes, Rui Wang,
	Jean Delvare, Alun Evans, Robert Elliott,
	linux-i2c-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	Mauro Carvalho Chehab, Paul Bolle, Tony Luck,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org

On Wed, Jun 17, 2015 at 03:18:42PM +0200, Wolfram Sang wrote:
> 
> > > Having said that, I am still not convinced that the driver should be in the kernel
> > > to start with. Browsing through Intel's datasheets, the registers are supported
> > > in E5-2600 v1, v2, and v3. However, in v3 Intel added a note saying that the registers
> > > should not be accessed by the OS directly, but only through the bios. Given that,
> > > and if that is possible, it might make more sense to rely on ACPI. It would then
> > > be up to the board and/or BIOS vendor to decide if the information should be available
> > > to the OS or not.
> > 
> > I think the plan is to add something to ACPI to tell us when we can
> > use these registers.  Unfortunately I'm not privy to whatever the ACPI
> > committee is doing.
> 
> Coming from the embedded world and not knowing much about this, I tend
> to wait until the above issue is clear, meaning when and how this driver
> is safe to be used. I hope you don't mind. Keeping your code up to date
> and sharing it is much appreciated, though! As well as Guenter's comments.
> 
When I suggested that we should rely on ACPI, I meant through ACPI SMBus CMI
(i2c-scmi), not through some ACPI properties which would permit direct access.

Thanks,
Guenter

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2015-06-17 15:13 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-03-09 20:55 [PATCH v2 0/2] i2c_imc: New driver, at long last Andy Lutomirski
2015-03-09 20:55 ` Andy Lutomirski
2015-03-09 20:55 ` [PATCH v2 1/2] i2c_imc: New driver for Intel's iMC, found on LGA2011 chips Andy Lutomirski
2015-03-14  4:14   ` Guenter Roeck
2015-03-17 20:14     ` Andy Lutomirski
2015-03-17 20:14       ` Andy Lutomirski
2015-06-17 13:18       ` Wolfram Sang
2015-06-17 15:12         ` Guenter Roeck
2015-06-17 15:12           ` Guenter Roeck
2015-03-09 20:55 ` [PATCH v2 2/2] i2c, i2c_imc: Add DIMM bus code Andy Lutomirski

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.