aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/HOWTO3
-rw-r--r--Documentation/SubmitChecklist2
-rw-r--r--Documentation/video4linux/CARDLIST.em28xx2
-rw-r--r--Documentation/video4linux/gspca.txt1
-rw-r--r--MAINTAINERS3
-rw-r--r--Makefile2
-rw-r--r--arch/ia64/include/asm/sections.h3
-rw-r--r--arch/ia64/kernel/head.S9
-rw-r--r--arch/ia64/kernel/vmlinux.lds.S8
-rw-r--r--arch/ia64/mm/contig.c2
-rw-r--r--arch/ia64/mm/discontig.c2
-rw-r--r--arch/mips/Kconfig53
-rw-r--r--arch/mips/kernel/Makefile1
-rw-r--r--arch/mips/kernel/cevt-r4k.c173
-rw-r--r--arch/mips/kernel/cevt-smtc.c321
-rw-r--r--arch/mips/kernel/cpu-probe.c10
-rw-r--r--arch/mips/kernel/entry.S10
-rw-r--r--arch/mips/kernel/genex.S4
-rw-r--r--arch/mips/kernel/head.S1
-rw-r--r--arch/mips/kernel/mips-mt-fpaff.c2
-rw-r--r--arch/mips/kernel/process.c19
-rw-r--r--arch/mips/kernel/ptrace.c2
-rw-r--r--arch/mips/kernel/smtc.c260
-rw-r--r--arch/mips/kernel/traps.c6
-rw-r--r--arch/mips/mti-malta/Makefile2
-rw-r--r--arch/mips/mti-malta/malta-smtc.c9
-rw-r--r--arch/mips/sibyte/swarm/Makefile3
-rw-r--r--arch/mips/sibyte/swarm/platform.c85
-rw-r--r--arch/mn10300/kernel/irq.c71
-rw-r--r--arch/mn10300/unit-asb2303/unit-init.c2
-rw-r--r--arch/mn10300/unit-asb2305/unit-init.c2
-rw-r--r--arch/powerpc/boot/dts/holly.dts106
-rw-r--r--arch/powerpc/kernel/idle.c6
-rw-r--r--arch/powerpc/platforms/fsl_uli1575.c12
-rw-r--r--arch/s390/kernel/time.c2
-rw-r--r--arch/s390/lib/delay.c88
-rw-r--r--arch/x86/boot/compressed/relocs.c2
-rw-r--r--arch/x86/kernel/acpi/boot.c16
-rw-r--r--arch/x86/kernel/cpu/mtrr/main.c2
-rw-r--r--arch/x86/kernel/kgdb.c7
-rw-r--r--arch/x86/kernel/pci-gart_64.c20
-rw-r--r--arch/x86/kernel/vmi_32.c2
-rw-r--r--drivers/accessibility/braille/braille_console.c13
-rw-r--r--drivers/acpi/glue.c5
-rw-r--r--drivers/acpi/sleep/proc.c10
-rw-r--r--drivers/bluetooth/bpa10x.c2
-rw-r--r--drivers/bluetooth/btusb.c8
-rw-r--r--drivers/dma/dw_dmac.c2
-rw-r--r--drivers/ide/Kconfig4
-rw-r--r--drivers/ide/ide-cd.c6
-rw-r--r--drivers/ide/ide-dma.c2
-rw-r--r--drivers/ide/ide-probe.c2
-rw-r--r--drivers/ide/mips/Makefile1
-rw-r--r--drivers/ide/mips/swarm.c197
-rw-r--r--drivers/leds/leds-fsg.c28
-rw-r--r--drivers/leds/leds-pca955x.c70
-rw-r--r--drivers/md/dm-mpath.c16
-rw-r--r--drivers/md/dm.c12
-rw-r--r--drivers/media/common/tuners/tuner-xc2028.h1
-rw-r--r--drivers/media/dvb/b2c2/flexcop-fe-tuner.c1
-rw-r--r--drivers/media/dvb/dvb-core/dmxdev.c16
-rw-r--r--drivers/media/dvb/dvb-core/dvb_demux.c16
-rw-r--r--drivers/media/dvb/frontends/s5h1420.c11
-rw-r--r--drivers/media/dvb/frontends/s5h1420.h8
-rw-r--r--drivers/media/dvb/siano/sms-cards.c4
-rw-r--r--drivers/media/video/bt8xx/bttv-driver.c2
-rw-r--r--drivers/media/video/cafe_ccic.c1
-rw-r--r--drivers/media/video/cpia2/cpia2_usb.c5
-rw-r--r--drivers/media/video/cx18/cx18-cards.c2
-rw-r--r--drivers/media/video/em28xx/em28xx-audio.c12
-rw-r--r--drivers/media/video/em28xx/em28xx-cards.c55
-rw-r--r--drivers/media/video/em28xx/em28xx-dvb.c9
-rw-r--r--drivers/media/video/gspca/gspca.c3
-rw-r--r--drivers/media/video/gspca/pac7311.c1
-rw-r--r--drivers/media/video/gspca/sonixb.c4
-rw-r--r--drivers/media/video/gspca/sonixj.c19
-rw-r--r--drivers/media/video/gspca/spca561.c2
-rw-r--r--drivers/media/video/gspca/zc3xx.c4
-rw-r--r--drivers/media/video/ov511.c6
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-devattr.c2
-rw-r--r--drivers/media/video/s2255drv.c3
-rw-r--r--drivers/media/video/uvc/uvc_ctrl.c2
-rw-r--r--drivers/media/video/w9968cf.c2
-rw-r--r--drivers/media/video/wm8739.c4
-rw-r--r--drivers/media/video/zoran_card.c2
-rw-r--r--drivers/media/video/zoran_driver.c15
-rw-r--r--drivers/mfd/Kconfig4
-rw-r--r--drivers/mfd/asic3.c2
-rw-r--r--drivers/mmc/host/atmel-mci.c6
-rw-r--r--drivers/net/e1000e/e1000.h5
-rw-r--r--drivers/net/e1000e/ethtool.c9
-rw-r--r--drivers/net/e1000e/ich8lan.c78
-rw-r--r--drivers/net/e1000e/netdev.c68
-rw-r--r--drivers/net/e1000e/param.c30
-rw-r--r--drivers/pci/pci-sysfs.c19
-rw-r--r--drivers/rtc/rtc-dev.c15
-rw-r--r--drivers/s390/cio/qdio_setup.c55
-rw-r--r--drivers/spi/orion_spi.c2
-rw-r--r--drivers/spi/pxa2xx_spi.c4
-rw-r--r--drivers/video/console/fbcon.c6
-rw-r--r--drivers/video/console/fbcon.h2
-rw-r--r--fs/inotify_user.c27
-rw-r--r--fs/ramfs/file-nommu.c2
-rw-r--r--include/asm-mips/cevt-r4k.h46
-rw-r--r--include/asm-mips/irqflags.h26
-rw-r--r--include/asm-mips/mipsregs.h6
-rw-r--r--include/asm-mips/smtc.h8
-rw-r--r--include/asm-mips/sn/mapped_kernel.h8
-rw-r--r--include/asm-mips/stackframe.h72
-rw-r--r--include/asm-x86/uaccess_64.h1
-rw-r--r--include/linux/hrtimer.h18
-rw-r--r--include/linux/ide.h4
-rw-r--r--include/linux/ramfs.h1
-rw-r--r--include/linux/stacktrace.h2
-rw-r--r--init/main.c9
-rw-r--r--kernel/hrtimer.c95
-rw-r--r--kernel/kgdb.c3
-rw-r--r--kernel/posix-timers.c2
-rw-r--r--kernel/sched.c4
-rw-r--r--kernel/time/tick-broadcast.c6
-rw-r--r--kernel/time/tick-sched.c2
-rw-r--r--kernel/trace/trace_sysprof.c2
-rw-r--r--mm/page_alloc.c13
-rw-r--r--mm/page_isolation.c12
-rw-r--r--mm/slob.c2
-rw-r--r--mm/tiny-shmem.c6
-rw-r--r--net/ax25/af_ax25.c3
-rw-r--r--net/ax25/ax25_std_timer.c8
-rw-r--r--net/core/dev.c43
-rw-r--r--net/core/rtnetlink.c2
-rw-r--r--net/ipv4/tcp_hybla.c6
-rw-r--r--net/ipv4/tcp_input.c3
-rw-r--r--net/netrom/af_netrom.c2
-rw-r--r--scripts/mod/modpost.c6
-rw-r--r--security/selinux/ss/services.c11
-rw-r--r--sound/pci/hda/patch_sigmatel.c2
-rw-r--r--sound/ppc/awacs.c50
-rw-r--r--sound/soc/codecs/cs4270.c25
-rw-r--r--sound/soc/codecs/wm8753.c4
139 files changed, 1732 insertions, 1041 deletions
diff --git a/Documentation/HOWTO b/Documentation/HOWTO
index c2371c5a98f..48a3955f05f 100644
--- a/Documentation/HOWTO
+++ b/Documentation/HOWTO
@@ -77,7 +77,8 @@ documentation files are also added which explain how to use the feature.
When a kernel change causes the interface that the kernel exposes to
userspace to change, it is recommended that you send the information or
a patch to the manual pages explaining the change to the manual pages
-maintainer at mtk.manpages@gmail.com.
+maintainer at mtk.manpages@gmail.com, and CC the list
+linux-api@vger.kernel.org.
Here is a list of files that are in the kernel source tree that are
required reading:
diff --git a/Documentation/SubmitChecklist b/Documentation/SubmitChecklist
index da10e071424..21f0795af20 100644
--- a/Documentation/SubmitChecklist
+++ b/Documentation/SubmitChecklist
@@ -67,6 +67,8 @@ kernel patches.
19: All new userspace interfaces are documented in Documentation/ABI/.
See Documentation/ABI/README for more information.
+ Patches that change userspace interfaces should be CCed to
+ linux-api@vger.kernel.org.
20: Check that it all passes `make headers_check'.
diff --git a/Documentation/video4linux/CARDLIST.em28xx b/Documentation/video4linux/CARDLIST.em28xx
index 89c7f32abf9..53449cb99b1 100644
--- a/Documentation/video4linux/CARDLIST.em28xx
+++ b/Documentation/video4linux/CARDLIST.em28xx
@@ -46,7 +46,7 @@
45 -> Pinnacle PCTV DVB-T (em2870)
46 -> Compro, VideoMate U3 (em2870) [185b:2870]
47 -> KWorld DVB-T 305U (em2880) [eb1a:e305]
- 48 -> KWorld DVB-T 310U (em2880)
+ 48 -> KWorld DVB-T 310U (em2880) [eb1a:e310]
49 -> MSI DigiVox A/D (em2880) [eb1a:e310]
50 -> MSI DigiVox A/D II (em2880) [eb1a:e320]
51 -> Terratec Hybrid XS Secam (em2880) [0ccd:004c]
diff --git a/Documentation/video4linux/gspca.txt b/Documentation/video4linux/gspca.txt
index 0f03900c48f..9a3e4d797fa 100644
--- a/Documentation/video4linux/gspca.txt
+++ b/Documentation/video4linux/gspca.txt
@@ -190,6 +190,7 @@ pac7311 093a:260f SnakeCam
pac7311 093a:2621 PAC731x
pac7311 093a:2624 PAC7302
pac7311 093a:2626 Labtec 2200
+pac7311 093a:262a Webcam 300k
zc3xx 0ac8:0302 Z-star Vimicro zc0302
vc032x 0ac8:0321 Vimicro generic vc0321
vc032x 0ac8:0323 Vimicro Vc0323
diff --git a/MAINTAINERS b/MAINTAINERS
index e6aa6aa789f..e6e48148362 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1205,9 +1205,7 @@ M: hpa@zytor.com
S: Maintained
CPUSETS
-P: Paul Jackson
P: Paul Menage
-M: pj@sgi.com
M: menage@google.com
L: linux-kernel@vger.kernel.org
W: http://www.bullopensource.org/cpuset/
@@ -2719,6 +2717,7 @@ MAN-PAGES: MANUAL PAGES FOR LINUX -- Sections 2, 3, 4, 5, and 7
P: Michael Kerrisk
M: mtk.manpages@gmail.com
W: http://www.kernel.org/doc/man-pages
+L: linux-man@vger.kernel.org
S: Supported
MARVELL LIBERTAS WIRELESS DRIVER
diff --git a/Makefile b/Makefile
index 1d03c1644dd..ce9eceb2538 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
VERSION = 2
PATCHLEVEL = 6
SUBLEVEL = 27
-EXTRAVERSION = -rc8
+EXTRAVERSION = -rc9
NAME = Rotary Wombat
# *DOCUMENTATION*
diff --git a/arch/ia64/include/asm/sections.h b/arch/ia64/include/asm/sections.h
index f6679989103..1a873b36a4a 100644
--- a/arch/ia64/include/asm/sections.h
+++ b/arch/ia64/include/asm/sections.h
@@ -11,6 +11,9 @@
#include <asm-generic/sections.h>
extern char __per_cpu_start[], __per_cpu_end[], __phys_per_cpu_start[];
+#ifdef CONFIG_SMP
+extern char __cpu0_per_cpu[];
+#endif
extern char __start___vtop_patchlist[], __end___vtop_patchlist[];
extern char __start___rse_patchlist[], __end___rse_patchlist[];
extern char __start___mckinley_e9_bundles[], __end___mckinley_e9_bundles[];
diff --git a/arch/ia64/kernel/head.S b/arch/ia64/kernel/head.S
index 8bdea8eb62e..66e491d8baa 100644
--- a/arch/ia64/kernel/head.S
+++ b/arch/ia64/kernel/head.S
@@ -367,16 +367,17 @@ start_ap:
;;
#else
(isAP) br.few 2f
- mov r20=r19
- sub r19=r19,r18
+ movl r20=__cpu0_per_cpu
;;
shr.u r18=r18,3
1:
- ld8 r21=[r20],8;;
- st8[r19]=r21,8
+ ld8 r21=[r19],8;;
+ st8[r20]=r21,8
adds r18=-1,r18;;
cmp4.lt p7,p6=0,r18
(p7) br.cond.dptk.few 1b
+ mov r19=r20
+ ;;
2:
#endif
tpa r19=r19
diff --git a/arch/ia64/kernel/vmlinux.lds.S b/arch/ia64/kernel/vmlinux.lds.S
index de71da811cd..10a7d47e851 100644
--- a/arch/ia64/kernel/vmlinux.lds.S
+++ b/arch/ia64/kernel/vmlinux.lds.S
@@ -215,9 +215,6 @@ SECTIONS
/* Per-cpu data: */
percpu : { } :percpu
. = ALIGN(PERCPU_PAGE_SIZE);
-#ifdef CONFIG_SMP
- . = . + PERCPU_PAGE_SIZE; /* cpu0 per-cpu space */
-#endif
__phys_per_cpu_start = .;
.data.percpu PERCPU_ADDR : AT(__phys_per_cpu_start - LOAD_OFFSET)
{
@@ -233,6 +230,11 @@ SECTIONS
data : { } :data
.data : AT(ADDR(.data) - LOAD_OFFSET)
{
+#ifdef CONFIG_SMP
+ . = ALIGN(PERCPU_PAGE_SIZE);
+ __cpu0_per_cpu = .;
+ . = . + PERCPU_PAGE_SIZE; /* cpu0 per-cpu space */
+#endif
DATA_DATA
*(.data1)
*(.gnu.linkonce.d*)
diff --git a/arch/ia64/mm/contig.c b/arch/ia64/mm/contig.c
index e566ff43884..0ee085efbe2 100644
--- a/arch/ia64/mm/contig.c
+++ b/arch/ia64/mm/contig.c
@@ -163,7 +163,7 @@ per_cpu_init (void)
* get_zeroed_page().
*/
if (first_time) {
- void *cpu0_data = __phys_per_cpu_start - PERCPU_PAGE_SIZE;
+ void *cpu0_data = __cpu0_per_cpu;
first_time=0;
diff --git a/arch/ia64/mm/discontig.c b/arch/ia64/mm/discontig.c
index 78026aabaa7..d8c5fcd89e5 100644
--- a/arch/ia64/mm/discontig.c
+++ b/arch/ia64/mm/discontig.c
@@ -144,7 +144,7 @@ static void *per_cpu_node_setup(void *cpu_data, int node)
for_each_possible_early_cpu(cpu) {
if (cpu == 0) {
- void *cpu0_data = __phys_per_cpu_start - PERCPU_PAGE_SIZE;
+ void *cpu0_data = __cpu0_per_cpu;
__per_cpu_offset[cpu] = (char*)cpu0_data -
__per_cpu_start;
} else if (node == node_cpuid[cpu].nid) {
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index 49896a2a1d7..1e06d233fa8 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -211,6 +211,7 @@ config MIPS_MALTA
select SYS_SUPPORTS_64BIT_KERNEL
select SYS_SUPPORTS_BIG_ENDIAN
select SYS_SUPPORTS_LITTLE_ENDIAN
+ select SYS_SUPPORTS_MIPS_CMP if BROKEN # because SYNC_R4K is broken
select SYS_SUPPORTS_MULTITHREADING
select SYS_SUPPORTS_SMARTMIPS
help
@@ -1403,7 +1404,6 @@ config MIPS_MT_SMTC
depends on CPU_MIPS32_R2
#depends on CPU_MIPS64_R2 # once there is hardware ...
depends on SYS_SUPPORTS_MULTITHREADING
- select GENERIC_CLOCKEVENTS_BROADCAST
select CPU_MIPSR2_IRQ_VI
select CPU_MIPSR2_IRQ_EI
select MIPS_MT
@@ -1451,32 +1451,17 @@ config MIPS_VPE_LOADER
Includes a loader for loading an elf relocatable object
onto another VPE and running it.
-config MIPS_MT_SMTC_INSTANT_REPLAY
- bool "Low-latency Dispatch of Deferred SMTC IPIs"
- depends on MIPS_MT_SMTC && !PREEMPT
- default y
- help
- SMTC pseudo-interrupts between TCs are deferred and queued
- if the target TC is interrupt-inhibited (IXMT). In the first
- SMTC prototypes, these queued IPIs were serviced on return
- to user mode, or on entry into the kernel idle loop. The
- INSTANT_REPLAY option dispatches them as part of local_irq_restore()
- processing, which adds runtime overhead (hence the option to turn
- it off), but ensures that IPIs are handled promptly even under
- heavy I/O interrupt load.
-
config MIPS_MT_SMTC_IM_BACKSTOP
bool "Use per-TC register bits as backstop for inhibited IM bits"
depends on MIPS_MT_SMTC
- default y
+ default n
help
To support multiple TC microthreads acting as "CPUs" within
a VPE, VPE-wide interrupt mask bits must be specially manipulated
during interrupt handling. To support legacy drivers and interrupt
controller management code, SMTC has a "backstop" to track and
if necessary restore the interrupt mask. This has some performance
- impact on interrupt service overhead. Disable it only if you know
- what you are doing.
+ impact on interrupt service overhead.
config MIPS_MT_SMTC_IRQAFF
bool "Support IRQ affinity API"
@@ -1486,10 +1471,8 @@ config MIPS_MT_SMTC_IRQAFF
Enables SMP IRQ affinity API (/proc/irq/*/smp_affinity, etc.)
for SMTC Linux kernel. Requires platform support, of which
an example can be found in the MIPS kernel i8259 and Malta
- platform code. It is recommended that MIPS_MT_SMTC_INSTANT_REPLAY
- be enabled if MIPS_MT_SMTC_IRQAFF is used. Adds overhead to
- interrupt dispatch, and should be used only if you know what
- you are doing.
+ platform code. Adds some overhead to interrupt dispatch, and
+ should be used only if you know what you are doing.
config MIPS_VPE_LOADER_TOM
bool "Load VPE program into memory hidden from linux"
@@ -1517,6 +1500,18 @@ config MIPS_APSP_KSPD
"exit" syscall notifying other kernel modules the SP program is
exiting. You probably want to say yes here.
+config MIPS_CMP
+ bool "MIPS CMP framework support"
+ depends on SYS_SUPPORTS_MIPS_CMP
+ select SYNC_R4K if BROKEN
+ select SYS_SUPPORTS_SMP
+ select SYS_SUPPORTS_SCHED_SMT if SMP
+ select WEAK_ORDERING
+ default n
+ help
+ This is a placeholder option for the GCMP work. It will need to
+ be handled differently...
+
config SB1_PASS_1_WORKAROUNDS
bool
depends on CPU_SB1_PASS_1
@@ -1693,6 +1688,9 @@ config SMP
config SMP_UP
bool
+config SYS_SUPPORTS_MIPS_CMP
+ bool
+
config SYS_SUPPORTS_SMP
bool
@@ -1740,17 +1738,6 @@ config NR_CPUS
performance should round up your number of processors to the next
power of two.
-config MIPS_CMP
- bool "MIPS CMP framework support"
- depends on SMP
- select SYNC_R4K
- select SYS_SUPPORTS_SCHED_SMT
- select WEAK_ORDERING
- default n
- help
- This is a placeholder option for the GCMP work. It will need to
- be handled differently...
-
source "kernel/time/Kconfig"
#
diff --git a/arch/mips/kernel/Makefile b/arch/mips/kernel/Makefile
index 706f9397479..25775cb5400 100644
--- a/arch/mips/kernel/Makefile
+++ b/arch/mips/kernel/Makefile
@@ -10,6 +10,7 @@ obj-y += cpu-probe.o branch.o entry.o genex.o irq.o process.o \
obj-$(CONFIG_CEVT_BCM1480) += cevt-bcm1480.o
obj-$(CONFIG_CEVT_R4K) += cevt-r4k.o
+obj-$(CONFIG_MIPS_MT_SMTC) += cevt-smtc.o
obj-$(CONFIG_CEVT_DS1287) += cevt-ds1287.o
obj-$(CONFIG_CEVT_GT641XX) += cevt-gt641xx.o
obj-$(CONFIG_CEVT_SB1250) += cevt-sb1250.o
diff --git a/arch/mips/kernel/cevt-r4k.c b/arch/mips/kernel/cevt-r4k.c
index 24a2d907aa0..4a4c59f2737 100644
--- a/arch/mips/kernel/cevt-r4k.c
+++ b/arch/mips/kernel/cevt-r4k.c
@@ -12,6 +12,14 @@
#include <asm/smtc_ipi.h>
#include <asm/time.h>
+#include <asm/cevt-r4k.h>
+
+/*
+ * The SMTC Kernel for the 34K, 1004K, et. al. replaces several
+ * of these routines with SMTC-specific variants.
+ */
+
+#ifndef CONFIG_MIPS_MT_SMTC
static int mips_next_event(unsigned long delta,
struct clock_event_device *evt)
@@ -19,60 +27,27 @@ static int mips_next_event(unsigned long delta,
unsigned int cnt;
int res;
-#ifdef CONFIG_MIPS_MT_SMTC
- {
- unsigned long flags, vpflags;
- local_irq_save(flags);
- vpflags = dvpe();
-#endif
cnt = read_c0_count();
cnt += delta;
write_c0_compare(cnt);
res = ((int)(read_c0_count() - cnt) > 0) ? -ETIME : 0;
-#ifdef CONFIG_MIPS_MT_SMTC
- evpe(vpflags);
- local_irq_restore(flags);
- }
-#endif
return res;
}
-static void mips_set_mode(enum clock_event_mode mode,
- struct clock_event_device *evt)
+#endif /* CONFIG_MIPS_MT_SMTC */
+
+void mips_set_clock_mode(enum clock_event_mode mode,
+ struct clock_event_device *evt)
{
/* Nothing to do ... */
}
-static DEFINE_PER_CPU(struct clock_event_device, mips_clockevent_device);
-static int cp0_timer_irq_installed;
+DEFINE_PER_CPU(struct clock_event_device, mips_clockevent_device);
+int cp0_timer_irq_installed;
-/*
- * Timer ack for an R4k-compatible timer of a known frequency.
- */
-static void c0_timer_ack(void)
-{
- write_c0_compare(read_c0_compare());
-}
+#ifndef CONFIG_MIPS_MT_SMTC
-/*
- * Possibly handle a performance counter interrupt.
- * Return true if the timer interrupt should not be checked
- */
-static inline int handle_perf_irq(int r2)
-{
- /*
- * The performance counter overflow interrupt may be shared with the
- * timer interrupt (cp0_perfcount_irq < 0). If it is and a
- * performance counter has overflowed (perf_irq() == IRQ_HANDLED)
- * and we can't reliably determine if a counter interrupt has also
- * happened (!r2) then don't check for a timer interrupt.
- */
- return (cp0_perfcount_irq < 0) &&
- perf_irq() == IRQ_HANDLED &&
- !r2;
-}
-
-static irqreturn_t c0_compare_interrupt(int irq, void *dev_id)
+irqreturn_t c0_compare_interrupt(int irq, void *dev_id)
{
const int r2 = cpu_has_mips_r2;
struct clock_event_device *cd;
@@ -93,12 +68,8 @@ static irqreturn_t c0_compare_interrupt(int irq, void *dev_id)
* interrupt. Being the paranoiacs we are we check anyway.
*/
if (!r2 || (read_c0_cause() & (1 << 30))) {
- c0_timer_ack();
-#ifdef CONFIG_MIPS_MT_SMTC
- if (cpu_data[cpu].vpe_id)
- goto out;
- cpu = 0;
-#endif
+ /* Clear Count/Compare Interrupt */
+ write_c0_compare(read_c0_compare());
cd = &per_cpu(mips_clockevent_device, cpu);
cd->event_handler(cd);
}
@@ -107,65 +78,16 @@ out:
return IRQ_HANDLED;
}
-static struct irqaction c0_compare_irqaction = {
+#endif /* Not CONFIG_MIPS_MT_SMTC */
+
+struct irqaction c0_compare_irqaction = {
.handler = c0_compare_interrupt,
-#ifdef CONFIG_MIPS_MT_SMTC
- .flags = IRQF_DISABLED,
-#else
.flags = IRQF_DISABLED | IRQF_PERCPU,
-#endif
.name = "timer",
};
-#ifdef CONFIG_MIPS_MT_SMTC
-DEFINE_PER_CPU(struct clock_event_device, smtc_dummy_clockevent_device);
-
-static void smtc_set_mode(enum clock_event_mode mode,
- struct clock_event_device *evt)
-{
-}
-
-static void mips_broadcast(cpumask_t mask)
-{
- unsigned int cpu;
-
- for_each_cpu_mask(cpu, mask)
- smtc_send_ipi(cpu, SMTC_CLOCK_TICK, 0);
-}
-
-static void setup_smtc_dummy_clockevent_device(void)
-{
- //uint64_t mips_freq = mips_hpt_^frequency;
- unsigned int cpu = smp_processor_id();
- struct clock_event_device *cd;
- cd = &per_cpu(smtc_dummy_clockevent_device, cpu);
-
- cd->name = "SMTC";
- cd->features = CLOCK_EVT_FEAT_DUMMY;
-
- /* Calculate the min / max delta */
- cd->mult = 0; //div_sc((unsigned long) mips_freq, NSEC_PER_SEC, 32);
- cd->shift = 0; //32;
- cd->max_delta_ns = 0; //clockevent_delta2ns(0x7fffffff, cd);
- cd->min_delta_ns = 0; //clockevent_delta2ns(0x30, cd);
-
- cd->rating = 200;
- cd->irq = 17; //-1;
-// if (cpu)
-// cd->cpumask = CPU_MASK_ALL; // cpumask_of_cpu(cpu);
-// else
- cd->cpumask = cpumask_of_cpu(cpu);
-
- cd->set_mode = smtc_set_mode;
-
- cd->broadcast = mips_broadcast;
-
- clockevents_register_device(cd);
-}
-#endif
-
-static void mips_event_handler(struct clock_event_device *dev)
+void mips_event_handler(struct clock_event_device *dev)
{
}
@@ -177,7 +99,23 @@ static int c0_compare_int_pending(void)
return (read_c0_cause() >> cp0_compare_irq) & 0x100;
}
-static int c0_compare_int_usable(void)
+/*
+ * Compare interrupt can be routed and latched outside the core,
+ * so a single execution hazard barrier may not be enough to give
+ * it time to clear as seen in the Cause register. 4 time the
+ * pipeline depth seems reasonably conservative, and empirically
+ * works better in configurations with high CPU/bus clock ratios.
+ */
+
+#define compare_change_hazard() \
+ do { \
+ irq_disable_hazard(); \
+ irq_disable_hazard(); \
+ irq_disable_hazard(); \
+ irq_disable_hazard(); \
+ } while (0)
+
+int c0_compare_int_usable(void)
{
unsigned int delta;
unsigned int cnt;
@@ -187,7 +125,7 @@ static int c0_compare_int_usable(void)
*/
if (c0_compare_int_pending()) {
write_c0_compare(read_c0_count());
- irq_disable_hazard();
+ compare_change_hazard();
if (c0_compare_int_pending())
return 0;
}
@@ -196,7 +134,7 @@ static int c0_compare_int_usable(void)
cnt = read_c0_count();
cnt += delta;
write_c0_compare(cnt);
- irq_disable_hazard();
+ compare_change_hazard();
if ((int)(read_c0_count() - cnt) < 0)
break;
/* increase delta if the timer was already expired */
@@ -205,11 +143,12 @@ static int c0_compare_int_usable(void)
while ((int)(read_c0_count() - cnt) <= 0)
; /* Wait for expiry */
+ compare_change_hazard();
if (!c0_compare_int_pending())
return 0;
write_c0_compare(read_c0_count());
- irq_disable_hazard();
+ compare_change_hazard();
if (c0_compare_int_pending())
return 0;
@@ -219,6 +158,8 @@ static int c0_compare_int_usable(void)
return 1;
}
+#ifndef CONFIG_MIPS_MT_SMTC
+
int __cpuinit mips_clockevent_init(void)
{
uint64_t mips_freq = mips_hpt_frequency;
@@ -229,17 +170,6 @@ int __cpuinit mips_clockevent_init(void)
if (!cpu_has_counter || !mips_hpt_frequency)
return -ENXIO;
-#ifdef CONFIG_MIPS_MT_SMTC
- setup_smtc_dummy_clockevent_device();
-
- /*
- * On SMTC we only register VPE0's compare interrupt as clockevent
- * device.
- */
- if (cpu)
- return 0;
-#endif
-
if (!c0_compare_int_usable())
return -ENXIO;
@@ -265,13 +195,9 @@ int __cpuinit mips_clockevent_init(void)
cd->rating = 300;
cd->irq = irq;
-#ifdef CONFIG_MIPS_MT_SMTC
- cd->cpumask = CPU_MASK_ALL;
-#else
cd->cpumask = cpumask_of_cpu(cpu);
-#endif
cd->set_next_event = mips_next_event;
- cd->set_mode = mips_set_mode;
+ cd->set_mode = mips_set_clock_mode;
cd->event_handler = mips_event_handler;
clockevents_register_device(cd);
@@ -281,12 +207,9 @@ int __cpuinit mips_clockevent_init(void)
cp0_timer_irq_installed = 1;
-#ifdef CONFIG_MIPS_MT_SMTC
-#define CPUCTR_IMASKBIT (0x100 << cp0_compare_irq)
- setup_irq_smtc(irq, &c0_compare_irqaction, CPUCTR_IMASKBIT);
-#else
setup_irq(irq, &c0_compare_irqaction);
-#endif
return 0;
}
+
+#endif /* Not CONFIG_MIPS_MT_SMTC */
diff --git a/arch/mips/kernel/cevt-smtc.c b/arch/mips/kernel/cevt-smtc.c
new file mode 100644
index 00000000000..5162fe4b595
--- /dev/null
+++ b/arch/mips/kernel/cevt-smtc.c
@@ -0,0 +1,321 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2007 MIPS Technologies, Inc.
+ * Copyright (C) 2007 Ralf Baechle <ralf@linux-mips.org>
+ * Copyright (C) 2008 Kevin D. Kissell, Paralogos sarl
+ */
+#include <linux/clockchips.h>
+#include <linux/interrupt.h>
+#include <linux/percpu.h>
+
+#include <asm/smtc_ipi.h>
+#include <asm/time.h>
+#include <asm/cevt-r4k.h>
+
+/*
+ * Variant clock event timer support for SMTC on MIPS 34K, 1004K
+ * or other MIPS MT cores.
+ *
+ * Notes on SMTC Support:
+ *
+ * SMTC has multiple microthread TCs pretending to be Linux CPUs.
+ * But there's only one Count/Compare pair per VPE, and Compare
+ * interrupts are taken opportunisitically by available TCs
+ * bound to the VPE with the Count register. The new timer
+ * framework provides for global broadcasts, but we really
+ * want VPE-level multicasts for best behavior. So instead
+ * of invoking the high-level clock-event broadcast code,
+ * this version of SMTC support uses the historical SMTC
+ * multicast mechanisms "under the hood", appearing to the
+ * generic clock layer as if the interrupts are per-CPU.
+ *
+ * The approach taken here is to maintain a set of NR_CPUS
+ * virtual timers, and track which "CPU" needs to be alerted
+ * at each event.
+ *
+ * It's unlikely that we'll see a MIPS MT core with more than
+ * 2 VPEs, but we *know* that we won't need to handle more
+ * VPEs than we have "CPUs". So NCPUs arrays of NCPUs elements
+ * is always going to be overkill, but always going to be enough.
+ */
+
+unsigned long smtc_nexttime[NR_CPUS][NR_CPUS];
+static int smtc_nextinvpe[NR_CPUS];
+
+/*
+ * Timestamps stored are absolute values to be programmed
+ * into Count register. Valid timestamps will never be zero.
+ * If a Zero Count value is actually calculated, it is converted
+ * to be a 1, which will introduce 1 or two CPU cycles of error
+ * roughly once every four billion events, which at 1000 HZ means
+ * about once every 50 days. If that's actually a problem, one
+ * could alternate squashing 0 to 1 and to -1.
+ */
+
+#define MAKEVALID(x) (((x) == 0L) ? 1L : (x))
+#define ISVALID(x) ((x) != 0L)
+
+/*
+ * Time comparison is subtle, as it's really truncated
+ * modular arithmetic.
+ */
+
+#define IS_SOONER(a, b, reference) \
+ (((a) - (unsigned long)(reference)) < ((b) - (unsigned long)(reference)))
+
+/*
+ * CATCHUP_INCREMENT, used when the function falls behind the counter.
+ * Could be an increasing function instead of a constant;
+ */
+
+#define CATCHUP_INCREMENT 64
+
+static int mips_next_event(unsigned long delta,
+ struct clock_event_device *evt)
+{
+ unsigned long flags;
+ unsigned int mtflags;
+ unsigned long timestamp, reference, previous;
+ unsigned long nextcomp = 0L;
+ int vpe = current_cpu_data.vpe_id;
+ int cpu = smp_processor_id();
+ local_irq_save(flags);
+ mtflags = dmt();
+
+ /*
+ * Maintain the per-TC virtual timer
+ * and program the per-VPE shared Count register
+ * as appropriate here...
+ */
+ reference = (unsigned long)read_c0_count();
+ timestamp = MAKEVALID(reference + delta);
+ /*
+ * To really model the clock, we have to catch the case
+ * where the current next-in-VPE timestamp is the old
+ * timestamp for the calling CPE, but the new value is
+ * in fact later. In that case, we have to do a full
+ * scan and discover the new next-in-VPE CPU id and
+ * timestamp.
+ */
+ previous = smtc_nexttime[vpe][cpu];
+ if (cpu == smtc_nextinvpe[vpe] && ISVALID(previous)
+ && IS_SOONER(previous, timestamp, reference)) {
+ int i;
+ int soonest = cpu;
+
+ /*
+ * Update timestamp array here, so that new
+ * value gets considered along with those of
+ * other virtual CPUs on the VPE.
+ */
+ smtc_nexttime[vpe][cpu] = timestamp;
+ for_each_online_cpu(i) {
+ if (ISVALID(smtc_nexttime[vpe][i])
+ && IS_SOONER(smtc_nexttime[vpe][i],
+ smtc_nexttime[vpe][soonest], reference)) {
+ soonest = i;
+ }
+ }
+ smtc_nextinvpe[vpe] = soonest;
+ nextcomp = smtc_nexttime[vpe][soonest];
+ /*
+ * Otherwise, we don't have to process the whole array rank,
+ * we just have to see if the event horizon has gotten closer.
+ */
+ } else {
+ if (!ISVALID(smtc_nexttime[vpe][smtc_nextinvpe[vpe]]) ||
+ IS_SOONER(timestamp,
+ smtc_nexttime[vpe][smtc_nextinvpe[vpe]], reference)) {
+ smtc_nextinvpe[vpe] = cpu;
+ nextcomp = timestamp;
+ }
+ /*
+ * Since next-in-VPE may me the same as the executing
+ * virtual CPU, we update the array *after* checking
+ * its value.
+ */
+ smtc_nexttime[vpe][cpu] = timestamp;
+ }
+
+ /*
+ * It may be that, in fact, we don't need to update Compare,
+ * but if we do, we want to make sure we didn't fall into
+ * a crack just behind Count.
+ */
+ if (ISVALID(nextcomp)) {
+ write_c0_compare(nextcomp);
+ ehb();
+ /*
+ * We never return an error, we just make sure
+ * that we trigger the handlers as quickly as
+ * we can if we fell behind.
+ */
+ while ((nextcomp - (unsigned long)read_c0_count())
+ > (unsigned long)LONG_MAX) {
+ nextcomp += CATCHUP_INCREMENT;
+ write_c0_compare(nextcomp);
+ ehb();
+ }
+ }
+ emt(mtflags);
+ local_irq_restore(flags);
+ return 0;
+}
+
+
+void smtc_distribute_timer(int vpe)
+{
+ unsigned long flags;
+ unsigned int mtflags;
+ int cpu;
+ struct clock_event_device *cd;
+ unsigned long nextstamp = 0L;
+ unsigned long reference;
+
+
+repeat:
+ for_each_online_cpu(cpu) {
+ /*
+ * Find virtual CPUs within the current VPE who have
+ * unserviced timer requests whose time is now past.
+ */
+ local_irq_save(flags);
+ mtflags = dmt();
+ if (cpu_data[cpu].vpe_id == vpe &&
+ ISVALID(smtc_nexttime[vpe][cpu])) {
+ reference = (unsigned long)read_c0_count();
+ if ((smtc_nexttime[vpe][cpu] - reference)
+ > (unsigned long)LONG_MAX) {
+ smtc_nexttime[vpe][cpu] = 0L;
+ emt(mtflags);
+ local_irq_restore(flags);
+ /*
+ * We don't send IPIs to ourself.
+ */
+ if (cpu != smp_processor_id()) {
+ smtc_send_ipi(cpu, SMTC_CLOCK_TICK, 0);
+ } else {
+ cd = &per_cpu(mips_clockevent_device, cpu);
+ cd->event_handler(cd);
+ }
+ } else {
+ /* Local to VPE but Valid Time not yet reached. */
+ if (!ISVALID(nextstamp) ||
+ IS_SOONER(smtc_nexttime[vpe][cpu], nextstamp,
+ reference)) {
+ smtc_nextinvpe[vpe] = cpu;
+ nextstamp = smtc_nexttime[vpe][cpu];
+ }
+ emt(mtflags);
+ local_irq_restore(flags);
+ }
+ } else {
+ emt(mtflags);
+ local_irq_restore(flags);
+
+ }
+ }
+ /* Reprogram for interrupt at next soonest timestamp for VPE */
+ if (ISVALID(nextstamp)) {
+ write_c0_compare(nextstamp);
+ ehb();
+ if ((nextstamp - (unsigned long)read_c0_count())
+ > (unsigned long)LONG_MAX)
+ goto repeat;
+ }
+}
+
+
+irqreturn_t c0_compare_interrupt(int irq, void *dev_id)
+{
+ int cpu = smp_processor_id();
+
+ /* If we're running SMTC, we've got MIPS MT and therefore MIPS32R2 */
+ handle_perf_irq(1);
+
+ if (read_c0_cause() & (1 << 30)) {
+ /* Clear Count/Compare Interrupt */
+ write_c0_compare(read_c0_compare());
+ smtc_distribute_timer(cpu_data[cpu].vpe_id);
+ }
+ return IRQ_HANDLED;
+}
+
+
+int __cpuinit mips_clockevent_init(void)
+{
+ uint64_t mips_freq = mips_hpt_frequency;
+ unsigned int cpu = smp_processor_id();
+ struct clock_event_device *cd;
+ unsigned int irq;
+ int i;
+ int j;
+
+ if (!cpu_has_counter || !mips_hpt_frequency)
+ return -ENXIO;
+ if (cpu == 0) {
+ for (i = 0; i < num_possible_cpus(); i++) {
+ smtc_nextinvpe[i] = 0;
+ for (j = 0; j < num_possible_cpus(); j++)
+ smtc_nexttime[i][j] = 0L;
+ }
+ /*
+ * SMTC also can't have the usablility test
+ * run by secondary TCs once Compare is in use.
+ */
+ if (!c0_compare_int_usable())
+ return -ENXIO;
+ }
+
+ /*
+ * With vectored interrupts things are getting platform specific.
+ * get_c0_compare_int is a hook to allow a platform to return the
+ * interrupt number of it's liking.
+ */
+ irq = MIPS_CPU_IRQ_BASE + cp0_compare_irq;
+ if (get_c0_compare_int)
+ irq = get_c0_compare_int();
+
+ cd = &per_cpu(mips_clockevent_device, cpu);
+
+ cd->name = "MIPS";
+ cd->features = CLOCK_EVT_FEAT_ONESHOT;
+
+ /* Calculate the min / max delta */
+ cd->mult = div_sc((unsigned long) mips_freq, NSEC_PER_SEC, 32);
+ cd->shift = 32;
+ cd->max_delta_ns = clockevent_delta2ns(0x7fffffff, cd);
+ cd->min_delta_ns = clockevent_delta2ns(0x300, cd);
+
+ cd->rating = 300;
+ cd->irq = irq;
+ cd->cpumask = cpumask_of_cpu(cpu);
+ cd->set_next_event = mips_next_event;
+ cd->set_mode = mips_set_clock_mode;
+ cd->event_handler = mips_event_handler;
+
+ clockevents_register_device(cd);
+
+ /*
+ * On SMTC we only want to do the data structure
+ * initialization and IRQ setup once.
+ */
+ if (cpu)
+ return 0;
+ /*
+ * And we need the hwmask associated with the c0_compare
+ * vector to be initialized.
+ */
+ irq_hwmask[irq] = (0x100 << cp0_compare_irq);
+ if (cp0_timer_irq_installed)
+ return 0;
+
+ cp0_timer_irq_installed = 1;
+
+ setup_irq(irq, &c0_compare_irqaction);
+
+ return 0;
+}
diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c
index 11c92dc5379..e621fda8ab3 100644
--- a/arch/mips/kernel/cpu-probe.c
+++ b/arch/mips/kernel/cpu-probe.c
@@ -54,14 +54,18 @@ extern void r4k_wait(void);
* interrupt is requested" restriction in the MIPS32/MIPS64 architecture makes
* using this version a gamble.
*/
-static void r4k_wait_irqoff(void)
+void r4k_wait_irqoff(void)
{
local_irq_disable();
if (!need_resched())
- __asm__(" .set mips3 \n"
+ __asm__(" .set push \n"
+ " .set mips3 \n"
" wait \n"
- " .set mips0 \n");
+ " .set pop \n");
local_irq_enable();
+ __asm__(" .globl __pastwait \n"
+ "__pastwait: \n");
+ return;
}
/*
diff --git a/arch/mips/kernel/entry.S b/arch/mips/kernel/entry.S
index e29598ae939..ffa331029e0 100644
--- a/arch/mips/kernel/entry.S
+++ b/arch/mips/kernel/entry.S
@@ -79,11 +79,6 @@ FEXPORT(syscall_exit)
FEXPORT(restore_all) # restore full frame
#ifdef CONFIG_MIPS_MT_SMTC
-/* Detect and execute deferred IPI "interrupts" */
- LONG_L s0, TI_REGS($28)
- LONG_S sp, TI_REGS($28)
- jal deferred_smtc_ipi
- LONG_S s0, TI_REGS($28)
#ifdef CONFIG_MIPS_MT_SMTC_IM_BACKSTOP
/* Re-arm any temporarily masked interrupts not explicitly "acked" */
mfc0 v0, CP0_TCSTATUS
@@ -112,6 +107,11 @@ FEXPORT(restore_all) # restore full frame
xor t0, t0, t3
mtc0 t0, CP0_TCCONTEXT
#endif /* CONFIG_MIPS_MT_SMTC_IM_BACKSTOP */
+/* Detect and execute deferred IPI "interrupts" */
+ LONG_L s0, TI_REGS($28)
+ LONG_S sp, TI_REGS($28)
+ jal deferred_smtc_ipi
+ LONG_S s0, TI_REGS($28)
#endif /* CONFIG_MIPS_MT_SMTC */
.set noat
RESTORE_TEMP
diff --git a/arch/mips/kernel/genex.S b/arch/mips/kernel/genex.S
index f886dd7f708..01dcbe38fa0 100644
--- a/arch/mips/kernel/genex.S
+++ b/arch/mips/kernel/genex.S
@@ -282,8 +282,8 @@ NESTED(except_vec_vi_handler, 0, sp)
and t0, a0, t1
#ifdef CONFIG_MIPS_MT_SMTC_IM_BACKSTOP
mfc0 t2, CP0_TCCONTEXT
- or t0, t0, t2
- mtc0 t0, CP0_TCCONTEXT
+ or t2, t0, t2
+ mtc0 t2, CP0_TCCONTEXT
#endif /* CONFIG_MIPS_MT_SMTC_IM_BACKSTOP */
xor t1, t1, t0
mtc0 t1, CP0_STATUS
diff --git a/arch/mips/kernel/head.S b/arch/mips/kernel/head.S
index 361364501d3..492a0a8d70f 100644
--- a/arch/mips/kernel/head.S
+++ b/arch/mips/kernel/head.S
@@ -22,6 +22,7 @@
#include <asm/irqflags.h>
#include <asm/regdef.h>
#include <asm/page.h>
+#include <asm/pgtable-bits.h>
#include <asm/mipsregs.h>
#include <asm/stackframe.h>
diff --git a/arch/mips/kernel/mips-mt-fpaff.c b/arch/mips/kernel/mips-mt-fpaff.c
index df4d3f2f740..dc9eb72ed9d 100644
--- a/arch/mips/kernel/mips-mt-fpaff.c
+++ b/arch/mips/kernel/mips-mt-fpaff.c
@@ -159,7 +159,7 @@ __setup("fpaff=", fpaff_thresh);
/*
* FPU Use Factor empirically derived from experiments on 34K
*/
-#define FPUSEFACTOR 333
+#define FPUSEFACTOR 2000
static __init int mt_fp_affinity_init(void)
{
diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c
index ce7684335a4..22fc19bbe87 100644
--- a/arch/mips/kernel/process.c
+++ b/arch/mips/kernel/process.c
@@ -55,7 +55,7 @@ void __noreturn cpu_idle(void)
while (1) {
tick_nohz_stop_sched_tick(1);
while (!need_resched()) {
-#ifdef CONFIG_SMTC_IDLE_HOOK_DEBUG
+#ifdef CONFIG_MIPS_MT_SMTC
extern void smtc_idle_loop_hook(void);
smtc_idle_loop_hook();
@@ -145,19 +145,18 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
*/
p->thread.cp0_status = read_c0_status() & ~(ST0_CU2|ST0_CU1);
childregs->cp0_status &= ~(ST0_CU2|ST0_CU1);
+
+#ifdef CONFIG_MIPS_MT_SMTC
+ /*
+ * SMTC restores TCStatus after Status, and the CU bits
+ * are aliased there.
+ */
+ childregs->cp0_tcstatus &= ~(ST0_CU2|ST0_CU1);
+#endif
clear_tsk_thread_flag(p, TIF_USEDFPU);
#ifdef CONFIG_MIPS_MT_FPAFF
clear_tsk_thread_flag(p, TIF_FPUBOUND);
-
- /*
- * FPU affinity support is cleaner if we track the
- * user-visible CPU affinity from the very beginning.
- * The generic cpus_allowed mask will already have
- * been copied from the parent before copy_thread
- * is invoked.
- */
- p->thread.user_cpus_allowed = p->cpus_allowed;
#endif /* CONFIG_MIPS_MT_FPAFF */
if (clone_flags & CLONE_SETTLS)
diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c
index 35234b92b9a..96ffc9c6d19 100644
--- a/arch/mips/kernel/ptrace.c
+++ b/arch/mips/kernel/ptrace.c
@@ -238,7 +238,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
case FPC_EIR: { /* implementation / version register */
unsigned int flags;
#ifdef CONFIG_MIPS_MT_SMTC
- unsigned int irqflags;
+ unsigned long irqflags;
unsigned int mtflags;
#endif /* CONFIG_MIPS_MT_SMTC */
diff --git a/arch/mips/kernel/smtc.c b/arch/mips/kernel/smtc.c
index a516286532a..897fb2b4751 100644
--- a/arch/mips/kernel/smtc.c
+++ b/arch/mips/kernel/smtc.c
@@ -1,4 +1,21 @@
-/* Copyright (C) 2004 Mips Technologies, Inc */
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Copyright (C) 2004 Mips Technologies, Inc
+ * Copyright (C) 2008 Kevin D. Kissell
+ */
#include <linux/clockchips.h>
#include <linux/kernel.h>
@@ -21,7 +38,6 @@
#include <asm/time.h>
#include <asm/addrspace.h>
#include <asm/smtc.h>
-#include <asm/smtc_ipi.h>
#include <asm/smtc_proc.h>
/*
@@ -58,11 +74,6 @@ unsigned long irq_hwmask[NR_IRQS];
asiduse smtc_live_asid[MAX_SMTC_TLBS][MAX_SMTC_ASIDS];
-/*
- * Clock interrupt "latch" buffers, per "CPU"
- */
-
-static atomic_t ipi_timer_latch[NR_CPUS];
/*
* Number of InterProcessor Interrupt (IPI) message buffers to allocate
@@ -70,7 +81,7 @@ static atomic_t ipi_timer_latch[NR_CPUS];
#define IPIBUF_PER_CPU 4
-static struct smtc_ipi_q IPIQ[NR_CPUS];
+struct smtc_ipi_q IPIQ[NR_CPUS];
static struct smtc_ipi_q freeIPIq;
@@ -282,7 +293,7 @@ static void smtc_configure_tlb(void)
* phys_cpu_present_map and the logical/physical mappings.
*/
-int __init mipsmt_build_cpu_map(int start_cpu_slot)
+int __init smtc_build_cpu_map(int start_cpu_slot)
{
int i, ntcs;
@@ -325,7 +336,12 @@ static void smtc_tc_setup(int vpe, int tc, int cpu)
write_tc_c0_tcstatus((read_tc_c0_tcstatus()
& ~(TCSTATUS_TKSU | TCSTATUS_DA | TCSTATUS_IXMT))
| TCSTATUS_A);
- write_tc_c0_tccontext(0);
+ /*
+ * TCContext gets an offset from the base of the IPIQ array
+ * to be used in low-level code to detect the presence of
+ * an active IPI queue
+ */
+ write_tc_c0_tccontext((sizeof(struct smtc_ipi_q) * cpu) << 16);
/* Bind tc to vpe */
write_tc_c0_tcbind(vpe);
/* In general, all TCs should have the same cpu_data indications */
@@ -336,10 +352,18 @@ static void smtc_tc_setup(int vpe, int tc, int cpu)
cpu_data[cpu].options &= ~MIPS_CPU_FPU;
cpu_data[cpu].vpe_id = vpe;
cpu_data[cpu].tc_id = tc;
+ /* Multi-core SMTC hasn't been tested, but be prepared */
+ cpu_data[cpu].core = (read_vpe_c0_ebase() >> 1) & 0xff;
}
+/*
+ * Tweak to get Count registes in as close a sync as possible.
+ * Value seems good for 34K-class cores.
+ */
+
+#define CP0_SKEW 8
-void mipsmt_prepare_cpus(void)
+void smtc_prepare_cpus(int cpus)
{
int i, vpe, tc, ntc, nvpe, tcpervpe[NR_CPUS], slop, cpu;
unsigned long flags;
@@ -363,13 +387,13 @@ void mipsmt_prepare_cpus(void)
IPIQ[i].head = IPIQ[i].tail = NULL;
spin_lock_init(&IPIQ[i].lock);
IPIQ[i].depth = 0;
- atomic_set(&ipi_timer_latch[i], 0);
}
/* cpu_data index starts at zero */
cpu = 0;
cpu_data[cpu].vpe_id = 0;
cpu_data[cpu].tc_id = 0;
+ cpu_data[cpu].core = (read_c0_ebase() >> 1) & 0xff;
cpu++;
/* Report on boot-time options */
@@ -484,7 +508,8 @@ void mipsmt_prepare_cpus(void)
write_vpe_c0_compare(0);
/* Propagate Config7 */
write_vpe_c0_config7(read_c0_config7());
- write_vpe_c0_count(read_c0_count());
+ write_vpe_c0_count(read_c0_count() + CP0_SKEW);
+ ehb();
}
/* enable multi-threading within VPE */
write_vpe_c0_vpecontrol(read_vpe_c0_vpecontrol() | VPECONTROL_TE);
@@ -556,7 +581,7 @@ void mipsmt_prepare_cpus(void)
void __cpuinit smtc_boot_secondary(int cpu, struct task_struct *idle)
{
extern u32 kernelsp[NR_CPUS];
- long flags;
+ unsigned long flags;
int mtflags;
LOCK_MT_PRA();
@@ -585,24 +610,22 @@ void __cpuinit smtc_boot_secondary(int cpu, struct task_struct *idle)
void smtc_init_secondary(void)
{
- /*
- * Start timer on secondary VPEs if necessary.
- * plat_timer_setup has already have been invoked by init/main
- * on "boot" TC. Like per_cpu_trap_init() hack, this assumes that
- * SMTC init code assigns TCs consdecutively and in ascending order
- * to across available VPEs.
- */
- if (((read_c0_tcbind() & TCBIND_CURTC) != 0) &&
- ((read_c0_tcbind() & TCBIND_CURVPE)
- != cpu_data[smp_processor_id() - 1].vpe_id)){
- write_c0_compare(read_c0_count() + mips_hpt_frequency/HZ);
- }
-
local_irq_enable();
}
void smtc_smp_finish(void)
{
+ int cpu = smp_processor_id();
+
+ /*
+ * Lowest-numbered CPU per VPE starts a clock tick.
+ * Like per_cpu_trap_init() hack, this assumes that
+ * SMTC init code assigns TCs consdecutively and
+ * in ascending order across available VPEs.
+ */
+ if (cpu > 0 && (cpu_data[cpu].vpe_id != cpu_data[cpu - 1].vpe_id))
+ write_c0_compare(read_c0_count() + mips_hpt_frequency/HZ);
+
printk("TC %d going on-line as CPU %d\n",
cpu_data[smp_processor_id()].tc_id, smp_processor_id());
}
@@ -753,8 +776,10 @@ void smtc_send_ipi(int cpu, int type, unsigned int action)
{
int tcstatus;
struct smtc_ipi *pipi;
- long flags;
+ unsigned long flags;
int mtflags;
+ unsigned long tcrestart;
+ extern void r4k_wait_irqoff(void), __pastwait(void);
if (cpu == smp_processor_id()) {
printk("Cannot Send IPI to self!\n");
@@ -771,8 +796,6 @@ void smtc_send_ipi(int cpu, int type, unsigned int action)
pipi->arg = (void *)action;
pipi->dest = cpu;
if (cpu_data[cpu].vpe_id != cpu_data[smp_processor_id()].vpe_id) {
- if (type == SMTC_CLOCK_TICK)
- atomic_inc(&ipi_timer_latch[cpu]);
/* If not on same VPE, enqueue and send cross-VPE interrupt */
smtc_ipi_nq(&IPIQ[cpu], pipi);
LOCK_CORE_PRA();
@@ -800,22 +823,29 @@ void smtc_send_ipi(int cpu, int type, unsigned int action)
if ((tcstatus & TCSTATUS_IXMT) != 0) {
/*
- * Spin-waiting here can deadlock,
- * so we queue the message for the target TC.
+ * If we're in the the irq-off version of the wait
+ * loop, we need to force exit from the wait and
+ * do a direct post of the IPI.
+ */
+ if (cpu_wait == r4k_wait_irqoff) {
+ tcrestart = read_tc_c0_tcrestart();
+ if (tcrestart >= (unsigned long)r4k_wait_irqoff
+ && tcrestart < (unsigned long)__pastwait) {
+ write_tc_c0_tcrestart(__pastwait);
+ tcstatus &= ~TCSTATUS_IXMT;
+ write_tc_c0_tcstatus(tcstatus);
+ goto postdirect;
+ }
+ }
+ /*
+ * Otherwise we queue the message for the target TC
+ * to pick up when he does a local_irq_restore()
*/
write_tc_c0_tchalt(0);
UNLOCK_CORE_PRA();
- /* Try to reduce redundant timer interrupt messages */
- if (type == SMTC_CLOCK_TICK) {
- if (atomic_postincrement(&ipi_timer_latch[cpu])!=0){
- smtc_ipi_nq(&freeIPIq, pipi);
- return;
- }
- }
smtc_ipi_nq(&IPIQ[cpu], pipi);
} else {
- if (type == SMTC_CLOCK_TICK)
- atomic_inc(&ipi_timer_latch[cpu]);
+postdirect:
post_direct_ipi(cpu, pipi);
write_tc_c0_tchalt(0);
UNLOCK_CORE_PRA();
@@ -883,7 +913,7 @@ static void ipi_call_interrupt(void)
smp_call_function_interrupt();
}
-DECLARE_PER_CPU(struct clock_event_device, smtc_dummy_clockevent_device);
+DECLARE_PER_CPU(struct clock_event_device, mips_clockevent_device);
void ipi_decode(struct smtc_ipi *pipi)
{
@@ -891,20 +921,13 @@ void ipi_decode(struct smtc_ipi *pipi)
struct clock_event_device *cd;
void *arg_copy = pipi->arg;
int type_copy = pipi->type;
- int ticks;
-
smtc_ipi_nq(&freeIPIq, pipi);
switch (type_copy) {
case SMTC_CLOCK_TICK:
irq_enter();
kstat_this_cpu.irqs[MIPS_CPU_IRQ_BASE + 1]++;
- cd = &per_cpu(smtc_dummy_clockevent_device, cpu);
- ticks = atomic_read(&ipi_timer_latch[cpu]);
- atomic_sub(ticks, &ipi_timer_latch[cpu]);
- while (ticks) {
- cd->event_handler(cd);
- ticks--;
- }
+ cd = &per_cpu(mips_clockevent_device, cpu);
+ cd->event_handler(cd);
irq_exit();
break;
@@ -937,24 +960,48 @@ void ipi_decode(struct smtc_ipi *pipi)
}
}
+/*
+ * Similar to smtc_ipi_replay(), but invoked from context restore,
+ * so it reuses the current exception frame rather than set up a
+ * new one with self_ipi.
+ */
+
void deferred_smtc_ipi(void)
{
- struct smtc_ipi *pipi;
- unsigned long flags;
-/* DEBUG */
- int q = smp_processor_id();
+ int cpu = smp_processor_id();
/*
* Test is not atomic, but much faster than a dequeue,
* and the vast majority of invocations will have a null queue.
+ * If irq_disabled when this was called, then any IPIs queued
+ * after we test last will be taken on the next irq_enable/restore.
+ * If interrupts were enabled, then any IPIs added after the
+ * last test will be taken directly.
*/
- if (IPIQ[q].head != NULL) {
- while((pipi = smtc_ipi_dq(&IPIQ[q])) != NULL) {
- /* ipi_decode() should be called with interrupts off */
- local_irq_save(flags);
+
+ while (IPIQ[cpu].head != NULL) {
+ struct smtc_ipi_q *q = &IPIQ[cpu];
+ struct smtc_ipi *pipi;
+ unsigned long flags;
+
+ /*
+ * It may be possible we'll come in with interrupts
+ * already enabled.
+ */
+ local_irq_save(flags);
+
+ spin_lock(&q->lock);
+ pipi = __smtc_ipi_dq(q);
+ spin_unlock(&q->lock);
+ if (pipi != NULL)
ipi_decode(pipi);
- local_irq_restore(flags);
- }
+ /*
+ * The use of the __raw_local restore isn't
+ * as obviously necessary here as in smtc_ipi_replay(),
+ * but it's more efficient, given that we're already
+ * running down the IPI queue.
+ */
+ __raw_local_irq_restore(flags);
}
}
@@ -975,7 +1022,7 @@ static irqreturn_t ipi_interrupt(int irq, void *dev_idm)
struct smtc_ipi *pipi;
unsigned long tcstatus;
int sent;
- long flags;
+ unsigned long flags;
unsigned int mtflags;
unsigned int vpflags;
@@ -1066,55 +1113,53 @@ static void setup_cross_vpe_interrupts(unsigned int nvpe)
/*
* SMTC-specific hacks invoked from elsewhere in the kernel.
- *
- * smtc_ipi_replay is called from raw_local_irq_restore which is only ever
- * called with interrupts disabled. We do rely on interrupts being disabled
- * here because using spin_lock_irqsave()/spin_unlock_irqrestore() would
- * result in a recursive call to raw_local_irq_restore().
*/
-static void __smtc_ipi_replay(void)
+ /*
+ * smtc_ipi_replay is called from raw_local_irq_restore
+ */
+
+void smtc_ipi_replay(void)
{
unsigned int cpu = smp_processor_id();
/*
* To the extent that we've ever turned interrupts off,
* we may have accumulated deferred IPIs. This is subtle.
- * If we use the smtc_ipi_qdepth() macro, we'll get an
- * exact number - but we'll also disable interrupts
- * and create a window of failure where a new IPI gets
- * queued after we test the depth but before we re-enable
- * interrupts. So long as IXMT never gets set, however,
* we should be OK: If we pick up something and dispatch
* it here, that's great. If we see nothing, but concurrent
* with this operation, another TC sends us an IPI, IXMT
* is clear, and we'll handle it as a real pseudo-interrupt
- * and not a pseudo-pseudo interrupt.
+ * and not a pseudo-pseudo interrupt. The important thing
+ * is to do the last check for queued message *after* the
+ * re-enabling of interrupts.
*/
- if (IPIQ[cpu].depth > 0) {
- while (1) {
- struct smtc_ipi_q *q = &IPIQ[cpu];
- struct smtc_ipi *pipi;
- extern void self_ipi(struct smtc_ipi *);
-
- spin_lock(&q->lock);
- pipi = __smtc_ipi_dq(q);
- spin_unlock(&q->lock);
- if (!pipi)
- break;
+ while (IPIQ[cpu].head != NULL) {
+ struct smtc_ipi_q *q = &IPIQ[cpu];
+ struct smtc_ipi *pipi;
+ unsigned long flags;
+
+ /*
+ * It's just possible we'll come in with interrupts
+ * already enabled.
+ */
+ local_irq_save(flags);
+
+ spin_lock(&q->lock);
+ pipi = __smtc_ipi_dq(q);
+ spin_unlock(&q->lock);
+ /*
+ ** But use a raw restore here to avoid recursion.
+ */
+ __raw_local_irq_restore(flags);
+ if (pipi) {
self_ipi(pipi);
smtc_cpu_stats[cpu].selfipis++;
}
}
}
-void smtc_ipi_replay(void)
-{
- raw_local_irq_disable();
- __smtc_ipi_replay();
-}
-
EXPORT_SYMBOL(smtc_ipi_replay);
void smtc_idle_loop_hook(void)
@@ -1193,40 +1238,13 @@ void smtc_idle_loop_hook(void)
}
}
- /*
- * Now that we limit outstanding timer IPIs, check for hung TC
- */
- for (tc = 0; tc < NR_CPUS; tc++) {
- /* Don't check ourself - we'll dequeue IPIs just below */
- if ((tc != smp_processor_id()) &&
- atomic_read(&ipi_timer_latch[tc]) > timerq_limit) {
- if (clock_hang_reported[tc] == 0) {
- pdb_msg += sprintf(pdb_msg,
- "TC %d looks hung with timer latch at %d\n",
- tc, atomic_read(&ipi_timer_latch[tc]));
- clock_hang_reported[tc]++;
- }
- }
- }
emt(mtflags);
local_irq_restore(flags);
if (pdb_msg != &id_ho_db_msg[0])
printk("CPU%d: %s", smp_processor_id(), id_ho_db_msg);
#endif /* CONFIG_SMTC_IDLE_HOOK_DEBUG */
- /*
- * Replay any accumulated deferred IPIs. If "Instant Replay"
- * is in use, there should never be any.
- */
-#ifndef CONFIG_MIPS_MT_SMTC_INSTANT_REPLAY
- {
- unsigned long flags;
-
- local_irq_save(flags);
- __smtc_ipi_replay();
- local_irq_restore(flags);
- }
-#endif /* CONFIG_MIPS_MT_SMTC_INSTANT_REPLAY */
+ smtc_ipi_replay();
}
void smtc_soft_dump(void)
@@ -1242,10 +1260,6 @@ void smtc_soft_dump(void)
printk("%d: %ld\n", i, smtc_cpu_stats[i].selfipis);
}
smtc_ipi_qdump();
- printk("Timer IPI Backlogs:\n");
- for (i=0; i < NR_CPUS; i++) {
- printk("%d: %d\n", i, atomic_read(&ipi_timer_latch[i]));
- }
printk("%d Recoveries of \"stolen\" FPU\n",
atomic_read(&smtc_fpu_recoveries));
}
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index 5fd0cd020af..b602ac6eb47 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -825,8 +825,10 @@ static void mt_ase_fp_affinity(void)
if (cpus_intersects(current->cpus_allowed, mt_fpu_cpumask)) {
cpumask_t tmask;
- cpus_and(tmask, current->thread.user_cpus_allowed,
- mt_fpu_cpumask);
+ current->thread.user_cpus_allowed
+ = current->cpus_allowed;
+ cpus_and(tmask, current->cpus_allowed,
+ mt_fpu_cpumask);
set_cpus_allowed(current, tmask);
set_thread_flag(TIF_FPUBOUND);
}
diff --git a/arch/mips/mti-malta/Makefile b/arch/mips/mti-malta/Makefile
index 3b7dd722c32..cef2db8d222 100644
--- a/arch/mips/mti-malta/Makefile
+++ b/arch/mips/mti-malta/Makefile
@@ -15,6 +15,6 @@ obj-$(CONFIG_EARLY_PRINTK) += malta-console.o
obj-$(CONFIG_PCI) += malta-pci.o
# FIXME FIXME FIXME
-obj-$(CONFIG_MIPS_MT_SMTC) += malta_smtc.o
+obj-$(CONFIG_MIPS_MT_SMTC) += malta-smtc.o
EXTRA_CFLAGS += -Werror
diff --git a/arch/mips/mti-malta/malta-smtc.c b/arch/mips/mti-malta/malta-smtc.c
index 5ea705e4945..f84a46a8ae6 100644
--- a/arch/mips/mti-malta/malta-smtc.c
+++ b/arch/mips/mti-malta/malta-smtc.c
@@ -84,12 +84,17 @@ static void msmtc_cpus_done(void)
static void __init msmtc_smp_setup(void)
{
- mipsmt_build_cpu_map(0);
+ /*
+ * we won't get the definitive value until
+ * we've run smtc_prepare_cpus later, but
+ * we would appear to need an upper bound now.
+ */
+ smp_num_siblings = smtc_build_cpu_map(0);
}
static void __init msmtc_prepare_cpus(unsigned int max_cpus)
{
- mipsmt_prepare_cpus();
+ smtc_prepare_cpus(max_cpus);
}
struct plat_smp_ops msmtc_smp_ops = {
diff --git a/arch/mips/sibyte/swarm/Makefile b/arch/mips/sibyte/swarm/Makefile
index f18ba9201bb..7b45f199d92 100644
--- a/arch/mips/sibyte/swarm/Makefile
+++ b/arch/mips/sibyte/swarm/Makefile
@@ -1,3 +1,4 @@
-obj-y := setup.o rtc_xicor1241.o rtc_m41t81.o
+obj-y := platform.o setup.o rtc_xicor1241.o \
+ rtc_m41t81.o
obj-$(CONFIG_I2C_BOARDINFO) += swarm-i2c.o
diff --git a/arch/mips/sibyte/swarm/platform.c b/arch/mips/sibyte/swarm/platform.c
new file mode 100644
index 00000000000..54847fe1e56
--- /dev/null
+++ b/arch/mips/sibyte/swarm/platform.c
@@ -0,0 +1,85 @@
+#include <linux/err.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/platform_device.h>
+#include <linux/ata_platform.h>
+
+#include <asm/sibyte/board.h>
+#include <asm/sibyte/sb1250_genbus.h>
+#include <asm/sibyte/sb1250_regs.h>
+
+#if defined(CONFIG_SIBYTE_SWARM) || defined(CONFIG_SIBYTE_LITTLESUR)
+
+#define DRV_NAME "pata-swarm"
+
+#define SWARM_IDE_SHIFT 5
+#define SWARM_IDE_BASE 0x1f0
+#define SWARM_IDE_CTRL 0x3f6
+
+static struct resource swarm_pata_resource[] = {
+ {
+ .name = "Swarm GenBus IDE",
+ .flags = IORESOURCE_MEM,
+ }, {
+ .name = "Swarm GenBus IDE",
+ .flags = IORESOURCE_MEM,
+ }, {
+ .name = "Swarm GenBus IDE",
+ .flags = IORESOURCE_IRQ,
+ .start = K_INT_GB_IDE,
+ .end = K_INT_GB_IDE,
+ },
+};
+
+static struct pata_platform_info pata_platform_data = {
+ .ioport_shift = SWARM_IDE_SHIFT,
+};
+
+static struct platform_device swarm_pata_device = {
+ .name = "pata_platform",
+ .id = -1,
+ .resource = swarm_pata_resource,
+ .num_resources = ARRAY_SIZE(swarm_pata_resource),
+ .dev = {
+ .platform_data = &pata_platform_data,
+ .coherent_dma_mask = ~0, /* grumble */
+ },
+};
+
+static int __init swarm_pata_init(void)
+{
+ u8 __iomem *base;
+ phys_t offset, size;
+ struct resource *r;
+
+ if (!SIBYTE_HAVE_IDE)
+ return -ENODEV;
+
+ base = ioremap(A_IO_EXT_BASE, 0x800);
+ offset = __raw_readq(base + R_IO_EXT_REG(R_IO_EXT_START_ADDR, IDE_CS));
+ size = __raw_readq(base + R_IO_EXT_REG(R_IO_EXT_MULT_SIZE, IDE_CS));
+ iounmap(base);
+
+ offset = G_IO_START_ADDR(offset) << S_IO_ADDRBASE;
+ size = (G_IO_MULT_SIZE(size) + 1) << S_IO_REGSIZE;
+ if (offset < A_PHYS_GENBUS || offset >= A_PHYS_GENBUS_END) {
+ pr_info(DRV_NAME ": PATA interface at GenBus disabled\n");
+
+ return -EBUSY;
+ }
+
+ pr_info(DRV_NAME ": PATA interface at GenBus slot %i\n", IDE_CS);
+
+ r = swarm_pata_resource;
+ r[0].start = offset + (SWARM_IDE_BASE << SWARM_IDE_SHIFT);
+ r[0].end = offset + ((SWARM_IDE_BASE + 8) << SWARM_IDE_SHIFT) - 1;
+ r[1].start = offset + (SWARM_IDE_CTRL << SWARM_IDE_SHIFT);
+ r[1].end = offset + ((SWARM_IDE_CTRL + 1) << SWARM_IDE_SHIFT) - 1;
+
+ return platform_device_register(&swarm_pata_device);
+}
+
+device_initcall(swarm_pata_init);
+
+#endif /* defined(CONFIG_SIBYTE_SWARM) || defined(CONFIG_SIBYTE_LITTLESUR) */
diff --git a/arch/mn10300/kernel/irq.c b/arch/mn10300/kernel/irq.c
index 761c434a248..56c64ccc9c2 100644
--- a/arch/mn10300/kernel/irq.c
+++ b/arch/mn10300/kernel/irq.c
@@ -20,22 +20,8 @@ EXPORT_SYMBOL(__mn10300_irq_enabled_epsw);
atomic_t irq_err_count;
/*
- * MN10300 INTC controller operations
+ * MN10300 interrupt controller operations
*/
-static void mn10300_cpupic_disable(unsigned int irq)
-{
- u16 tmp = GxICR(irq);
- GxICR(irq) = (tmp & GxICR_LEVEL) | GxICR_DETECT;
- tmp = GxICR(irq);
-}
-
-static void mn10300_cpupic_enable(unsigned int irq)
-{
- u16 tmp = GxICR(irq);
- GxICR(irq) = (tmp & GxICR_LEVEL) | GxICR_ENABLE;
- tmp = GxICR(irq);
-}
-
static void mn10300_cpupic_ack(unsigned int irq)
{
u16 tmp;
@@ -60,26 +46,54 @@ static void mn10300_cpupic_mask_ack(unsigned int irq)
static void mn10300_cpupic_unmask(unsigned int irq)
{
u16 tmp = GxICR(irq);
- GxICR(irq) = (tmp & GxICR_LEVEL) | GxICR_ENABLE | GxICR_DETECT;
+ GxICR(irq) = (tmp & GxICR_LEVEL) | GxICR_ENABLE;
tmp = GxICR(irq);
}
-static void mn10300_cpupic_end(unsigned int irq)
+static void mn10300_cpupic_unmask_clear(unsigned int irq)
{
+ /* the MN10300 PIC latches its interrupt request bit, even after the
+ * device has ceased to assert its interrupt line and the interrupt
+ * channel has been disabled in the PIC, so for level-triggered
+ * interrupts we need to clear the request bit when we re-enable */
u16 tmp = GxICR(irq);
- GxICR(irq) = (tmp & GxICR_LEVEL) | GxICR_ENABLE;
+ GxICR(irq) = (tmp & GxICR_LEVEL) | GxICR_ENABLE | GxICR_DETECT;
tmp = GxICR(irq);
}
-static struct irq_chip mn10300_cpu_pic = {
- .name = "cpu",
- .disable = mn10300_cpupic_disable,
- .enable = mn10300_cpupic_enable,
+/*
+ * MN10300 PIC level-triggered IRQ handling.
+ *
+ * The PIC has no 'ACK' function per se. It is possible to clear individual
+ * channel latches, but each latch relatches whether or not the channel is
+ * masked, so we need to clear the latch when we unmask the channel.
+ *
+ * Also for this reason, we don't supply an ack() op (it's unused anyway if
+ * mask_ack() is provided), and mask_ack() just masks.
+ */
+static struct irq_chip mn10300_cpu_pic_level = {
+ .name = "cpu_l",
+ .disable = mn10300_cpupic_mask,
+ .enable = mn10300_cpupic_unmask_clear,
+ .ack = NULL,
+ .mask = mn10300_cpupic_mask,
+ .mask_ack = mn10300_cpupic_mask,
+ .unmask = mn10300_cpupic_unmask_clear,
+};
+
+/*
+ * MN10300 PIC edge-triggered IRQ handling.
+ *
+ * We use the latch clearing function of the PIC as the 'ACK' function.
+ */
+static struct irq_chip mn10300_cpu_pic_edge = {
+ .name = "cpu_e",
+ .disable = mn10300_cpupic_mask,
+ .enable = mn10300_cpupic_unmask,
.ack = mn10300_cpupic_ack,
.mask = mn10300_cpupic_mask,
.mask_ack = mn10300_cpupic_mask_ack,
.unmask = mn10300_cpupic_unmask,
- .end = mn10300_cpupic_end,
};
/*
@@ -114,7 +128,8 @@ void set_intr_level(int irq, u16 level)
*/
void set_intr_postackable(int irq)
{
- set_irq_handler(irq, handle_level_irq);
+ set_irq_chip_and_handler(irq, &mn10300_cpu_pic_level,
+ handle_level_irq);
}
/*
@@ -126,8 +141,12 @@ void __init init_IRQ(void)
for (irq = 0; irq < NR_IRQS; irq++)
if (irq_desc[irq].chip == &no_irq_type)
- set_irq_chip_and_handler(irq, &mn10300_cpu_pic,
- handle_edge_irq);
+ /* due to the PIC latching interrupt requests, even
+ * when the IRQ is disabled, IRQ_PENDING is superfluous
+ * and we can use handle_level_irq() for edge-triggered
+ * interrupts */
+ set_irq_chip_and_handler(irq, &mn10300_cpu_pic_edge,
+ handle_level_irq);
unit_init_IRQ();
}
diff --git a/arch/mn10300/unit-asb2303/unit-init.c b/arch/mn10300/unit-asb2303/unit-init.c
index 14b2c817cff..70e8cb4ea26 100644
--- a/arch/mn10300/unit-asb2303/unit-init.c
+++ b/arch/mn10300/unit-asb2303/unit-init.c
@@ -51,7 +51,7 @@ void __init unit_init_IRQ(void)
switch (GET_XIRQ_TRIGGER(extnum)) {
case XIRQ_TRIGGER_HILEVEL:
case XIRQ_TRIGGER_LOWLEVEL:
- set_irq_handler(XIRQ2IRQ(extnum), handle_level_irq);
+ set_intr_postackable(XIRQ2IRQ(extnum));
break;
default:
break;
diff --git a/arch/mn10300/unit-asb2305/unit-init.c b/arch/mn10300/unit-asb2305/unit-init.c
index 6a352414a35..72812a9439a 100644
--- a/arch/mn10300/unit-asb2305/unit-init.c
+++ b/arch/mn10300/unit-asb2305/unit-init.c
@@ -52,7 +52,7 @@ void __init unit_init_IRQ(void)
switch (GET_XIRQ_TRIGGER(extnum)) {
case XIRQ_TRIGGER_HILEVEL:
case XIRQ_TRIGGER_LOWLEVEL:
- set_irq_handler(XIRQ2IRQ(extnum), handle_level_irq);
+ set_intr_postackable(XIRQ2IRQ(extnum));
break;
default:
break;
diff --git a/arch/powerpc/boot/dts/holly.dts b/arch/powerpc/boot/dts/holly.dts
index f87fe7b9ced..c6e11ebeceb 100644
--- a/arch/powerpc/boot/dts/holly.dts
+++ b/arch/powerpc/boot/dts/holly.dts
@@ -133,61 +133,61 @@
reg = <0x00007400 0x00000400>;
big-endian;
};
+ };
- pci@1000 {
- device_type = "pci";
- compatible = "tsi109-pci", "tsi108-pci";
- #interrupt-cells = <1>;
- #size-cells = <2>;
- #address-cells = <3>;
- reg = <0x00001000 0x00001000>;
- bus-range = <0x0 0x0>;
- /*----------------------------------------------------+
- | PCI memory range.
- | 01 denotes I/O space
- | 02 denotes 32-bit memory space
- +----------------------------------------------------*/
- ranges = <0x02000000 0x00000000 0x40000000 0x40000000 0x00000000 0x10000000
- 0x01000000 0x00000000 0x00000000 0x7e000000 0x00000000 0x00010000>;
- clock-frequency = <133333332>;
- interrupt-parent = <&MPIC>;
+ pci@c0001000 {
+ device_type = "pci";
+ compatible = "tsi109-pci", "tsi108-pci";
+ #interrupt-cells = <1>;
+ #size-cells = <2>;
+ #address-cells = <3>;
+ reg = <0xc0001000 0x00001000>;
+ bus-range = <0x0 0x0>;
+ /*----------------------------------------------------+
+ | PCI memory range.
+ | 01 denotes I/O space
+ | 02 denotes 32-bit memory space
+ +----------------------------------------------------*/
+ ranges = <0x02000000 0x00000000 0x40000000 0x40000000 0x00000000 0x10000000
+ 0x01000000 0x00000000 0x00000000 0x7e000000 0x00000000 0x00010000>;
+ clock-frequency = <133333332>;
+ interrupt-parent = <&MPIC>;
+ interrupts = <0x17 0x2>;
+ interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
+ /*----------------------------------------------------+
+ | The INTA, INTB, INTC, INTD are shared.
+ +----------------------------------------------------*/
+ interrupt-map = <
+ 0x800 0x0 0x0 0x1 &RT0 0x24 0x0
+ 0x800 0x0 0x0 0x2 &RT0 0x25 0x0
+ 0x800 0x0 0x0 0x3 &RT0 0x26 0x0
+ 0x800 0x0 0x0 0x4 &RT0 0x27 0x0
+
+ 0x1000 0x0 0x0 0x1 &RT0 0x25 0x0
+ 0x1000 0x0 0x0 0x2 &RT0 0x26 0x0
+ 0x1000 0x0 0x0 0x3 &RT0 0x27 0x0
+ 0x1000 0x0 0x0 0x4 &RT0 0x24 0x0
+
+ 0x1800 0x0 0x0 0x1 &RT0 0x26 0x0
+ 0x1800 0x0 0x0 0x2 &RT0 0x27 0x0
+ 0x1800 0x0 0x0 0x3 &RT0 0x24 0x0
+ 0x1800 0x0 0x0 0x4 &RT0 0x25 0x0
+
+ 0x2000 0x0 0x0 0x1 &RT0 0x27 0x0
+ 0x2000 0x0 0x0 0x2 &RT0 0x24 0x0
+ 0x2000 0x0 0x0 0x3 &RT0 0x25 0x0
+ 0x2000 0x0 0x0 0x4 &RT0 0x26 0x0
+ >;
+
+ RT0: router@1180 {
+ device_type = "pic-router";
+ interrupt-controller;
+ big-endian;
+ clock-frequency = <0>;
+ #address-cells = <0>;
+ #interrupt-cells = <2>;
interrupts = <0x17 0x2>;
- interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
- /*----------------------------------------------------+
- | The INTA, INTB, INTC, INTD are shared.
- +----------------------------------------------------*/
- interrupt-map = <
- 0x800 0x0 0x0 0x1 &RT0 0x24 0x0
- 0x800 0x0 0x0 0x2 &RT0 0x25 0x0
- 0x800 0x0 0x0 0x3 &RT0 0x26 0x0
- 0x800 0x0 0x0 0x4 &RT0 0x27 0x0
-
- 0x1000 0x0 0x0 0x1 &RT0 0x25 0x0
- 0x1000 0x0 0x0 0x2 &RT0 0x26 0x0
- 0x1000 0x0 0x0 0x3 &RT0 0x27 0x0
- 0x1000 0x0 0x0 0x4 &RT0 0x24 0x0
-
- 0x1800 0x0 0x0 0x1 &RT0 0x26 0x0
- 0x1800 0x0 0x0 0x2 &RT0 0x27 0x0
- 0x1800 0x0 0x0 0x3 &RT0 0x24 0x0
- 0x1800 0x0 0x0 0x4 &RT0 0x25 0x0
-
- 0x2000 0x0 0x0 0x1 &RT0 0x27 0x0
- 0x2000 0x0 0x0 0x2 &RT0 0x24 0x0
- 0x2000 0x0 0x0 0x3 &RT0 0x25 0x0
- 0x2000 0x0 0x0 0x4 &RT0 0x26 0x0
- >;
-
- RT0: router@1180 {
- device_type = "pic-router";
- interrupt-controller;
- big-endian;
- clock-frequency = <0>;
- #address-cells = <0>;
- #interrupt-cells = <2>;
- interrupts = <0x17 0x2>;
- interrupt-parent = <&MPIC>;
- };
+ interrupt-parent = <&MPIC>;
};
};
diff --git a/arch/powerpc/kernel/idle.c b/arch/powerpc/kernel/idle.c
index d308a9f70f1..31982d05d81 100644
--- a/arch/powerpc/kernel/idle.c
+++ b/arch/powerpc/kernel/idle.c
@@ -34,11 +34,7 @@
#include <asm/smp.h>
#ifdef CONFIG_HOTPLUG_CPU
-/* this is used for software suspend, and that shuts down
- * CPUs even while the system is still booting... */
-#define cpu_should_die() (cpu_is_offline(smp_processor_id()) && \
- (system_state == SYSTEM_RUNNING \
- || system_state == SYSTEM_BOOTING))
+#define cpu_should_die() cpu_is_offline(smp_processor_id())
#else
#define cpu_should_die() 0
#endif
diff --git a/arch/powerpc/platforms/fsl_uli1575.c b/arch/powerpc/platforms/fsl_uli1575.c
index ef74a0763ec..8c619963bec 100644
--- a/arch/powerpc/platforms/fsl_uli1575.c
+++ b/arch/powerpc/platforms/fsl_uli1575.c
@@ -219,11 +219,21 @@ static void __devinit quirk_final_uli5249(struct pci_dev *dev)
int i;
u8 *dummy;
struct pci_bus *bus = dev->bus;
+ resource_size_t end = 0;
+
+ for (i = PCI_BRIDGE_RESOURCES; i < PCI_BRIDGE_RESOURCES+3; i++) {
+ unsigned long flags = pci_resource_flags(dev, i);
+ if ((flags & (IORESOURCE_MEM|IORESOURCE_PREFETCH)) == IORESOURCE_MEM)
+ end = pci_resource_end(dev, i);
+ }
for (i = 0; i < PCI_BUS_NUM_RESOURCES; i++) {
if ((bus->resource[i]) &&
(bus->resource[i]->flags & IORESOURCE_MEM)) {
- dummy = ioremap(bus->resource[i]->end - 3, 0x4);
+ if (bus->resource[i]->end == end)
+ dummy = ioremap(bus->resource[i]->start, 0x4);
+ else
+ dummy = ioremap(bus->resource[i]->end - 3, 0x4);
if (dummy) {
in_8(dummy);
iounmap(dummy);
diff --git a/arch/s390/kernel/time.c b/arch/s390/kernel/time.c
index ca114fe46ff..06acb1a18bb 100644
--- a/arch/s390/kernel/time.c
+++ b/arch/s390/kernel/time.c
@@ -169,6 +169,8 @@ void init_cpu_timer(void)
static void clock_comparator_interrupt(__u16 code)
{
+ if (S390_lowcore.clock_comparator == -1ULL)
+ set_clock_comparator(S390_lowcore.clock_comparator);
}
static void etr_timing_alert(struct etr_irq_parm *);
diff --git a/arch/s390/lib/delay.c b/arch/s390/lib/delay.c
index fc6ab6094df..0953cee05ef 100644
--- a/arch/s390/lib/delay.c
+++ b/arch/s390/lib/delay.c
@@ -1,14 +1,9 @@
/*
- * arch/s390/lib/delay.c
* Precise Delay Loops for S390
*
- * S390 version
- * Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
- * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com),
- *
- * Derived from "arch/i386/lib/delay.c"
- * Copyright (C) 1993 Linus Torvalds
- * Copyright (C) 1997 Martin Mares <mj@atrey.karlin.mff.cuni.cz>
+ * Copyright IBM Corp. 1999,2008
+ * Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com>,
+ * Heiko Carstens <heiko.carstens@de.ibm.com>,
*/
#include <linux/sched.h>
@@ -29,30 +24,31 @@ void __delay(unsigned long loops)
asm volatile("0: brct %0,0b" : : "d" ((loops/2) + 1));
}
-/*
- * Waits for 'usecs' microseconds using the TOD clock comparator.
- */
-void __udelay(unsigned long usecs)
+static void __udelay_disabled(unsigned long usecs)
{
- u64 end, time, old_cc = 0;
- unsigned long flags, cr0, mask, dummy;
- int irq_context;
+ unsigned long mask, cr0, cr0_saved;
+ u64 clock_saved;
- irq_context = in_interrupt();
- if (!irq_context)
- local_bh_disable();
- local_irq_save(flags);
- if (raw_irqs_disabled_flags(flags)) {
- old_cc = local_tick_disable();
- S390_lowcore.clock_comparator = -1ULL;
- __ctl_store(cr0, 0, 0);
- dummy = (cr0 & 0xffff00e0) | 0x00000800;
- __ctl_load(dummy , 0, 0);
- mask = psw_kernel_bits | PSW_MASK_WAIT | PSW_MASK_EXT;
- } else
- mask = psw_kernel_bits | PSW_MASK_WAIT |
- PSW_MASK_EXT | PSW_MASK_IO;
+ clock_saved = local_tick_disable();
+ set_clock_comparator(get_clock() + ((u64) usecs << 12));
+ __ctl_store(cr0_saved, 0, 0);
+ cr0 = (cr0_saved & 0xffff00e0) | 0x00000800;
+ __ctl_load(cr0 , 0, 0);
+ mask = psw_kernel_bits | PSW_MASK_WAIT | PSW_MASK_EXT;
+ trace_hardirqs_on();
+ __load_psw_mask(mask);
+ local_irq_disable();
+ __ctl_load(cr0_saved, 0, 0);
+ local_tick_enable(clock_saved);
+ set_clock_comparator(S390_lowcore.clock_comparator);
+}
+static void __udelay_enabled(unsigned long usecs)
+{
+ unsigned long mask;
+ u64 end, time;
+
+ mask = psw_kernel_bits | PSW_MASK_WAIT | PSW_MASK_EXT | PSW_MASK_IO;
end = get_clock() + ((u64) usecs << 12);
do {
time = end < S390_lowcore.clock_comparator ?
@@ -62,13 +58,37 @@ void __udelay(unsigned long usecs)
__load_psw_mask(mask);
local_irq_disable();
} while (get_clock() < end);
+ set_clock_comparator(S390_lowcore.clock_comparator);
+}
- if (raw_irqs_disabled_flags(flags)) {
- __ctl_load(cr0, 0, 0);
- local_tick_enable(old_cc);
+/*
+ * Waits for 'usecs' microseconds using the TOD clock comparator.
+ */
+void __udelay(unsigned long usecs)
+{
+ unsigned long flags;
+
+ preempt_disable();
+ local_irq_save(flags);
+ if (in_irq()) {
+ __udelay_disabled(usecs);
+ goto out;
+ }
+ if (in_softirq()) {
+ if (raw_irqs_disabled_flags(flags))
+ __udelay_disabled(usecs);
+ else
+ __udelay_enabled(usecs);
+ goto out;
}
- if (!irq_context)
+ if (raw_irqs_disabled_flags(flags)) {
+ local_bh_disable();
+ __udelay_disabled(usecs);
_local_bh_enable();
- set_clock_comparator(S390_lowcore.clock_comparator);
+ goto out;
+ }
+ __udelay_enabled(usecs);
+out:
local_irq_restore(flags);
+ preempt_enable();
}
diff --git a/arch/x86/boot/compressed/relocs.c b/arch/x86/boot/compressed/relocs.c
index a1310c52fc0..857e492c571 100644
--- a/arch/x86/boot/compressed/relocs.c
+++ b/arch/x86/boot/compressed/relocs.c
@@ -492,7 +492,7 @@ static void walk_relocs(void (*visit)(Elf32_Rel *rel, Elf32_Sym *sym))
continue;
}
sh_symtab = sec_symtab->symtab;
- sym_strtab = sec->link->strtab;
+ sym_strtab = sec_symtab->link->strtab;
for (j = 0; j < sec->shdr.sh_size/sizeof(Elf32_Rel); j++) {
Elf32_Rel *rel;
Elf32_Sym *sym;
diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c
index bfd10fd211c..c102af85df9 100644
--- a/arch/x86/kernel/acpi/boot.c
+++ b/arch/x86/kernel/acpi/boot.c
@@ -1605,6 +1605,14 @@ static struct dmi_system_id __initdata acpi_dmi_table[] = {
*/
{
.callback = dmi_ignore_irq0_timer_override,
+ .ident = "HP nx6115 laptop",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "HP Compaq nx6115"),
+ },
+ },
+ {
+ .callback = dmi_ignore_irq0_timer_override,
.ident = "HP NX6125 laptop",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
@@ -1619,6 +1627,14 @@ static struct dmi_system_id __initdata acpi_dmi_table[] = {
DMI_MATCH(DMI_PRODUCT_NAME, "HP Compaq nx6325"),
},
},
+ {
+ .callback = dmi_ignore_irq0_timer_override,
+ .ident = "HP 6715b laptop",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "HP Compaq 6715b"),
+ },
+ },
{}
};
diff --git a/arch/x86/kernel/cpu/mtrr/main.c b/arch/x86/kernel/cpu/mtrr/main.c
index b117d7f8a56..885c8265e6b 100644
--- a/arch/x86/kernel/cpu/mtrr/main.c
+++ b/arch/x86/kernel/cpu/mtrr/main.c
@@ -834,7 +834,7 @@ static int __init enable_mtrr_cleanup_setup(char *str)
enable_mtrr_cleanup = 1;
return 0;
}
-early_param("enble_mtrr_cleanup", enable_mtrr_cleanup_setup);
+early_param("enable_mtrr_cleanup", enable_mtrr_cleanup_setup);
struct var_mtrr_state {
unsigned long range_startk;
diff --git a/arch/x86/kernel/kgdb.c b/arch/x86/kernel/kgdb.c
index 8282a213968..10435a120d2 100644
--- a/arch/x86/kernel/kgdb.c
+++ b/arch/x86/kernel/kgdb.c
@@ -455,12 +455,7 @@ static int __kgdb_notify(struct die_args *args, unsigned long cmd)
return NOTIFY_DONE;
case DIE_NMI_IPI:
- if (atomic_read(&kgdb_active) != -1) {
- /* KGDB CPU roundup */
- kgdb_nmicallback(raw_smp_processor_id(), regs);
- was_in_debug_nmi[raw_smp_processor_id()] = 1;
- touch_nmi_watchdog();
- }
+ /* Just ignore, we will handle the roundup on DIE_NMI. */
return NOTIFY_DONE;
case DIE_NMIUNKNOWN:
diff --git a/arch/x86/kernel/pci-gart_64.c b/arch/x86/kernel/pci-gart_64.c
index 49285f8fd4d..be33a5442d8 100644
--- a/arch/x86/kernel/pci-gart_64.c
+++ b/arch/x86/kernel/pci-gart_64.c
@@ -626,7 +626,6 @@ static __init int init_k8_gatt(struct agp_kern_info *info)
struct pci_dev *dev;
void *gatt;
int i, error;
- unsigned long start_pfn, end_pfn;
printk(KERN_INFO "PCI-DMA: Disabling AGP.\n");
aper_size = aper_base = info->aper_size = 0;
@@ -672,12 +671,6 @@ static __init int init_k8_gatt(struct agp_kern_info *info)
printk(KERN_INFO "PCI-DMA: aperture base @ %x size %u KB\n",
aper_base, aper_size>>10);
- /* need to map that range */
- end_pfn = (aper_base>>PAGE_SHIFT) + (aper_size>>PAGE_SHIFT);
- if (end_pfn > max_low_pfn_mapped) {
- start_pfn = (aper_base>>PAGE_SHIFT);
- init_memory_mapping(start_pfn<<PAGE_SHIFT, end_pfn<<PAGE_SHIFT);
- }
return 0;
nommu:
@@ -727,7 +720,8 @@ void __init gart_iommu_init(void)
{
struct agp_kern_info info;
unsigned long iommu_start;
- unsigned long aper_size;
+ unsigned long aper_base, aper_size;
+ unsigned long start_pfn, end_pfn;
unsigned long scratch;
long i;
@@ -765,8 +759,16 @@ void __init gart_iommu_init(void)
return;
}
+ /* need to map that range */
+ aper_size = info.aper_size << 20;
+ aper_base = info.aper_base;
+ end_pfn = (aper_base>>PAGE_SHIFT) + (aper_size>>PAGE_SHIFT);
+ if (end_pfn > max_low_pfn_mapped) {
+ start_pfn = (aper_base>>PAGE_SHIFT);
+ init_memory_mapping(start_pfn<<PAGE_SHIFT, end_pfn<<PAGE_SHIFT);
+ }
+
printk(KERN_INFO "PCI-DMA: using GART IOMMU.\n");
- aper_size = info.aper_size * 1024 * 1024;
iommu_size = check_iommu_size(info.aper_base, aper_size);
iommu_pages = iommu_size >> PAGE_SHIFT;
diff --git a/arch/x86/kernel/vmi_32.c b/arch/x86/kernel/vmi_32.c
index 6ca515d6db5..edfb09f3047 100644
--- a/arch/x86/kernel/vmi_32.c
+++ b/arch/x86/kernel/vmi_32.c
@@ -235,7 +235,7 @@ static void vmi_write_ldt_entry(struct desc_struct *dt, int entry,
const void *desc)
{
u32 *ldt_entry = (u32 *)desc;
- vmi_ops.write_idt_entry(dt, entry, ldt_entry[0], ldt_entry[1]);
+ vmi_ops.write_ldt_entry(dt, entry, ldt_entry[0], ldt_entry[1]);
}
static void vmi_load_sp0(struct tss_struct *tss,
diff --git a/drivers/accessibility/braille/braille_console.c b/drivers/accessibility/braille/braille_console.c
index 0a5f6b2114c..d672cfe7ca5 100644
--- a/drivers/accessibility/braille/braille_console.c
+++ b/drivers/accessibility/braille/braille_console.c
@@ -376,6 +376,8 @@ int braille_register_console(struct console *console, int index,
console->flags |= CON_ENABLED;
console->index = index;
braille_co = console;
+ register_keyboard_notifier(&keyboard_notifier_block);
+ register_vt_notifier(&vt_notifier_block);
return 0;
}
@@ -383,15 +385,8 @@ int braille_unregister_console(struct console *console)
{
if (braille_co != console)
return -EINVAL;
+ unregister_keyboard_notifier(&keyboard_notifier_block);
+ unregister_vt_notifier(&vt_notifier_block);
braille_co = NULL;
return 0;
}
-
-static int __init braille_init(void)
-{
- register_keyboard_notifier(&keyboard_notifier_block);
- register_vt_notifier(&vt_notifier_block);
- return 0;
-}
-
-console_initcall(braille_init);
diff --git a/drivers/acpi/glue.c b/drivers/acpi/glue.c
index 084109507c9..8dd3336efd7 100644
--- a/drivers/acpi/glue.c
+++ b/drivers/acpi/glue.c
@@ -165,8 +165,11 @@ static int acpi_bind_one(struct device *dev, acpi_handle handle)
"firmware_node");
ret = sysfs_create_link(&acpi_dev->dev.kobj, &dev->kobj,
"physical_node");
- if (acpi_dev->wakeup.flags.valid)
+ if (acpi_dev->wakeup.flags.valid) {
device_set_wakeup_capable(dev, true);
+ device_set_wakeup_enable(dev,
+ acpi_dev->wakeup.state.enabled);
+ }
}
return 0;
diff --git a/drivers/acpi/sleep/proc.c b/drivers/acpi/sleep/proc.c
index 4ebbba2b6b1..bf5b04de02d 100644
--- a/drivers/acpi/sleep/proc.c
+++ b/drivers/acpi/sleep/proc.c
@@ -377,6 +377,14 @@ acpi_system_wakeup_device_seq_show(struct seq_file *seq, void *offset)
return 0;
}
+static void physical_device_enable_wakeup(struct acpi_device *adev)
+{
+ struct device *dev = acpi_get_physical_device(adev->handle);
+
+ if (dev && device_can_wakeup(dev))
+ device_set_wakeup_enable(dev, adev->wakeup.state.enabled);
+}
+
static ssize_t
acpi_system_write_wakeup_device(struct file *file,
const char __user * buffer,
@@ -411,6 +419,7 @@ acpi_system_write_wakeup_device(struct file *file,
}
}
if (found_dev) {
+ physical_device_enable_wakeup(found_dev);
list_for_each_safe(node, next, &acpi_wakeup_device_list) {
struct acpi_device *dev = container_of(node,
struct
@@ -428,6 +437,7 @@ acpi_system_write_wakeup_device(struct file *file,
dev->pnp.bus_id, found_dev->pnp.bus_id);
dev->wakeup.state.enabled =
found_dev->wakeup.state.enabled;
+ physical_device_enable_wakeup(dev);
}
}
}
diff --git a/drivers/bluetooth/bpa10x.c b/drivers/bluetooth/bpa10x.c
index 1e55a658e6c..32f3a8ed8d3 100644
--- a/drivers/bluetooth/bpa10x.c
+++ b/drivers/bluetooth/bpa10x.c
@@ -256,7 +256,6 @@ static inline int bpa10x_submit_intr_urb(struct hci_dev *hdev)
BT_ERR("%s urb %p submission failed (%d)",
hdev->name, urb, -err);
usb_unanchor_urb(urb);
- kfree(buf);
}
usb_free_urb(urb);
@@ -298,7 +297,6 @@ static inline int bpa10x_submit_bulk_urb(struct hci_dev *hdev)
BT_ERR("%s urb %p submission failed (%d)",
hdev->name, urb, -err);
usb_unanchor_urb(urb);
- kfree(buf);
}
usb_free_urb(urb);
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
index 29ae99817c6..af472e05273 100644
--- a/drivers/bluetooth/btusb.c
+++ b/drivers/bluetooth/btusb.c
@@ -102,6 +102,7 @@ static struct usb_device_id blacklist_table[] = {
{ USB_DEVICE(0x0a5c, 0x2101), .driver_info = BTUSB_RESET | BTUSB_WRONG_SCO_MTU },
/* Broadcom BCM2046 */
+ { USB_DEVICE(0x0a5c, 0x2146), .driver_info = BTUSB_RESET },
{ USB_DEVICE(0x0a5c, 0x2151), .driver_info = BTUSB_RESET },
/* Apple MacBook Pro with Broadcom chip */
@@ -113,6 +114,7 @@ static struct usb_device_id blacklist_table[] = {
/* Targus ACB10US */
{ USB_DEVICE(0x0a5c, 0x2100), .driver_info = BTUSB_RESET },
+ { USB_DEVICE(0x0a5c, 0x2154), .driver_info = BTUSB_RESET },
/* ANYCOM Bluetooth USB-200 and USB-250 */
{ USB_DEVICE(0x0a5c, 0x2111), .driver_info = BTUSB_RESET },
@@ -150,6 +152,9 @@ static struct usb_device_id blacklist_table[] = {
{ USB_DEVICE(0x050d, 0x0012), .driver_info = BTUSB_RESET | BTUSB_WRONG_SCO_MTU },
{ USB_DEVICE(0x050d, 0x0013), .driver_info = BTUSB_RESET | BTUSB_WRONG_SCO_MTU },
+ /* Belkin F8T016 device */
+ { USB_DEVICE(0x050d, 0x016a), .driver_info = BTUSB_RESET },
+
/* Digianswer devices */
{ USB_DEVICE(0x08fd, 0x0001), .driver_info = BTUSB_DIGIANSWER },
{ USB_DEVICE(0x08fd, 0x0002), .driver_info = BTUSB_IGNORE },
@@ -271,7 +276,6 @@ static int btusb_submit_intr_urb(struct hci_dev *hdev)
BT_ERR("%s urb %p submission failed (%d)",
hdev->name, urb, -err);
usb_unanchor_urb(urb);
- kfree(buf);
}
usb_free_urb(urb);
@@ -354,7 +358,6 @@ static int btusb_submit_bulk_urb(struct hci_dev *hdev)
BT_ERR("%s urb %p submission failed (%d)",
hdev->name, urb, -err);
usb_unanchor_urb(urb);
- kfree(buf);
}
usb_free_urb(urb);
@@ -475,7 +478,6 @@ static int btusb_submit_isoc_urb(struct hci_dev *hdev)
BT_ERR("%s urb %p submission failed (%d)",
hdev->name, urb, -err);
usb_unanchor_urb(urb);
- kfree(buf);
}
usb_free_urb(urb);
diff --git a/drivers/dma/dw_dmac.c b/drivers/dma/dw_dmac.c
index 94df9177124..0778d99aea7 100644
--- a/drivers/dma/dw_dmac.c
+++ b/drivers/dma/dw_dmac.c
@@ -364,7 +364,7 @@ static void dw_dma_tasklet(unsigned long data)
int i;
status_block = dma_readl(dw, RAW.BLOCK);
- status_xfer = dma_readl(dw, RAW.BLOCK);
+ status_xfer = dma_readl(dw, RAW.XFER);
status_err = dma_readl(dw, RAW.ERROR);
dev_vdbg(dw->dma.dev, "tasklet: status_block=%x status_err=%x\n",
diff --git a/drivers/ide/Kconfig b/drivers/ide/Kconfig
index 8e93a797c93..052879a6f85 100644
--- a/drivers/ide/Kconfig
+++ b/drivers/ide/Kconfig
@@ -780,10 +780,6 @@ config BLK_DEV_IDEDMA_PMAC
to transfer data to and from memory. Saying Y is safe and improves
performance.
-config BLK_DEV_IDE_SWARM
- tristate "IDE for Sibyte evaluation boards"
- depends on SIBYTE_SB1xxx_SOC
-
config BLK_DEV_IDE_AU1XXX
bool "IDE for AMD Alchemy Au1200"
depends on SOC_AU1200
diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c
index 49a8c589e34..f16bb466723 100644
--- a/drivers/ide/ide-cd.c
+++ b/drivers/ide/ide-cd.c
@@ -1661,7 +1661,9 @@ static int ide_cdrom_probe_capabilities(ide_drive_t *drive)
cdi->mask &= ~CDC_PLAY_AUDIO;
mechtype = buf[8 + 6] >> 5;
- if (mechtype == mechtype_caddy || mechtype == mechtype_popup)
+ if (mechtype == mechtype_caddy ||
+ mechtype == mechtype_popup ||
+ (drive->atapi_flags & IDE_AFLAG_NO_AUTOCLOSE))
cdi->mask |= CDC_CLOSE_TRAY;
if (cdi->sanyo_slot > 0) {
@@ -1859,6 +1861,8 @@ static const struct cd_list_entry ide_cd_quirks_list[] = {
{ "MATSHITADVD-ROM SR-8176", NULL, IDE_AFLAG_PLAY_AUDIO_OK },
{ "MATSHITADVD-ROM SR-8174", NULL, IDE_AFLAG_PLAY_AUDIO_OK },
{ "Optiarc DVD RW AD-5200A", NULL, IDE_AFLAG_PLAY_AUDIO_OK },
+ { "Optiarc DVD RW AD-7200A", NULL, IDE_AFLAG_PLAY_AUDIO_OK },
+ { "Optiarc DVD RW AD-7543A", NULL, IDE_AFLAG_NO_AUTOCLOSE },
{ NULL, NULL, 0 }
};
diff --git a/drivers/ide/ide-dma.c b/drivers/ide/ide-dma.c
index adc68275585..3fa07c0aeaa 100644
--- a/drivers/ide/ide-dma.c
+++ b/drivers/ide/ide-dma.c
@@ -211,7 +211,7 @@ int ide_build_dmatable (ide_drive_t *drive, struct request *rq)
xcount = bcount & 0xffff;
if (is_trm290)
xcount = ((xcount >> 2) - 1) << 16;
- if (xcount == 0x0000) {
+ else if (xcount == 0x0000) {
/*
* Most chipsets correctly interpret a length of 0x0000 as 64KB,
* but at least one (e.g. CS5530) misinterprets it as zero (!).
diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c
index 994e41099b4..a51a30e9eab 100644
--- a/drivers/ide/ide-probe.c
+++ b/drivers/ide/ide-probe.c
@@ -1492,7 +1492,7 @@ static struct device_attribute *ide_port_attrs[] = {
static int ide_sysfs_register_port(ide_hwif_t *hwif)
{
- int i, rc;
+ int i, uninitialized_var(rc);
for (i = 0; ide_port_attrs[i]; i++) {
rc = device_create_file(hwif->portdev, ide_port_attrs[i]);
diff --git a/drivers/ide/mips/Makefile b/drivers/ide/mips/Makefile
index 677c7b2bac9..5873fa0b876 100644
--- a/drivers/ide/mips/Makefile
+++ b/drivers/ide/mips/Makefile
@@ -1,4 +1,3 @@
-obj-$(CONFIG_BLK_DEV_IDE_SWARM) += swarm.o
obj-$(CONFIG_BLK_DEV_IDE_AU1XXX) += au1xxx-ide.o
EXTRA_CFLAGS := -Idrivers/ide
diff --git a/drivers/ide/mips/swarm.c b/drivers/ide/mips/swarm.c
deleted file mode 100644
index 39c9ee99585..00000000000
--- a/drivers/ide/mips/swarm.c
+++ /dev/null
@@ -1,197 +0,0 @@
-/*
- * Copyright (C) 2001, 2002, 2003 Broadcom Corporation
- * Copyright (C) 2004 MontaVista Software Inc.
- * Author: Manish Lachwani, mlachwani@mvista.com
- * Copyright (C) 2004 MIPS Technologies, Inc. All rights reserved.
- * Author: Maciej W. Rozycki <macro@mips.com>
- * Copyright (c) 2006, 2008 Maciej W. Rozycki
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-/*
- * Derived loosely from ide-pmac.c, so:
- * Copyright (C) 1998 Paul Mackerras.
- * Copyright (C) 1995-1998 Mark Lord
- */
-
-/*
- * Boards with SiByte processors so far have supported IDE devices via
- * the Generic Bus, PCI bus, and built-in PCMCIA interface. In all
- * cases, byte-swapping must be avoided for these devices (whereas
- * other PCI devices, for example, will require swapping). Any
- * SiByte-targetted kernel including IDE support will include this
- * file. Probing of a Generic Bus for an IDE device is controlled by
- * the definition of "SIBYTE_HAVE_IDE", which is provided by
- * <asm/sibyte/board.h> for Broadcom boards.
- */
-
-#include <linux/ide.h>
-#include <linux/ioport.h>
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/platform_device.h>
-
-#include <asm/io.h>
-
-#include <asm/sibyte/board.h>
-#include <asm/sibyte/sb1250_genbus.h>
-#include <asm/sibyte/sb1250_regs.h>
-
-#define DRV_NAME "ide-swarm"
-
-static char swarm_ide_string[] = DRV_NAME;
-
-static struct resource swarm_ide_resource = {
- .name = "SWARM GenBus IDE",
- .flags = IORESOURCE_MEM,
-};
-
-static struct platform_device *swarm_ide_dev;
-
-static const struct ide_port_info swarm_port_info = {
- .name = DRV_NAME,
- .host_flags = IDE_HFLAG_MMIO | IDE_HFLAG_NO_DMA,
-};
-
-/*
- * swarm_ide_probe - if the board header indicates the existence of
- * Generic Bus IDE, allocate a HWIF for it.
- */
-static int __devinit swarm_ide_probe(struct device *dev)
-{
- u8 __iomem *base;
- struct ide_host *host;
- phys_t offset, size;
- int i, rc;
- hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL };
-
- if (!SIBYTE_HAVE_IDE)
- return -ENODEV;
-
- base = ioremap(A_IO_EXT_BASE, 0x800);
- offset = __raw_readq(base + R_IO_EXT_REG(R_IO_EXT_START_ADDR, IDE_CS));
- size = __raw_readq(base + R_IO_EXT_REG(R_IO_EXT_MULT_SIZE, IDE_CS));
- iounmap(base);
-
- offset = G_IO_START_ADDR(offset) << S_IO_ADDRBASE;
- size = (G_IO_MULT_SIZE(size) + 1) << S_IO_REGSIZE;
- if (offset < A_PHYS_GENBUS || offset >= A_PHYS_GENBUS_END) {
- printk(KERN_INFO DRV_NAME
- ": IDE interface at GenBus disabled\n");
- return -EBUSY;
- }
-
- printk(KERN_INFO DRV_NAME ": IDE interface at GenBus slot %i\n",
- IDE_CS);
-
- swarm_ide_resource.start = offset;
- swarm_ide_resource.end = offset + size - 1;
- if (request_resource(&iomem_resource, &swarm_ide_resource)) {
- printk(KERN_ERR DRV_NAME
- ": can't request I/O memory resource\n");
- return -EBUSY;
- }
-
- base = ioremap(offset, size);
-
- memset(&hw, 0, sizeof(hw));
- for (i = 0; i <= 7; i++)
- hw.io_ports_array[i] =
- (unsigned long)(base + ((0x1f0 + i) << 5));
- hw.io_ports.ctl_addr =
- (unsigned long)(base + (0x3f6 << 5));
- hw.irq = K_INT_GB_IDE;
- hw.chipset = ide_generic;
-
- rc = ide_host_add(&swarm_port_info, hws, &host);
- if (rc)
- goto err;
-
- dev_set_drvdata(dev, host);
-
- return 0;
-err:
- release_resource(&swarm_ide_resource);
- iounmap(base);
- return rc;
-}
-
-static struct device_driver swarm_ide_driver = {
- .name = swarm_ide_string,
- .bus = &platform_bus_type,
- .probe = swarm_ide_probe,
-};
-
-static void swarm_ide_platform_release(struct device *device)
-{
- struct platform_device *pldev;
-
- /* free device */
- pldev = to_platform_device(device);
- kfree(pldev);
-}
-
-static int __devinit swarm_ide_init_module(void)
-{
- struct platform_device *pldev;
- int err;
-
- printk(KERN_INFO "SWARM IDE driver\n");
-
- if (driver_register(&swarm_ide_driver)) {
- printk(KERN_ERR "Driver registration failed\n");
- err = -ENODEV;
- goto out;
- }
-
- if (!(pldev = kzalloc(sizeof (*pldev), GFP_KERNEL))) {
- err = -ENOMEM;
- goto out_unregister_driver;
- }
-
- pldev->name = swarm_ide_string;
- pldev->id = 0;
- pldev->dev.release = swarm_ide_platform_release;
-
- if (platform_device_register(pldev)) {
- err = -ENODEV;
- goto out_free_pldev;
- }
-
- if (!pldev->dev.driver) {
- /*
- * The driver was not bound to this device, there was
- * no hardware at this address. Unregister it, as the
- * release fuction will take care of freeing the
- * allocated structure
- */
- platform_device_unregister (pldev);
- }
-
- swarm_ide_dev = pldev;
-
- return 0;
-
-out_free_pldev:
- kfree(pldev);
-
-out_unregister_driver:
- driver_unregister(&swarm_ide_driver);
-out:
- return err;
-}
-
-module_init(swarm_ide_init_module);
diff --git a/drivers/leds/leds-fsg.c b/drivers/leds/leds-fsg.c
index be0e12144b8..34935155c1c 100644
--- a/drivers/leds/leds-fsg.c
+++ b/drivers/leds/leds-fsg.c
@@ -161,6 +161,16 @@ static int fsg_led_probe(struct platform_device *pdev)
{
int ret;
+ /* Map the LED chip select address space */
+ latch_address = (unsigned short *) ioremap(IXP4XX_EXP_BUS_BASE(2), 512);
+ if (!latch_address) {
+ ret = -ENOMEM;
+ goto failremap;
+ }
+
+ latch_value = 0xffff;
+ *latch_address = latch_value;
+
ret = led_classdev_register(&pdev->dev, &fsg_wlan_led);
if (ret < 0)
goto failwlan;
@@ -185,20 +195,8 @@ static int fsg_led_probe(struct platform_device *pdev)
if (ret < 0)
goto failring;
- /* Map the LED chip select address space */
- latch_address = (unsigned short *) ioremap(IXP4XX_EXP_BUS_BASE(2), 512);
- if (!latch_address) {
- ret = -ENOMEM;
- goto failremap;
- }
-
- latch_value = 0xffff;
- *latch_address = latch_value;
-
return ret;
- failremap:
- led_classdev_unregister(&fsg_ring_led);
failring:
led_classdev_unregister(&fsg_sync_led);
failsync:
@@ -210,14 +208,14 @@ static int fsg_led_probe(struct platform_device *pdev)
failwan:
led_classdev_unregister(&fsg_wlan_led);
failwlan:
+ iounmap(latch_address);
+ failremap:
return ret;
}
static int fsg_led_remove(struct platform_device *pdev)
{
- iounmap(latch_address);
-
led_classdev_unregister(&fsg_wlan_led);
led_classdev_unregister(&fsg_wan_led);
led_classdev_unregister(&fsg_sata_led);
@@ -225,6 +223,8 @@ static int fsg_led_remove(struct platform_device *pdev)
led_classdev_unregister(&fsg_sync_led);
led_classdev_unregister(&fsg_ring_led);
+ iounmap(latch_address);
+
return 0;
}
diff --git a/drivers/leds/leds-pca955x.c b/drivers/leds/leds-pca955x.c
index 146c0697286..f508729123b 100644
--- a/drivers/leds/leds-pca955x.c
+++ b/drivers/leds/leds-pca955x.c
@@ -248,11 +248,10 @@ static int __devinit pca955x_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct pca955x_led *pca955x;
- int i;
- int err = -ENODEV;
struct pca955x_chipdef *chip;
struct i2c_adapter *adapter;
struct led_platform_data *pdata;
+ int i, err;
chip = &pca955x_chipdefs[id->driver_data];
adapter = to_i2c_adapter(client->dev.parent);
@@ -282,43 +281,41 @@ static int __devinit pca955x_probe(struct i2c_client *client,
}
}
+ pca955x = kzalloc(sizeof(*pca955x) * chip->bits, GFP_KERNEL);
+ if (!pca955x)
+ return -ENOMEM;
+
+ i2c_set_clientdata(client, pca955x);
+
for (i = 0; i < chip->bits; i++) {
- pca955x = kzalloc(sizeof(struct pca955x_led), GFP_KERNEL);
- if (!pca955x) {
- err = -ENOMEM;
- goto exit;
- }
+ pca955x[i].chipdef = chip;
+ pca955x[i].client = client;
+ pca955x[i].led_num = i;
- pca955x->chipdef = chip;
- pca955x->client = client;
- pca955x->led_num = i;
/* Platform data can specify LED names and default triggers */
if (pdata) {
if (pdata->leds[i].name)
- snprintf(pca955x->name, 32, "pca955x:%s",
- pdata->leds[i].name);
+ snprintf(pca955x[i].name,
+ sizeof(pca955x[i].name), "pca955x:%s",
+ pdata->leds[i].name);
if (pdata->leds[i].default_trigger)
- pca955x->led_cdev.default_trigger =
+ pca955x[i].led_cdev.default_trigger =
pdata->leds[i].default_trigger;
} else {
- snprintf(pca955x->name, 32, "pca955x:%d", i);
+ snprintf(pca955x[i].name, sizeof(pca955x[i].name),
+ "pca955x:%d", i);
}
- spin_lock_init(&pca955x->lock);
- pca955x->led_cdev.name = pca955x->name;
- pca955x->led_cdev.brightness_set =
- pca955x_led_set;
+ spin_lock_init(&pca955x[i].lock);
- /*
- * Client data is a pointer to the _first_ pca955x_led
- * struct
- */
- if (i == 0)
- i2c_set_clientdata(client, pca955x);
+ pca955x[i].led_cdev.name = pca955x[i].name;
+ pca955x[i].led_cdev.brightness_set = pca955x_led_set;
- INIT_WORK(&(pca955x->work), pca955x_led_work);
+ INIT_WORK(&pca955x[i].work, pca955x_led_work);
- led_classdev_register(&client->dev, &(pca955x->led_cdev));
+ err = led_classdev_register(&client->dev, &pca955x[i].led_cdev);
+ if (err < 0)
+ goto exit;
}
/* Turn off LEDs */
@@ -336,23 +333,32 @@ static int __devinit pca955x_probe(struct i2c_client *client,
pca955x_write_psc(client, 1, 0);
return 0;
+
exit:
+ while (i--) {
+ led_classdev_unregister(&pca955x[i].led_cdev);
+ cancel_work_sync(&pca955x[i].work);
+ }
+
+ kfree(pca955x);
+ i2c_set_clientdata(client, NULL);
+
return err;
}
static int __devexit pca955x_remove(struct i2c_client *client)
{
struct pca955x_led *pca955x = i2c_get_clientdata(client);
- int leds = pca955x->chipdef->bits;
int i;
- for (i = 0; i < leds; i++) {
- led_classdev_unregister(&(pca955x->led_cdev));
- cancel_work_sync(&(pca955x->work));
- kfree(pca955x);
- pca955x = pca955x + 1;
+ for (i = 0; i < pca955x->chipdef->bits; i++) {
+ led_classdev_unregister(&pca955x[i].led_cdev);
+ cancel_work_sync(&pca955x[i].work);
}
+ kfree(pca955x);
+ i2c_set_clientdata(client, NULL);
+
return 0;
}
diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c
index 71dd65aa31b..c2fcf28b4c7 100644
--- a/drivers/md/dm-mpath.c
+++ b/drivers/md/dm-mpath.c
@@ -63,6 +63,7 @@ struct multipath {
const char *hw_handler_name;
struct work_struct activate_path;
+ struct pgpath *pgpath_to_activate;
unsigned nr_priority_groups;
struct list_head priority_groups;
unsigned pg_init_required; /* pg_init needs calling? */
@@ -146,6 +147,7 @@ static struct priority_group *alloc_priority_group(void)
static void free_pgpaths(struct list_head *pgpaths, struct dm_target *ti)
{
+ unsigned long flags;
struct pgpath *pgpath, *tmp;
struct multipath *m = ti->private;
@@ -154,6 +156,10 @@ static void free_pgpaths(struct list_head *pgpaths, struct dm_target *ti)
if (m->hw_handler_name)
scsi_dh_detach(bdev_get_queue(pgpath->path.dev->bdev));
dm_put_device(ti, pgpath->path.dev);
+ spin_lock_irqsave(&m->lock, flags);
+ if (m->pgpath_to_activate == pgpath)
+ m->pgpath_to_activate = NULL;
+ spin_unlock_irqrestore(&m->lock, flags);
free_pgpath(pgpath);
}
}
@@ -421,6 +427,7 @@ static void process_queued_ios(struct work_struct *work)
__choose_pgpath(m);
pgpath = m->current_pgpath;
+ m->pgpath_to_activate = m->current_pgpath;
if ((pgpath && !m->queue_io) ||
(!pgpath && !m->queue_if_no_path))
@@ -1093,8 +1100,15 @@ static void activate_path(struct work_struct *work)
int ret;
struct multipath *m =
container_of(work, struct multipath, activate_path);
- struct dm_path *path = &m->current_pgpath->path;
+ struct dm_path *path;
+ unsigned long flags;
+ spin_lock_irqsave(&m->lock, flags);
+ path = &m->pgpath_to_activate->path;
+ m->pgpath_to_activate = NULL;
+ spin_unlock_irqrestore(&m->lock, flags);
+ if (!path)
+ return;
ret = scsi_dh_activate(bdev_get_queue(path->dev->bdev));
pg_init_done(path, ret);
}
diff --git a/drivers/md/dm.c b/drivers/md/dm.c
index bca448e1187..ace998ce59f 100644
--- a/drivers/md/dm.c
+++ b/drivers/md/dm.c
@@ -837,12 +837,14 @@ static int dm_merge_bvec(struct request_queue *q,
struct dm_table *map = dm_get_table(md);
struct dm_target *ti;
sector_t max_sectors;
- int max_size;
+ int max_size = 0;
if (unlikely(!map))
- return 0;
+ goto out;
ti = dm_table_find_target(map, bvm->bi_sector);
+ if (!dm_target_is_valid(ti))
+ goto out_table;
/*
* Find maximum amount of I/O that won't need splitting
@@ -861,14 +863,16 @@ static int dm_merge_bvec(struct request_queue *q,
if (max_size && ti->type->merge)
max_size = ti->type->merge(ti, bvm, biovec, max_size);
+out_table:
+ dm_table_put(map);
+
+out:
/*
* Always allow an entire first page
*/
if (max_size <= biovec->bv_len && !(bvm->bi_size >> SECTOR_SHIFT))
max_size = biovec->bv_len;
- dm_table_put(map);
-
return max_size;
}
diff --git a/drivers/media/common/tuners/tuner-xc2028.h b/drivers/media/common/tuners/tuner-xc2028.h
index 216025cf5d4..2c5b6282b56 100644
--- a/drivers/media/common/tuners/tuner-xc2028.h
+++ b/drivers/media/common/tuners/tuner-xc2028.h
@@ -10,6 +10,7 @@
#include "dvb_frontend.h"
#define XC2028_DEFAULT_FIRMWARE "xc3028-v27.fw"
+#define XC3028L_DEFAULT_FIRMWARE "xc3028L-v36.fw"
/* Dmoduler IF (kHz) */
#define XC3028_FE_DEFAULT 0 /* Don't load SCODE */
diff --git a/drivers/media/dvb/b2c2/flexcop-fe-tuner.c b/drivers/media/dvb/b2c2/flexcop-fe-tuner.c
index 4eed783f4bc..a127a4175c4 100644
--- a/drivers/media/dvb/b2c2/flexcop-fe-tuner.c
+++ b/drivers/media/dvb/b2c2/flexcop-fe-tuner.c
@@ -491,6 +491,7 @@ static struct s5h1420_config skystar2_rev2_7_s5h1420_config = {
.demod_address = 0x53,
.invert = 1,
.repeated_start_workaround = 1,
+ .serial_mpeg = 1,
};
static struct itd1000_config skystar2_rev2_7_itd1000_config = {
diff --git a/drivers/media/dvb/dvb-core/dmxdev.c b/drivers/media/dvb/dvb-core/dmxdev.c
index 069d847ba88..0c733c66a44 100644
--- a/drivers/media/dvb/dvb-core/dmxdev.c
+++ b/drivers/media/dvb/dvb-core/dmxdev.c
@@ -364,15 +364,16 @@ static int dvb_dmxdev_section_callback(const u8 *buffer1, size_t buffer1_len,
enum dmx_success success)
{
struct dmxdev_filter *dmxdevfilter = filter->priv;
+ unsigned long flags;
int ret;
if (dmxdevfilter->buffer.error) {
wake_up(&dmxdevfilter->buffer.queue);
return 0;
}
- spin_lock(&dmxdevfilter->dev->lock);
+ spin_lock_irqsave(&dmxdevfilter->dev->lock, flags);
if (dmxdevfilter->state != DMXDEV_STATE_GO) {
- spin_unlock(&dmxdevfilter->dev->lock);
+ spin_unlock_irqrestore(&dmxdevfilter->dev->lock, flags);
return 0;
}
del_timer(&dmxdevfilter->timer);
@@ -391,7 +392,7 @@ static int dvb_dmxdev_section_callback(const u8 *buffer1, size_t buffer1_len,
}
if (dmxdevfilter->params.sec.flags & DMX_ONESHOT)
dmxdevfilter->state = DMXDEV_STATE_DONE;
- spin_unlock(&dmxdevfilter->dev->lock);
+ spin_unlock_irqrestore(&dmxdevfilter->dev->lock, flags);
wake_up(&dmxdevfilter->buffer.queue);
return 0;
}
@@ -403,11 +404,12 @@ static int dvb_dmxdev_ts_callback(const u8 *buffer1, size_t buffer1_len,
{
struct dmxdev_filter *dmxdevfilter = feed->priv;
struct dvb_ringbuffer *buffer;
+ unsigned long flags;
int ret;
- spin_lock(&dmxdevfilter->dev->lock);
+ spin_lock_irqsave(&dmxdevfilter->dev->lock, flags);
if (dmxdevfilter->params.pes.output == DMX_OUT_DECODER) {
- spin_unlock(&dmxdevfilter->dev->lock);
+ spin_unlock_irqrestore(&dmxdevfilter->dev->lock, flags);
return 0;
}
@@ -417,7 +419,7 @@ static int dvb_dmxdev_ts_callback(const u8 *buffer1, size_t buffer1_len,
else
buffer = &dmxdevfilter->dev->dvr_buffer;
if (buffer->error) {
- spin_unlock(&dmxdevfilter->dev->lock);
+ spin_unlock_irqrestore(&dmxdevfilter->dev->lock, flags);
wake_up(&buffer->queue);
return 0;
}
@@ -428,7 +430,7 @@ static int dvb_dmxdev_ts_callback(const u8 *buffer1, size_t buffer1_len,
dvb_ringbuffer_flush(buffer);
buffer->error = ret;
}
- spin_unlock(&dmxdevfilter->dev->lock);
+ spin_unlock_irqrestore(&dmxdevfilter->dev->lock, flags);
wake_up(&buffer->queue);
return 0;
}
diff --git a/drivers/media/dvb/dvb-core/dvb_demux.c b/drivers/media/dvb/dvb-core/dvb_demux.c
index e2eca0b1fe7..a2c1fd5d2f6 100644
--- a/drivers/media/dvb/dvb-core/dvb_demux.c
+++ b/drivers/media/dvb/dvb-core/dvb_demux.c
@@ -399,7 +399,9 @@ static void dvb_dmx_swfilter_packet(struct dvb_demux *demux, const u8 *buf)
void dvb_dmx_swfilter_packets(struct dvb_demux *demux, const u8 *buf,
size_t count)
{
- spin_lock(&demux->lock);
+ unsigned long flags;
+
+ spin_lock_irqsave(&demux->lock, flags);
while (count--) {
if (buf[0] == 0x47)
@@ -407,16 +409,17 @@ void dvb_dmx_swfilter_packets(struct dvb_demux *demux, const u8 *buf,
buf += 188;
}
- spin_unlock(&demux->lock);
+ spin_unlock_irqrestore(&demux->lock, flags);
}
EXPORT_SYMBOL(dvb_dmx_swfilter_packets);
void dvb_dmx_swfilter(struct dvb_demux *demux, const u8 *buf, size_t count)
{
+ unsigned long flags;
int p = 0, i, j;
- spin_lock(&demux->lock);
+ spin_lock_irqsave(&demux->lock, flags);
if (demux->tsbufp) {
i = demux->tsbufp;
@@ -449,17 +452,18 @@ void dvb_dmx_swfilter(struct dvb_demux *demux, const u8 *buf, size_t count)
}
bailout:
- spin_unlock(&demux->lock);
+ spin_unlock_irqrestore(&demux->lock, flags);
}
EXPORT_SYMBOL(dvb_dmx_swfilter);
void dvb_dmx_swfilter_204(struct dvb_demux *demux, const u8 *buf, size_t count)
{
+ unsigned long flags;
int p = 0, i, j;
u8 tmppack[188];
- spin_lock(&demux->lock);
+ spin_lock_irqsave(&demux->lock, flags);
if (demux->tsbufp) {
i = demux->tsbufp;
@@ -500,7 +504,7 @@ void dvb_dmx_swfilter_204(struct dvb_demux *demux, const u8 *buf, size_t count)
}
bailout:
- spin_unlock(&demux->lock);
+ spin_unlock_irqrestore(&demux->lock, flags);
}
EXPORT_SYMBOL(dvb_dmx_swfilter_204);
diff --git a/drivers/media/dvb/frontends/s5h1420.c b/drivers/media/dvb/frontends/s5h1420.c
index 747d3fa2e5e..2e9fd2893ed 100644
--- a/drivers/media/dvb/frontends/s5h1420.c
+++ b/drivers/media/dvb/frontends/s5h1420.c
@@ -59,7 +59,7 @@ struct s5h1420_state {
* it does not support repeated-start, workaround: write addr-1
* and then read
*/
- u8 shadow[255];
+ u8 shadow[256];
};
static u32 s5h1420_getsymbolrate(struct s5h1420_state* state);
@@ -94,8 +94,11 @@ static u8 s5h1420_readreg(struct s5h1420_state *state, u8 reg)
if (ret != 3)
return ret;
} else {
- ret = i2c_transfer(state->i2c, &msg[1], 2);
- if (ret != 2)
+ ret = i2c_transfer(state->i2c, &msg[1], 1);
+ if (ret != 1)
+ return ret;
+ ret = i2c_transfer(state->i2c, &msg[2], 1);
+ if (ret != 1)
return ret;
}
@@ -823,7 +826,7 @@ static int s5h1420_init (struct dvb_frontend* fe)
struct s5h1420_state* state = fe->demodulator_priv;
/* disable power down and do reset */
- state->CON_1_val = 0x10;
+ state->CON_1_val = state->config->serial_mpeg << 4;
s5h1420_writereg(state, 0x02, state->CON_1_val);
msleep(10);
s5h1420_reset(state);
diff --git a/drivers/media/dvb/frontends/s5h1420.h b/drivers/media/dvb/frontends/s5h1420.h
index 4c913f142bc..ff308136d86 100644
--- a/drivers/media/dvb/frontends/s5h1420.h
+++ b/drivers/media/dvb/frontends/s5h1420.h
@@ -32,10 +32,12 @@ struct s5h1420_config
u8 demod_address;
/* does the inversion require inversion? */
- u8 invert : 1;
+ u8 invert:1;
- u8 repeated_start_workaround : 1;
- u8 cdclk_polarity : 1; /* 1 == falling edge, 0 == raising edge */
+ u8 repeated_start_workaround:1;
+ u8 cdclk_polarity:1; /* 1 == falling edge, 0 == raising edge */
+
+ u8 serial_mpeg:1;
};
#if defined(CONFIG_DVB_S5H1420) || (defined(CONFIG_DVB_S5H1420_MODULE) && defined(MODULE))
diff --git a/drivers/media/dvb/siano/sms-cards.c b/drivers/media/dvb/siano/sms-cards.c
index cc5efb643f3..9da260fe3fd 100644
--- a/drivers/media/dvb/siano/sms-cards.c
+++ b/drivers/media/dvb/siano/sms-cards.c
@@ -40,6 +40,8 @@ struct usb_device_id smsusb_id_table[] = {
.driver_info = SMS1XXX_BOARD_HAUPPAUGE_OKEMO_B },
{ USB_DEVICE(0x2040, 0x5500),
.driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM },
+ { USB_DEVICE(0x2040, 0x5510),
+ .driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM },
{ USB_DEVICE(0x2040, 0x5580),
.driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM },
{ USB_DEVICE(0x2040, 0x5590),
@@ -87,7 +89,7 @@ static struct sms_board sms_boards[] = {
.fw[DEVICE_MODE_DVBT_BDA] = "sms1xxx-nova-b-dvbt-01.fw",
},
[SMS1XXX_BOARD_HAUPPAUGE_WINDHAM] = {
- .name = "Hauppauge WinTV-Nova-T-MiniStick",
+ .name = "Hauppauge WinTV MiniStick",
.type = SMS_NOVA_B0,
.fw[DEVICE_MODE_DVBT_BDA] = "sms1xxx-hcw-55xxx-dvbt-01.fw",
},
diff --git a/drivers/media/video/bt8xx/bttv-driver.c b/drivers/media/video/bt8xx/bttv-driver.c
index 6ae4cc860ef..933eaef41ea 100644
--- a/drivers/media/video/bt8xx/bttv-driver.c
+++ b/drivers/media/video/bt8xx/bttv-driver.c
@@ -3431,7 +3431,7 @@ static int radio_open(struct inode *inode, struct file *file)
dprintk("bttv: open minor=%d\n",minor);
for (i = 0; i < bttv_num; i++) {
- if (bttvs[i].radio_dev->minor == minor) {
+ if (bttvs[i].radio_dev && bttvs[i].radio_dev->minor == minor) {
btv = &bttvs[i];
break;
}
diff --git a/drivers/media/video/cafe_ccic.c b/drivers/media/video/cafe_ccic.c
index c149b7d712e..5405c30dbb0 100644
--- a/drivers/media/video/cafe_ccic.c
+++ b/drivers/media/video/cafe_ccic.c
@@ -19,6 +19,7 @@
#include <linux/module.h>
#include <linux/init.h>
#include <linux/fs.h>
+#include <linux/mm.h>
#include <linux/pci.h>
#include <linux/i2c.h>
#include <linux/interrupt.h>
diff --git a/drivers/media/video/cpia2/cpia2_usb.c b/drivers/media/video/cpia2/cpia2_usb.c
index a4574740350..a8a199047cb 100644
--- a/drivers/media/video/cpia2/cpia2_usb.c
+++ b/drivers/media/video/cpia2/cpia2_usb.c
@@ -632,7 +632,7 @@ int cpia2_usb_transfer_cmd(struct camera_data *cam,
static int submit_urbs(struct camera_data *cam)
{
struct urb *urb;
- int fx, err, i;
+ int fx, err, i, j;
for(i=0; i<NUM_SBUF; ++i) {
if (cam->sbuf[i].data)
@@ -657,6 +657,9 @@ static int submit_urbs(struct camera_data *cam)
}
urb = usb_alloc_urb(FRAMES_PER_DESC, GFP_KERNEL);
if (!urb) {
+ ERR("%s: usb_alloc_urb error!\n", __func__);
+ for (j = 0; j < i; j++)
+ usb_free_urb(cam->sbuf[j].urb);
return -ENOMEM;
}
diff --git a/drivers/media/video/cx18/cx18-cards.c b/drivers/media/video/cx18/cx18-cards.c
index 8fe5f38c4d7..3cb9734ec07 100644
--- a/drivers/media/video/cx18/cx18-cards.c
+++ b/drivers/media/video/cx18/cx18-cards.c
@@ -163,7 +163,7 @@ static const struct cx18_card cx18_card_h900 = {
},
.audio_inputs = {
{ CX18_CARD_INPUT_AUD_TUNER,
- CX18_AV_AUDIO8, 0 },
+ CX18_AV_AUDIO5, 0 },
{ CX18_CARD_INPUT_LINE_IN1,
CX18_AV_AUDIO_SERIAL1, 0 },
},
diff --git a/drivers/media/video/em28xx/em28xx-audio.c b/drivers/media/video/em28xx/em28xx-audio.c
index 3c006103c1e..ac3292d7646 100644
--- a/drivers/media/video/em28xx/em28xx-audio.c
+++ b/drivers/media/video/em28xx/em28xx-audio.c
@@ -117,10 +117,10 @@ static void em28xx_audio_isocirq(struct urb *urb)
if (oldptr + length >= runtime->buffer_size) {
unsigned int cnt =
- runtime->buffer_size - oldptr - 1;
+ runtime->buffer_size - oldptr;
memcpy(runtime->dma_area + oldptr * stride, cp,
cnt * stride);
- memcpy(runtime->dma_area, cp + cnt,
+ memcpy(runtime->dma_area, cp + cnt * stride,
length * stride - cnt * stride);
} else {
memcpy(runtime->dma_area + oldptr * stride, cp,
@@ -161,8 +161,14 @@ static int em28xx_init_audio_isoc(struct em28xx *dev)
memset(dev->adev->transfer_buffer[i], 0x80, sb_size);
urb = usb_alloc_urb(EM28XX_NUM_AUDIO_PACKETS, GFP_ATOMIC);
- if (!urb)
+ if (!urb) {
+ em28xx_errdev("usb_alloc_urb failed!\n");
+ for (j = 0; j < i; j++) {
+ usb_free_urb(dev->adev->urb[j]);
+ kfree(dev->adev->transfer_buffer[j]);
+ }
return -ENOMEM;
+ }
urb->dev = dev->udev;
urb->context = dev;
diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c
index 452da70e719..de943cf6c16 100644
--- a/drivers/media/video/em28xx/em28xx-cards.c
+++ b/drivers/media/video/em28xx/em28xx-cards.c
@@ -93,28 +93,6 @@ struct em28xx_board em28xx_boards[] = {
.amux = 0,
} },
},
- [EM2800_BOARD_KWORLD_USB2800] = {
- .name = "Kworld USB2800",
- .valid = EM28XX_BOARD_NOT_VALIDATED,
- .is_em2800 = 1,
- .vchannels = 3,
- .tuner_type = TUNER_PHILIPS_FCV1236D,
- .tda9887_conf = TDA9887_PRESENT,
- .decoder = EM28XX_SAA7113,
- .input = { {
- .type = EM28XX_VMUX_TELEVISION,
- .vmux = SAA7115_COMPOSITE2,
- .amux = 0,
- }, {
- .type = EM28XX_VMUX_COMPOSITE1,
- .vmux = SAA7115_COMPOSITE0,
- .amux = 1,
- }, {
- .type = EM28XX_VMUX_SVIDEO,
- .vmux = SAA7115_SVIDEO3,
- .amux = 1,
- } },
- },
[EM2820_BOARD_KWORLD_PVRTV2800RF] = {
.name = "Kworld PVR TV 2800 RF",
.is_em2800 = 0,
@@ -599,7 +577,7 @@ struct em28xx_board em28xx_boards[] = {
}, {
.type = EM28XX_VMUX_COMPOSITE1,
.vmux = TVP5150_COMPOSITE1,
- .amux = 1,
+ .amux = 3,
}, {
.type = EM28XX_VMUX_SVIDEO,
.vmux = TVP5150_SVIDEO,
@@ -952,22 +930,23 @@ struct em28xx_board em28xx_boards[] = {
},
[EM2880_BOARD_KWORLD_DVB_310U] = {
.name = "KWorld DVB-T 310U",
- .valid = EM28XX_BOARD_NOT_VALIDATED,
.vchannels = 3,
.tuner_type = TUNER_XC2028,
+ .has_dvb = 1,
+ .mts_firmware = 1,
.decoder = EM28XX_TVP5150,
.input = { {
.type = EM28XX_VMUX_TELEVISION,
.vmux = TVP5150_COMPOSITE0,
- .amux = 0,
+ .amux = EM28XX_AMUX_VIDEO,
}, {
.type = EM28XX_VMUX_COMPOSITE1,
.vmux = TVP5150_COMPOSITE1,
- .amux = 1,
- }, {
+ .amux = EM28XX_AMUX_AC97_LINE_IN,
+ }, { /* S-video has not been tested yet */
.type = EM28XX_VMUX_SVIDEO,
.vmux = TVP5150_SVIDEO,
- .amux = 1,
+ .amux = EM28XX_AMUX_AC97_LINE_IN,
} },
},
[EM2881_BOARD_DNT_DA2_HYBRID] = {
@@ -1282,6 +1261,7 @@ static struct em28xx_reg_seq em2882_terratec_hybrid_xs_digital[] = {
static struct em28xx_hash_table em28xx_eeprom_hash [] = {
/* P/N: SA 60002070465 Tuner: TVF7533-MF */
{0x6ce05a8f, EM2820_BOARD_PROLINK_PLAYTV_USB2, TUNER_YMEC_TVF_5533MF},
+ {0x966a0441, EM2880_BOARD_KWORLD_DVB_310U, TUNER_XC2028},
};
/* I2C devicelist hash table for devices with generic USB IDs */
@@ -1552,9 +1532,12 @@ static void em28xx_setup_xc3028(struct em28xx *dev, struct xc2028_ctrl *ctl)
/* djh - Not sure which demod we need here */
ctl->demod = XC3028_FE_DEFAULT;
break;
+ case EM2880_BOARD_AMD_ATI_TV_WONDER_HD_600:
+ ctl->demod = XC3028_FE_DEFAULT;
+ ctl->fname = XC3028L_DEFAULT_FIRMWARE;
+ break;
case EM2883_BOARD_HAUPPAUGE_WINTV_HVR_950:
case EM2880_BOARD_PINNACLE_PCTV_HD_PRO:
- case EM2880_BOARD_AMD_ATI_TV_WONDER_HD_600:
/* FIXME: Better to specify the needed IF */
ctl->demod = XC3028_FE_DEFAULT;
break;
@@ -1764,6 +1747,20 @@ void em28xx_card_setup(struct em28xx *dev)
break;
case EM2820_BOARD_UNKNOWN:
case EM2800_BOARD_UNKNOWN:
+ /*
+ * The K-WORLD DVB-T 310U is detected as an MSI Digivox AD.
+ *
+ * This occurs because they share identical USB vendor and
+ * product IDs.
+ *
+ * What we do here is look up the EEPROM hash of the K-WORLD
+ * and if it is found then we decide that we do not have
+ * a DIGIVOX and reset the device to the K-WORLD instead.
+ *
+ * This solution is only valid if they do not share eeprom
+ * hash identities which has not been determined as yet.
+ */
+ case EM2880_BOARD_MSI_DIGIVOX_AD:
if (!em28xx_hint_board(dev))
em28xx_set_model(dev);
break;
diff --git a/drivers/media/video/em28xx/em28xx-dvb.c b/drivers/media/video/em28xx/em28xx-dvb.c
index 4b992bc0083..d2b1a1a5268 100644
--- a/drivers/media/video/em28xx/em28xx-dvb.c
+++ b/drivers/media/video/em28xx/em28xx-dvb.c
@@ -452,6 +452,15 @@ static int dvb_init(struct em28xx *dev)
goto out_free;
}
break;
+ case EM2880_BOARD_KWORLD_DVB_310U:
+ dvb->frontend = dvb_attach(zl10353_attach,
+ &em28xx_zl10353_with_xc3028,
+ &dev->i2c_adap);
+ if (attach_xc3028(0x61, dev) < 0) {
+ result = -EINVAL;
+ goto out_free;
+ }
+ break;
default:
printk(KERN_ERR "%s/2: The frontend of your DVB/ATSC card"
" isn't supported yet\n",
diff --git a/drivers/media/video/gspca/gspca.c b/drivers/media/video/gspca/gspca.c
index 7be69284da0..ac95c55887d 100644
--- a/drivers/media/video/gspca/gspca.c
+++ b/drivers/media/video/gspca/gspca.c
@@ -459,6 +459,7 @@ static int create_urbs(struct gspca_dev *gspca_dev,
urb = usb_alloc_urb(npkt, GFP_KERNEL);
if (!urb) {
err("usb_alloc_urb failed");
+ destroy_urbs(gspca_dev);
return -ENOMEM;
}
urb->transfer_buffer = usb_buffer_alloc(gspca_dev->dev,
@@ -468,8 +469,8 @@ static int create_urbs(struct gspca_dev *gspca_dev,
if (urb->transfer_buffer == NULL) {
usb_free_urb(urb);
- destroy_urbs(gspca_dev);
err("usb_buffer_urb failed");
+ destroy_urbs(gspca_dev);
return -ENOMEM;
}
gspca_dev->urb[n] = urb;
diff --git a/drivers/media/video/gspca/pac7311.c b/drivers/media/video/gspca/pac7311.c
index d4be5184328..ba865b7f1ed 100644
--- a/drivers/media/video/gspca/pac7311.c
+++ b/drivers/media/video/gspca/pac7311.c
@@ -1063,6 +1063,7 @@ static __devinitdata struct usb_device_id device_table[] = {
{USB_DEVICE(0x093a, 0x2621), .driver_info = SENSOR_PAC7302},
{USB_DEVICE(0x093a, 0x2624), .driver_info = SENSOR_PAC7302},
{USB_DEVICE(0x093a, 0x2626), .driver_info = SENSOR_PAC7302},
+ {USB_DEVICE(0x093a, 0x262a), .driver_info = SENSOR_PAC7302},
{}
};
MODULE_DEVICE_TABLE(usb, device_table);
diff --git a/drivers/media/video/gspca/sonixb.c b/drivers/media/video/gspca/sonixb.c
index 5dd78c6766e..12b81ae526b 100644
--- a/drivers/media/video/gspca/sonixb.c
+++ b/drivers/media/video/gspca/sonixb.c
@@ -232,7 +232,7 @@ static struct ctrl sd_ctrls[] = {
static struct v4l2_pix_format vga_mode[] = {
{160, 120, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
.bytesperline = 160,
- .sizeimage = 160 * 120 * 5 / 4,
+ .sizeimage = 160 * 120,
.colorspace = V4L2_COLORSPACE_SRGB,
.priv = 2 | MODE_RAW},
{160, 120, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
@@ -264,7 +264,7 @@ static struct v4l2_pix_format sif_mode[] = {
.priv = 1 | MODE_REDUCED_SIF},
{176, 144, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
.bytesperline = 176,
- .sizeimage = 176 * 144 * 5 / 4,
+ .sizeimage = 176 * 144,
.colorspace = V4L2_COLORSPACE_SRGB,
.priv = 1 | MODE_RAW},
{176, 144, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
diff --git a/drivers/media/video/gspca/sonixj.c b/drivers/media/video/gspca/sonixj.c
index d75b1d20b31..572b0f363b6 100644
--- a/drivers/media/video/gspca/sonixj.c
+++ b/drivers/media/video/gspca/sonixj.c
@@ -707,6 +707,7 @@ static void i2c_w8(struct gspca_dev *gspca_dev,
0x08, 0, /* value, index */
gspca_dev->usb_buf, 8,
500);
+ msleep(2);
}
/* read 5 bytes in gspca_dev->usb_buf */
@@ -976,13 +977,13 @@ static int sd_init(struct gspca_dev *gspca_dev)
case BRIDGE_SN9C105:
if (regF1 != 0x11)
return -ENODEV;
- reg_w(gspca_dev, 0x02, regGpio, 2);
+ reg_w(gspca_dev, 0x01, regGpio, 2);
break;
case BRIDGE_SN9C120:
if (regF1 != 0x12)
return -ENODEV;
regGpio[1] = 0x70;
- reg_w(gspca_dev, 0x02, regGpio, 2);
+ reg_w(gspca_dev, 0x01, regGpio, 2);
break;
default:
/* case BRIDGE_SN9C110: */
@@ -1183,7 +1184,7 @@ static void sd_start(struct gspca_dev *gspca_dev)
static const __u8 CA[] = { 0x28, 0xd8, 0x14, 0xec };
static const __u8 CE[] = { 0x32, 0xdd, 0x2d, 0xdd }; /* MI0360 */
static const __u8 CE_ov76xx[] =
- { 0x32, 0xdd, 0x32, 0xdd }; /* OV7630/48 */
+ { 0x32, 0xdd, 0x32, 0xdd };
sn9c1xx = sn_tb[(int) sd->sensor];
configure_gpio(gspca_dev, sn9c1xx);
@@ -1223,8 +1224,15 @@ static void sd_start(struct gspca_dev *gspca_dev)
reg_w(gspca_dev, 0x20, gamma_def, sizeof gamma_def);
for (i = 0; i < 8; i++)
reg_w(gspca_dev, 0x84, reg84, sizeof reg84);
+ switch (sd->sensor) {
+ case SENSOR_OV7660:
+ reg_w1(gspca_dev, 0x9a, 0x05);
+ break;
+ default:
reg_w1(gspca_dev, 0x9a, 0x08);
reg_w1(gspca_dev, 0x99, 0x59);
+ break;
+ }
mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
if (mode)
@@ -1275,8 +1283,8 @@ static void sd_start(struct gspca_dev *gspca_dev)
/* reg1 = 0x44; */
/* reg1 = 0x46; (done) */
} else {
- reg17 = 0x22; /* 640 MCKSIZE */
- reg1 = 0x06;
+ reg17 = 0xa2; /* 640 */
+ reg1 = 0x44;
}
break;
}
@@ -1285,6 +1293,7 @@ static void sd_start(struct gspca_dev *gspca_dev)
switch (sd->sensor) {
case SENSOR_OV7630:
case SENSOR_OV7648:
+ case SENSOR_OV7660:
reg_w(gspca_dev, 0xce, CE_ov76xx, 4);
break;
default:
diff --git a/drivers/media/video/gspca/spca561.c b/drivers/media/video/gspca/spca561.c
index cfbc9ebc5c5..95fcfcb9e31 100644
--- a/drivers/media/video/gspca/spca561.c
+++ b/drivers/media/video/gspca/spca561.c
@@ -225,7 +225,7 @@ static int i2c_read(struct gspca_dev *gspca_dev, __u16 reg, __u8 mode)
reg_w_val(gspca_dev->dev, 0x8802, (mode | 0x01));
do {
reg_r(gspca_dev, 0x8803, 1);
- if (!gspca_dev->usb_buf)
+ if (!gspca_dev->usb_buf[0])
break;
} while (--retry);
if (retry == 0)
diff --git a/drivers/media/video/gspca/zc3xx.c b/drivers/media/video/gspca/zc3xx.c
index 8d7c27e6ac7..d61ef727e0c 100644
--- a/drivers/media/video/gspca/zc3xx.c
+++ b/drivers/media/video/gspca/zc3xx.c
@@ -6576,8 +6576,8 @@ static int setlightfreq(struct gspca_dev *gspca_dev)
cs2102_60HZ, cs2102_60HZScale},
/* SENSOR_CS2102K 1 */
{cs2102_NoFliker, cs2102_NoFlikerScale,
- cs2102_50HZ, cs2102_50HZScale,
- cs2102_60HZ, cs2102_60HZScale},
+ NULL, NULL, /* currently disabled */
+ NULL, NULL},
/* SENSOR_GC0305 2 */
{gc0305_NoFliker, gc0305_NoFliker,
gc0305_50HZ, gc0305_50HZ,
diff --git a/drivers/media/video/ov511.c b/drivers/media/video/ov511.c
index 3d3c48db45d..c6852402c5e 100644
--- a/drivers/media/video/ov511.c
+++ b/drivers/media/video/ov511.c
@@ -3591,7 +3591,7 @@ static int
ov51x_init_isoc(struct usb_ov511 *ov)
{
struct urb *urb;
- int fx, err, n, size;
+ int fx, err, n, i, size;
PDEBUG(3, "*** Initializing capture ***");
@@ -3662,6 +3662,8 @@ ov51x_init_isoc(struct usb_ov511 *ov)
urb = usb_alloc_urb(FRAMES_PER_DESC, GFP_KERNEL);
if (!urb) {
err("init isoc: usb_alloc_urb ret. NULL");
+ for (i = 0; i < n; i++)
+ usb_free_urb(ov->sbuf[i].urb);
return -ENOMEM;
}
ov->sbuf[n].urb = urb;
@@ -5651,7 +5653,7 @@ static ssize_t show_exposure(struct device *cd,
if (!ov->dev)
return -ENODEV;
sensor_get_exposure(ov, &exp);
- return sprintf(buf, "%d\n", exp >> 8);
+ return sprintf(buf, "%d\n", exp);
}
static DEVICE_ATTR(exposure, S_IRUGO, show_exposure, NULL);
diff --git a/drivers/media/video/pvrusb2/pvrusb2-devattr.c b/drivers/media/video/pvrusb2/pvrusb2-devattr.c
index 88e17516843..cbe2a341785 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-devattr.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-devattr.c
@@ -489,6 +489,8 @@ static const struct pvr2_device_desc pvr2_device_751xx = {
struct usb_device_id pvr2_device_table[] = {
{ USB_DEVICE(0x2040, 0x2900),
.driver_info = (kernel_ulong_t)&pvr2_device_29xxx},
+ { USB_DEVICE(0x2040, 0x2950), /* Logically identical to 2900 */
+ .driver_info = (kernel_ulong_t)&pvr2_device_29xxx},
{ USB_DEVICE(0x2040, 0x2400),
.driver_info = (kernel_ulong_t)&pvr2_device_24xxx},
{ USB_DEVICE(0x1164, 0x0622),
diff --git a/drivers/media/video/s2255drv.c b/drivers/media/video/s2255drv.c
index b1d09d8e2b8..92b83feae36 100644
--- a/drivers/media/video/s2255drv.c
+++ b/drivers/media/video/s2255drv.c
@@ -669,7 +669,7 @@ static void s2255_fillbuff(struct s2255_dev *dev, struct s2255_buffer *buf,
(unsigned long)vbuf, pos);
/* tell v4l buffer was filled */
- buf->vb.field_count++;
+ buf->vb.field_count = dev->frame_count[chn] * 2;
do_gettimeofday(&ts);
buf->vb.ts = ts;
buf->vb.state = VIDEOBUF_DONE;
@@ -1268,6 +1268,7 @@ static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
dev->last_frame[chn] = -1;
dev->bad_payload[chn] = 0;
dev->cur_frame[chn] = 0;
+ dev->frame_count[chn] = 0;
for (j = 0; j < SYS_FRAMES; j++) {
dev->buffer[chn].frame[j].ulState = 0;
dev->buffer[chn].frame[j].cur_size = 0;
diff --git a/drivers/media/video/uvc/uvc_ctrl.c b/drivers/media/video/uvc/uvc_ctrl.c
index 6ef3e5297de..feab12aa2c7 100644
--- a/drivers/media/video/uvc/uvc_ctrl.c
+++ b/drivers/media/video/uvc/uvc_ctrl.c
@@ -592,7 +592,7 @@ int uvc_query_v4l2_ctrl(struct uvc_video_device *video,
if (ctrl == NULL)
return -EINVAL;
- data = kmalloc(8, GFP_KERNEL);
+ data = kmalloc(ctrl->info->size, GFP_KERNEL);
if (data == NULL)
return -ENOMEM;
diff --git a/drivers/media/video/w9968cf.c b/drivers/media/video/w9968cf.c
index 168baabe465..11edf79f57b 100644
--- a/drivers/media/video/w9968cf.c
+++ b/drivers/media/video/w9968cf.c
@@ -911,7 +911,6 @@ static int w9968cf_start_transfer(struct w9968cf_device* cam)
for (i = 0; i < W9968CF_URBS; i++) {
urb = usb_alloc_urb(W9968CF_ISO_PACKETS, GFP_KERNEL);
- cam->urb[i] = urb;
if (!urb) {
for (j = 0; j < i; j++)
usb_free_urb(cam->urb[j]);
@@ -919,6 +918,7 @@ static int w9968cf_start_transfer(struct w9968cf_device* cam)
return -ENOMEM;
}
+ cam->urb[i] = urb;
urb->dev = udev;
urb->context = (void*)cam;
urb->pipe = usb_rcvisocpipe(udev, 1);
diff --git a/drivers/media/video/wm8739.c b/drivers/media/video/wm8739.c
index 95c79ad8048..54ac3fe26ec 100644
--- a/drivers/media/video/wm8739.c
+++ b/drivers/media/video/wm8739.c
@@ -274,10 +274,8 @@ static int wm8739_probe(struct i2c_client *client,
client->addr << 1, client->adapter->name);
state = kmalloc(sizeof(struct wm8739_state), GFP_KERNEL);
- if (state == NULL) {
- kfree(client);
+ if (state == NULL)
return -ENOMEM;
- }
state->vol_l = 0x17; /* 0dB */
state->vol_r = 0x17; /* 0dB */
state->muted = 0;
diff --git a/drivers/media/video/zoran_card.c b/drivers/media/video/zoran_card.c
index d842a7cb99d..3282be73029 100644
--- a/drivers/media/video/zoran_card.c
+++ b/drivers/media/video/zoran_card.c
@@ -988,7 +988,7 @@ zoran_open_init_params (struct zoran *zr)
zr->v4l_grab_seq = 0;
zr->v4l_settings.width = 192;
zr->v4l_settings.height = 144;
- zr->v4l_settings.format = &zoran_formats[4]; /* YUY2 - YUV-4:2:2 packed */
+ zr->v4l_settings.format = &zoran_formats[7]; /* YUY2 - YUV-4:2:2 packed */
zr->v4l_settings.bytesperline =
zr->v4l_settings.width *
((zr->v4l_settings.format->depth + 7) / 8);
diff --git a/drivers/media/video/zoran_driver.c b/drivers/media/video/zoran_driver.c
index ec6f59674b1..2dab9eea4de 100644
--- a/drivers/media/video/zoran_driver.c
+++ b/drivers/media/video/zoran_driver.c
@@ -134,7 +134,7 @@ const struct zoran_format zoran_formats[] = {
}, {
.name = "16-bit RGB BE",
ZFMT(-1,
- V4L2_PIX_FMT_RGB565, V4L2_COLORSPACE_SRGB),
+ V4L2_PIX_FMT_RGB565X, V4L2_COLORSPACE_SRGB),
.depth = 16,
.flags = ZORAN_FORMAT_CAPTURE |
ZORAN_FORMAT_OVERLAY,
@@ -2737,7 +2737,8 @@ zoran_do_ioctl (struct inode *inode,
fh->v4l_settings.format->fourcc;
fmt->fmt.pix.colorspace =
fh->v4l_settings.format->colorspace;
- fmt->fmt.pix.bytesperline = 0;
+ fmt->fmt.pix.bytesperline =
+ fh->v4l_settings.bytesperline;
if (BUZ_MAX_HEIGHT <
(fh->v4l_settings.height * 2))
fmt->fmt.pix.field =
@@ -2833,13 +2834,6 @@ zoran_do_ioctl (struct inode *inode,
fmt->fmt.pix.pixelformat,
(char *) &printformat);
- if (fmt->fmt.pix.bytesperline > 0) {
- dprintk(5,
- KERN_ERR "%s: bpl not supported\n",
- ZR_DEVNAME(zr));
- return -EINVAL;
- }
-
/* we can be requested to do JPEG/raw playback/capture */
if (!
(fmt->type == V4L2_BUF_TYPE_VIDEO_CAPTURE ||
@@ -2923,6 +2917,7 @@ zoran_do_ioctl (struct inode *inode,
fh->jpg_buffers.buffer_size =
zoran_v4l2_calc_bufsize(&fh->
jpg_settings);
+ fmt->fmt.pix.bytesperline = 0;
fmt->fmt.pix.sizeimage =
fh->jpg_buffers.buffer_size;
@@ -2979,6 +2974,8 @@ zoran_do_ioctl (struct inode *inode,
/* tell the user the
* results/missing stuff */
+ fmt->fmt.pix.bytesperline =
+ fh->v4l_settings.bytesperline;
fmt->fmt.pix.sizeimage =
fh->v4l_settings.height *
fh->v4l_settings.bytesperline;
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 10c44d3fe01..68dc8d9eb24 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -21,7 +21,7 @@ config MFD_SM501
config MFD_SM501_GPIO
bool "Export GPIO via GPIO layer"
- depends on MFD_SM501 && HAVE_GPIO_LIB
+ depends on MFD_SM501 && GPIOLIB
---help---
This option uses the gpio library layer to export the 64 GPIO
lines on the SM501. The platform data is used to supply the
@@ -29,7 +29,7 @@ config MFD_SM501_GPIO
config MFD_ASIC3
bool "Support for Compaq ASIC3"
- depends on GENERIC_HARDIRQS && HAVE_GPIO_LIB && ARM
+ depends on GENERIC_HARDIRQS && GPIOLIB && ARM
---help---
This driver supports the ASIC3 multifunction chip found on many
PDAs (mainly iPAQ and HTC based ones)
diff --git a/drivers/mfd/asic3.c b/drivers/mfd/asic3.c
index bc2a807f210..ba5aa200827 100644
--- a/drivers/mfd/asic3.c
+++ b/drivers/mfd/asic3.c
@@ -312,7 +312,6 @@ static int __init asic3_irq_probe(struct platform_device *pdev)
struct asic3 *asic = platform_get_drvdata(pdev);
unsigned long clksel = 0;
unsigned int irq, irq_base;
- int map_size;
int ret;
ret = platform_get_irq(pdev, 0);
@@ -534,6 +533,7 @@ static int __init asic3_probe(struct platform_device *pdev)
struct asic3 *asic;
struct resource *mem;
unsigned long clksel;
+ int map_size;
int ret = 0;
asic = kzalloc(sizeof(struct asic3), GFP_KERNEL);
diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c
index 917035e16da..00008967ef7 100644
--- a/drivers/mmc/host/atmel-mci.c
+++ b/drivers/mmc/host/atmel-mci.c
@@ -426,8 +426,6 @@ static u32 atmci_submit_data(struct mmc_host *mmc, struct mmc_data *data)
host->sg = NULL;
host->data = data;
- mci_writel(host, BLKR, MCI_BCNT(data->blocks)
- | MCI_BLKLEN(data->blksz));
dev_vdbg(&mmc->class_dev, "BLKR=0x%08x\n",
MCI_BCNT(data->blocks) | MCI_BLKLEN(data->blksz));
@@ -483,6 +481,10 @@ static void atmci_request(struct mmc_host *mmc, struct mmc_request *mrq)
if (data->blocks > 1 && data->blksz & 3)
goto fail;
atmci_set_timeout(host, data);
+
+ /* Must set block count/size before sending command */
+ mci_writel(host, BLKR, MCI_BCNT(data->blocks)
+ | MCI_BLKLEN(data->blksz));
}
iflags = MCI_CMDRDY;
diff --git a/drivers/net/e1000e/e1000.h b/drivers/net/e1000e/e1000.h
index 0a1916b0419..c55de1c027a 100644
--- a/drivers/net/e1000e/e1000.h
+++ b/drivers/net/e1000e/e1000.h
@@ -270,7 +270,6 @@ struct e1000_adapter {
struct net_device *netdev;
struct pci_dev *pdev;
struct net_device_stats net_stats;
- spinlock_t stats_lock; /* prevent concurrent stats updates */
/* structs defined in e1000_hw.h */
struct e1000_hw hw;
@@ -300,6 +299,8 @@ struct e1000_adapter {
unsigned long led_status;
unsigned int flags;
+ struct work_struct downshift_task;
+ struct work_struct update_phy_task;
};
struct e1000_info {
@@ -321,6 +322,7 @@ struct e1000_info {
#define FLAG_HAS_CTRLEXT_ON_LOAD (1 << 5)
#define FLAG_HAS_SWSM_ON_LOAD (1 << 6)
#define FLAG_HAS_JUMBO_FRAMES (1 << 7)
+#define FLAG_READ_ONLY_NVM (1 << 8)
#define FLAG_IS_ICH (1 << 9)
#define FLAG_HAS_MSIX (1 << 10)
#define FLAG_HAS_SMART_POWER_DOWN (1 << 11)
@@ -406,6 +408,7 @@ extern bool e1000e_enable_mng_pass_thru(struct e1000_hw *hw);
extern bool e1000e_get_laa_state_82571(struct e1000_hw *hw);
extern void e1000e_set_laa_state_82571(struct e1000_hw *hw, bool state);
+extern void e1000e_write_protect_nvm_ich8lan(struct e1000_hw *hw);
extern void e1000e_set_kmrn_lock_loss_workaround_ich8lan(struct e1000_hw *hw,
bool state);
extern void e1000e_igp3_phy_powerdown_workaround_ich8lan(struct e1000_hw *hw);
diff --git a/drivers/net/e1000e/ethtool.c b/drivers/net/e1000e/ethtool.c
index 52b762eb174..70c11c811a0 100644
--- a/drivers/net/e1000e/ethtool.c
+++ b/drivers/net/e1000e/ethtool.c
@@ -432,6 +432,10 @@ static void e1000_get_regs(struct net_device *netdev,
regs_buff[11] = er32(TIDV);
regs_buff[12] = adapter->hw.phy.type; /* PHY type (IGP=1, M88=0) */
+
+ /* ethtool doesn't use anything past this point, so all this
+ * code is likely legacy junk for apps that may or may not
+ * exist */
if (hw->phy.type == e1000_phy_m88) {
e1e_rphy(hw, M88E1000_PHY_SPEC_STATUS, &phy_data);
regs_buff[13] = (u32)phy_data; /* cable length */
@@ -447,7 +451,7 @@ static void e1000_get_regs(struct net_device *netdev,
regs_buff[22] = adapter->phy_stats.receive_errors;
regs_buff[23] = regs_buff[13]; /* mdix mode */
}
- regs_buff[21] = adapter->phy_stats.idle_errors; /* phy idle errors */
+ regs_buff[21] = 0; /* was idle_errors */
e1e_rphy(hw, PHY_1000T_STATUS, &phy_data);
regs_buff[24] = (u32)phy_data; /* phy local receiver status */
regs_buff[25] = regs_buff[24]; /* phy remote receiver status */
@@ -529,6 +533,9 @@ static int e1000_set_eeprom(struct net_device *netdev,
if (eeprom->magic != (adapter->pdev->vendor | (adapter->pdev->device << 16)))
return -EFAULT;
+ if (adapter->flags & FLAG_READ_ONLY_NVM)
+ return -EINVAL;
+
max_len = hw->nvm.word_size * 2;
first_word = eeprom->offset >> 1;
diff --git a/drivers/net/e1000e/ich8lan.c b/drivers/net/e1000e/ich8lan.c
index 692251b6091..523b9716a54 100644
--- a/drivers/net/e1000e/ich8lan.c
+++ b/drivers/net/e1000e/ich8lan.c
@@ -60,6 +60,7 @@
#define ICH_FLASH_HSFCTL 0x0006
#define ICH_FLASH_FADDR 0x0008
#define ICH_FLASH_FDATA0 0x0010
+#define ICH_FLASH_PR0 0x0074
#define ICH_FLASH_READ_COMMAND_TIMEOUT 500
#define ICH_FLASH_WRITE_COMMAND_TIMEOUT 500
@@ -152,6 +153,19 @@ union ich8_hws_flash_regacc {
u16 regval;
};
+/* ICH Flash Protected Region */
+union ich8_flash_protected_range {
+ struct ich8_pr {
+ u32 base:13; /* 0:12 Protected Range Base */
+ u32 reserved1:2; /* 13:14 Reserved */
+ u32 rpe:1; /* 15 Read Protection Enable */
+ u32 limit:13; /* 16:28 Protected Range Limit */
+ u32 reserved2:2; /* 29:30 Reserved */
+ u32 wpe:1; /* 31 Write Protection Enable */
+ } range;
+ u32 regval;
+};
+
static s32 e1000_setup_link_ich8lan(struct e1000_hw *hw);
static void e1000_clear_hw_cntrs_ich8lan(struct e1000_hw *hw);
static void e1000_initialize_hw_bits_ich8lan(struct e1000_hw *hw);
@@ -371,6 +385,9 @@ static s32 e1000_get_variants_ich8lan(struct e1000_adapter *adapter)
return 0;
}
+static DEFINE_MUTEX(nvm_mutex);
+static pid_t nvm_owner = -1;
+
/**
* e1000_acquire_swflag_ich8lan - Acquire software control flag
* @hw: pointer to the HW structure
@@ -384,6 +401,15 @@ static s32 e1000_acquire_swflag_ich8lan(struct e1000_hw *hw)
u32 extcnf_ctrl;
u32 timeout = PHY_CFG_TIMEOUT;
+ might_sleep();
+
+ if (!mutex_trylock(&nvm_mutex)) {
+ WARN(1, KERN_ERR "e1000e mutex contention. Owned by pid %d\n",
+ nvm_owner);
+ mutex_lock(&nvm_mutex);
+ }
+ nvm_owner = current->pid;
+
while (timeout) {
extcnf_ctrl = er32(EXTCNF_CTRL);
extcnf_ctrl |= E1000_EXTCNF_CTRL_SWFLAG;
@@ -400,6 +426,8 @@ static s32 e1000_acquire_swflag_ich8lan(struct e1000_hw *hw)
hw_dbg(hw, "FW or HW has locked the resource for too long.\n");
extcnf_ctrl &= ~E1000_EXTCNF_CTRL_SWFLAG;
ew32(EXTCNF_CTRL, extcnf_ctrl);
+ nvm_owner = -1;
+ mutex_unlock(&nvm_mutex);
return -E1000_ERR_CONFIG;
}
@@ -421,6 +449,9 @@ static void e1000_release_swflag_ich8lan(struct e1000_hw *hw)
extcnf_ctrl = er32(EXTCNF_CTRL);
extcnf_ctrl &= ~E1000_EXTCNF_CTRL_SWFLAG;
ew32(EXTCNF_CTRL, extcnf_ctrl);
+
+ nvm_owner = -1;
+ mutex_unlock(&nvm_mutex);
}
/**
@@ -1386,6 +1417,7 @@ static s32 e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw)
* programming failed.
*/
if (ret_val) {
+ /* Possibly read-only, see e1000e_write_protect_nvm_ich8lan() */
hw_dbg(hw, "Flash commit failed.\n");
e1000_release_swflag_ich8lan(hw);
return ret_val;
@@ -1476,6 +1508,49 @@ static s32 e1000_validate_nvm_checksum_ich8lan(struct e1000_hw *hw)
}
/**
+ * e1000e_write_protect_nvm_ich8lan - Make the NVM read-only
+ * @hw: pointer to the HW structure
+ *
+ * To prevent malicious write/erase of the NVM, set it to be read-only
+ * so that the hardware ignores all write/erase cycles of the NVM via
+ * the flash control registers. The shadow-ram copy of the NVM will
+ * still be updated, however any updates to this copy will not stick
+ * across driver reloads.
+ **/
+void e1000e_write_protect_nvm_ich8lan(struct e1000_hw *hw)
+{
+ union ich8_flash_protected_range pr0;
+ union ich8_hws_flash_status hsfsts;
+ u32 gfpreg;
+ s32 ret_val;
+
+ ret_val = e1000_acquire_swflag_ich8lan(hw);
+ if (ret_val)
+ return;
+
+ gfpreg = er32flash(ICH_FLASH_GFPREG);
+
+ /* Write-protect GbE Sector of NVM */
+ pr0.regval = er32flash(ICH_FLASH_PR0);
+ pr0.range.base = gfpreg & FLASH_GFPREG_BASE_MASK;
+ pr0.range.limit = ((gfpreg >> 16) & FLASH_GFPREG_BASE_MASK);
+ pr0.range.wpe = true;
+ ew32flash(ICH_FLASH_PR0, pr0.regval);
+
+ /*
+ * Lock down a subset of GbE Flash Control Registers, e.g.
+ * PR0 to prevent the write-protection from being lifted.
+ * Once FLOCKDN is set, the registers protected by it cannot
+ * be written until FLOCKDN is cleared by a hardware reset.
+ */
+ hsfsts.regval = er16flash(ICH_FLASH_HSFSTS);
+ hsfsts.hsf_status.flockdn = true;
+ ew32flash(ICH_FLASH_HSFSTS, hsfsts.regval);
+
+ e1000_release_swflag_ich8lan(hw);
+}
+
+/**
* e1000_write_flash_data_ich8lan - Writes bytes to the NVM
* @hw: pointer to the HW structure
* @offset: The offset (in bytes) of the byte/word to read.
@@ -1822,6 +1897,9 @@ static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw)
ew32(CTRL, (ctrl | E1000_CTRL_RST));
msleep(20);
+ /* release the swflag because it is not reset by hardware reset */
+ e1000_release_swflag_ich8lan(hw);
+
ret_val = e1000e_get_auto_rd_done(hw);
if (ret_val) {
/*
diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c
index 24d05cb7005..1b72749979c 100644
--- a/drivers/net/e1000e/netdev.c
+++ b/drivers/net/e1000e/netdev.c
@@ -47,7 +47,7 @@
#include "e1000.h"
-#define DRV_VERSION "0.3.3.3-k2"
+#define DRV_VERSION "0.3.3.3-k6"
char e1000e_driver_name[] = "e1000e";
const char e1000e_driver_version[] = DRV_VERSION;
@@ -1117,6 +1117,14 @@ static void e1000_clean_rx_ring(struct e1000_adapter *adapter)
writel(0, adapter->hw.hw_addr + rx_ring->tail);
}
+static void e1000e_downshift_workaround(struct work_struct *work)
+{
+ struct e1000_adapter *adapter = container_of(work,
+ struct e1000_adapter, downshift_task);
+
+ e1000e_gig_downshift_workaround_ich8lan(&adapter->hw);
+}
+
/**
* e1000_intr_msi - Interrupt Handler
* @irq: interrupt number
@@ -1141,7 +1149,7 @@ static irqreturn_t e1000_intr_msi(int irq, void *data)
*/
if ((adapter->flags & FLAG_LSC_GIG_SPEED_DROP) &&
(!(er32(STATUS) & E1000_STATUS_LU)))
- e1000e_gig_downshift_workaround_ich8lan(hw);
+ schedule_work(&adapter->downshift_task);
/*
* 80003ES2LAN workaround-- For packet buffer work-around on
@@ -1207,7 +1215,7 @@ static irqreturn_t e1000_intr(int irq, void *data)
*/
if ((adapter->flags & FLAG_LSC_GIG_SPEED_DROP) &&
(!(er32(STATUS) & E1000_STATUS_LU)))
- e1000e_gig_downshift_workaround_ich8lan(hw);
+ schedule_work(&adapter->downshift_task);
/*
* 80003ES2LAN workaround--
@@ -2905,8 +2913,6 @@ static int __devinit e1000_sw_init(struct e1000_adapter *adapter)
/* Explicitly disable IRQ since the NIC can be in any state. */
e1000_irq_disable(adapter);
- spin_lock_init(&adapter->stats_lock);
-
set_bit(__E1000_DOWN, &adapter->state);
return 0;
}
@@ -3221,6 +3227,21 @@ static int e1000_set_mac(struct net_device *netdev, void *p)
return 0;
}
+/**
+ * e1000e_update_phy_task - work thread to update phy
+ * @work: pointer to our work struct
+ *
+ * this worker thread exists because we must acquire a
+ * semaphore to read the phy, which we could msleep while
+ * waiting for it, and we can't msleep in a timer.
+ **/
+static void e1000e_update_phy_task(struct work_struct *work)
+{
+ struct e1000_adapter *adapter = container_of(work,
+ struct e1000_adapter, update_phy_task);
+ e1000_get_phy_info(&adapter->hw);
+}
+
/*
* Need to wait a few seconds after link up to get diagnostic information from
* the phy
@@ -3228,7 +3249,7 @@ static int e1000_set_mac(struct net_device *netdev, void *p)
static void e1000_update_phy_info(unsigned long data)
{
struct e1000_adapter *adapter = (struct e1000_adapter *) data;
- e1000_get_phy_info(&adapter->hw);
+ schedule_work(&adapter->update_phy_task);
}
/**
@@ -3239,10 +3260,6 @@ void e1000e_update_stats(struct e1000_adapter *adapter)
{
struct e1000_hw *hw = &adapter->hw;
struct pci_dev *pdev = adapter->pdev;
- unsigned long irq_flags;
- u16 phy_tmp;
-
-#define PHY_IDLE_ERROR_COUNT_MASK 0x00FF
/*
* Prevent stats update while adapter is being reset, or if the pci
@@ -3253,14 +3270,6 @@ void e1000e_update_stats(struct e1000_adapter *adapter)
if (pci_channel_offline(pdev))
return;
- spin_lock_irqsave(&adapter->stats_lock, irq_flags);
-
- /*
- * these counters are modified from e1000_adjust_tbi_stats,
- * called from the interrupt context, so they must only
- * be written while holding adapter->stats_lock
- */
-
adapter->stats.crcerrs += er32(CRCERRS);
adapter->stats.gprc += er32(GPRC);
adapter->stats.gorc += er32(GORCL);
@@ -3332,21 +3341,10 @@ void e1000e_update_stats(struct e1000_adapter *adapter)
/* Tx Dropped needs to be maintained elsewhere */
- /* Phy Stats */
- if (hw->phy.media_type == e1000_media_type_copper) {
- if ((adapter->link_speed == SPEED_1000) &&
- (!e1e_rphy(hw, PHY_1000T_STATUS, &phy_tmp))) {
- phy_tmp &= PHY_IDLE_ERROR_COUNT_MASK;
- adapter->phy_stats.idle_errors += phy_tmp;
- }
- }
-
/* Management Stats */
adapter->stats.mgptc += er32(MGTPTC);
adapter->stats.mgprc += er32(MGTPRC);
adapter->stats.mgpdc += er32(MGTPDC);
-
- spin_unlock_irqrestore(&adapter->stats_lock, irq_flags);
}
/**
@@ -3358,10 +3356,6 @@ static void e1000_phy_read_status(struct e1000_adapter *adapter)
struct e1000_hw *hw = &adapter->hw;
struct e1000_phy_regs *phy = &adapter->phy_regs;
int ret_val;
- unsigned long irq_flags;
-
-
- spin_lock_irqsave(&adapter->stats_lock, irq_flags);
if ((er32(STATUS) & E1000_STATUS_LU) &&
(adapter->hw.phy.media_type == e1000_media_type_copper)) {
@@ -3392,8 +3386,6 @@ static void e1000_phy_read_status(struct e1000_adapter *adapter)
phy->stat1000 = 0;
phy->estatus = (ESTATUS_1000_TFULL | ESTATUS_1000_THALF);
}
-
- spin_unlock_irqrestore(&adapter->stats_lock, irq_flags);
}
static void e1000_print_link_info(struct e1000_adapter *adapter)
@@ -4822,6 +4814,10 @@ static int __devinit e1000_probe(struct pci_dev *pdev,
if (err)
goto err_hw_init;
+ if ((adapter->flags & FLAG_IS_ICH) &&
+ (adapter->flags & FLAG_READ_ONLY_NVM))
+ e1000e_write_protect_nvm_ich8lan(&adapter->hw);
+
hw->mac.ops.get_bus_info(&adapter->hw);
adapter->hw.phy.autoneg_wait_to_complete = 0;
@@ -4912,6 +4908,8 @@ static int __devinit e1000_probe(struct pci_dev *pdev,
INIT_WORK(&adapter->reset_task, e1000_reset_task);
INIT_WORK(&adapter->watchdog_task, e1000_watchdog_task);
+ INIT_WORK(&adapter->downshift_task, e1000e_downshift_workaround);
+ INIT_WORK(&adapter->update_phy_task, e1000e_update_phy_task);
/* Initialize link parameters. User can change them with ethtool */
adapter->hw.mac.autoneg = 1;
diff --git a/drivers/net/e1000e/param.c b/drivers/net/e1000e/param.c
index f46db6cda48..77a3d7207a5 100644
--- a/drivers/net/e1000e/param.c
+++ b/drivers/net/e1000e/param.c
@@ -142,6 +142,15 @@ E1000_PARAM(SmartPowerDownEnable, "Enable PHY smart power down");
*/
E1000_PARAM(KumeranLockLoss, "Enable Kumeran lock loss workaround");
+/*
+ * Write Protect NVM
+ *
+ * Valid Range: 0, 1
+ *
+ * Default Value: 1 (enabled)
+ */
+E1000_PARAM(WriteProtectNVM, "Write-protect NVM [WARNING: disabling this can lead to corrupted NVM]");
+
struct e1000_option {
enum { enable_option, range_option, list_option } type;
const char *name;
@@ -415,4 +424,25 @@ void __devinit e1000e_check_options(struct e1000_adapter *adapter)
opt.def);
}
}
+ { /* Write-protect NVM */
+ const struct e1000_option opt = {
+ .type = enable_option,
+ .name = "Write-protect NVM",
+ .err = "defaulting to Enabled",
+ .def = OPTION_ENABLED
+ };
+
+ if (adapter->flags & FLAG_IS_ICH) {
+ if (num_WriteProtectNVM > bd) {
+ unsigned int write_protect_nvm = WriteProtectNVM[bd];
+ e1000_validate_option(&write_protect_nvm, &opt,
+ adapter);
+ if (write_protect_nvm)
+ adapter->flags |= FLAG_READ_ONLY_NVM;
+ } else {
+ if (opt.def)
+ adapter->flags |= FLAG_READ_ONLY_NVM;
+ }
+ }
+ }
}
diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c
index 9c718583a23..77baff022f7 100644
--- a/drivers/pci/pci-sysfs.c
+++ b/drivers/pci/pci-sysfs.c
@@ -16,6 +16,7 @@
#include <linux/kernel.h>
+#include <linux/sched.h>
#include <linux/pci.h>
#include <linux/stat.h>
#include <linux/topology.h>
@@ -484,6 +485,21 @@ pci_mmap_legacy_mem(struct kobject *kobj, struct bin_attribute *attr,
#endif /* HAVE_PCI_LEGACY */
#ifdef HAVE_PCI_MMAP
+
+static int pci_mmap_fits(struct pci_dev *pdev, int resno, struct vm_area_struct *vma)
+{
+ unsigned long nr, start, size;
+
+ nr = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT;
+ start = vma->vm_pgoff;
+ size = pci_resource_len(pdev, resno) >> PAGE_SHIFT;
+ if (start < size && size - start >= nr)
+ return 1;
+ WARN(1, "process \"%s\" tried to map 0x%08lx-0x%08lx on %s BAR %d (size 0x%08lx)\n",
+ current->comm, start, start+nr, pci_name(pdev), resno, size);
+ return 0;
+}
+
/**
* pci_mmap_resource - map a PCI resource into user memory space
* @kobj: kobject for mapping
@@ -510,6 +526,9 @@ pci_mmap_resource(struct kobject *kobj, struct bin_attribute *attr,
if (i >= PCI_ROM_RESOURCE)
return -ENODEV;
+ if (!pci_mmap_fits(pdev, i, vma))
+ return -EINVAL;
+
/* pci_mmap_page_range() expects the same kind of entry as coming
* from /proc/bus/pci/ which is a "user visible" value. If this is
* different from the resource itself, arch will do necessary fixup.
diff --git a/drivers/rtc/rtc-dev.c b/drivers/rtc/rtc-dev.c
index f118252f3a9..52e2743b04e 100644
--- a/drivers/rtc/rtc-dev.c
+++ b/drivers/rtc/rtc-dev.c
@@ -422,6 +422,12 @@ done:
return err;
}
+static int rtc_dev_fasync(int fd, struct file *file, int on)
+{
+ struct rtc_device *rtc = file->private_data;
+ return fasync_helper(fd, file, on, &rtc->async_queue);
+}
+
static int rtc_dev_release(struct inode *inode, struct file *file)
{
struct rtc_device *rtc = file->private_data;
@@ -434,16 +440,13 @@ static int rtc_dev_release(struct inode *inode, struct file *file)
if (rtc->ops->release)
rtc->ops->release(rtc->dev.parent);
+ if (file->f_flags & FASYNC)
+ rtc_dev_fasync(-1, file, 0);
+
clear_bit_unlock(RTC_DEV_BUSY, &rtc->flags);
return 0;
}
-static int rtc_dev_fasync(int fd, struct file *file, int on)
-{
- struct rtc_device *rtc = file->private_data;
- return fasync_helper(fd, file, on, &rtc->async_queue);
-}
-
static const struct file_operations rtc_dev_fops = {
.owner = THIS_MODULE,
.llseek = no_llseek,
diff --git a/drivers/s390/cio/qdio_setup.c b/drivers/s390/cio/qdio_setup.c
index 1679e2f91c9..a0b6b46e746 100644
--- a/drivers/s390/cio/qdio_setup.c
+++ b/drivers/s390/cio/qdio_setup.c
@@ -447,51 +447,36 @@ void qdio_print_subchannel_info(struct qdio_irq *irq_ptr,
{
char s[80];
- sprintf(s, "%s sc:%x ", cdev->dev.bus_id, irq_ptr->schid.sch_no);
-
+ sprintf(s, "qdio: %s ", dev_name(&cdev->dev));
switch (irq_ptr->qib.qfmt) {
case QDIO_QETH_QFMT:
- sprintf(s + strlen(s), "OSADE ");
+ sprintf(s + strlen(s), "OSA ");
break;
case QDIO_ZFCP_QFMT:
sprintf(s + strlen(s), "ZFCP ");
break;
case QDIO_IQDIO_QFMT:
- sprintf(s + strlen(s), "HiperSockets ");
+ sprintf(s + strlen(s), "HS ");
break;
}
- sprintf(s + strlen(s), "using: ");
-
- if (!is_thinint_irq(irq_ptr))
- sprintf(s + strlen(s), "no");
- sprintf(s + strlen(s), "AdapterInterrupts ");
- if (!(irq_ptr->sch_token != 0))
- sprintf(s + strlen(s), "no");
- sprintf(s + strlen(s), "QEBSM ");
- if (!(irq_ptr->qib.ac & QIB_AC_OUTBOUND_PCI_SUPPORTED))
- sprintf(s + strlen(s), "no");
- sprintf(s + strlen(s), "OutboundPCI ");
- if (!css_general_characteristics.aif_tdd)
- sprintf(s + strlen(s), "no");
- sprintf(s + strlen(s), "TDD\n");
- printk(KERN_INFO "qdio: %s", s);
-
- memset(s, 0, sizeof(s));
- sprintf(s, "%s SIGA required: ", cdev->dev.bus_id);
- if (irq_ptr->siga_flag.input)
- sprintf(s + strlen(s), "Read ");
- if (irq_ptr->siga_flag.output)
- sprintf(s + strlen(s), "Write ");
- if (irq_ptr->siga_flag.sync)
- sprintf(s + strlen(s), "Sync ");
- if (!irq_ptr->siga_flag.no_sync_ti)
- sprintf(s + strlen(s), "SyncAI ");
- if (!irq_ptr->siga_flag.no_sync_out_ti)
- sprintf(s + strlen(s), "SyncOutAI ");
- if (!irq_ptr->siga_flag.no_sync_out_pci)
- sprintf(s + strlen(s), "SyncOutPCI");
+ sprintf(s + strlen(s), "on SC %x using ", irq_ptr->schid.sch_no);
+ sprintf(s + strlen(s), "AI:%d ", is_thinint_irq(irq_ptr));
+ sprintf(s + strlen(s), "QEBSM:%d ", (irq_ptr->sch_token) ? 1 : 0);
+ sprintf(s + strlen(s), "PCI:%d ",
+ (irq_ptr->qib.ac & QIB_AC_OUTBOUND_PCI_SUPPORTED) ? 1 : 0);
+ sprintf(s + strlen(s), "TDD:%d ", css_general_characteristics.aif_tdd);
+ sprintf(s + strlen(s), "SIGA:");
+ sprintf(s + strlen(s), "%s", (irq_ptr->siga_flag.input) ? "R" : " ");
+ sprintf(s + strlen(s), "%s", (irq_ptr->siga_flag.output) ? "W" : " ");
+ sprintf(s + strlen(s), "%s", (irq_ptr->siga_flag.sync) ? "S" : " ");
+ sprintf(s + strlen(s), "%s",
+ (!irq_ptr->siga_flag.no_sync_ti) ? "A" : " ");
+ sprintf(s + strlen(s), "%s",
+ (!irq_ptr->siga_flag.no_sync_out_ti) ? "O" : " ");
+ sprintf(s + strlen(s), "%s",
+ (!irq_ptr->siga_flag.no_sync_out_pci) ? "P" : " ");
sprintf(s + strlen(s), "\n");
- printk(KERN_INFO "qdio: %s", s);
+ printk(KERN_INFO "%s", s);
}
int __init qdio_setup_init(void)
diff --git a/drivers/spi/orion_spi.c b/drivers/spi/orion_spi.c
index c4eaacd6e55..b872bfaf4bd 100644
--- a/drivers/spi/orion_spi.c
+++ b/drivers/spi/orion_spi.c
@@ -427,7 +427,7 @@ static int orion_spi_transfer(struct spi_device *spi, struct spi_message *m)
goto msg_rejected;
}
- if (t->speed_hz < orion_spi->min_speed) {
+ if (t->speed_hz && t->speed_hz < orion_spi->min_speed) {
dev_err(&spi->dev,
"message rejected : "
"device min speed (%d Hz) exceeds "
diff --git a/drivers/spi/pxa2xx_spi.c b/drivers/spi/pxa2xx_spi.c
index 0e53354c1cf..d47d3636227 100644
--- a/drivers/spi/pxa2xx_spi.c
+++ b/drivers/spi/pxa2xx_spi.c
@@ -49,7 +49,7 @@ MODULE_ALIAS("platform:pxa2xx-spi");
#define DMA_INT_MASK (DCSR_ENDINTR | DCSR_STARTINTR | DCSR_BUSERR)
#define RESET_DMA_CHANNEL (DCSR_NODESC | DMA_INT_MASK)
-#define IS_DMA_ALIGNED(x) (((x) & 0x07) == 0)
+#define IS_DMA_ALIGNED(x) ((((u32)(x)) & 0x07) == 0)
#define MAX_DMA_LEN 8191
/*
@@ -896,7 +896,7 @@ static void pump_transfers(unsigned long data)
|| transfer->rx_dma || transfer->tx_dma) {
dev_err(&drv_data->pdev->dev,
"pump_transfers: mapped transfer length "
- "of %lu is greater than %d\n",
+ "of %u is greater than %d\n",
transfer->len, MAX_DMA_LEN);
message->status = -EINVAL;
giveback(drv_data);
diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c
index c6299e8a041..9cbff84b787 100644
--- a/drivers/video/console/fbcon.c
+++ b/drivers/video/console/fbcon.c
@@ -2400,11 +2400,15 @@ static int fbcon_blank(struct vc_data *vc, int blank, int mode_switch)
if (!fbcon_is_inactive(vc, info)) {
if (ops->blank_state != blank) {
+ int ret = 1;
+
ops->blank_state = blank;
fbcon_cursor(vc, blank ? CM_ERASE : CM_DRAW);
ops->cursor_flash = (!blank);
- if (fb_blank(info, blank))
+ if (info->fbops->fb_blank)
+ ret = info->fbops->fb_blank(blank, info);
+ if (ret)
fbcon_generic_blank(vc, info, blank);
}
diff --git a/drivers/video/console/fbcon.h b/drivers/video/console/fbcon.h
index a6e38e9ea73..89a346880ec 100644
--- a/drivers/video/console/fbcon.h
+++ b/drivers/video/console/fbcon.h
@@ -110,7 +110,7 @@ static inline int mono_col(const struct fb_info *info)
__u32 max_len;
max_len = max(info->var.green.length, info->var.red.length);
max_len = max(info->var.blue.length, max_len);
- return ~(0xfff << (max_len & 0xff));
+ return (~(0xfff << max_len)) & 0xff;
}
static inline int attr_col_ec(int shift, struct vc_data *vc,
diff --git a/fs/inotify_user.c b/fs/inotify_user.c
index 60249429a25..d85c7d931cd 100644
--- a/fs/inotify_user.c
+++ b/fs/inotify_user.c
@@ -323,7 +323,7 @@ out:
}
/*
- * remove_kevent - cleans up and ultimately frees the given kevent
+ * remove_kevent - cleans up the given kevent
*
* Caller must hold dev->ev_mutex.
*/
@@ -334,7 +334,13 @@ static void remove_kevent(struct inotify_device *dev,
dev->event_count--;
dev->queue_size -= sizeof(struct inotify_event) + kevent->event.len;
+}
+/*
+ * free_kevent - frees the given kevent.
+ */
+static void free_kevent(struct inotify_kernel_event *kevent)
+{
kfree(kevent->name);
kmem_cache_free(event_cachep, kevent);
}
@@ -350,6 +356,7 @@ static void inotify_dev_event_dequeue(struct inotify_device *dev)
struct inotify_kernel_event *kevent;
kevent = inotify_dev_get_event(dev);
remove_kevent(dev, kevent);
+ free_kevent(kevent);
}
}
@@ -433,17 +440,15 @@ static ssize_t inotify_read(struct file *file, char __user *buf,
dev = file->private_data;
while (1) {
- int events;
prepare_to_wait(&dev->wq, &wait, TASK_INTERRUPTIBLE);
mutex_lock(&dev->ev_mutex);
- events = !list_empty(&dev->events);
- mutex_unlock(&dev->ev_mutex);
- if (events) {
+ if (!list_empty(&dev->events)) {
ret = 0;
break;
}
+ mutex_unlock(&dev->ev_mutex);
if (file->f_flags & O_NONBLOCK) {
ret = -EAGAIN;
@@ -462,7 +467,6 @@ static ssize_t inotify_read(struct file *file, char __user *buf,
if (ret)
return ret;
- mutex_lock(&dev->ev_mutex);
while (1) {
struct inotify_kernel_event *kevent;
@@ -481,6 +485,13 @@ static ssize_t inotify_read(struct file *file, char __user *buf,
}
break;
}
+ remove_kevent(dev, kevent);
+
+ /*
+ * Must perform the copy_to_user outside the mutex in order
+ * to avoid a lock order reversal with mmap_sem.
+ */
+ mutex_unlock(&dev->ev_mutex);
if (copy_to_user(buf, &kevent->event, event_size)) {
ret = -EFAULT;
@@ -498,7 +509,9 @@ static ssize_t inotify_read(struct file *file, char __user *buf,
count -= kevent->event.len;
}
- remove_kevent(dev, kevent);
+ free_kevent(kevent);
+
+ mutex_lock(&dev->ev_mutex);
}
mutex_unlock(&dev->ev_mutex);
diff --git a/fs/ramfs/file-nommu.c b/fs/ramfs/file-nommu.c
index 52312ec93ff..5145cb9125a 100644
--- a/fs/ramfs/file-nommu.c
+++ b/fs/ramfs/file-nommu.c
@@ -58,7 +58,7 @@ const struct inode_operations ramfs_file_inode_operations = {
* size 0 on the assumption that it's going to be used for an mmap of shared
* memory
*/
-static int ramfs_nommu_expand_for_mapping(struct inode *inode, size_t newsize)
+int ramfs_nommu_expand_for_mapping(struct inode *inode, size_t newsize)
{
struct pagevec lru_pvec;
unsigned long npages, xpages, loop, limit;
diff --git a/include/asm-mips/cevt-r4k.h b/include/asm-mips/cevt-r4k.h
new file mode 100644
index 00000000000..fa4328f9124
--- /dev/null
+++ b/include/asm-mips/cevt-r4k.h
@@ -0,0 +1,46 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2008 Kevin D. Kissell
+ */
+
+/*
+ * Definitions used for common event timer implementation
+ * for MIPS 4K-type processors and their MIPS MT variants.
+ * Avoids unsightly extern declarations in C files.
+ */
+#ifndef __ASM_CEVT_R4K_H
+#define __ASM_CEVT_R4K_H
+
+DECLARE_PER_CPU(struct clock_event_device, mips_clockevent_device);
+
+void mips_event_handler(struct clock_event_device *dev);
+int c0_compare_int_usable(void);
+void mips_set_clock_mode(enum clock_event_mode, struct clock_event_device *);
+irqreturn_t c0_compare_interrupt(int, void *);
+
+extern struct irqaction c0_compare_irqaction;
+extern int cp0_timer_irq_installed;
+
+/*
+ * Possibly handle a performance counter interrupt.
+ * Return true if the timer interrupt should not be checked
+ */
+
+static inline int handle_perf_irq(int r2)
+{
+ /*
+ * The performance counter overflow interrupt may be shared with the
+ * timer interrupt (cp0_perfcount_irq < 0). If it is and a
+ * performance counter has overflowed (perf_irq() == IRQ_HANDLED)
+ * and we can't reliably determine if a counter interrupt has also
+ * happened (!r2) then don't check for a timer interrupt.
+ */
+ return (cp0_perfcount_irq < 0) &&
+ perf_irq() == IRQ_HANDLED &&
+ !r2;
+}
+
+#endif /* __ASM_CEVT_R4K_H */
diff --git a/include/asm-mips/irqflags.h b/include/asm-mips/irqflags.h
index 881e8866501..701ec0ba8fa 100644
--- a/include/asm-mips/irqflags.h
+++ b/include/asm-mips/irqflags.h
@@ -38,8 +38,17 @@ __asm__(
" .set pop \n"
" .endm");
+extern void smtc_ipi_replay(void);
+
static inline void raw_local_irq_enable(void)
{
+#ifdef CONFIG_MIPS_MT_SMTC
+ /*
+ * SMTC kernel needs to do a software replay of queued
+ * IPIs, at the cost of call overhead on each local_irq_enable()
+ */
+ smtc_ipi_replay();
+#endif
__asm__ __volatile__(
"raw_local_irq_enable"
: /* no outputs */
@@ -47,6 +56,7 @@ static inline void raw_local_irq_enable(void)
: "memory");
}
+
/*
* For cli() we have to insert nops to make sure that the new value
* has actually arrived in the status register before the end of this
@@ -185,15 +195,14 @@ __asm__(
" .set pop \n"
" .endm \n");
-extern void smtc_ipi_replay(void);
static inline void raw_local_irq_restore(unsigned long flags)
{
unsigned long __tmp1;
-#ifdef CONFIG_MIPS_MT_SMTC_INSTANT_REPLAY
+#ifdef CONFIG_MIPS_MT_SMTC
/*
- * CONFIG_MIPS_MT_SMTC_INSTANT_REPLAY does prompt replay of deferred
+ * SMTC kernel needs to do a software replay of queued
* IPIs, at the cost of branch and call overhead on each
* local_irq_restore()
*/
@@ -208,6 +217,17 @@ static inline void raw_local_irq_restore(unsigned long flags)
: "memory");
}
+static inline void __raw_local_irq_restore(unsigned long flags)
+{
+ unsigned long __tmp1;
+
+ __asm__ __volatile__(
+ "raw_local_irq_restore\t%0"
+ : "=r" (__tmp1)
+ : "0" (flags)
+ : "memory");
+}
+
static inline int raw_irqs_disabled_flags(unsigned long flags)
{
#ifdef CONFIG_MIPS_MT_SMTC
diff --git a/include/asm-mips/mipsregs.h b/include/asm-mips/mipsregs.h
index a46f8e258e6..979866000da 100644
--- a/include/asm-mips/mipsregs.h
+++ b/include/asm-mips/mipsregs.h
@@ -1462,7 +1462,7 @@ set_c0_##name(unsigned int set) \
{ \
unsigned int res; \
unsigned int omt; \
- unsigned int flags; \
+ unsigned long flags; \
\
local_irq_save(flags); \
omt = __dmt(); \
@@ -1480,7 +1480,7 @@ clear_c0_##name(unsigned int clear) \
{ \
unsigned int res; \
unsigned int omt; \
- unsigned int flags; \
+ unsigned long flags; \
\
local_irq_save(flags); \
omt = __dmt(); \
@@ -1498,7 +1498,7 @@ change_c0_##name(unsigned int change, unsigned int new) \
{ \
unsigned int res; \
unsigned int omt; \
- unsigned int flags; \
+ unsigned long flags; \
\
local_irq_save(flags); \
\
diff --git a/include/asm-mips/smtc.h b/include/asm-mips/smtc.h
index 3639b28f80d..ea60bf08dcb 100644
--- a/include/asm-mips/smtc.h
+++ b/include/asm-mips/smtc.h
@@ -6,6 +6,7 @@
*/
#include <asm/mips_mt.h>
+#include <asm/smtc_ipi.h>
/*
* System-wide SMTC status information
@@ -38,14 +39,15 @@ struct mm_struct;
struct task_struct;
void smtc_get_new_mmu_context(struct mm_struct *mm, unsigned long cpu);
-
+void self_ipi(struct smtc_ipi *);
void smtc_flush_tlb_asid(unsigned long asid);
-extern int mipsmt_build_cpu_map(int startslot);
-extern void mipsmt_prepare_cpus(void);
+extern int smtc_build_cpu_map(int startslot);
+extern void smtc_prepare_cpus(int cpus);
extern void smtc_smp_finish(void);
extern void smtc_boot_secondary(int cpu, struct task_struct *t);
extern void smtc_cpus_done(void);
+
/*
* Sharing the TLB between multiple VPEs means that the
* "random" index selection function is not allowed to
diff --git a/include/asm-mips/sn/mapped_kernel.h b/include/asm-mips/sn/mapped_kernel.h
index c3dd5d0d525..721496a0bb9 100644
--- a/include/asm-mips/sn/mapped_kernel.h
+++ b/include/asm-mips/sn/mapped_kernel.h
@@ -5,6 +5,8 @@
#ifndef __ASM_SN_MAPPED_KERNEL_H
#define __ASM_SN_MAPPED_KERNEL_H
+#include <linux/mmzone.h>
+
/*
* Note on how mapped kernels work: the text and data section is
* compiled at cksseg segment (LOADADDR = 0xc001c000), and the
@@ -29,10 +31,8 @@
#define MAPPED_ADDR_RO_TO_PHYS(x) (x - REP_BASE)
#define MAPPED_ADDR_RW_TO_PHYS(x) (x - REP_BASE - 16777216)
-#define MAPPED_KERN_RO_PHYSBASE(n) \
- (PLAT_NODE_DATA(n)->kern_vars.kv_ro_baseaddr)
-#define MAPPED_KERN_RW_PHYSBASE(n) \
- (PLAT_NODE_DATA(n)->kern_vars.kv_rw_baseaddr)
+#define MAPPED_KERN_RO_PHYSBASE(n) (hub_data(n)->kern_vars.kv_ro_baseaddr)
+#define MAPPED_KERN_RW_PHYSBASE(n) (hub_data(n)->kern_vars.kv_rw_baseaddr)
#define MAPPED_KERN_RO_TO_PHYS(x) \
((unsigned long)MAPPED_ADDR_RO_TO_PHYS(x) | \
diff --git a/include/asm-mips/stackframe.h b/include/asm-mips/stackframe.h
index 051e1af0bb9..4c37c4e5f72 100644
--- a/include/asm-mips/stackframe.h
+++ b/include/asm-mips/stackframe.h
@@ -297,14 +297,31 @@
#ifdef CONFIG_MIPS_MT_SMTC
.set mips32r2
/*
- * This may not really be necessary if ints are already
- * inhibited here.
+ * We need to make sure the read-modify-write
+ * of Status below isn't perturbed by an interrupt
+ * or cross-TC access, so we need to do at least a DMT,
+ * protected by an interrupt-inhibit. But setting IXMT
+ * also creates a few-cycle window where an IPI could
+ * be queued and not be detected before potentially
+ * returning to a WAIT or user-mode loop. It must be
+ * replayed.
+ *
+ * We're in the middle of a context switch, and
+ * we can't dispatch it directly without trashing
+ * some registers, so we'll try to detect this unlikely
+ * case and program a software interrupt in the VPE,
+ * as would be done for a cross-VPE IPI. To accomodate
+ * the handling of that case, we're doing a DVPE instead
+ * of just a DMT here to protect against other threads.
+ * This is a lot of cruft to cover a tiny window.
+ * If you can find a better design, implement it!
+ *
*/
mfc0 v0, CP0_TCSTATUS
ori v0, TCSTATUS_IXMT
mtc0 v0, CP0_TCSTATUS
_ehb
- DMT 5 # dmt a1
+ DVPE 5 # dvpe a1
jal mips_ihb
#endif /* CONFIG_MIPS_MT_SMTC */
mfc0 a0, CP0_STATUS
@@ -325,17 +342,50 @@
*/
LONG_L v1, PT_TCSTATUS(sp)
_ehb
- mfc0 v0, CP0_TCSTATUS
+ mfc0 a0, CP0_TCSTATUS
andi v1, TCSTATUS_IXMT
- /* We know that TCStatua.IXMT should be set from above */
- xori v0, v0, TCSTATUS_IXMT
- or v0, v0, v1
- mtc0 v0, CP0_TCSTATUS
- _ehb
- andi a1, a1, VPECONTROL_TE
+ bnez v1, 0f
+
+/*
+ * We'd like to detect any IPIs queued in the tiny window
+ * above and request an software interrupt to service them
+ * when we ERET.
+ *
+ * Computing the offset into the IPIQ array of the executing
+ * TC's IPI queue in-line would be tedious. We use part of
+ * the TCContext register to hold 16 bits of offset that we
+ * can add in-line to find the queue head.
+ */
+ mfc0 v0, CP0_TCCONTEXT
+ la a2, IPIQ
+ srl v0, v0, 16
+ addu a2, a2, v0
+ LONG_L v0, 0(a2)
+ beqz v0, 0f
+/*
+ * If we have a queue, provoke dispatch within the VPE by setting C_SW1
+ */
+ mfc0 v0, CP0_CAUSE
+ ori v0, v0, C_SW1
+ mtc0 v0, CP0_CAUSE
+0:
+ /*
+ * This test should really never branch but
+ * let's be prudent here. Having atomized
+ * the shared register modifications, we can
+ * now EVPE, and must do so before interrupts
+ * are potentially re-enabled.
+ */
+ andi a1, a1, MVPCONTROL_EVP
beqz a1, 1f
- emt
+ evpe
1:
+ /* We know that TCStatua.IXMT should be set from above */
+ xori a0, a0, TCSTATUS_IXMT
+ or a0, a0, v1
+ mtc0 a0, CP0_TCSTATUS
+ _ehb
+
.set mips0
#endif /* CONFIG_MIPS_MT_SMTC */
LONG_L v1, PT_EPC(sp)
diff --git a/include/asm-x86/uaccess_64.h b/include/asm-x86/uaccess_64.h
index 515d4dce96b..45806d60bcb 100644
--- a/include/asm-x86/uaccess_64.h
+++ b/include/asm-x86/uaccess_64.h
@@ -7,6 +7,7 @@
#include <linux/compiler.h>
#include <linux/errno.h>
#include <linux/prefetch.h>
+#include <linux/lockdep.h>
#include <asm/page.h>
/*
diff --git a/include/linux/hrtimer.h b/include/linux/hrtimer.h
index 6d93dce61cb..2f245fe63bd 100644
--- a/include/linux/hrtimer.h
+++ b/include/linux/hrtimer.h
@@ -47,14 +47,22 @@ enum hrtimer_restart {
* HRTIMER_CB_IRQSAFE: Callback may run in hardirq context
* HRTIMER_CB_IRQSAFE_NO_RESTART: Callback may run in hardirq context and
* does not restart the timer
- * HRTIMER_CB_IRQSAFE_NO_SOFTIRQ: Callback must run in hardirq context
- * Special mode for tick emultation
+ * HRTIMER_CB_IRQSAFE_PERCPU: Callback must run in hardirq context
+ * Special mode for tick emulation and
+ * scheduler timer. Such timers are per
+ * cpu and not allowed to be migrated on
+ * cpu unplug.
+ * HRTIMER_CB_IRQSAFE_UNLOCKED: Callback should run in hardirq context
+ * with timer->base lock unlocked
+ * used for timers which call wakeup to
+ * avoid lock order problems with rq->lock
*/
enum hrtimer_cb_mode {
HRTIMER_CB_SOFTIRQ,
HRTIMER_CB_IRQSAFE,
HRTIMER_CB_IRQSAFE_NO_RESTART,
- HRTIMER_CB_IRQSAFE_NO_SOFTIRQ,
+ HRTIMER_CB_IRQSAFE_PERCPU,
+ HRTIMER_CB_IRQSAFE_UNLOCKED,
};
/*
@@ -67,9 +75,10 @@ enum hrtimer_cb_mode {
* 0x02 callback function running
* 0x04 callback pending (high resolution mode)
*
- * Special case:
+ * Special cases:
* 0x03 callback function running and enqueued
* (was requeued on another CPU)
+ * 0x09 timer was migrated on CPU hotunplug
* The "callback function running and enqueued" status is only possible on
* SMP. It happens for example when a posix timer expired and the callback
* queued a signal. Between dropping the lock which protects the posix timer
@@ -87,6 +96,7 @@ enum hrtimer_cb_mode {
#define HRTIMER_STATE_ENQUEUED 0x01
#define HRTIMER_STATE_CALLBACK 0x02
#define HRTIMER_STATE_PENDING 0x04
+#define HRTIMER_STATE_MIGRATE 0x08
/**
* struct hrtimer - the basic hrtimer structure
diff --git a/include/linux/ide.h b/include/linux/ide.h
index 1524829f73f..6514db8fd2e 100644
--- a/include/linux/ide.h
+++ b/include/linux/ide.h
@@ -366,7 +366,9 @@ enum {
/* Currently on a filemark */
IDE_AFLAG_FILEMARK = (1 << 25),
/* 0 = no tape is loaded, so we don't rewind after ejecting */
- IDE_AFLAG_MEDIUM_PRESENT = (1 << 26)
+ IDE_AFLAG_MEDIUM_PRESENT = (1 << 26),
+
+ IDE_AFLAG_NO_AUTOCLOSE = (1 << 27),
};
struct ide_drive_s {
diff --git a/include/linux/ramfs.h b/include/linux/ramfs.h
index b160fb18e8d..37aaf2b3986 100644
--- a/include/linux/ramfs.h
+++ b/include/linux/ramfs.h
@@ -6,6 +6,7 @@ extern int ramfs_get_sb(struct file_system_type *fs_type,
int flags, const char *dev_name, void *data, struct vfsmount *mnt);
#ifndef CONFIG_MMU
+extern int ramfs_nommu_expand_for_mapping(struct inode *inode, size_t newsize);
extern unsigned long ramfs_nommu_get_unmapped_area(struct file *file,
unsigned long addr,
unsigned long len,
diff --git a/include/linux/stacktrace.h b/include/linux/stacktrace.h
index 5da9794b2d7..b106fd8e0d5 100644
--- a/include/linux/stacktrace.h
+++ b/include/linux/stacktrace.h
@@ -1,6 +1,8 @@
#ifndef __LINUX_STACKTRACE_H
#define __LINUX_STACKTRACE_H
+struct task_struct;
+
#ifdef CONFIG_STACKTRACE
struct stack_trace {
unsigned int nr_entries, max_entries;
diff --git a/init/main.c b/init/main.c
index f6f7042331d..3820323c4c8 100644
--- a/init/main.c
+++ b/init/main.c
@@ -708,7 +708,7 @@ int do_one_initcall(initcall_t fn)
int result;
if (initcall_debug) {
- print_fn_descriptor_symbol("calling %s\n", fn);
+ printk("calling %pF\n", fn);
t0 = ktime_get();
}
@@ -718,8 +718,8 @@ int do_one_initcall(initcall_t fn)
t1 = ktime_get();
delta = ktime_sub(t1, t0);
- print_fn_descriptor_symbol("initcall %s", fn);
- printk(" returned %d after %Ld msecs\n", result,
+ printk("initcall %pF returned %d after %Ld msecs\n",
+ fn, result,
(unsigned long long) delta.tv64 >> 20);
}
@@ -737,8 +737,7 @@ int do_one_initcall(initcall_t fn)
local_irq_enable();
}
if (msgbuf[0]) {
- print_fn_descriptor_symbol(KERN_WARNING "initcall %s", fn);
- printk(" returned with %s\n", msgbuf);
+ printk("initcall %pF returned with %s\n", fn, msgbuf);
}
return result;
diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c
index b8e4dce80a7..cdec83e722f 100644
--- a/kernel/hrtimer.c
+++ b/kernel/hrtimer.c
@@ -672,13 +672,14 @@ static inline int hrtimer_enqueue_reprogram(struct hrtimer *timer,
*/
BUG_ON(timer->function(timer) != HRTIMER_NORESTART);
return 1;
- case HRTIMER_CB_IRQSAFE_NO_SOFTIRQ:
+ case HRTIMER_CB_IRQSAFE_PERCPU:
+ case HRTIMER_CB_IRQSAFE_UNLOCKED:
/*
* This is solely for the sched tick emulation with
* dynamic tick support to ensure that we do not
* restart the tick right on the edge and end up with
* the tick timer in the softirq ! The calling site
- * takes care of this.
+ * takes care of this. Also used for hrtimer sleeper !
*/
debug_hrtimer_deactivate(timer);
return 1;
@@ -1245,7 +1246,8 @@ static void __run_hrtimer(struct hrtimer *timer)
timer_stats_account_hrtimer(timer);
fn = timer->function;
- if (timer->cb_mode == HRTIMER_CB_IRQSAFE_NO_SOFTIRQ) {
+ if (timer->cb_mode == HRTIMER_CB_IRQSAFE_PERCPU ||
+ timer->cb_mode == HRTIMER_CB_IRQSAFE_UNLOCKED) {
/*
* Used for scheduler timers, avoid lock inversion with
* rq->lock and tasklist_lock.
@@ -1452,7 +1454,7 @@ void hrtimer_init_sleeper(struct hrtimer_sleeper *sl, struct task_struct *task)
sl->timer.function = hrtimer_wakeup;
sl->task = task;
#ifdef CONFIG_HIGH_RES_TIMERS
- sl->timer.cb_mode = HRTIMER_CB_IRQSAFE_NO_SOFTIRQ;
+ sl->timer.cb_mode = HRTIMER_CB_IRQSAFE_UNLOCKED;
#endif
}
@@ -1591,29 +1593,95 @@ static void __cpuinit init_hrtimers_cpu(int cpu)
#ifdef CONFIG_HOTPLUG_CPU
-static void migrate_hrtimer_list(struct hrtimer_clock_base *old_base,
- struct hrtimer_clock_base *new_base)
+static int migrate_hrtimer_list(struct hrtimer_clock_base *old_base,
+ struct hrtimer_clock_base *new_base, int dcpu)
{
struct hrtimer *timer;
struct rb_node *node;
+ int raise = 0;
while ((node = rb_first(&old_base->active))) {
timer = rb_entry(node, struct hrtimer, node);
BUG_ON(hrtimer_callback_running(timer));
debug_hrtimer_deactivate(timer);
- __remove_hrtimer(timer, old_base, HRTIMER_STATE_INACTIVE, 0);
+
+ /*
+ * Should not happen. Per CPU timers should be
+ * canceled _before_ the migration code is called
+ */
+ if (timer->cb_mode == HRTIMER_CB_IRQSAFE_PERCPU) {
+ __remove_hrtimer(timer, old_base,
+ HRTIMER_STATE_INACTIVE, 0);
+ WARN(1, "hrtimer (%p %p)active but cpu %d dead\n",
+ timer, timer->function, dcpu);
+ continue;
+ }
+
+ /*
+ * Mark it as STATE_MIGRATE not INACTIVE otherwise the
+ * timer could be seen as !active and just vanish away
+ * under us on another CPU
+ */
+ __remove_hrtimer(timer, old_base, HRTIMER_STATE_MIGRATE, 0);
timer->base = new_base;
/*
* Enqueue the timer. Allow reprogramming of the event device
*/
enqueue_hrtimer(timer, new_base, 1);
+
+#ifdef CONFIG_HIGH_RES_TIMERS
+ /*
+ * Happens with high res enabled when the timer was
+ * already expired and the callback mode is
+ * HRTIMER_CB_IRQSAFE_UNLOCKED (hrtimer_sleeper). The
+ * enqueue code does not move them to the soft irq
+ * pending list for performance/latency reasons, but
+ * in the migration state, we need to do that
+ * otherwise we end up with a stale timer.
+ */
+ if (timer->state == HRTIMER_STATE_MIGRATE) {
+ timer->state = HRTIMER_STATE_PENDING;
+ list_add_tail(&timer->cb_entry,
+ &new_base->cpu_base->cb_pending);
+ raise = 1;
+ }
+#endif
+ /* Clear the migration state bit */
+ timer->state &= ~HRTIMER_STATE_MIGRATE;
+ }
+ return raise;
+}
+
+#ifdef CONFIG_HIGH_RES_TIMERS
+static int migrate_hrtimer_pending(struct hrtimer_cpu_base *old_base,
+ struct hrtimer_cpu_base *new_base)
+{
+ struct hrtimer *timer;
+ int raise = 0;
+
+ while (!list_empty(&old_base->cb_pending)) {
+ timer = list_entry(old_base->cb_pending.next,
+ struct hrtimer, cb_entry);
+
+ __remove_hrtimer(timer, timer->base, HRTIMER_STATE_PENDING, 0);
+ timer->base = &new_base->clock_base[timer->base->index];
+ list_add_tail(&timer->cb_entry, &new_base->cb_pending);
+ raise = 1;
}
+ return raise;
+}
+#else
+static int migrate_hrtimer_pending(struct hrtimer_cpu_base *old_base,
+ struct hrtimer_cpu_base *new_base)
+{
+ return 0;
}
+#endif
static void migrate_hrtimers(int cpu)
{
struct hrtimer_cpu_base *old_base, *new_base;
- int i;
+ int i, raise = 0;
BUG_ON(cpu_online(cpu));
old_base = &per_cpu(hrtimer_bases, cpu);
@@ -1626,14 +1694,21 @@ static void migrate_hrtimers(int cpu)
spin_lock_nested(&old_base->lock, SINGLE_DEPTH_NESTING);
for (i = 0; i < HRTIMER_MAX_CLOCK_BASES; i++) {
- migrate_hrtimer_list(&old_base->clock_base[i],
- &new_base->clock_base[i]);
+ if (migrate_hrtimer_list(&old_base->clock_base[i],
+ &new_base->clock_base[i], cpu))
+ raise = 1;
}
+ if (migrate_hrtimer_pending(old_base, new_base))
+ raise = 1;
+
spin_unlock(&old_base->lock);
spin_unlock(&new_base->lock);
local_irq_enable();
put_cpu_var(hrtimer_bases);
+
+ if (raise)
+ hrtimer_raise_softirq();
}
#endif /* CONFIG_HOTPLUG_CPU */
diff --git a/kernel/kgdb.c b/kernel/kgdb.c
index 25d955dbb98..e4dcfb2272a 100644
--- a/kernel/kgdb.c
+++ b/kernel/kgdb.c
@@ -590,6 +590,7 @@ static void kgdb_wait(struct pt_regs *regs)
/* Signal the primary CPU that we are done: */
atomic_set(&cpu_in_kgdb[cpu], 0);
+ touch_softlockup_watchdog();
clocksource_touch_watchdog();
local_irq_restore(flags);
}
@@ -1432,6 +1433,7 @@ acquirelock:
atomic_read(&kgdb_cpu_doing_single_step) != cpu) {
atomic_set(&kgdb_active, -1);
+ touch_softlockup_watchdog();
clocksource_touch_watchdog();
local_irq_restore(flags);
@@ -1524,6 +1526,7 @@ acquirelock:
kgdb_restore:
/* Free kgdb_active */
atomic_set(&kgdb_active, -1);
+ touch_softlockup_watchdog();
clocksource_touch_watchdog();
local_irq_restore(flags);
diff --git a/kernel/posix-timers.c b/kernel/posix-timers.c
index e36d5798cbf..5131e547116 100644
--- a/kernel/posix-timers.c
+++ b/kernel/posix-timers.c
@@ -441,7 +441,7 @@ static struct k_itimer * alloc_posix_timer(void)
return tmr;
if (unlikely(!(tmr->sigq = sigqueue_alloc()))) {
kmem_cache_free(posix_timers_cache, tmr);
- tmr = NULL;
+ return NULL;
}
memset(&tmr->sigq->info, 0, sizeof(siginfo_t));
return tmr;
diff --git a/kernel/sched.c b/kernel/sched.c
index 13dd2db9fb2..ad1962dc0aa 100644
--- a/kernel/sched.c
+++ b/kernel/sched.c
@@ -201,7 +201,7 @@ void init_rt_bandwidth(struct rt_bandwidth *rt_b, u64 period, u64 runtime)
hrtimer_init(&rt_b->rt_period_timer,
CLOCK_MONOTONIC, HRTIMER_MODE_REL);
rt_b->rt_period_timer.function = sched_rt_period_timer;
- rt_b->rt_period_timer.cb_mode = HRTIMER_CB_IRQSAFE_NO_SOFTIRQ;
+ rt_b->rt_period_timer.cb_mode = HRTIMER_CB_IRQSAFE_UNLOCKED;
}
static void start_rt_bandwidth(struct rt_bandwidth *rt_b)
@@ -1119,7 +1119,7 @@ static void init_rq_hrtick(struct rq *rq)
hrtimer_init(&rq->hrtick_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
rq->hrtick_timer.function = hrtick;
- rq->hrtick_timer.cb_mode = HRTIMER_CB_IRQSAFE_NO_SOFTIRQ;
+ rq->hrtick_timer.cb_mode = HRTIMER_CB_IRQSAFE_PERCPU;
}
#else
static inline void hrtick_clear(struct rq *rq)
diff --git a/kernel/time/tick-broadcast.c b/kernel/time/tick-broadcast.c
index bd703454239..cb01cd8f919 100644
--- a/kernel/time/tick-broadcast.c
+++ b/kernel/time/tick-broadcast.c
@@ -235,7 +235,8 @@ static void tick_do_broadcast_on_off(void *why)
case CLOCK_EVT_NOTIFY_BROADCAST_FORCE:
if (!cpu_isset(cpu, tick_broadcast_mask)) {
cpu_set(cpu, tick_broadcast_mask);
- if (bc->mode == TICKDEV_MODE_PERIODIC)
+ if (tick_broadcast_device.mode ==
+ TICKDEV_MODE_PERIODIC)
clockevents_shutdown(dev);
}
if (*reason == CLOCK_EVT_NOTIFY_BROADCAST_FORCE)
@@ -245,7 +246,8 @@ static void tick_do_broadcast_on_off(void *why)
if (!tick_broadcast_force &&
cpu_isset(cpu, tick_broadcast_mask)) {
cpu_clear(cpu, tick_broadcast_mask);
- if (bc->mode == TICKDEV_MODE_PERIODIC)
+ if (tick_broadcast_device.mode ==
+ TICKDEV_MODE_PERIODIC)
tick_setup_periodic(dev, 0);
}
break;
diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c
index 39019b3f762..cb02324bdb8 100644
--- a/kernel/time/tick-sched.c
+++ b/kernel/time/tick-sched.c
@@ -625,7 +625,7 @@ void tick_setup_sched_timer(void)
*/
hrtimer_init(&ts->sched_timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS);
ts->sched_timer.function = tick_sched_timer;
- ts->sched_timer.cb_mode = HRTIMER_CB_IRQSAFE_NO_SOFTIRQ;
+ ts->sched_timer.cb_mode = HRTIMER_CB_IRQSAFE_PERCPU;
/* Get the next period (per cpu) */
ts->sched_timer.expires = tick_init_jiffy_update();
diff --git a/kernel/trace/trace_sysprof.c b/kernel/trace/trace_sysprof.c
index bb948e52ce2..db58fb66a13 100644
--- a/kernel/trace/trace_sysprof.c
+++ b/kernel/trace/trace_sysprof.c
@@ -202,7 +202,7 @@ static void start_stack_timer(int cpu)
hrtimer_init(hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
hrtimer->function = stack_trace_timer_fn;
- hrtimer->cb_mode = HRTIMER_CB_IRQSAFE_NO_SOFTIRQ;
+ hrtimer->cb_mode = HRTIMER_CB_IRQSAFE_PERCPU;
hrtimer_start(hrtimer, ns_to_ktime(sample_period), HRTIMER_MODE_REL);
}
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index e293c58bea5..27b8681139f 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -268,13 +268,14 @@ void prep_compound_page(struct page *page, unsigned long order)
{
int i;
int nr_pages = 1 << order;
+ struct page *p = page + 1;
set_compound_page_dtor(page, free_compound_page);
set_compound_order(page, order);
__SetPageHead(page);
- for (i = 1; i < nr_pages; i++) {
- struct page *p = page + i;
-
+ for (i = 1; i < nr_pages; i++, p++) {
+ if (unlikely((i & (MAX_ORDER_NR_PAGES - 1)) == 0))
+ p = pfn_to_page(page_to_pfn(page) + i);
__SetPageTail(p);
p->first_page = page;
}
@@ -284,6 +285,7 @@ static void destroy_compound_page(struct page *page, unsigned long order)
{
int i;
int nr_pages = 1 << order;
+ struct page *p = page + 1;
if (unlikely(compound_order(page) != order))
bad_page(page);
@@ -291,8 +293,9 @@ static void destroy_compound_page(struct page *page, unsigned long order)
if (unlikely(!PageHead(page)))
bad_page(page);
__ClearPageHead(page);
- for (i = 1; i < nr_pages; i++) {
- struct page *p = page + i;
+ for (i = 1; i < nr_pages; i++, p++) {
+ if (unlikely((i & (MAX_ORDER_NR_PAGES - 1)) == 0))
+ p = pfn_to_page(page_to_pfn(page) + i);
if (unlikely(!PageTail(p) |
(p->first_page != page)))
diff --git a/mm/page_isolation.c b/mm/page_isolation.c
index c69f84fe038..b70a7fec1ff 100644
--- a/mm/page_isolation.c
+++ b/mm/page_isolation.c
@@ -114,8 +114,10 @@ __test_page_isolated_in_pageblock(unsigned long pfn, unsigned long end_pfn)
int test_pages_isolated(unsigned long start_pfn, unsigned long end_pfn)
{
- unsigned long pfn;
+ unsigned long pfn, flags;
struct page *page;
+ struct zone *zone;
+ int ret;
pfn = start_pfn;
/*
@@ -131,7 +133,9 @@ int test_pages_isolated(unsigned long start_pfn, unsigned long end_pfn)
if (pfn < end_pfn)
return -EBUSY;
/* Check all pages are free or Marked as ISOLATED */
- if (__test_page_isolated_in_pageblock(start_pfn, end_pfn))
- return 0;
- return -EBUSY;
+ zone = page_zone(pfn_to_page(pfn));
+ spin_lock_irqsave(&zone->lock, flags);
+ ret = __test_page_isolated_in_pageblock(start_pfn, end_pfn);
+ spin_unlock_irqrestore(&zone->lock, flags);
+ return ret ? 0 : -EBUSY;
}
diff --git a/mm/slob.c b/mm/slob.c
index 4c82dd41f32..62b679dc660 100644
--- a/mm/slob.c
+++ b/mm/slob.c
@@ -515,7 +515,7 @@ size_t ksize(const void *block)
sp = (struct slob_page *)virt_to_page(block);
if (slob_page(sp))
- return ((slob_t *)block - 1)->units + SLOB_UNIT;
+ return (((slob_t *)block - 1)->units - 1) * SLOB_UNIT;
else
return sp->page.private;
}
diff --git a/mm/tiny-shmem.c b/mm/tiny-shmem.c
index d17cb6f6ab1..8d7a27a6335 100644
--- a/mm/tiny-shmem.c
+++ b/mm/tiny-shmem.c
@@ -80,6 +80,12 @@ struct file *shmem_file_setup(char *name, loff_t size, unsigned long flags)
inode->i_nlink = 0; /* It is unlinked */
init_file(file, shm_mnt, dentry, FMODE_WRITE | FMODE_READ,
&ramfs_file_operations);
+
+#ifndef CONFIG_MMU
+ error = ramfs_nommu_expand_for_mapping(inode, size);
+ if (error)
+ goto close_file;
+#endif
return file;
close_file:
diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c
index 01c83e2a4c1..28c71574a78 100644
--- a/net/ax25/af_ax25.c
+++ b/net/ax25/af_ax25.c
@@ -317,6 +317,9 @@ void ax25_destroy_socket(ax25_cb *ax25)
/* Queue the unaccepted socket for death */
sock_orphan(skb->sk);
+ /* 9A4GL: hack to release unaccepted sockets */
+ skb->sk->sk_state = TCP_LISTEN;
+
ax25_start_heartbeat(sax25);
sax25->state = AX25_STATE_0;
}
diff --git a/net/ax25/ax25_std_timer.c b/net/ax25/ax25_std_timer.c
index cdc7e751ef3..96e4b927325 100644
--- a/net/ax25/ax25_std_timer.c
+++ b/net/ax25/ax25_std_timer.c
@@ -39,9 +39,11 @@ void ax25_std_heartbeat_expiry(ax25_cb *ax25)
switch (ax25->state) {
case AX25_STATE_0:
- if (!sk ||
- sock_flag(sk, SOCK_DESTROY) ||
- sock_flag(sk, SOCK_DEAD)) {
+ /* Magic here: If we listen() and a new link dies before it
+ is accepted() it isn't 'dead' so doesn't get removed. */
+ if (!sk || sock_flag(sk, SOCK_DESTROY) ||
+ (sk->sk_state == TCP_LISTEN &&
+ sock_flag(sk, SOCK_DEAD))) {
if (sk) {
sock_hold(sk);
ax25_destroy_socket(ax25);
diff --git a/net/core/dev.c b/net/core/dev.c
index 7091040e32a..1408a083fe4 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -2949,6 +2949,12 @@ int netdev_set_master(struct net_device *slave, struct net_device *master)
return 0;
}
+static void dev_change_rx_flags(struct net_device *dev, int flags)
+{
+ if (dev->flags & IFF_UP && dev->change_rx_flags)
+ dev->change_rx_flags(dev, flags);
+}
+
static int __dev_set_promiscuity(struct net_device *dev, int inc)
{
unsigned short old_flags = dev->flags;
@@ -2986,8 +2992,7 @@ static int __dev_set_promiscuity(struct net_device *dev, int inc)
current->uid, current->gid,
audit_get_sessionid(current));
- if (dev->change_rx_flags)
- dev->change_rx_flags(dev, IFF_PROMISC);
+ dev_change_rx_flags(dev, IFF_PROMISC);
}
return 0;
}
@@ -3053,8 +3058,7 @@ int dev_set_allmulti(struct net_device *dev, int inc)
}
}
if (dev->flags ^ old_flags) {
- if (dev->change_rx_flags)
- dev->change_rx_flags(dev, IFF_ALLMULTI);
+ dev_change_rx_flags(dev, IFF_ALLMULTI);
dev_set_rx_mode(dev);
}
return 0;
@@ -3392,8 +3396,8 @@ int dev_change_flags(struct net_device *dev, unsigned flags)
* Load in the correct multicast list now the flags have changed.
*/
- if (dev->change_rx_flags && (old_flags ^ flags) & IFF_MULTICAST)
- dev->change_rx_flags(dev, IFF_MULTICAST);
+ if ((old_flags ^ flags) & IFF_MULTICAST)
+ dev_change_rx_flags(dev, IFF_MULTICAST);
dev_set_rx_mode(dev);
@@ -3867,14 +3871,11 @@ static int dev_new_index(struct net *net)
}
/* Delayed registration/unregisteration */
-static DEFINE_SPINLOCK(net_todo_list_lock);
static LIST_HEAD(net_todo_list);
static void net_set_todo(struct net_device *dev)
{
- spin_lock(&net_todo_list_lock);
list_add_tail(&dev->todo_list, &net_todo_list);
- spin_unlock(&net_todo_list_lock);
}
static void rollback_registered(struct net_device *dev)
@@ -4201,33 +4202,24 @@ static void netdev_wait_allrefs(struct net_device *dev)
* free_netdev(y1);
* free_netdev(y2);
*
- * We are invoked by rtnl_unlock() after it drops the semaphore.
+ * We are invoked by rtnl_unlock().
* This allows us to deal with problems:
* 1) We can delete sysfs objects which invoke hotplug
* without deadlocking with linkwatch via keventd.
* 2) Since we run with the RTNL semaphore not held, we can sleep
* safely in order to wait for the netdev refcnt to drop to zero.
+ *
+ * We must not return until all unregister events added during
+ * the interval the lock was held have been completed.
*/
-static DEFINE_MUTEX(net_todo_run_mutex);
void netdev_run_todo(void)
{
struct list_head list;
- /* Need to guard against multiple cpu's getting out of order. */
- mutex_lock(&net_todo_run_mutex);
-
- /* Not safe to do outside the semaphore. We must not return
- * until all unregister events invoked by the local processor
- * have been completed (either by this todo run, or one on
- * another cpu).
- */
- if (list_empty(&net_todo_list))
- goto out;
-
/* Snapshot list, allow later requests */
- spin_lock(&net_todo_list_lock);
list_replace_init(&net_todo_list, &list);
- spin_unlock(&net_todo_list_lock);
+
+ __rtnl_unlock();
while (!list_empty(&list)) {
struct net_device *dev
@@ -4259,9 +4251,6 @@ void netdev_run_todo(void)
/* Free network device */
kobject_put(&dev->dev.kobj);
}
-
-out:
- mutex_unlock(&net_todo_run_mutex);
}
static struct net_device_stats *internal_stats(struct net_device *dev)
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index 8862498fd4a..3630131fa1f 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -73,7 +73,7 @@ void __rtnl_unlock(void)
void rtnl_unlock(void)
{
- mutex_unlock(&rtnl_mutex);
+ /* This fellow will unlock it for us. */
netdev_run_todo();
}
diff --git a/net/ipv4/tcp_hybla.c b/net/ipv4/tcp_hybla.c
index bfcbd148a89..c209e054a63 100644
--- a/net/ipv4/tcp_hybla.c
+++ b/net/ipv4/tcp_hybla.c
@@ -150,7 +150,11 @@ static void hybla_cong_avoid(struct sock *sk, u32 ack, u32 in_flight)
ca->snd_cwnd_cents -= 128;
tp->snd_cwnd_cnt = 0;
}
-
+ /* check when cwnd has not been incremented for a while */
+ if (increment == 0 && odd == 0 && tp->snd_cwnd_cnt >= tp->snd_cwnd) {
+ tp->snd_cwnd++;
+ tp->snd_cwnd_cnt = 0;
+ }
/* clamp down slowstart cwnd to ssthresh value. */
if (is_slowstart)
tp->snd_cwnd = min(tp->snd_cwnd, tp->snd_ssthresh);
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index 63da39372d4..d77c0d29e23 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -4957,7 +4957,8 @@ int tcp_rcv_established(struct sock *sk, struct sk_buff *skb,
goto no_ack;
}
- __tcp_ack_snd_check(sk, 0);
+ if (!copied_early || tp->rcv_nxt != tp->rcv_wup)
+ __tcp_ack_snd_check(sk, 0);
no_ack:
#ifdef CONFIG_NET_DMA
if (copied_early)
diff --git a/net/netrom/af_netrom.c b/net/netrom/af_netrom.c
index 532e4faa29f..9f1ea4a27b3 100644
--- a/net/netrom/af_netrom.c
+++ b/net/netrom/af_netrom.c
@@ -525,6 +525,7 @@ static int nr_release(struct socket *sock)
if (sk == NULL) return 0;
sock_hold(sk);
+ sock_orphan(sk);
lock_sock(sk);
nr = nr_sk(sk);
@@ -548,7 +549,6 @@ static int nr_release(struct socket *sock)
sk->sk_state = TCP_CLOSE;
sk->sk_shutdown |= SEND_SHUTDOWN;
sk->sk_state_change(sk);
- sock_orphan(sk);
sock_set_flag(sk, SOCK_DESTROY);
break;
diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c
index 418cd7dbbc9..8e0de6a5e18 100644
--- a/scripts/mod/modpost.c
+++ b/scripts/mod/modpost.c
@@ -1986,11 +1986,13 @@ static void read_markers(const char *fname)
mod = find_module(modname);
if (!mod) {
- if (is_vmlinux(modname))
- have_vmlinux = 1;
mod = new_module(NOFAIL(strdup(modname)));
mod->skip = 1;
}
+ if (is_vmlinux(modname)) {
+ have_vmlinux = 1;
+ mod->skip = 0;
+ }
if (!mod->skip)
add_marker(mod, marker, fmt);
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
index d11a8154500..8551952ef32 100644
--- a/security/selinux/ss/services.c
+++ b/security/selinux/ss/services.c
@@ -2737,6 +2737,7 @@ int security_netlbl_secattr_to_sid(struct netlbl_lsm_secattr *secattr,
if (ctx == NULL)
goto netlbl_secattr_to_sid_return;
+ context_init(&ctx_new);
ctx_new.user = ctx->user;
ctx_new.role = ctx->role;
ctx_new.type = ctx->type;
@@ -2745,13 +2746,9 @@ int security_netlbl_secattr_to_sid(struct netlbl_lsm_secattr *secattr,
if (ebitmap_netlbl_import(&ctx_new.range.level[0].cat,
secattr->attr.mls.cat) != 0)
goto netlbl_secattr_to_sid_return;
- ctx_new.range.level[1].cat.highbit =
- ctx_new.range.level[0].cat.highbit;
- ctx_new.range.level[1].cat.node =
- ctx_new.range.level[0].cat.node;
- } else {
- ebitmap_init(&ctx_new.range.level[0].cat);
- ebitmap_init(&ctx_new.range.level[1].cat);
+ memcpy(&ctx_new.range.level[1].cat,
+ &ctx_new.range.level[0].cat,
+ sizeof(ctx_new.range.level[0].cat));
}
if (mls_context_isvalid(&policydb, &ctx_new) != 1)
goto netlbl_secattr_to_sid_return_cleanup;
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c
index ad994fcab72..f3da621f25c 100644
--- a/sound/pci/hda/patch_sigmatel.c
+++ b/sound/pci/hda/patch_sigmatel.c
@@ -1683,8 +1683,8 @@ static struct snd_pci_quirk stac927x_cfg_tbl[] = {
/* Dell 3 stack systems with verb table in BIOS */
SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01f3, "Dell Inspiron 1420", STAC_DELL_BIOS),
SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0227, "Dell Vostro 1400 ", STAC_DELL_BIOS),
- SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x022f, "Dell ", STAC_DELL_BIOS),
SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x022e, "Dell ", STAC_DELL_BIOS),
+ SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x022f, "Dell Inspiron 1525", STAC_DELL_3ST),
SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0242, "Dell ", STAC_DELL_BIOS),
SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0243, "Dell ", STAC_DELL_BIOS),
SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x02ff, "Dell ", STAC_DELL_BIOS),
diff --git a/sound/ppc/awacs.c b/sound/ppc/awacs.c
index 566a6d0daf4..106c48225bb 100644
--- a/sound/ppc/awacs.c
+++ b/sound/ppc/awacs.c
@@ -621,6 +621,13 @@ static struct snd_kcontrol_new snd_pmac_screamer_mixers_imac[] __initdata = {
AWACS_SWITCH("CD Capture Switch", 0, SHIFT_MUX_CD, 0),
};
+static struct snd_kcontrol_new snd_pmac_screamer_mixers_g4agp[] __initdata = {
+ AWACS_VOLUME("Line out Playback Volume", 2, 6, 1),
+ AWACS_VOLUME("Master Playback Volume", 5, 6, 1),
+ AWACS_SWITCH("CD Capture Switch", 0, SHIFT_MUX_CD, 0),
+ AWACS_SWITCH("Line Capture Switch", 0, SHIFT_MUX_MIC, 0),
+};
+
static struct snd_kcontrol_new snd_pmac_awacs_mixers_pmac7500[] __initdata = {
AWACS_VOLUME("Line out Playback Volume", 2, 6, 1),
AWACS_SWITCH("CD Capture Switch", 0, SHIFT_MUX_CD, 0),
@@ -688,7 +695,10 @@ static struct snd_kcontrol_new snd_pmac_awacs_speaker_vol[] __initdata = {
static struct snd_kcontrol_new snd_pmac_awacs_speaker_sw __initdata =
AWACS_SWITCH("PC Speaker Playback Switch", 1, SHIFT_SPKMUTE, 1);
-static struct snd_kcontrol_new snd_pmac_awacs_speaker_sw_imac __initdata =
+static struct snd_kcontrol_new snd_pmac_awacs_speaker_sw_imac1 __initdata =
+AWACS_SWITCH("PC Speaker Playback Switch", 1, SHIFT_PAROUT1, 1);
+
+static struct snd_kcontrol_new snd_pmac_awacs_speaker_sw_imac2 __initdata =
AWACS_SWITCH("PC Speaker Playback Switch", 1, SHIFT_PAROUT1, 0);
@@ -765,11 +775,12 @@ static void snd_pmac_awacs_resume(struct snd_pmac *chip)
#define IS_PM7500 (machine_is_compatible("AAPL,7500"))
#define IS_BEIGE (machine_is_compatible("AAPL,Gossamer"))
-#define IS_IMAC (machine_is_compatible("PowerMac2,1") \
- || machine_is_compatible("PowerMac2,2") \
+#define IS_IMAC1 (machine_is_compatible("PowerMac2,1"))
+#define IS_IMAC2 (machine_is_compatible("PowerMac2,2") \
|| machine_is_compatible("PowerMac4,1"))
+#define IS_G4AGP (machine_is_compatible("PowerMac3,1"))
-static int imac;
+static int imac1, imac2;
#ifdef PMAC_SUPPORT_AUTOMUTE
/*
@@ -815,13 +826,18 @@ static void snd_pmac_awacs_update_automute(struct snd_pmac *chip, int do_notify)
{
int reg = chip->awacs_reg[1]
| (MASK_HDMUTE | MASK_SPKMUTE);
- if (imac) {
+ if (imac1) {
+ reg &= ~MASK_SPKMUTE;
+ reg |= MASK_PAROUT1;
+ } else if (imac2) {
reg &= ~MASK_SPKMUTE;
reg &= ~MASK_PAROUT1;
}
if (snd_pmac_awacs_detect_headphone(chip))
reg &= ~MASK_HDMUTE;
- else if (imac)
+ else if (imac1)
+ reg &= ~MASK_PAROUT1;
+ else if (imac2)
reg |= MASK_PAROUT1;
else
reg &= ~MASK_SPKMUTE;
@@ -850,9 +866,13 @@ snd_pmac_awacs_init(struct snd_pmac *chip)
{
int pm7500 = IS_PM7500;
int beige = IS_BEIGE;
+ int g4agp = IS_G4AGP;
+ int imac;
int err, vol;
- imac = IS_IMAC;
+ imac1 = IS_IMAC1;
+ imac2 = IS_IMAC2;
+ imac = imac1 || imac2;
/* looks like MASK_GAINLINE triggers something, so we set here
* as start-up
*/
@@ -939,7 +959,7 @@ snd_pmac_awacs_init(struct snd_pmac *chip)
snd_pmac_awacs_mixers);
if (err < 0)
return err;
- if (beige)
+ if (beige || g4agp)
;
else if (chip->model == PMAC_SCREAMER)
err = build_mixers(chip, ARRAY_SIZE(snd_pmac_screamer_mixers2),
@@ -961,13 +981,17 @@ snd_pmac_awacs_init(struct snd_pmac *chip)
err = build_mixers(chip,
ARRAY_SIZE(snd_pmac_screamer_mixers_imac),
snd_pmac_screamer_mixers_imac);
+ else if (g4agp)
+ err = build_mixers(chip,
+ ARRAY_SIZE(snd_pmac_screamer_mixers_g4agp),
+ snd_pmac_screamer_mixers_g4agp);
else
err = build_mixers(chip,
ARRAY_SIZE(snd_pmac_awacs_mixers_pmac),
snd_pmac_awacs_mixers_pmac);
if (err < 0)
return err;
- chip->master_sw_ctl = snd_ctl_new1((pm7500 || imac)
+ chip->master_sw_ctl = snd_ctl_new1((pm7500 || imac || g4agp)
? &snd_pmac_awacs_master_sw_imac
: &snd_pmac_awacs_master_sw, chip);
err = snd_ctl_add(chip->card, chip->master_sw_ctl);
@@ -1004,15 +1028,17 @@ snd_pmac_awacs_init(struct snd_pmac *chip)
snd_pmac_awacs_speaker_vol);
if (err < 0)
return err;
- chip->speaker_sw_ctl = snd_ctl_new1(imac
- ? &snd_pmac_awacs_speaker_sw_imac
+ chip->speaker_sw_ctl = snd_ctl_new1(imac1
+ ? &snd_pmac_awacs_speaker_sw_imac1
+ : imac2
+ ? &snd_pmac_awacs_speaker_sw_imac2
: &snd_pmac_awacs_speaker_sw, chip);
err = snd_ctl_add(chip->card, chip->speaker_sw_ctl);
if (err < 0)
return err;
}
- if (beige)
+ if (beige || g4agp)
err = build_mixers(chip,
ARRAY_SIZE(snd_pmac_screamer_mic_boost_beige),
snd_pmac_screamer_mic_boost_beige);
diff --git a/sound/soc/codecs/cs4270.c b/sound/soc/codecs/cs4270.c
index d68650de39b..0bbd94501d7 100644
--- a/sound/soc/codecs/cs4270.c
+++ b/sound/soc/codecs/cs4270.c
@@ -681,7 +681,7 @@ static int cs4270_probe(struct platform_device *pdev)
ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
if (ret < 0) {
printk(KERN_ERR "cs4270: failed to create PCMs\n");
- return ret;
+ goto error_free_codec;
}
#ifdef USE_I2C
@@ -690,8 +690,7 @@ static int cs4270_probe(struct platform_device *pdev)
ret = i2c_add_driver(&cs4270_i2c_driver);
if (ret) {
printk(KERN_ERR "cs4270: failed to attach driver");
- snd_soc_free_pcms(socdev);
- return ret;
+ goto error_free_pcms;
}
/* Did we find a CS4270 on the I2C bus? */
@@ -713,10 +712,23 @@ static int cs4270_probe(struct platform_device *pdev)
ret = snd_soc_register_card(socdev);
if (ret < 0) {
printk(KERN_ERR "cs4270: failed to register card\n");
- snd_soc_free_pcms(socdev);
- return ret;
+ goto error_del_driver;
}
+ return 0;
+
+error_del_driver:
+#ifdef USE_I2C
+ i2c_del_driver(&cs4270_i2c_driver);
+
+error_free_pcms:
+#endif
+ snd_soc_free_pcms(socdev);
+
+error_free_codec:
+ kfree(socdev->codec);
+ socdev->codec = NULL;
+
return ret;
}
@@ -727,8 +739,7 @@ static int cs4270_remove(struct platform_device *pdev)
snd_soc_free_pcms(socdev);
#ifdef USE_I2C
- if (socdev->codec->control_data)
- i2c_del_driver(&cs4270_i2c_driver);
+ i2c_del_driver(&cs4270_i2c_driver);
#endif
kfree(socdev->codec);
diff --git a/sound/soc/codecs/wm8753.c b/sound/soc/codecs/wm8753.c
index 5761164fe16..e873414840c 100644
--- a/sound/soc/codecs/wm8753.c
+++ b/sound/soc/codecs/wm8753.c
@@ -583,7 +583,7 @@ static const struct snd_soc_dapm_route audio_map[] = {
/* out 4 */
{"Out4 Mux", "VREF", "VREF"},
- {"Out4 Mux", "Capture ST", "Capture ST Mixer"},
+ {"Out4 Mux", "Capture ST", "Playback Mixer"},
{"Out4 Mux", "LOUT2", "LOUT2"},
{"Out 4", NULL, "Out4 Mux"},
{"OUT4", NULL, "Out 4"},
@@ -607,7 +607,7 @@ static const struct snd_soc_dapm_route audio_map[] = {
/* Capture Right Mux */
{"Capture Right Mux", "PGA", "Right Capture Volume"},
{"Capture Right Mux", "Line or RXP-RXN", "Line Right Mux"},
- {"Capture Right Mux", "Sidetone", "Capture ST Mixer"},
+ {"Capture Right Mux", "Sidetone", "Playback Mixer"},
/* Mono Capture mixer-mux */
{"Capture Right Mixer", "Stereo", "Capture Right Mux"},