All of lore.kernel.org
 help / color / mirror / Atom feed
* watchdog driver for W83627HF chip
From: zhz @ 2002-12-19  2:54 UTC (permalink / raw)
  To: linux-kernel

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

hi, man,
 
    I have written the watchdog driver for the Winbond W83627HF 
chip.  The attachment is the driver source code. Any suggestion is
welcome.
    Thanks a lot.
                            
Regards, 
Zhou HongZhen

[-- Attachment #2: w83627hf_wdt.c --]
[-- Type: application/octet-stream, Size: 15443 bytes --]


/*
 * 	W83627HF watchdog driver for Linux 2.2.x
 *
 * 	(c) Copyright 2002	Zhou HongZhen.
 *
 *	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
 *	2 of the License, or (at your option) any later version.
 *
 *	(c) Copyright 2002	Zhou HongZhen <inetbash@yahoo.com>
 *	                                      <netdiff@netease.com>
 *
 *	Release 1.0.
 *
 *	Fixes
 *
 * */

#include <linux/module.h>
#include <linux/config.h>
#include <linux/version.h>
#include <linux/types.h>
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/sched.h>
#include <linux/miscdevice.h>
#include <linux/init.h>
#include <linux/smp_lock.h>
#include <asm/param.h>
#include <asm/io.h>
#include <linux/ioport.h>
#include <asm/system.h>
#include <asm/semaphore.h>
#include <linux/sysctl.h>
#include <asm/uaccess.h>
#include <linux/notifier.h>
#include <linux/reboot.h>
#include <linux/watchdog.h>

#if 0
#define W83627HF_WDT_DEBUG
#endif

#if 0
#undef CONFIG_WATCHDOG_NOWAYOUT
#else
#define CONFIG_WATCHDOG_NOWAYOUT
#endif

#ifdef W83627HF_WDT_DEBUG
#define assert_w83627hf_wdt(p) if (1) {\
	if (!(p)) \
		panic("assert failed in %s line %d\n", __FILE__, __LINE__);\
} else

#else
#define assert_w83627hf_wdt(p)
#endif

#define W83627HF_LPCIP 0x295 /* LPC Index Port */
#define W83627HF_LPCDP 0x296 /* LPC Data Port */

#define W83627HF_EFER 0x2E /* Extended Function Enable Register */
#define W83627HF_EFIR 0x2E /* Extended Function Index Register*/
#define W83627HF_EFDR 0x2F /* Extended Function Data Register */

#define W83627HF_ENTER_EFM 0x87 /* enter externed function mode */
#define W83627HF_EXIT_EFM 0xAA /* exit externed function mode */

/* default watchdog timeout value -- 12s */
#define W83627HF_WDT_DEF_TIMO 0x0C 
#define W83627HF_WDT_MAX_TIMO 0xFF
#define W83627HF_WDT_MIN_TIMO 0x01
/* #define W83627HF_WDT_MIN_TIMO 0x05 */

/* default watchdog timeout unit -- second */
#define W83627HF_WDT_DEF_TIMU 0x00

/* only one can open the watchdog device */
static unsigned long wdt_is_open = 0;
#ifndef CONFIG_WATCHDOG_NOWAYOUT
static unsigned long wdt_expect_close = 0;
#endif

/* 0x01--0xFF seconds(minutes). 0x00 to disable watchdog. */
static unsigned int w83627hf_margin = W83627HF_WDT_DEF_TIMO;
static unsigned int w83627hf_timeunit = W83627HF_WDT_DEF_TIMU;

#define W83627HF_WDT_MAGIC_NUM 13
#define W83627HF_WDT_MAGIC_U 3
#define W83627HF_WDT_MAGIC_M 1
/* magic word which change margin and timeunit */
static char w83627hf_wdt_magic[W83627HF_WDT_MAGIC_NUM] = "?M?UFH72638W";

#define w83627hf_wdt_feed() if (1) {\
	w83627hf_timeunit = w83627hf_timeunit ? \
		0x08 : 0x00;\
\
	if (W83627HF_WDT_MAX_TIMO < w83627hf_margin) \
		w83627hf_margin = W83627HF_WDT_MAX_TIMO;\
\
	if (0!=w83627hf_margin &&\
		W83627HF_WDT_MIN_TIMO>w83627hf_margin) \
		w83627hf_margin = W83627HF_WDT_MIN_TIMO; \
\
	outb(W83627HF_ENTER_EFM, W83627HF_EFER); \
	outb(W83627HF_ENTER_EFM, W83627HF_EFER); \
\
	outb(0x07, W83627HF_EFIR);\
	outb(0x08, W83627HF_EFDR);\
\
	outb(0xF5, W83627HF_EFIR);\
	outb((unsigned char)w83627hf_timeunit, W83627HF_EFDR);\
\
	outb(0xF6, W83627HF_EFIR);\
	outb((unsigned char)w83627hf_margin, W83627HF_EFDR);\
\
	outb(W83627HF_EXIT_EFM, W83627HF_EFER); \
} else

#define w83627hf_wdt_stop() if (1) {\
	outb(W83627HF_ENTER_EFM, W83627HF_EFER); \
	outb(W83627HF_ENTER_EFM, W83627HF_EFER); \
\
	outb(0x07, W83627HF_EFIR);\
	outb(0x08, W83627HF_EFDR);\
\
	/* 0x00 to disable watchdog */\
	outb(0xF6, W83627HF_EFIR);\
	outb(0x00, W83627HF_EFDR);\
\
	outb(W83627HF_EXIT_EFM, W83627HF_EFER); \
} else


#ifdef W83627HF_WDT_DEBUG
/* watchdog sysctl configuration(just for debug) */

enum {
	SYSCTL_W83627HF_WDT_MARGIN=1,
	SYSCTL_W83627HF_WDT_TIMEUNIT,
	SYSCTL_W83627HF_WDT_FEED
};

enum {
	SYSCTL_W83627HF_WDT=21
};

static int sysctl_w83627hf_wdt_noused = 0;

static int w83627hf_wdt_sysctl_feed(struct ctl_table *table, int write,
	struct file *filp, void *buffer, size_t *lenp);

static struct ctl_table sysctl_w83627hf_wdt_dir[] = {
	{SYSCTL_W83627HF_WDT_MARGIN, "margin",
		&w83627hf_margin, sizeof(int),
		0644, 0, &proc_dointvec},
	{SYSCTL_W83627HF_WDT_TIMEUNIT, "timeunit",
		&w83627hf_timeunit, sizeof(int),
		0644, 0, &proc_dointvec},
	{SYSCTL_W83627HF_WDT_FEED, "feed",
		&sysctl_w83627hf_wdt_noused, sizeof(int),
		0200, 0, &w83627hf_wdt_sysctl_feed},
	{0}
};

static struct ctl_table sysctl_w83627hf_wdt_root[] = {
	{SYSCTL_W83627HF_WDT, "w83627hf_wdt",
		0, 0, 0555, sysctl_w83627hf_wdt_dir},
	{0}
};

static struct ctl_table_header *sysctl_w83627hf_wdt_header = 0;

/*
 * When you write something into /proc/sys/w83627hf_wdt/feed, the dog begin
 * watch the system for you.
 * Remember to feed it again before the dog burks.
 * Set /proc/sys/w83627hf_wdt/margin to 0, and update 
 * /proc/sys/w83627hf_wdt/feed will stop the dog.
 * */
int w83627hf_wdt_sysctl_feed(struct ctl_table *table, int write,
	struct file *filp, void *buffer, size_t *lenp)
{
	if (!write)
		return -EPERM;

	w83627hf_wdt_feed();

	return 0;
}

int w83627hf_wdt_sysctl_create(void)
{
	sysctl_w83627hf_wdt_header =
		register_sysctl_table(sysctl_w83627hf_wdt_root, 0);
	if (0 == sysctl_w83627hf_wdt_header) {
		printk("W83627HF WDT: register_sysctl_table() failed\n");
		return -1;
	}

	return 0;
}

void w83627hf_wdt_sysctl_clean(void)
{
	unregister_sysctl_table(sysctl_w83627hf_wdt_header);
	sysctl_w83627hf_wdt_header = 0;
}
#endif

/*
 * Read the margin and timeunit from watchdog device, just for debug.
 * */
static ssize_t w83627hf_wdt_read(struct file *file, char *buf,
	size_t len, loff_t *ppos)
{
	unsigned char t[2];

	assert_w83627hf_wdt(wdt_is_open);

	if (ppos != &file->f_pos) {
#ifdef W83627HF_WDT_DEBUG
		printk("W83627HF WDT: device can NOT be seek\n");
#endif
		return -ESPIPE;
	}

	if (2 > len) {
#ifdef W83627HF_WDT_DEBUG
		printk("W83627HF WDT: read invalid data length %d\n", len);
#endif
		return -EINVAL;
	}

	outb(W83627HF_ENTER_EFM, W83627HF_EFER);
	outb(W83627HF_ENTER_EFM, W83627HF_EFER);

	outb(0x07, W83627HF_EFIR);
	outb(0x08, W83627HF_EFDR);

	outb(0xF5, W83627HF_EFIR);
	t[0] = (0x08 & inb(W83627HF_EFDR)) ? 0x01 : 0x00;

	outb(0xF6, W83627HF_EFIR);
	t[1] = inb(W83627HF_EFDR);

	outb(W83627HF_EXIT_EFM, W83627HF_EFER);

	if (copy_to_user(buf, t, 2)) {
#ifdef W83627HF_WDT_DEBUG
		printk("W83627HF WDT: copy_to_user failed\n");
#endif
		return -EFAULT;
	}

	return 2;
}

static ssize_t w83627hf_wdt_write(struct file *file, const char *data,
	size_t len, loff_t *ppos)
{
	size_t i;
	int j = 0, seek = 0;
	unsigned int timeunit = 0;

	assert_w83627hf_wdt(wdt_is_open);

	if (ppos != &file->f_pos) {
#ifdef W83627HF_WDT_DEBUG
		printk("W83627HF WDT: device can NOT be seek\n");
#endif
		return -ESPIPE;
	}

	if (0 == len)
		goto ping;

	for (i=0; i<len; i++){
		switch (data[i]) {
		case 'W':
			j = W83627HF_WDT_MAGIC_NUM - 2;
			seek = 1;
			break;
#ifndef CONFIG_WATCHDOG_NOWAYOUT
		case 'V':
			wdt_expect_close = 1;
			printk(KERN_DEBUG "expect_close changed\n");
			j = 0;
			seek = 0;
			break;
#endif
		default:
			if (0 == seek) {
				assert_w83627hf_wdt(0 == j);
				break;
			}
			assert_w83627hf_wdt(1 == seek);
			assert_w83627hf_wdt(0 <= j - 1);

			if (W83627HF_WDT_MAGIC_U == j) {
				assert_w83627hf_wdt('?' ==
					w83627hf_wdt_magic[j - 1]);
				if (1 == data[i]) 
					timeunit = 1;
				else
					timeunit = 0;
				j--;
			} else if (W83627HF_WDT_MAGIC_M == j) {
				assert_w83627hf_wdt('?' ==
					w83627hf_wdt_magic[j - 1]);
				if (0<=data[i] &&
					W83627HF_WDT_DEF_TIMO>=data[i]) {
					w83627hf_margin = data[i];
					w83627hf_timeunit = timeunit;
					printk(KERN_DEBUG "margin chanded! "
						"margin == %d, unit == %d\n", 
						w83627hf_margin, 
						w83627hf_timeunit);
				}
				j = 0;
				seek = 0;
			} else if (data[i] == w83627hf_wdt_magic[j - 1]) {
				j--;
			} else {
				j = 0;
				seek = 0;
			}

			break;
		}
	}

ping:
	if (wdt_is_open) {
		w83627hf_wdt_feed();
	}

	return len;
}

static int w83627hf_wdt_ioctl(struct inode *inode, struct file *file,
	unsigned int cmd, unsigned long arg)
{
	int ret = 0;
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,4,0)
	int time;
#endif
	struct watchdog_info ident = {
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,4,0)
		WDIOF_SETTIMEOUT |
#endif
		0,
		1,
		"W83627HF"
	};

	assert_w83627hf_wdt(wdt_is_open);

	if (WATCHDOG_MINOR != MINOR(inode->i_rdev))
		return -ENODEV;

	switch (cmd) {
	case WDIOC_GETSUPPORT:
		if (copy_to_user((struct watchdog_info *)arg, &ident,
			sizeof(ident)))
			ret = -EFAULT;
		break;
	case WDIOC_KEEPALIVE:
		if (wdt_is_open) {
			w83627hf_wdt_feed();
		}
		break;
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,4,0)
	case WDIOC_SETTIMEOUT:
		if (copy_from_user(&time, (int *)arg, sizeof(int))) {
			ret = -EFAULT;
			break;
		}

		printk(KERN_DEBUG "W83627HF WDT: w83627hf_margin %d.\n",
			w83627hf_margin);

		if (W83627HF_WDT_MAX_TIMO < time) {
			printk("W83627HF WDT: w83637hf_margin > 0xFF\n");
			time = W83627HF_WDT_MAX_TIMO;
		}

		if (0!=time && W83627HF_WDT_MIN_TIMO>time) {
			printk("W83627HF WDT: w83627hf_margin < 0x01\n");
			time = W83627HF_WDT_MIN_TIMO;
		}

		w83627hf_margin = time;
		/* Fall */
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,4,18)
	case WDIOC_GETTIMEOUT:
		if (copy_to_user((int *)arg, &w83627hf_margin,
			sizeof(int)))
			ret = -EFAULT;
#endif
		break;
#endif
	default:
		ret = -ENOTTY;
		break;
	}

	return ret;
}

/*
 * Once the user application open the device file, watchdog start work.
 * You MUST feed the dog before it burks.
 * */
static int w83627hf_wdt_open(struct inode *inode, struct file *file)
{
	if (WATCHDOG_MINOR != MINOR(inode->i_rdev))
		return -ENODEV;

	/* only one can open this device */
	if (wdt_is_open)
		return -EBUSY;
	wdt_is_open = 1;

	MOD_INC_USE_COUNT;

#ifndef CONFIG_WATCHDOG_NOWAYOUT
	wdt_expect_close = 0;
#endif

	if (W83627HF_WDT_MAX_TIMO < w83627hf_margin) {
		printk("W83627HF WDT: w83627hf_margin > 0xFF\n");
		w83627hf_margin = W83627HF_WDT_MAX_TIMO;
	}

	if (0!=w83627hf_margin &&
		W83627HF_WDT_MIN_TIMO>w83627hf_margin) {
		printk("W83627HF WDT: w83627hf_margin < 0x01\n");
		w83627hf_margin = W83627HF_WDT_MIN_TIMO;
	}

	/* enter the extended function mode */
	outb(W83627HF_ENTER_EFM, W83627HF_EFER);
	outb(W83627HF_ENTER_EFM, W83627HF_EFER);

	/*
	 * watchdog timer is controlled by CRF5, CRF6, CRF7 of logical
	 * device 8.
	 * */
	outb(0x2B, W83627HF_EFIR);
	outb(0xC0, W83627HF_EFDR);

	/* write CR07 to select logical device A */
	outb(0x07, W83627HF_EFIR);
	outb(0x0A, W83627HF_EFDR);

	/* disable watchdog IRQ */
	outb(0xF7, W83627HF_EFIR);
	outb(0x00, W83627HF_EFDR);

	/* write CR07 to select logical device 8 */
	outb(0x07, W83627HF_EFIR);
	outb(0x08, W83627HF_EFDR);

	/* count time base second(NOT minute). */
	outb(0xF5, W83627HF_EFIR);
	outb((unsigned char)W83627HF_WDT_DEF_TIMU, W83627HF_EFDR);

	/* write the timeout vlaue into CRF6 */
	outb(0xF6, W83627HF_EFIR);
	outb((unsigned char)w83627hf_margin, W83627HF_EFDR);

	/* watchdog will NOT be reset upon a mouse/keyboard interrupt. */
	outb(0xF7, W83627HF_EFIR);
	outb(0x00, W83627HF_EFDR);

	/* exit extended function mode */
	outb(W83627HF_EXIT_EFM, W83627HF_EFER);

	printk(KERN_INFO "W83627HF WDT: wake up, current timeout %d.\n",
		w83627hf_margin);

	return 0;
}

static int w83627hf_wdt_release(struct inode *inode, struct file *file)
{
	assert_w83627hf_wdt(wdt_is_open);

	if (WATCHDOG_MINOR != MINOR(inode->i_rdev))
		return -ENODEV;

#ifndef CONFIG_WATCHDOG_NOWAYOUT
	if (wdt_expect_close) {
		if(wdt_is_open) {
			w83627hf_wdt_stop();
		}
	}

	wdt_expect_close = 0;
#endif

	wdt_is_open = 0;

	MOD_DEC_USE_COUNT;

	printk(KERN_INFO "W83627HF WDT: sleeping again.\n");

	return 0;
}

/*
 * probe the W83627HF chip.
 * */
static int w83627hf_probe(void)
{
	unsigned char device;
	unsigned char chip;
	int ret = -1;

	if (0 > check_region(W83627HF_LPCIP, 2)) {
		ret = -EBUSY;
		goto out;
	}

	outb(0x49, W83627HF_LPCIP);
	device = inb(W83627HF_LPCDP);
	if (0x01 != (device >> 1)) {
		/*printk("W83627HF WDT: Device ID %x != 0x01\n", device >> 1);*/
		goto out;
	}

	outb(0x58, W83627HF_LPCIP);
	chip = inb(W83627HF_LPCDP);
	if (0x21 != chip) {
		/*printk("W83627HF WDT: Chip ID %x != 0x21\n", chip);*/
		goto out;
	}

	/*printk(KERN_INFO "W83627HF WDT: W83627HF chip found\n");*/
	ret = 0;

out:
	return ret;
}

static int w83627hf_wdt_notify(struct notifier_block *this, unsigned long code,
	void *unused)
{
	if (SYS_DOWN==code || SYS_HALT==code) {
		if (wdt_is_open) {
			w83627hf_wdt_stop();
#ifndef CONFIG_WATCHDOG_NOWAYOUT
			wdt_expect_close = 0;
#endif
			wdt_is_open = 0;
		}
	}

	return NOTIFY_DONE;
}

static struct notifier_block w83627hf_wdt_notifier=
{
	w83627hf_wdt_notify,
	0,
	0
};

static struct file_operations w83627hf_wdt_fops = {
	llseek:		0,
	read:		w83627hf_wdt_read,
	write:		w83627hf_wdt_write,
	readdir:	0,
	poll:		0,
	ioctl:		w83627hf_wdt_ioctl,
	mmap:		0,
	open:		w83627hf_wdt_open,
	flush:		0,
	release:	w83627hf_wdt_release,
};

static struct miscdevice w83627hf_wdt_miscdev = {
	WATCHDOG_MINOR,
	"watchdog",
	&w83627hf_wdt_fops
};

int init_module(void)
{
	int ret;

	if ((ret = w83627hf_probe()))
		goto out;

	ret = -1;
	request_region(W83627HF_LPCIP, 2, "W83627HF_WDT");

	if (misc_register(&w83627hf_wdt_miscdev)) {
		printk("W83627HF WDT: misc_register() failed\n");
		goto clean_region;
	}

	if (register_reboot_notifier(&w83627hf_wdt_notifier)) {
		printk("W83627HF WDT: register_reboot_notifier() failed\n");
		goto clean_miscdev;
	}

#ifdef W83627HF_WDT_DEBUG
	if (w83627hf_wdt_sysctl_create())
		goto clean_notifier;
#endif

	if (W83627HF_WDT_MAX_TIMO < w83627hf_margin) {
		printk("W83627HF WDT: w83627hf_margin > 0xFF\n");
		w83627hf_margin = W83627HF_WDT_MAX_TIMO;
	}

	if (W83627HF_WDT_MIN_TIMO > w83627hf_margin) {
		printk("W83627HF WDT: w83627hf_margin < 0x01\n");
		w83627hf_margin = W83627HF_WDT_MIN_TIMO;
	}

	printk(KERN_INFO "W83627HF WDT: sleeping.\n");

	ret = 0;
	goto out;

#ifdef W83627HF_WDT_DEBUG
clean_notifier:
	unregister_reboot_notifier(&w83627hf_wdt_notifier);
#endif
clean_miscdev:
	misc_deregister(&w83627hf_wdt_miscdev);
clean_region:
	release_region(W83627HF_LPCIP, 2);
out:
	return ret;
}

void cleanup_module(void)
{
#ifdef W83627HF_WDT_DEBUG
	w83627hf_wdt_sysctl_clean();
#endif
	unregister_reboot_notifier(&w83627hf_wdt_notifier);
	misc_deregister(&w83627hf_wdt_miscdev);
	release_region(W83627HF_LPCIP, 2);
}

MODULE_PARM(w83627hf_margin, "i");
MODULE_PARM_DESC(w83627hf_magin, "WDT timeout (default 12 <0x01-0xFF>)");
MODULE_AUTHOR("Zhou HongZhen -- <inetbash@yahoo.com>|<netdiff@netease.com>");
MODULE_DESCRIPTION("Watchdog driver for Winbond W83627HF chip");
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,4,0)
MODULE_LICENSE("GPL");
#endif

EXPORT_NO_SYMBOLS;


^ permalink raw reply

* Re: 405LP compile fix
From: David Gibson @ 2002-12-19  2:51 UTC (permalink / raw)
  To: Hollis Blanchard; +Cc: embedded list
In-Reply-To: <1040226565.29647.15.camel@granite.austin.ibm.com>


On Wed, Dec 18, 2002 at 09:49:24AM -0600, Hollis Blanchard wrote:
>
> I'm glad I'm not the only one who sometimes doesn't compile-test his
> patches... ;)
>
> This patch fixes the Beech build, which is calling the now-nonexistant
> function beech_time_init. In actuality beech_calibrate_decr was never called
> anyways... :)

Oops, wasn't paying enough attention to your post.

> Please apply to _2_4_devel.

Applied.

--
David Gibson			| For every complex problem there is a
david@gibson.dropbear.id.au	| solution which is simple, neat and
				| wrong.
http://www.ozlabs.org/people/dgibson

** Sent via the linuxppc-embedded mail list. See http://lists.linuxppc.org/

^ permalink raw reply

* [PATCH 2.4] : donauboe IrDA driver (resend)
From: Jean Tourrilhes @ 2002-12-19  2:46 UTC (permalink / raw)
  To: Marcelo Tosatti, Linux kernel mailing list

	Hi Marcelo,

	I've noticed that the attached patch was also not included in
2.4.21-pre2.
	It's a new driver that replaces the old toshoboe by fixing a
mountain of bugs and adding support for newer revisions of the
hardware, and is therefore anticipated by people having this hardware
(and who don't want to upgrade to 2.5.X). I decided to include this
new driver alongside the old driver to be on the safe side.
	I checked that it applies properly in 2.4.21-pre2, so would
you mind applying that to your kernel ?

	Thanks...

	Jean


ir241_donauboe-2.diff :
---------------------
                <Following patch from Martin Lucina & Christian Gennerat>
        o [FEATURE] Rewrite of the toshoboe driver using documentation
        o [FEATURE] Support Donau oboe chipsets.
        o [FEATURE] FIR support
        o [CORRECT] Probe chip before opening
        o [FEATURE] suspend/resume support
        o [FEATURE] Numerous other improvements/cleanups
                <Currently, we keep the old toshoboe driver around>


diff -u -p linux/Documentation/Configure.d2.help linux/Documentation/Configure.help
--- linux/Documentation/Configure.d2.help	Mon Dec  2 15:05:53 2002
+++ linux/Documentation/Configure.help	Mon Dec  2 15:05:58 2002
@@ -24413,13 +24413,24 @@ CONFIG_NS83820
   say M here and read <file:Documentation/modules.txt>.  The module
   will be called ns83820.o.
 
+Toshiba Type-O IR Port device driver (old driver)
+CONFIG_TOSHIBA_OLD
+  Say Y here if you want to build support for the Toshiba Type-O IR
+  chipset.  This chipset is used by the Toshiba Libretto 100CT, and
+  many more laptops. This driver is obsolete, will no more be
+  maintained and will be removed in favor of the new driver.
+  If you want to compile it as a module, say M here and read
+  <file:Documentation/modules.txt>.
+  The module will be called toshoboe.o.
+
 Toshiba Type-O IR Port device driver
 CONFIG_TOSHIBA_FIR
   Say Y here if you want to build support for the Toshiba Type-O IR
-  chipset.  This chipset is used by the Toshiba Libretto 100CT, and
-  many more laptops.  If you want to compile it as a module, say M
-  here and read <file:Documentation/modules.txt>.  The module will be
-  called toshoboe.o.
+  and Donau oboe chipsets. These chipsets are used by the Toshiba
+  Libretto 100/110CT, Tecra 8100, Portege 7020 and many more laptops.
+  If you want to compile it as a module, say M here and read
+  <file:Documentation/modules.txt>.
+  The module will be called donauboe.o.
 
 SMC IrCC
 CONFIG_SMC_IRCC_FIR
diff -u -p -r --new-file linux/drivers/net/irda.d2/Config.in linux/drivers/net/irda/Config.in
--- linux/drivers/net/irda.d2/Config.in	Wed Sep 11 15:22:22 2002
+++ linux/drivers/net/irda/Config.in	Thu Sep 12 10:33:51 2002
@@ -28,6 +28,7 @@ comment 'FIR device drivers'
 dep_tristate 'IrDA USB dongles (Experimental)' CONFIG_USB_IRDA $CONFIG_IRDA $CONFIG_USB $CONFIG_EXPERIMENTAL
 dep_tristate 'NSC PC87108/PC87338' CONFIG_NSC_FIR  $CONFIG_IRDA
 dep_tristate 'Winbond W83977AF (IR)' CONFIG_WINBOND_FIR $CONFIG_IRDA
+dep_tristate 'Toshiba Type-O IR Port (old driver)' CONFIG_TOSHIBA_OLD $CONFIG_IRDA
 dep_tristate 'Toshiba Type-O IR Port' CONFIG_TOSHIBA_FIR $CONFIG_IRDA
 if [ "$CONFIG_MIPS" = "y" ]; then
    dep_tristate 'Alchemy Au1000 SIR/FIR' CONFIG_AU1000_FIR $CONFIG_IRDA
diff -u -p -r --new-file linux/drivers/net/irda.d2/Makefile linux/drivers/net/irda/Makefile
--- linux/drivers/net/irda.d2/Makefile	Wed Sep 11 15:22:22 2002
+++ linux/drivers/net/irda/Makefile	Thu Sep 12 10:33:51 2002
@@ -17,7 +17,8 @@ obj-$(CONFIG_USB_IRDA)		+= irda-usb.o
 obj-$(CONFIG_NSC_FIR)		+= nsc-ircc.o
 obj-$(CONFIG_WINBOND_FIR)	+= w83977af_ir.o
 obj-$(CONFIG_SA1100_FIR)	+= sa1100_ir.o
-obj-$(CONFIG_TOSHIBA_FIR)	+= toshoboe.o
+obj-$(CONFIG_TOSHIBA_OLD)	+= toshoboe.o
+obj-$(CONFIG_TOSHIBA_FIR)	+= donauboe.o
 obj-$(CONFIG_SMC_IRCC_FIR)	+= smc-ircc.o	irport.o
 obj-$(CONFIG_ALI_FIR)		+= ali-ircc.o
 obj-$(CONFIG_VLSI_FIR)		+= vlsi_ir.o
diff -u -p -r --new-file linux/drivers/net/irda.d2/donauboe.c linux/drivers/net/irda/donauboe.c
--- linux/drivers/net/irda.d2/donauboe.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/net/irda/donauboe.c	Thu Sep 12 10:57:57 2002
@@ -0,0 +1,1850 @@
+/*****************************************************************
+ *
+ * Filename:		donauboe.c
+ * Version: 		2.17
+ * Description:   Driver for the Toshiba OBOE (or type-O or 701)
+ *                FIR Chipset, also supports the DONAUOBOE (type-DO
+ *                or d01) FIR chipset which as far as I know is
+ *                register compatible.
+ * Status:        Experimental.
+ * Author:        James McKenzie <james@fishsoup.dhs.org>
+ * Created at:    Sat May 8  12:35:27 1999
+ * Modified:      Paul Bristow <paul.bristow@technologist.com>
+ * Modified:      Mon Nov 11 19:10:05 1999
+ * Modified:      James McKenzie <james@fishsoup.dhs.org>
+ * Modified:      Thu Mar 16 12:49:00 2000 (Substantial rewrite)
+ * Modified:      Sat Apr 29 00:23:03 2000 (Added DONAUOBOE support)
+ * Modified:      Wed May 24 23:45:02 2000 (Fixed chipio_t structure)
+ * Modified: 2.13 Christian Gennerat <christian.gennerat@polytechnique.org>
+ * Modified: 2.13 dim jan 07 21:57:39 2001 (tested with kernel 2.4 & irnet/ppp)
+ * Modified: 2.14 Christian Gennerat <christian.gennerat@polytechnique.org>
+ * Modified: 2.14 lun fev 05 17:55:59 2001 (adapted to patch-2.4.1-pre8-irda1)
+ * Modified: 2.15 Martin Lucina <mato@kotelna.sk>
+ * Modified: 2.15 Fri Jun 21 20:40:59 2002 (sync with 2.4.18, substantial fixes)
+ * Modified: 2.16 Martin Lucina <mato@kotelna.sk>
+ * Modified: 2.16 Sat Jun 22 18:54:29 2002 (fix freeregion, default to verbose)
+ * Modified: 2.17 Christian Gennerat <christian.gennerat@polytechnique.org>
+ * Modified: 2.17 jeu sep 12 08:50:20 2002 (save_flags();cli(); replaced by spinlocks)
+ *
+ *     Copyright (c) 1999 James McKenzie, All Rights Reserved.
+ *
+ *     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 2 of
+ *     the License, or (at your option) any later version.
+ *
+ *     Neither James McKenzie nor Cambridge University admit liability nor
+ *     provide warranty for any of this software. This material is
+ *     provided "AS-IS" and at no charge.
+ *
+ *     Applicable Models : Libretto 100/110CT and many more.
+ *     Toshiba refers to this chip as the type-O IR port,
+ *     or the type-DO IR port.
+ *
+ ********************************************************************/
+
+/* Look at toshoboe.h (currently in include/net/irda) for details of */
+/* Where to get documentation on the chip         */
+
+
+static char *rcsid =
+  "$Id: donauboe.c V2.17 jeu sep 12 08:50:20 2002 $";
+
+/* See below for a description of the logic in this driver */
+
+/* Is irda_crc16_table[] exported? not yet */
+/* define this if you get errors about multiple defns of irda_crc16_table */
+#undef CRC_EXPORTED
+
+/* User servicable parts */
+/* Enable the code which probes the chip and does a few tests */
+/* Probe code is very useful for understanding how the hardware works */
+/* Use it with various combinations of TT_LEN, RX_LEN */
+/* Strongly recomended, disable if the probe fails on your machine */
+/* and send me <james@fishsoup.dhs.org> the output of dmesg */
+#define DO_PROBE 1
+
+/* Trace Transmit ring, interrupts, Receive ring or not ? */
+#define PROBE_VERBOSE 1
+
+/* Debug option, examine sent and received raw data */
+/* Irdadump is better, but does not see all packets. enable it if you want. */
+#undef DUMP_PACKETS
+
+/* MIR mode has not been tested. Some behaviour is different */
+/* Seems to work against an Ericsson R520 for me. -Martin */
+#define USE_MIR
+
+/* Schedule back to back hardware transmits wherever possible, otherwise */
+/* we need an interrupt for every frame, unset if oboe works for a bit and */
+/* then hangs */
+#define OPTIMIZE_TX
+
+/* Set the number of slots in the rings */
+/* If you get rx/tx fifo overflows at high bitrates, you can try increasing */
+/* these */
+
+#define RING_SIZE (OBOE_RING_SIZE_RX8 | OBOE_RING_SIZE_TX8)
+#define TX_SLOTS    8
+#define RX_SLOTS    8
+
+
+/* Less user servicable parts below here */
+
+/* Test, Transmit and receive buffer sizes, adjust at your peril */
+/* remarks: nfs usually needs 1k blocks */
+/* remarks: in SIR mode, CRC is received, -> RX_LEN=TX_LEN+2 */
+/* remarks: test accepts large blocks. Standard is 0x80 */
+/* When TT_LEN > RX_LEN (SIR mode) data is stored in successive slots. */
+/* When 3 or more slots are needed for each test packet, */
+/* data received in the first slots is overwritten, even */
+/* if OBOE_CTL_RX_HW_OWNS is not set, without any error! */
+#define TT_LEN      0x80
+#define TX_LEN      0xc00
+#define RX_LEN      0xc04
+/* Real transmitted length (SIR mode) is about 14+(2%*TX_LEN) more */
+/* long than user-defined length (see async_wrap_skb) and is less then 4K */
+/* Real received length is (max RX_LEN) differs from user-defined */
+/* length only b the CRC (2 or 4 bytes) */
+#define BUF_SAFETY  0x7a
+#define RX_BUF_SZ   (RX_LEN)
+#define TX_BUF_SZ   (TX_LEN+BUF_SAFETY)
+
+
+/* Logic of the netdev part of this driver                             */
+
+/* The RX ring is filled with buffers, when a packet arrives           */
+/* it is DMA'd into the buffer which is marked used and RxDone called  */
+/* RxDone forms an skb (and checks the CRC if in SIR mode) and ships   */
+/* the packet off upstairs */
+
+/* The transmitter on the oboe chip can work in one of two modes       */
+/* for each ring->tx[] the transmitter can either                      */
+/* a) transmit the packet, leave the trasmitter enabled and proceed to */
+/*    the next ring                                                    */
+/* OR                                                                  */
+/* b) transmit the packet, switch off the transmitter and issue TxDone */
+
+/* All packets are entered into the ring in mode b), if the ring was   */
+/* empty the transmitter is started.                                   */
+
+/* If OPTIMIZE_TX is defined then in TxDone if the ring contains       */
+/* more than one packet, all but the last are set to mode a) [HOWEVER  */
+/* the hardware may not notice this, this is why we start in mode b) ] */
+/* then restart the transmitter                                        */
+
+/* If OPTIMIZE_TX is not defined then we just restart the transmitter  */
+/* if the ring isn't empty */
+
+/* Speed changes are delayed until the TxRing is empty                 */
+/* mtt is handled by generating packets with bad CRCs, before the data */
+
+/* TODO: */
+/* check the mtt works ok      */
+/* finish the watchdog         */
+
+/* No user servicable parts below here */
+
+#define STATIC static
+
+#include <linux/module.h>
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/skbuff.h>
+#include <linux/netdevice.h>
+#include <linux/ioport.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/rtnetlink.h>
+
+#include <asm/system.h>
+#include <asm/io.h>
+
+#include <net/irda/wrapper.h>
+#include <net/irda/irda.h>
+//#include <net/irda/irmod.h>
+//#include <net/irda/irlap_frame.h>
+#include <net/irda/irda_device.h>
+#include <net/irda/crc.h>
+
+#include "donauboe.h"
+
+#define INB(port)       inb_p(port)
+#define OUTB(val,port)  outb_p(val,port)
+#define OUTBP(val,port) outb_p(val,port)
+
+#define PROMPT  OUTB(OBOE_PROMPT_BIT,OBOE_PROMPT);
+
+#if PROBE_VERBOSE
+#define PROBE_DEBUG(args...) (printk (args))
+#else
+#define PROBE_DEBUG(args...) ;
+#endif
+
+/* Set the DMA to be byte at a time */
+#define CONFIG0H_DMA_OFF OBOE_CONFIG0H_RCVANY
+#define CONFIG0H_DMA_ON_NORX CONFIG0H_DMA_OFF| OBOE_CONFIG0H_ENDMAC
+#define CONFIG0H_DMA_ON CONFIG0H_DMA_ON_NORX | OBOE_CONFIG0H_ENRX
+
+static struct pci_device_id toshoboe_pci_tbl[] __initdata = {
+	{ PCI_VENDOR_ID_TOSHIBA, PCI_DEVICE_ID_FIR701, PCI_ANY_ID, PCI_ANY_ID, },
+	{ PCI_VENDOR_ID_TOSHIBA, PCI_DEVICE_ID_FIRD01, PCI_ANY_ID, PCI_ANY_ID, },
+	{ }			/* Terminating entry */
+};
+MODULE_DEVICE_TABLE(pci, toshoboe_pci_tbl);
+
+#define DRIVER_NAME "toshoboe"
+static char *driver_name = DRIVER_NAME;
+
+static int max_baud = 4000000;
+static int do_probe = DO_PROBE;
+
+
+/**********************************************************************/
+/* Fcs code */
+
+#ifdef CRC_EXPORTED
+extern __u16 const irda_crc16_table[];
+#else
+static __u16 const irda_crc16_table[256] = {
+  0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
+  0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
+  0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
+  0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
+  0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
+  0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
+  0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
+  0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
+  0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
+  0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
+  0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
+  0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
+  0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
+  0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
+  0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
+  0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
+  0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
+  0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
+  0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
+  0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
+  0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
+  0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
+  0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
+  0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
+  0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
+  0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
+  0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
+  0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
+  0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
+  0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
+  0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
+  0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
+};
+#endif
+
+STATIC int
+toshoboe_checkfcs (unsigned char *buf, int len)
+{
+  int i;
+  union
+  {
+    __u16 value;
+    __u8 bytes[2];
+  }
+  fcs;
+
+  fcs.value = INIT_FCS;
+
+  for (i = 0; i < len; ++i)
+    fcs.value = irda_fcs (fcs.value, *(buf++));
+
+  return (fcs.value == GOOD_FCS);
+}
+
+/***********************************************************************/
+/* Generic chip handling code */
+#ifdef DUMP_PACKETS
+static unsigned char dump[50];
+STATIC void 
+_dumpbufs (unsigned char *data, int len, char tete)
+{
+int i,j;
+char head=tete;
+for (i=0;i<len;i+=16) {
+    for (j=0;j<16 && i+j<len;j++) { sprintf(&dump[3*j],"%02x.",data[i+j]); }
+    dump [3*j]=0;
+    IRDA_DEBUG (2, "%c%s\n",head , dump);
+    head='+'; 
+    }
+}
+#endif
+
+/* Dump the registers */
+STATIC void
+toshoboe_dumpregs (struct toshoboe_cb *self)
+{
+  __u32 ringbase;
+
+  IRDA_DEBUG (4, "%s()\n", __FUNCTION__);
+
+  ringbase = INB (OBOE_RING_BASE0) << 10;
+  ringbase |= INB (OBOE_RING_BASE1) << 18;
+  ringbase |= INB (OBOE_RING_BASE2) << 26;
+
+  printk (KERN_ERR DRIVER_NAME ": Register dump:\n");
+  printk (KERN_ERR "Interrupts: Tx:%d Rx:%d TxUnder:%d RxOver:%d Sip:%d\n",
+          self->int_tx, self->int_rx, self->int_txunder, self->int_rxover,
+          self->int_sip);
+  printk (KERN_ERR "RX %02x TX %02x RingBase %08x\n",
+          INB (OBOE_RXSLOT), INB (OBOE_TXSLOT), ringbase);
+  printk (KERN_ERR "RING_SIZE %02x IER %02x ISR %02x\n",
+          INB (OBOE_RING_SIZE), INB (OBOE_IER), INB (OBOE_ISR));
+  printk (KERN_ERR "CONFIG1 %02x STATUS %02x\n",
+          INB (OBOE_CONFIG1), INB (OBOE_STATUS));
+  printk (KERN_ERR "CONFIG0 %02x%02x ENABLE %02x%02x\n",
+          INB (OBOE_CONFIG0H), INB (OBOE_CONFIG0L),
+          INB (OBOE_ENABLEH), INB (OBOE_ENABLEL));
+  printk (KERN_ERR "NEW_PCONFIG %02x%02x CURR_PCONFIG %02x%02x\n",
+          INB (OBOE_NEW_PCONFIGH), INB (OBOE_NEW_PCONFIGL),
+          INB (OBOE_CURR_PCONFIGH), INB (OBOE_CURR_PCONFIGL));
+  printk (KERN_ERR "MAXLEN %02x%02x RXCOUNT %02x%02x\n",
+          INB (OBOE_MAXLENH), INB (OBOE_MAXLENL),
+          INB (OBOE_RXCOUNTL), INB (OBOE_RXCOUNTH));
+
+  if (self->ring)
+    {
+      int i;
+      ringbase = virt_to_bus (self->ring);
+      printk (KERN_ERR "Ring at %08x:\n", ringbase);
+      printk (KERN_ERR "RX:");
+      for (i = 0; i < RX_SLOTS; ++i)
+        printk (" (%d,%02x)",self->ring->rx[i].len,self->ring->rx[i].control);
+      printk ("\n");
+      printk (KERN_ERR "TX:");
+      for (i = 0; i < RX_SLOTS; ++i)
+        printk (" (%d,%02x)",self->ring->tx[i].len,self->ring->tx[i].control);
+      printk ("\n");
+    }
+}
+
+/*Don't let the chip look at memory */
+STATIC void
+toshoboe_disablebm (struct toshoboe_cb *self)
+{
+  __u8 command;
+  IRDA_DEBUG (4, "%s()\n", __FUNCTION__);
+
+  pci_read_config_byte (self->pdev, PCI_COMMAND, &command);
+  command &= ~PCI_COMMAND_MASTER;
+  pci_write_config_byte (self->pdev, PCI_COMMAND, command);
+
+}
+
+/* Shutdown the chip and point the taskfile reg somewhere else */
+STATIC void
+toshoboe_stopchip (struct toshoboe_cb *self)
+{
+  IRDA_DEBUG (4, "%s()\n", __FUNCTION__);
+
+  /*Disable interrupts */
+  OUTB (0x0, OBOE_IER);
+  /*Disable DMA, Disable Rx, Disable Tx */
+  OUTB (CONFIG0H_DMA_OFF, OBOE_CONFIG0H);
+  /*Disable SIR MIR FIR, Tx and Rx */
+  OUTB (0x00, OBOE_ENABLEH);
+  /*Point the ring somewhere safe */
+  OUTB (0x3f, OBOE_RING_BASE2);
+  OUTB (0xff, OBOE_RING_BASE1);
+  OUTB (0xff, OBOE_RING_BASE0);
+
+  OUTB (RX_LEN >> 8, OBOE_MAXLENH);
+  OUTB (RX_LEN & 0xff, OBOE_MAXLENL);
+
+  /*Acknoledge any pending interrupts */
+  OUTB (0xff, OBOE_ISR);
+
+  /*Why */
+  OUTB (OBOE_ENABLEH_PHYANDCLOCK, OBOE_ENABLEH);
+
+  /*switch it off */
+  OUTB (OBOE_CONFIG1_OFF, OBOE_CONFIG1);
+
+  toshoboe_disablebm (self);
+}
+
+/* Transmitter initialization */
+STATIC void
+toshoboe_start_DMA (struct toshoboe_cb *self, int opts)
+{
+  OUTB (0x0, OBOE_ENABLEH);
+  OUTB (CONFIG0H_DMA_ON | opts,  OBOE_CONFIG0H);
+  OUTB (OBOE_ENABLEH_PHYANDCLOCK, OBOE_ENABLEH);
+  PROMPT;
+}
+
+/*Set the baud rate */
+STATIC void
+toshoboe_setbaud (struct toshoboe_cb *self)
+{
+  __u16 pconfig = 0;
+  __u8 config0l = 0;
+
+  IRDA_DEBUG (2, "%s(%d/%d)\n", __FUNCTION__, self->speed, self->io.speed);
+
+  switch (self->speed)
+    {
+    case 2400:
+    case 4800:
+    case 9600:
+    case 19200:
+    case 38400:
+    case 57600:
+    case 115200:
+#ifdef USE_MIR
+    case 1152000:
+#endif
+    case 4000000:
+      break;
+    default:
+
+      printk (KERN_ERR DRIVER_NAME ": switch to unsupported baudrate %d\n",
+              self->speed);
+      return;
+    }
+
+  switch (self->speed)
+    {
+      /* For SIR the preamble is done by adding XBOFs */
+      /* to the packet */
+      /* set to filtered SIR mode, filter looks for BOF and EOF */
+    case 2400:
+      pconfig |= 47 << OBOE_PCONFIG_BAUDSHIFT;
+      pconfig |= 25 << OBOE_PCONFIG_WIDTHSHIFT;
+      break;
+    case 4800:
+      pconfig |= 23 << OBOE_PCONFIG_BAUDSHIFT;
+      pconfig |= 25 << OBOE_PCONFIG_WIDTHSHIFT;
+      break;
+    case 9600:
+      pconfig |= 11 << OBOE_PCONFIG_BAUDSHIFT;
+      pconfig |= 25 << OBOE_PCONFIG_WIDTHSHIFT;
+      break;
+    case 19200:
+      pconfig |= 5 << OBOE_PCONFIG_BAUDSHIFT;
+      pconfig |= 25 << OBOE_PCONFIG_WIDTHSHIFT;
+      break;
+    case 38400:
+      pconfig |= 2 << OBOE_PCONFIG_BAUDSHIFT;
+      pconfig |= 25 << OBOE_PCONFIG_WIDTHSHIFT;
+      break;
+    case 57600:
+      pconfig |= 1 << OBOE_PCONFIG_BAUDSHIFT;
+      pconfig |= 25 << OBOE_PCONFIG_WIDTHSHIFT;
+      break;
+    case 115200:
+      pconfig |= 0 << OBOE_PCONFIG_BAUDSHIFT;
+      pconfig |= 25 << OBOE_PCONFIG_WIDTHSHIFT;
+      break;
+    default:
+      /*Set to packet based reception */
+      OUTB (RX_LEN >> 8, OBOE_MAXLENH);
+      OUTB (RX_LEN & 0xff, OBOE_MAXLENL);
+      break;
+    }
+
+  switch (self->speed)
+    {
+    case 2400:
+    case 4800:
+    case 9600:
+    case 19200:
+    case 38400:
+    case 57600:
+    case 115200:
+      config0l = OBOE_CONFIG0L_ENSIR;
+      if (self->async)
+        {
+          /*Set to character based reception */
+          /*System will lock if MAXLEN=0 */
+          /*so have to be careful */
+          OUTB (0x01, OBOE_MAXLENH);
+          OUTB (0x01, OBOE_MAXLENL);
+          OUTB (0x00, OBOE_MAXLENH);
+        }
+      else
+        {
+          /*Set to packet based reception */
+          config0l |= OBOE_CONFIG0L_ENSIRF;
+          OUTB (RX_LEN >> 8, OBOE_MAXLENH);
+          OUTB (RX_LEN & 0xff, OBOE_MAXLENL);
+        }
+      break;
+
+#ifdef USE_MIR
+      /* MIR mode */
+      /* Set for 16 bit CRC and enable MIR */
+      /* Preamble now handled by the chip */
+    case 1152000:
+      pconfig |= 0 << OBOE_PCONFIG_BAUDSHIFT;
+      pconfig |= 8 << OBOE_PCONFIG_WIDTHSHIFT;
+      pconfig |= 1 << OBOE_PCONFIG_PREAMBLESHIFT;
+      config0l = OBOE_CONFIG0L_CRC16 | OBOE_CONFIG0L_ENMIR;
+      break;
+#endif
+      /* FIR mode */
+      /* Set for 32 bit CRC and enable FIR */
+      /* Preamble handled by the chip */
+    case 4000000:
+      pconfig |= 0 << OBOE_PCONFIG_BAUDSHIFT;
+      /* Documentation says 14, but toshiba use 15 in their drivers */
+      pconfig |= 15 << OBOE_PCONFIG_PREAMBLESHIFT;
+      config0l = OBOE_CONFIG0L_ENFIR;
+      break;
+    }
+
+  /* Copy into new PHY config buffer */
+  OUTBP (pconfig >> 8, OBOE_NEW_PCONFIGH);
+  OUTB (pconfig & 0xff, OBOE_NEW_PCONFIGL);
+  OUTB (config0l, OBOE_CONFIG0L);
+
+  /* Now make OBOE copy from new PHY to current PHY */
+  OUTB (0x0, OBOE_ENABLEH);
+  OUTB (OBOE_ENABLEH_PHYANDCLOCK, OBOE_ENABLEH);
+  PROMPT;
+
+  /* speed change executed */
+  self->new_speed = 0;
+  self->io.speed = self->speed;
+}
+
+/*Let the chip look at memory */
+STATIC void
+toshoboe_enablebm (struct toshoboe_cb *self)
+{
+  IRDA_DEBUG (4, "%s()\n", __FUNCTION__);
+  pci_set_master (self->pdev);
+}
+
+/*setup the ring */
+STATIC void
+toshoboe_initring (struct toshoboe_cb *self)
+{
+  int i;
+
+  IRDA_DEBUG (4, "%s()\n", __FUNCTION__);
+
+  for (i = 0; i < TX_SLOTS; ++i)
+    {
+      self->ring->tx[i].len = 0;
+      self->ring->tx[i].control = 0x00;
+      self->ring->tx[i].address = virt_to_bus (self->tx_bufs[i]);
+    }
+
+  for (i = 0; i < RX_SLOTS; ++i)
+    {
+      self->ring->rx[i].len = RX_LEN;
+      self->ring->rx[i].len = 0;
+      self->ring->rx[i].address = virt_to_bus (self->rx_bufs[i]);
+      self->ring->rx[i].control = OBOE_CTL_RX_HW_OWNS;
+    }
+}
+
+STATIC void
+toshoboe_resetptrs (struct toshoboe_cb *self)
+{
+  /* Can reset pointers by twidling DMA */
+  OUTB (0x0, OBOE_ENABLEH);
+  OUTBP (CONFIG0H_DMA_OFF, OBOE_CONFIG0H);
+  OUTB (OBOE_ENABLEH_PHYANDCLOCK, OBOE_ENABLEH);
+
+  self->rxs = inb_p (OBOE_RXSLOT) & OBOE_SLOT_MASK;
+  self->txs = inb_p (OBOE_TXSLOT) & OBOE_SLOT_MASK;
+}
+
+/* Called in locked state */
+STATIC void
+toshoboe_initptrs (struct toshoboe_cb *self)
+{
+
+  /* spin_lock_irqsave(self->spinlock, flags); */
+  /* save_flags (flags); */
+
+  /* Can reset pointers by twidling DMA */
+  toshoboe_resetptrs (self);
+
+  OUTB (0x0, OBOE_ENABLEH);
+  OUTB (CONFIG0H_DMA_ON, OBOE_CONFIG0H);
+  OUTB (OBOE_ENABLEH_PHYANDCLOCK, OBOE_ENABLEH);
+
+  self->txpending = 0;
+
+  /* spin_unlock_irqrestore(self->spinlock, flags); */
+  /* restore_flags (flags); */
+}
+
+/* Wake the chip up and get it looking at the rings */
+/* Called in locked state */
+STATIC void
+toshoboe_startchip (struct toshoboe_cb *self)
+{
+  __u32 physaddr;
+
+  IRDA_DEBUG (4, "%s()\n", __FUNCTION__);
+
+  toshoboe_initring (self);
+  toshoboe_enablebm (self);
+  OUTBP (OBOE_CONFIG1_RESET, OBOE_CONFIG1);
+  OUTBP (OBOE_CONFIG1_ON, OBOE_CONFIG1);
+
+  /* Stop the clocks */
+  OUTB (0, OBOE_ENABLEH);
+
+  /*Set size of rings */
+  OUTB (RING_SIZE, OBOE_RING_SIZE);
+
+  /*Acknoledge any pending interrupts */
+  OUTB (0xff, OBOE_ISR);
+
+  /*Enable ints */
+  OUTB (OBOE_INT_TXDONE  | OBOE_INT_RXDONE |
+        OBOE_INT_TXUNDER | OBOE_INT_RXOVER | OBOE_INT_SIP , OBOE_IER);
+
+  /*Acknoledge any pending interrupts */
+  OUTB (0xff, OBOE_ISR);
+
+  /*Set the maximum packet length to 0xfff (4095) */
+  OUTB (RX_LEN >> 8, OBOE_MAXLENH);
+  OUTB (RX_LEN & 0xff, OBOE_MAXLENL);
+
+  /*Shutdown DMA */
+  OUTB (CONFIG0H_DMA_OFF, OBOE_CONFIG0H);
+
+  /*Find out where the rings live */
+  physaddr = virt_to_bus (self->ring);
+
+  ASSERT ((physaddr & 0x3ff) == 0,
+          printk (KERN_ERR DRIVER_NAME "ring not correctly aligned\n");
+          return;);
+
+  OUTB ((physaddr >> 10) & 0xff, OBOE_RING_BASE0);
+  OUTB ((physaddr >> 18) & 0xff, OBOE_RING_BASE1);
+  OUTB ((physaddr >> 26) & 0x3f, OBOE_RING_BASE2);
+
+  /*Enable DMA controler in byte mode and RX */
+  OUTB (CONFIG0H_DMA_ON, OBOE_CONFIG0H);
+
+  /* Start up the clocks */
+  OUTB (OBOE_ENABLEH_PHYANDCLOCK, OBOE_ENABLEH);
+
+  /*set to sensible speed */
+  self->speed = 9600;
+  toshoboe_setbaud (self);
+  toshoboe_initptrs (self);
+}
+
+STATIC void
+toshoboe_isntstuck (struct toshoboe_cb *self)
+{
+}
+
+STATIC void
+toshoboe_checkstuck (struct toshoboe_cb *self)
+{
+  unsigned long flags;
+
+  if (0)
+    {
+      spin_lock_irqsave(&self->spinlock, flags);
+
+      /* This will reset the chip completely */
+      printk (KERN_ERR DRIVER_NAME ": Resetting chip\n");
+
+      toshoboe_stopchip (self);
+      toshoboe_startchip (self);
+      spin_unlock_irqrestore(&self->spinlock, flags);
+    }
+}
+
+/*Generate packet of about mtt us long */
+STATIC int
+toshoboe_makemttpacket (struct toshoboe_cb *self, void *buf, int mtt)
+{
+  int xbofs;
+
+  xbofs = ((int) (mtt/100)) * (int) (self->speed);
+  xbofs=xbofs/80000; /*Eight bits per byte, and mtt is in us*/
+  xbofs++;
+
+  IRDA_DEBUG (2, DRIVER_NAME 
+      ": generated mtt of %d bytes for %d us at %d baud\n"
+	  , xbofs,mtt,self->speed);
+
+  if (xbofs > TX_LEN)
+    {
+      printk (KERN_ERR DRIVER_NAME ": wanted %d bytes MTT but TX_LEN is %d\n",
+              xbofs, TX_LEN);
+      xbofs = TX_LEN;
+    }
+
+  /*xbofs will do for SIR, MIR and FIR,SIR mode doesn't generate a checksum anyway */
+  memset (buf, XBOF, xbofs);
+
+  return xbofs;
+}
+
+/***********************************************************************/
+/* Probe code */
+
+STATIC void
+toshoboe_dumptx (struct toshoboe_cb *self)
+{
+  int i;
+  PROBE_DEBUG(KERN_WARNING "TX:");
+  for (i = 0; i < RX_SLOTS; ++i)
+    PROBE_DEBUG(" (%d,%02x)",self->ring->tx[i].len,self->ring->tx[i].control);
+  PROBE_DEBUG(" [%d]\n",self->speed);
+}
+
+STATIC void
+toshoboe_dumprx (struct toshoboe_cb *self, int score)
+{
+  int i;
+  PROBE_DEBUG(" %d\nRX:",score);
+  for (i = 0; i < RX_SLOTS; ++i)
+    PROBE_DEBUG(" (%d,%02x)",self->ring->rx[i].len,self->ring->rx[i].control);
+  PROBE_DEBUG("\n");
+}
+
+static inline int
+stuff_byte (__u8 byte, __u8 * buf)
+{
+  switch (byte)
+    {
+    case BOF:                  /* FALLTHROUGH */
+    case EOF:                  /* FALLTHROUGH */
+    case CE:
+      /* Insert transparently coded */
+      buf[0] = CE;              /* Send link escape */
+      buf[1] = byte ^ IRDA_TRANS; /* Complement bit 5 */
+      return 2;
+      /* break; */
+    default:
+      /* Non-special value, no transparency required */
+      buf[0] = byte;
+      return 1;
+      /* break; */
+    }
+}
+
+STATIC int toshoboe_invalid_dev(int irq) 
+{
+  printk (KERN_WARNING DRIVER_NAME ": irq %d for unknown device.\n", irq);
+  return 1;
+}
+
+STATIC void
+toshoboe_probeinterrupt (int irq, void *dev_id, struct pt_regs *regs)
+{
+  struct toshoboe_cb *self = (struct toshoboe_cb *) dev_id;
+  __u8 irqstat;
+
+  if (self == NULL && toshoboe_invalid_dev(irq)) 
+    return;
+
+  irqstat = INB (OBOE_ISR);
+
+/* was it us */
+  if (!(irqstat & OBOE_INT_MASK))
+    return;
+
+/* Ack all the interrupts */
+  OUTB (irqstat, OBOE_ISR);
+
+  if (irqstat & OBOE_INT_TXDONE)
+    {
+      int txp;
+
+      self->int_tx++;
+      PROBE_DEBUG("T");
+
+      txp = INB (OBOE_TXSLOT) & OBOE_SLOT_MASK;
+      if (self->ring->tx[txp].control & OBOE_CTL_TX_HW_OWNS)
+        {
+          self->int_tx+=100;
+          PROBE_DEBUG("S");
+          toshoboe_start_DMA(self, OBOE_CONFIG0H_ENTX | OBOE_CONFIG0H_LOOP);
+        }
+    }
+
+  if (irqstat & OBOE_INT_RXDONE) {
+    self->int_rx++;
+    PROBE_DEBUG("R"); }
+  if (irqstat & OBOE_INT_TXUNDER) {
+    self->int_txunder++;
+    PROBE_DEBUG("U"); }
+  if (irqstat & OBOE_INT_RXOVER) {
+    self->int_rxover++;
+    PROBE_DEBUG("O"); }
+  if (irqstat & OBOE_INT_SIP) {
+    self->int_sip++;
+    PROBE_DEBUG("I"); }
+}
+
+STATIC int
+toshoboe_maketestpacket (unsigned char *buf, int badcrc, int fir)
+{
+  int i;
+  int len = 0;
+  union
+  {
+    __u16 value;
+    __u8 bytes[2];
+  }
+  fcs;
+
+  if (fir)
+    {
+      memset (buf, 0, TT_LEN);
+      return (TT_LEN);
+    }
+
+  fcs.value = INIT_FCS;
+
+  memset (buf, XBOF, 10);
+  len += 10;
+  buf[len++] = BOF;
+
+  for (i = 0; i < TT_LEN; ++i)
+    {
+      len += stuff_byte (i, buf + len);
+      fcs.value = irda_fcs (fcs.value, i);
+    }
+
+  len += stuff_byte (fcs.bytes[0] ^ badcrc, buf + len);
+  len += stuff_byte (fcs.bytes[1] ^ badcrc, buf + len);
+  buf[len++] = EOF;
+  len++;
+  return len;
+}
+
+STATIC int
+toshoboe_probefail (struct toshoboe_cb *self, char *msg)
+{
+  printk (KERN_ERR DRIVER_NAME "probe(%d) failed %s\n",self-> speed, msg);
+  toshoboe_dumpregs (self);
+  toshoboe_stopchip (self);
+  free_irq (self->io.irq, (void *) self);
+  return 0;
+}
+
+STATIC int
+toshoboe_numvalidrcvs (struct toshoboe_cb *self)
+{
+  int i, ret = 0;
+  for (i = 0; i < RX_SLOTS; ++i)
+    if ((self->ring->rx[i].control & 0xe0) == 0)
+      ret++;
+
+  return ret;
+}
+
+STATIC int
+toshoboe_numrcvs (struct toshoboe_cb *self)
+{
+  int i, ret = 0;
+  for (i = 0; i < RX_SLOTS; ++i)
+    if (!(self->ring->rx[i].control & OBOE_CTL_RX_HW_OWNS))
+      ret++;
+
+  return ret;
+}
+
+STATIC int
+toshoboe_probe (struct toshoboe_cb *self)
+{
+  int i, j, n;
+#ifdef USE_MIR
+  int bauds[] = { 9600, 115200, 4000000, 1152000 };
+#else
+  int bauds[] = { 9600, 115200, 4000000 };
+#endif
+  unsigned long flags;
+
+  IRDA_DEBUG (4, "%s()\n", __FUNCTION__);
+
+  if (request_irq (self->io.irq, toshoboe_probeinterrupt,
+                   self->io.irqflags, "toshoboe", (void *) self))
+    {
+      printk (KERN_ERR DRIVER_NAME ": probe failed to allocate irq %d\n",
+              self->io.irq);
+      return 0;
+    }
+
+  /* test 1: SIR filter and back to back */
+
+  for (j = 0; j < (sizeof (bauds) / sizeof (int)); ++j)
+    {
+      int fir = (j > 1);
+      toshoboe_stopchip (self);
+
+
+      spin_lock_irqsave(&self->spinlock, flags);
+      /*Address is already setup */
+      toshoboe_startchip (self);
+      self->int_rx = self->int_tx = 0;
+      self->speed = bauds[j];
+      toshoboe_setbaud (self);
+      toshoboe_initptrs (self);
+      spin_unlock_irqrestore(&self->spinlock, flags); 
+
+      self->ring->tx[self->txs].control =
+/*   (FIR only) OBOE_CTL_TX_SIP needed for switching to next slot */
+/*    MIR: all received data is stored in one slot */
+        (fir) ? OBOE_CTL_TX_HW_OWNS | OBOE_CTL_TX_RTCENTX
+              : OBOE_CTL_TX_HW_OWNS ;
+      self->ring->tx[self->txs].len =
+        toshoboe_maketestpacket (self->tx_bufs[self->txs], 0, fir);
+      self->txs++;
+      self->txs %= TX_SLOTS;
+
+      self->ring->tx[self->txs].control =
+        (fir) ? OBOE_CTL_TX_HW_OWNS | OBOE_CTL_TX_SIP
+              : OBOE_CTL_TX_HW_OWNS | OBOE_CTL_TX_RTCENTX ;
+      self->ring->tx[self->txs].len =
+        toshoboe_maketestpacket (self->tx_bufs[self->txs], 0, fir);
+      self->txs++;
+      self->txs %= TX_SLOTS;
+
+      self->ring->tx[self->txs].control = 
+        (fir) ? OBOE_CTL_TX_HW_OWNS | OBOE_CTL_TX_RTCENTX
+              : OBOE_CTL_TX_HW_OWNS ;
+      self->ring->tx[self->txs].len =
+        toshoboe_maketestpacket (self->tx_bufs[self->txs], 0, fir);
+      self->txs++;
+      self->txs %= TX_SLOTS;
+
+      self->ring->tx[self->txs].control =
+        (fir) ? OBOE_CTL_TX_HW_OWNS | OBOE_CTL_TX_RTCENTX
+              | OBOE_CTL_TX_SIP     | OBOE_CTL_TX_BAD_CRC
+              : OBOE_CTL_TX_HW_OWNS | OBOE_CTL_TX_RTCENTX ;
+      self->ring->tx[self->txs].len =
+        toshoboe_maketestpacket (self->tx_bufs[self->txs], 0, fir);
+      self->txs++;
+      self->txs %= TX_SLOTS;
+
+      toshoboe_dumptx (self);
+      /* Turn on TX and RX and loopback */
+      toshoboe_start_DMA(self, OBOE_CONFIG0H_ENTX | OBOE_CONFIG0H_LOOP);
+
+      i = 0;
+      n = fir ? 1 : 4;
+      while (toshoboe_numvalidrcvs (self) != n)
+        {
+          if (i > 4800)
+              return toshoboe_probefail (self, "filter test");
+          udelay ((9600*(TT_LEN+16))/self->speed);
+          i++;
+        }
+
+      n = fir ? 203 : 102;
+      while ((toshoboe_numrcvs(self) != self->int_rx) || (self->int_tx != n))
+        {
+          if (i > 4800)
+              return toshoboe_probefail (self, "interrupt test");
+          udelay ((9600*(TT_LEN+16))/self->speed);
+          i++;
+        }
+     toshoboe_dumprx (self,i);
+
+     }
+
+  /* test 2: SIR in char at a time */
+
+  toshoboe_stopchip (self);
+  self->int_rx = self->int_tx = 0;
+
+  spin_lock_irqsave(&self->spinlock, flags);
+  toshoboe_startchip (self);
+  spin_unlock_irqrestore(&self->spinlock, flags);
+
+  self->async = 1;
+  self->speed = 115200;
+  toshoboe_setbaud (self);
+  self->ring->tx[self->txs].control =
+    OBOE_CTL_TX_RTCENTX | OBOE_CTL_TX_HW_OWNS;
+  self->ring->tx[self->txs].len = 4;
+
+  ((unsigned char *) self->tx_bufs[self->txs])[0] = 'f';
+  ((unsigned char *) self->tx_bufs[self->txs])[1] = 'i';
+  ((unsigned char *) self->tx_bufs[self->txs])[2] = 's';
+  ((unsigned char *) self->tx_bufs[self->txs])[3] = 'h';
+  toshoboe_dumptx (self);
+  toshoboe_start_DMA(self, OBOE_CONFIG0H_ENTX | OBOE_CONFIG0H_LOOP);
+
+  i = 0;
+  while (toshoboe_numvalidrcvs (self) != 4)
+    {
+      if (i > 100)
+          return toshoboe_probefail (self, "Async test");
+      udelay (100);
+      i++;
+    }
+
+  while ((toshoboe_numrcvs (self) != self->int_rx) || (self->int_tx != 1))
+    {
+      if (i > 100)
+          return toshoboe_probefail (self, "Async interrupt test");
+      udelay (100);
+      i++;
+    }
+  toshoboe_dumprx (self,i);
+
+  self->async = 0;
+  self->speed = 9600;
+  toshoboe_setbaud (self);
+  toshoboe_stopchip (self);
+
+  free_irq (self->io.irq, (void *) self);
+
+  printk (KERN_WARNING DRIVER_NAME ": Self test passed ok\n");
+
+  return 1;
+}
+
+/******************************************************************/
+/* Netdev style code */
+
+/* Transmit something */
+STATIC int
+toshoboe_hard_xmit (struct sk_buff *skb, struct net_device *dev)
+{
+  struct toshoboe_cb *self;
+  __s32 speed;
+  int mtt, len, ctl;
+  unsigned long flags;
+  struct irda_skb_cb *cb = (struct irda_skb_cb *) skb->cb;
+
+  self = (struct toshoboe_cb *) dev->priv;
+
+  ASSERT (self != NULL, return 0; );
+
+  IRDA_DEBUG (1, "%s.tx:%x(%x)%x\n", __FUNCTION__ 
+      ,skb->len,self->txpending,INB (OBOE_ENABLEH));
+  if (!cb->magic) {
+      IRDA_DEBUG (2, "%s.Not IrLAP:%x\n", __FUNCTION__, cb->magic);
+#ifdef DUMP_PACKETS
+      _dumpbufs(skb->data,skb->len,'>'); 
+#endif
+    }
+
+  /* change speed pending, wait for its execution */
+  if (self->new_speed)
+      return -EBUSY;
+
+  /* device stopped (apm) wait for restart */
+  if (self->stopped)
+      return -EBUSY;
+
+  toshoboe_checkstuck (self);
+
+  /* Check if we need to change the speed */
+  /* But not now. Wait after transmission if mtt not required */
+  speed=irda_get_next_speed(skb);
+  if ((speed != self->io.speed) && (speed != -1))
+    {
+      spin_lock_irqsave(&self->spinlock, flags);
+
+      if (self->txpending || skb->len)
+        {
+          self->new_speed = speed;
+          IRDA_DEBUG (1, "%s: Queued TxDone scheduled speed change %d\n" ,
+		      __FUNCTION__, speed);
+          /* if no data, that's all! */
+          if (!skb->len) 
+            {
+	      spin_unlock_irqrestore(&self->spinlock, flags);
+              dev_kfree_skb (skb);
+              return 0;
+            }
+          /* True packet, go on, but */
+          /* do not accept anything before change speed execution */
+          netif_stop_queue(dev); 
+          /* ready to process TxDone interrupt */
+	  spin_unlock_irqrestore(&self->spinlock, flags);
+        }
+      else
+        { 
+          /* idle and no data, change speed now */
+          self->speed = speed;
+          toshoboe_setbaud (self);
+	  spin_unlock_irqrestore(&self->spinlock, flags);
+          dev_kfree_skb (skb);
+          return 0;
+        }
+
+    }
+
+  if ((mtt = irda_get_mtt(skb)))
+    {
+      /* This is fair since the queue should be empty anyway */
+      spin_lock_irqsave(&self->spinlock, flags);
+
+      if (self->txpending)
+        {
+	  spin_unlock_irqrestore(&self->spinlock, flags);
+          return -EBUSY;
+        }
+
+      /* If in SIR mode we need to generate a string of XBOFs */
+      /* In MIR and FIR we need to generate a string of data */
+      /* which we will add a wrong checksum to */
+
+      mtt = toshoboe_makemttpacket (self, self->tx_bufs[self->txs], mtt);
+      IRDA_DEBUG (1, "%s.mtt:%x(%x)%d\n", __FUNCTION__ 
+          ,skb->len,mtt,self->txpending);
+      if (mtt)
+        {
+          self->ring->tx[self->txs].len = mtt & 0xfff;
+
+          ctl = OBOE_CTL_TX_HW_OWNS | OBOE_CTL_TX_RTCENTX;
+          if (INB (OBOE_ENABLEH) & OBOE_ENABLEH_FIRON)
+            {
+              ctl |= OBOE_CTL_TX_BAD_CRC | OBOE_CTL_TX_SIP ;
+            }
+#ifdef USE_MIR
+          else if (INB (OBOE_ENABLEH) & OBOE_ENABLEH_MIRON)
+            {
+              ctl |= OBOE_CTL_TX_BAD_CRC;
+            }
+#endif
+          self->ring->tx[self->txs].control = ctl;
+
+          OUTB (0x0, OBOE_ENABLEH);
+          /* It is only a timer. Do not send mtt packet outside! */
+          toshoboe_start_DMA(self, OBOE_CONFIG0H_ENTX | OBOE_CONFIG0H_LOOP);
+
+          self->txpending++;
+
+          self->txs++;
+          self->txs %= TX_SLOTS;
+
+        }
+      else
+        {
+          printk(KERN_ERR DRIVER_NAME ": problem with mtt packet - ignored\n");
+        }
+      spin_unlock_irqrestore(&self->spinlock, flags);
+    }
+
+#ifdef DUMP_PACKETS
+dumpbufs(skb->data,skb->len,'>'); 
+#endif
+
+  spin_lock_irqsave(&self->spinlock, flags);
+
+  if (self->ring->tx[self->txs].control & OBOE_CTL_TX_HW_OWNS)
+    {
+      IRDA_DEBUG (0, "%s.ful:%x(%x)%x\n", __FUNCTION__
+          ,skb->len, self->ring->tx[self->txs].control, self->txpending);
+      toshoboe_start_DMA(self, OBOE_CONFIG0H_ENTX);
+      spin_unlock_irqrestore(&self->spinlock, flags);
+      return -EBUSY;
+    }
+
+  if (INB (OBOE_ENABLEH) & OBOE_ENABLEH_SIRON)
+    {
+      len = async_wrap_skb (skb, self->tx_bufs[self->txs], TX_BUF_SZ);
+    }
+  else
+    {
+      len = skb->len;
+      memcpy (self->tx_bufs[self->txs], skb->data, len);
+    }
+  self->ring->tx[self->txs].len = len & 0x0fff;
+
+  /*Sometimes the HW doesn't see us assert RTCENTX in the interrupt code */
+  /*later this plays safe, we garuntee the last packet to be transmitted */
+  /*has RTCENTX set */
+
+  ctl = OBOE_CTL_TX_HW_OWNS | OBOE_CTL_TX_RTCENTX;
+  if (INB (OBOE_ENABLEH) & OBOE_ENABLEH_FIRON)
+    {
+      ctl |= OBOE_CTL_TX_SIP ;
+    }
+  self->ring->tx[self->txs].control = ctl;
+
+  /* If transmitter is idle start in one-shot mode */
+
+  if (!self->txpending)
+      toshoboe_start_DMA(self, OBOE_CONFIG0H_ENTX);
+
+  self->txpending++;
+
+  self->txs++;
+  self->txs %= TX_SLOTS;
+
+  spin_unlock_irqrestore(&self->spinlock, flags);
+  dev_kfree_skb (skb);
+
+  return 0;
+}
+
+/*interrupt handler */
+STATIC void
+toshoboe_interrupt (int irq, void *dev_id, struct pt_regs *regs)
+{
+  struct toshoboe_cb *self = (struct toshoboe_cb *) dev_id;
+  __u8 irqstat;
+  struct sk_buff *skb = NULL;
+
+  if (self == NULL && toshoboe_invalid_dev(irq)) 
+    return;
+
+  irqstat = INB (OBOE_ISR);
+
+/* was it us */
+  if (!(irqstat & OBOE_INT_MASK))
+      return;
+
+/* Ack all the interrupts */
+  OUTB (irqstat, OBOE_ISR);
+
+  toshoboe_isntstuck (self);
+
+/* Txdone */
+  if (irqstat & OBOE_INT_TXDONE)
+    {
+      int txp, txpc;
+      int i;
+
+      txp = self->txpending;
+      self->txpending = 0;
+
+      for (i = 0; i < TX_SLOTS; ++i)
+        {
+          if (self->ring->tx[i].control & OBOE_CTL_TX_HW_OWNS)
+              self->txpending++;
+        }
+      IRDA_DEBUG (1, "%s.txd(%x)%x/%x\n", __FUNCTION__
+          ,irqstat,txp,self->txpending);
+
+      txp = INB (OBOE_TXSLOT) & OBOE_SLOT_MASK;
+
+      /* Got anything queued ? start it together */
+      if (self->ring->tx[txp].control & OBOE_CTL_TX_HW_OWNS)
+        {
+          txpc = txp;
+#ifdef OPTIMIZE_TX
+          while (self->ring->tx[txpc].control & OBOE_CTL_TX_HW_OWNS)
+            {
+              txp = txpc;
+              txpc++;
+              txpc %= TX_SLOTS;
+              self->stats.tx_packets++;
+              if (self->ring->tx[txpc].control & OBOE_CTL_TX_HW_OWNS)
+                  self->ring->tx[txp].control &= ~OBOE_CTL_TX_RTCENTX;
+            }
+          self->stats.tx_packets--;
+#else
+          self->stats.tx_packets++;
+#endif
+          toshoboe_start_DMA(self, OBOE_CONFIG0H_ENTX);
+        }
+
+      if ((!self->txpending) && (self->new_speed))
+        {
+          self->speed = self->new_speed;
+          IRDA_DEBUG (1, "%s: Executed TxDone scheduled speed change %d\n",
+		      __FUNCTION__, self->speed);
+          toshoboe_setbaud (self);
+        }
+
+      /* Tell network layer that we want more frames */
+      if (!self->new_speed)
+          netif_wake_queue(self->netdev);
+    }
+
+  if (irqstat & OBOE_INT_RXDONE)
+    {
+      while (!(self->ring->rx[self->rxs].control & OBOE_CTL_RX_HW_OWNS))
+        {
+          int len = self->ring->rx[self->rxs].len;
+          skb = NULL;
+          IRDA_DEBUG (3, "%s.rcv:%x(%x)\n", __FUNCTION__ 
+		      ,len,self->ring->rx[self->rxs].control);
+
+#ifdef DUMP_PACKETS
+dumpbufs(self->rx_bufs[self->rxs],len,'<');
+#endif
+
+          if (self->ring->rx[self->rxs].control == 0)
+            {
+              __u8 enable = INB (OBOE_ENABLEH);
+
+              /* In SIR mode we need to check the CRC as this */
+              /* hasn't been done by the hardware */
+              if (enable & OBOE_ENABLEH_SIRON)
+                {
+                  if (!toshoboe_checkfcs (self->rx_bufs[self->rxs], len))
+                      len = 0;
+                  /*Trim off the CRC */
+                  if (len > 1)
+                      len -= 2;
+                  else
+                      len = 0;
+                  IRDA_DEBUG (1, "%s.SIR:%x(%x)\n", __FUNCTION__, len,enable);
+                }
+
+#ifdef USE_MIR
+              else if (enable & OBOE_ENABLEH_MIRON)
+                {
+                  if (len > 1)
+                      len -= 2;
+                  else
+                      len = 0;
+                  IRDA_DEBUG (2, "%s.MIR:%x(%x)\n", __FUNCTION__, len,enable);
+                }
+#endif
+              else if (enable & OBOE_ENABLEH_FIRON)
+                {
+                  if (len > 3)
+                      len -= 4;   /*FIXME: check this */
+                  else
+                      len = 0;
+                  IRDA_DEBUG (1, "%s.FIR:%x(%x)\n", __FUNCTION__, len,enable);
+                }
+              else 
+                  IRDA_DEBUG (0, "%s.?IR:%x(%x)\n", __FUNCTION__, len,enable);
+
+              if (len)
+                {
+                  skb = dev_alloc_skb (len + 1);
+                  if (skb)
+                    {
+                      skb_reserve (skb, 1);
+
+                      skb_put (skb, len);
+                      memcpy (skb->data, self->rx_bufs[self->rxs], len);
+
+                      self->stats.rx_packets++;
+                      skb->dev = self->netdev;
+                      skb->mac.raw = skb->data;
+                      skb->protocol = htons (ETH_P_IRDA);
+                    }
+                  else
+                    {
+                      printk (KERN_INFO 
+                              "%s(), memory squeeze, dropping frame.\n",
+			      __FUNCTION__);
+                    }
+                }
+            }
+          else 
+            {
+            /* TODO: =========================================== */
+            /*  if OBOE_CTL_RX_LENGTH, our buffers are too small */
+            /* (MIR or FIR) data is lost. */
+            /* (SIR) data is splitted in several slots. */
+            /* we have to join all the received buffers received */
+            /*in a large buffer before checking CRC. */
+            IRDA_DEBUG (0, "%s.err:%x(%x)\n", __FUNCTION__
+                ,len,self->ring->rx[self->rxs].control);
+            }
+
+          self->ring->rx[self->rxs].len = 0x0;
+          self->ring->rx[self->rxs].control = OBOE_CTL_RX_HW_OWNS;
+
+          self->rxs++;
+          self->rxs %= RX_SLOTS;
+
+          if (skb)
+              netif_rx (skb);
+
+        }
+    }
+
+  if (irqstat & OBOE_INT_TXUNDER)
+    {
+      printk (KERN_WARNING DRIVER_NAME ": tx fifo underflow\n");
+    }
+  if (irqstat & OBOE_INT_RXOVER)
+    {
+      printk (KERN_WARNING DRIVER_NAME ": rx fifo overflow\n");
+    }
+/* This must be useful for something... */
+  if (irqstat & OBOE_INT_SIP)
+    {
+      self->int_sip++;
+      IRDA_DEBUG (1, "%s.sip:%x(%x)%x\n", __FUNCTION__
+	      ,self->int_sip,irqstat,self->txpending);
+    }
+}
+
+STATIC int
+toshoboe_net_init (struct net_device *dev)
+{
+  IRDA_DEBUG (4, "%s()\n", __FUNCTION__);
+
+  /* Setup to be a normal IrDA network device driver */
+  irda_device_setup (dev);
+
+  /* Insert overrides below this line! */
+  return 0;
+}
+
+STATIC int
+toshoboe_net_open (struct net_device *dev)
+{
+  struct toshoboe_cb *self;
+  unsigned long flags;
+
+  IRDA_DEBUG (4, "%s()\n", __FUNCTION__);
+
+  ASSERT (dev != NULL, return -1; );
+  self = (struct toshoboe_cb *) dev->priv;
+
+  ASSERT (self != NULL, return 0; );
+
+  if (self->async)
+    return -EBUSY;
+
+  if (self->stopped)
+    return 0;
+
+  if (request_irq (self->io.irq, toshoboe_interrupt,
+                   SA_SHIRQ | SA_INTERRUPT, dev->name, (void *) self))
+    {
+      return -EAGAIN;
+    }
+
+  spin_lock_irqsave(&self->spinlock, flags);
+  toshoboe_startchip (self);
+  spin_unlock_irqrestore(&self->spinlock, flags);
+
+  /* Ready to play! */
+  netif_start_queue(dev);
+
+  /*
+   * Open new IrLAP layer instance, now that everything should be
+   * initialized properly
+   */
+  self->irlap = irlap_open (dev, &self->qos, driver_name);
+
+  self->irdad = 1;
+
+  MOD_INC_USE_COUNT;
+
+  return 0;
+}
+
+STATIC int
+toshoboe_net_close (struct net_device *dev)
+{
+  struct toshoboe_cb *self;
+
+  IRDA_DEBUG (4, "%s()\n", __FUNCTION__);
+
+  ASSERT (dev != NULL, return -1; );
+  self = (struct toshoboe_cb *) dev->priv;
+
+  /* Stop device */
+  netif_stop_queue(dev);
+
+  /* Stop and remove instance of IrLAP */
+  if (self->irlap)
+    irlap_close (self->irlap);
+  self->irlap = NULL;
+
+  self->irdad = 0;
+
+  free_irq (self->io.irq, (void *) self);
+
+  if (!self->stopped)
+    {
+      toshoboe_stopchip (self);
+    }
+
+  MOD_DEC_USE_COUNT;
+
+  return 0;
+}
+
+/*
+ * Function toshoboe_net_ioctl (dev, rq, cmd)
+ *
+ *    Process IOCTL commands for this device
+ *
+ */
+STATIC int
+toshoboe_net_ioctl (struct net_device *dev, struct ifreq *rq, int cmd)
+{
+  struct if_irda_req *irq = (struct if_irda_req *) rq;
+  struct toshoboe_cb *self;
+  unsigned long flags;
+  int ret = 0;
+
+  ASSERT (dev != NULL, return -1; );
+
+  self = dev->priv;
+
+  ASSERT (self != NULL, return -1; );
+
+  IRDA_DEBUG (5, "%s(), %s, (cmd=0x%X)\n", __FUNCTION__, dev->name, cmd);
+
+  /* Disable interrupts & save flags */
+  spin_lock_irqsave(&self->spinlock, flags);
+
+  switch (cmd)
+    {
+    case SIOCSBANDWIDTH:       /* Set bandwidth */
+      /* This function will also be used by IrLAP to change the
+       * speed, so we still must allow for speed change within
+       * interrupt context.
+       */
+      IRDA_DEBUG (1, "%s(BANDWIDTH), %s, (%X/%ld\n", __FUNCTION__
+          ,dev->name, INB (OBOE_STATUS), irq->ifr_baudrate );
+      if (!in_interrupt () && !capable (CAP_NET_ADMIN))
+        return -EPERM;
+
+      /* self->speed=irq->ifr_baudrate; */
+      /* toshoboe_setbaud(self); */
+      /* Just change speed once - inserted by Paul Bristow */
+      self->new_speed = irq->ifr_baudrate;
+      break;
+    case SIOCSMEDIABUSY:       /* Set media busy */
+      IRDA_DEBUG (1, "%s(MEDIABUSY), %s, (%X/%x)\n", __FUNCTION__
+          ,dev->name, INB (OBOE_STATUS), capable (CAP_NET_ADMIN) );
+      if (!capable (CAP_NET_ADMIN))
+        return -EPERM;
+      irda_device_set_media_busy (self->netdev, TRUE);
+      break;
+    case SIOCGRECEIVING:       /* Check if we are receiving right now */
+      irq->ifr_receiving = (INB (OBOE_STATUS) & OBOE_STATUS_RXBUSY) ? 1 : 0;
+      IRDA_DEBUG (3, "%s(RECEIVING), %s, (%X/%x)\n", __FUNCTION__
+          ,dev->name, INB (OBOE_STATUS), irq->ifr_receiving );
+      break;
+    default:
+      IRDA_DEBUG (1, "%s(?), %s, (cmd=0x%X)\n", __FUNCTION__, dev->name, cmd);
+      ret = -EOPNOTSUPP;
+    }
+
+  spin_unlock_irqrestore(&self->spinlock, flags);
+  return ret;
+
+}
+
+MODULE_DESCRIPTION("Toshiba OBOE IrDA Device Driver");
+MODULE_AUTHOR("James McKenzie <james@fishsoup.dhs.org>");
+MODULE_LICENSE("GPL");
+
+MODULE_PARM (max_baud, "i");
+MODULE_PARM_DESC(max_baud, "Maximum baud rate");
+
+MODULE_PARM (do_probe, "i");
+MODULE_PARM_DESC(do_probe, "Enable/disable chip probing and self-test");
+
+STATIC void
+toshoboe_close (struct pci_dev *pci_dev)
+{
+  int i;
+  struct toshoboe_cb *self = (struct toshoboe_cb*)pci_get_drvdata(pci_dev);
+
+  IRDA_DEBUG (4, "%s()\n", __FUNCTION__);
+
+  ASSERT (self != NULL, return; );
+
+  if (!self->stopped)
+    {
+      toshoboe_stopchip (self);
+    }
+
+  release_region (self->io.fir_base, self->io.fir_ext);
+
+  for (i = 0; i < TX_SLOTS; ++i)
+    {
+      kfree (self->tx_bufs[i]);
+      self->tx_bufs[i] = NULL;
+    }
+
+  for (i = 0; i < RX_SLOTS; ++i)
+    {
+      kfree (self->rx_bufs[i]);
+      self->rx_bufs[i] = NULL;
+    }
+
+  if (self->netdev)
+    {
+      /* Remove netdevice */
+      rtnl_lock ();
+      unregister_netdevice (self->netdev);
+      rtnl_unlock ();
+    }
+
+  kfree (self->ringbuf);
+  self->ringbuf = NULL;
+  self->ring = NULL;
+
+  return;
+}
+
+STATIC int
+toshoboe_open (struct pci_dev *pci_dev, const struct pci_device_id *pdid)
+{
+  struct toshoboe_cb *self;
+  struct net_device *dev;
+  int i = 0;
+  int ok = 0;
+  int err;
+
+  IRDA_DEBUG (4, "%s()\n", __FUNCTION__);
+
+  if ((err=pci_enable_device(pci_dev)))
+    return err;
+
+  self = kmalloc (sizeof (struct toshoboe_cb), GFP_KERNEL);
+
+  if (self == NULL)
+    {
+      printk (KERN_ERR DRIVER_NAME ": can't allocate memory for "
+              "IrDA control block\n");
+      return -ENOMEM;
+    }
+
+  memset (self, 0, sizeof (struct toshoboe_cb));
+
+  self->pdev = pci_dev;
+  self->base = pci_resource_start(pci_dev,0);
+
+  self->io.fir_base = self->base;
+  self->io.fir_ext = OBOE_IO_EXTENT;
+  self->io.irq = pci_dev->irq;
+  self->io.irqflags = SA_SHIRQ | SA_INTERRUPT;
+
+  self->speed = self->io.speed = 9600;
+  self->async = 0;
+
+  /* Lock the port that we need */
+  if (NULL==request_region (self->io.fir_base, self->io.fir_ext, driver_name))
+    {
+      printk (KERN_ERR DRIVER_NAME ": can't get iobase of 0x%03x\n"
+	      ,self->io.fir_base);
+      err = -EBUSY;
+      goto freeself;
+    }
+
+  spin_lock_init(&self->spinlock);
+  
+  irda_init_max_qos_capabilies (&self->qos);
+  self->qos.baud_rate.bits = 0;
+
+  if (max_baud >= 2400)
+    self->qos.baud_rate.bits |= IR_2400;
+  /*if (max_baud>=4800) idev->qos.baud_rate.bits|=IR_4800; */
+  if (max_baud >= 9600)
+    self->qos.baud_rate.bits |= IR_9600;
+  if (max_baud >= 19200)
+    self->qos.baud_rate.bits |= IR_19200;
+  if (max_baud >= 115200)
+    self->qos.baud_rate.bits |= IR_115200;
+#ifdef USE_MIR
+  if (max_baud >= 1152000)
+    {
+      self->qos.baud_rate.bits |= IR_1152000;
+      self->flags |= IFF_MIR;
+    }
+#endif
+  if (max_baud >= 4000000)
+    {
+      self->qos.baud_rate.bits |= (IR_4000000 << 8);
+      self->flags |= IFF_FIR;
+    }
+
+  /*FIXME: work this out... */
+  self->qos.min_turn_time.bits = 0xff;
+
+  irda_qos_bits_to_value (&self->qos);
+
+  self->flags = IFF_SIR | IFF_DMA | IFF_PIO;
+
+  /* Allocate twice the size to guarantee alignment */
+  self->ringbuf = (void *) kmalloc (OBOE_RING_LEN << 1, GFP_KERNEL);
+  if (!self->ringbuf)
+    {
+      printk (KERN_ERR DRIVER_NAME ": can't allocate DMA buffers\n");
+      err = -ENOMEM;
+      goto freeregion;
+    }
+
+  /*We need to align the taskfile on a taskfile size boundary */
+  {
+    __u32 addr;
+
+    addr = (__u32) self->ringbuf;
+    addr &= ~(OBOE_RING_LEN - 1);
+    addr += OBOE_RING_LEN;
+    self->ring = (struct OboeRing *) addr;
+  }
+
+  memset (self->ring, 0, OBOE_RING_LEN);
+  self->io.mem_base = (__u32) self->ring;
+
+  ok = 1;
+  for (i = 0; i < TX_SLOTS; ++i)
+    {
+      self->tx_bufs[i] = kmalloc (TX_BUF_SZ, GFP_KERNEL);
+      if (!self->tx_bufs[i])
+        ok = 0;
+    }
+
+  for (i = 0; i < RX_SLOTS; ++i)
+    {
+      self->rx_bufs[i] = kmalloc (RX_BUF_SZ, GFP_KERNEL);
+      if (!self->rx_bufs[i])
+        ok = 0;
+    }
+
+  if (!ok)
+    {
+      printk (KERN_ERR DRIVER_NAME ": can't allocate rx/tx buffers\n");
+      err = -ENOMEM;
+      goto freebufs;
+    }
+
+  if (do_probe)
+    if (!toshoboe_probe (self))
+      {
+        err = -ENODEV;
+        goto freebufs;
+      }
+
+  if (!(dev = dev_alloc ("irda%d", &err)))
+    {
+      printk (KERN_ERR DRIVER_NAME ": dev_alloc() failed\n");
+      err = -ENOMEM;
+      goto freebufs;
+    }
+
+  dev->priv = (void *) self;
+  self->netdev = dev;
+
+  printk (KERN_INFO "IrDA: Registered device %s\n", dev->name);
+
+  dev->init = toshoboe_net_init;
+  dev->hard_start_xmit = toshoboe_hard_xmit;
+  dev->open = toshoboe_net_open;
+  dev->stop = toshoboe_net_close;
+  dev->do_ioctl = toshoboe_net_ioctl;
+
+  rtnl_lock ();
+  err = register_netdevice (dev);
+  rtnl_unlock ();
+  if (err)
+    {
+      printk (KERN_ERR DRIVER_NAME ": register_netdev() failed\n");
+      err = -ENOMEM;
+      goto freebufs;
+    }
+
+  pci_set_drvdata(pci_dev,self);
+
+  printk (KERN_INFO DRIVER_NAME ": Using multiple tasks, version %s\n", rcsid);
+
+  return 0;
+
+freebufs:
+  for (i = 0; i < TX_SLOTS; ++i)
+    if (self->tx_bufs[i])
+      kfree (self->tx_bufs[i]);
+  for (i = 0; i < RX_SLOTS; ++i)
+    if (self->rx_bufs[i])
+      kfree (self->rx_bufs[i]);
+  kfree(self->ringbuf);
+
+freeregion:
+  release_region (self->io.fir_base, self->io.fir_ext);
+
+freeself:
+  kfree (self);
+
+  return err;
+}
+
+STATIC int
+toshoboe_gotosleep (struct pci_dev *pci_dev, u32 crap)
+{
+  struct toshoboe_cb *self = (struct toshoboe_cb*)pci_get_drvdata(pci_dev);
+  unsigned long flags;
+  int i = 10;
+
+  IRDA_DEBUG (4, "%s()\n", __FUNCTION__);
+
+  if (!self || self->stopped)
+    return 0;
+
+  if ((!self->irdad) && (!self->async))
+    return 0;
+
+/* Flush all packets */
+  while ((i--) && (self->txpending))
+    udelay (10000);
+
+  spin_lock_irqsave(&self->spinlock, flags);
+
+  toshoboe_stopchip (self);
+  self->stopped = 1;
+  self->txpending = 0;
+
+  spin_unlock_irqrestore(&self->spinlock, flags);
+  return 0;
+}
+
+STATIC int
+toshoboe_wakeup (struct pci_dev *pci_dev)
+{
+  struct toshoboe_cb *self = (struct toshoboe_cb*)pci_get_drvdata(pci_dev);
+  unsigned long flags;
+
+  IRDA_DEBUG (4, "%s()\n", __FUNCTION__);
+
+  if (!self || !self->stopped)
+    return 0;
+
+  if ((!self->irdad) && (!self->async))
+    return 0;
+
+  spin_lock_irqsave(&self->spinlock, flags);
+
+  toshoboe_startchip (self);
+  self->stopped = 0;
+
+  netif_wake_queue(self->netdev);
+  spin_unlock_irqrestore(&self->spinlock, flags);
+  return 0;
+}
+
+static struct pci_driver toshoboe_pci_driver = {
+  name		: "toshoboe",
+  id_table	: toshoboe_pci_tbl,
+  probe		: toshoboe_open,
+  remove	: toshoboe_close,
+  suspend	: toshoboe_gotosleep,
+  resume	: toshoboe_wakeup 
+};
+
+int __init
+toshoboe_init (void)
+{
+  return pci_module_init(&toshoboe_pci_driver);
+}
+
+STATIC void __exit
+toshoboe_cleanup (void)
+{
+  pci_unregister_driver(&toshoboe_pci_driver);
+}
+
+module_init(toshoboe_init);
+module_exit(toshoboe_cleanup);
diff -u -p -r --new-file linux/drivers/net/irda.d2/donauboe.h linux/drivers/net/irda/donauboe.h
--- linux/drivers/net/irda.d2/donauboe.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/net/irda/donauboe.h	Thu Sep 12 10:44:56 2002
@@ -0,0 +1,363 @@
+/*********************************************************************
+ *                
+ * Filename:      toshoboe.h
+ * Version:       2.16
+ * Description:   Driver for the Toshiba OBOE (or type-O or 701)
+ *                FIR Chipset, also supports the DONAUOBOE (type-DO
+ *                or d01) FIR chipset which as far as I know is
+ *                register compatible.
+ * Status:        Experimental.
+ * Author:        James McKenzie <james@fishsoup.dhs.org>
+ * Created at:    Sat May 8  12:35:27 1999
+ * Modified: 2.16 Martin Lucina <mato@kotelna.sk>
+ * Modified: 2.16 Sat Jun 22 18:54:29 2002 (sync headers)
+ * Modified: 2.17 Christian Gennerat <christian.gennerat@polytechnique.org>
+ * Modified: 2.17 jeu sep 12 08:50:20 2002 (add lock to be used by spinlocks)
+ * 
+ *     Copyright (c) 1999 James McKenzie, All Rights Reserved.
+ *      
+ *     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 2 of 
+ *     the License, or (at your option) any later version.
+ *  
+ *     Neither James McKenzie nor Cambridge University admit liability nor
+ *     provide warranty for any of this software. This material is 
+ *     provided "AS-IS" and at no charge.
+ * 
+ *     Applicable Models : Libretto 100/110CT and many more.
+ *     Toshiba refers to this chip as the type-O IR port,
+ *     or the type-DO IR port.
+ *
+ * IrDA chip set list from Toshiba Computer Engineering Corp.
+ * model			method	maker	controler		Version 
+ * Portege 320CT	FIR,SIR Toshiba Oboe(Triangle) 
+ * Portege 3010CT	FIR,SIR Toshiba Oboe(Sydney) 
+ * Portege 3015CT	FIR,SIR Toshiba Oboe(Sydney) 
+ * Portege 3020CT	FIR,SIR Toshiba Oboe(Sydney) 
+ * Portege 7020CT	FIR,SIR ?		?
+ * 
+ * Satell. 4090XCDT	FIR,SIR ?		?
+ * 
+ * Libretto 100CT	FIR,SIR Toshiba Oboe 
+ * Libretto 1000CT	FIR,SIR Toshiba Oboe 
+ * 
+ * TECRA750DVD		FIR,SIR Toshiba Oboe(Triangle)	REV ID=14h 
+ * TECRA780			FIR,SIR Toshiba Oboe(Sandlot)	REV ID=32h,33h 
+ * TECRA750CDT		FIR,SIR Toshiba Oboe(Triangle)	REV ID=13h,14h 
+ * TECRA8000		FIR,SIR Toshiba Oboe(ISKUR)		REV ID=23h 
+ * 
+ ********************************************************************/
+
+/* The documentation for this chip is allegedly released         */
+/* However I have not seen it, not have I managed to contact     */
+/* anyone who has. HOWEVER the chip bears a striking resemblence */
+/* to the IrDA controller in the Toshiba RISC TMPR3922 chip      */
+/* the documentation for this is freely available at             */
+/* http://www.toshiba.com/taec/components/Generic/TMPR3922.shtml */
+/* The mapping between the registers in that document and the    */
+/* Registers in the 701 oboe chip are as follows    */
+
+
+/* 3922 reg     701 regs, by bit numbers                        */
+/*               7- 0  15- 8  24-16  31-25                      */
+/* $28            0x0    0x1                                    */
+/* $2c                                     SEE NOTE 1           */
+/* $30            0x6    0x7                                    */
+/* $34            0x8    0x9               SEE NOTE 2           */
+/* $38           0x10   0x11                                    */
+/* $3C                   0xe               SEE NOTE 3           */
+/* $40           0x12   0x13                                    */
+/* $44           0x14   0x15                                    */
+/* $48           0x16   0x17                                    */
+/* $4c           0x18   0x19                                    */
+/* $50           0x1a   0x1b                                    */
+
+/* FIXME: could be 0x1b 0x1a here */
+
+/* $54           0x1d   0x1c                                    */
+/* $5C           0xf                       SEE NOTE 4           */
+/* $130                                    SEE NOTE 5           */
+/* $134                                    SEE NOTE 6           */
+/*                                                              */
+/* NOTES:                                                       */
+/* 1. The pointer to ring is packed in most unceremoniusly      */
+/*    701 Register      Address bits    (A9-A0 must be zero)    */
+/*            0x4:      A17 A16 A15 A14 A13 A12 A11 A10         */
+/*            0x5:      A25 A24 A23 A22 A21 A20 A19 A18         */
+/*            0x2:        0   0 A31 A30 A29 A28 A27 A26         */
+/*                                                              */
+/* 2. The M$ drivers do a write 0x1 to 0x9, however the 3922    */
+/*    documentation would suggest that a write of 0x1 to 0x8    */
+/*    would be more appropriate.                                */
+/*                                                              */
+/* 3. This assignment is tenuous at best, register 0xe seems to */
+/*    have bits arranged 0 0 0 R/W R/W R/W R/W R/W              */
+/*    if either of the lower two bits are set the chip seems to */
+/*    switch off                                                */
+/*                                                              */
+/* 4. Bits 7-4 seem to be different 4 seems just to be generic  */
+/*    receiver busy flag                                        */
+/*                                                              */
+/* 5. and 6. The IER and ISR have a different bit assignment    */
+/*    The lower three bits of both read back as ones            */
+/* ISR is register 0xc, IER is register 0xd                     */
+/*           7      6      5      4      3      2      1      0 */
+/* 0xc: TxDone RxDone TxUndr RxOver SipRcv      1      1      1 */
+/* 0xd: TxDone RxDone TxUndr RxOver SipRcv      1      1      1 */
+/* TxDone xmitt done (generated only if generate interrupt bit  */
+/*   is set in the ring)                                        */
+/* RxDone recv completed (or other recv condition if you set it */
+/*   up                                                         */
+/* TxUnder underflow in Transmit FIFO                           */
+/* RxOver  overflow in Recv FIFO                                */
+/* SipRcv  received serial gap  (or other condition you set)    */
+/* Interrupts are enabled by writing a one to the IER register  */
+/* Interrupts are cleared by writting a one to the ISR register */
+/*                                                              */
+/* 6. The remaining registers: 0x6 and 0x3 appear to be         */
+/*    reserved parts of 16 or 32 bit registersthe remainder     */
+/*    0xa 0xb 0x1e 0x1f could possibly be (by their behaviour)  */
+/*    the Unicast Filter register at $58.                       */
+/*                                                              */
+/* 7. While the core obviously expects 32 bit accesses all the  */
+/*    M$ drivers do 8 bit accesses, infact the Miniport ones    */
+/*    write and read back the byte serveral times (why?)        */
+
+
+#ifndef TOSHOBOE_H
+#define TOSHOBOE_H
+
+/* Registers */
+
+#define OBOE_IO_EXTENT	0x1f
+
+/*Receive and transmit slot pointers */
+#define OBOE_REG(i)	(i+(self->base))
+#define OBOE_RXSLOT	OBOE_REG(0x0)
+#define OBOE_TXSLOT	OBOE_REG(0x1)
+#define OBOE_SLOT_MASK	0x3f
+
+#define OBOE_TXRING_OFFSET		0x200
+#define OBOE_TXRING_OFFSET_IN_SLOTS	0x40
+
+/*pointer to the ring */
+#define OBOE_RING_BASE0	OBOE_REG(0x4)
+#define OBOE_RING_BASE1	OBOE_REG(0x5)
+#define OBOE_RING_BASE2	OBOE_REG(0x2)
+#define OBOE_RING_BASE3	OBOE_REG(0x3)
+
+/*Number of slots in the ring */
+#define OBOE_RING_SIZE  OBOE_REG(0x7)
+#define OBOE_RING_SIZE_RX4	0x00
+#define OBOE_RING_SIZE_RX8	0x01
+#define OBOE_RING_SIZE_RX16	0x03
+#define OBOE_RING_SIZE_RX32	0x07
+#define OBOE_RING_SIZE_RX64	0x0f
+#define OBOE_RING_SIZE_TX4	0x00
+#define OBOE_RING_SIZE_TX8	0x10
+#define OBOE_RING_SIZE_TX16	0x30
+#define OBOE_RING_SIZE_TX32	0x70
+#define OBOE_RING_SIZE_TX64	0xf0
+
+#define OBOE_RING_MAX_SIZE	64
+
+/*Causes the gubbins to re-examine the ring */
+#define OBOE_PROMPT	OBOE_REG(0x9)
+#define OBOE_PROMPT_BIT		0x1
+
+/* Interrupt Status Register */
+#define OBOE_ISR	OBOE_REG(0xc)
+/* Interrupt Enable Register */
+#define OBOE_IER	OBOE_REG(0xd)
+/* Interrupt bits for IER and ISR */
+#define OBOE_INT_TXDONE		0x80
+#define OBOE_INT_RXDONE		0x40
+#define OBOE_INT_TXUNDER	0x20
+#define OBOE_INT_RXOVER		0x10
+#define OBOE_INT_SIP		0x08
+#define OBOE_INT_MASK		0xf8
+
+/*Reset Register */
+#define OBOE_CONFIG1	OBOE_REG(0xe)
+#define OBOE_CONFIG1_RST	0x01
+#define OBOE_CONFIG1_DISABLE	0x02
+#define OBOE_CONFIG1_4		0x08
+#define OBOE_CONFIG1_8		0x08
+
+#define OBOE_CONFIG1_ON		0x8
+#define OBOE_CONFIG1_RESET	0xf
+#define OBOE_CONFIG1_OFF	0xe
+
+#define OBOE_STATUS	OBOE_REG(0xf)
+#define OBOE_STATUS_RXBUSY	0x10
+#define OBOE_STATUS_FIRRX	0x04
+#define OBOE_STATUS_MIRRX	0x02
+#define OBOE_STATUS_SIRRX	0x01
+
+
+/*Speed control registers */
+#define OBOE_CONFIG0L	OBOE_REG(0x10)
+#define OBOE_CONFIG0H	OBOE_REG(0x11)
+
+#define OBOE_CONFIG0H_TXONLOOP  0x80 /*Transmit when looping (dangerous) */
+#define OBOE_CONFIG0H_LOOP	0x40 /*Loopback Tx->Rx */
+#define OBOE_CONFIG0H_ENTX	0x10 /*Enable Tx */
+#define OBOE_CONFIG0H_ENRX	0x08 /*Enable Rx */
+#define OBOE_CONFIG0H_ENDMAC	0x04 /*Enable/reset* the DMA controller */
+#define OBOE_CONFIG0H_RCVANY	0x02 /*DMA mode 1=bytes, 0=dwords */
+
+#define OBOE_CONFIG0L_CRC16	0x80 /*CRC 1=16 bit 0=32 bit */
+#define OBOE_CONFIG0L_ENFIR	0x40 /*Enable FIR */
+#define OBOE_CONFIG0L_ENMIR	0x20 /*Enable MIR */
+#define OBOE_CONFIG0L_ENSIR	0x10 /*Enable SIR */
+#define OBOE_CONFIG0L_ENSIRF	0x08 /*Enable SIR framer */
+#define OBOE_CONFIG0L_SIRTEST	0x04 /*Enable SIR framer in MIR and FIR */
+#define OBOE_CONFIG0L_INVERTTX  0x02 /*Invert Tx Line */
+#define OBOE_CONFIG0L_INVERTRX  0x01 /*Invert Rx Line */
+
+#define OBOE_BOF	OBOE_REG(0x12)
+#define OBOE_EOF	OBOE_REG(0x13)
+
+#define OBOE_ENABLEL	OBOE_REG(0x14)
+#define OBOE_ENABLEH	OBOE_REG(0x15)
+
+#define OBOE_ENABLEH_PHYANDCLOCK	0x80 /*Toggle low to copy config in */
+#define OBOE_ENABLEH_CONFIGERR		0x40
+#define OBOE_ENABLEH_FIRON		0x20
+#define OBOE_ENABLEH_MIRON		0x10
+#define OBOE_ENABLEH_SIRON		0x08
+#define OBOE_ENABLEH_ENTX		0x04
+#define OBOE_ENABLEH_ENRX		0x02
+#define OBOE_ENABLEH_CRC16		0x01
+
+#define OBOE_ENABLEL_BROADCAST		0x01
+
+#define OBOE_CURR_PCONFIGL		OBOE_REG(0x16) /*Current config */
+#define OBOE_CURR_PCONFIGH		OBOE_REG(0x17)
+
+#define OBOE_NEW_PCONFIGL		OBOE_REG(0x18)
+#define OBOE_NEW_PCONFIGH		OBOE_REG(0x19)
+
+#define OBOE_PCONFIGH_BAUDMASK		0xfc
+#define OBOE_PCONFIGH_WIDTHMASK		0x04
+#define OBOE_PCONFIGL_WIDTHMASK		0xe0
+#define OBOE_PCONFIGL_PREAMBLEMASK	0x1f
+
+#define OBOE_PCONFIG_BAUDMASK		0xfc00
+#define OBOE_PCONFIG_BAUDSHIFT		10
+#define OBOE_PCONFIG_WIDTHMASK		0x04e0
+#define OBOE_PCONFIG_WIDTHSHIFT		5
+#define OBOE_PCONFIG_PREAMBLEMASK	0x001f
+#define OBOE_PCONFIG_PREAMBLESHIFT	0
+
+#define OBOE_MAXLENL			OBOE_REG(0x1a)
+#define OBOE_MAXLENH			OBOE_REG(0x1b)
+
+#define OBOE_RXCOUNTH			OBOE_REG(0x1c) /*Reset on recipt */
+#define OBOE_RXCOUNTL			OBOE_REG(0x1d) /*of whole packet */
+
+/* The PCI ID of the OBOE chip */
+#ifndef PCI_DEVICE_ID_FIR701
+#define PCI_DEVICE_ID_FIR701 	0x0701
+#endif
+
+#ifndef PCI_DEVICE_ID_FIRD01
+#define PCI_DEVICE_ID_FIRD01 	0x0d01
+#endif
+
+struct OboeSlot
+{
+  __u16 len;                    /*Tweleve bits of packet length */
+  __u8 unused;
+  __u8 control;                 /*Slot control/status see below */
+  __u32 address;                /*Slot buffer address */
+}
+__attribute__ ((packed));
+
+#define OBOE_NTASKS OBOE_TXRING_OFFSET_IN_SLOTS
+
+struct OboeRing
+{
+  struct OboeSlot rx[OBOE_NTASKS];
+  struct OboeSlot tx[OBOE_NTASKS];
+};
+
+#define OBOE_RING_LEN (sizeof(struct OboeRing))
+
+
+#define OBOE_CTL_TX_HW_OWNS	0x80 /*W/R This slot owned by the hardware */
+#define OBOE_CTL_TX_DISTX_CRC	0x40 /*W Disable CRC generation for [FM]IR */
+#define OBOE_CTL_TX_BAD_CRC     0x20 /*W Generate bad CRC */
+#define OBOE_CTL_TX_SIP		0x10   /*W Generate an SIP after xmittion */
+#define OBOE_CTL_TX_MKUNDER	0x08 /*W Generate an underrun error */
+#define OBOE_CTL_TX_RTCENTX	0x04 /*W Enable receiver and generate TXdone */
+     /*  After this slot is processed        */
+#define OBOE_CTL_TX_UNDER	0x01  /*R Set by hardware to indicate underrun */
+
+
+#define OBOE_CTL_RX_HW_OWNS	0x80 /*W/R This slot owned by hardware */
+#define OBOE_CTL_RX_PHYERR	0x40 /*R Decoder error on receiption */
+#define OBOE_CTL_RX_CRCERR	0x20 /*R CRC error only set for [FM]IR */
+#define OBOE_CTL_RX_LENGTH	0x10 /*R Packet > max Rx length  */
+#define OBOE_CTL_RX_OVER	0x08   /*R set to indicate an overflow */
+#define OBOE_CTL_RX_SIRBAD	0x04 /*R SIR had BOF in packet or ABORT sequence */
+#define OBOE_CTL_RX_RXEOF	0x02  /*R Finished receiving on this slot */
+
+
+struct toshoboe_cb
+{
+  struct net_device *netdev;    /* Yes! we are some kind of netdevice */
+  struct net_device_stats stats;
+  struct tty_driver ttydev;
+
+  struct irlap_cb *irlap;       /* The link layer we are binded to */
+
+  chipio_t io;                  /* IrDA controller information */
+  struct qos_info qos;          /* QoS capabilities for this device */
+
+  __u32 flags;                  /* Interface flags */
+
+  struct pci_dev *pdev;         /*PCI device */
+  int base;                     /*IO base */
+
+
+  int txpending;                /*how many tx's are pending */
+  int txs, rxs;                 /*Which slots are we at  */
+
+  int irdad;                    /*Driver under control of netdev end  */
+  int async;                    /*Driver under control of async end   */
+
+
+  int stopped;                  /*Stopped by some or other APM stuff */
+
+  int filter;                   /*In SIR mode do we want to receive
+                                   frames or byte ranges */
+
+  void *ringbuf;                /*The ring buffer */
+  struct OboeRing *ring;        /*The ring */
+
+  void *tx_bufs[OBOE_RING_MAX_SIZE]; /*The buffers   */
+  void *rx_bufs[OBOE_RING_MAX_SIZE];
+
+
+  int speed;                    /*Current setting of the speed */
+  int new_speed;                /*Set to request a speed change */
+
+/* The spinlock protect critical parts of the driver.
+ *	Locking is done like this :
+ *		spin_lock_irqsave(&self->spinlock, flags);
+ *	Releasing the lock :
+ *		spin_unlock_irqrestore(&self->spinlock, flags);
+ */
+  spinlock_t spinlock;		
+  /* Used for the probe and diagnostics code */
+  int int_rx;
+  int int_tx;
+  int int_txunder;
+  int int_rxover;
+  int int_sip;
+};
+
+
+#endif

^ permalink raw reply

* RE: [PATCH][2.4]  generic cluster APIC support for systems with more than 8 CPUs
From: Pallipadi, Venkatesh @ 2002-12-19  2:45 UTC (permalink / raw)
  To: jamesclv, Linux Kernel, Christoph Hellwig
  Cc: Martin Bligh, John Stultz, Nakajima, Jun, Mallick, Asit K,
	Saxena, Sunil


> From: James Cleverdon [mailto:jamesclv@us.ibm.com]
> > On Wednesday 18 December 2002 05:05 pm, Pallipadi, Venkatesh wrote:
> > I am not really sure about the local APIC versions in summit. What I
> > remember seeing on lkml was summit has older IOAPIC 
> version. Can someone
> > clarify this?
> 
> Sure, I can verify it.  The I/O APICs in shipped summit 
> chipsets contains a 
> version ID of 0x11 instead of 0x14 to 0x1F.  The high 
> performance folks 
> claimed that Intel specified 0x14 for the local APICs, but 
> left their orange 
> jacket docs saying 0x1X for I/O APICs until after the chips taped out.
> 
> Whatever.  In any case, there are boxes in the field that 
> contain those 
> version numbers.  We can recognize them using the OEM and 
> product strings in 
> the MPS and ACPI tables, so it's only an annoyance.
> 

OK. In my patch I am looking at local APIC version > 0x14, to check xAPIC support.
This should work on all systems irrespective of IOAPIC version.
And even if there are problems here for summit, we can workaround it, by simply 
forcing xAPIC support at already existing OEM string check.


Thanks,
-Venkatesh 

^ permalink raw reply

* [PATCH] [v850]  Pass extra signal handler args correctly on the v850
From: Miles Bader @ 2002-12-19  2:43 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: linux-kernel

The old code seems completely wrong; I guess it was just left over from
whichever architecture this code was copied from.

diff -ruN -X../cludes ../orig/linux-2.5.52-uc0/arch/v850/kernel/signal.c arch/v850/kernel/signal.c
--- ../orig/linux-2.5.52-uc0/arch/v850/kernel/signal.c	2002-11-28 10:24:54.000000000 +0900
+++ arch/v850/kernel/signal.c	2002-12-19 11:37:31.000000000 +0900
@@ -147,8 +146,6 @@
 
 struct rt_sigframe
 {
-	struct siginfo *pinfo;
-	void *puc;
 	struct siginfo info;
 	struct ucontext uc;
 	unsigned long tramp[2];	/* signal trampoline */
@@ -330,10 +327,12 @@
 	if (err)
 		goto give_sigsegv;
 
-	/* Set up registers for signal handler */
-	regs->gpr[GPR_SP] = (unsigned long) frame;
-	regs->gpr[GPR_ARG0] = signal; /* Arg for signal handler */
-	regs->pc = (unsigned long) ka->sa.sa_handler;
+	/* Set up registers for signal handler.  */
+	regs->pc = (v850_reg_t) ka->sa.sa_handler;
+	regs->gpr[GPR_SP] = (v850_reg_t)frame;
+	/* Signal handler args:  */
+	regs->gpr[GPR_ARG0] = signal; /* arg 0: signum */
+	regs->gpr[GPR_ARG1] = (v850_reg_t)&frame->sc;/* arg 1: sigcontext */
 
 	set_fs(USER_DS);
 
@@ -368,8 +367,6 @@
 		? current_thread_info()->exec_domain->signal_invmap[sig]
 		: sig;
 
-	err |= __put_user(&frame->info, &frame->pinfo);
-	err |= __put_user(&frame->uc, &frame->puc);
 	err |= copy_siginfo_to_user(&frame->info, info);
 
 	/* Create the ucontext.  */
@@ -406,10 +403,13 @@
 	if (err)
 		goto give_sigsegv;
 
-	/* Set up registers for signal handler */
-	regs->gpr[GPR_SP] = (unsigned long) frame;
-	regs->gpr[GPR_ARG0] = signal; /* Arg for signal handler */
-	regs->pc = (unsigned long) ka->sa.sa_handler;
+	/* Set up registers for signal handler.  */
+	regs->pc = (v850_reg_t) ka->sa.sa_handler;
+	regs->gpr[GPR_SP] = (v850_reg_t)frame;
+	/* Signal handler args:  */
+	regs->gpr[GPR_ARG0] = signal; /* arg 0: signum */
+	regs->gpr[GPR_ARG1] = (v850_reg_t)&frame->info; /* arg 1: siginfo */
+	regs->gpr[GPR_ARG2] = (v850_reg_t)&frame->uc; /* arg 2: ucontext */
 
 	set_fs(USER_DS);
 

^ permalink raw reply

* Re: modules oops in 2.5.52
From: Rusty Russell @ 2002-12-19  2:11 UTC (permalink / raw)
  To: Jeremy Fitzhardinge; +Cc: Linux Kernel List
In-Reply-To: <1040260444.1316.4.camel@ixodes.goop.org>

In message <1040260444.1316.4.camel@ixodes.goop.org> you write:
> Hi,
> 
> I just had an oops in the modules code:
> 
> Dec 18 16:58:59 ixodes kernel: Unable to handle kernel paging request at virt
ual address f8980924
> Dec 18 16:58:59 ixodes kernel:  printing eip:
> Dec 18 16:58:59 ixodes kernel: f896756d
> Dec 18 16:58:59 ixodes kernel: *pde = 01bfc067
> Dec 18 16:58:59 ixodes kernel: *pte = 00000000
> Dec 18 16:58:59 ixodes kernel: Oops: 0000
> Dec 18 16:58:59 ixodes kernel: CPU:    0
> Dec 18 16:58:59 ixodes kernel: EIP:    0060:[<f896756d>]    Not tainted
> Dec 18 16:58:59 ixodes kernel: EFLAGS: 00010282
> Dec 18 16:58:59 ixodes kernel: EIP is at __exitfn+0xd/0x4c [parport_pc]

Actually, you had an oops in the parport_pc code, in
cleanup_module().  Now, *why* that oopsed, I don't know...

> Now, any process which touches /proc/modules hangs, I guess because a
> lock was being held.

Yes.  Changing this would be particularly interesting, since you don't
want a simultaneous "modprobe" to fail.

Rusty.
--
  Anyone who quotes me in their sig is an idiot. -- Rusty Russell.

^ permalink raw reply

* [PATCH 2.4] : IrLMP basic socket scheduler (to make 2.4.21-pre2 compile)
From: Jean Tourrilhes @ 2002-12-19  2:40 UTC (permalink / raw)
  To: Marcelo Tosatti, Linux kernel mailing list

	Hi Marcelo,

	One of the IrDA patch I sent you didn't made it into the
kernel. That's unfortunate because it was one half of a complete
patch, and as the other part is in the kernel, the IrDA stack is not
functional (see previous e-mail).
	I've rediffed the patch against 2.4.21-pre2 to avoid the fuzz,
and it is included below. Would you mind including that in the kernel ?

	Regards,

	Jean


ir241_flow_sched_lap_lmp-7.diff :
-------------------------------
        o [FEATURE] Reduce LAP Tx queue to 2 packets (from 10)
                Improve latency, reduce buffer usage
        o [FEATURE] LAP Tx queue not full notification (flow start)
                Poll higher layer to fill synchronously LAP window (7 packets)
        o [FEATURE] LMP LSAP scheduler
                Ensure Tx fairness between LSAPs (sockets, IrCOMM, IrNET...)

		<And I might add...>
        o [CRITICA] Required by the IrTTP patch already in 2.4.21-pre2


diff -u -p -r linux/include/net/irda/irlap.d6.h linux/include/net/irda/irlap.h
--- linux/include/net/irda/irlap.d6.h	Wed Dec 18 17:54:47 2002
+++ linux/include/net/irda/irlap.h	Wed Dec 18 17:56:13 2002
@@ -50,8 +50,32 @@
 #define CBROADCAST 0xfe       /* Connection broadcast address */
 #define XID_FORMAT 0x01       /* Discovery XID format */
 
+/* Nobody seems to use this constant. */
 #define LAP_WINDOW_SIZE 8
-#define LAP_MAX_QUEUE  10
+/* We keep the LAP queue very small to minimise the amount of buffering.
+ * this improve latency and reduce resource consumption.
+ * This work only because we have synchronous refilling of IrLAP through
+ * the flow control mechanism (via scheduler and IrTTP).
+ * 2 buffers is the minimum we can work with, one that we send while polling
+ * IrTTP, and another to know that we should not send the pf bit.
+ * Jean II */
+#define LAP_HIGH_THRESHOLD     2
+/* Some rare non TTP clients don't implement flow control, and
+ * so don't comply with the above limit (and neither with this one).
+ * For IAP and management, it doesn't matter, because they never transmit much.
+ *.For IrLPT, this should be fixed.
+ * - Jean II */
+#define LAP_MAX_QUEUE 10
+/* Please note that all IrDA management frames (LMP/TTP conn req/disc and
+ * IAS queries) fall in the second category and are sent to LAP even if TTP
+ * is stopped. This means that those frames will wait only a maximum of
+ * two (2) data frames before beeing sent on the "wire", which speed up
+ * new socket setup when the link is saturated.
+ * Same story for two sockets competing for the medium : if one saturates
+ * the LAP, when the other want to transmit it only has to wait for
+ * maximum three (3) packets (2 + one scheduling), which improve performance
+ * of delay sensitive applications.
+ * Jean II */
 
 #define NR_EXPECTED     1
 #define NR_UNEXPECTED   0
diff -u -p -r linux/include/net/irda/irlmp.d6.h linux/include/net/irda/irlmp.h
--- linux/include/net/irda/irlmp.d6.h	Wed Dec 18 17:54:56 2002
+++ linux/include/net/irda/irlmp.h	Wed Dec 18 17:56:13 2002
@@ -132,6 +132,7 @@ struct lap_cb {
 
 	struct irlap_cb *irlap;   /* Instance of IrLAP layer */
 	hashbin_t *lsaps;         /* LSAP associated with this link */
+	struct lsap_cb *flow_next;	/* Next lsap to be polled for Tx */
 
 	__u8  caddr;  /* Connection address */
  	__u32 saddr;  /* Source device address */
@@ -235,6 +236,7 @@ void irlmp_connless_data_indication(stru
 
 void irlmp_status_request(void);
 void irlmp_status_indication(struct lap_cb *, LINK_STATUS link, LOCK_STATUS lock);
+void irlmp_flow_indication(struct lap_cb *self, LOCAL_FLOW flow);
 
 int  irlmp_slsap_inuse(__u8 slsap);
 __u8 irlmp_find_free_slsap(void);
@@ -252,7 +254,9 @@ extern struct irlmp_cb *irlmp;
 
 static inline hashbin_t *irlmp_get_cachelog(void) { return irlmp->cachelog; }
 
-static inline int irlmp_get_lap_tx_queue_len(struct lsap_cb *self)
+/* Check if LAP queue is full.
+ * Used by IrTTP for low control, see comments in irlap.h - Jean II */
+static inline int irlmp_lap_tx_queue_full(struct lsap_cb *self)
 {
 	if (self == NULL)
 		return 0;
@@ -261,7 +265,7 @@ static inline int irlmp_get_lap_tx_queue
 	if (self->lap->irlap == NULL)
 		return 0;
 
-	return IRLAP_GET_TX_QUEUE_LEN(self->lap->irlap);
+	return(IRLAP_GET_TX_QUEUE_LEN(self->lap->irlap) >= LAP_HIGH_THRESHOLD);
 }
 
 /* After doing a irlmp_dup(), this get one of the two socket back into
diff -u -p -r linux/net/irda/irlap_event.d6.c linux/net/irda/irlap_event.c
--- linux/net/irda/irlap_event.d6.c	Wed Dec 18 17:55:32 2002
+++ linux/net/irda/irlap_event.c	Wed Dec 18 17:56:13 2002
@@ -253,19 +253,45 @@ void irlap_do_event(struct irlap_cb *sel
 	case LAP_XMIT_P: /* FALLTHROUGH */
 	case LAP_XMIT_S:
 		/* 
+		 * We just received the pf bit and are at the beginning
+		 * of a new LAP transmit window.
 		 * Check if there are any queued data frames, and do not
 		 * try to disconnect link if we send any data frames, since
 		 * that will change the state away form XMIT
 		 */
+		IRDA_DEBUG(2, __FUNCTION__ "() : queue len = %d\n",
+			   skb_queue_len(&self->txq));
+
 		if (skb_queue_len(&self->txq)) {
 			/* Prevent race conditions with irlap_data_request() */
 			self->local_busy = TRUE;
 
+			/* Theory of operation.
+			 * We send frames up to when we fill the window or
+			 * reach line capacity. Those frames will queue up
+			 * in the device queue, and the driver will slowly
+			 * send them.
+			 * After each frame that we send, we poll the higher
+			 * layer for more data. It's the right time to do
+			 * that because the link layer need to perform the mtt
+			 * and then send the first frame, so we can afford
+			 * to send a bit of time in kernel space.
+			 * The explicit flow indication allow to minimise
+			 * buffers (== lower latency), to avoid higher layer
+			 * polling via timers (== less context switches) and
+			 * to implement a crude scheduler - Jean II */
+
 			/* Try to send away all queued data frames */
 			while ((skb = skb_dequeue(&self->txq)) != NULL) {
+				/* Send one frame */
 				ret = (*state[self->state])(self, SEND_I_CMD,
 							    skb, NULL);
 				kfree_skb(skb);
+
+				/* Poll the higher layers for one more frame */
+				irlmp_flow_indication(self->notify.instance,
+						      FLOW_START);
+
 				if (ret == -EPROTO)
 					break; /* Try again later! */
 			}
diff -u -p -r linux/net/irda/irlmp.d6.c linux/net/irda/irlmp.c
--- linux/net/irda/irlmp.d6.c	Wed Dec 18 17:55:46 2002
+++ linux/net/irda/irlmp.c	Wed Dec 18 17:56:13 2002
@@ -1220,6 +1220,72 @@ void irlmp_status_indication(struct lap_
 }
 
 /*
+ * Receive flow control indication from LAP.
+ * LAP want us to send it one more frame. We implement a simple round
+ * robin scheduler between the active sockets so that we get a bit of
+ * fairness. Note that the round robin is far from perfect, but it's
+ * better than nothing.
+ * We then poll the selected socket so that we can do synchronous
+ * refilling of IrLAP (which allow to minimise the number of buffers).
+ * Jean II
+ */
+void irlmp_flow_indication(struct lap_cb *self, LOCAL_FLOW flow)
+{
+	struct lsap_cb *next;
+	struct lsap_cb *curr;
+	int	lsap_todo;
+
+	ASSERT(self->magic == LMP_LAP_MAGIC, return;);
+	ASSERT(flow == FLOW_START, return;);
+
+	/* Get the number of lsap. That's the only safe way to know
+	 * that we have looped around... - Jean II */
+	lsap_todo = HASHBIN_GET_SIZE(self->lsaps);
+	IRDA_DEBUG(4, __FUNCTION__ "() : %d lsaps to scan\n", lsap_todo);
+
+	/* Poll lsap in order until the queue is full or until we
+	 * tried them all.
+	 * Most often, the current LSAP will have something to send,
+	 * so we will go through this loop only once. - Jean II */
+	while((lsap_todo--) &&
+	      (IRLAP_GET_TX_QUEUE_LEN(self->irlap) < LAP_HIGH_THRESHOLD)) {
+		/* Try to find the next lsap we should poll. */
+		next = self->flow_next;
+		if(next != NULL) {
+			/* Note that if there is only one LSAP on the LAP
+			 * (most common case), self->flow_next is always NULL,
+			 * so we always avoid this loop. - Jean II */
+			IRDA_DEBUG(4, __FUNCTION__ "() : searching my LSAP\n");
+
+			/* We look again in hashbins, because the lsap
+			 * might have gone away... - Jean II */
+			curr = (struct lsap_cb *) hashbin_get_first(self->lsaps);
+			while((curr != NULL ) && (curr != next))
+				curr = (struct lsap_cb *) hashbin_get_next(self->lsaps);
+		} else
+			curr = NULL;
+
+		/* If we have no lsap, restart from first one */
+		if(curr == NULL)
+			curr = (struct lsap_cb *) hashbin_get_first(self->lsaps);
+		/* Uh-oh... Paranoia */
+		if(curr == NULL)
+			break;
+
+		/* Next time, we will get the next one (or the first one) */
+		self->flow_next = (struct lsap_cb *) hashbin_get_next(self->lsaps);
+		IRDA_DEBUG(4, __FUNCTION__ "() : curr is %p, next was %p and is now %p, still %d to go - queue len = %d\n", curr, next, self->flow_next, lsap_todo, IRLAP_GET_TX_QUEUE_LEN(self->irlap));
+
+		/* Inform lsap user that it can send one more packet. */
+		if (curr->notify.flow_indication != NULL)
+			curr->notify.flow_indication(curr->notify.instance, 
+						     curr, flow);
+		else
+			IRDA_DEBUG(1, __FUNCTION__ "(), no handler\n");
+	}
+}
+
+/*
  * Function irlmp_hint_to_service (hint)
  *
  *    Returns a list of all servics contained in the given hint bits. This

^ permalink raw reply

* RE: [PATCH 2.5.52] Use __set_current_state() instead of current-> state = (take 1)
From: Perez-Gonzalez, Inaky @ 2002-12-19  2:40 UTC (permalink / raw)
  To: 'Robert Love'; +Cc: torvalds, linux-kernel


> > - any setting before a return should be barriered unless we 
> >   return to a place[s] known to be harmless
> 
> Not sure.

Well, I think it makes kind of sense. If we know we are
returning to some place where nothing bad could happen
with reordering ... well, so be it, don't use __set_...()
 
> > - any setting to TASK_RUNNING should be kind of safe
> 
> Yes, I agree.  It may race, but with what?

Hmmm ... I guess it could race, but it would not really
be that important [unless maybe certain constructs], as
the only setting it will go to would be [UN]INTERRUPTIBLE,
where it would be waken up afterwards, as it'd be out of the
rq, STOPPED, same thing, out of the rq, ZOMBIE or DEAD [gone].

I guess in this case, the only one I can come up with,
there would be an inconsistency between the actual state
of the task in task->state and the real one [or its position
in whatever rq or wq].

Could that have ugly consequences? I dunno ...

> > -		current->state = TASK_UNINTERRUPTIBLE;
> > +		__set_current_state(TASK_UNINTERRUPTIBLE);
> >  		spin_unlock_irq(&oldsig->siglock);
> > 
> >   Should be safe, as spin_unlock_irq() will do memory clobber
> >   on sti() [undependant from UP/SMP].
> 
> The memory clobber only acts as a compiler barrier and insures the
> compiler does not reorder the statements from the order in the C code.

while (1)
  printk ("Inaky, remember, clobber is a hint to gcc\n"); 

And that would now really work when CONFIG_X86_OOSTORE=1 is required
[after all, it is a write, so it'd need the equivalent of a wmb() or
xchg()]. 
Okay, changing that one too, just in case.


Inaky Perez-Gonzalez -- Not speaking for Intel - opinions are my own [or my
fault]



^ permalink raw reply

* [PATCH] [v850]  Add v850 support for `sys_restart_syscall'
From: Miles Bader @ 2002-12-19  2:33 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: linux-kernel

diff -ruN -X../cludes ../orig/linux-2.5.52-uc0/arch/v850/kernel/entry.S arch/v850/kernel/entry.S
--- ../orig/linux-2.5.52-uc0/arch/v850/kernel/entry.S	2002-11-28 10:24:54.000000000 +0900
+++ arch/v850/kernel/entry.S	2002-12-17 17:23:49.000000000 +0900
@@ -781,7 +781,7 @@
 	
 	.align 4
 C_DATA(sys_call_table):
-	.long CSYM(sys_ni_syscall)	// 0  -  old "setup()" system call
+	.long CSYM(sys_restart_syscall)	// 0
 	.long CSYM(sys_exit)
 	.long sys_fork_wrapper
 	.long CSYM(sys_read)
diff -ruN -X../cludes ../orig/linux-2.5.52-uc0/arch/v850/kernel/signal.c arch/v850/kernel/signal.c
--- ../orig/linux-2.5.52-uc0/arch/v850/kernel/signal.c	2002-11-28 10:24:54.000000000 +0900
+++ arch/v850/kernel/signal.c	2002-12-17 17:23:49.000000000 +0900
@@ -440,19 +440,23 @@
 	if (PT_REGS_SYSCALL (regs)) {
 		/* If so, check system call restarting.. */
 		switch (regs->gpr[GPR_RVAL]) {
-			case -ERESTARTNOHAND:
+		case -ERESTART_RESTARTBLOCK:
+			current_thread_info()->restart_block.fn =
+				do_no_restart_syscall;
+			/* fall through */
+		case -ERESTARTNOHAND:
+			regs->gpr[GPR_RVAL] = -EINTR;
+			break;
+
+		case -ERESTARTSYS:
+			if (!(ka->sa.sa_flags & SA_RESTART)) {
 				regs->gpr[GPR_RVAL] = -EINTR;
 				break;
-
-			case -ERESTARTSYS:
-				if (!(ka->sa.sa_flags & SA_RESTART)) {
-					regs->gpr[GPR_RVAL] = -EINTR;
-					break;
-				}
+			}
 			/* fallthrough */
-			case -ERESTARTNOINTR:
-				regs->gpr[12] = PT_REGS_SYSCALL (regs);
-				regs->pc -= 4; /* Size of `trap 0' insn.  */
+		case -ERESTARTNOINTR:
+			regs->gpr[12] = PT_REGS_SYSCALL (regs);
+			regs->pc -= 4; /* Size of `trap 0' insn.  */
 		}
 
 		PT_REGS_SET_SYSCALL (regs, 0);
@@ -511,14 +515,19 @@
 
 	/* Did we come from a system call? */
 	if (PT_REGS_SYSCALL (regs)) {
+		int rval = (int)regs->gpr[GPR_RVAL];
 		/* Restart the system call - no handlers present */
-		if (regs->gpr[GPR_RVAL] == (v850_reg_t)-ERESTARTNOHAND ||
-		    regs->gpr[GPR_RVAL] == (v850_reg_t)-ERESTARTSYS ||
-		    regs->gpr[GPR_RVAL] == (v850_reg_t)-ERESTARTNOINTR)
+		if (rval == -ERESTARTNOHAND
+		    || rval == -ERESTARTSYS
+		    || rval == -ERESTARTNOINTR)
 		{
 			regs->gpr[12] = PT_REGS_SYSCALL (regs);
 			regs->pc -= 4; /* Size of `trap 0' insn.  */
 		}
+		else if (rval == -ERESTART_RESTARTBLOCK) {
+			regs->gpr[12] = __NR_restart_syscall;
+			regs->pc -= 4; /* Size of `trap 0' insn.  */
+		}
 	}
 	return 0;
 }
diff -ruN -X../cludes ../orig/linux-2.5.52-uc0/include/asm-v850/current.h include/asm-v850/current.h
--- ../orig/linux-2.5.52-uc0/include/asm-v850/current.h	2002-11-05 11:25:31.000000000 +0900
+++ include/asm-v850/current.h	2002-12-17 17:23:49.000000000 +0900
@@ -14,8 +14,11 @@
 #ifndef __V850_CURRENT_H__
 #define __V850_CURRENT_H__
 
+#ifndef __ASSEMBLY__ /* <linux/thread_info.h> is not asm-safe.  */
+#include <linux/thread_info.h>
+#endif
+
 #include <asm/macrology.h>
-#include <asm/thread_info.h>
 
 
 /* Register used to hold the current task pointer while in the kernel.
diff -ruN -X../cludes ../orig/linux-2.5.52-uc0/include/asm-v850/processor.h include/asm-v850/processor.h
--- ../orig/linux-2.5.52-uc0/include/asm-v850/processor.h	2002-11-28 10:25:08.000000000 +0900
+++ include/asm-v850/processor.h	2002-12-17 17:23:49.000000000 +0900
@@ -15,9 +15,11 @@
 #define __V850_PROCESSOR_H__
 
 #include <linux/config.h>
+#ifndef __ASSEMBLY__ /* <linux/thread_info.h> is not asm-safe.  */
+#include <linux/thread_info.h>
+#endif
 
 #include <asm/ptrace.h>
-#include <asm/thread_info.h>
 #include <asm/entry.h>
 
 /* Some code expects `segment' stuff to be defined here.  */
diff -ruN -X../cludes ../orig/linux-2.5.52-uc0/include/asm-v850/thread_info.h include/asm-v850/thread_info.h
--- ../orig/linux-2.5.52-uc0/include/asm-v850/thread_info.h	2002-11-05 11:25:32.000000000 +0900
+++ include/asm-v850/thread_info.h	2002-12-17 17:23:49.000000000 +0900
@@ -31,15 +31,19 @@
 	unsigned long		flags;		/* low level flags */
 	int			cpu;		/* cpu we're on */
 	int			preempt_count;
+	struct restart_block	restart_block;
 };
 
-#define INIT_THREAD_INFO(tsk)			\
-{						\
-	.task =		&tsk,			\
-	.exec_domain =	&default_exec_domain,	\
-	.flags =	0,			\
-	.cpu =		0,			\
-	.preempt_count = 1			\
+#define INIT_THREAD_INFO(tsk)						      \
+{									      \
+	.task =		&tsk,						      \
+	.exec_domain =	&default_exec_domain,				      \
+	.flags =	0,						      \
+	.cpu =		0,						      \
+	.preempt_count = 1,						      \
+	.restart_block = {						      \
+		.fn = do_no_restart_syscall,				      \
+	},								      \
 }
 
 #define init_thread_info	(init_thread_union.thread_info)
@@ -67,8 +71,6 @@
 #define TI_FLAGS	8
 #define TI_CPU		12
 #define TI_PREEMPT	16
-#define TI_SOFTIRQ	20
-#define TI_HARDIRQ	24
 
 #define PREEMPT_ACTIVE		0x4000000
 
diff -ruN -X../cludes ../orig/linux-2.5.52-uc0/include/asm-v850/unistd.h include/asm-v850/unistd.h
--- ../orig/linux-2.5.52-uc0/include/asm-v850/unistd.h	2002-11-28 10:25:08.000000000 +0900
+++ include/asm-v850/unistd.h	2002-12-17 17:23:49.000000000 +0900
@@ -16,6 +16,7 @@
 
 #include <asm/clinkage.h>
 
+#define __NR_restart_syscall	  0
 #define __NR_exit		  1
 #define __NR_fork		  2
 #define __NR_read		  3

^ permalink raw reply

* [PATCH] [v850]  Add some v850 elf constants
From: Miles Bader @ 2002-12-19  2:34 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: linux-kernel

These are used for the new in-kernel module loader (actually not all the
relocation types are used right now, but are included for completeness).

Only the EM_CYGNUS_V850 macro, which is in a global namespace, is added
to <linux/elf.h>; the relocation types, which are private to the v850,
are added to <asm-v850/elf.h>.  [Perhaps some other archs can do a
similar split, to reduce the bloat in <linux/elf.h>]

diff -ruN -X../cludes ../orig/linux-2.5.52-uc0/include/linux/elf.h include/linux/elf.h
--- ../orig/linux-2.5.52-uc0/include/linux/elf.h	2002-12-17 16:31:27.000000000 +0900
+++ include/linux/elf.h	2002-12-17 17:23:49.000000000 +0900
@@ -92,6 +92,9 @@
  */
 #define EM_ALPHA	0x9026
 
+/* Bogus old v850 magic number, used by old tools.  */
+#define EM_CYGNUS_V850	0x9080
+
 /*
  * This is the old interim value for S/390 architecture
  */
diff -ruN -X../cludes ../orig/linux-2.5.52-uc0/include/asm-v850/elf.h include/asm-v850/elf.h
--- ../orig/linux-2.5.52-uc0/include/asm-v850/elf.h	2002-11-28 10:25:08.000000000 +0900
+++ include/asm-v850/elf.h	2002-12-17 17:23:49.000000000 +0900
@@ -22,6 +22,31 @@
 #define elf_check_arch(x)  \
   ((x)->e_machine == EM_V850 || (x)->e_machine == EM_CYGNUS_V850)
 
+
+/* v850 relocation types.  */
+#define R_V850_NONE		0
+#define R_V850_9_PCREL		1
+#define R_V850_22_PCREL		2
+#define R_V850_HI16_S		3
+#define R_V850_HI16		4
+#define R_V850_LO16		5
+#define R_V850_32		6
+#define R_V850_16		7
+#define R_V850_8		8
+#define R_V850_SDA_16_16_OFFSET	9	/* For ld.b, st.b, set1, clr1,
+					   not1, tst1, movea, movhi */
+#define R_V850_SDA_15_16_OFFSET	10	/* For ld.w, ld.h, ld.hu, st.w, st.h */
+#define R_V850_ZDA_16_16_OFFSET	11	/* For ld.b, st.b, set1, clr1,
+					   not1, tst1, movea, movhi */
+#define R_V850_ZDA_15_16_OFFSET	12	/* For ld.w, ld.h, ld.hu, st.w, st.h */
+#define R_V850_TDA_6_8_OFFSET	13	/* For sst.w, sld.w */
+#define R_V850_TDA_7_8_OFFSET	14	/* For sst.h, sld.h */
+#define R_V850_TDA_7_7_OFFSET	15	/* For sst.b, sld.b */
+#define R_V850_TDA_16_16_OFFSET	16	/* For set1, clr1, not1, tst1,
+					   movea, movhi */
+#define R_V850_NUM		17
+
+
 /*
  * These are used to set parameters in the core dumps.
  */

^ permalink raw reply

* RE: [PATCH][2.4]  generic cluster APIC support for systems with more than 8 CPUs
From: Pallipadi, Venkatesh @ 2002-12-19  2:35 UTC (permalink / raw)
  To: Martin J. Bligh, Linux Kernel
  Cc: John Stultz, Nakajima, Jun, jamesclv, Mallick, Asit K,
	Saxena, Sunil


The rules that I am trying to follow

					numaq		summit/			all other      
							other >8 CPU system	systems
------------------------------------------------------------------------------
clustered_apic_mode		CLUSTERED	CLUSTERED			NONE
configured_platform_type	NUMAQ		NONE				NONE
------------------------------------------------------------------------------
Note that in the patch, wherever I said NUMA, I actually meant NUMAQ. I think I lost
that Q, while I was trying to reduce the length of this variable 
(CONFIGURED_PLATFORM_NUMAQ) :). Sorry about all the resulting confusion. Doing a 
search and replace of NUMA by NUMAQ on my patch right now.

Noticeable changes here are
- summit using CLUSTERED in place of XAPIC(Physical destination).
- use "configured_platform_type" it basically separate out numaq specific stuff
  (like, waking up the CPUs through NMI), from the generic cluster apic support.

We are trying to use a common APIC destination mode for all systems with more
than 8 CPUs. This is by having the logical clusters of the CPUs. I am hoping that
this mode works fine on summit. Another option is to allow summit to continue using 
physical mode, if there is any binding reason to do so. But anyway NUMAQ specific stuff
has to be separated from cluster APIC stuff.

Rest of the comments inlined below..

> From: Martin J. Bligh [mailto:mbligh@aracnet.com]
> > -         define_bool CONFIG_X86_CLUSTERED_APIC y
> > +                 define_bool CONFIG_MULTIQUAD y
> 
> You seem to have lost turning on CONFIG_X86_NUMA.

I dont see CONFIG_X86_NUMA getting used anywhere in 2.4.21-pre1. Am I missing
something here??

> > +CONFIG_X86_APIC_CLUSTER=y
> >  # CONFIG_MULTIQUAD is not set
> >  CONFIG_HAVE_DEC_LOCK=y
> 
> Errrm ... on by default?

I was just trying to be little ambitious :). Will remove that now..

> > -	if(clustered_apic_mode == CLUSTERED_APIC_XAPIC)
> > -		id = 
> physical_to_logical_apicid(hard_smp_processor_id());
> > +	if(clustered_apic_mode)
> > +		id = cpu_2_logical_apicid[smp_processor_id()];
> 
> Don't use those arrays directly, use the macros.

OK. Will change it.

> And that was off before for NUMA-Q ... you seem to have turned it on.
> Unless you've inverted the meaning of clustered_apic_mode, which is
> going to confuse the hell out of everyone?

NO. This check is happening inside calculate_ldr() routine, and NUMAQ never comes
to calculate_ldr(), as (according to the comments), it is the BIOS that programs 
LDR in NUMAQ. So only thing we have to worry about in calculate_ldr() is 
non-NUMAQ systems.

> > -	if (clustered_apic_mode != CLUSTERED_APIC_NUMAQ) {
> > +	if (configured_platform_type != CONFIGURED_PLATFORM_NUMA) {
> 
> OK, what exactly are your switching rules here? Before:

I am trying to get the stuff which are _only_ specific to NUMAQ, under
"platform type" check. And the stuff specific to cluster APIC setup under 
"apic mode" check.
Can you please review the complete patch now. I am not sure whether my explaination 
was clear enough. Let me know if have any questions.

Thanks,
-Venkatesh 

^ permalink raw reply

* [PATCH] [v850]  Update v850 includes for slimmed-down sched.h
From: Miles Bader @ 2002-12-19  2:33 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: linux-kernel

Adds extra includes needed because sched.h doesn't include them anymore,
and removes includes of sched.h where they're not really necessary.

diff -ruN -X../cludes ../orig/linux-2.5.52-uc0/arch/v850/kernel/irq.c arch/v850/kernel/irq.c
--- ../orig/linux-2.5.52-uc0/arch/v850/kernel/irq.c	2002-11-28 10:24:54.000000000 +0900
+++ arch/v850/kernel/irq.c	2002-12-19 11:18:38.000000000 +0900
@@ -21,7 +21,6 @@
 #include <linux/slab.h>
 #include <linux/mm.h>
 #include <linux/random.h>
-#include <linux/sched.h>
 #include <linux/seq_file.h>
 
 #include <asm/system.h>
diff -ruN -X../cludes ../orig/linux-2.5.52-uc0/arch/v850/kernel/semaphore.c arch/v850/kernel/semaphore.c
--- ../orig/linux-2.5.52-uc0/arch/v850/kernel/semaphore.c	2002-11-05 11:25:22.000000000 +0900
+++ arch/v850/kernel/semaphore.c	2002-12-19 11:20:47.000000000 +0900
@@ -13,6 +13,7 @@
  * which was derived from the i386 version, linux/arch/i386/kernel/semaphore.c
  */
 
+#include <linux/errno.h>
 #include <linux/sched.h>
 
 #include <asm/semaphore.h>
diff -ruN -X../cludes ../orig/linux-2.5.52-uc0/arch/v850/kernel/setup.c arch/v850/kernel/setup.c
--- ../orig/linux-2.5.52-uc0/arch/v850/kernel/setup.c	2002-11-28 10:24:54.000000000 +0900
+++ arch/v850/kernel/setup.c	2002-12-19 11:19:21.000000000 +0900
@@ -11,7 +11,6 @@
  * Written by Miles Bader <miles@gnu.org>
  */
 
-#include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/bootmem.h>
 #include <linux/irq.h>
diff -ruN -X../cludes ../orig/linux-2.5.52-uc0/arch/v850/kernel/signal.c arch/v850/kernel/signal.c
--- ../orig/linux-2.5.52-uc0/arch/v850/kernel/signal.c	2002-11-28 10:24:54.000000000 +0900
+++ arch/v850/kernel/signal.c	2002-12-19 11:19:33.000000000 +0900
@@ -15,7 +15,6 @@
  * This file was derived from the sh version, arch/sh/kernel/signal.c
  */
 
-#include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/smp.h>
 #include <linux/smp_lock.h>
diff -ruN -X../cludes ../orig/linux-2.5.52-uc0/arch/v850/kernel/syscalls.c arch/v850/kernel/syscalls.c
--- ../orig/linux-2.5.52-uc0/arch/v850/kernel/syscalls.c	2002-11-05 11:25:22.000000000 +0900
+++ arch/v850/kernel/syscalls.c	2002-12-19 11:19:39.000000000 +0900
@@ -17,7 +17,6 @@
 
 #include <linux/config.h>
 #include <linux/errno.h>
-#include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/smp.h>
 #include <linux/smp_lock.h>
diff -ruN -X../cludes ../orig/linux-2.5.52-uc0/arch/v850/kernel/time.c arch/v850/kernel/time.c
--- ../orig/linux-2.5.52-uc0/arch/v850/kernel/time.c	2002-11-05 11:25:22.000000000 +0900
+++ arch/v850/kernel/time.c	2002-12-19 11:19:56.000000000 +0900
@@ -12,7 +12,6 @@
 
 #include <linux/config.h> /* CONFIG_HEARTBEAT */
 #include <linux/errno.h>
-#include <linux/sched.h>
 #include <linux/kernel.h>
 #include <linux/param.h>
 #include <linux/string.h>
diff -ruN -X../cludes ../orig/linux-2.5.52-uc0/include/asm-v850/mmu_context.h include/asm-v850/mmu_context.h
--- ../orig/linux-2.5.52-uc0/include/asm-v850/mmu_context.h	2002-11-05 11:25:32.000000000 +0900
+++ include/asm-v850/mmu_context.h	2002-12-19 11:11:03.000000000 +0900
@@ -1,8 +1,6 @@
 #ifndef __V850_MMU_CONTEXT_H__
 #define __V850_MMU_CONTEXT_H__
 
-#include <linux/sched.h>
-
 #define destroy_context(mm)		((void)0)
 #define init_new_context(tsk,mm)	0
 #define switch_mm(prev,next,tsk,cpu)	((void)0)
diff -ruN -X../cludes ../orig/linux-2.5.52-uc0/include/asm-v850/uaccess.h include/asm-v850/uaccess.h
--- ../orig/linux-2.5.52-uc0/include/asm-v850/uaccess.h	2002-11-05 11:25:32.000000000 +0900
+++ include/asm-v850/uaccess.h	2002-12-17 17:23:49.000000000 +0900
@@ -4,7 +4,9 @@
 /*
  * User space memory access functions
  */
-#include <linux/sched.h>
+
+#include <linux/errno.h>
+#include <linux/string.h>
 
 #include <asm/segment.h>
 #include <asm/machdep.h>

^ permalink raw reply

* [PATCH]  Make some symbol exports conditional on CONFIG_MMU
From: Miles Bader @ 2002-12-19  2:33 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: linux-kernel

A few symbols are only defined when CONFIG_MMU=y, but are exported
(by kernel/ksyms.c) unconditionally.  This patch makes them conditional.

diff -ruN -X../cludes ../orig/linux-2.5.52-uc0/kernel/ksyms.c kernel/ksyms.c
--- ../orig/linux-2.5.52-uc0/kernel/ksyms.c	2002-12-16 12:53:59.000000000 +0900
+++ kernel/ksyms.c	2002-12-17 17:23:49.000000000 +0900
@@ -327,7 +327,9 @@
 /* for stackable file systems (lofs, wrapfs, cryptfs, etc.) */
 EXPORT_SYMBOL(default_llseek);
 EXPORT_SYMBOL(dentry_open);
+#ifdef CONFIG_MMU
 EXPORT_SYMBOL(filemap_nopage);
+#endif
 EXPORT_SYMBOL(filemap_fdatawrite);
 EXPORT_SYMBOL(filemap_fdatawait);
 EXPORT_SYMBOL(lock_page);
@@ -523,7 +525,9 @@
 EXPORT_SYMBOL(single_release);
 
 /* Program loader interfaces */
+#ifdef CONFIG_MMU
 EXPORT_SYMBOL(setup_arg_pages);
+#endif
 EXPORT_SYMBOL(copy_strings_kernel);
 EXPORT_SYMBOL(do_execve);
 EXPORT_SYMBOL(flush_old_exec);

^ permalink raw reply

* Re: Re: [parisc-linux] rp2430 questions
From: Gavin Hubbard @ 2002-12-19  2:08 UTC (permalink / raw)
  To: grundler, "Grant Grundler"; +Cc: parisc-linux

> On Thu, Dec 19, 2002 at 01:51:18PM +1300, Gavin Hubbard wrote:
> > Hi
> > 
> > I'm installing a dual-boot rp2430 system for one of our developers
> > this weekend. Are there any parisc-linux issues I need to be aware of
> > with regards to the crippled firmware e.g. known installation problems
> > or gotchas?
> 
> Nope. You will want to upgrade the kernel ASAP though.
> Get the latest 2.4.19 kernel you can find.
> 
> > Also, if we do a firmware upgrade to rp2470 in two or three months time
> > will it require a complete rebuild or reinstallation of the linux OE to
> > support the unlocked hardware?
> 
> We don't have any rp2430's here to test such an upgrade.
> But I can't imagine any difference besides the additional (faster?) CPU
> (and more memory) getting recogized. Should your root disk get renamed,
> it's possible to recovery from that pretty easily - I've done it
> more than a few times.

Thanks Grant

The other difference is the PCI controller support - the rp2430 has two working PCI slots and two disabled slots which are enabled by the upgrade.

Since I don't actually know how the device disabling is done in hardware, I'm not convinced that parisc-linux will come up smoothly after I install the upgrade (I'm not worried about HP-UX - it will be fine). Can anyone shed light on this?

Regards,

Gavin

^ permalink raw reply

* Re: [Lse-tech] Re: 15000+ processes -- poor performance ?!
From: William Lee Irwin III @ 2002-12-19  2:05 UTC (permalink / raw)
  To: David Lang; +Cc: Robert Love, Till Immanuel Patzschke, lse-tech, linux-kernel
In-Reply-To: <Pine.LNX.4.44.0212181743350.7848-100000@dlang.diginsite.com>

On Wed, Dec 18, 2002 at 05:44:46PM -0800, David Lang wrote:
> In my case I will still be running thousands of processes, so I have to
> just teach everyone not to use top instead.
> David Lang

Well, a better solution would be a userspace free of /proc/ dependency.

Or actually fixing the kernel. proc_pid_readdir() wants an efficiently
indexable linear list, e.g. TAOCP's 6.2.3 "Linear List Representation".
At that point its expense is proportional to the buffer size and
"seeking" about the list as it is wont to do is O(lg(processes)).



Bill

^ permalink raw reply

* RE: [PATCH 2.5.52] Use __set_current_state() instead of current-> state = (take 1)
From: Robert Love @ 2002-12-19  2:04 UTC (permalink / raw)
  To: Perez-Gonzalez, Inaky; +Cc: torvalds, linux-kernel
In-Reply-To: <A46BBDB345A7D5118EC90002A5072C7806CACA2D@orsmsx116.jf.intel.com>

On Wed, 2002-12-18 at 20:53, Perez-Gonzalez, Inaky wrote:

> - any setting before a return should be barriered unless we 
>   return to a place[s] known to be harmless

Not sure.

> - any setting to TASK_RUNNING should be kind of safe

Yes, I agree.  It may race, but with what?

> - exec.c:de_thread(), 
> 
>  	while (atomic_read(&oldsig->count) > count) {
>  		oldsig->group_exit_task = current;
> -		current->state = TASK_UNINTERRUPTIBLE;
> +		__set_current_state(TASK_UNINTERRUPTIBLE);
>  		spin_unlock_irq(&oldsig->siglock);
> 
>   Should be safe, as spin_unlock_irq() will do memory clobber
>   on sti() [undependant from UP/SMP].

The memory clobber only acts as a compiler barrier and insures the
compiler does not reorder the statements from the order in the C code.

What we need is a memory barrier to ensure the processor does not
reorder statements.  In other words, the processor can completely
rearrange loads and stores as they are issued to it, as long as it does
not break obvious data dependencies.  On a weakly ordered processor,
sans memory barrier, there is no telling when and where a store will
actually reach memory.  This is regardless of the order of the C code or
anything else.

That said, I do not know if the above example is a problem or not.  On a
very quick glance, the only issue I saw is the one I pointed out
earlier, and you fixed it.

	Robert Love


^ permalink raw reply

* Re: 15000+ processes -- poor performance ?!
From: William Lee Irwin III @ 2002-12-19  2:01 UTC (permalink / raw)
  To: Alan Cox
  Cc: Perez-Gonzalez, Inaky, 'Till Immanuel Patzschke',
	lse-tech, Linux Kernel Mailing List
In-Reply-To: <1040265088.27221.7.camel@irongate.swansea.linux.org.uk>

On Thu, 2002-12-19 at 01:04, Perez-Gonzalez, Inaky wrote:
>> If it has it ... well, I have no idea - maybe Robert Love would know.

On Thu, Dec 19, 2002 at 02:31:28AM +0000, Alan Cox wrote:
> He's running the -aa kernel, which has all the right bits for this too.
> In fact in some ways for very large memory boxes its probably the better
> variant

In my experience the most critical issues running 16K processes are:
(1) the highmem footprint of the pte's is significant
(2) the lowmem footprint of pmd's

and most of the rest is in the noise. It's probably a bad idea to run
top(1) or perhaps even mount /proc/ at all until top itself,
proc_pid_readdir(), and the tasklist_lock are all fixed.

Pretty much all he needs to "stay alive" is highpte of some flavor or
another. Performance etc. is addressed somewhat more by 2.5.x than -aa,
at least in the context of not degrading with this kind of multitasking.
i.e. shpte and pidhash. I've been randomly shooting down do_each_thread()
and for_each_process() loops in -wli, which is why I recommended it.

Bill

^ permalink raw reply

* Re: 2.4.19, don't "hdparm -I /dev/hde" if hde is on a Asus A7V133  Promise ctrlr, or...
From: Mike Dresser @ 2002-12-19  2:02 UTC (permalink / raw)
  To: D.A.M. Revok; +Cc: linux-kernel
In-Reply-To: <200212181718.26407.marvin@synapse.net>

On Wed, 18 Dec 2002, D.A.M. Revok wrote:

> yes, they updated it to deal with the Thoroughbred, .. blockheads don't
> have the flash-util available on the site?

They have at least a few boards that don't need the flash util, you just
alt-f2 when it's booting, and it loads it off the floppy.  I've got an
ASUS P4B533 that i just flashed to a beta 1012, futilely searching for a
fix for the fact that my machine will not boot Win98 unless it is in
logged mode.  Safe mode works, but regular boot will not, only if you do
option 2 in the startup menu.  Had to hunt down a disk to recycle to use.

Speaking of floppies, old wisdom said to always flash off the floppy, then
it was always flash off the hd, and now it's back to flashing off the floppy?

I wonder what you do for floppyless computers.

Mike


^ permalink raw reply

* Re: Help in cross-compiler
From: ?? @ 2002-12-19  1:52 UTC (permalink / raw)
  To: Chien-Lung Wu, linux-mips
In-Reply-To: <A4E787A2467EF849B00585F14C9005590689B4@dprn03.deltartp.com>

hi, chienlung,
try this when prepareing header:

rm -rf $PREFIX/mips-linux/include
mkdir -p $PREFIX/mips-linux/include
rm -rf $PREFIX/mips-linux/include/linux
rm -rf $PREFIX/mips-linux/include/asm-mips
rm -rf $PREFIX/mips-linux/include/asm
cp -af ./linuxmips-2.4.x/include/linux $PREFIX/mips-linux/include
cp -af ./linuxmips-2.4.x/include/asm-mips $PREFIX/mips-linux/include
ln -sf $PREFIX/mips-linux/include/asm-mips $PREFIX/mips-linux/include/asm

(linuxmips-2.4.x is the source of your mips-linux kernel)
in your message, i see register "ax" which is a x86 register
 which means you are using x86 header when building compiler that will
generate mips code
this is of course incorrect

/usr/include/asm & /usr/include/linux normally linked to
/usr/src/linux/include/asm & /usr/src/linux/include/linux
and /usr/src/linux is normally linked to x86 kernel source on pc

best regards,

----- Original Message -----
From: "Chien-Lung Wu" <cwu@deltartp.com>
To: <linux-mips@linux-mips.org>
Cc: "Chien-Lung Wu" <cwu@deltartp.com>
Sent: Wednesday, December 18, 2002 11:57 PM
Subject: Help in cross-compiler


> Hi,
>
> I am working on the embedded linux system on bug endian mips (mips-linux).
> As I understand, I need to get the cross-compiler work on my linux-i686
host
> (redhat 7.2).
> Following the Bradly's "Building a modern MIPS cross-toolchain for linux",
>  I download following packages:
>
> binutils-2.11
> gcc-2.95
> glibc-2.2.5
> glibc-linuxthreads-2.2.5
>
> And following the procedue:
> 1. build the cross-binutils
> tar -xzf binutils-2.11.tar.gz
>
> mkdir mips-binutils-2.11
> cd mips-binutils-2.11
>
> ../binutils-2.11/configure --target=mips-linux \
> --prefix=/usr/toolchain-mips
>
> --libdir='${exec_prefix}'/mips-linux/i386-linux-lib
>
> make
> make install
> cd ..
>
> Everything is fine.
>
> 2. build the C cross-compiler
>
> tar -xzf gcc-2.95.tar.gz
> mkdir mips-gcc-2.95
> cd mips-gcc-2.95
>
> ../gcc-2.95/configure --target=mips-linux
> --prefix=/usr/toolchain-mips --enable-languages=c \
> --disable-shared --with-headers=/usr/include
>
>
> make
> make install
>   cd ..
>
> As thw warning, The --with-headers causes configure to make a copy of the
> headers at the specified location into
/usr/local/mipsel-linux/sys-includes
> and to run fixincludes on them. These headers are then used by xgcc during
> the cross-building of libgcc.a (which is part of building the static C
> compiler). This means that you'll need some MIPS host headers laying
around
> somewhere, including the linux and asm subdirectories from the Linux
kernel.
> Maybe you have them from your previous cross-compiler installation. If
not,
> there are various creative ways of obtaining them, including grabbing them
> from some MIPS distribution. There is also the dubious hack of using your
> hosts's headers (--with-headers=/usr/include) instead. The key word here
is
> "dubious"; you have been warned.
> Since I can not get "some MIPS host headers", I use the dubious hack.
> And it seems get the build of C cross-compiler work.
> 3. Cross-build glibc
> tar -xzf glibc.tar.gz
> cd glibc
> patch -i ../glibc-2.2.5-mips-build-gmon.diff
> tar -xzf ../glibc-linuxthreads.tar.gz
> cd ..
> mkdir mipsel-glibc
> cd mipsel-glibc
>
> CFLAGS="-O2 -g -finline-limit=10000" ../glibc/configure
> --host=i686-linux\
>   --enable-add-ons --prefix=/usr
>
> make
> make install install_root=/usr/local/mips-linux/glibc
> cd ..
>
> cp -a /usr/local/mips-linux/glibc/lib/*
> /usr/toolchain/mips-linux/lib/
> cp -a /usr/local/mips-linux/glibc/usr/include/*
> /usr/toolchain/mips-linux/include/
> cp -a /usr/local/mips-linux/glibc/usr/lib/*
> /usr/toolchain/mips-linux/lib/
>
> GROUP ( /usr/toolchain/mips-linux/lib/libc.so.6
>   /usr/toolchain/mipsel-linux/lib/libc_nonshared.a )
>
> It works fine!
>
> 4. Build the final C and C++ cross-compilers
> cd mipsel-gcc
> ../gcc/configure --target=mipsel-linux  prefic=/usr/toolchain
> --enable-languages=c,c++
> make
> make install
>
>
> However, I got the error_message:
>
> home/cross-compiler1/mips-gcc-2.95/gcc/xgcc
> -B/home/cross-compiler1/mips-gcc-2.95/gcc/
> -B/usr/toolchain1-mips/mips-linux/bin/ -c -g -O2 -fvtable-thunks
> -D_GNU_SOURCE
> -fno-implicit-templates -I../../../gcc-2.95/libstdc++
> -I../../../gcc-2.95/libstdc++/stl -I../libio
> -I../../../gcc-2.95/libstdc++/../libio -nostdinc++ -D_IO_MTSAFE_IO
> ../../../gcc-2.95/libstdc++/cmathi.cc
> In file included from
>
/usr/toolchain1-mips/lib/gcc-lib/mips-linux/2.95/../../../../mips-linux/sys-
> include/math.h:350,
>     from ../../../gcc-2.95/libstdc++/cmath:7,
>     from ../../../gcc-2.95/libstdc++/cmathi.cc:7:
>
>
/usr/toolchain1-mips/lib/gcc-lib/mips-linux/2.95/../../../../mips-linux/sys-
> include/bits/mathinline.h:
>       In function `double atan2(double, double)':
>
>
/usr/toolchain1-mips/lib/gcc-lib/mips-linux/2.95/../../../../mips-linux/sys-
> include/bits/mathinline.h:426:
>       unknown register name `st(1)' in `asm'
>
>
/usr/toolchain1-mips/lib/gcc-lib/mips-linux/2.95/../../../../mips-linux/sys-
> include/bits/mathinline.h:
>       In function `float atan2f(float, float)':
>
>
/usr/toolchain1-mips/lib/gcc-lib/mips-linux/2.95/../../../../mips-linux/sys-
> include/bits/mathinline.h:426:
>       unknown register name `st(1)' in `asm'
>
>
/usr/toolchain1-mips/lib/gcc-lib/mips-linux/2.95/../../../../mips-linux/sys-
> include/bits/mathinline.h:
>       In function `long double atan2l(long double, long double)':
>
>
/usr/toolchain1-mips/lib/gcc-lib/mips-linux/2.95/../../../../mips-linux/sys-
> include/bits/mathinline.h:426:
>       unknown register name `st(1)' in `asm'
>
>
/usr/toolchain1-mips/lib/gcc-lib/mips-linux/2.95/../../../../mips-linux/sys-
> include/bits/mathinline.h:
>       In function `long double __atan2l(long double, long double)':
>
>
/usr/toolchain1-mips/lib/gcc-lib/mips-linux/2.95/../../../../mips-linux/sys-
> include/bits/mathinline.h:427:
>       unknown register name `st(1)' in `asm'
>
>
/usr/toolchain1-mips/lib/gcc-lib/mips-linux/2.95/../../../../mips-linux/sys-
> include/bits/mathinline.h:
>       In function `double fmod(double, double)':
>
>
/usr/toolchain1-mips/lib/gcc-lib/mips-linux/2.95/../../../../mips-linux/sys-
> include/bits/mathinline.h:430:
>     unknown register name `ax' in `asm'
>
>
/usr/toolchain1-mips/lib/gcc-lib/mips-linux/2.95/../../../../mips-linux/sys-
> include/bits/mathinline.h:
>     In function `float fmodf(float, float)':
>
>
/usr/toolchain1-mips/lib/gcc-lib/mips-linux/2.95/../../../../mips-linux/sys-
> include/bits/mathinline.h:430:
>     unknown register name `ax' in `asm'
>
>
/usr/toolchain1-mips/lib/gcc-lib/mips-linux/2.95/../../../../mips-linux/sys-
> include/bits/mathinline.h:
>     In function `long double fmodl(long double, long double)':
>
>
/usr/toolchain1-mips/lib/gcc-lib/mips-linux/2.95/../../../../mips-linux/sys-
> include/bits/mathinline.h:430:
>     unknown register name `ax' in `asm'
>
>
/usr/toolchain1-mips/lib/gcc-lib/mips-linux/2.95/../../../../mips-linux/sys-
> include/bits/mathinline.h:
>     In function `double atan(double)':
>
>
/usr/toolchain1-mips/lib/gcc-lib/mips-linux/2.95/../../../../mips-linux/sys-
> include/bits/mathinline.h:467:
>     unknown register name `st(1)' in `asm'
>
>
/usr/toolchain1-mips/lib/gcc-lib/mips-linux/2.95/../../../../mips-linux/sys-
> include/bits/mathinline.h:
>     In function `float atanf(float)':
>
>
/usr/toolchain1-mips/lib/gcc-lib/mips-linux/2.95/../../../../mips-linux/sys-
> include/bits/mathinline.h:467:
>     unknown register name `st(1)' in `asm'
>
>
/usr/toolchain1-mips/lib/gcc-lib/mips-linux/2.95/../../../../mips-linux/sys-
> include/bits/mathinline.h:
>     In function `long double atanl(long double)':
>
>
/usr/toolchain1-mips/lib/gcc-lib/mips-linux/2.95/../../../../mips-linux/sys-
> include/bits/mathinline.h:467:
>     unknown register name `st(1)' in `asm'
>
>
/usr/toolchain1-mips/lib/gcc-lib/mips-linux/2.95/../../../../mips-linux/sys-
> include/bits/mathinline.h:
>     In function `double log1p(double)':
>
>
/usr/toolchain1-mips/lib/gcc-lib/mips-linux/2.95/../../../../mips-linux/sys-
> include/bits/mathinline.h:540:
>     unknown register name `st(1)' in `asm'
>
>
/usr/toolchain1-mips/lib/gcc-lib/mips-linux/2.95/../../../../mips-linux/sys-
> include/bits/mathinline.h:
>     In function `float log1pf(float)':
>
>
/usr/toolchain1-mips/lib/gcc-lib/mips-linux/2.95/../../../../mips-linux/sys-
> include/bits/mathinline.h:540:
>     unknown register name `st(1)' in `asm'
>
>
/usr/toolchain1-mips/lib/gcc-lib/mips-linux/2.95/../../../../mips-linux/sys-
> include/bits/mathinline.h:
>     In function `long double log1pl(long double)':
>
>
/usr/toolchain1-mips/lib/gcc-lib/mips-linux/2.95/../../../../mips-linux/sys-
> include/bits/mathinline.h:540:
>     unknown register name `st(1)' in `asm'
>
>
/usr/toolchain1-mips/lib/gcc-lib/mips-linux/2.95/../../../../mips-linux/sys-
> include/bits/mathinline.h:
>     In function `long int lrintf(float)':
>
>
/usr/toolchain1-mips/lib/gcc-lib/mips-linux/2.95/../../../../mips-linux/sys-
> include/bits/mathinline.h:611:
>     unknown register name `st' in `asm'
>
>
/usr/toolchain1-mips/lib/gcc-lib/mips-linux/2.95/../../../../mips-linux/sys-
> include/bits/mathinline.h:
>     In function `long int lrint(double)':
>
>
/usr/toolchain1-mips/lib/gcc-lib/mips-linux/2.95/../../../../mips-linux/sys-
> include/bits/mathinline.h:616:
>     unknown register name `st' in `asm'
>
>
/usr/toolchain1-mips/lib/gcc-lib/mips-linux/2.95/../../../../mips-linux/sys-
> include/bits/mathinline.h:
>     In function `long int lrintl(long double)':
>
>
/usr/toolchain1-mips/lib/gcc-lib/mips-linux/2.95/../../../../mips-linux/sys-
> include/bits/mathinline.h:621:
>     unknown register name `st' in `asm'
>
>
/usr/toolchain1-mips/lib/gcc-lib/mips-linux/2.95/../../../../mips-linux/sys-
> include/bits/mathinline.h:
>     In function `long long int llrintf(float)':
>
>
/usr/toolchain1-mips/lib/gcc-lib/mips-linux/2.95/../../../../mips-linux/sys-
> include/bits/mathinline.h:634:
>     unknown register name `st' in `asm'
>
>
/usr/toolchain1-mips/lib/gcc-lib/mips-linux/2.95/../../../../mips-linux/sys-
> include/bits/mathinline.h:
>     In function `long long int llrint(double)':
>
>
/usr/toolchain1-mips/lib/gcc-lib/mips-linux/2.95/../../../../mips-linux/sys-
> include/bits/mathinline.h:639:
>     unknown register name `st' in `asm'
>
>
/usr/toolchain1-mips/lib/gcc-lib/mips-linux/2.95/../../../../mips-linux/sys-
> include/bits/mathinline.h:
>     In function `long long int llrintl(long double)':
>
>
/usr/toolchain1-mips/lib/gcc-lib/mips-linux/2.95/../../../../mips-linux/sys-
> include/bits/mathinline.h:644:
>     unknown register name `st' in `asm'
>     make[1]: *** [cmathi.o] Error 1
>     make[1]: Leaving directory
>     `/home/cross-compiler1/mips-gcc-2.95/mips-linux/libstdc++'
>     make: *** [all-target-libstdc++] Error 2
>
> Does any have any idea to fix this error?
> When I build the C cross-compiler, I use the "dubious hack"
> --with-headers=/usr/include copy the "MIPS host header files". Are there
any
> other ways to copy the MIPS-host headers?
> Thanks for your help.
>
> Chien-Lung
>
>
>
>
>

^ permalink raw reply

* Re: Help in cross-compiler
From: ?? @ 2002-12-19  1:52 UTC (permalink / raw)
  To: Chien-Lung Wu, linux-mips; +Cc: Chien-Lung Wu
In-Reply-To: <A4E787A2467EF849B00585F14C9005590689B4@dprn03.deltartp.com>

hi, chienlung,
try this when prepareing header:

rm -rf $PREFIX/mips-linux/include
mkdir -p $PREFIX/mips-linux/include
rm -rf $PREFIX/mips-linux/include/linux
rm -rf $PREFIX/mips-linux/include/asm-mips
rm -rf $PREFIX/mips-linux/include/asm
cp -af ./linuxmips-2.4.x/include/linux $PREFIX/mips-linux/include
cp -af ./linuxmips-2.4.x/include/asm-mips $PREFIX/mips-linux/include
ln -sf $PREFIX/mips-linux/include/asm-mips $PREFIX/mips-linux/include/asm

(linuxmips-2.4.x is the source of your mips-linux kernel)
in your message, i see register "ax" which is a x86 register
 which means you are using x86 header when building compiler that will
generate mips code
this is of course incorrect

/usr/include/asm & /usr/include/linux normally linked to
/usr/src/linux/include/asm & /usr/src/linux/include/linux
and /usr/src/linux is normally linked to x86 kernel source on pc

best regards,

----- Original Message -----
From: "Chien-Lung Wu" <cwu@deltartp.com>
To: <linux-mips@linux-mips.org>
Cc: "Chien-Lung Wu" <cwu@deltartp.com>
Sent: Wednesday, December 18, 2002 11:57 PM
Subject: Help in cross-compiler


> Hi,
>
> I am working on the embedded linux system on bug endian mips (mips-linux).
> As I understand, I need to get the cross-compiler work on my linux-i686
host
> (redhat 7.2).
> Following the Bradly's "Building a modern MIPS cross-toolchain for linux",
>  I download following packages:
>
> binutils-2.11
> gcc-2.95
> glibc-2.2.5
> glibc-linuxthreads-2.2.5
>
> And following the procedue:
> 1. build the cross-binutils
> tar -xzf binutils-2.11.tar.gz
>
> mkdir mips-binutils-2.11
> cd mips-binutils-2.11
>
> ../binutils-2.11/configure --target=mips-linux \
> --prefix=/usr/toolchain-mips
>
> --libdir='${exec_prefix}'/mips-linux/i386-linux-lib
>
> make
> make install
> cd ..
>
> Everything is fine.
>
> 2. build the C cross-compiler
>
> tar -xzf gcc-2.95.tar.gz
> mkdir mips-gcc-2.95
> cd mips-gcc-2.95
>
> ../gcc-2.95/configure --target=mips-linux
> --prefix=/usr/toolchain-mips --enable-languages=c \
> --disable-shared --with-headers=/usr/include
>
>
> make
> make install
>   cd ..
>
> As thw warning, The --with-headers causes configure to make a copy of the
> headers at the specified location into
/usr/local/mipsel-linux/sys-includes
> and to run fixincludes on them. These headers are then used by xgcc during
> the cross-building of libgcc.a (which is part of building the static C
> compiler). This means that you'll need some MIPS host headers laying
around
> somewhere, including the linux and asm subdirectories from the Linux
kernel.
> Maybe you have them from your previous cross-compiler installation. If
not,
> there are various creative ways of obtaining them, including grabbing them
> from some MIPS distribution. There is also the dubious hack of using your
> hosts's headers (--with-headers=/usr/include) instead. The key word here
is
> "dubious"; you have been warned.
> Since I can not get "some MIPS host headers", I use the dubious hack.
> And it seems get the build of C cross-compiler work.
> 3. Cross-build glibc
> tar -xzf glibc.tar.gz
> cd glibc
> patch -i ../glibc-2.2.5-mips-build-gmon.diff
> tar -xzf ../glibc-linuxthreads.tar.gz
> cd ..
> mkdir mipsel-glibc
> cd mipsel-glibc
>
> CFLAGS="-O2 -g -finline-limit=10000" ../glibc/configure
> --host=i686-linux\
>   --enable-add-ons --prefix=/usr
>
> make
> make install install_root=/usr/local/mips-linux/glibc
> cd ..
>
> cp -a /usr/local/mips-linux/glibc/lib/*
> /usr/toolchain/mips-linux/lib/
> cp -a /usr/local/mips-linux/glibc/usr/include/*
> /usr/toolchain/mips-linux/include/
> cp -a /usr/local/mips-linux/glibc/usr/lib/*
> /usr/toolchain/mips-linux/lib/
>
> GROUP ( /usr/toolchain/mips-linux/lib/libc.so.6
>   /usr/toolchain/mipsel-linux/lib/libc_nonshared.a )
>
> It works fine!
>
> 4. Build the final C and C++ cross-compilers
> cd mipsel-gcc
> ../gcc/configure --target=mipsel-linux  prefic=/usr/toolchain
> --enable-languages=c,c++
> make
> make install
>
>
> However, I got the error_message:
>
> home/cross-compiler1/mips-gcc-2.95/gcc/xgcc
> -B/home/cross-compiler1/mips-gcc-2.95/gcc/
> -B/usr/toolchain1-mips/mips-linux/bin/ -c -g -O2 -fvtable-thunks
> -D_GNU_SOURCE
> -fno-implicit-templates -I../../../gcc-2.95/libstdc++
> -I../../../gcc-2.95/libstdc++/stl -I../libio
> -I../../../gcc-2.95/libstdc++/../libio -nostdinc++ -D_IO_MTSAFE_IO
> ../../../gcc-2.95/libstdc++/cmathi.cc
> In file included from
>
/usr/toolchain1-mips/lib/gcc-lib/mips-linux/2.95/../../../../mips-linux/sys-
> include/math.h:350,
>     from ../../../gcc-2.95/libstdc++/cmath:7,
>     from ../../../gcc-2.95/libstdc++/cmathi.cc:7:
>
>
/usr/toolchain1-mips/lib/gcc-lib/mips-linux/2.95/../../../../mips-linux/sys-
> include/bits/mathinline.h:
>       In function `double atan2(double, double)':
>
>
/usr/toolchain1-mips/lib/gcc-lib/mips-linux/2.95/../../../../mips-linux/sys-
> include/bits/mathinline.h:426:
>       unknown register name `st(1)' in `asm'
>
>
/usr/toolchain1-mips/lib/gcc-lib/mips-linux/2.95/../../../../mips-linux/sys-
> include/bits/mathinline.h:
>       In function `float atan2f(float, float)':
>
>
/usr/toolchain1-mips/lib/gcc-lib/mips-linux/2.95/../../../../mips-linux/sys-
> include/bits/mathinline.h:426:
>       unknown register name `st(1)' in `asm'
>
>
/usr/toolchain1-mips/lib/gcc-lib/mips-linux/2.95/../../../../mips-linux/sys-
> include/bits/mathinline.h:
>       In function `long double atan2l(long double, long double)':
>
>
/usr/toolchain1-mips/lib/gcc-lib/mips-linux/2.95/../../../../mips-linux/sys-
> include/bits/mathinline.h:426:
>       unknown register name `st(1)' in `asm'
>
>
/usr/toolchain1-mips/lib/gcc-lib/mips-linux/2.95/../../../../mips-linux/sys-
> include/bits/mathinline.h:
>       In function `long double __atan2l(long double, long double)':
>
>
/usr/toolchain1-mips/lib/gcc-lib/mips-linux/2.95/../../../../mips-linux/sys-
> include/bits/mathinline.h:427:
>       unknown register name `st(1)' in `asm'
>
>
/usr/toolchain1-mips/lib/gcc-lib/mips-linux/2.95/../../../../mips-linux/sys-
> include/bits/mathinline.h:
>       In function `double fmod(double, double)':
>
>
/usr/toolchain1-mips/lib/gcc-lib/mips-linux/2.95/../../../../mips-linux/sys-
> include/bits/mathinline.h:430:
>     unknown register name `ax' in `asm'
>
>
/usr/toolchain1-mips/lib/gcc-lib/mips-linux/2.95/../../../../mips-linux/sys-
> include/bits/mathinline.h:
>     In function `float fmodf(float, float)':
>
>
/usr/toolchain1-mips/lib/gcc-lib/mips-linux/2.95/../../../../mips-linux/sys-
> include/bits/mathinline.h:430:
>     unknown register name `ax' in `asm'
>
>
/usr/toolchain1-mips/lib/gcc-lib/mips-linux/2.95/../../../../mips-linux/sys-
> include/bits/mathinline.h:
>     In function `long double fmodl(long double, long double)':
>
>
/usr/toolchain1-mips/lib/gcc-lib/mips-linux/2.95/../../../../mips-linux/sys-
> include/bits/mathinline.h:430:
>     unknown register name `ax' in `asm'
>
>
/usr/toolchain1-mips/lib/gcc-lib/mips-linux/2.95/../../../../mips-linux/sys-
> include/bits/mathinline.h:
>     In function `double atan(double)':
>
>
/usr/toolchain1-mips/lib/gcc-lib/mips-linux/2.95/../../../../mips-linux/sys-
> include/bits/mathinline.h:467:
>     unknown register name `st(1)' in `asm'
>
>
/usr/toolchain1-mips/lib/gcc-lib/mips-linux/2.95/../../../../mips-linux/sys-
> include/bits/mathinline.h:
>     In function `float atanf(float)':
>
>
/usr/toolchain1-mips/lib/gcc-lib/mips-linux/2.95/../../../../mips-linux/sys-
> include/bits/mathinline.h:467:
>     unknown register name `st(1)' in `asm'
>
>
/usr/toolchain1-mips/lib/gcc-lib/mips-linux/2.95/../../../../mips-linux/sys-
> include/bits/mathinline.h:
>     In function `long double atanl(long double)':
>
>
/usr/toolchain1-mips/lib/gcc-lib/mips-linux/2.95/../../../../mips-linux/sys-
> include/bits/mathinline.h:467:
>     unknown register name `st(1)' in `asm'
>
>
/usr/toolchain1-mips/lib/gcc-lib/mips-linux/2.95/../../../../mips-linux/sys-
> include/bits/mathinline.h:
>     In function `double log1p(double)':
>
>
/usr/toolchain1-mips/lib/gcc-lib/mips-linux/2.95/../../../../mips-linux/sys-
> include/bits/mathinline.h:540:
>     unknown register name `st(1)' in `asm'
>
>
/usr/toolchain1-mips/lib/gcc-lib/mips-linux/2.95/../../../../mips-linux/sys-
> include/bits/mathinline.h:
>     In function `float log1pf(float)':
>
>
/usr/toolchain1-mips/lib/gcc-lib/mips-linux/2.95/../../../../mips-linux/sys-
> include/bits/mathinline.h:540:
>     unknown register name `st(1)' in `asm'
>
>
/usr/toolchain1-mips/lib/gcc-lib/mips-linux/2.95/../../../../mips-linux/sys-
> include/bits/mathinline.h:
>     In function `long double log1pl(long double)':
>
>
/usr/toolchain1-mips/lib/gcc-lib/mips-linux/2.95/../../../../mips-linux/sys-
> include/bits/mathinline.h:540:
>     unknown register name `st(1)' in `asm'
>
>
/usr/toolchain1-mips/lib/gcc-lib/mips-linux/2.95/../../../../mips-linux/sys-
> include/bits/mathinline.h:
>     In function `long int lrintf(float)':
>
>
/usr/toolchain1-mips/lib/gcc-lib/mips-linux/2.95/../../../../mips-linux/sys-
> include/bits/mathinline.h:611:
>     unknown register name `st' in `asm'
>
>
/usr/toolchain1-mips/lib/gcc-lib/mips-linux/2.95/../../../../mips-linux/sys-
> include/bits/mathinline.h:
>     In function `long int lrint(double)':
>
>
/usr/toolchain1-mips/lib/gcc-lib/mips-linux/2.95/../../../../mips-linux/sys-
> include/bits/mathinline.h:616:
>     unknown register name `st' in `asm'
>
>
/usr/toolchain1-mips/lib/gcc-lib/mips-linux/2.95/../../../../mips-linux/sys-
> include/bits/mathinline.h:
>     In function `long int lrintl(long double)':
>
>
/usr/toolchain1-mips/lib/gcc-lib/mips-linux/2.95/../../../../mips-linux/sys-
> include/bits/mathinline.h:621:
>     unknown register name `st' in `asm'
>
>
/usr/toolchain1-mips/lib/gcc-lib/mips-linux/2.95/../../../../mips-linux/sys-
> include/bits/mathinline.h:
>     In function `long long int llrintf(float)':
>
>
/usr/toolchain1-mips/lib/gcc-lib/mips-linux/2.95/../../../../mips-linux/sys-
> include/bits/mathinline.h:634:
>     unknown register name `st' in `asm'
>
>
/usr/toolchain1-mips/lib/gcc-lib/mips-linux/2.95/../../../../mips-linux/sys-
> include/bits/mathinline.h:
>     In function `long long int llrint(double)':
>
>
/usr/toolchain1-mips/lib/gcc-lib/mips-linux/2.95/../../../../mips-linux/sys-
> include/bits/mathinline.h:639:
>     unknown register name `st' in `asm'
>
>
/usr/toolchain1-mips/lib/gcc-lib/mips-linux/2.95/../../../../mips-linux/sys-
> include/bits/mathinline.h:
>     In function `long long int llrintl(long double)':
>
>
/usr/toolchain1-mips/lib/gcc-lib/mips-linux/2.95/../../../../mips-linux/sys-
> include/bits/mathinline.h:644:
>     unknown register name `st' in `asm'
>     make[1]: *** [cmathi.o] Error 1
>     make[1]: Leaving directory
>     `/home/cross-compiler1/mips-gcc-2.95/mips-linux/libstdc++'
>     make: *** [all-target-libstdc++] Error 2
>
> Does any have any idea to fix this error?
> When I build the C cross-compiler, I use the "dubious hack"
> --with-headers=/usr/include copy the "MIPS host header files". Are there
any
> other ways to copy the MIPS-host headers?
> Thanks for your help.
>
> Chien-Lung
>
>
>
>
>

^ permalink raw reply

* RE: 15000+ processes -- poor performance ?!
From: Rik van Riel @ 2002-12-19  1:58 UTC (permalink / raw)
  To: Alan Cox
  Cc: Perez-Gonzalez, Inaky, 'Till Immanuel Patzschke',
	lse-tech, Linux Kernel Mailing List
In-Reply-To: <1040265088.27221.7.camel@irongate.swansea.linux.org.uk>

On Thu, 19 Dec 2002, Alan Cox wrote:

> He's running the -aa kernel, which has all the right bits for this too.
> In fact in some ways for very large memory boxes its probably the better
> variant

If you're willing to merge a patch to take -ac up to rmap15b
I'll integrate some large memory stuff into my tree for 15c
and 2.4-ac should be able to handle large boxes too within a
month or so.

(keeping the speed of merging slow, deliberately)

regards,

Rik
-- 
Bravely reimplemented by the knights who say "NIH".
http://www.surriel.com/		http://guru.conectiva.com/
Current spamtrap:  <a href=mailto:"october@surriel.com">october@surriel.com</a>

^ permalink raw reply

* Re: 15000+ processes -- poor performance ?!
From: David Lang @ 2002-12-19  1:44 UTC (permalink / raw)
  To: Robert Love
  Cc: William Lee Irwin III, Till Immanuel Patzschke, lse-tech,
	linux-kernel
In-Reply-To: <1040262178.855.106.camel@phantasy>

In my case I will still be running thousands of processes, so I have to
just teach everyone not to use top instead.

David Lang

On 18 Dec 2002, Robert Love wrote:

> Date: 18 Dec 2002 20:42:58 -0500
> From: Robert Love <rml@tech9.net>
> To: David Lang <dlang@diginsite.com>
> Cc: William Lee Irwin III <wli@holomorphy.com>,
>      Till Immanuel Patzschke <tip@inw.de>,
>      lse-tech <lse-tech@lists.sourceforge.net>,
>      "linux-kernel@vger.kernel.org" <linux-kernel@vger.kernel.org>
> Subject: Re: 15000+ processes -- poor performance ?!
>
> On Wed, 2002-12-18 at 20:20, David Lang wrote:
> > Ok, I wasn't sure of the cause, but I've seen this as far back as 2.2 I
> > had a machine trying to run 2000 processes under 2.2 and 2.4.0 (after
> > upping the 2.2 kernel limit) and top would cost me ~40% throughput on the
> > machine (while claiming it was useing ~5% of the CPU)
>
> Yah a lot of it is like William is saying... you just do not want to
> read multiple files for each process in /proc when you have a kajillion
> processes, and that is what top does.  Over and over.
>
> Work has gone into 2.5 to make this a lot better.. If you use threads
> with NPTL in 2.5, a lot of this is resolved, since the sub-threads will
> not show up in as /proc/#/ entries.
>
> 	Robert Love
>

^ permalink raw reply

* [PATCH 2.5.52] Use __set_current_state() instead of current->state = (take 2)
From: Inaky Perez-Gonzalez @ 2002-12-19  1:49 UTC (permalink / raw)
  To: linux-kernel, rml, torvalds



Hi all

In fs/*.c, many functions manually set the task state directly
accessing current->state, or with a macro, kind of
inconsistently. This patch changes all of them to use
[__]set_current_state().

Changelog:

- Added feedback from Robert Love regarding usage of
  __set_current_thread() vs. set_current_thread() to avoid race
  conditions related to memory flush. 

- Use cond_resched() in namei.c:do_follow_link().

Take 1:

- Ported forward to 2.5.52

diff -u fs/dquot.c:1.1.1.4 fs/dquot.c:1.1.1.1.6.2
--- fs/dquot.c:1.1.1.4	Wed Dec 11 11:13:35 2002
+++ fs/dquot.c	Wed Dec 18 13:20:24 2002
@@ -264,7 +264,7 @@
 		goto repeat;
 	}
 	remove_wait_queue(&dquot->dq_wait_lock, &wait);
-	current->state = TASK_RUNNING;
+	__set_current_state(TASK_RUNNING);
 }
 
 static inline void wait_on_dquot(struct dquot *dquot)
@@ -298,7 +298,7 @@
 		goto repeat;
 	}
 	remove_wait_queue(&dquot->dq_wait_free, &wait);
-	current->state = TASK_RUNNING;
+	__set_current_state(TASK_RUNNING);
 }
 
 /* Wait for all duplicated dquot references to be dropped */
@@ -314,7 +314,7 @@
 		goto repeat;
 	}
 	remove_wait_queue(&dquot->dq_wait_free, &wait);
-	current->state = TASK_RUNNING;
+	__set_current_state(TASK_RUNNING);
 }
 
 static int read_dqblk(struct dquot *dquot)
diff -u fs/exec.c:1.1.1.8 fs/exec.c:1.1.1.1.6.2
--- fs/exec.c:1.1.1.8	Mon Dec 16 18:44:31 2002
+++ fs/exec.c	Wed Dec 18 13:20:24 2002
@@ -587,7 +587,7 @@
 		count = 1;
 	while (atomic_read(&oldsig->count) > count) {
 		oldsig->group_exit_task = current;
-		current->state = TASK_UNINTERRUPTIBLE;
+		__set_current_state(TASK_UNINTERRUPTIBLE);
 		spin_unlock_irq(&oldsig->siglock);
 		schedule();
 		spin_lock_irq(&oldsig->siglock);
diff -u fs/inode.c:1.1.1.6 fs/inode.c:1.1.1.1.6.2
--- fs/inode.c:1.1.1.6	Mon Dec 16 18:44:31 2002
+++ fs/inode.c	Wed Dec 18 13:20:24 2002
@@ -1195,7 +1195,7 @@
 		goto repeat;
 	}
 	remove_wait_queue(wq, &wait);
-	current->state = TASK_RUNNING;
+	__set_current_state(TASK_RUNNING);
 }
 
 void wake_up_inode(struct inode *inode)
diff -u fs/locks.c:1.1.1.6 fs/locks.c:1.1.1.1.6.3
--- fs/locks.c:1.1.1.6	Wed Dec 11 11:13:35 2002
+++ fs/locks.c	Wed Dec 18 17:42:37 2002
@@ -571,7 +571,7 @@
 	int result = 0;
 	DECLARE_WAITQUEUE(wait, current);
 
-	current->state = TASK_INTERRUPTIBLE;
+	set_current_state (TASK_INTERRUPTIBLE);
 	add_wait_queue(fl_wait, &wait);
 	if (timeout == 0)
 		schedule();
@@ -580,7 +580,7 @@
 	if (signal_pending(current))
 		result = -ERESTARTSYS;
 	remove_wait_queue(fl_wait, &wait);
-	current->state = TASK_RUNNING;
+	__set_current_state (TASK_RUNNING);
 	return result;
 }
 
diff -u fs/namei.c:1.1.1.6 fs/namei.c:1.1.1.1.6.3
--- fs/namei.c:1.1.1.6	Wed Dec 11 11:13:35 2002
+++ fs/namei.c	Wed Dec 18 17:42:49 2002
@@ -409,10 +409,7 @@
 		goto loop;
 	if (current->total_link_count >= 40)
 		goto loop;
-	if (need_resched()) {
-		current->state = TASK_RUNNING;
-		schedule();
-	}
+	cond_resched();
 	err = security_inode_follow_link(dentry, nd);
 	if (err)
 		goto loop;
diff -u fs/select.c:1.1.1.3 fs/select.c:1.1.1.1.6.2
--- fs/select.c:1.1.1.3	Wed Dec 11 11:10:14 2002
+++ fs/select.c	Wed Dec 18 13:20:24 2002
@@ -235,7 +235,7 @@
 		}
 		__timeout = schedule_timeout(__timeout);
 	}
-	current->state = TASK_RUNNING;
+	__set_current_state (TASK_RUNNING);
 
 	poll_freewait(&table);
 
@@ -417,7 +417,7 @@
 			break;
 		timeout = schedule_timeout(timeout);
 	}
-	current->state = TASK_RUNNING;
+	__set_current_state (TASK_RUNNING);
 	return count;
 }
 


-- 

Inaky Perez-Gonzalez -- Not speaking for Intel - opinions are my own [or my fault]

^ permalink raw reply

* RE: [PATCH 2.5.52] Use __set_current_state() instead of current-> state = (take 1)
From: Perez-Gonzalez, Inaky @ 2002-12-19  1:53 UTC (permalink / raw)
  To: 'Robert Love', 'torvalds@transmeta.com'; +Cc: linux-kernel


> > Agreed; however, I also don't want to introduce unnecessary
> > bloat, so I need to understand first what cases need it - it
> > is kind of hard for me. Care to let me know some gotchas?
> 
> set_current_state() includes a write barrier to ensure the setting of
> the state is flushed before any further instructions.  This is to
> provide a memory barrier for weak-ordering processors that 
> can and will rearrange the writes.

It is what I was expecting, given xchg() being in the equation;
then it is reduced to a problem of guessing what can be the 
delay for the flushing of the write ... beautiful ...

So, in that scenario, it means that:

- any setting before a return should be barriered unless we 
  return to a place[s] known to be harmless

- any setting to TASK_RUNNING should be kind of safe

- exec.c:de_thread(), 

 	while (atomic_read(&oldsig->count) > count) {
 		oldsig->group_exit_task = current;
-		current->state = TASK_UNINTERRUPTIBLE;
+		__set_current_state(TASK_UNINTERRUPTIBLE);
 		spin_unlock_irq(&oldsig->siglock);

  Should be safe, as spin_unlock_irq() will do memory clobber
  on sti() [undependant from UP/SMP].

- namei.c:do_follow_link()


 	if (current->total_link_count >= 40)
 		goto loop;
 	if (need_resched()) {
-		current->state = TASK_RUNNING;
+		__set_current_state(TASK_RUNNING);
 		schedule();
 	}
 	err = security_inode_follow_link(dentry, nd);

  There is a function for it, cond_resched().

So, sending an updated patch right now

> Not all processors like those made by your employer are 
> strongly-ordered :)

You'd be surprised how little about those gory details I do know :]

Inaky Perez-Gonzalez -- Not speaking for Intel - opinions are my own [or my
fault]


^ permalink raw reply

* RE: 15000+ processes -- poor performance ?!
From: Alan Cox @ 2002-12-19  2:31 UTC (permalink / raw)
  To: Perez-Gonzalez, Inaky
  Cc: 'Till Immanuel Patzschke', lse-tech,
	Linux Kernel Mailing List
In-Reply-To: <A46BBDB345A7D5118EC90002A5072C7806CACA2C@orsmsx116.jf.intel.com>

On Thu, 2002-12-19 at 01:04, Perez-Gonzalez, Inaky wrote:
> 
> > 
> > forgot the kernel version (2.4.20aa1)...
> 
> You need the O(1) scheduler; not sure if aa has it or not; if not, lots of
> processes will suck your machine. I think -ac has the O(1) scheduler, or try
> 2.5. The old scheduler is pretty cool but not as scalable as the new one.
> 
> If it has it ... well, I have no idea - maybe Robert Love would know.

He's running the -aa kernel, which has all the right bits for this too.
In fact in some ways for very large memory boxes its probably the better
variant


^ permalink raw reply


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.