--- /dev/null
+From stable-bounces@linux.kernel.org Thu Dec 13 19:04:09 2007
+From: Henrique de Moraes Holschuh <hmh@hmh.eng.br>
+Date: Thu, 13 Dec 2007 22:03:52 -0500
+Subject: ACPI: thinkpad-acpi: fix lenovo keymap for brightness
+To: stable@kernel.org
+Cc: Henrique Holschuh <hmh@hmh.eng.br>
+Message-ID: <200712132203.53013.lenb@kernel.org>
+Content-Disposition: inline
+
+
+From: Henrique de Moraes Holschuh <hmh@hmh.eng.br>
+
+upstream commit 56a185b43be05e48da7428e6a1d3e2585b232b1d
+
+Starting in 2.6.23...
+
+Several reports from X60 users complained that the default Lenovo keymap
+issuing EV_KEY KEY_BRIGHTNESS_UP/DOWN input events caused major issues when
+the proper brightness support through ACPI video.c was loaded.
+
+Therefore, remove the generation of these events by default, which is the
+right thing for T60, X60, R60, T61, X61 and R61 with their latest BIOSes.
+
+Distros that want to misuse these events into OSD reporting (which requires
+an ugly hack from hell in HAL) are welcome to set up the key map they need
+through HAL. That way, we don't break everyone else's systems.
+
+Signed-off-by: Henrique de Moraes Holschuh <hmh@hmh.eng.br>
+Signed-off-by: Len Brown <len.brown@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/misc/thinkpad_acpi.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/drivers/misc/thinkpad_acpi.c
++++ b/drivers/misc/thinkpad_acpi.c
+@@ -968,9 +968,9 @@ static int __init hotkey_init(struct ibm
+ KEY_UNKNOWN, /* 0x0C: FN+BACKSPACE */
+ KEY_UNKNOWN, /* 0x0D: FN+INSERT */
+ KEY_UNKNOWN, /* 0x0E: FN+DELETE */
+- KEY_BRIGHTNESSUP, /* 0x0F: FN+HOME (brightness up) */
++ KEY_RESERVED, /* 0x0F: FN+HOME (brightness up) */
+ /* Scan codes 0x10 to 0x1F: Extended ACPI HKEY hot keys */
+- KEY_BRIGHTNESSDOWN, /* 0x10: FN+END (brightness down) */
++ KEY_RESERVED, /* 0x10: FN+END (brightness down) */
+ KEY_RESERVED, /* 0x11: FN+PGUP (thinklight toggle) */
+ KEY_UNKNOWN, /* 0x12: FN+PGDOWN */
+ KEY_ZOOM, /* 0x13: FN+SPACE (zoom) */
--- /dev/null
+From stable-bounces@linux.kernel.org Thu Dec 13 14:41:00 2007
+From: William Lee Irwin III <wli@holomorphy.com>
+Date: Thu, 13 Dec 2007 16:29:16 -0500
+Subject: ACPI: video_device_list corruption
+To: stable@kernel.org
+Message-ID: <200712131629.16257.lenb@kernel.org>
+Content-Disposition: inline
+
+
+From: William Lee Irwin III <wli@holomorphy.com>
+
+The ->cap fields of struct acpi_video_device and struct acpi_video_bus
+are 1B each, not 4B. The oversized memset()'s corrupted the subsequent
+list_head fields. This resulted in silent corruption without
+CONFIG_DEBUG_LIST and BUG's with it. This patch uses sizeof() to pass
+the proper bounds to the memset() calls and thereby correct the bugs.
+
+upstream commit 98934def70b48dac74fac3738b78ab2d1a28edda
+
+Signed-off-by: William Irwin <wli@holomorphy.com>
+Acked-by: Mikael Pettersson <mikpe@it.uu.se>
+Signed-off-by: Len Brown <len.brown@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/acpi/video.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/drivers/acpi/video.c
++++ b/drivers/acpi/video.c
+@@ -573,7 +573,7 @@ static void acpi_video_device_find_cap(s
+ struct acpi_video_device_brightness *br = NULL;
+
+
+- memset(&device->cap, 0, 4);
++ memset(&device->cap, 0, sizeof(device->cap));
+
+ if (ACPI_SUCCESS(acpi_get_handle(device->dev->handle, "_ADR", &h_dummy1))) {
+ device->cap._ADR = 1;
+@@ -693,7 +693,7 @@ static void acpi_video_bus_find_cap(stru
+ {
+ acpi_handle h_dummy1;
+
+- memset(&video->cap, 0, 4);
++ memset(&video->cap, 0, sizeof(video->cap));
+ if (ACPI_SUCCESS(acpi_get_handle(video->device->handle, "_DOS", &h_dummy1))) {
+ video->cap._DOS = 1;
+ }
--- /dev/null
+From stable-bounces@linux.kernel.org Thu Dec 13 06:43:32 2007
+From: Milan Broz <mbroz@redhat.com>
+Date: Thu, 13 Dec 2007 14:43:05 +0000
+Subject: dm crypt: fix write endio
+To: Linus Torvalds <torvalds@linux-foundation.org>
+Cc: dm-crypt@saout.de, stable@kernel.org, dm-devel@redhat.com, linux-kernel@vger.kernel.org, Milan Broz <mbroz@redhat.com>
+Message-ID: <20071213144305.GV24157@agk.fab.redhat.com>
+Content-Disposition: inline
+
+
+From: Milan Broz <mbroz@redhat.com>
+
+patch adfe47702c4726b3e045f9f83178def02833be4c in mainline.
+
+Fix BIO_UPTODATE test for write io.
+
+Signed-off-by: Milan Broz <mbroz@redhat.com>
+Signed-off-by: Alasdair G Kergon <agk@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/md/dm-crypt.c | 7 ++++---
+ 1 file changed, 4 insertions(+), 3 deletions(-)
+
+--- a/drivers/md/dm-crypt.c
++++ b/drivers/md/dm-crypt.c
+@@ -515,6 +515,9 @@ static int crypt_endio(struct bio *clone
+ struct crypt_config *cc = io->target->private;
+ unsigned read_io = bio_data_dir(clone) == READ;
+
++ if (unlikely(!bio_flagged(clone, BIO_UPTODATE) && !error))
++ error = -EIO;
++
+ /*
+ * free the processed pages, even if
+ * it's only a partially completed write
+@@ -529,10 +532,8 @@ static int crypt_endio(struct bio *clone
+ if (!read_io)
+ goto out;
+
+- if (unlikely(!bio_flagged(clone, BIO_UPTODATE))) {
+- error = -EIO;
++ if (unlikely(error))
+ goto out;
+- }
+
+ bio_put(clone);
+ io->post_process = 1;
--- /dev/null
+From stable-bounces@linux.kernel.org Thu Dec 13 06:44:53 2007
+From: Milan Broz <mbroz@redhat.com>
+Date: Thu, 13 Dec 2007 14:44:18 +0000
+Subject: dm crypt: use bio_add_page
+To: Linus Torvalds <torvalds@linux-foundation.org>
+Cc: dm-crypt@saout.de, stable@kernel.org, dm-devel@redhat.com, linux-kernel@vger.kernel.org, Milan Broz <mbroz@redhat.com>
+Message-ID: <20071213144418.GY24157@agk.fab.redhat.com>
+Content-Disposition: inline
+
+
+From: Milan Broz <mbroz@redhat.com>
+
+patch 91e106259214b40e992a58fb9417da46868e19b2 in mainline.
+
+Fix possible max_phys_segments violation in cloned dm-crypt bio.
+
+In write operation dm-crypt needs to allocate new bio request
+and run crypto operation on this clone. Cloned request has always
+the same size, but number of physical segments can be increased
+and violate max_phys_segments restriction.
+
+This can lead to data corruption and serious hardware malfunction.
+This was observed when using XFS over dm-crypt and at least
+two HBA controller drivers (arcmsr, cciss) recently.
+
+Fix it by using bio_add_page() call (which tests for other
+restrictions too) instead of constructing own biovec.
+
+All versions of dm-crypt are affected by this bug.
+
+Signed-off-by: Milan Broz <mbroz@redhat.com>
+Signed-off-by: Alasdair G Kergon <agk@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/md/dm-crypt.c | 24 +++++++++++-------------
+ 1 file changed, 11 insertions(+), 13 deletions(-)
+
+--- a/drivers/md/dm-crypt.c
++++ b/drivers/md/dm-crypt.c
+@@ -399,7 +399,8 @@ static struct bio *crypt_alloc_buffer(st
+ struct bio *clone;
+ unsigned int nr_iovecs = (size + PAGE_SIZE - 1) >> PAGE_SHIFT;
+ gfp_t gfp_mask = GFP_NOIO | __GFP_HIGHMEM;
+- unsigned int i;
++ unsigned i, len;
++ struct page *page;
+
+ clone = bio_alloc_bioset(GFP_NOIO, nr_iovecs, cc->bs);
+ if (!clone)
+@@ -408,10 +409,8 @@ static struct bio *crypt_alloc_buffer(st
+ clone_init(io, clone);
+
+ for (i = 0; i < nr_iovecs; i++) {
+- struct bio_vec *bv = bio_iovec_idx(clone, i);
+-
+- bv->bv_page = mempool_alloc(cc->page_pool, gfp_mask);
+- if (!bv->bv_page)
++ page = mempool_alloc(cc->page_pool, gfp_mask);
++ if (!page)
+ break;
+
+ /*
+@@ -422,15 +421,14 @@ static struct bio *crypt_alloc_buffer(st
+ if (i == (MIN_BIO_PAGES - 1))
+ gfp_mask = (gfp_mask | __GFP_NOWARN) & ~__GFP_WAIT;
+
+- bv->bv_offset = 0;
+- if (size > PAGE_SIZE)
+- bv->bv_len = PAGE_SIZE;
+- else
+- bv->bv_len = size;
++ len = (size > PAGE_SIZE) ? PAGE_SIZE : size;
++
++ if (!bio_add_page(clone, page, len, 0)) {
++ mempool_free(page, cc->page_pool);
++ break;
++ }
+
+- clone->bi_size += bv->bv_len;
+- clone->bi_vcnt++;
+- size -= bv->bv_len;
++ size -= len;
+ }
+
+ if (!clone->bi_size) {
--- /dev/null
+From stable-bounces@linux.kernel.org Thu Dec 13 06:42:48 2007
+From: Jun'ichi Nomura <j-nomura@ce.jp.nec.com>
+Date: Thu, 13 Dec 2007 14:42:08 +0000
+Subject: dm: table detect io beyond device
+To: Linus Torvalds <torvalds@linux-foundation.org>
+Cc: "Jun'ichi Nomura" <j-nomura@ce.jp.nec.com>, dm-devel@redhat.com, linux-kernel@vger.kernel.org, stable@kernel.org
+Message-ID: <20071213144208.GT24157@agk.fab.redhat.com>
+Content-Disposition: inline
+
+
+From: Jun'ichi Nomura <j-nomura@ce.jp.nec.com>
+
+Patch 512875bd9661368da6f993205a61213b79ba1df0 in mainline.
+
+This patch fixes a panic on shrinking a DM device if there is
+outstanding I/O to the part of the device that is being removed.
+(Normally this doesn't happen - a filesystem would be resized first,
+for example.)
+
+The bug is that __clone_and_map() assumes dm_table_find_target()
+always returns a valid pointer. It may fail if a bio arrives from the
+block layer but its target sector is no longer included in the DM
+btree.
+
+This patch appends an empty entry to table->targets[] which will
+be returned by a lookup beyond the end of the device.
+
+After calling dm_table_find_target(), __clone_and_map() and target_message()
+check for this condition using
+dm_target_is_valid().
+
+Sample test script to trigger oops:
+
+#!/bin/bash
+
+FILE=$(mktemp)
+LODEV=$(losetup -f)
+MAP=$(basename ${FILE})
+SIZE=4M
+
+dd if=/dev/zero of=${FILE} bs=${SIZE} count=1
+losetup ${LODEV} ${FILE}
+
+echo "0 $(blockdev --getsz ${LODEV}) linear ${LODEV} 0" |dmsetup create ${MAP}
+dmsetup suspend ${MAP}
+echo "0 1 linear ${LODEV} 0" |dmsetup load ${MAP}
+dd if=/dev/zero of=/dev/mapper/${MAP} bs=${SIZE} count=1 &
+echo "Wait til dd push some I/O"
+sleep 5
+dmsetup resume ${MAP}
+
+Signed-off-by: Jun'ichi Nomura <j-nomura@ce.jp.nec.com>
+Signed-off-by: Alasdair G Kergon <agk@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+
+---
+ drivers/md/dm-ioctl.c | 10 +++-------
+ drivers/md/dm-table.c | 7 ++++++-
+ drivers/md/dm.c | 24 ++++++++++++++++++------
+ drivers/md/dm.h | 5 +++++
+ 4 files changed, 32 insertions(+), 14 deletions(-)
+
+--- a/drivers/md/dm-ioctl.c
++++ b/drivers/md/dm-ioctl.c
+@@ -1250,21 +1250,17 @@ static int target_message(struct dm_ioct
+ if (!table)
+ goto out_argv;
+
+- if (tmsg->sector >= dm_table_get_size(table)) {
++ ti = dm_table_find_target(table, tmsg->sector);
++ if (!dm_target_is_valid(ti)) {
+ DMWARN("Target message sector outside device.");
+ r = -EINVAL;
+- goto out_table;
+- }
+-
+- ti = dm_table_find_target(table, tmsg->sector);
+- if (ti->type->message)
++ } else if (ti->type->message)
+ r = ti->type->message(ti, argc, argv);
+ else {
+ DMWARN("Target type does not support messages");
+ r = -EINVAL;
+ }
+
+- out_table:
+ dm_table_put(table);
+ out_argv:
+ kfree(argv);
+--- a/drivers/md/dm-table.c
++++ b/drivers/md/dm-table.c
+@@ -187,8 +187,10 @@ static int alloc_targets(struct dm_table
+
+ /*
+ * Allocate both the target array and offset array at once.
++ * Append an empty entry to catch sectors beyond the end of
++ * the device.
+ */
+- n_highs = (sector_t *) dm_vcalloc(num, sizeof(struct dm_target) +
++ n_highs = (sector_t *) dm_vcalloc(num + 1, sizeof(struct dm_target) +
+ sizeof(sector_t));
+ if (!n_highs)
+ return -ENOMEM;
+@@ -862,6 +864,9 @@ struct dm_target *dm_table_get_target(st
+
+ /*
+ * Search the btree for the correct target.
++ *
++ * Caller should check returned pointer with dm_target_is_valid()
++ * to trap I/O beyond end of device.
+ */
+ struct dm_target *dm_table_find_target(struct dm_table *t, sector_t sector)
+ {
+--- a/drivers/md/dm.c
++++ b/drivers/md/dm.c
+@@ -663,13 +663,19 @@ static struct bio *clone_bio(struct bio
+ return clone;
+ }
+
+-static void __clone_and_map(struct clone_info *ci)
++static int __clone_and_map(struct clone_info *ci)
+ {
+ struct bio *clone, *bio = ci->bio;
+- struct dm_target *ti = dm_table_find_target(ci->map, ci->sector);
+- sector_t len = 0, max = max_io_len(ci->md, ci->sector, ti);
++ struct dm_target *ti;
++ sector_t len = 0, max;
+ struct dm_target_io *tio;
+
++ ti = dm_table_find_target(ci->map, ci->sector);
++ if (!dm_target_is_valid(ti))
++ return -EIO;
++
++ max = max_io_len(ci->md, ci->sector, ti);
++
+ /*
+ * Allocate a target io object.
+ */
+@@ -727,6 +733,9 @@ static void __clone_and_map(struct clone
+ do {
+ if (offset) {
+ ti = dm_table_find_target(ci->map, ci->sector);
++ if (!dm_target_is_valid(ti))
++ return -EIO;
++
+ max = max_io_len(ci->md, ci->sector, ti);
+
+ tio = alloc_tio(ci->md);
+@@ -750,6 +759,8 @@ static void __clone_and_map(struct clone
+
+ ci->idx++;
+ }
++
++ return 0;
+ }
+
+ /*
+@@ -758,6 +769,7 @@ static void __clone_and_map(struct clone
+ static void __split_bio(struct mapped_device *md, struct bio *bio)
+ {
+ struct clone_info ci;
++ int error = 0;
+
+ ci.map = dm_get_table(md);
+ if (!ci.map) {
+@@ -777,11 +789,11 @@ static void __split_bio(struct mapped_de
+ ci.idx = bio->bi_idx;
+
+ start_io_acct(ci.io);
+- while (ci.sector_count)
+- __clone_and_map(&ci);
++ while (ci.sector_count && !error)
++ error = __clone_and_map(&ci);
+
+ /* drop the extra reference count */
+- dec_pending(ci.io, 0);
++ dec_pending(ci.io, error);
+ dm_table_put(ci.map);
+ }
+ /*-----------------------------------------------------------------
+--- a/drivers/md/dm.h
++++ b/drivers/md/dm.h
+@@ -113,6 +113,11 @@ int dm_table_any_congested(struct dm_tab
+ void dm_table_unplug_all(struct dm_table *t);
+ int dm_table_flush_all(struct dm_table *t);
+
++/*
++ * To check the return value from dm_table_find_target().
++ */
++#define dm_target_is_valid(t) ((t)->table)
++
+ /*-----------------------------------------------------------------
+ * A registry of target types.
+ *---------------------------------------------------------------*/
--- /dev/null
+dm-table-detect-io-beyond-device.patch
+dm-crypt-fix-write-endio.patch
+dm-crypt-use-bio_add_page.patch
+acpi-video_device_list-corruption.patch
+acpi-thinkpad-acpi-fix-lenovo-keymap-for-brightness.patch