public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/5] 2.6.13-rc5-mm1, remove uneeded function
@ 2005-08-10 10:32 Andrey Panin
  2005-08-10 10:32 ` [PATCH 1/5] 2.6.13-rc5-mm1, remove old debugging code Andrey Panin
  0 siblings, 1 reply; 9+ messages in thread
From: Andrey Panin @ 2005-08-10 10:32 UTC (permalink / raw)
  To: Andrew Morton, linux-kernel


After elimination of central DMI blacklist dmi_scan_machine() function
became a wrapper for dmi_iterate(). This patch moves some code around to
kill unneeded function.

Signed-off-by: Andrey Panin <pazke@donpac.ru>

 arch/i386/kernel/dmi_scan.c |   85 ++++++++++++++++++++------------------------
 1 files changed, 40 insertions(+), 45 deletions(-)

diff -urdpNX /usr/share/dontdiff linux-2.6.13-rc5-mm1.vanilla/arch/i386/kernel/dmi_scan.c linux-2.6.13-rc5-mm1/arch/i386/kernel/dmi_scan.c
--- linux-2.6.13-rc5-mm1.vanilla/arch/i386/kernel/dmi_scan.c	2005-06-12 23:07:37.000000000 +0400
+++ linux-2.6.13-rc5-mm1/arch/i386/kernel/dmi_scan.c	2005-06-14 23:18:18.000000000 +0400
@@ -84,49 +84,6 @@ static int __init dmi_checksum(u8 *buf)
 	return sum == 0;
 }
 
-static int __init dmi_iterate(void (*decode)(struct dmi_header *))
-{
-	u8 buf[15];
-	char __iomem *p, *q;
-
-	/*
-	 * no iounmap() for that ioremap(); it would be a no-op, but it's
-	 * so early in setup that sucker gets confused into doing what
-	 * it shouldn't if we actually call it.
-	 */
-	p = ioremap(0xF0000, 0x10000);
-	if (p == NULL)
-		return -1;
-
-	for (q = p; q < p + 0x10000; q += 16) {
-		memcpy_fromio(buf, q, 15);
-		if ((memcmp(buf, "_DMI_", 5) == 0) && dmi_checksum(buf)) {
-			u16 num = (buf[13] << 8) | buf[12];
-			u16 len = (buf[7] << 8) | buf[6];
-			u32 base = (buf[11] << 24) | (buf[10] << 16) |
-				   (buf[9] << 8) | buf[8];
-
-			/*
-			 * DMI version 0.0 means that the real version is taken from
-			 * the SMBIOS version, which we don't know at this point.
-			 */
-			if (buf[14] != 0)
-				printk(KERN_INFO "DMI %d.%d present.\n",
-					buf[14] >> 4, buf[14] & 0xF);
-			else
-				printk(KERN_INFO "DMI present.\n");
-
-			dmi_printk((KERN_INFO "%d structures occupying %d bytes.\n",
-				num, len));
-			dmi_printk((KERN_INFO "DMI table at 0x%08X.\n", base));
-
-			if (dmi_table(base,len, num, decode) == 0)
-				return 0;
-		}
-	}
-	return -1;
-}
-
 static char *dmi_ident[DMI_STRING_MAX];
 
 /*
@@ -190,8 +147,46 @@ static void __init dmi_decode(struct dmi
 
 void __init dmi_scan_machine(void)
 {
-	if (dmi_iterate(dmi_decode))
-		printk(KERN_INFO "DMI not present.\n");
+	u8 buf[15];
+	char __iomem *p, *q;
+
+	/*
+	 * no iounmap() for that ioremap(); it would be a no-op, but it's
+	 * so early in setup that sucker gets confused into doing what
+	 * it shouldn't if we actually call it.
+	 */
+	p = ioremap(0xF0000, 0x10000);
+	if (p == NULL)
+		goto out;
+
+	for (q = p; q < p + 0x10000; q += 16) {
+		memcpy_fromio(buf, q, 15);
+		if ((memcmp(buf, "_DMI_", 5) == 0) && dmi_checksum(buf)) {
+			u16 num = (buf[13] << 8) | buf[12];
+			u16 len = (buf[7] << 8) | buf[6];
+			u32 base = (buf[11] << 24) | (buf[10] << 16) |
+				   (buf[9] << 8) | buf[8];
+
+			/*
+			 * DMI version 0.0 means that the real version is taken from
+			 * the SMBIOS version, which we don't know at this point.
+			 */
+			if (buf[14] != 0)
+				printk(KERN_INFO "DMI %d.%d present.\n",
+					buf[14] >> 4, buf[14] & 0xF);
+			else
+				printk(KERN_INFO "DMI present.\n");
+
+			dmi_printk((KERN_INFO "%d structures occupying %d bytes.\n",
+				num, len));
+			dmi_printk((KERN_INFO "DMI table at 0x%08X.\n", base));
+
+			if (dmi_table(base,len, num, dmi_decode) == 0)
+				return;
+		}
+	}
+
+out:	printk(KERN_INFO "DMI not present.\n");
 }
 
 


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

* [PATCH 1/5] 2.6.13-rc5-mm1, remove old debugging code
  2005-08-10 10:32 [PATCH 0/5] 2.6.13-rc5-mm1, remove uneeded function Andrey Panin
@ 2005-08-10 10:32 ` Andrey Panin
  2005-08-10 10:32   ` [PATCH 2/5] 2.6.13-rc5-mm1, make dmi_string() behave like strdup() Andrey Panin
  0 siblings, 1 reply; 9+ messages in thread
From: Andrey Panin @ 2005-08-10 10:32 UTC (permalink / raw)
  To: Andrew Morton, linux-kernel


DMI debugging code is unused for ages. This patch removes it.

Signed-off-by: Andrey Panin <pazke@donpac.ru>

 arch/i386/kernel/dmi_scan.c |   21 ---------------------
 1 files changed, 21 deletions(-)

diff -urdpNX /usr/share/dontdiff linux-2.6.13-rc5-mm1.vanilla/arch/i386/kernel/dmi_scan.c linux-2.6.13-rc5-mm1/arch/i386/kernel/dmi_scan.c
--- linux-2.6.13-rc5-mm1.vanilla/arch/i386/kernel/dmi_scan.c	2005-06-14 23:24:54.000000000 +0400
+++ linux-2.6.13-rc5-mm1/arch/i386/kernel/dmi_scan.c	2005-06-14 23:25:07.000000000 +0400
@@ -12,13 +12,6 @@ struct dmi_header {
 	u16 handle;
 };
 
-#undef DMI_DEBUG
-
-#ifdef DMI_DEBUG
-#define dmi_printk(x) printk x
-#else
-#define dmi_printk(x)
-#endif
 
 static char * __init dmi_string(struct dmi_header *dm, u8 s)
 {
@@ -117,29 +110,19 @@ static void __init dmi_decode(struct dmi
 	
 	switch(dm->type) {
 	case  0:
-		dmi_printk(("BIOS Vendor: %s\n", dmi_string(dm, data[4])));
 		dmi_save_ident(dm, DMI_BIOS_VENDOR, 4);
-		dmi_printk(("BIOS Version: %s\n", dmi_string(dm, data[5])));
 		dmi_save_ident(dm, DMI_BIOS_VERSION, 5);
-		dmi_printk(("BIOS Release: %s\n", dmi_string(dm, data[8])));
 		dmi_save_ident(dm, DMI_BIOS_DATE, 8);
 		break;
 	case 1:
-		dmi_printk(("System Vendor: %s\n", dmi_string(dm, data[4])));
 		dmi_save_ident(dm, DMI_SYS_VENDOR, 4);
-		dmi_printk(("Product Name: %s\n", dmi_string(dm, data[5])));
 		dmi_save_ident(dm, DMI_PRODUCT_NAME, 5);
-		dmi_printk(("Version: %s\n", dmi_string(dm, data[6])));
 		dmi_save_ident(dm, DMI_PRODUCT_VERSION, 6);
-		dmi_printk(("Serial Number: %s\n", dmi_string(dm, data[7])));
 		dmi_save_ident(dm, DMI_PRODUCT_SERIAL, 7);
 		break;
 	case 2:
-		dmi_printk(("Board Vendor: %s\n", dmi_string(dm, data[4])));
 		dmi_save_ident(dm, DMI_BOARD_VENDOR, 4);
-		dmi_printk(("Board Name: %s\n", dmi_string(dm, data[5])));
 		dmi_save_ident(dm, DMI_BOARD_NAME, 5);
-		dmi_printk(("Board Version: %s\n", dmi_string(dm, data[6])));
 		dmi_save_ident(dm, DMI_BOARD_VERSION, 6);
 		break;
 	}
@@ -177,10 +160,6 @@ void __init dmi_scan_machine(void)
 			else
 				printk(KERN_INFO "DMI present.\n");
 
-			dmi_printk((KERN_INFO "%d structures occupying %d bytes.\n",
-				num, len));
-			dmi_printk((KERN_INFO "DMI table at 0x%08X.\n", base));
-
 			if (dmi_table(base,len, num, dmi_decode) == 0)
 				return;
 		}


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

* [PATCH 2/5] 2.6.13-rc5-mm1, make dmi_string() behave like strdup()
  2005-08-10 10:32 ` [PATCH 1/5] 2.6.13-rc5-mm1, remove old debugging code Andrey Panin
@ 2005-08-10 10:32   ` Andrey Panin
  2005-08-10 10:32     ` [PATCH 3/5] 2.6.13-rc5-mm1, add onboard devices discovery Andrey Panin
  0 siblings, 1 reply; 9+ messages in thread
From: Andrey Panin @ 2005-08-10 10:32 UTC (permalink / raw)
  To: Andrew Morton, linux-kernel


This patch changes dmi_string() function to allocate string copy by itself,
to avoid code duplication in the next patch.

Signed-off-by: Andrey Panin <pazke@donpac.ru>

 arch/i386/kernel/dmi_scan.c |   39 +++++++++++++++++++++++----------------
 1 files changed, 23 insertions(+), 16 deletions(-)

diff -urdpNX /usr/share/dontdiff linux-2.6.13-rc5-mm1.vanilla/arch/i386/kernel/dmi_scan.c linux-2.6.13-rc5-mm1/arch/i386/kernel/dmi_scan.c
--- linux-2.6.13-rc5-mm1.vanilla/arch/i386/kernel/dmi_scan.c	2005-06-14 23:31:39.000000000 +0400
+++ linux-2.6.13-rc5-mm1/arch/i386/kernel/dmi_scan.c	2005-06-14 23:31:51.000000000 +0400
@@ -16,15 +16,25 @@ struct dmi_header {
 static char * __init dmi_string(struct dmi_header *dm, u8 s)
 {
 	u8 *bp = ((u8 *) dm) + dm->length;
+	char *str = "";
 
-	if (!s)
-		return "";
-	s--;
-	while (s > 0 && *bp) {
-		bp += strlen(bp) + 1;
+	if (s) {
 		s--;
-	}
-	return bp;
+		while (s > 0 && *bp) {
+			bp += strlen(bp) + 1;
+			s--;
+		}
+
+		if (*bp != 0) {
+			str = alloc_bootmem(strlen(bp) + 1);
+			if (str != NULL)
+				strcpy(str, bp);
+			else
+				printk(KERN_ERR "dmi_string: out of memory.\n");
+		}
+ 	}
+
+	return str;
 }
 
 /*
@@ -84,19 +94,16 @@ static char *dmi_ident[DMI_STRING_MAX];
  */
 static void __init dmi_save_ident(struct dmi_header *dm, int slot, int string)
 {
-	char *d = (char*)dm;
-	char *p = dmi_string(dm, d[string]);
+	char *p, *d = (char*) dm;
 
-	if (p == NULL || *p == 0)
-		return;
 	if (dmi_ident[slot])
 		return;
 
-	dmi_ident[slot] = alloc_bootmem(strlen(p) + 1);
-	if(dmi_ident[slot])
-		strcpy(dmi_ident[slot], p);
-	else
-		printk(KERN_ERR "dmi_save_ident: out of memory.\n");
+	p = dmi_string(dm, d[string]);
+	if (p == NULL)
+		return;
+
+	dmi_ident[slot] = p;
 }
 
 /*


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

* [PATCH 3/5] 2.6.13-rc5-mm1, add onboard devices discovery
  2005-08-10 10:32   ` [PATCH 2/5] 2.6.13-rc5-mm1, make dmi_string() behave like strdup() Andrey Panin
@ 2005-08-10 10:32     ` Andrey Panin
  2005-08-10 10:32       ` [PATCH 4/5] 2.6.13-rc5-mm1, IPMI, use dmi_find_device() Andrey Panin
  0 siblings, 1 reply; 9+ messages in thread
From: Andrey Panin @ 2005-08-10 10:32 UTC (permalink / raw)
  To: Andrew Morton, linux-kernel, cminyard


This patch adds onboard devices and IPMI BMC discovery into DMI scan code.
Drivers can use dmi_find_device() function to search for devices by type
and name.

Signed-off-by: Andrey Panin <pazke@donpac.ru>

 arch/i386/kernel/dmi_scan.c |  102 ++++++++++++++++++++++++++++++++++++++------
 include/linux/dmi.h         |   34 +++++++++++++-
 2 files changed, 121 insertions(+), 15 deletions(-)

diff -urdpNX /usr/share/dontdiff linux-2.6.13-rc5-mm1.vanilla/arch/i386/kernel/dmi_scan.c linux-2.6.13-rc5-mm1/arch/i386/kernel/dmi_scan.c
--- linux-2.6.13-rc5-mm1.vanilla/arch/i386/kernel/dmi_scan.c	2005-08-09 14:39:13.000000000 +0400
+++ linux-2.6.13-rc5-mm1/arch/i386/kernel/dmi_scan.c	2005-08-09 15:07:57.000000000 +0400
@@ -6,13 +6,6 @@
 #include <linux/bootmem.h>
 
 
-struct dmi_header {
-	u8 type;
-	u8 length;
-	u16 handle;
-};
-
-
 static char * __init dmi_string(struct dmi_header *dm, u8 s)
 {
 	u8 *bp = ((u8 *) dm) + dm->length;
@@ -88,6 +81,7 @@ static int __init dmi_checksum(u8 *buf)
 }
 
 static char *dmi_ident[DMI_STRING_MAX];
+static LIST_HEAD(dmi_devices);
 
 /*
  *	Save a DMI string
@@ -106,6 +100,58 @@ static void __init dmi_save_ident(struct
 	dmi_ident[slot] = p;
 }
 
+static void __init dmi_save_devices(struct dmi_header *dm)
+{
+	int i, count = (dm->length - sizeof(struct dmi_header)) / 2;
+	struct dmi_device *dev;
+
+	for (i = 0; i < count; i++) {
+		char *d = ((char *) dm) + (i * 2);
+
+		/* Skip disabled device */
+		if ((*d & 0x80) == 0)
+			continue;
+
+		dev = alloc_bootmem(sizeof(*dev));
+		if (!dev) {
+			printk(KERN_ERR "dmi_save_devices: out of memory.\n");
+			break;
+		}
+
+		dev->type = *d++ & 0x7f;
+		dev->name = dmi_string(dm, *d);
+		dev->device_data = NULL;
+
+		list_add(&dev->list, &dmi_devices);
+	}
+}
+
+static void __init dmi_save_ipmi_device(struct dmi_header *dm)
+{
+	struct dmi_device *dev;
+	void * data;
+
+	data = alloc_bootmem(dm->length);
+	if (data == NULL) {
+		printk(KERN_ERR "dmi_save_ipmi_device: out of memory.\n");
+		return;
+	}
+
+	memcpy(data, dm, dm->length);
+
+	dev = alloc_bootmem(sizeof(*dev));
+	if (!dev) {
+		printk(KERN_ERR "dmi_save_ipmi_device: out of memory.\n");
+		return;
+	}
+
+	dev->type = DMI_DEV_TYPE_IPMI;
+	dev->name = "IPMI controller";
+	dev->device_data = data;
+
+	list_add(&dev->list, &dmi_devices);
+}
+
 /*
  *	Process a DMI table entry. Right now all we care about are the BIOS
  *	and machine entries. For 2.5 we should pull the smbus controller info
@@ -113,25 +159,28 @@ static void __init dmi_save_ident(struct
  */
 static void __init dmi_decode(struct dmi_header *dm)
 {
-	u8 *data __attribute__((__unused__)) = (u8 *)dm;
-	
 	switch(dm->type) {
-	case  0:
+	case 0:		/* BIOS Information */
 		dmi_save_ident(dm, DMI_BIOS_VENDOR, 4);
 		dmi_save_ident(dm, DMI_BIOS_VERSION, 5);
 		dmi_save_ident(dm, DMI_BIOS_DATE, 8);
 		break;
-	case 1:
+	case 1:		/* System Information */
 		dmi_save_ident(dm, DMI_SYS_VENDOR, 4);
 		dmi_save_ident(dm, DMI_PRODUCT_NAME, 5);
 		dmi_save_ident(dm, DMI_PRODUCT_VERSION, 6);
 		dmi_save_ident(dm, DMI_PRODUCT_SERIAL, 7);
 		break;
-	case 2:
+	case 2:		/* Base Board Information */
 		dmi_save_ident(dm, DMI_BOARD_VENDOR, 4);
 		dmi_save_ident(dm, DMI_BOARD_NAME, 5);
 		dmi_save_ident(dm, DMI_BOARD_VERSION, 6);
 		break;
+	case 10:	/* Onboard Devices Information */
+		dmi_save_devices(dm);
+		break;
+	case 38:	/* IPMI Device Information */
+		dmi_save_ipmi_device(dm);
 	}
 }
 
@@ -221,3 +270,32 @@ char *dmi_get_system_info(int field)
 	return dmi_ident[field];
 }
 EXPORT_SYMBOL(dmi_get_system_info);
+
+/**
+ *	dmi_find_device - find onboard device by type/name
+ *	@type: device type or %DMI_DEV_TYPE_ANY to match all device types
+ *	@desc: device name string or %NULL to match all
+ *	@from: previous device found in search, or %NULL for new search.
+ *
+ *	Iterates through the list of known onboard devices. If a device is
+ *	found with a matching @vendor and @device, a pointer to its device
+ *	structure is returned.  Otherwise, %NULL is returned.
+ *	A new search is initiated by passing %NULL to the @from argument.
+ *	If @from is not %NULL, searches continue from next device.
+ */
+struct dmi_device * dmi_find_device(int type, const char *name,
+				    struct dmi_device *from)
+{
+	struct list_head *d, *head = from ? &from->list : &dmi_devices;
+
+	for(d = head->next; d != &dmi_devices; d = d->next) {
+		struct dmi_device *dev = list_entry(d, struct dmi_device, list);
+
+		if (((type == DMI_DEV_TYPE_ANY) || (dev->type == type)) &&
+		    ((name == NULL) || (strcmp(dev->name, name) == 0)))
+			return dev;
+	}
+
+	return NULL;
+}
+EXPORT_SYMBOL(dmi_find_device);
diff -urdpNX /usr/share/dontdiff linux-2.6.13-rc5-mm1.vanilla/include/linux/dmi.h linux-2.6.13-rc5-mm1/include/linux/dmi.h
--- linux-2.6.13-rc5-mm1.vanilla/include/linux/dmi.h	2005-06-12 23:08:16.000000000 +0400
+++ linux-2.6.13-rc5-mm1/include/linux/dmi.h	2005-06-12 22:45:19.000000000 +0400
@@ -16,6 +16,24 @@ enum dmi_field {
 	DMI_STRING_MAX,
 };
 
+enum dmi_device_type {
+	DMI_DEV_TYPE_ANY = 0,
+	DMI_DEV_TYPE_OTHER,
+	DMI_DEV_TYPE_UNKNOWN,
+	DMI_DEV_TYPE_VIDEO,
+	DMI_DEV_TYPE_SCSI,
+	DMI_DEV_TYPE_ETHERNET,
+	DMI_DEV_TYPE_TOKENRING,
+	DMI_DEV_TYPE_SOUND,
+	DMI_DEV_TYPE_IPMI = -1
+};
+
+struct dmi_header {
+	u8 type;
+	u8 length;
+	u16 handle;
+};
+
 /*
  *	DMI callbacks for problem boards
  */
@@ -26,22 +44,32 @@ struct dmi_strmatch {
 
 struct dmi_system_id {
 	int (*callback)(struct dmi_system_id *);
-	char *ident;
+	const char *ident;
 	struct dmi_strmatch matches[4];
 	void *driver_data;
 };
 
-#define DMI_MATCH(a,b)	{ a, b }
+#define DMI_MATCH(a, b)	{ a, b }
+
+struct dmi_device {
+	struct list_head list;
+	int type;
+	const char *name;
+	void *device_data;	/* Type specific data */
+};
 
 #if defined(CONFIG_X86) && !defined(CONFIG_X86_64)
 
 extern int dmi_check_system(struct dmi_system_id *list);
 extern char * dmi_get_system_info(int field);
-
+extern struct dmi_device * dmi_find_device(int type, const char *name,
+	struct dmi_device *from);
 #else
 
 static inline int dmi_check_system(struct dmi_system_id *list) { return 0; }
 static inline char * dmi_get_system_info(int field) { return NULL; }
+static struct dmi_device * dmi_find_device(int type, const char *name,
+	struct dmi_device *from) { return NULL; }
 
 #endif
 


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

* [PATCH 4/5] 2.6.13-rc5-mm1, IPMI, use dmi_find_device()
  2005-08-10 10:32     ` [PATCH 3/5] 2.6.13-rc5-mm1, add onboard devices discovery Andrey Panin
@ 2005-08-10 10:32       ` Andrey Panin
  2005-08-10 10:32         ` [PATCH 5/5] 2.6.13-rc5-mm1, driver for IBM Automatic Server Restart watchdog Andrey Panin
  2005-08-10 14:12         ` [PATCH 4/5] 2.6.13-rc5-mm1, IPMI, use dmi_find_device() Corey Minyard
  0 siblings, 2 replies; 9+ messages in thread
From: Andrey Panin @ 2005-08-10 10:32 UTC (permalink / raw)
  To: Andrew Morton, linux-kernel, cminyard


This patch replaces homebrew DMI scanning code in IPMI System Interface driver
with dmi_find_device() call.

Signed-off-by: Andrey Panin <pazke@donpac.ru>

 drivers/char/ipmi/ipmi_si_intf.c |  105 ++++++---------------------------------
 1 files changed, 17 insertions(+), 88 deletions(-)

diff -urdpNX /usr/share/dontdiff linux-2.6.13-rc5-mm1.vanilla/drivers/char/ipmi/ipmi_si_intf.c linux-2.6.13-rc5-mm1/drivers/char/ipmi/ipmi_si_intf.c
--- linux-2.6.13-rc5-mm1.vanilla/drivers/char/ipmi/ipmi_si_intf.c	2005-08-08 14:32:07.000000000 +0400
+++ linux-2.6.13-rc5-mm1/drivers/char/ipmi/ipmi_si_intf.c	2005-08-08 11:39:00.000000000 +0400
@@ -75,6 +75,7 @@ static inline void add_usec_to_timer(str
 #include <asm/io.h>
 #include "ipmi_si_sm.h"
 #include <linux/init.h>
+#include <linux/dmi.h>
 
 /* Measure times between events in the driver. */
 #undef DEBUG_TIMING
@@ -1642,22 +1643,15 @@ typedef struct dmi_ipmi_data
 static dmi_ipmi_data_t dmi_data[SI_MAX_DRIVERS];
 static int dmi_data_entries;
 
-typedef struct dmi_header
-{
-	u8	type;
-	u8	length;
-	u16	handle;
-} dmi_header_t;
-
-static int decode_dmi(dmi_header_t __iomem *dm, int intf_num)
+static int __init decode_dmi(struct dmi_header *dm, int intf_num)
 {
-	u8		__iomem *data = (u8 __iomem *)dm;
+	u8 *data = (u8 *)dm;
 	unsigned long  	base_addr;
 	u8		reg_spacing;
-	u8              len = readb(&dm->length);
+	u8              len = dm->length;
 	dmi_ipmi_data_t *ipmi_data = dmi_data+intf_num;
 
-	ipmi_data->type = readb(&data[4]);
+	ipmi_data->type = data[4];
 
 	memcpy(&base_addr, data+8, sizeof(unsigned long));
 	if (len >= 0x11) {
@@ -1672,12 +1666,12 @@ static int decode_dmi(dmi_header_t __iom
 		}
 		/* If bit 4 of byte 0x10 is set, then the lsb for the address
 		   is odd. */
-		ipmi_data->base_addr = base_addr | ((readb(&data[0x10]) & 0x10) >> 4);
+		ipmi_data->base_addr = base_addr | ((data[0x10] & 0x10) >> 4);
 
-		ipmi_data->irq = readb(&data[0x11]);
+		ipmi_data->irq = data[0x11];
 
 		/* The top two bits of byte 0x10 hold the register spacing. */
-		reg_spacing = (readb(&data[0x10]) & 0xC0) >> 6;
+		reg_spacing = (data[0x10] & 0xC0) >> 6;
 		switch(reg_spacing){
 		case 0x00: /* Byte boundaries */
 		    ipmi_data->offset = 1;
@@ -1705,7 +1699,7 @@ static int decode_dmi(dmi_header_t __iom
 		ipmi_data->offset = 1;
 	}
 
-	ipmi_data->slave_addr = readb(&data[6]);
+	ipmi_data->slave_addr = data[6];
 
 	if (is_new_interface(-1, ipmi_data->addr_space,ipmi_data->base_addr)) {
 		dmi_data_entries++;
@@ -1717,82 +1711,17 @@ static int decode_dmi(dmi_header_t __iom
 	return -1;
 }
 
-static int dmi_table(u32 base, int len, int num)
-{
-	u8 		  __iomem *buf;
-	struct dmi_header __iomem *dm;
-	u8 		  __iomem *data;
-	int 		  i=1;
-	int		  status=-1;
-	int               intf_num = 0;
-
-	buf = ioremap(base, len);
-	if(buf==NULL)
-		return -1;
-
-	data = buf;
-
-	while(i<num && (data - buf) < len)
-	{
-		dm=(dmi_header_t __iomem *)data;
-
-		if((data-buf+readb(&dm->length)) >= len)
-        		break;
-
-		if (readb(&dm->type) == 38) {
-			if (decode_dmi(dm, intf_num) == 0) {
-				intf_num++;
-				if (intf_num >= SI_MAX_DRIVERS)
-					break;
-			}
-		}
-
-	        data+=readb(&dm->length);
-		while((data-buf) < len && (readb(data)||readb(data+1)))
-			data++;
-		data+=2;
-		i++;
-	}
-	iounmap(buf);
-
-	return status;
-}
-
-static inline int dmi_checksum(u8 *buf)
-{
-	u8   sum=0;
-	int  a;
-
-	for(a=0; a<15; a++)
-		sum+=buf[a];
-	return (sum==0);
-}
-
-static int dmi_decode(void)
+static void __init dmi_find_bmc(void)
 {
-	u8   buf[15];
-	u32  fp=0xF0000;
-
-#ifdef CONFIG_SIMNOW
-	return -1;
-#endif
+	struct dmi_device *dev = NULL;
+	int intf_num = 0;
 
-	while(fp < 0xFFFFF)
-	{
-		isa_memcpy_fromio(buf, fp, 15);
-		if(memcmp(buf, "_DMI_", 5)==0 && dmi_checksum(buf))
-		{
-			u16 num=buf[13]<<8|buf[12];
-			u16 len=buf[7]<<8|buf[6];
-			u32 base=buf[11]<<24|buf[10]<<16|buf[9]<<8|buf[8];
+	while ((dev = dmi_find_device(DMI_DEV_TYPE_IPMI, NULL, dev))) {
+		if (intf_num >= SI_MAX_DRIVERS)
+			break;
 
-			if(dmi_table(base, len, num) == 0)
-				return 0;
-		}
-		fp+=16;
+		decode_dmi((struct dmi_header *) dev->device_data, intf_num++);
 	}
-
-	return -1;
 }
 
 static int try_init_smbios(int intf_num, struct smi_info **new_info)
@@ -2382,7 +2311,7 @@ static __init int init_ipmi_si(void)
 	printk(KERN_INFO "IPMI System Interface driver.\n");
 
 #ifdef CONFIG_X86
-	dmi_decode();
+	dmi_find_bmc();
 #endif
 
 	rv = init_one_smi(0, &(smi_infos[pos]));


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

* [PATCH 5/5] 2.6.13-rc5-mm1, driver for IBM Automatic Server Restart watchdog
  2005-08-10 10:32       ` [PATCH 4/5] 2.6.13-rc5-mm1, IPMI, use dmi_find_device() Andrey Panin
@ 2005-08-10 10:32         ` Andrey Panin
  2005-08-17 20:14           ` Andrew Morton
  2005-08-10 14:12         ` [PATCH 4/5] 2.6.13-rc5-mm1, IPMI, use dmi_find_device() Corey Minyard
  1 sibling, 1 reply; 9+ messages in thread
From: Andrey Panin @ 2005-08-10 10:32 UTC (permalink / raw)
  To: Andrew Morton, linux-kernel


This patch adds driver for IBM Automatic Server Restart watchdog hardware
found in some IBM eServer xSeries machines. This driver is based on the ugly
driver provided by IBM. Driver was tested on IBM eServer 226.

Signed-off-by: Andrey Panin <pazke@donpac.ru>

 drivers/char/watchdog/Kconfig  |   10 +
 drivers/char/watchdog/Makefile |    1 
 drivers/char/watchdog/ibmasr.c |  407 +++++++++++++++++++++++++++++++++++++++++
 3 files changed, 418 insertions(+)

diff -urdpN linux-2.6.13-rc5-mm1.vanilla/drivers/char/watchdog/ibmasr.c linux-2.6.13-rc5-mm1/drivers/char/watchdog/ibmasr.c
--- linux-2.6.13-rc5-mm1.vanilla/drivers/char/watchdog/ibmasr.c	1970-01-01 03:00:00.000000000 +0300
+++ linux-2.6.13-rc5-mm1/drivers/char/watchdog/ibmasr.c	2005-08-10 11:43:45.000000000 +0400
@@ -0,0 +1,407 @@
+/*
+ * IBM Automatic Server Restart driver.
+ *
+ * Copyright (c) 2005 Andrey Panin <pazke@donpac.ru>
+ *
+ * Based on driver written by Pete Reynolds.
+ * Copyright (c) IBM Corporation, 1998-2004.
+ *
+ * This software may be used and distributed according to the terms
+ * of the GNU Public License, incorporated herein by reference.
+ */
+
+#include <linux/config.h>
+#include <linux/fs.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/timer.h>
+#include <linux/miscdevice.h>
+#include <linux/watchdog.h>
+#include <linux/dmi.h>
+
+#include <asm/io.h>
+#include <asm/uaccess.h>
+
+
+enum {
+	ASMTYPE_UNKNOWN,
+	ASMTYPE_TOPAZ,
+	ASMTYPE_JASPER,
+	ASMTYPE_PEARL,
+	ASMTYPE_JUNIPER,
+	ASMTYPE_SPRUCE,
+};
+
+#define PFX "ibmasr: "
+
+#define TOPAZ_ASR_REG_OFFSET	4
+#define TOPAZ_ASR_TOGGLE	0x40
+#define TOPAZ_ASR_DISABLE	0x80
+
+/* PEARL ASR S/W REGISTER SUPERIO PORT ADDRESSES */
+#define PEARL_BASE	0xe04
+#define PEARL_WRITE	0xe06
+#define PEARL_READ	0xe07
+
+#define PEARL_ASR_DISABLE_MASK	0x80	/* bit 7: disable = 1, enable = 0 */
+#define PEARL_ASR_TOGGLE_MASK	0x40	/* bit 6: 0, then 1, then 0 */
+
+/* JASPER OFFSET FROM SIO BASE ADDR TO ASR S/W REGISTERS. */
+#define JASPER_ASR_REG_OFFSET	0x38
+
+#define JASPER_ASR_DISABLE_MASK	0x01	/* bit 0: disable = 1, enable = 0 */
+#define JASPER_ASR_TOGGLE_MASK	0x02	/* bit 1: 0, then 1, then 0 */
+
+#define JUNIPER_BASE_ADDRESS	0x54b	/* Base address of Juniper ASR */
+#define JUNIPER_ASR_DISABLE_MASK 0x01	/* bit 0: disable = 1 enable = 0 */
+#define JUNIPER_ASR_TOGGLE_MASK	0x02	/* bit 1: 0, then 1, then 0 */
+
+#define SPRUCE_BASE_ADDRESS	0x118e	/* Base address of Spruce ASR */
+#define SPRUCE_ASR_DISABLE_MASK	0x01	/* bit 1: disable = 1 enable = 0 */
+#define SPRUCE_ASR_TOGGLE_MASK	0x02	/* bit 0: 0, then 1, then 0 */
+
+
+static int nowayout = WATCHDOG_NOWAYOUT;
+
+static unsigned long asr_is_open;
+static char asr_expect_close;
+
+static unsigned int asr_type, asr_base, asr_length;
+static unsigned int asr_read_addr, asr_write_addr;
+static unsigned char asr_toggle_mask, asr_disable_mask;
+
+static void asr_toggle(void)
+{
+	unsigned char reg = inb(asr_read_addr);
+
+	outb(reg & ~asr_toggle_mask, asr_write_addr);
+	reg = inb(asr_read_addr);
+
+	outb(reg | asr_toggle_mask, asr_write_addr);
+	reg = inb(asr_read_addr);
+
+	outb(reg & ~asr_toggle_mask, asr_write_addr);
+	reg = inb(asr_read_addr);
+}
+
+static void asr_enable(void)
+{
+	unsigned char reg;
+
+	if (asr_type == ASMTYPE_TOPAZ) {
+		/* asr_write_addr == asr_read_addr */
+		reg = inb(asr_read_addr);
+		outb(reg & ~(TOPAZ_ASR_TOGGLE | TOPAZ_ASR_DISABLE),
+		     asr_read_addr);
+	} else {
+		/*
+		 * First make sure the hardware timer is reset by toggling
+		 * ASR hardware timer line.
+		 */
+		asr_toggle();
+
+		reg = inb(asr_read_addr);
+		outb(reg & ~asr_disable_mask, asr_write_addr);
+	}
+	reg = inb(asr_read_addr);
+}
+
+static void asr_disable(void)
+{
+	unsigned char reg = inb(asr_read_addr);
+
+	if (asr_type == ASMTYPE_TOPAZ)
+		/* asr_write_addr == asr_read_addr */
+		outb(reg | TOPAZ_ASR_TOGGLE | TOPAZ_ASR_DISABLE,
+		     asr_read_addr);
+	else {
+		outb(reg | asr_toggle_mask, asr_write_addr);
+		reg = inb(asr_read_addr);
+
+		outb(reg | asr_disable_mask, asr_write_addr);
+	}
+	reg = inb(asr_read_addr);
+}
+
+static int __init asr_get_base_address(void)
+{
+	unsigned char low, high;
+	const char *type = "";
+
+	asr_length = 1;
+
+	switch (asr_type) {
+	case ASMTYPE_TOPAZ:
+		/* SELECT SuperIO CHIP FOR QUERYING (WRITE 0x07 TO BOTH 0x2E and 0x2F) */
+		outb(0x07, 0x2e);
+		outb(0x07, 0x2f);
+
+		/* SELECT AND READ THE HIGH-NIBBLE OF THE GPIO BASE ADDRESS */
+		outb(0x60, 0x2e);
+		high = inb(0x2f);
+
+		/* SELECT AND READ THE LOW-NIBBLE OF THE GPIO BASE ADDRESS */
+		outb(0x61, 0x2e);
+		low = inb(0x2f);
+
+		asr_base = (high << 16) | low;
+		asr_read_addr = asr_write_addr =
+			asr_base + TOPAZ_ASR_REG_OFFSET;
+		asr_length = 5;
+
+		break;
+
+	case ASMTYPE_JASPER:
+		type = "Jaspers ";
+
+		/* FIXME: need to use pci_config_lock here, but it's not exported */
+
+/*		spin_lock_irqsave(&pci_config_lock, flags);*/
+
+		/* Select the SuperIO chip in the PCI I/O port register */
+		outl(0x8000f858, 0xcf8);
+
+		/* 
+		 * Read the base address for the SuperIO chip.
+		 * Only the lower 16 bits are valid, but the address is word 
+		 * aligned so the last bit must be masked off.
+		 */
+		asr_base = inl(0xcfc) & 0xfffe;
+
+/*		spin_unlock_irqrestore(&pci_config_lock, flags);*/
+
+		asr_read_addr = asr_write_addr = 
+			asr_base + JASPER_ASR_REG_OFFSET;
+		asr_toggle_mask = JASPER_ASR_TOGGLE_MASK;
+		asr_disable_mask = JASPER_ASR_DISABLE_MASK;
+		asr_length = JASPER_ASR_REG_OFFSET + 1; 
+
+		break;
+
+	case ASMTYPE_PEARL:
+		type = "Pearls ";
+		asr_base = PEARL_BASE;
+		asr_read_addr = PEARL_READ;
+		asr_write_addr = PEARL_WRITE;
+		asr_toggle_mask = PEARL_ASR_TOGGLE_MASK;
+		asr_disable_mask = PEARL_ASR_DISABLE_MASK;
+		asr_length = 4;
+		break;
+
+	case ASMTYPE_JUNIPER:
+		type = "Junipers ";
+		asr_base = JUNIPER_BASE_ADDRESS;
+		asr_read_addr = asr_write_addr = asr_base;
+		asr_toggle_mask = JUNIPER_ASR_TOGGLE_MASK;
+		asr_disable_mask = JUNIPER_ASR_DISABLE_MASK;
+		break;
+
+	case ASMTYPE_SPRUCE:
+		type = "Spruce's ";
+		asr_base = SPRUCE_BASE_ADDRESS;
+		asr_read_addr = asr_write_addr = asr_base;
+		asr_toggle_mask = SPRUCE_ASR_TOGGLE_MASK;
+		asr_disable_mask = SPRUCE_ASR_DISABLE_MASK;
+		break;
+	}
+
+	if (!request_region(asr_base, asr_length, "ibmasr")) {
+		printk(KERN_ERR PFX "address %#x already in use\n",
+			asr_base);
+		return -EBUSY;
+	}
+
+	printk(KERN_INFO PFX "found %sASR @ addr %#x\n", type, asr_base);
+
+	return 0;
+}
+
+
+static ssize_t asr_write(struct file *file, const char __user *buf,
+			 size_t count, loff_t *ppos)
+{
+	if (count) {
+		if (!nowayout) {
+			size_t i;
+
+			/* In case it was set long ago */
+			asr_expect_close = 0;
+
+			for (i = 0; i != count; i++) {
+				char c;
+				if (get_user(c, buf + i))
+					return -EFAULT;
+				if (c == 'V')
+					asr_expect_close = 42;
+			}
+		}
+		asr_toggle();
+	}
+	return count;
+}
+
+static int asr_ioctl(struct inode *inode, struct file *file,
+		     unsigned int cmd, unsigned long arg)
+{
+	static const struct watchdog_info ident = {
+		.options =	WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT |
+				WDIOF_MAGICCLOSE,
+		.identity =	"IBM ASR"
+	};
+	void __user *argp = (void __user *)arg;
+	int __user *p = argp;
+	int heartbeat;
+
+	switch (cmd) {
+		case WDIOC_GETSUPPORT:
+			return copy_to_user(argp, &ident, sizeof(ident)) ? 
+				-EFAULT : 0;
+
+		case WDIOC_GETSTATUS:
+		case WDIOC_GETBOOTSTATUS:
+			return put_user(0, p);
+
+		case WDIOC_KEEPALIVE:
+			asr_toggle();
+			return 0;
+
+
+		case WDIOC_SETTIMEOUT:
+			if (get_user(heartbeat, p))
+				return -EFAULT;
+			/* Fall */
+
+		case WDIOC_GETTIMEOUT:
+			heartbeat = 256;
+			return put_user(heartbeat, p);
+
+		case WDIOC_SETOPTIONS: {
+			int new_options, retval = -EINVAL;
+
+			if (get_user(new_options, p))
+				return -EFAULT;
+
+			if (new_options & WDIOS_DISABLECARD) {
+				asr_disable();
+				retval = 0;
+			}
+
+			if (new_options & WDIOS_ENABLECARD) {
+				asr_enable();
+				asr_toggle();
+				retval = 0;
+			}
+
+			return retval;
+		}
+	}
+
+	return -ENOIOCTLCMD;
+}
+
+static int asr_open(struct inode *inode, struct file *file)
+{
+	if(test_and_set_bit(0, &asr_is_open))
+		return -EBUSY;
+
+	asr_toggle();
+	asr_enable();
+
+	return nonseekable_open(inode, file);
+}
+
+static int asr_release(struct inode *inode, struct file *file)
+{
+	if (asr_expect_close == 42)
+		asr_disable();
+	else {
+		printk(KERN_CRIT PFX "unexpected close, not stopping watchdog!\n");
+		asr_toggle();
+	}
+	clear_bit(0, &asr_is_open);
+	asr_expect_close = 0;
+	return 0;
+}
+
+static struct file_operations asr_fops = {
+	.owner =	THIS_MODULE,
+	.llseek	=	no_llseek,
+	.write =	asr_write,
+	.ioctl =	asr_ioctl,
+	.open =		asr_open,
+	.release =	asr_release,
+};
+
+static struct miscdevice asr_miscdev = {
+	.minor =	WATCHDOG_MINOR,
+	.name =		"watchdog",
+	.fops =		&asr_fops,
+};
+
+
+struct ibmasr_id {
+	const char *desc;
+	int type;
+};
+
+static struct ibmasr_id __initdata ibmasr_id_table[] = {
+	{ "IBM Automatic Server Restart - eserver xSeries 220", ASMTYPE_TOPAZ },
+	{ "IBM Automatic Server Restart - Machine Type 8673", ASMTYPE_PEARL },
+	{ "IBM Automatic Server Restart - Machine Type 8480", ASMTYPE_JASPER },
+	{ "IBM Automatic Server Restart - Machine Type 8482", ASMTYPE_JUNIPER },
+	{ "IBM Automatic Server Restart - Machine Type 8648", ASMTYPE_SPRUCE },
+	{ NULL }
+};
+
+static int __init ibmasr_init(void)
+{
+	struct ibmasr_id *id;
+	int rc;
+
+	for (id = ibmasr_id_table; id->desc; id++) {
+		if (dmi_find_device(DMI_DEV_TYPE_OTHER, id->desc, NULL)) {
+			asr_type = id->type;
+			break;
+		}
+	} 
+
+	if (!asr_type)
+		return -ENODEV;
+
+	rc = misc_register(&asr_miscdev);
+	if (rc < 0) {
+		printk(KERN_ERR PFX "failed to register misc device\n");
+		return rc;
+	}
+
+	rc = asr_get_base_address();
+	if (rc) {
+		misc_deregister(&asr_miscdev);
+		return rc;
+	}
+
+	return 0;
+}
+
+static void __exit ibmasr_exit(void)
+{
+	if (!nowayout)
+		asr_disable();
+
+	misc_deregister(&asr_miscdev);
+
+	release_region(asr_base, asr_length);
+}
+
+module_init(ibmasr_init);
+module_exit(ibmasr_exit);
+
+module_param(nowayout, int, 0);
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
+
+MODULE_DESCRIPTION("IBM Automatic Server Restart driver");
+MODULE_AUTHOR("Andrey Panin");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
diff -urdpN linux-2.6.13-rc5-mm1.vanilla/drivers/char/watchdog/Kconfig linux-2.6.13-rc5-mm1/drivers/char/watchdog/Kconfig
--- linux-2.6.13-rc5-mm1.vanilla/drivers/char/watchdog/Kconfig	2005-08-09 11:03:44.000000000 +0400
+++ linux-2.6.13-rc5-mm1/drivers/char/watchdog/Kconfig	2005-08-08 13:55:10.000000000 +0400
@@ -548,6 +548,16 @@ config WDT_501_PCI
 	  can do this via the tachometer parameter. Only do this if you have a
 	  fan tachometer actually set up.
 
+config IBMASR
+        tristate "IBM Automatic Server Restart"
+        depends on WATCHDOG && X86
+        help
+	  This is the driver for the IBM Automatic Server Restart watchdog
+	  timer builtin into some eServer xSeries machines.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called ibmasr.
+
 #
 # USB-based Watchdog Cards
 #
diff -urdpN linux-2.6.13-rc5-mm1.vanilla/drivers/char/watchdog/Makefile linux-2.6.13-rc5-mm1/drivers/char/watchdog/Makefile
--- linux-2.6.13-rc5-mm1.vanilla/drivers/char/watchdog/Makefile	2005-08-09 11:03:44.000000000 +0400
+++ linux-2.6.13-rc5-mm1/drivers/char/watchdog/Makefile	2005-08-08 13:55:10.000000000 +0400
@@ -48,6 +48,7 @@ obj-$(CONFIG_CPU5_WDT) += cpu5wdt.o
 obj-$(CONFIG_W83627HF_WDT) += w83627hf_wdt.o
 obj-$(CONFIG_W83877F_WDT) += w83877f_wdt.o
 obj-$(CONFIG_MACHZ_WDT) += machzwd.o
+obj-$(CONFIG_IBMASR) += ibmasr.o
 
 # PowerPC Architecture
 obj-$(CONFIG_8xx_WDT) += mpc8xx_wdt.o


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

* Re: [PATCH 4/5] 2.6.13-rc5-mm1, IPMI, use dmi_find_device()
  2005-08-10 10:32       ` [PATCH 4/5] 2.6.13-rc5-mm1, IPMI, use dmi_find_device() Andrey Panin
  2005-08-10 10:32         ` [PATCH 5/5] 2.6.13-rc5-mm1, driver for IBM Automatic Server Restart watchdog Andrey Panin
@ 2005-08-10 14:12         ` Corey Minyard
  1 sibling, 0 replies; 9+ messages in thread
From: Corey Minyard @ 2005-08-10 14:12 UTC (permalink / raw)
  To: Andrey Panin; +Cc: Andrew Morton, linux-kernel

Andrew, this patch (along with the patch 3/5) works fine for me and is
an obvious improvement to the IPMI driver.  You will need to remove the
patch named dmi_table-counting-in-ipmi_si_intfc.patch first.

Thanks, Andrey.

-Corey

On Wed, 2005-08-10 at 14:32 +0400, Andrey Panin wrote:
> This patch replaces homebrew DMI scanning code in IPMI System Interface driver
> with dmi_find_device() call.
> 
> Signed-off-by: Andrey Panin <pazke@donpac.ru>
> 
>  drivers/char/ipmi/ipmi_si_intf.c |  105 ++++++---------------------------------
>  1 files changed, 17 insertions(+), 88 deletions(-)
> 
> diff -urdpNX /usr/share/dontdiff linux-2.6.13-rc5-mm1.vanilla/drivers/char/ipmi/ipmi_si_intf.c linux-2.6.13-rc5-mm1/drivers/char/ipmi/ipmi_si_intf.c
> --- linux-2.6.13-rc5-mm1.vanilla/drivers/char/ipmi/ipmi_si_intf.c	2005-08-08 14:32:07.000000000 +0400
> +++ linux-2.6.13-rc5-mm1/drivers/char/ipmi/ipmi_si_intf.c	2005-08-08 11:39:00.000000000 +0400
> @@ -75,6 +75,7 @@ static inline void add_usec_to_timer(str
>  #include <asm/io.h>
>  #include "ipmi_si_sm.h"
>  #include <linux/init.h>
> +#include <linux/dmi.h>
>  
>  /* Measure times between events in the driver. */
>  #undef DEBUG_TIMING
> @@ -1642,22 +1643,15 @@ typedef struct dmi_ipmi_data
>  static dmi_ipmi_data_t dmi_data[SI_MAX_DRIVERS];
>  static int dmi_data_entries;
>  
> -typedef struct dmi_header
> -{
> -	u8	type;
> -	u8	length;
> -	u16	handle;
> -} dmi_header_t;
> -
> -static int decode_dmi(dmi_header_t __iomem *dm, int intf_num)
> +static int __init decode_dmi(struct dmi_header *dm, int intf_num)
>  {
> -	u8		__iomem *data = (u8 __iomem *)dm;
> +	u8 *data = (u8 *)dm;
>  	unsigned long  	base_addr;
>  	u8		reg_spacing;
> -	u8              len = readb(&dm->length);
> +	u8              len = dm->length;
>  	dmi_ipmi_data_t *ipmi_data = dmi_data+intf_num;
>  
> -	ipmi_data->type = readb(&data[4]);
> +	ipmi_data->type = data[4];
>  
>  	memcpy(&base_addr, data+8, sizeof(unsigned long));
>  	if (len >= 0x11) {
> @@ -1672,12 +1666,12 @@ static int decode_dmi(dmi_header_t __iom
>  		}
>  		/* If bit 4 of byte 0x10 is set, then the lsb for the address
>  		   is odd. */
> -		ipmi_data->base_addr = base_addr | ((readb(&data[0x10]) & 0x10) >> 4);
> +		ipmi_data->base_addr = base_addr | ((data[0x10] & 0x10) >> 4);
>  
> -		ipmi_data->irq = readb(&data[0x11]);
> +		ipmi_data->irq = data[0x11];
>  
>  		/* The top two bits of byte 0x10 hold the register spacing. */
> -		reg_spacing = (readb(&data[0x10]) & 0xC0) >> 6;
> +		reg_spacing = (data[0x10] & 0xC0) >> 6;
>  		switch(reg_spacing){
>  		case 0x00: /* Byte boundaries */
>  		    ipmi_data->offset = 1;
> @@ -1705,7 +1699,7 @@ static int decode_dmi(dmi_header_t __iom
>  		ipmi_data->offset = 1;
>  	}
>  
> -	ipmi_data->slave_addr = readb(&data[6]);
> +	ipmi_data->slave_addr = data[6];
>  
>  	if (is_new_interface(-1, ipmi_data->addr_space,ipmi_data->base_addr)) {
>  		dmi_data_entries++;
> @@ -1717,82 +1711,17 @@ static int decode_dmi(dmi_header_t __iom
>  	return -1;
>  }
>  
> -static int dmi_table(u32 base, int len, int num)
> -{
> -	u8 		  __iomem *buf;
> -	struct dmi_header __iomem *dm;
> -	u8 		  __iomem *data;
> -	int 		  i=1;
> -	int		  status=-1;
> -	int               intf_num = 0;
> -
> -	buf = ioremap(base, len);
> -	if(buf==NULL)
> -		return -1;
> -
> -	data = buf;
> -
> -	while(i<num && (data - buf) < len)
> -	{
> -		dm=(dmi_header_t __iomem *)data;
> -
> -		if((data-buf+readb(&dm->length)) >= len)
> -        		break;
> -
> -		if (readb(&dm->type) == 38) {
> -			if (decode_dmi(dm, intf_num) == 0) {
> -				intf_num++;
> -				if (intf_num >= SI_MAX_DRIVERS)
> -					break;
> -			}
> -		}
> -
> -	        data+=readb(&dm->length);
> -		while((data-buf) < len && (readb(data)||readb(data+1)))
> -			data++;
> -		data+=2;
> -		i++;
> -	}
> -	iounmap(buf);
> -
> -	return status;
> -}
> -
> -static inline int dmi_checksum(u8 *buf)
> -{
> -	u8   sum=0;
> -	int  a;
> -
> -	for(a=0; a<15; a++)
> -		sum+=buf[a];
> -	return (sum==0);
> -}
> -
> -static int dmi_decode(void)
> +static void __init dmi_find_bmc(void)
>  {
> -	u8   buf[15];
> -	u32  fp=0xF0000;
> -
> -#ifdef CONFIG_SIMNOW
> -	return -1;
> -#endif
> +	struct dmi_device *dev = NULL;
> +	int intf_num = 0;
>  
> -	while(fp < 0xFFFFF)
> -	{
> -		isa_memcpy_fromio(buf, fp, 15);
> -		if(memcmp(buf, "_DMI_", 5)==0 && dmi_checksum(buf))
> -		{
> -			u16 num=buf[13]<<8|buf[12];
> -			u16 len=buf[7]<<8|buf[6];
> -			u32 base=buf[11]<<24|buf[10]<<16|buf[9]<<8|buf[8];
> +	while ((dev = dmi_find_device(DMI_DEV_TYPE_IPMI, NULL, dev))) {
> +		if (intf_num >= SI_MAX_DRIVERS)
> +			break;
>  
> -			if(dmi_table(base, len, num) == 0)
> -				return 0;
> -		}
> -		fp+=16;
> +		decode_dmi((struct dmi_header *) dev->device_data, intf_num++);
>  	}
> -
> -	return -1;
>  }
>  
>  static int try_init_smbios(int intf_num, struct smi_info **new_info)
> @@ -2382,7 +2311,7 @@ static __init int init_ipmi_si(void)
>  	printk(KERN_INFO "IPMI System Interface driver.\n");
>  
>  #ifdef CONFIG_X86
> -	dmi_decode();
> +	dmi_find_bmc();
>  #endif
>  
>  	rv = init_one_smi(0, &(smi_infos[pos]));
> 


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

* Re: [PATCH 5/5] 2.6.13-rc5-mm1, driver for IBM Automatic Server Restart watchdog
  2005-08-10 10:32         ` [PATCH 5/5] 2.6.13-rc5-mm1, driver for IBM Automatic Server Restart watchdog Andrey Panin
@ 2005-08-17 20:14           ` Andrew Morton
  2005-08-18  4:49             ` Andrey Panin
  0 siblings, 1 reply; 9+ messages in thread
From: Andrew Morton @ 2005-08-17 20:14 UTC (permalink / raw)
  To: Andrey Panin; +Cc: linux-kernel, Greg KH

Andrey Panin <pazke@donpac.ru> wrote:
>
> 
> This patch adds driver for IBM Automatic Server Restart watchdog hardware
> found in some IBM eServer xSeries machines. This driver is based on the ugly
> driver provided by IBM. Driver was tested on IBM eServer 226.
> 
> ...
> +
> +	case ASMTYPE_JASPER:
> +		type = "Jaspers ";
> +
> +		/* FIXME: need to use pci_config_lock here, but it's not exported */

That's gregkh material.

> +
> +/*		spin_lock_irqsave(&pci_config_lock, flags);*/
> +
> +		/* Select the SuperIO chip in the PCI I/O port register */
> +		outl(0x8000f858, 0xcf8);
> +
> +		/* 
> +		 * Read the base address for the SuperIO chip.
> +		 * Only the lower 16 bits are valid, but the address is word 
> +		 * aligned so the last bit must be masked off.
> +		 */
> +		asr_base = inl(0xcfc) & 0xfffe;
> +
> +/*		spin_unlock_irqrestore(&pci_config_lock, flags);*/
>
> ...
>
> +static int asr_ioctl(struct inode *inode, struct file *file,
> +		     unsigned int cmd, unsigned long arg)
> +{
> +	static const struct watchdog_info ident = {
> +		.options =	WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT |
> +				WDIOF_MAGICCLOSE,
> +		.identity =	"IBM ASR"
> +	};
> +	void __user *argp = (void __user *)arg;
> +	int __user *p = argp;
> +	int heartbeat;
> +
> +	switch (cmd) {
> +		case WDIOC_GETSUPPORT:
> +			return copy_to_user(argp, &ident, sizeof(ident)) ? 
> +				-EFAULT : 0;
> +
> +		case WDIOC_GETSTATUS:
> +		case WDIOC_GETBOOTSTATUS:
> +			return put_user(0, p);
> +
> +		case WDIOC_KEEPALIVE:
> +			asr_toggle();
> +			return 0;
> +
> +
> +		case WDIOC_SETTIMEOUT:
> +			if (get_user(heartbeat, p))
> +				return -EFAULT;
> +			/* Fall */
> +
> +		case WDIOC_GETTIMEOUT:
> +			heartbeat = 256;
> +			return put_user(heartbeat, p);

Something very wrong is happening with WDIOC_SETTIMEOUT and
WDIOC_GETTIMEOUT.  They're both no-ops and the effect of WDIOC_SETTIMEOUT
is immidiately overwritten.


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

* Re: [PATCH 5/5] 2.6.13-rc5-mm1, driver for IBM Automatic Server Restart watchdog
  2005-08-17 20:14           ` Andrew Morton
@ 2005-08-18  4:49             ` Andrey Panin
  0 siblings, 0 replies; 9+ messages in thread
From: Andrey Panin @ 2005-08-18  4:49 UTC (permalink / raw)
  To: Andrew Morton; +Cc: linux-kernel

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

On 229, 08 17, 2005 at 01:14:15PM -0700, Andrew Morton wrote:
> Andrey Panin <pazke@donpac.ru> wrote:
> >
> > 
> > This patch adds driver for IBM Automatic Server Restart watchdog hardware
> > found in some IBM eServer xSeries machines. This driver is based on the ugly
> > driver provided by IBM. Driver was tested on IBM eServer 226.
> > 
> > ...
> > +
> > +	case ASMTYPE_JASPER:
> > +		type = "Jaspers ";
> > +
> > +		/* FIXME: need to use pci_config_lock here, but it's not exported */
> 
> That's gregkh material.
> 
> > +
> > +/*		spin_lock_irqsave(&pci_config_lock, flags);*/
> > +
> > +		/* Select the SuperIO chip in the PCI I/O port register */
> > +		outl(0x8000f858, 0xcf8);
> > +
> > +		/* 
> > +		 * Read the base address for the SuperIO chip.
> > +		 * Only the lower 16 bits are valid, but the address is word 
> > +		 * aligned so the last bit must be masked off.
> > +		 */
> > +		asr_base = inl(0xcfc) & 0xfffe;
> > +
> > +/*		spin_unlock_irqrestore(&pci_config_lock, flags);*/
> >
> > ...
> >
> > +static int asr_ioctl(struct inode *inode, struct file *file,
> > +		     unsigned int cmd, unsigned long arg)
> > +{
> > +	static const struct watchdog_info ident = {
> > +		.options =	WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT |
> > +				WDIOF_MAGICCLOSE,
> > +		.identity =	"IBM ASR"
> > +	};
> > +	void __user *argp = (void __user *)arg;
> > +	int __user *p = argp;
> > +	int heartbeat;
> > +
> > +	switch (cmd) {
> > +		case WDIOC_GETSUPPORT:
> > +			return copy_to_user(argp, &ident, sizeof(ident)) ? 
> > +				-EFAULT : 0;
> > +
> > +		case WDIOC_GETSTATUS:
> > +		case WDIOC_GETBOOTSTATUS:
> > +			return put_user(0, p);
> > +
> > +		case WDIOC_KEEPALIVE:
> > +			asr_toggle();
> > +			return 0;
> > +
> > +
> > +		case WDIOC_SETTIMEOUT:
> > +			if (get_user(heartbeat, p))
> > +				return -EFAULT;
> > +			/* Fall */
> > +
> > +		case WDIOC_GETTIMEOUT:
> > +			heartbeat = 256;
> > +			return put_user(heartbeat, p);
> 
> Something very wrong is happening with WDIOC_SETTIMEOUT and
> WDIOC_GETTIMEOUT.  They're both no-ops and the effect of WDIOC_SETTIMEOUT
> is immidiately overwritten.

Hardware has fixed timeout value, so WDIOC_SETTIMEOUT is noop and WDIOC_GETTIMEOUT
always returns 256.

-- 
Andrey Panin		| Linux and UNIX system administrator
pazke@donpac.ru		| PGP key: wwwkeys.pgp.net

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

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

end of thread, other threads:[~2005-08-18  4:49 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2005-08-10 10:32 [PATCH 0/5] 2.6.13-rc5-mm1, remove uneeded function Andrey Panin
2005-08-10 10:32 ` [PATCH 1/5] 2.6.13-rc5-mm1, remove old debugging code Andrey Panin
2005-08-10 10:32   ` [PATCH 2/5] 2.6.13-rc5-mm1, make dmi_string() behave like strdup() Andrey Panin
2005-08-10 10:32     ` [PATCH 3/5] 2.6.13-rc5-mm1, add onboard devices discovery Andrey Panin
2005-08-10 10:32       ` [PATCH 4/5] 2.6.13-rc5-mm1, IPMI, use dmi_find_device() Andrey Panin
2005-08-10 10:32         ` [PATCH 5/5] 2.6.13-rc5-mm1, driver for IBM Automatic Server Restart watchdog Andrey Panin
2005-08-17 20:14           ` Andrew Morton
2005-08-18  4:49             ` Andrey Panin
2005-08-10 14:12         ` [PATCH 4/5] 2.6.13-rc5-mm1, IPMI, use dmi_find_device() Corey Minyard

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox