[kernel] r11007 - in dists/trunk/linux-2.6/debian/patches: bugfix/all bugfix/arm series

Maximilian Attems maks at alioth.debian.org
Sat Mar 29 11:10:54 UTC 2008


Author: maks
Date: Sat Mar 29 11:10:53 2008
New Revision: 11007

Log:
update to 2.6.25-rc7-git5

nuke merged ixp4xx-beeper-add-module_alias.patch.
vfs + dm + various fixes.


Added:
   dists/trunk/linux-2.6/debian/patches/bugfix/all/patch-2.6.25-rc7-git5
      - copied, changed from r11006, /dists/trunk/linux-2.6/debian/patches/bugfix/all/patch-2.6.25-rc7-git4
Removed:
   dists/trunk/linux-2.6/debian/patches/bugfix/all/patch-2.6.25-rc7-git4
   dists/trunk/linux-2.6/debian/patches/bugfix/arm/ixp4xx-beeper-add-module_alias.patch
Modified:
   dists/trunk/linux-2.6/debian/patches/series/1~experimental.1

Copied: dists/trunk/linux-2.6/debian/patches/bugfix/all/patch-2.6.25-rc7-git5 (from r11006, /dists/trunk/linux-2.6/debian/patches/bugfix/all/patch-2.6.25-rc7-git4)
==============================================================================
--- /dists/trunk/linux-2.6/debian/patches/bugfix/all/patch-2.6.25-rc7-git4	(original)
+++ dists/trunk/linux-2.6/debian/patches/bugfix/all/patch-2.6.25-rc7-git5	Sat Mar 29 11:10:53 2008
@@ -300,10 +300,23 @@
  Using local APIC (nmi_watchdog=2) needs the first performance register, so
  you can't use it for other purposes (such as high precision performance
 diff --git a/MAINTAINERS b/MAINTAINERS
-index 73883b8..f1ed75c 100644
+index 73883b8..90dcbbc 100644
 --- a/MAINTAINERS
 +++ b/MAINTAINERS
-@@ -2110,7 +2110,7 @@ M:	reinette.chatre at intel.com
+@@ -163,6 +163,12 @@ M:	A2232 at gmx.net
+ L:	linux-m68k at lists.linux-m68k.org
+ S:	Maintained
+ 
++AFS FILESYSTEM & AF_RXRPC SOCKET DOMAIN
++P:	David Howells
++M:	dhowells at redhat.com
++L:	linux-afs at lists.infradead.org
++S:	Supported
++
+ AIO
+ P:	Benjamin LaHaise
+ M:	bcrl at kvack.org
+@@ -2110,7 +2116,7 @@ M:	reinette.chatre at intel.com
  L:	linux-wireless at vger.kernel.org
  L:	ipw3945-devel at lists.sourceforge.net
  W:	http://intellinuxwireless.org
@@ -312,7 +325,15 @@
  S:	Supported
  
  IOC3 ETHERNET DRIVER
-@@ -2322,6 +2322,8 @@ P:	Anil S Keshavamurthy
+@@ -2314,14 +2320,14 @@ L:	kexec at lists.infradead.org
+ S:	Maintained
+ 
+ KPROBES
+-P:	Prasanna S Panchamukhi
+-M:	prasanna at in.ibm.com
+ P:	Ananth N Mavinakayanahalli
+ M:	ananth at in.ibm.com
+ P:	Anil S Keshavamurthy
  M:	anil.s.keshavamurthy at intel.com
  P:	David S. Miller
  M:	davem at davemloft.net
@@ -2962,6 +2983,29 @@
  	if (error_code & PF_INSTR)
  		return 0;
  
+diff --git a/arch/x86/mm/highmem_32.c b/arch/x86/mm/highmem_32.c
+index 3d936f2..9cf33d3 100644
+--- a/arch/x86/mm/highmem_32.c
++++ b/arch/x86/mm/highmem_32.c
+@@ -73,15 +73,15 @@ void *kmap_atomic_prot(struct page *page, enum km_type type, pgprot_t prot)
+ {
+ 	enum fixed_addresses idx;
+ 	unsigned long vaddr;
+-	/* even !CONFIG_PREEMPT needs this, for in_atomic in do_page_fault */
+-
+-	debug_kmap_atomic_prot(type);
+ 
++	/* even !CONFIG_PREEMPT needs this, for in_atomic in do_page_fault */
+ 	pagefault_disable();
+ 
+ 	if (!PageHighMem(page))
+ 		return page_address(page);
+ 
++	debug_kmap_atomic_prot(type);
++
+ 	idx = type + KM_TYPE_NR*smp_processor_id();
+ 	vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
+ 	BUG_ON(!pte_none(*(kmap_pte-idx)));
 diff --git a/arch/x86/mm/hugetlbpage.c b/arch/x86/mm/hugetlbpage.c
 index 4fbafb4..0b3d567 100644
 --- a/arch/x86/mm/hugetlbpage.c
@@ -3205,6 +3249,45 @@
  
  		cid_list = acpi_dev->pnp.cid_list;
  		for (i = 0; i < cid_list->count; i++) {
+diff --git a/drivers/base/driver.c b/drivers/base/driver.c
+index bf31a01..9a6537f 100644
+--- a/drivers/base/driver.c
++++ b/drivers/base/driver.c
+@@ -133,6 +133,7 @@ int driver_add_kobj(struct device_driver *drv, struct kobject *kobj,
+ {
+ 	va_list args;
+ 	char *name;
++	int ret;
+ 
+ 	va_start(args, fmt);
+ 	name = kvasprintf(GFP_KERNEL, fmt, args);
+@@ -141,7 +142,9 @@ int driver_add_kobj(struct device_driver *drv, struct kobject *kobj,
+ 	if (!name)
+ 		return -ENOMEM;
+ 
+-	return kobject_add(kobj, &drv->p->kobj, "%s", name);
++	ret = kobject_add(kobj, &drv->p->kobj, "%s", name);
++	kfree(name);
++	return ret;
+ }
+ EXPORT_SYMBOL_GPL(driver_add_kobj);
+ 
+diff --git a/drivers/char/drm/ati_pcigart.c b/drivers/char/drm/ati_pcigart.c
+index e5a0e97..35d25d8 100644
+--- a/drivers/char/drm/ati_pcigart.c
++++ b/drivers/char/drm/ati_pcigart.c
+@@ -122,8 +122,9 @@ int drm_ati_pcigart_init(struct drm_device *dev, struct drm_ati_pcigart_info *ga
+ 	} else {
+ 		address = gart_info->addr;
+ 		bus_address = gart_info->bus_addr;
+-		DRM_DEBUG("PCI: Gart Table: VRAM %08X mapped at %08lX\n",
+-			  bus_address, (unsigned long)address);
++		DRM_DEBUG("PCI: Gart Table: VRAM %08LX mapped at %08lX\n",
++			  (unsigned long long)bus_address,
++			  (unsigned long)address);
+ 	}
+ 
+ 	pci_gart = (u32 *) address;
 diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c
 index d73663a..fc555a9 100644
 --- a/drivers/cpuidle/cpuidle.c
@@ -3268,6 +3351,18 @@
  	attrs.max_ord = ep->ord;
  	attrs.llp_stream_handle = ep;
  	attrs.next_state = IWCH_QP_STATE_RTS;
+diff --git a/drivers/input/misc/ixp4xx-beeper.c b/drivers/input/misc/ixp4xx-beeper.c
+index d2ade74..798d84c 100644
+--- a/drivers/input/misc/ixp4xx-beeper.c
++++ b/drivers/input/misc/ixp4xx-beeper.c
+@@ -25,6 +25,7 @@
+ MODULE_AUTHOR("Alessandro Zummo <a.zummo at towertech.it>");
+ MODULE_DESCRIPTION("ixp4xx beeper driver");
+ MODULE_LICENSE("GPL");
++MODULE_ALIAS("platform:ixp4xx-beeper");
+ 
+ static DEFINE_SPINLOCK(beep_lock);
+ 
 diff --git a/drivers/lguest/Makefile b/drivers/lguest/Makefile
 index 5e8272d..7d463c2 100644
 --- a/drivers/lguest/Makefile
@@ -3754,6 +3849,335 @@
  // Yet both must save Guest state and restore Host
  // So we put the routine in a macro.
  #define SWITCH_TO_HOST							\
+diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c
+index b04f98d..835def1 100644
+--- a/drivers/md/dm-crypt.c
++++ b/drivers/md/dm-crypt.c
+@@ -1,7 +1,7 @@
+ /*
+  * Copyright (C) 2003 Christophe Saout <christophe at saout.de>
+  * Copyright (C) 2004 Clemens Fruhwirth <clemens at endorphin.org>
+- * Copyright (C) 2006-2007 Red Hat, Inc. All rights reserved.
++ * Copyright (C) 2006-2008 Red Hat, Inc. All rights reserved.
+  *
+  * This file is released under the GPL.
+  */
+@@ -93,6 +93,8 @@ struct crypt_config {
+ 
+ 	struct workqueue_struct *io_queue;
+ 	struct workqueue_struct *crypt_queue;
++	wait_queue_head_t writeq;
++
+ 	/*
+ 	 * crypto related data
+ 	 */
+@@ -331,14 +333,7 @@ static void crypt_convert_init(struct crypt_config *cc,
+ 	ctx->idx_out = bio_out ? bio_out->bi_idx : 0;
+ 	ctx->sector = sector + cc->iv_offset;
+ 	init_completion(&ctx->restart);
+-	/*
+-	 * Crypto operation can be asynchronous,
+-	 * ctx->pending is increased after request submission.
+-	 * We need to ensure that we don't call the crypt finish
+-	 * operation before pending got incremented
+-	 * (dependent on crypt submission return code).
+-	 */
+-	atomic_set(&ctx->pending, 2);
++	atomic_set(&ctx->pending, 1);
+ }
+ 
+ static int crypt_convert_block(struct crypt_config *cc,
+@@ -411,43 +406,42 @@ static void crypt_alloc_req(struct crypt_config *cc,
+ static int crypt_convert(struct crypt_config *cc,
+ 			 struct convert_context *ctx)
+ {
+-	int r = 0;
++	int r;
+ 
+ 	while(ctx->idx_in < ctx->bio_in->bi_vcnt &&
+ 	      ctx->idx_out < ctx->bio_out->bi_vcnt) {
+ 
+ 		crypt_alloc_req(cc, ctx);
+ 
++		atomic_inc(&ctx->pending);
++
+ 		r = crypt_convert_block(cc, ctx, cc->req);
+ 
+ 		switch (r) {
++		/* async */
+ 		case -EBUSY:
+ 			wait_for_completion(&ctx->restart);
+ 			INIT_COMPLETION(ctx->restart);
+ 			/* fall through*/
+ 		case -EINPROGRESS:
+-			atomic_inc(&ctx->pending);
+ 			cc->req = NULL;
+-			r = 0;
+-			/* fall through*/
++			ctx->sector++;
++			continue;
++
++		/* sync */
+ 		case 0:
++			atomic_dec(&ctx->pending);
+ 			ctx->sector++;
+ 			continue;
+-		}
+ 
+-		break;
++		/* error */
++		default:
++			atomic_dec(&ctx->pending);
++			return r;
++		}
+ 	}
+ 
+-	/*
+-	 * If there are pending crypto operation run async
+-	 * code. Otherwise process return code synchronously.
+-	 * The step of 2 ensures that async finish doesn't
+-	 * call crypto finish too early.
+-	 */
+-	if (atomic_sub_return(2, &ctx->pending))
+-		return -EINPROGRESS;
+-
+-	return r;
++	return 0;
+ }
+ 
+ static void dm_crypt_bio_destructor(struct bio *bio)
+@@ -624,8 +618,10 @@ static void kcryptd_io_read(struct dm_crypt_io *io)
+ static void kcryptd_io_write(struct dm_crypt_io *io)
+ {
+ 	struct bio *clone = io->ctx.bio_out;
++	struct crypt_config *cc = io->target->private;
+ 
+ 	generic_make_request(clone);
++	wake_up(&cc->writeq);
+ }
+ 
+ static void kcryptd_io(struct work_struct *work)
+@@ -698,7 +694,8 @@ static void kcryptd_crypt_write_convert_loop(struct dm_crypt_io *io)
+ 
+ 		r = crypt_convert(cc, &io->ctx);
+ 
+-		if (r != -EINPROGRESS) {
++		if (atomic_dec_and_test(&io->ctx.pending)) {
++			/* processed, no running async crypto  */
+ 			kcryptd_crypt_write_io_submit(io, r, 0);
+ 			if (unlikely(r < 0))
+ 				return;
+@@ -706,8 +703,12 @@ static void kcryptd_crypt_write_convert_loop(struct dm_crypt_io *io)
+ 			atomic_inc(&io->pending);
+ 
+ 		/* out of memory -> run queues */
+-		if (unlikely(remaining))
++		if (unlikely(remaining)) {
++			/* wait for async crypto then reinitialize pending */
++			wait_event(cc->writeq, !atomic_read(&io->ctx.pending));
++			atomic_set(&io->ctx.pending, 1);
+ 			congestion_wait(WRITE, HZ/100);
++		}
+ 	}
+ }
+ 
+@@ -746,7 +747,7 @@ static void kcryptd_crypt_read_convert(struct dm_crypt_io *io)
+ 
+ 	r = crypt_convert(cc, &io->ctx);
+ 
+-	if (r != -EINPROGRESS)
++	if (atomic_dec_and_test(&io->ctx.pending))
+ 		kcryptd_crypt_read_done(io, r);
+ 
+ 	crypt_dec_pending(io);
+@@ -1047,6 +1048,7 @@ static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv)
+ 		goto bad_crypt_queue;
+ 	}
+ 
++	init_waitqueue_head(&cc->writeq);
+ 	ti->private = cc;
+ 	return 0;
+ 
+diff --git a/drivers/md/dm-io.c b/drivers/md/dm-io.c
+index b8e342f..8f25f62 100644
+--- a/drivers/md/dm-io.c
++++ b/drivers/md/dm-io.c
+@@ -114,7 +114,7 @@ static void dec_count(struct io *io, unsigned int region, int error)
+ 			wake_up_process(io->sleeper);
+ 
+ 		else {
+-			int r = io->error;
++			unsigned long r = io->error;
+ 			io_notify_fn fn = io->callback;
+ 			void *context = io->context;
+ 
+diff --git a/drivers/md/dm-raid1.c b/drivers/md/dm-raid1.c
+index 5160587..762cb08 100644
+--- a/drivers/md/dm-raid1.c
++++ b/drivers/md/dm-raid1.c
+@@ -753,7 +753,7 @@ out:
+  * are in the no-sync state.  We have to recover these by
+  * recopying from the default mirror to all the others.
+  *---------------------------------------------------------------*/
+-static void recovery_complete(int read_err, unsigned int write_err,
++static void recovery_complete(int read_err, unsigned long write_err,
+ 			      void *context)
+ {
+ 	struct region *reg = (struct region *)context;
+@@ -767,7 +767,7 @@ static void recovery_complete(int read_err, unsigned int write_err,
+ 	}
+ 
+ 	if (write_err) {
+-		DMERR_LIMIT("Write error during recovery (error = 0x%x)",
++		DMERR_LIMIT("Write error during recovery (error = 0x%lx)",
+ 			    write_err);
+ 		/*
+ 		 * Bits correspond to devices (excluding default mirror).
+diff --git a/drivers/md/dm-snap.c b/drivers/md/dm-snap.c
+index ae24eab..4dc8a43 100644
+--- a/drivers/md/dm-snap.c
++++ b/drivers/md/dm-snap.c
+@@ -804,7 +804,7 @@ static void commit_callback(void *context, int success)
+  * Called when the copy I/O has finished.  kcopyd actually runs
+  * this code so don't block.
+  */
+-static void copy_callback(int read_err, unsigned int write_err, void *context)
++static void copy_callback(int read_err, unsigned long write_err, void *context)
+ {
+ 	struct dm_snap_pending_exception *pe = context;
+ 	struct dm_snapshot *s = pe->snap;
+diff --git a/drivers/md/kcopyd.c b/drivers/md/kcopyd.c
+index f3831f3..e76b52a 100644
+--- a/drivers/md/kcopyd.c
++++ b/drivers/md/kcopyd.c
+@@ -169,7 +169,7 @@ struct kcopyd_job {
+ 	 * Error state of the job.
+ 	 */
+ 	int read_err;
+-	unsigned int write_err;
++	unsigned long write_err;
+ 
+ 	/*
+ 	 * Either READ or WRITE
+@@ -293,7 +293,7 @@ static int run_complete_job(struct kcopyd_job *job)
+ {
+ 	void *context = job->context;
+ 	int read_err = job->read_err;
+-	unsigned int write_err = job->write_err;
++	unsigned long write_err = job->write_err;
+ 	kcopyd_notify_fn fn = job->fn;
+ 	struct kcopyd_client *kc = job->kc;
+ 
+@@ -396,7 +396,7 @@ static int process_jobs(struct list_head *jobs, int (*fn) (struct kcopyd_job *))
+ 		if (r < 0) {
+ 			/* error this rogue job */
+ 			if (job->rw == WRITE)
+-				job->write_err = (unsigned int) -1;
++				job->write_err = (unsigned long) -1L;
+ 			else
+ 				job->read_err = 1;
+ 			push(&_complete_jobs, job);
+@@ -448,8 +448,8 @@ static void dispatch_job(struct kcopyd_job *job)
+ }
+ 
+ #define SUB_JOB_SIZE 128
+-static void segment_complete(int read_err,
+-			     unsigned int write_err, void *context)
++static void segment_complete(int read_err, unsigned long write_err,
++			     void *context)
+ {
+ 	/* FIXME: tidy this function */
+ 	sector_t progress = 0;
+diff --git a/drivers/md/kcopyd.h b/drivers/md/kcopyd.h
+index 4621ea0..4845f2a 100644
+--- a/drivers/md/kcopyd.h
++++ b/drivers/md/kcopyd.h
+@@ -32,8 +32,8 @@ void kcopyd_client_destroy(struct kcopyd_client *kc);
+  * read_err is a boolean,
+  * write_err is a bitset, with 1 bit for each destination region
+  */
+-typedef void (*kcopyd_notify_fn)(int read_err,
+-				 unsigned int write_err, void *context);
++typedef void (*kcopyd_notify_fn)(int read_err, unsigned long write_err,
++				 void *context);
+ 
+ int kcopyd_copy(struct kcopyd_client *kc, struct io_region *from,
+ 		unsigned int num_dests, struct io_region *dests,
+diff --git a/drivers/memstick/host/tifm_ms.c b/drivers/memstick/host/tifm_ms.c
+index eb150df..8577de4 100644
+--- a/drivers/memstick/host/tifm_ms.c
++++ b/drivers/memstick/host/tifm_ms.c
+@@ -182,7 +182,7 @@ static unsigned int tifm_ms_transfer_data(struct tifm_ms *host)
+ 	struct tifm_dev *sock = host->dev;
+ 	unsigned int length;
+ 	unsigned int off;
+-	unsigned int t_size, p_off, p_cnt;
++	unsigned int t_size, p_cnt;
+ 	unsigned char *buf;
+ 	struct page *pg;
+ 	unsigned long flags = 0;
+@@ -198,6 +198,8 @@ static unsigned int tifm_ms_transfer_data(struct tifm_ms *host)
+ 		host->block_pos);
+ 
+ 	while (length) {
++		unsigned int uninitialized_var(p_off);
++
+ 		if (host->req->long_data) {
+ 			pg = nth_page(sg_page(&host->req->sg),
+ 				      off >> PAGE_SHIFT);
+diff --git a/drivers/mtd/maps/physmap.c b/drivers/mtd/maps/physmap.c
+index f00e04e..bc4649a 100644
+--- a/drivers/mtd/maps/physmap.c
++++ b/drivers/mtd/maps/physmap.c
+@@ -202,9 +202,8 @@ static int physmap_flash_suspend(struct platform_device *dev, pm_message_t state
+ 	int ret = 0;
+ 	int i;
+ 
+-	if (info)
+-		for (i = 0; i < MAX_RESOURCES; i++)
+-			ret |= info->mtd[i]->suspend(info->mtd[i]);
++	for (i = 0; i < MAX_RESOURCES && info->mtd[i]; i++)
++		ret |= info->mtd[i]->suspend(info->mtd[i]);
+ 
+ 	return ret;
+ }
+@@ -214,9 +213,9 @@ static int physmap_flash_resume(struct platform_device *dev)
+ 	struct physmap_flash_info *info = platform_get_drvdata(dev);
+ 	int i;
+ 
+-	if (info)
+-		for (i = 0; i < MAX_RESOURCES; i++)
+-			info->mtd[i]->resume(info->mtd[i]);
++	for (i = 0; i < MAX_RESOURCES && info->mtd[i]; i++)
++		info->mtd[i]->resume(info->mtd[i]);
++
+ 	return 0;
+ }
+ 
+@@ -225,8 +224,8 @@ static void physmap_flash_shutdown(struct platform_device *dev)
+ 	struct physmap_flash_info *info = platform_get_drvdata(dev);
+ 	int i;
+ 
+-	for (i = 0; i < MAX_RESOURCES; i++)
+-		if (info && info->mtd[i]->suspend(info->mtd[i]) == 0)
++	for (i = 0; i < MAX_RESOURCES && info->mtd[i]; i++)
++		if (info->mtd[i]->suspend(info->mtd[i]) == 0)
+ 			info->mtd[i]->resume(info->mtd[i]);
+ }
+ #else
+diff --git a/drivers/mtd/nand/rtc_from4.c b/drivers/mtd/nand/rtc_from4.c
+index 9189ec8..0f6ac25 100644
+--- a/drivers/mtd/nand/rtc_from4.c
++++ b/drivers/mtd/nand/rtc_from4.c
+@@ -460,7 +460,7 @@ static int rtc_from4_errstat(struct mtd_info *mtd, struct nand_chip *this,
+ 			er_stat |= 1 << 1;
+ 		kfree(buf);
+ 	}
+-
++out:
+ 	rtn = status;
+ 	if (er_stat == 0) {	/* if ECC is available   */
+ 		rtn = (status & ~NAND_STATUS_FAIL);	/*   clear the error bit */
 diff --git a/drivers/net/b44.c b/drivers/net/b44.c
 index ea2a2b5..25f1337 100644
 --- a/drivers/net/b44.c
@@ -5982,6 +6406,35 @@
  
  /* Size for structure checking (if padding is correct) */
  #define	MMW_SIZE	37
+diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
+index e9a333d..e887aa4 100644
+--- a/drivers/pci/quirks.c
++++ b/drivers/pci/quirks.c
+@@ -951,6 +951,12 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82375,	quirk_e
+  * accesses to the SMBus registers, with potentially bad effects. Thus you
+  * should be very careful when adding new entries: if SMM is accessing the
+  * Intel SMBus, this is a very good reason to leave it hidden.
++ *
++ * Likewise, many recent laptops use ACPI for thermal management. If the
++ * ACPI DSDT code accesses the SMBus, then Linux should not access it
++ * natively, and keeping the SMBus hidden is the right thing to do. If you
++ * are about to add an entry in the table below, please first disassemble
++ * the DSDT and double-check that there is no code accessing the SMBus.
+  */
+ static int asus_hides_smbus;
+ 
+@@ -1028,11 +1034,6 @@ static void __init asus_hides_smbus_hostbridge(struct pci_dev *dev)
+ 			case 0x12bf: /* HP xw4100 */
+ 				asus_hides_smbus = 1;
+ 			}
+-		else if (dev->device == PCI_DEVICE_ID_INTEL_82915GM_HB)
+-			switch (dev->subsystem_device) {
+-			case 0x099c: /* HP Compaq nx6110 */
+-				asus_hides_smbus = 1;
+-			}
+        } else if (unlikely(dev->subsystem_vendor == PCI_VENDOR_ID_SAMSUNG)) {
+                if (dev->device ==  PCI_DEVICE_ID_INTEL_82855PM_HB)
+                        switch(dev->subsystem_device) {
 diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c
 index 125e7b7..f7cb8e0 100644
 --- a/drivers/pci/setup-bus.c
@@ -6039,6 +6492,139 @@
  				"resources: %d\n", PNP_MAX_MEM);
  		warned = 1;
  	}
+diff --git a/drivers/video/bf54x-lq043fb.c b/drivers/video/bf54x-lq043fb.c
+index 986a550..eefba3d 100644
+--- a/drivers/video/bf54x-lq043fb.c
++++ b/drivers/video/bf54x-lq043fb.c
+@@ -384,7 +384,7 @@ static int bfin_bf54x_fb_mmap(struct fb_info *info, struct vm_area_struct *vma)
+ 	 *   Other flags can be set, and are documented in
+ 	 *   include/linux/mm.h
+ 	 */
+-	vma->vm_flags |= VM_MAYSHARE;
++	vma->vm_flags |=  VM_MAYSHARE | VM_SHARED;
+ 
+ 	return 0;
+ }
+diff --git a/drivers/video/bfin-t350mcqb-fb.c b/drivers/video/bfin-t350mcqb-fb.c
+index a2bb2de..135d6dd 100644
+--- a/drivers/video/bfin-t350mcqb-fb.c
++++ b/drivers/video/bfin-t350mcqb-fb.c
+@@ -91,6 +91,7 @@ struct bfin_t350mcqbfb_info {
+ 	int lq043_open_cnt;
+ 	int irq;
+ 	spinlock_t lock;	/* lock */
++	u32 pseudo_pal[16];
+ };
+ 
+ static int nocursor;
+@@ -182,13 +183,13 @@ static void bfin_t350mcqb_config_dma(struct bfin_t350mcqbfb_info *fbi)
+ 
+ }
+ 
+-static int bfin_t350mcqb_request_ports(int action)
+-{
+-	u16 ppi0_req_8[] = {P_PPI0_CLK, P_PPI0_FS1, P_PPI0_FS2,
++static	u16 ppi0_req_8[] = {P_PPI0_CLK, P_PPI0_FS1, P_PPI0_FS2,
+ 			    P_PPI0_D0, P_PPI0_D1, P_PPI0_D2,
+ 			    P_PPI0_D3, P_PPI0_D4, P_PPI0_D5,
+ 			    P_PPI0_D6, P_PPI0_D7, 0};
+ 
++static int bfin_t350mcqb_request_ports(int action)
++{
+ 	if (action) {
+ 		if (peripheral_request_list(ppi0_req_8, DRIVER_NAME)) {
+ 			printk(KERN_ERR "Requesting Peripherals faild\n");
+@@ -301,7 +302,7 @@ static int bfin_t350mcqb_fb_mmap(struct fb_info *info, struct vm_area_struct *vm
+ 	 *   Other flags can be set, and are documented in
+ 	 *   include/linux/mm.h
+ 	 */
+-	vma->vm_flags |= VM_MAYSHARE;
++	vma->vm_flags |= VM_MAYSHARE | VM_SHARED;
+ 
+ 	return 0;
+ }
+@@ -520,16 +521,7 @@ static int __init bfin_t350mcqb_probe(struct platform_device *pdev)
+ 
+ 	fbinfo->fbops = &bfin_t350mcqb_fb_ops;
+ 
+-	fbinfo->pseudo_palette = kmalloc(sizeof(u32) * 16, GFP_KERNEL);
+-	if (!fbinfo->pseudo_palette) {
+-		printk(KERN_ERR DRIVER_NAME
+-		       "Fail to allocate pseudo_palette\n");
+-
+-		ret = -ENOMEM;
+-		goto out4;
+-	}
+-
+-	memset(fbinfo->pseudo_palette, 0, sizeof(u32) * 16);
++	fbinfo->pseudo_palette = &info->pseudo_pal;
+ 
+ 	if (fb_alloc_cmap(&fbinfo->cmap, BFIN_LCD_NBR_PALETTE_ENTRIES, 0)
+ 	    < 0) {
+@@ -537,7 +529,7 @@ static int __init bfin_t350mcqb_probe(struct platform_device *pdev)
+ 		       "Fail to allocate colormap (%d entries)\n",
+ 		       BFIN_LCD_NBR_PALETTE_ENTRIES);
+ 		ret = -EFAULT;
+-		goto out5;
++		goto out4;
+ 	}
+ 
+ 	if (bfin_t350mcqb_request_ports(1)) {
+@@ -552,11 +544,11 @@ static int __init bfin_t350mcqb_probe(struct platform_device *pdev)
+ 		goto out7;
+ 	}
+ 
+-	if (request_irq(info->irq, (void *)bfin_t350mcqb_irq_error, IRQF_DISABLED,
+-			"PPI ERROR", info) < 0) {
++	ret = request_irq(info->irq, bfin_t350mcqb_irq_error, IRQF_DISABLED,
++			"PPI ERROR", info);
++	if (ret < 0) {
+ 		printk(KERN_ERR DRIVER_NAME
+ 		       ": unable to request PPI ERROR IRQ\n");
+-		ret = -EFAULT;
+ 		goto out7;
+ 	}
+ 
+@@ -584,8 +576,6 @@ out7:
+ 	bfin_t350mcqb_request_ports(0);
+ out6:
+ 	fb_dealloc_cmap(&fbinfo->cmap);
+-out5:
+-	kfree(fbinfo->pseudo_palette);
+ out4:
+ 	dma_free_coherent(NULL, fbinfo->fix.smem_len, info->fb_buffer,
+ 			  info->dma_handle);
+@@ -605,6 +595,8 @@ static int bfin_t350mcqb_remove(struct platform_device *pdev)
+ 	struct fb_info *fbinfo = platform_get_drvdata(pdev);
+ 	struct bfin_t350mcqbfb_info *info = fbinfo->par;
+ 
++	unregister_framebuffer(fbinfo);
++
+ 	free_dma(CH_PPI);
+ 	free_irq(info->irq, info);
+ 
+@@ -612,7 +604,6 @@ static int bfin_t350mcqb_remove(struct platform_device *pdev)
+ 		dma_free_coherent(NULL, fbinfo->fix.smem_len, info->fb_buffer,
+ 				  info->dma_handle);
+ 
+-	kfree(fbinfo->pseudo_palette);
+ 	fb_dealloc_cmap(&fbinfo->cmap);
+ 
+ #ifndef NO_BL_SUPPORT
+@@ -620,10 +611,11 @@ static int bfin_t350mcqb_remove(struct platform_device *pdev)
+ 	backlight_device_unregister(bl_dev);
+ #endif
+ 
+-	unregister_framebuffer(fbinfo);
+-
+ 	bfin_t350mcqb_request_ports(0);
+ 
++	platform_set_drvdata(pdev, NULL);
++	framebuffer_release(fbinfo);
++
+ 	printk(KERN_INFO DRIVER_NAME ": Unregister LCD driver.\n");
+ 
+ 	return 0;
 diff --git a/drivers/virtio/virtio_pci.c b/drivers/virtio/virtio_pci.c
 index 59a8f73..6c8ecde 100644
 --- a/drivers/virtio/virtio_pci.c
@@ -6051,6 +6637,568 @@
  	free_irq(pci_dev->irq, vp_dev);
  	pci_set_drvdata(pci_dev, NULL);
  	pci_iounmap(pci_dev, vp_dev->ioaddr);
+diff --git a/fs/afs/cell.c b/fs/afs/cell.c
+index 970d38f..788865d 100644
+--- a/fs/afs/cell.c
++++ b/fs/afs/cell.c
+@@ -127,14 +127,20 @@ struct afs_cell *afs_cell_create(const char *name, char *vllist)
+ 
+ 	_enter("%s,%s", name, vllist);
+ 
++	down_write(&afs_cells_sem);
++	read_lock(&afs_cells_lock);
++	list_for_each_entry(cell, &afs_cells, link) {
++		if (strcasecmp(cell->name, name) == 0)
++			goto duplicate_name;
++	}
++	read_unlock(&afs_cells_lock);
++
+ 	cell = afs_cell_alloc(name, vllist);
+ 	if (IS_ERR(cell)) {
+ 		_leave(" = %ld", PTR_ERR(cell));
+ 		return cell;
+ 	}
+ 
+-	down_write(&afs_cells_sem);
+-
+ 	/* add a proc directory for this cell */
+ 	ret = afs_proc_cell_setup(cell);
+ 	if (ret < 0)
+@@ -167,6 +173,11 @@ error:
+ 	kfree(cell);
+ 	_leave(" = %d", ret);
+ 	return ERR_PTR(ret);
++
++duplicate_name:
++	read_unlock(&afs_cells_lock);
++	up_write(&afs_cells_sem);
++	return ERR_PTR(-EEXIST);
+ }
+ 
+ /*
+diff --git a/fs/afs/internal.h b/fs/afs/internal.h
+index 5ca3625..9ba16ed 100644
+--- a/fs/afs/internal.h
++++ b/fs/afs/internal.h
+@@ -573,7 +573,6 @@ extern const struct file_operations afs_mntpt_file_operations;
+ 
+ extern int afs_mntpt_check_symlink(struct afs_vnode *, struct key *);
+ extern void afs_mntpt_kill_timer(void);
+-extern void afs_umount_begin(struct vfsmount *, int);
+ 
+ /*
+  * proc.c
+diff --git a/fs/afs/mntpt.c b/fs/afs/mntpt.c
+index a3510b8..2f55039 100644
+--- a/fs/afs/mntpt.c
++++ b/fs/afs/mntpt.c
+@@ -283,11 +283,3 @@ void afs_mntpt_kill_timer(void)
+ 	cancel_delayed_work(&afs_mntpt_expiry_timer);
+ 	flush_scheduled_work();
+ }
+-
+-/*
+- * begin unmount by attempting to remove all automounted mountpoints we added
+- */
+-void afs_umount_begin(struct vfsmount *vfsmnt, int flags)
+-{
+-	shrink_submounts(vfsmnt, &afs_vfsmounts);
+-}
+diff --git a/fs/afs/super.c b/fs/afs/super.c
+index 36bbce4..4b572b8 100644
+--- a/fs/afs/super.c
++++ b/fs/afs/super.c
+@@ -50,7 +50,6 @@ static const struct super_operations afs_super_ops = {
+ 	.write_inode	= afs_write_inode,
+ 	.destroy_inode	= afs_destroy_inode,
+ 	.clear_inode	= afs_clear_inode,
+-	.umount_begin	= afs_umount_begin,
+ 	.put_super	= afs_put_super,
+ 	.show_options	= generic_show_options,
+ };
+diff --git a/fs/buffer.c b/fs/buffer.c
+index 7ba5838..9819632 100644
+--- a/fs/buffer.c
++++ b/fs/buffer.c
+@@ -2564,14 +2564,13 @@ int nobh_write_end(struct file *file, struct address_space *mapping,
+ 	struct inode *inode = page->mapping->host;
+ 	struct buffer_head *head = fsdata;
+ 	struct buffer_head *bh;
++	BUG_ON(fsdata != NULL && page_has_buffers(page));
+ 
+-	if (!PageMappedToDisk(page)) {
+-		if (unlikely(copied < len) && !page_has_buffers(page))
+-			attach_nobh_buffers(page, head);
+-		if (page_has_buffers(page))
+-			return generic_write_end(file, mapping, pos, len,
+-						copied, page, fsdata);
+-	}
++	if (unlikely(copied < len) && !page_has_buffers(page))
++		attach_nobh_buffers(page, head);
++	if (page_has_buffers(page))
++		return generic_write_end(file, mapping, pos, len,
++					copied, page, fsdata);
+ 
+ 	SetPageUptodate(page);
+ 	set_page_dirty(page);
+diff --git a/fs/cifs/cifs_dfs_ref.c b/fs/cifs/cifs_dfs_ref.c
+index a1a95b0..56c9240 100644
+--- a/fs/cifs/cifs_dfs_ref.c
++++ b/fs/cifs/cifs_dfs_ref.c
+@@ -33,7 +33,6 @@ void dfs_shrink_umount_helper(struct vfsmount *vfsmnt)
+ {
+ 	mark_mounts_for_expiry(&cifs_dfs_automount_list);
+ 	mark_mounts_for_expiry(&cifs_dfs_automount_list);
+-	shrink_submounts(vfsmnt, &cifs_dfs_automount_list);
+ }
+ 
+ /**
+diff --git a/fs/namespace.c b/fs/namespace.c
+index 7953c96..94f026e 100644
+--- a/fs/namespace.c
++++ b/fs/namespace.c
+@@ -155,15 +155,15 @@ static void __touch_mnt_namespace(struct mnt_namespace *ns)
+ 	}
+ }
+ 
+-static void detach_mnt(struct vfsmount *mnt, struct nameidata *old_nd)
++static void detach_mnt(struct vfsmount *mnt, struct path *old_path)
+ {
+-	old_nd->path.dentry = mnt->mnt_mountpoint;
+-	old_nd->path.mnt = mnt->mnt_parent;
++	old_path->dentry = mnt->mnt_mountpoint;
++	old_path->mnt = mnt->mnt_parent;
+ 	mnt->mnt_parent = mnt;
+ 	mnt->mnt_mountpoint = mnt->mnt_root;
+ 	list_del_init(&mnt->mnt_child);
+ 	list_del_init(&mnt->mnt_hash);
+-	old_nd->path.dentry->d_mounted--;
++	old_path->dentry->d_mounted--;
+ }
+ 
+ void mnt_set_mountpoint(struct vfsmount *mnt, struct dentry *dentry,
+@@ -174,12 +174,12 @@ void mnt_set_mountpoint(struct vfsmount *mnt, struct dentry *dentry,
+ 	dentry->d_mounted++;
+ }
+ 
+-static void attach_mnt(struct vfsmount *mnt, struct nameidata *nd)
++static void attach_mnt(struct vfsmount *mnt, struct path *path)
+ {
+-	mnt_set_mountpoint(nd->path.mnt, nd->path.dentry, mnt);
++	mnt_set_mountpoint(path->mnt, path->dentry, mnt);
+ 	list_add_tail(&mnt->mnt_hash, mount_hashtable +
+-			hash(nd->path.mnt, nd->path.dentry));
+-	list_add_tail(&mnt->mnt_child, &nd->path.mnt->mnt_mounts);
++			hash(path->mnt, path->dentry));
++	list_add_tail(&mnt->mnt_child, &path->mnt->mnt_mounts);
+ }
+ 
+ /*
+@@ -262,10 +262,8 @@ static struct vfsmount *clone_mnt(struct vfsmount *old, struct dentry *root,
+ 		/* stick the duplicate mount on the same expiry list
+ 		 * as the original if that was on one */
+ 		if (flag & CL_EXPIRE) {
+-			spin_lock(&vfsmount_lock);
+ 			if (!list_empty(&old->mnt_expire))
+ 				list_add(&mnt->mnt_expire, &old->mnt_expire);
+-			spin_unlock(&vfsmount_lock);
+ 		}
+ 	}
+ 	return mnt;
+@@ -548,6 +546,7 @@ void release_mounts(struct list_head *head)
+ 			m = mnt->mnt_parent;
+ 			mnt->mnt_mountpoint = mnt->mnt_root;
+ 			mnt->mnt_parent = mnt;
++			m->mnt_ghosts--;
+ 			spin_unlock(&vfsmount_lock);
+ 			dput(dentry);
+ 			mntput(m);
+@@ -572,12 +571,16 @@ void umount_tree(struct vfsmount *mnt, int propagate, struct list_head *kill)
+ 		__touch_mnt_namespace(p->mnt_ns);
+ 		p->mnt_ns = NULL;
+ 		list_del_init(&p->mnt_child);
+-		if (p->mnt_parent != p)
++		if (p->mnt_parent != p) {
++			p->mnt_parent->mnt_ghosts++;
+ 			p->mnt_mountpoint->d_mounted--;
++		}
+ 		change_mnt_propagation(p, MS_PRIVATE);
+ 	}
+ }
+ 
++static void shrink_submounts(struct vfsmount *mnt, struct list_head *umounts);
++
+ static int do_umount(struct vfsmount *mnt, int flags)
+ {
+ 	struct super_block *sb = mnt->mnt_sb;
+@@ -650,6 +653,9 @@ static int do_umount(struct vfsmount *mnt, int flags)
+ 	spin_lock(&vfsmount_lock);
+ 	event++;
+ 
++	if (!(flags & MNT_DETACH))
++		shrink_submounts(mnt, &umount_list);
++
+ 	retval = -EBUSY;
+ 	if (flags & MNT_DETACH || !propagate_mount_busy(mnt, 2)) {
+ 		if (!list_empty(&mnt->mnt_list))
+@@ -744,7 +750,7 @@ struct vfsmount *copy_tree(struct vfsmount *mnt, struct dentry *dentry,
+ 					int flag)
+ {
+ 	struct vfsmount *res, *p, *q, *r, *s;
+-	struct nameidata nd;
++	struct path path;
+ 
+ 	if (!(flag & CL_COPY_ALL) && IS_MNT_UNBINDABLE(mnt))
+ 		return NULL;
+@@ -769,14 +775,14 @@ struct vfsmount *copy_tree(struct vfsmount *mnt, struct dentry *dentry,
+ 				q = q->mnt_parent;
+ 			}
+ 			p = s;
+-			nd.path.mnt = q;
+-			nd.path.dentry = p->mnt_mountpoint;
++			path.mnt = q;
++			path.dentry = p->mnt_mountpoint;
+ 			q = clone_mnt(p, p->mnt_root, flag);
+ 			if (!q)
+ 				goto Enomem;
+ 			spin_lock(&vfsmount_lock);
+ 			list_add_tail(&q->mnt_list, &res->mnt_list);
+-			attach_mnt(q, &nd);
++			attach_mnt(q, &path);
+ 			spin_unlock(&vfsmount_lock);
+ 		}
+ 	}
+@@ -876,11 +882,11 @@ void drop_collected_mounts(struct vfsmount *mnt)
+  * in allocations.
+  */
+ static int attach_recursive_mnt(struct vfsmount *source_mnt,
+-			struct nameidata *nd, struct nameidata *parent_nd)
++			struct path *path, struct path *parent_path)
+ {
+ 	LIST_HEAD(tree_list);
+-	struct vfsmount *dest_mnt = nd->path.mnt;
+-	struct dentry *dest_dentry = nd->path.dentry;
++	struct vfsmount *dest_mnt = path->mnt;
++	struct dentry *dest_dentry = path->dentry;
+ 	struct vfsmount *child, *p;
+ 
+ 	if (propagate_mnt(dest_mnt, dest_dentry, source_mnt, &tree_list))
+@@ -892,9 +898,9 @@ static int attach_recursive_mnt(struct vfsmount *source_mnt,
+ 	}
+ 
+ 	spin_lock(&vfsmount_lock);
+-	if (parent_nd) {
+-		detach_mnt(source_mnt, parent_nd);
+-		attach_mnt(source_mnt, nd);
++	if (parent_path) {
++		detach_mnt(source_mnt, parent_path);
++		attach_mnt(source_mnt, path);
+ 		touch_mnt_namespace(current->nsproxy->mnt_ns);
+ 	} else {
+ 		mnt_set_mountpoint(dest_mnt, dest_dentry, source_mnt);
+@@ -930,7 +936,7 @@ static int graft_tree(struct vfsmount *mnt, struct nameidata *nd)
+ 
+ 	err = -ENOENT;
+ 	if (IS_ROOT(nd->path.dentry) || !d_unhashed(nd->path.dentry))
+-		err = attach_recursive_mnt(mnt, nd, NULL);
++		err = attach_recursive_mnt(mnt, &nd->path, NULL);
+ out_unlock:
+ 	mutex_unlock(&nd->path.dentry->d_inode->i_mutex);
+ 	if (!err)
+@@ -1059,7 +1065,8 @@ static inline int tree_contains_unbindable(struct vfsmount *mnt)
+  */
+ static noinline int do_move_mount(struct nameidata *nd, char *old_name)
+ {
+-	struct nameidata old_nd, parent_nd;
++	struct nameidata old_nd;
++	struct path parent_path;
+ 	struct vfsmount *p;
+ 	int err = 0;
+ 	if (!capable(CAP_SYS_ADMIN))
+@@ -1114,21 +1121,19 @@ static noinline int do_move_mount(struct nameidata *nd, char *old_name)
+ 		if (p == old_nd.path.mnt)
+ 			goto out1;
+ 
+-	err = attach_recursive_mnt(old_nd.path.mnt, nd, &parent_nd);
++	err = attach_recursive_mnt(old_nd.path.mnt, &nd->path, &parent_path);
+ 	if (err)
+ 		goto out1;
+ 
+-	spin_lock(&vfsmount_lock);
+ 	/* if the mount is moved, it should no longer be expire
+ 	 * automatically */
+ 	list_del_init(&old_nd.path.mnt->mnt_expire);
+-	spin_unlock(&vfsmount_lock);
+ out1:
+ 	mutex_unlock(&nd->path.dentry->d_inode->i_mutex);
+ out:
+ 	up_write(&namespace_sem);
+ 	if (!err)
+-		path_put(&parent_nd.path);
++		path_put(&parent_path);
+ 	path_put(&old_nd.path);
+ 	return err;
+ }
+@@ -1189,12 +1194,9 @@ int do_add_mount(struct vfsmount *newmnt, struct nameidata *nd,
+ 	if ((err = graft_tree(newmnt, nd)))
+ 		goto unlock;
+ 
+-	if (fslist) {
+-		/* add to the specified expiration list */
+-		spin_lock(&vfsmount_lock);
++	if (fslist) /* add to the specified expiration list */
+ 		list_add_tail(&newmnt->mnt_expire, fslist);
+-		spin_unlock(&vfsmount_lock);
+-	}
++
+ 	up_write(&namespace_sem);
+ 	return 0;
+ 
+@@ -1206,75 +1208,6 @@ unlock:
+ 
+ EXPORT_SYMBOL_GPL(do_add_mount);
+ 
+-static void expire_mount(struct vfsmount *mnt, struct list_head *mounts,
+-				struct list_head *umounts)
+-{
+-	spin_lock(&vfsmount_lock);
+-
+-	/*
+-	 * Check if mount is still attached, if not, let whoever holds it deal
+-	 * with the sucker
+-	 */
+-	if (mnt->mnt_parent == mnt) {
+-		spin_unlock(&vfsmount_lock);
+-		return;
+-	}
+-
+-	/*
+-	 * Check that it is still dead: the count should now be 2 - as
+-	 * contributed by the vfsmount parent and the mntget above
+-	 */
+-	if (!propagate_mount_busy(mnt, 2)) {
+-		/* delete from the namespace */
+-		touch_mnt_namespace(mnt->mnt_ns);
+-		list_del_init(&mnt->mnt_list);
+-		mnt->mnt_ns = NULL;
+-		umount_tree(mnt, 1, umounts);
+-		spin_unlock(&vfsmount_lock);
+-	} else {
+-		/*
+-		 * Someone brought it back to life whilst we didn't have any
+-		 * locks held so return it to the expiration list
+-		 */
+-		list_add_tail(&mnt->mnt_expire, mounts);
+-		spin_unlock(&vfsmount_lock);
+-	}
+-}
+-
+-/*
+- * go through the vfsmounts we've just consigned to the graveyard to
+- * - check that they're still dead
+- * - delete the vfsmount from the appropriate namespace under lock
+- * - dispose of the corpse
+- */
+-static void expire_mount_list(struct list_head *graveyard, struct list_head *mounts)
+-{
+-	struct mnt_namespace *ns;
+-	struct vfsmount *mnt;
+-
+-	while (!list_empty(graveyard)) {
+-		LIST_HEAD(umounts);
+-		mnt = list_first_entry(graveyard, struct vfsmount, mnt_expire);
+-		list_del_init(&mnt->mnt_expire);
+-
+-		/* don't do anything if the namespace is dead - all the
+-		 * vfsmounts from it are going away anyway */
+-		ns = mnt->mnt_ns;
+-		if (!ns || !ns->root)
+-			continue;
+-		get_mnt_ns(ns);
+-
+-		spin_unlock(&vfsmount_lock);
+-		down_write(&namespace_sem);
+-		expire_mount(mnt, mounts, &umounts);
+-		up_write(&namespace_sem);
+-		release_mounts(&umounts);
+-		mntput(mnt);
+-		put_mnt_ns(ns);
+-		spin_lock(&vfsmount_lock);
+-	}
+-}
+-
+ /*
+  * process a list of expirable mountpoints with the intent of discarding any
+  * mountpoints that aren't in use and haven't been touched since last we came
+@@ -1284,10 +1217,12 @@ void mark_mounts_for_expiry(struct list_head *mounts)
+ {
+ 	struct vfsmount *mnt, *next;
+ 	LIST_HEAD(graveyard);
++	LIST_HEAD(umounts);
+ 
+ 	if (list_empty(mounts))
+ 		return;
+ 
++	down_write(&namespace_sem);
+ 	spin_lock(&vfsmount_lock);
+ 
+ 	/* extract from the expiration list every vfsmount that matches the
+@@ -1298,16 +1233,19 @@ void mark_mounts_for_expiry(struct list_head *mounts)
+ 	 */
+ 	list_for_each_entry_safe(mnt, next, mounts, mnt_expire) {
+ 		if (!xchg(&mnt->mnt_expiry_mark, 1) ||
+-		    atomic_read(&mnt->mnt_count) != 1)
++			propagate_mount_busy(mnt, 1))
+ 			continue;
+-
+-		mntget(mnt);
+ 		list_move(&mnt->mnt_expire, &graveyard);
+ 	}
+-
+-	expire_mount_list(&graveyard, mounts);
+-
++	while (!list_empty(&graveyard)) {
++		mnt = list_first_entry(&graveyard, struct vfsmount, mnt_expire);
++		touch_mnt_namespace(mnt->mnt_ns);
++		umount_tree(mnt, 1, &umounts);
++	}
+ 	spin_unlock(&vfsmount_lock);
++	up_write(&namespace_sem);
++
++	release_mounts(&umounts);
+ }
+ 
+ EXPORT_SYMBOL_GPL(mark_mounts_for_expiry);
+@@ -1343,7 +1281,6 @@ resume:
+ 		}
+ 
+ 		if (!propagate_mount_busy(mnt, 1)) {
+-			mntget(mnt);
+ 			list_move_tail(&mnt->mnt_expire, graveyard);
+ 			found++;
+ 		}
+@@ -1363,22 +1300,22 @@ resume:
+  * process a list of expirable mountpoints with the intent of discarding any
+  * submounts of a specific parent mountpoint
+  */
+-void shrink_submounts(struct vfsmount *mountpoint, struct list_head *mounts)
++static void shrink_submounts(struct vfsmount *mnt, struct list_head *umounts)
+ {
+ 	LIST_HEAD(graveyard);
+-	int found;
+-
+-	spin_lock(&vfsmount_lock);
++	struct vfsmount *m;
+ 
+ 	/* extract submounts of 'mountpoint' from the expiration list */
+-	while ((found = select_submounts(mountpoint, &graveyard)) != 0)
+-		expire_mount_list(&graveyard, mounts);
+-
+-	spin_unlock(&vfsmount_lock);
++	while (select_submounts(mnt, &graveyard)) {
++		while (!list_empty(&graveyard)) {
++			m = list_first_entry(&graveyard, struct vfsmount,
++						mnt_expire);
++			touch_mnt_namespace(mnt->mnt_ns);
++			umount_tree(mnt, 1, umounts);
++		}
++	}
+ }
+ 
+-EXPORT_SYMBOL_GPL(shrink_submounts);
+-
+ /*
+  * Some copy_from_user() implementations do not return the exact number of
+  * bytes remaining to copy on a fault.  But copy_mount_options() requires that.
+@@ -1683,7 +1620,7 @@ void set_fs_pwd(struct fs_struct *fs, struct path *path)
+ 		path_put(&old_pwd);
+ }
+ 
+-static void chroot_fs_refs(struct nameidata *old_nd, struct nameidata *new_nd)
++static void chroot_fs_refs(struct path *old_root, struct path *new_root)
+ {
+ 	struct task_struct *g, *p;
+ 	struct fs_struct *fs;
+@@ -1695,12 +1632,12 @@ static void chroot_fs_refs(struct nameidata *old_nd, struct nameidata *new_nd)
+ 		if (fs) {
+ 			atomic_inc(&fs->count);
+ 			task_unlock(p);
+-			if (fs->root.dentry == old_nd->path.dentry
+-			    && fs->root.mnt == old_nd->path.mnt)
+-				set_fs_root(fs, &new_nd->path);
+-			if (fs->pwd.dentry == old_nd->path.dentry
+-			    && fs->pwd.mnt == old_nd->path.mnt)
+-				set_fs_pwd(fs, &new_nd->path);
++			if (fs->root.dentry == old_root->dentry
++			    && fs->root.mnt == old_root->mnt)
++				set_fs_root(fs, new_root);
++			if (fs->pwd.dentry == old_root->dentry
++			    && fs->pwd.mnt == old_root->mnt)
++				set_fs_pwd(fs, new_root);
+ 			put_fs_struct(fs);
+ 		} else
+ 			task_unlock(p);
+@@ -1737,7 +1674,8 @@ asmlinkage long sys_pivot_root(const char __user * new_root,
+ 			       const char __user * put_old)
+ {
+ 	struct vfsmount *tmp;
+-	struct nameidata new_nd, old_nd, parent_nd, root_parent, user_nd;
++	struct nameidata new_nd, old_nd, user_nd;
++	struct path parent_path, root_parent;
+ 	int error;
+ 
+ 	if (!capable(CAP_SYS_ADMIN))
+@@ -1811,19 +1749,19 @@ asmlinkage long sys_pivot_root(const char __user * new_root,
+ 			goto out3;
+ 	} else if (!is_subdir(old_nd.path.dentry, new_nd.path.dentry))
+ 		goto out3;
+-	detach_mnt(new_nd.path.mnt, &parent_nd);
++	detach_mnt(new_nd.path.mnt, &parent_path);
+ 	detach_mnt(user_nd.path.mnt, &root_parent);
+ 	/* mount old root on put_old */
+-	attach_mnt(user_nd.path.mnt, &old_nd);
++	attach_mnt(user_nd.path.mnt, &old_nd.path);
+ 	/* mount new_root on / */
+ 	attach_mnt(new_nd.path.mnt, &root_parent);
+ 	touch_mnt_namespace(current->nsproxy->mnt_ns);
+ 	spin_unlock(&vfsmount_lock);
+-	chroot_fs_refs(&user_nd, &new_nd);
++	chroot_fs_refs(&user_nd.path, &new_nd.path);
+ 	security_sb_post_pivotroot(&user_nd, &new_nd);
+ 	error = 0;
+-	path_put(&root_parent.path);
+-	path_put(&parent_nd.path);
++	path_put(&root_parent);
++	path_put(&parent_path);
+ out2:
+ 	mutex_unlock(&old_nd.path.dentry->d_inode->i_mutex);
+ 	up_write(&namespace_sem);
+diff --git a/fs/nfs/super.c b/fs/nfs/super.c
+index dd4dfcd..f921902 100644
+--- a/fs/nfs/super.c
++++ b/fs/nfs/super.c
+@@ -589,8 +589,6 @@ static void nfs_umount_begin(struct vfsmount *vfsmnt, int flags)
+ 	struct nfs_server *server = NFS_SB(vfsmnt->mnt_sb);
+ 	struct rpc_clnt *rpc;
+ 
+-	shrink_submounts(vfsmnt, &nfs_automount_list);
+-
+ 	if (!(flags & MNT_FORCE))
+ 		return;
+ 	/* -EIO all pending I/O */
+diff --git a/fs/pnode.c b/fs/pnode.c
+index 05ba692..1d8f544 100644
+--- a/fs/pnode.c
++++ b/fs/pnode.c
+@@ -225,7 +225,7 @@ out:
+  */
+ static inline int do_refcount_check(struct vfsmount *mnt, int count)
+ {
+-	int mycount = atomic_read(&mnt->mnt_count);
++	int mycount = atomic_read(&mnt->mnt_count) - mnt->mnt_ghosts;
+ 	return (mycount > count);
+ }
+ 
 diff --git a/include/asm-avr32/byteorder.h b/include/asm-avr32/byteorder.h
 index 402ff41..d77b48b 100644
 --- a/include/asm-avr32/byteorder.h
@@ -6318,6 +7466,77 @@
  #define PAGE_KERNEL_EXEC_NOCACHE	MAKE_GLOBAL(__PAGE_KERNEL_EXEC_NOCACHE)
  #define PAGE_KERNEL_LARGE		MAKE_GLOBAL(__PAGE_KERNEL_LARGE)
  #define PAGE_KERNEL_LARGE_EXEC		MAKE_GLOBAL(__PAGE_KERNEL_LARGE_EXEC)
+diff --git a/include/linux/Kbuild b/include/linux/Kbuild
+index 4108b38..4a446a1 100644
+--- a/include/linux/Kbuild
++++ b/include/linux/Kbuild
+@@ -195,7 +195,6 @@ unifdef-y += ethtool.h
+ unifdef-y += eventpoll.h
+ unifdef-y += signalfd.h
+ unifdef-y += ext2_fs.h
+-unifdef-y += ext3_fs.h
+ unifdef-y += fb.h
+ unifdef-y += fcntl.h
+ unifdef-y += filter.h
+@@ -248,7 +247,6 @@ unifdef-y += isdn.h
+ unifdef-y += isdnif.h
+ unifdef-y += isdn_divertif.h
+ unifdef-y += isdn_ppp.h
+-unifdef-y += jbd.h
+ unifdef-y += joystick.h
+ unifdef-y += kdev_t.h
+ unifdef-y += kd.h
+diff --git a/include/linux/bitops.h b/include/linux/bitops.h
+index 69c1edb..40d5473 100644
+--- a/include/linux/bitops.h
++++ b/include/linux/bitops.h
+@@ -65,6 +65,46 @@ static inline __u32 ror32(__u32 word, unsigned int shift)
+ 	return (word >> shift) | (word << (32 - shift));
+ }
+ 
++/**
++ * rol16 - rotate a 16-bit value left
++ * @word: value to rotate
++ * @shift: bits to roll
++ */
++static inline __u16 rol16(__u16 word, unsigned int shift)
++{
++	return (word << shift) | (word >> (16 - shift));
++}
++
++/**
++ * ror16 - rotate a 16-bit value right
++ * @word: value to rotate
++ * @shift: bits to roll
++ */
++static inline __u16 ror16(__u16 word, unsigned int shift)
++{
++	return (word >> shift) | (word << (16 - shift));
++}
++
++/**
++ * rol8 - rotate an 8-bit value left
++ * @word: value to rotate
++ * @shift: bits to roll
++ */
++static inline __u8 rol8(__u8 word, unsigned int shift)
++{
++	return (word << shift) | (word >> (8 - shift));
++}
++
++/**
++ * ror8 - rotate an 8-bit value right
++ * @word: value to rotate
++ * @shift: bits to roll
++ */
++static inline __u8 ror8(__u8 word, unsigned int shift)
++{
++	return (word >> shift) | (word << (8 - shift));
++}
++
+ static inline unsigned fls_long(unsigned long l)
+ {
+ 	if (sizeof(l) == 4)
 diff --git a/include/linux/cpuidle.h b/include/linux/cpuidle.h
 index 6b72a45..51e6b1e 100644
 --- a/include/linux/cpuidle.h
@@ -6333,6 +7552,24 @@
  
  	int (*enter)	(struct cpuidle_device *dev,
  			 struct cpuidle_state *state);
+diff --git a/include/linux/hardirq.h b/include/linux/hardirq.h
+index 4982998..897f723 100644
+--- a/include/linux/hardirq.h
++++ b/include/linux/hardirq.h
+@@ -72,6 +72,13 @@
+ #define in_softirq()		(softirq_count())
+ #define in_interrupt()		(irq_count())
+ 
++/*
++ * Are we running in atomic context?  WARNING: this macro cannot
++ * always detect atomic context; in particular, it cannot know about
++ * held spinlocks in non-preemptible kernels.  Thus it should not be
++ * used in the general case to determine whether sleeping is possible.
++ * Do not use in_atomic() in driver code.
++ */
+ #define in_atomic()		((preempt_count() & ~PREEMPT_ACTIVE) != 0)
+ 
+ #ifdef CONFIG_PREEMPT
 diff --git a/include/linux/lguest_launcher.h b/include/linux/lguest_launcher.h
 index 589be3e..e7217dc 100644
 --- a/include/linux/lguest_launcher.h
@@ -6357,6 +7594,26 @@
  	__u8 feature_len;
  	/* The number of bytes of the config array after virtqueues. */
  	__u8 config_len;
+diff --git a/include/linux/mount.h b/include/linux/mount.h
+index 6d3047d..5ee2df2 100644
+--- a/include/linux/mount.h
++++ b/include/linux/mount.h
+@@ -61,6 +61,7 @@ struct vfsmount {
+ 	atomic_t mnt_count;
+ 	int mnt_expiry_mark;		/* true if marked for expiry */
+ 	int mnt_pinned;
++	int mnt_ghosts;
+ };
+ 
+ static inline struct vfsmount *mntget(struct vfsmount *mnt)
+@@ -98,7 +99,6 @@ extern int do_add_mount(struct vfsmount *newmnt, struct nameidata *nd,
+ 			int mnt_flags, struct list_head *fslist);
+ 
+ extern void mark_mounts_for_expiry(struct list_head *mounts);
+-extern void shrink_submounts(struct vfsmount *mountpoint, struct list_head *mounts);
+ 
+ extern spinlock_t vfsmount_lock;
+ extern dev_t name_to_dev_t(char *name);
 diff --git a/include/linux/sched.h b/include/linux/sched.h
 index fed07d0..6a1e7af 100644
 --- a/include/linux/sched.h
@@ -6457,6 +7714,50 @@
  extern int xfrm4_extract_header(struct sk_buff *skb);
  extern int xfrm4_extract_input(struct xfrm_state *x, struct sk_buff *skb);
  extern int xfrm4_rcv_encap(struct sk_buff *skb, int nexthdr, __be32 spi,
+diff --git a/kernel/audit.c b/kernel/audit.c
+index be55cb5..b782b04 100644
+--- a/kernel/audit.c
++++ b/kernel/audit.c
+@@ -1269,8 +1269,8 @@ static void audit_log_n_string(struct audit_buffer *ab, size_t slen,
+ 
+ /**
+  * audit_string_contains_control - does a string need to be logged in hex
+- * @string - string to be checked
+- * @len - max length of the string to check
++ * @string: string to be checked
++ * @len: max length of the string to check
+  */
+ int audit_string_contains_control(const char *string, size_t len)
+ {
+@@ -1285,7 +1285,7 @@ int audit_string_contains_control(const char *string, size_t len)
+ /**
+  * audit_log_n_untrustedstring - log a string that may contain random characters
+  * @ab: audit_buffer
+- * @len: lenth of string (not including trailing null)
++ * @len: length of string (not including trailing null)
+  * @string: string to be logged
+  *
+  * This code will escape a string that is passed to it if the string
+diff --git a/kernel/fork.c b/kernel/fork.c
+index dd249c3..9c042f9 100644
+--- a/kernel/fork.c
++++ b/kernel/fork.c
+@@ -394,7 +394,6 @@ void __mmdrop(struct mm_struct *mm)
+ {
+ 	BUG_ON(mm == &init_mm);
+ 	mm_free_pgd(mm);
+-	mm_free_cgroup(mm);
+ 	destroy_context(mm);
+ 	free_mm(mm);
+ }
+@@ -416,6 +415,7 @@ void mmput(struct mm_struct *mm)
+ 			spin_unlock(&mmlist_lock);
+ 		}
+ 		put_swap_token(mm);
++		mm_free_cgroup(mm);
+ 		mmdrop(mm);
+ 	}
+ }
 diff --git a/kernel/futex.c b/kernel/futex.c
 index 06968cd..87a6428 100644
 --- a/kernel/futex.c
@@ -6712,6 +8013,19 @@
  	dev->iflink = real_dev->ifindex;
  	dev->state  = (real_dev->state & ((1<<__LINK_STATE_NOCARRIER) |
  					  (1<<__LINK_STATE_DORMANT))) |
+diff --git a/net/9p/trans_fd.c b/net/9p/trans_fd.c
+index 4e8d4e7..f624dff 100644
+--- a/net/9p/trans_fd.c
++++ b/net/9p/trans_fd.c
+@@ -1520,7 +1520,7 @@ static int __init p9_trans_fd_init(void)
+ 	v9fs_register_trans(&p9_unix_trans);
+ 	v9fs_register_trans(&p9_fd_trans);
+ 
+-	return 1;
++	return 0;
+ }
+ 
+ module_init(p9_trans_fd_init);
 diff --git a/net/ax25/TODO b/net/ax25/TODO
 index 4089c49..69fb4e3 100644
 --- a/net/ax25/TODO
@@ -7273,3 +8587,913 @@
  }
  
  /*
+diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl
+index 2a7cef9..58a9494 100755
+--- a/scripts/checkpatch.pl
++++ b/scripts/checkpatch.pl
+@@ -9,7 +9,7 @@ use strict;
+ my $P = $0;
+ $P =~ s at .*/@@g;
+ 
+-my $V = '0.15';
++my $V = '0.16';
+ 
+ use Getopt::Long qw(:config no_auto_abbrev);
+ 
+@@ -18,6 +18,7 @@ my $tree = 1;
+ my $chk_signoff = 1;
+ my $chk_patch = 1;
+ my $tst_type = 0;
++my $tst_only;
+ my $emacs = 0;
+ my $terse = 0;
+ my $file = 0;
+@@ -44,6 +45,7 @@ GetOptions(
+ 
+ 	'debug=s'	=> \%debug,
+ 	'test-type!'	=> \$tst_type,
++	'test-only=s'	=> \$tst_only,
+ ) or exit;
+ 
+ my $exit = 0;
+@@ -263,17 +265,7 @@ sub expand_tabs {
+ 	return $res;
+ }
+ sub copy_spacing {
+-	my ($str) = @_;
+-
+-	my $res = '';
+-	for my $c (split(//, $str)) {
+-		if ($c eq "\t") {
+-			$res .= $c;
+-		} else {
+-			$res .= ' ';
+-		}
+-	}
+-
++	(my $res = shift) =~ tr/\t/ /c;
+ 	return $res;
+ }
+ 
+@@ -290,53 +282,76 @@ sub line_stats {
+ 	return (length($line), length($white));
+ }
+ 
++my $sanitise_quote = '';
++
++sub sanitise_line_reset {
++	my ($in_comment) = @_;
++
++	if ($in_comment) {
++		$sanitise_quote = '*/';
++	} else {
++		$sanitise_quote = '';
++	}
++}
+ sub sanitise_line {
+ 	my ($line) = @_;
+ 
+ 	my $res = '';
+ 	my $l = '';
+ 
+-	my $quote = '';
+ 	my $qlen = 0;
++	my $off = 0;
++	my $c;
+ 
+-	foreach my $c (split(//, $line)) {
+-		# The second backslash of a pair is not a "quote".
+-		if ($l eq "\\" && $c eq "\\") {
+-			$c = 'X';
+-		}
+-		if ($l ne "\\" && ($c eq "'" || $c eq '"')) {
+-			if ($quote eq '') {
+-				$quote = $c;
+-				$res .= $c;
+-				$l = $c;
+-				$qlen = 0;
+-				next;
+-			} elsif ($quote eq $c) {
+-				$quote = '';
+-			}
++	# Always copy over the diff marker.
++	$res = substr($line, 0, 1);
++
++	for ($off = 1; $off < length($line); $off++) {
++		$c = substr($line, $off, 1);
++
++		# Comments we are wacking completly including the begin
++		# and end, all to $;.
++		if ($sanitise_quote eq '' && substr($line, $off, 2) eq '/*') {
++			$sanitise_quote = '*/';
++
++			substr($res, $off, 2, "$;$;");
++			$off++;
++			next;
+ 		}
+-		if ($quote eq "'" && $qlen > 1) {
+-			$quote = '';
++		if (substr($line, $off, 2) eq $sanitise_quote) {
++			$sanitise_quote = '';
++			substr($res, $off, 2, "$;$;");
++			$off++;
++			next;
+ 		}
+-		if ($quote && $c ne "\t") {
+-			$res .= "X";
+-			$qlen++;
+-		} else {
+-			$res .= $c;
++
++		# A \ in a string means ignore the next character.
++		if (($sanitise_quote eq "'" || $sanitise_quote eq '"') &&
++		    $c eq "\\") {
++			substr($res, $off, 2, 'XX');
++			$off++;
++			next;
+ 		}
++		# Regular quotes.
++		if ($c eq "'" || $c eq '"') {
++			if ($sanitise_quote eq '') {
++				$sanitise_quote = $c;
+ 
+-		$l = $c;
+-	}
++				substr($res, $off, 1, $c);
++				next;
++			} elsif ($sanitise_quote eq $c) {
++				$sanitise_quote = '';
++			}
++		}
+ 
+-	# Clear out the comments.
+-	while ($res =~ m@(/\*.*?\*/)@g) {
+-		substr($res, $-[1], $+[1] - $-[1]) = $; x ($+[1] - $-[1]);
+-	}
+-	if ($res =~ m@(/\*.*)@) {
+-		substr($res, $-[1], $+[1] - $-[1]) = $; x ($+[1] - $-[1]);
+-	}
+-	if ($res =~ m@^.(.*\*/)@) {
+-		substr($res, $-[1], $+[1] - $-[1]) = $; x ($+[1] - $-[1]);
++		#print "SQ:$sanitise_quote\n";
++		if ($off != 0 && $sanitise_quote eq '*/' && $c ne "\t") {
++			substr($res, $off, 1, $;);
++		} elsif ($off != 0 && $sanitise_quote && $c ne "\t") {
++			substr($res, $off, 1, 'X');
++		} else {
++			substr($res, $off, 1, $c);
++		}
+ 	}
+ 
+ 	# The pathname on a #include may be surrounded by '<' and '>'.
+@@ -359,6 +374,7 @@ sub ctx_statement_block {
+ 	my $blk = '';
+ 	my $soff = $off;
+ 	my $coff = $off - 1;
++	my $coff_set = 0;
+ 
+ 	my $loff = 0;
+ 
+@@ -370,7 +386,7 @@ sub ctx_statement_block {
+ 
+ 	my $remainder;
+ 	while (1) {
+-		#warn "CSB: blk<$blk>\n";
++		#warn "CSB: blk<$blk> remain<$remain>\n";
+ 		# If we are about to drop off the end, pull in more
+ 		# context.
+ 		if ($off >= $len) {
+@@ -393,7 +409,7 @@ sub ctx_statement_block {
+ 		$c = substr($blk, $off, 1);
+ 		$remainder = substr($blk, $off);
+ 
+-		#warn "CSB: c<$c> type<$type> level<$level>\n";
++		#warn "CSB: c<$c> type<$type> level<$level> remainder<$remainder> coff_set<$coff_set>\n";
+ 		# Statement ends at the ';' or a close '}' at the
+ 		# outermost level.
+ 		if ($level == 0 && $c eq ';') {
+@@ -401,10 +417,14 @@ sub ctx_statement_block {
+ 		}
+ 
+ 		# An else is really a conditional as long as its not else if
+-		if ($level == 0 && (!defined($p) || $p =~ /(?:\s|\})/) &&
+-				$remainder =~ /(else)(?:\s|{)/ &&
+-				$remainder !~ /else\s+if\b/) {
+-			$coff = $off + length($1);
++		if ($level == 0 && $coff_set == 0 &&
++				(!defined($p) || $p =~ /(?:\s|\}|\+)/) &&
++				$remainder =~ /^(else)(?:\s|{)/ &&
++				$remainder !~ /^else\s+if\b/) {
++			$coff = $off + length($1) - 1;
++			$coff_set = 1;
++			#warn "CSB: mark coff<$coff> soff<$soff> 1<$1>\n";
++			#warn "[" . substr($blk, $soff, $coff - $soff + 1) . "]\n";
+ 		}
+ 
+ 		if (($type eq '' || $type eq '(') && $c eq '(') {
+@@ -417,6 +437,8 @@ sub ctx_statement_block {
+ 
+ 			if ($level == 0 && $coff < $soff) {
+ 				$coff = $off;
++				$coff_set = 1;
++				#warn "CSB: mark coff<$coff>\n";
+ 			}
+ 		}
+ 		if (($type eq '' || $type eq '{') && $c eq '{') {
+@@ -444,7 +466,7 @@ sub ctx_statement_block {
+ 	#warn "STATEMENT<$statement>\n";
+ 	#warn "CONDITION<$condition>\n";
+ 
+-	#print "off<$off> loff<$loff>\n";
++	#print "coff<$coff> soff<$off> loff<$loff>\n";
+ 
+ 	return ($statement, $condition,
+ 			$line, $remain + 1, $off - $loff + 1, $level);
+@@ -502,7 +524,7 @@ sub ctx_statement_full {
+ 	# Grab the first conditional/block pair.
+ 	($statement, $condition, $linenr, $remain, $off, $level) =
+ 				ctx_statement_block($linenr, $remain, $off);
+-	#print "F: c<$condition> s<$statement>\n";
++	#print "F: c<$condition> s<$statement> remain<$remain>\n";
+ 	push(@chunks, [ $condition, $statement ]);
+ 	if (!($remain > 0 && $condition =~ /^\s*(?:\n[+-])?\s*(?:if|else|do)\b/s)) {
+ 		return ($level, $linenr, @chunks);
+@@ -514,7 +536,7 @@ sub ctx_statement_full {
+ 		($statement, $condition, $linenr, $remain, $off, $level) =
+ 				ctx_statement_block($linenr, $remain, $off);
+ 		#print "C: c<$condition> s<$statement> remain<$remain>\n";
+-		last if (!($remain > 0 && $condition =~ /^\s*(?:\n[+-])?\s*(?:else|do)\b/s));
++		last if (!($remain > 0 && $condition =~ /^(?:\s*\n[+-])*\s*(?:else|do)\b/s));
+ 		#print "C: push\n";
+ 		push(@chunks, [ $condition, $statement ]);
+ 	}
+@@ -668,6 +690,7 @@ sub annotate_values {
+ 	print "$stream\n" if ($dbg_values > 1);
+ 
+ 	while (length($cur)) {
++		@av_paren_type = ('E') if ($#av_paren_type < 0);
+ 		print " <" . join('', @av_paren_type) .
+ 					"> <$type> " if ($dbg_values > 1);
+ 		if ($cur =~ /^(\s+)/o) {
+@@ -804,28 +827,34 @@ sub possible {
+ my $prefix = '';
+ 
+ sub report {
++	if (defined $tst_only && $_[0] !~ /\Q$tst_only\E/) {
++		return 0;
++	}
+ 	my $line = $prefix . $_[0];
+ 
+ 	$line = (split('\n', $line))[0] . "\n" if ($terse);
+ 
+ 	push(our @report, $line);
++
++	return 1;
+ }
+ sub report_dump {
+ 	our @report;
+ }
+ sub ERROR {
+-	report("ERROR: $_[0]\n");
+-	our $clean = 0;
+-	our $cnt_error++;
++	if (report("ERROR: $_[0]\n")) {
++		our $clean = 0;
++		our $cnt_error++;
++	}
+ }
+ sub WARN {
+-	report("WARNING: $_[0]\n");
+-	our $clean = 0;
+-	our $cnt_warn++;
++	if (report("WARNING: $_[0]\n")) {
++		our $clean = 0;
++		our $cnt_warn++;
++	}
+ }
+ sub CHK {
+-	if ($check) {
+-		report("CHECK: $_[0]\n");
++	if ($check && report("CHECK: $_[0]\n")) {
+ 		our $clean = 0;
+ 		our $cnt_chk++;
+ 	}
+@@ -867,30 +896,76 @@ sub process {
+ 	my $prev_values = 'E';
+ 
+ 	# suppression flags
+-	my $suppress_ifbraces = 0;
++	my %suppress_ifbraces;
+ 
+ 	# Pre-scan the patch sanitizing the lines.
+ 	# Pre-scan the patch looking for any __setup documentation.
+ 	#
+ 	my @setup_docs = ();
+ 	my $setup_docs = 0;
++
++	sanitise_line_reset();
+ 	my $line;
+ 	foreach my $rawline (@rawlines) {
+-		# Standardise the strings and chars within the input to
+-		# simplify matching.
+-		$line = sanitise_line($rawline);
+-		push(@lines, $line);
+-
+-		##print "==>$rawline\n";
+-		##print "-->$line\n";
++		$linenr++;
++		$line = $rawline;
+ 
+-		if ($line=~/^\+\+\+\s+(\S+)/) {
++		if ($rawline=~/^\+\+\+\s+(\S+)/) {
+ 			$setup_docs = 0;
+ 			if ($1 =~ m at Documentation/kernel-parameters.txt$@) {
+ 				$setup_docs = 1;
+ 			}
+-			next;
++			#next;
++		}
++		if ($rawline=~/^\@\@ -\d+(?:,\d+)? \+(\d+)(,(\d+))? \@\@/) {
++			$realline=$1-1;
++			if (defined $2) {
++				$realcnt=$3+1;
++			} else {
++				$realcnt=1+1;
++			}
++
++			# Guestimate if this is a continuing comment.  Run
++			# the context looking for a comment "edge".  If this
++			# edge is a close comment then we must be in a comment
++			# at context start.
++			my $edge;
++			for (my $ln = $linenr; $ln < ($linenr + $realcnt); $ln++) {
++				next if ($line =~ /^-/);
++				($edge) = ($rawlines[$ln - 1] =~ m@(/\*|\*/)@);
++				last if (defined $edge);
++			}
++			if (defined $edge && $edge eq '*/') {
++				$in_comment = 1;
++			}
++
++			# Guestimate if this is a continuing comment.  If this
++			# is the start of a diff block and this line starts
++			# ' *' then it is very likely a comment.
++			if (!defined $edge &&
++			    $rawlines[$linenr] =~ m@^.\s* \*(?:\s|$)@)
++			{
++				$in_comment = 1;
++			}
++
++			##print "COMMENT:$in_comment edge<$edge> $rawline\n";
++			sanitise_line_reset($in_comment);
++
++		} elsif ($realcnt) {
++			# Standardise the strings and chars within the input to
++			# simplify matching.
++			$line = sanitise_line($rawline);
+ 		}
++		push(@lines, $line);
++
++		if ($realcnt > 1) {
++			$realcnt-- if ($line =~ /^(?:\+| |$)/);
++		} else {
++			$realcnt = 0;
++		}
++
++		#print "==>$rawline\n";
++		#print "-->$line\n";
+ 
+ 		if ($setup_docs && $line =~ /^\+/) {
+ 			push(@setup_docs, $line);
+@@ -899,23 +974,17 @@ sub process {
+ 
+ 	$prefix = '';
+ 
++	$realcnt = 0;
++	$linenr = 0;
+ 	foreach my $line (@lines) {
+ 		$linenr++;
+ 
+ 		my $rawline = $rawlines[$linenr - 1];
+ 
+-#extract the filename as it passes
+-		if ($line=~/^\+\+\+\s+(\S+)/) {
+-			$realfile=$1;
+-			$realfile =~ s@^[^/]*/@@;
+-			$in_comment = 0;
+-			next;
+-		}
+ #extract the line range in the file after the patch is applied
+ 		if ($line=~/^\@\@ -\d+(?:,\d+)? \+(\d+)(,(\d+))? \@\@/) {
+ 			$is_patch = 1;
+ 			$first_line = $linenr + 1;
+-			$in_comment = 0;
+ 			$realline=$1-1;
+ 			if (defined $2) {
+ 				$realcnt=$3+1;
+@@ -925,50 +994,16 @@ sub process {
+ 			annotate_reset();
+ 			$prev_values = 'E';
+ 
+-			$suppress_ifbraces = $linenr - 1;
++			%suppress_ifbraces = ();
+ 			next;
+-		}
+ 
+ # track the line number as we move through the hunk, note that
+ # new versions of GNU diff omit the leading space on completely
+ # blank context lines so we need to count that too.
+-		if ($line =~ /^( |\+|$)/) {
++		} elsif ($line =~ /^( |\+|$)/) {
+ 			$realline++;
+ 			$realcnt-- if ($realcnt != 0);
+ 
+-			# Guestimate if this is a continuing comment.  Run
+-			# the context looking for a comment "edge".  If this
+-			# edge is a close comment then we must be in a comment
+-			# at context start.
+-			if ($linenr == $first_line) {
+-				my $edge;
+-				for (my $ln = $first_line; $ln < ($linenr + $realcnt); $ln++) {
+-					($edge) = ($rawlines[$ln - 1] =~ m@(/\*|\*/)@);
+-					last if (defined $edge);
+-				}
+-				if (defined $edge && $edge eq '*/') {
+-					$in_comment = 1;
+-				}
+-			}
+-
+-			# Guestimate if this is a continuing comment.  If this
+-			# is the start of a diff block and this line starts
+-			# ' *' then it is very likely a comment.
+-			if ($linenr == $first_line and $rawline =~ m@^.\s* \*(?:\s|$)@) {
+-				$in_comment = 1;
+-			}
+-
+-			# Find the last comment edge on _this_ line.
+-			$comment_edge = 0;
+-			while (($rawline =~ m@(/\*|\*/)@g)) {
+-				if ($1 eq '/*') {
+-					$in_comment = 1;
+-				} else {
+-					$in_comment = 0;
+-				}
+-				$comment_edge = 1;
+-			}
+-
+ 			# Measure the line length and indent.
+ 			($length, $indent) = line_stats($rawline);
+ 
+@@ -977,23 +1012,36 @@ sub process {
+ 			($previndent, $stashindent) = ($stashindent, $indent);
+ 			($prevrawline, $stashrawline) = ($stashrawline, $rawline);
+ 
+-			#warn "ic<$in_comment> ce<$comment_edge> line<$line>\n";
++			#warn "line<$line>\n";
+ 
+ 		} elsif ($realcnt == 1) {
+ 			$realcnt--;
+ 		}
+ 
+ #make up the handle for any error we report on this line
++		$prefix = "$filename:$realline: " if ($emacs && $file);
++		$prefix = "$filename:$linenr: " if ($emacs && !$file);
++
+ 		$here = "#$linenr: " if (!$file);
+ 		$here = "#$realline: " if ($file);
++
++		# extract the filename as it passes
++		if ($line=~/^\+\+\+\s+(\S+)/) {
++			$realfile = $1;
++			$realfile =~ s@^[^/]*/@@;
++
++			if ($realfile =~ m at include/asm/@) {
++				ERROR("do not modify files in include/asm, change architecture specific files in include/asm-<architecture>\n" . "$here$rawline\n");
++			}
++			next;
++		}
++
+ 		$here .= "FILE: $realfile:$realline:" if ($realcnt != 0);
+ 
+ 		my $hereline = "$here\n$rawline\n";
+ 		my $herecurr = "$here\n$rawline\n";
+ 		my $hereprev = "$here\n$prevrawline\n$rawline\n";
+ 
+-		$prefix = "$filename:$realline: " if ($emacs && $file);
+-		$prefix = "$filename:$linenr: " if ($emacs && !$file);
+ 		$cnt_lines++ if ($realcnt != 0);
+ 
+ #check the patch for a signoff:
+@@ -1005,7 +1053,7 @@ sub process {
+ 					$herecurr);
+ 			}
+ 			if ($line =~ /^\s*signed-off-by:\S/i) {
+-				WARN("need space after Signed-off-by:\n" .
++				WARN("space required after Signed-off-by:\n" .
+ 					$herecurr);
+ 			}
+ 		}
+@@ -1072,11 +1120,6 @@ sub process {
+ 			WARN("CVS style keyword markers, these will _not_ be updated\n". $herecurr);
+ 		}
+ 
+-# The rest of our checks refer specifically to C style
+-# only apply those _outside_ comments.  Only skip
+-# lines in the middle of comments.
+-		next if (!$comment_edge && $in_comment);
+-
+ # Check for potential 'bare' types
+ 		if ($realcnt) {
+ 			my ($s, $c) = ctx_statement_block($linenr, $realcnt, 0);
+@@ -1110,7 +1153,7 @@ sub process {
+ 				my ($name_len) = length($1);
+ 
+ 				my $ctx = $s;
+-				substr($ctx, 0, $name_len + 1) = '';
++				substr($ctx, 0, $name_len + 1, '');
+ 				$ctx =~ s/\)[^\)]*$//;
+ 
+ 				for my $arg (split(/\s*,\s*/, $ctx)) {
+@@ -1151,27 +1194,33 @@ sub process {
+ 
+ # if/while/etc brace do not go on next line, unless defining a do while loop,
+ # or if that brace on the next line is for something else
+-		if ($line =~ /\b(?:(if|while|for|switch)\s*\(|do\b|else\b)/ && $line !~ /^.#/) {
++		if ($line =~ /(.*)\b((?:if|while|for|switch)\s*\(|do\b|else\b)/ && $line !~ /^.#/) {
++			my $pre_ctx = "$1$2";
++
+ 			my ($level, @ctx) = ctx_statement_level($linenr, $realcnt, 0);
+ 			my $ctx_ln = $linenr + $#ctx + 1;
+ 			my $ctx_cnt = $realcnt - $#ctx - 1;
+ 			my $ctx = join("\n", @ctx);
+ 
++			##warn "realcnt<$realcnt> ctx_cnt<$ctx_cnt>\n";
++
+ 			# Skip over any removed lines in the context following statement.
+-			while ($ctx_cnt > 0 && $lines[$ctx_ln - 1] =~ /^-/) {
++			while (defined($lines[$ctx_ln - 1]) && $lines[$ctx_ln - 1] =~ /^-/) {
+ 				$ctx_ln++;
+-				$ctx_cnt--;
+ 			}
+-			##warn "line<$line>\nctx<$ctx>\nnext<$lines[$ctx_ln - 1]>";
++			##warn "pre<$pre_ctx>\nline<$line>\nctx<$ctx>\nnext<$lines[$ctx_ln - 1]>\n";
+ 
+-			if ($ctx !~ /{\s*/ && $ctx_cnt > 0 && $lines[$ctx_ln - 1] =~ /^\+\s*{/) {
+-				ERROR("That open brace { should be on the previous line\n" .
++			if ($ctx !~ /{\s*/ && defined($lines[$ctx_ln -1]) && $lines[$ctx_ln - 1] =~ /^\+\s*{/) {
++				ERROR("that open brace { should be on the previous line\n" .
+ 					"$here\n$ctx\n$lines[$ctx_ln - 1]");
+ 			}
+-			if ($level == 0 && $ctx =~ /\)\s*\;\s*$/ && defined $lines[$ctx_ln - 1]) {
++			if ($level == 0 && $pre_ctx !~ /}\s*while\s*\($/ &&
++			    $ctx =~ /\)\s*\;\s*$/ &&
++			    defined $lines[$ctx_ln - 1])
++			{
+ 				my ($nlength, $nindent) = line_stats($lines[$ctx_ln - 1]);
+ 				if ($nindent > $indent) {
+-					WARN("Trailing semicolon indicates no statements, indent implies otherwise\n" .
++					WARN("trailing semicolon indicates no statements, indent implies otherwise\n" .
+ 						"$here\n$ctx\n$lines[$ctx_ln - 1]");
+ 				}
+ 			}
+@@ -1200,7 +1249,7 @@ sub process {
+ # check for initialisation to aggregates open brace on the next line
+ 		if ($prevline =~ /$Declare\s*$Ident\s*=\s*$/ &&
+ 		    $line =~ /^.\s*{/) {
+-			ERROR("That open brace { should be on the previous line\n" . $hereprev);
++			ERROR("that open brace { should be on the previous line\n" . $hereprev);
+ 		}
+ 
+ #
+@@ -1325,22 +1374,31 @@ sub process {
+ # check for spaces between functions and their parentheses.
+ 		while ($line =~ /($Ident)\s+\(/g) {
+ 			my $name = $1;
+-			my $ctx = substr($line, 0, $-[1]);
++			my $ctx_before = substr($line, 0, $-[1]);
++			my $ctx = "$ctx_before$name";
+ 
+ 			# Ignore those directives where spaces _are_ permitted.
+-			if ($name =~ /^(?:if|for|while|switch|return|volatile|__volatile__|__attribute__|format|__extension__|Copyright|case|__asm__)$/) {
++			if ($name =~ /^(?:
++				if|for|while|switch|return|case|
++				volatile|__volatile__|
++				__attribute__|format|__extension__|
++				asm|__asm__)$/x)
++			{
+ 
+ 			# cpp #define statements have non-optional spaces, ie
+ 			# if there is a space between the name and the open
+ 			# parenthesis it is simply not a parameter group.
+-			} elsif ($ctx =~ /^.\#\s*define\s*$/) {
++			} elsif ($ctx_before =~ /^.\#\s*define\s*$/) {
++
++			# cpp #elif statement condition may start with a (
++			} elsif ($ctx =~ /^.\#\s*elif\s*$/) {
+ 
+ 			# If this whole things ends with a type its most
+ 			# likely a typedef for a function.
+-			} elsif ("$ctx$name" =~ /$Type$/) {
++			} elsif ($ctx =~ /$Type$/) {
+ 
+ 			} else {
+-				WARN("no space between function name and open parenthesis '('\n" . $herecurr);
++				WARN("space prohibited between function name and open parenthesis '('\n" . $herecurr);
+ 			}
+ 		}
+ # Check operator spacing.
+@@ -1359,13 +1417,21 @@ sub process {
+ 			for (my $n = 0; $n < $#elements; $n += 2) {
+ 				$off += length($elements[$n]);
+ 
++				# Pick up the preceeding and succeeding characters.
++				my $ca = substr($opline, 0, $off);
++				my $cc = '';
++				if (length($opline) >= ($off + length($elements[$n + 1]))) {
++					$cc = substr($opline, $off + length($elements[$n + 1]));
++				}
++				my $cb = "$ca$;$cc";
++
+ 				my $a = '';
+ 				$a = 'V' if ($elements[$n] ne '');
+ 				$a = 'W' if ($elements[$n] =~ /\s$/);
+ 				$a = 'C' if ($elements[$n] =~ /$;$/);
+ 				$a = 'B' if ($elements[$n] =~ /(\[|\()$/);
+ 				$a = 'O' if ($elements[$n] eq '');
+-				$a = 'E' if ($elements[$n] eq '' && $n == 0);
++				$a = 'E' if ($ca =~ /^\s*$/);
+ 
+ 				my $op = $elements[$n + 1];
+ 
+@@ -1381,14 +1447,6 @@ sub process {
+ 					$c = 'E';
+ 				}
+ 
+-				# Pick up the preceeding and succeeding characters.
+-				my $ca = substr($opline, 0, $off);
+-				my $cc = '';
+-				if (length($opline) >= ($off + length($elements[$n + 1]))) {
+-					$cc = substr($opline, $off + length($elements[$n + 1]));
+-				}
+-				my $cb = "$ca$;$cc";
+-
+ 				my $ctx = "${a}x${c}";
+ 
+ 				my $at = "(ctx:$ctx)";
+@@ -1424,7 +1482,7 @@ sub process {
+ 				} elsif ($op eq ';') {
+ 					if ($ctx !~ /.x[WEBC]/ &&
+ 					    $cc !~ /^\\/ && $cc !~ /^;/) {
+-						ERROR("need space after that '$op' $at\n" . $hereptr);
++						ERROR("space required after that '$op' $at\n" . $hereptr);
+ 					}
+ 
+ 				# // is a comment
+@@ -1433,13 +1491,13 @@ sub process {
+ 				# -> should have no spaces
+ 				} elsif ($op eq '->') {
+ 					if ($ctx =~ /Wx.|.xW/) {
+-						ERROR("no spaces around that '$op' $at\n" . $hereptr);
++						ERROR("spaces prohibited around that '$op' $at\n" . $hereptr);
+ 					}
+ 
+ 				# , must have a space on the right.
+ 				} elsif ($op eq ',') {
+ 					if ($ctx !~ /.x[WEC]/ && $cc !~ /^}/) {
+-						ERROR("need space after that '$op' $at\n" . $hereptr);
++						ERROR("space required after that '$op' $at\n" . $hereptr);
+ 					}
+ 
+ 				# '*' as part of a type definition -- reported already.
+@@ -1452,21 +1510,26 @@ sub process {
+ 				} elsif ($op eq '!' || $op eq '~' ||
+ 				         ($is_unary && ($op eq '*' || $op eq '-' || $op eq '&'))) {
+ 					if ($ctx !~ /[WEBC]x./ && $ca !~ /(?:\)|!|~|\*|-|\&|\||\+\+|\-\-|\{)$/) {
+-						ERROR("need space before that '$op' $at\n" . $hereptr);
++						ERROR("space required before that '$op' $at\n" . $hereptr);
+ 					}
+ 					if ($ctx =~ /.xW/) {
+-						ERROR("no space after that '$op' $at\n" . $hereptr);
++						ERROR("space prohibited after that '$op' $at\n" . $hereptr);
+ 					}
+ 
+ 				# unary ++ and unary -- are allowed no space on one side.
+ 				} elsif ($op eq '++' or $op eq '--') {
+-					if ($ctx !~ /[WOBC]x[^W]/ && $ctx !~ /[^W]x[WOBEC]/) {
+-						ERROR("need space one side of that '$op' $at\n" . $hereptr);
++					if ($ctx !~ /[WEOBC]x[^W]/ && $ctx !~ /[^W]x[WOBEC]/) {
++						ERROR("space required one side of that '$op' $at\n" . $hereptr);
++					}
++					if ($ctx =~ /Wx[BE]/ ||
++					    ($ctx =~ /Wx./ && $cc =~ /^;/)) {
++						ERROR("space prohibited before that '$op' $at\n" . $hereptr);
+ 					}
+-					if ($ctx =~ /WxB/ || ($ctx =~ /Wx./ && $cc =~ /^;/)) {
+-						ERROR("no space before that '$op' $at\n" . $hereptr);
++					if ($ctx =~ /ExW/) {
++						ERROR("space prohibited after that '$op' $at\n" . $hereptr);
+ 					}
+ 
++
+ 				# << and >> may either have or not have spaces both sides
+ 				} elsif ($op eq '<<' or $op eq '>>' or
+ 					 $op eq '&' or $op eq '^' or $op eq '|' or
+@@ -1474,7 +1537,7 @@ sub process {
+ 					 $op eq '*' or $op eq '/' or
+ 					 $op eq '%')
+ 				{
+-					if ($ctx !~ /VxV|WxW|VxE|WxE|VxO|Cx.|.xC/) {
++					if ($ctx =~ /Wx[^WCE]|[^WCE]xW/) {
+ 						ERROR("need consistent spacing around '$op' $at\n" .
+ 							$hereptr);
+ 					}
+@@ -1484,7 +1547,7 @@ sub process {
+ 					# Ignore email addresses <foo at bar>
+ 					if (!($op eq '<' && $cb =~ /$;\S+\@\S+>/) &&
+ 					    !($op eq '>' && $cb =~ /<\S+\@\S+$;/)) {
+-						ERROR("need spaces around that '$op' $at\n" . $hereptr);
++						ERROR("spaces required around that '$op' $at\n" . $hereptr);
+ 					}
+ 				}
+ 				$off += length($elements[$n + 1]);
+@@ -1514,31 +1577,31 @@ sub process {
+ #need space before brace following if, while, etc
+ 		if (($line =~ /\(.*\){/ && $line !~ /\($Type\){/) ||
+ 		    $line =~ /do{/) {
+-			ERROR("need a space before the open brace '{'\n" . $herecurr);
++			ERROR("space required before the open brace '{'\n" . $herecurr);
+ 		}
+ 
+ # closing brace should have a space following it when it has anything
+ # on the line
+ 		if ($line =~ /}(?!(?:,|;|\)))\S/) {
+-			ERROR("need a space after that close brace '}'\n" . $herecurr);
++			ERROR("space required after that close brace '}'\n" . $herecurr);
+ 		}
+ 
+ # check spacing on square brackets
+ 		if ($line =~ /\[\s/ && $line !~ /\[\s*$/) {
+-			ERROR("no space after that open square bracket '['\n" . $herecurr);
++			ERROR("space prohibited after that open square bracket '['\n" . $herecurr);
+ 		}
+ 		if ($line =~ /\s\]/) {
+-			ERROR("no space before that close square bracket ']'\n" . $herecurr);
++			ERROR("space prohibited before that close square bracket ']'\n" . $herecurr);
+ 		}
+ 
+ # check spacing on paretheses
+ 		if ($line =~ /\(\s/ && $line !~ /\(\s*(?:\\)?$/ &&
+ 		    $line !~ /for\s*\(\s+;/) {
+-			ERROR("no space after that open parenthesis '('\n" . $herecurr);
++			ERROR("space prohibited after that open parenthesis '('\n" . $herecurr);
+ 		}
+ 		if ($line =~ /(\s+)\)/ && $line !~ /^.\s*\)/ &&
+ 		    $line !~ /for\s*\(.*;\s+\)/) {
+-			ERROR("no space before that close parenthesis ')'\n" . $herecurr);
++			ERROR("space prohibited before that close parenthesis ')'\n" . $herecurr);
+ 		}
+ 
+ #goto labels aren't indented, allow a single space however
+@@ -1549,7 +1612,7 @@ sub process {
+ 
+ # Need a space before open parenthesis after if, while etc
+ 		if ($line=~/\b(if|while|for|switch)\(/) {
+-			ERROR("need a space before the open parenthesis '('\n" . $herecurr);
++			ERROR("space required before the open parenthesis '('\n" . $herecurr);
+ 		}
+ 
+ # Check for illegal assignment in if conditional.
+@@ -1562,10 +1625,12 @@ sub process {
+ 
+ 			# Find out what is on the end of the line after the
+ 			# conditional.
+-			substr($s, 0, length($c)) = '';
++			substr($s, 0, length($c), '');
+ 			$s =~ s/\n.*//g;
+ 			$s =~ s/$;//g; 	# Remove any comments
+-			if (length($c) && $s !~ /^\s*({|;|)\s*\\*\s*$/) {
++			if (length($c) && $s !~ /^\s*({|;|)\s*\\*\s*$/ &&
++			    $c !~ /^.\#\s*if/)
++			{
+ 				ERROR("trailing statements should be on next line\n" . $herecurr);
+ 			}
+ 		}
+@@ -1607,7 +1672,7 @@ sub process {
+ 
+ 			# Find out what is on the end of the line after the
+ 			# conditional.
+-			substr($s, 0, length($c)) = '';
++			substr($s, 0, length($c), '');
+ 			$s =~ s/\n.*//g;
+ 
+ 			if ($s =~ /^\s*;/) {
+@@ -1631,7 +1696,7 @@ sub process {
+ 		if ($tree && $rawline =~ m{^.\#\s*include\s*\<asm\/(.*)\.h\>}) {
+ 			my $checkfile = "$root/include/linux/$1.h";
+ 			if (-f $checkfile && $1 ne 'irq.h') {
+-				CHK("Use #include <linux/$1.h> instead of <asm/$1.h>\n" .
++				WARN("Use #include <linux/$1.h> instead of <asm/$1.h>\n" .
+ 					$herecurr);
+ 			}
+ 		}
+@@ -1692,15 +1757,24 @@ sub process {
+ 			if ($#chunks > 0 && $level == 0) {
+ 				my $allowed = 0;
+ 				my $seen = 0;
+-				my $herectx = $here . "\n";;
++				my $herectx = $here . "\n";
+ 				my $ln = $linenr - 1;
+ 				for my $chunk (@chunks) {
+ 					my ($cond, $block) = @{$chunk};
+ 
+-					$herectx .= "$rawlines[$ln]\n[...]\n";
++					# If the condition carries leading newlines, then count those as offsets.
++					my ($whitespace) = ($cond =~ /^((?:\s*\n[+-])*\s*)/s);
++					my $offset = statement_rawlines($whitespace) - 1;
++
++					#print "COND<$cond> whitespace<$whitespace> offset<$offset>\n";
++
++					# We have looked at and allowed this specific line.
++					$suppress_ifbraces{$ln + $offset} = 1;
++
++					$herectx .= "$rawlines[$ln + $offset]\n[...]\n";
+ 					$ln += statement_rawlines($block) - 1;
+ 
+-					substr($block, 0, length($cond)) = '';
++					substr($block, 0, length($cond), '');
+ 
+ 					$seen++ if ($block =~ /^\s*{/);
+ 
+@@ -1721,16 +1795,10 @@ sub process {
+ 				if ($seen && !$allowed) {
+ 					WARN("braces {} are not necessary for any arm of this statement\n" . $herectx);
+ 				}
+-				# Either way we have looked over this whole
+-				# statement and said what needs to be said.
+-				$suppress_ifbraces = $endln;
+ 			}
+ 		}
+-		if ($linenr > $suppress_ifbraces &&
++		if (!defined $suppress_ifbraces{$linenr - 1} &&
+ 					$line =~ /\b(if|while|for|else)\b/) {
+-			my ($level, $endln, @chunks) =
+-				ctx_statement_full($linenr, $realcnt, $-[0]);
+-
+ 			my $allowed = 0;
+ 
+ 			# Check the pre-context.
+@@ -1738,10 +1806,15 @@ sub process {
+ 				#print "APW: ALLOWED: pre<$1>\n";
+ 				$allowed = 1;
+ 			}
++
++			my ($level, $endln, @chunks) =
++				ctx_statement_full($linenr, $realcnt, $-[0]);
++
+ 			# Check the condition.
+ 			my ($cond, $block) = @{$chunks[0]};
++			#print "CHECKING<$linenr> cond<$cond> block<$block>\n";
+ 			if (defined $cond) {
+-				substr($block, 0, length($cond)) = '';
++				substr($block, 0, length($cond), '');
+ 			}
+ 			if (statement_lines($cond) > 1) {
+ 				#print "APW: ALLOWED: cond<$cond>\n";
+@@ -1759,7 +1832,7 @@ sub process {
+ 			if (defined $chunks[1]) {
+ 				my ($cond, $block) = @{$chunks[1]};
+ 				if (defined $cond) {
+-					substr($block, 0, length($cond)) = '';
++					substr($block, 0, length($cond), '');
+ 				}
+ 				if ($block =~ /^\s*\{/) {
+ 					#print "APW: ALLOWED: chunk-1 block<$block>\n";
+@@ -1882,6 +1955,28 @@ sub process {
+ 		if ($line =~ /__FUNCTION__/) {
+ 			WARN("__func__ should be used instead of gcc specific __FUNCTION__\n"  . $herecurr);
+ 		}
++
++# check for semaphores used as mutexes
++		if ($line =~ /\b(DECLARE_MUTEX|init_MUTEX)\s*\(/) {
++			WARN("mutexes are preferred for single holder semaphores\n" . $herecurr);
++		}
++# check for semaphores used as mutexes
++		if ($line =~ /\binit_MUTEX_LOCKED\s*\(/) {
++			WARN("consider using a completion\n" . $herecurr);
++		}
++# recommend strict_strto* over simple_strto*
++		if ($line =~ /\bsimple_(strto.*?)\s*\(/) {
++			WARN("consider using strict_$1 in preference to simple_$1\n" . $herecurr);
++		}
++
++# use of NR_CPUS is usually wrong
++# ignore definitions of NR_CPUS and usage to define arrays as likely right
++		if ($line =~ /\bNR_CPUS\b/ &&
++		    $line !~ /^.#\s*define\s+NR_CPUS\s+/ &&
++		    $line !~ /^.\s*$Declare\s.*\[[^\]]*NR_CPUS[^\]]*\]/)
++		{
++			WARN("usage of NR_CPUS is often wrong - consider using cpu_possible(), num_possible_cpus(), for_each_possible_cpu(), etc\n" . $herecurr);
++		}
+ 	}
+ 
+ 	# If we have no input at all, then there is nothing to report on

Modified: dists/trunk/linux-2.6/debian/patches/series/1~experimental.1
==============================================================================
--- dists/trunk/linux-2.6/debian/patches/series/1~experimental.1	(original)
+++ dists/trunk/linux-2.6/debian/patches/series/1~experimental.1	Sat Mar 29 11:10:53 2008
@@ -1,4 +1,4 @@
-+ bugfix/all/patch-2.6.25-rc7-git4
++ bugfix/all/patch-2.6.25-rc7-git5
 + debian/version.patch
 + debian/kernelvariables.patch
 + debian/doc-build-parallel.patch
@@ -35,5 +35,4 @@
 + features/all/mtd-nor-add-support-for-the-st-m29w400db-flash-chip.patch
 + bugfix/all/rtc-x1205-new-style-conversion.patch
 + bugfix/all/rtc-x1205-new-style-conversion-checkpatch-fixes.patch
-+ bugfix/arm/ixp4xx-beeper-add-module_alias.patch
 + bugfix/all/mtd-prevent-physmap-from-causing-request_module-runaway-loop-modprobe-net-pf-1.patch



More information about the Kernel-svn-changes mailing list