Skip to contentSkip to conversation

4 -stable kernel review cycles starting

PATCH New Greg KH 22 participants 658 messages Jul 1, 2010 – Sep 24, 2010 Page 3 of 4

Subsystems (87)
lore
Share & tools
lore
#360 lore raw

Re: [patch 134/149] x86, paravirt: Add a global synchronization point for pvclock

In reply to Avi Kivity

Sorry for the delay.

Quoted 3 lines · Avi Kivity

I'm unable to reproduce.

Can you provide the stack trace where this hangs?

Here goes:

| (gdb) target remote :1234
| Remote debugging using :1234
| [New Thread 1]
| 0xffffffff81702314 in _spin_lock (lock=0xffffffff81ab9e30)
|     at /scratch/kernel/2.6.32.16/arch/x86/include/asm/spinlock.h:65
| 65      /scratch/kernel/2.6.32.16/arch/x86/include/asm/spinlock.h: No such file or directory.
|         in /scratch/kernel/2.6.32.16/arch/x86/include/asm/spinlock.h
| (gdb) bt
| #0  0xffffffff81702314 in _spin_lock (lock=0xffffffff81ab9e30)
|     at /scratch/kernel/2.6.32.16/arch/x86/include/asm/spinlock.h:65
| #1  0xffffffff8107b214 in vprintk (
|     fmt=0xffffffff818a3ee8 "<1>BUG: unable to handle kernel ", 
|     args=0xffff88001f8f2c38) at kernel/printk.c:705
| #2  0xffffffff816ff387 in printk (fmt=0xffffffff81ab9e30 "")
|     at kernel/printk.c:595
| #3  0xffffffff8105b94a in no_context (regs=0xffff88001f8f2e98, error_code=3, 
|     address=18446744071586262656) at arch/x86/mm/fault.c:583
| #4  0xffffffff8105bb65 in __bad_area_nosemaphore (regs=0xffff88001f8f2e98, 
|     error_code=3, address=18446744071586262656, si_code=196609)
|     at arch/x86/mm/fault.c:741
| #5  0xffffffff8105bc4e in bad_area_nosemaphore (regs=0xffffffff81ab9e30, 
|     error_code=18446612132843695160, address=4294892530)
|     at arch/x86/mm/fault.c:748
| #6  0xffffffff8105c02f in do_page_fault (regs=0xffff88001f8f2e98, error_code=3)
|     at arch/x86/mm/fault.c:1061
| #7  0xffffffff81702765 in page_fault ()
| #8  0x000d3496569e13a8 in ?? ()
| #9  0x00000000b4b2c8e7 in ?? ()
| #10 0x00000003ede5a5a5 in ?? ()
| #11 0x0000000000000001 in per_cpu__irq_stack_union ()
| #12 0xffff880001c11e80 in ?? ()
| ---Type <return> to continue, or q <return> to quit---
| #13 0x0000000000000000 in ?? ()
| (gdb) 
| (gdb) 
| (gdb) 
| (gdb) bt full
| #0  0xffffffff81702314 in _spin_lock (lock=0xffffffff81ab9e30)
|     at /scratch/kernel/2.6.32.16/arch/x86/include/asm/spinlock.h:65
| No locals.
| #1  0xffffffff8107b214 in vprintk (
|     fmt=0xffffffff818a3ee8 "<1>BUG: unable to handle kernel ", 
|     args=0xffff88001f8f2c38) at kernel/printk.c:705
|         printed_len = 0
|         current_log_level = 4
|         flags = 70
|         p = <value optimized out>
| #2  0xffffffff816ff387 in printk (fmt=0xffffffff81ab9e30 "")
|     at kernel/printk.c:595
|         args = {{gp_offset = 8, fp_offset = 48, 
|     overflow_arg_area = 0xffff88001f8f2d18, 
|     reg_save_area = 0xffff88001f8f2c58}}
|         r = 256
| #3  0xffffffff8105b94a in no_context (regs=0xffff88001f8f2e98, error_code=3, 
|     address=18446744071586262656) at arch/x86/mm/fault.c:583
|         tsk = (struct task_struct *) 0xffff88001f908000
|         flags = 146
|         sig = <value optimized out>
| #4  0xffffffff8105bb65 in __bad_area_nosemaphore (regs=0xffff88001f8f2e98, 
|     error_code=3, address=18446744071586262656, si_code=196609)
| ---Type <return> to continue, or q <return> to quit---
|     at arch/x86/mm/fault.c:741
|         tsk = (struct task_struct *) 0xffff88001f908000
| #5  0xffffffff8105bc4e in bad_area_nosemaphore (regs=0xffffffff81ab9e30, 
|     error_code=18446612132843695160, address=4294892530)
|     at arch/x86/mm/fault.c:748
| No locals.
| #6  0xffffffff8105c02f in do_page_fault (regs=0xffff88001f8f2e98, error_code=3)
|     at arch/x86/mm/fault.c:1061
|         vma = <value optimized out>
|         tsk = (struct task_struct *) 0xffff88001f908000
|         address = 18446744071586262656
|         mm = (struct mm_struct *) 0x0
|         write = <value optimized out>
|         fault = 256
| #7  0xffffffff81702765 in page_fault ()
| No symbol table info available.
| #8  0x000d3496569e13a8 in ?? ()
| No symbol table info available.
| #9  0x00000000b4b2c8e7 in ?? ()
| No symbol table info available.
| #10 0x00000003ede5a5a5 in ?? ()
| No symbol table info available.
| #11 0x0000000000000001 in per_cpu__irq_stack_union ()
| ---Type <return> to continue, or q <return> to quit---
| No symbol table info available.
| #12 0xffff880001c11e80 in ?? ()
| No symbol table info available.
| #13 0x0000000000000000 in ?? ()
| No symbol table info available.
| (gdb) quit

So, I disabled PRINTK_TIME and tried again. This time I got:

VFS: Mounted root (ext3 filesystem) readonly on device 253:0. Freeing unused kernel memory: 632k freed
Write protecting the kernel read-only data: 9492k

BUG: unable to handle kernel paging request at ffffffff81712e80
IP: [<ffffffff81054f73>] pvclock_clocksource_read+0x83/0xc0
PGD 1003067 PUD 1007063 PMD 7e8b1063 PTE 8000000001712161
Oops: 0003 [#1] SMP 
last sysfs file: 
CPU 0 
Pid: 1, comm: swapper Not tainted 2.6.32.16-dsa-amd64 #2 
RIP: 0010:[<ffffffff81054f73>]  [<ffffffff81054f73>] pvclock_clocksource_read+0x83/0xc0
RSP: 0018:ffff88007fb47880  EFLAGS: 00010283
RAX: 000d362a57085b85 RBX: ffff880001c11e80 RCX: 000d362a573c6400
RDX: 000d362a57085b85 RSI: 000000000001c410 RDI: ffff880001c11e80
RBP: ffff88007fb478c0 R08: 000000000001a9f2 R09: 6db6db6db6db6db7
R10: ffff88007f15a0a0 R11: ffff88007f15a040 R12: 0000000000000001
R13: 0000001112bb6a47 R14: 00000000b4b2c8e7 R15: 000d362a573c2e34
FS:  0000000000000000(0000) GS:ffff880001c00000(0000) knlGS:0000000000000000
CS:  0010 DS: 0018 ES: 0018 CR0: 000000008005003b
CR2: ffffffff81712e80 CR3: 0000000001001000 CR4: 00000000000006f0
DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400
Process swapper (pid: 1, threadinfo ffff88007fb46000, task ffff88007fb50000)
Stack:
 ffff88007fb47900 ffffffff0001a9f2 ffff88007e884150 ffffffff81975c00
<0> 00000000000001b6 ffffffffb3c3c368 ffff88007fb29078 0000000000000000
<0> ffff88007fb478d0 ffffffff8105423c ffff88007fb478e0 ffffffff81054249
Call Trace:
 [<ffffffff8105423c>] kvm_clock_read+0x1c/0x20
 [<ffffffff81054249>] kvm_clock_get_cycles+0x9/0x10
 [<ffffffff81099101>] ktime_get_ts+0x71/0xe0
 [<ffffffff810add4d>] __delayacct_blkio_start+0x1d/0x20
 [<ffffffff8170032a>] io_schedule+0x5a/0xd0
 [<ffffffff81117bdd>] sync_buffer+0x3d/0x50
 [<ffffffff817008ca>] __wait_on_bit+0x5a/0x90
 [<ffffffff81117ba0>] ? sync_buffer+0x0/0x50
 [<ffffffff81117ba0>] ? sync_buffer+0x0/0x50
 [<ffffffff81700974>] out_of_line_wait_on_bit+0x74/0x90
 [<ffffffff81090b30>] ? wake_bit_function+0x0/0x40
 [<ffffffff81117b46>] __wait_on_buffer+0x26/0x30
 [<ffffffff8116331d>] ext3_find_entry+0x19d/0x6b0
 [<ffffffff81060e90>] ? do_flush_tlb_all+0x0/0x70
 [<ffffffff8116418d>] ext3_lookup+0x4d/0x130
 [<ffffffff81105203>] ? d_alloc+0x123/0x1b0
 [<ffffffff810f9fe6>] do_lookup+0x206/0x260
 [<ffffffff810fbe6b>] __link_path_walk+0x19b/0x1000
 [<ffffffff81060eb8>] ? do_flush_tlb_all+0x28/0x70
 [<ffffffff8107fece>] ? on_each_cpu+0x2e/0x50
 [<ffffffff810fcf5e>] path_walk+0x6e/0xe0
 [<ffffffff810fd0eb>] do_path_lookup+0x5b/0x60
 [<ffffffff810fe015>] do_filp_open+0xf5/0xb10
 [<ffffffff810a4026>] ? smp_call_function_many+0x1e6/0x230
 [<ffffffff8105cad0>] ? __cpa_flush_range+0x0/0x30
 [<ffffffff8105caf5>] ? __cpa_flush_range+0x25/0x30
 [<ffffffff8105db73>] ? change_page_attr_set_clr+0x273/0x410
 [<ffffffff81108a5a>] ? alloc_fd+0x4a/0x140
 [<ffffffff810eed7f>] do_sys_open+0x7f/0x140
 [<ffffffff810eee6b>] sys_open+0x1b/0x20
 [<ffffffff810091ef>] init_post+0x3f/0x1b0
 [<ffffffff81a106e5>] kernel_init+0x1a2/0x1ba
 [<ffffffff810373ca>] child_rip+0xa/0x20
 [<ffffffff81a10543>] ? kernel_init+0x0/0x1ba
 [<ffffffff810373c0>] ? child_rip+0x0/0x20
Code: 78 4f 44 89 e1 48 d3 e0 44 89 f2 48 f7 e2 48 0f ac d0 20 4a 8d 0c 38 44 39 03 75 a4 48 8b 15 15 df 6b 00 48 39 ca 77 17 48 89 d0 <f0> 48 0f b1 0d 04 df 6b 00 48 39 c1 48 89 c2 75 e7 48 89 ca 48 
RIP  [<ffffffff81054f73>] pvclock_clocksource_read+0x83/0xc0
 RSP <ffff88007fb47880>
CR2: ffffffff81712e80
---[ end trace 38f25e02ae34d4c1 ]---
BUG: unable to handle kernel paging request at ffffffff81712e80
IP: [<ffffffff81054f73>] pvclock_clocksource_read+0x83/0xc0
PGD 1003067 PUD 1007063 PMD 7e8b1063 PTE 8000000001712161
Oops: 0003 [#2] SMP 
last sysfs file: 
CPU 0 
Pid: 1, comm: swapper Tainted: G      D    2.6.32.16-dsa-amd64 #2 
RIP: 0010:[<ffffffff81054f73>]  [<ffffffff81054f73>] pvclock_clocksource_read+0x83/0xc0
RSP: 0018:ffff880001c03e78  EFLAGS: 00010097
RAX: 000d362a57085b85 RBX: ffff880001c11e80 RCX: 000d362a5b7e8c49
RDX: 000d362a57085b85 RSI: 0000000000000000 RDI: ffff880001c11e80
RBP: ffff880001c03eb8 R08: 000000000001e50c R09: 0000000000000001
R10: ffffffff81ac2360 R11: 0000000000000021 R12: 0000000000000001
R13: 000000111eca7f9f R14: 00000000b4b2c8e7 R15: 000d362a5b7dc64c
FS:  0000000000000000(0000) GS:ffff880001c00000(0000) knlGS:0000000000000000
CS:  0010 DS: 0018 ES: 0018 CR0: 000000008005003b
CR2: ffffffff81712e80 CR3: 0000000001001000 CR4: 00000000000006f0
DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400
Process swapper (pid: 1, threadinfo ffff88007fb46000, task ffff88007fb50000)
Stack:
 0000000000000282 000000000001e50c 0000000000000001 ffffffff81975c00
<0> 0000000000000000 0000000023493c1b 00000000000001b6 0000000000000000
<0> ffff880001c03ec8 ffffffff8105423c ffff880001c03ed8 ffffffff81054249
Call Trace:
 <IRQ> 
 [<ffffffff8105423c>] kvm_clock_read+0x1c/0x20
 [<ffffffff81054249>] kvm_clock_get_cycles+0x9/0x10
 [<ffffffff810991da>] ktime_get+0x6a/0xf0
 [<ffffffff81093cd4>] hrtimer_interrupt+0x54/0x1f0
 [<ffffffff810374cc>] ? call_softirq+0x1c/0x30
 [<ffffffff8104e138>] smp_apic_timer_interrupt+0x68/0xa0
 [<ffffffff81036eb3>] apic_timer_interrupt+0x13/0x20
 <EOI> 
 [<ffffffff810a5bb4>] ? acct_collect+0x164/0x1b0
 [<ffffffff810a5af5>] ? acct_collect+0xa5/0x1b0
 [<ffffffff8107e5bc>] ? do_exit+0x6ec/0x7a0
 [<ffffffff8103a943>] ? oops_end+0xa3/0xb0
 [<ffffffff8105b8a8>] ? no_context+0xe8/0x260
 [<ffffffff810c442d>] ? zone_statistics+0x7d/0xa0
 [<ffffffff8105bb65>] ? __bad_area_nosemaphore+0x145/0x220
 [<ffffffff810b2a01>] ? mempool_alloc_slab+0x11/0x20
 [<ffffffff810b2b30>] ? mempool_alloc+0x60/0x130
 [<ffffffff8105bc4e>] ? bad_area_nosemaphore+0xe/0x10
 [<ffffffff8105c02f>] ? do_page_fault+0x1cf/0x280
 [<ffffffff81702765>] ? page_fault+0x25/0x30
 [<ffffffff81054f73>] ? pvclock_clocksource_read+0x83/0xc0
 [<ffffffff8105423c>] ? kvm_clock_read+0x1c/0x20
 [<ffffffff81054249>] ? kvm_clock_get_cycles+0x9/0x10
 [<ffffffff81099101>] ? ktime_get_ts+0x71/0xe0
 [<ffffffff810add4d>] ? __delayacct_blkio_start+0x1d/0x20
 [<ffffffff8170032a>] ? io_schedule+0x5a/0xd0
 [<ffffffff81117bdd>] ? sync_buffer+0x3d/0x50
 [<ffffffff817008ca>] ? __wait_on_bit+0x5a/0x90
 [<ffffffff81117ba0>] ? sync_buffer+0x0/0x50
 [<ffffffff81117ba0>] ? sync_buffer+0x0/0x50
 [<ffffffff81700974>] ? out_of_line_wait_on_bit+0x74/0x90
 [<ffffffff81090b30>] ? wake_bit_function+0x0/0x40
 [<ffffffff81117b46>] ? __wait_on_buffer+0x26/0x30
 [<ffffffff8116331d>] ? ext3_find_entry+0x19d/0x6b0
 [<ffffffff81060e90>] ? do_flush_tlb_all+0x0/0x70
 [<ffffffff8116418d>] ? ext3_lookup+0x4d/0x130
 [<ffffffff81105203>] ? d_alloc+0x123/0x1b0
 [<ffffffff810f9fe6>] ? do_lookup+0x206/0x260
 [<ffffffff810fbe6b>] ? __link_path_walk+0x19b/0x1000
 [<ffffffff81060eb8>] ? do_flush_tlb_all+0x28/0x70
 [<ffffffff8107fece>] ? on_each_cpu+0x2e/0x50
 [<ffffffff810fcf5e>] ? path_walk+0x6e/0xe0
 [<ffffffff810fd0eb>] ? do_path_lookup+0x5b/0x60
 [<ffffffff810fe015>] ? do_filp_open+0xf5/0xb10
 [<ffffffff810a4026>] ? smp_call_function_many+0x1e6/0x230
 [<ffffffff8105cad0>] ? __cpa_flush_range+0x0/0x30
 [<ffffffff8105caf5>] ? __cpa_flush_range+0x25/0x30
 [<ffffffff8105db73>] ? change_page_attr_set_clr+0x273/0x410
 [<ffffffff81108a5a>] ? alloc_fd+0x4a/0x140
 [<ffffffff810eed7f>] ? do_sys_open+0x7f/0x140
 [<ffffffff810eee6b>] ? sys_open+0x1b/0x20
 [<ffffffff810091ef>] ? init_post+0x3f/0x1b0
 [<ffffffff81a106e5>] ? kernel_init+0x1a2/0x1ba
 [<ffffffff810373ca>] ? child_rip+0xa/0x20
 [<ffffffff81a10543>] ? kernel_init+0x0/0x1ba
 [<ffffffff810373c0>] ? child_rip+0x0/0x20
Code: 78 4f 44 89 e1 48 d3 e0 44 89 f2 48 f7 e2 48 0f ac d0 20 4a 8d 0c 38 44 39 03 75 a4 48 8b 15 15 df 6b 00 48 39 ca 77 17 48 89 d0 <f0> 48 0f b1 0d 04 df 6b 00 48 39 c1 48 89 c2 75 e7 48 89 ca 48 
RIP  [<ffffffff81054f73>] pvclock_clocksource_read+0x83/0xc0
 RSP <ffff880001c03e78>
CR2: ffffffff81712e80
---[ end trace 38f25e02ae34d4c2 ]---
Kernel panic - not syncing: Fatal exception in interrupt
Pid: 1, comm: swapper Tainted: G      D    2.6.32.16-dsa-amd64 #2
Call Trace:
 <IRQ>  [<ffffffff816ff24f>] panic+0xa0/0x171
 [<ffffffff81095095>] ? up+0x35/0x50
 [<ffffffff8107ae7d>] ? release_console_sem+0x1cd/0x220
 [<ffffffff8107b155>] ? console_unblank+0x75/0x90
 [<ffffffff8103a93b>] oops_end+0x9b/0xb0
 [<ffffffff8105b8a8>] no_context+0xe8/0x260
 [<ffffffff8105bb65>] __bad_area_nosemaphore+0x145/0x220
 [<ffffffff810b2a22>] ? mempool_free_slab+0x12/0x20
 [<ffffffff810b2aba>] ? mempool_free+0x8a/0xa0
 [<ffffffff813ec9cb>] ? mix_pool_bytes_extract+0x14b/0x160
 [<ffffffff8105bc4e>] bad_area_nosemaphore+0xe/0x10
 [<ffffffff8105c02f>] do_page_fault+0x1cf/0x280
 [<ffffffff81702765>] page_fault+0x25/0x30
 [<ffffffff81054f73>] ? pvclock_clocksource_read+0x83/0xc0
 [<ffffffff81054f3e>] ? pvclock_clocksource_read+0x4e/0xc0
 [<ffffffff8105423c>] kvm_clock_read+0x1c/0x20
 [<ffffffff81054249>] kvm_clock_get_cycles+0x9/0x10
 [<ffffffff810991da>] ktime_get+0x6a/0xf0
 [<ffffffff81093cd4>] hrtimer_interrupt+0x54/0x1f0
 [<ffffffff810374cc>] ? call_softirq+0x1c/0x30
 [<ffffffff8104e138>] smp_apic_timer_interrupt+0x68/0xa0
 [<ffffffff81036eb3>] apic_timer_interrupt+0x13/0x20
 <EOI>  [<ffffffff810a5bb4>] ? acct_collect+0x164/0x1b0
 [<ffffffff810a5af5>] ? acct_collect+0xa5/0x1b0
 [<ffffffff8107e5bc>] ? do_exit+0x6ec/0x7a0
 [<ffffffff8103a943>] ? oops_end+0xa3/0xb0
 [<ffffffff8105b8a8>] ? no_context+0xe8/0x260
 [<ffffffff810c442d>] ? zone_statistics+0x7d/0xa0
 [<ffffffff8105bb65>] ? __bad_area_nosemaphore+0x145/0x220
 [<ffffffff810b2a01>] ? mempool_alloc_slab+0x11/0x20
 [<ffffffff810b2b30>] ? mempool_alloc+0x60/0x130
 [<ffffffff8105bc4e>] ? bad_area_nosemaphore+0xe/0x10
 [<ffffffff8105c02f>] ? do_page_fault+0x1cf/0x280
 [<ffffffff81702765>] ? page_fault+0x25/0x30
 [<ffffffff81054f73>] ? pvclock_clocksource_read+0x83/0xc0
 [<ffffffff8105423c>] ? kvm_clock_read+0x1c/0x20
 [<ffffffff81054249>] ? kvm_clock_get_cycles+0x9/0x10
 [<ffffffff81099101>] ? ktime_get_ts+0x71/0xe0
 [<ffffffff810add4d>] ? __delayacct_blkio_start+0x1d/0x20
 [<ffffffff8170032a>] ? io_schedule+0x5a/0xd0
 [<ffffffff81117bdd>] ? sync_buffer+0x3d/0x50
 [<ffffffff817008ca>] ? __wait_on_bit+0x5a/0x90
 [<ffffffff81117ba0>] ? sync_buffer+0x0/0x50
 [<ffffffff81117ba0>] ? sync_buffer+0x0/0x50
 [<ffffffff81700974>] ? out_of_line_wait_on_bit+0x74/0x90
 [<ffffffff81090b30>] ? wake_bit_function+0x0/0x40
 [<ffffffff81117b46>] ? __wait_on_buffer+0x26/0x30
 [<ffffffff8116331d>] ? ext3_find_entry+0x19d/0x6b0
 [<ffffffff81060e90>] ? do_flush_tlb_all+0x0/0x70
 [<ffffffff8116418d>] ? ext3_lookup+0x4d/0x130
 [<ffffffff81105203>] ? d_alloc+0x123/0x1b0
 [<ffffffff810f9fe6>] ? do_lookup+0x206/0x260
 [<ffffffff810fbe6b>] ? __link_path_walk+0x19b/0x1000
 [<ffffffff81060eb8>] ? do_flush_tlb_all+0x28/0x70
 [<ffffffff8107fece>] ? on_each_cpu+0x2e/0x50
 [<ffffffff810fcf5e>] ? path_walk+0x6e/0xe0
 [<ffffffff810fd0eb>] ? do_path_lookup+0x5b/0x60
 [<ffffffff810fe015>] ? do_filp_open+0xf5/0xb10
 [<ffffffff810a4026>] ? smp_call_function_many+0x1e6/0x230
 [<ffffffff8105cad0>] ? __cpa_flush_range+0x0/0x30
 [<ffffffff8105caf5>] ? __cpa_flush_range+0x25/0x30
 [<ffffffff8105db73>] ? change_page_attr_set_clr+0x273/0x410
 [<ffffffff81108a5a>] ? alloc_fd+0x4a/0x140
 [<ffffffff810eed7f>] ? do_sys_open+0x7f/0x140
 [<ffffffff810eee6b>] ? sys_open+0x1b/0x20
 [<ffffffff810091ef>] ? init_post+0x3f/0x1b0
 [<ffffffff81a106e5>] ? kernel_init+0x1a2/0x1ba
 [<ffffffff810373ca>] ? child_rip+0xa/0x20
 [<ffffffff81a10543>] ? kernel_init+0x0/0x1ba
 [<ffffffff810373c0>] ? child_rip+0x0/0x20

[Also available at http://asteria.noreply.org/~weasel/volatile/2010-07-13-CQL4Lj0xCNo/typescript.zoe.kvmclock.panic ]

Signature · 4 lines
                           |  .''`.  ** Debian GNU/Linux **
      Peter Palfrader      | : :' :      The  universal
 http://www.palfrader.org/ | `. `'      Operating System
                           |   `-    http://www.debian.org/
#361 lore raw

Re: [patch 134/149] x86, paravirt: Add a global synchronization point for pvclock

Quoted 2 lines · Peter Palfrader

Sorry for the delay.

A good trace is worth it.

Quoted 10 lines

[<ffffffff810373c0>] ? child_rip+0x0/0x20

Code: 78 4f 44 89 e1 48 d3 e0 44 89 f2 48 f7 e2 48 0f ac d0 20 4a 8d 0c 38 44 39 03 75 a4 48 8b 15 15 df 6b 00 48 39 ca 77 17 48 89 d0<f0>  48 0f b1 0d 04 df 6b 00 48 39 c1 48 89 c2 75 e7 48 89 ca 48
RIP  [<ffffffff81054f73>] pvclock_clocksource_read+0x83/0xc0
  RSP<ffff88007fb47880>
CR2: ffffffff81712e80
---[ end trace 38f25e02ae34d4c1 ]---
BUG: unable to handle kernel paging request at ffffffff81712e80
IP: [<ffffffff81054f73>] pvclock_clocksource_read+0x83/0xc0

PGD 1003067 PUD 1007063 PMD 7e8b1063 PTE 8000000001712161

Read-only pte

Quoted 2 lines
Oops: 0003 [#2] SMP

Write fault.

Quoted 3 lines
Code: 78 4f 44 89 e1 48 d3 e0 44 89 f2 48 f7 e2 48 0f ac d0 20 4a 8d 0c 38 44 39 03 75 a4 48 8b 15 15 df 6b 00 48 39 ca 77 17 48 89 d0<f0>  48 0f b1 0d 04 df 6b 00 48 39 c1 48 89 c2 75 e7 48 89 ca 48
RIP  [<ffffffff81054f73>] pvclock_clocksource_read+0x83/0xc0

--> lock cmpxchg %rcx,0x6bdf04(%rip)

Quoted 5 lines

static atomic64_t last_value = ATOMIC64_INIT(0);

cycle_t pvclock_clocksource_read(struct pvclock_vcpu_time_info *src) {

[...]

Quoted 9 lines
    last = atomic64_read(&last_value);
    do {
        if (ret < last)
            return last;
        last = atomic64_cmpxchg(&last_value, last, ret);
    } while (unlikely(last != ret));

    return ret;
}

So it looks like last_value was placed in a read only section. Please post your System.map somewhere.

Signature · 1 line
error compiling committee.c: too many arguments to function
#362 lore raw

Re: [patch 134/149] x86, paravirt: Add a global synchronization point for pvclock

Quoted 11 lines · Avi Kivity
Quoted 3 lines
BUG: unable to handle kernel paging request at ffffffff81712e80
IP: [<ffffffff81054f73>] pvclock_clocksource_read+0x83/0xc0

PGD 1003067 PUD 1007063 PMD 7e8b1063 PTE 8000000001712161

Read-only pte

Quoted 1 line
Oops: 0003 [#2] SMP

Write fault.

Quoted 2 lines
Code: 78 4f 44 89 e1 48 d3 e0 44 89 f2 48 f7 e2 48 0f ac d0 20 4a 8d 0c 38 44 39 03 75 a4 48 8b 15 15 df 6b 00 48 39 ca 77 17 48 89 d0<f0>  48 0f b1 0d 04 df 6b 00 48 39 c1 48 89 c2 75 e7 48 89 ca 48
RIP  [<ffffffff81054f73>] pvclock_clocksource_read+0x83/0xc0

--> lock cmpxchg %rcx,0x6bdf04(%rip)

Quoted 8 lines
Quoted 4 lines

static atomic64_t last_value = ATOMIC64_INIT(0);

cycle_t pvclock_clocksource_read(struct pvclock_vcpu_time_info *src)

        last = atomic64_cmpxchg(&last_value, last, ret);

So it looks like last_value was placed in a read only section. Please post your System.map somewhere.

weasel@intrepid:~$ publish System.map
http://asteria.noreply.org/~weasel/volatile/2010-07-13-mbm2xEdd8Q4/System.map
weasel@intrepid:~$ grep -i last_value System.map
ffffffff81712e80 r last_value
ffffffff81b05240 b last_value.26163

Cheers,
Peter

Signature · 4 lines
                           |  .''`.  ** Debian GNU/Linux **
      Peter Palfrader      | : :' :      The  universal
 http://www.palfrader.org/ | `. `'      Operating System
                           |   `-    http://www.debian.org/
#363 lore raw

Re: [patch 134/149] x86, paravirt: Add a global synchronization point for pvclock

Quoted 10 lines · Peter Palfrader
Quoted 4 lines

So it looks like last_value was placed in a read only section. Please post your System.map somewhere.

weasel@intrepid:~$ publish System.map
http://asteria.noreply.org/~weasel/volatile/2010-07-13-mbm2xEdd8Q4/System.map
weasel@intrepid:~$ grep -i last_value System.map
ffffffff81712e80 r last_value
ffffffff81b05240 b last_value.26163

"r" = "read only"

How does it look in 'nm arch/x86/kernel/pvclock.o'?

#364 lore raw

Re: [patch 134/149] x86, paravirt: Add a global synchronization point for pvclock

Quoted 10 lines · Avi Kivity
Quoted 9 lines
Quoted 3 lines

So it looks like last_value was placed in a read only section. Please post your System.map somewhere.

weasel@intrepid:~$ publish System.map
http://asteria.noreply.org/~weasel/volatile/2010-07-13-mbm2xEdd8Q4/System.map
weasel@intrepid:~$ grep -i last_value System.map
ffffffff81712e80 r last_value
ffffffff81b05240 b last_value.26163
Quoted 3 lines

"r" = "read only"

How does it look in 'nm arch/x86/kernel/pvclock.o'?

The same:

[git|v2.6.32.16] weasel@thelma:/scratch/kernel/2.6.32.16$ nm arch/x86/kernel/pvclock.o 0000000000000000 r last_value
U native_read_tsc
0000000000000040 T pvclock_clocksource_read
0000000000000100 T pvclock_read_wallclock
0000000000000000 T pvclock_tsc_khz
U set_normalized_timespec

Signature · 4 lines
                           |  .''`.  ** Debian GNU/Linux **
      Peter Palfrader      | : :' :      The  universal
 http://www.palfrader.org/ | `. `'      Operating System
                           |   `-    http://www.debian.org/
#365 lore raw

Re: [patch 134/149] x86, paravirt: Add a global synchronization point for pvclock

Quoted 14 lines · Peter Palfrader
Quoted 8 lines
Quoted 8 lines
weasel@intrepid:~$ publish System.map
http://asteria.noreply.org/~weasel/volatile/2010-07-13-mbm2xEdd8Q4/System.map
weasel@intrepid:~$ grep -i last_value System.map
ffffffff81712e80 r last_value
ffffffff81b05240 b last_value.26163
Quoted 4 lines

"r" = "read only"

How does it look in 'nm arch/x86/kernel/pvclock.o'?

The same:

Quoted 8 lines

[git|v2.6.32.16] weasel@thelma:/scratch/kernel/2.6.32.16$ nm arch/x86/kernel/pvclock.o 0000000000000000 r last_value
U native_read_tsc
0000000000000040 T pvclock_clocksource_read
0000000000000100 T pvclock_read_wallclock
0000000000000000 T pvclock_tsc_khz
U set_normalized_timespec

But it's

Quoted 3 lines

static atomic64_t last_value = ATOMIC64_INIT(0);

Doesn't make any sense.

Let's try to see if the toolchain is confused:

- rename last_value to some random name
- drop the 'static' qualifier
- drop the '= ATOMIC64_INIT(0)'
- all of the above

(better start with the last).

No need to rebuild everything, just look at the output of nm pvclock.o.

My bet is that dropping 'static' will fix it. We may have the wrong constraints on atomic64_cmpxchg64(), so the compiler thinks we never change last_value.

Signature · 1 line
error compiling committee.c: too many arguments to function
#366 lore raw

Re: [patch 134/149] x86, paravirt: Add a global synchronization point for pvclock

Quoted 3 lines · Avi Kivity

My bet is that dropping 'static' will fix it. We may have the wrong constraints on atomic64_cmpxchg64(), so the compiler thinks we never change last_value.

The constraints are there, but maybe the toolchain is confused.

Signature · 1 line
error compiling committee.c: too many arguments to function
#367 lore raw

Re: [patch 134/149] x86, paravirt: Add a global synchronization point for pvclock

Quoted 7 lines · Avi Kivity
Quoted 3 lines · Avi Kivity

My bet is that dropping 'static' will fix it. We may have the wrong constraints on atomic64_cmpxchg64(), so the compiler thinks we never change last_value.

The constraints are there, but maybe the toolchain is confused.

No they aren't, as Linus just pointed out. His patch should fix the problem.

Signature · 1 line
error compiling committee.c: too many arguments to function
#368 lore raw

Re: [patch 134/149] x86, paravirt: Add a global synchronization point for pvclock

Quoted 8 lines · Avi Kivity
Quoted 7 lines · Avi Kivity
Quoted 5 lines · Avi Kivity

My bet is that dropping 'static' will fix it. We may have the wrong constraints on atomic64_cmpxchg64(), so the compiler thinks we never change last_value.

Quoted 5 lines
Quoted 2 lines

The constraints are there, but maybe the toolchain is confused.

No they aren't, as Linus just pointed out. His patch should fix the problem.

Linus's patch touches __xchg() whereas we're using __cmpxchg() in this particular case I think.

At least, applying it to my 2.6.32.16 tree didn't help, last_value was still read-only. Or I backported it wrong.

Signature · 4 lines
                           |  .''`.  ** Debian GNU/Linux **
      Peter Palfrader      | : :' :      The  universal
 http://www.palfrader.org/ | `. `'      Operating System
                           |   `-    http://www.debian.org/
#369 lore raw

Re: [patch 134/149] x86, paravirt: Add a global synchronization point for pvclock

Quoted 6 lines · Peter Palfrader

Linus's patch touches __xchg() whereas we're using __cmpxchg() in this particular case I think.

At least, applying it to my 2.6.32.16 tree didn't help, last_value was still read-only.  Or I backported it wrong.

No, you didn't back-port it wrong. I just didn't fix the right part. I thought the PV code used xchg, not cmpxchg, so I only patched that. But cmpxchg has the exact same issue.

Does this fix it?

Again: UNTESTED.

Linus

#370 lore raw

Re: [patch 134/149] x86, paravirt: Add a global synchronization point for pvclock

Quoted 6 lines · Linus Torvalds

No, you didn't back-port it wrong. I just didn't fix the right part. I thought the PV code used xchg, not cmpxchg, so I only patched that. But cmpxchg has the exact same issue.

Does this fix it?

Btw, this second patch was a bit more aggressive than the first one, and actually removes the "memory" clobber entirely, and the fake cast of the target type.

That shouldn't matter _except_ if people actually use cmpxchg to implement their own locking, since now the compiler could potentially move unrelated memory references around the lock. Of course, if you use cmpxchg to implement your own locking, you're probably doing something wrong anyway (ie you'll get the wrong memory barriers on various architectures), so it should all be fine.

But I thought I'd mention it. And I don't really know how much gcc moves memory accesses around a "asm volatile" - the gcc docs are historically very vague ("volatile asms aren't moved around 'significantly'", whatever 'significant' means)

And btw, none of the above should be taken to mean that I have tested the patch or found it to be otherwise good. It might be totally broken for other reasons. Caveat emptor.

Linus

#371 lore raw

Re: [patch 134/149] x86, paravirt: Add a global synchronization point for pvclock

Quoted 11 lines · Linus Torvalds

Btw, this second patch was a bit more aggressive than the first one, and actually removes the "memory" clobber entirely, and the fake cast of the target type.

That shouldn't matter _except_ if people actually use cmpxchg to implement their own locking, since now the compiler could potentially move unrelated memory references around the lock. Of course, if you use cmpxchg to implement your own locking, you're probably doing something wrong anyway (ie you'll get the wrong memory barriers on various architectures), so it should all be fine.

There are some places which rely on xchg/cmpxchg being a barrier in arch-specific code. For example, the Xen code uses as part of the shared memory protocol with the hypervisor.

Quoted 5 lines

But I thought I'd mention it. And I don't really know how much gcc moves memory accesses around a "asm volatile" - the gcc docs are historically very vague ("volatile asms aren't moved around 'significantly'", whatever 'significant' means)

"asm volatile"'s only real meaning is that it will not get elided if it appears its output is unused (assuming it is reachable at all). I don't think you can consider it having any meaningful effects on ordering.

J

reviewer Acked-by
#372 lore raw

Re: [patch 134/149] x86, paravirt: Add a global synchronization point for pvclock

Quoted 5 lines · Jeremy Fitzhardinge

"asm volatile"'s only real meaning is that it will not get elided if it appears its output is unused (assuming it is reachable at all). I don't think you can consider it having any meaningful effects on ordering.

Actually, I believe volatile operations (including asm volatile) are strictly ordered *with respect to other volatile operations*. As such I would think we'd want to keep the "memory" clobber here, to make it strictly ordered with regards to *all* memory operations.

As for the concept in this patch, it's obviously the right thing, but as Linus said elsewhere it's incomplete.

Conceptually:

Unfortunately I can't write the productization patch right now since I have a plane to catch in about an hour, but if noone beats me to it I'll to it Thursday.

-hpa

#373 lore raw

Re: [patch 134/149] x86, paravirt: Add a global synchronization point for pvclock

Quoted 2 lines · H. Peter Anvin

Actually, I believe volatile operations (including asm volatile) are strictly ordered *with respect to other volatile operations*.

The documentation makes no reference to that property; in fact it suggests it is outright not true:

Note that even a volatile `asm' instruction can be moved relative to other
code, including across jump instructions. For example, on many targets there is a system register which can be set to control the rounding mode of floating point operations. You might try setting it with a volatile `asm', like this PowerPC example:

asm volatile("mtfsf 255,%0" : : "f" (fpenv)); sum = x + y;

This will not work reliably, as the compiler may move the addition back before the volatile asm'. To make it work you need to add an artificial dependency to the asm' referencing a variable in the code you don't want moved, for example:

asm volatile ("mtfsf 255,%1" : "=X"(sum): "f"(fpenv)); sum = x + y;

Similarly, you can't expect a sequence of volatile `asm' instructions to remain perfectly consecutive.
[...]
An asm' instruction without any output operands will be treated identically to a volatile asm' instruction.

Quoted 4 lines

As such I
would think we'd want to keep the "memory" clobber here, to make it strictly ordered with regards to *all* memory operations.

That would keep its overall effect consistent.

J

#374 lore raw

Re: [patch 134/149] x86, paravirt: Add a global synchronization point for pvclock

Quoted 3 lines · Jeremy Fitzhardinge

The documentation makes no reference to that property; in fact it suggests it is outright not true:

The gcc documentation wrt inline asm's is totally worthless. Don't even bother quoting it - because the gcc people themselves have never cared. If the docs ever end up not matching what they want to do, they will just change the documentation.

In other words, at least historically the docs are not in any way meaningful. They are not a "these are the semantics we guarantee", they are just random noise. As I mentioned, the docs historically just said something like "will not be moved significantly", and apparently they've been changed to be something else.

The only thing that has ever been meaningful is "this works". And, of course, that has changed over time too, including actual recommendations on how to make something work (as mentioned, iirc "+" was only valid on register constraints, and "+m" used to not be allowed _or_ recommended, these days it's the only way to do certain things).

It's irritating, because in other circumstances, gcc people take the reverse approach, and consider paper documentation more important than actual implementation issues. So sometimes they say "hey, this is the spec", but when it comes to their own docs, the answer has historically been "we'll just change the spec".

Linus

#375 lore raw

Re: [patch 134/149] x86, paravirt: Add a global synchronization point for pvclock

Quoted 5 lines · Linus Torvalds

The gcc documentation wrt inline asm's is totally worthless. Don't even bother quoting it - because the gcc people themselves have never cared. If the docs ever end up not matching what they want to do, they will just change the documentation.

Quoted 7 lines

In other words, at least historically the docs are not in any way meaningful. They are not a "these are the semantics we guarantee", they are just random noise. As I mentioned, the docs historically just said something like "will not be moved significantly", and apparently they've been changed to be something else.

Sure, I completely agree. At the moment the docs say "asm volatile guarantees nothing", and we can work with that. So long as we don't expect asm volatile to mean anything more (ie, magic semantics involving reordering), everyone is happy.

BTW, gcc 2.95's docs do mention "asm volatile" having an effect on ordering, which is probably where the notion came from: "If you write an asm' instruction with no outputs, GNU CC [...] not delete the instruction or move it outside of loops. [...] you should write the volatile' keyword to prevent future versions of GNU CC from moving the instruction around within a core region". Lucky we never relied on that, right? Right?

J

#376 lore raw

Re: [patch 134/149] x86, paravirt: Add a global synchronization point for pvclock

Quoted 12 lines · Jeremy Fitzhardinge
Quoted 10 lines · Linus Torvalds

The gcc documentation wrt inline asm's is totally worthless. Don't even bother quoting it - because the gcc people themselves have never cared. If the docs ever end up not matching what they want to do, they will just change the documentation.

In other words, at least historically the docs are not in any way meaningful. They are not a "these are the semantics we guarantee", they are just random noise. As I mentioned, the docs historically just said something like "will not be moved significantly", and apparently they've been changed to be something else.

Quoted 4 lines

Sure, I completely agree. At the moment the docs say "asm volatile guarantees nothing", and we can work with that. So long as we don't expect asm volatile to mean anything more (ie, magic semantics involving reordering), everyone is happy.

Except we do.

Quoted 7 lines

BTW, gcc 2.95's docs do mention "asm volatile" having an effect on ordering, which is probably where the notion came from: "If you write an asm' instruction with no outputs, GNU CC [...] not delete the instruction or move it outside of loops. [...] you should write the volatile' keyword to prevent future versions of GNU CC from moving the instruction around within a core region". Lucky we never relied on that, right? Right?

If gcc ever starts reordering volatile operations, including "asm volatile", the kernel will break, and will be unfixable. Just about every single driver will break. All over the kernel we're explicitly or implicitly making the assumption that volatile operations are strictly ordered by the compiler with respect to each other.

-hpa

#377 lore raw

Re: [patch 134/149] x86, paravirt: Add a global synchronization point for pvclock

Quoted 6 lines · H. Peter Anvin

If gcc ever starts reordering volatile operations, including "asm volatile", the kernel will break, and will be unfixable. Just about every single driver will break. All over the kernel we're explicitly or implicitly making the assumption that volatile operations are strictly ordered by the compiler with respect to each other.

Can you give an example? All the cases I've seen rely on the ordering properties of "memory" clobbers, which is sound. (And volatile variables are a completely unrelated issue, of course.)

J

#378 lore raw

Re: [patch 134/149] x86, paravirt: Add a global synchronization point for pvclock

Quoted 11 lines · Jeremy Fitzhardinge
Quoted 5 lines · H. Peter Anvin

If gcc ever starts reordering volatile operations, including "asm volatile", the kernel will break, and will be unfixable. Just about every single driver will break. All over the kernel we're explicitly or implicitly making the assumption that volatile operations are strictly ordered by the compiler with respect to each other.

Can you give an example? All the cases I've seen rely on the ordering properties of "memory" clobbers, which is sound. (And volatile variables are a completely unrelated issue, of course.)

I/O ports, for example.

-hpa

#379 lore raw

Re: [patch 134/149] x86, paravirt: Add a global synchronization point for pvclock

Quoted 10 lines · H. Peter Anvin
Quoted 8 lines · Jeremy Fitzhardinge
Quoted 6 lines · H. Peter Anvin

If gcc ever starts reordering volatile operations, including "asm volatile", the kernel will break, and will be unfixable. Just about every single driver will break. All over the kernel we're explicitly or implicitly making the assumption that volatile operations are strictly ordered by the compiler with respect to each other.

Quoted 7 lines
Quoted 5 lines

Can you give an example? All the cases I've seen rely on the ordering properties of "memory" clobbers, which is sound. (And volatile variables are a completely unrelated issue, of course.)

I/O ports, for example.

Yes, it looks like they should have memory barriers if we want them to be ordered with respect to normal writes; afaict "asm volatile" has never had strict ordering wrt memory ops.

Anything else?

J

#380 lore raw

Re: [patch 134/149] x86, paravirt: Add a global synchronization point for pvclock

[Adding H.J. to the Cc: list]

Quoted 8 lines · Jeremy Fitzhardinge
Quoted 3 lines
Quoted 1 line

I/O ports, for example.

Yes, it looks like they should have memory barriers if we want them to be ordered with respect to normal writes; afaict "asm volatile" has never had strict ordering wrt memory ops.

Noone has talked about strict ordering between volatiles and (non-volatile) memory ops in general. I have been talking about volatile to volatile ordering, and I thought I'd been very clear about that.

H.J., we're having a debate about the actual semantics of "volatile", especially "asm volatile" in gcc. In particular, I believe that volatile operations should not be possible to reorder with regards to each other, and the kernel depends on that fact.

-hpa

P.S: gcc 4.4 seems to handle "const volatile" incorrectly, probably by applying CSE to those values.

#381 lore raw

Re: [patch 134/149] x86, paravirt: Add a global synchronization point for pvclock

Quoted 4 lines · H. Peter Anvin

Noone has talked about strict ordering between volatiles and (non-volatile) memory ops in general. I have been talking about volatile to volatile ordering, and I thought I'd been very clear about that.

OK.

Quoted 5 lines

H.J., we're having a debate about the actual semantics of "volatile", especially "asm volatile" in gcc. In particular, I believe that volatile operations should not be possible to reorder with regards to each other, and the kernel depends on that fact.

I think we should consider that deprecated and rely on dependencies and clobbers.

J

#382 lore raw

Re: [patch 134/149] x86, paravirt: Add a global synchronization point for pvclock

Quoted 4 lines · Jeremy Fitzhardinge

I think we should consider that deprecated and rely on dependencies and clobbers.

I don't think that's practical in general. If the compiler is *that broken*, I don't see how it is usable at all.

As Linus indicated, I don't think we can assume the gcc documentation to accurately reflect the intent of the gcc team, mostly because I think it often lags way behind what they're thinking.

-hpa

#383 lore raw

Re: [patch 134/149] x86, paravirt: Add a global synchronization point for pvclock

Quoted 9 lines · H. Peter Anvin
Quoted 4 lines · Jeremy Fitzhardinge

I think we should consider that deprecated and rely on dependencies and clobbers.

I don't think that's practical in general. If the compiler is *that broken*, I don't see how it is usable at all.

Well, over the years, gcc has explicitly changed the docs to weaken the meaning of "asm volatile" from "not being moved ``significantly''" to "no real guarantees about movement at all".

I don't see why its so broken. There are lots of mechanisms to control asm ordering; we don't need "asm volatile" as well. But we do need it to mean "still emit an apparently dead asm with no outputs (or unused outputs)".

They can still be omitted if the whole basic block is dead code, and they can be duplicated by things like inlining and loop unrolling. But presumably they can never be evaluated more times than the source code says they should be, so to that extent they're like volatile variables.

I think the use of the "volatile" keyword here is a red herring. Just because the gcc devs decided to use it as a qualifier for asm statements doesn't mean that one should read anything other than a vague, vague relationship to volatile variables (and extra-vague given how weakly defined *they* are).

Quoted 4 lines

As Linus indicated, I don't think we can assume the gcc documentation to accurately reflect the intent of the gcc team, mostly because I think it often lags way behind what they're thinking.

I can get not trusting gcc to do what the documentation says it should do, but relying on it to do things that the documentation definitely says it doesn't seems foolhardy.

I'm finding it a bit surreal to be arguing on the side of "don't trust gcc" vs you and Linus on the "gcc developers are arbitrary, capricious and untrustworthy, but we can rely on this piece of undocumented behaviour" side.

J

#384 lore raw

Re: [patch 134/149] x86, paravirt: Add a global synchronization point for pvclock

In reply to Jeremy Fitzhardinge
Quoted 3 lines · Jeremy Fitzhardinge

I think we should consider that deprecated and rely on dependencies and clobbers.

That makes no sense. According to that logic, "asm volatile" has no semantic meaning at ALL. That's just crazy talk.

The sane compiler semantics for "asm volatile" is that it acts as a volatile memory access. That's what the naming implies, and it has valid semantics that also happen to match the historical semantics. It means that it cannot be removed or duplicated, and it cannot be re-ordered wrt other volatile accesses (whether "asm volatile" or a traditional C volatile memory access).

I agree that we could just add memory clobbers to them all, but my objection to that is that it just makes the whole keyword totally pointless.

Linus

#385 lore raw

Re: [patch 134/149] x86, paravirt: Add a global synchronization point for pvclock

In reply to H. Peter Anvin
Quoted 21 lines · H. Peter Anvin

[Adding H.J. to the Cc: list]

Quoted 8 lines · Jeremy Fitzhardinge
Quoted 3 lines
Quoted 1 line

I/O ports, for example.

Yes, it looks like they should have memory barriers if we want them to be ordered with respect to normal writes; afaict "asm volatile" has never had strict ordering wrt memory ops.

Noone has talked about strict ordering between volatiles and (non-volatile) memory ops in general.  I have been talking about volatile to volatile ordering, and I thought I'd been very clear about that.

H.J., we're having a debate about the actual semantics of "volatile", especially "asm volatile" in gcc.  In particular, I believe that volatile operations should not be possible to reorder with regards to each other, and the kernel depends on that fact.

Quoted 6 lines

       -hpa

P.S: gcc 4.4 seems to handle "const volatile" incorrectly, probably by applying CSE to those values.

There are some discussions on:

http://gcc.gnu.org/ml/gcc-patches/2010-06/msg02001.html
http://gcc.gnu.org/ml/gcc-patches/2010-07/msg00001.html

Are they related?

Signature · 1 line
H.J.
#386 lore raw

Re: [patch 134/149] x86, paravirt: Add a global synchronization point for pvclock

Quoted 8 lines · H.J. Lu

There are some discussions on:

http://gcc.gnu.org/ml/gcc-patches/2010-06/msg02001.html
http://gcc.gnu.org/ml/gcc-patches/2010-07/msg00001.html

Are they related?

Not directly as far as I can tell.

The issue is if gcc can ever reorder, duplicate or elide a volatile operation (either asm volatile or a volatile-annotated memory reference.) In my (and Linus') opinion, this would be an incredibly serious bug.

The gcc 4.4 issue, which is separate from the definition issue, is that it seems to assume that it can elide references to "const volatile" objects. "const volatile" should mean a value that could change at any time but which is a bug to write to -- for example a readonly hardware register.

-hpa

#387 lore raw

Re: [patch 134/149] x86, paravirt: Add a global synchronization point for pvclock

Quoted 10 lines · H. Peter Anvin
Quoted 8 lines · H.J. Lu

There are some discussions on:

http://gcc.gnu.org/ml/gcc-patches/2010-06/msg02001.html
http://gcc.gnu.org/ml/gcc-patches/2010-07/msg00001.html

Are they related?

Quoted 8 lines

Not directly as far as I can tell.

The issue is if gcc can ever reorder, duplicate or elide a volatile operation (either asm volatile or a volatile-annotated memory reference.)  In my (and Linus') opinion, this would be an incredibly serious bug.

Is there a gcc bug for this?

Signature · 1 line
H.J.
#388 lore raw

Re: [patch 134/149] x86, paravirt: Add a global synchronization point for pvclock

Quoted 11 lines · H.J. Lu
Quoted 10 lines · H. Peter Anvin
Quoted 8 lines · H.J. Lu

There are some discussions on:

http://gcc.gnu.org/ml/gcc-patches/2010-06/msg02001.html
http://gcc.gnu.org/ml/gcc-patches/2010-07/msg00001.html

Are they related?

Quoted 9 lines
Quoted 6 lines

Not directly as far as I can tell.

The issue is if gcc can ever reorder, duplicate or elide a volatile operation (either asm volatile or a volatile-annotated memory reference.) In my (and Linus') opinion, this would be an incredibly serious bug.

Is there a gcc bug for this?

Are you asking for a bug report against the documentation? We're not sure what the semantics intended by the gcc team to be, which I guess is a documentation bug.

-hpa

#389 lore raw

Re: [patch 134/149] x86, paravirt: Add a global synchronization point for pvclock

Quoted 19 lines · H. Peter Anvin
Quoted 18 lines · H.J. Lu
Quoted 16 lines · H. Peter Anvin
Quoted 8 lines · H.J. Lu

There are some discussions on:

http://gcc.gnu.org/ml/gcc-patches/2010-06/msg02001.html
http://gcc.gnu.org/ml/gcc-patches/2010-07/msg00001.html

Are they related?

Not directly as far as I can tell.

The issue is if gcc can ever reorder, duplicate or elide a volatile operation (either asm volatile or a volatile-annotated memory reference.)  In my (and Linus') opinion, this would be an incredibly serious bug.

Quoted 7 lines
Quoted 2 lines

Is there a gcc bug for this?

Are you asking for a bug report against the documentation?  We're not sure what the semantics intended by the gcc team to be, which I guess is a documentation bug.

Documentation bug is also a bug :-).

Signature · 1 line
H.J.
#390 lore raw

Re: [patch 134/149] x86, paravirt: Add a global synchronization point for pvclock

Quoted 26 lines · H.J. Lu
Quoted 24 lines · H. Peter Anvin
Quoted 22 lines · H.J. Lu
Quoted 10 lines · H. Peter Anvin
Quoted 8 lines · H.J. Lu

There are some discussions on:

http://gcc.gnu.org/ml/gcc-patches/2010-06/msg02001.html
http://gcc.gnu.org/ml/gcc-patches/2010-07/msg00001.html

Are they related?

Quoted 7 lines

Not directly as far as I can tell.

The issue is if gcc can ever reorder, duplicate or elide a volatile operation (either asm volatile or a volatile-annotated memory reference.) In my (and Linus') opinion, this would be an incredibly serious bug.

Is there a gcc bug for this?

Quoted 7 lines
Quoted 5 lines

Are you asking for a bug report against the documentation? We're not sure what the semantics intended by the gcc team to be, which I guess is a documentation bug.

Documentation bug is also a bug :-).

The question is "what are the real ordering semantics of asm volatile"? What ordering is enforced between other asm volatiles? What ordering is enforced between asm volatiles and regular memory accesses? asm volatile and other code?

The documentation discusses this to some extent, but mostly says "there are no ordering guarantees". Older versions of gcc - 2.95, for example
- are more explicit, saying that "asm volatiles" won't be moved out of their basic block (I think that's how I parse it, anyway).

Linux relies on "asm volatile" being ordered at least with respect to other asm volatiles. Is this reasonable now? Will gcc break this at some point in the future? If we can't rely on "asm volatile" ordering semantics, what other mechanism can we use (for example, to order clts with respect to FPU-using code)?

Thanks,
J

#391 lore raw

Re: [patch 134/149] x86, paravirt: Add a global synchronization point for pvclock

Quoted 11 lines · Jeremy Fitzhardinge

The question is "what are the real ordering semantics of asm volatile"? What ordering is enforced between other asm volatiles? What ordering is enforced between asm volatiles and regular memory accesses? asm volatile and other code?

The documentation discusses this to some extent, but mostly says "there are no ordering guarantees". Older versions of gcc - 2.95, for example
- are more explicit, saying that "asm volatiles" won't be moved out of their basic block (I think that's how I parse it, anyway).

I looked over the text, and I think you're confusing static reordering and duplication with execution reordering (gcc is indeed free to move around and even replicate asm volatile statements). One thing is that the docs makes it perfectly clear that asm volatile is not ordered with respect to *non*-volatile operations (*all* the examples are volatile-nonvolatile.) It says that asm volatile statements may not be "consecutive", i.e. gcc may generate code in between them, but all of this is well known and understood.

The other thing that the documentation *does* specifically make clear is that an "asm volatile" has an implicit dependency on all memory (as an input, as opposed to an output/clobber.)

I actually found the following statement in the gcc documentation, although it is in the section on C++ (6.1 in my version); the text, though, makes it clear that it applies to both C and C++:

Both the C and C++ standard have the concept of volatile objects. These are normally accessed by pointers and used for accessing hardware. The standards encourage compilers to refrain from optimizations concerning accesses to volatile objects. The C standard leaves it implementation defined as to what constitutes a volatile access. The C++ standard omits to specify this, except to say that C++ should behave in a similar manner to C with respect to volatiles, where possible. The minimum either standard specifies is that at a sequence point all previous accesses to volatile objects have stabilized and no subsequent accesses have occurred. Thus an implementation is free to reorder and

                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

combine volatile accesses which occur between sequence points, but ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot do so for accesses across a sequence point. The use of ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ volatiles does not allow you to violate the restriction on updating objects multiple times within a sequence point.

[My emphasis, obviously.]

I think that pretty much settles the matter, since any statement (including an asm statement) inherently has a sequence point before or after it. However, I will file a gcc bug report to clarify.

-hpa

#393 lore raw

Re: [patch 134/149] x86, paravirt: Add a global synchronization point for pvclock

In reply to Jeremy Fitzhardinge
Quoted 1 line · Jeremy Fitzhardinge

Anything else?

1. set up a mapping
2. invlpg or set cr3
3. use the mapping

Moving the invlpg will break your code.

Signature · 2 lines
I have a truly marvellous patch that fixes the bug which this
signature is too narrow to contain.
#394 lore raw

Re: [patch 134/149] x86, paravirt: Add a global synchronization point for pvclock

Quoted 8 lines · Avi Kivity
Quoted 1 line · Jeremy Fitzhardinge

Anything else?

1. set up a mapping
2. invlpg or set cr3
3. use the mapping

Moving the invlpg will break your code.

invlpg uses memory clobbers. All the crX ops seem to use a __force_order variable to sequence them - but it looks like it's done precisely backwards and it's barking mad to do allow write_crX to be reordered with respect to memory ops.

Hm, looks like glommer added it surreptitiously while unifying system_32.h and system_64.h (system_32.h relied on asm volatile not being reordered; system_64.h used memory clobbers).
J

#395 lore raw

Re: [patch 134/149] x86, paravirt: Add a global synchronization point for pvclock

Quoted 17 lines · Jeremy Fitzhardinge
Quoted 10 lines · Avi Kivity
Quoted 2 lines · Jeremy Fitzhardinge

Anything else?

1. set up a mapping
2. invlpg or set cr3
3. use the mapping

Moving the invlpg will break your code.

invlpg uses memory clobbers. All the crX ops seem to use a __force_order variable to sequence them - but it looks like it's done precisely backwards and it's barking mad to do allow write_crX to be reordered with respect to memory ops.

Quoted 5 lines

Hm, looks like glommer added it surreptitiously while unifying system_32.h and system_64.h (system_32.h relied on asm volatile not being reordered; system_64.h used memory clobbers).
J

clts() has no memory clobber; it is used to serialize execution of code within kernel_fpu_begin() / kernel_fpu_end() blocks.

If the code within is reordered before the clts(), we've corrupted guest FPU state.

That's the kind of bug I think Linus is talking about. We've been expecting volatile to work that way for over a decade, by my recollection, and if it doesn't, there is going to be a lot of broken code.

Shouldn't we at least get a compiler switch to force the volatile behavior? I'd suggest it default to conservative.

#396 lore raw

Re: [patch 134/149] x86, paravirt: Add a global synchronization point for pvclock

Quoted 19 lines · Zachary Amsden
Quoted 13 lines · Jeremy Fitzhardinge
Quoted 7 lines · Avi Kivity
Quoted 1 line · Jeremy Fitzhardinge

Anything else?

1. set up a mapping
2. invlpg or set cr3
3. use the mapping

Moving the invlpg will break your code.

invlpg uses memory clobbers. All the crX ops seem to use a __force_order variable to sequence them - but it looks like it's done precisely backwards and it's barking mad to do allow write_crX to be reordered with respect to memory ops.

Quoted 4 lines

Hm, looks like glommer added it surreptitiously while unifying system_32.h and system_64.h (system_32.h relied on asm volatile not being reordered; system_64.h used memory clobbers).
J

Quoted 7 lines

clts() has no memory clobber; it is used to serialize execution of code within kernel_fpu_begin() / kernel_fpu_end() blocks.

If the code within is reordered before the clts(), we've corrupted guest FPU state.

That's the kind of bug I think Linus is talking about. We've been expecting volatile to work that way for over a decade, by my recollection, and if it doesn't, there is going to be a lot of broken code.

Shouldn't we at least get a compiler switch to force the volatile behavior? I'd suggest it default to conservative.

Hmm, well, despite that not being quite correct (if guest has used FPU, we save it, which has a memory clobber), it seems to be the case that a reordering of the clts() among the other volatile asm statements would be a very bad thing - you'd get kernel FPU exceptions.

And among asm volatiles, clts() is fairly unique in not having any clobbers or dependencies at all, so it could happen.

Zach

#397 lore raw

Re: [patch 134/149] x86, paravirt: Add a global synchronization point for pvclock

In reply to Zachary Amsden
Quoted 5 lines · Zachary Amsden

clts() has no memory clobber; it is used to serialize execution of code within kernel_fpu_begin() / kernel_fpu_end() blocks.

If the code within is reordered before the clts(), we've corrupted guest FPU state.

Hm, that's awkward - you'd really need some way of specifying ordering with respect to the FPU state, and "memory" would only be an approximate proxy of that. And not a good one, since gcc wouldn't regard register-only fpu ops as being affected by a memory clobber.

J

#398 lore raw

Re: [patch 134/149] x86, paravirt: Add a global synchronization point for pvclock

In reply to Zachary Amsden
Quoted 6 lines · Zachary Amsden

That's the kind of bug I think Linus is talking about. We've been expecting volatile to work that way for over a decade, by my recollection, and if it doesn't, there is going to be a lot of broken code.

Shouldn't we at least get a compiler switch to force the volatile behavior? I'd suggest it default to conservative.

At this point, it looks like there is no reason to be alarmed. The documentation actually contains a statement about volatiles not being mutually reordered across sequence points, and since asm is a statement (rather than an expression) it is always surrounded by sequence points.
I have filed a gcc ticket to ask for clarification.

-hpa

Signature · 2 lines
H. Peter Anvin, Intel Open Source Technology Center
I work for Intel.  I don't speak on their behalf.
#399 lore raw

Re: [patch 134/149] x86, paravirt: Add a global synchronization point for pvclock

In reply to Jeremy Fitzhardinge
Quoted 15 lines · Jeremy Fitzhardinge
Quoted 8 lines · Avi Kivity
Quoted 1 line · Jeremy Fitzhardinge

Anything else?

1. set up a mapping
2. invlpg or set cr3
3. use the mapping

Moving the invlpg will break your code.

invlpg uses memory clobbers. All the crX ops seem to use a __force_order variable to sequence them - but it looks like it's done precisely backwards and it's barking mad to do allow write_crX to be reordered with respect to memory ops.

Quoted 4 lines

Hm, looks like glommer added it surreptitiously while unifying system_32.h and system_64.h (system_32.h relied on asm volatile not being reordered; system_64.h used memory clobbers).
J

invlpg, in the general case, definitely needs a memory clobber even if volatiles are ordered, since it needs to be ordered with regards to non-volatile memory operations.

Note that memory clobbers don't by themselves enforce ordering since they don't prevent the ordering of memory clobbers with respect to each other.

-hpa

#400 lore raw

Re: [patch 134/149] x86, paravirt: Add a global synchronization point for pvclock

Quoted 4 lines · H. Peter Anvin

invlpg, in the general case, definitely needs a memory clobber even if volatiles are ordered, since it needs to be ordered with regards to non-volatile memory operations.

Yes. I'd say write_crX should need that too, since they can they can have a variety global effects on how memory addressing works (from tlb flush to switching pagetable formats).

Quoted 4 lines

Note that memory clobbers don't by themselves enforce ordering since they don't prevent the ordering of memory clobbers with respect to each other.

Hm. Well we do *definitely* rely on that. I guess technically we'd need at least a memory input on the asm to be ordered with respect to a memory clobber. But that doesn't seem to have been an issue (or perhaps its mixed up with the secret semantics of asm volatile).

J

#401 lore raw

Re: [patch 134/149] x86, paravirt: Add a global synchronization point for pvclock

In reply to Linus Torvalds
Quoted 8 lines · Linus Torvalds
Quoted 6 lines · Linus Torvalds

No, you didn't back-port it wrong. I just didn't fix the right part. I thought the PV code used xchg, not cmpxchg, so I only patched that. But cmpxchg has the exact same issue.

Does this fix it?

It appears to, thanks a lot.

[git|v2.6.32.16] weasel@thelma:/scratch/kernel/2.6.32.16$ nm arch/x86/kernel/pvclock.o 0000000000000000 b last_value
..

And it did boot too.

Quoted 3 lines

Btw, this second patch was a bit more aggressive than the first one, and actually removes the "memory" clobber entirely, and the fake cast of the target type.

Without the cast gcc spews a fair amount of warnings. About four every time it hits the include file.

Just for completeness' sake I attached the patch on top of 2.6.32.16 that I built with.

Signature · 4 lines
                           |  .''`.  ** Debian GNU/Linux **
      Peter Palfrader      | : :' :      The  universal
 http://www.palfrader.org/ | `. `'      Operating System
                           |   `-    http://www.debian.org/
arch/x86/include/asm/cmpxchg_64.h +20 -24
index 52de72e..f0551c5 100644
@@ -26,26 +26,26 @@ static inline unsigned long __xchg(unsigned long x, volatile void *ptr,
 	switch (size) {
 	case 1:
 		asm volatile("xchgb %b0,%1"
-			     : "=q" (x)
-			     : "m" (*__xg(ptr)), "0" (x)
+			     : "=q" (x), "+m" (*__xg(ptr))
+			     : "0" (x)
 			     : "memory");
 		break;
 	case 2:
 		asm volatile("xchgw %w0,%1"
-			     : "=r" (x)
-			     : "m" (*__xg(ptr)), "0" (x)
+			     : "=r" (x), "+m" (*__xg(ptr))
+			     : "0" (x)
 			     : "memory");
 		break;
 	case 4:
 		asm volatile("xchgl %k0,%1"
-			     : "=r" (x)
-			     : "m" (*__xg(ptr)), "0" (x)
+			     : "=r" (x), "+m" (*__xg(ptr))
+			     : "0" (x)
 			     : "memory");
 		break;
 	case 8:
 		asm volatile("xchgq %0,%1"
-			     : "=r" (x)
-			     : "m" (*__xg(ptr)), "0" (x)
+			     : "=r" (x), "+m" (*__xg(ptr))
+			     : "0" (x)
 			     : "memory");
 		break;
 	}
@@ -66,28 +66,24 @@ static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old,
 	unsigned long prev;
 	switch (size) {
 	case 1:
-		asm volatile(LOCK_PREFIX "cmpxchgb %b1,%2"
-			     : "=a"(prev)
-			     : "q"(new), "m"(*__xg(ptr)), "0"(old)
-			     : "memory");
+		asm volatile(LOCK_PREFIX "cmpxchgb %b2,%1"
+			     : "=a"(prev), "+m" (*__xg(ptr))
+			     : "q"(new), "0"(old));
 		return prev;
 	case 2:
-		asm volatile(LOCK_PREFIX "cmpxchgw %w1,%2"
-			     : "=a"(prev)
-			     : "r"(new), "m"(*__xg(ptr)), "0"(old)
-			     : "memory");
+		asm volatile(LOCK_PREFIX "cmpxchgw %w2,%1"
+			     : "=a"(prev), "+m" (*__xg(ptr))
+			     : "r"(new), "0"(old));
 		return prev;
 	case 4:
-		asm volatile(LOCK_PREFIX "cmpxchgl %k1,%2"
-			     : "=a"(prev)
-			     : "r"(new), "m"(*__xg(ptr)), "0"(old)
-			     : "memory");
+		asm volatile(LOCK_PREFIX "cmpxchgl %k2,%1"
+			     : "=a"(prev), "+m" (*__xg(ptr))
+			     : "r"(new), "0"(old));
 		return prev;
 	case 8:
-		asm volatile(LOCK_PREFIX "cmpxchgq %1,%2"
-			     : "=a"(prev)
-			     : "r"(new), "m"(*__xg(ptr)), "0"(old)
-			     : "memory");
+		asm volatile(LOCK_PREFIX "cmpxchgq %2,%1"
+			     : "=a"(prev), "+m" (*__xg(ptr))
+			     : "r"(new), "0"(old));
 		return prev;
 	}
 	return old;
#402 lore raw

Re: [patch 134/149] x86, paravirt: Add a global synchronization point for pvclock

In reply to Avi Kivity
Quoted 14 lines · Avi Kivity
Quoted 10 lines

The same:

[git|v2.6.32.16] weasel@thelma:/scratch/kernel/2.6.32.16$ nm arch/x86/kernel/pvclock.o 0000000000000000 r last_value
U native_read_tsc
0000000000000040 T pvclock_clocksource_read
0000000000000100 T pvclock_read_wallclock
0000000000000000 T pvclock_tsc_khz
U set_normalized_timespec

But it's

Quoted 1 line
Quoted 8 lines
Quoted 2 lines

static atomic64_t last_value = ATOMIC64_INIT(0);

Doesn't make any sense.

Let's try to see if the toolchain is confused:

- rename last_value to some random name

0000000000000000 r some_random_name

Quoted 1 line

- drop the 'static' qualifier

0000000000000000 B last_value

Quoted 1 line

- drop the '= ATOMIC64_INIT(0)'

0000000000000000 b last_value

Quoted 1 line

- all of the above

0000000000000000 B some_random_name

make -f scripts/Makefile.build obj=arch/x86/kernel arch/x86/kernel/pvclock.o
gcc -Wp,-MD,arch/x86/kernel/.pvclock.o.d -nostdinc -isystem /usr/lib/gcc/x86_64-linux-gnu/4.3.2/include -Iinclude -I/scratch/kernel/2.6.32.16/arch/x86/include -include include/linux/autoconf.h -D__KERNEL__ -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs -fno-strict-aliasing -fno-common -Werror-implicit-function-declaration -Wno-format-security -fno-delete-null-pointer-checks -O2 -m64 -mtune=generic -mno-red-zone -mcmodel=kernel -funit-at-a-time -maccumulate-outgoing-args -fstack-protector -DCONFIG_AS_CFI=1 -DCONFIG_AS_CFI_SIGNAL_FRAME=1 -pipe -Wno-sign-compare -fno-asynchronous-unwind-tables -mno-sse -mno-mmx -mno-sse2 -mno-3dnow -fno-omit-frame-pointer -fno-optimize-sibling-calls -g -Wdeclaration-after-statement -Wno-pointer-sign -fno-strict-overflow -D"KBUILD_STR(s)=#s" -D"KBUILD_BASENAME=KBUILD_STR(pvclock)" -D"KBUILD_MODNAME=KBUILD_STR(pvclock)" -c -o arch/x86/kernel/pvclock.o arch/x86/kernel/pvclock.c

[git|v2.6.32.16] weasel@thelma:/scratch/kernel/2.6.32.16$ gcc --version gcc (Debian 4.3.2-1.1) 4.3.2
Copyright (C) 2008 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

Using -O0 also results in a writeable last_value (b).

Signature · 4 lines
                           |  .''`.  ** Debian GNU/Linux **
      Peter Palfrader      | : :' :      The  universal
 http://www.palfrader.org/ | `. `'      Operating System
                           |   `-    http://www.debian.org/
#403 lore raw

Re: [patch 134/149] x86, paravirt: Add a global synchronization point for pvclock

In reply to Avi Kivity
Quoted 14 lines · Avi Kivity
Quoted 5 lines · Peter Palfrader
Quoted 4 lines

So it looks like last_value was placed in a read only section.  Please post your System.map somewhere.

Quoted 7 lines
weasel@intrepid:~$ publish System.map

http://asteria.noreply.org/~weasel/volatile/2010-07-13-mbm2xEdd8Q4/System.map

weasel@intrepid:~$ grep -i last_value System.map
ffffffff81712e80 r last_value
ffffffff81b05240 b last_value.26163
Quoted 3 lines

"r" = "read only"

How does it look in 'nm arch/x86/kernel/pvclock.o'?

I bet it is the same. And I have a suspicion: because the only write access to that variable is in an asm that uses the "memory" clobber to say it wrote to it (rather than say it writes to it directly), and because the variable is marked 'static', gcc decides that nothing ever writes to it in that compilation unit, and it can be made read-only.

Look at our definition for "xchg()" in arch/x86/include/asm/cmpxchg_64.h. It boils down to

                asm volatile("xchgq %0,%1"                              \
                             : "=r" (__x)                               \
                             : "m" (*__xg(ptr)), "0" (__x)              \
                             : "memory");                               \

for the 8-byte case (which is obviously what atomic64_xchg() uses). And the _reason_ we do that thing where we use a memory _input_ and then a clobber is that older versions of gcc did not accept the thing we _want_ to use, namely using "+m" to say that we actually change the memory. So the above is "wrong", but has historical reasons - and it's apparently never been changed.

However, the "+m" was fixed, and we use it elsewhere, so I think the "m" plus memory clobber is now purely historical. Does a patch something like the appended fix it? I also suspect we should look at some other uses in this area. The atomic64_64.h file uses "=m" and "m", which looks like another legacy thing (again, "+m" historically wasn't allowed, and then later became the 'correct' way to do things).

NOTE NOTE NOTE! This is UNTESTED and INCOMPLETE. We should do cmpxchg too, and the 32-bit versions. I'm adding Ingo and Peter to the cc.

Linus

#404 lore raw

Re: [patch 134/149] x86, paravirt: Add a global synchronization point for pvclock

Quoted 22 lines · Linus Torvalds

I bet it is the same. And I have a suspicion: because the only write access to that variable is in an asm that uses the "memory" clobber to say it wrote to it (rather than say it writes to it directly), and because the variable is marked 'static', gcc decides that nothing ever writes to it in that compilation unit, and it can be made read-only.

Look at our definition for "xchg()" in arch/x86/include/asm/cmpxchg_64.h. It boils down to

                 asm volatile("xchgq %0,%1"                              \
                              : "=r" (__x)                               \
                              : "m" (*__xg(ptr)), "0" (__x)              \
                              : "memory");                               \

for the 8-byte case (which is obviously what atomic64_xchg() uses). And the _reason_ we do that thing where we use a memory _input_ and then a clobber is that older versions of gcc did not accept the thing we _want_ to use, namely using "+m" to say that we actually change the memory. So the above is "wrong", but has historical reasons - and it's apparently never been changed.

Quoted 8 lines

However, the "+m" was fixed, and we use it elsewhere, so I think the "m" plus memory clobber is now purely historical. Does a patch something like the appended fix it? I also suspect we should look at some other uses in this area. The atomic64_64.h file uses "=m" and "m", which looks like another legacy thing (again, "+m" historically wasn't allowed, and then later became the 'correct' way to do things).

Well, current upstream uses "m":

Quoted 6 lines
        case 8:                                                         \
                asm volatile(lock "cmpxchgq %1,%2"                      \
                             : "=a"(__ret)                              \
                             : "r"(__new), "m"(*__xg(ptr)), "0"(__old)  \
                             : "memory");                               \
                break;                                                  \

and works; I also failed to reproduce with 2.6.32.16. So I expect some toolchain involvement.

Peter, what gcc are you using?

Signature · 2 lines
I have a truly marvellous patch that fixes the bug which this
signature is too narrow to contain.
#405 lore raw

Re: [patch 134/149] x86, paravirt: Add a global synchronization point for pvclock

Quoted 2 lines · Avi Kivity

Well, current upstream uses "m":

Yes, I'd expect current 2.6.34 to also show the same problem.

Quoted 2 lines

and works; I also failed to reproduce with 2.6.32.16.  So I expect some toolchain involvement.

And yes, I do believe it's likely a newer gcc that triggers it too, otherwise we'd have seen more reports of it.

Linus

#406 lore raw

Re: [patch 134/149] x86, paravirt: Add a global synchronization point for pvclock

Quoted 8 lines · Linus Torvalds
Quoted 1 line · Avi Kivity

Well, current upstream uses "m":

Yes, I'd expect current 2.6.34 to also show the same problem.

Quoted 2 lines

and works; I also failed to reproduce with 2.6.32.16. So I expect some toolchain involvement.

And yes, I do believe it's likely a newer gcc that triggers it too, otherwise we'd have seen more reports of it.

Did anyone get around to doing a proper fix for this? I don't see one in tip.git or linux-2.6.git. And it needs to get back into stable...

Thanks,
J

#407 lore raw

Re: [patch 134/149] x86, paravirt: Add a global synchronization point for pvclock

Quoted 5 lines · Jeremy Fitzhardinge
Quoted 4 lines · Linus Torvalds
Quoted 1 line · Avi Kivity

Well, current upstream uses "m":

Yes, I'd expect current 2.6.34 to also show the same problem.

Quoted 8 lines
Quoted 4 lines
Quoted 2 lines

and works; I also failed to reproduce with 2.6.32.16. So I expect some toolchain involvement.

And yes, I do believe it's likely a newer gcc that triggers it too, otherwise we'd have seen more reports of it.

Did anyone get around to doing a proper fix for this? I don't see one
in tip.git or linux-2.6.git. And it needs to get back into stable...

I'll go ahead and write it up.

-hpa

Signature · 2 lines
H. Peter Anvin, Intel Open Source Technology Center
I work for Intel.  I don't speak on their behalf.
#408 lore raw

xchg() and cmpxchg()

In reply to Jeremy Fitzhardinge

Okay, I've stared at this issue for most of the day, and I have a fix for the immediate issue.

However, I also am convinced that the whole scheme with the __xg() macro is just broken. It was introduced in 1.3.11 when xchg and cmpxchg where neither "asm volatile" nor had "memory" clobbers as an apparent way to keep gcc from moving memory references around it, but since the array type is "unsigned long" rather than a char type, it probably doesn't even work right, and with asm volatile/memory clobber it should not be necessary.

At this point I'd like to push an urgent patch to fix the immediate issue, and a cleanup patch getting rid of __xg() for .36.

-hpa

Signature · 2 lines
H. Peter Anvin, Intel Open Source Technology Center
I work for Intel.  I don't speak on their behalf.
#409 lore raw

[tip:x86/urgent] x86: Add memory modify constraints to xchg() and cmpxchg()

Commit-ID:  113fc5a6e8c2288619ff7e8187a6f556b7e0d372
Gitweb:     http://git.kernel.org/tip/113fc5a6e8c2288619ff7e8187a6f556b7e0d372
Author:     H. Peter Anvin <[email protected]>
AuthorDate: Tue, 27 Jul 2010 17:01:49 -0700
Committer:  H. Peter Anvin <[email protected]>
CommitDate: Tue, 27 Jul 2010 17:14:02 -0700

x86: Add memory modify constraints to xchg() and cmpxchg()

xchg() and cmpxchg() modify their memory operands, not merely read them. For some versions of gcc the "memory" clobber has apparently dealt with the situation, but not for all.

Cc Glauber Costa <[email protected]>
Cc Avi Kivity <[email protected]>
Cc Peter Palfrader <[email protected]>
Cc Greg KH <[email protected]>
Cc Alan Cox <[email protected]>
Cc Zachary Amsden <[email protected]>
Cc Marcelo Tosatti <[email protected]>

LKML-Reference: <[email protected]>

---
 arch/x86/include/asm/cmpxchg_32.h |   68 ++++++++++++++++++------------------
 arch/x86/include/asm/cmpxchg_64.h |   40 +++++++++++-----------
 2 files changed, 54 insertions(+), 54 deletions(-)
arch/x86/include/asm/cmpxchg_32.h +34 -34
index 8859e12..c1cf59d 100644
@@ -27,20 +27,20 @@ struct __xchg_dummy {
 	switch (size) {							\
 	case 1:								\
 		asm volatile("xchgb %b0,%1"				\
-			     : "=q" (__x)				\
-			     : "m" (*__xg(ptr)), "0" (__x)		\
+			     : "=q" (__x), "+m" (*__xg(ptr))		\
+			     : "0" (__x)				\
 			     : "memory");				\
 		break;							\
 	case 2:								\
 		asm volatile("xchgw %w0,%1"				\
-			     : "=r" (__x)				\
-			     : "m" (*__xg(ptr)), "0" (__x)		\
+			     : "=r" (__x), "+m" (*__xg(ptr))		\
+			     : "0" (__x)				\
 			     : "memory");				\
 		break;							\
 	case 4:								\
 		asm volatile("xchgl %0,%1"				\
-			     : "=r" (__x)				\
-			     : "m" (*__xg(ptr)), "0" (__x)		\
+			     : "=r" (__x), "+m" (*__xg(ptr))		\
+			     : "0" (__x)				\
 			     : "memory");				\
 		break;							\
 	default:							\
@@ -70,14 +70,14 @@ static inline void __set_64bit(unsigned long long *ptr,
 			       unsigned int low, unsigned int high)
 {
 	asm volatile("\n1:\t"
-		     "movl (%0), %%eax\n\t"
-		     "movl 4(%0), %%edx\n\t"
-		     LOCK_PREFIX "cmpxchg8b (%0)\n\t"
+		     "movl (%1), %%eax\n\t"
+		     "movl 4(%1), %%edx\n\t"
+		     LOCK_PREFIX "cmpxchg8b (%1)\n\t"
 		     "jnz 1b"
-		     : /* no outputs */
-		     : "D"(ptr),
-		       "b"(low),
-		       "c"(high)
+		     : "=m" (*ptr)
+		     : "D" (ptr),
+		       "b" (low),
+		       "c" (high)
 		     : "ax", "dx", "memory");
 }
 
@@ -121,21 +121,21 @@ extern void __cmpxchg_wrong_size(void);
 	__typeof__(*(ptr)) __new = (new);				\
 	switch (size) {							\
 	case 1:								\
-		asm volatile(lock "cmpxchgb %b1,%2"			\
-			     : "=a"(__ret)				\
-			     : "q"(__new), "m"(*__xg(ptr)), "0"(__old)	\
+		asm volatile(lock "cmpxchgb %b2,%1"			\
+			     : "=a" (__ret), "+m" (*__xg(ptr))		\
+			     : "q" (__new), "0" (__old)			\
 			     : "memory");				\
 		break;							\
 	case 2:								\
-		asm volatile(lock "cmpxchgw %w1,%2"			\
-			     : "=a"(__ret)				\
-			     : "r"(__new), "m"(*__xg(ptr)), "0"(__old)	\
+		asm volatile(lock "cmpxchgw %w2,%1"			\
+			     : "=a" (__ret), "+m" (*__xg(ptr))		\
+			     : "r" (__new), "0" (__old)			\
 			     : "memory");				\
 		break;							\
 	case 4:								\
-		asm volatile(lock "cmpxchgl %1,%2"			\
-			     : "=a"(__ret)				\
-			     : "r"(__new), "m"(*__xg(ptr)), "0"(__old)	\
+		asm volatile(lock "cmpxchgl %2,%1"			\
+			     : "=a" (__ret), "+m" (*__xg(ptr))		\
+			     : "r" (__new), "0" (__old)			\
 			     : "memory");				\
 		break;							\
 	default:							\
@@ -180,12 +180,12 @@ static inline unsigned long long __cmpxchg64(volatile void *ptr,
 					     unsigned long long new)
 {
 	unsigned long long prev;
-	asm volatile(LOCK_PREFIX "cmpxchg8b %3"
-		     : "=A"(prev)
-		     : "b"((unsigned long)new),
-		       "c"((unsigned long)(new >> 32)),
-		       "m"(*__xg(ptr)),
-		       "0"(old)
+	asm volatile(LOCK_PREFIX "cmpxchg8b %1"
+		     : "=A" (prev),
+		       "+m" (*__xg(ptr))
+		     : "b" ((unsigned long)new),
+		       "c" ((unsigned long)(new >> 32)),
+		       "0" (old)
 		     : "memory");
 	return prev;
 }
@@ -195,12 +195,12 @@ static inline unsigned long long __cmpxchg64_local(volatile void *ptr,
 						   unsigned long long new)
 {
 	unsigned long long prev;
-	asm volatile("cmpxchg8b %3"
-		     : "=A"(prev)
-		     : "b"((unsigned long)new),
-		       "c"((unsigned long)(new >> 32)),
-		       "m"(*__xg(ptr)),
-		       "0"(old)
+	asm volatile("cmpxchg8b %1"
+		     : "=A" (prev),
+		       "+m" (*__xg(ptr))
+		     : "b" ((unsigned long)new),
+		       "c" ((unsigned long)(new >> 32)),
+		       "0" (old)
 		     : "memory");
 	return prev;
 }
arch/x86/include/asm/cmpxchg_64.h +20 -20
index 485ae41..b92f147 100644
@@ -26,26 +26,26 @@ extern void __cmpxchg_wrong_size(void);
 	switch (size) {							\
 	case 1:								\
 		asm volatile("xchgb %b0,%1"				\
-			     : "=q" (__x)				\
-			     : "m" (*__xg(ptr)), "0" (__x)		\
+			     : "=q" (__x), "+m" (*__xg(ptr))		\
+			     : "0" (__x)				\
 			     : "memory");				\
 		break;							\
 	case 2:								\
 		asm volatile("xchgw %w0,%1"				\
-			     : "=r" (__x)				\
-			     : "m" (*__xg(ptr)), "0" (__x)		\
+			     : "=r" (__x), "+m" (*__xg(ptr))		\
+			     : "0" (__x)				\
 			     : "memory");				\
 		break;							\
 	case 4:								\
 		asm volatile("xchgl %k0,%1"				\
-			     : "=r" (__x)				\
-			     : "m" (*__xg(ptr)), "0" (__x)		\
+			     : "=r" (__x), "+m" (*__xg(ptr))		\
+			     : "0" (__x)				\
 			     : "memory");				\
 		break;							\
 	case 8:								\
 		asm volatile("xchgq %0,%1"				\
-			     : "=r" (__x)				\
-			     : "m" (*__xg(ptr)), "0" (__x)		\
+			     : "=r" (__x), "+m" (*__xg(ptr))		\
+			     : "0" (__x)				\
 			     : "memory");				\
 		break;							\
 	default:							\
@@ -71,27 +71,27 @@ extern void __cmpxchg_wrong_size(void);
 	__typeof__(*(ptr)) __new = (new);				\
 	switch (size) {							\
 	case 1:								\
-		asm volatile(lock "cmpxchgb %b1,%2"			\
-			     : "=a"(__ret)				\
-			     : "q"(__new), "m"(*__xg(ptr)), "0"(__old)	\
+		asm volatile(lock "cmpxchgb %b2,%1"			\
+			     : "=a" (__ret), "+m" (*__xg(ptr))		\
+			     : "q" (__new), "0" (__old)			\
 			     : "memory");				\
 		break;							\
 	case 2:								\
-		asm volatile(lock "cmpxchgw %w1,%2"			\
-			     : "=a"(__ret)				\
-			     : "r"(__new), "m"(*__xg(ptr)), "0"(__old)	\
+		asm volatile(lock "cmpxchgw %w2,%1"			\
+			     : "=a" (__ret), "+m" (*__xg(ptr))		\
+			     : "r" (__new), "0" (__old)			\
 			     : "memory");				\
 		break;							\
 	case 4:								\
-		asm volatile(lock "cmpxchgl %k1,%2"			\
-			     : "=a"(__ret)				\
-			     : "r"(__new), "m"(*__xg(ptr)), "0"(__old)	\
+		asm volatile(lock "cmpxchgl %k2,%1"			\
+			     : "=a" (__ret), "+m" (*__xg(ptr))		\
+			     : "r" (__new), "0" (__old)			\
 			     : "memory");				\
 		break;							\
 	case 8:								\
-		asm volatile(lock "cmpxchgq %1,%2"			\
-			     : "=a"(__ret)				\
-			     : "r"(__new), "m"(*__xg(ptr)), "0"(__old)	\
+		asm volatile(lock "cmpxchgq %2,%1"			\
+			     : "=a" (__ret), "+m" (*__xg(ptr))		\
+			     : "r" (__new), "0" (__old)			\
 			     : "memory");				\
 		break;							\
 	default:							\
#410 lore raw

Re: [tip:x86/urgent] x86: Add memory modify constraints to xchg() and cmpxchg()

Quoted 2 lines · tip-bot for H. Peter Anvin

x86: Add memory modify constraints to xchg() and cmpxchg()

Ack. I assume this doesn't really change the code generated? At least not with a gcc that honors the whole memory clobber thing properly?

I also suspect that we can/should get rid of the __xg() thing - it was there just to make sure gcc didn't see the memory read as a single word and tried to optimize it. With the "+m" it probably doesn't matter any more (don't know if it ever did)

Linus

#411 lore raw

Re: [tip:x86/urgent] x86: Add memory modify constraints to xchg() and cmpxchg()

Quoted 7 lines · Linus Torvalds
Quoted 2 lines · tip-bot for H. Peter Anvin

x86: Add memory modify constraints to xchg() and cmpxchg()

Ack. I assume this doesn't really change the code generated? At least not with a gcc that honors the whole memory clobber thing properly?

I didn't do a binary A:B comparison, on the assumption it would preturb the code too much to be equal, but I guess it would be a good idea to at least try.

Quoted 4 lines

I also suspect that we can/should get rid of the __xg() thing - it was there just to make sure gcc didn't see the memory read as a single word and tried to optimize it. With the "+m" it probably doesn't matter any more (don't know if it ever did)

"+m" would still see as a single word, but the __xg() thing should be obsoleted by asm volatile + "memory", neither of which were in the 1.3.11 version.

-hpa

Signature · 2 lines
H. Peter Anvin, Intel Open Source Technology Center
I work for Intel.  I don't speak on their behalf.
#412 lore raw

Re: [tip:x86/urgent] x86: Add memory modify constraints to xchg() and cmpxchg()

In reply to Linus Torvalds
Quoted 5 lines · Linus Torvalds
Quoted 2 lines · tip-bot for H. Peter Anvin

x86: Add memory modify constraints to xchg() and cmpxchg()

Quoted 8 lines

Ack. I assume this doesn't really change the code generated? At least not with a gcc that honors the whole memory clobber thing properly?

I also suspect that we can/should get rid of the __xg() thing - it was there just to make sure gcc didn't see the memory read as a single word and tried to optimize it. With the "+m" it probably doesn't matter any more (don't know if it ever did)

For what it's worth, it fairly heavily preturbs code around __set_64bit(), which implies it actually does something useful in that case. The rest of the code looks similar enough.

-hpa

#413 lore raw

[tip:x86/asm] x86, asm: Clean up and simplify <asm/cmpxchg.h>

In reply to Linus Torvalds
Commit-ID:  4532b305e8f0c238dd73048068ff8a6dd1380291
Gitweb:     http://git.kernel.org/tip/4532b305e8f0c238dd73048068ff8a6dd1380291
Author:     H. Peter Anvin <[email protected]>
AuthorDate: Wed, 28 Jul 2010 15:18:35 -0700
Committer:  H. Peter Anvin <[email protected]>
CommitDate: Wed, 28 Jul 2010 15:24:09 -0700

x86, asm: Clean up and simplify <asm/cmpxchg.h>

Remove the __xg() hack to create a memory barrier near xchg and cmpxchg; it has been there since 1.3.11 but should not be necessary with "asm volatile" and a "memory" clobber, neither of which were there in the original implementation.

However, we *should* make this a volatile reference.

LKML-Reference: <[email protected]>

---
 arch/x86/include/asm/cmpxchg_32.h |   75 ++++++++++++++++++++----------------
 arch/x86/include/asm/cmpxchg_64.h |   61 ++++++++++++++++++++---------
 2 files changed, 84 insertions(+), 52 deletions(-)
arch/x86/include/asm/cmpxchg_32.h +42 -33
index 20955ea..f5bd1fd 100644
@@ -11,38 +11,42 @@
 extern void __xchg_wrong_size(void);
 
 /*
- * Note: no "lock" prefix even on SMP: xchg always implies lock anyway
- * Note 2: xchg has side effect, so that attribute volatile is necessary,
- *	  but generally the primitive is invalid, *ptr is output argument. --ANK
+ * Note: no "lock" prefix even on SMP: xchg always implies lock anyway.
+ * Since this is generally used to protect other memory information, we
+ * use "asm volatile" and "memory" clobbers to prevent gcc from moving
+ * information around.
  */
-
-struct __xchg_dummy {
-	unsigned long a[100];
-};
-#define __xg(x) ((struct __xchg_dummy *)(x))
-
 #define __xchg(x, ptr, size)						\
 ({									\
 	__typeof(*(ptr)) __x = (x);					\
 	switch (size) {							\
 	case 1:								\
-		asm volatile("xchgb %b0,%1"				\
-			     : "=q" (__x), "+m" (*__xg(ptr))		\
+	{								\
+		volatile u8 *__ptr = (volatile u8 *)(ptr);		\
+		asm volatile("xchgb %0,%1"				\
+			     : "=q" (__x), "+m" (*__ptr)		\
 			     : "0" (__x)				\
 			     : "memory");				\
 		break;							\
+	}								\
 	case 2:								\
-		asm volatile("xchgw %w0,%1"				\
-			     : "=r" (__x), "+m" (*__xg(ptr))		\
+	{								\
+		volatile u16 *__ptr = (volatile u16 *)(ptr);		\
+		asm volatile("xchgw %0,%1"				\
+			     : "=r" (__x), "+m" (*__ptr)		\
 			     : "0" (__x)				\
 			     : "memory");				\
 		break;							\
+	}								\
 	case 4:								\
+	{								\
+		volatile u32 *__ptr = (volatile u32 *)(ptr);		\
 		asm volatile("xchgl %0,%1"				\
-			     : "=r" (__x), "+m" (*__xg(ptr))		\
+			     : "=r" (__x), "+m" (*__ptr)		\
 			     : "0" (__x)				\
 			     : "memory");				\
 		break;							\
+	}								\
 	default:							\
 		__xchg_wrong_size();					\
 	}								\
@@ -94,23 +98,32 @@ extern void __cmpxchg_wrong_size(void);
 	__typeof__(*(ptr)) __new = (new);				\
 	switch (size) {							\
 	case 1:								\
-		asm volatile(lock "cmpxchgb %b2,%1"			\
-			     : "=a" (__ret), "+m" (*__xg(ptr))		\
+	{								\
+		volatile u8 *__ptr = (volatile u8 *)(ptr);		\
+		asm volatile(lock "cmpxchgb %2,%1"			\
+			     : "=a" (__ret), "+m" (*__ptr)		\
 			     : "q" (__new), "0" (__old)			\
 			     : "memory");				\
 		break;							\
+	}								\
 	case 2:								\
-		asm volatile(lock "cmpxchgw %w2,%1"			\
-			     : "=a" (__ret), "+m" (*__xg(ptr))		\
+	{								\
+		volatile u16 *__ptr = (volatile u16 *)(ptr);		\
+		asm volatile(lock "cmpxchgw %2,%1"			\
+			     : "=a" (__ret), "+m" (*__ptr)		\
 			     : "r" (__new), "0" (__old)			\
 			     : "memory");				\
 		break;							\
+	}								\
 	case 4:								\
+	{								\
+		volatile u32 *__ptr = (volatile u32 *)(ptr);		\
 		asm volatile(lock "cmpxchgl %2,%1"			\
-			     : "=a" (__ret), "+m" (*__xg(ptr))		\
+			     : "=a" (__ret), "+m" (*__ptr)		\
 			     : "r" (__new), "0" (__old)			\
 			     : "memory");				\
 		break;							\
+	}								\
 	default:							\
 		__cmpxchg_wrong_size();					\
 	}								\
@@ -148,31 +161,27 @@ extern void __cmpxchg_wrong_size(void);
 					       (unsigned long long)(n)))
 #endif
 
-static inline unsigned long long __cmpxchg64(volatile void *ptr,
-					     unsigned long long old,
-					     unsigned long long new)
+static inline u64 __cmpxchg64(volatile u64 *ptr, u64 old, u64 new)
 {
-	unsigned long long prev;
+	u64 prev;
 	asm volatile(LOCK_PREFIX "cmpxchg8b %1"
 		     : "=A" (prev),
-		       "+m" (*__xg(ptr))
-		     : "b" ((unsigned long)new),
-		       "c" ((unsigned long)(new >> 32)),
+		       "+m" (*ptr)
+		     : "b" ((u32)new),
+		       "c" ((u32)(new >> 32)),
 		       "0" (old)
 		     : "memory");
 	return prev;
 }
 
-static inline unsigned long long __cmpxchg64_local(volatile void *ptr,
-						   unsigned long long old,
-						   unsigned long long new)
+static inline u64 __cmpxchg64_local(volatile u64 *ptr, u64 old, u64 new)
 {
-	unsigned long long prev;
+	u64 prev;
 	asm volatile("cmpxchg8b %1"
 		     : "=A" (prev),
-		       "+m" (*__xg(ptr))
-		     : "b" ((unsigned long)new),
-		       "c" ((unsigned long)(new >> 32)),
+		       "+m" (*ptr)
+		     : "b" ((u32)new),
+		       "c" ((u32)(new >> 32)),
 		       "0" (old)
 		     : "memory");
 	return prev;
arch/x86/include/asm/cmpxchg_64.h +42 -19

117 lines not on this page · raw message

#414 lore raw

[tip:x86/asm] x86, asm: Move cmpxchg emulation code to arch/x86/lib

In reply to Linus Torvalds
Commit-ID:  90c8f92f5c807807ca74d5f2f313794925174e6b
Gitweb:     http://git.kernel.org/tip/90c8f92f5c807807ca74d5f2f313794925174e6b
Author:     H. Peter Anvin <[email protected]>
AuthorDate: Wed, 28 Jul 2010 16:53:49 -0700
Committer:  H. Peter Anvin <[email protected]>
CommitDate: Wed, 28 Jul 2010 16:53:49 -0700

x86, asm: Move cmpxchg emulation code to arch/x86/lib

Move cmpxchg emulation code from arch/x86/kernel/cpu (which is otherwise CPU identification) to arch/x86/lib, where other emulation code lives already.

LKML-Reference: <[email protected]>

---
 arch/x86/kernel/cpu/Makefile           |    2 +-
 arch/x86/lib/Makefile                  |    1 +
 arch/x86/{kernel/cpu => lib}/cmpxchg.c |    0
 3 files changed, 2 insertions(+), 1 deletions(-)
arch/x86/kernel/cpu/Makefile +1 -1
index 3a785da..c47c439 100644
@@ -16,7 +16,7 @@ obj-y			:= intel_cacheinfo.o addon_cpuid_features.o
 obj-y			+= proc.o capflags.o powerflags.o common.o
 obj-y			+= vmware.o hypervisor.o sched.o mshyperv.o
 
-obj-$(CONFIG_X86_32)	+= bugs.o cmpxchg.o
+obj-$(CONFIG_X86_32)	+= bugs.o
 obj-$(CONFIG_X86_64)	+= bugs_64.o
 
 obj-$(CONFIG_CPU_SUP_INTEL)		+= intel.o
arch/x86/lib/Makefile +1 -0
index f871e04..e10cf07 100644
@@ -30,6 +30,7 @@ ifeq ($(CONFIG_X86_32),y)
         lib-y += checksum_32.o
         lib-y += strstr_32.o
         lib-y += semaphore_32.o string_32.o
+        lib-y += cmpxchg.o
 ifneq ($(CONFIG_X86_CMPXCHG64),y)
         lib-y += cmpxchg8b_emu.o atomic64_386_32.o
 endif
arch/x86/lib/cmpxchg.c renamed from arch/x86/kernel/cpu/cmpxchg.c +0 -0
similarity index 100%
rename from arch/x86/kernel/cpu/cmpxchg.c
rename to arch/x86/lib/cmpxchg.c
#415 lore raw

[tip:x86/asm] x86, asm: Merge cmpxchg_486_u64() and cmpxchg8b_emu()

In reply to Linus Torvalds
Commit-ID:  a378d9338e8dde78314b3a6ae003de351936c729
Gitweb:     http://git.kernel.org/tip/a378d9338e8dde78314b3a6ae003de351936c729
Author:     H. Peter Anvin <[email protected]>
AuthorDate: Wed, 28 Jul 2010 17:05:11 -0700
Committer:  H. Peter Anvin <[email protected]>
CommitDate: Wed, 28 Jul 2010 17:05:11 -0700

x86, asm: Merge cmpxchg_486_u64() and cmpxchg8b_emu()

We have two functions for doing exactly the same thing -- emulating cmpxchg8b on 486 and older hardware -- with different calling conventions, and yet doing the same thing. Drop the C version and use the assembly version, via alternatives, for both the local and non-local versions of cmpxchg8b.

LKML-Reference: <[email protected]>

---
 arch/x86/include/asm/cmpxchg_32.h |   30 ++++++++++++++----------------
 arch/x86/lib/cmpxchg.c            |   18 ------------------
 2 files changed, 14 insertions(+), 34 deletions(-)
arch/x86/include/asm/cmpxchg_32.h +14 -16
index f5bd1fd..284a6e8 100644
@@ -246,8 +246,6 @@ static inline unsigned long cmpxchg_386(volatile void *ptr, unsigned long old,
  * to simulate the cmpxchg8b on the 80386 and 80486 CPU.
  */
 
-extern unsigned long long cmpxchg_486_u64(volatile void *, u64, u64);
-
 #define cmpxchg64(ptr, o, n)					\
 ({								\
 	__typeof__(*(ptr)) __ret;				\
@@ -265,20 +263,20 @@ extern unsigned long long cmpxchg_486_u64(volatile void *, u64, u64);
 	__ret; })
 
 
-
-#define cmpxchg64_local(ptr, o, n)					\
-({									\
-	__typeof__(*(ptr)) __ret;					\
-	if (likely(boot_cpu_data.x86 > 4))				\
-		__ret = (__typeof__(*(ptr)))__cmpxchg64_local((ptr),	\
-				(unsigned long long)(o),		\
-				(unsigned long long)(n));		\
-	else								\
-		__ret = (__typeof__(*(ptr)))cmpxchg_486_u64((ptr),	\
-				(unsigned long long)(o),		\
-				(unsigned long long)(n));		\
-	__ret;								\
-})
+#define cmpxchg64_local(ptr, o, n)				\
+({								\
+	__typeof__(*(ptr)) __ret;				\
+	__typeof__(*(ptr)) __old = (o);				\
+	__typeof__(*(ptr)) __new = (n);				\
+	alternative_io("call cmpxchg8b_emu",			\
+		       "cmpxchg8b (%%esi)" ,			\
+		       X86_FEATURE_CX8,				\
+		       "=A" (__ret),				\
+		       "S" ((ptr)), "0" (__old),		\
+		       "b" ((unsigned int)__new),		\
+		       "c" ((unsigned int)(__new>>32))		\
+		       : "memory");				\
+	__ret; })
 
 #endif
 
arch/x86/lib/cmpxchg.c +0 -18
index 2056ccf..5d619f6 100644
@@ -52,21 +52,3 @@ unsigned long cmpxchg_386_u32(volatile void *ptr, u32 old, u32 new)
 }
 EXPORT_SYMBOL(cmpxchg_386_u32);
 #endif
-
-#ifndef CONFIG_X86_CMPXCHG64
-unsigned long long cmpxchg_486_u64(volatile void *ptr, u64 old, u64 new)
-{
-	u64 prev;
-	unsigned long flags;
-
-	/* Poor man's cmpxchg8b for 386 and 486. Unsuitable for SMP */
-	local_irq_save(flags);
-	prev = *(u64 *)ptr;
-	if (prev == old)
-		*(u64 *)ptr = new;
-	local_irq_restore(flags);
-	return prev;
-}
-EXPORT_SYMBOL(cmpxchg_486_u64);
-#endif
-
#416 lore raw

Re: [tip:x86/urgent] x86: Add memory modify constraints to xchg() and cmpxchg()

In reply to tip-bot for H. Peter Anvin
Quoted 8 lines · tip-bot for H. Peter Anvin
Commit-ID:  113fc5a6e8c2288619ff7e8187a6f556b7e0d372
Gitweb:     http://git.kernel.org/tip/113fc5a6e8c2288619ff7e8187a6f556b7e0d372
Author:     H. Peter Anvin<[email protected]>
AuthorDate: Tue, 27 Jul 2010 17:01:49 -0700
Committer:  H. Peter Anvin<[email protected]>
CommitDate: Tue, 27 Jul 2010 17:14:02 -0700

x86: Add memory modify constraints to xchg() and cmpxchg()

Here's the 2.6.32 version for stable.

J

From: Jeremy Fitzhardinge<[email protected]>
Date: Tue, 27 Jul 2010 23:03:58 -0700
Subject: [PATCH] x86: Add memory modify constraints to xchg() and cmpxchg()

xchg() and cmpxchg() modify their memory operands, not merely read them. For some versions of gcc the "memory" clobber has apparently dealt with the situation, but not for all.

Also adds the missing 8-byte case for __sync_cmpxchg().

Based on HPA's patch.

Cc "H. Peter Anvin"<[email protected]>
Cc Stable Kernel<[email protected]>
arch/x86/include/asm/cmpxchg_32.h +42 -44
index ee1931b..5af5051 100644
@@ -34,12 +34,12 @@ static inline void __set_64bit(unsigned long long *ptr,
 			       unsigned int low, unsigned int high)
 {
 	asm volatile("\n1:\t"
-		     "movl (%0), %%eax\n\t"
-		     "movl 4(%0), %%edx\n\t"
-		     LOCK_PREFIX "cmpxchg8b (%0)\n\t"
+		     "movl (%1), %%eax\n\t"
+		     "movl 4(%1), %%edx\n\t"
+		     LOCK_PREFIX "cmpxchg8b %0\n\t"
 		     "jnz 1b"
-		     : /* no outputs */
-		     : "D"(ptr),
+		     : "=m"(*ptr)
+		     : "D" (ptr),
 		       "b"(low),
 		       "c"(high)
 		     : "ax", "dx", "memory");
@@ -82,20 +82,20 @@ static inline unsigned long __xchg(unsigned long x, volatile void *ptr,
 	switch (size) {
 	case 1:
 		asm volatile("xchgb %b0,%1"
-			     : "=q" (x)
-			     : "m" (*__xg(ptr)), "0" (x)
+			     : "=q" (x), "+m" (*__xg(ptr))
+			     : "0" (x)
 			     : "memory");
 		break;
 	case 2:
 		asm volatile("xchgw %w0,%1"
-			     : "=r" (x)
-			     : "m" (*__xg(ptr)), "0" (x)
+			     : "=r" (x), "+m" (*__xg(ptr))
+			     : "0" (x)
 			     : "memory");
 		break;
 	case 4:
 		asm volatile("xchgl %0,%1"
-			     : "=r" (x)
-			     : "m" (*__xg(ptr)), "0" (x)
+			     : "=r" (x), "+m" (*__xg(ptr))
+			     : "0" (x)
 			     : "memory");
 		break;
 	}
@@ -139,21 +139,21 @@ static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old,
 	unsigned long prev;
 	switch (size) {
 	case 1:
-		asm volatile(LOCK_PREFIX "cmpxchgb %b1,%2"
-			     : "=a"(prev)
-			     : "q"(new), "m"(*__xg(ptr)), "0"(old)
+		asm volatile(LOCK_PREFIX "cmpxchgb %b2,%1"
+			     : "=a"(prev), "+m"(*__xg(ptr))
+			     : "q"(new), "0"(old)
 			     : "memory");
 		return prev;
 	case 2:
-		asm volatile(LOCK_PREFIX "cmpxchgw %w1,%2"
-			     : "=a"(prev)
-			     : "r"(new), "m"(*__xg(ptr)), "0"(old)
+		asm volatile(LOCK_PREFIX "cmpxchgw %w2,%1"
+			     : "=a"(prev), "+m"(*__xg(ptr))
+			     : "r"(new), "0"(old)
 			     : "memory");
 		return prev;
 	case 4:
-		asm volatile(LOCK_PREFIX "cmpxchgl %1,%2"
-			     : "=a"(prev)
-			     : "r"(new), "m"(*__xg(ptr)), "0"(old)
+		asm volatile(LOCK_PREFIX "cmpxchgl %2,%1"
+			     : "=a"(prev), "+m"(*__xg(ptr))
+			     : "r"(new), "0"(old)
 			     : "memory");
 		return prev;
 	}
@@ -172,21 +172,21 @@ static inline unsigned long __sync_cmpxchg(volatile void *ptr,
 	unsigned long prev;
 	switch (size) {
 	case 1:
-		asm volatile("lock; cmpxchgb %b1,%2"
-			     : "=a"(prev)
-			     : "q"(new), "m"(*__xg(ptr)), "0"(old)
+		asm volatile("lock; cmpxchgb %b2,%1"
+			     : "=a"(prev), "+m"(*__xg(ptr))
+			     : "q"(new), "0"(old)
 			     : "memory");
 		return prev;
 	case 2:
-		asm volatile("lock; cmpxchgw %w1,%2"
-			     : "=a"(prev)
-			     : "r"(new), "m"(*__xg(ptr)), "0"(old)
+		asm volatile("lock; cmpxchgw %w2,%1"
+			     : "=a"(prev), "+m"(*__xg(ptr))
+			     : "r"(new), "0"(old)
 			     : "memory");
 		return prev;
 	case 4:
-		asm volatile("lock; cmpxchgl %1,%2"
-			     : "=a"(prev)
-			     : "r"(new), "m"(*__xg(ptr)), "0"(old)
+		asm volatile("lock; cmpxchgl %2,%1"
+			     : "=a"(prev), "+m"(*__xg(ptr))
+			     : "r"(new), "0"(old)
 			     : "memory");
 		return prev;
 	}
@@ -200,21 +200,21 @@ static inline unsigned long __cmpxchg_local(volatile void *ptr,
 	unsigned long prev;
 	switch (size) {
 	case 1:
-		asm volatile("cmpxchgb %b1,%2"
-			     : "=a"(prev)
-			     : "q"(new), "m"(*__xg(ptr)), "0"(old)
+		asm volatile("cmpxchgb %b2,%1"
+			     : "=a"(prev), "+m"(*__xg(ptr))
+			     : "q"(new), "0"(old)
 			     : "memory");
 		return prev;
 	case 2:
-		asm volatile("cmpxchgw %w1,%2"
-			     : "=a"(prev)
-			     : "r"(new), "m"(*__xg(ptr)), "0"(old)
+		asm volatile("cmpxchgw %w2,%1"
+			     : "=a"(prev), "+m"(*__xg(ptr))
+			     : "r"(new), "0"(old)
 			     : "memory");
 		return prev;
 	case 4:
-		asm volatile("cmpxchgl %1,%2"
-			     : "=a"(prev)
-			     : "r"(new), "m"(*__xg(ptr)), "0"(old)
+		asm volatile("cmpxchgl %2,%1"
+			     : "=a"(prev), "+m"(*__xg(ptr))
+			     : "r"(new), "0"(old)
 			     : "memory");
 		return prev;
 	}
@@ -226,11 +226,10 @@ static inline unsigned long long __cmpxchg64(volatile void *ptr,
 					     unsigned long long new)
 {
 	unsigned long long prev;
-	asm volatile(LOCK_PREFIX "cmpxchg8b %3"
-		     : "=A"(prev)
+	asm volatile(LOCK_PREFIX "cmpxchg8b %1"
+		     : "=A"(prev), "+m" (*__xg(ptr))
 		     : "b"((unsigned long)new),
 		       "c"((unsigned long)(new>>  32)),
-		       "m"(*__xg(ptr)),
 		       "0"(old)
 		     : "memory");
 	return prev;
@@ -241,11 +240,10 @@ static inline unsigned long long __cmpxchg64_local(volatile void *ptr,
 						   unsigned long long new)
 {
 	unsigned long long prev;
-	asm volatile("cmpxchg8b %3"
-		     : "=A"(prev)
+	asm volatile("cmpxchg8b %1"
+		     : "=A"(prev), "+m"(*__xg(ptr))
 		     : "b"((unsigned long)new),
 		       "c"((unsigned long)(new>>  32)),
-		       "m"(*__xg(ptr)),
 		       "0"(old)
 		     : "memory");
 	return prev;
arch/x86/include/asm/cmpxchg_64.h +47 -41

148 lines not on this page · raw message

author
#417 lore raw

Re: [stable] [tip:x86/urgent] x86: Add memory modify constraints to xchg() and cmpxchg()

Quoted 11 lines · Jeremy Fitzhardinge
Quoted 8 lines · tip-bot for H. Peter Anvin
Commit-ID:  113fc5a6e8c2288619ff7e8187a6f556b7e0d372
Gitweb:     http://git.kernel.org/tip/113fc5a6e8c2288619ff7e8187a6f556b7e0d372
Author:     H. Peter Anvin<[email protected]>
AuthorDate: Tue, 27 Jul 2010 17:01:49 -0700
Committer:  H. Peter Anvin<[email protected]>
CommitDate: Tue, 27 Jul 2010 17:14:02 -0700

x86: Add memory modify constraints to xchg() and cmpxchg()

Here's the 2.6.32 version for stable.

Thanks, I'll queue it up when it hits Linus's tree.

greg k-h

#418 lore raw

Re: [stable] [tip:x86/urgent] x86: Add memory modify constraints to xchg() and cmpxchg()

Hello,

2.6.32.21 does not boot on my HP Compaq nx7300. I bisected it to this patch:

Quoted 9 lines · Greg KH
Quoted 8 lines · Jeremy Fitzhardinge
Quoted 7 lines · tip-bot for H. Peter Anvin
Commit-ID:  113fc5a6e8c2288619ff7e8187a6f556b7e0d372
Gitweb:     http://git.kernel.org/tip/113fc5a6e8c2288619ff7e8187a6f556b7e0d372
Author:     H. Peter Anvin<[email protected]>
AuthorDate: Tue, 27 Jul 2010 17:01:49 -0700
Committer:  H. Peter Anvin<[email protected]>
CommitDate: Tue, 27 Jul 2010 17:14:02 -0700
Quoted 5 lines
Quoted 3 lines
Quoted 1 line

x86: Add memory modify constraints to xchg() and cmpxchg()

Here's the 2.6.32 version for stable.

Thanks, I'll queue it up when it hits Linus's tree.

Here's a video of the crash: http://store.lisk.in/tmp/09092010019.mp4
With boot_delay=30, it sometimes just reboots and sometimes prints the trace. Without it, it always prints the trace. The crash occurs during the initialization of intel-agp (which explains why I can't reproduce it in qemu). More details in the video.

The system boots and works just fine with 2.6.32.21 with the patch reverted. v2.6.36-rc3-185-gd56557a works fine as well, perhaps there were other fixes that didn't get to stable (e.g. 4532b30).

I'm compiling the kernel with the latest gcc in Debian (-dumpversion says 4.4.5, dpkg reports 4:4.4.4-2). Shall I post dmesg/lspci as well?

Since I have an easy workaround and other things to do, I won't spend time trying to backport those other fixes myself, but if you're going to fix this, I will help with testing.

Regards,

Signature · 1 line
Tomáš Janoušek, a.k.a. Liskni_si, http://work.lisk.in/
#419 lore raw

Re: [stable] [tip:x86/urgent] x86: Add memory modify constraints to xchg() and cmpxchg()

Quoted 30 lines · Tomáš Janoušek

Hello,

2.6.32.21 does not boot on my HP Compaq nx7300. I bisected it to this patch:

Quoted 9 lines · Greg KH
Quoted 8 lines · Jeremy Fitzhardinge
Quoted 7 lines · tip-bot for H. Peter Anvin
Commit-ID:  113fc5a6e8c2288619ff7e8187a6f556b7e0d372
Gitweb:     http://git.kernel.org/tip/113fc5a6e8c2288619ff7e8187a6f556b7e0d372
Author:     H. Peter Anvin<[email protected]>
AuthorDate: Tue, 27 Jul 2010 17:01:49 -0700
Committer:  H. Peter Anvin<[email protected]>
CommitDate: Tue, 27 Jul 2010 17:14:02 -0700
Quoted 5 lines
Quoted 3 lines
Quoted 1 line

x86: Add memory modify constraints to xchg() and cmpxchg()

Here's the 2.6.32 version for stable.

Thanks, I'll queue it up when it hits Linus's tree.

Here's a video of the crash: http://store.lisk.in/tmp/09092010019.mp4
With boot_delay=30, it sometimes just reboots and sometimes prints the trace. Without it, it always prints the trace. The crash occurs during the initialization of intel-agp (which explains why I can't reproduce it in qemu). More details in the video.

The system boots and works just fine with 2.6.32.21 with the patch reverted. v2.6.36-rc3-185-gd56557a works fine as well, perhaps there were other fixes that didn't get to stable (e.g. 4532b30).

Quoted 7 lines

I'm compiling the kernel with the latest gcc in Debian (-dumpversion says 4.4.5, dpkg reports 4:4.4.4-2). Shall I post dmesg/lspci as well?

Since I have an easy workaround and other things to do, I won't spend time trying to backport those other fixes myself, but if you're going to fix this, I will help with testing.

Could you give us your .config and also what version of gcc and binutils is on your system?

-hpa

#420 lore raw

Re: [stable] [tip:x86/urgent] x86: Add memory modify constraints to xchg() and cmpxchg()

Hello,

Quoted 2 lines · H. Peter Anvin

Could you give us your .config and also what version of gcc and binutils is on your system?

http://store.lisk.in/tmp/.config.2.6.32.21-debug

$ ld -V
GNU ld (GNU Binutils for Debian) 2.20.1-system.20100303

(that's 2.20.1-12 in Debian testing)

$ cc -dumpversion
4.4.5

(that's 4:4.4.4-2 in Debian testing)

$ cat /proc/version 
Linux version 2.6.36-rc3-lis-00187-ga784c32 ([email protected]) (gcc version
4.4.5 20100728 (prerelease) (Debian 4.4.4-8) ) #103 SMP Thu Sep 9 16:40:09
CEST 2010

Regards,

Signature · 1 line
Tomáš Janoušek, a.k.a. Liskni_si, http://work.lisk.in/
#421 lore raw

Re: [stable] [tip:x86/urgent] x86: Add memory modify constraints to xchg() and cmpxchg()

In reply to Tomáš Janoušek
Quoted 5 lines

The system boots and works just fine with 2.6.32.21 with the patch reverted. v2.6.36-rc3-185-gd56557a works fine as well, perhaps there were other fixes that didn't get to stable (e.g. 4532b30).

I believe this needs 69309a05907546fb686b251d4ab041c26afe1e1d, which I think is being queued up for stable.

Could you try applying 69309a05907546fb686b251d4ab041c26afe1e1d and see if it solves your problem.

-hpa

#422 lore raw

Re: [stable] [tip:x86/urgent] x86: Add memory modify constraints to xchg() and cmpxchg()

Hello,

Quoted 9 lines · H. Peter Anvin
Quoted 3 lines

The system boots and works just fine with 2.6.32.21 with the patch reverted. v2.6.36-rc3-185-gd56557a works fine as well, perhaps there were other fixes that didn't get to stable (e.g. 4532b30).

I believe this needs 69309a05907546fb686b251d4ab041c26afe1e1d, which I think is being queued up for stable.

Could you try applying 69309a05907546fb686b251d4ab041c26afe1e1d and see if it solves your problem.

It does indeed. Thanks.

Signature · 1 line
Tomáš Janoušek, a.k.a. Liskni_si, http://work.lisk.in/
author
#423 lore raw

Re: [stable] [tip:x86/urgent] x86: Add memory modify constraints to xchg() and cmpxchg()

Quoted 7 lines · Tomáš Janoušek

Hello,

Quoted 4 lines · H. Peter Anvin
Quoted 3 lines

The system boots and works just fine with 2.6.32.21 with the patch reverted. v2.6.36-rc3-185-gd56557a works fine as well, perhaps there were other fixes that didn't get to stable (e.g. 4532b30).

Quoted 7 lines
Quoted 5 lines

I believe this needs 69309a05907546fb686b251d4ab041c26afe1e1d, which I think is being queued up for stable.

Could you try applying 69309a05907546fb686b251d4ab041c26afe1e1d and see if it solves your problem.

It does indeed. Thanks.

Hm, that patch doesn't apply to the latest .32-stable tree. Can someone provide me with a backported version so I make sure I get it correct?

thanks,

greg k-h

#424 lore raw

Re: [stable] [tip:x86/urgent] x86: Add memory modify constraints to xchg() and cmpxchg()

Hello,

Quoted 2 lines · Greg KH

Hm, that patch doesn't apply to the latest .32-stable tree. Can someone provide me with a backported version so I make sure I get it correct?

I'm attaching the one I used and tested.

Signature · 1 line
Tomáš Janoušek, a.k.a. Liskni_si, http://work.lisk.in/

From 48a45b4cd701520435188fcf9ef0c04e73c79172 Mon Sep 17 00:00:00 2001
From: H. Peter Anvin <[email protected]>
Date: Tue, 27 Jul 2010 23:29:52 -0700
Subject: [PATCH] x86, asm: Clean up and simplify set_64bit()

Clean up and simplify set_64bit(). This code is quite old (1.3.11) and contains a fair bit of auxilliary machinery that current versions of gcc handle just fine automatically. Worse, the auxilliary machinery can actually cause an unnecessary spill to memory.

Furthermore, the loading of the old value inside the loop in the 32-bit case is unnecessary: if the value doesn't match, the CMPXCHG8B instruction will already have loaded the "new previous" value for us.

Clean up the comment, too, and remove page references to obsolete versions of the Intel SDM.

LKML-Reference: <tip-*@vger.kernel.org>

---
 arch/x86/include/asm/cmpxchg_32.h |   65 +++++++++++--------------------------
 arch/x86/include/asm/cmpxchg_64.h |    4 +--
 2 files changed, 20 insertions(+), 49 deletions(-)
arch/x86/include/asm/cmpxchg_32.h +19 -46
index 5af5051..9873a5f 100644
@@ -17,60 +17,33 @@ struct __xchg_dummy {
 #define __xg(x) ((struct __xchg_dummy *)(x))
 
 /*
- * The semantics of XCHGCMP8B are a bit strange, this is why
- * there is a loop and the loading of %%eax and %%edx has to
- * be inside. This inlines well in most cases, the cached
- * cost is around ~38 cycles. (in the future we might want
- * to do an SIMD/3DNOW!/MMX/FPU 64-bit store here, but that
- * might have an implicit FPU-save as a cost, so it's not
- * clear which path to go.)
+ * CMPXCHG8B only writes to the target if we had the previous
+ * value in registers, otherwise it acts as a read and gives us the
+ * "new previous" value.  That is why there is a loop.  Preloading
+ * EDX:EAX is a performance optimization: in the common case it means
+ * we need only one locked operation.
  *
- * cmpxchg8b must be used with the lock prefix here to allow
- * the instruction to be executed atomically, see page 3-102
- * of the instruction set reference 24319102.pdf. We need
- * the reader side to see the coherent 64bit value.
+ * A SIMD/3DNOW!/MMX/FPU 64-bit store here would require at the very
+ * least an FPU save and/or %cr0.ts manipulation.
+ *
+ * cmpxchg8b must be used with the lock prefix here to allow the
+ * instruction to be executed atomically.  We need to have the reader
+ * side to see the coherent 64bit value.
  */
-static inline void __set_64bit(unsigned long long *ptr,
-			       unsigned int low, unsigned int high)
+static inline void set_64bit(volatile u64 *ptr, u64 value)
 {
+	u32 low  = value;
+	u32 high = value >> 32;
+	u64 prev = *ptr;
+
 	asm volatile("\n1:\t"
-		     "movl (%1), %%eax\n\t"
-		     "movl 4(%1), %%edx\n\t"
 		     LOCK_PREFIX "cmpxchg8b %0\n\t"
 		     "jnz 1b"
-		     : "=m"(*ptr)
-		     : "D" (ptr),
-		       "b"(low),
-		       "c"(high)
-		     : "ax", "dx", "memory");
-}
-
-static inline void __set_64bit_constant(unsigned long long *ptr,
-					unsigned long long value)
-{
-	__set_64bit(ptr, (unsigned int)value, (unsigned int)(value >> 32));
-}
-
-#define ll_low(x)	*(((unsigned int *)&(x)) + 0)
-#define ll_high(x)	*(((unsigned int *)&(x)) + 1)
-
-static inline void __set_64bit_var(unsigned long long *ptr,
-				   unsigned long long value)
-{
-	__set_64bit(ptr, ll_low(value), ll_high(value));
+		     : "=m" (*ptr), "+A" (prev)
+		     : "b" (low), "c" (high)
+		     : "memory");
 }
 
-#define set_64bit(ptr, value)			\
-	(__builtin_constant_p((value))		\
-	 ? __set_64bit_constant((ptr), (value))	\
-	 : __set_64bit_var((ptr), (value)))
-
-#define _set_64bit(ptr, value)						\
-	(__builtin_constant_p(value)					\
-	 ? __set_64bit(ptr, (unsigned int)(value),			\
-		       (unsigned int)((value) >> 32))			\
-	 : __set_64bit(ptr, ll_low((value)), ll_high((value))))
-
 /*
  * Note: no "lock" prefix even on SMP: xchg always implies lock anyway
  * Note 2: xchg has side effect, so that attribute volatile is necessary,
arch/x86/include/asm/cmpxchg_64.h +1 -3
index 1871cb0..e8cb051 100644
@@ -8,13 +8,11 @@
 
 #define __xg(x) ((volatile long *)(x))
 
-static inline void set_64bit(volatile unsigned long *ptr, unsigned long val)
+static inline void set_64bit(volatile u64 *ptr, u64 val)
 {
 	*ptr = val;
 }
 
-#define _set_64bit set_64bit
-
 /*
  * Note: no "lock" prefix even on SMP: xchg always implies lock anyway
  * Note 2: xchg has side effect, so that attribute volatile is necessary,
Signature · 1 line
1.7.1
author
#425 lore raw

Re: [stable] [tip:x86/urgent] x86: Add memory modify constraints to xchg() and cmpxchg()

Quoted 7 lines · Tomáš Janoušek

Hello,

Quoted 2 lines · Greg KH

Hm, that patch doesn't apply to the latest .32-stable tree. Can someone provide me with a backported version so I make sure I get it correct?

I'm attaching the one I used and tested.

That worked, thanks, I've queued it up now.

greg k-h

#426 lore raw

Re: [tip:x86/urgent] x86: Add memory modify constraints to xchg() and cmpxchg()

In reply to Jeremy Fitzhardinge
Quoted 10 lines · Jeremy Fitzhardinge
Quoted 8 lines
Commit-ID:  113fc5a6e8c2288619ff7e8187a6f556b7e0d372
Gitweb:     http://git.kernel.org/tip/113fc5a6e8c2288619ff7e8187a6f556b7e0d372
Author:     H. Peter Anvin<[email protected]>
AuthorDate: Tue, 27 Jul 2010 17:01:49 -0700
Committer:  H. Peter Anvin<[email protected]>
CommitDate: Tue, 27 Jul 2010 17:14:02 -0700

x86: Add memory modify constraints to xchg() and cmpxchg()

Here's the 2.6.32 version for stable.

Thanks a lot everyone. This patch resolves the issue for me on top of 2.6.32.17.

(I had some whitespace issue with applying the patch, so I've attached the cleaned up version in case it wasn't just me.)

Cheers,
Peter

Signature · 4 lines
                           |  .''`.  ** Debian GNU/Linux **
      Peter Palfrader      | : :' :      The  universal
 http://www.palfrader.org/ | `. `'      Operating System
                           |   `-    http://www.debian.org/

From f6fd342ddae3f7edecd0254e5c4e6795d4fba4a9 Mon Sep 17 00:00:00 2001
From: Jeremy Fitzhardinge <[email protected]>
Date: Tue, 27 Jul 2010 23:03:58 -0700
Subject: [PATCH] x86: Add memory modify constraints to xchg() and cmpxchg()

xchg() and cmpxchg() modify their memory operands, not merely read them. For some versions of gcc the "memory" clobber has apparently dealt with the situation, but not for all.

Also adds the missing 8-byte case for __sync_cmpxchg().

Based on HPA's patch.

Cc "H. Peter Anvin"<[email protected]>
Cc Stable Kernel<[email protected]>
---
 arch/x86/include/asm/cmpxchg_32.h |   86 +++++++++++++++++------------------
 arch/x86/include/asm/cmpxchg_64.h |   88 ++++++++++++++++++++-----------------
 2 files changed, 89 insertions(+), 85 deletions(-)
arch/x86/include/asm/cmpxchg_32.h +42 -44
index ee1931b..5af5051 100644
@@ -34,12 +34,12 @@ static inline void __set_64bit(unsigned long long *ptr,
 			       unsigned int low, unsigned int high)
 {
 	asm volatile("\n1:\t"
-		     "movl (%0), %%eax\n\t"
-		     "movl 4(%0), %%edx\n\t"
-		     LOCK_PREFIX "cmpxchg8b (%0)\n\t"
+		     "movl (%1), %%eax\n\t"
+		     "movl 4(%1), %%edx\n\t"
+		     LOCK_PREFIX "cmpxchg8b %0\n\t"
 		     "jnz 1b"
-		     : /* no outputs */
-		     : "D"(ptr),
+		     : "=m"(*ptr)
+		     : "D" (ptr),
 		       "b"(low),
 		       "c"(high)
 		     : "ax", "dx", "memory");
@@ -82,20 +82,20 @@ static inline unsigned long __xchg(unsigned long x, volatile void *ptr,
 	switch (size) {
 	case 1:
 		asm volatile("xchgb %b0,%1"
-			     : "=q" (x)
-			     : "m" (*__xg(ptr)), "0" (x)
+			     : "=q" (x), "+m" (*__xg(ptr))
+			     : "0" (x)
 			     : "memory");
 		break;
 	case 2:
 		asm volatile("xchgw %w0,%1"
-			     : "=r" (x)
-			     : "m" (*__xg(ptr)), "0" (x)
+			     : "=r" (x), "+m" (*__xg(ptr))
+			     : "0" (x)
 			     : "memory");
 		break;
 	case 4:
 		asm volatile("xchgl %0,%1"
-			     : "=r" (x)
-			     : "m" (*__xg(ptr)), "0" (x)
+			     : "=r" (x), "+m" (*__xg(ptr))
+			     : "0" (x)
 			     : "memory");
 		break;
 	}
@@ -139,21 +139,21 @@ static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old,
 	unsigned long prev;
 	switch (size) {
 	case 1:
-		asm volatile(LOCK_PREFIX "cmpxchgb %b1,%2"
-			     : "=a"(prev)
-			     : "q"(new), "m"(*__xg(ptr)), "0"(old)
+		asm volatile(LOCK_PREFIX "cmpxchgb %b2,%1"
+			     : "=a"(prev), "+m"(*__xg(ptr))
+			     : "q"(new), "0"(old)
 			     : "memory");
 		return prev;
 	case 2:
-		asm volatile(LOCK_PREFIX "cmpxchgw %w1,%2"
-			     : "=a"(prev)
-			     : "r"(new), "m"(*__xg(ptr)), "0"(old)
+		asm volatile(LOCK_PREFIX "cmpxchgw %w2,%1"
+			     : "=a"(prev), "+m"(*__xg(ptr))
+			     : "r"(new), "0"(old)
 			     : "memory");
 		return prev;
 	case 4:
-		asm volatile(LOCK_PREFIX "cmpxchgl %1,%2"
-			     : "=a"(prev)
-			     : "r"(new), "m"(*__xg(ptr)), "0"(old)
+		asm volatile(LOCK_PREFIX "cmpxchgl %2,%1"
+			     : "=a"(prev), "+m"(*__xg(ptr))
+			     : "r"(new), "0"(old)
 			     : "memory");
 		return prev;
 	}
@@ -172,21 +172,21 @@ static inline unsigned long __sync_cmpxchg(volatile void *ptr,
 	unsigned long prev;
 	switch (size) {
 	case 1:
-		asm volatile("lock; cmpxchgb %b1,%2"
-			     : "=a"(prev)
-			     : "q"(new), "m"(*__xg(ptr)), "0"(old)
+		asm volatile("lock; cmpxchgb %b2,%1"
+			     : "=a"(prev), "+m"(*__xg(ptr))
+			     : "q"(new), "0"(old)
 			     : "memory");
 		return prev;
 	case 2:
-		asm volatile("lock; cmpxchgw %w1,%2"
-			     : "=a"(prev)
-			     : "r"(new), "m"(*__xg(ptr)), "0"(old)
+		asm volatile("lock; cmpxchgw %w2,%1"
+			     : "=a"(prev), "+m"(*__xg(ptr))
+			     : "r"(new), "0"(old)
 			     : "memory");
 		return prev;
 	case 4:
-		asm volatile("lock; cmpxchgl %1,%2"
-			     : "=a"(prev)
-			     : "r"(new), "m"(*__xg(ptr)), "0"(old)
+		asm volatile("lock; cmpxchgl %2,%1"
+			     : "=a"(prev), "+m"(*__xg(ptr))
+			     : "r"(new), "0"(old)
 			     : "memory");
 		return prev;
 	}
@@ -200,21 +200,21 @@ static inline unsigned long __cmpxchg_local(volatile void *ptr,
 	unsigned long prev;
 	switch (size) {
 	case 1:
-		asm volatile("cmpxchgb %b1,%2"
-			     : "=a"(prev)
-			     : "q"(new), "m"(*__xg(ptr)), "0"(old)
+		asm volatile("cmpxchgb %b2,%1"
+			     : "=a"(prev), "+m"(*__xg(ptr))
+			     : "q"(new), "0"(old)
 			     : "memory");
 		return prev;
 	case 2:
-		asm volatile("cmpxchgw %w1,%2"
-			     : "=a"(prev)
-			     : "r"(new), "m"(*__xg(ptr)), "0"(old)
+		asm volatile("cmpxchgw %w2,%1"
+			     : "=a"(prev), "+m"(*__xg(ptr))
+			     : "r"(new), "0"(old)
 			     : "memory");
 		return prev;
 	case 4:
-		asm volatile("cmpxchgl %1,%2"
-			     : "=a"(prev)
-			     : "r"(new), "m"(*__xg(ptr)), "0"(old)
+		asm volatile("cmpxchgl %2,%1"
+			     : "=a"(prev), "+m"(*__xg(ptr))
+			     : "r"(new), "0"(old)
 			     : "memory");
 		return prev;
 	}
@@ -226,11 +226,10 @@ static inline unsigned long long __cmpxchg64(volatile void *ptr,
 					     unsigned long long new)
 {
 	unsigned long long prev;
-	asm volatile(LOCK_PREFIX "cmpxchg8b %3"
-		     : "=A"(prev)
+	asm volatile(LOCK_PREFIX "cmpxchg8b %1"
+		     : "=A"(prev), "+m" (*__xg(ptr))
 		     : "b"((unsigned long)new),
 		       "c"((unsigned long)(new >> 32)),
-		       "m"(*__xg(ptr)),
 		       "0"(old)
 		     : "memory");
 	return prev;
@@ -241,11 +240,10 @@ static inline unsigned long long __cmpxchg64_local(volatile void *ptr,
 						   unsigned long long new)
 {
 	unsigned long long prev;
-	asm volatile("cmpxchg8b %3"
-		     : "=A"(prev)
+	asm volatile("cmpxchg8b %1"
+		     : "=A"(prev), "+m"(*__xg(ptr))
 		     : "b"((unsigned long)new),
 		       "c"((unsigned long)(new >> 32)),
-		       "m"(*__xg(ptr)),
 		       "0"(old)
 		     : "memory");
 	return prev;
arch/x86/include/asm/cmpxchg_64.h +47 -41

148 lines not on this page · raw message

Signature · 1 line
1.5.6.5
author
#427 lore raw

Re: [tip:x86/urgent] x86: Add memory modify constraints to xchg() and cmpxchg()

Quoted 11 lines · Peter Palfrader
Quoted 9 lines · Jeremy Fitzhardinge
Quoted 8 lines
Commit-ID:  113fc5a6e8c2288619ff7e8187a6f556b7e0d372
Gitweb:     http://git.kernel.org/tip/113fc5a6e8c2288619ff7e8187a6f556b7e0d372
Author:     H. Peter Anvin<[email protected]>
AuthorDate: Tue, 27 Jul 2010 17:01:49 -0700
Committer:  H. Peter Anvin<[email protected]>
CommitDate: Tue, 27 Jul 2010 17:14:02 -0700

x86: Add memory modify constraints to xchg() and cmpxchg()

Quoted 7 lines
Quoted 1 line

Here's the 2.6.32 version for stable.

Thanks a lot everyone. This patch resolves the issue for me on top of 2.6.32.17.

(I had some whitespace issue with applying the patch, so I've attached the cleaned up version in case it wasn't just me.)

Thanks, I needed this version, it wasn't just you :)

greg k-h

#428 lore raw

Re: [patch 134/149] x86, paravirt: Add a global synchronization point for pvclock

In reply to Avi Kivity
Quoted 9 lines · Avi Kivity

Well, current upstream uses "m":

Quoted 6 lines
        case 8:                                                         \
                asm volatile(lock "cmpxchgq %1,%2"                      \
                             : "=a"(__ret)                              \
                             : "r"(__new), "m"(*__xg(ptr)), "0"(__old)  \
                             : "memory");                               \
                break;                                                  \
Quoted 4 lines

and works; I also failed to reproduce with 2.6.32.16. So I expect some toolchain involvement.

Peter, what gcc are you using?

gcc (Debian 4.3.2-1.1) 4.3.2

Signature · 4 lines
                           |  .''`.  ** Debian GNU/Linux **
      Peter Palfrader      | : :' :      The  universal
 http://www.palfrader.org/ | `. `'      Operating System
                           |   `-    http://www.debian.org/
#429 lore raw

Re: [Stable-review] [patch 134/149] x86, paravirt: Add a global synchronization point for pvclock

Quoted 11 lines · Peter Palfrader
Quoted 9 lines · Avi Kivity

Well, current upstream uses "m":

Quoted 6 lines
        case 8:                                                         \
                asm volatile(lock "cmpxchgq %1,%2"                      \
                             : "=a"(__ret)                              \
                             : "r"(__new), "m"(*__xg(ptr)), "0"(__old)  \
                             : "memory");                               \
                break;                                                  \
Quoted 6 lines
Quoted 4 lines

and works; I also failed to reproduce with 2.6.32.16. So I expect some toolchain involvement.

Peter, what gcc are you using?

gcc (Debian 4.3.2-1.1) 4.3.2

The experimental Debian packages of 2.6.35-rc5 are built with gcc 4.4 and they don't have this bug - last_value is marked as 'b' in System.map, which I assume means BSS. So this may be specific to gcc 4.3.

Ben.

Signature · 2 lines
Ben Hutchings
Once a job is fouled up, anything done to improve it makes it worse.
#430 lore raw

PATCH 135/149 KVM: Dont allow lmsw to clear cr0.pe

In reply to Greg KH

2.6.32-stable review patch. If anyone has any objections, please let us know.

------------------

From: Avi Kivity <[email protected]>

The current lmsw implementation allows the guest to clear cr0.pe, contrary to the manual, which breaks EMM386.EXE.

Fix by ORing the old cr0.pe with lmsw's operand.

(cherry picked from commit f78e917688edbf1f14c318d2e50dc8e7dad20445)
---
 arch/x86/kvm/x86.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
arch/x86/kvm/x86.c +1 -1
@@ -345,7 +345,7 @@ EXPORT_SYMBOL_GPL(kvm_set_cr0);
 
 void kvm_lmsw(struct kvm_vcpu *vcpu, unsigned long msw)
 {
-	kvm_set_cr0(vcpu, (vcpu->arch.cr0 & ~0x0ful) | (msw & 0x0f));
+	kvm_set_cr0(vcpu, (vcpu->arch.cr0 & ~0x0eul) | (msw & 0x0f));
 }
 EXPORT_SYMBOL_GPL(kvm_lmsw);
 
#431 lore raw

PATCH 136/149 KVM: x86: Check LMA bit before set_efer

In reply to Greg KH

2.6.32-stable review patch. If anyone has any objections, please let us know.

------------------

From: Sheng Yang <[email protected]>

kvm_x86_ops->set_efer() would execute vcpu->arch.efer = efer, so the checking of LMA bit didn't work.

(cherry picked from commit a3d204e28579427609c3d15d2310127ebaa47d94)
---
 arch/x86/kvm/x86.c |    4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
arch/x86/kvm/x86.c +2 -2
@@ -516,11 +516,11 @@ static void set_efer(struct kvm_vcpu *vc
 		}
 	}
 
-	kvm_x86_ops->set_efer(vcpu, efer);
-
 	efer &= ~EFER_LMA;
 	efer |= vcpu->arch.shadow_efer & EFER_LMA;
 
+	kvm_x86_ops->set_efer(vcpu, efer);
+
 	vcpu->arch.shadow_efer = efer;
 
 	vcpu->arch.mmu.base_role.nxe = (efer & EFER_NX) && !tdp_enabled;
#432 lore raw

PATCH 137/149 KVM: MMU: Segregate shadow pages with different cr0.wp

In reply to Greg KH

2.6.32-stable review patch. If anyone has any objections, please let us know.

------------------

From: Avi Kivity <[email protected]>

When cr0.wp=0, we may shadow a gpte having u/s=1 and r/w=0 with an spte having u/s=0 and r/w=1. This allows excessive access if the guest sets cr0.wp=1 and accesses through this spte.

Fix by making cr0.wp part of the base role; we'll have different sptes for the two cases and the problem disappears.

(cherry picked from commit 3dbe141595faa48a067add3e47bba3205b79d33c)
---
 arch/x86/include/asm/kvm_host.h |    1 +
 arch/x86/kvm/mmu.c              |    3 ++-
 2 files changed, 3 insertions(+), 1 deletion(-)
arch/x86/include/asm/kvm_host.h +1 -0
@@ -193,6 +193,7 @@ union kvm_mmu_page_role {
 		unsigned invalid:1;
 		unsigned cr4_pge:1;
 		unsigned nxe:1;
+		unsigned cr0_wp:1;
 	};
 };
 
arch/x86/kvm/mmu.c +2 -1
@@ -221,7 +221,7 @@ void kvm_mmu_set_mask_ptes(u64 user_mask
 }
 EXPORT_SYMBOL_GPL(kvm_mmu_set_mask_ptes);
 
-static int is_write_protection(struct kvm_vcpu *vcpu)
+static bool is_write_protection(struct kvm_vcpu *vcpu)
 {
 	return vcpu->arch.cr0 & X86_CR0_WP;
 }
@@ -2445,6 +2445,7 @@ static int init_kvm_softmmu(struct kvm_v
 		r = paging32_init_context(vcpu);
 
 	vcpu->arch.mmu.base_role.glevels = vcpu->arch.mmu.root_level;
+	vcpu->arch.mmu.base_role.cr0_wp = is_write_protection(vcpu);
 
 	return r;
 }
#433 lore raw

PATCH 138/149 KVM: VMX: enable VMXON check with SMX enabled (Intel TXT)

In reply to Greg KH

2.6.32-stable review patch. If anyone has any objections, please let us know.

------------------

From: Shane Wang <[email protected]>

Per document, for feature control MSR:

Bit 1 enables VMXON in SMX operation. If the bit is clear, execution
of VMXON in SMX operation causes a general-protection exception.
Bit 2 enables VMXON outside SMX operation. If the bit is clear, execution
of VMXON outside SMX operation causes a general-protection exception.

This patch is to enable this kind of check with SMX for VMXON in KVM.

(cherry picked from commit cafd66595d92591e4bd25c3904e004fc6f897e2d)
---
 arch/x86/include/asm/msr-index.h |    5 +++--
 arch/x86/kernel/tboot.c          |    1 +
 arch/x86/kvm/vmx.c               |   32 +++++++++++++++++++++-----------
 include/linux/tboot.h            |    1 +
 4 files changed, 26 insertions(+), 13 deletions(-)
arch/x86/include/asm/msr-index.h +3 -2
@@ -198,8 +198,9 @@
 #define MSR_IA32_EBL_CR_POWERON		0x0000002a
 #define MSR_IA32_FEATURE_CONTROL        0x0000003a
 
-#define FEATURE_CONTROL_LOCKED		(1<<0)
-#define FEATURE_CONTROL_VMXON_ENABLED	(1<<2)
+#define FEATURE_CONTROL_LOCKED				(1<<0)
+#define FEATURE_CONTROL_VMXON_ENABLED_INSIDE_SMX	(1<<1)
+#define FEATURE_CONTROL_VMXON_ENABLED_OUTSIDE_SMX	(1<<2)
 
 #define MSR_IA32_APICBASE		0x0000001b
 #define MSR_IA32_APICBASE_BSP		(1<<8)
arch/x86/kernel/tboot.c +1 -0
@@ -46,6 +46,7 @@
 
 /* Global pointer to shared data; NULL means no measured launch. */
 struct tboot *tboot __read_mostly;
+EXPORT_SYMBOL(tboot);
 
 /* timeout for APs (in secs) to enter wait-for-SIPI state during shutdown */
 #define AP_WAIT_TIMEOUT		1
arch/x86/kvm/vmx.c +21 -11
@@ -26,6 +26,7 @@
 #include <linux/sched.h>
 #include <linux/moduleparam.h>
 #include <linux/ftrace_event.h>
+#include <linux/tboot.h>
 #include "kvm_cache_regs.h"
 #include "x86.h"
 
@@ -1140,9 +1141,16 @@ static __init int vmx_disabled_by_bios(v
 	u64 msr;
 
 	rdmsrl(MSR_IA32_FEATURE_CONTROL, msr);
-	return (msr & (FEATURE_CONTROL_LOCKED |
-		       FEATURE_CONTROL_VMXON_ENABLED))
-	    == FEATURE_CONTROL_LOCKED;
+	if (msr & FEATURE_CONTROL_LOCKED) {
+		if (!(msr & FEATURE_CONTROL_VMXON_ENABLED_INSIDE_SMX)
+			&& tboot_enabled())
+			return 1;
+		if (!(msr & FEATURE_CONTROL_VMXON_ENABLED_OUTSIDE_SMX)
+			&& !tboot_enabled())
+			return 1;
+	}
+
+	return 0;
 	/* locked but not enabled */
 }
 
@@ -1150,18 +1158,20 @@ static void hardware_enable(void *garbag
 {
 	int cpu = raw_smp_processor_id();
 	u64 phys_addr = __pa(per_cpu(vmxarea, cpu));
-	u64 old;
+	u64 old, test_bits;
 
 	INIT_LIST_HEAD(&per_cpu(vcpus_on_cpu, cpu));
 	rdmsrl(MSR_IA32_FEATURE_CONTROL, old);
-	if ((old & (FEATURE_CONTROL_LOCKED |
-		    FEATURE_CONTROL_VMXON_ENABLED))
-	    != (FEATURE_CONTROL_LOCKED |
-		FEATURE_CONTROL_VMXON_ENABLED))
+
+	test_bits = FEATURE_CONTROL_LOCKED;
+	test_bits |= FEATURE_CONTROL_VMXON_ENABLED_OUTSIDE_SMX;
+	if (tboot_enabled())
+		test_bits |= FEATURE_CONTROL_VMXON_ENABLED_INSIDE_SMX;
+
+	if ((old & test_bits) != test_bits) {
 		/* enable and lock */
-		wrmsrl(MSR_IA32_FEATURE_CONTROL, old |
-		       FEATURE_CONTROL_LOCKED |
-		       FEATURE_CONTROL_VMXON_ENABLED);
+		wrmsrl(MSR_IA32_FEATURE_CONTROL, old | test_bits);
+	}
 	write_cr4(read_cr4() | X86_CR4_VMXE); /* FIXME: not cpu hotplug safe */
 	asm volatile (ASM_VMX_VMXON_RAX
 		      : : "a"(&phys_addr), "m"(phys_addr)
include/linux/tboot.h +1 -0
@@ -150,6 +150,7 @@ extern int tboot_force_iommu(void);
 
 #else
 
+#define tboot_enabled()			0
 #define tboot_probe()			do { } while (0)
 #define tboot_shutdown(shutdown_type)	do { } while (0)
 #define tboot_sleep(sleep_state, pm1a_control, pm1b_control)	\
#434 lore raw

PATCH 139/149 KVM: MMU: Dont read pdptrs with mmu spinlock held in mmu_alloc_roots

In reply to Greg KH

2.6.32-stable review patch. If anyone has any objections, please let us know.

------------------

From: Avi Kivity <[email protected]>

On svm, kvm_read_pdptr() may require reading guest memory, which can sleep.

Push the spinlock into mmu_alloc_roots(), and only take it after we've read the pdptr.

(cherry picked from commit 8facbbff071ff2b19268d3732e31badc60471e21)
---
 arch/x86/kvm/mmu.c |    7 +++++++
 1 file changed, 7 insertions(+)
arch/x86/kvm/mmu.c +7 -0
@@ -2091,11 +2091,13 @@ static int mmu_alloc_roots(struct kvm_vc
 			direct = 1;
 		if (mmu_check_root(vcpu, root_gfn))
 			return 1;
+		spin_lock(&vcpu->kvm->mmu_lock);
 		sp = kvm_mmu_get_page(vcpu, root_gfn, 0,
 				      PT64_ROOT_LEVEL, direct,
 				      ACC_ALL, NULL);
 		root = __pa(sp->spt);
 		++sp->root_count;
+		spin_unlock(&vcpu->kvm->mmu_lock);
 		vcpu->arch.mmu.root_hpa = root;
 		return 0;
 	}
@@ -2117,11 +2119,14 @@ static int mmu_alloc_roots(struct kvm_vc
 			root_gfn = 0;
 		if (mmu_check_root(vcpu, root_gfn))
 			return 1;
+		spin_lock(&vcpu->kvm->mmu_lock);
 		sp = kvm_mmu_get_page(vcpu, root_gfn, i << 30,
 				      PT32_ROOT_LEVEL, direct,
 				      ACC_ALL, NULL);
 		root = __pa(sp->spt);
 		++sp->root_count;
+		spin_unlock(&vcpu->kvm->mmu_lock);
+
 		vcpu->arch.mmu.pae_root[i] = root | PT_PRESENT_MASK;
 	}
 	vcpu->arch.mmu.root_hpa = __pa(vcpu->arch.mmu.pae_root);
@@ -2485,7 +2490,9 @@ int kvm_mmu_load(struct kvm_vcpu *vcpu)
 		goto out;
 	spin_lock(&vcpu->kvm->mmu_lock);
 	kvm_mmu_free_some_pages(vcpu);
+	spin_unlock(&vcpu->kvm->mmu_lock);
 	r = mmu_alloc_roots(vcpu);
+	spin_lock(&vcpu->kvm->mmu_lock);
 	mmu_sync_roots(vcpu);
 	spin_unlock(&vcpu->kvm->mmu_lock);
 	if (r)
#435 lore raw

PATCH 140/149 KVM: Fix wallclock version writing race

In reply to Greg KH

2.6.32-stable review patch. If anyone has any objections, please let us know.

------------------

From: Avi Kivity <[email protected]>

Wallclock writing uses an unprotected global variable to hold the version; this can cause one guest to interfere with another if both write their wallclock at the same time.

(cherry picked from commit 9ed3c444ab8987c7b219173a2f7807e3f71e234e)
---
 arch/x86/kvm/x86.c |   12 ++++++++++--
 1 file changed, 10 insertions(+), 2 deletions(-)
arch/x86/kvm/x86.c +10 -2
@@ -554,14 +554,22 @@ static int do_set_msr(struct kvm_vcpu *v
 
 static void kvm_write_wall_clock(struct kvm *kvm, gpa_t wall_clock)
 {
-	static int version;
+	int version;
+	int r;
 	struct pvclock_wall_clock wc;
 	struct timespec boot;
 
 	if (!wall_clock)
 		return;
 
-	version++;
+	r = kvm_read_guest(kvm, wall_clock, &version, sizeof(version));
+	if (r)
+		return;
+
+	if (version & 1)
+		++version;  /* first time write, random junk */
+
+	++version;
 
 	kvm_write_guest(kvm, wall_clock, &version, sizeof(version));
 
#436 lore raw

PATCH 141/149 KVM: x86: Add missing locking to arch specific vcpu ioctls

In reply to Greg KH

2.6.32-stable review patch. If anyone has any objections, please let us know.

------------------

From: Avi Kivity <[email protected]>

(cherry picked from commit 8fbf065d625617bbbf6b72d5f78f84ad13c8b547)
---
 arch/x86/kvm/x86.c |    6 ++++++
 1 file changed, 6 insertions(+)
arch/x86/kvm/x86.c +6 -0
@@ -1420,6 +1420,7 @@ static int kvm_vcpu_ioctl_get_cpuid2(str
 {
 	int r;
 
+	vcpu_load(vcpu);
 	r = -E2BIG;
 	if (cpuid->nent < vcpu->arch.cpuid_nent)
 		goto out;
@@ -1431,6 +1432,7 @@ static int kvm_vcpu_ioctl_get_cpuid2(str
 
 out:
 	cpuid->nent = vcpu->arch.cpuid_nent;
+	vcpu_put(vcpu);
 	return r;
 }
 
@@ -1680,6 +1682,7 @@ static int kvm_vcpu_ioctl_x86_setup_mce(
 	int r;
 	unsigned bank_num = mcg_cap & 0xff, bank;
 
+	vcpu_load(vcpu);
 	r = -EINVAL;
 	if (!bank_num || bank_num >= KVM_MAX_MCE_BANKS)
 		goto out;
@@ -1694,6 +1697,7 @@ static int kvm_vcpu_ioctl_x86_setup_mce(
 	for (bank = 0; bank < bank_num; bank++)
 		vcpu->arch.mce_banks[bank*4] = ~(u64)0;
 out:
+	vcpu_put(vcpu);
 	return r;
 }
 
@@ -1896,7 +1900,9 @@ long kvm_arch_vcpu_ioctl(struct file *fi
 		r = -EFAULT;
 		if (copy_from_user(&mce, argp, sizeof mce))
 			goto out;
+		vcpu_load(vcpu);
 		r = kvm_vcpu_ioctl_x86_set_mce(vcpu, &mce);
+		vcpu_put(vcpu);
 		break;
 	}
 	default:
#437 lore raw

PATCH 142/149 KVM: x86: Inject #GP with the right rip on efer writes

In reply to Greg KH

2.6.32-stable review patch. If anyone has any objections, please let us know.

------------------

From: Roedel, Joerg <[email protected]>

This patch fixes a bug in the KVM efer-msr write path. If a guest writes to a reserved efer bit the set_efer function injects the #GP directly. The architecture dependent wrmsr function does not see this, assumes success and advances the rip. This results in a #GP in the guest with the wrong rip. This patch fixes this by reporting efer write errors back to the architectural wrmsr function.

(cherry picked from commit b69e8caef5b190af48c525f6d715e7b7728a77f6)
---
 arch/x86/kvm/x86.c |   31 ++++++++++++-------------------
 1 file changed, 12 insertions(+), 19 deletions(-)
arch/x86/kvm/x86.c +12 -19
@@ -483,37 +483,29 @@ static u32 emulated_msrs[] = {
 	MSR_IA32_MISC_ENABLE,
 };
 
-static void set_efer(struct kvm_vcpu *vcpu, u64 efer)
+static int set_efer(struct kvm_vcpu *vcpu, u64 efer)
 {
-	if (efer & efer_reserved_bits) {
-		kvm_inject_gp(vcpu, 0);
-		return;
-	}
+	if (efer & efer_reserved_bits)
+		return 1;
 
 	if (is_paging(vcpu)
-	    && (vcpu->arch.shadow_efer & EFER_LME) != (efer & EFER_LME)) {
-		kvm_inject_gp(vcpu, 0);
-		return;
-	}
+	    && (vcpu->arch.shadow_efer & EFER_LME) != (efer & EFER_LME))
+		return 1;
 
 	if (efer & EFER_FFXSR) {
 		struct kvm_cpuid_entry2 *feat;
 
 		feat = kvm_find_cpuid_entry(vcpu, 0x80000001, 0);
-		if (!feat || !(feat->edx & bit(X86_FEATURE_FXSR_OPT))) {
-			kvm_inject_gp(vcpu, 0);
-			return;
-		}
+		if (!feat || !(feat->edx & bit(X86_FEATURE_FXSR_OPT)))
+			return 1;
 	}
 
 	if (efer & EFER_SVME) {
 		struct kvm_cpuid_entry2 *feat;
 
 		feat = kvm_find_cpuid_entry(vcpu, 0x80000001, 0);
-		if (!feat || !(feat->ecx & bit(X86_FEATURE_SVM))) {
-			kvm_inject_gp(vcpu, 0);
-			return;
-		}
+		if (!feat || !(feat->ecx & bit(X86_FEATURE_SVM)))
+			return 1;
 	}
 
 	efer &= ~EFER_LMA;
@@ -525,6 +517,8 @@ static void set_efer(struct kvm_vcpu *vc
 
 	vcpu->arch.mmu.base_role.nxe = (efer & EFER_NX) && !tdp_enabled;
 	kvm_mmu_reset_context(vcpu);
+
+	return 0;
 }
 
 void kvm_enable_efer_bits(u64 mask)
@@ -827,8 +821,7 @@ int kvm_set_msr_common(struct kvm_vcpu *
 {
 	switch (msr) {
 	case MSR_EFER:
-		set_efer(vcpu, data);
-		break;
+		return set_efer(vcpu, data);
 	case MSR_K7_HWCR:
 		data &= ~(u64)0x40;	/* ignore flush filter disable */
 		if (data != 0) {
#438 lore raw

PATCH 143/149 jbd: jbd-debug and jbd2-debug should be writable

In reply to Greg KH

2.6.32-stable review patch. If anyone has any objections, please let us know.

------------------

From: Yin Kangkai <[email protected]>

commit 765f8361902d015c864d5e62019b2f139452d7ef upstream.

jbd-debug and jbd2-debug is currently read-only (S_IRUGO), which is not correct. Make it writable so that we can start debuging.

---
 fs/jbd/journal.c  |    2 +-
 fs/jbd2/journal.c |    3 ++-
 2 files changed, 3 insertions(+), 2 deletions(-)
fs/jbd/journal.c +1 -1
@@ -1913,7 +1913,7 @@ static void __init jbd_create_debugfs_en
 {
 	jbd_debugfs_dir = debugfs_create_dir("jbd", NULL);
 	if (jbd_debugfs_dir)
-		jbd_debug = debugfs_create_u8("jbd-debug", S_IRUGO,
+		jbd_debug = debugfs_create_u8("jbd-debug", S_IRUGO | S_IWUSR,
 					       jbd_debugfs_dir,
 					       &journal_enable_debug);
 }
fs/jbd2/journal.c +2 -1
@@ -2115,7 +2115,8 @@ static void __init jbd2_create_debugfs_e
 {
 	jbd2_debugfs_dir = debugfs_create_dir("jbd2", NULL);
 	if (jbd2_debugfs_dir)
-		jbd2_debug = debugfs_create_u8(JBD2_DEBUG_NAME, S_IRUGO,
+		jbd2_debug = debugfs_create_u8(JBD2_DEBUG_NAME,
+					       S_IRUGO | S_IWUSR,
 					       jbd2_debugfs_dir,
 					       &jbd2_journal_enable_debug);
 }
#439 lore raw

PATCH 144/149 parisc: clear floating point exception flag on SIGFPE signal

In reply to Greg KH

2.6.32-stable review patch. If anyone has any objections, please let us know.

------------------

From: Helge Deller <[email protected]>

commit 550f0d922286556c7ea43974bb7921effb5a5278 upstream.

Clear the floating point exception flag before returning to user space. This is needed, else the libc trampoline handler may hit the same SIGFPE again while building up a trampoline to a signal handler.

Fixes debian bug #559406.

---
 arch/parisc/math-emu/decode_exc.c |    1 +
 1 file changed, 1 insertion(+)
arch/parisc/math-emu/decode_exc.c +1 -0
@@ -342,6 +342,7 @@ decode_fpu(unsigned int Fpu_register[],
 		return SIGNALCODE(SIGFPE, FPE_FLTINV);
 	  case DIVISIONBYZEROEXCEPTION:
 		update_trap_counts(Fpu_register, aflags, bflags, trap_counts);
+		Clear_excp_register(exception_index);
 	  	return SIGNALCODE(SIGFPE, FPE_FLTDIV);
 	  case INEXACTEXCEPTION:
 		update_trap_counts(Fpu_register, aflags, bflags, trap_counts);
#440 lore raw

PATCH 145/149 dm snapshot: simplify sector_to_chunk expression

In reply to Greg KH

2.6.32-stable review patch. If anyone has any objections, please let us know.

------------------

From: Mikulas Patocka <[email protected]>

commit 102c6ddb1d081a6a1fede38c43a42c9811313ec7 upstream.

Removed unnecessary 'and' masking: The right shift discards the lower bits so there is no need to clear them.

(A later patch needs this change to support a 32-bit chunk_mask.)

---
 drivers/md/dm-exception-store.h |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/md/dm-exception-store.h +1 -1
@@ -162,7 +162,7 @@ static inline sector_t get_dev_size(stru
 static inline chunk_t sector_to_chunk(struct dm_exception_store *store,
 				      sector_t sector)
 {
-	return (sector & ~store->chunk_mask) >> store->chunk_shift;
+	return sector >> store->chunk_shift;
 }
 
 int dm_exception_store_type_register(struct dm_exception_store_type *type);
#441 lore raw

PATCH 146/149 KEYS: Return more accurate error codes

In reply to Greg KH

2.6.32-stable review patch. If anyone has any objections, please let us know.

------------------

From: Dan Carpenter <[email protected]>

commit 4d09ec0f705cf88a12add029c058b53f288cfaa2 upstream.

We were using the wrong variable here so the error codes weren't being returned properly. The original code returns -ENOKEY.

---
 security/keys/process_keys.c |    6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)
security/keys/process_keys.c +3 -3
@@ -509,7 +509,7 @@ try_again:
 
 			ret = install_thread_keyring();
 			if (ret < 0) {
-				key = ERR_PTR(ret);
+				key_ref = ERR_PTR(ret);
 				goto error;
 			}
 			goto reget_creds;
@@ -527,7 +527,7 @@ try_again:
 
 			ret = install_process_keyring();
 			if (ret < 0) {
-				key = ERR_PTR(ret);
+				key_ref = ERR_PTR(ret);
 				goto error;
 			}
 			goto reget_creds;
@@ -586,7 +586,7 @@ try_again:
 
 	case KEY_SPEC_GROUP_KEYRING:
 		/* group keyrings are not yet supported */
-		key = ERR_PTR(-EINVAL);
+		key_ref = ERR_PTR(-EINVAL);
 		goto error;
 
 	case KEY_SPEC_REQKEY_AUTH_KEY:
#442 lore raw

PATCH 147/149 KEYS: find_keyring_by_name() can gain access to a freed keyring

In reply to Greg KH

2.6.32-stable review patch. If anyone has any objections, please let us know.

------------------

From: Toshiyuki Okajima <[email protected]>

commit cea7daa3589d6b550546a8c8963599f7c1a3ae5c upstream.

find_keyring_by_name() can gain access to a keyring that has had its reference count reduced to zero, and is thus ready to be freed. This then allows the dead keyring to be brought back into use whilst it is being destroyed.

The following timeline illustrates the process:

|(cleaner)                           (user)
|
| free_user(user)                    sys_keyctl()
|  |                                  |
|  key_put(user->session_keyring)     keyctl_get_keyring_ID()
|  ||	//=> keyring->usage = 0        |
|  |schedule_work(&key_cleanup_task)   lookup_user_key()
|  ||                                   |
|  kmem_cache_free(,user)               |
|  .                                    |[KEY_SPEC_USER_KEYRING]
|  .                                    install_user_keyrings()
|  .                                    ||
| key_cleanup() [<= worker_thread()]    ||
|  |                                    ||
|  [spin_lock(&key_serial_lock)]        |[mutex_lock(&key_user_keyr..mutex)]
|  |                                    ||
|  atomic_read() == 0                   ||
|  |{ rb_ease(&key->serial_node,) }     ||
|  |                                    ||
|  [spin_unlock(&key_serial_lock)]      |find_keyring_by_name()
|  |                                    |||
|  keyring_destroy(keyring)             ||[read_lock(&keyring_name_lock)]
|  ||                                   |||
|  |[write_lock(&keyring_name_lock)]    ||atomic_inc(&keyring->usage)
|  |.                                   ||| *** GET freeing keyring ***
|  |.                                   ||[read_unlock(&keyring_name_lock)]
|  ||                                   ||
|  |list_del()                          |[mutex_unlock(&key_user_k..mutex)]
|  ||                                   |
|  |[write_unlock(&keyring_name_lock)]  ** INVALID keyring is returned **
|  |                                    .
|  kmem_cache_free(,keyring)            .
|                                       .
|                                       atomic_dec(&keyring->usage)

v *** DESTROYED ***
TIME

If CONFIG_SLUB_DEBUG=y then we may see the following message generated:

	=============================================================================
	BUG key_jar: Poison overwritten
	-----------------------------------------------------------------------------

	INFO: 0xffff880197a7e200-0xffff880197a7e200. First byte 0x6a instead of 0x6b
	INFO: Allocated in key_alloc+0x10b/0x35f age=25 cpu=1 pid=5086
	INFO: Freed in key_cleanup+0xd0/0xd5 age=12 cpu=1 pid=10
	INFO: Slab 0xffffea000592cb90 objects=16 used=2 fp=0xffff880197a7e200 flags=0x200000000000c3
	INFO: Object 0xffff880197a7e200 @offset=512 fp=0xffff880197a7e300

	Bytes b4 0xffff880197a7e1f0:  5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a ZZZZZZZZZZZZZZZZ
	  Object 0xffff880197a7e200:  6a 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b jkkkkkkkkkkkkkkk

Alternatively, we may see a system panic happen, such as:

	BUG: unable to handle kernel NULL pointer dereference at 0000000000000001
	IP: [<ffffffff810e61a3>] kmem_cache_alloc+0x5b/0xe9
	PGD 6b2b4067 PUD 6a80d067 PMD 0
	Oops: 0000 [#1] SMP
	last sysfs file: /sys/kernel/kexec_crash_loaded
	CPU 1
	...
	Pid: 31245, comm: su Not tainted 2.6.34-rc5-nofixed-nodebug #2 D2089/PRIMERGY
	RIP: 0010:[<ffffffff810e61a3>]  [<ffffffff810e61a3>] kmem_cache_alloc+0x5b/0xe9
	RSP: 0018:ffff88006af3bd98  EFLAGS: 00010002
	RAX: 0000000000000000 RBX: 0000000000000001 RCX: ffff88007d19900b
	RDX: 0000000100000000 RSI: 00000000000080d0 RDI: ffffffff81828430
	RBP: ffffffff81828430 R08: ffff88000a293750 R09: 0000000000000000
	R10: 0000000000000001 R11: 0000000000100000 R12: 00000000000080d0
	R13: 00000000000080d0 R14: 0000000000000296 R15: ffffffff810f20ce
	FS:  00007f97116bc700(0000) GS:ffff88000a280000(0000) knlGS:0000000000000000
	CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
	CR2: 0000000000000001 CR3: 000000006a91c000 CR4: 00000000000006e0
	DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
	DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400
	Process su (pid: 31245, threadinfo ffff88006af3a000, task ffff8800374414c0)
	Stack:
	 0000000512e0958e 0000000000008000 ffff880037f8d180 0000000000000001
	 0000000000000000 0000000000008001 ffff88007d199000 ffffffff810f20ce
	 0000000000008000 ffff88006af3be48 0000000000000024 ffffffff810face3
	Call Trace:
	 [<ffffffff810f20ce>] ? get_empty_filp+0x70/0x12f
	 [<ffffffff810face3>] ? do_filp_open+0x145/0x590
	 [<ffffffff810ce208>] ? tlb_finish_mmu+0x2a/0x33
	 [<ffffffff810ce43c>] ? unmap_region+0xd3/0xe2
	 [<ffffffff810e4393>] ? virt_to_head_page+0x9/0x2d
	 [<ffffffff81103916>] ? alloc_fd+0x69/0x10e
	 [<ffffffff810ef4ed>] ? do_sys_open+0x56/0xfc
	 [<ffffffff81008a02>] ? system_call_fastpath+0x16/0x1b
	Code: 0f 1f 44 00 00 49 89 c6 fa 66 0f 1f 44 00 00 65 4c 8b 04 25 60 e8 00 00 48 8b 45 00 49 01 c0 49 8b 18 48 85 db 74 0d 48 63 45 18 <48> 8b 04 03 49 89 00 eb 14 4c 89 f9 83 ca ff 44 89 e6 48 89 ef
	RIP  [<ffffffff810e61a3>] kmem_cache_alloc+0x5b/0xe9

This problem is that find_keyring_by_name does not confirm that the keyring is valid before accepting it.

Skipping keyrings that have been reduced to a zero count seems the way to go. To this end, use atomic_inc_not_zero() to increment the usage count and skip the candidate keyring if that returns false.

The following script _may_ cause the bug to happen, but there's no guarantee as the window of opportunity is small:

	#!/bin/sh
	LOOP=100000
	USER=dummy_user
	/bin/su -c "exit;" $USER || { /usr/sbin/adduser -m $USER; add=1; }
	for ((i=0; i<LOOP; i++))
	do
		/bin/su -c "echo '$i' > /dev/null" $USER
	done
	(( add == 1 )) && /usr/sbin/userdel -r $USER
	exit

Note that the nominated user must not be in use.

An alternative way of testing this may be:

	for ((i=0; i<100000; i++))
	do
		keyctl session foo /bin/true || break
	done >&/dev/null

as that uses a keyring named "foo" rather than relying on the user and user-session named keyrings.

---
 security/keys/keyring.c |   18 +++++++++---------
 1 file changed, 9 insertions(+), 9 deletions(-)
security/keys/keyring.c +9 -9
@@ -524,9 +524,8 @@ struct key *find_keyring_by_name(const c
 	struct key *keyring;
 	int bucket;
 
-	keyring = ERR_PTR(-EINVAL);
 	if (!name)
-		goto error;
+		return ERR_PTR(-EINVAL);
 
 	bucket = keyring_hash(name);
 
@@ -553,17 +552,18 @@ struct key *find_keyring_by_name(const c
 					   KEY_SEARCH) < 0)
 				continue;
 
-			/* we've got a match */
-			atomic_inc(&keyring->usage);
-			read_unlock(&keyring_name_lock);
-			goto error;
+			/* we've got a match but we might end up racing with
+			 * key_cleanup() if the keyring is currently 'dead'
+			 * (ie. it has a zero usage count) */
+			if (!atomic_inc_not_zero(&keyring->usage))
+				continue;
+			goto out;
 		}
 	}
 
-	read_unlock(&keyring_name_lock);
 	keyring = ERR_PTR(-ENOKEY);
-
- error:
+out:
+	read_unlock(&keyring_name_lock);
 	return keyring;
 
 } /* end find_keyring_by_name() */
#443 lore raw

PATCH 148/149 qla2xxx: Disable MSI on qla24xx chips other than QLA2432.

In reply to Greg KH

2.6.32-stable review patch. If anyone has any objections, please let us know.

------------------

From: Ben Hutchings <[email protected]>

commit 6377a7ae1ab82859edccdbc8eaea63782efb134d upstream.

On specific platforms, MSI is unreliable on some of the QLA24xx chips, resulting in fatal I/O errors under load, as reported in <http://bugs.debian.org/572322>
and by some RHEL customers.

---
 drivers/scsi/qla2xxx/qla_isr.c |   28 +++++++++++++---------------
 1 file changed, 13 insertions(+), 15 deletions(-)
drivers/scsi/qla2xxx/qla_isr.c +13 -15
@@ -2240,30 +2240,28 @@ qla2x00_request_irqs(struct qla_hw_data
 
 	/* If possible, enable MSI-X. */
 	if (!IS_QLA2432(ha) && !IS_QLA2532(ha) &&
-	    !IS_QLA8432(ha) && !IS_QLA8001(ha))
-		goto skip_msix;
+		!IS_QLA8432(ha) && !IS_QLA8001(ha))
+		goto skip_msi;
+
+	if (ha->pdev->subsystem_vendor == PCI_VENDOR_ID_HP &&
+		(ha->pdev->subsystem_device == 0x7040 ||
+		ha->pdev->subsystem_device == 0x7041 ||
+		ha->pdev->subsystem_device == 0x1705)) {
+		DEBUG2(qla_printk(KERN_WARNING, ha,
+			"MSI-X: Unsupported ISP2432 SSVID/SSDID (0x%X,0x%X).\n",
+			ha->pdev->subsystem_vendor,
+			ha->pdev->subsystem_device));
+		goto skip_msi;
+	}
 
 	if (IS_QLA2432(ha) && (ha->pdev->revision < QLA_MSIX_CHIP_REV_24XX ||
 		!QLA_MSIX_FW_MODE_1(ha->fw_attributes))) {
 		DEBUG2(qla_printk(KERN_WARNING, ha,
 		"MSI-X: Unsupported ISP2432 (0x%X, 0x%X).\n",
 			ha->pdev->revision, ha->fw_attributes));
-
 		goto skip_msix;
 	}
 
-	if (ha->pdev->subsystem_vendor == PCI_VENDOR_ID_HP &&
-	    (ha->pdev->subsystem_device == 0x7040 ||
-		ha->pdev->subsystem_device == 0x7041 ||
-		ha->pdev->subsystem_device == 0x1705)) {
-		DEBUG2(qla_printk(KERN_WARNING, ha,
-		    "MSI-X: Unsupported ISP2432 SSVID/SSDID (0x%X, 0x%X).\n",
-		    ha->pdev->subsystem_vendor,
-		    ha->pdev->subsystem_device));
-
-		goto skip_msi;
-	}
-
 	ret = qla24xx_enable_msix(ha, rsp);
 	if (!ret) {
 		DEBUG2(qla_printk(KERN_INFO, ha,
#444 lore raw

PATCH 149/149 sctp: fix append error cause to ERROR chunk correctly

In reply to Greg KH

2.6.32-stable review patch. If anyone has any objections, please let us know.

------------------

From: Wei Yongjun <[email protected]>

commit 2e3219b5c8a2e44e0b83ae6e04f52f20a82ac0f2 upstream.

commit 5fa782c2f5ef6c2e4f04d3e228412c9b4a4c8809
sctp: Fix skb_over_panic resulting from multiple invalid \

    parameter errors (CVE-2010-1173) (v4)

cause 'error cause' never be add the the ERROR chunk due to some typo when check valid length in sctp_init_cause_fixed().

---
 net/sctp/sm_make_chunk.c |    4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
net/sctp/sm_make_chunk.c +2 -2
@@ -140,7 +140,7 @@ int sctp_init_cause_fixed(struct sctp_ch
 	len = sizeof(sctp_errhdr_t) + paylen;
 	err.length  = htons(len);
 
-	if (skb_tailroom(chunk->skb) >  len)
+	if (skb_tailroom(chunk->skb) < len)
 		return -ENOSPC;
 	chunk->subh.err_hdr = sctp_addto_chunk_fixed(chunk,
 						     sizeof(sctp_errhdr_t),
@@ -1412,7 +1412,7 @@ void *sctp_addto_chunk(struct sctp_chunk
 void *sctp_addto_chunk_fixed(struct sctp_chunk *chunk,
 			     int len, const void *data)
 {
-	if (skb_tailroom(chunk->skb) > len)
+	if (skb_tailroom(chunk->skb) >= len)
 		return sctp_addto_chunk(chunk, len, data);
 	else
 		return NULL;
#445 lore raw

cover 2.6.34.1 stable review

In reply to Greg KH

This is the start of the stable review cycle for the 2.6.34.1 release. There are 200 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know. If anyone is a maintainer of the proper subsystem, and wants to add a Signed-off-by: line to the patch, please respond with it.

Responses should be made by Sat, July 3, 17:00:00 UTC UTC. Anything received after that time might be too late.

The whole patch series can be found in one patch at:

        kernel.org/pub/linux/kernel/v2.6/stable-review/patch-2.6.34.1-rc1.gz

and the diffstat can be found below.

thanks,

greg k-h

 Documentation/hwmon/ltc4245                     |    4 +-
 Makefile                                        |    2 +-
 arch/arm/common/sa1111.c                        |    9 +-
 arch/arm/mach-mx2/devices.c                     |    4 +-
 arch/arm/mm/cache-v7.S                          |    4 +
 arch/arm/mm/copypage-feroceon.c                 |    4 +-
 arch/arm/mm/copypage-v4wb.c                     |    4 +-
 arch/arm/mm/copypage-v4wt.c                     |    4 +-
 arch/arm/mm/copypage-xsc3.c                     |    4 +-
 arch/arm/mm/fault.c                             |    3 +
 arch/arm/mm/init.c                              |    6 +-
 arch/arm/vfp/vfphw.S                            |    2 +-
 arch/blackfin/include/asm/cache.h               |    2 +
 arch/frv/include/asm/cache.h                    |    2 +
 arch/m68k/include/asm/cache.h                   |    2 +
 arch/mn10300/include/asm/cache.h                |    2 +
 arch/parisc/math-emu/decode_exc.c               |    1 +
 arch/powerpc/kernel/asm-offsets.c               |    8 +
 arch/powerpc/kernel/head_fsl_booke.S            |   13 +-
 arch/powerpc/kvm/book3s.c                       |   10 +
 arch/powerpc/kvm/booke.c                        |   15 +-
 arch/powerpc/kvm/powerpc.c                      |    3 +-
 arch/powerpc/lib/string.S                       |    4 +-
 arch/powerpc/mm/fsl_booke_mmu.c                 |   25 +--
 arch/powerpc/mm/mmu_decl.h                      |   10 +-
 arch/powerpc/mm/pgtable_32.c                    |    8 +
 arch/powerpc/mm/pgtable_64.c                    |    8 +
 arch/powerpc/mm/tlb_nohash_low.S                |   28 ++
 arch/powerpc/oprofile/op_model_cell.c           |    2 +-
 arch/powerpc/platforms/pseries/hotplug-cpu.c    |   30 +--
 arch/powerpc/platforms/pseries/plpar_wrappers.h |    8 +
 arch/powerpc/platforms/pseries/smp.c            |   28 ++
 arch/s390/kvm/kvm-s390.c                        |    4 +-
 arch/x86/include/asm/kvm_host.h                 |    3 +
 arch/x86/include/asm/msr-index.h                |    5 +-
 arch/x86/kernel/amd_iommu.c                     |   16 +-
 arch/x86/kernel/amd_iommu_init.c                |   20 ++-
 arch/x86/kernel/cpu/perf_event.c                |    5 +-
 arch/x86/kernel/pvclock.c                       |   24 ++
 arch/x86/kernel/setup.c                         |   11 +
 arch/x86/kernel/tboot.c                         |    1 +
 arch/x86/kvm/mmu.c                              |   10 +-
 arch/x86/kvm/svm.c                              |  163 ++++++++-----
 arch/x86/kvm/vmx.c                              |   38 ++-
 arch/x86/kvm/x86.c                              |   58 +++--
 arch/x86/oprofile/nmi_int.c                     |   10 +-
 arch/x86/xen/suspend.c                          |    4 +-
 arch/xtensa/include/asm/cache.h                 |    1 +
 block/cfq-iosched.c                             |   20 +-
 drivers/acpi/video_detect.c                     |    2 +-
 drivers/ata/libata-core.c                       |    7 +-
 drivers/ata/libata-sff.c                        |    2 +-
 drivers/ata/sata_nv.c                           |    5 +-
 drivers/ata/sata_via.c                          |   13 +
 drivers/base/cpu.c                              |    2 +-
 drivers/char/ipmi/ipmi_si_intf.c                |   11 +-
 drivers/clocksource/sh_cmt.c                    |   21 +-
 drivers/clocksource/sh_tmu.c                    |   20 +-
 drivers/firewire/core-card.c                    |   24 ++-
 drivers/gpu/drm/drm_edid.c                      |    2 +-
 drivers/gpu/drm/i915/i915_gem.c                 |   19 ++
 drivers/gpu/drm/i915/intel_display.c            |    6 -
 drivers/gpu/drm/i915/intel_dp.c                 |   10 -
 drivers/gpu/drm/radeon/radeon.h                 |    1 +
 drivers/gpu/drm/radeon/radeon_agp.c             |    5 +
 drivers/gpu/drm/radeon/radeon_atombios.c        |    7 +-
 drivers/gpu/drm/radeon/radeon_device.c          |    2 +
 drivers/gpu/drm/radeon/radeon_display.c         |    5 +-
 drivers/gpu/drm/radeon/radeon_state.c           |    5 +-
 drivers/hid/hid-core.c                          |    1 +
 drivers/hid/hid-gyration.c                      |    1 +
 drivers/hid/hid-ids.h                           |    1 +
 drivers/hwmon/ltc4245.c                         |   18 +-
 drivers/md/linear.c                             |    1 +
 drivers/md/md.c                                 |   99 +++++++-
 drivers/md/md.h                                 |    1 +
 drivers/md/raid1.c                              |    9 +-
 drivers/md/raid10.c                             |    2 +-
 drivers/md/raid5.c                              |    7 +-
 drivers/media/video/uvc/uvc_ctrl.c              |    2 +
 drivers/misc/vmware_balloon.c                   |   18 ++-
 drivers/net/arcnet/com20020-pci.c               |    4 +-
 drivers/net/can/sja1000/sja1000.c               |   20 ++-
 drivers/net/can/sja1000/sja1000.h               |    1 +
 drivers/net/mlx4/icm.c                          |    3 +-
 drivers/net/wireless/ath/ar9170/hw.h            |    1 +
 drivers/net/wireless/ath/ar9170/main.c          |    2 +-
 drivers/net/wireless/ath/ar9170/usb.c           |   10 +
 drivers/net/wireless/ath/ath5k/base.c           |   11 +-
 drivers/net/wireless/ath/ath9k/hw.c             |    4 +-
 drivers/net/wireless/ath/ath9k/init.c           |    3 +
 drivers/net/wireless/iwlwifi/iwl-agn-rs.c       |   10 +-
 drivers/net/wireless/iwlwifi/iwl-scan.c         |   21 ++-
 drivers/net/wireless/iwlwifi/iwl-tx.c           |    2 +
 drivers/net/wireless/p54/p54usb.c               |    1 +
 drivers/net/wireless/rtl818x/rtl8180_dev.c      |    1 +
 drivers/net/wireless/wl12xx/wl1251_sdio.c       |    1 +
 drivers/oprofile/cpu_buffer.c                   |   63 +----
 drivers/pci/quirks.c                            |   13 +-
 drivers/pcmcia/ds.c                             |    1 +
 drivers/pcmcia/yenta_socket.c                   |    5 +-
 drivers/platform/x86/Kconfig                    |    1 +
 drivers/rtc/rtc-cmos.c                          |    5 +-
 drivers/rtc/rtc-s3c.c                           |    5 +-
 drivers/scsi/libsas/sas_ata.c                   |    5 +-
 drivers/scsi/libsas/sas_scsi_host.c             |   16 +-
 drivers/serial/68328serial.c                    |    2 +-
 drivers/staging/batman-adv/proc.c               |   51 +++--
 drivers/staging/batman-adv/vis.c                |  235 ++++++++++++------
 drivers/staging/batman-adv/vis.h                |    8 +-
 drivers/staging/comedi/drivers/ni_mio_cs.c      |    2 +-
 drivers/staging/rt2860/usb_main_dev.c           |    1 +
 drivers/staging/vt6655/device_main.c            |    2 +
 drivers/usb/class/cdc-acm.c                     |    6 +-
 drivers/usb/core/driver.c                       |    2 +
 drivers/usb/core/hcd.c                          |  169 ++++++++-----
 drivers/usb/core/message.c                      |   45 +---
 drivers/usb/core/urb.c                          |    9 +-
 drivers/usb/core/usb.c                          |    4 +
 drivers/usb/gadget/fsl_udc_core.c               |    2 +-
 drivers/usb/host/ehci-au1xxx.c                  |   16 +-
 drivers/usb/host/ehci-fsl.c                     |    2 +
 drivers/usb/host/ehci-hub.c                     |  158 ++++++++++---
 drivers/usb/host/ehci-pci.c                     |   15 +-
 drivers/usb/host/ehci.h                         |   10 +
 drivers/usb/host/fhci.h                         |    9 +-
 drivers/usb/host/whci/qset.c                    |    2 +-
 drivers/usb/host/xhci-pci.c                     |    2 +-
 drivers/usb/host/xhci-ring.c                    |   39 +++-
 drivers/usb/host/xhci.c                         |   54 ++++-
 drivers/usb/mon/mon_bin.c                       |    2 +-
 drivers/usb/mon/mon_text.c                      |    4 +-
 drivers/usb/serial/cp210x.c                     |   11 +
 drivers/usb/serial/cypress_m8.c                 |    2 +-
 drivers/usb/serial/digi_acceleport.c            |    4 +-
 drivers/usb/serial/ftdi_sio.c                   |    4 +
 drivers/usb/serial/ir-usb.c                     |    2 +
 drivers/usb/serial/kl5kusb105.c                 |    1 +
 drivers/usb/serial/kobil_sct.c                  |    3 +-
 drivers/usb/serial/mos7840.c                    |    1 -
 drivers/usb/serial/option.c                     |  180 ++++++++++++++
 drivers/usb/serial/qcaux.c                      |    5 +
 drivers/usb/serial/spcp8x5.c                    |    4 +-
 drivers/usb/serial/visor.c                      |    1 +
 drivers/usb/storage/unusual_devs.h              |   15 ++
 drivers/vhost/net.c                             |    2 +-
 drivers/video/arcfb.c                           |    8 +-
 drivers/video/hgafb.c                           |   10 +-
 drivers/video/vfb.c                             |    4 +-
 drivers/video/vga16fb.c                         |   10 +-
 drivers/video/w100fb.c                          |   10 +-
 drivers/xen/xenbus/xenbus_xs.c                  |    2 +-
 fs/aio.c                                        |   65 +++--
 fs/btrfs/acl.c                                  |    3 +
 fs/cifs/cifsproto.h                             |    6 +-
 fs/cifs/dir.c                                   |   20 +-
 fs/cifs/file.c                                  |   11 +-
 fs/compat.c                                     |  132 ++++++----
 fs/dcache.c                                     |    1 +
 fs/exofs/dir.c                                  |    2 +-
 fs/ext4/move_extent.c                           |    3 +
 fs/ext4/resize.c                                |    3 +-
 fs/fs-writeback.c                               |   14 +-
 fs/gfs2/file.c                                  |    7 +
 fs/libfs.c                                      |    3 +-
 fs/namei.c                                      |    2 +-
 fs/nfs/write.c                                  |   20 ++-
 fs/nfsd/nfssvc.c                                |    2 +-
 fs/nfsd/vfs.c                                   |   11 +-
 fs/nfsd/vfs.h                                   |    1 +
 include/linux/aio.h                             |    5 +
 include/linux/compat.h                          |    4 +
 include/linux/fs.h                              |    2 +-
 include/linux/miscdevice.h                      |    7 +-
 include/linux/pci_ids.h                         |    1 +
 include/linux/perf_event.h                      |    5 +-
 include/linux/slub_def.h                        |   11 +-
 include/linux/swap.h                            |   10 -
 include/linux/tboot.h                           |    1 +
 include/linux/usb.h                             |    9 +
 include/trace/events/signal.h                   |    3 +-
 kernel/cgroup.c                                 |    2 +-
 kernel/compat.c                                 |   25 +-
 kernel/mutex.c                                  |    7 +
 kernel/perf_event.c                             |  299 +++++++++++++---------
 kernel/posix-timers.c                           |   11 +-
 kernel/signal.c                                 |    6 +-
 lib/idr.c                                       |    5 +-
 mm/filemap.c                                    |   10 +-
 mm/slub.c                                       |   33 +--
 net/mac80211/Kconfig                            |    9 +
 net/mac80211/cfg.c                              |    7 +-
 net/mac80211/mlme.c                             |   40 +++-
 net/mac80211/rx.c                               |    3 +-
 net/mac80211/tx.c                               |    5 +-
 scripts/kconfig/Makefile                        |    2 +-
 sound/core/pcm_lib.c                            |   13 +-
 sound/core/pcm_native.c                         |   39 +---
 sound/pci/hda/hda_intel.c                       |    9 +-
 sound/pci/hda/patch_realtek.c                   |    1 +
 sound/pci/hda/patch_sigmatel.c                  |    2 +-
 sound/soc/codecs/wm8350.c                       |    4 +-
 sound/soc/codecs/wm8400.c                       |   18 +-
 sound/soc/codecs/wm8990.c                       |   18 +-
 sound/soc/imx/imx-pcm-dma-mx2.c                 |    7 +-
 tools/perf/bench/mem-memcpy.c                   |    2 +-
 tools/perf/bench/sched-messaging.c              |    4 +-
 tools/perf/builtin-annotate.c                   |    8 +-
 tools/perf/builtin-buildid-cache.c              |    2 +-
 tools/perf/builtin-buildid-list.c               |    4 +-
 tools/perf/builtin-diff.c                       |    4 +-
 tools/perf/builtin-help.c                       |    2 +-
 tools/perf/builtin-lock.c                       |    2 +-
 tools/perf/builtin-probe.c                      |    2 +-
 tools/perf/builtin-record.c                     |   24 +-
 tools/perf/builtin-report.c                     |    6 +-
 tools/perf/builtin-sched.c                      |    6 +-
 tools/perf/builtin-stat.c                       |   10 +-
 tools/perf/builtin-timechart.c                  |    2 +-
 tools/perf/builtin-top.c                        |   47 +++--
 tools/perf/builtin-trace.c                      |    2 +-
 tools/perf/util/debug.c                         |    2 +-
 tools/perf/util/debug.h                         |    3 +-
 tools/perf/util/parse-options.c                 |    6 +
 tools/perf/util/parse-options.h                 |    4 +-
 tools/perf/util/symbol.c                        |   25 +-
 tools/perf/util/symbol.h                        |   15 ++
 tools/perf/util/trace-event-parse.c             |    2 +-
 tools/perf/util/trace-event.h                   |    3 +-
 229 files changed, 2312 insertions(+), 1134 deletions(-)
#446 lore raw

PATCH 1/200 oprofile/x86: fix uninitialized counter usage during cpu hotplug

2.6.34-stable review patch. If anyone has any objections, please let me know.

------------------

From: Robert Richter <[email protected]>

commit 2623a1d55a6260c855e1f6d1895900b50b40a896 upstream.

This fixes a NULL pointer dereference that is triggered when taking a cpu offline after oprofile was initialized, e.g.:

 $ opcontrol --init
 $ opcontrol --start-daemon
 $ opcontrol --shutdown
 $ opcontrol --deinit
 $ echo 0 > /sys/devices/system/cpu/cpu1/online

See the crash dump below. Though the counter has been disabled the cpu notifier is still active and trying to use already freed counter data.

This fix is for linux-stable. To proper fix this, the hotplug code must be rewritten. Thus I will leave a WARN_ON_ONCE() message with this patch.

BUG: unable to handle kernel NULL pointer dereference at (null)
IP: [<ffffffff8132ad57>] op_amd_stop+0x2d/0x8e
PGD 0
Oops: 0000 [#1] SMP
last sysfs file: /sys/devices/system/cpu/cpu1/online
CPU 1
Modules linked in:

Pid: 0, comm: swapper Not tainted 2.6.34-rc5-oprofile-x86_64-standard-00210-g8c00f06 #16 Anaheim/Anaheim

RIP: 0010:[<ffffffff8132ad57>]  [<ffffffff8132ad57>] op_amd_stop+0x2d/0x8e
RSP: 0018:ffff880001843f28  EFLAGS: 00010006
RAX: 0000000000000000 RBX: 0000000000000000 RCX: dead000000200200
RDX: ffff880001843f68 RSI: dead000000100100 RDI: 0000000000000000
RBP: ffff880001843f48 R08: 0000000000000000 R09: ffff880001843f08
R10: ffffffff8102c9a5 R11: ffff88000184ea80 R12: 0000000000000000
R13: ffff88000184f6c0 R14: 0000000000000000 R15: 0000000000000000
FS:  00007fec6a92e6f0(0000) GS:ffff880001840000(0000) knlGS:0000000000000000
CS:  0010 DS: 0000 ES: 0000 CR0: 000000008005003b
CR2: 0000000000000000 CR3: 000000000163b000 CR4: 00000000000006e0
DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400
Process swapper (pid: 0, threadinfo ffff88042fcd8000, task ffff88042fcd51d0)
Stack:
 ffff880001843f48 0000000000000001 ffff88042e9f7d38 ffff880001843f68
<0> ffff880001843f58 ffffffff8132a602 ffff880001843f98 ffffffff810521b3
<0> ffff880001843f68 ffff880001843f68 ffff880001843f88 ffff88042fcd9fd8
Call Trace:
 <IRQ>
 [<ffffffff8132a602>] nmi_cpu_stop+0x21/0x23
 [<ffffffff810521b3>] generic_smp_call_function_single_interrupt+0xdf/0x11b
 [<ffffffff8101804f>] smp_call_function_single_interrupt+0x22/0x31
 [<ffffffff810029f3>] call_function_single_interrupt+0x13/0x20
 <EOI>
 [<ffffffff8102c9a5>] ? wake_up_process+0x10/0x12
 [<ffffffff81008701>] ? default_idle+0x22/0x37
 [<ffffffff8100896d>] c1e_idle+0xdf/0xe6
 [<ffffffff813f1170>] ? atomic_notifier_call_chain+0x13/0x15
 [<ffffffff810012fb>] cpu_idle+0x4b/0x7e
 [<ffffffff813e8a4e>] start_secondary+0x1ae/0x1b2
Code: 89 e5 41 55 49 89 fd 41 54 45 31 e4 53 31 db 48 83 ec 08 89 df e8 be f8 ff ff 48 98 48 83 3c c5 10 67 7a 81 00 74 1f 49 8b 45 08 <42> 8b 0c 20 0f 32 48 c1 e2 20 25 ff ff bf ff 48 09 d0 48 89 c2
RIP  [<ffffffff8132ad57>] op_amd_stop+0x2d/0x8e
 RSP <ffff880001843f28>
CR2: 0000000000000000
---[ end trace 679ac372d674b757 ]---
Kernel panic - not syncing: Fatal exception in interrupt
Pid: 0, comm: swapper Tainted: G      D    2.6.34-rc5-oprofile-x86_64-standard-00210-g8c00f06 #16
Call Trace:
 <IRQ>  [<ffffffff813ebd6a>] panic+0x9e/0x10c
 [<ffffffff810474b0>] ? up+0x34/0x39
 [<ffffffff81031ccc>] ? kmsg_dump+0x112/0x12c
 [<ffffffff813eeff1>] oops_end+0x81/0x8e
 [<ffffffff8101efee>] no_context+0x1f3/0x202
 [<ffffffff8101f1b7>] __bad_area_nosemaphore+0x1ba/0x1e0
 [<ffffffff81028d24>] ? enqueue_task_fair+0x16d/0x17a
 [<ffffffff810264dc>] ? activate_task+0x42/0x53
 [<ffffffff8102c967>] ? try_to_wake_up+0x272/0x284
 [<ffffffff8101f1eb>] bad_area_nosemaphore+0xe/0x10
 [<ffffffff813f0f3f>] do_page_fault+0x1c8/0x37c
 [<ffffffff81028d24>] ? enqueue_task_fair+0x16d/0x17a
 [<ffffffff813ee55f>] page_fault+0x1f/0x30
 [<ffffffff8102c9a5>] ? wake_up_process+0x10/0x12
 [<ffffffff8132ad57>] ? op_amd_stop+0x2d/0x8e
 [<ffffffff8132ad46>] ? op_amd_stop+0x1c/0x8e
 [<ffffffff8132a602>] nmi_cpu_stop+0x21/0x23
 [<ffffffff810521b3>] generic_smp_call_function_single_interrupt+0xdf/0x11b
 [<ffffffff8101804f>] smp_call_function_single_interrupt+0x22/0x31
 [<ffffffff810029f3>] call_function_single_interrupt+0x13/0x20
 <EOI>  [<ffffffff8102c9a5>] ? wake_up_process+0x10/0x12
 [<ffffffff81008701>] ? default_idle+0x22/0x37
 [<ffffffff8100896d>] c1e_idle+0xdf/0xe6
 [<ffffffff813f1170>] ? atomic_notifier_call_chain+0x13/0x15
 [<ffffffff810012fb>] cpu_idle+0x4b/0x7e
 [<ffffffff813e8a4e>] start_secondary+0x1ae/0x1b2
------------[ cut here ]------------
WARNING: at /local/rrichter/.source/linux/arch/x86/kernel/smp.c:118 native_smp_send_reschedule+0x27/0x53()
Hardware name: Anaheim
Modules linked in:
Pid: 0, comm: swapper Tainted: G      D    2.6.34-rc5-oprofile-x86_64-standard-00210-g8c00f06 #16
Call Trace:
 <IRQ>  [<ffffffff81017f32>] ? native_smp_send_reschedule+0x27/0x53
 [<ffffffff81030ee2>] warn_slowpath_common+0x77/0xa4
 [<ffffffff81030f1e>] warn_slowpath_null+0xf/0x11
 [<ffffffff81017f32>] native_smp_send_reschedule+0x27/0x53
 [<ffffffff8102634b>] resched_task+0x60/0x62
 [<ffffffff8102653a>] check_preempt_curr_idle+0x10/0x12
 [<ffffffff8102c8ea>] try_to_wake_up+0x1f5/0x284
 [<ffffffff8102c986>] default_wake_function+0xd/0xf
 [<ffffffff810a110d>] pollwake+0x57/0x5a
 [<ffffffff8102c979>] ? default_wake_function+0x0/0xf
 [<ffffffff81026be5>] __wake_up_common+0x46/0x75
 [<ffffffff81026ed0>] __wake_up+0x38/0x50
 [<ffffffff81031694>] printk_tick+0x39/0x3b
 [<ffffffff8103ac37>] update_process_times+0x3f/0x5c
 [<ffffffff8104dc63>] tick_periodic+0x5d/0x69
 [<ffffffff8104dc90>] tick_handle_periodic+0x21/0x71
 [<ffffffff81018fd0>] smp_apic_timer_interrupt+0x82/0x95
 [<ffffffff81002853>] apic_timer_interrupt+0x13/0x20
 [<ffffffff81030cb5>] ? panic_blink_one_second+0x0/0x7b
 [<ffffffff813ebdd6>] ? panic+0x10a/0x10c
 [<ffffffff810474b0>] ? up+0x34/0x39
 [<ffffffff81031ccc>] ? kmsg_dump+0x112/0x12c
 [<ffffffff813eeff1>] ? oops_end+0x81/0x8e
 [<ffffffff8101efee>] ? no_context+0x1f3/0x202
 [<ffffffff8101f1b7>] ? __bad_area_nosemaphore+0x1ba/0x1e0
 [<ffffffff81028d24>] ? enqueue_task_fair+0x16d/0x17a
 [<ffffffff810264dc>] ? activate_task+0x42/0x53
 [<ffffffff8102c967>] ? try_to_wake_up+0x272/0x284
 [<ffffffff8101f1eb>] ? bad_area_nosemaphore+0xe/0x10
 [<ffffffff813f0f3f>] ? do_page_fault+0x1c8/0x37c
 [<ffffffff81028d24>] ? enqueue_task_fair+0x16d/0x17a
 [<ffffffff813ee55f>] ? page_fault+0x1f/0x30
 [<ffffffff8102c9a5>] ? wake_up_process+0x10/0x12
 [<ffffffff8132ad57>] ? op_amd_stop+0x2d/0x8e
 [<ffffffff8132ad46>] ? op_amd_stop+0x1c/0x8e
 [<ffffffff8132a602>] ? nmi_cpu_stop+0x21/0x23
 [<ffffffff810521b3>] ? generic_smp_call_function_single_interrupt+0xdf/0x11b
 [<ffffffff8101804f>] ? smp_call_function_single_interrupt+0x22/0x31
 [<ffffffff810029f3>] ? call_function_single_interrupt+0x13/0x20
 <EOI>  [<ffffffff8102c9a5>] ? wake_up_process+0x10/0x12
 [<ffffffff81008701>] ? default_idle+0x22/0x37
 [<ffffffff8100896d>] ? c1e_idle+0xdf/0xe6
 [<ffffffff813f1170>] ? atomic_notifier_call_chain+0x13/0x15
 [<ffffffff810012fb>] ? cpu_idle+0x4b/0x7e
 [<ffffffff813e8a4e>] ? start_secondary+0x1ae/0x1b2
---[ end trace 679ac372d674b758 ]---
arch/x86/oprofile/nmi_int.c +8 -2
@@ -95,7 +95,10 @@ static void nmi_cpu_save_registers(struct op_msrs *msrs)
 static void nmi_cpu_start(void *dummy)
 {
 	struct op_msrs const *msrs = &__get_cpu_var(cpu_msrs);
-	model->start(msrs);
+	if (!msrs->controls)
+		WARN_ON_ONCE(1);
+	else
+		model->start(msrs);
 }
 
 static int nmi_start(void)
@@ -107,7 +110,10 @@ static int nmi_start(void)
 static void nmi_cpu_stop(void *dummy)
 {
 	struct op_msrs const *msrs = &__get_cpu_var(cpu_msrs);
-	model->stop(msrs);
+	if (!msrs->controls)
+		WARN_ON_ONCE(1);
+	else
+		model->stop(msrs);
 }
 
 static void nmi_stop(void)
#447 lore raw

PATCH 2/200 oprofile: remove double ring buffering

In reply to Greg KH

2.6.34-stable review patch. If anyone has any objections, please let me know.

------------------

From: Andi Kleen <[email protected]>

commit cb6e943ccf19ab6d3189147e9d625a992e016084 upstream.

oprofile used a double buffer scheme for its cpu event buffer to avoid races on reading with the old locked ring buffer.

But that is obsolete now with the new ring buffer, so simply use a single buffer. This greatly simplifies the code and avoids a lot of sample drops on large runs, especially with call graph.

Based on suggestions from Steven Rostedt

For stable kernels from v2.6.32, but not earlier.

---
 drivers/oprofile/cpu_buffer.c |   63 ++++++++----------------------------------
 1 file changed, 13 insertions(+), 50 deletions(-)
drivers/oprofile/cpu_buffer.c +13 -50
@@ -30,23 +30,7 @@
 
 #define OP_BUFFER_FLAGS	0
 
-/*
- * Read and write access is using spin locking. Thus, writing to the
- * buffer by NMI handler (x86) could occur also during critical
- * sections when reading the buffer. To avoid this, there are 2
- * buffers for independent read and write access. Read access is in
- * process context only, write access only in the NMI handler. If the
- * read buffer runs empty, both buffers are swapped atomically. There
- * is potentially a small window during swapping where the buffers are
- * disabled and samples could be lost.
- *
- * Using 2 buffers is a little bit overhead, but the solution is clear
- * and does not require changes in the ring buffer implementation. It
- * can be changed to a single buffer solution when the ring buffer
- * access is implemented as non-locking atomic code.
- */
-static struct ring_buffer *op_ring_buffer_read;
-static struct ring_buffer *op_ring_buffer_write;
+static struct ring_buffer *op_ring_buffer;
 DEFINE_PER_CPU(struct oprofile_cpu_buffer, op_cpu_buffer);
 
 static void wq_sync_buffer(struct work_struct *work);
@@ -68,12 +52,9 @@ void oprofile_cpu_buffer_inc_smpl_lost(v
 
 void free_cpu_buffers(void)
 {
-	if (op_ring_buffer_read)
-		ring_buffer_free(op_ring_buffer_read);
-	op_ring_buffer_read = NULL;
-	if (op_ring_buffer_write)
-		ring_buffer_free(op_ring_buffer_write);
-	op_ring_buffer_write = NULL;
+	if (op_ring_buffer)
+		ring_buffer_free(op_ring_buffer);
+	op_ring_buffer = NULL;
 }
 
 #define RB_EVENT_HDR_SIZE 4
@@ -86,11 +67,8 @@ int alloc_cpu_buffers(void)
 	unsigned long byte_size = buffer_size * (sizeof(struct op_sample) +
 						 RB_EVENT_HDR_SIZE);
 
-	op_ring_buffer_read = ring_buffer_alloc(byte_size, OP_BUFFER_FLAGS);
-	if (!op_ring_buffer_read)
-		goto fail;
-	op_ring_buffer_write = ring_buffer_alloc(byte_size, OP_BUFFER_FLAGS);
-	if (!op_ring_buffer_write)
+	op_ring_buffer = ring_buffer_alloc(byte_size, OP_BUFFER_FLAGS);
+	if (!op_ring_buffer)
 		goto fail;
 
 	for_each_possible_cpu(i) {
@@ -162,16 +140,11 @@ struct op_sample
 *op_cpu_buffer_write_reserve(struct op_entry *entry, unsigned long size)
 {
 	entry->event = ring_buffer_lock_reserve
-		(op_ring_buffer_write, sizeof(struct op_sample) +
+		(op_ring_buffer, sizeof(struct op_sample) +
 		 size * sizeof(entry->sample->data[0]));
-	if (entry->event)
-		entry->sample = ring_buffer_event_data(entry->event);
-	else
-		entry->sample = NULL;
-
-	if (!entry->sample)
+	if (!entry->event)
 		return NULL;
-
+	entry->sample = ring_buffer_event_data(entry->event);
 	entry->size = size;
 	entry->data = entry->sample->data;
 
@@ -180,25 +153,16 @@ struct op_sample
 
 int op_cpu_buffer_write_commit(struct op_entry *entry)
 {
-	return ring_buffer_unlock_commit(op_ring_buffer_write, entry->event);
+	return ring_buffer_unlock_commit(op_ring_buffer, entry->event);
 }
 
 struct op_sample *op_cpu_buffer_read_entry(struct op_entry *entry, int cpu)
 {
 	struct ring_buffer_event *e;
-	e = ring_buffer_consume(op_ring_buffer_read, cpu, NULL);
-	if (e)
-		goto event;
-	if (ring_buffer_swap_cpu(op_ring_buffer_read,
-				 op_ring_buffer_write,
-				 cpu))
+	e = ring_buffer_consume(op_ring_buffer, cpu, NULL);
+	if (!e)
 		return NULL;
-	e = ring_buffer_consume(op_ring_buffer_read, cpu, NULL);
-	if (e)
-		goto event;
-	return NULL;
 
-event:
 	entry->event = e;
 	entry->sample = ring_buffer_event_data(e);
 	entry->size = (ring_buffer_event_length(e) - sizeof(struct op_sample))
@@ -209,8 +173,7 @@ event:
 
 unsigned long op_cpu_buffer_entries(int cpu)
 {
-	return ring_buffer_entries_cpu(op_ring_buffer_read, cpu)
-		+ ring_buffer_entries_cpu(op_ring_buffer_write, cpu);
+	return ring_buffer_entries_cpu(op_ring_buffer, cpu);
 }
 
 static int
#448 lore raw

PATCH 4/200 perf: Fix exit() vs PERF_FORMAT_GROUP

In reply to Greg KH

2.6.34-stable review patch. If anyone has any objections, please let me know.

------------------

From: Peter Zijlstra <[email protected]>

commit 050735b08ca8a016bbace4445fa025b88fee770b upstream.

Both Stephane and Corey reported that PERF_FORMAT_GROUP didn't work as expected if the task the counters were attached to quit before the read() call.

The cause is that we unconditionally destroy the grouping when we remove counters from their context. Fix this by splitting off the group destroy from the list removal such that perf_event_remove_from_context() does not do this and change perf_event_release() to do so.

Cc Arnaldo Carvalho de Melo <[email protected]>
Cc Frederic Weisbecker <[email protected]>
Cc Paul Mackerras <[email protected]>

LKML-Reference: <1273571513.5605.3527.camel@twins>

---
 kernel/perf_event.c |   19 ++++++++++++++++---
 1 file changed, 16 insertions(+), 3 deletions(-)
kernel/perf_event.c +16 -3
@@ -315,8 +315,6 @@ list_add_event(struct perf_event *event,
 static void
 list_del_event(struct perf_event *event, struct perf_event_context *ctx)
 {
-	struct perf_event *sibling, *tmp;
-
 	if (list_empty(&event->group_entry))
 		return;
 	ctx->nr_events--;
@@ -340,6 +338,12 @@ list_del_event(struct perf_event *event,
 	 */
 	if (event->state > PERF_EVENT_STATE_OFF)
 		event->state = PERF_EVENT_STATE_OFF;
+}
+
+static void
+perf_destroy_group(struct perf_event *event, struct perf_event_context *ctx)
+{
+	struct perf_event *sibling, *tmp;
 
 	/*
 	 * If this was a group event with sibling events then
@@ -1856,9 +1860,18 @@ int perf_event_release_kernel(struct per
 {
 	struct perf_event_context *ctx = event->ctx;
 
+	/*
+	 * Remove from the PMU, can't get re-enabled since we got
+	 * here because the last ref went.
+	 */
+	perf_event_disable(event);
+
 	WARN_ON_ONCE(ctx->parent_ctx);
 	mutex_lock(&ctx->mutex);
-	perf_event_remove_from_context(event);
+	raw_spin_lock_irq(&ctx->lock);
+	list_del_event(event, ctx);
+	perf_destroy_group(event, ctx);
+	raw_spin_unlock_irq(&ctx->lock);
 	mutex_unlock(&ctx->mutex);
 
 	mutex_lock(&event->owner->perf_event_mutex);
#449 lore raw

PATCH 5/200 perf top: Properly notify the user that vmlinux is missing

In reply to Greg KH

2.6.34-stable review patch. If anyone has any objections, please let me know.

------------------

From: Arnaldo Carvalho de Melo <[email protected]>

commit b0a9ab62ab96e258a0ddd81d7fe2719c3db36006 upstream.

Before this patch this message would very briefly appear on the screen and then the screen would get updates only on the top, for number of interrupts received, etc, but no annotation would be performed:

[root@doppio linux-2.6-tip]# perf top -s n_tty_write > /tmp/bla
objdump: '[kernel.kallsyms]': No such file

Now this is what the user gets:

[root@doppio linux-2.6-tip]# perf top -s n_tty_write Can't annotate n_tty_write: No vmlinux file was found in the
path: [0] vmlinux
[1] /boot/vmlinux
[2] /boot/vmlinux-2.6.33-rc5
[3] /lib/modules/2.6.33-rc5/build/vmlinux
[4] /usr/lib/debug/lib/modules/2.6.33-rc5/vmlinux [root@doppio linux-2.6-tip]#

This bug was introduced when we added automatic search for vmlinux, before that time the user had to specify a vmlinux file.

Cc Frédéric Weisbecker <[email protected]>
Cc Mike Galbraith <[email protected]>
Cc Peter Zijlstra <[email protected]>
Cc Paul Mackerras <[email protected]>

LKML-Reference: <[email protected]>

---
 tools/perf/builtin-top.c |   33 +++++++++++++++++++++++++--------
 tools/perf/util/symbol.c |   25 ++++++++++++-------------
 tools/perf/util/symbol.h |   15 +++++++++++++++
 3 files changed, 52 insertions(+), 21 deletions(-)
tools/perf/builtin-top.c +25 -8
@@ -169,7 +169,7 @@ static void sig_winch_handler(int sig __
 	update_print_entries(&winsize);
 }
 
-static void parse_source(struct sym_entry *syme)
+static int parse_source(struct sym_entry *syme)
 {
 	struct symbol *sym;
 	struct sym_entry_source *source;
@@ -180,12 +180,21 @@ static void parse_source(struct sym_entr
 	u64 len;
 
 	if (!syme)
-		return;
+		return -1;
+
+	sym = sym_entry__symbol(syme);
+	map = syme->map;
+
+	/*
+	 * We can't annotate with just /proc/kallsyms
+	 */
+	if (map->dso->origin == DSO__ORIG_KERNEL)
+		return -1;
 
 	if (syme->src == NULL) {
 		syme->src = zalloc(sizeof(*source));
 		if (syme->src == NULL)
-			return;
+			return -1;
 		pthread_mutex_init(&syme->src->lock, NULL);
 	}
 
@@ -195,9 +204,6 @@ static void parse_source(struct sym_entr
 		pthread_mutex_lock(&source->lock);
 		goto out_assign;
 	}
-
-	sym = sym_entry__symbol(syme);
-	map = syme->map;
 	path = map->dso->long_name;
 
 	len = sym->end - sym->start;
@@ -209,7 +215,7 @@ static void parse_source(struct sym_entr
 
 	file = popen(command, "r");
 	if (!file)
-		return;
+		return -1;
 
 	pthread_mutex_lock(&source->lock);
 	source->lines_tail = &source->lines;
@@ -245,6 +251,7 @@ static void parse_source(struct sym_entr
 out_assign:
 	sym_filter_entry = syme;
 	pthread_mutex_unlock(&source->lock);
+	return 0;
 }
 
 static void __zero_source_counters(struct sym_entry *syme)
@@ -990,7 +997,17 @@ static void event__process_sample(const
 	if (sym_filter_entry_sched) {
 		sym_filter_entry = sym_filter_entry_sched;
 		sym_filter_entry_sched = NULL;
-		parse_source(sym_filter_entry);
+		if (parse_source(sym_filter_entry) < 0) {
+			struct symbol *sym = sym_entry__symbol(sym_filter_entry);
+
+			pr_err("Can't annotate %s", sym->name);
+			if (sym_filter_entry->map->dso->origin == DSO__ORIG_KERNEL) {
+				pr_err(": No vmlinux file was found in the path:\n");
+				vmlinux_path__fprintf(stderr);
+			} else
+				pr_err(".\n");
+			exit(1);
+		}
 	}
 
 	syme = symbol__priv(al.sym);
tools/perf/util/symbol.c +12 -13
@@ -18,18 +18,6 @@
 #define NT_GNU_BUILD_ID 3
 #endif
 
-enum dso_origin {
-	DSO__ORIG_KERNEL = 0,
-	DSO__ORIG_JAVA_JIT,
-	DSO__ORIG_BUILD_ID_CACHE,
-	DSO__ORIG_FEDORA,
-	DSO__ORIG_UBUNTU,
-	DSO__ORIG_BUILDID,
-	DSO__ORIG_DSO,
-	DSO__ORIG_KMODULE,
-	DSO__ORIG_NOT_FOUND,
-};
-
 static void dsos__add(struct list_head *head, struct dso *dso);
 static struct map *map__new2(u64 start, struct dso *dso, enum map_type type);
 static int dso__load_kernel_sym(struct dso *self, struct map *map,
@@ -1025,7 +1013,7 @@ static int dso__load_sym(struct dso *sel
 				}
 				curr_map->map_ip = identity__map_ip;
 				curr_map->unmap_ip = identity__map_ip;
-				curr_dso->origin = DSO__ORIG_KERNEL;
+				curr_dso->origin = self->origin;
 				map_groups__insert(kmap->kmaps, curr_map);
 				dsos__add(&dsos__kernel, curr_dso);
 				dso__set_loaded(curr_dso, map->type);
@@ -1895,6 +1883,17 @@ out_fail:
 	return -1;
 }
 
+size_t vmlinux_path__fprintf(FILE *fp)
+{
+	int i;
+	size_t printed = 0;
+
+	for (i = 0; i < vmlinux_path__nr_entries; ++i)
+		printed += fprintf(fp, "[%d] %s\n", i, vmlinux_path[i]);
+
+	return printed;
+}
+
 static int setup_list(struct strlist **list, const char *list_str,
 		      const char *list_name)
 {
tools/perf/util/symbol.h +15 -0
@@ -150,6 +150,19 @@ size_t dsos__fprintf_buildid(FILE *fp, b
 
 size_t dso__fprintf_buildid(struct dso *self, FILE *fp);
 size_t dso__fprintf(struct dso *self, enum map_type type, FILE *fp);
+
+enum dso_origin {
+	DSO__ORIG_KERNEL = 0,
+	DSO__ORIG_JAVA_JIT,
+	DSO__ORIG_BUILD_ID_CACHE,
+	DSO__ORIG_FEDORA,
+	DSO__ORIG_UBUNTU,
+	DSO__ORIG_BUILDID,
+	DSO__ORIG_DSO,
+	DSO__ORIG_KMODULE,
+	DSO__ORIG_NOT_FOUND,
+};
+
 char dso__symtab_origin(const struct dso *self);
 void dso__set_long_name(struct dso *self, char *name);
 void dso__set_build_id(struct dso *self, void *build_id);
@@ -169,4 +182,6 @@ int kallsyms__parse(const char *filename
 int symbol__init(void);
 bool symbol_type__is_a(char symbol_type, enum map_type map_type);
 
+size_t vmlinux_path__fprintf(FILE *fp);
+
 #endif /* __PERF_SYMBOL */
#450 lore raw

PATCH 6/200 perf: Fix exit() vs event-groups

In reply to Greg KH

2.6.34-stable review patch. If anyone has any objections, please let me know.

------------------

From: Peter Zijlstra <[email protected]>

commit 96c21a460a37880abfbc8445d5b098dbab958a29 upstream.

Corey reported that the value scale times of group siblings are not updated when the monitored task dies.

The problem appears to be that we only update the group leader's time values, fix it by updating the whole group.

Cc Paul Mackerras <[email protected]>
Cc Mike Galbraith <[email protected]>
Cc Arnaldo Carvalho de Melo <[email protected]>
Cc Frederic Weisbecker <[email protected]>

LKML-Reference: <1273588935.1810.6.camel@laptop>

---
 kernel/perf_event.c |   26 +++++++++++++-------------
 1 file changed, 13 insertions(+), 13 deletions(-)
kernel/perf_event.c +13 -13
@@ -262,6 +262,18 @@ static void update_event_times(struct pe
 	event->total_time_running = run_end - event->tstamp_running;
 }
 
+/*
+ * Update total_time_enabled and total_time_running for all events in a group.
+ */
+static void update_group_times(struct perf_event *leader)
+{
+	struct perf_event *event;
+
+	update_event_times(leader);
+	list_for_each_entry(event, &leader->sibling_list, group_entry)
+		update_event_times(event);
+}
+
 static struct list_head *
 ctx_group_list(struct perf_event *event, struct perf_event_context *ctx)
 {
@@ -327,7 +339,7 @@ list_del_event(struct perf_event *event,
 	if (event->group_leader != event)
 		event->group_leader->nr_siblings--;
 
-	update_event_times(event);
+	update_group_times(event);
 
 	/*
 	 * If event was in error state, then keep it
@@ -509,18 +521,6 @@ retry:
 }
 
 /*
- * Update total_time_enabled and total_time_running for all events in a group.
- */
-static void update_group_times(struct perf_event *leader)
-{
-	struct perf_event *event;
-
-	update_event_times(leader);
-	list_for_each_entry(event, &leader->sibling_list, group_entry)
-		update_event_times(event);
-}
-
-/*
  * Cross CPU call to disable a performance event
  */
 static void __perf_event_disable(void *info)
#451 lore raw

PATCH 7/200 Fix racy use of anon_inode_getfd() in perf_event.c

In reply to Greg KH

2.6.34-stable review patch. If anyone has any objections, please let me know.

------------------

From: Al Viro <[email protected]>

commit ea635c64e007061f6468ece5cc9cc62d41d4ecf2 upstream.

once anon_inode_getfd() is called, you can't expect *anything* about struct file that descriptor points to - another thread might be doing whatever it likes with descriptor table at that point.

---
 kernel/perf_event.c |   40 ++++++++++++++++++++++------------------
 1 file changed, 22 insertions(+), 18 deletions(-)
kernel/perf_event.c +22 -18
@@ -4811,8 +4811,8 @@ SYSCALL_DEFINE5(perf_event_open,
 	struct perf_event_context *ctx;
 	struct file *event_file = NULL;
 	struct file *group_file = NULL;
+	int event_fd;
 	int fput_needed = 0;
-	int fput_needed2 = 0;
 	int err;
 
 	/* for future expandability... */
@@ -4833,12 +4833,18 @@ SYSCALL_DEFINE5(perf_event_open,
 			return -EINVAL;
 	}
 
+	event_fd = get_unused_fd_flags(O_RDWR);
+	if (event_fd < 0)
+		return event_fd;
+
 	/*
 	 * Get the target context (task or percpu):
 	 */
 	ctx = find_get_context(pid, cpu);
-	if (IS_ERR(ctx))
-		return PTR_ERR(ctx);
+	if (IS_ERR(ctx)) {
+		err = PTR_ERR(ctx);
+		goto err_fd;
+	}
 
 	/*
 	 * Look up the group leader (we will attach this event to it):
@@ -4878,13 +4884,11 @@ SYSCALL_DEFINE5(perf_event_open,
 	if (IS_ERR(event))
 		goto err_put_context;
 
-	err = anon_inode_getfd("[perf_event]", &perf_fops, event, O_RDWR);
-	if (err < 0)
-		goto err_free_put_context;
-
-	event_file = fget_light(err, &fput_needed2);
-	if (!event_file)
+	event_file = anon_inode_getfile("[perf_event]", &perf_fops, event, O_RDWR);
+	if (IS_ERR(event_file)) {
+		err = PTR_ERR(event_file);
 		goto err_free_put_context;
+	}
 
 	if (flags & PERF_FLAG_FD_OUTPUT) {
 		err = perf_event_set_output(event, group_fd);
@@ -4905,19 +4909,19 @@ SYSCALL_DEFINE5(perf_event_open,
 	list_add_tail(&event->owner_entry, &current->perf_event_list);
 	mutex_unlock(&current->perf_event_mutex);
 
-err_fput_free_put_context:
-	fput_light(event_file, fput_needed2);
+	fput_light(group_file, fput_needed);
+	fd_install(event_fd, event_file);
+	return event_fd;
 
+err_fput_free_put_context:
+	fput(event_file);
 err_free_put_context:
-	if (err < 0)
-		free_event(event);
-
+	free_event(event);
 err_put_context:
-	if (err < 0)
-		put_ctx(ctx);
-
 	fput_light(group_file, fput_needed);
-
+	put_ctx(ctx);
+err_fd:
+	put_unused_fd(event_fd);
 	return err;
 }
 
#452 lore raw

PATCH 8/200 VFS: fix recent breakage of FS_REVAL_DOT

In reply to Greg KH

2.6.34-stable review patch. If anyone has any objections, please let me know.

------------------

From: Neil Brown <[email protected]>

commit 176306f59ac7a35369cbba87aff13e14c5916074 upstream.

Commit 1f36f774b22a0ceb7dd33eca626746c81a97b6a5 broke FS_REVAL_DOT semantics.

In particular, before this patch, the command
ls -l
in an NFS mounted directory would always check if the directory on the server had changed and if so would flush and refill the pagecache for the dir. After this patch, the same "ls -l" will repeatedly return stale date until the cached attributes for the directory time out.

The following patch fixes this by ensuring the d_revalidate is called by do_last when "." is being looked-up.
link_path_walk has already called d_revalidate, but in that case LOOKUP_OPEN is not set so nfs_lookup_verify_inode chooses not to do any validation.

The following patch restores the original behaviour.

---
 fs/namei.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
fs/namei.c +1 -1
@@ -1620,6 +1620,7 @@ static struct file *do_last(struct namei
 	case LAST_DOTDOT:
 		follow_dotdot(nd);
 		dir = nd->path.dentry;
+	case LAST_DOT:
 		if (nd->path.mnt->mnt_sb->s_type->fs_flags & FS_REVAL_DOT) {
 			if (!dir->d_op->d_revalidate(dir, nd)) {
 				error = -ESTALE;
@@ -1627,7 +1628,6 @@ static struct file *do_last(struct namei
 			}
 		}
 		/* fallthrough */
-	case LAST_DOT:
 	case LAST_ROOT:
 		if (open_flag & O_CREAT)
 			goto exit;
#453 lore raw

PATCH 9/200 posix_timer: Fix error path in timer_create

In reply to Greg KH

2.6.34-stable review patch. If anyone has any objections, please let me know.

------------------

From: Andrey Vagin <[email protected]>

commit 45e0fffc8a7778282e6a1514a6ae3e7ae6545111 upstream.

Move CLOCK_DISPATCH(which_clock, timer_create, (new_timer)) after all posible EFAULT erros.

*_timer_create may allocate/get resources.
(for example posix_cpu_timer_create does get_task_struct)

[ tglx: fold the remove crappy comment patch into this ]

---
 kernel/posix-timers.c |   11 ++++-------
 1 file changed, 4 insertions(+), 7 deletions(-)
kernel/posix-timers.c +4 -7
@@ -559,14 +559,7 @@ SYSCALL_DEFINE3(timer_create, const cloc
 	new_timer->it_id = (timer_t) new_timer_id;
 	new_timer->it_clock = which_clock;
 	new_timer->it_overrun = -1;
-	error = CLOCK_DISPATCH(which_clock, timer_create, (new_timer));
-	if (error)
-		goto out;
 
-	/*
-	 * return the timer_id now.  The next step is hard to
-	 * back out if there is an error.
-	 */
 	if (copy_to_user(created_timer_id,
 			 &new_timer_id, sizeof (new_timer_id))) {
 		error = -EFAULT;
@@ -597,6 +590,10 @@ SYSCALL_DEFINE3(timer_create, const cloc
 	new_timer->sigq->info.si_tid   = new_timer->it_id;
 	new_timer->sigq->info.si_code  = SI_TIMER;
 
+	error = CLOCK_DISPATCH(which_clock, timer_create, (new_timer));
+	if (error)
+		goto out;
+
 	spin_lock_irq(&current->sighand->siglock);
 	new_timer->it_signal = current->signal;
 	list_add(&new_timer->list, &current->signal->posix_timers);
#454 lore raw

PATCH 10/200 libata: disable ATAPI AN by default

In reply to Greg KH

2.6.34-stable review patch. If anyone has any objections, please let me know.

------------------

From: Tejun Heo <[email protected]>

commit e7ecd435692ca9bde9d124be30b3a26e672ea6c2 upstream.

There are ATAPI devices which raise AN when hit by commands issued by open(). This leads to infinite loop of AN -> MEDIA_CHANGE uevent -> udev open() to check media -> AN.

Both ACS and SerialATA standards don't define in which case ATAPI devices are supposed to raise or not raise AN. They both list media insertion event as a possible use case for ATAPI ANs but there is no clear description of what constitutes such events. As such, it seems a bit too naive to export ANs directly to userland as MEDIA_CHANGE events without further verification (which should behave similarly to windows as it apparently is the only thing that some hardware vendors are testing against).

This patch adds libata.atapi_an module parameter and disables ATAPI AN by default for now.

---
 drivers/ata/libata-core.c |    7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)
drivers/ata/libata-core.c +6 -1
@@ -160,6 +160,10 @@ int libata_allow_tpm = 0;
 module_param_named(allow_tpm, libata_allow_tpm, int, 0444);
 MODULE_PARM_DESC(allow_tpm, "Permit the use of TPM commands (0=off [default], 1=on)");
 
+static int atapi_an;
+module_param(atapi_an, int, 0444);
+MODULE_PARM_DESC(atapi_an, "Enable ATAPI AN media presence notification (0=0ff [default], 1=on)");
+
 MODULE_AUTHOR("Jeff Garzik");
 MODULE_DESCRIPTION("Library module for ATA devices");
 MODULE_LICENSE("GPL");
@@ -2572,7 +2576,8 @@ int ata_dev_configure(struct ata_device
 		 * to enable ATAPI AN to discern between PHY status
 		 * changed notifications and ATAPI ANs.
 		 */
-		if ((ap->flags & ATA_FLAG_AN) && ata_id_has_atapi_AN(id) &&
+		if (atapi_an &&
+		    (ap->flags & ATA_FLAG_AN) && ata_id_has_atapi_AN(id) &&
 		    (!sata_pmp_attached(ap) ||
 		     sata_scr_read(&ap->link, SCR_NOTIFICATION, &sntf) == 0)) {
 			unsigned int err_mask;
#455 lore raw

PATCH 11/200 libata: dont flush dcache on slab pages

In reply to Greg KH

2.6.34-stable review patch. If anyone has any objections, please let me know.

------------------

From: Sebastian Andrzej Siewior <[email protected]>

commit 3842e835490cdf17013b30a788f6311bdcfd0571 upstream.

page_mapping() check this via VM_BUG_ON(PageSlab(page)) so we bug here with the according debuging turned on.

Future TODO: replace this with a flush_dcache_page_for_pio() API

---
 drivers/ata/libata-sff.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/ata/libata-sff.c +1 -1
@@ -894,7 +894,7 @@ static void ata_pio_sector(struct ata_qu
 				       do_write);
 	}
 
-	if (!do_write)
+	if (!do_write && !PageSlab(page))
 		flush_dcache_page(page);
 
 	qc->curbytes += qc->sect_size;
#456 lore raw

PATCH 12/200 cpumask: fix compat getaffinity

In reply to Greg KH

2.6.34-stable review patch. If anyone has any objections, please let me know.

------------------

From: KOSAKI Motohiro <[email protected]>

commit fa9dc265ace9774e62f0e31108e5f47911124bda upstream.

Commit a45185d2d "cpumask: convert kernel/compat.c" broke libnuma, which abuses sched_getaffinity to find out NR_CPUS in order to parse /sys/devices/system/node/node*/cpumap.

On NUMA systems with less than 32 possibly CPUs, the current compat_sys_sched_getaffinity now returns '4' instead of the actual NR_CPUS/8, which makes libnuma bail out when parsing the cpumap.

The libnuma call sched_getaffinity(0, bitmap, 4096) at first. It mean the libnuma expect the return value of sched_getaffinity() is either len argument or NR_CPUS. But it doesn't expect to return nr_cpu_ids.

Strictly speaking, userland requirement are

1) Glibc assume the return value mean the lengh of initialized of mask argument. E.g. if sched_getaffinity(1024) return 128, glibc make zero fill rest 896 byte.
2) Libnuma assume the return value can be used to guess NR_CPUS in kernel. It assume len-arg<NR_CPUS makes -EINVAL. But it try len=4096 at first and 4096 is always bigger than NR_CPUS. Then, if we remove strange min_length normalization, we never hit -EINVAL case.

sched_getaffinity() already solved this issue. This patch adapts compat_sys_sched_getaffinity() to match the non-compat case.

---
 kernel/compat.c |   25 +++++++++++--------------
 1 file changed, 11 insertions(+), 14 deletions(-)
kernel/compat.c +11 -14
@@ -495,29 +495,26 @@ asmlinkage long compat_sys_sched_getaffi
 {
 	int ret;
 	cpumask_var_t mask;
-	unsigned long *k;
-	unsigned int min_length = cpumask_size();
 
-	if (nr_cpu_ids <= BITS_PER_COMPAT_LONG)
-		min_length = sizeof(compat_ulong_t);
-
-	if (len < min_length)
+	if ((len * BITS_PER_BYTE) < nr_cpu_ids)
+		return -EINVAL;
+	if (len & (sizeof(compat_ulong_t)-1))
 		return -EINVAL;
 
 	if (!alloc_cpumask_var(&mask, GFP_KERNEL))
 		return -ENOMEM;
 
 	ret = sched_getaffinity(pid, mask);
-	if (ret < 0)
-		goto out;
+	if (ret == 0) {
+		size_t retlen = min_t(size_t, len, cpumask_size());
 
-	k = cpumask_bits(mask);
-	ret = compat_put_bitmap(user_mask_ptr, k, min_length * 8);
-	if (ret == 0)
-		ret = min_length;
-
-out:
+		if (compat_put_bitmap(user_mask_ptr, cpumask_bits(mask), retlen * 8))
+			ret = -EFAULT;
+		else
+			ret = retlen;
+	}
 	free_cpumask_var(mask);
+
 	return ret;
 }
 
#457 lore raw

PATCH 13/200 NFSD: dont report compiled-out versions as present

In reply to Greg KH

2.6.34-stable review patch. If anyone has any objections, please let me know.

------------------

From: Pavel Emelyanov <[email protected]>

commit 15ddb4aec54422ead137b03ea4e9b3f5db3f7cc2 upstream.

The /proc/fs/nfsd/versions file calls nfsd_vers() to check whether the particular nfsd version is present/available. The problem is that once I turn off e.g. NFSD-V4 this call returns -1 which is true from the callers POV which is wrong.

The proposal is to report false in that case.

The bug has existed since 6658d3a7bbfd1768 "[PATCH] knfsd: remove nfsd_versbits as intermediate storage for desired versions".

---
 fs/nfsd/nfssvc.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
fs/nfsd/nfssvc.c +1 -1
@@ -120,7 +120,7 @@ u32 nfsd_supported_minorversion;
 int nfsd_vers(int vers, enum vers_op change)
 {
 	if (vers < NFSD_MINVERS || vers >= NFSD_NRVERS)
-		return -1;
+		return 0;
 	switch(change) {
 	case NFSD_SET:
 		nfsd_versions[vers] = nfsd_version[vers];
#458 lore raw

PATCH 14/200 nfsd: dont break lease while servicing a COMMIT

In reply to Greg KH

2.6.34-stable review patch. If anyone has any objections, please let me know.

------------------

From: Jeff Layton <[email protected]>

commit 91885258e8343bb65c08f668d7e6c16563eb4284 upstream.

This is the second attempt to fix the problem whereby a COMMIT call causes a lease break and triggers a possible deadlock.

The problem is that nfsd attempts to break a lease on a COMMIT call. This triggers a delegation recall if the lease is held for a delegation. If the client is the one holding the delegation and it's the same one on which it's issuing the COMMIT, then it can't return that delegation until the COMMIT is complete. But, nfsd won't complete the COMMIT until the delegation is returned. The client and server are essentially deadlocked until the state is marked bad (due to the client not responding on the callback channel).

The first patch attempted to deal with this by eliminating the open of the file altogether and simply had nfsd_commit pass a NULL file pointer to the vfs_fsync_range. That would conflict with some work in progress by Christoph Hellwig to clean up the fsync interface, so this patch takes a different approach.

This declares a new NFSD_MAY_NOT_BREAK_LEASE access flag that indicates to nfsd_open that it should not break any leases when opening the file, and has nfsd_commit set that flag on the nfsd_open call.

For now, this patch leaves nfsd_commit opening the file with write access since I'm not clear on what sort of access would be more appropriate.

---
 fs/nfsd/vfs.c |    8 +++++---
 fs/nfsd/vfs.h |    1 +
 2 files changed, 6 insertions(+), 3 deletions(-)
fs/nfsd/vfs.c +5 -3
@@ -724,7 +724,7 @@ nfsd_open(struct svc_rqst *rqstp, struct
 	struct inode	*inode;
 	int		flags = O_RDONLY|O_LARGEFILE;
 	__be32		err;
-	int		host_err;
+	int		host_err = 0;
 
 	validate_process_creds();
 
@@ -761,7 +761,8 @@ nfsd_open(struct svc_rqst *rqstp, struct
 	 * Check to see if there are any leases on this file.
 	 * This may block while leases are broken.
 	 */
-	host_err = break_lease(inode, O_NONBLOCK | ((access & NFSD_MAY_WRITE) ? O_WRONLY : 0));
+	if (!(access & NFSD_MAY_NOT_BREAK_LEASE))
+		host_err = break_lease(inode, O_NONBLOCK | ((access & NFSD_MAY_WRITE) ? O_WRONLY : 0));
 	if (host_err == -EWOULDBLOCK)
 		host_err = -ETIMEDOUT;
 	if (host_err) /* NOMEM or WOULDBLOCK */
@@ -1169,7 +1170,8 @@ nfsd_commit(struct svc_rqst *rqstp, stru
 			goto out;
 	}
 
-	err = nfsd_open(rqstp, fhp, S_IFREG, NFSD_MAY_WRITE, &file);
+	err = nfsd_open(rqstp, fhp, S_IFREG,
+			NFSD_MAY_WRITE|NFSD_MAY_NOT_BREAK_LEASE, &file);
 	if (err)
 		goto out;
 	if (EX_ISSYNC(fhp->fh_export)) {
fs/nfsd/vfs.h +1 -0
@@ -20,6 +20,7 @@
 #define NFSD_MAY_OWNER_OVERRIDE	64
 #define NFSD_MAY_LOCAL_ACCESS	128 /* IRIX doing local access check on device special file*/
 #define NFSD_MAY_BYPASS_GSS_ON_ROOT 256
+#define NFSD_MAY_NOT_BREAK_LEASE 512
 
 #define NFSD_MAY_CREATE		(NFSD_MAY_EXEC|NFSD_MAY_WRITE)
 #define NFSD_MAY_REMOVE		(NFSD_MAY_EXEC|NFSD_MAY_WRITE|NFSD_MAY_TRUNC)
#459 lore raw

PATCH 15/200 sata_nv: use ata_pci_sff_activate_host() instead of ata_host_activate()

In reply to Greg KH

2.6.34-stable review patch. If anyone has any objections, please let me know.

------------------

From: Tejun Heo <[email protected]>

commit 95cc2c70c139936a2142bcd583da8af6f9d88efb upstream.

sata_nv was incorrectly using ata_host_activate() instead of ata_pci_sff_activate_host() leading to IRQ assignment failure in legacy mode. Fix it.

---
 drivers/ata/sata_nv.c |    3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)
drivers/ata/sata_nv.c +1 -2
@@ -2479,8 +2479,7 @@ static int nv_init_one(struct pci_dev *p
 	}
 
 	pci_set_master(pdev);
-	return ata_host_activate(host, pdev->irq, ipriv->irq_handler,
-				 IRQF_SHARED, ipriv->sht);
+	return ata_pci_sff_activate_host(host, ipriv->irq_handler, ipriv->sht);
 }
 
 #ifdef CONFIG_PM
#460 lore raw

PATCH 16/200 ARCNET: Limit com20020 PCI ID matches for SOHARD cards

In reply to Greg KH

2.6.34-stable review patch. If anyone has any objections, please let me know.

------------------

From: Andreas Bombe <[email protected]>

commit e7971c80a8e0299f91272ad8e8ac4167623e1862 upstream.

The SH SOHARD ARCNET cards are implemented using generic PLX Technology PCI<->IOBus bridges. Subvendor and subdevice IDs were not specified, causing the driver to attach to any such bridge and likely crash the system by attempting to initialize an unrelated device.

Fix by specifying subvendor and subdevice according to the values found in the PCI-ID Repository at http://pci-ids.ucw.cz/ .

---
 drivers/net/arcnet/com20020-pci.c |    4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/net/arcnet/com20020-pci.c +2 -2
@@ -164,8 +164,8 @@ static DEFINE_PCI_DEVICE_TABLE(com20020p
 	{ 0x1571, 0xa204, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ARC_CAN_10MBIT },
 	{ 0x1571, 0xa205, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ARC_CAN_10MBIT },
 	{ 0x1571, 0xa206, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ARC_CAN_10MBIT },
-	{ 0x10B5, 0x9030, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ARC_CAN_10MBIT },
-	{ 0x10B5, 0x9050, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ARC_CAN_10MBIT },
+	{ 0x10B5, 0x9030, 0x10B5,     0x2978,     0, 0, ARC_CAN_10MBIT },
+	{ 0x10B5, 0x9050, 0x10B5,     0x2273,     0, 0, ARC_CAN_10MBIT },
 	{ 0x14BA, 0x6000, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ARC_CAN_10MBIT },
 	{ 0x10B5, 0x2200, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ARC_CAN_10MBIT },
 	{0,}
#461 lore raw

PATCH 17/200 rtl8180: fix tx status reporting

In reply to Greg KH

2.6.34-stable review patch. If anyone has any objections, please let me know.

------------------

From: John W. Linville <[email protected]>

commit d989ff7cf8d14f1b523f63ba0bf2ec1a9b7c25bc upstream.

When reporting Tx status, indicate that only one rate was used. Otherwise, the rate is frozen at rate index 0 (i.e. 1Mb/s).

---
 drivers/net/wireless/rtl818x/rtl8180_dev.c |    1 +
 1 file changed, 1 insertion(+)
drivers/net/wireless/rtl818x/rtl8180_dev.c +1 -0
@@ -188,6 +188,7 @@ static void rtl8180_handle_tx(struct iee
 			info->flags |= IEEE80211_TX_STAT_ACK;
 
 		info->status.rates[0].count = (flags & 0xFF) + 1;
+		info->status.rates[1].idx = -1;
 
 		ieee80211_tx_status_irqsafe(dev, skb);
 		if (ring->entries - skb_queue_len(&ring->queue) == 2)
#462 lore raw

PATCH 18/200 staging: vt6655: Fix kernel BUG on driver wpa initialization

In reply to Greg KH

2.6.34-stable review patch. If anyone has any objections, please let me know.

------------------

From: Larry Finger <[email protected]>

commit f65515275ea3e45fdcd0fb78455f542d6fdca086 upstream.

In http://bugzilla.novell.com/show_bug.cgi?id=597299, the vt6655 driver generates a kernel BUG on a NULL pointer dereference at NULL. This problem has been traced to a failure in the wpa_set_wpadev() routine. As the vt6656 driver does not call this routine, the vt6655 code is similarly set to skip the call.

---
 drivers/staging/vt6655/device_main.c |    2 ++
 1 file changed, 2 insertions(+)
drivers/staging/vt6655/device_main.c +2 -0
@@ -1090,11 +1090,13 @@ device_found1(struct pci_dev *pcid, cons
     }
 //2008-07-21-01<Add>by MikeLiu
 //register wpadev
+#if 0
    if(wpa_set_wpadev(pDevice, 1)!=0) {
      printk("Fail to Register WPADEV?\n");
         unregister_netdev(pDevice->dev);
         free_netdev(dev);
    }
+#endif
     device_print_info(pDevice);
     pci_set_drvdata(pcid, pDevice);
     return 0;
#463 lore raw

PATCH 19/200 Staging: rt2870: add device ID of MelCo.,Inc. WLI-UC-G301N

In reply to Greg KH

2.6.34-stable review patch. If anyone has any objections, please let me know.

------------------

From: Nobuhiro KUSUNO <[email protected]>

commit de37cd49b5a54facef174cf34496919857436e8f upstream.

My wireless LAN module 'MelCo.,Inc. WLI-UC-G301N' works fine, if the following line is added into 2870_main_dev.c.

---
 drivers/staging/rt2860/usb_main_dev.c |    1 +
 1 file changed, 1 insertion(+)
drivers/staging/rt2860/usb_main_dev.c +1 -0
@@ -98,6 +98,7 @@ struct usb_device_id rtusb_usb_id[] = {
 	{USB_DEVICE(0x5A57, 0x0282)},	/* Zinwell */
 	{USB_DEVICE(0x7392, 0x7718)},
 	{USB_DEVICE(0x7392, 0x7717)},
+	{USB_DEVICE(0x0411, 0x016f)},	/* MelCo.,Inc. WLI-UC-G301N */
 	{USB_DEVICE(0x1737, 0x0070)},	/* Linksys WUSB100 */
 	{USB_DEVICE(0x1737, 0x0071)},	/* Linksys WUSB600N */
 	{USB_DEVICE(0x0411, 0x00e8)},	/* Buffalo WLI-UC-G300N */
#464 lore raw

PATCH 20/200 Staging: batman-adv: dont have interrupts disabled while sending.

In reply to Greg KH

2.6.34-stable review patch. If anyone has any objections, please let me know.

------------------

From: Andrew Lunn <[email protected]>

commit 107c32fe68f0b64acb7edd31d44d79b87c7fa8b4 upstream.

send_vis_packets() would disable interrupts before calling dev_queue_xmit() which resulting in a backtrace in local_bh_enable(). Fix this by using kref on the vis_info object so that we can call send_vis_packets() without holding vis_hash_lock. vis_hash_lock also used to protect recv_list, so we now need a new lock to protect that instead of vis_hash_lock.

Also a few checkpatch cleanups.

---
 drivers/staging/batman-adv/vis.c |  198 +++++++++++++++++++++++++++------------
 drivers/staging/batman-adv/vis.h |    1 
 2 files changed, 139 insertions(+), 60 deletions(-)
drivers/staging/batman-adv/vis.c +138 -60
@@ -29,22 +29,26 @@
 
 struct hashtable_t *vis_hash;
 DEFINE_SPINLOCK(vis_hash_lock);
+static DEFINE_SPINLOCK(recv_list_lock);
 static struct vis_info *my_vis_info;
 static struct list_head send_list;	/* always locked with vis_hash_lock */
 
 static void start_vis_timer(void);
 
 /* free the info */
-static void free_info(void *data)
+static void free_info(struct kref *ref)
 {
-	struct vis_info *info = data;
+	struct vis_info *info = container_of(ref, struct vis_info, refcount);
 	struct recvlist_node *entry, *tmp;
+	unsigned long flags;
 
 	list_del_init(&info->send_list);
+	spin_lock_irqsave(&recv_list_lock, flags);
 	list_for_each_entry_safe(entry, tmp, &info->recv_list, list) {
 		list_del(&entry->list);
 		kfree(entry);
 	}
+	spin_unlock_irqrestore(&recv_list_lock, flags);
 	kfree(info);
 }
 
@@ -142,36 +146,65 @@ void proc_vis_read_entry(struct seq_file
 	}
 }
 
+/* add the info packet to the send list, if it was not
+ * already linked in. */
+static void send_list_add(struct vis_info *info)
+{
+	if (list_empty(&info->send_list)) {
+		kref_get(&info->refcount);
+		list_add_tail(&info->send_list, &send_list);
+	}
+}
+
+/* delete the info packet from the send list, if it was
+ * linked in. */
+static void send_list_del(struct vis_info *info)
+{
+	if (!list_empty(&info->send_list)) {
+		list_del_init(&info->send_list);
+		kref_put(&info->refcount, free_info);
+	}
+}
+
 /* tries to add one entry to the receive list. */
 static void recv_list_add(struct list_head *recv_list, char *mac)
 {
 	struct recvlist_node *entry;
+	unsigned long flags;
+
 	entry = kmalloc(sizeof(struct recvlist_node), GFP_ATOMIC);
 	if (!entry)
 		return;
 
 	memcpy(entry->mac, mac, ETH_ALEN);
+	spin_lock_irqsave(&recv_list_lock, flags);
 	list_add_tail(&entry->list, recv_list);
+	spin_unlock_irqrestore(&recv_list_lock, flags);
 }
 
 /* returns 1 if this mac is in the recv_list */
 static int recv_list_is_in(struct list_head *recv_list, char *mac)
 {
 	struct recvlist_node *entry;
+	unsigned long flags;
 
+	spin_lock_irqsave(&recv_list_lock, flags);
 	list_for_each_entry(entry, recv_list, list) {
-		if (memcmp(entry->mac, mac, ETH_ALEN) == 0)
+		if (memcmp(entry->mac, mac, ETH_ALEN) == 0) {
+			spin_unlock_irqrestore(&recv_list_lock, flags);
 			return 1;
+		}
 	}
-
+	spin_unlock_irqrestore(&recv_list_lock, flags);
 	return 0;
 }
 
 /* try to add the packet to the vis_hash. return NULL if invalid (e.g. too old,
- * broken.. ).  vis hash must be locked outside.  is_new is set when the packet
+ * broken.. ).	vis hash must be locked outside.  is_new is set when the packet
  * is newer than old entries in the hash. */
 static struct vis_info *add_packet(struct vis_packet *vis_packet,
-				   int vis_info_len, int *is_new)
+				   int vis_info_len, int *is_new,
+				   int make_broadcast)
 {
 	struct vis_info *info, *old_info;
 	struct vis_info search_elem;
@@ -198,13 +231,15 @@ static struct vis_info *add_packet(struc
 		}
 		/* remove old entry */
 		hash_remove(vis_hash, old_info);
-		free_info(old_info);
+		send_list_del(old_info);
+		kref_put(&old_info->refcount, free_info);
 	}
 
 	info = kmalloc(sizeof(struct vis_info) + vis_info_len, GFP_ATOMIC);
 	if (info == NULL)
 		return NULL;
 
+	kref_init(&info->refcount);
 	INIT_LIST_HEAD(&info->send_list);
 	INIT_LIST_HEAD(&info->recv_list);
 	info->first_seen = jiffies;
@@ -214,16 +249,21 @@ static struct vis_info *add_packet(struc
 	/* initialize and add new packet. */
 	*is_new = 1;
 
+	/* Make it a broadcast packet, if required */
+	if (make_broadcast)
+		memcpy(info->packet.target_orig, broadcastAddr, ETH_ALEN);
+
 	/* repair if entries is longer than packet. */
 	if (info->packet.entries * sizeof(struct vis_info_entry) > vis_info_len)
-		info->packet.entries = vis_info_len / sizeof(struct vis_info_entry);
+		info->packet.entries = vis_info_len /
+			sizeof(struct vis_info_entry);
 
 	recv_list_add(&info->recv_list, info->packet.sender_orig);
 
 	/* try to add it */
 	if (hash_add(vis_hash, info) < 0) {
 		/* did not work (for some reason) */
-		free_info(info);
+		kref_put(&old_info->refcount, free_info);
 		info = NULL;
 	}
 
@@ -234,22 +274,21 @@ static struct vis_info *add_packet(struc
 void receive_server_sync_packet(struct vis_packet *vis_packet, int vis_info_len)
 {
 	struct vis_info *info;
-	int is_new;
+	int is_new, make_broadcast;
 	unsigned long flags;
 	int vis_server = atomic_read(&vis_mode);
 
+	make_broadcast = (vis_server == VIS_TYPE_SERVER_SYNC);
+
 	spin_lock_irqsave(&vis_hash_lock, flags);
-	info = add_packet(vis_packet, vis_info_len, &is_new);
+	info = add_packet(vis_packet, vis_info_len, &is_new, make_broadcast);
 	if (info == NULL)
 		goto end;
 
 	/* only if we are server ourselves and packet is newer than the one in
 	 * hash.*/
-	if (vis_server == VIS_TYPE_SERVER_SYNC && is_new) {
-		memcpy(info->packet.target_orig, broadcastAddr, ETH_ALEN);
-		if (list_empty(&info->send_list))
-			list_add_tail(&info->send_list, &send_list);
-	}
+	if (vis_server == VIS_TYPE_SERVER_SYNC && is_new)
+		send_list_add(info);
 end:
 	spin_unlock_irqrestore(&vis_hash_lock, flags);
 }
@@ -262,31 +301,32 @@ void receive_client_update_packet(struct
 	int is_new;
 	unsigned long flags;
 	int vis_server = atomic_read(&vis_mode);
+	int are_target = 0;
 
 	/* clients shall not broadcast. */
 	if (is_bcast(vis_packet->target_orig))
 		return;
 
+	/* Are we the target for this VIS packet? */
+	if (vis_server == VIS_TYPE_SERVER_SYNC	&&
+	    is_my_mac(vis_packet->target_orig))
+		are_target = 1;
+
 	spin_lock_irqsave(&vis_hash_lock, flags);
-	info = add_packet(vis_packet, vis_info_len, &is_new);
+	info = add_packet(vis_packet, vis_info_len, &is_new, are_target);
 	if (info == NULL)
 		goto end;
 	/* note that outdated packets will be dropped at this point. */
 
 
 	/* send only if we're the target server or ... */
-	if (vis_server == VIS_TYPE_SERVER_SYNC  &&
-	    is_my_mac(info->packet.target_orig) &&
-	    is_new) {
+	if (are_target && is_new) {
 		info->packet.vis_type = VIS_TYPE_SERVER_SYNC;	/* upgrade! */
-		memcpy(info->packet.target_orig, broadcastAddr, ETH_ALEN);
-		if (list_empty(&info->send_list))
-			list_add_tail(&info->send_list, &send_list);
+		send_list_add(info);
 
 		/* ... we're not the recipient (and thus need to forward). */
 	} else if (!is_my_mac(info->packet.target_orig)) {
-		if (list_empty(&info->send_list))
-			list_add_tail(&info->send_list, &send_list);
+		send_list_add(info);
 	}
 end:
 	spin_unlock_irqrestore(&vis_hash_lock, flags);
@@ -361,14 +401,17 @@ static int generate_vis_packet(void)
 	while (hash_iterate(orig_hash, &hashit_global)) {
 		orig_node = hashit_global.bucket->data;
 		if (orig_node->router != NULL
-			&& compare_orig(orig_node->router->addr, orig_node->orig)
+			&& compare_orig(orig_node->router->addr,
+					orig_node->orig)
 			&& orig_node->batman_if
 			&& (orig_node->batman_if->if_active == IF_ACTIVE)
 		    && orig_node->router->tq_avg > 0) {
 
 			/* fill one entry into buffer. */
 			entry = &entry_array[info->packet.entries];
-			memcpy(entry->src, orig_node->batman_if->net_dev->dev_addr, ETH_ALEN);
+			memcpy(entry->src,
+			       orig_node->batman_if->net_dev->dev_addr,
+			       ETH_ALEN);
 			memcpy(entry->dest, orig_node->orig, ETH_ALEN);
 			entry->quality = orig_node->router->tq_avg;
 			info->packet.entries++;
@@ -400,6 +443,8 @@ static int generate_vis_packet(void)
 	return 0;
 }
 
+/* free old vis packets. Must be called with this vis_hash_lock
+ * held */
 static void purge_vis_packets(void)
 {
 	HASHIT(hashit);
@@ -412,7 +457,8 @@ static void purge_vis_packets(void)
 		if (time_after(jiffies,
 			       info->first_seen + (VIS_TIMEOUT*HZ)/1000)) {
 			hash_remove_bucket(vis_hash, &hashit);
-			free_info(info);
+			send_list_del(info);
+			kref_put(&info->refcount, free_info);
 		}
 	}
 }
@@ -422,6 +468,8 @@ static void broadcast_vis_packet(struct
 	HASHIT(hashit);
 	struct orig_node *orig_node;
 	unsigned long flags;
+	struct batman_if *batman_if;
+	uint8_t dstaddr[ETH_ALEN];
 
 	spin_lock_irqsave(&orig_hash_lock, flags);
 
@@ -430,45 +478,56 @@ static void broadcast_vis_packet(struct
 		orig_node = hashit.bucket->data;
 
 		/* if it's a vis server and reachable, send it. */
-		if (orig_node &&
-		    (orig_node->flags & VIS_SERVER) &&
-		    orig_node->batman_if &&
-		    orig_node->router) {
+		if ((!orig_node) || (!orig_node->batman_if) ||
+		    (!orig_node->router))
+			continue;
+		if (!(orig_node->flags & VIS_SERVER))
+			continue;
+		/* don't send it if we already received the packet from
+		 * this node. */
+		if (recv_list_is_in(&info->recv_list, orig_node->orig))
+			continue;
+
+		memcpy(info->packet.target_orig, orig_node->orig, ETH_ALEN);
+		batman_if = orig_node->batman_if;
+		memcpy(dstaddr, orig_node->router->addr, ETH_ALEN);
+		spin_unlock_irqrestore(&orig_hash_lock, flags);
+
+		send_raw_packet((unsigned char *)&info->packet,
+				packet_length, batman_if, dstaddr);
+
+		spin_lock_irqsave(&orig_hash_lock, flags);
 
-			/* don't send it if we already received the packet from
-			 * this node. */
-			if (recv_list_is_in(&info->recv_list, orig_node->orig))
-				continue;
-
-			memcpy(info->packet.target_orig,
-			       orig_node->orig, ETH_ALEN);
-
-			send_raw_packet((unsigned char *) &info->packet,
-					packet_length,
-					orig_node->batman_if,
-					orig_node->router->addr);
-		}
 	}
-	memcpy(info->packet.target_orig, broadcastAddr, ETH_ALEN);
 	spin_unlock_irqrestore(&orig_hash_lock, flags);
+	memcpy(info->packet.target_orig, broadcastAddr, ETH_ALEN);
 }
 
 static void unicast_vis_packet(struct vis_info *info, int packet_length)
 {
 	struct orig_node *orig_node;
 	unsigned long flags;
+	struct batman_if *batman_if;
+	uint8_t dstaddr[ETH_ALEN];
 
 	spin_lock_irqsave(&orig_hash_lock, flags);
 	orig_node = ((struct orig_node *)
 		     hash_find(orig_hash, info->packet.target_orig));
 
-	if ((orig_node != NULL) &&
-	    (orig_node->batman_if != NULL) &&
-	    (orig_node->router != NULL)) {
-		send_raw_packet((unsigned char *) &info->packet, packet_length,
-				orig_node->batman_if,
-				orig_node->router->addr);
-	}
+	if ((!orig_node) || (!orig_node->batman_if) || (!orig_node->router))
+		goto out;
+
+	/* don't lock while sending the packets ... we therefore
+	 * copy the required data before sending */
+	batman_if = orig_node->batman_if;
+	memcpy(dstaddr, orig_node->router->addr, ETH_ALEN);
+	spin_unlock_irqrestore(&orig_hash_lock, flags);
+
+	send_raw_packet((unsigned char *)&info->packet,
+			packet_length, batman_if, dstaddr);
+	return;
+
+out:
 	spin_unlock_irqrestore(&orig_hash_lock, flags);
 }
 
@@ -502,15 +561,24 @@ static void send_vis_packets(struct work
 	unsigned long flags;
 
 	spin_lock_irqsave(&vis_hash_lock, flags);
+
 	purge_vis_packets();
 
-	if (generate_vis_packet() == 0)
+	if (generate_vis_packet() == 0) {
 		/* schedule if generation was successful */
-		list_add_tail(&my_vis_info->send_list, &send_list);
+		send_list_add(my_vis_info);
+	}
 
 	list_for_each_entry_safe(info, temp, &send_list, send_list) {
-		list_del_init(&info->send_list);
+
+		kref_get(&info->refcount);
+		spin_unlock_irqrestore(&vis_hash_lock, flags);
+
 		send_vis_packet(info);
+
+		spin_lock_irqsave(&vis_hash_lock, flags);
+		send_list_del(info);
+		kref_put(&info->refcount, free_info);
 	}
 	spin_unlock_irqrestore(&vis_hash_lock, flags);
 	start_vis_timer();
@@ -543,6 +611,7 @@ int vis_init(void)
 	my_vis_info->first_seen = jiffies - atomic_read(&vis_interval);
 	INIT_LIST_HEAD(&my_vis_info->recv_list);
 	INIT_LIST_HEAD(&my_vis_info->send_list);
+	kref_init(&my_vis_info->refcount);
 	my_vis_info->packet.version = COMPAT_VERSION;
 	my_vis_info->packet.packet_type = BAT_VIS;
 	my_vis_info->packet.ttl = TTL;
@@ -556,9 +625,9 @@ int vis_init(void)
 
 	if (hash_add(vis_hash, my_vis_info) < 0) {
 		printk(KERN_ERR
-			  "batman-adv:Can't add own vis packet into hash\n");
-		free_info(my_vis_info);	/* not in hash, need to remove it
-					 * manually. */
+		       "batman-adv:Can't add own vis packet into hash\n");
+		/* not in hash, need to remove it manually. */
+		kref_put(&my_vis_info->refcount, free_info);
 		goto err;
 	}
 
@@ -572,6 +641,15 @@ err:
 	return 0;
 }
 
+/* Decrease the reference count on a hash item info */
+static void free_info_ref(void *data)
+{
+	struct vis_info *info = data;
+
+	send_list_del(info);
+	kref_put(&info->refcount, free_info);
+}
+
 /* shutdown vis-server */
 void vis_quit(void)
 {
@@ -583,7 +661,7 @@ void vis_quit(void)
 
 	spin_lock_irqsave(&vis_hash_lock, flags);
 	/* properly remove, kill timers ... */
-	hash_delete(vis_hash, free_info);
+	hash_delete(vis_hash, free_info_ref);
 	vis_hash = NULL;
 	my_vis_info = NULL;
 	spin_unlock_irqrestore(&vis_hash_lock, flags);
drivers/staging/batman-adv/vis.h +1 -0
@@ -29,6 +29,7 @@ struct vis_info {
 			    /* list of server-neighbors we received a vis-packet
 			     * from.  we should not reply to them. */
 	struct list_head send_list;
+	struct kref refcount;
 	/* this packet might be part of the vis send queue. */
 	struct vis_packet packet;
 	/* vis_info may follow here*/
#465 lore raw

PATCH 21/200 Staging: batman-adv: Fix VIS output bug for secondary interfaces

In reply to Greg KH

2.6.34-stable review patch. If anyone has any objections, please let me know.

------------------

From: =?UTF-8?q?Linus=20L=C3=BCssing?= <[email protected]>

commit f6497e38fda6970819daacb67725d67474079381 upstream.

TQ and HNA records for originators on secondary interfaces were wrongly being included on the primary interface. Ensure we output a line for each source interface on every node, so we correctly separate primary and secondary interface records.

---
 drivers/staging/batman-adv/proc.c |   51 ++++++++++++++++++++++++++------------
 drivers/staging/batman-adv/vis.c  |   25 ++++++------------
 drivers/staging/batman-adv/vis.h  |    7 +++--
 3 files changed, 49 insertions(+), 34 deletions(-)
drivers/staging/batman-adv/proc.c +35 -16
@@ -41,7 +41,7 @@ static int proc_interfaces_read(struct s
 
 	rcu_read_lock();
 	list_for_each_entry_rcu(batman_if, &if_list, list) {
-		seq_printf(seq, "[%8s] %s %s \n",
+		seq_printf(seq, "[%8s] %s %s\n",
 			   (batman_if->if_active == IF_ACTIVE ?
 			    "active" : "inactive"),
 			   batman_if->dev,
@@ -188,18 +188,18 @@ static int proc_originators_read(struct
 	rcu_read_lock();
 	if (list_empty(&if_list)) {
 		rcu_read_unlock();
-		seq_printf(seq, "BATMAN disabled - please specify interfaces to enable it \n");
+		seq_printf(seq, "BATMAN disabled - please specify interfaces to enable it\n");
 		goto end;
 	}
 
 	if (((struct batman_if *)if_list.next)->if_active != IF_ACTIVE) {
 		rcu_read_unlock();
-		seq_printf(seq, "BATMAN disabled - primary interface not active \n");
+		seq_printf(seq, "BATMAN disabled - primary interface not active\n");
 		goto end;
 	}
 
 	seq_printf(seq,
-		   "  %-14s (%s/%i) %17s [%10s]: %20s ... [B.A.T.M.A.N. adv %s%s, MainIF/MAC: %s/%s] \n",
+		   "  %-14s (%s/%i) %17s [%10s]: %20s ... [B.A.T.M.A.N. adv %s%s, MainIF/MAC: %s/%s]\n",
 		   "Originator", "#", TQ_MAX_VALUE, "Nexthop", "outgoingIF",
 		   "Potential nexthops", SOURCE_VERSION, REVISION_VERSION_STR,
 		   ((struct batman_if *)if_list.next)->dev,
@@ -240,7 +240,7 @@ static int proc_originators_read(struct
 	spin_unlock_irqrestore(&orig_hash_lock, flags);
 
 	if (batman_count == 0)
-		seq_printf(seq, "No batman nodes in range ... \n");
+		seq_printf(seq, "No batman nodes in range ...\n");
 
 end:
 	return 0;
@@ -262,7 +262,7 @@ static int proc_transt_local_read(struct
 	rcu_read_lock();
 	if (list_empty(&if_list)) {
 		rcu_read_unlock();
-		seq_printf(seq, "BATMAN disabled - please specify interfaces to enable it \n");
+		seq_printf(seq, "BATMAN disabled - please specify interfaces to enable it\n");
 		goto end;
 	}
 
@@ -294,7 +294,7 @@ static int proc_transt_global_read(struc
 	rcu_read_lock();
 	if (list_empty(&if_list)) {
 		rcu_read_unlock();
-		seq_printf(seq, "BATMAN disabled - please specify interfaces to enable it \n");
+		seq_printf(seq, "BATMAN disabled - please specify interfaces to enable it\n");
 		goto end;
 	}
 	rcu_read_unlock();
@@ -350,9 +350,9 @@ static int proc_vis_srv_read(struct seq_
 {
 	int vis_server = atomic_read(&vis_mode);
 
-	seq_printf(seq, "[%c] client mode (server disabled) \n",
+	seq_printf(seq, "[%c] client mode (server disabled)\n",
 			(vis_server == VIS_TYPE_CLIENT_UPDATE) ? 'x' : ' ');
-	seq_printf(seq, "[%c] server mode (server enabled) \n",
+	seq_printf(seq, "[%c] server mode (server enabled)\n",
 			(vis_server == VIS_TYPE_SERVER_SYNC) ? 'x' : ' ');
 
 	return 0;
@@ -369,6 +369,8 @@ static int proc_vis_data_read(struct seq
 	struct vis_info *info;
 	struct vis_info_entry *entries;
 	HLIST_HEAD(vis_if_list);
+	struct if_list_entry *entry;
+	struct hlist_node *pos, *n;
 	int i;
 	char tmp_addr_str[ETH_STR_LEN];
 	unsigned long flags;
@@ -387,17 +389,34 @@ static int proc_vis_data_read(struct seq
 		info = hashit.bucket->data;
 		entries = (struct vis_info_entry *)
 			((char *)info + sizeof(struct vis_info));
-		addr_to_string(tmp_addr_str, info->packet.vis_orig);
-		seq_printf(seq, "%s,", tmp_addr_str);
 
 		for (i = 0; i < info->packet.entries; i++) {
-			proc_vis_read_entry(seq, &entries[i], &vis_if_list,
-					    info->packet.vis_orig);
+			if (entries[i].quality == 0)
+				continue;
+			proc_vis_insert_interface(entries[i].src, &vis_if_list,
+				compare_orig(entries[i].src,
+						info->packet.vis_orig));
 		}
 
-		/* add primary/secondary records */
-		proc_vis_read_prim_sec(seq, &vis_if_list);
-		seq_printf(seq, "\n");
+		hlist_for_each_entry(entry, pos, &vis_if_list, list) {
+			addr_to_string(tmp_addr_str, entry->addr);
+			seq_printf(seq, "%s,", tmp_addr_str);
+
+			for (i = 0; i < info->packet.entries; i++)
+				proc_vis_read_entry(seq, &entries[i],
+						entry->addr, entry->primary);
+
+			/* add primary/secondary records */
+			if (compare_orig(entry->addr, info->packet.vis_orig))
+				proc_vis_read_prim_sec(seq, &vis_if_list);
+
+			seq_printf(seq, "\n");
+		}
+
+		hlist_for_each_entry_safe(entry, pos, n, &vis_if_list, list) {
+			hlist_del(&entry->list);
+			kfree(entry);
+		}
 	}
 	spin_unlock_irqrestore(&vis_hash_lock, flags);
 
drivers/staging/batman-adv/vis.c +9 -16
@@ -86,7 +86,7 @@ static int vis_info_choose(void *data, i
 
 /* insert interface to the list of interfaces of one originator, if it
  * does not already exist in the list */
-static void proc_vis_insert_interface(const uint8_t *interface,
+void proc_vis_insert_interface(const uint8_t *interface,
 				      struct hlist_head *if_list,
 				      bool primary)
 {
@@ -111,39 +111,32 @@ void proc_vis_read_prim_sec(struct seq_f
 			    struct hlist_head *if_list)
 {
 	struct if_list_entry *entry;
-	struct hlist_node *pos, *n;
+	struct hlist_node *pos;
 	char tmp_addr_str[ETH_STR_LEN];
 
-	hlist_for_each_entry_safe(entry, pos, n, if_list, list) {
-		if (entry->primary) {
+	hlist_for_each_entry(entry, pos, if_list, list) {
+		if (entry->primary)
 			seq_printf(seq, "PRIMARY, ");
-		} else {
+		else {
 			addr_to_string(tmp_addr_str, entry->addr);
 			seq_printf(seq, "SEC %s, ", tmp_addr_str);
 		}
-
-		hlist_del(&entry->list);
-		kfree(entry);
 	}
 }
 
 /* read an entry  */
 void proc_vis_read_entry(struct seq_file *seq,
 				struct vis_info_entry *entry,
-				struct hlist_head *if_list,
-				uint8_t *vis_orig)
+				uint8_t *src,
+				bool primary)
 {
 	char to[40];
 
 	addr_to_string(to, entry->dest);
-	if (entry->quality == 0) {
-		proc_vis_insert_interface(vis_orig, if_list, true);
+	if (primary && entry->quality == 0)
 		seq_printf(seq, "HNA %s, ", to);
-	} else {
-		proc_vis_insert_interface(entry->src, if_list,
-					  compare_orig(entry->src, vis_orig));
+	else if (compare_orig(entry->src, src))
 		seq_printf(seq, "TQ %s %d, ", to, entry->quality);
-	}
 }
 
 /* add the info packet to the send list, if it was not
drivers/staging/batman-adv/vis.h +5 -2
@@ -49,10 +49,13 @@ struct recvlist_node {
 extern struct hashtable_t *vis_hash;
 extern spinlock_t vis_hash_lock;
 
+void proc_vis_insert_interface(const uint8_t *interface,
+				      struct hlist_head *if_list,
+				      bool primary);
 void proc_vis_read_entry(struct seq_file *seq,
 				struct vis_info_entry *entry,
-				struct hlist_head *if_list,
-				uint8_t *vis_orig);
+				uint8_t *src,
+				bool primary);
 void proc_vis_read_prim_sec(struct seq_file *seq,
 			    struct hlist_head *if_list);
 void receive_server_sync_packet(struct vis_packet *vis_packet,
#466 lore raw

PATCH 22/200 Staging: batman-adv: Fixing wrap-around bug in vis

In reply to Greg KH

2.6.34-stable review patch. If anyone has any objections, please let me know.

------------------

From: =?UTF-8?q?Linus=20L=C3=BCssing?= <[email protected]>

commit ea4ceb18b525fd7016c10995c0f1313a729c7e2b upstream.

When the seqno for a vis packet had a wrap around from i.e. 255 to 0, add_packet() would falsely claim the older packet with the seqno 255 as newer as the one with the seqno of 0 and would therefore ignore the new packet. This happens with all following vis packets until the old vis packet expires after 180 seconds timeout. This patch fixes this issue and gets rid of these highly undesired 3min. breaks for the vis-server.

---
 drivers/staging/batman-adv/vis.c |   18 +++++++++++++++++-
 1 file changed, 17 insertions(+), 1 deletion(-)
drivers/staging/batman-adv/vis.c +17 -1
@@ -27,6 +27,22 @@
 #include "hard-interface.h"
 #include "hash.h"
 
+/* Returns the smallest signed integer in two's complement with the sizeof x */
+#define smallest_signed_int(x) (1u << (7u + 8u * (sizeof(x) - 1u)))
+
+/* Checks if a sequence number x is a predecessor/successor of y.
+   they handle overflows/underflows and can correctly check for a
+   predecessor/successor unless the variable sequence number has grown by
+   more then 2**(bitwidth(x)-1)-1.
+   This means that for a uint8_t with the maximum value 255, it would think:
+    * when adding nothing - it is neither a predecessor nor a successor
+    * before adding more than 127 to the starting value - it is a predecessor,
+    * when adding 128 - it is neither a predecessor nor a successor,
+    * after adding more than 127 to the starting value - it is a successor */
+#define seq_before(x, y) ({typeof(x) _dummy = (x - y); \
+			  _dummy > smallest_signed_int(_dummy); })
+#define seq_after(x, y) seq_before(y, x)
+
 struct hashtable_t *vis_hash;
 DEFINE_SPINLOCK(vis_hash_lock);
 static DEFINE_SPINLOCK(recv_list_lock);
@@ -212,7 +228,7 @@ static struct vis_info *add_packet(struc
 	old_info = hash_find(vis_hash, &search_elem);
 
 	if (old_info != NULL) {
-		if (vis_packet->seqno - old_info->packet.seqno <= 0) {
+		if (!seq_after(vis_packet->seqno, old_info->packet.seqno)) {
 			if (old_info->packet.seqno == vis_packet->seqno) {
 				recv_list_add(&old_info->recv_list,
 					      vis_packet->sender_orig);
#467 lore raw

PATCH 23/200 mutex: Fix optimistic spinning vs. BKL

In reply to Greg KH

2.6.34-stable review patch. If anyone has any objections, please let me know.

------------------

From: Tony Breeds <[email protected]>

commit fd6be105b883244127a734ac9f14ae94a022dcc0 upstream.

Currently, we can hit a nasty case with optimistic spinning on mutexes:

CPU A tries to take a mutex, while holding the BKL

CPU B tried to take the BLK while holding the mutex

This looks like a AB-BA scenario but in practice, is allowed and happens due to the auto-release on schedule() nature of the BKL.

In that case, the optimistic spinning code can get us into a situation where instead of going to sleep, A will spin waiting for B who is spinning waiting for A, and the only way out of that loop is the need_resched() test in mutex_spin_on_owner().

This patch fixes it by completely disabling spinning if we own the BKL. This adds one more detail to the extensive list of reasons why it's a bad idea for kernel code to be holding the BKL.

LKML-Reference: <[email protected]>

[ added an unlikely() attribute to the branch ]
---
 kernel/mutex.c |    7 +++++++
 1 file changed, 7 insertions(+)
kernel/mutex.c +7 -0
@@ -172,6 +172,13 @@ __mutex_lock_common(struct mutex *lock,
 		struct thread_info *owner;
 
 		/*
+		 * If we own the BKL, then don't spin. The owner of
+		 * the mutex might be waiting on us to release the BKL.
+		 */
+		if (unlikely(current->lock_depth >= 0))
+			break;
+
+		/*
 		 * If there's an owner, wait for it to either
 		 * release the lock or go to sleep.
 		 */
#468 lore raw

PATCH 24/200 ALSA: pcm: fix delta calculation at boundary wraparound

In reply to Greg KH

2.6.34-stable review patch. If anyone has any objections, please let me know.

------------------

From: Clemens Ladisch <[email protected]>

commit b406e6103baa3da85950f22d3d46d21a8da654c5 upstream.

In the cleanup of the hw_ptr update functions in 2.6.33, the calculation of the delta value was changed to use the modulo operator to protect against a negative difference due to the pointer wrapping around at the boundary.

However, the ptr variables are unsigned, so a negative difference would result in the two complement's value which has no relation to the actual difference relative to the boundary; the result is typically some value near LONG_MAX-boundary. Furthermore, even if the modulo operation would be done with signed types, the result of a negative dividend could be negative.

The invalid delta value is then caught by the following checks, but this means that the pointer update is ignored.

To fix this, use a range check as in the other pointer calculations.

---
 sound/core/pcm_lib.c |    4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)
sound/core/pcm_lib.c +3 -1
@@ -345,7 +345,9 @@ static int snd_pcm_update_hw_ptr0(struct
 		new_hw_ptr = hw_base + pos;
 	}
       __delta:
-	delta = (new_hw_ptr - old_hw_ptr) % runtime->boundary;
+	delta = new_hw_ptr - old_hw_ptr;
+	if (delta < 0)
+		delta += runtime->boundary;
 	if (xrun_debug(substream, in_interrupt ?
 			XRUN_DEBUG_PERIODUPDATE : XRUN_DEBUG_HWPTRUPDATE)) {
 		char name[16];
#469 lore raw

PATCH 25/200 ALSA: pcm: fix the fix of the runtime->boundary calculation

In reply to Greg KH

2.6.34-stable review patch. If anyone has any objections, please let me know.

------------------

From: Clemens Ladisch <[email protected]>

commit ead4046b2fdfd69acc4272e693afd249ad3eb689 upstream.

Commit 7910b4a1db63fefc3d291853d33c34c5b6352e8e in 2.6.34 changed the runtime->boundary calculation to make this value a multiple of both the buffer_size and the period_size, because the latter is assumed by the runtime->hw_ptr_interrupt calculation.

However, due to the lack of a ioctl that could read the software parameters before they are set, the kernel requires that alsa-lib calculates the boundary value, too. The changed algorithm leads to a different boundary value used by alsa-lib, which makes, e.g., mplayer fail to play a 44.1 kHz file because the silence_size parameter is now invalid; bug report:
<https://bugtrack.alsa-project.org/alsa-bug/view.php?id=5015>.

This patch reverts the change to the boundary calculation, and instead fixes the hw_ptr_interrupt calculation to be period-aligned regardless of the boundary value.

---
 sound/core/pcm_lib.c    |    9 +++++++--
 sound/core/pcm_native.c |   39 +++------------------------------------
 2 files changed, 10 insertions(+), 38 deletions(-)
sound/core/pcm_lib.c +7 -2
@@ -441,8 +441,13 @@ static int snd_pcm_update_hw_ptr0(struct
 		snd_pcm_playback_silence(substream, new_hw_ptr);
 
 	if (in_interrupt) {
-		runtime->hw_ptr_interrupt = new_hw_ptr -
-				(new_hw_ptr % runtime->period_size);
+		delta = new_hw_ptr - runtime->hw_ptr_interrupt;
+		if (delta < 0)
+			delta += runtime->boundary;
+		delta -= (snd_pcm_uframes_t)delta % runtime->period_size;
+		runtime->hw_ptr_interrupt += delta;
+		if (runtime->hw_ptr_interrupt >= runtime->boundary)
+			runtime->hw_ptr_interrupt -= runtime->boundary;
 	}
 	runtime->hw_ptr_base = hw_base;
 	runtime->status->hw_ptr = new_hw_ptr;
sound/core/pcm_native.c +3 -36
@@ -27,7 +27,6 @@
 #include <linux/pm_qos_params.h>
 #include <linux/uio.h>
 #include <linux/dma-mapping.h>
-#include <linux/math64.h>
 #include <sound/core.h>
 #include <sound/control.h>
 #include <sound/info.h>
@@ -370,38 +369,6 @@ static int period_to_usecs(struct snd_pc
 	return usecs;
 }
 
-static int calc_boundary(struct snd_pcm_runtime *runtime)
-{
-	u_int64_t boundary;
-
-	boundary = (u_int64_t)runtime->buffer_size *
-		   (u_int64_t)runtime->period_size;
-#if BITS_PER_LONG < 64
-	/* try to find lowest common multiple for buffer and period */
-	if (boundary > LONG_MAX - runtime->buffer_size) {
-		u_int32_t remainder = -1;
-		u_int32_t divident = runtime->buffer_size;
-		u_int32_t divisor = runtime->period_size;
-		while (remainder) {
-			remainder = divident % divisor;
-			if (remainder) {
-				divident = divisor;
-				divisor = remainder;
-			}
-		}
-		boundary = div_u64(boundary, divisor);
-		if (boundary > LONG_MAX - runtime->buffer_size)
-			return -ERANGE;
-	}
-#endif
-	if (boundary == 0)
-		return -ERANGE;
-	runtime->boundary = boundary;
-	while (runtime->boundary * 2 <= LONG_MAX - runtime->buffer_size)
-		runtime->boundary *= 2;
-	return 0;
-}
-
 static int snd_pcm_hw_params(struct snd_pcm_substream *substream,
 			     struct snd_pcm_hw_params *params)
 {
@@ -477,9 +444,9 @@ static int snd_pcm_hw_params(struct snd_
 	runtime->stop_threshold = runtime->buffer_size;
 	runtime->silence_threshold = 0;
 	runtime->silence_size = 0;
-	err = calc_boundary(runtime);
-	if (err < 0)
-		goto _error;
+	runtime->boundary = runtime->buffer_size;
+	while (runtime->boundary * 2 <= LONG_MAX - runtime->buffer_size)
+		runtime->boundary *= 2;
 
 	snd_pcm_timer_resolution_change(substream);
 	runtime->status->state = SNDRV_PCM_STATE_SETUP;
#470 lore raw

PATCH 26/200 ALSA: hda: Fix model quirk for Dell M1730

In reply to Greg KH

2.6.34-stable review patch. If anyone has any objections, please let me know.

------------------

From: Daniel T Chen <[email protected]>

commit 66668b6fb6861fad7f6bfef6646ac84693474c9a upstream.

Symptom: Currently (2.6.32.12) the Dell M1730 uses the 3stack model quirk. Unfortunately this means that capture is not functional out- of-the-box despite ensuring that capture settings are unmuted and raised fully.

Test case: boot from Ubuntu 10.04 LTS live cd; capture does not work.

Resolution: Correct the model quirk for Dell M1730 to rely on the BIOS configuration.

This patch also trivially sorts the quirk into the correct section based on the comments.

Reported-and-Tested-By <[email protected]>
Tested-by Daren Hayward
Tested-by Tobias Krais
---
 sound/pci/hda/patch_sigmatel.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
sound/pci/hda/patch_sigmatel.c +1 -1
@@ -2078,12 +2078,12 @@ static struct snd_pci_quirk stac927x_cfg
 	SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_INTEL, 0xff00, 0x2000,
 			   "Intel D965", STAC_D965_3ST),
 	/* Dell 3 stack systems */
-	SND_PCI_QUIRK(PCI_VENDOR_ID_DELL,  0x01f7, "Dell XPS M1730", STAC_DELL_3ST),
 	SND_PCI_QUIRK(PCI_VENDOR_ID_DELL,  0x01dd, "Dell Dimension E520", STAC_DELL_3ST),
 	SND_PCI_QUIRK(PCI_VENDOR_ID_DELL,  0x01ed, "Dell     ", STAC_DELL_3ST),
 	SND_PCI_QUIRK(PCI_VENDOR_ID_DELL,  0x01f4, "Dell     ", STAC_DELL_3ST),
 	/* Dell 3 stack systems with verb table in BIOS */
 	SND_PCI_QUIRK(PCI_VENDOR_ID_DELL,  0x01f3, "Dell Inspiron 1420", STAC_DELL_BIOS),
+	SND_PCI_QUIRK(PCI_VENDOR_ID_DELL,  0x01f7, "Dell XPS M1730", STAC_DELL_BIOS),
 	SND_PCI_QUIRK(PCI_VENDOR_ID_DELL,  0x0227, "Dell Vostro 1400  ", STAC_DELL_BIOS),
 	SND_PCI_QUIRK(PCI_VENDOR_ID_DELL,  0x022e, "Dell     ", STAC_DELL_BIOS),
 	SND_PCI_QUIRK(PCI_VENDOR_ID_DELL,  0x022f, "Dell Inspiron 1525", STAC_DELL_BIOS),
#471 lore raw

PATCH 27/200 ALSA: hda: Use LPIB for Toshiba A100-259

In reply to Greg KH

2.6.34-stable review patch. If anyone has any objections, please let me know.

------------------

From: Daniel T Chen <[email protected]>

commit 4e0938dba7fccf37a4aecba4d937da7f312b5d55 upstream.

Symptom: on a significant number of hardware, booting from a live cd results in capture working correctly, but once the distribution is installed, booting from the install results in capture not working.

Test case: boot from Ubuntu 10.04 LTS live cd; capture works correctly. Install to HD and reboot; capture does not work. Reproduced with 2.6.32 mainline build (vanilla kernel.org compile)

Resolution: add SSID for Toshiba A100-259 to the position_fix quirk table, explicitly specifying the LPIB method.

I'll be sending additional patches for these SSIDs as bug reports are confirmed.

This patch also trivially sorts the quirk table in ascending order by subsystem vendor.

---
 sound/pci/hda/hda_intel.c |    3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)
sound/pci/hda/hda_intel.c +2 -1
@@ -2267,8 +2267,9 @@ static struct snd_pci_quirk position_fix
 	SND_PCI_QUIRK(0x1028, 0x01de, "Dell Precision 390", POS_FIX_LPIB),
 	SND_PCI_QUIRK(0x1028, 0x01f6, "Dell Latitude 131L", POS_FIX_LPIB),
 	SND_PCI_QUIRK(0x103c, 0x306d, "HP dv3", POS_FIX_LPIB),
-	SND_PCI_QUIRK(0x1106, 0x3288, "ASUS M2V-MX SE", POS_FIX_LPIB),
 	SND_PCI_QUIRK(0x1043, 0x813d, "ASUS P5AD2", POS_FIX_LPIB),
+	SND_PCI_QUIRK(0x1106, 0x3288, "ASUS M2V-MX SE", POS_FIX_LPIB),
+	SND_PCI_QUIRK(0x1179, 0xff10, "Toshiba A100-259", POS_FIX_LPIB),
 	SND_PCI_QUIRK(0x1458, 0xa022, "ga-ma770-ud3", POS_FIX_LPIB),
 	SND_PCI_QUIRK(0x1462, 0x1002, "MSI Wind U115", POS_FIX_LPIB),
 	SND_PCI_QUIRK(0x1565, 0x820f, "Biostar Microtech", POS_FIX_LPIB),
#472 lore raw

PATCH 28/200 ALSA: hda: Use LPIB for Acer Aspire 5110

In reply to Greg KH

2.6.34-stable review patch. If anyone has any objections, please let me know.

------------------

From: Daniel T Chen <[email protected]>

commit 7a68be94e22e7643038726ebc14360752a91800b upstream.

Symptom: on a significant number of hardware, booting from a live cd results in capture working correctly, but once the distribution is installed, booting from the install results in capture not working.

Test case: boot from Ubuntu 10.04 LTS live cd; capture works correctly. Install to HD and reboot; capture does not work. Reproduced with 2.6.32 mainline build (vanilla kernel.org compile).

Resolution: add SSID for Acer Aspire 5110 to the position_fix quirk table, explicitly specifying the LPIB method.

I'll be sending additional patches for these SSIDs as bug reports are confirmed.

---
 sound/pci/hda/hda_intel.c |    1 +
 1 file changed, 1 insertion(+)
sound/pci/hda/hda_intel.c +1 -0
@@ -2263,6 +2263,7 @@ static int azx_dev_free(struct snd_devic
  * white/black-listing for position_fix
  */
 static struct snd_pci_quirk position_fix_list[] __devinitdata = {
+	SND_PCI_QUIRK(0x1025, 0x009f, "Acer Aspire 5110", POS_FIX_LPIB),
 	SND_PCI_QUIRK(0x1028, 0x01cc, "Dell D820", POS_FIX_LPIB),
 	SND_PCI_QUIRK(0x1028, 0x01de, "Dell Precision 390", POS_FIX_LPIB),
 	SND_PCI_QUIRK(0x1028, 0x01f6, "Dell Latitude 131L", POS_FIX_LPIB),
#473 lore raw

PATCH 29/200 ALSA: hda: Use LPIB for Sony VPCS11V9E

In reply to Greg KH

2.6.34-stable review patch. If anyone has any objections, please let me know.

------------------

From: Daniel T Chen <[email protected]>

commit e96d3127760a2fc509bca6bf7e61e8bc61497aeb upstream.

Symptom: On the Sony VPCS11V9E, using GStreamer-based applications with PulseAudio in Ubuntu 10.04 LTS results in stuttering audio. It appears to worsen with increased I/O.

Test case: use Rhythmbox under increased I/O pressure. This symptom is reproducible in the current daily stable alsa-driver snapshots (at least up until 21 May 2010; later snapshots fail to build from source due to missing preprocessor directives when compiled against 2.6.32).

Resolution: add SSID for this machine to the position_fix quirk table, explicitly specifying the LPIB method.

---
 sound/pci/hda/hda_intel.c |    1 +
 1 file changed, 1 insertion(+)
sound/pci/hda/hda_intel.c +1 -0
@@ -2269,6 +2269,7 @@ static struct snd_pci_quirk position_fix
 	SND_PCI_QUIRK(0x1028, 0x01f6, "Dell Latitude 131L", POS_FIX_LPIB),
 	SND_PCI_QUIRK(0x103c, 0x306d, "HP dv3", POS_FIX_LPIB),
 	SND_PCI_QUIRK(0x1043, 0x813d, "ASUS P5AD2", POS_FIX_LPIB),
+	SND_PCI_QUIRK(0x104d, 0x9069, "Sony VPCS11V9E", POS_FIX_LPIB),
 	SND_PCI_QUIRK(0x1106, 0x3288, "ASUS M2V-MX SE", POS_FIX_LPIB),
 	SND_PCI_QUIRK(0x1179, 0xff10, "Toshiba A100-259", POS_FIX_LPIB),
 	SND_PCI_QUIRK(0x1458, 0xa022, "ga-ma770-ud3", POS_FIX_LPIB),
#474 lore raw

PATCH 30/200 ALSA: hda: Use LPIB for a Shuttle device

In reply to Greg KH

2.6.34-stable review patch. If anyone has any objections, please let me know.

------------------

From: Daniel T Chen <[email protected]>

commit 61bb42c37dfa9016dcacc86bcd41362ab2457d4a upstream.

Symptom: On the reporter's Shuttle device, using PulseAudio in Ubuntu 10.04 LTS results in "popping clicking" audio with the PA crashing shortly thereafter.

Test case: Using Ubuntu 10.04 LTS (Linux 2.6.32.12), Linux 2.6.33, or Linux 2.6.34, adjust the HDA device's volume with PulseAudio.

Resolution: add SSID for this machine to the position_fix quirk table, explicitly specifying the LPIB method.

---
 sound/pci/hda/hda_intel.c |    1 +
 1 file changed, 1 insertion(+)
sound/pci/hda/hda_intel.c +1 -0
@@ -2272,6 +2272,7 @@ static struct snd_pci_quirk position_fix
 	SND_PCI_QUIRK(0x104d, 0x9069, "Sony VPCS11V9E", POS_FIX_LPIB),
 	SND_PCI_QUIRK(0x1106, 0x3288, "ASUS M2V-MX SE", POS_FIX_LPIB),
 	SND_PCI_QUIRK(0x1179, 0xff10, "Toshiba A100-259", POS_FIX_LPIB),
+	SND_PCI_QUIRK(0x1297, 0x3166, "Shuttle", POS_FIX_LPIB),
 	SND_PCI_QUIRK(0x1458, 0xa022, "ga-ma770-ud3", POS_FIX_LPIB),
 	SND_PCI_QUIRK(0x1462, 0x1002, "MSI Wind U115", POS_FIX_LPIB),
 	SND_PCI_QUIRK(0x1565, 0x820f, "Biostar Microtech", POS_FIX_LPIB),
#475 lore raw

PATCH 31/200 ACPI: video: fix acpi_backlight=video

In reply to Greg KH

2.6.34-stable review patch. If anyone has any objections, please let me know.

------------------

From: Kamal Mostafa <[email protected]>

commit eeb4bcb4771679d7b3446c0293334faee11b090a upstream.

Make "acpi_backlight=video" param enable ACPI_VIDEO_BACKLIGHT_FORCE_VIDEO as intended, instead of incorrectly enabling video output switching.

---
 drivers/acpi/video_detect.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/acpi/video_detect.c +1 -1
@@ -250,7 +250,7 @@ static int __init acpi_backlight(char *s
 				ACPI_VIDEO_BACKLIGHT_FORCE_VENDOR;
 		if (!strcmp("video", str))
 			acpi_video_support |=
-				ACPI_VIDEO_OUTPUT_SWITCHING_FORCE_VIDEO;
+				ACPI_VIDEO_BACKLIGHT_FORCE_VIDEO;
 	}
 	return 1;
 }
#476 lore raw

PATCH 32/200 HID: Add the GYR4101US USB ID to hid-gyration

In reply to Greg KH

2.6.34-stable review patch. If anyone has any objections, please let me know.

------------------

From: Cory Maccarrone <[email protected]>

commit c2fd1a4ebf9127c280d227acb635eb1df213439c upstream.

This change adds in the USB product ID for the Gyration GYR4101US USB media center remote control. This remote is similar enough to the other two devices that this driver can be used without any other changes to get full support for the remote.

---
 drivers/hid/hid-core.c     |    1 +
 drivers/hid/hid-gyration.c |    1 +
 drivers/hid/hid-ids.h      |    1 +
 3 files changed, 3 insertions(+)
drivers/hid/hid-core.c +1 -0
@@ -1305,6 +1305,7 @@ static const struct hid_device_id hid_bl
 	{ HID_USB_DEVICE(USB_VENDOR_ID_GREENASIA, 0x0012) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE_2) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE_3) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_KENSINGTON, USB_DEVICE_ID_KS_SLIMBLADE) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_ERGO_525V) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_LABTEC, USB_DEVICE_ID_LABTEC_WIRELESS_KEYBOARD) },
drivers/hid/hid-gyration.c +1 -0
@@ -73,6 +73,7 @@ static int gyration_event(struct hid_dev
 static const struct hid_device_id gyration_devices[] = {
 	{ HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE_2) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE_3) },
 	{ }
 };
 MODULE_DEVICE_TABLE(hid, gyration_devices);
drivers/hid/hid-ids.h +1 -0
@@ -267,6 +267,7 @@
 #define USB_VENDOR_ID_GYRATION		0x0c16
 #define USB_DEVICE_ID_GYRATION_REMOTE	0x0002
 #define USB_DEVICE_ID_GYRATION_REMOTE_2 0x0003
+#define USB_DEVICE_ID_GYRATION_REMOTE_3 0x0008
 
 #define USB_VENDOR_ID_HAPP		0x078b
 #define USB_DEVICE_ID_UGCI_DRIVING	0x0010
#477 lore raw

PATCH 33/200 ar9170usb: add a couple more USB IDs

In reply to Greg KH

2.6.34-stable review patch. If anyone has any objections, please let me know.

------------------

From: Christian Lamparter <[email protected]>

commit 94d0bbe849190255b93fede8eb46809a38f9b8bf upstream.

This patch adds the following 5 entries to the usbid device table:

* Netgear WNA1000
* Proxim ORiNOCO Dual Band 802.11n USB Adapter
* 3Com Dual Band 802.11n USB Adapter
* H3C Dual Band 802.11n USB Adapter
* WNC Generic 11n USB dongle

---
 drivers/net/wireless/ath/ar9170/usb.c |   10 ++++++++++
 1 file changed, 10 insertions(+)
drivers/net/wireless/ath/ar9170/usb.c +10 -0
@@ -67,18 +67,28 @@ static struct usb_device_id ar9170_usb_i
 	{ USB_DEVICE(0x0cf3, 0x1001) },
 	/* TP-Link TL-WN821N v2 */
 	{ USB_DEVICE(0x0cf3, 0x1002) },
+	/* 3Com Dual Band 802.11n USB Adapter */
+	{ USB_DEVICE(0x0cf3, 0x1010) },
+	/* H3C Dual Band 802.11n USB Adapter */
+	{ USB_DEVICE(0x0cf3, 0x1011) },
 	/* Cace Airpcap NX */
 	{ USB_DEVICE(0xcace, 0x0300) },
 	/* D-Link DWA 160 A1 */
 	{ USB_DEVICE(0x07d1, 0x3c10) },
 	/* D-Link DWA 160 A2 */
 	{ USB_DEVICE(0x07d1, 0x3a09) },
+	/* Netgear WNA1000 */
+	{ USB_DEVICE(0x0846, 0x9040) },
 	/* Netgear WNDA3100 */
 	{ USB_DEVICE(0x0846, 0x9010) },
 	/* Netgear WN111 v2 */
 	{ USB_DEVICE(0x0846, 0x9001) },
 	/* Zydas ZD1221 */
 	{ USB_DEVICE(0x0ace, 0x1221) },
+	/* Proxim ORiNOCO 802.11n USB */
+	{ USB_DEVICE(0x1435, 0x0804) },
+	/* WNC Generic 11n USB Dongle */
+	{ USB_DEVICE(0x1435, 0x0326) },
 	/* ZyXEL NWD271N */
 	{ USB_DEVICE(0x0586, 0x3417) },
 	/* Z-Com UB81 BG */
#478 lore raw

PATCH 34/200 ar9170usb: fix panic triggered by undersized rxstream buffer

In reply to Greg KH

2.6.34-stable review patch. If anyone has any objections, please let me know.

------------------

From: Christian Lamparter <[email protected]>

commit 879999cec9489f8942ebce3ec1b5f23ef948dda7 upstream.

While ar9170's USB transport packet size is currently set to 8KiB, the PHY is capable of receiving AMPDUs with up to 64KiB. Such a large frame will be split over several rx URBs and exceed the previously allocated space for rx stream reconstruction.

This patch increases the buffer size to 64KiB which is in fact the phy & rx stream designed size limit.

Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=15591

---
 drivers/net/wireless/ath/ar9170/hw.h   |    1 +
 drivers/net/wireless/ath/ar9170/main.c |    2 +-
 2 files changed, 2 insertions(+), 1 deletion(-)
drivers/net/wireless/ath/ar9170/hw.h +1 -0
@@ -425,5 +425,6 @@ enum ar9170_txq {
 
 #define AR9170_TXQ_DEPTH	32
 #define AR9170_TX_MAX_PENDING	128
+#define AR9170_RX_STREAM_MAX_SIZE 65535
 
 #endif /* __AR9170_HW_H */
drivers/net/wireless/ath/ar9170/main.c +1 -1
@@ -2516,7 +2516,7 @@ void *ar9170_alloc(size_t priv_size)
 	 * tends to split the streams into separate rx descriptors.
 	 */
 
-	skb = __dev_alloc_skb(AR9170_MAX_RX_BUFFER_SIZE, GFP_KERNEL);
+	skb = __dev_alloc_skb(AR9170_RX_STREAM_MAX_SIZE, GFP_KERNEL);
 	if (!skb)
 		goto err_nomem;
 
#479 lore raw

PATCH 35/200 ARM: 6135/1: mx21/devices: fix USBOTG resource

In reply to Greg KH

2.6.34-stable review patch. If anyone has any objections, please let me know.

------------------

From: Wolfram Sang <[email protected]>

commit e1695307e6b85477afd2421d3b4891ca5bea8300 upstream.

It got a typo from 988addf82e4c03739375279de73929580a2d4a6a.

---
 arch/arm/mach-mx2/devices.c |    4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
arch/arm/mach-mx2/devices.c +2 -2
@@ -483,8 +483,8 @@ int __init mxc_register_gpios(void)
 #ifdef CONFIG_MACH_MX21
 static struct resource mx21_usbhc_resources[] = {
 	{
-		.start	= MX21_BASE_ADDR,
-		.end	= MX21_BASE_ADDR + 0x1FFF,
+		.start	= MX21_USBOTG_BASE_ADDR,
+		.end	= MX21_USBOTG_BASE_ADDR + SZ_8K - 1,
 		.flags	= IORESOURCE_MEM,
 	},
 	{
#480 lore raw

PATCH 36/200 USB: visor: fix memory leak

In reply to Greg KH

2.6.34-stable review patch. If anyone has any objections, please let me know.

------------------

From: Johan Hovold <[email protected]>

commit 199b113978015309dd02c69844c19a1be3f4dbcf upstream.

Fix memory leak for some devices (Sony Clie 3.5) due to port private data not being freed on release.

---
 drivers/usb/serial/visor.c |    1 +
 1 file changed, 1 insertion(+)
drivers/usb/serial/visor.c +1 -0
@@ -249,6 +249,7 @@ static struct usb_serial_driver clie_3_5
 	.throttle =		visor_throttle,
 	.unthrottle =		visor_unthrottle,
 	.attach =		clie_3_5_startup,
+	.release =		visor_release,
 	.write =		visor_write,
 	.write_room =		visor_write_room,
 	.write_bulk_callback =	visor_write_bulk_callback,
#481 lore raw

PATCH 37/200 USB: CP210x New Device IDs 11 New device IDs

In reply to Greg KH

2.6.34-stable review patch. If anyone has any objections, please let me know.

------------------

From: Craig Shelley <[email protected]>

commit eefd9029fde4d90d59804eeb54880ab8db5c1866 upstream.

---
 drivers/usb/serial/cp210x.c |   11 +++++++++++
 1 file changed, 11 insertions(+)
drivers/usb/serial/cp210x.c +11 -0
@@ -61,6 +61,8 @@ static const struct usb_device_id id_tab
 	{ USB_DEVICE(0x0745, 0x1000) }, /* CipherLab USB CCD Barcode Scanner 1000 */
 	{ USB_DEVICE(0x08e6, 0x5501) }, /* Gemalto Prox-PU/CU contactless smartcard reader */
 	{ USB_DEVICE(0x08FD, 0x000A) }, /* Digianswer A/S , ZigBee/802.15.4 MAC Device */
+	{ USB_DEVICE(0x0BED, 0x1100) }, /* MEI (TM) Cashflow-SC Bill/Voucher Acceptor */
+	{ USB_DEVICE(0x0BED, 0x1101) }, /* MEI series 2000 Combo Acceptor */
 	{ USB_DEVICE(0x0FCF, 0x1003) }, /* Dynastream ANT development board */
 	{ USB_DEVICE(0x0FCF, 0x1004) }, /* Dynastream ANT2USB */
 	{ USB_DEVICE(0x0FCF, 0x1006) }, /* Dynastream ANT development board */
@@ -72,9 +74,12 @@ static const struct usb_device_id id_tab
 	{ USB_DEVICE(0x10C4, 0x1601) }, /* Arkham Technology DS101 Adapter */
 	{ USB_DEVICE(0x10C4, 0x800A) }, /* SPORTident BSM7-D-USB main station */
 	{ USB_DEVICE(0x10C4, 0x803B) }, /* Pololu USB-serial converter */
+	{ USB_DEVICE(0x10C4, 0x8044) }, /* Cygnal Debug Adapter */
+	{ USB_DEVICE(0x10C4, 0x804E) }, /* Software Bisque Paramount ME build-in converter */
 	{ USB_DEVICE(0x10C4, 0x8053) }, /* Enfora EDG1228 */
 	{ USB_DEVICE(0x10C4, 0x8054) }, /* Enfora GSM2228 */
 	{ USB_DEVICE(0x10C4, 0x8066) }, /* Argussoft In-System Programmer */
+	{ USB_DEVICE(0x10C4, 0x806F) }, /* IMS USB to RS422 Converter Cable */
 	{ USB_DEVICE(0x10C4, 0x807A) }, /* Crumb128 board */
 	{ USB_DEVICE(0x10C4, 0x80CA) }, /* Degree Controls Inc */
 	{ USB_DEVICE(0x10C4, 0x80DD) }, /* Tracient RFID */
@@ -82,12 +87,15 @@ static const struct usb_device_id id_tab
 	{ USB_DEVICE(0x10C4, 0x8115) }, /* Arygon NFC/Mifare Reader */
 	{ USB_DEVICE(0x10C4, 0x813D) }, /* Burnside Telecom Deskmobile */
 	{ USB_DEVICE(0x10C4, 0x813F) }, /* Tams Master Easy Control */
+	{ USB_DEVICE(0x10C4, 0x8149) }, /* West Mountain Radio Computerized Battery Analyzer */
 	{ USB_DEVICE(0x10C4, 0x814A) }, /* West Mountain Radio RIGblaster P&P */
 	{ USB_DEVICE(0x10C4, 0x814B) }, /* West Mountain Radio RIGtalk */
 	{ USB_DEVICE(0x10C4, 0x815E) }, /* Helicomm IP-Link 1220-DVM */
+	{ USB_DEVICE(0x10C4, 0x818B) }, /* AVIT Research USB to TTL */
 	{ USB_DEVICE(0x10C4, 0x819F) }, /* MJS USB Toslink Switcher */
 	{ USB_DEVICE(0x10C4, 0x81A6) }, /* ThinkOptics WavIt */
 	{ USB_DEVICE(0x10C4, 0x81AC) }, /* MSD Dash Hawk */
+	{ USB_DEVICE(0x10C4, 0x81AD) }, /* INSYS USB Modem */
 	{ USB_DEVICE(0x10C4, 0x81C8) }, /* Lipowsky Industrie Elektronik GmbH, Baby-JTAG */
 	{ USB_DEVICE(0x10C4, 0x81E2) }, /* Lipowsky Industrie Elektronik GmbH, Baby-LIN */
 	{ USB_DEVICE(0x10C4, 0x81E7) }, /* Aerocomm Radio */
@@ -105,6 +113,7 @@ static const struct usb_device_id id_tab
 	{ USB_DEVICE(0x10C4, 0x846E) }, /* BEI USB Sensor Interface (VCP) */
 	{ USB_DEVICE(0x10C4, 0xEA60) }, /* Silicon Labs factory default */
 	{ USB_DEVICE(0x10C4, 0xEA61) }, /* Silicon Labs factory default */
+	{ USB_DEVICE(0x10C4, 0xEA71) }, /* Infinity GPS-MIC-1 Radio Monophone */
 	{ USB_DEVICE(0x10C4, 0xF001) }, /* Elan Digital Systems USBscope50 */
 	{ USB_DEVICE(0x10C4, 0xF002) }, /* Elan Digital Systems USBwave12 */
 	{ USB_DEVICE(0x10C4, 0xF003) }, /* Elan Digital Systems USBpulse100 */
@@ -115,6 +124,8 @@ static const struct usb_device_id id_tab
 	{ USB_DEVICE(0x1555, 0x0004) }, /* Owen AC4 USB-RS485 Converter */
 	{ USB_DEVICE(0x166A, 0x0303) }, /* Clipsal 5500PCU C-Bus USB interface */
 	{ USB_DEVICE(0x16D6, 0x0001) }, /* Jablotron serial interface */
+	{ USB_DEVICE(0x17F4, 0xAAAA) }, /* Wavesense Jazz blood glucose meter */
+	{ USB_DEVICE(0x1843, 0x0200) }, /* Vaisala USB Instrument Cable */
 	{ USB_DEVICE(0x18EF, 0xE00F) }, /* ELV USB-I2C-Interface */
 	{ USB_DEVICE(0x413C, 0x9500) }, /* DW700 GPS USB interface */
 	{ } /* Terminating Entry */
#482 lore raw

PATCH 38/200 USB: kobil: fix memory leak

In reply to Greg KH

2.6.34-stable review patch. If anyone has any objections, please let me know.

------------------

From: Johan Hovold <[email protected]>

commit c0f631d1948658b27349545b2cbcb4b32f010c7a upstream.

An urb transfer buffer is allocated at every open but was never freed.

This driver is a bit of a mess...

---
 drivers/usb/serial/kobil_sct.c |    3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/usb/serial/kobil_sct.c +2 -1
@@ -345,7 +345,8 @@ static void kobil_close(struct usb_seria
 
 	/* FIXME: Add rts/dtr methods */
 	if (port->write_urb) {
-		usb_kill_urb(port->write_urb);
+		usb_poison_urb(port->write_urb);
+		kfree(port->write_urb->transfer_buffer);
 		usb_free_urb(port->write_urb);
 		port->write_urb = NULL;
 	}
#483 lore raw

PATCH 39/200 USB: tty: fix incorrect use of tty_insert_flip_string_fixed_flag

In reply to Greg KH

2.6.34-stable review patch. If anyone has any objections, please let me know.

------------------

From: Johan Hovold <[email protected]>

commit 70ced221cc9f041481f129e63cc5b1dedb0ff959 upstream.

Fix regression introduced by commit a108bfcb372d8c4452701039308fb95747911c59 (USB: tty: Prune uses of tty_request_room in the USB layer) which broke three drivers (cypress_m8, digi_acceleport and spcp8x5) through incorrect use of tty_insert_flip_string_fixed_flag.

---
 drivers/usb/serial/cypress_m8.c      |    2 +-
 drivers/usb/serial/digi_acceleport.c |    4 ++--
 drivers/usb/serial/spcp8x5.c         |    4 ++--
 3 files changed, 5 insertions(+), 5 deletions(-)
drivers/usb/serial/cypress_m8.c +1 -1
@@ -1309,7 +1309,7 @@ static void cypress_read_int_callback(st
 	/* process read if there is data other than line status */
 	if (tty && bytes > i) {
 		tty_insert_flip_string_fixed_flag(tty, data + i,
-				bytes - i, tty_flag);
+				tty_flag, bytes - i);
 		tty_flip_buffer_push(tty);
 	}
 
drivers/usb/serial/digi_acceleport.c +2 -2
@@ -1703,8 +1703,8 @@ static int digi_read_inb_callback(struct
 		/* data length is len-1 (one byte of len is port_status) */
 		--len;
 		if (len > 0) {
-			tty_insert_flip_string_fixed_flag(tty, data, len,
-									flag);
+			tty_insert_flip_string_fixed_flag(tty, data, flag,
+									len);
 			tty_flip_buffer_push(tty);
 		}
 	}
drivers/usb/serial/spcp8x5.c +2 -2
@@ -726,8 +726,8 @@ static void spcp8x5_read_bulk_callback(s
 		/* overrun is special, not associated with a char */
 		if (status & UART_OVERRUN_ERROR)
 			tty_insert_flip_char(tty, 0, TTY_OVERRUN);
-		tty_insert_flip_string_fixed_flag(tty, data,
-						urb->actual_length, tty_flag);
+		tty_insert_flip_string_fixed_flag(tty, data, tty_flag,
+							urb->actual_length);
 		tty_flip_buffer_push(tty);
 	}
 	tty_kref_put(tty);
#484 lore raw

PATCH 40/200 USB: option: add PID for ZTE product

In reply to Greg KH

2.6.34-stable review patch. If anyone has any objections, please let me know.

------------------

From: zhao1980ming <[email protected]>

commit a71ee85e1d74e862d68cc9b2f2ab6a806d2550c9 upstream.

this patch adds ZTE modem devices

---
 drivers/usb/serial/option.c |  174 ++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 174 insertions(+)
drivers/usb/serial/option.c +174 -0
@@ -675,6 +675,180 @@ static const struct usb_device_id option
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0160, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0161, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0162, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1008, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1010, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1012, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1057, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1058, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1059, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1060, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1061, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1062, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1063, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1064, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1065, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1066, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1067, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1068, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1069, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1070, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1071, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1072, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1073, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1074, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1075, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1076, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1077, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1078, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1079, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1080, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1081, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1082, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1083, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1084, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1085, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1086, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1087, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1088, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1089, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1090, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1091, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1092, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1093, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1094, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1095, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1096, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1097, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1098, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1099, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1100, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1101, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1102, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1103, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1104, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1105, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1106, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1107, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1108, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1109, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1110, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1111, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1112, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1113, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1114, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1115, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1116, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1117, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1118, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1119, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1120, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1121, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1122, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1123, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1124, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1125, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1126, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1127, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1128, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1129, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1130, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1131, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1132, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1133, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1134, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1135, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1136, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1137, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1138, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1139, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1140, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1141, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1142, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1143, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1144, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1145, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1146, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1147, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1148, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1149, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1150, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1151, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1152, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1153, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1154, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1155, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1156, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1157, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1158, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1159, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1160, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1161, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1162, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1163, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1164, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1165, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1166, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1167, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1168, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1169, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1170, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1244, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1245, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1246, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1247, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1248, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1249, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1250, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1251, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1252, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1253, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1254, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1255, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1256, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1257, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1258, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1259, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1260, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1261, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1262, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1263, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1264, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1265, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1266, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1267, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1268, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1269, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1270, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1271, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1272, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1273, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1274, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1275, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1276, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1277, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1278, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1279, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1280, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1281, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1282, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1283, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1284, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1285, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1286, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1287, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1288, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1289, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1290, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1291, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1292, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1293, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1294, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1295, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1296, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1297, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1298, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1299, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1300, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0014, 0xff, 0xff, 0xff) }, /* ZTE CDMA products */
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0027, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0059, 0xff, 0xff, 0xff) },
#485 lore raw

PATCH 41/200 USB: option.c: OLIVETTI OLICARD100 support

In reply to Greg KH

2.6.34-stable review patch. If anyone has any objections, please let me know.

------------------

From: Nils Radtke <[email protected]>

commit 86234d4975ce084d14711283a3bfc69305f97602 upstream.

This patch adds support for an olivetti olicard100 HЅDPA usb-stick.

This device is a zeroCD one with ID 0b3c:c700 that needs switching via eject or usb-modeswitch with MessageContent="5553424312345678000000000000061b000000030000000000000000000000". After switching it has ID 0b3c:c000 and provides 5 serial ports ttyUSB[0-4]. Port 0 (modem) and 4 are interrupt ports.

---
 drivers/usb/serial/option.c |    6 ++++++
 1 file changed, 6 insertions(+)
drivers/usb/serial/option.c +6 -0
@@ -380,6 +380,10 @@ static int  option_resume(struct usb_ser
 
 #define CINTERION_VENDOR_ID			0x0681
 
+/* Olivetti products */
+#define OLIVETTI_VENDOR_ID			0x0b3c
+#define OLIVETTI_PRODUCT_OLICARD100		0xc000
+
 /* some devices interfaces need special handling due to a number of reasons */
 enum option_blacklist_reason {
 		OPTION_BLACKLIST_NONE = 0,
@@ -900,6 +904,8 @@ static const struct usb_device_id option
 	{ USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_1012)},
 
 	{ USB_DEVICE(CINTERION_VENDOR_ID, 0x0047) },
+
+	{ USB_DEVICE(OLIVETTI_VENDOR_ID, OLIVETTI_PRODUCT_OLICARD100) },
 	{ } /* Terminating entry */
 };
 MODULE_DEVICE_TABLE(usb, option_ids);
#486 lore raw

PATCH 42/200 USB: ir-usb: fix double free

In reply to Greg KH

2.6.34-stable review patch. If anyone has any objections, please let me know.

------------------

From: Johan Hovold <[email protected]>

commit 2ff78c0c2b67120c8e503268da3f177cae2228a2 upstream.

If the user specifies a custom bulk buffer size we get a double free at port release.

---
 drivers/usb/serial/ir-usb.c |    2 ++
 1 file changed, 2 insertions(+)
drivers/usb/serial/ir-usb.c +2 -0
@@ -312,6 +312,7 @@ static int ir_open(struct tty_struct *tt
 		kfree(port->read_urb->transfer_buffer);
 		port->read_urb->transfer_buffer = buffer;
 		port->read_urb->transfer_buffer_length = buffer_size;
+		port->bulk_in_buffer = buffer;
 
 		buffer = kmalloc(buffer_size, GFP_KERNEL);
 		if (!buffer) {
@@ -321,6 +322,7 @@ static int ir_open(struct tty_struct *tt
 		kfree(port->write_urb->transfer_buffer);
 		port->write_urb->transfer_buffer = buffer;
 		port->write_urb->transfer_buffer_length = buffer_size;
+		port->bulk_out_buffer = buffer;
 		port->bulk_out_size = buffer_size;
 	}
 
#487 lore raw

PATCH 43/200 USB: kl5usb105: fix memory leak

In reply to Greg KH

2.6.34-stable review patch. If anyone has any objections, please let me know.

------------------

From: Johan Hovold <[email protected]>

commit 313b0d80c1717ffe8f64b455a4d323996748b91a upstream.

Private data was not freed on error path in startup.

---
 drivers/usb/serial/kl5kusb105.c |    1 +
 1 file changed, 1 insertion(+)
drivers/usb/serial/kl5kusb105.c +1 -0
@@ -321,6 +321,7 @@ err_cleanup:
 				usb_free_urb(priv->write_urb_pool[j]);
 			}
 		}
+		kfree(priv);
 		usb_set_serial_port_data(serial->port[i], NULL);
 	}
 	return -ENOMEM;
#488 lore raw

PATCH 44/200 USB: qcaux: add Samsung U520 device ID

In reply to Greg KH

2.6.34-stable review patch. If anyone has any objections, please let me know.

------------------

From: Dan Williams <[email protected]>

commit f5cddcd0995366f15d2b6b0df556a2cd99fa806e upstream.

Another CDC-ACM + vendor specific interface layout.

---
 drivers/usb/serial/qcaux.c |    5 +++++
 1 file changed, 5 insertions(+)
drivers/usb/serial/qcaux.c +5 -0
@@ -50,6 +50,10 @@
 #define SANYO_VENDOR_ID				0x0474
 #define SANYO_PRODUCT_KATANA_LX			0x0754 /* SCP-3800 (Katana LX) */
 
+/* Samsung devices */
+#define SAMSUNG_VENDOR_ID			0x04e8
+#define SAMSUNG_PRODUCT_U520			0x6640 /* SCH-U520 */
+
 static struct usb_device_id id_table[] = {
 	{ USB_DEVICE_AND_INTERFACE_INFO(UTSTARCOM_VENDOR_ID, UTSTARCOM_PRODUCT_PC5740, 0xff, 0x00, 0x00) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(UTSTARCOM_VENDOR_ID, UTSTARCOM_PRODUCT_PC5750, 0xff, 0x00, 0x00) },
@@ -61,6 +65,7 @@ static struct usb_device_id id_table[] =
 	{ USB_DEVICE_AND_INTERFACE_INFO(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_CDX650, 0xff, 0xff, 0x00) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(LG_VENDOR_ID, LG_PRODUCT_VX4400_6000, 0xff, 0xff, 0x00) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(SANYO_VENDOR_ID, SANYO_PRODUCT_KATANA_LX, 0xff, 0xff, 0x00) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(SAMSUNG_VENDOR_ID, SAMSUNG_PRODUCT_U520, 0xff, 0x00, 0x00) },
 	{ },
 };
 MODULE_DEVICE_TABLE(usb, id_table);
#489 lore raw

PATCH 45/200 USB: mxc: gadget: Fix bitfield for calculating maximum packet size

In reply to Greg KH

2.6.34-stable review patch. If anyone has any objections, please let me know.

------------------

From: Dinh Nguyen <[email protected]>

commit 88e3b59b5adce5b12e205af0e34d518ba0dcdc0c upstream.

The max packet length bit mask used for isochronous endpoints should be 0x7FF instead of 0x8FF. 0x8FF will actually clear higher-order bits in the max packet length field.

This patch applies to 2.6.34-rc6.

---
 drivers/usb/gadget/fsl_udc_core.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/usb/gadget/fsl_udc_core.c +1 -1
@@ -489,7 +489,7 @@ static int fsl_ep_enable(struct usb_ep *
 	case USB_ENDPOINT_XFER_ISOC:
 		/* Calculate transactions needed for high bandwidth iso */
 		mult = (unsigned char)(1 + ((max >> 11) & 0x03));
-		max = max & 0x8ff;	/* bit 0~10 */
+		max = max & 0x7ff;	/* bit 0~10 */
 		/* 3 transactions at most */
 		if (mult > 3)
 			goto en_done;
#490 lore raw

PATCH 46/200 USB: unusual-dev: Add bad sense flag for Appotech ax203 based picture frames

In reply to Greg KH

2.6.34-stable review patch. If anyone has any objections, please let me know.

------------------

From: Hans de Goede <[email protected]>

commit a78f4f1a16d87f3d33158d036af94e48e32f8aad upstream.

These Appotech controllers are found in Picture Frames, they provide a (buggy) emulation of a cdrom drive which contains the windows software Uploading of pictures happens over the corresponding /dev/sg device.

---
 drivers/usb/storage/unusual_devs.h |   15 +++++++++++++++
 1 file changed, 15 insertions(+)
drivers/usb/storage/unusual_devs.h +15 -0
@@ -1853,6 +1853,21 @@ UNUSUAL_DEV(  0x1652, 0x6600, 0x0201, 0x
 		US_SC_DEVICE, US_PR_DEVICE, NULL,
 		US_FL_IGNORE_RESIDUE ),
 
+/* Reported by Hans de Goede <[email protected]>
+ * These Appotech controllers are found in Picture Frames, they provide a
+ * (buggy) emulation of a cdrom drive which contains the windows software
+ * Uploading of pictures happens over the corresponding /dev/sg device. */
+UNUSUAL_DEV( 0x1908, 0x1315, 0x0000, 0x0000,
+		"BUILDWIN",
+		"Photo Frame",
+		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		US_FL_BAD_SENSE ),
+UNUSUAL_DEV( 0x1908, 0x1320, 0x0000, 0x0000,
+		"BUILDWIN",
+		"Photo Frame",
+		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		US_FL_BAD_SENSE ),
+
 UNUSUAL_DEV( 0x2116, 0x0320, 0x0001, 0x0001,
 		"ST",
 		"2A",
#491 lore raw

PATCH 47/200 USB: fix usbmon and DMA mapping for scatter-gather URBs

In reply to Greg KH

2.6.34-stable review patch. If anyone has any objections, please let me know.

------------------

From: Alan Stern <[email protected]>

commit ff9c895f07d36193c75533bda8193bde8ca99d02 upstream.

This patch (as1368) fixes a rather obscure bug in usbmon: When tracing URBs sent by the scatter-gather library, it accesses the data buffers while they are still mapped for DMA.

The solution is to move the mapping and unmapping out of the s-g library and into the usual place in hcd.c. This requires the addition of new URB flag bits to describe the kind of mapping needed, since we have to call dma_map_sg() if the HCD supports native scatter-gather operation and dma_map_page() if it doesn't. The nice thing about having the new flags is that they simplify the testing for unmapping.

The patch removes the only caller of usb_buffer_[un]map_sg(), so those functions are #if'ed out. A later patch will remove them entirely.

As a result of this change, urb->sg will be set in situations where it wasn't set previously. Hence the xhci and whci drivers are adjusted to test urb->num_sgs instead, which retains its original meaning and is nonzero only when the HCD has to handle a scatterlist.

Finally, even when a submission error occurs we don't want to hand URBs to usbmon before they are unmapped. The submission path is rearranged so that map_urb_for_dma() is called only for non-root-hub URBs and unmap_urb_for_dma() is called immediately after a submission error. This simplifies the error handling.

---
 drivers/usb/core/hcd.c       |  169 ++++++++++++++++++++++++++-----------------
 drivers/usb/core/message.c   |   45 ++---------
 drivers/usb/core/urb.c       |    9 +-
 drivers/usb/core/usb.c       |    4 +
 drivers/usb/host/whci/qset.c |    2 
 drivers/usb/host/xhci-ring.c |    2 
 drivers/usb/mon/mon_bin.c    |    2 
 drivers/usb/mon/mon_text.c   |    4 -
 include/linux/usb.h          |    9 ++
 9 files changed, 138 insertions(+), 108 deletions(-)
drivers/usb/core/hcd.c +105 -64
@@ -1261,6 +1261,51 @@ static void hcd_free_coherent(struct usb
 	*dma_handle = 0;
 }
 
+static void unmap_urb_for_dma(struct usb_hcd *hcd, struct urb *urb)
+{
+	enum dma_data_direction dir;
+
+	if (urb->transfer_flags & URB_SETUP_MAP_SINGLE)
+		dma_unmap_single(hcd->self.controller,
+				urb->setup_dma,
+				sizeof(struct usb_ctrlrequest),
+				DMA_TO_DEVICE);
+	else if (urb->transfer_flags & URB_SETUP_MAP_LOCAL)
+		hcd_free_coherent(urb->dev->bus,
+				&urb->setup_dma,
+				(void **) &urb->setup_packet,
+				sizeof(struct usb_ctrlrequest),
+				DMA_TO_DEVICE);
+
+	dir = usb_urb_dir_in(urb) ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
+	if (urb->transfer_flags & URB_DMA_MAP_SG)
+		dma_unmap_sg(hcd->self.controller,
+				urb->sg->sg,
+				urb->num_sgs,
+				dir);
+	else if (urb->transfer_flags & URB_DMA_MAP_PAGE)
+		dma_unmap_page(hcd->self.controller,
+				urb->transfer_dma,
+				urb->transfer_buffer_length,
+				dir);
+	else if (urb->transfer_flags & URB_DMA_MAP_SINGLE)
+		dma_unmap_single(hcd->self.controller,
+				urb->transfer_dma,
+				urb->transfer_buffer_length,
+				dir);
+	else if (urb->transfer_flags & URB_MAP_LOCAL)
+		hcd_free_coherent(urb->dev->bus,
+				&urb->transfer_dma,
+				&urb->transfer_buffer,
+				urb->transfer_buffer_length,
+				dir);
+
+	/* Make it safe to call this routine more than once */
+	urb->transfer_flags &= ~(URB_SETUP_MAP_SINGLE | URB_SETUP_MAP_LOCAL |
+			URB_DMA_MAP_SG | URB_DMA_MAP_PAGE |
+			URB_DMA_MAP_SINGLE | URB_MAP_LOCAL);
+}
+
 static int map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb,
 			   gfp_t mem_flags)
 {
@@ -1272,8 +1317,6 @@ static int map_urb_for_dma(struct usb_hc
 	 * unless it uses pio or talks to another transport,
 	 * or uses the provided scatter gather list for bulk.
 	 */
-	if (is_root_hub(urb->dev))
-		return 0;
 
 	if (usb_endpoint_xfer_control(&urb->ep->desc)
 	    && !(urb->transfer_flags & URB_NO_SETUP_DMA_MAP)) {
@@ -1286,6 +1329,7 @@ static int map_urb_for_dma(struct usb_hc
 			if (dma_mapping_error(hcd->self.controller,
 						urb->setup_dma))
 				return -EAGAIN;
+			urb->transfer_flags |= URB_SETUP_MAP_SINGLE;
 		} else if (hcd->driver->flags & HCD_LOCAL_MEM)
 			ret = hcd_alloc_coherent(
 					urb->dev->bus, mem_flags,
@@ -1293,20 +1337,57 @@ static int map_urb_for_dma(struct usb_hc
 					(void **)&urb->setup_packet,
 					sizeof(struct usb_ctrlrequest),
 					DMA_TO_DEVICE);
+			if (ret)
+				return ret;
+			urb->transfer_flags |= URB_SETUP_MAP_LOCAL;
 	}
 
 	dir = usb_urb_dir_in(urb) ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
-	if (ret == 0 && urb->transfer_buffer_length != 0
+	if (urb->transfer_buffer_length != 0
 	    && !(urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP)) {
 		if (hcd->self.uses_dma) {
-			urb->transfer_dma = dma_map_single (
-					hcd->self.controller,
-					urb->transfer_buffer,
-					urb->transfer_buffer_length,
-					dir);
-			if (dma_mapping_error(hcd->self.controller,
+			if (urb->num_sgs) {
+				int n = dma_map_sg(
+						hcd->self.controller,
+						urb->sg->sg,
+						urb->num_sgs,
+						dir);
+				if (n <= 0)
+					ret = -EAGAIN;
+				else
+					urb->transfer_flags |= URB_DMA_MAP_SG;
+				if (n != urb->num_sgs) {
+					urb->num_sgs = n;
+					urb->transfer_flags |=
+							URB_DMA_SG_COMBINED;
+				}
+			} else if (urb->sg) {
+				struct scatterlist *sg;
+
+				sg = (struct scatterlist *) urb->sg;
+				urb->transfer_dma = dma_map_page(
+						hcd->self.controller,
+						sg_page(sg),
+						sg->offset,
+						urb->transfer_buffer_length,
+						dir);
+				if (dma_mapping_error(hcd->self.controller,
 						urb->transfer_dma))
-				return -EAGAIN;
+					ret = -EAGAIN;
+				else
+					urb->transfer_flags |= URB_DMA_MAP_PAGE;
+			} else {
+				urb->transfer_dma = dma_map_single(
+						hcd->self.controller,
+						urb->transfer_buffer,
+						urb->transfer_buffer_length,
+						dir);
+				if (dma_mapping_error(hcd->self.controller,
+						urb->transfer_dma))
+					ret = -EAGAIN;
+				else
+					urb->transfer_flags |= URB_DMA_MAP_SINGLE;
+			}
 		} else if (hcd->driver->flags & HCD_LOCAL_MEM) {
 			ret = hcd_alloc_coherent(
 					urb->dev->bus, mem_flags,
@@ -1314,55 +1395,16 @@ static int map_urb_for_dma(struct usb_hc
 					&urb->transfer_buffer,
 					urb->transfer_buffer_length,
 					dir);
-
-			if (ret && usb_endpoint_xfer_control(&urb->ep->desc)
-			    && !(urb->transfer_flags & URB_NO_SETUP_DMA_MAP))
-				hcd_free_coherent(urb->dev->bus,
-					&urb->setup_dma,
-					(void **)&urb->setup_packet,
-					sizeof(struct usb_ctrlrequest),
-					DMA_TO_DEVICE);
+			if (ret == 0)
+				urb->transfer_flags |= URB_MAP_LOCAL;
 		}
+		if (ret && (urb->transfer_flags & (URB_SETUP_MAP_SINGLE |
+				URB_SETUP_MAP_LOCAL)))
+			unmap_urb_for_dma(hcd, urb);
 	}
 	return ret;
 }
 
-static void unmap_urb_for_dma(struct usb_hcd *hcd, struct urb *urb)
-{
-	enum dma_data_direction dir;
-
-	if (is_root_hub(urb->dev))
-		return;
-
-	if (usb_endpoint_xfer_control(&urb->ep->desc)
-	    && !(urb->transfer_flags & URB_NO_SETUP_DMA_MAP)) {
-		if (hcd->self.uses_dma)
-			dma_unmap_single(hcd->self.controller, urb->setup_dma,
-					sizeof(struct usb_ctrlrequest),
-					DMA_TO_DEVICE);
-		else if (hcd->driver->flags & HCD_LOCAL_MEM)
-			hcd_free_coherent(urb->dev->bus, &urb->setup_dma,
-					(void **)&urb->setup_packet,
-					sizeof(struct usb_ctrlrequest),
-					DMA_TO_DEVICE);
-	}
-
-	dir = usb_urb_dir_in(urb) ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
-	if (urb->transfer_buffer_length != 0
-	    && !(urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP)) {
-		if (hcd->self.uses_dma)
-			dma_unmap_single(hcd->self.controller,
-					urb->transfer_dma,
-					urb->transfer_buffer_length,
-					dir);
-		else if (hcd->driver->flags & HCD_LOCAL_MEM)
-			hcd_free_coherent(urb->dev->bus, &urb->transfer_dma,
-					&urb->transfer_buffer,
-					urb->transfer_buffer_length,
-					dir);
-	}
-}
-
 /*-------------------------------------------------------------------------*/
 
 /* may be called in any context with a valid urb->dev usecount
@@ -1391,21 +1433,20 @@ int usb_hcd_submit_urb (struct urb *urb,
 	 * URBs must be submitted in process context with interrupts
 	 * enabled.
 	 */
-	status = map_urb_for_dma(hcd, urb, mem_flags);
-	if (unlikely(status)) {
-		usbmon_urb_submit_error(&hcd->self, urb, status);
-		goto error;
-	}
 
-	if (is_root_hub(urb->dev))
+	if (is_root_hub(urb->dev)) {
 		status = rh_urb_enqueue(hcd, urb);
-	else
-		status = hcd->driver->urb_enqueue(hcd, urb, mem_flags);
+	} else {
+		status = map_urb_for_dma(hcd, urb, mem_flags);
+		if (likely(status == 0)) {
+			status = hcd->driver->urb_enqueue(hcd, urb, mem_flags);
+			if (unlikely(status))
+				unmap_urb_for_dma(hcd, urb);
+		}
+	}
 
 	if (unlikely(status)) {
 		usbmon_urb_submit_error(&hcd->self, urb, status);
-		unmap_urb_for_dma(hcd, urb);
- error:
 		urb->hcpriv = NULL;
 		INIT_LIST_HEAD(&urb->urb_list);
 		atomic_dec(&urb->use_count);
drivers/usb/core/message.c +10 -35

99 lines not on this page · raw message

drivers/usb/core/urb.c +6 -3
@@ -333,9 +333,12 @@ int usb_submit_urb(struct urb *urb, gfp_
 		is_out = usb_endpoint_dir_out(&ep->desc);
 	}
 
-	/* Cache the direction for later use */
-	urb->transfer_flags = (urb->transfer_flags & ~URB_DIR_MASK) |
-			(is_out ? URB_DIR_OUT : URB_DIR_IN);
+	/* Clear the internal flags and cache the direction for later use */
+	urb->transfer_flags &= ~(URB_DIR_MASK | URB_DMA_MAP_SINGLE |
+			URB_DMA_MAP_PAGE | URB_DMA_MAP_SG | URB_MAP_LOCAL |
+			URB_SETUP_MAP_SINGLE | URB_SETUP_MAP_LOCAL |
+			URB_DMA_SG_COMBINED);
+	urb->transfer_flags |= (is_out ? URB_DIR_OUT : URB_DIR_IN);
 
 	if (xfertype != USB_ENDPOINT_XFER_CONTROL &&
 			dev->state < USB_STATE_CONFIGURED)
drivers/usb/core/usb.c +4 -0
@@ -893,6 +893,7 @@ void usb_buffer_unmap(struct urb *urb)
 EXPORT_SYMBOL_GPL(usb_buffer_unmap);
 #endif  /*  0  */
 
+#if 0
 /**
  * usb_buffer_map_sg - create scatterlist DMA mapping(s) for an endpoint
  * @dev: device to which the scatterlist will be mapped
@@ -936,6 +937,7 @@ int usb_buffer_map_sg(const struct usb_d
 			is_in ? DMA_FROM_DEVICE : DMA_TO_DEVICE) ? : -ENOMEM;
 }
 EXPORT_SYMBOL_GPL(usb_buffer_map_sg);
+#endif
 
 /* XXX DISABLED, no users currently.  If you wish to re-enable this
  * XXX please determine whether the sync is to transfer ownership of
@@ -972,6 +974,7 @@ void usb_buffer_dmasync_sg(const struct
 EXPORT_SYMBOL_GPL(usb_buffer_dmasync_sg);
 #endif
 
+#if 0
 /**
  * usb_buffer_unmap_sg - free DMA mapping(s) for a scatterlist
  * @dev: device to which the scatterlist will be mapped
@@ -997,6 +1000,7 @@ void usb_buffer_unmap_sg(const struct us
 			is_in ? DMA_FROM_DEVICE : DMA_TO_DEVICE);
 }
 EXPORT_SYMBOL_GPL(usb_buffer_unmap_sg);
+#endif
 
 /* To disable USB, kernel command line is 'nousb' not 'usbcore.nousb' */
 #ifdef MODULE
drivers/usb/host/whci/qset.c +1 -1
@@ -646,7 +646,7 @@ int qset_add_urb(struct whc *whc, struct
 	wurb->urb = urb;
 	INIT_WORK(&wurb->dequeue_work, urb_dequeue_work);
 
-	if (urb->sg) {
+	if (urb->num_sgs) {
 		ret = qset_add_urb_sg(whc, qset, urb, mem_flags);
 		if (ret == -EINVAL) {
 			qset_free_stds(qset, urb);
drivers/usb/host/xhci-ring.c +1 -1
@@ -1938,7 +1938,7 @@ int xhci_queue_bulk_tx(struct xhci_hcd *
 	int running_total, trb_buff_len, ret;
 	u64 addr;
 
-	if (urb->sg)
+	if (urb->num_sgs)
 		return queue_bulk_sg_tx(xhci, mem_flags, urb, slot_id, ep_index);
 
 	ep_ring = xhci->devs[slot_id]->eps[ep_index].ring;
drivers/usb/mon/mon_bin.c +1 -1
@@ -416,7 +416,7 @@ static unsigned int mon_bin_get_data(con
 
 	} else {
 		/* If IOMMU coalescing occurred, we cannot trust sg_page */
-		if (urb->sg->nents != urb->num_sgs) {
+		if (urb->transfer_flags & URB_DMA_SG_COMBINED) {
 			*flag = 'D';
 			return length;
 		}
drivers/usb/mon/mon_text.c +1 -3
@@ -161,9 +161,7 @@ static inline char mon_text_get_data(str
 	} else {
 		struct scatterlist *sg = urb->sg->sg;
 
-		/* If IOMMU coalescing occurred, we cannot trust sg_page */
-		if (urb->sg->nents != urb->num_sgs ||
-				PageHighMem(sg_page(sg)))
+		if (PageHighMem(sg_page(sg)))
 			return 'D';
 
 		/* For the text interface we copy only the first sg buffer */
include/linux/usb.h +9 -0
@@ -965,10 +965,19 @@ extern int usb_disabled(void);
 					 * needed */
 #define URB_FREE_BUFFER		0x0100	/* Free transfer buffer with the URB */
 
+/* The following flags are used internally by usbcore and HCDs */
 #define URB_DIR_IN		0x0200	/* Transfer from device to host */
 #define URB_DIR_OUT		0
 #define URB_DIR_MASK		URB_DIR_IN
 
+#define URB_DMA_MAP_SINGLE	0x00010000	/* Non-scatter-gather mapping */
+#define URB_DMA_MAP_PAGE	0x00020000	/* HCD-unsupported S-G */
+#define URB_DMA_MAP_SG		0x00040000	/* HCD-supported S-G */
+#define URB_MAP_LOCAL		0x00080000	/* HCD-local-memory mapping */
+#define URB_SETUP_MAP_SINGLE	0x00100000	/* Setup packet DMA mapped */
+#define URB_SETUP_MAP_LOCAL	0x00200000	/* HCD-local setup packet */
+#define URB_DMA_SG_COMBINED	0x00400000	/* S-G entries were combined */
+
 struct usb_iso_packet_descriptor {
 	unsigned int offset;
 	unsigned int length;		/* expected length */
#492 lore raw

PATCH 48/200 USB: FHCI: cq_get() should check kfifo_out()s return value

In reply to Greg KH

2.6.34-stable review patch. If anyone has any objections, please let me know.

------------------

From: Anton Vorontsov <[email protected]>

commit 7f1cccd3ec8789e52897bc34420ca81a5e2edeab upstream.

Since commit 7acd72eb85f1c7a15e8b5eb554994949241737f1 ("kfifo: rename kfifo_put... into kfifo_in... and kfifo_get... into kfifo_out..."), kfifo_out() is marked __must_check, and that causes gcc to produce lots of warnings like this:

CC drivers/usb/host/fhci-mem.o
In file included from drivers/usb/host/fhci-hcd.c:34:
drivers/usb/host/fhci.h: In function 'cq_get':
drivers/usb/host/fhci.h:520: warning: ignoring return value of 'kfifo_out', declared with attribute warn_unused_result
...

This patch fixes the issue by properly checking the return value.

---
 drivers/usb/host/fhci.h |    9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)
drivers/usb/host/fhci.h +7 -2
@@ -20,6 +20,7 @@
 
 #include <linux/kernel.h>
 #include <linux/types.h>
+#include <linux/bug.h>
 #include <linux/spinlock.h>
 #include <linux/interrupt.h>
 #include <linux/kfifo.h>
@@ -515,9 +516,13 @@ static inline int cq_put(struct kfifo *k
 
 static inline void *cq_get(struct kfifo *kfifo)
 {
-	void *p = NULL;
+	unsigned int sz;
+	void *p;
+
+	sz = kfifo_out(kfifo, (void *)&p, sizeof(p));
+	if (sz != sizeof(p))
+		return NULL;
 
-	kfifo_out(kfifo, (void *)&p, sizeof(p));
 	return p;
 }
 
#493 lore raw

PATCH 49/200 USB: EHCI: clear PHCD before resuming

In reply to Greg KH

2.6.34-stable review patch. If anyone has any objections, please let me know.

------------------

From: Alek Du <[email protected]>

commit eab80de01cb398419ef3305f35abcb367c647c8b upstream.

This is a bug fix for PHCD (phy clock disable) low power feature:
After PHCD is set, any write to PORTSC register is illegal, so when resume ports, clear PHCD bit first.

---
 drivers/usb/host/ehci-hub.c |   17 +++++++++++++++++
 1 file changed, 17 insertions(+)
drivers/usb/host/ehci-hub.c +17 -0
@@ -294,6 +294,16 @@ static int ehci_bus_resume (struct usb_h
 	/* manually resume the ports we suspended during bus_suspend() */
 	i = HCS_N_PORTS (ehci->hcs_params);
 	while (i--) {
+		/* clear phy low power mode before resume */
+		if (ehci->has_hostpc) {
+			u32 __iomem	*hostpc_reg =
+				(u32 __iomem *)((u8 *)ehci->regs
+				+ HOSTPC0 + 4 * (i & 0xff));
+			temp = ehci_readl(ehci, hostpc_reg);
+			ehci_writel(ehci, temp & ~HOSTPC_PHCD,
+				hostpc_reg);
+			mdelay(5);
+		}
 		temp = ehci_readl(ehci, &ehci->regs->port_status [i]);
 		temp &= ~(PORT_RWC_BITS | PORT_WAKE_BITS);
 		if (test_bit(i, &ehci->bus_suspended) &&
@@ -678,6 +688,13 @@ static int ehci_hub_control (
 			if (temp & PORT_SUSPEND) {
 				if ((temp & PORT_PE) == 0)
 					goto error;
+				/* clear phy low power mode before resume */
+				if (hostpc_reg) {
+					temp1 = ehci_readl(ehci, hostpc_reg);
+					ehci_writel(ehci, temp1 & ~HOSTPC_PHCD,
+						hostpc_reg);
+					mdelay(5);
+				}
 				/* resume signaling for 20 msec */
 				temp &= ~(PORT_RWC_BITS | PORT_WAKE_BITS);
 				ehci_writel(ehci, temp | PORT_RESUME,
#494 lore raw

PATCH 50/200 USB: EHCI: fix controller wakeup flag settings during suspend

In reply to Greg KH

2.6.34-stable review patch. If anyone has any objections, please let me know.

------------------

From: Alan Stern <[email protected]>

commit 16032c4f5b291af541e9114a09ea20ff5a0dc474 upstream.

This patch (as1380) fixes a bug in the wakeup settings for EHCI host controllers. When the controller is suspended, if it isn't enabled for remote wakeup then we have to turn off all the port wakeup flags. Disabling PCI PME# isn't good enough, because some systems (Intel) evidently use alternate wakeup signalling paths.

In addition, the patch improves the handling of the Intel Moorestown hardware by performing various power-up and power-down delays just once instead of once for each port (i.e., the delays are moved outside of the port loops). This requires extra code, but the total delay time is reduced.

There are also a few additional minor cleanups.

---
 drivers/usb/host/ehci-au1xxx.c |   16 ---
 drivers/usb/host/ehci-fsl.c    |    2 
 drivers/usb/host/ehci-hub.c    |  173 +++++++++++++++++++++++++++++------------
 drivers/usb/host/ehci-pci.c    |   15 ---
 drivers/usb/host/ehci.h        |   10 ++
 5 files changed, 145 insertions(+), 71 deletions(-)
drivers/usb/host/ehci-au1xxx.c +4 -12
@@ -215,26 +215,17 @@ static int ehci_hcd_au1xxx_drv_suspend(s
 		msleep(10);
 
 	/* Root hub was already suspended. Disable irq emission and
-	 * mark HW unaccessible, bail out if RH has been resumed. Use
-	 * the spinlock to properly synchronize with possible pending
-	 * RH suspend or resume activity.
-	 *
-	 * This is still racy as hcd->state is manipulated outside of
-	 * any locks =P But that will be a different fix.
+	 * mark HW unaccessible.  The PM and USB cores make sure that
+	 * the root hub is either suspended or stopped.
 	 */
 	spin_lock_irqsave(&ehci->lock, flags);
-	if (hcd->state != HC_STATE_SUSPENDED) {
-		rc = -EINVAL;
-		goto bail;
-	}
+	ehci_prepare_ports_for_controller_suspend(ehci);
 	ehci_writel(ehci, 0, &ehci->regs->intr_enable);
 	(void)ehci_readl(ehci, &ehci->regs->intr_enable);
 
 	clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
 
 	au1xxx_stop_ehc();
-
-bail:
 	spin_unlock_irqrestore(&ehci->lock, flags);
 
 	// could save FLADJ in case of Vaux power loss
@@ -264,6 +255,7 @@ static int ehci_hcd_au1xxx_drv_resume(st
 	if (ehci_readl(ehci, &ehci->regs->configured_flag) == FLAG_CF) {
 		int	mask = INTR_MASK;
 
+		ehci_prepare_ports_for_controller_resume(ehci);
 		if (!hcd->self.root_hub->do_remote_wakeup)
 			mask &= ~STS_PCD;
 		ehci_writel(ehci, mask, &ehci->regs->intr_enable);
drivers/usb/host/ehci-fsl.c +2 -0
@@ -313,6 +313,7 @@ static int ehci_fsl_drv_suspend(struct d
 	struct ehci_fsl *ehci_fsl = hcd_to_ehci_fsl(hcd);
 	void __iomem *non_ehci = hcd->regs;
 
+	ehci_prepare_ports_for_controller_suspend(hcd_to_ehci(hcd));
 	if (!fsl_deep_sleep())
 		return 0;
 
@@ -327,6 +328,7 @@ static int ehci_fsl_drv_resume(struct de
 	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
 	void __iomem *non_ehci = hcd->regs;
 
+	ehci_prepare_ports_for_controller_resume(ehci);
 	if (!fsl_deep_sleep())
 		return 0;
 
drivers/usb/host/ehci-hub.c +125 -48

234 lines not on this page · raw message

drivers/usb/host/ehci-pci.c +4 -11
@@ -284,23 +284,15 @@ static int ehci_pci_suspend(struct usb_h
 		msleep(10);
 
 	/* Root hub was already suspended. Disable irq emission and
-	 * mark HW unaccessible, bail out if RH has been resumed. Use
-	 * the spinlock to properly synchronize with possible pending
-	 * RH suspend or resume activity.
-	 *
-	 * This is still racy as hcd->state is manipulated outside of
-	 * any locks =P But that will be a different fix.
+	 * mark HW unaccessible.  The PM and USB cores make sure that
+	 * the root hub is either suspended or stopped.
 	 */
 	spin_lock_irqsave (&ehci->lock, flags);
-	if (hcd->state != HC_STATE_SUSPENDED) {
-		rc = -EINVAL;
-		goto bail;
-	}
+	ehci_prepare_ports_for_controller_suspend(ehci);
 	ehci_writel(ehci, 0, &ehci->regs->intr_enable);
 	(void)ehci_readl(ehci, &ehci->regs->intr_enable);
 
 	clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
- bail:
 	spin_unlock_irqrestore (&ehci->lock, flags);
 
 	// could save FLADJ in case of Vaux power loss
@@ -330,6 +322,7 @@ static int ehci_pci_resume(struct usb_hc
 				!hibernated) {
 		int	mask = INTR_MASK;
 
+		ehci_prepare_ports_for_controller_resume(ehci);
 		if (!hcd->self.root_hub->do_remote_wakeup)
 			mask &= ~STS_PCD;
 		ehci_writel(ehci, mask, &ehci->regs->intr_enable);
drivers/usb/host/ehci.h +10 -0
@@ -536,6 +536,16 @@ struct ehci_fstn {
 
 /*-------------------------------------------------------------------------*/
 
+/* Prepare the PORTSC wakeup flags during controller suspend/resume */
+
+#define ehci_prepare_ports_for_controller_suspend(ehci)		\
+		ehci_adjust_port_wakeup_flags(ehci, true);
+
+#define ehci_prepare_ports_for_controller_resume(ehci)		\
+		ehci_adjust_port_wakeup_flags(ehci, false);
+
+/*-------------------------------------------------------------------------*/
+
 #ifdef CONFIG_USB_EHCI_ROOT_HUB_TT
 
 /*
#495 lore raw

PATCH 51/200 USB: xhci: Fix issue with set interface after stall.

In reply to Greg KH

2.6.34-stable review patch. If anyone has any objections, please let me know.

------------------

From: Sarah Sharp <[email protected]>

commit 1624ae1c19e227096ba85bfc389d9b99cb6f7dde upstream.

When the USB core installs a new interface, it unconditionally clears the halts on all the endpoints on the new interface. Usually the xHCI host needs to know when an endpoint is reset, so it can change its internal endpoint state. In this case, it doesn't care, because the endpoints were never halted in the first place.

To avoid issuing a redundant Reset Endpoint command, the xHCI driver looks at xhci_virt_ep->stopped_td to determine if the endpoint was actually halted. However, the functions that handle the stall never set that variable to NULL after it dealt with the stall. So if an endpoint stalled and a Reset Endpoint command completed, and then the class driver tried to install a new alternate setting, the xHCI driver would access the old xhci_virt_ep->stopped_td pointer. A similar problem occurs if the endpoint has been stopped to cancel a transfer.

---
 drivers/usb/host/xhci-ring.c |    7 +++++++
 drivers/usb/host/xhci.c      |    2 ++
 2 files changed, 9 insertions(+)
drivers/usb/host/xhci-ring.c +7 -0
@@ -578,6 +578,8 @@ static void handle_stopped_endpoint(stru
 		/* Otherwise just ring the doorbell to restart the ring */
 		ring_ep_doorbell(xhci, slot_id, ep_index);
 	}
+	ep->stopped_td = NULL;
+	ep->stopped_trb = NULL;
 
 	/*
 	 * Drop the lock and complete the URBs in the cancelled TD list.
@@ -1061,8 +1063,13 @@ static void xhci_cleanup_halted_endpoint
 	ep->ep_state |= EP_HALTED;
 	ep->stopped_td = td;
 	ep->stopped_trb = event_trb;
+
 	xhci_queue_reset_ep(xhci, slot_id, ep_index);
 	xhci_cleanup_stalled_ring(xhci, td->urb->dev, ep_index);
+
+	ep->stopped_td = NULL;
+	ep->stopped_trb = NULL;
+
 	xhci_ring_cmd_db(xhci);
 }
 
drivers/usb/host/xhci.c +2 -0
@@ -1438,6 +1438,8 @@ void xhci_endpoint_reset(struct usb_hcd
 		kfree(virt_ep->stopped_td);
 		xhci_ring_cmd_db(xhci);
 	}
+	virt_ep->stopped_td = NULL;
+	virt_ep->stopped_trb = NULL;
 	spin_unlock_irqrestore(&xhci->lock, flags);
 
 	if (ret)
#496 lore raw

PATCH 52/200 USB: xhci: Limit bus sg_tablesize to 62 TRBs.

In reply to Greg KH

2.6.34-stable review patch. If anyone has any objections, please let me know.

------------------

From: Sarah Sharp <[email protected]>

commit bc88d2eba5e19d10dd546e428314909d889b3b6a upstream.

When a scatter-gather list is enqueued to the xHCI driver, it translates each entry into a transfer request block (TRB). Only 63 TRBs can be used per ring segment, and there must be one additional TRB reserved to make sure the hardware does not think the ring is empty (so the enqueue pointer doesn't equal the dequeue pointer). Limit the bus sg_tablesize to 62 TRBs.

---
 drivers/usb/host/xhci-pci.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/usb/host/xhci-pci.c +1 -1
@@ -54,7 +54,7 @@ static int xhci_pci_setup(struct usb_hcd
 	struct pci_dev		*pdev = to_pci_dev(hcd->self.controller);
 	int			retval;
 
-	hcd->self.sg_tablesize = TRBS_PER_SEGMENT - 1;
+	hcd->self.sg_tablesize = TRBS_PER_SEGMENT - 2;
 
 	xhci->cap_regs = hcd->regs;
 	xhci->op_regs = hcd->regs +
#497 lore raw

PATCH 53/200 USB: xhci: Fix check for room on the ring.

In reply to Greg KH

2.6.34-stable review patch. If anyone has any objections, please let me know.

------------------

From: Sarah Sharp <[email protected]>

commit 44ebd037c54f80db3121ac9f5fe6e677b76e11d5 upstream.

The length of the scatter gather list a driver can enqueue is limited by the bus' sg_tablesize to 62 entries. Each entry will be described by at least one transfer request block (TRB). If the entry's buffer crosses a 64KB boundary, then that entry will have to be described by two or more TRBs. So even if the USB device driver respects sg_tablesize, the whole scatter list may take more than 62 TRBs to describe, and won't fit on the ring.

Don't assume that an empty ring means there is enough room on the transfer ring. The old code would unconditionally queue this too-large transfer, and over write the beginning of the transfer. This would mean the cycle bit was unchanged in those overwritten transfers, causing the hardware to think it didn't own the TRBs, and the host would seem to hang.

Now drivers may see submit_urb() fail with -ENOMEM if the transfers are too big to fit on the ring.

---
 drivers/usb/host/xhci-ring.c |   19 ++++++++++++++++++-
 1 file changed, 18 insertions(+), 1 deletion(-)
drivers/usb/host/xhci-ring.c +18 -1
@@ -242,10 +242,27 @@ static int room_on_ring(struct xhci_hcd
 	int i;
 	union xhci_trb *enq = ring->enqueue;
 	struct xhci_segment *enq_seg = ring->enq_seg;
+	struct xhci_segment *cur_seg;
+	unsigned int left_on_ring;
 
 	/* Check if ring is empty */
-	if (enq == ring->dequeue)
+	if (enq == ring->dequeue) {
+		/* Can't use link trbs */
+		left_on_ring = TRBS_PER_SEGMENT - 1;
+		for (cur_seg = enq_seg->next; cur_seg != enq_seg;
+				cur_seg = cur_seg->next)
+			left_on_ring += TRBS_PER_SEGMENT - 1;
+
+		/* Always need one TRB free in the ring. */
+		left_on_ring -= 1;
+		if (num_trbs > left_on_ring) {
+			xhci_warn(xhci, "Not enough room on ring; "
+					"need %u TRBs, %u TRBs left\n",
+					num_trbs, left_on_ring);
+			return 0;
+		}
 		return 1;
+	}
 	/* Make sure there's an extra empty TRB available */
 	for (i = 0; i <= num_trbs; ++i) {
 		if (enq == ring->dequeue)
#498 lore raw

PATCH 54/200 USB: xHCI: Fix wrong usage of macro TRB_TYPE

In reply to Greg KH

2.6.34-stable review patch. If anyone has any objections, please let me know.

------------------

From: Andiry Xu <[email protected]>

commit 54b5acf3acb7a1f83ec281d111d3e2812cd7ad9d upstream.

Macro TRB_TYPE is misused in some places. Fix the wrong usage.

---
 drivers/usb/host/xhci-ring.c |   11 +++++++----
 1 file changed, 7 insertions(+), 4 deletions(-)
drivers/usb/host/xhci-ring.c +7 -4
@@ -351,7 +351,8 @@ static struct xhci_segment *find_trb_seg
 	while (cur_seg->trbs > trb ||
 			&cur_seg->trbs[TRBS_PER_SEGMENT - 1] < trb) {
 		generic_trb = &cur_seg->trbs[TRBS_PER_SEGMENT - 1].generic;
-		if (TRB_TYPE(generic_trb->field[3]) == TRB_LINK &&
+		if ((generic_trb->field[3] & TRB_TYPE_BITMASK) ==
+				TRB_TYPE(TRB_LINK) &&
 				(generic_trb->field[3] & LINK_TOGGLE))
 			*cycle_state = ~(*cycle_state) & 0x1;
 		cur_seg = cur_seg->next;
@@ -407,7 +408,7 @@ void xhci_find_new_dequeue_state(struct
 		BUG();
 
 	trb = &state->new_deq_ptr->generic;
-	if (TRB_TYPE(trb->field[3]) == TRB_LINK &&
+	if ((trb->field[3] & TRB_TYPE_BITMASK) == TRB_TYPE(TRB_LINK) &&
 				(trb->field[3] & LINK_TOGGLE))
 		state->new_cycle_state = ~(state->new_cycle_state) & 0x1;
 	next_trb(xhci, ep_ring, &state->new_deq_seg, &state->new_deq_ptr);
@@ -1414,8 +1415,10 @@ static int handle_tx_event(struct xhci_h
 			for (cur_trb = ep_ring->dequeue, cur_seg = ep_ring->deq_seg;
 					cur_trb != event_trb;
 					next_trb(xhci, ep_ring, &cur_seg, &cur_trb)) {
-				if (TRB_TYPE(cur_trb->generic.field[3]) != TRB_TR_NOOP &&
-						TRB_TYPE(cur_trb->generic.field[3]) != TRB_LINK)
+				if ((cur_trb->generic.field[3] &
+				 TRB_TYPE_BITMASK) != TRB_TYPE(TRB_TR_NOOP) &&
+				    (cur_trb->generic.field[3] &
+				 TRB_TYPE_BITMASK) != TRB_TYPE(TRB_LINK))
 					td->urb->actual_length +=
 						TRB_LEN(cur_trb->generic.field[2]);
 			}
#499 lore raw

PATCH 55/200 ath5k: consistently use rx_bufsize for RX DMA

In reply to Greg KH

2.6.34-stable review patch. If anyone has any objections, please let me know.

------------------

From: Bruno Randolf <[email protected]>

commit b5eae9ff5ba6d76de19286dd6429acd7cde3f79d upstream.

We should use the same buffer size we set up for DMA also in the hardware descriptor. Previously we used common->rx_bufsize for setting up the DMA mapping, but used skb_tailroom(skb) for the size we tell to the hardware in the descriptor itself. The problem is that skb_tailroom(skb) can give us a larger value than the size we set up for DMA before. This allows the hardware to write into memory locations not set up for DMA. In practice this should rarely happen because all packets should be smaller than the maximum 802.11 packet size.

On the tested platform rx_bufsize is 2528, and we allocated an skb of 2559 bytes length (including padding for cache alignment) but sbk_tailroom() was 2592. Just consistently use rx_bufsize for all RX DMA memory sizes.

Also use the return value of the descriptor setup function.

---
 drivers/net/wireless/ath/ath5k/base.c |    7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)
drivers/net/wireless/ath/ath5k/base.c +4 -3
@@ -1211,6 +1211,7 @@ ath5k_rxbuf_setup(struct ath5k_softc *sc
 	struct ath5k_hw *ah = sc->ah;
 	struct sk_buff *skb = bf->skb;
 	struct ath5k_desc *ds;
+	int ret;
 
 	if (!skb) {
 		skb = ath5k_rx_skb_alloc(sc, &bf->skbaddr);
@@ -1237,9 +1238,9 @@ ath5k_rxbuf_setup(struct ath5k_softc *sc
 	ds = bf->desc;
 	ds->ds_link = bf->daddr;	/* link to self */
 	ds->ds_data = bf->skbaddr;
-	ah->ah_setup_rx_desc(ah, ds,
-		skb_tailroom(skb),	/* buffer size */
-		0);
+	ret = ah->ah_setup_rx_desc(ah, ds, ah->common.rx_bufsize, 0);
+	if (ret)
+		return ret;
 
 	if (sc->rxlink != NULL)
 		*sc->rxlink = bf->daddr;
#500 lore raw

PATCH 56/200 fbdev: section cleanup in hgafb

In reply to Greg KH

2.6.34-stable review patch. If anyone has any objections, please let me know.

------------------

From: Henrik Kretzschmar <[email protected]>

commit e217e6e39f62e47f7e659b715235dbd57df480f8 upstream.

Fix up the sections in the hgafb driver, by

* moving hga_default_var and hga_fix from .init.data to .devinit.data

* moving hga_detect() from .init.text to .devinit.text

* moving hga_fb_remove() from .text to .devexit.text

This fixes the following warnings issued by modpost:

WARNING: drivers/video/hgafb.o(.devinit.text+0x18): Section mismatch in referenc e from the function hgafb_probe() to the function .init.text:hga_card_detect() The function __devinit hgafb_probe() references
a function __init hga_card_detect().
If hga_card_detect is only used by hgafb_probe then
annotate hga_card_detect with a matching annotation.

WARNING: drivers/video/hgafb.o(.devinit.text+0xfe): Section mismatch in referenc e from the function hgafb_probe() to the variable .init.data:hga_fix The function __devinit hgafb_probe() references
a variable __initdata hga_fix.
If hga_fix is only used by hgafb_probe then
annotate hga_fix with a matching annotation.

WARNING: drivers/video/hgafb.o(.devinit.text+0x105): Section mismatch in reference from the function hgafb_probe() to the variable .init.data:hga_default_var The function __devinit hgafb_probe() references
a variable __initdata hga_default_var.
If hga_default_var is only used by hgafb_probe then
annotate hga_default_var with a matching annotation.

---
 drivers/video/hgafb.c |   10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)
drivers/video/hgafb.c +5 -5
@@ -106,7 +106,7 @@ static DEFINE_SPINLOCK(hga_reg_lock);
 
 /* Framebuffer driver structures */
 
-static struct fb_var_screeninfo __initdata hga_default_var = {
+static struct fb_var_screeninfo hga_default_var __devinitdata = {
 	.xres		= 720,
 	.yres 		= 348,
 	.xres_virtual 	= 720,
@@ -120,7 +120,7 @@ static struct fb_var_screeninfo __initda
 	.width 		= -1,
 };
 
-static struct fb_fix_screeninfo __initdata hga_fix = {
+static struct fb_fix_screeninfo hga_fix __devinitdata = {
 	.id 		= "HGA",
 	.type 		= FB_TYPE_PACKED_PIXELS,	/* (not sure) */
 	.visual 	= FB_VISUAL_MONO10,
@@ -276,7 +276,7 @@ static void hga_blank(int blank_mode)
 	spin_unlock_irqrestore(&hga_reg_lock, flags);
 }
 
-static int __init hga_card_detect(void)
+static int __devinit hga_card_detect(void)
 {
 	int count = 0;
 	void __iomem *p, *q;
@@ -596,7 +596,7 @@ static int __devinit hgafb_probe(struct
 	return 0;
 }
 
-static int hgafb_remove(struct platform_device *pdev)
+static int __devexit hgafb_remove(struct platform_device *pdev)
 {
 	struct fb_info *info = platform_get_drvdata(pdev);
 
@@ -621,7 +621,7 @@ static int hgafb_remove(struct platform_
 
 static struct platform_driver hgafb_driver = {
 	.probe = hgafb_probe,
-	.remove = hgafb_remove,
+	.remove = __devexit_p(hgafb_remove),
 	.driver = {
 		.name = "hgafb",
 	},
#501 lore raw

PATCH 57/200 fbdev: section cleanup in vfb

In reply to Greg KH

2.6.34-stable review patch. If anyone has any objections, please let me know.

------------------

From: Henrik Kretzschmar <[email protected]>

commit 3cc04971661e37e7de6fbf9808ede554b5e1cb4e upstream.

Fix up the section in the vfb driver, by moving the variables vfb_default and vfb_fix from .init.data to .devinit.data

This fixes the following warnings issued by modpost:

WARNING: drivers/video/vfb.o(.devinit.text+0xf8): Section mismatch in reference from the function vfb_probe() to the variable .init.data:vfb_default The function __devinit vfb_probe() references
a variable __initdata vfb_default.
If vfb_default is only used by vfb_probe then
annotate vfb_default with a matching annotation.

WARNING: drivers/video/vfb.o(.devinit.text+0x114): Section mismatch in reference from the function vfb_probe() to the variable .init.data:vfb_fix The function __devinit vfb_probe() references
a variable __initdata vfb_fix.
If vfb_fix is only used by vfb_probe then
annotate vfb_fix with a matching annotation.

---
 drivers/video/vfb.c |    4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/video/vfb.c +2 -2
@@ -78,7 +78,7 @@ static void rvfree(void *mem, unsigned l
 	vfree(mem);
 }
 
-static struct fb_var_screeninfo vfb_default __initdata = {
+static struct fb_var_screeninfo vfb_default __devinitdata = {
 	.xres =		640,
 	.yres =		480,
 	.xres_virtual =	640,
@@ -100,7 +100,7 @@ static struct fb_var_screeninfo vfb_defa
       	.vmode =	FB_VMODE_NONINTERLACED,
 };
 
-static struct fb_fix_screeninfo vfb_fix __initdata = {
+static struct fb_fix_screeninfo vfb_fix __devinitdata = {
 	.id =		"Virtual FB",
 	.type =		FB_TYPE_PACKED_PIXELS,
 	.visual =	FB_VISUAL_PSEUDOCOLOR,
#502 lore raw

PATCH 58/200 fbdev: section cleanup in vga16fb

In reply to Greg KH

2.6.34-stable review patch. If anyone has any objections, please let me know.

------------------

From: Henrik Kretzschmar <[email protected]>

commit ad1458464cbbe6935be6e20d70920301733158af upstream.

Fix up the sections in the vga16fb driver, by moving:

* the variables vga16_defined and vga16fb
from .init.data to .devinit.data

* vga16fb_setup() from .text to .init.text

* vga16fb_remove() from .text. to .devexit.text

This fixes the following warnings issued by modpost:

WARNING: drivers/video/built-in.o(.devinit.text+0x1a420): Section mismatch in re ference from the function vga16fb_probe() to the (unknown reference) .init.data:
(unknown)
The function __devinit vga16fb_probe() references
a (unknown reference) __initdata (unknown).
If (unknown) is only used by vga16fb_probe then
annotate (unknown) with a matching annotation.

WARNING: drivers/video/built-in.o(.devinit.text+0x1a437): Section mismatch in reference from the function vga16fb_probe() to the variable .init.data:vga16fb_defined The function __devinit vga16fb_probe() references
a variable __initdata vga16fb_defined.
If vga16fb_defined is only used by vga16fb_probe then
annotate vga16fb_defined with a matching annotation.

WARNING: drivers/video/built-in.o(.devinit.text+0x1a457): Section mismatch in reference from the function vga16fb_probe() to the variable .init.data:vga16fb_fix The function __devinit vga16fb_probe() references
a variable __initdata vga16fb_fix.
If vga16fb_fix is only used by vga16fb_probe then
annotate vga16fb_fix with a matching annotation.

---
 drivers/video/vga16fb.c |   10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)
drivers/video/vga16fb.c +5 -5
@@ -65,7 +65,7 @@ struct vga16fb_par {
 
 /* --------------------------------------------------------------------- */
 
-static struct fb_var_screeninfo vga16fb_defined __initdata = {
+static struct fb_var_screeninfo vga16fb_defined __devinitdata = {
 	.xres		= 640,
 	.yres		= 480,
 	.xres_virtual	= 640,
@@ -85,7 +85,7 @@ static struct fb_var_screeninfo vga16fb_
 };
 
 /* name should not depend on EGA/VGA */
-static struct fb_fix_screeninfo vga16fb_fix __initdata = {
+static struct fb_fix_screeninfo vga16fb_fix __devinitdata = {
 	.id		= "VGA16 VGA",
 	.smem_start	= VGA_FB_PHYS,
 	.smem_len	= VGA_FB_PHYS_LEN,
@@ -1278,7 +1278,7 @@ static struct fb_ops vga16fb_ops = {
 };
 
 #ifndef MODULE
-static int vga16fb_setup(char *options)
+static int __init vga16fb_setup(char *options)
 {
 	char *this_opt;
 	
@@ -1376,7 +1376,7 @@ static int __devinit vga16fb_probe(struc
 	return ret;
 }
 
-static int vga16fb_remove(struct platform_device *dev)
+static int __devexit vga16fb_remove(struct platform_device *dev)
 {
 	struct fb_info *info = platform_get_drvdata(dev);
 
@@ -1393,7 +1393,7 @@ static int vga16fb_remove(struct platfor
 
 static struct platform_driver vga16fb_driver = {
 	.probe = vga16fb_probe,
-	.remove = vga16fb_remove,
+	.remove = __devexit_p(vga16fb_remove),
 	.driver = {
 		.name = "vga16fb",
 	},
#503 lore raw

PATCH 59/200 fbdev: section cleanup in arcfb

In reply to Greg KH

2.6.34-stable review patch. If anyone has any objections, please let me know.

------------------

From: Henrik Kretzschmar <[email protected]>

commit bd9b5caf8616501d2ab6f17210b11f81ea7546eb upstream.

Fix the sections in the arcfb driver, by moving:

* the variables arcfb_fix and arcfb_var from .init.data to .devinit.data

* arcfb_remove() from .text to .devexit.text

This fixes the following warnings issued by modpost:

WARNING: drivers/video/built-in.o(.devinit.text+0x543): Section mismatch in reference from the function arcfb_probe() to the variable .init.data:arcfb_var The function __devinit arcfb_probe() references
a variable __initdata arcfb_var.
If arcfb_var is only used by arcfb_probe then
annotate arcfb_var with a matching annotation.

WARNING: drivers/video/built-in.o(.devinit.text+0x558): Section mismatch in reference from the function arcfb_probe() to the variable .init.data:arcfb_fix The function __devinit arcfb_probe() references
a variable __initdata arcfb_fix.
If arcfb_fix is only used by arcfb_probe then
annotate arcfb_fix with a matching annotation.

---
 drivers/video/arcfb.c |    8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)
drivers/video/arcfb.c +4 -4
@@ -80,7 +80,7 @@ struct arcfb_par {
 	spinlock_t lock;
 };
 
-static struct fb_fix_screeninfo arcfb_fix __initdata = {
+static struct fb_fix_screeninfo arcfb_fix __devinitdata = {
 	.id =		"arcfb",
 	.type =		FB_TYPE_PACKED_PIXELS,
 	.visual =	FB_VISUAL_MONO01,
@@ -90,7 +90,7 @@ static struct fb_fix_screeninfo arcfb_fi
 	.accel =	FB_ACCEL_NONE,
 };
 
-static struct fb_var_screeninfo arcfb_var __initdata = {
+static struct fb_var_screeninfo arcfb_var __devinitdata = {
 	.xres		= 128,
 	.yres		= 64,
 	.xres_virtual	= 128,
@@ -588,7 +588,7 @@ err:
 	return retval;
 }
 
-static int arcfb_remove(struct platform_device *dev)
+static int __devexit arcfb_remove(struct platform_device *dev)
 {
 	struct fb_info *info = platform_get_drvdata(dev);
 
@@ -602,7 +602,7 @@ static int arcfb_remove(struct platform_
 
 static struct platform_driver arcfb_driver = {
 	.probe	= arcfb_probe,
-	.remove = arcfb_remove,
+	.remove = __devexit_p(arcfb_remove),
 	.driver	= {
 		.name	= "arcfb",
 	},
#504 lore raw

PATCH 60/200 fbdev: section cleanup in w100fb

In reply to Greg KH

2.6.34-stable review patch. If anyone has any objections, please let me know.

------------------

From: Henrik Kretzschmar <[email protected]>

commit fb6cb3270af8f2ad3dd556906a9c52aa85754849 upstream.

Fix up the section in the w100fb driver, by moving:

* w100fb_remove() from .text to .devexit.text

* w100_get_xtal_table() from .text to .devinit.text

* w100fb_init() from .devinit.text to .init.text

---
 drivers/video/w100fb.c |   10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)
drivers/video/w100fb.c +5 -5
@@ -53,7 +53,7 @@ static void w100_update_enable(void);
 static void w100_update_disable(void);
 static void calc_hsync(struct w100fb_par *par);
 static void w100_init_graphic_engine(struct w100fb_par *par);
-struct w100_pll_info *w100_get_xtal_table(unsigned int freq);
+struct w100_pll_info *w100_get_xtal_table(unsigned int freq) __devinit;
 
 /* Pseudo palette size */
 #define MAX_PALETTES      16
@@ -782,7 +782,7 @@ out:
 }
 
 
-static int w100fb_remove(struct platform_device *pdev)
+static int __devexit w100fb_remove(struct platform_device *pdev)
 {
 	struct fb_info *info = platform_get_drvdata(pdev);
 	struct w100fb_par *par=info->par;
@@ -1020,7 +1020,7 @@ static struct pll_entries {
 	{ 0 },
 };
 
-struct w100_pll_info *w100_get_xtal_table(unsigned int freq)
+struct w100_pll_info __devinit *w100_get_xtal_table(unsigned int freq)
 {
 	struct pll_entries *pll_entry = w100_pll_tables;
 
@@ -1611,7 +1611,7 @@ static void w100_vsync(void)
 
 static struct platform_driver w100fb_driver = {
 	.probe		= w100fb_probe,
-	.remove		= w100fb_remove,
+	.remove		= __devexit_p(w100fb_remove),
 	.suspend	= w100fb_suspend,
 	.resume		= w100fb_resume,
 	.driver		= {
@@ -1619,7 +1619,7 @@ static struct platform_driver w100fb_dri
 	},
 };
 
-int __devinit w100fb_init(void)
+int __init w100fb_init(void)
 {
 	return platform_driver_register(&w100fb_driver);
 }
#505 lore raw

PATCH 61/200 mac80211: give warning if building w/out rate ctrl algorithm

In reply to Greg KH

2.6.34-stable review patch. If anyone has any objections, please let me know.

------------------

From: Andres Salomon <[email protected]>

commit c2ef355bf3ef0b8006b96128726684fba47ac928 upstream.

I discovered that if EMBEDDED=y, one can accidentally build a mac80211 stack and drivers w/ no rate control algorithm. For drivers like RTL8187 that don't supply their own RC algorithms, this will cause ieee80211_register_hw to fail (making the driver unusable).

This will tell kconfig to provide a warning if no rate control algorithms have been selected. That'll at least warn the user; users that know that their drivers supply a rate control algorithm can safely ignore the warning, and those who don't know (or who expect to be using multiple drivers) can select a default RC algorithm.

---
 net/mac80211/Kconfig |    9 +++++++++
 1 file changed, 9 insertions(+)
net/mac80211/Kconfig +9 -0
@@ -15,8 +15,12 @@ comment "CFG80211 needs to be enabled fo
 
 if MAC80211 != n
 
+config MAC80211_HAS_RC
+	def_bool n
+
 config MAC80211_RC_PID
 	bool "PID controller based rate control algorithm" if EMBEDDED
+	select MAC80211_HAS_RC
 	---help---
 	  This option enables a TX rate control algorithm for
 	  mac80211 that uses a PID controller to select the TX
@@ -24,12 +28,14 @@ config MAC80211_RC_PID
 
 config MAC80211_RC_MINSTREL
 	bool "Minstrel" if EMBEDDED
+	select MAC80211_HAS_RC
 	default y
 	---help---
 	  This option enables the 'minstrel' TX rate control algorithm
 
 choice
 	prompt "Default rate control algorithm"
+	depends on MAC80211_HAS_RC
 	default MAC80211_RC_DEFAULT_MINSTREL
 	---help---
 	  This option selects the default rate control algorithm
@@ -62,6 +68,9 @@ config MAC80211_RC_DEFAULT
 
 endif
 
+comment "Some wireless drivers require a rate control algorithm"
+	depends on MAC80211_HAS_RC=n
+
 config MAC80211_MESH
 	bool "Enable mac80211 mesh networking (pre-802.11s) support"
 	depends on MAC80211 && EXPERIMENTAL
#506 lore raw

PATCH 62/200 mac80211: Fix robust management frame handling (MFP)

In reply to Greg KH

2.6.34-stable review patch. If anyone has any objections, please let me know.

------------------

From: Jouni Malinen <[email protected]>

commit d211e90e28a074447584729018a39910d691d1a8 upstream.

Commit e34e09401ee9888dd662b2fca5d607794a56daf2 incorrectly removed use of ieee80211_has_protected() from the management frame case and in practice, made this validation drop all Action frames when MFP is enabled. This should have only been done for frames with Protected field set to zero.

---
 net/mac80211/rx.c |    3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)
net/mac80211/rx.c +2 -1
@@ -1414,7 +1414,8 @@ ieee80211_drop_unencrypted_mgmt(struct i
 		return res;
 
 	if (rx->sta && test_sta_flags(rx->sta, WLAN_STA_MFP)) {
-		if (unlikely(ieee80211_is_unicast_robust_mgmt_frame(rx->skb) &&
+		if (unlikely(!ieee80211_has_protected(fc) &&
+			     ieee80211_is_unicast_robust_mgmt_frame(rx->skb) &&
 			     rx->key))
 			return -EACCES;
 		/* BIP does not use Protected field, so need to check MMIE */
#507 lore raw

PATCH 63/200 mac80211: fix rts threshold check

In reply to Greg KH

2.6.34-stable review patch. If anyone has any objections, please let me know.

------------------

From: Shanyu Zhao <[email protected]>

commit a2c40249a36d0b4d76d1caf6bf806e4ae5b06e8a upstream.

Currently whenever rts thresold is set, every packet will use RTS protection no matter its size exceeds the threshold or not. This is due to a bug in the rts threshold check.

	if (len > tx->local->hw.wiphy->rts_threshold) {
		txrc.rts = rts = true;
	}
Basically it is comparing an int (len) and a u32 (rts_threshold),
and the variable len is assigned as:
	len = min_t(int, tx->skb->len + FCS_LEN,
			 tx->local->hw.wiphy->frag_threshold);

However, when frag_threshold is "-1", len is always "-1", which is 0xffffffff therefore rts is always set to true.

---
 net/mac80211/tx.c |    5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)
net/mac80211/tx.c +3 -2
@@ -584,7 +584,8 @@ ieee80211_tx_h_rate_ctrl(struct ieee8021
 	struct ieee80211_hdr *hdr = (void *)tx->skb->data;
 	struct ieee80211_supported_band *sband;
 	struct ieee80211_rate *rate;
-	int i, len;
+	int i;
+	u32 len;
 	bool inval = false, rts = false, short_preamble = false;
 	struct ieee80211_tx_rate_control txrc;
 	u32 sta_flags;
@@ -593,7 +594,7 @@ ieee80211_tx_h_rate_ctrl(struct ieee8021
 
 	sband = tx->local->hw.wiphy->bands[tx->channel->band];
 
-	len = min_t(int, tx->skb->len + FCS_LEN,
+	len = min_t(u32, tx->skb->len + FCS_LEN,
 			 tx->local->hw.wiphy->frag_threshold);
 
 	/* set up the tx rate control struct we give the RC algo */
#508 lore raw

PATCH 64/200 mac80211: fix handling of 4-address-mode in ieee80211_change_iface

In reply to Greg KH

2.6.34-stable review patch. If anyone has any objections, please let me know.

------------------

From: Felix Fietkau <[email protected]>

commit f7917af92024d43bc20bc1afc92de27b0bd0f50b upstream.

A misplaced interface type check bails out too early if the interface is not in monitor mode. This patch moves it to the right place, so that it only covers changes to the monitor flags.

---
 net/mac80211/cfg.c |    7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)
net/mac80211/cfg.c +3 -4
@@ -97,9 +97,6 @@ static int ieee80211_change_iface(struct
 					    params->mesh_id_len,
 					    params->mesh_id);
 
-	if (sdata->vif.type != NL80211_IFTYPE_MONITOR || !flags)
-		return 0;
-
 	if (type == NL80211_IFTYPE_AP_VLAN &&
 	    params && params->use_4addr == 0)
 		rcu_assign_pointer(sdata->u.vlan.sta, NULL);
@@ -107,7 +104,9 @@ static int ieee80211_change_iface(struct
 		 params && params->use_4addr >= 0)
 		sdata->u.mgd.use_4addr = params->use_4addr;
 
-	sdata->u.mntr_flags = *flags;
+	if (sdata->vif.type == NL80211_IFTYPE_MONITOR && flags)
+		sdata->u.mntr_flags = *flags;
+
 	return 0;
 }
 
#509 lore raw

PATCH 65/200 ath9k_hw: fix hardware deinit

In reply to Greg KH

2.6.34-stable review patch. If anyone has any objections, please let me know.

------------------

From: Sujith <[email protected]>

commit 736b3a27b3c50c4a23717b802240435a69e8d0ff upstream.

Without this you will get a panic if the device initialization fails. Also, free ath_hw instance properly. ath9k_hw_deinit() shouldn't do it.

---
 drivers/net/wireless/ath/ath9k/hw.c   |    4 +---
 drivers/net/wireless/ath/ath9k/init.c |    3 +++
 2 files changed, 4 insertions(+), 3 deletions(-)
drivers/net/wireless/ath/ath9k/hw.c +1 -3
@@ -1241,7 +1241,7 @@ void ath9k_hw_deinit(struct ath_hw *ah)
 {
 	struct ath_common *common = ath9k_hw_common(ah);
 
-	if (common->state <= ATH_HW_INITIALIZED)
+	if (common->state < ATH_HW_INITIALIZED)
 		goto free_hw;
 
 	if (!AR_SREV_9100(ah))
@@ -1252,8 +1252,6 @@ void ath9k_hw_deinit(struct ath_hw *ah)
 free_hw:
 	if (!AR_SREV_9280_10_OR_LATER(ah))
 		ath9k_hw_rf_free_ext_banks(ah);
-	kfree(ah);
-	ah = NULL;
 }
 EXPORT_SYMBOL(ath9k_hw_deinit);
 
drivers/net/wireless/ath/ath9k/init.c +3 -0
@@ -760,6 +760,9 @@ static void ath9k_deinit_softc(struct at
 
 	tasklet_kill(&sc->intr_tq);
 	tasklet_kill(&sc->bcon_tasklet);
+
+	kfree(sc->sc_ah);
+	sc->sc_ah = NULL;
 }
 
 void ath9k_deinit_device(struct ath_softc *sc)
#510 lore raw

PATCH 66/200 drm/i915: Reject bind_to_gtt() early if object > aperture

In reply to Greg KH

2.6.34-stable review patch. If anyone has any objections, please let me know.

------------------

From: Chris Wilson <[email protected]>

commit 654fc6073f68efa3b6c466825749e73e7fbb92cd upstream.

If the object is bigger than the entire aperture, reject it early before evicting everything in a vain attempt to find space.

v2: Use E2BIG as suggested by Owain G. Ainsworth.

---
 drivers/gpu/drm/i915/i915_gem.c |    8 ++++++++
 1 file changed, 8 insertions(+)
drivers/gpu/drm/i915/i915_gem.c +8 -0
@@ -2688,6 +2688,14 @@ i915_gem_object_bind_to_gtt(struct drm_g
 		return -EINVAL;
 	}
 
+	/* If the object is bigger than the entire aperture, reject it early
+	 * before evicting everything in a vain attempt to find space.
+	 */
+	if (obj->size > dev->gtt_total) {
+		DRM_ERROR("Attempting to bind an object larger than the aperture\n");
+		return -E2BIG;
+	}
+
  search_free:
 	free_space = drm_mm_search_free(&dev_priv->mm.gtt_space,
 					obj->size, alignment, 0);
#511 lore raw

PATCH 67/200 libsas: fix deref before check in commit 70b25f890ce

In reply to Greg KH

2.6.34-stable review patch. If anyone has any objections, please let me know.

------------------

From: James Bottomley <[email protected]>

commit 1b4d0d8ea7b3cbd107f345ab766416f9b38ce66a upstream.

commit 70b25f890ce9f0520c64075ce9225a5b020a513e

Author: Tejun Heo <[email protected]>
Date:   Thu Apr 15 09:00:08 2010 +0900

[SCSI] fix locking around blk_abort_request()

Introduced a reference before check problem, fix this by moving the lock shorthand code to be right at the point of actual use.

---
 drivers/scsi/libsas/sas_ata.c       |    5 +++--
 drivers/scsi/libsas/sas_scsi_host.c |   16 ++++++++--------
 2 files changed, 11 insertions(+), 10 deletions(-)
drivers/scsi/libsas/sas_ata.c +3 -2
@@ -395,12 +395,13 @@ int sas_ata_init_host_and_port(struct do
 void sas_ata_task_abort(struct sas_task *task)
 {
 	struct ata_queued_cmd *qc = task->uldd_task;
-	struct request_queue *q = qc->scsicmd->device->request_queue;
 	struct completion *waiting;
-	unsigned long flags;
 
 	/* Bounce SCSI-initiated commands to the SCSI EH */
 	if (qc->scsicmd) {
+		struct request_queue *q = qc->scsicmd->device->request_queue;
+		unsigned long flags;
+
 		spin_lock_irqsave(q->queue_lock, flags);
 		blk_abort_request(qc->scsicmd->request);
 		spin_unlock_irqrestore(q->queue_lock, flags);
drivers/scsi/libsas/sas_scsi_host.c +8 -8
@@ -1030,8 +1030,6 @@ int __sas_task_abort(struct sas_task *ta
 void sas_task_abort(struct sas_task *task)
 {
 	struct scsi_cmnd *sc = task->uldd_task;
-	struct request_queue *q = sc->device->request_queue;
-	unsigned long flags;
 
 	/* Escape for libsas internal commands */
 	if (!sc) {
@@ -1043,13 +1041,15 @@ void sas_task_abort(struct sas_task *tas
 
 	if (dev_is_sata(task->dev)) {
 		sas_ata_task_abort(task);
-		return;
-	}
+	} else {
+		struct request_queue *q = sc->device->request_queue;
+		unsigned long flags;
 
-	spin_lock_irqsave(q->queue_lock, flags);
-	blk_abort_request(sc->request);
-	spin_unlock_irqrestore(q->queue_lock, flags);
-	scsi_schedule_eh(sc->device->host);
+		spin_lock_irqsave(q->queue_lock, flags);
+		blk_abort_request(sc->request);
+		spin_unlock_irqrestore(q->queue_lock, flags);
+		scsi_schedule_eh(sc->device->host);
+	}
 }
 
 int sas_slave_alloc(struct scsi_device *scsi_dev)
#512 lore raw

PATCH 68/200 drivers/base/cpu.c: fix the output from /sys/devices/system/cpu/offline

In reply to Greg KH

2.6.34-stable review patch. If anyone has any objections, please let me know.

------------------

From: Jan Beulich <[email protected]>

commit cdc6e3d3968052cebb2f2ddcd742bff29fbd1a90 upstream.

Without CONFIG_CPUMASK_OFFSTACK, simply inverting cpu_online_mask leads to CPUs beyond nr_cpu_ids to be displayed twice and CPUs not even possible to be displayed as offline.

---
 drivers/base/cpu.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/base/cpu.c +1 -1
@@ -186,7 +186,7 @@ static ssize_t print_cpus_offline(struct
 	/* display offline cpus < nr_cpu_ids */
 	if (!alloc_cpumask_var(&offline, GFP_KERNEL))
 		return -ENOMEM;
-	cpumask_complement(offline, cpu_online_mask);
+	cpumask_andnot(offline, cpu_possible_mask, cpu_online_mask);
 	n = cpulist_scnprintf(buf, len, offline);
 	free_cpumask_var(offline);
 
#513 lore raw

PATCH 69/200 can: Fix SJA1000 command register writes on SMP systems

In reply to Greg KH

2.6.34-stable review patch. If anyone has any objections, please let me know.

------------------

From: Oliver Hartkopp <[email protected]>

commit 57c8a456640fa3ca777652f11f2db4179a3e66b6 upstream.

The SJA1000 command register is concurrently written in the rx-path to free the receive buffer _and_ in the tx-path to start the transmission.

The SJA1000 data sheet, 6.4.4 COMMAND REGISTER (CMR) states:
"Between two commands at least one internal clock cycle is needed in order to proceed. The internal clock is half of the external oscillator frequency."

On SMP systems the current implementation leads to a write stall in the tx-path, which can be solved by adding some general locking and some time to settle the write_reg() operation for the command register.

Thanks to Klaus Hitschler for the original fix and detailed problem description.

This patch applies on net-2.6 and (with some offsets) on net-next-2.6 .

---
 drivers/net/can/sja1000/sja1000.c |   20 +++++++++++++++++---
 drivers/net/can/sja1000/sja1000.h |    1 +
 2 files changed, 18 insertions(+), 3 deletions(-)
drivers/net/can/sja1000/sja1000.c +17 -3
@@ -84,6 +84,20 @@ static struct can_bittiming_const sja100
 	.brp_inc = 1,
 };
 
+static void sja1000_write_cmdreg(struct sja1000_priv *priv, u8 val)
+{
+	unsigned long flags;
+
+	/*
+	 * The command register needs some locking and time to settle
+	 * the write_reg() operation - especially on SMP systems.
+	 */
+	spin_lock_irqsave(&priv->cmdreg_lock, flags);
+	priv->write_reg(priv, REG_CMR, val);
+	priv->read_reg(priv, REG_SR);
+	spin_unlock_irqrestore(&priv->cmdreg_lock, flags);
+}
+
 static int sja1000_probe_chip(struct net_device *dev)
 {
 	struct sja1000_priv *priv = netdev_priv(dev);
@@ -297,7 +311,7 @@ static netdev_tx_t sja1000_start_xmit(st
 
 	can_put_echo_skb(skb, dev, 0);
 
-	priv->write_reg(priv, REG_CMR, CMD_TR);
+	sja1000_write_cmdreg(priv, CMD_TR);
 
 	return NETDEV_TX_OK;
 }
@@ -346,7 +360,7 @@ static void sja1000_rx(struct net_device
 	cf->can_id = id;
 
 	/* release receive buffer */
-	priv->write_reg(priv, REG_CMR, CMD_RRB);
+	sja1000_write_cmdreg(priv, CMD_RRB);
 
 	netif_rx(skb);
 
@@ -374,7 +388,7 @@ static int sja1000_err(struct net_device
 		cf->data[1] = CAN_ERR_CRTL_RX_OVERFLOW;
 		stats->rx_over_errors++;
 		stats->rx_errors++;
-		priv->write_reg(priv, REG_CMR, CMD_CDO);	/* clear bit */
+		sja1000_write_cmdreg(priv, CMD_CDO);	/* clear bit */
 	}
 
 	if (isrc & IRQ_EI) {
drivers/net/can/sja1000/sja1000.h +1 -0
@@ -167,6 +167,7 @@ struct sja1000_priv {
 
 	void __iomem *reg_base;	 /* ioremap'ed address to registers */
 	unsigned long irq_flags; /* for request_irq() */
+	spinlock_t cmdreg_lock;  /* lock for concurrent cmd register writes */
 
 	u16 flags;		/* custom mode flags */
 	u8 ocr;			/* output control register */
#514 lore raw

PATCH 70/200 PCI quirks: disable msi on AMD rs4xx internal gfx bridges

In reply to Greg KH

2.6.34-stable review patch. If anyone has any objections, please let me know.

------------------

From: Alex Deucher <[email protected]>

commit 9313ff450400e6a2ab10fe6b9bdb12a828329410 upstream.

Doesn't work reliably for internal gfx. Fixes kernel bug
https://bugzilla.kernel.org/show_bug.cgi?id=15626.

---
 drivers/pci/quirks.c |    1 +
 1 file changed, 1 insertion(+)
drivers/pci/quirks.c +1 -0
@@ -2127,6 +2127,7 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AM
 DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ASUSTEK, 0x9602, quirk_disable_msi);
 DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AI, 0x9602, quirk_disable_msi);
 DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, 0xa238, quirk_disable_msi);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x5a3f, quirk_disable_msi);
 
 /* Go through the list of Hypertransport capabilities and
  * return 1 if a HT MSI capability is found and enabled */
#515 lore raw

PATCH 71/200 PCI: Disable MSI for MCP55 on P5N32-E SLI

In reply to Greg KH

2.6.34-stable review patch. If anyone has any objections, please let me know.

------------------

From: Ben Hutchings <[email protected]>

commit e4146bb9088c01c8b6e82be11f0c371f8aff023c upstream.

As reported in <http://bugs.debian.org/552299>, MSI appears to be broken for this on-board device. We already have a quirk for the P5N32-SLI Premium; extend it to cover both variants of the board.

---
 drivers/pci/quirks.c |    7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)
drivers/pci/quirks.c +4 -3
@@ -2219,15 +2219,16 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_S
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8132_BRIDGE,
 			 ht_enable_msi_mapping);
 
-/* The P5N32-SLI Premium motherboard from Asus has a problem with msi
+/* The P5N32-SLI motherboards from Asus have a problem with msi
  * for the MCP55 NIC. It is not yet determined whether the msi problem
  * also affects other devices. As for now, turn off msi for this device.
  */
 static void __devinit nvenet_msi_disable(struct pci_dev *dev)
 {
-	if (dmi_name_in_vendors("P5N32-SLI PREMIUM")) {
+	if (dmi_name_in_vendors("P5N32-SLI PREMIUM") ||
+	    dmi_name_in_vendors("P5N32-E SLI")) {
 		dev_info(&dev->dev,
-			 "Disabling msi for MCP55 NIC on P5N32-SLI Premium\n");
+			 "Disabling msi for MCP55 NIC on P5N32-SLI\n");
 		dev->no_msi = 1;
 	}
 }
#516 lore raw

PATCH 72/200 drm/radeon/kms: dont default display priority to high on rs4xx

In reply to Greg KH

2.6.34-stable review patch. If anyone has any objections, please let me know.

------------------

From: Alex Deucher <[email protected]>

commit 45737447ed160faaba036c0709226bf9057f7b72 upstream.

Seems to cause issues with the sound hardware. Fixes kernel bug 15982:
https://bugzilla.kernel.org/show_bug.cgi?id=15982

---
 drivers/gpu/drm/radeon/radeon_display.c |    5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)
drivers/gpu/drm/radeon/radeon_display.c +4 -1
@@ -978,8 +978,11 @@ void radeon_update_display_priority(stru
 		/* set display priority to high for r3xx, rv515 chips
 		 * this avoids flickering due to underflow to the
 		 * display controllers during heavy acceleration.
+		 * Don't force high on rs4xx igp chips as it seems to
+		 * affect the sound card.  See kernel bug 15982.
 		 */
-		if (ASIC_IS_R300(rdev) || (rdev->family == CHIP_RV515))
+		if ((ASIC_IS_R300(rdev) || (rdev->family == CHIP_RV515)) &&
+		    !(rdev->flags & RADEON_IS_IGP))
 			rdev->disp_priority = 2;
 		else
 			rdev->disp_priority = 0;
#517 lore raw

PATCH 73/200 drm/edid: Fix 1024x768@85Hz

In reply to Greg KH

2.6.34-stable review patch. If anyone has any objections, please let me know.

------------------

From: Adam Jackson <[email protected]>

commit 61dd98fad58f945ed720ba132681acb58fcee015 upstream.

Having hsync both start and end on pixel 1072 ain't gonna work very well. Matches the X server's list.

---
 drivers/gpu/drm/drm_edid.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/gpu/drm/drm_edid.c +1 -1
@@ -335,7 +335,7 @@ static struct drm_display_mode drm_dmt_m
 		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
 	/* 1024x768@85Hz */
 	{ DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER, 94500, 1024, 1072,
-		   1072, 1376, 0, 768, 769, 772, 808, 0,
+		   1168, 1376, 0, 768, 769, 772, 808, 0,
 		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
 	/* 1152x864@75Hz */
 	{ DRM_MODE("1152x864", DRM_MODE_TYPE_DRIVER, 108000, 1152, 1216,
#518 lore raw

PATCH 74/200 drm/radeon/kms: reset ddc_bus in object header parsing

In reply to Greg KH

2.6.34-stable review patch. If anyone has any objections, please let me know.

------------------

From: Alex Deucher <[email protected]>

commit 2bfcc0fc698d550689ef020c73b2d977b73e728c upstream.

Some LVDS connectors don't have a ddc bus, so reset the ddc bus to invalid before parsing the next connector to avoid using stale ddc bus data. Should fix fdo bug 28164.

---
 drivers/gpu/drm/radeon/radeon_atombios.c |    5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)
drivers/gpu/drm/radeon/radeon_atombios.c +2 -3
@@ -530,6 +530,8 @@ bool radeon_get_atom_connector_info_from
 			}
 
 			/* look up gpio for ddc, hpd */
+			ddc_bus.valid = false;
+			hpd.hpd = RADEON_HPD_NONE;
 			if ((le16_to_cpu(path->usDeviceTag) &
 			     (ATOM_DEVICE_TV_SUPPORT | ATOM_DEVICE_CV_SUPPORT)) == 0) {
 				for (j = 0; j < con_obj->ucNumberOfObjects; j++) {
@@ -585,9 +587,6 @@ bool radeon_get_atom_connector_info_from
 						break;
 					}
 				}
-			} else {
-				hpd.hpd = RADEON_HPD_NONE;
-				ddc_bus.valid = false;
 			}
 
 			/* needed for aux chan transactions */
#519 lore raw

PATCH 75/200 drm/radeon/kms/atom: fix typo in LVDS panel info parsing

In reply to Greg KH

2.6.34-stable review patch. If anyone has any objections, please let me know.

------------------

From: Alex Deucher <[email protected]>

commit 1ff26a3604d0292988d4cade0e49ba9918dbfd46 upstream.

Fixes LVDS issues on some laptops; notably laptops with 2048x1536 panels.

---
 drivers/gpu/drm/radeon/radeon_atombios.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/gpu/drm/radeon/radeon_atombios.c +1 -1
@@ -1173,7 +1173,7 @@ struct radeon_encoder_atom_dig *radeon_a
 		lvds->native_mode.vtotal = lvds->native_mode.vdisplay +
 			le16_to_cpu(lvds_info->info.sLCDTiming.usVBlanking_Time);
 		lvds->native_mode.vsync_start = lvds->native_mode.vdisplay +
-			le16_to_cpu(lvds_info->info.sLCDTiming.usVSyncWidth);
+			le16_to_cpu(lvds_info->info.sLCDTiming.usVSyncOffset);
 		lvds->native_mode.vsync_end = lvds->native_mode.vsync_start +
 			le16_to_cpu(lvds_info->info.sLCDTiming.usVSyncWidth);
 		lvds->panel_pwr_delay =
#520 lore raw

PATCH 76/200 drm/radeon/kms: release AGP bridge at suspend

In reply to Greg KH

2.6.34-stable review patch. If anyone has any objections, please let me know.

------------------

From: Jerome Glisse <[email protected]>

commit 10b06122afcc78468bd1d009633cb71e528acdc5 upstream.

I think it's good to release the AGP bridge at suspend and reacquire it at resume. Also fix :
https://bugzilla.kernel.org/show_bug.cgi?id=15969

---
 drivers/gpu/drm/radeon/radeon.h        |    1 +
 drivers/gpu/drm/radeon/radeon_agp.c    |    5 +++++
 drivers/gpu/drm/radeon/radeon_device.c |    2 ++
 3 files changed, 8 insertions(+)
drivers/gpu/drm/radeon/radeon.h +1 -0
@@ -566,6 +566,7 @@ typedef int (*radeon_packet3_check_t)(st
  */
 int radeon_agp_init(struct radeon_device *rdev);
 void radeon_agp_resume(struct radeon_device *rdev);
+void radeon_agp_suspend(struct radeon_device *rdev);
 void radeon_agp_fini(struct radeon_device *rdev);
 
 
drivers/gpu/drm/radeon/radeon_agp.c +5 -0
@@ -270,3 +270,8 @@ void radeon_agp_fini(struct radeon_devic
 	}
 #endif
 }
+
+void radeon_agp_suspend(struct radeon_device *rdev)
+{
+	radeon_agp_fini(rdev);
+}
drivers/gpu/drm/radeon/radeon_device.c +2 -0
@@ -748,6 +748,8 @@ int radeon_suspend_kms(struct drm_device
 	/* evict remaining vram memory */
 	radeon_bo_evict_vram(rdev);
 
+	radeon_agp_suspend(rdev);
+
 	pci_save_state(dev->pdev);
 	if (state.event == PM_EVENT_SUSPEND) {
 		/* Shut down the device */
#521 lore raw

PATCH 77/200 powerpc: Fix handling of strncmp with zero len

In reply to Greg KH

2.6.34-stable review patch. If anyone has any objections, please let me know.

------------------

From: Jeff Mahoney <[email protected]>

commit 637a99022fb119b90fb281715d13172f0394fc12 upstream.

Commit 0119536c, which added the assembly version of strncmp to powerpc, mentions that it adds two instructions to the version from boot/string.S to allow it to handle len=0. Unfortunately, it doesn't always return 0 when that is the case. The length is passed in r5, but the return value is passed back in r3. In certain cases, this will happen to work. Otherwise it will pass back the address of the first string as the return value.

This patch lifts the len <= 0 handling code from memcpy to handle that case.

Reported by: [email protected]

---
 arch/powerpc/lib/string.S |    4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)
arch/powerpc/lib/string.S +3 -1
@@ -71,7 +71,7 @@ _GLOBAL(strcmp)
 
 _GLOBAL(strncmp)
 	PPC_LCMPI r5,0
-	beqlr
+	ble-	2f
 	mtctr	r5
 	addi	r5,r3,-1
 	addi	r4,r4,-1
@@ -82,6 +82,8 @@ _GLOBAL(strncmp)
 	beqlr	1
 	bdnzt	eq,1b
 	blr
+2:	li	r3,0
+	blr
 
 _GLOBAL(strlen)
 	addi	r4,r3,-1
#522 lore raw

PATCH 78/200 powerpc/pseries: Only call start-cpu when a CPU is stopped

In reply to Greg KH

2.6.34-stable review patch. If anyone has any objections, please let me know.

------------------

From: Michael Neuling <[email protected]>

commit aef40e87d866355ffd279ab21021de733242d0d5 upstream.

Currently we always call start-cpu irrespective of if the CPU is stopped or not. Unfortunatley on POWER7, firmware seems to not like start-cpu being called when a cpu already been started. This was not the case on POWER6 and earlier.

This patch checks to see if the CPU is stopped or not via an query-cpu-stopped-state call, and only calls start-cpu on CPUs which are stopped.

This fixes a bug with kexec on POWER7 on PHYP where only the primary thread would make it to the second kernel.

---
 arch/powerpc/platforms/pseries/smp.c |    6 ++++++
 1 file changed, 6 insertions(+)
arch/powerpc/platforms/pseries/smp.c +6 -0
@@ -82,6 +82,12 @@ static inline int __devinit smp_startup_
 
 	pcpu = get_hard_smp_processor_id(lcpu);
 
+	/* Check to see if the CPU out of FW already for kexec */
+	if (smp_query_cpu_stopped(pcpu) == QCSS_NOT_STOPPED){
+		cpu_set(lcpu, of_spin_map);
+		return 1;
+	}
+
 	/* Fixup atomic count: it exited inside IRQ handler. */
 	task_thread_info(paca[lcpu].__current)->preempt_count	= 0;
 
#523 lore raw

PATCH 79/200 powerpc/pseries: Make query_cpu_stopped callable outside hotplug cpu

In reply to Greg KH

2.6.34-stable review patch. If anyone has any objections, please let me know.

------------------

From: Michael Neuling <[email protected]>

commit f8b67691828321f5c85bb853283aa101ae673130 upstream.

This moves query_cpu_stopped() out of the hotplug cpu code and into smp.c so it can called in other places and renames it to smp_query_cpu_stopped().

It also cleans up the return values by adding some #defines

---
 arch/powerpc/platforms/pseries/hotplug-cpu.c    |   30 +++---------------------
 arch/powerpc/platforms/pseries/plpar_wrappers.h |    8 ++++++
 arch/powerpc/platforms/pseries/smp.c            |   22 +++++++++++++++++
 3 files changed, 34 insertions(+), 26 deletions(-)
arch/powerpc/platforms/pseries/hotplug-cpu.c +4 -26
@@ -154,30 +154,6 @@ static void pseries_mach_cpu_die(void)
 	for(;;);
 }
 
-static int qcss_tok;	/* query-cpu-stopped-state token */
-
-/* Get state of physical CPU.
- * Return codes:
- *	0	- The processor is in the RTAS stopped state
- *	1	- stop-self is in progress
- *	2	- The processor is not in the RTAS stopped state
- *	-1	- Hardware Error
- *	-2	- Hardware Busy, Try again later.
- */
-static int query_cpu_stopped(unsigned int pcpu)
-{
-	int cpu_status, status;
-
-	status = rtas_call(qcss_tok, 1, 2, &cpu_status, pcpu);
-	if (status != 0) {
-		printk(KERN_ERR
-		       "RTAS query-cpu-stopped-state failed: %i\n", status);
-		return status;
-	}
-
-	return cpu_status;
-}
-
 static int pseries_cpu_disable(void)
 {
 	int cpu = smp_processor_id();
@@ -224,8 +200,9 @@ static void pseries_cpu_die(unsigned int
 	} else if (get_preferred_offline_state(cpu) == CPU_STATE_OFFLINE) {
 
 		for (tries = 0; tries < 25; tries++) {
-			cpu_status = query_cpu_stopped(pcpu);
-			if (cpu_status == 0 || cpu_status == -1)
+			cpu_status = smp_query_cpu_stopped(pcpu);
+			if (cpu_status == QCSS_STOPPED ||
+			    cpu_status == QCSS_HARDWARE_ERROR)
 				break;
 			cpu_relax();
 		}
@@ -388,6 +365,7 @@ static int __init pseries_cpu_hotplug_in
 	struct device_node *np;
 	const char *typep;
 	int cpu;
+	int qcss_tok;
 
 	for_each_node_by_name(np, "interrupt-controller") {
 		typep = of_get_property(np, "compatible", NULL);
arch/powerpc/platforms/pseries/plpar_wrappers.h +8 -0
@@ -4,6 +4,14 @@
 #include <asm/hvcall.h>
 #include <asm/page.h>
 
+/* Get state of physical CPU from query_cpu_stopped */
+int smp_query_cpu_stopped(unsigned int pcpu);
+#define QCSS_STOPPED 0
+#define QCSS_STOPPING 1
+#define QCSS_NOT_STOPPED 2
+#define QCSS_HARDWARE_ERROR -1
+#define QCSS_HARDWARE_BUSY -2
+
 static inline long poll_pending(void)
 {
 	return plpar_hcall_norets(H_POLL_PENDING);
arch/powerpc/platforms/pseries/smp.c +22 -0
@@ -57,6 +57,28 @@
  */
 static cpumask_t of_spin_map;
 
+/* Query where a cpu is now.  Return codes #defined in plpar_wrappers.h */
+int smp_query_cpu_stopped(unsigned int pcpu)
+{
+	int cpu_status, status;
+	int qcss_tok = rtas_token("query-cpu-stopped-state");
+
+	if (qcss_tok == RTAS_UNKNOWN_SERVICE) {
+		printk(KERN_INFO "Firmware doesn't support "
+				"query-cpu-stopped-state\n");
+		return QCSS_HARDWARE_ERROR;
+	}
+
+	status = rtas_call(qcss_tok, 1, 2, &cpu_status, pcpu);
+	if (status != 0) {
+		printk(KERN_ERR
+		       "RTAS query-cpu-stopped-state failed: %i\n", status);
+		return status;
+	}
+
+	return cpu_status;
+}
+
 /**
  * smp_startup_cpu() - start the given cpu
  *
#524 lore raw

Re: [079/200] powerpc/pseries: Make query_cpu_stopped callable outside hotplug cpu

Greg,

This won't break ppc64, but it pointless without:
aef40e87d866355ffd279ab21021de733242d0d5 powerpc/pseries: Make query_cpu_stopped callable outside hotplug cpu

There are two patches that can be put in stable, f8b676918 and aef40e87d. In this batch of stable releases you have:

2.6.27.48 : aef40e87d only (breaks ppc64)
2.6.32.16 : aef40e87d only (breaks ppc64)
2.6.33.6 : aef40e87d & f8b676918 (works!)
2.6.34.1 : f8b676918 only (does nothing)

Mikey

Quoted 1 line · In message <[email protected]> you wrote:

2.6.34-stable review patch. If anyone has any objections, please let me know

.

Quoted 11 lines

------------------

From: Michael Neuling <[email protected]>

commit f8b67691828321f5c85bb853283aa101ae673130 upstream.

This moves query_cpu_stopped() out of the hotplug cpu code and into smp.c so it can called in other places and renames it to smp_query_cpu_stopped().

Quoted 8 lines

It also cleans up the return values by adding some #defines

---
 arch/powerpc/platforms/pseries/hotplug-cpu.c    |   30 +++------------------

---

Quoted 107 lines
 arch/powerpc/platforms/pseries/plpar_wrappers.h |    8 ++++++
 arch/powerpc/platforms/pseries/smp.c            |   22 +++++++++++++++++
 3 files changed, 34 insertions(+), 26 deletions(-)
arch/powerpc/platforms/pseries/hotplug-cpu.c +4 -26
@@ -154,30 +154,6 @@ static void pseries_mach_cpu_die(void)
 	for(;;);
 }
 
-static int qcss_tok;	/* query-cpu-stopped-state token */
-
-/* Get state of physical CPU.
- * Return codes:
- *	0	- The processor is in the RTAS stopped state
- *	1	- stop-self is in progress
- *	2	- The processor is not in the RTAS stopped state
- *	-1	- Hardware Error
- *	-2	- Hardware Busy, Try again later.
- */
-static int query_cpu_stopped(unsigned int pcpu)
-{
-	int cpu_status, status;
-
-	status = rtas_call(qcss_tok, 1, 2, &cpu_status, pcpu);
-	if (status != 0) {
-		printk(KERN_ERR
-		       "RTAS query-cpu-stopped-state failed: %i\n", status);
-		return status;
-	}
-
-	return cpu_status;
-}
-
 static int pseries_cpu_disable(void)
 {
 	int cpu = smp_processor_id();
@@ -224,8 +200,9 @@ static void pseries_cpu_die(unsigned int
 	} else if (get_preferred_offline_state(cpu) == CPU_STATE_OFFLINE) {
 
 		for (tries = 0; tries < 25; tries++) {
-			cpu_status = query_cpu_stopped(pcpu);
-			if (cpu_status == 0 || cpu_status == -1)
+			cpu_status = smp_query_cpu_stopped(pcpu);
+			if (cpu_status == QCSS_STOPPED ||
+			    cpu_status == QCSS_HARDWARE_ERROR)
 				break;
 			cpu_relax();
 		}
@@ -388,6 +365,7 @@ static int __init pseries_cpu_hotplug_in
 	struct device_node *np;
 	const char *typep;
 	int cpu;
+	int qcss_tok;
 
 	for_each_node_by_name(np, "interrupt-controller") {
 		typep = of_get_property(np, "compatible", NULL);
arch/powerpc/platforms/pseries/plpar_wrappers.h +8 -0
@@ -4,6 +4,14 @@
 #include <asm/hvcall.h>
 #include <asm/page.h>
 
+/* Get state of physical CPU from query_cpu_stopped */
+int smp_query_cpu_stopped(unsigned int pcpu);
+#define QCSS_STOPPED 0
+#define QCSS_STOPPING 1
+#define QCSS_NOT_STOPPED 2
+#define QCSS_HARDWARE_ERROR -1
+#define QCSS_HARDWARE_BUSY -2
+
 static inline long poll_pending(void)
 {
 	return plpar_hcall_norets(H_POLL_PENDING);
arch/powerpc/platforms/pseries/smp.c +22 -0
@@ -57,6 +57,28 @@
  */
 static cpumask_t of_spin_map;
 
+/* Query where a cpu is now.  Return codes #defined in plpar_wrappers.h */
+int smp_query_cpu_stopped(unsigned int pcpu)
+{
+	int cpu_status, status;
+	int qcss_tok = rtas_token("query-cpu-stopped-state");
+
+	if (qcss_tok == RTAS_UNKNOWN_SERVICE) {
+		printk(KERN_INFO "Firmware doesn't support "
+				"query-cpu-stopped-state\n");
+		return QCSS_HARDWARE_ERROR;
+	}
+
+	status = rtas_call(qcss_tok, 1, 2, &cpu_status, pcpu);
+	if (status != 0) {
+		printk(KERN_ERR
+		       "RTAS query-cpu-stopped-state failed: %i\n", status);
+		return status;
+	}
+
+	return cpu_status;
+}
+
 /**
  * smp_startup_cpu() - start the given cpu
  *
#525 lore raw

Re: [079/200] powerpc/pseries: Make query_cpu_stopped callable outside hotplug cpu

Quoted 5 lines · Michael Neuling

Greg,

This won't break ppc64, but it pointless without:
aef40e87d866355ffd279ab21021de733242d0d5 powerpc/pseries: Make query_cpu_stopped callable outside hotplug cpu

That patch does not apply to the .34 tree, as it seems to be already included there. If not, can you please send me a backported version?

thanks,

greg k-h

#526 lore raw

Re: [079/200] powerpc/pseries: Make query_cpu_stopped callable outside hotplug cpu

Quoted 8 lines
Quoted 5 lines

Greg,

This won't break ppc64, but it pointless without:
aef40e87d866355ffd279ab21021de733242d0d5 powerpc/pseries: Make query_cpu_stopped callable outside hotplug cpu

That patch does not apply to the .34 tree, as it seems to be already included there. If not, can you please send me a backported version?

Sorry, my bad.

aef40e87d866355ffd279ab21021de733242d0d5 is 078/200 in this series (seemed to escape my inbox). All is good.

Thanks,
Mikey

#527 lore raw

Re: [079/200] powerpc/pseries: Make query_cpu_stopped callable outside hotplug cpu

Quoted 6 lines · Michael Neuling
Quoted 6 lines
Quoted 5 lines

Greg,

This won't break ppc64, but it pointless without:
aef40e87d866355ffd279ab21021de733242d0d5 powerpc/pseries: Make query_cpu_stopped callable outside hotplug cpu

Quoted 7 lines
Quoted 2 lines

That patch does not apply to the .34 tree, as it seems to be already included there. If not, can you please send me a backported version?

Sorry, my bad.

aef40e87d866355ffd279ab21021de733242d0d5 is 078/200 in this series (seemed to escape my inbox). All is good.

Great, thanks for verifying.

greg k-h

#528 lore raw

PATCH 80/200 powerpc: Fix ioremap_flags() with book3e pte definition

In reply to Greg KH

2.6.34-stable review patch. If anyone has any objections, please let me know.

------------------

From: Benjamin Herrenschmidt <[email protected]>

commit 55052eeca6d71d76f7c3f156c0501814d8e5e6d3 upstream.

We can't just clear the user read permission in book3e pte, because that will also clear supervisor read permission. This surely isn't desired. Fix the problem by adding the supervisor read back.

BenH: Slightly simplified the ifdef and applied to ppc64 too

---
 arch/powerpc/mm/pgtable_32.c |    8 ++++++++
 arch/powerpc/mm/pgtable_64.c |    8 ++++++++
 2 files changed, 16 insertions(+)
arch/powerpc/mm/pgtable_32.c +8 -0
@@ -146,6 +146,14 @@ ioremap_flags(phys_addr_t addr, unsigned
 	/* we don't want to let _PAGE_USER and _PAGE_EXEC leak out */
 	flags &= ~(_PAGE_USER | _PAGE_EXEC);
 
+#ifdef _PAGE_BAP_SR
+	/* _PAGE_USER contains _PAGE_BAP_SR on BookE using the new PTE format
+	 * which means that we just cleared supervisor access... oops ;-) This
+	 * restores it
+	 */
+	flags |= _PAGE_BAP_SR;
+#endif
+
 	return __ioremap_caller(addr, size, flags, __builtin_return_address(0));
 }
 EXPORT_SYMBOL(ioremap_flags);
arch/powerpc/mm/pgtable_64.c +8 -0
@@ -265,6 +265,14 @@ void __iomem * ioremap_flags(phys_addr_t
 	/* we don't want to let _PAGE_USER and _PAGE_EXEC leak out */
 	flags &= ~(_PAGE_USER | _PAGE_EXEC);
 
+#ifdef _PAGE_BAP_SR
+	/* _PAGE_USER contains _PAGE_BAP_SR on BookE using the new PTE format
+	 * which means that we just cleared supervisor access... oops ;-) This
+	 * restores it
+	 */
+	flags |= _PAGE_BAP_SR;
+#endif
+
 	if (ppc_md.ioremap)
 		return ppc_md.ioremap(addr, size, flags, caller);
 	return __ioremap_caller(addr, size, flags, caller);
#529 lore raw

PATCH 81/200 powerpc/fsl-booke: Fix InstructionTLBError execute permission check

In reply to Greg KH

2.6.34-stable review patch. If anyone has any objections, please let me know.

------------------

From: Li Yang <[email protected]>

commit 78e2e68a2b79f394b7cd61e07987a8a89af907f7 upstream.

In CONFIG_PTE_64BIT the PTE format has unique permission bits for user and supervisor execute. However on !CONFIG_PTE_64BIT we overload the supervisor bit to imply user execute with _PAGE_USER set. This allows us to use the same permission check mask for user or supervisor code on !CONFIG_PTE_64BIT.

However, on CONFIG_PTE_64BIT we map _PAGE_EXEC to _PAGE_BAP_UX so we need a different permission mask based on the fault coming from a kernel address or user space.

Without unique permission masks we see issues like the following with modules:

Unable to handle kernel paging request for instruction fetch
Faulting instruction address: 0xf938d040
Oops: Kernel access of bad area, sig: 11 [#1]
---
 arch/powerpc/kernel/head_fsl_booke.S |   13 ++++++++++---
 1 file changed, 10 insertions(+), 3 deletions(-)
arch/powerpc/kernel/head_fsl_booke.S +10 -3
@@ -639,6 +639,13 @@ interrupt_base:
 	rlwinm	r12,r12,0,16,1
 	mtspr	SPRN_MAS1,r12
 
+	/* Make up the required permissions for kernel code */
+#ifdef CONFIG_PTE_64BIT
+	li	r13,_PAGE_PRESENT | _PAGE_BAP_SX
+	oris	r13,r13,_PAGE_ACCESSED@h
+#else
+	li	r13,_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_EXEC
+#endif
 	b	4f
 
 	/* Get the PGD for the current thread */
@@ -646,15 +653,15 @@ interrupt_base:
 	mfspr	r11,SPRN_SPRG_THREAD
 	lwz	r11,PGDIR(r11)
 
-4:
-	/* Make up the required permissions */
+	/* Make up the required permissions for user code */
 #ifdef CONFIG_PTE_64BIT
-	li	r13,_PAGE_PRESENT | _PAGE_EXEC
+	li	r13,_PAGE_PRESENT | _PAGE_BAP_UX
 	oris	r13,r13,_PAGE_ACCESSED@h
 #else
 	li	r13,_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_EXEC
 #endif
 
+4:
 	FIND_PTE
 	andc.	r13,r13,r11		/* Check permission */
 
#530 lore raw

PATCH 82/200 powerpc/fsl-booke: Move loadcam_entry back to asm code to fix SMP ftrace

In reply to Greg KH

2.6.34-stable review patch. If anyone has any objections, please let me know.

------------------

From: Kumar Gala <[email protected]>

commit 78f622377f7d31d988db350a43c5689dd5f31876 upstream.

When we build with ftrace enabled its possible that loadcam_entry would have used the stack pointer (even though the code doesn't need it). We call loadcam_entry in __secondary_start before the stack is setup. To ensure that loadcam_entry doesn't use the stack pointer the easiest solution is to just have it in asm code.

---
 arch/powerpc/kernel/asm-offsets.c |    8 ++++++++
 arch/powerpc/mm/fsl_booke_mmu.c   |   25 +++----------------------
 arch/powerpc/mm/mmu_decl.h        |    8 ++++++++
 arch/powerpc/mm/tlb_nohash_low.S  |   28 ++++++++++++++++++++++++++++
 4 files changed, 47 insertions(+), 22 deletions(-)
arch/powerpc/kernel/asm-offsets.c +8 -0
@@ -447,6 +447,14 @@ int main(void)
 	DEFINE(PGD_T_LOG2, PGD_T_LOG2);
 	DEFINE(PTE_T_LOG2, PTE_T_LOG2);
 #endif
+#ifdef CONFIG_FSL_BOOKE
+	DEFINE(TLBCAM_SIZE, sizeof(struct tlbcam));
+	DEFINE(TLBCAM_MAS0, offsetof(struct tlbcam, MAS0));
+	DEFINE(TLBCAM_MAS1, offsetof(struct tlbcam, MAS1));
+	DEFINE(TLBCAM_MAS2, offsetof(struct tlbcam, MAS2));
+	DEFINE(TLBCAM_MAS3, offsetof(struct tlbcam, MAS3));
+	DEFINE(TLBCAM_MAS7, offsetof(struct tlbcam, MAS7));
+#endif
 
 #ifdef CONFIG_KVM_EXIT_TIMING
 	DEFINE(VCPU_TIMING_EXIT_TBU, offsetof(struct kvm_vcpu,
arch/powerpc/mm/fsl_booke_mmu.c +3 -22
@@ -2,7 +2,7 @@
  * Modifications by Kumar Gala ([email protected]) to support
  * E500 Book E processors.
  *
- * Copyright 2004 Freescale Semiconductor, Inc
+ * Copyright 2004,2010 Freescale Semiconductor, Inc.
  *
  * This file contains the routines for initializing the MMU
  * on the 4xx series of chips.
@@ -56,19 +56,13 @@
 
 unsigned int tlbcam_index;
 
-#define NUM_TLBCAMS	(64)
 
 #if defined(CONFIG_LOWMEM_CAM_NUM_BOOL) && (CONFIG_LOWMEM_CAM_NUM >= NUM_TLBCAMS)
 #error "LOWMEM_CAM_NUM must be less than NUM_TLBCAMS"
 #endif
 
-struct tlbcam {
-	u32	MAS0;
-	u32	MAS1;
-	unsigned long	MAS2;
-	u32	MAS3;
-	u32	MAS7;
-} TLBCAM[NUM_TLBCAMS];
+#define NUM_TLBCAMS	(64)
+struct tlbcam TLBCAM[NUM_TLBCAMS];
 
 struct tlbcamrange {
 	unsigned long start;
@@ -109,19 +103,6 @@ unsigned long p_mapped_by_tlbcam(phys_ad
 	return 0;
 }
 
-void loadcam_entry(int idx)
-{
-	mtspr(SPRN_MAS0, TLBCAM[idx].MAS0);
-	mtspr(SPRN_MAS1, TLBCAM[idx].MAS1);
-	mtspr(SPRN_MAS2, TLBCAM[idx].MAS2);
-	mtspr(SPRN_MAS3, TLBCAM[idx].MAS3);
-
-	if (mmu_has_feature(MMU_FTR_BIG_PHYS))
-		mtspr(SPRN_MAS7, TLBCAM[idx].MAS7);
-
-	asm volatile("isync;tlbwe;isync" : : : "memory");
-}
-
 /*
  * Set up one of the I/D BAT (block address translation) register pairs.
  * The parameters are not checked; in particular size must be a power
arch/powerpc/mm/mmu_decl.h +8 -0
@@ -149,7 +149,15 @@ extern unsigned long mmu_mapin_ram(unsig
 extern void MMU_init_hw(void);
 extern unsigned long mmu_mapin_ram(unsigned long top);
 extern void adjust_total_lowmem(void);
+extern void loadcam_entry(unsigned int index);
 
+struct tlbcam {
+	u32	MAS0;
+	u32	MAS1;
+	unsigned long	MAS2;
+	u32	MAS3;
+	u32	MAS7;
+};
 #elif defined(CONFIG_PPC32)
 /* anything 32-bit except 4xx or 8xx */
 extern void MMU_init_hw(void);
arch/powerpc/mm/tlb_nohash_low.S +28 -0
@@ -271,3 +271,31 @@ _GLOBAL(set_context)
 #else
 #error Unsupported processor type !
 #endif
+
+#if defined(CONFIG_FSL_BOOKE)
+/*
+ * extern void loadcam_entry(unsigned int index)
+ *
+ * Load TLBCAM[index] entry in to the L2 CAM MMU
+ */
+_GLOBAL(loadcam_entry)
+	LOAD_REG_ADDR(r4, TLBCAM)
+	mulli	r5,r3,TLBCAM_SIZE
+	add	r3,r5,r4
+	lwz	r4,TLBCAM_MAS0(r3)
+	mtspr	SPRN_MAS0,r4
+	lwz	r4,TLBCAM_MAS1(r3)
+	mtspr	SPRN_MAS1,r4
+	PPC_LL	r4,TLBCAM_MAS2(r3)
+	mtspr	SPRN_MAS2,r4
+	lwz	r4,TLBCAM_MAS3(r3)
+	mtspr	SPRN_MAS3,r4
+BEGIN_MMU_FTR_SECTION
+	lwz	r4,TLBCAM_MAS7(r3)
+	mtspr	SPRN_MAS7,r4
+END_MMU_FTR_SECTION_IFSET(MMU_FTR_BIG_PHYS)
+	isync
+	tlbwe
+	isync
+	blr
+#endif
#531 lore raw

PATCH 83/200 powerpc/oprofile: fix potential buffer overrun in op_model_cell.c

In reply to Greg KH

2.6.34-stable review patch. If anyone has any objections, please let me know.

------------------

From: Denis Kirjanov <[email protected]>

commit 238c1a78c957f3dc7cb848b161dcf4805793ed56 upstream.

Fix potential initial_lfsr buffer overrun.
Writing past the end of the buffer could happen when index == ENTRIES

---
 arch/powerpc/oprofile/op_model_cell.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
arch/powerpc/oprofile/op_model_cell.c +1 -1
@@ -1077,7 +1077,7 @@ static int calculate_lfsr(int n)
 		index = ENTRIES-1;
 
 	/* make sure index is valid */
-	if ((index > ENTRIES) || (index < 0))
+	if ((index >= ENTRIES) || (index < 0))
 		index = ENTRIES-1;
 
 	return initial_lfsr[index];
#532 lore raw

PATCH 84/200 writeback: disable periodic old data writeback for !dirty_writeback_centisecs

In reply to Greg KH

2.6.34-stable review patch. If anyone has any objections, please let me know.

------------------

From: Jens Axboe <[email protected]>

commit 69b62d01ec44fe0d505d89917392347732135a4d upstream.

Prior to 2.6.32, setting /proc/sys/vm/dirty_writeback_centisecs disabled periodic dirty writeback from kupdate. This got broken and now causes excessive sys CPU usage if set to zero, as we'll keep beating on schedule().

---
 fs/fs-writeback.c |   14 ++++++++++++--
 1 file changed, 12 insertions(+), 2 deletions(-)
fs/fs-writeback.c +12 -2
@@ -852,6 +852,12 @@ static long wb_check_old_data_flush(stru
 	unsigned long expired;
 	long nr_pages;
 
+	/*
+	 * When set to zero, disable periodic writeback
+	 */
+	if (!dirty_writeback_interval)
+		return 0;
+
 	expired = wb->last_old_flush +
 			msecs_to_jiffies(dirty_writeback_interval * 10);
 	if (time_before(jiffies, expired))
@@ -947,8 +953,12 @@ int bdi_writeback_task(struct bdi_writeb
 				break;
 		}
 
-		wait_jiffies = msecs_to_jiffies(dirty_writeback_interval * 10);
-		schedule_timeout_interruptible(wait_jiffies);
+		if (dirty_writeback_interval) {
+			wait_jiffies = msecs_to_jiffies(dirty_writeback_interval * 10);
+			schedule_timeout_interruptible(wait_jiffies);
+		} else
+			schedule();
+
 		try_to_freeze();
 	}
 
#533 lore raw

PATCH 85/200 md/raid1: fix counting of write targets.

In reply to Greg KH

2.6.34-stable review patch. If anyone has any objections, please let me know.

------------------

From: NeilBrown <[email protected]>

commit 964147d5c86d63be79b442c30f3783d49860c078 upstream.

There is a very small race window when writing to a RAID1 such that if a device is marked faulty at exactly the wrong time, the write-in-progress will not be sent to the device, but the bitmap (if present) will be updated to say that the write was sent.

Then if the device turned out to still be usable as was re-added to the array, the bitmap-based-resync would skip resyncing that block, possibly leading to corruption. This would only be a problem if no further writes were issued to that area of the device (i.e. that bitmap chunk).

Suitable for any pending -stable kernel.

---
 drivers/md/raid1.c |    5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)
drivers/md/raid1.c +3 -2
@@ -912,9 +912,10 @@ static int make_request(struct request_q
 			if (test_bit(Faulty, &rdev->flags)) {
 				rdev_dec_pending(rdev, mddev);
 				r1_bio->bios[i] = NULL;
-			} else
+			} else {
 				r1_bio->bios[i] = bio;
-			targets++;
+				targets++;
+			}
 		} else
 			r1_bio->bios[i] = NULL;
 	}
#534 lore raw

PATCH 86/200 md: Fix read balancing in RAID1 and RAID10 on drives > 2TB

In reply to Greg KH

2.6.34-stable review patch. If anyone has any objections, please let me know.

------------------

From: NeilBrown <[email protected]>

commit af3a2cd6b8a479345786e7fe5e199ad2f6240e56 upstream.

read_balance uses a "unsigned long" for a sector number which will get truncated beyond 2TB.
This will cause read-balancing to be non-optimal, and can cause data to be read from the 'wrong' branch during a resync. This has a very small chance of returning wrong data.

---
 drivers/md/raid1.c  |    4 ++--
 drivers/md/raid10.c |    2 +-
 2 files changed, 3 insertions(+), 3 deletions(-)
drivers/md/raid1.c +2 -2
@@ -418,7 +418,7 @@ static void raid1_end_write_request(stru
  */
 static int read_balance(conf_t *conf, r1bio_t *r1_bio)
 {
-	const unsigned long this_sector = r1_bio->sector;
+	const sector_t this_sector = r1_bio->sector;
 	int new_disk = conf->last_used, disk = new_disk;
 	int wonly_disk = -1;
 	const int sectors = r1_bio->sectors;
@@ -434,7 +434,7 @@ static int read_balance(conf_t *conf, r1
  retry:
 	if (conf->mddev->recovery_cp < MaxSector &&
 	    (this_sector + sectors >= conf->next_resync)) {
-		/* Choose the first operation device, for consistancy */
+		/* Choose the first operational device, for consistancy */
 		new_disk = 0;
 
 		for (rdev = rcu_dereference(conf->mirrors[new_disk].rdev);
drivers/md/raid10.c +1 -1
@@ -494,7 +494,7 @@ static int raid10_mergeable_bvec(struct
  */
 static int read_balance(conf_t *conf, r10bio_t *r10_bio)
 {
-	const unsigned long this_sector = r10_bio->sector;
+	const sector_t this_sector = r10_bio->sector;
 	int disk, slot, nslot;
 	const int sectors = r10_bio->sectors;
 	sector_t new_distance, current_distance;
#535 lore raw

PATCH 87/200 md/linear: avoid possible oops and array stop

In reply to Greg KH

2.6.34-stable review patch. If anyone has any objections, please let me know.

------------------

From: NeilBrown <[email protected]>

commit ef2f80ff7325b2c1888ff02ead28957b5840bf51 upstream.

Since commit ef286f6fa673cd7fb367e1b145069d8dbfcc6081 it has been important that each personality clears ->private in the ->stop() function, or sets it to a attribute group to be removed.
linear.c doesn't. This can sometimes lead to an oops, though it doesn't always.

Suitable for 2.6.33-stable and 2.6.34.

---
 drivers/md/linear.c |    1 +
 1 file changed, 1 insertion(+)
drivers/md/linear.c +1 -0
@@ -282,6 +282,7 @@ static int linear_stop (mddev_t *mddev)
 	rcu_barrier();
 	blk_sync_queue(mddev->queue); /* the unplug fn references 'conf'*/
 	kfree(conf);
+	mddev->private = NULL;
 
 	return 0;
 }
#536 lore raw

PATCH 88/200 md: remove unneeded sysfs files more promptly

In reply to Greg KH

2.6.34-stable review patch. If anyone has any objections, please let me know.

------------------

From: NeilBrown <[email protected]>

commit b6eb127d274385d81ce8dd45c98190f097bce1b4 upstream.

When an array is stopped we need to remove some sysfs files which are dependent on the type of array.

We need to delay that deletion as deleting them while holding reconfig_mutex can lead to deadlocks.

We currently delay them until the array is completely destroyed. However it is possible to deactivate and then reactivate the array. It is also possible to need to remove sysfs files when changing level, which can potentially happen several times before an array is destroyed.

So we need to delete these files more promptly: as soon as reconfig_mutex is dropped.

We need to ensure this happens before do_md_run can restart the array, so we use open_mutex for some extra locking. This is not deadlock prone.

---
 drivers/md/md.c |   41 +++++++++++++++++++++++++++++++----------
 1 file changed, 31 insertions(+), 10 deletions(-)
drivers/md/md.c +31 -10
@@ -508,9 +508,32 @@ static inline int mddev_trylock(mddev_t
 	return mutex_trylock(&mddev->reconfig_mutex);
 }
 
+static struct attribute_group md_redundancy_group;
+
 static inline void mddev_unlock(mddev_t * mddev)
 {
-	mutex_unlock(&mddev->reconfig_mutex);
+	if (mddev->pers == NULL && mddev->private) {
+		/* These cannot be removed under reconfig_mutex as
+		 * an access to the files will try to take reconfig_mutex
+		 * while holding the file unremovable, which leads to
+		 * a deadlock.
+		 * So hold open_mutex instead - we are allowed to take
+		 * it while holding reconfig_mutex, and md_run can
+		 * use it to wait for the remove to complete.
+		 */
+		mutex_lock(&mddev->open_mutex);
+		mutex_unlock(&mddev->reconfig_mutex);
+
+		sysfs_remove_group(&mddev->kobj, &md_redundancy_group);
+		if (mddev->private != (void*)1)
+			sysfs_remove_group(&mddev->kobj, mddev->private);
+		if (mddev->sysfs_action)
+			sysfs_put(mddev->sysfs_action);
+		mddev->sysfs_action = NULL;
+		mddev->private = NULL;
+		mutex_unlock(&mddev->open_mutex);
+	} else
+		mutex_unlock(&mddev->reconfig_mutex);
 
 	md_wakeup_thread(mddev->thread);
 }
@@ -4082,15 +4105,6 @@ static void mddev_delayed_delete(struct
 {
 	mddev_t *mddev = container_of(ws, mddev_t, del_work);
 
-	if (mddev->private) {
-		sysfs_remove_group(&mddev->kobj, &md_redundancy_group);
-		if (mddev->private != (void*)1)
-			sysfs_remove_group(&mddev->kobj, mddev->private);
-		if (mddev->sysfs_action)
-			sysfs_put(mddev->sysfs_action);
-		mddev->sysfs_action = NULL;
-		mddev->private = NULL;
-	}
 	sysfs_remove_group(&mddev->kobj, &md_bitmap_group);
 	kobject_del(&mddev->kobj);
 	kobject_put(&mddev->kobj);
@@ -4248,6 +4262,13 @@ static int do_md_run(mddev_t * mddev)
 	if (mddev->pers)
 		return -EBUSY;
 
+	/* These two calls synchronise us with the
+	 * sysfs_remove_group calls in mddev_unlock,
+	 * so they must have completed.
+	 */
+	mutex_lock(&mddev->open_mutex);
+	mutex_unlock(&mddev->open_mutex);
+
 	/*
 	 * Analyze all RAID superblock(s)
 	 */