All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC][Patch] IBM Real-Time "SMI Free" mode driver
@ 2009-02-11  0:37 Keith Mannthey
  2009-02-11 10:02 ` Alan Cox
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: Keith Mannthey @ 2009-02-11  0:37 UTC (permalink / raw)
  To: lkml; +Cc: John Stultz

This driver supports the Real-Time Linux (RTL) BIOS feature.  The RTL
feature allows non-fatal System Management Interrupts (SMIs) to be
disabled on supported IBM platforms (LS21, LS22 and HS21xm blades).  

This driver creates a simple sysfs interface to allow a simple entry and
exit from RTL mode in the BIOS. 

Signed-off-by:  Keith Mannthey <kmannth@us.ibm.com>

---

diff -urN linux-2.6.29-rc3-git7-orig/drivers/misc/ibmrtl/ibm_rtl.c linux-2.6.29-rc3-git7/drivers/misc/ibmrtl/ibm_rtl.c
--- linux-2.6.29-rc3-git7-orig/drivers/misc/ibmrtl/ibm_rtl.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-2.6.29-rc3-git7/drivers/misc/ibmrtl/ibm_rtl.c	2009-02-10 13:58:21.000000000 -0500
@@ -0,0 +1,205 @@
+/*
+ * IBM Real Time Linux Mode Device Driver
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Copyright (C) IBM Corporation, 2009
+ *
+ * Author: Keith Mannthey <kmannth@us.ibm.com>
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/io.h>
+#include <linux/sysdev.h>
+#include "rtl.h"
+
+static unsigned int table_addr;
+
+int ibm_rtl_write(u8 value)
+{
+	int ret = 0;
+	void __iomem *rtl;
+
+	/* only valid value is 0 and 1 */
+	if (value > 1) {
+		ret = -EINVAL;
+		goto err_out;
+	}
+
+	rtl = ioremap(table_addr, RTL_TABLE_SIZE);
+
+	if (!rtl) {
+		printk(KERN_WARNING "Could not ioremap RTL table\n");
+		ret = -ENOMEM;
+		goto err_out;
+	}
+
+	if (readb(rtl+RTL_STATE) != value) {
+		if (value == 1)
+			writeb(1, (rtl+RTL_CMD));
+		else
+			writeb(2, (rtl+RTL_CMD));
+
+		/*write special command*/
+		outb(bios_to_value(rtl, RTL_CMD_PORT_VALUE),
+			bios_to_value(rtl, RTL_CMD_PORT_ADDR));
+
+		while (readb(rtl+RTL_CMD))
+			msleep(10);
+
+		if (readb(rtl+RTL_CMD_STATUS))
+			ret = -EIO;
+	}
+
+	iounmap(rtl);
+err_out:
+	return ret;
+}
+
+static ssize_t rtl_show_version(struct sysdev_class *dev, char * buf)
+{
+	int ret;
+	void  __iomem *rtl;
+
+	rtl = ioremap(table_addr, RTL_TABLE_SIZE);
+
+	if (!rtl) {
+		ret = -ENOMEM;
+		goto err_out;
+	}
+	ret = sprintf(buf, "%d\n", (int)readb(rtl+RTL_VERSION));
+
+	iounmap(rtl);
+err_out:
+	return ret;
+}
+
+static ssize_t rtl_show_state(struct sysdev_class *dev, char *buf)
+{
+	int ret;
+	void __iomem *rtl;
+
+	rtl = ioremap(table_addr, RTL_TABLE_SIZE);
+
+	if (!rtl) {
+		printk(KERN_WARNING "Could not ioremap RTL table\n");
+		ret = -ENOMEM;
+		goto err_out;
+	}
+	ret = sprintf(buf, "%d\n", readb(rtl+RTL_STATE));
+
+	iounmap(rtl);
+err_out:
+	return ret;
+}
+
+static ssize_t rtl_set_state(struct sysdev_class *dev, const char *buf,
+								size_t size)
+{
+	ssize_t ret;
+	switch (buf[0]) {
+	case '0':
+		ret = ibm_rtl_write(0);
+		break;
+	case '1':
+		ret = ibm_rtl_write(1);
+		break;
+	default:
+		ret = -EINVAL;
+	}
+	if (ret >= 0)
+		ret = size;
+
+	return ret;
+}
+
+static struct sysdev_class class_rtl = {
+	.name	= "ibm_rtl",
+};
+
+static SYSDEV_CLASS_ATTR(version, S_IRUGO, rtl_show_version, NULL);
+static SYSDEV_CLASS_ATTR(state, 0600, rtl_show_state, rtl_set_state);
+
+static struct sysdev_class_attribute *rtl_attributes[] = {
+	&attr_version,
+	&attr_state,
+	NULL
+};
+
+
+static int rtl_setup_sysfs(void)
+{
+	int ret, i;
+	ret = sysdev_class_register(&class_rtl);
+
+	if (!ret) {
+		for (i = 0; rtl_attributes[i]; i++)
+			sysdev_class_create_file(&class_rtl, rtl_attributes[i]);
+	}
+	return ret;
+}
+
+static void rtl_teardown_sysfs(void)
+{
+	int i;
+	for (i = 0; rtl_attributes[i]; i++)
+		sysdev_class_remove_file(&class_rtl, rtl_attributes[i]);
+	sysdev_class_unregister(&class_rtl);
+	return;
+}
+
+/* only allow the modules to load if the _RTL_ table can be found*/
+int init_module(void)
+{
+	unsigned long ebda_addr, ebda_size;
+	void __iomem *data, *d;
+	int ret, i;
+
+	/*get the address for the RTL table from the EBDA */
+	ebda_addr = *(unsigned short *)phys_to_virt(0x40E);
+	ebda_addr <<= 4;
+	ebda_size = 64*1024;
+
+	data = ioremap(ebda_addr, ebda_size);
+	d = data;
+	if (!data) {
+		ret = -ENOMEM;
+		goto exit;
+	}
+
+	for (i = 0 ; i < ebda_size/4; i++) {
+		unsigned int *tmp = (unsigned int *) data++;
+		if (*tmp == RTL_MAGIC_IDENT) {
+			table_addr = ebda_addr + i;
+			ret = rtl_setup_sysfs();
+			goto exit;
+		}
+	}
+
+	ret = -ENODEV;
+
+exit:
+	iounmap(d);
+	return ret;
+}
+
+void cleanup_module(void)
+{
+	rtl_teardown_sysfs();
+}
+
+MODULE_LICENSE("GPL");
diff -urN linux-2.6.29-rc3-git7-orig/drivers/misc/ibmrtl/Makefile linux-2.6.29-rc3-git7/drivers/misc/ibmrtl/Makefile
--- linux-2.6.29-rc3-git7-orig/drivers/misc/ibmrtl/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-2.6.29-rc3-git7/drivers/misc/ibmrtl/Makefile	2009-02-05 12:38:35.000000000 -0500
@@ -0,0 +1 @@
+obj-$(CONFIG_IBM_RTL) := ibm_rtl.o
diff -urN linux-2.6.29-rc3-git7-orig/drivers/misc/ibmrtl/rtl.h linux-2.6.29-rc3-git7/drivers/misc/ibmrtl/rtl.h
--- linux-2.6.29-rc3-git7-orig/drivers/misc/ibmrtl/rtl.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-2.6.29-rc3-git7/drivers/misc/ibmrtl/rtl.h	2009-02-10 13:58:12.000000000 -0500
@@ -0,0 +1,49 @@
+/*
+ * IBM Real Time Linux Mode Device Driver
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Copyright (C) IBM Corporation, 2009
+ *
+ * Author: Keith Mannthey <kmannth@us.ibm.com>
+ *
+ */
+
+#include <linux/io.h>
+
+/* The RTL table looks something like
+	u8 signature[5];
+	u8 version;
+	u8 RT_Status;
+	u8 Command;
+	u8 CommandStatus;
+	u8 CMDAddressType;
+	u8 CmdGranularity;
+	u8 CmdOffset;
+	u16 Reserve1;
+	u8 CmdPortAddress[4];
+	u8 CmdPortValue[4];
+*/
+#define RTL_TABLE_SIZE 0x16
+#define RTL_MAGIC_IDENT (('L'<<24)|('T'<<16)|('R'<<8)|'_')
+#define RTL_VERSION 0x5
+#define RTL_STATE 0x6
+#define RTL_CMD 0x7
+#define RTL_CMD_STATUS 0x8
+#define RTL_CMD_PORT_ADDR 0xE
+#define RTL_CMD_PORT_VALUE 0x12
+
+/*needed to decode CmdPortAddress and CmdPortValue*/
+#define bios_to_value(rtl, offset) (u32)((readb(rtl+(offset+1)) << 8) + \
+							readb(rtl+offset))
diff -urN linux-2.6.29-rc3-git7-orig/drivers/misc/Kconfig linux-2.6.29-rc3-git7/drivers/misc/Kconfig
--- linux-2.6.29-rc3-git7-orig/drivers/misc/Kconfig	2009-02-05 12:29:22.000000000 -0500
+++ linux-2.6.29-rc3-git7/drivers/misc/Kconfig	2009-02-05 12:45:48.000000000 -0500
@@ -75,6 +75,21 @@
 	  website <http://www.pc.ibm.com/ww/eserver/xseries/serverproven> for
 	  information on the specific driver level and support statement
 	  for your IBM server.
+config IBM_RTL
+        tristate "Device driver to enable IBM PRTL support"
+        depends on X86 && PCI && EXPERIMENTAL
+        ---help---
+	  Enable support for IBM Preimium Real Time Mode (PRTM).
+	  This module will allow you the enter and exit PRTM in the BIOS via
+	  sysfs on platforms that support this feature.  System in PRTM will
+	  not recive cpu generated SMIs for recoverable errors.  Use of this
+	  feature without proper support may void your hardware warrenty.
+
+	  If the proper bios support is found the driver will load and create
+	  /sys/devices/system/ibm_rtl/.  The "state" varable will indicate
+	  weather or not the BIOS is in PRTM.
+	  state = 0 (BIOS SMI's on)
+	  state = 1 (BIOS SMI's off)
 
 config PHANTOM
 	tristate "Sensable PHANToM (PCI)"
diff -urN linux-2.6.29-rc3-git7-orig/drivers/misc/Makefile linux-2.6.29-rc3-git7/drivers/misc/Makefile
--- linux-2.6.29-rc3-git7-orig/drivers/misc/Makefile	2009-02-05 12:29:22.000000000 -0500
+++ linux-2.6.29-rc3-git7/drivers/misc/Makefile	2009-02-05 12:39:54.000000000 -0500
@@ -3,6 +3,7 @@
 #
 
 obj-$(CONFIG_IBM_ASM)		+= ibmasm/
+obj-$(CONFIG_IBM_RTL)		+= ibmrtl/
 obj-$(CONFIG_HDPU_FEATURES)	+= hdpuftrs/
 obj-$(CONFIG_ATMEL_PWM)		+= atmel_pwm.o
 obj-$(CONFIG_ATMEL_SSC)		+= atmel-ssc.o



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

* Re: [RFC][Patch] IBM Real-Time "SMI Free" mode driver
  2009-02-11  0:37 [RFC][Patch] IBM Real-Time "SMI Free" mode driver Keith Mannthey
@ 2009-02-11 10:02 ` Alan Cox
  2009-02-11 10:05 ` Alan Cox
  2009-02-11 12:18 ` Michal Schmidt
  2 siblings, 0 replies; 4+ messages in thread
From: Alan Cox @ 2009-02-11 10:02 UTC (permalink / raw)
  To: Keith Mannthey; +Cc: lkml, John Stultz

> +	if (readb(rtl+RTL_STATE) != value) {
> +		if (value == 1)
> +			writeb(1, (rtl+RTL_CMD));
> +		else
> +			writeb(2, (rtl+RTL_CMD));

		writeb( 1 + value , ... ) ??

> +	rtl = ioremap(table_addr, RTL_TABLE_SIZE);
> +
> +	if (!rtl) {
> +		ret = -ENOMEM;
> +		goto err_out;

Would it be better to eliminate all the ioremap special test casing and
just remap it once at load time, or at least use a single function so the
tests/printks don't all get duplicated ? That would also eliminate the
fact you can get multiple mappings of the same thing if there are
multiple parallel users.

I note also there is no locking versus multiple accessors - eg when
writing the RTL_CMD registers


> +	/*get the address for the RTL table from the EBDA */
> +	ebda_addr = *(unsigned short *)phys_to_virt(0x40E);
> +	ebda_addr <<= 4;
> +	ebda_size = 64*1024;
> +
> +	data = ioremap(ebda_addr, ebda_size);

Careful - it is perfectly valid for a BIOS EBDA table to be zero
indicating no EBDA is present, and at this point you've not checked if
the driver is being loaded on a relevant IBM platform.

> +		unsigned int *tmp = (unsigned int *) data++;

Use u32 - it makea it obvious what is going on here.

> +/*needed to decode CmdPortAddress and CmdPortValue*/
> +#define bios_to_value(rtl, offset) (u32)((readb(rtl+(offset+1)) << 8) + \
> +							readb(rtl+offset))

What is wrong with readw() ?


Alan

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

* Re: [RFC][Patch] IBM Real-Time "SMI Free" mode driver
  2009-02-11  0:37 [RFC][Patch] IBM Real-Time "SMI Free" mode driver Keith Mannthey
  2009-02-11 10:02 ` Alan Cox
@ 2009-02-11 10:05 ` Alan Cox
  2009-02-11 12:18 ` Michal Schmidt
  2 siblings, 0 replies; 4+ messages in thread
From: Alan Cox @ 2009-02-11 10:05 UTC (permalink / raw)
  To: Keith Mannthey; +Cc: lkml, John Stultz

> +	/*get the address for the RTL table from the EBDA */
> +	ebda_addr = *(unsigned short *)phys_to_virt(0x40E);
> +	ebda_addr <<= 4;
> +	ebda_size = 64*1024;

Second problem - you'll crash some systems with the assumptions here

> +	for (i = 0 ; i < ebda_size/4; i++) {
> +		unsigned int *tmp = (unsigned int *) data++;
> +		if (*tmp == RTL_MAGIC_IDENT) {
> +			table_addr = ebda_addr + i;
> +			ret = rtl_setup_sysfs();
> +			goto exit;
> +		}
> +	}

Some machines place the EBDA in the top pages of the low 640K. Your 64K
walk will continue into ISA MMIO space which isn't safe to blindly read.

Alan

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

* Re: [RFC][Patch] IBM Real-Time "SMI Free" mode driver
  2009-02-11  0:37 [RFC][Patch] IBM Real-Time "SMI Free" mode driver Keith Mannthey
  2009-02-11 10:02 ` Alan Cox
  2009-02-11 10:05 ` Alan Cox
@ 2009-02-11 12:18 ` Michal Schmidt
  2 siblings, 0 replies; 4+ messages in thread
From: Michal Schmidt @ 2009-02-11 12:18 UTC (permalink / raw)
  To: Keith Mannthey; +Cc: lkml, John Stultz

On Tue, 10 Feb 2009 16:37:13 -0800
Keith Mannthey <kmannth@us.ibm.com> wrote:

> + * This program is free software: you can redistribute it and/or
> modify
> + * it under the terms of the GNU General Public License as published
> by
> + * the Free Software Foundation, either version 3 of the License, or
> + * (at your option) any later version.

GPLv3+ is not compatible with Linux's GPLv2, is it?

Michal

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

end of thread, other threads:[~2009-02-11 12:18 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-02-11  0:37 [RFC][Patch] IBM Real-Time "SMI Free" mode driver Keith Mannthey
2009-02-11 10:02 ` Alan Cox
2009-02-11 10:05 ` Alan Cox
2009-02-11 12:18 ` Michal Schmidt

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.