diff options
90 files changed, 1202 insertions, 633 deletions
diff --git a/Documentation/input/multi-touch-protocol.txt b/Documentation/input/multi-touch-protocol.txt index 8490480ce432..c0fc1c75fd88 100644 --- a/Documentation/input/multi-touch-protocol.txt +++ b/Documentation/input/multi-touch-protocol.txt | |||
| @@ -68,6 +68,22 @@ like: | |||
| 68 | SYN_MT_REPORT | 68 | SYN_MT_REPORT |
| 69 | SYN_REPORT | 69 | SYN_REPORT |
| 70 | 70 | ||
| 71 | Here is the sequence after lifting one of the fingers: | ||
| 72 | |||
| 73 | ABS_MT_POSITION_X | ||
| 74 | ABS_MT_POSITION_Y | ||
| 75 | SYN_MT_REPORT | ||
| 76 | SYN_REPORT | ||
| 77 | |||
| 78 | And here is the sequence after lifting the remaining finger: | ||
| 79 | |||
| 80 | SYN_MT_REPORT | ||
| 81 | SYN_REPORT | ||
| 82 | |||
| 83 | If the driver reports one of BTN_TOUCH or ABS_PRESSURE in addition to the | ||
| 84 | ABS_MT events, the last SYN_MT_REPORT event may be omitted. Otherwise, the | ||
| 85 | last SYN_REPORT will be dropped by the input core, resulting in no | ||
| 86 | zero-finger event reaching userland. | ||
| 71 | 87 | ||
| 72 | Event Semantics | 88 | Event Semantics |
| 73 | --------------- | 89 | --------------- |
| @@ -217,11 +233,6 @@ where examples can be found. | |||
| 217 | difference between the contact position and the approaching tool position | 233 | difference between the contact position and the approaching tool position |
| 218 | could be used to derive tilt. | 234 | could be used to derive tilt. |
| 219 | [2] The list can of course be extended. | 235 | [2] The list can of course be extended. |
| 220 | [3] The multi-touch X driver is currently in the prototyping stage. At the | 236 | [3] Multitouch X driver project: http://bitmath.org/code/multitouch/. |
| 221 | time of writing (April 2009), the MT protocol is not yet merged, and the | ||
| 222 | prototype implements finger matching, basic mouse support and two-finger | ||
| 223 | scrolling. The project aims at improving the quality of current multi-touch | ||
| 224 | functionality available in the Synaptics X driver, and in addition | ||
| 225 | implement more advanced gestures. | ||
| 226 | [4] See the section on event computation. | 237 | [4] See the section on event computation. |
| 227 | [5] See the section on finger tracking. | 238 | [5] See the section on finger tracking. |
diff --git a/Documentation/networking/timestamping.txt b/Documentation/networking/timestamping.txt index 0e58b4539176..e8c8f4f06c67 100644 --- a/Documentation/networking/timestamping.txt +++ b/Documentation/networking/timestamping.txt | |||
| @@ -41,11 +41,12 @@ SOF_TIMESTAMPING_SOFTWARE: return system time stamp generated in | |||
| 41 | SOF_TIMESTAMPING_TX/RX determine how time stamps are generated. | 41 | SOF_TIMESTAMPING_TX/RX determine how time stamps are generated. |
| 42 | SOF_TIMESTAMPING_RAW/SYS determine how they are reported in the | 42 | SOF_TIMESTAMPING_RAW/SYS determine how they are reported in the |
| 43 | following control message: | 43 | following control message: |
| 44 | struct scm_timestamping { | 44 | |
| 45 | struct timespec systime; | 45 | struct scm_timestamping { |
| 46 | struct timespec hwtimetrans; | 46 | struct timespec systime; |
| 47 | struct timespec hwtimeraw; | 47 | struct timespec hwtimetrans; |
| 48 | }; | 48 | struct timespec hwtimeraw; |
| 49 | }; | ||
| 49 | 50 | ||
| 50 | recvmsg() can be used to get this control message for regular incoming | 51 | recvmsg() can be used to get this control message for regular incoming |
| 51 | packets. For send time stamps the outgoing packet is looped back to | 52 | packets. For send time stamps the outgoing packet is looped back to |
| @@ -87,12 +88,13 @@ by the network device and will be empty without that support. | |||
| 87 | SIOCSHWTSTAMP: | 88 | SIOCSHWTSTAMP: |
| 88 | 89 | ||
| 89 | Hardware time stamping must also be initialized for each device driver | 90 | Hardware time stamping must also be initialized for each device driver |
| 90 | that is expected to do hardware time stamping. The parameter is: | 91 | that is expected to do hardware time stamping. The parameter is defined in |
| 92 | /include/linux/net_tstamp.h as: | ||
| 91 | 93 | ||
| 92 | struct hwtstamp_config { | 94 | struct hwtstamp_config { |
| 93 | int flags; /* no flags defined right now, must be zero */ | 95 | int flags; /* no flags defined right now, must be zero */ |
| 94 | int tx_type; /* HWTSTAMP_TX_* */ | 96 | int tx_type; /* HWTSTAMP_TX_* */ |
| 95 | int rx_filter; /* HWTSTAMP_FILTER_* */ | 97 | int rx_filter; /* HWTSTAMP_FILTER_* */ |
| 96 | }; | 98 | }; |
| 97 | 99 | ||
| 98 | Desired behavior is passed into the kernel and to a specific device by | 100 | Desired behavior is passed into the kernel and to a specific device by |
| @@ -139,42 +141,56 @@ enum { | |||
| 139 | /* time stamp any incoming packet */ | 141 | /* time stamp any incoming packet */ |
| 140 | HWTSTAMP_FILTER_ALL, | 142 | HWTSTAMP_FILTER_ALL, |
| 141 | 143 | ||
| 142 | /* return value: time stamp all packets requested plus some others */ | 144 | /* return value: time stamp all packets requested plus some others */ |
| 143 | HWTSTAMP_FILTER_SOME, | 145 | HWTSTAMP_FILTER_SOME, |
| 144 | 146 | ||
| 145 | /* PTP v1, UDP, any kind of event packet */ | 147 | /* PTP v1, UDP, any kind of event packet */ |
| 146 | HWTSTAMP_FILTER_PTP_V1_L4_EVENT, | 148 | HWTSTAMP_FILTER_PTP_V1_L4_EVENT, |
| 147 | 149 | ||
| 148 | ... | 150 | /* for the complete list of values, please check |
| 151 | * the include file /include/linux/net_tstamp.h | ||
| 152 | */ | ||
| 149 | }; | 153 | }; |
| 150 | 154 | ||
| 151 | 155 | ||
| 152 | DEVICE IMPLEMENTATION | 156 | DEVICE IMPLEMENTATION |
| 153 | 157 | ||
| 154 | A driver which supports hardware time stamping must support the | 158 | A driver which supports hardware time stamping must support the |
| 155 | SIOCSHWTSTAMP ioctl. Time stamps for received packets must be stored | 159 | SIOCSHWTSTAMP ioctl and update the supplied struct hwtstamp_config with |
| 156 | in the skb with skb_hwtstamp_set(). | 160 | the actual values as described in the section on SIOCSHWTSTAMP. |
| 161 | |||
| 162 | Time stamps for received packets must be stored in the skb. To get a pointer | ||
| 163 | to the shared time stamp structure of the skb call skb_hwtstamps(). Then | ||
| 164 | set the time stamps in the structure: | ||
| 165 | |||
| 166 | struct skb_shared_hwtstamps { | ||
| 167 | /* hardware time stamp transformed into duration | ||
| 168 | * since arbitrary point in time | ||
| 169 | */ | ||
| 170 | ktime_t hwtstamp; | ||
| 171 | ktime_t syststamp; /* hwtstamp transformed to system time base */ | ||
| 172 | }; | ||
| 157 | 173 | ||
| 158 | Time stamps for outgoing packets are to be generated as follows: | 174 | Time stamps for outgoing packets are to be generated as follows: |
| 159 | - In hard_start_xmit(), check if skb_hwtstamp_check_tx_hardware() | 175 | - In hard_start_xmit(), check if skb_tx(skb)->hardware is set no-zero. |
| 160 | returns non-zero. If yes, then the driver is expected | 176 | If yes, then the driver is expected to do hardware time stamping. |
| 161 | to do hardware time stamping. | ||
| 162 | - If this is possible for the skb and requested, then declare | 177 | - If this is possible for the skb and requested, then declare |
| 163 | that the driver is doing the time stamping by calling | 178 | that the driver is doing the time stamping by setting the field |
| 164 | skb_hwtstamp_tx_in_progress(). A driver not supporting | 179 | skb_tx(skb)->in_progress non-zero. You might want to keep a pointer |
| 165 | hardware time stamping doesn't do that. A driver must never | 180 | to the associated skb for the next step and not free the skb. A driver |
| 166 | touch sk_buff::tstamp! It is used to store how time stamping | 181 | not supporting hardware time stamping doesn't do that. A driver must |
| 167 | for an outgoing packets is to be done. | 182 | never touch sk_buff::tstamp! It is used to store software generated |
| 183 | time stamps by the network subsystem. | ||
| 168 | - As soon as the driver has sent the packet and/or obtained a | 184 | - As soon as the driver has sent the packet and/or obtained a |
| 169 | hardware time stamp for it, it passes the time stamp back by | 185 | hardware time stamp for it, it passes the time stamp back by |
| 170 | calling skb_hwtstamp_tx() with the original skb, the raw | 186 | calling skb_hwtstamp_tx() with the original skb, the raw |
| 171 | hardware time stamp and a handle to the device (necessary | 187 | hardware time stamp. skb_hwtstamp_tx() clones the original skb and |
| 172 | to convert the hardware time stamp to system time). If obtaining | 188 | adds the timestamps, therefore the original skb has to be freed now. |
| 173 | the hardware time stamp somehow fails, then the driver should | 189 | If obtaining the hardware time stamp somehow fails, then the driver |
| 174 | not fall back to software time stamping. The rationale is that | 190 | should not fall back to software time stamping. The rationale is that |
| 175 | this would occur at a later time in the processing pipeline | 191 | this would occur at a later time in the processing pipeline than other |
| 176 | than other software time stamping and therefore could lead | 192 | software time stamping and therefore could lead to unexpected deltas |
| 177 | to unexpected deltas between time stamps. | 193 | between time stamps. |
| 178 | - If the driver did not call skb_hwtstamp_tx_in_progress(), then | 194 | - If the driver did not call set skb_tx(skb)->in_progress, then |
| 179 | dev_hard_start_xmit() checks whether software time stamping | 195 | dev_hard_start_xmit() checks whether software time stamping |
| 180 | is wanted as fallback and potentially generates the time stamp. | 196 | is wanted as fallback and potentially generates the time stamp. |
diff --git a/MAINTAINERS b/MAINTAINERS index 5b422908d0f3..a0e3c3a47a51 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
| @@ -485,8 +485,8 @@ S: Maintained | |||
| 485 | F: drivers/input/mouse/bcm5974.c | 485 | F: drivers/input/mouse/bcm5974.c |
| 486 | 486 | ||
| 487 | APPLE SMC DRIVER | 487 | APPLE SMC DRIVER |
| 488 | M: Nicolas Boichat <nicolas@boichat.ch> | 488 | M: Henrik Rydberg <rydberg@euromail.se> |
| 489 | L: mactel-linux-devel@lists.sourceforge.net | 489 | L: lm-sensors@lm-sensors.org |
| 490 | S: Maintained | 490 | S: Maintained |
| 491 | F: drivers/hwmon/applesmc.c | 491 | F: drivers/hwmon/applesmc.c |
| 492 | 492 | ||
diff --git a/arch/m68k/include/asm/atomic_mm.h b/arch/m68k/include/asm/atomic_mm.h index 88b7af20a996..d9d2ed647435 100644 --- a/arch/m68k/include/asm/atomic_mm.h +++ b/arch/m68k/include/asm/atomic_mm.h | |||
| @@ -148,14 +148,18 @@ static inline int atomic_xchg(atomic_t *v, int new) | |||
| 148 | static inline int atomic_sub_and_test(int i, atomic_t *v) | 148 | static inline int atomic_sub_and_test(int i, atomic_t *v) |
| 149 | { | 149 | { |
| 150 | char c; | 150 | char c; |
| 151 | __asm__ __volatile__("subl %2,%1; seq %0" : "=d" (c), "+m" (*v): "g" (i)); | 151 | __asm__ __volatile__("subl %2,%1; seq %0" |
| 152 | : "=d" (c), "+m" (*v) | ||
| 153 | : "id" (i)); | ||
| 152 | return c != 0; | 154 | return c != 0; |
| 153 | } | 155 | } |
| 154 | 156 | ||
| 155 | static inline int atomic_add_negative(int i, atomic_t *v) | 157 | static inline int atomic_add_negative(int i, atomic_t *v) |
| 156 | { | 158 | { |
| 157 | char c; | 159 | char c; |
| 158 | __asm__ __volatile__("addl %2,%1; smi %0" : "=d" (c), "+m" (*v): "g" (i)); | 160 | __asm__ __volatile__("addl %2,%1; smi %0" |
| 161 | : "=d" (c), "+m" (*v) | ||
| 162 | : "id" (i)); | ||
| 159 | return c != 0; | 163 | return c != 0; |
| 160 | } | 164 | } |
| 161 | 165 | ||
diff --git a/arch/m68k/include/asm/sigcontext.h b/arch/m68k/include/asm/sigcontext.h index 1320eaa4cc2a..a29dd74a17cb 100644 --- a/arch/m68k/include/asm/sigcontext.h +++ b/arch/m68k/include/asm/sigcontext.h | |||
| @@ -17,13 +17,11 @@ struct sigcontext { | |||
| 17 | #ifndef __uClinux__ | 17 | #ifndef __uClinux__ |
| 18 | # ifdef __mcoldfire__ | 18 | # ifdef __mcoldfire__ |
| 19 | unsigned long sc_fpregs[2][2]; /* room for two fp registers */ | 19 | unsigned long sc_fpregs[2][2]; /* room for two fp registers */ |
| 20 | unsigned long sc_fpcntl[3]; | ||
| 21 | unsigned char sc_fpstate[16+6*8]; | ||
| 22 | # else | 20 | # else |
| 23 | unsigned long sc_fpregs[2*3]; /* room for two fp registers */ | 21 | unsigned long sc_fpregs[2*3]; /* room for two fp registers */ |
| 22 | # endif | ||
| 24 | unsigned long sc_fpcntl[3]; | 23 | unsigned long sc_fpcntl[3]; |
| 25 | unsigned char sc_fpstate[216]; | 24 | unsigned char sc_fpstate[216]; |
| 26 | # endif | ||
| 27 | #endif | 25 | #endif |
| 28 | }; | 26 | }; |
| 29 | 27 | ||
diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig index 6db513674050..9908d477ccd9 100644 --- a/arch/sparc/Kconfig +++ b/arch/sparc/Kconfig | |||
| @@ -37,6 +37,9 @@ config SPARC64 | |||
| 37 | def_bool 64BIT | 37 | def_bool 64BIT |
| 38 | select ARCH_SUPPORTS_MSI | 38 | select ARCH_SUPPORTS_MSI |
| 39 | select HAVE_FUNCTION_TRACER | 39 | select HAVE_FUNCTION_TRACER |
| 40 | select HAVE_FUNCTION_GRAPH_TRACER | ||
| 41 | select HAVE_FUNCTION_GRAPH_FP_TEST | ||
| 42 | select HAVE_FUNCTION_TRACE_MCOUNT_TEST | ||
| 40 | select HAVE_KRETPROBES | 43 | select HAVE_KRETPROBES |
| 41 | select HAVE_KPROBES | 44 | select HAVE_KPROBES |
| 42 | select HAVE_LMB | 45 | select HAVE_LMB |
diff --git a/arch/sparc/Kconfig.debug b/arch/sparc/Kconfig.debug index 9d3c889718ac..1b4a831565f9 100644 --- a/arch/sparc/Kconfig.debug +++ b/arch/sparc/Kconfig.debug | |||
| @@ -19,13 +19,10 @@ config DEBUG_DCFLUSH | |||
| 19 | bool "D-cache flush debugging" | 19 | bool "D-cache flush debugging" |
| 20 | depends on SPARC64 && DEBUG_KERNEL | 20 | depends on SPARC64 && DEBUG_KERNEL |
| 21 | 21 | ||
| 22 | config STACK_DEBUG | ||
| 23 | bool "Stack Overflow Detection Support" | ||
| 24 | |||
| 25 | config MCOUNT | 22 | config MCOUNT |
| 26 | bool | 23 | bool |
| 27 | depends on SPARC64 | 24 | depends on SPARC64 |
| 28 | depends on STACK_DEBUG || FUNCTION_TRACER | 25 | depends on FUNCTION_TRACER |
| 29 | default y | 26 | default y |
| 30 | 27 | ||
| 31 | config FRAME_POINTER | 28 | config FRAME_POINTER |
diff --git a/arch/sparc/include/asm/cpudata_64.h b/arch/sparc/include/asm/cpudata_64.h index 926397d345ff..050ef35b9dcf 100644 --- a/arch/sparc/include/asm/cpudata_64.h +++ b/arch/sparc/include/asm/cpudata_64.h | |||
| @@ -17,7 +17,7 @@ typedef struct { | |||
| 17 | unsigned int __nmi_count; | 17 | unsigned int __nmi_count; |
| 18 | unsigned long clock_tick; /* %tick's per second */ | 18 | unsigned long clock_tick; /* %tick's per second */ |
| 19 | unsigned long __pad; | 19 | unsigned long __pad; |
| 20 | unsigned int __pad1; | 20 | unsigned int irq0_irqs; |
| 21 | unsigned int __pad2; | 21 | unsigned int __pad2; |
| 22 | 22 | ||
| 23 | /* Dcache line 2, rarely used */ | 23 | /* Dcache line 2, rarely used */ |
diff --git a/arch/sparc/include/asm/irqflags_64.h b/arch/sparc/include/asm/irqflags_64.h index 8b49bf920df3..bfa1ea45b4cd 100644 --- a/arch/sparc/include/asm/irqflags_64.h +++ b/arch/sparc/include/asm/irqflags_64.h | |||
| @@ -76,9 +76,26 @@ static inline int raw_irqs_disabled(void) | |||
| 76 | */ | 76 | */ |
| 77 | static inline unsigned long __raw_local_irq_save(void) | 77 | static inline unsigned long __raw_local_irq_save(void) |
| 78 | { | 78 | { |
| 79 | unsigned long flags = __raw_local_save_flags(); | 79 | unsigned long flags, tmp; |
| 80 | 80 | ||
| 81 | raw_local_irq_disable(); | 81 | /* Disable interrupts to PIL_NORMAL_MAX unless we already |
| 82 | * are using PIL_NMI, in which case PIL_NMI is retained. | ||
| 83 | * | ||
| 84 | * The only values we ever program into the %pil are 0, | ||
| 85 | * PIL_NORMAL_MAX and PIL_NMI. | ||
| 86 | * | ||
| 87 | * Since PIL_NMI is the largest %pil value and all bits are | ||
| 88 | * set in it (0xf), it doesn't matter what PIL_NORMAL_MAX | ||
| 89 | * actually is. | ||
| 90 | */ | ||
| 91 | __asm__ __volatile__( | ||
| 92 | "rdpr %%pil, %0\n\t" | ||
| 93 | "or %0, %2, %1\n\t" | ||
| 94 | "wrpr %1, 0x0, %%pil" | ||
| 95 | : "=r" (flags), "=r" (tmp) | ||
| 96 | : "i" (PIL_NORMAL_MAX) | ||
| 97 | : "memory" | ||
| 98 | ); | ||
| 82 | 99 | ||
| 83 | return flags; | 100 | return flags; |
| 84 | } | 101 | } |
diff --git a/arch/sparc/kernel/Makefile b/arch/sparc/kernel/Makefile index c6316142db4e..0c2dc1f24a9a 100644 --- a/arch/sparc/kernel/Makefile +++ b/arch/sparc/kernel/Makefile | |||
| @@ -13,6 +13,14 @@ extra-y += init_task.o | |||
| 13 | CPPFLAGS_vmlinux.lds := -Usparc -m$(BITS) | 13 | CPPFLAGS_vmlinux.lds := -Usparc -m$(BITS) |
| 14 | extra-y += vmlinux.lds | 14 | extra-y += vmlinux.lds |
| 15 | 15 | ||
| 16 | ifdef CONFIG_FUNCTION_TRACER | ||
| 17 | # Do not profile debug and lowlevel utilities | ||
| 18 | CFLAGS_REMOVE_ftrace.o := -pg | ||
| 19 | CFLAGS_REMOVE_time_$(BITS).o := -pg | ||
| 20 | CFLAGS_REMOVE_perf_event.o := -pg | ||
| 21 | CFLAGS_REMOVE_pcr.o := -pg | ||
| 22 | endif | ||
| 23 | |||
| 16 | obj-$(CONFIG_SPARC32) += entry.o wof.o wuf.o | 24 | obj-$(CONFIG_SPARC32) += entry.o wof.o wuf.o |
| 17 | obj-$(CONFIG_SPARC32) += etrap_32.o | 25 | obj-$(CONFIG_SPARC32) += etrap_32.o |
| 18 | obj-$(CONFIG_SPARC32) += rtrap_32.o | 26 | obj-$(CONFIG_SPARC32) += rtrap_32.o |
| @@ -85,7 +93,7 @@ obj-$(CONFIG_KGDB) += kgdb_$(BITS).o | |||
| 85 | 93 | ||
| 86 | 94 | ||
| 87 | obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o | 95 | obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o |
| 88 | CFLAGS_REMOVE_ftrace.o := -pg | 96 | obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += ftrace.o |
| 89 | 97 | ||
| 90 | obj-$(CONFIG_EARLYFB) += btext.o | 98 | obj-$(CONFIG_EARLYFB) += btext.o |
| 91 | obj-$(CONFIG_STACKTRACE) += stacktrace.o | 99 | obj-$(CONFIG_STACKTRACE) += stacktrace.o |
diff --git a/arch/sparc/kernel/ftrace.c b/arch/sparc/kernel/ftrace.c index 9103a56b39e8..03ab022e51c5 100644 --- a/arch/sparc/kernel/ftrace.c +++ b/arch/sparc/kernel/ftrace.c | |||
| @@ -13,7 +13,7 @@ static const u32 ftrace_nop = 0x01000000; | |||
| 13 | 13 | ||
| 14 | static u32 ftrace_call_replace(unsigned long ip, unsigned long addr) | 14 | static u32 ftrace_call_replace(unsigned long ip, unsigned long addr) |
| 15 | { | 15 | { |
| 16 | static u32 call; | 16 | u32 call; |
| 17 | s32 off; | 17 | s32 off; |
| 18 | 18 | ||
| 19 | off = ((s32)addr - (s32)ip); | 19 | off = ((s32)addr - (s32)ip); |
| @@ -91,3 +91,61 @@ int __init ftrace_dyn_arch_init(void *data) | |||
| 91 | return 0; | 91 | return 0; |
| 92 | } | 92 | } |
| 93 | #endif | 93 | #endif |
| 94 | |||
| 95 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER | ||
| 96 | |||
| 97 | #ifdef CONFIG_DYNAMIC_FTRACE | ||
| 98 | extern void ftrace_graph_call(void); | ||
| 99 | |||
| 100 | int ftrace_enable_ftrace_graph_caller(void) | ||
| 101 | { | ||
| 102 | unsigned long ip = (unsigned long)(&ftrace_graph_call); | ||
| 103 | u32 old, new; | ||
| 104 | |||
| 105 | old = *(u32 *) &ftrace_graph_call; | ||
| 106 | new = ftrace_call_replace(ip, (unsigned long) &ftrace_graph_caller); | ||
| 107 | return ftrace_modify_code(ip, old, new); | ||
| 108 | } | ||
| 109 | |||
| 110 | int ftrace_disable_ftrace_graph_caller(void) | ||
| 111 | { | ||
| 112 | unsigned long ip = (unsigned long)(&ftrace_graph_call); | ||
| 113 | u32 old, new; | ||
| 114 | |||
| 115 | old = *(u32 *) &ftrace_graph_call; | ||
| 116 | new = ftrace_call_replace(ip, (unsigned long) &ftrace_stub); | ||
| 117 | |||
| 118 | return ftrace_modify_code(ip, old, new); | ||
| 119 | } | ||
| 120 | |||
| 121 | #endif /* !CONFIG_DYNAMIC_FTRACE */ | ||
| 122 | |||
| 123 | /* | ||
| 124 | * Hook the return address and push it in the stack of return addrs | ||
| 125 | * in current thread info. | ||
| 126 | */ | ||
| 127 | unsigned long prepare_ftrace_return(unsigned long parent, | ||
| 128 | unsigned long self_addr, | ||
| 129 | unsigned long frame_pointer) | ||
| 130 | { | ||
| 131 | unsigned long return_hooker = (unsigned long) &return_to_handler; | ||
| 132 | struct ftrace_graph_ent trace; | ||
| 133 | |||
| 134 | if (unlikely(atomic_read(¤t->tracing_graph_pause))) | ||
| 135 | return parent + 8UL; | ||
| 136 | |||
| 137 | if (ftrace_push_return_trace(parent, self_addr, &trace.depth, | ||
| 138 | frame_pointer) == -EBUSY) | ||
| 139 | return parent + 8UL; | ||
| 140 | |||
| 141 | trace.func = self_addr; | ||
| 142 | |||
| 143 | /* Only trace if the calling function expects to */ | ||
| 144 | if (!ftrace_graph_entry(&trace)) { | ||
| 145 | current->curr_ret_stack--; | ||
| 146 | return parent + 8UL; | ||
| 147 | } | ||
| 148 | |||
| 149 | return return_hooker; | ||
| 150 | } | ||
| 151 | #endif /* CONFIG_FUNCTION_GRAPH_TRACER */ | ||
diff --git a/arch/sparc/kernel/irq_64.c b/arch/sparc/kernel/irq_64.c index e1cbdb94d97b..454ce3a25273 100644 --- a/arch/sparc/kernel/irq_64.c +++ b/arch/sparc/kernel/irq_64.c | |||
| @@ -20,6 +20,7 @@ | |||
| 20 | #include <linux/delay.h> | 20 | #include <linux/delay.h> |
| 21 | #include <linux/proc_fs.h> | 21 | #include <linux/proc_fs.h> |
| 22 | #include <linux/seq_file.h> | 22 | #include <linux/seq_file.h> |
| 23 | #include <linux/ftrace.h> | ||
| 23 | #include <linux/irq.h> | 24 | #include <linux/irq.h> |
| 24 | 25 | ||
| 25 | #include <asm/ptrace.h> | 26 | #include <asm/ptrace.h> |
| @@ -647,6 +648,14 @@ unsigned int sun4v_build_virq(u32 devhandle, unsigned int devino) | |||
| 647 | bucket = kzalloc(sizeof(struct ino_bucket), GFP_ATOMIC); | 648 | bucket = kzalloc(sizeof(struct ino_bucket), GFP_ATOMIC); |
| 648 | if (unlikely(!bucket)) | 649 | if (unlikely(!bucket)) |
| 649 | return 0; | 650 | return 0; |
| 651 | |||
| 652 | /* The only reference we store to the IRQ bucket is | ||
| 653 | * by physical address which kmemleak can't see, tell | ||
| 654 | * it that this object explicitly is not a leak and | ||
| 655 | * should be scanned. | ||
| 656 | */ | ||
| 657 | kmemleak_not_leak(bucket); | ||
| 658 | |||
| 650 | __flush_dcache_range((unsigned long) bucket, | 659 | __flush_dcache_range((unsigned long) bucket, |
| 651 | ((unsigned long) bucket + | 660 | ((unsigned long) bucket + |
| 652 | sizeof(struct ino_bucket))); | 661 | sizeof(struct ino_bucket))); |
| @@ -721,7 +730,7 @@ static __attribute__((always_inline)) void restore_hardirq_stack(void *orig_sp) | |||
| 721 | __asm__ __volatile__("mov %0, %%sp" : : "r" (orig_sp)); | 730 | __asm__ __volatile__("mov %0, %%sp" : : "r" (orig_sp)); |
| 722 | } | 731 | } |
| 723 | 732 | ||
| 724 | void handler_irq(int irq, struct pt_regs *regs) | 733 | void __irq_entry handler_irq(int irq, struct pt_regs *regs) |
| 725 | { | 734 | { |
| 726 | unsigned long pstate, bucket_pa; | 735 | unsigned long pstate, bucket_pa; |
| 727 | struct pt_regs *old_regs; | 736 | struct pt_regs *old_regs; |
diff --git a/arch/sparc/kernel/kgdb_64.c b/arch/sparc/kernel/kgdb_64.c index f5a0fd490b59..0a2bd0f99fc1 100644 --- a/arch/sparc/kernel/kgdb_64.c +++ b/arch/sparc/kernel/kgdb_64.c | |||
| @@ -5,6 +5,7 @@ | |||
| 5 | 5 | ||
| 6 | #include <linux/kgdb.h> | 6 | #include <linux/kgdb.h> |
| 7 | #include <linux/kdebug.h> | 7 | #include <linux/kdebug.h> |
| 8 | #include <linux/ftrace.h> | ||
| 8 | 9 | ||
| 9 | #include <asm/kdebug.h> | 10 | #include <asm/kdebug.h> |
| 10 | #include <asm/ptrace.h> | 11 | #include <asm/ptrace.h> |
| @@ -108,7 +109,7 @@ void gdb_regs_to_pt_regs(unsigned long *gdb_regs, struct pt_regs *regs) | |||
| 108 | } | 109 | } |
| 109 | 110 | ||
| 110 | #ifdef CONFIG_SMP | 111 | #ifdef CONFIG_SMP |
| 111 | void smp_kgdb_capture_client(int irq, struct pt_regs *regs) | 112 | void __irq_entry smp_kgdb_capture_client(int irq, struct pt_regs *regs) |
| 112 | { | 113 | { |
| 113 | unsigned long flags; | 114 | unsigned long flags; |
| 114 | 115 | ||
diff --git a/arch/sparc/kernel/nmi.c b/arch/sparc/kernel/nmi.c index b287b62c7ea3..75a3d1a25356 100644 --- a/arch/sparc/kernel/nmi.c +++ b/arch/sparc/kernel/nmi.c | |||
| @@ -92,7 +92,6 @@ static void die_nmi(const char *str, struct pt_regs *regs, int do_panic) | |||
| 92 | notrace __kprobes void perfctr_irq(int irq, struct pt_regs *regs) | 92 | notrace __kprobes void perfctr_irq(int irq, struct pt_regs *regs) |
| 93 | { | 93 | { |
| 94 | unsigned int sum, touched = 0; | 94 | unsigned int sum, touched = 0; |
| 95 | int cpu = smp_processor_id(); | ||
| 96 | 95 | ||
| 97 | clear_softint(1 << irq); | 96 | clear_softint(1 << irq); |
| 98 | 97 | ||
| @@ -106,7 +105,7 @@ notrace __kprobes void perfctr_irq(int irq, struct pt_regs *regs) | |||
| 106 | else | 105 | else |
| 107 | pcr_ops->write(PCR_PIC_PRIV); | 106 | pcr_ops->write(PCR_PIC_PRIV); |
| 108 | 107 | ||
| 109 | sum = kstat_irqs_cpu(0, cpu); | 108 | sum = local_cpu_data().irq0_irqs; |
| 110 | if (__get_cpu_var(nmi_touch)) { | 109 | if (__get_cpu_var(nmi_touch)) { |
| 111 | __get_cpu_var(nmi_touch) = 0; | 110 | __get_cpu_var(nmi_touch) = 0; |
| 112 | touched = 1; | 111 | touched = 1; |
diff --git a/arch/sparc/kernel/pci_common.c b/arch/sparc/kernel/pci_common.c index b775658a927d..8a000583b5cf 100644 --- a/arch/sparc/kernel/pci_common.c +++ b/arch/sparc/kernel/pci_common.c | |||
| @@ -371,14 +371,19 @@ static void pci_register_iommu_region(struct pci_pbm_info *pbm) | |||
| 371 | struct resource *rp = kzalloc(sizeof(*rp), GFP_KERNEL); | 371 | struct resource *rp = kzalloc(sizeof(*rp), GFP_KERNEL); |
| 372 | 372 | ||
| 373 | if (!rp) { | 373 | if (!rp) { |
| 374 | prom_printf("Cannot allocate IOMMU resource.\n"); | 374 | pr_info("%s: Cannot allocate IOMMU resource.\n", |
| 375 | prom_halt(); | 375 | pbm->name); |
| 376 | return; | ||
| 376 | } | 377 | } |
| 377 | rp->name = "IOMMU"; | 378 | rp->name = "IOMMU"; |
| 378 | rp->start = pbm->mem_space.start + (unsigned long) vdma[0]; | 379 | rp->start = pbm->mem_space.start + (unsigned long) vdma[0]; |
| 379 | rp->end = rp->start + (unsigned long) vdma[1] - 1UL; | 380 | rp->end = rp->start + (unsigned long) vdma[1] - 1UL; |
| 380 | rp->flags = IORESOURCE_BUSY; | 381 | rp->flags = IORESOURCE_BUSY; |
| 381 | request_resource(&pbm->mem_space, rp); | 382 | if (request_resource(&pbm->mem_space, rp)) { |
| 383 | pr_info("%s: Unable to request IOMMU resource.\n", | ||
| 384 | pbm->name); | ||
| 385 | kfree(rp); | ||
| 386 | } | ||
| 382 | } | 387 | } |
| 383 | } | 388 | } |
| 384 | 389 | ||
diff --git a/arch/sparc/kernel/pcr.c b/arch/sparc/kernel/pcr.c index 2d94e7a03af5..c4a6a50b4849 100644 --- a/arch/sparc/kernel/pcr.c +++ b/arch/sparc/kernel/pcr.c | |||
| @@ -8,6 +8,7 @@ | |||
| 8 | #include <linux/irq.h> | 8 | #include <linux/irq.h> |
| 9 | 9 | ||
| 10 | #include <linux/perf_event.h> | 10 | #include <linux/perf_event.h> |
| 11 | #include <linux/ftrace.h> | ||
| 11 | 12 | ||
| 12 | #include <asm/pil.h> | 13 | #include <asm/pil.h> |
| 13 | #include <asm/pcr.h> | 14 | #include <asm/pcr.h> |
| @@ -34,7 +35,7 @@ unsigned int picl_shift; | |||
| 34 | * Therefore in such situations we defer the work by signalling | 35 | * Therefore in such situations we defer the work by signalling |
| 35 | * a lower level cpu IRQ. | 36 | * a lower level cpu IRQ. |
| 36 | */ | 37 | */ |
| 37 | void deferred_pcr_work_irq(int irq, struct pt_regs *regs) | 38 | void __irq_entry deferred_pcr_work_irq(int irq, struct pt_regs *regs) |
| 38 | { | 39 | { |
| 39 | struct pt_regs *old_regs; | 40 | struct pt_regs *old_regs; |
| 40 | 41 | ||
diff --git a/arch/sparc/kernel/smp_64.c b/arch/sparc/kernel/smp_64.c index 4c5334528109..b6a2b8f47040 100644 --- a/arch/sparc/kernel/smp_64.c +++ b/arch/sparc/kernel/smp_64.c | |||
| @@ -22,6 +22,7 @@ | |||
| 22 | #include <linux/profile.h> | 22 | #include <linux/profile.h> |
| 23 | #include <linux/bootmem.h> | 23 | #include <linux/bootmem.h> |
| 24 | #include <linux/vmalloc.h> | 24 | #include <linux/vmalloc.h> |
| 25 | #include <linux/ftrace.h> | ||
| 25 | #include <linux/cpu.h> | 26 | #include <linux/cpu.h> |
| 26 | #include <linux/slab.h> | 27 | #include <linux/slab.h> |
| 27 | 28 | ||
| @@ -823,13 +824,13 @@ void arch_send_call_function_single_ipi(int cpu) | |||
| 823 | &cpumask_of_cpu(cpu)); | 824 | &cpumask_of_cpu(cpu)); |
| 824 | } | 825 | } |
| 825 | 826 | ||
| 826 | void smp_call_function_client(int irq, struct pt_regs *regs) | 827 | void __irq_entry smp_call_function_client(int irq, struct pt_regs *regs) |
| 827 | { | 828 | { |
| 828 | clear_softint(1 << irq); | 829 | clear_softint(1 << irq); |
| 829 | generic_smp_call_function_interrupt(); | 830 | generic_smp_call_function_interrupt(); |
| 830 | } | 831 | } |
| 831 | 832 | ||
| 832 | void smp_call_function_single_client(int irq, struct pt_regs *regs) | 833 | void __irq_entry smp_call_function_single_client(int irq, struct pt_regs *regs) |
| 833 | { | 834 | { |
| 834 | clear_softint(1 << irq); | 835 | clear_softint(1 << irq); |
| 835 | generic_smp_call_function_single_interrupt(); | 836 | generic_smp_call_function_single_interrupt(); |
| @@ -965,7 +966,7 @@ void flush_dcache_page_all(struct mm_struct *mm, struct page *page) | |||
| 965 | put_cpu(); | 966 | put_cpu(); |
| 966 | } | 967 | } |
| 967 | 968 | ||
| 968 | void smp_new_mmu_context_version_client(int irq, struct pt_regs *regs) | 969 | void __irq_entry smp_new_mmu_context_version_client(int irq, struct pt_regs *regs) |
| 969 | { | 970 | { |
| 970 | struct mm_struct *mm; | 971 | struct mm_struct *mm; |
| 971 | unsigned long flags; | 972 | unsigned long flags; |
| @@ -1149,7 +1150,7 @@ void smp_release(void) | |||
| 1149 | */ | 1150 | */ |
| 1150 | extern void prom_world(int); | 1151 | extern void prom_world(int); |
| 1151 | 1152 | ||
| 1152 | void smp_penguin_jailcell(int irq, struct pt_regs *regs) | 1153 | void __irq_entry smp_penguin_jailcell(int irq, struct pt_regs *regs) |
| 1153 | { | 1154 | { |
| 1154 | clear_softint(1 << irq); | 1155 | clear_softint(1 << irq); |
| 1155 | 1156 | ||
| @@ -1365,7 +1366,7 @@ void smp_send_reschedule(int cpu) | |||
| 1365 | &cpumask_of_cpu(cpu)); | 1366 | &cpumask_of_cpu(cpu)); |
| 1366 | } | 1367 | } |
| 1367 | 1368 | ||
| 1368 | void smp_receive_signal_client(int irq, struct pt_regs *regs) | 1369 | void __irq_entry smp_receive_signal_client(int irq, struct pt_regs *regs) |
| 1369 | { | 1370 | { |
| 1370 | clear_softint(1 << irq); | 1371 | clear_softint(1 << irq); |
| 1371 | } | 1372 | } |
diff --git a/arch/sparc/kernel/time_64.c b/arch/sparc/kernel/time_64.c index 67e165102885..c7bbe6cf7b85 100644 --- a/arch/sparc/kernel/time_64.c +++ b/arch/sparc/kernel/time_64.c | |||
| @@ -35,6 +35,7 @@ | |||
| 35 | #include <linux/clocksource.h> | 35 | #include <linux/clocksource.h> |
| 36 | #include <linux/of_device.h> | 36 | #include <linux/of_device.h> |
| 37 | #include <linux/platform_device.h> | 37 | #include <linux/platform_device.h> |
| 38 | #include <linux/ftrace.h> | ||
| 38 | 39 | ||
| 39 | #include <asm/oplib.h> | 40 | #include <asm/oplib.h> |
| 40 | #include <asm/timer.h> | 41 | #include <asm/timer.h> |
| @@ -717,7 +718,7 @@ static struct clock_event_device sparc64_clockevent = { | |||
| 717 | }; | 718 | }; |
| 718 | static DEFINE_PER_CPU(struct clock_event_device, sparc64_events); | 719 | static DEFINE_PER_CPU(struct clock_event_device, sparc64_events); |
| 719 | 720 | ||
| 720 | void timer_interrupt(int irq, struct pt_regs *regs) | 721 | void __irq_entry timer_interrupt(int irq, struct pt_regs *regs) |
| 721 | { | 722 | { |
| 722 | struct pt_regs *old_regs = set_irq_regs(regs); | 723 | struct pt_regs *old_regs = set_irq_regs(regs); |
| 723 | unsigned long tick_mask = tick_ops->softint_mask; | 724 | unsigned long tick_mask = tick_ops->softint_mask; |
| @@ -728,6 +729,7 @@ void timer_interrupt(int irq, struct pt_regs *regs) | |||
| 728 | 729 | ||
| 729 | irq_enter(); | 730 | irq_enter(); |
| 730 | 731 | ||
| 732 | local_cpu_data().irq0_irqs++; | ||
| 731 | kstat_incr_irqs_this_cpu(0, irq_to_desc(0)); | 733 | kstat_incr_irqs_this_cpu(0, irq_to_desc(0)); |
| 732 | 734 | ||
| 733 | if (unlikely(!evt->event_handler)) { | 735 | if (unlikely(!evt->event_handler)) { |
diff --git a/arch/sparc/kernel/traps_64.c b/arch/sparc/kernel/traps_64.c index 837dfc2390d6..9da57f032983 100644 --- a/arch/sparc/kernel/traps_64.c +++ b/arch/sparc/kernel/traps_64.c | |||
| @@ -2203,27 +2203,6 @@ void dump_stack(void) | |||
| 2203 | 2203 | ||
| 2204 | EXPORT_SYMBOL(dump_stack); | 2204 | EXPORT_SYMBOL(dump_stack); |
| 2205 | 2205 | ||
| 2206 | static inline int is_kernel_stack(struct task_struct *task, | ||
| 2207 | struct reg_window *rw) | ||
| 2208 | { | ||
| 2209 | unsigned long rw_addr = (unsigned long) rw; | ||
| 2210 | unsigned long thread_base, thread_end; | ||
| 2211 | |||
| 2212 | if (rw_addr < PAGE_OFFSET) { | ||
| 2213 | if (task != &init_task) | ||
| 2214 | return 0; | ||
| 2215 | } | ||
| 2216 | |||
| 2217 | thread_base = (unsigned long) task_stack_page(task); | ||
| 2218 | thread_end = thread_base + sizeof(union thread_union); | ||
| 2219 | if (rw_addr >= thread_base && | ||
| 2220 | rw_addr < thread_end && | ||
| 2221 | !(rw_addr & 0x7UL)) | ||
| 2222 | return 1; | ||
| 2223 | |||
| 2224 | return 0; | ||
| 2225 | } | ||
| 2226 | |||
| 2227 | static inline struct reg_window *kernel_stack_up(struct reg_window *rw) | 2206 | static inline struct reg_window *kernel_stack_up(struct reg_window *rw) |
| 2228 | { | 2207 | { |
| 2229 | unsigned long fp = rw->ins[6]; | 2208 | unsigned long fp = rw->ins[6]; |
| @@ -2252,6 +2231,7 @@ void die_if_kernel(char *str, struct pt_regs *regs) | |||
| 2252 | show_regs(regs); | 2231 | show_regs(regs); |
| 2253 | add_taint(TAINT_DIE); | 2232 | add_taint(TAINT_DIE); |
| 2254 | if (regs->tstate & TSTATE_PRIV) { | 2233 | if (regs->tstate & TSTATE_PRIV) { |
| 2234 | struct thread_info *tp = current_thread_info(); | ||
| 2255 | struct reg_window *rw = (struct reg_window *) | 2235 | struct reg_window *rw = (struct reg_window *) |
| 2256 | (regs->u_regs[UREG_FP] + STACK_BIAS); | 2236 | (regs->u_regs[UREG_FP] + STACK_BIAS); |
| 2257 | 2237 | ||
| @@ -2259,8 +2239,8 @@ void die_if_kernel(char *str, struct pt_regs *regs) | |||
| 2259 | * find some badly aligned kernel stack. | 2239 | * find some badly aligned kernel stack. |
| 2260 | */ | 2240 | */ |
| 2261 | while (rw && | 2241 | while (rw && |
| 2262 | count++ < 30&& | 2242 | count++ < 30 && |
| 2263 | is_kernel_stack(current, rw)) { | 2243 | kstack_valid(tp, (unsigned long) rw)) { |
| 2264 | printk("Caller[%016lx]: %pS\n", rw->ins[7], | 2244 | printk("Caller[%016lx]: %pS\n", rw->ins[7], |
| 2265 | (void *) rw->ins[7]); | 2245 | (void *) rw->ins[7]); |
| 2266 | 2246 | ||
diff --git a/arch/sparc/kernel/vmlinux.lds.S b/arch/sparc/kernel/vmlinux.lds.S index 4e5992593967..0c1e6783657f 100644 --- a/arch/sparc/kernel/vmlinux.lds.S +++ b/arch/sparc/kernel/vmlinux.lds.S | |||
| @@ -46,11 +46,16 @@ SECTIONS | |||
| 46 | SCHED_TEXT | 46 | SCHED_TEXT |
| 47 | LOCK_TEXT | 47 | LOCK_TEXT |
| 48 | KPROBES_TEXT | 48 | KPROBES_TEXT |
| 49 | IRQENTRY_TEXT | ||
| 49 | *(.gnu.warning) | 50 | *(.gnu.warning) |
| 50 | } = 0 | 51 | } = 0 |
| 51 | _etext = .; | 52 | _etext = .; |
| 52 | 53 | ||
| 53 | RO_DATA(PAGE_SIZE) | 54 | RO_DATA(PAGE_SIZE) |
| 55 | |||
| 56 | /* Start of data section */ | ||
| 57 | _sdata = .; | ||
| 58 | |||
| 54 | .data1 : { | 59 | .data1 : { |
| 55 | *(.data1) | 60 | *(.data1) |
| 56 | } | 61 | } |
diff --git a/arch/sparc/lib/mcount.S b/arch/sparc/lib/mcount.S index 24b8b12deed2..3753e3c6e176 100644 --- a/arch/sparc/lib/mcount.S +++ b/arch/sparc/lib/mcount.S | |||
| @@ -7,26 +7,11 @@ | |||
| 7 | 7 | ||
| 8 | #include <linux/linkage.h> | 8 | #include <linux/linkage.h> |
| 9 | 9 | ||
| 10 | #include <asm/ptrace.h> | ||
| 11 | #include <asm/thread_info.h> | ||
| 12 | |||
| 13 | /* | 10 | /* |
| 14 | * This is the main variant and is called by C code. GCC's -pg option | 11 | * This is the main variant and is called by C code. GCC's -pg option |
| 15 | * automatically instruments every C function with a call to this. | 12 | * automatically instruments every C function with a call to this. |
| 16 | */ | 13 | */ |
| 17 | 14 | ||
| 18 | #ifdef CONFIG_STACK_DEBUG | ||
| 19 | |||
| 20 | #define OVSTACKSIZE 4096 /* lets hope this is enough */ | ||
| 21 | |||
| 22 | .data | ||
| 23 | .align 8 | ||
| 24 | panicstring: | ||
| 25 | .asciz "Stack overflow\n" | ||
| 26 | .align 8 | ||
| 27 | ovstack: | ||
| 28 | .skip OVSTACKSIZE | ||
| 29 | #endif | ||
| 30 | .text | 15 | .text |
| 31 | .align 32 | 16 | .align 32 |
| 32 | .globl _mcount | 17 | .globl _mcount |
| @@ -35,84 +20,48 @@ ovstack: | |||
| 35 | .type mcount,#function | 20 | .type mcount,#function |
| 36 | _mcount: | 21 | _mcount: |
| 37 | mcount: | 22 | mcount: |
| 38 | #ifdef CONFIG_STACK_DEBUG | ||
| 39 | /* | ||
| 40 | * Check whether %sp is dangerously low. | ||
| 41 | */ | ||
| 42 | ldub [%g6 + TI_FPDEPTH], %g1 | ||
| 43 | srl %g1, 1, %g3 | ||
| 44 | add %g3, 1, %g3 | ||
| 45 | sllx %g3, 8, %g3 ! each fpregs frame is 256b | ||
| 46 | add %g3, 192, %g3 | ||
| 47 | add %g6, %g3, %g3 ! where does task_struct+frame end? | ||
| 48 | sub %g3, STACK_BIAS, %g3 | ||
| 49 | cmp %sp, %g3 | ||
| 50 | bg,pt %xcc, 1f | ||
| 51 | nop | ||
| 52 | lduh [%g6 + TI_CPU], %g1 | ||
| 53 | sethi %hi(hardirq_stack), %g3 | ||
| 54 | or %g3, %lo(hardirq_stack), %g3 | ||
| 55 | sllx %g1, 3, %g1 | ||
| 56 | ldx [%g3 + %g1], %g7 | ||
| 57 | sub %g7, STACK_BIAS, %g7 | ||
| 58 | cmp %sp, %g7 | ||
| 59 | bleu,pt %xcc, 2f | ||
| 60 | sethi %hi(THREAD_SIZE), %g3 | ||
| 61 | add %g7, %g3, %g7 | ||
| 62 | cmp %sp, %g7 | ||
| 63 | blu,pn %xcc, 1f | ||
| 64 | 2: sethi %hi(softirq_stack), %g3 | ||
| 65 | or %g3, %lo(softirq_stack), %g3 | ||
| 66 | ldx [%g3 + %g1], %g7 | ||
| 67 | sub %g7, STACK_BIAS, %g7 | ||
| 68 | cmp %sp, %g7 | ||
| 69 | bleu,pt %xcc, 3f | ||
| 70 | sethi %hi(THREAD_SIZE), %g3 | ||
| 71 | add %g7, %g3, %g7 | ||
| 72 | cmp %sp, %g7 | ||
| 73 | blu,pn %xcc, 1f | ||
| 74 | nop | ||
| 75 | /* If we are already on ovstack, don't hop onto it | ||
| 76 | * again, we are already trying to output the stack overflow | ||
| 77 | * message. | ||
| 78 | */ | ||
| 79 | 3: sethi %hi(ovstack), %g7 ! cant move to panic stack fast enough | ||
| 80 | or %g7, %lo(ovstack), %g7 | ||
| 81 | add %g7, OVSTACKSIZE, %g3 | ||
| 82 | sub %g3, STACK_BIAS + 192, %g3 | ||
| 83 | sub %g7, STACK_BIAS, %g7 | ||
| 84 | cmp %sp, %g7 | ||
| 85 | blu,pn %xcc, 2f | ||
| 86 | cmp %sp, %g3 | ||
| 87 | bleu,pn %xcc, 1f | ||
| 88 | nop | ||
| 89 | 2: mov %g3, %sp | ||
| 90 | sethi %hi(panicstring), %g3 | ||
| 91 | call prom_printf | ||
| 92 | or %g3, %lo(panicstring), %o0 | ||
| 93 | call prom_halt | ||
| 94 | nop | ||
| 95 | 1: | ||
| 96 | #endif | ||
| 97 | #ifdef CONFIG_FUNCTION_TRACER | 23 | #ifdef CONFIG_FUNCTION_TRACER |
| 98 | #ifdef CONFIG_DYNAMIC_FTRACE | 24 | #ifdef CONFIG_DYNAMIC_FTRACE |
| 99 | mov %o7, %o0 | 25 | /* Do nothing, the retl/nop below is all we need. */ |
| 100 | .globl mcount_call | ||
| 101 | mcount_call: | ||
| 102 | call ftrace_stub | ||
| 103 | mov %o0, %o7 | ||
| 104 | #else | 26 | #else |
| 105 | sethi %hi(ftrace_trace_function), %g1 | 27 | sethi %hi(function_trace_stop), %g1 |
| 28 | lduw [%g1 + %lo(function_trace_stop)], %g2 | ||
| 29 | brnz,pn %g2, 2f | ||
| 30 | sethi %hi(ftrace_trace_function), %g1 | ||
| 106 | sethi %hi(ftrace_stub), %g2 | 31 | sethi %hi(ftrace_stub), %g2 |
| 107 | ldx [%g1 + %lo(ftrace_trace_function)], %g1 | 32 | ldx [%g1 + %lo(ftrace_trace_function)], %g1 |
| 108 | or %g2, %lo(ftrace_stub), %g2 | 33 | or %g2, %lo(ftrace_stub), %g2 |
| 109 | cmp %g1, %g2 | 34 | cmp %g1, %g2 |
| 110 | be,pn %icc, 1f | 35 | be,pn %icc, 1f |
| 111 | mov %i7, %o1 | 36 | mov %i7, %g3 |
| 112 | jmpl %g1, %g0 | 37 | save %sp, -128, %sp |
| 113 | mov %o7, %o0 | 38 | mov %g3, %o1 |
| 39 | jmpl %g1, %o7 | ||
| 40 | mov %i7, %o0 | ||
| 41 | ret | ||
| 42 | restore | ||
| 114 | /* not reached */ | 43 | /* not reached */ |
| 115 | 1: | 44 | 1: |
| 45 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER | ||
| 46 | sethi %hi(ftrace_graph_return), %g1 | ||
| 47 | ldx [%g1 + %lo(ftrace_graph_return)], %g3 | ||
| 48 | cmp %g2, %g3 | ||
| 49 | bne,pn %xcc, 5f | ||
| 50 | sethi %hi(ftrace_graph_entry_stub), %g2 | ||
| 51 | sethi %hi(ftrace_graph_entry), %g1 | ||
| 52 | or %g2, %lo(ftrace_graph_entry_stub), %g2 | ||
| 53 | ldx [%g1 + %lo(ftrace_graph_entry)], %g1 | ||
| 54 | cmp %g1, %g2 | ||
| 55 | be,pt %xcc, 2f | ||
| 56 | nop | ||
| 57 | 5: mov %i7, %g2 | ||
| 58 | mov %fp, %g3 | ||
| 59 | save %sp, -128, %sp | ||
| 60 | mov %g2, %l0 | ||
| 61 | ba,pt %xcc, ftrace_graph_caller | ||
| 62 | mov %g3, %l1 | ||
| 63 | #endif | ||
| 64 | 2: | ||
| 116 | #endif | 65 | #endif |
| 117 | #endif | 66 | #endif |
| 118 | retl | 67 | retl |
| @@ -131,14 +80,50 @@ ftrace_stub: | |||
| 131 | .globl ftrace_caller | 80 | .globl ftrace_caller |
| 132 | .type ftrace_caller,#function | 81 | .type ftrace_caller,#function |
| 133 | ftrace_caller: | 82 | ftrace_caller: |
| 134 | mov %i7, %o1 | 83 | sethi %hi(function_trace_stop), %g1 |
| 135 | mov %o7, %o0 | 84 | mov %i7, %g2 |
| 85 | lduw [%g1 + %lo(function_trace_stop)], %g1 | ||
| 86 | brnz,pn %g1, ftrace_stub | ||
| 87 | mov %fp, %g3 | ||
| 88 | save %sp, -128, %sp | ||
| 89 | mov %g2, %o1 | ||
| 90 | mov %g2, %l0 | ||
| 91 | mov %g3, %l1 | ||
| 136 | .globl ftrace_call | 92 | .globl ftrace_call |
| 137 | ftrace_call: | 93 | ftrace_call: |
| 138 | call ftrace_stub | 94 | call ftrace_stub |
| 139 | mov %o0, %o7 | 95 | mov %i7, %o0 |
| 140 | retl | 96 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER |
| 97 | .globl ftrace_graph_call | ||
| 98 | ftrace_graph_call: | ||
| 99 | call ftrace_stub | ||
| 141 | nop | 100 | nop |
| 101 | #endif | ||
| 102 | ret | ||
| 103 | restore | ||
| 104 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER | ||
| 105 | .size ftrace_graph_call,.-ftrace_graph_call | ||
| 106 | #endif | ||
| 107 | .size ftrace_call,.-ftrace_call | ||
| 142 | .size ftrace_caller,.-ftrace_caller | 108 | .size ftrace_caller,.-ftrace_caller |
| 143 | #endif | 109 | #endif |
| 144 | #endif | 110 | #endif |
| 111 | |||
| 112 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER | ||
| 113 | ENTRY(ftrace_graph_caller) | ||
| 114 | mov %l0, %o0 | ||
| 115 | mov %i7, %o1 | ||
| 116 | call prepare_ftrace_return | ||
| 117 | mov %l1, %o2 | ||
| 118 | ret | ||
| 119 | restore %o0, -8, %i7 | ||
| 120 | END(ftrace_graph_caller) | ||
| 121 | |||
| 122 | ENTRY(return_to_handler) | ||
| 123 | save %sp, -128, %sp | ||
| 124 | call ftrace_return_to_handler | ||
| 125 | mov %fp, %o0 | ||
| 126 | jmpl %o0 + 8, %g0 | ||
| 127 | restore | ||
| 128 | END(return_to_handler) | ||
| 129 | #endif | ||
diff --git a/arch/x86/include/asm/lguest_hcall.h b/arch/x86/include/asm/lguest_hcall.h index ba0eed8aa1a6..b60f2924c413 100644 --- a/arch/x86/include/asm/lguest_hcall.h +++ b/arch/x86/include/asm/lguest_hcall.h | |||
| @@ -28,22 +28,39 @@ | |||
| 28 | 28 | ||
| 29 | #ifndef __ASSEMBLY__ | 29 | #ifndef __ASSEMBLY__ |
| 30 | #include <asm/hw_irq.h> | 30 | #include <asm/hw_irq.h> |
| 31 | #include <asm/kvm_para.h> | ||
| 32 | 31 | ||
| 33 | /*G:030 | 32 | /*G:030 |
| 34 | * But first, how does our Guest contact the Host to ask for privileged | 33 | * But first, how does our Guest contact the Host to ask for privileged |
| 35 | * operations? There are two ways: the direct way is to make a "hypercall", | 34 | * operations? There are two ways: the direct way is to make a "hypercall", |
| 36 | * to make requests of the Host Itself. | 35 | * to make requests of the Host Itself. |
| 37 | * | 36 | * |
| 38 | * We use the KVM hypercall mechanism, though completely different hypercall | 37 | * Our hypercall mechanism uses the highest unused trap code (traps 32 and |
| 39 | * numbers. Seventeen hypercalls are available: the hypercall number is put in | 38 | * above are used by real hardware interrupts). Seventeen hypercalls are |
| 40 | * the %eax register, and the arguments (when required) are placed in %ebx, | 39 | * available: the hypercall number is put in the %eax register, and the |
| 41 | * %ecx, %edx and %esi. If a return value makes sense, it's returned in %eax. | 40 | * arguments (when required) are placed in %ebx, %ecx, %edx and %esi. |
| 41 | * If a return value makes sense, it's returned in %eax. | ||
| 42 | * | 42 | * |
| 43 | * Grossly invalid calls result in Sudden Death at the hands of the vengeful | 43 | * Grossly invalid calls result in Sudden Death at the hands of the vengeful |
| 44 | * Host, rather than returning failure. This reflects Winston Churchill's | 44 | * Host, rather than returning failure. This reflects Winston Churchill's |
| 45 | * definition of a gentleman: "someone who is only rude intentionally". | 45 | * definition of a gentleman: "someone who is only rude intentionally". |
| 46 | :*/ | 46 | */ |
| 47 | static inline unsigned long | ||
| 48 | hcall(unsigned long call, | ||
| 49 | unsigned long arg1, unsigned long arg2, unsigned long arg3, | ||
| 50 | unsigned long arg4) | ||
| 51 | { | ||
| 52 | /* "int" is the Intel instruction to trigger a trap. */ | ||
| 53 | asm volatile("int $" __stringify(LGUEST_TRAP_ENTRY) | ||
| 54 | /* The call in %eax (aka "a") might be overwritten */ | ||
| 55 | : "=a"(call) | ||
| 56 | /* The arguments are in %eax, %ebx, %ecx, %edx & %esi */ | ||
| 57 | : "a"(call), "b"(arg1), "c"(arg2), "d"(arg3), "S"(arg4) | ||
| 58 | /* "memory" means this might write somewhere in memory. | ||
| 59 | * This isn't true for all calls, but it's safe to tell | ||
| 60 | * gcc that it might happen so it doesn't get clever. */ | ||
| 61 | : "memory"); | ||
| 62 | return call; | ||
| 63 | } | ||
| 47 | 64 | ||
| 48 | /* Can't use our min() macro here: needs to be a constant */ | 65 | /* Can't use our min() macro here: needs to be a constant */ |
| 49 | #define LGUEST_IRQS (NR_IRQS < 32 ? NR_IRQS: 32) | 66 | #define LGUEST_IRQS (NR_IRQS < 32 ? NR_IRQS: 32) |
diff --git a/arch/x86/lguest/boot.c b/arch/x86/lguest/boot.c index 7e59dc1d3fc2..2bdf628066bd 100644 --- a/arch/x86/lguest/boot.c +++ b/arch/x86/lguest/boot.c | |||
| @@ -115,7 +115,7 @@ static void async_hcall(unsigned long call, unsigned long arg1, | |||
| 115 | local_irq_save(flags); | 115 | local_irq_save(flags); |
| 116 | if (lguest_data.hcall_status[next_call] != 0xFF) { | 116 | if (lguest_data.hcall_status[next_call] != 0xFF) { |
| 117 | /* Table full, so do normal hcall which will flush table. */ | 117 | /* Table full, so do normal hcall which will flush table. */ |
| 118 | kvm_hypercall4(call, arg1, arg2, arg3, arg4); | 118 | hcall(call, arg1, arg2, arg3, arg4); |
| 119 | } else { | 119 | } else { |
| 120 | lguest_data.hcalls[next_call].arg0 = call; | 120 | lguest_data.hcalls[next_call].arg0 = call; |
| 121 | lguest_data.hcalls[next_call].arg1 = arg1; | 121 | lguest_data.hcalls[next_call].arg1 = arg1; |
| @@ -145,46 +145,45 @@ static void async_hcall(unsigned long call, unsigned long arg1, | |||
| 145 | * So, when we're in lazy mode, we call async_hcall() to store the call for | 145 | * So, when we're in lazy mode, we call async_hcall() to store the call for |
| 146 | * future processing: | 146 | * future processing: |
| 147 | */ | 147 | */ |
| 148 | static void lazy_hcall1(unsigned long call, | 148 | static void lazy_hcall1(unsigned long call, unsigned long arg1) |
| 149 | unsigned long arg1) | ||
| 150 | { | 149 | { |
| 151 | if (paravirt_get_lazy_mode() == PARAVIRT_LAZY_NONE) | 150 | if (paravirt_get_lazy_mode() == PARAVIRT_LAZY_NONE) |
| 152 | kvm_hypercall1(call, arg1); | 151 | hcall(call, arg1, 0, 0, 0); |
| 153 | else | 152 | else |
| 154 | async_hcall(call, arg1, 0, 0, 0); | 153 | async_hcall(call, arg1, 0, 0, 0); |
| 155 | } | 154 | } |
| 156 | 155 | ||
| 157 | /* You can imagine what lazy_hcall2, 3 and 4 look like. :*/ | 156 | /* You can imagine what lazy_hcall2, 3 and 4 look like. :*/ |
| 158 | static void lazy_hcall2(unsigned long call, | 157 | static void lazy_hcall2(unsigned long call, |
| 159 | unsigned long arg1, | 158 | unsigned long arg1, |
| 160 | unsigned long arg2) | 159 | unsigned long arg2) |
| 161 | { | 160 | { |
| 162 | if (paravirt_get_lazy_mode() == PARAVIRT_LAZY_NONE) | 161 | if (paravirt_get_lazy_mode() == PARAVIRT_LAZY_NONE) |
| 163 | kvm_hypercall2(call, arg1, arg2); | 162 | hcall(call, arg1, arg2, 0, 0); |
| 164 | else | 163 | else |
| 165 | async_hcall(call, arg1, arg2, 0, 0); | 164 | async_hcall(call, arg1, arg2, 0, 0); |
| 166 | } | 165 | } |
| 167 | 166 | ||
| 168 | static void lazy_hcall3(unsigned long call, | 167 | static void lazy_hcall3(unsigned long call, |
| 169 | unsigned long arg1, | 168 | unsigned long arg1, |
| 170 | unsigned long arg2, | 169 | unsigned long arg2, |
| 171 | unsigned long arg3) | 170 | unsigned long arg3) |
| 172 | { | 171 | { |
| 173 | if (paravirt_get_lazy_mode() == PARAVIRT_LAZY_NONE) | 172 | if (paravirt_get_lazy_mode() == PARAVIRT_LAZY_NONE) |
| 174 | kvm_hypercall3(call, arg1, arg2, arg3); | 173 | hcall(call, arg1, arg2, arg3, 0); |
| 175 | else | 174 | else |
| 176 | async_hcall(call, arg1, arg2, arg3, 0); | 175 | async_hcall(call, arg1, arg2, arg3, 0); |
| 177 | } | 176 | } |
| 178 | 177 | ||
| 179 | #ifdef CONFIG_X86_PAE | 178 | #ifdef CONFIG_X86_PAE |
| 180 | static void lazy_hcall4(unsigned long call, | 179 | static void lazy_hcall4(unsigned long call, |
| 181 | unsigned long arg1, | 180 | unsigned long arg1, |
| 182 | unsigned long arg2, | 181 | unsigned long arg2, |
| 183 | unsigned long arg3, | 182 | unsigned long arg3, |
| 184 | unsigned long arg4) | 183 | unsigned long arg4) |
| 185 | { | 184 | { |
| 186 | if (paravirt_get_lazy_mode() == PARAVIRT_LAZY_NONE) | 185 | if (paravirt_get_lazy_mode() == PARAVIRT_LAZY_NONE) |
| 187 | kvm_hypercall4(call, arg1, arg2, arg3, arg4); | 186 | hcall(call, arg1, arg2, arg3, arg4); |
| 188 | else | 187 | else |
| 189 | async_hcall(call, arg1, arg2, arg3, arg4); | 188 | async_hcall(call, arg1, arg2, arg3, arg4); |
| 190 | } | 189 | } |
| @@ -196,13 +195,13 @@ static void lazy_hcall4(unsigned long call, | |||
| 196 | :*/ | 195 | :*/ |
| 197 | static void lguest_leave_lazy_mmu_mode(void) | 196 | static void lguest_leave_lazy_mmu_mode(void) |
| 198 | { | 197 | { |
| 199 | kvm_hypercall0(LHCALL_FLUSH_ASYNC); | 198 | hcall(LHCALL_FLUSH_ASYNC, 0, 0, 0, 0); |
| 200 | paravirt_leave_lazy_mmu(); | 199 | paravirt_leave_lazy_mmu(); |
| 201 | } | 200 | } |
| 202 | 201 | ||
| 203 | static void lguest_end_context_switch(struct task_struct *next) | 202 | static void lguest_end_context_switch(struct task_struct *next) |
| 204 | { | 203 | { |
| 205 | kvm_hypercall0(LHCALL_FLUSH_ASYNC); | 204 | hcall(LHCALL_FLUSH_ASYNC, 0, 0, 0, 0); |
| 206 | paravirt_end_context_switch(next); | 205 | paravirt_end_context_switch(next); |
| 207 | } | 206 | } |
| 208 | 207 | ||
| @@ -286,7 +285,7 @@ static void lguest_write_idt_entry(gate_desc *dt, | |||
| 286 | /* Keep the local copy up to date. */ | 285 | /* Keep the local copy up to date. */ |
| 287 | native_write_idt_entry(dt, entrynum, g); | 286 | native_write_idt_entry(dt, entrynum, g); |
| 288 | /* Tell Host about this new entry. */ | 287 | /* Tell Host about this new entry. */ |
| 289 | kvm_hypercall3(LHCALL_LOAD_IDT_ENTRY, entrynum, desc[0], desc[1]); | 288 | hcall(LHCALL_LOAD_IDT_ENTRY, entrynum, desc[0], desc[1], 0); |
| 290 | } | 289 | } |
| 291 | 290 | ||
| 292 | /* | 291 | /* |
| @@ -300,7 +299,7 @@ static void lguest_load_idt(const struct desc_ptr *desc) | |||
| 300 | struct desc_struct *idt = (void *)desc->address; | 299 | struct desc_struct *idt = (void *)desc->address; |
| 301 | 300 | ||
| 302 | for (i = 0; i < (desc->size+1)/8; i++) | 301 | for (i = 0; i < (desc->size+1)/8; i++) |
| 303 | kvm_hypercall3(LHCALL_LOAD_IDT_ENTRY, i, idt[i].a, idt[i].b); | 302 | hcall(LHCALL_LOAD_IDT_ENTRY, i, idt[i].a, idt[i].b, 0); |
| 304 | } | 303 | } |
| 305 | 304 | ||
| 306 | /* | 305 | /* |
| @@ -321,7 +320,7 @@ static void lguest_load_gdt(const struct desc_ptr *desc) | |||
| 321 | struct desc_struct *gdt = (void *)desc->address; | 320 | struct desc_struct *gdt = (void *)desc->address; |
| 322 | 321 | ||
| 323 | for (i = 0; i < (desc->size+1)/8; i++) | 322 | for (i = 0; i < (desc->size+1)/8; i++) |
| 324 | kvm_hypercall3(LHCALL_LOAD_GDT_ENTRY, i, gdt[i].a, gdt[i].b); | 323 | hcall(LHCALL_LOAD_GDT_ENTRY, i, gdt[i].a, gdt[i].b, 0); |
| 325 | } | 324 | } |
| 326 | 325 | ||
| 327 | /* | 326 | /* |
| @@ -334,8 +333,8 @@ static void lguest_write_gdt_entry(struct desc_struct *dt, int entrynum, | |||
| 334 | { | 333 | { |
| 335 | native_write_gdt_entry(dt, entrynum, desc, type); | 334 | native_write_gdt_entry(dt, entrynum, desc, type); |
| 336 | /* Tell Host about this new entry. */ | 335 | /* Tell Host about this new entry. */ |
| 337 | kvm_hypercall3(LHCALL_LOAD_GDT_ENTRY, entrynum, | 336 | hcall(LHCALL_LOAD_GDT_ENTRY, entrynum, |
| 338 | dt[entrynum].a, dt[entrynum].b); | 337 | dt[entrynum].a, dt[entrynum].b, 0); |
| 339 | } | 338 | } |
| 340 | 339 | ||
| 341 | /* | 340 | /* |
| @@ -931,7 +930,7 @@ static int lguest_clockevent_set_next_event(unsigned long delta, | |||
| 931 | } | 930 | } |
| 932 | 931 | ||
| 933 | /* Please wake us this far in the future. */ | 932 | /* Please wake us this far in the future. */ |
| 934 | kvm_hypercall1(LHCALL_SET_CLOCKEVENT, delta); | 933 | hcall(LHCALL_SET_CLOCKEVENT, delta, 0, 0, 0); |
| 935 | return 0; | 934 | return 0; |
| 936 | } | 935 | } |
| 937 | 936 | ||
| @@ -942,7 +941,7 @@ static void lguest_clockevent_set_mode(enum clock_event_mode mode, | |||
| 942 | case CLOCK_EVT_MODE_UNUSED: | 941 | case CLOCK_EVT_MODE_UNUSED: |
| 943 | case CLOCK_EVT_MODE_SHUTDOWN: | 942 | case CLOCK_EVT_MODE_SHUTDOWN: |
| 944 | /* A 0 argument shuts the clock down. */ | 943 | /* A 0 argument shuts the clock down. */ |
| 945 | kvm_hypercall0(LHCALL_SET_CLOCKEVENT); | 944 | hcall(LHCALL_SET_CLOCKEVENT, 0, 0, 0, 0); |
| 946 | break; | 945 | break; |
| 947 | case CLOCK_EVT_MODE_ONESHOT: | 946 | case CLOCK_EVT_MODE_ONESHOT: |
| 948 | /* This is what we expect. */ | 947 | /* This is what we expect. */ |
| @@ -1100,7 +1099,7 @@ static void set_lguest_basic_apic_ops(void) | |||
| 1100 | /* STOP! Until an interrupt comes in. */ | 1099 | /* STOP! Until an interrupt comes in. */ |
| 1101 | static void lguest_safe_halt(void) | 1100 | static void lguest_safe_halt(void) |
| 1102 | { | 1101 | { |
| 1103 | kvm_hypercall0(LHCALL_HALT); | 1102 | hcall(LHCALL_HALT, 0, 0, 0, 0); |
| 1104 | } | 1103 | } |
| 1105 | 1104 | ||
| 1106 | /* | 1105 | /* |
| @@ -1112,8 +1111,8 @@ static void lguest_safe_halt(void) | |||
| 1112 | */ | 1111 | */ |
| 1113 | static void lguest_power_off(void) | 1112 | static void lguest_power_off(void) |
| 1114 | { | 1113 | { |
| 1115 | kvm_hypercall2(LHCALL_SHUTDOWN, __pa("Power down"), | 1114 | hcall(LHCALL_SHUTDOWN, __pa("Power down"), |
| 1116 | LGUEST_SHUTDOWN_POWEROFF); | 1115 | LGUEST_SHUTDOWN_POWEROFF, 0, 0); |
| 1117 | } | 1116 | } |
| 1118 | 1117 | ||
| 1119 | /* | 1118 | /* |
| @@ -1123,7 +1122,7 @@ static void lguest_power_off(void) | |||
| 1123 | */ | 1122 | */ |
| 1124 | static int lguest_panic(struct notifier_block *nb, unsigned long l, void *p) | 1123 | static int lguest_panic(struct notifier_block *nb, unsigned long l, void *p) |
| 1125 | { | 1124 | { |
| 1126 | kvm_hypercall2(LHCALL_SHUTDOWN, __pa(p), LGUEST_SHUTDOWN_POWEROFF); | 1125 | hcall(LHCALL_SHUTDOWN, __pa(p), LGUEST_SHUTDOWN_POWEROFF, 0, 0); |
| 1127 | /* The hcall won't return, but to keep gcc happy, we're "done". */ | 1126 | /* The hcall won't return, but to keep gcc happy, we're "done". */ |
| 1128 | return NOTIFY_DONE; | 1127 | return NOTIFY_DONE; |
| 1129 | } | 1128 | } |
| @@ -1162,7 +1161,7 @@ static __init int early_put_chars(u32 vtermno, const char *buf, int count) | |||
| 1162 | len = sizeof(scratch) - 1; | 1161 | len = sizeof(scratch) - 1; |
| 1163 | scratch[len] = '\0'; | 1162 | scratch[len] = '\0'; |
| 1164 | memcpy(scratch, buf, len); | 1163 | memcpy(scratch, buf, len); |
| 1165 | kvm_hypercall1(LHCALL_NOTIFY, __pa(scratch)); | 1164 | hcall(LHCALL_NOTIFY, __pa(scratch), 0, 0, 0); |
| 1166 | 1165 | ||
| 1167 | /* This routine returns the number of bytes actually written. */ | 1166 | /* This routine returns the number of bytes actually written. */ |
| 1168 | return len; | 1167 | return len; |
| @@ -1174,7 +1173,7 @@ static __init int early_put_chars(u32 vtermno, const char *buf, int count) | |||
| 1174 | */ | 1173 | */ |
| 1175 | static void lguest_restart(char *reason) | 1174 | static void lguest_restart(char *reason) |
| 1176 | { | 1175 | { |
| 1177 | kvm_hypercall2(LHCALL_SHUTDOWN, __pa(reason), LGUEST_SHUTDOWN_RESTART); | 1176 | hcall(LHCALL_SHUTDOWN, __pa(reason), LGUEST_SHUTDOWN_RESTART, 0, 0); |
| 1178 | } | 1177 | } |
| 1179 | 1178 | ||
| 1180 | /*G:050 | 1179 | /*G:050 |
diff --git a/arch/x86/lguest/i386_head.S b/arch/x86/lguest/i386_head.S index 27eac0faee48..4f420c2f2d55 100644 --- a/arch/x86/lguest/i386_head.S +++ b/arch/x86/lguest/i386_head.S | |||
| @@ -32,7 +32,7 @@ ENTRY(lguest_entry) | |||
| 32 | */ | 32 | */ |
| 33 | movl $LHCALL_LGUEST_INIT, %eax | 33 | movl $LHCALL_LGUEST_INIT, %eax |
| 34 | movl $lguest_data - __PAGE_OFFSET, %ebx | 34 | movl $lguest_data - __PAGE_OFFSET, %ebx |
| 35 | .byte 0x0f,0x01,0xc1 /* KVM_HYPERCALL */ | 35 | int $LGUEST_TRAP_ENTRY |
| 36 | 36 | ||
| 37 | /* Set up the initial stack so we can run C code. */ | 37 | /* Set up the initial stack so we can run C code. */ |
| 38 | movl $(init_thread_union+THREAD_SIZE),%esp | 38 | movl $(init_thread_union+THREAD_SIZE),%esp |
diff --git a/drivers/firewire/core-cdev.c b/drivers/firewire/core-cdev.c index 702dcc98c074..14a34d99eea2 100644 --- a/drivers/firewire/core-cdev.c +++ b/drivers/firewire/core-cdev.c | |||
| @@ -960,6 +960,8 @@ static int ioctl_queue_iso(struct client *client, union ioctl_arg *arg) | |||
| 960 | u.packet.header_length = GET_HEADER_LENGTH(control); | 960 | u.packet.header_length = GET_HEADER_LENGTH(control); |
| 961 | 961 | ||
| 962 | if (ctx->type == FW_ISO_CONTEXT_TRANSMIT) { | 962 | if (ctx->type == FW_ISO_CONTEXT_TRANSMIT) { |
| 963 | if (u.packet.header_length % 4 != 0) | ||
| 964 | return -EINVAL; | ||
| 963 | header_length = u.packet.header_length; | 965 | header_length = u.packet.header_length; |
| 964 | } else { | 966 | } else { |
| 965 | /* | 967 | /* |
| @@ -969,7 +971,8 @@ static int ioctl_queue_iso(struct client *client, union ioctl_arg *arg) | |||
| 969 | if (ctx->header_size == 0) { | 971 | if (ctx->header_size == 0) { |
| 970 | if (u.packet.header_length > 0) | 972 | if (u.packet.header_length > 0) |
| 971 | return -EINVAL; | 973 | return -EINVAL; |
| 972 | } else if (u.packet.header_length % ctx->header_size != 0) { | 974 | } else if (u.packet.header_length == 0 || |
| 975 | u.packet.header_length % ctx->header_size != 0) { | ||
| 973 | return -EINVAL; | 976 | return -EINVAL; |
| 974 | } | 977 | } |
| 975 | header_length = 0; | 978 | header_length = 0; |
| @@ -1354,24 +1357,24 @@ static int dispatch_ioctl(struct client *client, | |||
| 1354 | return -ENODEV; | 1357 | return -ENODEV; |
| 1355 | 1358 | ||
| 1356 | if (_IOC_TYPE(cmd) != '#' || | 1359 | if (_IOC_TYPE(cmd) != '#' || |
| 1357 | _IOC_NR(cmd) >= ARRAY_SIZE(ioctl_handlers)) | 1360 | _IOC_NR(cmd) >= ARRAY_SIZE(ioctl_handlers) || |
| 1361 | _IOC_SIZE(cmd) > sizeof(buffer)) | ||
| 1358 | return -EINVAL; | 1362 | return -EINVAL; |
| 1359 | 1363 | ||
| 1360 | if (_IOC_DIR(cmd) & _IOC_WRITE) { | 1364 | if (_IOC_DIR(cmd) == _IOC_READ) |
| 1361 | if (_IOC_SIZE(cmd) > sizeof(buffer) || | 1365 | memset(&buffer, 0, _IOC_SIZE(cmd)); |
| 1362 | copy_from_user(&buffer, arg, _IOC_SIZE(cmd))) | 1366 | |
| 1367 | if (_IOC_DIR(cmd) & _IOC_WRITE) | ||
| 1368 | if (copy_from_user(&buffer, arg, _IOC_SIZE(cmd))) | ||
| 1363 | return -EFAULT; | 1369 | return -EFAULT; |
| 1364 | } | ||
| 1365 | 1370 | ||
| 1366 | ret = ioctl_handlers[_IOC_NR(cmd)](client, &buffer); | 1371 | ret = ioctl_handlers[_IOC_NR(cmd)](client, &buffer); |
| 1367 | if (ret < 0) | 1372 | if (ret < 0) |
| 1368 | return ret; | 1373 | return ret; |
| 1369 | 1374 | ||
| 1370 | if (_IOC_DIR(cmd) & _IOC_READ) { | 1375 | if (_IOC_DIR(cmd) & _IOC_READ) |
| 1371 | if (_IOC_SIZE(cmd) > sizeof(buffer) || | 1376 | if (copy_to_user(arg, &buffer, _IOC_SIZE(cmd))) |
| 1372 | copy_to_user(arg, &buffer, _IOC_SIZE(cmd))) | ||
| 1373 | return -EFAULT; | 1377 | return -EFAULT; |
| 1374 | } | ||
| 1375 | 1378 | ||
| 1376 | return ret; | 1379 | return ret; |
| 1377 | } | 1380 | } |
diff --git a/drivers/hwmon/applesmc.c b/drivers/hwmon/applesmc.c index c1605b528e8f..0f28d91f29d8 100644 --- a/drivers/hwmon/applesmc.c +++ b/drivers/hwmon/applesmc.c | |||
| @@ -142,6 +142,12 @@ static const char *temperature_sensors_sets[][41] = { | |||
| 142 | "TM1S", "TM2P", "TM2S", "TM3S", "TM8P", "TM8S", "TM9P", "TM9S", | 142 | "TM1S", "TM2P", "TM2S", "TM3S", "TM8P", "TM8S", "TM9P", "TM9S", |
| 143 | "TN0C", "TN0D", "TN0H", "TS0C", "Tp0C", "Tp1C", "Tv0S", "Tv1S", | 143 | "TN0C", "TN0D", "TN0H", "TS0C", "Tp0C", "Tp1C", "Tv0S", "Tv1S", |
| 144 | NULL }, | 144 | NULL }, |
| 145 | /* Set 17: iMac 9,1 */ | ||
| 146 | { "TA0P", "TC0D", "TC0H", "TC0P", "TG0D", "TG0H", "TH0P", "TL0P", | ||
| 147 | "TN0D", "TN0H", "TN0P", "TO0P", "Tm0P", "Tp0P", NULL }, | ||
| 148 | /* Set 18: MacBook Pro 2,2 */ | ||
| 149 | { "TB0T", "TC0D", "TC0P", "TG0H", "TG0P", "TG0T", "TM0P", "TTF0", | ||
| 150 | "Th0H", "Th1H", "Tm0P", "Ts0P", NULL }, | ||
| 145 | }; | 151 | }; |
| 146 | 152 | ||
| 147 | /* List of keys used to read/write fan speeds */ | 153 | /* List of keys used to read/write fan speeds */ |
| @@ -1350,6 +1356,10 @@ static __initdata struct dmi_match_data applesmc_dmi_data[] = { | |||
| 1350 | { .accelerometer = 1, .light = 1, .temperature_set = 15 }, | 1356 | { .accelerometer = 1, .light = 1, .temperature_set = 15 }, |
| 1351 | /* MacPro3,1: temperature set 16 */ | 1357 | /* MacPro3,1: temperature set 16 */ |
| 1352 | { .accelerometer = 0, .light = 0, .temperature_set = 16 }, | 1358 | { .accelerometer = 0, .light = 0, .temperature_set = 16 }, |
| 1359 | /* iMac 9,1: light sensor only, temperature set 17 */ | ||
| 1360 | { .accelerometer = 0, .light = 0, .temperature_set = 17 }, | ||
| 1361 | /* MacBook Pro 2,2: accelerometer, backlight and temperature set 18 */ | ||
| 1362 | { .accelerometer = 1, .light = 1, .temperature_set = 18 }, | ||
| 1353 | }; | 1363 | }; |
| 1354 | 1364 | ||
| 1355 | /* Note that DMI_MATCH(...,"MacBook") will match "MacBookPro1,1". | 1365 | /* Note that DMI_MATCH(...,"MacBook") will match "MacBookPro1,1". |
| @@ -1375,6 +1385,10 @@ static __initdata struct dmi_system_id applesmc_whitelist[] = { | |||
| 1375 | DMI_MATCH(DMI_BOARD_VENDOR, "Apple"), | 1385 | DMI_MATCH(DMI_BOARD_VENDOR, "Apple"), |
| 1376 | DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro3") }, | 1386 | DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro3") }, |
| 1377 | &applesmc_dmi_data[9]}, | 1387 | &applesmc_dmi_data[9]}, |
| 1388 | { applesmc_dmi_match, "Apple MacBook Pro 2,2", { | ||
| 1389 | DMI_MATCH(DMI_BOARD_VENDOR, "Apple Computer, Inc."), | ||
| 1390 | DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro2,2") }, | ||
| 1391 | &applesmc_dmi_data[18]}, | ||
| 1378 | { applesmc_dmi_match, "Apple MacBook Pro", { | 1392 | { applesmc_dmi_match, "Apple MacBook Pro", { |
| 1379 | DMI_MATCH(DMI_BOARD_VENDOR,"Apple"), | 1393 | DMI_MATCH(DMI_BOARD_VENDOR,"Apple"), |
| 1380 | DMI_MATCH(DMI_PRODUCT_NAME,"MacBookPro") }, | 1394 | DMI_MATCH(DMI_PRODUCT_NAME,"MacBookPro") }, |
| @@ -1415,6 +1429,10 @@ static __initdata struct dmi_system_id applesmc_whitelist[] = { | |||
| 1415 | DMI_MATCH(DMI_BOARD_VENDOR, "Apple"), | 1429 | DMI_MATCH(DMI_BOARD_VENDOR, "Apple"), |
| 1416 | DMI_MATCH(DMI_PRODUCT_NAME, "MacPro") }, | 1430 | DMI_MATCH(DMI_PRODUCT_NAME, "MacPro") }, |
| 1417 | &applesmc_dmi_data[4]}, | 1431 | &applesmc_dmi_data[4]}, |
| 1432 | { applesmc_dmi_match, "Apple iMac 9,1", { | ||
| 1433 | DMI_MATCH(DMI_BOARD_VENDOR, "Apple Inc."), | ||
| 1434 | DMI_MATCH(DMI_PRODUCT_NAME, "iMac9,1") }, | ||
| 1435 | &applesmc_dmi_data[17]}, | ||
| 1418 | { applesmc_dmi_match, "Apple iMac 8", { | 1436 | { applesmc_dmi_match, "Apple iMac 8", { |
| 1419 | DMI_MATCH(DMI_BOARD_VENDOR, "Apple"), | 1437 | DMI_MATCH(DMI_BOARD_VENDOR, "Apple"), |
| 1420 | DMI_MATCH(DMI_PRODUCT_NAME, "iMac8") }, | 1438 | DMI_MATCH(DMI_PRODUCT_NAME, "iMac8") }, |
diff --git a/drivers/hwmon/it87.c b/drivers/hwmon/it87.c index 1002befd87d5..5be09c048c5f 100644 --- a/drivers/hwmon/it87.c +++ b/drivers/hwmon/it87.c | |||
| @@ -539,14 +539,14 @@ static ssize_t set_sensor(struct device *dev, struct device_attribute *attr, | |||
| 539 | 539 | ||
| 540 | struct it87_data *data = dev_get_drvdata(dev); | 540 | struct it87_data *data = dev_get_drvdata(dev); |
| 541 | long val; | 541 | long val; |
| 542 | u8 reg; | ||
| 542 | 543 | ||
| 543 | if (strict_strtol(buf, 10, &val) < 0) | 544 | if (strict_strtol(buf, 10, &val) < 0) |
| 544 | return -EINVAL; | 545 | return -EINVAL; |
| 545 | 546 | ||
| 546 | mutex_lock(&data->update_lock); | 547 | reg = it87_read_value(data, IT87_REG_TEMP_ENABLE); |
| 547 | 548 | reg &= ~(1 << nr); | |
| 548 | data->sensor &= ~(1 << nr); | 549 | reg &= ~(8 << nr); |
| 549 | data->sensor &= ~(8 << nr); | ||
| 550 | if (val == 2) { /* backwards compatibility */ | 550 | if (val == 2) { /* backwards compatibility */ |
| 551 | dev_warn(dev, "Sensor type 2 is deprecated, please use 4 " | 551 | dev_warn(dev, "Sensor type 2 is deprecated, please use 4 " |
| 552 | "instead\n"); | 552 | "instead\n"); |
| @@ -554,14 +554,16 @@ static ssize_t set_sensor(struct device *dev, struct device_attribute *attr, | |||
| 554 | } | 554 | } |
| 555 | /* 3 = thermal diode; 4 = thermistor; 0 = disabled */ | 555 | /* 3 = thermal diode; 4 = thermistor; 0 = disabled */ |
| 556 | if (val == 3) | 556 | if (val == 3) |
| 557 | data->sensor |= 1 << nr; | 557 | reg |= 1 << nr; |
| 558 | else if (val == 4) | 558 | else if (val == 4) |
| 559 | data->sensor |= 8 << nr; | 559 | reg |= 8 << nr; |
| 560 | else if (val != 0) { | 560 | else if (val != 0) |
| 561 | mutex_unlock(&data->update_lock); | ||
| 562 | return -EINVAL; | 561 | return -EINVAL; |
| 563 | } | 562 | |
| 563 | mutex_lock(&data->update_lock); | ||
| 564 | data->sensor = reg; | ||
| 564 | it87_write_value(data, IT87_REG_TEMP_ENABLE, data->sensor); | 565 | it87_write_value(data, IT87_REG_TEMP_ENABLE, data->sensor); |
| 566 | data->valid = 0; /* Force cache refresh */ | ||
| 565 | mutex_unlock(&data->update_lock); | 567 | mutex_unlock(&data->update_lock); |
| 566 | return count; | 568 | return count; |
| 567 | } | 569 | } |
| @@ -1841,14 +1843,10 @@ static void __devinit it87_init_device(struct platform_device *pdev) | |||
| 1841 | it87_write_value(data, IT87_REG_TEMP_HIGH(i), 127); | 1843 | it87_write_value(data, IT87_REG_TEMP_HIGH(i), 127); |
| 1842 | } | 1844 | } |
| 1843 | 1845 | ||
| 1844 | /* Check if temperature channels are reset manually or by some reason */ | 1846 | /* Temperature channels are not forcibly enabled, as they can be |
| 1845 | tmp = it87_read_value(data, IT87_REG_TEMP_ENABLE); | 1847 | * set to two different sensor types and we can't guess which one |
| 1846 | if ((tmp & 0x3f) == 0) { | 1848 | * is correct for a given system. These channels can be enabled at |
| 1847 | /* Temp1,Temp3=thermistor; Temp2=thermal diode */ | 1849 | * run-time through the temp{1-3}_type sysfs accessors if needed. */ |
| 1848 | tmp = (tmp & 0xc0) | 0x2a; | ||
| 1849 | it87_write_value(data, IT87_REG_TEMP_ENABLE, tmp); | ||
| 1850 | } | ||
| 1851 | data->sensor = tmp; | ||
| 1852 | 1850 | ||
| 1853 | /* Check if voltage monitors are reset manually or by some reason */ | 1851 | /* Check if voltage monitors are reset manually or by some reason */ |
| 1854 | tmp = it87_read_value(data, IT87_REG_VIN_ENABLE); | 1852 | tmp = it87_read_value(data, IT87_REG_VIN_ENABLE); |
diff --git a/drivers/hwmon/sht15.c b/drivers/hwmon/sht15.c index 6b2d8ae64fe1..a610e7880fb3 100644 --- a/drivers/hwmon/sht15.c +++ b/drivers/hwmon/sht15.c | |||
| @@ -303,13 +303,13 @@ error_ret: | |||
| 303 | **/ | 303 | **/ |
| 304 | static inline int sht15_calc_temp(struct sht15_data *data) | 304 | static inline int sht15_calc_temp(struct sht15_data *data) |
| 305 | { | 305 | { |
| 306 | int d1 = 0; | 306 | int d1 = temppoints[0].d1; |
| 307 | int i; | 307 | int i; |
| 308 | 308 | ||
| 309 | for (i = 1; i < ARRAY_SIZE(temppoints); i++) | 309 | for (i = ARRAY_SIZE(temppoints) - 1; i > 0; i--) |
| 310 | /* Find pointer to interpolate */ | 310 | /* Find pointer to interpolate */ |
| 311 | if (data->supply_uV > temppoints[i - 1].vdd) { | 311 | if (data->supply_uV > temppoints[i - 1].vdd) { |
| 312 | d1 = (data->supply_uV/1000 - temppoints[i - 1].vdd) | 312 | d1 = (data->supply_uV - temppoints[i - 1].vdd) |
| 313 | * (temppoints[i].d1 - temppoints[i - 1].d1) | 313 | * (temppoints[i].d1 - temppoints[i - 1].d1) |
| 314 | / (temppoints[i].vdd - temppoints[i - 1].vdd) | 314 | / (temppoints[i].vdd - temppoints[i - 1].vdd) |
| 315 | + temppoints[i - 1].d1; | 315 | + temppoints[i - 1].d1; |
| @@ -542,7 +542,12 @@ static int __devinit sht15_probe(struct platform_device *pdev) | |||
| 542 | /* If a regulator is available, query what the supply voltage actually is!*/ | 542 | /* If a regulator is available, query what the supply voltage actually is!*/ |
| 543 | data->reg = regulator_get(data->dev, "vcc"); | 543 | data->reg = regulator_get(data->dev, "vcc"); |
| 544 | if (!IS_ERR(data->reg)) { | 544 | if (!IS_ERR(data->reg)) { |
| 545 | data->supply_uV = regulator_get_voltage(data->reg); | 545 | int voltage; |
| 546 | |||
| 547 | voltage = regulator_get_voltage(data->reg); | ||
| 548 | if (voltage) | ||
| 549 | data->supply_uV = voltage; | ||
| 550 | |||
| 546 | regulator_enable(data->reg); | 551 | regulator_enable(data->reg); |
| 547 | /* setup a notifier block to update this if another device | 552 | /* setup a notifier block to update this if another device |
| 548 | * causes the voltage to change */ | 553 | * causes the voltage to change */ |
diff --git a/drivers/input/input.c b/drivers/input/input.c index afd4e2b7658c..9c79bd56b51a 100644 --- a/drivers/input/input.c +++ b/drivers/input/input.c | |||
| @@ -660,7 +660,14 @@ static int input_default_setkeycode(struct input_dev *dev, | |||
| 660 | int input_get_keycode(struct input_dev *dev, | 660 | int input_get_keycode(struct input_dev *dev, |
| 661 | unsigned int scancode, unsigned int *keycode) | 661 | unsigned int scancode, unsigned int *keycode) |
| 662 | { | 662 | { |
| 663 | return dev->getkeycode(dev, scancode, keycode); | 663 | unsigned long flags; |
| 664 | int retval; | ||
| 665 | |||
| 666 | spin_lock_irqsave(&dev->event_lock, flags); | ||
| 667 | retval = dev->getkeycode(dev, scancode, keycode); | ||
| 668 | spin_unlock_irqrestore(&dev->event_lock, flags); | ||
| 669 | |||
| 670 | return retval; | ||
| 664 | } | 671 | } |
| 665 | EXPORT_SYMBOL(input_get_keycode); | 672 | EXPORT_SYMBOL(input_get_keycode); |
| 666 | 673 | ||
diff --git a/drivers/input/keyboard/matrix_keypad.c b/drivers/input/keyboard/matrix_keypad.c index ffc25cfcef7a..b443e088fd3c 100644 --- a/drivers/input/keyboard/matrix_keypad.c +++ b/drivers/input/keyboard/matrix_keypad.c | |||
| @@ -374,7 +374,9 @@ static int __devinit matrix_keypad_probe(struct platform_device *pdev) | |||
| 374 | input_dev->name = pdev->name; | 374 | input_dev->name = pdev->name; |
| 375 | input_dev->id.bustype = BUS_HOST; | 375 | input_dev->id.bustype = BUS_HOST; |
| 376 | input_dev->dev.parent = &pdev->dev; | 376 | input_dev->dev.parent = &pdev->dev; |
| 377 | input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP); | 377 | input_dev->evbit[0] = BIT_MASK(EV_KEY); |
| 378 | if (!pdata->no_autorepeat) | ||
| 379 | input_dev->evbit[0] |= BIT_MASK(EV_REP); | ||
| 378 | input_dev->open = matrix_keypad_start; | 380 | input_dev->open = matrix_keypad_start; |
| 379 | input_dev->close = matrix_keypad_stop; | 381 | input_dev->close = matrix_keypad_stop; |
| 380 | 382 | ||
diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c index 99d58764ef03..0d22cb9ce42e 100644 --- a/drivers/input/mouse/alps.c +++ b/drivers/input/mouse/alps.c | |||
| @@ -64,6 +64,7 @@ static const struct alps_model_info alps_model_data[] = { | |||
| 64 | { { 0x62, 0x02, 0x14 }, 0xcf, 0xcf, | 64 | { { 0x62, 0x02, 0x14 }, 0xcf, 0xcf, |
| 65 | ALPS_PASS | ALPS_DUALPOINT | ALPS_PS2_INTERLEAVED }, | 65 | ALPS_PASS | ALPS_DUALPOINT | ALPS_PS2_INTERLEAVED }, |
| 66 | { { 0x73, 0x02, 0x50 }, 0xcf, 0xcf, ALPS_FOUR_BUTTONS }, /* Dell Vostro 1400 */ | 66 | { { 0x73, 0x02, 0x50 }, 0xcf, 0xcf, ALPS_FOUR_BUTTONS }, /* Dell Vostro 1400 */ |
| 67 | { { 0x73, 0x02, 0x64 }, 0xf8, 0xf8, 0 }, /* HP Pavilion dm3 */ | ||
| 67 | { { 0x52, 0x01, 0x14 }, 0xff, 0xff, | 68 | { { 0x52, 0x01, 0x14 }, 0xff, 0xff, |
| 68 | ALPS_PASS | ALPS_DUALPOINT | ALPS_PS2_INTERLEAVED }, /* Toshiba Tecra A11-11L */ | 69 | ALPS_PASS | ALPS_DUALPOINT | ALPS_PS2_INTERLEAVED }, /* Toshiba Tecra A11-11L */ |
| 69 | }; | 70 | }; |
diff --git a/drivers/input/mouse/bcm5974.c b/drivers/input/mouse/bcm5974.c index 4f8fe0886b2a..b89879bd860f 100644 --- a/drivers/input/mouse/bcm5974.c +++ b/drivers/input/mouse/bcm5974.c | |||
| @@ -803,7 +803,6 @@ static struct usb_driver bcm5974_driver = { | |||
| 803 | .disconnect = bcm5974_disconnect, | 803 | .disconnect = bcm5974_disconnect, |
| 804 | .suspend = bcm5974_suspend, | 804 | .suspend = bcm5974_suspend, |
| 805 | .resume = bcm5974_resume, | 805 | .resume = bcm5974_resume, |
| 806 | .reset_resume = bcm5974_resume, | ||
| 807 | .id_table = bcm5974_table, | 806 | .id_table = bcm5974_table, |
| 808 | .supports_autosuspend = 1, | 807 | .supports_autosuspend = 1, |
| 809 | }; | 808 | }; |
diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c index 577688b5b951..6440a8f55686 100644 --- a/drivers/input/serio/i8042.c +++ b/drivers/input/serio/i8042.c | |||
| @@ -39,7 +39,7 @@ MODULE_PARM_DESC(noaux, "Do not probe or use AUX (mouse) port."); | |||
| 39 | 39 | ||
| 40 | static bool i8042_nomux; | 40 | static bool i8042_nomux; |
| 41 | module_param_named(nomux, i8042_nomux, bool, 0); | 41 | module_param_named(nomux, i8042_nomux, bool, 0); |
| 42 | MODULE_PARM_DESC(nomux, "Do not check whether an active multiplexing conrtoller is present."); | 42 | MODULE_PARM_DESC(nomux, "Do not check whether an active multiplexing controller is present."); |
| 43 | 43 | ||
| 44 | static bool i8042_unlock; | 44 | static bool i8042_unlock; |
| 45 | module_param_named(unlock, i8042_unlock, bool, 0); | 45 | module_param_named(unlock, i8042_unlock, bool, 0); |
diff --git a/drivers/input/sparse-keymap.c b/drivers/input/sparse-keymap.c index 82ae18d29685..014248344763 100644 --- a/drivers/input/sparse-keymap.c +++ b/drivers/input/sparse-keymap.c | |||
| @@ -68,12 +68,14 @@ static int sparse_keymap_getkeycode(struct input_dev *dev, | |||
| 68 | unsigned int scancode, | 68 | unsigned int scancode, |
| 69 | unsigned int *keycode) | 69 | unsigned int *keycode) |
| 70 | { | 70 | { |
| 71 | const struct key_entry *key = | 71 | const struct key_entry *key; |
| 72 | sparse_keymap_entry_from_scancode(dev, scancode); | ||
| 73 | 72 | ||
| 74 | if (key && key->type == KE_KEY) { | 73 | if (dev->keycode) { |
| 75 | *keycode = key->keycode; | 74 | key = sparse_keymap_entry_from_scancode(dev, scancode); |
| 76 | return 0; | 75 | if (key && key->type == KE_KEY) { |
| 76 | *keycode = key->keycode; | ||
| 77 | return 0; | ||
| 78 | } | ||
| 77 | } | 79 | } |
| 78 | 80 | ||
| 79 | return -EINVAL; | 81 | return -EINVAL; |
| @@ -86,17 +88,16 @@ static int sparse_keymap_setkeycode(struct input_dev *dev, | |||
| 86 | struct key_entry *key; | 88 | struct key_entry *key; |
| 87 | int old_keycode; | 89 | int old_keycode; |
| 88 | 90 | ||
| 89 | if (keycode < 0 || keycode > KEY_MAX) | 91 | if (dev->keycode) { |
| 90 | return -EINVAL; | 92 | key = sparse_keymap_entry_from_scancode(dev, scancode); |
| 91 | 93 | if (key && key->type == KE_KEY) { | |
| 92 | key = sparse_keymap_entry_from_scancode(dev, scancode); | 94 | old_keycode = key->keycode; |
| 93 | if (key && key->type == KE_KEY) { | 95 | key->keycode = keycode; |
| 94 | old_keycode = key->keycode; | 96 | set_bit(keycode, dev->keybit); |
| 95 | key->keycode = keycode; | 97 | if (!sparse_keymap_entry_from_keycode(dev, old_keycode)) |
| 96 | set_bit(keycode, dev->keybit); | 98 | clear_bit(old_keycode, dev->keybit); |
| 97 | if (!sparse_keymap_entry_from_keycode(dev, old_keycode)) | 99 | return 0; |
| 98 | clear_bit(old_keycode, dev->keybit); | 100 | } |
| 99 | return 0; | ||
| 100 | } | 101 | } |
| 101 | 102 | ||
| 102 | return -EINVAL; | 103 | return -EINVAL; |
| @@ -164,7 +165,7 @@ int sparse_keymap_setup(struct input_dev *dev, | |||
| 164 | return 0; | 165 | return 0; |
| 165 | 166 | ||
| 166 | err_out: | 167 | err_out: |
| 167 | kfree(keymap); | 168 | kfree(map); |
| 168 | return error; | 169 | return error; |
| 169 | 170 | ||
| 170 | } | 171 | } |
| @@ -176,14 +177,27 @@ EXPORT_SYMBOL(sparse_keymap_setup); | |||
| 176 | * | 177 | * |
| 177 | * This function is used to free memory allocated by sparse keymap | 178 | * This function is used to free memory allocated by sparse keymap |
| 178 | * in an input device that was set up by sparse_keymap_setup(). | 179 | * in an input device that was set up by sparse_keymap_setup(). |
| 180 | * NOTE: It is safe to cal this function while input device is | ||
| 181 | * still registered (however the drivers should care not to try to | ||
| 182 | * use freed keymap and thus have to shut off interrups/polling | ||
| 183 | * before freeing the keymap). | ||
| 179 | */ | 184 | */ |
| 180 | void sparse_keymap_free(struct input_dev *dev) | 185 | void sparse_keymap_free(struct input_dev *dev) |
| 181 | { | 186 | { |
| 187 | unsigned long flags; | ||
| 188 | |||
| 189 | /* | ||
| 190 | * Take event lock to prevent racing with input_get_keycode() | ||
| 191 | * and input_set_keycode() if we are called while input device | ||
| 192 | * is still registered. | ||
| 193 | */ | ||
| 194 | spin_lock_irqsave(&dev->event_lock, flags); | ||
| 195 | |||
| 182 | kfree(dev->keycode); | 196 | kfree(dev->keycode); |
| 183 | dev->keycode = NULL; | 197 | dev->keycode = NULL; |
| 184 | dev->keycodemax = 0; | 198 | dev->keycodemax = 0; |
| 185 | dev->getkeycode = NULL; | 199 | |
| 186 | dev->setkeycode = NULL; | 200 | spin_unlock_irqrestore(&dev->event_lock, flags); |
| 187 | } | 201 | } |
| 188 | EXPORT_SYMBOL(sparse_keymap_free); | 202 | EXPORT_SYMBOL(sparse_keymap_free); |
| 189 | 203 | ||
diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c index 8b5d2873f0c4..f46502589e4e 100644 --- a/drivers/input/tablet/wacom_sys.c +++ b/drivers/input/tablet/wacom_sys.c | |||
| @@ -673,13 +673,15 @@ static int wacom_resume(struct usb_interface *intf) | |||
| 673 | int rv; | 673 | int rv; |
| 674 | 674 | ||
| 675 | mutex_lock(&wacom->lock); | 675 | mutex_lock(&wacom->lock); |
| 676 | if (wacom->open) { | 676 | |
| 677 | /* switch to wacom mode first */ | ||
| 678 | wacom_query_tablet_data(intf, features); | ||
| 679 | |||
| 680 | if (wacom->open) | ||
| 677 | rv = usb_submit_urb(wacom->irq, GFP_NOIO); | 681 | rv = usb_submit_urb(wacom->irq, GFP_NOIO); |
| 678 | /* switch to wacom mode if needed */ | 682 | else |
| 679 | if (!wacom_retrieve_hid_descriptor(intf, features)) | ||
| 680 | wacom_query_tablet_data(intf, features); | ||
| 681 | } else | ||
| 682 | rv = 0; | 683 | rv = 0; |
| 684 | |||
| 683 | mutex_unlock(&wacom->lock); | 685 | mutex_unlock(&wacom->lock); |
| 684 | 686 | ||
| 685 | return rv; | 687 | return rv; |
diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c index b3ba3437a2eb..4a852d815c68 100644 --- a/drivers/input/tablet/wacom_wac.c +++ b/drivers/input/tablet/wacom_wac.c | |||
| @@ -155,19 +155,19 @@ static int wacom_graphire_irq(struct wacom_wac *wacom, void *wcombo) | |||
| 155 | { | 155 | { |
| 156 | struct wacom_features *features = &wacom->features; | 156 | struct wacom_features *features = &wacom->features; |
| 157 | unsigned char *data = wacom->data; | 157 | unsigned char *data = wacom->data; |
| 158 | int x, y, prox; | 158 | int x, y, rw; |
| 159 | int rw = 0; | 159 | static int penData = 0; |
| 160 | int retval = 0; | ||
| 161 | 160 | ||
| 162 | if (data[0] != WACOM_REPORT_PENABLED) { | 161 | if (data[0] != WACOM_REPORT_PENABLED) { |
| 163 | dbg("wacom_graphire_irq: received unknown report #%d", data[0]); | 162 | dbg("wacom_graphire_irq: received unknown report #%d", data[0]); |
| 164 | goto exit; | 163 | return 0; |
| 165 | } | 164 | } |
| 166 | 165 | ||
| 167 | prox = data[1] & 0x80; | 166 | if (data[1] & 0x80) { |
| 168 | if (prox || wacom->id[0]) { | 167 | /* in prox and not a pad data */ |
| 169 | if (prox) { | 168 | penData = 1; |
| 170 | switch ((data[1] >> 5) & 3) { | 169 | |
| 170 | switch ((data[1] >> 5) & 3) { | ||
| 171 | 171 | ||
| 172 | case 0: /* Pen */ | 172 | case 0: /* Pen */ |
| 173 | wacom->tool[0] = BTN_TOOL_PEN; | 173 | wacom->tool[0] = BTN_TOOL_PEN; |
| @@ -181,13 +181,23 @@ static int wacom_graphire_irq(struct wacom_wac *wacom, void *wcombo) | |||
| 181 | 181 | ||
| 182 | case 2: /* Mouse with wheel */ | 182 | case 2: /* Mouse with wheel */ |
| 183 | wacom_report_key(wcombo, BTN_MIDDLE, data[1] & 0x04); | 183 | wacom_report_key(wcombo, BTN_MIDDLE, data[1] & 0x04); |
| 184 | if (features->type == WACOM_G4 || features->type == WACOM_MO) { | ||
| 185 | rw = data[7] & 0x04 ? (data[7] & 0x03)-4 : (data[7] & 0x03); | ||
| 186 | wacom_report_rel(wcombo, REL_WHEEL, -rw); | ||
| 187 | } else | ||
| 188 | wacom_report_rel(wcombo, REL_WHEEL, -(signed char) data[6]); | ||
| 184 | /* fall through */ | 189 | /* fall through */ |
| 185 | 190 | ||
| 186 | case 3: /* Mouse without wheel */ | 191 | case 3: /* Mouse without wheel */ |
| 187 | wacom->tool[0] = BTN_TOOL_MOUSE; | 192 | wacom->tool[0] = BTN_TOOL_MOUSE; |
| 188 | wacom->id[0] = CURSOR_DEVICE_ID; | 193 | wacom->id[0] = CURSOR_DEVICE_ID; |
| 194 | wacom_report_key(wcombo, BTN_LEFT, data[1] & 0x01); | ||
| 195 | wacom_report_key(wcombo, BTN_RIGHT, data[1] & 0x02); | ||
| 196 | if (features->type == WACOM_G4 || features->type == WACOM_MO) | ||
| 197 | wacom_report_abs(wcombo, ABS_DISTANCE, data[6] & 0x3f); | ||
| 198 | else | ||
| 199 | wacom_report_abs(wcombo, ABS_DISTANCE, data[7] & 0x3f); | ||
| 189 | break; | 200 | break; |
| 190 | } | ||
| 191 | } | 201 | } |
| 192 | x = wacom_le16_to_cpu(&data[2]); | 202 | x = wacom_le16_to_cpu(&data[2]); |
| 193 | y = wacom_le16_to_cpu(&data[4]); | 203 | y = wacom_le16_to_cpu(&data[4]); |
| @@ -198,32 +208,36 @@ static int wacom_graphire_irq(struct wacom_wac *wacom, void *wcombo) | |||
| 198 | wacom_report_key(wcombo, BTN_TOUCH, data[1] & 0x01); | 208 | wacom_report_key(wcombo, BTN_TOUCH, data[1] & 0x01); |
| 199 | wacom_report_key(wcombo, BTN_STYLUS, data[1] & 0x02); | 209 | wacom_report_key(wcombo, BTN_STYLUS, data[1] & 0x02); |
| 200 | wacom_report_key(wcombo, BTN_STYLUS2, data[1] & 0x04); | 210 | wacom_report_key(wcombo, BTN_STYLUS2, data[1] & 0x04); |
| 201 | } else { | ||
| 202 | wacom_report_key(wcombo, BTN_LEFT, data[1] & 0x01); | ||
| 203 | wacom_report_key(wcombo, BTN_RIGHT, data[1] & 0x02); | ||
| 204 | if (features->type == WACOM_G4 || | ||
| 205 | features->type == WACOM_MO) { | ||
| 206 | wacom_report_abs(wcombo, ABS_DISTANCE, data[6] & 0x3f); | ||
| 207 | rw = (signed)(data[7] & 0x04) - (data[7] & 0x03); | ||
| 208 | } else { | ||
| 209 | wacom_report_abs(wcombo, ABS_DISTANCE, data[7] & 0x3f); | ||
| 210 | rw = -(signed)data[6]; | ||
| 211 | } | ||
| 212 | wacom_report_rel(wcombo, REL_WHEEL, rw); | ||
| 213 | } | 211 | } |
| 214 | |||
| 215 | if (!prox) | ||
| 216 | wacom->id[0] = 0; | ||
| 217 | wacom_report_abs(wcombo, ABS_MISC, wacom->id[0]); /* report tool id */ | 212 | wacom_report_abs(wcombo, ABS_MISC, wacom->id[0]); /* report tool id */ |
| 218 | wacom_report_key(wcombo, wacom->tool[0], prox); | 213 | wacom_report_key(wcombo, wacom->tool[0], 1); |
| 219 | wacom_input_sync(wcombo); /* sync last event */ | 214 | } else if (wacom->id[0]) { |
| 215 | wacom_report_abs(wcombo, ABS_X, 0); | ||
| 216 | wacom_report_abs(wcombo, ABS_Y, 0); | ||
| 217 | if (wacom->tool[0] == BTN_TOOL_MOUSE) { | ||
| 218 | wacom_report_key(wcombo, BTN_LEFT, 0); | ||
| 219 | wacom_report_key(wcombo, BTN_RIGHT, 0); | ||
| 220 | wacom_report_abs(wcombo, ABS_DISTANCE, 0); | ||
| 221 | } else { | ||
| 222 | wacom_report_abs(wcombo, ABS_PRESSURE, 0); | ||
| 223 | wacom_report_key(wcombo, BTN_TOUCH, 0); | ||
| 224 | wacom_report_key(wcombo, BTN_STYLUS, 0); | ||
| 225 | wacom_report_key(wcombo, BTN_STYLUS2, 0); | ||
| 226 | } | ||
| 227 | wacom->id[0] = 0; | ||
| 228 | wacom_report_abs(wcombo, ABS_MISC, 0); /* reset tool id */ | ||
| 229 | wacom_report_key(wcombo, wacom->tool[0], 0); | ||
| 220 | } | 230 | } |
| 221 | 231 | ||
| 222 | /* send pad data */ | 232 | /* send pad data */ |
| 223 | switch (features->type) { | 233 | switch (features->type) { |
| 224 | case WACOM_G4: | 234 | case WACOM_G4: |
| 225 | prox = data[7] & 0xf8; | 235 | if (data[7] & 0xf8) { |
| 226 | if (prox || wacom->id[1]) { | 236 | if (penData) { |
| 237 | wacom_input_sync(wcombo); /* sync last event */ | ||
| 238 | if (!wacom->id[0]) | ||
| 239 | penData = 0; | ||
| 240 | } | ||
| 227 | wacom->id[1] = PAD_DEVICE_ID; | 241 | wacom->id[1] = PAD_DEVICE_ID; |
| 228 | wacom_report_key(wcombo, BTN_0, (data[7] & 0x40)); | 242 | wacom_report_key(wcombo, BTN_0, (data[7] & 0x40)); |
| 229 | wacom_report_key(wcombo, BTN_4, (data[7] & 0x80)); | 243 | wacom_report_key(wcombo, BTN_4, (data[7] & 0x80)); |
| @@ -231,16 +245,29 @@ static int wacom_graphire_irq(struct wacom_wac *wacom, void *wcombo) | |||
| 231 | wacom_report_rel(wcombo, REL_WHEEL, rw); | 245 | wacom_report_rel(wcombo, REL_WHEEL, rw); |
| 232 | wacom_report_key(wcombo, BTN_TOOL_FINGER, 0xf0); | 246 | wacom_report_key(wcombo, BTN_TOOL_FINGER, 0xf0); |
| 233 | wacom_report_abs(wcombo, ABS_MISC, wacom->id[1]); | 247 | wacom_report_abs(wcombo, ABS_MISC, wacom->id[1]); |
| 234 | if (!prox) | 248 | wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xf0); |
| 235 | wacom->id[1] = 0; | 249 | } else if (wacom->id[1]) { |
| 236 | wacom_report_abs(wcombo, ABS_MISC, wacom->id[1]); | 250 | if (penData) { |
| 251 | wacom_input_sync(wcombo); /* sync last event */ | ||
| 252 | if (!wacom->id[0]) | ||
| 253 | penData = 0; | ||
| 254 | } | ||
| 255 | wacom->id[1] = 0; | ||
| 256 | wacom_report_key(wcombo, BTN_0, (data[7] & 0x40)); | ||
| 257 | wacom_report_key(wcombo, BTN_4, (data[7] & 0x80)); | ||
| 258 | wacom_report_rel(wcombo, REL_WHEEL, 0); | ||
| 259 | wacom_report_key(wcombo, BTN_TOOL_FINGER, 0); | ||
| 260 | wacom_report_abs(wcombo, ABS_MISC, 0); | ||
| 237 | wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xf0); | 261 | wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xf0); |
| 238 | } | 262 | } |
| 239 | retval = 1; | ||
| 240 | break; | 263 | break; |
| 241 | case WACOM_MO: | 264 | case WACOM_MO: |
| 242 | prox = (data[7] & 0xf8) || data[8]; | 265 | if ((data[7] & 0xf8) || (data[8] & 0xff)) { |
| 243 | if (prox || wacom->id[1]) { | 266 | if (penData) { |
| 267 | wacom_input_sync(wcombo); /* sync last event */ | ||
| 268 | if (!wacom->id[0]) | ||
| 269 | penData = 0; | ||
| 270 | } | ||
| 244 | wacom->id[1] = PAD_DEVICE_ID; | 271 | wacom->id[1] = PAD_DEVICE_ID; |
| 245 | wacom_report_key(wcombo, BTN_0, (data[7] & 0x08)); | 272 | wacom_report_key(wcombo, BTN_0, (data[7] & 0x08)); |
| 246 | wacom_report_key(wcombo, BTN_1, (data[7] & 0x20)); | 273 | wacom_report_key(wcombo, BTN_1, (data[7] & 0x20)); |
| @@ -248,16 +275,27 @@ static int wacom_graphire_irq(struct wacom_wac *wacom, void *wcombo) | |||
| 248 | wacom_report_key(wcombo, BTN_5, (data[7] & 0x40)); | 275 | wacom_report_key(wcombo, BTN_5, (data[7] & 0x40)); |
| 249 | wacom_report_abs(wcombo, ABS_WHEEL, (data[8] & 0x7f)); | 276 | wacom_report_abs(wcombo, ABS_WHEEL, (data[8] & 0x7f)); |
| 250 | wacom_report_key(wcombo, BTN_TOOL_FINGER, 0xf0); | 277 | wacom_report_key(wcombo, BTN_TOOL_FINGER, 0xf0); |
| 251 | if (!prox) | ||
| 252 | wacom->id[1] = 0; | ||
| 253 | wacom_report_abs(wcombo, ABS_MISC, wacom->id[1]); | 278 | wacom_report_abs(wcombo, ABS_MISC, wacom->id[1]); |
| 254 | wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xf0); | 279 | wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xf0); |
| 280 | } else if (wacom->id[1]) { | ||
| 281 | if (penData) { | ||
| 282 | wacom_input_sync(wcombo); /* sync last event */ | ||
| 283 | if (!wacom->id[0]) | ||
| 284 | penData = 0; | ||
| 285 | } | ||
| 286 | wacom->id[1] = 0; | ||
| 287 | wacom_report_key(wcombo, BTN_0, (data[7] & 0x08)); | ||
| 288 | wacom_report_key(wcombo, BTN_1, (data[7] & 0x20)); | ||
| 289 | wacom_report_key(wcombo, BTN_4, (data[7] & 0x10)); | ||
| 290 | wacom_report_key(wcombo, BTN_5, (data[7] & 0x40)); | ||
| 291 | wacom_report_abs(wcombo, ABS_WHEEL, (data[8] & 0x7f)); | ||
| 292 | wacom_report_key(wcombo, BTN_TOOL_FINGER, 0); | ||
| 293 | wacom_report_abs(wcombo, ABS_MISC, 0); | ||
| 294 | wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xf0); | ||
| 255 | } | 295 | } |
| 256 | retval = 1; | ||
| 257 | break; | 296 | break; |
| 258 | } | 297 | } |
| 259 | exit: | 298 | return 1; |
| 260 | return retval; | ||
| 261 | } | 299 | } |
| 262 | 300 | ||
| 263 | static int wacom_intuos_inout(struct wacom_wac *wacom, void *wcombo) | 301 | static int wacom_intuos_inout(struct wacom_wac *wacom, void *wcombo) |
| @@ -598,9 +636,9 @@ static int wacom_intuos_irq(struct wacom_wac *wacom, void *wcombo) | |||
| 598 | static void wacom_tpc_finger_in(struct wacom_wac *wacom, void *wcombo, char *data, int idx) | 636 | static void wacom_tpc_finger_in(struct wacom_wac *wacom, void *wcombo, char *data, int idx) |
| 599 | { | 637 | { |
| 600 | wacom_report_abs(wcombo, ABS_X, | 638 | wacom_report_abs(wcombo, ABS_X, |
| 601 | data[2 + idx * 2] | ((data[3 + idx * 2] & 0x7f) << 8)); | 639 | (data[2 + idx * 2] & 0xff) | ((data[3 + idx * 2] & 0x7f) << 8)); |
| 602 | wacom_report_abs(wcombo, ABS_Y, | 640 | wacom_report_abs(wcombo, ABS_Y, |
| 603 | data[6 + idx * 2] | ((data[7 + idx * 2] & 0x7f) << 8)); | 641 | (data[6 + idx * 2] & 0xff) | ((data[7 + idx * 2] & 0x7f) << 8)); |
| 604 | wacom_report_abs(wcombo, ABS_MISC, wacom->id[0]); | 642 | wacom_report_abs(wcombo, ABS_MISC, wacom->id[0]); |
| 605 | wacom_report_key(wcombo, wacom->tool[idx], 1); | 643 | wacom_report_key(wcombo, wacom->tool[idx], 1); |
| 606 | if (idx) | 644 | if (idx) |
| @@ -744,24 +782,31 @@ static int wacom_tpc_irq(struct wacom_wac *wacom, void *wcombo) | |||
| 744 | 782 | ||
| 745 | touchInProx = 0; | 783 | touchInProx = 0; |
| 746 | 784 | ||
| 747 | if (!wacom->id[0]) { /* first in prox */ | 785 | if (prox) { /* in prox */ |
| 748 | /* Going into proximity select tool */ | 786 | if (!wacom->id[0]) { |
| 749 | wacom->tool[0] = (data[1] & 0x0c) ? BTN_TOOL_RUBBER : BTN_TOOL_PEN; | 787 | /* Going into proximity select tool */ |
| 750 | if (wacom->tool[0] == BTN_TOOL_PEN) | 788 | wacom->tool[0] = (data[1] & 0x0c) ? BTN_TOOL_RUBBER : BTN_TOOL_PEN; |
| 751 | wacom->id[0] = STYLUS_DEVICE_ID; | 789 | if (wacom->tool[0] == BTN_TOOL_PEN) |
| 752 | else | 790 | wacom->id[0] = STYLUS_DEVICE_ID; |
| 753 | wacom->id[0] = ERASER_DEVICE_ID; | 791 | else |
| 754 | } | 792 | wacom->id[0] = ERASER_DEVICE_ID; |
| 755 | wacom_report_key(wcombo, BTN_STYLUS, data[1] & 0x02); | 793 | } |
| 756 | wacom_report_key(wcombo, BTN_STYLUS2, data[1] & 0x10); | 794 | wacom_report_key(wcombo, BTN_STYLUS, data[1] & 0x02); |
| 757 | wacom_report_abs(wcombo, ABS_X, wacom_le16_to_cpu(&data[2])); | 795 | wacom_report_key(wcombo, BTN_STYLUS2, data[1] & 0x10); |
| 758 | wacom_report_abs(wcombo, ABS_Y, wacom_le16_to_cpu(&data[4])); | 796 | wacom_report_abs(wcombo, ABS_X, wacom_le16_to_cpu(&data[2])); |
| 759 | pressure = ((data[7] & 0x01) << 8) | data[6]; | 797 | wacom_report_abs(wcombo, ABS_Y, wacom_le16_to_cpu(&data[4])); |
| 760 | if (pressure < 0) | 798 | pressure = ((data[7] & 0x01) << 8) | data[6]; |
| 761 | pressure = features->pressure_max + pressure + 1; | 799 | if (pressure < 0) |
| 762 | wacom_report_abs(wcombo, ABS_PRESSURE, pressure); | 800 | pressure = features->pressure_max + pressure + 1; |
| 763 | wacom_report_key(wcombo, BTN_TOUCH, data[1] & 0x05); | 801 | wacom_report_abs(wcombo, ABS_PRESSURE, pressure); |
| 764 | if (!prox) { /* out-prox */ | 802 | wacom_report_key(wcombo, BTN_TOUCH, data[1] & 0x05); |
| 803 | } else { | ||
| 804 | wacom_report_abs(wcombo, ABS_X, 0); | ||
| 805 | wacom_report_abs(wcombo, ABS_Y, 0); | ||
| 806 | wacom_report_abs(wcombo, ABS_PRESSURE, 0); | ||
| 807 | wacom_report_key(wcombo, BTN_STYLUS, 0); | ||
| 808 | wacom_report_key(wcombo, BTN_STYLUS2, 0); | ||
| 809 | wacom_report_key(wcombo, BTN_TOUCH, 0); | ||
| 765 | wacom->id[0] = 0; | 810 | wacom->id[0] = 0; |
| 766 | /* pen is out so touch can be enabled now */ | 811 | /* pen is out so touch can be enabled now */ |
| 767 | touchInProx = 1; | 812 | touchInProx = 1; |
diff --git a/drivers/lguest/lguest_device.c b/drivers/lguest/lguest_device.c index 07090f379c63..69c84a1d88ea 100644 --- a/drivers/lguest/lguest_device.c +++ b/drivers/lguest/lguest_device.c | |||
| @@ -178,7 +178,7 @@ static void set_status(struct virtio_device *vdev, u8 status) | |||
| 178 | 178 | ||
| 179 | /* We set the status. */ | 179 | /* We set the status. */ |
| 180 | to_lgdev(vdev)->desc->status = status; | 180 | to_lgdev(vdev)->desc->status = status; |
| 181 | kvm_hypercall1(LHCALL_NOTIFY, (max_pfn << PAGE_SHIFT) + offset); | 181 | hcall(LHCALL_NOTIFY, (max_pfn << PAGE_SHIFT) + offset, 0, 0, 0); |
| 182 | } | 182 | } |
| 183 | 183 | ||
| 184 | static void lg_set_status(struct virtio_device *vdev, u8 status) | 184 | static void lg_set_status(struct virtio_device *vdev, u8 status) |
| @@ -229,7 +229,7 @@ static void lg_notify(struct virtqueue *vq) | |||
| 229 | */ | 229 | */ |
| 230 | struct lguest_vq_info *lvq = vq->priv; | 230 | struct lguest_vq_info *lvq = vq->priv; |
| 231 | 231 | ||
| 232 | kvm_hypercall1(LHCALL_NOTIFY, lvq->config.pfn << PAGE_SHIFT); | 232 | hcall(LHCALL_NOTIFY, lvq->config.pfn << PAGE_SHIFT, 0, 0, 0); |
| 233 | } | 233 | } |
| 234 | 234 | ||
| 235 | /* An extern declaration inside a C file is bad form. Don't do it. */ | 235 | /* An extern declaration inside a C file is bad form. Don't do it. */ |
diff --git a/drivers/lguest/x86/core.c b/drivers/lguest/x86/core.c index fb2b7ef7868e..b4eb675a807e 100644 --- a/drivers/lguest/x86/core.c +++ b/drivers/lguest/x86/core.c | |||
| @@ -288,6 +288,18 @@ static int emulate_insn(struct lg_cpu *cpu) | |||
| 288 | insn = lgread(cpu, physaddr, u8); | 288 | insn = lgread(cpu, physaddr, u8); |
| 289 | 289 | ||
| 290 | /* | 290 | /* |
| 291 | * Around 2.6.33, the kernel started using an emulation for the | ||
| 292 | * cmpxchg8b instruction in early boot on many configurations. This | ||
| 293 | * code isn't paravirtualized, and it tries to disable interrupts. | ||
| 294 | * Ignore it, which will Mostly Work. | ||
| 295 | */ | ||
| 296 | if (insn == 0xfa) { | ||
| 297 | /* "cli", or Clear Interrupt Enable instruction. Skip it. */ | ||
| 298 | cpu->regs->eip++; | ||
| 299 | return 1; | ||
| 300 | } | ||
| 301 | |||
| 302 | /* | ||
| 291 | * 0x66 is an "operand prefix". It means it's using the upper 16 bits | 303 | * 0x66 is an "operand prefix". It means it's using the upper 16 bits |
| 292 | * of the eax register. | 304 | * of the eax register. |
| 293 | */ | 305 | */ |
diff --git a/drivers/net/cnic.c b/drivers/net/cnic.c index 9781942992e9..4b451a7c03e9 100644 --- a/drivers/net/cnic.c +++ b/drivers/net/cnic.c | |||
| @@ -2334,13 +2334,13 @@ static int cnic_service_bnx2x(void *data, void *status_blk) | |||
| 2334 | struct cnic_local *cp = dev->cnic_priv; | 2334 | struct cnic_local *cp = dev->cnic_priv; |
| 2335 | u16 prod = cp->kcq_prod_idx & MAX_KCQ_IDX; | 2335 | u16 prod = cp->kcq_prod_idx & MAX_KCQ_IDX; |
| 2336 | 2336 | ||
| 2337 | prefetch(cp->status_blk.bnx2x); | 2337 | if (likely(test_bit(CNIC_F_CNIC_UP, &dev->flags))) { |
| 2338 | prefetch(&cp->kcq[KCQ_PG(prod)][KCQ_IDX(prod)]); | 2338 | prefetch(cp->status_blk.bnx2x); |
| 2339 | prefetch(&cp->kcq[KCQ_PG(prod)][KCQ_IDX(prod)]); | ||
| 2339 | 2340 | ||
| 2340 | if (likely(test_bit(CNIC_F_CNIC_UP, &dev->flags))) | ||
| 2341 | tasklet_schedule(&cp->cnic_irq_task); | 2341 | tasklet_schedule(&cp->cnic_irq_task); |
| 2342 | 2342 | cnic_chk_pkt_rings(cp); | |
| 2343 | cnic_chk_pkt_rings(cp); | 2343 | } |
| 2344 | 2344 | ||
| 2345 | return 0; | 2345 | return 0; |
| 2346 | } | 2346 | } |
diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c index cfd09cea7214..73d43c53015a 100644 --- a/drivers/net/e1000e/netdev.c +++ b/drivers/net/e1000e/netdev.c | |||
| @@ -661,6 +661,8 @@ static bool e1000_clean_tx_irq(struct e1000_adapter *adapter) | |||
| 661 | i = 0; | 661 | i = 0; |
| 662 | } | 662 | } |
| 663 | 663 | ||
| 664 | if (i == tx_ring->next_to_use) | ||
| 665 | break; | ||
| 664 | eop = tx_ring->buffer_info[i].next_to_watch; | 666 | eop = tx_ring->buffer_info[i].next_to_watch; |
| 665 | eop_desc = E1000_TX_DESC(*tx_ring, eop); | 667 | eop_desc = E1000_TX_DESC(*tx_ring, eop); |
| 666 | } | 668 | } |
diff --git a/drivers/net/igb/igb_ethtool.c b/drivers/net/igb/igb_ethtool.c index d313fae992da..743038490104 100644 --- a/drivers/net/igb/igb_ethtool.c +++ b/drivers/net/igb/igb_ethtool.c | |||
| @@ -1814,6 +1814,7 @@ static int igb_wol_exclusion(struct igb_adapter *adapter, | |||
| 1814 | retval = 0; | 1814 | retval = 0; |
| 1815 | break; | 1815 | break; |
| 1816 | case E1000_DEV_ID_82576_QUAD_COPPER: | 1816 | case E1000_DEV_ID_82576_QUAD_COPPER: |
| 1817 | case E1000_DEV_ID_82576_QUAD_COPPER_ET2: | ||
| 1817 | /* quad port adapters only support WoL on port A */ | 1818 | /* quad port adapters only support WoL on port A */ |
| 1818 | if (!(adapter->flags & IGB_FLAG_QUAD_PORT_A)) { | 1819 | if (!(adapter->flags & IGB_FLAG_QUAD_PORT_A)) { |
| 1819 | wol->supported = 0; | 1820 | wol->supported = 0; |
diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index 9b3c51ab1758..c9baa2aa98cd 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c | |||
| @@ -1612,6 +1612,7 @@ static int __devinit igb_probe(struct pci_dev *pdev, | |||
| 1612 | adapter->eeprom_wol = 0; | 1612 | adapter->eeprom_wol = 0; |
| 1613 | break; | 1613 | break; |
| 1614 | case E1000_DEV_ID_82576_QUAD_COPPER: | 1614 | case E1000_DEV_ID_82576_QUAD_COPPER: |
| 1615 | case E1000_DEV_ID_82576_QUAD_COPPER_ET2: | ||
| 1615 | /* if quad port adapter, disable WoL on all but port A */ | 1616 | /* if quad port adapter, disable WoL on all but port A */ |
| 1616 | if (global_quad_port_a != 0) | 1617 | if (global_quad_port_a != 0) |
| 1617 | adapter->eeprom_wol = 0; | 1618 | adapter->eeprom_wol = 0; |
diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c index 471887742b02..ecde0876a785 100644 --- a/drivers/net/myri10ge/myri10ge.c +++ b/drivers/net/myri10ge/myri10ge.c | |||
| @@ -1690,7 +1690,7 @@ myri10ge_set_pauseparam(struct net_device *netdev, | |||
| 1690 | if (pause->tx_pause != mgp->pause) | 1690 | if (pause->tx_pause != mgp->pause) |
| 1691 | return myri10ge_change_pause(mgp, pause->tx_pause); | 1691 | return myri10ge_change_pause(mgp, pause->tx_pause); |
| 1692 | if (pause->rx_pause != mgp->pause) | 1692 | if (pause->rx_pause != mgp->pause) |
| 1693 | return myri10ge_change_pause(mgp, pause->tx_pause); | 1693 | return myri10ge_change_pause(mgp, pause->rx_pause); |
| 1694 | if (pause->autoneg != 0) | 1694 | if (pause->autoneg != 0) |
| 1695 | return -EINVAL; | 1695 | return -EINVAL; |
| 1696 | return 0; | 1696 | return 0; |
diff --git a/drivers/net/pcmcia/smc91c92_cs.c b/drivers/net/pcmcia/smc91c92_cs.c index ff7eb9116b6a..fd9d6e34fda4 100644 --- a/drivers/net/pcmcia/smc91c92_cs.c +++ b/drivers/net/pcmcia/smc91c92_cs.c | |||
| @@ -1608,9 +1608,12 @@ static void set_rx_mode(struct net_device *dev) | |||
| 1608 | { | 1608 | { |
| 1609 | unsigned int ioaddr = dev->base_addr; | 1609 | unsigned int ioaddr = dev->base_addr; |
| 1610 | struct smc_private *smc = netdev_priv(dev); | 1610 | struct smc_private *smc = netdev_priv(dev); |
| 1611 | u_int multicast_table[ 2 ] = { 0, }; | 1611 | unsigned char multicast_table[8]; |
| 1612 | unsigned long flags; | 1612 | unsigned long flags; |
| 1613 | u_short rx_cfg_setting; | 1613 | u_short rx_cfg_setting; |
| 1614 | int i; | ||
| 1615 | |||
| 1616 | memset(multicast_table, 0, sizeof(multicast_table)); | ||
| 1614 | 1617 | ||
| 1615 | if (dev->flags & IFF_PROMISC) { | 1618 | if (dev->flags & IFF_PROMISC) { |
| 1616 | rx_cfg_setting = RxStripCRC | RxEnable | RxPromisc | RxAllMulti; | 1619 | rx_cfg_setting = RxStripCRC | RxEnable | RxPromisc | RxAllMulti; |
| @@ -1622,10 +1625,6 @@ static void set_rx_mode(struct net_device *dev) | |||
| 1622 | 1625 | ||
| 1623 | netdev_for_each_mc_addr(mc_addr, dev) { | 1626 | netdev_for_each_mc_addr(mc_addr, dev) { |
| 1624 | u_int position = ether_crc(6, mc_addr->dmi_addr); | 1627 | u_int position = ether_crc(6, mc_addr->dmi_addr); |
| 1625 | #ifndef final_version /* Verify multicast address. */ | ||
| 1626 | if ((mc_addr->dmi_addr[0] & 1) == 0) | ||
| 1627 | continue; | ||
| 1628 | #endif | ||
| 1629 | multicast_table[position >> 29] |= 1 << ((position >> 26) & 7); | 1628 | multicast_table[position >> 29] |= 1 << ((position >> 26) & 7); |
| 1630 | } | 1629 | } |
| 1631 | } | 1630 | } |
| @@ -1635,8 +1634,8 @@ static void set_rx_mode(struct net_device *dev) | |||
| 1635 | /* Load MC table and Rx setting into the chip without interrupts. */ | 1634 | /* Load MC table and Rx setting into the chip without interrupts. */ |
| 1636 | spin_lock_irqsave(&smc->lock, flags); | 1635 | spin_lock_irqsave(&smc->lock, flags); |
| 1637 | SMC_SELECT_BANK(3); | 1636 | SMC_SELECT_BANK(3); |
| 1638 | outl(multicast_table[0], ioaddr + MULTICAST0); | 1637 | for (i = 0; i < 8; i++) |
| 1639 | outl(multicast_table[1], ioaddr + MULTICAST4); | 1638 | outb(multicast_table[i], ioaddr + MULTICAST0 + i); |
| 1640 | SMC_SELECT_BANK(0); | 1639 | SMC_SELECT_BANK(0); |
| 1641 | outw(rx_cfg_setting, ioaddr + RCR); | 1640 | outw(rx_cfg_setting, ioaddr + RCR); |
| 1642 | SMC_SELECT_BANK(2); | 1641 | SMC_SELECT_BANK(2); |
diff --git a/drivers/net/qlcnic/qlcnic_hw.c b/drivers/net/qlcnic/qlcnic_hw.c index a6ef266a2fe2..e73ba455aa20 100644 --- a/drivers/net/qlcnic/qlcnic_hw.c +++ b/drivers/net/qlcnic/qlcnic_hw.c | |||
| @@ -431,6 +431,9 @@ void qlcnic_set_multi(struct net_device *netdev) | |||
| 431 | u8 bcast_addr[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; | 431 | u8 bcast_addr[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; |
| 432 | u32 mode = VPORT_MISS_MODE_DROP; | 432 | u32 mode = VPORT_MISS_MODE_DROP; |
| 433 | 433 | ||
| 434 | if (adapter->is_up != QLCNIC_ADAPTER_UP_MAGIC) | ||
| 435 | return; | ||
| 436 | |||
| 434 | qlcnic_nic_add_mac(adapter, adapter->mac_addr); | 437 | qlcnic_nic_add_mac(adapter, adapter->mac_addr); |
| 435 | qlcnic_nic_add_mac(adapter, bcast_addr); | 438 | qlcnic_nic_add_mac(adapter, bcast_addr); |
| 436 | 439 | ||
diff --git a/drivers/net/r6040.c b/drivers/net/r6040.c index 43afdb6b25e6..0298d8c1dcb6 100644 --- a/drivers/net/r6040.c +++ b/drivers/net/r6040.c | |||
| @@ -134,7 +134,7 @@ | |||
| 134 | #define RX_DESC_SIZE (RX_DCNT * sizeof(struct r6040_descriptor)) | 134 | #define RX_DESC_SIZE (RX_DCNT * sizeof(struct r6040_descriptor)) |
| 135 | #define TX_DESC_SIZE (TX_DCNT * sizeof(struct r6040_descriptor)) | 135 | #define TX_DESC_SIZE (TX_DCNT * sizeof(struct r6040_descriptor)) |
| 136 | #define MBCR_DEFAULT 0x012A /* MAC Bus Control Register */ | 136 | #define MBCR_DEFAULT 0x012A /* MAC Bus Control Register */ |
| 137 | #define MCAST_MAX 4 /* Max number multicast addresses to filter */ | 137 | #define MCAST_MAX 3 /* Max number multicast addresses to filter */ |
| 138 | 138 | ||
| 139 | /* Descriptor status */ | 139 | /* Descriptor status */ |
| 140 | #define DSC_OWNER_MAC 0x8000 /* MAC is the owner of this descriptor */ | 140 | #define DSC_OWNER_MAC 0x8000 /* MAC is the owner of this descriptor */ |
| @@ -982,9 +982,6 @@ static void r6040_multicast_list(struct net_device *dev) | |||
| 982 | crc >>= 26; | 982 | crc >>= 26; |
| 983 | hash_table[crc >> 4] |= 1 << (15 - (crc & 0xf)); | 983 | hash_table[crc >> 4] |= 1 << (15 - (crc & 0xf)); |
| 984 | } | 984 | } |
| 985 | /* Write the index of the hash table */ | ||
| 986 | for (i = 0; i < 4; i++) | ||
| 987 | iowrite16(hash_table[i] << 14, ioaddr + MCR1); | ||
| 988 | /* Fill the MAC hash tables with their values */ | 985 | /* Fill the MAC hash tables with their values */ |
| 989 | iowrite16(hash_table[0], ioaddr + MAR0); | 986 | iowrite16(hash_table[0], ioaddr + MAR0); |
| 990 | iowrite16(hash_table[1], ioaddr + MAR1); | 987 | iowrite16(hash_table[1], ioaddr + MAR1); |
| @@ -1000,9 +997,9 @@ static void r6040_multicast_list(struct net_device *dev) | |||
| 1000 | iowrite16(adrp[1], ioaddr + MID_1M + 8 * i); | 997 | iowrite16(adrp[1], ioaddr + MID_1M + 8 * i); |
| 1001 | iowrite16(adrp[2], ioaddr + MID_1H + 8 * i); | 998 | iowrite16(adrp[2], ioaddr + MID_1H + 8 * i); |
| 1002 | } else { | 999 | } else { |
| 1003 | iowrite16(0xffff, ioaddr + MID_0L + 8 * i); | 1000 | iowrite16(0xffff, ioaddr + MID_1L + 8 * i); |
| 1004 | iowrite16(0xffff, ioaddr + MID_0M + 8 * i); | 1001 | iowrite16(0xffff, ioaddr + MID_1M + 8 * i); |
| 1005 | iowrite16(0xffff, ioaddr + MID_0H + 8 * i); | 1002 | iowrite16(0xffff, ioaddr + MID_1H + 8 * i); |
| 1006 | } | 1003 | } |
| 1007 | i++; | 1004 | i++; |
| 1008 | } | 1005 | } |
diff --git a/drivers/net/stmmac/stmmac_main.c b/drivers/net/stmmac/stmmac_main.c index a214a1627e8b..4111a85ec80e 100644 --- a/drivers/net/stmmac/stmmac_main.c +++ b/drivers/net/stmmac/stmmac_main.c | |||
| @@ -1686,7 +1686,7 @@ static int stmmac_dvr_probe(struct platform_device *pdev) | |||
| 1686 | } | 1686 | } |
| 1687 | pr_info("done!\n"); | 1687 | pr_info("done!\n"); |
| 1688 | 1688 | ||
| 1689 | if (!request_mem_region(res->start, (res->end - res->start), | 1689 | if (!request_mem_region(res->start, resource_size(res), |
| 1690 | pdev->name)) { | 1690 | pdev->name)) { |
| 1691 | pr_err("%s: ERROR: memory allocation failed" | 1691 | pr_err("%s: ERROR: memory allocation failed" |
| 1692 | "cannot get the I/O addr 0x%x\n", | 1692 | "cannot get the I/O addr 0x%x\n", |
| @@ -1695,9 +1695,9 @@ static int stmmac_dvr_probe(struct platform_device *pdev) | |||
| 1695 | goto out; | 1695 | goto out; |
| 1696 | } | 1696 | } |
| 1697 | 1697 | ||
| 1698 | addr = ioremap(res->start, (res->end - res->start)); | 1698 | addr = ioremap(res->start, resource_size(res)); |
| 1699 | if (!addr) { | 1699 | if (!addr) { |
| 1700 | pr_err("%s: ERROR: memory mapping failed \n", __func__); | 1700 | pr_err("%s: ERROR: memory mapping failed\n", __func__); |
| 1701 | ret = -ENOMEM; | 1701 | ret = -ENOMEM; |
| 1702 | goto out; | 1702 | goto out; |
| 1703 | } | 1703 | } |
| @@ -1775,7 +1775,7 @@ static int stmmac_dvr_probe(struct platform_device *pdev) | |||
| 1775 | out: | 1775 | out: |
| 1776 | if (ret < 0) { | 1776 | if (ret < 0) { |
| 1777 | platform_set_drvdata(pdev, NULL); | 1777 | platform_set_drvdata(pdev, NULL); |
| 1778 | release_mem_region(res->start, (res->end - res->start)); | 1778 | release_mem_region(res->start, resource_size(res)); |
| 1779 | if (addr != NULL) | 1779 | if (addr != NULL) |
| 1780 | iounmap(addr); | 1780 | iounmap(addr); |
| 1781 | } | 1781 | } |
| @@ -1813,7 +1813,7 @@ static int stmmac_dvr_remove(struct platform_device *pdev) | |||
| 1813 | 1813 | ||
| 1814 | iounmap((void *)ndev->base_addr); | 1814 | iounmap((void *)ndev->base_addr); |
| 1815 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 1815 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
| 1816 | release_mem_region(res->start, (res->end - res->start)); | 1816 | release_mem_region(res->start, resource_size(res)); |
| 1817 | 1817 | ||
| 1818 | free_netdev(ndev); | 1818 | free_netdev(ndev); |
| 1819 | 1819 | ||
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index 6fb783ce20b9..b0577dd1a42d 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c | |||
| @@ -327,6 +327,7 @@ static int add_recvbuf_small(struct virtnet_info *vi, gfp_t gfp) | |||
| 327 | struct scatterlist sg[2]; | 327 | struct scatterlist sg[2]; |
| 328 | int err; | 328 | int err; |
| 329 | 329 | ||
| 330 | sg_init_table(sg, 2); | ||
| 330 | skb = netdev_alloc_skb_ip_align(vi->dev, MAX_PACKET_LEN); | 331 | skb = netdev_alloc_skb_ip_align(vi->dev, MAX_PACKET_LEN); |
| 331 | if (unlikely(!skb)) | 332 | if (unlikely(!skb)) |
| 332 | return -ENOMEM; | 333 | return -ENOMEM; |
| @@ -352,6 +353,7 @@ static int add_recvbuf_big(struct virtnet_info *vi, gfp_t gfp) | |||
| 352 | char *p; | 353 | char *p; |
| 353 | int i, err, offset; | 354 | int i, err, offset; |
| 354 | 355 | ||
| 356 | sg_init_table(sg, MAX_SKB_FRAGS + 2); | ||
| 355 | /* page in sg[MAX_SKB_FRAGS + 1] is list tail */ | 357 | /* page in sg[MAX_SKB_FRAGS + 1] is list tail */ |
| 356 | for (i = MAX_SKB_FRAGS + 1; i > 1; --i) { | 358 | for (i = MAX_SKB_FRAGS + 1; i > 1; --i) { |
| 357 | first = get_a_page(vi, gfp); | 359 | first = get_a_page(vi, gfp); |
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 67ca4e5a6017..115e1aeedb59 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c | |||
| @@ -1532,8 +1532,7 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed) | |||
| 1532 | all_wiphys_idle = ath9k_all_wiphys_idle(sc); | 1532 | all_wiphys_idle = ath9k_all_wiphys_idle(sc); |
| 1533 | ath9k_set_wiphy_idle(aphy, idle); | 1533 | ath9k_set_wiphy_idle(aphy, idle); |
| 1534 | 1534 | ||
| 1535 | if (!idle && all_wiphys_idle) | 1535 | enable_radio = (!idle && all_wiphys_idle); |
| 1536 | enable_radio = true; | ||
| 1537 | 1536 | ||
| 1538 | /* | 1537 | /* |
| 1539 | * After we unlock here its possible another wiphy | 1538 | * After we unlock here its possible another wiphy |
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index 83c52a682622..8972166386cb 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c | |||
| @@ -2015,7 +2015,9 @@ static void iwl4965_rx_reply_tx(struct iwl_priv *priv, | |||
| 2015 | IWL_DEBUG_TX_REPLY(priv, "Retry scheduler reclaim scd_ssn " | 2015 | IWL_DEBUG_TX_REPLY(priv, "Retry scheduler reclaim scd_ssn " |
| 2016 | "%d index %d\n", scd_ssn , index); | 2016 | "%d index %d\n", scd_ssn , index); |
| 2017 | freed = iwl_tx_queue_reclaim(priv, txq_id, index); | 2017 | freed = iwl_tx_queue_reclaim(priv, txq_id, index); |
| 2018 | iwl_free_tfds_in_queue(priv, sta_id, tid, freed); | 2018 | if (qc) |
| 2019 | iwl_free_tfds_in_queue(priv, sta_id, | ||
| 2020 | tid, freed); | ||
| 2019 | 2021 | ||
| 2020 | if (priv->mac80211_registered && | 2022 | if (priv->mac80211_registered && |
| 2021 | (iwl_queue_space(&txq->q) > txq->q.low_mark) && | 2023 | (iwl_queue_space(&txq->q) > txq->q.low_mark) && |
| @@ -2041,14 +2043,17 @@ static void iwl4965_rx_reply_tx(struct iwl_priv *priv, | |||
| 2041 | tx_resp->failure_frame); | 2043 | tx_resp->failure_frame); |
| 2042 | 2044 | ||
| 2043 | freed = iwl_tx_queue_reclaim(priv, txq_id, index); | 2045 | freed = iwl_tx_queue_reclaim(priv, txq_id, index); |
| 2044 | iwl_free_tfds_in_queue(priv, sta_id, tid, freed); | 2046 | if (qc && likely(sta_id != IWL_INVALID_STATION)) |
| 2047 | iwl_free_tfds_in_queue(priv, sta_id, tid, freed); | ||
| 2048 | else if (sta_id == IWL_INVALID_STATION) | ||
| 2049 | IWL_DEBUG_TX_REPLY(priv, "Station not known\n"); | ||
| 2045 | 2050 | ||
| 2046 | if (priv->mac80211_registered && | 2051 | if (priv->mac80211_registered && |
| 2047 | (iwl_queue_space(&txq->q) > txq->q.low_mark)) | 2052 | (iwl_queue_space(&txq->q) > txq->q.low_mark)) |
| 2048 | iwl_wake_queue(priv, txq_id); | 2053 | iwl_wake_queue(priv, txq_id); |
| 2049 | } | 2054 | } |
| 2050 | 2055 | if (qc && likely(sta_id != IWL_INVALID_STATION)) | |
| 2051 | iwl_txq_check_empty(priv, sta_id, tid, txq_id); | 2056 | iwl_txq_check_empty(priv, sta_id, tid, txq_id); |
| 2052 | 2057 | ||
| 2053 | if (iwl_check_bits(status, TX_ABORT_REQUIRED_MSK)) | 2058 | if (iwl_check_bits(status, TX_ABORT_REQUIRED_MSK)) |
| 2054 | IWL_ERR(priv, "TODO: Implement Tx ABORT REQUIRED!!!\n"); | 2059 | IWL_ERR(priv, "TODO: Implement Tx ABORT REQUIRED!!!\n"); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index 35f819ac87a3..1460116d329f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c | |||
| @@ -346,6 +346,17 @@ static inline int get_num_of_ant_from_rate(u32 rate_n_flags) | |||
| 346 | !!(rate_n_flags & RATE_MCS_ANT_C_MSK); | 346 | !!(rate_n_flags & RATE_MCS_ANT_C_MSK); |
| 347 | } | 347 | } |
| 348 | 348 | ||
| 349 | /* | ||
| 350 | * Static function to get the expected throughput from an iwl_scale_tbl_info | ||
| 351 | * that wraps a NULL pointer check | ||
| 352 | */ | ||
| 353 | static s32 get_expected_tpt(struct iwl_scale_tbl_info *tbl, int rs_index) | ||
| 354 | { | ||
| 355 | if (tbl->expected_tpt) | ||
| 356 | return tbl->expected_tpt[rs_index]; | ||
| 357 | return 0; | ||
| 358 | } | ||
| 359 | |||
| 349 | /** | 360 | /** |
| 350 | * rs_collect_tx_data - Update the success/failure sliding window | 361 | * rs_collect_tx_data - Update the success/failure sliding window |
| 351 | * | 362 | * |
| @@ -353,19 +364,21 @@ static inline int get_num_of_ant_from_rate(u32 rate_n_flags) | |||
| 353 | * at this rate. window->data contains the bitmask of successful | 364 | * at this rate. window->data contains the bitmask of successful |
| 354 | * packets. | 365 | * packets. |
| 355 | */ | 366 | */ |
| 356 | static int rs_collect_tx_data(struct iwl_rate_scale_data *windows, | 367 | static int rs_collect_tx_data(struct iwl_scale_tbl_info *tbl, |
| 357 | int scale_index, s32 tpt, int attempts, | 368 | int scale_index, int attempts, int successes) |
| 358 | int successes) | ||
| 359 | { | 369 | { |
| 360 | struct iwl_rate_scale_data *window = NULL; | 370 | struct iwl_rate_scale_data *window = NULL; |
| 361 | static const u64 mask = (((u64)1) << (IWL_RATE_MAX_WINDOW - 1)); | 371 | static const u64 mask = (((u64)1) << (IWL_RATE_MAX_WINDOW - 1)); |
| 362 | s32 fail_count; | 372 | s32 fail_count, tpt; |
| 363 | 373 | ||
| 364 | if (scale_index < 0 || scale_index >= IWL_RATE_COUNT) | 374 | if (scale_index < 0 || scale_index >= IWL_RATE_COUNT) |
| 365 | return -EINVAL; | 375 | return -EINVAL; |
| 366 | 376 | ||
| 367 | /* Select window for current tx bit rate */ | 377 | /* Select window for current tx bit rate */ |
| 368 | window = &(windows[scale_index]); | 378 | window = &(tbl->win[scale_index]); |
| 379 | |||
| 380 | /* Get expected throughput */ | ||
| 381 | tpt = get_expected_tpt(tbl, scale_index); | ||
| 369 | 382 | ||
| 370 | /* | 383 | /* |
| 371 | * Keep track of only the latest 62 tx frame attempts in this rate's | 384 | * Keep track of only the latest 62 tx frame attempts in this rate's |
| @@ -739,16 +752,6 @@ static bool table_type_matches(struct iwl_scale_tbl_info *a, | |||
| 739 | return (a->lq_type == b->lq_type) && (a->ant_type == b->ant_type) && | 752 | return (a->lq_type == b->lq_type) && (a->ant_type == b->ant_type) && |
| 740 | (a->is_SGI == b->is_SGI); | 753 | (a->is_SGI == b->is_SGI); |
| 741 | } | 754 | } |
| 742 | /* | ||
| 743 | * Static function to get the expected throughput from an iwl_scale_tbl_info | ||
| 744 | * that wraps a NULL pointer check | ||
| 745 | */ | ||
| 746 | static s32 get_expected_tpt(struct iwl_scale_tbl_info *tbl, int rs_index) | ||
| 747 | { | ||
| 748 | if (tbl->expected_tpt) | ||
| 749 | return tbl->expected_tpt[rs_index]; | ||
| 750 | return 0; | ||
| 751 | } | ||
| 752 | 755 | ||
| 753 | /* | 756 | /* |
| 754 | * mac80211 sends us Tx status | 757 | * mac80211 sends us Tx status |
| @@ -765,12 +768,10 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband, | |||
| 765 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | 768 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; |
| 766 | struct iwl_priv *priv = (struct iwl_priv *)priv_r; | 769 | struct iwl_priv *priv = (struct iwl_priv *)priv_r; |
| 767 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 770 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
| 768 | struct iwl_rate_scale_data *window = NULL; | ||
| 769 | enum mac80211_rate_control_flags mac_flags; | 771 | enum mac80211_rate_control_flags mac_flags; |
| 770 | u32 tx_rate; | 772 | u32 tx_rate; |
| 771 | struct iwl_scale_tbl_info tbl_type; | 773 | struct iwl_scale_tbl_info tbl_type; |
| 772 | struct iwl_scale_tbl_info *curr_tbl, *other_tbl; | 774 | struct iwl_scale_tbl_info *curr_tbl, *other_tbl, *tmp_tbl; |
| 773 | s32 tpt = 0; | ||
| 774 | 775 | ||
| 775 | IWL_DEBUG_RATE_LIMIT(priv, "get frame ack response, update rate scale window\n"); | 776 | IWL_DEBUG_RATE_LIMIT(priv, "get frame ack response, update rate scale window\n"); |
| 776 | 777 | ||
| @@ -853,7 +854,6 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband, | |||
| 853 | IWL_DEBUG_RATE(priv, "Neither active nor search matches tx rate\n"); | 854 | IWL_DEBUG_RATE(priv, "Neither active nor search matches tx rate\n"); |
| 854 | return; | 855 | return; |
| 855 | } | 856 | } |
| 856 | window = (struct iwl_rate_scale_data *)&(curr_tbl->win[0]); | ||
| 857 | 857 | ||
| 858 | /* | 858 | /* |
| 859 | * Updating the frame history depends on whether packets were | 859 | * Updating the frame history depends on whether packets were |
| @@ -866,8 +866,7 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband, | |||
| 866 | tx_rate = le32_to_cpu(table->rs_table[0].rate_n_flags); | 866 | tx_rate = le32_to_cpu(table->rs_table[0].rate_n_flags); |
| 867 | rs_get_tbl_info_from_mcs(tx_rate, priv->band, &tbl_type, | 867 | rs_get_tbl_info_from_mcs(tx_rate, priv->band, &tbl_type, |
| 868 | &rs_index); | 868 | &rs_index); |
| 869 | tpt = get_expected_tpt(curr_tbl, rs_index); | 869 | rs_collect_tx_data(curr_tbl, rs_index, |
| 870 | rs_collect_tx_data(window, rs_index, tpt, | ||
| 871 | info->status.ampdu_ack_len, | 870 | info->status.ampdu_ack_len, |
| 872 | info->status.ampdu_ack_map); | 871 | info->status.ampdu_ack_map); |
| 873 | 872 | ||
| @@ -897,19 +896,13 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband, | |||
| 897 | * table as active/search. | 896 | * table as active/search. |
| 898 | */ | 897 | */ |
| 899 | if (table_type_matches(&tbl_type, curr_tbl)) | 898 | if (table_type_matches(&tbl_type, curr_tbl)) |
| 900 | tpt = get_expected_tpt(curr_tbl, rs_index); | 899 | tmp_tbl = curr_tbl; |
| 901 | else if (table_type_matches(&tbl_type, other_tbl)) | 900 | else if (table_type_matches(&tbl_type, other_tbl)) |
| 902 | tpt = get_expected_tpt(other_tbl, rs_index); | 901 | tmp_tbl = other_tbl; |
| 903 | else | 902 | else |
| 904 | continue; | 903 | continue; |
| 905 | 904 | rs_collect_tx_data(tmp_tbl, rs_index, 1, | |
| 906 | /* Constants mean 1 transmission, 0 successes */ | 905 | i < retries ? 0 : legacy_success); |
| 907 | if (i < retries) | ||
| 908 | rs_collect_tx_data(window, rs_index, tpt, 1, | ||
| 909 | 0); | ||
| 910 | else | ||
| 911 | rs_collect_tx_data(window, rs_index, tpt, 1, | ||
| 912 | legacy_success); | ||
| 913 | } | 906 | } |
| 914 | 907 | ||
| 915 | /* Update success/fail counts if not searching for new mode */ | 908 | /* Update success/fail counts if not searching for new mode */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index db050b811232..3352f7086632 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c | |||
| @@ -308,10 +308,13 @@ int iwl_hw_nic_init(struct iwl_priv *priv) | |||
| 308 | 308 | ||
| 309 | spin_unlock_irqrestore(&priv->lock, flags); | 309 | spin_unlock_irqrestore(&priv->lock, flags); |
| 310 | 310 | ||
| 311 | /* Allocate and init all Tx and Command queues */ | 311 | /* Allocate or reset and init all Tx and Command queues */ |
| 312 | ret = iwl_txq_ctx_reset(priv); | 312 | if (!priv->txq) { |
| 313 | if (ret) | 313 | ret = iwl_txq_ctx_alloc(priv); |
| 314 | return ret; | 314 | if (ret) |
| 315 | return ret; | ||
| 316 | } else | ||
| 317 | iwl_txq_ctx_reset(priv); | ||
| 315 | 318 | ||
| 316 | set_bit(STATUS_INIT, &priv->status); | 319 | set_bit(STATUS_INIT, &priv->status); |
| 317 | 320 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 4ef7739f9e8e..732590f5fe30 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h | |||
| @@ -442,7 +442,8 @@ void iwl_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb); | |||
| 442 | /***************************************************** | 442 | /***************************************************** |
| 443 | * TX | 443 | * TX |
| 444 | ******************************************************/ | 444 | ******************************************************/ |
| 445 | int iwl_txq_ctx_reset(struct iwl_priv *priv); | 445 | int iwl_txq_ctx_alloc(struct iwl_priv *priv); |
| 446 | void iwl_txq_ctx_reset(struct iwl_priv *priv); | ||
| 446 | void iwl_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq); | 447 | void iwl_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq); |
| 447 | int iwl_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv, | 448 | int iwl_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv, |
| 448 | struct iwl_tx_queue *txq, | 449 | struct iwl_tx_queue *txq, |
| @@ -456,6 +457,8 @@ void iwl_free_tfds_in_queue(struct iwl_priv *priv, | |||
| 456 | void iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq); | 457 | void iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq); |
| 457 | int iwl_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq, | 458 | int iwl_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq, |
| 458 | int slots_num, u32 txq_id); | 459 | int slots_num, u32 txq_id); |
| 460 | void iwl_tx_queue_reset(struct iwl_priv *priv, struct iwl_tx_queue *txq, | ||
| 461 | int slots_num, u32 txq_id); | ||
| 459 | void iwl_tx_queue_free(struct iwl_priv *priv, int txq_id); | 462 | void iwl_tx_queue_free(struct iwl_priv *priv, int txq_id); |
| 460 | int iwl_tx_agg_start(struct iwl_priv *priv, const u8 *ra, u16 tid, u16 *ssn); | 463 | int iwl_tx_agg_start(struct iwl_priv *priv, const u8 *ra, u16 tid, u16 *ssn); |
| 461 | int iwl_tx_agg_stop(struct iwl_priv *priv , const u8 *ra, u16 tid); | 464 | int iwl_tx_agg_stop(struct iwl_priv *priv , const u8 *ra, u16 tid); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c index f0b7e6cfbe4f..8dd0c036d547 100644 --- a/drivers/net/wireless/iwlwifi/iwl-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-tx.c | |||
| @@ -194,10 +194,34 @@ void iwl_cmd_queue_free(struct iwl_priv *priv) | |||
| 194 | struct iwl_queue *q = &txq->q; | 194 | struct iwl_queue *q = &txq->q; |
| 195 | struct device *dev = &priv->pci_dev->dev; | 195 | struct device *dev = &priv->pci_dev->dev; |
| 196 | int i; | 196 | int i; |
| 197 | bool huge = false; | ||
| 197 | 198 | ||
| 198 | if (q->n_bd == 0) | 199 | if (q->n_bd == 0) |
| 199 | return; | 200 | return; |
| 200 | 201 | ||
| 202 | for (; q->read_ptr != q->write_ptr; | ||
| 203 | q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) { | ||
| 204 | /* we have no way to tell if it is a huge cmd ATM */ | ||
| 205 | i = get_cmd_index(q, q->read_ptr, 0); | ||
| 206 | |||
| 207 | if (txq->meta[i].flags & CMD_SIZE_HUGE) { | ||
| 208 | huge = true; | ||
| 209 | continue; | ||
| 210 | } | ||
| 211 | |||
| 212 | pci_unmap_single(priv->pci_dev, | ||
| 213 | pci_unmap_addr(&txq->meta[i], mapping), | ||
| 214 | pci_unmap_len(&txq->meta[i], len), | ||
| 215 | PCI_DMA_BIDIRECTIONAL); | ||
| 216 | } | ||
| 217 | if (huge) { | ||
| 218 | i = q->n_window; | ||
| 219 | pci_unmap_single(priv->pci_dev, | ||
| 220 | pci_unmap_addr(&txq->meta[i], mapping), | ||
| 221 | pci_unmap_len(&txq->meta[i], len), | ||
| 222 | PCI_DMA_BIDIRECTIONAL); | ||
| 223 | } | ||
| 224 | |||
| 201 | /* De-alloc array of command/tx buffers */ | 225 | /* De-alloc array of command/tx buffers */ |
| 202 | for (i = 0; i <= TFD_CMD_SLOTS; i++) | 226 | for (i = 0; i <= TFD_CMD_SLOTS; i++) |
| 203 | kfree(txq->cmd[i]); | 227 | kfree(txq->cmd[i]); |
| @@ -410,6 +434,26 @@ out_free_arrays: | |||
| 410 | } | 434 | } |
| 411 | EXPORT_SYMBOL(iwl_tx_queue_init); | 435 | EXPORT_SYMBOL(iwl_tx_queue_init); |
| 412 | 436 | ||
| 437 | void iwl_tx_queue_reset(struct iwl_priv *priv, struct iwl_tx_queue *txq, | ||
| 438 | int slots_num, u32 txq_id) | ||
| 439 | { | ||
| 440 | int actual_slots = slots_num; | ||
| 441 | |||
| 442 | if (txq_id == IWL_CMD_QUEUE_NUM) | ||
| 443 | actual_slots++; | ||
| 444 | |||
| 445 | memset(txq->meta, 0, sizeof(struct iwl_cmd_meta) * actual_slots); | ||
| 446 | |||
| 447 | txq->need_update = 0; | ||
| 448 | |||
| 449 | /* Initialize queue's high/low-water marks, and head/tail indexes */ | ||
| 450 | iwl_queue_init(priv, &txq->q, TFD_QUEUE_SIZE_MAX, slots_num, txq_id); | ||
| 451 | |||
| 452 | /* Tell device where to find queue */ | ||
| 453 | priv->cfg->ops->lib->txq_init(priv, txq); | ||
| 454 | } | ||
| 455 | EXPORT_SYMBOL(iwl_tx_queue_reset); | ||
| 456 | |||
| 413 | /** | 457 | /** |
| 414 | * iwl_hw_txq_ctx_free - Free TXQ Context | 458 | * iwl_hw_txq_ctx_free - Free TXQ Context |
| 415 | * | 459 | * |
| @@ -421,8 +465,7 @@ void iwl_hw_txq_ctx_free(struct iwl_priv *priv) | |||
| 421 | 465 | ||
| 422 | /* Tx queues */ | 466 | /* Tx queues */ |
| 423 | if (priv->txq) { | 467 | if (priv->txq) { |
| 424 | for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; | 468 | for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) |
| 425 | txq_id++) | ||
| 426 | if (txq_id == IWL_CMD_QUEUE_NUM) | 469 | if (txq_id == IWL_CMD_QUEUE_NUM) |
| 427 | iwl_cmd_queue_free(priv); | 470 | iwl_cmd_queue_free(priv); |
| 428 | else | 471 | else |
| @@ -438,15 +481,15 @@ void iwl_hw_txq_ctx_free(struct iwl_priv *priv) | |||
| 438 | EXPORT_SYMBOL(iwl_hw_txq_ctx_free); | 481 | EXPORT_SYMBOL(iwl_hw_txq_ctx_free); |
| 439 | 482 | ||
| 440 | /** | 483 | /** |
| 441 | * iwl_txq_ctx_reset - Reset TX queue context | 484 | * iwl_txq_ctx_alloc - allocate TX queue context |
| 442 | * Destroys all DMA structures and initialize them again | 485 | * Allocate all Tx DMA structures and initialize them |
| 443 | * | 486 | * |
| 444 | * @param priv | 487 | * @param priv |
| 445 | * @return error code | 488 | * @return error code |
| 446 | */ | 489 | */ |
| 447 | int iwl_txq_ctx_reset(struct iwl_priv *priv) | 490 | int iwl_txq_ctx_alloc(struct iwl_priv *priv) |
| 448 | { | 491 | { |
| 449 | int ret = 0; | 492 | int ret; |
| 450 | int txq_id, slots_num; | 493 | int txq_id, slots_num; |
| 451 | unsigned long flags; | 494 | unsigned long flags; |
| 452 | 495 | ||
| @@ -504,8 +547,31 @@ int iwl_txq_ctx_reset(struct iwl_priv *priv) | |||
| 504 | return ret; | 547 | return ret; |
| 505 | } | 548 | } |
| 506 | 549 | ||
| 550 | void iwl_txq_ctx_reset(struct iwl_priv *priv) | ||
| 551 | { | ||
| 552 | int txq_id, slots_num; | ||
| 553 | unsigned long flags; | ||
| 554 | |||
| 555 | spin_lock_irqsave(&priv->lock, flags); | ||
| 556 | |||
| 557 | /* Turn off all Tx DMA fifos */ | ||
| 558 | priv->cfg->ops->lib->txq_set_sched(priv, 0); | ||
| 559 | |||
| 560 | /* Tell NIC where to find the "keep warm" buffer */ | ||
| 561 | iwl_write_direct32(priv, FH_KW_MEM_ADDR_REG, priv->kw.dma >> 4); | ||
| 562 | |||
| 563 | spin_unlock_irqrestore(&priv->lock, flags); | ||
| 564 | |||
| 565 | /* Alloc and init all Tx queues, including the command queue (#4) */ | ||
| 566 | for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) { | ||
| 567 | slots_num = txq_id == IWL_CMD_QUEUE_NUM ? | ||
| 568 | TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS; | ||
| 569 | iwl_tx_queue_reset(priv, &priv->txq[txq_id], slots_num, txq_id); | ||
| 570 | } | ||
| 571 | } | ||
| 572 | |||
| 507 | /** | 573 | /** |
| 508 | * iwl_txq_ctx_stop - Stop all Tx DMA channels, free Tx queue memory | 574 | * iwl_txq_ctx_stop - Stop all Tx DMA channels |
| 509 | */ | 575 | */ |
| 510 | void iwl_txq_ctx_stop(struct iwl_priv *priv) | 576 | void iwl_txq_ctx_stop(struct iwl_priv *priv) |
| 511 | { | 577 | { |
| @@ -525,9 +591,6 @@ void iwl_txq_ctx_stop(struct iwl_priv *priv) | |||
| 525 | 1000); | 591 | 1000); |
| 526 | } | 592 | } |
| 527 | spin_unlock_irqrestore(&priv->lock, flags); | 593 | spin_unlock_irqrestore(&priv->lock, flags); |
| 528 | |||
| 529 | /* Deallocate memory for all Tx queues */ | ||
| 530 | iwl_hw_txq_ctx_free(priv); | ||
| 531 | } | 594 | } |
| 532 | EXPORT_SYMBOL(iwl_txq_ctx_stop); | 595 | EXPORT_SYMBOL(iwl_txq_ctx_stop); |
| 533 | 596 | ||
| @@ -1050,6 +1113,14 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) | |||
| 1050 | 1113 | ||
| 1051 | spin_lock_irqsave(&priv->hcmd_lock, flags); | 1114 | spin_lock_irqsave(&priv->hcmd_lock, flags); |
| 1052 | 1115 | ||
| 1116 | /* If this is a huge cmd, mark the huge flag also on the meta.flags | ||
| 1117 | * of the _original_ cmd. This is used for DMA mapping clean up. | ||
| 1118 | */ | ||
| 1119 | if (cmd->flags & CMD_SIZE_HUGE) { | ||
| 1120 | idx = get_cmd_index(q, q->write_ptr, 0); | ||
| 1121 | txq->meta[idx].flags = CMD_SIZE_HUGE; | ||
| 1122 | } | ||
| 1123 | |||
| 1053 | idx = get_cmd_index(q, q->write_ptr, cmd->flags & CMD_SIZE_HUGE); | 1124 | idx = get_cmd_index(q, q->write_ptr, cmd->flags & CMD_SIZE_HUGE); |
| 1054 | out_cmd = txq->cmd[idx]; | 1125 | out_cmd = txq->cmd[idx]; |
| 1055 | out_meta = &txq->meta[idx]; | 1126 | out_meta = &txq->meta[idx]; |
| @@ -1227,6 +1298,7 @@ void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) | |||
| 1227 | bool huge = !!(pkt->hdr.sequence & SEQ_HUGE_FRAME); | 1298 | bool huge = !!(pkt->hdr.sequence & SEQ_HUGE_FRAME); |
| 1228 | struct iwl_device_cmd *cmd; | 1299 | struct iwl_device_cmd *cmd; |
| 1229 | struct iwl_cmd_meta *meta; | 1300 | struct iwl_cmd_meta *meta; |
| 1301 | struct iwl_tx_queue *txq = &priv->txq[IWL_CMD_QUEUE_NUM]; | ||
| 1230 | 1302 | ||
| 1231 | /* If a Tx command is being handled and it isn't in the actual | 1303 | /* If a Tx command is being handled and it isn't in the actual |
| 1232 | * command queue then there a command routing bug has been introduced | 1304 | * command queue then there a command routing bug has been introduced |
| @@ -1240,9 +1312,17 @@ void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) | |||
| 1240 | return; | 1312 | return; |
| 1241 | } | 1313 | } |
| 1242 | 1314 | ||
| 1243 | cmd_index = get_cmd_index(&priv->txq[IWL_CMD_QUEUE_NUM].q, index, huge); | 1315 | /* If this is a huge cmd, clear the huge flag on the meta.flags |
| 1244 | cmd = priv->txq[IWL_CMD_QUEUE_NUM].cmd[cmd_index]; | 1316 | * of the _original_ cmd. So that iwl_cmd_queue_free won't unmap |
| 1245 | meta = &priv->txq[IWL_CMD_QUEUE_NUM].meta[cmd_index]; | 1317 | * the DMA buffer for the scan (huge) command. |
| 1318 | */ | ||
| 1319 | if (huge) { | ||
| 1320 | cmd_index = get_cmd_index(&txq->q, index, 0); | ||
| 1321 | txq->meta[cmd_index].flags = 0; | ||
| 1322 | } | ||
| 1323 | cmd_index = get_cmd_index(&txq->q, index, huge); | ||
| 1324 | cmd = txq->cmd[cmd_index]; | ||
| 1325 | meta = &txq->meta[cmd_index]; | ||
| 1246 | 1326 | ||
| 1247 | pci_unmap_single(priv->pci_dev, | 1327 | pci_unmap_single(priv->pci_dev, |
| 1248 | pci_unmap_addr(meta, mapping), | 1328 | pci_unmap_addr(meta, mapping), |
| @@ -1264,6 +1344,7 @@ void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) | |||
| 1264 | get_cmd_string(cmd->hdr.cmd)); | 1344 | get_cmd_string(cmd->hdr.cmd)); |
| 1265 | wake_up_interruptible(&priv->wait_command_queue); | 1345 | wake_up_interruptible(&priv->wait_command_queue); |
| 1266 | } | 1346 | } |
| 1347 | meta->flags = 0; | ||
| 1267 | } | 1348 | } |
| 1268 | EXPORT_SYMBOL(iwl_tx_cmd_complete); | 1349 | EXPORT_SYMBOL(iwl_tx_cmd_complete); |
| 1269 | 1350 | ||
diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c index 5be11c99e18f..e69d238c5af0 100644 --- a/drivers/vhost/vhost.c +++ b/drivers/vhost/vhost.c | |||
| @@ -236,6 +236,10 @@ static int vq_memory_access_ok(void __user *log_base, struct vhost_memory *mem, | |||
| 236 | int log_all) | 236 | int log_all) |
| 237 | { | 237 | { |
| 238 | int i; | 238 | int i; |
| 239 | |||
| 240 | if (!mem) | ||
| 241 | return 0; | ||
| 242 | |||
| 239 | for (i = 0; i < mem->nregions; ++i) { | 243 | for (i = 0; i < mem->nregions; ++i) { |
| 240 | struct vhost_memory_region *m = mem->regions + i; | 244 | struct vhost_memory_region *m = mem->regions + i; |
| 241 | unsigned long a = m->userspace_addr; | 245 | unsigned long a = m->userspace_addr; |
diff --git a/fs/ceph/addr.c b/fs/ceph/addr.c index aa3cd7cc3e40..412593703d1e 100644 --- a/fs/ceph/addr.c +++ b/fs/ceph/addr.c | |||
| @@ -337,16 +337,15 @@ out: | |||
| 337 | /* | 337 | /* |
| 338 | * Get ref for the oldest snapc for an inode with dirty data... that is, the | 338 | * Get ref for the oldest snapc for an inode with dirty data... that is, the |
| 339 | * only snap context we are allowed to write back. | 339 | * only snap context we are allowed to write back. |
| 340 | * | ||
| 341 | * Caller holds i_lock. | ||
| 342 | */ | 340 | */ |
| 343 | static struct ceph_snap_context *__get_oldest_context(struct inode *inode, | 341 | static struct ceph_snap_context *get_oldest_context(struct inode *inode, |
| 344 | u64 *snap_size) | 342 | u64 *snap_size) |
| 345 | { | 343 | { |
| 346 | struct ceph_inode_info *ci = ceph_inode(inode); | 344 | struct ceph_inode_info *ci = ceph_inode(inode); |
| 347 | struct ceph_snap_context *snapc = NULL; | 345 | struct ceph_snap_context *snapc = NULL; |
| 348 | struct ceph_cap_snap *capsnap = NULL; | 346 | struct ceph_cap_snap *capsnap = NULL; |
| 349 | 347 | ||
| 348 | spin_lock(&inode->i_lock); | ||
| 350 | list_for_each_entry(capsnap, &ci->i_cap_snaps, ci_item) { | 349 | list_for_each_entry(capsnap, &ci->i_cap_snaps, ci_item) { |
| 351 | dout(" cap_snap %p snapc %p has %d dirty pages\n", capsnap, | 350 | dout(" cap_snap %p snapc %p has %d dirty pages\n", capsnap, |
| 352 | capsnap->context, capsnap->dirty_pages); | 351 | capsnap->context, capsnap->dirty_pages); |
| @@ -357,21 +356,11 @@ static struct ceph_snap_context *__get_oldest_context(struct inode *inode, | |||
| 357 | break; | 356 | break; |
| 358 | } | 357 | } |
| 359 | } | 358 | } |
| 360 | if (!snapc && ci->i_snap_realm) { | 359 | if (!snapc && ci->i_head_snapc) { |
| 361 | snapc = ceph_get_snap_context(ci->i_snap_realm->cached_context); | 360 | snapc = ceph_get_snap_context(ci->i_head_snapc); |
| 362 | dout(" head snapc %p has %d dirty pages\n", | 361 | dout(" head snapc %p has %d dirty pages\n", |
| 363 | snapc, ci->i_wrbuffer_ref_head); | 362 | snapc, ci->i_wrbuffer_ref_head); |
| 364 | } | 363 | } |
| 365 | return snapc; | ||
| 366 | } | ||
| 367 | |||
| 368 | static struct ceph_snap_context *get_oldest_context(struct inode *inode, | ||
| 369 | u64 *snap_size) | ||
| 370 | { | ||
| 371 | struct ceph_snap_context *snapc = NULL; | ||
| 372 | |||
| 373 | spin_lock(&inode->i_lock); | ||
| 374 | snapc = __get_oldest_context(inode, snap_size); | ||
| 375 | spin_unlock(&inode->i_lock); | 364 | spin_unlock(&inode->i_lock); |
| 376 | return snapc; | 365 | return snapc; |
| 377 | } | 366 | } |
| @@ -392,7 +381,7 @@ static int writepage_nounlock(struct page *page, struct writeback_control *wbc) | |||
| 392 | int len = PAGE_CACHE_SIZE; | 381 | int len = PAGE_CACHE_SIZE; |
| 393 | loff_t i_size; | 382 | loff_t i_size; |
| 394 | int err = 0; | 383 | int err = 0; |
| 395 | struct ceph_snap_context *snapc; | 384 | struct ceph_snap_context *snapc, *oldest; |
| 396 | u64 snap_size = 0; | 385 | u64 snap_size = 0; |
| 397 | long writeback_stat; | 386 | long writeback_stat; |
| 398 | 387 | ||
| @@ -413,13 +402,16 @@ static int writepage_nounlock(struct page *page, struct writeback_control *wbc) | |||
| 413 | dout("writepage %p page %p not dirty?\n", inode, page); | 402 | dout("writepage %p page %p not dirty?\n", inode, page); |
| 414 | goto out; | 403 | goto out; |
| 415 | } | 404 | } |
| 416 | if (snapc != get_oldest_context(inode, &snap_size)) { | 405 | oldest = get_oldest_context(inode, &snap_size); |
| 406 | if (snapc->seq > oldest->seq) { | ||
| 417 | dout("writepage %p page %p snapc %p not writeable - noop\n", | 407 | dout("writepage %p page %p snapc %p not writeable - noop\n", |
| 418 | inode, page, (void *)page->private); | 408 | inode, page, (void *)page->private); |
| 419 | /* we should only noop if called by kswapd */ | 409 | /* we should only noop if called by kswapd */ |
| 420 | WARN_ON((current->flags & PF_MEMALLOC) == 0); | 410 | WARN_ON((current->flags & PF_MEMALLOC) == 0); |
| 411 | ceph_put_snap_context(oldest); | ||
| 421 | goto out; | 412 | goto out; |
| 422 | } | 413 | } |
| 414 | ceph_put_snap_context(oldest); | ||
| 423 | 415 | ||
| 424 | /* is this a partial page at end of file? */ | 416 | /* is this a partial page at end of file? */ |
| 425 | if (snap_size) | 417 | if (snap_size) |
| @@ -458,7 +450,7 @@ static int writepage_nounlock(struct page *page, struct writeback_control *wbc) | |||
| 458 | ClearPagePrivate(page); | 450 | ClearPagePrivate(page); |
| 459 | end_page_writeback(page); | 451 | end_page_writeback(page); |
| 460 | ceph_put_wrbuffer_cap_refs(ci, 1, snapc); | 452 | ceph_put_wrbuffer_cap_refs(ci, 1, snapc); |
| 461 | ceph_put_snap_context(snapc); | 453 | ceph_put_snap_context(snapc); /* page's reference */ |
| 462 | out: | 454 | out: |
| 463 | return err; | 455 | return err; |
| 464 | } | 456 | } |
| @@ -558,9 +550,9 @@ static void writepages_finish(struct ceph_osd_request *req, | |||
| 558 | dout("inode %p skipping page %p\n", inode, page); | 550 | dout("inode %p skipping page %p\n", inode, page); |
| 559 | wbc->pages_skipped++; | 551 | wbc->pages_skipped++; |
| 560 | } | 552 | } |
| 553 | ceph_put_snap_context((void *)page->private); | ||
| 561 | page->private = 0; | 554 | page->private = 0; |
| 562 | ClearPagePrivate(page); | 555 | ClearPagePrivate(page); |
| 563 | ceph_put_snap_context(snapc); | ||
| 564 | dout("unlocking %d %p\n", i, page); | 556 | dout("unlocking %d %p\n", i, page); |
| 565 | end_page_writeback(page); | 557 | end_page_writeback(page); |
| 566 | 558 | ||
| @@ -618,7 +610,7 @@ static int ceph_writepages_start(struct address_space *mapping, | |||
| 618 | int range_whole = 0; | 610 | int range_whole = 0; |
| 619 | int should_loop = 1; | 611 | int should_loop = 1; |
| 620 | pgoff_t max_pages = 0, max_pages_ever = 0; | 612 | pgoff_t max_pages = 0, max_pages_ever = 0; |
| 621 | struct ceph_snap_context *snapc = NULL, *last_snapc = NULL; | 613 | struct ceph_snap_context *snapc = NULL, *last_snapc = NULL, *pgsnapc; |
| 622 | struct pagevec pvec; | 614 | struct pagevec pvec; |
| 623 | int done = 0; | 615 | int done = 0; |
| 624 | int rc = 0; | 616 | int rc = 0; |
| @@ -770,9 +762,10 @@ get_more_pages: | |||
| 770 | } | 762 | } |
| 771 | 763 | ||
| 772 | /* only if matching snap context */ | 764 | /* only if matching snap context */ |
| 773 | if (snapc != (void *)page->private) { | 765 | pgsnapc = (void *)page->private; |
| 774 | dout("page snapc %p != oldest %p\n", | 766 | if (pgsnapc->seq > snapc->seq) { |
| 775 | (void *)page->private, snapc); | 767 | dout("page snapc %p %lld > oldest %p %lld\n", |
| 768 | pgsnapc, pgsnapc->seq, snapc, snapc->seq); | ||
| 776 | unlock_page(page); | 769 | unlock_page(page); |
| 777 | if (!locked_pages) | 770 | if (!locked_pages) |
| 778 | continue; /* keep looking for snap */ | 771 | continue; /* keep looking for snap */ |
| @@ -914,7 +907,10 @@ static int context_is_writeable_or_written(struct inode *inode, | |||
| 914 | struct ceph_snap_context *snapc) | 907 | struct ceph_snap_context *snapc) |
| 915 | { | 908 | { |
| 916 | struct ceph_snap_context *oldest = get_oldest_context(inode, NULL); | 909 | struct ceph_snap_context *oldest = get_oldest_context(inode, NULL); |
| 917 | return !oldest || snapc->seq <= oldest->seq; | 910 | int ret = !oldest || snapc->seq <= oldest->seq; |
| 911 | |||
| 912 | ceph_put_snap_context(oldest); | ||
| 913 | return ret; | ||
| 918 | } | 914 | } |
| 919 | 915 | ||
| 920 | /* | 916 | /* |
| @@ -936,8 +932,8 @@ static int ceph_update_writeable_page(struct file *file, | |||
| 936 | int pos_in_page = pos & ~PAGE_CACHE_MASK; | 932 | int pos_in_page = pos & ~PAGE_CACHE_MASK; |
| 937 | int end_in_page = pos_in_page + len; | 933 | int end_in_page = pos_in_page + len; |
| 938 | loff_t i_size; | 934 | loff_t i_size; |
| 939 | struct ceph_snap_context *snapc; | ||
| 940 | int r; | 935 | int r; |
| 936 | struct ceph_snap_context *snapc, *oldest; | ||
| 941 | 937 | ||
| 942 | retry_locked: | 938 | retry_locked: |
| 943 | /* writepages currently holds page lock, but if we change that later, */ | 939 | /* writepages currently holds page lock, but if we change that later, */ |
| @@ -947,23 +943,24 @@ retry_locked: | |||
| 947 | BUG_ON(!ci->i_snap_realm); | 943 | BUG_ON(!ci->i_snap_realm); |
| 948 | down_read(&mdsc->snap_rwsem); | 944 | down_read(&mdsc->snap_rwsem); |
| 949 | BUG_ON(!ci->i_snap_realm->cached_context); | 945 | BUG_ON(!ci->i_snap_realm->cached_context); |
| 950 | if (page->private && | 946 | snapc = (void *)page->private; |
| 951 | (void *)page->private != ci->i_snap_realm->cached_context) { | 947 | if (snapc && snapc != ci->i_head_snapc) { |
| 952 | /* | 948 | /* |
| 953 | * this page is already dirty in another (older) snap | 949 | * this page is already dirty in another (older) snap |
| 954 | * context! is it writeable now? | 950 | * context! is it writeable now? |
| 955 | */ | 951 | */ |
| 956 | snapc = get_oldest_context(inode, NULL); | 952 | oldest = get_oldest_context(inode, NULL); |
| 957 | up_read(&mdsc->snap_rwsem); | 953 | up_read(&mdsc->snap_rwsem); |
| 958 | 954 | ||
| 959 | if (snapc != (void *)page->private) { | 955 | if (snapc->seq > oldest->seq) { |
| 956 | ceph_put_snap_context(oldest); | ||
| 960 | dout(" page %p snapc %p not current or oldest\n", | 957 | dout(" page %p snapc %p not current or oldest\n", |
| 961 | page, (void *)page->private); | 958 | page, snapc); |
| 962 | /* | 959 | /* |
| 963 | * queue for writeback, and wait for snapc to | 960 | * queue for writeback, and wait for snapc to |
| 964 | * be writeable or written | 961 | * be writeable or written |
| 965 | */ | 962 | */ |
| 966 | snapc = ceph_get_snap_context((void *)page->private); | 963 | snapc = ceph_get_snap_context(snapc); |
| 967 | unlock_page(page); | 964 | unlock_page(page); |
| 968 | ceph_queue_writeback(inode); | 965 | ceph_queue_writeback(inode); |
| 969 | r = wait_event_interruptible(ci->i_cap_wq, | 966 | r = wait_event_interruptible(ci->i_cap_wq, |
| @@ -973,6 +970,7 @@ retry_locked: | |||
| 973 | return r; | 970 | return r; |
| 974 | return -EAGAIN; | 971 | return -EAGAIN; |
| 975 | } | 972 | } |
| 973 | ceph_put_snap_context(oldest); | ||
| 976 | 974 | ||
| 977 | /* yay, writeable, do it now (without dropping page lock) */ | 975 | /* yay, writeable, do it now (without dropping page lock) */ |
| 978 | dout(" page %p snapc %p not current, but oldest\n", | 976 | dout(" page %p snapc %p not current, but oldest\n", |
diff --git a/fs/ceph/caps.c b/fs/ceph/caps.c index 3710e077a857..aa2239fa9a3b 100644 --- a/fs/ceph/caps.c +++ b/fs/ceph/caps.c | |||
| @@ -1205,6 +1205,12 @@ retry: | |||
| 1205 | if (capsnap->dirty_pages || capsnap->writing) | 1205 | if (capsnap->dirty_pages || capsnap->writing) |
| 1206 | continue; | 1206 | continue; |
| 1207 | 1207 | ||
| 1208 | /* | ||
| 1209 | * if cap writeback already occurred, we should have dropped | ||
| 1210 | * the capsnap in ceph_put_wrbuffer_cap_refs. | ||
| 1211 | */ | ||
| 1212 | BUG_ON(capsnap->dirty == 0); | ||
| 1213 | |||
| 1208 | /* pick mds, take s_mutex */ | 1214 | /* pick mds, take s_mutex */ |
| 1209 | mds = __ceph_get_cap_mds(ci, &mseq); | 1215 | mds = __ceph_get_cap_mds(ci, &mseq); |
| 1210 | if (session && session->s_mds != mds) { | 1216 | if (session && session->s_mds != mds) { |
| @@ -2118,8 +2124,8 @@ void ceph_put_cap_refs(struct ceph_inode_info *ci, int had) | |||
| 2118 | } | 2124 | } |
| 2119 | spin_unlock(&inode->i_lock); | 2125 | spin_unlock(&inode->i_lock); |
| 2120 | 2126 | ||
| 2121 | dout("put_cap_refs %p had %s %s\n", inode, ceph_cap_string(had), | 2127 | dout("put_cap_refs %p had %s%s%s\n", inode, ceph_cap_string(had), |
| 2122 | last ? "last" : ""); | 2128 | last ? " last" : "", put ? " put" : ""); |
| 2123 | 2129 | ||
| 2124 | if (last && !flushsnaps) | 2130 | if (last && !flushsnaps) |
| 2125 | ceph_check_caps(ci, 0, NULL); | 2131 | ceph_check_caps(ci, 0, NULL); |
| @@ -2143,7 +2149,8 @@ void ceph_put_wrbuffer_cap_refs(struct ceph_inode_info *ci, int nr, | |||
| 2143 | { | 2149 | { |
| 2144 | struct inode *inode = &ci->vfs_inode; | 2150 | struct inode *inode = &ci->vfs_inode; |
| 2145 | int last = 0; | 2151 | int last = 0; |
| 2146 | int last_snap = 0; | 2152 | int complete_capsnap = 0; |
| 2153 | int drop_capsnap = 0; | ||
| 2147 | int found = 0; | 2154 | int found = 0; |
| 2148 | struct ceph_cap_snap *capsnap = NULL; | 2155 | struct ceph_cap_snap *capsnap = NULL; |
| 2149 | 2156 | ||
| @@ -2166,19 +2173,32 @@ void ceph_put_wrbuffer_cap_refs(struct ceph_inode_info *ci, int nr, | |||
| 2166 | list_for_each_entry(capsnap, &ci->i_cap_snaps, ci_item) { | 2173 | list_for_each_entry(capsnap, &ci->i_cap_snaps, ci_item) { |
| 2167 | if (capsnap->context == snapc) { | 2174 | if (capsnap->context == snapc) { |
| 2168 | found = 1; | 2175 | found = 1; |
| 2169 | capsnap->dirty_pages -= nr; | ||
| 2170 | last_snap = !capsnap->dirty_pages; | ||
| 2171 | break; | 2176 | break; |
| 2172 | } | 2177 | } |
| 2173 | } | 2178 | } |
| 2174 | BUG_ON(!found); | 2179 | BUG_ON(!found); |
| 2180 | capsnap->dirty_pages -= nr; | ||
| 2181 | if (capsnap->dirty_pages == 0) { | ||
| 2182 | complete_capsnap = 1; | ||
| 2183 | if (capsnap->dirty == 0) | ||
| 2184 | /* cap writeback completed before we created | ||
| 2185 | * the cap_snap; no FLUSHSNAP is needed */ | ||
| 2186 | drop_capsnap = 1; | ||
| 2187 | } | ||
| 2175 | dout("put_wrbuffer_cap_refs on %p cap_snap %p " | 2188 | dout("put_wrbuffer_cap_refs on %p cap_snap %p " |
| 2176 | " snap %lld %d/%d -> %d/%d %s%s\n", | 2189 | " snap %lld %d/%d -> %d/%d %s%s%s\n", |
| 2177 | inode, capsnap, capsnap->context->seq, | 2190 | inode, capsnap, capsnap->context->seq, |
| 2178 | ci->i_wrbuffer_ref+nr, capsnap->dirty_pages + nr, | 2191 | ci->i_wrbuffer_ref+nr, capsnap->dirty_pages + nr, |
| 2179 | ci->i_wrbuffer_ref, capsnap->dirty_pages, | 2192 | ci->i_wrbuffer_ref, capsnap->dirty_pages, |
| 2180 | last ? " (wrbuffer last)" : "", | 2193 | last ? " (wrbuffer last)" : "", |
| 2181 | last_snap ? " (capsnap last)" : ""); | 2194 | complete_capsnap ? " (complete capsnap)" : "", |
| 2195 | drop_capsnap ? " (drop capsnap)" : ""); | ||
| 2196 | if (drop_capsnap) { | ||
| 2197 | ceph_put_snap_context(capsnap->context); | ||
| 2198 | list_del(&capsnap->ci_item); | ||
| 2199 | list_del(&capsnap->flushing_item); | ||
| 2200 | ceph_put_cap_snap(capsnap); | ||
| 2201 | } | ||
| 2182 | } | 2202 | } |
| 2183 | 2203 | ||
| 2184 | spin_unlock(&inode->i_lock); | 2204 | spin_unlock(&inode->i_lock); |
| @@ -2186,10 +2206,12 @@ void ceph_put_wrbuffer_cap_refs(struct ceph_inode_info *ci, int nr, | |||
| 2186 | if (last) { | 2206 | if (last) { |
| 2187 | ceph_check_caps(ci, CHECK_CAPS_AUTHONLY, NULL); | 2207 | ceph_check_caps(ci, CHECK_CAPS_AUTHONLY, NULL); |
| 2188 | iput(inode); | 2208 | iput(inode); |
| 2189 | } else if (last_snap) { | 2209 | } else if (complete_capsnap) { |
| 2190 | ceph_flush_snaps(ci); | 2210 | ceph_flush_snaps(ci); |
| 2191 | wake_up(&ci->i_cap_wq); | 2211 | wake_up(&ci->i_cap_wq); |
| 2192 | } | 2212 | } |
| 2213 | if (drop_capsnap) | ||
| 2214 | iput(inode); | ||
| 2193 | } | 2215 | } |
| 2194 | 2216 | ||
| 2195 | /* | 2217 | /* |
| @@ -2465,8 +2487,8 @@ static void handle_cap_flushsnap_ack(struct inode *inode, u64 flush_tid, | |||
| 2465 | break; | 2487 | break; |
| 2466 | } | 2488 | } |
| 2467 | WARN_ON(capsnap->dirty_pages || capsnap->writing); | 2489 | WARN_ON(capsnap->dirty_pages || capsnap->writing); |
| 2468 | dout(" removing cap_snap %p follows %lld\n", | 2490 | dout(" removing %p cap_snap %p follows %lld\n", |
| 2469 | capsnap, follows); | 2491 | inode, capsnap, follows); |
| 2470 | ceph_put_snap_context(capsnap->context); | 2492 | ceph_put_snap_context(capsnap->context); |
| 2471 | list_del(&capsnap->ci_item); | 2493 | list_del(&capsnap->ci_item); |
| 2472 | list_del(&capsnap->flushing_item); | 2494 | list_del(&capsnap->flushing_item); |
diff --git a/fs/ceph/dir.c b/fs/ceph/dir.c index 7261dc6c2ead..ea8ee2e526aa 100644 --- a/fs/ceph/dir.c +++ b/fs/ceph/dir.c | |||
| @@ -171,11 +171,11 @@ more: | |||
| 171 | spin_lock(&inode->i_lock); | 171 | spin_lock(&inode->i_lock); |
| 172 | spin_lock(&dcache_lock); | 172 | spin_lock(&dcache_lock); |
| 173 | 173 | ||
| 174 | last = dentry; | ||
| 175 | |||
| 174 | if (err < 0) | 176 | if (err < 0) |
| 175 | goto out_unlock; | 177 | goto out_unlock; |
| 176 | 178 | ||
| 177 | last = dentry; | ||
| 178 | |||
| 179 | p = p->prev; | 179 | p = p->prev; |
| 180 | filp->f_pos++; | 180 | filp->f_pos++; |
| 181 | 181 | ||
| @@ -312,7 +312,7 @@ more: | |||
| 312 | req->r_readdir_offset = fi->next_offset; | 312 | req->r_readdir_offset = fi->next_offset; |
| 313 | req->r_args.readdir.frag = cpu_to_le32(frag); | 313 | req->r_args.readdir.frag = cpu_to_le32(frag); |
| 314 | req->r_args.readdir.max_entries = cpu_to_le32(max_entries); | 314 | req->r_args.readdir.max_entries = cpu_to_le32(max_entries); |
| 315 | req->r_num_caps = max_entries; | 315 | req->r_num_caps = max_entries + 1; |
| 316 | err = ceph_mdsc_do_request(mdsc, NULL, req); | 316 | err = ceph_mdsc_do_request(mdsc, NULL, req); |
| 317 | if (err < 0) { | 317 | if (err < 0) { |
| 318 | ceph_mdsc_put_request(req); | 318 | ceph_mdsc_put_request(req); |
| @@ -489,6 +489,7 @@ struct dentry *ceph_finish_lookup(struct ceph_mds_request *req, | |||
| 489 | struct inode *inode = ceph_get_snapdir(parent); | 489 | struct inode *inode = ceph_get_snapdir(parent); |
| 490 | dout("ENOENT on snapdir %p '%.*s', linking to snapdir %p\n", | 490 | dout("ENOENT on snapdir %p '%.*s', linking to snapdir %p\n", |
| 491 | dentry, dentry->d_name.len, dentry->d_name.name, inode); | 491 | dentry, dentry->d_name.len, dentry->d_name.name, inode); |
| 492 | BUG_ON(!d_unhashed(dentry)); | ||
| 492 | d_add(dentry, inode); | 493 | d_add(dentry, inode); |
| 493 | err = 0; | 494 | err = 0; |
| 494 | } | 495 | } |
diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c index aca82d55cc53..26f883c275e8 100644 --- a/fs/ceph/inode.c +++ b/fs/ceph/inode.c | |||
| @@ -886,6 +886,7 @@ int ceph_fill_trace(struct super_block *sb, struct ceph_mds_request *req, | |||
| 886 | struct inode *in = NULL; | 886 | struct inode *in = NULL; |
| 887 | struct ceph_mds_reply_inode *ininfo; | 887 | struct ceph_mds_reply_inode *ininfo; |
| 888 | struct ceph_vino vino; | 888 | struct ceph_vino vino; |
| 889 | struct ceph_client *client = ceph_sb_to_client(sb); | ||
| 889 | int i = 0; | 890 | int i = 0; |
| 890 | int err = 0; | 891 | int err = 0; |
| 891 | 892 | ||
| @@ -949,7 +950,14 @@ int ceph_fill_trace(struct super_block *sb, struct ceph_mds_request *req, | |||
| 949 | return err; | 950 | return err; |
| 950 | } | 951 | } |
| 951 | 952 | ||
| 952 | if (rinfo->head->is_dentry && !req->r_aborted) { | 953 | /* |
| 954 | * ignore null lease/binding on snapdir ENOENT, or else we | ||
| 955 | * will have trouble splicing in the virtual snapdir later | ||
| 956 | */ | ||
| 957 | if (rinfo->head->is_dentry && !req->r_aborted && | ||
| 958 | (rinfo->head->is_target || strncmp(req->r_dentry->d_name.name, | ||
| 959 | client->mount_args->snapdir_name, | ||
| 960 | req->r_dentry->d_name.len))) { | ||
| 953 | /* | 961 | /* |
| 954 | * lookup link rename : null -> possibly existing inode | 962 | * lookup link rename : null -> possibly existing inode |
| 955 | * mknod symlink mkdir : null -> new inode | 963 | * mknod symlink mkdir : null -> new inode |
diff --git a/fs/ceph/messenger.c b/fs/ceph/messenger.c index 8f1715ffbe4b..cdaaa131add3 100644 --- a/fs/ceph/messenger.c +++ b/fs/ceph/messenger.c | |||
| @@ -30,6 +30,10 @@ static char tag_msg = CEPH_MSGR_TAG_MSG; | |||
| 30 | static char tag_ack = CEPH_MSGR_TAG_ACK; | 30 | static char tag_ack = CEPH_MSGR_TAG_ACK; |
| 31 | static char tag_keepalive = CEPH_MSGR_TAG_KEEPALIVE; | 31 | static char tag_keepalive = CEPH_MSGR_TAG_KEEPALIVE; |
| 32 | 32 | ||
| 33 | #ifdef CONFIG_LOCKDEP | ||
| 34 | static struct lock_class_key socket_class; | ||
| 35 | #endif | ||
| 36 | |||
| 33 | 37 | ||
| 34 | static void queue_con(struct ceph_connection *con); | 38 | static void queue_con(struct ceph_connection *con); |
| 35 | static void con_work(struct work_struct *); | 39 | static void con_work(struct work_struct *); |
| @@ -228,6 +232,10 @@ static struct socket *ceph_tcp_connect(struct ceph_connection *con) | |||
| 228 | con->sock = sock; | 232 | con->sock = sock; |
| 229 | sock->sk->sk_allocation = GFP_NOFS; | 233 | sock->sk->sk_allocation = GFP_NOFS; |
| 230 | 234 | ||
| 235 | #ifdef CONFIG_LOCKDEP | ||
| 236 | lockdep_set_class(&sock->sk->sk_lock, &socket_class); | ||
| 237 | #endif | ||
| 238 | |||
| 231 | set_sock_callbacks(sock, con); | 239 | set_sock_callbacks(sock, con); |
| 232 | 240 | ||
| 233 | dout("connect %s\n", pr_addr(&con->peer_addr.in_addr)); | 241 | dout("connect %s\n", pr_addr(&con->peer_addr.in_addr)); |
| @@ -333,6 +341,7 @@ static void reset_connection(struct ceph_connection *con) | |||
| 333 | con->out_msg = NULL; | 341 | con->out_msg = NULL; |
| 334 | } | 342 | } |
| 335 | con->in_seq = 0; | 343 | con->in_seq = 0; |
| 344 | con->in_seq_acked = 0; | ||
| 336 | } | 345 | } |
| 337 | 346 | ||
| 338 | /* | 347 | /* |
diff --git a/fs/ceph/osdmap.c b/fs/ceph/osdmap.c index 21c6623c4b07..2e2c15eed82a 100644 --- a/fs/ceph/osdmap.c +++ b/fs/ceph/osdmap.c | |||
| @@ -314,71 +314,6 @@ bad: | |||
| 314 | return ERR_PTR(err); | 314 | return ERR_PTR(err); |
| 315 | } | 315 | } |
| 316 | 316 | ||
| 317 | |||
| 318 | /* | ||
| 319 | * osd map | ||
| 320 | */ | ||
| 321 | void ceph_osdmap_destroy(struct ceph_osdmap *map) | ||
| 322 | { | ||
| 323 | dout("osdmap_destroy %p\n", map); | ||
| 324 | if (map->crush) | ||
| 325 | crush_destroy(map->crush); | ||
| 326 | while (!RB_EMPTY_ROOT(&map->pg_temp)) { | ||
| 327 | struct ceph_pg_mapping *pg = | ||
| 328 | rb_entry(rb_first(&map->pg_temp), | ||
| 329 | struct ceph_pg_mapping, node); | ||
| 330 | rb_erase(&pg->node, &map->pg_temp); | ||
| 331 | kfree(pg); | ||
| 332 | } | ||
| 333 | while (!RB_EMPTY_ROOT(&map->pg_pools)) { | ||
| 334 | struct ceph_pg_pool_info *pi = | ||
| 335 | rb_entry(rb_first(&map->pg_pools), | ||
| 336 | struct ceph_pg_pool_info, node); | ||
| 337 | rb_erase(&pi->node, &map->pg_pools); | ||
| 338 | kfree(pi); | ||
| 339 | } | ||
| 340 | kfree(map->osd_state); | ||
| 341 | kfree(map->osd_weight); | ||
| 342 | kfree(map->osd_addr); | ||
| 343 | kfree(map); | ||
| 344 | } | ||
| 345 | |||
| 346 | /* | ||
| 347 | * adjust max osd value. reallocate arrays. | ||
| 348 | */ | ||
| 349 | static int osdmap_set_max_osd(struct ceph_osdmap *map, int max) | ||
| 350 | { | ||
| 351 | u8 *state; | ||
| 352 | struct ceph_entity_addr *addr; | ||
| 353 | u32 *weight; | ||
| 354 | |||
| 355 | state = kcalloc(max, sizeof(*state), GFP_NOFS); | ||
| 356 | addr = kcalloc(max, sizeof(*addr), GFP_NOFS); | ||
| 357 | weight = kcalloc(max, sizeof(*weight), GFP_NOFS); | ||
| 358 | if (state == NULL || addr == NULL || weight == NULL) { | ||
| 359 | kfree(state); | ||
| 360 | kfree(addr); | ||
| 361 | kfree(weight); | ||
| 362 | return -ENOMEM; | ||
| 363 | } | ||
| 364 | |||
| 365 | /* copy old? */ | ||
| 366 | if (map->osd_state) { | ||
| 367 | memcpy(state, map->osd_state, map->max_osd*sizeof(*state)); | ||
| 368 | memcpy(addr, map->osd_addr, map->max_osd*sizeof(*addr)); | ||
| 369 | memcpy(weight, map->osd_weight, map->max_osd*sizeof(*weight)); | ||
| 370 | kfree(map->osd_state); | ||
| 371 | kfree(map->osd_addr); | ||
| 372 | kfree(map->osd_weight); | ||
| 373 | } | ||
| 374 | |||
| 375 | map->osd_state = state; | ||
| 376 | map->osd_weight = weight; | ||
| 377 | map->osd_addr = addr; | ||
| 378 | map->max_osd = max; | ||
| 379 | return 0; | ||
| 380 | } | ||
| 381 | |||
| 382 | /* | 317 | /* |
| 383 | * rbtree of pg_mapping for handling pg_temp (explicit mapping of pgid | 318 | * rbtree of pg_mapping for handling pg_temp (explicit mapping of pgid |
| 384 | * to a set of osds) | 319 | * to a set of osds) |
| @@ -482,6 +417,13 @@ static struct ceph_pg_pool_info *__lookup_pg_pool(struct rb_root *root, int id) | |||
| 482 | return NULL; | 417 | return NULL; |
| 483 | } | 418 | } |
| 484 | 419 | ||
| 420 | static void __remove_pg_pool(struct rb_root *root, struct ceph_pg_pool_info *pi) | ||
| 421 | { | ||
| 422 | rb_erase(&pi->node, root); | ||
| 423 | kfree(pi->name); | ||
| 424 | kfree(pi); | ||
| 425 | } | ||
| 426 | |||
| 485 | void __decode_pool(void **p, struct ceph_pg_pool_info *pi) | 427 | void __decode_pool(void **p, struct ceph_pg_pool_info *pi) |
| 486 | { | 428 | { |
| 487 | ceph_decode_copy(p, &pi->v, sizeof(pi->v)); | 429 | ceph_decode_copy(p, &pi->v, sizeof(pi->v)); |
| @@ -490,6 +432,98 @@ void __decode_pool(void **p, struct ceph_pg_pool_info *pi) | |||
| 490 | *p += le32_to_cpu(pi->v.num_removed_snap_intervals) * sizeof(u64) * 2; | 432 | *p += le32_to_cpu(pi->v.num_removed_snap_intervals) * sizeof(u64) * 2; |
| 491 | } | 433 | } |
| 492 | 434 | ||
| 435 | static int __decode_pool_names(void **p, void *end, struct ceph_osdmap *map) | ||
| 436 | { | ||
| 437 | struct ceph_pg_pool_info *pi; | ||
| 438 | u32 num, len, pool; | ||
| 439 | |||
| 440 | ceph_decode_32_safe(p, end, num, bad); | ||
| 441 | dout(" %d pool names\n", num); | ||
| 442 | while (num--) { | ||
| 443 | ceph_decode_32_safe(p, end, pool, bad); | ||
| 444 | ceph_decode_32_safe(p, end, len, bad); | ||
| 445 | dout(" pool %d len %d\n", pool, len); | ||
| 446 | pi = __lookup_pg_pool(&map->pg_pools, pool); | ||
| 447 | if (pi) { | ||
| 448 | kfree(pi->name); | ||
| 449 | pi->name = kmalloc(len + 1, GFP_NOFS); | ||
| 450 | if (pi->name) { | ||
| 451 | memcpy(pi->name, *p, len); | ||
| 452 | pi->name[len] = '\0'; | ||
| 453 | dout(" name is %s\n", pi->name); | ||
| 454 | } | ||
| 455 | } | ||
| 456 | *p += len; | ||
| 457 | } | ||
| 458 | return 0; | ||
| 459 | |||
| 460 | bad: | ||
| 461 | return -EINVAL; | ||
| 462 | } | ||
| 463 | |||
| 464 | /* | ||
| 465 | * osd map | ||
| 466 | */ | ||
| 467 | void ceph_osdmap_destroy(struct ceph_osdmap *map) | ||
| 468 | { | ||
| 469 | dout("osdmap_destroy %p\n", map); | ||
| 470 | if (map->crush) | ||
| 471 | crush_destroy(map->crush); | ||
| 472 | while (!RB_EMPTY_ROOT(&map->pg_temp)) { | ||
| 473 | struct ceph_pg_mapping *pg = | ||
| 474 | rb_entry(rb_first(&map->pg_temp), | ||
| 475 | struct ceph_pg_mapping, node); | ||
| 476 | rb_erase(&pg->node, &map->pg_temp); | ||
| 477 | kfree(pg); | ||
| 478 | } | ||
| 479 | while (!RB_EMPTY_ROOT(&map->pg_pools)) { | ||
| 480 | struct ceph_pg_pool_info *pi = | ||
| 481 | rb_entry(rb_first(&map->pg_pools), | ||
| 482 | struct ceph_pg_pool_info, node); | ||
| 483 | __remove_pg_pool(&map->pg_pools, pi); | ||
| 484 | } | ||
| 485 | kfree(map->osd_state); | ||
| 486 | kfree(map->osd_weight); | ||
| 487 | kfree(map->osd_addr); | ||
| 488 | kfree(map); | ||
| 489 | } | ||
| 490 | |||
| 491 | /* | ||
| 492 | * adjust max osd value. reallocate arrays. | ||
| 493 | */ | ||
| 494 | static int osdmap_set_max_osd(struct ceph_osdmap *map, int max) | ||
| 495 | { | ||
| 496 | u8 *state; | ||
| 497 | struct ceph_entity_addr *addr; | ||
| 498 | u32 *weight; | ||
| 499 | |||
| 500 | state = kcalloc(max, sizeof(*state), GFP_NOFS); | ||
| 501 | addr = kcalloc(max, sizeof(*addr), GFP_NOFS); | ||
| 502 | weight = kcalloc(max, sizeof(*weight), GFP_NOFS); | ||
| 503 | if (state == NULL || addr == NULL || weight == NULL) { | ||
| 504 | kfree(state); | ||
| 505 | kfree(addr); | ||
| 506 | kfree(weight); | ||
| 507 | return -ENOMEM; | ||
| 508 | } | ||
| 509 | |||
| 510 | /* copy old? */ | ||
| 511 | if (map->osd_state) { | ||
| 512 | memcpy(state, map->osd_state, map->max_osd*sizeof(*state)); | ||
| 513 | memcpy(addr, map->osd_addr, map->max_osd*sizeof(*addr)); | ||
| 514 | memcpy(weight, map->osd_weight, map->max_osd*sizeof(*weight)); | ||
| 515 | kfree(map->osd_state); | ||
| 516 | kfree(map->osd_addr); | ||
| 517 | kfree(map->osd_weight); | ||
| 518 | } | ||
| 519 | |||
| 520 | map->osd_state = state; | ||
| 521 | map->osd_weight = weight; | ||
| 522 | map->osd_addr = addr; | ||
| 523 | map->max_osd = max; | ||
| 524 | return 0; | ||
| 525 | } | ||
| 526 | |||
| 493 | /* | 527 | /* |
| 494 | * decode a full map. | 528 | * decode a full map. |
| 495 | */ | 529 | */ |
| @@ -526,7 +560,7 @@ struct ceph_osdmap *osdmap_decode(void **p, void *end) | |||
| 526 | ceph_decode_32_safe(p, end, max, bad); | 560 | ceph_decode_32_safe(p, end, max, bad); |
| 527 | while (max--) { | 561 | while (max--) { |
| 528 | ceph_decode_need(p, end, 4 + 1 + sizeof(pi->v), bad); | 562 | ceph_decode_need(p, end, 4 + 1 + sizeof(pi->v), bad); |
| 529 | pi = kmalloc(sizeof(*pi), GFP_NOFS); | 563 | pi = kzalloc(sizeof(*pi), GFP_NOFS); |
| 530 | if (!pi) | 564 | if (!pi) |
| 531 | goto bad; | 565 | goto bad; |
| 532 | pi->id = ceph_decode_32(p); | 566 | pi->id = ceph_decode_32(p); |
| @@ -539,6 +573,10 @@ struct ceph_osdmap *osdmap_decode(void **p, void *end) | |||
| 539 | __decode_pool(p, pi); | 573 | __decode_pool(p, pi); |
| 540 | __insert_pg_pool(&map->pg_pools, pi); | 574 | __insert_pg_pool(&map->pg_pools, pi); |
| 541 | } | 575 | } |
| 576 | |||
| 577 | if (version >= 5 && __decode_pool_names(p, end, map) < 0) | ||
| 578 | goto bad; | ||
| 579 | |||
| 542 | ceph_decode_32_safe(p, end, map->pool_max, bad); | 580 | ceph_decode_32_safe(p, end, map->pool_max, bad); |
| 543 | 581 | ||
| 544 | ceph_decode_32_safe(p, end, map->flags, bad); | 582 | ceph_decode_32_safe(p, end, map->flags, bad); |
| @@ -712,7 +750,7 @@ struct ceph_osdmap *osdmap_apply_incremental(void **p, void *end, | |||
| 712 | } | 750 | } |
| 713 | pi = __lookup_pg_pool(&map->pg_pools, pool); | 751 | pi = __lookup_pg_pool(&map->pg_pools, pool); |
| 714 | if (!pi) { | 752 | if (!pi) { |
| 715 | pi = kmalloc(sizeof(*pi), GFP_NOFS); | 753 | pi = kzalloc(sizeof(*pi), GFP_NOFS); |
| 716 | if (!pi) { | 754 | if (!pi) { |
| 717 | err = -ENOMEM; | 755 | err = -ENOMEM; |
| 718 | goto bad; | 756 | goto bad; |
| @@ -722,6 +760,8 @@ struct ceph_osdmap *osdmap_apply_incremental(void **p, void *end, | |||
| 722 | } | 760 | } |
| 723 | __decode_pool(p, pi); | 761 | __decode_pool(p, pi); |
| 724 | } | 762 | } |
| 763 | if (version >= 5 && __decode_pool_names(p, end, map) < 0) | ||
| 764 | goto bad; | ||
| 725 | 765 | ||
| 726 | /* old_pool */ | 766 | /* old_pool */ |
| 727 | ceph_decode_32_safe(p, end, len, bad); | 767 | ceph_decode_32_safe(p, end, len, bad); |
| @@ -730,10 +770,8 @@ struct ceph_osdmap *osdmap_apply_incremental(void **p, void *end, | |||
| 730 | 770 | ||
| 731 | ceph_decode_32_safe(p, end, pool, bad); | 771 | ceph_decode_32_safe(p, end, pool, bad); |
| 732 | pi = __lookup_pg_pool(&map->pg_pools, pool); | 772 | pi = __lookup_pg_pool(&map->pg_pools, pool); |
| 733 | if (pi) { | 773 | if (pi) |
| 734 | rb_erase(&pi->node, &map->pg_pools); | 774 | __remove_pg_pool(&map->pg_pools, pi); |
| 735 | kfree(pi); | ||
| 736 | } | ||
| 737 | } | 775 | } |
| 738 | 776 | ||
| 739 | /* new_up */ | 777 | /* new_up */ |
diff --git a/fs/ceph/osdmap.h b/fs/ceph/osdmap.h index 1fb55afb2642..8bc9f1e4f562 100644 --- a/fs/ceph/osdmap.h +++ b/fs/ceph/osdmap.h | |||
| @@ -23,6 +23,7 @@ struct ceph_pg_pool_info { | |||
| 23 | int id; | 23 | int id; |
| 24 | struct ceph_pg_pool v; | 24 | struct ceph_pg_pool v; |
| 25 | int pg_num_mask, pgp_num_mask, lpg_num_mask, lpgp_num_mask; | 25 | int pg_num_mask, pgp_num_mask, lpg_num_mask, lpgp_num_mask; |
| 26 | char *name; | ||
| 26 | }; | 27 | }; |
| 27 | 28 | ||
| 28 | struct ceph_pg_mapping { | 29 | struct ceph_pg_mapping { |
diff --git a/fs/ceph/rados.h b/fs/ceph/rados.h index 26ac8b89a676..a1fc1d017b58 100644 --- a/fs/ceph/rados.h +++ b/fs/ceph/rados.h | |||
| @@ -11,8 +11,10 @@ | |||
| 11 | /* | 11 | /* |
| 12 | * osdmap encoding versions | 12 | * osdmap encoding versions |
| 13 | */ | 13 | */ |
| 14 | #define CEPH_OSDMAP_INC_VERSION 4 | 14 | #define CEPH_OSDMAP_INC_VERSION 5 |
| 15 | #define CEPH_OSDMAP_VERSION 4 | 15 | #define CEPH_OSDMAP_INC_VERSION_EXT 5 |
| 16 | #define CEPH_OSDMAP_VERSION 5 | ||
| 17 | #define CEPH_OSDMAP_VERSION_EXT 5 | ||
| 16 | 18 | ||
| 17 | /* | 19 | /* |
| 18 | * fs id | 20 | * fs id |
diff --git a/fs/ceph/snap.c b/fs/ceph/snap.c index e6f9bc57d472..2b881262ef67 100644 --- a/fs/ceph/snap.c +++ b/fs/ceph/snap.c | |||
| @@ -431,8 +431,7 @@ static int dup_array(u64 **dst, __le64 *src, int num) | |||
| 431 | * Caller must hold snap_rwsem for read (i.e., the realm topology won't | 431 | * Caller must hold snap_rwsem for read (i.e., the realm topology won't |
| 432 | * change). | 432 | * change). |
| 433 | */ | 433 | */ |
| 434 | void ceph_queue_cap_snap(struct ceph_inode_info *ci, | 434 | void ceph_queue_cap_snap(struct ceph_inode_info *ci) |
| 435 | struct ceph_snap_context *snapc) | ||
| 436 | { | 435 | { |
| 437 | struct inode *inode = &ci->vfs_inode; | 436 | struct inode *inode = &ci->vfs_inode; |
| 438 | struct ceph_cap_snap *capsnap; | 437 | struct ceph_cap_snap *capsnap; |
| @@ -451,10 +450,11 @@ void ceph_queue_cap_snap(struct ceph_inode_info *ci, | |||
| 451 | as no new writes are allowed to start when pending, so any | 450 | as no new writes are allowed to start when pending, so any |
| 452 | writes in progress now were started before the previous | 451 | writes in progress now were started before the previous |
| 453 | cap_snap. lucky us. */ | 452 | cap_snap. lucky us. */ |
| 454 | dout("queue_cap_snap %p snapc %p seq %llu used %d" | 453 | dout("queue_cap_snap %p already pending\n", inode); |
| 455 | " already pending\n", inode, snapc, snapc->seq, used); | ||
| 456 | kfree(capsnap); | 454 | kfree(capsnap); |
| 457 | } else if (ci->i_wrbuffer_ref_head || (used & CEPH_CAP_FILE_WR)) { | 455 | } else if (ci->i_wrbuffer_ref_head || (used & CEPH_CAP_FILE_WR)) { |
| 456 | struct ceph_snap_context *snapc = ci->i_head_snapc; | ||
| 457 | |||
| 458 | igrab(inode); | 458 | igrab(inode); |
| 459 | 459 | ||
| 460 | atomic_set(&capsnap->nref, 1); | 460 | atomic_set(&capsnap->nref, 1); |
| @@ -463,7 +463,6 @@ void ceph_queue_cap_snap(struct ceph_inode_info *ci, | |||
| 463 | INIT_LIST_HEAD(&capsnap->flushing_item); | 463 | INIT_LIST_HEAD(&capsnap->flushing_item); |
| 464 | 464 | ||
| 465 | capsnap->follows = snapc->seq - 1; | 465 | capsnap->follows = snapc->seq - 1; |
| 466 | capsnap->context = ceph_get_snap_context(snapc); | ||
| 467 | capsnap->issued = __ceph_caps_issued(ci, NULL); | 466 | capsnap->issued = __ceph_caps_issued(ci, NULL); |
| 468 | capsnap->dirty = __ceph_caps_dirty(ci); | 467 | capsnap->dirty = __ceph_caps_dirty(ci); |
| 469 | 468 | ||
| @@ -480,7 +479,7 @@ void ceph_queue_cap_snap(struct ceph_inode_info *ci, | |||
| 480 | snapshot. */ | 479 | snapshot. */ |
| 481 | capsnap->dirty_pages = ci->i_wrbuffer_ref_head; | 480 | capsnap->dirty_pages = ci->i_wrbuffer_ref_head; |
| 482 | ci->i_wrbuffer_ref_head = 0; | 481 | ci->i_wrbuffer_ref_head = 0; |
| 483 | ceph_put_snap_context(ci->i_head_snapc); | 482 | capsnap->context = snapc; |
| 484 | ci->i_head_snapc = NULL; | 483 | ci->i_head_snapc = NULL; |
| 485 | list_add_tail(&capsnap->ci_item, &ci->i_cap_snaps); | 484 | list_add_tail(&capsnap->ci_item, &ci->i_cap_snaps); |
| 486 | 485 | ||
| @@ -522,15 +521,17 @@ int __ceph_finish_cap_snap(struct ceph_inode_info *ci, | |||
| 522 | capsnap->ctime = inode->i_ctime; | 521 | capsnap->ctime = inode->i_ctime; |
| 523 | capsnap->time_warp_seq = ci->i_time_warp_seq; | 522 | capsnap->time_warp_seq = ci->i_time_warp_seq; |
| 524 | if (capsnap->dirty_pages) { | 523 | if (capsnap->dirty_pages) { |
| 525 | dout("finish_cap_snap %p cap_snap %p snapc %p %llu s=%llu " | 524 | dout("finish_cap_snap %p cap_snap %p snapc %p %llu %s s=%llu " |
| 526 | "still has %d dirty pages\n", inode, capsnap, | 525 | "still has %d dirty pages\n", inode, capsnap, |
| 527 | capsnap->context, capsnap->context->seq, | 526 | capsnap->context, capsnap->context->seq, |
| 528 | capsnap->size, capsnap->dirty_pages); | 527 | ceph_cap_string(capsnap->dirty), capsnap->size, |
| 528 | capsnap->dirty_pages); | ||
| 529 | return 0; | 529 | return 0; |
| 530 | } | 530 | } |
| 531 | dout("finish_cap_snap %p cap_snap %p snapc %p %llu s=%llu clean\n", | 531 | dout("finish_cap_snap %p cap_snap %p snapc %p %llu %s s=%llu\n", |
| 532 | inode, capsnap, capsnap->context, | 532 | inode, capsnap, capsnap->context, |
| 533 | capsnap->context->seq, capsnap->size); | 533 | capsnap->context->seq, ceph_cap_string(capsnap->dirty), |
| 534 | capsnap->size); | ||
| 534 | 535 | ||
| 535 | spin_lock(&mdsc->snap_flush_lock); | 536 | spin_lock(&mdsc->snap_flush_lock); |
| 536 | list_add_tail(&ci->i_snap_flush_item, &mdsc->snap_flush_list); | 537 | list_add_tail(&ci->i_snap_flush_item, &mdsc->snap_flush_list); |
| @@ -602,7 +603,7 @@ more: | |||
| 602 | if (lastinode) | 603 | if (lastinode) |
| 603 | iput(lastinode); | 604 | iput(lastinode); |
| 604 | lastinode = inode; | 605 | lastinode = inode; |
| 605 | ceph_queue_cap_snap(ci, realm->cached_context); | 606 | ceph_queue_cap_snap(ci); |
| 606 | spin_lock(&realm->inodes_with_caps_lock); | 607 | spin_lock(&realm->inodes_with_caps_lock); |
| 607 | } | 608 | } |
| 608 | spin_unlock(&realm->inodes_with_caps_lock); | 609 | spin_unlock(&realm->inodes_with_caps_lock); |
| @@ -824,8 +825,7 @@ void ceph_handle_snap(struct ceph_mds_client *mdsc, | |||
| 824 | spin_unlock(&realm->inodes_with_caps_lock); | 825 | spin_unlock(&realm->inodes_with_caps_lock); |
| 825 | spin_unlock(&inode->i_lock); | 826 | spin_unlock(&inode->i_lock); |
| 826 | 827 | ||
| 827 | ceph_queue_cap_snap(ci, | 828 | ceph_queue_cap_snap(ci); |
| 828 | ci->i_snap_realm->cached_context); | ||
| 829 | 829 | ||
| 830 | iput(inode); | 830 | iput(inode); |
| 831 | continue; | 831 | continue; |
diff --git a/fs/ceph/super.h b/fs/ceph/super.h index ca702c67bc66..e30dfbb056c3 100644 --- a/fs/ceph/super.h +++ b/fs/ceph/super.h | |||
| @@ -715,8 +715,7 @@ extern int ceph_update_snap_trace(struct ceph_mds_client *m, | |||
| 715 | extern void ceph_handle_snap(struct ceph_mds_client *mdsc, | 715 | extern void ceph_handle_snap(struct ceph_mds_client *mdsc, |
| 716 | struct ceph_mds_session *session, | 716 | struct ceph_mds_session *session, |
| 717 | struct ceph_msg *msg); | 717 | struct ceph_msg *msg); |
| 718 | extern void ceph_queue_cap_snap(struct ceph_inode_info *ci, | 718 | extern void ceph_queue_cap_snap(struct ceph_inode_info *ci); |
| 719 | struct ceph_snap_context *snapc); | ||
| 720 | extern int __ceph_finish_cap_snap(struct ceph_inode_info *ci, | 719 | extern int __ceph_finish_cap_snap(struct ceph_inode_info *ci, |
| 721 | struct ceph_cap_snap *capsnap); | 720 | struct ceph_cap_snap *capsnap); |
| 722 | extern void ceph_cleanup_empty_realms(struct ceph_mds_client *mdsc); | 721 | extern void ceph_cleanup_empty_realms(struct ceph_mds_client *mdsc); |
diff --git a/fs/nfs/client.c b/fs/nfs/client.c index 2a3d352c0bff..a8766c4ef2e0 100644 --- a/fs/nfs/client.c +++ b/fs/nfs/client.c | |||
| @@ -1294,7 +1294,8 @@ static int nfs4_init_server(struct nfs_server *server, | |||
| 1294 | 1294 | ||
| 1295 | /* Initialise the client representation from the mount data */ | 1295 | /* Initialise the client representation from the mount data */ |
| 1296 | server->flags = data->flags; | 1296 | server->flags = data->flags; |
| 1297 | server->caps |= NFS_CAP_ATOMIC_OPEN|NFS_CAP_CHANGE_ATTR; | 1297 | server->caps |= NFS_CAP_ATOMIC_OPEN|NFS_CAP_CHANGE_ATTR| |
| 1298 | NFS_CAP_POSIX_LOCK; | ||
| 1298 | server->options = data->options; | 1299 | server->options = data->options; |
| 1299 | 1300 | ||
| 1300 | /* Get a client record */ | 1301 | /* Get a client record */ |
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index c6f2750648f4..be46f26c9a56 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c | |||
| @@ -1025,12 +1025,12 @@ static struct dentry *nfs_atomic_lookup(struct inode *dir, struct dentry *dentry | |||
| 1025 | res = NULL; | 1025 | res = NULL; |
| 1026 | goto out; | 1026 | goto out; |
| 1027 | /* This turned out not to be a regular file */ | 1027 | /* This turned out not to be a regular file */ |
| 1028 | case -EISDIR: | ||
| 1028 | case -ENOTDIR: | 1029 | case -ENOTDIR: |
| 1029 | goto no_open; | 1030 | goto no_open; |
| 1030 | case -ELOOP: | 1031 | case -ELOOP: |
| 1031 | if (!(nd->intent.open.flags & O_NOFOLLOW)) | 1032 | if (!(nd->intent.open.flags & O_NOFOLLOW)) |
| 1032 | goto no_open; | 1033 | goto no_open; |
| 1033 | /* case -EISDIR: */ | ||
| 1034 | /* case -EINVAL: */ | 1034 | /* case -EINVAL: */ |
| 1035 | default: | 1035 | default: |
| 1036 | goto out; | 1036 | goto out; |
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index 737128f777f3..50a56edca0b5 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c | |||
| @@ -623,10 +623,10 @@ struct nfs_open_context *nfs_find_open_context(struct inode *inode, struct rpc_c | |||
| 623 | list_for_each_entry(pos, &nfsi->open_files, list) { | 623 | list_for_each_entry(pos, &nfsi->open_files, list) { |
| 624 | if (cred != NULL && pos->cred != cred) | 624 | if (cred != NULL && pos->cred != cred) |
| 625 | continue; | 625 | continue; |
| 626 | if ((pos->mode & mode) == mode) { | 626 | if ((pos->mode & (FMODE_READ|FMODE_WRITE)) != mode) |
| 627 | ctx = get_nfs_open_context(pos); | 627 | continue; |
| 628 | break; | 628 | ctx = get_nfs_open_context(pos); |
| 629 | } | 629 | break; |
| 630 | } | 630 | } |
| 631 | spin_unlock(&inode->i_lock); | 631 | spin_unlock(&inode->i_lock); |
| 632 | return ctx; | 632 | return ctx; |
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index fe0cd9eb1d4d..638067007c65 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
| @@ -1523,6 +1523,8 @@ static int _nfs4_proc_open(struct nfs4_opendata *data) | |||
| 1523 | nfs_post_op_update_inode(dir, o_res->dir_attr); | 1523 | nfs_post_op_update_inode(dir, o_res->dir_attr); |
| 1524 | } else | 1524 | } else |
| 1525 | nfs_refresh_inode(dir, o_res->dir_attr); | 1525 | nfs_refresh_inode(dir, o_res->dir_attr); |
| 1526 | if ((o_res->rflags & NFS4_OPEN_RESULT_LOCKTYPE_POSIX) == 0) | ||
| 1527 | server->caps &= ~NFS_CAP_POSIX_LOCK; | ||
| 1526 | if(o_res->rflags & NFS4_OPEN_RESULT_CONFIRM) { | 1528 | if(o_res->rflags & NFS4_OPEN_RESULT_CONFIRM) { |
| 1527 | status = _nfs4_proc_open_confirm(data); | 1529 | status = _nfs4_proc_open_confirm(data); |
| 1528 | if (status != 0) | 1530 | if (status != 0) |
| @@ -1664,7 +1666,7 @@ static int _nfs4_do_open(struct inode *dir, struct path *path, fmode_t fmode, in | |||
| 1664 | status = PTR_ERR(state); | 1666 | status = PTR_ERR(state); |
| 1665 | if (IS_ERR(state)) | 1667 | if (IS_ERR(state)) |
| 1666 | goto err_opendata_put; | 1668 | goto err_opendata_put; |
| 1667 | if ((opendata->o_res.rflags & NFS4_OPEN_RESULT_LOCKTYPE_POSIX) != 0) | 1669 | if (server->caps & NFS_CAP_POSIX_LOCK) |
| 1668 | set_bit(NFS_STATE_POSIX_LOCKS, &state->flags); | 1670 | set_bit(NFS_STATE_POSIX_LOCKS, &state->flags); |
| 1669 | nfs4_opendata_put(opendata); | 1671 | nfs4_opendata_put(opendata); |
| 1670 | nfs4_put_state_owner(sp); | 1672 | nfs4_put_state_owner(sp); |
diff --git a/fs/nfs/write.c b/fs/nfs/write.c index 53ff70e23993..de38d63aa920 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c | |||
| @@ -201,6 +201,7 @@ static int nfs_set_page_writeback(struct page *page) | |||
| 201 | struct inode *inode = page->mapping->host; | 201 | struct inode *inode = page->mapping->host; |
| 202 | struct nfs_server *nfss = NFS_SERVER(inode); | 202 | struct nfs_server *nfss = NFS_SERVER(inode); |
| 203 | 203 | ||
| 204 | page_cache_get(page); | ||
| 204 | if (atomic_long_inc_return(&nfss->writeback) > | 205 | if (atomic_long_inc_return(&nfss->writeback) > |
| 205 | NFS_CONGESTION_ON_THRESH) { | 206 | NFS_CONGESTION_ON_THRESH) { |
| 206 | set_bdi_congested(&nfss->backing_dev_info, | 207 | set_bdi_congested(&nfss->backing_dev_info, |
| @@ -216,6 +217,7 @@ static void nfs_end_page_writeback(struct page *page) | |||
| 216 | struct nfs_server *nfss = NFS_SERVER(inode); | 217 | struct nfs_server *nfss = NFS_SERVER(inode); |
| 217 | 218 | ||
| 218 | end_page_writeback(page); | 219 | end_page_writeback(page); |
| 220 | page_cache_release(page); | ||
| 219 | if (atomic_long_dec_return(&nfss->writeback) < NFS_CONGESTION_OFF_THRESH) | 221 | if (atomic_long_dec_return(&nfss->writeback) < NFS_CONGESTION_OFF_THRESH) |
| 220 | clear_bdi_congested(&nfss->backing_dev_info, BLK_RW_ASYNC); | 222 | clear_bdi_congested(&nfss->backing_dev_info, BLK_RW_ASYNC); |
| 221 | } | 223 | } |
| @@ -421,6 +423,7 @@ static void | |||
| 421 | nfs_mark_request_dirty(struct nfs_page *req) | 423 | nfs_mark_request_dirty(struct nfs_page *req) |
| 422 | { | 424 | { |
| 423 | __set_page_dirty_nobuffers(req->wb_page); | 425 | __set_page_dirty_nobuffers(req->wb_page); |
| 426 | __mark_inode_dirty(req->wb_page->mapping->host, I_DIRTY_DATASYNC); | ||
| 424 | } | 427 | } |
| 425 | 428 | ||
| 426 | #if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4) | 429 | #if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4) |
| @@ -660,9 +663,11 @@ static int nfs_writepage_setup(struct nfs_open_context *ctx, struct page *page, | |||
| 660 | req = nfs_setup_write_request(ctx, page, offset, count); | 663 | req = nfs_setup_write_request(ctx, page, offset, count); |
| 661 | if (IS_ERR(req)) | 664 | if (IS_ERR(req)) |
| 662 | return PTR_ERR(req); | 665 | return PTR_ERR(req); |
| 666 | nfs_mark_request_dirty(req); | ||
| 663 | /* Update file length */ | 667 | /* Update file length */ |
| 664 | nfs_grow_file(page, offset, count); | 668 | nfs_grow_file(page, offset, count); |
| 665 | nfs_mark_uptodate(page, req->wb_pgbase, req->wb_bytes); | 669 | nfs_mark_uptodate(page, req->wb_pgbase, req->wb_bytes); |
| 670 | nfs_mark_request_dirty(req); | ||
| 666 | nfs_clear_page_tag_locked(req); | 671 | nfs_clear_page_tag_locked(req); |
| 667 | return 0; | 672 | return 0; |
| 668 | } | 673 | } |
| @@ -739,8 +744,6 @@ int nfs_updatepage(struct file *file, struct page *page, | |||
| 739 | status = nfs_writepage_setup(ctx, page, offset, count); | 744 | status = nfs_writepage_setup(ctx, page, offset, count); |
| 740 | if (status < 0) | 745 | if (status < 0) |
| 741 | nfs_set_pageerror(page); | 746 | nfs_set_pageerror(page); |
| 742 | else | ||
| 743 | __set_page_dirty_nobuffers(page); | ||
| 744 | 747 | ||
| 745 | dprintk("NFS: nfs_updatepage returns %d (isize %lld)\n", | 748 | dprintk("NFS: nfs_updatepage returns %d (isize %lld)\n", |
| 746 | status, (long long)i_size_read(inode)); | 749 | status, (long long)i_size_read(inode)); |
| @@ -749,13 +752,12 @@ int nfs_updatepage(struct file *file, struct page *page, | |||
| 749 | 752 | ||
| 750 | static void nfs_writepage_release(struct nfs_page *req) | 753 | static void nfs_writepage_release(struct nfs_page *req) |
| 751 | { | 754 | { |
| 755 | struct page *page = req->wb_page; | ||
| 752 | 756 | ||
| 753 | if (PageError(req->wb_page) || !nfs_reschedule_unstable_write(req)) { | 757 | if (PageError(req->wb_page) || !nfs_reschedule_unstable_write(req)) |
| 754 | nfs_end_page_writeback(req->wb_page); | ||
| 755 | nfs_inode_remove_request(req); | 758 | nfs_inode_remove_request(req); |
| 756 | } else | ||
| 757 | nfs_end_page_writeback(req->wb_page); | ||
| 758 | nfs_clear_page_tag_locked(req); | 759 | nfs_clear_page_tag_locked(req); |
| 760 | nfs_end_page_writeback(page); | ||
| 759 | } | 761 | } |
| 760 | 762 | ||
| 761 | static int flush_task_priority(int how) | 763 | static int flush_task_priority(int how) |
| @@ -779,7 +781,6 @@ static int nfs_write_rpcsetup(struct nfs_page *req, | |||
| 779 | int how) | 781 | int how) |
| 780 | { | 782 | { |
| 781 | struct inode *inode = req->wb_context->path.dentry->d_inode; | 783 | struct inode *inode = req->wb_context->path.dentry->d_inode; |
| 782 | int flags = (how & FLUSH_SYNC) ? 0 : RPC_TASK_ASYNC; | ||
| 783 | int priority = flush_task_priority(how); | 784 | int priority = flush_task_priority(how); |
| 784 | struct rpc_task *task; | 785 | struct rpc_task *task; |
| 785 | struct rpc_message msg = { | 786 | struct rpc_message msg = { |
| @@ -794,9 +795,10 @@ static int nfs_write_rpcsetup(struct nfs_page *req, | |||
| 794 | .callback_ops = call_ops, | 795 | .callback_ops = call_ops, |
| 795 | .callback_data = data, | 796 | .callback_data = data, |
| 796 | .workqueue = nfsiod_workqueue, | 797 | .workqueue = nfsiod_workqueue, |
| 797 | .flags = flags, | 798 | .flags = RPC_TASK_ASYNC, |
| 798 | .priority = priority, | 799 | .priority = priority, |
| 799 | }; | 800 | }; |
| 801 | int ret = 0; | ||
| 800 | 802 | ||
| 801 | /* Set up the RPC argument and reply structs | 803 | /* Set up the RPC argument and reply structs |
| 802 | * NB: take care not to mess about with data->commit et al. */ | 804 | * NB: take care not to mess about with data->commit et al. */ |
| @@ -835,10 +837,18 @@ static int nfs_write_rpcsetup(struct nfs_page *req, | |||
| 835 | (unsigned long long)data->args.offset); | 837 | (unsigned long long)data->args.offset); |
| 836 | 838 | ||
| 837 | task = rpc_run_task(&task_setup_data); | 839 | task = rpc_run_task(&task_setup_data); |
| 838 | if (IS_ERR(task)) | 840 | if (IS_ERR(task)) { |
| 839 | return PTR_ERR(task); | 841 | ret = PTR_ERR(task); |
| 842 | goto out; | ||
| 843 | } | ||
| 844 | if (how & FLUSH_SYNC) { | ||
| 845 | ret = rpc_wait_for_completion_task(task); | ||
| 846 | if (ret == 0) | ||
| 847 | ret = task->tk_status; | ||
| 848 | } | ||
| 840 | rpc_put_task(task); | 849 | rpc_put_task(task); |
| 841 | return 0; | 850 | out: |
| 851 | return ret; | ||
| 842 | } | 852 | } |
| 843 | 853 | ||
| 844 | /* If a nfs_flush_* function fails, it should remove reqs from @head and | 854 | /* If a nfs_flush_* function fails, it should remove reqs from @head and |
| @@ -847,9 +857,11 @@ static int nfs_write_rpcsetup(struct nfs_page *req, | |||
| 847 | */ | 857 | */ |
| 848 | static void nfs_redirty_request(struct nfs_page *req) | 858 | static void nfs_redirty_request(struct nfs_page *req) |
| 849 | { | 859 | { |
| 860 | struct page *page = req->wb_page; | ||
| 861 | |||
| 850 | nfs_mark_request_dirty(req); | 862 | nfs_mark_request_dirty(req); |
| 851 | nfs_end_page_writeback(req->wb_page); | ||
| 852 | nfs_clear_page_tag_locked(req); | 863 | nfs_clear_page_tag_locked(req); |
| 864 | nfs_end_page_writeback(page); | ||
| 853 | } | 865 | } |
| 854 | 866 | ||
| 855 | /* | 867 | /* |
| @@ -1084,16 +1096,15 @@ static void nfs_writeback_release_full(void *calldata) | |||
| 1084 | if (nfs_write_need_commit(data)) { | 1096 | if (nfs_write_need_commit(data)) { |
| 1085 | memcpy(&req->wb_verf, &data->verf, sizeof(req->wb_verf)); | 1097 | memcpy(&req->wb_verf, &data->verf, sizeof(req->wb_verf)); |
| 1086 | nfs_mark_request_commit(req); | 1098 | nfs_mark_request_commit(req); |
| 1087 | nfs_end_page_writeback(page); | ||
| 1088 | dprintk(" marked for commit\n"); | 1099 | dprintk(" marked for commit\n"); |
| 1089 | goto next; | 1100 | goto next; |
| 1090 | } | 1101 | } |
| 1091 | dprintk(" OK\n"); | 1102 | dprintk(" OK\n"); |
| 1092 | remove_request: | 1103 | remove_request: |
| 1093 | nfs_end_page_writeback(page); | ||
| 1094 | nfs_inode_remove_request(req); | 1104 | nfs_inode_remove_request(req); |
| 1095 | next: | 1105 | next: |
| 1096 | nfs_clear_page_tag_locked(req); | 1106 | nfs_clear_page_tag_locked(req); |
| 1107 | nfs_end_page_writeback(page); | ||
| 1097 | } | 1108 | } |
| 1098 | nfs_writedata_release(calldata); | 1109 | nfs_writedata_release(calldata); |
| 1099 | } | 1110 | } |
| @@ -1207,7 +1218,6 @@ static int nfs_commit_rpcsetup(struct list_head *head, | |||
| 1207 | { | 1218 | { |
| 1208 | struct nfs_page *first = nfs_list_entry(head->next); | 1219 | struct nfs_page *first = nfs_list_entry(head->next); |
| 1209 | struct inode *inode = first->wb_context->path.dentry->d_inode; | 1220 | struct inode *inode = first->wb_context->path.dentry->d_inode; |
| 1210 | int flags = (how & FLUSH_SYNC) ? 0 : RPC_TASK_ASYNC; | ||
| 1211 | int priority = flush_task_priority(how); | 1221 | int priority = flush_task_priority(how); |
| 1212 | struct rpc_task *task; | 1222 | struct rpc_task *task; |
| 1213 | struct rpc_message msg = { | 1223 | struct rpc_message msg = { |
| @@ -1222,7 +1232,7 @@ static int nfs_commit_rpcsetup(struct list_head *head, | |||
| 1222 | .callback_ops = &nfs_commit_ops, | 1232 | .callback_ops = &nfs_commit_ops, |
| 1223 | .callback_data = data, | 1233 | .callback_data = data, |
| 1224 | .workqueue = nfsiod_workqueue, | 1234 | .workqueue = nfsiod_workqueue, |
| 1225 | .flags = flags, | 1235 | .flags = RPC_TASK_ASYNC, |
| 1226 | .priority = priority, | 1236 | .priority = priority, |
| 1227 | }; | 1237 | }; |
| 1228 | 1238 | ||
| @@ -1252,6 +1262,8 @@ static int nfs_commit_rpcsetup(struct list_head *head, | |||
| 1252 | task = rpc_run_task(&task_setup_data); | 1262 | task = rpc_run_task(&task_setup_data); |
| 1253 | if (IS_ERR(task)) | 1263 | if (IS_ERR(task)) |
| 1254 | return PTR_ERR(task); | 1264 | return PTR_ERR(task); |
| 1265 | if (how & FLUSH_SYNC) | ||
| 1266 | rpc_wait_for_completion_task(task); | ||
| 1255 | rpc_put_task(task); | 1267 | rpc_put_task(task); |
| 1256 | return 0; | 1268 | return 0; |
| 1257 | } | 1269 | } |
diff --git a/include/linux/firewire-cdev.h b/include/linux/firewire-cdev.h index 40b11013408e..81f3b14d5d76 100644 --- a/include/linux/firewire-cdev.h +++ b/include/linux/firewire-cdev.h | |||
| @@ -1,21 +1,26 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * Char device interface. | 2 | * Char device interface. |
| 3 | * | 3 | * |
| 4 | * Copyright (C) 2005-2006 Kristian Hoegsberg <krh@bitplanet.net> | 4 | * Copyright (C) 2005-2007 Kristian Hoegsberg <krh@bitplanet.net> |
| 5 | * | 5 | * |
| 6 | * This program is free software; you can redistribute it and/or modify | 6 | * Permission is hereby granted, free of charge, to any person obtaining a |
| 7 | * it under the terms of the GNU General Public License as published by | 7 | * copy of this software and associated documentation files (the "Software"), |
| 8 | * the Free Software Foundation; either version 2 of the License, or | 8 | * to deal in the Software without restriction, including without limitation |
| 9 | * (at your option) any later version. | 9 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, |
| 10 | * | 10 | * and/or sell copies of the Software, and to permit persons to whom the |
| 11 | * This program is distributed in the hope that it will be useful, | 11 | * Software is furnished to do so, subject to the following conditions: |
| 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 12 | * |
| 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 13 | * The above copyright notice and this permission notice (including the next |
| 14 | * GNU General Public License for more details. | 14 | * paragraph) shall be included in all copies or substantial portions of the |
| 15 | * | 15 | * Software. |
| 16 | * You should have received a copy of the GNU General Public License | 16 | * |
| 17 | * along with this program; if not, write to the Free Software Foundation, | 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| 18 | * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
| 20 | * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR | ||
| 21 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | ||
| 22 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | ||
| 23 | * DEALINGS IN THE SOFTWARE. | ||
| 19 | */ | 24 | */ |
| 20 | 25 | ||
| 21 | #ifndef _LINUX_FIREWIRE_CDEV_H | 26 | #ifndef _LINUX_FIREWIRE_CDEV_H |
| @@ -438,7 +443,7 @@ struct fw_cdev_remove_descriptor { | |||
| 438 | * @type: %FW_CDEV_ISO_CONTEXT_TRANSMIT or %FW_CDEV_ISO_CONTEXT_RECEIVE | 443 | * @type: %FW_CDEV_ISO_CONTEXT_TRANSMIT or %FW_CDEV_ISO_CONTEXT_RECEIVE |
| 439 | * @header_size: Header size to strip for receive contexts | 444 | * @header_size: Header size to strip for receive contexts |
| 440 | * @channel: Channel to bind to | 445 | * @channel: Channel to bind to |
| 441 | * @speed: Speed to transmit at | 446 | * @speed: Speed for transmit contexts |
| 442 | * @closure: To be returned in &fw_cdev_event_iso_interrupt | 447 | * @closure: To be returned in &fw_cdev_event_iso_interrupt |
| 443 | * @handle: Handle to context, written back by kernel | 448 | * @handle: Handle to context, written back by kernel |
| 444 | * | 449 | * |
| @@ -451,6 +456,9 @@ struct fw_cdev_remove_descriptor { | |||
| 451 | * If a context was successfully created, the kernel writes back a handle to the | 456 | * If a context was successfully created, the kernel writes back a handle to the |
| 452 | * context, which must be passed in for subsequent operations on that context. | 457 | * context, which must be passed in for subsequent operations on that context. |
| 453 | * | 458 | * |
| 459 | * For receive contexts, @header_size must be at least 4 and must be a multiple | ||
| 460 | * of 4. | ||
| 461 | * | ||
| 454 | * Note that the effect of a @header_size > 4 depends on | 462 | * Note that the effect of a @header_size > 4 depends on |
| 455 | * &fw_cdev_get_info.version, as documented at &fw_cdev_event_iso_interrupt. | 463 | * &fw_cdev_get_info.version, as documented at &fw_cdev_event_iso_interrupt. |
| 456 | */ | 464 | */ |
| @@ -481,10 +489,34 @@ struct fw_cdev_create_iso_context { | |||
| 481 | * | 489 | * |
| 482 | * &struct fw_cdev_iso_packet is used to describe isochronous packet queues. | 490 | * &struct fw_cdev_iso_packet is used to describe isochronous packet queues. |
| 483 | * | 491 | * |
| 484 | * Use the FW_CDEV_ISO_ macros to fill in @control. The sy and tag fields are | 492 | * Use the FW_CDEV_ISO_ macros to fill in @control. |
| 485 | * specified by IEEE 1394a and IEC 61883. | 493 | * |
| 486 | * | 494 | * For transmit packets, the header length must be a multiple of 4 and specifies |
| 487 | * FIXME - finish this documentation | 495 | * the numbers of bytes in @header that will be prepended to the packet's |
| 496 | * payload; these bytes are copied into the kernel and will not be accessed | ||
| 497 | * after the ioctl has returned. The sy and tag fields are copied to the iso | ||
| 498 | * packet header (these fields are specified by IEEE 1394a and IEC 61883-1). | ||
| 499 | * The skip flag specifies that no packet is to be sent in a frame; when using | ||
| 500 | * this, all other fields except the interrupt flag must be zero. | ||
| 501 | * | ||
| 502 | * For receive packets, the header length must be a multiple of the context's | ||
| 503 | * header size; if the header length is larger than the context's header size, | ||
| 504 | * multiple packets are queued for this entry. The sy and tag fields are | ||
| 505 | * ignored. If the sync flag is set, the context drops all packets until | ||
| 506 | * a packet with a matching sy field is received (the sync value to wait for is | ||
| 507 | * specified in the &fw_cdev_start_iso structure). The payload length defines | ||
| 508 | * how many payload bytes can be received for one packet (in addition to payload | ||
| 509 | * quadlets that have been defined as headers and are stripped and returned in | ||
| 510 | * the &fw_cdev_event_iso_interrupt structure). If more bytes are received, the | ||
| 511 | * additional bytes are dropped. If less bytes are received, the remaining | ||
| 512 | * bytes in this part of the payload buffer will not be written to, not even by | ||
| 513 | * the next packet, i.e., packets received in consecutive frames will not | ||
| 514 | * necessarily be consecutive in memory. If an entry has queued multiple | ||
| 515 | * packets, the payload length is divided equally among them. | ||
| 516 | * | ||
| 517 | * When a packet with the interrupt flag set has been completed, the | ||
| 518 | * &fw_cdev_event_iso_interrupt event will be sent. An entry that has queued | ||
| 519 | * multiple receive packets is completed when its last packet is completed. | ||
| 488 | */ | 520 | */ |
| 489 | struct fw_cdev_iso_packet { | 521 | struct fw_cdev_iso_packet { |
| 490 | __u32 control; | 522 | __u32 control; |
| @@ -501,7 +533,7 @@ struct fw_cdev_iso_packet { | |||
| 501 | * Queue a number of isochronous packets for reception or transmission. | 533 | * Queue a number of isochronous packets for reception or transmission. |
| 502 | * This ioctl takes a pointer to an array of &fw_cdev_iso_packet structs, | 534 | * This ioctl takes a pointer to an array of &fw_cdev_iso_packet structs, |
| 503 | * which describe how to transmit from or receive into a contiguous region | 535 | * which describe how to transmit from or receive into a contiguous region |
| 504 | * of a mmap()'ed payload buffer. As part of the packet descriptors, | 536 | * of a mmap()'ed payload buffer. As part of transmit packet descriptors, |
| 505 | * a series of headers can be supplied, which will be prepended to the | 537 | * a series of headers can be supplied, which will be prepended to the |
| 506 | * payload during DMA. | 538 | * payload during DMA. |
| 507 | * | 539 | * |
| @@ -620,8 +652,8 @@ struct fw_cdev_get_cycle_timer2 { | |||
| 620 | * instead of allocated. | 652 | * instead of allocated. |
| 621 | * An %FW_CDEV_EVENT_ISO_RESOURCE_DEALLOCATED event concludes this operation. | 653 | * An %FW_CDEV_EVENT_ISO_RESOURCE_DEALLOCATED event concludes this operation. |
| 622 | * | 654 | * |
| 623 | * To summarize, %FW_CDEV_IOC_DEALLOCATE_ISO_RESOURCE allocates iso resources | 655 | * To summarize, %FW_CDEV_IOC_ALLOCATE_ISO_RESOURCE allocates iso resources |
| 624 | * for the lifetime of the fd or handle. | 656 | * for the lifetime of the fd or @handle. |
| 625 | * In contrast, %FW_CDEV_IOC_ALLOCATE_ISO_RESOURCE_ONCE allocates iso resources | 657 | * In contrast, %FW_CDEV_IOC_ALLOCATE_ISO_RESOURCE_ONCE allocates iso resources |
| 626 | * for the duration of a bus generation. | 658 | * for the duration of a bus generation. |
| 627 | * | 659 | * |
diff --git a/include/linux/firewire-constants.h b/include/linux/firewire-constants.h index b316770a43fd..9c63f06e67f2 100644 --- a/include/linux/firewire-constants.h +++ b/include/linux/firewire-constants.h | |||
| @@ -1,3 +1,28 @@ | |||
| 1 | /* | ||
| 2 | * IEEE 1394 constants. | ||
| 3 | * | ||
| 4 | * Copyright (C) 2005-2007 Kristian Hoegsberg <krh@bitplanet.net> | ||
| 5 | * | ||
| 6 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
| 7 | * copy of this software and associated documentation files (the "Software"), | ||
| 8 | * to deal in the Software without restriction, including without limitation | ||
| 9 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
| 10 | * and/or sell copies of the Software, and to permit persons to whom the | ||
| 11 | * Software is furnished to do so, subject to the following conditions: | ||
| 12 | * | ||
| 13 | * The above copyright notice and this permission notice (including the next | ||
| 14 | * paragraph) shall be included in all copies or substantial portions of the | ||
| 15 | * Software. | ||
| 16 | * | ||
| 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
| 20 | * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR | ||
| 21 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | ||
| 22 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | ||
| 23 | * DEALINGS IN THE SOFTWARE. | ||
| 24 | */ | ||
| 25 | |||
| 1 | #ifndef _LINUX_FIREWIRE_CONSTANTS_H | 26 | #ifndef _LINUX_FIREWIRE_CONSTANTS_H |
| 2 | #define _LINUX_FIREWIRE_CONSTANTS_H | 27 | #define _LINUX_FIREWIRE_CONSTANTS_H |
| 3 | 28 | ||
| @@ -21,7 +46,7 @@ | |||
| 21 | #define EXTCODE_WRAP_ADD 0x6 | 46 | #define EXTCODE_WRAP_ADD 0x6 |
| 22 | #define EXTCODE_VENDOR_DEPENDENT 0x7 | 47 | #define EXTCODE_VENDOR_DEPENDENT 0x7 |
| 23 | 48 | ||
| 24 | /* Juju specific tcodes */ | 49 | /* Linux firewire-core (Juju) specific tcodes */ |
| 25 | #define TCODE_LOCK_MASK_SWAP (0x10 | EXTCODE_MASK_SWAP) | 50 | #define TCODE_LOCK_MASK_SWAP (0x10 | EXTCODE_MASK_SWAP) |
| 26 | #define TCODE_LOCK_COMPARE_SWAP (0x10 | EXTCODE_COMPARE_SWAP) | 51 | #define TCODE_LOCK_COMPARE_SWAP (0x10 | EXTCODE_COMPARE_SWAP) |
| 27 | #define TCODE_LOCK_FETCH_ADD (0x10 | EXTCODE_FETCH_ADD) | 52 | #define TCODE_LOCK_FETCH_ADD (0x10 | EXTCODE_FETCH_ADD) |
| @@ -36,7 +61,7 @@ | |||
| 36 | #define RCODE_TYPE_ERROR 0x6 | 61 | #define RCODE_TYPE_ERROR 0x6 |
| 37 | #define RCODE_ADDRESS_ERROR 0x7 | 62 | #define RCODE_ADDRESS_ERROR 0x7 |
| 38 | 63 | ||
| 39 | /* Juju specific rcodes */ | 64 | /* Linux firewire-core (Juju) specific rcodes */ |
| 40 | #define RCODE_SEND_ERROR 0x10 | 65 | #define RCODE_SEND_ERROR 0x10 |
| 41 | #define RCODE_CANCELLED 0x11 | 66 | #define RCODE_CANCELLED 0x11 |
| 42 | #define RCODE_BUSY 0x12 | 67 | #define RCODE_BUSY 0x12 |
diff --git a/include/linux/input/matrix_keypad.h b/include/linux/input/matrix_keypad.h index 3bd018baae20..c964cd7f436a 100644 --- a/include/linux/input/matrix_keypad.h +++ b/include/linux/input/matrix_keypad.h | |||
| @@ -44,6 +44,7 @@ struct matrix_keymap_data { | |||
| 44 | * @active_low: gpio polarity | 44 | * @active_low: gpio polarity |
| 45 | * @wakeup: controls whether the device should be set up as wakeup | 45 | * @wakeup: controls whether the device should be set up as wakeup |
| 46 | * source | 46 | * source |
| 47 | * @no_autorepeat: disable key autorepeat | ||
| 47 | * | 48 | * |
| 48 | * This structure represents platform-specific data that use used by | 49 | * This structure represents platform-specific data that use used by |
| 49 | * matrix_keypad driver to perform proper initialization. | 50 | * matrix_keypad driver to perform proper initialization. |
| @@ -64,6 +65,7 @@ struct matrix_keypad_platform_data { | |||
| 64 | 65 | ||
| 65 | bool active_low; | 66 | bool active_low; |
| 66 | bool wakeup; | 67 | bool wakeup; |
| 68 | bool no_autorepeat; | ||
| 67 | }; | 69 | }; |
| 68 | 70 | ||
| 69 | /** | 71 | /** |
diff --git a/include/linux/nfs_fs_sb.h b/include/linux/nfs_fs_sb.h index 717a5e54eb1d..e82957acea56 100644 --- a/include/linux/nfs_fs_sb.h +++ b/include/linux/nfs_fs_sb.h | |||
| @@ -176,6 +176,7 @@ struct nfs_server { | |||
| 176 | #define NFS_CAP_ATIME (1U << 11) | 176 | #define NFS_CAP_ATIME (1U << 11) |
| 177 | #define NFS_CAP_CTIME (1U << 12) | 177 | #define NFS_CAP_CTIME (1U << 12) |
| 178 | #define NFS_CAP_MTIME (1U << 13) | 178 | #define NFS_CAP_MTIME (1U << 13) |
| 179 | #define NFS_CAP_POSIX_LOCK (1U << 14) | ||
| 179 | 180 | ||
| 180 | 181 | ||
| 181 | /* maximum number of slots to use */ | 182 | /* maximum number of slots to use */ |
diff --git a/include/net/x25.h b/include/net/x25.h index 15ef9624ab75..468551ea4f1d 100644 --- a/include/net/x25.h +++ b/include/net/x25.h | |||
| @@ -183,6 +183,10 @@ extern int sysctl_x25_clear_request_timeout; | |||
| 183 | extern int sysctl_x25_ack_holdback_timeout; | 183 | extern int sysctl_x25_ack_holdback_timeout; |
| 184 | extern int sysctl_x25_forward; | 184 | extern int sysctl_x25_forward; |
| 185 | 185 | ||
| 186 | extern int x25_parse_address_block(struct sk_buff *skb, | ||
| 187 | struct x25_address *called_addr, | ||
| 188 | struct x25_address *calling_addr); | ||
| 189 | |||
| 186 | extern int x25_addr_ntoa(unsigned char *, struct x25_address *, | 190 | extern int x25_addr_ntoa(unsigned char *, struct x25_address *, |
| 187 | struct x25_address *); | 191 | struct x25_address *); |
| 188 | extern int x25_addr_aton(unsigned char *, struct x25_address *, | 192 | extern int x25_addr_aton(unsigned char *, struct x25_address *, |
diff --git a/kernel/power/user.c b/kernel/power/user.c index 4d2289626a84..a8c96212bc1b 100644 --- a/kernel/power/user.c +++ b/kernel/power/user.c | |||
| @@ -420,7 +420,7 @@ static long snapshot_ioctl(struct file *filp, unsigned int cmd, | |||
| 420 | * User space encodes device types as two-byte values, | 420 | * User space encodes device types as two-byte values, |
| 421 | * so we need to recode them | 421 | * so we need to recode them |
| 422 | */ | 422 | */ |
| 423 | swdev = old_decode_dev(swap_area.dev); | 423 | swdev = new_decode_dev(swap_area.dev); |
| 424 | if (swdev) { | 424 | if (swdev) { |
| 425 | offset = swap_area.offset; | 425 | offset = swap_area.offset; |
| 426 | data->swap = swap_type_of(swdev, offset, NULL); | 426 | data->swap = swap_type_of(swdev, offset, NULL); |
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index ff017108700d..935248bdbc47 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug | |||
| @@ -356,7 +356,7 @@ config SLUB_STATS | |||
| 356 | config DEBUG_KMEMLEAK | 356 | config DEBUG_KMEMLEAK |
| 357 | bool "Kernel memory leak detector" | 357 | bool "Kernel memory leak detector" |
| 358 | depends on DEBUG_KERNEL && EXPERIMENTAL && !MEMORY_HOTPLUG && \ | 358 | depends on DEBUG_KERNEL && EXPERIMENTAL && !MEMORY_HOTPLUG && \ |
| 359 | (X86 || ARM || PPC || S390 || SUPERH || MICROBLAZE) | 359 | (X86 || ARM || PPC || S390 || SPARC64 || SUPERH || MICROBLAZE) |
| 360 | 360 | ||
| 361 | select DEBUG_FS if SYSFS | 361 | select DEBUG_FS if SYSFS |
| 362 | select STACKTRACE if STACKTRACE_SUPPORT | 362 | select STACKTRACE if STACKTRACE_SUPPORT |
diff --git a/lib/vsprintf.c b/lib/vsprintf.c index 24112e5a5780..7376b7c55ffe 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c | |||
| @@ -408,12 +408,12 @@ enum format_type { | |||
| 408 | }; | 408 | }; |
| 409 | 409 | ||
| 410 | struct printf_spec { | 410 | struct printf_spec { |
| 411 | u16 type; | 411 | u8 type; /* format_type enum */ |
| 412 | s16 field_width; /* width of output field */ | ||
| 413 | u8 flags; /* flags to number() */ | 412 | u8 flags; /* flags to number() */ |
| 414 | u8 base; | 413 | u8 base; /* number base, 8, 10 or 16 only */ |
| 415 | s8 precision; /* # of digits/chars */ | 414 | u8 qualifier; /* number qualifier, one of 'hHlLtzZ' */ |
| 416 | u8 qualifier; | 415 | s16 field_width; /* width of output field */ |
| 416 | s16 precision; /* # of digits/chars */ | ||
| 417 | }; | 417 | }; |
| 418 | 418 | ||
| 419 | static char *number(char *buf, char *end, unsigned long long num, | 419 | static char *number(char *buf, char *end, unsigned long long num, |
diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c index 6980625537ca..f29ada827a6a 100644 --- a/net/bridge/br_multicast.c +++ b/net/bridge/br_multicast.c | |||
| @@ -723,7 +723,7 @@ static int br_multicast_igmp3_report(struct net_bridge *br, | |||
| 723 | if (!pskb_may_pull(skb, len)) | 723 | if (!pskb_may_pull(skb, len)) |
| 724 | return -EINVAL; | 724 | return -EINVAL; |
| 725 | 725 | ||
| 726 | grec = (void *)(skb->data + len); | 726 | grec = (void *)(skb->data + len - sizeof(*grec)); |
| 727 | group = grec->grec_mca; | 727 | group = grec->grec_mca; |
| 728 | type = grec->grec_type; | 728 | type = grec->grec_type; |
| 729 | 729 | ||
diff --git a/net/can/raw.c b/net/can/raw.c index 3a7dffb6519c..da99cf153b33 100644 --- a/net/can/raw.c +++ b/net/can/raw.c | |||
| @@ -445,7 +445,7 @@ static int raw_setsockopt(struct socket *sock, int level, int optname, | |||
| 445 | return -EFAULT; | 445 | return -EFAULT; |
| 446 | } | 446 | } |
| 447 | } else if (count == 1) { | 447 | } else if (count == 1) { |
| 448 | if (copy_from_user(&sfilter, optval, optlen)) | 448 | if (copy_from_user(&sfilter, optval, sizeof(sfilter))) |
| 449 | return -EFAULT; | 449 | return -EFAULT; |
| 450 | } | 450 | } |
| 451 | 451 | ||
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index 954bbfb39dff..8fef859db35d 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c | |||
| @@ -472,8 +472,8 @@ static struct sock *__udp4_lib_lookup(struct net *net, __be32 saddr, | |||
| 472 | if (hslot->count < hslot2->count) | 472 | if (hslot->count < hslot2->count) |
| 473 | goto begin; | 473 | goto begin; |
| 474 | 474 | ||
| 475 | result = udp4_lib_lookup2(net, INADDR_ANY, sport, | 475 | result = udp4_lib_lookup2(net, saddr, sport, |
| 476 | daddr, hnum, dif, | 476 | INADDR_ANY, hnum, dif, |
| 477 | hslot2, slot2); | 477 | hslot2, slot2); |
| 478 | } | 478 | } |
| 479 | rcu_read_unlock(); | 479 | rcu_read_unlock(); |
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index c177aea88c0b..90824852f598 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c | |||
| @@ -259,8 +259,8 @@ static struct sock *__udp6_lib_lookup(struct net *net, | |||
| 259 | if (hslot->count < hslot2->count) | 259 | if (hslot->count < hslot2->count) |
| 260 | goto begin; | 260 | goto begin; |
| 261 | 261 | ||
| 262 | result = udp6_lib_lookup2(net, &in6addr_any, sport, | 262 | result = udp6_lib_lookup2(net, saddr, sport, |
| 263 | daddr, hnum, dif, | 263 | &in6addr_any, hnum, dif, |
| 264 | hslot2, slot2); | 264 | hslot2, slot2); |
| 265 | } | 265 | } |
| 266 | rcu_read_unlock(); | 266 | rcu_read_unlock(); |
diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 06c33b68d8e5..b887e484ae04 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c | |||
| @@ -225,11 +225,11 @@ void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata, | |||
| 225 | switch (sdata->vif.type) { | 225 | switch (sdata->vif.type) { |
| 226 | case NL80211_IFTYPE_AP: | 226 | case NL80211_IFTYPE_AP: |
| 227 | sdata->vif.bss_conf.enable_beacon = | 227 | sdata->vif.bss_conf.enable_beacon = |
| 228 | !!rcu_dereference(sdata->u.ap.beacon); | 228 | !!sdata->u.ap.beacon; |
| 229 | break; | 229 | break; |
| 230 | case NL80211_IFTYPE_ADHOC: | 230 | case NL80211_IFTYPE_ADHOC: |
| 231 | sdata->vif.bss_conf.enable_beacon = | 231 | sdata->vif.bss_conf.enable_beacon = |
| 232 | !!rcu_dereference(sdata->u.ibss.presp); | 232 | !!sdata->u.ibss.presp; |
| 233 | break; | 233 | break; |
| 234 | case NL80211_IFTYPE_MESH_POINT: | 234 | case NL80211_IFTYPE_MESH_POINT: |
| 235 | sdata->vif.bss_conf.enable_beacon = true; | 235 | sdata->vif.bss_conf.enable_beacon = true; |
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index 58e3e3a61d99..859ee5f3d941 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c | |||
| @@ -750,9 +750,6 @@ ieee80211_mesh_rx_mgmt(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb) | |||
| 750 | 750 | ||
| 751 | switch (fc & IEEE80211_FCTL_STYPE) { | 751 | switch (fc & IEEE80211_FCTL_STYPE) { |
| 752 | case IEEE80211_STYPE_ACTION: | 752 | case IEEE80211_STYPE_ACTION: |
| 753 | if (skb->len < IEEE80211_MIN_ACTION_SIZE) | ||
| 754 | return RX_DROP_MONITOR; | ||
| 755 | /* fall through */ | ||
| 756 | case IEEE80211_STYPE_PROBE_RESP: | 753 | case IEEE80211_STYPE_PROBE_RESP: |
| 757 | case IEEE80211_STYPE_BEACON: | 754 | case IEEE80211_STYPE_BEACON: |
| 758 | skb_queue_tail(&ifmsh->skb_queue, skb); | 755 | skb_queue_tail(&ifmsh->skb_queue, skb); |
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index f0accf622cd7..04ea07f0e78a 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
| @@ -1974,6 +1974,11 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) | |||
| 1974 | goto handled; | 1974 | goto handled; |
| 1975 | } | 1975 | } |
| 1976 | break; | 1976 | break; |
| 1977 | case MESH_PLINK_CATEGORY: | ||
| 1978 | case MESH_PATH_SEL_CATEGORY: | ||
| 1979 | if (ieee80211_vif_is_mesh(&sdata->vif)) | ||
| 1980 | return ieee80211_mesh_rx_mgmt(sdata, rx->skb); | ||
| 1981 | break; | ||
| 1977 | } | 1982 | } |
| 1978 | 1983 | ||
| 1979 | /* | 1984 | /* |
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index 56422d894351..fb12cec4d333 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c | |||
| @@ -93,12 +93,18 @@ struct sta_info *sta_info_get(struct ieee80211_sub_if_data *sdata, | |||
| 93 | struct ieee80211_local *local = sdata->local; | 93 | struct ieee80211_local *local = sdata->local; |
| 94 | struct sta_info *sta; | 94 | struct sta_info *sta; |
| 95 | 95 | ||
| 96 | sta = rcu_dereference(local->sta_hash[STA_HASH(addr)]); | 96 | sta = rcu_dereference_check(local->sta_hash[STA_HASH(addr)], |
| 97 | rcu_read_lock_held() || | ||
| 98 | lockdep_is_held(&local->sta_lock) || | ||
| 99 | lockdep_is_held(&local->sta_mtx)); | ||
| 97 | while (sta) { | 100 | while (sta) { |
| 98 | if (sta->sdata == sdata && | 101 | if (sta->sdata == sdata && |
| 99 | memcmp(sta->sta.addr, addr, ETH_ALEN) == 0) | 102 | memcmp(sta->sta.addr, addr, ETH_ALEN) == 0) |
| 100 | break; | 103 | break; |
| 101 | sta = rcu_dereference(sta->hnext); | 104 | sta = rcu_dereference_check(sta->hnext, |
| 105 | rcu_read_lock_held() || | ||
| 106 | lockdep_is_held(&local->sta_lock) || | ||
| 107 | lockdep_is_held(&local->sta_mtx)); | ||
| 102 | } | 108 | } |
| 103 | return sta; | 109 | return sta; |
| 104 | } | 110 | } |
| @@ -113,13 +119,19 @@ struct sta_info *sta_info_get_bss(struct ieee80211_sub_if_data *sdata, | |||
| 113 | struct ieee80211_local *local = sdata->local; | 119 | struct ieee80211_local *local = sdata->local; |
| 114 | struct sta_info *sta; | 120 | struct sta_info *sta; |
| 115 | 121 | ||
| 116 | sta = rcu_dereference(local->sta_hash[STA_HASH(addr)]); | 122 | sta = rcu_dereference_check(local->sta_hash[STA_HASH(addr)], |
| 123 | rcu_read_lock_held() || | ||
| 124 | lockdep_is_held(&local->sta_lock) || | ||
| 125 | lockdep_is_held(&local->sta_mtx)); | ||
| 117 | while (sta) { | 126 | while (sta) { |
| 118 | if ((sta->sdata == sdata || | 127 | if ((sta->sdata == sdata || |
| 119 | sta->sdata->bss == sdata->bss) && | 128 | sta->sdata->bss == sdata->bss) && |
| 120 | memcmp(sta->sta.addr, addr, ETH_ALEN) == 0) | 129 | memcmp(sta->sta.addr, addr, ETH_ALEN) == 0) |
| 121 | break; | 130 | break; |
| 122 | sta = rcu_dereference(sta->hnext); | 131 | sta = rcu_dereference_check(sta->hnext, |
| 132 | rcu_read_lock_held() || | ||
| 133 | lockdep_is_held(&local->sta_lock) || | ||
| 134 | lockdep_is_held(&local->sta_mtx)); | ||
| 123 | } | 135 | } |
| 124 | return sta; | 136 | return sta; |
| 125 | } | 137 | } |
diff --git a/net/x25/af_x25.c b/net/x25/af_x25.c index e56f711baccc..cbddd0cb83f1 100644 --- a/net/x25/af_x25.c +++ b/net/x25/af_x25.c | |||
| @@ -83,6 +83,41 @@ struct compat_x25_subscrip_struct { | |||
| 83 | }; | 83 | }; |
| 84 | #endif | 84 | #endif |
| 85 | 85 | ||
| 86 | |||
| 87 | int x25_parse_address_block(struct sk_buff *skb, | ||
| 88 | struct x25_address *called_addr, | ||
| 89 | struct x25_address *calling_addr) | ||
| 90 | { | ||
| 91 | unsigned char len; | ||
| 92 | int needed; | ||
| 93 | int rc; | ||
| 94 | |||
| 95 | if (skb->len < 1) { | ||
| 96 | /* packet has no address block */ | ||
| 97 | rc = 0; | ||
| 98 | goto empty; | ||
| 99 | } | ||
| 100 | |||
| 101 | len = *skb->data; | ||
| 102 | needed = 1 + (len >> 4) + (len & 0x0f); | ||
| 103 | |||
| 104 | if (skb->len < needed) { | ||
| 105 | /* packet is too short to hold the addresses it claims | ||
| 106 | to hold */ | ||
| 107 | rc = -1; | ||
| 108 | goto empty; | ||
| 109 | } | ||
| 110 | |||
| 111 | return x25_addr_ntoa(skb->data, called_addr, calling_addr); | ||
| 112 | |||
| 113 | empty: | ||
| 114 | *called_addr->x25_addr = 0; | ||
| 115 | *calling_addr->x25_addr = 0; | ||
| 116 | |||
| 117 | return rc; | ||
| 118 | } | ||
| 119 | |||
| 120 | |||
| 86 | int x25_addr_ntoa(unsigned char *p, struct x25_address *called_addr, | 121 | int x25_addr_ntoa(unsigned char *p, struct x25_address *called_addr, |
| 87 | struct x25_address *calling_addr) | 122 | struct x25_address *calling_addr) |
| 88 | { | 123 | { |
| @@ -554,7 +589,8 @@ static int x25_create(struct net *net, struct socket *sock, int protocol, | |||
| 554 | x25->facilities.winsize_out = X25_DEFAULT_WINDOW_SIZE; | 589 | x25->facilities.winsize_out = X25_DEFAULT_WINDOW_SIZE; |
| 555 | x25->facilities.pacsize_in = X25_DEFAULT_PACKET_SIZE; | 590 | x25->facilities.pacsize_in = X25_DEFAULT_PACKET_SIZE; |
| 556 | x25->facilities.pacsize_out = X25_DEFAULT_PACKET_SIZE; | 591 | x25->facilities.pacsize_out = X25_DEFAULT_PACKET_SIZE; |
| 557 | x25->facilities.throughput = X25_DEFAULT_THROUGHPUT; | 592 | x25->facilities.throughput = 0; /* by default don't negotiate |
| 593 | throughput */ | ||
| 558 | x25->facilities.reverse = X25_DEFAULT_REVERSE; | 594 | x25->facilities.reverse = X25_DEFAULT_REVERSE; |
| 559 | x25->dte_facilities.calling_len = 0; | 595 | x25->dte_facilities.calling_len = 0; |
| 560 | x25->dte_facilities.called_len = 0; | 596 | x25->dte_facilities.called_len = 0; |
| @@ -922,16 +958,26 @@ int x25_rx_call_request(struct sk_buff *skb, struct x25_neigh *nb, | |||
| 922 | /* | 958 | /* |
| 923 | * Extract the X.25 addresses and convert them to ASCII strings, | 959 | * Extract the X.25 addresses and convert them to ASCII strings, |
| 924 | * and remove them. | 960 | * and remove them. |
| 961 | * | ||
| 962 | * Address block is mandatory in call request packets | ||
| 925 | */ | 963 | */ |
| 926 | addr_len = x25_addr_ntoa(skb->data, &source_addr, &dest_addr); | 964 | addr_len = x25_parse_address_block(skb, &source_addr, &dest_addr); |
| 965 | if (addr_len <= 0) | ||
| 966 | goto out_clear_request; | ||
| 927 | skb_pull(skb, addr_len); | 967 | skb_pull(skb, addr_len); |
| 928 | 968 | ||
| 929 | /* | 969 | /* |
| 930 | * Get the length of the facilities, skip past them for the moment | 970 | * Get the length of the facilities, skip past them for the moment |
| 931 | * get the call user data because this is needed to determine | 971 | * get the call user data because this is needed to determine |
| 932 | * the correct listener | 972 | * the correct listener |
| 973 | * | ||
| 974 | * Facilities length is mandatory in call request packets | ||
| 933 | */ | 975 | */ |
| 976 | if (skb->len < 1) | ||
| 977 | goto out_clear_request; | ||
| 934 | len = skb->data[0] + 1; | 978 | len = skb->data[0] + 1; |
| 979 | if (skb->len < len) | ||
| 980 | goto out_clear_request; | ||
| 935 | skb_pull(skb,len); | 981 | skb_pull(skb,len); |
| 936 | 982 | ||
| 937 | /* | 983 | /* |
| @@ -1415,9 +1461,20 @@ static int x25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) | |||
| 1415 | if (facilities.winsize_in < 1 || | 1461 | if (facilities.winsize_in < 1 || |
| 1416 | facilities.winsize_in > 127) | 1462 | facilities.winsize_in > 127) |
| 1417 | break; | 1463 | break; |
| 1418 | if (facilities.throughput < 0x03 || | 1464 | if (facilities.throughput) { |
| 1419 | facilities.throughput > 0xDD) | 1465 | int out = facilities.throughput & 0xf0; |
| 1420 | break; | 1466 | int in = facilities.throughput & 0x0f; |
| 1467 | if (!out) | ||
| 1468 | facilities.throughput |= | ||
| 1469 | X25_DEFAULT_THROUGHPUT << 4; | ||
| 1470 | else if (out < 0x30 || out > 0xD0) | ||
| 1471 | break; | ||
| 1472 | if (!in) | ||
| 1473 | facilities.throughput |= | ||
| 1474 | X25_DEFAULT_THROUGHPUT; | ||
| 1475 | else if (in < 0x03 || in > 0x0D) | ||
| 1476 | break; | ||
| 1477 | } | ||
| 1421 | if (facilities.reverse && | 1478 | if (facilities.reverse && |
| 1422 | (facilities.reverse & 0x81) != 0x81) | 1479 | (facilities.reverse & 0x81) != 0x81) |
| 1423 | break; | 1480 | break; |
diff --git a/net/x25/x25_facilities.c b/net/x25/x25_facilities.c index a21f6646eb3a..771bab00754b 100644 --- a/net/x25/x25_facilities.c +++ b/net/x25/x25_facilities.c | |||
| @@ -35,7 +35,7 @@ int x25_parse_facilities(struct sk_buff *skb, struct x25_facilities *facilities, | |||
| 35 | struct x25_dte_facilities *dte_facs, unsigned long *vc_fac_mask) | 35 | struct x25_dte_facilities *dte_facs, unsigned long *vc_fac_mask) |
| 36 | { | 36 | { |
| 37 | unsigned char *p = skb->data; | 37 | unsigned char *p = skb->data; |
| 38 | unsigned int len = *p++; | 38 | unsigned int len; |
| 39 | 39 | ||
| 40 | *vc_fac_mask = 0; | 40 | *vc_fac_mask = 0; |
| 41 | 41 | ||
| @@ -50,6 +50,14 @@ int x25_parse_facilities(struct sk_buff *skb, struct x25_facilities *facilities, | |||
| 50 | memset(dte_facs->called_ae, '\0', sizeof(dte_facs->called_ae)); | 50 | memset(dte_facs->called_ae, '\0', sizeof(dte_facs->called_ae)); |
| 51 | memset(dte_facs->calling_ae, '\0', sizeof(dte_facs->calling_ae)); | 51 | memset(dte_facs->calling_ae, '\0', sizeof(dte_facs->calling_ae)); |
| 52 | 52 | ||
| 53 | if (skb->len < 1) | ||
| 54 | return 0; | ||
| 55 | |||
| 56 | len = *p++; | ||
| 57 | |||
| 58 | if (len >= skb->len) | ||
| 59 | return -1; | ||
| 60 | |||
| 53 | while (len > 0) { | 61 | while (len > 0) { |
| 54 | switch (*p & X25_FAC_CLASS_MASK) { | 62 | switch (*p & X25_FAC_CLASS_MASK) { |
| 55 | case X25_FAC_CLASS_A: | 63 | case X25_FAC_CLASS_A: |
| @@ -247,6 +255,8 @@ int x25_negotiate_facilities(struct sk_buff *skb, struct sock *sk, | |||
| 247 | memcpy(new, ours, sizeof(*new)); | 255 | memcpy(new, ours, sizeof(*new)); |
| 248 | 256 | ||
| 249 | len = x25_parse_facilities(skb, &theirs, dte, &x25->vc_facil_mask); | 257 | len = x25_parse_facilities(skb, &theirs, dte, &x25->vc_facil_mask); |
| 258 | if (len < 0) | ||
| 259 | return len; | ||
| 250 | 260 | ||
| 251 | /* | 261 | /* |
| 252 | * They want reverse charging, we won't accept it. | 262 | * They want reverse charging, we won't accept it. |
| @@ -259,9 +269,18 @@ int x25_negotiate_facilities(struct sk_buff *skb, struct sock *sk, | |||
| 259 | new->reverse = theirs.reverse; | 269 | new->reverse = theirs.reverse; |
| 260 | 270 | ||
| 261 | if (theirs.throughput) { | 271 | if (theirs.throughput) { |
| 262 | if (theirs.throughput < ours->throughput) { | 272 | int theirs_in = theirs.throughput & 0x0f; |
| 263 | SOCK_DEBUG(sk, "X.25: throughput negotiated down\n"); | 273 | int theirs_out = theirs.throughput & 0xf0; |
| 264 | new->throughput = theirs.throughput; | 274 | int ours_in = ours->throughput & 0x0f; |
| 275 | int ours_out = ours->throughput & 0xf0; | ||
| 276 | if (!ours_in || theirs_in < ours_in) { | ||
| 277 | SOCK_DEBUG(sk, "X.25: inbound throughput negotiated\n"); | ||
| 278 | new->throughput = (new->throughput & 0xf0) | theirs_in; | ||
| 279 | } | ||
| 280 | if (!ours_out || theirs_out < ours_out) { | ||
| 281 | SOCK_DEBUG(sk, | ||
| 282 | "X.25: outbound throughput negotiated\n"); | ||
| 283 | new->throughput = (new->throughput & 0x0f) | theirs_out; | ||
| 265 | } | 284 | } |
| 266 | } | 285 | } |
| 267 | 286 | ||
diff --git a/net/x25/x25_in.c b/net/x25/x25_in.c index a31b3b9e5966..372ac226e648 100644 --- a/net/x25/x25_in.c +++ b/net/x25/x25_in.c | |||
| @@ -90,6 +90,7 @@ static int x25_queue_rx_frame(struct sock *sk, struct sk_buff *skb, int more) | |||
| 90 | static int x25_state1_machine(struct sock *sk, struct sk_buff *skb, int frametype) | 90 | static int x25_state1_machine(struct sock *sk, struct sk_buff *skb, int frametype) |
| 91 | { | 91 | { |
| 92 | struct x25_address source_addr, dest_addr; | 92 | struct x25_address source_addr, dest_addr; |
| 93 | int len; | ||
| 93 | 94 | ||
| 94 | switch (frametype) { | 95 | switch (frametype) { |
| 95 | case X25_CALL_ACCEPTED: { | 96 | case X25_CALL_ACCEPTED: { |
| @@ -107,11 +108,17 @@ static int x25_state1_machine(struct sock *sk, struct sk_buff *skb, int frametyp | |||
| 107 | * Parse the data in the frame. | 108 | * Parse the data in the frame. |
| 108 | */ | 109 | */ |
| 109 | skb_pull(skb, X25_STD_MIN_LEN); | 110 | skb_pull(skb, X25_STD_MIN_LEN); |
| 110 | skb_pull(skb, x25_addr_ntoa(skb->data, &source_addr, &dest_addr)); | 111 | |
| 111 | skb_pull(skb, | 112 | len = x25_parse_address_block(skb, &source_addr, |
| 112 | x25_parse_facilities(skb, &x25->facilities, | 113 | &dest_addr); |
| 114 | if (len > 0) | ||
| 115 | skb_pull(skb, len); | ||
| 116 | |||
| 117 | len = x25_parse_facilities(skb, &x25->facilities, | ||
| 113 | &x25->dte_facilities, | 118 | &x25->dte_facilities, |
| 114 | &x25->vc_facil_mask)); | 119 | &x25->vc_facil_mask); |
| 120 | if (len > 0) | ||
| 121 | skb_pull(skb, len); | ||
| 115 | /* | 122 | /* |
| 116 | * Copy any Call User Data. | 123 | * Copy any Call User Data. |
| 117 | */ | 124 | */ |
diff --git a/security/selinux/ss/avtab.h b/security/selinux/ss/avtab.h index 8da6a8428086..cd4f734e2749 100644 --- a/security/selinux/ss/avtab.h +++ b/security/selinux/ss/avtab.h | |||
| @@ -82,7 +82,7 @@ struct avtab_node *avtab_search_node_next(struct avtab_node *node, int specified | |||
| 82 | void avtab_cache_init(void); | 82 | void avtab_cache_init(void); |
| 83 | void avtab_cache_destroy(void); | 83 | void avtab_cache_destroy(void); |
| 84 | 84 | ||
| 85 | #define MAX_AVTAB_HASH_BITS 13 | 85 | #define MAX_AVTAB_HASH_BITS 11 |
| 86 | #define MAX_AVTAB_HASH_BUCKETS (1 << MAX_AVTAB_HASH_BITS) | 86 | #define MAX_AVTAB_HASH_BUCKETS (1 << MAX_AVTAB_HASH_BITS) |
| 87 | #define MAX_AVTAB_HASH_MASK (MAX_AVTAB_HASH_BUCKETS-1) | 87 | #define MAX_AVTAB_HASH_MASK (MAX_AVTAB_HASH_BUCKETS-1) |
| 88 | #define MAX_AVTAB_SIZE MAX_AVTAB_HASH_BUCKETS | 88 | #define MAX_AVTAB_SIZE MAX_AVTAB_HASH_BUCKETS |
