Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs

Pull VFS updates from Al Viro,

Misc cleanups all over the place, mainly wrt /proc interfaces (switch
create_proc_entry to proc_create(), get rid of the deprecated
create_proc_read_entry() in favor of using proc_create_data() and
seq_file etc).

7kloc removed.

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs: (204 commits)
  don't bother with deferred freeing of fdtables
  proc: Move non-public stuff from linux/proc_fs.h to fs/proc/internal.h
  proc: Make the PROC_I() and PDE() macros internal to procfs
  proc: Supply a function to remove a proc entry by PDE
  take cgroup_open() and cpuset_open() to fs/proc/base.c
  ppc: Clean up scanlog
  ppc: Clean up rtas_flash driver somewhat
  hostap: proc: Use remove_proc_subtree()
  drm: proc: Use remove_proc_subtree()
  drm: proc: Use minor->index to label things, not PDE->name
  drm: Constify drm_proc_list[]
  zoran: Don't print proc_dir_entry data in debug
  reiserfs: Don't access the proc_dir_entry in r_open(), r_start() r_show()
  proc: Supply an accessor for getting the data from a PDE's parent
  airo: Use remove_proc_subtree()
  rtl8192u: Don't need to save device proc dir PDE
  rtl8187se: Use a dir under /proc/net/r8180/
  proc: Add proc_mkdir_data()
  proc: Move some bits from linux/proc_fs.h to linux/{of.h,signal.h,tty.h}
  proc: Move PDE_NET() to fs/proc/proc_net.c
  ...
diff --git a/arch/alpha/kernel/srm_env.c b/arch/alpha/kernel/srm_env.c
index e64559f..ffe996a 100644
--- a/arch/alpha/kernel/srm_env.c
+++ b/arch/alpha/kernel/srm_env.c
@@ -51,13 +51,11 @@
 typedef struct _srm_env {
 	char			*name;
 	unsigned long		id;
-	struct proc_dir_entry	*proc_entry;
 } srm_env_t;
 
 static struct proc_dir_entry	*base_dir;
 static struct proc_dir_entry	*named_dir;
 static struct proc_dir_entry	*numbered_dir;
-static char			number[256][4];
 
 static srm_env_t	srm_named_entries[] = {
 	{ "auto_action",	ENV_AUTO_ACTION		},
@@ -77,21 +75,18 @@
 	{ "tty_dev",		ENV_TTY_DEV		},
 	{ NULL,			0			},
 };
-static srm_env_t	srm_numbered_entries[256];
-
 
 static int srm_env_proc_show(struct seq_file *m, void *v)
 {
 	unsigned long	ret;
-	srm_env_t	*entry;
+	unsigned long	id = (unsigned long)m->private;
 	char		*page;
 
-	entry = m->private;
 	page = (char *)__get_free_page(GFP_USER);
 	if (!page)
 		return -ENOMEM;
 
-	ret = callback_getenv(entry->id, page, PAGE_SIZE);
+	ret = callback_getenv(id, page, PAGE_SIZE);
 
 	if ((ret >> 61) == 0) {
 		seq_write(m, page, ret);
@@ -104,14 +99,14 @@
 
 static int srm_env_proc_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, srm_env_proc_show, PDE(inode)->data);
+	return single_open(file, srm_env_proc_show, PDE_DATA(inode));
 }
 
 static ssize_t srm_env_proc_write(struct file *file, const char __user *buffer,
 				  size_t count, loff_t *pos)
 {
 	int res;
-	srm_env_t	*entry = PDE(file_inode(file))->data;
+	unsigned long	id = (unsigned long)PDE_DATA(file_inode(file));
 	char		*buf = (char *) __get_free_page(GFP_USER);
 	unsigned long	ret1, ret2;
 
@@ -127,7 +122,7 @@
 		goto out;
 	buf[count] = '\0';
 
-	ret1 = callback_setenv(entry->id, buf, count);
+	ret1 = callback_setenv(id, buf, count);
 	if ((ret1 >> 61) == 0) {
 		do
 			ret2 = callback_save_env();
@@ -149,52 +144,6 @@
 	.write		= srm_env_proc_write,
 };
 
-static void
-srm_env_cleanup(void)
-{
-	srm_env_t	*entry;
-	unsigned long	var_num;
-
-	if (base_dir) {
-		/*
-		 * Remove named entries
-		 */
-		if (named_dir) {
-			entry = srm_named_entries;
-			while (entry->name != NULL && entry->id != 0) {
-				if (entry->proc_entry) {
-					remove_proc_entry(entry->name,
-							named_dir);
-					entry->proc_entry = NULL;
-				}
-				entry++;
-			}
-			remove_proc_entry(NAMED_DIR, base_dir);
-		}
-
-		/*
-		 * Remove numbered entries
-		 */
-		if (numbered_dir) {
-			for (var_num = 0; var_num <= 255; var_num++) {
-				entry =	&srm_numbered_entries[var_num];
-
-				if (entry->proc_entry) {
-					remove_proc_entry(entry->name,
-							numbered_dir);
-					entry->proc_entry	= NULL;
-					entry->name		= NULL;
-				}
-			}
-			remove_proc_entry(NUMBERED_DIR, base_dir);
-		}
-
-		remove_proc_entry(BASE_DIR, NULL);
-	}
-
-	return;
-}
-
 static int __init
 srm_env_init(void)
 {
@@ -213,19 +162,13 @@
 	}
 
 	/*
-	 * Init numbers
-	 */
-	for (var_num = 0; var_num <= 255; var_num++)
-		sprintf(number[var_num], "%ld", var_num);
-
-	/*
 	 * Create base directory
 	 */
 	base_dir = proc_mkdir(BASE_DIR, NULL);
 	if (!base_dir) {
 		printk(KERN_ERR "Couldn't create base dir /proc/%s\n",
 				BASE_DIR);
-		goto cleanup;
+		return -ENOMEM;
 	}
 
 	/*
@@ -254,9 +197,8 @@
 	 */
 	entry = srm_named_entries;
 	while (entry->name && entry->id) {
-		entry->proc_entry = proc_create_data(entry->name, 0644, named_dir,
-						     &srm_env_proc_fops, entry);
-		if (!entry->proc_entry)
+		if (!proc_create_data(entry->name, 0644, named_dir,
+			     &srm_env_proc_fops, (void *)entry->id))
 			goto cleanup;
 		entry++;
 	}
@@ -265,15 +207,11 @@
 	 * Create all numbered nodes
 	 */
 	for (var_num = 0; var_num <= 255; var_num++) {
-		entry = &srm_numbered_entries[var_num];
-		entry->name = number[var_num];
-
-		entry->proc_entry = proc_create_data(entry->name, 0644, numbered_dir,
-						     &srm_env_proc_fops, entry);
-		if (!entry->proc_entry)
+		char name[4];
+		sprintf(name, "%ld", var_num);
+		if (!proc_create_data(name, 0644, numbered_dir,
+			     &srm_env_proc_fops, (void *)var_num))
 			goto cleanup;
-
-		entry->id			= var_num;
 	}
 
 	printk(KERN_INFO "%s: version %s loaded successfully\n", NAME,
@@ -282,18 +220,15 @@
 	return 0;
 
 cleanup:
-	srm_env_cleanup();
-
+	remove_proc_subtree(BASE_DIR, NULL);
 	return -ENOMEM;
 }
 
 static void __exit
 srm_env_exit(void)
 {
-	srm_env_cleanup();
+	remove_proc_subtree(BASE_DIR, NULL);
 	printk(KERN_INFO "%s: unloaded successfully\n", NAME);
-
-	return;
 }
 
 module_init(srm_env_init);
diff --git a/arch/arm/kernel/atags_proc.c b/arch/arm/kernel/atags_proc.c
index 42a1a14..c7ff807 100644
--- a/arch/arm/kernel/atags_proc.c
+++ b/arch/arm/kernel/atags_proc.c
@@ -9,24 +9,18 @@
 	char data[];
 };
 
-static int
-read_buffer(char* page, char** start, off_t off, int count,
-	int* eof, void* data)
+static ssize_t atags_read(struct file *file, char __user *buf,
+			  size_t count, loff_t *ppos)
 {
-	struct buffer *buffer = (struct buffer *)data;
-
-	if (off >= buffer->size) {
-		*eof = 1;
-		return 0;
-	}
-
-	count = min((int) (buffer->size - off), count);
-
-	memcpy(page, &buffer->data[off], count);
-
-	return count;
+	struct buffer *b = PDE_DATA(file_inode(file));
+	return simple_read_from_buffer(buf, count, ppos, b->data, b->size);
 }
 
+static const struct file_operations atags_fops = {
+	.read = atags_read,
+	.llseek = default_llseek,
+};
+
 #define BOOT_PARAMS_SIZE 1536
 static char __initdata atags_copy[BOOT_PARAMS_SIZE];
 
@@ -66,9 +60,7 @@
 	b->size = size;
 	memcpy(b->data, atags_copy, size);
 
-	tags_entry = create_proc_read_entry("atags", 0400,
-			NULL, read_buffer, b);
-
+	tags_entry = proc_create_data("atags", 0400, NULL, &atags_fops, b);
 	if (!tags_entry)
 		goto nomem;
 
diff --git a/arch/arm/kernel/swp_emulate.c b/arch/arm/kernel/swp_emulate.c
index ab1017b..087fc32 100644
--- a/arch/arm/kernel/swp_emulate.c
+++ b/arch/arm/kernel/swp_emulate.c
@@ -21,6 +21,7 @@
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/proc_fs.h>
+#include <linux/seq_file.h>
 #include <linux/sched.h>
 #include <linux/syscalls.h>
 #include <linux/perf_event.h>
@@ -79,27 +80,27 @@
 static pid_t         previous_pid;
 
 #ifdef CONFIG_PROC_FS
-static int proc_read_status(char *page, char **start, off_t off, int count,
-			    int *eof, void *data)
+static int proc_status_show(struct seq_file *m, void *v)
 {
-	char *p = page;
-	int len;
-
-	p += sprintf(p, "Emulated SWP:\t\t%lu\n", swpcounter);
-	p += sprintf(p, "Emulated SWPB:\t\t%lu\n", swpbcounter);
-	p += sprintf(p, "Aborted SWP{B}:\t\t%lu\n", abtcounter);
+	seq_printf(m, "Emulated SWP:\t\t%lu\n", swpcounter);
+	seq_printf(m, "Emulated SWPB:\t\t%lu\n", swpbcounter);
+	seq_printf(m, "Aborted SWP{B}:\t\t%lu\n", abtcounter);
 	if (previous_pid != 0)
-		p += sprintf(p, "Last process:\t\t%d\n", previous_pid);
-
-	len = (p - page) - off;
-	if (len < 0)
-		len = 0;
-
-	*eof = (len <= count) ? 1 : 0;
-	*start = page + off;
-
-	return len;
+		seq_printf(m, "Last process:\t\t%d\n", previous_pid);
+	return 0;
 }
+
+static int proc_status_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, proc_status_show, PDE_DATA(inode));
+}
+
+static const struct file_operations proc_status_fops = {
+	.open		= proc_status_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= seq_release,
+};
 #endif
 
 /*
@@ -266,14 +267,8 @@
 static int __init swp_emulation_init(void)
 {
 #ifdef CONFIG_PROC_FS
-	struct proc_dir_entry *res;
-
-	res = create_proc_entry("cpu/swp_emulation", S_IRUGO, NULL);
-
-	if (!res)
+	if (!proc_create("cpu/swp_emulation", S_IRUGO, NULL, &proc_status_fops))
 		return -ENOMEM;
-
-	res->read_proc = proc_read_status;
 #endif /* CONFIG_PROC_FS */
 
 	printk(KERN_NOTICE "Registering SWP/SWPB emulation handler\n");
diff --git a/arch/arm/mach-msm/last_radio_log.c b/arch/arm/mach-msm/last_radio_log.c
index 1e243f4..7777767 100644
--- a/arch/arm/mach-msm/last_radio_log.c
+++ b/arch/arm/mach-msm/last_radio_log.c
@@ -31,20 +31,8 @@
 static ssize_t last_radio_log_read(struct file *file, char __user *buf,
 			size_t len, loff_t *offset)
 {
-	loff_t pos = *offset;
-	ssize_t count;
-
-	if (pos >= radio_log_size)
-		return 0;
-
-	count = min(len, (size_t)(radio_log_size - pos));
-	if (copy_to_user(buf, radio_log_base + pos, count)) {
-		pr_err("%s: copy to user failed\n", __func__);
-		return -EFAULT;
-	}
-
-	*offset += count;
-	return count;
+	return simple_read_from_buffer(buf, len, offset,
+				radio_log_base, radio_log_size);
 }
 
 static struct file_operations last_radio_log_fops = {
@@ -67,7 +55,8 @@
 		return;
 	}
 
-	entry = create_proc_entry("last_radio_log", S_IFREG | S_IRUGO, NULL);
+	entry = proc_create("last_radio_log", S_IRUGO, NULL,
+				&last_radio_log_fops);
 	if (!entry) {
 		pr_err("%s: could not create proc entry for radio log\n",
 				__func__);
@@ -77,7 +66,6 @@
 	pr_err("%s: last radio log is %d bytes long\n", __func__,
 		radio_log_size);
 	last_radio_log_fops.owner = owner;
-	entry->proc_fops = &last_radio_log_fops;
 	entry->size = radio_log_size;
 }
 EXPORT_SYMBOL(msm_init_last_radio_log);
diff --git a/arch/arm/mach-omap1/pm.c b/arch/arm/mach-omap1/pm.c
index db37f49..dd712f1 100644
--- a/arch/arm/mach-omap1/pm.c
+++ b/arch/arm/mach-omap1/pm.c
@@ -37,7 +37,8 @@
 
 #include <linux/suspend.h>
 #include <linux/sched.h>
-#include <linux/proc_fs.h>
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
 #include <linux/interrupt.h>
 #include <linux/sysfs.h>
 #include <linux/module.h>
@@ -423,23 +424,12 @@
 		omap_rev());
 }
 
-#if defined(DEBUG) && defined(CONFIG_PROC_FS)
-static int g_read_completed;
-
+#ifdef CONFIG_DEBUG_FS
 /*
  * Read system PM registers for debugging
  */
-static int omap_pm_read_proc(
-	char *page_buffer,
-	char **my_first_byte,
-	off_t virtual_start,
-	int length,
-	int *eof,
-	void *data)
+static int omap_pm_debug_show(struct seq_file *m, void *v)
 {
-	int my_buffer_offset = 0;
-	char * const my_base = page_buffer;
-
 	ARM_SAVE(ARM_CKCTL);
 	ARM_SAVE(ARM_IDLECT1);
 	ARM_SAVE(ARM_IDLECT2);
@@ -480,10 +470,7 @@
 		MPUI1610_SAVE(EMIFS_CONFIG);
 	}
 
-	if (virtual_start == 0) {
-		g_read_completed = 0;
-
-		my_buffer_offset += sprintf(my_base + my_buffer_offset,
+	seq_printf(m,
 		   "ARM_CKCTL_REG:            0x%-8x     \n"
 		   "ARM_IDLECT1_REG:          0x%-8x     \n"
 		   "ARM_IDLECT2_REG:          0x%-8x     \n"
@@ -513,8 +500,8 @@
 		   ULPD_SHOW(ULPD_STATUS_REQ),
 		   ULPD_SHOW(ULPD_POWER_CTRL));
 
-		if (cpu_is_omap7xx()) {
-			my_buffer_offset += sprintf(my_base + my_buffer_offset,
+	if (cpu_is_omap7xx()) {
+		seq_printf(m,
 			   "MPUI7XX_CTRL_REG	     0x%-8x \n"
 			   "MPUI7XX_DSP_STATUS_REG:      0x%-8x \n"
 			   "MPUI7XX_DSP_BOOT_CONFIG_REG: 0x%-8x \n"
@@ -527,8 +514,8 @@
 			   MPUI7XX_SHOW(MPUI_DSP_API_CONFIG),
 			   MPUI7XX_SHOW(EMIFF_SDRAM_CONFIG),
 			   MPUI7XX_SHOW(EMIFS_CONFIG));
-		} else if (cpu_is_omap15xx()) {
-			my_buffer_offset += sprintf(my_base + my_buffer_offset,
+	} else if (cpu_is_omap15xx()) {
+		seq_printf(m,
 			   "MPUI1510_CTRL_REG             0x%-8x \n"
 			   "MPUI1510_DSP_STATUS_REG:      0x%-8x \n"
 			   "MPUI1510_DSP_BOOT_CONFIG_REG: 0x%-8x \n"
@@ -541,8 +528,8 @@
 			   MPUI1510_SHOW(MPUI_DSP_API_CONFIG),
 			   MPUI1510_SHOW(EMIFF_SDRAM_CONFIG),
 			   MPUI1510_SHOW(EMIFS_CONFIG));
-		} else if (cpu_is_omap16xx()) {
-			my_buffer_offset += sprintf(my_base + my_buffer_offset,
+	} else if (cpu_is_omap16xx()) {
+		seq_printf(m,
 			   "MPUI1610_CTRL_REG             0x%-8x \n"
 			   "MPUI1610_DSP_STATUS_REG:      0x%-8x \n"
 			   "MPUI1610_DSP_BOOT_CONFIG_REG: 0x%-8x \n"
@@ -555,28 +542,37 @@
 			   MPUI1610_SHOW(MPUI_DSP_API_CONFIG),
 			   MPUI1610_SHOW(EMIFF_SDRAM_CONFIG),
 			   MPUI1610_SHOW(EMIFS_CONFIG));
-		}
-
-		g_read_completed++;
-	} else if (g_read_completed >= 1) {
-		 *eof = 1;
-		 return 0;
 	}
-	g_read_completed++;
 
-	*my_first_byte = page_buffer;
-	return  my_buffer_offset;
+	return 0;
 }
 
-static void omap_pm_init_proc(void)
+static int omap_pm_debug_open(struct inode *inode, struct file *file)
 {
-	/* XXX Appears to leak memory */
-	create_proc_read_entry("driver/omap_pm",
-			       S_IWUSR | S_IRUGO, NULL,
-			       omap_pm_read_proc, NULL);
+	return single_open(file, omap_pm_debug_show,
+				&inode->i_private);
 }
 
-#endif /* DEBUG && CONFIG_PROC_FS */
+static const struct file_operations omap_pm_debug_fops = {
+	.open		= omap_pm_debug_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= seq_release,
+};
+
+static void omap_pm_init_debugfs(void)
+{
+	struct dentry *d;
+
+	d = debugfs_create_dir("pm_debug", NULL);
+	if (!d)
+		return;
+
+	(void) debugfs_create_file("omap_pm", S_IWUSR | S_IRUGO,
+					d, NULL, &omap_pm_debug_fops);
+}
+
+#endif /* CONFIG_DEBUG_FS */
 
 /*
  *	omap_pm_prepare - Do preliminary suspend work.
@@ -701,8 +697,8 @@
 
 	suspend_set_ops(&omap_pm_ops);
 
-#if defined(DEBUG) && defined(CONFIG_PROC_FS)
-	omap_pm_init_proc();
+#ifdef CONFIG_DEBUG_FS
+	omap_pm_init_debugfs();
 #endif
 
 #ifdef CONFIG_OMAP_32K_TIMER
diff --git a/arch/blackfin/kernel/cplbinfo.c b/arch/blackfin/kernel/cplbinfo.c
index e1d0b24..404045d 100644
--- a/arch/blackfin/kernel/cplbinfo.c
+++ b/arch/blackfin/kernel/cplbinfo.c
@@ -116,14 +116,12 @@
 
 static int cplbinfo_open(struct inode *inode, struct file *file)
 {
-	struct proc_dir_entry *pde = PDE(file_inode(file));
 	char cplb_type;
-	unsigned int cpu;
+	unsigned int cpu = (unsigned long)PDE_DATA(file_inode(file));
 	int ret;
 	struct seq_file *m;
 	struct cplbinfo_data *cdata;
 
-	cpu = (unsigned int)pde->data;
 	cplb_type = cpu & CPLBINFO_DCPLB_FLAG ? 'D' : 'I';
 	cpu &= ~CPLBINFO_DCPLB_FLAG;
 
diff --git a/arch/cris/arch-v10/kernel/fasttimer.c b/arch/cris/arch-v10/kernel/fasttimer.c
index 082f189..ce6f512 100644
--- a/arch/cris/arch-v10/kernel/fasttimer.c
+++ b/arch/cris/arch-v10/kernel/fasttimer.c
@@ -25,6 +25,7 @@
 #include <arch/svinto.h>
 #include <asm/fasttimer.h>
 #include <linux/proc_fs.h>
+#include <linux/seq_file.h>
 
 
 #define DEBUG_LOG_INCLUDED
@@ -489,197 +490,162 @@
 }
 
 #ifdef CONFIG_PROC_FS
-static int proc_fasttimer_read(char *buf, char **start, off_t offset, int len
-                       ,int *eof, void *data_unused);
-static struct proc_dir_entry *fasttimer_proc_entry;
-#endif /* CONFIG_PROC_FS */
-
-#ifdef CONFIG_PROC_FS
-
 /* This value is very much based on testing */
 #define BIG_BUF_SIZE (500 + NUM_TIMER_STATS * 300)
 
-static int proc_fasttimer_read(char *buf, char **start, off_t offset, int len
-                       ,int *eof, void *data_unused)
+static int proc_fasttimer_show(struct seq_file *m, void *v)
 {
-  unsigned long flags;
-  int i = 0;
-  int num_to_show;
+	unsigned long flags;
+	int i = 0;
+	int num_to_show;
 	struct fasttime_t tv;
-  struct fast_timer *t, *nextt;
-  static char *bigbuf = NULL;
-  static unsigned long used;
+	struct fast_timer *t, *nextt;
 
-  if (!bigbuf && !(bigbuf = vmalloc(BIG_BUF_SIZE)))
-  {
-    used = 0;
-	if (buf)
-		buf[0] = '\0';
-    return 0;
-  }
+	do_gettimeofday_fast(&tv);
 
-  if (!offset || !used)
-  {
-    do_gettimeofday_fast(&tv);
-
-    used = 0;
-    used += sprintf(bigbuf + used, "Fast timers added:     %i\n",
-                    fast_timers_added);
-    used += sprintf(bigbuf + used, "Fast timers started:   %i\n",
-                    fast_timers_started);
-    used += sprintf(bigbuf + used, "Fast timer interrupts: %i\n",
-                    fast_timer_ints);
-    used += sprintf(bigbuf + used, "Fast timers expired:   %i\n",
-                    fast_timers_expired);
-    used += sprintf(bigbuf + used, "Fast timers deleted:   %i\n",
-                    fast_timers_deleted);
-    used += sprintf(bigbuf + used, "Fast timer running:    %s\n",
-                    fast_timer_running ? "yes" : "no");
-    used += sprintf(bigbuf + used, "Current time:          %lu.%06lu\n",
-			(unsigned long)tv.tv_jiff,
-                    (unsigned long)tv.tv_usec);
+	seq_printf(m, "Fast timers added:     %i\n", fast_timers_added);
+	seq_printf(m, "Fast timers started:   %i\n", fast_timers_started);
+	seq_printf(m, "Fast timer interrupts: %i\n", fast_timer_ints);
+	seq_printf(m, "Fast timers expired:   %i\n", fast_timers_expired);
+	seq_printf(m, "Fast timers deleted:   %i\n", fast_timers_deleted);
+	seq_printf(m, "Fast timer running:    %s\n",
+		   fast_timer_running ? "yes" : "no");
+	seq_printf(m, "Current time:          %lu.%06lu\n",
+		   (unsigned long)tv.tv_jiff,
+		   (unsigned long)tv.tv_usec);
 #ifdef FAST_TIMER_SANITY_CHECKS
-    used += sprintf(bigbuf + used, "Sanity failed:         %i\n",
-                    sanity_failed);
+	seq_printf(m, "Sanity failed:         %i\n", sanity_failed);
 #endif
-    used += sprintf(bigbuf + used, "\n");
+	seq_putc(m, '\n');
 
 #ifdef DEBUG_LOG_INCLUDED
-    {
-      int end_i = debug_log_cnt;
-      i = 0;
+	{
+		int end_i = debug_log_cnt;
+		i = 0;
 
-      if (debug_log_cnt_wrapped)
-      {
-        i = debug_log_cnt;
-      }
+		if (debug_log_cnt_wrapped)
+			i = debug_log_cnt;
 
-      while ((i != end_i || (debug_log_cnt_wrapped && !used)) &&
-             used+100 < BIG_BUF_SIZE)
-      {
-        used += sprintf(bigbuf + used, debug_log_string[i],
-                        debug_log_value[i]);
-        i = (i+1) % DEBUG_LOG_MAX;
-      }
-    }
-    used += sprintf(bigbuf + used, "\n");
+		while (i != end_i || debug_log_cnt_wrapped) {
+			if (seq_printf(m, debug_log_string[i], debug_log_value[i]) < 0)
+				return 0;
+			i = (i+1) % DEBUG_LOG_MAX;
+		}
+	}
+	seq_putc(m, '\n');
 #endif
 
-    num_to_show = (fast_timers_started < NUM_TIMER_STATS ? fast_timers_started:
-                   NUM_TIMER_STATS);
-    used += sprintf(bigbuf + used, "Timers started: %i\n", fast_timers_started);
-    for (i = 0; i < num_to_show && (used+100 < BIG_BUF_SIZE) ; i++)
-    {
-      int cur = (fast_timers_started - i - 1) % NUM_TIMER_STATS;
+	num_to_show = (fast_timers_started < NUM_TIMER_STATS ? fast_timers_started:
+		       NUM_TIMER_STATS);
+	seq_printf(m, "Timers started: %i\n", fast_timers_started);
+	for (i = 0; i < num_to_show; i++) {
+		int cur = (fast_timers_started - i - 1) % NUM_TIMER_STATS;
 
 #if 1 //ndef FAST_TIMER_LOG
-      used += sprintf(bigbuf + used, "div: %i freq: %i delay: %i"
-                      "\n",
-                      timer_div_settings[cur],
-                      timer_freq_settings[cur],
-                      timer_delay_settings[cur]
-                      );
+		seq_printf(m, "div: %i freq: %i delay: %i"
+			   "\n",
+			   timer_div_settings[cur],
+			   timer_freq_settings[cur],
+			   timer_delay_settings[cur]);
 #endif
 #ifdef FAST_TIMER_LOG
-      t = &timer_started_log[cur];
-      used += sprintf(bigbuf + used, "%-14s s: %6lu.%06lu e: %6lu.%06lu "
-                      "d: %6li us data: 0x%08lX"
-                      "\n",
-                      t->name,
-			(unsigned long)t->tv_set.tv_jiff,
-                      (unsigned long)t->tv_set.tv_usec,
-			(unsigned long)t->tv_expires.tv_jiff,
-                      (unsigned long)t->tv_expires.tv_usec,
-                      t->delay_us,
-                      t->data
-                      );
+		t = &timer_started_log[cur];
+		if (seq_printf(m, "%-14s s: %6lu.%06lu e: %6lu.%06lu "
+			       "d: %6li us data: 0x%08lX"
+			       "\n",
+			       t->name,
+			       (unsigned long)t->tv_set.tv_jiff,
+			       (unsigned long)t->tv_set.tv_usec,
+			       (unsigned long)t->tv_expires.tv_jiff,
+			       (unsigned long)t->tv_expires.tv_usec,
+			       t->delay_us,
+			       t->data) < 0)
+			return 0;
 #endif
-    }
-    used += sprintf(bigbuf + used, "\n");
+	}
+	seq_putc(m, '\n');
 
 #ifdef FAST_TIMER_LOG
-    num_to_show = (fast_timers_added < NUM_TIMER_STATS ? fast_timers_added:
-                   NUM_TIMER_STATS);
-    used += sprintf(bigbuf + used, "Timers added: %i\n", fast_timers_added);
-    for (i = 0; i < num_to_show && (used+100 < BIG_BUF_SIZE); i++)
-    {
-      t = &timer_added_log[(fast_timers_added - i - 1) % NUM_TIMER_STATS];
-      used += sprintf(bigbuf + used, "%-14s s: %6lu.%06lu e: %6lu.%06lu "
-                      "d: %6li us data: 0x%08lX"
-                      "\n",
-                      t->name,
-			(unsigned long)t->tv_set.tv_jiff,
-                      (unsigned long)t->tv_set.tv_usec,
-			(unsigned long)t->tv_expires.tv_jiff,
-                      (unsigned long)t->tv_expires.tv_usec,
-                      t->delay_us,
-                      t->data
-                      );
-    }
-    used += sprintf(bigbuf + used, "\n");
+	num_to_show = (fast_timers_added < NUM_TIMER_STATS ? fast_timers_added:
+		       NUM_TIMER_STATS);
+	seq_printf(m, "Timers added: %i\n", fast_timers_added);
+	for (i = 0; i < num_to_show; i++) {
+		t = &timer_added_log[(fast_timers_added - i - 1) % NUM_TIMER_STATS];
+		if (seq_printf(m, "%-14s s: %6lu.%06lu e: %6lu.%06lu "
+			       "d: %6li us data: 0x%08lX"
+			       "\n",
+			       t->name,
+			       (unsigned long)t->tv_set.tv_jiff,
+			       (unsigned long)t->tv_set.tv_usec,
+			       (unsigned long)t->tv_expires.tv_jiff,
+			       (unsigned long)t->tv_expires.tv_usec,
+			       t->delay_us,
+			       t->data) < 0)
+			return 0;
+	}
+	seq_putc(m, '\n');
 
-    num_to_show = (fast_timers_expired < NUM_TIMER_STATS ? fast_timers_expired:
-                   NUM_TIMER_STATS);
-    used += sprintf(bigbuf + used, "Timers expired: %i\n", fast_timers_expired);
-    for (i = 0; i < num_to_show && (used+100 < BIG_BUF_SIZE); i++)
-    {
-      t = &timer_expired_log[(fast_timers_expired - i - 1) % NUM_TIMER_STATS];
-      used += sprintf(bigbuf + used, "%-14s s: %6lu.%06lu e: %6lu.%06lu "
-                      "d: %6li us data: 0x%08lX"
-                      "\n",
-                      t->name,
-			(unsigned long)t->tv_set.tv_jiff,
-                      (unsigned long)t->tv_set.tv_usec,
-			(unsigned long)t->tv_expires.tv_jiff,
-                      (unsigned long)t->tv_expires.tv_usec,
-                      t->delay_us,
-                      t->data
-                      );
-    }
-    used += sprintf(bigbuf + used, "\n");
+	num_to_show = (fast_timers_expired < NUM_TIMER_STATS ? fast_timers_expired:
+		       NUM_TIMER_STATS);
+	seq_printf(m, "Timers expired: %i\n", fast_timers_expired);
+	for (i = 0; i < num_to_show; i++) {
+		t = &timer_expired_log[(fast_timers_expired - i - 1) % NUM_TIMER_STATS];
+		if (seq_printf(m, "%-14s s: %6lu.%06lu e: %6lu.%06lu "
+			       "d: %6li us data: 0x%08lX"
+			       "\n",
+			       t->name,
+			       (unsigned long)t->tv_set.tv_jiff,
+			       (unsigned long)t->tv_set.tv_usec,
+			       (unsigned long)t->tv_expires.tv_jiff,
+			       (unsigned long)t->tv_expires.tv_usec,
+			       t->delay_us,
+			       t->data) < 0)
+			return 0;
+	}
+	seq_putc(m, '\n');
 #endif
 
-    used += sprintf(bigbuf + used, "Active timers:\n");
-    local_irq_save(flags);
-    t = fast_timer_list;
-    while (t != NULL && (used+100 < BIG_BUF_SIZE))
-    {
-      nextt = t->next;
-      local_irq_restore(flags);
-      used += sprintf(bigbuf + used, "%-14s s: %6lu.%06lu e: %6lu.%06lu "
-                      "d: %6li us data: 0x%08lX"
-/*                      " func: 0x%08lX" */
-                      "\n",
-                      t->name,
-			(unsigned long)t->tv_set.tv_jiff,
-                      (unsigned long)t->tv_set.tv_usec,
-			(unsigned long)t->tv_expires.tv_jiff,
-                      (unsigned long)t->tv_expires.tv_usec,
-                      t->delay_us,
-                      t->data
-/*                      , t->function */
-                      );
+	seq_puts(m, "Active timers:\n");
 	local_irq_save(flags);
-      if (t->next != nextt)
-      {
-        printk(KERN_WARNING "timer removed!\n");
-      }
-      t = nextt;
-    }
-    local_irq_restore(flags);
-  }
+	t = fast_timer_list;
+	while (t) {
+		nextt = t->next;
+		local_irq_restore(flags);
+		if (seq_printf(m, "%-14s s: %6lu.%06lu e: %6lu.%06lu "
+			       "d: %6li us data: 0x%08lX"
+/*                      " func: 0x%08lX" */
+			       "\n",
+			       t->name,
+			       (unsigned long)t->tv_set.tv_jiff,
+			       (unsigned long)t->tv_set.tv_usec,
+			       (unsigned long)t->tv_expires.tv_jiff,
+			       (unsigned long)t->tv_expires.tv_usec,
+			       t->delay_us,
+			       t->data
+/*                      , t->function */
+			       ) < 0)
+			return 0;
+		local_irq_save(flags);
+		if (t->next != nextt)
+			printk(KERN_WARNING "timer removed!\n");
+		t = nextt;
+	}
+	local_irq_restore(flags);
 
-  if (used - offset < len)
-  {
-    len = used - offset;
-  }
-
-  memcpy(buf, bigbuf + offset, len);
-  *start = buf;
-  *eof = 1;
-
-  return len;
+	return 0;
 }
+
+static int proc_fasttimer_open(struct inode *inode, struct file *file)
+{
+	return single_open_size(file, proc_fasttimer_show, PDE_DATA(inode), BIG_BUF_SIZE);
+}
+
+static const struct file_operations proc_fasttimer_fops = {
+	.open		= proc_fasttimer_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= seq_release,
+};
 #endif /* PROC_FS */
 
 #ifdef FAST_TIMER_TEST
@@ -857,8 +823,7 @@
     }
 #endif
 #ifdef CONFIG_PROC_FS
-   if ((fasttimer_proc_entry = create_proc_entry( "fasttimer", 0, 0 )))
-     fasttimer_proc_entry->read_proc = proc_fasttimer_read;
+   proc_create("fasttimer", 0, NULL, &proc_fasttimer_fops);
 #endif /* PROC_FS */
     if(request_irq(TIMER1_IRQ_NBR, timer1_handler, 0,
                    "fast timer int", NULL))
diff --git a/arch/cris/arch-v32/kernel/fasttimer.c b/arch/cris/arch-v32/kernel/fasttimer.c
index ab1551e..e43dd70 100644
--- a/arch/cris/arch-v32/kernel/fasttimer.c
+++ b/arch/cris/arch-v32/kernel/fasttimer.c
@@ -23,6 +23,7 @@
 #include <hwregs/timer_defs.h>
 #include <asm/fasttimer.h>
 #include <linux/proc_fs.h>
+#include <linux/seq_file.h>
 
 /*
  * timer0 is running at 100MHz and generating jiffies timer ticks
@@ -463,195 +464,161 @@
 }
 
 #ifdef CONFIG_PROC_FS
-static int proc_fasttimer_read(char *buf, char **start, off_t offset, int len
-                       ,int *eof, void *data_unused);
-static struct proc_dir_entry *fasttimer_proc_entry;
-#endif /* CONFIG_PROC_FS */
-
-#ifdef CONFIG_PROC_FS
-
 /* This value is very much based on testing */
 #define BIG_BUF_SIZE (500 + NUM_TIMER_STATS * 300)
 
-static int proc_fasttimer_read(char *buf, char **start, off_t offset, int len
-                       ,int *eof, void *data_unused)
+static int proc_fasttimer_show(struct seq_file *m, void *v)
 {
-  unsigned long flags;
-  int i = 0;
-  int num_to_show;
+	unsigned long flags;
+	int i = 0;
+	int num_to_show;
 	struct fasttime_t tv;
-  struct fast_timer *t, *nextt;
-  static char *bigbuf = NULL;
-  static unsigned long used;
+	struct fast_timer *t, *nextt;
 
-	if (!bigbuf) {
-		bigbuf = vmalloc(BIG_BUF_SIZE);
-		if (!bigbuf) {
-			used = 0;
-			if (buf)
-				buf[0] = '\0';
-			return 0;
-		}
-	}
+	do_gettimeofday_fast(&tv);
 
-	if (!offset || !used) {
-    do_gettimeofday_fast(&tv);
-
-    used = 0;
-    used += sprintf(bigbuf + used, "Fast timers added:     %i\n",
-                    fast_timers_added);
-    used += sprintf(bigbuf + used, "Fast timers started:   %i\n",
-                    fast_timers_started);
-    used += sprintf(bigbuf + used, "Fast timer interrupts: %i\n",
-                    fast_timer_ints);
-    used += sprintf(bigbuf + used, "Fast timers expired:   %i\n",
-                    fast_timers_expired);
-    used += sprintf(bigbuf + used, "Fast timers deleted:   %i\n",
-                    fast_timers_deleted);
-    used += sprintf(bigbuf + used, "Fast timer running:    %s\n",
-                    fast_timer_running ? "yes" : "no");
-    used += sprintf(bigbuf + used, "Current time:          %lu.%06lu\n",
-			(unsigned long)tv.tv_jiff,
-                    (unsigned long)tv.tv_usec);
+	seq_printf(m, "Fast timers added:     %i\n", fast_timers_added);
+	seq_printf(m, "Fast timers started:   %i\n", fast_timers_started);
+	seq_printf(m, "Fast timer interrupts: %i\n", fast_timer_ints);
+	seq_printf(m, "Fast timers expired:   %i\n", fast_timers_expired);
+	seq_printf(m, "Fast timers deleted:   %i\n", fast_timers_deleted);
+	seq_printf(m, "Fast timer running:    %s\n",
+		   fast_timer_running ? "yes" : "no");
+	seq_printf(m, "Current time:          %lu.%06lu\n",
+		   (unsigned long)tv.tv_jiff,
+		   (unsigned long)tv.tv_usec);
 #ifdef FAST_TIMER_SANITY_CHECKS
-    used += sprintf(bigbuf + used, "Sanity failed:         %i\n",
-                    sanity_failed);
+	seq_printf(m, "Sanity failed:         %i\n", sanity_failed);
 #endif
-    used += sprintf(bigbuf + used, "\n");
+	seq_putc(m, '\n');
 
 #ifdef DEBUG_LOG_INCLUDED
-    {
-      int end_i = debug_log_cnt;
-      i = 0;
+	{
+		int end_i = debug_log_cnt;
+		i = 0;
 
-			if (debug_log_cnt_wrapped)
-        i = debug_log_cnt;
+		if (debug_log_cnt_wrapped)
+			i = debug_log_cnt;
 
-      while ((i != end_i || (debug_log_cnt_wrapped && !used)) &&
-             used+100 < BIG_BUF_SIZE)
-      {
-        used += sprintf(bigbuf + used, debug_log_string[i],
-                        debug_log_value[i]);
-        i = (i+1) % DEBUG_LOG_MAX;
-      }
-    }
-    used += sprintf(bigbuf + used, "\n");
+		while ((i != end_i || debug_log_cnt_wrapped)) {
+			if (seq_printf(m, debug_log_string[i], debug_log_value[i]) < 0)
+				return 0;
+			i = (i+1) % DEBUG_LOG_MAX;
+		}
+	}
+	seq_putc(m, '\n');
 #endif
 
-    num_to_show = (fast_timers_started < NUM_TIMER_STATS ? fast_timers_started:
-                   NUM_TIMER_STATS);
-    used += sprintf(bigbuf + used, "Timers started: %i\n", fast_timers_started);
-    for (i = 0; i < num_to_show && (used+100 < BIG_BUF_SIZE) ; i++)
-    {
-      int cur = (fast_timers_started - i - 1) % NUM_TIMER_STATS;
+	num_to_show = (fast_timers_started < NUM_TIMER_STATS ? fast_timers_started:
+		       NUM_TIMER_STATS);
+	seq_printf(m, "Timers started: %i\n", fast_timers_started);
+	for (i = 0; i < num_to_show; i++) {
+		int cur = (fast_timers_started - i - 1) % NUM_TIMER_STATS;
 
 #if 1 //ndef FAST_TIMER_LOG
-      used += sprintf(bigbuf + used, "div: %i delay: %i"
-                      "\n",
-                      timer_div_settings[cur],
-                      timer_delay_settings[cur]
-                      );
+		seq_printf(m, "div: %i delay: %i"
+			   "\n",
+			   timer_div_settings[cur],
+			   timer_delay_settings[cur]);
 #endif
 #ifdef FAST_TIMER_LOG
-      t = &timer_started_log[cur];
-      used += sprintf(bigbuf + used, "%-14s s: %6lu.%06lu e: %6lu.%06lu "
-                      "d: %6li us data: 0x%08lX"
-                      "\n",
-                      t->name,
-				(unsigned long)t->tv_set.tv_jiff,
-                      (unsigned long)t->tv_set.tv_usec,
-				(unsigned long)t->tv_expires.tv_jiff,
-                      (unsigned long)t->tv_expires.tv_usec,
-                      t->delay_us,
-                      t->data
-                      );
+		t = &timer_started_log[cur];
+		if (seq_printf(m, "%-14s s: %6lu.%06lu e: %6lu.%06lu "
+			       "d: %6li us data: 0x%08lX"
+			       "\n",
+			       t->name,
+			       (unsigned long)t->tv_set.tv_jiff,
+			       (unsigned long)t->tv_set.tv_usec,
+			       (unsigned long)t->tv_expires.tv_jiff,
+			       (unsigned long)t->tv_expires.tv_usec,
+			       t->delay_us,
+			       t->data) < 0)
+			return 0;
 #endif
-    }
-    used += sprintf(bigbuf + used, "\n");
+	}
+	seq_putc(m, '\n');
 
 #ifdef FAST_TIMER_LOG
-    num_to_show = (fast_timers_added < NUM_TIMER_STATS ? fast_timers_added:
-                   NUM_TIMER_STATS);
-    used += sprintf(bigbuf + used, "Timers added: %i\n", fast_timers_added);
-    for (i = 0; i < num_to_show && (used+100 < BIG_BUF_SIZE); i++)
-    {
-      t = &timer_added_log[(fast_timers_added - i - 1) % NUM_TIMER_STATS];
-      used += sprintf(bigbuf + used, "%-14s s: %6lu.%06lu e: %6lu.%06lu "
-                      "d: %6li us data: 0x%08lX"
-                      "\n",
-                      t->name,
-				(unsigned long)t->tv_set.tv_jiff,
-                      (unsigned long)t->tv_set.tv_usec,
-				(unsigned long)t->tv_expires.tv_jiff,
-                      (unsigned long)t->tv_expires.tv_usec,
-                      t->delay_us,
-                      t->data
-                      );
-    }
-    used += sprintf(bigbuf + used, "\n");
+	num_to_show = (fast_timers_added < NUM_TIMER_STATS ? fast_timers_added:
+		       NUM_TIMER_STATS);
+	seq_printf(m, "Timers added: %i\n", fast_timers_added);
+	for (i = 0; i < num_to_show; i++) {
+		t = &timer_added_log[(fast_timers_added - i - 1) % NUM_TIMER_STATS];
+		if (seq_printf(m, "%-14s s: %6lu.%06lu e: %6lu.%06lu "
+			       "d: %6li us data: 0x%08lX"
+			       "\n",
+			       t->name,
+			       (unsigned long)t->tv_set.tv_jiff,
+			       (unsigned long)t->tv_set.tv_usec,
+			       (unsigned long)t->tv_expires.tv_jiff,
+			       (unsigned long)t->tv_expires.tv_usec,
+			       t->delay_us,
+			       t->data) < 0)
+			return 0;
+	}
+	seq_putc(m, '\n');
 
-    num_to_show = (fast_timers_expired < NUM_TIMER_STATS ? fast_timers_expired:
-                   NUM_TIMER_STATS);
-    used += sprintf(bigbuf + used, "Timers expired: %i\n", fast_timers_expired);
-    for (i = 0; i < num_to_show && (used+100 < BIG_BUF_SIZE); i++)
-    {
-      t = &timer_expired_log[(fast_timers_expired - i - 1) % NUM_TIMER_STATS];
-      used += sprintf(bigbuf + used, "%-14s s: %6lu.%06lu e: %6lu.%06lu "
-                      "d: %6li us data: 0x%08lX"
-                      "\n",
-                      t->name,
-				(unsigned long)t->tv_set.tv_jiff,
-                      (unsigned long)t->tv_set.tv_usec,
-				(unsigned long)t->tv_expires.tv_jiff,
-                      (unsigned long)t->tv_expires.tv_usec,
-                      t->delay_us,
-                      t->data
-                      );
-    }
-    used += sprintf(bigbuf + used, "\n");
+	num_to_show = (fast_timers_expired < NUM_TIMER_STATS ? fast_timers_expired:
+		       NUM_TIMER_STATS);
+	seq_printf(m, "Timers expired: %i\n", fast_timers_expired);
+	for (i = 0; i < num_to_show; i++){
+		t = &timer_expired_log[(fast_timers_expired - i - 1) % NUM_TIMER_STATS];
+		if (seq_printf(m, "%-14s s: %6lu.%06lu e: %6lu.%06lu "
+			       "d: %6li us data: 0x%08lX"
+			       "\n",
+			       t->name,
+			       (unsigned long)t->tv_set.tv_jiff,
+			       (unsigned long)t->tv_set.tv_usec,
+			       (unsigned long)t->tv_expires.tv_jiff,
+			       (unsigned long)t->tv_expires.tv_usec,
+			       t->delay_us,
+			       t->data) < 0)
+			return 0;
+	}
+	seq_putc(m, '\n');
 #endif
 
-    used += sprintf(bigbuf + used, "Active timers:\n");
-    local_irq_save(flags);
-    t = fast_timer_list;
-    while (t != NULL && (used+100 < BIG_BUF_SIZE))
-    {
-      nextt = t->next;
-      local_irq_restore(flags);
-      used += sprintf(bigbuf + used, "%-14s s: %6lu.%06lu e: %6lu.%06lu "
-			"d: %6li us data: 0x%08lX"
+	seq_puts(m, "Active timers:\n");
+	local_irq_save(flags);
+	t = fast_timer_list;
+	while (t != NULL){
+		nextt = t->next;
+		local_irq_restore(flags);
+		if (seq_printf(m, "%-14s s: %6lu.%06lu e: %6lu.%06lu "
+			       "d: %6li us data: 0x%08lX"
 /*			" func: 0x%08lX" */
-			"\n",
-			t->name,
-			(unsigned long)t->tv_set.tv_jiff,
-			(unsigned long)t->tv_set.tv_usec,
-			(unsigned long)t->tv_expires.tv_jiff,
-			(unsigned long)t->tv_expires.tv_usec,
-                      t->delay_us,
-                      t->data
+			       "\n",
+			       t->name,
+			       (unsigned long)t->tv_set.tv_jiff,
+			       (unsigned long)t->tv_set.tv_usec,
+			       (unsigned long)t->tv_expires.tv_jiff,
+			       (unsigned long)t->tv_expires.tv_usec,
+			       t->delay_us,
+			       t->data
 /*                      , t->function */
-                      );
-			local_irq_save(flags);
-      if (t->next != nextt)
-      {
-        printk("timer removed!\n");
-      }
-      t = nextt;
-    }
-    local_irq_restore(flags);
-  }
-
-  if (used - offset < len)
-  {
-    len = used - offset;
-  }
-
-  memcpy(buf, bigbuf + offset, len);
-  *start = buf;
-  *eof = 1;
-
-  return len;
+			       ) < 0)
+			return 0;
+		local_irq_save(flags);
+		if (t->next != nextt)
+			printk("timer removed!\n");
+		t = nextt;
+	}
+	local_irq_restore(flags);
+	return 0;
 }
+
+static int proc_fasttimer_open(struct inode *inode, struct file *file)
+{
+	return single_open_size(file, proc_fasttimer_show, PDE_DATA(inode), BIG_BUF_SIZE);
+}
+
+static const struct file_operations proc_fasttimer_fops = {
+	.open		= proc_fasttimer_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= seq_release,
+};
+
 #endif /* PROC_FS */
 
 #ifdef FAST_TIMER_TEST
@@ -816,9 +783,7 @@
     printk("fast_timer_init()\n");
 
 #ifdef CONFIG_PROC_FS
-    fasttimer_proc_entry = create_proc_entry("fasttimer", 0, 0);
-    if (fasttimer_proc_entry)
-      fasttimer_proc_entry->read_proc = proc_fasttimer_read;
+    proc_create("fasttimer", 0, NULL, &proc_fasttimer_fops);
 #endif /* PROC_FS */
 		if (request_irq(TIMER0_INTR_VECT, timer_trig_interrupt,
 				IRQF_SHARED | IRQF_DISABLED,
diff --git a/arch/h8300/kernel/gpio.c b/arch/h8300/kernel/gpio.c
index 6a25dd5..b02c752 100644
--- a/arch/h8300/kernel/gpio.c
+++ b/arch/h8300/kernel/gpio.c
@@ -11,6 +11,7 @@
 
 #include <linux/stddef.h>
 #include <linux/proc_fs.h>
+#include <linux/seq_file.h>
 #include <linux/kernel.h>
 #include <linux/string.h>
 #include <linux/fs.h>
@@ -138,30 +139,34 @@
 	return result;
 }
 
-static int gpio_proc_read(char *buf, char **start, off_t offset, 
-                          int len, int *unused_i, void *unused_v)
+static int gpio_proc_show(struct seq_file *m, void *v)
 {
-	int c,outlen;
 	static const char port_name[]="123456789ABCDEFGH";
-	outlen = 0;
+	int c;
+
 	for (c = 0; c < MAX_PORT; c++) {
 		if (ddrs[c] == NULL)
-			continue ;
-		len = sprintf(buf,"P%c: %s\n",port_name[c],port_status(c));
-		buf += len;
-		outlen += len;
+			continue;
+		seq_printf(m, "P%c: %s\n", port_name[c], port_status(c));
 	}
-	return outlen;
+	return 0;
 }
 
+static int gpio_proc_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, gpio_proc_show, PDE_DATA(inode));
+}
+
+static const struct file_operations gpio_proc_fops = {
+	.open		= gpio_proc_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= seq_release,
+};
+
 static __init int register_proc(void)
 {
-	struct proc_dir_entry *proc_gpio;
-
-	proc_gpio = create_proc_entry("gpio", S_IRUGO, NULL);
-	if (proc_gpio) 
-		proc_gpio->read_proc = gpio_proc_read;
-	return proc_gpio != NULL;
+	return proc_create("gpio", S_IRUGO, NULL, &gpio_proc_fops) != NULL;
 }
 
 __initcall(register_proc);
diff --git a/arch/ia64/kernel/palinfo.c b/arch/ia64/kernel/palinfo.c
index 79521d5..b17129e 100644
--- a/arch/ia64/kernel/palinfo.c
+++ b/arch/ia64/kernel/palinfo.c
@@ -22,6 +22,7 @@
 #include <linux/errno.h>
 #include <linux/init.h>
 #include <linux/proc_fs.h>
+#include <linux/seq_file.h>
 #include <linux/mm.h>
 #include <linux/module.h>
 #include <linux/efi.h>
@@ -41,7 +42,7 @@
 
 #define PALINFO_VERSION "0.5"
 
-typedef int (*palinfo_func_t)(char*);
+typedef int (*palinfo_func_t)(struct seq_file *);
 
 typedef struct {
 	const char		*name;		/* name of the proc entry */
@@ -54,7 +55,7 @@
  *  A bunch of string array to get pretty printing
  */
 
-static char *cache_types[] = {
+static const char *cache_types[] = {
 	"",			/* not used */
 	"Instruction",
 	"Data",
@@ -122,19 +123,16 @@
  *	- a pointer to the end of the buffer
  *
  */
-static char *
-bitvector_process(char *p, u64 vector)
+static void bitvector_process(struct seq_file *m, u64 vector)
 {
 	int i,j;
-	const char *units[]={ "", "K", "M", "G", "T" };
+	static const char *units[]={ "", "K", "M", "G", "T" };
 
 	for (i=0, j=0; i < 64; i++ , j=i/10) {
-		if (vector & 0x1) {
-			p += sprintf(p, "%d%s ", 1 << (i-j*10), units[j]);
-		}
+		if (vector & 0x1)
+			seq_printf(m, "%d%s ", 1 << (i-j*10), units[j]);
 		vector >>= 1;
 	}
-	return p;
 }
 
 /*
@@ -149,8 +147,7 @@
  *	- a pointer to the end of the buffer
  *
  */
-static char *
-bitregister_process(char *p, u64 *reg_info, int max)
+static void bitregister_process(struct seq_file *m, u64 *reg_info, int max)
 {
 	int i, begin, skip = 0;
 	u64 value = reg_info[0];
@@ -163,9 +160,9 @@
 
 		if ((value & 0x1) == 0 && skip == 0) {
 			if (begin  <= i - 2)
-				p += sprintf(p, "%d-%d ", begin, i-1);
+				seq_printf(m, "%d-%d ", begin, i-1);
 			else
-				p += sprintf(p, "%d ", i-1);
+				seq_printf(m, "%d ", i-1);
 			skip  = 1;
 			begin = -1;
 		} else if ((value & 0x1) && skip == 1) {
@@ -176,19 +173,15 @@
 	}
 	if (begin > -1) {
 		if (begin < 127)
-			p += sprintf(p, "%d-127", begin);
+			seq_printf(m, "%d-127", begin);
 		else
-			p += sprintf(p, "127");
+			seq_puts(m, "127");
 	}
-
-	return p;
 }
 
-static int
-power_info(char *page)
+static int power_info(struct seq_file *m)
 {
 	s64 status;
-	char *p = page;
 	u64 halt_info_buffer[8];
 	pal_power_mgmt_info_u_t *halt_info =(pal_power_mgmt_info_u_t *)halt_info_buffer;
 	int i;
@@ -198,26 +191,25 @@
 
 	for (i=0; i < 8 ; i++ ) {
 		if (halt_info[i].pal_power_mgmt_info_s.im == 1) {
-			p += sprintf(p,	"Power level %d:\n"
-				     "\tentry_latency       : %d cycles\n"
-				     "\texit_latency        : %d cycles\n"
-				     "\tpower consumption   : %d mW\n"
-				     "\tCache+TLB coherency : %s\n", i,
-				     halt_info[i].pal_power_mgmt_info_s.entry_latency,
-				     halt_info[i].pal_power_mgmt_info_s.exit_latency,
-				     halt_info[i].pal_power_mgmt_info_s.power_consumption,
-				     halt_info[i].pal_power_mgmt_info_s.co ? "Yes" : "No");
+			seq_printf(m,
+				   "Power level %d:\n"
+				   "\tentry_latency       : %d cycles\n"
+				   "\texit_latency        : %d cycles\n"
+				   "\tpower consumption   : %d mW\n"
+				   "\tCache+TLB coherency : %s\n", i,
+				   halt_info[i].pal_power_mgmt_info_s.entry_latency,
+				   halt_info[i].pal_power_mgmt_info_s.exit_latency,
+				   halt_info[i].pal_power_mgmt_info_s.power_consumption,
+				   halt_info[i].pal_power_mgmt_info_s.co ? "Yes" : "No");
 		} else {
-			p += sprintf(p,"Power level %d: not implemented\n",i);
+			seq_printf(m,"Power level %d: not implemented\n", i);
 		}
 	}
-	return p - page;
+	return 0;
 }
 
-static int
-cache_info(char *page)
+static int cache_info(struct seq_file *m)
 {
-	char *p = page;
 	unsigned long i, levels, unique_caches;
 	pal_cache_config_info_t cci;
 	int j, k;
@@ -228,73 +220,74 @@
 		return 0;
 	}
 
-	p += sprintf(p, "Cache levels  : %ld\nUnique caches : %ld\n\n", levels, unique_caches);
+	seq_printf(m, "Cache levels  : %ld\nUnique caches : %ld\n\n",
+		   levels, unique_caches);
 
 	for (i=0; i < levels; i++) {
-
 		for (j=2; j >0 ; j--) {
-
 			/* even without unification some level may not be present */
-			if ((status=ia64_pal_cache_config_info(i,j, &cci)) != 0) {
+			if ((status=ia64_pal_cache_config_info(i,j, &cci)) != 0)
 				continue;
-			}
-			p += sprintf(p,
-				     "%s Cache level %lu:\n"
-				     "\tSize           : %u bytes\n"
-				     "\tAttributes     : ",
-				     cache_types[j+cci.pcci_unified], i+1,
-				     cci.pcci_cache_size);
 
-			if (cci.pcci_unified) p += sprintf(p, "Unified ");
+			seq_printf(m,
+				   "%s Cache level %lu:\n"
+				   "\tSize           : %u bytes\n"
+				   "\tAttributes     : ",
+				   cache_types[j+cci.pcci_unified], i+1,
+				   cci.pcci_cache_size);
 
-			p += sprintf(p, "%s\n", cache_mattrib[cci.pcci_cache_attr]);
+			if (cci.pcci_unified)
+				seq_puts(m, "Unified ");
 
-			p += sprintf(p,
-				     "\tAssociativity  : %d\n"
-				     "\tLine size      : %d bytes\n"
-				     "\tStride         : %d bytes\n",
-				     cci.pcci_assoc, 1<<cci.pcci_line_size, 1<<cci.pcci_stride);
+			seq_printf(m, "%s\n", cache_mattrib[cci.pcci_cache_attr]);
+
+			seq_printf(m,
+				   "\tAssociativity  : %d\n"
+				   "\tLine size      : %d bytes\n"
+				   "\tStride         : %d bytes\n",
+				   cci.pcci_assoc,
+				   1<<cci.pcci_line_size,
+				   1<<cci.pcci_stride);
 			if (j == 1)
-				p += sprintf(p, "\tStore latency  : N/A\n");
+				seq_puts(m, "\tStore latency  : N/A\n");
 			else
-				p += sprintf(p, "\tStore latency  : %d cycle(s)\n",
-						cci.pcci_st_latency);
+				seq_printf(m, "\tStore latency  : %d cycle(s)\n",
+					   cci.pcci_st_latency);
 
-			p += sprintf(p,
-				     "\tLoad latency   : %d cycle(s)\n"
-				     "\tStore hints    : ", cci.pcci_ld_latency);
+			seq_printf(m,
+				   "\tLoad latency   : %d cycle(s)\n"
+				   "\tStore hints    : ", cci.pcci_ld_latency);
 
 			for(k=0; k < 8; k++ ) {
 				if ( cci.pcci_st_hints & 0x1)
-					p += sprintf(p, "[%s]", cache_st_hints[k]);
+					seq_printf(m, "[%s]", cache_st_hints[k]);
 				cci.pcci_st_hints >>=1;
 			}
-			p += sprintf(p, "\n\tLoad hints     : ");
+			seq_puts(m, "\n\tLoad hints     : ");
 
 			for(k=0; k < 8; k++ ) {
 				if (cci.pcci_ld_hints & 0x1)
-					p += sprintf(p, "[%s]", cache_ld_hints[k]);
+					seq_printf(m, "[%s]", cache_ld_hints[k]);
 				cci.pcci_ld_hints >>=1;
 			}
-			p += sprintf(p,
-				     "\n\tAlias boundary : %d byte(s)\n"
-				     "\tTag LSB        : %d\n"
-				     "\tTag MSB        : %d\n",
-				     1<<cci.pcci_alias_boundary, cci.pcci_tag_lsb,
-				     cci.pcci_tag_msb);
+			seq_printf(m,
+				   "\n\tAlias boundary : %d byte(s)\n"
+				   "\tTag LSB        : %d\n"
+				   "\tTag MSB        : %d\n",
+				   1<<cci.pcci_alias_boundary, cci.pcci_tag_lsb,
+				   cci.pcci_tag_msb);
 
 			/* when unified, data(j=2) is enough */
-			if (cci.pcci_unified) break;
+			if (cci.pcci_unified)
+				break;
 		}
 	}
-	return p - page;
+	return 0;
 }
 
 
-static int
-vm_info(char *page)
+static int vm_info(struct seq_file *m)
 {
-	char *p = page;
 	u64 tr_pages =0, vw_pages=0, tc_pages;
 	u64 attrib;
 	pal_vm_info_1_u_t vm_info_1;
@@ -309,7 +302,7 @@
 		printk(KERN_ERR "ia64_pal_vm_summary=%ld\n", status);
 	} else {
 
-		p += sprintf(p,
+		seq_printf(m,
 		     "Physical Address Space         : %d bits\n"
 		     "Virtual Address Space          : %d bits\n"
 		     "Protection Key Registers(PKR)  : %d\n"
@@ -324,49 +317,49 @@
 		     vm_info_1.pal_vm_info_1_s.hash_tag_id,
 		     vm_info_2.pal_vm_info_2_s.rid_size);
 		if (vm_info_2.pal_vm_info_2_s.max_purges == PAL_MAX_PURGES)
-			p += sprintf(p, "unlimited\n");
+			seq_puts(m, "unlimited\n");
 		else
-			p += sprintf(p, "%d\n",
+			seq_printf(m, "%d\n",
 		     		vm_info_2.pal_vm_info_2_s.max_purges ?
 				vm_info_2.pal_vm_info_2_s.max_purges : 1);
 	}
 
 	if (ia64_pal_mem_attrib(&attrib) == 0) {
-		p += sprintf(p, "Supported memory attributes    : ");
+		seq_puts(m, "Supported memory attributes    : ");
 		sep = "";
 		for (i = 0; i < 8; i++) {
 			if (attrib & (1 << i)) {
-				p += sprintf(p, "%s%s", sep, mem_attrib[i]);
+				seq_printf(m, "%s%s", sep, mem_attrib[i]);
 				sep = ", ";
 			}
 		}
-		p += sprintf(p, "\n");
+		seq_putc(m, '\n');
 	}
 
 	if ((status = ia64_pal_vm_page_size(&tr_pages, &vw_pages)) !=0) {
 		printk(KERN_ERR "ia64_pal_vm_page_size=%ld\n", status);
 	} else {
 
-		p += sprintf(p,
-			     "\nTLB walker                     : %simplemented\n"
-			     "Number of DTR                  : %d\n"
-			     "Number of ITR                  : %d\n"
-			     "TLB insertable page sizes      : ",
-			     vm_info_1.pal_vm_info_1_s.vw ? "" : "not ",
-			     vm_info_1.pal_vm_info_1_s.max_dtr_entry+1,
-			     vm_info_1.pal_vm_info_1_s.max_itr_entry+1);
+		seq_printf(m,
+			   "\nTLB walker                     : %simplemented\n"
+			   "Number of DTR                  : %d\n"
+			   "Number of ITR                  : %d\n"
+			   "TLB insertable page sizes      : ",
+			   vm_info_1.pal_vm_info_1_s.vw ? "" : "not ",
+			   vm_info_1.pal_vm_info_1_s.max_dtr_entry+1,
+			   vm_info_1.pal_vm_info_1_s.max_itr_entry+1);
 
+		bitvector_process(m, tr_pages);
 
-		p = bitvector_process(p, tr_pages);
+		seq_puts(m, "\nTLB purgeable page sizes       : ");
 
-		p += sprintf(p, "\nTLB purgeable page sizes       : ");
-
-		p = bitvector_process(p, vw_pages);
+		bitvector_process(m, vw_pages);
 	}
-	if ((status=ia64_get_ptce(&ptce)) != 0) {
+
+	if ((status = ia64_get_ptce(&ptce)) != 0) {
 		printk(KERN_ERR "ia64_get_ptce=%ld\n", status);
 	} else {
-		p += sprintf(p,
+		seq_printf(m,
 		     "\nPurge base address             : 0x%016lx\n"
 		     "Purge outer loop count         : %d\n"
 		     "Purge inner loop count         : %d\n"
@@ -375,7 +368,7 @@
 		     ptce.base, ptce.count[0], ptce.count[1],
 		     ptce.stride[0], ptce.stride[1]);
 
-		p += sprintf(p,
+		seq_printf(m,
 		     "TC Levels                      : %d\n"
 		     "Unique TC(s)                   : %d\n",
 		     vm_info_1.pal_vm_info_1_s.num_tc_levels,
@@ -385,13 +378,11 @@
 			for (j=2; j>0 ; j--) {
 				tc_pages = 0; /* just in case */
 
-
 				/* even without unification, some levels may not be present */
-				if ((status=ia64_pal_vm_info(i,j, &tc_info, &tc_pages)) != 0) {
+				if ((status=ia64_pal_vm_info(i,j, &tc_info, &tc_pages)) != 0)
 					continue;
-				}
 
-				p += sprintf(p,
+				seq_printf(m,
 				     "\n%s Translation Cache Level %d:\n"
 				     "\tHash sets           : %d\n"
 				     "\tAssociativity       : %d\n"
@@ -403,15 +394,15 @@
 				     tc_info.tc_num_entries);
 
 				if (tc_info.tc_pf)
-					p += sprintf(p, "PreferredPageSizeOptimized ");
+					seq_puts(m, "PreferredPageSizeOptimized ");
 				if (tc_info.tc_unified)
-					p += sprintf(p, "Unified ");
+					seq_puts(m, "Unified ");
 				if (tc_info.tc_reduce_tr)
-					p += sprintf(p, "TCReduction");
+					seq_puts(m, "TCReduction");
 
-				p += sprintf(p, "\n\tSupported page sizes: ");
+				seq_puts(m, "\n\tSupported page sizes: ");
 
-				p = bitvector_process(p, tc_pages);
+				bitvector_process(m, tc_pages);
 
 				/* when unified date (j=2) is enough */
 				if (tc_info.tc_unified)
@@ -419,16 +410,14 @@
 			}
 		}
 	}
-	p += sprintf(p, "\n");
 
-	return p - page;
+	seq_putc(m, '\n');
+	return 0;
 }
 
 
-static int
-register_info(char *page)
+static int register_info(struct seq_file *m)
 {
-	char *p = page;
 	u64 reg_info[2];
 	u64 info;
 	unsigned long phys_stacked;
@@ -442,35 +431,31 @@
 	};
 
 	for(info=0; info < 4; info++) {
-
-		if (ia64_pal_register_info(info, &reg_info[0], &reg_info[1]) != 0) return 0;
-
-		p += sprintf(p, "%-32s : ", info_type[info]);
-
-		p = bitregister_process(p, reg_info, 128);
-
-		p += sprintf(p, "\n");
+		if (ia64_pal_register_info(info, &reg_info[0], &reg_info[1]) != 0)
+			return 0;
+		seq_printf(m, "%-32s : ", info_type[info]);
+		bitregister_process(m, reg_info, 128);
+		seq_putc(m, '\n');
 	}
 
-	if (ia64_pal_rse_info(&phys_stacked, &hints) == 0) {
+	if (ia64_pal_rse_info(&phys_stacked, &hints) == 0)
+		seq_printf(m,
+			   "RSE stacked physical registers   : %ld\n"
+			   "RSE load/store hints             : %ld (%s)\n",
+			   phys_stacked, hints.ph_data,
+			   hints.ph_data < RSE_HINTS_COUNT ? rse_hints[hints.ph_data]: "(??)");
 
-	p += sprintf(p,
-		     "RSE stacked physical registers   : %ld\n"
-		     "RSE load/store hints             : %ld (%s)\n",
-		     phys_stacked, hints.ph_data,
-		     hints.ph_data < RSE_HINTS_COUNT ? rse_hints[hints.ph_data]: "(??)");
-	}
 	if (ia64_pal_debug_info(&iregs, &dregs))
 		return 0;
 
-	p += sprintf(p,
-		     "Instruction debug register pairs : %ld\n"
-		     "Data debug register pairs        : %ld\n", iregs, dregs);
+	seq_printf(m,
+		   "Instruction debug register pairs : %ld\n"
+		   "Data debug register pairs        : %ld\n", iregs, dregs);
 
-	return p - page;
+	return 0;
 }
 
-static char *proc_features_0[]={		/* Feature set 0 */
+static const char *const proc_features_0[]={		/* Feature set 0 */
 	NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
 	NULL,NULL,NULL,NULL,NULL,NULL,NULL, NULL,NULL,
 	NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
@@ -502,7 +487,7 @@
 	"Enable BERR promotion"
 };
 
-static char *proc_features_16[]={		/* Feature set 16 */
+static const char *const proc_features_16[]={		/* Feature set 16 */
 	"Disable ETM",
 	"Enable ETM",
 	"Enable MCA on half-way timer",
@@ -522,7 +507,7 @@
 	NULL, NULL, NULL, NULL, NULL
 };
 
-static char **proc_features[]={
+static const char *const *const proc_features[]={
 	proc_features_0,
 	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
 	NULL, NULL, NULL, NULL,
@@ -530,11 +515,10 @@
 	NULL, NULL, NULL, NULL,
 };
 
-static char * feature_set_info(char *page, u64 avail, u64 status, u64 control,
-							unsigned long set)
+static void feature_set_info(struct seq_file *m, u64 avail, u64 status, u64 control,
+			     unsigned long set)
 {
-	char *p = page;
-	char **vf, **v;
+	const char *const *vf, *const *v;
 	int i;
 
 	vf = v = proc_features[set];
@@ -547,13 +531,13 @@
 		if (vf)
 			v = vf + i;
 		if ( v && *v ) {
-			p += sprintf(p, "%-40s : %s %s\n", *v,
+			seq_printf(m, "%-40s : %s %s\n", *v,
 				avail & 0x1 ? (status & 0x1 ?
-						"On " : "Off"): "",
+					      "On " : "Off"): "",
 				avail & 0x1 ? (control & 0x1 ?
 						"Ctrl" : "NoCtrl"): "");
 		} else {
-			p += sprintf(p, "Feature set %2ld bit %2d\t\t\t"
+			seq_printf(m, "Feature set %2ld bit %2d\t\t\t"
 					" : %s %s\n",
 				set, i,
 				avail & 0x1 ? (status & 0x1 ?
@@ -562,36 +546,32 @@
 						"Ctrl" : "NoCtrl"): "");
 		}
 	}
-	return p;
 }
 
-static int
-processor_info(char *page)
+static int processor_info(struct seq_file *m)
 {
-	char *p = page;
 	u64 avail=1, status=1, control=1, feature_set=0;
 	s64 ret;
 
 	do {
 		ret = ia64_pal_proc_get_features(&avail, &status, &control,
 						feature_set);
-		if (ret < 0) {
-			return p - page;
-		}
+		if (ret < 0)
+			return 0;
+
 		if (ret == 1) {
 			feature_set++;
 			continue;
 		}
 
-		p = feature_set_info(p, avail, status, control, feature_set);
-
+		feature_set_info(m, avail, status, control, feature_set);
 		feature_set++;
 	} while(1);
 
-	return p - page;
+	return 0;
 }
 
-static const char *bus_features[]={
+static const char *const bus_features[]={
 	NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
 	NULL,NULL,NULL,NULL,NULL,NULL,NULL, NULL,NULL,
 	NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
@@ -617,125 +597,118 @@
 };
 
 
-static int
-bus_info(char *page)
+static int bus_info(struct seq_file *m)
 {
-	char *p = page;
-	const char **v = bus_features;
+	const char *const *v = bus_features;
 	pal_bus_features_u_t av, st, ct;
 	u64 avail, status, control;
 	int i;
 	s64 ret;
 
-	if ((ret=ia64_pal_bus_get_features(&av, &st, &ct)) != 0) return 0;
+	if ((ret=ia64_pal_bus_get_features(&av, &st, &ct)) != 0)
+		return 0;
 
 	avail   = av.pal_bus_features_val;
 	status  = st.pal_bus_features_val;
 	control = ct.pal_bus_features_val;
 
 	for(i=0; i < 64; i++, v++, avail >>=1, status >>=1, control >>=1) {
-		if ( ! *v ) continue;
-		p += sprintf(p, "%-48s : %s%s %s\n", *v,
-				avail & 0x1 ? "" : "NotImpl",
-				avail & 0x1 ? (status  & 0x1 ? "On" : "Off"): "",
-				avail & 0x1 ? (control & 0x1 ? "Ctrl" : "NoCtrl"): "");
+		if ( ! *v )
+			continue;
+		seq_printf(m, "%-48s : %s%s %s\n", *v,
+			   avail & 0x1 ? "" : "NotImpl",
+			   avail & 0x1 ? (status  & 0x1 ? "On" : "Off"): "",
+			   avail & 0x1 ? (control & 0x1 ? "Ctrl" : "NoCtrl"): "");
 	}
-	return p - page;
+	return 0;
 }
 
-static int
-version_info(char *page)
+static int version_info(struct seq_file *m)
 {
 	pal_version_u_t min_ver, cur_ver;
-	char *p = page;
 
 	if (ia64_pal_version(&min_ver, &cur_ver) != 0)
 		return 0;
 
-	p += sprintf(p,
-		     "PAL_vendor : 0x%02x (min=0x%02x)\n"
-		     "PAL_A      : %02x.%02x (min=%02x.%02x)\n"
-		     "PAL_B      : %02x.%02x (min=%02x.%02x)\n",
-		     cur_ver.pal_version_s.pv_pal_vendor,
-		     min_ver.pal_version_s.pv_pal_vendor,
-		     cur_ver.pal_version_s.pv_pal_a_model,
-		     cur_ver.pal_version_s.pv_pal_a_rev,
-		     min_ver.pal_version_s.pv_pal_a_model,
-		     min_ver.pal_version_s.pv_pal_a_rev,
-		     cur_ver.pal_version_s.pv_pal_b_model,
-		     cur_ver.pal_version_s.pv_pal_b_rev,
-		     min_ver.pal_version_s.pv_pal_b_model,
-		     min_ver.pal_version_s.pv_pal_b_rev);
-	return p - page;
+	seq_printf(m,
+		   "PAL_vendor : 0x%02x (min=0x%02x)\n"
+		   "PAL_A      : %02x.%02x (min=%02x.%02x)\n"
+		   "PAL_B      : %02x.%02x (min=%02x.%02x)\n",
+		   cur_ver.pal_version_s.pv_pal_vendor,
+		   min_ver.pal_version_s.pv_pal_vendor,
+		   cur_ver.pal_version_s.pv_pal_a_model,
+		   cur_ver.pal_version_s.pv_pal_a_rev,
+		   min_ver.pal_version_s.pv_pal_a_model,
+		   min_ver.pal_version_s.pv_pal_a_rev,
+		   cur_ver.pal_version_s.pv_pal_b_model,
+		   cur_ver.pal_version_s.pv_pal_b_rev,
+		   min_ver.pal_version_s.pv_pal_b_model,
+		   min_ver.pal_version_s.pv_pal_b_rev);
+	return 0;
 }
 
-static int
-perfmon_info(char *page)
+static int perfmon_info(struct seq_file *m)
 {
-	char *p = page;
 	u64 pm_buffer[16];
 	pal_perf_mon_info_u_t pm_info;
 
-	if (ia64_pal_perf_mon_info(pm_buffer, &pm_info) != 0) return 0;
+	if (ia64_pal_perf_mon_info(pm_buffer, &pm_info) != 0)
+		return 0;
 
-	p += sprintf(p,
-		     "PMC/PMD pairs                 : %d\n"
-		     "Counter width                 : %d bits\n"
-		     "Cycle event number            : %d\n"
-		     "Retired event number          : %d\n"
-		     "Implemented PMC               : ",
-		     pm_info.pal_perf_mon_info_s.generic, pm_info.pal_perf_mon_info_s.width,
-		     pm_info.pal_perf_mon_info_s.cycles, pm_info.pal_perf_mon_info_s.retired);
+	seq_printf(m,
+		   "PMC/PMD pairs                 : %d\n"
+		   "Counter width                 : %d bits\n"
+		   "Cycle event number            : %d\n"
+		   "Retired event number          : %d\n"
+		   "Implemented PMC               : ",
+		   pm_info.pal_perf_mon_info_s.generic,
+		   pm_info.pal_perf_mon_info_s.width,
+		   pm_info.pal_perf_mon_info_s.cycles,
+		   pm_info.pal_perf_mon_info_s.retired);
 
-	p = bitregister_process(p, pm_buffer, 256);
-	p += sprintf(p, "\nImplemented PMD               : ");
-	p = bitregister_process(p, pm_buffer+4, 256);
-	p += sprintf(p, "\nCycles count capable          : ");
-	p = bitregister_process(p, pm_buffer+8, 256);
-	p += sprintf(p, "\nRetired bundles count capable : ");
+	bitregister_process(m, pm_buffer, 256);
+	seq_puts(m, "\nImplemented PMD               : ");
+	bitregister_process(m, pm_buffer+4, 256);
+	seq_puts(m, "\nCycles count capable          : ");
+	bitregister_process(m, pm_buffer+8, 256);
+	seq_puts(m, "\nRetired bundles count capable : ");
 
 #ifdef CONFIG_ITANIUM
 	/*
 	 * PAL_PERF_MON_INFO reports that only PMC4 can be used to count CPU_CYCLES
 	 * which is wrong, both PMC4 and PMD5 support it.
 	 */
-	if (pm_buffer[12] == 0x10) pm_buffer[12]=0x30;
+	if (pm_buffer[12] == 0x10)
+		pm_buffer[12]=0x30;
 #endif
 
-	p = bitregister_process(p, pm_buffer+12, 256);
-
-	p += sprintf(p, "\n");
-
-	return p - page;
+	bitregister_process(m, pm_buffer+12, 256);
+	seq_putc(m, '\n');
+	return 0;
 }
 
-static int
-frequency_info(char *page)
+static int frequency_info(struct seq_file *m)
 {
-	char *p = page;
 	struct pal_freq_ratio proc, itc, bus;
 	unsigned long base;
 
 	if (ia64_pal_freq_base(&base) == -1)
-		p += sprintf(p, "Output clock            : not implemented\n");
+		seq_puts(m, "Output clock            : not implemented\n");
 	else
-		p += sprintf(p, "Output clock            : %ld ticks/s\n", base);
+		seq_printf(m, "Output clock            : %ld ticks/s\n", base);
 
 	if (ia64_pal_freq_ratios(&proc, &bus, &itc) != 0) return 0;
 
-	p += sprintf(p,
+	seq_printf(m,
 		     "Processor/Clock ratio   : %d/%d\n"
 		     "Bus/Clock ratio         : %d/%d\n"
 		     "ITC/Clock ratio         : %d/%d\n",
 		     proc.num, proc.den, bus.num, bus.den, itc.num, itc.den);
-
-	return p - page;
+	return 0;
 }
 
-static int
-tr_info(char *page)
+static int tr_info(struct seq_file *m)
 {
-	char *p = page;
 	long status;
 	pal_tr_valid_u_t tr_valid;
 	u64 tr_buffer[4];
@@ -794,39 +767,40 @@
 
 		ifa_reg  = (struct ifa_reg *)&tr_buffer[2];
 
-		if (ifa_reg->valid == 0) continue;
+		if (ifa_reg->valid == 0)
+			continue;
 
 		gr_reg   = (struct gr_reg *)tr_buffer;
 		itir_reg = (struct itir_reg *)&tr_buffer[1];
 		rid_reg  = (struct rid_reg *)&tr_buffer[3];
 
 		pgm	 = -1 << (itir_reg->ps - 12);
-		p += sprintf(p,
-			     "%cTR%lu: av=%d pv=%d dv=%d mv=%d\n"
-			     "\tppn  : 0x%lx\n"
-			     "\tvpn  : 0x%lx\n"
-			     "\tps   : ",
-			     "ID"[i], j,
-			     tr_valid.pal_tr_valid_s.access_rights_valid,
-			     tr_valid.pal_tr_valid_s.priv_level_valid,
-			     tr_valid.pal_tr_valid_s.dirty_bit_valid,
-			     tr_valid.pal_tr_valid_s.mem_attr_valid,
-			     (gr_reg->ppn & pgm)<< 12, (ifa_reg->vpn & pgm)<< 12);
+		seq_printf(m,
+			   "%cTR%lu: av=%d pv=%d dv=%d mv=%d\n"
+			   "\tppn  : 0x%lx\n"
+			   "\tvpn  : 0x%lx\n"
+			   "\tps   : ",
+			   "ID"[i], j,
+			   tr_valid.pal_tr_valid_s.access_rights_valid,
+			   tr_valid.pal_tr_valid_s.priv_level_valid,
+			   tr_valid.pal_tr_valid_s.dirty_bit_valid,
+			   tr_valid.pal_tr_valid_s.mem_attr_valid,
+			   (gr_reg->ppn & pgm)<< 12, (ifa_reg->vpn & pgm)<< 12);
 
-		p = bitvector_process(p, 1<< itir_reg->ps);
+		bitvector_process(m, 1<< itir_reg->ps);
 
-		p += sprintf(p,
-			     "\n\tpl   : %d\n"
-			     "\tar   : %d\n"
-			     "\trid  : %x\n"
-			     "\tp    : %d\n"
-			     "\tma   : %d\n"
-			     "\td    : %d\n",
-			     gr_reg->pl, gr_reg->ar, rid_reg->rid, gr_reg->p, gr_reg->ma,
-			     gr_reg->d);
+		seq_printf(m,
+			   "\n\tpl   : %d\n"
+			   "\tar   : %d\n"
+			   "\trid  : %x\n"
+			   "\tp    : %d\n"
+			   "\tma   : %d\n"
+			   "\td    : %d\n",
+			   gr_reg->pl, gr_reg->ar, rid_reg->rid, gr_reg->p, gr_reg->ma,
+			   gr_reg->d);
 		}
 	}
-	return p - page;
+	return 0;
 }
 
 
@@ -834,7 +808,7 @@
 /*
  * List {name,function} pairs for every entry in /proc/palinfo/cpu*
  */
-static palinfo_entry_t palinfo_entries[]={
+static const palinfo_entry_t palinfo_entries[]={
 	{ "version_info",	version_info, },
 	{ "vm_info",		vm_info, },
 	{ "cache_info",		cache_info, },
@@ -876,7 +850,7 @@
  */
 typedef struct {
 	palinfo_func_t	func;	/* pointer to function to call */
-	char		*page;	/* buffer to store results */
+	struct seq_file *m;	/* buffer to store results */
 	int		ret;	/* return value from call */
 } palinfo_smp_data_t;
 
@@ -889,7 +863,7 @@
 palinfo_smp_call(void *info)
 {
 	palinfo_smp_data_t *data = (palinfo_smp_data_t *)info;
-	data->ret = (*data->func)(data->page);
+	data->ret = (*data->func)(data->m);
 }
 
 /*
@@ -899,13 +873,13 @@
  *	otherwise how many bytes in the "page" buffer were written
  */
 static
-int palinfo_handle_smp(pal_func_cpu_u_t *f, char *page)
+int palinfo_handle_smp(struct seq_file *m, pal_func_cpu_u_t *f)
 {
 	palinfo_smp_data_t ptr;
 	int ret;
 
 	ptr.func = palinfo_entries[f->func_id].proc_read;
-	ptr.page = page;
+	ptr.m = m;
 	ptr.ret  = 0; /* just in case */
 
 
@@ -919,7 +893,7 @@
 }
 #else /* ! CONFIG_SMP */
 static
-int palinfo_handle_smp(pal_func_cpu_u_t *f, char *page)
+int palinfo_handle_smp(struct seq_file *m, pal_func_cpu_u_t *f)
 {
 	printk(KERN_ERR "palinfo: should not be called with non SMP kernel\n");
 	return 0;
@@ -929,34 +903,35 @@
 /*
  * Entry point routine: all calls go through this function
  */
-static int
-palinfo_read_entry(char *page, char **start, off_t off, int count, int *eof, void *data)
+static int proc_palinfo_show(struct seq_file *m, void *v)
 {
-	int len=0;
-	pal_func_cpu_u_t *f = (pal_func_cpu_u_t *)&data;
+	pal_func_cpu_u_t *f = (pal_func_cpu_u_t *)&m->private;
 
 	/*
 	 * in SMP mode, we may need to call another CPU to get correct
 	 * information. PAL, by definition, is processor specific
 	 */
 	if (f->req_cpu == get_cpu())
-		len = (*palinfo_entries[f->func_id].proc_read)(page);
+		(*palinfo_entries[f->func_id].proc_read)(m);
 	else
-		len = palinfo_handle_smp(f, page);
+		palinfo_handle_smp(m, f);
 
 	put_cpu();
-
-	if (len <= off+count) *eof = 1;
-
-	*start = page + off;
-	len   -= off;
-
-	if (len>count) len = count;
-	if (len<0) len = 0;
-
-	return len;
+	return 0;
 }
 
+static int proc_palinfo_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, proc_palinfo_show, PDE_DATA(inode));
+}
+
+static const struct file_operations proc_palinfo_fops = {
+	.open		= proc_palinfo_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= seq_release,
+};
+
 static void __cpuinit
 create_palinfo_proc_entries(unsigned int cpu)
 {
@@ -974,9 +949,8 @@
 
 	for (j=0; j < NR_PALINFO_ENTRIES; j++) {
 		f.func_id = j;
-		create_proc_read_entry(
-			palinfo_entries[j].name, 0, cpu_dir,
-			palinfo_read_entry, (void *)f.value);
+		proc_create_data(palinfo_entries[j].name, 0, cpu_dir,
+				 &proc_palinfo_fops, (void *)f.value);
 	}
 }
 
diff --git a/arch/ia64/kernel/salinfo.c b/arch/ia64/kernel/salinfo.c
index aa527d7..5035245 100644
--- a/arch/ia64/kernel/salinfo.c
+++ b/arch/ia64/kernel/salinfo.c
@@ -40,6 +40,7 @@
 #include <linux/cpu.h>
 #include <linux/types.h>
 #include <linux/proc_fs.h>
+#include <linux/seq_file.h>
 #include <linux/module.h>
 #include <linux/smp.h>
 #include <linux/timer.h>
@@ -53,7 +54,7 @@
 MODULE_DESCRIPTION("/proc interface to IA-64 SAL features");
 MODULE_LICENSE("GPL");
 
-static int salinfo_read(char *page, char **start, off_t off, int count, int *eof, void *data);
+static const struct file_operations proc_salinfo_fops;
 
 typedef struct {
 	const char		*name;		/* name of the proc entry */
@@ -65,7 +66,7 @@
  * List {name,feature} pairs for every entry in /proc/sal/<feature>
  * that this module exports
  */
-static salinfo_entry_t salinfo_entries[]={
+static const salinfo_entry_t salinfo_entries[]={
 	{ "bus_lock",           IA64_SAL_PLATFORM_FEATURE_BUS_LOCK, },
 	{ "irq_redirection",	IA64_SAL_PLATFORM_FEATURE_IRQ_REDIR_HINT, },
 	{ "ipi_redirection",	IA64_SAL_PLATFORM_FEATURE_IPI_REDIR_HINT, },
@@ -301,9 +302,7 @@
 static ssize_t
 salinfo_event_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos)
 {
-	struct inode *inode = file_inode(file);
-	struct proc_dir_entry *entry = PDE(inode);
-	struct salinfo_data *data = entry->data;
+	struct salinfo_data *data = PDE_DATA(file_inode(file));
 	char cmd[32];
 	size_t size;
 	int i, n, cpu = -1;
@@ -360,8 +359,7 @@
 static int
 salinfo_log_open(struct inode *inode, struct file *file)
 {
-	struct proc_dir_entry *entry = PDE(inode);
-	struct salinfo_data *data = entry->data;
+	struct salinfo_data *data = PDE_DATA(inode);
 
 	if (!capable(CAP_SYS_ADMIN))
 		return -EPERM;
@@ -386,8 +384,7 @@
 static int
 salinfo_log_release(struct inode *inode, struct file *file)
 {
-	struct proc_dir_entry *entry = PDE(inode);
-	struct salinfo_data *data = entry->data;
+	struct salinfo_data *data = PDE_DATA(inode);
 
 	if (data->state == STATE_NO_DATA) {
 		vfree(data->log_buffer);
@@ -463,9 +460,7 @@
 static ssize_t
 salinfo_log_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos)
 {
-	struct inode *inode = file_inode(file);
-	struct proc_dir_entry *entry = PDE(inode);
-	struct salinfo_data *data = entry->data;
+	struct salinfo_data *data = PDE_DATA(file_inode(file));
 	u8 *buf;
 	u64 bufsize;
 
@@ -524,9 +519,7 @@
 static ssize_t
 salinfo_log_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos)
 {
-	struct inode *inode = file_inode(file);
-	struct proc_dir_entry *entry = PDE(inode);
-	struct salinfo_data *data = entry->data;
+	struct salinfo_data *data = PDE_DATA(file_inode(file));
 	char cmd[32];
 	size_t size;
 	u32 offset;
@@ -637,8 +630,9 @@
 
 	for (i=0; i < NR_SALINFO_ENTRIES; i++) {
 		/* pass the feature bit in question as misc data */
-		*sdir++ = create_proc_read_entry (salinfo_entries[i].name, 0, salinfo_dir,
-						  salinfo_read, (void *)salinfo_entries[i].feature);
+		*sdir++ = proc_create_data(salinfo_entries[i].name, 0, salinfo_dir,
+					   &proc_salinfo_fops,
+					   (void *)salinfo_entries[i].feature);
 	}
 
 	for (i = 0; i < ARRAY_SIZE(salinfo_log_name); i++) {
@@ -684,22 +678,23 @@
  * 'data' contains an integer that corresponds to the feature we're
  * testing
  */
-static int
-salinfo_read(char *page, char **start, off_t off, int count, int *eof, void *data)
+static int proc_salinfo_show(struct seq_file *m, void *v)
 {
-	int len = 0;
-
-	len = sprintf(page, (sal_platform_features & (unsigned long)data) ? "1\n" : "0\n");
-
-	if (len <= off+count) *eof = 1;
-
-	*start = page + off;
-	len   -= off;
-
-	if (len>count) len = count;
-	if (len<0) len = 0;
-
-	return len;
+	unsigned long data = (unsigned long)v;
+	seq_puts(m, (sal_platform_features & data) ? "1\n" : "0\n");
+	return 0;
 }
 
+static int proc_salinfo_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, proc_salinfo_show, PDE_DATA(inode));
+}
+
+static const struct file_operations proc_salinfo_fops = {
+	.open		= proc_salinfo_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= seq_release,
+};
+
 module_init(salinfo_init);
diff --git a/arch/ia64/sn/kernel/sn2/prominfo_proc.c b/arch/ia64/sn/kernel/sn2/prominfo_proc.c
index 20b88cb..daa8d6b 100644
--- a/arch/ia64/sn/kernel/sn2/prominfo_proc.c
+++ b/arch/ia64/sn/kernel/sn2/prominfo_proc.c
@@ -11,6 +11,7 @@
 #include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/proc_fs.h>
+#include <linux/seq_file.h>
 #include <linux/nodemask.h>
 #include <asm/io.h>
 #include <asm/sn/sn_sal.h>
@@ -101,18 +102,18 @@
 /*
  * These two routines display the FIT table for each node.
  */
-static int dump_fit_entry(char *page, unsigned long *fentry)
+static void dump_fit_entry(struct seq_file *m, unsigned long *fentry)
 {
 	unsigned type;
 
 	type = FIT_TYPE(fentry[1]);
-	return sprintf(page, "%02x %-25s %x.%02x %016lx %u\n",
-		       type,
-		       fit_type_name(type),
-		       FIT_MAJOR(fentry[1]), FIT_MINOR(fentry[1]),
-		       fentry[0],
-		       /* mult by sixteen to get size in bytes */
-		       (unsigned)(fentry[1] & 0xffffff) * 16);
+	seq_printf(m, "%02x %-25s %x.%02x %016lx %u\n",
+		   type,
+		   fit_type_name(type),
+		   FIT_MAJOR(fentry[1]), FIT_MINOR(fentry[1]),
+		   fentry[0],
+		   /* mult by sixteen to get size in bytes */
+		   (unsigned)(fentry[1] & 0xffffff) * 16);
 }
 
 
@@ -124,31 +125,39 @@
  * OK except for 4kB pages (and no one is going to do that on SN
  * anyway).
  */
-static int
-dump_fit(char *page, unsigned long nasid)
+static int proc_fit_show(struct seq_file *m, void *v)
 {
+	unsigned long nasid = (unsigned long)m->private;
 	unsigned long fentry[2];
 	int index;
-	char *p;
 
-	p = page;
 	for (index=0;;index++) {
 		BUG_ON(index * 60 > PAGE_SIZE);
 		if (get_fit_entry(nasid, index, fentry, NULL, 0))
 			break;
-		p += dump_fit_entry(p, fentry);
+		dump_fit_entry(m, fentry);
 	}
-
-	return p - page;
+	return 0;
 }
 
-static int
-dump_version(char *page, unsigned long nasid)
+static int proc_fit_open(struct inode *inode, struct file *file)
 {
+	return single_open(file, proc_fit_show, PDE_DATA(inode));
+}
+
+static const struct file_operations proc_fit_fops = {
+	.open		= proc_fit_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= seq_release,
+};
+
+static int proc_version_show(struct seq_file *m, void *v)
+{
+	unsigned long nasid = (unsigned long)m->private;
 	unsigned long fentry[2];
 	char banner[128];
 	int index;
-	int len;
 
 	for (index = 0; ; index++) {
 		if (get_fit_entry(nasid, index, fentry, banner,
@@ -158,56 +167,24 @@
 			break;
 	}
 
-	len = sprintf(page, "%x.%02x\n", FIT_MAJOR(fentry[1]),
-		      FIT_MINOR(fentry[1]));
-	page += len;
+	seq_printf(m, "%x.%02x\n", FIT_MAJOR(fentry[1]), FIT_MINOR(fentry[1]));
 
 	if (banner[0])
-		len += snprintf(page, PAGE_SIZE-len, "%s\n", banner);
-
-	return len;
+		seq_printf(m, "%s\n", banner);
+	return 0;
 }
 
-/* same as in proc_misc.c */
-static int
-proc_calc_metrics(char *page, char **start, off_t off, int count, int *eof,
-		  int len)
+static int proc_version_open(struct inode *inode, struct file *file)
 {
-	if (len <= off + count)
-		*eof = 1;
-	*start = page + off;
-	len -= off;
-	if (len > count)
-		len = count;
-	if (len < 0)
-		len = 0;
-	return len;
+	return single_open(file, proc_version_show, PDE_DATA(inode));
 }
 
-static int
-read_version_entry(char *page, char **start, off_t off, int count, int *eof,
-		   void *data)
-{
-	int len;
-
-	/* data holds the NASID of the node */
-	len = dump_version(page, (unsigned long)data);
-	len = proc_calc_metrics(page, start, off, count, eof, len);
-	return len;
-}
-
-static int
-read_fit_entry(char *page, char **start, off_t off, int count, int *eof,
-	       void *data)
-{
-	int len;
-
-	/* data holds the NASID of the node */
-	len = dump_fit(page, (unsigned long)data);
-	len = proc_calc_metrics(page, start, off, count, eof, len);
-
-	return len;
-}
+static const struct file_operations proc_version_fops = {
+	.open		= proc_version_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= seq_release,
+};
 
 /* module entry points */
 int __init prominfo_init(void);
@@ -216,58 +193,39 @@
 module_init(prominfo_init);
 module_exit(prominfo_exit);
 
-static struct proc_dir_entry **proc_entries;
-static struct proc_dir_entry *sgi_prominfo_entry;
-
 #define NODE_NAME_LEN 11
 
 int __init prominfo_init(void)
 {
-	struct proc_dir_entry **entp;
+	struct proc_dir_entry *sgi_prominfo_entry;
 	cnodeid_t cnodeid;
-	unsigned long nasid;
-	int size;
-	char name[NODE_NAME_LEN];
 
 	if (!ia64_platform_is("sn2"))
 		return 0;
 
-	size = num_online_nodes() * sizeof(struct proc_dir_entry *);
-	proc_entries = kzalloc(size, GFP_KERNEL);
-	if (!proc_entries)
+	sgi_prominfo_entry = proc_mkdir("sgi_prominfo", NULL);
+	if (!sgi_prominfo_entry)
 		return -ENOMEM;
 
-	sgi_prominfo_entry = proc_mkdir("sgi_prominfo", NULL);
-
-	entp = proc_entries;
 	for_each_online_node(cnodeid) {
-		sprintf(name, "node%d", cnodeid);
-		*entp = proc_mkdir(name, sgi_prominfo_entry);
-		nasid = cnodeid_to_nasid(cnodeid);
-		create_proc_read_entry("fit", 0, *entp, read_fit_entry,
-					   (void *)nasid);
-		create_proc_read_entry("version", 0, *entp,
-					   read_version_entry, (void *)nasid);
-		entp++;
-	}
+		struct proc_dir_entry *dir;
+		unsigned long nasid;
+		char name[NODE_NAME_LEN];
 
+		sprintf(name, "node%d", cnodeid);
+		dir = proc_mkdir(name, sgi_prominfo_entry);
+		if (!dir)
+			continue;
+		nasid = cnodeid_to_nasid(cnodeid);
+		proc_create_data("fit", 0, dir,
+				 &proc_fit_fops, (void *)nasid);
+		proc_create_data("version", 0, dir,
+				 &proc_version_fops, (void *)nasid);
+	}
 	return 0;
 }
 
 void __exit prominfo_exit(void)
 {
-	struct proc_dir_entry **entp;
-	unsigned int cnodeid;
-	char name[NODE_NAME_LEN];
-
-	entp = proc_entries;
-	for_each_online_node(cnodeid) {
-		remove_proc_entry("fit", *entp);
-		remove_proc_entry("version", *entp);
-		sprintf(name, "node%d", cnodeid);
-		remove_proc_entry(name, sgi_prominfo_entry);
-		entp++;
-	}
-	remove_proc_entry("sgi_prominfo", NULL);
-	kfree(proc_entries);
+	remove_proc_subtree("sgi_prominfo", NULL);
 }
diff --git a/arch/mips/kernel/smtc-proc.c b/arch/mips/kernel/smtc-proc.c
index aee7c81..9fb7144 100644
--- a/arch/mips/kernel/smtc-proc.c
+++ b/arch/mips/kernel/smtc-proc.c
@@ -16,6 +16,7 @@
 #include <asm/mipsregs.h>
 #include <asm/cacheflush.h>
 #include <linux/proc_fs.h>
+#include <linux/seq_file.h>
 
 #include <asm/smtc_proc.h>
 
@@ -30,51 +31,39 @@
 
 struct smtc_cpu_proc smtc_cpu_stats[NR_CPUS];
 
-static struct proc_dir_entry *smtc_stats;
-
 atomic_t smtc_fpu_recoveries;
 
-static int proc_read_smtc(char *page, char **start, off_t off,
-			  int count, int *eof, void *data)
+static int smtc_proc_show(struct seq_file *m, void *v)
 {
-	int totalen = 0;
-	int len;
 	int i;
 	extern unsigned long ebase;
 
-	len = sprintf(page, "SMTC Status Word: 0x%08x\n", smtc_status);
-	totalen += len;
-	page += len;
-	len = sprintf(page, "Config7: 0x%08x\n", read_c0_config7());
-	totalen += len;
-	page += len;
-	len = sprintf(page, "EBASE: 0x%08lx\n", ebase);
-	totalen += len;
-	page += len;
-	len = sprintf(page, "Counter Interrupts taken per CPU (TC)\n");
-	totalen += len;
-	page += len;
-	for (i=0; i < NR_CPUS; i++) {
-		len = sprintf(page, "%d: %ld\n", i, smtc_cpu_stats[i].timerints);
-		totalen += len;
-		page += len;
-	}
-	len = sprintf(page, "Self-IPIs by CPU:\n");
-	totalen += len;
-	page += len;
-	for(i = 0; i < NR_CPUS; i++) {
-		len = sprintf(page, "%d: %ld\n", i, smtc_cpu_stats[i].selfipis);
-		totalen += len;
-		page += len;
-	}
-	len = sprintf(page, "%d Recoveries of \"stolen\" FPU\n",
-		      atomic_read(&smtc_fpu_recoveries));
-	totalen += len;
-	page += len;
-
-	return totalen;
+	seq_printf(m, "SMTC Status Word: 0x%08x\n", smtc_status);
+	seq_printf(m, "Config7: 0x%08x\n", read_c0_config7());
+	seq_printf(m, "EBASE: 0x%08lx\n", ebase);
+	seq_printf(m, "Counter Interrupts taken per CPU (TC)\n");
+	for (i=0; i < NR_CPUS; i++)
+		seq_printf(m, "%d: %ld\n", i, smtc_cpu_stats[i].timerints);
+	seq_printf(m, "Self-IPIs by CPU:\n");
+	for(i = 0; i < NR_CPUS; i++)
+		seq_printf(m, "%d: %ld\n", i, smtc_cpu_stats[i].selfipis);
+	seq_printf(m, "%d Recoveries of \"stolen\" FPU\n",
+		   atomic_read(&smtc_fpu_recoveries));
+	return 0;
 }
 
+static int smtc_proc_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, smtc_proc_show, NULL);
+}
+
+static const struct file_operations smtc_proc_fops = {
+	.open		= smtc_proc_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= seq_release,
+};
+
 void init_smtc_stats(void)
 {
 	int i;
@@ -86,6 +75,5 @@
 
 	atomic_set(&smtc_fpu_recoveries, 0);
 
-	smtc_stats = create_proc_read_entry("smtc", 0444, NULL,
-					    proc_read_smtc, NULL);
+	proc_create("smtc", 0444, NULL, &smtc_proc_fops);
 }
diff --git a/arch/mips/lasat/picvue_proc.c b/arch/mips/lasat/picvue_proc.c
index c592bc8..638c5db 100644
--- a/arch/mips/lasat/picvue_proc.c
+++ b/arch/mips/lasat/picvue_proc.c
@@ -58,13 +58,13 @@
 
 static int pvc_line_proc_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, pvc_line_proc_show, PDE(inode)->data);
+	return single_open(file, pvc_line_proc_show, PDE_DATA(inode));
 }
 
 static ssize_t pvc_line_proc_write(struct file *file, const char __user *buf,
 				   size_t count, loff_t *pos)
 {
-	int lineno = *(int *)PDE(file_inode(file))->data;
+	int lineno = *(int *)PDE_DATA(file_inode(file));
 	char kbuf[PVC_LINELEN];
 	size_t len;
 
diff --git a/arch/mips/mm/init.c b/arch/mips/mm/init.c
index 3d0346d..9b973e0 100644
--- a/arch/mips/mm/init.c
+++ b/arch/mips/mm/init.c
@@ -29,6 +29,7 @@
 #include <linux/pfn.h>
 #include <linux/hardirq.h>
 #include <linux/gfp.h>
+#include <linux/kcore.h>
 
 #include <asm/asm-offsets.h>
 #include <asm/bootinfo.h>
diff --git a/arch/mips/pci/ops-pmcmsp.c b/arch/mips/pci/ops-pmcmsp.c
index d0b6f83..4eaab63 100644
--- a/arch/mips/pci/ops-pmcmsp.c
+++ b/arch/mips/pci/ops-pmcmsp.c
@@ -53,56 +53,51 @@
 
 /*****************************************************************************
  *
- *  FUNCTION: read_msp_pci_counts
+ *  FUNCTION: show_msp_pci_counts
  *  _________________________________________________________________________
  *
  *  DESCRIPTION: Prints the count of how many times each PCI
  *		 interrupt has asserted. Can be invoked by the
  *		 /proc filesystem.
  *
- *  INPUTS:	 page	 - part of STDOUT calculation
- *		 off	 - part of STDOUT calculation
- *		 count	 - part of STDOUT calculation
- *		 data	 - unused
+ *  INPUTS:	 m	 - synthetic file construction data
+ *		 v	 - iterator
  *
- *  OUTPUTS:	 start	 - new start location
- *		 eof	 - end of file pointer
- *
- *  RETURNS:	 len	 - STDOUT length
+ *  RETURNS:	 0 or error
  *
  ****************************************************************************/
-static int read_msp_pci_counts(char *page, char **start, off_t off,
-				int count, int *eof, void *data)
+static int show_msp_pci_counts(struct seq_file *m, void *v)
 {
 	int i;
-	int len = 0;
 	unsigned int intcount, total = 0;
 
 	for (i = 0; i < 32; ++i) {
 		intcount = pci_int_count[i];
 		if (intcount != 0) {
-			len += sprintf(page + len, "[%d] = %u\n", i, intcount);
+			seq_printf(m, "[%d] = %u\n", i, intcount);
 			total += intcount;
 		}
 	}
 
-	len += sprintf(page + len, "total = %u\n", total);
-	if (len <= off+count)
-		*eof = 1;
-
-	*start = page + off;
-	len -= off;
-	if (len > count)
-		len = count;
-	if (len < 0)
-		len = 0;
-
-	return len;
+	seq_printf(m, "total = %u\n", total);
+	return 0;
 }
 
+static int msp_pci_rd_cnt_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, show_msp_pci_counts, NULL);
+}
+
+static const struct file_operations msp_pci_rd_cnt_fops = {
+	.open		= msp_pci_rd_cnt_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= seq_release,
+};
+
 /*****************************************************************************
  *
- *  FUNCTION: gen_pci_cfg_wr
+ *  FUNCTION: gen_pci_cfg_wr_show
  *  _________________________________________________________________________
  *
  *  DESCRIPTION: Generates a configuration write cycle for debug purposes.
@@ -112,37 +107,30 @@
  *		 PCI bus.  Intent is that this function by invocable from
  *		 the /proc filesystem.
  *
- *  INPUTS:	 page	 - part of STDOUT calculation
- *		 off	 - part of STDOUT calculation
- *		 count	 - part of STDOUT calculation
- *		 data	 - unused
+ *  INPUTS:	 m	 - synthetic file construction data
+ *		 v	 - iterator
  *
- *  OUTPUTS:	 start	 - new start location
- *		 eof	 - end of file pointer
- *
- *  RETURNS:	 len	 - STDOUT length
+ *  RETURNS:	 0 or error
  *
  ****************************************************************************/
-static int gen_pci_cfg_wr(char *page, char **start, off_t off,
-				int count, int *eof, void *data)
+static int gen_pci_cfg_wr_show(struct seq_file *m, void *v)
 {
 	unsigned char where = 0; /* Write to static Device/Vendor ID */
 	unsigned char bus_num = 0; /* Bus 0 */
 	unsigned char dev_fn = 0xF; /* Arbitrary device number */
 	u32 wr_data = 0xFF00AA00; /* Arbitrary data */
 	struct msp_pci_regs *preg = (void *)PCI_BASE_REG;
-	int len = 0;
 	unsigned long value;
 	int intr;
 
-	len += sprintf(page + len, "PMC MSP PCI: Beginning\n");
+	seq_puts(m, "PMC MSP PCI: Beginning\n");
 
 	if (proc_init == 0) {
 		pci_proc_init();
 		proc_init = ~0;
 	}
 
-	len += sprintf(page + len, "PMC MSP PCI: Before Cfg Wr\n");
+	seq_puts(m, "PMC MSP PCI: Before Cfg Wr\n");
 
 	/*
 	 * Generate PCI Configuration Write Cycle
@@ -168,21 +156,22 @@
 	 */
 	intr = preg->if_status;
 
-	len += sprintf(page + len, "PMC MSP PCI: After Cfg Wr\n");
-
-	/* Handle STDOUT calculations */
-	if (len <= off+count)
-		*eof = 1;
-	*start = page + off;
-	len -= off;
-	if (len > count)
-		len = count;
-	if (len < 0)
-		len = 0;
-
-	return len;
+	seq_puts(m, "PMC MSP PCI: After Cfg Wr\n");
+	return 0;
 }
 
+static int gen_pci_cfg_wr_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, gen_pci_cfg_wr_show, NULL);
+}
+
+static const struct file_operations gen_pci_cfg_wr_fops = {
+	.open		= gen_pci_cfg_wr_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= seq_release,
+};
+
 /*****************************************************************************
  *
  *  FUNCTION: pci_proc_init
@@ -199,10 +188,8 @@
  ****************************************************************************/
 static void pci_proc_init(void)
 {
-	create_proc_read_entry("pmc_msp_pci_rd_cnt", 0, NULL,
-				read_msp_pci_counts, NULL);
-	create_proc_read_entry("pmc_msp_pci_cfg_wr", 0, NULL,
-				gen_pci_cfg_wr, NULL);
+	proc_create("pmc_msp_pci_rd_cnt", 0, NULL, &msp_pci_rd_cnt_fops);
+	proc_create("pmc_msp_pci_cfg_wr", 0, NULL, &gen_pci_cfg_wr_fops);
 }
 #endif /* CONFIG_PROC_FS && PCI_COUNTERS */
 
diff --git a/arch/mips/sibyte/sb1250/bus_watcher.c b/arch/mips/sibyte/sb1250/bus_watcher.c
index e651105..cb1e3cb 100644
--- a/arch/mips/sibyte/sb1250/bus_watcher.c
+++ b/arch/mips/sibyte/sb1250/bus_watcher.c
@@ -30,6 +30,7 @@
 #include <linux/interrupt.h>
 #include <linux/sched.h>
 #include <linux/proc_fs.h>
+#include <linux/seq_file.h>
 #include <asm/io.h>
 
 #include <asm/sibyte/sb1250.h>
@@ -99,63 +100,60 @@
 		printk("Bus watcher indicates no error\n");
 }
 
-static int bw_print_buffer(char *page, struct bw_stats_struct *stats)
-{
-	int len;
-
-	len = sprintf(page, "SiByte Bus Watcher statistics\n");
-	len += sprintf(page+len, "-----------------------------\n");
-	len += sprintf(page+len, "L2-d-cor %8ld\nL2-d-bad %8ld\n",
-		       stats->l2_cor_d, stats->l2_bad_d);
-	len += sprintf(page+len, "L2-t-cor %8ld\nL2-t-bad %8ld\n",
-		       stats->l2_cor_t, stats->l2_bad_t);
-	len += sprintf(page+len, "MC-d-cor %8ld\nMC-d-bad %8ld\n",
-		       stats->mem_cor_d, stats->mem_bad_d);
-	len += sprintf(page+len, "IO-err   %8ld\n", stats->bus_error);
-	len += sprintf(page+len, "\nLast recorded signature:\n");
-	len += sprintf(page+len, "Request %02x from %d, answered by %d with Dcode %d\n",
-		       (unsigned int)(G_SCD_BERR_TID(stats->status) & 0x3f),
-		       (int)(G_SCD_BERR_TID(stats->status) >> 6),
-		       (int)G_SCD_BERR_RID(stats->status),
-		       (int)G_SCD_BERR_DCODE(stats->status));
-	/* XXXKW indicate multiple errors between printings, or stats
-	   collection (or both)? */
-	if (stats->status & M_SCD_BERR_MULTERRS)
-		len += sprintf(page+len, "Multiple errors observed since last check.\n");
-	if (stats->status_printed) {
-		len += sprintf(page+len, "(no change since last printing)\n");
-	} else {
-		stats->status_printed = 1;
-	}
-
-	return len;
-}
-
 #ifdef CONFIG_PROC_FS
 
 /* For simplicity, I want to assume a single read is required each
    time */
-static int bw_read_proc(char *page, char **start, off_t off,
-			int count, int *eof, void *data)
+static int bw_proc_show(struct seq_file *m, void *v)
 {
-	int len;
+	struct bw_stats_struct *stats = m->private;
 
-	if (off == 0) {
-		len = bw_print_buffer(page, data);
-		*start = page;
+	seq_puts(m, "SiByte Bus Watcher statistics\n");
+	seq_puts(m, "-----------------------------\n");
+	seq_printf(m, "L2-d-cor %8ld\nL2-d-bad %8ld\n",
+		   stats->l2_cor_d, stats->l2_bad_d);
+	seq_printf(m, "L2-t-cor %8ld\nL2-t-bad %8ld\n",
+		   stats->l2_cor_t, stats->l2_bad_t);
+	seq_printf(m, "MC-d-cor %8ld\nMC-d-bad %8ld\n",
+		   stats->mem_cor_d, stats->mem_bad_d);
+	seq_printf(m, "IO-err   %8ld\n", stats->bus_error);
+	seq_puts(m, "\nLast recorded signature:\n");
+	seq_printf(m, "Request %02x from %d, answered by %d with Dcode %d\n",
+		   (unsigned int)(G_SCD_BERR_TID(stats->status) & 0x3f),
+		   (int)(G_SCD_BERR_TID(stats->status) >> 6),
+		   (int)G_SCD_BERR_RID(stats->status),
+		   (int)G_SCD_BERR_DCODE(stats->status));
+	/* XXXKW indicate multiple errors between printings, or stats
+	   collection (or both)? */
+	if (stats->status & M_SCD_BERR_MULTERRS)
+		seq_puts(m, "Multiple errors observed since last check.\n");
+	if (stats->status_printed) {
+		seq_puts(m, "(no change since last printing)\n");
 	} else {
-		len = 0;
-		*eof = 1;
+		stats->status_printed = 1;
 	}
-	return len;
+
+	return 0;
 }
 
+static int bw_proc_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, bw_proc_show, PDE_DATA(inode));
+}
+
+static const struct file_operations bw_proc_fops = {
+	.open		= bw_proc_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= seq_release,
+};
+
 static void create_proc_decoder(struct bw_stats_struct *stats)
 {
 	struct proc_dir_entry *ent;
 
-	ent = create_proc_read_entry("bus_watcher", S_IWUSR | S_IRUGO, NULL,
-				     bw_read_proc, stats);
+	ent = proc_create_data("bus_watcher", S_IWUSR | S_IRUGO, NULL,
+			       &bw_proc_fops, stats);
 	if (!ent) {
 		printk(KERN_INFO "Unable to initialize bus_watcher /proc entry\n");
 		return;
@@ -210,11 +208,6 @@
 	stats->bus_error += G_SCD_MEM_BUSERR(cntr);
 	csr_out32(0, IOADDR(A_BUS_MEM_IO_ERRORS));
 
-#ifndef CONFIG_PROC_FS
-	bw_print_buffer(bw_buf, stats);
-	printk(bw_buf);
-#endif
-
 	return IRQ_HANDLED;
 }
 
diff --git a/arch/parisc/kernel/pdc_chassis.c b/arch/parisc/kernel/pdc_chassis.c
index d47ba1a..8fa314f 100644
--- a/arch/parisc/kernel/pdc_chassis.c
+++ b/arch/parisc/kernel/pdc_chassis.c
@@ -30,11 +30,13 @@
 #endif
 
 #include <linux/init.h>
+#include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/reboot.h>
 #include <linux/notifier.h>
 #include <linux/cache.h>
 #include <linux/proc_fs.h>
+#include <linux/seq_file.h>
 
 #include <asm/pdc_chassis.h>
 #include <asm/processor.h>
@@ -244,38 +246,38 @@
 
 #ifdef CONFIG_PDC_CHASSIS_WARN
 #ifdef CONFIG_PROC_FS
-static int pdc_chassis_warn_pread(char *page, char **start, off_t off,
-		int count, int *eof, void *data)
+static int pdc_chassis_warn_show(struct seq_file *m, void *v)
 {
-	char *out = page;
-	int len, ret;
 	unsigned long warn;
 	u32 warnreg;
 
-	ret = pdc_chassis_warn(&warn);
-	if (ret != PDC_OK)
+	if (pdc_chassis_warn(&warn) != PDC_OK)
 		return -EIO;
 
 	warnreg = (warn & 0xFFFFFFFF);
 
 	if ((warnreg >> 24) & 0xFF)
-		out += sprintf(out, "Chassis component failure! (eg fan or PSU): 0x%.2x\n", ((warnreg >> 24) & 0xFF));
+		seq_printf(m, "Chassis component failure! (eg fan or PSU): 0x%.2x\n",
+			   (warnreg >> 24) & 0xFF);
 
-	out += sprintf(out, "Battery: %s\n", (warnreg & 0x04) ? "Low!" : "OK");
-	out += sprintf(out, "Temp low: %s\n", (warnreg & 0x02) ? "Exceeded!" : "OK");
-	out += sprintf(out, "Temp mid: %s\n", (warnreg & 0x01) ? "Exceeded!" : "OK");
-
-	len = out - page - off;
-	if (len < count) {
-		*eof = 1;
-		if (len <= 0) return 0;
-	} else {
-		len = count;
-	}
-	*start = page + off;
-	return len;
+	seq_printf(m, "Battery: %s\n", (warnreg & 0x04) ? "Low!" : "OK");
+	seq_printf(m, "Temp low: %s\n", (warnreg & 0x02) ? "Exceeded!" : "OK");
+	seq_printf(m, "Temp mid: %s\n", (warnreg & 0x01) ? "Exceeded!" : "OK");
+	return 0;
 }
 
+static int pdc_chassis_warn_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, pdc_chassis_warn_show, NULL);
+}
+
+static const struct file_operations pdc_chassis_warn_fops = {
+	.open		= pdc_chassis_warn_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= seq_release,
+};
+
 static int __init pdc_chassis_create_procfs(void)
 {
 	unsigned long test;
@@ -290,8 +292,7 @@
 
 	printk(KERN_INFO "Enabling PDC chassis warnings support v%s\n",
 			PDC_CHASSIS_VER);
-	create_proc_read_entry("chassis", 0400, NULL, pdc_chassis_warn_pread,
-				NULL);
+	proc_create("chassis", 0400, NULL, &pdc_chassis_warn_fops);
 	return 0;
 }
 
diff --git a/arch/powerpc/kernel/lparcfg.c b/arch/powerpc/kernel/lparcfg.c
index f5725bc..801a757 100644
--- a/arch/powerpc/kernel/lparcfg.c
+++ b/arch/powerpc/kernel/lparcfg.c
@@ -41,8 +41,6 @@
 
 /* #define LPARCFG_DEBUG */
 
-static struct proc_dir_entry *proc_ppc64_lparcfg;
-
 /*
  * Track sum of all purrs across all processors. This is used to further
  * calculate usage values by different applications
@@ -688,27 +686,22 @@
 
 static int __init lparcfg_init(void)
 {
-	struct proc_dir_entry *ent;
 	umode_t mode = S_IRUSR | S_IRGRP | S_IROTH;
 
 	/* Allow writing if we have FW_FEATURE_SPLPAR */
 	if (firmware_has_feature(FW_FEATURE_SPLPAR))
 		mode |= S_IWUSR;
 
-	ent = proc_create("powerpc/lparcfg", mode, NULL, &lparcfg_fops);
-	if (!ent) {
+	if (!proc_create("powerpc/lparcfg", mode, NULL, &lparcfg_fops)) {
 		printk(KERN_ERR "Failed to create powerpc/lparcfg\n");
 		return -EIO;
 	}
-
-	proc_ppc64_lparcfg = ent;
 	return 0;
 }
 
 static void __exit lparcfg_cleanup(void)
 {
-	if (proc_ppc64_lparcfg)
-		remove_proc_entry("lparcfg", proc_ppc64_lparcfg->parent);
+	remove_proc_subtree("powerpc/lparcfg", NULL);
 }
 
 module_init(lparcfg_init);
diff --git a/arch/powerpc/kernel/proc_powerpc.c b/arch/powerpc/kernel/proc_powerpc.c
index f19d0bd..feb8580 100644
--- a/arch/powerpc/kernel/proc_powerpc.c
+++ b/arch/powerpc/kernel/proc_powerpc.c
@@ -32,8 +32,6 @@
 static loff_t page_map_seek( struct file *file, loff_t off, int whence)
 {
 	loff_t new;
-	struct proc_dir_entry *dp = PDE(file_inode(file));
-
 	switch(whence) {
 	case 0:
 		new = off;
@@ -42,12 +40,12 @@
 		new = file->f_pos + off;
 		break;
 	case 2:
-		new = dp->size + off;
+		new = PAGE_SIZE + off;
 		break;
 	default:
 		return -EINVAL;
 	}
-	if ( new < 0 || new > dp->size )
+	if ( new < 0 || new > PAGE_SIZE )
 		return -EINVAL;
 	return (file->f_pos = new);
 }
@@ -55,19 +53,18 @@
 static ssize_t page_map_read( struct file *file, char __user *buf, size_t nbytes,
 			      loff_t *ppos)
 {
-	struct proc_dir_entry *dp = PDE(file_inode(file));
-	return simple_read_from_buffer(buf, nbytes, ppos, dp->data, dp->size);
+	return simple_read_from_buffer(buf, nbytes, ppos,
+			PDE_DATA(file_inode(file)), PAGE_SIZE);
 }
 
 static int page_map_mmap( struct file *file, struct vm_area_struct *vma )
 {
-	struct proc_dir_entry *dp = PDE(file_inode(file));
-
-	if ((vma->vm_end - vma->vm_start) > dp->size)
+	if ((vma->vm_end - vma->vm_start) > PAGE_SIZE)
 		return -EINVAL;
 
-	remap_pfn_range(vma, vma->vm_start, __pa(dp->data) >> PAGE_SHIFT,
-						dp->size, vma->vm_page_prot);
+	remap_pfn_range(vma, vma->vm_start,
+			__pa(PDE_DATA(file_inode(file))) >> PAGE_SHIFT,
+			PAGE_SIZE, vma->vm_page_prot);
 	return 0;
 }
 
@@ -86,7 +83,7 @@
 			       &page_map_fops, vdso_data);
 	if (!pde)
 		return 1;
-	pde->size = PAGE_SIZE;
+	proc_set_size(pde, PAGE_SIZE);
 
 	return 0;
 }
diff --git a/arch/powerpc/kernel/rtas_flash.c b/arch/powerpc/kernel/rtas_flash.c
index c642f01..5b77026 100644
--- a/arch/powerpc/kernel/rtas_flash.c
+++ b/arch/powerpc/kernel/rtas_flash.c
@@ -102,9 +102,10 @@
 
 #define FLASH_BLOCK_LIST_VERSION (1UL)
 
-/* Local copy of the flash block list.
- * We only allow one open of the flash proc file and create this
- * list as we go.  The rtas_firmware_flash_list varable will be
+/*
+ * Local copy of the flash block list.
+ *
+ * The rtas_firmware_flash_list varable will be
  * set once the data is fully read.
  *
  * For convenience as we build the list we use virtual addrs,
@@ -125,23 +126,23 @@
 struct rtas_manage_flash_t
 {
 	int status;			/* Returned status */
-	unsigned int op;		/* Reject or commit image */
 };
 
 /* Status int must be first member of struct */
 struct rtas_validate_flash_t
 {
 	int status;		 	/* Returned status */	
-	char buf[VALIDATE_BUF_SIZE]; 	/* Candidate image buffer */
+	char *buf;			/* Candidate image buffer */
 	unsigned int buf_size;		/* Size of image buf */
 	unsigned int update_results;	/* Update results token */
 };
 
-static DEFINE_SPINLOCK(flash_file_open_lock);
-static struct proc_dir_entry *firmware_flash_pde;
-static struct proc_dir_entry *firmware_update_pde;
-static struct proc_dir_entry *validate_pde;
-static struct proc_dir_entry *manage_pde;
+static struct rtas_update_flash_t rtas_update_flash_data;
+static struct rtas_manage_flash_t rtas_manage_flash_data;
+static struct rtas_validate_flash_t rtas_validate_flash_data;
+static DEFINE_MUTEX(rtas_update_flash_mutex);
+static DEFINE_MUTEX(rtas_manage_flash_mutex);
+static DEFINE_MUTEX(rtas_validate_flash_mutex);
 
 /* Do simple sanity checks on the flash image. */
 static int flash_list_valid(struct flash_block_list *flist)
@@ -191,10 +192,10 @@
 
 static int rtas_flash_release(struct inode *inode, struct file *file)
 {
-	struct proc_dir_entry *dp = PDE(file_inode(file));
-	struct rtas_update_flash_t *uf;
-	
-	uf = (struct rtas_update_flash_t *) dp->data;
+	struct rtas_update_flash_t *const uf = &rtas_update_flash_data;
+
+	mutex_lock(&rtas_update_flash_mutex);
+
 	if (uf->flist) {    
 		/* File was opened in write mode for a new flash attempt */
 		/* Clear saved list */
@@ -214,13 +215,14 @@
 		uf->flist = NULL;
 	}
 
-	atomic_dec(&dp->count);
+	mutex_unlock(&rtas_update_flash_mutex);
 	return 0;
 }
 
-static void get_flash_status_msg(int status, char *buf)
+static size_t get_flash_status_msg(int status, char *buf)
 {
-	char *msg;
+	const char *msg;
+	size_t len;
 
 	switch (status) {
 	case FLASH_AUTH:
@@ -242,34 +244,51 @@
 		msg = "ready: firmware image ready for flash on reboot\n";
 		break;
 	default:
-		sprintf(buf, "error: unexpected status value %d\n", status);
-		return;
+		return sprintf(buf, "error: unexpected status value %d\n",
+			       status);
 	}
 
-	strcpy(buf, msg);	
+	len = strlen(msg);
+	memcpy(buf, msg, len + 1);
+	return len;
 }
 
 /* Reading the proc file will show status (not the firmware contents) */
-static ssize_t rtas_flash_read(struct file *file, char __user *buf,
-			       size_t count, loff_t *ppos)
+static ssize_t rtas_flash_read_msg(struct file *file, char __user *buf,
+				   size_t count, loff_t *ppos)
 {
-	struct proc_dir_entry *dp = PDE(file_inode(file));
-	struct rtas_update_flash_t *uf;
+	struct rtas_update_flash_t *const uf = &rtas_update_flash_data;
 	char msg[RTAS_MSG_MAXLEN];
+	size_t len;
+	int status;
 
-	uf = dp->data;
+	mutex_lock(&rtas_update_flash_mutex);
+	status = uf->status;
+	mutex_unlock(&rtas_update_flash_mutex);
 
-	if (!strcmp(dp->name, FIRMWARE_FLASH_NAME)) {
-		get_flash_status_msg(uf->status, msg);
-	} else {	   /* FIRMWARE_UPDATE_NAME */
-		sprintf(msg, "%d\n", uf->status);
-	}
+	/* Read as text message */
+	len = get_flash_status_msg(status, msg);
+	return simple_read_from_buffer(buf, count, ppos, msg, len);
+}
 
+static ssize_t rtas_flash_read_num(struct file *file, char __user *buf,
+				   size_t count, loff_t *ppos)
+{
+	struct rtas_update_flash_t *const uf = &rtas_update_flash_data;
+	char msg[RTAS_MSG_MAXLEN];
+	int status;
+
+	mutex_lock(&rtas_update_flash_mutex);
+	status = uf->status;
+	mutex_unlock(&rtas_update_flash_mutex);
+
+	/* Read as number */
+	sprintf(msg, "%d\n", status);
 	return simple_read_from_buffer(buf, count, ppos, msg, strlen(msg));
 }
 
 /* constructor for flash_block_cache */
-void rtas_block_ctor(void *ptr)
+static void rtas_block_ctor(void *ptr)
 {
 	memset(ptr, 0, RTAS_BLK_SIZE);
 }
@@ -282,16 +301,15 @@
 static ssize_t rtas_flash_write(struct file *file, const char __user *buffer,
 				size_t count, loff_t *off)
 {
-	struct proc_dir_entry *dp = PDE(file_inode(file));
-	struct rtas_update_flash_t *uf;
+	struct rtas_update_flash_t *const uf = &rtas_update_flash_data;
 	char *p;
-	int next_free;
+	int next_free, rc;
 	struct flash_block_list *fl;
 
-	uf = (struct rtas_update_flash_t *) dp->data;
+	mutex_lock(&rtas_update_flash_mutex);
 
 	if (uf->status == FLASH_AUTH || count == 0)
-		return count;	/* discard data */
+		goto out;	/* discard data */
 
 	/* In the case that the image is not ready for flashing, the memory
 	 * allocated for the block list will be freed upon the release of the 
@@ -300,7 +318,7 @@
 	if (uf->flist == NULL) {
 		uf->flist = kmem_cache_alloc(flash_block_cache, GFP_KERNEL);
 		if (!uf->flist)
-			return -ENOMEM;
+			goto nomem;
 	}
 
 	fl = uf->flist;
@@ -311,7 +329,7 @@
 		/* Need to allocate another block_list */
 		fl->next = kmem_cache_alloc(flash_block_cache, GFP_KERNEL);
 		if (!fl->next)
-			return -ENOMEM;
+			goto nomem;
 		fl = fl->next;
 		next_free = 0;
 	}
@@ -320,52 +338,37 @@
 		count = RTAS_BLK_SIZE;
 	p = kmem_cache_alloc(flash_block_cache, GFP_KERNEL);
 	if (!p)
-		return -ENOMEM;
+		goto nomem;
 	
 	if(copy_from_user(p, buffer, count)) {
 		kmem_cache_free(flash_block_cache, p);
-		return -EFAULT;
+		rc = -EFAULT;
+		goto error;
 	}
 	fl->blocks[next_free].data = p;
 	fl->blocks[next_free].length = count;
 	fl->num_blocks++;
-
+out:
+	mutex_unlock(&rtas_update_flash_mutex);
 	return count;
+
+nomem:
+	rc = -ENOMEM;
+error:
+	mutex_unlock(&rtas_update_flash_mutex);
+	return rc;
 }
 
-static int rtas_excl_open(struct inode *inode, struct file *file)
-{
-	struct proc_dir_entry *dp = PDE(inode);
-
-	/* Enforce exclusive open with use count of PDE */
-	spin_lock(&flash_file_open_lock);
-	if (atomic_read(&dp->count) > 2) {
-		spin_unlock(&flash_file_open_lock);
-		return -EBUSY;
-	}
-
-	atomic_inc(&dp->count);
-	spin_unlock(&flash_file_open_lock);
-	
-	return 0;
-}
-
-static int rtas_excl_release(struct inode *inode, struct file *file)
-{
-	struct proc_dir_entry *dp = PDE(inode);
-
-	atomic_dec(&dp->count);
-
-	return 0;
-}
-
-static void manage_flash(struct rtas_manage_flash_t *args_buf)
+/*
+ * Flash management routines.
+ */
+static void manage_flash(struct rtas_manage_flash_t *args_buf, unsigned int op)
 {
 	s32 rc;
 
 	do {
-		rc = rtas_call(rtas_token("ibm,manage-flash-image"), 1, 
-			       1, NULL, args_buf->op);
+		rc = rtas_call(rtas_token("ibm,manage-flash-image"), 1, 1,
+			       NULL, op);
 	} while (rtas_busy_delay(rc));
 
 	args_buf->status = rc;
@@ -374,55 +377,62 @@
 static ssize_t manage_flash_read(struct file *file, char __user *buf,
 			       size_t count, loff_t *ppos)
 {
-	struct proc_dir_entry *dp = PDE(file_inode(file));
-	struct rtas_manage_flash_t *args_buf;
+	struct rtas_manage_flash_t *const args_buf = &rtas_manage_flash_data;
 	char msg[RTAS_MSG_MAXLEN];
-	int msglen;
+	int msglen, status;
 
-	args_buf = dp->data;
-	if (args_buf == NULL)
-		return 0;
+	mutex_lock(&rtas_manage_flash_mutex);
+	status = args_buf->status;
+	mutex_unlock(&rtas_manage_flash_mutex);
 
-	msglen = sprintf(msg, "%d\n", args_buf->status);
-
+	msglen = sprintf(msg, "%d\n", status);
 	return simple_read_from_buffer(buf, count, ppos, msg, msglen);
 }
 
 static ssize_t manage_flash_write(struct file *file, const char __user *buf,
 				size_t count, loff_t *off)
 {
-	struct proc_dir_entry *dp = PDE(file_inode(file));
-	struct rtas_manage_flash_t *args_buf;
-	const char reject_str[] = "0";
-	const char commit_str[] = "1";
+	struct rtas_manage_flash_t *const args_buf = &rtas_manage_flash_data;
+	static const char reject_str[] = "0";
+	static const char commit_str[] = "1";
 	char stkbuf[10];
-	int op;
+	int op, rc;
 
-	args_buf = (struct rtas_manage_flash_t *) dp->data;
+	mutex_lock(&rtas_manage_flash_mutex);
+
 	if ((args_buf->status == MANAGE_AUTH) || (count == 0))
-		return count;
+		goto out;
 		
 	op = -1;
 	if (buf) {
 		if (count > 9) count = 9;
-		if (copy_from_user (stkbuf, buf, count)) {
-			return -EFAULT;
-		}
+		rc = -EFAULT;
+		if (copy_from_user (stkbuf, buf, count))
+			goto error;
 		if (strncmp(stkbuf, reject_str, strlen(reject_str)) == 0) 
 			op = RTAS_REJECT_TMP_IMG;
 		else if (strncmp(stkbuf, commit_str, strlen(commit_str)) == 0) 
 			op = RTAS_COMMIT_TMP_IMG;
 	}
 	
-	if (op == -1)   /* buf is empty, or contains invalid string */
-		return -EINVAL;
+	if (op == -1) {   /* buf is empty, or contains invalid string */
+		rc = -EINVAL;
+		goto error;
+	}
 
-	args_buf->op = op;
-	manage_flash(args_buf);
-
+	manage_flash(args_buf, op);
+out:
+	mutex_unlock(&rtas_manage_flash_mutex);
 	return count;
+
+error:
+	mutex_unlock(&rtas_manage_flash_mutex);
+	return rc;
 }
 
+/*
+ * Validation routines.
+ */
 static void validate_flash(struct rtas_validate_flash_t *args_buf)
 {
 	int token = rtas_token("ibm,validate-flash-image");
@@ -462,14 +472,14 @@
 static ssize_t validate_flash_read(struct file *file, char __user *buf,
 			       size_t count, loff_t *ppos)
 {
-	struct proc_dir_entry *dp = PDE(file_inode(file));
-	struct rtas_validate_flash_t *args_buf;
+	struct rtas_validate_flash_t *const args_buf =
+		&rtas_validate_flash_data;
 	char msg[RTAS_MSG_MAXLEN];
 	int msglen;
 
-	args_buf = dp->data;
-
+	mutex_lock(&rtas_validate_flash_mutex);
 	msglen = get_validate_flash_msg(args_buf, msg);
+	mutex_unlock(&rtas_validate_flash_mutex);
 
 	return simple_read_from_buffer(buf, count, ppos, msg, msglen);
 }
@@ -477,24 +487,18 @@
 static ssize_t validate_flash_write(struct file *file, const char __user *buf,
 				    size_t count, loff_t *off)
 {
-	struct proc_dir_entry *dp = PDE(file_inode(file));
-	struct rtas_validate_flash_t *args_buf;
+	struct rtas_validate_flash_t *const args_buf =
+		&rtas_validate_flash_data;
 	int rc;
 
-	args_buf = (struct rtas_validate_flash_t *) dp->data;
-
-	if (dp->data == NULL) {
-		dp->data = kmalloc(sizeof(struct rtas_validate_flash_t), 
-				GFP_KERNEL);
-		if (dp->data == NULL) 
-			return -ENOMEM;
-	}
+	mutex_lock(&rtas_validate_flash_mutex);
 
 	/* We are only interested in the first 4K of the
 	 * candidate image */
 	if ((*off >= VALIDATE_BUF_SIZE) || 
 		(args_buf->status == VALIDATE_AUTH)) {
 		*off += count;
+		mutex_unlock(&rtas_validate_flash_mutex);
 		return count;
 	}
 
@@ -517,31 +521,29 @@
 	*off += count;
 	rc = count;
 done:
-	if (rc < 0) {
-		kfree(dp->data);
-		dp->data = NULL;
-	}
+	mutex_unlock(&rtas_validate_flash_mutex);
 	return rc;
 }
 
 static int validate_flash_release(struct inode *inode, struct file *file)
 {
-	struct proc_dir_entry *dp = PDE(file_inode(file));
-	struct rtas_validate_flash_t *args_buf;
+	struct rtas_validate_flash_t *const args_buf =
+		&rtas_validate_flash_data;
 
-	args_buf = (struct rtas_validate_flash_t *) dp->data;
+	mutex_lock(&rtas_validate_flash_mutex);
 
 	if (args_buf->status == VALIDATE_READY) {
 		args_buf->buf_size = VALIDATE_BUF_SIZE;
 		validate_flash(args_buf);
 	}
 
-	/* The matching atomic_inc was in rtas_excl_open() */
-	atomic_dec(&dp->count);
-
+	mutex_unlock(&rtas_validate_flash_mutex);
 	return 0;
 }
 
+/*
+ * On-reboot flash update applicator.
+ */
 static void rtas_flash_firmware(int reboot_type)
 {
 	unsigned long image_size;
@@ -634,75 +636,57 @@
 	spin_unlock(&rtas_data_buf_lock);
 }
 
-static void remove_flash_pde(struct proc_dir_entry *dp)
-{
-	if (dp) {
-		kfree(dp->data);
-		remove_proc_entry(dp->name, dp->parent);
-	}
-}
-
-static int initialize_flash_pde_data(const char *rtas_call_name,
-				     size_t buf_size,
-				     struct proc_dir_entry *dp)
-{
+/*
+ * Manifest of proc files to create
+ */
+struct rtas_flash_file {
+	const char *filename;
+	const char *rtas_call_name;
 	int *status;
-	int token;
-
-	dp->data = kzalloc(buf_size, GFP_KERNEL);
-	if (dp->data == NULL)
-		return -ENOMEM;
-
-	/*
-	 * This code assumes that the status int is the first member of the
-	 * struct 
-	 */
-	status = (int *) dp->data;
-	token = rtas_token(rtas_call_name);
-	if (token == RTAS_UNKNOWN_SERVICE)
-		*status = FLASH_AUTH;
-	else
-		*status = FLASH_NO_OP;
-
-	return 0;
-}
-
-static struct proc_dir_entry *create_flash_pde(const char *filename,
-					       const struct file_operations *fops)
-{
-	return proc_create(filename, S_IRUSR | S_IWUSR, NULL, fops);
-}
-
-static const struct file_operations rtas_flash_operations = {
-	.owner		= THIS_MODULE,
-	.read		= rtas_flash_read,
-	.write		= rtas_flash_write,
-	.open		= rtas_excl_open,
-	.release	= rtas_flash_release,
-	.llseek		= default_llseek,
+	const struct file_operations fops;
 };
 
-static const struct file_operations manage_flash_operations = {
-	.owner		= THIS_MODULE,
-	.read		= manage_flash_read,
-	.write		= manage_flash_write,
-	.open		= rtas_excl_open,
-	.release	= rtas_excl_release,
-	.llseek		= default_llseek,
-};
-
-static const struct file_operations validate_flash_operations = {
-	.owner		= THIS_MODULE,
-	.read		= validate_flash_read,
-	.write		= validate_flash_write,
-	.open		= rtas_excl_open,
-	.release	= validate_flash_release,
-	.llseek		= default_llseek,
+static const struct rtas_flash_file rtas_flash_files[] = {
+	{
+		.filename	= "powerpc/rtas/" FIRMWARE_FLASH_NAME,
+		.rtas_call_name	= "ibm,update-flash-64-and-reboot",
+		.status		= &rtas_update_flash_data.status,
+		.fops.read	= rtas_flash_read_msg,
+		.fops.write	= rtas_flash_write,
+		.fops.release	= rtas_flash_release,
+		.fops.llseek	= default_llseek,
+	},
+	{
+		.filename	= "powerpc/rtas/" FIRMWARE_UPDATE_NAME,
+		.rtas_call_name	= "ibm,update-flash-64-and-reboot",
+		.status		= &rtas_update_flash_data.status,
+		.fops.read	= rtas_flash_read_num,
+		.fops.write	= rtas_flash_write,
+		.fops.release	= rtas_flash_release,
+		.fops.llseek	= default_llseek,
+	},
+	{
+		.filename	= "powerpc/rtas/" VALIDATE_FLASH_NAME,
+		.rtas_call_name	= "ibm,validate-flash-image",
+		.status		= &rtas_validate_flash_data.status,
+		.fops.read	= validate_flash_read,
+		.fops.write	= validate_flash_write,
+		.fops.release	= validate_flash_release,
+		.fops.llseek	= default_llseek,
+	},
+	{
+		.filename	= "powerpc/rtas/" MANAGE_FLASH_NAME,
+		.rtas_call_name	= "ibm,manage-flash-image",
+		.status		= &rtas_manage_flash_data.status,
+		.fops.read	= manage_flash_read,
+		.fops.write	= manage_flash_write,
+		.fops.llseek	= default_llseek,
+	}
 };
 
 static int __init rtas_flash_init(void)
 {
-	int rc;
+	int i;
 
 	if (rtas_token("ibm,update-flash-64-and-reboot") ==
 		       RTAS_UNKNOWN_SERVICE) {
@@ -710,93 +694,65 @@
 		return 1;
 	}
 
-	firmware_flash_pde = create_flash_pde("powerpc/rtas/"
-					      FIRMWARE_FLASH_NAME,
-					      &rtas_flash_operations);
-	if (firmware_flash_pde == NULL) {
-		rc = -ENOMEM;
-		goto cleanup;
-	}
-
-	rc = initialize_flash_pde_data("ibm,update-flash-64-and-reboot",
-			 	       sizeof(struct rtas_update_flash_t), 
-				       firmware_flash_pde);
-	if (rc != 0)
-		goto cleanup;
-
-	firmware_update_pde = create_flash_pde("powerpc/rtas/"
-					       FIRMWARE_UPDATE_NAME,
-					       &rtas_flash_operations);
-	if (firmware_update_pde == NULL) {
-		rc = -ENOMEM;
-		goto cleanup;
-	}
-
-	rc = initialize_flash_pde_data("ibm,update-flash-64-and-reboot",
-			 	       sizeof(struct rtas_update_flash_t), 
-				       firmware_update_pde);
-	if (rc != 0)
-		goto cleanup;
-
-	validate_pde = create_flash_pde("powerpc/rtas/" VALIDATE_FLASH_NAME,
-			      		&validate_flash_operations);
-	if (validate_pde == NULL) {
-		rc = -ENOMEM;
-		goto cleanup;
-	}
-
-	rc = initialize_flash_pde_data("ibm,validate-flash-image",
-		                       sizeof(struct rtas_validate_flash_t), 
-				       validate_pde);
-	if (rc != 0)
-		goto cleanup;
-
-	manage_pde = create_flash_pde("powerpc/rtas/" MANAGE_FLASH_NAME,
-				      &manage_flash_operations);
-	if (manage_pde == NULL) {
-		rc = -ENOMEM;
-		goto cleanup;
-	}
-
-	rc = initialize_flash_pde_data("ibm,manage-flash-image",
-			               sizeof(struct rtas_manage_flash_t),
-				       manage_pde);
-	if (rc != 0)
-		goto cleanup;
-
-	rtas_flash_term_hook = rtas_flash_firmware;
+	rtas_validate_flash_data.buf = kzalloc(VALIDATE_BUF_SIZE, GFP_KERNEL);
+	if (!rtas_validate_flash_data.buf)
+		return -ENOMEM;
 
 	flash_block_cache = kmem_cache_create("rtas_flash_cache",
-				RTAS_BLK_SIZE, RTAS_BLK_SIZE, 0,
-				rtas_block_ctor);
+					      RTAS_BLK_SIZE, RTAS_BLK_SIZE, 0,
+					      rtas_block_ctor);
 	if (!flash_block_cache) {
 		printk(KERN_ERR "%s: failed to create block cache\n",
 				__func__);
-		rc = -ENOMEM;
-		goto cleanup;
+		goto enomem_buf;
 	}
+
+	for (i = 0; i < ARRAY_SIZE(rtas_flash_files); i++) {
+		const struct rtas_flash_file *f = &rtas_flash_files[i];
+		int token;
+
+		if (!proc_create(f->filename, S_IRUSR | S_IWUSR, NULL, &f->fops))
+			goto enomem;
+
+		/*
+		 * This code assumes that the status int is the first member of the
+		 * struct
+		 */
+		token = rtas_token(f->rtas_call_name);
+		if (token == RTAS_UNKNOWN_SERVICE)
+			*f->status = FLASH_AUTH;
+		else
+			*f->status = FLASH_NO_OP;
+	}
+
+	rtas_flash_term_hook = rtas_flash_firmware;
 	return 0;
 
-cleanup:
-	remove_flash_pde(firmware_flash_pde);
-	remove_flash_pde(firmware_update_pde);
-	remove_flash_pde(validate_pde);
-	remove_flash_pde(manage_pde);
+enomem:
+	while (--i >= 0) {
+		const struct rtas_flash_file *f = &rtas_flash_files[i];
+		remove_proc_entry(f->filename, NULL);
+	}
 
-	return rc;
+	kmem_cache_destroy(flash_block_cache);
+enomem_buf:
+	kfree(rtas_validate_flash_data.buf);
+	return -ENOMEM;
 }
 
 static void __exit rtas_flash_cleanup(void)
 {
+	int i;
+
 	rtas_flash_term_hook = NULL;
 
-	if (flash_block_cache)
-		kmem_cache_destroy(flash_block_cache);
+	for (i = 0; i < ARRAY_SIZE(rtas_flash_files); i++) {
+		const struct rtas_flash_file *f = &rtas_flash_files[i];
+		remove_proc_entry(f->filename, NULL);
+	}
 
-	remove_flash_pde(firmware_flash_pde);
-	remove_flash_pde(firmware_update_pde);
-	remove_flash_pde(validate_pde);
-	remove_flash_pde(manage_pde);
+	kmem_cache_destroy(flash_block_cache);
+	kfree(rtas_validate_flash_data.buf);
 }
 
 module_init(rtas_flash_init);
diff --git a/arch/powerpc/kvm/book3s_64_mmu_hv.c b/arch/powerpc/kvm/book3s_64_mmu_hv.c
index 8cc18ab..da98e26 100644
--- a/arch/powerpc/kvm/book3s_64_mmu_hv.c
+++ b/arch/powerpc/kvm/book3s_64_mmu_hv.c
@@ -1467,7 +1467,7 @@
 	return 0;
 }
 
-static struct file_operations kvm_htab_fops = {
+static const struct file_operations kvm_htab_fops = {
 	.read		= kvm_htab_read,
 	.write		= kvm_htab_write,
 	.llseek		= default_llseek,
diff --git a/arch/powerpc/kvm/book3s_64_vio.c b/arch/powerpc/kvm/book3s_64_vio.c
index 72ffc89..b2d3f3b 100644
--- a/arch/powerpc/kvm/book3s_64_vio.c
+++ b/arch/powerpc/kvm/book3s_64_vio.c
@@ -92,7 +92,7 @@
 	return 0;
 }
 
-static struct file_operations kvm_spapr_tce_fops = {
+static const struct file_operations kvm_spapr_tce_fops = {
 	.mmap           = kvm_spapr_tce_mmap,
 	.release	= kvm_spapr_tce_release,
 };
diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c
index 80dcc53..b62bd1b 100644
--- a/arch/powerpc/kvm/book3s_hv.c
+++ b/arch/powerpc/kvm/book3s_hv.c
@@ -1483,7 +1483,7 @@
 	return 0;
 }
 
-static struct file_operations kvm_rma_fops = {
+static const struct file_operations kvm_rma_fops = {
 	.mmap           = kvm_rma_mmap,
 	.release	= kvm_rma_release,
 };
diff --git a/arch/powerpc/platforms/cell/spufs/file.c b/arch/powerpc/platforms/cell/spufs/file.c
index 68c57d3..d43d2d0 100644
--- a/arch/powerpc/platforms/cell/spufs/file.c
+++ b/arch/powerpc/platforms/cell/spufs/file.c
@@ -149,7 +149,6 @@
 	return spufs_attr_open(inode, file, __get, __set, __fmt);	\
 }									\
 static const struct file_operations __fops = {				\
-	.owner	 = THIS_MODULE,						\
 	.open	 = __fops ## _open,					\
 	.release = spufs_attr_release,					\
 	.read	 = spufs_attr_read,					\
@@ -2591,7 +2590,6 @@
 }
 
 static const struct file_operations spufs_switch_log_fops = {
-	.owner		= THIS_MODULE,
 	.open		= spufs_switch_log_open,
 	.read		= spufs_switch_log_read,
 	.poll		= spufs_switch_log_poll,
diff --git a/arch/powerpc/platforms/pseries/reconfig.c b/arch/powerpc/platforms/pseries/reconfig.c
index d6491bd..f93cdf5 100644
--- a/arch/powerpc/platforms/pseries/reconfig.c
+++ b/arch/powerpc/platforms/pseries/reconfig.c
@@ -452,7 +452,7 @@
 
 	ent = proc_create("powerpc/ofdt", S_IWUSR, NULL, &ofdt_fops);
 	if (ent)
-		ent->size = 0;
+		proc_set_size(ent, 0);
 
 	return 0;
 }
diff --git a/arch/powerpc/platforms/pseries/scanlog.c b/arch/powerpc/platforms/pseries/scanlog.c
index 47f3cda..b502ab6 100644
--- a/arch/powerpc/platforms/pseries/scanlog.c
+++ b/arch/powerpc/platforms/pseries/scanlog.c
@@ -41,13 +41,12 @@
 
 
 static unsigned int ibm_scan_log_dump;			/* RTAS token */
-static struct proc_dir_entry *proc_ppc64_scan_log_dump;	/* The proc file */
+static unsigned int *scanlog_buffer;			/* The data buffer */
 
 static ssize_t scanlog_read(struct file *file, char __user *buf,
 			    size_t count, loff_t *ppos)
 {
-	struct proc_dir_entry *dp = PDE(file_inode(file));
-	unsigned int *data = (unsigned int *)dp->data;
+	unsigned int *data = scanlog_buffer;
 	int status;
 	unsigned long len, off;
 	unsigned int wait_time;
@@ -135,8 +134,7 @@
 
 static int scanlog_open(struct inode * inode, struct file * file)
 {
-	struct proc_dir_entry *dp = PDE(inode);
-	unsigned int *data = (unsigned int *)dp->data;
+	unsigned int *data = scanlog_buffer;
 
 	if (data[0] != 0) {
 		/* This imperfect test stops a second copy of the
@@ -152,11 +150,9 @@
 
 static int scanlog_release(struct inode * inode, struct file * file)
 {
-	struct proc_dir_entry *dp = PDE(inode);
-	unsigned int *data = (unsigned int *)dp->data;
+	unsigned int *data = scanlog_buffer;
 
 	data[0] = 0;
-
 	return 0;
 }
 
@@ -172,7 +168,6 @@
 static int __init scanlog_init(void)
 {
 	struct proc_dir_entry *ent;
-	void *data;
 	int err = -ENOMEM;
 
 	ibm_scan_log_dump = rtas_token("ibm,scan-log-dump");
@@ -180,29 +175,24 @@
 		return -ENODEV;
 
 	/* Ideally we could allocate a buffer < 4G */
-	data = kzalloc(RTAS_DATA_BUF_SIZE, GFP_KERNEL);
-	if (!data)
+	scanlog_buffer = kzalloc(RTAS_DATA_BUF_SIZE, GFP_KERNEL);
+	if (!scanlog_buffer)
 		goto err;
 
-	ent = proc_create_data("powerpc/rtas/scan-log-dump", S_IRUSR, NULL,
-			       &scanlog_fops, data);
+	ent = proc_create("powerpc/rtas/scan-log-dump", S_IRUSR, NULL,
+			  &scanlog_fops);
 	if (!ent)
 		goto err;
-
-	proc_ppc64_scan_log_dump = ent;
-
 	return 0;
 err:
-	kfree(data);
+	kfree(scanlog_buffer);
 	return err;
 }
 
 static void __exit scanlog_cleanup(void)
 {
-	if (proc_ppc64_scan_log_dump) {
-		kfree(proc_ppc64_scan_log_dump->data);
-		remove_proc_entry("scan-log-dump", proc_ppc64_scan_log_dump->parent);
-	}
+	remove_proc_entry("powerpc/rtas/scan-log-dump", NULL);
+	kfree(scanlog_buffer);
 }
 
 module_init(scanlog_init);
diff --git a/arch/s390/kernel/compat_wrapper.S b/arch/s390/kernel/compat_wrapper.S
index 17644c8..2d72d9e 100644
--- a/arch/s390/kernel/compat_wrapper.S
+++ b/arch/s390/kernel/compat_wrapper.S
@@ -1323,22 +1323,6 @@
 	llgfr	%r6,%r6			# u32
 	jg	compat_sys_keyctl	# branch to system call
 
-ENTRY(compat_sys_preadv_wrapper)
-	llgfr	%r2,%r2			# unsigned long
-	llgtr	%r3,%r3			# compat_iovec *
-	llgfr	%r4,%r4			# unsigned long
-	llgfr	%r5,%r5			# u32
-	llgfr	%r6,%r6			# u32
-	jg	compat_sys_preadv	# branch to system call
-
-ENTRY(compat_sys_pwritev_wrapper)
-	llgfr	%r2,%r2			# unsigned long
-	llgtr	%r3,%r3			# compat_iovec *
-	llgfr	%r4,%r4			# unsigned long
-	llgfr	%r5,%r5			# u32
-	llgfr	%r6,%r6			# u32
-	jg	compat_sys_pwritev	# branch to system call
-
 ENTRY(sys_perf_event_open_wrapper)
 	llgtr	%r2,%r2			# const struct perf_event_attr *
 	lgfr	%r3,%r3			# pid_t
diff --git a/arch/s390/kernel/irq.c b/arch/s390/kernel/irq.c
index 4f5ef629..f7fb589 100644
--- a/arch/s390/kernel/irq.c
+++ b/arch/s390/kernel/irq.c
@@ -162,10 +162,8 @@
 #ifdef CONFIG_PROC_FS
 void init_irq_proc(void)
 {
-	struct proc_dir_entry *root_irq_dir;
-
-	root_irq_dir = proc_mkdir("irq", NULL);
-	create_prof_cpu_mask(root_irq_dir);
+	if (proc_mkdir("irq", NULL))
+		create_prof_cpu_mask();
 }
 #endif
 
diff --git a/arch/s390/kernel/os_info.c b/arch/s390/kernel/os_info.c
index 46480d8..d112fc6 100644
--- a/arch/s390/kernel/os_info.c
+++ b/arch/s390/kernel/os_info.c
@@ -10,6 +10,7 @@
 
 #include <linux/crash_dump.h>
 #include <linux/kernel.h>
+#include <linux/slab.h>
 #include <asm/checksum.h>
 #include <asm/lowcore.h>
 #include <asm/os_info.h>
diff --git a/arch/s390/kernel/syscalls.S b/arch/s390/kernel/syscalls.S
index d2baabe..9f214e9 100644
--- a/arch/s390/kernel/syscalls.S
+++ b/arch/s390/kernel/syscalls.S
@@ -336,8 +336,8 @@
 SYSCALL(sys_pipe2,sys_pipe2,sys_pipe2_wrapper) /* 325 */
 SYSCALL(sys_dup3,sys_dup3,sys_dup3_wrapper)
 SYSCALL(sys_epoll_create1,sys_epoll_create1,sys_epoll_create1_wrapper)
-SYSCALL(sys_preadv,sys_preadv,compat_sys_preadv_wrapper)
-SYSCALL(sys_pwritev,sys_pwritev,compat_sys_pwritev_wrapper)
+SYSCALL(sys_preadv,sys_preadv,compat_sys_preadv)
+SYSCALL(sys_pwritev,sys_pwritev,compat_sys_pwritev)
 SYSCALL(sys_rt_tgsigqueueinfo,sys_rt_tgsigqueueinfo,compat_sys_rt_tgsigqueueinfo) /* 330 */
 SYSCALL(sys_perf_event_open,sys_perf_event_open,sys_perf_event_open_wrapper)
 SYSCALL(sys_fanotify_init,sys_fanotify_init,sys_fanotify_init_wrapper)
diff --git a/arch/score/mm/init.c b/arch/score/mm/init.c
index 1592aad..d8f988a 100644
--- a/arch/score/mm/init.c
+++ b/arch/score/mm/init.c
@@ -31,7 +31,7 @@
 #include <linux/mm.h>
 #include <linux/mman.h>
 #include <linux/pagemap.h>
-#include <linux/proc_fs.h>
+#include <linux/kcore.h>
 #include <linux/sched.h>
 #include <linux/initrd.h>
 
diff --git a/arch/sh/drivers/dma/dma-api.c b/arch/sh/drivers/dma/dma-api.c
index f46848f..851e510 100644
--- a/arch/sh/drivers/dma/dma-api.c
+++ b/arch/sh/drivers/dma/dma-api.c
@@ -13,6 +13,7 @@
 #include <linux/module.h>
 #include <linux/spinlock.h>
 #include <linux/proc_fs.h>
+#include <linux/seq_file.h>
 #include <linux/list.h>
 #include <linux/platform_device.h>
 #include <linux/mm.h>
@@ -308,11 +309,9 @@
 }
 EXPORT_SYMBOL(dma_extend);
 
-static int dma_read_proc(char *buf, char **start, off_t off,
-			 int len, int *eof, void *data)
+static int dma_proc_show(struct seq_file *m, void *v)
 {
-	struct dma_info *info;
-	char *p = buf;
+	struct dma_info *info = v;
 
 	if (list_empty(&registered_dmac_list))
 		return 0;
@@ -332,14 +331,26 @@
 			if (!(channel->flags & DMA_CONFIGURED))
 				continue;
 
-			p += sprintf(p, "%2d: %14s    %s\n", i,
-				     info->name, channel->dev_id);
+			seq_printf(m, "%2d: %14s    %s\n", i,
+				   info->name, channel->dev_id);
 		}
 	}
 
-	return p - buf;
+	return 0;
 }
 
+static int dma_proc_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, dma_proc_show, NULL);
+}
+
+static const struct file_operations dma_proc_fops = {
+	.open		= dma_proc_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= seq_release,
+};
+
 int register_dmac(struct dma_info *info)
 {
 	unsigned int total_channels, i;
@@ -412,8 +423,7 @@
 static int __init dma_api_init(void)
 {
 	printk(KERN_NOTICE "DMA: Registering DMA API.\n");
-	return create_proc_read_entry("dma", 0, 0, dma_read_proc, 0)
-		    ? 0 : -ENOMEM;
+	return proc_create("dma", 0, NULL, &dma_proc_fops) ? 0 : -ENOMEM;
 }
 subsys_initcall(dma_api_init);
 
diff --git a/arch/sh/mm/alignment.c b/arch/sh/mm/alignment.c
index aea1485..ec2b253 100644
--- a/arch/sh/mm/alignment.c
+++ b/arch/sh/mm/alignment.c
@@ -140,7 +140,7 @@
 static ssize_t alignment_proc_write(struct file *file,
 		const char __user *buffer, size_t count, loff_t *pos)
 {
-	int *data = PDE(file_inode(file))->data;
+	int *data = PDE_DATA(file_inode(file));
 	char mode;
 
 	if (count > 0) {
diff --git a/arch/sparc/kernel/ioport.c b/arch/sparc/kernel/ioport.c
index 0f094db..2096468 100644
--- a/arch/sparc/kernel/ioport.c
+++ b/arch/sparc/kernel/ioport.c
@@ -693,7 +693,7 @@
 
 static int sparc_io_proc_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, sparc_io_proc_show, PDE(inode)->data);
+	return single_open(file, sparc_io_proc_show, PDE_DATA(inode));
 }
 
 static const struct file_operations sparc_io_proc_fops = {
diff --git a/arch/sparc/kernel/sun4d_irq.c b/arch/sparc/kernel/sun4d_irq.c
index e490ac9..f8933be 100644
--- a/arch/sparc/kernel/sun4d_irq.c
+++ b/arch/sparc/kernel/sun4d_irq.c
@@ -6,6 +6,7 @@
  */
 
 #include <linux/kernel_stat.h>
+#include <linux/slab.h>
 #include <linux/seq_file.h>
 
 #include <asm/timer.h>
diff --git a/arch/tile/kernel/hardwall.c b/arch/tile/kernel/hardwall.c
index 20273ee..38ac189 100644
--- a/arch/tile/kernel/hardwall.c
+++ b/arch/tile/kernel/hardwall.c
@@ -914,7 +914,7 @@
 static int hardwall_proc_open(struct inode *inode,
 			      struct file *file)
 {
-	return single_open(file, hardwall_proc_show, PDE(inode)->data);
+	return single_open(file, hardwall_proc_show, PDE_DATA(inode));
 }
 
 static const struct file_operations hardwall_proc_fops = {
diff --git a/arch/um/drivers/mconsole_kern.c b/arch/um/drivers/mconsole_kern.c
index 4bd82ac..d7d2185 100644
--- a/arch/um/drivers/mconsole_kern.c
+++ b/arch/um/drivers/mconsole_kern.c
@@ -782,8 +782,7 @@
 
 	ent = proc_create("mconsole", 0200, NULL, &mconsole_proc_fops);
 	if (ent == NULL) {
-		printk(KERN_INFO "create_proc_mconsole : create_proc_entry "
-		       "failed\n");
+		printk(KERN_INFO "create_proc_mconsole : proc_create failed\n");
 		return 0;
 	}
 	return 0;
diff --git a/arch/x86/ia32/ia32_aout.c b/arch/x86/ia32/ia32_aout.c
index 81e94d9..805078e 100644
--- a/arch/x86/ia32/ia32_aout.c
+++ b/arch/x86/ia32/ia32_aout.c
@@ -322,11 +322,8 @@
 
 	if (N_MAGIC(ex) == OMAGIC) {
 		unsigned long text_addr, map_size;
-		loff_t pos;
 
 		text_addr = N_TXTADDR(ex);
-
-		pos = 32;
 		map_size = ex.a_text+ex.a_data;
 
 		error = vm_brk(text_addr & PAGE_MASK, map_size);
@@ -336,15 +333,12 @@
 			return error;
 		}
 
-		error = bprm->file->f_op->read(bprm->file,
-			 (char __user *)text_addr,
-			  ex.a_text+ex.a_data, &pos);
+		error = read_code(bprm->file, text_addr, 32,
+				  ex.a_text + ex.a_data);
 		if ((signed long)error < 0) {
 			send_sig(SIGKILL, current, 0);
 			return error;
 		}
-
-		flush_icache_range(text_addr, text_addr+ex.a_text+ex.a_data);
 	} else {
 #ifdef WARN_OLD
 		static unsigned long error_time, error_time2;
@@ -366,15 +360,9 @@
 #endif
 
 		if (!bprm->file->f_op->mmap || (fd_offset & ~PAGE_MASK) != 0) {
-			loff_t pos = fd_offset;
-
 			vm_brk(N_TXTADDR(ex), ex.a_text+ex.a_data);
-			bprm->file->f_op->read(bprm->file,
-					(char __user *)N_TXTADDR(ex),
-					ex.a_text+ex.a_data, &pos);
-			flush_icache_range((unsigned long) N_TXTADDR(ex),
-					   (unsigned long) N_TXTADDR(ex) +
-					   ex.a_text+ex.a_data);
+			read_code(bprm->file, N_TXTADDR(ex), fd_offset,
+					ex.a_text+ex.a_data);
 			goto beyond_if;
 		}
 
@@ -451,8 +439,6 @@
 	start_addr =  ex.a_entry & 0xfffff000;
 
 	if ((N_TXTOFF(ex) & ~PAGE_MASK) != 0) {
-		loff_t pos = N_TXTOFF(ex);
-
 #ifdef WARN_OLD
 		static unsigned long error_time;
 		if (time_after(jiffies, error_time + 5*HZ)) {
@@ -465,12 +451,8 @@
 #endif
 		vm_brk(start_addr, ex.a_text + ex.a_data + ex.a_bss);
 
-		file->f_op->read(file, (char __user *)start_addr,
-			ex.a_text + ex.a_data, &pos);
-		flush_icache_range((unsigned long) start_addr,
-				   (unsigned long) start_addr + ex.a_text +
-				   ex.a_data);
-
+		read_code(file, start_addr, N_TXTOFF(ex),
+			  ex.a_text + ex.a_data);
 		retval = 0;
 		goto out;
 	}
diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c
index caad9a0..bb00c46 100644
--- a/arch/x86/mm/init_64.c
+++ b/arch/x86/mm/init_64.c
@@ -32,6 +32,7 @@
 #include <linux/memory_hotplug.h>
 #include <linux/nmi.h>
 #include <linux/gfp.h>
+#include <linux/kcore.h>
 
 #include <asm/processor.h>
 #include <asm/bios_ebda.h>
diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c
index 6b85db0..55856b2 100644
--- a/arch/x86/platform/efi/efi.c
+++ b/arch/x86/platform/efi/efi.c
@@ -34,6 +34,7 @@
 #include <linux/efi-bgrt.h>
 #include <linux/export.h>
 #include <linux/bootmem.h>
+#include <linux/slab.h>
 #include <linux/memblock.h>
 #include <linux/spinlock.h>
 #include <linux/uaccess.h>
diff --git a/arch/x86/platform/efi/efi_64.c b/arch/x86/platform/efi/efi_64.c
index 2b20038..39a0e7f 100644
--- a/arch/x86/platform/efi/efi_64.c
+++ b/arch/x86/platform/efi/efi_64.c
@@ -27,6 +27,7 @@
 #include <linux/uaccess.h>
 #include <linux/io.h>
 #include <linux/reboot.h>
+#include <linux/slab.h>
 
 #include <asm/setup.h>
 #include <asm/page.h>
diff --git a/arch/xtensa/platforms/iss/simdisk.c b/arch/xtensa/platforms/iss/simdisk.c
index f58ffc3..4a06d70 100644
--- a/arch/xtensa/platforms/iss/simdisk.c
+++ b/arch/xtensa/platforms/iss/simdisk.c
@@ -214,20 +214,27 @@
 	return err;
 }
 
-static int proc_read_simdisk(char *page, char **start, off_t off,
-		int count, int *eof, void *data)
+static ssize_t proc_read_simdisk(struct file *file, char __user *buf,
+			size_t size, loff_t *ppos)
 {
-	int len;
-	struct simdisk *dev = (struct simdisk *) data;
-	len = sprintf(page, "%s\n", dev->filename ? dev->filename : "");
-	return len;
+	struct simdisk *dev = PDE_DATA(file_inode(file));
+	char *s = dev->filename;
+	if (s) {
+		ssize_t n = simple_read_from_buffer(buf, size, ppos,
+							s, strlen(s));
+		if (n < 0)
+			return n;
+		buf += n;
+		size -= n;
+	}
+	return simple_read_from_buffer(buf, size, ppos, "\n", 1);
 }
 
-static int proc_write_simdisk(struct file *file, const char *buffer,
-		unsigned long count, void *data)
+static ssize_t proc_write_simdisk(struct file *file, const char __user *buf,
+			size_t size, loff_t *ppos)
 {
 	char *tmp = kmalloc(count + 1, GFP_KERNEL);
-	struct simdisk *dev = (struct simdisk *) data;
+	struct simdisk *dev = PDE_DATA(file_inode(file));
 	int err;
 
 	if (tmp == NULL)
@@ -256,6 +263,12 @@
 	return err;
 }
 
+static const struct file_operations fops = {
+	.read = proc_read_simdisk,
+	.write = proc_write_simdisk,
+	.llseek = default_llseek,
+};
+
 static int __init simdisk_setup(struct simdisk *dev, int which,
 		struct proc_dir_entry *procdir)
 {
@@ -289,10 +302,7 @@
 	set_capacity(dev->gd, 0);
 	add_disk(dev->gd);
 
-	dev->procfile = create_proc_entry(tmp, 0644, procdir);
-	dev->procfile->data = dev;
-	dev->procfile->read_proc = proc_read_simdisk;
-	dev->procfile->write_proc = proc_write_simdisk;
+	dev->procfile = proc_create_data(tmp, 0644, procdir, &fops, dev);
 	return 0;
 
 out_alloc_disk:
diff --git a/drivers/acpi/ac.c b/drivers/acpi/ac.c
index 6d5bf64..00d2efd 100644
--- a/drivers/acpi/ac.c
+++ b/drivers/acpi/ac.c
@@ -194,7 +194,7 @@
 
 static int acpi_ac_open_fs(struct inode *inode, struct file *file)
 {
-	return single_open(file, acpi_ac_seq_show, PDE(inode)->data);
+	return single_open(file, acpi_ac_seq_show, PDE_DATA(inode));
 }
 
 static int acpi_ac_add_fs(struct acpi_device *device)
diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c
index 0cc384b..e710045 100644
--- a/drivers/acpi/battery.c
+++ b/drivers/acpi/battery.c
@@ -929,7 +929,7 @@
 } \
 static int acpi_battery_##_name##_open_fs(struct inode *inode, struct file *file) \
 { \
-	return single_open(file, acpi_battery_read_##_name, PDE(inode)->data); \
+	return single_open(file, acpi_battery_read_##_name, PDE_DATA(inode)); \
 }
 
 DECLARE_FILE_FUNCTIONS(info);
diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c
index 92a659a..d2e617b 100644
--- a/drivers/acpi/button.c
+++ b/drivers/acpi/button.c
@@ -129,7 +129,7 @@
 
 static int acpi_button_state_open_fs(struct inode *inode, struct file *file)
 {
-	return single_open(file, acpi_button_state_seq_show, PDE(inode)->data);
+	return single_open(file, acpi_button_state_seq_show, PDE_DATA(inode));
 }
 
 static const struct file_operations acpi_button_state_fops = {
diff --git a/drivers/acpi/proc.c b/drivers/acpi/proc.c
index 52ce767..aa1227a 100644
--- a/drivers/acpi/proc.c
+++ b/drivers/acpi/proc.c
@@ -120,7 +120,7 @@
 
 static int acpi_system_alarm_open_fs(struct inode *inode, struct file *file)
 {
-	return single_open(file, acpi_system_alarm_seq_show, PDE(inode)->data);
+	return single_open(file, acpi_system_alarm_seq_show, PDE_DATA(inode));
 }
 
 static int get_date_field(char **p, u32 * value)
@@ -397,7 +397,7 @@
 acpi_system_wakeup_device_open_fs(struct inode *inode, struct file *file)
 {
 	return single_open(file, acpi_system_wakeup_device_seq_show,
-			   PDE(inode)->data);
+			   PDE_DATA(inode));
 }
 
 static const struct file_operations acpi_system_wakeup_device_fops = {
diff --git a/drivers/acpi/sbs.c b/drivers/acpi/sbs.c
index e523245..b6241ee 100644
--- a/drivers/acpi/sbs.c
+++ b/drivers/acpi/sbs.c
@@ -521,19 +521,6 @@
 	return 0;
 }
 
-static void
-acpi_sbs_remove_fs(struct proc_dir_entry **dir,
-			   struct proc_dir_entry *parent_dir)
-{
-	if (*dir) {
-		remove_proc_entry(ACPI_SBS_FILE_INFO, *dir);
-		remove_proc_entry(ACPI_SBS_FILE_STATE, *dir);
-		remove_proc_entry(ACPI_SBS_FILE_ALARM, *dir);
-		remove_proc_entry((*dir)->name, parent_dir);
-		*dir = NULL;
-	}
-}
-
 /* Smart Battery Interface */
 static struct proc_dir_entry *acpi_battery_dir = NULL;
 
@@ -584,7 +571,7 @@
 
 static int acpi_battery_info_open_fs(struct inode *inode, struct file *file)
 {
-	return single_open(file, acpi_battery_read_info, PDE(inode)->data);
+	return single_open(file, acpi_battery_read_info, PDE_DATA(inode));
 }
 
 static int acpi_battery_read_state(struct seq_file *seq, void *offset)
@@ -623,7 +610,7 @@
 
 static int acpi_battery_state_open_fs(struct inode *inode, struct file *file)
 {
-	return single_open(file, acpi_battery_read_state, PDE(inode)->data);
+	return single_open(file, acpi_battery_read_state, PDE_DATA(inode));
 }
 
 static int acpi_battery_read_alarm(struct seq_file *seq, void *offset)
@@ -688,7 +675,7 @@
 
 static int acpi_battery_alarm_open_fs(struct inode *inode, struct file *file)
 {
-	return single_open(file, acpi_battery_read_alarm, PDE(inode)->data);
+	return single_open(file, acpi_battery_read_alarm, PDE_DATA(inode));
 }
 
 static const struct file_operations acpi_battery_info_fops = {
@@ -736,7 +723,7 @@
 
 static int acpi_ac_state_open_fs(struct inode *inode, struct file *file)
 {
-	return single_open(file, acpi_ac_read_state, PDE(inode)->data);
+	return single_open(file, acpi_ac_read_state, PDE_DATA(inode));
 }
 
 static const struct file_operations acpi_ac_state_fops = {
@@ -836,8 +823,8 @@
 		power_supply_unregister(&battery->bat);
 	}
 #ifdef CONFIG_ACPI_PROCFS_POWER
-	if (battery->proc_entry)
-		acpi_sbs_remove_fs(&battery->proc_entry, acpi_battery_dir);
+	proc_remove(battery->proc_entry);
+	battery->proc_entry = NULL;
 #endif
 }
 
@@ -873,8 +860,8 @@
 	if (sbs->charger.dev)
 		power_supply_unregister(&sbs->charger);
 #ifdef CONFIG_ACPI_PROCFS_POWER
-	if (sbs->charger_entry)
-		acpi_sbs_remove_fs(&sbs->charger_entry, acpi_ac_dir);
+	proc_remove(sbs->charger_entry);
+	sbs->charger_entry = NULL;
 #endif
 }
 
diff --git a/drivers/ata/sata_svw.c b/drivers/ata/sata_svw.c
index 08608de..dc4f701 100644
--- a/drivers/ata/sata_svw.c
+++ b/drivers/ata/sata_svw.c
@@ -322,23 +322,11 @@
 }
 
 #ifdef CONFIG_PPC_OF
-/*
- * k2_sata_proc_info
- * inout : decides on the direction of the dataflow and the meaning of the
- *	   variables
- * buffer: If inout==FALSE data is being written to it else read from it
- * *start: If inout==FALSE start of the valid data in the buffer
- * offset: If inout==FALSE offset from the beginning of the imaginary file
- *	   from which we start writing into the buffer
- * length: If inout==FALSE max number of bytes to be written into the buffer
- *	   else number of bytes in the buffer
- */
-static int k2_sata_proc_info(struct Scsi_Host *shost, char *page, char **start,
-			     off_t offset, int count, int inout)
+static int k2_sata_show_info(struct seq_file *m, struct Scsi_Host *shost)
 {
 	struct ata_port *ap;
 	struct device_node *np;
-	int len, index;
+	int index;
 
 	/* Find  the ata_port */
 	ap = ata_shost_to_port(shost);
@@ -356,15 +344,12 @@
 		const u32 *reg = of_get_property(np, "reg", NULL);
 		if (!reg)
 			continue;
-		if (index == *reg)
+		if (index == *reg) {
+			seq_printf(m, "devspec: %s\n", np->full_name);
 			break;
+		}
 	}
-	if (np == NULL)
-		return 0;
-
-	len = sprintf(page, "devspec: %s\n", np->full_name);
-
-	return len;
+	return 0;
 }
 #endif /* CONFIG_PPC_OF */
 
@@ -372,7 +357,7 @@
 static struct scsi_host_template k2_sata_sht = {
 	ATA_BMDMA_SHT(DRV_NAME),
 #ifdef CONFIG_PPC_OF
-	.proc_info		= k2_sata_proc_info,
+	.show_info		= k2_sata_show_info,
 #endif
 };
 
diff --git a/drivers/block/DAC960.c b/drivers/block/DAC960.c
index 5b5ee79..eb39501 100644
--- a/drivers/block/DAC960.c
+++ b/drivers/block/DAC960.c
@@ -6473,7 +6473,7 @@
 
 static int dac960_initial_status_proc_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, dac960_initial_status_proc_show, PDE(inode)->data);
+	return single_open(file, dac960_initial_status_proc_show, PDE_DATA(inode));
 }
 
 static const struct file_operations dac960_initial_status_proc_fops = {
@@ -6519,7 +6519,7 @@
 
 static int dac960_current_status_proc_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, dac960_current_status_proc_show, PDE(inode)->data);
+	return single_open(file, dac960_current_status_proc_show, PDE_DATA(inode));
 }
 
 static const struct file_operations dac960_current_status_proc_fops = {
@@ -6540,14 +6540,14 @@
 
 static int dac960_user_command_proc_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, dac960_user_command_proc_show, PDE(inode)->data);
+	return single_open(file, dac960_user_command_proc_show, PDE_DATA(inode));
 }
 
 static ssize_t dac960_user_command_proc_write(struct file *file,
 				       const char __user *Buffer,
 				       size_t Count, loff_t *pos)
 {
-  DAC960_Controller_T *Controller = (DAC960_Controller_T *) PDE(file_inode(file))->data;
+  DAC960_Controller_T *Controller = PDE_DATA(file_inode(file));
   unsigned char CommandBuffer[80];
   int Length;
   if (Count > sizeof(CommandBuffer)-1) return -EINVAL;
diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c
index 1c1b8e5..e18c991 100644
--- a/drivers/block/cciss.c
+++ b/drivers/block/cciss.c
@@ -493,7 +493,7 @@
 	struct seq_file *seq = file->private_data;
 
 	if (!ret)
-		seq->private = PDE(inode)->data;
+		seq->private = PDE_DATA(inode);
 
 	return ret;
 }
diff --git a/drivers/block/cciss_scsi.c b/drivers/block/cciss_scsi.c
index da33111..ecd845c 100644
--- a/drivers/block/cciss_scsi.c
+++ b/drivers/block/cciss_scsi.c
@@ -54,13 +54,11 @@
 static void cmd_free(ctlr_info_t *h, CommandList_struct *c);
 static void cmd_special_free(ctlr_info_t *h, CommandList_struct *c);
 
-static int cciss_scsi_proc_info(
-		struct Scsi_Host *sh,
+static int cciss_scsi_write_info(struct Scsi_Host *sh,
 		char *buffer, /* data buffer */
-		char **start, 	   /* where data in buffer starts */
-		off_t offset,	   /* offset from start of imaginary file */
-		int length, 	   /* length of data in buffer */
-		int func);	   /* 0 == read, 1 == write */
+		int length); 	   /* length of data in buffer */
+static int cciss_scsi_show_info(struct seq_file *m,
+				struct Scsi_Host *sh);
 
 static int cciss_scsi_queue_command (struct Scsi_Host *h,
 				     struct scsi_cmnd *cmd);
@@ -82,7 +80,8 @@
 	.module			= THIS_MODULE,
 	.name			= "cciss",
 	.proc_name		= "cciss",
-	.proc_info		= cciss_scsi_proc_info,
+	.write_info		= cciss_scsi_write_info,
+	.show_info		= cciss_scsi_show_info,
 	.queuecommand		= cciss_scsi_queue_command,
 	.this_id		= 7,
 	.cmd_per_lun		= 1,
@@ -1302,60 +1301,55 @@
 	return length;
 }
 
-
 static int
-cciss_scsi_proc_info(struct Scsi_Host *sh,
+cciss_scsi_write_info(struct Scsi_Host *sh,
 		char *buffer, /* data buffer */
-		char **start, 	   /* where data in buffer starts */
-		off_t offset,	   /* offset from start of imaginary file */
-		int length, 	   /* length of data in buffer */
-		int func)	   /* 0 == read, 1 == write */
+		int length) 	   /* length of data in buffer */
 {
-
-	int buflen, datalen;
-	ctlr_info_t *h;
-	int i;
-
-	h = (ctlr_info_t *) sh->hostdata[0];
+	ctlr_info_t *h = (ctlr_info_t *) sh->hostdata[0];
 	if (h == NULL)  /* This really shouldn't ever happen. */
 		return -EINVAL;
 
-	if (func == 0) {	/* User is reading from /proc/scsi/ciss*?/?*  */
-		buflen = sprintf(buffer, "cciss%d: SCSI host: %d\n",
-				h->ctlr, sh->host_no);
-
-		/* this information is needed by apps to know which cciss
-		   device corresponds to which scsi host number without
-		   having to open a scsi target device node.  The device
-		   information is not a duplicate of /proc/scsi/scsi because
-		   the two may be out of sync due to scsi hotplug, rather
-		   this info is for an app to be able to use to know how to
-		   get them back in sync. */
-
-		for (i = 0; i < ccissscsi[h->ctlr].ndevices; i++) {
-			struct cciss_scsi_dev_t *sd =
-				&ccissscsi[h->ctlr].dev[i];
-			buflen += sprintf(&buffer[buflen], "c%db%dt%dl%d %02d "
-				"0x%02x%02x%02x%02x%02x%02x%02x%02x\n",
-				sh->host_no, sd->bus, sd->target, sd->lun,
-				sd->devtype,
-				sd->scsi3addr[0], sd->scsi3addr[1],
-				sd->scsi3addr[2], sd->scsi3addr[3],
-				sd->scsi3addr[4], sd->scsi3addr[5],
-				sd->scsi3addr[6], sd->scsi3addr[7]);
-		}
-		datalen = buflen - offset;
-		if (datalen < 0) { 	/* they're reading past EOF. */
-			datalen = 0;
-			*start = buffer+buflen;	
-		} else
-			*start = buffer + offset;
-		return(datalen);
-	} else 	/* User is writing to /proc/scsi/cciss*?/?*  ... */
-		return cciss_scsi_user_command(h, sh->host_no,
+	return cciss_scsi_user_command(h, sh->host_no,
 			buffer, length);	
 } 
 
+static int
+cciss_scsi_show_info(struct seq_file *m, struct Scsi_Host *sh)
+{
+
+	ctlr_info_t *h = (ctlr_info_t *) sh->hostdata[0];
+	int i;
+
+	if (h == NULL)  /* This really shouldn't ever happen. */
+		return -EINVAL;
+
+	seq_printf(m, "cciss%d: SCSI host: %d\n",
+			h->ctlr, sh->host_no);
+
+	/* this information is needed by apps to know which cciss
+	   device corresponds to which scsi host number without
+	   having to open a scsi target device node.  The device
+	   information is not a duplicate of /proc/scsi/scsi because
+	   the two may be out of sync due to scsi hotplug, rather
+	   this info is for an app to be able to use to know how to
+	   get them back in sync. */
+
+	for (i = 0; i < ccissscsi[h->ctlr].ndevices; i++) {
+		struct cciss_scsi_dev_t *sd =
+			&ccissscsi[h->ctlr].dev[i];
+		seq_printf(m, "c%db%dt%dl%d %02d "
+			"0x%02x%02x%02x%02x%02x%02x%02x%02x\n",
+			sh->host_no, sd->bus, sd->target, sd->lun,
+			sd->devtype,
+			sd->scsi3addr[0], sd->scsi3addr[1],
+			sd->scsi3addr[2], sd->scsi3addr[3],
+			sd->scsi3addr[4], sd->scsi3addr[5],
+			sd->scsi3addr[6], sd->scsi3addr[7]);
+	}
+	return 0;
+}
+
 /* cciss_scatter_gather takes a struct scsi_cmnd, (cmd), and does the pci 
    dma mapping  and fills in the scatter gather entries of the 
    cciss command, c. */
diff --git a/drivers/block/cpqarray.c b/drivers/block/cpqarray.c
index 3f08713..3b9e8eb 100644
--- a/drivers/block/cpqarray.c
+++ b/drivers/block/cpqarray.c
@@ -296,7 +296,7 @@
 
 static int ida_proc_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, ida_proc_show, PDE(inode)->data);
+	return single_open(file, ida_proc_show, PDE_DATA(inode));
 }
 
 static const struct file_operations ida_proc_fops = {
diff --git a/drivers/block/drbd/drbd_proc.c b/drivers/block/drbd/drbd_proc.c
index 56672a6..928adb8 100644
--- a/drivers/block/drbd/drbd_proc.c
+++ b/drivers/block/drbd/drbd_proc.c
@@ -314,7 +314,7 @@
 static int drbd_proc_open(struct inode *inode, struct file *file)
 {
 	if (try_module_get(THIS_MODULE))
-		return single_open(file, drbd_seq_show, PDE(inode)->data);
+		return single_open(file, drbd_seq_show, PDE_DATA(inode));
 	return -ENODEV;
 }
 
diff --git a/drivers/block/loop.c b/drivers/block/loop.c
index dfe7583..b2955b3 100644
--- a/drivers/block/loop.c
+++ b/drivers/block/loop.c
@@ -230,9 +230,11 @@
 	ssize_t bw;
 	mm_segment_t old_fs = get_fs();
 
+	file_start_write(file);
 	set_fs(get_ds());
 	bw = file->f_op->write(file, buf, len, &pos);
 	set_fs(old_fs);
+	file_end_write(file);
 	if (likely(bw == len))
 		return 0;
 	printk(KERN_ERR "loop: Write error at byte offset %llu, length %i.\n",
diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c
index 2e7de7a..e0588c6 100644
--- a/drivers/block/pktcdvd.c
+++ b/drivers/block/pktcdvd.c
@@ -2648,7 +2648,7 @@
 
 static int pkt_seq_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, pkt_seq_show, PDE(inode)->data);
+	return single_open(file, pkt_seq_show, PDE_DATA(inode));
 }
 
 static const struct file_operations pkt_proc_fops = {
diff --git a/drivers/block/ps3vram.c b/drivers/block/ps3vram.c
index 75e112d..06a2e53 100644
--- a/drivers/block/ps3vram.c
+++ b/drivers/block/ps3vram.c
@@ -525,7 +525,7 @@
 
 static int ps3vram_proc_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, ps3vram_proc_show, PDE(inode)->data);
+	return single_open(file, ps3vram_proc_show, PDE_DATA(inode));
 }
 
 static const struct file_operations ps3vram_proc_fops = {
diff --git a/drivers/char/ds1620.c b/drivers/char/ds1620.c
index 24ffd8c..544b4ce 100644
--- a/drivers/char/ds1620.c
+++ b/drivers/char/ds1620.c
@@ -6,6 +6,7 @@
 #include <linux/miscdevice.h>
 #include <linux/delay.h>
 #include <linux/proc_fs.h>
+#include <linux/seq_file.h>
 #include <linux/capability.h>
 #include <linux/init.h>
 #include <linux/mutex.h>
@@ -329,9 +330,7 @@
 }
 
 #ifdef THERM_USE_PROC
-static int
-proc_therm_ds1620_read(char *buf, char **start, off_t offset,
-		       int len, int *eof, void *unused)
+static int ds1620_proc_therm_show(struct seq_file *m, void *v)
 {
 	struct therm th;
 	int temp;
@@ -339,17 +338,25 @@
 	ds1620_read_state(&th);
 	temp =  cvt_9_to_int(ds1620_in(THERM_READ_TEMP, 9));
 
-	len = sprintf(buf, "Thermostat: HI %i.%i, LOW %i.%i; "
-		      "temperature: %i.%i C, fan %s\n",
-		      th.hi >> 1, th.hi & 1 ? 5 : 0,
-		      th.lo >> 1, th.lo & 1 ? 5 : 0,
-		      temp  >> 1, temp  & 1 ? 5 : 0,
-		      fan_state[netwinder_get_fan()]);
-
-	return len;
+	seq_printf(m, "Thermostat: HI %i.%i, LOW %i.%i; temperature: %i.%i C, fan %s\n",
+		   th.hi >> 1, th.hi & 1 ? 5 : 0,
+		   th.lo >> 1, th.lo & 1 ? 5 : 0,
+		   temp  >> 1, temp  & 1 ? 5 : 0,
+		   fan_state[netwinder_get_fan()]);
+	return 0;
 }
 
-static struct proc_dir_entry *proc_therm_ds1620;
+static int ds1620_proc_therm_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, ds1620_proc_therm_show, NULL);
+}
+
+static const struct file_operations ds1620_proc_therm_fops = {
+	.open		= ds1620_proc_therm_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= seq_release,
+};
 #endif
 
 static const struct file_operations ds1620_fops = {
@@ -397,10 +404,7 @@
 		return ret;
 
 #ifdef THERM_USE_PROC
-	proc_therm_ds1620 = create_proc_entry("therm", 0, NULL);
-	if (proc_therm_ds1620)
-		proc_therm_ds1620->read_proc = proc_therm_ds1620_read;
-	else
+	if (!proc_create("therm", 0, NULL, &ds1620_proc_therm_fops))
 		printk(KERN_ERR "therm: unable to register /proc/therm\n");
 #endif
 
diff --git a/drivers/char/efirtc.c b/drivers/char/efirtc.c
index a082d00..ea54a6e 100644
--- a/drivers/char/efirtc.c
+++ b/drivers/char/efirtc.c
@@ -34,6 +34,7 @@
 #include <linux/init.h>
 #include <linux/rtc.h>
 #include <linux/proc_fs.h>
+#include <linux/seq_file.h>
 #include <linux/efi.h>
 #include <linux/uaccess.h>
 
@@ -296,12 +297,10 @@
 /*
  *	We export RAW EFI information to /proc/driver/efirtc
  */
-static int
-efi_rtc_get_status(char *buf)
+static int efi_rtc_proc_show(struct seq_file *m, void *v)
 {
 	efi_time_t 	eft, alm;
 	efi_time_cap_t	cap;
-	char		*p = buf;
 	efi_bool_t	enabled, pending;	
 	unsigned long	flags;
 
@@ -316,64 +315,63 @@
 
 	spin_unlock_irqrestore(&efi_rtc_lock,flags);
 
-	p += sprintf(p,
-		     "Time           : %u:%u:%u.%09u\n"
-		     "Date           : %u-%u-%u\n"
-		     "Daylight       : %u\n",
-		     eft.hour, eft.minute, eft.second, eft.nanosecond, 
-		     eft.year, eft.month, eft.day,
-		     eft.daylight);
+	seq_printf(m,
+		   "Time           : %u:%u:%u.%09u\n"
+		   "Date           : %u-%u-%u\n"
+		   "Daylight       : %u\n",
+		   eft.hour, eft.minute, eft.second, eft.nanosecond, 
+		   eft.year, eft.month, eft.day,
+		   eft.daylight);
 
 	if (eft.timezone == EFI_UNSPECIFIED_TIMEZONE)
-		p += sprintf(p, "Timezone       : unspecified\n");
+		seq_puts(m, "Timezone       : unspecified\n");
 	else
 		/* XXX fixme: convert to string? */
-		p += sprintf(p, "Timezone       : %u\n", eft.timezone);
+		seq_printf(m, "Timezone       : %u\n", eft.timezone);
 		
 
-	p += sprintf(p,
-		     "Alarm Time     : %u:%u:%u.%09u\n"
-		     "Alarm Date     : %u-%u-%u\n"
-		     "Alarm Daylight : %u\n"
-		     "Enabled        : %s\n"
-		     "Pending        : %s\n",
-		     alm.hour, alm.minute, alm.second, alm.nanosecond, 
-		     alm.year, alm.month, alm.day, 
-		     alm.daylight,
-		     enabled == 1 ? "yes" : "no",
-		     pending == 1 ? "yes" : "no");
+	seq_printf(m,
+		   "Alarm Time     : %u:%u:%u.%09u\n"
+		   "Alarm Date     : %u-%u-%u\n"
+		   "Alarm Daylight : %u\n"
+		   "Enabled        : %s\n"
+		   "Pending        : %s\n",
+		   alm.hour, alm.minute, alm.second, alm.nanosecond, 
+		   alm.year, alm.month, alm.day, 
+		   alm.daylight,
+		   enabled == 1 ? "yes" : "no",
+		   pending == 1 ? "yes" : "no");
 
 	if (eft.timezone == EFI_UNSPECIFIED_TIMEZONE)
-		p += sprintf(p, "Timezone       : unspecified\n");
+		seq_puts(m, "Timezone       : unspecified\n");
 	else
 		/* XXX fixme: convert to string? */
-		p += sprintf(p, "Timezone       : %u\n", alm.timezone);
+		seq_printf(m, "Timezone       : %u\n", alm.timezone);
 
 	/*
 	 * now prints the capabilities
 	 */
-	p += sprintf(p,
-		     "Resolution     : %u\n"
-		     "Accuracy       : %u\n"
-		     "SetstoZero     : %u\n",
-		      cap.resolution, cap.accuracy, cap.sets_to_zero);
+	seq_printf(m,
+		   "Resolution     : %u\n"
+		   "Accuracy       : %u\n"
+		   "SetstoZero     : %u\n",
+		   cap.resolution, cap.accuracy, cap.sets_to_zero);
 
-	return  p - buf;
+	return 0;
 }
 
-static int
-efi_rtc_read_proc(char *page, char **start, off_t off,
-                                 int count, int *eof, void *data)
+static int efi_rtc_proc_open(struct inode *inode, struct file *file)
 {
-        int len = efi_rtc_get_status(page);
-        if (len <= off+count) *eof = 1;
-        *start = page + off;
-        len -= off;
-        if (len>count) len = count;
-        if (len<0) len = 0;
-        return len;
+	return single_open(file, efi_rtc_proc_show, NULL);
 }
 
+static const struct file_operations efi_rtc_proc_fops = {
+	.open		= efi_rtc_proc_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= seq_release,
+};
+
 static int __init 
 efi_rtc_init(void)
 {
@@ -389,8 +387,7 @@
 		return ret;
 	}
 
-	dir = create_proc_read_entry ("driver/efirtc", 0, NULL,
-			              efi_rtc_read_proc, NULL);
+	dir = proc_create("driver/efirtc", 0, NULL, &efi_rtc_proc_fops);
 	if (dir == NULL) {
 		printk(KERN_ERR "efirtc: can't create /proc/driver/efirtc.\n");
 		misc_deregister(&efi_rtc_dev);
diff --git a/drivers/char/genrtc.c b/drivers/char/genrtc.c
index 21cb980..bc9b84d 100644
--- a/drivers/char/genrtc.c
+++ b/drivers/char/genrtc.c
@@ -52,6 +52,7 @@
 #include <linux/init.h>
 #include <linux/poll.h>
 #include <linux/proc_fs.h>
+#include <linux/seq_file.h>
 #include <linux/mutex.h>
 #include <linux/workqueue.h>
 
@@ -386,18 +387,15 @@
  *	Info exported via "/proc/driver/rtc".
  */
 
-static int gen_rtc_proc_output(char *buf)
+static int gen_rtc_proc_show(struct seq_file *m, void *v)
 {
-	char *p;
 	struct rtc_time tm;
 	unsigned int flags;
 	struct rtc_pll_info pll;
 
-	p = buf;
-
 	flags = get_rtc_time(&tm);
 
-	p += sprintf(p,
+	seq_printf(m,
 		     "rtc_time\t: %02d:%02d:%02d\n"
 		     "rtc_date\t: %04d-%02d-%02d\n"
 		     "rtc_epoch\t: %04u\n",
@@ -406,23 +404,23 @@
 
 	tm.tm_hour = tm.tm_min = tm.tm_sec = 0;
 
-	p += sprintf(p, "alarm\t\t: ");
+	seq_puts(m, "alarm\t\t: ");
 	if (tm.tm_hour <= 24)
-		p += sprintf(p, "%02d:", tm.tm_hour);
+		seq_printf(m, "%02d:", tm.tm_hour);
 	else
-		p += sprintf(p, "**:");
+		seq_puts(m, "**:");
 
 	if (tm.tm_min <= 59)
-		p += sprintf(p, "%02d:", tm.tm_min);
+		seq_printf(m, "%02d:", tm.tm_min);
 	else
-		p += sprintf(p, "**:");
+		seq_puts(m, "**:");
 
 	if (tm.tm_sec <= 59)
-		p += sprintf(p, "%02d\n", tm.tm_sec);
+		seq_printf(m, "%02d\n", tm.tm_sec);
 	else
-		p += sprintf(p, "**\n");
+		seq_puts(m, "**\n");
 
-	p += sprintf(p,
+	seq_printf(m,
 		     "DST_enable\t: %s\n"
 		     "BCD\t\t: %s\n"
 		     "24hr\t\t: %s\n"
@@ -442,7 +440,7 @@
 		     0L /* freq */,
 		     (flags & RTC_BATT_BAD) ? "bad" : "okay");
 	if (!get_rtc_pll(&pll))
-	    p += sprintf(p,
+	    seq_printf(m,
 			 "PLL adjustment\t: %d\n"
 			 "PLL max +ve adjustment\t: %d\n"
 			 "PLL max -ve adjustment\t: %d\n"
@@ -455,26 +453,26 @@
 			 pll.pll_posmult,
 			 pll.pll_negmult,
 			 pll.pll_clock);
-	return p - buf;
+	return 0;
 }
 
-static int gen_rtc_read_proc(char *page, char **start, off_t off,
-			     int count, int *eof, void *data)
+static int gen_rtc_proc_open(struct inode *inode, struct file *file)
 {
-	int len = gen_rtc_proc_output (page);
-        if (len <= off+count) *eof = 1;
-	*start = page + off;
-	len -= off;
-        if (len>count) len = count;
-        if (len<0) len = 0;
-	return len;
+	return single_open(file, gen_rtc_proc_show, NULL);
 }
 
+static const struct file_operations gen_rtc_proc_fops = {
+	.open		= gen_rtc_proc_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= seq_release,
+};
+
 static int __init gen_rtc_proc_init(void)
 {
 	struct proc_dir_entry *r;
 
-	r = create_proc_read_entry("driver/rtc", 0, NULL, gen_rtc_read_proc, NULL);
+	r = proc_create("driver/rtc", 0, NULL, &gen_rtc_proc_fops);
 	if (!r)
 		return -ENOMEM;
 	return 0;
diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c
index 053201b..4d439d2 100644
--- a/drivers/char/ipmi/ipmi_msghandler.c
+++ b/drivers/char/ipmi/ipmi_msghandler.c
@@ -1917,7 +1917,7 @@
 
 static int smi_ipmb_proc_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, smi_ipmb_proc_show, PDE(inode)->data);
+	return single_open(file, smi_ipmb_proc_show, PDE_DATA(inode));
 }
 
 static const struct file_operations smi_ipmb_proc_ops = {
@@ -1938,7 +1938,7 @@
 
 static int smi_version_proc_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, smi_version_proc_show, PDE(inode)->data);
+	return single_open(file, smi_version_proc_show, PDE_DATA(inode));
 }
 
 static const struct file_operations smi_version_proc_ops = {
@@ -2013,7 +2013,7 @@
 
 static int smi_stats_proc_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, smi_stats_proc_show, PDE(inode)->data);
+	return single_open(file, smi_stats_proc_show, PDE_DATA(inode));
 }
 
 static const struct file_operations smi_stats_proc_ops = {
@@ -4541,7 +4541,7 @@
 	del_timer_sync(&ipmi_timer);
 
 #ifdef CONFIG_PROC_FS
-	remove_proc_entry(proc_ipmi_root->name, NULL);
+	proc_remove(proc_ipmi_root);
 #endif /* CONFIG_PROC_FS */
 
 	driver_unregister(&ipmidriver.driver);
diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c
index 0ac9b45..313538a 100644
--- a/drivers/char/ipmi/ipmi_si_intf.c
+++ b/drivers/char/ipmi/ipmi_si_intf.c
@@ -2839,7 +2839,7 @@
 
 static int smi_type_proc_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, smi_type_proc_show, PDE(inode)->data);
+	return single_open(file, smi_type_proc_show, PDE_DATA(inode));
 }
 
 static const struct file_operations smi_type_proc_ops = {
@@ -2882,7 +2882,7 @@
 
 static int smi_si_stats_proc_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, smi_si_stats_proc_show, PDE(inode)->data);
+	return single_open(file, smi_si_stats_proc_show, PDE_DATA(inode));
 }
 
 static const struct file_operations smi_si_stats_proc_ops = {
@@ -2910,7 +2910,7 @@
 
 static int smi_params_proc_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, smi_params_proc_show, PDE(inode)->data);
+	return single_open(file, smi_params_proc_show, PDE_DATA(inode));
 }
 
 static const struct file_operations smi_params_proc_ops = {
diff --git a/drivers/firmware/efi/efi-pstore.c b/drivers/firmware/efi/efi-pstore.c
index 67615d6..202d2c8 100644
--- a/drivers/firmware/efi/efi-pstore.c
+++ b/drivers/firmware/efi/efi-pstore.c
@@ -1,6 +1,7 @@
 #include <linux/efi.h>
 #include <linux/module.h>
 #include <linux/pstore.h>
+#include <linux/slab.h>
 #include <linux/ucs2_string.h>
 
 #define DUMP_NAME_LEN 52
diff --git a/drivers/firmware/efi/efivars.c b/drivers/firmware/efi/efivars.c
index 5e94897..b623c59 100644
--- a/drivers/firmware/efi/efivars.c
+++ b/drivers/firmware/efi/efivars.c
@@ -67,6 +67,7 @@
 
 #include <linux/efi.h>
 #include <linux/module.h>
+#include <linux/slab.h>
 #include <linux/ucs2_string.h>
 
 #define EFIVARS_VERSION "0.08"
diff --git a/drivers/gpu/drm/drm_proc.c b/drivers/gpu/drm/drm_proc.c
index ff5456b..d7f2324 100644
--- a/drivers/gpu/drm/drm_proc.c
+++ b/drivers/gpu/drm/drm_proc.c
@@ -49,7 +49,7 @@
 /**
  * Proc file list.
  */
-static struct drm_info_list drm_proc_list[] = {
+static const struct drm_info_list drm_proc_list[] = {
 	{"name", drm_name_info, 0},
 	{"vm", drm_vm_info, 0},
 	{"clients", drm_clients_info, 0},
@@ -63,7 +63,7 @@
 
 static int drm_proc_open(struct inode *inode, struct file *file)
 {
-	struct drm_info_node* node = PDE(inode)->data;
+	struct drm_info_node* node = PDE_DATA(inode);
 
 	return single_open(file, node->info_ent->show, node);
 }
@@ -89,13 +89,13 @@
  * Create a given set of proc files represented by an array of
  * gdm_proc_lists in the given root directory.
  */
-static int drm_proc_create_files(struct drm_info_list *files, int count,
+static int drm_proc_create_files(const struct drm_info_list *files, int count,
 			  struct proc_dir_entry *root, struct drm_minor *minor)
 {
 	struct drm_device *dev = minor->dev;
 	struct proc_dir_entry *ent;
 	struct drm_info_node *tmp;
-	int i, ret;
+	int i;
 
 	for (i = 0; i < count; i++) {
 		u32 features = files[i].driver_features;
@@ -105,10 +105,9 @@
 			continue;
 
 		tmp = kmalloc(sizeof(struct drm_info_node), GFP_KERNEL);
-		if (tmp == NULL) {
-			ret = -1;
-			goto fail;
-		}
+		if (!tmp)
+			return -1;
+
 		tmp->minor = minor;
 		tmp->info_ent = &files[i];
 		list_add(&tmp->list, &minor->proc_nodes.list);
@@ -116,28 +115,20 @@
 		ent = proc_create_data(files[i].name, S_IRUGO, root,
 				       &drm_proc_fops, tmp);
 		if (!ent) {
-			DRM_ERROR("Cannot create /proc/dri/%s/%s\n",
-				  root->name, files[i].name);
+			DRM_ERROR("Cannot create /proc/dri/%u/%s\n",
+				  minor->index, files[i].name);
 			list_del(&tmp->list);
 			kfree(tmp);
-			ret = -1;
-			goto fail;
+			return -1;
 		}
-
 	}
 	return 0;
-
-fail:
-	for (i = 0; i < count; i++)
-		remove_proc_entry(drm_proc_list[i].name, minor->proc_root);
-	return ret;
 }
 
 /**
  * Initialize the DRI proc filesystem for a device
  *
  * \param dev DRM device
- * \param minor device minor number
  * \param root DRI proc dir entry.
  * \param dev_root resulting DRI device proc dir entry.
  * \return root entry pointer on success, or NULL on failure.
@@ -146,14 +137,13 @@
  * "/proc/dri/%minor%/", and each entry in proc_list as
  * "/proc/dri/%minor%/%name%".
  */
-int drm_proc_init(struct drm_minor *minor, int minor_id,
-		  struct proc_dir_entry *root)
+int drm_proc_init(struct drm_minor *minor, struct proc_dir_entry *root)
 {
-	char name[64];
+	char name[12];
 	int ret;
 
 	INIT_LIST_HEAD(&minor->proc_nodes.list);
-	sprintf(name, "%d", minor_id);
+	sprintf(name, "%u", minor->index);
 	minor->proc_root = proc_mkdir(name, root);
 	if (!minor->proc_root) {
 		DRM_ERROR("Cannot create /proc/dri/%s\n", name);
@@ -163,7 +153,7 @@
 	ret = drm_proc_create_files(drm_proc_list, DRM_PROC_ENTRIES,
 				    minor->proc_root, minor);
 	if (ret) {
-		remove_proc_entry(name, root);
+		remove_proc_subtree(name, root);
 		minor->proc_root = NULL;
 		DRM_ERROR("Failed to create core drm proc files\n");
 		return ret;
@@ -172,7 +162,7 @@
 	return 0;
 }
 
-static int drm_proc_remove_files(struct drm_info_list *files, int count,
+static int drm_proc_remove_files(const struct drm_info_list *files, int count,
 			  struct drm_minor *minor)
 {
 	struct list_head *pos, *q;
@@ -213,8 +203,7 @@
 	drm_proc_remove_files(drm_proc_list, DRM_PROC_ENTRIES, minor);
 
 	sprintf(name, "%d", minor->index);
-	remove_proc_entry(name, root);
-
+	remove_proc_subtree(name, root);
 	return 0;
 }
 
diff --git a/drivers/gpu/drm/drm_stub.c b/drivers/gpu/drm/drm_stub.c
index 7d30802..16f3ec5 100644
--- a/drivers/gpu/drm/drm_stub.c
+++ b/drivers/gpu/drm/drm_stub.c
@@ -352,7 +352,7 @@
 	idr_replace(&drm_minors_idr, new_minor, minor_id);
 
 	if (type == DRM_MINOR_LEGACY) {
-		ret = drm_proc_init(new_minor, minor_id, drm_proc_root);
+		ret = drm_proc_init(new_minor, drm_proc_root);
 		if (ret) {
 			DRM_ERROR("DRM: Failed to initialize /proc/dri.\n");
 			goto err_mem;
diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c
index 8126824..b231139 100644
--- a/drivers/ide/ide-cd.c
+++ b/drivers/ide/ide-cd.c
@@ -1408,7 +1408,7 @@
 
 static int idecd_capacity_proc_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, idecd_capacity_proc_show, PDE(inode)->data);
+	return single_open(file, idecd_capacity_proc_show, PDE_DATA(inode));
 }
 
 static const struct file_operations idecd_capacity_proc_fops = {
diff --git a/drivers/ide/ide-disk_proc.c b/drivers/ide/ide-disk_proc.c
index 8b570a1..0d1fae6 100644
--- a/drivers/ide/ide-disk_proc.c
+++ b/drivers/ide/ide-disk_proc.c
@@ -53,7 +53,7 @@
 
 static int idedisk_cache_proc_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, idedisk_cache_proc_show, PDE(inode)->data);
+	return single_open(file, idedisk_cache_proc_show, PDE_DATA(inode));
 }
 
 static const struct file_operations idedisk_cache_proc_fops = {
@@ -74,7 +74,7 @@
 
 static int idedisk_capacity_proc_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, idedisk_capacity_proc_show, PDE(inode)->data);
+	return single_open(file, idedisk_capacity_proc_show, PDE_DATA(inode));
 }
 
 static const struct file_operations idedisk_capacity_proc_fops = {
@@ -115,7 +115,7 @@
 
 static int idedisk_sv_proc_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, idedisk_sv_proc_show, PDE(inode)->data);
+	return single_open(file, idedisk_sv_proc_show, PDE_DATA(inode));
 }
 
 static const struct file_operations idedisk_sv_proc_fops = {
@@ -133,7 +133,7 @@
 
 static int idedisk_st_proc_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, idedisk_st_proc_show, PDE(inode)->data);
+	return single_open(file, idedisk_st_proc_show, PDE_DATA(inode));
 }
 
 static const struct file_operations idedisk_st_proc_fops = {
diff --git a/drivers/ide/ide-floppy_proc.c b/drivers/ide/ide-floppy_proc.c
index 1600720..e7a25ea 100644
--- a/drivers/ide/ide-floppy_proc.c
+++ b/drivers/ide/ide-floppy_proc.c
@@ -15,7 +15,7 @@
 
 static int idefloppy_capacity_proc_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, idefloppy_capacity_proc_show, PDE(inode)->data);
+	return single_open(file, idefloppy_capacity_proc_show, PDE_DATA(inode));
 }
 
 static const struct file_operations idefloppy_capacity_proc_fops = {
diff --git a/drivers/ide/ide-proc.c b/drivers/ide/ide-proc.c
index 2abcc47..97c0700 100644
--- a/drivers/ide/ide-proc.c
+++ b/drivers/ide/ide-proc.c
@@ -58,7 +58,7 @@
 
 static int ide_imodel_proc_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, ide_imodel_proc_show, PDE(inode)->data);
+	return single_open(file, ide_imodel_proc_show, PDE_DATA(inode));
 }
 
 static const struct file_operations ide_imodel_proc_fops = {
@@ -82,7 +82,7 @@
 
 static int ide_mate_proc_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, ide_mate_proc_show, PDE(inode)->data);
+	return single_open(file, ide_mate_proc_show, PDE_DATA(inode));
 }
 
 static const struct file_operations ide_mate_proc_fops = {
@@ -103,7 +103,7 @@
 
 static int ide_channel_proc_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, ide_channel_proc_show, PDE(inode)->data);
+	return single_open(file, ide_channel_proc_show, PDE_DATA(inode));
 }
 
 static const struct file_operations ide_channel_proc_fops = {
@@ -143,7 +143,7 @@
 
 static int ide_identify_proc_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, ide_identify_proc_show, PDE(inode)->data);
+	return single_open(file, ide_identify_proc_show, PDE_DATA(inode));
 }
 
 static const struct file_operations ide_identify_proc_fops = {
@@ -325,7 +325,7 @@
 
 static int ide_settings_proc_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, ide_settings_proc_show, PDE(inode)->data);
+	return single_open(file, ide_settings_proc_show, PDE_DATA(inode));
 }
 
 #define MAX_LEN	30
@@ -333,7 +333,7 @@
 static ssize_t ide_settings_proc_write(struct file *file, const char __user *buffer,
 				       size_t count, loff_t *pos)
 {
-	ide_drive_t	*drive = (ide_drive_t *) PDE(file_inode(file))->data;
+	ide_drive_t	*drive = PDE_DATA(file_inode(file));
 	char		name[MAX_LEN + 1];
 	int		for_real = 0, mul_factor, div_factor;
 	unsigned long	n;
@@ -474,7 +474,7 @@
 
 static int ide_geometry_proc_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, ide_geometry_proc_show, PDE(inode)->data);
+	return single_open(file, ide_geometry_proc_show, PDE_DATA(inode));
 }
 
 const struct file_operations ide_geometry_proc_fops = {
@@ -497,7 +497,7 @@
 
 static int ide_dmodel_proc_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, ide_dmodel_proc_show, PDE(inode)->data);
+	return single_open(file, ide_dmodel_proc_show, PDE_DATA(inode));
 }
 
 static const struct file_operations ide_dmodel_proc_fops = {
@@ -525,7 +525,7 @@
 
 static int ide_driver_proc_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, ide_driver_proc_show, PDE(inode)->data);
+	return single_open(file, ide_driver_proc_show, PDE_DATA(inode));
 }
 
 static int ide_replace_subdriver(ide_drive_t *drive, const char *driver)
@@ -558,7 +558,7 @@
 static ssize_t ide_driver_proc_write(struct file *file, const char __user *buffer,
 				     size_t count, loff_t *pos)
 {
-	ide_drive_t	*drive = (ide_drive_t *) PDE(file_inode(file))->data;
+	ide_drive_t	*drive = PDE_DATA(file_inode(file));
 	char name[32];
 
 	if (!capable(CAP_SYS_ADMIN))
@@ -601,7 +601,7 @@
 
 static int ide_media_proc_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, ide_media_proc_show, PDE(inode)->data);
+	return single_open(file, ide_media_proc_show, PDE_DATA(inode));
 }
 
 static const struct file_operations ide_media_proc_fops = {
diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c
index ce8237d..89f8595 100644
--- a/drivers/ide/ide-tape.c
+++ b/drivers/ide/ide-tape.c
@@ -1847,7 +1847,7 @@
 
 static int idetape_name_proc_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, idetape_name_proc_show, PDE(inode)->data);
+	return single_open(file, idetape_name_proc_show, PDE_DATA(inode));
 }
 
 static const struct file_operations idetape_name_proc_fops = {
diff --git a/drivers/input/misc/hp_sdc_rtc.c b/drivers/input/misc/hp_sdc_rtc.c
index 2e3334b..770479d 100644
--- a/drivers/input/misc/hp_sdc_rtc.c
+++ b/drivers/input/misc/hp_sdc_rtc.c
@@ -41,6 +41,7 @@
 #include <linux/time.h>
 #include <linux/miscdevice.h>
 #include <linux/proc_fs.h>
+#include <linux/seq_file.h>
 #include <linux/poll.h>
 #include <linux/rtc.h>
 #include <linux/mutex.h>
@@ -74,9 +75,6 @@
 static int hp_sdc_rtc_open(struct inode *inode, struct file *file);
 static int hp_sdc_rtc_fasync (int fd, struct file *filp, int on);
 
-static int hp_sdc_rtc_read_proc(char *page, char **start, off_t off,
-				int count, int *eof, void *data);
-
 static void hp_sdc_rtc_isr (int irq, void *dev_id, 
 			    uint8_t status, uint8_t data) 
 {
@@ -427,22 +425,19 @@
         return fasync_helper (fd, filp, on, &hp_sdc_rtc_async_queue);
 }
 
-static int hp_sdc_rtc_proc_output (char *buf)
+static int hp_sdc_rtc_proc_show(struct seq_file *m, void *v)
 {
 #define YN(bit) ("no")
 #define NY(bit) ("yes")
-        char *p;
         struct rtc_time tm;
 	struct timeval tv;
 
 	memset(&tm, 0, sizeof(struct rtc_time));
 
-	p = buf;
-
 	if (hp_sdc_rtc_read_bbrtc(&tm)) {
-		p += sprintf(p, "BBRTC\t\t: READ FAILED!\n");
+		seq_puts(m, "BBRTC\t\t: READ FAILED!\n");
 	} else {
-		p += sprintf(p,
+		seq_printf(m,
 			     "rtc_time\t: %02d:%02d:%02d\n"
 			     "rtc_date\t: %04d-%02d-%02d\n"
 			     "rtc_epoch\t: %04lu\n",
@@ -452,41 +447,41 @@
 	}
 
 	if (hp_sdc_rtc_read_rt(&tv)) {
-		p += sprintf(p, "i8042 rtc\t: READ FAILED!\n");
+		seq_puts(m, "i8042 rtc\t: READ FAILED!\n");
 	} else {
-		p += sprintf(p, "i8042 rtc\t: %ld.%02d seconds\n", 
+		seq_printf(m, "i8042 rtc\t: %ld.%02d seconds\n", 
 			     tv.tv_sec, (int)tv.tv_usec/1000);
 	}
 
 	if (hp_sdc_rtc_read_fhs(&tv)) {
-		p += sprintf(p, "handshake\t: READ FAILED!\n");
+		seq_puts(m, "handshake\t: READ FAILED!\n");
 	} else {
-        	p += sprintf(p, "handshake\t: %ld.%02d seconds\n", 
+        	seq_printf(m, "handshake\t: %ld.%02d seconds\n", 
 			     tv.tv_sec, (int)tv.tv_usec/1000);
 	}
 
 	if (hp_sdc_rtc_read_mt(&tv)) {
-		p += sprintf(p, "alarm\t\t: READ FAILED!\n");
+		seq_puts(m, "alarm\t\t: READ FAILED!\n");
 	} else {
-		p += sprintf(p, "alarm\t\t: %ld.%02d seconds\n", 
+		seq_printf(m, "alarm\t\t: %ld.%02d seconds\n", 
 			     tv.tv_sec, (int)tv.tv_usec/1000);
 	}
 
 	if (hp_sdc_rtc_read_dt(&tv)) {
-		p += sprintf(p, "delay\t\t: READ FAILED!\n");
+		seq_puts(m, "delay\t\t: READ FAILED!\n");
 	} else {
-		p += sprintf(p, "delay\t\t: %ld.%02d seconds\n", 
+		seq_printf(m, "delay\t\t: %ld.%02d seconds\n", 
 			     tv.tv_sec, (int)tv.tv_usec/1000);
 	}
 
 	if (hp_sdc_rtc_read_ct(&tv)) {
-		p += sprintf(p, "periodic\t: READ FAILED!\n");
+		seq_puts(m, "periodic\t: READ FAILED!\n");
 	} else {
-		p += sprintf(p, "periodic\t: %ld.%02d seconds\n", 
+		seq_printf(m, "periodic\t: %ld.%02d seconds\n", 
 			     tv.tv_sec, (int)tv.tv_usec/1000);
 	}
 
-        p += sprintf(p,
+        seq_printf(m,
                      "DST_enable\t: %s\n"
                      "BCD\t\t: %s\n"
                      "24hr\t\t: %s\n"
@@ -506,23 +501,23 @@
                      1UL,
                      1 ? "okay" : "dead");
 
-        return  p - buf;
+        return 0;
 #undef YN
 #undef NY
 }
 
-static int hp_sdc_rtc_read_proc(char *page, char **start, off_t off,
-                         int count, int *eof, void *data)
+static int hp_sdc_rtc_proc_open(struct inode *inode, struct file *file)
 {
-	int len = hp_sdc_rtc_proc_output (page);
-        if (len <= off+count) *eof = 1;
-        *start = page + off;
-        len -= off;
-        if (len>count) len = count;
-        if (len<0) len = 0;
-        return len;
+	return single_open(file, hp_sdc_rtc_proc_show, NULL);
 }
 
+static const struct file_operations hp_sdc_rtc_proc_fops = {
+	.open		= hp_sdc_rtc_proc_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= seq_release,
+};
+
 static int hp_sdc_rtc_ioctl(struct file *file, 
 			    unsigned int cmd, unsigned long arg)
 {
@@ -715,8 +710,7 @@
 	if (misc_register(&hp_sdc_rtc_dev) != 0)
 		printk(KERN_INFO "Could not register misc. dev for i8042 rtc\n");
 
-        create_proc_read_entry ("driver/rtc", 0, NULL,
-				hp_sdc_rtc_read_proc, NULL);
+        proc_create("driver/rtc", 0, NULL, &hp_sdc_rtc_proc_fops);
 
 	printk(KERN_INFO "HP i8042 SDC + MSM-58321 RTC support loaded "
 			 "(RTC v " RTC_VERSION ")\n");
diff --git a/drivers/isdn/gigaset/capi.c b/drivers/isdn/gigaset/capi.c
index 03a0a01..3286903 100644
--- a/drivers/isdn/gigaset/capi.c
+++ b/drivers/isdn/gigaset/capi.c
@@ -2334,7 +2334,7 @@
 
 static int gigaset_proc_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, gigaset_proc_show, PDE(inode)->data);
+	return single_open(file, gigaset_proc_show, PDE_DATA(inode));
 }
 
 static const struct file_operations gigaset_proc_fops = {
diff --git a/drivers/isdn/hardware/avm/b1.c b/drivers/isdn/hardware/avm/b1.c
index 821f7ac..4d9b195 100644
--- a/drivers/isdn/hardware/avm/b1.c
+++ b/drivers/isdn/hardware/avm/b1.c
@@ -702,7 +702,7 @@
 
 static int b1ctl_proc_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, b1ctl_proc_show, PDE(inode)->data);
+	return single_open(file, b1ctl_proc_show, PDE_DATA(inode));
 }
 
 const struct file_operations b1ctl_proc_fops = {
diff --git a/drivers/isdn/hardware/avm/b1dma.c b/drivers/isdn/hardware/avm/b1dma.c
index 0896aa8..19b113f 100644
--- a/drivers/isdn/hardware/avm/b1dma.c
+++ b/drivers/isdn/hardware/avm/b1dma.c
@@ -944,7 +944,7 @@
 
 static int b1dmactl_proc_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, b1dmactl_proc_show, PDE(inode)->data);
+	return single_open(file, b1dmactl_proc_show, PDE_DATA(inode));
 }
 
 const struct file_operations b1dmactl_proc_fops = {
diff --git a/drivers/isdn/hardware/avm/c4.c b/drivers/isdn/hardware/avm/c4.c
index 1d7fc44..5d00d72 100644
--- a/drivers/isdn/hardware/avm/c4.c
+++ b/drivers/isdn/hardware/avm/c4.c
@@ -1129,7 +1129,7 @@
 
 static int c4_proc_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, c4_proc_show, PDE(inode)->data);
+	return single_open(file, c4_proc_show, PDE_DATA(inode));
 }
 
 static const struct file_operations c4_proc_fops = {
diff --git a/drivers/isdn/hardware/eicon/divasproc.c b/drivers/isdn/hardware/eicon/divasproc.c
index 3a4165c..56ce98a 100644
--- a/drivers/isdn/hardware/eicon/divasproc.c
+++ b/drivers/isdn/hardware/eicon/divasproc.c
@@ -145,7 +145,7 @@
 static ssize_t grp_opt_proc_write(struct file *file, const char __user *buffer,
 				  size_t count, loff_t *pos)
 {
-	diva_os_xdi_adapter_t *a = PDE(file_inode(file))->data;
+	diva_os_xdi_adapter_t *a = PDE_DATA(file_inode(file));
 	PISDN_ADAPTER IoAdapter = IoAdapters[a->controller - 1];
 
 	if ((count == 1) || (count == 2)) {
@@ -172,7 +172,7 @@
 static ssize_t d_l1_down_proc_write(struct file *file, const char __user *buffer,
 				    size_t count, loff_t *pos)
 {
-	diva_os_xdi_adapter_t *a = PDE(file_inode(file))->data;
+	diva_os_xdi_adapter_t *a = PDE_DATA(file_inode(file));
 	PISDN_ADAPTER IoAdapter = IoAdapters[a->controller - 1];
 
 	if ((count == 1) || (count == 2)) {
@@ -210,7 +210,7 @@
 
 static int d_l1_down_proc_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, d_l1_down_proc_show, PDE(inode)->data);
+	return single_open(file, d_l1_down_proc_show, PDE_DATA(inode));
 }
 
 static const struct file_operations d_l1_down_proc_fops = {
@@ -236,7 +236,7 @@
 
 static int grp_opt_proc_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, grp_opt_proc_show, PDE(inode)->data);
+	return single_open(file, grp_opt_proc_show, PDE_DATA(inode));
 }
 
 static const struct file_operations grp_opt_proc_fops = {
@@ -251,7 +251,7 @@
 static ssize_t info_proc_write(struct file *file, const char __user *buffer,
 			       size_t count, loff_t *pos)
 {
-	diva_os_xdi_adapter_t *a = PDE(file_inode(file))->data;
+	diva_os_xdi_adapter_t *a = PDE_DATA(file_inode(file));
 	PISDN_ADAPTER IoAdapter = IoAdapters[a->controller - 1];
 	char c[4];
 
@@ -335,7 +335,7 @@
 
 static int info_proc_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, info_proc_show, PDE(inode)->data);
+	return single_open(file, info_proc_show, PDE_DATA(inode));
 }
 
 static const struct file_operations info_proc_fops = {
diff --git a/drivers/isdn/hysdn/hycapi.c b/drivers/isdn/hysdn/hycapi.c
index 931f916..00aad10 100644
--- a/drivers/isdn/hysdn/hycapi.c
+++ b/drivers/isdn/hysdn/hycapi.c
@@ -469,7 +469,7 @@
 
 static int hycapi_proc_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, hycapi_proc_show, PDE(inode)->data);
+	return single_open(file, hycapi_proc_show, PDE_DATA(inode));
 }
 
 static const struct file_operations hycapi_proc_fops = {
diff --git a/drivers/isdn/hysdn/hysdn_procconf.c b/drivers/isdn/hysdn/hysdn_procconf.c
index 8023d25..7307921 100644
--- a/drivers/isdn/hysdn/hysdn_procconf.c
+++ b/drivers/isdn/hysdn/hysdn_procconf.c
@@ -229,23 +229,12 @@
 hysdn_conf_open(struct inode *ino, struct file *filep)
 {
 	hysdn_card *card;
-	struct proc_dir_entry *pd;
 	struct conf_writedata *cnf;
 	char *cp, *tmp;
 
 	/* now search the addressed card */
 	mutex_lock(&hysdn_conf_mutex);
-	card = card_root;
-	while (card) {
-		pd = card->procconf;
-		if (pd == PDE(ino))
-			break;
-		card = card->next;	/* search next entry */
-	}
-	if (!card) {
-		mutex_unlock(&hysdn_conf_mutex);
-		return (-ENODEV);	/* device is unknown/invalid */
-	}
+	card = PDE_DATA(ino);
 	if (card->debug_flags & (LOG_PROC_OPEN | LOG_PROC_ALL))
 		hysdn_addlog(card, "config open for uid=%d gid=%d mode=0x%x",
 			     filep->f_cred->fsuid, filep->f_cred->fsgid,
@@ -317,21 +306,9 @@
 	hysdn_card *card;
 	struct conf_writedata *cnf;
 	int retval = 0;
-	struct proc_dir_entry *pd;
 
 	mutex_lock(&hysdn_conf_mutex);
-	/* search the addressed card */
-	card = card_root;
-	while (card) {
-		pd = card->procconf;
-		if (pd == PDE(ino))
-			break;
-		card = card->next;	/* search next entry */
-	}
-	if (!card) {
-		mutex_unlock(&hysdn_conf_mutex);
-		return (-ENODEV);	/* device is unknown/invalid */
-	}
+	card = PDE_DATA(ino);
 	if (card->debug_flags & (LOG_PROC_OPEN | LOG_PROC_ALL))
 		hysdn_addlog(card, "config close for uid=%d gid=%d mode=0x%x",
 			     filep->f_cred->fsuid, filep->f_cred->fsgid,
@@ -394,10 +371,11 @@
 	while (card) {
 
 		sprintf(conf_name, "%s%d", PROC_CONF_BASENAME, card->myid);
-		if ((card->procconf = (void *) proc_create(conf_name,
+		if ((card->procconf = (void *) proc_create_data(conf_name,
 							   S_IFREG | S_IRUGO | S_IWUSR,
 							   hysdn_proc_entry,
-							   &conf_fops)) != NULL) {
+							   &conf_fops,
+							   card)) != NULL) {
 			hysdn_proclog_init(card);	/* init the log file entry */
 		}
 		card = card->next;	/* next entry */
diff --git a/drivers/isdn/hysdn/hysdn_proclog.c b/drivers/isdn/hysdn/hysdn_proclog.c
index 9a3ce93..b61e8d5 100644
--- a/drivers/isdn/hysdn/hysdn_proclog.c
+++ b/drivers/isdn/hysdn/hysdn_proclog.c
@@ -173,27 +173,14 @@
 {
 	struct log_data *inf;
 	int len;
-	struct proc_dir_entry *pde = PDE(file_inode(file));
-	struct procdata *pd = NULL;
-	hysdn_card *card;
+	hysdn_card *card = PDE_DATA(file_inode(file));
 
 	if (!*((struct log_data **) file->private_data)) {
+		struct procdata *pd = card->proclog;
 		if (file->f_flags & O_NONBLOCK)
 			return (-EAGAIN);
 
-		/* sorry, but we need to search the card */
-		card = card_root;
-		while (card) {
-			pd = card->proclog;
-			if (pd->log == pde)
-				break;
-			card = card->next;	/* search next entry */
-		}
-		if (card)
-			interruptible_sleep_on(&(pd->rd_queue));
-		else
-			return (-EAGAIN);
-
+		interruptible_sleep_on(&(pd->rd_queue));
 	}
 	if (!(inf = *((struct log_data **) file->private_data)))
 		return (0);
@@ -215,27 +202,15 @@
 static int
 hysdn_log_open(struct inode *ino, struct file *filep)
 {
-	hysdn_card *card;
-	struct procdata *pd = NULL;
-	unsigned long flags;
+	hysdn_card *card = PDE_DATA(ino);
 
 	mutex_lock(&hysdn_log_mutex);
-	card = card_root;
-	while (card) {
-		pd = card->proclog;
-		if (pd->log == PDE(ino))
-			break;
-		card = card->next;	/* search next entry */
-	}
-	if (!card) {
-		mutex_unlock(&hysdn_log_mutex);
-		return (-ENODEV);	/* device is unknown/invalid */
-	}
-	filep->private_data = card;	/* remember our own card */
-
 	if ((filep->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_WRITE) {
 		/* write only access -> write log level only */
+		filep->private_data = card;	/* remember our own card */
 	} else if ((filep->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ) {
+		struct procdata *pd = card->proclog;
+		unsigned long flags;
 
 		/* read access -> log/debug read */
 		spin_lock_irqsave(&card->hysdn_lock, flags);
@@ -275,21 +250,13 @@
 	} else {
 		/* read access -> log/debug read, mark one further file as closed */
 
-		pd = NULL;
 		inf = *((struct log_data **) filep->private_data);	/* get first log entry */
 		if (inf)
 			pd = (struct procdata *) inf->proc_ctrl;	/* still entries there */
 		else {
 			/* no info available -> search card */
-			card = card_root;
-			while (card) {
-				pd = card->proclog;
-				if (pd->log == PDE(ino))
-					break;
-				card = card->next;	/* search next entry */
-			}
-			if (card)
-				pd = card->proclog;	/* pointer to procfs log */
+			card = PDE_DATA(file_inode(filep));
+			pd = card->proclog;	/* pointer to procfs log */
 		}
 		if (pd)
 			pd->if_used--;	/* decrement interface usage count by one */
@@ -319,24 +286,12 @@
 hysdn_log_poll(struct file *file, poll_table *wait)
 {
 	unsigned int mask = 0;
-	struct proc_dir_entry *pde = PDE(file_inode(file));
-	hysdn_card *card;
-	struct procdata *pd = NULL;
+	hysdn_card *card = PDE_DATA(file_inode(file));
+	struct procdata *pd = card->proclog;
 
 	if ((file->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_WRITE)
 		return (mask);	/* no polling for write supported */
 
-	/* we need to search the card */
-	card = card_root;
-	while (card) {
-		pd = card->proclog;
-		if (pd->log == pde)
-			break;
-		card = card->next;	/* search next entry */
-	}
-	if (!card)
-		return (mask);	/* card not found */
-
 	poll_wait(file, &(pd->rd_queue), wait);
 
 	if (*((struct log_data **) file->private_data))
@@ -373,9 +328,9 @@
 
 	if ((pd = kzalloc(sizeof(struct procdata), GFP_KERNEL)) != NULL) {
 		sprintf(pd->log_name, "%s%d", PROC_LOG_BASENAME, card->myid);
-		pd->log = proc_create(pd->log_name,
+		pd->log = proc_create_data(pd->log_name,
 				      S_IFREG | S_IRUGO | S_IWUSR, hysdn_proc_entry,
-				      &log_fops);
+				      &log_fops, card);
 
 		init_waitqueue_head(&(pd->rd_queue));
 
diff --git a/drivers/isdn/mISDN/timerdev.c b/drivers/isdn/mISDN/timerdev.c
index 1094667..9438d7e 100644
--- a/drivers/isdn/mISDN/timerdev.c
+++ b/drivers/isdn/mISDN/timerdev.c
@@ -64,7 +64,6 @@
 	dev->work = 0;
 	init_waitqueue_head(&dev->wait);
 	filep->private_data = dev;
-	__module_get(THIS_MODULE);
 	return nonseekable_open(ino, filep);
 }
 
@@ -72,19 +71,28 @@
 mISDN_close(struct inode *ino, struct file *filep)
 {
 	struct mISDNtimerdev	*dev = filep->private_data;
+	struct list_head	*list = &dev->pending;
 	struct mISDNtimer	*timer, *next;
 
 	if (*debug & DEBUG_TIMER)
 		printk(KERN_DEBUG "%s(%p,%p)\n", __func__, ino, filep);
-	list_for_each_entry_safe(timer, next, &dev->pending, list) {
-		del_timer(&timer->tl);
+
+	spin_lock_irq(&dev->lock);
+	while (!list_empty(list)) {
+		timer = list_first_entry(list, struct mISDNtimer, list);
+		spin_unlock_irq(&dev->lock);
+		del_timer_sync(&timer->tl);
+		spin_lock_irq(&dev->lock);
+		/* it might have been moved to ->expired */
+		list_del(&timer->list);
 		kfree(timer);
 	}
+	spin_unlock_irq(&dev->lock);
+
 	list_for_each_entry_safe(timer, next, &dev->expired, list) {
 		kfree(timer);
 	}
 	kfree(dev);
-	module_put(THIS_MODULE);
 	return 0;
 }
 
@@ -92,36 +100,41 @@
 mISDN_read(struct file *filep, char __user *buf, size_t count, loff_t *off)
 {
 	struct mISDNtimerdev	*dev = filep->private_data;
+	struct list_head *list = &dev->expired;
 	struct mISDNtimer	*timer;
-	u_long	flags;
 	int	ret = 0;
 
 	if (*debug & DEBUG_TIMER)
 		printk(KERN_DEBUG "%s(%p, %p, %d, %p)\n", __func__,
 		       filep, buf, (int)count, off);
 
-	if (list_empty(&dev->expired) && (dev->work == 0)) {
+	if (count < sizeof(int))
+		return -ENOSPC;
+
+	spin_lock_irq(&dev->lock);
+	while (list_empty(list) && (dev->work == 0)) {
+		spin_unlock_irq(&dev->lock);
 		if (filep->f_flags & O_NONBLOCK)
 			return -EAGAIN;
 		wait_event_interruptible(dev->wait, (dev->work ||
-						     !list_empty(&dev->expired)));
+						     !list_empty(list)));
 		if (signal_pending(current))
 			return -ERESTARTSYS;
+		spin_lock_irq(&dev->lock);
 	}
-	if (count < sizeof(int))
-		return -ENOSPC;
 	if (dev->work)
 		dev->work = 0;
-	if (!list_empty(&dev->expired)) {
-		spin_lock_irqsave(&dev->lock, flags);
-		timer = (struct mISDNtimer *)dev->expired.next;
+	if (!list_empty(list)) {
+		timer = list_first_entry(list, struct mISDNtimer, list);
 		list_del(&timer->list);
-		spin_unlock_irqrestore(&dev->lock, flags);
+		spin_unlock_irq(&dev->lock);
 		if (put_user(timer->id, (int __user *)buf))
 			ret = -EFAULT;
 		else
 			ret = sizeof(int);
 		kfree(timer);
+	} else {
+		spin_unlock_irq(&dev->lock);
 	}
 	return ret;
 }
@@ -153,7 +166,8 @@
 	u_long			flags;
 
 	spin_lock_irqsave(&timer->dev->lock, flags);
-	list_move_tail(&timer->list, &timer->dev->expired);
+	if (timer->id >= 0)
+		list_move_tail(&timer->list, &timer->dev->expired);
 	spin_unlock_irqrestore(&timer->dev->lock, flags);
 	wake_up_interruptible(&timer->dev->wait);
 }
@@ -162,7 +176,6 @@
 misdn_add_timer(struct mISDNtimerdev *dev, int timeout)
 {
 	int			id;
-	u_long			flags;
 	struct mISDNtimer	*timer;
 
 	if (!timeout) {
@@ -173,19 +186,16 @@
 		timer = kzalloc(sizeof(struct mISDNtimer), GFP_KERNEL);
 		if (!timer)
 			return -ENOMEM;
-		spin_lock_irqsave(&dev->lock, flags);
-		timer->id = dev->next_id++;
+		timer->dev = dev;
+		setup_timer(&timer->tl, dev_expire_timer, (long)timer);
+		spin_lock_irq(&dev->lock);
+		id = timer->id = dev->next_id++;
 		if (dev->next_id < 0)
 			dev->next_id = 1;
 		list_add_tail(&timer->list, &dev->pending);
-		spin_unlock_irqrestore(&dev->lock, flags);
-		timer->dev = dev;
-		timer->tl.data = (long)timer;
-		timer->tl.function = dev_expire_timer;
-		init_timer(&timer->tl);
 		timer->tl.expires = jiffies + ((HZ * (u_long)timeout) / 1000);
 		add_timer(&timer->tl);
-		id = timer->id;
+		spin_unlock_irq(&dev->lock);
 	}
 	return id;
 }
@@ -193,26 +203,21 @@
 static int
 misdn_del_timer(struct mISDNtimerdev *dev, int id)
 {
-	u_long			flags;
 	struct mISDNtimer	*timer;
-	int			ret = 0;
 
-	spin_lock_irqsave(&dev->lock, flags);
+	spin_lock_irq(&dev->lock);
 	list_for_each_entry(timer, &dev->pending, list) {
 		if (timer->id == id) {
 			list_del_init(&timer->list);
-			/* RED-PEN AK: race -- timer can be still running on
-			 * other CPU. Needs reference count I think
-			 */
-			del_timer(&timer->tl);
-			ret = timer->id;
+			timer->id = -1;
+			spin_unlock_irq(&dev->lock);
+			del_timer_sync(&timer->tl);
 			kfree(timer);
-			goto unlock;
+			return id;
 		}
 	}
-unlock:
-	spin_unlock_irqrestore(&dev->lock, flags);
-	return ret;
+	spin_unlock_irq(&dev->lock);
+	return 0;
 }
 
 static long
@@ -262,6 +267,7 @@
 }
 
 static const struct file_operations mISDN_fops = {
+	.owner		= THIS_MODULE,
 	.read		= mISDN_read,
 	.poll		= mISDN_poll,
 	.unlocked_ioctl	= mISDN_ioctl,
diff --git a/drivers/macintosh/via-pmu.c b/drivers/macintosh/via-pmu.c
index 22b8ce4..c31fbab 100644
--- a/drivers/macintosh/via-pmu.c
+++ b/drivers/macintosh/via-pmu.c
@@ -869,7 +869,7 @@
 
 static int pmu_battery_proc_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, pmu_battery_proc_show, PDE(inode)->data);
+	return single_open(file, pmu_battery_proc_show, PDE_DATA(inode));
 }
 
 static const struct file_operations pmu_battery_proc_fops = {
diff --git a/drivers/media/dvb-core/dvb_frontend.c b/drivers/media/dvb-core/dvb_frontend.c
index 57601c0..1f925e8 100644
--- a/drivers/media/dvb-core/dvb_frontend.c
+++ b/drivers/media/dvb-core/dvb_frontend.c
@@ -2527,11 +2527,8 @@
 
 	if (dvbdev->users == -1) {
 		wake_up(&fepriv->wait_queue);
-		if (fepriv->exit != DVB_FE_NO_EXIT) {
-			fops_put(file->f_op);
-			file->f_op = NULL;
+		if (fepriv->exit != DVB_FE_NO_EXIT)
 			wake_up(&dvbdev->wait_queue);
-		}
 		if (fe->ops.ts_bus_ctrl)
 			fe->ops.ts_bus_ctrl(fe, 0);
 	}
diff --git a/drivers/media/dvb-core/dvb_net.c b/drivers/media/dvb-core/dvb_net.c
index c3cc3b5..f91c80c 100644
--- a/drivers/media/dvb-core/dvb_net.c
+++ b/drivers/media/dvb-core/dvb_net.c
@@ -1479,11 +1479,8 @@
 
 	dvb_generic_release(inode, file);
 
-	if(dvbdev->users == 1 && dvbnet->exit == 1) {
-		fops_put(file->f_op);
-		file->f_op = NULL;
+	if(dvbdev->users == 1 && dvbnet->exit == 1)
 		wake_up(&dvbdev->wait_queue);
-	}
 	return 0;
 }
 
diff --git a/drivers/media/pci/cx25821/cx25821-audio-upstream.c b/drivers/media/pci/cx25821/cx25821-audio-upstream.c
index b9be535..68dbc2d 100644
--- a/drivers/media/pci/cx25821/cx25821-audio-upstream.c
+++ b/drivers/media/pci/cx25821/cx25821-audio-upstream.c
@@ -259,80 +259,47 @@
 static int cx25821_get_audio_data(struct cx25821_dev *dev,
 			   const struct sram_channel *sram_ch)
 {
-	struct file *myfile;
+	struct file *file;
 	int frame_index_temp = dev->_audioframe_index;
 	int i = 0;
-	int line_size = AUDIO_LINE_SIZE;
 	int frame_size = AUDIO_DATA_BUF_SZ;
 	int frame_offset = frame_size * frame_index_temp;
-	ssize_t vfs_read_retval = 0;
-	char mybuf[line_size];
+	char mybuf[AUDIO_LINE_SIZE];
 	loff_t file_offset = dev->_audioframe_count * frame_size;
-	loff_t pos;
-	mm_segment_t old_fs;
+	char *p = NULL;
 
 	if (dev->_audiofile_status == END_OF_FILE)
 		return 0;
 
-	myfile = filp_open(dev->_audiofilename, O_RDONLY | O_LARGEFILE, 0);
-
-	if (IS_ERR(myfile)) {
-		const int open_errno = -PTR_ERR(myfile);
-		pr_err("%s(): ERROR opening file(%s) with errno = %d!\n",
-		       __func__, dev->_audiofilename, open_errno);
-		return PTR_ERR(myfile);
-	} else {
-		if (!(myfile->f_op)) {
-			pr_err("%s(): File has no file operations registered!\n",
-				__func__);
-			filp_close(myfile, NULL);
-			return -EIO;
-		}
-
-		if (!myfile->f_op->read) {
-			pr_err("%s(): File has no READ operations registered!\n",
-				__func__);
-			filp_close(myfile, NULL);
-			return -EIO;
-		}
-
-		pos = myfile->f_pos;
-		old_fs = get_fs();
-		set_fs(KERNEL_DS);
-
-		for (i = 0; i < dev->_audio_lines_count; i++) {
-			pos = file_offset;
-
-			vfs_read_retval = vfs_read(myfile, mybuf, line_size,
-									&pos);
-
-			if (vfs_read_retval > 0 && vfs_read_retval == line_size
-			    && dev->_audiodata_buf_virt_addr != NULL) {
-				memcpy((void *)(dev->_audiodata_buf_virt_addr +
-						frame_offset / 4), mybuf,
-					vfs_read_retval);
-			}
-
-			file_offset += vfs_read_retval;
-			frame_offset += vfs_read_retval;
-
-			if (vfs_read_retval < line_size) {
-				pr_info("Done: exit %s() since no more bytes to read from Audio file\n",
-					__func__);
-				break;
-			}
-		}
-
-		if (i > 0)
-			dev->_audioframe_count++;
-
-		dev->_audiofile_status = (vfs_read_retval == line_size) ?
-						IN_PROGRESS : END_OF_FILE;
-
-		set_fs(old_fs);
-		filp_close(myfile, NULL);
+	file = filp_open(dev->_audiofilename, O_RDONLY | O_LARGEFILE, 0);
+	if (IS_ERR(file)) {
+		pr_err("%s(): ERROR opening file(%s) with errno = %ld!\n",
+		       __func__, dev->_audiofilename, -PTR_ERR(file));
+		return PTR_ERR(file);
 	}
 
+	if (dev->_audiodata_buf_virt_addr)
+		p = (char *)dev->_audiodata_buf_virt_addr + frame_offset;
+
+	for (i = 0; i < dev->_audio_lines_count; i++) {
+		int n = kernel_read(file, file_offset, mybuf, AUDIO_LINE_SIZE);
+		if (n < AUDIO_LINE_SIZE) {
+			pr_info("Done: exit %s() since no more bytes to read from Audio file\n",
+				__func__);
+			dev->_audiofile_status = END_OF_FILE;
+			fput(file);
+			return 0;
+		}
+		dev->_audiofile_status = IN_PROGRESS;
+		if (p) {
+			memcpy(p, mybuf, n);
+			p += n;
+		}
+		file_offset += n;
+	}
+	dev->_audioframe_count++;
+	fput(file);
+
 	return 0;
 }
 
@@ -354,81 +321,41 @@
 static int cx25821_openfile_audio(struct cx25821_dev *dev,
 			   const struct sram_channel *sram_ch)
 {
-	struct file *myfile;
-	int i = 0, j = 0;
-	int line_size = AUDIO_LINE_SIZE;
-	ssize_t vfs_read_retval = 0;
-	char mybuf[line_size];
-	loff_t pos;
-	loff_t offset = (unsigned long)0;
-	mm_segment_t old_fs;
+	char *p = (void *)dev->_audiodata_buf_virt_addr;
+	struct file *file;
+	loff_t offset;
+	int i, j;
 
-	myfile = filp_open(dev->_audiofilename, O_RDONLY | O_LARGEFILE, 0);
-
-	if (IS_ERR(myfile)) {
-		const int open_errno = -PTR_ERR(myfile);
-		pr_err("%s(): ERROR opening file(%s) with errno = %d!\n",
-			__func__, dev->_audiofilename, open_errno);
-		return PTR_ERR(myfile);
-	} else {
-		if (!(myfile->f_op)) {
-			pr_err("%s(): File has no file operations registered!\n",
-				__func__);
-			filp_close(myfile, NULL);
-			return -EIO;
-		}
-
-		if (!myfile->f_op->read) {
-			pr_err("%s(): File has no READ operations registered!\n",
-				__func__);
-			filp_close(myfile, NULL);
-			return -EIO;
-		}
-
-		pos = myfile->f_pos;
-		old_fs = get_fs();
-		set_fs(KERNEL_DS);
-
-		for (j = 0; j < NUM_AUDIO_FRAMES; j++) {
-			for (i = 0; i < dev->_audio_lines_count; i++) {
-				pos = offset;
-
-				vfs_read_retval = vfs_read(myfile, mybuf,
-						line_size, &pos);
-
-				if (vfs_read_retval > 0 &&
-				    vfs_read_retval == line_size &&
-				    dev->_audiodata_buf_virt_addr != NULL) {
-					memcpy((void *)(dev->
-							_audiodata_buf_virt_addr
-							+ offset / 4), mybuf,
-					       vfs_read_retval);
-				}
-
-				offset += vfs_read_retval;
-
-				if (vfs_read_retval < line_size) {
-					pr_info("Done: exit %s() since no more bytes to read from Audio file\n",
-						__func__);
-					break;
-				}
-			}
-
-			if (i > 0)
-				dev->_audioframe_count++;
-
-			if (vfs_read_retval < line_size)
-				break;
-		}
-
-		dev->_audiofile_status = (vfs_read_retval == line_size) ?
-						IN_PROGRESS : END_OF_FILE;
-
-		set_fs(old_fs);
-		myfile->f_pos = 0;
-		filp_close(myfile, NULL);
+	file = filp_open(dev->_audiofilename, O_RDONLY | O_LARGEFILE, 0);
+	if (IS_ERR(file)) {
+		pr_err("%s(): ERROR opening file(%s) with errno = %ld!\n",
+			__func__, dev->_audiofilename, PTR_ERR(file));
+		return PTR_ERR(file);
 	}
 
+	for (j = 0, offset = 0; j < NUM_AUDIO_FRAMES; j++) {
+		for (i = 0; i < dev->_audio_lines_count; i++) {
+			char buf[AUDIO_LINE_SIZE];
+			int n = kernel_read(file, offset, buf,
+						AUDIO_LINE_SIZE);
+
+			if (n < AUDIO_LINE_SIZE) {
+				pr_info("Done: exit %s() since no more bytes to read from Audio file\n",
+					__func__);
+				dev->_audiofile_status = END_OF_FILE;
+				fput(file);
+				return 0;
+			}
+
+			if (p)
+				memcpy(p + offset, buf, n);
+
+			offset += n;
+		}
+		dev->_audioframe_count++;
+	}
+	dev->_audiofile_status = IN_PROGRESS;
+	fput(file);
 	return 0;
 }
 
diff --git a/drivers/media/pci/ttpci/av7110_ir.c b/drivers/media/pci/ttpci/av7110_ir.c
index eb82286..0e763a7 100644
--- a/drivers/media/pci/ttpci/av7110_ir.c
+++ b/drivers/media/pci/ttpci/av7110_ir.c
@@ -375,7 +375,7 @@
 	if (av_cnt == 1) {
 		e = proc_create("av7110_ir", S_IWUSR, NULL, &av7110_ir_proc_fops);
 		if (e)
-			e->size = 4 + 256 * sizeof(u16);
+			proc_set_size(e, 4 + 256 * sizeof(u16));
 	}
 
 	tasklet_init(&av7110->ir.ir_tasklet, av7110_emit_key, (unsigned long) &av7110->ir);
diff --git a/drivers/media/pci/zoran/zoran_procfs.c b/drivers/media/pci/zoran/zoran_procfs.c
index 1512b5d..f7ceee0 100644
--- a/drivers/media/pci/zoran/zoran_procfs.c
+++ b/drivers/media/pci/zoran/zoran_procfs.c
@@ -130,14 +130,14 @@
 
 static int zoran_open(struct inode *inode, struct file *file)
 {
-	struct zoran *data = PDE(inode)->data;
+	struct zoran *data = PDE_DATA(inode);
 	return single_open(file, zoran_show, data);
 }
 
 static ssize_t zoran_write(struct file *file, const char __user *buffer,
 			size_t count, loff_t *ppos)
 {
-	struct zoran *zr = PDE(file_inode(file))->data;
+	struct zoran *zr = PDE_DATA(file_inode(file));
 	char *string, *sp;
 	char *line, *ldelim, *varname, *svar, *tdelim;
 
diff --git a/drivers/media/rc/ir-lirc-codec.c b/drivers/media/rc/ir-lirc-codec.c
index ff4d93d..e456126 100644
--- a/drivers/media/rc/ir-lirc-codec.c
+++ b/drivers/media/rc/ir-lirc-codec.c
@@ -307,7 +307,7 @@
 	return;
 }
 
-static struct file_operations lirc_fops = {
+static const struct file_operations lirc_fops = {
 	.owner		= THIS_MODULE,
 	.write		= ir_lirc_transmit_ir,
 	.unlocked_ioctl	= ir_lirc_ioctl,
diff --git a/drivers/media/rc/lirc_dev.c b/drivers/media/rc/lirc_dev.c
index 5247d94..8dc057b 100644
--- a/drivers/media/rc/lirc_dev.c
+++ b/drivers/media/rc/lirc_dev.c
@@ -152,7 +152,7 @@
 }
 
 
-static struct file_operations lirc_dev_fops = {
+static const struct file_operations lirc_dev_fops = {
 	.owner		= THIS_MODULE,
 	.read		= lirc_dev_fop_read,
 	.write		= lirc_dev_fop_write,
diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c
index fb69baa..767ff4d 100644
--- a/drivers/message/fusion/mptbase.c
+++ b/drivers/message/fusion/mptbase.c
@@ -6656,7 +6656,7 @@
 
 static int mpt_summary_proc_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, mpt_summary_proc_show, PDE(inode)->data);
+	return single_open(file, mpt_summary_proc_show, PDE_DATA(inode));
 }
 
 static const struct file_operations mpt_summary_proc_fops = {
@@ -6805,7 +6805,7 @@
 
 static int mpt_iocinfo_proc_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, mpt_iocinfo_proc_show, PDE(inode)->data);
+	return single_open(file, mpt_iocinfo_proc_show, PDE_DATA(inode));
 }
 
 static const struct file_operations mpt_iocinfo_proc_fops = {
diff --git a/drivers/message/fusion/mptctl.c b/drivers/message/fusion/mptctl.c
index b383b69..dcc8385 100644
--- a/drivers/message/fusion/mptctl.c
+++ b/drivers/message/fusion/mptctl.c
@@ -597,13 +597,6 @@
 }
 
 static int
-mptctl_release(struct inode *inode, struct file *filep)
-{
-	fasync_helper(-1, filep, 0, &async_queue);
-	return 0;
-}
-
-static int
 mptctl_fasync(int fd, struct file *filep, int mode)
 {
 	MPT_ADAPTER	*ioc;
@@ -2822,7 +2815,6 @@
 	.llseek =	no_llseek,
 	.fasync = 	mptctl_fasync,
 	.unlocked_ioctl = mptctl_ioctl,
-	.release =	mptctl_release,
 #ifdef CONFIG_COMPAT
 	.compat_ioctl = compat_mpctl_ioctl,
 #endif
diff --git a/drivers/message/fusion/mptfc.c b/drivers/message/fusion/mptfc.c
index c13cd9b..fd75108 100644
--- a/drivers/message/fusion/mptfc.c
+++ b/drivers/message/fusion/mptfc.c
@@ -109,7 +109,7 @@
 static struct scsi_host_template mptfc_driver_template = {
 	.module				= THIS_MODULE,
 	.proc_name			= "mptfc",
-	.proc_info			= mptscsih_proc_info,
+	.show_info			= mptscsih_show_info,
 	.name				= "MPT FC Host",
 	.info				= mptscsih_info,
 	.queuecommand			= mptfc_qcmd,
diff --git a/drivers/message/fusion/mptsas.c b/drivers/message/fusion/mptsas.c
index fa43c39..ffee6f7 100644
--- a/drivers/message/fusion/mptsas.c
+++ b/drivers/message/fusion/mptsas.c
@@ -1977,7 +1977,7 @@
 static struct scsi_host_template mptsas_driver_template = {
 	.module				= THIS_MODULE,
 	.proc_name			= "mptsas",
-	.proc_info			= mptscsih_proc_info,
+	.show_info			= mptscsih_show_info,
 	.name				= "MPT SAS Host",
 	.info				= mptscsih_info,
 	.queuecommand			= mptsas_qcmd,
diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c
index 164afa7..727819c 100644
--- a/drivers/message/fusion/mptscsih.c
+++ b/drivers/message/fusion/mptscsih.c
@@ -1284,101 +1284,17 @@
 	return h->info_kbuf;
 }
 
-struct info_str {
-	char *buffer;
-	int   length;
-	int   offset;
-	int   pos;
-};
-
-static void
-mptscsih_copy_mem_info(struct info_str *info, char *data, int len)
-{
-	if (info->pos + len > info->length)
-		len = info->length - info->pos;
-
-	if (info->pos + len < info->offset) {
-		info->pos += len;
-		return;
-	}
-
-	if (info->pos < info->offset) {
-	        data += (info->offset - info->pos);
-	        len  -= (info->offset - info->pos);
-	}
-
-	if (len > 0) {
-                memcpy(info->buffer + info->pos, data, len);
-                info->pos += len;
-	}
-}
-
-static int
-mptscsih_copy_info(struct info_str *info, char *fmt, ...)
-{
-	va_list args;
-	char buf[81];
-	int len;
-
-	va_start(args, fmt);
-	len = vsprintf(buf, fmt, args);
-	va_end(args);
-
-	mptscsih_copy_mem_info(info, buf, len);
-	return len;
-}
-
-static int
-mptscsih_host_info(MPT_ADAPTER *ioc, char *pbuf, off_t offset, int len)
-{
-	struct info_str info;
-
-	info.buffer	= pbuf;
-	info.length	= len;
-	info.offset	= offset;
-	info.pos	= 0;
-
-	mptscsih_copy_info(&info, "%s: %s, ", ioc->name, ioc->prod_name);
-	mptscsih_copy_info(&info, "%s%08xh, ", MPT_FW_REV_MAGIC_ID_STRING, ioc->facts.FWVersion.Word);
-	mptscsih_copy_info(&info, "Ports=%d, ", ioc->facts.NumberOfPorts);
-	mptscsih_copy_info(&info, "MaxQ=%d\n", ioc->req_depth);
-
-	return ((info.pos > info.offset) ? info.pos - info.offset : 0);
-}
-
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/**
- *	mptscsih_proc_info - Return information about MPT adapter
- * 	@host:   scsi host struct
- * 	@buffer: if write, user data; if read, buffer for user
- *	@start: returns the buffer address
- * 	@offset: if write, 0; if read, the current offset into the buffer from
- * 		 the previous read.
- * 	@length: if write, return length;
- *	@func:   write = 1; read = 0
- *
- *	(linux scsi_host_template.info routine)
- */
-int
-mptscsih_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t offset,
-			int length, int func)
+int mptscsih_show_info(struct seq_file *m, struct Scsi_Host *host)
 {
 	MPT_SCSI_HOST	*hd = shost_priv(host);
 	MPT_ADAPTER	*ioc = hd->ioc;
-	int size = 0;
 
-	if (func) {
-		/*
-		 * write is not supported
-		 */
-	} else {
-		if (start)
-			*start = buffer;
+	seq_printf(m, "%s: %s, ", ioc->name, ioc->prod_name);
+	seq_printf(m, "%s%08xh, ", MPT_FW_REV_MAGIC_ID_STRING, ioc->facts.FWVersion.Word);
+	seq_printf(m, "Ports=%d, ", ioc->facts.NumberOfPorts);
+	seq_printf(m, "MaxQ=%d\n", ioc->req_depth);
 
-		size = mptscsih_host_info(ioc, buffer, offset, length);
-	}
-
-	return size;
+	return 0;
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -3348,7 +3264,7 @@
 EXPORT_SYMBOL(mptscsih_suspend);
 EXPORT_SYMBOL(mptscsih_resume);
 #endif
-EXPORT_SYMBOL(mptscsih_proc_info);
+EXPORT_SYMBOL(mptscsih_show_info);
 EXPORT_SYMBOL(mptscsih_info);
 EXPORT_SYMBOL(mptscsih_qcmd);
 EXPORT_SYMBOL(mptscsih_slave_destroy);
diff --git a/drivers/message/fusion/mptscsih.h b/drivers/message/fusion/mptscsih.h
index 43e75ff..83f5031 100644
--- a/drivers/message/fusion/mptscsih.h
+++ b/drivers/message/fusion/mptscsih.h
@@ -111,7 +111,7 @@
 extern int mptscsih_suspend(struct pci_dev *pdev, pm_message_t state);
 extern int mptscsih_resume(struct pci_dev *pdev);
 #endif
-extern int mptscsih_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t offset, int length, int func);
+extern int mptscsih_show_info(struct seq_file *, struct Scsi_Host *);
 extern const char * mptscsih_info(struct Scsi_Host *SChost);
 extern int mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *));
 extern int mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel,
diff --git a/drivers/message/fusion/mptspi.c b/drivers/message/fusion/mptspi.c
index c3aabde..5653e50 100644
--- a/drivers/message/fusion/mptspi.c
+++ b/drivers/message/fusion/mptspi.c
@@ -831,7 +831,7 @@
 static struct scsi_host_template mptspi_driver_template = {
 	.module				= THIS_MODULE,
 	.proc_name			= "mptspi",
-	.proc_info			= mptscsih_proc_info,
+	.show_info			= mptscsih_show_info,
 	.name				= "MPT SPI Host",
 	.info				= mptscsih_info,
 	.queuecommand			= mptspi_qcmd,
diff --git a/drivers/message/i2o/i2o_proc.c b/drivers/message/i2o/i2o_proc.c
index 8001aa6..b7d87cd 100644
--- a/drivers/message/i2o/i2o_proc.c
+++ b/drivers/message/i2o/i2o_proc.c
@@ -1599,98 +1599,98 @@
 
 static int i2o_seq_open_hrt(struct inode *inode, struct file *file)
 {
-	return single_open(file, i2o_seq_show_hrt, PDE(inode)->data);
+	return single_open(file, i2o_seq_show_hrt, PDE_DATA(inode));
 };
 
 static int i2o_seq_open_lct(struct inode *inode, struct file *file)
 {
-	return single_open(file, i2o_seq_show_lct, PDE(inode)->data);
+	return single_open(file, i2o_seq_show_lct, PDE_DATA(inode));
 };
 
 static int i2o_seq_open_status(struct inode *inode, struct file *file)
 {
-	return single_open(file, i2o_seq_show_status, PDE(inode)->data);
+	return single_open(file, i2o_seq_show_status, PDE_DATA(inode));
 };
 
 static int i2o_seq_open_hw(struct inode *inode, struct file *file)
 {
-	return single_open(file, i2o_seq_show_hw, PDE(inode)->data);
+	return single_open(file, i2o_seq_show_hw, PDE_DATA(inode));
 };
 
 static int i2o_seq_open_ddm_table(struct inode *inode, struct file *file)
 {
-	return single_open(file, i2o_seq_show_ddm_table, PDE(inode)->data);
+	return single_open(file, i2o_seq_show_ddm_table, PDE_DATA(inode));
 };
 
 static int i2o_seq_open_driver_store(struct inode *inode, struct file *file)
 {
-	return single_open(file, i2o_seq_show_driver_store, PDE(inode)->data);
+	return single_open(file, i2o_seq_show_driver_store, PDE_DATA(inode));
 };
 
 static int i2o_seq_open_drivers_stored(struct inode *inode, struct file *file)
 {
-	return single_open(file, i2o_seq_show_drivers_stored, PDE(inode)->data);
+	return single_open(file, i2o_seq_show_drivers_stored, PDE_DATA(inode));
 };
 
 static int i2o_seq_open_groups(struct inode *inode, struct file *file)
 {
-	return single_open(file, i2o_seq_show_groups, PDE(inode)->data);
+	return single_open(file, i2o_seq_show_groups, PDE_DATA(inode));
 };
 
 static int i2o_seq_open_phys_device(struct inode *inode, struct file *file)
 {
-	return single_open(file, i2o_seq_show_phys_device, PDE(inode)->data);
+	return single_open(file, i2o_seq_show_phys_device, PDE_DATA(inode));
 };
 
 static int i2o_seq_open_claimed(struct inode *inode, struct file *file)
 {
-	return single_open(file, i2o_seq_show_claimed, PDE(inode)->data);
+	return single_open(file, i2o_seq_show_claimed, PDE_DATA(inode));
 };
 
 static int i2o_seq_open_users(struct inode *inode, struct file *file)
 {
-	return single_open(file, i2o_seq_show_users, PDE(inode)->data);
+	return single_open(file, i2o_seq_show_users, PDE_DATA(inode));
 };
 
 static int i2o_seq_open_priv_msgs(struct inode *inode, struct file *file)
 {
-	return single_open(file, i2o_seq_show_priv_msgs, PDE(inode)->data);
+	return single_open(file, i2o_seq_show_priv_msgs, PDE_DATA(inode));
 };
 
 static int i2o_seq_open_authorized_users(struct inode *inode, struct file *file)
 {
 	return single_open(file, i2o_seq_show_authorized_users,
-			   PDE(inode)->data);
+			   PDE_DATA(inode));
 };
 
 static int i2o_seq_open_dev_identity(struct inode *inode, struct file *file)
 {
-	return single_open(file, i2o_seq_show_dev_identity, PDE(inode)->data);
+	return single_open(file, i2o_seq_show_dev_identity, PDE_DATA(inode));
 };
 
 static int i2o_seq_open_ddm_identity(struct inode *inode, struct file *file)
 {
-	return single_open(file, i2o_seq_show_ddm_identity, PDE(inode)->data);
+	return single_open(file, i2o_seq_show_ddm_identity, PDE_DATA(inode));
 };
 
 static int i2o_seq_open_uinfo(struct inode *inode, struct file *file)
 {
-	return single_open(file, i2o_seq_show_uinfo, PDE(inode)->data);
+	return single_open(file, i2o_seq_show_uinfo, PDE_DATA(inode));
 };
 
 static int i2o_seq_open_sgl_limits(struct inode *inode, struct file *file)
 {
-	return single_open(file, i2o_seq_show_sgl_limits, PDE(inode)->data);
+	return single_open(file, i2o_seq_show_sgl_limits, PDE_DATA(inode));
 };
 
 static int i2o_seq_open_sensors(struct inode *inode, struct file *file)
 {
-	return single_open(file, i2o_seq_show_sensors, PDE(inode)->data);
+	return single_open(file, i2o_seq_show_sensors, PDE_DATA(inode));
 };
 
 static int i2o_seq_open_dev_name(struct inode *inode, struct file *file)
 {
-	return single_open(file, i2o_seq_show_dev_name, PDE(inode)->data);
+	return single_open(file, i2o_seq_show_dev_name, PDE_DATA(inode));
 };
 
 static const struct file_operations i2o_seq_fops_lct = {
@@ -1895,25 +1895,6 @@
 }
 
 /**
- *	i2o_proc_subdir_remove - Remove child entries from a proc entry
- *	@dir: proc dir entry from which the childs should be removed
- *
- *	Iterate over each i2o proc entry under dir and remove it. If the child
- *	also has entries, remove them too.
- */
-static void i2o_proc_subdir_remove(struct proc_dir_entry *dir)
-{
-	struct proc_dir_entry *pe, *tmp;
-	pe = dir->subdir;
-	while (pe) {
-		tmp = pe->next;
-		i2o_proc_subdir_remove(pe);
-		remove_proc_entry(pe->name, dir);
-		pe = tmp;
-	}
-};
-
-/**
  *	i2o_proc_device_add - Add an I2O device to the proc dir
  *	@dir: proc dir entry to which the device should be added
  *	@dev: I2O device which should be added
@@ -1932,14 +1913,12 @@
 
 	osm_debug("adding device /proc/i2o/%s/%s\n", dev->iop->name, buff);
 
-	devdir = proc_mkdir(buff, dir);
+	devdir = proc_mkdir_data(buff, 0, dir, dev);
 	if (!devdir) {
 		osm_warn("Could not allocate procdir!\n");
 		return;
 	}
 
-	devdir->data = dev;
-
 	i2o_proc_create_entries(devdir, generic_dev_entries, dev);
 
 	/* Inform core that we want updates about this device's status */
@@ -1973,12 +1952,10 @@
 
 	osm_debug("adding IOP /proc/i2o/%s\n", c->name);
 
-	iopdir = proc_mkdir(c->name, dir);
+	iopdir = proc_mkdir_data(c->name, 0, dir, c);
 	if (!iopdir)
 		return -1;
 
-	iopdir->data = c;
-
 	i2o_proc_create_entries(iopdir, i2o_proc_generic_iop_entries, c);
 
 	list_for_each_entry(dev, &c->devices, list)
@@ -1988,31 +1965,6 @@
 }
 
 /**
- *	i2o_proc_iop_remove - Removes an I2O controller from the i2o proc tree
- *	@dir: parent proc dir entry
- *	@c: I2O controller which should be removed
- *
- *	Iterate over each i2o proc entry and search controller c. If it is found
- *	remove it from the tree.
- */
-static void i2o_proc_iop_remove(struct proc_dir_entry *dir,
-				struct i2o_controller *c)
-{
-	struct proc_dir_entry *pe, *tmp;
-
-	pe = dir->subdir;
-	while (pe) {
-		tmp = pe->next;
-		if (pe->data == c) {
-			i2o_proc_subdir_remove(pe);
-			remove_proc_entry(pe->name, dir);
-		}
-		osm_debug("removing IOP /proc/i2o/%s\n", c->name);
-		pe = tmp;
-	}
-}
-
-/**
  *	i2o_proc_fs_create - Create the i2o proc fs.
  *
  *	Iterate over each I2O controller and create the entries for it.
@@ -2042,12 +1994,7 @@
  */
 static int __exit i2o_proc_fs_destroy(void)
 {
-	struct i2o_controller *c;
-
-	list_for_each_entry(c, &i2o_controllers, list)
-	    i2o_proc_iop_remove(i2o_proc_dir_root, c);
-
-	remove_proc_entry("i2o", NULL);
+	remove_proc_subtree("i2o", NULL);
 
 	return 0;
 };
diff --git a/drivers/misc/lis3lv02d/lis3lv02d.c b/drivers/misc/lis3lv02d/lis3lv02d.c
index 4a87e5c..4cd4a3d 100644
--- a/drivers/misc/lis3lv02d/lis3lv02d.c
+++ b/drivers/misc/lis3lv02d/lis3lv02d.c
@@ -593,7 +593,6 @@
 	struct lis3lv02d *lis3 = container_of(file->private_data,
 					      struct lis3lv02d, miscdev);
 
-	fasync_helper(-1, file, 0, &lis3->async_queue);
 	clear_bit(0, &lis3->misc_opened); /* release the device */
 	if (lis3->pm_dev)
 		pm_runtime_put(lis3->pm_dev);
diff --git a/drivers/misc/sgi-gru/gruprocfs.c b/drivers/misc/sgi-gru/gruprocfs.c
index 950dbe9..797d796 100644
--- a/drivers/misc/sgi-gru/gruprocfs.c
+++ b/drivers/misc/sgi-gru/gruprocfs.c
@@ -355,7 +355,7 @@
 		for (p = proc_files; p->name; p++)
 			if (p->entry)
 				remove_proc_entry(p->name, proc_gru);
-		remove_proc_entry("gru", proc_gru->parent);
+		proc_remove(proc_gru);
 	}
 }
 
diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c
index 61d5f56..322ca65 100644
--- a/drivers/mtd/mtdcore.c
+++ b/drivers/mtd/mtdcore.c
@@ -36,6 +36,7 @@
 #include <linux/idr.h>
 #include <linux/backing-dev.h>
 #include <linux/gfp.h>
+#include <linux/slab.h>
 
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
diff --git a/drivers/net/bonding/bond_procfs.c b/drivers/net/bonding/bond_procfs.c
index 3cea38d..94d06f1 100644
--- a/drivers/net/bonding/bond_procfs.c
+++ b/drivers/net/bonding/bond_procfs.c
@@ -218,15 +218,13 @@
 static int bond_info_open(struct inode *inode, struct file *file)
 {
 	struct seq_file *seq;
-	struct proc_dir_entry *proc;
 	int res;
 
 	res = seq_open(file, &bond_info_seq_ops);
 	if (!res) {
 		/* recover the pointer buried in proc_dir_entry data */
 		seq = file->private_data;
-		proc = PDE(inode);
-		seq->private = proc->data;
+		seq->private = PDE_DATA(inode);
 	}
 
 	return res;
diff --git a/drivers/net/irda/vlsi_ir.c b/drivers/net/irda/vlsi_ir.c
index 2f99f88..5f47584 100644
--- a/drivers/net/irda/vlsi_ir.c
+++ b/drivers/net/irda/vlsi_ir.c
@@ -383,7 +383,7 @@
 
 static int vlsi_seq_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, vlsi_seq_show, PDE(inode)->data);
+	return single_open(file, vlsi_seq_show, PDE_DATA(inode));
 }
 
 static const struct file_operations vlsi_proc_fops = {
@@ -1678,7 +1678,7 @@
 			IRDA_WARNING("%s: failed to create proc entry\n",
 				     __func__);
 		} else {
-			ent->size = 0;
+			proc_set_size(ent, 0);
 		}
 		idev->proc_entry = ent;
 	}
diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c
index 5329541..6125adb 100644
--- a/drivers/net/wireless/airo.c
+++ b/drivers/net/wireless/airo.c
@@ -4506,108 +4506,75 @@
 	apriv->proc_entry = proc_mkdir_mode(apriv->proc_name, airo_perm,
 					    airo_entry);
 	if (!apriv->proc_entry)
-		goto fail;
-	apriv->proc_entry->uid = proc_kuid;
-	apriv->proc_entry->gid = proc_kgid;
+		return -ENOMEM;
+	proc_set_user(apriv->proc_entry, proc_kuid, proc_kgid);
 
 	/* Setup the StatsDelta */
 	entry = proc_create_data("StatsDelta", S_IRUGO & proc_perm,
 				 apriv->proc_entry, &proc_statsdelta_ops, dev);
 	if (!entry)
-		goto fail_stats_delta;
-	entry->uid = proc_kuid;
-	entry->gid = proc_kgid;
+		goto fail;
+	proc_set_user(entry, proc_kuid, proc_kgid);
 
 	/* Setup the Stats */
 	entry = proc_create_data("Stats", S_IRUGO & proc_perm,
 				 apriv->proc_entry, &proc_stats_ops, dev);
 	if (!entry)
-		goto fail_stats;
-	entry->uid = proc_kuid;
-	entry->gid = proc_kgid;
+		goto fail;
+	proc_set_user(entry, proc_kuid, proc_kgid);
 
 	/* Setup the Status */
 	entry = proc_create_data("Status", S_IRUGO & proc_perm,
 				 apriv->proc_entry, &proc_status_ops, dev);
 	if (!entry)
-		goto fail_status;
-	entry->uid = proc_kuid;
-	entry->gid = proc_kgid;
+		goto fail;
+	proc_set_user(entry, proc_kuid, proc_kgid);
 
 	/* Setup the Config */
 	entry = proc_create_data("Config", proc_perm,
 				 apriv->proc_entry, &proc_config_ops, dev);
 	if (!entry)
-		goto fail_config;
-	entry->uid = proc_kuid;
-	entry->gid = proc_kgid;
+		goto fail;
+	proc_set_user(entry, proc_kuid, proc_kgid);
 
 	/* Setup the SSID */
 	entry = proc_create_data("SSID", proc_perm,
 				 apriv->proc_entry, &proc_SSID_ops, dev);
 	if (!entry)
-		goto fail_ssid;
-	entry->uid = proc_kuid;
-	entry->gid = proc_kgid;
+		goto fail;
+	proc_set_user(entry, proc_kuid, proc_kgid);
 
 	/* Setup the APList */
 	entry = proc_create_data("APList", proc_perm,
 				 apriv->proc_entry, &proc_APList_ops, dev);
 	if (!entry)
-		goto fail_aplist;
-	entry->uid = proc_kuid;
-	entry->gid = proc_kgid;
+		goto fail;
+	proc_set_user(entry, proc_kuid, proc_kgid);
 
 	/* Setup the BSSList */
 	entry = proc_create_data("BSSList", proc_perm,
 				 apriv->proc_entry, &proc_BSSList_ops, dev);
 	if (!entry)
-		goto fail_bsslist;
-	entry->uid = proc_kuid;
-	entry->gid = proc_kgid;
+		goto fail;
+	proc_set_user(entry, proc_kuid, proc_kgid);
 
 	/* Setup the WepKey */
 	entry = proc_create_data("WepKey", proc_perm,
 				 apriv->proc_entry, &proc_wepkey_ops, dev);
 	if (!entry)
-		goto fail_wepkey;
-	entry->uid = proc_kuid;
-	entry->gid = proc_kgid;
-
+		goto fail;
+	proc_set_user(entry, proc_kuid, proc_kgid);
 	return 0;
 
-fail_wepkey:
-	remove_proc_entry("BSSList", apriv->proc_entry);
-fail_bsslist:
-	remove_proc_entry("APList", apriv->proc_entry);
-fail_aplist:
-	remove_proc_entry("SSID", apriv->proc_entry);
-fail_ssid:
-	remove_proc_entry("Config", apriv->proc_entry);
-fail_config:
-	remove_proc_entry("Status", apriv->proc_entry);
-fail_status:
-	remove_proc_entry("Stats", apriv->proc_entry);
-fail_stats:
-	remove_proc_entry("StatsDelta", apriv->proc_entry);
-fail_stats_delta:
-	remove_proc_entry(apriv->proc_name, airo_entry);
 fail:
+	remove_proc_subtree(apriv->proc_name, airo_entry);
 	return -ENOMEM;
 }
 
 static int takedown_proc_entry( struct net_device *dev,
-				struct airo_info *apriv ) {
-	if ( !apriv->proc_entry->namelen ) return 0;
-	remove_proc_entry("Stats",apriv->proc_entry);
-	remove_proc_entry("StatsDelta",apriv->proc_entry);
-	remove_proc_entry("Status",apriv->proc_entry);
-	remove_proc_entry("Config",apriv->proc_entry);
-	remove_proc_entry("SSID",apriv->proc_entry);
-	remove_proc_entry("APList",apriv->proc_entry);
-	remove_proc_entry("BSSList",apriv->proc_entry);
-	remove_proc_entry("WepKey",apriv->proc_entry);
-	remove_proc_entry(apriv->proc_name,airo_entry);
+				struct airo_info *apriv )
+{
+	remove_proc_subtree(apriv->proc_name, airo_entry);
 	return 0;
 }
 
@@ -4663,8 +4630,7 @@
 static int proc_status_open(struct inode *inode, struct file *file)
 {
 	struct proc_data *data;
-	struct proc_dir_entry *dp = PDE(inode);
-	struct net_device *dev = dp->data;
+	struct net_device *dev = PDE_DATA(inode);
 	struct airo_info *apriv = dev->ml_priv;
 	CapabilityRid cap_rid;
 	StatusRid status_rid;
@@ -4746,8 +4712,7 @@
 				u16 rid )
 {
 	struct proc_data *data;
-	struct proc_dir_entry *dp = PDE(inode);
-	struct net_device *dev = dp->data;
+	struct net_device *dev = PDE_DATA(inode);
 	struct airo_info *apriv = dev->ml_priv;
 	StatsRid stats;
 	int i, j;
@@ -4809,8 +4774,7 @@
 static void proc_config_on_close(struct inode *inode, struct file *file)
 {
 	struct proc_data *data = file->private_data;
-	struct proc_dir_entry *dp = PDE(inode);
-	struct net_device *dev = dp->data;
+	struct net_device *dev = PDE_DATA(inode);
 	struct airo_info *ai = dev->ml_priv;
 	char *line;
 
@@ -5021,8 +4985,7 @@
 static int proc_config_open(struct inode *inode, struct file *file)
 {
 	struct proc_data *data;
-	struct proc_dir_entry *dp = PDE(inode);
-	struct net_device *dev = dp->data;
+	struct net_device *dev = PDE_DATA(inode);
 	struct airo_info *ai = dev->ml_priv;
 	int i;
 	__le16 mode;
@@ -5112,8 +5075,7 @@
 static void proc_SSID_on_close(struct inode *inode, struct file *file)
 {
 	struct proc_data *data = file->private_data;
-	struct proc_dir_entry *dp = PDE(inode);
-	struct net_device *dev = dp->data;
+	struct net_device *dev = PDE_DATA(inode);
 	struct airo_info *ai = dev->ml_priv;
 	SsidRid SSID_rid;
 	int i;
@@ -5148,8 +5110,7 @@
 
 static void proc_APList_on_close( struct inode *inode, struct file *file ) {
 	struct proc_data *data = file->private_data;
-	struct proc_dir_entry *dp = PDE(inode);
-	struct net_device *dev = dp->data;
+	struct net_device *dev = PDE_DATA(inode);
 	struct airo_info *ai = dev->ml_priv;
 	APListRid APList_rid;
 	int i;
@@ -5283,8 +5244,7 @@
 
 static void proc_wepkey_on_close( struct inode *inode, struct file *file ) {
 	struct proc_data *data;
-	struct proc_dir_entry *dp = PDE(inode);
-	struct net_device *dev = dp->data;
+	struct net_device *dev = PDE_DATA(inode);
 	struct airo_info *ai = dev->ml_priv;
 	int i, rc;
 	char key[16];
@@ -5335,8 +5295,7 @@
 static int proc_wepkey_open( struct inode *inode, struct file *file )
 {
 	struct proc_data *data;
-	struct proc_dir_entry *dp = PDE(inode);
-	struct net_device *dev = dp->data;
+	struct net_device *dev = PDE_DATA(inode);
 	struct airo_info *ai = dev->ml_priv;
 	char *ptr;
 	WepKeyRid wkr;
@@ -5384,8 +5343,7 @@
 static int proc_SSID_open(struct inode *inode, struct file *file)
 {
 	struct proc_data *data;
-	struct proc_dir_entry *dp = PDE(inode);
-	struct net_device *dev = dp->data;
+	struct net_device *dev = PDE_DATA(inode);
 	struct airo_info *ai = dev->ml_priv;
 	int i;
 	char *ptr;
@@ -5428,8 +5386,7 @@
 
 static int proc_APList_open( struct inode *inode, struct file *file ) {
 	struct proc_data *data;
-	struct proc_dir_entry *dp = PDE(inode);
-	struct net_device *dev = dp->data;
+	struct net_device *dev = PDE_DATA(inode);
 	struct airo_info *ai = dev->ml_priv;
 	int i;
 	char *ptr;
@@ -5468,8 +5425,7 @@
 
 static int proc_BSSList_open( struct inode *inode, struct file *file ) {
 	struct proc_data *data;
-	struct proc_dir_entry *dp = PDE(inode);
-	struct net_device *dev = dp->data;
+	struct net_device *dev = PDE_DATA(inode);
 	struct airo_info *ai = dev->ml_priv;
 	char *ptr;
 	BSSListRid BSSList_rid;
@@ -5706,10 +5662,8 @@
 
 	airo_entry = proc_mkdir_mode("driver/aironet", airo_perm, NULL);
 
-	if (airo_entry) {
-		airo_entry->uid = proc_kuid;
-		airo_entry->gid = proc_kgid;
-	}
+	if (airo_entry)
+		proc_set_user(airo_entry, proc_kuid, proc_kgid);
 
 	for (i = 0; i < 4 && io[i] && irq[i]; i++) {
 		airo_print_info("", "Trying to configure ISA adapter at irq=%d "
diff --git a/drivers/net/wireless/ath/wil6210/debugfs.c b/drivers/net/wireless/ath/wil6210/debugfs.c
index 4be07f5..727b1f5 100644
--- a/drivers/net/wireless/ath/wil6210/debugfs.c
+++ b/drivers/net/wireless/ath/wil6210/debugfs.c
@@ -216,7 +216,7 @@
 			wil_debugfs_iomem_x32_set, "0x%08llx\n");
 
 static struct dentry *wil_debugfs_create_iomem_x32(const char *name,
-						   mode_t mode,
+						   umode_t mode,
 						   struct dentry *parent,
 						   void __iomem *value)
 {
@@ -359,7 +359,7 @@
 
 static
 struct dentry *wil_debugfs_create_ioblob(const char *name,
-					 mode_t mode,
+					 umode_t mode,
 					 struct dentry *parent,
 					 struct debugfs_blob_wrapper *blob)
 {
diff --git a/drivers/net/wireless/atmel.c b/drivers/net/wireless/atmel.c
index 4374079..23a3498 100644
--- a/drivers/net/wireless/atmel.c
+++ b/drivers/net/wireless/atmel.c
@@ -63,6 +63,7 @@
 #include <net/iw_handler.h>
 #include <linux/crc32.h>
 #include <linux/proc_fs.h>
+#include <linux/seq_file.h>
 #include <linux/device.h>
 #include <linux/moduleparam.h>
 #include <linux/firmware.h>
@@ -1409,30 +1410,28 @@
 	return 0;
 }
 
-static int atmel_proc_output (char *buf, struct atmel_private *priv)
+static int atmel_proc_show(struct seq_file *m, void *v)
 {
+	struct atmel_private *priv = m->private;
 	int i;
-	char *p = buf;
 	char *s, *r, *c;
 
-	p += sprintf(p, "Driver version:\t\t%d.%d\n",
-		     DRIVER_MAJOR, DRIVER_MINOR);
+	seq_printf(m, "Driver version:\t\t%d.%d\n", DRIVER_MAJOR, DRIVER_MINOR);
 
 	if (priv->station_state != STATION_STATE_DOWN) {
-		p += sprintf(p, "Firmware version:\t%d.%d build %d\n"
-				"Firmware location:\t",
-			     priv->host_info.major_version,
-			     priv->host_info.minor_version,
-			     priv->host_info.build_version);
+		seq_printf(m,
+			   "Firmware version:\t%d.%d build %d\n"
+			   "Firmware location:\t",
+			   priv->host_info.major_version,
+			   priv->host_info.minor_version,
+			   priv->host_info.build_version);
 
 		if (priv->card_type != CARD_TYPE_EEPROM)
-			p += sprintf(p, "on card\n");
+			seq_puts(m, "on card\n");
 		else if (priv->firmware)
-			p += sprintf(p, "%s loaded by host\n",
-				     priv->firmware_id);
+			seq_printf(m, "%s loaded by host\n", priv->firmware_id);
 		else
-			p += sprintf(p, "%s loaded by hotplug\n",
-				     priv->firmware_id);
+			seq_printf(m, "%s loaded by hotplug\n", priv->firmware_id);
 
 		switch (priv->card_type) {
 		case CARD_TYPE_PARALLEL_FLASH:
@@ -1453,12 +1452,12 @@
 			if (priv->reg_domain == channel_table[i].reg_domain)
 				r = channel_table[i].name;
 
-		p += sprintf(p, "MAC memory type:\t%s\n", c);
-		p += sprintf(p, "Regulatory domain:\t%s\n", r);
-		p += sprintf(p, "Host CRC checking:\t%s\n",
-			     priv->do_rx_crc ? "On" : "Off");
-		p += sprintf(p, "WPA-capable firmware:\t%s\n",
-			     priv->use_wpa ? "Yes" : "No");
+		seq_printf(m, "MAC memory type:\t%s\n", c);
+		seq_printf(m, "Regulatory domain:\t%s\n", r);
+		seq_printf(m, "Host CRC checking:\t%s\n",
+			 priv->do_rx_crc ? "On" : "Off");
+		seq_printf(m, "WPA-capable firmware:\t%s\n",
+			 priv->use_wpa ? "Yes" : "No");
 	}
 
 	switch (priv->station_state) {
@@ -1490,26 +1489,22 @@
 		s = "<unknown>";
 	}
 
-	p += sprintf(p, "Current state:\t\t%s\n", s);
-	return p - buf;
+	seq_printf(m, "Current state:\t\t%s\n", s);
+	return 0;
 }
 
-static int atmel_read_proc(char *page, char **start, off_t off,
-			   int count, int *eof, void *data)
+static int atmel_proc_open(struct inode *inode, struct file *file)
 {
-	struct atmel_private *priv = data;
-	int len = atmel_proc_output (page, priv);
-	if (len <= off+count)
-		*eof = 1;
-	*start = page + off;
-	len -= off;
-	if (len > count)
-		len = count;
-	if (len < 0)
-		len = 0;
-	return len;
+	return single_open(file, atmel_proc_show, PDE_DATA(inode));
 }
 
+static const struct file_operations atmel_proc_fops = {
+	.open		= atmel_proc_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= seq_release,
+};
+
 static const struct net_device_ops atmel_netdev_ops = {
 	.ndo_open 		= atmel_open,
 	.ndo_stop		= atmel_close,
@@ -1525,7 +1520,6 @@
 				   struct device *sys_dev,
 				   int (*card_present)(void *), void *card)
 {
-	struct proc_dir_entry *ent;
 	struct net_device *dev;
 	struct atmel_private *priv;
 	int rc;
@@ -1630,8 +1624,7 @@
 
 	netif_carrier_off(dev);
 
-	ent = create_proc_read_entry ("driver/atmel", 0, NULL, atmel_read_proc, priv);
-	if (!ent)
+	if (!proc_create_data("driver/atmel", 0, NULL, &atmel_proc_fops, priv));
 		printk(KERN_WARNING "atmel: unable to create /proc entry.\n");
 
 	printk(KERN_INFO "%s: Atmel at76c50x. Version %d.%d. MAC %pM\n",
diff --git a/drivers/net/wireless/hostap/hostap_ap.c b/drivers/net/wireless/hostap/hostap_ap.c
index dd9a18f..19c45e3 100644
--- a/drivers/net/wireless/hostap/hostap_ap.c
+++ b/drivers/net/wireless/hostap/hostap_ap.c
@@ -17,6 +17,7 @@
  */
 
 #include <linux/proc_fs.h>
+#include <linux/seq_file.h>
 #include <linux/delay.h>
 #include <linux/random.h>
 #include <linux/if_arp.h>
@@ -64,28 +65,32 @@
 
 
 #ifndef PRISM2_NO_PROCFS_DEBUG
-static int ap_debug_proc_read(char *page, char **start, off_t off,
-			      int count, int *eof, void *data)
+static int ap_debug_proc_show(struct seq_file *m, void *v)
 {
-	char *p = page;
-	struct ap_data *ap = (struct ap_data *) data;
+	struct ap_data *ap = m->private;
 
-	if (off != 0) {
-		*eof = 1;
-		return 0;
-	}
-
-	p += sprintf(p, "BridgedUnicastFrames=%u\n", ap->bridged_unicast);
-	p += sprintf(p, "BridgedMulticastFrames=%u\n", ap->bridged_multicast);
-	p += sprintf(p, "max_inactivity=%u\n", ap->max_inactivity / HZ);
-	p += sprintf(p, "bridge_packets=%u\n", ap->bridge_packets);
-	p += sprintf(p, "nullfunc_ack=%u\n", ap->nullfunc_ack);
-	p += sprintf(p, "autom_ap_wds=%u\n", ap->autom_ap_wds);
-	p += sprintf(p, "auth_algs=%u\n", ap->local->auth_algs);
-	p += sprintf(p, "tx_drop_nonassoc=%u\n", ap->tx_drop_nonassoc);
-
-	return (p - page);
+	seq_printf(m, "BridgedUnicastFrames=%u\n", ap->bridged_unicast);
+	seq_printf(m, "BridgedMulticastFrames=%u\n", ap->bridged_multicast);
+	seq_printf(m, "max_inactivity=%u\n", ap->max_inactivity / HZ);
+	seq_printf(m, "bridge_packets=%u\n", ap->bridge_packets);
+	seq_printf(m, "nullfunc_ack=%u\n", ap->nullfunc_ack);
+	seq_printf(m, "autom_ap_wds=%u\n", ap->autom_ap_wds);
+	seq_printf(m, "auth_algs=%u\n", ap->local->auth_algs);
+	seq_printf(m, "tx_drop_nonassoc=%u\n", ap->tx_drop_nonassoc);
+	return 0;
 }
+
+static int ap_debug_proc_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, ap_debug_proc_show, PDE_DATA(inode));
+}
+
+static const struct file_operations ap_debug_proc_fops = {
+	.open		= ap_debug_proc_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= seq_release,
+};
 #endif /* PRISM2_NO_PROCFS_DEBUG */
 
 
@@ -325,50 +330,81 @@
 }
 
 
-static int ap_control_proc_read(char *page, char **start, off_t off,
-				int count, int *eof, void *data)
+static int ap_control_proc_show(struct seq_file *m, void *v)
 {
-	char *p = page;
-	struct ap_data *ap = (struct ap_data *) data;
+	struct ap_data *ap = m->private;
 	char *policy_txt;
 	struct mac_entry *entry;
 
-	if (off != 0) {
-		*eof = 1;
+	if (v == SEQ_START_TOKEN) {
+		switch (ap->mac_restrictions.policy) {
+		case MAC_POLICY_OPEN:
+			policy_txt = "open";
+			break;
+		case MAC_POLICY_ALLOW:
+			policy_txt = "allow";
+			break;
+		case MAC_POLICY_DENY:
+			policy_txt = "deny";
+			break;
+		default:
+			policy_txt = "unknown";
+			break;
+		}
+		seq_printf(m, "MAC policy: %s\n", policy_txt);
+		seq_printf(m, "MAC entries: %u\n", ap->mac_restrictions.entries);
+		seq_puts(m, "MAC list:\n");
 		return 0;
 	}
 
-	switch (ap->mac_restrictions.policy) {
-	case MAC_POLICY_OPEN:
-		policy_txt = "open";
-		break;
-	case MAC_POLICY_ALLOW:
-		policy_txt = "allow";
-		break;
-	case MAC_POLICY_DENY:
-		policy_txt = "deny";
-		break;
-	default:
-		policy_txt = "unknown";
-		break;
-	}
-	p += sprintf(p, "MAC policy: %s\n", policy_txt);
-	p += sprintf(p, "MAC entries: %u\n", ap->mac_restrictions.entries);
-	p += sprintf(p, "MAC list:\n");
-	spin_lock_bh(&ap->mac_restrictions.lock);
-	list_for_each_entry(entry, &ap->mac_restrictions.mac_list, list) {
-		if (p - page > PAGE_SIZE - 80) {
-			p += sprintf(p, "All entries did not fit one page.\n");
-			break;
-		}
-
-		p += sprintf(p, "%pM\n", entry->addr);
-	}
-	spin_unlock_bh(&ap->mac_restrictions.lock);
-
-	return (p - page);
+	entry = v;
+	seq_printf(m, "%pM\n", entry->addr);
+	return 0;
 }
 
+static void *ap_control_proc_start(struct seq_file *m, loff_t *_pos)
+{
+	struct ap_data *ap = m->private;
+	spin_lock_bh(&ap->mac_restrictions.lock);
+	return seq_list_start_head(&ap->mac_restrictions.mac_list, *_pos);
+}
+
+static void *ap_control_proc_next(struct seq_file *m, void *v, loff_t *_pos)
+{
+	struct ap_data *ap = m->private;
+	return seq_list_next(v, &ap->mac_restrictions.mac_list, _pos);
+}
+
+static void ap_control_proc_stop(struct seq_file *m, void *v)
+{
+	struct ap_data *ap = m->private;
+	spin_unlock_bh(&ap->mac_restrictions.lock);
+}
+
+static const struct seq_operations ap_control_proc_seqops = {
+	.start	= ap_control_proc_start,
+	.next	= ap_control_proc_next,
+	.stop	= ap_control_proc_stop,
+	.show	= ap_control_proc_show,
+};
+
+static int ap_control_proc_open(struct inode *inode, struct file *file)
+{
+	int ret = seq_open(file, &ap_control_proc_seqops);
+	if (ret == 0) {
+		struct seq_file *m = file->private_data;
+		m->private = PDE_DATA(inode);
+	}
+	return ret;
+}
+
+static const struct file_operations ap_control_proc_fops = {
+	.open		= ap_control_proc_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= seq_release,
+};
+
 
 int ap_control_add_mac(struct mac_restrictions *mac_restrictions, u8 *mac)
 {
@@ -510,61 +546,84 @@
 
 #ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT
 
-#define PROC_LIMIT (PAGE_SIZE - 80)
-
-static int prism2_ap_proc_read(char *page, char **start, off_t off,
-			       int count, int *eof, void *data)
+static int prism2_ap_proc_show(struct seq_file *m, void *v)
 {
-	char *p = page;
-	struct ap_data *ap = (struct ap_data *) data;
-	struct sta_info *sta;
+	struct sta_info *sta = v;
 	int i;
 
-	if (off > PROC_LIMIT) {
-		*eof = 1;
+	if (v == SEQ_START_TOKEN) {
+		seq_printf(m, "# BSSID CHAN SIGNAL NOISE RATE SSID FLAGS\n");
 		return 0;
 	}
 
-	p += sprintf(p, "# BSSID CHAN SIGNAL NOISE RATE SSID FLAGS\n");
-	spin_lock_bh(&ap->sta_table_lock);
-	list_for_each_entry(sta, &ap->sta_list, list) {
-		if (!sta->ap)
-			continue;
-
-		p += sprintf(p, "%pM %d %d %d %d '",
-			     sta->addr,
-			     sta->u.ap.channel, sta->last_rx_signal,
-			     sta->last_rx_silence, sta->last_rx_rate);
-		for (i = 0; i < sta->u.ap.ssid_len; i++)
-			p += sprintf(p, ((sta->u.ap.ssid[i] >= 32 &&
-					  sta->u.ap.ssid[i] < 127) ?
-					 "%c" : "<%02x>"),
-				     sta->u.ap.ssid[i]);
-		p += sprintf(p, "'");
-		if (sta->capability & WLAN_CAPABILITY_ESS)
-			p += sprintf(p, " [ESS]");
-		if (sta->capability & WLAN_CAPABILITY_IBSS)
-			p += sprintf(p, " [IBSS]");
-		if (sta->capability & WLAN_CAPABILITY_PRIVACY)
-			p += sprintf(p, " [WEP]");
-		p += sprintf(p, "\n");
-
-		if ((p - page) > PROC_LIMIT) {
-			printk(KERN_DEBUG "hostap: ap proc did not fit\n");
-			break;
-		}
-	}
-	spin_unlock_bh(&ap->sta_table_lock);
-
-	if ((p - page) <= off) {
-		*eof = 1;
+	if (!sta->ap)
 		return 0;
+
+	seq_printf(m, "%pM %d %d %d %d '",
+		   sta->addr,
+		   sta->u.ap.channel, sta->last_rx_signal,
+		   sta->last_rx_silence, sta->last_rx_rate);
+
+	for (i = 0; i < sta->u.ap.ssid_len; i++) {
+		if (sta->u.ap.ssid[i] >= 32 && sta->u.ap.ssid[i] < 127)
+			seq_putc(m, sta->u.ap.ssid[i]);
+		else
+			seq_printf(m, "<%02x>", sta->u.ap.ssid[i]);
 	}
 
-	*start = page + off;
-
-	return (p - page - off);
+	seq_putc(m, '\'');
+	if (sta->capability & WLAN_CAPABILITY_ESS)
+		seq_puts(m, " [ESS]");
+	if (sta->capability & WLAN_CAPABILITY_IBSS)
+		seq_puts(m, " [IBSS]");
+	if (sta->capability & WLAN_CAPABILITY_PRIVACY)
+		seq_puts(m, " [WEP]");
+	seq_putc(m, '\n');
+	return 0;
 }
+
+static void *prism2_ap_proc_start(struct seq_file *m, loff_t *_pos)
+{
+	struct ap_data *ap = m->private;
+	spin_lock_bh(&ap->sta_table_lock);
+	return seq_list_start_head(&ap->sta_list, *_pos);
+}
+
+static void *prism2_ap_proc_next(struct seq_file *m, void *v, loff_t *_pos)
+{
+	struct ap_data *ap = m->private;
+	return seq_list_next(v, &ap->sta_list, _pos);
+}
+
+static void prism2_ap_proc_stop(struct seq_file *m, void *v)
+{
+	struct ap_data *ap = m->private;
+	spin_unlock_bh(&ap->sta_table_lock);
+}
+
+static const struct seq_operations prism2_ap_proc_seqops = {
+	.start	= prism2_ap_proc_start,
+	.next	= prism2_ap_proc_next,
+	.stop	= prism2_ap_proc_stop,
+	.show	= prism2_ap_proc_show,
+};
+
+static int prism2_ap_proc_open(struct inode *inode, struct file *file)
+{
+	int ret = seq_open(file, &prism2_ap_proc_seqops);
+	if (ret == 0) {
+		struct seq_file *m = file->private_data;
+		m->private = PDE_DATA(inode);
+	}
+	return ret;
+}
+
+static const struct file_operations prism2_ap_proc_fops = {
+	.open		= prism2_ap_proc_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= seq_release,
+};
 #endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */
 
 
@@ -836,15 +895,12 @@
 		return;
 
 #ifndef PRISM2_NO_PROCFS_DEBUG
-	create_proc_read_entry("ap_debug", 0, ap->proc,
-			       ap_debug_proc_read, ap);
+	proc_create_data("ap_debug", 0, ap->proc, &ap_debug_proc_fops, ap);
 #endif /* PRISM2_NO_PROCFS_DEBUG */
 
 #ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT
-	create_proc_read_entry("ap_control", 0, ap->proc,
-			       ap_control_proc_read, ap);
-	create_proc_read_entry("ap", 0, ap->proc,
-			       prism2_ap_proc_read, ap);
+	proc_create_data("ap_control", 0, ap->proc, &ap_control_proc_fops, ap);
+	proc_create_data("ap", 0, ap->proc, &prism2_ap_proc_fops, ap);
 #endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */
 
 }
@@ -982,79 +1038,86 @@
 #endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */
 
 
-static int prism2_sta_proc_read(char *page, char **start, off_t off,
-				int count, int *eof, void *data)
+static int prism2_sta_proc_show(struct seq_file *m, void *v)
 {
-	char *p = page;
-	struct sta_info *sta = (struct sta_info *) data;
+	struct sta_info *sta = m->private;
 	int i;
 
 	/* FIX: possible race condition.. the STA data could have just expired,
 	 * but proc entry was still here so that the read could have started;
 	 * some locking should be done here.. */
 
-	if (off != 0) {
-		*eof = 1;
-		return 0;
-	}
-
-	p += sprintf(p, "%s=%pM\nusers=%d\naid=%d\n"
-		     "flags=0x%04x%s%s%s%s%s%s%s\n"
-		     "capability=0x%02x\nlisten_interval=%d\nsupported_rates=",
-		     sta->ap ? "AP" : "STA",
-		     sta->addr, atomic_read(&sta->users), sta->aid,
-		     sta->flags,
-		     sta->flags & WLAN_STA_AUTH ? " AUTH" : "",
-		     sta->flags & WLAN_STA_ASSOC ? " ASSOC" : "",
-		     sta->flags & WLAN_STA_PS ? " PS" : "",
-		     sta->flags & WLAN_STA_TIM ? " TIM" : "",
-		     sta->flags & WLAN_STA_PERM ? " PERM" : "",
-		     sta->flags & WLAN_STA_AUTHORIZED ? " AUTHORIZED" : "",
-		     sta->flags & WLAN_STA_PENDING_POLL ? " POLL" : "",
-		     sta->capability, sta->listen_interval);
+	seq_printf(m,
+		   "%s=%pM\nusers=%d\naid=%d\n"
+		   "flags=0x%04x%s%s%s%s%s%s%s\n"
+		   "capability=0x%02x\nlisten_interval=%d\nsupported_rates=",
+		   sta->ap ? "AP" : "STA",
+		   sta->addr, atomic_read(&sta->users), sta->aid,
+		   sta->flags,
+		   sta->flags & WLAN_STA_AUTH ? " AUTH" : "",
+		   sta->flags & WLAN_STA_ASSOC ? " ASSOC" : "",
+		   sta->flags & WLAN_STA_PS ? " PS" : "",
+		   sta->flags & WLAN_STA_TIM ? " TIM" : "",
+		   sta->flags & WLAN_STA_PERM ? " PERM" : "",
+		   sta->flags & WLAN_STA_AUTHORIZED ? " AUTHORIZED" : "",
+		   sta->flags & WLAN_STA_PENDING_POLL ? " POLL" : "",
+		   sta->capability, sta->listen_interval);
 	/* supported_rates: 500 kbit/s units with msb ignored */
 	for (i = 0; i < sizeof(sta->supported_rates); i++)
 		if (sta->supported_rates[i] != 0)
-			p += sprintf(p, "%d%sMbps ",
-				     (sta->supported_rates[i] & 0x7f) / 2,
-				     sta->supported_rates[i] & 1 ? ".5" : "");
-	p += sprintf(p, "\njiffies=%lu\nlast_auth=%lu\nlast_assoc=%lu\n"
-		     "last_rx=%lu\nlast_tx=%lu\nrx_packets=%lu\n"
-		     "tx_packets=%lu\n"
-		     "rx_bytes=%lu\ntx_bytes=%lu\nbuffer_count=%d\n"
-		     "last_rx: silence=%d dBm signal=%d dBm rate=%d%s Mbps\n"
-		     "tx_rate=%d\ntx[1M]=%d\ntx[2M]=%d\ntx[5.5M]=%d\n"
-		     "tx[11M]=%d\n"
-		     "rx[1M]=%d\nrx[2M]=%d\nrx[5.5M]=%d\nrx[11M]=%d\n",
-		     jiffies, sta->last_auth, sta->last_assoc, sta->last_rx,
-		     sta->last_tx,
-		     sta->rx_packets, sta->tx_packets, sta->rx_bytes,
-		     sta->tx_bytes, skb_queue_len(&sta->tx_buf),
-		     sta->last_rx_silence,
-		     sta->last_rx_signal, sta->last_rx_rate / 10,
-		     sta->last_rx_rate % 10 ? ".5" : "",
-		     sta->tx_rate, sta->tx_count[0], sta->tx_count[1],
-		     sta->tx_count[2], sta->tx_count[3],  sta->rx_count[0],
-		     sta->rx_count[1], sta->rx_count[2], sta->rx_count[3]);
+			seq_printf(m, "%d%sMbps ",
+				   (sta->supported_rates[i] & 0x7f) / 2,
+				   sta->supported_rates[i] & 1 ? ".5" : "");
+	seq_printf(m,
+		   "\njiffies=%lu\nlast_auth=%lu\nlast_assoc=%lu\n"
+		   "last_rx=%lu\nlast_tx=%lu\nrx_packets=%lu\n"
+		   "tx_packets=%lu\n"
+		   "rx_bytes=%lu\ntx_bytes=%lu\nbuffer_count=%d\n"
+		   "last_rx: silence=%d dBm signal=%d dBm rate=%d%s Mbps\n"
+		   "tx_rate=%d\ntx[1M]=%d\ntx[2M]=%d\ntx[5.5M]=%d\n"
+		   "tx[11M]=%d\n"
+		   "rx[1M]=%d\nrx[2M]=%d\nrx[5.5M]=%d\nrx[11M]=%d\n",
+		   jiffies, sta->last_auth, sta->last_assoc, sta->last_rx,
+		   sta->last_tx,
+		   sta->rx_packets, sta->tx_packets, sta->rx_bytes,
+		   sta->tx_bytes, skb_queue_len(&sta->tx_buf),
+		   sta->last_rx_silence,
+		   sta->last_rx_signal, sta->last_rx_rate / 10,
+		   sta->last_rx_rate % 10 ? ".5" : "",
+		   sta->tx_rate, sta->tx_count[0], sta->tx_count[1],
+		   sta->tx_count[2], sta->tx_count[3],  sta->rx_count[0],
+		   sta->rx_count[1], sta->rx_count[2], sta->rx_count[3]);
 	if (sta->crypt && sta->crypt->ops && sta->crypt->ops->print_stats)
-		p = sta->crypt->ops->print_stats(p, sta->crypt->priv);
+		sta->crypt->ops->print_stats(m, sta->crypt->priv);
 #ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT
 	if (sta->ap) {
 		if (sta->u.ap.channel >= 0)
-			p += sprintf(p, "channel=%d\n", sta->u.ap.channel);
-		p += sprintf(p, "ssid=");
-		for (i = 0; i < sta->u.ap.ssid_len; i++)
-			p += sprintf(p, ((sta->u.ap.ssid[i] >= 32 &&
-					  sta->u.ap.ssid[i] < 127) ?
-					 "%c" : "<%02x>"),
-				     sta->u.ap.ssid[i]);
-		p += sprintf(p, "\n");
+			seq_printf(m, "channel=%d\n", sta->u.ap.channel);
+		seq_puts(m, "ssid=");
+		for (i = 0; i < sta->u.ap.ssid_len; i++) {
+			if (sta->u.ap.ssid[i] >= 32 && sta->u.ap.ssid[i] < 127)
+				seq_putc(m, sta->u.ap.ssid[i]);
+			else
+				seq_printf(m, "<%02x>", sta->u.ap.ssid[i]);
+		}
+		seq_putc(m, '\n');
 	}
 #endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */
 
-	return (p - page);
+	return 0;
 }
 
+static int prism2_sta_proc_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, prism2_sta_proc_show, PDE_DATA(inode));
+}
+
+static const struct file_operations prism2_sta_proc_fops = {
+	.open		= prism2_sta_proc_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= seq_release,
+};
 
 static void handle_add_proc_queue(struct work_struct *work)
 {
@@ -1076,9 +1139,9 @@
 
 		if (sta) {
 			sprintf(name, "%pM", sta->addr);
-			sta->proc = create_proc_read_entry(
+			sta->proc = proc_create_data(
 				name, 0, ap->proc,
-				prism2_sta_proc_read, sta);
+				&prism2_sta_proc_fops, sta);
 
 			atomic_dec(&sta->users);
 		}
diff --git a/drivers/net/wireless/hostap/hostap_download.c b/drivers/net/wireless/hostap/hostap_download.c
index e73bf73..705fe66 100644
--- a/drivers/net/wireless/hostap/hostap_download.c
+++ b/drivers/net/wireless/hostap/hostap_download.c
@@ -174,20 +174,70 @@
 }
 
 
-static int prism2_download_aux_dump(struct net_device *dev,
-				     unsigned int addr, int len, u8 *buf)
+#define prism2_download_aux_dump_npages 65536
+
+struct prism2_download_aux_dump {
+	local_info_t *local;
+	u16 page[0x80];
+};
+
+static int prism2_download_aux_dump_proc_show(struct seq_file *m, void *v)
 {
-	int res;
+	struct prism2_download_aux_dump *ctx = m->private;
 
-	prism2_enable_aux_port(dev, 1);
-	res = hfa384x_from_aux(dev, addr, len, buf);
-	prism2_enable_aux_port(dev, 0);
-	if (res)
-		return -1;
-
+	hfa384x_from_aux(ctx->local->dev, (unsigned long)v - 1, 0x80, ctx->page);
+	seq_write(m, ctx->page, 0x80);
 	return 0;
 }
 
+static void *prism2_download_aux_dump_proc_start(struct seq_file *m, loff_t *_pos)
+{
+	struct prism2_download_aux_dump *ctx = m->private;
+	prism2_enable_aux_port(ctx->local->dev, 1);
+	if (*_pos >= prism2_download_aux_dump_npages)
+		return NULL;
+	return (void *)((unsigned long)*_pos + 1);
+}
+
+static void *prism2_download_aux_dump_proc_next(struct seq_file *m, void *v, loff_t *_pos)
+{
+	++*_pos;
+	if (*_pos >= prism2_download_aux_dump_npages)
+		return NULL;
+	return (void *)((unsigned long)*_pos + 1);
+}
+
+static void prism2_download_aux_dump_proc_stop(struct seq_file *m, void *v)
+{
+	struct prism2_download_aux_dump *ctx = m->private;
+	prism2_enable_aux_port(ctx->local->dev, 0);
+}
+
+static const struct seq_operations prism2_download_aux_dump_proc_seqops = {
+	.start	= prism2_download_aux_dump_proc_start,
+	.next	= prism2_download_aux_dump_proc_next,
+	.stop	= prism2_download_aux_dump_proc_stop,
+	.show	= prism2_download_aux_dump_proc_show,
+};
+
+static int prism2_download_aux_dump_proc_open(struct inode *inode, struct file *file)
+{
+	int ret = seq_open_private(file, &prism2_download_aux_dump_proc_seqops,
+				   sizeof(struct prism2_download_aux_dump));
+	if (ret == 0) {
+		struct seq_file *m = file->private_data;
+		m->private = PDE_DATA(inode);
+	}
+	return ret;
+}
+
+static const struct file_operations prism2_download_aux_dump_proc_fops = {
+	.open		= prism2_download_aux_dump_proc_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= seq_release_private,
+};
+
 
 static u8 * prism2_read_pda(struct net_device *dev)
 {
diff --git a/drivers/net/wireless/hostap/hostap_hw.c b/drivers/net/wireless/hostap/hostap_hw.c
index 8e7000f..507ab99 100644
--- a/drivers/net/wireless/hostap/hostap_hw.c
+++ b/drivers/net/wireless/hostap/hostap_hw.c
@@ -38,6 +38,7 @@
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/proc_fs.h>
+#include <linux/seq_file.h>
 #include <linux/if_arp.h>
 #include <linux/delay.h>
 #include <linux/random.h>
@@ -129,8 +130,7 @@
 
 #ifdef PRISM2_DOWNLOAD_SUPPORT
 /* hostap_download.c */
-static int prism2_download_aux_dump(struct net_device *dev,
-				    unsigned int addr, int len, u8 *buf);
+static const struct file_operations prism2_download_aux_dump_proc_fops;
 static u8 * prism2_read_pda(struct net_device *dev);
 static int prism2_download(local_info_t *local,
 			   struct prism2_download_param *param);
@@ -2894,19 +2894,12 @@
 
 
 #ifndef PRISM2_NO_PROCFS_DEBUG
-static int prism2_registers_proc_read(char *page, char **start, off_t off,
-				      int count, int *eof, void *data)
+static int prism2_registers_proc_show(struct seq_file *m, void *v)
 {
-	char *p = page;
-	local_info_t *local = (local_info_t *) data;
-
-	if (off != 0) {
-		*eof = 1;
-		return 0;
-	}
+	local_info_t *local = m->private;
 
 #define SHOW_REG(n) \
-p += sprintf(p, #n "=%04x\n", hfa384x_read_reg(local->dev, HFA384X_##n##_OFF))
+  seq_printf(m, #n "=%04x\n", hfa384x_read_reg(local->dev, HFA384X_##n##_OFF))
 
 	SHOW_REG(CMD);
 	SHOW_REG(PARAM0);
@@ -2952,8 +2945,21 @@
 	SHOW_REG(PCI_M1_CTL);
 #endif /* PRISM2_PCI */
 
-	return (p - page);
+	return 0;
 }
+
+static int prism2_registers_proc_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, prism2_registers_proc_show, PDE_DATA(inode));
+}
+
+static const struct file_operations prism2_registers_proc_fops = {
+	.open		= prism2_registers_proc_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= seq_release,
+};
+
 #endif /* PRISM2_NO_PROCFS_DEBUG */
 
 
@@ -3128,7 +3134,7 @@
 	local->func->reset_port = prism2_reset_port;
 	local->func->schedule_reset = prism2_schedule_reset;
 #ifdef PRISM2_DOWNLOAD_SUPPORT
-	local->func->read_aux = prism2_download_aux_dump;
+	local->func->read_aux_fops = &prism2_download_aux_dump_proc_fops;
 	local->func->download = prism2_download;
 #endif /* PRISM2_DOWNLOAD_SUPPORT */
 	local->func->tx = prism2_tx_80211;
@@ -3274,8 +3280,8 @@
 		}
 		hostap_init_proc(local);
 #ifndef PRISM2_NO_PROCFS_DEBUG
-		create_proc_read_entry("registers", 0, local->proc,
-				       prism2_registers_proc_read, local);
+		proc_create_data("registers", 0, local->proc,
+				 &prism2_registers_proc_fops, local);
 #endif /* PRISM2_NO_PROCFS_DEBUG */
 		hostap_init_ap_proc(local);
 		return 0;
diff --git a/drivers/net/wireless/hostap/hostap_proc.c b/drivers/net/wireless/hostap/hostap_proc.c
index dc447c1..7491dab 100644
--- a/drivers/net/wireless/hostap/hostap_proc.c
+++ b/drivers/net/wireless/hostap/hostap_proc.c
@@ -12,259 +12,297 @@
 
 
 #ifndef PRISM2_NO_PROCFS_DEBUG
-static int prism2_debug_proc_read(char *page, char **start, off_t off,
-				  int count, int *eof, void *data)
+static int prism2_debug_proc_show(struct seq_file *m, void *v)
 {
-	char *p = page;
-	local_info_t *local = (local_info_t *) data;
+	local_info_t *local = m->private;
 	int i;
 
-	if (off != 0) {
-		*eof = 1;
-		return 0;
-	}
-
-	p += sprintf(p, "next_txfid=%d next_alloc=%d\n",
-		     local->next_txfid, local->next_alloc);
+	seq_printf(m, "next_txfid=%d next_alloc=%d\n",
+		   local->next_txfid, local->next_alloc);
 	for (i = 0; i < PRISM2_TXFID_COUNT; i++)
-		p += sprintf(p, "FID: tx=%04X intransmit=%04X\n",
-			     local->txfid[i], local->intransmitfid[i]);
-	p += sprintf(p, "FW TX rate control: %d\n", local->fw_tx_rate_control);
-	p += sprintf(p, "beacon_int=%d\n", local->beacon_int);
-	p += sprintf(p, "dtim_period=%d\n", local->dtim_period);
-	p += sprintf(p, "wds_max_connections=%d\n",
-		     local->wds_max_connections);
-	p += sprintf(p, "dev_enabled=%d\n", local->dev_enabled);
-	p += sprintf(p, "sw_tick_stuck=%d\n", local->sw_tick_stuck);
+		seq_printf(m, "FID: tx=%04X intransmit=%04X\n",
+			   local->txfid[i], local->intransmitfid[i]);
+	seq_printf(m, "FW TX rate control: %d\n", local->fw_tx_rate_control);
+	seq_printf(m, "beacon_int=%d\n", local->beacon_int);
+	seq_printf(m, "dtim_period=%d\n", local->dtim_period);
+	seq_printf(m, "wds_max_connections=%d\n", local->wds_max_connections);
+	seq_printf(m, "dev_enabled=%d\n", local->dev_enabled);
+	seq_printf(m, "sw_tick_stuck=%d\n", local->sw_tick_stuck);
 	for (i = 0; i < WEP_KEYS; i++) {
 		if (local->crypt_info.crypt[i] &&
 		    local->crypt_info.crypt[i]->ops) {
-			p += sprintf(p, "crypt[%d]=%s\n", i,
-				     local->crypt_info.crypt[i]->ops->name);
+			seq_printf(m, "crypt[%d]=%s\n", i,
+				   local->crypt_info.crypt[i]->ops->name);
 		}
 	}
-	p += sprintf(p, "pri_only=%d\n", local->pri_only);
-	p += sprintf(p, "pci=%d\n", local->func->hw_type == HOSTAP_HW_PCI);
-	p += sprintf(p, "sram_type=%d\n", local->sram_type);
-	p += sprintf(p, "no_pri=%d\n", local->no_pri);
+	seq_printf(m, "pri_only=%d\n", local->pri_only);
+	seq_printf(m, "pci=%d\n", local->func->hw_type == HOSTAP_HW_PCI);
+	seq_printf(m, "sram_type=%d\n", local->sram_type);
+	seq_printf(m, "no_pri=%d\n", local->no_pri);
 
-	return (p - page);
+	return 0;
 }
+
+static int prism2_debug_proc_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, prism2_debug_proc_show, PDE_DATA(inode));
+}
+
+static const struct file_operations prism2_debug_proc_fops = {
+	.open		= prism2_debug_proc_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= seq_release,
+};
 #endif /* PRISM2_NO_PROCFS_DEBUG */
 
 
-static int prism2_stats_proc_read(char *page, char **start, off_t off,
-				  int count, int *eof, void *data)
+static int prism2_stats_proc_show(struct seq_file *m, void *v)
 {
-	char *p = page;
-	local_info_t *local = (local_info_t *) data;
+	local_info_t *local = m->private;
 	struct comm_tallies_sums *sums = &local->comm_tallies;
 
-	if (off != 0) {
-		*eof = 1;
-		return 0;
-	}
-
-	p += sprintf(p, "TxUnicastFrames=%u\n", sums->tx_unicast_frames);
-	p += sprintf(p, "TxMulticastframes=%u\n", sums->tx_multicast_frames);
-	p += sprintf(p, "TxFragments=%u\n", sums->tx_fragments);
-	p += sprintf(p, "TxUnicastOctets=%u\n", sums->tx_unicast_octets);
-	p += sprintf(p, "TxMulticastOctets=%u\n", sums->tx_multicast_octets);
-	p += sprintf(p, "TxDeferredTransmissions=%u\n",
-		     sums->tx_deferred_transmissions);
-	p += sprintf(p, "TxSingleRetryFrames=%u\n",
-		     sums->tx_single_retry_frames);
-	p += sprintf(p, "TxMultipleRetryFrames=%u\n",
-		     sums->tx_multiple_retry_frames);
-	p += sprintf(p, "TxRetryLimitExceeded=%u\n",
-		     sums->tx_retry_limit_exceeded);
-	p += sprintf(p, "TxDiscards=%u\n", sums->tx_discards);
-	p += sprintf(p, "RxUnicastFrames=%u\n", sums->rx_unicast_frames);
-	p += sprintf(p, "RxMulticastFrames=%u\n", sums->rx_multicast_frames);
-	p += sprintf(p, "RxFragments=%u\n", sums->rx_fragments);
-	p += sprintf(p, "RxUnicastOctets=%u\n", sums->rx_unicast_octets);
-	p += sprintf(p, "RxMulticastOctets=%u\n", sums->rx_multicast_octets);
-	p += sprintf(p, "RxFCSErrors=%u\n", sums->rx_fcs_errors);
-	p += sprintf(p, "RxDiscardsNoBuffer=%u\n",
-		     sums->rx_discards_no_buffer);
-	p += sprintf(p, "TxDiscardsWrongSA=%u\n", sums->tx_discards_wrong_sa);
-	p += sprintf(p, "RxDiscardsWEPUndecryptable=%u\n",
-		     sums->rx_discards_wep_undecryptable);
-	p += sprintf(p, "RxMessageInMsgFragments=%u\n",
-		     sums->rx_message_in_msg_fragments);
-	p += sprintf(p, "RxMessageInBadMsgFragments=%u\n",
-		     sums->rx_message_in_bad_msg_fragments);
+	seq_printf(m, "TxUnicastFrames=%u\n", sums->tx_unicast_frames);
+	seq_printf(m, "TxMulticastframes=%u\n", sums->tx_multicast_frames);
+	seq_printf(m, "TxFragments=%u\n", sums->tx_fragments);
+	seq_printf(m, "TxUnicastOctets=%u\n", sums->tx_unicast_octets);
+	seq_printf(m, "TxMulticastOctets=%u\n", sums->tx_multicast_octets);
+	seq_printf(m, "TxDeferredTransmissions=%u\n",
+		   sums->tx_deferred_transmissions);
+	seq_printf(m, "TxSingleRetryFrames=%u\n", sums->tx_single_retry_frames);
+	seq_printf(m, "TxMultipleRetryFrames=%u\n",
+		   sums->tx_multiple_retry_frames);
+	seq_printf(m, "TxRetryLimitExceeded=%u\n",
+		   sums->tx_retry_limit_exceeded);
+	seq_printf(m, "TxDiscards=%u\n", sums->tx_discards);
+	seq_printf(m, "RxUnicastFrames=%u\n", sums->rx_unicast_frames);
+	seq_printf(m, "RxMulticastFrames=%u\n", sums->rx_multicast_frames);
+	seq_printf(m, "RxFragments=%u\n", sums->rx_fragments);
+	seq_printf(m, "RxUnicastOctets=%u\n", sums->rx_unicast_octets);
+	seq_printf(m, "RxMulticastOctets=%u\n", sums->rx_multicast_octets);
+	seq_printf(m, "RxFCSErrors=%u\n", sums->rx_fcs_errors);
+	seq_printf(m, "RxDiscardsNoBuffer=%u\n", sums->rx_discards_no_buffer);
+	seq_printf(m, "TxDiscardsWrongSA=%u\n", sums->tx_discards_wrong_sa);
+	seq_printf(m, "RxDiscardsWEPUndecryptable=%u\n",
+		   sums->rx_discards_wep_undecryptable);
+	seq_printf(m, "RxMessageInMsgFragments=%u\n",
+		   sums->rx_message_in_msg_fragments);
+	seq_printf(m, "RxMessageInBadMsgFragments=%u\n",
+		   sums->rx_message_in_bad_msg_fragments);
 	/* FIX: this may grow too long for one page(?) */
 
-	return (p - page);
+	return 0;
 }
 
-
-static int prism2_wds_proc_read(char *page, char **start, off_t off,
-				int count, int *eof, void *data)
+static int prism2_stats_proc_open(struct inode *inode, struct file *file)
 {
-	char *p = page;
-	local_info_t *local = (local_info_t *) data;
-	struct list_head *ptr;
+	return single_open(file, prism2_stats_proc_show, PDE_DATA(inode));
+}
+
+static const struct file_operations prism2_stats_proc_fops = {
+	.open		= prism2_stats_proc_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= seq_release,
+};
+
+
+static int prism2_wds_proc_show(struct seq_file *m, void *v)
+{
+	struct list_head *ptr = v;
 	struct hostap_interface *iface;
 
-	if (off > PROC_LIMIT) {
-		*eof = 1;
-		return 0;
-	}
-
-	read_lock_bh(&local->iface_lock);
-	list_for_each(ptr, &local->hostap_interfaces) {
-		iface = list_entry(ptr, struct hostap_interface, list);
-		if (iface->type != HOSTAP_INTERFACE_WDS)
-			continue;
-		p += sprintf(p, "%s\t%pM\n",
-			     iface->dev->name,
-			     iface->u.wds.remote_addr);
-		if ((p - page) > PROC_LIMIT) {
-			printk(KERN_DEBUG "%s: wds proc did not fit\n",
-			       local->dev->name);
-			break;
-		}
-	}
-	read_unlock_bh(&local->iface_lock);
-
-	if ((p - page) <= off) {
-		*eof = 1;
-		return 0;
-	}
-
-	*start = page + off;
-
-	return (p - page - off);
+	iface = list_entry(ptr, struct hostap_interface, list);
+	if (iface->type == HOSTAP_INTERFACE_WDS)
+		seq_printf(m, "%s\t%pM\n",
+			   iface->dev->name, iface->u.wds.remote_addr);
+	return 0;
 }
 
-
-static int prism2_bss_list_proc_read(char *page, char **start, off_t off,
-				     int count, int *eof, void *data)
+static void *prism2_wds_proc_start(struct seq_file *m, loff_t *_pos)
 {
-	char *p = page;
-	local_info_t *local = (local_info_t *) data;
-	struct list_head *ptr;
+	local_info_t *local = m->private;
+	read_lock_bh(&local->iface_lock);
+	return seq_list_start(&local->hostap_interfaces, *_pos);
+}
+
+static void *prism2_wds_proc_next(struct seq_file *m, void *v, loff_t *_pos)
+{
+	local_info_t *local = m->private;
+	return seq_list_next(v, &local->hostap_interfaces, _pos);
+}
+
+static void prism2_wds_proc_stop(struct seq_file *m, void *v)
+{
+	local_info_t *local = m->private;
+	read_unlock_bh(&local->iface_lock);
+}
+
+static const struct seq_operations prism2_wds_proc_seqops = {
+	.start	= prism2_wds_proc_start,
+	.next	= prism2_wds_proc_next,
+	.stop	= prism2_wds_proc_stop,
+	.show	= prism2_wds_proc_show,
+};
+
+static int prism2_wds_proc_open(struct inode *inode, struct file *file)
+{
+	int ret = seq_open(file, &prism2_wds_proc_seqops);
+	if (ret == 0) {
+		struct seq_file *m = file->private_data;
+		m->private = PDE_DATA(inode);
+	}
+	return ret;
+}
+
+static const struct file_operations prism2_wds_proc_fops = {
+	.open		= prism2_wds_proc_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= seq_release,
+};
+
+
+static int prism2_bss_list_proc_show(struct seq_file *m, void *v)
+{
+	local_info_t *local = m->private;
+	struct list_head *ptr = v;
 	struct hostap_bss_info *bss;
 	int i;
 
-	if (off > PROC_LIMIT) {
-		*eof = 1;
+	if (ptr == &local->bss_list) {
+		seq_printf(m, "#BSSID\tlast_update\tcount\tcapab_info\tSSID(txt)\t"
+			   "SSID(hex)\tWPA IE\n");
 		return 0;
 	}
 
-	p += sprintf(p, "#BSSID\tlast_update\tcount\tcapab_info\tSSID(txt)\t"
-		     "SSID(hex)\tWPA IE\n");
-	spin_lock_bh(&local->lock);
-	list_for_each(ptr, &local->bss_list) {
-		bss = list_entry(ptr, struct hostap_bss_info, list);
-		p += sprintf(p, "%pM\t%lu\t%u\t0x%x\t",
-			     bss->bssid, bss->last_update,
-			     bss->count, bss->capab_info);
-		for (i = 0; i < bss->ssid_len; i++) {
-			p += sprintf(p, "%c",
-				     bss->ssid[i] >= 32 && bss->ssid[i] < 127 ?
-				     bss->ssid[i] : '_');
-		}
-		p += sprintf(p, "\t");
-		for (i = 0; i < bss->ssid_len; i++) {
-			p += sprintf(p, "%02x", bss->ssid[i]);
-		}
-		p += sprintf(p, "\t");
-		for (i = 0; i < bss->wpa_ie_len; i++) {
-			p += sprintf(p, "%02x", bss->wpa_ie[i]);
-		}
-		p += sprintf(p, "\n");
-		if ((p - page) > PROC_LIMIT) {
-			printk(KERN_DEBUG "%s: BSS proc did not fit\n",
-			       local->dev->name);
-			break;
-		}
-	}
-	spin_unlock_bh(&local->lock);
+	bss = list_entry(ptr, struct hostap_bss_info, list);
+	seq_printf(m, "%pM\t%lu\t%u\t0x%x\t",
+		   bss->bssid, bss->last_update,
+		   bss->count, bss->capab_info);
 
-	if ((p - page) <= off) {
-		*eof = 1;
-		return 0;
-	}
+	for (i = 0; i < bss->ssid_len; i++)
+		seq_putc(m,bss->ssid[i] >= 32 && bss->ssid[i] < 127 ?
+			   bss->ssid[i] : '_');
 
-	*start = page + off;
-
-	return (p - page - off);
+	seq_putc(m, '\t');
+	for (i = 0; i < bss->ssid_len; i++)
+		seq_printf(m, "%02x", bss->ssid[i]);
+	seq_putc(m, '\t');
+	for (i = 0; i < bss->wpa_ie_len; i++)
+		seq_printf(m, "%02x", bss->wpa_ie[i]);
+	seq_putc(m, '\n');
+	return 0;
 }
 
-
-static int prism2_crypt_proc_read(char *page, char **start, off_t off,
-				  int count, int *eof, void *data)
+static void *prism2_bss_list_proc_start(struct seq_file *m, loff_t *_pos)
 {
-	char *p = page;
-	local_info_t *local = (local_info_t *) data;
+	local_info_t *local = m->private;
+	spin_lock_bh(&local->lock);
+	return seq_list_start_head(&local->bss_list, *_pos);
+}
+
+static void *prism2_bss_list_proc_next(struct seq_file *m, void *v, loff_t *_pos)
+{
+	local_info_t *local = m->private;
+	return seq_list_next(v, &local->bss_list, _pos);
+}
+
+static void prism2_bss_list_proc_stop(struct seq_file *m, void *v)
+{
+	local_info_t *local = m->private;
+	spin_unlock_bh(&local->lock);
+}
+
+static const struct seq_operations prism2_bss_list_proc_seqops = {
+	.start	= prism2_bss_list_proc_start,
+	.next	= prism2_bss_list_proc_next,
+	.stop	= prism2_bss_list_proc_stop,
+	.show	= prism2_bss_list_proc_show,
+};
+
+static int prism2_bss_list_proc_open(struct inode *inode, struct file *file)
+{
+	int ret = seq_open(file, &prism2_bss_list_proc_seqops);
+	if (ret == 0) {
+		struct seq_file *m = file->private_data;
+		m->private = PDE_DATA(inode);
+	}
+	return ret;
+}
+
+static const struct file_operations prism2_bss_list_proc_fops = {
+	.open		= prism2_bss_list_proc_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= seq_release,
+};
+
+
+static int prism2_crypt_proc_show(struct seq_file *m, void *v)
+{
+	local_info_t *local = m->private;
 	int i;
 
-	if (off > PROC_LIMIT) {
-		*eof = 1;
-		return 0;
-	}
-
-	p += sprintf(p, "tx_keyidx=%d\n", local->crypt_info.tx_keyidx);
+	seq_printf(m, "tx_keyidx=%d\n", local->crypt_info.tx_keyidx);
 	for (i = 0; i < WEP_KEYS; i++) {
 		if (local->crypt_info.crypt[i] &&
 		    local->crypt_info.crypt[i]->ops &&
 		    local->crypt_info.crypt[i]->ops->print_stats) {
-			p = local->crypt_info.crypt[i]->ops->print_stats(
-				p, local->crypt_info.crypt[i]->priv);
+			local->crypt_info.crypt[i]->ops->print_stats(
+				m, local->crypt_info.crypt[i]->priv);
 		}
 	}
-
-	if ((p - page) <= off) {
-		*eof = 1;
-		return 0;
-	}
-
-	*start = page + off;
-
-	return (p - page - off);
+	return 0;
 }
 
-
-static int prism2_pda_proc_read(char *page, char **start, off_t off,
-				int count, int *eof, void *data)
+static int prism2_crypt_proc_open(struct inode *inode, struct file *file)
 {
-	local_info_t *local = (local_info_t *) data;
+	return single_open(file, prism2_crypt_proc_show, PDE_DATA(inode));
+}
 
-	if (local->pda == NULL || off >= PRISM2_PDA_SIZE) {
-		*eof = 1;
+static const struct file_operations prism2_crypt_proc_fops = {
+	.open		= prism2_crypt_proc_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= seq_release,
+};
+
+
+static ssize_t prism2_pda_proc_read(struct file *file, char __user *buf,
+				    size_t count, loff_t *_pos)
+{
+	local_info_t *local = PDE_DATA(file_inode(file));
+	size_t off;
+
+	if (local->pda == NULL || *_pos >= PRISM2_PDA_SIZE)
 		return 0;
-	}
 
-	if (off + count > PRISM2_PDA_SIZE)
+	off = *_pos;
+	if (count > PRISM2_PDA_SIZE - off)
 		count = PRISM2_PDA_SIZE - off;
-
-	memcpy(page, local->pda + off, count);
+	if (copy_to_user(buf, local->pda + off, count) != 0)
+		return -EFAULT;
+	*_pos += count;
 	return count;
 }
 
+static const struct file_operations prism2_pda_proc_fops = {
+	.read		= prism2_pda_proc_read,
+	.llseek		= generic_file_llseek,
+};
 
-static int prism2_aux_dump_proc_read(char *page, char **start, off_t off,
-				     int count, int *eof, void *data)
+
+static ssize_t prism2_aux_dump_proc_no_read(struct file *file, char __user *buf,
+					    size_t bufsize, loff_t *_pos)
 {
-	local_info_t *local = (local_info_t *) data;
-
-	if (local->func->read_aux == NULL) {
-		*eof = 1;
-		return 0;
-	}
-
-	if (local->func->read_aux(local->dev, off, count, page)) {
-		*eof = 1;
-		return 0;
-	}
-	*start = page;
-
-	return count;
+	return 0;
 }
 
+static const struct file_operations prism2_aux_dump_proc_fops = {
+	.read		= prism2_aux_dump_proc_no_read,
+};
+
 
 #ifdef PRISM2_IO_DEBUG
 static int prism2_io_debug_proc_read(char *page, char **start, off_t off,
@@ -306,82 +344,108 @@
 
 
 #ifndef PRISM2_NO_STATION_MODES
-static int prism2_scan_results_proc_read(char *page, char **start, off_t off,
-					 int count, int *eof, void *data)
+static int prism2_scan_results_proc_show(struct seq_file *m, void *v)
 {
-	char *p = page;
-	local_info_t *local = (local_info_t *) data;
-	int entry, i, len, total = 0;
+	local_info_t *local = m->private;
+	unsigned long entry;
+	int i, len;
 	struct hfa384x_hostscan_result *scanres;
-	u8 *pos;
+	u8 *p;
 
-	p += sprintf(p, "CHID ANL SL BcnInt Capab Rate BSSID ATIM SupRates "
-		     "SSID\n");
-
-	spin_lock_bh(&local->lock);
-	for (entry = 0; entry < local->last_scan_results_count; entry++) {
-		scanres = &local->last_scan_results[entry];
-
-		if (total + (p - page) <= off) {
-			total += p - page;
-			p = page;
-		}
-		if (total + (p - page) > off + count)
-			break;
-		if ((p - page) > (PAGE_SIZE - 200))
-			break;
-
-		p += sprintf(p, "%d %d %d %d 0x%02x %d %pM %d ",
-			     le16_to_cpu(scanres->chid),
-			     (s16) le16_to_cpu(scanres->anl),
-			     (s16) le16_to_cpu(scanres->sl),
-			     le16_to_cpu(scanres->beacon_interval),
-			     le16_to_cpu(scanres->capability),
-			     le16_to_cpu(scanres->rate),
-			     scanres->bssid,
-			     le16_to_cpu(scanres->atim));
-
-		pos = scanres->sup_rates;
-		for (i = 0; i < sizeof(scanres->sup_rates); i++) {
-			if (pos[i] == 0)
-				break;
-			p += sprintf(p, "<%02x>", pos[i]);
-		}
-		p += sprintf(p, " ");
-
-		pos = scanres->ssid;
-		len = le16_to_cpu(scanres->ssid_len);
-		if (len > 32)
-			len = 32;
-		for (i = 0; i < len; i++) {
-			unsigned char c = pos[i];
-			if (c >= 32 && c < 127)
-				p += sprintf(p, "%c", c);
-			else
-				p += sprintf(p, "<%02x>", c);
-		}
-		p += sprintf(p, "\n");
-	}
-	spin_unlock_bh(&local->lock);
-
-	total += (p - page);
-	if (total >= off + count)
-		*eof = 1;
-
-	if (total < off) {
-		*eof = 1;
+	if (v == SEQ_START_TOKEN) {
+		seq_printf(m,
+			   "CHID ANL SL BcnInt Capab Rate BSSID ATIM SupRates SSID\n");
 		return 0;
 	}
 
-	len = total - off;
-	if (len > (p - page))
-		len = p - page;
-	*start = p - len;
-	if (len > count)
-		len = count;
+	entry = (unsigned long)v - 2;
+	scanres = &local->last_scan_results[entry];
 
-	return len;
+	seq_printf(m, "%d %d %d %d 0x%02x %d %pM %d ",
+		   le16_to_cpu(scanres->chid),
+		   (s16) le16_to_cpu(scanres->anl),
+		   (s16) le16_to_cpu(scanres->sl),
+		   le16_to_cpu(scanres->beacon_interval),
+		   le16_to_cpu(scanres->capability),
+		   le16_to_cpu(scanres->rate),
+		   scanres->bssid,
+		   le16_to_cpu(scanres->atim));
+
+	p = scanres->sup_rates;
+	for (i = 0; i < sizeof(scanres->sup_rates); i++) {
+		if (p[i] == 0)
+			break;
+		seq_printf(m, "<%02x>", p[i]);
+	}
+	seq_putc(m, ' ');
+
+	p = scanres->ssid;
+	len = le16_to_cpu(scanres->ssid_len);
+	if (len > 32)
+		len = 32;
+	for (i = 0; i < len; i++) {
+		unsigned char c = p[i];
+		if (c >= 32 && c < 127)
+			seq_putc(m, c);
+		else
+			seq_printf(m, "<%02x>", c);
+	}
+	seq_putc(m, '\n');
+	return 0;
 }
+
+static void *prism2_scan_results_proc_start(struct seq_file *m, loff_t *_pos)
+{
+	local_info_t *local = m->private;
+	spin_lock_bh(&local->lock);
+
+	/* We have a header (pos 0) + N results to show (pos 1...N) */
+	if (*_pos > local->last_scan_results_count)
+		return NULL;
+	return (void *)(unsigned long)(*_pos + 1); /* 0 would be EOF */
+}
+
+static void *prism2_scan_results_proc_next(struct seq_file *m, void *v, loff_t *_pos)
+{
+	local_info_t *local = m->private;
+
+	++*_pos;
+	if (*_pos > local->last_scan_results_count)
+		return NULL;
+	return (void *)(unsigned long)(*_pos + 1); /* 0 would be EOF */
+}
+
+static void prism2_scan_results_proc_stop(struct seq_file *m, void *v)
+{
+	local_info_t *local = m->private;
+	spin_unlock_bh(&local->lock);
+}
+
+static const struct seq_operations prism2_scan_results_proc_seqops = {
+	.start	= prism2_scan_results_proc_start,
+	.next	= prism2_scan_results_proc_next,
+	.stop	= prism2_scan_results_proc_stop,
+	.show	= prism2_scan_results_proc_show,
+};
+
+static int prism2_scan_results_proc_open(struct inode *inode, struct file *file)
+{
+	int ret = seq_open(file, &prism2_scan_results_proc_seqops);
+	if (ret == 0) {
+		struct seq_file *m = file->private_data;
+		m->private = PDE_DATA(inode);
+	}
+	return ret;
+}
+
+static const struct file_operations prism2_scan_results_proc_fops = {
+	.open		= prism2_scan_results_proc_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= seq_release,
+};
+
+
 #endif /* PRISM2_NO_STATION_MODES */
 
 
@@ -403,53 +467,36 @@
 	}
 
 #ifndef PRISM2_NO_PROCFS_DEBUG
-	create_proc_read_entry("debug", 0, local->proc,
-			       prism2_debug_proc_read, local);
+	proc_create_data("debug", 0, local->proc,
+			 &prism2_debug_proc_fops, local);
 #endif /* PRISM2_NO_PROCFS_DEBUG */
-	create_proc_read_entry("stats", 0, local->proc,
-			       prism2_stats_proc_read, local);
-	create_proc_read_entry("wds", 0, local->proc,
-			       prism2_wds_proc_read, local);
-	create_proc_read_entry("pda", 0, local->proc,
-			       prism2_pda_proc_read, local);
-	create_proc_read_entry("aux_dump", 0, local->proc,
-			       prism2_aux_dump_proc_read, local);
-	create_proc_read_entry("bss_list", 0, local->proc,
-			       prism2_bss_list_proc_read, local);
-	create_proc_read_entry("crypt", 0, local->proc,
-			       prism2_crypt_proc_read, local);
+	proc_create_data("stats", 0, local->proc,
+			 &prism2_stats_proc_fops, local);
+	proc_create_data("wds", 0, local->proc,
+			 &prism2_wds_proc_fops, local);
+	proc_create_data("pda", 0, local->proc,
+			 &prism2_pda_proc_fops, local);
+	proc_create_data("aux_dump", 0, local->proc,
+			 local->func->read_aux_fops ?: &prism2_aux_dump_proc_fops,
+			 local);
+	proc_create_data("bss_list", 0, local->proc,
+			 &prism2_bss_list_proc_fops, local);
+	proc_create_data("crypt", 0, local->proc,
+			 &prism2_crypt_proc_fops, local);
 #ifdef PRISM2_IO_DEBUG
-	create_proc_read_entry("io_debug", 0, local->proc,
-			       prism2_io_debug_proc_read, local);
+	proc_create_data("io_debug", 0, local->proc,
+			 &prism2_io_debug_proc_fops, local);
 #endif /* PRISM2_IO_DEBUG */
 #ifndef PRISM2_NO_STATION_MODES
-	create_proc_read_entry("scan_results", 0, local->proc,
-			       prism2_scan_results_proc_read, local);
+	proc_create_data("scan_results", 0, local->proc,
+			 &prism2_scan_results_proc_fops, local);
 #endif /* PRISM2_NO_STATION_MODES */
 }
 
 
 void hostap_remove_proc(local_info_t *local)
 {
-	if (local->proc != NULL) {
-#ifndef PRISM2_NO_STATION_MODES
-		remove_proc_entry("scan_results", local->proc);
-#endif /* PRISM2_NO_STATION_MODES */
-#ifdef PRISM2_IO_DEBUG
-		remove_proc_entry("io_debug", local->proc);
-#endif /* PRISM2_IO_DEBUG */
-		remove_proc_entry("pda", local->proc);
-		remove_proc_entry("aux_dump", local->proc);
-		remove_proc_entry("wds", local->proc);
-		remove_proc_entry("stats", local->proc);
-		remove_proc_entry("bss_list", local->proc);
-		remove_proc_entry("crypt", local->proc);
-#ifndef PRISM2_NO_PROCFS_DEBUG
-		remove_proc_entry("debug", local->proc);
-#endif /* PRISM2_NO_PROCFS_DEBUG */
-		if (hostap_proc != NULL)
-			remove_proc_entry(local->proc->name, hostap_proc);
-	}
+	remove_proc_subtree(local->ddev->name, hostap_proc);
 }
 
 
diff --git a/drivers/net/wireless/hostap/hostap_wlan.h b/drivers/net/wireless/hostap/hostap_wlan.h
index 7bb0b4b..5790401 100644
--- a/drivers/net/wireless/hostap/hostap_wlan.h
+++ b/drivers/net/wireless/hostap/hostap_wlan.h
@@ -596,8 +596,7 @@
 			struct prism2_download_param *param);
 	int (*tx)(struct sk_buff *skb, struct net_device *dev);
 	int (*set_tim)(struct net_device *dev, int aid, int set);
-	int (*read_aux)(struct net_device *dev, unsigned addr, int len,
-			u8 *buf);
+	const struct file_operations *read_aux_fops;
 
 	int need_tx_headroom; /* number of bytes of headroom needed before
 			       * IEEE 802.11 header */
diff --git a/drivers/net/wireless/ray_cs.c b/drivers/net/wireless/ray_cs.c
index ebada81..9b557a1 100644
--- a/drivers/net/wireless/ray_cs.c
+++ b/drivers/net/wireless/ray_cs.c
@@ -2778,7 +2778,7 @@
 		nr = nr * 10 + c;
 		p++;
 	} while (--len);
-	*(int *)PDE(file_inode(file))->data = nr;
+	*(int *)PDE_DATA(file_inode(file)) = nr;
 	return count;
 }
 
diff --git a/drivers/nubus/nubus.c b/drivers/nubus/nubus.c
index 44d01af..43926cd 100644
--- a/drivers/nubus/nubus.c
+++ b/drivers/nubus/nubus.c
@@ -19,7 +19,6 @@
 #include <asm/setup.h>
 #include <asm/page.h>
 #include <asm/hwtest.h>
-#include <linux/proc_fs.h>
 #include <asm/mac_via.h>
 #include <asm/mac_oss.h>
 
@@ -954,56 +953,6 @@
 	}
 }
 
-#if defined(CONFIG_PROC_FS)
-
-/* /proc/nubus stuff */
-
-static int sprint_nubus_board(struct nubus_board* board, char* ptr, int len)
-{
-	if(len < 100)
-		return -1;
-	
-	sprintf(ptr, "Slot %X: %s\n",
-		board->slot, board->name);
-	
-	return strlen(ptr);
-}
-
-static int nubus_read_proc(char *page, char **start, off_t off,
-				int count, int *eof, void *data)
-{
-	int nprinted, len, begin = 0;
-	int size = PAGE_SIZE;
-	struct nubus_board* board;
-	
-	len   = sprintf(page, "Nubus devices found:\n");
-	/* Walk the list of NuBus boards */
-	for (board = nubus_boards; board != NULL; board = board->next)
-	{
-		nprinted = sprint_nubus_board(board, page + len, size - len);
-		if (nprinted < 0)
-			break;
-		len += nprinted;
-		if (len+begin < off) {
-			begin += len;
-			len = 0;
-		}
-		if (len+begin >= off+count)
-			break;
-	}
-	if (len+begin < off)
-		*eof = 1;
-	off -= begin;
-	*start = page + off;
-	len -= off;
-	if (len>count)
-		len = count;
-	if (len<0)
-		len = 0;
-	return len;
-}
-#endif
-
 void __init nubus_scan_bus(void)
 {
 	int slot;
@@ -1041,11 +990,7 @@
 	nubus_devices = NULL;
 	nubus_boards  = NULL;
 	nubus_scan_bus();
-
-#ifdef CONFIG_PROC_FS
-	create_proc_read_entry("nubus", 0, NULL, nubus_read_proc, NULL);
 	nubus_proc_init();
-#endif
 	return 0;
 }
 
diff --git a/drivers/nubus/proc.c b/drivers/nubus/proc.c
index 208dd12..b8286ed 100644
--- a/drivers/nubus/proc.c
+++ b/drivers/nubus/proc.c
@@ -52,7 +52,6 @@
 }
 
 static const struct file_operations nubus_devices_proc_fops = {
-	.owner		= THIS_MODULE,
 	.open		= nubus_devices_proc_open,
 	.read		= seq_read,
 	.llseek		= seq_lseek,
@@ -61,6 +60,10 @@
 
 static struct proc_dir_entry *proc_bus_nubus_dir;
 
+static const struct file_operations nubus_proc_subdir_fops = {
+#warning Need to set some I/O handlers here
+};
+
 static void nubus_proc_subdir(struct nubus_dev* dev,
 			      struct proc_dir_entry* parent,
 			      struct nubus_dir* dir)
@@ -73,9 +76,10 @@
 		struct proc_dir_entry* e;
 		
 		sprintf(name, "%x", ent.type);
-		e = create_proc_entry(name, S_IFREG | S_IRUGO |
-				      S_IWUSR, parent);
-		if (!e) return;
+		e = proc_create(name, S_IFREG | S_IRUGO | S_IWUSR, parent,
+				&nubus_proc_subdir_fops);
+		if (!e)
+			return;
 	}
 }
 
@@ -158,6 +162,73 @@
 }
 EXPORT_SYMBOL(nubus_proc_detach_device);
 
+/*
+ * /proc/nubus stuff
+ */
+static int nubus_proc_show(struct seq_file *m, void *v)
+{
+	const struct nubus_board *board = v;
+
+	/* Display header on line 1 */
+	if (v == SEQ_START_TOKEN)
+		seq_puts(m, "Nubus devices found:\n");
+	else
+		seq_printf(m, "Slot %X: %s\n", board->slot, board->name);
+	return 0;
+}
+
+static void *nubus_proc_start(struct seq_file *m, loff_t *_pos)
+{
+	struct nubus_board *board;
+	unsigned pos;
+
+	if (*_pos > LONG_MAX)
+		return NULL;
+	pos = *_pos;
+	if (pos == 0)
+		return SEQ_START_TOKEN;
+	for (board = nubus_boards; board; board = board->next)
+		if (--pos == 0)
+			break;
+	return board;
+}
+
+static void *nubus_proc_next(struct seq_file *p, void *v, loff_t *_pos)
+{
+	/* Walk the list of NuBus boards */
+	struct nubus_board *board = v;
+
+	++*_pos;
+	if (v == SEQ_START_TOKEN)
+		board = nubus_boards;
+	else if (board)
+		board = board->next;
+	return board;
+}
+
+static void nubus_proc_stop(struct seq_file *p, void *v)
+{
+}
+
+static const struct seq_operations nubus_proc_seqops = {
+	.start	= nubus_proc_start,
+	.next	= nubus_proc_next,
+	.stop	= nubus_proc_stop,
+	.show	= nubus_proc_show,
+};
+
+static int nubus_proc_open(struct inode *inode, struct file *file)
+{
+	return seq_open(file, &nubus_proc_seqops);
+}
+
+static const struct file_operations nubus_proc_fops = {
+	.open		= nubus_proc_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= seq_release,
+};
+
 void __init proc_bus_nubus_add_devices(void)
 {
 	struct nubus_dev *dev;
@@ -168,6 +239,7 @@
 
 void __init nubus_proc_init(void)
 {
+	proc_create("nubus", 0, NULL, &nubus_proc_fops);
 	if (!MACH_IS_MAC)
 		return;
 	proc_bus_nubus_dir = proc_mkdir("bus/nubus", NULL);
diff --git a/drivers/of/base.c b/drivers/of/base.c
index 1733081..0a2bdd1 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -1453,16 +1453,7 @@
 #ifdef CONFIG_PROC_DEVICETREE
 static void of_remove_proc_dt_entry(struct device_node *dn)
 {
-	struct device_node *parent = dn->parent;
-	struct property *prop = dn->properties;
-
-	while (prop) {
-		remove_proc_entry(prop->name, dn->pde);
-		prop = prop->next;
-	}
-
-	if (dn->pde)
-		remove_proc_entry(dn->pde->name, parent->pde);
+	proc_remove(dn->pde);
 }
 #else
 static void of_remove_proc_dt_entry(struct device_node *dn)
diff --git a/drivers/parisc/led.c b/drivers/parisc/led.c
index d4d800c..b482431 100644
--- a/drivers/parisc/led.c
+++ b/drivers/parisc/led.c
@@ -172,14 +172,14 @@
 
 static int led_proc_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, led_proc_show, PDE(inode)->data);
+	return single_open(file, led_proc_show, PDE_DATA(inode));
 }
 
 
 static ssize_t led_proc_write(struct file *file, const char *buf,
 	size_t count, loff_t *pos)
 {
-	void *data = PDE(file_inode(file))->data;
+	void *data = PDE_DATA(file_inode(file));
 	char *cur, lbuf[32];
 	int d;
 
diff --git a/drivers/pci/proc.c b/drivers/pci/proc.c
index 0b00947..0812608 100644
--- a/drivers/pci/proc.c
+++ b/drivers/pci/proc.c
@@ -46,9 +46,7 @@
 static ssize_t
 proc_bus_pci_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos)
 {
-	const struct inode *ino = file_inode(file);
-	const struct proc_dir_entry *dp = PDE(ino);
-	struct pci_dev *dev = dp->data;
+	struct pci_dev *dev = PDE_DATA(file_inode(file));
 	unsigned int pos = *ppos;
 	unsigned int cnt, size;
 
@@ -59,7 +57,7 @@
 	 */
 
 	if (capable(CAP_SYS_ADMIN))
-		size = dp->size;
+		size = dev->cfg_size;
 	else if (dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)
 		size = 128;
 	else
@@ -133,10 +131,9 @@
 proc_bus_pci_write(struct file *file, const char __user *buf, size_t nbytes, loff_t *ppos)
 {
 	struct inode *ino = file_inode(file);
-	const struct proc_dir_entry *dp = PDE(ino);
-	struct pci_dev *dev = dp->data;
+	struct pci_dev *dev = PDE_DATA(ino);
 	int pos = *ppos;
-	int size = dp->size;
+	int size = dev->cfg_size;
 	int cnt;
 
 	if (pos >= size)
@@ -200,7 +197,7 @@
 	pci_config_pm_runtime_put(dev);
 
 	*ppos = pos;
-	i_size_write(ino, dp->size);
+	i_size_write(ino, dev->cfg_size);
 	return nbytes;
 }
 
@@ -212,8 +209,7 @@
 static long proc_bus_pci_ioctl(struct file *file, unsigned int cmd,
 			       unsigned long arg)
 {
-	const struct proc_dir_entry *dp = PDE(file_inode(file));
-	struct pci_dev *dev = dp->data;
+	struct pci_dev *dev = PDE_DATA(file_inode(file));
 #ifdef HAVE_PCI_MMAP
 	struct pci_filp_private *fpriv = file->private_data;
 #endif /* HAVE_PCI_MMAP */
@@ -253,9 +249,7 @@
 #ifdef HAVE_PCI_MMAP
 static int proc_bus_pci_mmap(struct file *file, struct vm_area_struct *vma)
 {
-	struct inode *inode = file_inode(file);
-	const struct proc_dir_entry *dp = PDE(inode);
-	struct pci_dev *dev = dp->data;
+	struct pci_dev *dev = PDE_DATA(file_inode(file));
 	struct pci_filp_private *fpriv = file->private_data;
 	int i, ret;
 
@@ -425,7 +419,7 @@
 			     &proc_bus_pci_operations, dev);
 	if (!e)
 		return -ENOMEM;
-	e->size = dev->cfg_size;
+	proc_set_size(e, dev->cfg_size);
 	dev->procent = e;
 
 	return 0;
@@ -433,20 +427,14 @@
 
 int pci_proc_detach_device(struct pci_dev *dev)
 {
-	struct proc_dir_entry *e;
-
-	if ((e = dev->procent)) {
-		remove_proc_entry(e->name, dev->bus->procdir);
-		dev->procent = NULL;
-	}
+	proc_remove(dev->procent);
+	dev->procent = NULL;
 	return 0;
 }
 
 int pci_proc_detach_bus(struct pci_bus* bus)
 {
-	struct proc_dir_entry *de = bus->procdir;
-	if (de)
-		remove_proc_entry(de->name, proc_bus_pci_dir);
+	proc_remove(bus->procdir);
 	return 0;
 }
 
diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c
index edec135..54d31c0 100644
--- a/drivers/platform/x86/thinkpad_acpi.c
+++ b/drivers/platform/x86/thinkpad_acpi.c
@@ -844,14 +844,14 @@
 
 static int dispatch_proc_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, dispatch_proc_show, PDE(inode)->data);
+	return single_open(file, dispatch_proc_show, PDE_DATA(inode));
 }
 
 static ssize_t dispatch_proc_write(struct file *file,
 			const char __user *userbuf,
 			size_t count, loff_t *pos)
 {
-	struct ibm_struct *ibm = PDE(file_inode(file))->data;
+	struct ibm_struct *ibm = PDE_DATA(file_inode(file));
 	char *kernbuf;
 	int ret;
 
diff --git a/drivers/platform/x86/toshiba_acpi.c b/drivers/platform/x86/toshiba_acpi.c
index 242abac..eb3467e 100644
--- a/drivers/platform/x86/toshiba_acpi.c
+++ b/drivers/platform/x86/toshiba_acpi.c
@@ -553,7 +553,7 @@
 
 static int lcd_proc_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, lcd_proc_show, PDE(inode)->data);
+	return single_open(file, lcd_proc_show, PDE_DATA(inode));
 }
 
 static int set_lcd_brightness(struct toshiba_acpi_dev *dev, int value)
@@ -583,7 +583,7 @@
 static ssize_t lcd_proc_write(struct file *file, const char __user *buf,
 			      size_t count, loff_t *pos)
 {
-	struct toshiba_acpi_dev *dev = PDE(file_inode(file))->data;
+	struct toshiba_acpi_dev *dev = PDE_DATA(file_inode(file));
 	char cmd[42];
 	size_t len;
 	int value;
@@ -644,13 +644,13 @@
 
 static int video_proc_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, video_proc_show, PDE(inode)->data);
+	return single_open(file, video_proc_show, PDE_DATA(inode));
 }
 
 static ssize_t video_proc_write(struct file *file, const char __user *buf,
 				size_t count, loff_t *pos)
 {
-	struct toshiba_acpi_dev *dev = PDE(file_inode(file))->data;
+	struct toshiba_acpi_dev *dev = PDE_DATA(file_inode(file));
 	char *cmd, *buffer;
 	int ret;
 	int value;
@@ -744,13 +744,13 @@
 
 static int fan_proc_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, fan_proc_show, PDE(inode)->data);
+	return single_open(file, fan_proc_show, PDE_DATA(inode));
 }
 
 static ssize_t fan_proc_write(struct file *file, const char __user *buf,
 			      size_t count, loff_t *pos)
 {
-	struct toshiba_acpi_dev *dev = PDE(file_inode(file))->data;
+	struct toshiba_acpi_dev *dev = PDE_DATA(file_inode(file));
 	char cmd[42];
 	size_t len;
 	int value;
@@ -816,13 +816,13 @@
 
 static int keys_proc_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, keys_proc_show, PDE(inode)->data);
+	return single_open(file, keys_proc_show, PDE_DATA(inode));
 }
 
 static ssize_t keys_proc_write(struct file *file, const char __user *buf,
 			       size_t count, loff_t *pos)
 {
-	struct toshiba_acpi_dev *dev = PDE(file_inode(file))->data;
+	struct toshiba_acpi_dev *dev = PDE_DATA(file_inode(file));
 	char cmd[42];
 	size_t len;
 	int value;
@@ -859,7 +859,7 @@
 
 static int version_proc_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, version_proc_show, PDE(inode)->data);
+	return single_open(file, version_proc_show, PDE_DATA(inode));
 }
 
 static const struct file_operations version_proc_fops = {
diff --git a/drivers/pnp/isapnp/proc.c b/drivers/pnp/isapnp/proc.c
index 65f735a..2365ef3 100644
--- a/drivers/pnp/isapnp/proc.c
+++ b/drivers/pnp/isapnp/proc.c
@@ -55,9 +55,7 @@
 static ssize_t isapnp_proc_bus_read(struct file *file, char __user * buf,
 				    size_t nbytes, loff_t * ppos)
 {
-	struct inode *ino = file_inode(file);
-	struct proc_dir_entry *dp = PDE(ino);
-	struct pnp_dev *dev = dp->data;
+	struct pnp_dev *dev = PDE_DATA(file_inode(file));
 	int pos = *ppos;
 	int cnt, size = 256;
 
@@ -107,7 +105,7 @@
 			&isapnp_proc_bus_file_operations, dev);
 	if (!e)
 		return -ENOMEM;
-	e->size = 256;
+	proc_set_size(e, 256);
 	return 0;
 }
 
diff --git a/drivers/pnp/pnpbios/proc.c b/drivers/pnp/pnpbios/proc.c
index 1c03ee8..c212db0 100644
--- a/drivers/pnp/pnpbios/proc.c
+++ b/drivers/pnp/pnpbios/proc.c
@@ -237,13 +237,13 @@
 
 static int pnpbios_proc_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, pnpbios_proc_show, PDE(inode)->data);
+	return single_open(file, pnpbios_proc_show, PDE_DATA(inode));
 }
 
 static ssize_t pnpbios_proc_write(struct file *file, const char __user *buf,
 				  size_t count, loff_t *pos)
 {
-	void *data = PDE(file_inode(file))->data;
+	void *data = PDE_DATA(file_inode(file));
 	struct pnp_bios_node *node;
 	int boot = (long)data >> 8;
 	u8 nodenum = (long)data;
diff --git a/drivers/pps/clients/pps_parport.c b/drivers/pps/clients/pps_parport.c
index e1b4705..38a8bbe 100644
--- a/drivers/pps/clients/pps_parport.c
+++ b/drivers/pps/clients/pps_parport.c
@@ -32,6 +32,7 @@
 #include <linux/init.h>
 #include <linux/irqnr.h>
 #include <linux/time.h>
+#include <linux/slab.h>
 #include <linux/parport.h>
 #include <linux/pps_kernel.h>
 
diff --git a/drivers/rtc/rtc-proc.c b/drivers/rtc/rtc-proc.c
index e96236a..ffa69e1 100644
--- a/drivers/rtc/rtc-proc.c
+++ b/drivers/rtc/rtc-proc.c
@@ -110,7 +110,7 @@
 static int rtc_proc_open(struct inode *inode, struct file *file)
 {
 	int ret;
-	struct rtc_device *rtc = PDE(inode)->data;
+	struct rtc_device *rtc = PDE_DATA(inode);
 
 	if (!try_module_get(THIS_MODULE))
 		return -ENODEV;
diff --git a/drivers/s390/cio/qdio_debug.c b/drivers/s390/cio/qdio_debug.c
index ccaae9d..4221b02 100644
--- a/drivers/s390/cio/qdio_debug.c
+++ b/drivers/s390/cio/qdio_debug.c
@@ -224,7 +224,7 @@
 			   file_inode(filp)->i_private);
 }
 
-static struct file_operations debugfs_perf_fops = {
+static const struct file_operations debugfs_perf_fops = {
 	.owner	 = THIS_MODULE,
 	.open	 = qperf_seq_open,
 	.read	 = seq_read,
diff --git a/drivers/scsi/BusLogic.c b/drivers/scsi/BusLogic.c
index d7ca247..344d875 100644
--- a/drivers/scsi/BusLogic.c
+++ b/drivers/scsi/BusLogic.c
@@ -3201,26 +3201,30 @@
   BugLogic_ProcDirectoryInfo implements /proc/scsi/BusLogic/<N>.
 */
 
-static int BusLogic_ProcDirectoryInfo(struct Scsi_Host *shost, char *ProcBuffer, char **StartPointer, off_t Offset, int BytesAvailable, int WriteFlag)
+static int BusLogic_write_info(struct Scsi_Host *shost, char *ProcBuffer, int BytesAvailable)
 {
 	struct BusLogic_HostAdapter *HostAdapter = (struct BusLogic_HostAdapter *) shost->hostdata;
 	struct BusLogic_TargetStatistics *TargetStatistics;
-	int TargetID, Length;
-	char *Buffer;
 
 	TargetStatistics = HostAdapter->TargetStatistics;
-	if (WriteFlag) {
-		HostAdapter->ExternalHostAdapterResets = 0;
-		HostAdapter->HostAdapterInternalErrors = 0;
-		memset(TargetStatistics, 0, BusLogic_MaxTargetDevices * sizeof(struct BusLogic_TargetStatistics));
-		return 0;
-	}
-	Buffer = HostAdapter->MessageBuffer;
-	Length = HostAdapter->MessageBufferLength;
-	Length += sprintf(&Buffer[Length], "\n\
+	HostAdapter->ExternalHostAdapterResets = 0;
+	HostAdapter->HostAdapterInternalErrors = 0;
+	memset(TargetStatistics, 0, BusLogic_MaxTargetDevices * sizeof(struct BusLogic_TargetStatistics));
+	return 0;
+}
+
+static int BusLogic_show_info(struct seq_file *m, struct Scsi_Host *shost)
+{
+	struct BusLogic_HostAdapter *HostAdapter = (struct BusLogic_HostAdapter *) shost->hostdata;
+	struct BusLogic_TargetStatistics *TargetStatistics;
+	int TargetID;
+
+	TargetStatistics = HostAdapter->TargetStatistics;
+	seq_write(m, HostAdapter->MessageBuffer, HostAdapter->MessageBufferLength);
+	seq_printf(m, "\n\
 Current Driver Queue Depth:	%d\n\
 Currently Allocated CCBs:	%d\n", HostAdapter->DriverQueueDepth, HostAdapter->AllocatedCCBs);
-	Length += sprintf(&Buffer[Length], "\n\n\
+	seq_printf(m, "\n\n\
 			   DATA TRANSFER STATISTICS\n\
 \n\
 Target	Tagged Queuing	Queue Depth  Active  Attempted	Completed\n\
@@ -3229,66 +3233,62 @@
 		struct BusLogic_TargetFlags *TargetFlags = &HostAdapter->TargetFlags[TargetID];
 		if (!TargetFlags->TargetExists)
 			continue;
-		Length += sprintf(&Buffer[Length], "  %2d	%s", TargetID, (TargetFlags->TaggedQueuingSupported ? (TargetFlags->TaggedQueuingActive ? "    Active" : (HostAdapter->TaggedQueuingPermitted & (1 << TargetID)
+		seq_printf(m, "  %2d	%s", TargetID, (TargetFlags->TaggedQueuingSupported ? (TargetFlags->TaggedQueuingActive ? "    Active" : (HostAdapter->TaggedQueuingPermitted & (1 << TargetID)
 																				    ? "  Permitted" : "   Disabled"))
 									  : "Not Supported"));
-		Length += sprintf(&Buffer[Length],
+		seq_printf(m,
 				  "	    %3d       %3u    %9u	%9u\n", HostAdapter->QueueDepth[TargetID], HostAdapter->ActiveCommands[TargetID], TargetStatistics[TargetID].CommandsAttempted, TargetStatistics[TargetID].CommandsCompleted);
 	}
-	Length += sprintf(&Buffer[Length], "\n\
+	seq_printf(m, "\n\
 Target  Read Commands  Write Commands   Total Bytes Read    Total Bytes Written\n\
 ======  =============  ==============  ===================  ===================\n");
 	for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++) {
 		struct BusLogic_TargetFlags *TargetFlags = &HostAdapter->TargetFlags[TargetID];
 		if (!TargetFlags->TargetExists)
 			continue;
-		Length += sprintf(&Buffer[Length], "  %2d	  %9u	 %9u", TargetID, TargetStatistics[TargetID].ReadCommands, TargetStatistics[TargetID].WriteCommands);
+		seq_printf(m, "  %2d	  %9u	 %9u", TargetID, TargetStatistics[TargetID].ReadCommands, TargetStatistics[TargetID].WriteCommands);
 		if (TargetStatistics[TargetID].TotalBytesRead.Billions > 0)
-			Length += sprintf(&Buffer[Length], "     %9u%09u", TargetStatistics[TargetID].TotalBytesRead.Billions, TargetStatistics[TargetID].TotalBytesRead.Units);
+			seq_printf(m, "     %9u%09u", TargetStatistics[TargetID].TotalBytesRead.Billions, TargetStatistics[TargetID].TotalBytesRead.Units);
 		else
-			Length += sprintf(&Buffer[Length], "		%9u", TargetStatistics[TargetID].TotalBytesRead.Units);
+			seq_printf(m, "		%9u", TargetStatistics[TargetID].TotalBytesRead.Units);
 		if (TargetStatistics[TargetID].TotalBytesWritten.Billions > 0)
-			Length += sprintf(&Buffer[Length], "   %9u%09u\n", TargetStatistics[TargetID].TotalBytesWritten.Billions, TargetStatistics[TargetID].TotalBytesWritten.Units);
+			seq_printf(m, "   %9u%09u\n", TargetStatistics[TargetID].TotalBytesWritten.Billions, TargetStatistics[TargetID].TotalBytesWritten.Units);
 		else
-			Length += sprintf(&Buffer[Length], "	     %9u\n", TargetStatistics[TargetID].TotalBytesWritten.Units);
+			seq_printf(m, "	     %9u\n", TargetStatistics[TargetID].TotalBytesWritten.Units);
 	}
-	Length += sprintf(&Buffer[Length], "\n\
+	seq_printf(m, "\n\
 Target  Command    0-1KB      1-2KB      2-4KB      4-8KB     8-16KB\n\
 ======  =======  =========  =========  =========  =========  =========\n");
 	for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++) {
 		struct BusLogic_TargetFlags *TargetFlags = &HostAdapter->TargetFlags[TargetID];
 		if (!TargetFlags->TargetExists)
 			continue;
-		Length +=
-		    sprintf(&Buffer[Length],
+		seq_printf(m,
 			    "  %2d	 Read	 %9u  %9u  %9u  %9u  %9u\n", TargetID,
 			    TargetStatistics[TargetID].ReadCommandSizeBuckets[0],
 			    TargetStatistics[TargetID].ReadCommandSizeBuckets[1], TargetStatistics[TargetID].ReadCommandSizeBuckets[2], TargetStatistics[TargetID].ReadCommandSizeBuckets[3], TargetStatistics[TargetID].ReadCommandSizeBuckets[4]);
-		Length +=
-		    sprintf(&Buffer[Length],
+		seq_printf(m,
 			    "  %2d	 Write	 %9u  %9u  %9u  %9u  %9u\n", TargetID,
 			    TargetStatistics[TargetID].WriteCommandSizeBuckets[0],
 			    TargetStatistics[TargetID].WriteCommandSizeBuckets[1], TargetStatistics[TargetID].WriteCommandSizeBuckets[2], TargetStatistics[TargetID].WriteCommandSizeBuckets[3], TargetStatistics[TargetID].WriteCommandSizeBuckets[4]);
 	}
-	Length += sprintf(&Buffer[Length], "\n\
+	seq_printf(m, "\n\
 Target  Command   16-32KB    32-64KB   64-128KB   128-256KB   256KB+\n\
 ======  =======  =========  =========  =========  =========  =========\n");
 	for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++) {
 		struct BusLogic_TargetFlags *TargetFlags = &HostAdapter->TargetFlags[TargetID];
 		if (!TargetFlags->TargetExists)
 			continue;
-		Length +=
-		    sprintf(&Buffer[Length],
+		seq_printf(m,
 			    "  %2d	 Read	 %9u  %9u  %9u  %9u  %9u\n", TargetID,
 			    TargetStatistics[TargetID].ReadCommandSizeBuckets[5],
 			    TargetStatistics[TargetID].ReadCommandSizeBuckets[6], TargetStatistics[TargetID].ReadCommandSizeBuckets[7], TargetStatistics[TargetID].ReadCommandSizeBuckets[8], TargetStatistics[TargetID].ReadCommandSizeBuckets[9]);
-		Length +=
-		    sprintf(&Buffer[Length],
+		seq_printf(m,
 			    "  %2d	 Write	 %9u  %9u  %9u  %9u  %9u\n", TargetID,
 			    TargetStatistics[TargetID].WriteCommandSizeBuckets[5],
 			    TargetStatistics[TargetID].WriteCommandSizeBuckets[6], TargetStatistics[TargetID].WriteCommandSizeBuckets[7], TargetStatistics[TargetID].WriteCommandSizeBuckets[8], TargetStatistics[TargetID].WriteCommandSizeBuckets[9]);
 	}
-	Length += sprintf(&Buffer[Length], "\n\n\
+	seq_printf(m, "\n\n\
 			   ERROR RECOVERY STATISTICS\n\
 \n\
 	  Command Aborts      Bus Device Resets	  Host Adapter Resets\n\
@@ -3299,20 +3299,12 @@
 		struct BusLogic_TargetFlags *TargetFlags = &HostAdapter->TargetFlags[TargetID];
 		if (!TargetFlags->TargetExists)
 			continue;
-		Length += sprintf(&Buffer[Length], "\
+		seq_printf(m, "\
   %2d	 %5d %5d %5d    %5d %5d %5d	   %5d %5d %5d\n", TargetID, TargetStatistics[TargetID].CommandAbortsRequested, TargetStatistics[TargetID].CommandAbortsAttempted, TargetStatistics[TargetID].CommandAbortsCompleted, TargetStatistics[TargetID].BusDeviceResetsRequested, TargetStatistics[TargetID].BusDeviceResetsAttempted, TargetStatistics[TargetID].BusDeviceResetsCompleted, TargetStatistics[TargetID].HostAdapterResetsRequested, TargetStatistics[TargetID].HostAdapterResetsAttempted, TargetStatistics[TargetID].HostAdapterResetsCompleted);
 	}
-	Length += sprintf(&Buffer[Length], "\nExternal Host Adapter Resets: %d\n", HostAdapter->ExternalHostAdapterResets);
-	Length += sprintf(&Buffer[Length], "Host Adapter Internal Errors: %d\n", HostAdapter->HostAdapterInternalErrors);
-	if (Length >= BusLogic_MessageBufferSize)
-		BusLogic_Error("Message Buffer length %d exceeds size %d\n", HostAdapter, Length, BusLogic_MessageBufferSize);
-	if ((Length -= Offset) <= 0)
-		return 0;
-	if (Length >= BytesAvailable)
-		Length = BytesAvailable;
-	memcpy(ProcBuffer, HostAdapter->MessageBuffer + Offset, Length);
-	*StartPointer = ProcBuffer;
-	return Length;
+	seq_printf(m, "\nExternal Host Adapter Resets: %d\n", HostAdapter->ExternalHostAdapterResets);
+	seq_printf(m, "Host Adapter Internal Errors: %d\n", HostAdapter->HostAdapterInternalErrors);
+	return 0;
 }
 
 
@@ -3566,7 +3558,8 @@
 static struct scsi_host_template Bus_Logic_template = {
 	.module = THIS_MODULE,
 	.proc_name = "BusLogic",
-	.proc_info = BusLogic_ProcDirectoryInfo,
+	.write_info = BusLogic_write_info,
+	.show_info = BusLogic_show_info,
 	.name = "BusLogic",
 	.info = BusLogic_DriverInfo,
 	.queuecommand = BusLogic_QueueCommand,
diff --git a/drivers/scsi/BusLogic.h b/drivers/scsi/BusLogic.h
index 649fcb3..6c6c13c 100644
--- a/drivers/scsi/BusLogic.h
+++ b/drivers/scsi/BusLogic.h
@@ -1321,7 +1321,6 @@
 static const char *BusLogic_DriverInfo(struct Scsi_Host *);
 static int BusLogic_QueueCommand(struct Scsi_Host *h, struct scsi_cmnd *);
 static int BusLogic_BIOSDiskParameters(struct scsi_device *, struct block_device *, sector_t, int *);
-static int BusLogic_ProcDirectoryInfo(struct Scsi_Host *, char *, char **, off_t, int, int);
 static int BusLogic_SlaveConfigure(struct scsi_device *);
 static void BusLogic_QueueCompletedCCB(struct BusLogic_CCB *);
 static irqreturn_t BusLogic_InterruptHandler(int, void *);
diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c
index 450353e..1e9d6ad 100644
--- a/drivers/scsi/NCR5380.c
+++ b/drivers/scsi/NCR5380.c
@@ -695,33 +695,35 @@
  * Return the number of bytes read from or written
  */
 
-#undef SPRINTF
-#define SPRINTF(args...) do { if(pos < buffer + length-80) pos += sprintf(pos, ## args); } while(0)
-static
-char *lprint_Scsi_Cmnd(Scsi_Cmnd * cmd, char *pos, char *buffer, int length);
-static
-char *lprint_command(unsigned char *cmd, char *pos, char *buffer, int len);
-static
-char *lprint_opcode(int opcode, char *pos, char *buffer, int length);
-
-static int __maybe_unused NCR5380_proc_info(struct Scsi_Host *instance,
-	char *buffer, char **start, off_t offset, int length, int inout)
+static int __maybe_unused NCR5380_write_info(struct Scsi_Host *instance,
+	char *buffer, int length)
 {
-	char *pos = buffer;
+#ifdef DTC_PUBLIC_RELEASE
+	dtc_wmaxi = dtc_maxi = 0;
+#endif
+#ifdef PAS16_PUBLIC_RELEASE
+	pas_wmaxi = pas_maxi = 0;
+#endif
+	return (-ENOSYS);	/* Currently this is a no-op */
+}
+
+#undef SPRINTF
+#define SPRINTF(args...) seq_printf(m, ## args)
+static
+void lprint_Scsi_Cmnd(Scsi_Cmnd * cmd, struct seq_file *m);
+static
+void lprint_command(unsigned char *cmd, struct seq_file *m);
+static
+void lprint_opcode(int opcode, struct seq_file *m);
+
+static int __maybe_unused NCR5380_show_info(struct seq_file *m,
+	struct Scsi_Host *instance)
+{
 	struct NCR5380_hostdata *hostdata;
 	Scsi_Cmnd *ptr;
 
 	hostdata = (struct NCR5380_hostdata *) instance->hostdata;
 
-	if (inout) {		/* Has data been written to the file ? */
-#ifdef DTC_PUBLIC_RELEASE
-		dtc_wmaxi = dtc_maxi = 0;
-#endif
-#ifdef PAS16_PUBLIC_RELEASE
-		pas_wmaxi = pas_maxi = 0;
-#endif
-		return (-ENOSYS);	/* Currently this is a no-op */
-	}
 	SPRINTF("NCR5380 core release=%d.   ", NCR5380_PUBLIC_RELEASE);
 	if (((struct NCR5380_hostdata *) instance->hostdata)->flags & FLAG_NCR53C400)
 		SPRINTF("ncr53c400 release=%d.  ", NCR53C400_PUBLIC_RELEASE);
@@ -755,46 +757,37 @@
 	if (!hostdata->connected)
 		SPRINTF("scsi%d: no currently connected command\n", instance->host_no);
 	else
-		pos = lprint_Scsi_Cmnd((Scsi_Cmnd *) hostdata->connected, pos, buffer, length);
+		lprint_Scsi_Cmnd((Scsi_Cmnd *) hostdata->connected, m);
 	SPRINTF("scsi%d: issue_queue\n", instance->host_no);
 	for (ptr = (Scsi_Cmnd *) hostdata->issue_queue; ptr; ptr = (Scsi_Cmnd *) ptr->host_scribble)
-		pos = lprint_Scsi_Cmnd(ptr, pos, buffer, length);
+		lprint_Scsi_Cmnd(ptr, m);
 
 	SPRINTF("scsi%d: disconnected_queue\n", instance->host_no);
 	for (ptr = (Scsi_Cmnd *) hostdata->disconnected_queue; ptr; ptr = (Scsi_Cmnd *) ptr->host_scribble)
-		pos = lprint_Scsi_Cmnd(ptr, pos, buffer, length);
+		lprint_Scsi_Cmnd(ptr, m);
 	spin_unlock_irq(instance->host_lock);
-	
-	*start = buffer;
-	if (pos - buffer < offset)
-		return 0;
-	else if (pos - buffer - offset < length)
-		return pos - buffer - offset;
-	return length;
+	return 0;
 }
 
-static char *lprint_Scsi_Cmnd(Scsi_Cmnd * cmd, char *pos, char *buffer, int length)
+static void lprint_Scsi_Cmnd(Scsi_Cmnd * cmd, struct seq_file *m)
 {
 	SPRINTF("scsi%d : destination target %d, lun %d\n", cmd->device->host->host_no, cmd->device->id, cmd->device->lun);
 	SPRINTF("        command = ");
-	pos = lprint_command(cmd->cmnd, pos, buffer, length);
-	return (pos);
+	lprint_command(cmd->cmnd, m);
 }
 
-static char *lprint_command(unsigned char *command, char *pos, char *buffer, int length)
+static void lprint_command(unsigned char *command, struct seq_file *m)
 {
 	int i, s;
-	pos = lprint_opcode(command[0], pos, buffer, length);
+	lprint_opcode(command[0], m);
 	for (i = 1, s = COMMAND_SIZE(command[0]); i < s; ++i)
 		SPRINTF("%02x ", command[i]);
 	SPRINTF("\n");
-	return (pos);
 }
 
-static char *lprint_opcode(int opcode, char *pos, char *buffer, int length)
+static void lprint_opcode(int opcode, struct seq_file *m)
 {
 	SPRINTF("%2d (0x%02x)", opcode, opcode);
-	return (pos);
 }
 
 
diff --git a/drivers/scsi/NCR5380.h b/drivers/scsi/NCR5380.h
index fd40a32..14964d0 100644
--- a/drivers/scsi/NCR5380.h
+++ b/drivers/scsi/NCR5380.h
@@ -314,8 +314,10 @@
 static int NCR5380_abort(Scsi_Cmnd * cmd);
 static int NCR5380_bus_reset(Scsi_Cmnd * cmd);
 static int NCR5380_queue_command(struct Scsi_Host *, struct scsi_cmnd *);
-static int __maybe_unused NCR5380_proc_info(struct Scsi_Host *instance,
-	char *buffer, char **start, off_t offset, int length, int inout);
+static int __maybe_unused NCR5380_show_info(struct seq_file *,
+	struct Scsi_Host *);
+static int __maybe_unused NCR5380_write_info(struct Scsi_Host *instance,
+	char *buffer, int length);
 
 static void NCR5380_reselect(struct Scsi_Host *instance);
 static int NCR5380_select(struct Scsi_Host *instance, Scsi_Cmnd * cmd, int tag);
diff --git a/drivers/scsi/a2091.c b/drivers/scsi/a2091.c
index 3e09aa2..30fa38a 100644
--- a/drivers/scsi/a2091.c
+++ b/drivers/scsi/a2091.c
@@ -166,7 +166,8 @@
 static struct scsi_host_template a2091_scsi_template = {
 	.module			= THIS_MODULE,
 	.name			= "Commodore A2091/A590 SCSI",
-	.proc_info		= wd33c93_proc_info,
+	.show_info		= wd33c93_show_info,
+	.write_info		= wd33c93_write_info,
 	.proc_name		= "A2901",
 	.queuecommand		= wd33c93_queuecommand,
 	.eh_abort_handler	= wd33c93_abort,
diff --git a/drivers/scsi/a3000.c b/drivers/scsi/a3000.c
index e29fe0e..c487916 100644
--- a/drivers/scsi/a3000.c
+++ b/drivers/scsi/a3000.c
@@ -181,7 +181,8 @@
 static struct scsi_host_template amiga_a3000_scsi_template = {
 	.module			= THIS_MODULE,
 	.name			= "Amiga 3000 built-in SCSI",
-	.proc_info		= wd33c93_proc_info,
+	.show_info		= wd33c93_show_info,
+	.write_info		= wd33c93_write_info,
 	.proc_name		= "A3000",
 	.queuecommand		= wd33c93_queuecommand,
 	.eh_abort_handler	= wd33c93_abort,
diff --git a/drivers/scsi/advansys.c b/drivers/scsi/advansys.c
index dcfaee6..c67e401 100644
--- a/drivers/scsi/advansys.c
+++ b/drivers/scsi/advansys.c
@@ -2178,22 +2178,6 @@
 
 #define ASC_INFO_SIZE           128	/* advansys_info() line size */
 
-#ifdef CONFIG_PROC_FS
-/* /proc/scsi/advansys/[0...] related definitions */
-#define ASC_PRTBUF_SIZE         2048
-#define ASC_PRTLINE_SIZE        160
-
-#define ASC_PRT_NEXT() \
-    if (cp) { \
-        totlen += len; \
-        leftlen -= len; \
-        if (leftlen == 0) { \
-            return totlen; \
-        } \
-        cp += len; \
-    }
-#endif /* CONFIG_PROC_FS */
-
 /* Asc Library return codes */
 #define ASC_TRUE        1
 #define ASC_FALSE       0
@@ -2384,7 +2368,6 @@
 	} eep_config;
 	ulong last_reset;	/* Saved last reset time */
 	/* /proc/scsi/advansys/[0...] */
-	char *prtbuf;		/* /proc print buffer */
 #ifdef ADVANSYS_STATS
 	struct asc_stats asc_stats;	/* Board statistics */
 #endif				/* ADVANSYS_STATS */
@@ -2875,64 +2858,21 @@
 }
 
 #ifdef CONFIG_PROC_FS
-/*
- * asc_prt_line()
- *
- * If 'cp' is NULL print to the console, otherwise print to a buffer.
- *
- * Return 0 if printing to the console, otherwise return the number of
- * bytes written to the buffer.
- *
- * Note: If any single line is greater than ASC_PRTLINE_SIZE bytes the stack
- * will be corrupted. 's[]' is defined to be ASC_PRTLINE_SIZE bytes.
- */
-static int asc_prt_line(char *buf, int buflen, char *fmt, ...)
-{
-	va_list args;
-	int ret;
-	char s[ASC_PRTLINE_SIZE];
-
-	va_start(args, fmt);
-	ret = vsprintf(s, fmt, args);
-	BUG_ON(ret >= ASC_PRTLINE_SIZE);
-	if (buf == NULL) {
-		(void)printk(s);
-		ret = 0;
-	} else {
-		ret = min(buflen, ret);
-		memcpy(buf, s, ret);
-	}
-	va_end(args);
-	return ret;
-}
 
 /*
  * asc_prt_board_devices()
  *
  * Print driver information for devices attached to the board.
- *
- * Note: no single line should be greater than ASC_PRTLINE_SIZE,
- * cf. asc_prt_line().
- *
- * Return the number of characters copied into 'cp'. No more than
- * 'cplen' characters will be copied to 'cp'.
  */
-static int asc_prt_board_devices(struct Scsi_Host *shost, char *cp, int cplen)
+static void asc_prt_board_devices(struct seq_file *m, struct Scsi_Host *shost)
 {
 	struct asc_board *boardp = shost_priv(shost);
-	int leftlen;
-	int totlen;
-	int len;
 	int chip_scsi_id;
 	int i;
 
-	leftlen = cplen;
-	totlen = len = 0;
-
-	len = asc_prt_line(cp, leftlen,
-			   "\nDevice Information for AdvanSys SCSI Host %d:\n",
-			   shost->host_no);
-	ASC_PRT_NEXT();
+	seq_printf(m,
+		   "\nDevice Information for AdvanSys SCSI Host %d:\n",
+		   shost->host_no);
 
 	if (ASC_NARROW_BOARD(boardp)) {
 		chip_scsi_id = boardp->dvc_cfg.asc_dvc_cfg.chip_scsi_id;
@@ -2940,60 +2880,42 @@
 		chip_scsi_id = boardp->dvc_var.adv_dvc_var.chip_scsi_id;
 	}
 
-	len = asc_prt_line(cp, leftlen, "Target IDs Detected:");
-	ASC_PRT_NEXT();
+	seq_printf(m, "Target IDs Detected:");
 	for (i = 0; i <= ADV_MAX_TID; i++) {
-		if (boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) {
-			len = asc_prt_line(cp, leftlen, " %X,", i);
-			ASC_PRT_NEXT();
-		}
+		if (boardp->init_tidmask & ADV_TID_TO_TIDMASK(i))
+			seq_printf(m, " %X,", i);
 	}
-	len = asc_prt_line(cp, leftlen, " (%X=Host Adapter)\n", chip_scsi_id);
-	ASC_PRT_NEXT();
-
-	return totlen;
+	seq_printf(m, " (%X=Host Adapter)\n", chip_scsi_id);
 }
 
 /*
  * Display Wide Board BIOS Information.
  */
-static int asc_prt_adv_bios(struct Scsi_Host *shost, char *cp, int cplen)
+static void asc_prt_adv_bios(struct seq_file *m, struct Scsi_Host *shost)
 {
 	struct asc_board *boardp = shost_priv(shost);
-	int leftlen;
-	int totlen;
-	int len;
 	ushort major, minor, letter;
 
-	leftlen = cplen;
-	totlen = len = 0;
-
-	len = asc_prt_line(cp, leftlen, "\nROM BIOS Version: ");
-	ASC_PRT_NEXT();
+	seq_printf(m, "\nROM BIOS Version: ");
 
 	/*
 	 * If the BIOS saved a valid signature, then fill in
 	 * the BIOS code segment base address.
 	 */
 	if (boardp->bios_signature != 0x55AA) {
-		len = asc_prt_line(cp, leftlen, "Disabled or Pre-3.1\n");
-		ASC_PRT_NEXT();
-		len = asc_prt_line(cp, leftlen,
-				   "BIOS either disabled or Pre-3.1. If it is pre-3.1, then a newer version\n");
-		ASC_PRT_NEXT();
-		len = asc_prt_line(cp, leftlen,
-				   "can be found at the ConnectCom FTP site: ftp://ftp.connectcom.net/pub\n");
-		ASC_PRT_NEXT();
+		seq_printf(m, "Disabled or Pre-3.1\n");
+		seq_printf(m,
+			  "BIOS either disabled or Pre-3.1. If it is pre-3.1, then a newer version\n");
+		seq_printf(m,
+			  "can be found at the ConnectCom FTP site: ftp://ftp.connectcom.net/pub\n");
 	} else {
 		major = (boardp->bios_version >> 12) & 0xF;
 		minor = (boardp->bios_version >> 8) & 0xF;
 		letter = (boardp->bios_version & 0xFF);
 
-		len = asc_prt_line(cp, leftlen, "%d.%d%c\n",
+		seq_printf(m, "%d.%d%c\n",
 				   major, minor,
 				   letter >= 26 ? '?' : letter + 'A');
-		ASC_PRT_NEXT();
-
 		/*
 		 * Current available ROM BIOS release is 3.1I for UW
 		 * and 3.2I for U2W. This code doesn't differentiate
@@ -3001,16 +2923,12 @@
 		 */
 		if (major < 3 || (major <= 3 && minor < 1) ||
 		    (major <= 3 && minor <= 1 && letter < ('I' - 'A'))) {
-			len = asc_prt_line(cp, leftlen,
-					   "Newer version of ROM BIOS is available at the ConnectCom FTP site:\n");
-			ASC_PRT_NEXT();
-			len = asc_prt_line(cp, leftlen,
-					   "ftp://ftp.connectcom.net/pub\n");
-			ASC_PRT_NEXT();
+			seq_printf(m,
+				   "Newer version of ROM BIOS is available at the ConnectCom FTP site:\n");
+			seq_printf(m,
+				   "ftp://ftp.connectcom.net/pub\n");
 		}
 	}
-
-	return totlen;
 }
 
 /*
@@ -3115,20 +3033,11 @@
  * asc_prt_asc_board_eeprom()
  *
  * Print board EEPROM configuration.
- *
- * Note: no single line should be greater than ASC_PRTLINE_SIZE,
- * cf. asc_prt_line().
- *
- * Return the number of characters copied into 'cp'. No more than
- * 'cplen' characters will be copied to 'cp'.
  */
-static int asc_prt_asc_board_eeprom(struct Scsi_Host *shost, char *cp, int cplen)
+static void asc_prt_asc_board_eeprom(struct seq_file *m, struct Scsi_Host *shost)
 {
 	struct asc_board *boardp = shost_priv(shost);
 	ASC_DVC_VAR *asc_dvc_varp;
-	int leftlen;
-	int totlen;
-	int len;
 	ASCEEP_CONFIG *ep;
 	int i;
 #ifdef CONFIG_ISA
@@ -3139,129 +3048,75 @@
 	asc_dvc_varp = &boardp->dvc_var.asc_dvc_var;
 	ep = &boardp->eep_config.asc_eep;
 
-	leftlen = cplen;
-	totlen = len = 0;
-
-	len = asc_prt_line(cp, leftlen,
-			   "\nEEPROM Settings for AdvanSys SCSI Host %d:\n",
-			   shost->host_no);
-	ASC_PRT_NEXT();
+	seq_printf(m,
+		   "\nEEPROM Settings for AdvanSys SCSI Host %d:\n",
+		   shost->host_no);
 
 	if (asc_get_eeprom_string((ushort *)&ep->adapter_info[0], serialstr)
-	    == ASC_TRUE) {
-		len =
-		    asc_prt_line(cp, leftlen, " Serial Number: %s\n",
-				 serialstr);
-		ASC_PRT_NEXT();
-	} else {
-		if (ep->adapter_info[5] == 0xBB) {
-			len = asc_prt_line(cp, leftlen,
-					   " Default Settings Used for EEPROM-less Adapter.\n");
-			ASC_PRT_NEXT();
-		} else {
-			len = asc_prt_line(cp, leftlen,
-					   " Serial Number Signature Not Present.\n");
-			ASC_PRT_NEXT();
-		}
-	}
+	    == ASC_TRUE)
+		seq_printf(m, " Serial Number: %s\n", serialstr);
+	else if (ep->adapter_info[5] == 0xBB)
+		seq_printf(m,
+			   " Default Settings Used for EEPROM-less Adapter.\n");
+	else
+		seq_printf(m,
+			   " Serial Number Signature Not Present.\n");
 
-	len = asc_prt_line(cp, leftlen,
-			   " Host SCSI ID: %u, Host Queue Size: %u, Device Queue Size: %u\n",
-			   ASC_EEP_GET_CHIP_ID(ep), ep->max_total_qng,
-			   ep->max_tag_qng);
-	ASC_PRT_NEXT();
+	seq_printf(m,
+		   " Host SCSI ID: %u, Host Queue Size: %u, Device Queue Size: %u\n",
+		   ASC_EEP_GET_CHIP_ID(ep), ep->max_total_qng,
+		   ep->max_tag_qng);
 
-	len = asc_prt_line(cp, leftlen,
-			   " cntl 0x%x, no_scam 0x%x\n", ep->cntl, ep->no_scam);
-	ASC_PRT_NEXT();
+	seq_printf(m,
+		   " cntl 0x%x, no_scam 0x%x\n", ep->cntl, ep->no_scam);
 
-	len = asc_prt_line(cp, leftlen, " Target ID:           ");
-	ASC_PRT_NEXT();
-	for (i = 0; i <= ASC_MAX_TID; i++) {
-		len = asc_prt_line(cp, leftlen, " %d", i);
-		ASC_PRT_NEXT();
-	}
-	len = asc_prt_line(cp, leftlen, "\n");
-	ASC_PRT_NEXT();
+	seq_printf(m, " Target ID:           ");
+	for (i = 0; i <= ASC_MAX_TID; i++)
+		seq_printf(m, " %d", i);
+	seq_printf(m, "\n");
 
-	len = asc_prt_line(cp, leftlen, " Disconnects:         ");
-	ASC_PRT_NEXT();
-	for (i = 0; i <= ASC_MAX_TID; i++) {
-		len = asc_prt_line(cp, leftlen, " %c",
-				   (ep->
-				    disc_enable & ADV_TID_TO_TIDMASK(i)) ? 'Y' :
-				   'N');
-		ASC_PRT_NEXT();
-	}
-	len = asc_prt_line(cp, leftlen, "\n");
-	ASC_PRT_NEXT();
+	seq_printf(m, " Disconnects:         ");
+	for (i = 0; i <= ASC_MAX_TID; i++)
+		seq_printf(m, " %c",
+			   (ep->disc_enable & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
+	seq_printf(m, "\n");
 
-	len = asc_prt_line(cp, leftlen, " Command Queuing:     ");
-	ASC_PRT_NEXT();
-	for (i = 0; i <= ASC_MAX_TID; i++) {
-		len = asc_prt_line(cp, leftlen, " %c",
-				   (ep->
-				    use_cmd_qng & ADV_TID_TO_TIDMASK(i)) ? 'Y' :
-				   'N');
-		ASC_PRT_NEXT();
-	}
-	len = asc_prt_line(cp, leftlen, "\n");
-	ASC_PRT_NEXT();
+	seq_printf(m, " Command Queuing:     ");
+	for (i = 0; i <= ASC_MAX_TID; i++)
+		seq_printf(m, " %c",
+			   (ep->use_cmd_qng & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
+	seq_printf(m, "\n");
 
-	len = asc_prt_line(cp, leftlen, " Start Motor:         ");
-	ASC_PRT_NEXT();
-	for (i = 0; i <= ASC_MAX_TID; i++) {
-		len = asc_prt_line(cp, leftlen, " %c",
-				   (ep->
-				    start_motor & ADV_TID_TO_TIDMASK(i)) ? 'Y' :
-				   'N');
-		ASC_PRT_NEXT();
-	}
-	len = asc_prt_line(cp, leftlen, "\n");
-	ASC_PRT_NEXT();
+	seq_printf(m, " Start Motor:         ");
+	for (i = 0; i <= ASC_MAX_TID; i++)
+		seq_printf(m, " %c",
+			   (ep->start_motor & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
+	seq_printf(m, "\n");
 
-	len = asc_prt_line(cp, leftlen, " Synchronous Transfer:");
-	ASC_PRT_NEXT();
-	for (i = 0; i <= ASC_MAX_TID; i++) {
-		len = asc_prt_line(cp, leftlen, " %c",
-				   (ep->
-				    init_sdtr & ADV_TID_TO_TIDMASK(i)) ? 'Y' :
-				   'N');
-		ASC_PRT_NEXT();
-	}
-	len = asc_prt_line(cp, leftlen, "\n");
-	ASC_PRT_NEXT();
+	seq_printf(m, " Synchronous Transfer:");
+	for (i = 0; i <= ASC_MAX_TID; i++)
+		seq_printf(m, " %c",
+			   (ep->init_sdtr & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
+	seq_printf(m, "\n");
 
 #ifdef CONFIG_ISA
 	if (asc_dvc_varp->bus_type & ASC_IS_ISA) {
-		len = asc_prt_line(cp, leftlen,
-				   " Host ISA DMA speed:   %d MB/S\n",
-				   isa_dma_speed[ASC_EEP_GET_DMA_SPD(ep)]);
-		ASC_PRT_NEXT();
+		seq_printf(m,
+			   " Host ISA DMA speed:   %d MB/S\n",
+			   isa_dma_speed[ASC_EEP_GET_DMA_SPD(ep)]);
 	}
 #endif /* CONFIG_ISA */
-
-	return totlen;
 }
 
 /*
  * asc_prt_adv_board_eeprom()
  *
  * Print board EEPROM configuration.
- *
- * Note: no single line should be greater than ASC_PRTLINE_SIZE,
- * cf. asc_prt_line().
- *
- * Return the number of characters copied into 'cp'. No more than
- * 'cplen' characters will be copied to 'cp'.
  */
-static int asc_prt_adv_board_eeprom(struct Scsi_Host *shost, char *cp, int cplen)
+static void asc_prt_adv_board_eeprom(struct seq_file *m, struct Scsi_Host *shost)
 {
 	struct asc_board *boardp = shost_priv(shost);
 	ADV_DVC_VAR *adv_dvc_varp;
-	int leftlen;
-	int totlen;
-	int len;
 	int i;
 	char *termstr;
 	uchar serialstr[13];
@@ -3281,13 +3136,9 @@
 		ep_38C1600 = &boardp->eep_config.adv_38C1600_eep;
 	}
 
-	leftlen = cplen;
-	totlen = len = 0;
-
-	len = asc_prt_line(cp, leftlen,
-			   "\nEEPROM Settings for AdvanSys SCSI Host %d:\n",
-			   shost->host_no);
-	ASC_PRT_NEXT();
+	seq_printf(m,
+		   "\nEEPROM Settings for AdvanSys SCSI Host %d:\n",
+		   shost->host_no);
 
 	if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
 		wordp = &ep_3550->serial_number_word1;
@@ -3297,38 +3148,28 @@
 		wordp = &ep_38C1600->serial_number_word1;
 	}
 
-	if (asc_get_eeprom_string(wordp, serialstr) == ASC_TRUE) {
-		len =
-		    asc_prt_line(cp, leftlen, " Serial Number: %s\n",
-				 serialstr);
-		ASC_PRT_NEXT();
-	} else {
-		len = asc_prt_line(cp, leftlen,
-				   " Serial Number Signature Not Present.\n");
-		ASC_PRT_NEXT();
-	}
+	if (asc_get_eeprom_string(wordp, serialstr) == ASC_TRUE)
+		seq_printf(m, " Serial Number: %s\n", serialstr);
+	else
+		seq_printf(m, " Serial Number Signature Not Present.\n");
 
-	if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
-		len = asc_prt_line(cp, leftlen,
-				   " Host SCSI ID: %u, Host Queue Size: %u, Device Queue Size: %u\n",
-				   ep_3550->adapter_scsi_id,
-				   ep_3550->max_host_qng, ep_3550->max_dvc_qng);
-		ASC_PRT_NEXT();
-	} else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
-		len = asc_prt_line(cp, leftlen,
-				   " Host SCSI ID: %u, Host Queue Size: %u, Device Queue Size: %u\n",
-				   ep_38C0800->adapter_scsi_id,
-				   ep_38C0800->max_host_qng,
-				   ep_38C0800->max_dvc_qng);
-		ASC_PRT_NEXT();
-	} else {
-		len = asc_prt_line(cp, leftlen,
-				   " Host SCSI ID: %u, Host Queue Size: %u, Device Queue Size: %u\n",
-				   ep_38C1600->adapter_scsi_id,
-				   ep_38C1600->max_host_qng,
-				   ep_38C1600->max_dvc_qng);
-		ASC_PRT_NEXT();
-	}
+	if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550)
+		seq_printf(m,
+			   " Host SCSI ID: %u, Host Queue Size: %u, Device Queue Size: %u\n",
+			   ep_3550->adapter_scsi_id,
+			   ep_3550->max_host_qng, ep_3550->max_dvc_qng);
+	else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800)
+		seq_printf(m,
+			   " Host SCSI ID: %u, Host Queue Size: %u, Device Queue Size: %u\n",
+			   ep_38C0800->adapter_scsi_id,
+			   ep_38C0800->max_host_qng,
+			   ep_38C0800->max_dvc_qng);
+	else
+		seq_printf(m,
+			   " Host SCSI ID: %u, Host Queue Size: %u, Device Queue Size: %u\n",
+			   ep_38C1600->adapter_scsi_id,
+			   ep_38C1600->max_host_qng,
+			   ep_38C1600->max_dvc_qng);
 	if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
 		word = ep_3550->termination;
 	} else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
@@ -3352,34 +3193,26 @@
 		break;
 	}
 
-	if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
-		len = asc_prt_line(cp, leftlen,
-				   " termination: %u (%s), bios_ctrl: 0x%x\n",
-				   ep_3550->termination, termstr,
-				   ep_3550->bios_ctrl);
-		ASC_PRT_NEXT();
-	} else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
-		len = asc_prt_line(cp, leftlen,
-				   " termination: %u (%s), bios_ctrl: 0x%x\n",
-				   ep_38C0800->termination_lvd, termstr,
-				   ep_38C0800->bios_ctrl);
-		ASC_PRT_NEXT();
-	} else {
-		len = asc_prt_line(cp, leftlen,
-				   " termination: %u (%s), bios_ctrl: 0x%x\n",
-				   ep_38C1600->termination_lvd, termstr,
-				   ep_38C1600->bios_ctrl);
-		ASC_PRT_NEXT();
-	}
+	if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550)
+		seq_printf(m,
+			   " termination: %u (%s), bios_ctrl: 0x%x\n",
+			   ep_3550->termination, termstr,
+			   ep_3550->bios_ctrl);
+	else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800)
+		seq_printf(m,
+			   " termination: %u (%s), bios_ctrl: 0x%x\n",
+			   ep_38C0800->termination_lvd, termstr,
+			   ep_38C0800->bios_ctrl);
+	else
+		seq_printf(m,
+			   " termination: %u (%s), bios_ctrl: 0x%x\n",
+			   ep_38C1600->termination_lvd, termstr,
+			   ep_38C1600->bios_ctrl);
 
-	len = asc_prt_line(cp, leftlen, " Target ID:           ");
-	ASC_PRT_NEXT();
-	for (i = 0; i <= ADV_MAX_TID; i++) {
-		len = asc_prt_line(cp, leftlen, " %X", i);
-		ASC_PRT_NEXT();
-	}
-	len = asc_prt_line(cp, leftlen, "\n");
-	ASC_PRT_NEXT();
+	seq_printf(m, " Target ID:           ");
+	for (i = 0; i <= ADV_MAX_TID; i++)
+		seq_printf(m, " %X", i);
+	seq_printf(m, "\n");
 
 	if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
 		word = ep_3550->disc_enable;
@@ -3388,15 +3221,11 @@
 	} else {
 		word = ep_38C1600->disc_enable;
 	}
-	len = asc_prt_line(cp, leftlen, " Disconnects:         ");
-	ASC_PRT_NEXT();
-	for (i = 0; i <= ADV_MAX_TID; i++) {
-		len = asc_prt_line(cp, leftlen, " %c",
-				   (word & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
-		ASC_PRT_NEXT();
-	}
-	len = asc_prt_line(cp, leftlen, "\n");
-	ASC_PRT_NEXT();
+	seq_printf(m, " Disconnects:         ");
+	for (i = 0; i <= ADV_MAX_TID; i++)
+		seq_printf(m, " %c",
+			   (word & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
+	seq_printf(m, "\n");
 
 	if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
 		word = ep_3550->tagqng_able;
@@ -3405,15 +3234,11 @@
 	} else {
 		word = ep_38C1600->tagqng_able;
 	}
-	len = asc_prt_line(cp, leftlen, " Command Queuing:     ");
-	ASC_PRT_NEXT();
-	for (i = 0; i <= ADV_MAX_TID; i++) {
-		len = asc_prt_line(cp, leftlen, " %c",
-				   (word & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
-		ASC_PRT_NEXT();
-	}
-	len = asc_prt_line(cp, leftlen, "\n");
-	ASC_PRT_NEXT();
+	seq_printf(m, " Command Queuing:     ");
+	for (i = 0; i <= ADV_MAX_TID; i++)
+		seq_printf(m, " %c",
+			   (word & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
+	seq_printf(m, "\n");
 
 	if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
 		word = ep_3550->start_motor;
@@ -3422,42 +3247,28 @@
 	} else {
 		word = ep_38C1600->start_motor;
 	}
-	len = asc_prt_line(cp, leftlen, " Start Motor:         ");
-	ASC_PRT_NEXT();
-	for (i = 0; i <= ADV_MAX_TID; i++) {
-		len = asc_prt_line(cp, leftlen, " %c",
-				   (word & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
-		ASC_PRT_NEXT();
-	}
-	len = asc_prt_line(cp, leftlen, "\n");
-	ASC_PRT_NEXT();
+	seq_printf(m, " Start Motor:         ");
+	for (i = 0; i <= ADV_MAX_TID; i++)
+		seq_printf(m, " %c",
+			   (word & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
+	seq_printf(m, "\n");
 
 	if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
-		len = asc_prt_line(cp, leftlen, " Synchronous Transfer:");
-		ASC_PRT_NEXT();
-		for (i = 0; i <= ADV_MAX_TID; i++) {
-			len = asc_prt_line(cp, leftlen, " %c",
-					   (ep_3550->
-					    sdtr_able & ADV_TID_TO_TIDMASK(i)) ?
-					   'Y' : 'N');
-			ASC_PRT_NEXT();
-		}
-		len = asc_prt_line(cp, leftlen, "\n");
-		ASC_PRT_NEXT();
+		seq_printf(m, " Synchronous Transfer:");
+		for (i = 0; i <= ADV_MAX_TID; i++)
+			seq_printf(m, " %c",
+				   (ep_3550->sdtr_able & ADV_TID_TO_TIDMASK(i)) ?
+				   'Y' : 'N');
+		seq_printf(m, "\n");
 	}
 
 	if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
-		len = asc_prt_line(cp, leftlen, " Ultra Transfer:      ");
-		ASC_PRT_NEXT();
-		for (i = 0; i <= ADV_MAX_TID; i++) {
-			len = asc_prt_line(cp, leftlen, " %c",
-					   (ep_3550->
-					    ultra_able & ADV_TID_TO_TIDMASK(i))
-					   ? 'Y' : 'N');
-			ASC_PRT_NEXT();
-		}
-		len = asc_prt_line(cp, leftlen, "\n");
-		ASC_PRT_NEXT();
+		seq_printf(m, " Ultra Transfer:      ");
+		for (i = 0; i <= ADV_MAX_TID; i++)
+			seq_printf(m, " %c",
+				   (ep_3550->ultra_able & ADV_TID_TO_TIDMASK(i))
+				   ? 'Y' : 'N');
+		seq_printf(m, "\n");
 	}
 
 	if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
@@ -3467,21 +3278,16 @@
 	} else {
 		word = ep_38C1600->wdtr_able;
 	}
-	len = asc_prt_line(cp, leftlen, " Wide Transfer:       ");
-	ASC_PRT_NEXT();
-	for (i = 0; i <= ADV_MAX_TID; i++) {
-		len = asc_prt_line(cp, leftlen, " %c",
-				   (word & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
-		ASC_PRT_NEXT();
-	}
-	len = asc_prt_line(cp, leftlen, "\n");
-	ASC_PRT_NEXT();
+	seq_printf(m, " Wide Transfer:       ");
+	for (i = 0; i <= ADV_MAX_TID; i++)
+		seq_printf(m, " %c",
+			   (word & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
+	seq_printf(m, "\n");
 
 	if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800 ||
 	    adv_dvc_varp->chip_type == ADV_CHIP_ASC38C1600) {
-		len = asc_prt_line(cp, leftlen,
-				   " Synchronous Transfer Speed (Mhz):\n  ");
-		ASC_PRT_NEXT();
+		seq_printf(m,
+			   " Synchronous Transfer Speed (Mhz):\n  ");
 		for (i = 0; i <= ADV_MAX_TID; i++) {
 			char *speed_str;
 
@@ -3517,99 +3323,64 @@
 				speed_str = "Unk";
 				break;
 			}
-			len = asc_prt_line(cp, leftlen, "%X:%s ", i, speed_str);
-			ASC_PRT_NEXT();
-			if (i == 7) {
-				len = asc_prt_line(cp, leftlen, "\n  ");
-				ASC_PRT_NEXT();
-			}
+			seq_printf(m, "%X:%s ", i, speed_str);
+			if (i == 7)
+				seq_printf(m, "\n  ");
 			sdtr_speed >>= 4;
 		}
-		len = asc_prt_line(cp, leftlen, "\n");
-		ASC_PRT_NEXT();
+		seq_printf(m, "\n");
 	}
-
-	return totlen;
 }
 
 /*
  * asc_prt_driver_conf()
- *
- * Note: no single line should be greater than ASC_PRTLINE_SIZE,
- * cf. asc_prt_line().
- *
- * Return the number of characters copied into 'cp'. No more than
- * 'cplen' characters will be copied to 'cp'.
  */
-static int asc_prt_driver_conf(struct Scsi_Host *shost, char *cp, int cplen)
+static void asc_prt_driver_conf(struct seq_file *m, struct Scsi_Host *shost)
 {
 	struct asc_board *boardp = shost_priv(shost);
-	int leftlen;
-	int totlen;
-	int len;
 	int chip_scsi_id;
 
-	leftlen = cplen;
-	totlen = len = 0;
+	seq_printf(m,
+		"\nLinux Driver Configuration and Information for AdvanSys SCSI Host %d:\n",
+		shost->host_no);
 
-	len = asc_prt_line(cp, leftlen,
-			   "\nLinux Driver Configuration and Information for AdvanSys SCSI Host %d:\n",
-			   shost->host_no);
-	ASC_PRT_NEXT();
+	seq_printf(m,
+		   " host_busy %u, last_reset %lu, max_id %u, max_lun %u, max_channel %u\n",
+		   shost->host_busy, shost->last_reset, shost->max_id,
+		   shost->max_lun, shost->max_channel);
 
-	len = asc_prt_line(cp, leftlen,
-			   " host_busy %u, last_reset %u, max_id %u, max_lun %u, max_channel %u\n",
-			   shost->host_busy, shost->last_reset, shost->max_id,
-			   shost->max_lun, shost->max_channel);
-	ASC_PRT_NEXT();
+	seq_printf(m,
+		   " unique_id %d, can_queue %d, this_id %d, sg_tablesize %u, cmd_per_lun %u\n",
+		   shost->unique_id, shost->can_queue, shost->this_id,
+		   shost->sg_tablesize, shost->cmd_per_lun);
 
-	len = asc_prt_line(cp, leftlen,
-			   " unique_id %d, can_queue %d, this_id %d, sg_tablesize %u, cmd_per_lun %u\n",
-			   shost->unique_id, shost->can_queue, shost->this_id,
-			   shost->sg_tablesize, shost->cmd_per_lun);
-	ASC_PRT_NEXT();
+	seq_printf(m,
+		   " unchecked_isa_dma %d, use_clustering %d\n",
+		   shost->unchecked_isa_dma, shost->use_clustering);
 
-	len = asc_prt_line(cp, leftlen,
-			   " unchecked_isa_dma %d, use_clustering %d\n",
-			   shost->unchecked_isa_dma, shost->use_clustering);
-	ASC_PRT_NEXT();
+	seq_printf(m,
+		   " flags 0x%x, last_reset 0x%lx, jiffies 0x%lx, asc_n_io_port 0x%x\n",
+		   boardp->flags, boardp->last_reset, jiffies,
+		   boardp->asc_n_io_port);
 
-	len = asc_prt_line(cp, leftlen,
-			   " flags 0x%x, last_reset 0x%x, jiffies 0x%x, asc_n_io_port 0x%x\n",
-			   boardp->flags, boardp->last_reset, jiffies,
-			   boardp->asc_n_io_port);
-	ASC_PRT_NEXT();
-
-	len = asc_prt_line(cp, leftlen, " io_port 0x%x\n", shost->io_port);
-	ASC_PRT_NEXT();
+	seq_printf(m, " io_port 0x%lx\n", shost->io_port);
 
 	if (ASC_NARROW_BOARD(boardp)) {
 		chip_scsi_id = boardp->dvc_cfg.asc_dvc_cfg.chip_scsi_id;
 	} else {
 		chip_scsi_id = boardp->dvc_var.adv_dvc_var.chip_scsi_id;
 	}
-
-	return totlen;
 }
 
 /*
  * asc_prt_asc_board_info()
  *
  * Print dynamic board configuration information.
- *
- * Note: no single line should be greater than ASC_PRTLINE_SIZE,
- * cf. asc_prt_line().
- *
- * Return the number of characters copied into 'cp'. No more than
- * 'cplen' characters will be copied to 'cp'.
  */
-static int asc_prt_asc_board_info(struct Scsi_Host *shost, char *cp, int cplen)
+static void asc_prt_asc_board_info(struct seq_file *m, struct Scsi_Host *shost)
 {
 	struct asc_board *boardp = shost_priv(shost);
 	int chip_scsi_id;
-	int leftlen;
-	int totlen;
-	int len;
 	ASC_DVC_VAR *v;
 	ASC_DVC_CFG *c;
 	int i;
@@ -3619,105 +3390,79 @@
 	c = &boardp->dvc_cfg.asc_dvc_cfg;
 	chip_scsi_id = c->chip_scsi_id;
 
-	leftlen = cplen;
-	totlen = len = 0;
+	seq_printf(m,
+		   "\nAsc Library Configuration and Statistics for AdvanSys SCSI Host %d:\n",
+		   shost->host_no);
 
-	len = asc_prt_line(cp, leftlen,
-			   "\nAsc Library Configuration and Statistics for AdvanSys SCSI Host %d:\n",
-			   shost->host_no);
-	ASC_PRT_NEXT();
-
-	len = asc_prt_line(cp, leftlen, " chip_version %u, mcode_date 0x%x, "
-			   "mcode_version 0x%x, err_code %u\n",
-			   c->chip_version, c->mcode_date, c->mcode_version,
-			   v->err_code);
-	ASC_PRT_NEXT();
+	seq_printf(m, " chip_version %u, mcode_date 0x%x, "
+		   "mcode_version 0x%x, err_code %u\n",
+		   c->chip_version, c->mcode_date, c->mcode_version,
+		   v->err_code);
 
 	/* Current number of commands waiting for the host. */
-	len = asc_prt_line(cp, leftlen,
-			   " Total Command Pending: %d\n", v->cur_total_qng);
-	ASC_PRT_NEXT();
+	seq_printf(m,
+		   " Total Command Pending: %d\n", v->cur_total_qng);
 
-	len = asc_prt_line(cp, leftlen, " Command Queuing:");
-	ASC_PRT_NEXT();
+	seq_printf(m, " Command Queuing:");
 	for (i = 0; i <= ASC_MAX_TID; i++) {
 		if ((chip_scsi_id == i) ||
 		    ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
 			continue;
 		}
-		len = asc_prt_line(cp, leftlen, " %X:%c",
-				   i,
-				   (v->
-				    use_tagged_qng & ADV_TID_TO_TIDMASK(i)) ?
-				   'Y' : 'N');
-		ASC_PRT_NEXT();
+		seq_printf(m, " %X:%c",
+			   i,
+			   (v->use_tagged_qng & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
 	}
-	len = asc_prt_line(cp, leftlen, "\n");
-	ASC_PRT_NEXT();
+	seq_printf(m, "\n");
 
 	/* Current number of commands waiting for a device. */
-	len = asc_prt_line(cp, leftlen, " Command Queue Pending:");
-	ASC_PRT_NEXT();
+	seq_printf(m, " Command Queue Pending:");
 	for (i = 0; i <= ASC_MAX_TID; i++) {
 		if ((chip_scsi_id == i) ||
 		    ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
 			continue;
 		}
-		len = asc_prt_line(cp, leftlen, " %X:%u", i, v->cur_dvc_qng[i]);
-		ASC_PRT_NEXT();
+		seq_printf(m, " %X:%u", i, v->cur_dvc_qng[i]);
 	}
-	len = asc_prt_line(cp, leftlen, "\n");
-	ASC_PRT_NEXT();
+	seq_printf(m, "\n");
 
 	/* Current limit on number of commands that can be sent to a device. */
-	len = asc_prt_line(cp, leftlen, " Command Queue Limit:");
-	ASC_PRT_NEXT();
+	seq_printf(m, " Command Queue Limit:");
 	for (i = 0; i <= ASC_MAX_TID; i++) {
 		if ((chip_scsi_id == i) ||
 		    ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
 			continue;
 		}
-		len = asc_prt_line(cp, leftlen, " %X:%u", i, v->max_dvc_qng[i]);
-		ASC_PRT_NEXT();
+		seq_printf(m, " %X:%u", i, v->max_dvc_qng[i]);
 	}
-	len = asc_prt_line(cp, leftlen, "\n");
-	ASC_PRT_NEXT();
+	seq_printf(m, "\n");
 
 	/* Indicate whether the device has returned queue full status. */
-	len = asc_prt_line(cp, leftlen, " Command Queue Full:");
-	ASC_PRT_NEXT();
+	seq_printf(m, " Command Queue Full:");
 	for (i = 0; i <= ASC_MAX_TID; i++) {
 		if ((chip_scsi_id == i) ||
 		    ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
 			continue;
 		}
-		if (boardp->queue_full & ADV_TID_TO_TIDMASK(i)) {
-			len = asc_prt_line(cp, leftlen, " %X:Y-%d",
-					   i, boardp->queue_full_cnt[i]);
-		} else {
-			len = asc_prt_line(cp, leftlen, " %X:N", i);
-		}
-		ASC_PRT_NEXT();
+		if (boardp->queue_full & ADV_TID_TO_TIDMASK(i))
+			seq_printf(m, " %X:Y-%d",
+				   i, boardp->queue_full_cnt[i]);
+		else
+			seq_printf(m, " %X:N", i);
 	}
-	len = asc_prt_line(cp, leftlen, "\n");
-	ASC_PRT_NEXT();
+	seq_printf(m, "\n");
 
-	len = asc_prt_line(cp, leftlen, " Synchronous Transfer:");
-	ASC_PRT_NEXT();
+	seq_printf(m, " Synchronous Transfer:");
 	for (i = 0; i <= ASC_MAX_TID; i++) {
 		if ((chip_scsi_id == i) ||
 		    ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
 			continue;
 		}
-		len = asc_prt_line(cp, leftlen, " %X:%c",
-				   i,
-				   (v->
-				    sdtr_done & ADV_TID_TO_TIDMASK(i)) ? 'Y' :
-				   'N');
-		ASC_PRT_NEXT();
+		seq_printf(m, " %X:%c",
+			   i,
+			   (v->sdtr_done & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
 	}
-	len = asc_prt_line(cp, leftlen, "\n");
-	ASC_PRT_NEXT();
+	seq_printf(m, "\n");
 
 	for (i = 0; i <= ASC_MAX_TID; i++) {
 		uchar syn_period_ix;
@@ -3728,69 +3473,48 @@
 			continue;
 		}
 
-		len = asc_prt_line(cp, leftlen, "  %X:", i);
-		ASC_PRT_NEXT();
+		seq_printf(m, "  %X:", i);
 
 		if ((boardp->sdtr_data[i] & ASC_SYN_MAX_OFFSET) == 0) {
-			len = asc_prt_line(cp, leftlen, " Asynchronous");
-			ASC_PRT_NEXT();
+			seq_printf(m, " Asynchronous");
 		} else {
 			syn_period_ix =
 			    (boardp->sdtr_data[i] >> 4) & (v->max_sdtr_index -
 							   1);
 
-			len = asc_prt_line(cp, leftlen,
-					   " Transfer Period Factor: %d (%d.%d Mhz),",
-					   v->sdtr_period_tbl[syn_period_ix],
-					   250 /
-					   v->sdtr_period_tbl[syn_period_ix],
-					   ASC_TENTHS(250,
-						      v->
-						      sdtr_period_tbl
-						      [syn_period_ix]));
-			ASC_PRT_NEXT();
+			seq_printf(m,
+				   " Transfer Period Factor: %d (%d.%d Mhz),",
+				   v->sdtr_period_tbl[syn_period_ix],
+				   250 / v->sdtr_period_tbl[syn_period_ix],
+				   ASC_TENTHS(250,
+					      v->sdtr_period_tbl[syn_period_ix]));
 
-			len = asc_prt_line(cp, leftlen, " REQ/ACK Offset: %d",
-					   boardp->
-					   sdtr_data[i] & ASC_SYN_MAX_OFFSET);
-			ASC_PRT_NEXT();
+			seq_printf(m, " REQ/ACK Offset: %d",
+				   boardp->sdtr_data[i] & ASC_SYN_MAX_OFFSET);
 		}
 
 		if ((v->sdtr_done & ADV_TID_TO_TIDMASK(i)) == 0) {
-			len = asc_prt_line(cp, leftlen, "*\n");
+			seq_printf(m, "*\n");
 			renegotiate = 1;
 		} else {
-			len = asc_prt_line(cp, leftlen, "\n");
+			seq_printf(m, "\n");
 		}
-		ASC_PRT_NEXT();
 	}
 
 	if (renegotiate) {
-		len = asc_prt_line(cp, leftlen,
-				   " * = Re-negotiation pending before next command.\n");
-		ASC_PRT_NEXT();
+		seq_printf(m,
+			   " * = Re-negotiation pending before next command.\n");
 	}
-
-	return totlen;
 }
 
 /*
  * asc_prt_adv_board_info()
  *
  * Print dynamic board configuration information.
- *
- * Note: no single line should be greater than ASC_PRTLINE_SIZE,
- * cf. asc_prt_line().
- *
- * Return the number of characters copied into 'cp'. No more than
- * 'cplen' characters will be copied to 'cp'.
  */
-static int asc_prt_adv_board_info(struct Scsi_Host *shost, char *cp, int cplen)
+static void asc_prt_adv_board_info(struct seq_file *m, struct Scsi_Host *shost)
 {
 	struct asc_board *boardp = shost_priv(shost);
-	int leftlen;
-	int totlen;
-	int len;
 	int i;
 	ADV_DVC_VAR *v;
 	ADV_DVC_CFG *c;
@@ -3809,47 +3533,35 @@
 	iop_base = v->iop_base;
 	chip_scsi_id = v->chip_scsi_id;
 
-	leftlen = cplen;
-	totlen = len = 0;
+	seq_printf(m,
+		   "\nAdv Library Configuration and Statistics for AdvanSys SCSI Host %d:\n",
+		   shost->host_no);
 
-	len = asc_prt_line(cp, leftlen,
-			   "\nAdv Library Configuration and Statistics for AdvanSys SCSI Host %d:\n",
-			   shost->host_no);
-	ASC_PRT_NEXT();
+	seq_printf(m,
+		   " iop_base 0x%lx, cable_detect: %X, err_code %u\n",
+		   (unsigned long)v->iop_base,
+		   AdvReadWordRegister(iop_base,IOPW_SCSI_CFG1) & CABLE_DETECT,
+		   v->err_code);
 
-	len = asc_prt_line(cp, leftlen,
-			   " iop_base 0x%lx, cable_detect: %X, err_code %u\n",
-			   v->iop_base,
-			   AdvReadWordRegister(iop_base,
-					       IOPW_SCSI_CFG1) & CABLE_DETECT,
-			   v->err_code);
-	ASC_PRT_NEXT();
-
-	len = asc_prt_line(cp, leftlen, " chip_version %u, mcode_date 0x%x, "
-			   "mcode_version 0x%x\n", c->chip_version,
-			   c->mcode_date, c->mcode_version);
-	ASC_PRT_NEXT();
+	seq_printf(m, " chip_version %u, mcode_date 0x%x, "
+		   "mcode_version 0x%x\n", c->chip_version,
+		   c->mcode_date, c->mcode_version);
 
 	AdvReadWordLram(iop_base, ASC_MC_TAGQNG_ABLE, tagqng_able);
-	len = asc_prt_line(cp, leftlen, " Queuing Enabled:");
-	ASC_PRT_NEXT();
+	seq_printf(m, " Queuing Enabled:");
 	for (i = 0; i <= ADV_MAX_TID; i++) {
 		if ((chip_scsi_id == i) ||
 		    ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
 			continue;
 		}
 
-		len = asc_prt_line(cp, leftlen, " %X:%c",
-				   i,
-				   (tagqng_able & ADV_TID_TO_TIDMASK(i)) ? 'Y' :
-				   'N');
-		ASC_PRT_NEXT();
+		seq_printf(m, " %X:%c",
+			   i,
+			   (tagqng_able & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
 	}
-	len = asc_prt_line(cp, leftlen, "\n");
-	ASC_PRT_NEXT();
+	seq_printf(m, "\n");
 
-	len = asc_prt_line(cp, leftlen, " Queue Limit:");
-	ASC_PRT_NEXT();
+	seq_printf(m, " Queue Limit:");
 	for (i = 0; i <= ADV_MAX_TID; i++) {
 		if ((chip_scsi_id == i) ||
 		    ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
@@ -3859,14 +3571,11 @@
 		AdvReadByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + i,
 				lrambyte);
 
-		len = asc_prt_line(cp, leftlen, " %X:%d", i, lrambyte);
-		ASC_PRT_NEXT();
+		seq_printf(m, " %X:%d", i, lrambyte);
 	}
-	len = asc_prt_line(cp, leftlen, "\n");
-	ASC_PRT_NEXT();
+	seq_printf(m, "\n");
 
-	len = asc_prt_line(cp, leftlen, " Command Pending:");
-	ASC_PRT_NEXT();
+	seq_printf(m, " Command Pending:");
 	for (i = 0; i <= ADV_MAX_TID; i++) {
 		if ((chip_scsi_id == i) ||
 		    ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
@@ -3876,33 +3585,26 @@
 		AdvReadByteLram(iop_base, ASC_MC_NUMBER_OF_QUEUED_CMD + i,
 				lrambyte);
 
-		len = asc_prt_line(cp, leftlen, " %X:%d", i, lrambyte);
-		ASC_PRT_NEXT();
+		seq_printf(m, " %X:%d", i, lrambyte);
 	}
-	len = asc_prt_line(cp, leftlen, "\n");
-	ASC_PRT_NEXT();
+	seq_printf(m, "\n");
 
 	AdvReadWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able);
-	len = asc_prt_line(cp, leftlen, " Wide Enabled:");
-	ASC_PRT_NEXT();
+	seq_printf(m, " Wide Enabled:");
 	for (i = 0; i <= ADV_MAX_TID; i++) {
 		if ((chip_scsi_id == i) ||
 		    ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
 			continue;
 		}
 
-		len = asc_prt_line(cp, leftlen, " %X:%c",
-				   i,
-				   (wdtr_able & ADV_TID_TO_TIDMASK(i)) ? 'Y' :
-				   'N');
-		ASC_PRT_NEXT();
+		seq_printf(m, " %X:%c",
+			   i,
+			   (wdtr_able & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
 	}
-	len = asc_prt_line(cp, leftlen, "\n");
-	ASC_PRT_NEXT();
+	seq_printf(m, "\n");
 
 	AdvReadWordLram(iop_base, ASC_MC_WDTR_DONE, wdtr_done);
-	len = asc_prt_line(cp, leftlen, " Transfer Bit Width:");
-	ASC_PRT_NEXT();
+	seq_printf(m, " Transfer Bit Width:");
 	for (i = 0; i <= ADV_MAX_TID; i++) {
 		if ((chip_scsi_id == i) ||
 		    ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
@@ -3913,37 +3615,30 @@
 				ASC_MC_DEVICE_HSHK_CFG_TABLE + (2 * i),
 				lramword);
 
-		len = asc_prt_line(cp, leftlen, " %X:%d",
-				   i, (lramword & 0x8000) ? 16 : 8);
-		ASC_PRT_NEXT();
+		seq_printf(m, " %X:%d",
+			   i, (lramword & 0x8000) ? 16 : 8);
 
 		if ((wdtr_able & ADV_TID_TO_TIDMASK(i)) &&
 		    (wdtr_done & ADV_TID_TO_TIDMASK(i)) == 0) {
-			len = asc_prt_line(cp, leftlen, "*");
-			ASC_PRT_NEXT();
+			seq_printf(m, "*");
 			renegotiate = 1;
 		}
 	}
-	len = asc_prt_line(cp, leftlen, "\n");
-	ASC_PRT_NEXT();
+	seq_printf(m, "\n");
 
 	AdvReadWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able);
-	len = asc_prt_line(cp, leftlen, " Synchronous Enabled:");
-	ASC_PRT_NEXT();
+	seq_printf(m, " Synchronous Enabled:");
 	for (i = 0; i <= ADV_MAX_TID; i++) {
 		if ((chip_scsi_id == i) ||
 		    ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
 			continue;
 		}
 
-		len = asc_prt_line(cp, leftlen, " %X:%c",
-				   i,
-				   (sdtr_able & ADV_TID_TO_TIDMASK(i)) ? 'Y' :
-				   'N');
-		ASC_PRT_NEXT();
+		seq_printf(m, " %X:%c",
+			   i,
+			   (sdtr_able & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
 	}
-	len = asc_prt_line(cp, leftlen, "\n");
-	ASC_PRT_NEXT();
+	seq_printf(m, "\n");
 
 	AdvReadWordLram(iop_base, ASC_MC_SDTR_DONE, sdtr_done);
 	for (i = 0; i <= ADV_MAX_TID; i++) {
@@ -3959,358 +3654,170 @@
 			continue;
 		}
 
-		len = asc_prt_line(cp, leftlen, "  %X:", i);
-		ASC_PRT_NEXT();
+		seq_printf(m, "  %X:", i);
 
 		if ((lramword & 0x1F) == 0) {	/* Check for REQ/ACK Offset 0. */
-			len = asc_prt_line(cp, leftlen, " Asynchronous");
-			ASC_PRT_NEXT();
+			seq_printf(m, " Asynchronous");
 		} else {
-			len =
-			    asc_prt_line(cp, leftlen,
-					 " Transfer Period Factor: ");
-			ASC_PRT_NEXT();
+			seq_printf(m, " Transfer Period Factor: ");
 
 			if ((lramword & 0x1F00) == 0x1100) {	/* 80 Mhz */
-				len =
-				    asc_prt_line(cp, leftlen, "9 (80.0 Mhz),");
-				ASC_PRT_NEXT();
+				seq_printf(m, "9 (80.0 Mhz),");
 			} else if ((lramword & 0x1F00) == 0x1000) {	/* 40 Mhz */
-				len =
-				    asc_prt_line(cp, leftlen, "10 (40.0 Mhz),");
-				ASC_PRT_NEXT();
+				seq_printf(m, "10 (40.0 Mhz),");
 			} else {	/* 20 Mhz or below. */
 
 				period = (((lramword >> 8) * 25) + 50) / 4;
 
 				if (period == 0) {	/* Should never happen. */
-					len =
-					    asc_prt_line(cp, leftlen,
-							 "%d (? Mhz), ");
-					ASC_PRT_NEXT();
+					seq_printf(m, "%d (? Mhz), ", period);
 				} else {
-					len = asc_prt_line(cp, leftlen,
-							   "%d (%d.%d Mhz),",
-							   period, 250 / period,
-							   ASC_TENTHS(250,
-								      period));
-					ASC_PRT_NEXT();
+					seq_printf(m,
+						   "%d (%d.%d Mhz),",
+						   period, 250 / period,
+						   ASC_TENTHS(250, period));
 				}
 			}
 
-			len = asc_prt_line(cp, leftlen, " REQ/ACK Offset: %d",
-					   lramword & 0x1F);
-			ASC_PRT_NEXT();
+			seq_printf(m, " REQ/ACK Offset: %d",
+				   lramword & 0x1F);
 		}
 
 		if ((sdtr_done & ADV_TID_TO_TIDMASK(i)) == 0) {
-			len = asc_prt_line(cp, leftlen, "*\n");
+			seq_printf(m, "*\n");
 			renegotiate = 1;
 		} else {
-			len = asc_prt_line(cp, leftlen, "\n");
+			seq_printf(m, "\n");
 		}
-		ASC_PRT_NEXT();
 	}
 
 	if (renegotiate) {
-		len = asc_prt_line(cp, leftlen,
-				   " * = Re-negotiation pending before next command.\n");
-		ASC_PRT_NEXT();
+		seq_printf(m,
+			   " * = Re-negotiation pending before next command.\n");
 	}
-
-	return totlen;
-}
-
-/*
- * asc_proc_copy()
- *
- * Copy proc information to a read buffer taking into account the current
- * read offset in the file and the remaining space in the read buffer.
- */
-static int
-asc_proc_copy(off_t advoffset, off_t offset, char *curbuf, int leftlen,
-	      char *cp, int cplen)
-{
-	int cnt = 0;
-
-	ASC_DBG(2, "offset %d, advoffset %d, cplen %d\n",
-		 (unsigned)offset, (unsigned)advoffset, cplen);
-	if (offset <= advoffset) {
-		/* Read offset below current offset, copy everything. */
-		cnt = min(cplen, leftlen);
-		ASC_DBG(2, "curbuf 0x%lx, cp 0x%lx, cnt %d\n",
-			 (ulong)curbuf, (ulong)cp, cnt);
-		memcpy(curbuf, cp, cnt);
-	} else if (offset < advoffset + cplen) {
-		/* Read offset within current range, partial copy. */
-		cnt = (advoffset + cplen) - offset;
-		cp = (cp + cplen) - cnt;
-		cnt = min(cnt, leftlen);
-		ASC_DBG(2, "curbuf 0x%lx, cp 0x%lx, cnt %d\n",
-			 (ulong)curbuf, (ulong)cp, cnt);
-		memcpy(curbuf, cp, cnt);
-	}
-	return cnt;
 }
 
 #ifdef ADVANSYS_STATS
 /*
  * asc_prt_board_stats()
- *
- * Note: no single line should be greater than ASC_PRTLINE_SIZE,
- * cf. asc_prt_line().
- *
- * Return the number of characters copied into 'cp'. No more than
- * 'cplen' characters will be copied to 'cp'.
  */
-static int asc_prt_board_stats(struct Scsi_Host *shost, char *cp, int cplen)
+static void asc_prt_board_stats(struct seq_file *m, struct Scsi_Host *shost)
 {
 	struct asc_board *boardp = shost_priv(shost);
 	struct asc_stats *s = &boardp->asc_stats;
 
-	int leftlen = cplen;
-	int len, totlen = 0;
+	seq_printf(m,
+		   "\nLinux Driver Statistics for AdvanSys SCSI Host %d:\n",
+		   shost->host_no);
 
-	len = asc_prt_line(cp, leftlen,
-			   "\nLinux Driver Statistics for AdvanSys SCSI Host %d:\n",
-			   shost->host_no);
-	ASC_PRT_NEXT();
+	seq_printf(m,
+		   " queuecommand %u, reset %u, biosparam %u, interrupt %u\n",
+		   s->queuecommand, s->reset, s->biosparam,
+		   s->interrupt);
 
-	len = asc_prt_line(cp, leftlen,
-			   " queuecommand %lu, reset %lu, biosparam %lu, interrupt %lu\n",
-			   s->queuecommand, s->reset, s->biosparam,
-			   s->interrupt);
-	ASC_PRT_NEXT();
+	seq_printf(m,
+		   " callback %u, done %u, build_error %u, build_noreq %u, build_nosg %u\n",
+		   s->callback, s->done, s->build_error,
+		   s->adv_build_noreq, s->adv_build_nosg);
 
-	len = asc_prt_line(cp, leftlen,
-			   " callback %lu, done %lu, build_error %lu, build_noreq %lu, build_nosg %lu\n",
-			   s->callback, s->done, s->build_error,
-			   s->adv_build_noreq, s->adv_build_nosg);
-	ASC_PRT_NEXT();
-
-	len = asc_prt_line(cp, leftlen,
-			   " exe_noerror %lu, exe_busy %lu, exe_error %lu, exe_unknown %lu\n",
-			   s->exe_noerror, s->exe_busy, s->exe_error,
-			   s->exe_unknown);
-	ASC_PRT_NEXT();
+	seq_printf(m,
+		   " exe_noerror %u, exe_busy %u, exe_error %u, exe_unknown %u\n",
+		   s->exe_noerror, s->exe_busy, s->exe_error,
+		   s->exe_unknown);
 
 	/*
 	 * Display data transfer statistics.
 	 */
 	if (s->xfer_cnt > 0) {
-		len = asc_prt_line(cp, leftlen, " xfer_cnt %lu, xfer_elem %lu, ",
-				   s->xfer_cnt, s->xfer_elem);
-		ASC_PRT_NEXT();
+		seq_printf(m, " xfer_cnt %u, xfer_elem %u, ",
+			   s->xfer_cnt, s->xfer_elem);
 
-		len = asc_prt_line(cp, leftlen, "xfer_bytes %lu.%01lu kb\n",
-				   s->xfer_sect / 2, ASC_TENTHS(s->xfer_sect, 2));
-		ASC_PRT_NEXT();
+		seq_printf(m, "xfer_bytes %u.%01u kb\n",
+			   s->xfer_sect / 2, ASC_TENTHS(s->xfer_sect, 2));
 
 		/* Scatter gather transfer statistics */
-		len = asc_prt_line(cp, leftlen, " avg_num_elem %lu.%01lu, ",
-				   s->xfer_elem / s->xfer_cnt,
-				   ASC_TENTHS(s->xfer_elem, s->xfer_cnt));
-		ASC_PRT_NEXT();
+		seq_printf(m, " avg_num_elem %u.%01u, ",
+			   s->xfer_elem / s->xfer_cnt,
+			   ASC_TENTHS(s->xfer_elem, s->xfer_cnt));
 
-		len = asc_prt_line(cp, leftlen, "avg_elem_size %lu.%01lu kb, ",
-				   (s->xfer_sect / 2) / s->xfer_elem,
-				   ASC_TENTHS((s->xfer_sect / 2), s->xfer_elem));
-		ASC_PRT_NEXT();
+		seq_printf(m, "avg_elem_size %u.%01u kb, ",
+			   (s->xfer_sect / 2) / s->xfer_elem,
+			   ASC_TENTHS((s->xfer_sect / 2), s->xfer_elem));
 
-		len = asc_prt_line(cp, leftlen, "avg_xfer_size %lu.%01lu kb\n",
-				   (s->xfer_sect / 2) / s->xfer_cnt,
-				   ASC_TENTHS((s->xfer_sect / 2), s->xfer_cnt));
-		ASC_PRT_NEXT();
+		seq_printf(m, "avg_xfer_size %u.%01u kb\n",
+			   (s->xfer_sect / 2) / s->xfer_cnt,
+			   ASC_TENTHS((s->xfer_sect / 2), s->xfer_cnt));
 	}
-
-	return totlen;
 }
 #endif /* ADVANSYS_STATS */
 
 /*
- * advansys_proc_info() - /proc/scsi/advansys/{0,1,2,3,...}
+ * advansys_show_info() - /proc/scsi/advansys/{0,1,2,3,...}
  *
- * *buffer: I/O buffer
- * **start: if inout == FALSE pointer into buffer where user read should start
- * offset: current offset into a /proc/scsi/advansys/[0...] file
- * length: length of buffer
- * hostno: Scsi_Host host_no
- * inout: TRUE - user is writing; FALSE - user is reading
+ * m: seq_file to print into
+ * shost: Scsi_Host
  *
  * Return the number of bytes read from or written to a
  * /proc/scsi/advansys/[0...] file.
- *
- * Note: This function uses the per board buffer 'prtbuf' which is
- * allocated when the board is initialized in advansys_detect(). The
- * buffer is ASC_PRTBUF_SIZE bytes. The function asc_proc_copy() is
- * used to write to the buffer. The way asc_proc_copy() is written
- * if 'prtbuf' is too small it will not be overwritten. Instead the
- * user just won't get all the available statistics.
  */
 static int
-advansys_proc_info(struct Scsi_Host *shost, char *buffer, char **start,
-		   off_t offset, int length, int inout)
+advansys_show_info(struct seq_file *m, struct Scsi_Host *shost)
 {
 	struct asc_board *boardp = shost_priv(shost);
-	char *cp;
-	int cplen;
-	int cnt;
-	int totcnt;
-	int leftlen;
-	char *curbuf;
-	off_t advoffset;
 
 	ASC_DBG(1, "begin\n");
 
 	/*
-	 * User write not supported.
-	 */
-	if (inout == TRUE)
-		return -ENOSYS;
-
-	/*
 	 * User read of /proc/scsi/advansys/[0...] file.
 	 */
 
-	/* Copy read data starting at the beginning of the buffer. */
-	*start = buffer;
-	curbuf = buffer;
-	advoffset = 0;
-	totcnt = 0;
-	leftlen = length;
-
 	/*
 	 * Get board configuration information.
 	 *
 	 * advansys_info() returns the board string from its own static buffer.
 	 */
-	cp = (char *)advansys_info(shost);
-	strcat(cp, "\n");
-	cplen = strlen(cp);
 	/* Copy board information. */
-	cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen);
-	totcnt += cnt;
-	leftlen -= cnt;
-	if (leftlen == 0) {
-		ASC_DBG(1, "totcnt %d\n", totcnt);
-		return totcnt;
-	}
-	advoffset += cplen;
-	curbuf += cnt;
-
+	seq_printf(m, "%s\n", (char *)advansys_info(shost));
 	/*
 	 * Display Wide Board BIOS Information.
 	 */
-	if (!ASC_NARROW_BOARD(boardp)) {
-		cp = boardp->prtbuf;
-		cplen = asc_prt_adv_bios(shost, cp, ASC_PRTBUF_SIZE);
-		BUG_ON(cplen >= ASC_PRTBUF_SIZE);
-		cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp,
-				  cplen);
-		totcnt += cnt;
-		leftlen -= cnt;
-		if (leftlen == 0) {
-			ASC_DBG(1, "totcnt %d\n", totcnt);
-			return totcnt;
-		}
-		advoffset += cplen;
-		curbuf += cnt;
-	}
+	if (!ASC_NARROW_BOARD(boardp))
+		asc_prt_adv_bios(m, shost);
 
 	/*
 	 * Display driver information for each device attached to the board.
 	 */
-	cp = boardp->prtbuf;
-	cplen = asc_prt_board_devices(shost, cp, ASC_PRTBUF_SIZE);
-	BUG_ON(cplen >= ASC_PRTBUF_SIZE);
-	cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen);
-	totcnt += cnt;
-	leftlen -= cnt;
-	if (leftlen == 0) {
-		ASC_DBG(1, "totcnt %d\n", totcnt);
-		return totcnt;
-	}
-	advoffset += cplen;
-	curbuf += cnt;
+	asc_prt_board_devices(m, shost);
 
 	/*
 	 * Display EEPROM configuration for the board.
 	 */
-	cp = boardp->prtbuf;
-	if (ASC_NARROW_BOARD(boardp)) {
-		cplen = asc_prt_asc_board_eeprom(shost, cp, ASC_PRTBUF_SIZE);
-	} else {
-		cplen = asc_prt_adv_board_eeprom(shost, cp, ASC_PRTBUF_SIZE);
-	}
-	BUG_ON(cplen >= ASC_PRTBUF_SIZE);
-	cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen);
-	totcnt += cnt;
-	leftlen -= cnt;
-	if (leftlen == 0) {
-		ASC_DBG(1, "totcnt %d\n", totcnt);
-		return totcnt;
-	}
-	advoffset += cplen;
-	curbuf += cnt;
+	if (ASC_NARROW_BOARD(boardp))
+		asc_prt_asc_board_eeprom(m, shost);
+	else
+		asc_prt_adv_board_eeprom(m, shost);
 
 	/*
 	 * Display driver configuration and information for the board.
 	 */
-	cp = boardp->prtbuf;
-	cplen = asc_prt_driver_conf(shost, cp, ASC_PRTBUF_SIZE);
-	BUG_ON(cplen >= ASC_PRTBUF_SIZE);
-	cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen);
-	totcnt += cnt;
-	leftlen -= cnt;
-	if (leftlen == 0) {
-		ASC_DBG(1, "totcnt %d\n", totcnt);
-		return totcnt;
-	}
-	advoffset += cplen;
-	curbuf += cnt;
+	asc_prt_driver_conf(m, shost);
 
 #ifdef ADVANSYS_STATS
 	/*
 	 * Display driver statistics for the board.
 	 */
-	cp = boardp->prtbuf;
-	cplen = asc_prt_board_stats(shost, cp, ASC_PRTBUF_SIZE);
-	BUG_ON(cplen >= ASC_PRTBUF_SIZE);
-	cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen);
-	totcnt += cnt;
-	leftlen -= cnt;
-	if (leftlen == 0) {
-		ASC_DBG(1, "totcnt %d\n", totcnt);
-		return totcnt;
-	}
-	advoffset += cplen;
-	curbuf += cnt;
+	asc_prt_board_stats(m, shost);
 #endif /* ADVANSYS_STATS */
 
 	/*
 	 * Display Asc Library dynamic configuration information
 	 * for the board.
 	 */
-	cp = boardp->prtbuf;
-	if (ASC_NARROW_BOARD(boardp)) {
-		cplen = asc_prt_asc_board_info(shost, cp, ASC_PRTBUF_SIZE);
-	} else {
-		cplen = asc_prt_adv_board_info(shost, cp, ASC_PRTBUF_SIZE);
-	}
-	BUG_ON(cplen >= ASC_PRTBUF_SIZE);
-	cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen);
-	totcnt += cnt;
-	leftlen -= cnt;
-	if (leftlen == 0) {
-		ASC_DBG(1, "totcnt %d\n", totcnt);
-		return totcnt;
-	}
-	advoffset += cplen;
-	curbuf += cnt;
-
-	ASC_DBG(1, "totcnt %d\n", totcnt);
-
-	return totcnt;
+	if (ASC_NARROW_BOARD(boardp))
+		asc_prt_asc_board_info(m, shost);
+	else
+		asc_prt_adv_board_info(m, shost);
+	return 0;
 }
 #endif /* CONFIG_PROC_FS */
 
@@ -11743,7 +11250,7 @@
 static struct scsi_host_template advansys_template = {
 	.proc_name = DRV_NAME,
 #ifdef CONFIG_PROC_FS
-	.proc_info = advansys_proc_info,
+	.show_info = advansys_show_info,
 #endif
 	.name = DRV_NAME,
 	.info = advansys_info,
@@ -11939,20 +11446,6 @@
 #endif /* CONFIG_PCI */
 	}
 
-#ifdef CONFIG_PROC_FS
-	/*
-	 * Allocate buffer for printing information from
-	 * /proc/scsi/advansys/[0...].
-	 */
-	boardp->prtbuf = kmalloc(ASC_PRTBUF_SIZE, GFP_KERNEL);
-	if (!boardp->prtbuf) {
-		shost_printk(KERN_ERR, shost, "kmalloc(%d) returned NULL\n",
-				ASC_PRTBUF_SIZE);
-		ret = -ENOMEM;
-		goto err_unmap;
-	}
-#endif /* CONFIG_PROC_FS */
-
 	if (ASC_NARROW_BOARD(boardp)) {
 		/*
 		 * Set the board bus type and PCI IRQ before
@@ -12010,7 +11503,7 @@
 	}
 
 	if (ret)
-		goto err_free_proc;
+		goto err_unmap;
 
 	/*
 	 * Save the EEPROM configuration so that it can be displayed
@@ -12055,7 +11548,7 @@
 		ASC_DBG(2, "AscInitSetConfig()\n");
 		ret = AscInitSetConfig(pdev, shost) ? -ENODEV : 0;
 		if (ret)
-			goto err_free_proc;
+			goto err_unmap;
 	} else {
 		ADVEEP_3550_CONFIG *ep_3550;
 		ADVEEP_38C0800_CONFIG *ep_38C0800;
@@ -12290,7 +11783,7 @@
 				shost_printk(KERN_ERR, shost, "request_dma() "
 						"%d failed %d\n",
 						shost->dma_channel, ret);
-				goto err_free_proc;
+				goto err_unmap;
 			}
 			AscEnableIsaDma(shost->dma_channel);
 		}
@@ -12371,8 +11864,6 @@
 	if (shost->dma_channel != NO_ISA_DMA)
 		free_dma(shost->dma_channel);
 #endif
- err_free_proc:
-	kfree(boardp->prtbuf);
  err_unmap:
 	if (boardp->ioremap_addr)
 		iounmap(boardp->ioremap_addr);
@@ -12406,7 +11897,6 @@
 		iounmap(board->ioremap_addr);
 		advansys_wide_free_mem(board);
 	}
-	kfree(board->prtbuf);
 	scsi_host_put(shost);
 	ASC_DBG(1, "end\n");
 	return 0;
diff --git a/drivers/scsi/aha152x.c b/drivers/scsi/aha152x.c
index a284be1..3f7b6fe 100644
--- a/drivers/scsi/aha152x.c
+++ b/drivers/scsi/aha152x.c
@@ -2977,11 +2977,10 @@
 }
 
 #undef SPRINTF
-#define SPRINTF(args...) pos += sprintf(pos, ## args)
+#define SPRINTF(args...) seq_printf(m, ##args)
 
-static int get_command(char *pos, Scsi_Cmnd * ptr)
+static void get_command(struct seq_file *m, Scsi_Cmnd * ptr)
 {
-	char *start = pos;
 	int i;
 
 	SPRINTF("%p: target=%d; lun=%d; cmnd=( ",
@@ -3011,13 +3010,10 @@
 	if (ptr->SCp.phase & syncneg)
 		SPRINTF("syncneg|");
 	SPRINTF("; next=0x%p\n", SCNEXT(ptr));
-
-	return (pos - start);
 }
 
-static int get_ports(struct Scsi_Host *shpnt, char *pos)
+static void get_ports(struct seq_file *m, struct Scsi_Host *shpnt)
 {
-	char *start = pos;
 	int s;
 
 	SPRINTF("\n%s: %s(%s) ", CURRENT_SC ? "on bus" : "waiting", states[STATE].name, states[PREVSTATE].name);
@@ -3273,11 +3269,9 @@
 	if (s & ENREQINIT)
 		SPRINTF("ENREQINIT ");
 	SPRINTF(")\n");
-
-	return (pos - start);
 }
 
-static int aha152x_set_info(char *buffer, int length, struct Scsi_Host *shpnt)
+static int aha152x_set_info(struct Scsi_Host *shpnt, char *buffer, int length)
 {
 	if(!shpnt || !buffer || length<8 || strncmp("aha152x ", buffer, 8)!=0)
 		return -EINVAL;
@@ -3320,26 +3314,11 @@
 	return length;
 }
 
-#undef SPRINTF
-#define SPRINTF(args...) \
-	do { if(pos < buffer + length) pos += sprintf(pos, ## args); } while(0)
-
-static int aha152x_proc_info(struct Scsi_Host *shpnt, char *buffer, char **start,
-		      off_t offset, int length, int inout)
+static int aha152x_show_info(struct seq_file *m, struct Scsi_Host *shpnt)
 {
 	int i;
-	char *pos = buffer;
 	Scsi_Cmnd *ptr;
 	unsigned long flags;
-	int thislength;
-
-	DPRINTK(debug_procinfo, 
-	       KERN_DEBUG "aha152x_proc_info: buffer=%p offset=%ld length=%d hostno=%d inout=%d\n",
-	       buffer, offset, length, shpnt->host_no, inout);
-
-
-	if (inout)
-		return aha152x_set_info(buffer, length, shpnt);
 
 	SPRINTF(AHA152X_REVID "\n");
 
@@ -3392,25 +3371,25 @@
 	if (ISSUE_SC) {
 		SPRINTF("not yet issued commands:\n");
 		for (ptr = ISSUE_SC; ptr; ptr = SCNEXT(ptr))
-			pos += get_command(pos, ptr);
+			get_command(m, ptr);
 	} else
 		SPRINTF("no not yet issued commands\n");
 	DO_UNLOCK(flags);
 
 	if (CURRENT_SC) {
 		SPRINTF("current command:\n");
-		pos += get_command(pos, CURRENT_SC);
+		get_command(m, CURRENT_SC);
 	} else
 		SPRINTF("no current command\n");
 
 	if (DISCONNECTED_SC) {
 		SPRINTF("disconnected commands:\n");
 		for (ptr = DISCONNECTED_SC; ptr; ptr = SCNEXT(ptr))
-			pos += get_command(pos, ptr);
+			get_command(m, ptr);
 	} else
 		SPRINTF("no disconnected commands\n");
 
-	pos += get_ports(shpnt, pos);
+	get_ports(m, shpnt);
 
 #if defined(AHA152X_STAT)
 	SPRINTF("statistics:\n"
@@ -3440,24 +3419,7 @@
 			HOSTDATA(shpnt)->time[i]);
 	}
 #endif
-
-	DPRINTK(debug_procinfo, KERN_DEBUG "aha152x_proc_info: pos=%p\n", pos);
-
-	thislength = pos - (buffer + offset);
-	DPRINTK(debug_procinfo, KERN_DEBUG "aha152x_proc_info: length=%d thislength=%d\n", length, thislength);
-
-	if(thislength<0) {
-		DPRINTK(debug_procinfo, KERN_DEBUG "aha152x_proc_info: output too short\n");
-		*start = NULL;
-		return 0;
-	}
-
-	thislength = thislength<length ? thislength : length;
-
-	DPRINTK(debug_procinfo, KERN_DEBUG "aha152x_proc_info: return %d\n", thislength);
-
-	*start = buffer + offset;
-	return thislength < length ? thislength : length;
+	return 0;
 }
 
 static int aha152x_adjust_queue(struct scsi_device *device)
@@ -3470,7 +3432,8 @@
 	.module				= THIS_MODULE,
 	.name				= AHA152X_REVID,
 	.proc_name			= "aha152x",
-	.proc_info			= aha152x_proc_info,
+	.show_info			= aha152x_show_info,
+	.write_info			= aha152x_set_info,
 	.queuecommand			= aha152x_queue,
 	.eh_abort_handler		= aha152x_abort,
 	.eh_device_reset_handler	= aha152x_device_reset,
diff --git a/drivers/scsi/aha1740.c b/drivers/scsi/aha1740.c
index df775e6..5f31017 100644
--- a/drivers/scsi/aha1740.c
+++ b/drivers/scsi/aha1740.c
@@ -106,33 +106,14 @@
 	return hdata->ecb_dma_addr + offset;
 }
 
-static int aha1740_proc_info(struct Scsi_Host *shpnt, char *buffer,
-			     char **start, off_t offset,
-			     int length, int inout)
+static int aha1740_show_info(struct seq_file *m, struct Scsi_Host *shpnt)
 {
-	int len;
-	struct aha1740_hostdata *host;
-
-	if (inout)
-		return-ENOSYS;
-
-	host = HOSTDATA(shpnt);
-
-	len = sprintf(buffer, "aha174x at IO:%lx, IRQ %d, SLOT %d.\n"
+	struct aha1740_hostdata *host = HOSTDATA(shpnt);
+	seq_printf(m, "aha174x at IO:%lx, IRQ %d, SLOT %d.\n"
 		      "Extended translation %sabled.\n",
 		      shpnt->io_port, shpnt->irq, host->edev->slot,
 		      host->translation ? "en" : "dis");
-
-	if (offset > len) {
-		*start = buffer;
-		return 0;
-	}
-
-	*start = buffer + offset;
-	len -= offset;
-	if (len > length)
-		len = length;
-	return len;
+	return 0;
 }
 
 static int aha1740_makecode(unchar *sense, unchar *status)
@@ -556,7 +537,7 @@
 static struct scsi_host_template aha1740_template = {
 	.module           = THIS_MODULE,
 	.proc_name        = "aha1740",
-	.proc_info        = aha1740_proc_info,
+	.show_info        = aha1740_show_info,
 	.name             = "Adaptec 174x (EISA)",
 	.queuecommand     = aha1740_queuecommand,
 	.bios_param       = aha1740_biosparam,
diff --git a/drivers/scsi/aic7xxx/aic79xx_osm.c b/drivers/scsi/aic7xxx/aic79xx_osm.c
index 9328121..69d5c43 100644
--- a/drivers/scsi/aic7xxx/aic79xx_osm.c
+++ b/drivers/scsi/aic7xxx/aic79xx_osm.c
@@ -906,7 +906,8 @@
 	.module			= THIS_MODULE,
 	.name			= "aic79xx",
 	.proc_name		= "aic79xx",
-	.proc_info		= ahd_linux_proc_info,
+	.show_info		= ahd_linux_show_info,
+	.write_info	 	= ahd_proc_write_seeprom,
 	.info			= ahd_linux_info,
 	.queuecommand		= ahd_linux_queue,
 	.eh_abort_handler	= ahd_linux_abort,
@@ -1702,19 +1703,13 @@
 	switch (code) {
 	case AC_TRANSFER_NEG:
 	{
-		char	buf[80];
 		struct  scsi_target *starget;
-		struct	info_str info;
 		struct	ahd_initiator_tinfo *tinfo;
 		struct	ahd_tmode_tstate *tstate;
 		unsigned int target_ppr_options;
 
 		BUG_ON(target == CAM_TARGET_WILDCARD);
 
-		info.buffer = buf;
-		info.length = sizeof(buf);
-		info.offset = 0;
-		info.pos = 0;
 		tinfo = ahd_fetch_transinfo(ahd, channel, ahd->our_id,
 					    target, &tstate);
 
diff --git a/drivers/scsi/aic7xxx/aic79xx_osm.h b/drivers/scsi/aic7xxx/aic79xx_osm.h
index 28e4349..c58fa33 100644
--- a/drivers/scsi/aic7xxx/aic79xx_osm.h
+++ b/drivers/scsi/aic7xxx/aic79xx_osm.h
@@ -379,14 +379,6 @@
 int		ahd_linux_register_host(struct ahd_softc *,
 					struct scsi_host_template *);
 
-/*************************** Pretty Printing **********************************/
-struct info_str {
-	char *buffer;
-	int length;
-	off_t offset;
-	int pos;
-};
-
 /******************************** Locking *************************************/
 static inline void
 ahd_lockinit(struct ahd_softc *ahd)
@@ -513,8 +505,8 @@
 }
 
 /**************************** Proc FS Support *********************************/
-int	ahd_linux_proc_info(struct Scsi_Host *, char *, char **,
-			    off_t, int, int);
+int	ahd_proc_write_seeprom(struct Scsi_Host *, char *, int);
+int	ahd_linux_show_info(struct seq_file *,struct Scsi_Host *);
 
 /*********************** Transaction Access Wrappers **************************/
 static inline void ahd_cmd_set_transaction_status(struct scsi_cmnd *, uint32_t);
diff --git a/drivers/scsi/aic7xxx/aic79xx_proc.c b/drivers/scsi/aic7xxx/aic79xx_proc.c
index 59c85d5..e9778b4 100644
--- a/drivers/scsi/aic7xxx/aic79xx_proc.c
+++ b/drivers/scsi/aic7xxx/aic79xx_proc.c
@@ -42,16 +42,12 @@
 #include "aic79xx_osm.h"
 #include "aic79xx_inline.h"
 
-static void	copy_mem_info(struct info_str *info, char *data, int len);
-static int	copy_info(struct info_str *info, char *fmt, ...);
 static void	ahd_dump_target_state(struct ahd_softc *ahd,
-				      struct info_str *info,
+				      struct seq_file *m,
 				      u_int our_id, char channel,
 				      u_int target_id);
-static void	ahd_dump_device_state(struct info_str *info,
+static void	ahd_dump_device_state(struct seq_file *m,
 				      struct scsi_device *sdev);
-static int	ahd_proc_write_seeprom(struct ahd_softc *ahd,
-				       char *buffer, int length);
 
 /*
  * Table of syncrates that don't follow the "divisible by 4"
@@ -93,58 +89,15 @@
 	return (10000000 / (period_factor * 4 * 10));
 }
 
-
 static void
-copy_mem_info(struct info_str *info, char *data, int len)
-{
-	if (info->pos + len > info->offset + info->length)
-		len = info->offset + info->length - info->pos;
-
-	if (info->pos + len < info->offset) {
-		info->pos += len;
-		return;
-	}
-
-	if (info->pos < info->offset) {
-		off_t partial;
-
-		partial = info->offset - info->pos;
-		data += partial;
-		info->pos += partial;
-		len  -= partial;
-	}
-
-	if (len > 0) {
-		memcpy(info->buffer, data, len);
-		info->pos += len;
-		info->buffer += len;
-	}
-}
-
-static int
-copy_info(struct info_str *info, char *fmt, ...)
-{
-	va_list args;
-	char buf[256];
-	int len;
-
-	va_start(args, fmt);
-	len = vsprintf(buf, fmt, args);
-	va_end(args);
-
-	copy_mem_info(info, buf, len);
-	return (len);
-}
-
-static void
-ahd_format_transinfo(struct info_str *info, struct ahd_transinfo *tinfo)
+ahd_format_transinfo(struct seq_file *m, struct ahd_transinfo *tinfo)
 {
 	u_int speed;
 	u_int freq;
 	u_int mb;
 
 	if (tinfo->period == AHD_PERIOD_UNKNOWN) {
-		copy_info(info, "Renegotiation Pending\n");
+		seq_printf(m, "Renegotiation Pending\n");
 		return;
 	}
         speed = 3300;
@@ -156,34 +109,34 @@
 	speed *= (0x01 << tinfo->width);
         mb = speed / 1000;
         if (mb > 0)
-		copy_info(info, "%d.%03dMB/s transfers", mb, speed % 1000);
+		seq_printf(m, "%d.%03dMB/s transfers", mb, speed % 1000);
         else
-		copy_info(info, "%dKB/s transfers", speed);
+		seq_printf(m, "%dKB/s transfers", speed);
 
 	if (freq != 0) {
 		int	printed_options;
 
 		printed_options = 0;
-		copy_info(info, " (%d.%03dMHz", freq / 1000, freq % 1000);
+		seq_printf(m, " (%d.%03dMHz", freq / 1000, freq % 1000);
 		if ((tinfo->ppr_options & MSG_EXT_PPR_RD_STRM) != 0) {
-			copy_info(info, " RDSTRM");
+			seq_printf(m, " RDSTRM");
 			printed_options++;
 		}
 		if ((tinfo->ppr_options & MSG_EXT_PPR_DT_REQ) != 0) {
-			copy_info(info, "%s", printed_options ? "|DT" : " DT");
+			seq_printf(m, "%s", printed_options ? "|DT" : " DT");
 			printed_options++;
 		}
 		if ((tinfo->ppr_options & MSG_EXT_PPR_IU_REQ) != 0) {
-			copy_info(info, "%s", printed_options ? "|IU" : " IU");
+			seq_printf(m, "%s", printed_options ? "|IU" : " IU");
 			printed_options++;
 		}
 		if ((tinfo->ppr_options & MSG_EXT_PPR_RTI) != 0) {
-			copy_info(info, "%s",
+			seq_printf(m, "%s",
 				  printed_options ? "|RTI" : " RTI");
 			printed_options++;
 		}
 		if ((tinfo->ppr_options & MSG_EXT_PPR_QAS_REQ) != 0) {
-			copy_info(info, "%s",
+			seq_printf(m, "%s",
 				  printed_options ? "|QAS" : " QAS");
 			printed_options++;
 		}
@@ -191,19 +144,19 @@
 
 	if (tinfo->width > 0) {
 		if (freq != 0) {
-			copy_info(info, ", ");
+			seq_printf(m, ", ");
 		} else {
-			copy_info(info, " (");
+			seq_printf(m, " (");
 		}
-		copy_info(info, "%dbit)", 8 * (0x01 << tinfo->width));
+		seq_printf(m, "%dbit)", 8 * (0x01 << tinfo->width));
 	} else if (freq != 0) {
-		copy_info(info, ")");
+		seq_printf(m, ")");
 	}
-	copy_info(info, "\n");
+	seq_printf(m, "\n");
 }
 
 static void
-ahd_dump_target_state(struct ahd_softc *ahd, struct info_str *info,
+ahd_dump_target_state(struct ahd_softc *ahd, struct seq_file *m,
 		      u_int our_id, char channel, u_int target_id)
 {
 	struct  scsi_target *starget;
@@ -213,17 +166,17 @@
 
 	tinfo = ahd_fetch_transinfo(ahd, channel, our_id,
 				    target_id, &tstate);
-	copy_info(info, "Target %d Negotiation Settings\n", target_id);
-	copy_info(info, "\tUser: ");
-	ahd_format_transinfo(info, &tinfo->user);
+	seq_printf(m, "Target %d Negotiation Settings\n", target_id);
+	seq_printf(m, "\tUser: ");
+	ahd_format_transinfo(m, &tinfo->user);
 	starget = ahd->platform_data->starget[target_id];
 	if (starget == NULL)
 		return;
 
-	copy_info(info, "\tGoal: ");
-	ahd_format_transinfo(info, &tinfo->goal);
-	copy_info(info, "\tCurr: ");
-	ahd_format_transinfo(info, &tinfo->curr);
+	seq_printf(m, "\tGoal: ");
+	ahd_format_transinfo(m, &tinfo->goal);
+	seq_printf(m, "\tCurr: ");
+	ahd_format_transinfo(m, &tinfo->curr);
 
 	for (lun = 0; lun < AHD_NUM_LUNS; lun++) {
 		struct scsi_device *dev;
@@ -233,29 +186,30 @@
 		if (dev == NULL)
 			continue;
 
-		ahd_dump_device_state(info, dev);
+		ahd_dump_device_state(m, dev);
 	}
 }
 
 static void
-ahd_dump_device_state(struct info_str *info, struct scsi_device *sdev)
+ahd_dump_device_state(struct seq_file *m, struct scsi_device *sdev)
 {
 	struct ahd_linux_device *dev = scsi_transport_device_data(sdev);
 
-	copy_info(info, "\tChannel %c Target %d Lun %d Settings\n",
+	seq_printf(m, "\tChannel %c Target %d Lun %d Settings\n",
 		  sdev->sdev_target->channel + 'A',
 		  sdev->sdev_target->id, sdev->lun);
 
-	copy_info(info, "\t\tCommands Queued %ld\n", dev->commands_issued);
-	copy_info(info, "\t\tCommands Active %d\n", dev->active);
-	copy_info(info, "\t\tCommand Openings %d\n", dev->openings);
-	copy_info(info, "\t\tMax Tagged Openings %d\n", dev->maxtags);
-	copy_info(info, "\t\tDevice Queue Frozen Count %d\n", dev->qfrozen);
+	seq_printf(m, "\t\tCommands Queued %ld\n", dev->commands_issued);
+	seq_printf(m, "\t\tCommands Active %d\n", dev->active);
+	seq_printf(m, "\t\tCommand Openings %d\n", dev->openings);
+	seq_printf(m, "\t\tMax Tagged Openings %d\n", dev->maxtags);
+	seq_printf(m, "\t\tDevice Queue Frozen Count %d\n", dev->qfrozen);
 }
 
-static int
-ahd_proc_write_seeprom(struct ahd_softc *ahd, char *buffer, int length)
+int
+ahd_proc_write_seeprom(struct Scsi_Host *shost, char *buffer, int length)
 {
+	struct	ahd_softc *ahd = *(struct ahd_softc **)shost->hostdata;
 	ahd_mode_state saved_modes;
 	int have_seeprom;
 	u_long s;
@@ -319,64 +273,45 @@
  * Return information to handle /proc support for the driver.
  */
 int
-ahd_linux_proc_info(struct Scsi_Host *shost, char *buffer, char **start,
-		    off_t offset, int length, int inout)
+ahd_linux_show_info(struct seq_file *m, struct Scsi_Host *shost)
 {
 	struct	ahd_softc *ahd = *(struct ahd_softc **)shost->hostdata;
-	struct	info_str info;
 	char	ahd_info[256];
 	u_int	max_targ;
 	u_int	i;
-	int	retval;
 
-	 /* Has data been written to the file? */ 
-	if (inout == TRUE) {
-		retval = ahd_proc_write_seeprom(ahd, buffer, length);
-		goto done;
-	}
-
-	if (start)
-		*start = buffer;
-
-	info.buffer	= buffer;
-	info.length	= length;
-	info.offset	= offset;
-	info.pos	= 0;
-
-	copy_info(&info, "Adaptec AIC79xx driver version: %s\n",
+	seq_printf(m, "Adaptec AIC79xx driver version: %s\n",
 		  AIC79XX_DRIVER_VERSION);
-	copy_info(&info, "%s\n", ahd->description);
+	seq_printf(m, "%s\n", ahd->description);
 	ahd_controller_info(ahd, ahd_info);
-	copy_info(&info, "%s\n", ahd_info);
-	copy_info(&info, "Allocated SCBs: %d, SG List Length: %d\n\n",
+	seq_printf(m, "%s\n", ahd_info);
+	seq_printf(m, "Allocated SCBs: %d, SG List Length: %d\n\n",
 		  ahd->scb_data.numscbs, AHD_NSEG);
 
 	max_targ = 16;
 
 	if (ahd->seep_config == NULL)
-		copy_info(&info, "No Serial EEPROM\n");
+		seq_printf(m, "No Serial EEPROM\n");
 	else {
-		copy_info(&info, "Serial EEPROM:\n");
+		seq_printf(m, "Serial EEPROM:\n");
 		for (i = 0; i < sizeof(*ahd->seep_config)/2; i++) {
 			if (((i % 8) == 0) && (i != 0)) {
-				copy_info(&info, "\n");
+				seq_printf(m, "\n");
 			}
-			copy_info(&info, "0x%.4x ",
+			seq_printf(m, "0x%.4x ",
 				  ((uint16_t*)ahd->seep_config)[i]);
 		}
-		copy_info(&info, "\n");
+		seq_printf(m, "\n");
 	}
-	copy_info(&info, "\n");
+	seq_printf(m, "\n");
 
 	if ((ahd->features & AHD_WIDE) == 0)
 		max_targ = 8;
 
 	for (i = 0; i < max_targ; i++) {
 
-		ahd_dump_target_state(ahd, &info, ahd->our_id, 'A',
+		ahd_dump_target_state(ahd, m, ahd->our_id, 'A',
 				      /*target_id*/i);
 	}
-	retval = info.pos > info.offset ? info.pos - info.offset : 0;
-done:
-	return (retval);
+	return 0;
 }
diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.c b/drivers/scsi/aic7xxx/aic7xxx_osm.c
index 5a477cd..c0c6258 100644
--- a/drivers/scsi/aic7xxx/aic7xxx_osm.c
+++ b/drivers/scsi/aic7xxx/aic7xxx_osm.c
@@ -803,7 +803,8 @@
 	.module			= THIS_MODULE,
 	.name			= "aic7xxx",
 	.proc_name		= "aic7xxx",
-	.proc_info		= ahc_linux_proc_info,
+	.show_info		= ahc_linux_show_info,
+	.write_info		= ahc_proc_write_seeprom,
 	.info			= ahc_linux_info,
 	.queuecommand		= ahc_linux_queue,
 	.eh_abort_handler	= ahc_linux_abort,
@@ -1631,10 +1632,8 @@
 	switch (code) {
 	case AC_TRANSFER_NEG:
 	{
-		char	buf[80];
 		struct	scsi_target *starget;
 		struct	ahc_linux_target *targ;
-		struct	info_str info;
 		struct	ahc_initiator_tinfo *tinfo;
 		struct	ahc_tmode_tstate *tstate;
 		int	target_offset;
@@ -1642,10 +1641,6 @@
 
 		BUG_ON(target == CAM_TARGET_WILDCARD);
 
-		info.buffer = buf;
-		info.length = sizeof(buf);
-		info.offset = 0;
-		info.pos = 0;
 		tinfo = ahc_fetch_transinfo(ahc, channel,
 						channel == 'A' ? ahc->our_id
 							       : ahc->our_id_b,
diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.h b/drivers/scsi/aic7xxx/aic7xxx_osm.h
index bca0fb83..bc4cca9 100644
--- a/drivers/scsi/aic7xxx/aic7xxx_osm.h
+++ b/drivers/scsi/aic7xxx/aic7xxx_osm.h
@@ -383,14 +383,6 @@
 int		ahc_linux_register_host(struct ahc_softc *,
 					struct scsi_host_template *);
 
-/*************************** Pretty Printing **********************************/
-struct info_str {
-	char *buffer;
-	int length;
-	off_t offset;
-	int pos;
-};
-
 /******************************** Locking *************************************/
 /* Lock protecting internal data structures */
 
@@ -523,8 +515,8 @@
 }
 
 /**************************** Proc FS Support *********************************/
-int	ahc_linux_proc_info(struct Scsi_Host *, char *, char **,
-			    off_t, int, int);
+int	ahc_proc_write_seeprom(struct Scsi_Host *, char *, int);
+int	ahc_linux_show_info(struct seq_file *, struct Scsi_Host *);
 
 /*************************** Domain Validation ********************************/
 /*********************** Transaction Access Wrappers *************************/
diff --git a/drivers/scsi/aic7xxx/aic7xxx_proc.c b/drivers/scsi/aic7xxx/aic7xxx_proc.c
index f2525f8..383a3d1 100644
--- a/drivers/scsi/aic7xxx/aic7xxx_proc.c
+++ b/drivers/scsi/aic7xxx/aic7xxx_proc.c
@@ -43,16 +43,12 @@
 #include "aic7xxx_inline.h"
 #include "aic7xxx_93cx6.h"
 
-static void	copy_mem_info(struct info_str *info, char *data, int len);
-static int	copy_info(struct info_str *info, char *fmt, ...);
 static void	ahc_dump_target_state(struct ahc_softc *ahc,
-				      struct info_str *info,
+				      struct seq_file *m,
 				      u_int our_id, char channel,
 				      u_int target_id, u_int target_offset);
-static void	ahc_dump_device_state(struct info_str *info,
+static void	ahc_dump_device_state(struct seq_file *m,
 				      struct scsi_device *dev);
-static int	ahc_proc_write_seeprom(struct ahc_softc *ahc,
-				       char *buffer, int length);
 
 /*
  * Table of syncrates that don't follow the "divisible by 4"
@@ -94,51 +90,8 @@
 	return (10000000 / (period_factor * 4 * 10));
 }
 
-
 static void
-copy_mem_info(struct info_str *info, char *data, int len)
-{
-	if (info->pos + len > info->offset + info->length)
-		len = info->offset + info->length - info->pos;
-
-	if (info->pos + len < info->offset) {
-		info->pos += len;
-		return;
-	}
-
-	if (info->pos < info->offset) {
-		off_t partial;
-
-		partial = info->offset - info->pos;
-		data += partial;
-		info->pos += partial;
-		len  -= partial;
-	}
-
-	if (len > 0) {
-		memcpy(info->buffer, data, len);
-		info->pos += len;
-		info->buffer += len;
-	}
-}
-
-static int
-copy_info(struct info_str *info, char *fmt, ...)
-{
-	va_list args;
-	char buf[256];
-	int len;
-
-	va_start(args, fmt);
-	len = vsprintf(buf, fmt, args);
-	va_end(args);
-
-	copy_mem_info(info, buf, len);
-	return (len);
-}
-
-static void
-ahc_format_transinfo(struct info_str *info, struct ahc_transinfo *tinfo)
+ahc_format_transinfo(struct seq_file *m, struct ahc_transinfo *tinfo)
 {
 	u_int speed;
 	u_int freq;
@@ -153,12 +106,12 @@
 	speed *= (0x01 << tinfo->width);
         mb = speed / 1000;
         if (mb > 0)
-		copy_info(info, "%d.%03dMB/s transfers", mb, speed % 1000);
+		seq_printf(m, "%d.%03dMB/s transfers", mb, speed % 1000);
         else
-		copy_info(info, "%dKB/s transfers", speed);
+		seq_printf(m, "%dKB/s transfers", speed);
 
 	if (freq != 0) {
-		copy_info(info, " (%d.%03dMHz%s, offset %d",
+		seq_printf(m, " (%d.%03dMHz%s, offset %d",
 			 freq / 1000, freq % 1000,
 			 (tinfo->ppr_options & MSG_EXT_PPR_DT_REQ) != 0
 			 ? " DT" : "", tinfo->offset);
@@ -166,19 +119,19 @@
 
 	if (tinfo->width > 0) {
 		if (freq != 0) {
-			copy_info(info, ", ");
+			seq_printf(m, ", ");
 		} else {
-			copy_info(info, " (");
+			seq_printf(m, " (");
 		}
-		copy_info(info, "%dbit)", 8 * (0x01 << tinfo->width));
+		seq_printf(m, "%dbit)", 8 * (0x01 << tinfo->width));
 	} else if (freq != 0) {
-		copy_info(info, ")");
+		seq_printf(m, ")");
 	}
-	copy_info(info, "\n");
+	seq_printf(m, "\n");
 }
 
 static void
-ahc_dump_target_state(struct ahc_softc *ahc, struct info_str *info,
+ahc_dump_target_state(struct ahc_softc *ahc, struct seq_file *m,
 		      u_int our_id, char channel, u_int target_id,
 		      u_int target_offset)
 {
@@ -190,18 +143,18 @@
 	tinfo = ahc_fetch_transinfo(ahc, channel, our_id,
 				    target_id, &tstate);
 	if ((ahc->features & AHC_TWIN) != 0)
-		copy_info(info, "Channel %c ", channel);
-	copy_info(info, "Target %d Negotiation Settings\n", target_id);
-	copy_info(info, "\tUser: ");
-	ahc_format_transinfo(info, &tinfo->user);
+		seq_printf(m, "Channel %c ", channel);
+	seq_printf(m, "Target %d Negotiation Settings\n", target_id);
+	seq_printf(m, "\tUser: ");
+	ahc_format_transinfo(m, &tinfo->user);
 	starget = ahc->platform_data->starget[target_offset];
 	if (!starget)
 		return;
 
-	copy_info(info, "\tGoal: ");
-	ahc_format_transinfo(info, &tinfo->goal);
-	copy_info(info, "\tCurr: ");
-	ahc_format_transinfo(info, &tinfo->curr);
+	seq_printf(m, "\tGoal: ");
+	ahc_format_transinfo(m, &tinfo->goal);
+	seq_printf(m, "\tCurr: ");
+	ahc_format_transinfo(m, &tinfo->curr);
 
 	for (lun = 0; lun < AHC_NUM_LUNS; lun++) {
 		struct scsi_device *sdev;
@@ -211,29 +164,30 @@
 		if (sdev == NULL)
 			continue;
 
-		ahc_dump_device_state(info, sdev);
+		ahc_dump_device_state(m, sdev);
 	}
 }
 
 static void
-ahc_dump_device_state(struct info_str *info, struct scsi_device *sdev)
+ahc_dump_device_state(struct seq_file *m, struct scsi_device *sdev)
 {
 	struct ahc_linux_device *dev = scsi_transport_device_data(sdev);
 
-	copy_info(info, "\tChannel %c Target %d Lun %d Settings\n",
+	seq_printf(m, "\tChannel %c Target %d Lun %d Settings\n",
 		  sdev->sdev_target->channel + 'A',
 		  sdev->sdev_target->id, sdev->lun);
 
-	copy_info(info, "\t\tCommands Queued %ld\n", dev->commands_issued);
-	copy_info(info, "\t\tCommands Active %d\n", dev->active);
-	copy_info(info, "\t\tCommand Openings %d\n", dev->openings);
-	copy_info(info, "\t\tMax Tagged Openings %d\n", dev->maxtags);
-	copy_info(info, "\t\tDevice Queue Frozen Count %d\n", dev->qfrozen);
+	seq_printf(m, "\t\tCommands Queued %ld\n", dev->commands_issued);
+	seq_printf(m, "\t\tCommands Active %d\n", dev->active);
+	seq_printf(m, "\t\tCommand Openings %d\n", dev->openings);
+	seq_printf(m, "\t\tMax Tagged Openings %d\n", dev->maxtags);
+	seq_printf(m, "\t\tDevice Queue Frozen Count %d\n", dev->qfrozen);
 }
 
-static int
-ahc_proc_write_seeprom(struct ahc_softc *ahc, char *buffer, int length)
+int
+ahc_proc_write_seeprom(struct Scsi_Host *shost, char *buffer, int length)
 {
+	struct	ahc_softc *ahc = *(struct ahc_softc **)shost->hostdata;
 	struct seeprom_descriptor sd;
 	int have_seeprom;
 	u_long s;
@@ -332,53 +286,36 @@
  * Return information to handle /proc support for the driver.
  */
 int
-ahc_linux_proc_info(struct Scsi_Host *shost, char *buffer, char **start,
-		    off_t offset, int length, int inout)
+ahc_linux_show_info(struct seq_file *m, struct Scsi_Host *shost)
 {
 	struct	ahc_softc *ahc = *(struct ahc_softc **)shost->hostdata;
-	struct	info_str info;
 	char	ahc_info[256];
 	u_int	max_targ;
 	u_int	i;
-	int	retval;
 
-	 /* Has data been written to the file? */ 
-	if (inout == TRUE) {
-		retval = ahc_proc_write_seeprom(ahc, buffer, length);
-		goto done;
-	}
-
-	if (start)
-		*start = buffer;
-
-	info.buffer	= buffer;
-	info.length	= length;
-	info.offset	= offset;
-	info.pos	= 0;
-
-	copy_info(&info, "Adaptec AIC7xxx driver version: %s\n",
+	seq_printf(m, "Adaptec AIC7xxx driver version: %s\n",
 		  AIC7XXX_DRIVER_VERSION);
-	copy_info(&info, "%s\n", ahc->description);
+	seq_printf(m, "%s\n", ahc->description);
 	ahc_controller_info(ahc, ahc_info);
-	copy_info(&info, "%s\n", ahc_info);
-	copy_info(&info, "Allocated SCBs: %d, SG List Length: %d\n\n",
+	seq_printf(m, "%s\n", ahc_info);
+	seq_printf(m, "Allocated SCBs: %d, SG List Length: %d\n\n",
 		  ahc->scb_data->numscbs, AHC_NSEG);
 
 
 	if (ahc->seep_config == NULL)
-		copy_info(&info, "No Serial EEPROM\n");
+		seq_printf(m, "No Serial EEPROM\n");
 	else {
-		copy_info(&info, "Serial EEPROM:\n");
+		seq_printf(m, "Serial EEPROM:\n");
 		for (i = 0; i < sizeof(*ahc->seep_config)/2; i++) {
 			if (((i % 8) == 0) && (i != 0)) {
-				copy_info(&info, "\n");
+				seq_printf(m, "\n");
 			}
-			copy_info(&info, "0x%.4x ",
+			seq_printf(m, "0x%.4x ",
 				  ((uint16_t*)ahc->seep_config)[i]);
 		}
-		copy_info(&info, "\n");
+		seq_printf(m, "\n");
 	}
-	copy_info(&info, "\n");
+	seq_printf(m, "\n");
 
 	max_targ = 16;
 	if ((ahc->features & (AHC_WIDE|AHC_TWIN)) == 0)
@@ -398,10 +335,8 @@
 			target_id = i % 8;
 		}
 
-		ahc_dump_target_state(ahc, &info, our_id,
+		ahc_dump_target_state(ahc, m, our_id,
 				      channel, target_id, i);
 	}
-	retval = info.pos > info.offset ? info.pos - info.offset : 0;
-done:
-	return (retval);
+	return 0;
 }
diff --git a/drivers/scsi/aic7xxx_old.c b/drivers/scsi/aic7xxx_old.c
index 5b212f0..33ec9c6 100644
--- a/drivers/scsi/aic7xxx_old.c
+++ b/drivers/scsi/aic7xxx_old.c
@@ -11108,7 +11108,7 @@
 
 
 static struct scsi_host_template driver_template = {
-	.proc_info		= aic7xxx_proc_info,
+	.show_info		= aic7xxx_show_info,
 	.detect			= aic7xxx_detect,
 	.release		= aic7xxx_release,
 	.info			= aic7xxx_info,	
diff --git a/drivers/scsi/aic7xxx_old/aic7xxx_proc.c b/drivers/scsi/aic7xxx_old/aic7xxx_proc.c
index b07e4f0..976f45c 100644
--- a/drivers/scsi/aic7xxx_old/aic7xxx_proc.c
+++ b/drivers/scsi/aic7xxx_old/aic7xxx_proc.c
@@ -30,62 +30,23 @@
  *-M*************************************************************************/
 
 
-#define	BLS	(&aic7xxx_buffer[size])
 #define HDRB \
 "               0 - 4K   4 - 16K   16 - 64K  64 - 256K  256K - 1M        1M+"
 
-#ifdef PROC_DEBUG
-extern int vsprintf(char *, const char *, va_list);
-
-static void
-proc_debug(const char *fmt, ...)
-{
-  va_list ap;
-  char buf[256];
-
-  va_start(ap, fmt);
-  vsprintf(buf, fmt, ap);
-  printk(buf);
-  va_end(ap);
-}
-#else /* PROC_DEBUG */
-#  define proc_debug(fmt, args...)
-#endif /* PROC_DEBUG */
-
-static int aic7xxx_buffer_size = 0;
-static char *aic7xxx_buffer = NULL;
-
 
 /*+F*************************************************************************
  * Function:
- *   aic7xxx_set_info
- *
- * Description:
- *   Set parameters for the driver from the /proc filesystem.
- *-F*************************************************************************/
-static int
-aic7xxx_set_info(char *buffer, int length, struct Scsi_Host *HBAptr)
-{
-  proc_debug("aic7xxx_set_info(): %s\n", buffer);
-  return (-ENOSYS);  /* Currently this is a no-op */
-}
-
-
-/*+F*************************************************************************
- * Function:
- *   aic7xxx_proc_info
+ *   aic7xxx_show_info
  *
  * Description:
  *   Return information to handle /proc support for the driver.
  *-F*************************************************************************/
 int
-aic7xxx_proc_info ( struct Scsi_Host *HBAptr, char *buffer, char **start, off_t offset, int length, 
-                    int inout)
+aic7xxx_show_info(struct seq_file *m, struct Scsi_Host *HBAptr)
 {
   struct aic7xxx_host *p;
   struct aic_dev_data *aic_dev;
   struct scsi_device *sdptr;
-  int    size = 0;
   unsigned char i;
   unsigned char tindex;
 
@@ -94,66 +55,21 @@
 
   if (!p)
   {
-    size += sprintf(buffer, "Can't find adapter for host number %d\n", HBAptr->host_no);
-    if (size > length)
-    {
-      return (size);
-    }
-    else
-    {
-      return (length);
-    }
-  }
-
-  if (inout == TRUE) /* Has data been written to the file? */ 
-  {
-    return (aic7xxx_set_info(buffer, length, HBAptr));
+    seq_printf(m, "Can't find adapter for host number %d\n", HBAptr->host_no);
+    return 0;
   }
 
   p = (struct aic7xxx_host *) HBAptr->hostdata;
 
-  /*
-   * It takes roughly 1K of space to hold all relevant card info, not
-   * counting any proc stats, so we start out with a 1.5k buffer size and
-   * if proc_stats is defined, then we sweep the stats structure to see
-   * how many drives we will be printing out for and add 384 bytes per
-   * device with active stats.
-   *
-   * Hmmmm...that 1.5k seems to keep growing as items get added so they
-   * can be easily viewed for debugging purposes.  So, we bumped that
-   * 1.5k to 4k so we can quit having to bump it all the time.
-   */
-
-  size = 4096;
-  list_for_each_entry(aic_dev, &p->aic_devs, list)
-    size += 512;
-  if (aic7xxx_buffer_size != size)
-  {
-    if (aic7xxx_buffer != NULL) 
-    {
-      kfree(aic7xxx_buffer);
-      aic7xxx_buffer_size = 0;
-    }
-    aic7xxx_buffer = kmalloc(size, GFP_KERNEL);
-  }
-  if (aic7xxx_buffer == NULL)
-  {
-    size = sprintf(buffer, "AIC7xxx - kmalloc error at line %d\n",
-        __LINE__);
-    return size;
-  }
-  aic7xxx_buffer_size = size;
-
-  size = 0;
-  size += sprintf(BLS, "Adaptec AIC7xxx driver version: ");
-  size += sprintf(BLS, "%s/", AIC7XXX_C_VERSION);
-  size += sprintf(BLS, "%s", AIC7XXX_H_VERSION);
-  size += sprintf(BLS, "\n");
-  size += sprintf(BLS, "Adapter Configuration:\n");
-  size += sprintf(BLS, "           SCSI Adapter: %s\n",
+  seq_printf(m, "Adaptec AIC7xxx driver version: ");
+  seq_printf(m, "%s/", AIC7XXX_C_VERSION);
+  seq_printf(m, "%s", AIC7XXX_H_VERSION);
+  seq_printf(m, "\n");
+  seq_printf(m, "Adapter Configuration:\n");
+  seq_printf(m, "           SCSI Adapter: %s\n",
       board_names[p->board_name_index]);
   if (p->flags & AHC_TWIN)
-    size += sprintf(BLS, "                         Twin Channel Controller ");
+    seq_printf(m, "                         Twin Channel Controller ");
   else
   {
     char *channel = "";
@@ -184,86 +100,86 @@
       ultra = "Ultra-2 LVD/SE ";
     else if (p->features & AHC_ULTRA)
       ultra = "Ultra ";
-    size += sprintf(BLS, "                           %s%sController%s ",
+    seq_printf(m, "                           %s%sController%s ",
       ultra, wide, channel);
   }
   switch(p->chip & ~AHC_CHIPID_MASK)
   {
     case AHC_VL:
-      size += sprintf(BLS, "at VLB slot %d\n", p->pci_device_fn);
+      seq_printf(m, "at VLB slot %d\n", p->pci_device_fn);
       break;
     case AHC_EISA:
-      size += sprintf(BLS, "at EISA slot %d\n", p->pci_device_fn);
+      seq_printf(m, "at EISA slot %d\n", p->pci_device_fn);
       break;
     default:
-      size += sprintf(BLS, "at PCI %d/%d/%d\n", p->pci_bus,
+      seq_printf(m, "at PCI %d/%d/%d\n", p->pci_bus,
         PCI_SLOT(p->pci_device_fn), PCI_FUNC(p->pci_device_fn));
       break;
   }
   if( !(p->maddr) )
   {
-    size += sprintf(BLS, "    Programmed I/O Base: %lx\n", p->base);
+    seq_printf(m, "    Programmed I/O Base: %lx\n", p->base);
   }
   else
   {
-    size += sprintf(BLS, "    PCI MMAPed I/O Base: 0x%lx\n", p->mbase);
+    seq_printf(m, "    PCI MMAPed I/O Base: 0x%lx\n", p->mbase);
   }
   if( (p->chip & (AHC_VL | AHC_EISA)) )
   {
-    size += sprintf(BLS, "    BIOS Memory Address: 0x%08x\n", p->bios_address);
+    seq_printf(m, "    BIOS Memory Address: 0x%08x\n", p->bios_address);
   }
-  size += sprintf(BLS, " Adapter SEEPROM Config: %s\n",
+  seq_printf(m, " Adapter SEEPROM Config: %s\n",
           (p->flags & AHC_SEEPROM_FOUND) ? "SEEPROM found and used." :
          ((p->flags & AHC_USEDEFAULTS) ? "SEEPROM not found, using defaults." :
            "SEEPROM not found, using leftover BIOS values.") );
-  size += sprintf(BLS, "      Adaptec SCSI BIOS: %s\n",
+  seq_printf(m, "      Adaptec SCSI BIOS: %s\n",
           (p->flags & AHC_BIOS_ENABLED) ? "Enabled" : "Disabled");
-  size += sprintf(BLS, "                    IRQ: %d\n", HBAptr->irq);
-  size += sprintf(BLS, "                   SCBs: Active %d, Max Active %d,\n",
+  seq_printf(m, "                    IRQ: %d\n", HBAptr->irq);
+  seq_printf(m, "                   SCBs: Active %d, Max Active %d,\n",
             p->activescbs, p->max_activescbs);
-  size += sprintf(BLS, "                         Allocated %d, HW %d, "
+  seq_printf(m, "                         Allocated %d, HW %d, "
             "Page %d\n", p->scb_data->numscbs, p->scb_data->maxhscbs,
             p->scb_data->maxscbs);
   if (p->flags & AHC_EXTERNAL_SRAM)
-    size += sprintf(BLS, "                         Using External SCB SRAM\n");
-  size += sprintf(BLS, "             Interrupts: %ld", p->isr_count);
+    seq_printf(m, "                         Using External SCB SRAM\n");
+  seq_printf(m, "             Interrupts: %ld", p->isr_count);
   if (p->chip & AHC_EISA)
   {
-    size += sprintf(BLS, " %s\n",
+    seq_printf(m, " %s\n",
         (p->pause & IRQMS) ? "(Level Sensitive)" : "(Edge Triggered)");
   }
   else
   {
-    size += sprintf(BLS, "\n");
+    seq_printf(m, "\n");
   }
-  size += sprintf(BLS, "      BIOS Control Word: 0x%04x\n",
+  seq_printf(m, "      BIOS Control Word: 0x%04x\n",
             p->bios_control);
-  size += sprintf(BLS, "   Adapter Control Word: 0x%04x\n",
+  seq_printf(m, "   Adapter Control Word: 0x%04x\n",
             p->adapter_control);
-  size += sprintf(BLS, "   Extended Translation: %sabled\n",
+  seq_printf(m, "   Extended Translation: %sabled\n",
       (p->flags & AHC_EXTEND_TRANS_A) ? "En" : "Dis");
-  size += sprintf(BLS, "Disconnect Enable Flags: 0x%04x\n", p->discenable);
+  seq_printf(m, "Disconnect Enable Flags: 0x%04x\n", p->discenable);
   if (p->features & (AHC_ULTRA | AHC_ULTRA2))
   {
-    size += sprintf(BLS, "     Ultra Enable Flags: 0x%04x\n", p->ultraenb);
+    seq_printf(m, "     Ultra Enable Flags: 0x%04x\n", p->ultraenb);
   }
-  size += sprintf(BLS, "Default Tag Queue Depth: %d\n", aic7xxx_default_queue_depth);
-  size += sprintf(BLS, "    Tagged Queue By Device array for aic7xxx host "
+  seq_printf(m, "Default Tag Queue Depth: %d\n", aic7xxx_default_queue_depth);
+  seq_printf(m, "    Tagged Queue By Device array for aic7xxx host "
                        "instance %d:\n", p->instance);
-  size += sprintf(BLS, "      {");
+  seq_printf(m, "      {");
   for(i=0; i < (MAX_TARGETS - 1); i++)
-    size += sprintf(BLS, "%d,",aic7xxx_tag_info[p->instance].tag_commands[i]);
-  size += sprintf(BLS, "%d}\n",aic7xxx_tag_info[p->instance].tag_commands[i]);
+    seq_printf(m, "%d,",aic7xxx_tag_info[p->instance].tag_commands[i]);
+  seq_printf(m, "%d}\n",aic7xxx_tag_info[p->instance].tag_commands[i]);
 
-  size += sprintf(BLS, "\n");
-  size += sprintf(BLS, "Statistics:\n\n");
+  seq_printf(m, "\n");
+  seq_printf(m, "Statistics:\n\n");
   list_for_each_entry(aic_dev, &p->aic_devs, list)
   {
     sdptr = aic_dev->SDptr;
     tindex = sdptr->channel << 3 | sdptr->id;
-    size += sprintf(BLS, "(scsi%d:%d:%d:%d)\n",
+    seq_printf(m, "(scsi%d:%d:%d:%d)\n",
         p->host_no, sdptr->channel, sdptr->id, sdptr->lun);
-    size += sprintf(BLS, "  Device using %s/%s",
+    seq_printf(m, "  Device using %s/%s",
           (aic_dev->cur.width == MSG_EXT_WDTR_BUS_16_BIT) ?
           "Wide" : "Narrow",
           (aic_dev->cur.offset != 0) ?
@@ -279,78 +195,59 @@
       sync_rate = aic7xxx_find_syncrate(p, &period, 0, &options);
       if (sync_rate != NULL)
       {
-        size += sprintf(BLS, "%s MByte/sec, offset %d\n",
+        seq_printf(m, "%s MByte/sec, offset %d\n",
                         sync_rate->rate[rate],
                         aic_dev->cur.offset );
       }
       else
       {
-        size += sprintf(BLS, "3.3 MByte/sec, offset %d\n",
+        seq_printf(m, "3.3 MByte/sec, offset %d\n",
                         aic_dev->cur.offset );
       }
     }
-    size += sprintf(BLS, "  Transinfo settings: ");
-    size += sprintf(BLS, "current(%d/%d/%d/%d), ",
+    seq_printf(m, "  Transinfo settings: ");
+    seq_printf(m, "current(%d/%d/%d/%d), ",
                     aic_dev->cur.period,
                     aic_dev->cur.offset,
                     aic_dev->cur.width,
                     aic_dev->cur.options);
-    size += sprintf(BLS, "goal(%d/%d/%d/%d), ",
+    seq_printf(m, "goal(%d/%d/%d/%d), ",
                     aic_dev->goal.period,
                     aic_dev->goal.offset,
                     aic_dev->goal.width,
                     aic_dev->goal.options);
-    size += sprintf(BLS, "user(%d/%d/%d/%d)\n",
+    seq_printf(m, "user(%d/%d/%d/%d)\n",
                     p->user[tindex].period,
                     p->user[tindex].offset,
                     p->user[tindex].width,
                     p->user[tindex].options);
     if(sdptr->simple_tags)
     {
-      size += sprintf(BLS, "  Tagged Command Queueing Enabled, Ordered Tags %s, Depth %d/%d\n", sdptr->ordered_tags ? "Enabled" : "Disabled", sdptr->queue_depth, aic_dev->max_q_depth);
+      seq_printf(m, "  Tagged Command Queueing Enabled, Ordered Tags %s, Depth %d/%d\n", sdptr->ordered_tags ? "Enabled" : "Disabled", sdptr->queue_depth, aic_dev->max_q_depth);
     }
     if(aic_dev->barrier_total)
-      size += sprintf(BLS, "  Total transfers %ld:\n    (%ld/%ld/%ld/%ld reads/writes/REQ_BARRIER/Ordered Tags)\n",
+      seq_printf(m, "  Total transfers %ld:\n    (%ld/%ld/%ld/%ld reads/writes/REQ_BARRIER/Ordered Tags)\n",
         aic_dev->r_total+aic_dev->w_total, aic_dev->r_total, aic_dev->w_total,
         aic_dev->barrier_total, aic_dev->ordered_total);
     else
-      size += sprintf(BLS, "  Total transfers %ld:\n    (%ld/%ld reads/writes)\n",
+      seq_printf(m, "  Total transfers %ld:\n    (%ld/%ld reads/writes)\n",
         aic_dev->r_total+aic_dev->w_total, aic_dev->r_total, aic_dev->w_total);
-    size += sprintf(BLS, "%s\n", HDRB);
-    size += sprintf(BLS, "   Reads:");
+    seq_printf(m, "%s\n", HDRB);
+    seq_printf(m, "   Reads:");
     for (i = 0; i < ARRAY_SIZE(aic_dev->r_bins); i++)
     {
-      size += sprintf(BLS, " %10ld", aic_dev->r_bins[i]);
+      seq_printf(m, " %10ld", aic_dev->r_bins[i]);
     }
-    size += sprintf(BLS, "\n");
-    size += sprintf(BLS, "  Writes:");
+    seq_printf(m, "\n");
+    seq_printf(m, "  Writes:");
     for (i = 0; i < ARRAY_SIZE(aic_dev->w_bins); i++)
     {
-      size += sprintf(BLS, " %10ld", aic_dev->w_bins[i]);
+      seq_printf(m, " %10ld", aic_dev->w_bins[i]);
     }
-    size += sprintf(BLS, "\n");
-    size += sprintf(BLS, "\n\n");
+    seq_printf(m, "\n");
+    seq_printf(m, "\n\n");
   }
-  if (size >= aic7xxx_buffer_size)
-  {
-    printk(KERN_WARNING "aic7xxx: Overflow in aic7xxx_proc.c\n");
-  }
-
-  if (offset > size - 1)
-  {
-    kfree(aic7xxx_buffer);
-    aic7xxx_buffer = NULL;
-    aic7xxx_buffer_size = length = 0;
-    *start = NULL;
-  }
-  else
-  {
-    *start = buffer;
-    length = min_t(int, length, size - offset);
-    memcpy(buffer, &aic7xxx_buffer[offset], length);
-  }
-
-  return (length);
+  return 0;
 }
 
 /*
diff --git a/drivers/scsi/arm/acornscsi.c b/drivers/scsi/arm/acornscsi.c
index 3e1172a..09ba186 100644
--- a/drivers/scsi/arm/acornscsi.c
+++ b/drivers/scsi/arm/acornscsi.c
@@ -2836,20 +2836,15 @@
     return string;
 }
 
-int acornscsi_proc_info(struct Scsi_Host *instance, char *buffer, char **start, off_t offset,
-			int length, int inout)
+static int acornscsi_show_info(struct seq_file *m, struct Scsi_Host *instance)
 {
-    int pos, begin = 0, devidx;
+    int devidx;
     struct scsi_device *scd;
     AS_Host *host;
-    char *p = buffer;
-
-    if (inout == 1)
-	return -EINVAL;
 
     host  = (AS_Host *)instance->hostdata;
     
-    p += sprintf(p, "AcornSCSI driver v%d.%d.%d"
+    seq_printf(m, "AcornSCSI driver v%d.%d.%d"
 #ifdef CONFIG_SCSI_ACORNSCSI_SYNC
     " SYNC"
 #endif
@@ -2864,14 +2859,14 @@
 #endif
 		"\n\n", VER_MAJOR, VER_MINOR, VER_PATCH);
 
-    p += sprintf(p,	"SBIC: WD33C93A  Address: %p    IRQ : %d\n",
+    seq_printf(m,	"SBIC: WD33C93A  Address: %p    IRQ : %d\n",
 			host->base + SBIC_REGIDX, host->scsi.irq);
 #ifdef USE_DMAC
-    p += sprintf(p,	"DMAC: uPC71071  Address: %p  IRQ : %d\n\n",
+    seq_printf(m,	"DMAC: uPC71071  Address: %p  IRQ : %d\n\n",
 			host->base + DMAC_OFFSET, host->scsi.irq);
 #endif
 
-    p += sprintf(p,	"Statistics:\n"
+    seq_printf(m,	"Statistics:\n"
 			"Queued commands: %-10u    Issued commands: %-10u\n"
 			"Done commands  : %-10u    Reads          : %-10u\n"
 			"Writes         : %-10u    Others         : %-10u\n"
@@ -2886,7 +2881,7 @@
     for (devidx = 0; devidx < 9; devidx ++) {
 	unsigned int statptr, prev;
 
-	p += sprintf(p, "\n%c:", devidx == 8 ? 'H' : ('0' + devidx));
+	seq_printf(m, "\n%c:", devidx == 8 ? 'H' : ('0' + devidx));
 	statptr = host->status_ptr[devidx] - 10;
 
 	if ((signed int)statptr < 0)
@@ -2896,7 +2891,7 @@
 
 	for (; statptr != host->status_ptr[devidx]; statptr = (statptr + 1) & (STATUS_BUFFER_SIZE - 1)) {
 	    if (host->status[devidx][statptr].when) {
-		p += sprintf(p, "%c%02X:%02X+%2ld",
+		seq_printf(m, "%c%02X:%02X+%2ld",
 			host->status[devidx][statptr].irq ? '-' : ' ',
 			host->status[devidx][statptr].ph,
 			host->status[devidx][statptr].ssr,
@@ -2907,51 +2902,32 @@
 	}
     }
 
-    p += sprintf(p, "\nAttached devices:\n");
+    seq_printf(m, "\nAttached devices:\n");
 
     shost_for_each_device(scd, instance) {
-	p += sprintf(p, "Device/Lun TaggedQ      Sync\n");
-	p += sprintf(p, "     %d/%d   ", scd->id, scd->lun);
+	seq_printf(m, "Device/Lun TaggedQ      Sync\n");
+	seq_printf(m, "     %d/%d   ", scd->id, scd->lun);
 	if (scd->tagged_supported)
-		p += sprintf(p, "%3sabled(%3d) ",
+		seq_printf(m, "%3sabled(%3d) ",
 			     scd->simple_tags ? "en" : "dis",
 			     scd->current_tag);
 	else
-		p += sprintf(p, "unsupported  ");
+		seq_printf(m, "unsupported  ");
 
 	if (host->device[scd->id].sync_xfer & 15)
-		p += sprintf(p, "offset %d, %d ns\n",
+		seq_printf(m, "offset %d, %d ns\n",
 			     host->device[scd->id].sync_xfer & 15,
 			     acornscsi_getperiod(host->device[scd->id].sync_xfer));
 	else
-		p += sprintf(p, "async\n");
+		seq_printf(m, "async\n");
 
-	pos = p - buffer;
-	if (pos + begin < offset) {
-	    begin += pos;
-	    p = buffer;
-	}
-	pos = p - buffer;
-	if (pos + begin > offset + length) {
-	    scsi_device_put(scd);
-	    break;
-	}
     }
-
-    pos = p - buffer;
-
-    *start = buffer + (offset - begin);
-    pos -= offset - begin;
-
-    if (pos > length)
-	pos = length;
-
-    return pos;
+    return 0;
 }
 
 static struct scsi_host_template acornscsi_template = {
 	.module			= THIS_MODULE,
-	.proc_info		= acornscsi_proc_info,
+	.show_info		= acornscsi_show_info,
 	.name			= "AcornSCSI",
 	.info			= acornscsi_info,
 	.queuecommand		= acornscsi_queuecmd,
diff --git a/drivers/scsi/arm/arxescsi.c b/drivers/scsi/arm/arxescsi.c
index 9274510..32d2321 100644
--- a/drivers/scsi/arm/arxescsi.c
+++ b/drivers/scsi/arm/arxescsi.c
@@ -220,47 +220,21 @@
 	return string;
 }
 
-/*
- * Function: int arxescsi_proc_info(char *buffer, char **start, off_t offset,
- *					 int length, int host_no, int inout)
- * Purpose : Return information about the driver to a user process accessing
- *	     the /proc filesystem.
- * Params  : buffer - a buffer to write information to
- *	     start  - a pointer into this buffer set by this routine to the start
- *		      of the required information.
- *	     offset - offset into information that we have read up to.
- *	     length - length of buffer
- *	     host_no - host number to return information for
- *	     inout  - 0 for reading, 1 for writing.
- * Returns : length of data written to buffer.
- */
 static int
-arxescsi_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t offset, int length,
-		   int inout)
+arxescsi_show_info(struct seq_file *m, struct Scsi_Host *host)
 {
 	struct arxescsi_info *info;
-	char *p = buffer;
-	int pos;
-
 	info = (struct arxescsi_info *)host->hostdata;
-	if (inout == 1)
-		return -EINVAL;
 
-	p += sprintf(p, "ARXE 16-bit SCSI driver v%s\n", VERSION);
-	p += fas216_print_host(&info->info, p);
-	p += fas216_print_stats(&info->info, p);
-	p += fas216_print_devices(&info->info, p);
-
-	*start = buffer + offset;
-	pos = p - buffer - offset;
-	if (pos > length)
-		pos = length;
-
-	return pos;
+	seq_printf(m, "ARXE 16-bit SCSI driver v%s\n", VERSION);
+	fas216_print_host(&info->info, m);
+	fas216_print_stats(&info->info, m);
+	fas216_print_devices(&info->info, m);
+	return 0;
 }
 
 static struct scsi_host_template arxescsi_template = {
-	.proc_info			= arxescsi_proc_info,
+	.show_info			= arxescsi_show_info,
 	.name				= "ARXE SCSI card",
 	.info				= arxescsi_info,
 	.queuecommand			= fas216_noqueue_command,
diff --git a/drivers/scsi/arm/cumana_1.c b/drivers/scsi/arm/cumana_1.c
index c93938b..b679778 100644
--- a/drivers/scsi/arm/cumana_1.c
+++ b/drivers/scsi/arm/cumana_1.c
@@ -30,7 +30,6 @@
 #define NCR5380_write(reg, value)	cumanascsi_write(_instance, reg, value)
 #define NCR5380_intr			cumanascsi_intr
 #define NCR5380_queue_command		cumanascsi_queue_command
-#define NCR5380_proc_info		cumanascsi_proc_info
 
 #define NCR5380_implementation_fields	\
 	unsigned ctrl;			\
diff --git a/drivers/scsi/arm/cumana_2.c b/drivers/scsi/arm/cumana_2.c
index e3bae93..58915f2 100644
--- a/drivers/scsi/arm/cumana_2.c
+++ b/drivers/scsi/arm/cumana_2.c
@@ -337,50 +337,25 @@
 	return ret;
 }
 
-/* Prototype: int cumanascsi_2_proc_info(char *buffer, char **start, off_t offset,
- *					 int length, int host_no, int inout)
- * Purpose  : Return information about the driver to a user process accessing
- *	      the /proc filesystem.
- * Params   : buffer - a buffer to write information to
- *	      start  - a pointer into this buffer set by this routine to the start
- *		       of the required information.
- *	      offset - offset into information that we have read up to.
- *	      length - length of buffer
- *	      host_no - host number to return information for
- *	      inout  - 0 for reading, 1 for writing.
- * Returns  : length of data written to buffer.
- */
-int cumanascsi_2_proc_info (struct Scsi_Host *host, char *buffer, char **start, off_t offset,
-			    int length, int inout)
+static int cumanascsi_2_show_info(struct seq_file *m, struct Scsi_Host *host)
 {
 	struct cumanascsi2_info *info;
-	char *p = buffer;
-	int pos;
-
-	if (inout == 1)
-		return cumanascsi_2_set_proc_info(host, buffer, length);
-
 	info = (struct cumanascsi2_info *)host->hostdata;
 
-	p += sprintf(p, "Cumana SCSI II driver v%s\n", VERSION);
-	p += fas216_print_host(&info->info, p);
-	p += sprintf(p, "Term    : o%s\n",
+	seq_printf(m, "Cumana SCSI II driver v%s\n", VERSION);
+	fas216_print_host(&info->info, m);
+	seq_printf(m, "Term    : o%s\n",
 			info->terms ? "n" : "ff");
 
-	p += fas216_print_stats(&info->info, p);
-	p += fas216_print_devices(&info->info, p);
-
-	*start = buffer + offset;
-	pos = p - buffer - offset;
-	if (pos > length)
-		pos = length;
-
-	return pos;
+	fas216_print_stats(&info->info, m);
+	fas216_print_devices(&info->info, m);
+	return 0;
 }
 
 static struct scsi_host_template cumanascsi2_template = {
 	.module				= THIS_MODULE,
-	.proc_info			= cumanascsi_2_proc_info,
+	.show_info			= cumanascsi_2_show_info,
+	.write_info			= cumanascsi_2_set_proc_info,
 	.name				= "Cumana SCSI II",
 	.info				= cumanascsi_2_info,
 	.queuecommand			= fas216_queue_command,
diff --git a/drivers/scsi/arm/eesox.c b/drivers/scsi/arm/eesox.c
index 8e36908..5bf3c0d 100644
--- a/drivers/scsi/arm/eesox.c
+++ b/drivers/scsi/arm/eesox.c
@@ -422,45 +422,20 @@
 	return ret;
 }
 
-/* Prototype: int eesoxscsi_proc_info(char *buffer, char **start, off_t offset,
- *				      int length, int host_no, int inout)
- * Purpose  : Return information about the driver to a user process accessing
- *	      the /proc filesystem.
- * Params   : buffer - a buffer to write information to
- *	      start  - a pointer into this buffer set by this routine to the start
- *		       of the required information.
- *	      offset - offset into information that we have read up to.
- *	      length - length of buffer
- *	      host_no - host number to return information for
- *	      inout  - 0 for reading, 1 for writing.
- * Returns  : length of data written to buffer.
- */
-int eesoxscsi_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t offset,
-			    int length, int inout)
+static int eesoxscsi_show_info(struct seq_file *m, struct Scsi_Host *host)
 {
 	struct eesoxscsi_info *info;
-	char *p = buffer;
-	int pos;
-
-	if (inout == 1)
-		return eesoxscsi_set_proc_info(host, buffer, length);
 
 	info = (struct eesoxscsi_info *)host->hostdata;
 
-	p += sprintf(p, "EESOX SCSI driver v%s\n", VERSION);
-	p += fas216_print_host(&info->info, p);
-	p += sprintf(p, "Term    : o%s\n",
+	seq_printf(m, "EESOX SCSI driver v%s\n", VERSION);
+	fas216_print_host(&info->info, m);
+	seq_printf(m, "Term    : o%s\n",
 			info->control & EESOX_TERM_ENABLE ? "n" : "ff");
 
-	p += fas216_print_stats(&info->info, p);
-	p += fas216_print_devices(&info->info, p);
-
-	*start = buffer + offset;
-	pos = p - buffer - offset;
-	if (pos > length)
-		pos = length;
-
-	return pos;
+	fas216_print_stats(&info->info, m);
+	fas216_print_devices(&info->info, m);
+	return 0;
 }
 
 static ssize_t eesoxscsi_show_term(struct device *dev, struct device_attribute *attr, char *buf)
@@ -498,7 +473,8 @@
 
 static struct scsi_host_template eesox_template = {
 	.module				= THIS_MODULE,
-	.proc_info			= eesoxscsi_proc_info,
+	.show_info			= eesoxscsi_show_info,
+	.write_info			= eesoxscsi_set_proc_info,
 	.name				= "EESOX SCSI",
 	.info				= eesoxscsi_info,
 	.queuecommand			= fas216_queue_command,
diff --git a/drivers/scsi/arm/fas216.c b/drivers/scsi/arm/fas216.c
index 737554c..b46a6f6 100644
--- a/drivers/scsi/arm/fas216.c
+++ b/drivers/scsi/arm/fas216.c
@@ -2958,9 +2958,9 @@
 	queue_free(&info->queues.issue);
 }
 
-int fas216_print_host(FAS216_Info *info, char *buffer)
+void fas216_print_host(FAS216_Info *info, struct seq_file *m)
 {
-	return sprintf(buffer,
+	seq_printf(m,
 			"\n"
 			"Chip    : %s\n"
 			" Address: 0x%p\n"
@@ -2970,11 +2970,9 @@
 			info->scsi.irq, info->scsi.dma);
 }
 
-int fas216_print_stats(FAS216_Info *info, char *buffer)
+void fas216_print_stats(FAS216_Info *info, struct seq_file *m)
 {
-	char *p = buffer;
-
-	p += sprintf(p, "\n"
+	seq_printf(m, "\n"
 			"Command Statistics:\n"
 			" Queued     : %u\n"
 			" Issued     : %u\n"
@@ -2991,38 +2989,33 @@
 			info->stats.writes,	 info->stats.miscs,
 			info->stats.disconnects, info->stats.aborts,
 			info->stats.bus_resets,	 info->stats.host_resets);
-
-	return p - buffer;
 }
 
-int fas216_print_devices(FAS216_Info *info, char *buffer)
+void fas216_print_devices(FAS216_Info *info, struct seq_file *m)
 {
 	struct fas216_device *dev;
 	struct scsi_device *scd;
-	char *p = buffer;
 
-	p += sprintf(p, "Device/Lun TaggedQ       Parity   Sync\n");
+	seq_printf(m, "Device/Lun TaggedQ       Parity   Sync\n");
 
 	shost_for_each_device(scd, info->host) {
 		dev = &info->device[scd->id];
-		p += sprintf(p, "     %d/%d   ", scd->id, scd->lun);
+		seq_printf(m, "     %d/%d   ", scd->id, scd->lun);
 		if (scd->tagged_supported)
-			p += sprintf(p, "%3sabled(%3d) ",
+			seq_printf(m, "%3sabled(%3d) ",
 				     scd->simple_tags ? "en" : "dis",
 				     scd->current_tag);
 		else
-			p += sprintf(p, "unsupported   ");
+			seq_printf(m, "unsupported   ");
 
-		p += sprintf(p, "%3sabled ", dev->parity_enabled ? "en" : "dis");
+		seq_printf(m, "%3sabled ", dev->parity_enabled ? "en" : "dis");
 
 		if (dev->sof)
-			p += sprintf(p, "offset %d, %d ns\n",
+			seq_printf(m, "offset %d, %d ns\n",
 				     dev->sof, dev->period * 4);
 		else
-			p += sprintf(p, "async\n");
+			seq_printf(m, "async\n");
 	}
-
-	return p - buffer;
 }
 
 EXPORT_SYMBOL(fas216_init);
diff --git a/drivers/scsi/arm/fas216.h b/drivers/scsi/arm/fas216.h
index df2e1b3..c57c16e 100644
--- a/drivers/scsi/arm/fas216.h
+++ b/drivers/scsi/arm/fas216.h
@@ -358,9 +358,9 @@
  */
 extern void fas216_release (struct Scsi_Host *instance);
 
-extern int fas216_print_host(FAS216_Info *info, char *buffer);
-extern int fas216_print_stats(FAS216_Info *info, char *buffer);
-extern int fas216_print_devices(FAS216_Info *info, char *buffer);
+extern void fas216_print_host(FAS216_Info *info, struct seq_file *m);
+extern void fas216_print_stats(FAS216_Info *info, struct seq_file *m);
+extern void fas216_print_devices(FAS216_Info *info, struct seq_file *m);
 
 /* Function: int fas216_eh_abort(struct scsi_cmnd *SCpnt)
  * Purpose : abort this command
diff --git a/drivers/scsi/arm/oak.c b/drivers/scsi/arm/oak.c
index 48facdc..4266eef 100644
--- a/drivers/scsi/arm/oak.c
+++ b/drivers/scsi/arm/oak.c
@@ -31,7 +31,8 @@
 #define NCR5380_write(reg, value)	writeb(value, _base + ((reg) << 2))
 #define NCR5380_intr			oakscsi_intr
 #define NCR5380_queue_command		oakscsi_queue_command
-#define NCR5380_proc_info		oakscsi_proc_info
+#define NCR5380_show_info		oakscsi_show_info
+#define NCR5380_write_info		oakscsi_write_info
 
 #define NCR5380_implementation_fields	\
 	void __iomem *base
@@ -115,7 +116,8 @@
 
 static struct scsi_host_template oakscsi_template = {
 	.module			= THIS_MODULE,
-	.proc_info		= oakscsi_proc_info,
+	.show_info		= oakscsi_show_info,
+	.write_info		= oakscsi_write_info,
 	.name			= "Oak 16-bit SCSI",
 	.info			= oakscsi_info,
 	.queuecommand		= oakscsi_queue_command,
diff --git a/drivers/scsi/arm/powertec.c b/drivers/scsi/arm/powertec.c
index 246600b..abc9593 100644
--- a/drivers/scsi/arm/powertec.c
+++ b/drivers/scsi/arm/powertec.c
@@ -237,32 +237,20 @@
  *	      inout   - 0 for reading, 1 for writing.
  * Returns  : length of data written to buffer.
  */
-int powertecscsi_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t offset,
-			    int length, int inout)
+static int powertecscsi_show_info(struct seq_file *m, struct Scsi_Host *host)
 {
 	struct powertec_info *info;
-	char *p = buffer;
-	int pos;
-
-	if (inout == 1)
-		return powertecscsi_set_proc_info(host, buffer, length);
 
 	info = (struct powertec_info *)host->hostdata;
 
-	p += sprintf(p, "PowerTec SCSI driver v%s\n", VERSION);
-	p += fas216_print_host(&info->info, p);
-	p += sprintf(p, "Term    : o%s\n",
+	seq_printf(m, "PowerTec SCSI driver v%s\n", VERSION);
+	fas216_print_host(&info->info, m);
+	seq_printf(m, "Term    : o%s\n",
 			info->term_ctl ? "n" : "ff");
 
-	p += fas216_print_stats(&info->info, p);
-	p += fas216_print_devices(&info->info, p);
-
-	*start = buffer + offset;
-	pos = p - buffer - offset;
-	if (pos > length)
-		pos = length;
-
-	return pos;
+	fas216_print_stats(&info->info, m);
+	fas216_print_devices(&info->info, m);
+	return 0;
 }
 
 static ssize_t powertecscsi_show_term(struct device *dev, struct device_attribute *attr, char *buf)
@@ -291,7 +279,8 @@
 
 static struct scsi_host_template powertecscsi_template = {
 	.module				= THIS_MODULE,
-	.proc_info			= powertecscsi_proc_info,
+	.show_info			= powertecscsi_show_info,
+	.write_info			= powertecscsi_set_proc_info,
 	.name				= "PowerTec SCSI",
 	.info				= powertecscsi_info,
 	.queuecommand			= fas216_queue_command,
diff --git a/drivers/scsi/atari_NCR5380.c b/drivers/scsi/atari_NCR5380.c
index 2db79b4..0f3cdbc 100644
--- a/drivers/scsi/atari_NCR5380.c
+++ b/drivers/scsi/atari_NCR5380.c
@@ -719,119 +719,94 @@
  * Inputs : instance, pointer to this instance.
  */
 
+static void lprint_Scsi_Cmnd(Scsi_Cmnd *cmd)
+{
+	int i, s;
+	unsigned char *command;
+	printk("scsi%d: destination target %d, lun %d\n",
+		H_NO(cmd), cmd->device->id, cmd->device->lun);
+	printk(KERN_CONT "        command = ");
+	command = cmd->cmnd;
+	printk(KERN_CONT "%2d (0x%02x)", command[0], command[0]);
+	for (i = 1, s = COMMAND_SIZE(command[0]); i < s; ++i)
+		printk(KERN_CONT " %02x", command[i]);
+	printk("\n");
+}
+
 static void NCR5380_print_status(struct Scsi_Host *instance)
 {
-	char *pr_bfr;
-	char *start;
-	int len;
+	struct NCR5380_hostdata *hostdata;
+	Scsi_Cmnd *ptr;
+	unsigned long flags;
 
 	NCR_PRINT(NDEBUG_ANY);
 	NCR_PRINT_PHASE(NDEBUG_ANY);
 
-	pr_bfr = (char *)__get_free_page(GFP_ATOMIC);
-	if (!pr_bfr) {
-		printk("NCR5380_print_status: no memory for print buffer\n");
-		return;
-	}
-	len = NCR5380_proc_info(instance, pr_bfr, &start, 0, PAGE_SIZE, 0);
-	pr_bfr[len] = 0;
-	printk("\n%s\n", pr_bfr);
-	free_page((unsigned long)pr_bfr);
-}
-
-
-/******************************************/
-/*
- * /proc/scsi/[dtc pas16 t128 generic]/[0-ASC_NUM_BOARD_SUPPORTED]
- *
- * *buffer: I/O buffer
- * **start: if inout == FALSE pointer into buffer where user read should start
- * offset: current offset
- * length: length of buffer
- * hostno: Scsi_Host host_no
- * inout: TRUE - user is writing; FALSE - user is reading
- *
- * Return the number of bytes read from or written
-*/
-
-#undef SPRINTF
-#define SPRINTF(fmt,args...)							\
-	do {									\
-		if (pos + strlen(fmt) + 20 /* slop */ < buffer + length)	\
-			pos += sprintf(pos, fmt , ## args);			\
-	} while(0)
-static char *lprint_Scsi_Cmnd(Scsi_Cmnd *cmd, char *pos, char *buffer, int length);
-
-static int NCR5380_proc_info(struct Scsi_Host *instance, char *buffer,
-			     char **start, off_t offset, int length, int inout)
-{
-	char *pos = buffer;
-	struct NCR5380_hostdata *hostdata;
-	Scsi_Cmnd *ptr;
-	unsigned long flags;
-	off_t begin = 0;
-#define check_offset()					\
-	do {						\
-		if (pos - buffer < offset - begin) {	\
-			begin += pos - buffer;		\
-			pos = buffer;			\
-		}					\
-	} while (0)
-
 	hostdata = (struct NCR5380_hostdata *)instance->hostdata;
 
-	if (inout)			/* Has data been written to the file ? */
-		return -ENOSYS;		/* Currently this is a no-op */
-	SPRINTF("NCR5380 core release=%d.\n", NCR5380_PUBLIC_RELEASE);
-	check_offset();
+	printk("\nNCR5380 core release=%d.\n", NCR5380_PUBLIC_RELEASE);
 	local_irq_save(flags);
-	SPRINTF("NCR5380: coroutine is%s running.\n",
+	printk("NCR5380: coroutine is%s running.\n",
 		main_running ? "" : "n't");
-	check_offset();
 	if (!hostdata->connected)
-		SPRINTF("scsi%d: no currently connected command\n", HOSTNO);
+		printk("scsi%d: no currently connected command\n", HOSTNO);
 	else
-		pos = lprint_Scsi_Cmnd((Scsi_Cmnd *) hostdata->connected,
-				       pos, buffer, length);
-	SPRINTF("scsi%d: issue_queue\n", HOSTNO);
-	check_offset();
-	for (ptr = (Scsi_Cmnd *)hostdata->issue_queue; ptr; ptr = NEXT(ptr)) {
-		pos = lprint_Scsi_Cmnd(ptr, pos, buffer, length);
-		check_offset();
-	}
+		lprint_Scsi_Cmnd((Scsi_Cmnd *) hostdata->connected);
+	printk("scsi%d: issue_queue\n", HOSTNO);
+	for (ptr = (Scsi_Cmnd *)hostdata->issue_queue; ptr; ptr = NEXT(ptr))
+		lprint_Scsi_Cmnd(ptr);
 
-	SPRINTF("scsi%d: disconnected_queue\n", HOSTNO);
-	check_offset();
+	printk("scsi%d: disconnected_queue\n", HOSTNO);
 	for (ptr = (Scsi_Cmnd *) hostdata->disconnected_queue; ptr;
-	     ptr = NEXT(ptr)) {
-		pos = lprint_Scsi_Cmnd(ptr, pos, buffer, length);
-		check_offset();
-	}
+	     ptr = NEXT(ptr))
+		lprint_Scsi_Cmnd(ptr);
 
 	local_irq_restore(flags);
-	*start = buffer + (offset - begin);
-	if (pos - buffer < offset - begin)
-		return 0;
-	else if (pos - buffer - (offset - begin) < length)
-		return pos - buffer - (offset - begin);
-	return length;
+	printk("\n");
 }
 
-static char *lprint_Scsi_Cmnd(Scsi_Cmnd *cmd, char *pos, char *buffer, int length)
+static void show_Scsi_Cmnd(Scsi_Cmnd *cmd, struct seq_file *m)
 {
 	int i, s;
 	unsigned char *command;
-	SPRINTF("scsi%d: destination target %d, lun %d\n",
+	seq_printf(m, "scsi%d: destination target %d, lun %d\n",
 		H_NO(cmd), cmd->device->id, cmd->device->lun);
-	SPRINTF("        command = ");
+	seq_printf(m, "        command = ");
 	command = cmd->cmnd;
-	SPRINTF("%2d (0x%02x)", command[0], command[0]);
+	seq_printf(m, "%2d (0x%02x)", command[0], command[0]);
 	for (i = 1, s = COMMAND_SIZE(command[0]); i < s; ++i)
-		SPRINTF(" %02x", command[i]);
-	SPRINTF("\n");
-	return pos;
+		seq_printf(m, " %02x", command[i]);
+	seq_printf(m, "\n");
 }
 
+static int NCR5380_show_info(struct seq_file *m, struct Scsi_Host *instance)
+{
+	struct NCR5380_hostdata *hostdata;
+	Scsi_Cmnd *ptr;
+	unsigned long flags;
+
+	hostdata = (struct NCR5380_hostdata *)instance->hostdata;
+
+	seq_printf(m, "NCR5380 core release=%d.\n", NCR5380_PUBLIC_RELEASE);
+	local_irq_save(flags);
+	seq_printf(m, "NCR5380: coroutine is%s running.\n",
+		main_running ? "" : "n't");
+	if (!hostdata->connected)
+		seq_printf(m, "scsi%d: no currently connected command\n", HOSTNO);
+	else
+		show_Scsi_Cmnd((Scsi_Cmnd *) hostdata->connected, m);
+	seq_printf(m, "scsi%d: issue_queue\n", HOSTNO);
+	for (ptr = (Scsi_Cmnd *)hostdata->issue_queue; ptr; ptr = NEXT(ptr))
+		show_Scsi_Cmnd(ptr, m);
+
+	seq_printf(m, "scsi%d: disconnected_queue\n", HOSTNO);
+	for (ptr = (Scsi_Cmnd *) hostdata->disconnected_queue; ptr;
+	     ptr = NEXT(ptr))
+		show_Scsi_Cmnd(ptr, m);
+
+	local_irq_restore(flags);
+	return 0;
+}
 
 /*
  * Function : void NCR5380_init (struct Scsi_Host *instance)
diff --git a/drivers/scsi/atari_scsi.c b/drivers/scsi/atari_scsi.c
index df740cb..a3e6c8a 100644
--- a/drivers/scsi/atari_scsi.c
+++ b/drivers/scsi/atari_scsi.c
@@ -1100,7 +1100,7 @@
 #include "atari_NCR5380.c"
 
 static struct scsi_host_template driver_template = {
-	.proc_info		= atari_scsi_proc_info,
+	.show_info		= atari_scsi_show_info,
 	.name			= "Atari native SCSI",
 	.detect			= atari_scsi_detect,
 	.release		= atari_scsi_release,
diff --git a/drivers/scsi/atari_scsi.h b/drivers/scsi/atari_scsi.h
index bd52df7..11c624b 100644
--- a/drivers/scsi/atari_scsi.h
+++ b/drivers/scsi/atari_scsi.h
@@ -47,7 +47,7 @@
 #define NCR5380_intr atari_scsi_intr
 #define NCR5380_queue_command atari_scsi_queue_command
 #define NCR5380_abort atari_scsi_abort
-#define NCR5380_proc_info atari_scsi_proc_info
+#define NCR5380_show_info atari_scsi_show_info
 #define NCR5380_dma_read_setup(inst,d,c) atari_scsi_dma_setup (inst, d, c, 0)
 #define NCR5380_dma_write_setup(inst,d,c) atari_scsi_dma_setup (inst, d, c, 1)
 #define NCR5380_dma_residual(inst) atari_scsi_dma_residual( inst )
diff --git a/drivers/scsi/atp870u.c b/drivers/scsi/atp870u.c
index cfc7304..15a629d 100644
--- a/drivers/scsi/atp870u.c
+++ b/drivers/scsi/atp870u.c
@@ -3099,38 +3099,14 @@
 	return buffer;
 }
 
-#define BLS buffer + len + size
-static int atp870u_proc_info(struct Scsi_Host *HBAptr, char *buffer, 
-			     char **start, off_t offset, int length, int inout)
+static int atp870u_show_info(struct seq_file *m, struct Scsi_Host *HBAptr)
 {
-	static u8 buff[512];
-	int size = 0;
-	int len = 0;
-	off_t begin = 0;
-	off_t pos = 0;
-	
-	if (inout) 	
-		return -EINVAL;
-	if (offset == 0)
-		memset(buff, 0, sizeof(buff));
-	size += sprintf(BLS, "ACARD AEC-671X Driver Version: 2.6+ac\n");
-	len += size;
-	pos = begin + len;
-	size = 0;
-
-	size += sprintf(BLS, "\n");
-	size += sprintf(BLS, "Adapter Configuration:\n");
-	size += sprintf(BLS, "               Base IO: %#.4lx\n", HBAptr->io_port);
-	size += sprintf(BLS, "                   IRQ: %d\n", HBAptr->irq);
-	len += size;
-	pos = begin + len;
-	
-	*start = buffer + (offset - begin);	/* Start of wanted data */
-	len -= (offset - begin);	/* Start slop */
-	if (len > length) {
-		len = length;	/* Ending slop */
-	}
-	return (len);
+	seq_printf(m, "ACARD AEC-671X Driver Version: 2.6+ac\n");
+	seq_printf(m, "\n");
+	seq_printf(m, "Adapter Configuration:\n");
+	seq_printf(m, "               Base IO: %#.4lx\n", HBAptr->io_port);
+	seq_printf(m, "                   IRQ: %d\n", HBAptr->irq);
+	return 0;
 }
 
 
@@ -3177,7 +3153,7 @@
      .module			= THIS_MODULE,
      .name              	= "atp870u"		/* name */,
      .proc_name			= "atp870u",
-     .proc_info			= atp870u_proc_info,
+     .show_info			= atp870u_show_info,
      .info              	= atp870u_info		/* info */,
      .queuecommand      	= atp870u_queuecommand	/* queuecommand */,
      .eh_abort_handler  	= atp870u_abort		/* abort */,
diff --git a/drivers/scsi/dc395x.c b/drivers/scsi/dc395x.c
index fed486bf..694e13c 100644
--- a/drivers/scsi/dc395x.c
+++ b/drivers/scsi/dc395x.c
@@ -4616,26 +4616,21 @@
 
 
 #undef SPRINTF
-#define SPRINTF(args...) pos += sprintf(pos, args)
+#define SPRINTF(args...) seq_printf(m,##args)
 
 #undef YESNO
 #define YESNO(YN) \
  if (YN) SPRINTF(" Yes ");\
  else SPRINTF(" No  ")
 
-static int dc395x_proc_info(struct Scsi_Host *host, char *buffer,
-		char **start, off_t offset, int length, int inout)
+static int dc395x_show_info(struct seq_file *m, struct Scsi_Host *host)
 {
 	struct AdapterCtlBlk *acb = (struct AdapterCtlBlk *)host->hostdata;
 	int spd, spd1;
-	char *pos = buffer;
 	struct DeviceCtlBlk *dcb;
 	unsigned long flags;
 	int dev;
 
-	if (inout)		/* Has data been written to the file ? */
-		return -EPERM;
-
 	SPRINTF(DC395X_BANNER " PCI SCSI Host Adapter\n");
 	SPRINTF(" Driver Version " DC395X_VERSION "\n");
 
@@ -4735,22 +4730,15 @@
 		SPRINTF("END\n");
 	}
 
-	*start = buffer + offset;
 	DC395x_UNLOCK_IO(acb->scsi_host, flags);
-
-	if (pos - buffer < offset)
-		return 0;
-	else if (pos - buffer - offset < length)
-		return pos - buffer - offset;
-	else
-		return length;
+	return 0;
 }
 
 
 static struct scsi_host_template dc395x_driver_template = {
 	.module                 = THIS_MODULE,
 	.proc_name              = DC395X_NAME,
-	.proc_info              = dc395x_proc_info,
+	.show_info              = dc395x_show_info,
 	.name                   = DC395X_BANNER " " DC395X_VERSION,
 	.queuecommand           = dc395x_queue_command,
 	.bios_param             = dc395x_bios_param,
diff --git a/drivers/scsi/dpt_i2o.c b/drivers/scsi/dpt_i2o.c
index b6e2700..19e1b42 100644
--- a/drivers/scsi/dpt_i2o.c
+++ b/drivers/scsi/dpt_i2o.c
@@ -553,36 +553,14 @@
 	return (char *) (pHba->detail);
 }
 
-static int adpt_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t offset,
-		  int length, int inout)
+static int adpt_show_info(struct seq_file *m, struct Scsi_Host *host)
 {
 	struct adpt_device* d;
 	int id;
 	int chan;
-	int len = 0;
-	int begin = 0;
-	int pos = 0;
 	adpt_hba* pHba;
 	int unit;
 
-	*start = buffer;
-	if (inout == TRUE) {
-		/*
-		 * The user has done a write and wants us to take the
-		 * data in the buffer and do something with it.
-		 * proc_scsiwrite calls us with inout = 1
-		 *
-		 * Read data from buffer (writing to us) - NOT SUPPORTED
-		 */
-		return -EINVAL;
-	}
-
-	/*
-	 * inout = 0 means the user has done a read and wants information
-	 * returned, so we write information about the cards into the buffer
-	 * proc_scsiread() calls us with inout = 0
-	 */
-
 	// Find HBA (host bus adapter) we are looking for
 	mutex_lock(&adpt_configuration_lock);
 	for (pHba = hba_chain; pHba; pHba = pHba->next) {
@@ -596,86 +574,30 @@
 	}
 	host = pHba->host;
 
-	len  = sprintf(buffer    , "Adaptec I2O RAID Driver Version: %s\n\n", DPT_I2O_VERSION);
-	len += sprintf(buffer+len, "%s\n", pHba->detail);
-	len += sprintf(buffer+len, "SCSI Host=scsi%d  Control Node=/dev/%s  irq=%d\n", 
+	seq_printf(m, "Adaptec I2O RAID Driver Version: %s\n\n", DPT_I2O_VERSION);
+	seq_printf(m, "%s\n", pHba->detail);
+	seq_printf(m, "SCSI Host=scsi%d  Control Node=/dev/%s  irq=%d\n", 
 			pHba->host->host_no, pHba->name, host->irq);
-	len += sprintf(buffer+len, "\tpost fifo size  = %d\n\treply fifo size = %d\n\tsg table size   = %d\n\n",
+	seq_printf(m, "\tpost fifo size  = %d\n\treply fifo size = %d\n\tsg table size   = %d\n\n",
 			host->can_queue, (int) pHba->reply_fifo_size , host->sg_tablesize);
 
-	pos = begin + len;
-
-	/* CHECKPOINT */
-	if(pos > offset + length) {
-		goto stop_output;
-	}
-	if(pos <= offset) {
-		/*
-		 * If we haven't even written to where we last left
-		 * off (the last time we were called), reset the 
-		 * beginning pointer.
-		 */
-		len = 0;
-		begin = pos;
-	}
-	len +=  sprintf(buffer+len, "Devices:\n");
+	seq_printf(m, "Devices:\n");
 	for(chan = 0; chan < MAX_CHANNEL; chan++) {
 		for(id = 0; id < MAX_ID; id++) {
 			d = pHba->channel[chan].device[id];
-			while(d){
-				len += sprintf(buffer+len,"\t%-24.24s", d->pScsi_dev->vendor);
-				len += sprintf(buffer+len," Rev: %-8.8s\n", d->pScsi_dev->rev);
-				pos = begin + len;
-
-
-				/* CHECKPOINT */
-				if(pos > offset + length) {
-					goto stop_output;
-				}
-				if(pos <= offset) {
-					len = 0;
-					begin = pos;
-				}
+			while(d) {
+				seq_printf(m,"\t%-24.24s", d->pScsi_dev->vendor);
+				seq_printf(m," Rev: %-8.8s\n", d->pScsi_dev->rev);
 
 				unit = d->pI2o_dev->lct_data.tid;
-				len += sprintf(buffer+len, "\tTID=%d, (Channel=%d, Target=%d, Lun=%d)  (%s)\n\n",
+				seq_printf(m, "\tTID=%d, (Channel=%d, Target=%d, Lun=%d)  (%s)\n\n",
 					       unit, (int)d->scsi_channel, (int)d->scsi_id, (int)d->scsi_lun,
 					       scsi_device_online(d->pScsi_dev)? "online":"offline"); 
-				pos = begin + len;
-
-				/* CHECKPOINT */
-				if(pos > offset + length) {
-					goto stop_output;
-				}
-				if(pos <= offset) {
-					len = 0;
-					begin = pos;
-				}
-
 				d = d->next_lun;
 			}
 		}
 	}
-
-	/*
-	 * begin is where we last checked our position with regards to offset
-	 * begin is always less than offset.  len is relative to begin.  It
-	 * is the number of bytes written past begin
-	 *
-	 */
-stop_output:
-	/* stop the output and calculate the correct length */
-	*(buffer + len) = '\0';
-
-	*start = buffer + (offset - begin);	/* Start of wanted data */
-	len -= (offset - begin);
-	if(len > length) {
-		len = length;
-	} else if(len < 0){
-		len = 0;
-		**start = '\0';
-	}
-	return len;
+	return 0;
 }
 
 /*
@@ -3639,7 +3561,7 @@
 	.module			= THIS_MODULE,
 	.name			= "dpt_i2o",
 	.proc_name		= "dpt_i2o",
-	.proc_info		= adpt_proc_info,
+	.show_info		= adpt_show_info,
 	.info			= adpt_info,
 	.queuecommand		= adpt_queue,
 	.eh_abort_handler	= adpt_abort,
diff --git a/drivers/scsi/dtc.c b/drivers/scsi/dtc.c
index 4b11bb0..d01f016 100644
--- a/drivers/scsi/dtc.c
+++ b/drivers/scsi/dtc.c
@@ -216,7 +216,8 @@
 	int sig, count;
 
 	tpnt->proc_name = "dtc3x80";
-	tpnt->proc_info = &dtc_proc_info;
+	tpnt->show_info = dtc_show_info;
+	tpnt->write_info = dtc_write_info;
 
 	for (count = 0; current_override < NO_OVERRIDES; ++current_override) {
 		addr = 0;
diff --git a/drivers/scsi/dtc.h b/drivers/scsi/dtc.h
index cdc6212..92d7cfc 100644
--- a/drivers/scsi/dtc.h
+++ b/drivers/scsi/dtc.h
@@ -88,7 +88,8 @@
 #define NCR5380_queue_command		dtc_queue_command
 #define NCR5380_abort			dtc_abort
 #define NCR5380_bus_reset		dtc_bus_reset
-#define NCR5380_proc_info		dtc_proc_info 
+#define NCR5380_show_info		dtc_show_info 
+#define NCR5380_write_info		dtc_write_info 
 
 /* 15 12 11 10
    1001 1100 0000 0000 */
diff --git a/drivers/scsi/eata_pio.c b/drivers/scsi/eata_pio.c
index d5f8362..356def4 100644
--- a/drivers/scsi/eata_pio.c
+++ b/drivers/scsi/eata_pio.c
@@ -92,58 +92,22 @@
 
 static struct scsi_host_template driver_template;
 
-/*
- * eata_proc_info
- * inout : decides on the direction of the dataflow and the meaning of the 
- *         variables
- * buffer: If inout==FALSE data is being written to it else read from it
- * *start: If inout==FALSE start of the valid data in the buffer
- * offset: If inout==FALSE offset from the beginning of the imaginary file 
- *         from which we start writing into the buffer
- * length: If inout==FALSE max number of bytes to be written into the buffer 
- *         else number of bytes in the buffer
- */
-static int eata_pio_proc_info(struct Scsi_Host *shost, char *buffer, char **start, off_t offset,
-			      int length, int rw)
+static int eata_pio_show_info(struct seq_file *m, struct Scsi_Host *shost)
 {
-	int len = 0;
-	off_t begin = 0, pos = 0;
-
-	if (rw)
-		return -ENOSYS;
-
-	len += sprintf(buffer+len, "EATA (Extended Attachment) PIO driver version: "
+	seq_printf(m, "EATA (Extended Attachment) PIO driver version: "
 		   "%d.%d%s\n",VER_MAJOR, VER_MINOR, VER_SUB);
-	len += sprintf(buffer + len, "queued commands:     %10ld\n"
+	seq_printf(m, "queued commands:     %10ld\n"
 		   "processed interrupts:%10ld\n", queue_counter, int_counter);
-	len += sprintf(buffer + len, "\nscsi%-2d: HBA %.10s\n",
+	seq_printf(m, "\nscsi%-2d: HBA %.10s\n",
 		   shost->host_no, SD(shost)->name);
-	len += sprintf(buffer + len, "Firmware revision: v%s\n",
+	seq_printf(m, "Firmware revision: v%s\n",
 		   SD(shost)->revision);
-	len += sprintf(buffer + len, "IO: PIO\n");
-	len += sprintf(buffer + len, "Base IO : %#.4x\n", (u32) shost->base);
-	len += sprintf(buffer + len, "Host Bus: %s\n",
+	seq_printf(m, "IO: PIO\n");
+	seq_printf(m, "Base IO : %#.4x\n", (u32) shost->base);
+	seq_printf(m, "Host Bus: %s\n",
 		   (SD(shost)->bustype == 'P')?"PCI ":
 		   (SD(shost)->bustype == 'E')?"EISA":"ISA ");
-    
-	pos = begin + len;
-    
-	if (pos < offset) {
-		len = 0;
-		begin = pos;
-	}
-	if (pos > offset + length)
-		goto stop_output;
-    
-stop_output:
-	DBG(DBG_PROC, printk("2pos: %ld offset: %ld len: %d\n", pos, offset, len));
-	*start = buffer + (offset - begin);   /* Start of wanted data */
-	len -= (offset - begin);            /* Start slop */
-	if (len > length)
-		len = length;               /* Ending slop */
-	DBG(DBG_PROC, printk("3pos: %ld offset: %ld len: %d\n", pos, offset, len));
-    
-	return len;
+	return 0;
 }
 
 static int eata_pio_release(struct Scsi_Host *sh)
@@ -985,7 +949,7 @@
 static struct scsi_host_template driver_template = {
 	.proc_name		= "eata_pio",
 	.name              	= "EATA (Extended Attachment) PIO driver",
-	.proc_info         	= eata_pio_proc_info,
+	.show_info         	= eata_pio_show_info,
 	.detect            	= eata_pio_detect,
 	.release           	= eata_pio_release,
 	.queuecommand      	= eata_pio_queue,
diff --git a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c
index 5041f92..5cec6c6 100644
--- a/drivers/scsi/g_NCR5380.c
+++ b/drivers/scsi/g_NCR5380.c
@@ -745,42 +745,36 @@
  
 #include "NCR5380.c"
 
-#define PRINTP(x) len += sprintf(buffer+len, x)
+#define PRINTP(x) seq_printf(m, x)
 #define ANDP ,
 
-static int sprint_opcode(char *buffer, int len, int opcode)
+static void sprint_opcode(struct seq_file *m, int opcode)
 {
-	int start = len;
 	PRINTP("0x%02x " ANDP opcode);
-	return len - start;
 }
 
-static int sprint_command(char *buffer, int len, unsigned char *command)
+static void sprint_command(struct seq_file *m, unsigned char *command)
 {
-	int i, s, start = len;
-	len += sprint_opcode(buffer, len, command[0]);
+	int i, s;
+	sprint_opcode(m, command[0]);
 	for (i = 1, s = COMMAND_SIZE(command[0]); i < s; ++i)
 		PRINTP("%02x " ANDP command[i]);
 	PRINTP("\n");
-	return len - start;
 }
 
 /**
  *	sprintf_Scsi_Cmnd	-	print a scsi command
- *	@buffer: buffr to print into
- *	@len: buffer length
+ *	@m: seq_fil to print into
  *	@cmd: SCSI command block
  *	
  *	Print out the target and command data in hex
  */
 
-static int sprint_Scsi_Cmnd(char *buffer, int len, Scsi_Cmnd * cmd)
+static void sprint_Scsi_Cmnd(struct seq_file *m, Scsi_Cmnd * cmd)
 {
-	int start = len;
 	PRINTP("host number %d destination target %d, lun %d\n" ANDP cmd->device->host->host_no ANDP cmd->device->id ANDP cmd->device->lun);
 	PRINTP("        command = ");
-	len += sprint_command(buffer, len, cmd->cmnd);
-	return len - start;
+	sprint_command(m, cmd->cmnd);
 }
 
 /**
@@ -800,9 +794,8 @@
  *	Locks: global cli/lock for queue walk
  */
  
-static int generic_NCR5380_proc_info(struct Scsi_Host *scsi_ptr, char *buffer, char **start, off_t offset, int length, int inout)
+static int generic_NCR5380_show_info(struct seq_file *m, struct Scsi_Host *scsi_ptr)
 {
-	int len = 0;
 	NCR5380_local_declare();
 	unsigned long flags;
 	unsigned char status;
@@ -853,16 +846,16 @@
 		PRINTP("  T:%d %s " ANDP dev->id ANDP scsi_device_type(dev->type));
 		for (i = 0; i < 8; i++)
 			if (dev->vendor[i] >= 0x20)
-				*(buffer + (len++)) = dev->vendor[i];
-		*(buffer + (len++)) = ' ';
+				seq_putc(m, dev->vendor[i]);
+		seq_putc(m, ' ');
 		for (i = 0; i < 16; i++)
 			if (dev->model[i] >= 0x20)
-				*(buffer + (len++)) = dev->model[i];
-		*(buffer + (len++)) = ' ';
+				seq_putc(m, dev->model[i]);
+		seq_putc(m, ' ');
 		for (i = 0; i < 4; i++)
 			if (dev->rev[i] >= 0x20)
-				*(buffer + (len++)) = dev->rev[i];
-		*(buffer + (len++)) = ' ';
+				seq_putc(m, dev->rev[i]);
+		seq_putc(m, ' ');
 
 		PRINTP("\n%10ld kb read    in %5ld secs" ANDP br / 1024 ANDP tr);
 		if (tr)
@@ -886,32 +879,28 @@
 	if (!hostdata->connected) {
 		PRINTP("No currently connected command\n");
 	} else {
-		len += sprint_Scsi_Cmnd(buffer, len, (Scsi_Cmnd *) hostdata->connected);
+		sprint_Scsi_Cmnd(m, (Scsi_Cmnd *) hostdata->connected);
 	}
 
 	PRINTP("issue_queue\n");
 
 	for (ptr = (Scsi_Cmnd *) hostdata->issue_queue; ptr; ptr = (Scsi_Cmnd *) ptr->host_scribble)
-		len += sprint_Scsi_Cmnd(buffer, len, ptr);
+		sprint_Scsi_Cmnd(m, ptr);
 
 	PRINTP("disconnected_queue\n");
 
 	for (ptr = (Scsi_Cmnd *) hostdata->disconnected_queue; ptr; ptr = (Scsi_Cmnd *) ptr->host_scribble)
-		len += sprint_Scsi_Cmnd(buffer, len, ptr);
+		sprint_Scsi_Cmnd(m, ptr);
 
-	*start = buffer + offset;
-	len -= offset;
-	if (len > length)
-		len = length;
 	spin_unlock_irqrestore(scsi_ptr->host_lock, flags);
-	return len;
+	return 0;
 }
 
 #undef PRINTP
 #undef ANDP
 
 static struct scsi_host_template driver_template = {
-	.proc_info      	= generic_NCR5380_proc_info,
+	.show_info      	= generic_NCR5380_show_info,
 	.name           	= "Generic NCR5380/NCR53C400 Scsi Driver",
 	.detect         	= generic_NCR5380_detect,
 	.release        	= generic_NCR5380_release_resources,
diff --git a/drivers/scsi/gdth.c b/drivers/scsi/gdth.c
index 59bceac..6d55b4e 100644
--- a/drivers/scsi/gdth.c
+++ b/drivers/scsi/gdth.c
@@ -4676,7 +4676,8 @@
         .eh_bus_reset_handler   = gdth_eh_bus_reset,
         .slave_configure        = gdth_slave_configure,
         .bios_param             = gdth_bios_param,
-        .proc_info              = gdth_proc_info,
+        .show_info              = gdth_show_info,
+        .write_info             = gdth_set_info,
 	.eh_timed_out		= gdth_timed_out,
         .proc_name              = "gdth",
         .can_queue              = GDTH_MAXCMDS,
diff --git a/drivers/scsi/gdth.h b/drivers/scsi/gdth.h
index fbf6f0f4..3fd8b83 100644
--- a/drivers/scsi/gdth.h
+++ b/drivers/scsi/gdth.h
@@ -1007,6 +1007,7 @@
 
 /* function prototyping */
 
-int gdth_proc_info(struct Scsi_Host *, char *,char **,off_t,int,int);
+int gdth_show_info(struct seq_file *, struct Scsi_Host *);
+int gdth_set_info(struct Scsi_Host *, char *, int);
 
 #endif
diff --git a/drivers/scsi/gdth_proc.c b/drivers/scsi/gdth_proc.c
index 6527543..9fb6326 100644
--- a/drivers/scsi/gdth_proc.c
+++ b/drivers/scsi/gdth_proc.c
@@ -5,23 +5,9 @@
 #include <linux/completion.h>
 #include <linux/slab.h>
 
-int gdth_proc_info(struct Scsi_Host *host, char *buffer,char **start,off_t offset,int length,   
-                   int inout)
+int gdth_set_info(struct Scsi_Host *host, char *buffer, int length)
 {
     gdth_ha_str *ha = shost_priv(host);
-
-    TRACE2(("gdth_proc_info() length %d offs %d inout %d\n",
-            length,(int)offset,inout));
-
-    if (inout)
-        return(gdth_set_info(buffer,length,host,ha));
-    else
-        return(gdth_get_info(buffer,start,offset,length,host,ha));
-}
-
-static int gdth_set_info(char *buffer,int length,struct Scsi_Host *host,
-                         gdth_ha_str *ha)
-{
     int ret_val = -EINVAL;
 
     TRACE2(("gdth_set_info() ha %d\n",ha->hanum,));
@@ -149,12 +135,10 @@
     return(-EINVAL);
 }
 
-static int gdth_get_info(char *buffer,char **start,off_t offset,int length,
-                         struct Scsi_Host *host, gdth_ha_str *ha)
+int gdth_show_info(struct seq_file *m, struct Scsi_Host *host)
 {
-    int size = 0,len = 0;
+    gdth_ha_str *ha = shost_priv(host);
     int hlen;
-    off_t begin = 0,pos = 0;
     int id, i, j, k, sec, flag;
     int no_mdrv = 0, drv_no, is_mirr;
     u32 cnt;
@@ -189,8 +173,7 @@
     /* request is i.e. "cat /proc/scsi/gdth/0" */ 
     /* format: %-15s\t%-10s\t%-15s\t%s */
     /* driver parameters */
-    size = sprintf(buffer+len,"Driver Parameters:\n");
-    len += size;  pos = begin + len;
+    seq_printf(m, "Driver Parameters:\n");
     if (reserve_list[0] == 0xff)
         strcpy(hrec, "--");
     else {
@@ -201,69 +184,50 @@
             hlen += snprintf(hrec + hlen , 161 - hlen, ",%d", reserve_list[i]);
         }
     }
-    size = sprintf(buffer+len,
+    seq_printf(m,
                    " reserve_mode: \t%d         \treserve_list:  \t%s\n",
                    reserve_mode, hrec);
-    len += size;  pos = begin + len;
-    size = sprintf(buffer+len,
+    seq_printf(m,
                    " max_ids:      \t%-3d       \thdr_channel:   \t%d\n",
                    max_ids, hdr_channel);
-    len += size;  pos = begin + len;
 
     /* controller information */
-    size = sprintf(buffer+len,"\nDisk Array Controller Information:\n");
-    len += size;  pos = begin + len;
-    strcpy(hrec, ha->binfo.type_string);
-    size = sprintf(buffer+len,
+    seq_printf(m,"\nDisk Array Controller Information:\n");
+    seq_printf(m,
                    " Number:       \t%d         \tName:          \t%s\n",
-                   ha->hanum, hrec);
-    len += size;  pos = begin + len;
+                   ha->hanum, ha->binfo.type_string);
 
+    seq_printf(m,
+                   " Driver Ver.:  \t%-10s\tFirmware Ver.: \t",
+                   GDTH_VERSION_STR);
     if (ha->more_proc)
-        sprintf(hrec, "%d.%02d.%02d-%c%03X", 
+        seq_printf(m, "%d.%02d.%02d-%c%03X\n", 
                 (u8)(ha->binfo.upd_fw_ver>>24),
                 (u8)(ha->binfo.upd_fw_ver>>16),
                 (u8)(ha->binfo.upd_fw_ver),
                 ha->bfeat.raid ? 'R':'N',
                 ha->binfo.upd_revision);
     else
-        sprintf(hrec, "%d.%02d", (u8)(ha->cpar.version>>8),
+        seq_printf(m, "%d.%02d\n", (u8)(ha->cpar.version>>8),
                 (u8)(ha->cpar.version));
-
-    size = sprintf(buffer+len,
-                   " Driver Ver.:  \t%-10s\tFirmware Ver.: \t%s\n",
-                   GDTH_VERSION_STR, hrec);
-    len += size;  pos = begin + len;
  
-    if (ha->more_proc) {
+    if (ha->more_proc)
         /* more information: 1. about controller */
-        size = sprintf(buffer+len,
+        seq_printf(m,
                        " Serial No.:   \t0x%8X\tCache RAM size:\t%d KB\n",
                        ha->binfo.ser_no, ha->binfo.memsize / 1024);
-        len += size;  pos = begin + len;
-    }
 
 #ifdef GDTH_DMA_STATISTICS
     /* controller statistics */
-    size = sprintf(buffer+len,"\nController Statistics:\n");
-    len += size;  pos = begin + len;
-    size = sprintf(buffer+len,
+    seq_printf(m,"\nController Statistics:\n");
+    seq_printf(m,
                    " 32-bit DMA buffer:\t%lu\t64-bit DMA buffer:\t%lu\n",
                    ha->dma32_cnt, ha->dma64_cnt);
-    len += size;  pos = begin + len;
 #endif
 
-    if (pos < offset) {
-        len = 0;
-        begin = pos;
-    }
-    if (pos > offset + length)
-        goto stop_output;
-
     if (ha->more_proc) {
         /* more information: 2. about physical devices */
-        size = sprintf(buffer+len,"\nPhysical Devices:");
-        len += size;  pos = begin + len;
+        seq_printf(m, "\nPhysical Devices:");
         flag = FALSE;
             
         buf = gdth_ioctl_alloc(ha, GDTH_SCRATCH, FALSE, &paddr);
@@ -309,21 +273,19 @@
                     strncpy(hrec+8,pdi->product,16);
                     strncpy(hrec+24,pdi->revision,4);
                     hrec[28] = 0;
-                    size = sprintf(buffer+len,
+                    seq_printf(m,
                                    "\n Chn/ID/LUN:   \t%c/%02d/%d    \tName:          \t%s\n",
                                    'A'+i,pdi->target_id,pdi->lun,hrec);
-                    len += size;  pos = begin + len;
                     flag = TRUE;
                     pdi->no_ldrive &= 0xffff;
                     if (pdi->no_ldrive == 0xffff)
                         strcpy(hrec,"--");
                     else
                         sprintf(hrec,"%d",pdi->no_ldrive);
-                    size = sprintf(buffer+len,
+                    seq_printf(m,
                                    " Capacity [MB]:\t%-6d    \tTo Log. Drive: \t%s\n",
                                    pdi->blkcnt/(1024*1024/pdi->blksize),
                                    hrec);
-                    len += size;  pos = begin + len;
                 } else {
                     pdi->devtype = 0xff;
                 }
@@ -333,11 +295,10 @@
                     for (k = 0; k < pds->count; ++k) {
                         if (pds->list[k].tid == pdi->target_id &&
                             pds->list[k].lun == pdi->lun) {
-                            size = sprintf(buffer+len,
+                            seq_printf(m,
                                            " Retries:      \t%-6d    \tReassigns:     \t%d\n",
                                            pds->list[k].retries,
                                            pds->list[k].reassigns);
-                            len += size;  pos = begin + len;
                             break;
                         }
                     }
@@ -355,32 +316,20 @@
                     pdef->sddc_type = 0x08;
 
                     if (gdth_execute(host, gdtcmd, cmnd, 30, NULL) == S_OK) {
-                        size = sprintf(buffer+len,
+                        seq_printf(m,
                                        " Grown Defects:\t%d\n",
                                        pdef->sddc_cnt);
-                        len += size;  pos = begin + len;
                     }
                 }
-                if (pos < offset) {
-                    len = 0;
-                    begin = pos;
-                }
-		if (pos > offset + length) {
-		    gdth_ioctl_free(ha, GDTH_SCRATCH, buf, paddr);
-                    goto stop_output;
-		}
             }
         }
         gdth_ioctl_free(ha, GDTH_SCRATCH, buf, paddr);
 
-        if (!flag) {
-            size = sprintf(buffer+len, "\n --\n");
-            len += size;  pos = begin + len;
-        }
+        if (!flag)
+            seq_printf(m, "\n --\n");
 
         /* 3. about logical drives */
-        size = sprintf(buffer+len,"\nLogical Drives:");
-        len += size;  pos = begin + len;
+        seq_printf(m,"\nLogical Drives:");
         flag = FALSE;
 
         buf = gdth_ioctl_alloc(ha, GDTH_SCRATCH, FALSE, &paddr);
@@ -418,10 +367,9 @@
                 }
                     
                 if (drv_no == i) {
-                    size = sprintf(buffer+len,
+                    seq_printf(m,
                                    "\n Number:       \t%-2d        \tStatus:        \t%s\n",
                                    drv_no, hrec);
-                    len += size;  pos = begin + len;
                     flag = TRUE;
                     no_mdrv = pcdi->cd_ldcnt;
                     if (no_mdrv > 1 || pcdi->ld_slave != -1) {
@@ -436,61 +384,37 @@
                     } else {
                         strcpy(hrec, "???");
                     }
-                    size = sprintf(buffer+len,
+                    seq_printf(m,
                                    " Capacity [MB]:\t%-6d    \tType:          \t%s\n",
                                    pcdi->ld_blkcnt/(1024*1024/pcdi->ld_blksize),
                                    hrec);
-                    len += size;  pos = begin + len;
                 } else {
-                    size = sprintf(buffer+len,
+                    seq_printf(m,
                                    " Slave Number: \t%-2d        \tStatus:        \t%s\n",
                                    drv_no & 0x7fff, hrec);
-                    len += size;  pos = begin + len;
                 }
                 drv_no = pcdi->ld_slave;
-                if (pos < offset) {
-                    len = 0;
-                    begin = pos;
-                }
-		if (pos > offset + length) {
-		    gdth_ioctl_free(ha, GDTH_SCRATCH, buf, paddr);
-                    goto stop_output;
-		}
             } while (drv_no != -1);
              
-            if (is_mirr) {
-                size = sprintf(buffer+len,
+            if (is_mirr)
+                seq_printf(m,
                                " Missing Drv.: \t%-2d        \tInvalid Drv.:  \t%d\n",
                                no_mdrv - j - k, k);
-                len += size;  pos = begin + len;
-            }
-              
+
             if (!ha->hdr[i].is_arraydrv)
                 strcpy(hrec, "--");
             else
                 sprintf(hrec, "%d", ha->hdr[i].master_no);
-            size = sprintf(buffer+len,
+            seq_printf(m,
                            " To Array Drv.:\t%s\n", hrec);
-            len += size;  pos = begin + len;
-            if (pos < offset) {
-                len = 0;
-                begin = pos;
-            }
-	    if (pos > offset + length) {
-		gdth_ioctl_free(ha, GDTH_SCRATCH, buf, paddr);
-                goto stop_output;
-	    }
         }       
         gdth_ioctl_free(ha, GDTH_SCRATCH, buf, paddr);
         
-        if (!flag) {
-            size = sprintf(buffer+len, "\n --\n");
-            len += size;  pos = begin + len;
-        }   
+        if (!flag)
+            seq_printf(m, "\n --\n");
 
         /* 4. about array drives */
-        size = sprintf(buffer+len,"\nArray Drives:");
-        len += size;  pos = begin + len;
+        seq_printf(m,"\nArray Drives:");
         flag = FALSE;
 
         buf = gdth_ioctl_alloc(ha, GDTH_SCRATCH, FALSE, &paddr);
@@ -525,10 +449,9 @@
                     strcat(hrec, "/expand");
                 else if (pai->ai_ext_state & 0x1)
                     strcat(hrec, "/patch");
-                size = sprintf(buffer+len,
+                seq_printf(m,
                                "\n Number:       \t%-2d        \tStatus:        \t%s\n",
                                i,hrec);
-                len += size;  pos = begin + len;
                 flag = TRUE;
 
                 if (pai->ai_type == 0)
@@ -539,31 +462,19 @@
                     strcpy(hrec, "RAID-5");
                 else 
                     strcpy(hrec, "RAID-10");
-                size = sprintf(buffer+len,
+                seq_printf(m,
                                " Capacity [MB]:\t%-6d    \tType:          \t%s\n",
                                pai->ai_size/(1024*1024/pai->ai_secsize),
                                hrec);
-                len += size;  pos = begin + len;
-                if (pos < offset) {
-                    len = 0;
-                    begin = pos;
-                }
-		if (pos > offset + length) {
-		    gdth_ioctl_free(ha, GDTH_SCRATCH, buf, paddr);
-                    goto stop_output;
-		}
             }
         }
         gdth_ioctl_free(ha, GDTH_SCRATCH, buf, paddr);
         
-        if (!flag) {
-            size = sprintf(buffer+len, "\n --\n");
-            len += size;  pos = begin + len;
-        }
+        if (!flag)
+            seq_printf(m, "\n --\n");
 
         /* 5. about host drives */
-        size = sprintf(buffer+len,"\nHost Drives:");
-        len += size;  pos = begin + len;
+        seq_printf(m,"\nHost Drives:");
         flag = FALSE;
 
         buf = gdth_ioctl_alloc(ha, sizeof(gdth_hget_str), FALSE, &paddr);
@@ -605,33 +516,22 @@
             if (!(ha->hdr[i].present))
                 continue;
               
-            size = sprintf(buffer+len,
+            seq_printf(m,
                            "\n Number:       \t%-2d        \tArr/Log. Drive:\t%d\n",
                            i, ha->hdr[i].ldr_no);
-            len += size;  pos = begin + len;
             flag = TRUE;
 
-            size = sprintf(buffer+len,
+            seq_printf(m,
                            " Capacity [MB]:\t%-6d    \tStart Sector:  \t%d\n",
                            (u32)(ha->hdr[i].size/2048), ha->hdr[i].start_sec);
-            len += size;  pos = begin + len;
-            if (pos < offset) {
-                len = 0;
-                begin = pos;
-            }
-            if (pos > offset + length)
-                goto stop_output;
         }
         
-        if (!flag) {
-            size = sprintf(buffer+len, "\n --\n");
-            len += size;  pos = begin + len;
-        }
+        if (!flag)
+            seq_printf(m, "\n --\n");
     }
 
     /* controller events */
-    size = sprintf(buffer+len,"\nController Events:\n");
-    len += size;  pos = begin + len;
+    seq_printf(m,"\nController Events:\n");
 
     for (id = -1;;) {
         id = gdth_read_event(ha, id, estr);
@@ -643,29 +543,14 @@
             do_gettimeofday(&tv);
             sec = (int)(tv.tv_sec - estr->first_stamp);
             if (sec < 0) sec = 0;
-            size = sprintf(buffer+len," date- %02d:%02d:%02d\t%s\n",
+            seq_printf(m," date- %02d:%02d:%02d\t%s\n",
                            sec/3600, sec%3600/60, sec%60, hrec);
-            len += size;  pos = begin + len;
-            if (pos < offset) {
-                len = 0;
-                begin = pos;
-            }
-            if (pos > offset + length)
-                goto stop_output;
         }
         if (id == -1)
             break;
     }
-
 stop_output:
-    *start = buffer +(offset-begin);
-    len -= (offset-begin);
-    if (len > length)
-        len = length;
-    TRACE2(("get_info() len %d pos %d begin %d offset %d length %d size %d\n",
-            len,(int)pos,(int)begin,(int)offset,length,size));
-    rc = len;
-
+    rc = 0;
 free_fail:
     kfree(gdtcmd);
     kfree(estr);
diff --git a/drivers/scsi/gdth_proc.h b/drivers/scsi/gdth_proc.h
index dab15f5..aaa6181 100644
--- a/drivers/scsi/gdth_proc.h
+++ b/drivers/scsi/gdth_proc.h
@@ -8,11 +8,6 @@
 int gdth_execute(struct Scsi_Host *shost, gdth_cmd_str *gdtcmd, char *cmnd,
                  int timeout, u32 *info);
 
-static int gdth_set_info(char *buffer,int length,struct Scsi_Host *host,
-                         gdth_ha_str *ha);
-static int gdth_get_info(char *buffer,char **start,off_t offset,int length,
-                         struct Scsi_Host *host, gdth_ha_str *ha);
-
 static int gdth_set_asc_info(struct Scsi_Host *host, char *buffer,
                              int length, gdth_ha_str *ha);
 
diff --git a/drivers/scsi/gvp11.c b/drivers/scsi/gvp11.c
index dbe4cc6..2203ac2 100644
--- a/drivers/scsi/gvp11.c
+++ b/drivers/scsi/gvp11.c
@@ -191,7 +191,8 @@
 static struct scsi_host_template gvp11_scsi_template = {
 	.module			= THIS_MODULE,
 	.name			= "GVP Series II SCSI",
-	.proc_info		= wd33c93_proc_info,
+	.show_info		= wd33c93_show_info,
+	.write_info		= wd33c93_write_info,
 	.proc_name		= "GVP11",
 	.queuecommand		= wd33c93_queuecommand,
 	.eh_abort_handler	= wd33c93_abort,
diff --git a/drivers/scsi/imm.c b/drivers/scsi/imm.c
index 26cd9d1..89a8266 100644
--- a/drivers/scsi/imm.c
+++ b/drivers/scsi/imm.c
@@ -121,45 +121,26 @@
  * testing...
  * Also gives a method to use a script to obtain optimum timings (TODO)
  */
-static inline int imm_proc_write(imm_struct *dev, char *buffer, int length)
+static int imm_write_info(struct Scsi_Host *host, char *buffer, int length)
 {
-	unsigned long x;
+	imm_struct *dev = imm_dev(host);
 
 	if ((length > 5) && (strncmp(buffer, "mode=", 5) == 0)) {
-		x = simple_strtoul(buffer + 5, NULL, 0);
-		dev->mode = x;
+		dev->mode = simple_strtoul(buffer + 5, NULL, 0);
 		return length;
 	}
 	printk("imm /proc: invalid variable\n");
-	return (-EINVAL);
+	return -EINVAL;
 }
 
-static int imm_proc_info(struct Scsi_Host *host, char *buffer, char **start,
-			off_t offset, int length, int inout)
+static int imm_show_info(struct seq_file *m, struct Scsi_Host *host)
 {
 	imm_struct *dev = imm_dev(host);
-	int len = 0;
 
-	if (inout)
-		return imm_proc_write(dev, buffer, length);
-
-	len += sprintf(buffer + len, "Version : %s\n", IMM_VERSION);
-	len +=
-	    sprintf(buffer + len, "Parport : %s\n",
-		    dev->dev->port->name);
-	len +=
-	    sprintf(buffer + len, "Mode    : %s\n",
-		    IMM_MODE_STRING[dev->mode]);
-
-	/* Request for beyond end of buffer */
-	if (offset > len)
-		return 0;
-
-	*start = buffer + offset;
-	len -= offset;
-	if (len > length)
-		len = length;
-	return len;
+	seq_printf(m, "Version : %s\n", IMM_VERSION);
+	seq_printf(m, "Parport : %s\n", dev->dev->port->name);
+	seq_printf(m, "Mode    : %s\n", IMM_MODE_STRING[dev->mode]);
+	return 0;
 }
 
 #if IMM_DEBUG > 0
@@ -1118,7 +1099,8 @@
 static struct scsi_host_template imm_template = {
 	.module			= THIS_MODULE,
 	.proc_name		= "imm",
-	.proc_info		= imm_proc_info,
+	.show_info		= imm_show_info,
+	.write_info		= imm_write_info,
 	.name			= "Iomega VPI2 (imm) interface",
 	.queuecommand		= imm_queuecommand,
 	.eh_abort_handler	= imm_abort,
diff --git a/drivers/scsi/in2000.c b/drivers/scsi/in2000.c
index deb5b6d..bf02821 100644
--- a/drivers/scsi/in2000.c
+++ b/drivers/scsi/in2000.c
@@ -2166,152 +2166,117 @@
 }
 
 
-static int in2000_proc_info(struct Scsi_Host *instance, char *buf, char **start, off_t off, int len, int in)
+static int in2000_write_info(struct Scsi_Host *instance, char *buf, int len)
 {
 
 #ifdef PROC_INTERFACE
 
 	char *bp;
-	char tbuf[128];
-	unsigned long flags;
 	struct IN2000_hostdata *hd;
-	Scsi_Cmnd *cmd;
 	int x, i;
-	static int stop = 0;
 
 	hd = (struct IN2000_hostdata *) instance->hostdata;
 
-/* If 'in' is TRUE we need to _read_ the proc file. We accept the following
- * keywords (same format as command-line, but only ONE per read):
- *    debug
- *    disconnect
- *    period
- *    resync
- *    proc
- */
-
-	if (in) {
-		buf[len] = '\0';
-		bp = buf;
-		if (!strncmp(bp, "debug:", 6)) {
-			bp += 6;
-			hd->args = simple_strtoul(bp, NULL, 0) & DB_MASK;
-		} else if (!strncmp(bp, "disconnect:", 11)) {
-			bp += 11;
-			x = simple_strtoul(bp, NULL, 0);
-			if (x < DIS_NEVER || x > DIS_ALWAYS)
-				x = DIS_ADAPTIVE;
-			hd->disconnect = x;
-		} else if (!strncmp(bp, "period:", 7)) {
-			bp += 7;
-			x = simple_strtoul(bp, NULL, 0);
-			hd->default_sx_per = sx_table[round_period((unsigned int) x)].period_ns;
-		} else if (!strncmp(bp, "resync:", 7)) {
-			bp += 7;
-			x = simple_strtoul(bp, NULL, 0);
-			for (i = 0; i < 7; i++)
-				if (x & (1 << i))
-					hd->sync_stat[i] = SS_UNSET;
-		} else if (!strncmp(bp, "proc:", 5)) {
-			bp += 5;
-			hd->proc = simple_strtoul(bp, NULL, 0);
-		} else if (!strncmp(bp, "level2:", 7)) {
-			bp += 7;
-			hd->level2 = simple_strtoul(bp, NULL, 0);
-		}
-		return len;
+	buf[len] = '\0';
+	bp = buf;
+	if (!strncmp(bp, "debug:", 6)) {
+		bp += 6;
+		hd->args = simple_strtoul(bp, NULL, 0) & DB_MASK;
+	} else if (!strncmp(bp, "disconnect:", 11)) {
+		bp += 11;
+		x = simple_strtoul(bp, NULL, 0);
+		if (x < DIS_NEVER || x > DIS_ALWAYS)
+			x = DIS_ADAPTIVE;
+		hd->disconnect = x;
+	} else if (!strncmp(bp, "period:", 7)) {
+		bp += 7;
+		x = simple_strtoul(bp, NULL, 0);
+		hd->default_sx_per = sx_table[round_period((unsigned int) x)].period_ns;
+	} else if (!strncmp(bp, "resync:", 7)) {
+		bp += 7;
+		x = simple_strtoul(bp, NULL, 0);
+		for (i = 0; i < 7; i++)
+			if (x & (1 << i))
+				hd->sync_stat[i] = SS_UNSET;
+	} else if (!strncmp(bp, "proc:", 5)) {
+		bp += 5;
+		hd->proc = simple_strtoul(bp, NULL, 0);
+	} else if (!strncmp(bp, "level2:", 7)) {
+		bp += 7;
+		hd->level2 = simple_strtoul(bp, NULL, 0);
 	}
+#endif
+	return len;
+}
+
+static int in2000_show_info(struct seq_file *m, struct Scsi_Host *instance)
+{
+
+#ifdef PROC_INTERFACE
+	unsigned long flags;
+	struct IN2000_hostdata *hd;
+	Scsi_Cmnd *cmd;
+	int x;
+
+	hd = (struct IN2000_hostdata *) instance->hostdata;
 
 	spin_lock_irqsave(instance->host_lock, flags);
-	bp = buf;
-	*bp = '\0';
-	if (hd->proc & PR_VERSION) {
-		sprintf(tbuf, "\nVersion %s - %s.", IN2000_VERSION, IN2000_DATE);
-		strcat(bp, tbuf);
-	}
+	if (hd->proc & PR_VERSION)
+		seq_printf(m, "\nVersion %s - %s.", IN2000_VERSION, IN2000_DATE);
+
 	if (hd->proc & PR_INFO) {
-		sprintf(tbuf, "\ndip_switch=%02x: irq=%d io=%02x floppy=%s sync/DOS5=%s", (hd->dip_switch & 0x7f), instance->irq, hd->io_base, (hd->dip_switch & 0x40) ? "Yes" : "No", (hd->dip_switch & 0x20) ? "Yes" : "No");
-		strcat(bp, tbuf);
-		strcat(bp, "\nsync_xfer[] =       ");
-		for (x = 0; x < 7; x++) {
-			sprintf(tbuf, "\t%02x", hd->sync_xfer[x]);
-			strcat(bp, tbuf);
-		}
-		strcat(bp, "\nsync_stat[] =       ");
-		for (x = 0; x < 7; x++) {
-			sprintf(tbuf, "\t%02x", hd->sync_stat[x]);
-			strcat(bp, tbuf);
-		}
+		seq_printf(m, "\ndip_switch=%02x: irq=%d io=%02x floppy=%s sync/DOS5=%s", (hd->dip_switch & 0x7f), instance->irq, hd->io_base, (hd->dip_switch & 0x40) ? "Yes" : "No", (hd->dip_switch & 0x20) ? "Yes" : "No");
+		seq_printf(m, "\nsync_xfer[] =       ");
+		for (x = 0; x < 7; x++)
+			seq_printf(m, "\t%02x", hd->sync_xfer[x]);
+		seq_printf(m, "\nsync_stat[] =       ");
+		for (x = 0; x < 7; x++)
+			seq_printf(m, "\t%02x", hd->sync_stat[x]);
 	}
 #ifdef PROC_STATISTICS
 	if (hd->proc & PR_STATISTICS) {
-		strcat(bp, "\ncommands issued:    ");
-		for (x = 0; x < 7; x++) {
-			sprintf(tbuf, "\t%ld", hd->cmd_cnt[x]);
-			strcat(bp, tbuf);
-		}
-		strcat(bp, "\ndisconnects allowed:");
-		for (x = 0; x < 7; x++) {
-			sprintf(tbuf, "\t%ld", hd->disc_allowed_cnt[x]);
-			strcat(bp, tbuf);
-		}
-		strcat(bp, "\ndisconnects done:   ");
-		for (x = 0; x < 7; x++) {
-			sprintf(tbuf, "\t%ld", hd->disc_done_cnt[x]);
-			strcat(bp, tbuf);
-		}
-		sprintf(tbuf, "\ninterrupts:      \t%ld", hd->int_cnt);
-		strcat(bp, tbuf);
+		seq_printf(m, "\ncommands issued:    ");
+		for (x = 0; x < 7; x++)
+			seq_printf(m, "\t%ld", hd->cmd_cnt[x]);
+		seq_printf(m, "\ndisconnects allowed:");
+		for (x = 0; x < 7; x++)
+			seq_printf(m, "\t%ld", hd->disc_allowed_cnt[x]);
+		seq_printf(m, "\ndisconnects done:   ");
+		for (x = 0; x < 7; x++)
+			seq_printf(m, "\t%ld", hd->disc_done_cnt[x]);
+		seq_printf(m, "\ninterrupts:      \t%ld", hd->int_cnt);
 	}
 #endif
 	if (hd->proc & PR_CONNECTED) {
-		strcat(bp, "\nconnected:     ");
+		seq_printf(m, "\nconnected:     ");
 		if (hd->connected) {
 			cmd = (Scsi_Cmnd *) hd->connected;
-			sprintf(tbuf, " %d:%d(%02x)", cmd->device->id, cmd->device->lun, cmd->cmnd[0]);
-			strcat(bp, tbuf);
+			seq_printf(m, " %d:%d(%02x)", cmd->device->id, cmd->device->lun, cmd->cmnd[0]);
 		}
 	}
 	if (hd->proc & PR_INPUTQ) {
-		strcat(bp, "\ninput_Q:       ");
+		seq_printf(m, "\ninput_Q:       ");
 		cmd = (Scsi_Cmnd *) hd->input_Q;
 		while (cmd) {
-			sprintf(tbuf, " %d:%d(%02x)", cmd->device->id, cmd->device->lun, cmd->cmnd[0]);
-			strcat(bp, tbuf);
+			seq_printf(m, " %d:%d(%02x)", cmd->device->id, cmd->device->lun, cmd->cmnd[0]);
 			cmd = (Scsi_Cmnd *) cmd->host_scribble;
 		}
 	}
 	if (hd->proc & PR_DISCQ) {
-		strcat(bp, "\ndisconnected_Q:");
+		seq_printf(m, "\ndisconnected_Q:");
 		cmd = (Scsi_Cmnd *) hd->disconnected_Q;
 		while (cmd) {
-			sprintf(tbuf, " %d:%d(%02x)", cmd->device->id, cmd->device->lun, cmd->cmnd[0]);
-			strcat(bp, tbuf);
+			seq_printf(m, " %d:%d(%02x)", cmd->device->id, cmd->device->lun, cmd->cmnd[0]);
 			cmd = (Scsi_Cmnd *) cmd->host_scribble;
 		}
 	}
 	if (hd->proc & PR_TEST) {
 		;		/* insert your own custom function here */
 	}
-	strcat(bp, "\n");
+	seq_printf(m, "\n");
 	spin_unlock_irqrestore(instance->host_lock, flags);
-	*start = buf;
-	if (stop) {
-		stop = 0;
-		return 0;	/* return 0 to signal end-of-file */
-	}
-	if (off > 0x40000)	/* ALWAYS stop after 256k bytes have been read */
-		stop = 1;
-	if (hd->proc & PR_STOP)	/* stop every other time */
-		stop = 1;
-	return strlen(bp);
-
-#else				/* PROC_INTERFACE */
-
-	return 0;
-
 #endif				/* PROC_INTERFACE */
-
+	return 0;
 }
 
 MODULE_LICENSE("GPL");
@@ -2319,7 +2284,8 @@
 
 static struct scsi_host_template driver_template = {
 	.proc_name       		= "in2000",
-	.proc_info       		= in2000_proc_info,
+	.write_info       		= in2000_write_info,
+	.show_info       		= in2000_show_info,
 	.name            		= "Always IN2000",
 	.detect          		= in2000_detect, 
 	.release			= in2000_release,
diff --git a/drivers/scsi/ips.c b/drivers/scsi/ips.c
index 9aa86a3..8d5ea8a 100644
--- a/drivers/scsi/ips.c
+++ b/drivers/scsi/ips.c
@@ -326,10 +326,9 @@
 static void ips_scmd_buf_read(struct scsi_cmnd * scmd, void *data,
 			      unsigned int count);
 
-static int ips_proc_info(struct Scsi_Host *, char *, char **, off_t, int, int);
-static int ips_host_info(ips_ha_t *, char *, off_t, int);
-static void copy_mem_info(IPS_INFOSTR *, char *, int);
-static int copy_info(IPS_INFOSTR *, char *, ...);
+static int ips_write_info(struct Scsi_Host *, char *, int);
+static int ips_show_info(struct seq_file *, struct Scsi_Host *);
+static int ips_host_info(ips_ha_t *, struct seq_file *);
 static int ips_abort_init(ips_ha_t * ha, int index);
 static int ips_init_phase2(int index);
 
@@ -367,7 +366,8 @@
 	.eh_abort_handler	= ips_eh_abort,
 	.eh_host_reset_handler	= ips_eh_reset,
 	.proc_name		= "ips",
-	.proc_info		= ips_proc_info,
+	.show_info		= ips_show_info,
+	.write_info		= ips_write_info,
 	.slave_configure	= ips_slave_configure,
 	.bios_param		= ips_biosparam,
 	.this_id		= -1,
@@ -1433,25 +1433,12 @@
 	return (bp);
 }
 
-/****************************************************************************/
-/*                                                                          */
-/* Routine Name: ips_proc_info                                              */
-/*                                                                          */
-/* Routine Description:                                                     */
-/*                                                                          */
-/*   The passthru interface for the driver                                  */
-/*                                                                          */
-/****************************************************************************/
 static int
-ips_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t offset,
-	      int length, int func)
+ips_write_info(struct Scsi_Host *host, char *buffer, int length)
 {
 	int i;
-	int ret;
 	ips_ha_t *ha = NULL;
 
-	METHOD_TRACE("ips_proc_info", 1);
-
 	/* Find our host structure */
 	for (i = 0; i < ips_next_controller; i++) {
 		if (ips_sh[i]) {
@@ -1465,18 +1452,29 @@
 	if (!ha)
 		return (-EINVAL);
 
-	if (func) {
-		/* write */
-		return (0);
-	} else {
-		/* read */
-		if (start)
-			*start = buffer;
+	return 0;
+}
 
-		ret = ips_host_info(ha, buffer, offset, length);
+static int
+ips_show_info(struct seq_file *m, struct Scsi_Host *host)
+{
+	int i;
+	ips_ha_t *ha = NULL;
 
-		return (ret);
+	/* Find our host structure */
+	for (i = 0; i < ips_next_controller; i++) {
+		if (ips_sh[i]) {
+			if (ips_sh[i] == host) {
+				ha = (ips_ha_t *) ips_sh[i]->hostdata;
+				break;
+			}
+		}
 	}
+
+	if (!ha)
+		return (-EINVAL);
+
+	return ips_host_info(ha, m);
 }
 
 /*--------------------------------------------------------------------------*/
@@ -2035,183 +2033,113 @@
 /*                                                                          */
 /****************************************************************************/
 static int
-ips_host_info(ips_ha_t * ha, char *ptr, off_t offset, int len)
+ips_host_info(ips_ha_t *ha, struct seq_file *m)
 {
-	IPS_INFOSTR info;
-
 	METHOD_TRACE("ips_host_info", 1);
 
-	info.buffer = ptr;
-	info.length = len;
-	info.offset = offset;
-	info.pos = 0;
-	info.localpos = 0;
-
-	copy_info(&info, "\nIBM ServeRAID General Information:\n\n");
+	seq_printf(m, "\nIBM ServeRAID General Information:\n\n");
 
 	if ((le32_to_cpu(ha->nvram->signature) == IPS_NVRAM_P5_SIG) &&
 	    (le16_to_cpu(ha->nvram->adapter_type) != 0))
-		copy_info(&info, "\tController Type                   : %s\n",
+		seq_printf(m, "\tController Type                   : %s\n",
 			  ips_adapter_name[ha->ad_type - 1]);
 	else
-		copy_info(&info,
+		seq_printf(m,
 			  "\tController Type                   : Unknown\n");
 
 	if (ha->io_addr)
-		copy_info(&info,
-			  "\tIO region                         : 0x%lx (%d bytes)\n",
+		seq_printf(m,
+			  "\tIO region                         : 0x%x (%d bytes)\n",
 			  ha->io_addr, ha->io_len);
 
 	if (ha->mem_addr) {
-		copy_info(&info,
-			  "\tMemory region                     : 0x%lx (%d bytes)\n",
+		seq_printf(m,
+			  "\tMemory region                     : 0x%x (%d bytes)\n",
 			  ha->mem_addr, ha->mem_len);
-		copy_info(&info,
+		seq_printf(m,
 			  "\tShared memory address             : 0x%lx\n",
-			  ha->mem_ptr);
+			  (unsigned long)ha->mem_ptr);
 	}
 
-	copy_info(&info, "\tIRQ number                        : %d\n", ha->pcidev->irq);
+	seq_printf(m, "\tIRQ number                        : %d\n", ha->pcidev->irq);
 
     /* For the Next 3 lines Check for Binary 0 at the end and don't include it if it's there. */
     /* That keeps everything happy for "text" operations on the proc file.                    */
 
 	if (le32_to_cpu(ha->nvram->signature) == IPS_NVRAM_P5_SIG) {
 	if (ha->nvram->bios_low[3] == 0) {
-            copy_info(&info,
-			          "\tBIOS Version                      : %c%c%c%c%c%c%c\n",
-			          ha->nvram->bios_high[0], ha->nvram->bios_high[1],
-			          ha->nvram->bios_high[2], ha->nvram->bios_high[3],
-			          ha->nvram->bios_low[0], ha->nvram->bios_low[1],
-			          ha->nvram->bios_low[2]);
+		seq_printf(m,
+			  "\tBIOS Version                      : %c%c%c%c%c%c%c\n",
+			  ha->nvram->bios_high[0], ha->nvram->bios_high[1],
+			  ha->nvram->bios_high[2], ha->nvram->bios_high[3],
+			  ha->nvram->bios_low[0], ha->nvram->bios_low[1],
+			  ha->nvram->bios_low[2]);
 
         } else {
-		    copy_info(&info,
-			          "\tBIOS Version                      : %c%c%c%c%c%c%c%c\n",
-			          ha->nvram->bios_high[0], ha->nvram->bios_high[1],
-			          ha->nvram->bios_high[2], ha->nvram->bios_high[3],
-			          ha->nvram->bios_low[0], ha->nvram->bios_low[1],
-			          ha->nvram->bios_low[2], ha->nvram->bios_low[3]);
+		seq_printf(m,
+			  "\tBIOS Version                      : %c%c%c%c%c%c%c%c\n",
+			  ha->nvram->bios_high[0], ha->nvram->bios_high[1],
+			  ha->nvram->bios_high[2], ha->nvram->bios_high[3],
+			  ha->nvram->bios_low[0], ha->nvram->bios_low[1],
+			  ha->nvram->bios_low[2], ha->nvram->bios_low[3]);
         }
 
     }
 
     if (ha->enq->CodeBlkVersion[7] == 0) {
-        copy_info(&info,
-		          "\tFirmware Version                  : %c%c%c%c%c%c%c\n",
-		          ha->enq->CodeBlkVersion[0], ha->enq->CodeBlkVersion[1],
-		          ha->enq->CodeBlkVersion[2], ha->enq->CodeBlkVersion[3],
-		          ha->enq->CodeBlkVersion[4], ha->enq->CodeBlkVersion[5],
-		          ha->enq->CodeBlkVersion[6]);
+        seq_printf(m,
+		  "\tFirmware Version                  : %c%c%c%c%c%c%c\n",
+		  ha->enq->CodeBlkVersion[0], ha->enq->CodeBlkVersion[1],
+		  ha->enq->CodeBlkVersion[2], ha->enq->CodeBlkVersion[3],
+		  ha->enq->CodeBlkVersion[4], ha->enq->CodeBlkVersion[5],
+		  ha->enq->CodeBlkVersion[6]);
     } else {
-        copy_info(&info,
-		          "\tFirmware Version                  : %c%c%c%c%c%c%c%c\n",
-		          ha->enq->CodeBlkVersion[0], ha->enq->CodeBlkVersion[1],
-		          ha->enq->CodeBlkVersion[2], ha->enq->CodeBlkVersion[3],
-		          ha->enq->CodeBlkVersion[4], ha->enq->CodeBlkVersion[5],
-		          ha->enq->CodeBlkVersion[6], ha->enq->CodeBlkVersion[7]);
+	seq_printf(m,
+		  "\tFirmware Version                  : %c%c%c%c%c%c%c%c\n",
+		  ha->enq->CodeBlkVersion[0], ha->enq->CodeBlkVersion[1],
+		  ha->enq->CodeBlkVersion[2], ha->enq->CodeBlkVersion[3],
+		  ha->enq->CodeBlkVersion[4], ha->enq->CodeBlkVersion[5],
+		  ha->enq->CodeBlkVersion[6], ha->enq->CodeBlkVersion[7]);
     }
 
     if (ha->enq->BootBlkVersion[7] == 0) {
-        copy_info(&info,
-		          "\tBoot Block Version                : %c%c%c%c%c%c%c\n",
-		          ha->enq->BootBlkVersion[0], ha->enq->BootBlkVersion[1],
-		          ha->enq->BootBlkVersion[2], ha->enq->BootBlkVersion[3],
-		          ha->enq->BootBlkVersion[4], ha->enq->BootBlkVersion[5],
-		          ha->enq->BootBlkVersion[6]);
+        seq_printf(m,
+		  "\tBoot Block Version                : %c%c%c%c%c%c%c\n",
+		  ha->enq->BootBlkVersion[0], ha->enq->BootBlkVersion[1],
+		  ha->enq->BootBlkVersion[2], ha->enq->BootBlkVersion[3],
+		  ha->enq->BootBlkVersion[4], ha->enq->BootBlkVersion[5],
+		  ha->enq->BootBlkVersion[6]);
     } else {
-        copy_info(&info,
-		          "\tBoot Block Version                : %c%c%c%c%c%c%c%c\n",
-		          ha->enq->BootBlkVersion[0], ha->enq->BootBlkVersion[1],
-		          ha->enq->BootBlkVersion[2], ha->enq->BootBlkVersion[3],
-		          ha->enq->BootBlkVersion[4], ha->enq->BootBlkVersion[5],
-		          ha->enq->BootBlkVersion[6], ha->enq->BootBlkVersion[7]);
+        seq_printf(m,
+		  "\tBoot Block Version                : %c%c%c%c%c%c%c%c\n",
+		  ha->enq->BootBlkVersion[0], ha->enq->BootBlkVersion[1],
+		  ha->enq->BootBlkVersion[2], ha->enq->BootBlkVersion[3],
+		  ha->enq->BootBlkVersion[4], ha->enq->BootBlkVersion[5],
+		  ha->enq->BootBlkVersion[6], ha->enq->BootBlkVersion[7]);
     }
 
-	copy_info(&info, "\tDriver Version                    : %s%s\n",
+	seq_printf(m, "\tDriver Version                    : %s%s\n",
 		  IPS_VERSION_HIGH, IPS_VERSION_LOW);
 
-	copy_info(&info, "\tDriver Build                      : %d\n",
+	seq_printf(m, "\tDriver Build                      : %d\n",
 		  IPS_BUILD_IDENT);
 
-	copy_info(&info, "\tMax Physical Devices              : %d\n",
+	seq_printf(m, "\tMax Physical Devices              : %d\n",
 		  ha->enq->ucMaxPhysicalDevices);
-	copy_info(&info, "\tMax Active Commands               : %d\n",
+	seq_printf(m, "\tMax Active Commands               : %d\n",
 		  ha->max_cmds);
-	copy_info(&info, "\tCurrent Queued Commands           : %d\n",
+	seq_printf(m, "\tCurrent Queued Commands           : %d\n",
 		  ha->scb_waitlist.count);
-	copy_info(&info, "\tCurrent Active Commands           : %d\n",
+	seq_printf(m, "\tCurrent Active Commands           : %d\n",
 		  ha->scb_activelist.count - ha->num_ioctl);
-	copy_info(&info, "\tCurrent Queued PT Commands        : %d\n",
+	seq_printf(m, "\tCurrent Queued PT Commands        : %d\n",
 		  ha->copp_waitlist.count);
-	copy_info(&info, "\tCurrent Active PT Commands        : %d\n",
+	seq_printf(m, "\tCurrent Active PT Commands        : %d\n",
 		  ha->num_ioctl);
 
-	copy_info(&info, "\n");
+	seq_printf(m, "\n");
 
-	return (info.localpos);
-}
-
-/****************************************************************************/
-/*                                                                          */
-/* Routine Name: copy_mem_info                                              */
-/*                                                                          */
-/* Routine Description:                                                     */
-/*                                                                          */
-/*   Copy data into an IPS_INFOSTR structure                                */
-/*                                                                          */
-/****************************************************************************/
-static void
-copy_mem_info(IPS_INFOSTR * info, char *data, int len)
-{
-	METHOD_TRACE("copy_mem_info", 1);
-
-	if (info->pos + len < info->offset) {
-		info->pos += len;
-		return;
-	}
-
-	if (info->pos < info->offset) {
-		data += (info->offset - info->pos);
-		len -= (info->offset - info->pos);
-		info->pos += (info->offset - info->pos);
-	}
-
-	if (info->localpos + len > info->length)
-		len = info->length - info->localpos;
-
-	if (len > 0) {
-		memcpy(info->buffer + info->localpos, data, len);
-		info->pos += len;
-		info->localpos += len;
-	}
-}
-
-/****************************************************************************/
-/*                                                                          */
-/* Routine Name: copy_info                                                  */
-/*                                                                          */
-/* Routine Description:                                                     */
-/*                                                                          */
-/*   printf style wrapper for an info structure                             */
-/*                                                                          */
-/****************************************************************************/
-static int
-copy_info(IPS_INFOSTR * info, char *fmt, ...)
-{
-	va_list args;
-	char buf[128];
-	int len;
-
-	METHOD_TRACE("copy_info", 1);
-
-	va_start(args, fmt);
-	len = vsprintf(buf, fmt, args);
-	va_end(args);
-
-	copy_mem_info(info, buf, len);
-
-	return (len);
+	return 0;
 }
 
 /****************************************************************************/
diff --git a/drivers/scsi/ips.h b/drivers/scsi/ips.h
index f2df059..45b9566 100644
--- a/drivers/scsi/ips.h
+++ b/drivers/scsi/ips.h
@@ -416,7 +416,6 @@
    /*
     * Scsi_Host Template
     */
-   static int ips_proc_info(struct Scsi_Host *, char *, char **, off_t, int, int);
    static int ips_biosparam(struct scsi_device *sdev, struct block_device *bdev,
 		sector_t capacity, int geom[]);
    static int ips_slave_configure(struct scsi_device *SDptr);
@@ -959,14 +958,6 @@
    IPS_ENH_SG_LIST  *enh_list;
 } IPS_SG_LIST;
 
-typedef struct _IPS_INFOSTR {
-   char *buffer;
-   int   length;
-   int   offset;
-   int   pos;
-   int   localpos;
-} IPS_INFOSTR;
-
 typedef struct {
    char *option_name;
    int  *option_flag;
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c
index 5da2972..90b8b05 100644
--- a/drivers/scsi/lpfc/lpfc_init.c
+++ b/drivers/scsi/lpfc/lpfc_init.c
@@ -10394,36 +10394,6 @@
 	return;
 }
 
-/**
- * lpfc_mgmt_open - method called when 'lpfcmgmt' is opened from userspace
- * @inode: pointer to the inode representing the lpfcmgmt device
- * @filep: pointer to the file representing the open lpfcmgmt device
- *
- * This routine puts a reference count on the lpfc module whenever the
- * character device is opened
- **/
-static int
-lpfc_mgmt_open(struct inode *inode, struct file *filep)
-{
-	try_module_get(THIS_MODULE);
-	return 0;
-}
-
-/**
- * lpfc_mgmt_release - method called when 'lpfcmgmt' is closed in userspace
- * @inode: pointer to the inode representing the lpfcmgmt device
- * @filep: pointer to the file representing the open lpfcmgmt device
- *
- * This routine removes a reference count from the lpfc module when the
- * character device is closed
- **/
-static int
-lpfc_mgmt_release(struct inode *inode, struct file *filep)
-{
-	module_put(THIS_MODULE);
-	return 0;
-}
-
 static struct pci_device_id lpfc_id_table[] = {
 	{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_VIPER,
 		PCI_ANY_ID, PCI_ANY_ID, },
@@ -10541,8 +10511,7 @@
 };
 
 static const struct file_operations lpfc_mgmt_fop = {
-	.open = lpfc_mgmt_open,
-	.release = lpfc_mgmt_release,
+	.owner = THIS_MODULE,
 };
 
 static struct miscdevice lpfc_mgmt_dev = {
diff --git a/drivers/scsi/mac_scsi.c b/drivers/scsi/mac_scsi.c
index 24828b5..8580757 100644
--- a/drivers/scsi/mac_scsi.c
+++ b/drivers/scsi/mac_scsi.c
@@ -561,7 +561,8 @@
 
 static struct scsi_host_template driver_template = {
 	.proc_name			= "Mac5380",
-	.proc_info			= macscsi_proc_info,
+	.show_info			= macscsi_show_info,
+	.write_info			= macscsi_write_info,
 	.name				= "Macintosh NCR5380 SCSI",
 	.detect				= macscsi_detect,
 	.release			= macscsi_release,
diff --git a/drivers/scsi/mac_scsi.h b/drivers/scsi/mac_scsi.h
index d26e331..7dc62fc 100644
--- a/drivers/scsi/mac_scsi.h
+++ b/drivers/scsi/mac_scsi.h
@@ -72,7 +72,8 @@
 #define NCR5380_queue_command macscsi_queue_command
 #define NCR5380_abort macscsi_abort
 #define NCR5380_bus_reset macscsi_bus_reset
-#define NCR5380_proc_info macscsi_proc_info
+#define NCR5380_show_info macscsi_show_info
+#define NCR5380_write_info macscsi_write_info
 
 #define BOARD_NORMAL	0
 #define BOARD_NCR53C400	1
diff --git a/drivers/scsi/megaraid.c b/drivers/scsi/megaraid.c
index 9504ec0..7373255 100644
--- a/drivers/scsi/megaraid.c
+++ b/drivers/scsi/megaraid.c
@@ -39,6 +39,7 @@
 #include <linux/completion.h>
 #include <linux/delay.h>
 #include <linux/proc_fs.h>
+#include <linux/seq_file.h>
 #include <linux/reboot.h>
 #include <linux/module.h>
 #include <linux/list.h>
@@ -2069,385 +2070,201 @@
 #ifdef CONFIG_PROC_FS
 /* Following code handles /proc fs  */
 
-#define CREATE_READ_PROC(string, func)	create_proc_read_entry(string,	\
-					S_IRUSR | S_IFREG,		\
-					controller_proc_dir_entry,	\
-					func, adapter)
-
 /**
- * mega_create_proc_entry()
- * @index - index in soft state array
- * @parent - parent node for this /proc entry
- *
- * Creates /proc entries for our controllers.
- */
-static void
-mega_create_proc_entry(int index, struct proc_dir_entry *parent)
-{
-	struct proc_dir_entry	*controller_proc_dir_entry = NULL;
-	u8		string[64] = { 0 };
-	adapter_t	*adapter = hba_soft_state[index];
-
-	sprintf(string, "hba%d", adapter->host->host_no);
-
-	controller_proc_dir_entry =
-		adapter->controller_proc_dir_entry = proc_mkdir(string, parent);
-
-	if(!controller_proc_dir_entry) {
-		printk(KERN_WARNING "\nmegaraid: proc_mkdir failed\n");
-		return;
-	}
-	adapter->proc_read = CREATE_READ_PROC("config", proc_read_config);
-	adapter->proc_stat = CREATE_READ_PROC("stat", proc_read_stat);
-	adapter->proc_mbox = CREATE_READ_PROC("mailbox", proc_read_mbox);
-#if MEGA_HAVE_ENH_PROC
-	adapter->proc_rr = CREATE_READ_PROC("rebuild-rate", proc_rebuild_rate);
-	adapter->proc_battery = CREATE_READ_PROC("battery-status",
-			proc_battery);
-
-	/*
-	 * Display each physical drive on its channel
-	 */
-	adapter->proc_pdrvstat[0] = CREATE_READ_PROC("diskdrives-ch0",
-					proc_pdrv_ch0);
-	adapter->proc_pdrvstat[1] = CREATE_READ_PROC("diskdrives-ch1",
-					proc_pdrv_ch1);
-	adapter->proc_pdrvstat[2] = CREATE_READ_PROC("diskdrives-ch2",
-					proc_pdrv_ch2);
-	adapter->proc_pdrvstat[3] = CREATE_READ_PROC("diskdrives-ch3",
-					proc_pdrv_ch3);
-
-	/*
-	 * Display a set of up to 10 logical drive through each of following
-	 * /proc entries
-	 */
-	adapter->proc_rdrvstat[0] = CREATE_READ_PROC("raiddrives-0-9",
-					proc_rdrv_10);
-	adapter->proc_rdrvstat[1] = CREATE_READ_PROC("raiddrives-10-19",
-					proc_rdrv_20);
-	adapter->proc_rdrvstat[2] = CREATE_READ_PROC("raiddrives-20-29",
-					proc_rdrv_30);
-	adapter->proc_rdrvstat[3] = CREATE_READ_PROC("raiddrives-30-39",
-					proc_rdrv_40);
-#endif
-}
-
-
-/**
- * proc_read_config()
- * @page - buffer to write the data in
- * @start - where the actual data has been written in page
- * @offset - same meaning as the read system call
- * @count - same meaning as the read system call
- * @eof - set if no more data needs to be returned
- * @data - pointer to our soft state
+ * proc_show_config()
+ * @m - Synthetic file construction data
+ * @v - File iterator
  *
  * Display configuration information about the controller.
  */
 static int
-proc_read_config(char *page, char **start, off_t offset, int count, int *eof,
-		void *data)
+proc_show_config(struct seq_file *m, void *v)
 {
 
-	adapter_t *adapter = (adapter_t *)data;
-	int len = 0;
+	adapter_t *adapter = m->private;
 
-	len += sprintf(page+len, "%s", MEGARAID_VERSION);
-
+	seq_puts(m, MEGARAID_VERSION);
 	if(adapter->product_info.product_name[0])
-		len += sprintf(page+len, "%s\n",
-				adapter->product_info.product_name);
+		seq_printf(m, "%s\n", adapter->product_info.product_name);
 
-	len += sprintf(page+len, "Controller Type: ");
+	seq_puts(m, "Controller Type: ");
 
-	if( adapter->flag & BOARD_MEMMAP ) {
-		len += sprintf(page+len,
-			"438/466/467/471/493/518/520/531/532\n");
-	}
-	else {
-		len += sprintf(page+len,
-			"418/428/434\n");
-	}
+	if( adapter->flag & BOARD_MEMMAP )
+		seq_puts(m, "438/466/467/471/493/518/520/531/532\n");
+	else
+		seq_puts(m, "418/428/434\n");
 
-	if(adapter->flag & BOARD_40LD) {
-		len += sprintf(page+len,
-				"Controller Supports 40 Logical Drives\n");
-	}
+	if(adapter->flag & BOARD_40LD)
+		seq_puts(m, "Controller Supports 40 Logical Drives\n");
 
-	if(adapter->flag & BOARD_64BIT) {
-		len += sprintf(page+len,
-		"Controller capable of 64-bit memory addressing\n");
-	}
-	if( adapter->has_64bit_addr ) {
-		len += sprintf(page+len,
-			"Controller using 64-bit memory addressing\n");
-	}
-	else {
-		len += sprintf(page+len,
-			"Controller is not using 64-bit memory addressing\n");
-	}
+	if(adapter->flag & BOARD_64BIT)
+		seq_puts(m, "Controller capable of 64-bit memory addressing\n");
+	if( adapter->has_64bit_addr )
+		seq_puts(m, "Controller using 64-bit memory addressing\n");
+	else
+		seq_puts(m, "Controller is not using 64-bit memory addressing\n");
 
-	len += sprintf(page+len, "Base = %08lx, Irq = %d, ", adapter->base,
-			adapter->host->irq);
+	seq_printf(m, "Base = %08lx, Irq = %d, ",
+		   adapter->base, adapter->host->irq);
 
-	len += sprintf(page+len, "Logical Drives = %d, Channels = %d\n",
-			adapter->numldrv, adapter->product_info.nchannels);
+	seq_printf(m, "Logical Drives = %d, Channels = %d\n",
+		   adapter->numldrv, adapter->product_info.nchannels);
 
-	len += sprintf(page+len, "Version =%s:%s, DRAM = %dMb\n",
-			adapter->fw_version, adapter->bios_version,
-			adapter->product_info.dram_size);
+	seq_printf(m, "Version =%s:%s, DRAM = %dMb\n",
+		   adapter->fw_version, adapter->bios_version,
+		   adapter->product_info.dram_size);
 
-	len += sprintf(page+len,
-		"Controller Queue Depth = %d, Driver Queue Depth = %d\n",
-		adapter->product_info.max_commands, adapter->max_cmds);
+	seq_printf(m, "Controller Queue Depth = %d, Driver Queue Depth = %d\n",
+		   adapter->product_info.max_commands, adapter->max_cmds);
 
-	len += sprintf(page+len, "support_ext_cdb    = %d\n",
-			adapter->support_ext_cdb);
-	len += sprintf(page+len, "support_random_del = %d\n",
-			adapter->support_random_del);
-	len += sprintf(page+len, "boot_ldrv_enabled  = %d\n",
-			adapter->boot_ldrv_enabled);
-	len += sprintf(page+len, "boot_ldrv          = %d\n",
-			adapter->boot_ldrv);
-	len += sprintf(page+len, "boot_pdrv_enabled  = %d\n",
-			adapter->boot_pdrv_enabled);
-	len += sprintf(page+len, "boot_pdrv_ch       = %d\n",
-			adapter->boot_pdrv_ch);
-	len += sprintf(page+len, "boot_pdrv_tgt      = %d\n",
-			adapter->boot_pdrv_tgt);
-	len += sprintf(page+len, "quiescent          = %d\n",
-			atomic_read(&adapter->quiescent));
-	len += sprintf(page+len, "has_cluster        = %d\n",
-			adapter->has_cluster);
+	seq_printf(m, "support_ext_cdb    = %d\n", adapter->support_ext_cdb);
+	seq_printf(m, "support_random_del = %d\n", adapter->support_random_del);
+	seq_printf(m, "boot_ldrv_enabled  = %d\n", adapter->boot_ldrv_enabled);
+	seq_printf(m, "boot_ldrv          = %d\n", adapter->boot_ldrv);
+	seq_printf(m, "boot_pdrv_enabled  = %d\n", adapter->boot_pdrv_enabled);
+	seq_printf(m, "boot_pdrv_ch       = %d\n", adapter->boot_pdrv_ch);
+	seq_printf(m, "boot_pdrv_tgt      = %d\n", adapter->boot_pdrv_tgt);
+	seq_printf(m, "quiescent          = %d\n",
+		   atomic_read(&adapter->quiescent));
+	seq_printf(m, "has_cluster        = %d\n", adapter->has_cluster);
 
-	len += sprintf(page+len, "\nModule Parameters:\n");
-	len += sprintf(page+len, "max_cmd_per_lun    = %d\n",
-			max_cmd_per_lun);
-	len += sprintf(page+len, "max_sectors_per_io = %d\n",
-			max_sectors_per_io);
-
-	*eof = 1;
-
-	return len;
+	seq_puts(m, "\nModule Parameters:\n");
+	seq_printf(m, "max_cmd_per_lun    = %d\n", max_cmd_per_lun);
+	seq_printf(m, "max_sectors_per_io = %d\n", max_sectors_per_io);
+	return 0;
 }
 
-
-
 /**
- * proc_read_stat()
- * @page - buffer to write the data in
- * @start - where the actual data has been written in page
- * @offset - same meaning as the read system call
- * @count - same meaning as the read system call
- * @eof - set if no more data needs to be returned
- * @data - pointer to our soft state
+ * proc_show_stat()
+ * @m - Synthetic file construction data
+ * @v - File iterator
  *
- * Diaplay statistical information about the I/O activity.
+ * Display statistical information about the I/O activity.
  */
 static int
-proc_read_stat(char *page, char **start, off_t offset, int count, int *eof,
-		void *data)
+proc_show_stat(struct seq_file *m, void *v)
 {
-	adapter_t	*adapter;
-	int	len;
-	int	i;
-
-	i = 0;	/* avoid compilation warnings */
-	len = 0;
-	adapter = (adapter_t *)data;
-
-	len = sprintf(page, "Statistical Information for this controller\n");
-	len += sprintf(page+len, "pend_cmds = %d\n",
-			atomic_read(&adapter->pend_cmds));
+	adapter_t *adapter = m->private;
 #if MEGA_HAVE_STATS
-	for(i = 0; i < adapter->numldrv; i++) {
-		len += sprintf(page+len, "Logical Drive %d:\n", i);
-
-		len += sprintf(page+len,
-			"\tReads Issued = %lu, Writes Issued = %lu\n",
-			adapter->nreads[i], adapter->nwrites[i]);
-
-		len += sprintf(page+len,
-			"\tSectors Read = %lu, Sectors Written = %lu\n",
-			adapter->nreadblocks[i], adapter->nwriteblocks[i]);
-
-		len += sprintf(page+len,
-			"\tRead errors = %lu, Write errors = %lu\n\n",
-			adapter->rd_errors[i], adapter->wr_errors[i]);
-	}
-#else
-	len += sprintf(page+len,
-			"IO and error counters not compiled in driver.\n");
+	int	i;
 #endif
 
-	*eof = 1;
-
-	return len;
+	seq_puts(m, "Statistical Information for this controller\n");
+	seq_printf(m, "pend_cmds = %d\n", atomic_read(&adapter->pend_cmds));
+#if MEGA_HAVE_STATS
+	for(i = 0; i < adapter->numldrv; i++) {
+		seq_printf(m, "Logical Drive %d:\n", i);
+		seq_printf(m, "\tReads Issued = %lu, Writes Issued = %lu\n",
+			   adapter->nreads[i], adapter->nwrites[i]);
+		seq_printf(m, "\tSectors Read = %lu, Sectors Written = %lu\n",
+			   adapter->nreadblocks[i], adapter->nwriteblocks[i]);
+		seq_printf(m, "\tRead errors = %lu, Write errors = %lu\n\n",
+			   adapter->rd_errors[i], adapter->wr_errors[i]);
+	}
+#else
+	seq_puts(m, "IO and error counters not compiled in driver.\n");
+#endif
+	return 0;
 }
 
 
 /**
- * proc_read_mbox()
- * @page - buffer to write the data in
- * @start - where the actual data has been written in page
- * @offset - same meaning as the read system call
- * @count - same meaning as the read system call
- * @eof - set if no more data needs to be returned
- * @data - pointer to our soft state
+ * proc_show_mbox()
+ * @m - Synthetic file construction data
+ * @v - File iterator
  *
  * Display mailbox information for the last command issued. This information
  * is good for debugging.
  */
 static int
-proc_read_mbox(char *page, char **start, off_t offset, int count, int *eof,
-		void *data)
+proc_show_mbox(struct seq_file *m, void *v)
 {
-
-	adapter_t	*adapter = (adapter_t *)data;
+	adapter_t	*adapter = m->private;
 	volatile mbox_t	*mbox = adapter->mbox;
-	int	len = 0;
 
-	len = sprintf(page, "Contents of Mail Box Structure\n");
-	len += sprintf(page+len, "  Fw Command   = 0x%02x\n", 
-			mbox->m_out.cmd);
-	len += sprintf(page+len, "  Cmd Sequence = 0x%02x\n", 
-			mbox->m_out.cmdid);
-	len += sprintf(page+len, "  No of Sectors= %04d\n", 
-			mbox->m_out.numsectors);
-	len += sprintf(page+len, "  LBA          = 0x%02x\n", 
-			mbox->m_out.lba);
-	len += sprintf(page+len, "  DTA          = 0x%08x\n", 
-			mbox->m_out.xferaddr);
-	len += sprintf(page+len, "  Logical Drive= 0x%02x\n", 
-			mbox->m_out.logdrv);
-	len += sprintf(page+len, "  No of SG Elmt= 0x%02x\n",
-			mbox->m_out.numsgelements);
-	len += sprintf(page+len, "  Busy         = %01x\n", 
-			mbox->m_in.busy);
-	len += sprintf(page+len, "  Status       = 0x%02x\n", 
-			mbox->m_in.status);
-
-	*eof = 1;
-
-	return len;
+	seq_puts(m, "Contents of Mail Box Structure\n");
+	seq_printf(m, "  Fw Command   = 0x%02x\n", mbox->m_out.cmd);
+	seq_printf(m, "  Cmd Sequence = 0x%02x\n", mbox->m_out.cmdid);
+	seq_printf(m, "  No of Sectors= %04d\n", mbox->m_out.numsectors);
+	seq_printf(m, "  LBA          = 0x%02x\n", mbox->m_out.lba);
+	seq_printf(m, "  DTA          = 0x%08x\n", mbox->m_out.xferaddr);
+	seq_printf(m, "  Logical Drive= 0x%02x\n", mbox->m_out.logdrv);
+	seq_printf(m, "  No of SG Elmt= 0x%02x\n", mbox->m_out.numsgelements);
+	seq_printf(m, "  Busy         = %01x\n", mbox->m_in.busy);
+	seq_printf(m, "  Status       = 0x%02x\n", mbox->m_in.status);
+	return 0;
 }
 
 
 /**
- * proc_rebuild_rate()
- * @page - buffer to write the data in
- * @start - where the actual data has been written in page
- * @offset - same meaning as the read system call
- * @count - same meaning as the read system call
- * @eof - set if no more data needs to be returned
- * @data - pointer to our soft state
+ * proc_show_rebuild_rate()
+ * @m - Synthetic file construction data
+ * @v - File iterator
  *
  * Display current rebuild rate
  */
 static int
-proc_rebuild_rate(char *page, char **start, off_t offset, int count, int *eof,
-		void *data)
+proc_show_rebuild_rate(struct seq_file *m, void *v)
 {
-	adapter_t	*adapter = (adapter_t *)data;
+	adapter_t	*adapter = m->private;
 	dma_addr_t	dma_handle;
 	caddr_t		inquiry;
 	struct pci_dev	*pdev;
-	int	len = 0;
 
-	if( make_local_pdev(adapter, &pdev) != 0 ) {
-		*eof = 1;
-		return len;
-	}
+	if( make_local_pdev(adapter, &pdev) != 0 )
+		return 0;
 
-	if( (inquiry = mega_allocate_inquiry(&dma_handle, pdev)) == NULL ) {
-		free_local_pdev(pdev);
-		*eof = 1;
-		return len;
-	}
+	if( (inquiry = mega_allocate_inquiry(&dma_handle, pdev)) == NULL )
+		goto free_pdev;
 
 	if( mega_adapinq(adapter, dma_handle) != 0 ) {
-
-		len = sprintf(page, "Adapter inquiry failed.\n");
-
+		seq_puts(m, "Adapter inquiry failed.\n");
 		printk(KERN_WARNING "megaraid: inquiry failed.\n");
-
-		mega_free_inquiry(inquiry, dma_handle, pdev);
-
-		free_local_pdev(pdev);
-
-		*eof = 1;
-
-		return len;
+		goto free_inquiry;
 	}
 
-	if( adapter->flag & BOARD_40LD ) {
-		len = sprintf(page, "Rebuild Rate: [%d%%]\n",
-			((mega_inquiry3 *)inquiry)->rebuild_rate);
-	}
-	else {
-		len = sprintf(page, "Rebuild Rate: [%d%%]\n",
+	if( adapter->flag & BOARD_40LD )
+		seq_printf(m, "Rebuild Rate: [%d%%]\n",
+			   ((mega_inquiry3 *)inquiry)->rebuild_rate);
+	else
+		seq_printf(m, "Rebuild Rate: [%d%%]\n",
 			((mraid_ext_inquiry *)
-			inquiry)->raid_inq.adapter_info.rebuild_rate);
-	}
+			 inquiry)->raid_inq.adapter_info.rebuild_rate);
 
-
+free_inquiry:
 	mega_free_inquiry(inquiry, dma_handle, pdev);
-
+free_pdev:
 	free_local_pdev(pdev);
-
-	*eof = 1;
-
-	return len;
+	return 0;
 }
 
 
 /**
- * proc_battery()
- * @page - buffer to write the data in
- * @start - where the actual data has been written in page
- * @offset - same meaning as the read system call
- * @count - same meaning as the read system call
- * @eof - set if no more data needs to be returned
- * @data - pointer to our soft state
+ * proc_show_battery()
+ * @m - Synthetic file construction data
+ * @v - File iterator
  *
  * Display information about the battery module on the controller.
  */
 static int
-proc_battery(char *page, char **start, off_t offset, int count, int *eof,
-		void *data)
+proc_show_battery(struct seq_file *m, void *v)
 {
-	adapter_t	*adapter = (adapter_t *)data;
+	adapter_t	*adapter = m->private;
 	dma_addr_t	dma_handle;
 	caddr_t		inquiry;
 	struct pci_dev	*pdev;
-	u8	battery_status = 0;
-	char	str[256];
-	int	len = 0;
+	u8	battery_status;
 
-	if( make_local_pdev(adapter, &pdev) != 0 ) {
-		*eof = 1;
-		return len;
-	}
+	if( make_local_pdev(adapter, &pdev) != 0 )
+		return 0;
 
-	if( (inquiry = mega_allocate_inquiry(&dma_handle, pdev)) == NULL ) {
-		free_local_pdev(pdev);
-		*eof = 1;
-		return len;
-	}
+	if( (inquiry = mega_allocate_inquiry(&dma_handle, pdev)) == NULL )
+		goto free_pdev;
 
 	if( mega_adapinq(adapter, dma_handle) != 0 ) {
-
-		len = sprintf(page, "Adapter inquiry failed.\n");
-
+		seq_printf(m, "Adapter inquiry failed.\n");
 		printk(KERN_WARNING "megaraid: inquiry failed.\n");
-
-		mega_free_inquiry(inquiry, dma_handle, pdev);
-
-		free_local_pdev(pdev);
-
-		*eof = 1;
-
-		return len;
+		goto free_inquiry;
 	}
 
 	if( adapter->flag & BOARD_40LD ) {
@@ -2461,146 +2278,80 @@
 	/*
 	 * Decode the battery status
 	 */
-	sprintf(str, "Battery Status:[%d]", battery_status);
+	seq_printf(m, "Battery Status:[%d]", battery_status);
 
 	if(battery_status == MEGA_BATT_CHARGE_DONE)
-		strcat(str, " Charge Done");
+		seq_puts(m, " Charge Done");
 
 	if(battery_status & MEGA_BATT_MODULE_MISSING)
-		strcat(str, " Module Missing");
+		seq_puts(m, " Module Missing");
 	
 	if(battery_status & MEGA_BATT_LOW_VOLTAGE)
-		strcat(str, " Low Voltage");
+		seq_puts(m, " Low Voltage");
 	
 	if(battery_status & MEGA_BATT_TEMP_HIGH)
-		strcat(str, " Temperature High");
+		seq_puts(m, " Temperature High");
 	
 	if(battery_status & MEGA_BATT_PACK_MISSING)
-		strcat(str, " Pack Missing");
+		seq_puts(m, " Pack Missing");
 	
 	if(battery_status & MEGA_BATT_CHARGE_INPROG)
-		strcat(str, " Charge In-progress");
+		seq_puts(m, " Charge In-progress");
 	
 	if(battery_status & MEGA_BATT_CHARGE_FAIL)
-		strcat(str, " Charge Fail");
+		seq_puts(m, " Charge Fail");
 	
 	if(battery_status & MEGA_BATT_CYCLES_EXCEEDED)
-		strcat(str, " Cycles Exceeded");
+		seq_puts(m, " Cycles Exceeded");
 
-	len = sprintf(page, "%s\n", str);
+	seq_putc(m, '\n');
 
-
+free_inquiry:
 	mega_free_inquiry(inquiry, dma_handle, pdev);
-
+free_pdev:
 	free_local_pdev(pdev);
-
-	*eof = 1;
-
-	return len;
+	return 0;
 }
 
 
-/**
- * proc_pdrv_ch0()
- * @page - buffer to write the data in
- * @start - where the actual data has been written in page
- * @offset - same meaning as the read system call
- * @count - same meaning as the read system call
- * @eof - set if no more data needs to be returned
- * @data - pointer to our soft state
- *
- * Display information about the physical drives on physical channel 0.
+/*
+ * Display scsi inquiry
  */
-static int
-proc_pdrv_ch0(char *page, char **start, off_t offset, int count, int *eof,
-		void *data)
+static void
+mega_print_inquiry(struct seq_file *m, char *scsi_inq)
 {
-	adapter_t *adapter = (adapter_t *)data;
+	int	i;
 
-	*eof = 1;
+	seq_puts(m, "  Vendor: ");
+	seq_write(m, scsi_inq + 8, 8);
+	seq_puts(m, "  Model: ");
+	seq_write(m, scsi_inq + 16, 16);
+	seq_puts(m, "  Rev: ");
+	seq_write(m, scsi_inq + 32, 4);
+	seq_putc(m, '\n');
 
-	return (proc_pdrv(adapter, page, 0));
+	i = scsi_inq[0] & 0x1f;
+	seq_printf(m, "  Type:   %s ", scsi_device_type(i));
+
+	seq_printf(m, "                 ANSI SCSI revision: %02x",
+		   scsi_inq[2] & 0x07);
+
+	if( (scsi_inq[2] & 0x07) == 1 && (scsi_inq[3] & 0x0f) == 1 )
+		seq_puts(m, " CCS\n");
+	else
+		seq_putc(m, '\n');
 }
 
-
 /**
- * proc_pdrv_ch1()
- * @page - buffer to write the data in
- * @start - where the actual data has been written in page
- * @offset - same meaning as the read system call
- * @count - same meaning as the read system call
- * @eof - set if no more data needs to be returned
- * @data - pointer to our soft state
- *
- * Display information about the physical drives on physical channel 1.
- */
-static int
-proc_pdrv_ch1(char *page, char **start, off_t offset, int count, int *eof,
-		void *data)
-{
-	adapter_t *adapter = (adapter_t *)data;
-
-	*eof = 1;
-
-	return (proc_pdrv(adapter, page, 1));
-}
-
-
-/**
- * proc_pdrv_ch2()
- * @page - buffer to write the data in
- * @start - where the actual data has been written in page
- * @offset - same meaning as the read system call
- * @count - same meaning as the read system call
- * @eof - set if no more data needs to be returned
- * @data - pointer to our soft state
- *
- * Display information about the physical drives on physical channel 2.
- */
-static int
-proc_pdrv_ch2(char *page, char **start, off_t offset, int count, int *eof,
-		void *data)
-{
-	adapter_t *adapter = (adapter_t *)data;
-
-	*eof = 1;
-
-	return (proc_pdrv(adapter, page, 2));
-}
-
-
-/**
- * proc_pdrv_ch3()
- * @page - buffer to write the data in
- * @start - where the actual data has been written in page
- * @offset - same meaning as the read system call
- * @count - same meaning as the read system call
- * @eof - set if no more data needs to be returned
- * @data - pointer to our soft state
- *
- * Display information about the physical drives on physical channel 3.
- */
-static int
-proc_pdrv_ch3(char *page, char **start, off_t offset, int count, int *eof,
-		void *data)
-{
-	adapter_t *adapter = (adapter_t *)data;
-
-	*eof = 1;
-
-	return (proc_pdrv(adapter, page, 3));
-}
-
-
-/**
- * proc_pdrv()
+ * proc_show_pdrv()
+ * @m - Synthetic file construction data
  * @page - buffer to write the data in
  * @adapter - pointer to our soft state
  *
  * Display information about the physical drives.
  */
 static int
-proc_pdrv(adapter_t *adapter, char *page, int channel)
+proc_show_pdrv(struct seq_file *m, adapter_t *adapter, int channel)
 {
 	dma_addr_t	dma_handle;
 	char		*scsi_inq;
@@ -2611,32 +2362,24 @@
 	u8	state;
 	int	tgt;
 	int	max_channels;
-	int	len = 0;
-	char	str[80];
 	int	i;
 
-	if( make_local_pdev(adapter, &pdev) != 0 ) {
-		return len;
-	}
+	if( make_local_pdev(adapter, &pdev) != 0 )
+		return 0;
 
-	if( (inquiry = mega_allocate_inquiry(&dma_handle, pdev)) == NULL ) {
+	if( (inquiry = mega_allocate_inquiry(&dma_handle, pdev)) == NULL )
 		goto free_pdev;
-	}
 
 	if( mega_adapinq(adapter, dma_handle) != 0 ) {
-		len = sprintf(page, "Adapter inquiry failed.\n");
-
+		seq_puts(m, "Adapter inquiry failed.\n");
 		printk(KERN_WARNING "megaraid: inquiry failed.\n");
-
 		goto free_inquiry;
 	}
 
 
 	scsi_inq = pci_alloc_consistent(pdev, 256, &scsi_inq_dma_handle);
-
 	if( scsi_inq == NULL ) {
-		len = sprintf(page, "memory not available for scsi inq.\n");
-
+		seq_puts(m, "memory not available for scsi inq.\n");
 		goto free_inquiry;
 	}
 
@@ -2659,39 +2402,31 @@
 		i = channel*16 + tgt;
 
 		state = *(pdrv_state + i);
-
 		switch( state & 0x0F ) {
-
 		case PDRV_ONLINE:
-			sprintf(str,
-			"Channel:%2d Id:%2d State: Online",
-				channel, tgt);
+			seq_printf(m, "Channel:%2d Id:%2d State: Online",
+				   channel, tgt);
 			break;
 
 		case PDRV_FAILED:
-			sprintf(str,
-			"Channel:%2d Id:%2d State: Failed",
-				channel, tgt);
+			seq_printf(m, "Channel:%2d Id:%2d State: Failed",
+				   channel, tgt);
 			break;
 
 		case PDRV_RBLD:
-			sprintf(str,
-			"Channel:%2d Id:%2d State: Rebuild",
-				channel, tgt);
+			seq_printf(m, "Channel:%2d Id:%2d State: Rebuild",
+				   channel, tgt);
 			break;
 
 		case PDRV_HOTSPARE:
-			sprintf(str,
-			"Channel:%2d Id:%2d State: Hot spare",
-				channel, tgt);
+			seq_printf(m, "Channel:%2d Id:%2d State: Hot spare",
+				   channel, tgt);
 			break;
 
 		default:
-			sprintf(str,
-			"Channel:%2d Id:%2d State: Un-configured",
-				channel, tgt);
+			seq_printf(m, "Channel:%2d Id:%2d State: Un-configured",
+				   channel, tgt);
 			break;
-
 		}
 
 		/*
@@ -2710,11 +2445,8 @@
 		 * Check for overflow. We print less than 240
 		 * characters for inquiry
 		 */
-		if( (len + 240) >= PAGE_SIZE ) break;
-
-		len += sprintf(page+len, "%s.\n", str);
-
-		len += mega_print_inquiry(page+len, scsi_inq);
+		seq_puts(m, ".\n");
+		mega_print_inquiry(m, scsi_inq);
 	}
 
 free_pci:
@@ -2723,150 +2455,68 @@
 	mega_free_inquiry(inquiry, dma_handle, pdev);
 free_pdev:
 	free_local_pdev(pdev);
-
-	return len;
+	return 0;
 }
 
-
-/*
- * Display scsi inquiry
- */
-static int
-mega_print_inquiry(char *page, char *scsi_inq)
-{
-	int	len = 0;
-	int	i;
-
-	len = sprintf(page, "  Vendor: ");
-	for( i = 8; i < 16; i++ ) {
-		len += sprintf(page+len, "%c", scsi_inq[i]);
-	}
-
-	len += sprintf(page+len, "  Model: ");
-
-	for( i = 16; i < 32; i++ ) {
-		len += sprintf(page+len, "%c", scsi_inq[i]);
-	}
-
-	len += sprintf(page+len, "  Rev: ");
-
-	for( i = 32; i < 36; i++ ) {
-		len += sprintf(page+len, "%c", scsi_inq[i]);
-	}
-
-	len += sprintf(page+len, "\n");
-
-	i = scsi_inq[0] & 0x1f;
-
-	len += sprintf(page+len, "  Type:   %s ", scsi_device_type(i));
-
-	len += sprintf(page+len,
-	"                 ANSI SCSI revision: %02x", scsi_inq[2] & 0x07);
-
-	if( (scsi_inq[2] & 0x07) == 1 && (scsi_inq[3] & 0x0f) == 1 )
-		len += sprintf(page+len, " CCS\n");
-	else
-		len += sprintf(page+len, "\n");
-
-	return len;
-}
-
-
 /**
- * proc_rdrv_10()
- * @page - buffer to write the data in
- * @start - where the actual data has been written in page
- * @offset - same meaning as the read system call
- * @count - same meaning as the read system call
- * @eof - set if no more data needs to be returned
- * @data - pointer to our soft state
+ * proc_show_pdrv_ch0()
+ * @m - Synthetic file construction data
+ * @v - File iterator
  *
- * Display real time information about the logical drives 0 through 9.
+ * Display information about the physical drives on physical channel 0.
  */
 static int
-proc_rdrv_10(char *page, char **start, off_t offset, int count, int *eof,
-		void *data)
+proc_show_pdrv_ch0(struct seq_file *m, void *v)
 {
-	adapter_t *adapter = (adapter_t *)data;
-
-	*eof = 1;
-
-	return (proc_rdrv(adapter, page, 0, 9));
+	return proc_show_pdrv(m, m->private, 0);
 }
 
 
 /**
- * proc_rdrv_20()
- * @page - buffer to write the data in
- * @start - where the actual data has been written in page
- * @offset - same meaning as the read system call
- * @count - same meaning as the read system call
- * @eof - set if no more data needs to be returned
- * @data - pointer to our soft state
+ * proc_show_pdrv_ch1()
+ * @m - Synthetic file construction data
+ * @v - File iterator
  *
- * Display real time information about the logical drives 0 through 9.
+ * Display information about the physical drives on physical channel 1.
  */
 static int
-proc_rdrv_20(char *page, char **start, off_t offset, int count, int *eof,
-		void *data)
+proc_show_pdrv_ch1(struct seq_file *m, void *v)
 {
-	adapter_t *adapter = (adapter_t *)data;
-
-	*eof = 1;
-
-	return (proc_rdrv(adapter, page, 10, 19));
+	return proc_show_pdrv(m, m->private, 1);
 }
 
 
 /**
- * proc_rdrv_30()
- * @page - buffer to write the data in
- * @start - where the actual data has been written in page
- * @offset - same meaning as the read system call
- * @count - same meaning as the read system call
- * @eof - set if no more data needs to be returned
- * @data - pointer to our soft state
+ * proc_show_pdrv_ch2()
+ * @m - Synthetic file construction data
+ * @v - File iterator
  *
- * Display real time information about the logical drives 0 through 9.
+ * Display information about the physical drives on physical channel 2.
  */
 static int
-proc_rdrv_30(char *page, char **start, off_t offset, int count, int *eof,
-		void *data)
+proc_show_pdrv_ch2(struct seq_file *m, void *v)
 {
-	adapter_t *adapter = (adapter_t *)data;
-
-	*eof = 1;
-
-	return (proc_rdrv(adapter, page, 20, 29));
+	return proc_show_pdrv(m, m->private, 2);
 }
 
 
 /**
- * proc_rdrv_40()
- * @page - buffer to write the data in
- * @start - where the actual data has been written in page
- * @offset - same meaning as the read system call
- * @count - same meaning as the read system call
- * @eof - set if no more data needs to be returned
- * @data - pointer to our soft state
+ * proc_show_pdrv_ch3()
+ * @m - Synthetic file construction data
+ * @v - File iterator
  *
- * Display real time information about the logical drives 0 through 9.
+ * Display information about the physical drives on physical channel 3.
  */
 static int
-proc_rdrv_40(char *page, char **start, off_t offset, int count, int *eof,
-		void *data)
+proc_show_pdrv_ch3(struct seq_file *m, void *v)
 {
-	adapter_t *adapter = (adapter_t *)data;
-
-	*eof = 1;
-
-	return (proc_rdrv(adapter, page, 30, 39));
+	return proc_show_pdrv(m, m->private, 3);
 }
 
 
 /**
- * proc_rdrv()
- * @page - buffer to write the data in
+ * proc_show_rdrv()
+ * @m - Synthetic file construction data
  * @adapter - pointer to our soft state
  * @start - starting logical drive to display
  * @end - ending logical drive to display
@@ -2875,7 +2525,7 @@
  * /proc/scsi/scsi interface
  */
 static int
-proc_rdrv(adapter_t *adapter, char *page, int start, int end )
+proc_show_rdrv(struct seq_file *m, adapter_t *adapter, int start, int end )
 {
 	dma_addr_t	dma_handle;
 	logdrv_param	*lparam;
@@ -2887,29 +2537,18 @@
 	u8	*rdrv_state;
 	int	num_ldrv;
 	u32	array_sz;
-	int	len = 0;
 	int	i;
 
-	if( make_local_pdev(adapter, &pdev) != 0 ) {
-		return len;
-	}
+	if( make_local_pdev(adapter, &pdev) != 0 )
+		return 0;
 
-	if( (inquiry = mega_allocate_inquiry(&dma_handle, pdev)) == NULL ) {
-		free_local_pdev(pdev);
-		return len;
-	}
+	if( (inquiry = mega_allocate_inquiry(&dma_handle, pdev)) == NULL )
+		goto free_pdev;
 
 	if( mega_adapinq(adapter, dma_handle) != 0 ) {
-
-		len = sprintf(page, "Adapter inquiry failed.\n");
-
+		seq_puts(m, "Adapter inquiry failed.\n");
 		printk(KERN_WARNING "megaraid: inquiry failed.\n");
-
-		mega_free_inquiry(inquiry, dma_handle, pdev);
-
-		free_local_pdev(pdev);
-
-		return len;
+		goto free_inquiry;
 	}
 
 	memset(&mc, 0, sizeof(megacmd_t));
@@ -2935,13 +2574,8 @@
 			&disk_array_dma_handle);
 
 	if( disk_array == NULL ) {
-		len = sprintf(page, "memory not available.\n");
-
-		mega_free_inquiry(inquiry, dma_handle, pdev);
-
-		free_local_pdev(pdev);
-
-		return len;
+		seq_puts(m, "memory not available.\n");
+		goto free_inquiry;
 	}
 
 	mc.xferaddr = (u32)disk_array_dma_handle;
@@ -2951,17 +2585,8 @@
 		mc.opcode = OP_DCMD_READ_CONFIG;
 
 		if( mega_internal_command(adapter, &mc, NULL) ) {
-
-			len = sprintf(page, "40LD read config failed.\n");
-
-			mega_free_inquiry(inquiry, dma_handle, pdev);
-
-			pci_free_consistent(pdev, array_sz, disk_array,
-					disk_array_dma_handle);
-
-			free_local_pdev(pdev);
-
-			return len;
+			seq_puts(m, "40LD read config failed.\n");
+			goto free_pci;
 		}
 
 	}
@@ -2969,24 +2594,10 @@
 		mc.cmd = NEW_READ_CONFIG_8LD;
 
 		if( mega_internal_command(adapter, &mc, NULL) ) {
-
 			mc.cmd = READ_CONFIG_8LD;
-
-			if( mega_internal_command(adapter, &mc,
-						NULL) ){
-
-				len = sprintf(page,
-					"8LD read config failed.\n");
-
-				mega_free_inquiry(inquiry, dma_handle, pdev);
-
-				pci_free_consistent(pdev, array_sz,
-						disk_array,
-						disk_array_dma_handle);
-
-				free_local_pdev(pdev);
-
-				return len;
+			if( mega_internal_command(adapter, &mc, NULL) ) {
+				seq_puts(m, "8LD read config failed.\n");
+				goto free_pci;
 			}
 		}
 	}
@@ -3006,29 +2617,23 @@
 		 * Check for overflow. We print less than 240 characters for
 		 * information about each logical drive.
 		 */
-		if( (len + 240) >= PAGE_SIZE ) break;
-
-		len += sprintf(page+len, "Logical drive:%2d:, ", i);
+		seq_printf(m, "Logical drive:%2d:, ", i);
 
 		switch( rdrv_state[i] & 0x0F ) {
 		case RDRV_OFFLINE:
-			len += sprintf(page+len, "state: offline");
+			seq_puts(m, "state: offline");
 			break;
-
 		case RDRV_DEGRADED:
-			len += sprintf(page+len, "state: degraded");
+			seq_puts(m, "state: degraded");
 			break;
-
 		case RDRV_OPTIMAL:
-			len += sprintf(page+len, "state: optimal");
+			seq_puts(m, "state: optimal");
 			break;
-
 		case RDRV_DELETED:
-			len += sprintf(page+len, "state: deleted");
+			seq_puts(m, "state: deleted");
 			break;
-
 		default:
-			len += sprintf(page+len, "state: unknown");
+			seq_puts(m, "state: unknown");
 			break;
 		}
 
@@ -3036,84 +2641,203 @@
 		 * Check if check consistency or initialization is going on
 		 * for this logical drive.
 		 */
-		if( (rdrv_state[i] & 0xF0) == 0x20 ) {
-			len += sprintf(page+len,
-					", check-consistency in progress");
-		}
-		else if( (rdrv_state[i] & 0xF0) == 0x10 ) {
-			len += sprintf(page+len,
-					", initialization in progress");
-		}
+		if( (rdrv_state[i] & 0xF0) == 0x20 )
+			seq_puts(m, ", check-consistency in progress");
+		else if( (rdrv_state[i] & 0xF0) == 0x10 )
+			seq_puts(m, ", initialization in progress");
 		
-		len += sprintf(page+len, "\n");
+		seq_putc(m, '\n');
 
-		len += sprintf(page+len, "Span depth:%3d, ",
-				lparam->span_depth);
+		seq_printf(m, "Span depth:%3d, ", lparam->span_depth);
+		seq_printf(m, "RAID level:%3d, ", lparam->level);
+		seq_printf(m, "Stripe size:%3d, ",
+			   lparam->stripe_sz ? lparam->stripe_sz/2: 128);
+		seq_printf(m, "Row size:%3d\n", lparam->row_size);
 
-		len += sprintf(page+len, "RAID level:%3d, ",
-				lparam->level);
-
-		len += sprintf(page+len, "Stripe size:%3d, ",
-				lparam->stripe_sz ? lparam->stripe_sz/2: 128);
-
-		len += sprintf(page+len, "Row size:%3d\n",
-				lparam->row_size);
-
-
-		len += sprintf(page+len, "Read Policy: ");
-
+		seq_puts(m, "Read Policy: ");
 		switch(lparam->read_ahead) {
-
 		case NO_READ_AHEAD:
-			len += sprintf(page+len, "No read ahead, ");
+			seq_puts(m, "No read ahead, ");
 			break;
-
 		case READ_AHEAD:
-			len += sprintf(page+len, "Read ahead, ");
+			seq_puts(m, "Read ahead, ");
 			break;
-
 		case ADAP_READ_AHEAD:
-			len += sprintf(page+len, "Adaptive, ");
+			seq_puts(m, "Adaptive, ");
 			break;
 
 		}
 
-		len += sprintf(page+len, "Write Policy: ");
-
+		seq_puts(m, "Write Policy: ");
 		switch(lparam->write_mode) {
-
 		case WRMODE_WRITE_THRU:
-			len += sprintf(page+len, "Write thru, ");
+			seq_puts(m, "Write thru, ");
 			break;
-
 		case WRMODE_WRITE_BACK:
-			len += sprintf(page+len, "Write back, ");
+			seq_puts(m, "Write back, ");
 			break;
 		}
 
-		len += sprintf(page+len, "Cache Policy: ");
-
+		seq_puts(m, "Cache Policy: ");
 		switch(lparam->direct_io) {
-
 		case CACHED_IO:
-			len += sprintf(page+len, "Cached IO\n\n");
+			seq_puts(m, "Cached IO\n\n");
 			break;
-
 		case DIRECT_IO:
-			len += sprintf(page+len, "Direct IO\n\n");
+			seq_puts(m, "Direct IO\n\n");
 			break;
 		}
 	}
 
-	mega_free_inquiry(inquiry, dma_handle, pdev);
-
+free_pci:
 	pci_free_consistent(pdev, array_sz, disk_array,
 			disk_array_dma_handle);
-
+free_inquiry:
+	mega_free_inquiry(inquiry, dma_handle, pdev);
+free_pdev:
 	free_local_pdev(pdev);
-
-	return len;
+	return 0;
 }
+
+/**
+ * proc_show_rdrv_10()
+ * @m - Synthetic file construction data
+ * @v - File iterator
+ *
+ * Display real time information about the logical drives 0 through 9.
+ */
+static int
+proc_show_rdrv_10(struct seq_file *m, void *v)
+{
+	return proc_show_rdrv(m, m->private, 0, 9);
+}
+
+
+/**
+ * proc_show_rdrv_20()
+ * @m - Synthetic file construction data
+ * @v - File iterator
+ *
+ * Display real time information about the logical drives 0 through 9.
+ */
+static int
+proc_show_rdrv_20(struct seq_file *m, void *v)
+{
+	return proc_show_rdrv(m, m->private, 10, 19);
+}
+
+
+/**
+ * proc_show_rdrv_30()
+ * @m - Synthetic file construction data
+ * @v - File iterator
+ *
+ * Display real time information about the logical drives 0 through 9.
+ */
+static int
+proc_show_rdrv_30(struct seq_file *m, void *v)
+{
+	return proc_show_rdrv(m, m->private, 20, 29);
+}
+
+
+/**
+ * proc_show_rdrv_40()
+ * @m - Synthetic file construction data
+ * @v - File iterator
+ *
+ * Display real time information about the logical drives 0 through 9.
+ */
+static int
+proc_show_rdrv_40(struct seq_file *m, void *v)
+{
+	return proc_show_rdrv(m, m->private, 30, 39);
+}
+
+
+/*
+ * seq_file wrappers for procfile show routines.
+ */
+static int mega_proc_open(struct inode *inode, struct file *file)
+{
+	adapter_t *adapter = proc_get_parent_data(inode);
+	int (*show)(struct seq_file *, void *) = PDE_DATA(inode);
+
+	return single_open(file, show, adapter);
+}
+
+static const struct file_operations mega_proc_fops = {
+	.open		= mega_proc_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= seq_release,
+};
+
+/*
+ * Table of proc files we need to create.
+ */
+struct mega_proc_file {
+	const char *name;
+	unsigned short ptr_offset;
+	int (*show) (struct seq_file *m, void *v);
+};
+
+static const struct mega_proc_file mega_proc_files[] = {
+	{ "config",	      offsetof(adapter_t, proc_read), proc_show_config },
+	{ "stat",	      offsetof(adapter_t, proc_stat), proc_show_stat },
+	{ "mailbox",	      offsetof(adapter_t, proc_mbox), proc_show_mbox },
+#if MEGA_HAVE_ENH_PROC
+	{ "rebuild-rate",     offsetof(adapter_t, proc_rr), proc_show_rebuild_rate },
+	{ "battery-status",   offsetof(adapter_t, proc_battery), proc_show_battery },
+	{ "diskdrives-ch0",   offsetof(adapter_t, proc_pdrvstat[0]), proc_show_pdrv_ch0 },
+	{ "diskdrives-ch1",   offsetof(adapter_t, proc_pdrvstat[1]), proc_show_pdrv_ch1 },
+	{ "diskdrives-ch2",   offsetof(adapter_t, proc_pdrvstat[2]), proc_show_pdrv_ch2 },
+	{ "diskdrives-ch3",   offsetof(adapter_t, proc_pdrvstat[3]), proc_show_pdrv_ch3 },
+	{ "raiddrives-0-9",   offsetof(adapter_t, proc_rdrvstat[0]), proc_show_rdrv_10 },
+	{ "raiddrives-10-19", offsetof(adapter_t, proc_rdrvstat[1]), proc_show_rdrv_20 },
+	{ "raiddrives-20-29", offsetof(adapter_t, proc_rdrvstat[2]), proc_show_rdrv_30 },
+	{ "raiddrives-30-39", offsetof(adapter_t, proc_rdrvstat[3]), proc_show_rdrv_40 },
+#endif
+	{ NULL }
+};
+
+/**
+ * mega_create_proc_entry()
+ * @index - index in soft state array
+ * @parent - parent node for this /proc entry
+ *
+ * Creates /proc entries for our controllers.
+ */
+static void
+mega_create_proc_entry(int index, struct proc_dir_entry *parent)
+{
+	const struct mega_proc_file *f;
+	adapter_t	*adapter = hba_soft_state[index];
+	struct proc_dir_entry	*dir, *de, **ppde;
+	u8		string[16];
+
+	sprintf(string, "hba%d", adapter->host->host_no);
+
+	dir = adapter->controller_proc_dir_entry =
+		proc_mkdir_data(string, 0, parent, adapter);
+	if(!dir) {
+		printk(KERN_WARNING "\nmegaraid: proc_mkdir failed\n");
+		return;
+	}
+
+	for (f = mega_proc_files; f->name; f++) {
+		de = proc_create_data(f->name, S_IRUSR, dir, &mega_proc_fops,
+				      f->show);
+		if (!de) {
+			printk(KERN_WARNING "\nmegaraid: proc_create failed\n");
+			return;
+		}
+
+		ppde = (void *)adapter + f->ptr_offset;
+		*ppde = de;
+	}
+}
+
 #else
 static inline void mega_create_proc_entry(int index, struct proc_dir_entry *parent)
 {
diff --git a/drivers/scsi/megaraid.h b/drivers/scsi/megaraid.h
index 4fb2adf..4d0ce4e 100644
--- a/drivers/scsi/megaraid.h
+++ b/drivers/scsi/megaraid.h
@@ -987,24 +987,7 @@
 static int mega_is_bios_enabled (adapter_t *);
 
 #ifdef CONFIG_PROC_FS
-static int mega_print_inquiry(char *, char *);
 static void mega_create_proc_entry(int, struct proc_dir_entry *);
-static int proc_read_config(char *, char **, off_t, int, int *, void *);
-static int proc_read_stat(char *, char **, off_t, int, int *, void *);
-static int proc_read_mbox(char *, char **, off_t, int, int *, void *);
-static int proc_rebuild_rate(char *, char **, off_t, int, int *, void *);
-static int proc_battery(char *, char **, off_t, int, int *, void *);
-static int proc_pdrv_ch0(char *, char **, off_t, int, int *, void *);
-static int proc_pdrv_ch1(char *, char **, off_t, int, int *, void *);
-static int proc_pdrv_ch2(char *, char **, off_t, int, int *, void *);
-static int proc_pdrv_ch3(char *, char **, off_t, int, int *, void *);
-static int proc_pdrv(adapter_t *, char *, int);
-static int proc_rdrv_10(char *, char **, off_t, int, int *, void *);
-static int proc_rdrv_20(char *, char **, off_t, int, int *, void *);
-static int proc_rdrv_30(char *, char **, off_t, int, int *, void *);
-static int proc_rdrv_40(char *, char **, off_t, int, int *, void *);
-static int proc_rdrv(adapter_t *, char *, int, int);
-
 static int mega_adapinq(adapter_t *, dma_addr_t);
 static int mega_internal_dev_inquiry(adapter_t *, u8, u8, dma_addr_t);
 #endif
diff --git a/drivers/scsi/mpt2sas/mpt2sas_ctl.c b/drivers/scsi/mpt2sas/mpt2sas_ctl.c
index 08685c4..eec052c 100644
--- a/drivers/scsi/mpt2sas/mpt2sas_ctl.c
+++ b/drivers/scsi/mpt2sas/mpt2sas_ctl.c
@@ -505,19 +505,6 @@
 }
 
 /**
- * _ctl_release -
- * @inode -
- * @filep -
- *
- * Called when application releases the fasyn callback handler.
- */
-static int
-_ctl_release(struct inode *inode, struct file *filep)
-{
-	return fasync_helper(-1, filep, 0, &async_queue);
-}
-
-/**
  * _ctl_poll -
  * @file -
  * @wait -
@@ -3027,7 +3014,6 @@
 static const struct file_operations ctl_fops = {
 	.owner = THIS_MODULE,
 	.unlocked_ioctl = _ctl_ioctl,
-	.release = _ctl_release,
 	.poll = _ctl_poll,
 	.fasync = _ctl_fasync,
 #ifdef CONFIG_COMPAT
diff --git a/drivers/scsi/mpt3sas/mpt3sas_ctl.c b/drivers/scsi/mpt3sas/mpt3sas_ctl.c
index 054d523..0b402b6 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_ctl.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_ctl.c
@@ -503,19 +503,6 @@
 }
 
 /**
- * _ctl_release -
- * @inode -
- * @filep -
- *
- * Called when application releases the fasyn callback handler.
- */
-static int
-_ctl_release(struct inode *inode, struct file *filep)
-{
-	return fasync_helper(-1, filep, 0, &async_queue);
-}
-
-/**
  * _ctl_poll -
  * @file -
  * @wait -
@@ -3233,7 +3220,6 @@
 static const struct file_operations ctl_fops = {
 	.owner = THIS_MODULE,
 	.unlocked_ioctl = _ctl_ioctl,
-	.release = _ctl_release,
 	.poll = _ctl_poll,
 	.fasync = _ctl_fasync,
 #ifdef CONFIG_COMPAT
diff --git a/drivers/scsi/mvme147.c b/drivers/scsi/mvme147.c
index c29d0db..e7f6661 100644
--- a/drivers/scsi/mvme147.c
+++ b/drivers/scsi/mvme147.c
@@ -76,7 +76,8 @@
 	called++;
 
 	tpnt->proc_name = "MVME147";
-	tpnt->proc_info = &wd33c93_proc_info;
+	tpnt->show_info = wd33c93_show_info,
+	tpnt->write_info = wd33c93_write_info,
 
 	instance = scsi_register(tpnt, sizeof(struct WD33C93_hostdata));
 	if (!instance)
diff --git a/drivers/scsi/nsp32.c b/drivers/scsi/nsp32.c
index 1cc0c1c..1e3879d 100644
--- a/drivers/scsi/nsp32.c
+++ b/drivers/scsi/nsp32.c
@@ -192,7 +192,7 @@
 static void __exit exit_nsp32  (void);
 
 /* struct struct scsi_host_template */
-static int         nsp32_proc_info   (struct Scsi_Host *, char *, char **, off_t, int, int);
+static int         nsp32_show_info   (struct seq_file *, struct Scsi_Host *);
 
 static int         nsp32_detect      (struct pci_dev *pdev);
 static int         nsp32_queuecommand(struct Scsi_Host *, struct scsi_cmnd *);
@@ -268,7 +268,7 @@
 static struct scsi_host_template nsp32_template = {
 	.proc_name			= "nsp32",
 	.name				= "Workbit NinjaSCSI-32Bi/UDE",
-	.proc_info			= nsp32_proc_info,
+	.show_info			= nsp32_show_info,
 	.info				= nsp32_info,
 	.queuecommand			= nsp32_queuecommand,
 	.can_queue			= 1,
@@ -1442,19 +1442,10 @@
 }
 
 #undef SPRINTF
-#define SPRINTF(args...) \
-	do { \
-		if(length > (pos - buffer)) { \
-			pos += snprintf(pos, length - (pos - buffer) + 1, ## args); \
-			nsp32_dbg(NSP32_DEBUG_PROC, "buffer=0x%p pos=0x%p length=%d %d\n", buffer, pos, length,  length - (pos - buffer));\
-		} \
-	} while(0)
+#define SPRINTF(args...) seq_printf(m, ##args)
 
-static int nsp32_proc_info(struct Scsi_Host *host, char *buffer, char **start,
-			   off_t offset, int length, int inout)
+static int nsp32_show_info(struct seq_file *m, struct Scsi_Host *host)
 {
-	char             *pos = buffer;
-	int               thislength;
 	unsigned long     flags;
 	nsp32_hw_data    *data;
 	int               hostno;
@@ -1463,11 +1454,6 @@
 	int               id, speed;
 	long              model;
 
-	/* Write is not supported, just return. */
-	if (inout == TRUE) {
-		return -EINVAL;
-	}
-
 	hostno = host->host_no;
 	data = (nsp32_hw_data *)host->hostdata;
 	base = host->io_port;
@@ -1527,20 +1513,7 @@
 		}
 		SPRINTF("\n");
 	}
-
-
-	thislength = pos - (buffer + offset);
-
-	if(thislength < 0) {
-		*start = NULL;
-                return 0;
-        }
-
-
-	thislength = min(thislength, length);
-	*start = buffer + offset;
-
-	return thislength;
+	return 0;
 }
 #undef SPRINTF
 
diff --git a/drivers/scsi/pas16.c b/drivers/scsi/pas16.c
index 2f72c98..62f1a60 100644
--- a/drivers/scsi/pas16.c
+++ b/drivers/scsi/pas16.c
@@ -388,7 +388,8 @@
     int  count;
 
     tpnt->proc_name = "pas16";
-    tpnt->proc_info = &pas16_proc_info;
+    tpnt->show_info = pas16_show_info;
+    tpnt->write_info = pas16_write_info;
 
     if (pas16_addr != 0) {
 	overrides[0].io_port = pas16_addr;
diff --git a/drivers/scsi/pas16.h b/drivers/scsi/pas16.h
index a04281c..3721342 100644
--- a/drivers/scsi/pas16.h
+++ b/drivers/scsi/pas16.h
@@ -163,7 +163,8 @@
 #define NCR5380_queue_command pas16_queue_command
 #define NCR5380_abort pas16_abort
 #define NCR5380_bus_reset pas16_bus_reset
-#define NCR5380_proc_info pas16_proc_info
+#define NCR5380_show_info pas16_show_info
+#define NCR5380_write_info pas16_write_info
 
 /* 15 14 12 10 7 5 3 
    1101 0100 1010 1000 */
diff --git a/drivers/scsi/pcmcia/nsp_cs.c b/drivers/scsi/pcmcia/nsp_cs.c
index b61a753..987fbb1 100644
--- a/drivers/scsi/pcmcia/nsp_cs.c
+++ b/drivers/scsi/pcmcia/nsp_cs.c
@@ -76,7 +76,7 @@
 
 static struct scsi_host_template nsp_driver_template = {
 	.proc_name	         = "nsp_cs",
-	.proc_info		 = nsp_proc_info,
+	.show_info		 = nsp_show_info,
 	.name			 = "WorkBit NinjaSCSI-3/32Bi(16bit)",
 	.info			 = nsp_info,
 	.queuecommand		 = nsp_queuecommand,
@@ -1365,33 +1365,19 @@
 }
 
 #undef SPRINTF
-#define SPRINTF(args...) \
-        do { \
-		if(length > (pos - buffer)) { \
-			pos += snprintf(pos, length - (pos - buffer) + 1, ## args); \
-			nsp_dbg(NSP_DEBUG_PROC, "buffer=0x%p pos=0x%p length=%d %d\n", buffer, pos, length,  length - (pos - buffer));\
-		} \
-	} while(0)
+#define SPRINTF(args...) seq_printf(m, ##args)
 
-static int nsp_proc_info(struct Scsi_Host *host, char *buffer, char **start,
-			 off_t offset, int length, int inout)
+static int nsp_show_info(struct seq_file *m, struct Scsi_Host *host)
 {
 	int id;
-	char *pos = buffer;
-	int thislength;
 	int speed;
 	unsigned long flags;
 	nsp_hw_data *data;
 	int hostno;
 
-	if (inout) {
-		return -EINVAL;
-	}
-
 	hostno = host->host_no;
 	data = (nsp_hw_data *)host->hostdata;
 
-
 	SPRINTF("NinjaSCSI status\n\n");
 	SPRINTF("Driver version:        $Revision: 1.23 $\n");
 	SPRINTF("SCSI host No.:         %d\n",          hostno);
@@ -1458,19 +1444,7 @@
 		}
 		SPRINTF("\n");
 	}
-
-	thislength = pos - (buffer + offset);
-
-	if(thislength < 0) {
-		*start = NULL;
-                return 0;
-        }
-
-
-	thislength = min(thislength, length);
-	*start = buffer + offset;
-
-	return thislength;
+	return 0;
 }
 #undef SPRINTF
 
diff --git a/drivers/scsi/pcmcia/nsp_cs.h b/drivers/scsi/pcmcia/nsp_cs.h
index 7fc9a9d..afd64f0 100644
--- a/drivers/scsi/pcmcia/nsp_cs.h
+++ b/drivers/scsi/pcmcia/nsp_cs.h
@@ -292,13 +292,8 @@
 /* Linux SCSI subsystem specific functions */
 static struct Scsi_Host *nsp_detect     (struct scsi_host_template *sht);
 static const  char      *nsp_info       (struct Scsi_Host *shpnt);
-static        int        nsp_proc_info  (
-	                                 struct Scsi_Host *host,
-					 char   *buffer,
-					 char  **start,
-					 off_t   offset,
-					 int     length,
-					 int     inout);
+static        int        nsp_show_info  (struct seq_file *m,
+	                                 struct Scsi_Host *host);
 static int nsp_queuecommand(struct Scsi_Host *h, struct scsi_cmnd *SCpnt);
 
 /* Error handler */
diff --git a/drivers/scsi/pmcraid.c b/drivers/scsi/pmcraid.c
index b46f5e9..8e1b737 100644
--- a/drivers/scsi/pmcraid.c
+++ b/drivers/scsi/pmcraid.c
@@ -3599,19 +3599,6 @@
 }
 
 /**
- * pmcraid_release - char node "release" entry point
- */
-static int pmcraid_chr_release(struct inode *inode, struct file *filep)
-{
-	struct pmcraid_instance *pinstance = filep->private_data;
-
-	filep->private_data = NULL;
-	fasync_helper(-1, filep, 0, &pinstance->aen_queue);
-
-	return 0;
-}
-
-/**
  * pmcraid_fasync - Async notifier registration from applications
  *
  * This function adds the calling process to a driver global queue. When an
@@ -4167,7 +4154,6 @@
 static const struct file_operations pmcraid_fops = {
 	.owner = THIS_MODULE,
 	.open = pmcraid_chr_open,
-	.release = pmcraid_chr_release,
 	.fasync = pmcraid_chr_fasync,
 	.unlocked_ioctl = pmcraid_chr_ioctl,
 #ifdef CONFIG_COMPAT
diff --git a/drivers/scsi/ppa.c b/drivers/scsi/ppa.c
index d164c96..1db8b26 100644
--- a/drivers/scsi/ppa.c
+++ b/drivers/scsi/ppa.c
@@ -118,8 +118,9 @@
  * Also gives a method to use a script to obtain optimum timings (TODO)
  */
 
-static inline int ppa_proc_write(ppa_struct *dev, char *buffer, int length)
+static inline int ppa_write_info(struct Scsi_Host *host, char *buffer, int length)
 {
+	ppa_struct *dev = ppa_dev(host);
 	unsigned long x;
 
 	if ((length > 5) && (strncmp(buffer, "mode=", 5) == 0)) {
@@ -137,35 +138,17 @@
 	return -EINVAL;
 }
 
-static int ppa_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t offset, int length, int inout)
+static int ppa_show_info(struct seq_file *m, struct Scsi_Host *host)
 {
-	int len = 0;
 	ppa_struct *dev = ppa_dev(host);
 
-	if (inout)
-		return ppa_proc_write(dev, buffer, length);
-
-	len += sprintf(buffer + len, "Version : %s\n", PPA_VERSION);
-	len +=
-	    sprintf(buffer + len, "Parport : %s\n",
-		    dev->dev->port->name);
-	len +=
-	    sprintf(buffer + len, "Mode    : %s\n",
-		    PPA_MODE_STRING[dev->mode]);
+	seq_printf(m, "Version : %s\n", PPA_VERSION);
+	seq_printf(m, "Parport : %s\n", dev->dev->port->name);
+	seq_printf(m, "Mode    : %s\n", PPA_MODE_STRING[dev->mode]);
 #if PPA_DEBUG > 0
-	len +=
-	    sprintf(buffer + len, "recon_tmo : %lu\n", dev->recon_tmo);
+	seq_printf(m, "recon_tmo : %lu\n", dev->recon_tmo);
 #endif
-
-	/* Request for beyond end of buffer */
-	if (offset > length)
-		return 0;
-
-	*start = buffer + offset;
-	len -= offset;
-	if (len > length)
-		len = length;
-	return len;
+	return 0;
 }
 
 static int device_check(ppa_struct *dev);
@@ -981,7 +964,8 @@
 static struct scsi_host_template ppa_template = {
 	.module			= THIS_MODULE,
 	.proc_name		= "ppa",
-	.proc_info		= ppa_proc_info,
+	.show_info		= ppa_show_info,
+	.write_info		= ppa_write_info,
 	.name			= "Iomega VPI0 (ppa) interface",
 	.queuecommand		= ppa_queuecommand,
 	.eh_abort_handler	= ppa_abort,
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index a083715..5307bf8 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -5539,7 +5539,7 @@
 	.err_handler	= &qla2xxx_err_handler,
 };
 
-static struct file_operations apidev_fops = {
+static const struct file_operations apidev_fops = {
 	.owner = THIS_MODULE,
 	.llseek = noop_llseek,
 };
diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c
index 5cda11c..5add6f4 100644
--- a/drivers/scsi/scsi_debug.c
+++ b/drivers/scsi/scsi_debug.c
@@ -2823,31 +2823,27 @@
 /* scsi_debug_proc_info
  * Used if the driver currently has no own support for /proc/scsi
  */
-static int scsi_debug_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t offset,
-				int length, int inout)
+static int scsi_debug_write_info(struct Scsi_Host *host, char *buffer, int length)
 {
-	int len, pos, begin;
-	int orig_length;
+	char arr[16];
+	int opts;
+	int minLen = length > 15 ? 15 : length;
 
-	orig_length = length;
+	if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO))
+		return -EACCES;
+	memcpy(arr, buffer, minLen);
+	arr[minLen] = '\0';
+	if (1 != sscanf(arr, "%d", &opts))
+		return -EINVAL;
+	scsi_debug_opts = opts;
+	if (scsi_debug_every_nth != 0)
+		scsi_debug_cmnd_count = 0;
+	return length;
+}
 
-	if (inout == 1) {
-		char arr[16];
-		int minLen = length > 15 ? 15 : length;
-
-		if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO))
-			return -EACCES;
-		memcpy(arr, buffer, minLen);
-		arr[minLen] = '\0';
-		if (1 != sscanf(arr, "%d", &pos))
-			return -EINVAL;
-		scsi_debug_opts = pos;
-		if (scsi_debug_every_nth != 0)
-                        scsi_debug_cmnd_count = 0;
-		return length;
-	}
-	begin = 0;
-	pos = len = sprintf(buffer, "scsi_debug adapter driver, version "
+static int scsi_debug_show_info(struct seq_file *m, struct Scsi_Host *host)
+{
+	seq_printf(m, "scsi_debug adapter driver, version "
 	    "%s [%s]\n"
 	    "num_tgts=%d, shared (ram) size=%d MB, opts=0x%x, "
 	    "every_nth=%d(curr:%d)\n"
@@ -2862,15 +2858,7 @@
 	    scsi_debug_sector_size, sdebug_cylinders_per, sdebug_heads,
 	    sdebug_sectors_per, num_aborts, num_dev_resets, num_bus_resets,
 	    num_host_resets, dix_reads, dix_writes, dif_errors);
-	if (pos < offset) {
-		len = 0;
-		begin = pos;
-	}
-	*start = buffer + (offset - begin);	/* Start of wanted data */
-	len -= (offset - begin);
-	if (len > length)
-		len = length;
-	return len;
+	return 0;
 }
 
 static ssize_t sdebug_delay_show(struct device_driver * ddp, char * buf)
@@ -3957,7 +3945,8 @@
 static DEF_SCSI_QCMD(scsi_debug_queuecommand)
 
 static struct scsi_host_template sdebug_driver_template = {
-	.proc_info =		scsi_debug_proc_info,
+	.show_info =		scsi_debug_show_info,
+	.write_info =		scsi_debug_write_info,
 	.proc_name =		sdebug_proc_name,
 	.name =			"SCSI DEBUG",
 	.info =			scsi_debug_info,
diff --git a/drivers/scsi/scsi_proc.c b/drivers/scsi/scsi_proc.c
index ad747dc..db66357 100644
--- a/drivers/scsi/scsi_proc.c
+++ b/drivers/scsi/scsi_proc.c
@@ -45,58 +45,50 @@
 /* Protect sht->present and sht->proc_dir */
 static DEFINE_MUTEX(global_host_template_mutex);
 
-/**
- * proc_scsi_read - handle read from /proc by calling host's proc_info() command
- * @buffer: passed to proc_info
- * @start: passed to proc_info
- * @offset: passed to proc_info
- * @length: passed to proc_info
- * @eof: returns whether length read was less than requested
- * @data: pointer to a &struct Scsi_Host
- */
-
-static int proc_scsi_read(char *buffer, char **start, off_t offset,
-			  int length, int *eof, void *data)
+static ssize_t proc_scsi_host_write(struct file *file, const char __user *buf,
+                           size_t count, loff_t *ppos)
 {
-	struct Scsi_Host *shost = data;
-	int n;
-
-	n = shost->hostt->proc_info(shost, buffer, start, offset, length, 0);
-	*eof = (n < length);
-
-	return n;
-}
-
-/**
- * proc_scsi_write_proc - Handle write to /proc by calling host's proc_info()
- * @file: not used
- * @buf: source of data to write.
- * @count: number of bytes (at most PROC_BLOCK_SIZE) to write.
- * @data: pointer to &struct Scsi_Host
- */
-static int proc_scsi_write_proc(struct file *file, const char __user *buf,
-                           unsigned long count, void *data)
-{
-	struct Scsi_Host *shost = data;
+	struct Scsi_Host *shost = PDE_DATA(file_inode(file));
 	ssize_t ret = -ENOMEM;
 	char *page;
-	char *start;
     
 	if (count > PROC_BLOCK_SIZE)
 		return -EOVERFLOW;
 
+	if (!shost->hostt->write_info)
+		return -EINVAL;
+
 	page = (char *)__get_free_page(GFP_KERNEL);
 	if (page) {
 		ret = -EFAULT;
 		if (copy_from_user(page, buf, count))
 			goto out;
-		ret = shost->hostt->proc_info(shost, page, &start, 0, count, 1);
+		ret = shost->hostt->write_info(shost, page, count);
 	}
 out:
 	free_page((unsigned long)page);
 	return ret;
 }
 
+static int proc_scsi_show(struct seq_file *m, void *v)
+{
+	struct Scsi_Host *shost = m->private;
+	return shost->hostt->show_info(m, shost);
+}
+
+static int proc_scsi_host_open(struct inode *inode, struct file *file)
+{
+	return single_open_size(file, proc_scsi_show, PDE_DATA(inode),
+				4 * PAGE_SIZE);
+}
+
+static const struct file_operations proc_scsi_fops = {
+	.open = proc_scsi_host_open,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.write = proc_scsi_host_write
+};
+
 /**
  * scsi_proc_hostdir_add - Create directory in /proc for a scsi host
  * @sht: owner of this directory
@@ -106,7 +98,7 @@
 
 void scsi_proc_hostdir_add(struct scsi_host_template *sht)
 {
-	if (!sht->proc_info)
+	if (!sht->show_info)
 		return;
 
 	mutex_lock(&global_host_template_mutex);
@@ -125,7 +117,7 @@
  */
 void scsi_proc_hostdir_rm(struct scsi_host_template *sht)
 {
-	if (!sht->proc_info)
+	if (!sht->show_info)
 		return;
 
 	mutex_lock(&global_host_template_mutex);
@@ -151,16 +143,12 @@
 		return;
 
 	sprintf(name,"%d", shost->host_no);
-	p = create_proc_read_entry(name, S_IFREG | S_IRUGO | S_IWUSR,
-			sht->proc_dir, proc_scsi_read, shost);
-	if (!p) {
+	p = proc_create_data(name, S_IRUGO | S_IWUSR,
+		sht->proc_dir, &proc_scsi_fops, shost);
+	if (!p)
 		printk(KERN_ERR "%s: Failed to register host %d in"
 		       "%s\n", __func__, shost->host_no,
 		       sht->proc_name);
-		return;
-	} 
-
-	p->write_proc = proc_scsi_write_proc;
 }
 
 /**
diff --git a/drivers/scsi/sym53c8xx_2/sym_glue.c b/drivers/scsi/sym53c8xx_2/sym_glue.c
index 5995682..bac55f7 100644
--- a/drivers/scsi/sym53c8xx_2/sym_glue.c
+++ b/drivers/scsi/sym53c8xx_2/sym_glue.c
@@ -1171,112 +1171,36 @@
 #endif	/* SYM_LINUX_USER_COMMAND_SUPPORT */
 
 
-#ifdef SYM_LINUX_USER_INFO_SUPPORT
-/*
- *  Informations through the proc file system.
- */
-struct info_str {
-	char *buffer;
-	int length;
-	int offset;
-	int pos;
-};
-
-static void copy_mem_info(struct info_str *info, char *data, int len)
-{
-	if (info->pos + len > info->length)
-		len = info->length - info->pos;
-
-	if (info->pos + len < info->offset) {
-		info->pos += len;
-		return;
-	}
-	if (info->pos < info->offset) {
-		data += (info->offset - info->pos);
-		len  -= (info->offset - info->pos);
-	}
-
-	if (len > 0) {
-		memcpy(info->buffer + info->pos, data, len);
-		info->pos += len;
-	}
-}
-
-static int copy_info(struct info_str *info, char *fmt, ...)
-{
-	va_list args;
-	char buf[81];
-	int len;
-
-	va_start(args, fmt);
-	len = vsprintf(buf, fmt, args);
-	va_end(args);
-
-	copy_mem_info(info, buf, len);
-	return len;
-}
-
 /*
  *  Copy formatted information into the input buffer.
  */
-static int sym_host_info(struct Scsi_Host *shost, char *ptr, off_t offset, int len)
+static int sym_show_info(struct seq_file *m, struct Scsi_Host *shost)
 {
+#ifdef SYM_LINUX_USER_INFO_SUPPORT
 	struct sym_data *sym_data = shost_priv(shost);
 	struct pci_dev *pdev = sym_data->pdev;
 	struct sym_hcb *np = sym_data->ncb;
-	struct info_str info;
 
-	info.buffer	= ptr;
-	info.length	= len;
-	info.offset	= offset;
-	info.pos	= 0;
-
-	copy_info(&info, "Chip " NAME53C "%s, device id 0x%x, "
-			 "revision id 0x%x\n", np->s.chip_name,
-			 pdev->device, pdev->revision);
-	copy_info(&info, "At PCI address %s, IRQ %u\n",
+	seq_printf(m, "Chip " NAME53C "%s, device id 0x%x, "
+		 "revision id 0x%x\n", np->s.chip_name,
+		 pdev->device, pdev->revision);
+	seq_printf(m, "At PCI address %s, IRQ %u\n",
 			 pci_name(pdev), pdev->irq);
-	copy_info(&info, "Min. period factor %d, %s SCSI BUS%s\n",
-			 (int) (np->minsync_dt ? np->minsync_dt : np->minsync),
-			 np->maxwide ? "Wide" : "Narrow",
-			 np->minsync_dt ? ", DT capable" : "");
+	seq_printf(m, "Min. period factor %d, %s SCSI BUS%s\n",
+		 (int) (np->minsync_dt ? np->minsync_dt : np->minsync),
+		 np->maxwide ? "Wide" : "Narrow",
+		 np->minsync_dt ? ", DT capable" : "");
 
-	copy_info(&info, "Max. started commands %d, "
-			 "max. commands per LUN %d\n",
-			 SYM_CONF_MAX_START, SYM_CONF_MAX_TAG);
+	seq_printf(m, "Max. started commands %d, "
+		 "max. commands per LUN %d\n",
+		 SYM_CONF_MAX_START, SYM_CONF_MAX_TAG);
 
-	return info.pos > info.offset? info.pos - info.offset : 0;
-}
+	return 0;
+#else
+	return -EINVAL;
 #endif /* SYM_LINUX_USER_INFO_SUPPORT */
-
-/*
- *  Entry point of the scsi proc fs of the driver.
- *  - func = 0 means read  (returns adapter infos)
- *  - func = 1 means write (not yet merget from sym53c8xx)
- */
-static int sym53c8xx_proc_info(struct Scsi_Host *shost, char *buffer,
-			char **start, off_t offset, int length, int func)
-{
-	int retv;
-
-	if (func) {
-#ifdef	SYM_LINUX_USER_COMMAND_SUPPORT
-		retv = sym_user_command(shost, buffer, length);
-#else
-		retv = -EINVAL;
-#endif
-	} else {
-		if (start)
-			*start = buffer;
-#ifdef SYM_LINUX_USER_INFO_SUPPORT
-		retv = sym_host_info(shost, buffer, offset, length);
-#else
-		retv = -EINVAL;
-#endif
-	}
-
-	return retv;
 }
+
 #endif /* SYM_LINUX_PROC_INFO_SUPPORT */
 
 /*
@@ -1742,7 +1666,10 @@
 	.use_clustering		= ENABLE_CLUSTERING,
 	.max_sectors		= 0xFFFF,
 #ifdef SYM_LINUX_PROC_INFO_SUPPORT
-	.proc_info		= sym53c8xx_proc_info,
+	.show_info		= sym_show_info,
+#ifdef	SYM_LINUX_USER_COMMAND_SUPPORT
+	.write_info		= sym_user_command,
+#endif
 	.proc_name		= NAME53C8XX,
 #endif
 };
diff --git a/drivers/scsi/t128.c b/drivers/scsi/t128.c
index d672d97..f1e4b41 100644
--- a/drivers/scsi/t128.c
+++ b/drivers/scsi/t128.c
@@ -201,7 +201,8 @@
     int sig, count;
 
     tpnt->proc_name = "t128";
-    tpnt->proc_info = &t128_proc_info;
+    tpnt->show_info = t128_show_info;
+    tpnt->write_info = t128_write_info;
 
     for (count = 0; current_override < NO_OVERRIDES; ++current_override) {
 	base = 0;
diff --git a/drivers/scsi/t128.h b/drivers/scsi/t128.h
index ada1115..1df82c28 100644
--- a/drivers/scsi/t128.h
+++ b/drivers/scsi/t128.h
@@ -140,7 +140,8 @@
 #define NCR5380_queue_command t128_queue_command
 #define NCR5380_abort t128_abort
 #define NCR5380_bus_reset t128_bus_reset
-#define NCR5380_proc_info t128_proc_info
+#define NCR5380_show_info t128_show_info
+#define NCR5380_write_info t128_write_info
 
 /* 15 14 12 10 7 5 3
    1101 0100 1010 1000 */
diff --git a/drivers/scsi/wd33c93.c b/drivers/scsi/wd33c93.c
index c0ee4ea..41883a8 100644
--- a/drivers/scsi/wd33c93.c
+++ b/drivers/scsi/wd33c93.c
@@ -2054,22 +2054,16 @@
 	printk("           Version %s - %s\n", WD33C93_VERSION, WD33C93_DATE);
 }
 
-int
-wd33c93_proc_info(struct Scsi_Host *instance, char *buf, char **start, off_t off, int len, int in)
+int wd33c93_write_info(struct Scsi_Host *instance, char *buf, int len)
 {
-
 #ifdef PROC_INTERFACE
-
 	char *bp;
-	char tbuf[128];
 	struct WD33C93_hostdata *hd;
-	struct scsi_cmnd *cmd;
 	int x;
-	static int stop = 0;
 
 	hd = (struct WD33C93_hostdata *) instance->hostdata;
 
-/* If 'in' is TRUE we need to _read_ the proc file. We accept the following
+/* We accept the following
  * keywords (same format as command-line, but arguments are not optional):
  *    debug
  *    disconnect
@@ -2083,145 +2077,124 @@
  *    nosync
  */
 
-	if (in) {
-		buf[len] = '\0';
-		for (bp = buf; *bp; ) {
-			while (',' == *bp || ' ' == *bp)
-				++bp;
-		if (!strncmp(bp, "debug:", 6)) {
-				hd->args = simple_strtoul(bp+6, &bp, 0) & DB_MASK;
-		} else if (!strncmp(bp, "disconnect:", 11)) {
-				x = simple_strtoul(bp+11, &bp, 0);
-			if (x < DIS_NEVER || x > DIS_ALWAYS)
-				x = DIS_ADAPTIVE;
-			hd->disconnect = x;
-		} else if (!strncmp(bp, "period:", 7)) {
+	buf[len] = '\0';
+	for (bp = buf; *bp; ) {
+		while (',' == *bp || ' ' == *bp)
+			++bp;
+	if (!strncmp(bp, "debug:", 6)) {
+			hd->args = simple_strtoul(bp+6, &bp, 0) & DB_MASK;
+	} else if (!strncmp(bp, "disconnect:", 11)) {
+			x = simple_strtoul(bp+11, &bp, 0);
+		if (x < DIS_NEVER || x > DIS_ALWAYS)
+			x = DIS_ADAPTIVE;
+		hd->disconnect = x;
+	} else if (!strncmp(bp, "period:", 7)) {
+		x = simple_strtoul(bp+7, &bp, 0);
+		hd->default_sx_per =
+			hd->sx_table[round_period((unsigned int) x,
+						  hd->sx_table)].period_ns;
+	} else if (!strncmp(bp, "resync:", 7)) {
+			set_resync(hd, (int)simple_strtoul(bp+7, &bp, 0));
+	} else if (!strncmp(bp, "proc:", 5)) {
+			hd->proc = simple_strtoul(bp+5, &bp, 0);
+	} else if (!strncmp(bp, "nodma:", 6)) {
+			hd->no_dma = simple_strtoul(bp+6, &bp, 0);
+	} else if (!strncmp(bp, "level2:", 7)) {
+			hd->level2 = simple_strtoul(bp+7, &bp, 0);
+		} else if (!strncmp(bp, "burst:", 6)) {
+			hd->dma_mode =
+				simple_strtol(bp+6, &bp, 0) ? CTRL_BURST:CTRL_DMA;
+		} else if (!strncmp(bp, "fast:", 5)) {
+			x = !!simple_strtol(bp+5, &bp, 0);
+			if (x != hd->fast)
+				set_resync(hd, 0xff);
+			hd->fast = x;
+		} else if (!strncmp(bp, "nosync:", 7)) {
 			x = simple_strtoul(bp+7, &bp, 0);
-			hd->default_sx_per =
-				hd->sx_table[round_period((unsigned int) x,
-							  hd->sx_table)].period_ns;
-		} else if (!strncmp(bp, "resync:", 7)) {
-				set_resync(hd, (int)simple_strtoul(bp+7, &bp, 0));
-		} else if (!strncmp(bp, "proc:", 5)) {
-				hd->proc = simple_strtoul(bp+5, &bp, 0);
-		} else if (!strncmp(bp, "nodma:", 6)) {
-				hd->no_dma = simple_strtoul(bp+6, &bp, 0);
-		} else if (!strncmp(bp, "level2:", 7)) {
-				hd->level2 = simple_strtoul(bp+7, &bp, 0);
-			} else if (!strncmp(bp, "burst:", 6)) {
-				hd->dma_mode =
-					simple_strtol(bp+6, &bp, 0) ? CTRL_BURST:CTRL_DMA;
-			} else if (!strncmp(bp, "fast:", 5)) {
-				x = !!simple_strtol(bp+5, &bp, 0);
-				if (x != hd->fast)
-					set_resync(hd, 0xff);
-				hd->fast = x;
-			} else if (!strncmp(bp, "nosync:", 7)) {
-				x = simple_strtoul(bp+7, &bp, 0);
-				set_resync(hd, x ^ hd->no_sync);
-				hd->no_sync = x;
-			} else {
-				break; /* unknown keyword,syntax-error,... */
-			}
+			set_resync(hd, x ^ hd->no_sync);
+			hd->no_sync = x;
+		} else {
+			break; /* unknown keyword,syntax-error,... */
 		}
-		return len;
 	}
+	return len;
+#else
+	return 0;
+#endif
+}
+
+int
+wd33c93_show_info(struct seq_file *m, struct Scsi_Host *instance)
+{
+#ifdef PROC_INTERFACE
+	struct WD33C93_hostdata *hd;
+	struct scsi_cmnd *cmd;
+	int x;
+
+	hd = (struct WD33C93_hostdata *) instance->hostdata;
 
 	spin_lock_irq(&hd->lock);
-	bp = buf;
-	*bp = '\0';
-	if (hd->proc & PR_VERSION) {
-		sprintf(tbuf, "\nVersion %s - %s.",
+	if (hd->proc & PR_VERSION)
+		seq_printf(m, "\nVersion %s - %s.",
 			WD33C93_VERSION, WD33C93_DATE);
-		strcat(bp, tbuf);
-	}
+
 	if (hd->proc & PR_INFO) {
-		sprintf(tbuf, "\nclock_freq=%02x no_sync=%02x no_dma=%d"
+		seq_printf(m, "\nclock_freq=%02x no_sync=%02x no_dma=%d"
 			" dma_mode=%02x fast=%d",
 			hd->clock_freq, hd->no_sync, hd->no_dma, hd->dma_mode, hd->fast);
-		strcat(bp, tbuf);
-		strcat(bp, "\nsync_xfer[] =       ");
-		for (x = 0; x < 7; x++) {
-			sprintf(tbuf, "\t%02x", hd->sync_xfer[x]);
-			strcat(bp, tbuf);
-		}
-		strcat(bp, "\nsync_stat[] =       ");
-		for (x = 0; x < 7; x++) {
-			sprintf(tbuf, "\t%02x", hd->sync_stat[x]);
-			strcat(bp, tbuf);
-		}
+		seq_printf(m, "\nsync_xfer[] =       ");
+		for (x = 0; x < 7; x++)
+			seq_printf(m, "\t%02x", hd->sync_xfer[x]);
+		seq_printf(m, "\nsync_stat[] =       ");
+		for (x = 0; x < 7; x++)
+			seq_printf(m, "\t%02x", hd->sync_stat[x]);
 	}
 #ifdef PROC_STATISTICS
 	if (hd->proc & PR_STATISTICS) {
-		strcat(bp, "\ncommands issued:    ");
-		for (x = 0; x < 7; x++) {
-			sprintf(tbuf, "\t%ld", hd->cmd_cnt[x]);
-			strcat(bp, tbuf);
-		}
-		strcat(bp, "\ndisconnects allowed:");
-		for (x = 0; x < 7; x++) {
-			sprintf(tbuf, "\t%ld", hd->disc_allowed_cnt[x]);
-			strcat(bp, tbuf);
-		}
-		strcat(bp, "\ndisconnects done:   ");
-		for (x = 0; x < 7; x++) {
-			sprintf(tbuf, "\t%ld", hd->disc_done_cnt[x]);
-			strcat(bp, tbuf);
-		}
-		sprintf(tbuf,
+		seq_printf(m, "\ncommands issued:    ");
+		for (x = 0; x < 7; x++)
+			seq_printf(m, "\t%ld", hd->cmd_cnt[x]);
+		seq_printf(m, "\ndisconnects allowed:");
+		for (x = 0; x < 7; x++)
+			seq_printf(m, "\t%ld", hd->disc_allowed_cnt[x]);
+		seq_printf(m, "\ndisconnects done:   ");
+		for (x = 0; x < 7; x++)
+			seq_printf(m, "\t%ld", hd->disc_done_cnt[x]);
+		seq_printf(m,
 			"\ninterrupts: %ld, DATA_PHASE ints: %ld DMA, %ld PIO",
 			hd->int_cnt, hd->dma_cnt, hd->pio_cnt);
-		strcat(bp, tbuf);
 	}
 #endif
 	if (hd->proc & PR_CONNECTED) {
-		strcat(bp, "\nconnected:     ");
+		seq_printf(m, "\nconnected:     ");
 		if (hd->connected) {
 			cmd = (struct scsi_cmnd *) hd->connected;
-			sprintf(tbuf, " %d:%d(%02x)",
+			seq_printf(m, " %d:%d(%02x)",
 				cmd->device->id, cmd->device->lun, cmd->cmnd[0]);
-			strcat(bp, tbuf);
 		}
 	}
 	if (hd->proc & PR_INPUTQ) {
-		strcat(bp, "\ninput_Q:       ");
+		seq_printf(m, "\ninput_Q:       ");
 		cmd = (struct scsi_cmnd *) hd->input_Q;
 		while (cmd) {
-			sprintf(tbuf, " %d:%d(%02x)",
+			seq_printf(m, " %d:%d(%02x)",
 				cmd->device->id, cmd->device->lun, cmd->cmnd[0]);
-			strcat(bp, tbuf);
 			cmd = (struct scsi_cmnd *) cmd->host_scribble;
 		}
 	}
 	if (hd->proc & PR_DISCQ) {
-		strcat(bp, "\ndisconnected_Q:");
+		seq_printf(m, "\ndisconnected_Q:");
 		cmd = (struct scsi_cmnd *) hd->disconnected_Q;
 		while (cmd) {
-			sprintf(tbuf, " %d:%d(%02x)",
+			seq_printf(m, " %d:%d(%02x)",
 				cmd->device->id, cmd->device->lun, cmd->cmnd[0]);
-			strcat(bp, tbuf);
 			cmd = (struct scsi_cmnd *) cmd->host_scribble;
 		}
 	}
-	strcat(bp, "\n");
+	seq_printf(m, "\n");
 	spin_unlock_irq(&hd->lock);
-	*start = buf;
-	if (stop) {
-		stop = 0;
-		return 0;
-	}
-	if (off > 0x40000)	/* ALWAYS stop after 256k bytes have been read */
-		stop = 1;
-	if (hd->proc & PR_STOP)	/* stop every other time */
-		stop = 1;
-	return strlen(bp);
-
-#else				/* PROC_INTERFACE */
-
-	return 0;
-
 #endif				/* PROC_INTERFACE */
-
+	return 0;
 }
 
 EXPORT_SYMBOL(wd33c93_host_reset);
@@ -2229,4 +2202,5 @@
 EXPORT_SYMBOL(wd33c93_abort);
 EXPORT_SYMBOL(wd33c93_queuecommand);
 EXPORT_SYMBOL(wd33c93_intr);
-EXPORT_SYMBOL(wd33c93_proc_info);
+EXPORT_SYMBOL(wd33c93_show_info);
+EXPORT_SYMBOL(wd33c93_write_info);
diff --git a/drivers/scsi/wd33c93.h b/drivers/scsi/wd33c93.h
index 3b463d7..08abe50 100644
--- a/drivers/scsi/wd33c93.h
+++ b/drivers/scsi/wd33c93.h
@@ -345,7 +345,8 @@
 int wd33c93_abort (struct scsi_cmnd *cmd);
 int wd33c93_queuecommand (struct Scsi_Host *h, struct scsi_cmnd *cmd);
 void wd33c93_intr (struct Scsi_Host *instance);
-int wd33c93_proc_info(struct Scsi_Host *, char *, char **, off_t, int, int);
+int wd33c93_show_info(struct seq_file *, struct Scsi_Host *);
+int wd33c93_write_info(struct Scsi_Host *, char *, int);
 int wd33c93_host_reset (struct scsi_cmnd *);
 
 #endif /* WD33C93_H */
diff --git a/drivers/scsi/wd7000.c b/drivers/scsi/wd7000.c
index d89a5df..f9a6e4b 100644
--- a/drivers/scsi/wd7000.c
+++ b/drivers/scsi/wd7000.c
@@ -1296,9 +1296,9 @@
 
 
 #undef SPRINTF
-#define SPRINTF(args...) { if (pos < (buffer + length)) pos += sprintf (pos, ## args); }
+#define SPRINTF(args...) { seq_printf(m, ## args); }
 
-static int wd7000_set_info(char *buffer, int length, struct Scsi_Host *host)
+static int wd7000_set_info(struct Scsi_Host *host, char *buffer, int length)
 {
 	dprintk("Buffer = <%.*s>, length = %d\n", length, buffer, length);
 
@@ -1310,22 +1310,15 @@
 }
 
 
-static int wd7000_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t offset, int length,  int inout)
+static int wd7000_show_info(struct seq_file *m, struct Scsi_Host *host)
 {
 	Adapter *adapter = (Adapter *)host->hostdata;
 	unsigned long flags;
-	char *pos = buffer;
 #ifdef WD7000_DEBUG
 	Mailbox *ogmbs, *icmbs;
 	short count;
 #endif
 
-	/*
-	 * Has data been written to the file ?
-	 */
-	if (inout)
-		return (wd7000_set_info(buffer, length, host));
-
 	spin_lock_irqsave(host->host_lock, flags);
 	SPRINTF("Host scsi%d: Western Digital WD-7000 (rev %d.%d)\n", host->host_no, adapter->rev1, adapter->rev2);
 	SPRINTF("  IO base:      0x%x\n", adapter->iobase);
@@ -1368,17 +1361,7 @@
 
 	spin_unlock_irqrestore(host->host_lock, flags);
 
-	/*
-	 * Calculate start of next buffer, and return value.
-	 */
-	*start = buffer + offset;
-
-	if ((pos - buffer) < offset)
-		return (0);
-	else if ((pos - buffer - offset) < length)
-		return (pos - buffer - offset);
-	else
-		return (length);
+	return 0;
 }
 
 
@@ -1413,7 +1396,8 @@
 	for (i = 0; i < NUM_CONFIGS; biosptr[i++] = -1);
 
 	tpnt->proc_name = "wd7000";
-	tpnt->proc_info = &wd7000_proc_info;
+	tpnt->show_info = &wd7000_show_info;
+	tpnt->write_info = wd7000_set_info;
 
 	/*
 	 * Set up SCB free list, which is shared by all adapters
@@ -1658,7 +1642,8 @@
 
 static struct scsi_host_template driver_template = {
 	.proc_name		= "wd7000",
-	.proc_info		= wd7000_proc_info,
+	.show_info		= wd7000_show_info,
+	.write_info		= wd7000_set_info,
 	.name			= "Western Digital WD-7000",
 	.detect			= wd7000_detect,
 	.release		= wd7000_release,
diff --git a/drivers/staging/comedi/proc.c b/drivers/staging/comedi/proc.c
index 362c214..db790f9 100644
--- a/drivers/staging/comedi/proc.c
+++ b/drivers/staging/comedi/proc.c
@@ -31,17 +31,15 @@
 #include "comedidev.h"
 #include "comedi_internal.h"
 #include <linux/proc_fs.h>
-#include <linux/string.h>
+#include <linux/seq_file.h>
 
-static int comedi_read(char *buf, char **start, off_t offset, int len,
-		       int *eof, void *data)
+static int comedi_read(struct seq_file *m, void *v)
 {
 	int i;
 	int devices_q = 0;
-	int l = 0;
 	struct comedi_driver *driv;
 
-	l += sprintf(buf + l,
+	seq_printf(m,
 		     "comedi version " COMEDI_RELEASE "\n"
 		     "format string: %s\n",
 		     "\"%2d: %-20s %-20s %4d\", i, "
@@ -49,42 +47,51 @@
 
 	for (i = 0; i < COMEDI_NUM_BOARD_MINORS; i++) {
 		struct comedi_device *dev = comedi_dev_from_minor(i);
-
 		if (!dev)
 			continue;
 
 		if (dev->attached) {
 			devices_q = 1;
-			l += sprintf(buf + l, "%2d: %-20s %-20s %4d\n",
-				     i,
-				     dev->driver->driver_name,
-				     dev->board_name, dev->n_subdevices);
+			seq_printf(m, "%2d: %-20s %-20s %4d\n",
+				   i, dev->driver->driver_name,
+				   dev->board_name, dev->n_subdevices);
 		}
 	}
 	if (!devices_q)
-		l += sprintf(buf + l, "no devices\n");
+		seq_puts(m, "no devices\n");
 
 	for (driv = comedi_drivers; driv; driv = driv->next) {
-		l += sprintf(buf + l, "%s:\n", driv->driver_name);
-		for (i = 0; i < driv->num_names; i++) {
-			l += sprintf(buf + l, " %s\n",
-				     *(char **)((char *)driv->board_name +
-						i * driv->offset));
-		}
+		seq_printf(m, "%s:\n", driv->driver_name);
+		for (i = 0; i < driv->num_names; i++)
+			seq_printf(m, " %s\n",
+				   *(char **)((char *)driv->board_name +
+					      i * driv->offset));
+
 		if (!driv->num_names)
-			l += sprintf(buf + l, " %s\n", driv->driver_name);
+			seq_printf(m, " %s\n", driv->driver_name);
 	}
 
-	return l;
+	return 0;
 }
 
+/*
+ * seq_file wrappers for procfile show routines.
+ */
+static int comedi_proc_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, comedi_read, NULL);
+}
+
+static const struct file_operations comedi_proc_fops = {
+	.open		= comedi_proc_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= seq_release,
+};
+
 void comedi_proc_init(void)
 {
-	struct proc_dir_entry *comedi_proc;
-
-	comedi_proc = create_proc_entry("comedi", S_IFREG | S_IRUGO, NULL);
-	if (comedi_proc)
-		comedi_proc->read_proc = comedi_read;
+	proc_create("comedi", 0644, NULL, &comedi_proc_fops);
 }
 
 void comedi_proc_cleanup(void)
diff --git a/drivers/staging/csr/csr_wifi_hip_udi.c b/drivers/staging/csr/csr_wifi_hip_udi.c
index a65b822..a6b006b 100644
--- a/drivers/staging/csr/csr_wifi_hip_udi.c
+++ b/drivers/staging/csr/csr_wifi_hip_udi.c
@@ -24,10 +24,50 @@
  *
  * ---------------------------------------------------------------------------
  */
+#include <linux/seq_file.h>
 #include "csr_wifi_hip_unifi.h"
 #include "csr_wifi_hip_card.h"
 
 
+static void unifi_print_unsafe_sdio_status(card_t *card, struct seq_file *m)
+{
+#ifdef CSR_UNSAFE_SDIO_ACCESS
+	s32 iostate;
+	CsrResult r;
+	static const char *const states[] = {
+		"AWAKE", "DROWSY", "TORPID"
+	};
+#define SHARED_READ_RETRY_LIMIT 10
+	u8 b;
+
+	seq_printf(m, "Host State: %s\n", states[card->host_state]);
+
+	r = unifi_check_io_status(card, &iostate);
+	if (iostate == 1) {
+		seq_puts(m, remaining, "I/O Check: F1 disabled\n");
+        } else {
+		if (iostate == 1) {
+			seq_puts(m, "I/O Check: pending interrupt\n");
+
+		seq_printf(m, "BH reason interrupt = %d\n", card->bh_reason_unifi);
+		seq_printf(m, "BH reason host      = %d\n", card->bh_reason_host);
+
+		for (i = 0; i < SHARED_READ_RETRY_LIMIT; i++) {
+			r = unifi_read_8_or_16(card, card->sdio_ctrl_addr + 2, &b);
+			if (r == CSR_RESULT_SUCCESS && !(b & 0x80)) {
+				seq_printf(m, "fhsr: %u (driver thinks is %u)\n",
+					   b, card->from_host_signals_r);
+				break;
+			}
+		}
+
+		iostate = unifi_read_shared_count(card, card->sdio_ctrl_addr + 4);
+		seq_printf(m, "thsw: %u (driver thinks is %u)\n",
+			   iostate, card->to_host_signals_w);
+        }
+#endif
+}
+
 /*
  * ---------------------------------------------------------------------------
  *  unifi_print_status
@@ -41,228 +81,93 @@
  *      None.
  * ---------------------------------------------------------------------------
  */
-s32 unifi_print_status(card_t *card, char *str, s32 *remain)
+s32 unifi_print_status(card_t *card, struct seq_file *m)
 {
-    char *p = str;
-    sdio_config_data_t *cfg;
-    u16 i, n;
-    s32 remaining = *remain;
-    s32 written;
-#ifdef CSR_UNSAFE_SDIO_ACCESS
-    s32 iostate;
-    CsrResult r;
-    static const char *const states[] = {
-        "AWAKE", "DROWSY", "TORPID"
-    };
-    #define SHARED_READ_RETRY_LIMIT 10
-    u8 b;
-#endif
+	sdio_config_data_t *cfg;
+	u16 i, n;
 
-    if (remaining <= 0)
-    {
-        return 0;
-    }
+	i = n = 0;
+	seq_printf(m, "Chip ID %u\n", card->chip_id);
+	seq_printf(m, "Chip Version %04X\n", card->chip_version);
+	seq_printf(m, "HIP v%u.%u\n",
+		   (card->config_data.version >> 8) & 0xFF,
+		   card->config_data.version & 0xFF);
+	seq_printf(m, "Build %u: %s\n", card->build_id, card->build_id_string);
 
-    i = n = 0;
-    written = scnprintf(p, remaining, "Chip ID %u\n",
-                          (u16)card->chip_id);
-    UNIFI_SNPRINTF_RET(p, remaining, written);
-    written = scnprintf(p, remaining, "Chip Version %04X\n",
-                          card->chip_version);
-    UNIFI_SNPRINTF_RET(p, remaining, written);
-    written = scnprintf(p, remaining, "HIP v%u.%u\n",
-                          (card->config_data.version >> 8) & 0xFF,
-                          card->config_data.version & 0xFF);
-    UNIFI_SNPRINTF_RET(p, remaining, written);
-    written = scnprintf(p, remaining, "Build %u: %s\n",
-                          card->build_id, card->build_id_string);
-    UNIFI_SNPRINTF_RET(p, remaining, written);
+	cfg = &card->config_data;
 
-    cfg = &card->config_data;
+	seq_printf(m, "sdio ctrl offset          %u\n", cfg->sdio_ctrl_offset);
+	seq_printf(m, "fromhost sigbuf handle    %u\n", cfg->fromhost_sigbuf_handle);
+	seq_printf(m, "tohost_sigbuf_handle      %u\n", cfg->tohost_sigbuf_handle);
+	seq_printf(m, "num_fromhost_sig_frags    %u\n", cfg->num_fromhost_sig_frags);
+	seq_printf(m, "num_tohost_sig_frags      %u\n", cfg->num_tohost_sig_frags);
+	seq_printf(m, "num_fromhost_data_slots   %u\n", cfg->num_fromhost_data_slots);
+	seq_printf(m, "num_tohost_data_slots     %u\n", cfg->num_tohost_data_slots);
+	seq_printf(m, "data_slot_size            %u\n", cfg->data_slot_size);
 
-    written = scnprintf(p, remaining, "sdio ctrl offset          %u\n",
-                          cfg->sdio_ctrl_offset);
-    UNIFI_SNPRINTF_RET(p, remaining, written);
-    written = scnprintf(p, remaining, "fromhost sigbuf handle    %u\n",
-                          cfg->fromhost_sigbuf_handle);
-    UNIFI_SNPRINTF_RET(p, remaining, written);
-    written = scnprintf(p, remaining, "tohost_sigbuf_handle      %u\n",
-                          cfg->tohost_sigbuf_handle);
-    UNIFI_SNPRINTF_RET(p, remaining, written);
-    written = scnprintf(p, remaining, "num_fromhost_sig_frags    %u\n",
-                          cfg->num_fromhost_sig_frags);
-    UNIFI_SNPRINTF_RET(p, remaining, written);
-    written = scnprintf(p, remaining, "num_tohost_sig_frags      %u\n",
-                          cfg->num_tohost_sig_frags);
-    UNIFI_SNPRINTF_RET(p, remaining, written);
-    written = scnprintf(p, remaining, "num_fromhost_data_slots   %u\n",
-                          cfg->num_fromhost_data_slots);
-    UNIFI_SNPRINTF_RET(p, remaining, written);
-    written = scnprintf(p, remaining, "num_tohost_data_slots     %u\n",
-                          cfg->num_tohost_data_slots);
-    UNIFI_SNPRINTF_RET(p, remaining, written);
-    written = scnprintf(p, remaining, "data_slot_size            %u\n",
-                          cfg->data_slot_size);
-    UNIFI_SNPRINTF_RET(p, remaining, written);
+	/* Added by protocol version 0x0001 */
+	seq_printf(m, "overlay_size              %u\n", cfg->overlay_size);
 
-    /* Added by protocol version 0x0001 */
-    written = scnprintf(p, remaining, "overlay_size              %u\n",
-                          (u16)cfg->overlay_size);
-    UNIFI_SNPRINTF_RET(p, remaining, written);
+	/* Added by protocol version 0x0300 */
+	seq_printf(m, "data_slot_round           %u\n", cfg->data_slot_round);
+	seq_printf(m, "sig_frag_size             %u\n", cfg->sig_frag_size);
 
-    /* Added by protocol version 0x0300 */
-    written = scnprintf(p, remaining, "data_slot_round           %u\n",
-                          cfg->data_slot_round);
-    UNIFI_SNPRINTF_RET(p, remaining, written);
-    written = scnprintf(p, remaining, "sig_frag_size             %u\n",
-                          cfg->sig_frag_size);
-    UNIFI_SNPRINTF_RET(p, remaining, written);
+	/* Added by protocol version 0x0300 */
+	seq_printf(m, "tohost_sig_pad            %u\n", cfg->tohost_signal_padding);
 
-    /* Added by protocol version 0x0300 */
-    written = scnprintf(p, remaining, "tohost_sig_pad            %u\n",
-                          cfg->tohost_signal_padding);
-    UNIFI_SNPRINTF_RET(p, remaining, written);
+	seq_puts(m, "\nInternal state:\n");
 
-    written = scnprintf(p, remaining, "\nInternal state:\n");
-    UNIFI_SNPRINTF_RET(p, remaining, written);
+	seq_printf(m, "Last PHY PANIC: %04x:%04x\n",
+		   card->last_phy_panic_code, card->last_phy_panic_arg);
+	seq_printf(m, "Last MAC PANIC: %04x:%04x\n",
+		   card->last_mac_panic_code, card->last_mac_panic_arg);
 
-    written = scnprintf(p, remaining, "Last PHY PANIC: %04x:%04x\n",
-                          card->last_phy_panic_code, card->last_phy_panic_arg);
-    UNIFI_SNPRINTF_RET(p, remaining, written);
-    written = scnprintf(p, remaining, "Last MAC PANIC: %04x:%04x\n",
-                          card->last_mac_panic_code, card->last_mac_panic_arg);
-    UNIFI_SNPRINTF_RET(p, remaining, written);
+	seq_printf(m, "fhsr: %hu\n", (u16)card->from_host_signals_r);
+	seq_printf(m, "fhsw: %hu\n", (u16)card->from_host_signals_w);
+	seq_printf(m, "thsr: %hu\n", (u16)card->to_host_signals_r);
+	seq_printf(m, "thsw: %hu\n", (u16)card->to_host_signals_w);
+	seq_printf(m, "fh buffer contains: %d signals, %td bytes\n",
+		   card->fh_buffer.count,
+		   card->fh_buffer.ptr - card->fh_buffer.buf);
 
-    written = scnprintf(p, remaining, "fhsr: %u\n",
-                          (u16)card->from_host_signals_r);
-    UNIFI_SNPRINTF_RET(p, remaining, written);
-    written = scnprintf(p, remaining, "fhsw: %u\n",
-                          (u16)card->from_host_signals_w);
-    UNIFI_SNPRINTF_RET(p, remaining, written);
-    written = scnprintf(p, remaining, "thsr: %u\n",
-                          (u16)card->to_host_signals_r);
-    UNIFI_SNPRINTF_RET(p, remaining, written);
-    written = scnprintf(p, remaining, "thsw: %u\n",
-                          (u16)card->to_host_signals_w);
-    UNIFI_SNPRINTF_RET(p, remaining, written);
-    written = scnprintf(p, remaining,
-                          "fh buffer contains: %d signals, %td bytes\n",
-                          card->fh_buffer.count,
-                          card->fh_buffer.ptr - card->fh_buffer.buf);
-    UNIFI_SNPRINTF_RET(p, remaining, written);
+	seq_puts(m, "paused: ");
+	for (i = 0; i < ARRAY_SIZE(card->tx_q_paused_flag); i++)
+		seq_printf(m, card->tx_q_paused_flag[i] ? "1" : "0");
+	seq_putc(m, '\n');
 
-    written = scnprintf(p, remaining, "paused: ");
-    UNIFI_SNPRINTF_RET(p, remaining, written);
-    for (i = 0; i < sizeof(card->tx_q_paused_flag) / sizeof(card->tx_q_paused_flag[0]); i++)
-    {
-        written = scnprintf(p, remaining, card->tx_q_paused_flag[i]?"1" : "0");
-        UNIFI_SNPRINTF_RET(p, remaining, written);
-    }
-    written = scnprintf(p, remaining, "\n");
-    UNIFI_SNPRINTF_RET(p, remaining, written);
+	seq_printf(m, "fh command q: %u waiting, %u free of %u:\n",
+		   CSR_WIFI_HIP_Q_SLOTS_USED(&card->fh_command_queue),
+		   CSR_WIFI_HIP_Q_SLOTS_FREE(&card->fh_command_queue),
+		   UNIFI_SOFT_COMMAND_Q_LENGTH);
 
-    written = scnprintf(p, remaining,
-                          "fh command q: %u waiting, %u free of %u:\n",
-                          CSR_WIFI_HIP_Q_SLOTS_USED(&card->fh_command_queue),
-                          CSR_WIFI_HIP_Q_SLOTS_FREE(&card->fh_command_queue),
-                          UNIFI_SOFT_COMMAND_Q_LENGTH);
-    UNIFI_SNPRINTF_RET(p, remaining, written);
-    for (i = 0; i < UNIFI_NO_OF_TX_QS; i++)
-    {
-        written = scnprintf(p, remaining,
-                              "fh traffic q[%u]: %u waiting, %u free of %u:\n",
-                              i,
-                              CSR_WIFI_HIP_Q_SLOTS_USED(&card->fh_traffic_queue[i]),
-                              CSR_WIFI_HIP_Q_SLOTS_FREE(&card->fh_traffic_queue[i]),
-                              UNIFI_SOFT_TRAFFIC_Q_LENGTH);
-        UNIFI_SNPRINTF_RET(p, remaining, written);
-    }
+	for (i = 0; i < UNIFI_NO_OF_TX_QS; i++)
+		seq_printf(m, "fh traffic q[%u]: %u waiting, %u free of %u:\n",
+			   i,
+			   CSR_WIFI_HIP_Q_SLOTS_USED(&card->fh_traffic_queue[i]),
+			   CSR_WIFI_HIP_Q_SLOTS_FREE(&card->fh_traffic_queue[i]),
+			   UNIFI_SOFT_TRAFFIC_Q_LENGTH);
 
-    written = scnprintf(p, remaining, "fh data slots free: %u\n",
-                          card->from_host_data?CardGetFreeFromHostDataSlots(card) : 0);
-    UNIFI_SNPRINTF_RET(p, remaining, written);
+	seq_printf(m, "fh data slots free: %u\n",
+		   card->from_host_data ? CardGetFreeFromHostDataSlots(card) : 0);
 
+	seq_puts(m, "From host data slots:");
+	n = card->config_data.num_fromhost_data_slots;
+	for (i = 0; i < n && card->from_host_data; i++)
+		seq_printf(m, " %hu", (u16)card->from_host_data[i].bd.data_length);
+	seq_putc(m, '\n');
 
-    written = scnprintf(p, remaining, "From host data slots:");
-    UNIFI_SNPRINTF_RET(p, remaining, written);
-    n = card->config_data.num_fromhost_data_slots;
-    for (i = 0; i < n && card->from_host_data; i++)
-    {
-        written = scnprintf(p, remaining, " %u",
-                              (u16)card->from_host_data[i].bd.data_length);
-        UNIFI_SNPRINTF_RET(p, remaining, written);
-    }
-    written = scnprintf(p, remaining, "\n");
-    UNIFI_SNPRINTF_RET(p, remaining, written);
+	seq_puts(m, "To host data slots:");
+	n = card->config_data.num_tohost_data_slots;
+	for (i = 0; i < n && card->to_host_data; i++)
+		seq_printf(m, " %hu", (u16)card->to_host_data[i].data_length);
+	seq_putc(m, '\n');
 
-    written = scnprintf(p, remaining, "To host data slots:");
-    UNIFI_SNPRINTF_RET(p, remaining, written);
-    n = card->config_data.num_tohost_data_slots;
-    for (i = 0; i < n && card->to_host_data; i++)
-    {
-        written = scnprintf(p, remaining, " %u",
-                              (u16)card->to_host_data[i].data_length);
-        UNIFI_SNPRINTF_RET(p, remaining, written);
-    }
+	unifi_print_unsafe_sdio_status(card, m);
 
-    written = scnprintf(p, remaining, "\n");
-    UNIFI_SNPRINTF_RET(p, remaining, written);
+	seq_puts(m, "\nStats:\n");
+	seq_printf(m, "Total SDIO bytes: R=%u W=%u\n",
+		   card->sdio_bytes_read, card->sdio_bytes_written);
 
-#ifdef CSR_UNSAFE_SDIO_ACCESS
-    written = scnprintf(p, remaining, "Host State: %s\n", states[card->host_state]);
-    UNIFI_SNPRINTF_RET(p, remaining, written);
-
-    r = unifi_check_io_status(card, &iostate);
-    if (iostate == 1)
-    {
-        written = scnprintf(p, remaining, "I/O Check: F1 disabled\n");
-        UNIFI_SNPRINTF_RET(p, remaining, written);
-    }
-    else
-    {
-        if (iostate == 1)
-        {
-            written = scnprintf(p, remaining, "I/O Check: pending interrupt\n");
-            UNIFI_SNPRINTF_RET(p, remaining, written);
-        }
-
-        written = scnprintf(p, remaining, "BH reason interrupt = %d\n",
-                              card->bh_reason_unifi);
-        UNIFI_SNPRINTF_RET(p, remaining, written);
-        written = scnprintf(p, remaining, "BH reason host      = %d\n",
-                              card->bh_reason_host);
-        UNIFI_SNPRINTF_RET(p, remaining, written);
-
-        for (i = 0; i < SHARED_READ_RETRY_LIMIT; i++)
-        {
-            r = unifi_read_8_or_16(card, card->sdio_ctrl_addr + 2, &b);
-            if ((r == CSR_RESULT_SUCCESS) && (!(b & 0x80)))
-            {
-                written = scnprintf(p, remaining, "fhsr: %u (driver thinks is %u)\n",
-                                      b, card->from_host_signals_r);
-                UNIFI_SNPRINTF_RET(p, remaining, written);
-                break;
-            }
-        }
-        iostate = unifi_read_shared_count(card, card->sdio_ctrl_addr + 4);
-        written = scnprintf(p, remaining, "thsw: %u (driver thinks is %u)\n",
-                              iostate, card->to_host_signals_w);
-        UNIFI_SNPRINTF_RET(p, remaining, written);
-    }
-#endif
-
-    written = scnprintf(p, remaining, "\nStats:\n");
-    UNIFI_SNPRINTF_RET(p, remaining, written);
-    written = scnprintf(p, remaining, "Total SDIO bytes: R=%u W=%u\n",
-                          card->sdio_bytes_read, card->sdio_bytes_written);
-
-    UNIFI_SNPRINTF_RET(p, remaining, written);
-    written = scnprintf(p, remaining, "Interrupts generated on card: %u\n",
-                          card->unifi_interrupt_seq);
-    UNIFI_SNPRINTF_RET(p, remaining, written);
-
-    *remain = remaining;
-    return (p - str);
-} /* unifi_print_status() */
-
-
+	seq_printf(m, "Interrupts generated on card: %u\n", card->unifi_interrupt_seq);
+	return 0;
+}
diff --git a/drivers/staging/csr/csr_wifi_hip_unifi_udi.h b/drivers/staging/csr/csr_wifi_hip_unifi_udi.h
index 9d85cfd..4126e85 100644
--- a/drivers/staging/csr/csr_wifi_hip_unifi_udi.h
+++ b/drivers/staging/csr/csr_wifi_hip_unifi_udi.h
@@ -47,21 +47,6 @@
  * This is used in the linux /proc interface and might be useful
  * in other systems.
  */
-s32 unifi_print_status(card_t *card, char *str, s32 *remain);
-
-#define UNIFI_SNPRINTF_RET(buf_p, remain, written)                  \
-    do {                                                            \
-        if (written >= remain) {                                    \
-            if (remain >= 2) {                                      \
-                buf_p[remain - 2] = '\n';                           \
-                buf_p[remain - 1] = 0;                              \
-            }                                                       \
-            buf_p += remain;                                        \
-            remain = 0;                                             \
-        } else if (written > 0) {                                   \
-            buf_p += written;                                       \
-            remain -= written;                                      \
-        }                                                           \
-    } while (0)
+s32 unifi_print_status(card_t *card, struct seq_file *m);
 
 #endif /* __CSR_WIFI_HIP_UNIFI_UDI_H__ */
diff --git a/drivers/staging/csr/drv.c b/drivers/staging/csr/drv.c
index 5520d65..bdc2523 100644
--- a/drivers/staging/csr/drv.c
+++ b/drivers/staging/csr/drv.c
@@ -1941,7 +1941,7 @@
  *
  ****************************************************************************
  */
-static struct file_operations unifi_fops = {
+static const struct file_operations unifi_fops = {
     .owner      = THIS_MODULE,
     .open       = unifi_open,
     .release    = unifi_release,
@@ -2041,7 +2041,7 @@
  * ----------------------------------------------------------------
  */
 static int
-uf_create_debug_device(struct file_operations *fops)
+uf_create_debug_device(const struct file_operations *fops)
 {
     int ret;
 
diff --git a/drivers/staging/csr/io.c b/drivers/staging/csr/io.c
index af9c28f..f9b5c22 100644
--- a/drivers/staging/csr/io.c
+++ b/drivers/staging/csr/io.c
@@ -31,6 +31,7 @@
  * ---------------------------------------------------------------------------
  */
 #include <linux/proc_fs.h>
+#include <linux/seq_file.h>
 
 #include "csr_wifi_hip_unifi.h"
 #include "csr_wifi_hip_unifiversion.h"
@@ -76,9 +77,28 @@
  */
 DECLARE_WAIT_QUEUE_HEAD(Unifi_cleanup_wq);
 
+#ifdef CONFIG_PROC_FS
+/*
+ * seq_file wrappers for procfile show routines.
+ */
+static int uf_proc_show(struct seq_file *m, void *v);
 
-static int uf_read_proc(char *page, char **start, off_t offset, int count,
-                        int *eof, void *data);
+#define UNIFI_DEBUG_TXT_BUFFER (8 * 1024)
+
+static int uf_proc_open(struct inode *inode, struct file *file)
+{
+	return single_open_size(file, uf_proc_show, PDE_DATA(inode),
+				UNIFI_DEBUG_TXT_BUFFER);
+}
+
+static const struct file_operations uf_proc_fops = {
+	.open		= uf_proc_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= seq_release,
+};
+
+#endif /* CONFIG_PROC_FS */
 
 #ifdef CSR_WIFI_RX_PATH_SPLIT
 
@@ -327,8 +347,8 @@
      * The following complex casting is in place in order to eliminate 64-bit compilation warning
      * "cast to/from pointer from/to integer of different size"
      */
-    if (!create_proc_read_entry(priv->proc_entry_name, 0, 0,
-                uf_read_proc, (void *)(long)priv->instance))
+    if (!proc_create_data(priv->proc_entry_name, 0, NULL,
+			  &uf_proc_fops, (void *)(long)priv->instance))
     {
         unifi_error(priv, "unifi: can't create /proc/driver/unifi\n");
     }
@@ -827,7 +847,7 @@
 
 /*
  * ---------------------------------------------------------------------------
- *  uf_read_proc
+ *  uf_proc_show
  *
  *      Read method for driver node in /proc/driver/unifi0
  *
@@ -844,107 +864,54 @@
  * ---------------------------------------------------------------------------
  */
 #ifdef CONFIG_PROC_FS
-static int
-uf_read_proc(char *page, char **start, off_t offset, int count,
-        int *eof, void *data)
+static int uf_proc_show(struct seq_file *m, void *v)
 {
-#define UNIFI_DEBUG_TXT_BUFFER 8*1024
-    unifi_priv_t *priv;
-    int actual_amount_to_copy;
-    char *p, *orig_p;
-    s32 remain = UNIFI_DEBUG_TXT_BUFFER;
-    s32 written;
-    int i;
+	unifi_priv_t *priv;
+	int i;
 
-    /*
-    * The following complex casting is in place in order to eliminate 64-bit compilation warning
-    * "cast to/from pointer from/to integer of different size"
-    */
-    priv = uf_find_instance((int)(long)data);
-    if (!priv) {
-        return 0;
-    }
+	/*
+	 * The following complex casting is in place in order to eliminate
+	 * 64-bit compilation warning "cast to/from pointer from/to integer of
+	 * different size"
+	 */
+	priv = uf_find_instance((long)m->private);
+	if (!priv)
+		return 0;
 
-    p = kmalloc( UNIFI_DEBUG_TXT_BUFFER, GFP_KERNEL );
-
-    orig_p = p;
-
-    written = scnprintf(p, remain, "UniFi SDIO Driver: %s %s %s\n",
-            CSR_WIFI_VERSION, __DATE__, __TIME__);
-    UNIFI_SNPRINTF_RET(p, remain, written);
+	seq_printf(m, "UniFi SDIO Driver: %s %s %s\n",
+		   CSR_WIFI_VERSION, __DATE__, __TIME__);
 #ifdef CSR_SME_USERSPACE
-    written = scnprintf(p, remain, "SME: CSR userspace ");
-    UNIFI_SNPRINTF_RET(p, remain, written);
+	seq_puts(m, "SME: CSR userspace ");
 #ifdef CSR_SUPPORT_WEXT
-    written = scnprintf(p, remain, "with WEXT support\n");
+	seq_puts(m, "with WEXT support\n");
 #else
-    written = scnprintf(p, remain, "\n");
+	seq_putc(m, '\n');
 #endif /* CSR_SUPPORT_WEXT */
-    UNIFI_SNPRINTF_RET(p, remain, written);
 #endif /* CSR_SME_USERSPACE */
 #ifdef CSR_NATIVE_LINUX
-    written = scnprintf(p, remain, "SME: native\n");
-    UNIFI_SNPRINTF_RET(p, remain, written);
+	seq_puts(m, "SME: native\n");
 #endif
 
 #ifdef CSR_SUPPORT_SME
-    written = scnprintf(p, remain,
-            "Firmware (ROM) build:%u, Patch:%u\n",
-            priv->card_info.fw_build,
-            priv->sme_versions.firmwarePatch);
-    UNIFI_SNPRINTF_RET(p, remain, written);
+	seq_printf(m, "Firmware (ROM) build:%u, Patch:%u\n",
+		   priv->card_info.fw_build,
+		   priv->sme_versions.firmwarePatch);
 #endif
-    p += unifi_print_status(priv->card, p, &remain);
 
-    written = scnprintf(p, remain, "Last dbg str: %s\n",
-            priv->last_debug_string);
-    UNIFI_SNPRINTF_RET(p, remain, written);
+	unifi_print_status(priv->card, m);
 
-    written = scnprintf(p, remain, "Last dbg16:");
-    UNIFI_SNPRINTF_RET(p, remain, written);
-    for (i = 0; i < 8; i++) {
-        written = scnprintf(p, remain, " %04X",
-                priv->last_debug_word16[i]);
-        UNIFI_SNPRINTF_RET(p, remain, written);
-    }
-    written = scnprintf(p, remain, "\n");
-    UNIFI_SNPRINTF_RET(p, remain, written);
-    written = scnprintf(p, remain, "           ");
-    UNIFI_SNPRINTF_RET(p, remain, written);
-    for (; i < 16; i++) {
-        written = scnprintf(p, remain, " %04X",
-                priv->last_debug_word16[i]);
-        UNIFI_SNPRINTF_RET(p, remain, written);
-    }
-    written = scnprintf(p, remain, "\n");
-    UNIFI_SNPRINTF_RET(p, remain, written);
-    *start = page;
+	seq_printf(m, "Last dbg str: %s\n", priv->last_debug_string);
 
-    written = UNIFI_DEBUG_TXT_BUFFER - remain;
-
-    if( offset >= written )
-    {
-        *eof = 1;
-        kfree( orig_p );
-        return(0);
-    }
-
-    if( offset + count > written )
-    {
-        actual_amount_to_copy = written - offset;
-        *eof = 1;
-    }
-    else
-    {
-        actual_amount_to_copy = count;
-    }
-
-    memcpy( page, &(orig_p[offset]), actual_amount_to_copy );
-
-    kfree( orig_p );
-
-    return( actual_amount_to_copy );
-} /* uf_read_proc() */
+	seq_puts(m, "Last dbg16:");
+	for (i = 0; i < 8; i++)
+		seq_printf(m, " %04X", priv->last_debug_word16[i]);
+	seq_putc(m, '\n');
+	seq_puts(m, "           ");
+	for (; i < 16; i++)
+		seq_printf(m, " %04X", priv->last_debug_word16[i]);
+	seq_putc(m, '\n');
+	return 0;
+}
 #endif
 
 
diff --git a/drivers/staging/cxt1e1/Makefile b/drivers/staging/cxt1e1/Makefile
index e99b823..b9ccb76 100644
--- a/drivers/staging/cxt1e1/Makefile
+++ b/drivers/staging/cxt1e1/Makefile
@@ -12,8 +12,9 @@
   linux.o 		\
   functions.o 		\
   hwprobe.o 		\
-  sbeproc.o 		\
   pmc93x6_eeprom.o 	\
   sbecrc.o 		\
   comet_tables.o 	\
   sbeid.o
+
+cxt1e1-$(CONFIG_PROC_FS) += sbeproc.o
diff --git a/drivers/staging/cxt1e1/sbeproc.c b/drivers/staging/cxt1e1/sbeproc.c
index f42531c..49f10f0 100644
--- a/drivers/staging/cxt1e1/sbeproc.c
+++ b/drivers/staging/cxt1e1/sbeproc.c
@@ -19,6 +19,7 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/proc_fs.h>
+#include <linux/seq_file.h>
 #include <linux/sched.h>
 #include <asm/uaccess.h>
 #include "pmcc4_sysdep.h"
@@ -26,332 +27,193 @@
 #include "pmcc4_private.h"
 #include "sbeproc.h"
 
-/* forwards */
-void        sbecom_get_brdinfo (ci_t *, struct sbe_brd_info *, u_int8_t *);
+extern void sbecom_get_brdinfo(ci_t *, struct sbe_brd_info *, u_int8_t *);
 extern struct s_hdw_info hdw_info[MAX_BOARDS];
 
-#ifdef CONFIG_PROC_FS
-
-/********************************************************************/
-/* procfs stuff                                                     */
-/********************************************************************/
-
-
-void
-sbecom_proc_brd_cleanup (ci_t * ci)
+void sbecom_proc_brd_cleanup(ci_t *ci)
 {
-    if (ci->dir_dev)
-    {
-	char dir[7 + SBE_IFACETMPL_SIZE + 1];
-	snprintf(dir, sizeof(dir), "driver/%s", ci->devname);
-        remove_proc_entry("info", ci->dir_dev);
-        remove_proc_entry(dir, NULL);
-        ci->dir_dev = NULL;
-    }
+	if (ci->dir_dev) {
+		char dir[7 + SBE_IFACETMPL_SIZE + 1];
+		snprintf(dir, sizeof(dir), "driver/%s", ci->devname);
+		remove_proc_entry("info", ci->dir_dev);
+		remove_proc_entry(dir, NULL);
+		ci->dir_dev = NULL;
+	}
 }
 
-
-static int
-sbecom_proc_get_sbe_info (char *buffer, char **start, off_t offset,
-                          int length, int *eof, void *priv)
+static void sbecom_proc_get_brdinfo(ci_t *ci, struct sbe_brd_info *bip)
 {
-    ci_t       *ci = (ci_t *) priv;
-    int         len = 0;
-    char       *spd;
-    struct sbe_brd_info *bip;
+	hdw_info_t *hi = &hdw_info[ci->brdno];
+	u_int8_t *bsn = 0;
 
-    if (!(bip = OS_kmalloc (sizeof (struct sbe_brd_info))))
-    {
-        return -ENOMEM;
-    }
-#if 0
-    /** RLD DEBUG **/
-    pr_info(">> sbecom_proc_get_sbe_info: entered, offset %d. length %d.\n",
-            (int) offset, (int) length);
-#endif
+	switch (hi->promfmt)
+	{
+	case PROM_FORMAT_TYPE1:
+		bsn = (u_int8_t *) hi->mfg_info.pft1.Serial;
+		break;
+	case PROM_FORMAT_TYPE2:
+		bsn = (u_int8_t *) hi->mfg_info.pft2.Serial;
+		break;
+	}
 
-    {
-        hdw_info_t *hi = &hdw_info[ci->brdno];
+	sbecom_get_brdinfo (ci, bip, bsn);
 
-        u_int8_t *bsn = 0;
+	pr_devel(">> sbecom_get_brdinfo: returned, first_if %p <%s> last_if %p <%s>\n",
+		 bip->first_iname, bip->first_iname,
+		 bip->last_iname, bip->last_iname);
+}
 
-        switch (hi->promfmt)
-        {
-        case PROM_FORMAT_TYPE1:
-            bsn = (u_int8_t *) hi->mfg_info.pft1.Serial;
-            break;
-        case PROM_FORMAT_TYPE2:
-            bsn = (u_int8_t *) hi->mfg_info.pft2.Serial;
-            break;
-        }
+/*
+ * Describe the driver state through /proc
+ */
+static int sbecom_proc_get_sbe_info(struct seq_file *m, void *v)
+{
+	ci_t       *ci = m->private;
+	char       *spd;
+	struct sbe_brd_info *bip;
 
-        sbecom_get_brdinfo (ci, bip, bsn);
-    }
+	if (!(bip = OS_kmalloc(sizeof(struct sbe_brd_info))))
+		return -ENOMEM;
 
-#if 0
-    /** RLD DEBUG **/
-    pr_info(">> sbecom_get_brdinfo: returned, first_if %p <%s> last_if %p <%s>\n",
-            (char *) &bip->first_iname, (char *) &bip->first_iname,
-            (char *) &bip->last_iname, (char *) &bip->last_iname);
-#endif
-    len += sprintf (buffer + len, "Board Type:    ");
-    switch (bip->brd_id)
-    {
-    case SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPMC_C1T3):
-        len += sprintf (buffer + len, "wanPMC-C1T3");
-        break;
-    case SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPTMC_256T3_E1):
-        len += sprintf (buffer + len, "wanPTMC-256T3 <E1>");
-        break;
-    case SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPTMC_256T3_T1):
-        len += sprintf (buffer + len, "wanPTMC-256T3 <T1>");
-        break;
-    case SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPTMC_C24TE1):
-        len += sprintf (buffer + len, "wanPTMC-C24TE1");
-        break;
+	pr_devel(">> sbecom_proc_get_sbe_info: entered\n");
 
-    case SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPMC_C4T1E1):
-    case SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPMC_C4T1E1_L):
-        len += sprintf (buffer + len, "wanPMC-C4T1E1");
-        break;
-    case SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPMC_C2T1E1):
-    case SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPMC_C2T1E1_L):
-        len += sprintf (buffer + len, "wanPMC-C2T1E1");
-        break;
-    case SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPMC_C1T1E1):
-    case SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPMC_C1T1E1_L):
-        len += sprintf (buffer + len, "wanPMC-C1T1E1");
-        break;
+	sbecom_proc_get_brdinfo(ci, bip);
 
-    case SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPCI_C4T1E1):
-        len += sprintf (buffer + len, "wanPCI-C4T1E1");
-        break;
-    case SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPCI_C2T1E1):
-        len += sprintf (buffer + len, "wanPCI-C2T1E1");
-        break;
-    case SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPCI_C1T1E1):
-        len += sprintf (buffer + len, "wanPCI-C1T1E1");
-        break;
+	seq_puts(m, "Board Type:    ");
+	switch (bip->brd_id) {
+	case SBE_BOARD_ID(PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPMC_C1T3):
+		seq_puts(m, "wanPMC-C1T3");
+		break;
+	case SBE_BOARD_ID(PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPTMC_256T3_E1):
+		seq_puts(m, "wanPTMC-256T3 <E1>");
+		break;
+	case SBE_BOARD_ID(PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPTMC_256T3_T1):
+		seq_puts(m, "wanPTMC-256T3 <T1>");
+		break;
+	case SBE_BOARD_ID(PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPTMC_C24TE1):
+		seq_puts(m, "wanPTMC-C24TE1");
+		break;
 
-    default:
-        len += sprintf (buffer + len, "unknown");
-        break;
-    }
-    len += sprintf (buffer + len, "  [%08X]\n", bip->brd_id);
+	case SBE_BOARD_ID(PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPMC_C4T1E1):
+	case SBE_BOARD_ID(PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPMC_C4T1E1_L):
+		seq_puts(m, "wanPMC-C4T1E1");
+		break;
+	case SBE_BOARD_ID(PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPMC_C2T1E1):
+	case SBE_BOARD_ID(PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPMC_C2T1E1_L):
+		seq_puts(m, "wanPMC-C2T1E1");
+		break;
+	case SBE_BOARD_ID(PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPMC_C1T1E1):
+	case SBE_BOARD_ID(PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPMC_C1T1E1_L):
+		seq_puts(m, "wanPMC-C1T1E1");
+		break;
 
-    len += sprintf (buffer + len, "Board Number:  %d\n", bip->brdno);
-    len += sprintf (buffer + len, "Hardware ID:   0x%02X\n", ci->hdw_bid);
-    len += sprintf (buffer + len, "Board SN:      %06X\n", bip->brd_sn);
-	len += sprintf(buffer + len, "Board MAC:     %pMF\n",
-		bip->brd_mac_addr);
-    len += sprintf (buffer + len, "Ports:         %d\n", ci->max_port);
-    len += sprintf (buffer + len, "Channels:      %d\n", bip->brd_chan_cnt);
+	case SBE_BOARD_ID(PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPCI_C4T1E1):
+		seq_puts(m, "wanPCI-C4T1E1");
+		break;
+	case SBE_BOARD_ID(PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPCI_C2T1E1):
+		seq_puts(m, "wanPCI-C2T1E1");
+		break;
+	case SBE_BOARD_ID(PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPCI_C1T1E1):
+		seq_puts(m, "wanPCI-C1T1E1");
+		break;
+
+	default:
+		seq_puts(m, "unknown");
+		break;
+	}
+
+	seq_printf(m, "  [%08X]\n", bip->brd_id);
+
+	seq_printf(m, "Board Number:  %d\n", bip->brdno);
+	seq_printf(m, "Hardware ID:   0x%02X\n", ci->hdw_bid);
+	seq_printf(m, "Board SN:      %06X\n", bip->brd_sn);
+	seq_printf(m, "Board MAC:     %pMF\n", bip->brd_mac_addr);
+	seq_printf(m, "Ports:         %d\n", ci->max_port);
+	seq_printf(m, "Channels:      %d\n", bip->brd_chan_cnt);
 #if 1
-    len += sprintf (buffer + len, "Interface:     %s -> %s\n",
-                    (char *) &bip->first_iname, (char *) &bip->last_iname);
+	seq_printf(m, "Interface:     %s -> %s\n",
+		   bip->first_iname, bip->last_iname);
 #else
-    len += sprintf (buffer + len, "Interface:     <not available> 1st %p lst %p\n",
-                    (char *) &bip->first_iname, (char *) &bip->last_iname);
+	seq_printf(m, "Interface:     <not available> 1st %p lst %p\n",
+		   bip->first_iname, bip->last_iname);
 #endif
 
-    switch (bip->brd_pci_speed)
-    {
-    case BINFO_PCI_SPEED_33:
-        spd = "33Mhz";
-        break;
-    case BINFO_PCI_SPEED_66:
-        spd = "66Mhz";
-        break;
-    default:
-        spd = "<not available>";
-        break;
-    }
-    len += sprintf (buffer + len, "PCI Bus Speed: %s\n", spd);
-    len += sprintf (buffer + len, "Release:       %s\n", ci->release);
+	switch (bip->brd_pci_speed) {
+	case BINFO_PCI_SPEED_33:
+		spd = "33Mhz";
+		break;
+	case BINFO_PCI_SPEED_66:
+		spd = "66Mhz";
+		break;
+	default:
+		spd = "<not available>";
+		break;
+	}
+	seq_printf(m, "PCI Bus Speed: %s\n", spd);
+	seq_printf(m, "Release:       %s\n", ci->release);
 
 #ifdef SBE_PMCC4_ENABLE
-    {
-               extern int cxt1e1_max_mru;
+	{
+		extern int cxt1e1_max_mru;
 #if 0
-        extern int max_chans_used;
-        extern int cxt1e1_max_mtu;
+		extern int max_chans_used;
+		extern int cxt1e1_max_mtu;
 #endif
-        extern int max_rxdesc_used, max_txdesc_used;
+		extern int max_rxdesc_used, max_txdesc_used;
 
-        len += sprintf (buffer + len, "\ncxt1e1_max_mru:         %d\n", cxt1e1_max_mru);
+		seq_printf(m, "\ncxt1e1_max_mru:         %d\n", cxt1e1_max_mru);
 #if 0
-        len += sprintf (buffer + len, "\nmax_chans_used:  %d\n", max_chans_used);
-        len += sprintf (buffer + len, "cxt1e1_max_mtu:         %d\n", cxt1e1_max_mtu);
+		seq_printf(m, "\nmax_chans_used:  %d\n", max_chans_used);
+		seq_printf(m, "cxt1e1_max_mtu:         %d\n", cxt1e1_max_mtu);
 #endif
-        len += sprintf (buffer + len, "max_rxdesc_used: %d\n", max_rxdesc_used);
-        len += sprintf (buffer + len, "max_txdesc_used: %d\n", max_txdesc_used);
-    }
+		seq_printf(m, "max_rxdesc_used: %d\n", max_rxdesc_used);
+		seq_printf(m, "max_txdesc_used: %d\n", max_txdesc_used);
+	}
 #endif
 
-    OS_kfree (bip);                 /* cleanup */
+	kfree(bip);
 
-    /***
-     * How to be a proc read function
-     * ------------------------------
-     * Prototype:
-     *    int f(char *buffer, char **start, off_t offset,
-     *          int count, int *peof, void *dat)
-     *
-     * Assume that the buffer is "count" bytes in size.
-     *
-     * If you know you have supplied all the data you
-     * have, set *peof.
-     *
-     * You have three ways to return data:
-     * 0) Leave *start = NULL.  (This is the default.)
-     *    Put the data of the requested offset at that
-     *    offset within the buffer.  Return the number (n)
-     *    of bytes there are from the beginning of the
-     *    buffer up to the last byte of data.  If the
-     *    number of supplied bytes (= n - offset) is
-     *    greater than zero and you didn't signal eof
-     *    and the reader is prepared to take more data
-     *    you will be called again with the requested
-     *    offset advanced by the number of bytes
-     *    absorbed.  This interface is useful for files
-     *    no larger than the buffer.
-     * 1) Set *start = an unsigned long value less than
-     *    the buffer address but greater than zero.
-     *    Put the data of the requested offset at the
-     *    beginning of the buffer.  Return the number of
-     *    bytes of data placed there.  If this number is
-     *    greater than zero and you didn't signal eof
-     *    and the reader is prepared to take more data
-     *    you will be called again with the requested
-     *    offset advanced by *start.  This interface is
-     *    useful when you have a large file consisting
-     *    of a series of blocks which you want to count
-     *    and return as wholes.
-     *    (Hack by Paul.Russell@rustcorp.com.au)
-     * 2) Set *start = an address within the buffer.
-     *    Put the data of the requested offset at *start.
-     *    Return the number of bytes of data placed there.
-     *    If this number is greater than zero and you
-     *    didn't signal eof and the reader is prepared to
-     *    take more data you will be called again with the
-     *    requested offset advanced by the number of bytes
-     *    absorbed.
-     */
-
-#if 1
-    /* #4 - interpretation of above = set EOF, return len */
-    *eof = 1;
-#endif
-
-#if 0
-    /*
-     * #1 - from net/wireless/atmel.c RLD NOTE -there's something wrong with
-     * this plagarized code which results in this routine being called TWICE.
-     * The second call returns ZERO, resulting in hidden failure, but at
-     * least only a single message set is being displayed.
-     */
-    if (len <= offset + length)
-        *eof = 1;
-    *start = buffer + offset;
-    len -= offset;
-    if (len > length)
-        len = length;
-    if (len < 0)
-        len = 0;
-#endif
-
-#if 0                               /* #2 from net/tokenring/olympic.c +
-                                     * lanstreamer.c */
-    {
-        off_t       begin = 0;
-        int         size = 0;
-        off_t       pos = 0;
-
-        size = len;
-        pos = begin + size;
-        if (pos < offset)
-        {
-            len = 0;
-            begin = pos;
-        }
-        *start = buffer + (offset - begin);     /* Start of wanted data */
-        len -= (offset - begin);    /* Start slop */
-        if (len > length)
-            len = length;           /* Ending slop */
-    }
-#endif
-
-#if 0                               /* #3 from
-                                     * char/ftape/lowlevel/ftape-proc.c */
-    len = strlen (buffer);
-    *start = NULL;
-    if (offset + length >= len)
-        *eof = 1;
-    else
-        *eof = 0;
-#endif
-
-#if 0
-    pr_info(">> proc_fs: returned len = %d., start %p\n", len, start);  /* RLD DEBUG */
-#endif
-
-/***
-   using NONE: returns = 314.314.314.
-   using #1  : returns = 314, 0.
-   using #2  : returns = 314, 0, 0.
-   using #3  : returns = 314, 314.
-   using #4  : returns = 314, 314.
-***/
-
-    return len;
+	pr_devel(">> proc_fs: finished\n");
+	return 0;
 }
 
-/* initialize the /proc subsystem for the specific SBE driver */
-
-int         __init
-sbecom_proc_brd_init (ci_t * ci)
+/*
+ * seq_file wrappers for procfile show routines.
+ */
+static int sbecom_proc_open(struct inode *inode, struct file *file)
 {
-    struct proc_dir_entry *e;
-    char dir[7 + SBE_IFACETMPL_SIZE + 1];
+	return single_open(file, sbecom_proc_get_sbe_info, PDE_DATA(inode));
+}
 
-    /* create a directory in the root procfs */
-    snprintf(dir, sizeof(dir), "driver/%s", ci->devname);
-    ci->dir_dev = proc_mkdir(dir, NULL);
-    if (!ci->dir_dev)
-    {
-        pr_err("Unable to create directory /proc/driver/%s\n", ci->devname);
-        goto fail;
-    }
-    e = create_proc_read_entry ("info", S_IFREG | S_IRUGO,
-                                ci->dir_dev, sbecom_proc_get_sbe_info, ci);
-    if (!e)
-    {
-        pr_err("Unable to create entry /proc/driver/%s/info\n", ci->devname);
-        goto fail;
-    }
-    return 0;
+static const struct file_operations sbecom_proc_fops = {
+	.open		= sbecom_proc_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= seq_release,
+};
+
+/*
+ * Initialize the /proc subsystem for the specific SBE driver
+ */
+int __init sbecom_proc_brd_init(ci_t *ci)
+{
+	char dir[7 + SBE_IFACETMPL_SIZE + 1];
+
+	snprintf(dir, sizeof(dir), "driver/%s", ci->devname);
+	ci->dir_dev = proc_mkdir(dir, NULL);
+	if (!ci->dir_dev) {
+		pr_err("Unable to create directory /proc/driver/%s\n", ci->devname);
+		goto fail;
+	}
+
+	if (!proc_create_data("info", S_IFREG | S_IRUGO, ci->dir_dev,
+			      &sbecom_proc_fops, ci)) {
+		pr_err("Unable to create entry /proc/driver/%s/info\n", ci->devname);
+		goto fail;
+	}
+	return 0;
 
 fail:
-    sbecom_proc_brd_cleanup (ci);
-    return 1;
+	sbecom_proc_brd_cleanup(ci);
+	return 1;
 }
-
-#else                           /*** ! CONFIG_PROC_FS ***/
-
-/* stubbed off dummy routines */
-
-void
-sbecom_proc_brd_cleanup (ci_t * ci)
-{
-}
-
-int         __init
-sbecom_proc_brd_init (ci_t * ci)
-{
-    return 0;
-}
-
-#endif                          /*** CONFIG_PROC_FS ***/
-
-
-/*** End-of-File ***/
diff --git a/drivers/staging/cxt1e1/sbeproc.h b/drivers/staging/cxt1e1/sbeproc.h
index e82be6a..e5c072c 100644
--- a/drivers/staging/cxt1e1/sbeproc.h
+++ b/drivers/staging/cxt1e1/sbeproc.h
@@ -23,10 +23,20 @@
 
 
 #ifdef CONFIG_PROC_FS
-#ifdef __KERNEL__
 void        sbecom_proc_brd_cleanup (ci_t *);
 int __init  sbecom_proc_brd_init (ci_t *);
 
-#endif                          /*** __KERNEL__ ***/
+#else
+
+static inline void sbecom_proc_brd_cleanup(ci_t * ci)
+{
+}
+
+static inline int __init sbecom_proc_brd_init(ci_t * ci)
+{
+	return 0;
+}
+
 #endif                          /*** CONFIG_PROC_FS ***/
+
 #endif                          /*** _INC_SBEPROC_H_ ***/
diff --git a/drivers/staging/dgrp/dgrp_common.c b/drivers/staging/dgrp/dgrp_common.c
index 3553998..9a9b456 100644
--- a/drivers/staging/dgrp/dgrp_common.c
+++ b/drivers/staging/dgrp/dgrp_common.c
@@ -167,34 +167,3 @@
 		ch->ch_flag &= ~CH_PHYS_CD;
 
 }
-
-/**
- * dgrp_chk_perm() -- check permissions for net device
- * @inode: pointer to inode structure for the net communication device
- * @op: operation to be tested
- *
- * The file permissions and ownerships are tested to determine whether
- * the operation "op" is permitted on the file pointed to by the inode.
- * Returns 0 if the operation is permitted, -EACCESS otherwise
- */
-int dgrp_chk_perm(int mode, int op)
-{
-	if (!uid_eq(GLOBAL_ROOT_UID, current_euid()))
-		mode >>= 6;
-	else if (in_egroup_p(GLOBAL_ROOT_GID))
-		mode >>= 3;
-
-	if ((mode & op & 0007) == op)
-		return 0;
-
-	if (capable(CAP_SYS_ADMIN))
-		return 0;
-
-	return -EACCES;
-}
-
-/* dgrp_chk_perm wrapper for permission call in struct inode_operations */
-int dgrp_inode_permission(struct inode *inode, int op)
-{
-	return dgrp_chk_perm(inode->i_mode, op);
-}
diff --git a/drivers/staging/dgrp/dgrp_common.h b/drivers/staging/dgrp/dgrp_common.h
index 2832b8e..23aba6c 100644
--- a/drivers/staging/dgrp/dgrp_common.h
+++ b/drivers/staging/dgrp/dgrp_common.h
@@ -49,20 +49,20 @@
 extern void dgrp_poll_handler(unsigned long arg);
 
 /* from dgrp_mon_ops.c */
-extern void dgrp_register_mon_hook(struct proc_dir_entry *de);
+extern const struct file_operations dgrp_mon_ops;
 
 /* from dgrp_tty.c */
 extern int dgrp_tty_init(struct nd_struct *nd);
 extern void dgrp_tty_uninit(struct nd_struct *nd);
 
 /* from dgrp_ports_ops.c */
-extern void dgrp_register_ports_hook(struct proc_dir_entry *de);
+extern const struct file_operations dgrp_ports_ops;
 
 /* from dgrp_net_ops.c */
-extern void dgrp_register_net_hook(struct proc_dir_entry *de);
+extern const struct file_operations dgrp_net_ops;
 
 /* from dgrp_dpa_ops.c */
-extern void dgrp_register_dpa_hook(struct proc_dir_entry *de);
+extern const struct file_operations dgrp_dpa_ops;
 extern void dgrp_dpa_data(struct nd_struct *, int, u8 *, int);
 
 /* from dgrp_sysfs.c */
@@ -76,61 +76,6 @@
 extern void dgrp_remove_tty_sysfs(struct device *c);
 
 /* from dgrp_specproc.c */
-/*
- *  The list of DGRP entries with r/w capabilities.  These
- *  magic numbers are used for identification purposes.
- */
-enum {
-	DGRP_CONFIG = 1,	/* Configure portservers */
-	DGRP_NETDIR = 2,	/* Directory for "net" devices */
-	DGRP_MONDIR = 3,	/* Directory for "mon" devices */
-	DGRP_PORTSDIR = 4,	/* Directory for "ports" devices */
-	DGRP_INFO = 5,		/* Get info. about the running module */
-	DGRP_NODEINFO = 6,	/* Get info. about the configured nodes */
-	DGRP_DPADIR = 7,	/* Directory for the "dpa" devices */
-};
-
-/*
- *  Directions for proc handlers
- */
-enum {
-	INBOUND = 1,		/* Data being written to kernel */
-	OUTBOUND = 2,		/* Data being read from the kernel */
-};
-
-/**
- * dgrp_proc_entry: structure for dgrp proc dirs
- * @id: ID number associated with this particular entry.  Should be
- *    unique across all of DGRP.
- * @name: text name associated with the /proc entry
- * @mode: file access permisssions for the /proc entry
- * @child: pointer to table describing a subdirectory for this entry
- * @de: pointer to directory entry for this object once registered.  Used
- *    to grab the handle of the object for unregistration
- * @excl_sem: semaphore to provide exclusive to struct
- * @excl_cnt: counter of current accesses
- *
- *  Each entry in a DGRP proc directory is described with a
- *  dgrp_proc_entry structure.  A collection of these
- *  entries (in an array) represents the members associated
- *  with a particular /proc directory, and is referred to
- *  as a table.  All tables are terminated by an entry with
- *  zeros for every member.
- */
-struct dgrp_proc_entry {
-	int                  id;          /* Integer identifier */
-	const char        *name;          /* ASCII identifier */
-	mode_t             mode;          /* File access permissions */
-	struct dgrp_proc_entry *child;    /* Child pointer */
-
-	/* file ops to use, pass NULL to use default */
-	struct file_operations *proc_file_ops;
-
-	struct proc_dir_entry *de;        /* proc entry pointer */
-	struct semaphore   excl_sem;      /* Protects exclusive access var */
-	int                excl_cnt;      /* Counts number of curr accesses */
-};
-
 extern void dgrp_unregister_proc(void);
 extern void dgrp_register_proc(void);
 
@@ -144,8 +89,6 @@
  *-----------------------------------------------------------------------*/
 
 void dgrp_carrier(struct ch_struct *ch);
-extern int dgrp_inode_permission(struct inode *inode, int op);
-extern int dgrp_chk_perm(int mode, int op);
 
 
 /*
diff --git a/drivers/staging/dgrp/dgrp_dpa_ops.c b/drivers/staging/dgrp/dgrp_dpa_ops.c
index ca10a33..114799c 100644
--- a/drivers/staging/dgrp/dgrp_dpa_ops.c
+++ b/drivers/staging/dgrp/dgrp_dpa_ops.c
@@ -40,6 +40,7 @@
 #include <linux/cred.h>
 #include <linux/sched.h>
 #include <linux/ratelimit.h>
+#include <linux/slab.h>
 #include <asm/unaligned.h>
 
 #include "dgrp_common.h"
@@ -52,7 +53,7 @@
 			   unsigned long arg);
 static unsigned int dgrp_dpa_select(struct file *, struct poll_table_struct *);
 
-static const struct file_operations dpa_ops = {
+const struct file_operations dgrp_dpa_ops = {
 	.owner   =  THIS_MODULE,
 	.read    =  dgrp_dpa_read,
 	.poll    =  dgrp_dpa_select,
@@ -61,12 +62,6 @@
 	.release =  dgrp_dpa_release,
 };
 
-static struct inode_operations dpa_inode_ops = {
-	.permission = dgrp_inode_permission
-};
-
-
-
 struct digi_node {
 	uint	nd_state;		/* Node state: 1 = up, 0 = down. */
 	uint	nd_chan_count;		/* Number of channels found */
@@ -111,17 +106,6 @@
 #define DIGI_SETDEBUG      (('d'<<8) | 247)	/* set debug info */
 
 
-void dgrp_register_dpa_hook(struct proc_dir_entry *de)
-{
-	struct nd_struct *node = de->data;
-
-	de->proc_iops = &dpa_inode_ops;
-	rcu_assign_pointer(de->proc_fops, &dpa_ops);
-
-	node->nd_dpa_de = de;
-	spin_lock_init(&node->nd_dpa_lock);
-}
-
 /*
  * dgrp_dpa_open -- open the DPA device for a particular PortServer
  */
@@ -130,8 +114,6 @@
 	struct nd_struct *nd;
 	int rtn = 0;
 
-	struct proc_dir_entry *de;
-
 	rtn = try_module_get(THIS_MODULE);
 	if (!rtn)
 		return -ENXIO;
@@ -154,12 +136,7 @@
 	/*
 	 *  Get the node pointer, and fail if it doesn't exist.
 	 */
-	de = PDE(inode);
-	if (!de) {
-		rtn = -ENXIO;
-		goto done;
-	}
-	nd = (struct nd_struct *)de->data;
+	nd = PDE_DATA(inode);
 	if (!nd) {
 		rtn = -ENXIO;
 		goto done;
diff --git a/drivers/staging/dgrp/dgrp_mon_ops.c b/drivers/staging/dgrp/dgrp_mon_ops.c
index b484fcc..d18be41 100644
--- a/drivers/staging/dgrp/dgrp_mon_ops.c
+++ b/drivers/staging/dgrp/dgrp_mon_ops.c
@@ -37,6 +37,7 @@
 #include <linux/tty.h>
 #include <linux/sched.h>
 #include <asm/unaligned.h>
+#include <linux/slab.h>
 #include <linux/proc_fs.h>
 #include <linux/uaccess.h>
 
@@ -49,7 +50,7 @@
 static long dgrp_mon_ioctl(struct file *file, unsigned int cmd,
 			   unsigned long arg);
 
-static const struct file_operations mon_ops = {
+const struct file_operations dgrp_mon_ops = {
 	.owner   = THIS_MODULE,
 	.read    = dgrp_mon_read,
 	.unlocked_ioctl = dgrp_mon_ioctl,
@@ -57,20 +58,6 @@
 	.release = dgrp_mon_release,
 };
 
-static struct inode_operations mon_inode_ops = {
-	.permission = dgrp_inode_permission
-};
-
-void dgrp_register_mon_hook(struct proc_dir_entry *de)
-{
-	struct nd_struct *node = de->data;
-
-	de->proc_iops = &mon_inode_ops;
-	rcu_assign_pointer(de->proc_fops, &mon_ops);
-	node->nd_mon_de = de;
-	sema_init(&node->nd_mon_semaphore, 1);
-}
-
 /**
  * dgrp_mon_open() -- open /proc/dgrp/ports device for a PortServer
  * @inode: struct inode *
@@ -81,7 +68,6 @@
 static int dgrp_mon_open(struct inode *inode, struct file *file)
 {
 	struct nd_struct *nd;
-	struct proc_dir_entry *de;
 	struct timeval tv;
 	uint32_t time;
 	u8 *buf;
@@ -109,13 +95,7 @@
 	/*
 	 *  Get the node pointer, and fail if it doesn't exist.
 	 */
-	de = PDE(inode);
-	if (!de) {
-		rtn = -ENXIO;
-		goto done;
-	}
-
-	nd = (struct nd_struct *)de->data;
+	nd = PDE_DATA(inode);
 	if (!nd) {
 		rtn = -ENXIO;
 		goto done;
diff --git a/drivers/staging/dgrp/dgrp_net_ops.c b/drivers/staging/dgrp/dgrp_net_ops.c
index 64f48ff..5b7833f 100644
--- a/drivers/staging/dgrp/dgrp_net_ops.c
+++ b/drivers/staging/dgrp/dgrp_net_ops.c
@@ -35,7 +35,7 @@
 
 #include <linux/module.h>
 #include <linux/proc_fs.h>
-#include <linux/types.h>
+#include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/device.h>
 #include <linux/tty.h>
@@ -72,7 +72,7 @@
 static unsigned int dgrp_net_select(struct file *file,
 				    struct poll_table_struct *table);
 
-static const struct file_operations net_ops = {
+const struct file_operations dgrp_net_ops = {
 	.owner   =  THIS_MODULE,
 	.read    =  dgrp_net_read,
 	.write   =  dgrp_net_write,
@@ -82,23 +82,6 @@
 	.release =  dgrp_net_release,
 };
 
-static struct inode_operations net_inode_ops = {
-	.permission = dgrp_inode_permission
-};
-
-void dgrp_register_net_hook(struct proc_dir_entry *de)
-{
-	struct nd_struct *node = de->data;
-
-	de->proc_iops = &net_inode_ops;
-	rcu_assign_pointer(de->proc_fops, &net_ops);
-	node->nd_net_de = de;
-	sema_init(&node->nd_net_semaphore, 1);
-	node->nd_state = NS_CLOSED;
-	dgrp_create_node_class_sysfs_files(node);
-}
-
-
 /**
  * dgrp_dump() -- prints memory for debugging purposes.
  * @mem: Memory location which should be printed to the console
@@ -801,7 +784,6 @@
 static int dgrp_net_open(struct inode *inode, struct file *file)
 {
 	struct nd_struct *nd;
-	struct proc_dir_entry *de;
 	ulong  lock_flags;
 	int rtn;
 
@@ -825,13 +807,7 @@
 	/*
 	 *  Get the node pointer, and fail if it doesn't exist.
 	 */
-	de = PDE(inode);
-	if (!de) {
-		rtn = -ENXIO;
-		goto done;
-	}
-
-	nd = (struct nd_struct *) de->data;
+	nd = PDE_DATA(inode);
 	if (!nd) {
 		rtn = -ENXIO;
 		goto done;
diff --git a/drivers/staging/dgrp/dgrp_ports_ops.c b/drivers/staging/dgrp/dgrp_ports_ops.c
index f93dc1f..4ce0308 100644
--- a/drivers/staging/dgrp/dgrp_ports_ops.c
+++ b/drivers/staging/dgrp/dgrp_ports_ops.c
@@ -47,7 +47,7 @@
 /* File operation declarations */
 static int dgrp_ports_open(struct inode *, struct file *);
 
-static const struct file_operations ports_ops = {
+const struct file_operations dgrp_ports_ops = {
 	.owner   = THIS_MODULE,
 	.open    = dgrp_ports_open,
 	.read    = seq_read,
@@ -55,20 +55,6 @@
 	.release = seq_release
 };
 
-static struct inode_operations ports_inode_ops = {
-	.permission = dgrp_inode_permission
-};
-
-
-void dgrp_register_ports_hook(struct proc_dir_entry *de)
-{
-	struct nd_struct *node = de->data;
-
-	de->proc_iops = &ports_inode_ops;
-	rcu_assign_pointer(de->proc_fops, &ports_ops);
-	node->nd_ports_de = de;
-}
-
 static void *dgrp_ports_seq_start(struct seq_file *seq, loff_t *pos)
 {
 	if (*pos == 0)
@@ -163,7 +149,7 @@
 	rtn = seq_open(file, &ports_seq_ops);
 	if (!rtn) {
 		seq = file->private_data;
-		seq->private = PDE(inode)->data;
+		seq->private = PDE_DATA(inode);
 	}
 
 	return rtn;
diff --git a/drivers/staging/dgrp/dgrp_specproc.c b/drivers/staging/dgrp/dgrp_specproc.c
index d66712c..205d80e 100644
--- a/drivers/staging/dgrp/dgrp_specproc.c
+++ b/drivers/staging/dgrp/dgrp_specproc.c
@@ -37,6 +37,7 @@
 #include <linux/sched.h>
 #include <linux/cred.h>
 #include <linux/proc_fs.h>
+#include <linux/slab.h>
 #include <linux/ctype.h>
 #include <linux/seq_file.h>
 #include <linux/uaccess.h>
@@ -44,43 +45,17 @@
 
 #include "dgrp_common.h"
 
-static struct dgrp_proc_entry dgrp_table[];
 static struct proc_dir_entry *dgrp_proc_dir_entry;
 
 static int dgrp_add_id(long id);
 static int dgrp_remove_nd(struct nd_struct *nd);
-static void unregister_dgrp_device(struct proc_dir_entry *de);
-static void register_dgrp_device(struct nd_struct *node,
+static struct proc_dir_entry *add_proc_file(struct nd_struct *node,
 				 struct proc_dir_entry *root,
-				 void (*register_hook)(struct proc_dir_entry *de));
+				 const struct file_operations *fops);
 
 /* File operation declarations */
-static int dgrp_gen_proc_open(struct inode *, struct file *);
-static int dgrp_gen_proc_close(struct inode *, struct file *);
 static int parse_write_config(char *);
 
-
-static const struct file_operations dgrp_proc_file_ops = {
-	.owner   = THIS_MODULE,
-	.open    = dgrp_gen_proc_open,
-	.release = dgrp_gen_proc_close,
-};
-
-static struct inode_operations proc_inode_ops = {
-	.permission = dgrp_inode_permission
-};
-
-
-static void register_proc_table(struct dgrp_proc_entry *,
-				struct proc_dir_entry *);
-static void unregister_proc_table(struct dgrp_proc_entry *,
-				  struct proc_dir_entry *);
-
-static struct dgrp_proc_entry dgrp_net_table[];
-static struct dgrp_proc_entry dgrp_mon_table[];
-static struct dgrp_proc_entry dgrp_ports_table[];
-static struct dgrp_proc_entry dgrp_dpa_table[];
-
 static ssize_t dgrp_config_proc_write(struct file *file,
 				      const char __user *buffer,
 				      size_t count, loff_t *pos);
@@ -89,7 +64,7 @@
 static int dgrp_info_proc_open(struct inode *inode, struct file *file);
 static int dgrp_config_proc_open(struct inode *inode, struct file *file);
 
-static struct file_operations config_proc_file_ops = {
+static const struct file_operations config_proc_file_ops = {
 	.owner	 = THIS_MODULE,
 	.open	 = dgrp_config_proc_open,
 	.read	 = seq_read,
@@ -98,7 +73,7 @@
 	.write   = dgrp_config_proc_write,
 };
 
-static struct file_operations info_proc_file_ops = {
+static const struct file_operations info_proc_file_ops = {
 	.owner	 = THIS_MODULE,
 	.open	 = dgrp_info_proc_open,
 	.read	 = seq_read,
@@ -106,7 +81,7 @@
 	.release = single_release,
 };
 
-static struct file_operations nodeinfo_proc_file_ops = {
+static const struct file_operations nodeinfo_proc_file_ops = {
 	.owner	 = THIS_MODULE,
 	.open	 = dgrp_nodeinfo_proc_open,
 	.read	 = seq_read,
@@ -114,71 +89,25 @@
 	.release = seq_release,
 };
 
-static struct dgrp_proc_entry dgrp_table[] = {
-	{
-		.id = DGRP_CONFIG,
-		.name = "config",
-		.mode = 0644,
-		.proc_file_ops = &config_proc_file_ops,
-	},
-	{
-		.id = DGRP_INFO,
-		.name = "info",
-		.mode = 0644,
-		.proc_file_ops = &info_proc_file_ops,
-	},
-	{
-		.id = DGRP_NODEINFO,
-		.name = "nodeinfo",
-		.mode = 0644,
-		.proc_file_ops = &nodeinfo_proc_file_ops,
-	},
-	{
-		.id = DGRP_NETDIR,
-		.name = "net",
-		.mode = 0500,
-		.child = dgrp_net_table
-	},
-	{
-		.id = DGRP_MONDIR,
-		.name = "mon",
-		.mode = 0500,
-		.child = dgrp_mon_table
-	},
-	{
-		.id = DGRP_PORTSDIR,
-		.name = "ports",
-		.mode = 0500,
-		.child = dgrp_ports_table
-	},
-	{
-		.id = DGRP_DPADIR,
-		.name = "dpa",
-		.mode = 0500,
-		.child = dgrp_dpa_table
-	}
-};
-
 static struct proc_dir_entry *net_entry_pointer;
 static struct proc_dir_entry *mon_entry_pointer;
 static struct proc_dir_entry *dpa_entry_pointer;
 static struct proc_dir_entry *ports_entry_pointer;
 
-static struct dgrp_proc_entry dgrp_net_table[] = {
-	{0}
-};
-
-static struct dgrp_proc_entry dgrp_mon_table[] = {
-	{0}
-};
-
-static struct dgrp_proc_entry dgrp_ports_table[] = {
-	{0}
-};
-
-static struct dgrp_proc_entry dgrp_dpa_table[] = {
-	{0}
-};
+static void remove_files(struct nd_struct *nd)
+{
+	char buf[3];
+	ID_TO_CHAR(nd->nd_ID, buf);
+	dgrp_remove_node_class_sysfs_files(nd);
+	if (nd->nd_net_de)
+		remove_proc_entry(buf, net_entry_pointer);
+	if (nd->nd_mon_de)
+		remove_proc_entry(buf, mon_entry_pointer);
+	if (nd->nd_dpa_de)
+		remove_proc_entry(buf, dpa_entry_pointer);
+	if (nd->nd_ports_de)
+		remove_proc_entry(buf, ports_entry_pointer);
+}
 
 void dgrp_unregister_proc(void)
 {
@@ -188,12 +117,19 @@
 	ports_entry_pointer = NULL;
 
 	if (dgrp_proc_dir_entry) {
-		unregister_proc_table(dgrp_table, dgrp_proc_dir_entry);
-		remove_proc_entry(dgrp_proc_dir_entry->name,
-				  dgrp_proc_dir_entry->parent);
+		struct nd_struct *nd;
+		list_for_each_entry(nd, &nd_struct_list, list)
+			remove_files(nd);
+		remove_proc_entry("dgrp/config", NULL);
+		remove_proc_entry("dgrp/info", NULL);
+		remove_proc_entry("dgrp/nodeinfo", NULL);
+		remove_proc_entry("dgrp/net", NULL);
+		remove_proc_entry("dgrp/mon", NULL);
+		remove_proc_entry("dgrp/dpa", NULL);
+		remove_proc_entry("dgrp/ports", NULL);
+		remove_proc_entry("dgrp", NULL);
 		dgrp_proc_dir_entry = NULL;
 	}
-
 }
 
 void dgrp_register_proc(void)
@@ -201,211 +137,16 @@
 	/*
 	 *	Register /proc/dgrp
 	 */
-	dgrp_proc_dir_entry = proc_create("dgrp", S_IFDIR, NULL,
-					  &dgrp_proc_file_ops);
-	register_proc_table(dgrp_table, dgrp_proc_dir_entry);
-}
-
-/*
- * /proc/sys support
- */
-static int dgrp_proc_match(int len, const char *name, struct proc_dir_entry *de)
-{
-	if (!de || !de->low_ino)
-		return 0;
-	if (de->namelen != len)
-		return 0;
-	return !memcmp(name, de->name, len);
-}
-
-
-/*
- *  Scan the entries in table and add them all to /proc at the position
- *  referred to by "root"
- */
-static void register_proc_table(struct dgrp_proc_entry *table,
-				struct proc_dir_entry *root)
-{
-	struct proc_dir_entry *de;
-	int len;
-	mode_t mode;
-
-	if (table == NULL)
+	dgrp_proc_dir_entry = proc_mkdir("dgrp", NULL);
+	if (!dgrp_proc_dir_entry)
 		return;
-	if (root == NULL)
-		return;
-
-	for (; table->id; table++) {
-		/* Can't do anything without a proc name. */
-		if (!table->name)
-			continue;
-
-		/* Maybe we can't do anything with it... */
-		if (!table->proc_file_ops &&
-		    !table->child) {
-			pr_warn("dgrp: Can't register %s\n",
-				table->name);
-			continue;
-		}
-
-		len = strlen(table->name);
-		mode = table->mode;
-
-		de = NULL;
-		if (!table->child)
-			mode |= S_IFREG;
-		else {
-			mode |= S_IFDIR;
-			for (de = root->subdir; de; de = de->next) {
-				if (dgrp_proc_match(len, table->name, de))
-					break;
-			}
-			/* If the subdir exists already, de is non-NULL */
-		}
-
-		if (!de) {
-			de = create_proc_entry(table->name, mode, root);
-			if (!de)
-				continue;
-			de->data = (void *) table;
-			if (!table->child) {
-				de->proc_iops = &proc_inode_ops;
-				if (table->proc_file_ops)
-					rcu_assign_pointer(de->proc_fops,
-							table->proc_file_ops);
-				else
-					rcu_assign_pointer(de->proc_fops,
-							 &dgrp_proc_file_ops);
-			}
-		}
-		table->de = de;
-		if (de->mode & S_IFDIR)
-			register_proc_table(table->child, de);
-
-		if (table->id == DGRP_NETDIR)
-			net_entry_pointer = de;
-
-		if (table->id == DGRP_MONDIR)
-			mon_entry_pointer = de;
-
-		if (table->id == DGRP_DPADIR)
-			dpa_entry_pointer = de;
-
-		if (table->id == DGRP_PORTSDIR)
-			ports_entry_pointer = de;
-	}
-}
-
-/*
- * Unregister a /proc sysctl table and any subdirectories.
- */
-static void unregister_proc_table(struct dgrp_proc_entry *table,
-				  struct proc_dir_entry *root)
-{
-	struct proc_dir_entry *de;
-	struct nd_struct *tmp;
-
-	if (table == NULL)
-		return;
-
-	list_for_each_entry(tmp, &nd_struct_list, list) {
-		if ((table == dgrp_net_table) && (tmp->nd_net_de)) {
-			unregister_dgrp_device(tmp->nd_net_de);
-			dgrp_remove_node_class_sysfs_files(tmp);
-		}
-
-		if ((table == dgrp_mon_table) && (tmp->nd_mon_de))
-			unregister_dgrp_device(tmp->nd_mon_de);
-
-		if ((table == dgrp_dpa_table) && (tmp->nd_dpa_de))
-			unregister_dgrp_device(tmp->nd_dpa_de);
-
-		if ((table == dgrp_ports_table) && (tmp->nd_ports_de))
-			unregister_dgrp_device(tmp->nd_ports_de);
-	}
-
-	for (; table->id; table++) {
-		de = table->de;
-
-		if (!de)
-			continue;
-		if (de->mode & S_IFDIR) {
-			if (!table->child) {
-				pr_alert("dgrp: malformed sysctl tree on free\n");
-				continue;
-			}
-			unregister_proc_table(table->child, de);
-
-	/* Don't unregister directories which still have entries */
-			if (de->subdir)
-				continue;
-		}
-
-		/* Don't unregister proc entries that are still being used.. */
-		if ((atomic_read(&de->count)) != 1) {
-			pr_alert("proc entry %s in use, not removing\n",
-				de->name);
-			continue;
-		}
-
-		remove_proc_entry(de->name, de->parent);
-		table->de = NULL;
-	}
-}
-
-static int dgrp_gen_proc_open(struct inode *inode, struct file *file)
-{
-	struct proc_dir_entry *de;
-	struct dgrp_proc_entry *entry;
-	int ret = 0;
-
-	de = (struct proc_dir_entry *) PDE(file_inode(file));
-	if (!de || !de->data) {
-		ret = -ENXIO;
-		goto done;
-	}
-
-	entry = (struct dgrp_proc_entry *) de->data;
-	if (!entry) {
-		ret = -ENXIO;
-		goto done;
-	}
-
-	down(&entry->excl_sem);
-
-	if (entry->excl_cnt)
-		ret = -EBUSY;
-	else
-		entry->excl_cnt++;
-
-	up(&entry->excl_sem);
-
-done:
-	return ret;
-}
-
-static int dgrp_gen_proc_close(struct inode *inode, struct file *file)
-{
-	struct proc_dir_entry *de;
-	struct dgrp_proc_entry *entry;
-
-	de = (struct proc_dir_entry *) PDE(file_inode(file));
-	if (!de || !de->data)
-		goto done;
-
-	entry = (struct dgrp_proc_entry *) de->data;
-	if (!entry)
-		goto done;
-
-	down(&entry->excl_sem);
-
-	if (entry->excl_cnt)
-		entry->excl_cnt = 0;
-
-	up(&entry->excl_sem);
-
-done:
-	return 0;
+	proc_create("dgrp/config", 0644, NULL, &config_proc_file_ops);
+	proc_create("dgrp/info", 0644, NULL, &info_proc_file_ops);
+	proc_create("dgrp/nodeinfo", 0644, NULL, &nodeinfo_proc_file_ops);
+	net_entry_pointer = proc_mkdir_mode("dgrp/net", 0500, NULL);
+	mon_entry_pointer = proc_mkdir_mode("dgrp/mon", 0500, NULL);
+	dpa_entry_pointer = proc_mkdir_mode("dgrp/dpa", 0500, NULL);
+	ports_entry_pointer = proc_mkdir_mode("dgrp/ports", 0500, NULL);
 }
 
 static void *dgrp_config_proc_start(struct seq_file *m, loff_t *pos)
@@ -736,6 +477,10 @@
 	init_waitqueue_head(&nd->nd_tx_waitq);
 	init_waitqueue_head(&nd->nd_mon_wqueue);
 	init_waitqueue_head(&nd->nd_dpa_wqueue);
+	sema_init(&nd->nd_mon_semaphore, 1);
+	sema_init(&nd->nd_net_semaphore, 1);
+	spin_lock_init(&nd->nd_dpa_lock);
+	nd->nd_state = NS_CLOSED;
 	for (i = 0; i < SEQ_MAX; i++)
 		init_waitqueue_head(&nd->nd_seq_wque[i]);
 
@@ -750,12 +495,12 @@
 	if (ret)
 		goto error_out;
 
-	register_dgrp_device(nd, net_entry_pointer, dgrp_register_net_hook);
-	register_dgrp_device(nd, mon_entry_pointer, dgrp_register_mon_hook);
-	register_dgrp_device(nd, dpa_entry_pointer, dgrp_register_dpa_hook);
-	register_dgrp_device(nd, ports_entry_pointer,
-			      dgrp_register_ports_hook);
-
+	dgrp_create_node_class_sysfs_files(nd);
+	nd->nd_net_de = add_proc_file(nd, net_entry_pointer, &dgrp_net_ops);
+	nd->nd_mon_de = add_proc_file(nd, mon_entry_pointer, &dgrp_mon_ops);
+	nd->nd_dpa_de = add_proc_file(nd, dpa_entry_pointer, &dgrp_dpa_ops);
+	nd->nd_ports_de = add_proc_file(nd, ports_entry_pointer,
+					&dgrp_ports_ops);
 	return 0;
 
 	/* FIXME this guy should free the tty driver stored in nd and destroy
@@ -774,16 +519,7 @@
 	if (nd->nd_tty_ref_cnt)
 		return -EBUSY;
 
-	if (nd->nd_net_de) {
-		unregister_dgrp_device(nd->nd_net_de);
-		dgrp_remove_node_class_sysfs_files(nd);
-	}
-
-	unregister_dgrp_device(nd->nd_mon_de);
-
-	unregister_dgrp_device(nd->nd_ports_de);
-
-	unregister_dgrp_device(nd->nd_dpa_de);
+	remove_files(nd);
 
 	dgrp_tty_uninit(nd);
 
@@ -795,38 +531,11 @@
 	return 0;
 }
 
-static void register_dgrp_device(struct nd_struct *node,
+static struct proc_dir_entry *add_proc_file(struct nd_struct *node,
 				 struct proc_dir_entry *root,
-				 void (*register_hook)(struct proc_dir_entry *de))
+				 const struct file_operations *fops)
 {
 	char buf[3];
-	struct proc_dir_entry *de;
-
 	ID_TO_CHAR(node->nd_ID, buf);
-
-	de = create_proc_entry(buf, 0600 | S_IFREG, root);
-	if (!de)
-		return;
-
-	de->data = (void *) node;
-
-	if (register_hook)
-		register_hook(de);
-
-}
-
-static void unregister_dgrp_device(struct proc_dir_entry *de)
-{
-	if (!de)
-		return;
-
-	/* Don't unregister proc entries that are still being used.. */
-	if ((atomic_read(&de->count)) != 1) {
-		pr_alert("%s - proc entry %s in use. Not removing.\n",
-			 __func__, de->name);
-		return;
-	}
-
-	remove_proc_entry(de->name, de->parent);
-	de = NULL;
+	return proc_create_data(buf, 0600, root, fops, node);
 }
diff --git a/drivers/staging/ft1000/ft1000-pcmcia/ft1000_proc.c b/drivers/staging/ft1000/ft1000-pcmcia/ft1000_proc.c
index 5337b41..21b369e 100644
--- a/drivers/staging/ft1000/ft1000-pcmcia/ft1000_proc.c
+++ b/drivers/staging/ft1000/ft1000-pcmcia/ft1000_proc.c
@@ -19,6 +19,7 @@
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/proc_fs.h>
+#include <linux/seq_file.h>
 #include <linux/string.h>
 #include <linux/vmalloc.h>
 #include <linux/netdevice.h>
@@ -29,70 +30,55 @@
 #define FT1000_PROC "ft1000"
 #define MAX_FILE_LEN 255
 
-#define PUTM_TO_PAGE(len, page, args...) \
-	len += snprintf(page+len, PAGE_SIZE - len, args)
-
-#define PUTX_TO_PAGE(len, page, message, size, var) \
-	len += snprintf(page+len, PAGE_SIZE - len, message); \
+#define seq_putx(m, message, size, var) \
+	seq_printf(m, message);	\
 	for(i = 0; i < (size - 1); i++) { \
-		len += snprintf(page+len, PAGE_SIZE - len, "%02x:", var[i]); \
+		seq_printf(m, "%02x:", var[i]); \
 	} \
-	len += snprintf(page+len, PAGE_SIZE - len, "%02x\n", var[i])
+	seq_printf(m, "%02x\n", var[i])
 
-#define PUTD_TO_PAGE(len, page, message, size, var) \
-	len += snprintf(page+len, PAGE_SIZE - len, message); \
+#define seq_putd(m, message, size, var) \
+	seq_printf(m, message); \
 	for(i = 0; i < (size - 1); i++) { \
-		len += snprintf(page+len, PAGE_SIZE - len, "%d.", var[i]); \
+		seq_printf(m, "%d.", var[i]); \
 	} \
-	len += snprintf(page+len, PAGE_SIZE - len, "%d\n", var[i])
+	seq_printf(m, "%d\n", var[i])
 
-static int ft1000ReadProc(char *page, char **start, off_t off,
-			  int count, int *eof, void *data)
+static int ft1000ReadProc(struct seq_file *m, void *v)
 {
-	struct net_device *dev;
-	int len;
-	int i;
-	struct ft1000_info *info;
-	char *status[] = {
+	static const char *status[] = {
 		"Idle (Disconnect)", "Searching", "Active (Connected)",
 		"Waiting for L2", "Sleep", "No Coverage", "", ""
 	};
-	char *signal[] = { "", "*", "**", "***", "****" };
+	static const char *signal[] = { "", "*", "**", "***", "****" };
+
+	struct net_device *dev = m->private;
+	struct ft1000_info *info = netdev_priv(dev);
+	int i;
 	int strength;
 	int quality;
 	struct timeval tv;
 	time_t delta;
 
-	dev = (struct net_device *)data;
-	info = netdev_priv(dev);
-
-	if (off > 0) {
-		*eof = 1;
-		return 0;
-	}
-
-	/* Wrap-around */
-
 	if (info->AsicID == ELECTRABUZZ_ID) {
 		if (info->ProgConStat != 0xFF) {
 			info->LedStat =
 				ft1000_read_dpram(dev, FT1000_DSP_LED);
 			info->ConStat =
-				ft1000_read_dpram(dev,
-						  FT1000_DSP_CON_STATE);
+				ft1000_read_dpram(dev, FT1000_DSP_CON_STATE);
 		} else {
 			info->ConStat = 0xf;
 		}
 	} else {
 		if (info->ProgConStat != 0xFF) {
 			info->LedStat =
-				ntohs(ft1000_read_dpram_mag_16
-				  (dev, FT1000_MAG_DSP_LED,
-				   FT1000_MAG_DSP_LED_INDX));
+				ntohs(ft1000_read_dpram_mag_16(
+					      dev, FT1000_MAG_DSP_LED,
+					      FT1000_MAG_DSP_LED_INDX));
 			info->ConStat =
-				ntohs(ft1000_read_dpram_mag_16
-				  (dev, FT1000_MAG_DSP_CON_STATE,
-				   FT1000_MAG_DSP_CON_STATE_INDX));
+				ntohs(ft1000_read_dpram_mag_16(
+					      dev, FT1000_MAG_DSP_CON_STATE,
+					      FT1000_MAG_DSP_CON_STATE_INDX));
 		} else {
 			info->ConStat = 0xf;
 		}
@@ -135,36 +121,46 @@
 	}
 
 	do_gettimeofday(&tv);
-	delta = (tv.tv_sec - info->ConTm);
-	len = 0;
-	PUTM_TO_PAGE(len, page, "Connection Time: %02ld:%02ld:%02ld\n",
+	delta = tv.tv_sec - info->ConTm;
+	seq_printf(m, "Connection Time: %02ld:%02ld:%02ld\n",
 			 ((delta / 3600) % 24), ((delta / 60) % 60), (delta % 60));
-	PUTM_TO_PAGE(len, page, "Connection Time[s]: %ld\n", delta);
-	PUTM_TO_PAGE(len, page, "Asic ID: %s\n",
-			 (info->AsicID) ==
+	seq_printf(m, "Connection Time[s]: %ld\n", delta);
+	seq_printf(m, "Asic ID: %s\n",
+			 info->AsicID ==
 			 ELECTRABUZZ_ID ? "ELECTRABUZZ ASIC" : "MAGNEMITE ASIC");
-	PUTX_TO_PAGE(len, page, "SKU: ", SKUSZ, info->Sku);
-	PUTX_TO_PAGE(len, page, "EUI64: ", EUISZ, info->eui64);
-	PUTD_TO_PAGE(len, page, "DSP version number: ", DSPVERSZ, info->DspVer);
-	PUTX_TO_PAGE(len, page, "Hardware Serial Number: ", HWSERNUMSZ,
-			 info->HwSerNum);
-	PUTX_TO_PAGE(len, page, "Caliberation Version: ", CALVERSZ,
-			 info->RfCalVer);
-	PUTD_TO_PAGE(len, page, "Caliberation Date: ", CALDATESZ,
-			 info->RfCalDate);
-	PUTM_TO_PAGE(len, page, "Media State: %s\n",
+	seq_putx(m, "SKU: ", SKUSZ, info->Sku);
+	seq_putx(m, "EUI64: ", EUISZ, info->eui64);
+	seq_putd(m, "DSP version number: ", DSPVERSZ, info->DspVer);
+	seq_putx(m, "Hardware Serial Number: ", HWSERNUMSZ, info->HwSerNum);
+	seq_putx(m, "Caliberation Version: ", CALVERSZ, info->RfCalVer);
+	seq_putd(m, "Caliberation Date: ", CALDATESZ, info->RfCalDate);
+	seq_printf(m, "Media State: %s\n",
 			 (info->mediastate) ? "link" : "no link");
-	PUTM_TO_PAGE(len, page, "Connection Status: %s\n",
-			 status[((info->ConStat) & 0x7)]);
-	PUTM_TO_PAGE(len, page, "RX packets: %ld\n", info->stats.rx_packets);
-	PUTM_TO_PAGE(len, page, "TX packets: %ld\n", info->stats.tx_packets);
-	PUTM_TO_PAGE(len, page, "RX bytes: %ld\n", info->stats.rx_bytes);
-	PUTM_TO_PAGE(len, page, "TX bytes: %ld\n", info->stats.tx_bytes);
-	PUTM_TO_PAGE(len, page, "Signal Strength: %s\n", signal[strength]);
-	PUTM_TO_PAGE(len, page, "Signal Quality: %s\n", signal[quality]);
-	return len;
+	seq_printf(m, "Connection Status: %s\n", status[info->ConStat & 0x7]);
+	seq_printf(m, "RX packets: %ld\n", info->stats.rx_packets);
+	seq_printf(m, "TX packets: %ld\n", info->stats.tx_packets);
+	seq_printf(m, "RX bytes: %ld\n", info->stats.rx_bytes);
+	seq_printf(m, "TX bytes: %ld\n", info->stats.tx_bytes);
+	seq_printf(m, "Signal Strength: %s\n", signal[strength]);
+	seq_printf(m, "Signal Quality: %s\n", signal[quality]);
+	return 0;
 }
 
+/*
+ * seq_file wrappers for procfile show routines.
+ */
+static int ft1000_proc_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, ft1000ReadProc, PDE_DATA(inode));
+}
+
+static const struct file_operations ft1000_proc_fops = {
+	.open		= ft1000_proc_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= seq_release,
+};
+
 static int ft1000NotifyProc(struct notifier_block *this, unsigned long event,
 				void *ptr)
 {
@@ -176,8 +172,8 @@
 	switch (event) {
 	case NETDEV_CHANGENAME:
 		remove_proc_entry(info->netdevname, info->ft1000_proc_dir);
-		create_proc_read_entry(dev->name, 0644, info->ft1000_proc_dir,
-					   ft1000ReadProc, dev);
+		proc_create_data(dev->name, 0644, info->ft1000_proc_dir,
+				 &ft1000_proc_fops, dev);
 		snprintf(info->netdevname, IFNAMSIZ, "%s", dev->name);
 		break;
 	}
@@ -195,8 +191,10 @@
 	info = netdev_priv(dev);
 
 	info->ft1000_proc_dir = proc_mkdir(FT1000_PROC, init_net.proc_net);
-	create_proc_read_entry(dev->name, 0644, info->ft1000_proc_dir,
-				   ft1000ReadProc, dev);
+
+	proc_create_data(dev->name, 0644, info->ft1000_proc_dir,
+			 &ft1000_proc_fops, dev);
+
 	snprintf(info->netdevname, IFNAMSIZ, "%s", dev->name);
 	register_netdevice_notifier(&ft1000_netdev_notifier);
 }
diff --git a/drivers/staging/ft1000/ft1000-usb/ft1000_debug.c b/drivers/staging/ft1000/ft1000-usb/ft1000_debug.c
index 297389e..3251d2e 100644
--- a/drivers/staging/ft1000/ft1000-usb/ft1000_debug.c
+++ b/drivers/staging/ft1000/ft1000-usb/ft1000_debug.c
@@ -55,7 +55,7 @@
 //
 // Table of entry-point routines for char device
 //
-static struct file_operations ft1000fops =
+static const struct file_operations ft1000fops =
 {
 	.unlocked_ioctl	= ft1000_ioctl,
 	.poll		= ft1000_poll_dev,
diff --git a/drivers/staging/ft1000/ft1000-usb/ft1000_proc.c b/drivers/staging/ft1000/ft1000-usb/ft1000_proc.c
index b996406..d8294d6 100644
--- a/drivers/staging/ft1000/ft1000-usb/ft1000_proc.c
+++ b/drivers/staging/ft1000/ft1000-usb/ft1000_proc.c
@@ -22,6 +22,7 @@
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/proc_fs.h>
+#include <linux/seq_file.h>
 #include <linux/netdevice.h>
 
 
@@ -30,22 +31,17 @@
 #define FT1000_PROC_DIR "ft1000"
 
 
-#define PUTM_TO_PAGE(len,page,args...) \
-	len += snprintf(page+len, PAGE_SIZE - len, args)
+#define seq_putx(m, message, size, var) \
+	seq_printf(m, message);	\
+	for(i = 0; i < (size - 1); i++) \
+		seq_printf(m, "%02x:", var[i]); \
+	seq_printf(m, "%02x\n", var[i])
 
-#define PUTX_TO_PAGE(len,page,message,size,var) \
-	len += snprintf(page+len, PAGE_SIZE - len, message); \
-	for (i = 0; i < (size - 1); i++) {\
-		len += snprintf(page+len, PAGE_SIZE - len, "%02x:", var[i]); \
-	} \
-	len += snprintf(page+len, PAGE_SIZE - len, "%02x\n", var[i])
-
-#define PUTD_TO_PAGE(len,page,message,size,var) \
-	len += snprintf(page+len, PAGE_SIZE - len, message); \
-	for (i = 0; i < (size - 1); i++) {\
-		len += snprintf(page+len, PAGE_SIZE - len, "%d.", var[i]); \
-	} \
-	len += snprintf(page+len, PAGE_SIZE - len, "%d\n", var[i])
+#define seq_putd(m, message, size, var) \
+	seq_printf(m, message); \
+	for(i = 0; i < (size - 1); i++) \
+		seq_printf(m, "%d.", var[i]); \
+	seq_printf(m, "%d\n", var[i])
 
 
 #define FTNET_PROC init_net.proc_net
@@ -55,19 +51,9 @@
 			 u8 *buffer, u8 highlow);
 
 
-static int
-ft1000ReadProc(char *page, char **start, off_t off, int count, int *eof,
-		void *data)
+static int ft1000ReadProc(struct seq_file *m, void *v)
 {
-	struct net_device *dev;
-	int len;
-	int i;
-	unsigned short ledStat;
-	unsigned short conStat;
-
-	struct ft1000_info *info;
-
-	char *status[] = { 
+	static const char *status[] = { 
 		"Idle (Disconnect)", 
 		"Searching",
 		"Active (Connected)",
@@ -77,22 +63,18 @@
 		"",
 		"",
 	};
+	static const char *signal[] = { "", "*", "**", "***", "****" };
 
-	char *signal[] = { "", "*", "**", "***", "****" };
+	struct net_device *dev = m->private;
+	struct ft1000_info *info = netdev_priv(dev);
+	int i;
+	unsigned short ledStat;
+	unsigned short conStat;
 	int strength;
 	int quality;
 	struct timeval tv;
 	time_t delta;
 
-	dev = (struct net_device *) data;
-	info = netdev_priv(dev);
-
-	if (off > 0) {
-		*eof = 1;
-		return 0;
-	}
-
-
 	if (info->ProgConStat != 0xFF) {
 		ft1000_read_dpram16(info->priv, FT1000_MAG_DSP_LED,
 			   (u8 *)&ledStat, FT1000_MAG_DSP_LED_INDX);
@@ -144,36 +126,43 @@
 		quality = 0;
 	}
 
-	len = 0;
-	PUTM_TO_PAGE(len, page, "Connection Time: %02ld:%02ld:%02ld\n",
+	seq_printf(m, "Connection Time: %02ld:%02ld:%02ld\n",
       		((delta / 3600) % 24), ((delta / 60) % 60), (delta % 60));
-	PUTM_TO_PAGE(len, page, "Connection Time[s]: %ld\n", delta);
-	PUTM_TO_PAGE(len, page, "Asic ID: %s\n",
-      	(info->AsicID) ==
-      	ELECTRABUZZ_ID ? "ELECTRABUZZ ASIC" : "MAGNEMITE ASIC");
-	PUTX_TO_PAGE(len, page, "SKU: ", SKUSZ, info->Sku);
-	PUTX_TO_PAGE(len, page, "EUI64: ", EUISZ, info->eui64);
-	PUTD_TO_PAGE(len, page, "DSP version number: ", DSPVERSZ, info->DspVer);
-	PUTX_TO_PAGE(len, page, "Hardware Serial Number: ", HWSERNUMSZ,
-      		info->HwSerNum);
-	PUTX_TO_PAGE(len, page, "Caliberation Version: ", CALVERSZ,
-      		info->RfCalVer);
-	PUTD_TO_PAGE(len, page, "Caliberation Date: ", CALDATESZ,
-		info->RfCalDate);
-	PUTM_TO_PAGE(len, page, "Media State: %s\n",
-      		(info->mediastate) ? "link" : "no link");
-	PUTM_TO_PAGE(len, page, "Connection Status: %s\n",
-      		status[((info->ConStat) & 0x7)]);
-	PUTM_TO_PAGE(len, page, "RX packets: %ld\n", info->stats.rx_packets);
-	PUTM_TO_PAGE(len, page, "TX packets: %ld\n", info->stats.tx_packets);
-	PUTM_TO_PAGE(len, page, "RX bytes: %ld\n", info->stats.rx_bytes);
-	PUTM_TO_PAGE(len, page, "TX bytes: %ld\n", info->stats.tx_bytes);
-	PUTM_TO_PAGE(len, page, "Signal Strength: %s\n", signal[strength]);
-	PUTM_TO_PAGE(len, page, "Signal Quality: %s\n", signal[quality]);
-
-	return len;
+	seq_printf(m, "Connection Time[s]: %ld\n", delta);
+	seq_printf(m, "Asic ID: %s\n",
+      	(info->AsicID) == ELECTRABUZZ_ID ? "ELECTRABUZZ ASIC" : "MAGNEMITE ASIC");
+	seq_putx(m, "SKU: ", SKUSZ, info->Sku);
+	seq_putx(m, "EUI64: ", EUISZ, info->eui64);
+	seq_putd(m, "DSP version number: ", DSPVERSZ, info->DspVer);
+	seq_putx(m, "Hardware Serial Number: ", HWSERNUMSZ, info->HwSerNum);
+	seq_putx(m, "Caliberation Version: ", CALVERSZ, info->RfCalVer);
+	seq_putd(m, "Caliberation Date: ", CALDATESZ, info->RfCalDate);
+	seq_printf(m, "Media State: %s\n", (info->mediastate) ? "link" : "no link");
+	seq_printf(m, "Connection Status: %s\n", status[info->ConStat & 0x7]);
+	seq_printf(m, "RX packets: %ld\n", info->stats.rx_packets);
+	seq_printf(m, "TX packets: %ld\n", info->stats.tx_packets);
+	seq_printf(m, "RX bytes: %ld\n", info->stats.rx_bytes);
+	seq_printf(m, "TX bytes: %ld\n", info->stats.tx_bytes);
+	seq_printf(m, "Signal Strength: %s\n", signal[strength]);
+	seq_printf(m, "Signal Quality: %s\n", signal[quality]);
+	return 0;
 }
 
+/*
+ * seq_file wrappers for procfile show routines.
+ */
+static int ft1000_proc_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, ft1000ReadProc, PDE_DATA(inode));
+}
+
+static const struct file_operations ft1000_proc_fops = {
+	.open		= ft1000_proc_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= seq_release,
+};
+
 static int
 ft1000NotifyProc(struct notifier_block *this, unsigned long event, void *ptr)
 {
@@ -186,9 +175,9 @@
 	switch (event) {
 	case NETDEV_CHANGENAME:
 		remove_proc_entry(info->netdevname, info->ft1000_proc_dir);
-		ft1000_proc_file = create_proc_read_entry(dev->name, 0644,
-					info->ft1000_proc_dir,
-					ft1000ReadProc, dev);
+		ft1000_proc_file =
+			proc_create_data(dev->name, 0644, info->ft1000_proc_dir,
+					 &ft1000_proc_fops, dev);
 		snprintf(info->netdevname, IFNAMSIZ, "%s", dev->name);
 		break;
 	}
@@ -217,10 +206,10 @@
 	}
 
 	ft1000_proc_file =
-		create_proc_read_entry(dev->name, 0644,
-			info->ft1000_proc_dir, ft1000ReadProc, dev);
+		proc_create_data(dev->name, 0644, info->ft1000_proc_dir,
+				 &ft1000_proc_fops, dev);
 
-	if (ft1000_proc_file == NULL) {
+	if (!ft1000_proc_file) {
 		printk(KERN_WARNING "Unable to create /proc entry.\n");
 		goto fail_entry;
 	}
diff --git a/drivers/staging/keucr/scsiglue.c b/drivers/staging/keucr/scsiglue.c
index 083b20e..48e1005 100644
--- a/drivers/staging/keucr/scsiglue.c
+++ b/drivers/staging/keucr/scsiglue.c
@@ -229,26 +229,18 @@
 
 /* we use this macro to help us write into the buffer */
 #undef SPRINTF
-#define SPRINTF(args...) \
-	do { \
-		if (pos < buffer+length) \
-			pos += sprintf(pos, ## args); \
-	} while (0)
+#define SPRINTF(args...) seq_printf(m, ##args)
 
-/*
- * proc_info()
- */
-static int proc_info(struct Scsi_Host *host, char *buffer, char **start,
-					off_t offset, int length, int inout)
+static int write_info(struct Scsi_Host *host, char *buffer, int length)
+{
+	return length;
+}
+
+static int show_info(struct seq_file *m, struct Scsi_Host *host)
 {
 	struct us_data *us = host_to_us(host);
-	char *pos = buffer;
 	const char *string;
 
-	/* pr_info("scsiglue --- proc_info\n"); */
-	if (inout)
-		return length;
-
 	/* print the controller name */
 	SPRINTF("   Host scsi%d: usb-storage\n", host->host_no);
 
@@ -278,29 +270,17 @@
 	SPRINTF("    Transport: %s\n", us->transport_name);
 
 	/* show the device flags */
-	if (pos < buffer + length) {
-		pos += sprintf(pos, "       Quirks:");
+	SPRINTF("       Quirks:");
 
 #define US_FLAG(name, value) \
 	do { \
 		if (us->fflags & value) \
-			pos += sprintf(pos, " " #name); \
+			SPRINTF(" " #name); \
 	} while (0);
 US_DO_ALL_FLAGS
 #undef US_FLAG
-
-		*(pos++) = '\n';
-	}
-
-	/* Calculate start of next buffer, and return value. */
-	*start = buffer + offset;
-
-	if ((pos - buffer) < offset)
-		return 0;
-	else if ((pos - buffer - offset) < length)
-		return pos - buffer - offset;
-	else
-		return length;
+	seq_putc(m, '\n');
+	return 0;
 }
 
 /***********************************************************************
@@ -351,7 +331,8 @@
 	/* basic userland interface stuff */
 	.name =				"eucr-storage",
 	.proc_name =			"eucr-storage",
-	.proc_info =			proc_info,
+	.write_info =			write_info,
+	.show_info =			show_info,
 	.info =				host_info,
 
 	/* command interface -- queued only */
diff --git a/drivers/staging/rtl8187se/r8180.h b/drivers/staging/rtl8187se/r8180.h
index 70ea414..edacc80 100644
--- a/drivers/staging/rtl8187se/r8180.h
+++ b/drivers/staging/rtl8187se/r8180.h
@@ -372,7 +372,6 @@
 	struct Stats stats;
 	struct _link_detect_t link_detect;  //YJ,add,080828
 	struct iw_statistics wstats;
-	struct proc_dir_entry *dir_dev;
 
 	/*RX stuff*/
 	u32 *rxring;
diff --git a/drivers/staging/rtl8187se/r8180_core.c b/drivers/staging/rtl8187se/r8180_core.c
index d10d75e..f7c1d99 100644
--- a/drivers/staging/rtl8187se/r8180_core.c
+++ b/drivers/staging/rtl8187se/r8180_core.c
@@ -36,6 +36,8 @@
 #include <linux/syscalls.h>
 #include <linux/eeprom_93cx6.h>
 #include <linux/interrupt.h>
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
 
 #include "r8180_hw.h"
 #include "r8180.h"
@@ -204,51 +206,35 @@
 
 static struct proc_dir_entry *rtl8180_proc;
 
-static int proc_get_registers(char *page, char **start,
-			  off_t offset, int count,
-			  int *eof, void *data)
+static int proc_get_registers(struct seq_file *m, void *v)
 {
-	struct net_device *dev = data;
-	int len = 0;
-	int i, n;
-	int max = 0xff;
+	struct net_device *dev = m->private;
+	int i, n, max = 0xff;
 
 	/* This dump the current register page */
 	for (n = 0; n <= max;) {
-		len += snprintf(page + len, count - len, "\nD:  %2x > ", n);
+		seq_printf(m, "\nD:  %2x > ", n);
 
 		for (i = 0; i < 16 && n <= max; i++, n++)
-			len += snprintf(page + len, count - len, "%2x ",
-					read_nic_byte(dev, n));
+			seq_printf(m, "%2x ", read_nic_byte(dev, n));
 	}
-	len += snprintf(page + len, count - len, "\n");
-
-	*eof = 1;
-	return len;
+	seq_putc(m, '\n');
+	return 0;
 }
 
 int get_curr_tx_free_desc(struct net_device *dev, int priority);
 
-static int proc_get_stats_hw(char *page, char **start,
-			  off_t offset, int count,
-			  int *eof, void *data)
+static int proc_get_stats_hw(struct seq_file *m, void *v)
 {
-	int len = 0;
-
-	*eof = 1;
-	return len;
+	return 0;
 }
 
-static int proc_get_stats_rx(char *page, char **start,
-			  off_t offset, int count,
-			  int *eof, void *data)
+static int proc_get_stats_rx(struct seq_file *m, void *v)
 {
-	struct net_device *dev = data;
+	struct net_device *dev = m->private;
 	struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
 
-	int len = 0;
-
-	len += snprintf(page + len, count - len,
+	seq_printf(m,
 		"RX OK: %lu\n"
 		"RX Retry: %lu\n"
 		"RX CRC Error(0-500): %lu\n"
@@ -263,22 +249,17 @@
 		priv->stats.rxicverr
 		);
 
-	*eof = 1;
-	return len;
+	return 0;
 }
 
-static int proc_get_stats_tx(char *page, char **start,
-			  off_t offset, int count,
-			  int *eof, void *data)
+static int proc_get_stats_tx(struct seq_file *m, void *v)
 {
-	struct net_device *dev = data;
+	struct net_device *dev = m->private;
 	struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
-
-	int len = 0;
 	unsigned long totalOK;
 
 	totalOK = priv->stats.txnpokint+priv->stats.txhpokint+priv->stats.txlpokint;
-	len += snprintf(page + len, count - len,
+	seq_printf(m,
 		"TX OK: %lu\n"
 		"TX Error: %lu\n"
 		"TX Retry: %lu\n"
@@ -291,8 +272,7 @@
 		priv->stats.txbeaconerr
 	);
 
-	*eof = 1;
-	return len;
+	return 0;
 }
 
 void rtl8180_proc_module_init(void)
@@ -308,59 +288,61 @@
 
 void rtl8180_proc_remove_one(struct net_device *dev)
 {
-	struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
-	if (priv->dir_dev) {
-		remove_proc_entry("stats-hw", priv->dir_dev);
-		remove_proc_entry("stats-tx", priv->dir_dev);
-		remove_proc_entry("stats-rx", priv->dir_dev);
-		remove_proc_entry("registers", priv->dir_dev);
-		priv->dir_dev = NULL;
-	}
+	remove_proc_subtree(dev->name, rtl8180_proc);
 }
 
+/*
+ * seq_file wrappers for procfile show routines.
+ */
+static int rtl8180_proc_open(struct inode *inode, struct file *file)
+{
+	struct net_device *dev = proc_get_parent_data(inode);
+	int (*show)(struct seq_file *, void *) = PDE_DATA(inode);
+
+	return single_open(file, show, dev);
+}
+
+static const struct file_operations rtl8180_proc_fops = {
+	.open		= rtl8180_proc_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= seq_release,
+};
+
+/*
+ * Table of proc files we need to create.
+ */
+struct rtl8180_proc_file {
+	char name[12];
+	int (*show)(struct seq_file *, void *);
+};
+
+static const struct rtl8180_proc_file rtl8180_proc_files[] = {
+	{ "stats-hw",	&proc_get_stats_hw },
+	{ "stats-rx",	&proc_get_stats_rx },
+	{ "stats-tx",	&proc_get_stats_tx },
+	{ "registers",	&proc_get_registers },
+	{ "" }
+};
+
 void rtl8180_proc_init_one(struct net_device *dev)
 {
-	struct proc_dir_entry *e;
-	struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
+	const struct rtl8180_proc_file *f;
+	struct proc_dir_entry *dir;
 
-	priv->dir_dev = rtl8180_proc;
-	if (!priv->dir_dev) {
-		DMESGE("Unable to initialize /proc/net/r8180/%s\n",
-		      dev->name);
+	dir = proc_mkdir_data(dev->name, 0, rtl8180_proc, dev);
+	if (!dir) {
+		DMESGE("Unable to initialize /proc/net/r8180/%s\n", dev->name);
 		return;
 	}
 
-	e = create_proc_read_entry("stats-hw", S_IFREG | S_IRUGO,
-				   priv->dir_dev, proc_get_stats_hw, dev);
-	if (!e) {
-		DMESGE("Unable to initialize "
-		      "/proc/net/r8180/%s/stats-hw\n",
-		      dev->name);
-	}
-
-	e = create_proc_read_entry("stats-rx", S_IFREG | S_IRUGO,
-				   priv->dir_dev, proc_get_stats_rx, dev);
-	if (!e) {
-		DMESGE("Unable to initialize "
-		      "/proc/net/r8180/%s/stats-rx\n",
-		      dev->name);
-	}
-
-
-	e = create_proc_read_entry("stats-tx", S_IFREG | S_IRUGO,
-				   priv->dir_dev, proc_get_stats_tx, dev);
-	if (!e) {
-		DMESGE("Unable to initialize "
-		      "/proc/net/r8180/%s/stats-tx\n",
-		      dev->name);
-	}
-
-	e = create_proc_read_entry("registers", S_IFREG | S_IRUGO,
-				   priv->dir_dev, proc_get_registers, dev);
-	if (!e) {
-		DMESGE("Unable to initialize "
-		      "/proc/net/r8180/%s/registers\n",
-		      dev->name);
+	for (f = rtl8180_proc_files; f->name[0]; f++) {
+		if (!proc_create_data(f->name, S_IFREG | S_IRUGO, dir,
+				      &rtl8180_proc_fops, f->show)) {
+			DMESGE("Unable to initialize /proc/net/r8180/%s/%s\n",
+			       dev->name, f->name);
+			return;
+		}
 	}
 }
 
diff --git a/drivers/staging/rtl8192e/rtl8192e/Makefile b/drivers/staging/rtl8192e/rtl8192e/Makefile
index 313a92e..a2c4fb4 100644
--- a/drivers/staging/rtl8192e/rtl8192e/Makefile
+++ b/drivers/staging/rtl8192e/rtl8192e/Makefile
@@ -7,7 +7,6 @@
 	r8190P_rtl8256.o	\
 	rtl_cam.o		\
 	rtl_core.o		\
-	rtl_debug.o		\
 	rtl_dm.o		\
 	rtl_eeprom.o		\
 	rtl_ethtool.o		\
diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_core.c b/drivers/staging/rtl8192e/rtl8192e/rtl_core.c
index 4ebf99b..2b6c61c 100644
--- a/drivers/staging/rtl8192e/rtl8192e/rtl_core.c
+++ b/drivers/staging/rtl8192e/rtl8192e/rtl_core.c
@@ -2966,8 +2966,6 @@
 		goto err_free_irq;
 	RT_TRACE(COMP_INIT, "dev name: %s\n", dev->name);
 
-	rtl8192_proc_init_one(dev);
-
 	if (priv->polling_timer_on == 0)
 		check_rfctrl_gpio_timer((unsigned long)dev);
 
@@ -3003,7 +3001,6 @@
 		del_timer_sync(&priv->gpio_polling_timer);
 		cancel_delayed_work(&priv->gpio_change_rf_wq);
 		priv->polling_timer_on = 0;
-		rtl8192_proc_remove_one(dev);
 		rtl8192_down(dev, true);
 		deinit_hal_dm(dev);
 		if (priv->pFirmware) {
@@ -3093,7 +3090,6 @@
 	printk(KERN_INFO "\nLinux kernel driver for RTL8192E WLAN cards\n");
 	printk(KERN_INFO "Copyright (c) 2007-2008, Realsil Wlan Driver\n");
 
-	rtl8192_proc_module_init();
 	if (0 != pci_register_driver(&rtl8192_pci_driver)) {
 		DMESG("No device found");
 		/*pci_unregister_driver (&rtl8192_pci_driver);*/
@@ -3107,7 +3103,6 @@
 	pci_unregister_driver(&rtl8192_pci_driver);
 
 	RT_TRACE(COMP_DOWN, "Exiting");
-	rtl8192_proc_module_remove();
 }
 
 void check_rfctrl_gpio_timer(unsigned long data)
diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_core.h b/drivers/staging/rtl8192e/rtl8192e/rtl_core.h
index 320d5fc..87d4d34 100644
--- a/drivers/staging/rtl8192e/rtl8192e/rtl_core.h
+++ b/drivers/staging/rtl8192e/rtl8192e/rtl_core.h
@@ -1085,10 +1085,4 @@
 			   enum wireless_mode WirelessMode,
 			   struct channel_access_setting *ChnlAccessSetting);
 
-/* proc stuff from rtl_debug.c */
-void rtl8192_proc_init_one(struct net_device *dev);
-void rtl8192_proc_remove_one(struct net_device *dev);
-void rtl8192_proc_module_init(void);
-void rtl8192_proc_module_remove(void);
-
 #endif
diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_debug.c b/drivers/staging/rtl8192e/rtl8192e/rtl_debug.c
deleted file mode 100644
index c19b14c..0000000
--- a/drivers/staging/rtl8192e/rtl8192e/rtl_debug.c
+++ /dev/null
@@ -1,1029 +0,0 @@
-/******************************************************************************
- * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved.
- *
- * Based on the r8180 driver, which is:
- * Copyright 2004-2005 Andrea Merello <andreamrl@tiscali.it>, et al.
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
-******************************************************************************/
-#include "rtl_core.h"
-#include "r8192E_phy.h"
-#include "r8192E_phyreg.h"
-#include "r8190P_rtl8256.h" /* RTL8225 Radio frontend */
-#include "r8192E_cmdpkt.h"
-
-/****************************************************************************
-   -----------------------------PROCFS STUFF-------------------------
-*****************************************************************************/
-/*This part is related to PROC, which will record some statistics. */
-static struct proc_dir_entry *rtl8192_proc;
-
-static int proc_get_stats_ap(char *page, char **start,
-			  off_t offset, int count,
-			  int *eof, void *data)
-{
-	struct net_device *dev = data;
-	struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
-	struct rtllib_device *ieee = priv->rtllib;
-	struct rtllib_network *target;
-	int len = 0;
-
-	list_for_each_entry(target, &ieee->network_list, list) {
-
-		len += snprintf(page + len, count - len,
-				"%s ", target->ssid);
-
-		if (target->wpa_ie_len > 0 || target->rsn_ie_len > 0)
-			len += snprintf(page + len, count - len,
-					"WPA\n");
-		else
-			len += snprintf(page + len, count - len,
-					"non_WPA\n");
-
-	}
-
-	*eof = 1;
-	return len;
-}
-
-static int proc_get_registers_0(char *page, char **start,
-			  off_t offset, int count,
-			  int *eof, void *data)
-{
-	struct net_device *dev = data;
-
-	int len = 0;
-	int i, n, page0;
-
-	int max = 0xff;
-	page0 = 0x000;
-
-	len += snprintf(page + len, count - len,
-			"\n####################page %x##################\n ",
-			(page0>>8));
-	len += snprintf(page + len, count - len,
-			"\nD:  OF > 00 01 02 03 04 05 06 07 08 09 0A 0B "
-			"0C 0D 0E 0F");
-	for (n = 0; n <= max;) {
-		len += snprintf(page + len, count - len, "\nD:  %2x > ", n);
-		for (i = 0; i < 16 && n <= max; n++, i++)
-			len += snprintf(page + len, count - len,
-					"%2.2x ", read_nic_byte(dev,
-					(page0 | n)));
-	}
-	len += snprintf(page + len, count - len, "\n");
-	*eof = 1;
-	return len;
-
-}
-static int proc_get_registers_1(char *page, char **start,
-			  off_t offset, int count,
-			  int *eof, void *data)
-{
-	struct net_device *dev = data;
-
-	int len = 0;
-	int i, n, page0;
-
-	int max = 0xff;
-	page0 = 0x100;
-
-	/* This dump the current register page */
-	len += snprintf(page + len, count - len,
-			"\n####################page %x##################\n ",
-			(page0>>8));
-	len += snprintf(page + len, count - len,
-			"\nD:  OF > 00 01 02 03 04 05 06 07 08 09 0A 0B "
-			"0C 0D 0E 0F");
-	for (n = 0; n <= max;) {
-		len += snprintf(page + len, count - len,
-				"\nD:  %2x > ", n);
-		for (i = 0; i < 16 && n <= max; i++, n++)
-			len += snprintf(page + len, count - len,
-					"%2.2x ", read_nic_byte(dev,
-					(page0 | n)));
-	}
-	len += snprintf(page + len, count - len, "\n");
-	*eof = 1;
-	return len;
-
-}
-static int proc_get_registers_2(char *page, char **start,
-			  off_t offset, int count,
-			  int *eof, void *data)
-{
-	struct net_device *dev = data;
-
-	int len = 0;
-	int i, n, page0;
-
-	int max = 0xff;
-	page0 = 0x200;
-
-	/* This dump the current register page */
-	len += snprintf(page + len, count - len,
-			"\n####################page %x##################\n ",
-			(page0 >> 8));
-	len += snprintf(page + len, count - len,
-			"\nD:  OF > 00 01 02 03 04 05 06 07 08 09 0A 0B 0C "
-			"0D 0E 0F");
-	for (n = 0; n <= max;) {
-		len += snprintf(page + len, count - len,
-				"\nD:  %2x > ", n);
-		for (i = 0; i < 16 && n <= max; i++, n++)
-			len += snprintf(page + len, count - len,
-					"%2.2x ", read_nic_byte(dev,
-					(page0 | n)));
-	}
-	len += snprintf(page + len, count - len, "\n");
-	*eof = 1;
-	return len;
-
-}
-static int proc_get_registers_3(char *page, char **start,
-			  off_t offset, int count,
-			  int *eof, void *data)
-{
-	struct net_device *dev = data;
-
-	int len = 0;
-	int i, n, page0;
-
-	int max = 0xff;
-	page0 = 0x300;
-
-	/* This dump the current register page */
-	len += snprintf(page + len, count - len,
-			"\n####################page %x##################\n ",
-			(page0>>8));
-	len += snprintf(page + len, count - len,
-			"\nD:  OF > 00 01 02 03 04 05 06 07 08 09 0A 0B "
-			"0C 0D 0E 0F");
-	for (n = 0; n <= max;) {
-		len += snprintf(page + len, count - len,
-				"\nD:  %2x > ", n);
-		for (i = 0; i < 16 && n <= max; i++, n++)
-			len += snprintf(page + len, count - len,
-					"%2.2x ", read_nic_byte(dev,
-					(page0 | n)));
-	}
-	len += snprintf(page + len, count - len, "\n");
-	*eof = 1;
-	return len;
-
-}
-static int proc_get_registers_4(char *page, char **start,
-			  off_t offset, int count,
-			  int *eof, void *data)
-{
-	struct net_device *dev = data;
-
-	int len = 0;
-	int i, n, page0;
-
-	int max = 0xff;
-	page0 = 0x400;
-
-	/* This dump the current register page */
-	len += snprintf(page + len, count - len,
-			"\n####################page %x##################\n ",
-			(page0>>8));
-	len += snprintf(page + len, count - len,
-			"\nD:  OF > 00 01 02 03 04 05 06 07 08 09 0A 0B "
-			"0C 0D 0E 0F");
-	for (n = 0; n <= max;) {
-		len += snprintf(page + len, count - len,
-				"\nD:  %2x > ", n);
-		for (i = 0; i < 16 && n <= max; i++, n++)
-			len += snprintf(page + len, count - len,
-					"%2.2x ", read_nic_byte(dev,
-					(page0 | n)));
-	}
-	len += snprintf(page + len, count - len, "\n");
-	*eof = 1;
-	return len;
-
-}
-static int proc_get_registers_5(char *page, char **start,
-			  off_t offset, int count,
-			  int *eof, void *data)
-{
-	struct net_device *dev = data;
-
-	int len = 0;
-	int i, n, page0;
-
-	int max = 0xff;
-	page0 = 0x500;
-
-	/* This dump the current register page */
-	len += snprintf(page + len, count - len,
-			"\n####################page %x##################\n ",
-			(page0 >> 8));
-	len += snprintf(page + len, count - len,
-			"\nD:  OF > 00 01 02 03 04 05 06 07 08 09 0A 0B "
-			"0C 0D 0E 0F");
-	for (n = 0; n <= max;) {
-		len += snprintf(page + len, count - len,
-				"\nD:  %2x > ", n);
-		for (i = 0; i < 16 && n <= max; i++, n++)
-			len += snprintf(page + len, count - len,
-					"%2.2x ", read_nic_byte(dev,
-					(page0 | n)));
-	}
-	len += snprintf(page + len, count - len, "\n");
-	*eof = 1;
-	return len;
-
-}
-static int proc_get_registers_6(char *page, char **start,
-			  off_t offset, int count,
-			  int *eof, void *data)
-{
-	struct net_device *dev = data;
-
-	int len = 0;
-	int i, n, page0;
-
-	int max = 0xff;
-	page0 = 0x600;
-
-	/* This dump the current register page */
-	len += snprintf(page + len, count - len,
-			"\n####################page %x##################\n ",
-			(page0>>8));
-	len += snprintf(page + len, count - len,
-			"\nD:  OF > 00 01 02 03 04 05 06 07 08 09 0A 0B "
-			"0C 0D 0E 0F");
-	for (n = 0; n <= max;) {
-		len += snprintf(page + len, count - len,
-				"\nD:  %2x > ", n);
-		for (i = 0; i < 16 && n <= max; i++, n++)
-			len += snprintf(page + len, count - len,
-					"%2.2x ", read_nic_byte(dev,
-					(page0 | n)));
-	}
-	len += snprintf(page + len, count - len, "\n");
-	*eof = 1;
-	return len;
-
-}
-static int proc_get_registers_7(char *page, char **start,
-			  off_t offset, int count,
-			  int *eof, void *data)
-{
-	struct net_device *dev = data;
-
-	int len = 0;
-	int i, n, page0;
-
-	int max = 0xff;
-	page0 = 0x700;
-
-	/* This dump the current register page */
-	len += snprintf(page + len, count - len,
-			"\n####################page %x##################\n ",
-			(page0 >> 8));
-	len += snprintf(page + len, count - len,
-			"\nD:  OF > 00 01 02 03 04 05 06 07 08 09 0A 0B 0C "
-			"0D 0E 0F");
-	for (n = 0; n <= max;) {
-		len += snprintf(page + len, count - len,
-				"\nD:  %2x > ", n);
-		for (i = 0; i < 16 && n <= max; i++, n++)
-			len += snprintf(page + len, count - len,
-					"%2.2x ", read_nic_byte(dev,
-					(page0 | n)));
-	}
-	len += snprintf(page + len, count - len, "\n");
-	*eof = 1;
-	return len;
-
-}
-static int proc_get_registers_8(char *page, char **start,
-			  off_t offset, int count,
-			  int *eof, void *data)
-{
-	struct net_device *dev = data;
-
-	int len = 0;
-	int i, n, page0;
-
-	int max = 0xff;
-	page0 = 0x800;
-
-	/* This dump the current register page */
-	len += snprintf(page + len, count - len,
-			"\n####################page %x##################\n",
-			(page0 >> 8));
-	for (n = 0; n <= max;) {
-		len += snprintf(page + len, count - len, "\nD:  %2x > ", n);
-		for (i = 0; i < 4 && n <= max; n += 4, i++)
-			len += snprintf(page + len, count - len,
-					"%8.8x ", rtl8192_QueryBBReg(dev,
-					(page0 | n), bMaskDWord));
-	}
-	len += snprintf(page + len, count - len, "\n");
-	*eof = 1;
-	return len;
-
-}
-static int proc_get_registers_9(char *page, char **start,
-			  off_t offset, int count,
-			  int *eof, void *data)
-{
-	struct net_device *dev = data;
-
-	int len = 0;
-	int i, n, page0;
-
-	int max = 0xff;
-	page0 = 0x900;
-
-	/* This dump the current register page */
-	len += snprintf(page + len, count - len,
-			"\n####################page %x##################\n",
-			(page0>>8));
-	for (n = 0; n <= max;) {
-		len += snprintf(page + len, count - len, "\nD:  %2x > ", n);
-		for (i = 0; i < 4 && n <= max; n += 4, i++)
-			len += snprintf(page + len, count - len,
-					"%8.8x ", rtl8192_QueryBBReg(dev,
-					(page0 | n), bMaskDWord));
-	}
-	len += snprintf(page + len, count - len, "\n");
-	*eof = 1;
-	return len;
-}
-static int proc_get_registers_a(char *page, char **start,
-			  off_t offset, int count,
-			  int *eof, void *data)
-{
-	struct net_device *dev = data;
-
-	int len = 0;
-	int i, n, page0;
-
-	int max = 0xff;
-	page0 = 0xa00;
-
-	/* This dump the current register page */
-	len += snprintf(page + len, count - len,
-			"\n####################page %x##################\n",
-			(page0>>8));
-	for (n = 0; n <= max;) {
-		len += snprintf(page + len, count - len, "\nD:  %2x > ", n);
-		for (i = 0; i < 4 && n <= max; n += 4, i++)
-			len += snprintf(page + len, count - len,
-					"%8.8x ", rtl8192_QueryBBReg(dev,
-					(page0 | n), bMaskDWord));
-	}
-	len += snprintf(page + len, count - len, "\n");
-	*eof = 1;
-	return len;
-}
-static int proc_get_registers_b(char *page, char **start,
-			  off_t offset, int count,
-			  int *eof, void *data)
-{
-	struct net_device *dev = data;
-
-	int len = 0;
-	int i, n, page0;
-
-	int max = 0xff;
-	page0 = 0xb00;
-
-	/* This dump the current register page */
-	len += snprintf(page + len, count - len,
-			"\n####################page %x##################\n",
-			(page0 >> 8));
-	for (n = 0; n <= max;) {
-		len += snprintf(page + len, count - len, "\nD:  %2x > ", n);
-		for (i = 0; i < 4 && n <= max; n += 4, i++)
-			len += snprintf(page + len, count - len,
-					"%8.8x ", rtl8192_QueryBBReg(dev,
-					(page0 | n), bMaskDWord));
-	}
-	len += snprintf(page + len, count - len, "\n");
-	*eof = 1;
-	return len;
-}
-static int proc_get_registers_c(char *page, char **start,
-			  off_t offset, int count,
-			  int *eof, void *data)
-{
-	struct net_device *dev = data;
-
-	int len = 0;
-	int i, n, page0;
-
-	int max = 0xff;
-	page0 = 0xc00;
-
-	/* This dump the current register page */
-	len += snprintf(page + len, count - len,
-			"\n####################page %x##################\n",
-			(page0>>8));
-	for (n = 0; n <= max;) {
-		len += snprintf(page + len, count - len, "\nD:  %2x > ", n);
-		for (i = 0; i < 4 && n <= max; n += 4, i++)
-			len += snprintf(page + len, count - len,
-					"%8.8x ", rtl8192_QueryBBReg(dev,
-					(page0 | n), bMaskDWord));
-	}
-	len += snprintf(page + len, count - len, "\n");
-	*eof = 1;
-	return len;
-}
-static int proc_get_registers_d(char *page, char **start,
-			  off_t offset, int count,
-			  int *eof, void *data)
-{
-	struct net_device *dev = data;
-
-	int len = 0;
-	int i, n, page0;
-
-	int max = 0xff;
-	page0 = 0xd00;
-
-	/* This dump the current register page */
-	len += snprintf(page + len, count - len,
-			"\n####################page %x##################\n",
-			(page0>>8));
-	for (n = 0; n <= max;) {
-		len += snprintf(page + len, count - len, "\nD:  %2x > ", n);
-		for (i = 0; i < 4 && n <= max; n += 4, i++)
-			len += snprintf(page + len, count - len,
-					"%8.8x ", rtl8192_QueryBBReg(dev,
-					(page0 | n), bMaskDWord));
-	}
-	len += snprintf(page + len, count - len, "\n");
-	*eof = 1;
-	return len;
-}
-static int proc_get_registers_e(char *page, char **start,
-			  off_t offset, int count,
-			  int *eof, void *data)
-{
-	struct net_device *dev = data;
-
-	int len = 0;
-	int i, n, page0;
-
-	int max = 0xff;
-	page0 = 0xe00;
-
-	/* This dump the current register page */
-	len += snprintf(page + len, count - len,
-			"\n####################page %x##################\n",
-			(page0>>8));
-	for (n = 0; n <= max;) {
-		len += snprintf(page + len, count - len, "\nD:  %2x > ", n);
-		for (i = 0; i < 4 && n <= max; n += 4, i++)
-			len += snprintf(page + len, count - len,
-					"%8.8x ", rtl8192_QueryBBReg(dev,
-					(page0 | n), bMaskDWord));
-	}
-	len += snprintf(page + len, count - len, "\n");
-	*eof = 1;
-	return len;
-}
-
-static int proc_get_reg_rf_a(char *page, char **start,
-			  off_t offset, int count,
-			  int *eof, void *data)
-{
-	struct net_device *dev = data;
-
-	int len = 0;
-	int i, n;
-
-	int max = 0xff;
-
-	/* This dump the current register page */
-	len += snprintf(page + len, count - len,
-			"\n#################### RF-A ##################\n ");
-	for (n = 0; n <= max;) {
-		len += snprintf(page + len, count - len, "\nD:  %2x > ", n);
-		for (i = 0; i < 4 && n <= max; n += 4, i++)
-			len += snprintf(page + len, count - len,
-					"%8.8x ", rtl8192_phy_QueryRFReg(dev,
-					(enum rf90_radio_path)RF90_PATH_A, n,
-					bMaskDWord));
-	}
-	len += snprintf(page + len, count - len, "\n");
-	*eof = 1;
-	return len;
-}
-
-static int proc_get_reg_rf_b(char *page, char **start,
-			  off_t offset, int count,
-			  int *eof, void *data)
-{
-	struct net_device *dev = data;
-
-	int len = 0;
-	int i, n;
-
-	int max = 0xff;
-
-	/* This dump the current register page */
-	len += snprintf(page + len, count - len,
-			"\n#################### RF-B ##################\n ");
-	for (n = 0; n <= max;) {
-		len += snprintf(page + len, count - len, "\nD:  %2x > ", n);
-		for (i = 0; i < 4 && n <= max; n += 4, i++)
-			len += snprintf(page + len, count - len,
-					"%8.8x ", rtl8192_phy_QueryRFReg(dev,
-					(enum rf90_radio_path)RF90_PATH_B, n,
-					bMaskDWord));
-	}
-	len += snprintf(page + len, count - len, "\n");
-	*eof = 1;
-	return len;
-}
-
-static int proc_get_reg_rf_c(char *page, char **start,
-			  off_t offset, int count,
-			  int *eof, void *data)
-{
-	struct net_device *dev = data;
-
-	int len = 0;
-	int i, n;
-
-	int max = 0xff;
-
-	/* This dump the current register page */
-	len += snprintf(page + len, count - len,
-			"\n#################### RF-C ##################\n");
-	for (n = 0; n <= max;) {
-		len += snprintf(page + len, count - len, "\nD:  %2x > ", n);
-		for (i = 0; i < 4 && n <= max; n += 4, i++)
-			len += snprintf(page + len, count - len,
-					"%8.8x ", rtl8192_phy_QueryRFReg(dev,
-					(enum rf90_radio_path)RF90_PATH_C, n,
-					bMaskDWord));
-	}
-	len += snprintf(page + len, count - len, "\n");
-	*eof = 1;
-	return len;
-}
-
-static int proc_get_reg_rf_d(char *page, char **start,
-			  off_t offset, int count,
-			  int *eof, void *data)
-{
-	struct net_device *dev = data;
-
-	int len = 0;
-	int i, n;
-
-	int max = 0xff;
-
-	/* This dump the current register page */
-	len += snprintf(page + len, count - len,
-			"\n#################### RF-D ##################\n ");
-	for (n = 0; n <= max;) {
-		len += snprintf(page + len, count - len, "\nD:  %2x > ", n);
-		for (i = 0; i < 4 && n <= max; n += 4, i++)
-			len += snprintf(page + len, count - len,
-					"%8.8x ", rtl8192_phy_QueryRFReg(dev,
-					(enum rf90_radio_path)RF90_PATH_D, n,
-					bMaskDWord));
-	}
-	len += snprintf(page + len, count - len, "\n");
-	*eof = 1;
-	return len;
-}
-
-static int proc_get_cam_register_1(char *page, char **start,
-			  off_t offset, int count,
-			  int *eof, void *data)
-{
-	struct net_device *dev = data;
-	u32 target_command = 0;
-	u32 target_content = 0;
-	u8 entry_i = 0;
-	u32 ulStatus;
-	int len = 0;
-	int i = 100, j = 0;
-
-	/* This dump the current register page */
-	len += snprintf(page + len, count - len,
-			"\n#################### SECURITY CAM (0-10) ######"
-			"############\n ");
-	for (j = 0; j < 11; j++) {
-		len += snprintf(page + len, count - len, "\nD:  %2x > ", j);
-		for (entry_i = 0; entry_i < CAM_CONTENT_COUNT; entry_i++) {
-			target_command = entry_i+CAM_CONTENT_COUNT*j;
-			target_command = target_command | BIT31;
-
-			while ((i--) >= 0) {
-				ulStatus = read_nic_dword(dev, RWCAM);
-				if (ulStatus & BIT31)
-					continue;
-				else
-					break;
-			}
-			write_nic_dword(dev, RWCAM, target_command);
-			target_content = read_nic_dword(dev, RCAMO);
-			len += snprintf(page + len, count - len, "%8.8x ",
-					target_content);
-		}
-	}
-
-	len += snprintf(page + len, count - len, "\n");
-	*eof = 1;
-	return len;
-}
-
-static int proc_get_cam_register_2(char *page, char **start,
-			  off_t offset, int count,
-			  int *eof, void *data)
-{
-	struct net_device *dev = data;
-	u32 target_command = 0;
-	u32 target_content = 0;
-	u8 entry_i = 0;
-	u32 ulStatus;
-	int len = 0;
-	int i = 100, j = 0;
-
-	/* This dump the current register page */
-	len += snprintf(page + len, count - len,
-			"\n#################### SECURITY CAM (11-21) "
-			"##################\n ");
-	for (j = 11; j < 22; j++) {
-		len += snprintf(page + len, count - len, "\nD:  %2x > ", j);
-		for (entry_i = 0; entry_i < CAM_CONTENT_COUNT; entry_i++) {
-			target_command = entry_i + CAM_CONTENT_COUNT * j;
-			target_command = target_command | BIT31;
-
-			while ((i--) >= 0) {
-				ulStatus = read_nic_dword(dev, RWCAM);
-				if (ulStatus & BIT31)
-					continue;
-				else
-					break;
-			}
-			write_nic_dword(dev, RWCAM, target_command);
-			target_content = read_nic_dword(dev, RCAMO);
-			len += snprintf(page + len, count - len, "%8.8x ",
-					target_content);
-		}
-	}
-
-	len += snprintf(page + len, count - len, "\n");
-	*eof = 1;
-	return len;
-}
-
-static int proc_get_cam_register_3(char *page, char **start,
-			  off_t offset, int count,
-			  int *eof, void *data)
-{
-	struct net_device *dev = data;
-	u32 target_command = 0;
-	u32 target_content = 0;
-	u8 entry_i = 0;
-	u32 ulStatus;
-	int len = 0;
-	int i = 100, j = 0;
-
-	/* This dump the current register page */
-	len += snprintf(page + len, count - len,
-			"\n#################### SECURITY CAM (22-31) ######"
-			"############\n ");
-	for (j = 22; j < TOTAL_CAM_ENTRY; j++) {
-		len += snprintf(page + len, count - len, "\nD:  %2x > ", j);
-		for (entry_i = 0; entry_i < CAM_CONTENT_COUNT; entry_i++) {
-			target_command = entry_i + CAM_CONTENT_COUNT * j;
-			target_command = target_command | BIT31;
-
-			while ((i--) >= 0) {
-				ulStatus = read_nic_dword(dev, RWCAM);
-				if (ulStatus & BIT31)
-					continue;
-				else
-					break;
-			}
-			write_nic_dword(dev, RWCAM, target_command);
-			target_content = read_nic_dword(dev, RCAMO);
-			len += snprintf(page + len, count - len, "%8.8x ",
-					target_content);
-		}
-	}
-
-	len += snprintf(page + len, count - len, "\n");
-	*eof = 1;
-	return len;
-}
-static int proc_get_stats_tx(char *page, char **start,
-			  off_t offset, int count,
-			  int *eof, void *data)
-{
-	struct net_device *dev = data;
-	struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
-
-	int len = 0;
-
-	len += snprintf(page + len, count - len,
-		"TX VI priority ok int: %lu\n"
-		"TX VO priority ok int: %lu\n"
-		"TX BE priority ok int: %lu\n"
-		"TX BK priority ok int: %lu\n"
-		"TX MANAGE priority ok int: %lu\n"
-		"TX BEACON priority ok int: %lu\n"
-		"TX BEACON priority error int: %lu\n"
-		"TX CMDPKT priority ok int: %lu\n"
-		"TX queue stopped?: %d\n"
-		"TX fifo overflow: %lu\n"
-		"TX total data packets %lu\n"
-		"TX total data bytes :%lu\n",
-		priv->stats.txviokint,
-		priv->stats.txvookint,
-		priv->stats.txbeokint,
-		priv->stats.txbkokint,
-		priv->stats.txmanageokint,
-		priv->stats.txbeaconokint,
-		priv->stats.txbeaconerr,
-		priv->stats.txcmdpktokint,
-		netif_queue_stopped(dev),
-		priv->stats.txoverflow,
-		priv->rtllib->stats.tx_packets,
-		priv->rtllib->stats.tx_bytes
-
-
-		);
-
-	*eof = 1;
-	return len;
-}
-
-
-
-static int proc_get_stats_rx(char *page, char **start,
-			  off_t offset, int count,
-			  int *eof, void *data)
-{
-	struct net_device *dev = data;
-	struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
-
-	int len = 0;
-
-	len += snprintf(page + len, count - len,
-		"RX packets: %lu\n"
-		"RX data crc err: %lu\n"
-		"RX mgmt crc err: %lu\n"
-		"RX desc err: %lu\n"
-		"RX rx overflow error: %lu\n",
-		priv->stats.rxint,
-		priv->stats.rxdatacrcerr,
-		priv->stats.rxmgmtcrcerr,
-		priv->stats.rxrdu,
-		priv->stats.rxoverflow);
-
-	*eof = 1;
-	return len;
-}
-
-void rtl8192_proc_module_init(void)
-{
-	RT_TRACE(COMP_INIT, "Initializing proc filesystem");
-	rtl8192_proc = create_proc_entry(DRV_NAME, S_IFDIR, init_net.proc_net);
-}
-
-
-void rtl8192_proc_module_remove(void)
-{
-	remove_proc_entry(DRV_NAME, init_net.proc_net);
-}
-
-
-void rtl8192_proc_remove_one(struct net_device *dev)
-{
-	struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
-
-	printk(KERN_INFO "dev name %s\n", dev->name);
-
-	if (priv->dir_dev) {
-		remove_proc_entry("stats-tx", priv->dir_dev);
-		remove_proc_entry("stats-rx", priv->dir_dev);
-		remove_proc_entry("stats-ap", priv->dir_dev);
-		remove_proc_entry("registers-0", priv->dir_dev);
-		remove_proc_entry("registers-1", priv->dir_dev);
-		remove_proc_entry("registers-2", priv->dir_dev);
-		remove_proc_entry("registers-3", priv->dir_dev);
-		remove_proc_entry("registers-4", priv->dir_dev);
-		remove_proc_entry("registers-5", priv->dir_dev);
-		remove_proc_entry("registers-6", priv->dir_dev);
-		remove_proc_entry("registers-7", priv->dir_dev);
-		remove_proc_entry("registers-8", priv->dir_dev);
-		remove_proc_entry("registers-9", priv->dir_dev);
-		remove_proc_entry("registers-a", priv->dir_dev);
-		remove_proc_entry("registers-b", priv->dir_dev);
-		remove_proc_entry("registers-c", priv->dir_dev);
-		remove_proc_entry("registers-d", priv->dir_dev);
-		remove_proc_entry("registers-e", priv->dir_dev);
-		remove_proc_entry("RF-A", priv->dir_dev);
-		remove_proc_entry("RF-B", priv->dir_dev);
-		remove_proc_entry("RF-C", priv->dir_dev);
-		remove_proc_entry("RF-D", priv->dir_dev);
-		remove_proc_entry("SEC-CAM-1", priv->dir_dev);
-		remove_proc_entry("SEC-CAM-2", priv->dir_dev);
-		remove_proc_entry("SEC-CAM-3", priv->dir_dev);
-		remove_proc_entry("wlan0", rtl8192_proc);
-		priv->dir_dev = NULL;
-	}
-}
-
-
-void rtl8192_proc_init_one(struct net_device *dev)
-{
-	struct proc_dir_entry *e;
-	struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
-
-	priv->dir_dev = create_proc_entry(dev->name,
-					  S_IFDIR | S_IRUGO | S_IXUGO,
-					  rtl8192_proc);
-	if (!priv->dir_dev) {
-		RT_TRACE(COMP_ERR, "Unable to initialize /proc/net/rtl8192"
-			 "/%s\n", dev->name);
-		return;
-	}
-	e = create_proc_read_entry("stats-rx", S_IFREG | S_IRUGO,
-				   priv->dir_dev, proc_get_stats_rx, dev);
-
-	if (!e)
-		RT_TRACE(COMP_ERR, "Unable to initialize "
-		      "/proc/net/rtl8192/%s/stats-rx\n",
-		      dev->name);
-
-	e = create_proc_read_entry("stats-tx", S_IFREG | S_IRUGO,
-				   priv->dir_dev, proc_get_stats_tx, dev);
-
-	if (!e)
-		RT_TRACE(COMP_ERR, "Unable to initialize "
-		      "/proc/net/rtl8192/%s/stats-tx\n",
-		      dev->name);
-
-	e = create_proc_read_entry("stats-ap", S_IFREG | S_IRUGO,
-				   priv->dir_dev, proc_get_stats_ap, dev);
-
-	if (!e)
-		RT_TRACE(COMP_ERR, "Unable to initialize "
-		      "/proc/net/rtl8192/%s/stats-ap\n",
-		      dev->name);
-
-	e = create_proc_read_entry("registers-0", S_IFREG | S_IRUGO,
-				   priv->dir_dev, proc_get_registers_0, dev);
-	if (!e)
-		RT_TRACE(COMP_ERR, "Unable to initialize "
-		      "/proc/net/rtl8192/%s/registers-0\n",
-		      dev->name);
-	e = create_proc_read_entry("registers-1", S_IFREG | S_IRUGO,
-				   priv->dir_dev, proc_get_registers_1, dev);
-	if (!e)
-		RT_TRACE(COMP_ERR, "Unable to initialize "
-		      "/proc/net/rtl8192/%s/registers-1\n",
-		      dev->name);
-	e = create_proc_read_entry("registers-2", S_IFREG | S_IRUGO,
-				   priv->dir_dev, proc_get_registers_2, dev);
-	if (!e)
-		RT_TRACE(COMP_ERR, "Unable to initialize "
-		      "/proc/net/rtl8192/%s/registers-2\n",
-		      dev->name);
-	e = create_proc_read_entry("registers-3", S_IFREG | S_IRUGO,
-				   priv->dir_dev, proc_get_registers_3, dev);
-	if (!e)
-		RT_TRACE(COMP_ERR, "Unable to initialize "
-		      "/proc/net/rtl8192/%s/registers-3\n",
-		      dev->name);
-	e = create_proc_read_entry("registers-4", S_IFREG | S_IRUGO,
-				   priv->dir_dev, proc_get_registers_4, dev);
-	if (!e)
-		RT_TRACE(COMP_ERR, "Unable to initialize "
-		      "/proc/net/rtl8192/%s/registers-4\n",
-		      dev->name);
-	e = create_proc_read_entry("registers-5", S_IFREG | S_IRUGO,
-				   priv->dir_dev, proc_get_registers_5, dev);
-	if (!e)
-		RT_TRACE(COMP_ERR, "Unable to initialize "
-		      "/proc/net/rtl8192/%s/registers-5\n",
-		      dev->name);
-	e = create_proc_read_entry("registers-6", S_IFREG | S_IRUGO,
-				   priv->dir_dev, proc_get_registers_6, dev);
-	if (!e)
-		RT_TRACE(COMP_ERR, "Unable to initialize "
-		      "/proc/net/rtl8192/%s/registers-6\n",
-		      dev->name);
-	e = create_proc_read_entry("registers-7", S_IFREG | S_IRUGO,
-				   priv->dir_dev, proc_get_registers_7, dev);
-	if (!e)
-		RT_TRACE(COMP_ERR, "Unable to initialize "
-		      "/proc/net/rtl8192/%s/registers-7\n",
-		      dev->name);
-	e = create_proc_read_entry("registers-8", S_IFREG | S_IRUGO,
-				   priv->dir_dev, proc_get_registers_8, dev);
-	if (!e)
-		RT_TRACE(COMP_ERR, "Unable to initialize "
-		      "/proc/net/rtl8192/%s/registers-8\n",
-		      dev->name);
-	e = create_proc_read_entry("registers-9", S_IFREG | S_IRUGO,
-				   priv->dir_dev, proc_get_registers_9, dev);
-	if (!e)
-		RT_TRACE(COMP_ERR, "Unable to initialize "
-		      "/proc/net/rtl8192/%s/registers-9\n",
-		      dev->name);
-	e = create_proc_read_entry("registers-a", S_IFREG | S_IRUGO,
-				   priv->dir_dev, proc_get_registers_a, dev);
-	if (!e)
-		RT_TRACE(COMP_ERR, "Unable to initialize "
-		      "/proc/net/rtl8192/%s/registers-a\n",
-		      dev->name);
-	e = create_proc_read_entry("registers-b", S_IFREG | S_IRUGO,
-				   priv->dir_dev, proc_get_registers_b, dev);
-	if (!e)
-		RT_TRACE(COMP_ERR, "Unable to initialize "
-		      "/proc/net/rtl8192/%s/registers-b\n",
-		      dev->name);
-	e = create_proc_read_entry("registers-c", S_IFREG | S_IRUGO,
-				   priv->dir_dev, proc_get_registers_c, dev);
-	if (!e)
-		RT_TRACE(COMP_ERR, "Unable to initialize "
-		      "/proc/net/rtl8192/%s/registers-c\n",
-		      dev->name);
-	e = create_proc_read_entry("registers-d", S_IFREG | S_IRUGO,
-				   priv->dir_dev, proc_get_registers_d, dev);
-	if (!e)
-		RT_TRACE(COMP_ERR, "Unable to initialize "
-		      "/proc/net/rtl8192/%s/registers-d\n",
-		      dev->name);
-	e = create_proc_read_entry("registers-e", S_IFREG | S_IRUGO,
-				   priv->dir_dev, proc_get_registers_e, dev);
-	if (!e)
-		RT_TRACE(COMP_ERR, "Unable to initialize "
-		      "/proc/net/rtl8192/%s/registers-e\n",
-		      dev->name);
-	e = create_proc_read_entry("RF-A", S_IFREG | S_IRUGO,
-				   priv->dir_dev, proc_get_reg_rf_a, dev);
-	if (!e)
-		RT_TRACE(COMP_ERR, "Unable to initialize "
-		      "/proc/net/rtl8192/%s/RF-A\n",
-		      dev->name);
-	e = create_proc_read_entry("RF-B", S_IFREG | S_IRUGO,
-				   priv->dir_dev, proc_get_reg_rf_b, dev);
-	if (!e)
-		RT_TRACE(COMP_ERR, "Unable to initialize "
-		      "/proc/net/rtl8192/%s/RF-B\n",
-		      dev->name);
-	e = create_proc_read_entry("RF-C", S_IFREG | S_IRUGO,
-				   priv->dir_dev, proc_get_reg_rf_c, dev);
-	if (!e)
-		RT_TRACE(COMP_ERR, "Unable to initialize "
-		      "/proc/net/rtl8192/%s/RF-C\n",
-		      dev->name);
-	e = create_proc_read_entry("RF-D", S_IFREG | S_IRUGO,
-				   priv->dir_dev, proc_get_reg_rf_d, dev);
-	if (!e)
-		RT_TRACE(COMP_ERR, "Unable to initialize "
-		      "/proc/net/rtl8192/%s/RF-D\n",
-		      dev->name);
-	e = create_proc_read_entry("SEC-CAM-1", S_IFREG | S_IRUGO,
-				   priv->dir_dev, proc_get_cam_register_1, dev);
-	if (!e)
-		RT_TRACE(COMP_ERR, "Unable to initialize "
-		      "/proc/net/rtl8192/%s/SEC-CAM-1\n",
-		      dev->name);
-	e = create_proc_read_entry("SEC-CAM-2", S_IFREG | S_IRUGO,
-				   priv->dir_dev, proc_get_cam_register_2, dev);
-	if (!e)
-		RT_TRACE(COMP_ERR, "Unable to initialize "
-		      "/proc/net/rtl8192/%s/SEC-CAM-2\n",
-		      dev->name);
-	e = create_proc_read_entry("SEC-CAM-3", S_IFREG | S_IRUGO,
-				   priv->dir_dev, proc_get_cam_register_3, dev);
-	if (!e)
-		RT_TRACE(COMP_ERR, "Unable to initialize "
-		      "/proc/net/rtl8192/%s/SEC-CAM-3\n",
-		      dev->name);
-}
diff --git a/drivers/staging/rtl8192e/rtllib_crypt_ccmp.c b/drivers/staging/rtl8192e/rtllib_crypt_ccmp.c
index 4217b88..e51cb49 100644
--- a/drivers/staging/rtl8192e/rtllib_crypt_ccmp.c
+++ b/drivers/staging/rtl8192e/rtllib_crypt_ccmp.c
@@ -412,19 +412,18 @@
 }
 
 
-static char *rtllib_ccmp_print_stats(char *p, void *priv)
+static void rtllib_ccmp_print_stats(struct seq_file *m, void *priv)
 {
 	struct rtllib_ccmp_data *ccmp = priv;
-	p += sprintf(p, "key[%d] alg=CCMP key_set=%d "
-		     "tx_pn=%pM rx_pn=%pM "
-		     "format_errors=%d replays=%d decrypt_errors=%d\n",
-		     ccmp->key_idx, ccmp->key_set,
-		     ccmp->tx_pn, ccmp->rx_pn,
-		     ccmp->dot11RSNAStatsCCMPFormatErrors,
-		     ccmp->dot11RSNAStatsCCMPReplays,
-		     ccmp->dot11RSNAStatsCCMPDecryptErrors);
-
-	return p;
+	seq_printf(m,
+		   "key[%d] alg=CCMP key_set=%d "
+		   "tx_pn=%pM rx_pn=%pM "
+		   "format_errors=%d replays=%d decrypt_errors=%d\n",
+		   ccmp->key_idx, ccmp->key_set,
+		   ccmp->tx_pn, ccmp->rx_pn,
+		   ccmp->dot11RSNAStatsCCMPFormatErrors,
+		   ccmp->dot11RSNAStatsCCMPReplays,
+		   ccmp->dot11RSNAStatsCCMPDecryptErrors);
 }
 
 static struct lib80211_crypto_ops rtllib_crypt_ccmp = {
diff --git a/drivers/staging/rtl8192e/rtllib_crypt_tkip.c b/drivers/staging/rtl8192e/rtllib_crypt_tkip.c
index 8009250..5cfd73b 100644
--- a/drivers/staging/rtl8192e/rtllib_crypt_tkip.c
+++ b/drivers/staging/rtl8192e/rtllib_crypt_tkip.c
@@ -708,30 +708,30 @@
 }
 
 
-static char *rtllib_tkip_print_stats(char *p, void *priv)
+static void rtllib_tkip_print_stats(struct seq_file *m, void *priv)
 {
 	struct rtllib_tkip_data *tkip = priv;
-	p += sprintf(p, "key[%d] alg=TKIP key_set=%d "
-		     "tx_pn=%02x%02x%02x%02x%02x%02x "
-		     "rx_pn=%02x%02x%02x%02x%02x%02x "
-		     "replays=%d icv_errors=%d local_mic_failures=%d\n",
-		     tkip->key_idx, tkip->key_set,
-		     (tkip->tx_iv32 >> 24) & 0xff,
-		     (tkip->tx_iv32 >> 16) & 0xff,
-		     (tkip->tx_iv32 >> 8) & 0xff,
-		     tkip->tx_iv32 & 0xff,
-		     (tkip->tx_iv16 >> 8) & 0xff,
-		     tkip->tx_iv16 & 0xff,
-		     (tkip->rx_iv32 >> 24) & 0xff,
-		     (tkip->rx_iv32 >> 16) & 0xff,
-		     (tkip->rx_iv32 >> 8) & 0xff,
-		     tkip->rx_iv32 & 0xff,
-		     (tkip->rx_iv16 >> 8) & 0xff,
-		     tkip->rx_iv16 & 0xff,
-		     tkip->dot11RSNAStatsTKIPReplays,
-		     tkip->dot11RSNAStatsTKIPICVErrors,
-		     tkip->dot11RSNAStatsTKIPLocalMICFailures);
-	return p;
+	seq_printf(m,
+		   "key[%d] alg=TKIP key_set=%d "
+		   "tx_pn=%02x%02x%02x%02x%02x%02x "
+		   "rx_pn=%02x%02x%02x%02x%02x%02x "
+		   "replays=%d icv_errors=%d local_mic_failures=%d\n",
+		   tkip->key_idx, tkip->key_set,
+		   (tkip->tx_iv32 >> 24) & 0xff,
+		   (tkip->tx_iv32 >> 16) & 0xff,
+		   (tkip->tx_iv32 >> 8) & 0xff,
+		   tkip->tx_iv32 & 0xff,
+		   (tkip->tx_iv16 >> 8) & 0xff,
+		   tkip->tx_iv16 & 0xff,
+		   (tkip->rx_iv32 >> 24) & 0xff,
+		   (tkip->rx_iv32 >> 16) & 0xff,
+		   (tkip->rx_iv32 >> 8) & 0xff,
+		   tkip->rx_iv32 & 0xff,
+		   (tkip->rx_iv16 >> 8) & 0xff,
+		   tkip->rx_iv16 & 0xff,
+		   tkip->dot11RSNAStatsTKIPReplays,
+		   tkip->dot11RSNAStatsTKIPICVErrors,
+		   tkip->dot11RSNAStatsTKIPLocalMICFailures);
 }
 
 static struct lib80211_crypto_ops rtllib_crypt_tkip = {
diff --git a/drivers/staging/rtl8192e/rtllib_crypt_wep.c b/drivers/staging/rtl8192e/rtllib_crypt_wep.c
index 8cdf389..c4df6e0 100644
--- a/drivers/staging/rtl8192e/rtllib_crypt_wep.c
+++ b/drivers/staging/rtl8192e/rtllib_crypt_wep.c
@@ -247,12 +247,10 @@
 }
 
 
-static char *prism2_wep_print_stats(char *p, void *priv)
+static void prism2_wep_print_stats(struct seq_file *m, void *priv)
 {
 	struct prism2_wep_data *wep = priv;
-	p += sprintf(p, "key[%d] alg=WEP len=%d\n",
-		     wep->key_idx, wep->key_len);
-	return p;
+	seq_printf(m, "key[%d] alg=WEP len=%d\n", wep->key_idx, wep->key_len);
 }
 
 static struct lib80211_crypto_ops rtllib_crypt_wep = {
diff --git a/drivers/staging/rtl8192e/rtllib_module.c b/drivers/staging/rtl8192e/rtllib_module.c
index f9dae95..84ea721 100644
--- a/drivers/staging/rtl8192e/rtllib_module.c
+++ b/drivers/staging/rtl8192e/rtllib_module.c
@@ -208,61 +208,51 @@
 			    ;
 static struct proc_dir_entry *rtllib_proc;
 
-static int show_debug_level(char *page, char **start, off_t offset,
-			    int count, int *eof, void *data)
+static int show_debug_level(struct seq_file *m, void *v)
 {
-	return snprintf(page, count, "0x%08X\n", rtllib_debug_level);
+	return seq_printf(m, "0x%08X\n", rtllib_debug_level);
 }
 
-static int store_debug_level(struct file *file, const char __user *buffer,
-			     unsigned long count, void *data)
+static ssize_t write_debug_level(struct file *file, const char __user *buffer,
+			     size_t count, loff_t *ppos)
 {
-	char buf[] = "0x00000000";
-	unsigned long len = min((unsigned long)sizeof(buf) - 1, count);
-	char *p = (char *)buf;
 	unsigned long val;
-
-	if (copy_from_user(buf, buffer, len))
-		return count;
-	buf[len] = 0;
-	if (p[1] == 'x' || p[1] == 'X' || p[0] == 'x' || p[0] == 'X') {
-		p++;
-		if (p[0] == 'x' || p[0] == 'X')
-			p++;
-		val = simple_strtoul(p, &p, 16);
-	} else
-		val = simple_strtoul(p, &p, 10);
-	if (p == buf)
-		printk(KERN_INFO DRV_NAME
-		       ": %s is not in hex or decimal form.\n", buf);
-	else
-		rtllib_debug_level = val;
-
-	return strnlen(buf, count);
+	int err = kstrtoul_from_user(buffer, count, 0, &val);
+	if (err)
+		return err;
+	rtllib_debug_level = val;
+	return count;
 }
 
+static int open_debug_level(struct inode *inode, struct file *file)
+{
+	return single_open(file, show_debug_level, NULL);
+}
+
+static const struct file_operations fops = {
+	.open = open_debug_level,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.write = write_debug_level
+};
+
 int __init rtllib_init(void)
 {
 	struct proc_dir_entry *e;
 
 	rtllib_debug_level = debug;
-	rtllib_proc = create_proc_entry(DRV_NAME, S_IFDIR, init_net.proc_net);
+	rtllib_proc = proc_mkdir(DRV_NAME, init_net.proc_net);
 	if (rtllib_proc == NULL) {
 		RTLLIB_ERROR("Unable to create " DRV_NAME
 				" proc directory\n");
 		return -EIO;
 	}
-	e = create_proc_entry("debug_level", S_IFREG | S_IRUGO | S_IWUSR,
-			      rtllib_proc);
+	e = proc_create("debug_level", S_IRUGO | S_IWUSR, rtllib_proc, &fops);
 	if (!e) {
 		remove_proc_entry(DRV_NAME, init_net.proc_net);
 		rtllib_proc = NULL;
 		return -EIO;
 	}
-	e->read_proc = show_debug_level;
-	e->write_proc = store_debug_level;
-	e->data = NULL;
-
 	return 0;
 }
 
diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_module.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_module.c
index 76c56e5..e0870c0 100644
--- a/drivers/staging/rtl8192u/ieee80211/ieee80211_module.c
+++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_module.c
@@ -243,39 +243,34 @@
 			    ;
 struct proc_dir_entry *ieee80211_proc;
 
-static int show_debug_level(char *page, char **start, off_t offset,
-			    int count, int *eof, void *data)
+static int show_debug_level(struct seq_file *m, void *v)
 {
-	return snprintf(page, count, "0x%08X\n", ieee80211_debug_level);
+	return seq_printf(m, "0x%08X\n", ieee80211_debug_level);
 }
 
-static int store_debug_level(struct file *file, const char *buffer,
-			     unsigned long count, void *data)
+static ssize_t write_debug_level(struct file *file, const char __user *buffer,
+			     size_t count, loff_t *ppos)
 {
-	char buf[] = "0x00000000";
-	unsigned long len = min_t(unsigned long, sizeof(buf) - 1, count);
-	char *p = (char *)buf;
 	unsigned long val;
-
-	if (copy_from_user(buf, buffer, len))
-		return count;
-	buf[len] = 0;
-	if (p[1] == 'x' || p[1] == 'X' || p[0] == 'x' || p[0] == 'X') {
-		p++;
-		if (p[0] == 'x' || p[0] == 'X')
-			p++;
-		val = simple_strtoul(p, &p, 16);
-	} else
-		val = simple_strtoul(p, &p, 10);
-	if (p == buf)
-		printk(KERN_INFO DRV_NAME
-		       ": %s is not in hex or decimal form.\n", buf);
-	else
-		ieee80211_debug_level = val;
-
-	return strnlen(buf, count);
+	int err = kstrtoul_from_user(buffer, count, 0, &val);
+	if (err)
+		return err;
+	ieee80211_debug_level = val;
+	return count;
 }
 
+static int open_debug_level(struct inode *inode, struct file *file)
+{
+	return single_open(file, show_debug_level, NULL);
+}
+
+static const struct file_operations fops = {
+	.open = open_debug_level,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.write = write_debug_level
+};
+
 int __init ieee80211_debug_init(void)
 {
 	struct proc_dir_entry *e;
@@ -288,17 +283,13 @@
 				" proc directory\n");
 		return -EIO;
 	}
-	e = create_proc_entry("debug_level", S_IFREG | S_IRUGO | S_IWUSR,
-			      ieee80211_proc);
+	e = proc_create("debug_level", S_IRUGO | S_IWUSR, 
+			      ieee80211_proc, &fops);
 	if (!e) {
 		remove_proc_entry(DRV_NAME, init_net.proc_net);
 		ieee80211_proc = NULL;
 		return -EIO;
 	}
-	e->read_proc = show_debug_level;
-	e->write_proc = store_debug_level;
-	e->data = NULL;
-
 	return 0;
 }
 
diff --git a/drivers/staging/rtl8192u/ieee80211/proc.c b/drivers/staging/rtl8192u/ieee80211/proc.c
index 6eda928..c426dfd 100644
--- a/drivers/staging/rtl8192u/ieee80211/proc.c
+++ b/drivers/staging/rtl8192u/ieee80211/proc.c
@@ -99,7 +99,7 @@
 	return seq_open(file, &crypto_seq_ops);
 }
 
-static struct file_operations proc_crypto_ops = {
+static const struct file_operations proc_crypto_ops = {
 	.open		= crypto_info_open,
 	.read		= seq_read,
 	.llseek		= seq_lseek,
@@ -108,9 +108,5 @@
 
 void __init crypto_init_proc(void)
 {
-	struct proc_dir_entry *proc;
-
-	proc = create_proc_entry("crypto", 0, NULL);
-	if (proc)
-		proc->proc_fops = &proc_crypto_ops;
+	proc_create("crypto", 0, NULL, &proc_crypto_ops);
 }
diff --git a/drivers/staging/rtl8192u/r8192U.h b/drivers/staging/rtl8192u/r8192U.h
index e538e02..bedeb33 100644
--- a/drivers/staging/rtl8192u/r8192U.h
+++ b/drivers/staging/rtl8192u/r8192U.h
@@ -946,7 +946,6 @@
 	/*stats*/
 	struct Stats stats;
 	struct iw_statistics wstats;
-	struct proc_dir_entry *dir_dev;
 
 	/*RX stuff*/
 //	u32 *rxring;
diff --git a/drivers/staging/rtl8192u/r8192U_core.c b/drivers/staging/rtl8192u/r8192U_core.c
index f7de2f6..1459233 100644
--- a/drivers/staging/rtl8192u/r8192U_core.c
+++ b/drivers/staging/rtl8192u/r8192U_core.c
@@ -71,6 +71,8 @@
 //#include "r8192xU_phyreg.h"
 #include <linux/usb.h>
 #include <linux/slab.h>
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
 // FIXME: check if 2.6.7 is ok
 
 #ifdef CONFIG_RTL8192_PM
@@ -472,103 +474,73 @@
 
 static struct proc_dir_entry *rtl8192_proc;
 
-static int proc_get_stats_ap(char *page, char **start, off_t offset, int count,
-							int *eof, void *data)
+static int proc_get_stats_ap(struct seq_file *m, void *v)
 {
-	struct net_device *dev = data;
+	struct net_device *dev = m->private;
 	struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
 	struct ieee80211_device *ieee = priv->ieee80211;
 	struct ieee80211_network *target;
 
-	int len = 0;
-
 	list_for_each_entry(target, &ieee->network_list, list) {
-
-		len += snprintf(page + len, count - len, "%s ", target->ssid);
-
+		const char *wpa = "non_WPA";
 		if (target->wpa_ie_len > 0 || target->rsn_ie_len > 0)
-			len += snprintf(page + len, count - len, "WPA\n");
-		else
-			len += snprintf(page + len, count - len, "non_WPA\n");
+			wpa = "WPA";
+
+		seq_printf(m, "%s %s\n", target->ssid, wpa);
 	}
 
-	*eof = 1;
-	return len;
+	return 0;
 }
 
-static int proc_get_registers(char *page, char **start,
-			  off_t offset, int count,
-			  int *eof, void *data)
+static int proc_get_registers(struct seq_file *m, void *v)
 {
-	struct net_device *dev = data;
-//	struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
+	struct net_device *dev = m->private;
+	int i,n, max = 0xff;
 
-	int len = 0;
-	int i,n;
-
-	int max=0xff;
-
-	/* This dump the current register page */
-	len += snprintf(page + len, count - len,
-			"\n####################page 0##################\n ");
+	seq_puts(m, "\n####################page 0##################\n ");
 
 	for (n=0;n<=max;) {
 		//printk( "\nD: %2x> ", n);
-		len += snprintf(page + len, count - len,
-			"\nD:  %2x > ",n);
+		seq_printf(m, "\nD:  %2x > ",n);
 
 		for (i=0;i<16 && n<=max;i++,n++)
-			len += snprintf(page + len, count - len,
-					"%2x ",read_nic_byte(dev,0x000|n));
+			seq_printf(m, "%2x ",read_nic_byte(dev,0x000|n));
 
 		//	printk("%2x ",read_nic_byte(dev,n));
 	}
-	len += snprintf(page + len, count - len,
-			"\n####################page 1##################\n ");
+
+	seq_puts(m, "\n####################page 1##################\n ");
 	for (n=0;n<=max;) {
 		//printk( "\nD: %2x> ", n);
-		len += snprintf(page + len, count - len,
-				"\nD:  %2x > ",n);
+		seq_printf(m, "\nD:  %2x > ",n);
 
 		for (i=0;i<16 && n<=max;i++,n++)
-			len += snprintf(page + len, count - len,
-					"%2x ",read_nic_byte(dev,0x100|n));
+			seq_printf(m, "%2x ",read_nic_byte(dev,0x100|n));
 
 		//      printk("%2x ",read_nic_byte(dev,n));
 	}
-	len += snprintf(page + len, count - len,
-			"\n####################page 3##################\n ");
+
+	seq_puts(m, "\n####################page 3##################\n ");
 	for (n=0;n<=max;) {
 		//printk( "\nD: %2x> ", n);
-		len += snprintf(page + len, count - len,
-			"\nD:  %2x > ",n);
+		seq_printf(m, "\nD:  %2x > ",n);
 
 		for(i=0;i<16 && n<=max;i++,n++)
-			len += snprintf(page + len, count - len,
-					"%2x ",read_nic_byte(dev,0x300|n));
+			seq_printf(m, "%2x ",read_nic_byte(dev,0x300|n));
 
 		//      printk("%2x ",read_nic_byte(dev,n));
 	}
 
-	len += snprintf(page + len, count - len,"\n");
-	*eof = 1;
-	return len;
+	seq_putc(m, '\n');
+	return 0;
 }
 
-
-
-
-
-static int proc_get_stats_tx(char *page, char **start,
-			  off_t offset, int count,
-			  int *eof, void *data)
+static int proc_get_stats_tx(struct seq_file *m, void *v)
 {
-	struct net_device *dev = data;
+	struct net_device *dev = m->private;
 	struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
 
-	int len = 0;
-
-	len += snprintf(page + len, count - len,
+	seq_printf(m,
 		"TX VI priority ok int: %lu\n"
 		"TX VI priority error int: %lu\n"
 		"TX VO priority ok int: %lu\n"
@@ -629,22 +601,15 @@
 //		priv->stats.txbeaconerr
 		);
 
-	*eof = 1;
-	return len;
+	return 0;
 }
 
-
-
-static int proc_get_stats_rx(char *page, char **start,
-			  off_t offset, int count,
-			  int *eof, void *data)
+static int proc_get_stats_rx(struct seq_file *m, void *v)
 {
-	struct net_device *dev = data;
+	struct net_device *dev = m->private;
 	struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
 
-	int len = 0;
-
-	len += snprintf(page + len, count - len,
+	seq_printf(m,
 		"RX packets: %lu\n"
 		"RX urb status error: %lu\n"
 		"RX invalid urb error: %lu\n",
@@ -652,9 +617,9 @@
 		priv->stats.rxstaterr,
 		priv->stats.rxurberr);
 
-	*eof = 1;
-	return len;
+	return 0;
 }
+
 void rtl8192_proc_module_init(void)
 {
 	RT_TRACE(COMP_INIT, "Initializing proc filesystem");
@@ -667,74 +632,70 @@
 	remove_proc_entry(RTL819xU_MODULE_NAME, init_net.proc_net);
 }
 
-
-void rtl8192_proc_remove_one(struct net_device *dev)
+/*
+ * seq_file wrappers for procfile show routines.
+ */
+static int rtl8192_proc_open(struct inode *inode, struct file *file)
 {
-	struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
+	struct net_device *dev = proc_get_parent_data(inode);
+	int (*show)(struct seq_file *, void *) = PDE_DATA(inode);
 
-
-	if (priv->dir_dev) {
-	//	remove_proc_entry("stats-hw", priv->dir_dev);
-		remove_proc_entry("stats-tx", priv->dir_dev);
-		remove_proc_entry("stats-rx", priv->dir_dev);
-	//	remove_proc_entry("stats-ieee", priv->dir_dev);
-		remove_proc_entry("stats-ap", priv->dir_dev);
-		remove_proc_entry("registers", priv->dir_dev);
-	//	remove_proc_entry("cck-registers",priv->dir_dev);
-	//	remove_proc_entry("ofdm-registers",priv->dir_dev);
-		//remove_proc_entry(dev->name, rtl8192_proc);
-		remove_proc_entry("wlan0", rtl8192_proc);
-		priv->dir_dev = NULL;
-	}
+	return single_open(file, show, dev);
 }
 
+static const struct file_operations rtl8192_proc_fops = {
+	.open		= rtl8192_proc_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= seq_release,
+};
+
+/*
+ * Table of proc files we need to create.
+ */
+struct rtl8192_proc_file {
+	char name[12];
+	int (*show)(struct seq_file *, void *);
+};
+
+static const struct rtl8192_proc_file rtl8192_proc_files[] = {
+	{ "stats-rx",	&proc_get_stats_rx },
+	{ "stats-tx",	&proc_get_stats_tx },
+	{ "stats-ap",	&proc_get_stats_ap },
+	{ "registers",	&proc_get_registers },
+	{ "" }
+};
 
 void rtl8192_proc_init_one(struct net_device *dev)
 {
-	struct proc_dir_entry *e;
-	struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
-	priv->dir_dev = proc_mkdir(dev->name, rtl8192_proc);
-	if (!priv->dir_dev) {
-		RT_TRACE(COMP_ERR, "Unable to initialize /proc/net/rtl8192/%s\n",
-		      dev->name);
-		return;
-	}
-	e = create_proc_read_entry("stats-rx", S_IFREG | S_IRUGO,
-				   priv->dir_dev, proc_get_stats_rx, dev);
+	const struct rtl8192_proc_file *f;
+	struct proc_dir_entry *dir;
 
-	if (!e) {
-		RT_TRACE(COMP_ERR,"Unable to initialize "
-		      "/proc/net/rtl8192/%s/stats-rx\n",
-		      dev->name);
-	}
+	if (rtl8192_proc) {
+		dir = proc_mkdir_data(dev->name, 0, rtl8192_proc, dev);
+		if (!dir) {
+			RT_TRACE(COMP_ERR, "Unable to initialize /proc/net/rtl8192/%s\n",
+				 dev->name);
+			return;
+		}
 
-
-	e = create_proc_read_entry("stats-tx", S_IFREG | S_IRUGO,
-				   priv->dir_dev, proc_get_stats_tx, dev);
-
-	if (!e) {
-		RT_TRACE(COMP_ERR, "Unable to initialize "
-		      "/proc/net/rtl8192/%s/stats-tx\n",
-		      dev->name);
-	}
-
-	e = create_proc_read_entry("stats-ap", S_IFREG | S_IRUGO,
-				   priv->dir_dev, proc_get_stats_ap, dev);
-
-	if (!e) {
-		RT_TRACE(COMP_ERR, "Unable to initialize "
-		      "/proc/net/rtl8192/%s/stats-ap\n",
-		      dev->name);
-	}
-
-	e = create_proc_read_entry("registers", S_IFREG | S_IRUGO,
-				   priv->dir_dev, proc_get_registers, dev);
-	if (!e) {
-		RT_TRACE(COMP_ERR, "Unable to initialize "
-		      "/proc/net/rtl8192/%s/registers\n",
-		      dev->name);
+		for (f = rtl8192_proc_files; f->name[0]; f++) {
+			if (!proc_create_data(f->name, S_IFREG | S_IRUGO, dir,
+					      &rtl8192_proc_fops, f->show)) {
+				RT_TRACE(COMP_ERR, "Unable to initialize "
+					 "/proc/net/rtl8192/%s/%s\n",
+					 dev->name, f->name);
+				return;
+			}
+		}
 	}
 }
+
+void rtl8192_proc_remove_one(struct net_device *dev)
+{
+	remove_proc_subtree(dev->name, rtl8192_proc);
+}
+
 /****************************************************************************
    -----------------------------MISC STUFF-------------------------
 *****************************************************************************/
diff --git a/drivers/staging/rts5139/rts51x_scsi.c b/drivers/staging/rts5139/rts51x_scsi.c
index b58f1df..6108705 100644
--- a/drivers/staging/rts5139/rts51x_scsi.c
+++ b/drivers/staging/rts5139/rts51x_scsi.c
@@ -1968,18 +1968,16 @@
 
 /* we use this macro to help us write into the buffer */
 #undef SPRINTF
-#define SPRINTF(args...) \
-	do { if (pos < buffer+length) pos += sprintf(pos, ## args); } while (0)
+#define SPRINTF(args...) seq_printf(m, ##args)
 
-int proc_info(struct Scsi_Host *host, char *buffer,
-	      char **start, off_t offset, int length, int inout)
+static int write_info(struct Scsi_Host *host, char *buffer, int length)
 {
-	char *pos = buffer;
-
 	/* if someone is sending us data, just throw it away */
-	if (inout)
-		return length;
+	return length;
+}
 
+static int show_info(struct seq_file *m, struct Scsi_Host *host)
+{
 	/* print the controller name */
 	SPRINTF("   Host scsi%d: %s\n", host->host_no, RTS51X_NAME);
 
@@ -1988,18 +1986,7 @@
 	SPRINTF("      Product: RTS51xx USB Card Reader\n");
 	SPRINTF("      Version: %s\n", DRIVER_VERSION);
 	SPRINTF("        Build: %s\n", __TIME__);
-
-	/*
-	 * Calculate start of next buffer, and return value.
-	 */
-	*start = buffer + offset;
-
-	if ((pos - buffer) < offset)
-		return 0;
-	else if ((pos - buffer - offset) < length)
-		return pos - buffer - offset;
-	else
-		return length;
+	return 0;
 }
 
 /* queue a command */
@@ -2100,7 +2087,8 @@
 	/* basic userland interface stuff */
 	.name = RTS51X_NAME,
 	.proc_name = RTS51X_NAME,
-	.proc_info = proc_info,
+	.show_info = show_info,
+	.write_info = write_info,
 	.info = rts5139_info,
 
 	/* command interface -- queued only */
diff --git a/drivers/staging/rts5139/rts51x_scsi.h b/drivers/staging/rts5139/rts51x_scsi.h
index 3a52136..1a0d705 100644
--- a/drivers/staging/rts5139/rts51x_scsi.h
+++ b/drivers/staging/rts5139/rts51x_scsi.h
@@ -147,8 +147,6 @@
 
 int slave_alloc(struct scsi_device *sdev);
 int slave_configure(struct scsi_device *sdev);
-int proc_info(struct Scsi_Host *host, char *buffer,
-	      char **start, off_t offset, int length, int inout);
 int queuecommand(struct Scsi_Host *, struct scsi_cmnd *);
 int command_abort(struct scsi_cmnd *srb);
 int bus_reset(struct scsi_cmnd *srb);
diff --git a/drivers/staging/silicom/Makefile b/drivers/staging/silicom/Makefile
index 80e6d12..ca83594 100644
--- a/drivers/staging/silicom/Makefile
+++ b/drivers/staging/silicom/Makefile
@@ -4,6 +4,3 @@
 
 obj-$(CONFIG_BPCTL) += bpctl_mod.o
 obj-$(CONFIG_SBYPASS) += bypasslib/
-
-
-bpctl_mod-objs := bp_mod.o  bp_proc.o
diff --git a/drivers/staging/silicom/bp_proc.c b/drivers/staging/silicom/bp_proc.c
deleted file mode 100644
index a01ca97..0000000
--- a/drivers/staging/silicom/bp_proc.c
+++ /dev/null
@@ -1,1327 +0,0 @@
-/******************************************************************************/
-/*                                                                            */
-/* Copyright (c) 2004-2006 Silicom, Ltd                                       */
-/* 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, located in the file LICENSE.                 */
-/*                                                                            */
-/*                                                                            */
-/******************************************************************************/
-
-#if defined(CONFIG_SMP) && !defined(__SMP__)
-#define __SMP__
-#endif
-
-#include <linux/proc_fs.h>
-#include <linux/netdevice.h>
-#include <asm/uaccess.h>
-/* #include <linux/smp_lock.h> */
-#include "bp_mod.h"
-
-#define BP_PROC_DIR "bypass"
-/* #define BYPASS_SUPPORT "bypass" */
-
-#ifdef BYPASS_SUPPORT
-
-#define GPIO6_SET_ENTRY_SD           "gpio6_set"
-#define GPIO6_CLEAR_ENTRY_SD         "gpio6_clear"
-
-#define GPIO7_SET_ENTRY_SD           "gpio7_set"
-#define GPIO7_CLEAR_ENTRY_SD         "gpio7_clear"
-
-#define PULSE_SET_ENTRY_SD            "pulse_set"
-#define ZERO_SET_ENTRY_SD            "zero_set"
-#define PULSE_GET1_ENTRY_SD            "pulse_get1"
-#define PULSE_GET2_ENTRY_SD            "pulse_get2"
-
-#define CMND_ON_ENTRY_SD              "cmnd_on"
-#define CMND_OFF_ENTRY_SD             "cmnd_off"
-#define RESET_CONT_ENTRY_SD           "reset_cont"
-
- /*COMMANDS*/
-#define BYPASS_INFO_ENTRY_SD     "bypass_info"
-#define BYPASS_SLAVE_ENTRY_SD    "bypass_slave"
-#define BYPASS_CAPS_ENTRY_SD     "bypass_caps"
-#define WD_SET_CAPS_ENTRY_SD     "wd_set_caps"
-#define BYPASS_ENTRY_SD          "bypass"
-#define BYPASS_CHANGE_ENTRY_SD   "bypass_change"
-#define BYPASS_WD_ENTRY_SD       "bypass_wd"
-#define WD_EXPIRE_TIME_ENTRY_SD  "wd_expire_time"
-#define RESET_BYPASS_WD_ENTRY_SD "reset_bypass_wd"
-#define DIS_BYPASS_ENTRY_SD      "dis_bypass"
-#define BYPASS_PWUP_ENTRY_SD     "bypass_pwup"
-#define BYPASS_PWOFF_ENTRY_SD     "bypass_pwoff"
-#define STD_NIC_ENTRY_SD         "std_nic"
-#define STD_NIC_ENTRY_SD         "std_nic"
-#define TAP_ENTRY_SD             "tap"
-#define TAP_CHANGE_ENTRY_SD      "tap_change"
-#define DIS_TAP_ENTRY_SD         "dis_tap"
-#define TAP_PWUP_ENTRY_SD        "tap_pwup"
-#define TWO_PORT_LINK_ENTRY_SD   "two_port_link"
-#define WD_EXP_MODE_ENTRY_SD     "wd_exp_mode"
-#define WD_AUTORESET_ENTRY_SD    "wd_autoreset"
-#define TPL_ENTRY_SD             "tpl"
-#define WAIT_AT_PWUP_ENTRY_SD    "wait_at_pwup"
-#define HW_RESET_ENTRY_SD        "hw_reset"
-#define DISC_ENTRY_SD             "disc"
-#define DISC_CHANGE_ENTRY_SD      "disc_change"
-#define DIS_DISC_ENTRY_SD         "dis_disc"
-#define DISC_PWUP_ENTRY_SD        "disc_pwup"
-
-static struct proc_dir_entry *bp_procfs_dir;
-
-static struct proc_dir_entry *proc_getdir(char *name,
-					  struct proc_dir_entry *proc_dir)
-{
-	struct proc_dir_entry *pde = proc_dir;
-	for (pde = pde->subdir; pde; pde = pde->next) {
-		if (pde->namelen && (strcmp(name, pde->name) == 0)) {
-			/* directory exists */
-			break;
-		}
-	}
-	if (pde == (struct proc_dir_entry *)0) {
-		/* create the directory */
-		pde = create_proc_entry(name, S_IFDIR, proc_dir);
-		if (pde == (struct proc_dir_entry *)0)
-			return pde;
-	}
-	return pde;
-}
-
-int
-bypass_proc_create_entry_sd(struct pfs_unit *pfs_unit_curr,
-			    char *proc_name,
-			    write_proc_t *write_proc,
-			    read_proc_t *read_proc,
-			    struct proc_dir_entry *parent_pfs, void *data)
-{
-	strcpy(pfs_unit_curr->proc_name, proc_name);
-	pfs_unit_curr->proc_entry = create_proc_entry(pfs_unit_curr->proc_name,
-						      S_IFREG | S_IRUSR |
-						      S_IWUSR | S_IRGRP |
-						      S_IROTH, parent_pfs);
-	if (pfs_unit_curr->proc_entry == 0)
-		return -1;
-
-	pfs_unit_curr->proc_entry->read_proc = read_proc;
-	pfs_unit_curr->proc_entry->write_proc = write_proc;
-	pfs_unit_curr->proc_entry->data = data;
-
-	return 0;
-
-}
-
-int
-get_bypass_info_pfs(char *page, char **start, off_t off, int count,
-		    int *eof, void *data)
-{
-	bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data;
-	int len = 0;
-
-	len += sprintf(page, "Name\t\t\t%s\n", pbp_device_block->bp_name);
-	len +=
-	    sprintf(page + len, "Firmware version\t0x%x\n",
-		    pbp_device_block->bp_fw_ver);
-
-	*eof = 1;
-	return len;
-}
-
-int
-get_bypass_slave_pfs(char *page, char **start, off_t off, int count,
-		     int *eof, void *data)
-{
-	bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data;
-
-	struct pci_dev *pci_slave_dev = pbp_device_block->bp_slave;
-	struct net_device *net_slave_dev;
-	int len = 0;
-
-	if (is_bypass_fn(pbp_device_block)) {
-		net_slave_dev = pci_get_drvdata(pci_slave_dev);
-		if (net_slave_dev)
-			len = sprintf(page, "%s\n", net_slave_dev->name);
-		else
-			len = sprintf(page, "fail\n");
-	} else
-		len = sprintf(page, "fail\n");
-
-	*eof = 1;
-	return len;
-}
-
-int
-get_bypass_caps_pfs(char *page, char **start, off_t off, int count,
-		    int *eof, void *data)
-{
-	bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data;
-
-	int len = 0, ret = 0;
-
-	ret = get_bypass_caps_fn(pbp_device_block);
-	if (ret == BP_NOT_CAP)
-		len = sprintf(page, "-1\n");
-	else
-		len = sprintf(page, "0x%x\n", ret);
-	*eof = 1;
-	return len;
-
-}
-
-int
-get_wd_set_caps_pfs(char *page, char **start, off_t off, int count,
-		    int *eof, void *data)
-{
-	bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data;
-
-	int len = 0, ret = 0;
-
-	ret = get_wd_set_caps_fn(pbp_device_block);
-	if (ret == BP_NOT_CAP)
-		len = sprintf(page, "-1\n");
-	else
-		len = sprintf(page, "0x%x\n", ret);
-	*eof = 1;
-	return len;
-}
-
-int
-set_bypass_pfs(struct file *file, const char *buffer,
-	       unsigned long count, void *data)
-{
-
-	char kbuf[256];
-	bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data;
-
-	int bypass_param = 0, length = 0;
-
-	if (count > (sizeof(kbuf) - 1))
-		return -1;
-
-	if (copy_from_user(&kbuf, buffer, count))
-		return -1;
-
-	kbuf[count] = '\0';
-	length = strlen(kbuf);
-	if (kbuf[length - 1] == '\n')
-		kbuf[--length] = '\0';
-
-	if (strcmp(kbuf, "on") == 0)
-		bypass_param = 1;
-	else if (strcmp(kbuf, "off") == 0)
-		bypass_param = 0;
-
-	set_bypass_fn(pbp_device_block, bypass_param);
-
-	return count;
-}
-
-int
-set_tap_pfs(struct file *file, const char *buffer,
-	    unsigned long count, void *data)
-{
-
-	char kbuf[256];
-	bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data;
-
-	int tap_param = 0, length = 0;
-
-	if (count > (sizeof(kbuf) - 1))
-		return -1;
-
-	if (copy_from_user(&kbuf, buffer, count))
-		return -1;
-
-	kbuf[count] = '\0';
-	length = strlen(kbuf);
-	if (kbuf[length - 1] == '\n')
-		kbuf[--length] = '\0';
-
-	if (strcmp(kbuf, "on") == 0)
-		tap_param = 1;
-	else if (strcmp(kbuf, "off") == 0)
-		tap_param = 0;
-
-	set_tap_fn(pbp_device_block, tap_param);
-
-	return count;
-}
-
-int
-set_disc_pfs(struct file *file, const char *buffer,
-	     unsigned long count, void *data)
-{
-
-	char kbuf[256];
-	bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data;
-
-	int tap_param = 0, length = 0;
-
-	if (count > (sizeof(kbuf) - 1))
-		return -1;
-
-	if (copy_from_user(&kbuf, buffer, count))
-		return -1;
-
-	kbuf[count] = '\0';
-	length = strlen(kbuf);
-	if (kbuf[length - 1] == '\n')
-		kbuf[--length] = '\0';
-
-	if (strcmp(kbuf, "on") == 0)
-		tap_param = 1;
-	else if (strcmp(kbuf, "off") == 0)
-		tap_param = 0;
-
-	set_disc_fn(pbp_device_block, tap_param);
-
-	return count;
-}
-
-int
-get_bypass_pfs(char *page, char **start, off_t off, int count,
-	       int *eof, void *data)
-{
-	bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data;
-
-	int len = 0, ret = 0;
-
-	ret = get_bypass_fn(pbp_device_block);
-	if (ret == BP_NOT_CAP)
-		len = sprintf(page, "fail\n");
-	else if (ret == 1)
-		len = sprintf(page, "on\n");
-	else if (ret == 0)
-		len = sprintf(page, "off\n");
-
-	*eof = 1;
-	return len;
-}
-
-int
-get_tap_pfs(char *page, char **start, off_t off, int count,
-	    int *eof, void *data)
-{
-	bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data;
-
-	int len = 0, ret = 0;
-
-	ret = get_tap_fn(pbp_device_block);
-	if (ret == BP_NOT_CAP)
-		len = sprintf(page, "fail\n");
-	else if (ret == 1)
-		len = sprintf(page, "on\n");
-	else if (ret == 0)
-		len = sprintf(page, "off\n");
-
-	*eof = 1;
-	return len;
-}
-
-int
-get_disc_pfs(char *page, char **start, off_t off, int count,
-	     int *eof, void *data)
-{
-	bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data;
-
-	int len = 0, ret = 0;
-
-	ret = get_disc_fn(pbp_device_block);
-	if (ret == BP_NOT_CAP)
-		len = sprintf(page, "fail\n");
-	else if (ret == 1)
-		len = sprintf(page, "on\n");
-	else if (ret == 0)
-		len = sprintf(page, "off\n");
-
-	*eof = 1;
-	return len;
-}
-
-int
-get_bypass_change_pfs(char *page, char **start, off_t off, int count,
-		      int *eof, void *data)
-{
-	bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data;
-
-	int len = 0, ret = 0;
-
-	ret = get_bypass_change_fn(pbp_device_block);
-	if (ret == 1)
-		len = sprintf(page, "on\n");
-	else if (ret == 0)
-		len = sprintf(page, "off\n");
-	else
-		len = sprintf(page, "fail\n");
-
-	*eof = 1;
-	return len;
-}
-
-int
-get_tap_change_pfs(char *page, char **start, off_t off, int count,
-		   int *eof, void *data)
-{
-	bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data;
-
-	int len = 0, ret = 0;
-
-	ret = get_tap_change_fn(pbp_device_block);
-	if (ret == 1)
-		len = sprintf(page, "on\n");
-	else if (ret == 0)
-		len = sprintf(page, "off\n");
-	else
-		len = sprintf(page, "fail\n");
-
-	*eof = 1;
-	return len;
-}
-
-int
-get_disc_change_pfs(char *page, char **start, off_t off, int count,
-		    int *eof, void *data)
-{
-	bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data;
-
-	int len = 0, ret = 0;
-
-	ret = get_disc_change_fn(pbp_device_block);
-	if (ret == 1)
-		len = sprintf(page, "on\n");
-	else if (ret == 0)
-		len = sprintf(page, "off\n");
-	else
-		len = sprintf(page, "fail\n");
-
-	*eof = 1;
-	return len;
-}
-
-int
-set_bypass_wd_pfs(struct file *file, const char *buffer,
-		  unsigned long count, void *data)
-{
-
-	char kbuf[256];
-	bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data;
-
-	unsigned int timeout = 0;
-	char *timeout_ptr = kbuf;
-
-	if (copy_from_user(&kbuf, buffer, count))
-		return -1;
-
-	timeout_ptr = kbuf;
-	timeout = atoi(&timeout_ptr);
-
-	set_bypass_wd_fn(pbp_device_block, timeout);
-
-	return count;
-}
-
-int
-get_bypass_wd_pfs(char *page, char **start, off_t off, int count,
-		  int *eof, void *data)
-{
-	bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data;
-
-	int len = 0, ret = 0, timeout = 0;
-
-	ret = get_bypass_wd_fn(pbp_device_block, &timeout);
-	if (ret == BP_NOT_CAP)
-		len = sprintf(page, "fail\n");
-	else if (timeout == -1)
-		len = sprintf(page, "unknown\n");
-	else if (timeout == 0)
-		len = sprintf(page, "disable\n");
-	else
-		len = sprintf(page, "%d\n", timeout);
-
-	*eof = 1;
-	return len;
-}
-
-int
-get_wd_expire_time_pfs(char *page, char **start, off_t off, int count,
-		       int *eof, void *data)
-{
-	bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data;
-
-	int len = 0, ret = 0, timeout = 0;
-
-	ret = get_wd_expire_time_fn(pbp_device_block, &timeout);
-	if (ret == BP_NOT_CAP)
-		len = sprintf(page, "fail\n");
-	else if (timeout == -1)
-		len = sprintf(page, "expire\n");
-	else if (timeout == 0)
-		len = sprintf(page, "disable\n");
-
-	else
-		len = sprintf(page, "%d\n", timeout);
-	*eof = 1;
-	return len;
-}
-
-int
-get_tpl_pfs(char *page, char **start, off_t off, int count,
-	    int *eof, void *data)
-{
-	bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data;
-
-	int len = 0, ret = 0;
-
-	ret = get_tpl_fn(pbp_device_block);
-	if (ret == BP_NOT_CAP)
-		len = sprintf(page, "fail\n");
-	else if (ret == 1)
-		len = sprintf(page, "on\n");
-	else if (ret == 0)
-		len = sprintf(page, "off\n");
-
-	*eof = 1;
-	return len;
-}
-
-#ifdef PMC_FIX_FLAG
-int
-get_wait_at_pwup_pfs(char *page, char **start, off_t off, int count,
-		     int *eof, void *data)
-{
-	bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data;
-
-	int len = 0, ret = 0;
-
-	ret = get_bp_wait_at_pwup_fn(pbp_device_block);
-	if (ret == BP_NOT_CAP)
-		len = sprintf(page, "fail\n");
-	else if (ret == 1)
-		len = sprintf(page, "on\n");
-	else if (ret == 0)
-		len = sprintf(page, "off\n");
-
-	*eof = 1;
-	return len;
-}
-
-int
-get_hw_reset_pfs(char *page, char **start, off_t off, int count,
-		 int *eof, void *data)
-{
-	bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data;
-
-	int len = 0, ret = 0;
-
-	ret = get_bp_hw_reset_fn(pbp_device_block);
-	if (ret == BP_NOT_CAP)
-		len = sprintf(page, "fail\n");
-	else if (ret == 1)
-		len = sprintf(page, "on\n");
-	else if (ret == 0)
-		len = sprintf(page, "off\n");
-
-	*eof = 1;
-	return len;
-}
-
-#endif				/*PMC_WAIT_FLAG */
-
-int
-reset_bypass_wd_pfs(char *page, char **start, off_t off, int count,
-		    int *eof, void *data)
-{
-	bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data;
-
-	int len = 0, ret = 0;
-
-	ret = reset_bypass_wd_timer_fn(pbp_device_block);
-	if (ret == BP_NOT_CAP)
-		len = sprintf(page, "fail\n");
-	else if (ret == 0)
-		len = sprintf(page, "disable\n");
-	else if (ret == 1)
-		len = sprintf(page, "success\n");
-
-	*eof = 1;
-	return len;
-}
-
-int
-set_dis_bypass_pfs(struct file *file, const char *buffer,
-		   unsigned long count, void *data)
-{
-
-	char kbuf[256];
-	bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data;
-
-	int bypass_param = 0, length = 0;
-
-	if (copy_from_user(&kbuf, buffer, count))
-		return -1;
-
-	kbuf[count] = '\0';
-	length = strlen(kbuf);
-	if (kbuf[length - 1] == '\n')
-		kbuf[--length] = '\0';
-
-	if (strcmp(kbuf, "on") == 0)
-		bypass_param = 1;
-	else if (strcmp(kbuf, "off") == 0)
-		bypass_param = 0;
-
-	set_dis_bypass_fn(pbp_device_block, bypass_param);
-
-	return count;
-}
-
-int
-set_dis_tap_pfs(struct file *file, const char *buffer,
-		unsigned long count, void *data)
-{
-
-	char kbuf[256];
-	bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data;
-
-	int tap_param = 0, length = 0;
-
-	if (copy_from_user(&kbuf, buffer, count))
-		return -1;
-
-	kbuf[count] = '\0';
-	length = strlen(kbuf);
-	if (kbuf[length - 1] == '\n')
-		kbuf[--length] = '\0';
-
-	if (strcmp(kbuf, "on") == 0)
-		tap_param = 1;
-	else if (strcmp(kbuf, "off") == 0)
-		tap_param = 0;
-
-	set_dis_tap_fn(pbp_device_block, tap_param);
-
-	return count;
-}
-
-int
-set_dis_disc_pfs(struct file *file, const char *buffer,
-		 unsigned long count, void *data)
-{
-
-	char kbuf[256];
-	bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data;
-
-	int tap_param = 0, length = 0;
-
-	if (copy_from_user(&kbuf, buffer, count))
-		return -1;
-
-	kbuf[count] = '\0';
-	length = strlen(kbuf);
-	if (kbuf[length - 1] == '\n')
-		kbuf[--length] = '\0';
-
-	if (strcmp(kbuf, "on") == 0)
-		tap_param = 1;
-	else if (strcmp(kbuf, "off") == 0)
-		tap_param = 0;
-
-	set_dis_disc_fn(pbp_device_block, tap_param);
-
-	return count;
-}
-
-int
-get_dis_bypass_pfs(char *page, char **start, off_t off, int count,
-		   int *eof, void *data)
-{
-	bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data;
-
-	int len = 0, ret = 0;
-
-	ret = get_dis_bypass_fn(pbp_device_block);
-	if (ret == BP_NOT_CAP)
-		len = sprintf(page, "fail\n");
-	else if (ret == 0)
-		len = sprintf(page, "off\n");
-	else
-		len = sprintf(page, "on\n");
-
-	*eof = 1;
-	return len;
-}
-
-int
-get_dis_tap_pfs(char *page, char **start, off_t off, int count,
-		int *eof, void *data)
-{
-	bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data;
-
-	int len = 0, ret = 0;
-
-	ret = get_dis_tap_fn(pbp_device_block);
-	if (ret == BP_NOT_CAP)
-		len = sprintf(page, "fail\n");
-	else if (ret == 0)
-		len = sprintf(page, "off\n");
-	else
-		len = sprintf(page, "on\n");
-
-	*eof = 1;
-	return len;
-}
-
-int
-get_dis_disc_pfs(char *page, char **start, off_t off, int count,
-		 int *eof, void *data)
-{
-	bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data;
-
-	int len = 0, ret = 0;
-
-	ret = get_dis_disc_fn(pbp_device_block);
-	if (ret == BP_NOT_CAP)
-		len = sprintf(page, "fail\n");
-	else if (ret == 0)
-		len = sprintf(page, "off\n");
-	else
-		len = sprintf(page, "on\n");
-
-	*eof = 1;
-	return len;
-}
-
-int
-set_bypass_pwup_pfs(struct file *file, const char *buffer,
-		    unsigned long count, void *data)
-{
-
-	char kbuf[256];
-	bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data;
-
-	int bypass_param = 0, length = 0;
-
-	if (copy_from_user(&kbuf, buffer, count))
-		return -1;
-
-	kbuf[count] = '\0';
-	length = strlen(kbuf);
-	if (kbuf[length - 1] == '\n')
-		kbuf[--length] = '\0';
-
-	if (strcmp(kbuf, "on") == 0)
-		bypass_param = 1;
-	else if (strcmp(kbuf, "off") == 0)
-		bypass_param = 0;
-
-	set_bypass_pwup_fn(pbp_device_block, bypass_param);
-
-	return count;
-}
-
-int
-set_bypass_pwoff_pfs(struct file *file, const char *buffer,
-		     unsigned long count, void *data)
-{
-
-	char kbuf[256];
-	bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data;
-
-	int bypass_param = 0, length = 0;
-
-	if (copy_from_user(&kbuf, buffer, count))
-		return -1;
-
-	kbuf[count] = '\0';
-	length = strlen(kbuf);
-	if (kbuf[length - 1] == '\n')
-		kbuf[--length] = '\0';
-
-	if (strcmp(kbuf, "on") == 0)
-		bypass_param = 1;
-	else if (strcmp(kbuf, "off") == 0)
-		bypass_param = 0;
-
-	set_bypass_pwoff_fn(pbp_device_block, bypass_param);
-
-	return count;
-}
-
-int
-set_tap_pwup_pfs(struct file *file, const char *buffer,
-		 unsigned long count, void *data)
-{
-
-	char kbuf[256];
-	bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data;
-
-	int tap_param = 0, length = 0;
-
-	if (copy_from_user(&kbuf, buffer, count))
-		return -1;
-
-	kbuf[count] = '\0';
-	length = strlen(kbuf);
-	if (kbuf[length - 1] == '\n')
-		kbuf[--length] = '\0';
-
-	if (strcmp(kbuf, "on") == 0)
-		tap_param = 1;
-	else if (strcmp(kbuf, "off") == 0)
-		tap_param = 0;
-
-	set_tap_pwup_fn(pbp_device_block, tap_param);
-
-	return count;
-}
-
-int
-set_disc_pwup_pfs(struct file *file, const char *buffer,
-		  unsigned long count, void *data)
-{
-
-	char kbuf[256];
-	bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data;
-
-	int tap_param = 0, length = 0;
-
-	if (copy_from_user(&kbuf, buffer, count))
-		return -1;
-
-	kbuf[count] = '\0';
-	length = strlen(kbuf);
-	if (kbuf[length - 1] == '\n')
-		kbuf[--length] = '\0';
-
-	if (strcmp(kbuf, "on") == 0)
-		tap_param = 1;
-	else if (strcmp(kbuf, "off") == 0)
-		tap_param = 0;
-
-	set_disc_pwup_fn(pbp_device_block, tap_param);
-
-	return count;
-}
-
-int
-get_bypass_pwup_pfs(char *page, char **start, off_t off, int count,
-		    int *eof, void *data)
-{
-	bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data;
-
-	int len = 0, ret = 0;
-
-	ret = get_bypass_pwup_fn(pbp_device_block);
-	if (ret == BP_NOT_CAP)
-		len = sprintf(page, "fail\n");
-	else if (ret == 0)
-		len = sprintf(page, "off\n");
-	else
-		len = sprintf(page, "on\n");
-
-	*eof = 1;
-	return len;
-}
-
-int
-get_bypass_pwoff_pfs(char *page, char **start, off_t off, int count,
-		     int *eof, void *data)
-{
-	bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data;
-
-	int len = 0, ret = 0;
-
-	ret = get_bypass_pwoff_fn(pbp_device_block);
-	if (ret == BP_NOT_CAP)
-		len = sprintf(page, "fail\n");
-	else if (ret == 0)
-		len = sprintf(page, "off\n");
-	else
-		len = sprintf(page, "on\n");
-
-	*eof = 1;
-	return len;
-}
-
-int
-get_tap_pwup_pfs(char *page, char **start, off_t off, int count,
-		 int *eof, void *data)
-{
-	bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data;
-
-	int len = 0, ret = 0;
-
-	ret = get_tap_pwup_fn(pbp_device_block);
-	if (ret == BP_NOT_CAP)
-		len = sprintf(page, "fail\n");
-	else if (ret == 0)
-		len = sprintf(page, "off\n");
-	else
-		len = sprintf(page, "on\n");
-
-	*eof = 1;
-	return len;
-}
-
-int
-get_disc_pwup_pfs(char *page, char **start, off_t off, int count,
-		  int *eof, void *data)
-{
-	bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data;
-
-	int len = 0, ret = 0;
-
-	ret = get_disc_pwup_fn(pbp_device_block);
-	if (ret == BP_NOT_CAP)
-		len = sprintf(page, "fail\n");
-	else if (ret == 0)
-		len = sprintf(page, "off\n");
-	else
-		len = sprintf(page, "on\n");
-
-	*eof = 1;
-	return len;
-}
-
-int
-set_std_nic_pfs(struct file *file, const char *buffer,
-		unsigned long count, void *data)
-{
-
-	char kbuf[256];
-	bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data;
-
-	int bypass_param = 0, length = 0;
-
-	if (copy_from_user(&kbuf, buffer, count))
-		return -1;
-
-	kbuf[count] = '\0';
-	length = strlen(kbuf);
-	if (kbuf[length - 1] == '\n')
-		kbuf[--length] = '\0';
-
-	if (strcmp(kbuf, "on") == 0)
-		bypass_param = 1;
-	else if (strcmp(kbuf, "off") == 0)
-		bypass_param = 0;
-
-	set_std_nic_fn(pbp_device_block, bypass_param);
-
-	return count;
-}
-
-int
-get_std_nic_pfs(char *page, char **start, off_t off, int count,
-		int *eof, void *data)
-{
-	bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data;
-
-	int len = 0, ret = 0;
-
-	ret = get_std_nic_fn(pbp_device_block);
-	if (ret == BP_NOT_CAP)
-		len = sprintf(page, "fail\n");
-	else if (ret == 0)
-		len = sprintf(page, "off\n");
-	else
-		len = sprintf(page, "on\n");
-
-	*eof = 1;
-	return len;
-}
-
-int
-get_wd_exp_mode_pfs(char *page, char **start, off_t off, int count,
-		    int *eof, void *data)
-{
-	bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data;
-
-	int len = 0, ret = 0;
-
-	ret = get_wd_exp_mode_fn(pbp_device_block);
-	if (ret == 1)
-		len = sprintf(page, "tap\n");
-	else if (ret == 0)
-		len = sprintf(page, "bypass\n");
-	else if (ret == 2)
-		len = sprintf(page, "disc\n");
-
-	else
-		len = sprintf(page, "fail\n");
-
-	*eof = 1;
-	return len;
-}
-
-int
-set_wd_exp_mode_pfs(struct file *file, const char *buffer,
-		    unsigned long count, void *data)
-{
-
-	char kbuf[256];
-	bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data;
-
-	int bypass_param = 0, length = 0;
-
-	if (count > (sizeof(kbuf) - 1))
-		return -1;
-
-	if (copy_from_user(&kbuf, buffer, count))
-		return -1;
-
-	kbuf[count] = '\0';
-	length = strlen(kbuf);
-	if (kbuf[length - 1] == '\n')
-		kbuf[--length] = '\0';
-
-	if (strcmp(kbuf, "tap") == 0)
-		bypass_param = 1;
-	else if (strcmp(kbuf, "bypass") == 0)
-		bypass_param = 0;
-	else if (strcmp(kbuf, "disc") == 0)
-		bypass_param = 2;
-
-	set_wd_exp_mode_fn(pbp_device_block, bypass_param);
-
-	return count;
-}
-
-int
-get_wd_autoreset_pfs(char *page, char **start, off_t off, int count,
-		     int *eof, void *data)
-{
-	bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data;
-
-	int len = 0, ret = 0;
-
-	ret = get_wd_autoreset_fn(pbp_device_block);
-	if (ret >= 0)
-		len = sprintf(page, "%d\n", ret);
-	else
-		len = sprintf(page, "fail\n");
-
-	*eof = 1;
-	return len;
-}
-
-int
-set_wd_autoreset_pfs(struct file *file, const char *buffer,
-		     unsigned long count, void *data)
-{
-	char kbuf[256];
-	bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data;
-	u32 timeout = 0;
-	char *timeout_ptr = kbuf;
-
-	if (copy_from_user(&kbuf, buffer, count))
-		return -1;
-
-	timeout_ptr = kbuf;
-	timeout = atoi(&timeout_ptr);
-
-	set_wd_autoreset_fn(pbp_device_block, timeout);
-
-	return count;
-}
-
-int
-set_tpl_pfs(struct file *file, const char *buffer,
-	    unsigned long count, void *data)
-{
-
-	char kbuf[256];
-	bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data;
-
-	int tpl_param = 0, length = 0;
-
-	if (count > (sizeof(kbuf) - 1))
-		return -1;
-
-	if (copy_from_user(&kbuf, buffer, count))
-		return -1;
-
-	kbuf[count] = '\0';
-	length = strlen(kbuf);
-	if (kbuf[length - 1] == '\n')
-		kbuf[--length] = '\0';
-
-	if (strcmp(kbuf, "on") == 0)
-		tpl_param = 1;
-	else if (strcmp(kbuf, "off") == 0)
-		tpl_param = 0;
-
-	set_tpl_fn(pbp_device_block, tpl_param);
-
-	return count;
-}
-
-#ifdef PMC_FIX_FLAG
-int
-set_wait_at_pwup_pfs(struct file *file, const char *buffer,
-		     unsigned long count, void *data)
-{
-
-	char kbuf[256];
-	bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data;
-
-	int tpl_param = 0, length = 0;
-
-	if (count > (sizeof(kbuf) - 1))
-		return -1;
-
-	if (copy_from_user(&kbuf, buffer, count))
-		return -1;
-
-	kbuf[count] = '\0';
-	length = strlen(kbuf);
-	if (kbuf[length - 1] == '\n')
-		kbuf[--length] = '\0';
-
-	if (strcmp(kbuf, "on") == 0)
-		tpl_param = 1;
-	else if (strcmp(kbuf, "off") == 0)
-		tpl_param = 0;
-
-	set_bp_wait_at_pwup_fn(pbp_device_block, tpl_param);
-
-	return count;
-}
-
-int
-set_hw_reset_pfs(struct file *file, const char *buffer,
-		 unsigned long count, void *data)
-{
-
-	char kbuf[256];
-	bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data;
-
-	int tpl_param = 0, length = 0;
-
-	if (count > (sizeof(kbuf) - 1))
-		return -1;
-
-	if (copy_from_user(&kbuf, buffer, count))
-		return -1;
-
-	kbuf[count] = '\0';
-	length = strlen(kbuf);
-	if (kbuf[length - 1] == '\n')
-		kbuf[--length] = '\0';
-
-	if (strcmp(kbuf, "on") == 0)
-		tpl_param = 1;
-	else if (strcmp(kbuf, "off") == 0)
-		tpl_param = 0;
-
-	set_bp_hw_reset_fn(pbp_device_block, tpl_param);
-
-	return count;
-}
-
-#endif				/*PMC_FIX_FLAG */
-
-int bypass_proc_create_dev_sd(bpctl_dev_t *pbp_device_block)
-{
-	struct bypass_pfs_sd *current_pfs = &(pbp_device_block->bypass_pfs_set);
-	static struct proc_dir_entry *procfs_dir;
-	int ret = 0;
-
-	sprintf(current_pfs->dir_name, "bypass_%s", dev->name);
-
-	if (!bp_procfs_dir)
-		return -1;
-
-	/* create device proc dir */
-	procfs_dir = proc_getdir(current_pfs->dir_name, bp_procfs_dir);
-	if (procfs_dir == 0) {
-		printk(KERN_DEBUG "Could not create procfs directory %s\n",
-		       current_pfs->dir_name);
-		return -1;
-	}
-	current_pfs->bypass_entry = procfs_dir;
-
-	if (bypass_proc_create_entry(&(current_pfs->bypass_info), BYPASS_INFO_ENTRY_SD, NULL,	/* write */
-				     get_bypass_info_pfs,	/* read  */
-				     procfs_dir, pbp_device_block))
-		ret = -1;
-
-	if (pbp_device_block->bp_caps & SW_CTL_CAP) {
-
-		/* Create set param proc's */
-		if (bypass_proc_create_entry_sd(&(current_pfs->bypass_slave), BYPASS_SLAVE_ENTRY_SD, NULL,	/* write */
-						get_bypass_slave_pfs,	/* read  */
-						procfs_dir, pbp_device_block))
-			ret = -1;
-
-		if (bypass_proc_create_entry_sd(&(current_pfs->bypass_caps), BYPASS_CAPS_ENTRY_SD, NULL,	/* write */
-						get_bypass_caps_pfs,	/* read  */
-						procfs_dir, pbp_device_block))
-			ret = -1;
-
-		if (bypass_proc_create_entry_sd(&(current_pfs->wd_set_caps), WD_SET_CAPS_ENTRY_SD, NULL,	/* write */
-						get_wd_set_caps_pfs,	/* read  */
-						procfs_dir, pbp_device_block))
-			ret = -1;
-		if (bypass_proc_create_entry_sd(&(current_pfs->bypass_wd), BYPASS_WD_ENTRY_SD, set_bypass_wd_pfs,	/* write */
-						get_bypass_wd_pfs,	/* read  */
-						procfs_dir, pbp_device_block))
-			ret = -1;
-
-		if (bypass_proc_create_entry_sd(&(current_pfs->wd_expire_time), WD_EXPIRE_TIME_ENTRY_SD, NULL,	/* write */
-						get_wd_expire_time_pfs,	/* read  */
-						procfs_dir, pbp_device_block))
-			ret = -1;
-
-		if (bypass_proc_create_entry_sd(&(current_pfs->reset_bypass_wd), RESET_BYPASS_WD_ENTRY_SD, NULL,	/* write */
-						reset_bypass_wd_pfs,	/* read  */
-						procfs_dir, pbp_device_block))
-			ret = -1;
-
-		if (bypass_proc_create_entry_sd(&(current_pfs->std_nic), STD_NIC_ENTRY_SD, set_std_nic_pfs,	/* write */
-						get_std_nic_pfs,	/* read  */
-						procfs_dir, pbp_device_block))
-			ret = -1;
-
-		if (pbp_device_block->bp_caps & BP_CAP) {
-			if (bypass_proc_create_entry_sd(&(current_pfs->bypass), BYPASS_ENTRY_SD, set_bypass_pfs,	/* write */
-							get_bypass_pfs,	/* read  */
-							procfs_dir,
-							pbp_device_block))
-				ret = -1;
-
-			if (bypass_proc_create_entry_sd(&(current_pfs->dis_bypass), DIS_BYPASS_ENTRY_SD, set_dis_bypass_pfs,	/* write */
-							get_dis_bypass_pfs,	/* read  */
-							procfs_dir,
-							pbp_device_block))
-				ret = -1;
-
-			if (bypass_proc_create_entry_sd(&(current_pfs->bypass_pwup), BYPASS_PWUP_ENTRY_SD, set_bypass_pwup_pfs,	/* write */
-							get_bypass_pwup_pfs,	/* read  */
-							procfs_dir,
-							pbp_device_block))
-				ret = -1;
-			if (bypass_proc_create_entry_sd(&(current_pfs->bypass_pwoff), BYPASS_PWOFF_ENTRY_SD, set_bypass_pwoff_pfs,	/* write */
-							get_bypass_pwoff_pfs,	/* read  */
-							procfs_dir,
-							pbp_device_block))
-				ret = -1;
-
-			if (bypass_proc_create_entry_sd(&(current_pfs->bypass_change), BYPASS_CHANGE_ENTRY_SD, NULL,	/* write */
-							get_bypass_change_pfs,	/* read  */
-							procfs_dir,
-							pbp_device_block))
-				ret = -1;
-		}
-
-		if (pbp_device_block->bp_caps & TAP_CAP) {
-
-			if (bypass_proc_create_entry_sd(&(current_pfs->tap), TAP_ENTRY_SD, set_tap_pfs,	/* write */
-							get_tap_pfs,	/* read  */
-							procfs_dir,
-							pbp_device_block))
-				ret = -1;
-
-			if (bypass_proc_create_entry_sd(&(current_pfs->dis_tap), DIS_TAP_ENTRY_SD, set_dis_tap_pfs,	/* write */
-							get_dis_tap_pfs,	/* read  */
-							procfs_dir,
-							pbp_device_block))
-				ret = -1;
-
-			if (bypass_proc_create_entry_sd(&(current_pfs->tap_pwup), TAP_PWUP_ENTRY_SD, set_tap_pwup_pfs,	/* write */
-							get_tap_pwup_pfs,	/* read  */
-							procfs_dir,
-							pbp_device_block))
-				ret = -1;
-
-			if (bypass_proc_create_entry_sd(&(current_pfs->tap_change), TAP_CHANGE_ENTRY_SD, NULL,	/* write */
-							get_tap_change_pfs,	/* read  */
-							procfs_dir,
-							pbp_device_block))
-				ret = -1;
-		}
-		if (pbp_device_block->bp_caps & DISC_CAP) {
-
-			if (bypass_proc_create_entry_sd(&(current_pfs->tap), DISC_ENTRY_SD, set_disc_pfs,	/* write */
-							get_disc_pfs,	/* read  */
-							procfs_dir,
-							pbp_device_block))
-				ret = -1;
-#if 1
-
-			if (bypass_proc_create_entry_sd(&(current_pfs->dis_tap), DIS_DISC_ENTRY_SD, set_dis_disc_pfs,	/* write */
-							get_dis_disc_pfs,	/* read  */
-							procfs_dir,
-							pbp_device_block))
-				ret = -1;
-#endif
-
-			if (bypass_proc_create_entry_sd(&(current_pfs->tap_pwup), DISC_PWUP_ENTRY_SD, set_disc_pwup_pfs,	/* write */
-							get_disc_pwup_pfs,	/* read  */
-							procfs_dir,
-							pbp_device_block))
-				ret = -1;
-
-			if (bypass_proc_create_entry_sd(&(current_pfs->tap_change), DISC_CHANGE_ENTRY_SD, NULL,	/* write */
-							get_disc_change_pfs,	/* read  */
-							procfs_dir,
-							pbp_device_block))
-				ret = -1;
-		}
-
-		if (bypass_proc_create_entry_sd(&(current_pfs->wd_exp_mode), WD_EXP_MODE_ENTRY_SD, set_wd_exp_mode_pfs,	/* write */
-						get_wd_exp_mode_pfs,	/* read  */
-						procfs_dir, pbp_device_block))
-			ret = -1;
-
-		if (bypass_proc_create_entry_sd(&(current_pfs->wd_autoreset), WD_AUTORESET_ENTRY_SD, set_wd_autoreset_pfs,	/* write */
-						get_wd_autoreset_pfs,	/* read  */
-						procfs_dir, pbp_device_block))
-			ret = -1;
-		if (bypass_proc_create_entry_sd(&(current_pfs->tpl), TPL_ENTRY_SD, set_tpl_pfs,	/* write */
-						get_tpl_pfs,	/* read  */
-						procfs_dir, pbp_device_block))
-			ret = -1;
-#ifdef PMC_FIX_FLAG
-		if (bypass_proc_create_entry_sd(&(current_pfs->tpl), WAIT_AT_PWUP_ENTRY_SD, set_wait_at_pwup_pfs,	/* write */
-						get_wait_at_pwup_pfs,	/* read  */
-						procfs_dir, pbp_device_block))
-			ret = -1;
-		if (bypass_proc_create_entry_sd(&(current_pfs->tpl), HW_RESET_ENTRY_SD, set_hw_reset_pfs,	/* write */
-						get_hw_reset_pfs,	/* read  */
-						procfs_dir, pbp_device_block))
-			ret = -1;
-
-#endif
-
-	}
-	if (ret < 0)
-		printk(KERN_DEBUG "Create proc entry failed\n");
-
-	return ret;
-}
-
-int bypass_proc_remove_dev_sd(bpctl_dev_t *pbp_device_block)
-{
-
-	struct bypass_pfs_sd *current_pfs = &pbp_device_block->bypass_pfs_set;
-	struct proc_dir_entry *pde = current_pfs->bypass_entry, *pde_curr =
-	    NULL;
-	char name[256];
-
-	for (pde = pde->subdir; pde;) {
-		strcpy(name, pde->name);
-		pde_curr = pde;
-		pde = pde->next;
-		remove_proc_entry(name, current_pfs->bypass_entry);
-	}
-	if (!pde)
-		remove_proc_entry(current_pfs->dir_name, bp_procfs_dir);
-
-	return 0;
-}
-
-#endif				/* BYPASS_SUPPORT */
diff --git a/drivers/staging/silicom/bp_mod.c b/drivers/staging/silicom/bpctl_mod.c
similarity index 83%
rename from drivers/staging/silicom/bp_mod.c
rename to drivers/staging/silicom/bpctl_mod.c
index 45a2227..b7e570c 100644
--- a/drivers/staging/silicom/bp_mod.c
+++ b/drivers/staging/silicom/bpctl_mod.c
@@ -35,7 +35,6 @@
 #define BP_MOD_DESCR "Silicom Bypass-SD Control driver"
 #define BP_SYNC_FLAG 1
 
-static int Device_Open = 0;
 static int major_num = 0;
 
 MODULE_AUTHOR("Anna Lukin, annal@silicom.co.il");
@@ -60,35 +59,9 @@
 	bp_none,
 } bp_media_type;
 
-struct pfs_unit_sd {
-	struct proc_dir_entry *proc_entry;
-	char proc_name[32];
-};
-
 struct bypass_pfs_sd {
 	char dir_name[32];
 	struct proc_dir_entry *bypass_entry;
-	struct pfs_unit_sd bypass_info;
-	struct pfs_unit_sd bypass_slave;
-	struct pfs_unit_sd bypass_caps;
-	struct pfs_unit_sd wd_set_caps;
-	struct pfs_unit_sd bypass;
-	struct pfs_unit_sd bypass_change;
-	struct pfs_unit_sd bypass_wd;
-	struct pfs_unit_sd wd_expire_time;
-	struct pfs_unit_sd reset_bypass_wd;
-	struct pfs_unit_sd dis_bypass;
-	struct pfs_unit_sd bypass_pwup;
-	struct pfs_unit_sd bypass_pwoff;
-	struct pfs_unit_sd std_nic;
-	struct pfs_unit_sd tap;
-	struct pfs_unit_sd dis_tap;
-	struct pfs_unit_sd tap_pwup;
-	struct pfs_unit_sd tap_change;
-	struct pfs_unit_sd wd_exp_mode;
-	struct pfs_unit_sd wd_autoreset;
-	struct pfs_unit_sd tpl;
-
 };
 
 typedef struct _bpctl_dev {
@@ -315,27 +288,6 @@
 	.notifier_call = bp_device_event,
 };
 
-static int device_open(struct inode *inode, struct file *file)
-{
-#ifdef DEBUG
-	printk("device_open(%p)\n", file);
-#endif
-	Device_Open++;
-/*
-* Initialize the message
-*/
-	return SUCCESS;
-}
-
-static int device_release(struct inode *inode, struct file *file)
-{
-#ifdef DEBUG
-	printk("device_release(%p,%p)\n", inode, file);
-#endif
-	Device_Open--;
-	return SUCCESS;
-}
-
 int is_bypass_fn(bpctl_dev_t *pbpctl_dev);
 int wdt_time_left(bpctl_dev_t *pbpctl_dev);
 
@@ -1728,62 +1680,33 @@
 }
 #endif				/*BYPASS_DEBUG */
 
+static bpctl_dev_t *lookup_port(bpctl_dev_t *dev)
+{
+	bpctl_dev_t *p;
+	int n;
+	for (n = 0, p = bpctl_dev_arr; n < device_num && p->pdev; n++) {
+		if (p->bus == dev->bus
+		    && p->slot == dev->slot
+		    && p->func == (dev->func ^ 1))
+			return p;
+	}
+	return NULL;
+}
+
 static bpctl_dev_t *get_status_port_fn(bpctl_dev_t *pbpctl_dev)
 {
-	int idx_dev = 0;
-
-	if (pbpctl_dev == NULL)
-		return NULL;
-
-	if ((pbpctl_dev->func == 0) || (pbpctl_dev->func == 2)) {
-		for (idx_dev = 0;
-		     ((bpctl_dev_arr[idx_dev].pdev != NULL)
-		      && (idx_dev < device_num)); idx_dev++) {
-			if ((bpctl_dev_arr[idx_dev].bus == pbpctl_dev->bus)
-			    && (bpctl_dev_arr[idx_dev].slot == pbpctl_dev->slot)
-			    && ((bpctl_dev_arr[idx_dev].func == 1)
-				&& (pbpctl_dev->func == 0))) {
-
-				return &(bpctl_dev_arr[idx_dev]);
-			}
-			if ((bpctl_dev_arr[idx_dev].bus == pbpctl_dev->bus) &&
-			    (bpctl_dev_arr[idx_dev].slot == pbpctl_dev->slot) &&
-			    ((bpctl_dev_arr[idx_dev].func == 3)
-			     && (pbpctl_dev->func == 2))) {
-
-				return &(bpctl_dev_arr[idx_dev]);
-			}
-		}
+	if (pbpctl_dev) {
+		if (pbpctl_dev->func == 0 || pbpctl_dev->func == 2)
+			return lookup_port(pbpctl_dev);
 	}
 	return NULL;
 }
 
 static bpctl_dev_t *get_master_port_fn(bpctl_dev_t *pbpctl_dev)
 {
-	int idx_dev = 0;
-
-	if (pbpctl_dev == NULL)
-		return NULL;
-
-	if ((pbpctl_dev->func == 1) || (pbpctl_dev->func == 3)) {
-		for (idx_dev = 0;
-		     ((bpctl_dev_arr[idx_dev].pdev != NULL)
-		      && (idx_dev < device_num)); idx_dev++) {
-			if ((bpctl_dev_arr[idx_dev].bus == pbpctl_dev->bus)
-			    && (bpctl_dev_arr[idx_dev].slot == pbpctl_dev->slot)
-			    && ((bpctl_dev_arr[idx_dev].func == 0)
-				&& (pbpctl_dev->func == 1))) {
-
-				return &(bpctl_dev_arr[idx_dev]);
-			}
-			if ((bpctl_dev_arr[idx_dev].bus == pbpctl_dev->bus) &&
-			    (bpctl_dev_arr[idx_dev].slot == pbpctl_dev->slot) &&
-			    ((bpctl_dev_arr[idx_dev].func == 2)
-			     && (pbpctl_dev->func == 3))) {
-
-				return &(bpctl_dev_arr[idx_dev]);
-			}
-		}
+	if (pbpctl_dev) {
+		if (pbpctl_dev->func == 1 || pbpctl_dev->func == 3)
+			return lookup_port(pbpctl_dev);
 	}
 	return NULL;
 }
@@ -5858,11 +5781,9 @@
 	return ret;
 }
 
-struct file_operations Fops = {
+static const struct file_operations Fops = {
 	.owner = THIS_MODULE,
 	.unlocked_ioctl = device_ioctl,
-	.open = device_open,
-	.release = device_release,	/* a.k.a. close */
 };
 
 #ifndef PCI_DEVICE
@@ -6686,6 +6607,118 @@
 	{0,}
 };
 
+static void find_fw(bpctl_dev_t *dev)
+{
+	unsigned long mmio_start, mmio_len;
+	struct pci_dev *pdev1 = dev->pdev;
+
+	if ((OLD_IF_SERIES(dev->subdevice)) ||
+	    (INTEL_IF_SERIES(dev->subdevice)))
+		dev->bp_fw_ver = 0xff;
+	else
+		dev->bp_fw_ver = bypass_fw_ver(dev);
+
+	if (dev->bp_10gb == 1 && dev->bp_fw_ver == 0xff) {
+		int cnt = 100;
+		while (cnt--) {
+			iounmap((void *)dev->mem_map);
+			mmio_start = pci_resource_start(pdev1, 0);
+			mmio_len = pci_resource_len(pdev1, 0);
+
+			dev->mem_map = (unsigned long)
+			    ioremap(mmio_start, mmio_len);
+
+			dev->bp_fw_ver = bypass_fw_ver(dev);
+			if (dev-> bp_fw_ver == 0xa8)
+				break;
+		}
+	}
+	/* dev->bp_fw_ver=0xa8; */
+	printk("firmware version: 0x%x\n", dev->bp_fw_ver);
+}
+
+static int init_one(bpctl_dev_t *dev, bpmod_info_t *info, struct pci_dev *pdev1)
+{
+	unsigned long mmio_start, mmio_len;
+
+	dev->pdev = pdev1;
+	mmio_start = pci_resource_start(pdev1, 0);
+	mmio_len = pci_resource_len(pdev1, 0);
+
+	dev->desc = dev_desc[info->index].name;
+	dev->name = info->bp_name;
+	dev->device = info->device;
+	dev->vendor = info->vendor;
+	dev->subdevice = info->subdevice;
+	dev->subvendor = info->subvendor;
+	dev->func = PCI_FUNC(pdev1->devfn);
+	dev->slot = PCI_SLOT(pdev1->devfn);
+	dev->bus = pdev1->bus->number;
+	dev->mem_map = (unsigned long)ioremap(mmio_start, mmio_len);
+#ifdef BP_SYNC_FLAG
+	spin_lock_init(&dev->bypass_wr_lock);
+#endif
+	if (BP10G9_IF_SERIES(dev->subdevice))
+		dev->bp_10g9 = 1;
+	if (BP10G_IF_SERIES(dev->subdevice))
+		dev->bp_10g = 1;
+	if (PEG540_IF_SERIES(dev->subdevice))
+		dev->bp_540 = 1;
+	if (PEGF5_IF_SERIES(dev->subdevice))
+		dev->bp_fiber5 = 1;
+	if (PEG80_IF_SERIES(dev->subdevice))
+		dev->bp_i80 = 1;
+	if (PEGF80_IF_SERIES(dev->subdevice))
+		dev->bp_i80 = 1;
+	if ((dev->subdevice & 0xa00) == 0xa00)
+		dev->bp_i80 = 1;
+	if (BP10GB_IF_SERIES(dev->subdevice)) {
+		if (dev->ifindex == 0) {
+			unregister_chrdev(major_num, DEVICE_NAME);
+			printk("Please load network driver for %s adapter!\n",
+			     dev->name);
+			return -1;
+		}
+
+		if (dev->ndev && !(dev->ndev->flags & IFF_UP)) {
+			unregister_chrdev(major_num, DEVICE_NAME);
+			printk("Please bring up network interfaces for %s adapter!\n",
+			     dev->name);
+			return -1;
+		}
+		dev->bp_10gb = 1;
+	}
+
+	if (!dev->bp_10g9) {
+		if (is_bypass_fn(dev)) {
+			printk(KERN_INFO "%s found, ",
+			       dev->name);
+			find_fw(dev);
+		}
+		dev->wdt_status = WDT_STATUS_UNKNOWN;
+		dev->reset_time = 0;
+		atomic_set(&dev->wdt_busy, 0);
+		dev->bp_status_un = 1;
+
+		bypass_caps_init(dev);
+
+		init_bypass_wd_auto(dev);
+		init_bypass_tpl_auto(dev);
+		if (NOKIA_SERIES(dev->subdevice))
+			reset_cont(dev);
+	}
+#ifdef BP_SELF_TEST
+	if ((dev->bp_tx_data = kzalloc(BPTEST_DATA_LEN, GFP_KERNEL))) {
+		memset(dev->bp_tx_data, 0xff, 6);
+		memset(dev->bp_tx_data + 6, 0x0, 1);
+		memset(dev->bp_tx_data + 7, 0xaa, 5);
+		*(__be16 *)(dev->bp_tx_data + 12) = htons(ETH_P_BPTEST);
+	} else
+		printk("bp_ctl: Memory allocation error!\n");
+#endif
+	return 0;
+}
+
 /*
 * Initialize the module - Register the character device
 */
@@ -6694,7 +6727,7 @@
 {
 	int ret_val, idx, idx_dev = 0;
 	struct pci_dev *pdev1 = NULL;
-	unsigned long mmio_start, mmio_len;
+	bpctl_dev_t *dev;
 
 	printk(BP_MOD_DESCR " v" BP_MOD_VER "\n");
 	ret_val = register_chrdev(major_num, DEVICE_NAME, &Fops);
@@ -6729,181 +6762,16 @@
 	memset(bpctl_dev_arr, 0, ((device_num) * sizeof(bpctl_dev_t)));
 
 	pdev1 = NULL;
+	dev = bpctl_dev_arr;
 	for (idx = 0; tx_ctl_pci_tbl[idx].vendor; idx++) {
 		while ((pdev1 = pci_get_subsys(tx_ctl_pci_tbl[idx].vendor,
 					       tx_ctl_pci_tbl[idx].device,
 					       tx_ctl_pci_tbl[idx].subvendor,
 					       tx_ctl_pci_tbl[idx].subdevice,
 					       pdev1))) {
-			bpctl_dev_arr[idx_dev].pdev = pdev1;
-
-			mmio_start = pci_resource_start(pdev1, 0);
-			mmio_len = pci_resource_len(pdev1, 0);
-
-			bpctl_dev_arr[idx_dev].desc =
-			    dev_desc[tx_ctl_pci_tbl[idx].index].name;
-			bpctl_dev_arr[idx_dev].name =
-			    tx_ctl_pci_tbl[idx].bp_name;
-			bpctl_dev_arr[idx_dev].device =
-			    tx_ctl_pci_tbl[idx].device;
-			bpctl_dev_arr[idx_dev].vendor =
-			    tx_ctl_pci_tbl[idx].vendor;
-			bpctl_dev_arr[idx_dev].subdevice =
-			    tx_ctl_pci_tbl[idx].subdevice;
-			bpctl_dev_arr[idx_dev].subvendor =
-			    tx_ctl_pci_tbl[idx].subvendor;
-			/* bpctl_dev_arr[idx_dev].pdev=pdev1; */
-			bpctl_dev_arr[idx_dev].func = PCI_FUNC(pdev1->devfn);
-			bpctl_dev_arr[idx_dev].slot = PCI_SLOT(pdev1->devfn);
-			bpctl_dev_arr[idx_dev].bus = pdev1->bus->number;
-			bpctl_dev_arr[idx_dev].mem_map =
-			    (unsigned long)ioremap(mmio_start, mmio_len);
-#ifdef BP_SYNC_FLAG
-			spin_lock_init(&bpctl_dev_arr[idx_dev].bypass_wr_lock);
-#endif
-			if (BP10G9_IF_SERIES(bpctl_dev_arr[idx_dev].subdevice))
-				bpctl_dev_arr[idx_dev].bp_10g9 = 1;
-			if (BP10G_IF_SERIES(bpctl_dev_arr[idx_dev].subdevice))
-				bpctl_dev_arr[idx_dev].bp_10g = 1;
-			if (PEG540_IF_SERIES(bpctl_dev_arr[idx_dev].subdevice)) {
-
-				bpctl_dev_arr[idx_dev].bp_540 = 1;
-			}
-			if (PEGF5_IF_SERIES(bpctl_dev_arr[idx_dev].subdevice))
-				bpctl_dev_arr[idx_dev].bp_fiber5 = 1;
-			if (PEG80_IF_SERIES(bpctl_dev_arr[idx_dev].subdevice))
-				bpctl_dev_arr[idx_dev].bp_i80 = 1;
-			if (PEGF80_IF_SERIES(bpctl_dev_arr[idx_dev].subdevice))
-				bpctl_dev_arr[idx_dev].bp_i80 = 1;
-			if ((bpctl_dev_arr[idx_dev].subdevice & 0xa00) == 0xa00)
-				bpctl_dev_arr[idx_dev].bp_i80 = 1;
-			if (BP10GB_IF_SERIES(bpctl_dev_arr[idx_dev].subdevice)) {
-				if (bpctl_dev_arr[idx_dev].ifindex == 0) {
-					unregister_chrdev(major_num,
-							  DEVICE_NAME);
-					printk
-					    ("Please load network driver for %s adapter!\n",
-					     bpctl_dev_arr[idx_dev].name);
-					return -1;
-				}
-
-				if (bpctl_dev_arr[idx_dev].ndev) {
-					if (!
-					    (bpctl_dev_arr[idx_dev].ndev->
-					     flags & IFF_UP)) {
-						if (!
-						    (bpctl_dev_arr[idx_dev].
-						     ndev->flags & IFF_UP)) {
-							unregister_chrdev
-							    (major_num,
-							     DEVICE_NAME);
-							printk
-							    ("Please bring up network interfaces for %s adapter!\n",
-							     bpctl_dev_arr
-							     [idx_dev].name);
-							return -1;
-						}
-
-					}
-				}
-				bpctl_dev_arr[idx_dev].bp_10gb = 1;
-			}
-
-			if (!bpctl_dev_arr[idx_dev].bp_10g9) {
-
-				if (is_bypass_fn(&bpctl_dev_arr[idx_dev])) {
-					printk(KERN_INFO "%s found, ",
-					       bpctl_dev_arr[idx_dev].name);
-					if ((OLD_IF_SERIES
-					     (bpctl_dev_arr[idx_dev].subdevice))
-					    ||
-					    (INTEL_IF_SERIES
-					     (bpctl_dev_arr[idx_dev].
-					      subdevice)))
-						bpctl_dev_arr[idx_dev].
-						    bp_fw_ver = 0xff;
-					else
-						bpctl_dev_arr[idx_dev].
-						    bp_fw_ver =
-						    bypass_fw_ver(&bpctl_dev_arr
-								  [idx_dev]);
-					if ((bpctl_dev_arr[idx_dev].bp_10gb ==
-					     1)
-					    && (bpctl_dev_arr[idx_dev].
-						bp_fw_ver == 0xff)) {
-						int cnt = 100;
-						while (cnt--) {
-							iounmap((void
-								 *)
-								(bpctl_dev_arr
-								 [idx_dev].
-								 mem_map));
-							mmio_start =
-							    pci_resource_start
-							    (pdev1, 0);
-							mmio_len =
-							    pci_resource_len
-							    (pdev1, 0);
-
-							bpctl_dev_arr[idx_dev].
-							    mem_map =
-							    (unsigned long)
-							    ioremap(mmio_start,
-								    mmio_len);
-
-							bpctl_dev_arr[idx_dev].
-							    bp_fw_ver =
-							    bypass_fw_ver
-							    (&bpctl_dev_arr
-							     [idx_dev]);
-							if (bpctl_dev_arr
-							    [idx_dev].
-							    bp_fw_ver == 0xa8)
-								break;
-
-						}
-					}
-					/* bpctl_dev_arr[idx_dev].bp_fw_ver=0xa8; */
-					printk("firmware version: 0x%x\n",
-					       bpctl_dev_arr[idx_dev].
-					       bp_fw_ver);
-				}
-				bpctl_dev_arr[idx_dev].wdt_status =
-				    WDT_STATUS_UNKNOWN;
-				bpctl_dev_arr[idx_dev].reset_time = 0;
-				atomic_set(&bpctl_dev_arr[idx_dev].wdt_busy, 0);
-				bpctl_dev_arr[idx_dev].bp_status_un = 1;
-
-				bypass_caps_init(&bpctl_dev_arr[idx_dev]);
-
-				init_bypass_wd_auto(&bpctl_dev_arr[idx_dev]);
-				init_bypass_tpl_auto(&bpctl_dev_arr[idx_dev]);
-				if (NOKIA_SERIES
-				    (bpctl_dev_arr[idx_dev].subdevice))
-					reset_cont(&bpctl_dev_arr[idx_dev]);
-			}
-#ifdef BP_SELF_TEST
-			if ((bpctl_dev_arr[idx_dev].bp_tx_data =
-			     kmalloc(BPTEST_DATA_LEN, GFP_KERNEL))) {
-
-				memset(bpctl_dev_arr[idx_dev].bp_tx_data, 0x0,
-				       BPTEST_DATA_LEN);
-
-				memset(bpctl_dev_arr[idx_dev].bp_tx_data, 0xff,
-				       6);
-				memset(bpctl_dev_arr[idx_dev].bp_tx_data + 6,
-				       0x0, 1);
-				memset(bpctl_dev_arr[idx_dev].bp_tx_data + 7,
-				       0xaa, 5);
-
-				*(__be16 *) (bpctl_dev_arr[idx_dev].bp_tx_data +
-					     12) = htons(ETH_P_BPTEST);
-
-			} else
-				printk("bp_ctl: Memory allocation error!\n");
-#endif
-			idx_dev++;
-
+			if (init_one(dev, &tx_ctl_pci_tbl[idx], pdev1) < 0)
+				return -1;
+			dev++;
 		}
 	}
 	if_scan_init();
@@ -6913,33 +6781,27 @@
 	{
 
 		bpctl_dev_t *pbpctl_dev_c = NULL;
-		for (idx_dev = 0;
-		     ((bpctl_dev_arr[idx_dev].pdev != NULL)
-		      && (idx_dev < device_num)); idx_dev++) {
-			if (bpctl_dev_arr[idx_dev].bp_10g9) {
-				pbpctl_dev_c =
-				    get_status_port_fn(&bpctl_dev_arr[idx_dev]);
-				if (is_bypass_fn(&bpctl_dev_arr[idx_dev])) {
+		for (idx_dev = 0, dev = bpctl_dev_arr;
+		     idx_dev < device_num && dev->pdev;
+		     idx_dev++, dev++) {
+			if (dev->bp_10g9) {
+				pbpctl_dev_c = get_status_port_fn(dev);
+				if (is_bypass_fn(dev)) {
 					printk(KERN_INFO "%s found, ",
-					       bpctl_dev_arr[idx_dev].name);
-					bpctl_dev_arr[idx_dev].bp_fw_ver =
-					    bypass_fw_ver(&bpctl_dev_arr
-							  [idx_dev]);
+					       dev->name);
+					dev->bp_fw_ver = bypass_fw_ver(dev);
 					printk("firmware version: 0x%x\n",
-					       bpctl_dev_arr[idx_dev].
-					       bp_fw_ver);
-
+					       dev->bp_fw_ver);
 				}
-				bpctl_dev_arr[idx_dev].wdt_status =
-				    WDT_STATUS_UNKNOWN;
-				bpctl_dev_arr[idx_dev].reset_time = 0;
-				atomic_set(&bpctl_dev_arr[idx_dev].wdt_busy, 0);
-				bpctl_dev_arr[idx_dev].bp_status_un = 1;
+				dev->wdt_status = WDT_STATUS_UNKNOWN;
+				dev->reset_time = 0;
+				atomic_set(&dev->wdt_busy, 0);
+				dev->bp_status_un = 1;
 
-				bypass_caps_init(&bpctl_dev_arr[idx_dev]);
+				bypass_caps_init(dev);
 
-				init_bypass_wd_auto(&bpctl_dev_arr[idx_dev]);
-				init_bypass_tpl_auto(&bpctl_dev_arr[idx_dev]);
+				init_bypass_wd_auto(dev);
+				init_bypass_tpl_auto(dev);
 
 			}
 
@@ -7336,78 +7198,11 @@
 
 #define BP_PROC_DIR "bypass"
 
-#define GPIO6_SET_ENTRY_SD           "gpio6_set"
-#define GPIO6_CLEAR_ENTRY_SD         "gpio6_clear"
-
-#define GPIO7_SET_ENTRY_SD           "gpio7_set"
-#define GPIO7_CLEAR_ENTRY_SD         "gpio7_clear"
-
-#define PULSE_SET_ENTRY_SD            "pulse_set"
-#define ZERO_SET_ENTRY_SD            "zero_set"
-#define PULSE_GET1_ENTRY_SD            "pulse_get1"
-#define PULSE_GET2_ENTRY_SD            "pulse_get2"
-
-#define CMND_ON_ENTRY_SD              "cmnd_on"
-#define CMND_OFF_ENTRY_SD             "cmnd_off"
-#define RESET_CONT_ENTRY_SD           "reset_cont"
-
- /*COMMANDS*/
-#define BYPASS_INFO_ENTRY_SD     "bypass_info"
-#define BYPASS_SLAVE_ENTRY_SD    "bypass_slave"
-#define BYPASS_CAPS_ENTRY_SD     "bypass_caps"
-#define WD_SET_CAPS_ENTRY_SD     "wd_set_caps"
-#define BYPASS_ENTRY_SD          "bypass"
-#define BYPASS_CHANGE_ENTRY_SD   "bypass_change"
-#define BYPASS_WD_ENTRY_SD       "bypass_wd"
-#define WD_EXPIRE_TIME_ENTRY_SD  "wd_expire_time"
-#define RESET_BYPASS_WD_ENTRY_SD "reset_bypass_wd"
-#define DIS_BYPASS_ENTRY_SD      "dis_bypass"
-#define BYPASS_PWUP_ENTRY_SD     "bypass_pwup"
-#define BYPASS_PWOFF_ENTRY_SD     "bypass_pwoff"
-#define STD_NIC_ENTRY_SD         "std_nic"
-#define STD_NIC_ENTRY_SD         "std_nic"
-#define TAP_ENTRY_SD             "tap"
-#define TAP_CHANGE_ENTRY_SD      "tap_change"
-#define DIS_TAP_ENTRY_SD         "dis_tap"
-#define TAP_PWUP_ENTRY_SD        "tap_pwup"
-#define TWO_PORT_LINK_ENTRY_SD   "two_port_link"
-#define WD_EXP_MODE_ENTRY_SD     "wd_exp_mode"
-#define WD_AUTORESET_ENTRY_SD    "wd_autoreset"
-#define TPL_ENTRY_SD             "tpl"
-#define WAIT_AT_PWUP_ENTRY_SD    "wait_at_pwup"
-#define HW_RESET_ENTRY_SD        "hw_reset"
-#define DISC_ENTRY_SD             "disc"
-#define DISC_CHANGE_ENTRY_SD      "disc_change"
-#define DIS_DISC_ENTRY_SD         "dis_disc"
-#define DISC_PWUP_ENTRY_SD        "disc_pwup"
 static struct proc_dir_entry *bp_procfs_dir;
 
-static struct proc_dir_entry *proc_getdir(char *name,
-					  struct proc_dir_entry *proc_dir)
-{
-	struct proc_dir_entry *pde = proc_dir;
-
-	for (pde = pde->subdir; pde; pde = pde->next) {
-		if (pde->namelen && (strcmp(name, pde->name) == 0)) {
-			/* directory exists */
-			break;
-		}
-	}
-	if (pde == (struct proc_dir_entry *)0) {
-		/* create the directory */
-		pde = proc_mkdir(name, proc_dir);
-		if (pde == (struct proc_dir_entry *)0) {
-
-			return pde;
-		}
-	}
-
-	return pde;
-}
-
 int bp_proc_create(void)
 {
-	bp_procfs_dir = proc_getdir(BP_PROC_DIR, init_net.proc_net);
+	bp_procfs_dir = proc_mkdir(BP_PROC_DIR, init_net.proc_net);
 	if (bp_procfs_dir == (struct proc_dir_entry *)0) {
 		printk(KERN_DEBUG
 		       "Could not create procfs nicinfo directory %s\n",
@@ -7417,144 +7212,99 @@
 	return 0;
 }
 
-int
-bypass_proc_create_entry_sd(struct pfs_unit_sd *pfs_unit_curr,
-			    char *proc_name,
-			    write_proc_t *write_proc,
-			    read_proc_t *read_proc,
-			    struct proc_dir_entry *parent_pfs, void *data)
+static int procfs_add(char *proc_name, const struct file_operations *fops,
+		      bpctl_dev_t *dev)
 {
-	strcpy(pfs_unit_curr->proc_name, proc_name);
-	pfs_unit_curr->proc_entry = create_proc_entry(pfs_unit_curr->proc_name,
-						      S_IFREG | S_IRUSR |
-						      S_IWUSR | S_IRGRP |
-						      S_IROTH, parent_pfs);
-	if (pfs_unit_curr->proc_entry == NULL)
+	struct bypass_pfs_sd *pfs = &dev->bypass_pfs_set;
+	if (!proc_create_data(proc_name, 0644, pfs->bypass_entry, fops, dev))
 		return -1;
-
-	pfs_unit_curr->proc_entry->read_proc = read_proc;
-	pfs_unit_curr->proc_entry->write_proc = write_proc;
-	pfs_unit_curr->proc_entry->data = data;
-
 	return 0;
-
 }
 
-int
-get_bypass_info_pfs(char *page, char **start, off_t off, int count,
-		    int *eof, void *data)
+#define RO_FOPS(name)	\
+static int name##_open(struct inode *inode, struct file *file)	\
+{								\
+	return single_open(file, show_##name, PDE_DATA(inode));\
+}								\
+static const struct file_operations name##_ops = {		\
+	.open = name##_open,					\
+	.read = seq_read,					\
+	.llseek = seq_lseek,					\
+	.release = single_release,				\
+};
+
+#define RW_FOPS(name)	\
+static int name##_open(struct inode *inode, struct file *file)	\
+{								\
+	return single_open(file, show_##name, PDE_DATA(inode));\
+}								\
+static const struct file_operations name##_ops = {		\
+	.open = name##_open,					\
+	.read = seq_read,					\
+	.write = name##_write,					\
+	.llseek = seq_lseek,					\
+	.release = single_release,				\
+};
+
+static int show_bypass_info(struct seq_file *m, void *v)
 {
-	bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data;
-	int len = 0;
+	bpctl_dev_t *dev = m->private;
 
-	len += sprintf(page, "Name\t\t\t%s\n", pbp_device_block->name);
-	len +=
-	    sprintf(page + len, "Firmware version\t0x%x\n",
-		    pbp_device_block->bp_fw_ver);
-
-	*eof = 1;
-	return len;
+	seq_printf(m, "Name\t\t\t%s\n", dev->name);
+	seq_printf(m, "Firmware version\t0x%x\n", dev->bp_fw_ver);
+	return 0;
 }
+RO_FOPS(bypass_info)
 
-int
-get_bypass_slave_pfs(char *page, char **start, off_t off, int count,
-		     int *eof, void *data)
+static int show_bypass_slave(struct seq_file *m, void *v)
 {
-	bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data;
-
-	int len = 0;
-	bpctl_dev_t *pbp_device_block_slave = NULL;
-	int idx_dev = 0;
-	struct net_device *net_slave_dev = NULL;
-
-	if ((pbp_device_block->func == 0) || (pbp_device_block->func == 2)) {
-		for (idx_dev = 0;
-		     ((bpctl_dev_arr[idx_dev].pdev != NULL)
-		      && (idx_dev < device_num)); idx_dev++) {
-			if ((bpctl_dev_arr[idx_dev].bus ==
-			     pbp_device_block->bus)
-			    && (bpctl_dev_arr[idx_dev].slot ==
-				pbp_device_block->slot)) {
-				if ((pbp_device_block->func == 0)
-				    && (bpctl_dev_arr[idx_dev].func == 1)) {
-					pbp_device_block_slave =
-					    &bpctl_dev_arr[idx_dev];
-					break;
-				}
-				if ((pbp_device_block->func == 2) &&
-				    (bpctl_dev_arr[idx_dev].func == 3)) {
-					pbp_device_block_slave =
-					    &bpctl_dev_arr[idx_dev];
-					break;
-				}
-			}
-		}
-	} else
-		pbp_device_block_slave = pbp_device_block;
-	if (!pbp_device_block_slave) {
-		len = sprintf(page, "fail\n");
-		*eof = 1;
-		return len;
-	}
-	net_slave_dev = pbp_device_block_slave->ndev;
-	if (net_slave_dev)
-		len = sprintf(page, "%s\n", net_slave_dev->name);
-
-	*eof = 1;
-	return len;
+	bpctl_dev_t *dev = m->private;
+	bpctl_dev_t *slave = get_status_port_fn(dev);
+	if (!slave)
+		slave = dev;
+	if (!slave)
+		seq_printf(m, "fail\n");
+	else if (slave->ndev)
+		seq_printf(m, "%s\n", slave->ndev->name);
+	return 0;
 }
+RO_FOPS(bypass_slave)
 
-int
-get_bypass_caps_pfs(char *page, char **start, off_t off, int count,
-		    int *eof, void *data)
+static int show_bypass_caps(struct seq_file *m, void *v)
 {
-	bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data;
-
-	int len = 0, ret = 0;
-
-	ret = get_bypass_caps_fn(pbp_device_block);
+	bpctl_dev_t *dev = m->private;
+	int ret = get_bypass_caps_fn(dev);
 	if (ret == BP_NOT_CAP)
-		len = sprintf(page, "-1\n");
+		seq_printf(m, "-1\n");
 	else
-		len = sprintf(page, "0x%x\n", ret);
-	*eof = 1;
-	return len;
-
+		seq_printf(m, "0x%x\n", ret);
+	return 0;
 }
+RO_FOPS(bypass_caps)
 
-int
-get_wd_set_caps_pfs(char *page, char **start, off_t off, int count,
-		    int *eof, void *data)
+static int show_wd_set_caps(struct seq_file *m, void *v)
 {
-	bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data;
-
-	int len = 0, ret = 0;
-
-	ret = get_wd_set_caps_fn(pbp_device_block);
+	bpctl_dev_t *dev = m->private;
+	int ret = get_wd_set_caps_fn(dev);
 	if (ret == BP_NOT_CAP)
-		len = sprintf(page, "-1\n");
+		seq_printf(m, "-1\n");
 	else
-		len = sprintf(page, "0x%x\n", ret);
-	*eof = 1;
-	return len;
+		seq_printf(m, "0x%x\n", ret);
+	return 0;
 }
+RO_FOPS(wd_set_caps)
 
-int
-set_bypass_pfs(struct file *file, const char *buffer,
-	       unsigned long count, void *data)
+static int user_on_off(const void __user *buffer, size_t count)
 {
 
 	char kbuf[256];
-	bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data;
-
-	int bypass_param = 0, length = 0;
+	int length = 0;
 
 	if (count > (sizeof(kbuf) - 1))
 		return -1;
 
-	if (copy_from_user(&kbuf, buffer, count)) {
+	if (copy_from_user(&kbuf, buffer, count))
 		return -1;
-	}
 
 	kbuf[count] = '\0';
 	length = strlen(kbuf);
@@ -7562,806 +7312,467 @@
 		kbuf[--length] = '\0';
 
 	if (strcmp(kbuf, "on") == 0)
-		bypass_param = 1;
-	else if (strcmp(kbuf, "off") == 0)
-		bypass_param = 0;
+		return 1;
+	if (strcmp(kbuf, "off") == 0)
+		return 0;
+	return 0;
+}
 
-	set_bypass_fn(pbp_device_block, bypass_param);
+static ssize_t bypass_write(struct file *file, const char __user *buffer,
+				  size_t count, loff_t *pos)
+{
+	int bypass_param = user_on_off(buffer, count);
+	if (bypass_param < 0)
+		return -1;
 
+	set_bypass_fn(PDE_DATA(file_inode(file)), bypass_param);
 	return count;
 }
-
-int
-set_tap_pfs(struct file *file, const char *buffer,
-	    unsigned long count, void *data)
+static int show_bypass(struct seq_file *m, void *v)
 {
+	bpctl_dev_t *dev = m->private;
+	int ret = get_bypass_fn(dev);
+	if (ret == BP_NOT_CAP)
+		seq_printf(m, "fail\n");
+	else if (ret == 1)
+		seq_printf(m, "on\n");
+	else if (ret == 0)
+		seq_printf(m, "off\n");
+	return 0;
+}
+RW_FOPS(bypass)
 
-	char kbuf[256];
-	bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data;
-
-	int tap_param = 0, length = 0;
-
-	if (count > (sizeof(kbuf) - 1))
+static ssize_t tap_write(struct file *file, const char __user *buffer,
+				  size_t count, loff_t *pos)
+{
+	int tap_param = user_on_off(buffer, count);
+	if (tap_param < 0)
 		return -1;
 
-	if (copy_from_user(&kbuf, buffer, count)) {
-		return -1;
-	}
-
-	kbuf[count] = '\0';
-	length = strlen(kbuf);
-	if (kbuf[length - 1] == '\n')
-		kbuf[--length] = '\0';
-
-	if (strcmp(kbuf, "on") == 0)
-		tap_param = 1;
-	else if (strcmp(kbuf, "off") == 0)
-		tap_param = 0;
-
-	set_tap_fn(pbp_device_block, tap_param);
-
+	set_tap_fn(PDE_DATA(file_inode(file)), tap_param);
 	return count;
 }
-
-int
-set_disc_pfs(struct file *file, const char *buffer,
-	     unsigned long count, void *data)
+static int show_tap(struct seq_file *m, void *v)
 {
+	bpctl_dev_t *dev = m->private;
+	int ret = get_tap_fn(dev);
+	if (ret == BP_NOT_CAP)
+		seq_printf(m, "fail\n");
+	else if (ret == 1)
+		seq_printf(m, "on\n");
+	else if (ret == 0)
+		seq_printf(m, "off\n");
+	return 0;
+}
+RW_FOPS(tap)
 
-	char kbuf[256];
-	bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data;
-
-	int tap_param = 0, length = 0;
-
-	if (count > (sizeof(kbuf) - 1))
+static ssize_t disc_write(struct file *file, const char __user *buffer,
+				  size_t count, loff_t *pos)
+{
+	int tap_param = user_on_off(buffer, count);
+	if (tap_param < 0)
 		return -1;
 
-	if (copy_from_user(&kbuf, buffer, count)) {
-		return -1;
-	}
-
-	kbuf[count] = '\0';
-	length = strlen(kbuf);
-	if (kbuf[length - 1] == '\n')
-		kbuf[--length] = '\0';
-
-	if (strcmp(kbuf, "on") == 0)
-		tap_param = 1;
-	else if (strcmp(kbuf, "off") == 0)
-		tap_param = 0;
-
-	set_disc_fn(pbp_device_block, tap_param);
-
+	set_disc_fn(PDE_DATA(file_inode(file)), tap_param);
 	return count;
 }
-
-int
-get_bypass_pfs(char *page, char **start, off_t off, int count,
-	       int *eof, void *data)
+static int show_disc(struct seq_file *m, void *v)
 {
-	bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data;
-
-	int len = 0, ret = 0;
-
-	ret = get_bypass_fn(pbp_device_block);
+	bpctl_dev_t *dev = m->private;
+	int ret = get_disc_fn(dev);
 	if (ret == BP_NOT_CAP)
-		len = sprintf(page, "fail\n");
+		seq_printf(m, "fail\n");
 	else if (ret == 1)
-		len = sprintf(page, "on\n");
+		seq_printf(m, "on\n");
 	else if (ret == 0)
-		len = sprintf(page, "off\n");
-
-	*eof = 1;
-	return len;
+		seq_printf(m, "off\n");
+	return 0;
 }
+RW_FOPS(disc)
 
-int
-get_tap_pfs(char *page, char **start, off_t off, int count,
-	    int *eof, void *data)
+static int show_bypass_change(struct seq_file *m, void *v)
 {
-	bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data;
-
-	int len = 0, ret = 0;
-
-	ret = get_tap_fn(pbp_device_block);
-	if (ret == BP_NOT_CAP)
-		len = sprintf(page, "fail\n");
-	else if (ret == 1)
-		len = sprintf(page, "on\n");
-	else if (ret == 0)
-		len = sprintf(page, "off\n");
-
-	*eof = 1;
-	return len;
-}
-
-int
-get_disc_pfs(char *page, char **start, off_t off, int count,
-	     int *eof, void *data)
-{
-	bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data;
-
-	int len = 0, ret = 0;
-
-	ret = get_disc_fn(pbp_device_block);
-	if (ret == BP_NOT_CAP)
-		len = sprintf(page, "fail\n");
-	else if (ret == 1)
-		len = sprintf(page, "on\n");
-	else if (ret == 0)
-		len = sprintf(page, "off\n");
-
-	*eof = 1;
-	return len;
-}
-
-int
-get_bypass_change_pfs(char *page, char **start, off_t off, int count,
-		      int *eof, void *data)
-{
-	bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data;
-
-	int len = 0, ret = 0;
-
-	ret = get_bypass_change_fn(pbp_device_block);
+	bpctl_dev_t *dev = m->private;
+	int ret = get_bypass_change_fn(dev);
 	if (ret == 1)
-		len = sprintf(page, "on\n");
+		seq_printf(m, "on\n");
 	else if (ret == 0)
-		len = sprintf(page, "off\n");
+		seq_printf(m, "off\n");
 	else
-		len = sprintf(page, "fail\n");
-
-	*eof = 1;
-	return len;
+		seq_printf(m, "fail\n");
+	return 0;
 }
+RO_FOPS(bypass_change)
 
-int
-get_tap_change_pfs(char *page, char **start, off_t off, int count,
-		   int *eof, void *data)
+static int show_tap_change(struct seq_file *m, void *v)
 {
-	bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data;
-
-	int len = 0, ret = 0;
-
-	ret = get_tap_change_fn(pbp_device_block);
+	bpctl_dev_t *dev = m->private;
+	int ret = get_tap_change_fn(dev);
 	if (ret == 1)
-		len = sprintf(page, "on\n");
+		seq_printf(m, "on\n");
 	else if (ret == 0)
-		len = sprintf(page, "off\n");
+		seq_printf(m, "off\n");
 	else
-		len = sprintf(page, "fail\n");
-
-	*eof = 1;
-	return len;
+		seq_printf(m, "fail\n");
+	return 0;
 }
+RO_FOPS(tap_change)
 
-int
-get_disc_change_pfs(char *page, char **start, off_t off, int count,
-		    int *eof, void *data)
+static int show_disc_change(struct seq_file *m, void *v)
 {
-	bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data;
-
-	int len = 0, ret = 0;
-
-	ret = get_disc_change_fn(pbp_device_block);
+	bpctl_dev_t *dev = m->private;
+	int ret = get_disc_change_fn(dev);
 	if (ret == 1)
-		len = sprintf(page, "on\n");
+		seq_printf(m, "on\n");
 	else if (ret == 0)
-		len = sprintf(page, "off\n");
+		seq_printf(m, "off\n");
 	else
-		len = sprintf(page, "fail\n");
-
-	*eof = 1;
-	return len;
+		seq_printf(m, "fail\n");
+	return 0;
 }
+RO_FOPS(disc_change)
 
-#define isdigit(c) (c >= '0' && c <= '9')
-__inline static int atoi(char **s)
+static ssize_t bypass_wd_write(struct file *file, const char __user *buffer,
+				  size_t count, loff_t *pos)
 {
-	int i = 0;
-	while (isdigit(**s))
-		i = i * 10 + *((*s)++) - '0';
-	return i;
-}
-
-int
-set_bypass_wd_pfs(struct file *file, const char *buffer,
-		  unsigned long count, void *data)
-{
-	bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data;
+	bpctl_dev_t *dev = PDE_DATA(file_inode(file));
 	int timeout;
-	int ret;
-
-	ret = kstrtoint_from_user(buffer, count, 10, &timeout);
+	int ret = kstrtoint_from_user(buffer, count, 10, &timeout);
 	if (ret)
 		return ret;
-	set_bypass_wd_fn(pbp_device_block, timeout);
-
+	set_bypass_wd_fn(dev, timeout);
 	return count;
 }
-
-int
-get_bypass_wd_pfs(char *page, char **start, off_t off, int count,
-		  int *eof, void *data)
+static int show_bypass_wd(struct seq_file *m, void *v)
 {
-	bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data;
+	bpctl_dev_t *dev = m->private;
+	int ret = 0, timeout = 0;
 
-	int len = 0, ret = 0, timeout = 0;
-
-	ret = get_bypass_wd_fn(pbp_device_block, &timeout);
+	ret = get_bypass_wd_fn(dev, &timeout);
 	if (ret == BP_NOT_CAP)
-		len = sprintf(page, "fail\n");
+		seq_printf(m,  "fail\n");
 	else if (timeout == -1)
-		len = sprintf(page, "unknown\n");
+		seq_printf(m,  "unknown\n");
 	else if (timeout == 0)
-		len = sprintf(page, "disable\n");
+		seq_printf(m,  "disable\n");
 	else
-		len = sprintf(page, "%d\n", timeout);
-
-	*eof = 1;
-	return len;
+		seq_printf(m, "%d\n", timeout);
+	return 0;
 }
+RW_FOPS(bypass_wd)
 
-int
-get_wd_expire_time_pfs(char *page, char **start, off_t off, int count,
-		       int *eof, void *data)
+static int show_wd_expire_time(struct seq_file *m, void *v)
 {
-	bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data;
-
-	int len = 0, ret = 0, timeout = 0;
-
-	ret = get_wd_expire_time_fn(pbp_device_block, &timeout);
+	bpctl_dev_t *dev = m->private;
+	int ret = 0, timeout = 0;
+	ret = get_wd_expire_time_fn(dev, &timeout);
 	if (ret == BP_NOT_CAP)
-		len = sprintf(page, "fail\n");
+		seq_printf(m, "fail\n");
 	else if (timeout == -1)
-		len = sprintf(page, "expire\n");
+		seq_printf(m, "expire\n");
 	else if (timeout == 0)
-		len = sprintf(page, "disable\n");
-
+		seq_printf(m, "disable\n");
 	else
-		len = sprintf(page, "%d\n", timeout);
-	*eof = 1;
-	return len;
+		seq_printf(m, "%d\n", timeout);
+	return 0;
 }
+RO_FOPS(wd_expire_time)
 
-int
-get_tpl_pfs(char *page, char **start, off_t off, int count,
-	    int *eof, void *data)
+static ssize_t tpl_write(struct file *file, const char __user *buffer,
+				  size_t count, loff_t *pos)
 {
-	bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data;
+	bpctl_dev_t *dev = PDE_DATA(file_inode(file));
+	int tpl_param = user_on_off(buffer, count);
+	if (tpl_param < 0)
+		return -1;
 
-	int len = 0, ret = 0;
-
-	ret = get_tpl_fn(pbp_device_block);
+	set_tpl_fn(dev, tpl_param);
+	return count;
+}
+static int show_tpl(struct seq_file *m, void *v)
+{
+	bpctl_dev_t *dev = m->private;
+	int ret = get_tpl_fn(dev);
 	if (ret == BP_NOT_CAP)
-		len = sprintf(page, "fail\n");
+		seq_printf(m, "fail\n");
 	else if (ret == 1)
-		len = sprintf(page, "on\n");
+		seq_printf(m, "on\n");
 	else if (ret == 0)
-		len = sprintf(page, "off\n");
-
-	*eof = 1;
-	return len;
+		seq_printf(m, "off\n");
+	return 0;
 }
+RW_FOPS(tpl)
 
 #ifdef PMC_FIX_FLAG
-int
-get_wait_at_pwup_pfs(char *page, char **start, off_t off, int count,
-		     int *eof, void *data)
+static ssize_t wait_at_pwup_write(struct file *file, const char __user *buffer,
+				  size_t count, loff_t *pos)
 {
-	bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data;
+	bpctl_dev_t *dev = PDE_DATA(file_inode(file));
+	int tpl_param = user_on_off(buffer, count);
+	if (tpl_param < 0)
+		return -1;
 
-	int len = 0, ret = 0;
-
-	ret = get_bp_wait_at_pwup_fn(pbp_device_block);
-	if (ret == BP_NOT_CAP)
-		len = sprintf(page, "fail\n");
-	else if (ret == 1)
-		len = sprintf(page, "on\n");
-	else if (ret == 0)
-		len = sprintf(page, "off\n");
-
-	*eof = 1;
-	return len;
+	set_bp_wait_at_pwup_fn(dev, tpl_param);
+	return count;
 }
-
-int
-get_hw_reset_pfs(char *page, char **start, off_t off, int count,
-		 int *eof, void *data)
+static int show_wait_at_pwup(struct seq_file *m, void *v)
 {
-	bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data;
-
-	int len = 0, ret = 0;
-
-	ret = get_bp_hw_reset_fn(pbp_device_block);
+	bpctl_dev_t *dev = m->private;
+	int ret = get_bp_wait_at_pwup_fn(dev);
 	if (ret == BP_NOT_CAP)
-		len = sprintf(page, "fail\n");
+		seq_printf(m, "fail\n");
 	else if (ret == 1)
-		len = sprintf(page, "on\n");
+		seq_printf(m, "on\n");
 	else if (ret == 0)
-		len = sprintf(page, "off\n");
-
-	*eof = 1;
-	return len;
+		seq_printf(m, "off\n");
+	return 0;
 }
+RW_FOPS(wait_at_pwup)
+
+static ssize_t hw_reset_write(struct file *file, const char __user *buffer,
+				  size_t count, loff_t *pos)
+{
+	bpctl_dev_t *dev = PDE_DATA(file_inode(file));
+	int tpl_param = user_on_off(buffer, count);
+	if (tpl_param < 0)
+		return -1;
+
+	set_bp_hw_reset_fn(dev, tpl_param);
+	return count;
+}
+static int show_hw_reset(struct seq_file *m, void *v)
+{
+	bpctl_dev_t *dev = m->private;
+	int ret = get_bp_hw_reset_fn(dev);
+	if (ret == BP_NOT_CAP)
+		seq_printf(m, "fail\n");
+	else if (ret == 1)
+		seq_printf(m, "on\n");
+	else if (ret == 0)
+		seq_printf(m, "off\n");
+	return 0;
+}
+RW_FOPS(hw_reset)
 
 #endif				/*PMC_WAIT_FLAG */
 
-int
-reset_bypass_wd_pfs(char *page, char **start, off_t off, int count,
-		    int *eof, void *data)
+static int show_reset_bypass_wd(struct seq_file *m, void *v)
 {
-	bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data;
-
-	int len = 0, ret = 0;
-
-	ret = reset_bypass_wd_timer_fn(pbp_device_block);
+	bpctl_dev_t *dev = m->private;
+	int ret = reset_bypass_wd_timer_fn(dev);
 	if (ret == BP_NOT_CAP)
-		len = sprintf(page, "fail\n");
+		seq_printf(m, "fail\n");
 	else if (ret == 0)
-		len = sprintf(page, "disable\n");
+		seq_printf(m, "disable\n");
 	else if (ret == 1)
-		len = sprintf(page, "success\n");
-
-	*eof = 1;
-	return len;
+		seq_printf(m, "success\n");
+	return 0;
 }
+RO_FOPS(reset_bypass_wd)
 
-int
-set_dis_bypass_pfs(struct file *file, const char *buffer,
-		   unsigned long count, void *data)
+static ssize_t dis_bypass_write(struct file *file, const char __user *buffer,
+				  size_t count, loff_t *pos)
 {
-
-	char kbuf[256];
-	bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data;
-
-	int bypass_param = 0, length = 0;
-
-	if (count >= sizeof(kbuf))
+	int bypass_param = user_on_off(buffer, count);
+	if (bypass_param < 0)
 		return -EINVAL;
 
-	if (copy_from_user(&kbuf, buffer, count)) {
-		return -1;
-	}
-
-	kbuf[count] = '\0';
-	length = strlen(kbuf);
-	if (kbuf[length - 1] == '\n')
-		kbuf[--length] = '\0';
-
-	if (strcmp(kbuf, "on") == 0)
-		bypass_param = 1;
-	else if (strcmp(kbuf, "off") == 0)
-		bypass_param = 0;
-
-	set_dis_bypass_fn(pbp_device_block, bypass_param);
-
+	set_dis_bypass_fn(PDE_DATA(file_inode(file)), bypass_param);
 	return count;
 }
-
-int
-set_dis_tap_pfs(struct file *file, const char *buffer,
-		unsigned long count, void *data)
+static int show_dis_bypass(struct seq_file *m, void *v)
 {
+	bpctl_dev_t *dev = m->private;
+	int ret = get_dis_bypass_fn(dev);
+	if (ret == BP_NOT_CAP)
+		seq_printf(m, "fail\n");
+	else if (ret == 0)
+		seq_printf(m, "off\n");
+	else
+		seq_printf(m, "on\n");
+	return 0;
+}
+RW_FOPS(dis_bypass)
 
-	char kbuf[256];
-	bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data;
-
-	int tap_param = 0, length = 0;
-
-	if (count >= sizeof(kbuf))
+static ssize_t dis_tap_write(struct file *file, const char __user *buffer,
+				  size_t count, loff_t *pos)
+{
+	int tap_param = user_on_off(buffer, count);
+	if (tap_param < 0)
 		return -EINVAL;
 
-	if (copy_from_user(&kbuf, buffer, count)) {
-		return -1;
-	}
-
-	kbuf[count] = '\0';
-	length = strlen(kbuf);
-	if (kbuf[length - 1] == '\n')
-		kbuf[--length] = '\0';
-
-	if (strcmp(kbuf, "on") == 0)
-		tap_param = 1;
-	else if (strcmp(kbuf, "off") == 0)
-		tap_param = 0;
-
-	set_dis_tap_fn(pbp_device_block, tap_param);
-
+	set_dis_tap_fn(PDE_DATA(file_inode(file)), tap_param);
 	return count;
 }
-
-int
-set_dis_disc_pfs(struct file *file, const char *buffer,
-		 unsigned long count, void *data)
+static int show_dis_tap(struct seq_file *m, void *v)
 {
+	bpctl_dev_t *dev = m->private;
+	int ret = get_dis_tap_fn(dev);
+	if (ret == BP_NOT_CAP)
+		seq_printf(m, "fail\n");
+	else if (ret == 0)
+		seq_printf(m, "off\n");
+	else
+		seq_printf(m, "on\n");
+	return 0;
+}
+RW_FOPS(dis_tap)
 
-	char kbuf[256];
-	bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data;
-
-	int tap_param = 0, length = 0;
-
-	if (count >= sizeof(kbuf))
+static ssize_t dis_disc_write(struct file *file, const char __user *buffer,
+				  size_t count, loff_t *pos)
+{
+	int tap_param = user_on_off(buffer, count);
+	if (tap_param < 0)
 		return -EINVAL;
 
-	if (copy_from_user(&kbuf, buffer, count)) {
-		return -1;
-	}
-
-	kbuf[count] = '\0';
-	length = strlen(kbuf);
-	if (kbuf[length - 1] == '\n')
-		kbuf[--length] = '\0';
-
-	if (strcmp(kbuf, "on") == 0)
-		tap_param = 1;
-	else if (strcmp(kbuf, "off") == 0)
-		tap_param = 0;
-
-	set_dis_disc_fn(pbp_device_block, tap_param);
-
+	set_dis_disc_fn(PDE_DATA(file_inode(file)), tap_param);
 	return count;
 }
-
-int
-get_dis_bypass_pfs(char *page, char **start, off_t off, int count,
-		   int *eof, void *data)
+static int show_dis_disc(struct seq_file *m, void *v)
 {
-	bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data;
-
-	int len = 0, ret = 0;
-
-	ret = get_dis_bypass_fn(pbp_device_block);
+	bpctl_dev_t *dev = m->private;
+	int ret = get_dis_disc_fn(dev);
 	if (ret == BP_NOT_CAP)
-		len = sprintf(page, "fail\n");
+		seq_printf(m, "fail\n");
 	else if (ret == 0)
-		len = sprintf(page, "off\n");
+		seq_printf(m, "off\n");
 	else
-		len = sprintf(page, "on\n");
-
-	*eof = 1;
-	return len;
+		seq_printf(m, "on\n");
+	return 0;
 }
+RW_FOPS(dis_disc)
 
-int
-get_dis_tap_pfs(char *page, char **start, off_t off, int count,
-		int *eof, void *data)
+static ssize_t bypass_pwup_write(struct file *file, const char __user *buffer,
+				  size_t count, loff_t *pos)
 {
-	bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data;
-
-	int len = 0, ret = 0;
-
-	ret = get_dis_tap_fn(pbp_device_block);
-	if (ret == BP_NOT_CAP)
-		len = sprintf(page, "fail\n");
-	else if (ret == 0)
-		len = sprintf(page, "off\n");
-	else
-		len = sprintf(page, "on\n");
-
-	*eof = 1;
-	return len;
-}
-
-int
-get_dis_disc_pfs(char *page, char **start, off_t off, int count,
-		 int *eof, void *data)
-{
-	bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data;
-
-	int len = 0, ret = 0;
-
-	ret = get_dis_disc_fn(pbp_device_block);
-	if (ret == BP_NOT_CAP)
-		len = sprintf(page, "fail\n");
-	else if (ret == 0)
-		len = sprintf(page, "off\n");
-	else
-		len = sprintf(page, "on\n");
-
-	*eof = 1;
-	return len;
-}
-
-int
-set_bypass_pwup_pfs(struct file *file, const char *buffer,
-		    unsigned long count, void *data)
-{
-
-	char kbuf[256];
-	bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data;
-
-	int bypass_param = 0, length = 0;
-
-	if (count >= sizeof(kbuf))
+	int bypass_param = user_on_off(buffer, count);
+	if (bypass_param < 0)
 		return -EINVAL;
 
-	if (copy_from_user(&kbuf, buffer, count)) {
-		return -1;
-	}
-
-	kbuf[count] = '\0';
-	length = strlen(kbuf);
-	if (kbuf[length - 1] == '\n')
-		kbuf[--length] = '\0';
-
-	if (strcmp(kbuf, "on") == 0)
-		bypass_param = 1;
-	else if (strcmp(kbuf, "off") == 0)
-		bypass_param = 0;
-
-	set_bypass_pwup_fn(pbp_device_block, bypass_param);
-
+	set_bypass_pwup_fn(PDE_DATA(file_inode(file)), bypass_param);
 	return count;
 }
-
-int
-set_bypass_pwoff_pfs(struct file *file, const char *buffer,
-		     unsigned long count, void *data)
+static int show_bypass_pwup(struct seq_file *m, void *v)
 {
+	bpctl_dev_t *dev = m->private;
+	int ret = get_bypass_pwup_fn(dev);
+	if (ret == BP_NOT_CAP)
+		seq_printf(m, "fail\n");
+	else if (ret == 0)
+		seq_printf(m, "off\n");
+	else
+		seq_printf(m, "on\n");
+	return 0;
+}
+RW_FOPS(bypass_pwup)
 
-	char kbuf[256];
-	bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data;
-
-	int bypass_param = 0, length = 0;
-
-	if (count >= sizeof(kbuf))
+static ssize_t bypass_pwoff_write(struct file *file, const char __user *buffer,
+				  size_t count, loff_t *pos)
+{
+	int bypass_param = user_on_off(buffer, count);
+	if (bypass_param < 0)
 		return -EINVAL;
 
-	if (copy_from_user(&kbuf, buffer, count)) {
-		return -1;
-	}
-
-	kbuf[count] = '\0';
-	length = strlen(kbuf);
-	if (kbuf[length - 1] == '\n')
-		kbuf[--length] = '\0';
-
-	if (strcmp(kbuf, "on") == 0)
-		bypass_param = 1;
-	else if (strcmp(kbuf, "off") == 0)
-		bypass_param = 0;
-
-	set_bypass_pwoff_fn(pbp_device_block, bypass_param);
-
+	set_bypass_pwoff_fn(PDE_DATA(file_inode(file)), bypass_param);
 	return count;
 }
-
-int
-set_tap_pwup_pfs(struct file *file, const char *buffer,
-		 unsigned long count, void *data)
+static int show_bypass_pwoff(struct seq_file *m, void *v)
 {
+	bpctl_dev_t *dev = m->private;
+	int ret = get_bypass_pwoff_fn(dev);
+	if (ret == BP_NOT_CAP)
+		seq_printf(m, "fail\n");
+	else if (ret == 0)
+		seq_printf(m, "off\n");
+	else
+		seq_printf(m, "on\n");
+	return 0;
+}
+RW_FOPS(bypass_pwoff)
 
-	char kbuf[256];
-	bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data;
-
-	int tap_param = 0, length = 0;
-
-	if (count >= sizeof(kbuf))
+static ssize_t tap_pwup_write(struct file *file, const char __user *buffer,
+				  size_t count, loff_t *pos)
+{
+	int tap_param = user_on_off(buffer, count);
+	if (tap_param < 0)
 		return -EINVAL;
 
-	if (copy_from_user(&kbuf, buffer, count)) {
-		return -1;
-	}
-
-	kbuf[count] = '\0';
-	length = strlen(kbuf);
-	if (kbuf[length - 1] == '\n')
-		kbuf[--length] = '\0';
-
-	if (strcmp(kbuf, "on") == 0)
-		tap_param = 1;
-	else if (strcmp(kbuf, "off") == 0)
-		tap_param = 0;
-
-	set_tap_pwup_fn(pbp_device_block, tap_param);
-
+	set_tap_pwup_fn(PDE_DATA(file_inode(file)), tap_param);
 	return count;
 }
-
-int
-set_disc_pwup_pfs(struct file *file, const char *buffer,
-		  unsigned long count, void *data)
+static int show_tap_pwup(struct seq_file *m, void *v)
 {
+	bpctl_dev_t *dev = m->private;
+	int ret = get_tap_pwup_fn(dev);
+	if (ret == BP_NOT_CAP)
+		seq_printf(m, "fail\n");
+	else if (ret == 0)
+		seq_printf(m, "off\n");
+	else
+		seq_printf(m, "on\n");
+	return 0;
+}
+RW_FOPS(tap_pwup)
 
-	char kbuf[256];
-	bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data;
-
-	int tap_param = 0, length = 0;
-
-	if (count >= sizeof(kbuf))
+static ssize_t disc_pwup_write(struct file *file, const char __user *buffer,
+				  size_t count, loff_t *pos)
+{
+	int tap_param = user_on_off(buffer, count);
+	if (tap_param < 0)
 		return -EINVAL;
 
-	if (copy_from_user(&kbuf, buffer, count)) {
-		return -1;
-	}
-
-	kbuf[count] = '\0';
-	length = strlen(kbuf);
-	if (kbuf[length - 1] == '\n')
-		kbuf[--length] = '\0';
-
-	if (strcmp(kbuf, "on") == 0)
-		tap_param = 1;
-	else if (strcmp(kbuf, "off") == 0)
-		tap_param = 0;
-
-	set_disc_pwup_fn(pbp_device_block, tap_param);
-
+	set_disc_pwup_fn(PDE_DATA(file_inode(file)), tap_param);
 	return count;
 }
-
-int
-get_bypass_pwup_pfs(char *page, char **start, off_t off, int count,
-		    int *eof, void *data)
+static int show_disc_pwup(struct seq_file *m, void *v)
 {
-	bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data;
-
-	int len = 0, ret = 0;
-
-	ret = get_bypass_pwup_fn(pbp_device_block);
+	bpctl_dev_t *dev = m->private;
+	int ret = get_disc_pwup_fn(dev);
 	if (ret == BP_NOT_CAP)
-		len = sprintf(page, "fail\n");
+		seq_printf(m, "fail\n");
 	else if (ret == 0)
-		len = sprintf(page, "off\n");
+		seq_printf(m, "off\n");
 	else
-		len = sprintf(page, "on\n");
-
-	*eof = 1;
-	return len;
+		seq_printf(m, "on\n");
+	return 0;
 }
+RW_FOPS(disc_pwup)
 
-int
-get_bypass_pwoff_pfs(char *page, char **start, off_t off, int count,
-		     int *eof, void *data)
+static ssize_t std_nic_write(struct file *file, const char __user *buffer,
+				  size_t count, loff_t *pos)
 {
-	bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data;
-
-	int len = 0, ret = 0;
-
-	ret = get_bypass_pwoff_fn(pbp_device_block);
-	if (ret == BP_NOT_CAP)
-		len = sprintf(page, "fail\n");
-	else if (ret == 0)
-		len = sprintf(page, "off\n");
-	else
-		len = sprintf(page, "on\n");
-
-	*eof = 1;
-	return len;
-}
-
-int
-get_tap_pwup_pfs(char *page, char **start, off_t off, int count,
-		 int *eof, void *data)
-{
-	bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data;
-
-	int len = 0, ret = 0;
-
-	ret = get_tap_pwup_fn(pbp_device_block);
-	if (ret == BP_NOT_CAP)
-		len = sprintf(page, "fail\n");
-	else if (ret == 0)
-		len = sprintf(page, "off\n");
-	else
-		len = sprintf(page, "on\n");
-
-	*eof = 1;
-	return len;
-}
-
-int
-get_disc_pwup_pfs(char *page, char **start, off_t off, int count,
-		  int *eof, void *data)
-{
-	bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data;
-
-	int len = 0, ret = 0;
-
-	ret = get_disc_pwup_fn(pbp_device_block);
-	if (ret == BP_NOT_CAP)
-		len = sprintf(page, "fail\n");
-	else if (ret == 0)
-		len = sprintf(page, "off\n");
-	else
-		len = sprintf(page, "on\n");
-
-	*eof = 1;
-	return len;
-}
-
-int
-set_std_nic_pfs(struct file *file, const char *buffer,
-		unsigned long count, void *data)
-{
-
-	char kbuf[256];
-	bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data;
-
-	int bypass_param = 0, length = 0;
-
-	if (count >= sizeof(kbuf))
+	int bypass_param = user_on_off(buffer, count);
+	if (bypass_param < 0)
 		return -EINVAL;
 
-	if (copy_from_user(&kbuf, buffer, count)) {
-		return -1;
-	}
-
-	kbuf[count] = '\0';
-	length = strlen(kbuf);
-	if (kbuf[length - 1] == '\n')
-		kbuf[--length] = '\0';
-
-	if (strcmp(kbuf, "on") == 0)
-		bypass_param = 1;
-	else if (strcmp(kbuf, "off") == 0)
-		bypass_param = 0;
-
-	set_std_nic_fn(pbp_device_block, bypass_param);
-
+	set_std_nic_fn(PDE_DATA(file_inode(file)), bypass_param);
 	return count;
 }
-
-int
-get_std_nic_pfs(char *page, char **start, off_t off, int count,
-		int *eof, void *data)
+static int show_std_nic(struct seq_file *m, void *v)
 {
-	bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data;
-
-	int len = 0, ret = 0;
-
-	ret = get_std_nic_fn(pbp_device_block);
+	bpctl_dev_t *dev = m->private;
+	int ret = get_std_nic_fn(dev);
 	if (ret == BP_NOT_CAP)
-		len = sprintf(page, "fail\n");
+		seq_printf(m, "fail\n");
 	else if (ret == 0)
-		len = sprintf(page, "off\n");
+		seq_printf(m, "off\n");
 	else
-		len = sprintf(page, "on\n");
-
-	*eof = 1;
-	return len;
+		seq_printf(m, "on\n");
+	return 0;
 }
+RW_FOPS(std_nic)
 
-int
-get_wd_exp_mode_pfs(char *page, char **start, off_t off, int count,
-		    int *eof, void *data)
+static ssize_t wd_exp_mode_write(struct file *file, const char __user *buffer,
+				  size_t count, loff_t *pos)
 {
-	bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data;
-
-	int len = 0, ret = 0;
-
-	ret = get_wd_exp_mode_fn(pbp_device_block);
-	if (ret == 1)
-		len = sprintf(page, "tap\n");
-	else if (ret == 0)
-		len = sprintf(page, "bypass\n");
-	else if (ret == 2)
-		len = sprintf(page, "disc\n");
-
-	else
-		len = sprintf(page, "fail\n");
-
-	*eof = 1;
-	return len;
-}
-
-int
-set_wd_exp_mode_pfs(struct file *file, const char *buffer,
-		    unsigned long count, void *data)
-{
-
 	char kbuf[256];
-	bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data;
-
 	int bypass_param = 0, length = 0;
 
 	if (count > (sizeof(kbuf) - 1))
 		return -1;
 
-	if (copy_from_user(&kbuf, buffer, count)) {
+	if (copy_from_user(&kbuf, buffer, count))
 		return -1;
-	}
 
 	kbuf[count] = '\0';
 	length = strlen(kbuf);
@@ -8375,143 +7786,47 @@
 	else if (strcmp(kbuf, "disc") == 0)
 		bypass_param = 2;
 
-	set_wd_exp_mode_fn(pbp_device_block, bypass_param);
+	set_wd_exp_mode_fn(PDE_DATA(file_inode(file)), bypass_param);
 
 	return count;
 }
-
-int
-get_wd_autoreset_pfs(char *page, char **start, off_t off, int count,
-		     int *eof, void *data)
+static int show_wd_exp_mode(struct seq_file *m, void *v)
 {
-	bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data;
-
-	int len = 0, ret = 0;
-
-	ret = get_wd_autoreset_fn(pbp_device_block);
-	if (ret >= 0)
-		len = sprintf(page, "%d\n", ret);
+	bpctl_dev_t *dev = m->private;
+	int ret = get_wd_exp_mode_fn(dev);
+	if (ret == 1)
+		seq_printf(m, "tap\n");
+	else if (ret == 0)
+		seq_printf(m, "bypass\n");
+	else if (ret == 2)
+		seq_printf(m, "disc\n");
 	else
-		len = sprintf(page, "fail\n");
-
-	*eof = 1;
-	return len;
+		seq_printf(m, "fail\n");
+	return 0;
 }
+RW_FOPS(wd_exp_mode)
 
-int
-set_wd_autoreset_pfs(struct file *file, const char *buffer,
-		     unsigned long count, void *data)
+static ssize_t wd_autoreset_write(struct file *file, const char __user *buffer,
+				  size_t count, loff_t *pos)
 {
-	bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data;
 	int timeout;
-	int ret;
-
-	ret = kstrtoint_from_user(buffer, count, 10, &timeout);
+	int ret = kstrtoint_from_user(buffer, count, 10, &timeout);
 	if (ret)
 		return ret;
-	set_wd_autoreset_fn(pbp_device_block, timeout);
-
+	set_wd_autoreset_fn(PDE_DATA(file_inode(file)), timeout);
 	return count;
 }
-
-int
-set_tpl_pfs(struct file *file, const char *buffer,
-	    unsigned long count, void *data)
+static int show_wd_autoreset(struct seq_file *m, void *v)
 {
-
-	char kbuf[256];
-	bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data;
-
-	int tpl_param = 0, length = 0;
-
-	if (count > (sizeof(kbuf) - 1))
-		return -1;
-
-	if (copy_from_user(&kbuf, buffer, count)) {
-		return -1;
-	}
-
-	kbuf[count] = '\0';
-	length = strlen(kbuf);
-	if (kbuf[length - 1] == '\n')
-		kbuf[--length] = '\0';
-
-	if (strcmp(kbuf, "on") == 0)
-		tpl_param = 1;
-	else if (strcmp(kbuf, "off") == 0)
-		tpl_param = 0;
-
-	set_tpl_fn(pbp_device_block, tpl_param);
-
-	return count;
+	bpctl_dev_t *dev = m->private;
+	int ret = get_wd_autoreset_fn(dev);
+	if (ret >= 0)
+		seq_printf(m, "%d\n", ret);
+	else
+		seq_printf(m, "fail\n");
+	return 0;
 }
-
-#ifdef PMC_FIX_FLAG
-int
-set_wait_at_pwup_pfs(struct file *file, const char *buffer,
-		     unsigned long count, void *data)
-{
-
-	char kbuf[256];
-	bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data;
-
-	int tpl_param = 0, length = 0;
-
-	if (count > (sizeof(kbuf) - 1))
-		return -1;
-
-	if (copy_from_user(&kbuf, buffer, count)) {
-		return -1;
-	}
-
-	kbuf[count] = '\0';
-	length = strlen(kbuf);
-	if (kbuf[length - 1] == '\n')
-		kbuf[--length] = '\0';
-
-	if (strcmp(kbuf, "on") == 0)
-		tpl_param = 1;
-	else if (strcmp(kbuf, "off") == 0)
-		tpl_param = 0;
-
-	set_bp_wait_at_pwup_fn(pbp_device_block, tpl_param);
-
-	return count;
-}
-
-int
-set_hw_reset_pfs(struct file *file, const char *buffer,
-		 unsigned long count, void *data)
-{
-
-	char kbuf[256];
-	bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data;
-
-	int tpl_param = 0, length = 0;
-
-	if (count > (sizeof(kbuf) - 1))
-		return -1;
-
-	if (copy_from_user(&kbuf, buffer, count)) {
-		return -1;
-	}
-
-	kbuf[count] = '\0';
-	length = strlen(kbuf);
-	if (kbuf[length - 1] == '\n')
-		kbuf[--length] = '\0';
-
-	if (strcmp(kbuf, "on") == 0)
-		tpl_param = 1;
-	else if (strcmp(kbuf, "off") == 0)
-		tpl_param = 0;
-
-	set_bp_hw_reset_fn(pbp_device_block, tpl_param);
-
-	return count;
-}
-
-#endif				/*PMC_FIX_FLAG */
+RW_FOPS(wd_autoreset)
 
 int bypass_proc_create_dev_sd(bpctl_dev_t *pbp_device_block)
 {
@@ -8528,168 +7843,54 @@
 		return -1;
 
 	/* create device proc dir */
-	procfs_dir = proc_getdir(current_pfs->dir_name, bp_procfs_dir);
-	if (procfs_dir == 0) {
+	procfs_dir = proc_mkdir(current_pfs->dir_name, bp_procfs_dir);
+	if (!procfs_dir) {
 		printk(KERN_DEBUG "Could not create procfs directory %s\n",
 		       current_pfs->dir_name);
 		return -1;
 	}
 	current_pfs->bypass_entry = procfs_dir;
 
-	if (bypass_proc_create_entry_sd(&(current_pfs->bypass_info), BYPASS_INFO_ENTRY_SD, NULL,	/* write */
-					get_bypass_info_pfs,	/* read  */
-					procfs_dir, pbp_device_block))
-		ret = -1;
-
+#define ENTRY(x) ret |= procfs_add(#x, &x##_ops, pbp_device_block)
+	ENTRY(bypass_info);
 	if (pbp_device_block->bp_caps & SW_CTL_CAP) {
-
 		/* Create set param proc's */
-		if (bypass_proc_create_entry_sd(&(current_pfs->bypass_slave), BYPASS_SLAVE_ENTRY_SD, NULL,	/* write */
-						get_bypass_slave_pfs,	/* read  */
-						procfs_dir, pbp_device_block))
-			ret = -1;
-
-		if (bypass_proc_create_entry_sd(&(current_pfs->bypass_caps), BYPASS_CAPS_ENTRY_SD, NULL,	/* write */
-						get_bypass_caps_pfs,	/* read  */
-						procfs_dir, pbp_device_block))
-			ret = -1;
-
-		if (bypass_proc_create_entry_sd(&(current_pfs->wd_set_caps), WD_SET_CAPS_ENTRY_SD, NULL,	/* write */
-						get_wd_set_caps_pfs,	/* read  */
-						procfs_dir, pbp_device_block))
-			ret = -1;
-		if (bypass_proc_create_entry_sd(&(current_pfs->bypass_wd), BYPASS_WD_ENTRY_SD, set_bypass_wd_pfs,	/* write */
-						get_bypass_wd_pfs,	/* read  */
-						procfs_dir, pbp_device_block))
-			ret = -1;
-
-		if (bypass_proc_create_entry_sd(&(current_pfs->wd_expire_time), WD_EXPIRE_TIME_ENTRY_SD, NULL,	/* write */
-						get_wd_expire_time_pfs,	/* read  */
-						procfs_dir, pbp_device_block))
-			ret = -1;
-
-		if (bypass_proc_create_entry_sd(&(current_pfs->reset_bypass_wd), RESET_BYPASS_WD_ENTRY_SD, NULL,	/* write */
-						reset_bypass_wd_pfs,	/* read  */
-						procfs_dir, pbp_device_block))
-			ret = -1;
-
-		if (bypass_proc_create_entry_sd(&(current_pfs->std_nic), STD_NIC_ENTRY_SD, set_std_nic_pfs,	/* write */
-						get_std_nic_pfs,	/* read  */
-						procfs_dir, pbp_device_block))
-			ret = -1;
-
+		ENTRY(bypass_slave);
+		ENTRY(bypass_caps);
+		ENTRY(wd_set_caps);
+		ENTRY(bypass_wd);
+		ENTRY(wd_expire_time);
+		ENTRY(reset_bypass_wd);
+		ENTRY(std_nic);
 		if (pbp_device_block->bp_caps & BP_CAP) {
-			if (bypass_proc_create_entry_sd(&(current_pfs->bypass), BYPASS_ENTRY_SD, set_bypass_pfs,	/* write */
-							get_bypass_pfs,	/* read  */
-							procfs_dir,
-							pbp_device_block))
-				ret = -1;
-
-			if (bypass_proc_create_entry_sd(&(current_pfs->dis_bypass), DIS_BYPASS_ENTRY_SD, set_dis_bypass_pfs,	/* write */
-							get_dis_bypass_pfs,	/* read  */
-							procfs_dir,
-							pbp_device_block))
-				ret = -1;
-
-			if (bypass_proc_create_entry_sd(&(current_pfs->bypass_pwup), BYPASS_PWUP_ENTRY_SD, set_bypass_pwup_pfs,	/* write */
-							get_bypass_pwup_pfs,	/* read  */
-							procfs_dir,
-							pbp_device_block))
-				ret = -1;
-			if (bypass_proc_create_entry_sd(&(current_pfs->bypass_pwoff), BYPASS_PWOFF_ENTRY_SD, set_bypass_pwoff_pfs,	/* write */
-							get_bypass_pwoff_pfs,	/* read  */
-							procfs_dir,
-							pbp_device_block))
-				ret = -1;
-
-			if (bypass_proc_create_entry_sd(&(current_pfs->bypass_change), BYPASS_CHANGE_ENTRY_SD, NULL,	/* write */
-							get_bypass_change_pfs,	/* read  */
-							procfs_dir,
-							pbp_device_block))
-				ret = -1;
+			ENTRY(bypass);
+			ENTRY(dis_bypass);
+			ENTRY(bypass_pwup);
+			ENTRY(bypass_pwoff);
+			ENTRY(bypass_change);
 		}
-
 		if (pbp_device_block->bp_caps & TAP_CAP) {
-
-			if (bypass_proc_create_entry_sd(&(current_pfs->tap), TAP_ENTRY_SD, set_tap_pfs,	/* write */
-							get_tap_pfs,	/* read  */
-							procfs_dir,
-							pbp_device_block))
-				ret = -1;
-
-			if (bypass_proc_create_entry_sd(&(current_pfs->dis_tap), DIS_TAP_ENTRY_SD, set_dis_tap_pfs,	/* write */
-							get_dis_tap_pfs,	/* read  */
-							procfs_dir,
-							pbp_device_block))
-				ret = -1;
-
-			if (bypass_proc_create_entry_sd(&(current_pfs->tap_pwup), TAP_PWUP_ENTRY_SD, set_tap_pwup_pfs,	/* write */
-							get_tap_pwup_pfs,	/* read  */
-							procfs_dir,
-							pbp_device_block))
-				ret = -1;
-
-			if (bypass_proc_create_entry_sd(&(current_pfs->tap_change), TAP_CHANGE_ENTRY_SD, NULL,	/* write */
-							get_tap_change_pfs,	/* read  */
-							procfs_dir,
-							pbp_device_block))
-				ret = -1;
+			ENTRY(tap);
+			ENTRY(dis_tap);
+			ENTRY(tap_pwup);
+			ENTRY(tap_change);
 		}
 		if (pbp_device_block->bp_caps & DISC_CAP) {
-
-			if (bypass_proc_create_entry_sd(&(current_pfs->tap), DISC_ENTRY_SD, set_disc_pfs,	/* write */
-							get_disc_pfs,	/* read  */
-							procfs_dir,
-							pbp_device_block))
-				ret = -1;
-#if 1
-
-			if (bypass_proc_create_entry_sd(&(current_pfs->dis_tap), DIS_DISC_ENTRY_SD, set_dis_disc_pfs,	/* write */
-							get_dis_disc_pfs,	/* read  */
-							procfs_dir,
-							pbp_device_block))
-				ret = -1;
-#endif
-
-			if (bypass_proc_create_entry_sd(&(current_pfs->tap_pwup), DISC_PWUP_ENTRY_SD, set_disc_pwup_pfs,	/* write */
-							get_disc_pwup_pfs,	/* read  */
-							procfs_dir,
-							pbp_device_block))
-				ret = -1;
-
-			if (bypass_proc_create_entry_sd(&(current_pfs->tap_change), DISC_CHANGE_ENTRY_SD, NULL,	/* write */
-							get_disc_change_pfs,	/* read  */
-							procfs_dir,
-							pbp_device_block))
-				ret = -1;
+			ENTRY(disc);
+			ENTRY(dis_disc);
+			ENTRY(disc_pwup);
+			ENTRY(disc_change);
 		}
 
-		if (bypass_proc_create_entry_sd(&(current_pfs->wd_exp_mode), WD_EXP_MODE_ENTRY_SD, set_wd_exp_mode_pfs,	/* write */
-						get_wd_exp_mode_pfs,	/* read  */
-						procfs_dir, pbp_device_block))
-			ret = -1;
-
-		if (bypass_proc_create_entry_sd(&(current_pfs->wd_autoreset), WD_AUTORESET_ENTRY_SD, set_wd_autoreset_pfs,	/* write */
-						get_wd_autoreset_pfs,	/* read  */
-						procfs_dir, pbp_device_block))
-			ret = -1;
-		if (bypass_proc_create_entry_sd(&(current_pfs->tpl), TPL_ENTRY_SD, set_tpl_pfs,	/* write */
-						get_tpl_pfs,	/* read  */
-						procfs_dir, pbp_device_block))
-			ret = -1;
+		ENTRY(wd_exp_mode);
+		ENTRY(wd_autoreset);
+		ENTRY(tpl);
 #ifdef PMC_FIX_FLAG
-		if (bypass_proc_create_entry_sd(&(current_pfs->tpl), WAIT_AT_PWUP_ENTRY_SD, set_wait_at_pwup_pfs,	/* write */
-						get_wait_at_pwup_pfs,	/* read  */
-						procfs_dir, pbp_device_block))
-			ret = -1;
-		if (bypass_proc_create_entry_sd(&(current_pfs->tpl), HW_RESET_ENTRY_SD, set_hw_reset_pfs,	/* write */
-						get_hw_reset_pfs,	/* read  */
-						procfs_dir, pbp_device_block))
-			ret = -1;
-
+		ENTRY(wait_at_pwup);
+		ENTRY(hw_reset);
 #endif
-
 	}
+#undef ENTRY
 	if (ret < 0)
 		printk(KERN_DEBUG "Create proc entry failed\n");
 
@@ -8700,21 +7901,7 @@
 {
 
 	struct bypass_pfs_sd *current_pfs = &pbp_device_block->bypass_pfs_set;
-	struct proc_dir_entry *pde = current_pfs->bypass_entry, *pde_curr =
-	    NULL;
-	char name[256];
-
-	if (!pde)
-		return 0;
-	for (pde = pde->subdir; pde;) {
-		strcpy(name, pde->name);
-		pde_curr = pde;
-		pde = pde->next;
-		remove_proc_entry(name, current_pfs->bypass_entry);
-	}
-	if (!pde)
-		remove_proc_entry(current_pfs->dir_name, bp_procfs_dir);
+	remove_proc_subtree(current_pfs->dir_name, bp_procfs_dir);
 	current_pfs->bypass_entry = NULL;
-
 	return 0;
 }
diff --git a/drivers/staging/vt6655/device_main.c b/drivers/staging/vt6655/device_main.c
index be4f6c2..08b250f 100644
--- a/drivers/staging/vt6655/device_main.c
+++ b/drivers/staging/vt6655/device_main.c
@@ -60,6 +60,7 @@
  */
 #undef __NO_VERSION__
 
+#include <linux/file.h>
 #include "device.h"
 #include "card.h"
 #include "channel.h"
@@ -2737,83 +2738,50 @@
 	return true;
 }
 
-int Config_FileOperation(PSDevice pDevice, bool fwrite, unsigned char *Parameter) {
-	unsigned char *config_path = CONFIG_PATH;
-	unsigned char *buffer = NULL;
+int Config_FileOperation(PSDevice pDevice,bool fwrite,unsigned char *Parameter)
+{
+	unsigned char *buffer = kmalloc(1024, GFP_KERNEL);
 	unsigned char tmpbuffer[20];
-	struct file   *filp = NULL;
-	mm_segment_t old_fs = get_fs();
-	//int oldfsuid=0,oldfsgid=0;
-	int result = 0;
+	struct file *file;
+	int result=0;
 
-	set_fs(KERNEL_DS);
-
-	/* Can't do this anymore, so we rely on correct filesystem permissions:
-	//Make sure a caller can read or write power as root
-	oldfsuid=current->cred->fsuid;
-	oldfsgid=current->cred->fsgid;
-	current->cred->fsuid = 0;
-	current->cred->fsgid = 0;
-	*/
-
-	//open file
-	filp = filp_open(config_path, O_RDWR, 0);
-	if (IS_ERR(filp)) {
-		printk("Config_FileOperation:open file fail?\n");
-		result = -1;
-		goto error2;
-	}
-
-	if (!(filp->f_op) || !(filp->f_op->read) || !(filp->f_op->write)) {
-		printk("file %s cann't readable or writable?\n", config_path);
-		result = -1;
-		goto error1;
-	}
-
-	buffer = kmalloc(1024, GFP_KERNEL);
-	if (buffer == NULL) {
+	if (!buffer) {
 		printk("allocate mem for file fail?\n");
-		result = -1;
-		goto error1;
+		return -1;
+	}
+	file = filp_open(CONFIG_PATH, O_RDONLY, 0);
+	if (IS_ERR(file)) {
+		kfree(buffer);
+		printk("Config_FileOperation:open file fail?\n");
+		return -1;
 	}
 
-	if (filp->f_op->read(filp, buffer, 1024, &filp->f_pos) < 0) {
+	if (kernel_read(file, 0, buffer, 1024) < 0) {
 		printk("read file error?\n");
 		result = -1;
 		goto error1;
 	}
 
-	if (Config_FileGetParameter("ZONETYPE", tmpbuffer, buffer) != true) {
+	if (Config_FileGetParameter("ZONETYPE",tmpbuffer,buffer)!=true) {
 		printk("get parameter error?\n");
 		result = -1;
 		goto error1;
 	}
 
-	if (memcmp(tmpbuffer, "USA", 3) == 0) {
+	if (memcmp(tmpbuffer,"USA",3)==0) {
 		result = ZoneType_USA;
-	} else if (memcmp(tmpbuffer, "JAPAN", 5) == 0) {
+	} else if(memcmp(tmpbuffer,"JAPAN",5)==0) {
 		result = ZoneType_Japan;
-	} else if (memcmp(tmpbuffer, "EUROPE", 5) == 0) {
+	} else if(memcmp(tmpbuffer,"EUROPE",5)==0) {
 		result = ZoneType_Europe;
 	} else {
 		result = -1;
-		printk("Unknown Zonetype[%s]?\n", tmpbuffer);
+		printk("Unknown Zonetype[%s]?\n",tmpbuffer);
 	}
 
 error1:
 	kfree(buffer);
-
-	if (filp_close(filp, NULL))
-		printk("Config_FileOperation:close file fail\n");
-
-error2:
-	set_fs(old_fs);
-
-	/*
-	  current->cred->fsuid=oldfsuid;
-	  current->cred->fsgid=oldfsgid;
-	*/
-
+	fput(file);
 	return result;
 }
 
diff --git a/drivers/staging/vt6656/main_usb.c b/drivers/staging/vt6656/main_usb.c
index 2161af8..3a3fdc5 100644
--- a/drivers/staging/vt6656/main_usb.c
+++ b/drivers/staging/vt6656/main_usb.c
@@ -46,6 +46,7 @@
  */
 #undef __NO_VERSION__
 
+#include <linux/file.h>
 #include "device.h"
 #include "card.h"
 #include "baseband.h"
@@ -1273,53 +1274,29 @@
 /* if read fails, return NULL, or return data pointer */
 static unsigned char *Config_FileOperation(struct vnt_private *pDevice)
 {
-    unsigned char *config_path = CONFIG_PATH;
-    unsigned char *buffer = NULL;
-    struct file   *filp=NULL;
-    mm_segment_t old_fs = get_fs();
+	unsigned char *buffer = kmalloc(1024, GFP_KERNEL);
+	struct file   *file;
 
-    int result = 0;
+	if (!buffer) {
+		printk("allocate mem for file fail?\n");
+		return NULL;
+	}
 
-    set_fs (KERNEL_DS);
+	file = filp_open(CONFIG_PATH, O_RDONLY, 0);
+	if (IS_ERR(file)) {
+		kfree(buffer);
+		printk("Config_FileOperation file Not exist\n");
+		return NULL;
+	}
 
-    /* open file */
-      filp = filp_open(config_path, O_RDWR, 0);
-        if (IS_ERR(filp)) {
-	     printk("Config_FileOperation file Not exist\n");
-	     result=-1;
-             goto error2;
-	  }
+	if (kernel_read(file, 0, buffer, 1024) < 0) {
+		printk("read file error?\n");
+		kfree(buffer);
+		buffer = NULL;
+	}
 
-     if(!(filp->f_op) || !(filp->f_op->read) ||!(filp->f_op->write)) {
-           printk("file %s is not read or writeable?\n",config_path);
-	  result = -1;
-	  goto error1;
-     	}
-
-    buffer = kmalloc(1024, GFP_KERNEL);
-    if(buffer==NULL) {
-      printk("allocate mem for file fail?\n");
-      result = -1;
-      goto error1;
-    }
-
-    if(filp->f_op->read(filp, buffer, 1024, &filp->f_pos)<0) {
-     printk("read file error?\n");
-     result = -1;
-    }
-
-error1:
-  if(filp_close(filp,NULL))
-       printk("Config_FileOperation:close file fail\n");
-
-error2:
-  set_fs (old_fs);
-
-if(result!=0) {
-    kfree(buffer);
-    buffer=NULL;
-}
-  return buffer;
+	fput(file);
+	return buffer;
 }
 
 /* return --->-1:fail; >=0:successful */
diff --git a/drivers/staging/wlags49_h2/wl_main.c b/drivers/staging/wlags49_h2/wl_main.c
index f5f120a..c4264e8 100644
--- a/drivers/staging/wlags49_h2/wl_main.c
+++ b/drivers/staging/wlags49_h2/wl_main.c
@@ -73,6 +73,7 @@
 
 #include <linux/module.h>
 #include <linux/proc_fs.h>
+#include <linux/seq_file.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
 // #include <linux/sched.h>
@@ -144,10 +145,23 @@
 void wl_isr_handler( unsigned long p );
 
 #if 0 //SCULL_USE_PROC /* don't waste space if unused */
-//int scull_read_procmem(char *buf, char **start, off_t offset, int len, int unused);
-int scull_read_procmem(char *buf, char **start, off_t offset, int len, int *eof, void *data );
+static int scull_read_procmem(struct seq_file *m, void *v);
 static int write_int(struct file *file, const char *buffer, unsigned long count, void *data);
-static void proc_write(const char *name, write_proc_t *w, void *data);
+
+/*
+ * seq_file wrappers for procfile show routines.
+ */
+static int scull_read_procmem_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, scull_read_procmem, PDE_DATA(inode));
+}
+
+static const struct file_operations scull_read_procmem_fops = {
+	.open		= scull_read_procmem_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= seq_release,
+};
 
 #endif /* SCULL_USE_PROC */
 
@@ -908,9 +922,8 @@
 	}
 
 #if 0 //SCULL_USE_PROC /* don't waste space if unused */
-	create_proc_read_entry( "wlags", 0, NULL, scull_read_procmem, dev );
+	proc_create_data( "wlags", 0, NULL, &scull_read_procmem_fops, dev );
 	proc_mkdir("driver/wlags49", 0);
-	proc_write("driver/wlags49/wlags49_type", write_int, &lp->wlags49_type);
 #endif /* SCULL_USE_PROC */
 
 	DBG_LEAVE( DbgInfo );
@@ -2097,7 +2110,7 @@
 
 	wl_adapter_cleanup_module( );
 #if 0 //SCULL_USE_PROC /* don't waste space if unused */
-	remove_proc_entry( "wlags", NULL );		//;?why so a-symmetric compared to location of create_proc_read_entry
+	remove_proc_entry( "wlags", NULL );		//;?why so a-symmetric compared to location of proc_create_data
 #endif
 
 	DBG_LEAVE( DbgInfo );
@@ -3531,229 +3544,215 @@
 /*
  * The proc filesystem: function to read and entry
  */
-int printf_hcf_16( char *s, char *buf, hcf_16* p, int n );
-int printf_hcf_16( char *s, char *buf, hcf_16* p, int n ) {
-
-int i, len;
-
-	len = sprintf(buf, "%s", s );
-	while ( len < 20 ) len += sprintf(buf+len, " " );
-	len += sprintf(buf+len,": " );
-	for ( i = 0; i < n; i++ ) {
-		if ( len % 80 > 75 ) {
-			len += sprintf(buf+len,"\n" );
-		}
-		len += sprintf(buf+len,"%04X ", p[i] );
-	}
-	len += sprintf(buf+len,"\n" );
-	return len;
-} // printf_hcf_16
-
-int printf_hcf_8( char *s, char *buf, hcf_8* p, int n );
-int printf_hcf_8( char *s, char *buf, hcf_8* p, int n ) {
-
-int i, len;
-
-	len = sprintf(buf, "%s", s );
-	while ( len < 20 ) len += sprintf(buf+len, " " );
-	len += sprintf(buf+len,": " );
-	for ( i = 0; i <= n; i++ ) {
-		if ( len % 80 > 77 ) {
-			len += sprintf(buf+len,"\n" );
-		}
-		len += sprintf(buf+len,"%02X ", p[i] );
-	}
-	len += sprintf(buf+len,"\n" );
-	return len;
-} // printf_hcf8
-
-int printf_strct( char *s, char *buf, hcf_16* p );
-int printf_strct( char *s, char *buf, hcf_16* p ) {
-
-int i, len;
-
-	len = sprintf(buf, "%s", s );
-	while ( len < 20 ) len += sprintf(buf+len, " " );
-	len += sprintf(buf+len,": " );
-	for ( i = 0; i <= *p; i++ ) {
-		if ( len % 80 > 75 ) {
-			len += sprintf(buf+len,"\n" );
-		}
-		len += sprintf(buf+len,"%04X ", p[i] );
-	}
-	len += sprintf(buf+len,"\n" );
-	return len;
-} // printf_strct
-
-int scull_read_procmem(char *buf, char **start, off_t offset, int len, int *eof, void *data )
+static void printf_hcf_16(struct seq_file *m, const char *s, hcf_16 *p, int n)
 {
-	struct wl_private	*lp = NULL;
+	int i, len;
+
+	seq_printf(m, "%-20.20s: ", s);
+	len = 22;
+
+	for (i = 0; i < n; i++) {
+		if (len % 80 > 75)
+			seq_putc(m, '\n');
+		seq_printf(m, "%04X ", p[i]);
+	}
+	seq_putc(m, '\n');
+}
+
+static void printf_hcf_8(struct seq_file *m, const char *s, hcf_8 *p, int n)
+{
+	int i, len;
+
+	seq_printf(m, "%-20.20s: ", s);
+	len = 22;
+
+	for (i = 0; i <= n; i++) {
+		if (len % 80 > 77)
+			seq_putc(m, '\n');
+		seq_printf(m, "%02X ", p[i]);
+	}
+	seq_putc(m, '\n');
+}
+
+static void printf_strct(struct seq_file *m, const char *s, hcf_16 *p)
+{
+	int i, len;
+
+	seq_printf(m, "%-20.20s: ", s);
+	len = 22;
+
+	for ( i = 0; i <= *p; i++ ) {
+		if (len % 80 > 75)
+			seq_putc(m, '\n');
+		seq_printf(m,"%04X ", p[i]);
+	}
+	seq_putc(m, '\n');
+}
+
+int scull_read_procmem(struct seq_file *m, void *v)
+{
+	struct wl_private	*lp = m->private;
 	IFBP				ifbp;
    	CFG_HERMES_TALLIES_STRCT *p;
 
-    #define LIMIT (PAGE_SIZE-80) /* don't print any more after this size */
-
-    len=0;
-
-	lp = ((struct net_device *)data)->priv;
 	if (lp == NULL) {
-        len += sprintf(buf+len,"No wl_private in scull_read_procmem\n" );
+		seq_puts(m, "No wl_private in scull_read_procmem\n" );
 	} else if ( lp->wlags49_type == 0 ){
-   	    ifbp = &lp->hcfCtx;
-   	    len += sprintf(buf+len,"Magic:               0x%04X\n", ifbp->IFB_Magic );
-   	    len += sprintf(buf+len,"IOBase:              0x%04X\n", ifbp->IFB_IOBase );
-   	    len += sprintf(buf+len,"LinkStat:            0x%04X\n", ifbp->IFB_LinkStat );
-   	    len += sprintf(buf+len,"DSLinkStat:          0x%04X\n", ifbp->IFB_DSLinkStat );
-   	    len += sprintf(buf+len,"TickIni:         0x%08lX\n", ifbp->IFB_TickIni );
-   	    len += sprintf(buf+len,"TickCnt:             0x%04X\n", ifbp->IFB_TickCnt );
-   	    len += sprintf(buf+len,"IntOffCnt:           0x%04X\n", ifbp->IFB_IntOffCnt );
-		len += printf_hcf_16( "IFB_FWIdentity", &buf[len],
-							  &ifbp->IFB_FWIdentity.len, ifbp->IFB_FWIdentity.len + 1 );
+		ifbp = &lp->hcfCtx;
+		seq_printf(m, "Magic:               0x%04X\n", ifbp->IFB_Magic );
+		seq_printf(m, "IOBase:              0x%04X\n", ifbp->IFB_IOBase );
+		seq_printf(m, "LinkStat:            0x%04X\n", ifbp->IFB_LinkStat );
+		seq_printf(m, "DSLinkStat:          0x%04X\n", ifbp->IFB_DSLinkStat );
+		seq_printf(m, "TickIni:         0x%08lX\n", ifbp->IFB_TickIni );
+		seq_printf(m, "TickCnt:             0x%04X\n", ifbp->IFB_TickCnt );
+		seq_printf(m, "IntOffCnt:           0x%04X\n", ifbp->IFB_IntOffCnt );
+		printf_hcf_16(m, "IFB_FWIdentity",
+			      &ifbp->IFB_FWIdentity.len, ifbp->IFB_FWIdentity.len + 1 );
 	} else if ( lp->wlags49_type == 1 ) {
-   	    len += sprintf(buf+len,"Channel:              0x%04X\n", lp->Channel );
-/****** len += sprintf(buf+len,"slock:                  %d\n", lp->slock );		*/
+		seq_printf(m, "Channel:              0x%04X\n", lp->Channel );
+/****** seq_printf(m, "slock:                  %d\n", lp->slock );		*/
 //x		struct tq_struct            "task:               0x%04X\n", lp->task );
 //x		struct net_device_stats     "stats:              0x%04X\n", lp->stats );
 #ifdef WIRELESS_EXT
 //x		struct iw_statistics        "wstats:             0x%04X\n", lp->wstats );
-//x   	    len += sprintf(buf+len,"spy_number:           0x%04X\n", lp->spy_number );
+//x   	    seq_printf(m, "spy_number:           0x%04X\n", lp->spy_number );
 //x		u_char                      spy_address[IW_MAX_SPY][ETH_ALEN];
 //x		struct iw_quality           spy_stat[IW_MAX_SPY];
 #endif // WIRELESS_EXT
-   	    len += sprintf(buf+len,"IFB:                  0x%p\n", &lp->hcfCtx );
-   	    len += sprintf(buf+len,"flags:                %#.8lX\n", lp->flags );  //;?use this format from now on
-   	    len += sprintf(buf+len,"DebugFlag(wl_private) 0x%04X\n", lp->DebugFlag );
+		seq_printf(m, "IFB:                  0x%p\n", &lp->hcfCtx );
+		seq_printf(m, "flags:                %#.8lX\n", lp->flags );  //;?use this format from now on
+		seq_printf(m, "DebugFlag(wl_private) 0x%04X\n", lp->DebugFlag );
 #if DBG
-   	    len += sprintf(buf+len,"DebugFlag (DbgInfo):   0x%08lX\n", DbgInfo->DebugFlag );
+		seq_printf(m, "DebugFlag (DbgInfo):   0x%08lX\n", DbgInfo->DebugFlag );
 #endif // DBG
-   	    len += sprintf(buf+len,"is_registered:        0x%04X\n", lp->is_registered );
+		seq_printf(m, "is_registered:        0x%04X\n", lp->is_registered );
 //x		CFG_DRV_INFO_STRCT          "driverInfo:         0x%04X\n", lp->driverInfo );
-		len += printf_strct( "driverInfo", &buf[len], (hcf_16*)&lp->driverInfo );
+		printf_strct( m, "driverInfo", (hcf_16*)&lp->driverInfo );
 //x		CFG_IDENTITY_STRCT          "driverIdentity:     0x%04X\n", lp->driverIdentity );
-		len += printf_strct( "driverIdentity", &buf[len], (hcf_16*)&lp->driverIdentity );
+		printf_strct( m, "driverIdentity", (hcf_16*)&lp->driverIdentity );
 //x		CFG_FW_IDENTITY_STRCT       "StationIdentity:    0x%04X\n", lp->StationIdentity );
-		len += printf_strct( "StationIdentity", &buf[len], (hcf_16*)&lp->StationIdentity );
+		printf_strct( m, "StationIdentity", (hcf_16*)&lp->StationIdentity );
 //x		CFG_PRI_IDENTITY_STRCT      "PrimaryIdentity:    0x%04X\n", lp->PrimaryIdentity );
-		len += printf_strct( "PrimaryIdentity", &buf[len], (hcf_16*)&lp->hcfCtx.IFB_PRIIdentity );
-		len += printf_strct( "PrimarySupplier", &buf[len], (hcf_16*)&lp->hcfCtx.IFB_PRISup );
+		printf_strct( m, "PrimaryIdentity", (hcf_16*)&lp->hcfCtx.IFB_PRIIdentity );
+		printf_strct( m, "PrimarySupplier", (hcf_16*)&lp->hcfCtx.IFB_PRISup );
 //x		CFG_PRI_IDENTITY_STRCT      "NICIdentity:        0x%04X\n", lp->NICIdentity );
-		len += printf_strct( "NICIdentity", &buf[len], (hcf_16*)&lp->NICIdentity );
+		printf_strct( m, "NICIdentity", (hcf_16*)&lp->NICIdentity );
 //x		ltv_t                       "ltvRecord:          0x%04X\n", lp->ltvRecord );
-   	    len += sprintf(buf+len,"txBytes:              0x%08lX\n", lp->txBytes );
-   	    len += sprintf(buf+len,"maxPort:              0x%04X\n", lp->maxPort );        /* 0 for STA, 6 for AP */
-	/* Elements used for async notification from hardware */
+		seq_printf(m, "txBytes:              0x%08lX\n", lp->txBytes );
+		seq_printf(m, "maxPort:              0x%04X\n", lp->maxPort );        /* 0 for STA, 6 for AP */
+		/* Elements used for async notification from hardware */
 //x		RID_LOG_STRCT				RidList[10];
 //x		ltv_t                       "updatedRecord:      0x%04X\n", lp->updatedRecord );
 //x		PROBE_RESP				    "ProbeResp:                    0x%04X\n", lp->ProbeResp );
 //x		ASSOC_STATUS_STRCT          "assoc_stat:         0x%04X\n", lp->assoc_stat );
 //x		SECURITY_STATUS_STRCT       "sec_stat:           0x%04X\n", lp->sec_stat );
 //x		u_char                      lookAheadBuf[WVLAN_MAX_LOOKAHEAD];
-   	    len += sprintf(buf+len,"PortType:             0x%04X\n", lp->PortType );           // 1 - 3 (1 [Normal] | 3 [AdHoc])
-   	    len += sprintf(buf+len,"Channel:              0x%04X\n", lp->Channel );            // 0 - 14 (0)
+		seq_printf(m, "PortType:             0x%04X\n", lp->PortType );           // 1 - 3 (1 [Normal] | 3 [AdHoc])
+		seq_printf(m, "Channel:              0x%04X\n", lp->Channel );            // 0 - 14 (0)
 //x		hcf_16                      TxRateControl[2];
-   	    len += sprintf(buf+len,"TxRateControl[2]:     0x%04X 0x%04X\n",
-						lp->TxRateControl[0], lp->TxRateControl[1] );
-   	    len += sprintf(buf+len,"DistanceBetweenAPs:   0x%04X\n", lp->DistanceBetweenAPs ); // 1 - 3 (1)
-   	    len += sprintf(buf+len,"RTSThreshold:         0x%04X\n", lp->RTSThreshold );       // 0 - 2347 (2347)
-   	    len += sprintf(buf+len,"PMEnabled:            0x%04X\n", lp->PMEnabled );          // 0 - 2, 8001 - 8002 (0)
-   	    len += sprintf(buf+len,"MicrowaveRobustness:  0x%04X\n", lp->MicrowaveRobustness );// 0 - 1 (0)
-   	    len += sprintf(buf+len,"CreateIBSS:           0x%04X\n", lp->CreateIBSS );         // 0 - 1 (0)
-   	    len += sprintf(buf+len,"MulticastReceive:     0x%04X\n", lp->MulticastReceive );   // 0 - 1 (1)
-   	    len += sprintf(buf+len,"MaxSleepDuration:     0x%04X\n", lp->MaxSleepDuration );   // 0 - 65535 (100)
+		seq_printf(m, "TxRateControl[2]:     0x%04X 0x%04X\n",
+			       lp->TxRateControl[0], lp->TxRateControl[1] );
+		seq_printf(m, "DistanceBetweenAPs:   0x%04X\n", lp->DistanceBetweenAPs ); // 1 - 3 (1)
+		seq_printf(m, "RTSThreshold:         0x%04X\n", lp->RTSThreshold );       // 0 - 2347 (2347)
+		seq_printf(m, "PMEnabled:            0x%04X\n", lp->PMEnabled );          // 0 - 2, 8001 - 8002 (0)
+		seq_printf(m, "MicrowaveRobustness:  0x%04X\n", lp->MicrowaveRobustness );// 0 - 1 (0)
+		seq_printf(m, "CreateIBSS:           0x%04X\n", lp->CreateIBSS );         // 0 - 1 (0)
+		seq_printf(m, "MulticastReceive:     0x%04X\n", lp->MulticastReceive );   // 0 - 1 (1)
+		seq_printf(m, "MaxSleepDuration:     0x%04X\n", lp->MaxSleepDuration );   // 0 - 65535 (100)
 //x		hcf_8                       MACAddress[ETH_ALEN];
-		len += printf_hcf_8( "MACAddress", &buf[len], lp->MACAddress, ETH_ALEN );
+		printf_hcf_8(m, "MACAddress", lp->MACAddress, ETH_ALEN );
 //x		char                        NetworkName[HCF_MAX_NAME_LEN+1];
-   	    len += sprintf(buf+len,"NetworkName:          %.32s\n", lp->NetworkName );
+		seq_printf(m, "NetworkName:          %.32s\n", lp->NetworkName );
 //x		char                        StationName[HCF_MAX_NAME_LEN+1];
-   	    len += sprintf(buf+len,"EnableEncryption:     0x%04X\n", lp->EnableEncryption );   // 0 - 1 (0)
+		seq_printf(m, "EnableEncryption:     0x%04X\n", lp->EnableEncryption );   // 0 - 1 (0)
 //x		char                        Key1[MAX_KEY_LEN+1];
-		len += printf_hcf_8( "Key1", &buf[len], lp->Key1, MAX_KEY_LEN );
+		printf_hcf_8( m, "Key1", lp->Key1, MAX_KEY_LEN );
 //x		char                        Key2[MAX_KEY_LEN+1];
 //x		char                        Key3[MAX_KEY_LEN+1];
 //x		char                        Key4[MAX_KEY_LEN+1];
-   	    len += sprintf(buf+len,"TransmitKeyID:        0x%04X\n", lp->TransmitKeyID );      // 1 - 4 (1)
+		seq_printf(m, "TransmitKeyID:        0x%04X\n", lp->TransmitKeyID );      // 1 - 4 (1)
 //x		CFG_DEFAULT_KEYS_STRCT	    "DefaultKeys:         0x%04X\n", lp->DefaultKeys );
 //x		u_char                      mailbox[MB_SIZE];
 //x		char                        szEncryption[MAX_ENC_LEN];
-   	    len += sprintf(buf+len,"driverEnable:         0x%04X\n", lp->driverEnable );
-   	    len += sprintf(buf+len,"wolasEnable:          0x%04X\n", lp->wolasEnable );
-   	    len += sprintf(buf+len,"atimWindow:           0x%04X\n", lp->atimWindow );
-   	    len += sprintf(buf+len,"holdoverDuration:     0x%04X\n", lp->holdoverDuration );
+		seq_printf(m, "driverEnable:         0x%04X\n", lp->driverEnable );
+		seq_printf(m, "wolasEnable:          0x%04X\n", lp->wolasEnable );
+		seq_printf(m, "atimWindow:           0x%04X\n", lp->atimWindow );
+		seq_printf(m, "holdoverDuration:     0x%04X\n", lp->holdoverDuration );
 //x		hcf_16                      MulticastRate[2];
-   	    len += sprintf(buf+len,"authentication:       0x%04X\n", lp->authentication ); // is this AP specific?
-   	    len += sprintf(buf+len,"promiscuousMode:      0x%04X\n", lp->promiscuousMode );
-   	    len += sprintf(buf+len,"DownloadFirmware:     0x%04X\n", lp->DownloadFirmware );   // 0 - 2 (0 [None] | 1 [STA] | 2 [AP])
-   	    len += sprintf(buf+len,"AuthKeyMgmtSuite:     0x%04X\n", lp->AuthKeyMgmtSuite );
-   	    len += sprintf(buf+len,"loadBalancing:        0x%04X\n", lp->loadBalancing );
-   	    len += sprintf(buf+len,"mediumDistribution:   0x%04X\n", lp->mediumDistribution );
-   	    len += sprintf(buf+len,"txPowLevel:           0x%04X\n", lp->txPowLevel );
-//   	    len += sprintf(buf+len,"shortRetryLimit:    0x%04X\n", lp->shortRetryLimit );
-//   	    len += sprintf(buf+len,"longRetryLimit:     0x%04X\n", lp->longRetryLimit );
+		seq_printf(m, "authentication:       0x%04X\n", lp->authentication ); // is this AP specific?
+		seq_printf(m, "promiscuousMode:      0x%04X\n", lp->promiscuousMode );
+		seq_printf(m, "DownloadFirmware:     0x%04X\n", lp->DownloadFirmware );   // 0 - 2 (0 [None] | 1 [STA] | 2 [AP])
+		seq_printf(m, "AuthKeyMgmtSuite:     0x%04X\n", lp->AuthKeyMgmtSuite );
+		seq_printf(m, "loadBalancing:        0x%04X\n", lp->loadBalancing );
+		seq_printf(m, "mediumDistribution:   0x%04X\n", lp->mediumDistribution );
+		seq_printf(m, "txPowLevel:           0x%04X\n", lp->txPowLevel );
+//   	    seq_printf(m, "shortRetryLimit:    0x%04X\n", lp->shortRetryLimit );
+//   	    seq_printf(m, "longRetryLimit:     0x%04X\n", lp->longRetryLimit );
 //x		hcf_16                      srsc[2];
 //x		hcf_16                      brsc[2];
-   	    len += sprintf(buf+len,"connectionControl:    0x%04X\n", lp->connectionControl );
+		seq_printf(m, "connectionControl:    0x%04X\n", lp->connectionControl );
 //x		//hcf_16                      probeDataRates[2];
-   	    len += sprintf(buf+len,"ownBeaconInterval:    0x%04X\n", lp->ownBeaconInterval );
-   	    len += sprintf(buf+len,"coexistence:          0x%04X\n", lp->coexistence );
+		seq_printf(m, "ownBeaconInterval:    0x%04X\n", lp->ownBeaconInterval );
+		seq_printf(m, "coexistence:          0x%04X\n", lp->coexistence );
 //x		WVLAN_FRAME                 "txF:                0x%04X\n", lp->txF );
 //x		WVLAN_LFRAME                txList[DEFAULT_NUM_TX_FRAMES];
 //x		struct list_head            "txFree:             0x%04X\n", lp->txFree );
 //x		struct list_head            txQ[WVLAN_MAX_TX_QUEUES];
-   	    len += sprintf(buf+len,"netif_queue_on:       0x%04X\n", lp->netif_queue_on );
-   	    len += sprintf(buf+len,"txQ_count:            0x%04X\n", lp->txQ_count );
+		seq_printf(m, "netif_queue_on:       0x%04X\n", lp->netif_queue_on );
+		seq_printf(m, "txQ_count:            0x%04X\n", lp->txQ_count );
 //x		DESC_STRCT                  "desc_rx:            0x%04X\n", lp->desc_rx );
 //x		DESC_STRCT                  "desc_tx:            0x%04X\n", lp->desc_tx );
 //x		WVLAN_PORT_STATE            "portState:          0x%04X\n", lp->portState );
 //x		ScanResult                  "scan_results:       0x%04X\n", lp->scan_results );
 //x		ProbeResult                 "probe_results:      0x%04X\n", lp->probe_results );
-   	    len += sprintf(buf+len,"probe_num_aps:        0x%04X\n", lp->probe_num_aps );
-   	    len += sprintf(buf+len,"use_dma:              0x%04X\n", lp->use_dma );
+		seq_printf(m, "probe_num_aps:        0x%04X\n", lp->probe_num_aps );
+		seq_printf(m, "use_dma:              0x%04X\n", lp->use_dma );
 //x		DMA_STRCT                   "dma:                0x%04X\n", lp->dma );
 #ifdef USE_RTS
-   	    len += sprintf(buf+len,"useRTS:               0x%04X\n", lp->useRTS );
+		seq_printf(m, "useRTS:               0x%04X\n", lp->useRTS );
 #endif  // USE_RTS
 #if 1 //;? (HCF_TYPE) & HCF_TYPE_AP
 		//;?should we restore this to allow smaller memory footprint
 		//;?I guess not. This should be brought under Debug mode only
-   	    len += sprintf(buf+len,"DTIMPeriod:           0x%04X\n", lp->DTIMPeriod );         // 1 - 255 (1)
-   	    len += sprintf(buf+len,"multicastPMBuffering: 0x%04X\n", lp->multicastPMBuffering );
-   	    len += sprintf(buf+len,"RejectAny:            0x%04X\n", lp->RejectAny );          // 0 - 1 (0)
-   	    len += sprintf(buf+len,"ExcludeUnencrypted:   0x%04X\n", lp->ExcludeUnencrypted ); // 0 - 1 (1)
-   	    len += sprintf(buf+len,"intraBSSRelay:        0x%04X\n", lp->intraBSSRelay );
-   	    len += sprintf(buf+len,"wlags49_type:             0x%08lX\n", lp->wlags49_type );
+		seq_printf(m, "DTIMPeriod:           0x%04X\n", lp->DTIMPeriod );         // 1 - 255 (1)
+		seq_printf(m, "multicastPMBuffering: 0x%04X\n", lp->multicastPMBuffering );
+		seq_printf(m, "RejectAny:            0x%04X\n", lp->RejectAny );          // 0 - 1 (0)
+		seq_printf(m, "ExcludeUnencrypted:   0x%04X\n", lp->ExcludeUnencrypted ); // 0 - 1 (1)
+		seq_printf(m, "intraBSSRelay:        0x%04X\n", lp->intraBSSRelay );
+		seq_printf(m, "wlags49_type:             0x%08lX\n", lp->wlags49_type );
 #ifdef USE_WDS
 //x		WVLAN_WDS_IF                wds_port[NUM_WDS_PORTS];
 #endif // USE_WDS
 #endif // HCF_AP
 	} else if ( lp->wlags49_type == 2 ){
-        len += sprintf(buf+len,"tallies to be added\n" );
+		seq_printf(m, "tallies to be added\n" );
 //Hermes Tallies (IFB substructure) {
-   	    p = &lp->hcfCtx.IFB_NIC_Tallies;
-        len += sprintf(buf+len,"TxUnicastFrames:          %08lX\n", p->TxUnicastFrames );
-        len += sprintf(buf+len,"TxMulticastFrames:        %08lX\n", p->TxMulticastFrames );
-        len += sprintf(buf+len,"TxFragments:              %08lX\n", p->TxFragments );
-        len += sprintf(buf+len,"TxUnicastOctets:          %08lX\n", p->TxUnicastOctets );
-        len += sprintf(buf+len,"TxMulticastOctets:        %08lX\n", p->TxMulticastOctets );
-        len += sprintf(buf+len,"TxDeferredTransmissions:  %08lX\n", p->TxDeferredTransmissions );
-        len += sprintf(buf+len,"TxSingleRetryFrames:      %08lX\n", p->TxSingleRetryFrames );
-        len += sprintf(buf+len,"TxMultipleRetryFrames:    %08lX\n", p->TxMultipleRetryFrames );
-        len += sprintf(buf+len,"TxRetryLimitExceeded:     %08lX\n", p->TxRetryLimitExceeded );
-        len += sprintf(buf+len,"TxDiscards:               %08lX\n", p->TxDiscards );
-        len += sprintf(buf+len,"RxUnicastFrames:          %08lX\n", p->RxUnicastFrames );
-        len += sprintf(buf+len,"RxMulticastFrames:        %08lX\n", p->RxMulticastFrames );
-        len += sprintf(buf+len,"RxFragments:              %08lX\n", p->RxFragments );
-        len += sprintf(buf+len,"RxUnicastOctets:          %08lX\n", p->RxUnicastOctets );
-        len += sprintf(buf+len,"RxMulticastOctets:        %08lX\n", p->RxMulticastOctets );
-        len += sprintf(buf+len,"RxFCSErrors:              %08lX\n", p->RxFCSErrors );
-        len += sprintf(buf+len,"RxDiscardsNoBuffer:       %08lX\n", p->RxDiscardsNoBuffer );
-        len += sprintf(buf+len,"TxDiscardsWrongSA:        %08lX\n", p->TxDiscardsWrongSA );
-        len += sprintf(buf+len,"RxWEPUndecryptable:       %08lX\n", p->RxWEPUndecryptable );
-        len += sprintf(buf+len,"RxMsgInMsgFragments:      %08lX\n", p->RxMsgInMsgFragments );
-        len += sprintf(buf+len,"RxMsgInBadMsgFragments:   %08lX\n", p->RxMsgInBadMsgFragments );
-        len += sprintf(buf+len,"RxDiscardsWEPICVError:    %08lX\n", p->RxDiscardsWEPICVError );
-        len += sprintf(buf+len,"RxDiscardsWEPExcluded:    %08lX\n", p->RxDiscardsWEPExcluded );
+		p = &lp->hcfCtx.IFB_NIC_Tallies;
+		seq_printf(m, "TxUnicastFrames:          %08lX\n", p->TxUnicastFrames );
+		seq_printf(m, "TxMulticastFrames:        %08lX\n", p->TxMulticastFrames );
+		seq_printf(m, "TxFragments:              %08lX\n", p->TxFragments );
+		seq_printf(m, "TxUnicastOctets:          %08lX\n", p->TxUnicastOctets );
+		seq_printf(m, "TxMulticastOctets:        %08lX\n", p->TxMulticastOctets );
+		seq_printf(m, "TxDeferredTransmissions:  %08lX\n", p->TxDeferredTransmissions );
+		seq_printf(m, "TxSingleRetryFrames:      %08lX\n", p->TxSingleRetryFrames );
+		seq_printf(m, "TxMultipleRetryFrames:    %08lX\n", p->TxMultipleRetryFrames );
+		seq_printf(m, "TxRetryLimitExceeded:     %08lX\n", p->TxRetryLimitExceeded );
+		seq_printf(m, "TxDiscards:               %08lX\n", p->TxDiscards );
+		seq_printf(m, "RxUnicastFrames:          %08lX\n", p->RxUnicastFrames );
+		seq_printf(m, "RxMulticastFrames:        %08lX\n", p->RxMulticastFrames );
+		seq_printf(m, "RxFragments:              %08lX\n", p->RxFragments );
+		seq_printf(m, "RxUnicastOctets:          %08lX\n", p->RxUnicastOctets );
+		seq_printf(m, "RxMulticastOctets:        %08lX\n", p->RxMulticastOctets );
+		seq_printf(m, "RxFCSErrors:              %08lX\n", p->RxFCSErrors );
+		seq_printf(m, "RxDiscardsNoBuffer:       %08lX\n", p->RxDiscardsNoBuffer );
+		seq_printf(m, "TxDiscardsWrongSA:        %08lX\n", p->TxDiscardsWrongSA );
+		seq_printf(m, "RxWEPUndecryptable:       %08lX\n", p->RxWEPUndecryptable );
+		seq_printf(m, "RxMsgInMsgFragments:      %08lX\n", p->RxMsgInMsgFragments );
+		seq_printf(m, "RxMsgInBadMsgFragments:   %08lX\n", p->RxMsgInBadMsgFragments );
+		seq_printf(m, "RxDiscardsWEPICVError:    %08lX\n", p->RxDiscardsWEPICVError );
+		seq_printf(m, "RxDiscardsWEPExcluded:    %08lX\n", p->RxDiscardsWEPExcluded );
 #if (HCF_EXT) & HCF_EXT_TALLIES_FW
-        //to be added ;?
+		//to be added ;?
 #endif // HCF_EXT_TALLIES_FW
 	} else if ( lp->wlags49_type & 0x8000 ) {	//;?kludgy but it is unclear to me were else to place this
 #if DBG
@@ -3761,27 +3760,19 @@
 #endif // DBG
 		lp->wlags49_type = 0;				//default to IFB again ;?
 	} else {
-        len += sprintf(buf+len,"unknown value for wlags49_type: 0x%08lX\n", lp->wlags49_type );
-        len += sprintf(buf+len,"0x0000 - IFB\n" );
-        len += sprintf(buf+len,"0x0001 - wl_private\n" );
-        len += sprintf(buf+len,"0x0002 - Tallies\n" );
-        len += sprintf(buf+len,"0x8xxx - Change debufflag\n" );
-        len += sprintf(buf+len,"ERROR    0001\nWARNING  0002\nNOTICE   0004\nTRACE    0008\n" );
-        len += sprintf(buf+len,"VERBOSE  0010\nPARAM    0020\nBREAK    0040\nRX       0100\n" );
-        len += sprintf(buf+len,"TX       0200\nDS       0400\n" );
+		seq_printf(m, "unknown value for wlags49_type: 0x%08lX\n", lp->wlags49_type );
+		seq_puts(m,
+			 "0x0000 - IFB\n"
+			 "0x0001 - wl_private\n"
+			 "0x0002 - Tallies\n"
+			 "0x8xxx - Change debufflag\n"
+			 "ERROR    0001\nWARNING  0002\nNOTICE   0004\nTRACE    0008\n"
+			 "VERBOSE  0010\nPARAM    0020\nBREAK    0040\nRX       0100\n"
+			 "TX       0200\nDS       0400\n");
 	}
-    return len;
+	return 0;
 } // scull_read_procmem
 
-static void proc_write(const char *name, write_proc_t *w, void *data)
-{
-	struct proc_dir_entry * entry = create_proc_entry(name, S_IFREG | S_IWUSR, NULL);
-	if (entry) {
-		entry->write_proc = w;
-		entry->data = data;
-	}
-} // proc_write
-
 static int write_int(struct file *file, const char *buffer, unsigned long count, void *data)
 {
 	static char		proc_number[11];
diff --git a/drivers/target/loopback/tcm_loop.c b/drivers/target/loopback/tcm_loop.c
index 2d444b1..7c90814 100644
--- a/drivers/target/loopback/tcm_loop.c
+++ b/drivers/target/loopback/tcm_loop.c
@@ -79,11 +79,10 @@
 	kmem_cache_free(tcm_loop_cmd_cache, tl_cmd);
 }
 
-static int tcm_loop_proc_info(struct Scsi_Host *host, char *buffer,
-				char **start, off_t offset,
-				int length, int inout)
+static int tcm_loop_show_info(struct seq_file *m, struct Scsi_Host *host)
 {
-	return sprintf(buffer, "tcm_loop_proc_info()\n");
+	seq_printf(m, "tcm_loop_proc_info()\n");
+	return 0;
 }
 
 static int tcm_loop_driver_probe(struct device *);
@@ -336,7 +335,7 @@
 }
 
 static struct scsi_host_template tcm_loop_driver_template = {
-	.proc_info		= tcm_loop_proc_info,
+	.show_info		= tcm_loop_show_info,
 	.proc_name		= "tcm_loopback",
 	.name			= "TCM_Loopback",
 	.queuecommand		= tcm_loop_queuecommand,
diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c
index 8fbb6d2..f87dbfd 100644
--- a/drivers/tty/serial/serial_core.c
+++ b/drivers/tty/serial/serial_core.c
@@ -1711,7 +1711,7 @@
 
 static int uart_proc_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, uart_proc_show, PDE(inode)->data);
+	return single_open(file, uart_proc_show, PDE_DATA(inode));
 }
 
 static const struct file_operations uart_proc_fops = {
diff --git a/drivers/usb/gadget/at91_udc.c b/drivers/usb/gadget/at91_udc.c
index a690d64..073b938 100644
--- a/drivers/usb/gadget/at91_udc.c
+++ b/drivers/usb/gadget/at91_udc.c
@@ -221,7 +221,7 @@
 
 static int proc_udc_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, proc_udc_show, PDE(inode)->data);
+	return single_open(file, proc_udc_show, PDE_DATA(inode));
 }
 
 static const struct file_operations proc_ops = {
diff --git a/drivers/usb/gadget/f_fs.c b/drivers/usb/gadget/f_fs.c
index c377ff8..f394f29 100644
--- a/drivers/usb/gadget/f_fs.c
+++ b/drivers/usb/gadget/f_fs.c
@@ -727,7 +727,6 @@
 }
 
 static const struct file_operations ffs_ep0_operations = {
-	.owner =	THIS_MODULE,
 	.llseek =	no_llseek,
 
 	.open =		ffs_ep0_open,
@@ -947,7 +946,6 @@
 }
 
 static const struct file_operations ffs_epfile_operations = {
-	.owner =	THIS_MODULE,
 	.llseek =	no_llseek,
 
 	.open =		ffs_epfile_open,
diff --git a/drivers/usb/gadget/fsl_udc_core.c b/drivers/usb/gadget/fsl_udc_core.c
index 7c2a101..2d8c1cf 100644
--- a/drivers/usb/gadget/fsl_udc_core.c
+++ b/drivers/usb/gadget/fsl_udc_core.c
@@ -2010,47 +2010,37 @@
 
 static const char proc_filename[] = "driver/fsl_usb2_udc";
 
-static int fsl_proc_read(char *page, char **start, off_t off, int count,
-		int *eof, void *_dev)
+static int fsl_proc_read(struct seq_file *m, void *v)
 {
-	char *buf = page;
-	char *next = buf;
-	unsigned size = count;
 	unsigned long flags;
-	int t, i;
+	int i;
 	u32 tmp_reg;
 	struct fsl_ep *ep = NULL;
 	struct fsl_req *req;
 
 	struct fsl_udc *udc = udc_controller;
-	if (off != 0)
-		return 0;
 
 	spin_lock_irqsave(&udc->lock, flags);
 
 	/* ------basic driver information ---- */
-	t = scnprintf(next, size,
+	seq_printf(m,
 			DRIVER_DESC "\n"
 			"%s version: %s\n"
 			"Gadget driver: %s\n\n",
 			driver_name, DRIVER_VERSION,
 			udc->driver ? udc->driver->driver.name : "(none)");
-	size -= t;
-	next += t;
 
 	/* ------ DR Registers ----- */
 	tmp_reg = fsl_readl(&dr_regs->usbcmd);
-	t = scnprintf(next, size,
+	seq_printf(m,
 			"USBCMD reg:\n"
 			"SetupTW: %d\n"
 			"Run/Stop: %s\n\n",
 			(tmp_reg & USB_CMD_SUTW) ? 1 : 0,
 			(tmp_reg & USB_CMD_RUN_STOP) ? "Run" : "Stop");
-	size -= t;
-	next += t;
 
 	tmp_reg = fsl_readl(&dr_regs->usbsts);
-	t = scnprintf(next, size,
+	seq_printf(m,
 			"USB Status Reg:\n"
 			"Dr Suspend: %d Reset Received: %d System Error: %s "
 			"USB Error Interrupt: %s\n\n",
@@ -2058,11 +2048,9 @@
 			(tmp_reg & USB_STS_RESET) ? 1 : 0,
 			(tmp_reg & USB_STS_SYS_ERR) ? "Err" : "Normal",
 			(tmp_reg & USB_STS_ERR) ? "Err detected" : "No err");
-	size -= t;
-	next += t;
 
 	tmp_reg = fsl_readl(&dr_regs->usbintr);
-	t = scnprintf(next, size,
+	seq_printf(m,
 			"USB Interrupt Enable Reg:\n"
 			"Sleep Enable: %d SOF Received Enable: %d "
 			"Reset Enable: %d\n"
@@ -2076,33 +2064,25 @@
 			(tmp_reg & USB_INTR_PTC_DETECT_EN) ? 1 : 0,
 			(tmp_reg & USB_INTR_ERR_INT_EN) ? 1 : 0,
 			(tmp_reg & USB_INTR_INT_EN) ? 1 : 0);
-	size -= t;
-	next += t;
 
 	tmp_reg = fsl_readl(&dr_regs->frindex);
-	t = scnprintf(next, size,
+	seq_printf(m,
 			"USB Frame Index Reg: Frame Number is 0x%x\n\n",
 			(tmp_reg & USB_FRINDEX_MASKS));
-	size -= t;
-	next += t;
 
 	tmp_reg = fsl_readl(&dr_regs->deviceaddr);
-	t = scnprintf(next, size,
+	seq_printf(m,
 			"USB Device Address Reg: Device Addr is 0x%x\n\n",
 			(tmp_reg & USB_DEVICE_ADDRESS_MASK));
-	size -= t;
-	next += t;
 
 	tmp_reg = fsl_readl(&dr_regs->endpointlistaddr);
-	t = scnprintf(next, size,
+	seq_printf(m,
 			"USB Endpoint List Address Reg: "
 			"Device Addr is 0x%x\n\n",
 			(tmp_reg & USB_EP_LIST_ADDRESS_MASK));
-	size -= t;
-	next += t;
 
 	tmp_reg = fsl_readl(&dr_regs->portsc1);
-	t = scnprintf(next, size,
+	seq_printf(m,
 		"USB Port Status&Control Reg:\n"
 		"Port Transceiver Type : %s Port Speed: %s\n"
 		"PHY Low Power Suspend: %s Port Reset: %s "
@@ -2111,7 +2091,7 @@
 		"Port Enable/Disable Change: %s\n"
 		"Port Enabled/Disabled: %s "
 		"Current Connect Status: %s\n\n", ( {
-			char *s;
+			const char *s;
 			switch (tmp_reg & PORTSCX_PTS_FSLS) {
 			case PORTSCX_PTS_UTMI:
 				s = "UTMI"; break;
@@ -2137,13 +2117,11 @@
 		"Not correct",
 		(tmp_reg & PORTSCX_CURRENT_CONNECT_STATUS) ?
 		"Attached" : "Not-Att");
-	size -= t;
-	next += t;
 
 	tmp_reg = fsl_readl(&dr_regs->usbmode);
-	t = scnprintf(next, size,
+	seq_printf(m,
 			"USB Mode Reg: Controller Mode is: %s\n\n", ( {
-				char *s;
+				const char *s;
 				switch (tmp_reg & USB_MODE_CTRL_MODE_HOST) {
 				case USB_MODE_CTRL_MODE_IDLE:
 					s = "Idle"; break;
@@ -2156,103 +2134,87 @@
 				}
 				s;
 			} ));
-	size -= t;
-	next += t;
 
 	tmp_reg = fsl_readl(&dr_regs->endptsetupstat);
-	t = scnprintf(next, size,
+	seq_printf(m,
 			"Endpoint Setup Status Reg: SETUP on ep 0x%x\n\n",
 			(tmp_reg & EP_SETUP_STATUS_MASK));
-	size -= t;
-	next += t;
 
 	for (i = 0; i < udc->max_ep / 2; i++) {
 		tmp_reg = fsl_readl(&dr_regs->endptctrl[i]);
-		t = scnprintf(next, size, "EP Ctrl Reg [0x%x]: = [0x%x]\n",
-				i, tmp_reg);
-		size -= t;
-		next += t;
+		seq_printf(m, "EP Ctrl Reg [0x%x]: = [0x%x]\n", i, tmp_reg);
 	}
 	tmp_reg = fsl_readl(&dr_regs->endpointprime);
-	t = scnprintf(next, size, "EP Prime Reg = [0x%x]\n\n", tmp_reg);
-	size -= t;
-	next += t;
+	seq_printf(m, "EP Prime Reg = [0x%x]\n\n", tmp_reg);
 
 #ifndef CONFIG_ARCH_MXC
 	if (udc->pdata->have_sysif_regs) {
 		tmp_reg = usb_sys_regs->snoop1;
-		t = scnprintf(next, size, "Snoop1 Reg : = [0x%x]\n\n", tmp_reg);
-		size -= t;
-		next += t;
+		seq_printf(m, "Snoop1 Reg : = [0x%x]\n\n", tmp_reg);
 
 		tmp_reg = usb_sys_regs->control;
-		t = scnprintf(next, size, "General Control Reg : = [0x%x]\n\n",
-				tmp_reg);
-		size -= t;
-		next += t;
+		seq_printf(m, "General Control Reg : = [0x%x]\n\n", tmp_reg);
 	}
 #endif
 
 	/* ------fsl_udc, fsl_ep, fsl_request structure information ----- */
 	ep = &udc->eps[0];
-	t = scnprintf(next, size, "For %s Maxpkt is 0x%x index is 0x%x\n",
+	seq_printf(m, "For %s Maxpkt is 0x%x index is 0x%x\n",
 			ep->ep.name, ep_maxpacket(ep), ep_index(ep));
-	size -= t;
-	next += t;
 
 	if (list_empty(&ep->queue)) {
-		t = scnprintf(next, size, "its req queue is empty\n\n");
-		size -= t;
-		next += t;
+		seq_puts(m, "its req queue is empty\n\n");
 	} else {
 		list_for_each_entry(req, &ep->queue, queue) {
-			t = scnprintf(next, size,
+			seq_printf(m,
 				"req %p actual 0x%x length 0x%x buf %p\n",
 				&req->req, req->req.actual,
 				req->req.length, req->req.buf);
-			size -= t;
-			next += t;
 		}
 	}
 	/* other gadget->eplist ep */
 	list_for_each_entry(ep, &udc->gadget.ep_list, ep.ep_list) {
 		if (ep->ep.desc) {
-			t = scnprintf(next, size,
+			seq_printf(m,
 					"\nFor %s Maxpkt is 0x%x "
 					"index is 0x%x\n",
 					ep->ep.name, ep_maxpacket(ep),
 					ep_index(ep));
-			size -= t;
-			next += t;
 
 			if (list_empty(&ep->queue)) {
-				t = scnprintf(next, size,
-						"its req queue is empty\n\n");
-				size -= t;
-				next += t;
+				seq_puts(m, "its req queue is empty\n\n");
 			} else {
 				list_for_each_entry(req, &ep->queue, queue) {
-					t = scnprintf(next, size,
+					seq_printf(m,
 						"req %p actual 0x%x length "
 						"0x%x  buf %p\n",
 						&req->req, req->req.actual,
 						req->req.length, req->req.buf);
-					size -= t;
-					next += t;
-					}	/* end for each_entry of ep req */
-				}	/* end for else */
-			}	/* end for if(ep->queue) */
-		}		/* end (ep->desc) */
+				}	/* end for each_entry of ep req */
+			}	/* end for else */
+		}	/* end for if(ep->queue) */
+	}	/* end (ep->desc) */
 
 	spin_unlock_irqrestore(&udc->lock, flags);
-
-	*eof = 1;
-	return count - size;
+	return 0;
 }
 
-#define create_proc_file()	create_proc_read_entry(proc_filename, \
-				0, NULL, fsl_proc_read, NULL)
+/*
+ * seq_file wrappers for procfile show routines.
+ */
+static int fsl_proc_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, fsl_proc_read, NULL);
+}
 
+static const struct file_operations fsl_proc_fops = {
+	.open		= fsl_proc_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= seq_release,
+};
+
+#define create_proc_file()	proc_create(proc_filename, 0, NULL, &fsl_proc_fops)
 #define remove_proc_file()	remove_proc_entry(proc_filename, NULL)
 
 #else				/* !CONFIG_USB_GADGET_DEBUG_FILES */
diff --git a/drivers/usb/gadget/goku_udc.c b/drivers/usb/gadget/goku_udc.c
index 991aba3..480eeb7 100644
--- a/drivers/usb/gadget/goku_udc.c
+++ b/drivers/usb/gadget/goku_udc.c
@@ -35,6 +35,7 @@
 #include <linux/list.h>
 #include <linux/interrupt.h>
 #include <linux/proc_fs.h>
+#include <linux/seq_file.h>
 #include <linux/device.h>
 #include <linux/usb/ch9.h>
 #include <linux/usb/gadget.h>
@@ -1005,7 +1006,7 @@
 
 /*-------------------------------------------------------------------------*/
 
-static inline char *dmastr(void)
+static inline const char *dmastr(void)
 {
 	if (use_dma == 0)
 		return "(dma disabled)";
@@ -1022,13 +1023,10 @@
 #define FOURBITS "%s%s%s%s"
 #define EIGHTBITS FOURBITS FOURBITS
 
-static void
-dump_intmask(const char *label, u32 mask, char **next, unsigned *size)
+static void dump_intmask(struct seq_file *m, const char *label, u32 mask)
 {
-	int t;
-
 	/* int_status is the same format ... */
-	t = scnprintf(*next, *size,
+	seq_printf(m,
 		"%s %05X =" FOURBITS EIGHTBITS EIGHTBITS "\n",
 		label, mask,
 		(mask & INT_PWRDETECT) ? " power" : "",
@@ -1055,33 +1053,23 @@
 		(mask & INT_ENDPOINT0) ? " ep0" : "",
 		(mask & INT_USBRESET) ? " reset" : "",
 		(mask & INT_SUSPEND) ? " suspend" : "");
-	*size -= t;
-	*next += t;
 }
 
 
-static int
-udc_proc_read(char *buffer, char **start, off_t off, int count,
-		int *eof, void *_dev)
+static int udc_proc_read(struct seq_file *m, void *v)
 {
-	char				*buf = buffer;
-	struct goku_udc			*dev = _dev;
+	struct goku_udc			*dev = m->private;
 	struct goku_udc_regs __iomem	*regs = dev->regs;
-	char				*next = buf;
-	unsigned			size = count;
 	unsigned long			flags;
-	int				i, t, is_usb_connected;
+	int				i, is_usb_connected;
 	u32				tmp;
 
-	if (off != 0)
-		return 0;
-
 	local_irq_save(flags);
 
 	/* basic device status */
 	tmp = readl(&regs->power_detect);
 	is_usb_connected = tmp & PW_DETECT;
-	t = scnprintf(next, size,
+	seq_printf(m,
 		"%s - %s\n"
 		"%s version: %s %s\n"
 		"Gadget driver: %s\n"
@@ -1093,7 +1081,7 @@
 		is_usb_connected
 			? ((tmp & PW_PULLUP) ? "full speed" : "powered")
 			: "disconnected",
-		({char *state;
+		({const char *state;
 		switch(dev->ep0state){
 		case EP0_DISCONNECT:	state = "ep0_disconnect"; break;
 		case EP0_IDLE:		state = "ep0_idle"; break;
@@ -1105,27 +1093,24 @@
 		default:		state = "ep0_?"; break;
 		} state; })
 		);
-	size -= t;
-	next += t;
 
-	dump_intmask("int_status", readl(&regs->int_status), &next, &size);
-	dump_intmask("int_enable", readl(&regs->int_enable), &next, &size);
+	dump_intmask(m, "int_status", readl(&regs->int_status));
+	dump_intmask(m, "int_enable", readl(&regs->int_enable));
 
 	if (!is_usb_connected || !dev->driver || (tmp & PW_PULLUP) == 0)
 		goto done;
 
 	/* registers for (active) device and ep0 */
-	t = scnprintf(next, size, "\nirqs %lu\ndataset %02x "
+	if (seq_printf(m, "\nirqs %lu\ndataset %02x "
 			"single.bcs %02x.%02x state %x addr %u\n",
 			dev->irqs, readl(&regs->DataSet),
 			readl(&regs->EPxSingle), readl(&regs->EPxBCS),
 			readl(&regs->UsbState),
-			readl(&regs->address));
-	size -= t;
-	next += t;
+			readl(&regs->address)) < 0)
+		goto done;
 
 	tmp = readl(&regs->dma_master);
-	t = scnprintf(next, size,
+	if (seq_printf(m,
 		"dma %03X =" EIGHTBITS "%s %s\n", tmp,
 		(tmp & MST_EOPB_DIS) ? " eopb-" : "",
 		(tmp & MST_EOPB_ENA) ? " eopb+" : "",
@@ -1140,9 +1125,8 @@
 		(tmp & MST_WR_ENA) ? " OUT" : "",
 		(tmp & MST_CONNECTION)
 			? "ep1in/ep2out"
-			: "ep1out/ep2in");
-	size -= t;
-	next += t;
+			: "ep1out/ep2in") < 0)
+		goto done;
 
 	/* dump endpoint queues */
 	for (i = 0; i < 4; i++) {
@@ -1153,7 +1137,7 @@
 			continue;
 
 		tmp = readl(ep->reg_status);
-		t = scnprintf(next, size,
+		if (seq_printf(m,
 			"%s %s max %u %s, irqs %lu, "
 			"status %02x (%s) " FOURBITS "\n",
 			ep->ep.name,
@@ -1186,18 +1170,12 @@
 			(tmp & EPxSTATUS_SUSPEND) ? " suspend" : "",
 			(tmp & EPxSTATUS_FIFO_DISABLE) ? " disable" : "",
 			(tmp & EPxSTATUS_STAGE_ERROR) ? " ep0stat" : ""
-			);
-		if (t <= 0 || t > size)
+			) < 0)
 			goto done;
-		size -= t;
-		next += t;
 
 		if (list_empty(&ep->queue)) {
-			t = scnprintf(next, size, "\t(nothing queued)\n");
-			if (t <= 0 || t > size)
+			if (seq_puts(m, "\t(nothing queued)\n") < 0)
 				goto done;
-			size -= t;
-			next += t;
 			continue;
 		}
 		list_for_each_entry(req, &ep->queue, queue) {
@@ -1211,23 +1189,34 @@
 			} else
 				tmp = req->req.actual;
 
-			t = scnprintf(next, size,
+			if (seq_printf(m,
 				"\treq %p len %u/%u buf %p\n",
 				&req->req, tmp, req->req.length,
-				req->req.buf);
-			if (t <= 0 || t > size)
+				req->req.buf) < 0)
 				goto done;
-			size -= t;
-			next += t;
 		}
 	}
 
 done:
 	local_irq_restore(flags);
-	*eof = 1;
-	return count - size;
+	return 0;
 }
 
+/*
+ * seq_file wrappers for procfile show routines.
+ */
+static int udc_proc_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, udc_proc_read, PDE_DATA(file_inode(file)));
+}
+
+static const struct file_operations udc_proc_fops = {
+	.open		= udc_proc_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= seq_release,
+};
+
 #endif	/* CONFIG_USB_GADGET_DEBUG_FILES */
 
 /*-------------------------------------------------------------------------*/
@@ -1796,7 +1785,7 @@
 
 
 #ifdef CONFIG_USB_GADGET_DEBUG_FILES
-	create_proc_read_entry(proc_node_name, 0, NULL, udc_proc_read, dev);
+	proc_create_data(proc_node_name, 0, NULL, &udc_proc_fops, dev);
 #endif
 
 	retval = usb_add_gadget_udc_release(&pdev->dev, &dev->gadget,
diff --git a/drivers/usb/gadget/inode.c b/drivers/usb/gadget/inode.c
index e2b2e9c..dda0dc4 100644
--- a/drivers/usb/gadget/inode.c
+++ b/drivers/usb/gadget/inode.c
@@ -887,7 +887,6 @@
 
 /* used before endpoint configuration */
 static const struct file_operations ep_config_operations = {
-	.owner =	THIS_MODULE,
 	.llseek =	no_llseek,
 
 	.open =		ep_open,
@@ -1940,7 +1939,6 @@
 }
 
 static const struct file_operations dev_init_operations = {
-	.owner =	THIS_MODULE,
 	.llseek =	no_llseek,
 
 	.open =		dev_open,
diff --git a/drivers/usb/gadget/lpc32xx_udc.c b/drivers/usb/gadget/lpc32xx_udc.c
index b943d8c..67128be 100644
--- a/drivers/usb/gadget/lpc32xx_udc.c
+++ b/drivers/usb/gadget/lpc32xx_udc.c
@@ -565,7 +565,7 @@
 
 static int proc_udc_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, proc_udc_show, PDE(inode)->data);
+	return single_open(file, proc_udc_show, PDE_DATA(inode));
 }
 
 static const struct file_operations proc_ops = {
diff --git a/drivers/usb/gadget/rndis.c b/drivers/usb/gadget/rndis.c
index d9297ee..1e4cfb0 100644
--- a/drivers/usb/gadget/rndis.c
+++ b/drivers/usb/gadget/rndis.c
@@ -1065,7 +1065,7 @@
 static ssize_t rndis_proc_write(struct file *file, const char __user *buffer,
 				size_t count, loff_t *ppos)
 {
-	rndis_params *p = PDE(file_inode(file))->data;
+	rndis_params *p = PDE_DATA(file_inode(file));
 	u32 speed = 0;
 	int i, fl_speed = 0;
 
@@ -1109,7 +1109,7 @@
 
 static int rndis_proc_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, rndis_proc_show, PDE(inode)->data);
+	return single_open(file, rndis_proc_show, PDE_DATA(inode));
 }
 
 static const struct file_operations rndis_proc_fops = {
diff --git a/drivers/usb/host/isp1362-hcd.c b/drivers/usb/host/isp1362-hcd.c
index 974480c..b04e8ec 100644
--- a/drivers/usb/host/isp1362-hcd.c
+++ b/drivers/usb/host/isp1362-hcd.c
@@ -2175,7 +2175,7 @@
 
 static int proc_isp1362_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, proc_isp1362_show, PDE(inode)->data);
+	return single_open(file, proc_isp1362_show, PDE_DATA(inode));
 }
 
 static const struct file_operations proc_ops = {
@@ -2192,14 +2192,11 @@
 {
 	struct proc_dir_entry *pde;
 
-	pde = create_proc_entry(proc_filename, 0, NULL);
+	pde = proc_create_data(proc_filename, 0, NULL, &proc_ops, isp1362_hcd);
 	if (pde == NULL) {
 		pr_warning("%s: Failed to create debug file '%s'\n", __func__, proc_filename);
 		return;
 	}
-
-	pde->proc_fops = &proc_ops;
-	pde->data = isp1362_hcd;
 	isp1362_hcd->pde = pde;
 }
 
diff --git a/drivers/usb/host/sl811-hcd.c b/drivers/usb/host/sl811-hcd.c
index 15ed7e8..ad4483e 100644
--- a/drivers/usb/host/sl811-hcd.c
+++ b/drivers/usb/host/sl811-hcd.c
@@ -1494,7 +1494,7 @@
 
 static int proc_sl811h_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, proc_sl811h_show, PDE(inode)->data);
+	return single_open(file, proc_sl811h_show, PDE_DATA(inode));
 }
 
 static const struct file_operations proc_ops = {
diff --git a/drivers/usb/misc/yurex.c b/drivers/usb/misc/yurex.c
index 42ad2e6..b6ab515 100644
--- a/drivers/usb/misc/yurex.c
+++ b/drivers/usb/misc/yurex.c
@@ -407,8 +407,6 @@
 	if (dev == NULL)
 		return -ENODEV;
 
-	yurex_fasync(-1, file, 0);
-
 	/* decrement the count on our device */
 	kref_put(&dev->kref, yurex_delete);
 	return 0;
diff --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c
index 4faa982..92b05d9 100644
--- a/drivers/usb/storage/scsiglue.c
+++ b/drivers/usb/storage/scsiglue.c
@@ -437,22 +437,21 @@
  * /proc/scsi/ functions
  ***********************************************************************/
 
+static int write_info(struct Scsi_Host *host, char *buffer, int length)
+{
+	/* if someone is sending us data, just throw it away */
+	return length;
+}
+
 /* we use this macro to help us write into the buffer */
 #undef SPRINTF
-#define SPRINTF(args...) \
-	do { if (pos < buffer+length) pos += sprintf(pos, ## args); } while (0)
+#define SPRINTF(args...) seq_printf(m, ## args)
 
-static int proc_info (struct Scsi_Host *host, char *buffer,
-		char **start, off_t offset, int length, int inout)
+static int show_info (struct seq_file *m, struct Scsi_Host *host)
 {
 	struct us_data *us = host_to_us(host);
-	char *pos = buffer;
 	const char *string;
 
-	/* if someone is sending us data, just throw it away */
-	if (inout)
-		return length;
-
 	/* print the controller name */
 	SPRINTF("   Host scsi%d: usb-storage\n", host->host_no);
 
@@ -482,28 +481,14 @@
 	SPRINTF("    Transport: %s\n", us->transport_name);
 
 	/* show the device flags */
-	if (pos < buffer + length) {
-		pos += sprintf(pos, "       Quirks:");
+	SPRINTF("       Quirks:");
 
 #define US_FLAG(name, value) \
-	if (us->fflags & value) pos += sprintf(pos, " " #name);
+	if (us->fflags & value) seq_printf(m, " " #name);
 US_DO_ALL_FLAGS
 #undef US_FLAG
-
-		*(pos++) = '\n';
-	}
-
-	/*
-	 * Calculate start of next buffer, and return value.
-	 */
-	*start = buffer + offset;
-
-	if ((pos - buffer) < offset)
-		return (0);
-	else if ((pos - buffer - offset) < length)
-		return (pos - buffer - offset);
-	else
-		return (length);
+	seq_putc(m, '\n');
+	return 0;
 }
 
 /***********************************************************************
@@ -548,7 +533,8 @@
 	/* basic userland interface stuff */
 	.name =				"usb-storage",
 	.proc_name =			"usb-storage",
-	.proc_info =			proc_info,
+	.show_info =			show_info,
+	.write_info =			write_info,
 	.info =				host_info,
 
 	/* command interface -- queued only */
diff --git a/drivers/video/bfin_adv7393fb.c b/drivers/video/bfin_adv7393fb.c
index 8d411a3..a54f7f7 100644
--- a/drivers/video/bfin_adv7393fb.c
+++ b/drivers/video/bfin_adv7393fb.c
@@ -333,29 +333,23 @@
 	return p - buf;
 }
 
-static int
-adv7393_read_proc(char *page, char **start, off_t off,
-		  int count, int *eof, void *data)
+static ssize_t
+adv7393_read_proc(struct file *file, char __user *buf,
+		  size_t size, loff_t *ppos)
 {
-	int len;
-
-	len = proc_output(page);
-	if (len <= off + count)
-		*eof = 1;
-	*start = page + off;
-	len -= off;
-	if (len > count)
-		len = count;
-	if (len < 0)
-		len = 0;
-	return len;
+	static const char message[] = "Usage:\n"
+		"echo 0x[REG][Value] > adv7393\n"
+		"example: echo 0x1234 >adv7393\n"
+		"writes 0x34 into Register 0x12\n";
+	return simple_read_from_buffer(buf, size, ppos, message,
+					sizeof(message));
 }
 
-static int
+static ssize_t
 adv7393_write_proc(struct file *file, const char __user * buffer,
-		   size_t count, void *data)
+		   size_t count, loff_t *ppos)
 {
-	struct adv7393fb_device *fbdev = data;
+	struct adv7393fb_device *fbdev = PDE_DATA(file_inode(file));
 	unsigned int val;
 	int ret;
 
@@ -368,6 +362,12 @@
 	return count;
 }
 
+static const struct file_operations fops = {
+	.read = adv7393_read_proc,
+	.write = adv7393_write_proc,
+	.llseek = default_llseek,
+};
+
 static int bfin_adv7393_fb_probe(struct i2c_client *client,
 				 const struct i2c_device_id *id)
 {
@@ -506,17 +506,12 @@
 	       fbdev->info.node, fbdev->info.fix.id);
 	dev_info(&client->dev, "fb memory address : 0x%p\n", fbdev->fb_mem);
 
-	entry = create_proc_entry("driver/adv7393", 0, NULL);
+	entry = proc_create_data("driver/adv7393", 0, NULL, &fops, fbdev);
 	if (!entry) {
 		dev_err(&client->dev, "unable to create /proc entry\n");
 		ret = -EFAULT;
 		goto free_fb;
 	}
-
-	entry->read_proc = adv7393_read_proc;
-	entry->write_proc = adv7393_write_proc;
-	entry->data = fbdev;
-
 	return 0;
 
 free_fb:
diff --git a/drivers/video/pxa3xx-gcu.c b/drivers/video/pxa3xx-gcu.c
index 6c984ea..97563c5 100644
--- a/drivers/video/pxa3xx-gcu.c
+++ b/drivers/video/pxa3xx-gcu.c
@@ -101,7 +101,6 @@
 	dma_addr_t		  shared_phys;
 	struct resource		 *resource_mem;
 	struct miscdevice	  misc_dev;
-	struct file_operations	  misc_fops;
 	wait_queue_head_t	  wait_idle;
 	wait_queue_head_t	  wait_free;
 	spinlock_t		  spinlock;
@@ -369,15 +368,20 @@
 
 /* Misc device layer */
 
+static inline struct pxa3xx_gcu_priv *file_dev(struct file *file)
+{
+	struct miscdevice *dev = file->private_data;
+	return container_of(dev, struct pxa3xx_gcu_priv, misc_dev);
+}
+
 static ssize_t
-pxa3xx_gcu_misc_write(struct file *filp, const char *buff,
+pxa3xx_gcu_misc_write(struct file *file, const char *buff,
 		      size_t count, loff_t *offp)
 {
 	int ret;
 	unsigned long flags;
 	struct pxa3xx_gcu_batch	*buffer;
-	struct pxa3xx_gcu_priv *priv =
-		container_of(filp->f_op, struct pxa3xx_gcu_priv, misc_fops);
+	struct pxa3xx_gcu_priv *priv = file_dev(file);
 
 	int words = count / 4;
 
@@ -450,11 +454,10 @@
 
 
 static long
-pxa3xx_gcu_misc_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+pxa3xx_gcu_misc_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 {
 	unsigned long flags;
-	struct pxa3xx_gcu_priv *priv =
-		container_of(filp->f_op, struct pxa3xx_gcu_priv, misc_fops);
+	struct pxa3xx_gcu_priv *priv = file_dev(file);
 
 	switch (cmd) {
 	case PXA3XX_GCU_IOCTL_RESET:
@@ -471,11 +474,10 @@
 }
 
 static int
-pxa3xx_gcu_misc_mmap(struct file *filp, struct vm_area_struct *vma)
+pxa3xx_gcu_misc_mmap(struct file *file, struct vm_area_struct *vma)
 {
 	unsigned int size = vma->vm_end - vma->vm_start;
-	struct pxa3xx_gcu_priv *priv =
-		container_of(filp->f_op, struct pxa3xx_gcu_priv, misc_fops);
+	struct pxa3xx_gcu_priv *priv = file_dev(file);
 
 	switch (vma->vm_pgoff) {
 	case 0:
@@ -574,6 +576,13 @@
 	priv->free = NULL;
 }
 
+static const struct file_operations misc_fops = {
+	.owner	= THIS_MODULE,
+	.write	= pxa3xx_gcu_misc_write,
+	.unlocked_ioctl = pxa3xx_gcu_misc_ioctl,
+	.mmap	= pxa3xx_gcu_misc_mmap
+};
+
 static int pxa3xx_gcu_probe(struct platform_device *dev)
 {
 	int i, ret, irq;
@@ -601,14 +610,9 @@
 	 * container_of(). This isn't really necessary as we have a fixed minor
 	 * number anyway, but this is to avoid statics. */
 
-	priv->misc_fops.owner	= THIS_MODULE;
-	priv->misc_fops.write	= pxa3xx_gcu_misc_write;
-	priv->misc_fops.unlocked_ioctl = pxa3xx_gcu_misc_ioctl;
-	priv->misc_fops.mmap	= pxa3xx_gcu_misc_mmap;
-
 	priv->misc_dev.minor	= MISCDEV_MINOR,
 	priv->misc_dev.name	= DRV_NAME,
-	priv->misc_dev.fops	= &priv->misc_fops,
+	priv->misc_dev.fops	= &misc_fops,
 
 	/* register misc device */
 	ret = misc_register(&priv->misc_dev);
diff --git a/drivers/zorro/proc.c b/drivers/zorro/proc.c
index 73b3383..1c15ee7 100644
--- a/drivers/zorro/proc.c
+++ b/drivers/zorro/proc.c
@@ -47,9 +47,7 @@
 static ssize_t
 proc_bus_zorro_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos)
 {
-	struct inode *ino = file_inode(file);
-	struct proc_dir_entry *dp = PDE(ino);
-	struct zorro_dev *z = dp->data;
+	struct zorro_dev *z = PDE_DATA(file_inode(file));
 	struct ConfigDev cd;
 	loff_t pos = *ppos;
 
@@ -141,7 +139,7 @@
 				 &zorro_autocon[slot]);
 	if (!entry)
 		return -ENOMEM;
-	entry->size = sizeof(struct zorro_dev);
+	proc_set_size(entry, sizeof(struct zorro_dev));
 	return 0;
 }
 
diff --git a/fs/Makefile b/fs/Makefile
index f0db9c9..4fe6df3 100644
--- a/fs/Makefile
+++ b/fs/Makefile
@@ -7,7 +7,7 @@
 
 obj-y :=	open.o read_write.o file_table.o super.o \
 		char_dev.o stat.o exec.o pipe.o namei.o fcntl.o \
-		ioctl.o readdir.o select.o fifo.o dcache.o inode.o \
+		ioctl.o readdir.o select.o dcache.o inode.o \
 		attr.o bad_inode.o file.o filesystems.o namespace.o \
 		seq_file.o xattr.o libfs.o fs-writeback.o \
 		pnode.o splice.o sync.o utimes.o \
diff --git a/fs/afs/proc.c b/fs/afs/proc.c
index 096b23f..526e4bb 100644
--- a/fs/afs/proc.c
+++ b/fs/afs/proc.c
@@ -190,7 +190,7 @@
 		return ret;
 
 	m = file->private_data;
-	m->private = PDE(inode)->data;
+	m->private = PDE_DATA(inode);
 
 	return 0;
 }
@@ -448,7 +448,7 @@
 	struct seq_file *m;
 	int ret;
 
-	cell = PDE(inode)->data;
+	cell = PDE_DATA(inode);
 	if (!cell)
 		return -ENOENT;
 
@@ -554,7 +554,7 @@
 	struct seq_file *m;
 	int ret;
 
-	cell = PDE(inode)->data;
+	cell = PDE_DATA(inode);
 	if (!cell)
 		return -ENOENT;
 
@@ -659,7 +659,7 @@
 	struct seq_file *m;
 	int ret;
 
-	cell = PDE(inode)->data;
+	cell = PDE_DATA(inode);
 	if (!cell)
 		return -ENOENT;
 
diff --git a/fs/aio.c b/fs/aio.c
index 6db8745..351afe7 100644
--- a/fs/aio.c
+++ b/fs/aio.c
@@ -1324,6 +1324,8 @@
 	if (iocb->ki_pos < 0)
 		return -EINVAL;
 
+	if (opcode == IOCB_CMD_PWRITEV)
+		file_start_write(file);
 	do {
 		ret = rw_op(iocb, &iocb->ki_iovec[iocb->ki_cur_seg],
 			    iocb->ki_nr_segs - iocb->ki_cur_seg,
@@ -1336,6 +1338,8 @@
 	} while (ret > 0 && iocb->ki_left > 0 &&
 		 (opcode == IOCB_CMD_PWRITEV ||
 		  (!S_ISFIFO(inode->i_mode) && !S_ISSOCK(inode->i_mode))));
+	if (opcode == IOCB_CMD_PWRITEV)
+		file_end_write(file);
 
 	/* This means we must have transferred all that we could */
 	/* No need to retry anymore */
diff --git a/fs/binfmt_aout.c b/fs/binfmt_aout.c
index 02fe378..bce8769 100644
--- a/fs/binfmt_aout.c
+++ b/fs/binfmt_aout.c
@@ -286,15 +286,12 @@
 			return error;
 		}
 
-		error = bprm->file->f_op->read(bprm->file,
-			  (char __user *)text_addr,
-			  ex.a_text+ex.a_data, &pos);
+		error = read_code(bprm->file, text_addr, pos,
+				  ex.a_text+ex.a_data);
 		if ((signed long)error < 0) {
 			send_sig(SIGKILL, current, 0);
 			return error;
 		}
-			 
-		flush_icache_range(text_addr, text_addr+ex.a_text+ex.a_data);
 	} else {
 		if ((ex.a_text & 0xfff || ex.a_data & 0xfff) &&
 		    (N_MAGIC(ex) != NMAGIC) && printk_ratelimit())
@@ -310,14 +307,9 @@
 		}
 
 		if (!bprm->file->f_op->mmap||((fd_offset & ~PAGE_MASK) != 0)) {
-			loff_t pos = fd_offset;
 			vm_brk(N_TXTADDR(ex), ex.a_text+ex.a_data);
-			bprm->file->f_op->read(bprm->file,
-					(char __user *)N_TXTADDR(ex),
-					ex.a_text+ex.a_data, &pos);
-			flush_icache_range((unsigned long) N_TXTADDR(ex),
-					   (unsigned long) N_TXTADDR(ex) +
-					   ex.a_text+ex.a_data);
+			read_code(bprm->file, N_TXTADDR(ex), fd_offset,
+				  ex.a_text + ex.a_data);
 			goto beyond_if;
 		}
 
@@ -396,8 +388,6 @@
 	start_addr =  ex.a_entry & 0xfffff000;
 
 	if ((N_TXTOFF(ex) & ~PAGE_MASK) != 0) {
-		loff_t pos = N_TXTOFF(ex);
-
 		if (printk_ratelimit())
 		{
 			printk(KERN_WARNING 
@@ -406,11 +396,8 @@
 		}
 		vm_brk(start_addr, ex.a_text + ex.a_data + ex.a_bss);
 		
-		file->f_op->read(file, (char __user *)start_addr,
-			ex.a_text + ex.a_data, &pos);
-		flush_icache_range((unsigned long) start_addr,
-				   (unsigned long) start_addr + ex.a_text + ex.a_data);
-
+		read_code(file, start_addr, N_TXTOFF(ex),
+			  ex.a_text + ex.a_data);
 		retval = 0;
 		goto out;
 	}
diff --git a/fs/binfmt_elf_fdpic.c b/fs/binfmt_elf_fdpic.c
index c1cc06a..9dac212 100644
--- a/fs/binfmt_elf_fdpic.c
+++ b/fs/binfmt_elf_fdpic.c
@@ -926,7 +926,6 @@
 	struct elf32_fdpic_loadseg *seg;
 	struct elf32_phdr *phdr;
 	unsigned long load_addr, base = ULONG_MAX, top = 0, maddr = 0, mflags;
-	loff_t fpos;
 	int loop, ret;
 
 	load_addr = params->load_addr;
@@ -964,14 +963,12 @@
 		if (params->phdrs[loop].p_type != PT_LOAD)
 			continue;
 
-		fpos = phdr->p_offset;
-
 		seg->addr = maddr + (phdr->p_vaddr - base);
 		seg->p_vaddr = phdr->p_vaddr;
 		seg->p_memsz = phdr->p_memsz;
 
-		ret = file->f_op->read(file, (void *) seg->addr,
-				       phdr->p_filesz, &fpos);
+		ret = read_code(file, seg->addr, phdr->p_offset,
+				       phdr->p_filesz);
 		if (ret < 0)
 			return ret;
 
diff --git a/fs/binfmt_flat.c b/fs/binfmt_flat.c
index 2036d21..d50bbe5 100644
--- a/fs/binfmt_flat.c
+++ b/fs/binfmt_flat.c
@@ -207,11 +207,12 @@
 
 	/* Read in first chunk of data and parse gzip header. */
 	fpos = offset;
-	ret = bprm->file->f_op->read(bprm->file, buf, LBUFSIZE, &fpos);
+	ret = kernel_read(bprm->file, offset, buf, LBUFSIZE);
 
 	strm.next_in = buf;
 	strm.avail_in = ret;
 	strm.total_in = 0;
+	fpos += ret;
 
 	retval = -ENOEXEC;
 
@@ -277,7 +278,7 @@
 	}
 
 	while ((ret = zlib_inflate(&strm, Z_NO_FLUSH)) == Z_OK) {
-		ret = bprm->file->f_op->read(bprm->file, buf, LBUFSIZE, &fpos);
+		ret = kernel_read(bprm->file, fpos, buf, LBUFSIZE);
 		if (ret <= 0)
 			break;
 		len -= ret;
@@ -285,6 +286,7 @@
 		strm.next_in = buf;
 		strm.avail_in = ret;
 		strm.total_in = 0;
+		fpos += ret;
 	}
 
 	if (ret < 0) {
@@ -428,6 +430,7 @@
 	unsigned long textpos = 0, datapos = 0, result;
 	unsigned long realdatastart = 0;
 	unsigned long text_len, data_len, bss_len, stack_len, flags;
+	unsigned long full_data;
 	unsigned long len, memp = 0;
 	unsigned long memp_size, extra, rlim;
 	unsigned long *reloc = 0, *rp;
@@ -451,6 +454,7 @@
 	relocs    = ntohl(hdr->reloc_count);
 	flags     = ntohl(hdr->flags);
 	rev       = ntohl(hdr->rev);
+	full_data = data_len + relocs * sizeof(unsigned long);
 
 	if (strncmp(hdr->magic, "bFLT", 4)) {
 		/*
@@ -577,12 +581,12 @@
 #ifdef CONFIG_BINFMT_ZFLAT
 		if (flags & FLAT_FLAG_GZDATA) {
 			result = decompress_exec(bprm, fpos, (char *) datapos, 
-						 data_len + (relocs * sizeof(unsigned long)), 0);
+						 full_data, 0);
 		} else
 #endif
 		{
-			result = bprm->file->f_op->read(bprm->file, (char *) datapos,
-					data_len + (relocs * sizeof(unsigned long)), &fpos);
+			result = read_code(bprm->file, datapos, fpos,
+					full_data);
 		}
 		if (IS_ERR_VALUE(result)) {
 			printk("Unable to read data+bss, errno %d\n", (int)-result);
@@ -627,30 +631,25 @@
 		if (flags & FLAT_FLAG_GZIP) {
 			result = decompress_exec(bprm, sizeof (struct flat_hdr),
 					 (((char *) textpos) + sizeof (struct flat_hdr)),
-					 (text_len + data_len + (relocs * sizeof(unsigned long))
+					 (text_len + full_data
 						  - sizeof (struct flat_hdr)),
 					 0);
 			memmove((void *) datapos, (void *) realdatastart,
-					data_len + (relocs * sizeof(unsigned long)));
+					full_data);
 		} else if (flags & FLAT_FLAG_GZDATA) {
-			fpos = 0;
-			result = bprm->file->f_op->read(bprm->file,
-					(char *) textpos, text_len, &fpos);
+			result = read_code(bprm->file, textpos, 0, text_len);
 			if (!IS_ERR_VALUE(result))
 				result = decompress_exec(bprm, text_len, (char *) datapos,
-						 data_len + (relocs * sizeof(unsigned long)), 0);
+						 full_data, 0);
 		}
 		else
 #endif
 		{
-			fpos = 0;
-			result = bprm->file->f_op->read(bprm->file,
-					(char *) textpos, text_len, &fpos);
-			if (!IS_ERR_VALUE(result)) {
-				fpos = ntohl(hdr->data_start);
-				result = bprm->file->f_op->read(bprm->file, (char *) datapos,
-					data_len + (relocs * sizeof(unsigned long)), &fpos);
-			}
+			result = read_code(bprm->file, textpos, 0, text_len);
+			if (!IS_ERR_VALUE(result))
+				result = read_code(bprm->file, datapos,
+						   ntohl(hdr->data_start),
+						   full_data);
 		}
 		if (IS_ERR_VALUE(result)) {
 			printk("Unable to read code+data+bss, errno %d\n",(int)-result);
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c
index ade03e6..bb8b7a0 100644
--- a/fs/btrfs/file.c
+++ b/fs/btrfs/file.c
@@ -1514,8 +1514,6 @@
 	size_t count, ocount;
 	bool sync = (file->f_flags & O_DSYNC) || IS_SYNC(file->f_mapping->host);
 
-	sb_start_write(inode->i_sb);
-
 	mutex_lock(&inode->i_mutex);
 
 	err = generic_segment_checks(iov, &nr_segs, &ocount, VERIFY_READ);
@@ -1617,7 +1615,6 @@
 	if (sync)
 		atomic_dec(&BTRFS_I(inode)->sync_writers);
 out:
-	sb_end_write(inode->i_sb);
 	current->backing_dev_info = NULL;
 	return num_written ? num_written : err;
 }
diff --git a/fs/cachefiles/rdwr.c b/fs/cachefiles/rdwr.c
index 4809922..317f9ee 100644
--- a/fs/cachefiles/rdwr.c
+++ b/fs/cachefiles/rdwr.c
@@ -962,12 +962,14 @@
 			}
 
 			data = kmap(page);
+			file_start_write(file);
 			old_fs = get_fs();
 			set_fs(KERNEL_DS);
 			ret = file->f_op->write(
 				file, (const void __user *) data, len, &pos);
 			set_fs(old_fs);
 			kunmap(page);
+			file_end_write(file);
 			if (ret != len)
 				ret = -EIO;
 		}
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index 7a0dd99..2d4a231 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -2520,8 +2520,6 @@
 
 	BUG_ON(iocb->ki_pos != pos);
 
-	sb_start_write(inode->i_sb);
-
 	/*
 	 * We need to hold the sem to be sure nobody modifies lock list
 	 * with a brlock that prevents writing.
@@ -2545,7 +2543,6 @@
 	}
 
 	up_read(&cinode->lock_sem);
-	sb_end_write(inode->i_sb);
 	return rc;
 }
 
diff --git a/fs/coda/file.c b/fs/coda/file.c
index fa4c100..380b798 100644
--- a/fs/coda/file.c
+++ b/fs/coda/file.c
@@ -79,6 +79,7 @@
 		return -EINVAL;
 
 	host_inode = file_inode(host_file);
+	file_start_write(host_file);
 	mutex_lock(&coda_inode->i_mutex);
 
 	ret = host_file->f_op->write(host_file, buf, count, ppos);
@@ -87,6 +88,7 @@
 	coda_inode->i_blocks = (coda_inode->i_size + 511) >> 9;
 	coda_inode->i_mtime = coda_inode->i_ctime = CURRENT_TIME_SEC;
 	mutex_unlock(&coda_inode->i_mutex);
+	file_end_write(host_file);
 
 	return ret;
 }
diff --git a/fs/compat.c b/fs/compat.c
index 5f83ffa..d0560c9 100644
--- a/fs/compat.c
+++ b/fs/compat.c
@@ -1068,190 +1068,6 @@
 }
 #endif /* ! __ARCH_OMIT_COMPAT_SYS_GETDENTS64 */
 
-static ssize_t compat_do_readv_writev(int type, struct file *file,
-			       const struct compat_iovec __user *uvector,
-			       unsigned long nr_segs, loff_t *pos)
-{
-	compat_ssize_t tot_len;
-	struct iovec iovstack[UIO_FASTIOV];
-	struct iovec *iov = iovstack;
-	ssize_t ret;
-	io_fn_t fn;
-	iov_fn_t fnv;
-
-	ret = -EINVAL;
-	if (!file->f_op)
-		goto out;
-
-	ret = compat_rw_copy_check_uvector(type, uvector, nr_segs,
-					       UIO_FASTIOV, iovstack, &iov);
-	if (ret <= 0)
-		goto out;
-
-	tot_len = ret;
-	ret = rw_verify_area(type, file, pos, tot_len);
-	if (ret < 0)
-		goto out;
-
-	fnv = NULL;
-	if (type == READ) {
-		fn = file->f_op->read;
-		fnv = file->f_op->aio_read;
-	} else {
-		fn = (io_fn_t)file->f_op->write;
-		fnv = file->f_op->aio_write;
-	}
-
-	if (fnv)
-		ret = do_sync_readv_writev(file, iov, nr_segs, tot_len,
-						pos, fnv);
-	else
-		ret = do_loop_readv_writev(file, iov, nr_segs, pos, fn);
-
-out:
-	if (iov != iovstack)
-		kfree(iov);
-	if ((ret + (type == READ)) > 0) {
-		if (type == READ)
-			fsnotify_access(file);
-		else
-			fsnotify_modify(file);
-	}
-	return ret;
-}
-
-static size_t compat_readv(struct file *file,
-			   const struct compat_iovec __user *vec,
-			   unsigned long vlen, loff_t *pos)
-{
-	ssize_t ret = -EBADF;
-
-	if (!(file->f_mode & FMODE_READ))
-		goto out;
-
-	ret = -EINVAL;
-	if (!file->f_op || (!file->f_op->aio_read && !file->f_op->read))
-		goto out;
-
-	ret = compat_do_readv_writev(READ, file, vec, vlen, pos);
-
-out:
-	if (ret > 0)
-		add_rchar(current, ret);
-	inc_syscr(current);
-	return ret;
-}
-
-asmlinkage ssize_t
-compat_sys_readv(unsigned long fd, const struct compat_iovec __user *vec,
-		 unsigned long vlen)
-{
-	struct fd f = fdget(fd);
-	ssize_t ret;
-	loff_t pos;
-
-	if (!f.file)
-		return -EBADF;
-	pos = f.file->f_pos;
-	ret = compat_readv(f.file, vec, vlen, &pos);
-	f.file->f_pos = pos;
-	fdput(f);
-	return ret;
-}
-
-asmlinkage ssize_t
-compat_sys_preadv64(unsigned long fd, const struct compat_iovec __user *vec,
-		    unsigned long vlen, loff_t pos)
-{
-	struct fd f;
-	ssize_t ret;
-
-	if (pos < 0)
-		return -EINVAL;
-	f = fdget(fd);
-	if (!f.file)
-		return -EBADF;
-	ret = -ESPIPE;
-	if (f.file->f_mode & FMODE_PREAD)
-		ret = compat_readv(f.file, vec, vlen, &pos);
-	fdput(f);
-	return ret;
-}
-
-asmlinkage ssize_t
-compat_sys_preadv(unsigned long fd, const struct compat_iovec __user *vec,
-		  unsigned long vlen, u32 pos_low, u32 pos_high)
-{
-	loff_t pos = ((loff_t)pos_high << 32) | pos_low;
-	return compat_sys_preadv64(fd, vec, vlen, pos);
-}
-
-static size_t compat_writev(struct file *file,
-			    const struct compat_iovec __user *vec,
-			    unsigned long vlen, loff_t *pos)
-{
-	ssize_t ret = -EBADF;
-
-	if (!(file->f_mode & FMODE_WRITE))
-		goto out;
-
-	ret = -EINVAL;
-	if (!file->f_op || (!file->f_op->aio_write && !file->f_op->write))
-		goto out;
-
-	ret = compat_do_readv_writev(WRITE, file, vec, vlen, pos);
-
-out:
-	if (ret > 0)
-		add_wchar(current, ret);
-	inc_syscw(current);
-	return ret;
-}
-
-asmlinkage ssize_t
-compat_sys_writev(unsigned long fd, const struct compat_iovec __user *vec,
-		  unsigned long vlen)
-{
-	struct fd f = fdget(fd);
-	ssize_t ret;
-	loff_t pos;
-
-	if (!f.file)
-		return -EBADF;
-	pos = f.file->f_pos;
-	ret = compat_writev(f.file, vec, vlen, &pos);
-	f.file->f_pos = pos;
-	fdput(f);
-	return ret;
-}
-
-asmlinkage ssize_t
-compat_sys_pwritev64(unsigned long fd, const struct compat_iovec __user *vec,
-		     unsigned long vlen, loff_t pos)
-{
-	struct fd f;
-	ssize_t ret;
-
-	if (pos < 0)
-		return -EINVAL;
-	f = fdget(fd);
-	if (!f.file)
-		return -EBADF;
-	ret = -ESPIPE;
-	if (f.file->f_mode & FMODE_PWRITE)
-		ret = compat_writev(f.file, vec, vlen, &pos);
-	fdput(f);
-	return ret;
-}
-
-asmlinkage ssize_t
-compat_sys_pwritev(unsigned long fd, const struct compat_iovec __user *vec,
-		   unsigned long vlen, u32 pos_low, u32 pos_high)
-{
-	loff_t pos = ((loff_t)pos_high << 32) | pos_low;
-	return compat_sys_pwritev64(fd, vec, vlen, pos);
-}
-
 /*
  * Exactly like fs/open.c:sys_open(), except that it doesn't set the
  * O_LARGEFILE flag.
diff --git a/fs/coredump.c b/fs/coredump.c
index ec306cc..a9abe31 100644
--- a/fs/coredump.c
+++ b/fs/coredump.c
@@ -432,9 +432,7 @@
 
 static void wait_for_dump_helpers(struct file *file)
 {
-	struct pipe_inode_info *pipe;
-
-	pipe = file_inode(file)->i_pipe;
+	struct pipe_inode_info *pipe = file->private_data;
 
 	pipe_lock(pipe);
 	pipe->readers++;
@@ -656,7 +654,9 @@
 		goto close_fail;
 	if (displaced)
 		put_files_struct(displaced);
+	file_start_write(cprm.file);
 	core_dumped = !dump_interrupted() && binfmt->core_dump(&cprm);
+	file_end_write(cprm.file);
 
 	if (ispipe && core_pipe_limit)
 		wait_for_dump_helpers(cprm.file);
diff --git a/fs/efivarfs/file.c b/fs/efivarfs/file.c
index ede07fc..bfb5315 100644
--- a/fs/efivarfs/file.c
+++ b/fs/efivarfs/file.c
@@ -9,6 +9,7 @@
 
 #include <linux/efi.h>
 #include <linux/fs.h>
+#include <linux/slab.h>
 
 #include "internal.h"
 
diff --git a/fs/efivarfs/inode.c b/fs/efivarfs/inode.c
index 640e289..7e787fb 100644
--- a/fs/efivarfs/inode.c
+++ b/fs/efivarfs/inode.c
@@ -10,6 +10,7 @@
 #include <linux/efi.h>
 #include <linux/fs.h>
 #include <linux/ctype.h>
+#include <linux/slab.h>
 
 #include "internal.h"
 
diff --git a/fs/efivarfs/super.c b/fs/efivarfs/super.c
index 525a2a1..141aee3 100644
--- a/fs/efivarfs/super.c
+++ b/fs/efivarfs/super.c
@@ -13,6 +13,8 @@
 #include <linux/module.h>
 #include <linux/pagemap.h>
 #include <linux/ucs2_string.h>
+#include <linux/slab.h>
+#include <linux/magic.h>
 
 #include "internal.h"
 
diff --git a/fs/exec.c b/fs/exec.c
index 963f510..6430195 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -802,6 +802,15 @@
 
 EXPORT_SYMBOL(kernel_read);
 
+ssize_t read_code(struct file *file, unsigned long addr, loff_t pos, size_t len)
+{
+	ssize_t res = file->f_op->read(file, (void __user *)addr, len, &pos);
+	if (res > 0)
+		flush_icache_range(addr, addr + len);
+	return res;
+}
+EXPORT_SYMBOL(read_code);
+
 static int exec_mmap(struct mm_struct *mm)
 {
 	struct task_struct *tsk;
diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
index a11ea4d..b1ed9e0 100644
--- a/fs/ext4/mballoc.c
+++ b/fs/ext4/mballoc.c
@@ -2260,7 +2260,7 @@
 
 static int ext4_mb_seq_groups_open(struct inode *inode, struct file *file)
 {
-	struct super_block *sb = PDE(inode)->data;
+	struct super_block *sb = PDE_DATA(inode);
 	int rc;
 
 	rc = seq_open(file, &ext4_mb_seq_groups_ops);
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index dbc7c09..24a146b 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -1806,7 +1806,7 @@
 
 static int options_open_fs(struct inode *inode, struct file *file)
 {
-	return single_open(file, options_seq_show, PDE(inode)->data);
+	return single_open(file, options_seq_show, PDE_DATA(inode));
 }
 
 static const struct file_operations ext4_seq_options_fops = {
diff --git a/fs/f2fs/acl.c b/fs/f2fs/acl.c
index 137af42..44abc2f 100644
--- a/fs/f2fs/acl.c
+++ b/fs/f2fs/acl.c
@@ -299,7 +299,7 @@
 	struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
 	struct posix_acl *acl;
 	int error;
-	mode_t mode = get_inode_mode(inode);
+	umode_t mode = get_inode_mode(inode);
 
 	if (!test_opt(sbi, POSIX_ACL))
 		return 0;
diff --git a/fs/f2fs/dir.c b/fs/f2fs/dir.c
index a1f3844..1be9487 100644
--- a/fs/f2fs/dir.c
+++ b/fs/f2fs/dir.c
@@ -60,7 +60,7 @@
 
 static void set_de_type(struct f2fs_dir_entry *de, struct inode *inode)
 {
-	mode_t mode = inode->i_mode;
+	umode_t mode = inode->i_mode;
 	de->file_type = f2fs_type_by_mode[(mode & S_IFMT) >> S_SHIFT];
 }
 
diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
index 958a46d..db62628 100644
--- a/fs/f2fs/file.c
+++ b/fs/f2fs/file.c
@@ -590,7 +590,7 @@
 	{
 		unsigned int oldflags;
 
-		ret = mnt_want_write(filp->f_path.mnt);
+		ret = mnt_want_write_file(filp);
 		if (ret)
 			return ret;
 
@@ -627,7 +627,7 @@
 		inode->i_ctime = CURRENT_TIME;
 		mark_inode_dirty(inode);
 out:
-		mnt_drop_write(filp->f_path.mnt);
+		mnt_drop_write_file(filp);
 		return ret;
 	}
 	default:
diff --git a/fs/fifo.c b/fs/fifo.c
deleted file mode 100644
index cf6f434..0000000
--- a/fs/fifo.c
+++ /dev/null
@@ -1,153 +0,0 @@
-/*
- *  linux/fs/fifo.c
- *
- *  written by Paul H. Hargrove
- *
- *  Fixes:
- *	10-06-1999, AV: fixed OOM handling in fifo_open(), moved
- *			initialization there, switched to external
- *			allocation of pipe_inode_info.
- */
-
-#include <linux/mm.h>
-#include <linux/fs.h>
-#include <linux/sched.h>
-#include <linux/pipe_fs_i.h>
-
-static int wait_for_partner(struct inode* inode, unsigned int *cnt)
-{
-	int cur = *cnt;	
-
-	while (cur == *cnt) {
-		pipe_wait(inode->i_pipe);
-		if (signal_pending(current))
-			break;
-	}
-	return cur == *cnt ? -ERESTARTSYS : 0;
-}
-
-static void wake_up_partner(struct inode* inode)
-{
-	wake_up_interruptible(&inode->i_pipe->wait);
-}
-
-static int fifo_open(struct inode *inode, struct file *filp)
-{
-	struct pipe_inode_info *pipe;
-	int ret;
-
-	mutex_lock(&inode->i_mutex);
-	pipe = inode->i_pipe;
-	if (!pipe) {
-		ret = -ENOMEM;
-		pipe = alloc_pipe_info(inode);
-		if (!pipe)
-			goto err_nocleanup;
-		inode->i_pipe = pipe;
-	}
-	filp->f_version = 0;
-
-	/* We can only do regular read/write on fifos */
-	filp->f_mode &= (FMODE_READ | FMODE_WRITE);
-
-	switch (filp->f_mode) {
-	case FMODE_READ:
-	/*
-	 *  O_RDONLY
-	 *  POSIX.1 says that O_NONBLOCK means return with the FIFO
-	 *  opened, even when there is no process writing the FIFO.
-	 */
-		filp->f_op = &read_pipefifo_fops;
-		pipe->r_counter++;
-		if (pipe->readers++ == 0)
-			wake_up_partner(inode);
-
-		if (!pipe->writers) {
-			if ((filp->f_flags & O_NONBLOCK)) {
-				/* suppress POLLHUP until we have
-				 * seen a writer */
-				filp->f_version = pipe->w_counter;
-			} else {
-				if (wait_for_partner(inode, &pipe->w_counter))
-					goto err_rd;
-			}
-		}
-		break;
-	
-	case FMODE_WRITE:
-	/*
-	 *  O_WRONLY
-	 *  POSIX.1 says that O_NONBLOCK means return -1 with
-	 *  errno=ENXIO when there is no process reading the FIFO.
-	 */
-		ret = -ENXIO;
-		if ((filp->f_flags & O_NONBLOCK) && !pipe->readers)
-			goto err;
-
-		filp->f_op = &write_pipefifo_fops;
-		pipe->w_counter++;
-		if (!pipe->writers++)
-			wake_up_partner(inode);
-
-		if (!pipe->readers) {
-			if (wait_for_partner(inode, &pipe->r_counter))
-				goto err_wr;
-		}
-		break;
-	
-	case FMODE_READ | FMODE_WRITE:
-	/*
-	 *  O_RDWR
-	 *  POSIX.1 leaves this case "undefined" when O_NONBLOCK is set.
-	 *  This implementation will NEVER block on a O_RDWR open, since
-	 *  the process can at least talk to itself.
-	 */
-		filp->f_op = &rdwr_pipefifo_fops;
-
-		pipe->readers++;
-		pipe->writers++;
-		pipe->r_counter++;
-		pipe->w_counter++;
-		if (pipe->readers == 1 || pipe->writers == 1)
-			wake_up_partner(inode);
-		break;
-
-	default:
-		ret = -EINVAL;
-		goto err;
-	}
-
-	/* Ok! */
-	mutex_unlock(&inode->i_mutex);
-	return 0;
-
-err_rd:
-	if (!--pipe->readers)
-		wake_up_interruptible(&pipe->wait);
-	ret = -ERESTARTSYS;
-	goto err;
-
-err_wr:
-	if (!--pipe->writers)
-		wake_up_interruptible(&pipe->wait);
-	ret = -ERESTARTSYS;
-	goto err;
-
-err:
-	if (!pipe->readers && !pipe->writers)
-		free_pipe_info(inode);
-
-err_nocleanup:
-	mutex_unlock(&inode->i_mutex);
-	return ret;
-}
-
-/*
- * Dummy default file-operations: the only thing this does
- * is contain the open that then fills in the correct operations
- * depending on the access mode of the file...
- */
-const struct file_operations def_fifo_fops = {
-	.open		= fifo_open,	/* will set read_ or write_pipefifo_fops */
-	.llseek		= noop_llseek,
-};
diff --git a/fs/file.c b/fs/file.c
index 3906d95..4a78f98 100644
--- a/fs/file.c
+++ b/fs/file.c
@@ -23,24 +23,10 @@
 #include <linux/rcupdate.h>
 #include <linux/workqueue.h>
 
-struct fdtable_defer {
-	spinlock_t lock;
-	struct work_struct wq;
-	struct fdtable *next;
-};
-
 int sysctl_nr_open __read_mostly = 1024*1024;
 int sysctl_nr_open_min = BITS_PER_LONG;
 int sysctl_nr_open_max = 1024 * 1024; /* raised later */
 
-/*
- * We use this list to defer free fdtables that have vmalloced
- * sets/arrays. By keeping a per-cpu list, we avoid having to embed
- * the work_struct in fdtable itself which avoids a 64 byte (i386) increase in
- * this per-task structure.
- */
-static DEFINE_PER_CPU(struct fdtable_defer, fdtable_defer_list);
-
 static void *alloc_fdmem(size_t size)
 {
 	/*
@@ -67,46 +53,9 @@
 	kfree(fdt);
 }
 
-static void free_fdtable_work(struct work_struct *work)
-{
-	struct fdtable_defer *f =
-		container_of(work, struct fdtable_defer, wq);
-	struct fdtable *fdt;
-
-	spin_lock_bh(&f->lock);
-	fdt = f->next;
-	f->next = NULL;
-	spin_unlock_bh(&f->lock);
-	while(fdt) {
-		struct fdtable *next = fdt->next;
-
-		__free_fdtable(fdt);
-		fdt = next;
-	}
-}
-
 static void free_fdtable_rcu(struct rcu_head *rcu)
 {
-	struct fdtable *fdt = container_of(rcu, struct fdtable, rcu);
-	struct fdtable_defer *fddef;
-
-	BUG_ON(!fdt);
-	BUG_ON(fdt->max_fds <= NR_OPEN_DEFAULT);
-
-	if (!is_vmalloc_addr(fdt->fd) && !is_vmalloc_addr(fdt->open_fds)) {
-		kfree(fdt->fd);
-		kfree(fdt->open_fds);
-		kfree(fdt);
-	} else {
-		fddef = &get_cpu_var(fdtable_defer_list);
-		spin_lock(&fddef->lock);
-		fdt->next = fddef->next;
-		fddef->next = fdt;
-		/* vmallocs are handled from the workqueue context */
-		schedule_work(&fddef->wq);
-		spin_unlock(&fddef->lock);
-		put_cpu_var(fdtable_defer_list);
-	}
+	__free_fdtable(container_of(rcu, struct fdtable, rcu));
 }
 
 /*
@@ -174,7 +123,6 @@
 	fdt->open_fds = data;
 	data += nr / BITS_PER_BYTE;
 	fdt->close_on_exec = data;
-	fdt->next = NULL;
 
 	return fdt;
 
@@ -221,7 +169,7 @@
 		/* Continue as planned */
 		copy_fdtable(new_fdt, cur_fdt);
 		rcu_assign_pointer(files->fdt, new_fdt);
-		if (cur_fdt->max_fds > NR_OPEN_DEFAULT)
+		if (cur_fdt != &files->fdtab)
 			call_rcu(&cur_fdt->rcu, free_fdtable_rcu);
 	} else {
 		/* Somebody else expanded, so undo our attempt */
@@ -316,7 +264,6 @@
 	new_fdt->close_on_exec = newf->close_on_exec_init;
 	new_fdt->open_fds = newf->open_fds_init;
 	new_fdt->fd = &newf->fd_array[0];
-	new_fdt->next = NULL;
 
 	spin_lock(&oldf->file_lock);
 	old_fdt = files_fdtable(oldf);
@@ -490,19 +437,8 @@
 	}
 }
 
-static void fdtable_defer_list_init(int cpu)
-{
-	struct fdtable_defer *fddef = &per_cpu(fdtable_defer_list, cpu);
-	spin_lock_init(&fddef->lock);
-	INIT_WORK(&fddef->wq, free_fdtable_work);
-	fddef->next = NULL;
-}
-
 void __init files_defer_init(void)
 {
-	int i;
-	for_each_possible_cpu(i)
-		fdtable_defer_list_init(i);
 	sysctl_nr_open_max = min((size_t)INT_MAX, ~(size_t)0/sizeof(void *)) &
 			     -BITS_PER_LONG;
 }
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c
index 11dfa0c..9bfd1a3 100644
--- a/fs/fuse/dev.c
+++ b/fs/fuse/dev.c
@@ -1319,7 +1319,7 @@
 		page_nr++;
 		ret += buf->len;
 
-		if (pipe->inode)
+		if (pipe->files)
 			do_wakeup = 1;
 	}
 
diff --git a/fs/fuse/file.c b/fs/fuse/file.c
index 34b80ba..d15c6f2 100644
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -971,7 +971,6 @@
 		return err;
 
 	count = ocount;
-	sb_start_write(inode->i_sb);
 	mutex_lock(&inode->i_mutex);
 
 	/* We can write back this queue in page reclaim */
@@ -1030,7 +1029,6 @@
 out:
 	current->backing_dev_info = NULL;
 	mutex_unlock(&inode->i_mutex);
-	sb_end_write(inode->i_sb);
 
 	return written ? written : err;
 }
diff --git a/fs/hpfs/file.c b/fs/hpfs/file.c
index 9f9dbec..3027f4d 100644
--- a/fs/hpfs/file.c
+++ b/fs/hpfs/file.c
@@ -131,6 +131,24 @@
 	return ret;
 }
 
+static int hpfs_write_end(struct file *file, struct address_space *mapping,
+			loff_t pos, unsigned len, unsigned copied,
+			struct page *pagep, void *fsdata)
+{
+	struct inode *inode = mapping->host;
+	int err;
+	err = generic_write_end(file, mapping, pos, len, copied, pagep, fsdata);
+	if (err < len)
+		hpfs_write_failed(mapping, pos + len);
+	if (!(err < 0)) {
+		/* make sure we write it on close, if not earlier */
+		hpfs_lock(inode->i_sb);
+		hpfs_i(inode)->i_dirty = 1;
+		hpfs_unlock(inode->i_sb);
+	}
+	return err;
+}
+
 static sector_t _hpfs_bmap(struct address_space *mapping, sector_t block)
 {
 	return generic_block_bmap(mapping,block,hpfs_get_block);
@@ -140,30 +158,16 @@
 	.readpage = hpfs_readpage,
 	.writepage = hpfs_writepage,
 	.write_begin = hpfs_write_begin,
-	.write_end = generic_write_end,
+	.write_end = hpfs_write_end,
 	.bmap = _hpfs_bmap
 };
 
-static ssize_t hpfs_file_write(struct file *file, const char __user *buf,
-			size_t count, loff_t *ppos)
-{
-	ssize_t retval;
-
-	retval = do_sync_write(file, buf, count, ppos);
-	if (retval > 0) {
-		hpfs_lock(file->f_path.dentry->d_sb);
-		hpfs_i(file_inode(file))->i_dirty = 1;
-		hpfs_unlock(file->f_path.dentry->d_sb);
-	}
-	return retval;
-}
-
 const struct file_operations hpfs_file_ops =
 {
 	.llseek		= generic_file_llseek,
 	.read		= do_sync_read,
 	.aio_read	= generic_file_aio_read,
-	.write		= hpfs_file_write,
+	.write		= do_sync_write,
 	.aio_write	= generic_file_aio_write,
 	.mmap		= generic_file_mmap,
 	.release	= hpfs_file_release,
diff --git a/fs/hppfs/hppfs.c b/fs/hppfs/hppfs.c
index 126d3c2..cd3e389 100644
--- a/fs/hppfs/hppfs.c
+++ b/fs/hppfs/hppfs.c
@@ -436,7 +436,6 @@
 	path.mnt = inode->i_sb->s_fs_info;
 	path.dentry = HPPFS_I(inode)->proc_dentry;
 
-	/* XXX This isn't closed anywhere */
 	data->proc_file = dentry_open(&path, file_mode(file->f_mode), cred);
 	err = PTR_ERR(data->proc_file);
 	if (IS_ERR(data->proc_file))
@@ -523,12 +522,23 @@
 	return default_llseek(file, off, where);
 }
 
+static int hppfs_release(struct inode *inode, struct file *file)
+{
+	struct hppfs_private *data = file->private_data;
+	struct file *proc_file = data->proc_file;
+	if (proc_file)
+		fput(proc_file);
+	kfree(data);
+	return 0;
+}
+
 static const struct file_operations hppfs_file_fops = {
 	.owner		= NULL,
 	.llseek		= hppfs_llseek,
 	.read		= hppfs_read,
 	.write		= hppfs_write,
 	.open		= hppfs_open,
+	.release	= hppfs_release,
 };
 
 struct hppfs_dirent {
@@ -570,18 +580,12 @@
 	return err;
 }
 
-static int hppfs_fsync(struct file *file, loff_t start, loff_t end,
-		       int datasync)
-{
-	return filemap_write_and_wait_range(file->f_mapping, start, end);
-}
-
 static const struct file_operations hppfs_dir_fops = {
 	.owner		= NULL,
 	.readdir	= hppfs_readdir,
 	.open		= hppfs_dir_open,
-	.fsync		= hppfs_fsync,
 	.llseek		= default_llseek,
+	.release	= hppfs_release,
 };
 
 static int hppfs_statfs(struct dentry *dentry, struct kstatfs *sf)
diff --git a/fs/inode.c b/fs/inode.c
index a898b3d..00d5fc3 100644
--- a/fs/inode.c
+++ b/fs/inode.c
@@ -1803,7 +1803,7 @@
 		inode->i_fop = &def_blk_fops;
 		inode->i_rdev = rdev;
 	} else if (S_ISFIFO(mode))
-		inode->i_fop = &def_fifo_fops;
+		inode->i_fop = &pipefifo_fops;
 	else if (S_ISSOCK(mode))
 		inode->i_fop = &bad_sock_fops;
 	else
diff --git a/fs/internal.h b/fs/internal.h
index 4be7823..eaa75f7 100644
--- a/fs/internal.h
+++ b/fs/internal.h
@@ -130,3 +130,8 @@
  * read_write.c
  */
 extern ssize_t __kernel_write(struct file *, const char *, size_t, loff_t *);
+
+/*
+ * pipe.c
+ */
+extern const struct file_operations pipefifo_fops;
diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c
index f6c5ba02..9545757 100644
--- a/fs/jbd2/journal.c
+++ b/fs/jbd2/journal.c
@@ -979,7 +979,7 @@
 
 static int jbd2_seq_info_open(struct inode *inode, struct file *file)
 {
-	journal_t *journal = PDE(inode)->data;
+	journal_t *journal = PDE_DATA(inode);
 	struct jbd2_stats_proc_session *s;
 	int rc, size;
 
diff --git a/fs/mount.h b/fs/mount.h
index cd50079..64a8581 100644
--- a/fs/mount.h
+++ b/fs/mount.h
@@ -18,6 +18,12 @@
 	int mnt_writers;
 };
 
+struct mountpoint {
+	struct list_head m_hash;
+	struct dentry *m_dentry;
+	int m_count;
+};
+
 struct mount {
 	struct list_head mnt_hash;
 	struct mount *mnt_parent;
@@ -40,6 +46,7 @@
 	struct list_head mnt_slave;	/* slave list entry */
 	struct mount *mnt_master;	/* slave is on master->mnt_slave_list */
 	struct mnt_namespace *mnt_ns;	/* containing namespace */
+	struct mountpoint *mnt_mp;	/* where is it mounted */
 #ifdef CONFIG_FSNOTIFY
 	struct hlist_head mnt_fsnotify_marks;
 	__u32 mnt_fsnotify_mask;
diff --git a/fs/namespace.c b/fs/namespace.c
index 341d3f5..b4f96a5 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -21,7 +21,8 @@
 #include <linux/fs_struct.h>	/* get_fs_root et.al. */
 #include <linux/fsnotify.h>	/* fsnotify_vfsmount_delete */
 #include <linux/uaccess.h>
-#include <linux/proc_fs.h>
+#include <linux/proc_ns.h>
+#include <linux/magic.h>
 #include "pnode.h"
 #include "internal.h"
 
@@ -36,6 +37,7 @@
 static int mnt_group_start = 1;
 
 static struct list_head *mount_hashtable __read_mostly;
+static struct list_head *mountpoint_hashtable __read_mostly;
 static struct kmem_cache *mnt_cache __read_mostly;
 static struct rw_semaphore namespace_sem;
 
@@ -605,6 +607,51 @@
 	}
 }
 
+static struct mountpoint *new_mountpoint(struct dentry *dentry)
+{
+	struct list_head *chain = mountpoint_hashtable + hash(NULL, dentry);
+	struct mountpoint *mp;
+
+	list_for_each_entry(mp, chain, m_hash) {
+		if (mp->m_dentry == dentry) {
+			/* might be worth a WARN_ON() */
+			if (d_unlinked(dentry))
+				return ERR_PTR(-ENOENT);
+			mp->m_count++;
+			return mp;
+		}
+	}
+
+	mp = kmalloc(sizeof(struct mountpoint), GFP_KERNEL);
+	if (!mp)
+		return ERR_PTR(-ENOMEM);
+
+	spin_lock(&dentry->d_lock);
+	if (d_unlinked(dentry)) {
+		spin_unlock(&dentry->d_lock);
+		kfree(mp);
+		return ERR_PTR(-ENOENT);
+	}
+	dentry->d_flags |= DCACHE_MOUNTED;
+	spin_unlock(&dentry->d_lock);
+	mp->m_dentry = dentry;
+	mp->m_count = 1;
+	list_add(&mp->m_hash, chain);
+	return mp;
+}
+
+static void put_mountpoint(struct mountpoint *mp)
+{
+	if (!--mp->m_count) {
+		struct dentry *dentry = mp->m_dentry;
+		spin_lock(&dentry->d_lock);
+		dentry->d_flags &= ~DCACHE_MOUNTED;
+		spin_unlock(&dentry->d_lock);
+		list_del(&mp->m_hash);
+		kfree(mp);
+	}
+}
+
 static inline int check_mnt(struct mount *mnt)
 {
 	return mnt->mnt_ns == current->nsproxy->mnt_ns;
@@ -633,27 +680,6 @@
 }
 
 /*
- * Clear dentry's mounted state if it has no remaining mounts.
- * vfsmount_lock must be held for write.
- */
-static void dentry_reset_mounted(struct dentry *dentry)
-{
-	unsigned u;
-
-	for (u = 0; u < HASH_SIZE; u++) {
-		struct mount *p;
-
-		list_for_each_entry(p, &mount_hashtable[u], mnt_hash) {
-			if (p->mnt_mountpoint == dentry)
-				return;
-		}
-	}
-	spin_lock(&dentry->d_lock);
-	dentry->d_flags &= ~DCACHE_MOUNTED;
-	spin_unlock(&dentry->d_lock);
-}
-
-/*
  * vfsmount lock must be held for write
  */
 static void detach_mnt(struct mount *mnt, struct path *old_path)
@@ -664,32 +690,35 @@
 	mnt->mnt_mountpoint = mnt->mnt.mnt_root;
 	list_del_init(&mnt->mnt_child);
 	list_del_init(&mnt->mnt_hash);
-	dentry_reset_mounted(old_path->dentry);
+	put_mountpoint(mnt->mnt_mp);
+	mnt->mnt_mp = NULL;
 }
 
 /*
  * vfsmount lock must be held for write
  */
-void mnt_set_mountpoint(struct mount *mnt, struct dentry *dentry,
+void mnt_set_mountpoint(struct mount *mnt,
+			struct mountpoint *mp,
 			struct mount *child_mnt)
 {
+	mp->m_count++;
 	mnt_add_count(mnt, 1);	/* essentially, that's mntget */
-	child_mnt->mnt_mountpoint = dget(dentry);
+	child_mnt->mnt_mountpoint = dget(mp->m_dentry);
 	child_mnt->mnt_parent = mnt;
-	spin_lock(&dentry->d_lock);
-	dentry->d_flags |= DCACHE_MOUNTED;
-	spin_unlock(&dentry->d_lock);
+	child_mnt->mnt_mp = mp;
 }
 
 /*
  * vfsmount lock must be held for write
  */
-static void attach_mnt(struct mount *mnt, struct path *path)
+static void attach_mnt(struct mount *mnt,
+			struct mount *parent,
+			struct mountpoint *mp)
 {
-	mnt_set_mountpoint(real_mount(path->mnt), path->dentry, mnt);
+	mnt_set_mountpoint(parent, mp, mnt);
 	list_add_tail(&mnt->mnt_hash, mount_hashtable +
-			hash(path->mnt, path->dentry));
-	list_add_tail(&mnt->mnt_child, &real_mount(path->mnt)->mnt_mounts);
+			hash(&parent->mnt, mp->m_dentry));
+	list_add_tail(&mnt->mnt_child, &parent->mnt_mounts);
 }
 
 /*
@@ -1095,11 +1124,23 @@
 
 EXPORT_SYMBOL(may_umount);
 
-void release_mounts(struct list_head *head)
+static LIST_HEAD(unmounted);	/* protected by namespace_sem */
+
+static void namespace_unlock(void)
 {
 	struct mount *mnt;
-	while (!list_empty(head)) {
-		mnt = list_first_entry(head, struct mount, mnt_hash);
+	LIST_HEAD(head);
+
+	if (likely(list_empty(&unmounted))) {
+		up_write(&namespace_sem);
+		return;
+	}
+
+	list_splice_init(&unmounted, &head);
+	up_write(&namespace_sem);
+
+	while (!list_empty(&head)) {
+		mnt = list_first_entry(&head, struct mount, mnt_hash);
 		list_del_init(&mnt->mnt_hash);
 		if (mnt_has_parent(mnt)) {
 			struct dentry *dentry;
@@ -1119,11 +1160,16 @@
 	}
 }
 
+static inline void namespace_lock(void)
+{
+	down_write(&namespace_sem);
+}
+
 /*
  * vfsmount lock must be held for write
  * namespace_sem must be held for write
  */
-void umount_tree(struct mount *mnt, int propagate, struct list_head *kill)
+void umount_tree(struct mount *mnt, int propagate)
 {
 	LIST_HEAD(tmp_list);
 	struct mount *p;
@@ -1142,20 +1188,20 @@
 		list_del_init(&p->mnt_child);
 		if (mnt_has_parent(p)) {
 			p->mnt_parent->mnt_ghosts++;
-			dentry_reset_mounted(p->mnt_mountpoint);
+			put_mountpoint(p->mnt_mp);
+			p->mnt_mp = NULL;
 		}
 		change_mnt_propagation(p, MS_PRIVATE);
 	}
-	list_splice(&tmp_list, kill);
+	list_splice(&tmp_list, &unmounted);
 }
 
-static void shrink_submounts(struct mount *mnt, struct list_head *umounts);
+static void shrink_submounts(struct mount *mnt);
 
 static int do_umount(struct mount *mnt, int flags)
 {
 	struct super_block *sb = mnt->mnt.mnt_sb;
 	int retval;
-	LIST_HEAD(umount_list);
 
 	retval = security_sb_umount(&mnt->mnt, flags);
 	if (retval)
@@ -1222,22 +1268,21 @@
 		return retval;
 	}
 
-	down_write(&namespace_sem);
+	namespace_lock();
 	br_write_lock(&vfsmount_lock);
 	event++;
 
 	if (!(flags & MNT_DETACH))
-		shrink_submounts(mnt, &umount_list);
+		shrink_submounts(mnt);
 
 	retval = -EBUSY;
 	if (flags & MNT_DETACH || !propagate_mount_busy(mnt, 2)) {
 		if (!list_empty(&mnt->mnt_list))
-			umount_tree(mnt, 1, &umount_list);
+			umount_tree(mnt, 1);
 		retval = 0;
 	}
 	br_write_unlock(&vfsmount_lock);
-	up_write(&namespace_sem);
-	release_mounts(&umount_list);
+	namespace_unlock();
 	return retval;
 }
 
@@ -1310,13 +1355,13 @@
 	 * mount namespace loop?
 	 */
 	struct inode *inode = path->dentry->d_inode;
-	struct proc_inode *ei;
+	struct proc_ns *ei;
 	struct mnt_namespace *mnt_ns;
 
 	if (!proc_ns_inode(inode))
 		return false;
 
-	ei = PROC_I(inode);
+	ei = get_proc_ns(inode);
 	if (ei->ns_ops != &mntns_operations)
 		return false;
 
@@ -1327,8 +1372,7 @@
 struct mount *copy_tree(struct mount *mnt, struct dentry *dentry,
 					int flag)
 {
-	struct mount *res, *p, *q, *r;
-	struct path path;
+	struct mount *res, *p, *q, *r, *parent;
 
 	if (!(flag & CL_COPY_ALL) && IS_MNT_UNBINDABLE(mnt))
 		return ERR_PTR(-EINVAL);
@@ -1355,25 +1399,22 @@
 				q = q->mnt_parent;
 			}
 			p = s;
-			path.mnt = &q->mnt;
-			path.dentry = p->mnt_mountpoint;
+			parent = q;
 			q = clone_mnt(p, p->mnt.mnt_root, flag);
 			if (IS_ERR(q))
 				goto out;
 			br_write_lock(&vfsmount_lock);
 			list_add_tail(&q->mnt_list, &res->mnt_list);
-			attach_mnt(q, &path);
+			attach_mnt(q, parent, p->mnt_mp);
 			br_write_unlock(&vfsmount_lock);
 		}
 	}
 	return res;
 out:
 	if (res) {
-		LIST_HEAD(umount_list);
 		br_write_lock(&vfsmount_lock);
-		umount_tree(res, 0, &umount_list);
+		umount_tree(res, 0);
 		br_write_unlock(&vfsmount_lock);
-		release_mounts(&umount_list);
 	}
 	return q;
 }
@@ -1383,10 +1424,10 @@
 struct vfsmount *collect_mounts(struct path *path)
 {
 	struct mount *tree;
-	down_write(&namespace_sem);
+	namespace_lock();
 	tree = copy_tree(real_mount(path->mnt), path->dentry,
 			 CL_COPY_ALL | CL_PRIVATE);
-	up_write(&namespace_sem);
+	namespace_unlock();
 	if (IS_ERR(tree))
 		return NULL;
 	return &tree->mnt;
@@ -1394,13 +1435,11 @@
 
 void drop_collected_mounts(struct vfsmount *mnt)
 {
-	LIST_HEAD(umount_list);
-	down_write(&namespace_sem);
+	namespace_lock();
 	br_write_lock(&vfsmount_lock);
-	umount_tree(real_mount(mnt), 0, &umount_list);
+	umount_tree(real_mount(mnt), 0);
 	br_write_unlock(&vfsmount_lock);
-	up_write(&namespace_sem);
-	release_mounts(&umount_list);
+	namespace_unlock();
 }
 
 int iterate_mounts(int (*f)(struct vfsmount *, void *), void *arg,
@@ -1509,11 +1548,11 @@
  * in allocations.
  */
 static int attach_recursive_mnt(struct mount *source_mnt,
-			struct path *path, struct path *parent_path)
+			struct mount *dest_mnt,
+			struct mountpoint *dest_mp,
+			struct path *parent_path)
 {
 	LIST_HEAD(tree_list);
-	struct mount *dest_mnt = real_mount(path->mnt);
-	struct dentry *dest_dentry = path->dentry;
 	struct mount *child, *p;
 	int err;
 
@@ -1522,7 +1561,7 @@
 		if (err)
 			goto out;
 	}
-	err = propagate_mnt(dest_mnt, dest_dentry, source_mnt, &tree_list);
+	err = propagate_mnt(dest_mnt, dest_mp, source_mnt, &tree_list);
 	if (err)
 		goto out_cleanup_ids;
 
@@ -1534,10 +1573,10 @@
 	}
 	if (parent_path) {
 		detach_mnt(source_mnt, parent_path);
-		attach_mnt(source_mnt, path);
+		attach_mnt(source_mnt, dest_mnt, dest_mp);
 		touch_mnt_namespace(source_mnt->mnt_ns);
 	} else {
-		mnt_set_mountpoint(dest_mnt, dest_dentry, source_mnt);
+		mnt_set_mountpoint(dest_mnt, dest_mp, source_mnt);
 		commit_tree(source_mnt);
 	}
 
@@ -1556,46 +1595,53 @@
 	return err;
 }
 
-static int lock_mount(struct path *path)
+static struct mountpoint *lock_mount(struct path *path)
 {
 	struct vfsmount *mnt;
+	struct dentry *dentry = path->dentry;
 retry:
-	mutex_lock(&path->dentry->d_inode->i_mutex);
-	if (unlikely(cant_mount(path->dentry))) {
-		mutex_unlock(&path->dentry->d_inode->i_mutex);
-		return -ENOENT;
+	mutex_lock(&dentry->d_inode->i_mutex);
+	if (unlikely(cant_mount(dentry))) {
+		mutex_unlock(&dentry->d_inode->i_mutex);
+		return ERR_PTR(-ENOENT);
 	}
-	down_write(&namespace_sem);
+	namespace_lock();
 	mnt = lookup_mnt(path);
-	if (likely(!mnt))
-		return 0;
-	up_write(&namespace_sem);
+	if (likely(!mnt)) {
+		struct mountpoint *mp = new_mountpoint(dentry);
+		if (IS_ERR(mp)) {
+			namespace_unlock();
+			mutex_unlock(&dentry->d_inode->i_mutex);
+			return mp;
+		}
+		return mp;
+	}
+	namespace_unlock();
 	mutex_unlock(&path->dentry->d_inode->i_mutex);
 	path_put(path);
 	path->mnt = mnt;
-	path->dentry = dget(mnt->mnt_root);
+	dentry = path->dentry = dget(mnt->mnt_root);
 	goto retry;
 }
 
-static void unlock_mount(struct path *path)
+static void unlock_mount(struct mountpoint *where)
 {
-	up_write(&namespace_sem);
-	mutex_unlock(&path->dentry->d_inode->i_mutex);
+	struct dentry *dentry = where->m_dentry;
+	put_mountpoint(where);
+	namespace_unlock();
+	mutex_unlock(&dentry->d_inode->i_mutex);
 }
 
-static int graft_tree(struct mount *mnt, struct path *path)
+static int graft_tree(struct mount *mnt, struct mount *p, struct mountpoint *mp)
 {
 	if (mnt->mnt.mnt_sb->s_flags & MS_NOUSER)
 		return -EINVAL;
 
-	if (S_ISDIR(path->dentry->d_inode->i_mode) !=
+	if (S_ISDIR(mp->m_dentry->d_inode->i_mode) !=
 	      S_ISDIR(mnt->mnt.mnt_root->d_inode->i_mode))
 		return -ENOTDIR;
 
-	if (d_unlinked(path->dentry))
-		return -ENOENT;
-
-	return attach_recursive_mnt(mnt, path, NULL);
+	return attach_recursive_mnt(mnt, p, mp, NULL);
 }
 
 /*
@@ -1633,7 +1679,7 @@
 	if (!type)
 		return -EINVAL;
 
-	down_write(&namespace_sem);
+	namespace_lock();
 	if (type == MS_SHARED) {
 		err = invent_group_ids(mnt, recurse);
 		if (err)
@@ -1646,7 +1692,7 @@
 	br_write_unlock(&vfsmount_lock);
 
  out_unlock:
-	up_write(&namespace_sem);
+	namespace_unlock();
 	return err;
 }
 
@@ -1656,9 +1702,9 @@
 static int do_loopback(struct path *path, const char *old_name,
 				int recurse)
 {
-	LIST_HEAD(umount_list);
 	struct path old_path;
-	struct mount *mnt = NULL, *old;
+	struct mount *mnt = NULL, *old, *parent;
+	struct mountpoint *mp;
 	int err;
 	if (!old_name || !*old_name)
 		return -EINVAL;
@@ -1670,17 +1716,19 @@
 	if (mnt_ns_loop(&old_path))
 		goto out; 
 
-	err = lock_mount(path);
-	if (err)
+	mp = lock_mount(path);
+	err = PTR_ERR(mp);
+	if (IS_ERR(mp))
 		goto out;
 
 	old = real_mount(old_path.mnt);
+	parent = real_mount(path->mnt);
 
 	err = -EINVAL;
 	if (IS_MNT_UNBINDABLE(old))
 		goto out2;
 
-	if (!check_mnt(real_mount(path->mnt)) || !check_mnt(old))
+	if (!check_mnt(parent) || !check_mnt(old))
 		goto out2;
 
 	if (recurse)
@@ -1693,15 +1741,14 @@
 		goto out2;
 	}
 
-	err = graft_tree(mnt, path);
+	err = graft_tree(mnt, parent, mp);
 	if (err) {
 		br_write_lock(&vfsmount_lock);
-		umount_tree(mnt, 0, &umount_list);
+		umount_tree(mnt, 0);
 		br_write_unlock(&vfsmount_lock);
 	}
 out2:
-	unlock_mount(path);
-	release_mounts(&umount_list);
+	unlock_mount(mp);
 out:
 	path_put(&old_path);
 	return err;
@@ -1786,6 +1833,7 @@
 	struct path old_path, parent_path;
 	struct mount *p;
 	struct mount *old;
+	struct mountpoint *mp;
 	int err;
 	if (!old_name || !*old_name)
 		return -EINVAL;
@@ -1793,8 +1841,9 @@
 	if (err)
 		return err;
 
-	err = lock_mount(path);
-	if (err < 0)
+	mp = lock_mount(path);
+	err = PTR_ERR(mp);
+	if (IS_ERR(mp))
 		goto out;
 
 	old = real_mount(old_path.mnt);
@@ -1804,9 +1853,6 @@
 	if (!check_mnt(p) || !check_mnt(old))
 		goto out1;
 
-	if (d_unlinked(path->dentry))
-		goto out1;
-
 	err = -EINVAL;
 	if (old_path.dentry != old_path.mnt->mnt_root)
 		goto out1;
@@ -1833,7 +1879,7 @@
 		if (p == old)
 			goto out1;
 
-	err = attach_recursive_mnt(old, path, &parent_path);
+	err = attach_recursive_mnt(old, real_mount(path->mnt), mp, &parent_path);
 	if (err)
 		goto out1;
 
@@ -1841,7 +1887,7 @@
 	 * automatically */
 	list_del_init(&old->mnt_expire);
 out1:
-	unlock_mount(path);
+	unlock_mount(mp);
 out:
 	if (!err)
 		path_put(&parent_path);
@@ -1877,21 +1923,24 @@
  */
 static int do_add_mount(struct mount *newmnt, struct path *path, int mnt_flags)
 {
+	struct mountpoint *mp;
+	struct mount *parent;
 	int err;
 
 	mnt_flags &= ~(MNT_SHARED | MNT_WRITE_HOLD | MNT_INTERNAL);
 
-	err = lock_mount(path);
-	if (err)
-		return err;
+	mp = lock_mount(path);
+	if (IS_ERR(mp))
+		return PTR_ERR(mp);
 
+	parent = real_mount(path->mnt);
 	err = -EINVAL;
-	if (unlikely(!check_mnt(real_mount(path->mnt)))) {
+	if (unlikely(!check_mnt(parent))) {
 		/* that's acceptable only for automounts done in private ns */
 		if (!(mnt_flags & MNT_SHRINKABLE))
 			goto unlock;
 		/* ... and for those we'd better have mountpoint still alive */
-		if (!real_mount(path->mnt)->mnt_ns)
+		if (!parent->mnt_ns)
 			goto unlock;
 	}
 
@@ -1906,10 +1955,10 @@
 		goto unlock;
 
 	newmnt->mnt.mnt_flags = mnt_flags;
-	err = graft_tree(newmnt, path);
+	err = graft_tree(newmnt, parent, mp);
 
 unlock:
-	unlock_mount(path);
+	unlock_mount(mp);
 	return err;
 }
 
@@ -1982,11 +2031,11 @@
 fail:
 	/* remove m from any expiration list it may be on */
 	if (!list_empty(&mnt->mnt_expire)) {
-		down_write(&namespace_sem);
+		namespace_lock();
 		br_write_lock(&vfsmount_lock);
 		list_del_init(&mnt->mnt_expire);
 		br_write_unlock(&vfsmount_lock);
-		up_write(&namespace_sem);
+		namespace_unlock();
 	}
 	mntput(m);
 	mntput(m);
@@ -2000,13 +2049,13 @@
  */
 void mnt_set_expiry(struct vfsmount *mnt, struct list_head *expiry_list)
 {
-	down_write(&namespace_sem);
+	namespace_lock();
 	br_write_lock(&vfsmount_lock);
 
 	list_add_tail(&real_mount(mnt)->mnt_expire, expiry_list);
 
 	br_write_unlock(&vfsmount_lock);
-	up_write(&namespace_sem);
+	namespace_unlock();
 }
 EXPORT_SYMBOL(mnt_set_expiry);
 
@@ -2019,12 +2068,11 @@
 {
 	struct mount *mnt, *next;
 	LIST_HEAD(graveyard);
-	LIST_HEAD(umounts);
 
 	if (list_empty(mounts))
 		return;
 
-	down_write(&namespace_sem);
+	namespace_lock();
 	br_write_lock(&vfsmount_lock);
 
 	/* extract from the expiration list every vfsmount that matches the
@@ -2042,12 +2090,10 @@
 	while (!list_empty(&graveyard)) {
 		mnt = list_first_entry(&graveyard, struct mount, mnt_expire);
 		touch_mnt_namespace(mnt->mnt_ns);
-		umount_tree(mnt, 1, &umounts);
+		umount_tree(mnt, 1);
 	}
 	br_write_unlock(&vfsmount_lock);
-	up_write(&namespace_sem);
-
-	release_mounts(&umounts);
+	namespace_unlock();
 }
 
 EXPORT_SYMBOL_GPL(mark_mounts_for_expiry);
@@ -2104,7 +2150,7 @@
  *
  * vfsmount_lock must be held for write
  */
-static void shrink_submounts(struct mount *mnt, struct list_head *umounts)
+static void shrink_submounts(struct mount *mnt)
 {
 	LIST_HEAD(graveyard);
 	struct mount *m;
@@ -2115,7 +2161,7 @@
 			m = list_first_entry(&graveyard, struct mount,
 						mnt_expire);
 			touch_mnt_namespace(m->mnt_ns);
-			umount_tree(m, 1, umounts);
+			umount_tree(m, 1);
 		}
 	}
 }
@@ -2342,14 +2388,14 @@
 	if (IS_ERR(new_ns))
 		return new_ns;
 
-	down_write(&namespace_sem);
+	namespace_lock();
 	/* First pass: copy the tree topology */
 	copy_flags = CL_COPY_ALL | CL_EXPIRE;
 	if (user_ns != mnt_ns->user_ns)
 		copy_flags |= CL_SHARED_TO_SLAVE | CL_UNPRIVILEGED;
 	new = copy_tree(old, old->mnt.mnt_root, copy_flags);
 	if (IS_ERR(new)) {
-		up_write(&namespace_sem);
+		namespace_unlock();
 		free_mnt_ns(new_ns);
 		return ERR_CAST(new);
 	}
@@ -2380,7 +2426,7 @@
 		p = next_mnt(p, old);
 		q = next_mnt(q, new);
 	}
-	up_write(&namespace_sem);
+	namespace_unlock();
 
 	if (rootmnt)
 		mntput(rootmnt);
@@ -2550,7 +2596,8 @@
 		const char __user *, put_old)
 {
 	struct path new, old, parent_path, root_parent, root;
-	struct mount *new_mnt, *root_mnt;
+	struct mount *new_mnt, *root_mnt, *old_mnt;
+	struct mountpoint *old_mp, *root_mp;
 	int error;
 
 	if (!may_mount())
@@ -2569,14 +2616,16 @@
 		goto out2;
 
 	get_fs_root(current->fs, &root);
-	error = lock_mount(&old);
-	if (error)
+	old_mp = lock_mount(&old);
+	error = PTR_ERR(old_mp);
+	if (IS_ERR(old_mp))
 		goto out3;
 
 	error = -EINVAL;
 	new_mnt = real_mount(new.mnt);
 	root_mnt = real_mount(root.mnt);
-	if (IS_MNT_SHARED(real_mount(old.mnt)) ||
+	old_mnt = real_mount(old.mnt);
+	if (IS_MNT_SHARED(old_mnt) ||
 		IS_MNT_SHARED(new_mnt->mnt_parent) ||
 		IS_MNT_SHARED(root_mnt->mnt_parent))
 		goto out4;
@@ -2585,37 +2634,37 @@
 	error = -ENOENT;
 	if (d_unlinked(new.dentry))
 		goto out4;
-	if (d_unlinked(old.dentry))
-		goto out4;
 	error = -EBUSY;
-	if (new.mnt == root.mnt ||
-	    old.mnt == root.mnt)
+	if (new_mnt == root_mnt || old_mnt == root_mnt)
 		goto out4; /* loop, on the same file system  */
 	error = -EINVAL;
 	if (root.mnt->mnt_root != root.dentry)
 		goto out4; /* not a mountpoint */
 	if (!mnt_has_parent(root_mnt))
 		goto out4; /* not attached */
+	root_mp = root_mnt->mnt_mp;
 	if (new.mnt->mnt_root != new.dentry)
 		goto out4; /* not a mountpoint */
 	if (!mnt_has_parent(new_mnt))
 		goto out4; /* not attached */
 	/* make sure we can reach put_old from new_root */
-	if (!is_path_reachable(real_mount(old.mnt), old.dentry, &new))
+	if (!is_path_reachable(old_mnt, old.dentry, &new))
 		goto out4;
+	root_mp->m_count++; /* pin it so it won't go away */
 	br_write_lock(&vfsmount_lock);
 	detach_mnt(new_mnt, &parent_path);
 	detach_mnt(root_mnt, &root_parent);
 	/* mount old root on put_old */
-	attach_mnt(root_mnt, &old);
+	attach_mnt(root_mnt, old_mnt, old_mp);
 	/* mount new_root on / */
-	attach_mnt(new_mnt, &root_parent);
+	attach_mnt(new_mnt, real_mount(root_parent.mnt), root_mp);
 	touch_mnt_namespace(current->nsproxy->mnt_ns);
 	br_write_unlock(&vfsmount_lock);
 	chroot_fs_refs(&root, &new);
+	put_mountpoint(root_mp);
 	error = 0;
 out4:
-	unlock_mount(&old);
+	unlock_mount(old_mp);
 	if (!error) {
 		path_put(&root_parent);
 		path_put(&parent_path);
@@ -2670,14 +2719,17 @@
 			0, SLAB_HWCACHE_ALIGN | SLAB_PANIC, NULL);
 
 	mount_hashtable = (struct list_head *)__get_free_page(GFP_ATOMIC);
+	mountpoint_hashtable = (struct list_head *)__get_free_page(GFP_ATOMIC);
 
-	if (!mount_hashtable)
+	if (!mount_hashtable || !mountpoint_hashtable)
 		panic("Failed to allocate mount hash table\n");
 
 	printk(KERN_INFO "Mount-cache hash table entries: %lu\n", HASH_SIZE);
 
 	for (u = 0; u < HASH_SIZE; u++)
 		INIT_LIST_HEAD(&mount_hashtable[u]);
+	for (u = 0; u < HASH_SIZE; u++)
+		INIT_LIST_HEAD(&mountpoint_hashtable[u]);
 
 	br_lock_init(&vfsmount_lock);
 
@@ -2694,16 +2746,13 @@
 
 void put_mnt_ns(struct mnt_namespace *ns)
 {
-	LIST_HEAD(umount_list);
-
 	if (!atomic_dec_and_test(&ns->count))
 		return;
-	down_write(&namespace_sem);
+	namespace_lock();
 	br_write_lock(&vfsmount_lock);
-	umount_tree(ns->root, 0, &umount_list);
+	umount_tree(ns->root, 0);
 	br_write_unlock(&vfsmount_lock);
-	up_write(&namespace_sem);
-	release_mounts(&umount_list);
+	namespace_unlock();
 	free_mnt_ns(ns);
 }
 
diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c
index f33455b..5bee031 100644
--- a/fs/nfsd/nfsctl.c
+++ b/fs/nfsd/nfsctl.c
@@ -177,7 +177,7 @@
 	return single_open(file, export_features_show, NULL);
 }
 
-static struct file_operations export_features_operations = {
+static const struct file_operations export_features_operations = {
 	.open		= export_features_open,
 	.read		= seq_read,
 	.llseek		= seq_lseek,
@@ -196,7 +196,7 @@
 	return single_open(file, supported_enctypes_show, NULL);
 }
 
-static struct file_operations supported_enctypes_ops = {
+static const struct file_operations supported_enctypes_ops = {
 	.open		= supported_enctypes_open,
 	.read		= seq_read,
 	.llseek		= seq_lseek,
diff --git a/fs/notify/inotify/inotify_user.c b/fs/notify/inotify/inotify_user.c
index c616a70..959815c 100644
--- a/fs/notify/inotify/inotify_user.c
+++ b/fs/notify/inotify/inotify_user.c
@@ -287,9 +287,6 @@
 
 	pr_debug("%s: group=%p\n", __func__, group);
 
-	if (file->f_flags & FASYNC)
-		fsnotify_fasync(-1, file, 0);
-
 	/* free this group, matching get was inotify_init->fsnotify_obtain_group */
 	fsnotify_destroy_group(group);
 
diff --git a/fs/ntfs/file.c b/fs/ntfs/file.c
index 5b2d4f0..1da4b81 100644
--- a/fs/ntfs/file.c
+++ b/fs/ntfs/file.c
@@ -2129,7 +2129,6 @@
 
 	BUG_ON(iocb->ki_pos != pos);
 
-	sb_start_write(inode->i_sb);
 	mutex_lock(&inode->i_mutex);
 	ret = ntfs_file_aio_write_nolock(iocb, iov, nr_segs, &iocb->ki_pos);
 	mutex_unlock(&inode->i_mutex);
@@ -2138,7 +2137,6 @@
 		if (err < 0)
 			ret = err;
 	}
-	sb_end_write(inode->i_sb);
 	return ret;
 }
 
diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c
index 6474cb4..8a7509f 100644
--- a/fs/ocfs2/file.c
+++ b/fs/ocfs2/file.c
@@ -2248,8 +2248,6 @@
 	if (iocb->ki_left == 0)
 		return 0;
 
-	sb_start_write(inode->i_sb);
-
 	appending = file->f_flags & O_APPEND ? 1 : 0;
 	direct_io = file->f_flags & O_DIRECT ? 1 : 0;
 
@@ -2423,7 +2421,6 @@
 		ocfs2_iocb_clear_sem_locked(iocb);
 
 	mutex_unlock(&inode->i_mutex);
-	sb_end_write(inode->i_sb);
 
 	if (written)
 		ret = written;
@@ -2468,8 +2465,7 @@
 			out->f_path.dentry->d_name.len,
 			out->f_path.dentry->d_name.name, len);
 
-	if (pipe->inode)
-		mutex_lock_nested(&pipe->inode->i_mutex, I_MUTEX_PARENT);
+	pipe_lock(pipe);
 
 	splice_from_pipe_begin(&sd);
 	do {
@@ -2489,8 +2485,7 @@
 	} while (ret > 0);
 	splice_from_pipe_end(pipe, &sd);
 
-	if (pipe->inode)
-		mutex_unlock(&pipe->inode->i_mutex);
+	pipe_unlock(pipe);
 
 	if (sd.num_spliced)
 		ret = sd.num_spliced;
diff --git a/fs/pipe.c b/fs/pipe.c
index 2234f3f..a029a14 100644
--- a/fs/pipe.c
+++ b/fs/pipe.c
@@ -25,6 +25,8 @@
 #include <asm/uaccess.h>
 #include <asm/ioctls.h>
 
+#include "internal.h"
+
 /*
  * The max size that a non-root user is allowed to grow the pipe. Can
  * be set by root in /proc/sys/fs/pipe-max-size
@@ -53,8 +55,8 @@
 
 static void pipe_lock_nested(struct pipe_inode_info *pipe, int subclass)
 {
-	if (pipe->inode)
-		mutex_lock_nested(&pipe->inode->i_mutex, subclass);
+	if (pipe->files)
+		mutex_lock_nested(&pipe->mutex, subclass);
 }
 
 void pipe_lock(struct pipe_inode_info *pipe)
@@ -68,11 +70,21 @@
 
 void pipe_unlock(struct pipe_inode_info *pipe)
 {
-	if (pipe->inode)
-		mutex_unlock(&pipe->inode->i_mutex);
+	if (pipe->files)
+		mutex_unlock(&pipe->mutex);
 }
 EXPORT_SYMBOL(pipe_unlock);
 
+static inline void __pipe_lock(struct pipe_inode_info *pipe)
+{
+	mutex_lock_nested(&pipe->mutex, I_MUTEX_PARENT);
+}
+
+static inline void __pipe_unlock(struct pipe_inode_info *pipe)
+{
+	mutex_unlock(&pipe->mutex);
+}
+
 void pipe_double_lock(struct pipe_inode_info *pipe1,
 		      struct pipe_inode_info *pipe2)
 {
@@ -361,8 +373,7 @@
 	   unsigned long nr_segs, loff_t pos)
 {
 	struct file *filp = iocb->ki_filp;
-	struct inode *inode = file_inode(filp);
-	struct pipe_inode_info *pipe;
+	struct pipe_inode_info *pipe = filp->private_data;
 	int do_wakeup;
 	ssize_t ret;
 	struct iovec *iov = (struct iovec *)_iov;
@@ -375,8 +386,7 @@
 
 	do_wakeup = 0;
 	ret = 0;
-	mutex_lock(&inode->i_mutex);
-	pipe = inode->i_pipe;
+	__pipe_lock(pipe);
 	for (;;) {
 		int bufs = pipe->nrbufs;
 		if (bufs) {
@@ -464,7 +474,7 @@
 		}
 		pipe_wait(pipe);
 	}
-	mutex_unlock(&inode->i_mutex);
+	__pipe_unlock(pipe);
 
 	/* Signal writers asynchronously that there is more room. */
 	if (do_wakeup) {
@@ -486,8 +496,7 @@
 	    unsigned long nr_segs, loff_t ppos)
 {
 	struct file *filp = iocb->ki_filp;
-	struct inode *inode = file_inode(filp);
-	struct pipe_inode_info *pipe;
+	struct pipe_inode_info *pipe = filp->private_data;
 	ssize_t ret;
 	int do_wakeup;
 	struct iovec *iov = (struct iovec *)_iov;
@@ -501,8 +510,7 @@
 
 	do_wakeup = 0;
 	ret = 0;
-	mutex_lock(&inode->i_mutex);
-	pipe = inode->i_pipe;
+	__pipe_lock(pipe);
 
 	if (!pipe->readers) {
 		send_sig(SIGPIPE, current, 0);
@@ -649,7 +657,7 @@
 		pipe->waiting_writers--;
 	}
 out:
-	mutex_unlock(&inode->i_mutex);
+	__pipe_unlock(pipe);
 	if (do_wakeup) {
 		wake_up_interruptible_sync_poll(&pipe->wait, POLLIN | POLLRDNORM);
 		kill_fasync(&pipe->fasync_readers, SIGIO, POLL_IN);
@@ -662,29 +670,14 @@
 	return ret;
 }
 
-static ssize_t
-bad_pipe_r(struct file *filp, char __user *buf, size_t count, loff_t *ppos)
-{
-	return -EBADF;
-}
-
-static ssize_t
-bad_pipe_w(struct file *filp, const char __user *buf, size_t count,
-	   loff_t *ppos)
-{
-	return -EBADF;
-}
-
 static long pipe_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 {
-	struct inode *inode = file_inode(filp);
-	struct pipe_inode_info *pipe;
+	struct pipe_inode_info *pipe = filp->private_data;
 	int count, buf, nrbufs;
 
 	switch (cmd) {
 		case FIONREAD:
-			mutex_lock(&inode->i_mutex);
-			pipe = inode->i_pipe;
+			__pipe_lock(pipe);
 			count = 0;
 			buf = pipe->curbuf;
 			nrbufs = pipe->nrbufs;
@@ -692,7 +685,7 @@
 				count += pipe->bufs[buf].len;
 				buf = (buf+1) & (pipe->buffers - 1);
 			}
-			mutex_unlock(&inode->i_mutex);
+			__pipe_unlock(pipe);
 
 			return put_user(count, (int __user *)arg);
 		default:
@@ -705,8 +698,7 @@
 pipe_poll(struct file *filp, poll_table *wait)
 {
 	unsigned int mask;
-	struct inode *inode = file_inode(filp);
-	struct pipe_inode_info *pipe = inode->i_pipe;
+	struct pipe_inode_info *pipe = filp->private_data;
 	int nrbufs;
 
 	poll_wait(filp, &pipe->wait, wait);
@@ -734,197 +726,56 @@
 }
 
 static int
-pipe_release(struct inode *inode, int decr, int decw)
+pipe_release(struct inode *inode, struct file *file)
 {
-	struct pipe_inode_info *pipe;
+	struct pipe_inode_info *pipe = inode->i_pipe;
+	int kill = 0;
 
-	mutex_lock(&inode->i_mutex);
-	pipe = inode->i_pipe;
-	pipe->readers -= decr;
-	pipe->writers -= decw;
+	__pipe_lock(pipe);
+	if (file->f_mode & FMODE_READ)
+		pipe->readers--;
+	if (file->f_mode & FMODE_WRITE)
+		pipe->writers--;
 
-	if (!pipe->readers && !pipe->writers) {
-		free_pipe_info(inode);
-	} else {
+	if (pipe->readers || pipe->writers) {
 		wake_up_interruptible_sync_poll(&pipe->wait, POLLIN | POLLOUT | POLLRDNORM | POLLWRNORM | POLLERR | POLLHUP);
 		kill_fasync(&pipe->fasync_readers, SIGIO, POLL_IN);
 		kill_fasync(&pipe->fasync_writers, SIGIO, POLL_OUT);
 	}
-	mutex_unlock(&inode->i_mutex);
+	spin_lock(&inode->i_lock);
+	if (!--pipe->files) {
+		inode->i_pipe = NULL;
+		kill = 1;
+	}
+	spin_unlock(&inode->i_lock);
+	__pipe_unlock(pipe);
+
+	if (kill)
+		free_pipe_info(pipe);
 
 	return 0;
 }
 
 static int
-pipe_read_fasync(int fd, struct file *filp, int on)
+pipe_fasync(int fd, struct file *filp, int on)
 {
-	struct inode *inode = file_inode(filp);
-	int retval;
+	struct pipe_inode_info *pipe = filp->private_data;
+	int retval = 0;
 
-	mutex_lock(&inode->i_mutex);
-	retval = fasync_helper(fd, filp, on, &inode->i_pipe->fasync_readers);
-	mutex_unlock(&inode->i_mutex);
-
-	return retval;
-}
-
-
-static int
-pipe_write_fasync(int fd, struct file *filp, int on)
-{
-	struct inode *inode = file_inode(filp);
-	int retval;
-
-	mutex_lock(&inode->i_mutex);
-	retval = fasync_helper(fd, filp, on, &inode->i_pipe->fasync_writers);
-	mutex_unlock(&inode->i_mutex);
-
-	return retval;
-}
-
-
-static int
-pipe_rdwr_fasync(int fd, struct file *filp, int on)
-{
-	struct inode *inode = file_inode(filp);
-	struct pipe_inode_info *pipe = inode->i_pipe;
-	int retval;
-
-	mutex_lock(&inode->i_mutex);
-	retval = fasync_helper(fd, filp, on, &pipe->fasync_readers);
-	if (retval >= 0) {
+	__pipe_lock(pipe);
+	if (filp->f_mode & FMODE_READ)
+		retval = fasync_helper(fd, filp, on, &pipe->fasync_readers);
+	if ((filp->f_mode & FMODE_WRITE) && retval >= 0) {
 		retval = fasync_helper(fd, filp, on, &pipe->fasync_writers);
-		if (retval < 0) /* this can happen only if on == T */
+		if (retval < 0 && (filp->f_mode & FMODE_READ))
+			/* this can happen only if on == T */
 			fasync_helper(-1, filp, 0, &pipe->fasync_readers);
 	}
-	mutex_unlock(&inode->i_mutex);
+	__pipe_unlock(pipe);
 	return retval;
 }
 
-
-static int
-pipe_read_release(struct inode *inode, struct file *filp)
-{
-	return pipe_release(inode, 1, 0);
-}
-
-static int
-pipe_write_release(struct inode *inode, struct file *filp)
-{
-	return pipe_release(inode, 0, 1);
-}
-
-static int
-pipe_rdwr_release(struct inode *inode, struct file *filp)
-{
-	int decr, decw;
-
-	decr = (filp->f_mode & FMODE_READ) != 0;
-	decw = (filp->f_mode & FMODE_WRITE) != 0;
-	return pipe_release(inode, decr, decw);
-}
-
-static int
-pipe_read_open(struct inode *inode, struct file *filp)
-{
-	int ret = -ENOENT;
-
-	mutex_lock(&inode->i_mutex);
-
-	if (inode->i_pipe) {
-		ret = 0;
-		inode->i_pipe->readers++;
-	}
-
-	mutex_unlock(&inode->i_mutex);
-
-	return ret;
-}
-
-static int
-pipe_write_open(struct inode *inode, struct file *filp)
-{
-	int ret = -ENOENT;
-
-	mutex_lock(&inode->i_mutex);
-
-	if (inode->i_pipe) {
-		ret = 0;
-		inode->i_pipe->writers++;
-	}
-
-	mutex_unlock(&inode->i_mutex);
-
-	return ret;
-}
-
-static int
-pipe_rdwr_open(struct inode *inode, struct file *filp)
-{
-	int ret = -ENOENT;
-
-	if (!(filp->f_mode & (FMODE_READ|FMODE_WRITE)))
-		return -EINVAL;
-
-	mutex_lock(&inode->i_mutex);
-
-	if (inode->i_pipe) {
-		ret = 0;
-		if (filp->f_mode & FMODE_READ)
-			inode->i_pipe->readers++;
-		if (filp->f_mode & FMODE_WRITE)
-			inode->i_pipe->writers++;
-	}
-
-	mutex_unlock(&inode->i_mutex);
-
-	return ret;
-}
-
-/*
- * The file_operations structs are not static because they
- * are also used in linux/fs/fifo.c to do operations on FIFOs.
- *
- * Pipes reuse fifos' file_operations structs.
- */
-const struct file_operations read_pipefifo_fops = {
-	.llseek		= no_llseek,
-	.read		= do_sync_read,
-	.aio_read	= pipe_read,
-	.write		= bad_pipe_w,
-	.poll		= pipe_poll,
-	.unlocked_ioctl	= pipe_ioctl,
-	.open		= pipe_read_open,
-	.release	= pipe_read_release,
-	.fasync		= pipe_read_fasync,
-};
-
-const struct file_operations write_pipefifo_fops = {
-	.llseek		= no_llseek,
-	.read		= bad_pipe_r,
-	.write		= do_sync_write,
-	.aio_write	= pipe_write,
-	.poll		= pipe_poll,
-	.unlocked_ioctl	= pipe_ioctl,
-	.open		= pipe_write_open,
-	.release	= pipe_write_release,
-	.fasync		= pipe_write_fasync,
-};
-
-const struct file_operations rdwr_pipefifo_fops = {
-	.llseek		= no_llseek,
-	.read		= do_sync_read,
-	.aio_read	= pipe_read,
-	.write		= do_sync_write,
-	.aio_write	= pipe_write,
-	.poll		= pipe_poll,
-	.unlocked_ioctl	= pipe_ioctl,
-	.open		= pipe_rdwr_open,
-	.release	= pipe_rdwr_release,
-	.fasync		= pipe_rdwr_fasync,
-};
-
-struct pipe_inode_info * alloc_pipe_info(struct inode *inode)
+struct pipe_inode_info *alloc_pipe_info(void)
 {
 	struct pipe_inode_info *pipe;
 
@@ -934,8 +785,8 @@
 		if (pipe->bufs) {
 			init_waitqueue_head(&pipe->wait);
 			pipe->r_counter = pipe->w_counter = 1;
-			pipe->inode = inode;
 			pipe->buffers = PIPE_DEF_BUFFERS;
+			mutex_init(&pipe->mutex);
 			return pipe;
 		}
 		kfree(pipe);
@@ -944,7 +795,7 @@
 	return NULL;
 }
 
-void __free_pipe_info(struct pipe_inode_info *pipe)
+void free_pipe_info(struct pipe_inode_info *pipe)
 {
 	int i;
 
@@ -959,12 +810,6 @@
 	kfree(pipe);
 }
 
-void free_pipe_info(struct inode *inode)
-{
-	__free_pipe_info(inode->i_pipe);
-	inode->i_pipe = NULL;
-}
-
 static struct vfsmount *pipe_mnt __read_mostly;
 
 /*
@@ -990,13 +835,14 @@
 
 	inode->i_ino = get_next_ino();
 
-	pipe = alloc_pipe_info(inode);
+	pipe = alloc_pipe_info();
 	if (!pipe)
 		goto fail_iput;
-	inode->i_pipe = pipe;
 
+	inode->i_pipe = pipe;
+	pipe->files = 2;
 	pipe->readers = pipe->writers = 1;
-	inode->i_fop = &rdwr_pipefifo_fops;
+	inode->i_fop = &pipefifo_fops;
 
 	/*
 	 * Mark the inode dirty from the very beginning,
@@ -1039,17 +885,19 @@
 	d_instantiate(path.dentry, inode);
 
 	err = -ENFILE;
-	f = alloc_file(&path, FMODE_WRITE, &write_pipefifo_fops);
+	f = alloc_file(&path, FMODE_WRITE, &pipefifo_fops);
 	if (IS_ERR(f))
 		goto err_dentry;
 
 	f->f_flags = O_WRONLY | (flags & (O_NONBLOCK | O_DIRECT));
+	f->private_data = inode->i_pipe;
 
-	res[0] = alloc_file(&path, FMODE_READ, &read_pipefifo_fops);
+	res[0] = alloc_file(&path, FMODE_READ, &pipefifo_fops);
 	if (IS_ERR(res[0]))
 		goto err_file;
 
 	path_get(&path);
+	res[0]->private_data = inode->i_pipe;
 	res[0]->f_flags = O_RDONLY | (flags & O_NONBLOCK);
 	res[1] = f;
 	return 0;
@@ -1057,12 +905,12 @@
 err_file:
 	put_filp(f);
 err_dentry:
-	free_pipe_info(inode);
+	free_pipe_info(inode->i_pipe);
 	path_put(&path);
 	return err;
 
 err_inode:
-	free_pipe_info(inode);
+	free_pipe_info(inode->i_pipe);
 	iput(inode);
 	return err;
 }
@@ -1144,6 +992,168 @@
 	return sys_pipe2(fildes, 0);
 }
 
+static int wait_for_partner(struct pipe_inode_info *pipe, unsigned int *cnt)
+{
+	int cur = *cnt;	
+
+	while (cur == *cnt) {
+		pipe_wait(pipe);
+		if (signal_pending(current))
+			break;
+	}
+	return cur == *cnt ? -ERESTARTSYS : 0;
+}
+
+static void wake_up_partner(struct pipe_inode_info *pipe)
+{
+	wake_up_interruptible(&pipe->wait);
+}
+
+static int fifo_open(struct inode *inode, struct file *filp)
+{
+	struct pipe_inode_info *pipe;
+	bool is_pipe = inode->i_sb->s_magic == PIPEFS_MAGIC;
+	int kill = 0;
+	int ret;
+
+	filp->f_version = 0;
+
+	spin_lock(&inode->i_lock);
+	if (inode->i_pipe) {
+		pipe = inode->i_pipe;
+		pipe->files++;
+		spin_unlock(&inode->i_lock);
+	} else {
+		spin_unlock(&inode->i_lock);
+		pipe = alloc_pipe_info();
+		if (!pipe)
+			return -ENOMEM;
+		pipe->files = 1;
+		spin_lock(&inode->i_lock);
+		if (unlikely(inode->i_pipe)) {
+			inode->i_pipe->files++;
+			spin_unlock(&inode->i_lock);
+			free_pipe_info(pipe);
+			pipe = inode->i_pipe;
+		} else {
+			inode->i_pipe = pipe;
+			spin_unlock(&inode->i_lock);
+		}
+	}
+	filp->private_data = pipe;
+	/* OK, we have a pipe and it's pinned down */
+
+	__pipe_lock(pipe);
+
+	/* We can only do regular read/write on fifos */
+	filp->f_mode &= (FMODE_READ | FMODE_WRITE);
+
+	switch (filp->f_mode) {
+	case FMODE_READ:
+	/*
+	 *  O_RDONLY
+	 *  POSIX.1 says that O_NONBLOCK means return with the FIFO
+	 *  opened, even when there is no process writing the FIFO.
+	 */
+		pipe->r_counter++;
+		if (pipe->readers++ == 0)
+			wake_up_partner(pipe);
+
+		if (!is_pipe && !pipe->writers) {
+			if ((filp->f_flags & O_NONBLOCK)) {
+				/* suppress POLLHUP until we have
+				 * seen a writer */
+				filp->f_version = pipe->w_counter;
+			} else {
+				if (wait_for_partner(pipe, &pipe->w_counter))
+					goto err_rd;
+			}
+		}
+		break;
+	
+	case FMODE_WRITE:
+	/*
+	 *  O_WRONLY
+	 *  POSIX.1 says that O_NONBLOCK means return -1 with
+	 *  errno=ENXIO when there is no process reading the FIFO.
+	 */
+		ret = -ENXIO;
+		if (!is_pipe && (filp->f_flags & O_NONBLOCK) && !pipe->readers)
+			goto err;
+
+		pipe->w_counter++;
+		if (!pipe->writers++)
+			wake_up_partner(pipe);
+
+		if (!is_pipe && !pipe->readers) {
+			if (wait_for_partner(pipe, &pipe->r_counter))
+				goto err_wr;
+		}
+		break;
+	
+	case FMODE_READ | FMODE_WRITE:
+	/*
+	 *  O_RDWR
+	 *  POSIX.1 leaves this case "undefined" when O_NONBLOCK is set.
+	 *  This implementation will NEVER block on a O_RDWR open, since
+	 *  the process can at least talk to itself.
+	 */
+
+		pipe->readers++;
+		pipe->writers++;
+		pipe->r_counter++;
+		pipe->w_counter++;
+		if (pipe->readers == 1 || pipe->writers == 1)
+			wake_up_partner(pipe);
+		break;
+
+	default:
+		ret = -EINVAL;
+		goto err;
+	}
+
+	/* Ok! */
+	__pipe_unlock(pipe);
+	return 0;
+
+err_rd:
+	if (!--pipe->readers)
+		wake_up_interruptible(&pipe->wait);
+	ret = -ERESTARTSYS;
+	goto err;
+
+err_wr:
+	if (!--pipe->writers)
+		wake_up_interruptible(&pipe->wait);
+	ret = -ERESTARTSYS;
+	goto err;
+
+err:
+	spin_lock(&inode->i_lock);
+	if (!--pipe->files) {
+		inode->i_pipe = NULL;
+		kill = 1;
+	}
+	spin_unlock(&inode->i_lock);
+	__pipe_unlock(pipe);
+	if (kill)
+		free_pipe_info(pipe);
+	return ret;
+}
+
+const struct file_operations pipefifo_fops = {
+	.open		= fifo_open,
+	.llseek		= no_llseek,
+	.read		= do_sync_read,
+	.aio_read	= pipe_read,
+	.write		= do_sync_write,
+	.aio_write	= pipe_write,
+	.poll		= pipe_poll,
+	.unlocked_ioctl	= pipe_ioctl,
+	.release	= pipe_release,
+	.fasync		= pipe_fasync,
+};
+
 /*
  * Allocate a new array of pipe buffers and copy the info over. Returns the
  * pipe size if successful, or return -ERROR on error.
@@ -1229,9 +1239,7 @@
  */
 struct pipe_inode_info *get_pipe_info(struct file *file)
 {
-	struct inode *i = file_inode(file);
-
-	return S_ISFIFO(i->i_mode) ? i->i_pipe : NULL;
+	return file->f_op == &pipefifo_fops ? file->private_data : NULL;
 }
 
 long pipe_fcntl(struct file *file, unsigned int cmd, unsigned long arg)
@@ -1243,7 +1251,7 @@
 	if (!pipe)
 		return -EBADF;
 
-	mutex_lock(&pipe->inode->i_mutex);
+	__pipe_lock(pipe);
 
 	switch (cmd) {
 	case F_SETPIPE_SZ: {
@@ -1272,7 +1280,7 @@
 	}
 
 out:
-	mutex_unlock(&pipe->inode->i_mutex);
+	__pipe_unlock(pipe);
 	return ret;
 }
 
diff --git a/fs/pnode.c b/fs/pnode.c
index 8b29d21..3d2a714 100644
--- a/fs/pnode.c
+++ b/fs/pnode.c
@@ -218,7 +218,7 @@
  * @source_mnt: source mount.
  * @tree_list : list of heads of trees to be attached.
  */
-int propagate_mnt(struct mount *dest_mnt, struct dentry *dest_dentry,
+int propagate_mnt(struct mount *dest_mnt, struct mountpoint *dest_mp,
 		    struct mount *source_mnt, struct list_head *tree_list)
 {
 	struct user_namespace *user_ns = current->nsproxy->mnt_ns->user_ns;
@@ -227,7 +227,6 @@
 	struct mount *prev_dest_mnt = dest_mnt;
 	struct mount *prev_src_mnt  = source_mnt;
 	LIST_HEAD(tmp_list);
-	LIST_HEAD(umount_list);
 
 	for (m = propagation_next(dest_mnt, dest_mnt); m;
 			m = propagation_next(m, dest_mnt)) {
@@ -250,8 +249,8 @@
 			goto out;
 		}
 
-		if (is_subdir(dest_dentry, m->mnt.mnt_root)) {
-			mnt_set_mountpoint(m, dest_dentry, child);
+		if (is_subdir(dest_mp->m_dentry, m->mnt.mnt_root)) {
+			mnt_set_mountpoint(m, dest_mp, child);
 			list_add_tail(&child->mnt_hash, tree_list);
 		} else {
 			/*
@@ -267,10 +266,9 @@
 	br_write_lock(&vfsmount_lock);
 	while (!list_empty(&tmp_list)) {
 		child = list_first_entry(&tmp_list, struct mount, mnt_hash);
-		umount_tree(child, 0, &umount_list);
+		umount_tree(child, 0);
 	}
 	br_write_unlock(&vfsmount_lock);
-	release_mounts(&umount_list);
 	return ret;
 }
 
diff --git a/fs/pnode.h b/fs/pnode.h
index a0493d5..b091445 100644
--- a/fs/pnode.h
+++ b/fs/pnode.h
@@ -32,17 +32,16 @@
 }
 
 void change_mnt_propagation(struct mount *, int);
-int propagate_mnt(struct mount *, struct dentry *, struct mount *,
+int propagate_mnt(struct mount *, struct mountpoint *, struct mount *,
 		struct list_head *);
 int propagate_umount(struct list_head *);
 int propagate_mount_busy(struct mount *, int);
 void mnt_release_group_id(struct mount *);
 int get_dominating_id(struct mount *mnt, const struct path *root);
 unsigned int mnt_get_count(struct mount *mnt);
-void mnt_set_mountpoint(struct mount *, struct dentry *,
+void mnt_set_mountpoint(struct mount *, struct mountpoint *,
 			struct mount *);
-void release_mounts(struct list_head *);
-void umount_tree(struct mount *, int, struct list_head *);
+void umount_tree(struct mount *, int);
 struct mount *copy_tree(struct mount *, struct dentry *, int);
 bool is_path_reachable(struct mount *, struct dentry *,
 			 const struct path *root);
diff --git a/fs/proc/base.c b/fs/proc/base.c
index 3861bce..dd51e50 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -405,6 +405,37 @@
 
 #endif
 
+#ifdef CONFIG_CGROUPS
+static int cgroup_open(struct inode *inode, struct file *file)
+{
+	struct pid *pid = PROC_I(inode)->pid;
+	return single_open(file, proc_cgroup_show, pid);
+}
+
+static const struct file_operations proc_cgroup_operations = {
+	.open		= cgroup_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+#endif
+
+#ifdef CONFIG_PROC_PID_CPUSET
+
+static int cpuset_open(struct inode *inode, struct file *file)
+{
+	struct pid *pid = PROC_I(inode)->pid;
+	return single_open(file, proc_cpuset_show, pid);
+}
+
+static const struct file_operations proc_cpuset_operations = {
+	.open		= cpuset_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+#endif
+
 static int proc_oom_score(struct task_struct *task, char *buffer)
 {
 	unsigned long totalpages = totalram_pages + total_swap_pages;
@@ -1621,6 +1652,15 @@
 	return 0;
 }
 
+int pid_delete_dentry(const struct dentry *dentry)
+{
+	/* Is the task we represent dead?
+	 * If so, then don't put the dentry on the lru list,
+	 * kill it immediately.
+	 */
+	return !proc_pid(dentry->d_inode)->tasks[PIDTYPE_PID].first;
+}
+
 const struct dentry_operations pid_dentry_operations =
 {
 	.d_revalidate	= pid_revalidate,
@@ -2893,7 +2933,7 @@
 	return iter;
 }
 
-#define TGID_OFFSET (FIRST_PROCESS_ENTRY)
+#define TGID_OFFSET (FIRST_PROCESS_ENTRY + 1)
 
 static int proc_pid_fill_cache(struct file *filp, void *dirent, filldir_t filldir,
 	struct tgid_iter iter)
@@ -2916,13 +2956,21 @@
 	struct tgid_iter iter;
 	struct pid_namespace *ns;
 	filldir_t __filldir;
+	loff_t pos = filp->f_pos;
 
-	if (filp->f_pos >= PID_MAX_LIMIT + TGID_OFFSET)
+	if (pos >= PID_MAX_LIMIT + TGID_OFFSET)
 		goto out;
 
-	ns = filp->f_dentry->d_sb->s_fs_info;
+	if (pos == TGID_OFFSET - 1) {
+		if (proc_fill_cache(filp, dirent, filldir, "self", 4,
+					NULL, NULL, NULL) < 0)
+			goto out;
+		iter.tgid = 0;
+	} else {
+		iter.tgid = pos - TGID_OFFSET;
+	}
 	iter.task = NULL;
-	iter.tgid = filp->f_pos - TGID_OFFSET;
+	ns = filp->f_dentry->d_sb->s_fs_info;
 	for (iter = next_tgid(ns, iter);
 	     iter.task;
 	     iter.tgid += 1, iter = next_tgid(ns, iter)) {
diff --git a/fs/proc/fd.h b/fs/proc/fd.h
index cbb1d47..7c047f2 100644
--- a/fs/proc/fd.h
+++ b/fs/proc/fd.h
@@ -11,4 +11,9 @@
 
 extern int proc_fd_permission(struct inode *inode, int mask);
 
+static inline int proc_fd(struct inode *inode)
+{
+	return PROC_I(inode)->fd;
+}
+
 #endif /* __PROCFS_FD_H__ */
diff --git a/fs/proc/generic.c b/fs/proc/generic.c
index 21e1a8f..a2596af 100644
--- a/fs/proc/generic.c
+++ b/fs/proc/generic.c
@@ -36,212 +36,6 @@
 	return !memcmp(name, de->name, len);
 }
 
-/* buffer size is one page but our output routines use some slack for overruns */
-#define PROC_BLOCK_SIZE	(PAGE_SIZE - 1024)
-
-static ssize_t
-__proc_file_read(struct file *file, char __user *buf, size_t nbytes,
-	       loff_t *ppos)
-{
-	struct inode * inode = file_inode(file);
-	char 	*page;
-	ssize_t	retval=0;
-	int	eof=0;
-	ssize_t	n, count;
-	char	*start;
-	struct proc_dir_entry * dp;
-	unsigned long long pos;
-
-	/*
-	 * Gaah, please just use "seq_file" instead. The legacy /proc
-	 * interfaces cut loff_t down to off_t for reads, and ignore
-	 * the offset entirely for writes..
-	 */
-	pos = *ppos;
-	if (pos > MAX_NON_LFS)
-		return 0;
-	if (nbytes > MAX_NON_LFS - pos)
-		nbytes = MAX_NON_LFS - pos;
-
-	dp = PDE(inode);
-	if (!(page = (char*) __get_free_page(GFP_TEMPORARY)))
-		return -ENOMEM;
-
-	while ((nbytes > 0) && !eof) {
-		count = min_t(size_t, PROC_BLOCK_SIZE, nbytes);
-
-		start = NULL;
-		if (dp->read_proc) {
-			/*
-			 * How to be a proc read function
-			 * ------------------------------
-			 * Prototype:
-			 *    int f(char *buffer, char **start, off_t offset,
-			 *          int count, int *peof, void *dat)
-			 *
-			 * Assume that the buffer is "count" bytes in size.
-			 *
-			 * If you know you have supplied all the data you
-			 * have, set *peof.
-			 *
-			 * You have three ways to return data:
-			 * 0) Leave *start = NULL.  (This is the default.)
-			 *    Put the data of the requested offset at that
-			 *    offset within the buffer.  Return the number (n)
-			 *    of bytes there are from the beginning of the
-			 *    buffer up to the last byte of data.  If the
-			 *    number of supplied bytes (= n - offset) is 
-			 *    greater than zero and you didn't signal eof
-			 *    and the reader is prepared to take more data
-			 *    you will be called again with the requested
-			 *    offset advanced by the number of bytes 
-			 *    absorbed.  This interface is useful for files
-			 *    no larger than the buffer.
-			 * 1) Set *start = an unsigned long value less than
-			 *    the buffer address but greater than zero.
-			 *    Put the data of the requested offset at the
-			 *    beginning of the buffer.  Return the number of
-			 *    bytes of data placed there.  If this number is
-			 *    greater than zero and you didn't signal eof
-			 *    and the reader is prepared to take more data
-			 *    you will be called again with the requested
-			 *    offset advanced by *start.  This interface is
-			 *    useful when you have a large file consisting
-			 *    of a series of blocks which you want to count
-			 *    and return as wholes.
-			 *    (Hack by Paul.Russell@rustcorp.com.au)
-			 * 2) Set *start = an address within the buffer.
-			 *    Put the data of the requested offset at *start.
-			 *    Return the number of bytes of data placed there.
-			 *    If this number is greater than zero and you
-			 *    didn't signal eof and the reader is prepared to
-			 *    take more data you will be called again with the
-			 *    requested offset advanced by the number of bytes
-			 *    absorbed.
-			 */
-			n = dp->read_proc(page, &start, *ppos,
-					  count, &eof, dp->data);
-		} else
-			break;
-
-		if (n == 0)   /* end of file */
-			break;
-		if (n < 0) {  /* error */
-			if (retval == 0)
-				retval = n;
-			break;
-		}
-
-		if (start == NULL) {
-			if (n > PAGE_SIZE)	/* Apparent buffer overflow */
-				n = PAGE_SIZE;
-			n -= *ppos;
-			if (n <= 0)
-				break;
-			if (n > count)
-				n = count;
-			start = page + *ppos;
-		} else if (start < page) {
-			if (n > PAGE_SIZE)	/* Apparent buffer overflow */
-				n = PAGE_SIZE;
-			if (n > count) {
-				/*
-				 * Don't reduce n because doing so might
-				 * cut off part of a data block.
-				 */
-				pr_warn("proc_file_read: count exceeded\n");
-			}
-		} else /* start >= page */ {
-			unsigned long startoff = (unsigned long)(start - page);
-			if (n > (PAGE_SIZE - startoff))	/* buffer overflow? */
-				n = PAGE_SIZE - startoff;
-			if (n > count)
-				n = count;
-		}
-		
- 		n -= copy_to_user(buf, start < page ? page : start, n);
-		if (n == 0) {
-			if (retval == 0)
-				retval = -EFAULT;
-			break;
-		}
-
-		*ppos += start < page ? (unsigned long)start : n;
-		nbytes -= n;
-		buf += n;
-		retval += n;
-	}
-	free_page((unsigned long) page);
-	return retval;
-}
-
-static ssize_t
-proc_file_read(struct file *file, char __user *buf, size_t nbytes,
-	       loff_t *ppos)
-{
-	struct proc_dir_entry *pde = PDE(file_inode(file));
-	ssize_t rv = -EIO;
-
-	spin_lock(&pde->pde_unload_lock);
-	if (!pde->proc_fops) {
-		spin_unlock(&pde->pde_unload_lock);
-		return rv;
-	}
-	pde->pde_users++;
-	spin_unlock(&pde->pde_unload_lock);
-
-	rv = __proc_file_read(file, buf, nbytes, ppos);
-
-	pde_users_dec(pde);
-	return rv;
-}
-
-static ssize_t
-proc_file_write(struct file *file, const char __user *buffer,
-		size_t count, loff_t *ppos)
-{
-	struct proc_dir_entry *pde = PDE(file_inode(file));
-	ssize_t rv = -EIO;
-
-	if (pde->write_proc) {
-		spin_lock(&pde->pde_unload_lock);
-		if (!pde->proc_fops) {
-			spin_unlock(&pde->pde_unload_lock);
-			return rv;
-		}
-		pde->pde_users++;
-		spin_unlock(&pde->pde_unload_lock);
-
-		/* FIXME: does this routine need ppos?  probably... */
-		rv = pde->write_proc(file, buffer, count, pde->data);
-		pde_users_dec(pde);
-	}
-	return rv;
-}
-
-
-static loff_t
-proc_file_lseek(struct file *file, loff_t offset, int orig)
-{
-	loff_t retval = -EINVAL;
-	switch (orig) {
-	case 1:
-		offset += file->f_pos;
-	/* fallthrough */
-	case 0:
-		if (offset < 0 || offset > MAX_NON_LFS)
-			break;
-		file->f_pos = retval = offset;
-	}
-	return retval;
-}
-
-static const struct file_operations proc_file_operations = {
-	.llseek		= proc_file_lseek,
-	.read		= proc_file_read,
-	.write		= proc_file_write,
-};
-
 static int proc_notify_change(struct dentry *dentry, struct iattr *iattr)
 {
 	struct inode *inode = dentry->d_inode;
@@ -371,7 +165,7 @@
 
 static void *proc_follow_link(struct dentry *dentry, struct nameidata *nd)
 {
-	nd_set_link(nd, PDE(dentry->d_inode)->data);
+	nd_set_link(nd, __PDE_DATA(dentry->d_inode));
 	return NULL;
 }
 
@@ -541,19 +335,17 @@
 		return ret;
 
 	if (S_ISDIR(dp->mode)) {
-		if (dp->proc_iops == NULL) {
-			dp->proc_fops = &proc_dir_operations;
-			dp->proc_iops = &proc_dir_inode_operations;
-		}
+		dp->proc_fops = &proc_dir_operations;
+		dp->proc_iops = &proc_dir_inode_operations;
 		dir->nlink++;
 	} else if (S_ISLNK(dp->mode)) {
-		if (dp->proc_iops == NULL)
-			dp->proc_iops = &proc_link_inode_operations;
+		dp->proc_iops = &proc_link_inode_operations;
 	} else if (S_ISREG(dp->mode)) {
-		if (dp->proc_fops == NULL)
-			dp->proc_fops = &proc_file_operations;
-		if (dp->proc_iops == NULL)
-			dp->proc_iops = &proc_file_inode_operations;
+		BUG_ON(dp->proc_fops == NULL);
+		dp->proc_iops = &proc_file_inode_operations;
+	} else {
+		WARN_ON(1);
+		return -EINVAL;
 	}
 
 	spin_lock(&proc_subdir_lock);
@@ -636,13 +428,17 @@
 }
 EXPORT_SYMBOL(proc_symlink);
 
-struct proc_dir_entry *proc_mkdir_mode(const char *name, umode_t mode,
-		struct proc_dir_entry *parent)
+struct proc_dir_entry *proc_mkdir_data(const char *name, umode_t mode,
+		struct proc_dir_entry *parent, void *data)
 {
 	struct proc_dir_entry *ent;
 
+	if (mode == 0)
+		mode = S_IRUGO | S_IXUGO;
+
 	ent = __proc_create(&parent, name, S_IFDIR | mode, 2);
 	if (ent) {
+		ent->data = data;
 		if (proc_register(parent, ent) < 0) {
 			kfree(ent);
 			ent = NULL;
@@ -650,82 +446,39 @@
 	}
 	return ent;
 }
+EXPORT_SYMBOL_GPL(proc_mkdir_data);
+
+struct proc_dir_entry *proc_mkdir_mode(const char *name, umode_t mode,
+				       struct proc_dir_entry *parent)
+{
+	return proc_mkdir_data(name, mode, parent, NULL);
+}
 EXPORT_SYMBOL(proc_mkdir_mode);
 
-struct proc_dir_entry *proc_net_mkdir(struct net *net, const char *name,
-		struct proc_dir_entry *parent)
-{
-	struct proc_dir_entry *ent;
-
-	ent = __proc_create(&parent, name, S_IFDIR | S_IRUGO | S_IXUGO, 2);
-	if (ent) {
-		ent->data = net;
-		if (proc_register(parent, ent) < 0) {
-			kfree(ent);
-			ent = NULL;
-		}
-	}
-	return ent;
-}
-EXPORT_SYMBOL_GPL(proc_net_mkdir);
-
 struct proc_dir_entry *proc_mkdir(const char *name,
 		struct proc_dir_entry *parent)
 {
-	return proc_mkdir_mode(name, S_IRUGO | S_IXUGO, parent);
+	return proc_mkdir_data(name, 0, parent, NULL);
 }
 EXPORT_SYMBOL(proc_mkdir);
 
-struct proc_dir_entry *create_proc_entry(const char *name, umode_t mode,
-					 struct proc_dir_entry *parent)
-{
-	struct proc_dir_entry *ent;
-	nlink_t nlink;
-
-	if (S_ISDIR(mode)) {
-		if ((mode & S_IALLUGO) == 0)
-			mode |= S_IRUGO | S_IXUGO;
-		nlink = 2;
-	} else {
-		if ((mode & S_IFMT) == 0)
-			mode |= S_IFREG;
-		if ((mode & S_IALLUGO) == 0)
-			mode |= S_IRUGO;
-		nlink = 1;
-	}
-
-	ent = __proc_create(&parent, name, mode, nlink);
-	if (ent) {
-		if (proc_register(parent, ent) < 0) {
-			kfree(ent);
-			ent = NULL;
-		}
-	}
-	return ent;
-}
-EXPORT_SYMBOL(create_proc_entry);
-
 struct proc_dir_entry *proc_create_data(const char *name, umode_t mode,
 					struct proc_dir_entry *parent,
 					const struct file_operations *proc_fops,
 					void *data)
 {
 	struct proc_dir_entry *pde;
-	nlink_t nlink;
+	if ((mode & S_IFMT) == 0)
+		mode |= S_IFREG;
 
-	if (S_ISDIR(mode)) {
-		if ((mode & S_IALLUGO) == 0)
-			mode |= S_IRUGO | S_IXUGO;
-		nlink = 2;
-	} else {
-		if ((mode & S_IFMT) == 0)
-			mode |= S_IFREG;
-		if ((mode & S_IALLUGO) == 0)
-			mode |= S_IRUGO;
-		nlink = 1;
+	if (!S_ISREG(mode)) {
+		WARN_ON(1);	/* use proc_mkdir() */
+		return NULL;
 	}
 
-	pde = __proc_create(&parent, name, mode, nlink);
+	if ((mode & S_IALLUGO) == 0)
+		mode |= S_IRUGO;
+	pde = __proc_create(&parent, name, mode, 1);
 	if (!pde)
 		goto out;
 	pde->proc_fops = proc_fops;
@@ -739,6 +492,19 @@
 	return NULL;
 }
 EXPORT_SYMBOL(proc_create_data);
+ 
+void proc_set_size(struct proc_dir_entry *de, loff_t size)
+{
+	de->size = size;
+}
+EXPORT_SYMBOL(proc_set_size);
+
+void proc_set_user(struct proc_dir_entry *de, kuid_t uid, kgid_t gid)
+{
+	de->uid = uid;
+	de->gid = gid;
+}
+EXPORT_SYMBOL(proc_set_user);
 
 static void free_proc_entry(struct proc_dir_entry *de)
 {
@@ -755,41 +521,6 @@
 		free_proc_entry(pde);
 }
 
-static void entry_rundown(struct proc_dir_entry *de)
-{
-	spin_lock(&de->pde_unload_lock);
-	/*
-	 * Stop accepting new callers into module. If you're
-	 * dynamically allocating ->proc_fops, save a pointer somewhere.
-	 */
-	de->proc_fops = NULL;
-	/* Wait until all existing callers into module are done. */
-	if (de->pde_users > 0) {
-		DECLARE_COMPLETION_ONSTACK(c);
-
-		if (!de->pde_unload_completion)
-			de->pde_unload_completion = &c;
-
-		spin_unlock(&de->pde_unload_lock);
-
-		wait_for_completion(de->pde_unload_completion);
-
-		spin_lock(&de->pde_unload_lock);
-	}
-
-	while (!list_empty(&de->pde_openers)) {
-		struct pde_opener *pdeo;
-
-		pdeo = list_first_entry(&de->pde_openers, struct pde_opener, lh);
-		list_del(&pdeo->lh);
-		spin_unlock(&de->pde_unload_lock);
-		pdeo->release(pdeo->inode, pdeo->file);
-		kfree(pdeo);
-		spin_lock(&de->pde_unload_lock);
-	}
-	spin_unlock(&de->pde_unload_lock);
-}
-
 /*
  * Remove a /proc entry and free it if it's not currently in use.
  */
@@ -821,7 +552,7 @@
 		return;
 	}
 
-	entry_rundown(de);
+	proc_entry_rundown(de);
 
 	if (S_ISDIR(de->mode))
 		parent->nlink--;
@@ -870,7 +601,7 @@
 		}
 		spin_unlock(&proc_subdir_lock);
 
-		entry_rundown(de);
+		proc_entry_rundown(de);
 		next = de->parent;
 		if (S_ISDIR(de->mode))
 			next->nlink--;
@@ -886,3 +617,23 @@
 	return 0;
 }
 EXPORT_SYMBOL(remove_proc_subtree);
+
+void *proc_get_parent_data(const struct inode *inode)
+{
+	struct proc_dir_entry *de = PDE(inode);
+	return de->parent->data;
+}
+EXPORT_SYMBOL_GPL(proc_get_parent_data);
+
+void proc_remove(struct proc_dir_entry *de)
+{
+	if (de)
+		remove_proc_subtree(de->name, de->parent);
+}
+EXPORT_SYMBOL(proc_remove);
+
+void *PDE_DATA(const struct inode *inode)
+{
+	return __PDE_DATA(inode);
+}
+EXPORT_SYMBOL(PDE_DATA);
diff --git a/fs/proc/inode.c b/fs/proc/inode.c
index 869116c..073aea60 100644
--- a/fs/proc/inode.c
+++ b/fs/proc/inode.c
@@ -22,6 +22,7 @@
 #include <linux/seq_file.h>
 #include <linux/slab.h>
 #include <linux/mount.h>
+#include <linux/magic.h>
 
 #include <asm/uaccess.h>
 
@@ -50,8 +51,8 @@
 		sysctl_head_put(head);
 	}
 	/* Release any associated namespace */
-	ns_ops = PROC_I(inode)->ns_ops;
-	ns = PROC_I(inode)->ns;
+	ns_ops = PROC_I(inode)->ns.ns_ops;
+	ns = PROC_I(inode)->ns.ns;
 	if (ns_ops && ns)
 		ns_ops->put(ns);
 }
@@ -72,8 +73,8 @@
 	ei->pde = NULL;
 	ei->sysctl = NULL;
 	ei->sysctl_entry = NULL;
-	ei->ns = NULL;
-	ei->ns_ops = NULL;
+	ei->ns.ns = NULL;
+	ei->ns.ns_ops = NULL;
 	inode = &ei->vfs_inode;
 	inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
 	return inode;
@@ -129,96 +130,100 @@
 	.show_options	= proc_show_options,
 };
 
-static void __pde_users_dec(struct proc_dir_entry *pde)
+enum {BIAS = -1U<<31};
+
+static inline int use_pde(struct proc_dir_entry *pde)
 {
-	pde->pde_users--;
-	if (pde->pde_unload_completion && pde->pde_users == 0)
+	return atomic_inc_unless_negative(&pde->in_use);
+}
+
+static void unuse_pde(struct proc_dir_entry *pde)
+{
+	if (atomic_dec_return(&pde->in_use) == BIAS)
 		complete(pde->pde_unload_completion);
 }
 
-void pde_users_dec(struct proc_dir_entry *pde)
+/* pde is locked */
+static void close_pdeo(struct proc_dir_entry *pde, struct pde_opener *pdeo)
 {
-	spin_lock(&pde->pde_unload_lock);
-	__pde_users_dec(pde);
-	spin_unlock(&pde->pde_unload_lock);
+	if (pdeo->closing) {
+		/* somebody else is doing that, just wait */
+		DECLARE_COMPLETION_ONSTACK(c);
+		pdeo->c = &c;
+		spin_unlock(&pde->pde_unload_lock);
+		wait_for_completion(&c);
+		spin_lock(&pde->pde_unload_lock);
+	} else {
+		struct file *file;
+		pdeo->closing = 1;
+		spin_unlock(&pde->pde_unload_lock);
+		file = pdeo->file;
+		pde->proc_fops->release(file_inode(file), file);
+		spin_lock(&pde->pde_unload_lock);
+		list_del_init(&pdeo->lh);
+		if (pdeo->c)
+			complete(pdeo->c);
+		kfree(pdeo);
+	}
+}
+
+void proc_entry_rundown(struct proc_dir_entry *de)
+{
+	DECLARE_COMPLETION_ONSTACK(c);
+	/* Wait until all existing callers into module are done. */
+	de->pde_unload_completion = &c;
+	if (atomic_add_return(BIAS, &de->in_use) != BIAS)
+		wait_for_completion(&c);
+
+	spin_lock(&de->pde_unload_lock);
+	while (!list_empty(&de->pde_openers)) {
+		struct pde_opener *pdeo;
+		pdeo = list_first_entry(&de->pde_openers, struct pde_opener, lh);
+		close_pdeo(de, pdeo);
+	}
+	spin_unlock(&de->pde_unload_lock);
 }
 
 static loff_t proc_reg_llseek(struct file *file, loff_t offset, int whence)
 {
 	struct proc_dir_entry *pde = PDE(file_inode(file));
 	loff_t rv = -EINVAL;
-	loff_t (*llseek)(struct file *, loff_t, int);
-
-	spin_lock(&pde->pde_unload_lock);
-	/*
-	 * remove_proc_entry() is going to delete PDE (as part of module
-	 * cleanup sequence). No new callers into module allowed.
-	 */
-	if (!pde->proc_fops) {
-		spin_unlock(&pde->pde_unload_lock);
-		return rv;
+	if (use_pde(pde)) {
+		loff_t (*llseek)(struct file *, loff_t, int);
+		llseek = pde->proc_fops->llseek;
+		if (!llseek)
+			llseek = default_llseek;
+		rv = llseek(file, offset, whence);
+		unuse_pde(pde);
 	}
-	/*
-	 * Bump refcount so that remove_proc_entry will wail for ->llseek to
-	 * complete.
-	 */
-	pde->pde_users++;
-	/*
-	 * Save function pointer under lock, to protect against ->proc_fops
-	 * NULL'ifying right after ->pde_unload_lock is dropped.
-	 */
-	llseek = pde->proc_fops->llseek;
-	spin_unlock(&pde->pde_unload_lock);
-
-	if (!llseek)
-		llseek = default_llseek;
-	rv = llseek(file, offset, whence);
-
-	pde_users_dec(pde);
 	return rv;
 }
 
 static ssize_t proc_reg_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
 {
+	ssize_t (*read)(struct file *, char __user *, size_t, loff_t *);
 	struct proc_dir_entry *pde = PDE(file_inode(file));
 	ssize_t rv = -EIO;
-	ssize_t (*read)(struct file *, char __user *, size_t, loff_t *);
-
-	spin_lock(&pde->pde_unload_lock);
-	if (!pde->proc_fops) {
-		spin_unlock(&pde->pde_unload_lock);
-		return rv;
+	if (use_pde(pde)) {
+		read = pde->proc_fops->read;
+		if (read)
+			rv = read(file, buf, count, ppos);
+		unuse_pde(pde);
 	}
-	pde->pde_users++;
-	read = pde->proc_fops->read;
-	spin_unlock(&pde->pde_unload_lock);
-
-	if (read)
-		rv = read(file, buf, count, ppos);
-
-	pde_users_dec(pde);
 	return rv;
 }
 
 static ssize_t proc_reg_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
 {
+	ssize_t (*write)(struct file *, const char __user *, size_t, loff_t *);
 	struct proc_dir_entry *pde = PDE(file_inode(file));
 	ssize_t rv = -EIO;
-	ssize_t (*write)(struct file *, const char __user *, size_t, loff_t *);
-
-	spin_lock(&pde->pde_unload_lock);
-	if (!pde->proc_fops) {
-		spin_unlock(&pde->pde_unload_lock);
-		return rv;
+	if (use_pde(pde)) {
+		write = pde->proc_fops->write;
+		if (write)
+			rv = write(file, buf, count, ppos);
+		unuse_pde(pde);
 	}
-	pde->pde_users++;
-	write = pde->proc_fops->write;
-	spin_unlock(&pde->pde_unload_lock);
-
-	if (write)
-		rv = write(file, buf, count, ppos);
-
-	pde_users_dec(pde);
 	return rv;
 }
 
@@ -227,20 +232,12 @@
 	struct proc_dir_entry *pde = PDE(file_inode(file));
 	unsigned int rv = DEFAULT_POLLMASK;
 	unsigned int (*poll)(struct file *, struct poll_table_struct *);
-
-	spin_lock(&pde->pde_unload_lock);
-	if (!pde->proc_fops) {
-		spin_unlock(&pde->pde_unload_lock);
-		return rv;
+	if (use_pde(pde)) {
+		poll = pde->proc_fops->poll;
+		if (poll)
+			rv = poll(file, pts);
+		unuse_pde(pde);
 	}
-	pde->pde_users++;
-	poll = pde->proc_fops->poll;
-	spin_unlock(&pde->pde_unload_lock);
-
-	if (poll)
-		rv = poll(file, pts);
-
-	pde_users_dec(pde);
 	return rv;
 }
 
@@ -249,20 +246,12 @@
 	struct proc_dir_entry *pde = PDE(file_inode(file));
 	long rv = -ENOTTY;
 	long (*ioctl)(struct file *, unsigned int, unsigned long);
-
-	spin_lock(&pde->pde_unload_lock);
-	if (!pde->proc_fops) {
-		spin_unlock(&pde->pde_unload_lock);
-		return rv;
+	if (use_pde(pde)) {
+		ioctl = pde->proc_fops->unlocked_ioctl;
+		if (ioctl)
+			rv = ioctl(file, cmd, arg);
+		unuse_pde(pde);
 	}
-	pde->pde_users++;
-	ioctl = pde->proc_fops->unlocked_ioctl;
-	spin_unlock(&pde->pde_unload_lock);
-
-	if (ioctl)
-		rv = ioctl(file, cmd, arg);
-
-	pde_users_dec(pde);
 	return rv;
 }
 
@@ -272,20 +261,12 @@
 	struct proc_dir_entry *pde = PDE(file_inode(file));
 	long rv = -ENOTTY;
 	long (*compat_ioctl)(struct file *, unsigned int, unsigned long);
-
-	spin_lock(&pde->pde_unload_lock);
-	if (!pde->proc_fops) {
-		spin_unlock(&pde->pde_unload_lock);
-		return rv;
+	if (use_pde(pde)) {
+		compat_ioctl = pde->proc_fops->compat_ioctl;
+		if (compat_ioctl)
+			rv = compat_ioctl(file, cmd, arg);
+		unuse_pde(pde);
 	}
-	pde->pde_users++;
-	compat_ioctl = pde->proc_fops->compat_ioctl;
-	spin_unlock(&pde->pde_unload_lock);
-
-	if (compat_ioctl)
-		rv = compat_ioctl(file, cmd, arg);
-
-	pde_users_dec(pde);
 	return rv;
 }
 #endif
@@ -295,20 +276,12 @@
 	struct proc_dir_entry *pde = PDE(file_inode(file));
 	int rv = -EIO;
 	int (*mmap)(struct file *, struct vm_area_struct *);
-
-	spin_lock(&pde->pde_unload_lock);
-	if (!pde->proc_fops) {
-		spin_unlock(&pde->pde_unload_lock);
-		return rv;
+	if (use_pde(pde)) {
+		mmap = pde->proc_fops->mmap;
+		if (mmap)
+			rv = mmap(file, vma);
+		unuse_pde(pde);
 	}
-	pde->pde_users++;
-	mmap = pde->proc_fops->mmap;
-	spin_unlock(&pde->pde_unload_lock);
-
-	if (mmap)
-		rv = mmap(file, vma);
-
-	pde_users_dec(pde);
 	return rv;
 }
 
@@ -330,91 +303,47 @@
 	 * by hand in remove_proc_entry(). For this, save opener's credentials
 	 * for later.
 	 */
-	pdeo = kmalloc(sizeof(struct pde_opener), GFP_KERNEL);
+	pdeo = kzalloc(sizeof(struct pde_opener), GFP_KERNEL);
 	if (!pdeo)
 		return -ENOMEM;
 
-	spin_lock(&pde->pde_unload_lock);
-	if (!pde->proc_fops) {
-		spin_unlock(&pde->pde_unload_lock);
+	if (!use_pde(pde)) {
 		kfree(pdeo);
 		return -ENOENT;
 	}
-	pde->pde_users++;
 	open = pde->proc_fops->open;
 	release = pde->proc_fops->release;
-	spin_unlock(&pde->pde_unload_lock);
 
 	if (open)
 		rv = open(inode, file);
 
-	spin_lock(&pde->pde_unload_lock);
 	if (rv == 0 && release) {
 		/* To know what to release. */
-		pdeo->inode = inode;
 		pdeo->file = file;
 		/* Strictly for "too late" ->release in proc_reg_release(). */
-		pdeo->release = release;
+		spin_lock(&pde->pde_unload_lock);
 		list_add(&pdeo->lh, &pde->pde_openers);
+		spin_unlock(&pde->pde_unload_lock);
 	} else
 		kfree(pdeo);
-	__pde_users_dec(pde);
-	spin_unlock(&pde->pde_unload_lock);
+
+	unuse_pde(pde);
 	return rv;
 }
 
-static struct pde_opener *find_pde_opener(struct proc_dir_entry *pde,
-					struct inode *inode, struct file *file)
-{
-	struct pde_opener *pdeo;
-
-	list_for_each_entry(pdeo, &pde->pde_openers, lh) {
-		if (pdeo->inode == inode && pdeo->file == file)
-			return pdeo;
-	}
-	return NULL;
-}
-
 static int proc_reg_release(struct inode *inode, struct file *file)
 {
 	struct proc_dir_entry *pde = PDE(inode);
-	int rv = 0;
-	int (*release)(struct inode *, struct file *);
 	struct pde_opener *pdeo;
-
 	spin_lock(&pde->pde_unload_lock);
-	pdeo = find_pde_opener(pde, inode, file);
-	if (!pde->proc_fops) {
-		/*
-		 * Can't simply exit, __fput() will think that everything is OK,
-		 * and move on to freeing struct file. remove_proc_entry() will
-		 * find slacker in opener's list and will try to do non-trivial
-		 * things with struct file. Therefore, remove opener from list.
-		 *
-		 * But if opener is removed from list, who will ->release it?
-		 */
-		if (pdeo) {
-			list_del(&pdeo->lh);
-			spin_unlock(&pde->pde_unload_lock);
-			rv = pdeo->release(inode, file);
-			kfree(pdeo);
-		} else
-			spin_unlock(&pde->pde_unload_lock);
-		return rv;
-	}
-	pde->pde_users++;
-	release = pde->proc_fops->release;
-	if (pdeo) {
-		list_del(&pdeo->lh);
-		kfree(pdeo);
+	list_for_each_entry(pdeo, &pde->pde_openers, lh) {
+		if (pdeo->file == file) {
+			close_pdeo(pde, pdeo);
+			break;
+		}
 	}
 	spin_unlock(&pde->pde_unload_lock);
-
-	if (release)
-		rv = release(inode, file);
-
-	pde_users_dec(pde);
-	return rv;
+	return 0;
 }
 
 static const struct file_operations proc_reg_file_ops = {
@@ -462,8 +391,8 @@
 			inode->i_size = de->size;
 		if (de->nlink)
 			set_nlink(inode, de->nlink);
-		if (de->proc_iops)
-			inode->i_op = de->proc_iops;
+		WARN_ON(!de->proc_iops);
+		inode->i_op = de->proc_iops;
 		if (de->proc_fops) {
 			if (S_ISREG(inode->i_mode)) {
 #ifdef CONFIG_COMPAT
@@ -506,5 +435,5 @@
 		return -ENOMEM;
 	}
 
-	return 0;
+	return proc_setup_self(s);
 }
diff --git a/fs/proc/internal.h b/fs/proc/internal.h
index 7571035..d600fb0 100644
--- a/fs/proc/internal.h
+++ b/fs/proc/internal.h
@@ -1,4 +1,4 @@
-/* internal.h: internal procfs definitions
+/* Internal procfs definitions
  *
  * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
  * Written by David Howells (dhowells@redhat.com)
@@ -9,62 +9,83 @@
  * 2 of the License, or (at your option) any later version.
  */
 
-#include <linux/sched.h>
 #include <linux/proc_fs.h>
+#include <linux/proc_ns.h>
+#include <linux/spinlock.h>
+#include <linux/atomic.h>
 #include <linux/binfmts.h>
-struct  ctl_table_header;
-struct  mempolicy;
 
-extern struct proc_dir_entry proc_root;
-extern void proc_self_init(void);
-#ifdef CONFIG_PROC_SYSCTL
-extern int proc_sys_init(void);
-extern void sysctl_head_put(struct ctl_table_header *head);
-#else
-static inline void proc_sys_init(void) { }
-static inline void sysctl_head_put(struct ctl_table_header *head) { }
-#endif
-#ifdef CONFIG_NET
-extern int proc_net_init(void);
-#else
-static inline int proc_net_init(void) { return 0; }
-#endif
+struct ctl_table_header;
+struct mempolicy;
 
-extern int proc_tid_stat(struct seq_file *m, struct pid_namespace *ns,
-				struct pid *pid, struct task_struct *task);
-extern int proc_tgid_stat(struct seq_file *m, struct pid_namespace *ns,
-				struct pid *pid, struct task_struct *task);
-extern int proc_pid_status(struct seq_file *m, struct pid_namespace *ns,
-				struct pid *pid, struct task_struct *task);
-extern int proc_pid_statm(struct seq_file *m, struct pid_namespace *ns,
-				struct pid *pid, struct task_struct *task);
-extern loff_t mem_lseek(struct file *file, loff_t offset, int orig);
-
-extern const struct file_operations proc_tid_children_operations;
-extern const struct file_operations proc_pid_maps_operations;
-extern const struct file_operations proc_tid_maps_operations;
-extern const struct file_operations proc_pid_numa_maps_operations;
-extern const struct file_operations proc_tid_numa_maps_operations;
-extern const struct file_operations proc_pid_smaps_operations;
-extern const struct file_operations proc_tid_smaps_operations;
-extern const struct file_operations proc_clear_refs_operations;
-extern const struct file_operations proc_pagemap_operations;
-extern const struct file_operations proc_net_operations;
-extern const struct inode_operations proc_net_inode_operations;
-extern const struct inode_operations proc_pid_link_inode_operations;
-
-struct proc_maps_private {
-	struct pid *pid;
-	struct task_struct *task;
-#ifdef CONFIG_MMU
-	struct vm_area_struct *tail_vma;
-#endif
-#ifdef CONFIG_NUMA
-	struct mempolicy *task_mempolicy;
-#endif
+/*
+ * This is not completely implemented yet. The idea is to
+ * create an in-memory tree (like the actual /proc filesystem
+ * tree) of these proc_dir_entries, so that we can dynamically
+ * add new files to /proc.
+ *
+ * The "next" pointer creates a linked list of one /proc directory,
+ * while parent/subdir create the directory structure (every
+ * /proc file has a parent, but "subdir" is NULL for all
+ * non-directory entries).
+ */
+struct proc_dir_entry {
+	unsigned int low_ino;
+	umode_t mode;
+	nlink_t nlink;
+	kuid_t uid;
+	kgid_t gid;
+	loff_t size;
+	const struct inode_operations *proc_iops;
+	const struct file_operations *proc_fops;
+	struct proc_dir_entry *next, *parent, *subdir;
+	void *data;
+	atomic_t count;		/* use count */
+	atomic_t in_use;	/* number of callers into module in progress; */
+			/* negative -> it's going away RSN */
+	struct completion *pde_unload_completion;
+	struct list_head pde_openers;	/* who did ->open, but not ->release */
+	spinlock_t pde_unload_lock; /* proc_fops checks and pde_users bumps */
+	u8 namelen;
+	char name[];
 };
 
-void proc_init_inodecache(void);
+union proc_op {
+	int (*proc_get_link)(struct dentry *, struct path *);
+	int (*proc_read)(struct task_struct *task, char *page);
+	int (*proc_show)(struct seq_file *m,
+		struct pid_namespace *ns, struct pid *pid,
+		struct task_struct *task);
+};
+
+struct proc_inode {
+	struct pid *pid;
+	int fd;
+	union proc_op op;
+	struct proc_dir_entry *pde;
+	struct ctl_table_header *sysctl;
+	struct ctl_table *sysctl_entry;
+	struct proc_ns ns;
+	struct inode vfs_inode;
+};
+
+/*
+ * General functions
+ */
+static inline struct proc_inode *PROC_I(const struct inode *inode)
+{
+	return container_of(inode, struct proc_inode, vfs_inode);
+}
+
+static inline struct proc_dir_entry *PDE(const struct inode *inode)
+{
+	return PROC_I(inode)->pde;
+}
+
+static inline void *__PDE_DATA(const struct inode *inode)
+{
+	return PDE(inode)->data;
+}
 
 static inline struct pid *proc_pid(struct inode *inode)
 {
@@ -76,11 +97,6 @@
 	return get_pid_task(proc_pid(inode), PIDTYPE_PID);
 }
 
-static inline int proc_fd(struct inode *inode)
-{
-	return PROC_I(inode)->fd;
-}
-
 static inline int task_dumpable(struct task_struct *task)
 {
 	int dumpable = 0;
@@ -96,15 +112,6 @@
 	return 0;
 }
 
-static inline int pid_delete_dentry(const struct dentry * dentry)
-{
-	/* Is the task we represent dead?
-	 * If so, then don't put the dentry on the lru list,
-	 * kill it immediately.
-	 */
-	return !proc_pid(dentry->d_inode)->tasks[PIDTYPE_PID].first;
-}
-
 static inline unsigned name_to_int(struct dentry *dentry)
 {
 	const char *name = dentry->d_name.name;
@@ -127,63 +134,165 @@
 	return ~0U;
 }
 
-struct dentry *proc_lookup_de(struct proc_dir_entry *de, struct inode *ino,
-		struct dentry *dentry);
-int proc_readdir_de(struct proc_dir_entry *de, struct file *filp, void *dirent,
-		filldir_t filldir);
+/*
+ * Offset of the first process in the /proc root directory..
+ */
+#define FIRST_PROCESS_ENTRY 256
 
-struct pde_opener {
-	struct inode *inode;
-	struct file *file;
-	int (*release)(struct inode *, struct file *);
-	struct list_head lh;
-};
-void pde_users_dec(struct proc_dir_entry *pde);
+/* Worst case buffer size needed for holding an integer. */
+#define PROC_NUMBUF 13
 
+/*
+ * array.c
+ */
+extern const struct file_operations proc_tid_children_operations;
+
+extern int proc_tid_stat(struct seq_file *, struct pid_namespace *,
+			 struct pid *, struct task_struct *);
+extern int proc_tgid_stat(struct seq_file *, struct pid_namespace *,
+			  struct pid *, struct task_struct *);
+extern int proc_pid_status(struct seq_file *, struct pid_namespace *,
+			   struct pid *, struct task_struct *);
+extern int proc_pid_statm(struct seq_file *, struct pid_namespace *,
+			  struct pid *, struct task_struct *);
+
+/*
+ * base.c
+ */
+extern const struct dentry_operations pid_dentry_operations;
+extern int pid_getattr(struct vfsmount *, struct dentry *, struct kstat *);
+extern int proc_setattr(struct dentry *, struct iattr *);
+extern struct inode *proc_pid_make_inode(struct super_block *, struct task_struct *);
+extern int pid_revalidate(struct dentry *, unsigned int);
+extern int pid_delete_dentry(const struct dentry *);
+extern int proc_pid_readdir(struct file *, void *, filldir_t);
+extern struct dentry *proc_pid_lookup(struct inode *, struct dentry *, unsigned int);
+extern loff_t mem_lseek(struct file *, loff_t, int);
+
+/* Lookups */
+typedef struct dentry *instantiate_t(struct inode *, struct dentry *,
+				     struct task_struct *, const void *);
+extern int proc_fill_cache(struct file *, void *, filldir_t, const char *, int,
+			   instantiate_t, struct task_struct *, const void *);
+
+/*
+ * generic.c
+ */
 extern spinlock_t proc_subdir_lock;
 
-struct dentry *proc_pid_lookup(struct inode *dir, struct dentry * dentry, unsigned int);
-int proc_pid_readdir(struct file * filp, void * dirent, filldir_t filldir);
-unsigned long task_vsize(struct mm_struct *);
-unsigned long task_statm(struct mm_struct *,
-	unsigned long *, unsigned long *, unsigned long *, unsigned long *);
-void task_mem(struct seq_file *, struct mm_struct *);
+extern struct dentry *proc_lookup(struct inode *, struct dentry *, unsigned int);
+extern struct dentry *proc_lookup_de(struct proc_dir_entry *, struct inode *,
+				     struct dentry *);
+extern int proc_readdir(struct file *, void *, filldir_t);
+extern int proc_readdir_de(struct proc_dir_entry *, struct file *, void *, filldir_t);
 
 static inline struct proc_dir_entry *pde_get(struct proc_dir_entry *pde)
 {
 	atomic_inc(&pde->count);
 	return pde;
 }
-void pde_put(struct proc_dir_entry *pde);
-
-int proc_fill_super(struct super_block *);
-struct inode *proc_get_inode(struct super_block *, struct proc_dir_entry *);
-int proc_remount(struct super_block *sb, int *flags, char *data);
+extern void pde_put(struct proc_dir_entry *);
 
 /*
- * These are generic /proc routines that use the internal
- * "struct proc_dir_entry" tree to traverse the filesystem.
- *
- * The /proc root directory has extended versions to take care
- * of the /proc/<pid> subdirectories.
+ * inode.c
  */
-int proc_readdir(struct file *, void *, filldir_t);
-struct dentry *proc_lookup(struct inode *, struct dentry *, unsigned int);
+struct pde_opener {
+	struct file *file;
+	struct list_head lh;
+	int closing;
+	struct completion *c;
+};
 
+extern const struct inode_operations proc_pid_link_inode_operations;
 
+extern void proc_init_inodecache(void);
+extern struct inode *proc_get_inode(struct super_block *, struct proc_dir_entry *);
+extern int proc_fill_super(struct super_block *);
+extern void proc_entry_rundown(struct proc_dir_entry *);
 
-/* Lookups */
-typedef struct dentry *instantiate_t(struct inode *, struct dentry *,
-				struct task_struct *, const void *);
-int proc_fill_cache(struct file *filp, void *dirent, filldir_t filldir,
-	const char *name, int len,
-	instantiate_t instantiate, struct task_struct *task, const void *ptr);
-int pid_revalidate(struct dentry *dentry, unsigned int flags);
-struct inode *proc_pid_make_inode(struct super_block * sb, struct task_struct *task);
-extern const struct dentry_operations pid_dentry_operations;
-int pid_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat);
-int proc_setattr(struct dentry *dentry, struct iattr *attr);
+/*
+ * proc_devtree.c
+ */
+#ifdef CONFIG_PROC_DEVICETREE
+extern void proc_device_tree_init(void);
+#endif
 
+/*
+ * proc_namespaces.c
+ */
 extern const struct inode_operations proc_ns_dir_inode_operations;
 extern const struct file_operations proc_ns_dir_operations;
 
+/*
+ * proc_net.c
+ */
+extern const struct file_operations proc_net_operations;
+extern const struct inode_operations proc_net_inode_operations;
+
+#ifdef CONFIG_NET
+extern int proc_net_init(void);
+#else
+static inline int proc_net_init(void) { return 0; }
+#endif
+
+/*
+ * proc_self.c
+ */
+extern int proc_setup_self(struct super_block *);
+
+/*
+ * proc_sysctl.c
+ */
+#ifdef CONFIG_PROC_SYSCTL
+extern int proc_sys_init(void);
+extern void sysctl_head_put(struct ctl_table_header *);
+#else
+static inline void proc_sys_init(void) { }
+static inline void sysctl_head_put(struct ctl_table_header *head) { }
+#endif
+
+/*
+ * proc_tty.c
+ */
+#ifdef CONFIG_TTY
+extern void proc_tty_init(void);
+#else
+static inline void proc_tty_init(void) {}
+#endif
+
+/*
+ * root.c
+ */
+extern struct proc_dir_entry proc_root;
+
+extern void proc_self_init(void);
+extern int proc_remount(struct super_block *, int *, char *);
+
+/*
+ * task_[no]mmu.c
+ */
+struct proc_maps_private {
+	struct pid *pid;
+	struct task_struct *task;
+#ifdef CONFIG_MMU
+	struct vm_area_struct *tail_vma;
+#endif
+#ifdef CONFIG_NUMA
+	struct mempolicy *task_mempolicy;
+#endif
+};
+
+extern const struct file_operations proc_pid_maps_operations;
+extern const struct file_operations proc_tid_maps_operations;
+extern const struct file_operations proc_pid_numa_maps_operations;
+extern const struct file_operations proc_tid_numa_maps_operations;
+extern const struct file_operations proc_pid_smaps_operations;
+extern const struct file_operations proc_tid_smaps_operations;
+extern const struct file_operations proc_clear_refs_operations;
+extern const struct file_operations proc_pagemap_operations;
+
+extern unsigned long task_vsize(struct mm_struct *);
+extern unsigned long task_statm(struct mm_struct *,
+				unsigned long *, unsigned long *,
+				unsigned long *, unsigned long *);
+extern void task_mem(struct seq_file *, struct mm_struct *);
diff --git a/fs/proc/kcore.c b/fs/proc/kcore.c
index f6a13f4..0a22194 100644
--- a/fs/proc/kcore.c
+++ b/fs/proc/kcore.c
@@ -11,6 +11,7 @@
 
 #include <linux/mm.h>
 #include <linux/proc_fs.h>
+#include <linux/kcore.h>
 #include <linux/user.h>
 #include <linux/capability.h>
 #include <linux/elf.h>
@@ -28,6 +29,7 @@
 #include <linux/ioport.h>
 #include <linux/memory.h>
 #include <asm/sections.h>
+#include "internal.h"
 
 #define CORE_STR "CORE"
 
diff --git a/fs/proc/namespaces.c b/fs/proc/namespaces.c
index 66b51c0..54bdc67 100644
--- a/fs/proc/namespaces.c
+++ b/fs/proc/namespaces.c
@@ -51,7 +51,7 @@
 static char *ns_dname(struct dentry *dentry, char *buffer, int buflen)
 {
 	struct inode *inode = dentry->d_inode;
-	const struct proc_ns_operations *ns_ops = PROC_I(inode)->ns_ops;
+	const struct proc_ns_operations *ns_ops = PROC_I(inode)->ns.ns_ops;
 
 	return dynamic_dname(dentry, buffer, buflen, "%s:[%lu]",
 		ns_ops->name, inode->i_ino);
@@ -95,8 +95,8 @@
 		inode->i_op = &ns_inode_operations;
 		inode->i_mode = S_IFREG | S_IRUGO;
 		inode->i_fop = &ns_file_operations;
-		ei->ns_ops = ns_ops;
-		ei->ns = ns;
+		ei->ns.ns_ops = ns_ops;
+		ei->ns.ns = ns;
 		unlock_new_inode(inode);
 	} else {
 		ns_ops->put(ns);
@@ -128,7 +128,7 @@
 	if (!ptrace_may_access(task, PTRACE_MODE_READ))
 		goto out_put_task;
 
-	ns_path.dentry = proc_ns_get_dentry(sb, task, ei->ns_ops);
+	ns_path.dentry = proc_ns_get_dentry(sb, task, ei->ns.ns_ops);
 	if (IS_ERR(ns_path.dentry)) {
 		error = ERR_CAST(ns_path.dentry);
 		goto out_put_task;
@@ -148,7 +148,7 @@
 {
 	struct inode *inode = dentry->d_inode;
 	struct proc_inode *ei = PROC_I(inode);
-	const struct proc_ns_operations *ns_ops = ei->ns_ops;
+	const struct proc_ns_operations *ns_ops = ei->ns.ns_ops;
 	struct task_struct *task;
 	void *ns;
 	char name[50];
@@ -202,7 +202,7 @@
 	ei = PROC_I(inode);
 	inode->i_mode = S_IFLNK|S_IRWXUGO;
 	inode->i_op = &proc_ns_link_inode_operations;
-	ei->ns_ops = ns_ops;
+	ei->ns.ns_ops = ns_ops;
 
 	d_set_d_op(dentry, &pid_dentry_operations);
 	d_add(dentry, inode);
@@ -337,6 +337,11 @@
 	return ERR_PTR(-EINVAL);
 }
 
+struct proc_ns *get_proc_ns(struct inode *inode)
+{
+	return &PROC_I(inode)->ns;
+}
+
 bool proc_ns_inode(struct inode *inode)
 {
 	return inode->i_fop == &ns_file_operations;
diff --git a/fs/proc/proc_devtree.c b/fs/proc/proc_devtree.c
index 30b590f..505afc9 100644
--- a/fs/proc/proc_devtree.c
+++ b/fs/proc/proc_devtree.c
@@ -41,7 +41,7 @@
 
 static int property_proc_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, property_proc_show, PDE(inode)->data);
+	return single_open(file, property_proc_show, __PDE_DATA(inode));
 }
 
 static const struct file_operations property_proc_fops = {
diff --git a/fs/proc/proc_net.c b/fs/proc/proc_net.c
index b4ac657..986e832 100644
--- a/fs/proc/proc_net.c
+++ b/fs/proc/proc_net.c
@@ -26,6 +26,10 @@
 
 #include "internal.h"
 
+static inline struct net *PDE_NET(struct proc_dir_entry *pde)
+{
+	return pde->parent->data;
+}
 
 static struct net *get_proc_net(const struct inode *inode)
 {
diff --git a/fs/proc/root.c b/fs/proc/root.c
index 9c7fab1..41a6ea9 100644
--- a/fs/proc/root.c
+++ b/fs/proc/root.c
@@ -141,6 +141,8 @@
 	struct pid_namespace *ns;
 
 	ns = (struct pid_namespace *)sb->s_fs_info;
+	if (ns->proc_self)
+		dput(ns->proc_self);
 	kill_anon_super(sb);
 	put_pid_ns(ns);
 }
diff --git a/fs/proc/self.c b/fs/proc/self.c
index aa5cc3b..6b6a993 100644
--- a/fs/proc/self.c
+++ b/fs/proc/self.c
@@ -1,6 +1,8 @@
-#include <linux/proc_fs.h>
 #include <linux/sched.h>
 #include <linux/namei.h>
+#include <linux/slab.h>
+#include <linux/pid_namespace.h>
+#include "internal.h"
 
 /*
  * /proc/self:
@@ -48,12 +50,43 @@
 	.put_link	= proc_self_put_link,
 };
 
+static unsigned self_inum;
+
+int proc_setup_self(struct super_block *s)
+{
+	struct inode *root_inode = s->s_root->d_inode;
+	struct pid_namespace *ns = s->s_fs_info;
+	struct dentry *self;
+	
+	mutex_lock(&root_inode->i_mutex);
+	self = d_alloc_name(s->s_root, "self");
+	if (self) {
+		struct inode *inode = new_inode_pseudo(s);
+		if (inode) {
+			inode->i_ino = self_inum;
+			inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
+			inode->i_mode = S_IFLNK | S_IRWXUGO;
+			inode->i_uid = GLOBAL_ROOT_UID;
+			inode->i_gid = GLOBAL_ROOT_GID;
+			inode->i_op = &proc_self_inode_operations;
+			d_add(self, inode);
+		} else {
+			dput(self);
+			self = ERR_PTR(-ENOMEM);
+		}
+	} else {
+		self = ERR_PTR(-ENOMEM);
+	}
+	mutex_unlock(&root_inode->i_mutex);
+	if (IS_ERR(self)) {
+		pr_err("proc_fill_super: can't allocate /proc/self\n");
+		return PTR_ERR(self);
+	}
+	ns->proc_self = self;
+	return 0;
+}
+
 void __init proc_self_init(void)
 {
-	struct proc_dir_entry *proc_self_symlink;
-	mode_t mode;
-
-	mode = S_IFLNK | S_IRWXUGO;
-	proc_self_symlink = proc_create("self", mode, NULL, NULL );
-	proc_self_symlink->proc_iops = &proc_self_inode_operations;
+	proc_alloc_inum(&self_inum);
 }
diff --git a/fs/proc/vmcore.c b/fs/proc/vmcore.c
index b870f74..17f7e08 100644
--- a/fs/proc/vmcore.c
+++ b/fs/proc/vmcore.c
@@ -8,7 +8,7 @@
  */
 
 #include <linux/mm.h>
-#include <linux/proc_fs.h>
+#include <linux/kcore.h>
 #include <linux/user.h>
 #include <linux/elf.h>
 #include <linux/elfcore.h>
@@ -22,6 +22,7 @@
 #include <linux/list.h>
 #include <asm/uaccess.h>
 #include <asm/io.h>
+#include "internal.h"
 
 /* List representing chunks of contiguous memory areas and their offsets in
  * vmcore file.
@@ -698,7 +699,7 @@
 	struct list_head *pos, *next;
 
 	if (proc_vmcore) {
-		remove_proc_entry(proc_vmcore->name, proc_vmcore->parent);
+		proc_remove(proc_vmcore);
 		proc_vmcore = NULL;
 	}
 
diff --git a/fs/read_write.c b/fs/read_write.c
index 8274a79..605dbbc 100644
--- a/fs/read_write.c
+++ b/fs/read_write.c
@@ -459,6 +459,7 @@
 	ret = rw_verify_area(WRITE, file, pos, count);
 	if (ret >= 0) {
 		count = ret;
+		file_start_write(file);
 		if (file->f_op->write)
 			ret = file->f_op->write(file, buf, count, pos);
 		else
@@ -468,6 +469,7 @@
 			add_wchar(current, ret);
 		}
 		inc_syscw(current);
+		file_end_write(file);
 	}
 
 	return ret;
@@ -576,7 +578,7 @@
 }
 EXPORT_SYMBOL(iov_shorten);
 
-ssize_t do_sync_readv_writev(struct file *filp, const struct iovec *iov,
+static ssize_t do_sync_readv_writev(struct file *filp, const struct iovec *iov,
 		unsigned long nr_segs, size_t len, loff_t *ppos, iov_fn_t fn)
 {
 	struct kiocb kiocb;
@@ -601,7 +603,7 @@
 }
 
 /* Do it by hand, with file-ops */
-ssize_t do_loop_readv_writev(struct file *filp, struct iovec *iov,
+static ssize_t do_loop_readv_writev(struct file *filp, struct iovec *iov,
 		unsigned long nr_segs, loff_t *ppos, io_fn_t fn)
 {
 	struct iovec *vector = iov;
@@ -743,6 +745,7 @@
 	} else {
 		fn = (io_fn_t)file->f_op->write;
 		fnv = file->f_op->aio_write;
+		file_start_write(file);
 	}
 
 	if (fnv)
@@ -751,6 +754,9 @@
 	else
 		ret = do_loop_readv_writev(file, iov, nr_segs, pos, fn);
 
+	if (type != READ)
+		file_end_write(file);
+
 out:
 	if (iov != iovstack)
 		kfree(iov);
@@ -881,6 +887,201 @@
 	return ret;
 }
 
+#ifdef CONFIG_COMPAT
+
+static ssize_t compat_do_readv_writev(int type, struct file *file,
+			       const struct compat_iovec __user *uvector,
+			       unsigned long nr_segs, loff_t *pos)
+{
+	compat_ssize_t tot_len;
+	struct iovec iovstack[UIO_FASTIOV];
+	struct iovec *iov = iovstack;
+	ssize_t ret;
+	io_fn_t fn;
+	iov_fn_t fnv;
+
+	ret = -EINVAL;
+	if (!file->f_op)
+		goto out;
+
+	ret = -EFAULT;
+	if (!access_ok(VERIFY_READ, uvector, nr_segs*sizeof(*uvector)))
+		goto out;
+
+	ret = compat_rw_copy_check_uvector(type, uvector, nr_segs,
+					       UIO_FASTIOV, iovstack, &iov);
+	if (ret <= 0)
+		goto out;
+
+	tot_len = ret;
+	ret = rw_verify_area(type, file, pos, tot_len);
+	if (ret < 0)
+		goto out;
+
+	fnv = NULL;
+	if (type == READ) {
+		fn = file->f_op->read;
+		fnv = file->f_op->aio_read;
+	} else {
+		fn = (io_fn_t)file->f_op->write;
+		fnv = file->f_op->aio_write;
+		file_start_write(file);
+	}
+
+	if (fnv)
+		ret = do_sync_readv_writev(file, iov, nr_segs, tot_len,
+						pos, fnv);
+	else
+		ret = do_loop_readv_writev(file, iov, nr_segs, pos, fn);
+
+	if (type != READ)
+		file_end_write(file);
+
+out:
+	if (iov != iovstack)
+		kfree(iov);
+	if ((ret + (type == READ)) > 0) {
+		if (type == READ)
+			fsnotify_access(file);
+		else
+			fsnotify_modify(file);
+	}
+	return ret;
+}
+
+static size_t compat_readv(struct file *file,
+			   const struct compat_iovec __user *vec,
+			   unsigned long vlen, loff_t *pos)
+{
+	ssize_t ret = -EBADF;
+
+	if (!(file->f_mode & FMODE_READ))
+		goto out;
+
+	ret = -EINVAL;
+	if (!file->f_op || (!file->f_op->aio_read && !file->f_op->read))
+		goto out;
+
+	ret = compat_do_readv_writev(READ, file, vec, vlen, pos);
+
+out:
+	if (ret > 0)
+		add_rchar(current, ret);
+	inc_syscr(current);
+	return ret;
+}
+
+COMPAT_SYSCALL_DEFINE3(readv, unsigned long, fd,
+		const struct compat_iovec __user *,vec,
+		unsigned long, vlen)
+{
+	struct fd f = fdget(fd);
+	ssize_t ret;
+	loff_t pos;
+
+	if (!f.file)
+		return -EBADF;
+	pos = f.file->f_pos;
+	ret = compat_readv(f.file, vec, vlen, &pos);
+	f.file->f_pos = pos;
+	fdput(f);
+	return ret;
+}
+
+COMPAT_SYSCALL_DEFINE4(preadv64, unsigned long, fd,
+		const struct compat_iovec __user *,vec,
+		unsigned long, vlen, loff_t, pos)
+{
+	struct fd f;
+	ssize_t ret;
+
+	if (pos < 0)
+		return -EINVAL;
+	f = fdget(fd);
+	if (!f.file)
+		return -EBADF;
+	ret = -ESPIPE;
+	if (f.file->f_mode & FMODE_PREAD)
+		ret = compat_readv(f.file, vec, vlen, &pos);
+	fdput(f);
+	return ret;
+}
+
+COMPAT_SYSCALL_DEFINE5(preadv, unsigned long, fd,
+		const struct compat_iovec __user *,vec,
+		unsigned long, vlen, u32, pos_low, u32, pos_high)
+{
+	loff_t pos = ((loff_t)pos_high << 32) | pos_low;
+	return compat_sys_preadv64(fd, vec, vlen, pos);
+}
+
+static size_t compat_writev(struct file *file,
+			    const struct compat_iovec __user *vec,
+			    unsigned long vlen, loff_t *pos)
+{
+	ssize_t ret = -EBADF;
+
+	if (!(file->f_mode & FMODE_WRITE))
+		goto out;
+
+	ret = -EINVAL;
+	if (!file->f_op || (!file->f_op->aio_write && !file->f_op->write))
+		goto out;
+
+	ret = compat_do_readv_writev(WRITE, file, vec, vlen, pos);
+
+out:
+	if (ret > 0)
+		add_wchar(current, ret);
+	inc_syscw(current);
+	return ret;
+}
+
+COMPAT_SYSCALL_DEFINE3(writev, unsigned long, fd,
+		const struct compat_iovec __user *, vec,
+		unsigned long, vlen)
+{
+	struct fd f = fdget(fd);
+	ssize_t ret;
+	loff_t pos;
+
+	if (!f.file)
+		return -EBADF;
+	pos = f.file->f_pos;
+	ret = compat_writev(f.file, vec, vlen, &pos);
+	f.file->f_pos = pos;
+	fdput(f);
+	return ret;
+}
+
+COMPAT_SYSCALL_DEFINE4(pwritev64, unsigned long, fd,
+		const struct compat_iovec __user *,vec,
+		unsigned long, vlen, loff_t, pos)
+{
+	struct fd f;
+	ssize_t ret;
+
+	if (pos < 0)
+		return -EINVAL;
+	f = fdget(fd);
+	if (!f.file)
+		return -EBADF;
+	ret = -ESPIPE;
+	if (f.file->f_mode & FMODE_PWRITE)
+		ret = compat_writev(f.file, vec, vlen, &pos);
+	fdput(f);
+	return ret;
+}
+
+COMPAT_SYSCALL_DEFINE5(pwritev, unsigned long, fd,
+		const struct compat_iovec __user *,vec,
+		unsigned long, vlen, u32, pos_low, u32, pos_high)
+{
+	loff_t pos = ((loff_t)pos_high << 32) | pos_low;
+	return compat_sys_pwritev64(fd, vec, vlen, pos);
+}
+#endif
+
 static ssize_t do_sendfile(int out_fd, int in_fd, loff_t *ppos,
 		  	   size_t count, loff_t max)
 {
diff --git a/fs/read_write.h b/fs/read_write.h
index d07b954..0ec530d 100644
--- a/fs/read_write.h
+++ b/fs/read_write.h
@@ -7,8 +7,3 @@
 typedef ssize_t (*io_fn_t)(struct file *, char __user *, size_t, loff_t *);
 typedef ssize_t (*iov_fn_t)(struct kiocb *, const struct iovec *,
 		unsigned long, loff_t);
-
-ssize_t do_sync_readv_writev(struct file *filp, const struct iovec *iov,
-		unsigned long nr_segs, size_t len, loff_t *ppos, iov_fn_t fn);
-ssize_t do_loop_readv_writev(struct file *filp, struct iovec *iov,
-		unsigned long nr_segs, loff_t *ppos, io_fn_t fn);
diff --git a/fs/reiserfs/file.c b/fs/reiserfs/file.c
index 6165bd4..dcaafcf 100644
--- a/fs/reiserfs/file.c
+++ b/fs/reiserfs/file.c
@@ -234,68 +234,9 @@
 	return ret;
 }
 
-/* Write @count bytes at position @ppos in a file indicated by @file
-   from the buffer @buf.
-
-   generic_file_write() is only appropriate for filesystems that are not seeking to optimize performance and want
-   something simple that works.  It is not for serious use by general purpose filesystems, excepting the one that it was
-   written for (ext2/3).  This is for several reasons:
-
-   * It has no understanding of any filesystem specific optimizations.
-
-   * It enters the filesystem repeatedly for each page that is written.
-
-   * It depends on reiserfs_get_block() function which if implemented by reiserfs performs costly search_by_key
-   * operation for each page it is supplied with. By contrast reiserfs_file_write() feeds as much as possible at a time
-   * to reiserfs which allows for fewer tree traversals.
-
-   * Each indirect pointer insertion takes a lot of cpu, because it involves memory moves inside of blocks.
-
-   * Asking the block allocation code for blocks one at a time is slightly less efficient.
-
-   All of these reasons for not using only generic file write were understood back when reiserfs was first miscoded to
-   use it, but we were in a hurry to make code freeze, and so it couldn't be revised then.  This new code should make
-   things right finally.
-
-   Future Features: providing search_by_key with hints.
-
-*/
-static ssize_t reiserfs_file_write(struct file *file,	/* the file we are going to write into */
-				   const char __user * buf,	/*  pointer to user supplied data
-								   (in userspace) */
-				   size_t count,	/* amount of bytes to write */
-				   loff_t * ppos	/* pointer to position in file that we start writing at. Should be updated to
-							 * new current position before returning. */
-				   )
-{
-	struct inode *inode = file_inode(file);	// Inode of the file that we are writing to.
-	/* To simplify coding at this time, we store
-	   locked pages in array for now */
-	struct reiserfs_transaction_handle th;
-	th.t_trans_id = 0;
-
-	/* If a filesystem is converted from 3.5 to 3.6, we'll have v3.5 items
-	* lying around (most of the disk, in fact). Despite the filesystem
-	* now being a v3.6 format, the old items still can't support large
-	* file sizes. Catch this case here, as the rest of the VFS layer is
-	* oblivious to the different limitations between old and new items.
-	* reiserfs_setattr catches this for truncates. This chunk is lifted
-	* from generic_write_checks. */
-	if (get_inode_item_key_version (inode) == KEY_FORMAT_3_5 &&
-	    *ppos + count > MAX_NON_LFS) {
-		if (*ppos >= MAX_NON_LFS) {
-			return -EFBIG;
-		}
-		if (count > MAX_NON_LFS - (unsigned long)*ppos)
-			count = MAX_NON_LFS - (unsigned long)*ppos;
-	}
-
-	return do_sync_write(file, buf, count, ppos);
-}
-
 const struct file_operations reiserfs_file_operations = {
 	.read = do_sync_read,
-	.write = reiserfs_file_write,
+	.write = do_sync_write,
 	.unlocked_ioctl = reiserfs_ioctl,
 #ifdef CONFIG_COMPAT
 	.compat_ioctl = reiserfs_compat_ioctl,
diff --git a/fs/reiserfs/procfs.c b/fs/reiserfs/procfs.c
index 9cc0740a..33532f7 100644
--- a/fs/reiserfs/procfs.c
+++ b/fs/reiserfs/procfs.c
@@ -394,20 +394,24 @@
 	return -ENOENT;
 }
 
+struct reiserfs_seq_private {
+	struct super_block *sb;
+	int (*show) (struct seq_file *, struct super_block *);
+};
+
 static void *r_start(struct seq_file *m, loff_t * pos)
 {
-	struct proc_dir_entry *de = m->private;
-	struct super_block *s = de->parent->data;
+	struct reiserfs_seq_private *priv = m->private;
 	loff_t l = *pos;
 
 	if (l)
 		return NULL;
 
-	if (IS_ERR(sget(&reiserfs_fs_type, test_sb, set_sb, 0, s)))
+	if (IS_ERR(sget(&reiserfs_fs_type, test_sb, set_sb, 0, priv->sb)))
 		return NULL;
 
-	up_write(&s->s_umount);
-	return s;
+	up_write(&priv->sb->s_umount);
+	return priv->sb;
 }
 
 static void *r_next(struct seq_file *m, void *v, loff_t * pos)
@@ -426,9 +430,8 @@
 
 static int r_show(struct seq_file *m, void *v)
 {
-	struct proc_dir_entry *de = m->private;
-	int (*show) (struct seq_file *, struct super_block *) = de->data;
-	return show(m, v);
+	struct reiserfs_seq_private *priv = m->private;
+	return priv->show(m, v);
 }
 
 static const struct seq_operations r_ops = {
@@ -440,11 +443,15 @@
 
 static int r_open(struct inode *inode, struct file *file)
 {
-	int ret = seq_open(file, &r_ops);
+	struct reiserfs_seq_private *priv;
+	int ret = seq_open_private(file, &r_ops,
+				   sizeof(struct reiserfs_seq_private));
 
 	if (!ret) {
 		struct seq_file *m = file->private_data;
-		m->private = PDE(inode);
+		priv = m->private;
+		priv->sb = proc_get_parent_data(inode);
+		priv->show = PDE_DATA(inode);
 	}
 	return ret;
 }
@@ -453,7 +460,7 @@
 	.open = r_open,
 	.read = seq_read,
 	.llseek = seq_lseek,
-	.release = seq_release,
+	.release = seq_release_private,
 	.owner = THIS_MODULE,
 };
 
@@ -479,9 +486,8 @@
 		*s = '!';
 
 	spin_lock_init(&__PINFO(sb).lock);
-	REISERFS_SB(sb)->procdir = proc_mkdir(b, proc_info_root);
+	REISERFS_SB(sb)->procdir = proc_mkdir_data(b, 0, proc_info_root, sb);
 	if (REISERFS_SB(sb)->procdir) {
-		REISERFS_SB(sb)->procdir->data = sb;
 		add_file(sb, "version", show_version);
 		add_file(sb, "super", show_super);
 		add_file(sb, "per-level", show_per_level);
@@ -499,29 +505,17 @@
 int reiserfs_proc_info_done(struct super_block *sb)
 {
 	struct proc_dir_entry *de = REISERFS_SB(sb)->procdir;
-	char b[BDEVNAME_SIZE];
-	char *s;
-
-	/* Some block devices use /'s */
-	strlcpy(b, reiserfs_bdevname(sb), BDEVNAME_SIZE);
-	s = strchr(b, '/');
-	if (s)
-		*s = '!';
-
 	if (de) {
-		remove_proc_entry("journal", de);
-		remove_proc_entry("oidmap", de);
-		remove_proc_entry("on-disk-super", de);
-		remove_proc_entry("bitmap", de);
-		remove_proc_entry("per-level", de);
-		remove_proc_entry("super", de);
-		remove_proc_entry("version", de);
-	}
-	spin_lock(&__PINFO(sb).lock);
-	__PINFO(sb).exiting = 1;
-	spin_unlock(&__PINFO(sb).lock);
-	if (proc_info_root) {
-		remove_proc_entry(b, proc_info_root);
+		char b[BDEVNAME_SIZE];
+		char *s;
+
+		/* Some block devices use /'s */
+		strlcpy(b, reiserfs_bdevname(sb), BDEVNAME_SIZE);
+		s = strchr(b, '/');
+		if (s)
+			*s = '!';
+
+		remove_proc_subtree(b, proc_info_root);
 		REISERFS_SB(sb)->procdir = NULL;
 	}
 	return 0;
diff --git a/fs/seq_file.c b/fs/seq_file.c
index 38bb59f..774c1eb 100644
--- a/fs/seq_file.c
+++ b/fs/seq_file.c
@@ -599,6 +599,24 @@
 }
 EXPORT_SYMBOL(single_open);
 
+int single_open_size(struct file *file, int (*show)(struct seq_file *, void *),
+		void *data, size_t size)
+{
+	char *buf = kmalloc(size, GFP_KERNEL);
+	int ret;
+	if (!buf)
+		return -ENOMEM;
+	ret = single_open(file, show, data);
+	if (ret) {
+		kfree(buf);
+		return ret;
+	}
+	((struct seq_file *)file->private_data)->buf = buf;
+	((struct seq_file *)file->private_data)->size = size;
+	return 0;
+}
+EXPORT_SYMBOL(single_open_size);
+
 int single_release(struct inode *inode, struct file *file)
 {
 	const struct seq_operations *op = ((struct seq_file *)file->private_data)->op;
diff --git a/fs/splice.c b/fs/splice.c
index 6b485b8..e6b2559 100644
--- a/fs/splice.c
+++ b/fs/splice.c
@@ -219,7 +219,7 @@
 			page_nr++;
 			ret += buf->len;
 
-			if (pipe->inode)
+			if (pipe->files)
 				do_wakeup = 1;
 
 			if (!--spd->nr_pages)
@@ -829,7 +829,7 @@
 			ops->release(pipe, buf);
 			pipe->curbuf = (pipe->curbuf + 1) & (pipe->buffers - 1);
 			pipe->nrbufs--;
-			if (pipe->inode)
+			if (pipe->files)
 				sd->need_wakeup = true;
 		}
 
@@ -1001,8 +1001,6 @@
 	};
 	ssize_t ret;
 
-	sb_start_write(inode->i_sb);
-
 	pipe_lock(pipe);
 
 	splice_from_pipe_begin(&sd);
@@ -1038,7 +1036,6 @@
 			*ppos += ret;
 		balance_dirty_pages_ratelimited(mapping);
 	}
-	sb_end_write(inode->i_sb);
 
 	return ret;
 }
@@ -1118,7 +1115,10 @@
 	else
 		splice_write = default_file_splice_write;
 
-	return splice_write(pipe, out, ppos, len, flags);
+	file_start_write(out);
+	ret = splice_write(pipe, out, ppos, len, flags);
+	file_end_write(out);
+	return ret;
 }
 
 /*
@@ -1184,7 +1184,7 @@
 	 */
 	pipe = current->splice_pipe;
 	if (unlikely(!pipe)) {
-		pipe = alloc_pipe_info(NULL);
+		pipe = alloc_pipe_info();
 		if (!pipe)
 			return -ENOMEM;
 
diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c
index f03bf1a..3800128 100644
--- a/fs/xfs/xfs_file.c
+++ b/fs/xfs/xfs_file.c
@@ -775,8 +775,6 @@
 	if (ocount == 0)
 		return 0;
 
-	sb_start_write(inode->i_sb);
-
 	if (XFS_FORCED_SHUTDOWN(ip->i_mount)) {
 		ret = -EIO;
 		goto out;
@@ -800,7 +798,6 @@
 	}
 
 out:
-	sb_end_write(inode->i_sb);
 	return ret;
 }
 
diff --git a/include/drm/drmP.h b/include/drm/drmP.h
index 2d94d74..60c33f1 100644
--- a/include/drm/drmP.h
+++ b/include/drm/drmP.h
@@ -1022,7 +1022,7 @@
 struct drm_info_node {
 	struct list_head list;
 	struct drm_minor *minor;
-	struct drm_info_list *info_ent;
+	const struct drm_info_list *info_ent;
 	struct dentry *dent;
 };
 
@@ -1546,8 +1546,7 @@
 extern struct drm_local_map *drm_getsarea(struct drm_device *dev);
 
 				/* Proc support (drm_proc.h) */
-extern int drm_proc_init(struct drm_minor *minor, int minor_id,
-			 struct proc_dir_entry *root);
+extern int drm_proc_init(struct drm_minor *minor, struct proc_dir_entry *root);
 extern int drm_proc_cleanup(struct drm_minor *minor, struct proc_dir_entry *root);
 
 				/* Debugfs support */
diff --git a/include/linux/binfmts.h b/include/linux/binfmts.h
index c3a0914..70cf138 100644
--- a/include/linux/binfmts.h
+++ b/include/linux/binfmts.h
@@ -118,5 +118,6 @@
 extern void install_exec_creds(struct linux_binprm *bprm);
 extern void set_binfmt(struct linux_binfmt *new);
 extern void free_bprm(struct linux_binprm *);
+extern ssize_t read_code(struct file *, unsigned long, loff_t, size_t);
 
 #endif /* _LINUX_BINFMTS_H */
diff --git a/include/linux/cgroup.h b/include/linux/cgroup.h
index 646ab9d..3bff9ce 100644
--- a/include/linux/cgroup.h
+++ b/include/linux/cgroup.h
@@ -39,7 +39,7 @@
 extern int cgroup_load_subsys(struct cgroup_subsys *ss);
 extern void cgroup_unload_subsys(struct cgroup_subsys *ss);
 
-extern const struct file_operations proc_cgroup_operations;
+extern int proc_cgroup_show(struct seq_file *, void *);
 
 /*
  * Define the enumeration of all cgroup subsystems.
diff --git a/include/linux/cpuset.h b/include/linux/cpuset.h
index ccd1de8..cc1b01c 100644
--- a/include/linux/cpuset.h
+++ b/include/linux/cpuset.h
@@ -63,10 +63,9 @@
 extern int cpuset_memory_pressure_enabled;
 extern void __cpuset_memory_pressure_bump(void);
 
-extern const struct file_operations proc_cpuset_operations;
-struct seq_file;
 extern void cpuset_task_status_allowed(struct seq_file *m,
 					struct task_struct *task);
+extern int proc_cpuset_show(struct seq_file *, void *);
 
 extern int cpuset_mem_spread_node(void);
 extern int cpuset_slab_spread_node(void);
diff --git a/include/linux/fdtable.h b/include/linux/fdtable.h
index fb7daca..085197b 100644
--- a/include/linux/fdtable.h
+++ b/include/linux/fdtable.h
@@ -27,7 +27,6 @@
 	unsigned long *close_on_exec;
 	unsigned long *open_fds;
 	struct rcu_head rcu;
-	struct fdtable *next;
 };
 
 static inline bool close_on_exec(int fd, const struct fdtable *fdt)
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 17d8b15..e8cd6b8 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -2082,7 +2082,6 @@
 extern const struct file_operations def_blk_fops;
 extern const struct file_operations def_chr_fops;
 extern const struct file_operations bad_sock_fops;
-extern const struct file_operations def_fifo_fops;
 #ifdef CONFIG_BLOCK
 extern int ioctl_by_bdev(struct block_device *, unsigned, unsigned long);
 extern int blkdev_ioctl(struct block_device *, fmode_t, unsigned, unsigned long);
@@ -2154,10 +2153,6 @@
 extern void make_bad_inode(struct inode *);
 extern int is_bad_inode(struct inode *);
 
-extern const struct file_operations read_pipefifo_fops;
-extern const struct file_operations write_pipefifo_fops;
-extern const struct file_operations rdwr_pipefifo_fops;
-
 #ifdef CONFIG_BLOCK
 /*
  * return READ, READA, or WRITE
@@ -2225,6 +2220,20 @@
 	return f->f_inode;
 }
 
+static inline void file_start_write(struct file *file)
+{
+	if (!S_ISREG(file_inode(file)->i_mode))
+		return;
+	__sb_start_write(file_inode(file)->i_sb, SB_FREEZE_WRITE, true);
+}
+
+static inline void file_end_write(struct file *file)
+{
+	if (!S_ISREG(file_inode(file)->i_mode))
+		return;
+	__sb_end_write(file_inode(file)->i_sb, SB_FREEZE_WRITE);
+}
+
 /*
  * get_write_access() gets write permission for a file.
  * put_write_access() releases this write permission.
diff --git a/include/linux/kcore.h b/include/linux/kcore.h
new file mode 100644
index 0000000..d927622
--- /dev/null
+++ b/include/linux/kcore.h
@@ -0,0 +1,38 @@
+/*
+ * /proc/kcore definitions
+ */
+#ifndef _LINUX_KCORE_H
+#define _LINUX_KCORE_H
+
+enum kcore_type {
+	KCORE_TEXT,
+	KCORE_VMALLOC,
+	KCORE_RAM,
+	KCORE_VMEMMAP,
+	KCORE_OTHER,
+};
+
+struct kcore_list {
+	struct list_head list;
+	unsigned long addr;
+	size_t size;
+	int type;
+};
+
+struct vmcore {
+	struct list_head list;
+	unsigned long long paddr;
+	unsigned long long size;
+	loff_t offset;
+};
+
+#ifdef CONFIG_PROC_KCORE
+extern void kclist_add(struct kcore_list *, void *, size_t, int type);
+#else
+static inline
+void kclist_add(struct kcore_list *new, void *addr, size_t size, int type)
+{
+}
+#endif
+
+#endif /* _LINUX_KCORE_H */
diff --git a/include/linux/nubus.h b/include/linux/nubus.h
index a8696bb..b374052 100644
--- a/include/linux/nubus.h
+++ b/include/linux/nubus.h
@@ -80,7 +80,11 @@
 
 /* Generic NuBus interface functions, modelled after the PCI interface */
 void nubus_scan_bus(void);
+#ifdef CONFIG_PROC_FS
 extern void nubus_proc_init(void);
+#else
+static inline void nubus_proc_init(void) {}
+#endif
 int get_nubus_list(char *buf);
 int nubus_proc_attach_device(struct nubus_dev *dev);
 int nubus_proc_detach_device(struct nubus_dev *dev);
diff --git a/include/linux/of.h b/include/linux/of.h
index a0f1292..2d25ff8 100644
--- a/include/linux/of.h
+++ b/include/linux/of.h
@@ -540,4 +540,14 @@
 	return of_property_read_u32_array(np, propname, out_value, 1);
 }
 
+#if defined(CONFIG_PROC_FS) && defined(CONFIG_PROC_DEVICETREE)
+extern void proc_device_tree_add_node(struct device_node *, struct proc_dir_entry *);
+extern void proc_device_tree_add_prop(struct proc_dir_entry *pde, struct property *prop);
+extern void proc_device_tree_remove_prop(struct proc_dir_entry *pde,
+					 struct property *prop);
+extern void proc_device_tree_update_prop(struct proc_dir_entry *pde,
+					 struct property *newprop,
+					 struct property *oldprop);
+#endif
+
 #endif /* _LINUX_OF_H */
diff --git a/include/linux/pid_namespace.h b/include/linux/pid_namespace.h
index 8ac3283..731e4ec 100644
--- a/include/linux/pid_namespace.h
+++ b/include/linux/pid_namespace.h
@@ -30,6 +30,7 @@
 	struct pid_namespace *parent;
 #ifdef CONFIG_PROC_FS
 	struct vfsmount *proc_mnt;
+	struct dentry *proc_self;
 #endif
 #ifdef CONFIG_BSD_PROCESS_ACCT
 	struct bsd_acct_struct *bacct;
diff --git a/include/linux/pipe_fs_i.h b/include/linux/pipe_fs_i.h
index ad1a427..b8809fe 100644
--- a/include/linux/pipe_fs_i.h
+++ b/include/linux/pipe_fs_i.h
@@ -27,6 +27,7 @@
 
 /**
  *	struct pipe_inode_info - a linux kernel pipe
+ *	@mutex: mutex protecting the whole thing
  *	@wait: reader/writer wait point in case of empty/full pipe
  *	@nrbufs: the number of non-empty pipe buffers in this pipe
  *	@buffers: total number of buffers (should be a power of 2)
@@ -34,26 +35,27 @@
  *	@tmp_page: cached released page
  *	@readers: number of current readers of this pipe
  *	@writers: number of current writers of this pipe
+ *	@files: number of struct file refering this pipe (protected by ->i_lock)
  *	@waiting_writers: number of writers blocked waiting for room
  *	@r_counter: reader counter
  *	@w_counter: writer counter
  *	@fasync_readers: reader side fasync
  *	@fasync_writers: writer side fasync
- *	@inode: inode this pipe is attached to
  *	@bufs: the circular array of pipe buffers
  **/
 struct pipe_inode_info {
+	struct mutex mutex;
 	wait_queue_head_t wait;
 	unsigned int nrbufs, curbuf, buffers;
 	unsigned int readers;
 	unsigned int writers;
+	unsigned int files;
 	unsigned int waiting_writers;
 	unsigned int r_counter;
 	unsigned int w_counter;
 	struct page *tmp_page;
 	struct fasync_struct *fasync_readers;
 	struct fasync_struct *fasync_writers;
-	struct inode *inode;
 	struct pipe_buffer *bufs;
 };
 
@@ -144,9 +146,8 @@
 /* Drop the inode semaphore and wait for a pipe event, atomically */
 void pipe_wait(struct pipe_inode_info *pipe);
 
-struct pipe_inode_info * alloc_pipe_info(struct inode * inode);
-void free_pipe_info(struct inode * inode);
-void __free_pipe_info(struct pipe_inode_info *);
+struct pipe_inode_info *alloc_pipe_info(void);
+void free_pipe_info(struct pipe_inode_info *);
 
 /* Generic pipe buffer ops functions */
 void *generic_pipe_buf_map(struct pipe_inode_info *, struct pipe_buffer *, int);
diff --git a/include/linux/proc_fs.h b/include/linux/proc_fs.h
index 94dfb2a..608e60a 100644
--- a/include/linux/proc_fs.h
+++ b/include/linux/proc_fs.h
@@ -1,318 +1,79 @@
-#ifndef _LINUX_PROC_FS_H
-#define _LINUX_PROC_FS_H
-
-#include <linux/slab.h>
-#include <linux/fs.h>
-#include <linux/spinlock.h>
-#include <linux/magic.h>
-#include <linux/atomic.h>
-
-struct net;
-struct completion;
-struct mm_struct;
-
 /*
  * The proc filesystem constants/structures
  */
+#ifndef _LINUX_PROC_FS_H
+#define _LINUX_PROC_FS_H
 
-/*
- * Offset of the first process in the /proc root directory..
- */
-#define FIRST_PROCESS_ENTRY 256
+#include <linux/types.h>
+#include <linux/fs.h>
 
-/* Worst case buffer size needed for holding an integer. */
-#define PROC_NUMBUF 13
-
-/*
- * We always define these enumerators
- */
-
-enum {
-	PROC_ROOT_INO		= 1,
-	PROC_IPC_INIT_INO	= 0xEFFFFFFFU,
-	PROC_UTS_INIT_INO	= 0xEFFFFFFEU,
-	PROC_USER_INIT_INO	= 0xEFFFFFFDU,
-	PROC_PID_INIT_INO	= 0xEFFFFFFCU,
-};
-
-/*
- * This is not completely implemented yet. The idea is to
- * create an in-memory tree (like the actual /proc filesystem
- * tree) of these proc_dir_entries, so that we can dynamically
- * add new files to /proc.
- *
- * The "next" pointer creates a linked list of one /proc directory,
- * while parent/subdir create the directory structure (every
- * /proc file has a parent, but "subdir" is NULL for all
- * non-directory entries).
- */
-
-typedef	int (read_proc_t)(char *page, char **start, off_t off,
-			  int count, int *eof, void *data);
-typedef	int (write_proc_t)(struct file *file, const char __user *buffer,
-			   unsigned long count, void *data);
-
-struct proc_dir_entry {
-	unsigned int low_ino;
-	umode_t mode;
-	nlink_t nlink;
-	kuid_t uid;
-	kgid_t gid;
-	loff_t size;
-	const struct inode_operations *proc_iops;
-	/*
-	 * NULL ->proc_fops means "PDE is going away RSN" or
-	 * "PDE is just created". In either case, e.g. ->read_proc won't be
-	 * called because it's too late or too early, respectively.
-	 *
-	 * If you're allocating ->proc_fops dynamically, save a pointer
-	 * somewhere.
-	 */
-	const struct file_operations *proc_fops;
-	struct proc_dir_entry *next, *parent, *subdir;
-	void *data;
-	read_proc_t *read_proc;
-	write_proc_t *write_proc;
-	atomic_t count;		/* use count */
-	int pde_users;	/* number of callers into module in progress */
-	struct completion *pde_unload_completion;
-	struct list_head pde_openers;	/* who did ->open, but not ->release */
-	spinlock_t pde_unload_lock; /* proc_fops checks and pde_users bumps */
-	u8 namelen;
-	char name[];
-};
-
-enum kcore_type {
-	KCORE_TEXT,
-	KCORE_VMALLOC,
-	KCORE_RAM,
-	KCORE_VMEMMAP,
-	KCORE_OTHER,
-};
-
-struct kcore_list {
-	struct list_head list;
-	unsigned long addr;
-	size_t size;
-	int type;
-};
-
-struct vmcore {
-	struct list_head list;
-	unsigned long long paddr;
-	unsigned long long size;
-	loff_t offset;
-};
+struct proc_dir_entry;
 
 #ifdef CONFIG_PROC_FS
 
 extern void proc_root_init(void);
-
-void proc_flush_task(struct task_struct *task);
-
-extern struct proc_dir_entry *create_proc_entry(const char *name, umode_t mode,
-						struct proc_dir_entry *parent);
-struct proc_dir_entry *proc_create_data(const char *name, umode_t mode,
-				struct proc_dir_entry *parent,
-				const struct file_operations *proc_fops,
-				void *data);
-extern void remove_proc_entry(const char *name, struct proc_dir_entry *parent);
-extern int remove_proc_subtree(const char *name, struct proc_dir_entry *parent);
-
-struct pid_namespace;
-
-extern int pid_ns_prepare_proc(struct pid_namespace *ns);
-extern void pid_ns_release_proc(struct pid_namespace *ns);
-
-/*
- * proc_tty.c
- */
-struct tty_driver;
-#ifdef CONFIG_TTY
-extern void proc_tty_init(void);
-#else
-static inline void proc_tty_init(void)
-{ }
-#endif
-extern void proc_tty_register_driver(struct tty_driver *driver);
-extern void proc_tty_unregister_driver(struct tty_driver *driver);
-
-/*
- * proc_devtree.c
- */
-#ifdef CONFIG_PROC_DEVICETREE
-struct device_node;
-struct property;
-extern void proc_device_tree_init(void);
-extern void proc_device_tree_add_node(struct device_node *, struct proc_dir_entry *);
-extern void proc_device_tree_add_prop(struct proc_dir_entry *pde, struct property *prop);
-extern void proc_device_tree_remove_prop(struct proc_dir_entry *pde,
-					 struct property *prop);
-extern void proc_device_tree_update_prop(struct proc_dir_entry *pde,
-					 struct property *newprop,
-					 struct property *oldprop);
-#endif /* CONFIG_PROC_DEVICETREE */
+extern void proc_flush_task(struct task_struct *);
 
 extern struct proc_dir_entry *proc_symlink(const char *,
 		struct proc_dir_entry *, const char *);
-extern struct proc_dir_entry *proc_mkdir(const char *,struct proc_dir_entry *);
-extern struct proc_dir_entry *proc_mkdir_mode(const char *name, umode_t mode,
-			struct proc_dir_entry *parent);
+extern struct proc_dir_entry *proc_mkdir(const char *, struct proc_dir_entry *);
+extern struct proc_dir_entry *proc_mkdir_data(const char *, umode_t,
+					      struct proc_dir_entry *, void *);
+extern struct proc_dir_entry *proc_mkdir_mode(const char *, umode_t,
+					      struct proc_dir_entry *);
+ 
+extern struct proc_dir_entry *proc_create_data(const char *, umode_t,
+					       struct proc_dir_entry *,
+					       const struct file_operations *,
+					       void *);
 
-static inline struct proc_dir_entry *proc_create(const char *name, umode_t mode,
-	struct proc_dir_entry *parent, const struct file_operations *proc_fops)
+static inline struct proc_dir_entry *proc_create(
+	const char *name, umode_t mode, struct proc_dir_entry *parent,
+	const struct file_operations *proc_fops)
 {
 	return proc_create_data(name, mode, parent, proc_fops, NULL);
 }
 
-static inline struct proc_dir_entry *create_proc_read_entry(const char *name,
-	umode_t mode, struct proc_dir_entry *base, 
-	read_proc_t *read_proc, void * data)
-{
-	struct proc_dir_entry *res=create_proc_entry(name,mode,base);
-	if (res) {
-		res->read_proc=read_proc;
-		res->data=data;
-	}
-	return res;
-}
- 
-extern struct proc_dir_entry *proc_net_mkdir(struct net *net, const char *name,
-	struct proc_dir_entry *parent);
+extern void proc_set_size(struct proc_dir_entry *, loff_t);
+extern void proc_set_user(struct proc_dir_entry *, kuid_t, kgid_t);
+extern void *PDE_DATA(const struct inode *);
+extern void *proc_get_parent_data(const struct inode *);
+extern void proc_remove(struct proc_dir_entry *);
+extern void remove_proc_entry(const char *, struct proc_dir_entry *);
+extern int remove_proc_subtree(const char *, struct proc_dir_entry *);
 
-extern struct file *proc_ns_fget(int fd);
-extern bool proc_ns_inode(struct inode *inode);
-
-extern int proc_alloc_inum(unsigned int *pino);
-extern void proc_free_inum(unsigned int inum);
-#else
+#else /* CONFIG_PROC_FS */
 
 static inline void proc_flush_task(struct task_struct *task)
 {
 }
 
-static inline struct proc_dir_entry *create_proc_entry(const char *name,
-	umode_t mode, struct proc_dir_entry *parent) { return NULL; }
-
-#define proc_create(name, mode, parent, fops)  ({ (void)(mode), NULL; })
-
-static inline struct proc_dir_entry *proc_create_data(const char *name,
-	umode_t mode, struct proc_dir_entry *parent,
-	const struct file_operations *proc_fops, void *data)
-{
-	return NULL;
-}
-#define remove_proc_entry(name, parent) do {} while (0)
-#define remove_proc_subtree(name, parent) do {} while (0)
-
 static inline struct proc_dir_entry *proc_symlink(const char *name,
-		struct proc_dir_entry *parent,const char *dest) {return NULL;}
+		struct proc_dir_entry *parent,const char *dest) { return NULL;}
 static inline struct proc_dir_entry *proc_mkdir(const char *name,
 	struct proc_dir_entry *parent) {return NULL;}
+static inline struct proc_dir_entry *proc_mkdir_data(const char *name,
+	umode_t mode, struct proc_dir_entry *parent, void *data) { return NULL; }
 static inline struct proc_dir_entry *proc_mkdir_mode(const char *name,
 	umode_t mode, struct proc_dir_entry *parent) { return NULL; }
+#define proc_create(name, mode, parent, proc_fops) ({NULL;})
+#define proc_create_data(name, mode, parent, proc_fops, data) ({NULL;})
 
-static inline struct proc_dir_entry *create_proc_read_entry(const char *name,
-	umode_t mode, struct proc_dir_entry *base, 
-	read_proc_t *read_proc, void * data) { return NULL; }
+static inline void proc_set_size(struct proc_dir_entry *de, loff_t size) {}
+static inline void proc_set_user(struct proc_dir_entry *de, kuid_t uid, kgid_t gid) {}
+static inline void *PDE_DATA(const struct inode *inode) {BUG(); return NULL;}
+static inline void *proc_get_parent_data(const struct inode *inode) { BUG(); return NULL; }
 
-struct tty_driver;
-static inline void proc_tty_register_driver(struct tty_driver *driver) {};
-static inline void proc_tty_unregister_driver(struct tty_driver *driver) {};
+static inline void proc_remove(struct proc_dir_entry *de) {}
+#define remove_proc_entry(name, parent) do {} while (0)
+static inline int remove_proc_subtree(const char *name, struct proc_dir_entry *parent) { return 0; }
 
-static inline int pid_ns_prepare_proc(struct pid_namespace *ns)
-{
-	return 0;
-}
-
-static inline void pid_ns_release_proc(struct pid_namespace *ns)
-{
-}
-
-static inline struct file *proc_ns_fget(int fd)
-{
-	return ERR_PTR(-EINVAL);
-}
-
-static inline bool proc_ns_inode(struct inode *inode)
-{
-	return false;
-}
-
-static inline int proc_alloc_inum(unsigned int *inum)
-{
-	*inum = 1;
-	return 0;
-}
-static inline void proc_free_inum(unsigned int inum)
-{
-}
 #endif /* CONFIG_PROC_FS */
 
-#if !defined(CONFIG_PROC_KCORE)
-static inline void
-kclist_add(struct kcore_list *new, void *addr, size_t size, int type)
+static inline struct proc_dir_entry *proc_net_mkdir(
+	struct net *net, const char *name, struct proc_dir_entry *parent)
 {
-}
-#else
-extern void kclist_add(struct kcore_list *, void *, size_t, int type);
-#endif
-
-struct nsproxy;
-struct proc_ns_operations {
-	const char *name;
-	int type;
-	void *(*get)(struct task_struct *task);
-	void (*put)(void *ns);
-	int (*install)(struct nsproxy *nsproxy, void *ns);
-	unsigned int (*inum)(void *ns);
-};
-extern const struct proc_ns_operations netns_operations;
-extern const struct proc_ns_operations utsns_operations;
-extern const struct proc_ns_operations ipcns_operations;
-extern const struct proc_ns_operations pidns_operations;
-extern const struct proc_ns_operations userns_operations;
-extern const struct proc_ns_operations mntns_operations;
-
-union proc_op {
-	int (*proc_get_link)(struct dentry *, struct path *);
-	int (*proc_read)(struct task_struct *task, char *page);
-	int (*proc_show)(struct seq_file *m,
-		struct pid_namespace *ns, struct pid *pid,
-		struct task_struct *task);
-};
-
-struct ctl_table_header;
-struct ctl_table;
-
-struct proc_inode {
-	struct pid *pid;
-	int fd;
-	union proc_op op;
-	struct proc_dir_entry *pde;
-	struct ctl_table_header *sysctl;
-	struct ctl_table *sysctl_entry;
-	void *ns;
-	const struct proc_ns_operations *ns_ops;
-	struct inode vfs_inode;
-};
-
-static inline struct proc_inode *PROC_I(const struct inode *inode)
-{
-	return container_of(inode, struct proc_inode, vfs_inode);
+	return proc_mkdir_data(name, 0, parent, net);
 }
 
-static inline struct proc_dir_entry *PDE(const struct inode *inode)
-{
-	return PROC_I(inode)->pde;
-}
-
-static inline struct net *PDE_NET(struct proc_dir_entry *pde)
-{
-	return pde->parent->data;
-}
-
-#include <linux/signal.h>
-
-void render_sigset_t(struct seq_file *m, const char *header, sigset_t *set);
 #endif /* _LINUX_PROC_FS_H */
diff --git a/include/linux/proc_ns.h b/include/linux/proc_ns.h
new file mode 100644
index 0000000..34a1e10
--- /dev/null
+++ b/include/linux/proc_ns.h
@@ -0,0 +1,74 @@
+/*
+ * procfs namespace bits
+ */
+#ifndef _LINUX_PROC_NS_H
+#define _LINUX_PROC_NS_H
+
+struct pid_namespace;
+struct nsproxy;
+
+struct proc_ns_operations {
+	const char *name;
+	int type;
+	void *(*get)(struct task_struct *task);
+	void (*put)(void *ns);
+	int (*install)(struct nsproxy *nsproxy, void *ns);
+	unsigned int (*inum)(void *ns);
+};
+
+struct proc_ns {
+	void *ns;
+	const struct proc_ns_operations *ns_ops;
+};
+
+extern const struct proc_ns_operations netns_operations;
+extern const struct proc_ns_operations utsns_operations;
+extern const struct proc_ns_operations ipcns_operations;
+extern const struct proc_ns_operations pidns_operations;
+extern const struct proc_ns_operations userns_operations;
+extern const struct proc_ns_operations mntns_operations;
+
+/*
+ * We always define these enumerators
+ */
+enum {
+	PROC_ROOT_INO		= 1,
+	PROC_IPC_INIT_INO	= 0xEFFFFFFFU,
+	PROC_UTS_INIT_INO	= 0xEFFFFFFEU,
+	PROC_USER_INIT_INO	= 0xEFFFFFFDU,
+	PROC_PID_INIT_INO	= 0xEFFFFFFCU,
+};
+
+#ifdef CONFIG_PROC_FS
+
+extern int pid_ns_prepare_proc(struct pid_namespace *ns);
+extern void pid_ns_release_proc(struct pid_namespace *ns);
+extern struct file *proc_ns_fget(int fd);
+extern struct proc_ns *get_proc_ns(struct inode *);
+extern int proc_alloc_inum(unsigned int *pino);
+extern void proc_free_inum(unsigned int inum);
+extern bool proc_ns_inode(struct inode *inode);
+
+#else /* CONFIG_PROC_FS */
+
+static inline int pid_ns_prepare_proc(struct pid_namespace *ns) { return 0; }
+static inline void pid_ns_release_proc(struct pid_namespace *ns) {}
+
+static inline struct file *proc_ns_fget(int fd)
+{
+	return ERR_PTR(-EINVAL);
+}
+
+static inline struct proc_ns *get_proc_ns(struct inode *inode) { return NULL; }
+
+static inline int proc_alloc_inum(unsigned int *inum)
+{
+	*inum = 1;
+	return 0;
+}
+static inline void proc_free_inum(unsigned int inum) {}
+static inline bool proc_ns_inode(struct inode *inode) { return false; }
+
+#endif /* CONFIG_PROC_FS */
+
+#endif /* _LINUX_PROC_NS_H */
diff --git a/include/linux/profile.h b/include/linux/profile.h
index 2112390..aaad386 100644
--- a/include/linux/profile.h
+++ b/include/linux/profile.h
@@ -18,10 +18,10 @@
 struct notifier_block;
 
 #if defined(CONFIG_PROFILING) && defined(CONFIG_PROC_FS)
-void create_prof_cpu_mask(struct proc_dir_entry *de);
+void create_prof_cpu_mask(void);
 int create_proc_profile(void);
 #else
-static inline void create_prof_cpu_mask(struct proc_dir_entry *de)
+static inline void create_prof_cpu_mask(void)
 {
 }
 
diff --git a/include/linux/seq_file.h b/include/linux/seq_file.h
index 68a04a3..2da29ac 100644
--- a/include/linux/seq_file.h
+++ b/include/linux/seq_file.h
@@ -123,6 +123,7 @@
 }
 
 int single_open(struct file *, int (*)(struct seq_file *, void *), void *);
+int single_open_size(struct file *, int (*)(struct seq_file *, void *), void *, size_t);
 int single_release(struct inode *, struct file *);
 void *__seq_open_private(struct file *, const struct seq_operations *, int);
 int seq_open_private(struct file *, const struct seq_operations *, int);
diff --git a/include/linux/signal.h b/include/linux/signal.h
index 9475c5c..d897484 100644
--- a/include/linux/signal.h
+++ b/include/linux/signal.h
@@ -434,4 +434,9 @@
 int restore_altstack(const stack_t __user *);
 int __save_altstack(stack_t __user *, unsigned long);
 
+#ifdef CONFIG_PROC_FS
+struct seq_file;
+extern void render_sigset_t(struct seq_file *, const char *, sigset_t *);
+#endif
+
 #endif /* _LINUX_SIGNAL_H */
diff --git a/include/linux/tty.h b/include/linux/tty.h
index 367a9df..7e92bd8 100644
--- a/include/linux/tty.h
+++ b/include/linux/tty.h
@@ -691,5 +691,12 @@
 	finish_wait(&wq, &__wait);					\
 } while (0)
 
+#ifdef CONFIG_PROC_FS
+extern void proc_tty_register_driver(struct tty_driver *);
+extern void proc_tty_unregister_driver(struct tty_driver *);
+#else
+static inline void proc_tty_register_driver(struct tty_driver *d) {}
+static inline void proc_tty_unregister_driver(struct tty_driver *d) {}
+#endif
 
 #endif
diff --git a/include/net/bluetooth/bluetooth.h b/include/net/bluetooth/bluetooth.h
index 6912ef9..10eb9b3 100644
--- a/include/net/bluetooth/bluetooth.h
+++ b/include/net/bluetooth/bluetooth.h
@@ -226,7 +226,6 @@
 	struct hlist_head head;
 	rwlock_t          lock;
 #ifdef CONFIG_PROC_FS
-        struct file_operations   fops;
         int (* custom_seq_show)(struct seq_file *, void *);
 #endif
 };
@@ -330,7 +329,7 @@
 extern int bt_sysfs_init(void);
 extern void bt_sysfs_cleanup(void);
 
-extern int  bt_procfs_init(struct module* module, struct net *net, const char *name,
+extern int  bt_procfs_init(struct net *net, const char *name,
 			   struct bt_sock_list* sk_list,
 			   int (* seq_show)(struct seq_file *, void *));
 extern void bt_procfs_cleanup(struct net *net, const char *name);
diff --git a/include/net/lib80211.h b/include/net/lib80211.h
index d178c26..be95b92 100644
--- a/include/net/lib80211.h
+++ b/include/net/lib80211.h
@@ -30,6 +30,8 @@
 #include <linux/skbuff.h>
 #include <linux/ieee80211.h>
 #include <linux/timer.h>
+#include <linux/seq_file.h>
+
 /* print_ssid() is intended to be used in debug (and possibly error)
  * messages. It should never be used for passing ssid to user space. */
 const char *print_ssid(char *buf, const char *ssid, u8 ssid_len);
@@ -75,7 +77,7 @@
 
 	/* procfs handler for printing out key information and possible
 	 * statistics */
-	char *(*print_stats) (char *p, void *priv);
+	void (*print_stats) (struct seq_file *m, void *priv);
 
 	/* Crypto specific flag get/set for configuration settings */
 	unsigned long (*get_flags) (void *priv);
diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h
index 2b6956e..7552435 100644
--- a/include/scsi/scsi_host.h
+++ b/include/scsi/scsi_host.h
@@ -6,6 +6,7 @@
 #include <linux/types.h>
 #include <linux/workqueue.h>
 #include <linux/mutex.h>
+#include <linux/seq_file.h>
 #include <scsi/scsi.h>
 
 struct request_queue;
@@ -340,7 +341,8 @@
 	 *
 	 * Status: OBSOLETE
 	 */
-	int (*proc_info)(struct Scsi_Host *, char *, char **, off_t, int, int);
+	int (*show_info)(struct seq_file *, struct Scsi_Host *);
+	int (*write_info)(struct Scsi_Host *, char *, int);
 
 	/*
 	 * This is an optional routine that allows the transport to become
@@ -375,7 +377,7 @@
 
 	/*
 	 * Used to store the procfs directory if a driver implements the
-	 * proc_info method.
+	 * show_info method.
 	 */
 	struct proc_dir_entry *proc_dir;
 
diff --git a/init/version.c b/init/version.c
index 58170f1..1a4718e 100644
--- a/init/version.c
+++ b/init/version.c
@@ -12,7 +12,7 @@
 #include <linux/utsname.h>
 #include <generated/utsrelease.h>
 #include <linux/version.h>
-#include <linux/proc_fs.h>
+#include <linux/proc_ns.h>
 
 #ifndef CONFIG_KALLSYMS
 #define version(a) Version_ ## a
diff --git a/ipc/msgutil.c b/ipc/msgutil.c
index d43439e..491e71f 100644
--- a/ipc/msgutil.c
+++ b/ipc/msgutil.c
@@ -16,7 +16,7 @@
 #include <linux/msg.h>
 #include <linux/ipc_namespace.h>
 #include <linux/utsname.h>
-#include <linux/proc_fs.h>
+#include <linux/proc_ns.h>
 #include <linux/uaccess.h>
 
 #include "util.h"
diff --git a/ipc/namespace.c b/ipc/namespace.c
index 7c1fa45..7ee61bf 100644
--- a/ipc/namespace.c
+++ b/ipc/namespace.c
@@ -12,7 +12,7 @@
 #include <linux/fs.h>
 #include <linux/mount.h>
 #include <linux/user_namespace.h>
-#include <linux/proc_fs.h>
+#include <linux/proc_ns.h>
 
 #include "util.h"
 
diff --git a/ipc/util.c b/ipc/util.c
index 579201e..abfc13e 100644
--- a/ipc/util.c
+++ b/ipc/util.c
@@ -1031,7 +1031,7 @@
 	seq = file->private_data;
 	seq->private = iter;
 
-	iter->iface = PDE(inode)->data;
+	iter->iface = PDE_DATA(inode);
 	iter->ns    = get_ipc_ns(current->nsproxy->ipc_ns);
 out:
 	return ret;
diff --git a/kernel/acct.c b/kernel/acct.c
index b9bd7f0..85389fe 100644
--- a/kernel/acct.c
+++ b/kernel/acct.c
@@ -543,6 +543,7 @@
 	 * Kernel segment override to datasegment and write it
 	 * to the accounting file.
 	 */
+	file_start_write(file);
 	fs = get_fs();
 	set_fs(KERNEL_DS);
 	/*
@@ -554,6 +555,7 @@
 			       sizeof(acct_t), &file->f_pos);
 	current->signal->rlim[RLIMIT_FSIZE].rlim_cur = flim;
 	set_fs(fs);
+	file_end_write(file);
 out:
 	revert_creds(orig_cred);
 }
diff --git a/kernel/cgroup.c b/kernel/cgroup.c
index d3abce2..2a99262 100644
--- a/kernel/cgroup.c
+++ b/kernel/cgroup.c
@@ -4678,7 +4678,7 @@
  */
 
 /* TODO: Use a proper seq_file iterator */
-static int proc_cgroup_show(struct seq_file *m, void *v)
+int proc_cgroup_show(struct seq_file *m, void *v)
 {
 	struct pid *pid;
 	struct task_struct *tsk;
@@ -4730,19 +4730,6 @@
 	return retval;
 }
 
-static int cgroup_open(struct inode *inode, struct file *file)
-{
-	struct pid *pid = PROC_I(inode)->pid;
-	return single_open(file, proc_cgroup_show, pid);
-}
-
-const struct file_operations proc_cgroup_operations = {
-	.open		= cgroup_open,
-	.read		= seq_read,
-	.llseek		= seq_lseek,
-	.release	= single_release,
-};
-
 /* Display information about each subsystem and each hierarchy */
 static int proc_cgroupstats_show(struct seq_file *m, void *v)
 {
diff --git a/kernel/configs.c b/kernel/configs.c
index 42e8fa0..c18b1f1 100644
--- a/kernel/configs.c
+++ b/kernel/configs.c
@@ -79,7 +79,7 @@
 	if (!entry)
 		return -ENOMEM;
 
-	entry->size = kernel_config_data_size;
+	proc_set_size(entry, kernel_config_data_size);
 
 	return 0;
 }
diff --git a/kernel/cpuset.c b/kernel/cpuset.c
index 1233112..64b3f79 100644
--- a/kernel/cpuset.c
+++ b/kernel/cpuset.c
@@ -2609,7 +2609,7 @@
  *    and we take cpuset_mutex, keeping cpuset_attach() from changing it
  *    anyway.
  */
-static int proc_cpuset_show(struct seq_file *m, void *unused_v)
+int proc_cpuset_show(struct seq_file *m, void *unused_v)
 {
 	struct pid *pid;
 	struct task_struct *tsk;
@@ -2643,19 +2643,6 @@
 out:
 	return retval;
 }
-
-static int cpuset_open(struct inode *inode, struct file *file)
-{
-	struct pid *pid = PROC_I(inode)->pid;
-	return single_open(file, proc_cpuset_show, pid);
-}
-
-const struct file_operations proc_cpuset_operations = {
-	.open		= cpuset_open,
-	.read		= seq_read,
-	.llseek		= seq_lseek,
-	.release	= single_release,
-};
 #endif /* CONFIG_PROC_PID_CPUSET */
 
 /* Display task mems_allowed in /proc/<pid>/status file. */
diff --git a/kernel/exit.c b/kernel/exit.c
index 6e3151e..af2eb3c 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -847,7 +847,7 @@
 		exit_io_context(tsk);
 
 	if (tsk->splice_pipe)
-		__free_pipe_info(tsk->splice_pipe);
+		free_pipe_info(tsk->splice_pipe);
 
 	if (tsk->task_frag.page)
 		put_page(tsk->task_frag.page);
diff --git a/kernel/irq/proc.c b/kernel/irq/proc.c
index 397db02..19ed5c4 100644
--- a/kernel/irq/proc.c
+++ b/kernel/irq/proc.c
@@ -76,7 +76,7 @@
 static ssize_t write_irq_affinity(int type, struct file *file,
 		const char __user *buffer, size_t count, loff_t *pos)
 {
-	unsigned int irq = (int)(long)PDE(file_inode(file))->data;
+	unsigned int irq = (int)(long)PDE_DATA(file_inode(file));
 	cpumask_var_t new_value;
 	int err;
 
@@ -131,17 +131,17 @@
 
 static int irq_affinity_proc_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, irq_affinity_proc_show, PDE(inode)->data);
+	return single_open(file, irq_affinity_proc_show, PDE_DATA(inode));
 }
 
 static int irq_affinity_list_proc_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, irq_affinity_list_proc_show, PDE(inode)->data);
+	return single_open(file, irq_affinity_list_proc_show, PDE_DATA(inode));
 }
 
 static int irq_affinity_hint_proc_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, irq_affinity_hint_proc_show, PDE(inode)->data);
+	return single_open(file, irq_affinity_hint_proc_show, PDE_DATA(inode));
 }
 
 static const struct file_operations irq_affinity_proc_fops = {
@@ -212,7 +212,7 @@
 
 static int default_affinity_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, default_affinity_show, PDE(inode)->data);
+	return single_open(file, default_affinity_show, PDE_DATA(inode));
 }
 
 static const struct file_operations default_affinity_proc_fops = {
@@ -233,7 +233,7 @@
 
 static int irq_node_proc_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, irq_node_proc_show, PDE(inode)->data);
+	return single_open(file, irq_node_proc_show, PDE_DATA(inode));
 }
 
 static const struct file_operations irq_node_proc_fops = {
@@ -256,7 +256,7 @@
 
 static int irq_spurious_proc_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, irq_spurious_proc_show, PDE(inode)->data);
+	return single_open(file, irq_spurious_proc_show, PDE_DATA(inode));
 }
 
 static const struct file_operations irq_spurious_proc_fops = {
@@ -366,11 +366,7 @@
 
 void unregister_handler_proc(unsigned int irq, struct irqaction *action)
 {
-	if (action->dir) {
-		struct irq_desc *desc = irq_to_desc(irq);
-
-		remove_proc_entry(action->dir->name, desc->dir);
-	}
+	proc_remove(action->dir);
 }
 
 static void register_default_affinity_proc(void)
diff --git a/kernel/nsproxy.c b/kernel/nsproxy.c
index afc0456..364ceab 100644
--- a/kernel/nsproxy.c
+++ b/kernel/nsproxy.c
@@ -22,7 +22,7 @@
 #include <linux/pid_namespace.h>
 #include <net/net_namespace.h>
 #include <linux/ipc_namespace.h>
-#include <linux/proc_fs.h>
+#include <linux/proc_ns.h>
 #include <linux/file.h>
 #include <linux/syscalls.h>
 
@@ -241,7 +241,7 @@
 	const struct proc_ns_operations *ops;
 	struct task_struct *tsk = current;
 	struct nsproxy *new_nsproxy;
-	struct proc_inode *ei;
+	struct proc_ns *ei;
 	struct file *file;
 	int err;
 
@@ -250,7 +250,7 @@
 		return PTR_ERR(file);
 
 	err = -EINVAL;
-	ei = PROC_I(file_inode(file));
+	ei = get_proc_ns(file_inode(file));
 	ops = ei->ns_ops;
 	if (nstype && (ops->type != nstype))
 		goto out;
diff --git a/kernel/pid.c b/kernel/pid.c
index 6283d64..0db3e79 100644
--- a/kernel/pid.c
+++ b/kernel/pid.c
@@ -36,6 +36,7 @@
 #include <linux/pid_namespace.h>
 #include <linux/init_task.h>
 #include <linux/syscalls.h>
+#include <linux/proc_ns.h>
 #include <linux/proc_fs.h>
 
 #define pid_hashfn(nr, ns)	\
diff --git a/kernel/pid_namespace.c b/kernel/pid_namespace.c
index 69473c4..6917e8e 100644
--- a/kernel/pid_namespace.c
+++ b/kernel/pid_namespace.c
@@ -15,7 +15,7 @@
 #include <linux/err.h>
 #include <linux/acct.h>
 #include <linux/slab.h>
-#include <linux/proc_fs.h>
+#include <linux/proc_ns.h>
 #include <linux/reboot.h>
 #include <linux/export.h>
 
diff --git a/kernel/profile.c b/kernel/profile.c
index dc3384e..0bf4007 100644
--- a/kernel/profile.c
+++ b/kernel/profile.c
@@ -462,10 +462,10 @@
 	.write		= prof_cpu_mask_proc_write,
 };
 
-void create_prof_cpu_mask(struct proc_dir_entry *root_irq_dir)
+void create_prof_cpu_mask(void)
 {
 	/* create /proc/irq/prof_cpu_mask */
-	proc_create("prof_cpu_mask", 0600, root_irq_dir, &prof_cpu_mask_proc_fops);
+	proc_create("irq/prof_cpu_mask", 0600, NULL, &prof_cpu_mask_proc_fops);
 }
 
 /*
@@ -600,7 +600,7 @@
 			    NULL, &proc_profile_operations);
 	if (!entry)
 		return 0;
-	entry->size = (1+prof_len) * sizeof(atomic_t);
+	proc_set_size(entry, (1 + prof_len) * sizeof(atomic_t));
 	hotcpu_notifier(profile_cpu_callback, 0);
 	return 0;
 }
diff --git a/kernel/sched/stats.c b/kernel/sched/stats.c
index e036eda..da98af3 100644
--- a/kernel/sched/stats.c
+++ b/kernel/sched/stats.c
@@ -130,16 +130,11 @@
 	return seq_open(file, &schedstat_sops);
 }
 
-static int schedstat_release(struct inode *inode, struct file *file)
-{
-	return 0;
-};
-
 static const struct file_operations proc_schedstat_operations = {
 	.open    = schedstat_open,
 	.read    = seq_read,
 	.llseek  = seq_lseek,
-	.release = schedstat_release,
+	.release = seq_release,
 };
 
 static int __init proc_schedstat_init(void)
diff --git a/kernel/user.c b/kernel/user.c
index 8e635a1..69b4c3d 100644
--- a/kernel/user.c
+++ b/kernel/user.c
@@ -16,7 +16,7 @@
 #include <linux/interrupt.h>
 #include <linux/export.h>
 #include <linux/user_namespace.h>
-#include <linux/proc_fs.h>
+#include <linux/proc_ns.h>
 
 /*
  * userns count is 1 for root user, 1 for init_uts_ns,
diff --git a/kernel/user_namespace.c b/kernel/user_namespace.c
index e134d8f..d8c30db 100644
--- a/kernel/user_namespace.c
+++ b/kernel/user_namespace.c
@@ -9,7 +9,7 @@
 #include <linux/nsproxy.h>
 #include <linux/slab.h>
 #include <linux/user_namespace.h>
-#include <linux/proc_fs.h>
+#include <linux/proc_ns.h>
 #include <linux/highuid.h>
 #include <linux/cred.h>
 #include <linux/securebits.h>
diff --git a/kernel/utsname.c b/kernel/utsname.c
index a47fc5d..2fc8576 100644
--- a/kernel/utsname.c
+++ b/kernel/utsname.c
@@ -15,7 +15,7 @@
 #include <linux/err.h>
 #include <linux/slab.h>
 #include <linux/user_namespace.h>
-#include <linux/proc_fs.h>
+#include <linux/proc_ns.h>
 
 static struct uts_namespace *create_uts_ns(void)
 {
diff --git a/lib/notifier-error-inject.c b/lib/notifier-error-inject.c
index 44b92cb..eb4a04a 100644
--- a/lib/notifier-error-inject.c
+++ b/lib/notifier-error-inject.c
@@ -17,7 +17,7 @@
 DEFINE_SIMPLE_ATTRIBUTE(fops_errno, debugfs_errno_get, debugfs_errno_set,
 			"%lld\n");
 
-static struct dentry *debugfs_create_errno(const char *name, mode_t mode,
+static struct dentry *debugfs_create_errno(const char *name, umode_t mode,
 				struct dentry *parent, int *value)
 {
 	return debugfs_create_file(name, mode, parent, value, &fops_errno);
@@ -50,7 +50,7 @@
 			struct notifier_err_inject *err_inject, int priority)
 {
 	struct notifier_err_inject_action *action;
-	mode_t mode = S_IFREG | S_IRUSR | S_IWUSR;
+	umode_t mode = S_IFREG | S_IRUSR | S_IWUSR;
 	struct dentry *dir;
 	struct dentry *actions_dir;
 
diff --git a/mm/filemap.c b/mm/filemap.c
index e989fb1..7905fe7 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -2546,7 +2546,6 @@
 
 	BUG_ON(iocb->ki_pos != pos);
 
-	sb_start_write(inode->i_sb);
 	mutex_lock(&inode->i_mutex);
 	ret = __generic_file_aio_write(iocb, iov, nr_segs, &iocb->ki_pos);
 	mutex_unlock(&inode->i_mutex);
@@ -2558,7 +2557,6 @@
 		if (err < 0 && ret > 0)
 			ret = err;
 	}
-	sb_end_write(inode->i_sb);
 	return ret;
 }
 EXPORT_SYMBOL(generic_file_aio_write);
diff --git a/mm/filemap_xip.c b/mm/filemap_xip.c
index a912da6..28fe26b 100644
--- a/mm/filemap_xip.c
+++ b/mm/filemap_xip.c
@@ -404,8 +404,6 @@
 	loff_t pos;
 	ssize_t ret;
 
-	sb_start_write(inode->i_sb);
-
 	mutex_lock(&inode->i_mutex);
 
 	if (!access_ok(VERIFY_READ, buf, len)) {
@@ -439,7 +437,6 @@
 	current->backing_dev_info = NULL;
  out_up:
 	mutex_unlock(&inode->i_mutex);
-	sb_end_write(inode->i_sb);
 	return ret;
 }
 EXPORT_SYMBOL_GPL(xip_file_write);
diff --git a/mm/vmalloc.c b/mm/vmalloc.c
index 72043d6..b12fd86 100644
--- a/mm/vmalloc.c
+++ b/mm/vmalloc.c
@@ -27,10 +27,30 @@
 #include <linux/pfn.h>
 #include <linux/kmemleak.h>
 #include <linux/atomic.h>
+#include <linux/llist.h>
 #include <asm/uaccess.h>
 #include <asm/tlbflush.h>
 #include <asm/shmparam.h>
 
+struct vfree_deferred {
+	struct llist_head list;
+	struct work_struct wq;
+};
+static DEFINE_PER_CPU(struct vfree_deferred, vfree_deferred);
+
+static void __vunmap(const void *, int);
+
+static void free_work(struct work_struct *w)
+{
+	struct vfree_deferred *p = container_of(w, struct vfree_deferred, wq);
+	struct llist_node *llnode = llist_del_all(&p->list);
+	while (llnode) {
+		void *p = llnode;
+		llnode = llist_next(llnode);
+		__vunmap(p, 1);
+	}
+}
+
 /*** Page table manipulation functions ***/
 
 static void vunmap_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end)
@@ -1175,10 +1195,14 @@
 
 	for_each_possible_cpu(i) {
 		struct vmap_block_queue *vbq;
+		struct vfree_deferred *p;
 
 		vbq = &per_cpu(vmap_block_queue, i);
 		spin_lock_init(&vbq->lock);
 		INIT_LIST_HEAD(&vbq->free);
+		p = &per_cpu(vfree_deferred, i);
+		init_llist_head(&p->list);
+		INIT_WORK(&p->wq, free_work);
 	}
 
 	/* Import existing vmlist entries. */
@@ -1486,7 +1510,7 @@
 	kfree(area);
 	return;
 }
-
+ 
 /**
  *	vfree  -  release memory allocated by vmalloc()
  *	@addr:		memory base address
@@ -1495,15 +1519,25 @@
  *	obtained from vmalloc(), vmalloc_32() or __vmalloc(). If @addr is
  *	NULL, no operation is performed.
  *
- *	Must not be called in interrupt context.
+ *	Must not be called in NMI context (strictly speaking, only if we don't
+ *	have CONFIG_ARCH_HAVE_NMI_SAFE_CMPXCHG, but making the calling
+ *	conventions for vfree() arch-depenedent would be a really bad idea)
+ *	
  */
 void vfree(const void *addr)
 {
-	BUG_ON(in_interrupt());
+	BUG_ON(in_nmi());
 
 	kmemleak_free(addr);
 
-	__vunmap(addr, 1);
+	if (!addr)
+		return;
+	if (unlikely(in_interrupt())) {
+		struct vfree_deferred *p = &__get_cpu_var(vfree_deferred);
+		llist_add((struct llist_node *)addr, &p->list);
+		schedule_work(&p->wq);
+	} else
+		__vunmap(addr, 1);
 }
 EXPORT_SYMBOL(vfree);
 
@@ -1520,7 +1554,8 @@
 {
 	BUG_ON(in_interrupt());
 	might_sleep();
-	__vunmap(addr, 0);
+	if (addr)
+		__vunmap(addr, 0);
 }
 EXPORT_SYMBOL(vunmap);
 
diff --git a/net/8021q/vlanproc.c b/net/8021q/vlanproc.c
index dc526ec..1d0e8921 100644
--- a/net/8021q/vlanproc.c
+++ b/net/8021q/vlanproc.c
@@ -93,7 +93,7 @@
 
 static int vlandev_seq_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, vlandev_seq_show, PDE(inode)->data);
+	return single_open(file, vlandev_seq_show, PDE_DATA(inode));
 }
 
 static const struct file_operations vlandev_fops = {
@@ -184,14 +184,9 @@
  */
 int vlan_proc_rem_dev(struct net_device *vlandev)
 {
-	struct vlan_net *vn = net_generic(dev_net(vlandev), vlan_net_id);
-
 	/** NOTE:  This will consume the memory pointed to by dent, it seems. */
-	if (vlan_dev_priv(vlandev)->dent) {
-		remove_proc_entry(vlan_dev_priv(vlandev)->dent->name,
-				  vn->proc_vlan_dir);
-		vlan_dev_priv(vlandev)->dent = NULL;
-	}
+	proc_remove(vlan_dev_priv(vlandev)->dent);
+	vlan_dev_priv(vlandev)->dent = NULL;
 	return 0;
 }
 
diff --git a/net/atm/proc.c b/net/atm/proc.c
index 6ac35ff..bbb6461 100644
--- a/net/atm/proc.c
+++ b/net/atm/proc.c
@@ -385,7 +385,7 @@
 	page = get_zeroed_page(GFP_KERNEL);
 	if (!page)
 		return -ENOMEM;
-	dev = PDE(file_inode(file))->data;
+	dev = PDE_DATA(file_inode(file));
 	if (!dev->ops->proc_read)
 		length = -EINVAL;
 	else {
diff --git a/net/bluetooth/af_bluetooth.c b/net/bluetooth/af_bluetooth.c
index e5338f7..9096137 100644
--- a/net/bluetooth/af_bluetooth.c
+++ b/net/bluetooth/af_bluetooth.c
@@ -609,7 +609,7 @@
 	struct bt_sock_list *sk_list;
 	struct bt_seq_state *s;
 
-	sk_list = PDE(inode)->data;
+	sk_list = PDE_DATA(inode);
 	s = __seq_open_private(file, &bt_seq_ops,
 			       sizeof(struct bt_seq_state));
 	if (!s)
@@ -619,26 +619,21 @@
 	return 0;
 }
 
-int bt_procfs_init(struct module* module, struct net *net, const char *name,
+static const struct file_operations bt_fops = {
+	.open = bt_seq_open,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = seq_release_private
+};
+
+int bt_procfs_init(struct net *net, const char *name,
 		   struct bt_sock_list* sk_list,
 		   int (* seq_show)(struct seq_file *, void *))
 {
-	struct proc_dir_entry * pde;
-
 	sk_list->custom_seq_show = seq_show;
 
-	sk_list->fops.owner     = module;
-	sk_list->fops.open      = bt_seq_open;
-	sk_list->fops.read      = seq_read;
-	sk_list->fops.llseek    = seq_lseek;
-	sk_list->fops.release   = seq_release_private;
-
-	pde = proc_create(name, 0, net->proc_net, &sk_list->fops);
-	if (!pde)
+	if (!proc_create_data(name, 0, net->proc_net, &bt_fops, sk_list))
 		return -ENOMEM;
-
-	pde->data = sk_list;
-
 	return 0;
 }
 
@@ -647,7 +642,7 @@
 	remove_proc_entry(name, net->proc_net);
 }
 #else
-int bt_procfs_init(struct module* module, struct net *net, const char *name,
+int bt_procfs_init(struct net *net, const char *name,
 		   struct bt_sock_list* sk_list,
 		   int (* seq_show)(struct seq_file *, void *))
 {
diff --git a/net/bluetooth/bnep/sock.c b/net/bluetooth/bnep/sock.c
index 5b1c04e..5f05129 100644
--- a/net/bluetooth/bnep/sock.c
+++ b/net/bluetooth/bnep/sock.c
@@ -234,7 +234,7 @@
 		goto error;
 	}
 
-	err = bt_procfs_init(THIS_MODULE, &init_net, "bnep", &bnep_sk_list, NULL);
+	err = bt_procfs_init(&init_net, "bnep", &bnep_sk_list, NULL);
 	if (err < 0) {
 		BT_ERR("Failed to create BNEP proc file");
 		bt_sock_unregister(BTPROTO_BNEP);
diff --git a/net/bluetooth/cmtp/capi.c b/net/bluetooth/cmtp/capi.c
index a4a9d4b..cd75e4d 100644
--- a/net/bluetooth/cmtp/capi.c
+++ b/net/bluetooth/cmtp/capi.c
@@ -539,7 +539,7 @@
 
 static int cmtp_proc_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, cmtp_proc_show, PDE(inode)->data);
+	return single_open(file, cmtp_proc_show, PDE_DATA(inode));
 }
 
 static const struct file_operations cmtp_proc_fops = {
diff --git a/net/bluetooth/cmtp/sock.c b/net/bluetooth/cmtp/sock.c
index 58d9ede..d82787d 100644
--- a/net/bluetooth/cmtp/sock.c
+++ b/net/bluetooth/cmtp/sock.c
@@ -245,7 +245,7 @@
 		goto error;
 	}
 
-	err = bt_procfs_init(THIS_MODULE, &init_net, "cmtp", &cmtp_sk_list, NULL);
+	err = bt_procfs_init(&init_net, "cmtp", &cmtp_sk_list, NULL);
 	if (err < 0) {
 		BT_ERR("Failed to create CMTP proc file");
 		bt_sock_unregister(BTPROTO_HIDP);
diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c
index aa4354f..9bd7d95 100644
--- a/net/bluetooth/hci_sock.c
+++ b/net/bluetooth/hci_sock.c
@@ -1107,7 +1107,7 @@
 		goto error;
 	}
 
-	err = bt_procfs_init(THIS_MODULE, &init_net, "hci", &hci_sk_list, NULL);
+	err = bt_procfs_init(&init_net, "hci", &hci_sk_list, NULL);
 	if (err < 0) {
 		BT_ERR("Failed to create HCI proc file");
 		bt_sock_unregister(BTPROTO_HCI);
diff --git a/net/bluetooth/hidp/sock.c b/net/bluetooth/hidp/sock.c
index 2f4cbb0..cb3fdde 100644
--- a/net/bluetooth/hidp/sock.c
+++ b/net/bluetooth/hidp/sock.c
@@ -275,7 +275,7 @@
 		goto error;
 	}
 
-	err = bt_procfs_init(THIS_MODULE, &init_net, "hidp", &hidp_sk_list, NULL);
+	err = bt_procfs_init(&init_net, "hidp", &hidp_sk_list, NULL);
 	if (err < 0) {
 		BT_ERR("Failed to create HIDP proc file");
 		bt_sock_unregister(BTPROTO_HIDP);
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c
index 141e7b0..36fed40 100644
--- a/net/bluetooth/l2cap_sock.c
+++ b/net/bluetooth/l2cap_sock.c
@@ -1298,7 +1298,7 @@
 		goto error;
 	}
 
-	err = bt_procfs_init(THIS_MODULE, &init_net, "l2cap", &l2cap_sk_list,
+	err = bt_procfs_init(&init_net, "l2cap", &l2cap_sk_list,
 			     NULL);
 	if (err < 0) {
 		BT_ERR("Failed to create L2CAP proc file");
diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c
index a8638b5..30b3721 100644
--- a/net/bluetooth/rfcomm/sock.c
+++ b/net/bluetooth/rfcomm/sock.c
@@ -1037,7 +1037,7 @@
 		goto error;
 	}
 
-	err = bt_procfs_init(THIS_MODULE, &init_net, "rfcomm", &rfcomm_sk_list, NULL);
+	err = bt_procfs_init(&init_net, "rfcomm", &rfcomm_sk_list, NULL);
 	if (err < 0) {
 		BT_ERR("Failed to create RFCOMM proc file");
 		bt_sock_unregister(BTPROTO_RFCOMM);
diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c
index 373d81e..e7bd4ee 100644
--- a/net/bluetooth/sco.c
+++ b/net/bluetooth/sco.c
@@ -1119,7 +1119,7 @@
 		goto error;
 	}
 
-	err = bt_procfs_init(THIS_MODULE, &init_net, "sco", &sco_sk_list, NULL);
+	err = bt_procfs_init(&init_net, "sco", &sco_sk_list, NULL);
 	if (err < 0) {
 		BT_ERR("Failed to create SCO proc file");
 		bt_sock_unregister(BTPROTO_SCO);
diff --git a/net/can/bcm.c b/net/can/bcm.c
index 5dcb200..8f113e6 100644
--- a/net/can/bcm.c
+++ b/net/can/bcm.c
@@ -226,7 +226,7 @@
 
 static int bcm_proc_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, bcm_proc_show, PDE(inode)->data);
+	return single_open(file, bcm_proc_show, PDE_DATA(inode));
 }
 
 static const struct file_operations bcm_proc_fops = {
diff --git a/net/can/proc.c b/net/can/proc.c
index 1ab8c88..b543470 100644
--- a/net/can/proc.c
+++ b/net/can/proc.c
@@ -378,7 +378,7 @@
 
 static int can_rcvlist_proc_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, can_rcvlist_proc_show, PDE(inode)->data);
+	return single_open(file, can_rcvlist_proc_show, PDE_DATA(inode));
 }
 
 static const struct file_operations can_rcvlist_proc_fops = {
diff --git a/net/core/neighbour.c b/net/core/neighbour.c
index 89a3a07..5c56b21 100644
--- a/net/core/neighbour.c
+++ b/net/core/neighbour.c
@@ -2705,7 +2705,7 @@
 
 	if (!ret) {
 		struct seq_file *sf = file->private_data;
-		sf->private = PDE(inode)->data;
+		sf->private = PDE_DATA(inode);
 	}
 	return ret;
 };
diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c
index 80e271d..f9765203 100644
--- a/net/core/net_namespace.c
+++ b/net/core/net_namespace.c
@@ -10,7 +10,8 @@
 #include <linux/idr.h>
 #include <linux/rculist.h>
 #include <linux/nsproxy.h>
-#include <linux/proc_fs.h>
+#include <linux/fs.h>
+#include <linux/proc_ns.h>
 #include <linux/file.h>
 #include <linux/export.h>
 #include <linux/user_namespace.h>
@@ -336,7 +337,7 @@
 
 struct net *get_net_ns_by_fd(int fd)
 {
-	struct proc_inode *ei;
+	struct proc_ns *ei;
 	struct file *file;
 	struct net *net;
 
@@ -344,7 +345,7 @@
 	if (IS_ERR(file))
 		return ERR_CAST(file);
 
-	ei = PROC_I(file_inode(file));
+	ei = get_proc_ns(file_inode(file));
 	if (ei->ns_ops == &netns_operations)
 		net = get_net(ei->ns);
 	else
diff --git a/net/core/pktgen.c b/net/core/pktgen.c
index 5c21742..11f2704 100644
--- a/net/core/pktgen.c
+++ b/net/core/pktgen.c
@@ -508,7 +508,7 @@
 
 static int pgctrl_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, pgctrl_show, PDE(inode)->data);
+	return single_open(file, pgctrl_show, PDE_DATA(inode));
 }
 
 static const struct file_operations pktgen_fops = {
@@ -1685,7 +1685,7 @@
 
 static int pktgen_if_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, pktgen_if_show, PDE(inode)->data);
+	return single_open(file, pktgen_if_show, PDE_DATA(inode));
 }
 
 static const struct file_operations pktgen_if_fops = {
@@ -1823,7 +1823,7 @@
 
 static int pktgen_thread_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, pktgen_thread_show, PDE(inode)->data);
+	return single_open(file, pktgen_thread_show, PDE_DATA(inode));
 }
 
 static const struct file_operations pktgen_thread_fops = {
@@ -1904,7 +1904,7 @@
 			if (pkt_dev->odev != dev)
 				continue;
 
-			remove_proc_entry(pkt_dev->entry->name, pn->proc_dir);
+			proc_remove(pkt_dev->entry);
 
 			pkt_dev->entry = proc_create_data(dev->name, 0600,
 							  pn->proc_dir,
@@ -3574,8 +3574,6 @@
 static int pktgen_remove_device(struct pktgen_thread *t,
 				struct pktgen_dev *pkt_dev)
 {
-	struct pktgen_net *pn = t->net;
-
 	pr_debug("remove_device pkt_dev=%p\n", pkt_dev);
 
 	if (pkt_dev->running) {
@@ -3595,7 +3593,7 @@
 	_rem_dev_from_if_list(t, pkt_dev);
 
 	if (pkt_dev->entry)
-		remove_proc_entry(pkt_dev->entry->name, pn->proc_dir);
+		proc_remove(pkt_dev->entry);
 
 #ifdef CONFIG_XFRM
 	free_SAs(pkt_dev);
diff --git a/net/ipv4/netfilter/ipt_CLUSTERIP.c b/net/ipv4/netfilter/ipt_CLUSTERIP.c
index 5852b24..0b732ef 100644
--- a/net/ipv4/netfilter/ipt_CLUSTERIP.c
+++ b/net/ipv4/netfilter/ipt_CLUSTERIP.c
@@ -105,7 +105,7 @@
 		 * functions are also incrementing the refcount on their own,
 		 * so it's safe to remove the entry even if it's in use. */
 #ifdef CONFIG_PROC_FS
-		remove_proc_entry(c->pde->name, c->pde->parent);
+		proc_remove(c->pde);
 #endif
 		return;
 	}
@@ -631,7 +631,7 @@
 
 	if (!ret) {
 		struct seq_file *sf = file->private_data;
-		struct clusterip_config *c = PDE(inode)->data;
+		struct clusterip_config *c = PDE_DATA(inode);
 
 		sf->private = c;
 
@@ -643,7 +643,7 @@
 
 static int clusterip_proc_release(struct inode *inode, struct file *file)
 {
-	struct clusterip_config *c = PDE(inode)->data;
+	struct clusterip_config *c = PDE_DATA(inode);
 	int ret;
 
 	ret = seq_release(inode, file);
@@ -657,7 +657,7 @@
 static ssize_t clusterip_proc_write(struct file *file, const char __user *input,
 				size_t size, loff_t *ofs)
 {
-	struct clusterip_config *c = PDE(file_inode(file))->data;
+	struct clusterip_config *c = PDE_DATA(file_inode(file));
 #define PROC_WRITELEN	10
 	char buffer[PROC_WRITELEN+1];
 	unsigned long nodenum;
@@ -736,7 +736,7 @@
 {
 	pr_info("ClusterIP Version %s unloading\n", CLUSTERIP_VERSION);
 #ifdef CONFIG_PROC_FS
-	remove_proc_entry(clusterip_procdir->name, clusterip_procdir->parent);
+	proc_remove(clusterip_procdir);
 #endif
 	nf_unregister_hook(&cip_arp_ops);
 	xt_unregister_target(&clusterip_tg_reg);
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index d979657..7196523 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -2583,7 +2583,7 @@
 
 int tcp_seq_open(struct inode *inode, struct file *file)
 {
-	struct tcp_seq_afinfo *afinfo = PDE(inode)->data;
+	struct tcp_seq_afinfo *afinfo = PDE_DATA(inode);
 	struct tcp_iter_state *s;
 	int err;
 
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index 3159d16..6abbe64 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -2100,7 +2100,7 @@
 
 int udp_seq_open(struct inode *inode, struct file *file)
 {
-	struct udp_seq_afinfo *afinfo = PDE(inode)->data;
+	struct udp_seq_afinfo *afinfo = PDE_DATA(inode);
 	struct udp_iter_state *s;
 	int err;
 
diff --git a/net/ipv6/proc.c b/net/ipv6/proc.c
index 115cc58..f3c1ff4 100644
--- a/net/ipv6/proc.c
+++ b/net/ipv6/proc.c
@@ -251,7 +251,7 @@
 
 static int snmp6_dev_seq_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, snmp6_dev_seq_show, PDE(inode)->data);
+	return single_open(file, snmp6_dev_seq_show, PDE_DATA(inode));
 }
 
 static const struct file_operations snmp6_dev_seq_fops = {
@@ -291,8 +291,7 @@
 		return -ENOENT;
 	if (!idev->stats.proc_dir_entry)
 		return -EINVAL;
-	remove_proc_entry(idev->stats.proc_dir_entry->name,
-			  net->mib.proc_net_devsnmp6);
+	proc_remove(idev->stats.proc_dir_entry);
 	idev->stats.proc_dir_entry = NULL;
 	return 0;
 }
diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c
index 1a73b18..8b03028 100644
--- a/net/netfilter/x_tables.c
+++ b/net/netfilter/x_tables.c
@@ -1000,7 +1000,7 @@
 			   sizeof(struct xt_names_priv));
 	if (!ret) {
 		priv = ((struct seq_file *)file->private_data)->private;
-		priv->af = (unsigned long)PDE(inode)->data;
+		priv->af = (unsigned long)PDE_DATA(inode);
 	}
 	return ret;
 }
@@ -1148,7 +1148,7 @@
 
 	seq = file->private_data;
 	seq->private = trav;
-	trav->nfproto = (unsigned long)PDE(inode)->data;
+	trav->nfproto = (unsigned long)PDE_DATA(inode);
 	return 0;
 }
 
@@ -1212,7 +1212,7 @@
 
 	seq = file->private_data;
 	seq->private = trav;
-	trav->nfproto = (unsigned long)PDE(inode)->data;
+	trav->nfproto = (unsigned long)PDE_DATA(inode);
 	return 0;
 }
 
diff --git a/net/netfilter/xt_hashlimit.c b/net/netfilter/xt_hashlimit.c
index 0199e7b..9ff035c 100644
--- a/net/netfilter/xt_hashlimit.c
+++ b/net/netfilter/xt_hashlimit.c
@@ -108,6 +108,7 @@
 
 	/* seq_file stuff */
 	struct proc_dir_entry *pde;
+	const char *name;
 	struct net *net;
 
 	struct hlist_head hash[0];	/* hashtable itself */
@@ -254,6 +255,11 @@
 	hinfo->count = 0;
 	hinfo->family = family;
 	hinfo->rnd_initialized = false;
+	hinfo->name = kstrdup(minfo->name, GFP_KERNEL);
+	if (!hinfo->name) {
+		vfree(hinfo);
+		return -ENOMEM;
+	}
 	spin_lock_init(&hinfo->lock);
 
 	hinfo->pde = proc_create_data(minfo->name, 0,
@@ -261,6 +267,7 @@
 		hashlimit_net->ipt_hashlimit : hashlimit_net->ip6t_hashlimit,
 		&dl_file_ops, hinfo);
 	if (hinfo->pde == NULL) {
+		kfree(hinfo->name);
 		vfree(hinfo);
 		return -ENOMEM;
 	}
@@ -331,9 +338,10 @@
 		parent = hashlimit_net->ip6t_hashlimit;
 
 	if(parent != NULL)
-		remove_proc_entry(hinfo->pde->name, parent);
+		remove_proc_entry(hinfo->name, parent);
 
 	htable_selective_cleanup(hinfo, select_all);
+	kfree(hinfo->name);
 	vfree(hinfo);
 }
 
@@ -345,7 +353,7 @@
 	struct xt_hashlimit_htable *hinfo;
 
 	hlist_for_each_entry(hinfo, &hashlimit_net->htables, node) {
-		if (!strcmp(name, hinfo->pde->name) &&
+		if (!strcmp(name, hinfo->name) &&
 		    hinfo->family == family) {
 			hinfo->use++;
 			return hinfo;
@@ -842,7 +850,7 @@
 
 	if (!ret) {
 		struct seq_file *sf = file->private_data;
-		sf->private = PDE(inode)->data;
+		sf->private = PDE_DATA(inode);
 	}
 	return ret;
 }
@@ -888,7 +896,7 @@
 		pde = hashlimit_net->ip6t_hashlimit;
 
 	hlist_for_each_entry(hinfo, &hashlimit_net->htables, node)
-		remove_proc_entry(hinfo->pde->name, pde);
+		remove_proc_entry(hinfo->name, pde);
 
 	hashlimit_net->ipt_hashlimit = NULL;
 	hashlimit_net->ip6t_hashlimit = NULL;
diff --git a/net/netfilter/xt_recent.c b/net/netfilter/xt_recent.c
index d9cad31..1e657cf 100644
--- a/net/netfilter/xt_recent.c
+++ b/net/netfilter/xt_recent.c
@@ -401,8 +401,7 @@
 		ret = -ENOMEM;
 		goto out;
 	}
-	pde->uid = uid;
-	pde->gid = gid;
+	proc_set_user(pde, uid, gid);
 #endif
 	spin_lock_bh(&recent_lock);
 	list_add_tail(&t->list, &recent_net->tables);
@@ -525,14 +524,13 @@
 
 static int recent_seq_open(struct inode *inode, struct file *file)
 {
-	struct proc_dir_entry *pde = PDE(inode);
 	struct recent_iter_state *st;
 
 	st = __seq_open_private(file, &recent_seq_ops, sizeof(*st));
 	if (st == NULL)
 		return -ENOMEM;
 
-	st->table    = pde->data;
+	st->table    = PDE_DATA(inode);
 	return 0;
 }
 
@@ -540,8 +538,7 @@
 recent_mt_proc_write(struct file *file, const char __user *input,
 		     size_t size, loff_t *loff)
 {
-	const struct proc_dir_entry *pde = PDE(file_inode(file));
-	struct recent_table *t = pde->data;
+	struct recent_table *t = PDE_DATA(file_inode(file));
 	struct recent_entry *e;
 	char buf[sizeof("+b335:1d35:1e55:dead:c0de:1715:5afe:c0de")];
 	const char *c = buf;
diff --git a/net/socket.c b/net/socket.c
index 280283f..b416093 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -1160,15 +1160,6 @@
 
 static int sock_close(struct inode *inode, struct file *filp)
 {
-	/*
-	 *      It was possible the inode is NULL we were
-	 *      closing an unfinished socket.
-	 */
-
-	if (!inode) {
-		printk(KERN_DEBUG "sock_close: NULL inode\n");
-		return 0;
-	}
 	sock_release(SOCKET_I(inode));
 	return 0;
 }
diff --git a/net/sunrpc/cache.c b/net/sunrpc/cache.c
index ce2d180..f1889be 100644
--- a/net/sunrpc/cache.c
+++ b/net/sunrpc/cache.c
@@ -1460,7 +1460,7 @@
 static ssize_t cache_read_procfs(struct file *filp, char __user *buf,
 				 size_t count, loff_t *ppos)
 {
-	struct cache_detail *cd = PDE(file_inode(filp))->data;
+	struct cache_detail *cd = PDE_DATA(file_inode(filp));
 
 	return cache_read(filp, buf, count, ppos, cd);
 }
@@ -1468,14 +1468,14 @@
 static ssize_t cache_write_procfs(struct file *filp, const char __user *buf,
 				  size_t count, loff_t *ppos)
 {
-	struct cache_detail *cd = PDE(file_inode(filp))->data;
+	struct cache_detail *cd = PDE_DATA(file_inode(filp));
 
 	return cache_write(filp, buf, count, ppos, cd);
 }
 
 static unsigned int cache_poll_procfs(struct file *filp, poll_table *wait)
 {
-	struct cache_detail *cd = PDE(file_inode(filp))->data;
+	struct cache_detail *cd = PDE_DATA(file_inode(filp));
 
 	return cache_poll(filp, wait, cd);
 }
@@ -1484,21 +1484,21 @@
 			       unsigned int cmd, unsigned long arg)
 {
 	struct inode *inode = file_inode(filp);
-	struct cache_detail *cd = PDE(inode)->data;
+	struct cache_detail *cd = PDE_DATA(inode);
 
 	return cache_ioctl(inode, filp, cmd, arg, cd);
 }
 
 static int cache_open_procfs(struct inode *inode, struct file *filp)
 {
-	struct cache_detail *cd = PDE(inode)->data;
+	struct cache_detail *cd = PDE_DATA(inode);
 
 	return cache_open(inode, filp, cd);
 }
 
 static int cache_release_procfs(struct inode *inode, struct file *filp)
 {
-	struct cache_detail *cd = PDE(inode)->data;
+	struct cache_detail *cd = PDE_DATA(inode);
 
 	return cache_release(inode, filp, cd);
 }
@@ -1516,14 +1516,14 @@
 
 static int content_open_procfs(struct inode *inode, struct file *filp)
 {
-	struct cache_detail *cd = PDE(inode)->data;
+	struct cache_detail *cd = PDE_DATA(inode);
 
 	return content_open(inode, filp, cd);
 }
 
 static int content_release_procfs(struct inode *inode, struct file *filp)
 {
-	struct cache_detail *cd = PDE(inode)->data;
+	struct cache_detail *cd = PDE_DATA(inode);
 
 	return content_release(inode, filp, cd);
 }
@@ -1537,14 +1537,14 @@
 
 static int open_flush_procfs(struct inode *inode, struct file *filp)
 {
-	struct cache_detail *cd = PDE(inode)->data;
+	struct cache_detail *cd = PDE_DATA(inode);
 
 	return open_flush(inode, filp, cd);
 }
 
 static int release_flush_procfs(struct inode *inode, struct file *filp)
 {
-	struct cache_detail *cd = PDE(inode)->data;
+	struct cache_detail *cd = PDE_DATA(inode);
 
 	return release_flush(inode, filp, cd);
 }
@@ -1552,7 +1552,7 @@
 static ssize_t read_flush_procfs(struct file *filp, char __user *buf,
 			    size_t count, loff_t *ppos)
 {
-	struct cache_detail *cd = PDE(file_inode(filp))->data;
+	struct cache_detail *cd = PDE_DATA(file_inode(filp));
 
 	return read_flush(filp, buf, count, ppos, cd);
 }
@@ -1561,7 +1561,7 @@
 				  const char __user *buf,
 				  size_t count, loff_t *ppos)
 {
-	struct cache_detail *cd = PDE(file_inode(filp))->data;
+	struct cache_detail *cd = PDE_DATA(file_inode(filp));
 
 	return write_flush(filp, buf, count, ppos, cd);
 }
diff --git a/net/sunrpc/stats.c b/net/sunrpc/stats.c
index bc2068e..21b75cb 100644
--- a/net/sunrpc/stats.c
+++ b/net/sunrpc/stats.c
@@ -64,7 +64,7 @@
 
 static int rpc_proc_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, rpc_proc_show, PDE(inode)->data);
+	return single_open(file, rpc_proc_show, PDE_DATA(inode));
 }
 
 static const struct file_operations rpc_proc_fops = {
diff --git a/net/wireless/lib80211_crypt_ccmp.c b/net/wireless/lib80211_crypt_ccmp.c
index 1526c21..dc0e59e 100644
--- a/net/wireless/lib80211_crypt_ccmp.c
+++ b/net/wireless/lib80211_crypt_ccmp.c
@@ -430,24 +430,23 @@
 	return CCMP_TK_LEN;
 }
 
-static char *lib80211_ccmp_print_stats(char *p, void *priv)
+static void lib80211_ccmp_print_stats(struct seq_file *m, void *priv)
 {
 	struct lib80211_ccmp_data *ccmp = priv;
 
-	p += sprintf(p, "key[%d] alg=CCMP key_set=%d "
-		     "tx_pn=%02x%02x%02x%02x%02x%02x "
-		     "rx_pn=%02x%02x%02x%02x%02x%02x "
-		     "format_errors=%d replays=%d decrypt_errors=%d\n",
-		     ccmp->key_idx, ccmp->key_set,
-		     ccmp->tx_pn[0], ccmp->tx_pn[1], ccmp->tx_pn[2],
-		     ccmp->tx_pn[3], ccmp->tx_pn[4], ccmp->tx_pn[5],
-		     ccmp->rx_pn[0], ccmp->rx_pn[1], ccmp->rx_pn[2],
-		     ccmp->rx_pn[3], ccmp->rx_pn[4], ccmp->rx_pn[5],
-		     ccmp->dot11RSNAStatsCCMPFormatErrors,
-		     ccmp->dot11RSNAStatsCCMPReplays,
-		     ccmp->dot11RSNAStatsCCMPDecryptErrors);
-
-	return p;
+	seq_printf(m,
+		   "key[%d] alg=CCMP key_set=%d "
+		   "tx_pn=%02x%02x%02x%02x%02x%02x "
+		   "rx_pn=%02x%02x%02x%02x%02x%02x "
+		   "format_errors=%d replays=%d decrypt_errors=%d\n",
+		   ccmp->key_idx, ccmp->key_set,
+		   ccmp->tx_pn[0], ccmp->tx_pn[1], ccmp->tx_pn[2],
+		   ccmp->tx_pn[3], ccmp->tx_pn[4], ccmp->tx_pn[5],
+		   ccmp->rx_pn[0], ccmp->rx_pn[1], ccmp->rx_pn[2],
+		   ccmp->rx_pn[3], ccmp->rx_pn[4], ccmp->rx_pn[5],
+		   ccmp->dot11RSNAStatsCCMPFormatErrors,
+		   ccmp->dot11RSNAStatsCCMPReplays,
+		   ccmp->dot11RSNAStatsCCMPDecryptErrors);
 }
 
 static struct lib80211_crypto_ops lib80211_crypt_ccmp = {
diff --git a/net/wireless/lib80211_crypt_tkip.c b/net/wireless/lib80211_crypt_tkip.c
index d475cfc..8c90ba7 100644
--- a/net/wireless/lib80211_crypt_tkip.c
+++ b/net/wireless/lib80211_crypt_tkip.c
@@ -703,30 +703,30 @@
 	return TKIP_KEY_LEN;
 }
 
-static char *lib80211_tkip_print_stats(char *p, void *priv)
+static void lib80211_tkip_print_stats(struct seq_file *m, void *priv)
 {
 	struct lib80211_tkip_data *tkip = priv;
-	p += sprintf(p, "key[%d] alg=TKIP key_set=%d "
-		     "tx_pn=%02x%02x%02x%02x%02x%02x "
-		     "rx_pn=%02x%02x%02x%02x%02x%02x "
-		     "replays=%d icv_errors=%d local_mic_failures=%d\n",
-		     tkip->key_idx, tkip->key_set,
-		     (tkip->tx_iv32 >> 24) & 0xff,
-		     (tkip->tx_iv32 >> 16) & 0xff,
-		     (tkip->tx_iv32 >> 8) & 0xff,
-		     tkip->tx_iv32 & 0xff,
-		     (tkip->tx_iv16 >> 8) & 0xff,
-		     tkip->tx_iv16 & 0xff,
-		     (tkip->rx_iv32 >> 24) & 0xff,
-		     (tkip->rx_iv32 >> 16) & 0xff,
-		     (tkip->rx_iv32 >> 8) & 0xff,
-		     tkip->rx_iv32 & 0xff,
-		     (tkip->rx_iv16 >> 8) & 0xff,
-		     tkip->rx_iv16 & 0xff,
-		     tkip->dot11RSNAStatsTKIPReplays,
-		     tkip->dot11RSNAStatsTKIPICVErrors,
-		     tkip->dot11RSNAStatsTKIPLocalMICFailures);
-	return p;
+	seq_printf(m,
+		   "key[%d] alg=TKIP key_set=%d "
+		   "tx_pn=%02x%02x%02x%02x%02x%02x "
+		   "rx_pn=%02x%02x%02x%02x%02x%02x "
+		   "replays=%d icv_errors=%d local_mic_failures=%d\n",
+		   tkip->key_idx, tkip->key_set,
+		   (tkip->tx_iv32 >> 24) & 0xff,
+		   (tkip->tx_iv32 >> 16) & 0xff,
+		   (tkip->tx_iv32 >> 8) & 0xff,
+		   tkip->tx_iv32 & 0xff,
+		   (tkip->tx_iv16 >> 8) & 0xff,
+		   tkip->tx_iv16 & 0xff,
+		   (tkip->rx_iv32 >> 24) & 0xff,
+		   (tkip->rx_iv32 >> 16) & 0xff,
+		   (tkip->rx_iv32 >> 8) & 0xff,
+		   tkip->rx_iv32 & 0xff,
+		   (tkip->rx_iv16 >> 8) & 0xff,
+		   tkip->rx_iv16 & 0xff,
+		   tkip->dot11RSNAStatsTKIPReplays,
+		   tkip->dot11RSNAStatsTKIPICVErrors,
+		   tkip->dot11RSNAStatsTKIPLocalMICFailures);
 }
 
 static struct lib80211_crypto_ops lib80211_crypt_tkip = {
diff --git a/net/wireless/lib80211_crypt_wep.c b/net/wireless/lib80211_crypt_wep.c
index c130401..1c292e4 100644
--- a/net/wireless/lib80211_crypt_wep.c
+++ b/net/wireless/lib80211_crypt_wep.c
@@ -253,11 +253,10 @@
 	return wep->key_len;
 }
 
-static char *lib80211_wep_print_stats(char *p, void *priv)
+static void lib80211_wep_print_stats(struct seq_file *m, void *priv)
 {
 	struct lib80211_wep_data *wep = priv;
-	p += sprintf(p, "key[%d] alg=WEP len=%d\n", wep->key_idx, wep->key_len);
-	return p;
+	seq_printf(m, "key[%d] alg=WEP len=%d\n", wep->key_idx, wep->key_len);
 }
 
 static struct lib80211_crypto_ops lib80211_crypt_wep = {
diff --git a/net/x25/x25_proc.c b/net/x25/x25_proc.c
index 2ffde46..0917f04 100644
--- a/net/x25/x25_proc.c
+++ b/net/x25/x25_proc.c
@@ -187,7 +187,6 @@
 }
 
 static const struct file_operations x25_seq_socket_fops = {
-	.owner		= THIS_MODULE,
 	.open		= x25_seq_socket_open,
 	.read		= seq_read,
 	.llseek		= seq_lseek,
@@ -195,7 +194,6 @@
 };
 
 static const struct file_operations x25_seq_route_fops = {
-	.owner		= THIS_MODULE,
 	.open		= x25_seq_route_open,
 	.read		= seq_read,
 	.llseek		= seq_lseek,
@@ -203,55 +201,38 @@
 };
 
 static const struct file_operations x25_seq_forward_fops = {
-	.owner		= THIS_MODULE,
 	.open		= x25_seq_forward_open,
 	.read		= seq_read,
 	.llseek		= seq_lseek,
 	.release	= seq_release,
 };
 
-static struct proc_dir_entry *x25_proc_dir;
-
 int __init x25_proc_init(void)
 {
-	struct proc_dir_entry *p;
-	int rc = -ENOMEM;
+	if (!proc_mkdir("x25", init_net.proc_net))
+		return -ENOMEM;
 
-	x25_proc_dir = proc_mkdir("x25", init_net.proc_net);
-	if (!x25_proc_dir)
+	if (!proc_create("x25/route", S_IRUGO, init_net.proc_net,
+			&x25_seq_route_fops))
 		goto out;
 
-	p = proc_create("route", S_IRUGO, x25_proc_dir, &x25_seq_route_fops);
-	if (!p)
-		goto out_route;
+	if (!proc_create("x25/socket", S_IRUGO, init_net.proc_net,
+			&x25_seq_socket_fops))
+		goto out;
 
-	p = proc_create("socket", S_IRUGO, x25_proc_dir, &x25_seq_socket_fops);
-	if (!p)
-		goto out_socket;
-
-	p = proc_create("forward", S_IRUGO, x25_proc_dir,
-			&x25_seq_forward_fops);
-	if (!p)
-		goto out_forward;
-	rc = 0;
+	if (!proc_create("x25/forward", S_IRUGO, init_net.proc_net,
+			&x25_seq_forward_fops))
+		goto out;
+	return 0;
 
 out:
-	return rc;
-out_forward:
-	remove_proc_entry("socket", x25_proc_dir);
-out_socket:
-	remove_proc_entry("route", x25_proc_dir);
-out_route:
-	remove_proc_entry("x25", init_net.proc_net);
-	goto out;
+	remove_proc_subtree("x25", init_net.proc_net);
+	return -ENOMEM;
 }
 
 void __exit x25_proc_exit(void)
 {
-	remove_proc_entry("forward", x25_proc_dir);
-	remove_proc_entry("route", x25_proc_dir);
-	remove_proc_entry("socket", x25_proc_dir);
-	remove_proc_entry("x25", init_net.proc_net);
+	remove_proc_subtree("x25", init_net.proc_net);
 }
 
 #else /* CONFIG_PROC_FS */
diff --git a/security/tomoyo/common.c b/security/tomoyo/common.c
index f89a033..283862a 100644
--- a/security/tomoyo/common.c
+++ b/security/tomoyo/common.c
@@ -2681,10 +2681,8 @@
  * tomoyo_close_control - close() for /sys/kernel/security/tomoyo/ interface.
  *
  * @head: Pointer to "struct tomoyo_io_buffer".
- *
- * Returns 0.
  */
-int tomoyo_close_control(struct tomoyo_io_buffer *head)
+void tomoyo_close_control(struct tomoyo_io_buffer *head)
 {
 	/*
 	 * If the file is /sys/kernel/security/tomoyo/query , decrement the
@@ -2694,7 +2692,6 @@
 	    atomic_dec_and_test(&tomoyo_query_observers))
 		wake_up_all(&tomoyo_answer_wait);
 	tomoyo_notify_gc(head, false);
-	return 0;
 }
 
 /**
diff --git a/security/tomoyo/common.h b/security/tomoyo/common.h
index d4f166b..b897d48 100644
--- a/security/tomoyo/common.h
+++ b/security/tomoyo/common.h
@@ -958,7 +958,7 @@
 (const struct tomoyo_path_info *pathname, const struct tomoyo_group *group);
 int tomoyo_check_open_permission(struct tomoyo_domain_info *domain,
 				 struct path *path, const int flag);
-int tomoyo_close_control(struct tomoyo_io_buffer *head);
+void tomoyo_close_control(struct tomoyo_io_buffer *head);
 int tomoyo_env_perm(struct tomoyo_request_info *r, const char *env);
 int tomoyo_execute_permission(struct tomoyo_request_info *r,
 			      const struct tomoyo_path_info *filename);
diff --git a/security/tomoyo/securityfs_if.c b/security/tomoyo/securityfs_if.c
index fcf3278..179a955 100644
--- a/security/tomoyo/securityfs_if.c
+++ b/security/tomoyo/securityfs_if.c
@@ -143,14 +143,13 @@
 /**
  * tomoyo_release - close() for /sys/kernel/security/tomoyo/ interface.
  *
- * @inode: Pointer to "struct inode".
  * @file:  Pointer to "struct file".
  *
- * Returns 0 on success, negative value otherwise.
  */
 static int tomoyo_release(struct inode *inode, struct file *file)
 {
-	return tomoyo_close_control(file->private_data);
+	tomoyo_close_control(file->private_data);
+	return 0;
 }
 
 /**
diff --git a/sound/core/info.c b/sound/core/info.c
index 5bb97e7..3c9bd6b 100644
--- a/sound/core/info.c
+++ b/sound/core/info.c
@@ -153,13 +153,6 @@
 struct snd_info_entry *snd_oss_root;
 #endif
 
-static void snd_remove_proc_entry(struct proc_dir_entry *parent,
-				  struct proc_dir_entry *de)
-{
-	if (de)
-		remove_proc_entry(de->name, parent);
-}
-
 static loff_t snd_info_entry_llseek(struct file *file, loff_t offset, int orig)
 {
 	struct snd_info_private_data *data;
@@ -310,12 +303,10 @@
 	struct snd_info_entry *entry;
 	struct snd_info_private_data *data;
 	struct snd_info_buffer *buffer;
-	struct proc_dir_entry *p;
 	int mode, err;
 
 	mutex_lock(&info_mutex);
-	p = PDE(inode);
-	entry = p == NULL ? NULL : (struct snd_info_entry *)p->data;
+	entry = PDE_DATA(inode);
 	if (entry == NULL || ! entry->p) {
 		mutex_unlock(&info_mutex);
 		return -ENODEV;
@@ -582,7 +573,7 @@
 #ifdef CONFIG_SND_OSSEMUL
 		snd_info_free_entry(snd_oss_root);
 #endif
-		snd_remove_proc_entry(NULL, snd_proc_root);
+		proc_remove(snd_proc_root);
 	}
 	return 0;
 }
@@ -644,7 +635,7 @@
 {
 	mutex_lock(&info_mutex);
 	if (card->proc_root_link) {
-		snd_remove_proc_entry(snd_proc_root, card->proc_root_link);
+		proc_remove(card->proc_root_link);
 		card->proc_root_link = NULL;
 	}
 	if (strcmp(card->id, card->proc_root->name))
@@ -663,10 +654,8 @@
 	if (!card)
 		return;
 	mutex_lock(&info_mutex);
-	if (card->proc_root_link) {
-		snd_remove_proc_entry(snd_proc_root, card->proc_root_link);
-		card->proc_root_link = NULL;
-	}
+	proc_remove(card->proc_root_link);
+	card->proc_root_link = NULL;
 	if (card->proc_root)
 		snd_info_disconnect(card->proc_root);
 	mutex_unlock(&info_mutex);
@@ -858,7 +847,7 @@
 	list_del_init(&entry->list);
 	root = entry->parent == NULL ? snd_proc_root : entry->parent->p;
 	snd_BUG_ON(!root);
-	snd_remove_proc_entry(root, entry->p);
+	proc_remove(entry->p);
 	entry->p = NULL;
 }
 
@@ -959,15 +948,21 @@
 		return -ENXIO;
 	root = entry->parent == NULL ? snd_proc_root : entry->parent->p;
 	mutex_lock(&info_mutex);
-	p = create_proc_entry(entry->name, entry->mode, root);
-	if (!p) {
-		mutex_unlock(&info_mutex);
-		return -ENOMEM;
+	if (S_ISDIR(entry->mode)) {
+		p = proc_mkdir_mode(entry->name, entry->mode, root);
+		if (!p) {
+			mutex_unlock(&info_mutex);
+			return -ENOMEM;
+		}
+	} else {
+		p = proc_create_data(entry->name, entry->mode, root,
+					&snd_info_entry_operations, entry);
+		if (!p) {
+			mutex_unlock(&info_mutex);
+			return -ENOMEM;
+		}
+		proc_set_size(p, entry->size);
 	}
-	if (!S_ISDIR(entry->mode))
-		p->proc_fops = &snd_info_entry_operations;
-	p->size = entry->size;
-	p->data = entry;
 	entry->p = p;
 	if (entry->parent)
 		list_add_tail(&entry->list, &entry->parent->children);
diff --git a/sound/oss/dmasound/dmasound_core.c b/sound/oss/dmasound/dmasound_core.c
index c918313..bac43b5 100644
--- a/sound/oss/dmasound/dmasound_core.c
+++ b/sound/oss/dmasound/dmasound_core.c
@@ -835,7 +835,7 @@
 	shared_resources_initialised = 0 ;
 }
 
-static int sq_fsync(struct file *filp, struct dentry *dentry)
+static int sq_fsync(void)
 {
 	int rc = 0;
 	int timeout = 5;
@@ -874,7 +874,7 @@
 
 	if (file->f_mode & FMODE_WRITE) {
 		if (write_sq.busy)
-			rc = sq_fsync(file, file->f_path.dentry);
+			rc = sq_fsync();
 
 		sq_reset_output() ; /* make sure dma is stopped and all is quiet */
 		write_sq_release_buffers();
@@ -1025,7 +1025,7 @@
 		*/
 		result = 0 ;
 		if (file->f_mode & FMODE_WRITE) {
-			result = sq_fsync(file, file->f_path.dentry);
+			result = sq_fsync();
 			sq_reset_output() ;
 		}
 		/* if we are the shared resource owner then release them */
diff --git a/sound/sound_firmware.c b/sound/sound_firmware.c
index e149034..b155137 100644
--- a/sound/sound_firmware.c
+++ b/sound/sound_firmware.c
@@ -1,6 +1,7 @@
 #include <linux/vmalloc.h>
 #include <linux/module.h>
 #include <linux/fs.h>
+#include <linux/file.h>
 #include <linux/mm.h>
 #include <linux/sched.h>
 #include <asm/uaccess.h>
@@ -23,14 +24,14 @@
 	if (l <= 0 || l > 131072)
 	{
 		printk(KERN_INFO "Invalid firmware '%s'\n", fn);
-		filp_close(filp, NULL);
+		fput(filp);
 		return 0;
 	}
 	dp = vmalloc(l);
 	if (dp == NULL)
 	{
 		printk(KERN_INFO "Out of memory loading '%s'.\n", fn);
-		filp_close(filp, NULL);
+		fput(filp);
 		return 0;
 	}
 	pos = 0;
@@ -38,10 +39,10 @@
 	{
 		printk(KERN_INFO "Failed to read '%s'.\n", fn);
 		vfree(dp);
-		filp_close(filp, NULL);
+		fput(filp);
 		return 0;
 	}
-	filp_close(filp, NULL);
+	fput(filp);
 	*fp = dp;
 	return (int) l;
 }