Index: linux/arch/powerpc/platforms/cell/iocmd_reg.c
===================================================================
--- linux/arch/powerpc/platforms/cell/iocmd_reg.c	(revision 3)
+++ linux/arch/powerpc/platforms/cell/iocmd_reg.c	(working copy)
@@ -0,0 +1,242 @@
+/*
+ * arch/powerpc/platforms/cell/iocmd_reg.c
+ *
+ * Toggles "interrupt broadcast reissue", which is bit 35 in the 
+ * IOCmd_cfg register.
+ *
+ * This bit setting is required in case the MBX is bursted. In such case it
+ * seems the interrupt are generated too fast and the MBX interrupts might
+ * get jammed without this bit.
+ *
+ * See "IOC IOCmd Configuration Register (IOC_IOCmd_Cfg)" in the "Cell 
+ * Broadband Engine Registers" manual.
+ *
+ * The state of the "interrupt broadcast reissue" bit can be controlled via 
+ * the /proc virtual file * system:
+ *
+ * $ echo "0" > /proc/iocmd_cfg
+ *
+ * disables "interrupt broadcast reissue", while:
+ * 
+ * $ echo "1" > /proc/iocmd_cfg
+ *
+ * re-enables it.
+ * 
+ * Copyright (C) Mercury Computer Systems, Inc. 2006
+ *
+ * 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.
+ *
+ */
+#include <linux/module.h>
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/proc_fs.h>
+#include <asm/uaccess.h>
+#include <asm/io.h>
+#include <asm/prom.h>
+
+#define BE0_IOCMD_CFG_ADDR 0x20000511C00L
+#define IOC_ENABLE_BROADCAST_INT_REISSUE  0x0000000010000000L
+#define PROC_ENTRY       "iocmd_cfg"
+#define MODNAME	  "iocmd_cfg"
+#define COMMAND_LEN      2
+
+MODULE_LICENSE("GPL");
+MODULE_VERSION("1.0");
+MODULE_AUTHOR("Mercury Computer Systems, Inc.");
+MODULE_DESCRIPTION("Toggles the interrupt broadcast reissue bit in Cell for Axon");
+
+static int num_nodes = 0;
+
+/*
+ * node_ioc_iocmd_cfg_set_int_broadcat_reissue -- flip  the interrupt broadcast 
+ * reissue bit for one node
+ */
+static int node_ioc_iocmd_cfg_set_int_broadcat_reissue(int node, int action)
+{
+	u64 *be0_iocmd_cfg;
+
+	be0_iocmd_cfg = ioremap(BE0_IOCMD_CFG_ADDR + (node * 0x10000000000L), sizeof(u64));
+
+	if (!be0_iocmd_cfg) {
+		printk(KERN_ERR "%s: failed to map BE %d IOCmd_cfg\n", MODNAME, node);
+		return -1;
+	}
+
+	pr_debug("%s: BE %d IOCmd_cfg address = %p\n", MODNAME, node, be0_iocmd_cfg);
+
+	pr_debug("%s: BE %d IOCmd_cfg = 0x%016lx\n", MODNAME, node, *be0_iocmd_cfg);
+
+	if (action) {
+		pr_debug("%s: allowing broadcast interrupt reissue\n", MODNAME);
+
+		*be0_iocmd_cfg |= IOC_ENABLE_BROADCAST_INT_REISSUE;
+	}
+	else {
+		pr_debug("%s: disabling broadcast interrupt reissue\n", MODNAME);
+
+		*be0_iocmd_cfg &= ~IOC_ENABLE_BROADCAST_INT_REISSUE;
+	}
+	
+	pr_debug("%s: BE %d IOCmd_cfg = 0x%016lx\n", MODNAME, node, *be0_iocmd_cfg);
+
+	iounmap(be0_iocmd_cfg);
+
+	return 0;
+}
+
+
+/*
+ * ioc_iocmd_cfg_set_int_broadcat_reissue -- flip  the interrupt broadcast 
+ * reissue bit in all nodes
+ */
+static int ioc_iocmd_cfg_set_int_broadcat_reissue(int action)
+{
+	int node;
+
+	/* Do the "action" for all the nodes */
+	for (node = 0; node < num_nodes; node ++)
+		if (node_ioc_iocmd_cfg_set_int_broadcat_reissue(node, action))
+			return -1;
+
+	return 0;
+}
+
+#ifdef CONFIG_PROC_FS
+/*
+ * ioc_iocmd_cfg_write_proc -- called when a user does `echo "1" > /proc/<foo>'.
+ * in this case, it will enable interrupt broadcast reissue if 1 is written
+ * and disable it if a 0 is written.
+ */
+static int ioc_iocmd_cfg_write_proc(struct file *file,
+			       const char __user *buffer,
+			       unsigned long count,
+			       void *data)
+{
+	char action[2];
+	int len;
+	int rc;
+
+	if (count > COMMAND_LEN) {
+		pr_debug("%s: user wrote %d bytes\n", MODNAME, count);
+		len = COMMAND_LEN;
+	}
+	else {
+		len = count;
+	}
+
+	rc = copy_from_user(&action, buffer, len);
+	if (rc) {
+		printk(KERN_ERR "%s: copy_from_user() failed\n", MODNAME);
+		return -EFAULT;
+	}
+
+	pr_debug("%s: received `%c'\n", MODNAME, action[0]);
+
+	rc = ioc_iocmd_cfg_set_int_broadcat_reissue(action[0] == '0'?0:1);
+
+	if (rc) {
+		printk(KERN_WARNING "%s: failed to flip mode bit\n", MODNAME);
+		return -EFAULT;
+	}
+	
+	return len;
+}
+
+static int ioc_iocmd_cfg_read_proc(char *page, char **start, off_t off,
+                          int count, int *eof, void *data)
+{
+	int len = 0;
+	int node;
+	u64 *be0_iocmd_cfg;
+	char tmp[256];
+
+	*page = 0;
+
+	/* Do the "action" for all the nodes */
+	for (node = 0; node < num_nodes; node ++) {
+		be0_iocmd_cfg = ioremap(BE0_IOCMD_CFG_ADDR + (node * 0x10000000000L), sizeof(u64));
+	
+		if (!be0_iocmd_cfg) {
+			printk(KERN_ERR "%s: failed to map BE %d IOCmd_cfg\n", MODNAME, node);
+			len += sprintf(tmp, "Node %d: Failed to map\n", node);
+			continue;
+		}
+
+		len += sprintf(tmp, "Node %d: 0x%016lx\n", node, *be0_iocmd_cfg);
+
+		strcat (page, tmp);
+
+		iounmap(be0_iocmd_cfg);
+	}
+
+	return len;
+}
+#endif
+
+/*
+ * ioc_iocmd_cfg_init -- called on insmod
+ */
+static int __init ioc_iocmd_cfg_init(void)
+{
+	struct device_node *dn;
+	struct proc_dir_entry *proc;
+	int rc;
+
+	pr_debug("%s: determining number of nodes...", MODNAME);
+
+	for(dn = of_find_node_by_type(NULL, "cpu");
+	    dn;
+	    dn = of_find_node_by_type(dn, "cpu")) {
+		unsigned int *node_id;
+		node_id = (unsigned int *)get_property(dn, "node-id", NULL);
+
+		if (num_nodes < *node_id)
+			num_nodes = *node_id;
+		}
+
+	num_nodes++;
+
+	pr_debug("%s: %i nodes found.\n", MODNAME, num_nodes);
+
+#ifdef CONFIG_PROC_FS
+	/* set up the proc file system entry */
+	proc = create_proc_entry(PROC_ENTRY, 0644, NULL);
+	if (!proc) {
+		printk(KERN_ERR "%s: couldn't create proc entry\n", MODNAME);
+		return -ENOMEM;
+	}
+
+	proc->write_proc = (write_proc_t*)&ioc_iocmd_cfg_write_proc;
+	proc->read_proc = (read_proc_t*)&ioc_iocmd_cfg_read_proc;
+	proc->owner = THIS_MODULE;
+#endif
+
+	/* enable local address range mode by default */
+	rc = ioc_iocmd_cfg_set_int_broadcat_reissue(1);
+	if (rc) {
+		printk(KERN_WARNING "%s: failed to flip mode bit\n", MODNAME);
+		return -EFAULT;
+	}
+
+	pr_debug("%s: loaded\n", MODNAME);
+	return 0;
+}
+
+/*
+ * ioc_iocmd_cfg_exit -- called on rmmod, removes the proc entry
+ */
+static void __exit ioc_iocmd_cfg_exit(void)
+{
+#ifdef CONFIG_PROC_FS
+	remove_proc_entry(PROC_ENTRY, &proc_root);
+#endif
+	pr_debug("%s: unloaded\n", MODNAME);
+}
+
+module_init(ioc_iocmd_cfg_init);
+module_exit(ioc_iocmd_cfg_exit);
Index: linux/arch/powerpc/platforms/cell/Kconfig
===================================================================
--- linux/arch/powerpc/platforms/cell/Kconfig	(revision 3)
+++ linux/arch/powerpc/platforms/cell/Kconfig	(working copy)
@@ -20,9 +20,18 @@
 	  Units on machines implementing the Broadband Processor
 	  Architecture.
 
config SPUFS_MMAP
	bool
	depends on SPU_FS && SPARSEMEM && MEMORY_HOTPLUG
	default y
+
+config IOC_SET_INT_BROADCAST
+	tristate "broadcast int switch"
+	default n
+	depends on PPC_CELL
+	help
+          Allow to switch the interrupt broadcast reissue bit
+          in the IOCmd config reg
+
 endmenu
Index: linux/arch/powerpc/platforms/cell/Makefile
===================================================================
--- linux/arch/powerpc/platforms/cell/Makefile	(revision 3)
+++ linux/arch/powerpc/platforms/cell/Makefile	(working copy)
@@ -3,6 +3,7 @@
 
 obj-$(CONFIG_SMP)	+= smp.o
 obj-$(CONFIG_SPU_FS)	+= spufs/
+obj-$(CONFIG_IOC_SET_INT_BROADCAST)+= iocmd_reg.o
 
 # needed only when building loadable spufs.ko
 spufs-modular-$(CONFIG_SPU_FS) += spu_syscalls.o
