diff options
99 files changed, 914 insertions, 877 deletions
diff --git a/Documentation/DocBook/device-drivers.tmpl b/Documentation/DocBook/device-drivers.tmpl index ecd35e9d4410..feca0758391e 100644 --- a/Documentation/DocBook/device-drivers.tmpl +++ b/Documentation/DocBook/device-drivers.tmpl | |||
| @@ -46,7 +46,6 @@ | |||
| 46 | 46 | ||
| 47 | <sect1><title>Atomic and pointer manipulation</title> | 47 | <sect1><title>Atomic and pointer manipulation</title> |
| 48 | !Iarch/x86/include/asm/atomic.h | 48 | !Iarch/x86/include/asm/atomic.h |
| 49 | !Iarch/x86/include/asm/unaligned.h | ||
| 50 | </sect1> | 49 | </sect1> |
| 51 | 50 | ||
| 52 | <sect1><title>Delaying, scheduling, and timer routines</title> | 51 | <sect1><title>Delaying, scheduling, and timer routines</title> |
diff --git a/Documentation/DocBook/kernel-api.tmpl b/Documentation/DocBook/kernel-api.tmpl index a20c6f6fffc3..6899f471fb15 100644 --- a/Documentation/DocBook/kernel-api.tmpl +++ b/Documentation/DocBook/kernel-api.tmpl | |||
| @@ -57,7 +57,6 @@ | |||
| 57 | </para> | 57 | </para> |
| 58 | 58 | ||
| 59 | <sect1><title>String Conversions</title> | 59 | <sect1><title>String Conversions</title> |
| 60 | !Ilib/vsprintf.c | ||
| 61 | !Elib/vsprintf.c | 60 | !Elib/vsprintf.c |
| 62 | </sect1> | 61 | </sect1> |
| 63 | <sect1><title>String Manipulation</title> | 62 | <sect1><title>String Manipulation</title> |
diff --git a/Documentation/kernel-doc-nano-HOWTO.txt b/Documentation/kernel-doc-nano-HOWTO.txt index 27a52b35d55b..3d8a97747f77 100644 --- a/Documentation/kernel-doc-nano-HOWTO.txt +++ b/Documentation/kernel-doc-nano-HOWTO.txt | |||
| @@ -345,5 +345,10 @@ documentation, in <filename>, for the functions listed. | |||
| 345 | section titled <section title> from <filename>. | 345 | section titled <section title> from <filename>. |
| 346 | Spaces are allowed in <section title>; do not quote the <section title>. | 346 | Spaces are allowed in <section title>; do not quote the <section title>. |
| 347 | 347 | ||
| 348 | !C<filename> is replaced by nothing, but makes the tools check that | ||
| 349 | all DOC: sections and documented functions, symbols, etc. are used. | ||
| 350 | This makes sense to use when you use !F/!P only and want to verify | ||
| 351 | that all documentation is included. | ||
| 352 | |||
| 348 | Tim. | 353 | Tim. |
| 349 | */ <twaugh@redhat.com> | 354 | */ <twaugh@redhat.com> |
| @@ -1,7 +1,7 @@ | |||
| 1 | VERSION = 2 | 1 | VERSION = 2 |
| 2 | PATCHLEVEL = 6 | 2 | PATCHLEVEL = 6 |
| 3 | SUBLEVEL = 36 | 3 | SUBLEVEL = 36 |
| 4 | EXTRAVERSION = -rc3 | 4 | EXTRAVERSION = -rc4 |
| 5 | NAME = Sheep on Meth | 5 | NAME = Sheep on Meth |
| 6 | 6 | ||
| 7 | # *DOCUMENTATION* | 7 | # *DOCUMENTATION* |
diff --git a/arch/ia64/include/asm/compat.h b/arch/ia64/include/asm/compat.h index f90edc85b509..9301a2821615 100644 --- a/arch/ia64/include/asm/compat.h +++ b/arch/ia64/include/asm/compat.h | |||
| @@ -199,7 +199,7 @@ ptr_to_compat(void __user *uptr) | |||
| 199 | } | 199 | } |
| 200 | 200 | ||
| 201 | static __inline__ void __user * | 201 | static __inline__ void __user * |
| 202 | compat_alloc_user_space (long len) | 202 | arch_compat_alloc_user_space (long len) |
| 203 | { | 203 | { |
| 204 | struct pt_regs *regs = task_pt_regs(current); | 204 | struct pt_regs *regs = task_pt_regs(current); |
| 205 | return (void __user *) (((regs->r12 & 0xffffffff) & -16) - len); | 205 | return (void __user *) (((regs->r12 & 0xffffffff) & -16) - len); |
diff --git a/arch/ia64/kernel/fsys.S b/arch/ia64/kernel/fsys.S index 3567d54f8cee..471a1e783aca 100644 --- a/arch/ia64/kernel/fsys.S +++ b/arch/ia64/kernel/fsys.S | |||
| @@ -424,14 +424,26 @@ EX(.fail_efault, ld8 r14=[r33]) // r14 <- *set | |||
| 424 | andcm r14=r14,r17 // filter out SIGKILL & SIGSTOP | 424 | andcm r14=r14,r17 // filter out SIGKILL & SIGSTOP |
| 425 | 425 | ||
| 426 | #ifdef CONFIG_SMP | 426 | #ifdef CONFIG_SMP |
| 427 | mov r17=1 | 427 | // __ticket_spin_trylock(r31) |
| 428 | ;; | 428 | ld4 r17=[r31] |
| 429 | cmpxchg4.acq r18=[r31],r17,ar.ccv // try to acquire the lock | ||
| 430 | mov r8=EINVAL // default to EINVAL | 429 | mov r8=EINVAL // default to EINVAL |
| 431 | ;; | 430 | ;; |
| 431 | extr r9=r17,17,15 | ||
| 432 | ;; | ||
| 433 | xor r18=r17,r9 | ||
| 434 | adds r19=1,r17 | ||
| 435 | ;; | ||
| 436 | extr.u r18=r18,0,15 | ||
| 437 | ;; | ||
| 438 | cmp.eq p0,p7=0,r18 | ||
| 439 | (p7) br.cond.spnt.many .lock_contention | ||
| 440 | mov.m ar.ccv=r17 | ||
| 441 | ;; | ||
| 442 | cmpxchg4.acq r9=[r31],r19,ar.ccv | ||
| 443 | ;; | ||
| 444 | cmp4.eq p0,p7=r9,r17 | ||
| 445 | (p7) br.cond.spnt.many .lock_contention | ||
| 432 | ld8 r3=[r2] // re-read current->blocked now that we hold the lock | 446 | ld8 r3=[r2] // re-read current->blocked now that we hold the lock |
| 433 | cmp4.ne p6,p0=r18,r0 | ||
| 434 | (p6) br.cond.spnt.many .lock_contention | ||
| 435 | ;; | 447 | ;; |
| 436 | #else | 448 | #else |
| 437 | ld8 r3=[r2] // re-read current->blocked now that we hold the lock | 449 | ld8 r3=[r2] // re-read current->blocked now that we hold the lock |
| @@ -490,7 +502,17 @@ EX(.fail_efault, ld8 r14=[r33]) // r14 <- *set | |||
| 490 | (p6) br.cond.spnt.few 1b // yes -> retry | 502 | (p6) br.cond.spnt.few 1b // yes -> retry |
| 491 | 503 | ||
| 492 | #ifdef CONFIG_SMP | 504 | #ifdef CONFIG_SMP |
| 493 | st4.rel [r31]=r0 // release the lock | 505 | // __ticket_spin_unlock(r31) |
| 506 | adds r31=2,r31 | ||
| 507 | ;; | ||
| 508 | ld2.bias r2=[r31] | ||
| 509 | mov r3=65534 | ||
| 510 | ;; | ||
| 511 | adds r2=2,r2 | ||
| 512 | ;; | ||
| 513 | and r3=r3,r2 | ||
| 514 | ;; | ||
| 515 | st2.rel [r31]=r3 | ||
| 494 | #endif | 516 | #endif |
| 495 | SSM_PSR_I(p0, p9, r31) | 517 | SSM_PSR_I(p0, p9, r31) |
| 496 | ;; | 518 | ;; |
| @@ -512,7 +534,17 @@ EX(.fail_efault, (p15) st8 [r34]=r3) | |||
| 512 | 534 | ||
| 513 | .sig_pending: | 535 | .sig_pending: |
| 514 | #ifdef CONFIG_SMP | 536 | #ifdef CONFIG_SMP |
| 515 | st4.rel [r31]=r0 // release the lock | 537 | // __ticket_spin_unlock(r31) |
| 538 | adds r31=2,r31 | ||
| 539 | ;; | ||
| 540 | ld2.bias r2=[r31] | ||
| 541 | mov r3=65534 | ||
| 542 | ;; | ||
| 543 | adds r2=2,r2 | ||
| 544 | ;; | ||
| 545 | and r3=r3,r2 | ||
| 546 | ;; | ||
| 547 | st2.rel [r31]=r3 | ||
| 516 | #endif | 548 | #endif |
| 517 | SSM_PSR_I(p0, p9, r17) | 549 | SSM_PSR_I(p0, p9, r17) |
| 518 | ;; | 550 | ;; |
diff --git a/arch/m68k/include/asm/unistd.h b/arch/m68k/include/asm/unistd.h index 60b15d0aa072..b43b36beafe3 100644 --- a/arch/m68k/include/asm/unistd.h +++ b/arch/m68k/include/asm/unistd.h | |||
| @@ -340,10 +340,13 @@ | |||
| 340 | #define __NR_set_thread_area 334 | 340 | #define __NR_set_thread_area 334 |
| 341 | #define __NR_atomic_cmpxchg_32 335 | 341 | #define __NR_atomic_cmpxchg_32 335 |
| 342 | #define __NR_atomic_barrier 336 | 342 | #define __NR_atomic_barrier 336 |
| 343 | #define __NR_fanotify_init 337 | ||
| 344 | #define __NR_fanotify_mark 338 | ||
| 345 | #define __NR_prlimit64 339 | ||
| 343 | 346 | ||
| 344 | #ifdef __KERNEL__ | 347 | #ifdef __KERNEL__ |
| 345 | 348 | ||
| 346 | #define NR_syscalls 337 | 349 | #define NR_syscalls 340 |
| 347 | 350 | ||
| 348 | #define __ARCH_WANT_IPC_PARSE_VERSION | 351 | #define __ARCH_WANT_IPC_PARSE_VERSION |
| 349 | #define __ARCH_WANT_OLD_READDIR | 352 | #define __ARCH_WANT_OLD_READDIR |
diff --git a/arch/m68k/kernel/entry.S b/arch/m68k/kernel/entry.S index 2391bdff0996..6360c437dcf5 100644 --- a/arch/m68k/kernel/entry.S +++ b/arch/m68k/kernel/entry.S | |||
| @@ -765,4 +765,7 @@ sys_call_table: | |||
| 765 | .long sys_set_thread_area | 765 | .long sys_set_thread_area |
| 766 | .long sys_atomic_cmpxchg_32 /* 335 */ | 766 | .long sys_atomic_cmpxchg_32 /* 335 */ |
| 767 | .long sys_atomic_barrier | 767 | .long sys_atomic_barrier |
| 768 | .long sys_fanotify_init | ||
| 769 | .long sys_fanotify_mark | ||
| 770 | .long sys_prlimit64 | ||
| 768 | 771 | ||
diff --git a/arch/m68knommu/kernel/syscalltable.S b/arch/m68knommu/kernel/syscalltable.S index b30b3eb197a5..79b1ed198c07 100644 --- a/arch/m68knommu/kernel/syscalltable.S +++ b/arch/m68knommu/kernel/syscalltable.S | |||
| @@ -355,6 +355,9 @@ ENTRY(sys_call_table) | |||
| 355 | .long sys_set_thread_area | 355 | .long sys_set_thread_area |
| 356 | .long sys_atomic_cmpxchg_32 /* 335 */ | 356 | .long sys_atomic_cmpxchg_32 /* 335 */ |
| 357 | .long sys_atomic_barrier | 357 | .long sys_atomic_barrier |
| 358 | .long sys_fanotify_init | ||
| 359 | .long sys_fanotify_mark | ||
| 360 | .long sys_prlimit64 | ||
| 358 | 361 | ||
| 359 | .rept NR_syscalls-(.-sys_call_table)/4 | 362 | .rept NR_syscalls-(.-sys_call_table)/4 |
| 360 | .long sys_ni_syscall | 363 | .long sys_ni_syscall |
diff --git a/arch/mips/include/asm/compat.h b/arch/mips/include/asm/compat.h index 613f6912dfc1..dbc51065df5b 100644 --- a/arch/mips/include/asm/compat.h +++ b/arch/mips/include/asm/compat.h | |||
| @@ -145,7 +145,7 @@ static inline compat_uptr_t ptr_to_compat(void __user *uptr) | |||
| 145 | return (u32)(unsigned long)uptr; | 145 | return (u32)(unsigned long)uptr; |
| 146 | } | 146 | } |
| 147 | 147 | ||
| 148 | static inline void __user *compat_alloc_user_space(long len) | 148 | static inline void __user *arch_compat_alloc_user_space(long len) |
| 149 | { | 149 | { |
| 150 | struct pt_regs *regs = (struct pt_regs *) | 150 | struct pt_regs *regs = (struct pt_regs *) |
| 151 | ((unsigned long) current_thread_info() + THREAD_SIZE - 32) - 1; | 151 | ((unsigned long) current_thread_info() + THREAD_SIZE - 32) - 1; |
diff --git a/arch/mn10300/kernel/mn10300-serial.c b/arch/mn10300/kernel/mn10300-serial.c index 9d49073e827a..db509dd80565 100644 --- a/arch/mn10300/kernel/mn10300-serial.c +++ b/arch/mn10300/kernel/mn10300-serial.c | |||
| @@ -156,17 +156,17 @@ struct mn10300_serial_port mn10300_serial_port_sif0 = { | |||
| 156 | ._intr = &SC0ICR, | 156 | ._intr = &SC0ICR, |
| 157 | ._rxb = &SC0RXB, | 157 | ._rxb = &SC0RXB, |
| 158 | ._txb = &SC0TXB, | 158 | ._txb = &SC0TXB, |
| 159 | .rx_name = "ttySM0/Rx", | 159 | .rx_name = "ttySM0:Rx", |
| 160 | .tx_name = "ttySM0/Tx", | 160 | .tx_name = "ttySM0:Tx", |
| 161 | #ifdef CONFIG_MN10300_TTYSM0_TIMER8 | 161 | #ifdef CONFIG_MN10300_TTYSM0_TIMER8 |
| 162 | .tm_name = "ttySM0/Timer8", | 162 | .tm_name = "ttySM0:Timer8", |
| 163 | ._tmxmd = &TM8MD, | 163 | ._tmxmd = &TM8MD, |
| 164 | ._tmxbr = &TM8BR, | 164 | ._tmxbr = &TM8BR, |
| 165 | ._tmicr = &TM8ICR, | 165 | ._tmicr = &TM8ICR, |
| 166 | .tm_irq = TM8IRQ, | 166 | .tm_irq = TM8IRQ, |
| 167 | .div_timer = MNSCx_DIV_TIMER_16BIT, | 167 | .div_timer = MNSCx_DIV_TIMER_16BIT, |
| 168 | #else /* CONFIG_MN10300_TTYSM0_TIMER2 */ | 168 | #else /* CONFIG_MN10300_TTYSM0_TIMER2 */ |
| 169 | .tm_name = "ttySM0/Timer2", | 169 | .tm_name = "ttySM0:Timer2", |
| 170 | ._tmxmd = &TM2MD, | 170 | ._tmxmd = &TM2MD, |
| 171 | ._tmxbr = (volatile u16 *) &TM2BR, | 171 | ._tmxbr = (volatile u16 *) &TM2BR, |
| 172 | ._tmicr = &TM2ICR, | 172 | ._tmicr = &TM2ICR, |
| @@ -209,17 +209,17 @@ struct mn10300_serial_port mn10300_serial_port_sif1 = { | |||
| 209 | ._intr = &SC1ICR, | 209 | ._intr = &SC1ICR, |
| 210 | ._rxb = &SC1RXB, | 210 | ._rxb = &SC1RXB, |
| 211 | ._txb = &SC1TXB, | 211 | ._txb = &SC1TXB, |
| 212 | .rx_name = "ttySM1/Rx", | 212 | .rx_name = "ttySM1:Rx", |
| 213 | .tx_name = "ttySM1/Tx", | 213 | .tx_name = "ttySM1:Tx", |
| 214 | #ifdef CONFIG_MN10300_TTYSM1_TIMER9 | 214 | #ifdef CONFIG_MN10300_TTYSM1_TIMER9 |
| 215 | .tm_name = "ttySM1/Timer9", | 215 | .tm_name = "ttySM1:Timer9", |
| 216 | ._tmxmd = &TM9MD, | 216 | ._tmxmd = &TM9MD, |
| 217 | ._tmxbr = &TM9BR, | 217 | ._tmxbr = &TM9BR, |
| 218 | ._tmicr = &TM9ICR, | 218 | ._tmicr = &TM9ICR, |
| 219 | .tm_irq = TM9IRQ, | 219 | .tm_irq = TM9IRQ, |
| 220 | .div_timer = MNSCx_DIV_TIMER_16BIT, | 220 | .div_timer = MNSCx_DIV_TIMER_16BIT, |
| 221 | #else /* CONFIG_MN10300_TTYSM1_TIMER3 */ | 221 | #else /* CONFIG_MN10300_TTYSM1_TIMER3 */ |
| 222 | .tm_name = "ttySM1/Timer3", | 222 | .tm_name = "ttySM1:Timer3", |
| 223 | ._tmxmd = &TM3MD, | 223 | ._tmxmd = &TM3MD, |
| 224 | ._tmxbr = (volatile u16 *) &TM3BR, | 224 | ._tmxbr = (volatile u16 *) &TM3BR, |
| 225 | ._tmicr = &TM3ICR, | 225 | ._tmicr = &TM3ICR, |
| @@ -260,9 +260,9 @@ struct mn10300_serial_port mn10300_serial_port_sif2 = { | |||
| 260 | .uart.lock = | 260 | .uart.lock = |
| 261 | __SPIN_LOCK_UNLOCKED(mn10300_serial_port_sif2.uart.lock), | 261 | __SPIN_LOCK_UNLOCKED(mn10300_serial_port_sif2.uart.lock), |
| 262 | .name = "ttySM2", | 262 | .name = "ttySM2", |
| 263 | .rx_name = "ttySM2/Rx", | 263 | .rx_name = "ttySM2:Rx", |
| 264 | .tx_name = "ttySM2/Tx", | 264 | .tx_name = "ttySM2:Tx", |
| 265 | .tm_name = "ttySM2/Timer10", | 265 | .tm_name = "ttySM2:Timer10", |
| 266 | ._iobase = &SC2CTR, | 266 | ._iobase = &SC2CTR, |
| 267 | ._control = &SC2CTR, | 267 | ._control = &SC2CTR, |
| 268 | ._status = &SC2STR, | 268 | ._status = &SC2STR, |
diff --git a/arch/parisc/include/asm/compat.h b/arch/parisc/include/asm/compat.h index 02b77baa5da6..efa0b60c63fe 100644 --- a/arch/parisc/include/asm/compat.h +++ b/arch/parisc/include/asm/compat.h | |||
| @@ -147,7 +147,7 @@ static inline compat_uptr_t ptr_to_compat(void __user *uptr) | |||
| 147 | return (u32)(unsigned long)uptr; | 147 | return (u32)(unsigned long)uptr; |
| 148 | } | 148 | } |
| 149 | 149 | ||
| 150 | static __inline__ void __user *compat_alloc_user_space(long len) | 150 | static __inline__ void __user *arch_compat_alloc_user_space(long len) |
| 151 | { | 151 | { |
| 152 | struct pt_regs *regs = ¤t->thread.regs; | 152 | struct pt_regs *regs = ¤t->thread.regs; |
| 153 | return (void __user *)regs->gr[30]; | 153 | return (void __user *)regs->gr[30]; |
diff --git a/arch/powerpc/include/asm/compat.h b/arch/powerpc/include/asm/compat.h index 396d21a80058..a11d4eac4f97 100644 --- a/arch/powerpc/include/asm/compat.h +++ b/arch/powerpc/include/asm/compat.h | |||
| @@ -134,7 +134,7 @@ static inline compat_uptr_t ptr_to_compat(void __user *uptr) | |||
| 134 | return (u32)(unsigned long)uptr; | 134 | return (u32)(unsigned long)uptr; |
| 135 | } | 135 | } |
| 136 | 136 | ||
| 137 | static inline void __user *compat_alloc_user_space(long len) | 137 | static inline void __user *arch_compat_alloc_user_space(long len) |
| 138 | { | 138 | { |
| 139 | struct pt_regs *regs = current->thread.regs; | 139 | struct pt_regs *regs = current->thread.regs; |
| 140 | unsigned long usp = regs->gpr[1]; | 140 | unsigned long usp = regs->gpr[1]; |
diff --git a/arch/s390/include/asm/compat.h b/arch/s390/include/asm/compat.h index 104f2007f097..a875c2f542e1 100644 --- a/arch/s390/include/asm/compat.h +++ b/arch/s390/include/asm/compat.h | |||
| @@ -181,7 +181,7 @@ static inline int is_compat_task(void) | |||
| 181 | 181 | ||
| 182 | #endif | 182 | #endif |
| 183 | 183 | ||
| 184 | static inline void __user *compat_alloc_user_space(long len) | 184 | static inline void __user *arch_compat_alloc_user_space(long len) |
| 185 | { | 185 | { |
| 186 | unsigned long stack; | 186 | unsigned long stack; |
| 187 | 187 | ||
diff --git a/arch/sparc/include/asm/compat.h b/arch/sparc/include/asm/compat.h index 5016f76ea98a..6f57325bb883 100644 --- a/arch/sparc/include/asm/compat.h +++ b/arch/sparc/include/asm/compat.h | |||
| @@ -167,7 +167,7 @@ static inline compat_uptr_t ptr_to_compat(void __user *uptr) | |||
| 167 | return (u32)(unsigned long)uptr; | 167 | return (u32)(unsigned long)uptr; |
| 168 | } | 168 | } |
| 169 | 169 | ||
| 170 | static inline void __user *compat_alloc_user_space(long len) | 170 | static inline void __user *arch_compat_alloc_user_space(long len) |
| 171 | { | 171 | { |
| 172 | struct pt_regs *regs = current_thread_info()->kregs; | 172 | struct pt_regs *regs = current_thread_info()->kregs; |
| 173 | unsigned long usp = regs->u_regs[UREG_I6]; | 173 | unsigned long usp = regs->u_regs[UREG_I6]; |
diff --git a/arch/tile/include/asm/compat.h b/arch/tile/include/asm/compat.h index 5a34da6cdd79..345d81ce44bb 100644 --- a/arch/tile/include/asm/compat.h +++ b/arch/tile/include/asm/compat.h | |||
| @@ -195,7 +195,7 @@ static inline unsigned long ptr_to_compat_reg(void __user *uptr) | |||
| 195 | return (long)(int)(long __force)uptr; | 195 | return (long)(int)(long __force)uptr; |
| 196 | } | 196 | } |
| 197 | 197 | ||
| 198 | static inline void __user *compat_alloc_user_space(long len) | 198 | static inline void __user *arch_compat_alloc_user_space(long len) |
| 199 | { | 199 | { |
| 200 | struct pt_regs *regs = task_pt_regs(current); | 200 | struct pt_regs *regs = task_pt_regs(current); |
| 201 | return (void __user *)regs->sp - len; | 201 | return (void __user *)regs->sp - len; |
diff --git a/arch/x86/ia32/ia32entry.S b/arch/x86/ia32/ia32entry.S index b86feabed69b..518bb99c3394 100644 --- a/arch/x86/ia32/ia32entry.S +++ b/arch/x86/ia32/ia32entry.S | |||
| @@ -50,7 +50,12 @@ | |||
| 50 | /* | 50 | /* |
| 51 | * Reload arg registers from stack in case ptrace changed them. | 51 | * Reload arg registers from stack in case ptrace changed them. |
| 52 | * We don't reload %eax because syscall_trace_enter() returned | 52 | * We don't reload %eax because syscall_trace_enter() returned |
| 53 | * the value it wants us to use in the table lookup. | 53 | * the %rax value we should see. Instead, we just truncate that |
| 54 | * value to 32 bits again as we did on entry from user mode. | ||
| 55 | * If it's a new value set by user_regset during entry tracing, | ||
| 56 | * this matches the normal truncation of the user-mode value. | ||
| 57 | * If it's -1 to make us punt the syscall, then (u32)-1 is still | ||
| 58 | * an appropriately invalid value. | ||
| 54 | */ | 59 | */ |
| 55 | .macro LOAD_ARGS32 offset, _r9=0 | 60 | .macro LOAD_ARGS32 offset, _r9=0 |
| 56 | .if \_r9 | 61 | .if \_r9 |
| @@ -60,6 +65,7 @@ | |||
| 60 | movl \offset+48(%rsp),%edx | 65 | movl \offset+48(%rsp),%edx |
| 61 | movl \offset+56(%rsp),%esi | 66 | movl \offset+56(%rsp),%esi |
| 62 | movl \offset+64(%rsp),%edi | 67 | movl \offset+64(%rsp),%edi |
| 68 | movl %eax,%eax /* zero extension */ | ||
| 63 | .endm | 69 | .endm |
| 64 | 70 | ||
| 65 | .macro CFI_STARTPROC32 simple | 71 | .macro CFI_STARTPROC32 simple |
| @@ -153,7 +159,7 @@ ENTRY(ia32_sysenter_target) | |||
| 153 | testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%r10) | 159 | testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%r10) |
| 154 | CFI_REMEMBER_STATE | 160 | CFI_REMEMBER_STATE |
| 155 | jnz sysenter_tracesys | 161 | jnz sysenter_tracesys |
| 156 | cmpl $(IA32_NR_syscalls-1),%eax | 162 | cmpq $(IA32_NR_syscalls-1),%rax |
| 157 | ja ia32_badsys | 163 | ja ia32_badsys |
| 158 | sysenter_do_call: | 164 | sysenter_do_call: |
| 159 | IA32_ARG_FIXUP | 165 | IA32_ARG_FIXUP |
| @@ -195,7 +201,7 @@ sysexit_from_sys_call: | |||
| 195 | movl $AUDIT_ARCH_I386,%edi /* 1st arg: audit arch */ | 201 | movl $AUDIT_ARCH_I386,%edi /* 1st arg: audit arch */ |
| 196 | call audit_syscall_entry | 202 | call audit_syscall_entry |
| 197 | movl RAX-ARGOFFSET(%rsp),%eax /* reload syscall number */ | 203 | movl RAX-ARGOFFSET(%rsp),%eax /* reload syscall number */ |
| 198 | cmpl $(IA32_NR_syscalls-1),%eax | 204 | cmpq $(IA32_NR_syscalls-1),%rax |
| 199 | ja ia32_badsys | 205 | ja ia32_badsys |
| 200 | movl %ebx,%edi /* reload 1st syscall arg */ | 206 | movl %ebx,%edi /* reload 1st syscall arg */ |
| 201 | movl RCX-ARGOFFSET(%rsp),%esi /* reload 2nd syscall arg */ | 207 | movl RCX-ARGOFFSET(%rsp),%esi /* reload 2nd syscall arg */ |
| @@ -248,7 +254,7 @@ sysenter_tracesys: | |||
| 248 | call syscall_trace_enter | 254 | call syscall_trace_enter |
| 249 | LOAD_ARGS32 ARGOFFSET /* reload args from stack in case ptrace changed it */ | 255 | LOAD_ARGS32 ARGOFFSET /* reload args from stack in case ptrace changed it */ |
| 250 | RESTORE_REST | 256 | RESTORE_REST |
| 251 | cmpl $(IA32_NR_syscalls-1),%eax | 257 | cmpq $(IA32_NR_syscalls-1),%rax |
| 252 | ja int_ret_from_sys_call /* sysenter_tracesys has set RAX(%rsp) */ | 258 | ja int_ret_from_sys_call /* sysenter_tracesys has set RAX(%rsp) */ |
| 253 | jmp sysenter_do_call | 259 | jmp sysenter_do_call |
| 254 | CFI_ENDPROC | 260 | CFI_ENDPROC |
| @@ -314,7 +320,7 @@ ENTRY(ia32_cstar_target) | |||
| 314 | testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%r10) | 320 | testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%r10) |
| 315 | CFI_REMEMBER_STATE | 321 | CFI_REMEMBER_STATE |
| 316 | jnz cstar_tracesys | 322 | jnz cstar_tracesys |
| 317 | cmpl $IA32_NR_syscalls-1,%eax | 323 | cmpq $IA32_NR_syscalls-1,%rax |
| 318 | ja ia32_badsys | 324 | ja ia32_badsys |
| 319 | cstar_do_call: | 325 | cstar_do_call: |
| 320 | IA32_ARG_FIXUP 1 | 326 | IA32_ARG_FIXUP 1 |
| @@ -367,7 +373,7 @@ cstar_tracesys: | |||
| 367 | LOAD_ARGS32 ARGOFFSET, 1 /* reload args from stack in case ptrace changed it */ | 373 | LOAD_ARGS32 ARGOFFSET, 1 /* reload args from stack in case ptrace changed it */ |
| 368 | RESTORE_REST | 374 | RESTORE_REST |
| 369 | xchgl %ebp,%r9d | 375 | xchgl %ebp,%r9d |
| 370 | cmpl $(IA32_NR_syscalls-1),%eax | 376 | cmpq $(IA32_NR_syscalls-1),%rax |
| 371 | ja int_ret_from_sys_call /* cstar_tracesys has set RAX(%rsp) */ | 377 | ja int_ret_from_sys_call /* cstar_tracesys has set RAX(%rsp) */ |
| 372 | jmp cstar_do_call | 378 | jmp cstar_do_call |
| 373 | END(ia32_cstar_target) | 379 | END(ia32_cstar_target) |
| @@ -425,7 +431,7 @@ ENTRY(ia32_syscall) | |||
| 425 | orl $TS_COMPAT,TI_status(%r10) | 431 | orl $TS_COMPAT,TI_status(%r10) |
| 426 | testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%r10) | 432 | testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%r10) |
| 427 | jnz ia32_tracesys | 433 | jnz ia32_tracesys |
| 428 | cmpl $(IA32_NR_syscalls-1),%eax | 434 | cmpq $(IA32_NR_syscalls-1),%rax |
| 429 | ja ia32_badsys | 435 | ja ia32_badsys |
| 430 | ia32_do_call: | 436 | ia32_do_call: |
| 431 | IA32_ARG_FIXUP | 437 | IA32_ARG_FIXUP |
| @@ -444,7 +450,7 @@ ia32_tracesys: | |||
| 444 | call syscall_trace_enter | 450 | call syscall_trace_enter |
| 445 | LOAD_ARGS32 ARGOFFSET /* reload args from stack in case ptrace changed it */ | 451 | LOAD_ARGS32 ARGOFFSET /* reload args from stack in case ptrace changed it */ |
| 446 | RESTORE_REST | 452 | RESTORE_REST |
| 447 | cmpl $(IA32_NR_syscalls-1),%eax | 453 | cmpq $(IA32_NR_syscalls-1),%rax |
| 448 | ja int_ret_from_sys_call /* ia32_tracesys has set RAX(%rsp) */ | 454 | ja int_ret_from_sys_call /* ia32_tracesys has set RAX(%rsp) */ |
| 449 | jmp ia32_do_call | 455 | jmp ia32_do_call |
| 450 | END(ia32_syscall) | 456 | END(ia32_syscall) |
diff --git a/arch/x86/include/asm/compat.h b/arch/x86/include/asm/compat.h index 306160e58b48..1d9cd27c2920 100644 --- a/arch/x86/include/asm/compat.h +++ b/arch/x86/include/asm/compat.h | |||
| @@ -205,7 +205,7 @@ static inline compat_uptr_t ptr_to_compat(void __user *uptr) | |||
| 205 | return (u32)(unsigned long)uptr; | 205 | return (u32)(unsigned long)uptr; |
| 206 | } | 206 | } |
| 207 | 207 | ||
| 208 | static inline void __user *compat_alloc_user_space(long len) | 208 | static inline void __user *arch_compat_alloc_user_space(long len) |
| 209 | { | 209 | { |
| 210 | struct pt_regs *regs = task_pt_regs(current); | 210 | struct pt_regs *regs = task_pt_regs(current); |
| 211 | return (void __user *)regs->sp - len; | 211 | return (void __user *)regs->sp - len; |
diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c index d2ab01e90a96..dcbeb98f195a 100644 --- a/drivers/gpu/drm/drm_crtc_helper.c +++ b/drivers/gpu/drm/drm_crtc_helper.c | |||
| @@ -103,8 +103,8 @@ int drm_helper_probe_single_connector_modes(struct drm_connector *connector, | |||
| 103 | if (connector->funcs->force) | 103 | if (connector->funcs->force) |
| 104 | connector->funcs->force(connector); | 104 | connector->funcs->force(connector); |
| 105 | } else { | 105 | } else { |
| 106 | connector->status = connector->funcs->detect(connector); | 106 | connector->status = connector->funcs->detect(connector, true); |
| 107 | drm_helper_hpd_irq_event(dev); | 107 | drm_kms_helper_poll_enable(dev); |
| 108 | } | 108 | } |
| 109 | 109 | ||
| 110 | if (connector->status == connector_status_disconnected) { | 110 | if (connector->status == connector_status_disconnected) { |
| @@ -637,13 +637,13 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set) | |||
| 637 | mode_changed = true; | 637 | mode_changed = true; |
| 638 | 638 | ||
| 639 | if (mode_changed) { | 639 | if (mode_changed) { |
| 640 | old_fb = set->crtc->fb; | ||
| 641 | set->crtc->fb = set->fb; | ||
| 642 | set->crtc->enabled = (set->mode != NULL); | 640 | set->crtc->enabled = (set->mode != NULL); |
| 643 | if (set->mode != NULL) { | 641 | if (set->mode != NULL) { |
| 644 | DRM_DEBUG_KMS("attempting to set mode from" | 642 | DRM_DEBUG_KMS("attempting to set mode from" |
| 645 | " userspace\n"); | 643 | " userspace\n"); |
| 646 | drm_mode_debug_printmodeline(set->mode); | 644 | drm_mode_debug_printmodeline(set->mode); |
| 645 | old_fb = set->crtc->fb; | ||
| 646 | set->crtc->fb = set->fb; | ||
| 647 | if (!drm_crtc_helper_set_mode(set->crtc, set->mode, | 647 | if (!drm_crtc_helper_set_mode(set->crtc, set->mode, |
| 648 | set->x, set->y, | 648 | set->x, set->y, |
| 649 | old_fb)) { | 649 | old_fb)) { |
| @@ -866,7 +866,7 @@ static void output_poll_execute(struct work_struct *work) | |||
| 866 | !(connector->polled & DRM_CONNECTOR_POLL_HPD)) | 866 | !(connector->polled & DRM_CONNECTOR_POLL_HPD)) |
| 867 | continue; | 867 | continue; |
| 868 | 868 | ||
| 869 | status = connector->funcs->detect(connector); | 869 | status = connector->funcs->detect(connector, false); |
| 870 | if (old_status != status) | 870 | if (old_status != status) |
| 871 | changed = true; | 871 | changed = true; |
| 872 | } | 872 | } |
diff --git a/drivers/gpu/drm/drm_pci.c b/drivers/gpu/drm/drm_pci.c index e20f78b542a7..f5bd9e590c80 100644 --- a/drivers/gpu/drm/drm_pci.c +++ b/drivers/gpu/drm/drm_pci.c | |||
| @@ -164,6 +164,8 @@ int drm_get_pci_dev(struct pci_dev *pdev, const struct pci_device_id *ent, | |||
| 164 | dev->hose = pdev->sysdata; | 164 | dev->hose = pdev->sysdata; |
| 165 | #endif | 165 | #endif |
| 166 | 166 | ||
| 167 | mutex_lock(&drm_global_mutex); | ||
| 168 | |||
| 167 | if ((ret = drm_fill_in_dev(dev, ent, driver))) { | 169 | if ((ret = drm_fill_in_dev(dev, ent, driver))) { |
| 168 | printk(KERN_ERR "DRM: Fill_in_dev failed.\n"); | 170 | printk(KERN_ERR "DRM: Fill_in_dev failed.\n"); |
| 169 | goto err_g2; | 171 | goto err_g2; |
| @@ -199,6 +201,7 @@ int drm_get_pci_dev(struct pci_dev *pdev, const struct pci_device_id *ent, | |||
| 199 | driver->name, driver->major, driver->minor, driver->patchlevel, | 201 | driver->name, driver->major, driver->minor, driver->patchlevel, |
| 200 | driver->date, pci_name(pdev), dev->primary->index); | 202 | driver->date, pci_name(pdev), dev->primary->index); |
| 201 | 203 | ||
| 204 | mutex_unlock(&drm_global_mutex); | ||
| 202 | return 0; | 205 | return 0; |
| 203 | 206 | ||
| 204 | err_g4: | 207 | err_g4: |
| @@ -210,6 +213,7 @@ err_g2: | |||
| 210 | pci_disable_device(pdev); | 213 | pci_disable_device(pdev); |
| 211 | err_g1: | 214 | err_g1: |
| 212 | kfree(dev); | 215 | kfree(dev); |
| 216 | mutex_unlock(&drm_global_mutex); | ||
| 213 | return ret; | 217 | return ret; |
| 214 | } | 218 | } |
| 215 | EXPORT_SYMBOL(drm_get_pci_dev); | 219 | EXPORT_SYMBOL(drm_get_pci_dev); |
diff --git a/drivers/gpu/drm/drm_platform.c b/drivers/gpu/drm/drm_platform.c index 460e9a3afa8d..92d1d0fb7b75 100644 --- a/drivers/gpu/drm/drm_platform.c +++ b/drivers/gpu/drm/drm_platform.c | |||
| @@ -53,6 +53,8 @@ int drm_get_platform_dev(struct platform_device *platdev, | |||
| 53 | dev->platformdev = platdev; | 53 | dev->platformdev = platdev; |
| 54 | dev->dev = &platdev->dev; | 54 | dev->dev = &platdev->dev; |
| 55 | 55 | ||
| 56 | mutex_lock(&drm_global_mutex); | ||
| 57 | |||
| 56 | ret = drm_fill_in_dev(dev, NULL, driver); | 58 | ret = drm_fill_in_dev(dev, NULL, driver); |
| 57 | 59 | ||
| 58 | if (ret) { | 60 | if (ret) { |
| @@ -87,6 +89,8 @@ int drm_get_platform_dev(struct platform_device *platdev, | |||
| 87 | 89 | ||
| 88 | list_add_tail(&dev->driver_item, &driver->device_list); | 90 | list_add_tail(&dev->driver_item, &driver->device_list); |
| 89 | 91 | ||
| 92 | mutex_unlock(&drm_global_mutex); | ||
| 93 | |||
| 90 | DRM_INFO("Initialized %s %d.%d.%d %s on minor %d\n", | 94 | DRM_INFO("Initialized %s %d.%d.%d %s on minor %d\n", |
| 91 | driver->name, driver->major, driver->minor, driver->patchlevel, | 95 | driver->name, driver->major, driver->minor, driver->patchlevel, |
| 92 | driver->date, dev->primary->index); | 96 | driver->date, dev->primary->index); |
| @@ -100,6 +104,7 @@ err_g2: | |||
| 100 | drm_put_minor(&dev->control); | 104 | drm_put_minor(&dev->control); |
| 101 | err_g1: | 105 | err_g1: |
| 102 | kfree(dev); | 106 | kfree(dev); |
| 107 | mutex_unlock(&drm_global_mutex); | ||
| 103 | return ret; | 108 | return ret; |
| 104 | } | 109 | } |
| 105 | EXPORT_SYMBOL(drm_get_platform_dev); | 110 | EXPORT_SYMBOL(drm_get_platform_dev); |
diff --git a/drivers/gpu/drm/drm_sysfs.c b/drivers/gpu/drm/drm_sysfs.c index 86118a742231..85da4c40694c 100644 --- a/drivers/gpu/drm/drm_sysfs.c +++ b/drivers/gpu/drm/drm_sysfs.c | |||
| @@ -159,7 +159,7 @@ static ssize_t status_show(struct device *device, | |||
| 159 | struct drm_connector *connector = to_drm_connector(device); | 159 | struct drm_connector *connector = to_drm_connector(device); |
| 160 | enum drm_connector_status status; | 160 | enum drm_connector_status status; |
| 161 | 161 | ||
| 162 | status = connector->funcs->detect(connector); | 162 | status = connector->funcs->detect(connector, true); |
| 163 | return snprintf(buf, PAGE_SIZE, "%s\n", | 163 | return snprintf(buf, PAGE_SIZE, "%s\n", |
| 164 | drm_get_connector_status_name(status)); | 164 | drm_get_connector_status_name(status)); |
| 165 | } | 165 | } |
diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c index 4b7735196cd5..a02a8df73727 100644 --- a/drivers/gpu/drm/i915/intel_crt.c +++ b/drivers/gpu/drm/i915/intel_crt.c | |||
| @@ -400,7 +400,8 @@ intel_crt_load_detect(struct drm_crtc *crtc, struct intel_encoder *intel_encoder | |||
| 400 | return status; | 400 | return status; |
| 401 | } | 401 | } |
| 402 | 402 | ||
| 403 | static enum drm_connector_status intel_crt_detect(struct drm_connector *connector) | 403 | static enum drm_connector_status |
| 404 | intel_crt_detect(struct drm_connector *connector, bool force) | ||
| 404 | { | 405 | { |
| 405 | struct drm_device *dev = connector->dev; | 406 | struct drm_device *dev = connector->dev; |
| 406 | struct drm_encoder *encoder = intel_attached_encoder(connector); | 407 | struct drm_encoder *encoder = intel_attached_encoder(connector); |
| @@ -419,6 +420,9 @@ static enum drm_connector_status intel_crt_detect(struct drm_connector *connecto | |||
| 419 | if (intel_crt_detect_ddc(encoder)) | 420 | if (intel_crt_detect_ddc(encoder)) |
| 420 | return connector_status_connected; | 421 | return connector_status_connected; |
| 421 | 422 | ||
| 423 | if (!force) | ||
| 424 | return connector->status; | ||
| 425 | |||
| 422 | /* for pre-945g platforms use load detect */ | 426 | /* for pre-945g platforms use load detect */ |
| 423 | if (encoder->crtc && encoder->crtc->enabled) { | 427 | if (encoder->crtc && encoder->crtc->enabled) { |
| 424 | status = intel_crt_load_detect(encoder->crtc, intel_encoder); | 428 | status = intel_crt_load_detect(encoder->crtc, intel_encoder); |
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 51d142939a26..1a51ee07de3e 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c | |||
| @@ -1386,7 +1386,7 @@ ironlake_dp_detect(struct drm_connector *connector) | |||
| 1386 | * \return false if DP port is disconnected. | 1386 | * \return false if DP port is disconnected. |
| 1387 | */ | 1387 | */ |
| 1388 | static enum drm_connector_status | 1388 | static enum drm_connector_status |
| 1389 | intel_dp_detect(struct drm_connector *connector) | 1389 | intel_dp_detect(struct drm_connector *connector, bool force) |
| 1390 | { | 1390 | { |
| 1391 | struct drm_encoder *encoder = intel_attached_encoder(connector); | 1391 | struct drm_encoder *encoder = intel_attached_encoder(connector); |
| 1392 | struct intel_dp *intel_dp = enc_to_intel_dp(encoder); | 1392 | struct intel_dp *intel_dp = enc_to_intel_dp(encoder); |
diff --git a/drivers/gpu/drm/i915/intel_dvo.c b/drivers/gpu/drm/i915/intel_dvo.c index a399f4b2c1c5..7c9ec1472d46 100644 --- a/drivers/gpu/drm/i915/intel_dvo.c +++ b/drivers/gpu/drm/i915/intel_dvo.c | |||
| @@ -221,7 +221,8 @@ static void intel_dvo_mode_set(struct drm_encoder *encoder, | |||
| 221 | * | 221 | * |
| 222 | * Unimplemented. | 222 | * Unimplemented. |
| 223 | */ | 223 | */ |
| 224 | static enum drm_connector_status intel_dvo_detect(struct drm_connector *connector) | 224 | static enum drm_connector_status |
| 225 | intel_dvo_detect(struct drm_connector *connector, bool force) | ||
| 225 | { | 226 | { |
| 226 | struct drm_encoder *encoder = intel_attached_encoder(connector); | 227 | struct drm_encoder *encoder = intel_attached_encoder(connector); |
| 227 | struct intel_dvo *intel_dvo = enc_to_intel_dvo(encoder); | 228 | struct intel_dvo *intel_dvo = enc_to_intel_dvo(encoder); |
diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c index ccd4c97e6524..926934a482ec 100644 --- a/drivers/gpu/drm/i915/intel_hdmi.c +++ b/drivers/gpu/drm/i915/intel_hdmi.c | |||
| @@ -139,7 +139,7 @@ static bool intel_hdmi_mode_fixup(struct drm_encoder *encoder, | |||
| 139 | } | 139 | } |
| 140 | 140 | ||
| 141 | static enum drm_connector_status | 141 | static enum drm_connector_status |
| 142 | intel_hdmi_detect(struct drm_connector *connector) | 142 | intel_hdmi_detect(struct drm_connector *connector, bool force) |
| 143 | { | 143 | { |
| 144 | struct drm_encoder *encoder = intel_attached_encoder(connector); | 144 | struct drm_encoder *encoder = intel_attached_encoder(connector); |
| 145 | struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder); | 145 | struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder); |
diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c index 4fbb0165b26f..6ec39a86ed06 100644 --- a/drivers/gpu/drm/i915/intel_lvds.c +++ b/drivers/gpu/drm/i915/intel_lvds.c | |||
| @@ -445,7 +445,8 @@ static void intel_lvds_mode_set(struct drm_encoder *encoder, | |||
| 445 | * connected and closed means disconnected. We also send hotplug events as | 445 | * connected and closed means disconnected. We also send hotplug events as |
| 446 | * needed, using lid status notification from the input layer. | 446 | * needed, using lid status notification from the input layer. |
| 447 | */ | 447 | */ |
| 448 | static enum drm_connector_status intel_lvds_detect(struct drm_connector *connector) | 448 | static enum drm_connector_status |
| 449 | intel_lvds_detect(struct drm_connector *connector, bool force) | ||
| 449 | { | 450 | { |
| 450 | struct drm_device *dev = connector->dev; | 451 | struct drm_device *dev = connector->dev; |
| 451 | enum drm_connector_status status = connector_status_connected; | 452 | enum drm_connector_status status = connector_status_connected; |
| @@ -540,7 +541,9 @@ static int intel_lid_notify(struct notifier_block *nb, unsigned long val, | |||
| 540 | * the LID nofication event. | 541 | * the LID nofication event. |
| 541 | */ | 542 | */ |
| 542 | if (connector) | 543 | if (connector) |
| 543 | connector->status = connector->funcs->detect(connector); | 544 | connector->status = connector->funcs->detect(connector, |
| 545 | false); | ||
| 546 | |||
| 544 | /* Don't force modeset on machines where it causes a GPU lockup */ | 547 | /* Don't force modeset on machines where it causes a GPU lockup */ |
| 545 | if (dmi_check_system(intel_no_modeset_on_lid)) | 548 | if (dmi_check_system(intel_no_modeset_on_lid)) |
| 546 | return NOTIFY_OK; | 549 | return NOTIFY_OK; |
diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c index e3b7a7ee39cb..e8e902d614ed 100644 --- a/drivers/gpu/drm/i915/intel_sdvo.c +++ b/drivers/gpu/drm/i915/intel_sdvo.c | |||
| @@ -1417,7 +1417,7 @@ intel_analog_is_connected(struct drm_device *dev) | |||
| 1417 | if (!analog_connector) | 1417 | if (!analog_connector) |
| 1418 | return false; | 1418 | return false; |
| 1419 | 1419 | ||
| 1420 | if (analog_connector->funcs->detect(analog_connector) == | 1420 | if (analog_connector->funcs->detect(analog_connector, false) == |
| 1421 | connector_status_disconnected) | 1421 | connector_status_disconnected) |
| 1422 | return false; | 1422 | return false; |
| 1423 | 1423 | ||
| @@ -1486,7 +1486,8 @@ intel_sdvo_hdmi_sink_detect(struct drm_connector *connector) | |||
| 1486 | return status; | 1486 | return status; |
| 1487 | } | 1487 | } |
| 1488 | 1488 | ||
| 1489 | static enum drm_connector_status intel_sdvo_detect(struct drm_connector *connector) | 1489 | static enum drm_connector_status |
| 1490 | intel_sdvo_detect(struct drm_connector *connector, bool force) | ||
| 1490 | { | 1491 | { |
| 1491 | uint16_t response; | 1492 | uint16_t response; |
| 1492 | struct drm_encoder *encoder = intel_attached_encoder(connector); | 1493 | struct drm_encoder *encoder = intel_attached_encoder(connector); |
diff --git a/drivers/gpu/drm/i915/intel_tv.c b/drivers/gpu/drm/i915/intel_tv.c index c671f60ce80b..4a117e318a73 100644 --- a/drivers/gpu/drm/i915/intel_tv.c +++ b/drivers/gpu/drm/i915/intel_tv.c | |||
| @@ -1341,7 +1341,7 @@ static void intel_tv_find_better_format(struct drm_connector *connector) | |||
| 1341 | * we have a pipe programmed in order to probe the TV. | 1341 | * we have a pipe programmed in order to probe the TV. |
| 1342 | */ | 1342 | */ |
| 1343 | static enum drm_connector_status | 1343 | static enum drm_connector_status |
| 1344 | intel_tv_detect(struct drm_connector *connector) | 1344 | intel_tv_detect(struct drm_connector *connector, bool force) |
| 1345 | { | 1345 | { |
| 1346 | struct drm_display_mode mode; | 1346 | struct drm_display_mode mode; |
| 1347 | struct drm_encoder *encoder = intel_attached_encoder(connector); | 1347 | struct drm_encoder *encoder = intel_attached_encoder(connector); |
| @@ -1353,7 +1353,7 @@ intel_tv_detect(struct drm_connector *connector) | |||
| 1353 | 1353 | ||
| 1354 | if (encoder->crtc && encoder->crtc->enabled) { | 1354 | if (encoder->crtc && encoder->crtc->enabled) { |
| 1355 | type = intel_tv_detect_type(intel_tv); | 1355 | type = intel_tv_detect_type(intel_tv); |
| 1356 | } else { | 1356 | } else if (force) { |
| 1357 | struct drm_crtc *crtc; | 1357 | struct drm_crtc *crtc; |
| 1358 | int dpms_mode; | 1358 | int dpms_mode; |
| 1359 | 1359 | ||
| @@ -1364,10 +1364,9 @@ intel_tv_detect(struct drm_connector *connector) | |||
| 1364 | intel_release_load_detect_pipe(&intel_tv->base, connector, | 1364 | intel_release_load_detect_pipe(&intel_tv->base, connector, |
| 1365 | dpms_mode); | 1365 | dpms_mode); |
| 1366 | } else | 1366 | } else |
| 1367 | type = -1; | 1367 | return connector_status_unknown; |
| 1368 | } | 1368 | } else |
| 1369 | 1369 | return connector->status; | |
| 1370 | intel_tv->type = type; | ||
| 1371 | 1370 | ||
| 1372 | if (type < 0) | 1371 | if (type < 0) |
| 1373 | return connector_status_disconnected; | 1372 | return connector_status_disconnected; |
diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c index a1473fff06ac..87186a4bbf03 100644 --- a/drivers/gpu/drm/nouveau/nouveau_connector.c +++ b/drivers/gpu/drm/nouveau/nouveau_connector.c | |||
| @@ -168,7 +168,7 @@ nouveau_connector_set_encoder(struct drm_connector *connector, | |||
| 168 | } | 168 | } |
| 169 | 169 | ||
| 170 | static enum drm_connector_status | 170 | static enum drm_connector_status |
| 171 | nouveau_connector_detect(struct drm_connector *connector) | 171 | nouveau_connector_detect(struct drm_connector *connector, bool force) |
| 172 | { | 172 | { |
| 173 | struct drm_device *dev = connector->dev; | 173 | struct drm_device *dev = connector->dev; |
| 174 | struct nouveau_connector *nv_connector = nouveau_connector(connector); | 174 | struct nouveau_connector *nv_connector = nouveau_connector(connector); |
| @@ -246,7 +246,7 @@ detect_analog: | |||
| 246 | } | 246 | } |
| 247 | 247 | ||
| 248 | static enum drm_connector_status | 248 | static enum drm_connector_status |
| 249 | nouveau_connector_detect_lvds(struct drm_connector *connector) | 249 | nouveau_connector_detect_lvds(struct drm_connector *connector, bool force) |
| 250 | { | 250 | { |
| 251 | struct drm_device *dev = connector->dev; | 251 | struct drm_device *dev = connector->dev; |
| 252 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 252 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
| @@ -267,7 +267,7 @@ nouveau_connector_detect_lvds(struct drm_connector *connector) | |||
| 267 | 267 | ||
| 268 | /* Try retrieving EDID via DDC */ | 268 | /* Try retrieving EDID via DDC */ |
| 269 | if (!dev_priv->vbios.fp_no_ddc) { | 269 | if (!dev_priv->vbios.fp_no_ddc) { |
| 270 | status = nouveau_connector_detect(connector); | 270 | status = nouveau_connector_detect(connector, force); |
| 271 | if (status == connector_status_connected) | 271 | if (status == connector_status_connected) |
| 272 | goto out; | 272 | goto out; |
| 273 | } | 273 | } |
diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c index 464a81a1990f..cd0290f946cf 100644 --- a/drivers/gpu/drm/radeon/atombios_crtc.c +++ b/drivers/gpu/drm/radeon/atombios_crtc.c | |||
| @@ -539,14 +539,15 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc, | |||
| 539 | pll->algo = PLL_ALGO_LEGACY; | 539 | pll->algo = PLL_ALGO_LEGACY; |
| 540 | pll->flags |= RADEON_PLL_PREFER_CLOSEST_LOWER; | 540 | pll->flags |= RADEON_PLL_PREFER_CLOSEST_LOWER; |
| 541 | } | 541 | } |
| 542 | /* There is some evidence (often anecdotal) that RV515 LVDS | 542 | /* There is some evidence (often anecdotal) that RV515/RV620 LVDS |
| 543 | * (on some boards at least) prefers the legacy algo. I'm not | 543 | * (on some boards at least) prefers the legacy algo. I'm not |
| 544 | * sure whether this should handled generically or on a | 544 | * sure whether this should handled generically or on a |
| 545 | * case-by-case quirk basis. Both algos should work fine in the | 545 | * case-by-case quirk basis. Both algos should work fine in the |
| 546 | * majority of cases. | 546 | * majority of cases. |
| 547 | */ | 547 | */ |
| 548 | if ((radeon_encoder->active_device & (ATOM_DEVICE_LCD_SUPPORT)) && | 548 | if ((radeon_encoder->active_device & (ATOM_DEVICE_LCD_SUPPORT)) && |
| 549 | (rdev->family == CHIP_RV515)) { | 549 | ((rdev->family == CHIP_RV515) || |
| 550 | (rdev->family == CHIP_RV620))) { | ||
| 550 | /* allow the user to overrride just in case */ | 551 | /* allow the user to overrride just in case */ |
| 551 | if (radeon_new_pll == 1) | 552 | if (radeon_new_pll == 1) |
| 552 | pll->algo = PLL_ALGO_NEW; | 553 | pll->algo = PLL_ALGO_NEW; |
diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c index b8b7f010b25f..79082d4398ae 100644 --- a/drivers/gpu/drm/radeon/evergreen.c +++ b/drivers/gpu/drm/radeon/evergreen.c | |||
| @@ -1160,14 +1160,25 @@ static void evergreen_gpu_init(struct radeon_device *rdev) | |||
| 1160 | EVERGREEN_MAX_BACKENDS_MASK)); | 1160 | EVERGREEN_MAX_BACKENDS_MASK)); |
| 1161 | break; | 1161 | break; |
| 1162 | } | 1162 | } |
| 1163 | } else | 1163 | } else { |
| 1164 | gb_backend_map = | 1164 | switch (rdev->family) { |
| 1165 | evergreen_get_tile_pipe_to_backend_map(rdev, | 1165 | case CHIP_CYPRESS: |
| 1166 | rdev->config.evergreen.max_tile_pipes, | 1166 | case CHIP_HEMLOCK: |
| 1167 | rdev->config.evergreen.max_backends, | 1167 | gb_backend_map = 0x66442200; |
| 1168 | ((EVERGREEN_MAX_BACKENDS_MASK << | 1168 | break; |
| 1169 | rdev->config.evergreen.max_backends) & | 1169 | case CHIP_JUNIPER: |
| 1170 | EVERGREEN_MAX_BACKENDS_MASK)); | 1170 | gb_backend_map = 0x00006420; |
| 1171 | break; | ||
| 1172 | default: | ||
| 1173 | gb_backend_map = | ||
| 1174 | evergreen_get_tile_pipe_to_backend_map(rdev, | ||
| 1175 | rdev->config.evergreen.max_tile_pipes, | ||
| 1176 | rdev->config.evergreen.max_backends, | ||
| 1177 | ((EVERGREEN_MAX_BACKENDS_MASK << | ||
| 1178 | rdev->config.evergreen.max_backends) & | ||
| 1179 | EVERGREEN_MAX_BACKENDS_MASK)); | ||
| 1180 | } | ||
| 1181 | } | ||
| 1171 | 1182 | ||
| 1172 | rdev->config.evergreen.tile_config = gb_addr_config; | 1183 | rdev->config.evergreen.tile_config = gb_addr_config; |
| 1173 | WREG32(GB_BACKEND_MAP, gb_backend_map); | 1184 | WREG32(GB_BACKEND_MAP, gb_backend_map); |
diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c index e817a0bb5eb4..e151f16a8f86 100644 --- a/drivers/gpu/drm/radeon/r100.c +++ b/drivers/gpu/drm/radeon/r100.c | |||
| @@ -2020,18 +2020,7 @@ bool r100_gpu_cp_is_lockup(struct radeon_device *rdev, struct r100_gpu_lockup *l | |||
| 2020 | return false; | 2020 | return false; |
| 2021 | } | 2021 | } |
| 2022 | elapsed = jiffies_to_msecs(cjiffies - lockup->last_jiffies); | 2022 | elapsed = jiffies_to_msecs(cjiffies - lockup->last_jiffies); |
| 2023 | if (elapsed >= 3000) { | 2023 | if (elapsed >= 10000) { |
| 2024 | /* very likely the improbable case where current | ||
| 2025 | * rptr is equal to last recorded, a while ago, rptr | ||
| 2026 | * this is more likely a false positive update tracking | ||
| 2027 | * information which should force us to be recall at | ||
| 2028 | * latter point | ||
| 2029 | */ | ||
| 2030 | lockup->last_cp_rptr = cp->rptr; | ||
| 2031 | lockup->last_jiffies = jiffies; | ||
| 2032 | return false; | ||
| 2033 | } | ||
| 2034 | if (elapsed >= 1000) { | ||
| 2035 | dev_err(rdev->dev, "GPU lockup CP stall for more than %lumsec\n", elapsed); | 2024 | dev_err(rdev->dev, "GPU lockup CP stall for more than %lumsec\n", elapsed); |
| 2036 | return true; | 2025 | return true; |
| 2037 | } | 2026 | } |
| @@ -3308,13 +3297,14 @@ int r100_cs_track_check(struct radeon_device *rdev, struct r100_cs_track *track) | |||
| 3308 | unsigned long size; | 3297 | unsigned long size; |
| 3309 | unsigned prim_walk; | 3298 | unsigned prim_walk; |
| 3310 | unsigned nverts; | 3299 | unsigned nverts; |
| 3300 | unsigned num_cb = track->num_cb; | ||
| 3311 | 3301 | ||
| 3312 | for (i = 0; i < track->num_cb; i++) { | 3302 | if (!track->zb_cb_clear && !track->color_channel_mask && |
| 3303 | !track->blend_read_enable) | ||
| 3304 | num_cb = 0; | ||
| 3305 | |||
| 3306 | for (i = 0; i < num_cb; i++) { | ||
| 3313 | if (track->cb[i].robj == NULL) { | 3307 | if (track->cb[i].robj == NULL) { |
| 3314 | if (!(track->zb_cb_clear || track->color_channel_mask || | ||
| 3315 | track->blend_read_enable)) { | ||
| 3316 | continue; | ||
| 3317 | } | ||
| 3318 | DRM_ERROR("[drm] No buffer for color buffer %d !\n", i); | 3308 | DRM_ERROR("[drm] No buffer for color buffer %d !\n", i); |
| 3319 | return -EINVAL; | 3309 | return -EINVAL; |
| 3320 | } | 3310 | } |
diff --git a/drivers/gpu/drm/radeon/r600_blit_kms.c b/drivers/gpu/drm/radeon/r600_blit_kms.c index d13622ae74e9..9ceb2a1ce799 100644 --- a/drivers/gpu/drm/radeon/r600_blit_kms.c +++ b/drivers/gpu/drm/radeon/r600_blit_kms.c | |||
| @@ -1,3 +1,28 @@ | |||
| 1 | /* | ||
| 2 | * Copyright 2009 Advanced Micro Devices, Inc. | ||
| 3 | * Copyright 2009 Red Hat Inc. | ||
| 4 | * | ||
| 5 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
| 6 | * copy of this software and associated documentation files (the "Software"), | ||
| 7 | * to deal in the Software without restriction, including without limitation | ||
| 8 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
| 9 | * and/or sell copies of the Software, and to permit persons to whom the | ||
| 10 | * Software is furnished to do so, subject to the following conditions: | ||
| 11 | * | ||
| 12 | * The above copyright notice and this permission notice (including the next | ||
| 13 | * paragraph) shall be included in all copies or substantial portions of the | ||
| 14 | * Software. | ||
| 15 | * | ||
| 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
| 19 | * THE COPYRIGHT HOLDER(S) AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR | ||
| 20 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | ||
| 21 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | ||
| 22 | * DEALINGS IN THE SOFTWARE. | ||
| 23 | * | ||
| 24 | */ | ||
| 25 | |||
| 1 | #include "drmP.h" | 26 | #include "drmP.h" |
| 2 | #include "drm.h" | 27 | #include "drm.h" |
| 3 | #include "radeon_drm.h" | 28 | #include "radeon_drm.h" |
diff --git a/drivers/gpu/drm/radeon/r600_blit_shaders.h b/drivers/gpu/drm/radeon/r600_blit_shaders.h index fdc3b378cbb0..f437d36dd98c 100644 --- a/drivers/gpu/drm/radeon/r600_blit_shaders.h +++ b/drivers/gpu/drm/radeon/r600_blit_shaders.h | |||
| @@ -1,3 +1,27 @@ | |||
| 1 | /* | ||
| 2 | * Copyright 2009 Advanced Micro Devices, Inc. | ||
| 3 | * Copyright 2009 Red Hat Inc. | ||
| 4 | * | ||
| 5 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
| 6 | * copy of this software and associated documentation files (the "Software"), | ||
| 7 | * to deal in the Software without restriction, including without limitation | ||
| 8 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
| 9 | * and/or sell copies of the Software, and to permit persons to whom the | ||
| 10 | * Software is furnished to do so, subject to the following conditions: | ||
| 11 | * | ||
| 12 | * The above copyright notice and this permission notice (including the next | ||
| 13 | * paragraph) shall be included in all copies or substantial portions of the | ||
| 14 | * Software. | ||
| 15 | * | ||
| 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
| 19 | * THE COPYRIGHT HOLDER(S) AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR | ||
| 20 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | ||
| 21 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | ||
| 22 | * DEALINGS IN THE SOFTWARE. | ||
| 23 | * | ||
| 24 | */ | ||
| 1 | 25 | ||
| 2 | #ifndef R600_BLIT_SHADERS_H | 26 | #ifndef R600_BLIT_SHADERS_H |
| 3 | #define R600_BLIT_SHADERS_H | 27 | #define R600_BLIT_SHADERS_H |
diff --git a/drivers/gpu/drm/radeon/r600_cs.c b/drivers/gpu/drm/radeon/r600_cs.c index d8864949e387..250a3a918193 100644 --- a/drivers/gpu/drm/radeon/r600_cs.c +++ b/drivers/gpu/drm/radeon/r600_cs.c | |||
| @@ -1170,9 +1170,8 @@ static inline int r600_check_texture_resource(struct radeon_cs_parser *p, u32 i | |||
| 1170 | /* using get ib will give us the offset into the mipmap bo */ | 1170 | /* using get ib will give us the offset into the mipmap bo */ |
| 1171 | word0 = radeon_get_ib_value(p, idx + 3) << 8; | 1171 | word0 = radeon_get_ib_value(p, idx + 3) << 8; |
| 1172 | if ((mipmap_size + word0) > radeon_bo_size(mipmap)) { | 1172 | if ((mipmap_size + word0) > radeon_bo_size(mipmap)) { |
| 1173 | dev_warn(p->dev, "mipmap bo too small (%d %d %d %d %d %d -> %d have %ld)\n", | 1173 | /*dev_warn(p->dev, "mipmap bo too small (%d %d %d %d %d %d -> %d have %ld)\n", |
| 1174 | w0, h0, bpe, blevel, nlevels, word0, mipmap_size, radeon_bo_size(texture)); | 1174 | w0, h0, bpe, blevel, nlevels, word0, mipmap_size, radeon_bo_size(texture));*/ |
| 1175 | return -EINVAL; | ||
| 1176 | } | 1175 | } |
| 1177 | return 0; | 1176 | return 0; |
| 1178 | } | 1177 | } |
diff --git a/drivers/gpu/drm/radeon/radeon_combios.c b/drivers/gpu/drm/radeon/radeon_combios.c index bd74e428bd14..a04b7a6ad95f 100644 --- a/drivers/gpu/drm/radeon/radeon_combios.c +++ b/drivers/gpu/drm/radeon/radeon_combios.c | |||
| @@ -1485,6 +1485,11 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev) | |||
| 1485 | /* PowerMac8,1 ? */ | 1485 | /* PowerMac8,1 ? */ |
| 1486 | /* imac g5 isight */ | 1486 | /* imac g5 isight */ |
| 1487 | rdev->mode_info.connector_table = CT_IMAC_G5_ISIGHT; | 1487 | rdev->mode_info.connector_table = CT_IMAC_G5_ISIGHT; |
| 1488 | } else if ((rdev->pdev->device == 0x4a48) && | ||
| 1489 | (rdev->pdev->subsystem_vendor == 0x1002) && | ||
| 1490 | (rdev->pdev->subsystem_device == 0x4a48)) { | ||
| 1491 | /* Mac X800 */ | ||
| 1492 | rdev->mode_info.connector_table = CT_MAC_X800; | ||
| 1488 | } else | 1493 | } else |
| 1489 | #endif /* CONFIG_PPC_PMAC */ | 1494 | #endif /* CONFIG_PPC_PMAC */ |
| 1490 | #ifdef CONFIG_PPC64 | 1495 | #ifdef CONFIG_PPC64 |
| @@ -1961,6 +1966,48 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev) | |||
| 1961 | CONNECTOR_OBJECT_ID_VGA, | 1966 | CONNECTOR_OBJECT_ID_VGA, |
| 1962 | &hpd); | 1967 | &hpd); |
| 1963 | break; | 1968 | break; |
| 1969 | case CT_MAC_X800: | ||
| 1970 | DRM_INFO("Connector Table: %d (mac x800)\n", | ||
| 1971 | rdev->mode_info.connector_table); | ||
| 1972 | /* DVI - primary dac, internal tmds */ | ||
| 1973 | ddc_i2c = combios_setup_i2c_bus(rdev, DDC_DVI, 0, 0); | ||
| 1974 | hpd.hpd = RADEON_HPD_1; /* ??? */ | ||
| 1975 | radeon_add_legacy_encoder(dev, | ||
| 1976 | radeon_get_encoder_enum(dev, | ||
| 1977 | ATOM_DEVICE_DFP1_SUPPORT, | ||
| 1978 | 0), | ||
| 1979 | ATOM_DEVICE_DFP1_SUPPORT); | ||
| 1980 | radeon_add_legacy_encoder(dev, | ||
| 1981 | radeon_get_encoder_enum(dev, | ||
| 1982 | ATOM_DEVICE_CRT1_SUPPORT, | ||
| 1983 | 1), | ||
| 1984 | ATOM_DEVICE_CRT1_SUPPORT); | ||
| 1985 | radeon_add_legacy_connector(dev, 0, | ||
| 1986 | ATOM_DEVICE_DFP1_SUPPORT | | ||
| 1987 | ATOM_DEVICE_CRT1_SUPPORT, | ||
| 1988 | DRM_MODE_CONNECTOR_DVII, &ddc_i2c, | ||
| 1989 | CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I, | ||
| 1990 | &hpd); | ||
| 1991 | /* DVI - tv dac, dvo */ | ||
| 1992 | ddc_i2c = combios_setup_i2c_bus(rdev, DDC_MONID, 0, 0); | ||
| 1993 | hpd.hpd = RADEON_HPD_2; /* ??? */ | ||
| 1994 | radeon_add_legacy_encoder(dev, | ||
| 1995 | radeon_get_encoder_enum(dev, | ||
| 1996 | ATOM_DEVICE_DFP2_SUPPORT, | ||
| 1997 | 0), | ||
| 1998 | ATOM_DEVICE_DFP2_SUPPORT); | ||
| 1999 | radeon_add_legacy_encoder(dev, | ||
| 2000 | radeon_get_encoder_enum(dev, | ||
| 2001 | ATOM_DEVICE_CRT2_SUPPORT, | ||
| 2002 | 2), | ||
| 2003 | ATOM_DEVICE_CRT2_SUPPORT); | ||
| 2004 | radeon_add_legacy_connector(dev, 1, | ||
| 2005 | ATOM_DEVICE_DFP2_SUPPORT | | ||
| 2006 | ATOM_DEVICE_CRT2_SUPPORT, | ||
| 2007 | DRM_MODE_CONNECTOR_DVII, &ddc_i2c, | ||
| 2008 | CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_I, | ||
| 2009 | &hpd); | ||
| 2010 | break; | ||
| 1964 | default: | 2011 | default: |
| 1965 | DRM_INFO("Connector table: %d (invalid)\n", | 2012 | DRM_INFO("Connector table: %d (invalid)\n", |
| 1966 | rdev->mode_info.connector_table); | 2013 | rdev->mode_info.connector_table); |
diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c index a9dd7847d96e..ecc1a8fafbfd 100644 --- a/drivers/gpu/drm/radeon/radeon_connectors.c +++ b/drivers/gpu/drm/radeon/radeon_connectors.c | |||
| @@ -481,7 +481,8 @@ static int radeon_lvds_mode_valid(struct drm_connector *connector, | |||
| 481 | return MODE_OK; | 481 | return MODE_OK; |
| 482 | } | 482 | } |
| 483 | 483 | ||
| 484 | static enum drm_connector_status radeon_lvds_detect(struct drm_connector *connector) | 484 | static enum drm_connector_status |
| 485 | radeon_lvds_detect(struct drm_connector *connector, bool force) | ||
| 485 | { | 486 | { |
| 486 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); | 487 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); |
| 487 | struct drm_encoder *encoder = radeon_best_single_encoder(connector); | 488 | struct drm_encoder *encoder = radeon_best_single_encoder(connector); |
| @@ -594,7 +595,8 @@ static int radeon_vga_mode_valid(struct drm_connector *connector, | |||
| 594 | return MODE_OK; | 595 | return MODE_OK; |
| 595 | } | 596 | } |
| 596 | 597 | ||
| 597 | static enum drm_connector_status radeon_vga_detect(struct drm_connector *connector) | 598 | static enum drm_connector_status |
| 599 | radeon_vga_detect(struct drm_connector *connector, bool force) | ||
| 598 | { | 600 | { |
| 599 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); | 601 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); |
| 600 | struct drm_encoder *encoder; | 602 | struct drm_encoder *encoder; |
| @@ -691,7 +693,8 @@ static int radeon_tv_mode_valid(struct drm_connector *connector, | |||
| 691 | return MODE_OK; | 693 | return MODE_OK; |
| 692 | } | 694 | } |
| 693 | 695 | ||
| 694 | static enum drm_connector_status radeon_tv_detect(struct drm_connector *connector) | 696 | static enum drm_connector_status |
| 697 | radeon_tv_detect(struct drm_connector *connector, bool force) | ||
| 695 | { | 698 | { |
| 696 | struct drm_encoder *encoder; | 699 | struct drm_encoder *encoder; |
| 697 | struct drm_encoder_helper_funcs *encoder_funcs; | 700 | struct drm_encoder_helper_funcs *encoder_funcs; |
| @@ -748,7 +751,8 @@ static int radeon_dvi_get_modes(struct drm_connector *connector) | |||
| 748 | * we have to check if this analog encoder is shared with anyone else (TV) | 751 | * we have to check if this analog encoder is shared with anyone else (TV) |
| 749 | * if its shared we have to set the other connector to disconnected. | 752 | * if its shared we have to set the other connector to disconnected. |
| 750 | */ | 753 | */ |
| 751 | static enum drm_connector_status radeon_dvi_detect(struct drm_connector *connector) | 754 | static enum drm_connector_status |
| 755 | radeon_dvi_detect(struct drm_connector *connector, bool force) | ||
| 752 | { | 756 | { |
| 753 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); | 757 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); |
| 754 | struct drm_encoder *encoder = NULL; | 758 | struct drm_encoder *encoder = NULL; |
| @@ -972,7 +976,8 @@ static int radeon_dp_get_modes(struct drm_connector *connector) | |||
| 972 | return ret; | 976 | return ret; |
| 973 | } | 977 | } |
| 974 | 978 | ||
| 975 | static enum drm_connector_status radeon_dp_detect(struct drm_connector *connector) | 979 | static enum drm_connector_status |
| 980 | radeon_dp_detect(struct drm_connector *connector, bool force) | ||
| 976 | { | 981 | { |
| 977 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); | 982 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); |
| 978 | enum drm_connector_status ret = connector_status_disconnected; | 983 | enum drm_connector_status ret = connector_status_disconnected; |
diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c index 6dd434ad2429..127a395f70fb 100644 --- a/drivers/gpu/drm/radeon/radeon_display.c +++ b/drivers/gpu/drm/radeon/radeon_display.c | |||
| @@ -1140,17 +1140,18 @@ bool radeon_crtc_scaling_mode_fixup(struct drm_crtc *crtc, | |||
| 1140 | radeon_crtc->rmx_type = radeon_encoder->rmx_type; | 1140 | radeon_crtc->rmx_type = radeon_encoder->rmx_type; |
| 1141 | else | 1141 | else |
| 1142 | radeon_crtc->rmx_type = RMX_OFF; | 1142 | radeon_crtc->rmx_type = RMX_OFF; |
| 1143 | src_v = crtc->mode.vdisplay; | ||
| 1144 | dst_v = radeon_crtc->native_mode.vdisplay; | ||
| 1145 | src_h = crtc->mode.hdisplay; | ||
| 1146 | dst_h = radeon_crtc->native_mode.vdisplay; | ||
| 1147 | /* copy native mode */ | 1143 | /* copy native mode */ |
| 1148 | memcpy(&radeon_crtc->native_mode, | 1144 | memcpy(&radeon_crtc->native_mode, |
| 1149 | &radeon_encoder->native_mode, | 1145 | &radeon_encoder->native_mode, |
| 1150 | sizeof(struct drm_display_mode)); | 1146 | sizeof(struct drm_display_mode)); |
| 1147 | src_v = crtc->mode.vdisplay; | ||
| 1148 | dst_v = radeon_crtc->native_mode.vdisplay; | ||
| 1149 | src_h = crtc->mode.hdisplay; | ||
| 1150 | dst_h = radeon_crtc->native_mode.hdisplay; | ||
| 1151 | 1151 | ||
| 1152 | /* fix up for overscan on hdmi */ | 1152 | /* fix up for overscan on hdmi */ |
| 1153 | if (ASIC_IS_AVIVO(rdev) && | 1153 | if (ASIC_IS_AVIVO(rdev) && |
| 1154 | (!(mode->flags & DRM_MODE_FLAG_INTERLACE)) && | ||
| 1154 | ((radeon_encoder->underscan_type == UNDERSCAN_ON) || | 1155 | ((radeon_encoder->underscan_type == UNDERSCAN_ON) || |
| 1155 | ((radeon_encoder->underscan_type == UNDERSCAN_AUTO) && | 1156 | ((radeon_encoder->underscan_type == UNDERSCAN_AUTO) && |
| 1156 | drm_detect_hdmi_monitor(radeon_connector->edid) && | 1157 | drm_detect_hdmi_monitor(radeon_connector->edid) && |
diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h index efbe975312dc..17a6602b5885 100644 --- a/drivers/gpu/drm/radeon/radeon_mode.h +++ b/drivers/gpu/drm/radeon/radeon_mode.h | |||
| @@ -204,7 +204,7 @@ struct radeon_i2c_chan { | |||
| 204 | 204 | ||
| 205 | /* mostly for macs, but really any system without connector tables */ | 205 | /* mostly for macs, but really any system without connector tables */ |
| 206 | enum radeon_connector_table { | 206 | enum radeon_connector_table { |
| 207 | CT_NONE, | 207 | CT_NONE = 0, |
| 208 | CT_GENERIC, | 208 | CT_GENERIC, |
| 209 | CT_IBOOK, | 209 | CT_IBOOK, |
| 210 | CT_POWERBOOK_EXTERNAL, | 210 | CT_POWERBOOK_EXTERNAL, |
| @@ -215,6 +215,7 @@ enum radeon_connector_table { | |||
| 215 | CT_IMAC_G5_ISIGHT, | 215 | CT_IMAC_G5_ISIGHT, |
| 216 | CT_EMAC, | 216 | CT_EMAC, |
| 217 | CT_RN50_POWER, | 217 | CT_RN50_POWER, |
| 218 | CT_MAC_X800, | ||
| 218 | }; | 219 | }; |
| 219 | 220 | ||
| 220 | enum radeon_dvo_chip { | 221 | enum radeon_dvo_chip { |
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c index 2ff5cf78235f..7083b1a24df3 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c | |||
| @@ -335,7 +335,8 @@ static void vmw_ldu_connector_restore(struct drm_connector *connector) | |||
| 335 | } | 335 | } |
| 336 | 336 | ||
| 337 | static enum drm_connector_status | 337 | static enum drm_connector_status |
| 338 | vmw_ldu_connector_detect(struct drm_connector *connector) | 338 | vmw_ldu_connector_detect(struct drm_connector *connector, |
| 339 | bool force) | ||
| 339 | { | 340 | { |
| 340 | if (vmw_connector_to_ldu(connector)->pref_active) | 341 | if (vmw_connector_to_ldu(connector)->pref_active) |
| 341 | return connector_status_connected; | 342 | return connector_status_connected; |
| @@ -516,7 +517,7 @@ static int vmw_ldu_init(struct vmw_private *dev_priv, unsigned unit) | |||
| 516 | 517 | ||
| 517 | drm_connector_init(dev, connector, &vmw_legacy_connector_funcs, | 518 | drm_connector_init(dev, connector, &vmw_legacy_connector_funcs, |
| 518 | DRM_MODE_CONNECTOR_LVDS); | 519 | DRM_MODE_CONNECTOR_LVDS); |
| 519 | connector->status = vmw_ldu_connector_detect(connector); | 520 | connector->status = vmw_ldu_connector_detect(connector, true); |
| 520 | 521 | ||
| 521 | drm_encoder_init(dev, encoder, &vmw_legacy_encoder_funcs, | 522 | drm_encoder_init(dev, encoder, &vmw_legacy_encoder_funcs, |
| 522 | DRM_MODE_ENCODER_LVDS); | 523 | DRM_MODE_ENCODER_LVDS); |
| @@ -610,7 +611,7 @@ int vmw_kms_ldu_update_layout(struct vmw_private *dev_priv, unsigned num, | |||
| 610 | ldu->pref_height = 600; | 611 | ldu->pref_height = 600; |
| 611 | ldu->pref_active = false; | 612 | ldu->pref_active = false; |
| 612 | } | 613 | } |
| 613 | con->status = vmw_ldu_connector_detect(con); | 614 | con->status = vmw_ldu_connector_detect(con, true); |
| 614 | } | 615 | } |
| 615 | 616 | ||
| 616 | mutex_unlock(&dev->mode_config.mutex); | 617 | mutex_unlock(&dev->mode_config.mutex); |
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 0c52899be964..3f7292486024 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c | |||
| @@ -1285,8 +1285,11 @@ static const struct hid_device_id hid_blacklist[] = { | |||
| 1285 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_JIS) }, | 1285 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_JIS) }, |
| 1286 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) }, | 1286 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) }, |
| 1287 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) }, | 1287 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) }, |
| 1288 | { HID_USB_DEVICE(USB_VENDOR_ID_ASUS, USB_DEVICE_ID_ASUS_T91MT) }, | ||
| 1289 | { HID_USB_DEVICE(USB_VENDOR_ID_ASUS, USB_DEVICE_ID_ASUSTEK_MULTITOUCH_YFO) }, | ||
| 1288 | { HID_USB_DEVICE(USB_VENDOR_ID_BELKIN, USB_DEVICE_ID_FLIP_KVM) }, | 1290 | { HID_USB_DEVICE(USB_VENDOR_ID_BELKIN, USB_DEVICE_ID_FLIP_KVM) }, |
| 1289 | { HID_USB_DEVICE(USB_VENDOR_ID_BTC, USB_DEVICE_ID_BTC_EMPREX_REMOTE) }, | 1291 | { HID_USB_DEVICE(USB_VENDOR_ID_BTC, USB_DEVICE_ID_BTC_EMPREX_REMOTE) }, |
| 1292 | { HID_USB_DEVICE(USB_VENDOR_ID_BTC, USB_DEVICE_ID_BTC_EMPREX_REMOTE_2) }, | ||
| 1290 | { HID_USB_DEVICE(USB_VENDOR_ID_CANDO, USB_DEVICE_ID_CANDO_MULTI_TOUCH) }, | 1293 | { HID_USB_DEVICE(USB_VENDOR_ID_CANDO, USB_DEVICE_ID_CANDO_MULTI_TOUCH) }, |
| 1291 | { HID_USB_DEVICE(USB_VENDOR_ID_CANDO, USB_DEVICE_ID_CANDO_MULTI_TOUCH_11_6) }, | 1294 | { HID_USB_DEVICE(USB_VENDOR_ID_CANDO, USB_DEVICE_ID_CANDO_MULTI_TOUCH_11_6) }, |
| 1292 | { HID_USB_DEVICE(USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION) }, | 1295 | { HID_USB_DEVICE(USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION) }, |
| @@ -1578,7 +1581,6 @@ static const struct hid_device_id hid_ignore_list[] = { | |||
| 1578 | { HID_USB_DEVICE(USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_24) }, | 1581 | { HID_USB_DEVICE(USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_24) }, |
| 1579 | { HID_USB_DEVICE(USB_VENDOR_ID_AIRCABLE, USB_DEVICE_ID_AIRCABLE1) }, | 1582 | { HID_USB_DEVICE(USB_VENDOR_ID_AIRCABLE, USB_DEVICE_ID_AIRCABLE1) }, |
| 1580 | { HID_USB_DEVICE(USB_VENDOR_ID_ALCOR, USB_DEVICE_ID_ALCOR_USBRS232) }, | 1583 | { HID_USB_DEVICE(USB_VENDOR_ID_ALCOR, USB_DEVICE_ID_ALCOR_USBRS232) }, |
| 1581 | { HID_USB_DEVICE(USB_VENDOR_ID_ASUS, USB_DEVICE_ID_ASUS_T91MT)}, | ||
| 1582 | { HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK, USB_DEVICE_ID_ASUSTEK_LCM)}, | 1584 | { HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK, USB_DEVICE_ID_ASUSTEK_LCM)}, |
| 1583 | { HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK, USB_DEVICE_ID_ASUSTEK_LCM2)}, | 1585 | { HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK, USB_DEVICE_ID_ASUSTEK_LCM2)}, |
| 1584 | { HID_USB_DEVICE(USB_VENDOR_ID_AVERMEDIA, USB_DEVICE_ID_AVER_FM_MR800) }, | 1586 | { HID_USB_DEVICE(USB_VENDOR_ID_AVERMEDIA, USB_DEVICE_ID_AVER_FM_MR800) }, |
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index 85c6d13c9ffa..765a4f53eb5c 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h | |||
| @@ -105,6 +105,7 @@ | |||
| 105 | 105 | ||
| 106 | #define USB_VENDOR_ID_ASUS 0x0486 | 106 | #define USB_VENDOR_ID_ASUS 0x0486 |
| 107 | #define USB_DEVICE_ID_ASUS_T91MT 0x0185 | 107 | #define USB_DEVICE_ID_ASUS_T91MT 0x0185 |
| 108 | #define USB_DEVICE_ID_ASUSTEK_MULTITOUCH_YFO 0x0186 | ||
| 108 | 109 | ||
| 109 | #define USB_VENDOR_ID_ASUSTEK 0x0b05 | 110 | #define USB_VENDOR_ID_ASUSTEK 0x0b05 |
| 110 | #define USB_DEVICE_ID_ASUSTEK_LCM 0x1726 | 111 | #define USB_DEVICE_ID_ASUSTEK_LCM 0x1726 |
| @@ -128,6 +129,7 @@ | |||
| 128 | 129 | ||
| 129 | #define USB_VENDOR_ID_BTC 0x046e | 130 | #define USB_VENDOR_ID_BTC 0x046e |
| 130 | #define USB_DEVICE_ID_BTC_EMPREX_REMOTE 0x5578 | 131 | #define USB_DEVICE_ID_BTC_EMPREX_REMOTE 0x5578 |
| 132 | #define USB_DEVICE_ID_BTC_EMPREX_REMOTE_2 0x5577 | ||
| 131 | 133 | ||
| 132 | #define USB_VENDOR_ID_CANDO 0x2087 | 134 | #define USB_VENDOR_ID_CANDO 0x2087 |
| 133 | #define USB_DEVICE_ID_CANDO_MULTI_TOUCH 0x0a01 | 135 | #define USB_DEVICE_ID_CANDO_MULTI_TOUCH 0x0a01 |
| @@ -149,6 +151,7 @@ | |||
| 149 | 151 | ||
| 150 | #define USB_VENDOR_ID_CHICONY 0x04f2 | 152 | #define USB_VENDOR_ID_CHICONY 0x04f2 |
| 151 | #define USB_DEVICE_ID_CHICONY_TACTICAL_PAD 0x0418 | 153 | #define USB_DEVICE_ID_CHICONY_TACTICAL_PAD 0x0418 |
| 154 | #define USB_DEVICE_ID_CHICONY_MULTI_TOUCH 0xb19d | ||
| 152 | 155 | ||
| 153 | #define USB_VENDOR_ID_CIDC 0x1677 | 156 | #define USB_VENDOR_ID_CIDC 0x1677 |
| 154 | 157 | ||
| @@ -507,6 +510,7 @@ | |||
| 507 | #define USB_VENDOR_ID_UCLOGIC 0x5543 | 510 | #define USB_VENDOR_ID_UCLOGIC 0x5543 |
| 508 | #define USB_DEVICE_ID_UCLOGIC_TABLET_PF1209 0x0042 | 511 | #define USB_DEVICE_ID_UCLOGIC_TABLET_PF1209 0x0042 |
| 509 | #define USB_DEVICE_ID_UCLOGIC_TABLET_WP4030U 0x0003 | 512 | #define USB_DEVICE_ID_UCLOGIC_TABLET_WP4030U 0x0003 |
| 513 | #define USB_DEVICE_ID_UCLOGIC_TABLET_KNA5 0x6001 | ||
| 510 | 514 | ||
| 511 | #define USB_VENDOR_ID_VERNIER 0x08f7 | 515 | #define USB_VENDOR_ID_VERNIER 0x08f7 |
| 512 | #define USB_DEVICE_ID_VERNIER_LABPRO 0x0001 | 516 | #define USB_DEVICE_ID_VERNIER_LABPRO 0x0001 |
diff --git a/drivers/hid/hid-mosart.c b/drivers/hid/hid-mosart.c index e91437c18906..ac5421d568f1 100644 --- a/drivers/hid/hid-mosart.c +++ b/drivers/hid/hid-mosart.c | |||
| @@ -239,6 +239,7 @@ static void mosart_remove(struct hid_device *hdev) | |||
| 239 | 239 | ||
| 240 | static const struct hid_device_id mosart_devices[] = { | 240 | static const struct hid_device_id mosart_devices[] = { |
| 241 | { HID_USB_DEVICE(USB_VENDOR_ID_ASUS, USB_DEVICE_ID_ASUS_T91MT) }, | 241 | { HID_USB_DEVICE(USB_VENDOR_ID_ASUS, USB_DEVICE_ID_ASUS_T91MT) }, |
| 242 | { HID_USB_DEVICE(USB_VENDOR_ID_ASUS, USB_DEVICE_ID_ASUSTEK_MULTITOUCH_YFO) }, | ||
| 242 | { } | 243 | { } |
| 243 | }; | 244 | }; |
| 244 | MODULE_DEVICE_TABLE(hid, mosart_devices); | 245 | MODULE_DEVICE_TABLE(hid, mosart_devices); |
diff --git a/drivers/hid/hid-topseed.c b/drivers/hid/hid-topseed.c index 5771f851f856..956ed9ac19d4 100644 --- a/drivers/hid/hid-topseed.c +++ b/drivers/hid/hid-topseed.c | |||
| @@ -64,6 +64,7 @@ static int ts_input_mapping(struct hid_device *hdev, struct hid_input *hi, | |||
| 64 | static const struct hid_device_id ts_devices[] = { | 64 | static const struct hid_device_id ts_devices[] = { |
| 65 | { HID_USB_DEVICE(USB_VENDOR_ID_TOPSEED, USB_DEVICE_ID_TOPSEED_CYBERLINK) }, | 65 | { HID_USB_DEVICE(USB_VENDOR_ID_TOPSEED, USB_DEVICE_ID_TOPSEED_CYBERLINK) }, |
| 66 | { HID_USB_DEVICE(USB_VENDOR_ID_BTC, USB_DEVICE_ID_BTC_EMPREX_REMOTE) }, | 66 | { HID_USB_DEVICE(USB_VENDOR_ID_BTC, USB_DEVICE_ID_BTC_EMPREX_REMOTE) }, |
| 67 | { HID_USB_DEVICE(USB_VENDOR_ID_BTC, USB_DEVICE_ID_BTC_EMPREX_REMOTE_2) }, | ||
| 67 | { HID_USB_DEVICE(USB_VENDOR_ID_TOPSEED2, USB_DEVICE_ID_TOPSEED2_RF_COMBO) }, | 68 | { HID_USB_DEVICE(USB_VENDOR_ID_TOPSEED2, USB_DEVICE_ID_TOPSEED2_RF_COMBO) }, |
| 68 | { } | 69 | { } |
| 69 | }; | 70 | }; |
diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c index b729c0286679..599041a7f670 100644 --- a/drivers/hid/usbhid/hid-core.c +++ b/drivers/hid/usbhid/hid-core.c | |||
| @@ -828,6 +828,7 @@ static int usbhid_output_raw_report(struct hid_device *hid, __u8 *buf, size_t co | |||
| 828 | } | 828 | } |
| 829 | } else { | 829 | } else { |
| 830 | int skipped_report_id = 0; | 830 | int skipped_report_id = 0; |
| 831 | int report_id = buf[0]; | ||
| 831 | if (buf[0] == 0x0) { | 832 | if (buf[0] == 0x0) { |
| 832 | /* Don't send the Report ID */ | 833 | /* Don't send the Report ID */ |
| 833 | buf++; | 834 | buf++; |
| @@ -837,7 +838,7 @@ static int usbhid_output_raw_report(struct hid_device *hid, __u8 *buf, size_t co | |||
| 837 | ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), | 838 | ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), |
| 838 | HID_REQ_SET_REPORT, | 839 | HID_REQ_SET_REPORT, |
| 839 | USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE, | 840 | USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE, |
| 840 | ((report_type + 1) << 8) | *buf, | 841 | ((report_type + 1) << 8) | report_id, |
| 841 | interface->desc.bInterfaceNumber, buf, count, | 842 | interface->desc.bInterfaceNumber, buf, count, |
| 842 | USB_CTRL_SET_TIMEOUT); | 843 | USB_CTRL_SET_TIMEOUT); |
| 843 | /* count also the report id, if this was a numbered report. */ | 844 | /* count also the report id, if this was a numbered report. */ |
| @@ -1445,6 +1446,11 @@ static const struct hid_device_id hid_usb_table[] = { | |||
| 1445 | { } | 1446 | { } |
| 1446 | }; | 1447 | }; |
| 1447 | 1448 | ||
| 1449 | struct usb_interface *usbhid_find_interface(int minor) | ||
| 1450 | { | ||
| 1451 | return usb_find_interface(&hid_driver, minor); | ||
| 1452 | } | ||
| 1453 | |||
| 1448 | static struct hid_driver hid_usb_driver = { | 1454 | static struct hid_driver hid_usb_driver = { |
| 1449 | .name = "generic-usb", | 1455 | .name = "generic-usb", |
| 1450 | .id_table = hid_usb_table, | 1456 | .id_table = hid_usb_table, |
diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c index 2643d3147621..70da3181c8a0 100644 --- a/drivers/hid/usbhid/hid-quirks.c +++ b/drivers/hid/usbhid/hid-quirks.c | |||
| @@ -33,6 +33,7 @@ static const struct hid_blacklist { | |||
| 33 | { USB_VENDOR_ID_AASHIMA, USB_DEVICE_ID_AASHIMA_PREDATOR, HID_QUIRK_BADPAD }, | 33 | { USB_VENDOR_ID_AASHIMA, USB_DEVICE_ID_AASHIMA_PREDATOR, HID_QUIRK_BADPAD }, |
| 34 | { USB_VENDOR_ID_ALPS, USB_DEVICE_ID_IBM_GAMEPAD, HID_QUIRK_BADPAD }, | 34 | { USB_VENDOR_ID_ALPS, USB_DEVICE_ID_IBM_GAMEPAD, HID_QUIRK_BADPAD }, |
| 35 | { USB_VENDOR_ID_CHIC, USB_DEVICE_ID_CHIC_GAMEPAD, HID_QUIRK_BADPAD }, | 35 | { USB_VENDOR_ID_CHIC, USB_DEVICE_ID_CHIC_GAMEPAD, HID_QUIRK_BADPAD }, |
| 36 | { USB_VENDOR_ID_DWAV, USB_DEVICE_ID_EGALAX_TOUCHCONTROLLER, HID_QUIRK_MULTI_INPUT | HID_QUIRK_NOGET }, | ||
| 36 | { USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH, HID_QUIRK_MULTI_INPUT }, | 37 | { USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH, HID_QUIRK_MULTI_INPUT }, |
| 37 | { USB_VENDOR_ID_MOJO, USB_DEVICE_ID_RETRO_ADAPTER, HID_QUIRK_MULTI_INPUT }, | 38 | { USB_VENDOR_ID_MOJO, USB_DEVICE_ID_RETRO_ADAPTER, HID_QUIRK_MULTI_INPUT }, |
| 38 | { USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_DRIVING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT }, | 39 | { USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_DRIVING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT }, |
| @@ -69,6 +70,7 @@ static const struct hid_blacklist { | |||
| 69 | { USB_VENDOR_ID_TURBOX, USB_DEVICE_ID_TURBOX_KEYBOARD, HID_QUIRK_NOGET }, | 70 | { USB_VENDOR_ID_TURBOX, USB_DEVICE_ID_TURBOX_KEYBOARD, HID_QUIRK_NOGET }, |
| 70 | { USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_PF1209, HID_QUIRK_MULTI_INPUT }, | 71 | { USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_PF1209, HID_QUIRK_MULTI_INPUT }, |
| 71 | { USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP4030U, HID_QUIRK_MULTI_INPUT }, | 72 | { USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP4030U, HID_QUIRK_MULTI_INPUT }, |
| 73 | { USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_KNA5, HID_QUIRK_MULTI_INPUT }, | ||
| 72 | { USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_DUAL_USB_JOYPAD, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT | HID_QUIRK_SKIP_OUTPUT_REPORTS }, | 74 | { USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_DUAL_USB_JOYPAD, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT | HID_QUIRK_SKIP_OUTPUT_REPORTS }, |
| 73 | { USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_QUAD_USB_JOYPAD, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT }, | 75 | { USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_QUAD_USB_JOYPAD, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT }, |
| 74 | 76 | ||
| @@ -77,6 +79,8 @@ static const struct hid_blacklist { | |||
| 77 | 79 | ||
| 78 | { USB_VENDOR_ID_PI_ENGINEERING, USB_DEVICE_ID_PI_ENGINEERING_VEC_USB_FOOTPEDAL, HID_QUIRK_HIDINPUT_FORCE }, | 80 | { USB_VENDOR_ID_PI_ENGINEERING, USB_DEVICE_ID_PI_ENGINEERING_VEC_USB_FOOTPEDAL, HID_QUIRK_HIDINPUT_FORCE }, |
| 79 | 81 | ||
| 82 | { USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_MULTI_TOUCH, HID_QUIRK_MULTI_INPUT }, | ||
| 83 | |||
| 80 | { 0, 0 } | 84 | { 0, 0 } |
| 81 | }; | 85 | }; |
| 82 | 86 | ||
diff --git a/drivers/hid/usbhid/hiddev.c b/drivers/hid/usbhid/hiddev.c index 0a29c51114aa..681e620eb95b 100644 --- a/drivers/hid/usbhid/hiddev.c +++ b/drivers/hid/usbhid/hiddev.c | |||
| @@ -270,7 +270,7 @@ static int hiddev_open(struct inode *inode, struct file *file) | |||
| 270 | struct hiddev *hiddev; | 270 | struct hiddev *hiddev; |
| 271 | int res; | 271 | int res; |
| 272 | 272 | ||
| 273 | intf = usb_find_interface(&hiddev_driver, iminor(inode)); | 273 | intf = usbhid_find_interface(iminor(inode)); |
| 274 | if (!intf) | 274 | if (!intf) |
| 275 | return -ENODEV; | 275 | return -ENODEV; |
| 276 | hid = usb_get_intfdata(intf); | 276 | hid = usb_get_intfdata(intf); |
diff --git a/drivers/hid/usbhid/usbhid.h b/drivers/hid/usbhid/usbhid.h index 693fd3e720df..89d2e847dcc6 100644 --- a/drivers/hid/usbhid/usbhid.h +++ b/drivers/hid/usbhid/usbhid.h | |||
| @@ -42,6 +42,7 @@ void usbhid_submit_report | |||
| 42 | (struct hid_device *hid, struct hid_report *report, unsigned char dir); | 42 | (struct hid_device *hid, struct hid_report *report, unsigned char dir); |
| 43 | int usbhid_get_power(struct hid_device *hid); | 43 | int usbhid_get_power(struct hid_device *hid); |
| 44 | void usbhid_put_power(struct hid_device *hid); | 44 | void usbhid_put_power(struct hid_device *hid); |
| 45 | struct usb_interface *usbhid_find_interface(int minor); | ||
| 45 | 46 | ||
| 46 | /* iofl flags */ | 47 | /* iofl flags */ |
| 47 | #define HID_CTRL_RUNNING 1 | 48 | #define HID_CTRL_RUNNING 1 |
diff --git a/drivers/mtd/nand/bf5xx_nand.c b/drivers/mtd/nand/bf5xx_nand.c index a382e3dd0a5d..6fbeefa3a766 100644 --- a/drivers/mtd/nand/bf5xx_nand.c +++ b/drivers/mtd/nand/bf5xx_nand.c | |||
| @@ -682,7 +682,6 @@ static int __devinit bf5xx_nand_add_partition(struct bf5xx_nand_info *info) | |||
| 682 | static int __devexit bf5xx_nand_remove(struct platform_device *pdev) | 682 | static int __devexit bf5xx_nand_remove(struct platform_device *pdev) |
| 683 | { | 683 | { |
| 684 | struct bf5xx_nand_info *info = to_nand_info(pdev); | 684 | struct bf5xx_nand_info *info = to_nand_info(pdev); |
| 685 | struct mtd_info *mtd = NULL; | ||
| 686 | 685 | ||
| 687 | platform_set_drvdata(pdev, NULL); | 686 | platform_set_drvdata(pdev, NULL); |
| 688 | 687 | ||
| @@ -690,11 +689,7 @@ static int __devexit bf5xx_nand_remove(struct platform_device *pdev) | |||
| 690 | * and their partitions, then go through freeing the | 689 | * and their partitions, then go through freeing the |
| 691 | * resources used | 690 | * resources used |
| 692 | */ | 691 | */ |
| 693 | mtd = &info->mtd; | 692 | nand_release(&info->mtd); |
| 694 | if (mtd) { | ||
| 695 | nand_release(mtd); | ||
| 696 | kfree(mtd); | ||
| 697 | } | ||
| 698 | 693 | ||
| 699 | peripheral_free_list(bfin_nfc_pin_req); | 694 | peripheral_free_list(bfin_nfc_pin_req); |
| 700 | bf5xx_nand_dma_remove(info); | 695 | bf5xx_nand_dma_remove(info); |
| @@ -710,7 +705,7 @@ static int bf5xx_nand_scan(struct mtd_info *mtd) | |||
| 710 | struct nand_chip *chip = mtd->priv; | 705 | struct nand_chip *chip = mtd->priv; |
| 711 | int ret; | 706 | int ret; |
| 712 | 707 | ||
| 713 | ret = nand_scan_ident(mtd, 1); | 708 | ret = nand_scan_ident(mtd, 1, NULL); |
| 714 | if (ret) | 709 | if (ret) |
| 715 | return ret; | 710 | return ret; |
| 716 | 711 | ||
diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c index fcf8ceb277d4..b2828e84d243 100644 --- a/drivers/mtd/nand/mxc_nand.c +++ b/drivers/mtd/nand/mxc_nand.c | |||
| @@ -67,7 +67,9 @@ | |||
| 67 | #define NFC_V1_V2_CONFIG1_BIG (1 << 5) | 67 | #define NFC_V1_V2_CONFIG1_BIG (1 << 5) |
| 68 | #define NFC_V1_V2_CONFIG1_RST (1 << 6) | 68 | #define NFC_V1_V2_CONFIG1_RST (1 << 6) |
| 69 | #define NFC_V1_V2_CONFIG1_CE (1 << 7) | 69 | #define NFC_V1_V2_CONFIG1_CE (1 << 7) |
| 70 | #define NFC_V1_V2_CONFIG1_ONE_CYCLE (1 << 8) | 70 | #define NFC_V2_CONFIG1_ONE_CYCLE (1 << 8) |
| 71 | #define NFC_V2_CONFIG1_PPB(x) (((x) & 0x3) << 9) | ||
| 72 | #define NFC_V2_CONFIG1_FP_INT (1 << 11) | ||
| 71 | 73 | ||
| 72 | #define NFC_V1_V2_CONFIG2_INT (1 << 15) | 74 | #define NFC_V1_V2_CONFIG2_INT (1 << 15) |
| 73 | 75 | ||
| @@ -402,16 +404,16 @@ static void send_read_id_v1_v2(struct mxc_nand_host *host) | |||
| 402 | /* Wait for operation to complete */ | 404 | /* Wait for operation to complete */ |
| 403 | wait_op_done(host, true); | 405 | wait_op_done(host, true); |
| 404 | 406 | ||
| 407 | memcpy(host->data_buf, host->main_area0, 16); | ||
| 408 | |||
| 405 | if (this->options & NAND_BUSWIDTH_16) { | 409 | if (this->options & NAND_BUSWIDTH_16) { |
| 406 | void __iomem *main_buf = host->main_area0; | ||
| 407 | /* compress the ID info */ | 410 | /* compress the ID info */ |
| 408 | writeb(readb(main_buf + 2), main_buf + 1); | 411 | host->data_buf[1] = host->data_buf[2]; |
| 409 | writeb(readb(main_buf + 4), main_buf + 2); | 412 | host->data_buf[2] = host->data_buf[4]; |
| 410 | writeb(readb(main_buf + 6), main_buf + 3); | 413 | host->data_buf[3] = host->data_buf[6]; |
| 411 | writeb(readb(main_buf + 8), main_buf + 4); | 414 | host->data_buf[4] = host->data_buf[8]; |
| 412 | writeb(readb(main_buf + 10), main_buf + 5); | 415 | host->data_buf[5] = host->data_buf[10]; |
| 413 | } | 416 | } |
| 414 | memcpy(host->data_buf, host->main_area0, 16); | ||
| 415 | } | 417 | } |
| 416 | 418 | ||
| 417 | static uint16_t get_dev_status_v3(struct mxc_nand_host *host) | 419 | static uint16_t get_dev_status_v3(struct mxc_nand_host *host) |
| @@ -729,27 +731,30 @@ static void preset_v1_v2(struct mtd_info *mtd) | |||
| 729 | { | 731 | { |
| 730 | struct nand_chip *nand_chip = mtd->priv; | 732 | struct nand_chip *nand_chip = mtd->priv; |
| 731 | struct mxc_nand_host *host = nand_chip->priv; | 733 | struct mxc_nand_host *host = nand_chip->priv; |
| 732 | uint16_t tmp; | 734 | uint16_t config1 = 0; |
| 733 | 735 | ||
| 734 | /* enable interrupt, disable spare enable */ | 736 | if (nand_chip->ecc.mode == NAND_ECC_HW) |
| 735 | tmp = readw(NFC_V1_V2_CONFIG1); | 737 | config1 |= NFC_V1_V2_CONFIG1_ECC_EN; |
| 736 | tmp &= ~NFC_V1_V2_CONFIG1_INT_MSK; | 738 | |
| 737 | tmp &= ~NFC_V1_V2_CONFIG1_SP_EN; | 739 | if (nfc_is_v21()) |
| 738 | if (nand_chip->ecc.mode == NAND_ECC_HW) { | 740 | config1 |= NFC_V2_CONFIG1_FP_INT; |
| 739 | tmp |= NFC_V1_V2_CONFIG1_ECC_EN; | 741 | |
| 740 | } else { | 742 | if (!cpu_is_mx21()) |
| 741 | tmp &= ~NFC_V1_V2_CONFIG1_ECC_EN; | 743 | config1 |= NFC_V1_V2_CONFIG1_INT_MSK; |
| 742 | } | ||
| 743 | 744 | ||
| 744 | if (nfc_is_v21() && mtd->writesize) { | 745 | if (nfc_is_v21() && mtd->writesize) { |
| 746 | uint16_t pages_per_block = mtd->erasesize / mtd->writesize; | ||
| 747 | |||
| 745 | host->eccsize = get_eccsize(mtd); | 748 | host->eccsize = get_eccsize(mtd); |
| 746 | if (host->eccsize == 4) | 749 | if (host->eccsize == 4) |
| 747 | tmp |= NFC_V2_CONFIG1_ECC_MODE_4; | 750 | config1 |= NFC_V2_CONFIG1_ECC_MODE_4; |
| 751 | |||
| 752 | config1 |= NFC_V2_CONFIG1_PPB(ffs(pages_per_block) - 6); | ||
| 748 | } else { | 753 | } else { |
| 749 | host->eccsize = 1; | 754 | host->eccsize = 1; |
| 750 | } | 755 | } |
| 751 | 756 | ||
| 752 | writew(tmp, NFC_V1_V2_CONFIG1); | 757 | writew(config1, NFC_V1_V2_CONFIG1); |
| 753 | /* preset operation */ | 758 | /* preset operation */ |
| 754 | 759 | ||
| 755 | /* Unlock the internal RAM Buffer */ | 760 | /* Unlock the internal RAM Buffer */ |
diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c index 4d89f3780207..4d01cda68844 100644 --- a/drivers/mtd/nand/pxa3xx_nand.c +++ b/drivers/mtd/nand/pxa3xx_nand.c | |||
| @@ -1320,6 +1320,7 @@ static int pxa3xx_nand_probe(struct platform_device *pdev) | |||
| 1320 | goto fail_free_irq; | 1320 | goto fail_free_irq; |
| 1321 | } | 1321 | } |
| 1322 | 1322 | ||
| 1323 | #ifdef CONFIG_MTD_PARTITIONS | ||
| 1323 | if (mtd_has_cmdlinepart()) { | 1324 | if (mtd_has_cmdlinepart()) { |
| 1324 | static const char *probes[] = { "cmdlinepart", NULL }; | 1325 | static const char *probes[] = { "cmdlinepart", NULL }; |
| 1325 | struct mtd_partition *parts; | 1326 | struct mtd_partition *parts; |
| @@ -1332,6 +1333,9 @@ static int pxa3xx_nand_probe(struct platform_device *pdev) | |||
| 1332 | } | 1333 | } |
| 1333 | 1334 | ||
| 1334 | return add_mtd_partitions(mtd, pdata->parts, pdata->nr_parts); | 1335 | return add_mtd_partitions(mtd, pdata->parts, pdata->nr_parts); |
| 1336 | #else | ||
| 1337 | return 0; | ||
| 1338 | #endif | ||
| 1335 | 1339 | ||
| 1336 | fail_free_irq: | 1340 | fail_free_irq: |
| 1337 | free_irq(irq, info); | 1341 | free_irq(irq, info); |
| @@ -1364,7 +1368,9 @@ static int pxa3xx_nand_remove(struct platform_device *pdev) | |||
| 1364 | platform_set_drvdata(pdev, NULL); | 1368 | platform_set_drvdata(pdev, NULL); |
| 1365 | 1369 | ||
| 1366 | del_mtd_device(mtd); | 1370 | del_mtd_device(mtd); |
| 1371 | #ifdef CONFIG_MTD_PARTITIONS | ||
| 1367 | del_mtd_partitions(mtd); | 1372 | del_mtd_partitions(mtd); |
| 1373 | #endif | ||
| 1368 | irq = platform_get_irq(pdev, 0); | 1374 | irq = platform_get_irq(pdev, 0); |
| 1369 | if (irq >= 0) | 1375 | if (irq >= 0) |
| 1370 | free_irq(irq, info); | 1376 | free_irq(irq, info); |
diff --git a/drivers/mtd/onenand/samsung.c b/drivers/mtd/onenand/samsung.c index cb443af3d45f..a460f1b748c2 100644 --- a/drivers/mtd/onenand/samsung.c +++ b/drivers/mtd/onenand/samsung.c | |||
| @@ -554,14 +554,13 @@ static int s5pc110_dma_ops(void *dst, void *src, size_t count, int direction) | |||
| 554 | 554 | ||
| 555 | do { | 555 | do { |
| 556 | status = readl(base + S5PC110_DMA_TRANS_STATUS); | 556 | status = readl(base + S5PC110_DMA_TRANS_STATUS); |
| 557 | if (status & S5PC110_DMA_TRANS_STATUS_TE) { | ||
| 558 | writel(S5PC110_DMA_TRANS_CMD_TEC, | ||
| 559 | base + S5PC110_DMA_TRANS_CMD); | ||
| 560 | return -EIO; | ||
| 561 | } | ||
| 557 | } while (!(status & S5PC110_DMA_TRANS_STATUS_TD)); | 562 | } while (!(status & S5PC110_DMA_TRANS_STATUS_TD)); |
| 558 | 563 | ||
| 559 | if (status & S5PC110_DMA_TRANS_STATUS_TE) { | ||
| 560 | writel(S5PC110_DMA_TRANS_CMD_TEC, base + S5PC110_DMA_TRANS_CMD); | ||
| 561 | writel(S5PC110_DMA_TRANS_CMD_TDC, base + S5PC110_DMA_TRANS_CMD); | ||
| 562 | return -EIO; | ||
| 563 | } | ||
| 564 | |||
| 565 | writel(S5PC110_DMA_TRANS_CMD_TDC, base + S5PC110_DMA_TRANS_CMD); | 564 | writel(S5PC110_DMA_TRANS_CMD_TDC, base + S5PC110_DMA_TRANS_CMD); |
| 566 | 565 | ||
| 567 | return 0; | 566 | return 0; |
| @@ -571,13 +570,12 @@ static int s5pc110_read_bufferram(struct mtd_info *mtd, int area, | |||
| 571 | unsigned char *buffer, int offset, size_t count) | 570 | unsigned char *buffer, int offset, size_t count) |
| 572 | { | 571 | { |
| 573 | struct onenand_chip *this = mtd->priv; | 572 | struct onenand_chip *this = mtd->priv; |
| 574 | void __iomem *bufferram; | ||
| 575 | void __iomem *p; | 573 | void __iomem *p; |
| 576 | void *buf = (void *) buffer; | 574 | void *buf = (void *) buffer; |
| 577 | dma_addr_t dma_src, dma_dst; | 575 | dma_addr_t dma_src, dma_dst; |
| 578 | int err; | 576 | int err; |
| 579 | 577 | ||
| 580 | p = bufferram = this->base + area; | 578 | p = this->base + area; |
| 581 | if (ONENAND_CURRENT_BUFFERRAM(this)) { | 579 | if (ONENAND_CURRENT_BUFFERRAM(this)) { |
| 582 | if (area == ONENAND_DATARAM) | 580 | if (area == ONENAND_DATARAM) |
| 583 | p += this->writesize; | 581 | p += this->writesize; |
| @@ -621,7 +619,7 @@ static int s5pc110_read_bufferram(struct mtd_info *mtd, int area, | |||
| 621 | normal: | 619 | normal: |
| 622 | if (count != mtd->writesize) { | 620 | if (count != mtd->writesize) { |
| 623 | /* Copy the bufferram to memory to prevent unaligned access */ | 621 | /* Copy the bufferram to memory to prevent unaligned access */ |
| 624 | memcpy(this->page_buf, bufferram, mtd->writesize); | 622 | memcpy(this->page_buf, p, mtd->writesize); |
| 625 | p = this->page_buf + offset; | 623 | p = this->page_buf + offset; |
| 626 | } | 624 | } |
| 627 | 625 | ||
diff --git a/drivers/net/ll_temac_main.c b/drivers/net/ll_temac_main.c index bdf2149e5296..87f0a93b165c 100644 --- a/drivers/net/ll_temac_main.c +++ b/drivers/net/ll_temac_main.c | |||
| @@ -38,6 +38,7 @@ | |||
| 38 | #include <linux/of_device.h> | 38 | #include <linux/of_device.h> |
| 39 | #include <linux/of_mdio.h> | 39 | #include <linux/of_mdio.h> |
| 40 | #include <linux/of_platform.h> | 40 | #include <linux/of_platform.h> |
| 41 | #include <linux/of_address.h> | ||
| 41 | #include <linux/skbuff.h> | 42 | #include <linux/skbuff.h> |
| 42 | #include <linux/spinlock.h> | 43 | #include <linux/spinlock.h> |
| 43 | #include <linux/tcp.h> /* needed for sizeof(tcphdr) */ | 44 | #include <linux/tcp.h> /* needed for sizeof(tcphdr) */ |
diff --git a/drivers/net/ll_temac_mdio.c b/drivers/net/ll_temac_mdio.c index 5ae28c975b38..8cf9d4f56bb2 100644 --- a/drivers/net/ll_temac_mdio.c +++ b/drivers/net/ll_temac_mdio.c | |||
| @@ -10,6 +10,7 @@ | |||
| 10 | #include <linux/phy.h> | 10 | #include <linux/phy.h> |
| 11 | #include <linux/of.h> | 11 | #include <linux/of.h> |
| 12 | #include <linux/of_device.h> | 12 | #include <linux/of_device.h> |
| 13 | #include <linux/of_address.h> | ||
| 13 | #include <linux/slab.h> | 14 | #include <linux/slab.h> |
| 14 | #include <linux/of_mdio.h> | 15 | #include <linux/of_mdio.h> |
| 15 | 16 | ||
diff --git a/drivers/serial/mpc52xx_uart.c b/drivers/serial/mpc52xx_uart.c index 8dedb266f143..c4399e23565a 100644 --- a/drivers/serial/mpc52xx_uart.c +++ b/drivers/serial/mpc52xx_uart.c | |||
| @@ -500,6 +500,7 @@ static int __init mpc512x_psc_fifoc_init(void) | |||
| 500 | psc_fifoc = of_iomap(np, 0); | 500 | psc_fifoc = of_iomap(np, 0); |
| 501 | if (!psc_fifoc) { | 501 | if (!psc_fifoc) { |
| 502 | pr_err("%s: Can't map FIFOC\n", __func__); | 502 | pr_err("%s: Can't map FIFOC\n", __func__); |
| 503 | of_node_put(np); | ||
| 503 | return -ENODEV; | 504 | return -ENODEV; |
| 504 | } | 505 | } |
| 505 | 506 | ||
diff --git a/drivers/spi/amba-pl022.c b/drivers/spi/amba-pl022.c index acd35d1ebd12..4c37c4e28647 100644 --- a/drivers/spi/amba-pl022.c +++ b/drivers/spi/amba-pl022.c | |||
| @@ -503,8 +503,9 @@ static void giveback(struct pl022 *pl022) | |||
| 503 | msg->state = NULL; | 503 | msg->state = NULL; |
| 504 | if (msg->complete) | 504 | if (msg->complete) |
| 505 | msg->complete(msg->context); | 505 | msg->complete(msg->context); |
| 506 | /* This message is completed, so let's turn off the clock! */ | 506 | /* This message is completed, so let's turn off the clocks! */ |
| 507 | clk_disable(pl022->clk); | 507 | clk_disable(pl022->clk); |
| 508 | amba_pclk_disable(pl022->adev); | ||
| 508 | } | 509 | } |
| 509 | 510 | ||
| 510 | /** | 511 | /** |
| @@ -1139,9 +1140,10 @@ static void pump_messages(struct work_struct *work) | |||
| 1139 | /* Setup the SPI using the per chip configuration */ | 1140 | /* Setup the SPI using the per chip configuration */ |
| 1140 | pl022->cur_chip = spi_get_ctldata(pl022->cur_msg->spi); | 1141 | pl022->cur_chip = spi_get_ctldata(pl022->cur_msg->spi); |
| 1141 | /* | 1142 | /* |
| 1142 | * We enable the clock here, then the clock will be disabled when | 1143 | * We enable the clocks here, then the clocks will be disabled when |
| 1143 | * giveback() is called in each method (poll/interrupt/DMA) | 1144 | * giveback() is called in each method (poll/interrupt/DMA) |
| 1144 | */ | 1145 | */ |
| 1146 | amba_pclk_enable(pl022->adev); | ||
| 1145 | clk_enable(pl022->clk); | 1147 | clk_enable(pl022->clk); |
| 1146 | restore_state(pl022); | 1148 | restore_state(pl022); |
| 1147 | flush(pl022); | 1149 | flush(pl022); |
| @@ -1786,11 +1788,9 @@ pl022_probe(struct amba_device *adev, struct amba_id *id) | |||
| 1786 | } | 1788 | } |
| 1787 | 1789 | ||
| 1788 | /* Disable SSP */ | 1790 | /* Disable SSP */ |
| 1789 | clk_enable(pl022->clk); | ||
| 1790 | writew((readw(SSP_CR1(pl022->virtbase)) & (~SSP_CR1_MASK_SSE)), | 1791 | writew((readw(SSP_CR1(pl022->virtbase)) & (~SSP_CR1_MASK_SSE)), |
| 1791 | SSP_CR1(pl022->virtbase)); | 1792 | SSP_CR1(pl022->virtbase)); |
| 1792 | load_ssp_default_config(pl022); | 1793 | load_ssp_default_config(pl022); |
| 1793 | clk_disable(pl022->clk); | ||
| 1794 | 1794 | ||
| 1795 | status = request_irq(adev->irq[0], pl022_interrupt_handler, 0, "pl022", | 1795 | status = request_irq(adev->irq[0], pl022_interrupt_handler, 0, "pl022", |
| 1796 | pl022); | 1796 | pl022); |
| @@ -1818,6 +1818,8 @@ pl022_probe(struct amba_device *adev, struct amba_id *id) | |||
| 1818 | goto err_spi_register; | 1818 | goto err_spi_register; |
| 1819 | } | 1819 | } |
| 1820 | dev_dbg(dev, "probe succeded\n"); | 1820 | dev_dbg(dev, "probe succeded\n"); |
| 1821 | /* Disable the silicon block pclk and clock it when needed */ | ||
| 1822 | amba_pclk_disable(adev); | ||
| 1821 | return 0; | 1823 | return 0; |
| 1822 | 1824 | ||
| 1823 | err_spi_register: | 1825 | err_spi_register: |
| @@ -1879,9 +1881,9 @@ static int pl022_suspend(struct amba_device *adev, pm_message_t state) | |||
| 1879 | return status; | 1881 | return status; |
| 1880 | } | 1882 | } |
| 1881 | 1883 | ||
| 1882 | clk_enable(pl022->clk); | 1884 | amba_pclk_enable(adev); |
| 1883 | load_ssp_default_config(pl022); | 1885 | load_ssp_default_config(pl022); |
| 1884 | clk_disable(pl022->clk); | 1886 | amba_pclk_disable(adev); |
| 1885 | dev_dbg(&adev->dev, "suspended\n"); | 1887 | dev_dbg(&adev->dev, "suspended\n"); |
| 1886 | return 0; | 1888 | return 0; |
| 1887 | } | 1889 | } |
| @@ -1981,7 +1983,7 @@ static int __init pl022_init(void) | |||
| 1981 | return amba_driver_register(&pl022_driver); | 1983 | return amba_driver_register(&pl022_driver); |
| 1982 | } | 1984 | } |
| 1983 | 1985 | ||
| 1984 | module_init(pl022_init); | 1986 | subsys_initcall(pl022_init); |
| 1985 | 1987 | ||
| 1986 | static void __exit pl022_exit(void) | 1988 | static void __exit pl022_exit(void) |
| 1987 | { | 1989 | { |
diff --git a/drivers/spi/dw_spi.c b/drivers/spi/dw_spi.c index d256cb00604c..56247853c298 100644 --- a/drivers/spi/dw_spi.c +++ b/drivers/spi/dw_spi.c | |||
| @@ -181,10 +181,6 @@ static void flush(struct dw_spi *dws) | |||
| 181 | wait_till_not_busy(dws); | 181 | wait_till_not_busy(dws); |
| 182 | } | 182 | } |
| 183 | 183 | ||
| 184 | static void null_cs_control(u32 command) | ||
| 185 | { | ||
| 186 | } | ||
| 187 | |||
| 188 | static int null_writer(struct dw_spi *dws) | 184 | static int null_writer(struct dw_spi *dws) |
| 189 | { | 185 | { |
| 190 | u8 n_bytes = dws->n_bytes; | 186 | u8 n_bytes = dws->n_bytes; |
| @@ -322,7 +318,7 @@ static void giveback(struct dw_spi *dws) | |||
| 322 | struct spi_transfer, | 318 | struct spi_transfer, |
| 323 | transfer_list); | 319 | transfer_list); |
| 324 | 320 | ||
| 325 | if (!last_transfer->cs_change) | 321 | if (!last_transfer->cs_change && dws->cs_control) |
| 326 | dws->cs_control(MRST_SPI_DEASSERT); | 322 | dws->cs_control(MRST_SPI_DEASSERT); |
| 327 | 323 | ||
| 328 | msg->state = NULL; | 324 | msg->state = NULL; |
| @@ -396,6 +392,11 @@ static irqreturn_t interrupt_transfer(struct dw_spi *dws) | |||
| 396 | static irqreturn_t dw_spi_irq(int irq, void *dev_id) | 392 | static irqreturn_t dw_spi_irq(int irq, void *dev_id) |
| 397 | { | 393 | { |
| 398 | struct dw_spi *dws = dev_id; | 394 | struct dw_spi *dws = dev_id; |
| 395 | u16 irq_status, irq_mask = 0x3f; | ||
| 396 | |||
| 397 | irq_status = dw_readw(dws, isr) & irq_mask; | ||
| 398 | if (!irq_status) | ||
| 399 | return IRQ_NONE; | ||
| 399 | 400 | ||
| 400 | if (!dws->cur_msg) { | 401 | if (!dws->cur_msg) { |
| 401 | spi_mask_intr(dws, SPI_INT_TXEI); | 402 | spi_mask_intr(dws, SPI_INT_TXEI); |
| @@ -544,13 +545,13 @@ static void pump_transfers(unsigned long data) | |||
| 544 | */ | 545 | */ |
| 545 | if (dws->cs_control) { | 546 | if (dws->cs_control) { |
| 546 | if (dws->rx && dws->tx) | 547 | if (dws->rx && dws->tx) |
| 547 | chip->tmode = 0x00; | 548 | chip->tmode = SPI_TMOD_TR; |
| 548 | else if (dws->rx) | 549 | else if (dws->rx) |
| 549 | chip->tmode = 0x02; | 550 | chip->tmode = SPI_TMOD_RO; |
| 550 | else | 551 | else |
| 551 | chip->tmode = 0x01; | 552 | chip->tmode = SPI_TMOD_TO; |
| 552 | 553 | ||
| 553 | cr0 &= ~(0x3 << SPI_MODE_OFFSET); | 554 | cr0 &= ~SPI_TMOD_MASK; |
| 554 | cr0 |= (chip->tmode << SPI_TMOD_OFFSET); | 555 | cr0 |= (chip->tmode << SPI_TMOD_OFFSET); |
| 555 | } | 556 | } |
| 556 | 557 | ||
| @@ -699,9 +700,6 @@ static int dw_spi_setup(struct spi_device *spi) | |||
| 699 | chip = kzalloc(sizeof(struct chip_data), GFP_KERNEL); | 700 | chip = kzalloc(sizeof(struct chip_data), GFP_KERNEL); |
| 700 | if (!chip) | 701 | if (!chip) |
| 701 | return -ENOMEM; | 702 | return -ENOMEM; |
| 702 | |||
| 703 | chip->cs_control = null_cs_control; | ||
| 704 | chip->enable_dma = 0; | ||
| 705 | } | 703 | } |
| 706 | 704 | ||
| 707 | /* | 705 | /* |
| @@ -883,7 +881,7 @@ int __devinit dw_spi_add_host(struct dw_spi *dws) | |||
| 883 | dws->dma_inited = 0; | 881 | dws->dma_inited = 0; |
| 884 | dws->dma_addr = (dma_addr_t)(dws->paddr + 0x60); | 882 | dws->dma_addr = (dma_addr_t)(dws->paddr + 0x60); |
| 885 | 883 | ||
| 886 | ret = request_irq(dws->irq, dw_spi_irq, 0, | 884 | ret = request_irq(dws->irq, dw_spi_irq, IRQF_SHARED, |
| 887 | "dw_spi", dws); | 885 | "dw_spi", dws); |
| 888 | if (ret < 0) { | 886 | if (ret < 0) { |
| 889 | dev_err(&master->dev, "can not get IRQ\n"); | 887 | dev_err(&master->dev, "can not get IRQ\n"); |
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index a9e5c79ae52a..0bcf4c1601a2 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c | |||
| @@ -554,11 +554,9 @@ done: | |||
| 554 | EXPORT_SYMBOL_GPL(spi_register_master); | 554 | EXPORT_SYMBOL_GPL(spi_register_master); |
| 555 | 555 | ||
| 556 | 556 | ||
| 557 | static int __unregister(struct device *dev, void *master_dev) | 557 | static int __unregister(struct device *dev, void *null) |
| 558 | { | 558 | { |
| 559 | /* note: before about 2.6.14-rc1 this would corrupt memory: */ | 559 | spi_unregister_device(to_spi_device(dev)); |
| 560 | if (dev != master_dev) | ||
| 561 | spi_unregister_device(to_spi_device(dev)); | ||
| 562 | return 0; | 560 | return 0; |
| 563 | } | 561 | } |
| 564 | 562 | ||
| @@ -576,8 +574,7 @@ void spi_unregister_master(struct spi_master *master) | |||
| 576 | { | 574 | { |
| 577 | int dummy; | 575 | int dummy; |
| 578 | 576 | ||
| 579 | dummy = device_for_each_child(master->dev.parent, &master->dev, | 577 | dummy = device_for_each_child(&master->dev, NULL, __unregister); |
| 580 | __unregister); | ||
| 581 | device_unregister(&master->dev); | 578 | device_unregister(&master->dev); |
| 582 | } | 579 | } |
| 583 | EXPORT_SYMBOL_GPL(spi_unregister_master); | 580 | EXPORT_SYMBOL_GPL(spi_unregister_master); |
diff --git a/drivers/spi/spi_s3c64xx.c b/drivers/spi/spi_s3c64xx.c index 97365815a729..c3038da2648a 100644 --- a/drivers/spi/spi_s3c64xx.c +++ b/drivers/spi/spi_s3c64xx.c | |||
| @@ -200,6 +200,9 @@ static void flush_fifo(struct s3c64xx_spi_driver_data *sdd) | |||
| 200 | val = readl(regs + S3C64XX_SPI_STATUS); | 200 | val = readl(regs + S3C64XX_SPI_STATUS); |
| 201 | } while (TX_FIFO_LVL(val, sci) && loops--); | 201 | } while (TX_FIFO_LVL(val, sci) && loops--); |
| 202 | 202 | ||
| 203 | if (loops == 0) | ||
| 204 | dev_warn(&sdd->pdev->dev, "Timed out flushing TX FIFO\n"); | ||
| 205 | |||
| 203 | /* Flush RxFIFO*/ | 206 | /* Flush RxFIFO*/ |
| 204 | loops = msecs_to_loops(1); | 207 | loops = msecs_to_loops(1); |
| 205 | do { | 208 | do { |
| @@ -210,6 +213,9 @@ static void flush_fifo(struct s3c64xx_spi_driver_data *sdd) | |||
| 210 | break; | 213 | break; |
| 211 | } while (loops--); | 214 | } while (loops--); |
| 212 | 215 | ||
| 216 | if (loops == 0) | ||
| 217 | dev_warn(&sdd->pdev->dev, "Timed out flushing RX FIFO\n"); | ||
| 218 | |||
| 213 | val = readl(regs + S3C64XX_SPI_CH_CFG); | 219 | val = readl(regs + S3C64XX_SPI_CH_CFG); |
| 214 | val &= ~S3C64XX_SPI_CH_SW_RST; | 220 | val &= ~S3C64XX_SPI_CH_SW_RST; |
| 215 | writel(val, regs + S3C64XX_SPI_CH_CFG); | 221 | writel(val, regs + S3C64XX_SPI_CH_CFG); |
| @@ -320,16 +326,17 @@ static int wait_for_xfer(struct s3c64xx_spi_driver_data *sdd, | |||
| 320 | 326 | ||
| 321 | /* millisecs to xfer 'len' bytes @ 'cur_speed' */ | 327 | /* millisecs to xfer 'len' bytes @ 'cur_speed' */ |
| 322 | ms = xfer->len * 8 * 1000 / sdd->cur_speed; | 328 | ms = xfer->len * 8 * 1000 / sdd->cur_speed; |
| 323 | ms += 5; /* some tolerance */ | 329 | ms += 10; /* some tolerance */ |
| 324 | 330 | ||
| 325 | if (dma_mode) { | 331 | if (dma_mode) { |
| 326 | val = msecs_to_jiffies(ms) + 10; | 332 | val = msecs_to_jiffies(ms) + 10; |
| 327 | val = wait_for_completion_timeout(&sdd->xfer_completion, val); | 333 | val = wait_for_completion_timeout(&sdd->xfer_completion, val); |
| 328 | } else { | 334 | } else { |
| 335 | u32 status; | ||
| 329 | val = msecs_to_loops(ms); | 336 | val = msecs_to_loops(ms); |
| 330 | do { | 337 | do { |
| 331 | val = readl(regs + S3C64XX_SPI_STATUS); | 338 | status = readl(regs + S3C64XX_SPI_STATUS); |
| 332 | } while (RX_FIFO_LVL(val, sci) < xfer->len && --val); | 339 | } while (RX_FIFO_LVL(status, sci) < xfer->len && --val); |
| 333 | } | 340 | } |
| 334 | 341 | ||
| 335 | if (!val) | 342 | if (!val) |
| @@ -447,8 +454,8 @@ static void s3c64xx_spi_config(struct s3c64xx_spi_driver_data *sdd) | |||
| 447 | writel(val, regs + S3C64XX_SPI_CLK_CFG); | 454 | writel(val, regs + S3C64XX_SPI_CLK_CFG); |
| 448 | } | 455 | } |
| 449 | 456 | ||
| 450 | void s3c64xx_spi_dma_rxcb(struct s3c2410_dma_chan *chan, void *buf_id, | 457 | static void s3c64xx_spi_dma_rxcb(struct s3c2410_dma_chan *chan, void *buf_id, |
| 451 | int size, enum s3c2410_dma_buffresult res) | 458 | int size, enum s3c2410_dma_buffresult res) |
| 452 | { | 459 | { |
| 453 | struct s3c64xx_spi_driver_data *sdd = buf_id; | 460 | struct s3c64xx_spi_driver_data *sdd = buf_id; |
| 454 | unsigned long flags; | 461 | unsigned long flags; |
| @@ -467,8 +474,8 @@ void s3c64xx_spi_dma_rxcb(struct s3c2410_dma_chan *chan, void *buf_id, | |||
| 467 | spin_unlock_irqrestore(&sdd->lock, flags); | 474 | spin_unlock_irqrestore(&sdd->lock, flags); |
| 468 | } | 475 | } |
| 469 | 476 | ||
| 470 | void s3c64xx_spi_dma_txcb(struct s3c2410_dma_chan *chan, void *buf_id, | 477 | static void s3c64xx_spi_dma_txcb(struct s3c2410_dma_chan *chan, void *buf_id, |
| 471 | int size, enum s3c2410_dma_buffresult res) | 478 | int size, enum s3c2410_dma_buffresult res) |
| 472 | { | 479 | { |
| 473 | struct s3c64xx_spi_driver_data *sdd = buf_id; | 480 | struct s3c64xx_spi_driver_data *sdd = buf_id; |
| 474 | unsigned long flags; | 481 | unsigned long flags; |
| @@ -508,8 +515,9 @@ static int s3c64xx_spi_map_mssg(struct s3c64xx_spi_driver_data *sdd, | |||
| 508 | list_for_each_entry(xfer, &msg->transfers, transfer_list) { | 515 | list_for_each_entry(xfer, &msg->transfers, transfer_list) { |
| 509 | 516 | ||
| 510 | if (xfer->tx_buf != NULL) { | 517 | if (xfer->tx_buf != NULL) { |
| 511 | xfer->tx_dma = dma_map_single(dev, xfer->tx_buf, | 518 | xfer->tx_dma = dma_map_single(dev, |
| 512 | xfer->len, DMA_TO_DEVICE); | 519 | (void *)xfer->tx_buf, xfer->len, |
| 520 | DMA_TO_DEVICE); | ||
| 513 | if (dma_mapping_error(dev, xfer->tx_dma)) { | 521 | if (dma_mapping_error(dev, xfer->tx_dma)) { |
| 514 | dev_err(dev, "dma_map_single Tx failed\n"); | 522 | dev_err(dev, "dma_map_single Tx failed\n"); |
| 515 | xfer->tx_dma = XFER_DMAADDR_INVALID; | 523 | xfer->tx_dma = XFER_DMAADDR_INVALID; |
| @@ -919,6 +927,13 @@ static int __init s3c64xx_spi_probe(struct platform_device *pdev) | |||
| 919 | return -ENODEV; | 927 | return -ENODEV; |
| 920 | } | 928 | } |
| 921 | 929 | ||
| 930 | sci = pdev->dev.platform_data; | ||
| 931 | if (!sci->src_clk_name) { | ||
| 932 | dev_err(&pdev->dev, | ||
| 933 | "Board init must call s3c64xx_spi_set_info()\n"); | ||
| 934 | return -EINVAL; | ||
| 935 | } | ||
| 936 | |||
| 922 | /* Check for availability of necessary resource */ | 937 | /* Check for availability of necessary resource */ |
| 923 | 938 | ||
| 924 | dmatx_res = platform_get_resource(pdev, IORESOURCE_DMA, 0); | 939 | dmatx_res = platform_get_resource(pdev, IORESOURCE_DMA, 0); |
| @@ -946,8 +961,6 @@ static int __init s3c64xx_spi_probe(struct platform_device *pdev) | |||
| 946 | return -ENOMEM; | 961 | return -ENOMEM; |
| 947 | } | 962 | } |
| 948 | 963 | ||
| 949 | sci = pdev->dev.platform_data; | ||
| 950 | |||
| 951 | platform_set_drvdata(pdev, master); | 964 | platform_set_drvdata(pdev, master); |
| 952 | 965 | ||
| 953 | sdd = spi_master_get_devdata(master); | 966 | sdd = spi_master_get_devdata(master); |
| @@ -1170,7 +1183,7 @@ static int __init s3c64xx_spi_init(void) | |||
| 1170 | { | 1183 | { |
| 1171 | return platform_driver_probe(&s3c64xx_spi_driver, s3c64xx_spi_probe); | 1184 | return platform_driver_probe(&s3c64xx_spi_driver, s3c64xx_spi_probe); |
| 1172 | } | 1185 | } |
| 1173 | module_init(s3c64xx_spi_init); | 1186 | subsys_initcall(s3c64xx_spi_init); |
| 1174 | 1187 | ||
| 1175 | static void __exit s3c64xx_spi_exit(void) | 1188 | static void __exit s3c64xx_spi_exit(void) |
| 1176 | { | 1189 | { |
diff --git a/fs/9p/vfs_dir.c b/fs/9p/vfs_dir.c index 16c8a2a98c1b..899f168fd19c 100644 --- a/fs/9p/vfs_dir.c +++ b/fs/9p/vfs_dir.c | |||
| @@ -292,9 +292,11 @@ int v9fs_dir_release(struct inode *inode, struct file *filp) | |||
| 292 | 292 | ||
| 293 | fid = filp->private_data; | 293 | fid = filp->private_data; |
| 294 | P9_DPRINTK(P9_DEBUG_VFS, | 294 | P9_DPRINTK(P9_DEBUG_VFS, |
| 295 | "inode: %p filp: %p fid: %d\n", inode, filp, fid->fid); | 295 | "v9fs_dir_release: inode: %p filp: %p fid: %d\n", |
| 296 | inode, filp, fid ? fid->fid : -1); | ||
| 296 | filemap_write_and_wait(inode->i_mapping); | 297 | filemap_write_and_wait(inode->i_mapping); |
| 297 | p9_client_clunk(fid); | 298 | if (fid) |
| 299 | p9_client_clunk(fid); | ||
| 298 | return 0; | 300 | return 0; |
| 299 | } | 301 | } |
| 300 | 302 | ||
diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c index c7c23eab9440..9e670d527646 100644 --- a/fs/9p/vfs_inode.c +++ b/fs/9p/vfs_inode.c | |||
| @@ -730,7 +730,10 @@ v9fs_vfs_create_dotl(struct inode *dir, struct dentry *dentry, int mode, | |||
| 730 | P9_DPRINTK(P9_DEBUG_VFS, "inode creation failed %d\n", err); | 730 | P9_DPRINTK(P9_DEBUG_VFS, "inode creation failed %d\n", err); |
| 731 | goto error; | 731 | goto error; |
| 732 | } | 732 | } |
| 733 | dentry->d_op = &v9fs_cached_dentry_operations; | 733 | if (v9ses->cache) |
| 734 | dentry->d_op = &v9fs_cached_dentry_operations; | ||
| 735 | else | ||
| 736 | dentry->d_op = &v9fs_dentry_operations; | ||
| 734 | d_instantiate(dentry, inode); | 737 | d_instantiate(dentry, inode); |
| 735 | err = v9fs_fid_add(dentry, fid); | 738 | err = v9fs_fid_add(dentry, fid); |
| 736 | if (err < 0) | 739 | if (err < 0) |
| @@ -1128,6 +1131,7 @@ v9fs_vfs_getattr(struct vfsmount *mnt, struct dentry *dentry, | |||
| 1128 | v9fs_stat2inode(st, dentry->d_inode, dentry->d_inode->i_sb); | 1131 | v9fs_stat2inode(st, dentry->d_inode, dentry->d_inode->i_sb); |
| 1129 | generic_fillattr(dentry->d_inode, stat); | 1132 | generic_fillattr(dentry->d_inode, stat); |
| 1130 | 1133 | ||
| 1134 | p9stat_free(st); | ||
| 1131 | kfree(st); | 1135 | kfree(st); |
| 1132 | return 0; | 1136 | return 0; |
| 1133 | } | 1137 | } |
| @@ -1489,6 +1493,7 @@ static int v9fs_readlink(struct dentry *dentry, char *buffer, int buflen) | |||
| 1489 | 1493 | ||
| 1490 | retval = strnlen(buffer, buflen); | 1494 | retval = strnlen(buffer, buflen); |
| 1491 | done: | 1495 | done: |
| 1496 | p9stat_free(st); | ||
| 1492 | kfree(st); | 1497 | kfree(st); |
| 1493 | return retval; | 1498 | return retval; |
| 1494 | } | 1499 | } |
| @@ -1942,7 +1947,7 @@ static const struct inode_operations v9fs_dir_inode_operations_dotu = { | |||
| 1942 | .unlink = v9fs_vfs_unlink, | 1947 | .unlink = v9fs_vfs_unlink, |
| 1943 | .mkdir = v9fs_vfs_mkdir, | 1948 | .mkdir = v9fs_vfs_mkdir, |
| 1944 | .rmdir = v9fs_vfs_rmdir, | 1949 | .rmdir = v9fs_vfs_rmdir, |
| 1945 | .mknod = v9fs_vfs_mknod_dotl, | 1950 | .mknod = v9fs_vfs_mknod, |
| 1946 | .rename = v9fs_vfs_rename, | 1951 | .rename = v9fs_vfs_rename, |
| 1947 | .getattr = v9fs_vfs_getattr, | 1952 | .getattr = v9fs_vfs_getattr, |
| 1948 | .setattr = v9fs_vfs_setattr, | 1953 | .setattr = v9fs_vfs_setattr, |
diff --git a/fs/9p/vfs_super.c b/fs/9p/vfs_super.c index f9311077de68..1d12ba0ed3db 100644 --- a/fs/9p/vfs_super.c +++ b/fs/9p/vfs_super.c | |||
| @@ -122,6 +122,10 @@ static int v9fs_get_sb(struct file_system_type *fs_type, int flags, | |||
| 122 | fid = v9fs_session_init(v9ses, dev_name, data); | 122 | fid = v9fs_session_init(v9ses, dev_name, data); |
| 123 | if (IS_ERR(fid)) { | 123 | if (IS_ERR(fid)) { |
| 124 | retval = PTR_ERR(fid); | 124 | retval = PTR_ERR(fid); |
| 125 | /* | ||
| 126 | * we need to call session_close to tear down some | ||
| 127 | * of the data structure setup by session_init | ||
| 128 | */ | ||
| 125 | goto close_session; | 129 | goto close_session; |
| 126 | } | 130 | } |
| 127 | 131 | ||
| @@ -144,7 +148,6 @@ static int v9fs_get_sb(struct file_system_type *fs_type, int flags, | |||
| 144 | retval = -ENOMEM; | 148 | retval = -ENOMEM; |
| 145 | goto release_sb; | 149 | goto release_sb; |
| 146 | } | 150 | } |
| 147 | |||
| 148 | sb->s_root = root; | 151 | sb->s_root = root; |
| 149 | 152 | ||
| 150 | if (v9fs_proto_dotl(v9ses)) { | 153 | if (v9fs_proto_dotl(v9ses)) { |
| @@ -152,7 +155,7 @@ static int v9fs_get_sb(struct file_system_type *fs_type, int flags, | |||
| 152 | st = p9_client_getattr_dotl(fid, P9_STATS_BASIC); | 155 | st = p9_client_getattr_dotl(fid, P9_STATS_BASIC); |
| 153 | if (IS_ERR(st)) { | 156 | if (IS_ERR(st)) { |
| 154 | retval = PTR_ERR(st); | 157 | retval = PTR_ERR(st); |
| 155 | goto clunk_fid; | 158 | goto release_sb; |
| 156 | } | 159 | } |
| 157 | 160 | ||
| 158 | v9fs_stat2inode_dotl(st, root->d_inode); | 161 | v9fs_stat2inode_dotl(st, root->d_inode); |
| @@ -162,7 +165,7 @@ static int v9fs_get_sb(struct file_system_type *fs_type, int flags, | |||
| 162 | st = p9_client_stat(fid); | 165 | st = p9_client_stat(fid); |
| 163 | if (IS_ERR(st)) { | 166 | if (IS_ERR(st)) { |
| 164 | retval = PTR_ERR(st); | 167 | retval = PTR_ERR(st); |
| 165 | goto clunk_fid; | 168 | goto release_sb; |
| 166 | } | 169 | } |
| 167 | 170 | ||
| 168 | root->d_inode->i_ino = v9fs_qid2ino(&st->qid); | 171 | root->d_inode->i_ino = v9fs_qid2ino(&st->qid); |
| @@ -174,19 +177,24 @@ static int v9fs_get_sb(struct file_system_type *fs_type, int flags, | |||
| 174 | 177 | ||
| 175 | v9fs_fid_add(root, fid); | 178 | v9fs_fid_add(root, fid); |
| 176 | 179 | ||
| 177 | P9_DPRINTK(P9_DEBUG_VFS, " simple set mount, return 0\n"); | 180 | P9_DPRINTK(P9_DEBUG_VFS, " simple set mount, return 0\n"); |
| 178 | simple_set_mnt(mnt, sb); | 181 | simple_set_mnt(mnt, sb); |
| 179 | return 0; | 182 | return 0; |
| 180 | 183 | ||
| 181 | clunk_fid: | 184 | clunk_fid: |
| 182 | p9_client_clunk(fid); | 185 | p9_client_clunk(fid); |
| 183 | |||
| 184 | close_session: | 186 | close_session: |
| 185 | v9fs_session_close(v9ses); | 187 | v9fs_session_close(v9ses); |
| 186 | kfree(v9ses); | 188 | kfree(v9ses); |
| 187 | return retval; | 189 | return retval; |
| 188 | |||
| 189 | release_sb: | 190 | release_sb: |
| 191 | /* | ||
| 192 | * we will do the session_close and root dentry release | ||
| 193 | * in the below call. But we need to clunk fid, because we haven't | ||
| 194 | * attached the fid to dentry so it won't get clunked | ||
| 195 | * automatically. | ||
| 196 | */ | ||
| 197 | p9_client_clunk(fid); | ||
| 190 | deactivate_locked_super(sb); | 198 | deactivate_locked_super(sb); |
| 191 | return retval; | 199 | return retval; |
| 192 | } | 200 | } |
| @@ -1659,6 +1659,9 @@ long do_io_submit(aio_context_t ctx_id, long nr, | |||
| 1659 | if (unlikely(nr < 0)) | 1659 | if (unlikely(nr < 0)) |
| 1660 | return -EINVAL; | 1660 | return -EINVAL; |
| 1661 | 1661 | ||
| 1662 | if (unlikely(nr > LONG_MAX/sizeof(*iocbpp))) | ||
| 1663 | nr = LONG_MAX/sizeof(*iocbpp); | ||
| 1664 | |||
| 1662 | if (unlikely(!access_ok(VERIFY_READ, iocbpp, (nr*sizeof(*iocbpp))))) | 1665 | if (unlikely(!access_ok(VERIFY_READ, iocbpp, (nr*sizeof(*iocbpp))))) |
| 1663 | return -EFAULT; | 1666 | return -EFAULT; |
| 1664 | 1667 | ||
diff --git a/fs/cifs/Kconfig b/fs/cifs/Kconfig index 0da1debd499d..917b7d449bb2 100644 --- a/fs/cifs/Kconfig +++ b/fs/cifs/Kconfig | |||
| @@ -2,8 +2,6 @@ config CIFS | |||
| 2 | tristate "CIFS support (advanced network filesystem, SMBFS successor)" | 2 | tristate "CIFS support (advanced network filesystem, SMBFS successor)" |
| 3 | depends on INET | 3 | depends on INET |
| 4 | select NLS | 4 | select NLS |
| 5 | select CRYPTO_MD5 | ||
| 6 | select CRYPTO_ARC4 | ||
| 7 | help | 5 | help |
| 8 | This is the client VFS module for the Common Internet File System | 6 | This is the client VFS module for the Common Internet File System |
| 9 | (CIFS) protocol which is the successor to the Server Message Block | 7 | (CIFS) protocol which is the successor to the Server Message Block |
diff --git a/fs/cifs/asn1.c b/fs/cifs/asn1.c index 21f0fbd86989..cfd1ce34e0bc 100644 --- a/fs/cifs/asn1.c +++ b/fs/cifs/asn1.c | |||
| @@ -597,13 +597,13 @@ decode_negTokenInit(unsigned char *security_blob, int length, | |||
| 597 | if (compare_oid(oid, oidlen, MSKRB5_OID, | 597 | if (compare_oid(oid, oidlen, MSKRB5_OID, |
| 598 | MSKRB5_OID_LEN)) | 598 | MSKRB5_OID_LEN)) |
| 599 | server->sec_mskerberos = true; | 599 | server->sec_mskerberos = true; |
| 600 | if (compare_oid(oid, oidlen, KRB5U2U_OID, | 600 | else if (compare_oid(oid, oidlen, KRB5U2U_OID, |
| 601 | KRB5U2U_OID_LEN)) | 601 | KRB5U2U_OID_LEN)) |
| 602 | server->sec_kerberosu2u = true; | 602 | server->sec_kerberosu2u = true; |
| 603 | if (compare_oid(oid, oidlen, KRB5_OID, | 603 | else if (compare_oid(oid, oidlen, KRB5_OID, |
| 604 | KRB5_OID_LEN)) | 604 | KRB5_OID_LEN)) |
| 605 | server->sec_kerberos = true; | 605 | server->sec_kerberos = true; |
| 606 | if (compare_oid(oid, oidlen, NTLMSSP_OID, | 606 | else if (compare_oid(oid, oidlen, NTLMSSP_OID, |
| 607 | NTLMSSP_OID_LEN)) | 607 | NTLMSSP_OID_LEN)) |
| 608 | server->sec_ntlmssp = true; | 608 | server->sec_ntlmssp = true; |
| 609 | 609 | ||
diff --git a/fs/cifs/cifsencrypt.c b/fs/cifs/cifsencrypt.c index 709f2296bdb4..35042d8f7338 100644 --- a/fs/cifs/cifsencrypt.c +++ b/fs/cifs/cifsencrypt.c | |||
| @@ -27,7 +27,6 @@ | |||
| 27 | #include "md5.h" | 27 | #include "md5.h" |
| 28 | #include "cifs_unicode.h" | 28 | #include "cifs_unicode.h" |
| 29 | #include "cifsproto.h" | 29 | #include "cifsproto.h" |
| 30 | #include "ntlmssp.h" | ||
| 31 | #include <linux/ctype.h> | 30 | #include <linux/ctype.h> |
| 32 | #include <linux/random.h> | 31 | #include <linux/random.h> |
| 33 | 32 | ||
| @@ -43,43 +42,21 @@ extern void SMBencrypt(unsigned char *passwd, const unsigned char *c8, | |||
| 43 | unsigned char *p24); | 42 | unsigned char *p24); |
| 44 | 43 | ||
| 45 | static int cifs_calculate_signature(const struct smb_hdr *cifs_pdu, | 44 | static int cifs_calculate_signature(const struct smb_hdr *cifs_pdu, |
| 46 | struct TCP_Server_Info *server, char *signature) | 45 | const struct mac_key *key, char *signature) |
| 47 | { | 46 | { |
| 48 | int rc; | 47 | struct MD5Context context; |
| 49 | 48 | ||
| 50 | if (cifs_pdu == NULL || server == NULL || signature == NULL) | 49 | if ((cifs_pdu == NULL) || (signature == NULL) || (key == NULL)) |
| 51 | return -EINVAL; | 50 | return -EINVAL; |
| 52 | 51 | ||
| 53 | if (!server->ntlmssp.sdescmd5) { | 52 | cifs_MD5_init(&context); |
| 54 | cERROR(1, | 53 | cifs_MD5_update(&context, (char *)&key->data, key->len); |
| 55 | "cifs_calculate_signature: can't generate signature\n"); | 54 | cifs_MD5_update(&context, cifs_pdu->Protocol, cifs_pdu->smb_buf_length); |
| 56 | return -1; | ||
| 57 | } | ||
| 58 | |||
| 59 | rc = crypto_shash_init(&server->ntlmssp.sdescmd5->shash); | ||
| 60 | if (rc) { | ||
| 61 | cERROR(1, "cifs_calculate_signature: oould not init md5\n"); | ||
| 62 | return rc; | ||
| 63 | } | ||
| 64 | |||
| 65 | if (server->secType == RawNTLMSSP) | ||
| 66 | crypto_shash_update(&server->ntlmssp.sdescmd5->shash, | ||
| 67 | server->session_key.data.ntlmv2.key, | ||
| 68 | CIFS_NTLMV2_SESSKEY_SIZE); | ||
| 69 | else | ||
| 70 | crypto_shash_update(&server->ntlmssp.sdescmd5->shash, | ||
| 71 | (char *)&server->session_key.data, | ||
| 72 | server->session_key.len); | ||
| 73 | |||
| 74 | crypto_shash_update(&server->ntlmssp.sdescmd5->shash, | ||
| 75 | cifs_pdu->Protocol, cifs_pdu->smb_buf_length); | ||
| 76 | 55 | ||
| 77 | rc = crypto_shash_final(&server->ntlmssp.sdescmd5->shash, signature); | 56 | cifs_MD5_final(signature, &context); |
| 78 | 57 | return 0; | |
| 79 | return rc; | ||
| 80 | } | 58 | } |
| 81 | 59 | ||
| 82 | |||
| 83 | int cifs_sign_smb(struct smb_hdr *cifs_pdu, struct TCP_Server_Info *server, | 60 | int cifs_sign_smb(struct smb_hdr *cifs_pdu, struct TCP_Server_Info *server, |
| 84 | __u32 *pexpected_response_sequence_number) | 61 | __u32 *pexpected_response_sequence_number) |
| 85 | { | 62 | { |
| @@ -101,7 +78,8 @@ int cifs_sign_smb(struct smb_hdr *cifs_pdu, struct TCP_Server_Info *server, | |||
| 101 | server->sequence_number++; | 78 | server->sequence_number++; |
| 102 | spin_unlock(&GlobalMid_Lock); | 79 | spin_unlock(&GlobalMid_Lock); |
| 103 | 80 | ||
| 104 | rc = cifs_calculate_signature(cifs_pdu, server, smb_signature); | 81 | rc = cifs_calculate_signature(cifs_pdu, &server->mac_signing_key, |
| 82 | smb_signature); | ||
| 105 | if (rc) | 83 | if (rc) |
| 106 | memset(cifs_pdu->Signature.SecuritySignature, 0, 8); | 84 | memset(cifs_pdu->Signature.SecuritySignature, 0, 8); |
| 107 | else | 85 | else |
| @@ -111,39 +89,21 @@ int cifs_sign_smb(struct smb_hdr *cifs_pdu, struct TCP_Server_Info *server, | |||
| 111 | } | 89 | } |
| 112 | 90 | ||
| 113 | static int cifs_calc_signature2(const struct kvec *iov, int n_vec, | 91 | static int cifs_calc_signature2(const struct kvec *iov, int n_vec, |
| 114 | struct TCP_Server_Info *server, char *signature) | 92 | const struct mac_key *key, char *signature) |
| 115 | { | 93 | { |
| 94 | struct MD5Context context; | ||
| 116 | int i; | 95 | int i; |
| 117 | int rc; | ||
| 118 | 96 | ||
| 119 | if (iov == NULL || server == NULL || signature == NULL) | 97 | if ((iov == NULL) || (signature == NULL) || (key == NULL)) |
| 120 | return -EINVAL; | 98 | return -EINVAL; |
| 121 | 99 | ||
| 122 | if (!server->ntlmssp.sdescmd5) { | 100 | cifs_MD5_init(&context); |
| 123 | cERROR(1, "cifs_calc_signature2: can't generate signature\n"); | 101 | cifs_MD5_update(&context, (char *)&key->data, key->len); |
| 124 | return -1; | ||
| 125 | } | ||
| 126 | |||
| 127 | rc = crypto_shash_init(&server->ntlmssp.sdescmd5->shash); | ||
| 128 | if (rc) { | ||
| 129 | cERROR(1, "cifs_calc_signature2: oould not init md5\n"); | ||
| 130 | return rc; | ||
| 131 | } | ||
| 132 | |||
| 133 | if (server->secType == RawNTLMSSP) | ||
| 134 | crypto_shash_update(&server->ntlmssp.sdescmd5->shash, | ||
| 135 | server->session_key.data.ntlmv2.key, | ||
| 136 | CIFS_NTLMV2_SESSKEY_SIZE); | ||
| 137 | else | ||
| 138 | crypto_shash_update(&server->ntlmssp.sdescmd5->shash, | ||
| 139 | (char *)&server->session_key.data, | ||
| 140 | server->session_key.len); | ||
| 141 | |||
| 142 | for (i = 0; i < n_vec; i++) { | 102 | for (i = 0; i < n_vec; i++) { |
| 143 | if (iov[i].iov_len == 0) | 103 | if (iov[i].iov_len == 0) |
| 144 | continue; | 104 | continue; |
| 145 | if (iov[i].iov_base == NULL) { | 105 | if (iov[i].iov_base == NULL) { |
| 146 | cERROR(1, "cifs_calc_signature2: null iovec entry"); | 106 | cERROR(1, "null iovec entry"); |
| 147 | return -EIO; | 107 | return -EIO; |
| 148 | } | 108 | } |
| 149 | /* The first entry includes a length field (which does not get | 109 | /* The first entry includes a length field (which does not get |
| @@ -151,18 +111,18 @@ static int cifs_calc_signature2(const struct kvec *iov, int n_vec, | |||
| 151 | if (i == 0) { | 111 | if (i == 0) { |
| 152 | if (iov[0].iov_len <= 8) /* cmd field at offset 9 */ | 112 | if (iov[0].iov_len <= 8) /* cmd field at offset 9 */ |
| 153 | break; /* nothing to sign or corrupt header */ | 113 | break; /* nothing to sign or corrupt header */ |
| 154 | crypto_shash_update(&server->ntlmssp.sdescmd5->shash, | 114 | cifs_MD5_update(&context, iov[0].iov_base+4, |
| 155 | iov[i].iov_base + 4, iov[i].iov_len - 4); | 115 | iov[0].iov_len-4); |
| 156 | } else | 116 | } else |
| 157 | crypto_shash_update(&server->ntlmssp.sdescmd5->shash, | 117 | cifs_MD5_update(&context, iov[i].iov_base, iov[i].iov_len); |
| 158 | iov[i].iov_base, iov[i].iov_len); | ||
| 159 | } | 118 | } |
| 160 | 119 | ||
| 161 | rc = crypto_shash_final(&server->ntlmssp.sdescmd5->shash, signature); | 120 | cifs_MD5_final(signature, &context); |
| 162 | 121 | ||
| 163 | return rc; | 122 | return 0; |
| 164 | } | 123 | } |
| 165 | 124 | ||
| 125 | |||
| 166 | int cifs_sign_smb2(struct kvec *iov, int n_vec, struct TCP_Server_Info *server, | 126 | int cifs_sign_smb2(struct kvec *iov, int n_vec, struct TCP_Server_Info *server, |
| 167 | __u32 *pexpected_response_sequence_number) | 127 | __u32 *pexpected_response_sequence_number) |
| 168 | { | 128 | { |
| @@ -185,7 +145,8 @@ int cifs_sign_smb2(struct kvec *iov, int n_vec, struct TCP_Server_Info *server, | |||
| 185 | server->sequence_number++; | 145 | server->sequence_number++; |
| 186 | spin_unlock(&GlobalMid_Lock); | 146 | spin_unlock(&GlobalMid_Lock); |
| 187 | 147 | ||
| 188 | rc = cifs_calc_signature2(iov, n_vec, server, smb_signature); | 148 | rc = cifs_calc_signature2(iov, n_vec, &server->mac_signing_key, |
| 149 | smb_signature); | ||
| 189 | if (rc) | 150 | if (rc) |
| 190 | memset(cifs_pdu->Signature.SecuritySignature, 0, 8); | 151 | memset(cifs_pdu->Signature.SecuritySignature, 0, 8); |
| 191 | else | 152 | else |
| @@ -195,14 +156,14 @@ int cifs_sign_smb2(struct kvec *iov, int n_vec, struct TCP_Server_Info *server, | |||
| 195 | } | 156 | } |
| 196 | 157 | ||
| 197 | int cifs_verify_signature(struct smb_hdr *cifs_pdu, | 158 | int cifs_verify_signature(struct smb_hdr *cifs_pdu, |
| 198 | struct TCP_Server_Info *server, | 159 | const struct mac_key *mac_key, |
| 199 | __u32 expected_sequence_number) | 160 | __u32 expected_sequence_number) |
| 200 | { | 161 | { |
| 201 | int rc; | 162 | unsigned int rc; |
| 202 | char server_response_sig[8]; | 163 | char server_response_sig[8]; |
| 203 | char what_we_think_sig_should_be[20]; | 164 | char what_we_think_sig_should_be[20]; |
| 204 | 165 | ||
| 205 | if (cifs_pdu == NULL || server == NULL) | 166 | if ((cifs_pdu == NULL) || (mac_key == NULL)) |
| 206 | return -EINVAL; | 167 | return -EINVAL; |
| 207 | 168 | ||
| 208 | if (cifs_pdu->Command == SMB_COM_NEGOTIATE) | 169 | if (cifs_pdu->Command == SMB_COM_NEGOTIATE) |
| @@ -231,7 +192,7 @@ int cifs_verify_signature(struct smb_hdr *cifs_pdu, | |||
| 231 | cpu_to_le32(expected_sequence_number); | 192 | cpu_to_le32(expected_sequence_number); |
| 232 | cifs_pdu->Signature.Sequence.Reserved = 0; | 193 | cifs_pdu->Signature.Sequence.Reserved = 0; |
| 233 | 194 | ||
| 234 | rc = cifs_calculate_signature(cifs_pdu, server, | 195 | rc = cifs_calculate_signature(cifs_pdu, mac_key, |
| 235 | what_we_think_sig_should_be); | 196 | what_we_think_sig_should_be); |
| 236 | 197 | ||
| 237 | if (rc) | 198 | if (rc) |
| @@ -248,7 +209,7 @@ int cifs_verify_signature(struct smb_hdr *cifs_pdu, | |||
| 248 | } | 209 | } |
| 249 | 210 | ||
| 250 | /* We fill in key by putting in 40 byte array which was allocated by caller */ | 211 | /* We fill in key by putting in 40 byte array which was allocated by caller */ |
| 251 | int cifs_calculate_session_key(struct session_key *key, const char *rn, | 212 | int cifs_calculate_mac_key(struct mac_key *key, const char *rn, |
| 252 | const char *password) | 213 | const char *password) |
| 253 | { | 214 | { |
| 254 | char temp_key[16]; | 215 | char temp_key[16]; |
| @@ -306,52 +267,38 @@ static int calc_ntlmv2_hash(struct cifsSesInfo *ses, | |||
| 306 | { | 267 | { |
| 307 | int rc = 0; | 268 | int rc = 0; |
| 308 | int len; | 269 | int len; |
| 309 | char nt_hash[CIFS_NTHASH_SIZE]; | 270 | char nt_hash[16]; |
| 271 | struct HMACMD5Context *pctxt; | ||
| 310 | wchar_t *user; | 272 | wchar_t *user; |
| 311 | wchar_t *domain; | 273 | wchar_t *domain; |
| 312 | wchar_t *server; | ||
| 313 | 274 | ||
| 314 | if (!ses->server->ntlmssp.sdeschmacmd5) { | 275 | pctxt = kmalloc(sizeof(struct HMACMD5Context), GFP_KERNEL); |
| 315 | cERROR(1, "calc_ntlmv2_hash: can't generate ntlmv2 hash\n"); | 276 | |
| 316 | return -1; | 277 | if (pctxt == NULL) |
| 317 | } | 278 | return -ENOMEM; |
| 318 | 279 | ||
| 319 | /* calculate md4 hash of password */ | 280 | /* calculate md4 hash of password */ |
| 320 | E_md4hash(ses->password, nt_hash); | 281 | E_md4hash(ses->password, nt_hash); |
| 321 | 282 | ||
| 322 | crypto_shash_setkey(ses->server->ntlmssp.hmacmd5, nt_hash, | 283 | /* convert Domainname to unicode and uppercase */ |
| 323 | CIFS_NTHASH_SIZE); | 284 | hmac_md5_init_limK_to_64(nt_hash, 16, pctxt); |
| 324 | |||
| 325 | rc = crypto_shash_init(&ses->server->ntlmssp.sdeschmacmd5->shash); | ||
| 326 | if (rc) { | ||
| 327 | cERROR(1, "calc_ntlmv2_hash: could not init hmacmd5\n"); | ||
| 328 | return rc; | ||
| 329 | } | ||
| 330 | 285 | ||
| 331 | /* convert ses->userName to unicode and uppercase */ | 286 | /* convert ses->userName to unicode and uppercase */ |
| 332 | len = strlen(ses->userName); | 287 | len = strlen(ses->userName); |
| 333 | user = kmalloc(2 + (len * 2), GFP_KERNEL); | 288 | user = kmalloc(2 + (len * 2), GFP_KERNEL); |
| 334 | if (user == NULL) { | 289 | if (user == NULL) |
| 335 | cERROR(1, "calc_ntlmv2_hash: user mem alloc failure\n"); | ||
| 336 | rc = -ENOMEM; | ||
| 337 | goto calc_exit_2; | 290 | goto calc_exit_2; |
| 338 | } | ||
| 339 | len = cifs_strtoUCS((__le16 *)user, ses->userName, len, nls_cp); | 291 | len = cifs_strtoUCS((__le16 *)user, ses->userName, len, nls_cp); |
| 340 | UniStrupr(user); | 292 | UniStrupr(user); |
| 341 | 293 | hmac_md5_update((char *)user, 2*len, pctxt); | |
| 342 | crypto_shash_update(&ses->server->ntlmssp.sdeschmacmd5->shash, | ||
| 343 | (char *)user, 2 * len); | ||
| 344 | 294 | ||
| 345 | /* convert ses->domainName to unicode and uppercase */ | 295 | /* convert ses->domainName to unicode and uppercase */ |
| 346 | if (ses->domainName) { | 296 | if (ses->domainName) { |
| 347 | len = strlen(ses->domainName); | 297 | len = strlen(ses->domainName); |
| 348 | 298 | ||
| 349 | domain = kmalloc(2 + (len * 2), GFP_KERNEL); | 299 | domain = kmalloc(2 + (len * 2), GFP_KERNEL); |
| 350 | if (domain == NULL) { | 300 | if (domain == NULL) |
| 351 | cERROR(1, "calc_ntlmv2_hash: domain mem alloc failure"); | ||
| 352 | rc = -ENOMEM; | ||
| 353 | goto calc_exit_1; | 301 | goto calc_exit_1; |
| 354 | } | ||
| 355 | len = cifs_strtoUCS((__le16 *)domain, ses->domainName, len, | 302 | len = cifs_strtoUCS((__le16 *)domain, ses->domainName, len, |
| 356 | nls_cp); | 303 | nls_cp); |
| 357 | /* the following line was removed since it didn't work well | 304 | /* the following line was removed since it didn't work well |
| @@ -359,292 +306,65 @@ static int calc_ntlmv2_hash(struct cifsSesInfo *ses, | |||
| 359 | Maybe converting the domain name earlier makes sense */ | 306 | Maybe converting the domain name earlier makes sense */ |
| 360 | /* UniStrupr(domain); */ | 307 | /* UniStrupr(domain); */ |
| 361 | 308 | ||
| 362 | crypto_shash_update(&ses->server->ntlmssp.sdeschmacmd5->shash, | 309 | hmac_md5_update((char *)domain, 2*len, pctxt); |
| 363 | (char *)domain, 2 * len); | ||
| 364 | 310 | ||
| 365 | kfree(domain); | 311 | kfree(domain); |
| 366 | } else if (ses->serverName) { | ||
| 367 | len = strlen(ses->serverName); | ||
| 368 | |||
| 369 | server = kmalloc(2 + (len * 2), GFP_KERNEL); | ||
| 370 | if (server == NULL) { | ||
| 371 | cERROR(1, "calc_ntlmv2_hash: server mem alloc failure"); | ||
| 372 | rc = -ENOMEM; | ||
| 373 | goto calc_exit_1; | ||
| 374 | } | ||
| 375 | len = cifs_strtoUCS((__le16 *)server, ses->serverName, len, | ||
| 376 | nls_cp); | ||
| 377 | /* the following line was removed since it didn't work well | ||
| 378 | with lower cased domain name that passed as an option. | ||
| 379 | Maybe converting the domain name earlier makes sense */ | ||
| 380 | /* UniStrupr(domain); */ | ||
| 381 | |||
| 382 | crypto_shash_update(&ses->server->ntlmssp.sdeschmacmd5->shash, | ||
| 383 | (char *)server, 2 * len); | ||
| 384 | |||
| 385 | kfree(server); | ||
| 386 | } | 312 | } |
| 387 | |||
| 388 | rc = crypto_shash_final(&ses->server->ntlmssp.sdeschmacmd5->shash, | ||
| 389 | ses->server->ntlmv2_hash); | ||
| 390 | |||
| 391 | calc_exit_1: | 313 | calc_exit_1: |
| 392 | kfree(user); | 314 | kfree(user); |
| 393 | calc_exit_2: | 315 | calc_exit_2: |
| 394 | /* BB FIXME what about bytes 24 through 40 of the signing key? | 316 | /* BB FIXME what about bytes 24 through 40 of the signing key? |
| 395 | compare with the NTLM example */ | 317 | compare with the NTLM example */ |
| 318 | hmac_md5_final(ses->server->ntlmv2_hash, pctxt); | ||
| 396 | 319 | ||
| 320 | kfree(pctxt); | ||
| 397 | return rc; | 321 | return rc; |
| 398 | } | 322 | } |
| 399 | 323 | ||
| 400 | static int | 324 | void setup_ntlmv2_rsp(struct cifsSesInfo *ses, char *resp_buf, |
| 401 | find_domain_name(struct cifsSesInfo *ses) | ||
| 402 | { | ||
| 403 | int rc = 0; | ||
| 404 | unsigned int attrsize; | ||
| 405 | unsigned int type; | ||
| 406 | unsigned char *blobptr; | ||
| 407 | struct ntlmssp2_name *attrptr; | ||
| 408 | |||
| 409 | if (ses->server->tiblob) { | ||
| 410 | blobptr = ses->server->tiblob; | ||
| 411 | attrptr = (struct ntlmssp2_name *) blobptr; | ||
| 412 | |||
| 413 | while ((type = attrptr->type) != 0) { | ||
| 414 | blobptr += 2; /* advance attr type */ | ||
| 415 | attrsize = attrptr->length; | ||
| 416 | blobptr += 2; /* advance attr size */ | ||
| 417 | if (type == NTLMSSP_AV_NB_DOMAIN_NAME) { | ||
| 418 | if (!ses->domainName) { | ||
| 419 | ses->domainName = | ||
| 420 | kmalloc(attrptr->length + 1, | ||
| 421 | GFP_KERNEL); | ||
| 422 | if (!ses->domainName) | ||
| 423 | return -ENOMEM; | ||
| 424 | cifs_from_ucs2(ses->domainName, | ||
| 425 | (__le16 *)blobptr, | ||
| 426 | attrptr->length, | ||
| 427 | attrptr->length, | ||
| 428 | load_nls_default(), false); | ||
| 429 | } | ||
| 430 | } | ||
| 431 | blobptr += attrsize; /* advance attr value */ | ||
| 432 | attrptr = (struct ntlmssp2_name *) blobptr; | ||
| 433 | } | ||
| 434 | } else { | ||
| 435 | ses->server->tilen = 2 * sizeof(struct ntlmssp2_name); | ||
| 436 | ses->server->tiblob = kmalloc(ses->server->tilen, GFP_KERNEL); | ||
| 437 | if (!ses->server->tiblob) { | ||
| 438 | ses->server->tilen = 0; | ||
| 439 | cERROR(1, "Challenge target info allocation failure"); | ||
| 440 | return -ENOMEM; | ||
| 441 | } | ||
| 442 | memset(ses->server->tiblob, 0x0, ses->server->tilen); | ||
| 443 | attrptr = (struct ntlmssp2_name *) ses->server->tiblob; | ||
| 444 | attrptr->type = cpu_to_le16(NTLMSSP_DOMAIN_TYPE); | ||
| 445 | } | ||
| 446 | |||
| 447 | return rc; | ||
| 448 | } | ||
| 449 | |||
| 450 | static int | ||
| 451 | CalcNTLMv2_response(const struct TCP_Server_Info *server, | ||
| 452 | char *v2_session_response) | ||
| 453 | { | ||
| 454 | int rc; | ||
| 455 | |||
| 456 | if (!server->ntlmssp.sdeschmacmd5) { | ||
| 457 | cERROR(1, "calc_ntlmv2_hash: can't generate ntlmv2 hash\n"); | ||
| 458 | return -1; | ||
| 459 | } | ||
| 460 | |||
| 461 | crypto_shash_setkey(server->ntlmssp.hmacmd5, server->ntlmv2_hash, | ||
| 462 | CIFS_HMAC_MD5_HASH_SIZE); | ||
| 463 | |||
| 464 | rc = crypto_shash_init(&server->ntlmssp.sdeschmacmd5->shash); | ||
| 465 | if (rc) { | ||
| 466 | cERROR(1, "CalcNTLMv2_response: could not init hmacmd5"); | ||
| 467 | return rc; | ||
| 468 | } | ||
| 469 | |||
| 470 | memcpy(v2_session_response + CIFS_SERVER_CHALLENGE_SIZE, | ||
| 471 | server->cryptKey, CIFS_SERVER_CHALLENGE_SIZE); | ||
| 472 | crypto_shash_update(&server->ntlmssp.sdeschmacmd5->shash, | ||
| 473 | v2_session_response + CIFS_SERVER_CHALLENGE_SIZE, | ||
| 474 | sizeof(struct ntlmv2_resp) - CIFS_SERVER_CHALLENGE_SIZE); | ||
| 475 | |||
| 476 | if (server->tilen) | ||
| 477 | crypto_shash_update(&server->ntlmssp.sdeschmacmd5->shash, | ||
| 478 | server->tiblob, server->tilen); | ||
| 479 | |||
| 480 | rc = crypto_shash_final(&server->ntlmssp.sdeschmacmd5->shash, | ||
| 481 | v2_session_response); | ||
| 482 | |||
| 483 | return rc; | ||
| 484 | } | ||
| 485 | |||
| 486 | int | ||
| 487 | setup_ntlmv2_rsp(struct cifsSesInfo *ses, char *resp_buf, | ||
| 488 | const struct nls_table *nls_cp) | 325 | const struct nls_table *nls_cp) |
| 489 | { | 326 | { |
| 490 | int rc = 0; | 327 | int rc; |
| 491 | struct ntlmv2_resp *buf = (struct ntlmv2_resp *)resp_buf; | 328 | struct ntlmv2_resp *buf = (struct ntlmv2_resp *)resp_buf; |
| 329 | struct HMACMD5Context context; | ||
| 492 | 330 | ||
| 493 | buf->blob_signature = cpu_to_le32(0x00000101); | 331 | buf->blob_signature = cpu_to_le32(0x00000101); |
| 494 | buf->reserved = 0; | 332 | buf->reserved = 0; |
| 495 | buf->time = cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME)); | 333 | buf->time = cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME)); |
| 496 | get_random_bytes(&buf->client_chal, sizeof(buf->client_chal)); | 334 | get_random_bytes(&buf->client_chal, sizeof(buf->client_chal)); |
| 497 | buf->reserved2 = 0; | 335 | buf->reserved2 = 0; |
| 498 | 336 | buf->names[0].type = cpu_to_le16(NTLMSSP_DOMAIN_TYPE); | |
| 499 | if (!ses->domainName) { | 337 | buf->names[0].length = 0; |
| 500 | rc = find_domain_name(ses); | 338 | buf->names[1].type = 0; |
| 501 | if (rc) { | 339 | buf->names[1].length = 0; |
| 502 | cERROR(1, "could not get domain/server name rc %d", rc); | ||
| 503 | return rc; | ||
| 504 | } | ||
| 505 | } | ||
| 506 | 340 | ||
| 507 | /* calculate buf->ntlmv2_hash */ | 341 | /* calculate buf->ntlmv2_hash */ |
| 508 | rc = calc_ntlmv2_hash(ses, nls_cp); | 342 | rc = calc_ntlmv2_hash(ses, nls_cp); |
| 509 | if (rc) { | 343 | if (rc) |
| 510 | cERROR(1, "could not get v2 hash rc %d", rc); | ||
| 511 | return rc; | ||
| 512 | } | ||
| 513 | rc = CalcNTLMv2_response(ses->server, resp_buf); | ||
| 514 | if (rc) { | ||
| 515 | cERROR(1, "could not get v2 hash rc %d", rc); | 344 | cERROR(1, "could not get v2 hash rc %d", rc); |
| 516 | return rc; | 345 | CalcNTLMv2_response(ses, resp_buf); |
| 517 | } | ||
| 518 | |||
| 519 | if (!ses->server->ntlmssp.sdeschmacmd5) { | ||
| 520 | cERROR(1, "calc_ntlmv2_hash: can't generate ntlmv2 hash\n"); | ||
| 521 | return -1; | ||
| 522 | } | ||
| 523 | |||
| 524 | crypto_shash_setkey(ses->server->ntlmssp.hmacmd5, | ||
| 525 | ses->server->ntlmv2_hash, CIFS_HMAC_MD5_HASH_SIZE); | ||
| 526 | 346 | ||
| 527 | rc = crypto_shash_init(&ses->server->ntlmssp.sdeschmacmd5->shash); | 347 | /* now calculate the MAC key for NTLMv2 */ |
| 528 | if (rc) { | 348 | hmac_md5_init_limK_to_64(ses->server->ntlmv2_hash, 16, &context); |
| 529 | cERROR(1, "setup_ntlmv2_rsp: could not init hmacmd5\n"); | 349 | hmac_md5_update(resp_buf, 16, &context); |
| 530 | return rc; | 350 | hmac_md5_final(ses->server->mac_signing_key.data.ntlmv2.key, &context); |
| 531 | } | ||
| 532 | 351 | ||
| 533 | crypto_shash_update(&ses->server->ntlmssp.sdeschmacmd5->shash, | 352 | memcpy(&ses->server->mac_signing_key.data.ntlmv2.resp, resp_buf, |
| 534 | resp_buf, CIFS_HMAC_MD5_HASH_SIZE); | 353 | sizeof(struct ntlmv2_resp)); |
| 535 | 354 | ses->server->mac_signing_key.len = 16 + sizeof(struct ntlmv2_resp); | |
| 536 | rc = crypto_shash_final(&ses->server->ntlmssp.sdeschmacmd5->shash, | ||
| 537 | ses->server->session_key.data.ntlmv2.key); | ||
| 538 | |||
| 539 | memcpy(&ses->server->session_key.data.ntlmv2.resp, resp_buf, | ||
| 540 | sizeof(struct ntlmv2_resp)); | ||
| 541 | ses->server->session_key.len = 16 + sizeof(struct ntlmv2_resp); | ||
| 542 | |||
| 543 | return rc; | ||
| 544 | } | 355 | } |
| 545 | 356 | ||
| 546 | int | 357 | void CalcNTLMv2_response(const struct cifsSesInfo *ses, |
| 547 | calc_seckey(struct TCP_Server_Info *server) | 358 | char *v2_session_response) |
| 548 | { | ||
| 549 | int rc; | ||
| 550 | unsigned char sec_key[CIFS_NTLMV2_SESSKEY_SIZE]; | ||
| 551 | struct crypto_blkcipher *tfm_arc4; | ||
| 552 | struct scatterlist sgin, sgout; | ||
| 553 | struct blkcipher_desc desc; | ||
| 554 | |||
| 555 | get_random_bytes(sec_key, CIFS_NTLMV2_SESSKEY_SIZE); | ||
| 556 | |||
| 557 | tfm_arc4 = crypto_alloc_blkcipher("ecb(arc4)", | ||
| 558 | 0, CRYPTO_ALG_ASYNC); | ||
| 559 | if (!tfm_arc4 || IS_ERR(tfm_arc4)) { | ||
| 560 | cERROR(1, "could not allocate " "master crypto API arc4\n"); | ||
| 561 | return 1; | ||
| 562 | } | ||
| 563 | |||
| 564 | desc.tfm = tfm_arc4; | ||
| 565 | |||
| 566 | crypto_blkcipher_setkey(tfm_arc4, | ||
| 567 | server->session_key.data.ntlmv2.key, CIFS_CPHTXT_SIZE); | ||
| 568 | sg_init_one(&sgin, sec_key, CIFS_CPHTXT_SIZE); | ||
| 569 | sg_init_one(&sgout, server->ntlmssp.ciphertext, CIFS_CPHTXT_SIZE); | ||
| 570 | rc = crypto_blkcipher_encrypt(&desc, &sgout, &sgin, CIFS_CPHTXT_SIZE); | ||
| 571 | |||
| 572 | if (!rc) | ||
| 573 | memcpy(server->session_key.data.ntlmv2.key, | ||
| 574 | sec_key, CIFS_NTLMV2_SESSKEY_SIZE); | ||
| 575 | |||
| 576 | crypto_free_blkcipher(tfm_arc4); | ||
| 577 | |||
| 578 | return 0; | ||
| 579 | } | ||
| 580 | |||
| 581 | void | ||
| 582 | cifs_crypto_shash_release(struct TCP_Server_Info *server) | ||
| 583 | { | ||
| 584 | if (server->ntlmssp.md5) | ||
| 585 | crypto_free_shash(server->ntlmssp.md5); | ||
| 586 | |||
| 587 | if (server->ntlmssp.hmacmd5) | ||
| 588 | crypto_free_shash(server->ntlmssp.hmacmd5); | ||
| 589 | |||
| 590 | kfree(server->ntlmssp.sdeschmacmd5); | ||
| 591 | |||
| 592 | kfree(server->ntlmssp.sdescmd5); | ||
| 593 | } | ||
| 594 | |||
| 595 | int | ||
| 596 | cifs_crypto_shash_allocate(struct TCP_Server_Info *server) | ||
| 597 | { | 359 | { |
| 598 | int rc; | 360 | struct HMACMD5Context context; |
| 599 | unsigned int size; | 361 | /* rest of v2 struct already generated */ |
| 600 | 362 | memcpy(v2_session_response + 8, ses->server->cryptKey, 8); | |
| 601 | server->ntlmssp.hmacmd5 = crypto_alloc_shash("hmac(md5)", 0, 0); | 363 | hmac_md5_init_limK_to_64(ses->server->ntlmv2_hash, 16, &context); |
| 602 | if (!server->ntlmssp.hmacmd5 || | ||
| 603 | IS_ERR(server->ntlmssp.hmacmd5)) { | ||
| 604 | cERROR(1, "could not allocate crypto hmacmd5\n"); | ||
| 605 | return 1; | ||
| 606 | } | ||
| 607 | |||
| 608 | server->ntlmssp.md5 = crypto_alloc_shash("md5", 0, 0); | ||
| 609 | if (!server->ntlmssp.md5 || IS_ERR(server->ntlmssp.md5)) { | ||
| 610 | cERROR(1, "could not allocate crypto md5\n"); | ||
| 611 | rc = 1; | ||
| 612 | goto cifs_crypto_shash_allocate_ret1; | ||
| 613 | } | ||
| 614 | |||
| 615 | size = sizeof(struct shash_desc) + | ||
| 616 | crypto_shash_descsize(server->ntlmssp.hmacmd5); | ||
| 617 | server->ntlmssp.sdeschmacmd5 = kmalloc(size, GFP_KERNEL); | ||
| 618 | if (!server->ntlmssp.sdeschmacmd5) { | ||
| 619 | cERROR(1, "cifs_crypto_shash_allocate: can't alloc hmacmd5\n"); | ||
| 620 | rc = -ENOMEM; | ||
| 621 | goto cifs_crypto_shash_allocate_ret2; | ||
| 622 | } | ||
| 623 | server->ntlmssp.sdeschmacmd5->shash.tfm = server->ntlmssp.hmacmd5; | ||
| 624 | server->ntlmssp.sdeschmacmd5->shash.flags = 0x0; | ||
| 625 | 364 | ||
| 365 | hmac_md5_update(v2_session_response+8, | ||
| 366 | sizeof(struct ntlmv2_resp) - 8, &context); | ||
| 626 | 367 | ||
| 627 | size = sizeof(struct shash_desc) + | 368 | hmac_md5_final(v2_session_response, &context); |
| 628 | crypto_shash_descsize(server->ntlmssp.md5); | 369 | /* cifs_dump_mem("v2_sess_rsp: ", v2_session_response, 32); */ |
| 629 | server->ntlmssp.sdescmd5 = kmalloc(size, GFP_KERNEL); | ||
| 630 | if (!server->ntlmssp.sdescmd5) { | ||
| 631 | cERROR(1, "cifs_crypto_shash_allocate: can't alloc md5\n"); | ||
| 632 | rc = -ENOMEM; | ||
| 633 | goto cifs_crypto_shash_allocate_ret3; | ||
| 634 | } | ||
| 635 | server->ntlmssp.sdescmd5->shash.tfm = server->ntlmssp.md5; | ||
| 636 | server->ntlmssp.sdescmd5->shash.flags = 0x0; | ||
| 637 | |||
| 638 | return 0; | ||
| 639 | |||
| 640 | cifs_crypto_shash_allocate_ret3: | ||
| 641 | kfree(server->ntlmssp.sdeschmacmd5); | ||
| 642 | |||
| 643 | cifs_crypto_shash_allocate_ret2: | ||
| 644 | crypto_free_shash(server->ntlmssp.md5); | ||
| 645 | |||
| 646 | cifs_crypto_shash_allocate_ret1: | ||
| 647 | crypto_free_shash(server->ntlmssp.hmacmd5); | ||
| 648 | |||
| 649 | return rc; | ||
| 650 | } | 370 | } |
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index c9d0cfc086eb..0cdfb8c32ac6 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h | |||
| @@ -25,9 +25,6 @@ | |||
| 25 | #include <linux/workqueue.h> | 25 | #include <linux/workqueue.h> |
| 26 | #include "cifs_fs_sb.h" | 26 | #include "cifs_fs_sb.h" |
| 27 | #include "cifsacl.h" | 27 | #include "cifsacl.h" |
| 28 | #include <crypto/internal/hash.h> | ||
| 29 | #include <linux/scatterlist.h> | ||
| 30 | |||
| 31 | /* | 28 | /* |
| 32 | * The sizes of various internal tables and strings | 29 | * The sizes of various internal tables and strings |
| 33 | */ | 30 | */ |
| @@ -100,7 +97,7 @@ enum protocolEnum { | |||
| 100 | /* Netbios frames protocol not supported at this time */ | 97 | /* Netbios frames protocol not supported at this time */ |
| 101 | }; | 98 | }; |
| 102 | 99 | ||
| 103 | struct session_key { | 100 | struct mac_key { |
| 104 | unsigned int len; | 101 | unsigned int len; |
| 105 | union { | 102 | union { |
| 106 | char ntlm[CIFS_SESS_KEY_SIZE + 16]; | 103 | char ntlm[CIFS_SESS_KEY_SIZE + 16]; |
| @@ -123,21 +120,6 @@ struct cifs_cred { | |||
| 123 | struct cifs_ace *aces; | 120 | struct cifs_ace *aces; |
| 124 | }; | 121 | }; |
| 125 | 122 | ||
| 126 | struct sdesc { | ||
| 127 | struct shash_desc shash; | ||
| 128 | char ctx[]; | ||
| 129 | }; | ||
| 130 | |||
| 131 | struct ntlmssp_auth { | ||
| 132 | __u32 client_flags; | ||
| 133 | __u32 server_flags; | ||
| 134 | unsigned char ciphertext[CIFS_CPHTXT_SIZE]; | ||
| 135 | struct crypto_shash *hmacmd5; | ||
| 136 | struct crypto_shash *md5; | ||
| 137 | struct sdesc *sdeschmacmd5; | ||
| 138 | struct sdesc *sdescmd5; | ||
| 139 | }; | ||
| 140 | |||
| 141 | /* | 123 | /* |
| 142 | ***************************************************************** | 124 | ***************************************************************** |
| 143 | * Except the CIFS PDUs themselves all the | 125 | * Except the CIFS PDUs themselves all the |
| @@ -200,14 +182,11 @@ struct TCP_Server_Info { | |||
| 200 | /* 16th byte of RFC1001 workstation name is always null */ | 182 | /* 16th byte of RFC1001 workstation name is always null */ |
| 201 | char workstation_RFC1001_name[RFC1001_NAME_LEN_WITH_NULL]; | 183 | char workstation_RFC1001_name[RFC1001_NAME_LEN_WITH_NULL]; |
| 202 | __u32 sequence_number; /* needed for CIFS PDU signature */ | 184 | __u32 sequence_number; /* needed for CIFS PDU signature */ |
| 203 | struct session_key session_key; | 185 | struct mac_key mac_signing_key; |
| 204 | char ntlmv2_hash[16]; | 186 | char ntlmv2_hash[16]; |
| 205 | unsigned long lstrp; /* when we got last response from this server */ | 187 | unsigned long lstrp; /* when we got last response from this server */ |
| 206 | u16 dialect; /* dialect index that server chose */ | 188 | u16 dialect; /* dialect index that server chose */ |
| 207 | /* extended security flavors that server supports */ | 189 | /* extended security flavors that server supports */ |
| 208 | unsigned int tilen; /* length of the target info blob */ | ||
| 209 | unsigned char *tiblob; /* target info blob in challenge response */ | ||
| 210 | struct ntlmssp_auth ntlmssp; /* various keys, ciphers, flags */ | ||
| 211 | bool sec_kerberos; /* supports plain Kerberos */ | 190 | bool sec_kerberos; /* supports plain Kerberos */ |
| 212 | bool sec_mskerberos; /* supports legacy MS Kerberos */ | 191 | bool sec_mskerberos; /* supports legacy MS Kerberos */ |
| 213 | bool sec_kerberosu2u; /* supports U2U Kerberos */ | 192 | bool sec_kerberosu2u; /* supports U2U Kerberos */ |
diff --git a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h index 320e0fd0ba7b..14d036d8db11 100644 --- a/fs/cifs/cifspdu.h +++ b/fs/cifs/cifspdu.h | |||
| @@ -134,12 +134,6 @@ | |||
| 134 | * Size of the session key (crypto key encrypted with the password | 134 | * Size of the session key (crypto key encrypted with the password |
| 135 | */ | 135 | */ |
| 136 | #define CIFS_SESS_KEY_SIZE (24) | 136 | #define CIFS_SESS_KEY_SIZE (24) |
| 137 | #define CIFS_CLIENT_CHALLENGE_SIZE (8) | ||
| 138 | #define CIFS_SERVER_CHALLENGE_SIZE (8) | ||
| 139 | #define CIFS_HMAC_MD5_HASH_SIZE (16) | ||
| 140 | #define CIFS_CPHTXT_SIZE (16) | ||
| 141 | #define CIFS_NTLMV2_SESSKEY_SIZE (16) | ||
| 142 | #define CIFS_NTHASH_SIZE (16) | ||
| 143 | 137 | ||
| 144 | /* | 138 | /* |
| 145 | * Maximum user name length | 139 | * Maximum user name length |
| @@ -669,6 +663,7 @@ struct ntlmv2_resp { | |||
| 669 | __le64 time; | 663 | __le64 time; |
| 670 | __u64 client_chal; /* random */ | 664 | __u64 client_chal; /* random */ |
| 671 | __u32 reserved2; | 665 | __u32 reserved2; |
| 666 | struct ntlmssp2_name names[2]; | ||
| 672 | /* array of name entries could follow ending in minimum 4 byte struct */ | 667 | /* array of name entries could follow ending in minimum 4 byte struct */ |
| 673 | } __attribute__((packed)); | 668 | } __attribute__((packed)); |
| 674 | 669 | ||
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index 1378d9133844..1d60c655e3e0 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h | |||
| @@ -87,8 +87,9 @@ extern unsigned int smbCalcSize_LE(struct smb_hdr *ptr); | |||
| 87 | extern int decode_negTokenInit(unsigned char *security_blob, int length, | 87 | extern int decode_negTokenInit(unsigned char *security_blob, int length, |
| 88 | struct TCP_Server_Info *server); | 88 | struct TCP_Server_Info *server); |
| 89 | extern int cifs_convert_address(struct sockaddr *dst, const char *src, int len); | 89 | extern int cifs_convert_address(struct sockaddr *dst, const char *src, int len); |
| 90 | extern int cifs_set_port(struct sockaddr *addr, const unsigned short int port); | ||
| 90 | extern int cifs_fill_sockaddr(struct sockaddr *dst, const char *src, int len, | 91 | extern int cifs_fill_sockaddr(struct sockaddr *dst, const char *src, int len, |
| 91 | unsigned short int port); | 92 | const unsigned short int port); |
| 92 | extern int map_smb_to_linux_error(struct smb_hdr *smb, int logErr); | 93 | extern int map_smb_to_linux_error(struct smb_hdr *smb, int logErr); |
| 93 | extern void header_assemble(struct smb_hdr *, char /* command */ , | 94 | extern void header_assemble(struct smb_hdr *, char /* command */ , |
| 94 | const struct cifsTconInfo *, int /* length of | 95 | const struct cifsTconInfo *, int /* length of |
| @@ -361,15 +362,13 @@ extern int cifs_sign_smb(struct smb_hdr *, struct TCP_Server_Info *, __u32 *); | |||
| 361 | extern int cifs_sign_smb2(struct kvec *iov, int n_vec, struct TCP_Server_Info *, | 362 | extern int cifs_sign_smb2(struct kvec *iov, int n_vec, struct TCP_Server_Info *, |
| 362 | __u32 *); | 363 | __u32 *); |
| 363 | extern int cifs_verify_signature(struct smb_hdr *, | 364 | extern int cifs_verify_signature(struct smb_hdr *, |
| 364 | struct TCP_Server_Info *server, | 365 | const struct mac_key *mac_key, |
| 365 | __u32 expected_sequence_number); | 366 | __u32 expected_sequence_number); |
| 366 | extern int cifs_calculate_session_key(struct session_key *key, const char *rn, | 367 | extern int cifs_calculate_mac_key(struct mac_key *key, const char *rn, |
| 367 | const char *pass); | 368 | const char *pass); |
| 368 | extern int setup_ntlmv2_rsp(struct cifsSesInfo *, char *, | 369 | extern void CalcNTLMv2_response(const struct cifsSesInfo *, char *); |
| 370 | extern void setup_ntlmv2_rsp(struct cifsSesInfo *, char *, | ||
| 369 | const struct nls_table *); | 371 | const struct nls_table *); |
| 370 | extern int cifs_crypto_shash_allocate(struct TCP_Server_Info *); | ||
| 371 | extern void cifs_crypto_shash_release(struct TCP_Server_Info *); | ||
| 372 | extern int calc_seckey(struct TCP_Server_Info *); | ||
| 373 | #ifdef CONFIG_CIFS_WEAK_PW_HASH | 372 | #ifdef CONFIG_CIFS_WEAK_PW_HASH |
| 374 | extern void calc_lanman_hash(const char *password, const char *cryptkey, | 373 | extern void calc_lanman_hash(const char *password, const char *cryptkey, |
| 375 | bool encrypt, char *lnm_session_key); | 374 | bool encrypt, char *lnm_session_key); |
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index 4bda920d1f75..c65c3419dd37 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c | |||
| @@ -604,14 +604,11 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses) | |||
| 604 | else | 604 | else |
| 605 | rc = -EINVAL; | 605 | rc = -EINVAL; |
| 606 | 606 | ||
| 607 | if (server->secType == Kerberos) { | 607 | if (server->sec_kerberos || server->sec_mskerberos) |
| 608 | if (!server->sec_kerberos && | 608 | server->secType = Kerberos; |
| 609 | !server->sec_mskerberos) | 609 | else if (server->sec_ntlmssp) |
| 610 | rc = -EOPNOTSUPP; | 610 | server->secType = RawNTLMSSP; |
| 611 | } else if (server->secType == RawNTLMSSP) { | 611 | else |
| 612 | if (!server->sec_ntlmssp) | ||
| 613 | rc = -EOPNOTSUPP; | ||
| 614 | } else | ||
| 615 | rc = -EOPNOTSUPP; | 612 | rc = -EOPNOTSUPP; |
| 616 | } | 613 | } |
| 617 | } else | 614 | } else |
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index ec0ea4a43bdb..67dad54fbfa1 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c | |||
| @@ -400,7 +400,9 @@ incomplete_rcv: | |||
| 400 | cFYI(1, "call to reconnect done"); | 400 | cFYI(1, "call to reconnect done"); |
| 401 | csocket = server->ssocket; | 401 | csocket = server->ssocket; |
| 402 | continue; | 402 | continue; |
| 403 | } else if ((length == -ERESTARTSYS) || (length == -EAGAIN)) { | 403 | } else if (length == -ERESTARTSYS || |
| 404 | length == -EAGAIN || | ||
| 405 | length == -EINTR) { | ||
| 404 | msleep(1); /* minimum sleep to prevent looping | 406 | msleep(1); /* minimum sleep to prevent looping |
| 405 | allowing socket to clear and app threads to set | 407 | allowing socket to clear and app threads to set |
| 406 | tcpStatus CifsNeedReconnect if server hung */ | 408 | tcpStatus CifsNeedReconnect if server hung */ |
| @@ -414,18 +416,6 @@ incomplete_rcv: | |||
| 414 | } else | 416 | } else |
| 415 | continue; | 417 | continue; |
| 416 | } else if (length <= 0) { | 418 | } else if (length <= 0) { |
| 417 | if (server->tcpStatus == CifsNew) { | ||
| 418 | cFYI(1, "tcp session abend after SMBnegprot"); | ||
| 419 | /* some servers kill the TCP session rather than | ||
| 420 | returning an SMB negprot error, in which | ||
| 421 | case reconnecting here is not going to help, | ||
| 422 | and so simply return error to mount */ | ||
| 423 | break; | ||
| 424 | } | ||
| 425 | if (!try_to_freeze() && (length == -EINTR)) { | ||
| 426 | cFYI(1, "cifsd thread killed"); | ||
| 427 | break; | ||
| 428 | } | ||
| 429 | cFYI(1, "Reconnect after unexpected peek error %d", | 419 | cFYI(1, "Reconnect after unexpected peek error %d", |
| 430 | length); | 420 | length); |
| 431 | cifs_reconnect(server); | 421 | cifs_reconnect(server); |
| @@ -466,27 +456,19 @@ incomplete_rcv: | |||
| 466 | an error on SMB negprot response */ | 456 | an error on SMB negprot response */ |
| 467 | cFYI(1, "Negative RFC1002 Session Response Error 0x%x)", | 457 | cFYI(1, "Negative RFC1002 Session Response Error 0x%x)", |
| 468 | pdu_length); | 458 | pdu_length); |
| 469 | if (server->tcpStatus == CifsNew) { | 459 | /* give server a second to clean up */ |
| 470 | /* if nack on negprot (rather than | 460 | msleep(1000); |
| 471 | ret of smb negprot error) reconnecting | 461 | /* always try 445 first on reconnect since we get NACK |
| 472 | not going to help, ret error to mount */ | 462 | * on some if we ever connected to port 139 (the NACK |
| 473 | break; | 463 | * is since we do not begin with RFC1001 session |
| 474 | } else { | 464 | * initialize frame) |
| 475 | /* give server a second to | 465 | */ |
| 476 | clean up before reconnect attempt */ | 466 | cifs_set_port((struct sockaddr *) |
| 477 | msleep(1000); | 467 | &server->addr.sockAddr, CIFS_PORT); |
| 478 | /* always try 445 first on reconnect | 468 | cifs_reconnect(server); |
| 479 | since we get NACK on some if we ever | 469 | csocket = server->ssocket; |
| 480 | connected to port 139 (the NACK is | 470 | wake_up(&server->response_q); |
| 481 | since we do not begin with RFC1001 | 471 | continue; |
| 482 | session initialize frame) */ | ||
| 483 | server->addr.sockAddr.sin_port = | ||
| 484 | htons(CIFS_PORT); | ||
| 485 | cifs_reconnect(server); | ||
| 486 | csocket = server->ssocket; | ||
| 487 | wake_up(&server->response_q); | ||
| 488 | continue; | ||
| 489 | } | ||
| 490 | } else if (temp != (char) 0) { | 472 | } else if (temp != (char) 0) { |
| 491 | cERROR(1, "Unknown RFC 1002 frame"); | 473 | cERROR(1, "Unknown RFC 1002 frame"); |
| 492 | cifs_dump_mem(" Received Data: ", (char *)smb_buffer, | 474 | cifs_dump_mem(" Received Data: ", (char *)smb_buffer, |
| @@ -522,8 +504,7 @@ incomplete_rcv: | |||
| 522 | total_read += length) { | 504 | total_read += length) { |
| 523 | length = kernel_recvmsg(csocket, &smb_msg, &iov, 1, | 505 | length = kernel_recvmsg(csocket, &smb_msg, &iov, 1, |
| 524 | pdu_length - total_read, 0); | 506 | pdu_length - total_read, 0); |
| 525 | if ((server->tcpStatus == CifsExiting) || | 507 | if (server->tcpStatus == CifsExiting) { |
| 526 | (length == -EINTR)) { | ||
| 527 | /* then will exit */ | 508 | /* then will exit */ |
| 528 | reconnect = 2; | 509 | reconnect = 2; |
| 529 | break; | 510 | break; |
| @@ -534,8 +515,9 @@ incomplete_rcv: | |||
| 534 | /* Now we will reread sock */ | 515 | /* Now we will reread sock */ |
| 535 | reconnect = 1; | 516 | reconnect = 1; |
| 536 | break; | 517 | break; |
| 537 | } else if ((length == -ERESTARTSYS) || | 518 | } else if (length == -ERESTARTSYS || |
| 538 | (length == -EAGAIN)) { | 519 | length == -EAGAIN || |
| 520 | length == -EINTR) { | ||
| 539 | msleep(1); /* minimum sleep to prevent looping, | 521 | msleep(1); /* minimum sleep to prevent looping, |
| 540 | allowing socket to clear and app | 522 | allowing socket to clear and app |
| 541 | threads to set tcpStatus | 523 | threads to set tcpStatus |
| @@ -1708,7 +1690,6 @@ cifs_put_smb_ses(struct cifsSesInfo *ses) | |||
| 1708 | CIFSSMBLogoff(xid, ses); | 1690 | CIFSSMBLogoff(xid, ses); |
| 1709 | _FreeXid(xid); | 1691 | _FreeXid(xid); |
| 1710 | } | 1692 | } |
| 1711 | cifs_crypto_shash_release(server); | ||
| 1712 | sesInfoFree(ses); | 1693 | sesInfoFree(ses); |
| 1713 | cifs_put_tcp_session(server); | 1694 | cifs_put_tcp_session(server); |
| 1714 | } | 1695 | } |
| @@ -1788,23 +1769,13 @@ cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb_vol *volume_info) | |||
| 1788 | ses->linux_uid = volume_info->linux_uid; | 1769 | ses->linux_uid = volume_info->linux_uid; |
| 1789 | ses->overrideSecFlg = volume_info->secFlg; | 1770 | ses->overrideSecFlg = volume_info->secFlg; |
| 1790 | 1771 | ||
| 1791 | rc = cifs_crypto_shash_allocate(server); | ||
| 1792 | if (rc) { | ||
| 1793 | cERROR(1, "could not setup hash structures rc %d", rc); | ||
| 1794 | goto get_ses_fail; | ||
| 1795 | } | ||
| 1796 | server->tilen = 0; | ||
| 1797 | server->tiblob = NULL; | ||
| 1798 | |||
| 1799 | mutex_lock(&ses->session_mutex); | 1772 | mutex_lock(&ses->session_mutex); |
| 1800 | rc = cifs_negotiate_protocol(xid, ses); | 1773 | rc = cifs_negotiate_protocol(xid, ses); |
| 1801 | if (!rc) | 1774 | if (!rc) |
| 1802 | rc = cifs_setup_session(xid, ses, volume_info->local_nls); | 1775 | rc = cifs_setup_session(xid, ses, volume_info->local_nls); |
| 1803 | mutex_unlock(&ses->session_mutex); | 1776 | mutex_unlock(&ses->session_mutex); |
| 1804 | if (rc) { | 1777 | if (rc) |
| 1805 | cifs_crypto_shash_release(ses->server); | ||
| 1806 | goto get_ses_fail; | 1778 | goto get_ses_fail; |
| 1807 | } | ||
| 1808 | 1779 | ||
| 1809 | /* success, put it on the list */ | 1780 | /* success, put it on the list */ |
| 1810 | write_lock(&cifs_tcp_ses_lock); | 1781 | write_lock(&cifs_tcp_ses_lock); |
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index 86a164f08a74..93f77d438d3c 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c | |||
| @@ -1462,29 +1462,18 @@ int cifs_rename(struct inode *source_dir, struct dentry *source_dentry, | |||
| 1462 | { | 1462 | { |
| 1463 | char *fromName = NULL; | 1463 | char *fromName = NULL; |
| 1464 | char *toName = NULL; | 1464 | char *toName = NULL; |
| 1465 | struct cifs_sb_info *cifs_sb_source; | 1465 | struct cifs_sb_info *cifs_sb; |
| 1466 | struct cifs_sb_info *cifs_sb_target; | ||
| 1467 | struct cifsTconInfo *tcon; | 1466 | struct cifsTconInfo *tcon; |
| 1468 | FILE_UNIX_BASIC_INFO *info_buf_source = NULL; | 1467 | FILE_UNIX_BASIC_INFO *info_buf_source = NULL; |
| 1469 | FILE_UNIX_BASIC_INFO *info_buf_target; | 1468 | FILE_UNIX_BASIC_INFO *info_buf_target; |
| 1470 | int xid, rc, tmprc; | 1469 | int xid, rc, tmprc; |
| 1471 | 1470 | ||
| 1472 | cifs_sb_target = CIFS_SB(target_dir->i_sb); | 1471 | cifs_sb = CIFS_SB(source_dir->i_sb); |
| 1473 | cifs_sb_source = CIFS_SB(source_dir->i_sb); | 1472 | tcon = cifs_sb->tcon; |
| 1474 | tcon = cifs_sb_source->tcon; | ||
| 1475 | 1473 | ||
| 1476 | xid = GetXid(); | 1474 | xid = GetXid(); |
| 1477 | 1475 | ||
| 1478 | /* | 1476 | /* |
| 1479 | * BB: this might be allowed if same server, but different share. | ||
| 1480 | * Consider adding support for this | ||
| 1481 | */ | ||
| 1482 | if (tcon != cifs_sb_target->tcon) { | ||
| 1483 | rc = -EXDEV; | ||
| 1484 | goto cifs_rename_exit; | ||
| 1485 | } | ||
| 1486 | |||
| 1487 | /* | ||
| 1488 | * we already have the rename sem so we do not need to | 1477 | * we already have the rename sem so we do not need to |
| 1489 | * grab it again here to protect the path integrity | 1478 | * grab it again here to protect the path integrity |
| 1490 | */ | 1479 | */ |
| @@ -1519,17 +1508,16 @@ int cifs_rename(struct inode *source_dir, struct dentry *source_dentry, | |||
| 1519 | info_buf_target = info_buf_source + 1; | 1508 | info_buf_target = info_buf_source + 1; |
| 1520 | tmprc = CIFSSMBUnixQPathInfo(xid, tcon, fromName, | 1509 | tmprc = CIFSSMBUnixQPathInfo(xid, tcon, fromName, |
| 1521 | info_buf_source, | 1510 | info_buf_source, |
| 1522 | cifs_sb_source->local_nls, | 1511 | cifs_sb->local_nls, |
| 1523 | cifs_sb_source->mnt_cifs_flags & | 1512 | cifs_sb->mnt_cifs_flags & |
| 1524 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 1513 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
| 1525 | if (tmprc != 0) | 1514 | if (tmprc != 0) |
| 1526 | goto unlink_target; | 1515 | goto unlink_target; |
| 1527 | 1516 | ||
| 1528 | tmprc = CIFSSMBUnixQPathInfo(xid, tcon, | 1517 | tmprc = CIFSSMBUnixQPathInfo(xid, tcon, toName, |
| 1529 | toName, info_buf_target, | 1518 | info_buf_target, |
| 1530 | cifs_sb_target->local_nls, | 1519 | cifs_sb->local_nls, |
| 1531 | /* remap based on source sb */ | 1520 | cifs_sb->mnt_cifs_flags & |
| 1532 | cifs_sb_source->mnt_cifs_flags & | ||
| 1533 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 1521 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
| 1534 | 1522 | ||
| 1535 | if (tmprc == 0 && (info_buf_source->UniqueId == | 1523 | if (tmprc == 0 && (info_buf_source->UniqueId == |
diff --git a/fs/cifs/netmisc.c b/fs/cifs/netmisc.c index f97851119e6c..9aad47a2d62f 100644 --- a/fs/cifs/netmisc.c +++ b/fs/cifs/netmisc.c | |||
| @@ -206,26 +206,30 @@ cifs_convert_address(struct sockaddr *dst, const char *src, int len) | |||
| 206 | } | 206 | } |
| 207 | 207 | ||
| 208 | int | 208 | int |
| 209 | cifs_fill_sockaddr(struct sockaddr *dst, const char *src, int len, | 209 | cifs_set_port(struct sockaddr *addr, const unsigned short int port) |
| 210 | const unsigned short int port) | ||
| 211 | { | 210 | { |
| 212 | if (!cifs_convert_address(dst, src, len)) | 211 | switch (addr->sa_family) { |
| 213 | return 0; | ||
| 214 | |||
| 215 | switch (dst->sa_family) { | ||
| 216 | case AF_INET: | 212 | case AF_INET: |
| 217 | ((struct sockaddr_in *)dst)->sin_port = htons(port); | 213 | ((struct sockaddr_in *)addr)->sin_port = htons(port); |
| 218 | break; | 214 | break; |
| 219 | case AF_INET6: | 215 | case AF_INET6: |
| 220 | ((struct sockaddr_in6 *)dst)->sin6_port = htons(port); | 216 | ((struct sockaddr_in6 *)addr)->sin6_port = htons(port); |
| 221 | break; | 217 | break; |
| 222 | default: | 218 | default: |
| 223 | return 0; | 219 | return 0; |
| 224 | } | 220 | } |
| 225 | |||
| 226 | return 1; | 221 | return 1; |
| 227 | } | 222 | } |
| 228 | 223 | ||
| 224 | int | ||
| 225 | cifs_fill_sockaddr(struct sockaddr *dst, const char *src, int len, | ||
| 226 | const unsigned short int port) | ||
| 227 | { | ||
| 228 | if (!cifs_convert_address(dst, src, len)) | ||
| 229 | return 0; | ||
| 230 | return cifs_set_port(dst, port); | ||
| 231 | } | ||
| 232 | |||
| 229 | /***************************************************************************** | 233 | /***************************************************************************** |
| 230 | convert a NT status code to a dos class/code | 234 | convert a NT status code to a dos class/code |
| 231 | *****************************************************************************/ | 235 | *****************************************************************************/ |
diff --git a/fs/cifs/ntlmssp.h b/fs/cifs/ntlmssp.h index 1db0f0746a5b..49c9a4e75319 100644 --- a/fs/cifs/ntlmssp.h +++ b/fs/cifs/ntlmssp.h | |||
| @@ -61,19 +61,6 @@ | |||
| 61 | #define NTLMSSP_NEGOTIATE_KEY_XCH 0x40000000 | 61 | #define NTLMSSP_NEGOTIATE_KEY_XCH 0x40000000 |
| 62 | #define NTLMSSP_NEGOTIATE_56 0x80000000 | 62 | #define NTLMSSP_NEGOTIATE_56 0x80000000 |
| 63 | 63 | ||
| 64 | /* Define AV Pair Field IDs */ | ||
| 65 | #define NTLMSSP_AV_EOL 0 | ||
| 66 | #define NTLMSSP_AV_NB_COMPUTER_NAME 1 | ||
| 67 | #define NTLMSSP_AV_NB_DOMAIN_NAME 2 | ||
| 68 | #define NTLMSSP_AV_DNS_COMPUTER_NAME 3 | ||
| 69 | #define NTLMSSP_AV_DNS_DOMAIN_NAME 4 | ||
| 70 | #define NTLMSSP_AV_DNS_TREE_NAME 5 | ||
| 71 | #define NTLMSSP_AV_FLAGS 6 | ||
| 72 | #define NTLMSSP_AV_TIMESTAMP 7 | ||
| 73 | #define NTLMSSP_AV_RESTRICTION 8 | ||
| 74 | #define NTLMSSP_AV_TARGET_NAME 9 | ||
| 75 | #define NTLMSSP_AV_CHANNEL_BINDINGS 10 | ||
| 76 | |||
| 77 | /* Although typedefs are not commonly used for structure definitions */ | 64 | /* Although typedefs are not commonly used for structure definitions */ |
| 78 | /* in the Linux kernel, in this particular case they are useful */ | 65 | /* in the Linux kernel, in this particular case they are useful */ |
| 79 | /* to more closely match the standards document for NTLMSSP from */ | 66 | /* to more closely match the standards document for NTLMSSP from */ |
diff --git a/fs/cifs/sess.c b/fs/cifs/sess.c index 795095f4eac6..0a57cb7db5dd 100644 --- a/fs/cifs/sess.c +++ b/fs/cifs/sess.c | |||
| @@ -383,9 +383,6 @@ static int decode_ascii_ssetup(char **pbcc_area, int bleft, | |||
| 383 | static int decode_ntlmssp_challenge(char *bcc_ptr, int blob_len, | 383 | static int decode_ntlmssp_challenge(char *bcc_ptr, int blob_len, |
| 384 | struct cifsSesInfo *ses) | 384 | struct cifsSesInfo *ses) |
| 385 | { | 385 | { |
| 386 | unsigned int tioffset; /* challeng message target info area */ | ||
| 387 | unsigned int tilen; /* challeng message target info area length */ | ||
| 388 | |||
| 389 | CHALLENGE_MESSAGE *pblob = (CHALLENGE_MESSAGE *)bcc_ptr; | 386 | CHALLENGE_MESSAGE *pblob = (CHALLENGE_MESSAGE *)bcc_ptr; |
| 390 | 387 | ||
| 391 | if (blob_len < sizeof(CHALLENGE_MESSAGE)) { | 388 | if (blob_len < sizeof(CHALLENGE_MESSAGE)) { |
| @@ -408,20 +405,6 @@ static int decode_ntlmssp_challenge(char *bcc_ptr, int blob_len, | |||
| 408 | /* BB spec says that if AvId field of MsvAvTimestamp is populated then | 405 | /* BB spec says that if AvId field of MsvAvTimestamp is populated then |
| 409 | we must set the MIC field of the AUTHENTICATE_MESSAGE */ | 406 | we must set the MIC field of the AUTHENTICATE_MESSAGE */ |
| 410 | 407 | ||
| 411 | ses->server->ntlmssp.server_flags = le32_to_cpu(pblob->NegotiateFlags); | ||
| 412 | |||
| 413 | tioffset = cpu_to_le16(pblob->TargetInfoArray.BufferOffset); | ||
| 414 | tilen = cpu_to_le16(pblob->TargetInfoArray.Length); | ||
| 415 | ses->server->tilen = tilen; | ||
| 416 | if (tilen) { | ||
| 417 | ses->server->tiblob = kmalloc(tilen, GFP_KERNEL); | ||
| 418 | if (!ses->server->tiblob) { | ||
| 419 | cERROR(1, "Challenge target info allocation failure"); | ||
| 420 | return -ENOMEM; | ||
| 421 | } | ||
| 422 | memcpy(ses->server->tiblob, bcc_ptr + tioffset, tilen); | ||
| 423 | } | ||
| 424 | |||
| 425 | return 0; | 408 | return 0; |
| 426 | } | 409 | } |
| 427 | 410 | ||
| @@ -442,13 +425,12 @@ static void build_ntlmssp_negotiate_blob(unsigned char *pbuffer, | |||
| 442 | /* BB is NTLMV2 session security format easier to use here? */ | 425 | /* BB is NTLMV2 session security format easier to use here? */ |
| 443 | flags = NTLMSSP_NEGOTIATE_56 | NTLMSSP_REQUEST_TARGET | | 426 | flags = NTLMSSP_NEGOTIATE_56 | NTLMSSP_REQUEST_TARGET | |
| 444 | NTLMSSP_NEGOTIATE_128 | NTLMSSP_NEGOTIATE_UNICODE | | 427 | NTLMSSP_NEGOTIATE_128 | NTLMSSP_NEGOTIATE_UNICODE | |
| 445 | NTLMSSP_NEGOTIATE_NTLM; | 428 | NTLMSSP_NEGOTIATE_NT_ONLY | NTLMSSP_NEGOTIATE_NTLM; |
| 446 | if (ses->server->secMode & | 429 | if (ses->server->secMode & |
| 447 | (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) { | 430 | (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) |
| 448 | flags |= NTLMSSP_NEGOTIATE_SIGN | | 431 | flags |= NTLMSSP_NEGOTIATE_SIGN; |
| 449 | NTLMSSP_NEGOTIATE_KEY_XCH | | 432 | if (ses->server->secMode & SECMODE_SIGN_REQUIRED) |
| 450 | NTLMSSP_NEGOTIATE_EXTENDED_SEC; | 433 | flags |= NTLMSSP_NEGOTIATE_ALWAYS_SIGN; |
| 451 | } | ||
| 452 | 434 | ||
| 453 | sec_blob->NegotiateFlags |= cpu_to_le32(flags); | 435 | sec_blob->NegotiateFlags |= cpu_to_le32(flags); |
| 454 | 436 | ||
| @@ -469,12 +451,10 @@ static int build_ntlmssp_auth_blob(unsigned char *pbuffer, | |||
| 469 | struct cifsSesInfo *ses, | 451 | struct cifsSesInfo *ses, |
| 470 | const struct nls_table *nls_cp, bool first) | 452 | const struct nls_table *nls_cp, bool first) |
| 471 | { | 453 | { |
| 472 | int rc; | ||
| 473 | unsigned int size; | ||
| 474 | AUTHENTICATE_MESSAGE *sec_blob = (AUTHENTICATE_MESSAGE *)pbuffer; | 454 | AUTHENTICATE_MESSAGE *sec_blob = (AUTHENTICATE_MESSAGE *)pbuffer; |
| 475 | __u32 flags; | 455 | __u32 flags; |
| 476 | unsigned char *tmp; | 456 | unsigned char *tmp; |
| 477 | struct ntlmv2_resp ntlmv2_response = {}; | 457 | char ntlm_session_key[CIFS_SESS_KEY_SIZE]; |
| 478 | 458 | ||
| 479 | memcpy(sec_blob->Signature, NTLMSSP_SIGNATURE, 8); | 459 | memcpy(sec_blob->Signature, NTLMSSP_SIGNATURE, 8); |
| 480 | sec_blob->MessageType = NtLmAuthenticate; | 460 | sec_blob->MessageType = NtLmAuthenticate; |
| @@ -497,25 +477,19 @@ static int build_ntlmssp_auth_blob(unsigned char *pbuffer, | |||
| 497 | sec_blob->LmChallengeResponse.Length = 0; | 477 | sec_blob->LmChallengeResponse.Length = 0; |
| 498 | sec_blob->LmChallengeResponse.MaximumLength = 0; | 478 | sec_blob->LmChallengeResponse.MaximumLength = 0; |
| 499 | 479 | ||
| 500 | sec_blob->NtChallengeResponse.BufferOffset = cpu_to_le32(tmp - pbuffer); | 480 | /* calculate session key, BB what about adding similar ntlmv2 path? */ |
| 501 | rc = setup_ntlmv2_rsp(ses, (char *)&ntlmv2_response, nls_cp); | 481 | SMBNTencrypt(ses->password, ses->server->cryptKey, ntlm_session_key); |
| 502 | if (rc) { | 482 | if (first) |
| 503 | cERROR(1, "error rc: %d during ntlmssp ntlmv2 setup", rc); | 483 | cifs_calculate_mac_key(&ses->server->mac_signing_key, |
| 504 | goto setup_ntlmv2_ret; | 484 | ntlm_session_key, ses->password); |
| 505 | } | ||
| 506 | size = sizeof(struct ntlmv2_resp); | ||
| 507 | memcpy(tmp, (char *)&ntlmv2_response, size); | ||
| 508 | tmp += size; | ||
| 509 | if (ses->server->tilen > 0) { | ||
| 510 | memcpy(tmp, ses->server->tiblob, ses->server->tilen); | ||
| 511 | tmp += ses->server->tilen; | ||
| 512 | } else | ||
| 513 | ses->server->tilen = 0; | ||
| 514 | 485 | ||
| 515 | sec_blob->NtChallengeResponse.Length = cpu_to_le16(size + | 486 | memcpy(tmp, ntlm_session_key, CIFS_SESS_KEY_SIZE); |
| 516 | ses->server->tilen); | 487 | sec_blob->NtChallengeResponse.BufferOffset = cpu_to_le32(tmp - pbuffer); |
| 488 | sec_blob->NtChallengeResponse.Length = cpu_to_le16(CIFS_SESS_KEY_SIZE); | ||
| 517 | sec_blob->NtChallengeResponse.MaximumLength = | 489 | sec_blob->NtChallengeResponse.MaximumLength = |
| 518 | cpu_to_le16(size + ses->server->tilen); | 490 | cpu_to_le16(CIFS_SESS_KEY_SIZE); |
| 491 | |||
| 492 | tmp += CIFS_SESS_KEY_SIZE; | ||
| 519 | 493 | ||
| 520 | if (ses->domainName == NULL) { | 494 | if (ses->domainName == NULL) { |
| 521 | sec_blob->DomainName.BufferOffset = cpu_to_le32(tmp - pbuffer); | 495 | sec_blob->DomainName.BufferOffset = cpu_to_le32(tmp - pbuffer); |
| @@ -527,6 +501,7 @@ static int build_ntlmssp_auth_blob(unsigned char *pbuffer, | |||
| 527 | len = cifs_strtoUCS((__le16 *)tmp, ses->domainName, | 501 | len = cifs_strtoUCS((__le16 *)tmp, ses->domainName, |
| 528 | MAX_USERNAME_SIZE, nls_cp); | 502 | MAX_USERNAME_SIZE, nls_cp); |
| 529 | len *= 2; /* unicode is 2 bytes each */ | 503 | len *= 2; /* unicode is 2 bytes each */ |
| 504 | len += 2; /* trailing null */ | ||
| 530 | sec_blob->DomainName.BufferOffset = cpu_to_le32(tmp - pbuffer); | 505 | sec_blob->DomainName.BufferOffset = cpu_to_le32(tmp - pbuffer); |
| 531 | sec_blob->DomainName.Length = cpu_to_le16(len); | 506 | sec_blob->DomainName.Length = cpu_to_le16(len); |
| 532 | sec_blob->DomainName.MaximumLength = cpu_to_le16(len); | 507 | sec_blob->DomainName.MaximumLength = cpu_to_le16(len); |
| @@ -543,6 +518,7 @@ static int build_ntlmssp_auth_blob(unsigned char *pbuffer, | |||
| 543 | len = cifs_strtoUCS((__le16 *)tmp, ses->userName, | 518 | len = cifs_strtoUCS((__le16 *)tmp, ses->userName, |
| 544 | MAX_USERNAME_SIZE, nls_cp); | 519 | MAX_USERNAME_SIZE, nls_cp); |
| 545 | len *= 2; /* unicode is 2 bytes each */ | 520 | len *= 2; /* unicode is 2 bytes each */ |
| 521 | len += 2; /* trailing null */ | ||
| 546 | sec_blob->UserName.BufferOffset = cpu_to_le32(tmp - pbuffer); | 522 | sec_blob->UserName.BufferOffset = cpu_to_le32(tmp - pbuffer); |
| 547 | sec_blob->UserName.Length = cpu_to_le16(len); | 523 | sec_blob->UserName.Length = cpu_to_le16(len); |
| 548 | sec_blob->UserName.MaximumLength = cpu_to_le16(len); | 524 | sec_blob->UserName.MaximumLength = cpu_to_le16(len); |
| @@ -554,26 +530,9 @@ static int build_ntlmssp_auth_blob(unsigned char *pbuffer, | |||
| 554 | sec_blob->WorkstationName.MaximumLength = 0; | 530 | sec_blob->WorkstationName.MaximumLength = 0; |
| 555 | tmp += 2; | 531 | tmp += 2; |
| 556 | 532 | ||
| 557 | if ((ses->server->ntlmssp.server_flags & NTLMSSP_NEGOTIATE_KEY_XCH) && | 533 | sec_blob->SessionKey.BufferOffset = cpu_to_le32(tmp - pbuffer); |
| 558 | !calc_seckey(ses->server)) { | 534 | sec_blob->SessionKey.Length = 0; |
| 559 | memcpy(tmp, ses->server->ntlmssp.ciphertext, CIFS_CPHTXT_SIZE); | 535 | sec_blob->SessionKey.MaximumLength = 0; |
| 560 | sec_blob->SessionKey.BufferOffset = cpu_to_le32(tmp - pbuffer); | ||
| 561 | sec_blob->SessionKey.Length = cpu_to_le16(CIFS_CPHTXT_SIZE); | ||
| 562 | sec_blob->SessionKey.MaximumLength = | ||
| 563 | cpu_to_le16(CIFS_CPHTXT_SIZE); | ||
| 564 | tmp += CIFS_CPHTXT_SIZE; | ||
| 565 | } else { | ||
| 566 | sec_blob->SessionKey.BufferOffset = cpu_to_le32(tmp - pbuffer); | ||
| 567 | sec_blob->SessionKey.Length = 0; | ||
| 568 | sec_blob->SessionKey.MaximumLength = 0; | ||
| 569 | } | ||
| 570 | |||
| 571 | ses->server->sequence_number = 0; | ||
| 572 | |||
| 573 | setup_ntlmv2_ret: | ||
| 574 | if (ses->server->tilen > 0) | ||
| 575 | kfree(ses->server->tiblob); | ||
| 576 | |||
| 577 | return tmp - pbuffer; | 536 | return tmp - pbuffer; |
| 578 | } | 537 | } |
| 579 | 538 | ||
| @@ -587,14 +546,15 @@ static void setup_ntlmssp_neg_req(SESSION_SETUP_ANDX *pSMB, | |||
| 587 | return; | 546 | return; |
| 588 | } | 547 | } |
| 589 | 548 | ||
| 590 | static int setup_ntlmssp_auth_req(char *ntlmsspblob, | 549 | static int setup_ntlmssp_auth_req(SESSION_SETUP_ANDX *pSMB, |
| 591 | struct cifsSesInfo *ses, | 550 | struct cifsSesInfo *ses, |
| 592 | const struct nls_table *nls, bool first_time) | 551 | const struct nls_table *nls, bool first_time) |
| 593 | { | 552 | { |
| 594 | int bloblen; | 553 | int bloblen; |
| 595 | 554 | ||
| 596 | bloblen = build_ntlmssp_auth_blob(ntlmsspblob, ses, nls, | 555 | bloblen = build_ntlmssp_auth_blob(&pSMB->req.SecurityBlob[0], ses, nls, |
| 597 | first_time); | 556 | first_time); |
| 557 | pSMB->req.SecurityBlobLength = cpu_to_le16(bloblen); | ||
| 598 | 558 | ||
| 599 | return bloblen; | 559 | return bloblen; |
| 600 | } | 560 | } |
| @@ -730,7 +690,7 @@ ssetup_ntlmssp_authenticate: | |||
| 730 | 690 | ||
| 731 | if (first_time) /* should this be moved into common code | 691 | if (first_time) /* should this be moved into common code |
| 732 | with similar ntlmv2 path? */ | 692 | with similar ntlmv2 path? */ |
| 733 | cifs_calculate_session_key(&ses->server->session_key, | 693 | cifs_calculate_mac_key(&ses->server->mac_signing_key, |
| 734 | ntlm_session_key, ses->password); | 694 | ntlm_session_key, ses->password); |
| 735 | /* copy session key */ | 695 | /* copy session key */ |
| 736 | 696 | ||
| @@ -769,21 +729,12 @@ ssetup_ntlmssp_authenticate: | |||
| 769 | cpu_to_le16(sizeof(struct ntlmv2_resp)); | 729 | cpu_to_le16(sizeof(struct ntlmv2_resp)); |
| 770 | 730 | ||
| 771 | /* calculate session key */ | 731 | /* calculate session key */ |
| 772 | rc = setup_ntlmv2_rsp(ses, v2_sess_key, nls_cp); | 732 | setup_ntlmv2_rsp(ses, v2_sess_key, nls_cp); |
| 773 | if (rc) { | ||
| 774 | kfree(v2_sess_key); | ||
| 775 | goto ssetup_exit; | ||
| 776 | } | ||
| 777 | /* FIXME: calculate MAC key */ | 733 | /* FIXME: calculate MAC key */ |
| 778 | memcpy(bcc_ptr, (char *)v2_sess_key, | 734 | memcpy(bcc_ptr, (char *)v2_sess_key, |
| 779 | sizeof(struct ntlmv2_resp)); | 735 | sizeof(struct ntlmv2_resp)); |
| 780 | bcc_ptr += sizeof(struct ntlmv2_resp); | 736 | bcc_ptr += sizeof(struct ntlmv2_resp); |
| 781 | kfree(v2_sess_key); | 737 | kfree(v2_sess_key); |
| 782 | if (ses->server->tilen > 0) { | ||
| 783 | memcpy(bcc_ptr, ses->server->tiblob, | ||
| 784 | ses->server->tilen); | ||
| 785 | bcc_ptr += ses->server->tilen; | ||
| 786 | } | ||
| 787 | if (ses->capabilities & CAP_UNICODE) { | 738 | if (ses->capabilities & CAP_UNICODE) { |
| 788 | if (iov[0].iov_len % 2) { | 739 | if (iov[0].iov_len % 2) { |
| 789 | *bcc_ptr = 0; | 740 | *bcc_ptr = 0; |
| @@ -814,15 +765,15 @@ ssetup_ntlmssp_authenticate: | |||
| 814 | } | 765 | } |
| 815 | /* bail out if key is too long */ | 766 | /* bail out if key is too long */ |
| 816 | if (msg->sesskey_len > | 767 | if (msg->sesskey_len > |
| 817 | sizeof(ses->server->session_key.data.krb5)) { | 768 | sizeof(ses->server->mac_signing_key.data.krb5)) { |
| 818 | cERROR(1, "Kerberos signing key too long (%u bytes)", | 769 | cERROR(1, "Kerberos signing key too long (%u bytes)", |
| 819 | msg->sesskey_len); | 770 | msg->sesskey_len); |
| 820 | rc = -EOVERFLOW; | 771 | rc = -EOVERFLOW; |
| 821 | goto ssetup_exit; | 772 | goto ssetup_exit; |
| 822 | } | 773 | } |
| 823 | if (first_time) { | 774 | if (first_time) { |
| 824 | ses->server->session_key.len = msg->sesskey_len; | 775 | ses->server->mac_signing_key.len = msg->sesskey_len; |
| 825 | memcpy(ses->server->session_key.data.krb5, | 776 | memcpy(ses->server->mac_signing_key.data.krb5, |
| 826 | msg->data, msg->sesskey_len); | 777 | msg->data, msg->sesskey_len); |
| 827 | } | 778 | } |
| 828 | pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC; | 779 | pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC; |
| @@ -864,28 +815,12 @@ ssetup_ntlmssp_authenticate: | |||
| 864 | if (phase == NtLmNegotiate) { | 815 | if (phase == NtLmNegotiate) { |
| 865 | setup_ntlmssp_neg_req(pSMB, ses); | 816 | setup_ntlmssp_neg_req(pSMB, ses); |
| 866 | iov[1].iov_len = sizeof(NEGOTIATE_MESSAGE); | 817 | iov[1].iov_len = sizeof(NEGOTIATE_MESSAGE); |
| 867 | iov[1].iov_base = &pSMB->req.SecurityBlob[0]; | ||
| 868 | } else if (phase == NtLmAuthenticate) { | 818 | } else if (phase == NtLmAuthenticate) { |
| 869 | int blob_len; | 819 | int blob_len; |
| 870 | char *ntlmsspblob; | 820 | blob_len = setup_ntlmssp_auth_req(pSMB, ses, |
| 871 | 821 | nls_cp, | |
| 872 | ntlmsspblob = kmalloc(5 * | 822 | first_time); |
| 873 | sizeof(struct _AUTHENTICATE_MESSAGE), | ||
| 874 | GFP_KERNEL); | ||
| 875 | if (!ntlmsspblob) { | ||
| 876 | cERROR(1, "Can't allocate NTLMSSP"); | ||
| 877 | rc = -ENOMEM; | ||
| 878 | goto ssetup_exit; | ||
| 879 | } | ||
| 880 | |||
| 881 | blob_len = setup_ntlmssp_auth_req(ntlmsspblob, | ||
| 882 | ses, | ||
| 883 | nls_cp, | ||
| 884 | first_time); | ||
| 885 | iov[1].iov_len = blob_len; | 823 | iov[1].iov_len = blob_len; |
| 886 | iov[1].iov_base = ntlmsspblob; | ||
| 887 | pSMB->req.SecurityBlobLength = | ||
| 888 | cpu_to_le16(blob_len); | ||
| 889 | /* Make sure that we tell the server that we | 824 | /* Make sure that we tell the server that we |
| 890 | are using the uid that it just gave us back | 825 | are using the uid that it just gave us back |
| 891 | on the response (challenge) */ | 826 | on the response (challenge) */ |
| @@ -895,6 +830,7 @@ ssetup_ntlmssp_authenticate: | |||
| 895 | rc = -ENOSYS; | 830 | rc = -ENOSYS; |
| 896 | goto ssetup_exit; | 831 | goto ssetup_exit; |
| 897 | } | 832 | } |
| 833 | iov[1].iov_base = &pSMB->req.SecurityBlob[0]; | ||
| 898 | /* unicode strings must be word aligned */ | 834 | /* unicode strings must be word aligned */ |
| 899 | if ((iov[0].iov_len + iov[1].iov_len) % 2) { | 835 | if ((iov[0].iov_len + iov[1].iov_len) % 2) { |
| 900 | *bcc_ptr = 0; | 836 | *bcc_ptr = 0; |
diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c index e0588cdf4cc5..82f78c4d6978 100644 --- a/fs/cifs/transport.c +++ b/fs/cifs/transport.c | |||
| @@ -543,7 +543,7 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses, | |||
| 543 | (ses->server->secMode & (SECMODE_SIGN_REQUIRED | | 543 | (ses->server->secMode & (SECMODE_SIGN_REQUIRED | |
| 544 | SECMODE_SIGN_ENABLED))) { | 544 | SECMODE_SIGN_ENABLED))) { |
| 545 | rc = cifs_verify_signature(midQ->resp_buf, | 545 | rc = cifs_verify_signature(midQ->resp_buf, |
| 546 | ses->server, | 546 | &ses->server->mac_signing_key, |
| 547 | midQ->sequence_number+1); | 547 | midQ->sequence_number+1); |
| 548 | if (rc) { | 548 | if (rc) { |
| 549 | cERROR(1, "Unexpected SMB signature"); | 549 | cERROR(1, "Unexpected SMB signature"); |
| @@ -731,7 +731,7 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses, | |||
| 731 | (ses->server->secMode & (SECMODE_SIGN_REQUIRED | | 731 | (ses->server->secMode & (SECMODE_SIGN_REQUIRED | |
| 732 | SECMODE_SIGN_ENABLED))) { | 732 | SECMODE_SIGN_ENABLED))) { |
| 733 | rc = cifs_verify_signature(out_buf, | 733 | rc = cifs_verify_signature(out_buf, |
| 734 | ses->server, | 734 | &ses->server->mac_signing_key, |
| 735 | midQ->sequence_number+1); | 735 | midQ->sequence_number+1); |
| 736 | if (rc) { | 736 | if (rc) { |
| 737 | cERROR(1, "Unexpected SMB signature"); | 737 | cERROR(1, "Unexpected SMB signature"); |
| @@ -981,7 +981,7 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifsTconInfo *tcon, | |||
| 981 | (ses->server->secMode & (SECMODE_SIGN_REQUIRED | | 981 | (ses->server->secMode & (SECMODE_SIGN_REQUIRED | |
| 982 | SECMODE_SIGN_ENABLED))) { | 982 | SECMODE_SIGN_ENABLED))) { |
| 983 | rc = cifs_verify_signature(out_buf, | 983 | rc = cifs_verify_signature(out_buf, |
| 984 | ses->server, | 984 | &ses->server->mac_signing_key, |
| 985 | midQ->sequence_number+1); | 985 | midQ->sequence_number+1); |
| 986 | if (rc) { | 986 | if (rc) { |
| 987 | cERROR(1, "Unexpected SMB signature"); | 987 | cERROR(1, "Unexpected SMB signature"); |
diff --git a/fs/nfs/Kconfig b/fs/nfs/Kconfig index 6c2aad49d731..f7e13db613cb 100644 --- a/fs/nfs/Kconfig +++ b/fs/nfs/Kconfig | |||
| @@ -63,6 +63,7 @@ config NFS_V3_ACL | |||
| 63 | config NFS_V4 | 63 | config NFS_V4 |
| 64 | bool "NFS client support for NFS version 4" | 64 | bool "NFS client support for NFS version 4" |
| 65 | depends on NFS_FS | 65 | depends on NFS_FS |
| 66 | select SUNRPC_GSS | ||
| 66 | help | 67 | help |
| 67 | This option enables support for version 4 of the NFS protocol | 68 | This option enables support for version 4 of the NFS protocol |
| 68 | (RFC 3530) in the kernel's NFS client. | 69 | (RFC 3530) in the kernel's NFS client. |
diff --git a/fs/nfs/client.c b/fs/nfs/client.c index 4e7df2adb212..e7340729af89 100644 --- a/fs/nfs/client.c +++ b/fs/nfs/client.c | |||
| @@ -275,7 +275,7 @@ static int nfs_sockaddr_match_ipaddr6(const struct sockaddr *sa1, | |||
| 275 | sin1->sin6_scope_id != sin2->sin6_scope_id) | 275 | sin1->sin6_scope_id != sin2->sin6_scope_id) |
| 276 | return 0; | 276 | return 0; |
| 277 | 277 | ||
| 278 | return ipv6_addr_equal(&sin1->sin6_addr, &sin1->sin6_addr); | 278 | return ipv6_addr_equal(&sin1->sin6_addr, &sin2->sin6_addr); |
| 279 | } | 279 | } |
| 280 | #else /* !defined(CONFIG_IPV6) && !defined(CONFIG_IPV6_MODULE) */ | 280 | #else /* !defined(CONFIG_IPV6) && !defined(CONFIG_IPV6_MODULE) */ |
| 281 | static int nfs_sockaddr_match_ipaddr6(const struct sockaddr *sa1, | 281 | static int nfs_sockaddr_match_ipaddr6(const struct sockaddr *sa1, |
diff --git a/fs/nfs/file.c b/fs/nfs/file.c index eb51bd6201da..05bf3c0dc751 100644 --- a/fs/nfs/file.c +++ b/fs/nfs/file.c | |||
| @@ -723,10 +723,6 @@ static int do_vfs_lock(struct file *file, struct file_lock *fl) | |||
| 723 | default: | 723 | default: |
| 724 | BUG(); | 724 | BUG(); |
| 725 | } | 725 | } |
| 726 | if (res < 0) | ||
| 727 | dprintk(KERN_WARNING "%s: VFS is out of sync with lock manager" | ||
| 728 | " - error %d!\n", | ||
| 729 | __func__, res); | ||
| 730 | return res; | 726 | return res; |
| 731 | } | 727 | } |
| 732 | 728 | ||
diff --git a/fs/nfs/super.c b/fs/nfs/super.c index ec3966e4706b..f4cbf0c306c6 100644 --- a/fs/nfs/super.c +++ b/fs/nfs/super.c | |||
| @@ -431,7 +431,15 @@ static int nfs_statfs(struct dentry *dentry, struct kstatfs *buf) | |||
| 431 | goto out_err; | 431 | goto out_err; |
| 432 | 432 | ||
| 433 | error = server->nfs_client->rpc_ops->statfs(server, fh, &res); | 433 | error = server->nfs_client->rpc_ops->statfs(server, fh, &res); |
| 434 | if (unlikely(error == -ESTALE)) { | ||
| 435 | struct dentry *pd_dentry; | ||
| 434 | 436 | ||
| 437 | pd_dentry = dget_parent(dentry); | ||
| 438 | if (pd_dentry != NULL) { | ||
| 439 | nfs_zap_caches(pd_dentry->d_inode); | ||
| 440 | dput(pd_dentry); | ||
| 441 | } | ||
| 442 | } | ||
| 435 | nfs_free_fattr(res.fattr); | 443 | nfs_free_fattr(res.fattr); |
| 436 | if (error < 0) | 444 | if (error < 0) |
| 437 | goto out_err; | 445 | goto out_err; |
diff --git a/fs/nfsd/Kconfig b/fs/nfsd/Kconfig index 95932f523aef..4264377552e2 100644 --- a/fs/nfsd/Kconfig +++ b/fs/nfsd/Kconfig | |||
| @@ -69,6 +69,7 @@ config NFSD_V4 | |||
| 69 | depends on NFSD && PROC_FS && EXPERIMENTAL | 69 | depends on NFSD && PROC_FS && EXPERIMENTAL |
| 70 | select NFSD_V3 | 70 | select NFSD_V3 |
| 71 | select FS_POSIX_ACL | 71 | select FS_POSIX_ACL |
| 72 | select SUNRPC_GSS | ||
| 72 | help | 73 | help |
| 73 | This option enables support in your system's NFS server for | 74 | This option enables support in your system's NFS server for |
| 74 | version 4 of the NFS protocol (RFC 3530). | 75 | version 4 of the NFS protocol (RFC 3530). |
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index c9f3cc5949a8..3e5a51af757c 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h | |||
| @@ -386,7 +386,15 @@ struct drm_connector_funcs { | |||
| 386 | void (*dpms)(struct drm_connector *connector, int mode); | 386 | void (*dpms)(struct drm_connector *connector, int mode); |
| 387 | void (*save)(struct drm_connector *connector); | 387 | void (*save)(struct drm_connector *connector); |
| 388 | void (*restore)(struct drm_connector *connector); | 388 | void (*restore)(struct drm_connector *connector); |
| 389 | enum drm_connector_status (*detect)(struct drm_connector *connector); | 389 | |
| 390 | /* Check to see if anything is attached to the connector. | ||
| 391 | * @force is set to false whilst polling, true when checking the | ||
| 392 | * connector due to user request. @force can be used by the driver | ||
| 393 | * to avoid expensive, destructive operations during automated | ||
| 394 | * probing. | ||
| 395 | */ | ||
| 396 | enum drm_connector_status (*detect)(struct drm_connector *connector, | ||
| 397 | bool force); | ||
| 390 | int (*fill_modes)(struct drm_connector *connector, uint32_t max_width, uint32_t max_height); | 398 | int (*fill_modes)(struct drm_connector *connector, uint32_t max_width, uint32_t max_height); |
| 391 | int (*set_property)(struct drm_connector *connector, struct drm_property *property, | 399 | int (*set_property)(struct drm_connector *connector, struct drm_property *property, |
| 392 | uint64_t val); | 400 | uint64_t val); |
diff --git a/include/linux/compat.h b/include/linux/compat.h index 9ddc8780e8db..5778b559d59c 100644 --- a/include/linux/compat.h +++ b/include/linux/compat.h | |||
| @@ -360,5 +360,8 @@ extern ssize_t compat_rw_copy_check_uvector(int type, | |||
| 360 | const struct compat_iovec __user *uvector, unsigned long nr_segs, | 360 | const struct compat_iovec __user *uvector, unsigned long nr_segs, |
| 361 | unsigned long fast_segs, struct iovec *fast_pointer, | 361 | unsigned long fast_segs, struct iovec *fast_pointer, |
| 362 | struct iovec **ret_pointer); | 362 | struct iovec **ret_pointer); |
| 363 | |||
| 364 | extern void __user *compat_alloc_user_space(unsigned long len); | ||
| 365 | |||
| 363 | #endif /* CONFIG_COMPAT */ | 366 | #endif /* CONFIG_COMPAT */ |
| 364 | #endif /* _LINUX_COMPAT_H */ | 367 | #endif /* _LINUX_COMPAT_H */ |
diff --git a/include/linux/gpio.h b/include/linux/gpio.h index 03f616b78cfa..e41f7dd1ae67 100644 --- a/include/linux/gpio.h +++ b/include/linux/gpio.h | |||
| @@ -13,6 +13,7 @@ | |||
| 13 | #include <linux/errno.h> | 13 | #include <linux/errno.h> |
| 14 | 14 | ||
| 15 | struct device; | 15 | struct device; |
| 16 | struct gpio_chip; | ||
| 16 | 17 | ||
| 17 | /* | 18 | /* |
| 18 | * Some platforms don't support the GPIO programming interface. | 19 | * Some platforms don't support the GPIO programming interface. |
diff --git a/include/linux/quotaops.h b/include/linux/quotaops.h index d50ba858cfe0..d1a9193960f1 100644 --- a/include/linux/quotaops.h +++ b/include/linux/quotaops.h | |||
| @@ -274,8 +274,14 @@ static inline int dquot_alloc_space(struct inode *inode, qsize_t nr) | |||
| 274 | int ret; | 274 | int ret; |
| 275 | 275 | ||
| 276 | ret = dquot_alloc_space_nodirty(inode, nr); | 276 | ret = dquot_alloc_space_nodirty(inode, nr); |
| 277 | if (!ret) | 277 | if (!ret) { |
| 278 | mark_inode_dirty_sync(inode); | 278 | /* |
| 279 | * Mark inode fully dirty. Since we are allocating blocks, inode | ||
| 280 | * would become fully dirty soon anyway and it reportedly | ||
| 281 | * reduces inode_lock contention. | ||
| 282 | */ | ||
| 283 | mark_inode_dirty(inode); | ||
| 284 | } | ||
| 279 | return ret; | 285 | return ret; |
| 280 | } | 286 | } |
| 281 | 287 | ||
diff --git a/include/linux/spi/dw_spi.h b/include/linux/spi/dw_spi.h index cc813f95a2f2..c91302f3a257 100644 --- a/include/linux/spi/dw_spi.h +++ b/include/linux/spi/dw_spi.h | |||
| @@ -14,7 +14,9 @@ | |||
| 14 | #define SPI_MODE_OFFSET 6 | 14 | #define SPI_MODE_OFFSET 6 |
| 15 | #define SPI_SCPH_OFFSET 6 | 15 | #define SPI_SCPH_OFFSET 6 |
| 16 | #define SPI_SCOL_OFFSET 7 | 16 | #define SPI_SCOL_OFFSET 7 |
| 17 | |||
| 17 | #define SPI_TMOD_OFFSET 8 | 18 | #define SPI_TMOD_OFFSET 8 |
| 19 | #define SPI_TMOD_MASK (0x3 << SPI_TMOD_OFFSET) | ||
| 18 | #define SPI_TMOD_TR 0x0 /* xmit & recv */ | 20 | #define SPI_TMOD_TR 0x0 /* xmit & recv */ |
| 19 | #define SPI_TMOD_TO 0x1 /* xmit only */ | 21 | #define SPI_TMOD_TO 0x1 /* xmit only */ |
| 20 | #define SPI_TMOD_RO 0x2 /* recv only */ | 22 | #define SPI_TMOD_RO 0x2 /* recv only */ |
diff --git a/include/linux/sunrpc/clnt.h b/include/linux/sunrpc/clnt.h index 569dc722a600..85f38a63f098 100644 --- a/include/linux/sunrpc/clnt.h +++ b/include/linux/sunrpc/clnt.h | |||
| @@ -30,7 +30,7 @@ struct rpc_inode; | |||
| 30 | * The high-level client handle | 30 | * The high-level client handle |
| 31 | */ | 31 | */ |
| 32 | struct rpc_clnt { | 32 | struct rpc_clnt { |
| 33 | struct kref cl_kref; /* Number of references */ | 33 | atomic_t cl_count; /* Number of references */ |
| 34 | struct list_head cl_clients; /* Global list of clients */ | 34 | struct list_head cl_clients; /* Global list of clients */ |
| 35 | struct list_head cl_tasks; /* List of tasks */ | 35 | struct list_head cl_tasks; /* List of tasks */ |
| 36 | spinlock_t cl_lock; /* spinlock */ | 36 | spinlock_t cl_lock; /* spinlock */ |
diff --git a/kernel/compat.c b/kernel/compat.c index e167efce8423..c9e2ec0b34a8 100644 --- a/kernel/compat.c +++ b/kernel/compat.c | |||
| @@ -1126,3 +1126,24 @@ compat_sys_sysinfo(struct compat_sysinfo __user *info) | |||
| 1126 | 1126 | ||
| 1127 | return 0; | 1127 | return 0; |
| 1128 | } | 1128 | } |
| 1129 | |||
| 1130 | /* | ||
| 1131 | * Allocate user-space memory for the duration of a single system call, | ||
| 1132 | * in order to marshall parameters inside a compat thunk. | ||
| 1133 | */ | ||
| 1134 | void __user *compat_alloc_user_space(unsigned long len) | ||
| 1135 | { | ||
| 1136 | void __user *ptr; | ||
| 1137 | |||
| 1138 | /* If len would occupy more than half of the entire compat space... */ | ||
| 1139 | if (unlikely(len > (((compat_uptr_t)~0) >> 1))) | ||
| 1140 | return NULL; | ||
| 1141 | |||
| 1142 | ptr = arch_compat_alloc_user_space(len); | ||
| 1143 | |||
| 1144 | if (unlikely(!access_ok(VERIFY_WRITE, ptr, len))) | ||
| 1145 | return NULL; | ||
| 1146 | |||
| 1147 | return ptr; | ||
| 1148 | } | ||
| 1149 | EXPORT_SYMBOL_GPL(compat_alloc_user_space); | ||
diff --git a/kernel/sched_fair.c b/kernel/sched_fair.c index 9b5b4f86b742..a171138a9402 100644 --- a/kernel/sched_fair.c +++ b/kernel/sched_fair.c | |||
| @@ -54,13 +54,13 @@ enum sched_tunable_scaling sysctl_sched_tunable_scaling | |||
| 54 | * Minimal preemption granularity for CPU-bound tasks: | 54 | * Minimal preemption granularity for CPU-bound tasks: |
| 55 | * (default: 2 msec * (1 + ilog(ncpus)), units: nanoseconds) | 55 | * (default: 2 msec * (1 + ilog(ncpus)), units: nanoseconds) |
| 56 | */ | 56 | */ |
| 57 | unsigned int sysctl_sched_min_granularity = 2000000ULL; | 57 | unsigned int sysctl_sched_min_granularity = 750000ULL; |
| 58 | unsigned int normalized_sysctl_sched_min_granularity = 2000000ULL; | 58 | unsigned int normalized_sysctl_sched_min_granularity = 750000ULL; |
| 59 | 59 | ||
| 60 | /* | 60 | /* |
| 61 | * is kept at sysctl_sched_latency / sysctl_sched_min_granularity | 61 | * is kept at sysctl_sched_latency / sysctl_sched_min_granularity |
| 62 | */ | 62 | */ |
| 63 | static unsigned int sched_nr_latency = 3; | 63 | static unsigned int sched_nr_latency = 8; |
| 64 | 64 | ||
| 65 | /* | 65 | /* |
| 66 | * After fork, child runs first. If set to 0 (default) then | 66 | * After fork, child runs first. If set to 0 (default) then |
diff --git a/net/9p/client.c b/net/9p/client.c index dc6f2f26d023..9eb72505308f 100644 --- a/net/9p/client.c +++ b/net/9p/client.c | |||
| @@ -331,8 +331,10 @@ static void p9_tag_cleanup(struct p9_client *c) | |||
| 331 | } | 331 | } |
| 332 | } | 332 | } |
| 333 | 333 | ||
| 334 | if (c->tagpool) | 334 | if (c->tagpool) { |
| 335 | p9_idpool_put(0, c->tagpool); /* free reserved tag 0 */ | ||
| 335 | p9_idpool_destroy(c->tagpool); | 336 | p9_idpool_destroy(c->tagpool); |
| 337 | } | ||
| 336 | 338 | ||
| 337 | /* free requests associated with tags */ | 339 | /* free requests associated with tags */ |
| 338 | for (row = 0; row < (c->max_tag/P9_ROW_MAXTAG); row++) { | 340 | for (row = 0; row < (c->max_tag/P9_ROW_MAXTAG); row++) { |
| @@ -944,6 +946,7 @@ struct p9_fid *p9_client_walk(struct p9_fid *oldfid, int nwname, char **wnames, | |||
| 944 | int16_t nwqids, count; | 946 | int16_t nwqids, count; |
| 945 | 947 | ||
| 946 | err = 0; | 948 | err = 0; |
| 949 | wqids = NULL; | ||
| 947 | clnt = oldfid->clnt; | 950 | clnt = oldfid->clnt; |
| 948 | if (clone) { | 951 | if (clone) { |
| 949 | fid = p9_fid_create(clnt); | 952 | fid = p9_fid_create(clnt); |
| @@ -994,9 +997,11 @@ struct p9_fid *p9_client_walk(struct p9_fid *oldfid, int nwname, char **wnames, | |||
| 994 | else | 997 | else |
| 995 | fid->qid = oldfid->qid; | 998 | fid->qid = oldfid->qid; |
| 996 | 999 | ||
| 1000 | kfree(wqids); | ||
| 997 | return fid; | 1001 | return fid; |
| 998 | 1002 | ||
| 999 | clunk_fid: | 1003 | clunk_fid: |
| 1004 | kfree(wqids); | ||
| 1000 | p9_client_clunk(fid); | 1005 | p9_client_clunk(fid); |
| 1001 | fid = NULL; | 1006 | fid = NULL; |
| 1002 | 1007 | ||
diff --git a/net/sunrpc/auth.c b/net/sunrpc/auth.c index 36cb66022a27..e9eaaf7d43c1 100644 --- a/net/sunrpc/auth.c +++ b/net/sunrpc/auth.c | |||
| @@ -38,7 +38,7 @@ static const struct rpc_authops *auth_flavors[RPC_AUTH_MAXFLAVOR] = { | |||
| 38 | static LIST_HEAD(cred_unused); | 38 | static LIST_HEAD(cred_unused); |
| 39 | static unsigned long number_cred_unused; | 39 | static unsigned long number_cred_unused; |
| 40 | 40 | ||
| 41 | #define MAX_HASHTABLE_BITS (10) | 41 | #define MAX_HASHTABLE_BITS (14) |
| 42 | static int param_set_hashtbl_sz(const char *val, const struct kernel_param *kp) | 42 | static int param_set_hashtbl_sz(const char *val, const struct kernel_param *kp) |
| 43 | { | 43 | { |
| 44 | unsigned long num; | 44 | unsigned long num; |
diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c index dcfc66bab2bb..12c485982814 100644 --- a/net/sunrpc/auth_gss/auth_gss.c +++ b/net/sunrpc/auth_gss/auth_gss.c | |||
| @@ -745,17 +745,18 @@ gss_pipe_release(struct inode *inode) | |||
| 745 | struct rpc_inode *rpci = RPC_I(inode); | 745 | struct rpc_inode *rpci = RPC_I(inode); |
| 746 | struct gss_upcall_msg *gss_msg; | 746 | struct gss_upcall_msg *gss_msg; |
| 747 | 747 | ||
| 748 | restart: | ||
| 748 | spin_lock(&inode->i_lock); | 749 | spin_lock(&inode->i_lock); |
| 749 | while (!list_empty(&rpci->in_downcall)) { | 750 | list_for_each_entry(gss_msg, &rpci->in_downcall, list) { |
| 750 | 751 | ||
| 751 | gss_msg = list_entry(rpci->in_downcall.next, | 752 | if (!list_empty(&gss_msg->msg.list)) |
| 752 | struct gss_upcall_msg, list); | 753 | continue; |
| 753 | gss_msg->msg.errno = -EPIPE; | 754 | gss_msg->msg.errno = -EPIPE; |
| 754 | atomic_inc(&gss_msg->count); | 755 | atomic_inc(&gss_msg->count); |
| 755 | __gss_unhash_msg(gss_msg); | 756 | __gss_unhash_msg(gss_msg); |
| 756 | spin_unlock(&inode->i_lock); | 757 | spin_unlock(&inode->i_lock); |
| 757 | gss_release_msg(gss_msg); | 758 | gss_release_msg(gss_msg); |
| 758 | spin_lock(&inode->i_lock); | 759 | goto restart; |
| 759 | } | 760 | } |
| 760 | spin_unlock(&inode->i_lock); | 761 | spin_unlock(&inode->i_lock); |
| 761 | 762 | ||
diff --git a/net/sunrpc/auth_gss/gss_krb5_mech.c b/net/sunrpc/auth_gss/gss_krb5_mech.c index 032644610524..778e5dfc5144 100644 --- a/net/sunrpc/auth_gss/gss_krb5_mech.c +++ b/net/sunrpc/auth_gss/gss_krb5_mech.c | |||
| @@ -237,6 +237,7 @@ get_key(const void *p, const void *end, | |||
| 237 | if (!supported_gss_krb5_enctype(alg)) { | 237 | if (!supported_gss_krb5_enctype(alg)) { |
| 238 | printk(KERN_WARNING "gss_kerberos_mech: unsupported " | 238 | printk(KERN_WARNING "gss_kerberos_mech: unsupported " |
| 239 | "encryption key algorithm %d\n", alg); | 239 | "encryption key algorithm %d\n", alg); |
| 240 | p = ERR_PTR(-EINVAL); | ||
| 240 | goto out_err; | 241 | goto out_err; |
| 241 | } | 242 | } |
| 242 | p = simple_get_netobj(p, end, &key); | 243 | p = simple_get_netobj(p, end, &key); |
| @@ -282,15 +283,19 @@ gss_import_v1_context(const void *p, const void *end, struct krb5_ctx *ctx) | |||
| 282 | ctx->enctype = ENCTYPE_DES_CBC_RAW; | 283 | ctx->enctype = ENCTYPE_DES_CBC_RAW; |
| 283 | 284 | ||
| 284 | ctx->gk5e = get_gss_krb5_enctype(ctx->enctype); | 285 | ctx->gk5e = get_gss_krb5_enctype(ctx->enctype); |
| 285 | if (ctx->gk5e == NULL) | 286 | if (ctx->gk5e == NULL) { |
| 287 | p = ERR_PTR(-EINVAL); | ||
| 286 | goto out_err; | 288 | goto out_err; |
| 289 | } | ||
| 287 | 290 | ||
| 288 | /* The downcall format was designed before we completely understood | 291 | /* The downcall format was designed before we completely understood |
| 289 | * the uses of the context fields; so it includes some stuff we | 292 | * the uses of the context fields; so it includes some stuff we |
| 290 | * just give some minimal sanity-checking, and some we ignore | 293 | * just give some minimal sanity-checking, and some we ignore |
| 291 | * completely (like the next twenty bytes): */ | 294 | * completely (like the next twenty bytes): */ |
| 292 | if (unlikely(p + 20 > end || p + 20 < p)) | 295 | if (unlikely(p + 20 > end || p + 20 < p)) { |
| 296 | p = ERR_PTR(-EFAULT); | ||
| 293 | goto out_err; | 297 | goto out_err; |
| 298 | } | ||
| 294 | p += 20; | 299 | p += 20; |
| 295 | p = simple_get_bytes(p, end, &tmp, sizeof(tmp)); | 300 | p = simple_get_bytes(p, end, &tmp, sizeof(tmp)); |
| 296 | if (IS_ERR(p)) | 301 | if (IS_ERR(p)) |
| @@ -619,6 +624,7 @@ gss_import_v2_context(const void *p, const void *end, struct krb5_ctx *ctx, | |||
| 619 | if (ctx->seq_send64 != ctx->seq_send) { | 624 | if (ctx->seq_send64 != ctx->seq_send) { |
| 620 | dprintk("%s: seq_send64 %lx, seq_send %x overflow?\n", __func__, | 625 | dprintk("%s: seq_send64 %lx, seq_send %x overflow?\n", __func__, |
| 621 | (long unsigned)ctx->seq_send64, ctx->seq_send); | 626 | (long unsigned)ctx->seq_send64, ctx->seq_send); |
| 627 | p = ERR_PTR(-EINVAL); | ||
| 622 | goto out_err; | 628 | goto out_err; |
| 623 | } | 629 | } |
| 624 | p = simple_get_bytes(p, end, &ctx->enctype, sizeof(ctx->enctype)); | 630 | p = simple_get_bytes(p, end, &ctx->enctype, sizeof(ctx->enctype)); |
diff --git a/net/sunrpc/auth_gss/gss_spkm3_mech.c b/net/sunrpc/auth_gss/gss_spkm3_mech.c index dc3f1f5ed865..adade3d313f2 100644 --- a/net/sunrpc/auth_gss/gss_spkm3_mech.c +++ b/net/sunrpc/auth_gss/gss_spkm3_mech.c | |||
| @@ -100,6 +100,7 @@ gss_import_sec_context_spkm3(const void *p, size_t len, | |||
| 100 | if (version != 1) { | 100 | if (version != 1) { |
| 101 | dprintk("RPC: unknown spkm3 token format: " | 101 | dprintk("RPC: unknown spkm3 token format: " |
| 102 | "obsolete nfs-utils?\n"); | 102 | "obsolete nfs-utils?\n"); |
| 103 | p = ERR_PTR(-EINVAL); | ||
| 103 | goto out_err_free_ctx; | 104 | goto out_err_free_ctx; |
| 104 | } | 105 | } |
| 105 | 106 | ||
| @@ -135,8 +136,10 @@ gss_import_sec_context_spkm3(const void *p, size_t len, | |||
| 135 | if (IS_ERR(p)) | 136 | if (IS_ERR(p)) |
| 136 | goto out_err_free_intg_alg; | 137 | goto out_err_free_intg_alg; |
| 137 | 138 | ||
| 138 | if (p != end) | 139 | if (p != end) { |
| 140 | p = ERR_PTR(-EFAULT); | ||
| 139 | goto out_err_free_intg_key; | 141 | goto out_err_free_intg_key; |
| 142 | } | ||
| 140 | 143 | ||
| 141 | ctx_id->internal_ctx_id = ctx; | 144 | ctx_id->internal_ctx_id = ctx; |
| 142 | 145 | ||
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c index 2388d83b68ff..fa5549079d79 100644 --- a/net/sunrpc/clnt.c +++ b/net/sunrpc/clnt.c | |||
| @@ -226,7 +226,7 @@ static struct rpc_clnt * rpc_new_client(const struct rpc_create_args *args, stru | |||
| 226 | goto out_no_principal; | 226 | goto out_no_principal; |
| 227 | } | 227 | } |
| 228 | 228 | ||
| 229 | kref_init(&clnt->cl_kref); | 229 | atomic_set(&clnt->cl_count, 1); |
| 230 | 230 | ||
| 231 | err = rpc_setup_pipedir(clnt, program->pipe_dir_name); | 231 | err = rpc_setup_pipedir(clnt, program->pipe_dir_name); |
| 232 | if (err < 0) | 232 | if (err < 0) |
| @@ -390,14 +390,14 @@ rpc_clone_client(struct rpc_clnt *clnt) | |||
| 390 | if (new->cl_principal == NULL) | 390 | if (new->cl_principal == NULL) |
| 391 | goto out_no_principal; | 391 | goto out_no_principal; |
| 392 | } | 392 | } |
| 393 | kref_init(&new->cl_kref); | 393 | atomic_set(&new->cl_count, 1); |
| 394 | err = rpc_setup_pipedir(new, clnt->cl_program->pipe_dir_name); | 394 | err = rpc_setup_pipedir(new, clnt->cl_program->pipe_dir_name); |
| 395 | if (err != 0) | 395 | if (err != 0) |
| 396 | goto out_no_path; | 396 | goto out_no_path; |
| 397 | if (new->cl_auth) | 397 | if (new->cl_auth) |
| 398 | atomic_inc(&new->cl_auth->au_count); | 398 | atomic_inc(&new->cl_auth->au_count); |
| 399 | xprt_get(clnt->cl_xprt); | 399 | xprt_get(clnt->cl_xprt); |
| 400 | kref_get(&clnt->cl_kref); | 400 | atomic_inc(&clnt->cl_count); |
| 401 | rpc_register_client(new); | 401 | rpc_register_client(new); |
| 402 | rpciod_up(); | 402 | rpciod_up(); |
| 403 | return new; | 403 | return new; |
| @@ -465,10 +465,8 @@ EXPORT_SYMBOL_GPL(rpc_shutdown_client); | |||
| 465 | * Free an RPC client | 465 | * Free an RPC client |
| 466 | */ | 466 | */ |
| 467 | static void | 467 | static void |
| 468 | rpc_free_client(struct kref *kref) | 468 | rpc_free_client(struct rpc_clnt *clnt) |
| 469 | { | 469 | { |
| 470 | struct rpc_clnt *clnt = container_of(kref, struct rpc_clnt, cl_kref); | ||
| 471 | |||
| 472 | dprintk("RPC: destroying %s client for %s\n", | 470 | dprintk("RPC: destroying %s client for %s\n", |
| 473 | clnt->cl_protname, clnt->cl_server); | 471 | clnt->cl_protname, clnt->cl_server); |
| 474 | if (!IS_ERR(clnt->cl_path.dentry)) { | 472 | if (!IS_ERR(clnt->cl_path.dentry)) { |
| @@ -495,12 +493,10 @@ out_free: | |||
| 495 | * Free an RPC client | 493 | * Free an RPC client |
| 496 | */ | 494 | */ |
| 497 | static void | 495 | static void |
| 498 | rpc_free_auth(struct kref *kref) | 496 | rpc_free_auth(struct rpc_clnt *clnt) |
| 499 | { | 497 | { |
| 500 | struct rpc_clnt *clnt = container_of(kref, struct rpc_clnt, cl_kref); | ||
| 501 | |||
| 502 | if (clnt->cl_auth == NULL) { | 498 | if (clnt->cl_auth == NULL) { |
| 503 | rpc_free_client(kref); | 499 | rpc_free_client(clnt); |
| 504 | return; | 500 | return; |
| 505 | } | 501 | } |
| 506 | 502 | ||
| @@ -509,10 +505,11 @@ rpc_free_auth(struct kref *kref) | |||
| 509 | * release remaining GSS contexts. This mechanism ensures | 505 | * release remaining GSS contexts. This mechanism ensures |
| 510 | * that it can do so safely. | 506 | * that it can do so safely. |
| 511 | */ | 507 | */ |
| 512 | kref_init(kref); | 508 | atomic_inc(&clnt->cl_count); |
| 513 | rpcauth_release(clnt->cl_auth); | 509 | rpcauth_release(clnt->cl_auth); |
| 514 | clnt->cl_auth = NULL; | 510 | clnt->cl_auth = NULL; |
| 515 | kref_put(kref, rpc_free_client); | 511 | if (atomic_dec_and_test(&clnt->cl_count)) |
| 512 | rpc_free_client(clnt); | ||
| 516 | } | 513 | } |
| 517 | 514 | ||
| 518 | /* | 515 | /* |
| @@ -525,7 +522,8 @@ rpc_release_client(struct rpc_clnt *clnt) | |||
| 525 | 522 | ||
| 526 | if (list_empty(&clnt->cl_tasks)) | 523 | if (list_empty(&clnt->cl_tasks)) |
| 527 | wake_up(&destroy_wait); | 524 | wake_up(&destroy_wait); |
| 528 | kref_put(&clnt->cl_kref, rpc_free_auth); | 525 | if (atomic_dec_and_test(&clnt->cl_count)) |
| 526 | rpc_free_auth(clnt); | ||
| 529 | } | 527 | } |
| 530 | 528 | ||
| 531 | /** | 529 | /** |
| @@ -588,7 +586,7 @@ void rpc_task_set_client(struct rpc_task *task, struct rpc_clnt *clnt) | |||
| 588 | if (clnt != NULL) { | 586 | if (clnt != NULL) { |
| 589 | rpc_task_release_client(task); | 587 | rpc_task_release_client(task); |
| 590 | task->tk_client = clnt; | 588 | task->tk_client = clnt; |
| 591 | kref_get(&clnt->cl_kref); | 589 | atomic_inc(&clnt->cl_count); |
| 592 | if (clnt->cl_softrtry) | 590 | if (clnt->cl_softrtry) |
| 593 | task->tk_flags |= RPC_TASK_SOFT; | 591 | task->tk_flags |= RPC_TASK_SOFT; |
| 594 | /* Add to the client's list of all tasks */ | 592 | /* Add to the client's list of all tasks */ |
| @@ -931,7 +929,7 @@ call_reserveresult(struct rpc_task *task) | |||
| 931 | task->tk_status = 0; | 929 | task->tk_status = 0; |
| 932 | if (status >= 0) { | 930 | if (status >= 0) { |
| 933 | if (task->tk_rqstp) { | 931 | if (task->tk_rqstp) { |
| 934 | task->tk_action = call_allocate; | 932 | task->tk_action = call_refresh; |
| 935 | return; | 933 | return; |
| 936 | } | 934 | } |
| 937 | 935 | ||
| @@ -966,13 +964,54 @@ call_reserveresult(struct rpc_task *task) | |||
| 966 | } | 964 | } |
| 967 | 965 | ||
| 968 | /* | 966 | /* |
| 969 | * 2. Allocate the buffer. For details, see sched.c:rpc_malloc. | 967 | * 2. Bind and/or refresh the credentials |
| 968 | */ | ||
| 969 | static void | ||
| 970 | call_refresh(struct rpc_task *task) | ||
| 971 | { | ||
| 972 | dprint_status(task); | ||
| 973 | |||
| 974 | task->tk_action = call_refreshresult; | ||
| 975 | task->tk_status = 0; | ||
| 976 | task->tk_client->cl_stats->rpcauthrefresh++; | ||
| 977 | rpcauth_refreshcred(task); | ||
| 978 | } | ||
| 979 | |||
| 980 | /* | ||
| 981 | * 2a. Process the results of a credential refresh | ||
| 982 | */ | ||
| 983 | static void | ||
| 984 | call_refreshresult(struct rpc_task *task) | ||
| 985 | { | ||
| 986 | int status = task->tk_status; | ||
| 987 | |||
| 988 | dprint_status(task); | ||
| 989 | |||
| 990 | task->tk_status = 0; | ||
| 991 | task->tk_action = call_allocate; | ||
| 992 | if (status >= 0 && rpcauth_uptodatecred(task)) | ||
| 993 | return; | ||
| 994 | switch (status) { | ||
| 995 | case -EACCES: | ||
| 996 | rpc_exit(task, -EACCES); | ||
| 997 | return; | ||
| 998 | case -ENOMEM: | ||
| 999 | rpc_exit(task, -ENOMEM); | ||
| 1000 | return; | ||
| 1001 | case -ETIMEDOUT: | ||
| 1002 | rpc_delay(task, 3*HZ); | ||
| 1003 | } | ||
| 1004 | task->tk_action = call_refresh; | ||
| 1005 | } | ||
| 1006 | |||
| 1007 | /* | ||
| 1008 | * 2b. Allocate the buffer. For details, see sched.c:rpc_malloc. | ||
| 970 | * (Note: buffer memory is freed in xprt_release). | 1009 | * (Note: buffer memory is freed in xprt_release). |
| 971 | */ | 1010 | */ |
| 972 | static void | 1011 | static void |
| 973 | call_allocate(struct rpc_task *task) | 1012 | call_allocate(struct rpc_task *task) |
| 974 | { | 1013 | { |
| 975 | unsigned int slack = task->tk_client->cl_auth->au_cslack; | 1014 | unsigned int slack = task->tk_rqstp->rq_cred->cr_auth->au_cslack; |
| 976 | struct rpc_rqst *req = task->tk_rqstp; | 1015 | struct rpc_rqst *req = task->tk_rqstp; |
| 977 | struct rpc_xprt *xprt = task->tk_xprt; | 1016 | struct rpc_xprt *xprt = task->tk_xprt; |
| 978 | struct rpc_procinfo *proc = task->tk_msg.rpc_proc; | 1017 | struct rpc_procinfo *proc = task->tk_msg.rpc_proc; |
| @@ -980,7 +1019,7 @@ call_allocate(struct rpc_task *task) | |||
| 980 | dprint_status(task); | 1019 | dprint_status(task); |
| 981 | 1020 | ||
| 982 | task->tk_status = 0; | 1021 | task->tk_status = 0; |
| 983 | task->tk_action = call_refresh; | 1022 | task->tk_action = call_bind; |
| 984 | 1023 | ||
| 985 | if (req->rq_buffer) | 1024 | if (req->rq_buffer) |
| 986 | return; | 1025 | return; |
| @@ -1017,47 +1056,6 @@ call_allocate(struct rpc_task *task) | |||
| 1017 | rpc_exit(task, -ERESTARTSYS); | 1056 | rpc_exit(task, -ERESTARTSYS); |
| 1018 | } | 1057 | } |
| 1019 | 1058 | ||
| 1020 | /* | ||
| 1021 | * 2a. Bind and/or refresh the credentials | ||
| 1022 | */ | ||
| 1023 | static void | ||
| 1024 | call_refresh(struct rpc_task *task) | ||
| 1025 | { | ||
| 1026 | dprint_status(task); | ||
| 1027 | |||
| 1028 | task->tk_action = call_refreshresult; | ||
| 1029 | task->tk_status = 0; | ||
| 1030 | task->tk_client->cl_stats->rpcauthrefresh++; | ||
| 1031 | rpcauth_refreshcred(task); | ||
| 1032 | } | ||
| 1033 | |||
| 1034 | /* | ||
| 1035 | * 2b. Process the results of a credential refresh | ||
| 1036 | */ | ||
| 1037 | static void | ||
| 1038 | call_refreshresult(struct rpc_task *task) | ||
| 1039 | { | ||
| 1040 | int status = task->tk_status; | ||
| 1041 | |||
| 1042 | dprint_status(task); | ||
| 1043 | |||
| 1044 | task->tk_status = 0; | ||
| 1045 | task->tk_action = call_bind; | ||
| 1046 | if (status >= 0 && rpcauth_uptodatecred(task)) | ||
| 1047 | return; | ||
| 1048 | switch (status) { | ||
| 1049 | case -EACCES: | ||
| 1050 | rpc_exit(task, -EACCES); | ||
| 1051 | return; | ||
| 1052 | case -ENOMEM: | ||
| 1053 | rpc_exit(task, -ENOMEM); | ||
| 1054 | return; | ||
| 1055 | case -ETIMEDOUT: | ||
| 1056 | rpc_delay(task, 3*HZ); | ||
| 1057 | } | ||
| 1058 | task->tk_action = call_refresh; | ||
| 1059 | } | ||
| 1060 | |||
| 1061 | static inline int | 1059 | static inline int |
| 1062 | rpc_task_need_encode(struct rpc_task *task) | 1060 | rpc_task_need_encode(struct rpc_task *task) |
| 1063 | { | 1061 | { |
diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c index 95ccbcf45d3e..8c8eef2b8f26 100644 --- a/net/sunrpc/rpc_pipe.c +++ b/net/sunrpc/rpc_pipe.c | |||
| @@ -48,7 +48,7 @@ static void rpc_purge_list(struct rpc_inode *rpci, struct list_head *head, | |||
| 48 | return; | 48 | return; |
| 49 | do { | 49 | do { |
| 50 | msg = list_entry(head->next, struct rpc_pipe_msg, list); | 50 | msg = list_entry(head->next, struct rpc_pipe_msg, list); |
| 51 | list_del(&msg->list); | 51 | list_del_init(&msg->list); |
| 52 | msg->errno = err; | 52 | msg->errno = err; |
| 53 | destroy_msg(msg); | 53 | destroy_msg(msg); |
| 54 | } while (!list_empty(head)); | 54 | } while (!list_empty(head)); |
| @@ -208,7 +208,7 @@ rpc_pipe_release(struct inode *inode, struct file *filp) | |||
| 208 | if (msg != NULL) { | 208 | if (msg != NULL) { |
| 209 | spin_lock(&inode->i_lock); | 209 | spin_lock(&inode->i_lock); |
| 210 | msg->errno = -EAGAIN; | 210 | msg->errno = -EAGAIN; |
| 211 | list_del(&msg->list); | 211 | list_del_init(&msg->list); |
| 212 | spin_unlock(&inode->i_lock); | 212 | spin_unlock(&inode->i_lock); |
| 213 | rpci->ops->destroy_msg(msg); | 213 | rpci->ops->destroy_msg(msg); |
| 214 | } | 214 | } |
| @@ -268,7 +268,7 @@ rpc_pipe_read(struct file *filp, char __user *buf, size_t len, loff_t *offset) | |||
| 268 | if (res < 0 || msg->len == msg->copied) { | 268 | if (res < 0 || msg->len == msg->copied) { |
| 269 | filp->private_data = NULL; | 269 | filp->private_data = NULL; |
| 270 | spin_lock(&inode->i_lock); | 270 | spin_lock(&inode->i_lock); |
| 271 | list_del(&msg->list); | 271 | list_del_init(&msg->list); |
| 272 | spin_unlock(&inode->i_lock); | 272 | spin_unlock(&inode->i_lock); |
| 273 | rpci->ops->destroy_msg(msg); | 273 | rpci->ops->destroy_msg(msg); |
| 274 | } | 274 | } |
| @@ -371,21 +371,23 @@ rpc_show_info(struct seq_file *m, void *v) | |||
| 371 | static int | 371 | static int |
| 372 | rpc_info_open(struct inode *inode, struct file *file) | 372 | rpc_info_open(struct inode *inode, struct file *file) |
| 373 | { | 373 | { |
| 374 | struct rpc_clnt *clnt; | 374 | struct rpc_clnt *clnt = NULL; |
| 375 | int ret = single_open(file, rpc_show_info, NULL); | 375 | int ret = single_open(file, rpc_show_info, NULL); |
| 376 | 376 | ||
| 377 | if (!ret) { | 377 | if (!ret) { |
| 378 | struct seq_file *m = file->private_data; | 378 | struct seq_file *m = file->private_data; |
| 379 | mutex_lock(&inode->i_mutex); | 379 | |
| 380 | clnt = RPC_I(inode)->private; | 380 | spin_lock(&file->f_path.dentry->d_lock); |
| 381 | if (clnt) { | 381 | if (!d_unhashed(file->f_path.dentry)) |
| 382 | kref_get(&clnt->cl_kref); | 382 | clnt = RPC_I(inode)->private; |
| 383 | if (clnt != NULL && atomic_inc_not_zero(&clnt->cl_count)) { | ||
| 384 | spin_unlock(&file->f_path.dentry->d_lock); | ||
| 383 | m->private = clnt; | 385 | m->private = clnt; |
| 384 | } else { | 386 | } else { |
| 387 | spin_unlock(&file->f_path.dentry->d_lock); | ||
| 385 | single_release(inode, file); | 388 | single_release(inode, file); |
| 386 | ret = -EINVAL; | 389 | ret = -EINVAL; |
| 387 | } | 390 | } |
| 388 | mutex_unlock(&inode->i_mutex); | ||
| 389 | } | 391 | } |
| 390 | return ret; | 392 | return ret; |
| 391 | } | 393 | } |
diff --git a/scripts/basic/docproc.c b/scripts/basic/docproc.c index 79ab973fb43a..fc3b18d844af 100644 --- a/scripts/basic/docproc.c +++ b/scripts/basic/docproc.c | |||
| @@ -34,12 +34,14 @@ | |||
| 34 | * | 34 | * |
| 35 | */ | 35 | */ |
| 36 | 36 | ||
| 37 | #define _GNU_SOURCE | ||
| 37 | #include <stdio.h> | 38 | #include <stdio.h> |
| 38 | #include <stdlib.h> | 39 | #include <stdlib.h> |
| 39 | #include <string.h> | 40 | #include <string.h> |
| 40 | #include <ctype.h> | 41 | #include <ctype.h> |
| 41 | #include <unistd.h> | 42 | #include <unistd.h> |
| 42 | #include <limits.h> | 43 | #include <limits.h> |
| 44 | #include <errno.h> | ||
| 43 | #include <sys/types.h> | 45 | #include <sys/types.h> |
| 44 | #include <sys/wait.h> | 46 | #include <sys/wait.h> |
| 45 | 47 | ||
| @@ -54,6 +56,7 @@ typedef void FILEONLY(char * file); | |||
| 54 | FILEONLY *internalfunctions; | 56 | FILEONLY *internalfunctions; |
| 55 | FILEONLY *externalfunctions; | 57 | FILEONLY *externalfunctions; |
| 56 | FILEONLY *symbolsonly; | 58 | FILEONLY *symbolsonly; |
| 59 | FILEONLY *findall; | ||
| 57 | 60 | ||
| 58 | typedef void FILELINE(char * file, char * line); | 61 | typedef void FILELINE(char * file, char * line); |
| 59 | FILELINE * singlefunctions; | 62 | FILELINE * singlefunctions; |
| @@ -65,12 +68,30 @@ FILELINE * docsection; | |||
| 65 | #define KERNELDOCPATH "scripts/" | 68 | #define KERNELDOCPATH "scripts/" |
| 66 | #define KERNELDOC "kernel-doc" | 69 | #define KERNELDOC "kernel-doc" |
| 67 | #define DOCBOOK "-docbook" | 70 | #define DOCBOOK "-docbook" |
| 71 | #define LIST "-list" | ||
| 68 | #define FUNCTION "-function" | 72 | #define FUNCTION "-function" |
| 69 | #define NOFUNCTION "-nofunction" | 73 | #define NOFUNCTION "-nofunction" |
| 70 | #define NODOCSECTIONS "-no-doc-sections" | 74 | #define NODOCSECTIONS "-no-doc-sections" |
| 71 | 75 | ||
| 72 | static char *srctree, *kernsrctree; | 76 | static char *srctree, *kernsrctree; |
| 73 | 77 | ||
| 78 | static char **all_list = NULL; | ||
| 79 | static int all_list_len = 0; | ||
| 80 | |||
| 81 | static void consume_symbol(const char *sym) | ||
| 82 | { | ||
| 83 | int i; | ||
| 84 | |||
| 85 | for (i = 0; i < all_list_len; i++) { | ||
| 86 | if (!all_list[i]) | ||
| 87 | continue; | ||
| 88 | if (strcmp(sym, all_list[i])) | ||
| 89 | continue; | ||
| 90 | all_list[i] = NULL; | ||
| 91 | break; | ||
| 92 | } | ||
| 93 | } | ||
| 94 | |||
| 74 | static void usage (void) | 95 | static void usage (void) |
| 75 | { | 96 | { |
| 76 | fprintf(stderr, "Usage: docproc {doc|depend} file\n"); | 97 | fprintf(stderr, "Usage: docproc {doc|depend} file\n"); |
| @@ -248,6 +269,7 @@ static void docfunctions(char * filename, char * type) | |||
| 248 | struct symfile * sym = &symfilelist[i]; | 269 | struct symfile * sym = &symfilelist[i]; |
| 249 | for (j=0; j < sym->symbolcnt; j++) { | 270 | for (j=0; j < sym->symbolcnt; j++) { |
| 250 | vec[idx++] = type; | 271 | vec[idx++] = type; |
| 272 | consume_symbol(sym->symbollist[j].name); | ||
| 251 | vec[idx++] = sym->symbollist[j].name; | 273 | vec[idx++] = sym->symbollist[j].name; |
| 252 | } | 274 | } |
| 253 | } | 275 | } |
| @@ -287,6 +309,11 @@ static void singfunc(char * filename, char * line) | |||
| 287 | vec[idx++] = &line[i]; | 309 | vec[idx++] = &line[i]; |
| 288 | } | 310 | } |
| 289 | } | 311 | } |
| 312 | for (i = 0; i < idx; i++) { | ||
| 313 | if (strcmp(vec[i], FUNCTION)) | ||
| 314 | continue; | ||
| 315 | consume_symbol(vec[i + 1]); | ||
| 316 | } | ||
| 290 | vec[idx++] = filename; | 317 | vec[idx++] = filename; |
| 291 | vec[idx] = NULL; | 318 | vec[idx] = NULL; |
| 292 | exec_kernel_doc(vec); | 319 | exec_kernel_doc(vec); |
| @@ -306,6 +333,10 @@ static void docsect(char *filename, char *line) | |||
| 306 | if (*s == '\n') | 333 | if (*s == '\n') |
| 307 | *s = '\0'; | 334 | *s = '\0'; |
| 308 | 335 | ||
| 336 | asprintf(&s, "DOC: %s", line); | ||
| 337 | consume_symbol(s); | ||
| 338 | free(s); | ||
| 339 | |||
| 309 | vec[0] = KERNELDOC; | 340 | vec[0] = KERNELDOC; |
| 310 | vec[1] = DOCBOOK; | 341 | vec[1] = DOCBOOK; |
| 311 | vec[2] = FUNCTION; | 342 | vec[2] = FUNCTION; |
| @@ -315,6 +346,84 @@ static void docsect(char *filename, char *line) | |||
| 315 | exec_kernel_doc(vec); | 346 | exec_kernel_doc(vec); |
| 316 | } | 347 | } |
| 317 | 348 | ||
| 349 | static void find_all_symbols(char *filename) | ||
| 350 | { | ||
| 351 | char *vec[4]; /* kerneldoc -list file NULL */ | ||
| 352 | pid_t pid; | ||
| 353 | int ret, i, count, start; | ||
| 354 | char real_filename[PATH_MAX + 1]; | ||
| 355 | int pipefd[2]; | ||
| 356 | char *data, *str; | ||
| 357 | size_t data_len = 0; | ||
| 358 | |||
| 359 | vec[0] = KERNELDOC; | ||
| 360 | vec[1] = LIST; | ||
| 361 | vec[2] = filename; | ||
| 362 | vec[3] = NULL; | ||
| 363 | |||
| 364 | if (pipe(pipefd)) { | ||
| 365 | perror("pipe"); | ||
| 366 | exit(1); | ||
| 367 | } | ||
| 368 | |||
| 369 | switch (pid=fork()) { | ||
| 370 | case -1: | ||
| 371 | perror("fork"); | ||
| 372 | exit(1); | ||
| 373 | case 0: | ||
| 374 | close(pipefd[0]); | ||
| 375 | dup2(pipefd[1], 1); | ||
| 376 | memset(real_filename, 0, sizeof(real_filename)); | ||
| 377 | strncat(real_filename, kernsrctree, PATH_MAX); | ||
| 378 | strncat(real_filename, "/" KERNELDOCPATH KERNELDOC, | ||
| 379 | PATH_MAX - strlen(real_filename)); | ||
| 380 | execvp(real_filename, vec); | ||
| 381 | fprintf(stderr, "exec "); | ||
| 382 | perror(real_filename); | ||
| 383 | exit(1); | ||
| 384 | default: | ||
| 385 | close(pipefd[1]); | ||
| 386 | data = malloc(4096); | ||
| 387 | do { | ||
| 388 | while ((ret = read(pipefd[0], | ||
| 389 | data + data_len, | ||
| 390 | 4096)) > 0) { | ||
| 391 | data_len += ret; | ||
| 392 | data = realloc(data, data_len + 4096); | ||
| 393 | } | ||
| 394 | } while (ret == -EAGAIN); | ||
| 395 | if (ret != 0) { | ||
| 396 | perror("read"); | ||
| 397 | exit(1); | ||
| 398 | } | ||
| 399 | waitpid(pid, &ret ,0); | ||
| 400 | } | ||
| 401 | if (WIFEXITED(ret)) | ||
| 402 | exitstatus |= WEXITSTATUS(ret); | ||
| 403 | else | ||
| 404 | exitstatus = 0xff; | ||
| 405 | |||
| 406 | count = 0; | ||
| 407 | /* poor man's strtok, but with counting */ | ||
| 408 | for (i = 0; i < data_len; i++) { | ||
| 409 | if (data[i] == '\n') { | ||
| 410 | count++; | ||
| 411 | data[i] = '\0'; | ||
| 412 | } | ||
| 413 | } | ||
| 414 | start = all_list_len; | ||
| 415 | all_list_len += count; | ||
| 416 | all_list = realloc(all_list, sizeof(char *) * all_list_len); | ||
| 417 | str = data; | ||
| 418 | for (i = 0; i < data_len && start != all_list_len; i++) { | ||
| 419 | if (data[i] == '\0') { | ||
| 420 | all_list[start] = str; | ||
| 421 | str = data + i + 1; | ||
| 422 | start++; | ||
| 423 | } | ||
| 424 | } | ||
| 425 | } | ||
| 426 | |||
| 318 | /* | 427 | /* |
| 319 | * Parse file, calling action specific functions for: | 428 | * Parse file, calling action specific functions for: |
| 320 | * 1) Lines containing !E | 429 | * 1) Lines containing !E |
| @@ -322,7 +431,8 @@ static void docsect(char *filename, char *line) | |||
| 322 | * 3) Lines containing !D | 431 | * 3) Lines containing !D |
| 323 | * 4) Lines containing !F | 432 | * 4) Lines containing !F |
| 324 | * 5) Lines containing !P | 433 | * 5) Lines containing !P |
| 325 | * 6) Default lines - lines not matching the above | 434 | * 6) Lines containing !C |
| 435 | * 7) Default lines - lines not matching the above | ||
| 326 | */ | 436 | */ |
| 327 | static void parse_file(FILE *infile) | 437 | static void parse_file(FILE *infile) |
| 328 | { | 438 | { |
| @@ -365,6 +475,12 @@ static void parse_file(FILE *infile) | |||
| 365 | s++; | 475 | s++; |
| 366 | docsection(line + 2, s); | 476 | docsection(line + 2, s); |
| 367 | break; | 477 | break; |
| 478 | case 'C': | ||
| 479 | while (*s && !isspace(*s)) s++; | ||
| 480 | *s = '\0'; | ||
| 481 | if (findall) | ||
| 482 | findall(line+2); | ||
| 483 | break; | ||
| 368 | default: | 484 | default: |
| 369 | defaultline(line); | 485 | defaultline(line); |
| 370 | } | 486 | } |
| @@ -380,6 +496,7 @@ static void parse_file(FILE *infile) | |||
| 380 | int main(int argc, char *argv[]) | 496 | int main(int argc, char *argv[]) |
| 381 | { | 497 | { |
| 382 | FILE * infile; | 498 | FILE * infile; |
| 499 | int i; | ||
| 383 | 500 | ||
| 384 | srctree = getenv("SRCTREE"); | 501 | srctree = getenv("SRCTREE"); |
| 385 | if (!srctree) | 502 | if (!srctree) |
| @@ -415,6 +532,7 @@ int main(int argc, char *argv[]) | |||
| 415 | symbolsonly = find_export_symbols; | 532 | symbolsonly = find_export_symbols; |
| 416 | singlefunctions = noaction2; | 533 | singlefunctions = noaction2; |
| 417 | docsection = noaction2; | 534 | docsection = noaction2; |
| 535 | findall = find_all_symbols; | ||
| 418 | parse_file(infile); | 536 | parse_file(infile); |
| 419 | 537 | ||
| 420 | /* Rewind to start from beginning of file again */ | 538 | /* Rewind to start from beginning of file again */ |
| @@ -425,8 +543,16 @@ int main(int argc, char *argv[]) | |||
| 425 | symbolsonly = printline; | 543 | symbolsonly = printline; |
| 426 | singlefunctions = singfunc; | 544 | singlefunctions = singfunc; |
| 427 | docsection = docsect; | 545 | docsection = docsect; |
| 546 | findall = NULL; | ||
| 428 | 547 | ||
| 429 | parse_file(infile); | 548 | parse_file(infile); |
| 549 | |||
| 550 | for (i = 0; i < all_list_len; i++) { | ||
| 551 | if (!all_list[i]) | ||
| 552 | continue; | ||
| 553 | fprintf(stderr, "Warning: didn't use docs for %s\n", | ||
| 554 | all_list[i]); | ||
| 555 | } | ||
| 430 | } | 556 | } |
| 431 | else if (strcmp("depend", argv[1]) == 0) | 557 | else if (strcmp("depend", argv[1]) == 0) |
| 432 | { | 558 | { |
| @@ -439,6 +565,7 @@ int main(int argc, char *argv[]) | |||
| 439 | symbolsonly = adddep; | 565 | symbolsonly = adddep; |
| 440 | singlefunctions = adddep2; | 566 | singlefunctions = adddep2; |
| 441 | docsection = adddep2; | 567 | docsection = adddep2; |
| 568 | findall = adddep; | ||
| 442 | parse_file(infile); | 569 | parse_file(infile); |
| 443 | printf("\n"); | 570 | printf("\n"); |
| 444 | } | 571 | } |
diff --git a/scripts/kernel-doc b/scripts/kernel-doc index 102e1235fd5c..cdb6dc1f6458 100755 --- a/scripts/kernel-doc +++ b/scripts/kernel-doc | |||
| @@ -44,12 +44,13 @@ use strict; | |||
| 44 | # Note: This only supports 'c'. | 44 | # Note: This only supports 'c'. |
| 45 | 45 | ||
| 46 | # usage: | 46 | # usage: |
| 47 | # kernel-doc [ -docbook | -html | -text | -man ] [ -no-doc-sections ] | 47 | # kernel-doc [ -docbook | -html | -text | -man | -list ] [ -no-doc-sections ] |
| 48 | # [ -function funcname [ -function funcname ...] ] c file(s)s > outputfile | 48 | # [ -function funcname [ -function funcname ...] ] c file(s)s > outputfile |
| 49 | # or | 49 | # or |
| 50 | # [ -nofunction funcname [ -function funcname ...] ] c file(s)s > outputfile | 50 | # [ -nofunction funcname [ -function funcname ...] ] c file(s)s > outputfile |
| 51 | # | 51 | # |
| 52 | # Set output format using one of -docbook -html -text or -man. Default is man. | 52 | # Set output format using one of -docbook -html -text or -man. Default is man. |
| 53 | # The -list format is for internal use by docproc. | ||
| 53 | # | 54 | # |
| 54 | # -no-doc-sections | 55 | # -no-doc-sections |
| 55 | # Do not output DOC: sections | 56 | # Do not output DOC: sections |
| @@ -210,9 +211,16 @@ my %highlights_text = ( $type_constant, "\$1", | |||
| 210 | $type_param, "\$1" ); | 211 | $type_param, "\$1" ); |
| 211 | my $blankline_text = ""; | 212 | my $blankline_text = ""; |
| 212 | 213 | ||
| 214 | # list mode | ||
| 215 | my %highlights_list = ( $type_constant, "\$1", | ||
| 216 | $type_func, "\$1", | ||
| 217 | $type_struct, "\$1", | ||
| 218 | $type_param, "\$1" ); | ||
| 219 | my $blankline_list = ""; | ||
| 213 | 220 | ||
| 214 | sub usage { | 221 | sub usage { |
| 215 | print "Usage: $0 [ -v ] [ -docbook | -html | -text | -man ] [ -no-doc-sections ]\n"; | 222 | print "Usage: $0 [ -v ] [ -docbook | -html | -text | -man | -list ]\n"; |
| 223 | print " [ -no-doc-sections ]\n"; | ||
| 216 | print " [ -function funcname [ -function funcname ...] ]\n"; | 224 | print " [ -function funcname [ -function funcname ...] ]\n"; |
| 217 | print " [ -nofunction funcname [ -nofunction funcname ...] ]\n"; | 225 | print " [ -nofunction funcname [ -nofunction funcname ...] ]\n"; |
| 218 | print " c source file(s) > outputfile\n"; | 226 | print " c source file(s) > outputfile\n"; |
| @@ -318,6 +326,10 @@ while ($ARGV[0] =~ m/^-(.*)/) { | |||
| 318 | $output_mode = "xml"; | 326 | $output_mode = "xml"; |
| 319 | %highlights = %highlights_xml; | 327 | %highlights = %highlights_xml; |
| 320 | $blankline = $blankline_xml; | 328 | $blankline = $blankline_xml; |
| 329 | } elsif ($cmd eq "-list") { | ||
| 330 | $output_mode = "list"; | ||
| 331 | %highlights = %highlights_list; | ||
| 332 | $blankline = $blankline_list; | ||
| 321 | } elsif ($cmd eq "-gnome") { | 333 | } elsif ($cmd eq "-gnome") { |
| 322 | $output_mode = "gnome"; | 334 | $output_mode = "gnome"; |
| 323 | %highlights = %highlights_gnome; | 335 | %highlights = %highlights_gnome; |
| @@ -1361,6 +1373,42 @@ sub output_blockhead_text(%) { | |||
| 1361 | } | 1373 | } |
| 1362 | } | 1374 | } |
| 1363 | 1375 | ||
| 1376 | ## list mode output functions | ||
| 1377 | |||
| 1378 | sub output_function_list(%) { | ||
| 1379 | my %args = %{$_[0]}; | ||
| 1380 | |||
| 1381 | print $args{'function'} . "\n"; | ||
| 1382 | } | ||
| 1383 | |||
| 1384 | # output enum in list | ||
| 1385 | sub output_enum_list(%) { | ||
| 1386 | my %args = %{$_[0]}; | ||
| 1387 | print $args{'enum'} . "\n"; | ||
| 1388 | } | ||
| 1389 | |||
| 1390 | # output typedef in list | ||
| 1391 | sub output_typedef_list(%) { | ||
| 1392 | my %args = %{$_[0]}; | ||
| 1393 | print $args{'typedef'} . "\n"; | ||
| 1394 | } | ||
| 1395 | |||
| 1396 | # output struct as list | ||
| 1397 | sub output_struct_list(%) { | ||
| 1398 | my %args = %{$_[0]}; | ||
| 1399 | |||
| 1400 | print $args{'struct'} . "\n"; | ||
| 1401 | } | ||
| 1402 | |||
| 1403 | sub output_blockhead_list(%) { | ||
| 1404 | my %args = %{$_[0]}; | ||
| 1405 | my ($parameter, $section); | ||
| 1406 | |||
| 1407 | foreach $section (@{$args{'sectionlist'}}) { | ||
| 1408 | print "DOC: $section\n"; | ||
| 1409 | } | ||
| 1410 | } | ||
| 1411 | |||
| 1364 | ## | 1412 | ## |
| 1365 | # generic output function for all types (function, struct/union, typedef, enum); | 1413 | # generic output function for all types (function, struct/union, typedef, enum); |
| 1366 | # calls the generated, variable output_ function name based on | 1414 | # calls the generated, variable output_ function name based on |
| @@ -1679,7 +1727,7 @@ sub check_sections($$$$$$) { | |||
| 1679 | foreach $px (0 .. $#prms) { | 1727 | foreach $px (0 .. $#prms) { |
| 1680 | $prm_clean = $prms[$px]; | 1728 | $prm_clean = $prms[$px]; |
| 1681 | $prm_clean =~ s/\[.*\]//; | 1729 | $prm_clean =~ s/\[.*\]//; |
| 1682 | $prm_clean =~ s/__attribute__\s*\(\([a-z,_\*\s\(\)]*\)\)//; | 1730 | $prm_clean =~ s/__attribute__\s*\(\([a-z,_\*\s\(\)]*\)\)//i; |
| 1683 | # ignore array size in a parameter string; | 1731 | # ignore array size in a parameter string; |
| 1684 | # however, the original param string may contain | 1732 | # however, the original param string may contain |
| 1685 | # spaces, e.g.: addr[6 + 2] | 1733 | # spaces, e.g.: addr[6 + 2] |
