From: Greg Kroah-Hartman Date: Tue, 25 Apr 2006 23:51:20 +0000 (-0700) Subject: lots more patches queued up. X-Git-Tag: v2.6.16.12~10 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=6ede41271ca31f9ffc36cffd4be23ecabc5a152c;p=thirdparty%2Fkernel%2Fstable-queue.git lots more patches queued up. --- diff --git a/queue-2.6.16/cxusb-bluebird-bug-fix-power-down-corrupts-frontend.patch b/queue-2.6.16/cxusb-bluebird-bug-fix-power-down-corrupts-frontend.patch new file mode 100644 index 00000000000..38455692335 --- /dev/null +++ b/queue-2.6.16/cxusb-bluebird-bug-fix-power-down-corrupts-frontend.patch @@ -0,0 +1,80 @@ +From stable-bounces@linux.kernel.org Sat Apr 22 00:35:54 2006 +Message-ID: <4449DCD6.5070609@linuxtv.org> +Date: Sat, 22 Apr 2006 03:35:50 -0400 +From: Michael Krufky +To: stable@kernel.org +Cc: +Subject: cxusb-bluebird: bug-fix: power down corrupts frontend + +From: Michael Krufky + +This patch prevents a bug where the frontend is unable to tune after waking +from powered down state. Now, the device remains powered on until it is +disconnected, just like the windows driver. It seems that the bluebird +firmware is unable to successfully handle tuning after a powered down state. + +This patch fixes all of the FusionHDTV Bluebird USB2 devices. The Medion +MD95700 will still behave as before, since it was unaffected by this bug. + +Signed-off-by: Michael Krufky +Signed-off-by: Greg Kroah-Hartman + + +--- + drivers/media/dvb/dvb-usb/cxusb.c | 17 +++++++++++++---- + 1 file changed, 13 insertions(+), 4 deletions(-) + +--- linux-2.6.16.11.orig/drivers/media/dvb/dvb-usb/cxusb.c ++++ linux-2.6.16.11/drivers/media/dvb/dvb-usb/cxusb.c +@@ -149,6 +149,15 @@ static int cxusb_power_ctrl(struct dvb_u + return cxusb_ctrl_msg(d, CMD_POWER_OFF, &b, 1, NULL, 0); + } + ++static int cxusb_bluebird_power_ctrl(struct dvb_usb_device *d, int onoff) ++{ ++ u8 b = 0; ++ if (onoff) ++ return cxusb_ctrl_msg(d, CMD_POWER_ON, &b, 1, NULL, 0); ++ else ++ return 0; ++} ++ + static int cxusb_streaming_ctrl(struct dvb_usb_device *d, int onoff) + { + u8 buf[2] = { 0x03, 0x00 }; +@@ -505,7 +514,7 @@ static struct dvb_usb_properties cxusb_b + .size_of_priv = sizeof(struct cxusb_state), + + .streaming_ctrl = cxusb_streaming_ctrl, +- .power_ctrl = cxusb_power_ctrl, ++ .power_ctrl = cxusb_bluebird_power_ctrl, + .frontend_attach = cxusb_lgdt3303_frontend_attach, + .tuner_attach = cxusb_lgh064f_tuner_attach, + +@@ -545,7 +554,7 @@ static struct dvb_usb_properties cxusb_b + .size_of_priv = sizeof(struct cxusb_state), + + .streaming_ctrl = cxusb_streaming_ctrl, +- .power_ctrl = cxusb_power_ctrl, ++ .power_ctrl = cxusb_bluebird_power_ctrl, + .frontend_attach = cxusb_dee1601_frontend_attach, + .tuner_attach = cxusb_dee1601_tuner_attach, + +@@ -594,7 +603,7 @@ static struct dvb_usb_properties cxusb_b + .size_of_priv = sizeof(struct cxusb_state), + + .streaming_ctrl = cxusb_streaming_ctrl, +- .power_ctrl = cxusb_power_ctrl, ++ .power_ctrl = cxusb_bluebird_power_ctrl, + .frontend_attach = cxusb_mt352_frontend_attach, + .tuner_attach = cxusb_lgz201_tuner_attach, + +@@ -634,7 +643,7 @@ static struct dvb_usb_properties cxusb_b + .size_of_priv = sizeof(struct cxusb_state), + + .streaming_ctrl = cxusb_streaming_ctrl, +- .power_ctrl = cxusb_power_ctrl, ++ .power_ctrl = cxusb_bluebird_power_ctrl, + .frontend_attach = cxusb_mt352_frontend_attach, + .tuner_attach = cxusb_dtt7579_tuner_attach, + diff --git a/queue-2.6.16/dm-flush-queue-EINTR.patch b/queue-2.6.16/dm-flush-queue-EINTR.patch new file mode 100644 index 00000000000..633f9b824a5 --- /dev/null +++ b/queue-2.6.16/dm-flush-queue-EINTR.patch @@ -0,0 +1,41 @@ +From nobody Mon Sep 17 00:00:00 2001 +From: Jun'ichi Nomura +Date: Mon Mar 27 01:17:51 2006 -0800 +Subject: [PATCH] dm flush queue EINTR + +If dm_suspend() is cancelled, bios already added to the deferred list need to +be submitted. Otherwise they remain 'in limbo' until there's a dm_resume(). + +Signed-off-by: Jun'ichi Nomura +Signed-off-by: Alasdair G Kergon +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/md/dm.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +--- linux-2.6.16.11.orig/drivers/md/dm.c ++++ linux-2.6.16.11/drivers/md/dm.c +@@ -1098,6 +1098,7 @@ int dm_suspend(struct mapped_device *md, + { + struct dm_table *map = NULL; + DECLARE_WAITQUEUE(wait, current); ++ struct bio *def; + int r = -EINVAL; + + down(&md->suspend_lock); +@@ -1157,9 +1158,11 @@ int dm_suspend(struct mapped_device *md, + /* were we interrupted ? */ + r = -EINTR; + if (atomic_read(&md->pending)) { ++ clear_bit(DMF_BLOCK_IO, &md->flags); ++ def = bio_list_get(&md->deferred); ++ __flush_deferred_io(md, def); + up_write(&md->io_lock); + unlock_fs(md); +- clear_bit(DMF_BLOCK_IO, &md->flags); + goto out; + } + up_write(&md->io_lock); diff --git a/queue-2.6.16/dm-snapshot-fix-kcopyd-destructor.patch b/queue-2.6.16/dm-snapshot-fix-kcopyd-destructor.patch new file mode 100644 index 00000000000..033cbaa604e --- /dev/null +++ b/queue-2.6.16/dm-snapshot-fix-kcopyd-destructor.patch @@ -0,0 +1,114 @@ +From stable-bounces@linux.kernel.org Mon Apr 24 13:38:02 2006 +Date: Mon, 24 Apr 2006 13:36:06 -0700 +From: Andrew Morton +To: stable@kernel.org +Message-Id: <20060424133606.66bd21f6.akpm@osdl.org> +Cc: Alasdair G Kergon +Subject: dm snapshot: fix kcopyd destructor + + +From: Alasdair G Kergon + +Before removing a snapshot, wait for the completion of any kcopyd jobs using +it. + +Do this by maintaining a count (nr_jobs) of how many outstanding jobs each +kcopyd_client has. + +The snapshot destructor first unregisters the snapshot so that no new kcopyd +jobs (created by writes to the origin) will reference that particular +snapshot. kcopyd_client_destroy() is now run next to wait for the completion +of any outstanding jobs before the snapshot exception structures (that those +jobs reference) are freed. + +Signed-off-by: Alasdair G Kergon +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/md/dm-snap.c | 6 +++++- + drivers/md/kcopyd.c | 17 ++++++++++++++++- + 2 files changed, 21 insertions(+), 2 deletions(-) + +--- linux-2.6.16.11.orig/drivers/md/dm-snap.c ++++ linux-2.6.16.11/drivers/md/dm-snap.c +@@ -542,8 +542,12 @@ static void snapshot_dtr(struct dm_targe + { + struct dm_snapshot *s = (struct dm_snapshot *) ti->private; + ++ /* Prevent further origin writes from using this snapshot. */ ++ /* After this returns there can be no new kcopyd jobs. */ + unregister_snapshot(s); + ++ kcopyd_client_destroy(s->kcopyd_client); ++ + exit_exception_table(&s->pending, pending_cache); + exit_exception_table(&s->complete, exception_cache); + +@@ -552,7 +556,7 @@ static void snapshot_dtr(struct dm_targe + + dm_put_device(ti, s->origin); + dm_put_device(ti, s->cow); +- kcopyd_client_destroy(s->kcopyd_client); ++ + kfree(s); + } + +--- linux-2.6.16.11.orig/drivers/md/kcopyd.c ++++ linux-2.6.16.11/drivers/md/kcopyd.c +@@ -44,6 +44,9 @@ struct kcopyd_client { + struct page_list *pages; + unsigned int nr_pages; + unsigned int nr_free_pages; ++ ++ wait_queue_head_t destroyq; ++ atomic_t nr_jobs; + }; + + static struct page_list *alloc_pl(void) +@@ -293,10 +296,15 @@ static int run_complete_job(struct kcopy + int read_err = job->read_err; + unsigned int write_err = job->write_err; + kcopyd_notify_fn fn = job->fn; ++ struct kcopyd_client *kc = job->kc; + +- kcopyd_put_pages(job->kc, job->pages); ++ kcopyd_put_pages(kc, job->pages); + mempool_free(job, _job_pool); + fn(read_err, write_err, context); ++ ++ if (atomic_dec_and_test(&kc->nr_jobs)) ++ wake_up(&kc->destroyq); ++ + return 0; + } + +@@ -431,6 +439,7 @@ static void do_work(void *ignored) + */ + static void dispatch_job(struct kcopyd_job *job) + { ++ atomic_inc(&job->kc->nr_jobs); + push(&_pages_jobs, job); + wake(); + } +@@ -670,6 +679,9 @@ int kcopyd_client_create(unsigned int nr + return r; + } + ++ init_waitqueue_head(&kc->destroyq); ++ atomic_set(&kc->nr_jobs, 0); ++ + client_add(kc); + *result = kc; + return 0; +@@ -677,6 +689,9 @@ int kcopyd_client_create(unsigned int nr + + void kcopyd_client_destroy(struct kcopyd_client *kc) + { ++ /* Wait for completion of all jobs submitted by this client. */ ++ wait_event(kc->destroyq, !atomic_read(&kc->nr_jobs)); ++ + dm_io_put(kc->nr_pages); + client_free_pages(kc); + client_del(kc); diff --git a/queue-2.6.16/fix-saa7129-support-in-saa7127-module-for-pvr350-tv-out.patch b/queue-2.6.16/fix-saa7129-support-in-saa7127-module-for-pvr350-tv-out.patch new file mode 100644 index 00000000000..0b456878c76 --- /dev/null +++ b/queue-2.6.16/fix-saa7129-support-in-saa7127-module-for-pvr350-tv-out.patch @@ -0,0 +1,35 @@ +From stable-bounces@linux.kernel.org Sat Apr 22 00:35:54 2006 +Message-ID: <4449DCD1.70008@linuxtv.org> +Date: Sat, 22 Apr 2006 03:35:45 -0400 +From: Michael Krufky +To: stable@kernel.org +Cc: +Subject: fix saa7129 support in saa7127 module for pvr350 tv out + +From: Jose Alberto Reguero + +This patch fixes tv-out support for the newer model of +the pvr350, which has a saa7129 instead of a saa7127 +video encoder. + +Signed-off-by: Jose Alberto Reguero +Signed-off-by: Mauro Carvalho Chehab +Signed-off-by: Hans Verkuil +Signed-off-by: Michael Krufky +Signed-off-by: Greg Kroah-Hartman + + +--- + drivers/media/video/saa7127.c | 1 + + 1 file changed, 1 insertion(+) + +--- linux-2.6.16.11.orig/drivers/media/video/saa7127.c ++++ linux-2.6.16.11/drivers/media/video/saa7127.c +@@ -141,6 +141,7 @@ struct i2c_reg_value { + static const struct i2c_reg_value saa7129_init_config_extra[] = { + { SAA7127_REG_OUTPUT_PORT_CONTROL, 0x38 }, + { SAA7127_REG_VTRIG, 0xfa }, ++ { 0, 0 } + }; + + static const struct i2c_reg_value saa7127_init_config_common[] = { diff --git a/queue-2.6.16/for_each_possible_cpu.patch b/queue-2.6.16/for_each_possible_cpu.patch new file mode 100644 index 00000000000..081e21ad852 --- /dev/null +++ b/queue-2.6.16/for_each_possible_cpu.patch @@ -0,0 +1,32 @@ +From stable-bounces@linux.kernel.org Mon Apr 24 01:51:43 2006 +Message-Id: <200604240851.k3O8pAW9012366@shell0.pdx.osdl.net> +To: stable@kernel.org +From: akpm@osdl.org +Date: Mon, 24 Apr 2006 01:49:59 -0700 +Cc: norbert@tretkowski.de +Subject: for_each_possible_cpu + + +From: Andrew Morton + +Backport for_each_possible_cpu() into 2.6.16. Fixes the alpha build, and any +future occurrences. + + +Signed-off-by: Andrew Morton +Signed-off-by: Greg Kroah-Hartman + +--- + include/linux/cpumask.h | 1 + + 1 file changed, 1 insertion(+) + +--- linux-2.6.16.11.orig/include/linux/cpumask.h ++++ linux-2.6.16.11/include/linux/cpumask.h +@@ -408,6 +408,7 @@ extern cpumask_t cpu_present_map; + }) + + #define for_each_cpu(cpu) for_each_cpu_mask((cpu), cpu_possible_map) ++#define for_each_possible_cpu(cpu) for_each_cpu_mask((cpu), cpu_possible_map) + #define for_each_online_cpu(cpu) for_each_cpu_mask((cpu), cpu_online_map) + #define for_each_present_cpu(cpu) for_each_cpu_mask((cpu), cpu_present_map) + diff --git a/queue-2.6.16/get_dvb_firmware-download-nxt2002-firmware-from-new-driver-location.patch b/queue-2.6.16/get_dvb_firmware-download-nxt2002-firmware-from-new-driver-location.patch new file mode 100644 index 00000000000..ec01ca50823 --- /dev/null +++ b/queue-2.6.16/get_dvb_firmware-download-nxt2002-firmware-from-new-driver-location.patch @@ -0,0 +1,47 @@ +From stable-bounces@linux.kernel.org Sat Apr 22 23:17:00 2006 +Message-ID: <444B1BCA.6050702@linuxtv.org> +Date: Sun, 23 Apr 2006 02:16:42 -0400 +From: Michael Krufky +To: stable@kernel.org +Cc: +Subject: get_dvb_firmware: download nxt2002 firmware from new driver location + +From: Michael Krufky + +BBTI has updated their driver, and removed the old one from their website. +This patch updates the get_dvb_firmware script to download the firmware +from the new driver location. + +Signed-off-by: Michael Krufky +Signed-off-by: Greg Kroah-Hartman + + +--- + Documentation/dvb/get_dvb_firmware | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +--- linux-2.6.16.11.orig/Documentation/dvb/get_dvb_firmware ++++ linux-2.6.16.11/Documentation/dvb/get_dvb_firmware +@@ -240,9 +240,9 @@ sub dibusb { + } + + sub nxt2002 { +- my $sourcefile = "Broadband4PC_4_2_11.zip"; ++ my $sourcefile = "Technisat_DVB-PC_4_4_COMPACT.zip"; + my $url = "http://www.bbti.us/download/windows/$sourcefile"; +- my $hash = "c6d2ea47a8f456d887ada0cfb718ff2a"; ++ my $hash = "476befae8c7c1bb9648954060b1eec1f"; + my $outfile = "dvb-fe-nxt2002.fw"; + my $tmpdir = tempdir(DIR => "/tmp", CLEANUP => 1); + +@@ -250,8 +250,8 @@ sub nxt2002 { + + wgetfile($sourcefile, $url); + unzip($sourcefile, $tmpdir); +- verify("$tmpdir/SkyNETU.sys", $hash); +- extract("$tmpdir/SkyNETU.sys", 375832, 5908, $outfile); ++ verify("$tmpdir/SkyNET.sys", $hash); ++ extract("$tmpdir/SkyNET.sys", 331624, 5908, $outfile); + + $outfile; + } diff --git a/queue-2.6.16/ide-io-increase-timeout-value-to-allow-for-slave-wakeup.patch b/queue-2.6.16/ide-io-increase-timeout-value-to-allow-for-slave-wakeup.patch new file mode 100644 index 00000000000..8ca201e18c1 --- /dev/null +++ b/queue-2.6.16/ide-io-increase-timeout-value-to-allow-for-slave-wakeup.patch @@ -0,0 +1,36 @@ +From stable-bounces@linux.kernel.org Sun Apr 23 16:21:19 2006 +Message-Id: <200604232320.k3NNKs3V001090@shell0.pdx.osdl.net> +To: a1426z@gawab.com, alan@lxorguk.ukuu.org.uk, + B.Zolnierkiewicz@elka.pw.edu.pl, stable@kernel.org, + mm-commits@vger.kernel.org +From: akpm@osdl.org +Date: Sun, 23 Apr 2006 16:19:45 -0700 +Cc: +Subject: ide-io: increase timeout value to allow for slave wakeup + +From: Al Boldi + +During an STR resume cycle, the ide master disk times-out when there is +also a slave present (especially CD). Increasing the timeout in ide-io +from 10,000 to 100,000 fixes this problem. + +Cc: Alan Cox +Cc: Bartlomiej Zolnierkiewicz +Signed-off-by: Andrew Morton +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/ide/ide-io.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- linux-2.6.16.11.orig/drivers/ide/ide-io.c ++++ linux-2.6.16.11/drivers/ide/ide-io.c +@@ -932,7 +932,7 @@ static ide_startstop_t start_request (id + printk(KERN_WARNING "%s: bus not ready on wakeup\n", drive->name); + SELECT_DRIVE(drive); + HWIF(drive)->OUTB(8, HWIF(drive)->io_ports[IDE_CONTROL_OFFSET]); +- rc = ide_wait_not_busy(HWIF(drive), 10000); ++ rc = ide_wait_not_busy(HWIF(drive), 100000); + if (rc) + printk(KERN_WARNING "%s: drive not ready on wakeup\n", drive->name); + } diff --git a/queue-2.6.16/make-vm86-call-audit_syscall_exit.patch b/queue-2.6.16/make-vm86-call-audit_syscall_exit.patch new file mode 100644 index 00000000000..4cd74413de1 --- /dev/null +++ b/queue-2.6.16/make-vm86-call-audit_syscall_exit.patch @@ -0,0 +1,106 @@ +From nobody Mon Sep 17 00:00:00 2001 +From: Jason Baron +Date: Tue Jan 31 16:56:28 2006 -0500 +Subject: [PATCH] make vm86 call audit_syscall_exit + +hi, + +The motivation behind the patch below was to address messages in +/var/log/messages such as: + +Jan 31 10:54:15 mets kernel: audit(:0): major=252 name_count=0: freeing +multiple contexts (1) +Jan 31 10:54:15 mets kernel: audit(:0): major=113 name_count=0: freeing +multiple contexts (2) + +I can reproduce by running 'get-edid' from: +http://john.fremlin.de/programs/linux/read-edid/. + +These messages come about in the log b/c the vm86 calls do not exit via +the normal system call exit paths and thus do not call +'audit_syscall_exit'. The next system call will then free the context for +itself and for the vm86 context, thus generating the above messages. This +patch addresses the issue by simply adding a call to 'audit_syscall_exit' +from the vm86 code. + +Besides fixing the above error messages the patch also now allows vm86 +system calls to become auditable. This is useful since strace does not +appear to properly record the return values from sys_vm86. + +I think this patch is also a step in the right direction in terms of +cleaning up some core auditing code. If we can correct any other paths +that do not properly call the audit exit and entries points, then we can +also eliminate the notion of context chaining. + +I've tested this patch by verifying that the log messages no longer +appear, and that the audit records for sys_vm86 appear to be correct. +Also, 'read_edid' produces itentical output. + +thanks, + +-Jason + +Signed-off-by: Jason Baron +Signed-off-by: Al Viro +Signed-off-by: Greg Kroah-Hartman + +--- +--- + arch/i386/kernel/vm86.c | 12 ++++++++++-- + kernel/auditsc.c | 5 ----- + 2 files changed, 10 insertions(+), 7 deletions(-) + +--- linux-2.6.16.11.orig/arch/i386/kernel/vm86.c ++++ linux-2.6.16.11/arch/i386/kernel/vm86.c +@@ -43,6 +43,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -252,6 +253,7 @@ out: + static void do_sys_vm86(struct kernel_vm86_struct *info, struct task_struct *tsk) + { + struct tss_struct *tss; ++ long eax; + /* + * make sure the vm86() system call doesn't try to do anything silly + */ +@@ -305,13 +307,19 @@ static void do_sys_vm86(struct kernel_vm + tsk->thread.screen_bitmap = info->screen_bitmap; + if (info->flags & VM86_SCREEN_BITMAP) + mark_screen_rdonly(tsk->mm); ++ __asm__ __volatile__("xorl %eax,%eax; movl %eax,%fs; movl %eax,%gs\n\t"); ++ __asm__ __volatile__("movl %%eax, %0\n" :"=r"(eax)); ++ ++ /*call audit_syscall_exit since we do not exit via the normal paths */ ++ if (unlikely(current->audit_context)) ++ audit_syscall_exit(current, AUDITSC_RESULT(eax), eax); ++ + __asm__ __volatile__( +- "xorl %%eax,%%eax; movl %%eax,%%fs; movl %%eax,%%gs\n\t" + "movl %0,%%esp\n\t" + "movl %1,%%ebp\n\t" + "jmp resume_userspace" + : /* no outputs */ +- :"r" (&info->regs), "r" (task_thread_info(tsk)) : "ax"); ++ :"r" (&info->regs), "r" (task_thread_info(tsk))); + /* we never return here */ + } + +--- linux-2.6.16.11.orig/kernel/auditsc.c ++++ linux-2.6.16.11/kernel/auditsc.c +@@ -966,11 +966,6 @@ void audit_syscall_entry(struct task_str + if (context->in_syscall) { + struct audit_context *newctx; + +-#if defined(__NR_vm86) && defined(__NR_vm86old) +- /* vm86 mode should only be entered once */ +- if (major == __NR_vm86 || major == __NR_vm86old) +- return; +-#endif + #if AUDIT_DEBUG + printk(KERN_ERR + "audit(:%d) pid=%d in syscall=%d;" diff --git a/queue-2.6.16/series b/queue-2.6.16/series index 536dd78f662..62474157786 100644 --- a/queue-2.6.16/series +++ b/queue-2.6.16/series @@ -1,2 +1,15 @@ sonypi-correct-detection-of-new-ich7-based-laptops.patch cs5535_gpio.c-call-cdev_del-during-module_exit-to-unmap-kobject-references-and-other-cleanups.patch +make-vm86-call-audit_syscall_exit.patch +x86_64-pass-32-to-the-assembler-when-compiling-the-32bit-vsyscall-pages.patch +x86_64-fix-a-race-in-the-free_iommu-path.patch +usb-fix-array-overrun-in-drivers-usb-serial-option.c.patch +tipar-oops-fix.patch +ide-io-increase-timeout-value-to-allow-for-slave-wakeup.patch +get_dvb_firmware-download-nxt2002-firmware-from-new-driver-location.patch +for_each_possible_cpu.patch +fix-saa7129-support-in-saa7127-module-for-pvr350-tv-out.patch +cxusb-bluebird-bug-fix-power-down-corrupts-frontend.patch +dm-snapshot-fix-kcopyd-destructor.patch +dm-flush-queue-EINTR.patch +simplify-proc-devices-and-fix-early-termination-regression.patch diff --git a/queue-2.6.16/simplify-proc-devices-and-fix-early-termination-regression.patch b/queue-2.6.16/simplify-proc-devices-and-fix-early-termination-regression.patch new file mode 100644 index 00000000000..9c270d33e5b --- /dev/null +++ b/queue-2.6.16/simplify-proc-devices-and-fix-early-termination-regression.patch @@ -0,0 +1,540 @@ +From akpm@osdl.org Fri Apr 21 01:52:42 2006 +Date: Fri, 21 Apr 2006 01:51:36 -0700 +From: Joe Korty +From: Andrew Morton +To: Greg KH , Chris Wright +Subject: Simplify proc/devices and fix early termination regression +Message-Id: <20060421015136.68ba9c1f.akpm@osdl.org> + + +Repair /proc/devices early-termination regression. + +2.6.16 broke /proc/devices. An application often gets an +EOF before the end of data is reached, if that application +uses a series of short read(2)s to access the data. I have +used read buffers of varying sizes with varying degrees +of unsuccess (larger sizes get further into the data than +smaller sizes, following a simple pattern). It appears +that the only safe way to get the data is to use a single +read buffer larger than all the data in /proc/devices. + +The following example demonstates the problem: + + # dd if=/proc/devices bs=1 + Character devices: + 1 mem + 27+0 records in + 27+0 records out + +This patch is a backport of the fix recently accepted to +Linus's tree: + + commit 68eef3b4791572ecb70249c7fb145bb3742dd899 + [PATCH] Simplify proc/devices and fix early termination regression + +It replaces the complex, state-machine algorithm introduced +in 2.6.16 with a simple algorithm, modeled on the implementation +of /proc/interrupts. + +[akpm@osdl.org: cleanups, simplifications] + +Signed-off-by: Joe Korty +Signed-off-by: Greg Kroah-Hartman + + +--- + block/genhd.c | 103 +++------------------------------ + fs/char_dev.c | 87 +++------------------------- + fs/proc/proc_misc.c | 161 +++++++++++----------------------------------------- + include/linux/fs.h | 15 +--- + 4 files changed, 61 insertions(+), 305 deletions(-) + +--- linux-2.6.16.11.orig/block/genhd.c ++++ linux-2.6.16.11/block/genhd.c +@@ -16,8 +16,6 @@ + #include + #include + +-#define MAX_PROBE_HASH 255 /* random */ +- + static struct subsystem block_subsys; + + static DECLARE_MUTEX(block_subsys_sem); +@@ -30,108 +28,29 @@ static struct blk_major_name { + struct blk_major_name *next; + int major; + char name[16]; +-} *major_names[MAX_PROBE_HASH]; ++} *major_names[BLKDEV_MAJOR_HASH_SIZE]; + + /* index in the above - for now: assume no multimajor ranges */ + static inline int major_to_index(int major) + { +- return major % MAX_PROBE_HASH; +-} +- +-struct blkdev_info { +- int index; +- struct blk_major_name *bd; +-}; +- +-/* +- * iterate over a list of blkdev_info structures. allows +- * the major_names array to be iterated over from outside this file +- * must be called with the block_subsys_sem held +- */ +-void *get_next_blkdev(void *dev) +-{ +- struct blkdev_info *info; +- +- if (dev == NULL) { +- info = kmalloc(sizeof(*info), GFP_KERNEL); +- if (!info) +- goto out; +- info->index=0; +- info->bd = major_names[info->index]; +- if (info->bd) +- goto out; +- } else { +- info = dev; +- } +- +- while (info->index < ARRAY_SIZE(major_names)) { +- if (info->bd) +- info->bd = info->bd->next; +- if (info->bd) +- goto out; +- /* +- * No devices on this chain, move to the next +- */ +- info->index++; +- info->bd = (info->index < ARRAY_SIZE(major_names)) ? +- major_names[info->index] : NULL; +- if (info->bd) +- goto out; +- } +- +-out: +- return info; +-} +- +-void *acquire_blkdev_list(void) +-{ +- down(&block_subsys_sem); +- return get_next_blkdev(NULL); +-} +- +-void release_blkdev_list(void *dev) +-{ +- up(&block_subsys_sem); +- kfree(dev); ++ return major % BLKDEV_MAJOR_HASH_SIZE; + } + ++#ifdef CONFIG_PROC_FS + +-/* +- * Count the number of records in the blkdev_list. +- * must be called with the block_subsys_sem held +- */ +-int count_blkdev_list(void) ++void blkdev_show(struct seq_file *f, off_t offset) + { +- struct blk_major_name *n; +- int i, count; +- +- count = 0; ++ struct blk_major_name *dp; + +- for (i = 0; i < ARRAY_SIZE(major_names); i++) { +- for (n = major_names[i]; n; n = n->next) +- count++; ++ if (offset < BLKDEV_MAJOR_HASH_SIZE) { ++ down(&block_subsys_sem); ++ for (dp = major_names[offset]; dp; dp = dp->next) ++ seq_printf(f, "%3d %s\n", dp->major, dp->name); ++ up(&block_subsys_sem); + } +- +- return count; +-} +- +-/* +- * extract the major and name values from a blkdev_info struct +- * passed in as a void to *dev. Must be called with +- * block_subsys_sem held +- */ +-int get_blkdev_info(void *dev, int *major, char **name) +-{ +- struct blkdev_info *info = dev; +- +- if (info->bd == NULL) +- return 1; +- +- *major = info->bd->major; +- *name = info->bd->name; +- return 0; + } + ++#endif /* CONFIG_PROC_FS */ + + int register_blkdev(unsigned int major, const char *name) + { +--- linux-2.6.16.11.orig/fs/char_dev.c ++++ linux-2.6.16.11/fs/char_dev.c +@@ -15,6 +15,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -26,8 +27,6 @@ + + static struct kobj_map *cdev_map; + +-#define MAX_PROBE_HASH 255 /* random */ +- + static DECLARE_MUTEX(chrdevs_lock); + + static struct char_device_struct { +@@ -38,93 +37,29 @@ static struct char_device_struct { + char name[64]; + struct file_operations *fops; + struct cdev *cdev; /* will die */ +-} *chrdevs[MAX_PROBE_HASH]; ++} *chrdevs[CHRDEV_MAJOR_HASH_SIZE]; + + /* index in the above */ + static inline int major_to_index(int major) + { +- return major % MAX_PROBE_HASH; +-} +- +-struct chrdev_info { +- int index; +- struct char_device_struct *cd; +-}; +- +-void *get_next_chrdev(void *dev) +-{ +- struct chrdev_info *info; +- +- if (dev == NULL) { +- info = kmalloc(sizeof(*info), GFP_KERNEL); +- if (!info) +- goto out; +- info->index=0; +- info->cd = chrdevs[info->index]; +- if (info->cd) +- goto out; +- } else { +- info = dev; +- } +- +- while (info->index < ARRAY_SIZE(chrdevs)) { +- if (info->cd) +- info->cd = info->cd->next; +- if (info->cd) +- goto out; +- /* +- * No devices on this chain, move to the next +- */ +- info->index++; +- info->cd = (info->index < ARRAY_SIZE(chrdevs)) ? +- chrdevs[info->index] : NULL; +- if (info->cd) +- goto out; +- } +- +-out: +- return info; +-} +- +-void *acquire_chrdev_list(void) +-{ +- down(&chrdevs_lock); +- return get_next_chrdev(NULL); +-} +- +-void release_chrdev_list(void *dev) +-{ +- up(&chrdevs_lock); +- kfree(dev); ++ return major % CHRDEV_MAJOR_HASH_SIZE; + } + ++#ifdef CONFIG_PROC_FS + +-int count_chrdev_list(void) ++void chrdev_show(struct seq_file *f, off_t offset) + { + struct char_device_struct *cd; +- int i, count; +- +- count = 0; + +- for (i = 0; i < ARRAY_SIZE(chrdevs) ; i++) { +- for (cd = chrdevs[i]; cd; cd = cd->next) +- count++; ++ if (offset < CHRDEV_MAJOR_HASH_SIZE) { ++ down(&chrdevs_lock); ++ for (cd = chrdevs[offset]; cd; cd = cd->next) ++ seq_printf(f, "%3d %s\n", cd->major, cd->name); ++ up(&chrdevs_lock); + } +- +- return count; + } + +-int get_chrdev_info(void *dev, int *major, char **name) +-{ +- struct chrdev_info *info = dev; +- +- if (info->cd == NULL) +- return 1; +- +- *major = info->cd->major; +- *name = info->cd->name; +- return 0; +-} ++#endif /* CONFIG_PROC_FS */ + + /* + * Register a single major with a specified minor range. +--- linux-2.6.16.11.orig/fs/proc/proc_misc.c ++++ linux-2.6.16.11/fs/proc/proc_misc.c +@@ -249,144 +249,60 @@ static int cpuinfo_open(struct inode *in + return seq_open(file, &cpuinfo_op); + } + +-enum devinfo_states { +- CHR_HDR, +- CHR_LIST, +- BLK_HDR, +- BLK_LIST, +- DEVINFO_DONE +-}; +- +-struct devinfo_state { +- void *chrdev; +- void *blkdev; +- unsigned int num_records; +- unsigned int cur_record; +- enum devinfo_states state; ++static struct file_operations proc_cpuinfo_operations = { ++ .open = cpuinfo_open, ++ .read = seq_read, ++ .llseek = seq_lseek, ++ .release = seq_release, + }; + +-static void *devinfo_start(struct seq_file *f, loff_t *pos) ++static int devinfo_show(struct seq_file *f, void *v) + { +- struct devinfo_state *info = f->private; ++ int i = *(loff_t *) v; + +- if (*pos) { +- if ((info) && (*pos <= info->num_records)) +- return info; +- return NULL; ++ if (i < CHRDEV_MAJOR_HASH_SIZE) { ++ if (i == 0) ++ seq_printf(f, "Character devices:\n"); ++ chrdev_show(f, i); ++ } else { ++ i -= CHRDEV_MAJOR_HASH_SIZE; ++ if (i == 0) ++ seq_printf(f, "\nBlock devices:\n"); ++ blkdev_show(f, i); + } +- info = kmalloc(sizeof(*info), GFP_KERNEL); +- f->private = info; +- info->chrdev = acquire_chrdev_list(); +- info->blkdev = acquire_blkdev_list(); +- info->state = CHR_HDR; +- info->num_records = count_chrdev_list(); +- info->num_records += count_blkdev_list(); +- info->num_records += 2; /* Character and Block headers */ +- *pos = 1; +- info->cur_record = *pos; +- return info; ++ return 0; + } + +-static void *devinfo_next(struct seq_file *f, void *v, loff_t *pos) ++static void *devinfo_start(struct seq_file *f, loff_t *pos) + { +- int idummy; +- char *ndummy; +- struct devinfo_state *info = f->private; +- +- switch (info->state) { +- case CHR_HDR: +- info->state = CHR_LIST; +- (*pos)++; +- /*fallthrough*/ +- case CHR_LIST: +- if (get_chrdev_info(info->chrdev,&idummy,&ndummy)) { +- /* +- * The character dev list is complete +- */ +- info->state = BLK_HDR; +- } else { +- info->chrdev = get_next_chrdev(info->chrdev); +- } +- (*pos)++; +- break; +- case BLK_HDR: +- info->state = BLK_LIST; +- (*pos)++; +- /*fallthrough*/ +- case BLK_LIST: +- if (get_blkdev_info(info->blkdev,&idummy,&ndummy)) { +- /* +- * The block dev list is complete +- */ +- info->state = DEVINFO_DONE; +- } else { +- info->blkdev = get_next_blkdev(info->blkdev); +- } +- (*pos)++; +- break; +- case DEVINFO_DONE: +- (*pos)++; +- info->cur_record = *pos; +- info = NULL; +- break; +- default: +- break; +- } +- if (info) +- info->cur_record = *pos; +- return info; ++ if (*pos < (BLKDEV_MAJOR_HASH_SIZE + CHRDEV_MAJOR_HASH_SIZE)) ++ return pos; ++ return NULL; + } + +-static void devinfo_stop(struct seq_file *f, void *v) ++static void *devinfo_next(struct seq_file *f, void *v, loff_t *pos) + { +- struct devinfo_state *info = f->private; +- +- if (info) { +- release_chrdev_list(info->chrdev); +- release_blkdev_list(info->blkdev); +- f->private = NULL; +- kfree(info); +- } ++ (*pos)++; ++ if (*pos >= (BLKDEV_MAJOR_HASH_SIZE + CHRDEV_MAJOR_HASH_SIZE)) ++ return NULL; ++ return pos; + } + +-static int devinfo_show(struct seq_file *f, void *arg) ++static void devinfo_stop(struct seq_file *f, void *v) + { +- int major; +- char *name; +- struct devinfo_state *info = f->private; +- +- switch(info->state) { +- case CHR_HDR: +- seq_printf(f,"Character devices:\n"); +- /* fallthrough */ +- case CHR_LIST: +- if (!get_chrdev_info(info->chrdev,&major,&name)) +- seq_printf(f,"%3d %s\n",major,name); +- break; +- case BLK_HDR: +- seq_printf(f,"\nBlock devices:\n"); +- /* fallthrough */ +- case BLK_LIST: +- if (!get_blkdev_info(info->blkdev,&major,&name)) +- seq_printf(f,"%3d %s\n",major,name); +- break; +- default: +- break; +- } +- +- return 0; ++ /* Nothing to do */ + } + +-static struct seq_operations devinfo_op = { +- .start = devinfo_start, +- .next = devinfo_next, +- .stop = devinfo_stop, +- .show = devinfo_show, ++static struct seq_operations devinfo_ops = { ++ .start = devinfo_start, ++ .next = devinfo_next, ++ .stop = devinfo_stop, ++ .show = devinfo_show + }; + +-static int devinfo_open(struct inode *inode, struct file *file) ++static int devinfo_open(struct inode *inode, struct file *filp) + { +- return seq_open(file, &devinfo_op); ++ return seq_open(filp, &devinfo_ops); + } + + static struct file_operations proc_devinfo_operations = { +@@ -396,13 +312,6 @@ static struct file_operations proc_devin + .release = seq_release, + }; + +-static struct file_operations proc_cpuinfo_operations = { +- .open = cpuinfo_open, +- .read = seq_read, +- .llseek = seq_lseek, +- .release = seq_release, +-}; +- + extern struct seq_operations vmstat_op; + static int vmstat_open(struct inode *inode, struct file *file) + { +--- linux-2.6.16.11.orig/include/linux/fs.h ++++ linux-2.6.16.11/include/linux/fs.h +@@ -1383,6 +1383,7 @@ extern int bd_claim(struct block_device + extern void bd_release(struct block_device *); + + /* fs/char_dev.c */ ++#define CHRDEV_MAJOR_HASH_SIZE 255 + extern int alloc_chrdev_region(dev_t *, unsigned, unsigned, const char *); + extern int register_chrdev_region(dev_t, unsigned, const char *); + extern int register_chrdev(unsigned int, const char *, +@@ -1390,25 +1391,17 @@ extern int register_chrdev(unsigned int, + extern int unregister_chrdev(unsigned int, const char *); + extern void unregister_chrdev_region(dev_t, unsigned); + extern int chrdev_open(struct inode *, struct file *); +-extern int get_chrdev_list(char *); +-extern void *acquire_chrdev_list(void); +-extern int count_chrdev_list(void); +-extern void *get_next_chrdev(void *); +-extern int get_chrdev_info(void *, int *, char **); +-extern void release_chrdev_list(void *); ++extern void chrdev_show(struct seq_file *,off_t); + + /* fs/block_dev.c */ ++#define BLKDEV_MAJOR_HASH_SIZE 255 + #define BDEVNAME_SIZE 32 /* Largest string for a blockdev identifier */ + extern const char *__bdevname(dev_t, char *buffer); + extern const char *bdevname(struct block_device *bdev, char *buffer); + extern struct block_device *lookup_bdev(const char *); + extern struct block_device *open_bdev_excl(const char *, int, void *); + extern void close_bdev_excl(struct block_device *); +-extern void *acquire_blkdev_list(void); +-extern int count_blkdev_list(void); +-extern void *get_next_blkdev(void *); +-extern int get_blkdev_info(void *, int *, char **); +-extern void release_blkdev_list(void *); ++extern void blkdev_show(struct seq_file *,off_t); + + extern void init_special_inode(struct inode *, umode_t, dev_t); + diff --git a/queue-2.6.16/tipar-oops-fix.patch b/queue-2.6.16/tipar-oops-fix.patch new file mode 100644 index 00000000000..ec5dac25317 --- /dev/null +++ b/queue-2.6.16/tipar-oops-fix.patch @@ -0,0 +1,36 @@ +From stable-bounces@linux.kernel.org Sun Apr 23 15:45:53 2006 +Message-Id: <200604232245.k3NMj7Zw000433@shell0.pdx.osdl.net> +To: dsd@gentoo.org, stable@kernel.org, mm-commits@vger.kernel.org +From: akpm@osdl.org +Date: Sun, 23 Apr 2006 15:43:59 -0700 +Cc: +Subject: tipar oops fix + +From: Daniel Drake + +If compiled into the kernel, parport_register_driver() is called before the +parport driver has been initalised. + +This means that it is expected that tp_count is 0 after the +parport_register_driver() call() - tipar's attach function will not be +called until later during bootup. + +Signed-off-by: Daniel Drake +Signed-off-by: Andrew Morton +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/char/tipar.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- linux-2.6.16.11.orig/drivers/char/tipar.c ++++ linux-2.6.16.11/drivers/char/tipar.c +@@ -515,7 +515,7 @@ tipar_init_module(void) + err = PTR_ERR(tipar_class); + goto out_chrdev; + } +- if (parport_register_driver(&tipar_driver) || tp_count == 0) { ++ if (parport_register_driver(&tipar_driver)) { + printk(KERN_ERR "tipar: unable to register with parport\n"); + err = -EIO; + goto out_class; diff --git a/queue-2.6.16/usb-fix-array-overrun-in-drivers-usb-serial-option.c.patch b/queue-2.6.16/usb-fix-array-overrun-in-drivers-usb-serial-option.c.patch new file mode 100644 index 00000000000..87a3e97ba22 --- /dev/null +++ b/queue-2.6.16/usb-fix-array-overrun-in-drivers-usb-serial-option.c.patch @@ -0,0 +1,44 @@ +From stable-bounces@linux.kernel.org Sun Apr 23 13:52:57 2006 +Date: Sun, 23 Apr 2006 22:52:28 +0200 +From: Adrian Bunk +To: stable@kernel.org +Message-ID: <20060423205228.GC13666@stusta.de> +Content-Disposition: inline +Cc: Eric Sesterhenn , smurf@smurf.noris.de +Subject: USB: fix array overrun in drivers/usb/serial/option.c + +From: Eric Sesterhenn + +since the arrays are declared as in_urbs[N_IN_URB] +and out_urbs[N_OUT_URB] both for loops, go one +over the end of the array. This fixes coverity id #555 + +This patch was already included in Linus' tree. + +Signed-off-by: Eric Sesterhenn +Signed-off-by: Adrian Bunk +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/serial/option.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- linux-2.6.16.11.orig/drivers/usb/serial/option.c ++++ linux-2.6.16.11/drivers/usb/serial/option.c +@@ -582,14 +582,14 @@ static void option_setup_urbs(struct usb + portdata = usb_get_serial_port_data(port); + + /* Do indat endpoints first */ +- for (j = 0; j <= N_IN_URB; ++j) { ++ for (j = 0; j < N_IN_URB; ++j) { + portdata->in_urbs[j] = option_setup_urb (serial, + port->bulk_in_endpointAddress, USB_DIR_IN, port, + portdata->in_buffer[j], IN_BUFLEN, option_indat_callback); + } + + /* outdat endpoints */ +- for (j = 0; j <= N_OUT_URB; ++j) { ++ for (j = 0; j < N_OUT_URB; ++j) { + portdata->out_urbs[j] = option_setup_urb (serial, + port->bulk_out_endpointAddress, USB_DIR_OUT, port, + portdata->out_buffer[j], OUT_BUFLEN, option_outdat_callback); diff --git a/queue-2.6.16/x86_64-fix-a-race-in-the-free_iommu-path.patch b/queue-2.6.16/x86_64-fix-a-race-in-the-free_iommu-path.patch new file mode 100644 index 00000000000..b94c84e37ea --- /dev/null +++ b/queue-2.6.16/x86_64-fix-a-race-in-the-free_iommu-path.patch @@ -0,0 +1,43 @@ +From stable-bounces@linux.kernel.org Fri Apr 21 00:43:54 2006 +Date: Fri, 21 Apr 2006 09:43:25 +0200 +From: "Andi Kleen" +To: stable@kernel.org +Message-ID: <44488D1D.mailLI911H6K7@suse.de> +Cc: mikew@google.com +Subject: x86_64: Fix a race in the free_iommu path. + + +From: Mike Waychison + +We do this by removing a micro-optimization that tries to avoid grabbing +the iommu_bitmap_lock spinlock and using a bus-locked operation. + +This still races with other simultaneous alloc_iommu or free_iommu(size +> 1) which both use bus-unlocked operations. + +The end result of this race is eventually ending +up with an iommu_gart_bitmap that has bits errornously set all over, +making large contiguous iommu space allocations fail with 'PCI-DMA: +Out of IOMMU space'. + +Signed-off-by: Mike Waychison +Signed-off-by: Andi Kleen +Signed-off-by: Greg Kroah-Hartman + +--- + arch/x86_64/kernel/pci-gart.c | 4 ---- + 1 file changed, 4 deletions(-) + +--- linux-2.6.16.11.orig/arch/x86_64/kernel/pci-gart.c ++++ linux-2.6.16.11/arch/x86_64/kernel/pci-gart.c +@@ -114,10 +114,6 @@ static unsigned long alloc_iommu(int siz + static void free_iommu(unsigned long offset, int size) + { + unsigned long flags; +- if (size == 1) { +- clear_bit(offset, iommu_gart_bitmap); +- return; +- } + spin_lock_irqsave(&iommu_bitmap_lock, flags); + __clear_bit_string(iommu_gart_bitmap, offset, size); + spin_unlock_irqrestore(&iommu_bitmap_lock, flags); diff --git a/queue-2.6.16/x86_64-pass-32-to-the-assembler-when-compiling-the-32bit-vsyscall-pages.patch b/queue-2.6.16/x86_64-pass-32-to-the-assembler-when-compiling-the-32bit-vsyscall-pages.patch new file mode 100644 index 00000000000..1de7214b38e --- /dev/null +++ b/queue-2.6.16/x86_64-pass-32-to-the-assembler-when-compiling-the-32bit-vsyscall-pages.patch @@ -0,0 +1,38 @@ +From stable-bounces@linux.kernel.org Fri Apr 21 00:43:54 2006 +Date: Fri, 21 Apr 2006 09:43:22 +0200 +From: "Andi Kleen" +To: stable@kernel.org +Message-ID: <44488D1A.mailLI211XJT4@suse.de> +Cc: brian.b@hp.com +Subject: x86_64: Pass -32 to the assembler when compiling the 32bit vsyscall pages + + +This quietens warnings and actually fixes a bug. The unwind tables would +come out wrong without -32, causing pthread cancellation during them +to crash in the gcc runtime. + +The problem seems to only happen with newer binutils +(it doesn't happen with 2.16.91.0.2 but happens wit 2.16.91.0.5) + +Thanks to Brian Baker @ HP for test case and initial analysis. + +Cc: brian.b@hp.com + +Signed-off-by: Andi Kleen +Signed-off-by: Greg Kroah-Hartman + + +--- + arch/x86_64/ia32/Makefile | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- linux-2.6.16.11.orig/arch/x86_64/ia32/Makefile ++++ linux-2.6.16.11/arch/x86_64/ia32/Makefile +@@ -27,5 +27,5 @@ $(obj)/vsyscall-sysenter.so $(obj)/vsysc + $(obj)/vsyscall-%.so: $(src)/vsyscall.lds $(obj)/vsyscall-%.o FORCE + $(call if_changed,syscall) + +-AFLAGS_vsyscall-sysenter.o = -m32 +-AFLAGS_vsyscall-syscall.o = -m32 ++AFLAGS_vsyscall-sysenter.o = -m32 -Wa,-32 ++AFLAGS_vsyscall-syscall.o = -m32 -Wa,-32